From ef3cbea49533be1b498fa1667efc6cb212ed93de Mon Sep 17 00:00:00 2001 From: Eduardo Peredo Rivero Date: Mon, 14 Oct 2024 11:20:10 -0500 Subject: [PATCH] add steps for indicators, share and summary --- .../dataset-wizard/DataSetWizard.tsx | 84 ++++++--- .../dataset-wizard/FilterIndicators.tsx | 163 ++++++++++++++++++ .../dataset-wizard/IndicatorsDataSet.tsx | 158 +++++++++++++++++ .../dataset-wizard/SetupDataSet.tsx | 6 +- .../dataset-wizard/ShareOptionsDataSet.tsx | 40 +++++ .../dataset-wizard/SummaryDataSet.tsx | 37 ++++ src/webapp/pages/app/App.css | 8 + src/webapp/pages/app/themes/dhis2.theme.ts | 2 +- 8 files changed, 474 insertions(+), 24 deletions(-) create mode 100644 src/webapp/components/dataset-wizard/FilterIndicators.tsx create mode 100644 src/webapp/components/dataset-wizard/IndicatorsDataSet.tsx create mode 100644 src/webapp/components/dataset-wizard/ShareOptionsDataSet.tsx create mode 100644 src/webapp/components/dataset-wizard/SummaryDataSet.tsx diff --git a/src/webapp/components/dataset-wizard/DataSetWizard.tsx b/src/webapp/components/dataset-wizard/DataSetWizard.tsx index 1acbb658..e3845c7c 100644 --- a/src/webapp/components/dataset-wizard/DataSetWizard.tsx +++ b/src/webapp/components/dataset-wizard/DataSetWizard.tsx @@ -1,30 +1,74 @@ -import i18n from "$/utils/i18n"; -import { SetupDataSet } from "$/webapp/components/dataset-wizard/SetupDataSet"; import { Wizard, WizardStep } from "@eyeseetea/d2-ui-components"; +import { Grid, Theme, Typography, createStyles } from "@material-ui/core"; +import { makeStyles } from "@material-ui/styles"; import React from "react"; +import i18n from "$/utils/i18n"; +import { IndicatorsDataSet } from "$/webapp/components/dataset-wizard/IndicatorsDataSet"; +import { SetupDataSet } from "$/webapp/components/dataset-wizard/SetupDataSet"; +import { ShareOptionsDataSet } from "$/webapp/components/dataset-wizard/ShareOptionsDataSet"; +import { SummaryDataSet } from "$/webapp/components/dataset-wizard/SummaryDataSet"; + export type DataSetWizardProps = { id?: string }; +const steps = [ + { + component: () => , + label: i18n.t("Setup"), + key: "setup", + }, + { + component: () => , + label: i18n.t("Indicators"), + key: "indicators", + }, + { + component: () => , + label: i18n.t("Share"), + key: "share", + }, + { + component: () => , + label: i18n.t("Summary and Save"), + key: "summary", + }, +]; + +const useStyles = makeStyles((theme: Theme) => + createStyles({ + root: { + paddingBlock: theme.spacing(2), + }, + titleContainer: { + padding: theme.spacing(1), + }, + }) +); + export const DataSetWizard = React.memo((props: DataSetWizardProps) => { + const { id } = props; + const isEditing = Boolean(id); + const actionTitle = isEditing ? i18n.t("Edit") : i18n.t("Create"); + + const classes = useStyles(); + return ( - { - return Promise.resolve([]); - }} - useSnackFeedback - steps={[ - { - component: () => , - label: i18n.t("Setup"), - key: "setup", - }, - { - component: () =>
Step 2: {props.id}
, - label: "Step 2", - key: "step2", - }, - ]} - /> + + + + {i18n.t("{{action}} a new dataSet", { action: actionTitle })} + + + + { + return Promise.resolve([]); + }} + useSnackFeedback + steps={steps} + /> + + ); }); diff --git a/src/webapp/components/dataset-wizard/FilterIndicators.tsx b/src/webapp/components/dataset-wizard/FilterIndicators.tsx new file mode 100644 index 00000000..a3a7b9c9 --- /dev/null +++ b/src/webapp/components/dataset-wizard/FilterIndicators.tsx @@ -0,0 +1,163 @@ +import React from "react"; +import styled from "styled-components"; +import { Chip, Divider, Drawer, Grid, IconButton, Typography } from "@material-ui/core"; + +import FilterListIcon from "@material-ui/icons/FilterList"; +import CloseIcon from "@material-ui/icons/Close"; +import i18n from "$/utils/i18n"; +import { Dropdown } from "@eyeseetea/d2-ui-components"; + +export type FilterType = "scope" | "core" | "outputType"; + +export type FilterIndicatorsProps = { + coreCompetencies: string[]; + coreValue: string; + groups: string[]; + onClose: () => void; + onFilterChange: (scope: string, type: FilterType) => void; + scopes: string[]; + scopeValue: string; + showCloseButton?: boolean; + themes: string[]; + types: string[]; +}; + +export type FilterWrapperProps = { + mode: FilterMode; + children: React.JSX.Element; + showDrawer: boolean; +}; +export type FilterMode = "default" | "drawer"; + +export const FilterWrapper = React.memo((props: FilterWrapperProps) => { + const { children, mode, showDrawer } = props; + const Wrapper = mode === "default" ? Grid : Drawer; + return ( + + {children} + + ); +}); + +export const FilterIndicators = React.memo((props: FilterIndicatorsProps) => { + const { + coreCompetencies, + coreValue, + onClose, + onFilterChange, + scopes, + scopeValue, + showCloseButton, + types, + } = props; + return ( + + + + {i18n.t("Filters")} + {showCloseButton && ( + + + + )} + + + onFilterChange(value, "scope")} + value={scopeValue} + /> + onFilterChange(value, "core")} + value={coreValue} + /> + + onFilterChange(value, "outputType")} + value={"Outputs"} + /> + + + {}} + label={i18n.t("Theme")} + /> + + + {}} + label={i18n.t("Group")} + /> + + + ); +}); + +export type ChipFilterProps = { + items: string[]; + label: string; + onChange: (value: string) => void; + value: string; +}; + +export const ChipFilter = React.memo((props: ChipFilterProps) => { + const { items, label, onChange, value } = props; + return ( + + + {label} + + + {items.map(item => { + return ( + onChange(item)} + /> + ); + })} + + + ); +}); + +const FilterIndicatorContainer = styled.div` + max-width: 350px; + display: flex; + flex-direction: column; + row-gap: 0.5em; +`; + +const HeaderFilterContainer = styled.div` + align-items: center; + display: flex; + gap: 0.5em; + padding-inline: 1em; + + .icon { + margin-left: auto; + } +`; + +const BodyFilterContainer = styled.div` + padding-inline: 1em; +`; + +const ScopeContainer = styled.div` + display: flex; + flex-wrap: wrap; + gap: 0.5em; + padding-block: 1em; +`; diff --git a/src/webapp/components/dataset-wizard/IndicatorsDataSet.tsx b/src/webapp/components/dataset-wizard/IndicatorsDataSet.tsx new file mode 100644 index 00000000..f9825570 --- /dev/null +++ b/src/webapp/components/dataset-wizard/IndicatorsDataSet.tsx @@ -0,0 +1,158 @@ +import React from "react"; +import { Button, Divider, Grid, useMediaQuery } from "@material-ui/core"; +import { ObjectsTable, useObjectsTable } from "@eyeseetea/d2-ui-components"; + +import { DataSet } from "$/domain/entities/DataSet"; +import i18n from "$/utils/i18n"; +import { + FilterIndicators, + FilterType, + FilterWrapper, +} from "$/webapp/components/dataset-wizard/FilterIndicators"; + +export type IndicatorsDataSetProps = { dataSet?: DataSet }; + +export type IndicatorsColumns = { + id: string; + name: string; + theme: string; + group: string; + status: string; + disaggregation: string; +}; + +export const IndicatorsDataSet = React.memo(() => { + const [showFilterModal, setShowFilterModal] = React.useState(false); + const [scope, setScope] = React.useState("Core"); + const [core, setCore] = React.useState("Icla"); + const isLargeDesktop = useMediaQuery("(min-width: 1320px)"); + const tableConfig = useObjectsTable( + React.useMemo(() => { + return { + columns: [ + { + name: "id", + text: i18n.t("Id"), + hidden: true, + }, + { + name: "name", + text: i18n.t("Name"), + }, + { + name: "theme", + text: i18n.t("Theme"), + }, + { + name: "group", + text: i18n.t("Group"), + }, + { + name: "status", + text: i18n.t("Status"), + }, + { + name: "disaggregation", + text: i18n.t("Disaggregation"), + }, + ], + actions: [], + initialSorting: { field: "name", order: "asc" }, + paginationOptions: { pageSizeInitialValue: 50, pageSizeOptions: [50, 100, 200] }, + searchBoxLabel: i18n.t("Search"), + }; + }, []), + React.useCallback(() => { + return Promise.resolve({ + objects: [], + pager: { page: 1, pageCount: 1, total: 1, pageSize: 1 }, + }); + }, []) + ); + + const openFilters = React.useCallback(() => { + setShowFilterModal(true); + }, []); + + const updateFilter = React.useCallback((value: string, filterType: FilterType) => { + if (filterType === "scope") { + setScope(value); + } else if (filterType === "core") { + setCore(value); + } + }, []); + + return ( +
+ + + setShowFilterModal(false)} + /> + + + + + + + + + {!isLargeDesktop && ( + + + + )} + + {i18n.t("Active Filters")}: {scope}, {core} + + + + } /> + + +
+ ); +}); + +export const FilterTable = React.memo(() => { + const [value, setValue] = React.useState(1); + return ( +
+ + +
+ ); +}); diff --git a/src/webapp/components/dataset-wizard/SetupDataSet.tsx b/src/webapp/components/dataset-wizard/SetupDataSet.tsx index 8be33451..5ac572d2 100644 --- a/src/webapp/components/dataset-wizard/SetupDataSet.tsx +++ b/src/webapp/components/dataset-wizard/SetupDataSet.tsx @@ -1,11 +1,11 @@ import React from "react"; +import { ConfirmationDialog, OrgUnitsSelector } from "@eyeseetea/d2-ui-components"; +import { Grid, IconButton, Typography, TextField, Button } from "@material-ui/core"; +import OpenInNewIcon from "@material-ui/icons/OpenInNew"; import { DataSet } from "$/domain/entities/DataSet"; import i18n from "$/utils/i18n"; import { useAppContext } from "$/webapp/contexts/app-context"; -import { ConfirmationDialog, OrgUnitsSelector } from "@eyeseetea/d2-ui-components"; -import { Grid, IconButton, Typography, TextField, Button } from "@material-ui/core"; -import OpenInNewIcon from "@material-ui/icons/OpenInNew"; export type SetupDataSetProps = { dataSet?: DataSet }; diff --git a/src/webapp/components/dataset-wizard/ShareOptionsDataSet.tsx b/src/webapp/components/dataset-wizard/ShareOptionsDataSet.tsx new file mode 100644 index 00000000..5efd5cc6 --- /dev/null +++ b/src/webapp/components/dataset-wizard/ShareOptionsDataSet.tsx @@ -0,0 +1,40 @@ +import React from "react"; +import i18n from "$/utils/i18n"; +import { MultiSelector } from "@eyeseetea/d2-ui-components"; + +export type ShareOptionsDataSetProps = {}; +export type SelectorItem = { text: string; value: string }; + +export const ShareOptionsDataSet = React.memo((_props: ShareOptionsDataSetProps) => { + const [selected, setSelected] = React.useState([]); + + const items: SelectorItem[] = [ + { + text: "Algeria", + value: "Bangladesh", + }, + { + text: "Brazil", + value: "Brazil", + }, + { + text: "Canada", + value: "Canada", + }, + ]; + + return ( +
+

{i18n.t("Please select the regions you want to share this dataSet with")}

+ +
+ ); +}); + +ShareOptionsDataSet.displayName = "ShareOptionsDataSet"; diff --git a/src/webapp/components/dataset-wizard/SummaryDataSet.tsx b/src/webapp/components/dataset-wizard/SummaryDataSet.tsx new file mode 100644 index 00000000..f44b407f --- /dev/null +++ b/src/webapp/components/dataset-wizard/SummaryDataSet.tsx @@ -0,0 +1,37 @@ +import i18n from "$/utils/i18n"; +import { Grid, Typography } from "@material-ui/core"; +import React from "react"; + +export type SummaryDataSetProps = {}; + +export const SummaryDataSet = React.memo((_props: SummaryDataSetProps) => { + return ( + + + + {i18n.t("The dataSet is finished. Press the button Save to save the data")} + + + +
    + + + + + + +
+
+
+ ); +}); + +export const SummaryItem = React.memo((props: { label: string; value: string }) => { + return ( +
  • + {props.label}: {props.value} +
  • + ); +}); + +SummaryDataSet.displayName = "SummaryDataSet"; diff --git a/src/webapp/pages/app/App.css b/src/webapp/pages/app/App.css index 4f0ed8f1..3eaca251 100644 --- a/src/webapp/pages/app/App.css +++ b/src/webapp/pages/app/App.css @@ -11,3 +11,11 @@ body { li { line-height: 1.75; } + +.dropdown { + width: 100%; +} + +.dropdown > div { + margin-left: 0; +} diff --git a/src/webapp/pages/app/themes/dhis2.theme.ts b/src/webapp/pages/app/themes/dhis2.theme.ts index e550ca22..32be95da 100644 --- a/src/webapp/pages/app/themes/dhis2.theme.ts +++ b/src/webapp/pages/app/themes/dhis2.theme.ts @@ -3,7 +3,7 @@ import { createTheme } from "@material-ui/core/styles"; // Color palette from https://projects.invisionapp.com/share/A7LT4TJYETS#/screens/302550228_Color const colors = { accentPrimary: "#fd5a00", - accentPrimaryDark: "#004BA0", + accentPrimaryDark: "#d14b00", accentPrimaryLight: "#63A4FF", accentPrimaryLightest: "#EAF4FF",