From 648a88d692a2c4e3d1d474599ad8445fec25b2a9 Mon Sep 17 00:00:00 2001 From: Ana Garcia Date: Thu, 27 Jun 2024 14:13:33 +0200 Subject: [PATCH 01/10] Fix styles and allow required and title in FormSection --- .../components/form-section/FormSection.tsx | 29 ++++++++++++++----- .../layout/side-bar/SideBarContent.tsx | 9 +++--- 2 files changed, 26 insertions(+), 12 deletions(-) diff --git a/src/webapp/components/form-section/FormSection.tsx b/src/webapp/components/form-section/FormSection.tsx index 2d2178f6..836a6086 100644 --- a/src/webapp/components/form-section/FormSection.tsx +++ b/src/webapp/components/form-section/FormSection.tsx @@ -6,7 +6,8 @@ import { Separator } from "../separator/Separator"; import { IconButton } from "../icon-button/IconButton"; type FormSectionProps = { - title: string; + title?: string; + required?: boolean; children: React.ReactNode; hasSeparator?: boolean; onClickInfo?: () => void; @@ -14,15 +15,28 @@ type FormSectionProps = { }; export const FormSection: React.FC = React.memo( - ({ title, hasSeparator = false, children, onClickInfo, direction = "row" }) => { + ({ + title, + hasSeparator = false, + children, + onClickInfo, + direction = "row", + required = false, + }) => { return ( {hasSeparator && } - - {title} - {onClickInfo && } onClick={onClickInfo} />} - + {title && ( + + + {title} + + {onClickInfo && ( + } onClick={onClickInfo} /> + )} + + )} {children} @@ -58,7 +72,8 @@ const RequiredText = styled.span` font-size: 0.875rem; font-weight: 700; white-space: nowrap; - &::after { + + &.required::after { content: "*"; color: ${props => props.theme.palette.common.red}; margin-inline-start: 4px; diff --git a/src/webapp/components/layout/side-bar/SideBarContent.tsx b/src/webapp/components/layout/side-bar/SideBarContent.tsx index 39f22d7f..21372b87 100644 --- a/src/webapp/components/layout/side-bar/SideBarContent.tsx +++ b/src/webapp/components/layout/side-bar/SideBarContent.tsx @@ -50,7 +50,7 @@ export const SideBarContent: React.FC = React.memo( }, [history]); return ( - + {hideOptions ? null : children ? ( children ) : showCreateEvent ? ( @@ -78,19 +78,18 @@ const StyledText = styled(ListItemText)<{ selected?: boolean }>` color: ${props => props.theme.palette.sidebar.text}; font-weight: ${props => (props.selected ? 700 : 400)}; font-size: 0.875rem; + padding-inline-start: 8px; } `; -const SideBarContainer = styled.div` +const SideBarContainer = styled.div<{ hideOptions?: boolean }>` display: flex; max-width: 245px; + width: ${props => (props.hideOptions ? "338px" : "initial")}; background-color: ${props => props.theme.palette.sidebar.background}; .MuiList-root { padding-block: 50px; } - .MuiListItem-root { - margin-inline: 8px; - } .MuiButtonBase-root { padding-inline: 24px; padding-block: 4px; From 79e447460032eb1d0d25c96c6b42fb2214c4f520 Mon Sep 17 00:00:00 2001 From: Ana Garcia Date: Thu, 27 Jun 2024 14:51:16 +0200 Subject: [PATCH 02/10] Add required and bold text in labels of fields --- src/webapp/components/date-picker/DatePicker.tsx | 16 ++++++++++++++-- src/webapp/components/input-field/InputField.tsx | 14 ++++++++++++-- .../multiple-selector/MultipleSelector.tsx | 16 ++++++++++++++-- src/webapp/components/selector/Selector.tsx | 16 ++++++++++++++-- src/webapp/components/text-area/TextArea.tsx | 16 ++++++++++++++-- 5 files changed, 68 insertions(+), 10 deletions(-) diff --git a/src/webapp/components/date-picker/DatePicker.tsx b/src/webapp/components/date-picker/DatePicker.tsx index c46191bf..5715a856 100644 --- a/src/webapp/components/date-picker/DatePicker.tsx +++ b/src/webapp/components/date-picker/DatePicker.tsx @@ -15,6 +15,7 @@ type DatePickerProps = { errorText?: string; disabled?: boolean; error?: boolean; + required?: boolean; }; export const DatePicker: React.FC = React.memo( @@ -27,10 +28,15 @@ export const DatePicker: React.FC = React.memo( helperText = "", errorText = "", error = false, + required = false, }) => { return ( - {label && } + {label && ( + + )} props.theme.palette.text.primary}; margin-block-end: 8px; + + &.required::after { + content: "*"; + color: ${props => props.theme.palette.common.red}; + margin-inline-start: 4px; + } `; const StyledDatePicker = styled(DatePickerMUI)<{ error?: boolean; disabled?: boolean }>` diff --git a/src/webapp/components/input-field/InputField.tsx b/src/webapp/components/input-field/InputField.tsx index 87f333ca..c53ac20c 100644 --- a/src/webapp/components/input-field/InputField.tsx +++ b/src/webapp/components/input-field/InputField.tsx @@ -28,7 +28,11 @@ export const InputField: React.FC = React.memo( }) => { return ( - {label && } + {label && ( + + )} props.theme.palette.text.primary}; margin-block-end: 8px; + + &.required::after { + content: "*"; + color: ${props => props.theme.palette.common.red}; + margin-inline-start: 4px; + } `; const StyledTextField = styled(TextField)<{ error?: boolean }>` diff --git a/src/webapp/components/multiple-selector/MultipleSelector.tsx b/src/webapp/components/multiple-selector/MultipleSelector.tsx index 38d06a4d..d5c3940c 100644 --- a/src/webapp/components/multiple-selector/MultipleSelector.tsx +++ b/src/webapp/components/multiple-selector/MultipleSelector.tsx @@ -20,6 +20,7 @@ type MultipleSelectorProps = { helperText?: string; errorText?: string; error?: boolean; + required?: boolean; }; export const MultipleSelector: React.FC = React.memo( @@ -34,6 +35,7 @@ export const MultipleSelector: React.FC = React.memo( helperText = "", errorText = "", error = false, + required = false, }) => { const getLabelFromValue = useCallback( (value: MultipleSelectorOption["value"]) => { @@ -68,7 +70,11 @@ export const MultipleSelector: React.FC = React.memo( return ( - {label && } + {label && ( + + )} props.theme.palette.text.primary}; margin-block-end: 8px; + + &.required::after { + content: "*"; + color: ${props => props.theme.palette.common.red}; + margin-inline-start: 4px; + } `; const StyledFormHelperText = styled(FormHelperText)<{ error?: boolean }>` diff --git a/src/webapp/components/selector/Selector.tsx b/src/webapp/components/selector/Selector.tsx index fde41143..98c0ad41 100644 --- a/src/webapp/components/selector/Selector.tsx +++ b/src/webapp/components/selector/Selector.tsx @@ -20,6 +20,7 @@ type SelectorProps = { helperText?: string; errorText?: string; error?: boolean; + required?: boolean; }; export const Selector: React.FC = React.memo( @@ -34,6 +35,7 @@ export const Selector: React.FC = React.memo( helperText = "", errorText = "", error = false, + required = false, }) => { const getLabelFromValue = useCallback( (value: SelectorOption["value"]) => { @@ -57,7 +59,11 @@ export const Selector: React.FC = React.memo( return ( - {label && } + {label && ( + + )} props.theme.palette.text.primary}; margin-block-end: 8px; + + &.required::after { + content: "*"; + color: ${props => props.theme.palette.common.red}; + margin-inline-start: 4px; + } `; const StyledFormHelperText = styled(FormHelperText)<{ error?: boolean }>` diff --git a/src/webapp/components/text-area/TextArea.tsx b/src/webapp/components/text-area/TextArea.tsx index ae779da6..8e6342c0 100644 --- a/src/webapp/components/text-area/TextArea.tsx +++ b/src/webapp/components/text-area/TextArea.tsx @@ -11,6 +11,7 @@ type TextAreaProps = { helperText?: string; errorText?: string; error?: boolean; + required?: boolean; }; export const TextArea: React.FC = React.memo( @@ -23,6 +24,7 @@ export const TextArea: React.FC = React.memo( helperText = "", errorText = "", error = false, + required = false, }) => { const handleChange = useCallback( (event: React.ChangeEvent) => { @@ -33,7 +35,11 @@ export const TextArea: React.FC = React.memo( return ( - {label && } + {label && ( + + )} props.theme.palette.text.primary}; margin-block-end: 8px; + + &.required::after { + content: "*"; + color: ${props => props.theme.palette.common.red}; + margin-inline-start: 4px; + } `; const StyledTextareaAutosize = styled(TextareaAutosize)<{ From ada9868daab3a684f656297eb75cc0cc69a39b98 Mon Sep 17 00:00:00 2001 From: Ana Garcia Date: Thu, 27 Jun 2024 14:52:33 +0200 Subject: [PATCH 03/10] Update translations --- i18n/en.pot | 10 ++-------- i18n/es.po | 8 +------- 2 files changed, 3 insertions(+), 15 deletions(-) diff --git a/i18n/en.pot b/i18n/en.pot index 171de7da..674d6b9d 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: 2024-06-26T13:33:38.517Z\n" -"PO-Revision-Date: 2024-06-26T13:33:38.517Z\n" +"POT-Creation-Date: 2024-06-27T12:51:45.020Z\n" +"PO-Revision-Date: 2024-06-27T12:51:45.020Z\n" msgid "Add new option" msgstr "" @@ -41,12 +41,6 @@ msgstr "" msgid "Cholera in NW Province, June 2023" msgstr "" -msgid "Event Name" -msgstr "" - -msgid "Hazard Type" -msgstr "" - msgid "Incident Action Plan" msgstr "" diff --git a/i18n/es.po b/i18n/es.po index 3c53cb62..797aabe5 100644 --- a/i18n/es.po +++ b/i18n/es.po @@ -1,7 +1,7 @@ msgid "" msgstr "" "Project-Id-Version: i18next-conv\n" -"POT-Creation-Date: 2024-06-26T13:33:38.517Z\n" +"POT-Creation-Date: 2024-06-27T12:51:45.020Z\n" "PO-Revision-Date: 2018-10-25T09:02:35.143Z\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" @@ -41,12 +41,6 @@ msgstr "" msgid "Cholera in NW Province, June 2023" msgstr "" -msgid "Event Name" -msgstr "" - -msgid "Hazard Type" -msgstr "" - msgid "Incident Action Plan" msgstr "" From 23b8c7cd57e993e4c3713c34cbf4dd9f99decd18 Mon Sep 17 00:00:00 2001 From: Ana Garcia Date: Fri, 28 Jun 2024 09:38:03 +0200 Subject: [PATCH 04/10] Move similar field component to same folder and extract repeated code in selector --- .../MultipleSelector.tsx | 30 ++++++------------- src/webapp/components/selector/Selector.tsx | 19 +++--------- .../selector/utils/selectorHelper.ts | 12 ++++++++ .../{text-area => text-input}/TextArea.tsx | 2 +- .../TextInput.tsx} | 6 ++-- src/webapp/components/utils/selectorHelper.ts | 0 6 files changed, 29 insertions(+), 40 deletions(-) rename src/webapp/components/{multiple-selector => selector}/MultipleSelector.tsx (85%) create mode 100644 src/webapp/components/selector/utils/selectorHelper.ts rename src/webapp/components/{text-area => text-input}/TextArea.tsx (99%) rename src/webapp/components/{input-field/InputField.tsx => text-input/TextInput.tsx} (94%) create mode 100644 src/webapp/components/utils/selectorHelper.ts diff --git a/src/webapp/components/multiple-selector/MultipleSelector.tsx b/src/webapp/components/selector/MultipleSelector.tsx similarity index 85% rename from src/webapp/components/multiple-selector/MultipleSelector.tsx rename to src/webapp/components/selector/MultipleSelector.tsx index d5c3940c..95f402a8 100644 --- a/src/webapp/components/multiple-selector/MultipleSelector.tsx +++ b/src/webapp/components/selector/MultipleSelector.tsx @@ -2,18 +2,13 @@ import React, { useCallback } from "react"; import styled from "styled-components"; import { Select, InputLabel, MenuItem, FormHelperText, Chip } from "@material-ui/core"; import { IconChevronDown24, IconCross16 } from "@dhis2/ui"; - -export type MultipleSelectorOption = { - value: T; - label: string; - disabled?: boolean; -}; +import { SelectorOption, getLabelFromValue } from "./utils/selectorHelper"; type MultipleSelectorProps = { id: string; selected: T[]; - onChange: (value: MultipleSelectorOption["value"][]) => void; - options: MultipleSelectorOption[]; + onChange: (value: SelectorOption["value"][]) => void; + options: SelectorOption[]; label?: string; placeholder?: string; disabled?: boolean; @@ -26,7 +21,7 @@ type MultipleSelectorProps = { export const MultipleSelector: React.FC = React.memo( ({ id, - label = "", + label, placeholder = "", selected, onChange, @@ -37,13 +32,6 @@ export const MultipleSelector: React.FC = React.memo( error = false, required = false, }) => { - const getLabelFromValue = useCallback( - (value: MultipleSelectorOption["value"]) => { - return options.find(option => option.value === value)?.label || ""; - }, - [options] - ); - const handleChange = useCallback( ( event: React.ChangeEvent<{ @@ -51,7 +39,7 @@ export const MultipleSelector: React.FC = React.memo( }>, _child: React.ReactNode ) => { - const value = event.target.value as MultipleSelectorOption["value"][]; + const value = event.target.value as SelectorOption["value"][]; onChange(value); }, [onChange] @@ -60,7 +48,7 @@ export const MultipleSelector: React.FC = React.memo( const handleDelete = useCallback( ( event: React.MouseEvent, - value: MultipleSelectorOption["value"] + value: SelectorOption["value"] ) => { event.stopPropagation(); onChange(selected?.filter(selection => selection !== value)); @@ -85,12 +73,12 @@ export const MultipleSelector: React.FC = React.memo( IconComponent={IconChevronDown24} error={error} renderValue={(selected: unknown) => - (selected as MultipleSelectorOption["value"][])?.length ? ( + (selected as SelectorOption["value"][])?.length ? (
- {(selected as MultipleSelectorOption["value"][]).map(value => ( + {(selected as SelectorOption["value"][]).map(value => ( } onDelete={event => handleDelete(event, value)} onMouseDown={event => handleDelete(event, value)} diff --git a/src/webapp/components/selector/Selector.tsx b/src/webapp/components/selector/Selector.tsx index 98c0ad41..e7a88c8d 100644 --- a/src/webapp/components/selector/Selector.tsx +++ b/src/webapp/components/selector/Selector.tsx @@ -2,12 +2,7 @@ import React, { useCallback } from "react"; import styled from "styled-components"; import { Select, InputLabel, MenuItem, FormHelperText } from "@material-ui/core"; import { IconChevronDown24 } from "@dhis2/ui"; - -export type SelectorOption = { - value: T; - label: string; - disabled?: boolean; -}; +import { SelectorOption, getLabelFromValue } from "./utils/selectorHelper"; type SelectorProps = { id: string; @@ -26,7 +21,7 @@ type SelectorProps = { export const Selector: React.FC = React.memo( ({ id, - label = "", + label, placeholder = "", selected, onChange, @@ -37,13 +32,6 @@ export const Selector: React.FC = React.memo( error = false, required = false, }) => { - const getLabelFromValue = useCallback( - (value: SelectorOption["value"]) => { - return options.find(option => option.value === value)?.label || ""; - }, - [options] - ); - const handleChange = useCallback( ( event: React.ChangeEvent<{ @@ -74,7 +62,8 @@ export const Selector: React.FC = React.memo( IconComponent={IconChevronDown24} error={error} renderValue={(selected: unknown) => - getLabelFromValue(selected as SelectorOption["value"]) || placeholder + getLabelFromValue(selected as SelectorOption["value"], options) || + placeholder } displayEmpty > diff --git a/src/webapp/components/selector/utils/selectorHelper.ts b/src/webapp/components/selector/utils/selectorHelper.ts new file mode 100644 index 00000000..7b23414f --- /dev/null +++ b/src/webapp/components/selector/utils/selectorHelper.ts @@ -0,0 +1,12 @@ +export type SelectorOption = { + value: T; + label: string; + disabled?: boolean; +}; + +export function getLabelFromValue( + value: SelectorOption["value"], + options: SelectorOption[] +) { + return options.find(option => option.value === value)?.label; +} diff --git a/src/webapp/components/text-area/TextArea.tsx b/src/webapp/components/text-input/TextArea.tsx similarity index 99% rename from src/webapp/components/text-area/TextArea.tsx rename to src/webapp/components/text-input/TextArea.tsx index 8e6342c0..d6f3302b 100644 --- a/src/webapp/components/text-area/TextArea.tsx +++ b/src/webapp/components/text-input/TextArea.tsx @@ -17,7 +17,7 @@ type TextAreaProps = { export const TextArea: React.FC = React.memo( ({ id, - label = "", + label, value, onChange, disabled = false, diff --git a/src/webapp/components/input-field/InputField.tsx b/src/webapp/components/text-input/TextInput.tsx similarity index 94% rename from src/webapp/components/input-field/InputField.tsx rename to src/webapp/components/text-input/TextInput.tsx index c53ac20c..367244bf 100644 --- a/src/webapp/components/input-field/InputField.tsx +++ b/src/webapp/components/text-input/TextInput.tsx @@ -2,7 +2,7 @@ import React from "react"; import { TextField, InputLabel } from "@material-ui/core"; import styled from "styled-components"; -type InputFieldProps = { +type TextInputProps = { id: string; label?: string; value: string; @@ -14,10 +14,10 @@ type InputFieldProps = { error?: boolean; }; -export const InputField: React.FC = React.memo( +export const TextInput: React.FC = React.memo( ({ id, - label = "", + label, value, onChange, helperText = "", diff --git a/src/webapp/components/utils/selectorHelper.ts b/src/webapp/components/utils/selectorHelper.ts new file mode 100644 index 00000000..e69de29b From bb23eef59b0ee4afe21e92ad85ccbff59119a88b Mon Sep 17 00:00:00 2001 From: Ana Garcia Date: Fri, 28 Jun 2024 09:39:02 +0200 Subject: [PATCH 05/10] Delete default value string in components in label and id --- src/webapp/components/add-new-option/AddNewOption.tsx | 2 +- src/webapp/components/date-picker/DatePicker.tsx | 4 ++-- src/webapp/components/not-applicable-checkbox/NACheckbox.tsx | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/webapp/components/add-new-option/AddNewOption.tsx b/src/webapp/components/add-new-option/AddNewOption.tsx index 26adbd2a..16186c5d 100644 --- a/src/webapp/components/add-new-option/AddNewOption.tsx +++ b/src/webapp/components/add-new-option/AddNewOption.tsx @@ -11,7 +11,7 @@ type AddNewOptionProps = { }; export const AddNewOption: React.FC = React.memo( - ({ id, label = "", onAddNewOption }) => { + ({ id, label, onAddNewOption }) => { return ( diff --git a/src/webapp/components/date-picker/DatePicker.tsx b/src/webapp/components/date-picker/DatePicker.tsx index 5715a856..7942ab72 100644 --- a/src/webapp/components/date-picker/DatePicker.tsx +++ b/src/webapp/components/date-picker/DatePicker.tsx @@ -20,8 +20,8 @@ type DatePickerProps = { export const DatePicker: React.FC = React.memo( ({ - id = "", - label = "", + id, + label, value, onChange, disabled = false, diff --git a/src/webapp/components/not-applicable-checkbox/NACheckbox.tsx b/src/webapp/components/not-applicable-checkbox/NACheckbox.tsx index e0026b50..8670fb7f 100644 --- a/src/webapp/components/not-applicable-checkbox/NACheckbox.tsx +++ b/src/webapp/components/not-applicable-checkbox/NACheckbox.tsx @@ -17,7 +17,7 @@ type NACheckboxProps = { export const NACheckbox: React.FC = React.memo( ({ id, - label = "", + label, checked, onChange, helperText = "", From efc8d44c5dba12a61655cf33ccf9d795b93b9bc5 Mon Sep 17 00:00:00 2001 From: Ana Garcia Date: Fri, 28 Jun 2024 09:40:46 +0200 Subject: [PATCH 06/10] Merge forms in one page for create and another for edit and change paths in Router --- .../{form-page => form}/FormPage.tsx | 6 ++-- .../{form-section => form}/FormSection.tsx | 15 ++++++---- .../layout/side-bar/SideBarContent.tsx | 2 +- src/webapp/pages/Router.tsx | 28 ++++++++----------- .../pages/assign-role/AssignRolePage.tsx | 16 ----------- .../pages/create-event/CreateEventPage.tsx | 8 ------ .../pages/create-form/CreateFormPage.tsx | 14 ++++++++++ .../CreateIncidentActionPlanPage.tsx | 16 ----------- .../CreateRiskAssessmentPage.tsx | 16 ----------- src/webapp/pages/edit-form/EditFormPage.tsx | 14 ++++++++++ 10 files changed, 54 insertions(+), 81 deletions(-) rename src/webapp/components/{form-page => form}/FormPage.tsx (90%) rename src/webapp/components/{form-section => form}/FormSection.tsx (82%) delete mode 100644 src/webapp/pages/assign-role/AssignRolePage.tsx delete mode 100644 src/webapp/pages/create-event/CreateEventPage.tsx create mode 100644 src/webapp/pages/create-form/CreateFormPage.tsx delete mode 100644 src/webapp/pages/create-incident-action-plan/CreateIncidentActionPlanPage.tsx delete mode 100644 src/webapp/pages/create-risk-assessment/CreateRiskAssessmentPage.tsx create mode 100644 src/webapp/pages/edit-form/EditFormPage.tsx diff --git a/src/webapp/components/form-page/FormPage.tsx b/src/webapp/components/form/FormPage.tsx similarity index 90% rename from src/webapp/components/form-page/FormPage.tsx rename to src/webapp/components/form/FormPage.tsx index 6fa37af9..e6a3f961 100644 --- a/src/webapp/components/form-page/FormPage.tsx +++ b/src/webapp/components/form/FormPage.tsx @@ -16,13 +16,13 @@ type FormPageProps = { }; export const FormPage: React.FC = React.memo( - ({ title, subtitle = "", saveLabel = "", cancelLabel = "", children, onSave, onCancel }) => { + ({ title, subtitle, saveLabel, cancelLabel, children, onSave, onCancel }) => { return (
- {title ? {title} : null} - {subtitle ? {subtitle} : null} + {title && {title}} + {subtitle && {subtitle}} {i18n.t("Indicates required")}
diff --git a/src/webapp/components/form-section/FormSection.tsx b/src/webapp/components/form/FormSection.tsx similarity index 82% rename from src/webapp/components/form-section/FormSection.tsx rename to src/webapp/components/form/FormSection.tsx index 836a6086..cc28e8a0 100644 --- a/src/webapp/components/form-section/FormSection.tsx +++ b/src/webapp/components/form/FormSection.tsx @@ -28,7 +28,7 @@ export const FormSection: React.FC = React.memo( {hasSeparator && } {title && ( - + {title} @@ -37,7 +37,7 @@ export const FormSection: React.FC = React.memo( )} )} - {children} + {children} ); @@ -55,16 +55,21 @@ const Container = styled.div<{ direction: string }>` width: 100%; gap: ${props => (props.direction === "row" ? "48px" : "24px")}; align-items: ${props => (props.direction === "row" ? "center" : "flex-start")}; + @media (max-width: 600px) { + flex-direction: column; + align-items: flex-start; + } `; -const TitleContainer = styled.div` +const TitleContainer = styled.div<{ direction: string }>` display: flex; align-items: center; gap: 4px; + width: 30%; `; -const FormContainer = styled.div` - width: 100%; +const FormContainer = styled.div<{ fulWidth: boolean }>` + width: ${props => (props.fulWidth ? "100%" : "70%")}; `; const RequiredText = styled.span` diff --git a/src/webapp/components/layout/side-bar/SideBarContent.tsx b/src/webapp/components/layout/side-bar/SideBarContent.tsx index 21372b87..9444d017 100644 --- a/src/webapp/components/layout/side-bar/SideBarContent.tsx +++ b/src/webapp/components/layout/side-bar/SideBarContent.tsx @@ -46,7 +46,7 @@ export const SideBarContent: React.FC = React.memo( const history = useHistory(); const goToCreateEvent = useCallback(() => { - history.push(`/create-event`); + history.push(`/create/diseaseOutbreakEvent`); }, [history]); return ( diff --git a/src/webapp/pages/Router.tsx b/src/webapp/pages/Router.tsx index 8665b9db..cf3aa77e 100644 --- a/src/webapp/pages/Router.tsx +++ b/src/webapp/pages/Router.tsx @@ -6,35 +6,31 @@ import { EventTrackerPage } from "./event-tracker/EventTrackerPage"; import { IncidentActionPlanPage } from "./incident-action-plan/IncidentActionPlanPage"; import { ResourcesPage } from "./resources/ResourcesPage"; import { IMTeamBuilderPage } from "./incident-management-team-builder/IMTeamBuilderPage"; -import { CreateEventPage } from "./create-event/CreateEventPage"; -import { CreateRiskAssessmentPage } from "./create-risk-assessment/CreateRiskAssessmentPage"; -import { CreateIncidentActionPlanPage } from "./create-incident-action-plan/CreateIncidentActionPlanPage"; -import { AssignRolePage } from "./assign-role/AssignRolePage"; +import { EditFormPage } from "./edit-form/EditFormPage"; +import { CreateFormPage } from "./create-form/CreateFormPage"; export function Router() { return ( - } /> - } /> + } /> } + path="/edit/:formType/:diseaseOutbreakEventId/:id?" + render={() => } /> } + path="/event-tracker/:diseaseOutbreakEvent" + render={() => } /> - } /> } + path="/incident-management-team-builder/:diseaseOutbreakEvent" + render={() => } /> } + path="/:diseaseOutbreakEvent/incident-action-plan/:incidentActionPlan" + render={() => } /> - } /> + } /> {/* Default route */} } /> diff --git a/src/webapp/pages/assign-role/AssignRolePage.tsx b/src/webapp/pages/assign-role/AssignRolePage.tsx deleted file mode 100644 index 0d36ad1d..00000000 --- a/src/webapp/pages/assign-role/AssignRolePage.tsx +++ /dev/null @@ -1,16 +0,0 @@ -import React from "react"; - -import { Layout } from "../../components/layout/Layout"; -import i18n from "../../../utils/i18n"; - -export const AssignRolePage: React.FC = React.memo(() => { - return ( - - AssignRolePage - - ); -}); diff --git a/src/webapp/pages/create-event/CreateEventPage.tsx b/src/webapp/pages/create-event/CreateEventPage.tsx deleted file mode 100644 index fb08a60f..00000000 --- a/src/webapp/pages/create-event/CreateEventPage.tsx +++ /dev/null @@ -1,8 +0,0 @@ -import React from "react"; - -import { Layout } from "../../components/layout/Layout"; -import i18n from "../../../utils/i18n"; - -export const CreateEventPage: React.FC = React.memo(() => { - return ; -}); diff --git a/src/webapp/pages/create-form/CreateFormPage.tsx b/src/webapp/pages/create-form/CreateFormPage.tsx new file mode 100644 index 00000000..af749d80 --- /dev/null +++ b/src/webapp/pages/create-form/CreateFormPage.tsx @@ -0,0 +1,14 @@ +import React from "react"; + +import { Layout } from "../../components/layout/Layout"; +import { FormPage } from "../../components/form/FormPage"; + +export const CreateFormPage: React.FC = React.memo(() => { + return ( + + {}}> +
CreateFormPage
+
+
+ ); +}); diff --git a/src/webapp/pages/create-incident-action-plan/CreateIncidentActionPlanPage.tsx b/src/webapp/pages/create-incident-action-plan/CreateIncidentActionPlanPage.tsx deleted file mode 100644 index 12a9b0be..00000000 --- a/src/webapp/pages/create-incident-action-plan/CreateIncidentActionPlanPage.tsx +++ /dev/null @@ -1,16 +0,0 @@ -import React from "react"; - -import { Layout } from "../../components/layout/Layout"; -import i18n from "../../../utils/i18n"; - -export const CreateIncidentActionPlanPage: React.FC = React.memo(() => { - return ( - - CreateIncidentActionPlanPage - - ); -}); diff --git a/src/webapp/pages/create-risk-assessment/CreateRiskAssessmentPage.tsx b/src/webapp/pages/create-risk-assessment/CreateRiskAssessmentPage.tsx deleted file mode 100644 index c4dcbdc3..00000000 --- a/src/webapp/pages/create-risk-assessment/CreateRiskAssessmentPage.tsx +++ /dev/null @@ -1,16 +0,0 @@ -import React from "react"; - -import { Layout } from "../../components/layout/Layout"; -import i18n from "../../../utils/i18n"; - -export const CreateRiskAssessmentPage: React.FC = React.memo(() => { - return ( - - CreateRiskAssessmentPage - - ); -}); diff --git a/src/webapp/pages/edit-form/EditFormPage.tsx b/src/webapp/pages/edit-form/EditFormPage.tsx new file mode 100644 index 00000000..f1f57979 --- /dev/null +++ b/src/webapp/pages/edit-form/EditFormPage.tsx @@ -0,0 +1,14 @@ +import React from "react"; + +import { Layout } from "../../components/layout/Layout"; +import { FormPage } from "../../components/form/FormPage"; + +export const EditFormPage: React.FC = React.memo(() => { + return ( + + {}}> +
EditFormPage
+
+
+ ); +}); From 2106be7a53c82bab888f91ac82882940b7862fe0 Mon Sep 17 00:00:00 2001 From: Ana Garcia Date: Fri, 28 Jun 2024 09:42:08 +0200 Subject: [PATCH 07/10] Update tranlations --- i18n/en.pot | 28 ++++++++++++++-------------- i18n/es.po | 26 +++++++++++++------------- 2 files changed, 27 insertions(+), 27 deletions(-) diff --git a/i18n/en.pot b/i18n/en.pot index 674d6b9d..18dced0b 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: 2024-06-27T12:51:45.020Z\n" -"PO-Revision-Date: 2024-06-27T12:51:45.020Z\n" +"POT-Creation-Date: 2024-06-28T07:41:17.026Z\n" +"PO-Revision-Date: 2024-06-28T07:41:17.026Z\n" msgid "Add new option" msgstr "" @@ -35,18 +35,6 @@ msgstr "" msgid "Last updated: " msgstr "" -msgid "Incident Management Team Builder" -msgstr "" - -msgid "Cholera in NW Province, June 2023" -msgstr "" - -msgid "Incident Action Plan" -msgstr "" - -msgid "Create Risk Assessment" -msgstr "" - msgid "Dashboard" msgstr "" @@ -77,12 +65,21 @@ msgstr "" msgid "Risk Assessment" msgstr "" +msgid "Create Risk Assessment" +msgstr "" + msgid "Risk assessment incomplete" msgstr "" msgid "Risks associated with this event have not yet been assessed." msgstr "" +msgid "Incident Action Plan" +msgstr "" + +msgid "Cholera in NW Province, June 2023" +msgstr "" + msgid "Response actions" msgstr "" @@ -101,5 +98,8 @@ msgstr "" msgid "Edit Team" msgstr "" +msgid "Incident Management Team Builder" +msgstr "" + msgid "Resources" msgstr "" diff --git a/i18n/es.po b/i18n/es.po index 797aabe5..502b3435 100644 --- a/i18n/es.po +++ b/i18n/es.po @@ -1,7 +1,7 @@ msgid "" msgstr "" "Project-Id-Version: i18next-conv\n" -"POT-Creation-Date: 2024-06-27T12:51:45.020Z\n" +"POT-Creation-Date: 2024-06-28T07:41:17.026Z\n" "PO-Revision-Date: 2018-10-25T09:02:35.143Z\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" @@ -35,18 +35,6 @@ msgstr "" msgid "Last updated: " msgstr "" -msgid "Incident Management Team Builder" -msgstr "" - -msgid "Cholera in NW Province, June 2023" -msgstr "" - -msgid "Incident Action Plan" -msgstr "" - -msgid "Create Risk Assessment" -msgstr "" - msgid "Dashboard" msgstr "" @@ -77,12 +65,21 @@ msgstr "" msgid "Risk Assessment" msgstr "" +msgid "Create Risk Assessment" +msgstr "" + msgid "Risk assessment incomplete" msgstr "" msgid "Risks associated with this event have not yet been assessed." msgstr "" +msgid "Incident Action Plan" +msgstr "" + +msgid "Cholera in NW Province, June 2023" +msgstr "" + msgid "Response actions" msgstr "" @@ -101,6 +98,9 @@ msgstr "" msgid "Edit Team" msgstr "" +msgid "Incident Management Team Builder" +msgstr "" + msgid "Resources" msgstr "" From 7f8ddf3954486e47a6d9955a619117d99aa809f5 Mon Sep 17 00:00:00 2001 From: Ana Garcia Date: Fri, 28 Jun 2024 09:53:58 +0200 Subject: [PATCH 08/10] Delete lodash library and add a TODO in SearcInput to add debounce function to Collection --- package.json | 2 -- src/webapp/components/search-input/SearchInput.tsx | 9 ++++----- yarn.lock | 5 ----- 3 files changed, 4 insertions(+), 12 deletions(-) diff --git a/package.json b/package.json index 258b6c67..a649d7aa 100644 --- a/package.json +++ b/package.json @@ -30,7 +30,6 @@ "d2": "31.10.2", "d2-manifest": "1.0.0", "font-awesome": "4.7.0", - "lodash": "^4.17.21", "purify-ts": "1.2.0", "purify-ts-extra-codec": "0.6.0", "react": "^18.2.0", @@ -50,7 +49,6 @@ "@testing-library/react": "^14.0.0", "@types/classnames": "2.3.1", "@types/isomorphic-fetch": "^0.0.36", - "@types/lodash": "^4.17.5", "@types/material-ui": "^0.21.12", "@types/node": "18", "@types/node-localstorage": "^1.3.0", diff --git a/src/webapp/components/search-input/SearchInput.tsx b/src/webapp/components/search-input/SearchInput.tsx index 3e0bac51..1e45691e 100644 --- a/src/webapp/components/search-input/SearchInput.tsx +++ b/src/webapp/components/search-input/SearchInput.tsx @@ -2,7 +2,6 @@ import React, { useCallback, useEffect, useState } from "react"; import { TextField } from "@material-ui/core"; import { IconSearch24 } from "@dhis2/ui"; import styled from "styled-components"; -import _ from "lodash"; import i18n from "../../../utils/i18n"; @@ -19,14 +18,14 @@ export const SearchInput: React.FC = React.memo( useEffect(() => updateStateValue(value), [value]); - // eslint-disable-next-line react-hooks/exhaustive-deps + // TODO: needs debounce function from Collection const onChangeDebounced = useCallback( - _.debounce((value: string) => { + (value: string) => { if (onChange) { onChange(value); } - }, 400), - [] + }, + [onChange] ); const handleChange = useCallback( diff --git a/yarn.lock b/yarn.lock index 2710f263..61d79c4a 100644 --- a/yarn.lock +++ b/yarn.lock @@ -4283,11 +4283,6 @@ resolved "https://registry.yarnpkg.com/@types/json5/-/json5-0.0.29.tgz#ee28707ae94e11d2b827bcbe5270bcea7f3e71ee" integrity sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ== -"@types/lodash@^4.17.5": - version "4.17.5" - resolved "https://registry.yarnpkg.com/@types/lodash/-/lodash-4.17.5.tgz#e6c29b58e66995d57cd170ce3e2a61926d55ee04" - integrity sha512-MBIOHVZqVqgfro1euRDWX7OO0fBVUUMrN6Pwm8LQsz8cWhEpihlvR70ENj3f40j58TNxZaWv2ndSkInykNBBJw== - "@types/material-ui@^0.21.12": version "0.21.12" resolved "https://registry.yarnpkg.com/@types/material-ui/-/material-ui-0.21.12.tgz#208e8b7e49a545bb704fa7e865986afde1b33384" From 13af8a5b4ef466d0bc97f10cf8d22d47c6c8b731 Mon Sep 17 00:00:00 2001 From: Ana Garcia Date: Fri, 28 Jun 2024 10:07:38 +0200 Subject: [PATCH 09/10] Use only one component for the forms --- .../form/{FormPage.tsx => FormLayout.tsx} | 10 +++++----- src/webapp/pages/Router.tsx | 7 +++---- src/webapp/pages/create-form/CreateFormPage.tsx | 14 -------------- src/webapp/pages/edit-form/EditFormPage.tsx | 14 -------------- src/webapp/pages/form/FormPage.tsx | 14 ++++++++++++++ 5 files changed, 22 insertions(+), 37 deletions(-) rename src/webapp/components/form/{FormPage.tsx => FormLayout.tsx} (92%) delete mode 100644 src/webapp/pages/create-form/CreateFormPage.tsx delete mode 100644 src/webapp/pages/edit-form/EditFormPage.tsx create mode 100644 src/webapp/pages/form/FormPage.tsx diff --git a/src/webapp/components/form/FormPage.tsx b/src/webapp/components/form/FormLayout.tsx similarity index 92% rename from src/webapp/components/form/FormPage.tsx rename to src/webapp/components/form/FormLayout.tsx index e6a3f961..a01eeba6 100644 --- a/src/webapp/components/form/FormPage.tsx +++ b/src/webapp/components/form/FormLayout.tsx @@ -5,7 +5,7 @@ import i18n from "../../../utils/i18n"; import { Button } from "../button/Button"; import { Separator } from "../separator/Separator"; -type FormPageProps = { +type FormLayoutProps = { title?: string; subtitle?: string; saveLabel?: string; @@ -15,10 +15,10 @@ type FormPageProps = { onCancel?: () => void; }; -export const FormPage: React.FC = React.memo( +export const FormLayout: React.FC = React.memo( ({ title, subtitle, saveLabel, cancelLabel, children, onSave, onCancel }) => { return ( - +
{title && {title}} @@ -38,12 +38,12 @@ export const FormPage: React.FC = React.memo( )} - + ); } ); -const StyledFormPage = styled.div` +const StyledFormLayout = styled.div` width: 100%; `; diff --git a/src/webapp/pages/Router.tsx b/src/webapp/pages/Router.tsx index cf3aa77e..3ee47f08 100644 --- a/src/webapp/pages/Router.tsx +++ b/src/webapp/pages/Router.tsx @@ -6,17 +6,16 @@ import { EventTrackerPage } from "./event-tracker/EventTrackerPage"; import { IncidentActionPlanPage } from "./incident-action-plan/IncidentActionPlanPage"; import { ResourcesPage } from "./resources/ResourcesPage"; import { IMTeamBuilderPage } from "./incident-management-team-builder/IMTeamBuilderPage"; -import { EditFormPage } from "./edit-form/EditFormPage"; -import { CreateFormPage } from "./create-form/CreateFormPage"; +import { FormPage } from "./form/FormPage"; export function Router() { return ( - } /> + } /> } + render={() => } /> { - return ( - - {}}> -
CreateFormPage
-
-
- ); -}); diff --git a/src/webapp/pages/edit-form/EditFormPage.tsx b/src/webapp/pages/edit-form/EditFormPage.tsx deleted file mode 100644 index f1f57979..00000000 --- a/src/webapp/pages/edit-form/EditFormPage.tsx +++ /dev/null @@ -1,14 +0,0 @@ -import React from "react"; - -import { Layout } from "../../components/layout/Layout"; -import { FormPage } from "../../components/form/FormPage"; - -export const EditFormPage: React.FC = React.memo(() => { - return ( - - {}}> -
EditFormPage
-
-
- ); -}); diff --git a/src/webapp/pages/form/FormPage.tsx b/src/webapp/pages/form/FormPage.tsx new file mode 100644 index 00000000..5199b37d --- /dev/null +++ b/src/webapp/pages/form/FormPage.tsx @@ -0,0 +1,14 @@ +import React from "react"; + +import { Layout } from "../../components/layout/Layout"; +import { FormLayout } from "../../components/form/FormLayout"; + +export const FormPage: React.FC = React.memo(() => { + return ( + + {}}> +
FormPage
+
+
+ ); +}); From c9e0fb8a80f0e62f9438a23e5d2c14f057984456 Mon Sep 17 00:00:00 2001 From: Ana Garcia Date: Fri, 28 Jun 2024 10:12:01 +0200 Subject: [PATCH 10/10] Remove dark-secondary --- src/webapp/components/button/Button.tsx | 15 ++++----------- 1 file changed, 4 insertions(+), 11 deletions(-) diff --git a/src/webapp/components/button/Button.tsx b/src/webapp/components/button/Button.tsx index 00621876..00894a1d 100644 --- a/src/webapp/components/button/Button.tsx +++ b/src/webapp/components/button/Button.tsx @@ -1,11 +1,10 @@ import React from "react"; import { Button as MUIButton } from "@material-ui/core"; -import styled from "styled-components"; type ButtonProps = { children?: React.ReactNode; variant?: "contained" | "outlined"; - color?: "primary" | "secondary" | "dark-secondary"; + color?: "primary" | "secondary"; disabled?: boolean; startIcon?: React.ReactNode; onClick: () => void; @@ -21,22 +20,16 @@ export const Button: React.FC = React.memo( onClick, }) => { return ( - {children} - + ); } ); - -const StyledButton = styled(MUIButton)<{ $darkBorder: boolean }>` - border-color: ${props => - props.$darkBorder ? props.theme.palette.button.borderDarkSecondary : "initial"}; -`;