From a36f22a9d7cb177c8b9b7d032575b0b9416bfb93 Mon Sep 17 00:00:00 2001 From: Jan Date: Tue, 14 May 2024 09:41:45 +0200 Subject: [PATCH 1/3] CM-808: add aggregation column for import --- .../dialogs/IndividualsUploadDialog.js | 82 +++++++++++++++++-- src/constants.js | 1 + src/translations/en.json | 4 +- 3 files changed, 81 insertions(+), 6 deletions(-) diff --git a/src/components/dialogs/IndividualsUploadDialog.js b/src/components/dialogs/IndividualsUploadDialog.js index 684d3c8..2afa50c 100644 --- a/src/components/dialogs/IndividualsUploadDialog.js +++ b/src/components/dialogs/IndividualsUploadDialog.js @@ -1,5 +1,7 @@ import React, { useEffect, useState } from 'react'; -import { Input, Grid, MenuItem } from '@material-ui/core'; +import { + Input, Grid, MenuItem, Typography, Select, +} from '@material-ui/core'; import { injectIntl } from 'react-intl'; import Button from '@material-ui/core/Button'; import Dialog from '@material-ui/core/Dialog'; @@ -12,6 +14,7 @@ import { useModulesManager, formatMessage, coreAlert, + FormattedMessage, } from '@openimis/fe-core'; import { withTheme, withStyles } from '@material-ui/core/styles'; import { connect } from 'react-redux'; @@ -19,7 +22,7 @@ import { bindActionCreators } from 'redux'; import WorkflowsPicker from '../../pickers/WorkflowsPicker'; import { fetchWorkflows } from '../../actions'; import IndividualsHistoryUploadDialog from './IndividualsHistoryUploadDialog'; -import { EMPTY_STRING } from '../../constants'; +import {EMPTY_STRING, INDIVIDUAL_MODULE_NAME, PYTHON_DEFAULT_IMPORT_WORKFLOW} from '../../constants'; const styles = (theme) => ({ item: theme.paper.item, @@ -34,6 +37,39 @@ function IndividualsUploadDialog({ const modulesManager = useModulesManager(); const [isOpen, setIsOpen] = useState(false); const [forms, setForms] = useState({}); + const [headers, setHeaders] = useState([]); + const [groupAggregationHeader, setGroupAggregationHeader] = useState(null); + + const getHeadersFromCSV = async (file) => new Promise((resolve, reject) => { + const reader = new FileReader(); + + reader.onload = (event) => { + const csvData = event.target.result; + const firstLine = csvData.substring(0, csvData.indexOf('\n')); // Get only the first line + const headers = firstLine.split(','); + if (headers.length && !headers.some((item) => !item)) { + headers.unshift(''); + } + resolve(headers); + }; + + reader.onerror = (error) => { + reject(error); + }; + + reader.readAsText(file); + }); + + const handleFileInputChange = async (selectedFile) => { + if (selectedFile) { + try { + const fileHeaders = await getHeadersFromCSV(selectedFile); + setHeaders(fileHeaders); + } catch (error) { + setHeaders([]); + } + } + }; const handleOpen = () => { setIsOpen(true); @@ -41,6 +77,7 @@ function IndividualsUploadDialog({ const handleClose = () => { setForms({}); + setHeaders([]); setIsOpen(false); }; @@ -48,7 +85,8 @@ function IndividualsUploadDialog({ fetchWorkflows(); }, []); - const handleFieldChange = (formName, fieldName, value) => { + const handleFieldChange = async (formName, fieldName, value) => { + await handleFileInputChange(value); setForms({ ...forms, [formName]: { @@ -58,7 +96,7 @@ function IndividualsUploadDialog({ }); }; - const getFieldValue = () => forms?.workflows?.values?.workflow?.label ?? {}; + const getFieldValue = () => forms?.workflows?.workflow?.name ?? {}; const onSubmit = async (values) => { const fileFormat = values.file.type; @@ -70,6 +108,7 @@ function IndividualsUploadDialog({ if (fileFormat.includes('/csv')) { formData.append('workflow_name', values.workflow.name); formData.append('workflow_group', values.workflow.group); + formData.append('group_aggregation_column', groupAggregationHeader); urlImport = `${baseApiUrl}/individual/import_individuals/`; } @@ -151,7 +190,7 @@ function IndividualsUploadDialog({ handleFieldChange('workflows', 'workflow', value)} value={() => getFieldValue()} @@ -160,6 +199,39 @@ function IndividualsUploadDialog({ /> + {getFieldValue() === PYTHON_DEFAULT_IMPORT_WORKFLOW ? ( + + + + + + + + + + + + + + * + {' '} + + + + + ) : null} diff --git a/src/constants.js b/src/constants.js index 2e00542..632b698 100644 --- a/src/constants.js +++ b/src/constants.js @@ -88,3 +88,4 @@ export const UPLOAD_STATUS = { FAIL: 'FAIL', }; export const INDIVIDUALS_QUANTITY_LIMIT = 15; +export const PYTHON_DEFAULT_IMPORT_WORKFLOW = 'Python Import Individuals'; diff --git a/src/translations/en.json b/src/translations/en.json index 079be28..aa8aedd 100644 --- a/src/translations/en.json +++ b/src/translations/en.json @@ -244,5 +244,7 @@ "confirm": "Confirm", "cancel": "Cancel", "changeGroupButtonTooltip": "Move to another group.", - "moveToNewGroup": "New Group" + "moveToNewGroup": "New Group", + "createGroupFromColumns": "Create groups from column:", + "groupAggregationInfo": "To specify recipients include header 'recipient_info' with possible values: '1' - head, '2' - recipient, '0' or empty - not a recipient." } \ No newline at end of file From 9b03226c87b94e30fd06cd397aee4f01479cd823 Mon Sep 17 00:00:00 2001 From: Jan Date: Tue, 14 May 2024 12:49:21 +0200 Subject: [PATCH 2/3] CM-808: fix headers --- src/components/dialogs/IndividualsUploadDialog.js | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/components/dialogs/IndividualsUploadDialog.js b/src/components/dialogs/IndividualsUploadDialog.js index 2afa50c..35e0ed2 100644 --- a/src/components/dialogs/IndividualsUploadDialog.js +++ b/src/components/dialogs/IndividualsUploadDialog.js @@ -22,7 +22,7 @@ import { bindActionCreators } from 'redux'; import WorkflowsPicker from '../../pickers/WorkflowsPicker'; import { fetchWorkflows } from '../../actions'; import IndividualsHistoryUploadDialog from './IndividualsHistoryUploadDialog'; -import {EMPTY_STRING, INDIVIDUAL_MODULE_NAME, PYTHON_DEFAULT_IMPORT_WORKFLOW} from '../../constants'; +import { EMPTY_STRING, INDIVIDUAL_MODULE_NAME, PYTHON_DEFAULT_IMPORT_WORKFLOW } from '../../constants'; const styles = (theme) => ({ item: theme.paper.item, @@ -64,7 +64,8 @@ function IndividualsUploadDialog({ if (selectedFile) { try { const fileHeaders = await getHeadersFromCSV(selectedFile); - setHeaders(fileHeaders); + const filteredHeaders = fileHeaders.filter((header) => header !== 'recipient_info'); + setHeaders(filteredHeaders); } catch (error) { setHeaders([]); } @@ -86,7 +87,7 @@ function IndividualsUploadDialog({ }, []); const handleFieldChange = async (formName, fieldName, value) => { - await handleFileInputChange(value); + if (fieldName === 'file') await handleFileInputChange(value); setForms({ ...forms, [formName]: { From 521fbc5d6d0ae24317e403c1ce27e5df539bb18c Mon Sep 17 00:00:00 2001 From: Jan Date: Wed, 15 May 2024 23:42:28 +0200 Subject: [PATCH 3/3] CM-808: aggregation column adjustments --- src/components/dialogs/IndividualsUploadDialog.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/components/dialogs/IndividualsUploadDialog.js b/src/components/dialogs/IndividualsUploadDialog.js index 35e0ed2..bc2ed46 100644 --- a/src/components/dialogs/IndividualsUploadDialog.js +++ b/src/components/dialogs/IndividualsUploadDialog.js @@ -64,7 +64,9 @@ function IndividualsUploadDialog({ if (selectedFile) { try { const fileHeaders = await getHeadersFromCSV(selectedFile); - const filteredHeaders = fileHeaders.filter((header) => header !== 'recipient_info'); + const filteredHeaders = fileHeaders.filter( + (header) => header !== 'recipient_info' && header !== 'group_id', + ); setHeaders(filteredHeaders); } catch (error) { setHeaders([]);