From 05b45c5203f94270d66e8b5c4d8267185a3abe64 Mon Sep 17 00:00:00 2001 From: David Echelberger Date: Wed, 13 Apr 2022 04:21:29 -0400 Subject: [PATCH 1/3] [spinners] moving copy button Signed-off-by: David Echelberger --- ui/src/components/Buttons/RunButton.tsx | 2 +- ui/src/pages/Home/views/MiddlePane.tsx | 29 ++++++++----------------- ui/src/translations/en.json | 1 + ui/src/utils/strings.ts | 9 -------- 4 files changed, 11 insertions(+), 30 deletions(-) diff --git a/ui/src/components/Buttons/RunButton.tsx b/ui/src/components/Buttons/RunButton.tsx index dac2018..36010f5 100644 --- a/ui/src/components/Buttons/RunButton.tsx +++ b/ui/src/components/Buttons/RunButton.tsx @@ -98,7 +98,7 @@ export const RunButton: React.FC = ({ endpoint, payload, disabled }) => { > diff --git a/ui/src/pages/Home/views/MiddlePane.tsx b/ui/src/pages/Home/views/MiddlePane.tsx index f6014d0..e6728a8 100644 --- a/ui/src/pages/Home/views/MiddlePane.tsx +++ b/ui/src/pages/Home/views/MiddlePane.tsx @@ -1,13 +1,14 @@ +import { ContentCopy } from '@mui/icons-material'; +import LinkIcon from '@mui/icons-material/Link'; import { Button, Chip, Grid, Paper, Typography } from '@mui/material'; import { t } from 'i18next'; import { useContext, useEffect, useState } from 'react'; +import CopyToClipboard from 'react-copy-to-clipboard'; import SyntaxHighlighter from 'react-syntax-highlighter'; import { tomorrowNightBright } from 'react-syntax-highlighter/dist/esm/styles/hljs'; -import CopyIcon from '@mui/icons-material/ContentCopy'; import * as _ from 'underscore'; import { RunButton } from '../../../components/Buttons/RunButton'; import { FF_Paths } from '../../../constants/FF_Paths'; -import LinkIcon from '@mui/icons-material/Link'; import { TutorialSections, TUTORIAL_CATEGORIES, @@ -19,7 +20,6 @@ import { DEFAULT_PADDING, FFColors, } from '../../../theme'; -import { copyToClipboard } from '../../../utils/strings'; const getTutorials = (tutorialTitle: string) => { return TutorialSections.find((t) => t.title === tutorialTitle)?.tutorials.map( @@ -149,22 +149,6 @@ export const MiddlePane = () => { padding: DEFAULT_PADDING, }} > - - - {t('typescriptSDK')} - - - { {codeBlock} - + + + + { } return true; }; - -export const copyToClipboard = (text: string) => { - const dummy = document.createElement('textarea'); - document.body.appendChild(dummy); - dummy.value = text; - dummy.select(); - document.execCommand('copy'); - document.body.removeChild(dummy); -}; From ff941c375df7f62d637d57ad22ffb8c16b4b1064 Mon Sep 17 00:00:00 2001 From: David Echelberger Date: Wed, 13 Apr 2022 06:08:47 -0400 Subject: [PATCH 2/3] [spinners] spinners Signed-off-by: David Echelberger --- ui/package-lock.json | 88 ++++++------ ui/src/App.tsx | 18 ++- ui/src/components/Buttons/RunButton.tsx | 87 +++++++---- ui/src/contexts/EventContext.tsx | 4 +- ui/src/interfaces/events.tsx | 1 + ui/src/pages/Home/views/MiddlePane.tsx | 26 ++-- ui/src/pages/Home/views/RightPane.tsx | 182 +++++++++++++----------- ui/src/translations/en.json | 1 + 8 files changed, 245 insertions(+), 162 deletions(-) diff --git a/ui/package-lock.json b/ui/package-lock.json index 610e0dd..1b55316 100644 --- a/ui/package-lock.json +++ b/ui/package-lock.json @@ -2950,12 +2950,12 @@ } }, "node_modules/@mui/private-theming": { - "version": "5.5.3", - "resolved": "https://registry.npmjs.org/@mui/private-theming/-/private-theming-5.5.3.tgz", - "integrity": "sha512-Wf7NurY7lk8SBWelSBY2U02zxLt1773JpIcXTHuEC9/GZdQA4CXCJGl2cVQzheKhee5rZ+8JwGulrRiVl1m+4A==", + "version": "5.6.1", + "resolved": "https://registry.npmjs.org/@mui/private-theming/-/private-theming-5.6.1.tgz", + "integrity": "sha512-8lgh+tUt/3ftStfvml3dwAzhW3fe/cUFjLcBViOTnWk7UixWR79me4qehsO4NVj0THpu3d2qclrLzdD8qBAWAQ==", "dependencies": { "@babel/runtime": "^7.17.2", - "@mui/utils": "^5.5.3", + "@mui/utils": "^5.6.1", "prop-types": "^15.7.2" }, "engines": { @@ -2966,8 +2966,8 @@ "url": "https://opencollective.com/mui" }, "peerDependencies": { - "@types/react": "^16.8.6 || ^17.0.0", - "react": "^17.0.0" + "@types/react": "^17.0.0 || ^18.0.0", + "react": "^17.0.0 || ^18.0.0" }, "peerDependenciesMeta": { "@types/react": { @@ -2976,9 +2976,9 @@ } }, "node_modules/@mui/styled-engine": { - "version": "5.5.2", - "resolved": "https://registry.npmjs.org/@mui/styled-engine/-/styled-engine-5.5.2.tgz", - "integrity": "sha512-jkz5AHHbA43akBo5L3y1X1/X0f+RvXvCp3eXKt+iOf3qnKSAausbtlVz7gBbC4xIWDnP1Jb/6T+t/0/7gObRYA==", + "version": "5.6.1", + "resolved": "https://registry.npmjs.org/@mui/styled-engine/-/styled-engine-5.6.1.tgz", + "integrity": "sha512-jEhH6TBY8jc9S8yVncXmoTYTbATjEu44RMFXj6sIYfKr5NArVwTwRo3JexLL0t3BOAiYM4xsFLgfKEIvB9SAeQ==", "dependencies": { "@babel/runtime": "^7.17.2", "@emotion/cache": "^11.7.1", @@ -2994,7 +2994,7 @@ "peerDependencies": { "@emotion/react": "^11.4.1", "@emotion/styled": "^11.3.0", - "react": "^17.0.0" + "react": "^17.0.0 || ^18.0.0" }, "peerDependenciesMeta": { "@emotion/react": { @@ -3006,15 +3006,15 @@ } }, "node_modules/@mui/system": { - "version": "5.5.3", - "resolved": "https://registry.npmjs.org/@mui/system/-/system-5.5.3.tgz", - "integrity": "sha512-J9JcySJuEqfEoP334K/2gEWm2vOx73Uqjii3qlFVhWRBOAJ0Pjyk0sN5W/eVRbwhUm95DNgh2V5s8dRK3vzyVw==", + "version": "5.6.1", + "resolved": "https://registry.npmjs.org/@mui/system/-/system-5.6.1.tgz", + "integrity": "sha512-Y5pDvEOK6VOY+0vgNeyDuEEO5QCinhXbZQDyLOlaGLKuAoRGLXO9pcSsjZoGkewYZitXD44EDfgBQ+BqsAfgUA==", "dependencies": { "@babel/runtime": "^7.17.2", - "@mui/private-theming": "^5.5.3", - "@mui/styled-engine": "^5.5.2", + "@mui/private-theming": "^5.6.1", + "@mui/styled-engine": "^5.6.1", "@mui/types": "^7.1.3", - "@mui/utils": "^5.5.3", + "@mui/utils": "^5.6.1", "clsx": "^1.1.1", "csstype": "^3.0.11", "prop-types": "^15.7.2" @@ -3029,8 +3029,8 @@ "peerDependencies": { "@emotion/react": "^11.5.0", "@emotion/styled": "^11.3.0", - "@types/react": "^16.8.6 || ^17.0.0", - "react": "^17.0.0" + "@types/react": "^17.0.0 || ^18.0.0", + "react": "^17.0.0 || ^18.0.0" }, "peerDependenciesMeta": { "@emotion/react": { @@ -3058,9 +3058,9 @@ } }, "node_modules/@mui/utils": { - "version": "5.5.3", - "resolved": "https://registry.npmjs.org/@mui/utils/-/utils-5.5.3.tgz", - "integrity": "sha512-t627eVRpl3SlxVya0cIVNs8jPl4KCEiGaTSWY9iKKTcMNaeDbuRML+zv/CFHDPr1zFv+FjJSP02ySB+tZ8xIag==", + "version": "5.6.1", + "resolved": "https://registry.npmjs.org/@mui/utils/-/utils-5.6.1.tgz", + "integrity": "sha512-CPrzrkiBusCZBLWu0Sg5MJvR3fKJyK3gKecLVX012LULyqg2U64Oz04BKhfkbtBrPBbSQxM+DWW9B1c9hmV9nQ==", "dependencies": { "@babel/runtime": "^7.17.2", "@types/prop-types": "^15.7.4", @@ -3076,7 +3076,7 @@ "url": "https://opencollective.com/mui" }, "peerDependencies": { - "react": "^17.0.0" + "react": "^17.0.0 || ^18.0.0" } }, "node_modules/@nodelib/fs.scandir": { @@ -3234,9 +3234,9 @@ } }, "node_modules/@popperjs/core": { - "version": "2.11.4", - "resolved": "https://registry.npmjs.org/@popperjs/core/-/core-2.11.4.tgz", - "integrity": "sha512-q/ytXxO5NKvyT37pmisQAItCFqA7FD/vNb8dgaJy3/630Fsc+Mz9/9f2SziBoIZ30TJooXyTwZmhi1zjXmObYg==", + "version": "2.11.5", + "resolved": "https://registry.npmjs.org/@popperjs/core/-/core-2.11.5.tgz", + "integrity": "sha512-9X2obfABZuDVLCgPK9aX0a/x4jaOEweTTWE2+9sr0Qqqevj2Uv5XorvusThmc9XGYpS9yI+fhh8RTafBtGposw==", "funding": { "type": "opencollective", "url": "https://opencollective.com/popperjs" @@ -19257,19 +19257,19 @@ } }, "@mui/private-theming": { - "version": "5.5.3", - "resolved": "https://registry.npmjs.org/@mui/private-theming/-/private-theming-5.5.3.tgz", - "integrity": "sha512-Wf7NurY7lk8SBWelSBY2U02zxLt1773JpIcXTHuEC9/GZdQA4CXCJGl2cVQzheKhee5rZ+8JwGulrRiVl1m+4A==", + "version": "5.6.1", + "resolved": "https://registry.npmjs.org/@mui/private-theming/-/private-theming-5.6.1.tgz", + "integrity": "sha512-8lgh+tUt/3ftStfvml3dwAzhW3fe/cUFjLcBViOTnWk7UixWR79me4qehsO4NVj0THpu3d2qclrLzdD8qBAWAQ==", "requires": { "@babel/runtime": "^7.17.2", - "@mui/utils": "^5.5.3", + "@mui/utils": "^5.6.1", "prop-types": "^15.7.2" } }, "@mui/styled-engine": { - "version": "5.5.2", - "resolved": "https://registry.npmjs.org/@mui/styled-engine/-/styled-engine-5.5.2.tgz", - "integrity": "sha512-jkz5AHHbA43akBo5L3y1X1/X0f+RvXvCp3eXKt+iOf3qnKSAausbtlVz7gBbC4xIWDnP1Jb/6T+t/0/7gObRYA==", + "version": "5.6.1", + "resolved": "https://registry.npmjs.org/@mui/styled-engine/-/styled-engine-5.6.1.tgz", + "integrity": "sha512-jEhH6TBY8jc9S8yVncXmoTYTbATjEu44RMFXj6sIYfKr5NArVwTwRo3JexLL0t3BOAiYM4xsFLgfKEIvB9SAeQ==", "requires": { "@babel/runtime": "^7.17.2", "@emotion/cache": "^11.7.1", @@ -19277,15 +19277,15 @@ } }, "@mui/system": { - "version": "5.5.3", - "resolved": "https://registry.npmjs.org/@mui/system/-/system-5.5.3.tgz", - "integrity": "sha512-J9JcySJuEqfEoP334K/2gEWm2vOx73Uqjii3qlFVhWRBOAJ0Pjyk0sN5W/eVRbwhUm95DNgh2V5s8dRK3vzyVw==", + "version": "5.6.1", + "resolved": "https://registry.npmjs.org/@mui/system/-/system-5.6.1.tgz", + "integrity": "sha512-Y5pDvEOK6VOY+0vgNeyDuEEO5QCinhXbZQDyLOlaGLKuAoRGLXO9pcSsjZoGkewYZitXD44EDfgBQ+BqsAfgUA==", "requires": { "@babel/runtime": "^7.17.2", - "@mui/private-theming": "^5.5.3", - "@mui/styled-engine": "^5.5.2", + "@mui/private-theming": "^5.6.1", + "@mui/styled-engine": "^5.6.1", "@mui/types": "^7.1.3", - "@mui/utils": "^5.5.3", + "@mui/utils": "^5.6.1", "clsx": "^1.1.1", "csstype": "^3.0.11", "prop-types": "^15.7.2" @@ -19298,9 +19298,9 @@ "requires": {} }, "@mui/utils": { - "version": "5.5.3", - "resolved": "https://registry.npmjs.org/@mui/utils/-/utils-5.5.3.tgz", - "integrity": "sha512-t627eVRpl3SlxVya0cIVNs8jPl4KCEiGaTSWY9iKKTcMNaeDbuRML+zv/CFHDPr1zFv+FjJSP02ySB+tZ8xIag==", + "version": "5.6.1", + "resolved": "https://registry.npmjs.org/@mui/utils/-/utils-5.6.1.tgz", + "integrity": "sha512-CPrzrkiBusCZBLWu0Sg5MJvR3fKJyK3gKecLVX012LULyqg2U64Oz04BKhfkbtBrPBbSQxM+DWW9B1c9hmV9nQ==", "requires": { "@babel/runtime": "^7.17.2", "@types/prop-types": "^15.7.4", @@ -19394,9 +19394,9 @@ } }, "@popperjs/core": { - "version": "2.11.4", - "resolved": "https://registry.npmjs.org/@popperjs/core/-/core-2.11.4.tgz", - "integrity": "sha512-q/ytXxO5NKvyT37pmisQAItCFqA7FD/vNb8dgaJy3/630Fsc+Mz9/9f2SziBoIZ30TJooXyTwZmhi1zjXmObYg==" + "version": "2.11.5", + "resolved": "https://registry.npmjs.org/@popperjs/core/-/core-2.11.5.tgz", + "integrity": "sha512-9X2obfABZuDVLCgPK9aX0a/x4jaOEweTTWE2+9sr0Qqqevj2Uv5XorvusThmc9XGYpS9yI+fhh8RTafBtGposw==" }, "@rollup/plugin-babel": { "version": "5.3.1", diff --git a/ui/src/App.tsx b/ui/src/App.tsx index 5aa6ae7..ceb65c4 100644 --- a/ui/src/App.tsx +++ b/ui/src/App.tsx @@ -20,6 +20,8 @@ import { summarizeFetchError } from './utils/fetches'; // TODO: Make dynamic export const SELECTED_NS = 'default'; +// TODO: Figure out why this works +let dumbAwaitedEventID: string | undefined = undefined; function App() { const [initialized, setInitialized] = useState(true); @@ -101,10 +103,15 @@ function App() { const txMap = deepCopyMap.get(event.tx); if (txMap !== undefined) { + const isComplete = event.reference === dumbAwaitedEventID; + if (isComplete) dumbAwaitedEventID = undefined; + return new Map( deepCopyMap.set(event.tx, { - events: [...txMap.events, event], + events: [event, ...txMap.events], created: event.created, + // TODO: Need better logic + isComplete, }) ); } else { @@ -112,12 +119,19 @@ function App() { deepCopyMap.set(event.tx, { events: [event], created: event.created, + isComplete: event.reference === dumbAwaitedEventID, }) ); } }); }; + const addAwaitedEventID = (apiRes: any) => { + if (apiRes?.id && apiRes?.id) { + dumbAwaitedEventID = apiRes.id; + } + }; + if (initialized) { return ( diff --git a/ui/src/components/Buttons/RunButton.tsx b/ui/src/components/Buttons/RunButton.tsx index 36010f5..110bc57 100644 --- a/ui/src/components/Buttons/RunButton.tsx +++ b/ui/src/components/Buttons/RunButton.tsx @@ -1,8 +1,16 @@ import { ArrowForwardIos } from '@mui/icons-material'; -import { Alert, Button, Snackbar, Typography } from '@mui/material'; -import { useContext, useState } from 'react'; +import { + Alert, + Button, + CircularProgress, + Grid, + Snackbar, + Typography, +} from '@mui/material'; +import { useContext, useEffect, useState } from 'react'; import { useTranslation } from 'react-i18next'; import { ApplicationContext } from '../../contexts/ApplicationContext'; +import { EventContext } from '../../contexts/EventContext'; import { DEFAULT_BORDER_RADIUS } from '../../theme'; interface Props { @@ -16,6 +24,9 @@ export const RunButton: React.FC = ({ endpoint, payload, disabled }) => { const [showSnackbar, setShowSnackbar] = useState(false); const { activeForm, setApiStatus, setApiResponse, payloadMissingFields } = useContext(ApplicationContext); + const { dumbAwaitedEventID, addAwaitedEventID } = useContext(EventContext); + // TODO: Remove soon + const [justSubmitted, setJustSubmitted] = useState(false); const handleCloseSnackbar = (_: any, reason?: string) => { if (reason === 'clickaway') { @@ -25,6 +36,11 @@ export const RunButton: React.FC = ({ endpoint, payload, disabled }) => { setShowSnackbar(false); }; + // TODO: Remove soon + useEffect(() => { + setJustSubmitted(false); + }, [dumbAwaitedEventID]); + const handlePost = () => { const blobUpload = activeForm.includes('blob'); managePayload(); @@ -48,6 +64,8 @@ export const RunButton: React.FC = ({ endpoint, payload, disabled }) => { .then((data) => { setShowSnackbar(true); setApiResponse(data); + setJustSubmitted(true); + addAwaitedEventID(data); }) .catch((err) => { setShowSnackbar(true); @@ -82,29 +100,50 @@ export const RunButton: React.FC = ({ endpoint, payload, disabled }) => { return ( <> - - - - {`${t('postSentTo')}${endpoint}`} - - + + + {t('waitingForTxEventsToFinish')} + + + + + + + ) : ( + <> + + + + {`${t('postSentTo')}${endpoint}`} + + + + )} ); }; diff --git a/ui/src/contexts/EventContext.tsx b/ui/src/contexts/EventContext.tsx index 0ceac2c..318b844 100644 --- a/ui/src/contexts/EventContext.tsx +++ b/ui/src/contexts/EventContext.tsx @@ -19,8 +19,10 @@ import { IEvent } from '../interfaces/api'; import { IEventHistoryItem } from '../interfaces/events'; export interface IEventContext { - logHistory: Map; addLogToHistory: (event: IEvent) => void; + logHistory: Map; + dumbAwaitedEventID: string | undefined; + addAwaitedEventID: (apiRes: any) => void; } export const EventContext = createContext({} as IEventContext); diff --git a/ui/src/interfaces/events.tsx b/ui/src/interfaces/events.tsx index 1a7af8d..62eb586 100644 --- a/ui/src/interfaces/events.tsx +++ b/ui/src/interfaces/events.tsx @@ -7,4 +7,5 @@ export interface IEventHistory { export interface IEventHistoryItem { events: IEvent[]; created: string; + isComplete: boolean; } diff --git a/ui/src/pages/Home/views/MiddlePane.tsx b/ui/src/pages/Home/views/MiddlePane.tsx index e6728a8..fb652f6 100644 --- a/ui/src/pages/Home/views/MiddlePane.tsx +++ b/ui/src/pages/Home/views/MiddlePane.tsx @@ -165,17 +165,21 @@ export const MiddlePane = () => { {codeBlock} - - - - - + + + + + + + + + diff --git a/ui/src/pages/Home/views/RightPane.tsx b/ui/src/pages/Home/views/RightPane.tsx index a6bd622..db2b734 100644 --- a/ui/src/pages/Home/views/RightPane.tsx +++ b/ui/src/pages/Home/views/RightPane.tsx @@ -1,8 +1,9 @@ -import { ExpandMore } from '@mui/icons-material'; +import { CheckCircleOutline, ExpandMore } from '@mui/icons-material'; import { Accordion, AccordionDetails, AccordionSummary, + CircularProgress, Divider, Grid, Typography, @@ -39,7 +40,6 @@ export const RightPane: React.FC = () => { background: theme.palette.background.default, height: 'auto', position: 'sticky', - top: '0', }} > @@ -51,97 +51,117 @@ export const RightPane: React.FC = () => { Array.from(logHistory.entries()) .reverse() .map(([txID, value], idx) => ( - - {/* Summary */} - }> - - - - - - - + + + {/* Summary */} + }> + + + + + + + {!value.isComplete ? ( + + ) : ( + + )} + + + + + - - - } - rightContent={ - - } - /> - - {/* Details */} - - {value.events.map((e: any, idx: number) => { - return ( - - {/* Event section */} + + } + rightContent={ - + + + } + /> + + {/* Details */} + + {value.events.map((e: IEvent, idx: number) => { + return ( + + {/* Event section */} - + + + + + + - - {/* Event key: values */} - - - {FF_EVENTS_CATEGORY_MAP[e.type as FF_EVENTS] - .eventKeyList(e as IEvent) - .map( - (d, idx) => - d.label !== '' && ( - - ) - )} + {/* Event key: values */} + + + {FF_EVENTS_CATEGORY_MAP[e.type as FF_EVENTS] + .eventKeyList(e as IEvent) + .map( + (d, idx) => + d.label !== '' && ( + + ) + )} + - - {idx !== value.events.length - 1 && } - - ); - })} - - + {idx !== value.events.length - 1 && } + + ); + })} + + + )) ) : ( Date: Wed, 13 Apr 2022 06:39:12 -0400 Subject: [PATCH 3/3] [spinners] tweaks Signed-off-by: David Echelberger --- ui/src/components/Accordion/ContractStateAccordion.tsx | 3 ++- ui/src/components/Buttons/RunButton.tsx | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/ui/src/components/Accordion/ContractStateAccordion.tsx b/ui/src/components/Accordion/ContractStateAccordion.tsx index 596fbe4..3f7f994 100644 --- a/ui/src/components/Accordion/ContractStateAccordion.tsx +++ b/ui/src/components/Accordion/ContractStateAccordion.tsx @@ -127,7 +127,7 @@ export const ContractStateAccordion: React.FC = () => { {contractListeners ?.filter((l) => l.address === api.address) - .map((l) => { + .map((l, idx) => { return ( { direction="row" justifyContent="space-between" alignItems="flex-start" + key={idx} > = ({ endpoint, payload, disabled }) => { alignItems={'center'} > - + {t('waitingForTxEventsToFinish')}