something works

pull/477/head
Tim Pechersky 2021-12-08 18:45:53 +00:00
rodzic a191f50ce0
commit 5fb524bf0e
18 zmienionych plików z 774 dodań i 372 usunięć

Wyświetl plik

@ -50,7 +50,9 @@
"showdown-highlight": "^2.1.8",
"slick-carousel": "^1.8.1",
"styled-components": "^5.3.3",
"unique-names-generator": "^4.6.0",
"uuid": "^8.3.2",
"web3-eth-abi": "^1.6.1",
"web3-utils": "^1.6.0"
},
"devDependencies": {

Wyświetl plik

@ -157,12 +157,15 @@ const Analytics = () => {
// }, [nodesReady, windowSize]);
const updateCallback = ({ name }) => {
const dashboard = { ...dashboardCache.data.data.resource_data };
dashboard.name = name;
updateDashboard.mutate({ id: dashboardCache.data.data.id, dashboard });
};
const addReportClicked = () => {
console.log("click");
updateDashboard.mutate({
id: dashboardCache.data.data.id,
dashboard: {
dashboard_id: dashboardCache.data.data.id,
name: name,
subscription_cache:
dashboardCache.data.data.resource_data.subscription_setting,
},
});
};
if (
@ -221,7 +224,7 @@ const Analytics = () => {
onClick={() =>
overlay.toggleDrawer({
type: DRAWER_TYPES.NEW_DASHBOARD_ITEM,
props: { dashboardId: dashboardId },
props: dashboardCache.data.data.resource_data,
})
}
mr={8}
@ -235,40 +238,59 @@ const Analytics = () => {
</Stack>
<Flex w="100%" direction="row" flexWrap="wrap-reverse" id="container">
{Object.keys(dashboardLinksCache.data.data).map((key) => {
const s3PresignedURLs = dashboardLinksCache.data.data[key];
const name = subscriptionsCache.data.subscriptions.find(
(subscription) => subscription.id === key
).label;
return (
<Flex
key={v4()}
flexBasis={plotMinW}
flexGrow={1}
minW={plotMinW}
minH="320px"
direction="column"
boxShadow="md"
m={["1px", 2]}
>
<Text
w="100%"
py={2}
bgColor="gray.50"
fontWeight="600"
textAlign="center"
<>
{Object.keys(dashboardLinksCache.data.data).map((key) => {
const s3PresignedURLs = dashboardLinksCache.data.data[key];
const name = subscriptionsCache.data.subscriptions.find(
(subscription) => subscription.id === key
).label;
return (
<Flex
key={v4()}
flexBasis={plotMinW}
flexGrow={1}
minW={plotMinW}
minH="320px"
direction="column"
boxShadow="md"
m={["1px", 2]}
>
{name}
</Text>
<SubscriptionReport
timeRange={timeRange}
url={s3PresignedURLs[timeRange]}
id={dashboardId}
refetchLinks={dashboardLinksCache.refetch}
/>
<Text
w="100%"
py={2}
bgColor="gray.50"
fontWeight="600"
textAlign="center"
>
{name}
</Text>
<SubscriptionReport
timeRange={timeRange}
url={s3PresignedURLs[timeRange]}
id={dashboardId}
refetchLinks={dashboardLinksCache.refetch}
/>
</Flex>
);
})}
{dashboardCache.data.data.resource_data.subscription_settings[0] ===
undefined && (
<Flex pt="220px" w="100%" placeContent="center">
<Button
size="lg"
colorScheme="orange"
onClick={() =>
overlay.toggleDrawer({
type: DRAWER_TYPES.NEW_DASHBOARD_ITEM,
props: dashboardCache.data.data.resource_data,
})
}
>
Populate dashboard
</Button>
</Flex>
);
})}
)}
</>
</Flex>
</Flex>
</Scrollable>

Wyświetl plik

@ -755,7 +755,6 @@ const Homepage = () => {
<Flex direction="row" flexWrap="wrap" placeContent="center">
<RouteButton
placeSelf="center"
isExternal
href={`https://github.com/bugout-dev/moonstream`}
size="md"
variant="outline"
@ -767,7 +766,6 @@ const Homepage = () => {
</RouteButton>
<RouteButton
placeSelf="center"
isExternal
href={"https://discord.gg/K56VNUQGvA"}
size="md"
variant="outline"
@ -780,7 +778,6 @@ const Homepage = () => {
</Flex>
<Button
placeSelf="center"
isExternal
w={["100%", "100%", "fit-content", null]}
maxW={["250px", null, "fit-content"]}
onClick={() => toggleModal({ type: MODAL_TYPES.SIGNUP })}

Wyświetl plik

@ -39,12 +39,20 @@ const AddNewIconButton = (props) => {
borderRadius={0}
>
<MenuGroup>
<MenuItem
onClick={
() => console.log("creating new empty dasbhoard...")
// modal.toggleDrawer({ type: DRAWER_TYPES.NEW_DASHBOARD })
}
>
New Empty dashboard...
</MenuItem>
<MenuItem
onClick={() =>
modal.toggleDrawer({ type: DRAWER_TYPES.NEW_DASHBOARD })
}
>
New Dashboard...
New ABI defined dashboard...
</MenuItem>
<MenuItem
onClick={() =>

Wyświetl plik

@ -13,8 +13,6 @@ import {
import UIContext from "../core/providers/UIProvider/context";
const AutoCompleter = ({
form,
setForm,
pickerItems,
initialSelectedItem,
itemToString,

Wyświetl plik

@ -0,0 +1,46 @@
import React from "react";
import { Stack, Checkbox } from "@chakra-ui/react";
import { v4 } from "uuid";
const CheckboxGroupped = ({
groupName,
list,
isItemChecked,
setItemChecked,
isAllChecked,
setAll,
isIndeterminate,
}) => {
return (
<Stack>
<Checkbox
isChecked={isAllChecked}
isIndeterminate={isIndeterminate}
onChange={() => setAll(!isAllChecked)}
>
{groupName}
</Checkbox>
<Stack pl={6} spacing={0}>
{list.map((listItem, idx) => {
return (
<Stack
px={2}
key={v4()}
direction="row"
bgColor={idx % 2 == 0 ? "gray.50" : "gray.100"}
>
<Checkbox
isChecked={isItemChecked(listItem)}
onChange={(e) => setItemChecked(listItem, e.target.checked)}
>
{listItem.name}
</Checkbox>
</Stack>
);
})}
</Stack>
</Stack>
);
};
export default CheckboxGroupped;

Wyświetl plik

@ -0,0 +1,41 @@
import React, { useContext } from "react";
import { chakra, ButtonGroup, Button } from "@chakra-ui/react";
import OverlayContext from "../core/providers/OverlayProvider/context";
import {
DRAWER_TYPES,
MODAL_TYPES,
} from "../core/providers/OverlayProvider/constants";
import { useDashboard } from "../core/hooks";
const NewDashboard = () => {
const overlay = useContext(OverlayContext);
const { createDashboard } = useDashboard();
return (
<>
<ButtonGroup>
<Button
onClick={() => {
overlay.toggleModal({ type: MODAL_TYPES.OFF });
sessionStorage.removeItem("new_dashboard");
createDashboard.mutate();
}}
>
Empty dashboard
</Button>
<Button
onClick={() => {
overlay.toggleModal({ type: MODAL_TYPES.OFF });
overlay.toggleDrawer({ type: DRAWER_TYPES.NEW_DASHBOARD });
}}
>
Automatically define from ABI
</Button>
</ButtonGroup>
</>
);
};
const ChakraNewDashboard = chakra(NewDashboard);
export default ChakraNewDashboard;

Wyświetl plik

@ -2,51 +2,21 @@ import React, { useContext, useEffect, useState } from "react";
import {
chakra,
FormLabel,
Input,
Stack,
InputGroup,
Box,
Button,
Table,
Th,
Td,
Tr,
Thead,
Tbody,
Center,
Checkbox,
CloseButton,
InputRightAddon,
Badge,
InputLeftAddon,
Heading,
Spinner,
Text,
ButtonGroup,
} from "@chakra-ui/react";
import { CheckCircleIcon } from "@chakra-ui/icons";
import { useSubscriptions } from "../core/hooks";
import Downshift from "downshift";
import color from "color";
import OverlayContext from "../core/providers/OverlayProvider/context";
import { MODAL_TYPES } from "../core/providers/OverlayProvider/constants";
import UIContext from "../core/providers/UIProvider/context";
import SuggestABI from "./SuggestABI";
import { v4 } from "uuid";
import AutoCompleter from "./AutoCompleter";
import { CHART_METRICS } from "../core/constants";
import CheckboxGrouped from "./CheckboxGroupped";
const NewDashboardChart = (props) => {
const [metric, setMetric] = useState();
const ui = useContext(UIContext);
const NewDashboardChart = ({ drawerState, setDrawerState }) => {
const overlay = useContext(OverlayContext);
const [newChartForm, setNewChartForm] = useState([
{
subscription: undefined, //subscription
type: undefined, // generic | events | transactions
name: undefined, // transactions_in | transactions_out | value_in | value_out | balance | abi.events.some() | abi.methods.some()
},
]);
const [pickerItems, setPickerItems] = useState();
@ -61,8 +31,7 @@ const NewDashboardChart = (props) => {
const { subscriptionsCache } = useSubscriptions();
if (subscriptionsCache.isLoading) return <Spinner />;
console.log("newChartForm:", newChartForm);
if (subscriptionsCache.isLoading || !pickerItems) return <Spinner />;
const filterFn = (item, inputValue) =>
(item.subscription_type_id === "ethereum_blockchain" ||
@ -74,35 +43,72 @@ const NewDashboardChart = (props) => {
return (
<>
<Stack spacing="24px">
{newChartForm.map((subscibedItem, idx) => {
const onAbiSuggestionSelect = ({ type, value }) => {
setNewChartForm((currentValue) => {
const newValue = [...currentValue];
newValue[idx].type = type;
newValue[idx].name = value;
return newValue;
{drawerState.map((subscribedItem, idx) => {
const setGeneric = (callbackFn) => {
setDrawerState((currentDrawerState) => {
const newDrawerState = [...currentDrawerState];
newDrawerState[idx].generic = callbackFn(
newDrawerState[idx].generic
);
return newDrawerState;
});
};
const onMetricSelect = ({ type, value }) => {
setNewChartForm((currentValue) => {
const newValue = [...currentValue];
newValue[idx].type = type;
newValue[idx].name = "";
return newValue;
});
const setDrawerAtHead = (arg) => {
let newDrawerState = [...drawerState];
if (typeof arg === "function") {
console.log("setDrawerAtHead is fn - running");
newDrawerState[idx] = arg(newDrawerState[idx]);
} else {
newDrawerState[idx] = [...arg];
}
console.log("setDrawerAtHead newstate:", newDrawerState);
setDrawerState(newDrawerState);
};
console.log("subscribed item mapped is", subscribedItem);
return (
<Stack key={v4()}>
<Stack key={`new-chart-component-${idx}`}>
<FormLabel pb={0}>Subscription:</FormLabel>
<AutoCompleter
itemIdx={idx}
pickerItems={pickerItems}
initialSelectedItem={newChartForm[idx].subscription}
initialSelectedItem={drawerState[idx].subscription}
itemToString={(item) => item.label}
onSelect={(selectedItem) =>
setNewChartForm((currentValue) => {
setDrawerState((currentValue) => {
const newValue = [...currentValue];
newValue[idx].subscription = selectedItem;
newValue[idx] = {
subscription: selectedItem,
generic: {
transactions_in: {
value: "transactions_in",
name: "transactions in",
checked: false,
},
transactions_out: {
value: "transactions_out",
name: "transactions out",
checked: false,
},
value_in: {
value: "value_in",
name: "value in",
checked: false,
},
value_out: {
value: "value_out",
name: "value out",
checked: false,
},
balance: {
value: "balance",
name: "balance",
checked: false,
},
},
events: {},
methods: {},
};
return newValue;
})
}
@ -166,64 +172,47 @@ const NewDashboardChart = (props) => {
);
}}
/>
{subscibedItem?.subscription?.id && (
{subscribedItem?.subscription?.id && (
<Stack spacing={1}>
<FormLabel pb={0}>Metric:</FormLabel>
<ButtonGroup spacing={0} display="flex">
<Button
flexGrow="1"
flexBasis="50px"
m={0}
colorScheme="orange"
bgColor="orange.600"
_active={{ bgColor: "orange.900" }}
borderRightRadius={0}
onClick={() =>
onMetricSelect({ type: CHART_METRICS.GENERIC })
}
isActive={
newChartForm[idx].type === CHART_METRICS.GENERIC
}
>
Balance
</Button>
<Button
m={0}
flexGrow="1"
flexBasis="50px"
borderRadius={0}
colorScheme="orange"
bgColor="orange.600"
_active={{ bgColor: "orange.900" }}
onClick={() =>
onMetricSelect({ type: CHART_METRICS.EVENTS })
}
isActive={newChartForm[idx].type === CHART_METRICS.EVENTS}
>
Events
</Button>
<Button
flexGrow="1"
flexBasis="50px"
m={0}
borderLeftRadius={0}
colorScheme="orange"
bgColor="orange.600"
_active={{ bgColor: "orange.900" }}
onClick={() =>
onMetricSelect({ type: CHART_METRICS.FUNCTIONS })
}
isActive={
newChartForm[idx].type === CHART_METRICS.FUNCTIONS
}
>
Functions
</Button>
</ButtonGroup>
<CheckboxGrouped
groupName="generic metrics:"
list={Object.values(drawerState[idx].generic)}
isItemChecked={(item) => item.checked}
isAllChecked={Object.values(drawerState[idx].generic).every(
(item) => !!item.checked
)}
isIndeterminate={
Object.values(drawerState[idx].generic).some(
(item) => item.checked
) &&
!Object.values(drawerState[idx].generic).every(
(item) => item.checked
)
}
setItemChecked={(item, isChecked) =>
setGeneric((currentState) => {
const newState = { ...currentState };
newState[item.value].checked = isChecked;
return newState;
})
}
setAll={(isChecked) =>
setGeneric((currentState) => {
const newState = { ...currentState };
Object.keys(newState).forEach(
(key) => (newState[key].checked = isChecked)
);
return newState;
})
}
/>
<SuggestABI
stateContainer={newChartForm[idx]}
subscriptionId={subscibedItem.subscription.id}
onSelect={onAbiSuggestionSelect}
subscriptionId={subscribedItem.subscription.id}
drawerState={drawerState[idx]}
setState={setDrawerAtHead}
idx={idx}
/>
</Stack>
)}

Wyświetl plik

@ -28,10 +28,7 @@ import { MdSettings, MdDashboard, MdTimeline } from "react-icons/md";
import { WHITE_LOGO_W_TEXT_URL, ALL_NAV_PATHES } from "../core/constants";
import { v4 } from "uuid";
import useDashboard from "../core/hooks/useDashboard";
import {
DRAWER_TYPES,
MODAL_TYPES,
} from "../core/providers/OverlayProvider/constants";
import { MODAL_TYPES } from "../core/providers/OverlayProvider/constants";
import OverlayContext from "../core/providers/OverlayProvider/context";
const Sidebar = () => {
@ -147,7 +144,9 @@ const Sidebar = () => {
colorScheme="orange"
size="sm"
onClick={() =>
overlay.toggleDrawer({ type: DRAWER_TYPES.NEW_DASHBOARD })
overlay.toggleModal({
type: MODAL_TYPES.NEW_DASHBOARD_FLOW,
})
}
// w="100%"
// borderRadius={0}

Wyświetl plik

@ -1,50 +1,10 @@
import React, { useContext, useEffect, useState } from "react";
import {
chakra,
FormLabel,
Input,
Stack,
InputGroup,
Box,
Button,
Table,
Th,
Td,
Tr,
Thead,
Tbody,
Center,
Checkbox,
CloseButton,
InputRightAddon,
Badge,
InputLeftAddon,
Spinner,
Heading,
Menu,
MenuButton,
MenuList,
MenuItem,
MenuGroup,
MenuDivider,
ButtonGroup,
Text,
} from "@chakra-ui/react";
import { CheckCircleIcon } from "@chakra-ui/icons";
import React, { useEffect } from "react";
import { chakra, Stack, Spinner } from "@chakra-ui/react";
import { useSubscription, usePresignedURL } from "../core/hooks";
import Downshift from "downshift";
import color from "color";
import OverlayContext from "../core/providers/OverlayProvider/context";
import { MODAL_TYPES } from "../core/providers/OverlayProvider/constants";
import UIContext from "../core/providers/UIProvider/context";
import { v4 } from "uuid";
import AutoCompleter from "./AutoCompleter";
import { CHART_METRICS } from "../core/constants";
const SuggestABI = ({ subscriptionId, onSelect, stateContainer }) => {
const ui = useContext(UIContext);
const overlay = useContext(OverlayContext);
import CheckboxGroupped from "./CheckboxGroupped";
import massageAbi from "../core/utils/massageAbi";
const SuggestABI = ({ subscriptionId, drawerState, setState }) => {
const { subscriptionLinksCache } = useSubscription({
id: subscriptionId,
});
@ -57,146 +17,107 @@ const SuggestABI = ({ subscriptionId, onSelect, stateContainer }) => {
requestNewURLCallback: subscriptionLinksCache.refetch,
});
const [pickerItems, setPickerItems] = React.useState();
const setFunctions = (arg) => {
setState((currentHeadState) => {
const newHeadState = { ...currentHeadState };
if (typeof arg === "function") {
newHeadState.methods = arg(newHeadState.methods);
} else {
newHeadState.methods = { ...arg };
}
return newHeadState;
});
};
// useEffect(() => {
// newDashboardForm.subscriptions.forEach((element, idx) => {
// const subscription =
// subscriptions.subscriptionsCache.data?.subscriptions.find(
// (subscription_item) =>
// element.subscription_id === subscription_item.id
// );
// if (
// element.subscription_id &&
// subscription &&
// newDashboardForm.subscriptions[idx].abi !== subscription?.abi
// ) {
// const newestDashboardForm = { ...newDashboardForm };
// newestDashboardForm.subscriptions[idx].abi = subscription.abi;
// setNewDashboardForm(newestDashboardForm);
// }
// });
// }, [
// subscriptions.subscriptionsCache.data,
// newDashboardForm,
// setNewDashboardForm,
// ]);
const setEvents = (arg) => {
setState((currentHeadState) => {
const newHeadState = { ...currentHeadState };
if (typeof arg === "function") {
newHeadState.events = arg(newHeadState.events);
} else {
newHeadState.events = { ...arg };
}
return newHeadState;
});
};
useEffect(() => {
if (!isLoading) {
const massaged = data?.map((item) => {
return { value: item.name ?? item.type, ...item };
if (data && !isLoading) {
const { fnsObj, eventsObj } = massageAbi(data);
setState((currentHeadState) => {
const newHeadState = { ...currentHeadState };
newHeadState.methods = fnsObj;
newHeadState.events = eventsObj;
return newHeadState;
});
setPickerItems(
massaged?.filter((item) => item.type === stateContainer.type)
);
}
}, [data, isLoading, stateContainer]);
//eslint-disable-next-line
}, [data, isLoading]);
const filterFn = (item, inputValue) =>
!inputValue || item.value.toUpperCase().includes(inputValue.toUpperCase());
if (isLoading || !data) return <Spinner />;
if (isLoading || !pickerItems) return <Spinner />;
console.log("pickerItems", pickerItems);
console.debug("list", drawerState);
return (
<>
<Stack spacing={1}>
{stateContainer.type === CHART_METRICS.EVENTS && (
<Stack>
<FormLabel pb={0}>Event:</FormLabel>
<AutoCompleter
itemIdx={""}
pickerItems={pickerItems.filter((item) => item.type === "event")}
initialSelectedItem={stateContainer}
itemToString={(item) => item.name}
onSelect={onSelect}
getLeftAddonColor={(item) => item?.color ?? "inherit"}
getLabelColor={() => undefined}
placeholder="Select metric"
getDefaultValue={(item) => (item?.value ? item.value : "")}
filterFn={filterFn}
empyListCTA={() => (
<Text alignSelf="center">No Events found {`>_<`}</Text>
)}
dropdownItem={(item) => {
console.log("dropdownItem,", item);
return (
<>
<chakra.span whiteSpace="nowrap">{item.value}</chakra.span>
<Badge isTruncated size="sm" placeSelf="self-end">
{item.type}
</Badge>
</>
);
}}
/>
</Stack>
)}
{stateContainer.type === CHART_METRICS.FUNCTIONS && (
<Stack>
<FormLabel pb={0}>Function:</FormLabel>
<AutoCompleter
itemIdx={""}
pickerItems={pickerItems.filter(
(item) => item.type === "function"
)}
initialSelectedItem={stateContainer}
itemToString={(item) => item.name}
onSelect={onSelect}
getLeftAddonColor={(item) => item?.color ?? "inherit"}
getLabelColor={() => undefined}
placeholder="Select metric"
getDefaultValue={(item) => (item?.value ? item.value : "")}
filterFn={filterFn}
empyListCTA={() => (
<Text alignSelf="center">No Functions found {`>_<`}</Text>
)}
dropdownItem={(item) => {
console.log("dropdownItem,", item);
return (
<>
<chakra.span whiteSpace="nowrap">{item.value}</chakra.span>
<Badge isTruncated size="sm" placeSelf="self-end">
{item.type}
</Badge>
</>
);
}}
/>
</Stack>
)}
{stateContainer.type === CHART_METRICS.GENERIC && (
<Stack>
<FormLabel pb={0}>Balance:</FormLabel>
<AutoCompleter
itemIdx={""}
pickerItems={pickerItems}
initialSelectedItem={stateContainer}
itemToString={(item) => item.name}
onSelect={onSelect}
getLeftAddonColor={(item) => item?.color ?? "inherit"}
getLabelColor={() => undefined}
placeholder="Select metric"
getDefaultValue={(item) => (item?.value ? item.value : "")}
filterFn={filterFn}
empyListCTA={() => ""}
dropdownItem={(item) => {
console.log("dropdownItem,", item);
return (
<>
<chakra.span whiteSpace="nowrap">{item.value}</chakra.span>
<Badge isTruncated size="sm" placeSelf="self-end">
{item.type}
</Badge>
</>
);
}}
/>
</Stack>
)}
<Stack>
<CheckboxGroupped
groupName="events"
list={Object.values(drawerState.events)}
isItemChecked={(item) => item.checked}
isAllChecked={Object.values(drawerState.events).every(
(item) => !!item.checked
)}
isIndeterminate={
Object.values(drawerState.events).some((item) => item.checked) &&
!Object.values(drawerState.events).every((item) => item.checked)
}
setItemChecked={(item, isChecked) =>
setEvents((currentState) => {
const newState = { ...currentState };
newState[item.signature].checked = isChecked;
return newState;
})
}
setAll={(isChecked) =>
setEvents((currentEvents) => {
console.log("setAll", isChecked);
const newEvents = { ...currentEvents };
Object.keys(newEvents).forEach(
(key) => (newEvents[key].checked = isChecked)
);
return newEvents;
})
}
/>
<CheckboxGroupped
groupName="functions"
list={Object.values(drawerState.methods)}
isItemChecked={(item) => item.checked}
isAllChecked={Object.values(drawerState.methods).every(
(item) => !!item.checked
)}
isIndeterminate={
Object.values(drawerState.methods).some((item) => item.checked) &&
!Object.values(drawerState.methods).every((item) => item.checked)
}
setItemChecked={(item, isChecked) =>
setFunctions((currentState) => {
const newState = { ...currentState };
newState[item.signature].checked = isChecked;
return newState;
})
}
setAll={(isChecked) =>
setFunctions((currentFunctions) => {
const newFunctions = { ...currentFunctions };
Object.keys(newFunctions).forEach(
(key) => (newFunctions[key].checked = isChecked)
);
return newFunctions;
})
}
/>
</Stack>
</>
);
@ -205,3 +126,101 @@ const SuggestABI = ({ subscriptionId, onSelect, stateContainer }) => {
const ChakraSuggestABI = chakra(SuggestABI);
export default ChakraSuggestABI;
{
/* <Stack pl={6} spacing={0}>
{getEvents(pickerItems).map((event, idx) => {
const pickedEvents = getEvents(pickedItems);
return (
<Stack
px={2}
key={v4()}
direction="row"
bgColor={idx % 2 == 0 ? "gray.50" : "gray.100"}
>
<Checkbox
isChecked={pickedEvents.some(
(pickedEvent) => pickedEvent.value === event.value
)}
onChange={() => {
const changedIndex = pickedItems.findIndex(
(pickedItem) =>
event.type === "event" &&
pickedItem.value === event.value
);
if (changedIndex === -1) {
setPickedItems((currentlyPicked) => {
const newPicked = [...currentlyPicked];
newPicked.push(event);
return newPicked;
});
} else {
setPickedItems((currentlyPicked) => {
const newPicked = [...currentlyPicked];
newPicked.splice(changedIndex, 1);
return newPicked;
});
}
}}
>
{event.value}
</Checkbox>
<Spacer />
{event.stateMutability === "view" && (
<Badge variant="solid" colorScheme="orange" size="sm">
View
</Badge>
)}
{event.stateMutability === "payable" && (
<Badge variant="solid" colorScheme="blue" size="sm">
Payable
</Badge>
)}
{event.stateMutability === "nonpayable" && (
<Badge variant="solid" colorScheme="green" size="sm">
Non-Payable
</Badge>
)}
</Stack>
);
})}
{pickerItems
?.filter((unfilteredItem) => unfilteredItem.type === "function")
.map((item, idx) => {
return (
<Stack
px={2}
key={v4()}
direction="row"
bgColor={idx % 2 == 0 ? "gray.50" : "gray.100"}
>
<Checkbox
isChecked={pickedItems.some(
(pickedItem) =>
item.type === "function" &&
pickedItem.value === item.value
)}
>
{item.value}
</Checkbox>
<Spacer />
{item.stateMutability === "view" && (
<Badge variant="solid" colorScheme="orange" size="sm">
View
</Badge>
)}
{item.stateMutability === "payable" && (
<Badge variant="solid" colorScheme="blue" size="sm">
Payable
</Badge>
)}
{item.stateMutability === "nonpayable" && (
<Badge variant="solid" colorScheme="green" size="sm">
Non-Payable
</Badge>
)}
</Stack>
);
})}
</Stack> */
}

Wyświetl plik

@ -34,7 +34,7 @@ const TxABI = (props) => {
</Tr>
</Thead>
<Tbody>
{abi.functions.concat(abi.events).map((el) => (
{abi.methods.concat(abi.events).map((el) => (
<Tr key={el.hex_signature}>
<Td>{el.hex_signature}</Td>
<Td>

Wyświetl plik

@ -4,6 +4,12 @@ import { queryCacheProps } from "./hookCommon";
import { DashboardService } from "../services";
import { useContext } from "react";
import UserContext from "../providers/UserProvider/context";
import {
uniqueNamesGenerator,
adjectives,
colors,
starWars,
} from "unique-names-generator";
const useDashboard = (dashboardId) => {
const toast = useToast();
@ -22,9 +28,23 @@ const useDashboard = (dashboardId) => {
}
);
const createDashboard = useMutation(DashboardService.createDashboard, {
const _createDashboard = async (dashboard) => {
const _dashboard = { ...dashboard };
console.log("dashboard", _dashboard);
if (!_dashboard.name || _dashboard.name === "")
_dashboard.name = uniqueNamesGenerator({
dictionaries: [colors, adjectives, starWars],
});
if (!_dashboard.subscription_settings) {
_dashboard.subscription_settings = [];
}
DashboardService.createDashboard(_dashboard);
};
const createDashboard = useMutation(_createDashboard, {
onSuccess: () => {
toast("Created new dashboard", "success");
sessionStorage.removeItem("new_dashboard");
},
onError: (error) => {
toast(error.error, "error", "Fail");

Wyświetl plik

@ -11,11 +11,12 @@ const useToast = () => {
const userTitle = title ?? message?.response?.statusText ?? type;
const userMessage =
message?.response?.data?.detail ?? typeof message === "string"
message?.response?.data?.detail ??
(typeof message === "string"
? message
: userTitle === type
? ""
: type;
: type);
if (mixpanel.get_distinct_id() && type === "error") {
mixpanel.track(`${MIXPANEL_EVENTS.TOAST_ERROR_DISPLAYED}`, {

Wyświetl plik

@ -8,6 +8,7 @@ export const MODAL_TYPES = {
HUBSPOT: 6,
NEW_SUBSCRIPTON: 7,
UPLOAD_ABI: 8,
NEW_DASHBOARD_FLOW: 9,
};
export const DRAWER_TYPES = {

Wyświetl plik

@ -36,7 +36,11 @@ import UserContext from "../UserProvider/context";
import UIContext from "../UIProvider/context";
import useDashboard from "../../hooks/useDashboard";
import SignUp from "../../../components/SignUp";
import NewDashboardElement from "../../../components/NewDashboardChart";
import NewDashboardChart from "../../../components/NewDashboardChart";
import { useRouter } from "../../hooks";
const DasbhboardFlowSelector = React.lazy(() =>
import("../../../components/DasbhboardFlowSelector")
);
const ForgotPassword = React.lazy(() =>
import("../../../components/ForgotPassword")
);
@ -52,7 +56,9 @@ const NewSubscription = React.lazy(() =>
const UploadABI = React.lazy(() => import("../../../components/UploadABI"));
const OverlayProvider = ({ children }) => {
const { createDashboard } = useDashboard();
const { createDashboard, updateDashboard } = useDashboard();
const { params } = useRouter();
const { dashboardId } = params;
const ui = useContext(UIContext);
const { user } = useContext(UserContext);
const [modal, toggleModal] = useState({
@ -67,6 +73,30 @@ const OverlayProvider = ({ children }) => {
const drawerDisclosure = useDisclosure();
const modalDisclosure = useDisclosure();
const alertDisclosure = useDisclosure();
const [drawerState, setDrawerState] = useState([
{
subscription: undefined,
generic: {
transactions_in: {
value: "transactions_in",
name: "transactions in",
checked: false,
},
transactions_out: {
value: "transactions_out",
name: "transactions out",
checked: false,
},
value_in: { value: "value_in", name: "value in", checked: false },
value_out: { value: "value_out", name: "value out", checked: false },
balance: { value: "balance", name: "balance", checked: false },
},
events: {},
methods: {},
},
]);
console.log("drawerState", drawerState);
useLayoutEffect(() => {
if (modal.type === MODAL_TYPES.OFF && modalDisclosure.isOpen) {
@ -127,42 +157,177 @@ const OverlayProvider = ({ children }) => {
const submitNewDashboard = () => {
const dashboardState = JSON.parse(sessionStorage.getItem("new_dashboard"));
createDashboard.mutate({
name: dashboardState.name,
subscriptions: dashboardState.subscriptions.map((pickedSubscription) => {
const retval = {
subscription_id: pickedSubscription.subscription_id,
generic: [],
all_methods: !!pickedSubscription.isMethods,
all_events: !!pickedSubscription.isEvents,
};
if (dashboardState) {
//creating ABI defined dashboard
createDashboard.mutate({
name: dashboardState.name,
subscription_settings: dashboardState.subscription_settings.map(
(pickedSubscription) => {
const retval = {
subscription_id: pickedSubscription.subscription_id,
generic: [],
all_methods: !!pickedSubscription.isMethods,
all_events: !!pickedSubscription.isEvents,
};
pickedSubscription.generic.transactions.in &&
retval.generic.push({ name: "transactions_in" });
pickedSubscription.generic.transactions.out &&
retval.generic.push({ name: "transactions_out" });
pickedSubscription.generic.value.in &&
retval.generic.push({ name: "value_in" });
pickedSubscription.generic.value.out &&
retval.generic.push({ name: "value_out" });
pickedSubscription.generic.balance &&
retval.generic.push({ name: "balance" });
retval["methods"] = [];
retval["events"] = [];
pickedSubscription.generic.transactions.in &&
retval.generic.push({ name: "transactions_in" });
pickedSubscription.generic.transactions.out &&
retval.generic.push({ name: "transactions_out" });
pickedSubscription.generic.value.in &&
retval.generic.push({ name: "value_in" });
pickedSubscription.generic.value.out &&
retval.generic.push({ name: "value_out" });
pickedSubscription.generic.balance &&
retval.generic.push({ name: "balance" });
retval["methods"] = [];
retval["events"] = [];
return retval;
}),
});
return retval;
}
),
});
} else {
//creating empty dashboard
createDashboard.mutate();
}
};
const submitNewDashboardItem = () => {
console.log("submit new dashboard item");
console.log("submit new dashboard item", drawerState);
const newDashboard = { ...drawer.props };
// console.log("newDashboard,", newDashboard);
drawerState.forEach((drawerSubscriptionSetting) => {
let index = newDashboard.subscription_settings.findIndex(
(subscriptionSetting) =>
subscriptionSetting.subscription_id ===
drawerSubscriptionSetting.subscription.id
);
if (index === -1) {
newDashboard.subscription_settings.push({
subscription_id: drawerSubscriptionSetting.subscription.id,
events: [],
generic: [],
methods: [],
});
index = newDashboard.subscription_settings.length - 1;
}
let temp = [];
Object.values(drawerSubscriptionSetting.generic).forEach(
(drawerGenericItem) => {
if (
drawerGenericItem.checked &&
!newDashboard.subscription_settings[index].generic.some(
(metric) => metric === drawerGenericItem.value
)
) {
temp.push({ name: drawerGenericItem.value });
}
}
);
console.log("temp,", temp);
newDashboard.subscription_settings[index].generic = [
...newDashboard.subscription_settings[index].generic,
...temp,
];
temp = [];
Object.values(drawerSubscriptionSetting.events).forEach(
(drawerEventItem) => {
const isSome = newDashboard.subscription_settings[index].events.some(
(metric) => metric === drawerEventItem.name
);
console.log("debug Submit drawerEventItem", drawerEventItem);
console.log(
"debug Submit isChecked:",
drawerEventItem.checked,
"isSome:",
isSome,
"current list:",
newDashboard.subscription_settings[index].events
);
if (drawerEventItem.checked && !isSome) {
console.log("pushing:", drawerEventItem);
temp.push({ name: drawerEventItem.name });
}
}
);
console.log("temp,", temp);
newDashboard.subscription_settings[index].events = [
...newDashboard.subscription_settings[index].events,
...temp,
];
temp = [];
Object.values(drawerSubscriptionSetting.methods).forEach(
(drawerFunctionItem) => {
const isSome = newDashboard.subscription_settings[index].methods.some(
(metric) => metric === drawerFunctionItem.name
);
console.log("debug Submit drawerEventItem", drawerFunctionItem);
console.log(
"debug Submit isChecked:",
drawerFunctionItem.checked,
"isSome:",
isSome,
"current list:",
newDashboard.subscription_settings[index].methods
);
if (drawerFunctionItem.checked && !isSome) {
console.log("pushing:", drawerFunctionItem);
temp.push({ name: drawerFunctionItem.name });
}
}
);
console.log("temp,", temp);
newDashboard.subscription_settings[index].methods = [
...newDashboard.subscription_settings[index].methods,
...temp,
];
});
updateDashboard.mutate({ dashboard: newDashboard, id: dashboardId });
};
useEffect(() => {
if (createDashboard.isSuccess) {
finishNewDashboard();
}
}, [createDashboard.isSuccess]);
useEffect(() => {
if (
createDashboard.isSuccess &&
drawer.type === DRAWER_TYPES.NEW_DASHBOARD_ITEM
) {
setDrawerState([
{
subscription: undefined,
generic: {
transactions_in: {
value: "transactions_in",
name: "transactions in",
checked: false,
},
transactions_out: {
value: "transactions_out",
name: "transactions out",
checked: false,
},
value_in: { value: "value_in", name: "value in", checked: false },
value_out: {
value: "value_out",
name: "value out",
checked: false,
},
balance: { value: "balance", name: "balance", checked: false },
},
events: {},
methods: {},
},
]);
toggleDrawer({ type: DRAWER_TYPES.OFF, props: undefined });
}
}, [createDashboard.isSuccess, drawer.type]);
return (
<OverlayContext.Provider
value={{ modal, toggleModal, drawer, toggleDrawer, toggleAlert }}
@ -216,6 +381,8 @@ const OverlayProvider = ({ children }) => {
{modal.type === MODAL_TYPES.LOGIN && "Login now"}
{modal.type === MODAL_TYPES.SIGNUP && "Create an account"}
{modal.type === MODAL_TYPES.UPLOAD_ABI && "Assign ABI"}
{modal.type === MODAL_TYPES.NEW_DASHBOARD_FLOW &&
"How would you like to define new dashboard?"}
</ModalHeader>
<Divider />
<ModalCloseButton />
@ -250,6 +417,9 @@ const OverlayProvider = ({ children }) => {
{modal.type === MODAL_TYPES.UPLOAD_ABI && (
<UploadABI {...modal.props} />
)}
{modal.type === MODAL_TYPES.NEW_DASHBOARD_FLOW && (
<DasbhboardFlowSelector {...modal.props} />
)}
</Suspense>
</ModalBody>
</ModalContent>
@ -281,9 +451,11 @@ const OverlayProvider = ({ children }) => {
)}
{drawer.type === DRAWER_TYPES.NEW_DASHBOARD_ITEM && (
<Suspense fallback={<Spinner />}>
<NewDashboardElement
<NewDashboardChart
firstField={firstField}
props={drawer.props}
drawerState={drawerState}
setDrawerState={setDrawerState}
/>
</Suspense>
)}
@ -298,9 +470,43 @@ const OverlayProvider = ({ children }) => {
toggleAlert(() => finishNewDashboard());
}
if (drawer.type === DRAWER_TYPES.NEW_DASHBOARD_ITEM) {
toggleAlert(() =>
toggleDrawer({ type: DRAWER_TYPES.OFF, props: undefined })
);
toggleAlert(() => {
toggleDrawer({ type: DRAWER_TYPES.OFF, props: undefined });
setDrawerState([
{
subscription: undefined,
generic: {
transactions_in: {
value: "transactions_in",
name: "transactions in",
checked: false,
},
transactions_out: {
value: "transactions_out",
name: "transactions out",
checked: false,
},
value_in: {
value: "value_in",
name: "value in",
checked: false,
},
value_out: {
value: "value_out",
name: "value out",
checked: false,
},
balance: {
value: "balance",
name: "balance",
checked: false,
},
},
events: {},
functions: {},
},
]);
});
}
}}
>

Wyświetl plik

@ -11,14 +11,11 @@ export const createDashboard = (data) => {
};
export const updateDashboard = ({ dashboard, id }) => {
console.log("das", dashboard);
return http({
method: "PUT",
url: `${API_URL}/dashboards/${id}`,
data: {
...dashboard,
dashboard_id: id,
subscriptions: dashboard.dashboard_subscriptions,
},
data: dashboard,
});
};

Wyświetl plik

@ -0,0 +1,56 @@
const massageAbi = (abi) => {
const coder = require("web3-eth-abi");
const getSignature = (item) => {
console.log("getting key for:", item);
if (item.type === `function`) {
const retval = coder.encodeFunctionSignature(item);
console.log("retval:", retval);
return retval;
} else if (item.type === `event`) {
const retval = coder.encodeEventSignature(item);
console.log("retval:", retval);
return retval;
}
console.error("item passed to getKay was neither fn neither event!");
};
const filtered = abi.filter(
(item) => item.type === `event` || item.type === `function`
);
const signed = filtered.map((item) => {
item.signature = getSignature(item);
return item;
});
const events = [];
const functions = [];
signed.forEach((item) => {
if (item.type === "event") {
events.push(item);
}
if (item.type === "function") {
functions.push(item);
}
});
const keyEv = {};
const keyFn = {};
console.log("functions:", functions);
console.log("events:", events);
const eventsObj =
events.length > 0
? events.reduce(
(acc, curr) => ((acc[curr.signature] = { ...curr }), keyEv)
)
: [];
const fnsObj =
functions.length > 0
? functions.reduce(
(acc, curr) => ((acc[curr.signature] = { ...curr }), keyFn)
)
: 0;
return { fnsObj, eventsObj };
};
export default massageAbi;