From 776d00fb0d5a7a15ca420ac267699f9b4ba9bda0 Mon Sep 17 00:00:00 2001 From: kompotkot Date: Wed, 18 Aug 2021 09:46:34 +0000 Subject: [PATCH 01/13] Unique const for addr in ethereum_address table --- .../ea8185bd24c7_unique_const_for_addr.py | 32 +++++++++++++++++++ db/moonstreamdb/models.py | 2 +- 2 files changed, 33 insertions(+), 1 deletion(-) create mode 100644 db/alembic/versions/ea8185bd24c7_unique_const_for_addr.py diff --git a/db/alembic/versions/ea8185bd24c7_unique_const_for_addr.py b/db/alembic/versions/ea8185bd24c7_unique_const_for_addr.py new file mode 100644 index 00000000..40a7c9bc --- /dev/null +++ b/db/alembic/versions/ea8185bd24c7_unique_const_for_addr.py @@ -0,0 +1,32 @@ +"""Unique const for addr + +Revision ID: ea8185bd24c7 +Revises: 40871a7807f6 +Create Date: 2021-08-18 09:41:00.512462 + +""" +from alembic import op +import sqlalchemy as sa + + +# revision identifiers, used by Alembic. +revision = 'ea8185bd24c7' +down_revision = '40871a7807f6' +branch_labels = None +depends_on = None + + +def upgrade(): + # ### commands auto generated by Alembic - please adjust! ### + op.drop_index('ix_ethereum_addresses_address', table_name='ethereum_addresses') + op.create_index(op.f('ix_ethereum_addresses_address'), 'ethereum_addresses', ['address'], unique=True) + op.create_unique_constraint(op.f('uq_ethereum_labels_id'), 'ethereum_labels', ['id']) + # ### end Alembic commands ### + + +def downgrade(): + # ### commands auto generated by Alembic - please adjust! ### + op.drop_constraint(op.f('uq_ethereum_labels_id'), 'ethereum_labels', type_='unique') + op.drop_index(op.f('ix_ethereum_addresses_address'), table_name='ethereum_addresses') + op.create_index('ix_ethereum_addresses_address', 'ethereum_addresses', ['address'], unique=False) + # ### end Alembic commands ### diff --git a/db/moonstreamdb/models.py b/db/moonstreamdb/models.py index 4ed85bf7..3114133f 100644 --- a/db/moonstreamdb/models.py +++ b/db/moonstreamdb/models.py @@ -113,7 +113,7 @@ class EthereumAddress(Base): # type: ignore nullable=True, index=True, ) - address = Column(VARCHAR(256), nullable=False, index=True) + address = Column(VARCHAR(256), nullable=False, unique=True, index=True) created_at = Column( DateTime(timezone=True), server_default=utcnow(), nullable=False ) From bceb66f900708cccd45812507ab4164d20893d5f Mon Sep 17 00:00:00 2001 From: Tim Pechersky Date: Wed, 18 Aug 2021 14:29:38 +0200 Subject: [PATCH 02/13] tooltip, spinner theme support --- frontend/src/Theme/Spinner/index.js | 43 +++++++++++++++++++++------ frontend/src/Theme/Tooltip/index.js | 46 +++++++++++++++++++++++++++++ frontend/src/Theme/theme.js | 4 +++ 3 files changed, 84 insertions(+), 9 deletions(-) create mode 100644 frontend/src/Theme/Tooltip/index.js diff --git a/frontend/src/Theme/Spinner/index.js b/frontend/src/Theme/Spinner/index.js index f9c7e4b6..4917150d 100644 --- a/frontend/src/Theme/Spinner/index.js +++ b/frontend/src/Theme/Spinner/index.js @@ -1,13 +1,38 @@ -const Spinner = { - baseStyle: { - color: "primary.400", - thickness: "4px", - speed: "1.5s", - my: 8, +const baseStyle = { + color: "primary.400", + thickness: "4px", + speed: "1.5s", + my: 8, +}; +const variants = { + basic: { thickness: "4px", speed: "1.5s" }, +}; + +const sizes = { + xs: { + "--spinner-size": "0.75rem", }, - variants: { - basic: { thickness: "4px", speed: "1.5s" }, + sm: { + "--spinner-size": "1rem", + }, + md: { + "--spinner-size": "1.5rem", + }, + lg: { + "--spinner-size": "2rem", + }, + xl: { + "--spinner-size": "3rem", }, }; -export default Spinner; +const defaultProps = { + size: "md", +}; + +export default { + baseStyle, + sizes, + defaultProps, + variants, +}; diff --git a/frontend/src/Theme/Tooltip/index.js b/frontend/src/Theme/Tooltip/index.js new file mode 100644 index 00000000..94c8b27a --- /dev/null +++ b/frontend/src/Theme/Tooltip/index.js @@ -0,0 +1,46 @@ +import { mode } from "@chakra-ui/theme-tools"; + +const baseStyle = (props) => { + const bg = mode("gray.700", "gray.300")(props); + return { + "--tooltip-bg": `colors.${bg}`, + px: "8px", + py: "2px", + bg: "var(--tooltip-bg)", + "--popper-arrow-bg": "var(--tooltip-bg)", + color: mode("whiteAlpha.900", "gray.900")(props), + borderRadius: "sm", + fontWeight: "medium", + fontSize: "sm", + boxShadow: "md", + maxW: "320px", + zIndex: "tooltip", + }; +}; + +const variantOnboarding = (props) => { + const bg = mode("secondary.700", "secondary.300")(props); + return { + "--tooltip-bg": `colors.${bg}`, + px: "8px", + py: "2px", + bg: "var(--tooltip-bg)", + "--popper-arrow-bg": "var(--tooltip-bg)", + color: mode("whiteAlpha.900", "gray.900")(props), + borderRadius: "md", + fontWeight: "medium", + fontSize: "sm", + boxShadow: "md", + maxW: "320px", + zIndex: "tooltip", + }; +}; + +const variants = { + onboarding: variantOnboarding, +}; + +export default { + baseStyle, + variants, +}; diff --git a/frontend/src/Theme/theme.js b/frontend/src/Theme/theme.js index b9f0e88a..40f70a1f 100644 --- a/frontend/src/Theme/theme.js +++ b/frontend/src/Theme/theme.js @@ -8,6 +8,8 @@ import NumberInput from "./NumberInput"; import Badge from "./Badge"; import Checkbox from "./Checkbox"; import Table from "./Table"; +import Tooltip from "./Tooltip"; +import Spinner from "./Spinner"; import { createBreakpoints } from "@chakra-ui/theme-tools"; const breakpointsCustom = createBreakpoints({ @@ -53,6 +55,8 @@ const theme = extendTheme({ Badge, Checkbox, Table, + Spinner, + Tooltip, }, fonts: { From eb8f5be087cfb7345b576a33e78412b0825b56a0 Mon Sep 17 00:00:00 2001 From: Tim Pechersky Date: Wed, 18 Aug 2021 14:30:42 +0200 Subject: [PATCH 03/13] newSubscription can be not modal (dplicate code) --- frontend/pages/subscriptions.js | 2 +- .../src/components/NewModalSubscripton.js | 177 +++++++++++++++ frontend/src/components/NewSubscription.js | 211 ++++++++++-------- 3 files changed, 291 insertions(+), 99 deletions(-) create mode 100644 frontend/src/components/NewModalSubscripton.js diff --git a/frontend/pages/subscriptions.js b/frontend/pages/subscriptions.js index 5a9cbb5e..fe0724cd 100644 --- a/frontend/pages/subscriptions.js +++ b/frontend/pages/subscriptions.js @@ -15,7 +15,7 @@ import { ModalOverlay, ModalContent, } from "@chakra-ui/react"; -import NewSubscription from "../src/components/NewSubscription"; +import NewSubscription from "../src/components/NewModalSubscripton"; import { AiOutlinePlusCircle } from "react-icons/ai"; const Subscriptions = () => { diff --git a/frontend/src/components/NewModalSubscripton.js b/frontend/src/components/NewModalSubscripton.js new file mode 100644 index 00000000..14b1536c --- /dev/null +++ b/frontend/src/components/NewModalSubscripton.js @@ -0,0 +1,177 @@ +import React, { useState, useEffect } from "react"; +import { useSubscriptions } from "../core/hooks"; +import { + Input, + Stack, + Text, + HStack, + useRadioGroup, + FormControl, + FormErrorMessage, + ModalBody, + ModalCloseButton, + ModalHeader, + Button, + ModalFooter, + Spinner, + IconButton, +} from "@chakra-ui/react"; +import RadioCard from "./RadioCard"; +import { useForm } from "react-hook-form"; +import { GithubPicker } from "react-color"; +import { BiRefresh } from "react-icons/bi"; +import { makeColor } from "../core/utils/makeColor"; +const NewSubscription = ({ isFreeOption, onClose }) => { + const [color, setColor] = useState(makeColor()); + const { typesCache, createSubscription } = useSubscriptions(); + const { handleSubmit, errors, register } = useForm({}); + const [radioState, setRadioState] = useState("ethereum_blockchain"); + let { getRootProps, getRadioProps } = useRadioGroup({ + name: "type", + defaultValue: radioState, + onChange: setRadioState, + }); + + const group = getRootProps(); + + useEffect(() => { + if (createSubscription.isSuccess) { + onClose(); + } + }, [createSubscription.isSuccess, onClose]); + + if (typesCache.isLoading) return ; + + const createSubscriptionWrap = (props) => { + createSubscription.mutate({ + ...props, + color: color, + type: isFreeOption ? "free" : radioState, + }); + }; + + const handleChangeColorComplete = (color) => { + setColor(color.hex); + }; + + return ( +
+ Subscribe to a new address + + + + + + {errors.label && errors.label.message} + + + + + + {errors.address && errors.address.message} + + + + + {isFreeOption + ? `Free subscription is only availible Ethereum blockchain source` + : `On which source?`} + + + + + {typesCache.data.subscriptions.map((type) => { + const radio = getRadioProps({ + value: type.id, + isDisabled: + !type.active || + (isFreeOption && + type.subscription_type !== "ethereum_blockchain"), + }); + return ( + + {type.name} + + ); + })} + + null} + > + + {errors.subscription_type && errors.subscription_type.message} + + + + + + + Label color + {" "} + setColor(makeColor())} + icon={} + /> + null} + w="200px" + > + + + + + + {errors.color && errors.color.message} + + + + + + + + + ); +}; + +export default NewSubscription; diff --git a/frontend/src/components/NewSubscription.js b/frontend/src/components/NewSubscription.js index 14b1536c..be79ac04 100644 --- a/frontend/src/components/NewSubscription.js +++ b/frontend/src/components/NewSubscription.js @@ -1,4 +1,4 @@ -import React, { useState, useEffect } from "react"; +import React, { useState, useEffect, useCallback } from "react"; import { useSubscriptions } from "../core/hooks"; import { Input, @@ -8,23 +8,24 @@ import { useRadioGroup, FormControl, FormErrorMessage, - ModalBody, - ModalCloseButton, - ModalHeader, Button, - ModalFooter, Spinner, IconButton, + ButtonGroup, + Spacer, + Flex, } from "@chakra-ui/react"; import RadioCard from "./RadioCard"; -import { useForm } from "react-hook-form"; -import { GithubPicker } from "react-color"; +// import { useForm } from "react-hook-form"; +import { CirclePicker } from "react-color"; import { BiRefresh } from "react-icons/bi"; import { makeColor } from "../core/utils/makeColor"; -const NewSubscription = ({ isFreeOption, onClose }) => { +import { useForm } from "react-hook-form"; +const _NewSubscription = ({ isFreeOption, onClose, setIsLoading }) => { const [color, setColor] = useState(makeColor()); - const { typesCache, createSubscription } = useSubscriptions(); const { handleSubmit, errors, register } = useForm({}); + const { typesCache, createSubscription } = useSubscriptions(); + // const { handleSubmit, errors, register } = useForm({}); const [radioState, setRadioState] = useState("ethereum_blockchain"); let { getRootProps, getRadioProps } = useRadioGroup({ name: "type", @@ -34,96 +35,106 @@ const NewSubscription = ({ isFreeOption, onClose }) => { const group = getRootProps(); + useEffect(() => { + if (setIsLoading) { + setIsLoading(createSubscription.isLoading); + } + }, [createSubscription.isLoading, setIsLoading]); + useEffect(() => { if (createSubscription.isSuccess) { onClose(); } }, [createSubscription.isSuccess, onClose]); - if (typesCache.isLoading) return ; + const createSubscriptionWrapper = useCallback( + (props) => { + createSubscription.mutate({ + ...props, + color: color, + type: isFreeOption ? 0 : radioState, + }); + }, + [createSubscription, isFreeOption, color, radioState] + ); - const createSubscriptionWrap = (props) => { - createSubscription.mutate({ - ...props, - color: color, - type: isFreeOption ? "free" : radioState, - }); - }; + if (typesCache.isLoading) return ; const handleChangeColorComplete = (color) => { setColor(color.hex); }; - return ( -
- Subscribe to a new address - - - - - - {errors.label && errors.label.message} - - - - - - {errors.address && errors.address.message} - - - - - {isFreeOption - ? `Free subscription is only availible Ethereum blockchain source` - : `On which source?`} - + console.log("check errors:", errors); + if (!errors) return ""; - - - {typesCache.data.subscriptions.map((type) => { - const radio = getRadioProps({ - value: type.id, - isDisabled: - !type.active || - (isFreeOption && - type.subscription_type !== "ethereum_blockchain"), - }); - return ( - - {type.name} - - ); - })} - - null} - > - - {errors.subscription_type && errors.subscription_type.message} - - - - - + return ( + + + + + {errors?.label && errors?.label.message} + + + + + + {errors?.address && errors?.address.message} + + + + {/* + {isFreeOption + ? `Right now you can subscribe only to ethereum blockchain` + : `On which source?`} + */} + + + + {typesCache.data.subscriptions.map((type) => { + const radio = getRadioProps({ + value: type.id, + isDisabled: + !type.active || + (isFreeOption && + type.subscription_type !== "ethereum_blockchain"), + }); + return ( + + {type.name} + + ); + })} + + null} + > + + {errors?.subscription_type && errors?.subscription_type.message} + + + + + + Label color {" "} @@ -147,18 +158,21 @@ const NewSubscription = ({ isFreeOption, onClose }) => { w="200px" > + + + + - + + {errors?.color && errors?.color.message} + + - - {errors.color && errors.color.message} - - - - + + - + ); }; -export default NewSubscription; +export default _NewSubscription; From 816543f17e09b220562a774a6207dfedd024cd0b Mon Sep 17 00:00:00 2001 From: Tim Pechersky Date: Wed, 18 Aug 2021 14:39:53 +0200 Subject: [PATCH 04/13] navbar routes to /welcome --- frontend/src/components/AppNavbar.js | 10 ++++++++++ frontend/src/components/LandingNavbar.js | 12 ++++++++++++ frontend/src/components/Sidebar.js | 8 ++++++++ 3 files changed, 30 insertions(+) diff --git a/frontend/src/components/AppNavbar.js b/frontend/src/components/AppNavbar.js index 10ff2a41..2f6c11f6 100644 --- a/frontend/src/components/AppNavbar.js +++ b/frontend/src/components/AppNavbar.js @@ -15,6 +15,7 @@ import { PopoverCloseButton, useBreakpointValue, Spacer, + ButtonGroup, } from "@chakra-ui/react"; import { HamburgerIcon, @@ -26,6 +27,7 @@ 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"; const AppNavbar = () => { const ui = useContext(UIContext); @@ -95,6 +97,14 @@ const AppNavbar = () => { + + {/* + Docs + */} + + Learn how to + + { const ui = useContext(UIContext); @@ -52,6 +53,17 @@ const LandingNavbar = () => { spacing={4} pr={16} > + {ui.isLoggedIn && ( + + {/* + Docs + */} + + Learn how to + + + )} + {ui.isLoggedIn && ( + + ); +}; + +const RouteButton = chakra(_RouteButton, "button"); + +export default RouteButton; From db7c68348c054dce7796b99294a76363b023f146 Mon Sep 17 00:00:00 2001 From: Tim Pechersky Date: Wed, 18 Aug 2021 14:41:18 +0200 Subject: [PATCH 08/13] step progress onboarding --- frontend/pages/welcome.js | 427 +++++++++++++++++++ frontend/src/components/EntriesNavigation.js | 1 + frontend/src/components/StepProgress.js | 70 +++ frontend/src/components/StreamEntry.js | 133 +++--- frontend/src/components/SubscriptionsList.js | 20 +- frontend/src/core/hooks/useSignUp.js | 24 +- 6 files changed, 605 insertions(+), 70 deletions(-) create mode 100644 frontend/pages/welcome.js create mode 100644 frontend/src/components/StepProgress.js diff --git a/frontend/pages/welcome.js b/frontend/pages/welcome.js new file mode 100644 index 00000000..1d734f2d --- /dev/null +++ b/frontend/pages/welcome.js @@ -0,0 +1,427 @@ +import React, { useContext, useEffect } from "react"; +import { getLayout } from "../src/layouts/AppLayout"; +import UIContext from "../src/core/providers/UIProvider/context"; +import { + Heading, + Text, + Button, + Stack, + ButtonGroup, + Spacer, + Radio, + RadioGroup, + UnorderedList, + ListItem, + Fade, + chakra, + useBoolean, +} from "@chakra-ui/react"; +import StepProgress from "../src/components/StepProgress"; +import { ArrowLeftIcon, ArrowRightIcon } from "@chakra-ui/icons"; +import Scrollable from "../src/components/Scrollable"; +import AnalyticsContext from "../src/core/providers/AnalyticsProvider/context"; +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"; + +const Welcome = () => { + const { subscriptionsCache } = useSubscriptions(); + console.log("StepProgress page!"); + const ui = useContext(UIContext); + const { mixpanel, isLoaded, MIXPANEL_PROPS } = useContext(AnalyticsContext); + const [profile, setProfile] = React.useState(); + const [showSubscriptionForm, setShowSubscriptionForm] = useBoolean(true); + + useEffect(() => { + if (typeof window !== "undefined") { + document.title = `Welcome to moonstream.to!`; + } + }, []); + + const progressButtonCallback = (index) => { + console.log("progress button callback!", index); + ui.setOnboardingStep(index); + }; + + useEffect(() => { + if (profile && isLoaded) { + mixpanel.people.set({ + [`${MIXPANEL_PROPS.USER_SPECIALITY}`]: profile, + }); + } + }, [profile, MIXPANEL_PROPS, isLoaded, mixpanel]); + + const SubscriptonCreatedCallback = () => { + setShowSubscriptionForm.off(); + }; + + const handleNextClick = () => { + if (ui.onboardingStep < ui.onboardingSteps.length - 1) { + ui.setOnboardingStep(ui.onboardingStep + 1); + } else { + ui.setisOnboardingComplete(true); + router.push("/stream"); + } + }; + + console.log("onboarding step:", ui.onboardingStep); + + return ( + + + + + {ui.onboardingStep === 0 && ( + + + + + Greetings traveller! + + + {" "} + We are very excited to see you onboard! + + + + Moonstream is a product which helps anyone participate in + decentralized finance. From the most sophisticated flash + arbitrageurs to people looking for yield from currency that + would otherwise lie dormant in their exchange accounts. + + + Moonstream is ment to give you critical insights needed to + succeed in your crypto quest! + + + + + How does Moonstream work? + + + + We run nodes + {" "} + - Now get most precise and accurate data you can just query + our database. You {`don't`} need to maintain your node, and + still have data that miners have access to! + + + + We crawl data + {" "} + We analyze millions of transactions, data, smart contract code + to link all them together + + + + + We provide data + {" "} + We allow you to fetch data trough the website or trough API + + + + + We analyze data + {" "} + We find most interesting stuff and show it to you! + + + + + UI 101? + + + On the left side corner there is sidebar that you can use to + navigate across the website. There are following views you can + navigate to: + + + + Subscriptions + {" "} + - Use this screen to set up addresses you would like to + monitor to.{" "} + + NB: Without setting up subscriptions moonstream will have + quite empty feel!{" "} + {" "} + No worries, we will help you to set up your subscriptions in + the next steps! + + + + Stream + {" "} + This view is somewhat similar to a bank statement where you + can define time range and see what happened in that time over + your subscriptions. In next steps we will show how you can + apply filters to it! + + + + + Stream Entry + {" "} + You can see detailed view of stream cards with very specific + and essential data, like methods called in smart contracts + etc!! + + + + + Analytics + {" "} + This section is under construction yet. Soon you will be able + to create your dashboard with data of your interest. We will + really appretiate if you visit that section, and fill up form + describing what analytical tools you would love to see there! + + + + + + Tell us more about your needs? + + + In order to fetch best possible experience, we would like to + know some details about you + + + Please tell us what profile describes you best?{" "} + + This is purely analytical data, you can change it anytime + later + + + + + I am trading crypto currency + I represent investment fund + I am developer + + + + + + )} + {ui.onboardingStep === 1 && ( + + + + + Subscriptions + + + Subscriptions is essential tool of Moonstream. We gather data + for you based on addresses you have subscribed for. +
+ Subscribe to any addres which you are interested in and they + will become part of your stream! + + + Color - you can define color to easily identify this + subscription in your stream + + Address - thing you subscribe to + + Label - Its good idea to use human readible name that + represents address + + + Source - In Alpha we support only Ethereum blockchain, + more sources are coming soon! + + +
+
+ {subscriptionsCache.data.subscriptions.length > 0 && + !subscriptionsCache.isLoading && ( + <> + + {" "} + You already have some subscriptions set up + + + )} + + {showSubscriptionForm && ( + <> + {`Let's add new subscription!`} + + + + )} + {!showSubscriptionForm && ( + + )} +
+
+ )} + {ui.onboardingStep === 2 && ( + + + + + Stream + + + We are almost done! +
+ {`Stream is where you can read data you've subscribed for. Here + you have different cards for different subscription types.`} +
+ If card has some extra details - there will be orange button + on right hand side inviting you to see more! +
+ Below is typical card for ethereum blockchain event. Useful + information right on the card: + + Hash - unique ID of the event + + From - sender address. If it is one of your subscription + addresses - will appear in color and with label{" "} + + + To - receiver address. If it is one of your subscription + addresses - will appear in color and with label{" "} + + + Nonce - Counter how many transactions address has sent. It + also determines sequence of transaction!{" "} + + + Gas Price - this is how much ether (gwei) is being paid + per gas unit + + + Gas - Ammount of gas this event consumes + + +
+
+ + + +
+
+ )} + {ui.onboardingStep === 3 && ( + + Subscriptions onboarding + + )} + + + + + +
+
+ ); +}; +Welcome.getLayout = getLayout; +export default Welcome; diff --git a/frontend/src/components/EntriesNavigation.js b/frontend/src/components/EntriesNavigation.js index 687eb850..082ba342 100644 --- a/frontend/src/components/EntriesNavigation.js +++ b/frontend/src/components/EntriesNavigation.js @@ -529,6 +529,7 @@ const EntriesNavigation = () => { ?.sort((a, b) => b.timestamp - a.timestamp) // TODO(Andrey) improve that for bi chunks of data sorting can take time .map((entry, idx) => ( { + const ui = useContext(UIContext); + console.log("currentStep", currentStep, numSteps); + return ( + + + {_.times(numSteps, (i) => { + const setActive = i === parseInt(currentStep) ? true : false; + console.log("setActive", setActive, i, parseInt(currentStep)); + return ( + + ); + })} + + + {/* */} + + ); +}; + +export default StepProgress; diff --git a/frontend/src/components/StreamEntry.js b/frontend/src/components/StreamEntry.js index 50b9f56b..0f20018f 100644 --- a/frontend/src/components/StreamEntry.js +++ b/frontend/src/components/StreamEntry.js @@ -11,6 +11,7 @@ import { useMediaQuery, Spacer, Spinner, + chakra, } from "@chakra-ui/react"; import moment from "moment"; import { ArrowRightIcon } from "@chakra-ui/icons"; @@ -18,7 +19,8 @@ import UIContext from "../core/providers/UIProvider/context"; import { useToast } from "../core/hooks"; import { useSubscriptions } from "../core/hooks"; -const StreamEntry = ({ entry }) => { +const StreamEntry = ({ entry, showOnboardingTooltips, className }) => { + console.log("stream entry:", entry); const { subscriptionsCache } = useSubscriptions(); const ui = useContext(UIContext); const [copyString, setCopyString] = useState(false); @@ -49,6 +51,7 @@ const StreamEntry = ({ entry }) => { return ( { overflowX="hidden" overflowY="visible" > - - - - Hash - - - setCopyString(entry.hash)} - pr={12} + - {entry.hash} - - + + + Hash + + + setCopyString(entry.hash)} + pr={12} + > + {entry.hash} + + + { placeContent="center" spacing={0} > - - From: - + + From: + + { + { )} - ui.setCurrentTransaction(entry)} - h="full" - // minH="24px" - borderLeftRadius={0} - variant="solid" - px={0} - minW="24px" - colorScheme="secondary" - icon={} - /> + + ui.setCurrentTransaction(entry)} + h="full" + // minH="24px" + borderLeftRadius={0} + variant="solid" + px={0} + minW="24px" + colorScheme="secondary" + icon={} + /> + ); }; -export default StreamEntry; +const StreamChakraEntry = chakra(StreamEntry); + +export default StreamChakraEntry; diff --git a/frontend/src/components/SubscriptionsList.js b/frontend/src/components/SubscriptionsList.js index 64e76ce1..738f27af 100644 --- a/frontend/src/components/SubscriptionsList.js +++ b/frontend/src/components/SubscriptionsList.js @@ -1,5 +1,5 @@ import React from "react"; -import { Skeleton, IconButton } from "@chakra-ui/react"; +import { Skeleton, IconButton, Container } from "@chakra-ui/react"; import { Table, Th, @@ -12,6 +12,7 @@ import { EditableInput, Image, EditablePreview, + Button, } from "@chakra-ui/react"; import { DeleteIcon } from "@chakra-ui/icons"; import moment from "moment"; @@ -20,7 +21,7 @@ import { useSubscriptions } from "../core/hooks"; import ConfirmationRequest from "./ConfirmationRequest"; import ColorSelector from "./ColorSelector"; -const SubscriptionsList = () => { +const SubscriptionsList = ({ emptyCTA }) => { const { subscriptionsCache, updateSubscription, deleteSubscription } = useSubscriptions(); @@ -31,7 +32,10 @@ const SubscriptionsList = () => { updateSubscription.mutate(data); }; - if (subscriptionsCache.data) { + if ( + subscriptionsCache.data && + subscriptionsCache.data.subscriptions.length > 0 + ) { return ( {
); + } else if ( + subscriptionsCache.data && + subscriptionsCache.data.subscriptions.length === 0 + ) { + return ( + + {` You don't have any subscriptions at the moment.`} + {emptyCTA && } + + ); } else if (subscriptionsCache.isLoading) { return ; } else { diff --git a/frontend/src/core/hooks/useSignUp.js b/frontend/src/core/hooks/useSignUp.js index dc5ab54e..f6dca897 100644 --- a/frontend/src/core/hooks/useSignUp.js +++ b/frontend/src/core/hooks/useSignUp.js @@ -1,9 +1,11 @@ -import { useEffect } from "react"; +import { useContext } from "react"; import { useMutation } from "react-query"; import { AuthService } from "../services"; import { useUser, useToast, useInviteAccept, useRouter, useAnalytics } from "."; +import UIContext from "../providers/UIProvider/context"; const useSignUp = (source) => { + const ui = useContext(UIContext); const router = useRouter(); const { getUser } = useUser(); const toast = useToast(); @@ -30,28 +32,16 @@ const useSignUp = (source) => { { full_url: router.nextRouter.asPath, code: source } ); } + getUser(); + ui.setisOnboardingComplete(false); + ui.setOnboardingState({ welcome: 0, subscriptions: 0, stream: 0 }); + router.push("/welcome", undefined, { shallow: false }); }, onError: (error) => { toast(error, "error"); }, }); - useEffect(() => { - if (!data) { - return; - } - - getUser(); - - const requested_pricing = window.sessionStorage.getItem( - "requested_pricing_plan" - ); - const redirectURL = requested_pricing ? "/subscriptions" : "/stream"; - - router.push(redirectURL); - window.sessionStorage.clear("requested_pricing"); - }, [data, getUser, router]); - return { signUp, isLoading, From 60db6708b41622c91a34ea2a657462f967d7e7ef Mon Sep 17 00:00:00 2001 From: Tim Pechersky Date: Wed, 18 Aug 2021 14:53:45 +0200 Subject: [PATCH 09/13] entry details will better fit in to split view --- frontend/src/components/SteamEntryDetails.js | 5 ++--- frontend/src/components/TxInfo.js | 16 ++++++++++------ 2 files changed, 12 insertions(+), 9 deletions(-) diff --git a/frontend/src/components/SteamEntryDetails.js b/frontend/src/components/SteamEntryDetails.js index 8d0f46e4..4d74b144 100644 --- a/frontend/src/components/SteamEntryDetails.js +++ b/frontend/src/components/SteamEntryDetails.js @@ -36,17 +36,16 @@ const SteamEntryDetails = () => { > - {entry && entry.tx.hash} + {entry && `Hash: ${entry.tx.hash}`} diff --git a/frontend/src/components/TxInfo.js b/frontend/src/components/TxInfo.js index f0afcc9f..a5c70ed1 100644 --- a/frontend/src/components/TxInfo.js +++ b/frontend/src/components/TxInfo.js @@ -58,25 +58,29 @@ const TxInfo = (props) => { return ( - + Value - {toEth(transaction.tx.value)} eth + + {toEth(transaction.tx.value)} eth + amount of ETH to transfer Gas limit - {transaction.tx.gas} + {transaction.tx.gas} Maximum amount of gas provided for the transaction Gas price - {toEth(transaction.tx.gasPrice)} eth + + {toEth(transaction.tx.gasPrice)} eth + the fee the sender pays per unit of gas - +
{Object.keys(transaction.tx) .filter(dont_display) @@ -85,7 +89,7 @@ const TxInfo = (props) => { transaction.tx[key] != undefined && ( - + ) )} From b2d20c8eb8fb847621f76a02b197f0fb2a0221d1 Mon Sep 17 00:00:00 2001 From: Tim Pechersky Date: Wed, 18 Aug 2021 16:08:19 +0200 Subject: [PATCH 10/13] remove console logs --- frontend/pages/_app.js | 3 - frontend/pages/stream/index.js | 1 + frontend/pages/welcome.js | 71 +++++++++++++++----- frontend/src/components/EntriesNavigation.js | 2 - frontend/src/components/NewSubscription.js | 1 - frontend/src/components/StepProgress.js | 6 +- frontend/src/components/StreamEntry.js | 1 - frontend/src/components/TxInfo.js | 1 - 8 files changed, 59 insertions(+), 27 deletions(-) diff --git a/frontend/pages/_app.js b/frontend/pages/_app.js index ec895ffd..44ad346c 100644 --- a/frontend/pages/_app.js +++ b/frontend/pages/_app.js @@ -39,7 +39,6 @@ export default function CachingApp({ Component, pageProps }) { router.events.on("routeChangeComplete", handleStop); router.events.on("routeChangeError", handleStop); - console.log("_app", router.asPath); return () => { router.events.off("routeChangeStart", handleStart); router.events.off("routeChangeComplete", handleStop); @@ -49,8 +48,6 @@ export default function CachingApp({ Component, pageProps }) { const getLayout = Component.getLayout || ((page) => {page}); - console.log("_app loaded", router.asPath); - return ( <>
{key}{transaction.tx[key]}{transaction.tx[key]}