From b334a68491f019432d02867d02b312e9ea6990d7 Mon Sep 17 00:00:00 2001 From: Viet Anh Date: Tue, 22 Jun 2021 16:56:28 +0700 Subject: [PATCH 1/8] adjust download bundle: show loading wheel while the data is being fetched; show progress for paginated downloads only when there are more than 1 page --- src/components/DownloadJSON.jsx | 27 ++++++++++++------- src/components/Proposal/Proposal.jsx | 4 +-- .../Download/DownloadCommentsTimestamps.jsx | 16 ++++++----- src/containers/Comments/Download/hooks.js | 8 +++--- .../Download/DownloadVotesTimestamps.jsx | 8 +++--- src/containers/Proposal/Download/hooks.js | 8 ++++-- 6 files changed, 42 insertions(+), 29 deletions(-) diff --git a/src/components/DownloadJSON.jsx b/src/components/DownloadJSON.jsx index 984ffcb19..7f6780855 100644 --- a/src/components/DownloadJSON.jsx +++ b/src/components/DownloadJSON.jsx @@ -1,7 +1,7 @@ -import React from "react"; +import React, { useState } from "react"; import PropTypes from "prop-types"; import fileDownload from "js-file-download"; -import { Link } from "pi-ui"; +import { Link, Spinner } from "pi-ui"; const isPromise = (obj) => obj && typeof obj.then === "function"; @@ -24,13 +24,16 @@ const DownloadJSON = ({ beforeDownload, ...props }) => { + const [asyncLoading, setAsyncLoading] = useState(false); function onDownload() { const data = JSON.stringify(content, null, 2); fileDownload(data, `${fileName}.json`); } function handleDownload() { + setAsyncLoading(true); beforeDownload().then((response) => { + setAsyncLoading(false); const data = JSON.stringify(response, null, 2); fileDownload(data, `${fileName}.json`); }); @@ -41,14 +44,18 @@ const DownloadJSON = ({ ) : ( ( - - {label} - - )} + customComponent={(props) => + isAsync && asyncLoading ? ( + + ) : ( + + {label} + + ) + } /> ); }; diff --git a/src/components/Proposal/Proposal.jsx b/src/components/Proposal/Proposal.jsx index 31d402887..8b4f14761 100644 --- a/src/components/Proposal/Proposal.jsx +++ b/src/components/Proposal/Proposal.jsx @@ -431,7 +431,7 @@ const Proposal = React.memo(function Proposal({ )} {isPublic && commentsCount > 0 && ( @@ -446,7 +446,7 @@ const Proposal = React.memo(function Proposal({ )} {votesCount > 0 && ( diff --git a/src/containers/Comments/Download/DownloadCommentsTimestamps.jsx b/src/containers/Comments/Download/DownloadCommentsTimestamps.jsx index 54354088c..45b684648 100644 --- a/src/containers/Comments/Download/DownloadCommentsTimestamps.jsx +++ b/src/containers/Comments/Download/DownloadCommentsTimestamps.jsx @@ -23,20 +23,22 @@ const DownloadCommentsTimestampsWrapper = ({ }; const DownloadCommentsTimestamps = ({ recordToken }) => { - const { loading, progress, timestamps } = + const { loading, progress, timestamps, multiPage } = useDownloadCommentsTimestamps(recordToken); return loading ? (
- {progress}% + {multiPage ? {progress}% : <>}
) : timestamps ? ( - +
+ +
) : null; }; diff --git a/src/containers/Comments/Download/hooks.js b/src/containers/Comments/Download/hooks.js index baee79de0..0088ed9e3 100644 --- a/src/containers/Comments/Download/hooks.js +++ b/src/containers/Comments/Download/hooks.js @@ -43,7 +43,8 @@ export function useDownloadCommentsTimestamps(recordToken) { [recordToken] ); const comments = useSelector(commentsSelector); - const commentsLength = comments.length || 0; + const commentsLength = comments?.length || 0; + const multiPage = commentsLength > TIMESTAMPS_PAGE_SIZE; const onFetchCommentsTimestamps = useAction(act.onFetchCommentsTimestamps); useEffect(() => { @@ -94,7 +95,7 @@ export function useDownloadCommentsTimestamps(recordToken) { }, start: () => { // fetch first page of comments timestamps - const [fetch, next] = getCommentIdsForPagination(remaining); + const [fetch, next] = getCommentIdsForPagination(remaining || []); onFetchCommentsTimestamps(recordToken, fetch) .then(({ comments }) => { setTimestamps({ comments }); @@ -147,6 +148,7 @@ export function useDownloadCommentsTimestamps(recordToken) { progress: progress, timestamps: { comments: state.timestamps?.comments - } + }, + multiPage: multiPage }; } diff --git a/src/containers/Proposal/Download/DownloadVotesTimestamps.jsx b/src/containers/Proposal/Download/DownloadVotesTimestamps.jsx index 6eaa41aa5..64e231ac9 100644 --- a/src/containers/Proposal/Download/DownloadVotesTimestamps.jsx +++ b/src/containers/Proposal/Download/DownloadVotesTimestamps.jsx @@ -26,14 +26,12 @@ const DownloadVotesTimestampsWrapper = ({ label, recordToken, votesCount }) => { }; const DownloadVotesTimestamps = ({ recordToken, votesCount }) => { - const { timestamps, progress, loading, error } = useDownloadVoteTimestamps( - recordToken, - votesCount - ); + const { timestamps, progress, loading, error, multiPage } = + useDownloadVoteTimestamps(recordToken, votesCount); return loading ? (
- {progress}% + {multiPage ? {progress}% : <>}
) : timestamps ? ( diff --git a/src/containers/Proposal/Download/hooks.js b/src/containers/Proposal/Download/hooks.js index 91095edc5..6b867acc8 100644 --- a/src/containers/Proposal/Download/hooks.js +++ b/src/containers/Proposal/Download/hooks.js @@ -8,18 +8,21 @@ import { loadVotesTimestamps } from "src/lib/local_storage"; +const TIMESTAMPS_PAGE_SIZE = 100; export function useDownloadVoteTimestamps(token, votesCount) { const [votes, setVotes] = useState(null); const [auths, setAuths] = useState(null); const [details, setDetails] = useState(null); const [page, setPage] = useState(1); const [progress, setProgress] = useState(0); + const multiPage = votesCount > TIMESTAMPS_PAGE_SIZE; const onFetchTicketVoteTimestamps = useAction( act.onFetchTicketVoteTimestamps ); const getProgressPercentage = useCallback( - (total) => (total ? ((total * 100) / votesCount).toFixed(2) : 0), + (total) => + total ? ((total * TIMESTAMPS_PAGE_SIZE) / votesCount).toFixed(2) : 0, [votesCount] ); @@ -104,6 +107,7 @@ export function useDownloadVoteTimestamps(token, votesCount) { auths: state.auths, details: state.details, votes: state.votes - } + }, + multiPage: multiPage }; } From 25811aa28d95a630245e6a0e276d9e55a2410cca Mon Sep 17 00:00:00 2001 From: Viet Anh Date: Wed, 23 Jun 2021 01:41:33 +0700 Subject: [PATCH 2/8] fix Download Comments Timestamp progress is wrong value --- src/containers/Comments/Download/hooks.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/containers/Comments/Download/hooks.js b/src/containers/Comments/Download/hooks.js index 0088ed9e3..e90bc509d 100644 --- a/src/containers/Comments/Download/hooks.js +++ b/src/containers/Comments/Download/hooks.js @@ -60,7 +60,7 @@ export function useDownloadCommentsTimestamps(recordToken) { const getProgressPercentage = useCallback( (timestamps) => timestamps - ? (Object.keys(timestamps.length * 100) / commentsLength).toFixed(2) + ? ((Object.keys(timestamps).length * 100) / commentsLength).toFixed(2) : 0, [commentsLength] ); From 7093c8e74add23a4f7084525ff4a3c0f14ef01b5 Mon Sep 17 00:00:00 2001 From: Viet Anh Date: Wed, 30 Jun 2021 23:09:50 +0700 Subject: [PATCH 3/8] fix javascript compact syntax, fix html redundant tag --- .../Download/DownloadCommentsTimestamps.jsx | 14 ++++++-------- src/containers/Comments/Download/hooks.js | 2 +- .../Proposal/Download/DownloadVotesTimestamps.jsx | 2 +- 3 files changed, 8 insertions(+), 10 deletions(-) diff --git a/src/containers/Comments/Download/DownloadCommentsTimestamps.jsx b/src/containers/Comments/Download/DownloadCommentsTimestamps.jsx index 45b684648..1e14556bf 100644 --- a/src/containers/Comments/Download/DownloadCommentsTimestamps.jsx +++ b/src/containers/Comments/Download/DownloadCommentsTimestamps.jsx @@ -28,17 +28,15 @@ const DownloadCommentsTimestamps = ({ recordToken }) => { return loading ? (
- {multiPage ? {progress}% : <>} + {multiPage && {progress}%}
) : timestamps ? ( -
- -
+ ) : null; }; diff --git a/src/containers/Comments/Download/hooks.js b/src/containers/Comments/Download/hooks.js index e90bc509d..36752c920 100644 --- a/src/containers/Comments/Download/hooks.js +++ b/src/containers/Comments/Download/hooks.js @@ -60,7 +60,7 @@ export function useDownloadCommentsTimestamps(recordToken) { const getProgressPercentage = useCallback( (timestamps) => timestamps - ? ((Object.keys(timestamps).length * 100) / commentsLength).toFixed(2) + ? ((Object.keys(timestamps).length * 100) / commentsLength).toFixed(0) : 0, [commentsLength] ); diff --git a/src/containers/Proposal/Download/DownloadVotesTimestamps.jsx b/src/containers/Proposal/Download/DownloadVotesTimestamps.jsx index 64e231ac9..8ace22c4f 100644 --- a/src/containers/Proposal/Download/DownloadVotesTimestamps.jsx +++ b/src/containers/Proposal/Download/DownloadVotesTimestamps.jsx @@ -31,7 +31,7 @@ const DownloadVotesTimestamps = ({ recordToken, votesCount }) => { return loading ? (
- {multiPage ? {progress}% : <>} + {multiPage && {progress}%}
) : timestamps ? ( From 30987c5eb59727b974b0f2bec76a2b63f5c554d4 Mon Sep 17 00:00:00 2001 From: Viet Anh Date: Sat, 3 Jul 2021 17:00:42 +0700 Subject: [PATCH 4/8] cache --- src/actions/api.js | 19 +++++++++++++++++++ src/actions/types.js | 3 +++ src/components/Proposal/Proposal.jsx | 2 ++ .../RecordWrapper/RecordWrapper.jsx | 18 +++++++++++++++--- src/hooks/api/useTimestamps.js | 4 +++- src/reducers/api.js | 2 ++ 6 files changed, 44 insertions(+), 4 deletions(-) diff --git a/src/actions/api.js b/src/actions/api.js index 4769e9715..619f68f02 100644 --- a/src/actions/api.js +++ b/src/actions/api.js @@ -1730,3 +1730,22 @@ export const onFetchCommentsTimestamps = (token, commentsids) => // Ticket Vote actions export const onFetchTicketVoteTimestamps = (token, votespage) => withCsrf((__, _, csrf) => api.ticketVoteTimestamps(csrf, token, votespage)); + +// Votes Bundle +export const onFetchVotesBundle = (token, version) => withCsrf(async (dispatch, _, csrf) => { + dispatch(act.REQUEST_VOTES_BUNDLE()); + try { + return await Promise.all([ + api.proposalVoteDetails(csrf, token), + api.recordsTimestamp(csrf, token, version), + api.ticketVoteTimestamps(csrf, token, 1) + ]).then(([details, records]) => { + console.log(details, records) + dispatch(act.RECEIVE_VOTES_BUNDLE(null)); + return { details, records }; + }); + } catch (error) { + dispatch(act.RECEIVE_VOTES_BUNDLE(null, error)); + throw error; + } +}); diff --git a/src/actions/types.js b/src/actions/types.js index 5a8eaf1fa..a9e8eae9d 100644 --- a/src/actions/types.js +++ b/src/actions/types.js @@ -252,3 +252,6 @@ export const REQUEST_VERIFY_TOTP = "API_REQUEST_VERIFY_TOTP"; export const RECEIVE_VERIFY_TOTP = "API_RECEIVE_VERIFY_TOTP"; export const SET_HAS_TOTP = "SET_HAS_TOTP"; + +export const REQUEST_VOTES_BUNDLE = "API_REQUEST_VOTES_BUNDLE"; +export const RECEIVE_VOTES_BUNDLE = "API_RECEIVE_VOTES_BUNDLE"; diff --git a/src/components/Proposal/Proposal.jsx b/src/components/Proposal/Proposal.jsx index 8b4f14761..23e641228 100644 --- a/src/components/Proposal/Proposal.jsx +++ b/src/components/Proposal/Proposal.jsx @@ -442,6 +442,8 @@ const Proposal = React.memo(function Proposal({ voteSummary={voteSummary} fileName={`${proposalToken}-votes`} serverpublickey={apiInfo.pubkey} + token={proposalToken} + version={version} /> )} {votesCount > 0 && ( diff --git a/src/components/RecordWrapper/RecordWrapper.jsx b/src/components/RecordWrapper/RecordWrapper.jsx index e11142b32..62015eb6d 100644 --- a/src/components/RecordWrapper/RecordWrapper.jsx +++ b/src/components/RecordWrapper/RecordWrapper.jsx @@ -337,15 +337,27 @@ export const DownloadVotes = ({ label, voteSummary, fileName, - serverpublickey + serverpublickey, + token, + version }) => { - const bundle = { + /*const bundle = { auths: voteSummary?.details?.auths, details: voteSummary?.details?.details, votes: voteSummary?.votes, serverpublickey }; - return ; + return ;*/ + const { onFetchVotesBundle } = useTimestamps(); + return ( + onFetchVotesBundle(token, version)} + /> + ); }; export const LinkSection = ({ children, className, title }) => ( diff --git a/src/hooks/api/useTimestamps.js b/src/hooks/api/useTimestamps.js index 12ec14bd5..c79d8dba3 100644 --- a/src/hooks/api/useTimestamps.js +++ b/src/hooks/api/useTimestamps.js @@ -7,9 +7,11 @@ export default function useTimestamps() { const onFetchTicketVoteTimestamps = useAction( act.onFetchTicketVoteTimestamps ); + const onFetchVotesBundle = useAction(act.onFetchVotesBundle); return { onFetchRecordTimestamps, onFetchCommentsTimestamps, - onFetchTicketVoteTimestamps + onFetchTicketVoteTimestamps, + onFetchVotesBundle }; } diff --git a/src/reducers/api.js b/src/reducers/api.js index b0365cad9..f54efaed1 100644 --- a/src/reducers/api.js +++ b/src/reducers/api.js @@ -208,6 +208,8 @@ const api = (state = DEFAULT_STATE, action) => [act.RECEIVE_SET_TOTP]: () => receive("setTotp", state, action), [act.REQUEST_VERIFY_TOTP]: () => request("verifyTotp", state, action), [act.RECEIVE_VERIFY_TOTP]: () => receive("verifyTotp", state, action), + [act.REQUEST_VOTES_BUNDLE]: () => request("votesBundle", state, action), + [act.RECEIVE_VOTES_BUNDLE]: () => receive("votesBundle", state, action), // == CMS START == [act.REQUEST_GENERATE_PAYOUTS]: () => request("payouts", state, action), [act.RECEIVE_GENERATE_PAYOUTS]: () => receive("payouts", state, action), From 6f12a0aa62a2a9a7d4ac21cc521d9aac995a1991 Mon Sep 17 00:00:00 2001 From: Viet Anh Date: Mon, 5 Jul 2021 09:18:13 +0700 Subject: [PATCH 5/8] Votes Bundle download data from the server(votes details and vote result) instead of cache data --- src/actions/api.js | 26 +++++++++---------- src/components/Proposal/Proposal.jsx | 3 --- .../RecordWrapper/RecordWrapper.jsx | 23 ++++++---------- 3 files changed, 21 insertions(+), 31 deletions(-) diff --git a/src/actions/api.js b/src/actions/api.js index 619f68f02..26ecd98e0 100644 --- a/src/actions/api.js +++ b/src/actions/api.js @@ -1732,20 +1732,20 @@ export const onFetchTicketVoteTimestamps = (token, votespage) => withCsrf((__, _, csrf) => api.ticketVoteTimestamps(csrf, token, votespage)); // Votes Bundle -export const onFetchVotesBundle = (token, version) => withCsrf(async (dispatch, _, csrf) => { +export const onFetchVotesBundle = (token) => + withCsrf(async (dispatch, _, csrf) => { dispatch(act.REQUEST_VOTES_BUNDLE()); try { - return await Promise.all([ - api.proposalVoteDetails(csrf, token), - api.recordsTimestamp(csrf, token, version), - api.ticketVoteTimestamps(csrf, token, 1) - ]).then(([details, records]) => { - console.log(details, records) - dispatch(act.RECEIVE_VOTES_BUNDLE(null)); - return { details, records }; - }); + return await Promise.all([ + api.proposalVoteDetails(csrf, token), + api.proposalVoteResults(csrf, token) + ]).then(([{ auths, vote }, { votes }]) => { + const response = { auths, detail: vote, votes }; + dispatch(act.RECEIVE_VOTES_BUNDLE(response)); + return response; + }); } catch (error) { - dispatch(act.RECEIVE_VOTES_BUNDLE(null, error)); - throw error; + dispatch(act.RECEIVE_VOTES_BUNDLE(null, error)); + throw error; } -}); + }); diff --git a/src/components/Proposal/Proposal.jsx b/src/components/Proposal/Proposal.jsx index 23e641228..9ca29ba0b 100644 --- a/src/components/Proposal/Proposal.jsx +++ b/src/components/Proposal/Proposal.jsx @@ -439,11 +439,8 @@ const Proposal = React.memo(function Proposal({ {votesCount > 0 && ( )} {votesCount > 0 && ( diff --git a/src/components/RecordWrapper/RecordWrapper.jsx b/src/components/RecordWrapper/RecordWrapper.jsx index 62015eb6d..015aafc36 100644 --- a/src/components/RecordWrapper/RecordWrapper.jsx +++ b/src/components/RecordWrapper/RecordWrapper.jsx @@ -333,14 +333,7 @@ export const DownloadTimestamps = ({ token, version, label }) => { ); }; -export const DownloadVotes = ({ - label, - voteSummary, - fileName, - serverpublickey, - token, - version -}) => { +export const DownloadVotes = ({ label, fileName, token }) => { /*const bundle = { auths: voteSummary?.details?.auths, details: voteSummary?.details?.details, @@ -350,13 +343,13 @@ export const DownloadVotes = ({ return ;*/ const { onFetchVotesBundle } = useTimestamps(); return ( - onFetchVotesBundle(token, version)} - /> + onFetchVotesBundle(token)} + /> ); }; From 8da4581884c7f91941ce2a0f066eb72afdb79c26 Mon Sep 17 00:00:00 2001 From: Viet Anh Date: Tue, 6 Jul 2021 20:00:21 +0700 Subject: [PATCH 6/8] remove unnecessary comments, fix Progress percentage is wrong alighment, remove decimal of progress percentage --- src/components/RecordWrapper/RecordWrapper.jsx | 7 ------- .../Comments/Download/DownloadCommentsTimestamps.jsx | 4 ++-- .../Proposal/Download/DownloadVotesTimestamps.jsx | 4 ++-- src/containers/Proposal/Download/hooks.js | 2 +- 4 files changed, 5 insertions(+), 12 deletions(-) diff --git a/src/components/RecordWrapper/RecordWrapper.jsx b/src/components/RecordWrapper/RecordWrapper.jsx index 015aafc36..63ffbad3c 100644 --- a/src/components/RecordWrapper/RecordWrapper.jsx +++ b/src/components/RecordWrapper/RecordWrapper.jsx @@ -334,13 +334,6 @@ export const DownloadTimestamps = ({ token, version, label }) => { }; export const DownloadVotes = ({ label, fileName, token }) => { - /*const bundle = { - auths: voteSummary?.details?.auths, - details: voteSummary?.details?.details, - votes: voteSummary?.votes, - serverpublickey - }; - return ;*/ const { onFetchVotesBundle } = useTimestamps(); return ( { useDownloadCommentsTimestamps(recordToken); return loading ? ( -
+ <> {multiPage && {progress}%} -
+ ) : timestamps ? ( { useDownloadVoteTimestamps(recordToken, votesCount); return loading ? ( -
+ <> {multiPage && {progress}%} -
+ ) : timestamps ? ( - total ? ((total * TIMESTAMPS_PAGE_SIZE) / votesCount).toFixed(2) : 0, + total ? ((total * TIMESTAMPS_PAGE_SIZE) / votesCount).toFixed(0) : 0, [votesCount] ); From 6b94a034e7022b5c3157f0f181255fe681ffc7d2 Mon Sep 17 00:00:00 2001 From: Viet Anh Date: Wed, 7 Jul 2021 00:10:48 +0700 Subject: [PATCH 7/8] add serverpublickey to the votesBundle download --- src/actions/api.js | 4 ++-- src/components/Proposal/Proposal.jsx | 1 + src/components/RecordWrapper/RecordWrapper.jsx | 4 ++-- 3 files changed, 5 insertions(+), 4 deletions(-) diff --git a/src/actions/api.js b/src/actions/api.js index 26ecd98e0..fed1668cf 100644 --- a/src/actions/api.js +++ b/src/actions/api.js @@ -1732,7 +1732,7 @@ export const onFetchTicketVoteTimestamps = (token, votespage) => withCsrf((__, _, csrf) => api.ticketVoteTimestamps(csrf, token, votespage)); // Votes Bundle -export const onFetchVotesBundle = (token) => +export const onFetchVotesBundle = (token, serverpublickey) => withCsrf(async (dispatch, _, csrf) => { dispatch(act.REQUEST_VOTES_BUNDLE()); try { @@ -1740,7 +1740,7 @@ export const onFetchVotesBundle = (token) => api.proposalVoteDetails(csrf, token), api.proposalVoteResults(csrf, token) ]).then(([{ auths, vote }, { votes }]) => { - const response = { auths, detail: vote, votes }; + const response = { auths, detail: vote, votes, serverpublickey }; dispatch(act.RECEIVE_VOTES_BUNDLE(response)); return response; }); diff --git a/src/components/Proposal/Proposal.jsx b/src/components/Proposal/Proposal.jsx index 9ca29ba0b..116b92fa9 100644 --- a/src/components/Proposal/Proposal.jsx +++ b/src/components/Proposal/Proposal.jsx @@ -440,6 +440,7 @@ const Proposal = React.memo(function Proposal({ )} diff --git a/src/components/RecordWrapper/RecordWrapper.jsx b/src/components/RecordWrapper/RecordWrapper.jsx index 63ffbad3c..94e35117e 100644 --- a/src/components/RecordWrapper/RecordWrapper.jsx +++ b/src/components/RecordWrapper/RecordWrapper.jsx @@ -333,7 +333,7 @@ export const DownloadTimestamps = ({ token, version, label }) => { ); }; -export const DownloadVotes = ({ label, fileName, token }) => { +export const DownloadVotes = ({ label, fileName, serverpublickey, token }) => { const { onFetchVotesBundle } = useTimestamps(); return ( { fileName={fileName} isAsync={true} content={[]} - beforeDownload={() => onFetchVotesBundle(token)} + beforeDownload={() => onFetchVotesBundle(token, serverpublickey)} /> ); }; From cc0ca18f8b39c58fb7c08334376db3568f962410 Mon Sep 17 00:00:00 2001 From: Viet Anh Date: Wed, 7 Jul 2021 00:34:35 +0700 Subject: [PATCH 8/8] change name of votesbulde back to details from detail --- src/actions/api.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/actions/api.js b/src/actions/api.js index fed1668cf..83cf34bb9 100644 --- a/src/actions/api.js +++ b/src/actions/api.js @@ -1740,7 +1740,7 @@ export const onFetchVotesBundle = (token, serverpublickey) => api.proposalVoteDetails(csrf, token), api.proposalVoteResults(csrf, token) ]).then(([{ auths, vote }, { votes }]) => { - const response = { auths, detail: vote, votes, serverpublickey }; + const response = { auths, details: vote, votes, serverpublickey }; dispatch(act.RECEIVE_VOTES_BUNDLE(response)); return response; });