kopia lustrzana https://github.com/bugout-dev/moonstream
better newSubscripton, pass args from drawer to modal
rodzic
35ed79a7ac
commit
e3cde8a7cb
|
@ -40,7 +40,8 @@
|
||||||
"react-xarrows": "^2.0.2",
|
"react-xarrows": "^2.0.2",
|
||||||
"showdown": "^1.9.1",
|
"showdown": "^1.9.1",
|
||||||
"showdown-highlight": "^2.1.8",
|
"showdown-highlight": "^2.1.8",
|
||||||
"uuid": "^8.3.2"
|
"uuid": "^8.3.2",
|
||||||
|
"web3": "^1.6.0"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@babel/core": "^7.14.3",
|
"@babel/core": "^7.14.3",
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import React, { useEffect } from "react";
|
import React, { useContext, useEffect } from "react";
|
||||||
import {
|
import {
|
||||||
chakra,
|
chakra,
|
||||||
FormLabel,
|
FormLabel,
|
||||||
|
@ -24,8 +24,13 @@ import { CheckCircleIcon } from "@chakra-ui/icons";
|
||||||
import { useStorage, useSubscriptions } from "../core/hooks";
|
import { useStorage, useSubscriptions } from "../core/hooks";
|
||||||
import Downshift from "downshift";
|
import Downshift from "downshift";
|
||||||
import color from "color";
|
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";
|
||||||
|
|
||||||
const NewDashboard = (props) => {
|
const NewDashboard = (props) => {
|
||||||
|
const ui = useContext(UIContext);
|
||||||
|
const overlay = useContext(OverlayContext);
|
||||||
const [newDashboardForm, setNewDashboardForm] = useStorage(
|
const [newDashboardForm, setNewDashboardForm] = useStorage(
|
||||||
sessionStorage,
|
sessionStorage,
|
||||||
"new_dashboard",
|
"new_dashboard",
|
||||||
|
@ -36,6 +41,7 @@ const NewDashboard = (props) => {
|
||||||
label: "",
|
label: "",
|
||||||
id: null,
|
id: null,
|
||||||
isMethods: false,
|
isMethods: false,
|
||||||
|
isEvents: false,
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
}
|
}
|
||||||
|
@ -104,7 +110,8 @@ const NewDashboard = (props) => {
|
||||||
<Tr>
|
<Tr>
|
||||||
<Th>Address</Th>
|
<Th>Address</Th>
|
||||||
<Th w="90px">ABI State</Th>
|
<Th w="90px">ABI State</Th>
|
||||||
<Th w="90px">Track ABI</Th>
|
<Th w="90px">Methods</Th>
|
||||||
|
<Th w="90px">Events</Th>
|
||||||
<Th w="60px"></Th>
|
<Th w="60px"></Th>
|
||||||
</Tr>
|
</Tr>
|
||||||
</Thead>
|
</Thead>
|
||||||
|
@ -155,7 +162,9 @@ const NewDashboard = (props) => {
|
||||||
<InputLeftAddon
|
<InputLeftAddon
|
||||||
isTruncated
|
isTruncated
|
||||||
maxW="60px"
|
maxW="60px"
|
||||||
fontSize="sm"
|
fontSize={
|
||||||
|
ui.isMobileView ? "xs" : "sm"
|
||||||
|
}
|
||||||
bgColor={
|
bgColor={
|
||||||
subscibedItem?.color ?? "gray.100"
|
subscibedItem?.color ?? "gray.100"
|
||||||
}
|
}
|
||||||
|
@ -178,9 +187,9 @@ const NewDashboard = (props) => {
|
||||||
placeholder="Subscription to use in dashboard"
|
placeholder="Subscription to use in dashboard"
|
||||||
isTruncated
|
isTruncated
|
||||||
fontSize="sm"
|
fontSize="sm"
|
||||||
defaultValue={
|
// defaultValue={
|
||||||
subscibedItem?.label ?? "yoyoy"
|
// subscibedItem?.label ?? "yoyoy"
|
||||||
}
|
// }
|
||||||
{...getInputProps({
|
{...getInputProps({
|
||||||
defaultValue:
|
defaultValue:
|
||||||
subscibedItem?.label ?? "iha",
|
subscibedItem?.label ?? "iha",
|
||||||
|
@ -233,9 +242,20 @@ const NewDashboard = (props) => {
|
||||||
colorScheme="orange"
|
colorScheme="orange"
|
||||||
variant="outline"
|
variant="outline"
|
||||||
size="sm"
|
size="sm"
|
||||||
|
fontSize="sm"
|
||||||
|
w="100%"
|
||||||
|
m={0}
|
||||||
|
isTruncated
|
||||||
|
onClick={() => {
|
||||||
|
overlay.toggleModal(
|
||||||
|
MODAL_TYPES.NEW_SUBSCRIPTON
|
||||||
|
);
|
||||||
|
overlay.setModalProps({
|
||||||
|
initialValue: inputValue,
|
||||||
|
});
|
||||||
|
}}
|
||||||
>
|
>
|
||||||
Set new subscription to:{" "}
|
Subscribe to: {inputValue}{" "}
|
||||||
{inputValue}{" "}
|
|
||||||
</Button>
|
</Button>
|
||||||
)}
|
)}
|
||||||
{pickerItems &&
|
{pickerItems &&
|
||||||
|
@ -306,6 +326,23 @@ const NewDashboard = (props) => {
|
||||||
</Stack>
|
</Stack>
|
||||||
);
|
);
|
||||||
})}
|
})}
|
||||||
|
{inputValue === "" && (
|
||||||
|
<Button
|
||||||
|
colorScheme="orange"
|
||||||
|
variant="outline"
|
||||||
|
w="100%"
|
||||||
|
m={0}
|
||||||
|
size="sm"
|
||||||
|
onClick={() =>
|
||||||
|
overlay.toggleModal(
|
||||||
|
MODAL_TYPES.NEW_SUBSCRIPTON
|
||||||
|
)
|
||||||
|
}
|
||||||
|
>
|
||||||
|
New subscription
|
||||||
|
{inputValue}{" "}
|
||||||
|
</Button>
|
||||||
|
)}
|
||||||
</Stack>
|
</Stack>
|
||||||
) : null}
|
) : null}
|
||||||
{/* </Menu> */}
|
{/* </Menu> */}
|
||||||
|
@ -355,6 +392,9 @@ const NewDashboard = (props) => {
|
||||||
size="xs"
|
size="xs"
|
||||||
py={2}
|
py={2}
|
||||||
disabled={!subscibedItem.address}
|
disabled={!subscibedItem.address}
|
||||||
|
onClick={() =>
|
||||||
|
overlay.toggleModal(MODAL_TYPES.UPLOAD_ABI)
|
||||||
|
}
|
||||||
>
|
>
|
||||||
Upload
|
Upload
|
||||||
</Button>
|
</Button>
|
||||||
|
@ -369,6 +409,14 @@ const NewDashboard = (props) => {
|
||||||
isChecked={subscibedItem.isMethods}
|
isChecked={subscibedItem.isMethods}
|
||||||
></Checkbox>
|
></Checkbox>
|
||||||
</Td>
|
</Td>
|
||||||
|
<Td w="60px">
|
||||||
|
<Checkbox
|
||||||
|
isDisabled={
|
||||||
|
!subscibedItem.address || !subscibedItem.hasABI
|
||||||
|
}
|
||||||
|
isChecked={subscibedItem.isEvents}
|
||||||
|
></Checkbox>
|
||||||
|
</Td>
|
||||||
|
|
||||||
<Td>
|
<Td>
|
||||||
{idx > 0 && (
|
{idx > 0 && (
|
||||||
|
|
|
@ -1,10 +1,9 @@
|
||||||
import React, { useState, useEffect, useCallback } from "react";
|
import React, { useState, useEffect, useCallback, useRef } from "react";
|
||||||
import { useSubscriptions } from "../core/hooks";
|
import { useSubscriptions } from "../core/hooks";
|
||||||
import {
|
import {
|
||||||
Input,
|
Input,
|
||||||
Stack,
|
Stack,
|
||||||
Text,
|
Text,
|
||||||
HStack,
|
|
||||||
useRadioGroup,
|
useRadioGroup,
|
||||||
FormControl,
|
FormControl,
|
||||||
FormErrorMessage,
|
FormErrorMessage,
|
||||||
|
@ -13,14 +12,26 @@ import {
|
||||||
IconButton,
|
IconButton,
|
||||||
ButtonGroup,
|
ButtonGroup,
|
||||||
Flex,
|
Flex,
|
||||||
|
Box,
|
||||||
|
InputGroup,
|
||||||
|
Image,
|
||||||
|
InputLeftAddon,
|
||||||
|
InputRightAddon,
|
||||||
|
chakra,
|
||||||
|
Tooltip,
|
||||||
|
VStack,
|
||||||
|
FormLabel,
|
||||||
|
useToast,
|
||||||
} from "@chakra-ui/react";
|
} from "@chakra-ui/react";
|
||||||
import RadioCard from "./RadioCard";
|
|
||||||
// import { useForm } from "react-hook-form";
|
// import { useForm } from "react-hook-form";
|
||||||
import { CirclePicker } from "react-color";
|
import { CirclePicker } from "react-color";
|
||||||
import { BiRefresh } from "react-icons/bi";
|
import { BiRefresh } from "react-icons/bi";
|
||||||
import { GithubPicker } from "react-color";
|
import { GithubPicker } from "react-color";
|
||||||
import { makeColor } from "../core/utils/makeColor";
|
import { makeColor } from "../core/utils/makeColor";
|
||||||
import { useForm } from "react-hook-form";
|
import { useForm } from "react-hook-form";
|
||||||
|
import Web3 from "web3";
|
||||||
|
import Downshift from "downshift";
|
||||||
|
import { QuestionIcon } from "@chakra-ui/icons";
|
||||||
const _NewSubscription = ({
|
const _NewSubscription = ({
|
||||||
isFreeOption,
|
isFreeOption,
|
||||||
onClose,
|
onClose,
|
||||||
|
@ -28,15 +39,32 @@ const _NewSubscription = ({
|
||||||
initialAddress,
|
initialAddress,
|
||||||
initialType,
|
initialType,
|
||||||
isModal,
|
isModal,
|
||||||
|
initialValue,
|
||||||
}) => {
|
}) => {
|
||||||
const [color, setColor] = useState(makeColor());
|
const [color, setColor] = useState(makeColor());
|
||||||
const { handleSubmit, errors, register } = useForm({});
|
const { handleSubmit, errors, register } = useForm({});
|
||||||
|
const [address, setAddress] = useState();
|
||||||
|
const [label, setLabel] = useState();
|
||||||
|
const [type, setType] = useState();
|
||||||
const { typesCache, createSubscription } = useSubscriptions();
|
const { typesCache, createSubscription } = useSubscriptions();
|
||||||
|
|
||||||
const [radioState, setRadioState] = useState(
|
const [radioState, setRadioState] = useState(
|
||||||
initialType ?? "ethereum_blockchain"
|
initialType ?? "ethereum_blockchain"
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const [pickerItems, setPickerItems] = useState();
|
||||||
|
|
||||||
|
const toast = useToast();
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (!typesCache.isLoading) {
|
||||||
|
const massaged = typesCache.data?.map((item) => {
|
||||||
|
return { value: item.name, ...item };
|
||||||
|
});
|
||||||
|
setPickerItems(massaged);
|
||||||
|
}
|
||||||
|
}, [typesCache.data, typesCache.isLoading]);
|
||||||
|
|
||||||
const mapper = {
|
const mapper = {
|
||||||
"tag:erc721": "NFTs",
|
"tag:erc721": "NFTs",
|
||||||
"input:address": "Address",
|
"input:address": "Address",
|
||||||
|
@ -57,6 +85,16 @@ const _NewSubscription = ({
|
||||||
onChange: setsubscriptionAdressFormatRadio,
|
onChange: setsubscriptionAdressFormatRadio,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (initialValue && initialValue !== "") {
|
||||||
|
console.log("iv:", initialValue, Web3.utils.isAddress(initialValue));
|
||||||
|
if (Web3.utils.isAddress(initialValue)) {
|
||||||
|
setAddress(initialValue);
|
||||||
|
} else {
|
||||||
|
setLabel(initialValue);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}, [initialValue]);
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (setIsLoading) {
|
if (setIsLoading) {
|
||||||
setIsLoading(createSubscription.isLoading);
|
setIsLoading(createSubscription.isLoading);
|
||||||
|
@ -71,7 +109,8 @@ const _NewSubscription = ({
|
||||||
|
|
||||||
const createSubscriptionWrapper = useCallback(
|
const createSubscriptionWrapper = useCallback(
|
||||||
(props) => {
|
(props) => {
|
||||||
props.label = "Address";
|
props.label = props.label ?? "Address";
|
||||||
|
props.type = type.id;
|
||||||
if (
|
if (
|
||||||
subscriptionAdressFormatRadio.startsWith("tag") &&
|
subscriptionAdressFormatRadio.startsWith("tag") &&
|
||||||
radioState != "ethereum_whalewatch"
|
radioState != "ethereum_whalewatch"
|
||||||
|
@ -79,21 +118,36 @@ const _NewSubscription = ({
|
||||||
props.address = subscriptionAdressFormatRadio;
|
props.address = subscriptionAdressFormatRadio;
|
||||||
props.label = "Tag";
|
props.label = "Tag";
|
||||||
}
|
}
|
||||||
|
if (!props.address) {
|
||||||
|
props.address = "0x000000000000000000000000000000000000dead";
|
||||||
|
}
|
||||||
|
|
||||||
createSubscription.mutate({
|
if (Web3.utils.isAddress(props.address)) {
|
||||||
...props,
|
createSubscription.mutate({
|
||||||
color: color,
|
...props,
|
||||||
type: isFreeOption ? "ethereum_blockchain" : radioState,
|
color: color,
|
||||||
});
|
});
|
||||||
|
} else {
|
||||||
|
if (!toast.isActive("address_toast"))
|
||||||
|
toast({
|
||||||
|
title: "Is not valid Ethereum Address",
|
||||||
|
status: "error",
|
||||||
|
position: "bottom",
|
||||||
|
id: "address_toast",
|
||||||
|
description: "Web3.utils.isAddress returned false",
|
||||||
|
});
|
||||||
|
}
|
||||||
},
|
},
|
||||||
[
|
[
|
||||||
|
toast,
|
||||||
createSubscription,
|
createSubscription,
|
||||||
isFreeOption,
|
|
||||||
color,
|
color,
|
||||||
radioState,
|
radioState,
|
||||||
subscriptionAdressFormatRadio,
|
subscriptionAdressFormatRadio,
|
||||||
|
type,
|
||||||
]
|
]
|
||||||
);
|
);
|
||||||
|
const downshiftRef = useRef(null);
|
||||||
|
|
||||||
if (typesCache.isLoading) return <Spinner />;
|
if (typesCache.isLoading) return <Spinner />;
|
||||||
|
|
||||||
|
@ -111,11 +165,21 @@ const _NewSubscription = ({
|
||||||
|
|
||||||
if (!errors) return "";
|
if (!errors) return "";
|
||||||
|
|
||||||
|
console.log("selected type", type);
|
||||||
|
console.log("pickerItems", pickerItems);
|
||||||
|
|
||||||
|
const filterFn = (item, inputValue) => {
|
||||||
|
console.log("filterFN", item.name, inputValue);
|
||||||
|
return (
|
||||||
|
!inputValue || item.name.toUpperCase().includes(inputValue.toUpperCase())
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<form onSubmit={handleSubmit(createSubscriptionWrapper)}>
|
<form onSubmit={handleSubmit(createSubscriptionWrapper)}>
|
||||||
<Stack mb={0} direction="column">
|
<Stack mb={0} direction="column">
|
||||||
<Stack spacing={1} w="100%">
|
<Stack spacing={1} w="100%" pb={2}>
|
||||||
<Text fontWeight="600">Source:</Text>
|
<Text fontWeight="600">Type:</Text>
|
||||||
{/* position must be relative otherwise radio boxes add strange spacing on selection */}
|
{/* position must be relative otherwise radio boxes add strange spacing on selection */}
|
||||||
<Stack
|
<Stack
|
||||||
spacing={1}
|
spacing={1}
|
||||||
|
@ -124,7 +188,164 @@ const _NewSubscription = ({
|
||||||
flexWrap="wrap"
|
flexWrap="wrap"
|
||||||
position="relative"
|
position="relative"
|
||||||
>
|
>
|
||||||
{typesCache.data
|
{!typesCache.isLoading && typesCache.data && pickerItems && (
|
||||||
|
<>
|
||||||
|
<Downshift
|
||||||
|
onSelect={(selectedItem) => {
|
||||||
|
setType(selectedItem);
|
||||||
|
}}
|
||||||
|
// isOpen={showSuggestions}
|
||||||
|
itemToString={(item) => (item ? item.name : "")}
|
||||||
|
// initialSelectedItem={pickerItems[1] ?? undefined}
|
||||||
|
ref={downshiftRef}
|
||||||
|
// initialInputValue={}
|
||||||
|
>
|
||||||
|
{({
|
||||||
|
getInputProps,
|
||||||
|
getItemProps,
|
||||||
|
getLabelProps,
|
||||||
|
getMenuProps,
|
||||||
|
getToggleButtonProps,
|
||||||
|
isOpen,
|
||||||
|
inputValue,
|
||||||
|
highlightedIndex,
|
||||||
|
selectedItem,
|
||||||
|
getRootProps,
|
||||||
|
}) => {
|
||||||
|
console.log("selected item,", selectedItem?.name);
|
||||||
|
return (
|
||||||
|
<Box pos="relative" w="100%">
|
||||||
|
<Box
|
||||||
|
// style={comboboxStyles}
|
||||||
|
{...getRootProps({}, { suppressRefError: true })}
|
||||||
|
>
|
||||||
|
<InputGroup>
|
||||||
|
<InputLeftAddon
|
||||||
|
isTruncated
|
||||||
|
maxW="60px"
|
||||||
|
fontSize="sm"
|
||||||
|
bgColor={"gray.100"}
|
||||||
|
>
|
||||||
|
<Image h="24px" src={selectedItem?.icon_url} />
|
||||||
|
</InputLeftAddon>
|
||||||
|
|
||||||
|
<Input
|
||||||
|
placeholder="What do you want to subscribe to"
|
||||||
|
isTruncated
|
||||||
|
fontSize="sm"
|
||||||
|
{...getInputProps()}
|
||||||
|
// defaultValue={selectedItem.name ?? undefined}
|
||||||
|
// value={selectedItem.name}
|
||||||
|
></Input>
|
||||||
|
<InputRightAddon p={0}>
|
||||||
|
<Button
|
||||||
|
variant="outline"
|
||||||
|
w="100%"
|
||||||
|
m={0}
|
||||||
|
p={0}
|
||||||
|
colorScheme="gray"
|
||||||
|
{...getToggleButtonProps({
|
||||||
|
// onClick: () =>
|
||||||
|
// console.log(
|
||||||
|
// "ref: ",
|
||||||
|
// downshiftRef.current.clearSelection()
|
||||||
|
// ),
|
||||||
|
})}
|
||||||
|
aria-label={"toggle menu"}
|
||||||
|
>
|
||||||
|
↓
|
||||||
|
</Button>
|
||||||
|
</InputRightAddon>
|
||||||
|
</InputGroup>
|
||||||
|
</Box>
|
||||||
|
{/* <Menu
|
||||||
|
isOpen={isOpen}
|
||||||
|
|
||||||
|
// style={menuStyles}
|
||||||
|
// position="absolute"
|
||||||
|
colorScheme="blue"
|
||||||
|
bgColor="gray.300"
|
||||||
|
inset="unset"
|
||||||
|
// spacing={2}
|
||||||
|
|
||||||
|
// p={2}
|
||||||
|
> */}
|
||||||
|
{isOpen ? (
|
||||||
|
<Stack
|
||||||
|
// display="flex"
|
||||||
|
direction="column"
|
||||||
|
className="menuListTim"
|
||||||
|
{...getMenuProps()}
|
||||||
|
bgColor="gray.300"
|
||||||
|
borderRadius="md"
|
||||||
|
boxShadow="lg"
|
||||||
|
pos="absolute"
|
||||||
|
left={0}
|
||||||
|
right={0}
|
||||||
|
spacing={2}
|
||||||
|
zIndex={1000}
|
||||||
|
py={2}
|
||||||
|
>
|
||||||
|
{pickerItems &&
|
||||||
|
pickerItems
|
||||||
|
.filter((item) => filterFn(item, inputValue))
|
||||||
|
.map((item, index) => {
|
||||||
|
return (
|
||||||
|
<Stack
|
||||||
|
px={4}
|
||||||
|
py={1}
|
||||||
|
alignItems="center"
|
||||||
|
key={item.value}
|
||||||
|
{...getItemProps({
|
||||||
|
key: item.value,
|
||||||
|
index,
|
||||||
|
item,
|
||||||
|
})}
|
||||||
|
direction="row"
|
||||||
|
w="100%"
|
||||||
|
bgColor={
|
||||||
|
index === highlightedIndex
|
||||||
|
? "orange.900"
|
||||||
|
: "inherit"
|
||||||
|
}
|
||||||
|
color={
|
||||||
|
index === highlightedIndex
|
||||||
|
? "gray.100"
|
||||||
|
: "inherit"
|
||||||
|
}
|
||||||
|
justifyContent="space-between"
|
||||||
|
>
|
||||||
|
<Image
|
||||||
|
h="24px"
|
||||||
|
src={item.icon_url}
|
||||||
|
alignSelf="flex-start"
|
||||||
|
/>
|
||||||
|
<chakra.span
|
||||||
|
whiteSpace="nowrap"
|
||||||
|
alignSelf="center"
|
||||||
|
>
|
||||||
|
{item.name}
|
||||||
|
</chakra.span>
|
||||||
|
<Tooltip
|
||||||
|
label={item.description}
|
||||||
|
colorScheme="blue"
|
||||||
|
variant="onboarding"
|
||||||
|
>
|
||||||
|
<QuestionIcon h="24px" />
|
||||||
|
</Tooltip>
|
||||||
|
</Stack>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
</Stack>
|
||||||
|
) : null}
|
||||||
|
{/* </Menu> */}
|
||||||
|
</Box>
|
||||||
|
);
|
||||||
|
}}
|
||||||
|
</Downshift>
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
{/* {typesCache.data
|
||||||
.sort((a, b) =>
|
.sort((a, b) =>
|
||||||
a?.name > b?.name ? 1 : b?.name > a?.name ? -1 : 0
|
a?.name > b?.name ? 1 : b?.name > a?.name ? -1 : 0
|
||||||
)
|
)
|
||||||
|
@ -136,7 +357,7 @@ const _NewSubscription = ({
|
||||||
!type.active ||
|
!type.active ||
|
||||||
(isFreeOption && type.id !== "ethereum_blockchain"),
|
(isFreeOption && type.id !== "ethereum_blockchain"),
|
||||||
});
|
});
|
||||||
if (type.id === "ethereum_whalewatch") return "";
|
|
||||||
return (
|
return (
|
||||||
<RadioCard
|
<RadioCard
|
||||||
px="8px"
|
px="8px"
|
||||||
|
@ -151,151 +372,176 @@ const _NewSubscription = ({
|
||||||
{type.name.slice(9, type.name.length)}
|
{type.name.slice(9, type.name.length)}
|
||||||
</RadioCard>
|
</RadioCard>
|
||||||
);
|
);
|
||||||
})}
|
})} */}
|
||||||
</Stack>
|
</Stack>
|
||||||
</Stack>
|
</Stack>
|
||||||
|
|
||||||
<Flex direction="row" w="100%" flexWrap="wrap" pt={4}>
|
{!type?.id?.includes("whalewatch") && type && (
|
||||||
{/* position must be relative otherwise radio boxes add strange spacing on selection */}
|
<Flex direction="row" w="100%" flexWrap="wrap">
|
||||||
<HStack flexGrow={0} flexBasis="140px" position="relative">
|
{/* position must be relative otherwise radio boxes add strange spacing on selection */}
|
||||||
{search(radioState, typesCache.data).choices.length > 0 && (
|
<VStack w="100%" spacing={0}>
|
||||||
<Text fontWeight="600">Type:</Text>
|
{subscriptionAdressFormatRadio.startsWith("input") && (
|
||||||
)}
|
<Flex w="100%">
|
||||||
{search(radioState, typesCache.data).choices.map(
|
<FormControl isInvalid={errors?.address}>
|
||||||
(addition_selects) => {
|
<InputGroup my={2} fontSize="xs">
|
||||||
const radio = getRadioPropsSubscription({
|
<InputLeftAddon>
|
||||||
value: addition_selects,
|
<FormLabel
|
||||||
isDisabled: addition_selects.startsWith("tag"),
|
fontWeight="600"
|
||||||
});
|
// alignSelf="flex-start"
|
||||||
return (
|
m={0}
|
||||||
<RadioCard
|
>
|
||||||
px="4px"
|
Address:
|
||||||
py="2px"
|
</FormLabel>
|
||||||
key={`subscription_tags_${addition_selects}`}
|
</InputLeftAddon>
|
||||||
{...radio}
|
<Input
|
||||||
>
|
type="text"
|
||||||
{mapper[addition_selects]}
|
autoComplete="off"
|
||||||
</RadioCard>
|
placeholder="Address to subscribe to"
|
||||||
);
|
name="address"
|
||||||
}
|
value={address}
|
||||||
)}
|
onChange={(e) => setAddress(e.target.value)}
|
||||||
</HStack>
|
ref={register({ required: "address is required!" })}
|
||||||
{subscriptionAdressFormatRadio.startsWith("input") &&
|
></Input>
|
||||||
radioState != "ethereum_whalewatch" && (
|
</InputGroup>
|
||||||
<Flex flexBasis="240px" flexGrow={1}>
|
<FormErrorMessage color="red.400" pl="1">
|
||||||
<FormControl isInvalid={errors?.address}>
|
{errors?.address && errors?.address.message}
|
||||||
<Input
|
</FormErrorMessage>
|
||||||
type="text"
|
</FormControl>
|
||||||
autoComplete="off"
|
</Flex>
|
||||||
my={2}
|
)}
|
||||||
placeholder="Address to subscribe to"
|
</VStack>
|
||||||
name="address"
|
</Flex>
|
||||||
ref={register({ required: "address is required!" })}
|
)}
|
||||||
></Input>
|
{!type?.id?.includes("whalewatch") && type && (
|
||||||
|
<Flex direction="row" w="100%" flexWrap="wrap">
|
||||||
|
{/* position must be relative otherwise radio boxes add strange spacing on selection */}
|
||||||
|
<VStack w="100%" spacing={0}>
|
||||||
|
<Flex w="100%">
|
||||||
|
<FormControl isInvalid={errors?.label}>
|
||||||
|
<InputGroup my={2} fontSize="xs">
|
||||||
|
<InputLeftAddon>
|
||||||
|
<FormLabel
|
||||||
|
fontWeight="600"
|
||||||
|
// alignSelf="flex-start"
|
||||||
|
m={0}
|
||||||
|
>
|
||||||
|
Label:
|
||||||
|
</FormLabel>
|
||||||
|
</InputLeftAddon>
|
||||||
|
<Input
|
||||||
|
type="text"
|
||||||
|
autoComplete="off"
|
||||||
|
placeholder="Name your label"
|
||||||
|
name="label"
|
||||||
|
value={label}
|
||||||
|
onChange={(e) => setLabel(e.target.value)}
|
||||||
|
ref={register({ required: "label is required!" })}
|
||||||
|
></Input>
|
||||||
|
</InputGroup>
|
||||||
<FormErrorMessage color="red.400" pl="1">
|
<FormErrorMessage color="red.400" pl="1">
|
||||||
{errors?.address && errors?.address.message}
|
{errors?.label && errors?.label.message}
|
||||||
</FormErrorMessage>
|
</FormErrorMessage>
|
||||||
</FormControl>
|
</FormControl>
|
||||||
</Flex>
|
</Flex>
|
||||||
)}
|
</VStack>
|
||||||
</Flex>
|
|
||||||
<Input
|
|
||||||
type="hidden"
|
|
||||||
placeholder="subscription_type"
|
|
||||||
name="subscription_type"
|
|
||||||
ref={register({ required: "select type" })}
|
|
||||||
value={radioState}
|
|
||||||
onChange={() => null}
|
|
||||||
></Input>
|
|
||||||
</Stack>
|
|
||||||
<FormControl isInvalid={errors?.color}>
|
|
||||||
{!isModal ? (
|
|
||||||
<Flex direction="row" pb={2} flexWrap="wrap" alignItems="baseline">
|
|
||||||
<Text fontWeight="600" alignSelf="center">
|
|
||||||
Label color
|
|
||||||
</Text>{" "}
|
|
||||||
<Stack
|
|
||||||
// pt={2}
|
|
||||||
direction={["row", "row", null]}
|
|
||||||
h="min-content"
|
|
||||||
alignSelf="center"
|
|
||||||
>
|
|
||||||
<IconButton
|
|
||||||
size="md"
|
|
||||||
// colorScheme="blue"
|
|
||||||
color={"white.100"}
|
|
||||||
_hover={{ bgColor: { color } }}
|
|
||||||
bgColor={color}
|
|
||||||
variant="outline"
|
|
||||||
onClick={() => setColor(makeColor())}
|
|
||||||
icon={<BiRefresh />}
|
|
||||||
/>
|
|
||||||
<Input
|
|
||||||
type="input"
|
|
||||||
placeholder="color"
|
|
||||||
name="color"
|
|
||||||
ref={register({ required: "color is required!" })}
|
|
||||||
value={color}
|
|
||||||
onChange={() => null}
|
|
||||||
w="200px"
|
|
||||||
></Input>
|
|
||||||
</Stack>
|
|
||||||
<Flex p={2} flexBasis="120px" flexGrow={1} alignSelf="center">
|
|
||||||
<CirclePicker
|
|
||||||
width="100%"
|
|
||||||
onChangeComplete={handleChangeColorComplete}
|
|
||||||
circleSpacing={1}
|
|
||||||
circleSize={24}
|
|
||||||
/>
|
|
||||||
</Flex>
|
|
||||||
</Flex>
|
</Flex>
|
||||||
) : (
|
|
||||||
<>
|
|
||||||
<Stack direction="row" pb={2}>
|
|
||||||
<Text fontWeight="600" alignSelf="center">
|
|
||||||
Label color
|
|
||||||
</Text>{" "}
|
|
||||||
<IconButton
|
|
||||||
size="md"
|
|
||||||
color={"white.100"}
|
|
||||||
_hover={{ bgColor: { color } }}
|
|
||||||
bgColor={color}
|
|
||||||
variant="outline"
|
|
||||||
onClick={() => setColor(makeColor())}
|
|
||||||
icon={<BiRefresh />}
|
|
||||||
/>
|
|
||||||
<Input
|
|
||||||
type="input"
|
|
||||||
placeholder="color"
|
|
||||||
name="color"
|
|
||||||
ref={register({ required: "color is required!" })}
|
|
||||||
value={color}
|
|
||||||
onChange={() => null}
|
|
||||||
w="200px"
|
|
||||||
></Input>
|
|
||||||
</Stack>
|
|
||||||
|
|
||||||
<GithubPicker onChangeComplete={handleChangeColorComplete} />
|
|
||||||
</>
|
|
||||||
)}
|
)}
|
||||||
<FormErrorMessage color="red.400" pl="1">
|
|
||||||
{errors?.color && errors?.color.message}
|
|
||||||
</FormErrorMessage>
|
|
||||||
</FormControl>
|
|
||||||
|
|
||||||
<ButtonGroup direction="row" justifyContent="flex-end" w="100%">
|
{type && (
|
||||||
<Button
|
<FormControl isInvalid={errors?.color}>
|
||||||
type="submit"
|
{!isModal ? (
|
||||||
colorScheme="green"
|
<Flex
|
||||||
isLoading={createSubscription.isLoading}
|
direction="row"
|
||||||
>
|
pb={2}
|
||||||
Confirm
|
flexWrap="wrap"
|
||||||
</Button>
|
alignItems="baseline"
|
||||||
|
>
|
||||||
|
<Text fontWeight="600" alignSelf="center">
|
||||||
|
Label color
|
||||||
|
</Text>{" "}
|
||||||
|
<Stack
|
||||||
|
// pt={2}
|
||||||
|
direction={["row", "row", null]}
|
||||||
|
h="min-content"
|
||||||
|
alignSelf="center"
|
||||||
|
>
|
||||||
|
<IconButton
|
||||||
|
size="md"
|
||||||
|
// colorScheme="blue"
|
||||||
|
color={"white.100"}
|
||||||
|
_hover={{ bgColor: { color } }}
|
||||||
|
bgColor={color}
|
||||||
|
variant="outline"
|
||||||
|
onClick={() => setColor(makeColor())}
|
||||||
|
icon={<BiRefresh />}
|
||||||
|
/>
|
||||||
|
<Input
|
||||||
|
type="input"
|
||||||
|
placeholder="color"
|
||||||
|
name="color"
|
||||||
|
ref={register({ required: "color is required!" })}
|
||||||
|
value={color}
|
||||||
|
onChange={() => null}
|
||||||
|
w="200px"
|
||||||
|
></Input>
|
||||||
|
</Stack>
|
||||||
|
<Flex p={2} flexBasis="120px" flexGrow={1} alignSelf="center">
|
||||||
|
<CirclePicker
|
||||||
|
width="100%"
|
||||||
|
onChangeComplete={handleChangeColorComplete}
|
||||||
|
circleSpacing={1}
|
||||||
|
circleSize={24}
|
||||||
|
/>
|
||||||
|
</Flex>
|
||||||
|
</Flex>
|
||||||
|
) : (
|
||||||
|
<>
|
||||||
|
<Stack direction="row" pb={2}>
|
||||||
|
<Text fontWeight="600" alignSelf="center">
|
||||||
|
Label color
|
||||||
|
</Text>{" "}
|
||||||
|
<IconButton
|
||||||
|
size="md"
|
||||||
|
color={"white.100"}
|
||||||
|
_hover={{ bgColor: { color } }}
|
||||||
|
bgColor={color}
|
||||||
|
variant="outline"
|
||||||
|
onClick={() => setColor(makeColor())}
|
||||||
|
icon={<BiRefresh />}
|
||||||
|
/>
|
||||||
|
<Input
|
||||||
|
type="input"
|
||||||
|
placeholder="color"
|
||||||
|
name="color"
|
||||||
|
ref={register({ required: "color is required!" })}
|
||||||
|
value={color}
|
||||||
|
onChange={() => null}
|
||||||
|
w="200px"
|
||||||
|
></Input>
|
||||||
|
</Stack>
|
||||||
|
|
||||||
<Button colorScheme="gray" onClick={onClose}>
|
<GithubPicker onChangeComplete={handleChangeColorComplete} />
|
||||||
Cancel
|
</>
|
||||||
</Button>
|
)}
|
||||||
</ButtonGroup>
|
<FormErrorMessage color="red.400" pl="1">
|
||||||
|
{errors?.color && errors?.color.message}
|
||||||
|
</FormErrorMessage>
|
||||||
|
</FormControl>
|
||||||
|
)}
|
||||||
|
<ButtonGroup direction="row" justifyContent="flex-end" w="100%">
|
||||||
|
<Button
|
||||||
|
type="submit"
|
||||||
|
colorScheme="green"
|
||||||
|
isLoading={createSubscription.isLoading}
|
||||||
|
>
|
||||||
|
Confirm
|
||||||
|
</Button>
|
||||||
|
|
||||||
|
<Button colorScheme="red" onClick={onClose}>
|
||||||
|
Cancel
|
||||||
|
</Button>
|
||||||
|
</ButtonGroup>
|
||||||
|
</Stack>
|
||||||
</form>
|
</form>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,4 +1,9 @@
|
||||||
import React, { useState, useLayoutEffect, useContext, Suspense } from "react";
|
import React, {
|
||||||
|
useState,
|
||||||
|
useLayoutEffect,
|
||||||
|
useContext,
|
||||||
|
Suspense,
|
||||||
|
} from "react";
|
||||||
import OverlayContext from "./context";
|
import OverlayContext from "./context";
|
||||||
import { MODAL_TYPES, DRAWER_TYPES } from "./constants";
|
import { MODAL_TYPES, DRAWER_TYPES } from "./constants";
|
||||||
import {
|
import {
|
||||||
|
@ -51,6 +56,7 @@ const OverlayProvider = ({ children }) => {
|
||||||
const drawerDisclosure = useDisclosure();
|
const drawerDisclosure = useDisclosure();
|
||||||
const modalDisclosure = useDisclosure();
|
const modalDisclosure = useDisclosure();
|
||||||
const alertDisclosure = useDisclosure();
|
const alertDisclosure = useDisclosure();
|
||||||
|
const [modalProps, setModalProps] = useState();
|
||||||
|
|
||||||
useLayoutEffect(() => {
|
useLayoutEffect(() => {
|
||||||
if (modal === MODAL_TYPES.OFF && modalDisclosure.isOpen) {
|
if (modal === MODAL_TYPES.OFF && modalDisclosure.isOpen) {
|
||||||
|
@ -106,7 +112,7 @@ const OverlayProvider = ({ children }) => {
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<OverlayContext.Provider
|
<OverlayContext.Provider
|
||||||
value={{ modal, toggleModal, drawer, toggleDrawer }}
|
value={{ modal, toggleModal, drawer, toggleDrawer, setModalProps }}
|
||||||
>
|
>
|
||||||
<AlertDialog
|
<AlertDialog
|
||||||
isOpen={alertDisclosure.isOpen}
|
isOpen={alertDisclosure.isOpen}
|
||||||
|
@ -169,6 +175,7 @@ const OverlayProvider = ({ children }) => {
|
||||||
<NewSubscription
|
<NewSubscription
|
||||||
onClose={() => toggleModal(MODAL_TYPES.OFF)}
|
onClose={() => toggleModal(MODAL_TYPES.OFF)}
|
||||||
isModal={true}
|
isModal={true}
|
||||||
|
{...modalProps}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
{modal === MODAL_TYPES.FORGOT && <ForgotPassword />}
|
{modal === MODAL_TYPES.FORGOT && <ForgotPassword />}
|
||||||
|
@ -193,6 +200,7 @@ const OverlayProvider = ({ children }) => {
|
||||||
</Modal>
|
</Modal>
|
||||||
{/* )} */}
|
{/* )} */}
|
||||||
<Drawer
|
<Drawer
|
||||||
|
trapFocus={false}
|
||||||
isOpen={drawerDisclosure.isOpen}
|
isOpen={drawerDisclosure.isOpen}
|
||||||
placement="right"
|
placement="right"
|
||||||
size="xl"
|
size="xl"
|
||||||
|
@ -201,13 +209,13 @@ const OverlayProvider = ({ children }) => {
|
||||||
onClose={() => toggleAlert(() => toggleDrawer(DRAWER_TYPES.OFF))}
|
onClose={() => toggleAlert(() => toggleDrawer(DRAWER_TYPES.OFF))}
|
||||||
>
|
>
|
||||||
<DrawerOverlay />
|
<DrawerOverlay />
|
||||||
<DrawerContent>
|
<DrawerContent overflowY="scroll">
|
||||||
<DrawerCloseButton />
|
<DrawerCloseButton />
|
||||||
<DrawerHeader borderBottomWidth="1px">
|
<DrawerHeader borderBottomWidth="1px">
|
||||||
{DRAWER_TYPES.NEW_DASHBOARD && "New dashboard"}
|
{DRAWER_TYPES.NEW_DASHBOARD && "New dashboard"}
|
||||||
</DrawerHeader>
|
</DrawerHeader>
|
||||||
|
|
||||||
<DrawerBody>
|
<DrawerBody h="auto">
|
||||||
{DRAWER_TYPES.NEW_DASHBOARD && (
|
{DRAWER_TYPES.NEW_DASHBOARD && (
|
||||||
<Suspense fallback={<Spinner />}>
|
<Suspense fallback={<Spinner />}>
|
||||||
<NewDashboard firstField={firstField} />
|
<NewDashboard firstField={firstField} />
|
||||||
|
|
Ładowanie…
Reference in New Issue