on master help sign in
Merge pull request #861 from willbach/download-csv-modal

Download CSV modal

commita0e0e3d9532df4d8e0d48101a069243580c200ac authortomholford <16504501+tomholford@users.noreply.github.com> dateTue 21 Dec 2021, 13:07 (5 years ago) parent7ad1ff576aa386
5 files changed+104−15
src/components/L2/Modal.scss+1 src/components/L2/Modal.tsx+12−4 src/views/Activate/MasterKeyReveal.tsx+3−3 src/views/Invite/Cohort.scss+38 src/views/Invite/Cohort.tsx+50−8
src/components/L2/Modal.scss+1
@@ -11,6 +11,7 @@
1111 flex-direction: column;
1212 justify-content: center;
1313 align-items: center;
14+ z-index: 2;
1415
1516 .close {
1617 position: absolute;
src/components/L2/Modal.tsx+12−4
@@ -6,10 +6,16 @@ import './Modal.scss';
66export interface ModalProps {
77 show: boolean;
88 hide: () => void;
9+ hideClose?: boolean;
910 children: React.ReactNode;
1011}
1112
12−export default function Modal({ show, hide, children }: ModalProps) {
13+export default function Modal({
14+ show,
15+ hide,
16+ hideClose = false,
17+ children,
18+}: ModalProps) {
1319 const dontHide = (e: MouseEvent) => {
1420 e.stopPropagation();
1521 };
@@ -21,9 +27,11 @@ export default function Modal({ show, hide, children }: ModalProps) {
2127 return (
2228 <Box className="modal" onClick={hide}>
2329 <Box className="content">
24− <Box className="close" onClick={hide}>
25− &#215;
26− </Box>
30+ {!hideClose && (
31+ <Box className="close" onClick={hide}>
32+ &#215;
33+ </Box>
34+ )}
2735 <Box onClick={dontHide}>{children}</Box>
2836 </Box>
2937 </Box>
src/views/Activate/MasterKeyReveal.tsx+3−3
@@ -14,8 +14,8 @@ import { DEFAULT_FADE_TIMEOUT, MASTER_KEY_DURATION } from 'lib/constants';
1414import View from 'components/View';
1515
1616const MasterKeyReveal = () => {
17− const { setIsIn } = useActivateFlow();
18− const { push, names } = useLocalRouter();
17+ const { setIsIn }: any = useActivateFlow();
18+ const { pop, push, names }: any = useLocalRouter();
1919 const [triggerAnimation, setTriggerAnimation] = useState<boolean>(false);
2020 const [fadeOutKey, setFadeOutKey] = useState<boolean>(false);
2121
@@ -74,7 +74,7 @@ const MasterKeyReveal = () => {
7474 }, [delayedFadeIn, setIsIn]);
7575
7676 return (
77− <View centered={true}>
77+ <View centered={true} pop={pop} header={null} className="">
7878 <ActivateView
7979 header={triggerAnimation && header}
8080 footer={triggerAnimation && footer}>
src/views/Invite/Cohort.scss+38
@@ -220,4 +220,42 @@
220220 font-size: 14px;
221221 line-height: 1.4em;
222222 }
223+
224+ .download-csv-modal {
225+ height: 167px;
226+ width: 333px;
227+ display: flex;
228+ flex-direction: column;
229+ justify-content: space-between;
230+ font-weight: 500;
231+
232+ .download-buttons {
233+ justify-content: flex-end;
234+
235+ .close-button, .download-button {
236+ padding: 4px 16px;
237+
238+ &:hover {
239+ opacity: 0.8;
240+ }
241+ }
242+
243+ .close-button {
244+ color: black;
245+ background-color: $washed-gray;
246+ margin-right: 8px;
247+ }
248+ }
249+ }
250+
251+ .csv-loading {
252+ position: absolute;
253+ top: 24px;
254+ right: 24px;
255+
256+ svg {
257+ width: 16px;
258+ height: 16px;
259+ }
260+ }
223261}
src/views/Invite/Cohort.tsx+50−8
@@ -49,6 +49,7 @@ import Paginator from 'components/L2/Paginator';
4949import InlineEthereumTransaction from 'components/InlineEthereumTransaction';
5050
5151import './Cohort.scss';
52+import Modal from 'components/L2/Modal';
5253
5354interface L1Invite {
5455 ticket: string;
@@ -89,6 +90,8 @@ export default function InviteCohort() {
8990 );
9091 const [showInviteForm, setShowInviteForm] = useState(false);
9192 const [loading, setLoading] = useState(false);
93+ const [showCsvModal, setShowCsvModal] = useState(false);
94+ const [csvElement, setCsvElement] = useState<HTMLAnchorElement | null>();
9295 const [error, setError] = useState('');
9396 const [l1Invite, setL1Invite] = useState<L1Invite | null>(null);
9497 const [page, setPage] = useState(0);
@@ -215,9 +218,10 @@ export default function InviteCohort() {
215218 point,
216219 ]);
217220
218− const downloadCsv = useCallback(() => {
219− const generateAndDownload = async () => {
221+ const generateCsv = useCallback(() => {
222+ const generateCsvElement = async () => {
220223 setLoading(true);
224+ setShowCsvModal(true);
221225 const invites = await getInvites();
222226 if (invites) {
223227 const csv = invites.reduce(
@@ -225,26 +229,35 @@ export default function InviteCohort() {
225229 (csvData += generateCsvLine(ind, ticket, planet)),
226230 'Number,Planet,Invite URL,Point,Ticket\n'
227231 );
232+ document.getElementById('csv')?.remove();
228233 const hiddenElement = document.createElement('a');
229234 hiddenElement.href = `data:text/csv;charset=utf-8,${encodeURIComponent(
230235 csv
231236 )}`;
232237 hiddenElement.target = '_blank';
238+ hiddenElement.id = 'csv';
233239
234240 //provide the name for the CSV file to be downloaded
235241 hiddenElement.download = generateCsvName(
236242 DEFAULT_CSV_NAME,
237243 point.patp?.slice(1) || 'bridge'
238244 );
239− hiddenElement.click();
245+ setCsvElement(hiddenElement);
240246 } else {
241247 setError('There was an error creating the CSV');
242248 }
243249 setLoading(false);
244250 setInviteGeneratingNum(0);
245251 };
246− generateAndDownload();
247− }, [getInvites, setError, setLoading, setInviteGeneratingNum, point]);
252+ generateCsvElement();
253+ }, [
254+ getInvites,
255+ setError,
256+ setLoading,
257+ setInviteGeneratingNum,
258+ setShowCsvModal,
259+ point,
260+ ]);
248261
249262 const goNextPage = useCallback(() => {
250263 setPage(page + 1);
@@ -425,7 +438,7 @@ export default function InviteCohort() {
425438 const showGenerateButton = !hasPending && !hasInvites && point.canSpawn;
426439 const showAddMoreButton =
427440 (hasInvites || hasPending) && point.canSpawn && point.l2Quota > 0;
428− const generatingCodesText = `Generating invite code ${inviteGeneratingNum} of ${invitePoints.length}...`;
441+ const generatingCodesText = `Generating ${inviteGeneratingNum} of ${invitePoints.length} codes...`;
429442
430443 return (
431444 <View
@@ -441,7 +454,7 @@ export default function InviteCohort() {
441454 ) : (
442455 <Row className="has-invites-header">
443456 {header}
444− <Row className="download-csv" onClick={downloadCsv}>
457+ <Row className="download-csv" onClick={generateCsv}>
445458 <Icon icon="Download" />
446459 <Box>CSV</Box>
447460 </Row>
@@ -486,7 +499,36 @@ export default function InviteCohort() {
486499 <strong>{` ${ddmmmYYYY(nextQuotaTime)}`}</strong>.
487500 </Box>
488501 ) : null}
489− <LoadingOverlay loading={loading} text={generatingCodesText} />
502+ <Modal show={showCsvModal} hide={() => setShowCsvModal(false)} hideClose>
503+ <Box className="download-csv-modal">
504+ <Box>
505+ <Box>Download CSV</Box>
506+ {loading && <Box>{generatingCodesText}</Box>}
507+ </Box>
508+ <Row className="download-buttons">
509+ <Button
510+ center
511+ className="ph4 close-button"
512+ solid
513+ onClick={() => setShowCsvModal(false)}>
514+ Close
515+ </Button>
516+ <Button
517+ center
518+ className="ph4 download-button"
519+ disabled={loading}
520+ solid
521+ onClick={() => csvElement?.click()}>
522+ Download CSV
523+ </Button>
524+ </Row>
525+ </Box>
526+ {loading && (
527+ <Box className="csv-loading">
528+ <LoadingSpinner background="#BCDCFF" foreground="#219DFF" />
529+ </Box>
530+ )}
531+ </Modal>
490532 </View>
491533 );
492534}