kopia lustrzana https://github.com/bugout-dev/moonstream
Merge pull request #324 from bugout-dev/CreateNew-ABIDashboard
"Create new" Frontend Expreiencepull/351/head
commit
cdc6f7231a
|
@ -16,6 +16,8 @@
|
|||
"@emotion/styled": "^11.3.0",
|
||||
"@stripe/stripe-js": "^1.16.0",
|
||||
"axios": "^0.21.1",
|
||||
"color": "^4.0.1",
|
||||
"downshift": "^6.1.7",
|
||||
"focus-visible": "^5.2.0",
|
||||
"framer-motion": "^4.1.17",
|
||||
"mixpanel-browser": "^2.41.0",
|
||||
|
|
|
@ -25,6 +25,7 @@ import {
|
|||
} from "../src/core/providers/AnalyticsProvider/constants";
|
||||
import { AWS_ASSETS_PATH } from "../src/core/constants";
|
||||
import mixpanel from "mixpanel-browser";
|
||||
import { MODAL_TYPES } from "../src/core/providers/OverlayProvider/constants";
|
||||
|
||||
const ConnectedButtons = dynamic(
|
||||
() => import("../src/components/ConnectedButtons"),
|
||||
|
@ -398,7 +399,7 @@ const Homepage = () => {
|
|||
[`${MIXPANEL_PROPS.BUTTON_NAME}`]: `Early access CTA: developer want to find more button`,
|
||||
}
|
||||
);
|
||||
toggleModal("hubspot-developer");
|
||||
toggleModal(MODAL_TYPES.HUBSPOT);
|
||||
}}
|
||||
>
|
||||
request early access
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import { getLayout } from "../src/layouts/AppLayout";
|
||||
import React, { useState } from "react";
|
||||
import React, { useContext } from "react";
|
||||
import SubscriptionsList from "../src/components/SubscriptionsList";
|
||||
import { useSubscriptions } from "../src/core/hooks";
|
||||
import {
|
||||
|
@ -10,21 +10,14 @@ import {
|
|||
Heading,
|
||||
Flex,
|
||||
Button,
|
||||
Modal,
|
||||
useDisclosure,
|
||||
ModalHeader,
|
||||
ModalCloseButton,
|
||||
ModalBody,
|
||||
ModalOverlay,
|
||||
ModalContent,
|
||||
} from "@chakra-ui/react";
|
||||
import NewSubscription from "../src/components/NewSubscription";
|
||||
import { AiOutlinePlusCircle } from "react-icons/ai";
|
||||
import OverlayContext from "../src/core/providers/OverlayProvider/context";
|
||||
import { MODAL_TYPES } from "../src/core/providers/OverlayProvider/constants";
|
||||
|
||||
const Subscriptions = () => {
|
||||
const { subscriptionsCache } = useSubscriptions();
|
||||
const { isOpen, onOpen, onClose } = useDisclosure();
|
||||
const [isAddingFreeSubscription, setIsAddingFreeSubscription] = useState();
|
||||
const modal = useContext(OverlayContext);
|
||||
|
||||
document.title = `My Subscriptions`;
|
||||
|
||||
|
@ -40,32 +33,11 @@ const Subscriptions = () => {
|
|||
borderBottomWidth: "2px",
|
||||
};
|
||||
|
||||
const newSubscriptionClicked = (isForFree) => {
|
||||
setIsAddingFreeSubscription(isForFree);
|
||||
onOpen();
|
||||
const newSubscriptionClicked = () => {
|
||||
modal.toggleModal(MODAL_TYPES.NEW_SUBSCRIPTON);
|
||||
};
|
||||
return (
|
||||
<Box w="100%" px="7%" pt={2}>
|
||||
<Modal
|
||||
isOpen={isOpen}
|
||||
onClose={onClose}
|
||||
size="2xl"
|
||||
scrollBehavior="outside"
|
||||
>
|
||||
<ModalOverlay />
|
||||
|
||||
<ModalContent>
|
||||
<ModalHeader>Subscribe to a new address</ModalHeader>
|
||||
<ModalCloseButton />
|
||||
<ModalBody>
|
||||
<NewSubscription
|
||||
isFreeOption={isAddingFreeSubscription}
|
||||
onClose={onClose}
|
||||
isModal={true}
|
||||
/>
|
||||
</ModalBody>
|
||||
</ModalContent>
|
||||
</Modal>
|
||||
{subscriptionsCache.isLoading ? (
|
||||
<Center>
|
||||
<Spinner
|
||||
|
|
|
@ -1,72 +1,32 @@
|
|||
import React, { useContext, useEffect, useRef } from "react";
|
||||
import React, { useEffect, useRef } from "react";
|
||||
import { getLayout } from "../src/layouts/AppLayout";
|
||||
import UIContext from "../src/core/providers/UIProvider/context";
|
||||
import {
|
||||
Heading,
|
||||
Text,
|
||||
Button,
|
||||
Stack,
|
||||
ButtonGroup,
|
||||
Spacer,
|
||||
UnorderedList,
|
||||
ListItem,
|
||||
Fade,
|
||||
chakra,
|
||||
useBoolean,
|
||||
Flex,
|
||||
IconButton,
|
||||
Tooltip,
|
||||
Accordion,
|
||||
AccordionItem,
|
||||
AccordionButton,
|
||||
AccordionPanel,
|
||||
AccordionIcon,
|
||||
Divider,
|
||||
} from "@chakra-ui/react";
|
||||
import StepProgress from "../src/components/StepProgress";
|
||||
import { ArrowLeftIcon, ArrowRightIcon } from "@chakra-ui/icons";
|
||||
import Scrollable from "../src/components/Scrollable";
|
||||
import NewSubscription from "../src/components/NewSubscription";
|
||||
import StreamEntry from "../src/components/StreamEntry";
|
||||
import SubscriptionsList from "../src/components/SubscriptionsList";
|
||||
import { useSubscriptions } from "../src/core/hooks";
|
||||
import router from "next/router";
|
||||
import { FaFilter } from "react-icons/fa";
|
||||
|
||||
const Welcome = () => {
|
||||
const { subscriptionsCache } = useSubscriptions();
|
||||
const ui = useContext(UIContext);
|
||||
const [showSubscriptionForm, setShowSubscriptionForm] = useBoolean(true);
|
||||
|
||||
useEffect(() => {
|
||||
if (typeof window !== "undefined") {
|
||||
document.title = `Welcome to moonstream.to!`;
|
||||
}
|
||||
}, []);
|
||||
|
||||
const progressButtonCallback = (index) => {
|
||||
ui.setOnboardingStep(index);
|
||||
};
|
||||
|
||||
const SubscriptonCreatedCallback = () => {
|
||||
setShowSubscriptionForm.off();
|
||||
};
|
||||
|
||||
const scrollRef = useRef();
|
||||
const handleNextClick = () => {
|
||||
if (ui.onboardingStep < ui.onboardingSteps.length - 1) {
|
||||
ui.setOnboardingStep(ui.onboardingStep + 1);
|
||||
scrollRef?.current?.scrollIntoView();
|
||||
} else {
|
||||
ui.setOnboardingComplete(true);
|
||||
router.push("/stream");
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<Scrollable>
|
||||
<Stack px="7%" pt={4} w="100%" spacing={4} ref={scrollRef}>
|
||||
<StepProgress
|
||||
{/* <StepProgress
|
||||
numSteps={ui.onboardingSteps.length}
|
||||
currentStep={ui.onboardingStep}
|
||||
colorScheme="blue"
|
||||
|
@ -77,11 +37,11 @@ const Welcome = () => {
|
|||
"How to read stream",
|
||||
]}
|
||||
style="arrows"
|
||||
/>
|
||||
/> */}
|
||||
|
||||
{ui.onboardingStep === 0 && (
|
||||
{true && (
|
||||
<Fade in>
|
||||
<Stack spacing={4}>
|
||||
<Stack spacing={4} pb={14}>
|
||||
<Stack
|
||||
px={[0, 12, null]}
|
||||
// mt={24}
|
||||
|
@ -240,192 +200,8 @@ const Welcome = () => {
|
|||
</Stack>
|
||||
</Fade>
|
||||
)}
|
||||
{ui.onboardingStep === 1 && (
|
||||
<Fade in>
|
||||
<Stack px="7%">
|
||||
<Stack
|
||||
px={[0, 12, null]}
|
||||
// mt={24}
|
||||
bgColor="gray.50"
|
||||
borderRadius="xl"
|
||||
boxShadow="xl"
|
||||
py={4}
|
||||
my={2}
|
||||
>
|
||||
<Heading as="h4" size="md">
|
||||
Subscriptions
|
||||
</Heading>
|
||||
<chakra.span fontWeight="semibold" pl={2}>
|
||||
Subscriptions are an essential tool of Moonstream. We gather
|
||||
data for you based on addresses you have subscribed to.
|
||||
<br />
|
||||
Subscribe to any address you are interested in and it will
|
||||
become part of your stream.
|
||||
<br />
|
||||
Name of subscription (you can change it later).
|
||||
<UnorderedList>
|
||||
<ListItem>
|
||||
Color - you can set colors to easily identify a
|
||||
subscription in your stream
|
||||
</ListItem>
|
||||
<ListItem>Address - the address you subscribe to</ListItem>
|
||||
<ListItem>
|
||||
Label - we recommend using a human-readable name that
|
||||
represents the subscription
|
||||
</ListItem>
|
||||
<ListItem>
|
||||
Source - In Alpha we’re only supporting Ethereum
|
||||
blockchain, but more sources are coming soon!
|
||||
</ListItem>
|
||||
</UnorderedList>
|
||||
</chakra.span>
|
||||
</Stack>
|
||||
{subscriptionsCache.data.subscriptions.length > 0 &&
|
||||
!subscriptionsCache.isLoading && (
|
||||
<>
|
||||
<Heading>
|
||||
{" "}
|
||||
You already have some subscriptions set up
|
||||
</Heading>
|
||||
</>
|
||||
)}
|
||||
<SubscriptionsList />
|
||||
{showSubscriptionForm && (
|
||||
<Flex direction="column" pt={6}>
|
||||
<Divider bgColor="gray.500" borderWidth="2px" />
|
||||
<Heading
|
||||
size="md"
|
||||
pt={2}
|
||||
>{`Let's add new subscription!`}</Heading>
|
||||
|
||||
<NewSubscription
|
||||
isFreeOption={false}
|
||||
onClose={SubscriptonCreatedCallback}
|
||||
/>
|
||||
</Flex>
|
||||
)}
|
||||
{!showSubscriptionForm && (
|
||||
<Button
|
||||
colorScheme="green"
|
||||
variant="solid"
|
||||
onClick={() => setShowSubscriptionForm.on()}
|
||||
>
|
||||
Add another subscription
|
||||
</Button>
|
||||
)}
|
||||
</Stack>
|
||||
</Fade>
|
||||
)}
|
||||
{ui.onboardingStep === 2 && (
|
||||
<Fade in>
|
||||
<Stack>
|
||||
<Stack
|
||||
px={[0, 12, null]}
|
||||
// mt={24}
|
||||
bgColor="gray.50"
|
||||
borderRadius="xl"
|
||||
boxShadow="xl"
|
||||
py={4}
|
||||
my={2}
|
||||
>
|
||||
<Heading as="h4" size="md">
|
||||
Stream
|
||||
</Heading>
|
||||
<chakra.span fontWeight="semibold" pl={2}>
|
||||
We are almost done!
|
||||
<br />
|
||||
{`Stream is where you can read data you've subscribed to. There are different cards for different subscription types.`}
|
||||
<br />
|
||||
If the card has some extra details, there will be an orange
|
||||
button on the right hand side inviting you to see more!
|
||||
<br />
|
||||
Below is a typical card for an Ethereum blockchain event.
|
||||
Useful information right on the card:
|
||||
<UnorderedList py={2}>
|
||||
<ListItem>Hash - Unique ID of the event</ListItem>
|
||||
<ListItem>
|
||||
From - Sender address. If it is one of your subscription
|
||||
addresses, it will appear in color with a label
|
||||
</ListItem>
|
||||
<ListItem>
|
||||
To - Receiver address. If it is one of your subscription
|
||||
addresses, it will appear in color with a label
|
||||
</ListItem>
|
||||
<ListItem>
|
||||
Nonce - Counter how many transaction addresses have been
|
||||
sent. It also determines the sequence of transactions!
|
||||
</ListItem>
|
||||
<ListItem>
|
||||
Gas Price - This is how much ether is being paid per gas
|
||||
unit
|
||||
</ListItem>
|
||||
<ListItem>Gas - Amount of gas this event consumes</ListItem>
|
||||
</UnorderedList>
|
||||
</chakra.span>
|
||||
</Stack>
|
||||
<Stack
|
||||
pb={ui.isMobileView ? 24 : 8}
|
||||
w={ui.isMobileView ? "100%" : "calc(100% - 300px)"}
|
||||
alignSelf="center"
|
||||
>
|
||||
<Flex h="3rem" w="100%" bgColor="gray.100" alignItems="center">
|
||||
<Flex maxW="90%"></Flex>
|
||||
<Spacer />
|
||||
<Tooltip
|
||||
variant="onboarding"
|
||||
placement={ui.isMobileView ? "bottom" : "right"}
|
||||
label="Filtering menu"
|
||||
isOpen={true}
|
||||
maxW="150px"
|
||||
hasArrow
|
||||
>
|
||||
<IconButton
|
||||
mr={4}
|
||||
// onClick={onOpen}
|
||||
colorScheme="blue"
|
||||
variant="ghost"
|
||||
icon={<FaFilter />}
|
||||
/>
|
||||
</Tooltip>
|
||||
</Flex>
|
||||
<StreamEntry
|
||||
mt={20}
|
||||
entry={{
|
||||
event_type: "ethereum_blockchain",
|
||||
event_data: {
|
||||
from: "this is address from",
|
||||
to: "this is to address",
|
||||
hash: "this is hash",
|
||||
},
|
||||
}}
|
||||
showOnboardingTooltips={true}
|
||||
/>
|
||||
</Stack>
|
||||
<Stack
|
||||
px={12}
|
||||
// mt={24}
|
||||
bgColor="gray.50"
|
||||
borderRadius="xl"
|
||||
boxShadow="xl"
|
||||
py={4}
|
||||
my={2}
|
||||
>
|
||||
<Heading as="h4" size="md">
|
||||
Applying filters
|
||||
</Heading>
|
||||
<chakra.span fontWeight="semibold" pl={2}>
|
||||
You can apply various filters by clicking the filter menu
|
||||
button.
|
||||
<br />
|
||||
{`Right now you can use it to select addresses from and to, and we are adding more complex queries soon — stay tuned!`}
|
||||
<br />
|
||||
</chakra.span>
|
||||
</Stack>
|
||||
</Stack>
|
||||
</Fade>
|
||||
)}
|
||||
|
||||
<ButtonGroup>
|
||||
{/* <ButtonGroup>
|
||||
<Button
|
||||
colorScheme="orange"
|
||||
leftIcon={<ArrowLeftIcon />}
|
||||
|
@ -462,7 +238,7 @@ const Welcome = () => {
|
|||
? `Next`
|
||||
: `Finish and move to stream`}
|
||||
</Button>
|
||||
</ButtonGroup>
|
||||
</ButtonGroup> */}
|
||||
</Stack>
|
||||
</Scrollable>
|
||||
);
|
||||
|
|
|
@ -4,9 +4,9 @@ import theme from "./Theme/theme";
|
|||
import {
|
||||
AnalyticsProvider,
|
||||
UserProvider,
|
||||
ModalProvider,
|
||||
UIProvider,
|
||||
DataProvider,
|
||||
OverlayProvider,
|
||||
} from "./core/providers";
|
||||
import { StripeProvider } from "./core/providers/StripeProvider";
|
||||
|
||||
|
@ -18,17 +18,17 @@ const AppContext = (props) => {
|
|||
}, []);
|
||||
return (
|
||||
<UserProvider>
|
||||
<ModalProvider>
|
||||
<StripeProvider>
|
||||
<ChakraProvider theme={theme}>
|
||||
<DataProvider>
|
||||
<UIProvider>
|
||||
<StripeProvider>
|
||||
<ChakraProvider theme={theme}>
|
||||
<DataProvider>
|
||||
<UIProvider>
|
||||
<OverlayProvider>
|
||||
<AnalyticsProvider>{props.children}</AnalyticsProvider>
|
||||
</UIProvider>
|
||||
</DataProvider>
|
||||
</ChakraProvider>
|
||||
</StripeProvider>
|
||||
</ModalProvider>
|
||||
</OverlayProvider>
|
||||
</UIProvider>
|
||||
</DataProvider>
|
||||
</ChakraProvider>
|
||||
</StripeProvider>
|
||||
</UserProvider>
|
||||
);
|
||||
};
|
||||
|
|
|
@ -0,0 +1,63 @@
|
|||
import React, { useContext } from "react";
|
||||
import {
|
||||
Menu,
|
||||
MenuButton,
|
||||
MenuList,
|
||||
MenuItem,
|
||||
MenuGroup,
|
||||
MenuDivider,
|
||||
IconButton,
|
||||
chakra,
|
||||
} from "@chakra-ui/react";
|
||||
import { PlusSquareIcon } from "@chakra-ui/icons";
|
||||
import UIContext from "../core/providers/UIProvider/context";
|
||||
import OverlayContext from "../core/providers/OverlayProvider/context";
|
||||
|
||||
import {
|
||||
DRAWER_TYPES,
|
||||
MODAL_TYPES,
|
||||
} from "../core/providers/OverlayProvider/constants";
|
||||
|
||||
const AddNewIconButton = (props) => {
|
||||
const ui = useContext(UIContext);
|
||||
const modal = useContext(OverlayContext);
|
||||
|
||||
return (
|
||||
<Menu>
|
||||
<MenuButton
|
||||
{...props}
|
||||
as={IconButton}
|
||||
// onClick={ui.addNewDrawerState.onOpen}
|
||||
aria-label="Account menu"
|
||||
icon={<PlusSquareIcon />}
|
||||
// variant="outline"
|
||||
color="gray.100"
|
||||
/>
|
||||
<MenuList
|
||||
zIndex="dropdown"
|
||||
width={["100vw", "100vw", "18rem", "20rem", "22rem", "24rem"]}
|
||||
borderRadius={0}
|
||||
>
|
||||
<MenuGroup>
|
||||
<MenuItem
|
||||
onClick={() => modal.toggleDrawer(DRAWER_TYPES.NEW_DASHBOARD)}
|
||||
>
|
||||
New Dashboard...
|
||||
</MenuItem>
|
||||
<MenuItem
|
||||
onClick={() => modal.toggleModal(MODAL_TYPES.NEW_SUBSCRIPTON)}
|
||||
>
|
||||
New Subscription...
|
||||
</MenuItem>
|
||||
|
||||
{ui.isInDashboard && <MenuItem>New report...</MenuItem>}
|
||||
</MenuGroup>
|
||||
<MenuDivider />
|
||||
</MenuList>
|
||||
</Menu>
|
||||
);
|
||||
};
|
||||
|
||||
const ChakraAddNewIconButton = chakra(AddNewIconButton);
|
||||
|
||||
export default ChakraAddNewIconButton;
|
|
@ -1,5 +1,4 @@
|
|||
import React, { useState, useContext, useEffect } from "react";
|
||||
import RouterLink from "next/link";
|
||||
import {
|
||||
Flex,
|
||||
Image,
|
||||
|
@ -23,11 +22,11 @@ import {
|
|||
ArrowLeftIcon,
|
||||
ArrowRightIcon,
|
||||
} from "@chakra-ui/icons";
|
||||
import { MdTimeline } from "react-icons/md";
|
||||
import useRouter from "../core/hooks/useRouter";
|
||||
import UIContext from "../core/providers/UIProvider/context";
|
||||
import AccountIconButton from "./AccountIconButton";
|
||||
import RouteButton from "./RouteButton";
|
||||
import AddNewIconButton from "./AddNewIconButton";
|
||||
import {
|
||||
USER_NAV_PATHES,
|
||||
ALL_NAV_PATHES,
|
||||
|
@ -129,6 +128,13 @@ const AppNavbar = () => {
|
|||
})}
|
||||
</ButtonGroup>
|
||||
<SupportPopover />
|
||||
<AddNewIconButton
|
||||
colorScheme="blue"
|
||||
variant="link"
|
||||
color="gray.100"
|
||||
size="lg"
|
||||
h="32px"
|
||||
/>
|
||||
<AccountIconButton
|
||||
colorScheme="blue"
|
||||
variant="link"
|
||||
|
@ -161,19 +167,14 @@ const AppNavbar = () => {
|
|||
}}
|
||||
/>
|
||||
)}
|
||||
<RouterLink href="/stream" passHref>
|
||||
<IconButton
|
||||
m={0}
|
||||
variant="link"
|
||||
justifyContent="space-evenly"
|
||||
alignContent="center"
|
||||
h="32px"
|
||||
size={iconSize}
|
||||
colorScheme="gray"
|
||||
aria-label="go to ticker"
|
||||
icon={<MdTimeline />}
|
||||
/>
|
||||
</RouterLink>
|
||||
<AddNewIconButton
|
||||
variant="link"
|
||||
justifyContent="space-evenly"
|
||||
alignContent="center"
|
||||
h="32px"
|
||||
size={iconSize}
|
||||
colorScheme="blue"
|
||||
/>
|
||||
{!isSearchBarActive && (
|
||||
<IconButton
|
||||
m={0}
|
||||
|
|
|
@ -54,8 +54,6 @@ const ArrowCTA = (props) => {
|
|||
null,
|
||||
];
|
||||
|
||||
const speedConst = -0.05;
|
||||
|
||||
return (
|
||||
<SimpleGrid
|
||||
columns={props.button4 ? [1, 2, 4, null, 4] : [1, 2, 3, null, 3]}
|
||||
|
|
|
@ -1,11 +1,7 @@
|
|||
/** @jsxRuntime classic */
|
||||
/** @jsx jsx */
|
||||
import { jsx } from "@emotion/react";
|
||||
import { useEffect } from "react";
|
||||
import React, { useEffect } from "react";
|
||||
import { useForm } from "react-hook-form";
|
||||
import { useToast, useForgotPassword } from "../core/hooks";
|
||||
import {
|
||||
Heading,
|
||||
FormControl,
|
||||
InputGroup,
|
||||
FormErrorMessage,
|
||||
|
@ -14,7 +10,7 @@ import {
|
|||
InputRightElement,
|
||||
} from "@chakra-ui/react";
|
||||
import CustomIcon from "./CustomIcon";
|
||||
import Modal from "./Modal";
|
||||
import { MODAL_TYPES } from "../core/providers/OverlayProvider/constants";
|
||||
|
||||
const ForgotPassword = ({ toggleModal }) => {
|
||||
const toast = useToast();
|
||||
|
@ -24,43 +20,38 @@ const ForgotPassword = ({ toggleModal }) => {
|
|||
useEffect(() => {
|
||||
if (!data) return;
|
||||
|
||||
toggleModal(null);
|
||||
toggleModal(MODAL_TYPES.OFF);
|
||||
}, [data, toggleModal, toast]);
|
||||
|
||||
return (
|
||||
<Modal onClose={() => toggleModal(null)}>
|
||||
<Heading mt={2} size="md">
|
||||
Forgot Password
|
||||
</Heading>
|
||||
<form onSubmit={handleSubmit(forgotPassword)}>
|
||||
<FormControl isInvalid={errors.email} my={4}>
|
||||
<InputGroup>
|
||||
<Input
|
||||
colorScheme="blue"
|
||||
variant="filled"
|
||||
placeholder="Your email here"
|
||||
name="email"
|
||||
ref={register({ required: "Email is required!" })}
|
||||
/>
|
||||
<InputRightElement>
|
||||
<CustomIcon icon="name" />
|
||||
</InputRightElement>
|
||||
</InputGroup>
|
||||
<FormErrorMessage color="red.400" pl="1">
|
||||
{errors.email && errors.email.message}
|
||||
</FormErrorMessage>
|
||||
</FormControl>
|
||||
<Button
|
||||
type="submit"
|
||||
variant="solid"
|
||||
colorScheme="blue"
|
||||
width="100%"
|
||||
isLoading={isLoading}
|
||||
>
|
||||
Send
|
||||
</Button>
|
||||
</form>
|
||||
</Modal>
|
||||
<form onSubmit={handleSubmit(forgotPassword)}>
|
||||
<FormControl isInvalid={errors.email} my={4}>
|
||||
<InputGroup>
|
||||
<Input
|
||||
colorScheme="blue"
|
||||
variant="filled"
|
||||
placeholder="Your email here"
|
||||
name="email"
|
||||
ref={register({ required: "Email is required!" })}
|
||||
/>
|
||||
<InputRightElement>
|
||||
<CustomIcon icon="name" />
|
||||
</InputRightElement>
|
||||
</InputGroup>
|
||||
<FormErrorMessage color="red.400" pl="1">
|
||||
{errors.email && errors.email.message}
|
||||
</FormErrorMessage>
|
||||
</FormControl>
|
||||
<Button
|
||||
type="submit"
|
||||
variant="solid"
|
||||
colorScheme="blue"
|
||||
width="100%"
|
||||
isLoading={isLoading}
|
||||
>
|
||||
Send
|
||||
</Button>
|
||||
</form>
|
||||
);
|
||||
};
|
||||
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
import React, { useEffect } from "react";
|
||||
import { Heading, Spinner } from "@chakra-ui/react";
|
||||
import Modal from "./Modal";
|
||||
import { Spinner } from "@chakra-ui/react";
|
||||
import { useToast } from "../core/hooks";
|
||||
import HubspotForm from "react-hubspot-form";
|
||||
import { MODAL_TYPES } from "../core/providers/OverlayProvider/constants";
|
||||
|
||||
const RequestIntegration = ({ toggleModal, title, formId }) => {
|
||||
const RequestIntegration = ({ toggleModal, formId }) => {
|
||||
const toast = useToast();
|
||||
|
||||
useEffect(() => {
|
||||
|
@ -14,7 +14,7 @@ const RequestIntegration = ({ toggleModal, title, formId }) => {
|
|||
event.data.eventName === "onFormSubmitted"
|
||||
) {
|
||||
if (event.data.id === formId) {
|
||||
toggleModal(null);
|
||||
toggleModal(MODAL_TYPES.OFF);
|
||||
toast("Request sent", "success");
|
||||
}
|
||||
}
|
||||
|
@ -28,17 +28,12 @@ const RequestIntegration = ({ toggleModal, title, formId }) => {
|
|||
}, [toast, toggleModal]);
|
||||
|
||||
return (
|
||||
<Modal onClose={() => toggleModal(null)}>
|
||||
<Heading my={2} as="h2" fontSize={["xl", "3xl"]}>
|
||||
{title}
|
||||
</Heading>
|
||||
<HubspotForm
|
||||
region="na1"
|
||||
portalId="8018701"
|
||||
formId={formId}
|
||||
loading={<Spinner colorScheme="blue" speed="1s" />}
|
||||
/>
|
||||
</Modal>
|
||||
<HubspotForm
|
||||
region="na1"
|
||||
portalId="8018701"
|
||||
formId={formId}
|
||||
loading={<Spinner colorScheme="blue" speed="1s" />}
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
||||
|
|
|
@ -16,6 +16,7 @@ import ChakraAccountIconButton from "./AccountIconButton";
|
|||
import RouteButton from "./RouteButton";
|
||||
import { ALL_NAV_PATHES, WHITE_LOGO_W_TEXT_URL } from "../core/constants";
|
||||
import router from "next/router";
|
||||
import { MODAL_TYPES } from "../core/providers/OverlayProvider/constants";
|
||||
|
||||
const LandingNavbar = () => {
|
||||
const ui = useContext(UIContext);
|
||||
|
@ -71,7 +72,7 @@ const LandingNavbar = () => {
|
|||
))}
|
||||
|
||||
{ui.isLoggedIn && (
|
||||
<RouterLink href="/stream" passHref>
|
||||
<RouterLink href="/welcome" passHref>
|
||||
<Button
|
||||
as={Link}
|
||||
colorScheme="orange"
|
||||
|
@ -99,7 +100,7 @@ const LandingNavbar = () => {
|
|||
{!ui.isLoggedIn && (
|
||||
<Button
|
||||
color="white"
|
||||
onClick={() => toggleModal("login")}
|
||||
onClick={() => toggleModal(MODAL_TYPES.LOGIN)}
|
||||
fontWeight="400"
|
||||
>
|
||||
Log in
|
||||
|
|
|
@ -1,29 +0,0 @@
|
|||
/** @jsxRuntime classic */
|
||||
/** @jsx jsx */
|
||||
import { jsx } from "@emotion/react";
|
||||
import { Flex, Image } from "@chakra-ui/react";
|
||||
import CustomIcon from "../CustomIcon";
|
||||
import styles from "./styles";
|
||||
|
||||
const Modal = ({ children, onClose }) => (
|
||||
<Flex onClick={onClose} css={styles.modal} zIndex={100002}>
|
||||
<Flex onClick={(e) => e.stopPropagation()} css={styles.flex}>
|
||||
<Image
|
||||
color="blue.900"
|
||||
height="24px"
|
||||
width="22px"
|
||||
sx={{ filter: "grayscale: 50%" }}
|
||||
fill="blue.800"
|
||||
src={
|
||||
"https://s3.amazonaws.com/static.simiotics.com/moonstream/assets/logo-black.svg"
|
||||
}
|
||||
/>
|
||||
<Flex cursor="pointer" onClick={onClose} css={styles.close}>
|
||||
<CustomIcon height="13px" width="13px" icon="close" />
|
||||
</Flex>
|
||||
{children}
|
||||
</Flex>
|
||||
</Flex>
|
||||
);
|
||||
|
||||
export default Modal;
|
|
@ -1,38 +0,0 @@
|
|||
import { css } from "@emotion/react";
|
||||
|
||||
const styles = {
|
||||
modal: css`
|
||||
position: fixed;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
display: flex;
|
||||
left: 0;
|
||||
top: 0;
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
background: rgba(0, 0, 0, 0.5);
|
||||
`,
|
||||
flex: css`
|
||||
position: relative;
|
||||
background: #ffffff;
|
||||
flex-direction: column;
|
||||
width: 31.25rem;
|
||||
padding: 2.5rem;
|
||||
border-radius: 0.375rem;
|
||||
@media (max-width: 576px) {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
border-radius: 0;
|
||||
}
|
||||
box-shadow: 0 11px 34px 0 rgba(0, 0, 0, 0.15);
|
||||
`,
|
||||
close: css`
|
||||
position: absolute;
|
||||
right: 38px;
|
||||
top: 38px;
|
||||
`,
|
||||
};
|
||||
|
||||
export default styles;
|
|
@ -1,17 +1,12 @@
|
|||
/** @jsxRuntime classic */
|
||||
/** @jsx jsx */
|
||||
import { jsx } from "@emotion/react";
|
||||
import React, { Suspense, useContext } from "react";
|
||||
import { Flex } from "@chakra-ui/react";
|
||||
import UIContext from "../core/providers/UIProvider/context";
|
||||
const ForgotPassword = React.lazy(() => import("./ForgotPassword"));
|
||||
const SignIn = React.lazy(() => import("./SignIn"));
|
||||
|
||||
const LandingNavbar = React.lazy(() => import("./LandingNavbar"));
|
||||
const AppNavbar = React.lazy(() => import("./AppNavbar"));
|
||||
const HubspotForm = React.lazy(() => import("./HubspotForm"));
|
||||
|
||||
const Navbar = () => {
|
||||
const { modal, toggleModal, isAppView, isLoggedIn } = useContext(UIContext);
|
||||
const { isAppView, isLoggedIn } = useContext(UIContext);
|
||||
|
||||
return (
|
||||
<Flex
|
||||
|
@ -26,30 +21,6 @@ const Navbar = () => {
|
|||
overflow="hidden"
|
||||
>
|
||||
<Suspense fallback={""}>
|
||||
{/* {modal === "register" && <SignUp toggleModal={toggleModal} />} */}
|
||||
{modal === "login" && <SignIn toggleModal={toggleModal} />}
|
||||
{modal === "forgot" && <ForgotPassword toggleModal={toggleModal} />}
|
||||
{modal === "hubspot-trader" && (
|
||||
<HubspotForm
|
||||
toggleModal={toggleModal}
|
||||
title={"Join the waitlist"}
|
||||
formId={"29a17405-819b-405d-9563-f75bfb3774e0"}
|
||||
/>
|
||||
)}
|
||||
{modal === "hubspot-fund" && (
|
||||
<HubspotForm
|
||||
toggleModal={toggleModal}
|
||||
title={"Join the waitlist"}
|
||||
formId={"04f0b8df-6b8f-4cd0-871f-4e872523b6f5"}
|
||||
/>
|
||||
)}
|
||||
{modal === "hubspot-developer" && (
|
||||
<HubspotForm
|
||||
toggleModal={toggleModal}
|
||||
title={"Join the waitlist"}
|
||||
formId={"1897f4a1-3a00-475b-9bd5-5ca2725bd720"}
|
||||
/>
|
||||
)}
|
||||
{(!isAppView || !isLoggedIn) && <LandingNavbar />}
|
||||
{isAppView && isLoggedIn && <AppNavbar />}
|
||||
</Suspense>
|
||||
|
|
|
@ -0,0 +1,433 @@
|
|||
import React, { useEffect } from "react";
|
||||
import {
|
||||
chakra,
|
||||
FormLabel,
|
||||
Input,
|
||||
Stack,
|
||||
InputGroup,
|
||||
Box,
|
||||
Button,
|
||||
Table,
|
||||
Th,
|
||||
Td,
|
||||
Tr,
|
||||
Thead,
|
||||
Tbody,
|
||||
Center,
|
||||
Checkbox,
|
||||
CloseButton,
|
||||
InputRightAddon,
|
||||
Badge,
|
||||
InputLeftAddon,
|
||||
} from "@chakra-ui/react";
|
||||
import { CheckCircleIcon } from "@chakra-ui/icons";
|
||||
import { useStorage, useSubscriptions } from "../core/hooks";
|
||||
import Downshift from "downshift";
|
||||
import color from "color";
|
||||
|
||||
const NewDashboard = (props) => {
|
||||
const [newDashboardForm, setNewDashboardForm] = useStorage(
|
||||
sessionStorage,
|
||||
"new_dashboard",
|
||||
{
|
||||
name: "",
|
||||
subscriptions: [
|
||||
{
|
||||
label: "",
|
||||
id: null,
|
||||
isMethods: false,
|
||||
},
|
||||
],
|
||||
}
|
||||
);
|
||||
|
||||
const subscriptions = useSubscriptions();
|
||||
|
||||
const [pickerItems, setPickerItems] = React.useState(
|
||||
subscriptions.subscriptionsCache.data?.subscriptions
|
||||
);
|
||||
|
||||
useEffect(() => {
|
||||
if (!subscriptions.subscriptionsCache.isLoading) {
|
||||
const massaged = subscriptions.subscriptionsCache.data?.subscriptions.map(
|
||||
(item) => {
|
||||
return { value: item.address, ...item };
|
||||
}
|
||||
);
|
||||
setPickerItems(massaged);
|
||||
}
|
||||
}, [
|
||||
subscriptions.subscriptionsCache.data,
|
||||
subscriptions.subscriptionsCache.isLoading,
|
||||
]);
|
||||
|
||||
const filterFn = (item, inputValue) =>
|
||||
item.subscription_type_id === "ethereum_blockchain" &&
|
||||
(!inputValue ||
|
||||
item.address.toUpperCase().includes(inputValue.toUpperCase()) ||
|
||||
item.label.toUpperCase().includes(inputValue.toUpperCase()));
|
||||
|
||||
return (
|
||||
<>
|
||||
<Stack spacing="24px">
|
||||
<Box>
|
||||
<FormLabel htmlFor="name">Name dashboard</FormLabel>
|
||||
<Input
|
||||
ref={props?.firstField}
|
||||
id="name"
|
||||
type="search"
|
||||
placeholder="How new board should be named?"
|
||||
value={newDashboardForm?.name}
|
||||
onChange={(e) =>
|
||||
setNewDashboardForm((prevState) => {
|
||||
return { ...prevState, name: e.target.value };
|
||||
})
|
||||
}
|
||||
/>
|
||||
</Box>
|
||||
|
||||
<Box>
|
||||
<FormLabel htmlFor="Addresses">Address list</FormLabel>
|
||||
<Table
|
||||
borderColor="gray.200"
|
||||
// borderWidth="1px"
|
||||
variant="simple"
|
||||
colorScheme="blue"
|
||||
justifyContent="center"
|
||||
borderBottomRadius="xl"
|
||||
alignItems="baseline"
|
||||
h="auto"
|
||||
size="sm"
|
||||
mt={0}
|
||||
>
|
||||
<Thead>
|
||||
<Tr>
|
||||
<Th>Address</Th>
|
||||
<Th w="90px">ABI State</Th>
|
||||
<Th w="90px">Track ABI</Th>
|
||||
<Th w="60px"></Th>
|
||||
</Tr>
|
||||
</Thead>
|
||||
<Tbody>
|
||||
{newDashboardForm?.subscriptions.map((subscibedItem, idx) => {
|
||||
return (
|
||||
<Tr key={`form-address-row-${idx}`}>
|
||||
<Td>
|
||||
{!subscriptions.subscriptionsCache.isLoading &&
|
||||
subscriptions.subscriptionsCache.data &&
|
||||
pickerItems && (
|
||||
<>
|
||||
<Downshift
|
||||
onSelect={(selectedItem) => {
|
||||
const newState = { ...newDashboardForm };
|
||||
newState.subscriptions[idx] = selectedItem;
|
||||
setNewDashboardForm(newState);
|
||||
}}
|
||||
// isOpen={showSuggestions}
|
||||
itemToString={(item) => (item ? item.label : "")}
|
||||
initialSelectedItem={subscibedItem ?? undefined}
|
||||
>
|
||||
{({
|
||||
getInputProps,
|
||||
getItemProps,
|
||||
getLabelProps,
|
||||
getMenuProps,
|
||||
getToggleButtonProps,
|
||||
isOpen,
|
||||
inputValue,
|
||||
highlightedIndex,
|
||||
// selectedItem,
|
||||
getRootProps,
|
||||
}) => {
|
||||
const labelColor =
|
||||
subscibedItem.color &&
|
||||
color(`${subscibedItem.color}`);
|
||||
return (
|
||||
<Box pos="relative">
|
||||
<Box
|
||||
// style={comboboxStyles}
|
||||
{...getRootProps(
|
||||
{},
|
||||
{ suppressRefError: true }
|
||||
)}
|
||||
>
|
||||
<InputGroup>
|
||||
<InputLeftAddon
|
||||
isTruncated
|
||||
maxW="60px"
|
||||
fontSize="sm"
|
||||
bgColor={
|
||||
subscibedItem?.color ?? "gray.100"
|
||||
}
|
||||
>
|
||||
<FormLabel
|
||||
alignContent="center"
|
||||
my={2}
|
||||
{...getLabelProps()}
|
||||
color={
|
||||
labelColor
|
||||
? labelColor?.isDark()
|
||||
? "white"
|
||||
: labelColor.darken(0.6).hex()
|
||||
: "inherit"
|
||||
}
|
||||
>{`#${idx}:`}</FormLabel>
|
||||
</InputLeftAddon>
|
||||
|
||||
<Input
|
||||
placeholder="Subscription to use in dashboard"
|
||||
isTruncated
|
||||
fontSize="sm"
|
||||
defaultValue={
|
||||
subscibedItem?.label ?? "yoyoy"
|
||||
}
|
||||
{...getInputProps({
|
||||
defaultValue:
|
||||
subscibedItem?.label ?? "iha",
|
||||
})}
|
||||
></Input>
|
||||
<InputRightAddon>
|
||||
{" "}
|
||||
<button
|
||||
{...getToggleButtonProps()}
|
||||
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)
|
||||
).length === 0 && (
|
||||
<Button
|
||||
colorScheme="orange"
|
||||
variant="outline"
|
||||
size="sm"
|
||||
>
|
||||
Set new subscription to:{" "}
|
||||
{inputValue}{" "}
|
||||
</Button>
|
||||
)}
|
||||
{pickerItems &&
|
||||
pickerItems
|
||||
.filter((item) =>
|
||||
filterFn(item, inputValue)
|
||||
)
|
||||
.map((item, index) => {
|
||||
const badgeColor = color(
|
||||
`${item.color}`
|
||||
);
|
||||
|
||||
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"
|
||||
}
|
||||
>
|
||||
<chakra.span whiteSpace="nowrap">
|
||||
{item.label}
|
||||
</chakra.span>
|
||||
<Badge
|
||||
size="sm"
|
||||
placeSelf="self-end"
|
||||
colorScheme={
|
||||
item.hasABI
|
||||
? "green"
|
||||
: "gray"
|
||||
}
|
||||
>
|
||||
ABI
|
||||
</Badge>
|
||||
<Badge
|
||||
isTruncated
|
||||
size="sm"
|
||||
placeSelf="self-end"
|
||||
bgColor={item.color}
|
||||
color={
|
||||
badgeColor.isDark()
|
||||
? badgeColor
|
||||
.lighten(100)
|
||||
.hex()
|
||||
: badgeColor
|
||||
.darken(0.6)
|
||||
.hex()
|
||||
}
|
||||
>
|
||||
{item.address}
|
||||
</Badge>
|
||||
</Stack>
|
||||
);
|
||||
})}
|
||||
</Stack>
|
||||
) : null}
|
||||
{/* </Menu> */}
|
||||
</Box>
|
||||
);
|
||||
}}
|
||||
</Downshift>
|
||||
</>
|
||||
// <AutoComplete
|
||||
// openOnFocus
|
||||
// creatable
|
||||
// suggestWhenEmpty
|
||||
// >
|
||||
// <AutoCompleteInput variant="filled" />
|
||||
// <AutoCompleteList>
|
||||
// {pickerItems?.map((subscription, oid) => (
|
||||
// <AutoCompleteItem
|
||||
// key={`row-${idx}-option-${oid}`}
|
||||
// value={subscription.address}
|
||||
// textTransform="capitalize"
|
||||
// align="center"
|
||||
// >
|
||||
// {/* <Avatar
|
||||
// size="sm"
|
||||
// // name={person.name}
|
||||
// // src={person.image}
|
||||
// /> */}
|
||||
// <Text ml="4">{subscription.label}</Text>
|
||||
// </AutoCompleteItem>
|
||||
// ))}
|
||||
// {/* <AutoCompleteCreatable>
|
||||
// {({ value }) => (
|
||||
// <span>New Subscription: {value}</span>
|
||||
// )}
|
||||
// </AutoCompleteCreatable> */}
|
||||
// </AutoCompleteList>
|
||||
// </AutoComplete>
|
||||
)}
|
||||
</Td>
|
||||
<Td w="90px">
|
||||
{subscibedItem.hasABI && subscibedItem.address && (
|
||||
<CheckCircleIcon color="green" />
|
||||
)}
|
||||
{!subscibedItem.hasABI && (
|
||||
<Button
|
||||
colorScheme="orange"
|
||||
size="xs"
|
||||
py={2}
|
||||
disabled={!subscibedItem.address}
|
||||
>
|
||||
Upload
|
||||
</Button>
|
||||
)}
|
||||
</Td>
|
||||
|
||||
<Td w="60px">
|
||||
<Checkbox
|
||||
isDisabled={
|
||||
!subscibedItem.address || !subscibedItem.hasABI
|
||||
}
|
||||
isChecked={subscibedItem.isMethods}
|
||||
></Checkbox>
|
||||
</Td>
|
||||
|
||||
<Td>
|
||||
{idx > 0 && (
|
||||
<CloseButton
|
||||
onClick={() => {
|
||||
const hardcopy = [
|
||||
...newDashboardForm?.subscriptions,
|
||||
];
|
||||
hardcopy.splice(idx, 1);
|
||||
setNewDashboardForm((prevState) => {
|
||||
return {
|
||||
...prevState,
|
||||
subscriptions: [...hardcopy],
|
||||
};
|
||||
});
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
</Td>
|
||||
</Tr>
|
||||
);
|
||||
})}
|
||||
</Tbody>
|
||||
</Table>
|
||||
<Center>
|
||||
<Button
|
||||
w="100px"
|
||||
colorScheme="gray"
|
||||
variant="solid"
|
||||
p={0}
|
||||
maxH="1.25rem"
|
||||
_active={{ textDecor: "none" }}
|
||||
onClick={() => {
|
||||
const newState = { ...newDashboardForm };
|
||||
newState.subscriptions.push({
|
||||
label: "",
|
||||
id: null,
|
||||
isMethods: false,
|
||||
});
|
||||
setNewDashboardForm(newState);
|
||||
}}
|
||||
>
|
||||
+
|
||||
</Button>
|
||||
</Center>
|
||||
</Box>
|
||||
|
||||
{/* <Box>
|
||||
<FormLabel htmlFor="desc">ABI</FormLabel>
|
||||
<Textarea
|
||||
id="desc"
|
||||
placeholder="ABI Upload element should be here instead"
|
||||
/>
|
||||
</Box> */}
|
||||
</Stack>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
const ChakraNewDashboard = chakra(NewDashboard);
|
||||
|
||||
export default ChakraNewDashboard;
|
|
@ -17,10 +17,10 @@ import {
|
|||
ArrowRightIcon,
|
||||
LockIcon,
|
||||
} from "@chakra-ui/icons";
|
||||
import { MdTimeline, MdSettings } from "react-icons/md";
|
||||
import { ImStatsBars } from "react-icons/im";
|
||||
import { MdSettings } from "react-icons/md";
|
||||
import { HiAcademicCap } from "react-icons/hi";
|
||||
import { WHITE_LOGO_W_TEXT_URL } from "../core/constants";
|
||||
import { MODAL_TYPES } from "../core/providers/OverlayProvider/constants";
|
||||
|
||||
const Sidebar = () => {
|
||||
const ui = useContext(UIContext);
|
||||
|
@ -68,24 +68,8 @@ const Sidebar = () => {
|
|||
</SidebarHeader>
|
||||
{ui.isLoggedIn && (
|
||||
<SidebarContent>
|
||||
<Menu iconShape="square">
|
||||
<MenuItem icon={<MdTimeline />}>
|
||||
{" "}
|
||||
<RouterLink href="/stream">Stream</RouterLink>
|
||||
</MenuItem>
|
||||
</Menu>
|
||||
<Menu iconShape="square">
|
||||
<MenuItem icon={<ImStatsBars />}>
|
||||
{" "}
|
||||
<RouterLink href="/analytics">Analytics </RouterLink>
|
||||
</MenuItem>
|
||||
</Menu>
|
||||
<Menu iconShape="square">
|
||||
<MenuItem icon={<MdSettings />}>
|
||||
{" "}
|
||||
<RouterLink href="/subscriptions">Subscriptions </RouterLink>
|
||||
</MenuItem>
|
||||
</Menu>
|
||||
<Menu iconShape="square"></Menu>
|
||||
<Menu iconShape="square"></Menu>
|
||||
{ui.isMobileView && (
|
||||
<Menu iconShape="square">
|
||||
<MenuItem icon={<HiAcademicCap />}>
|
||||
|
@ -112,7 +96,7 @@ const Sidebar = () => {
|
|||
<Menu iconShape="square">
|
||||
<MenuItem
|
||||
onClick={() => {
|
||||
ui.toggleModal("login");
|
||||
ui.toggleModal(MODAL_TYPES.LOGIN);
|
||||
ui.setSidebarToggled(false);
|
||||
}}
|
||||
>
|
||||
|
@ -137,6 +121,10 @@ const Sidebar = () => {
|
|||
<MenuItem icon={<LockIcon />}>
|
||||
<RouterLink href="/account/tokens">API Tokens</RouterLink>
|
||||
</MenuItem>
|
||||
<MenuItem icon={<MdSettings />}>
|
||||
{" "}
|
||||
<RouterLink href="/subscriptions">Subscriptions </RouterLink>
|
||||
</MenuItem>
|
||||
</Menu>
|
||||
)}
|
||||
</SidebarFooter>
|
||||
|
|
|
@ -1,10 +1,6 @@
|
|||
/** @jsxRuntime classic */
|
||||
/** @jsx jsx */
|
||||
import { jsx } from "@emotion/react";
|
||||
import { useEffect } from "react";
|
||||
import React, { useEffect } from "react";
|
||||
import { useForm } from "react-hook-form";
|
||||
import {
|
||||
Heading,
|
||||
Text,
|
||||
Stack,
|
||||
Box,
|
||||
|
@ -19,7 +15,7 @@ import {
|
|||
import CustomIcon from "./CustomIcon";
|
||||
import { useLogin } from "../core/hooks";
|
||||
import PasswordInput from "./PasswordInput";
|
||||
import Modal from "./Modal";
|
||||
import { MODAL_TYPES } from "../core/providers/OverlayProvider/constants";
|
||||
|
||||
const SignIn = ({ toggleModal }) => {
|
||||
const { handleSubmit, errors, register } = useForm();
|
||||
|
@ -30,14 +26,11 @@ const SignIn = ({ toggleModal }) => {
|
|||
return;
|
||||
}
|
||||
|
||||
toggleModal(null);
|
||||
toggleModal(MODAL_TYPES.OFF);
|
||||
}, [data, toggleModal]);
|
||||
|
||||
return (
|
||||
<Modal onClose={() => toggleModal(null)}>
|
||||
<Heading mt={2} size="md">
|
||||
Login now
|
||||
</Heading>
|
||||
<>
|
||||
<Text color="gray.1200" fontSize="md">
|
||||
To your Moonstream account
|
||||
</Text>
|
||||
|
@ -91,7 +84,7 @@ const SignIn = ({ toggleModal }) => {
|
|||
cursor="pointer"
|
||||
color="blue.800"
|
||||
as="span"
|
||||
onClick={() => toggleModal("forgot")}
|
||||
onClick={() => toggleModal(MODAL_TYPES.FORGOT)}
|
||||
>
|
||||
Forgot your password?
|
||||
</Box>
|
||||
|
@ -112,7 +105,7 @@ const SignIn = ({ toggleModal }) => {
|
|||
Register
|
||||
</Box> */}
|
||||
</Text>
|
||||
</Modal>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
|
|
|
@ -4,7 +4,6 @@ import { jsx } from "@emotion/react";
|
|||
import { useContext, useEffect } from "react";
|
||||
import { useForm } from "react-hook-form";
|
||||
import {
|
||||
Heading,
|
||||
Text,
|
||||
Stack,
|
||||
Box,
|
||||
|
@ -17,9 +16,9 @@ import {
|
|||
} from "@chakra-ui/react";
|
||||
import CustomIcon from "./CustomIcon";
|
||||
import { useSignUp } from "../core/hooks";
|
||||
import Modal from "./Modal";
|
||||
import PasswordInput from "./PasswordInput";
|
||||
import UIContext from "../core/providers/UIProvider/context";
|
||||
import { MODAL_TYPES } from "../core/providers/OverlayProvider/constants";
|
||||
|
||||
const SignUp = ({ toggleModal }) => {
|
||||
const { handleSubmit, errors, register } = useForm();
|
||||
|
@ -28,15 +27,12 @@ const SignUp = ({ toggleModal }) => {
|
|||
|
||||
useEffect(() => {
|
||||
if (isSuccess) {
|
||||
ui.toggleModal(null);
|
||||
ui.toggleModal(MODAL_TYPES.OFF);
|
||||
}
|
||||
}, [isSuccess, toggleModal, ui]);
|
||||
|
||||
return (
|
||||
<Modal onClose={() => ui.toggleModal(null)}>
|
||||
<Heading mt={2} size="md">
|
||||
Create an account
|
||||
</Heading>
|
||||
<>
|
||||
<Text color="gray.1200" fontSize="md">
|
||||
Sign up for free
|
||||
</Text>
|
||||
|
@ -105,12 +101,12 @@ const SignUp = ({ toggleModal }) => {
|
|||
cursor="pointer"
|
||||
color="blue.400"
|
||||
as="span"
|
||||
onClick={() => toggleModal("login")}
|
||||
onClick={() => toggleModal(MODAL_TYPES.LOGIN)}
|
||||
>
|
||||
Login
|
||||
</Box>
|
||||
</Text>
|
||||
</Modal>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
import ModalContext from "../providers/ModalProvider/context";
|
||||
import OverlayContext from "../providers/OverlayProvider/context";
|
||||
import { useContext } from "react";
|
||||
|
||||
const useModals = () => {
|
||||
const modals = useContext(ModalContext);
|
||||
const modals = useContext(OverlayContext);
|
||||
|
||||
return modals;
|
||||
};
|
||||
|
|
|
@ -1,5 +0,0 @@
|
|||
import { createContext } from "react";
|
||||
|
||||
const ModalContext = createContext();
|
||||
|
||||
export default ModalContext;
|
|
@ -1,13 +0,0 @@
|
|||
import React, { useState } from "react";
|
||||
import ModalContext from "./context";
|
||||
|
||||
const ModalProvider = ({ children }) => {
|
||||
const [modal, toggleModal] = useState();
|
||||
return (
|
||||
<ModalContext.Provider value={{ modal, toggleModal }}>
|
||||
{children}
|
||||
</ModalContext.Provider>
|
||||
);
|
||||
};
|
||||
|
||||
export default ModalProvider;
|
|
@ -0,0 +1,20 @@
|
|||
export const MODAL_TYPES = {
|
||||
OFF: 0,
|
||||
LOGIN: 1,
|
||||
SIGNUP: 2,
|
||||
FORGOT: 3,
|
||||
VERIFY: 4,
|
||||
CONFIRM: 5,
|
||||
HUBSPOT: 6,
|
||||
NEW_SUBSCRIPTON: 7,
|
||||
};
|
||||
|
||||
export const DRAWER_TYPES = {
|
||||
OFF: 0,
|
||||
NEW_DASHBOARD: 1,
|
||||
};
|
||||
|
||||
export const ALERT_TYPES = {
|
||||
OFF: 0,
|
||||
CLOSE_DRAWER: 1,
|
||||
};
|
|
@ -0,0 +1,5 @@
|
|||
import { createContext } from "react";
|
||||
|
||||
const OverlayContext = createContext();
|
||||
|
||||
export default OverlayContext;
|
|
@ -0,0 +1,234 @@
|
|||
import React, { useState, useLayoutEffect, useContext, Suspense } from "react";
|
||||
import OverlayContext from "./context";
|
||||
import { MODAL_TYPES, DRAWER_TYPES } from "./constants";
|
||||
import {
|
||||
Modal,
|
||||
ModalOverlay,
|
||||
ModalCloseButton,
|
||||
ModalBody,
|
||||
ModalContent,
|
||||
useDisclosure,
|
||||
ModalHeader,
|
||||
Drawer,
|
||||
DrawerBody,
|
||||
DrawerFooter,
|
||||
DrawerHeader,
|
||||
DrawerOverlay,
|
||||
DrawerContent,
|
||||
DrawerCloseButton,
|
||||
AlertDialog,
|
||||
AlertDialogBody,
|
||||
AlertDialogFooter,
|
||||
AlertDialogHeader,
|
||||
AlertDialogContent,
|
||||
AlertDialogOverlay,
|
||||
Button,
|
||||
Spinner,
|
||||
} from "@chakra-ui/react";
|
||||
import UserContext from "../UserProvider/context";
|
||||
import UIContext from "../UIProvider/context";
|
||||
const ForgotPassword = React.lazy(() =>
|
||||
import("../../../components/ForgotPassword")
|
||||
);
|
||||
const SignIn = React.lazy(() => import("../../../components/SignIn"));
|
||||
const HubspotForm = React.lazy(() => import("../../../components/HubspotForm"));
|
||||
const NewDashboard = React.lazy(() =>
|
||||
import("../../../components/NewDashboard")
|
||||
);
|
||||
const NewSubscription = React.lazy(() =>
|
||||
import("../../../components/NewSubscription")
|
||||
);
|
||||
|
||||
const OverlayProvider = ({ children }) => {
|
||||
const ui = useContext(UIContext);
|
||||
const { user } = useContext(UserContext);
|
||||
const [modal, toggleModal] = useState(MODAL_TYPES.OFF);
|
||||
const [drawer, toggleDrawer] = useState(DRAWER_TYPES.OFF);
|
||||
const [alertCallback, setAlertCallback] = useState(null);
|
||||
const drawerDisclosure = useDisclosure();
|
||||
const modalDisclosure = useDisclosure();
|
||||
const alertDisclosure = useDisclosure();
|
||||
|
||||
useLayoutEffect(() => {
|
||||
if (modal === MODAL_TYPES.OFF && modalDisclosure.isOpen) {
|
||||
modalDisclosure.onClose();
|
||||
} else if (modal !== MODAL_TYPES.OFF && !modalDisclosure.isOpen) {
|
||||
modalDisclosure.onOpen();
|
||||
}
|
||||
}, [modal, modalDisclosure]);
|
||||
|
||||
useLayoutEffect(() => {
|
||||
if (drawer === DRAWER_TYPES.OFF && drawerDisclosure.isOpen) {
|
||||
drawerDisclosure.onClose();
|
||||
} else if (drawer !== DRAWER_TYPES.OFF && !drawerDisclosure.isOpen) {
|
||||
drawerDisclosure.onOpen();
|
||||
}
|
||||
}, [drawer, drawerDisclosure]);
|
||||
|
||||
const handleAlertConfirm = () => {
|
||||
alertCallback && alertCallback();
|
||||
alertDisclosure.onClose();
|
||||
};
|
||||
|
||||
const toggleAlert = (callback) => {
|
||||
setAlertCallback(() => callback);
|
||||
alertDisclosure.onOpen();
|
||||
};
|
||||
|
||||
console.assert(
|
||||
Object.values(DRAWER_TYPES).some((element) => element === drawer)
|
||||
);
|
||||
console.assert(
|
||||
Object.values(MODAL_TYPES).some((element) => element === modal)
|
||||
);
|
||||
|
||||
const cancelRef = React.useRef();
|
||||
const firstField = React.useRef();
|
||||
|
||||
useLayoutEffect(() => {
|
||||
if (
|
||||
ui.isAppView &&
|
||||
ui.isInit &&
|
||||
!user?.username &&
|
||||
!ui.isLoggingOut &&
|
||||
!ui.isLoggingIn &&
|
||||
!modal
|
||||
) {
|
||||
toggleModal(MODAL_TYPES.LOGIN);
|
||||
} else if (user && ui.isLoggingOut) {
|
||||
toggleModal(MODAL_TYPES.OFF);
|
||||
}
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [ui.isAppView, ui.isAppReady, user, ui.isLoggingOut, modal]);
|
||||
|
||||
return (
|
||||
<OverlayContext.Provider
|
||||
value={{ modal, toggleModal, drawer, toggleDrawer }}
|
||||
>
|
||||
<AlertDialog
|
||||
isOpen={alertDisclosure.isOpen}
|
||||
leastDestructiveRef={cancelRef}
|
||||
// onClose={onClose}
|
||||
>
|
||||
<AlertDialogOverlay>
|
||||
<AlertDialogContent>
|
||||
<AlertDialogHeader fontSize="lg" fontWeight="bold">
|
||||
Cancel
|
||||
</AlertDialogHeader>
|
||||
|
||||
<AlertDialogBody>Are you sure you want to cancel?</AlertDialogBody>
|
||||
|
||||
<AlertDialogFooter>
|
||||
<Button ref={cancelRef} onClick={() => alertDisclosure.onClose()}>
|
||||
Cancel
|
||||
</Button>
|
||||
<Button
|
||||
colorScheme="red"
|
||||
ml={3}
|
||||
onClick={() => {
|
||||
handleAlertConfirm();
|
||||
}}
|
||||
>
|
||||
Confirm
|
||||
</Button>
|
||||
</AlertDialogFooter>
|
||||
</AlertDialogContent>
|
||||
</AlertDialogOverlay>
|
||||
</AlertDialog>
|
||||
|
||||
<Modal
|
||||
isOpen={modalDisclosure.isOpen}
|
||||
onClose={() => toggleModal(MODAL_TYPES.OFF)}
|
||||
size="2xl"
|
||||
scrollBehavior="outside"
|
||||
trapFocus={false}
|
||||
>
|
||||
<ModalOverlay />
|
||||
|
||||
<ModalContent>
|
||||
<ModalHeader>
|
||||
{modal === MODAL_TYPES.NEW_SUBSCRIPTON &&
|
||||
"Subscribe to a new address"}
|
||||
{modal === MODAL_TYPES.FORGOT && "Forgot Password"}
|
||||
{modal === MODAL_TYPES.HUBSPOT && "Join the waitlist"}
|
||||
{modal === MODAL_TYPES.LOGIN && "Login now"}
|
||||
{modal === MODAL_TYPES.SIGNUP && "Create an account"}
|
||||
</ModalHeader>
|
||||
<ModalCloseButton />
|
||||
<ModalBody zIndex={100002}>
|
||||
<Suspense fallback={<Spinner />}>
|
||||
{modal === MODAL_TYPES.NEW_SUBSCRIPTON && (
|
||||
<NewSubscription
|
||||
onClose={() => toggleModal(MODAL_TYPES.OFF)}
|
||||
isModal={true}
|
||||
/>
|
||||
)}
|
||||
{modal === MODAL_TYPES.FORGOT && <ForgotPassword />}
|
||||
{modal === MODAL_TYPES.HUBSPOT && (
|
||||
<HubspotForm
|
||||
toggleModal={toggleModal}
|
||||
title={"Join the waitlist"}
|
||||
formId={"1897f4a1-3a00-475b-9bd5-5ca2725bd720"}
|
||||
/>
|
||||
)}
|
||||
{modal === MODAL_TYPES.LOGIN && (
|
||||
<SignIn toggleModal={toggleModal} />
|
||||
)}
|
||||
{
|
||||
modal === MODAL_TYPES.SIGNUP && ""
|
||||
// <SignUp toggleModal={toggleModal} />
|
||||
}
|
||||
</Suspense>
|
||||
</ModalBody>
|
||||
</ModalContent>
|
||||
</Modal>
|
||||
{/* )} */}
|
||||
<Drawer
|
||||
isOpen={drawerDisclosure.isOpen}
|
||||
placement="right"
|
||||
size="xl"
|
||||
// w="80%"
|
||||
initialFocusRef={firstField}
|
||||
onClose={() => toggleAlert(() => toggleDrawer(DRAWER_TYPES.OFF))}
|
||||
>
|
||||
<DrawerOverlay />
|
||||
<DrawerContent>
|
||||
<DrawerCloseButton />
|
||||
<DrawerHeader borderBottomWidth="1px">
|
||||
{DRAWER_TYPES.NEW_DASHBOARD && "New dashboard"}
|
||||
</DrawerHeader>
|
||||
|
||||
<DrawerBody>
|
||||
{DRAWER_TYPES.NEW_DASHBOARD && (
|
||||
<Suspense fallback={<Spinner />}>
|
||||
<NewDashboard firstField={firstField} />
|
||||
</Suspense>
|
||||
)}
|
||||
</DrawerBody>
|
||||
<DrawerFooter borderTopWidth="1px">
|
||||
<Button
|
||||
variant="outline"
|
||||
mr={3}
|
||||
onClick={() => toggleAlert(() => toggleDrawer(DRAWER_TYPES.OFF))}
|
||||
>
|
||||
Cancel
|
||||
</Button>
|
||||
<Button
|
||||
colorScheme="blue"
|
||||
onClick={() => {
|
||||
//TODO: @Peersky Implement logic part
|
||||
console.log("submit clicked");
|
||||
}}
|
||||
>
|
||||
Submit
|
||||
</Button>
|
||||
</DrawerFooter>
|
||||
</DrawerContent>
|
||||
</Drawer>
|
||||
|
||||
{children}
|
||||
</OverlayContext.Provider>
|
||||
);
|
||||
};
|
||||
|
||||
export default OverlayProvider;
|
|
@ -9,7 +9,6 @@ import { useBreakpointValue } from "@chakra-ui/react";
|
|||
import { useStorage, useQuery, useRouter } from "../../hooks";
|
||||
import UIContext from "./context";
|
||||
import UserContext from "../UserProvider/context";
|
||||
import ModalContext from "../ModalProvider/context";
|
||||
import { v4 as uuid4 } from "uuid";
|
||||
import { PreferencesService } from "../../services";
|
||||
|
||||
|
@ -41,7 +40,6 @@ const UIProvider = ({ children }) => {
|
|||
});
|
||||
// const isMobileView = true;
|
||||
|
||||
const { modal, toggleModal } = useContext(ModalContext);
|
||||
const [searchTerm, setSearchTerm] = useQuery("q", "", true, false);
|
||||
|
||||
const [searchBarActive, setSearchBarActive] = useState(false);
|
||||
|
@ -57,22 +55,6 @@ const UIProvider = ({ children }) => {
|
|||
const [isAppReady, setAppReady] = useState(false);
|
||||
const [isAppView, setAppView] = useState(false);
|
||||
|
||||
useLayoutEffect(() => {
|
||||
if (
|
||||
isAppView &&
|
||||
isInit &&
|
||||
!user?.username &&
|
||||
!isLoggingOut &&
|
||||
!isLoggingIn &&
|
||||
!modal
|
||||
) {
|
||||
toggleModal("login");
|
||||
} else if (user || isLoggingOut) {
|
||||
toggleModal(false);
|
||||
}
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [isAppView, isAppReady, user, isLoggingOut, modal]);
|
||||
|
||||
useEffect(() => {
|
||||
if (isLoggingOut && !isAppView && user) {
|
||||
setLoggingOut(false);
|
||||
|
@ -269,8 +251,6 @@ const UIProvider = ({ children }) => {
|
|||
// eslint-disable-next-line
|
||||
}, [onboardingStep, router.nextRouter.pathname, user, isAppReady]);
|
||||
|
||||
// ********************************************************
|
||||
|
||||
useEffect(() => {
|
||||
if (
|
||||
isInit &&
|
||||
|
@ -293,6 +273,14 @@ const UIProvider = ({ children }) => {
|
|||
onboardingRedirectCheckPassed,
|
||||
]);
|
||||
|
||||
//***************Overlay's states ************************/
|
||||
// const [newDashboardForm, setNewDashboardForm] = useStorage(
|
||||
// window.sessionStorage,
|
||||
// "newDashboardForm",
|
||||
// null
|
||||
// );
|
||||
const [newDashboardForm, setNewDashboardForm] = useState();
|
||||
|
||||
return (
|
||||
<UIContext.Provider
|
||||
value={{
|
||||
|
@ -314,8 +302,6 @@ const UIProvider = ({ children }) => {
|
|||
isAppReady,
|
||||
entriesViewMode,
|
||||
setEntryDetailView,
|
||||
modal,
|
||||
toggleModal,
|
||||
sessionId,
|
||||
currentTransaction,
|
||||
setCurrentTransaction,
|
||||
|
@ -329,6 +315,8 @@ const UIProvider = ({ children }) => {
|
|||
isLoggingOut,
|
||||
isLoggingIn,
|
||||
setLoggingIn,
|
||||
newDashboardForm,
|
||||
setNewDashboardForm,
|
||||
}}
|
||||
>
|
||||
{children}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
export { default as AnalyticsProvider } from "./AnalyticsProvider";
|
||||
export { default as JournalsProvider } from "./DataProvider";
|
||||
export { default as ModalProvider } from "./ModalProvider";
|
||||
export { default as OverlayProvider } from "./OverlayProvider";
|
||||
export { default as StripeProvider } from "./StripeProvider";
|
||||
export { default as UserProvider } from "./UserProvider";
|
||||
export { default as UIProvider } from "./UIProvider";
|
||||
|
|
Ładowanie…
Reference in New Issue