From 52282e4c0328ebc580bac1b10af076d1a0639968 Mon Sep 17 00:00:00 2001 From: Thomas Zemp Date: Fri, 24 Mar 2023 15:01:42 +0100 Subject: [PATCH] feat: improve copy/past text [DHIS2-15012] --- i18n/en.pot | 53 +++++++- i18n/fr.po | 49 +++++++- src/bottom-bar/bottom-bar.js | 2 +- src/submit-modal/submit-modal.js | 13 +- src/submit-modal/success-content.js | 118 ++++++++++++++---- .../use-aggregate-data-exchange-mutation.js | 5 +- 6 files changed, 206 insertions(+), 34 deletions(-) diff --git a/i18n/en.pot b/i18n/en.pot index dd609b3..1d3d14d 100644 --- a/i18n/en.pot +++ b/i18n/en.pot @@ -5,8 +5,8 @@ msgstr "" "Content-Type: text/plain; charset=utf-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=(n != 1)\n" -"POT-Creation-Date: 2022-11-02T09:25:00.426Z\n" -"PO-Revision-Date: 2022-11-02T09:25:00.426Z\n" +"POT-Creation-Date: 2023-03-24T13:11:23.515Z\n" +"PO-Revision-Date: 2023-03-24T13:11:23.515Z\n" msgid "Aggregate data exchange information is not accessible" msgstr "Aggregate data exchange information is not accessible" @@ -79,6 +79,15 @@ msgstr "Exchange content not accessible" msgid "Click to refresh" msgstr "Click to refresh" +msgid "Conflicts" +msgstr "Conflicts" + +msgid "Object" +msgstr "Object" + +msgid "Value" +msgstr "Value" + msgid "Submitting..." msgstr "Submitting..." @@ -138,6 +147,43 @@ msgstr "Are you sure you want to submit this data?" msgid "Submitting data" msgstr "Submitting data" +msgid "imported" +msgstr "imported" + +msgid "updated" +msgstr "updated" + +msgid "ignored" +msgstr "ignored" + +msgid "Exchange: {{- exchangeName}}" +msgstr "Exchange: {{- exchangeName}}" + +msgid "Target URL: {{- exchangeURL}}" +msgstr "Target URL: {{- exchangeURL}}" + +msgid "Run date: {{- runDate}}" +msgstr "Run date: {{- runDate}}" + +msgid "SUMMARY" +msgstr "SUMMARY" + +msgid "" +"Imported: {{importedCount}}, Updated: {{updatedCount}}, Ignored: " +"{{ignoredCount}}" +msgstr "" +"Imported: {{importedCount}}, Updated: {{updatedCount}}, Ignored: " +"{{ignoredCount}}" + +msgid "DETAILS" +msgstr "DETAILS" + +msgid "Report: {{- requestName}}" +msgstr "Report: {{- requestName}}" + +msgid "Report" +msgstr "Report" + msgid "Imported" msgstr "Imported" @@ -147,9 +193,6 @@ msgstr "Updated" msgid "Ignored" msgstr "Ignored" -msgid "Report" -msgstr "Report" - msgid "Copy summary to clipboard" msgstr "Copy summary to clipboard" diff --git a/i18n/fr.po b/i18n/fr.po index 438d54f..15c16fd 100644 --- a/i18n/fr.po +++ b/i18n/fr.po @@ -129,7 +129,7 @@ msgid "Ignored" msgstr "Ignorés" msgid "Copy summary to clipboard" -msgstr "Copier l'information sommaire vers lcde presse-papier" +msgstr "Copier l'information sommaire vers le presse-papier" msgid "Data submitted successfully." msgstr "Les données ont été envoyées avec succès." @@ -148,3 +148,50 @@ msgstr "Échange de données" msgid "Choose a data exchange" msgstr "Choisir un échange de données" + +msgid "Exchange: {{- exchangeName}}" +msgstr "Echange: {{- exchangeName}}" + +msgid "Target URL: {{- exchangeURL}}" +msgstr "URL destination: {{- exchangeURL}}" + +msgid "Run date: {{- runDate}}" +msgstr "Date d'éxécution: {{- runDate}}" + +msgid "SUMMARY" +msgstr "SOMMAIRE" + +msgid "" +"Imported: {{importedCount}}, Updated: {{updatedCount}}, Ignored: " +"{{ignoredCount}}" +msgstr "" +"Importés: {{importedCount}}, Mis-à-jour: {{updatedCount}}, Ignorés: " +"{{ignoredCount}}" + +msgid "DETAILS" +msgstr "DETAILS" + +msgid "Report: {{- requestName}}" +msgstr "Rapport: {{- requestName}}" + +msgid "Conflicts" +msgstr "Conflits" + +msgid "imported" +msgstr "importés" + +msgid "updated" +msgstr "mis-à-jour" + +msgid "ignored" +msgstr "ignorés" + +msgid "Report" +msgstr "Rapport" + + +msgid "Object" +msgstr "Objet" + +msgid "Value" +msgstr "Valeur" \ No newline at end of file diff --git a/src/bottom-bar/bottom-bar.js b/src/bottom-bar/bottom-bar.js index 2af4441..3d78a3c 100644 --- a/src/bottom-bar/bottom-bar.js +++ b/src/bottom-bar/bottom-bar.js @@ -43,7 +43,7 @@ const BottomBar = ({ openSubmitModal, dataSubmitted }) => { } BottomBar.propTypes = { - dataSubmitted: PropTypes.bool, + dataSubmitted: PropTypes.string, openSubmitModal: PropTypes.func, } export { BottomBar } diff --git a/src/submit-modal/submit-modal.js b/src/submit-modal/submit-modal.js index cb8b5c1..c5167ea 100644 --- a/src/submit-modal/submit-modal.js +++ b/src/submit-modal/submit-modal.js @@ -79,11 +79,11 @@ ErrorModalContent.propTypes = { onRetry: PropTypes.func, } -const SuccessModalContent = ({ onClose, data }) => ( +const SuccessModalContent = ({ onClose, data, dataSubmitted }) => ( <> - + @@ -97,6 +97,7 @@ const SuccessModalContent = ({ onClose, data }) => ( SuccessModalContent.propTypes = { data: PropTypes.object, + dataSubmitted: PropTypes.string, onClose: PropTypes.func, } @@ -295,7 +296,13 @@ const SubmitModal = ({ open, onClose, setDataSubmitted }) => { onClose={onClose} /> )} - {data && } + {data && ( + + )} {loading && } ) diff --git a/src/submit-modal/success-content.js b/src/submit-modal/success-content.js index 9ccb0c0..5fb22bc 100644 --- a/src/submit-modal/success-content.js +++ b/src/submit-modal/success-content.js @@ -21,15 +21,15 @@ import styles from './success-content.module.css' const importTypeConfig = { imported: { style: 'success', - text: i18n.t('Imported'), + text: i18n.t('imported'), }, updated: { style: 'success', - text: i18n.t('Updated'), + text: i18n.t('updated'), }, ignored: { style: 'ignored', - text: i18n.t('Ignored'), + text: i18n.t('ignored'), }, } @@ -42,7 +42,7 @@ const SummaryBox = ({ importType, importCount }) => {
{importCount}
- {text.toLowerCase()} + {i18n.t(text)}
@@ -53,34 +53,94 @@ SummaryBox.propTypes = { importType: PropTypes.string, } -const copyTableToClipboard = ({ importSummaries, requests }) => { - const headerRowText = [ - i18n.t('Report'), - i18n.t('Imported'), - i18n.t('Updated'), - i18n.t('Ignored'), - ].join() - const clipboardText = importSummaries.reduce( +const getConflictLines = (conflicts) => { + if (!conflicts) { + return '' + } + return conflicts + .map((conflict) => `${conflict.object}: ${conflict.value}`) + .join('\n') +} + +const copyTableToClipboard = ({ + exchangeName, + exchangeURL, + importSummaries, + summaryCounts, + requests, + dataSubmitted, +}) => { + let text = '' + const exchangeNameLine = i18n.t('Exchange: {{- exchangeName}}', { + exchangeName, + nsSeparator: '-:-', + }) + const targetURLLine = i18n.t('Target URL: {{- exchangeURL}}', { + exchangeURL: decodeURI(exchangeURL), + nsSeparator: '-:-', + }) + const runDateLine = i18n.t('Run date: {{- runDate}}', { + runDate: dataSubmitted, + nsSeparator: '-:-', + }) + + if (exchangeURL) { + text += `${exchangeNameLine}\n${targetURLLine}` + } else { + text += exchangeNameLine + } + text += '\n' + runDateLine + '\n\n\n' + i18n.t('SUMMARY') + '\n' + + const summaryLine = i18n.t( + 'Imported: {{importedCount}}, Updated: {{updatedCount}}, Ignored: {{ignoredCount}}', + { + importedCount: summaryCounts.imported, + updatedCount: summaryCounts.updated, + ignoredCount: summaryCounts.ignored, + nsSeparator: '-:-', + } + ) + text += summaryLine + '\n\n\n' + i18n.t('DETAILS') + + const detailsText = importSummaries.reduce( (fullText, importSummary, index) => { let requestName = requests?.[index]?.name ?? '' if (requests?.[index]?.name?.includes(',')) { requestName = `"${requests?.[index]?.name}"` } + const requestNameLine = i18n.t('Report: {{- requestName}}', { + requestName, + nsSeparator: '-:-', + }) + const importedCount = importSummary.importCount?.imported + const ignoredCount = importSummary.importCount?.ignored + const updatedCount = importSummary.importCount?.updated + const summaryCountLine = i18n.t( + 'Imported: {{importedCount}}, Updated: {{updatedCount}}, Ignored: {{ignoredCount}}', + { + importedCount, + updatedCount, + ignoredCount, + nsSeparator: '-:-', + } + ) + const conflictLines = getConflictLines(importSummary.conflicts) return ( fullText + + '\n\n' + + requestNameLine + '\n' + - [ - requestName, - importSummary.importCount?.imported, - importSummary.importCount?.updated, - importSummary.importCount?.ignored, - ].join() + summaryCountLine + + '\n' + + conflictLines ) }, - headerRowText + '' ) - navigator.clipboard.writeText(clipboardText) + text += detailsText + + navigator.clipboard.writeText(text) } const SummaryRow = ({ @@ -124,7 +184,12 @@ SummaryRow.propTypes = { importSummary: PropTypes.object, } -const SummaryTable = ({ importSummaries, hasConflicts }) => { +const SummaryTable = ({ + importSummaries, + summaryCounts, + hasConflicts, + dataSubmitted, +}) => { const { exchange } = useExchangeContext() const [expandedRows, setExpandedRows] = useState([]) @@ -177,8 +242,12 @@ const SummaryTable = ({ importSummaries, hasConflicts }) => { icon={} onClick={() => { copyTableToClipboard({ + exchangeName: exchange.displayName, + exchangeURL: exchange.target?.api?.url, importSummaries, + summaryCounts, requests: exchange?.source?.requests, + dataSubmitted, }) }} > @@ -190,11 +259,13 @@ const SummaryTable = ({ importSummaries, hasConflicts }) => { } SummaryTable.propTypes = { + dataSubmitted: PropTypes.string, hasConflicts: PropTypes.bool, importSummaries: PropTypes.array, + summaryCounts: PropTypes.object, } -const SuccessContent = ({ data }) => { +const SuccessContent = ({ data, dataSubmitted }) => { const { importSummaries } = data const summaryCounts = importSummaries.reduce( @@ -240,7 +311,9 @@ const SuccessContent = ({ data }) => { 0} + dataSubmitted={dataSubmitted} /> ) @@ -248,6 +321,7 @@ const SuccessContent = ({ data }) => { SuccessContent.propTypes = { data: PropTypes.object, + dataSubmitted: PropTypes.submitted, } export { SuccessContent } diff --git a/src/submit-modal/use-aggregate-data-exchange-mutation.js b/src/submit-modal/use-aggregate-data-exchange-mutation.js index b9afbc3..1ee79eb 100644 --- a/src/submit-modal/use-aggregate-data-exchange-mutation.js +++ b/src/submit-modal/use-aggregate-data-exchange-mutation.js @@ -1,5 +1,6 @@ import { useDataEngine } from '@dhis2/app-runtime' import i18n from '@dhis2/d2-i18n' +import moment from 'moment' import { useEffect, useReducer, useState } from 'react' const getMutation = ({ id }) => ({ @@ -25,7 +26,7 @@ const submitReducer = (state, action) => { error: null, loading: false, called: true, - dataSubmitted: true, + dataSubmitted: moment().format(), } case 'error': return { @@ -33,7 +34,7 @@ const submitReducer = (state, action) => { error: action.payload, loading: false, called: false, - dataSubmitted: false, + dataSubmitted: null, } case 'reset': return { ...uncalledState }