Skip to content

Commit

Permalink
Merge pull request #1260 from BLSQ/IA-2887-ou-picker-validation-status
Browse files Browse the repository at this point in the history
IA-2887: Org unit picker validation status
  • Loading branch information
beygorghor authored May 2, 2024
2 parents 3129399 + d41cd8c commit 5311e98
Show file tree
Hide file tree
Showing 10 changed files with 269 additions and 109 deletions.
2 changes: 2 additions & 0 deletions hat/assets/js/apps/Iaso/domains/app/translations/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@
"blsq.label.clicktoOpenFileSelect": "Click to open file selection",
"blsq.label.dropHere": "Drop files here",
"blsq.label.Files": "Files",
"blsq.treeview.displayNew": "Show new organisation unit",
"blsq.treeview.displayRejected": "Show rejected organisation unit",
"blsq.treeview.displayTypes": "Show organisation unit types",
"blsq.treeview.error": "Please select an org unit",
"blsq.treeview.label.selectMultiple": "Select org unit(s)",
Expand Down
2 changes: 2 additions & 0 deletions hat/assets/js/apps/Iaso/domains/app/translations/fr.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@
"blsq.label.clicktoOpenFileSelect": "Cliquer pour sélectionner des fichiers",
"blsq.label.dropHere": "Déposez les fichiers ici",
"blsq.label.Files": "Fichiers",
"blsq.treeview.displayNew": "Afficher les unités d'org.",
"blsq.treeview.displayRejected": "Afficher les unités d'org. rejétées",
"blsq.treeview.displayTypes": "Afficher les types d'unités d'org.",
"blsq.treeview.error": "Veuillez sélectionner une unité d'org.",
"blsq.treeview.label.selectMultiple": "Sélectionner des unité(s) d'organisation",
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,11 @@
import { Box, Divider, Grid, Typography } from '@mui/material';
import { makeStyles } from '@mui/styles';
import {
IntlFormatMessage,
commonStyles,
useSafeIntl,
useSkipEffectOnMount,
} from 'bluesquare-components';
import React, {
Dispatch,
FunctionComponent,
Expand All @@ -6,34 +14,26 @@ import React, {
useMemo,
useState,
} from 'react';
import { Box, Divider, Grid, Typography } from '@mui/material';
import { makeStyles } from '@mui/styles';
import {
commonStyles,
IntlFormatMessage,
useSafeIntl,
useSkipEffectOnMount,
} from 'bluesquare-components';

import InputComponent from '../../../components/forms/InputComponent';
import DatesRange from '../../../components/filters/DatesRange';
import { ColorPicker } from '../../../components/forms/ColorPicker';
import { OrgUnitTreeviewModal } from './TreeView/OrgUnitTreeviewModal';
import InputComponent from '../../../components/forms/InputComponent';
import { LocationLimit } from '../../../utils/map/LocationLimit';
import DatesRange from '../../../components/filters/DatesRange';
import { OrgUnitTreeviewModal } from './TreeView/OrgUnitTreeviewModal';

import { getChipColors } from '../../../constants/chipColors';

import { useGetGroups } from '../hooks/requests/useGetGroups';
import { useGetDataSources } from '../hooks/requests/useGetDataSources';
import { useGetValidationStatus } from '../../forms/hooks/useGetValidationStatus';
import { useCurrentUser } from '../../../utils/usersUtils';
import { useGetValidationStatus } from '../../forms/hooks/useGetValidationStatus';
import { useGetDataSources } from '../hooks/requests/useGetDataSources';
import { useGetGroups } from '../hooks/requests/useGetGroups';
import { useGetOrgUnit } from './TreeView/requests';

import { Search } from '../types/search';
import MESSAGES from '../messages';
import { InputWithInfos } from '../../../components/InputWithInfos';
import { useGetProjectsDropDown } from '../../projects/hooks/requests/useGetProjectsDropDown';
import { useGetOrgUnitTypes } from '../hooks/requests/useGetOrgUnitTypes';
import { InputWithInfos } from '../../../components/InputWithInfos';
import MESSAGES from '../messages';
import { Search } from '../types/search';

type Props = {
searches: [Search];
Expand Down Expand Up @@ -262,7 +262,7 @@ export const OrgUnitFilters: FunctionComponent<Props> = ({
label={MESSAGES.search}
blockForbiddenChars
onEnterPressed={onSearch}
onErrorChange={(hasError) => setTextSearchError(hasError)}
onErrorChange={hasError => setTextSearchError(hasError)}
/>
</InputWithInfos>
<InputComponent
Expand Down Expand Up @@ -461,7 +461,7 @@ export const OrgUnitFilters: FunctionComponent<Props> = ({
dateFrom={filters?.dateFrom}
dateTo={filters?.dateTo}
/>
)}
)}
</Grid>
</Grid>
);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,29 +1,30 @@
import React, { useState, useCallback, useRef, useEffect } from 'react';
import { Box, useTheme } from '@mui/material';
import { makeStyles } from '@mui/styles';
import { TreeViewWithSearch } from 'bluesquare-components';
import { isEqual } from 'lodash';
import {
array,
arrayOf,
bool,
func,
number,
object,
arrayOf,
oneOfType,
number,
string,
array,
} from 'prop-types';
import { isEqual } from 'lodash';
import { makeStyles } from '@mui/styles';
import { TreeViewWithSearch, useSafeIntl } from 'bluesquare-components';
import { Box, FormControlLabel, Switch, useTheme } from '@mui/material';
import React, { useCallback, useEffect, useRef, useState } from 'react';
import ConfirmCancelDialogComponent from '../../../../components/dialogs/ConfirmCancelDialogComponent';
import { MESSAGES } from './messages';
import { getRootData, getChildrenData, searchOrgUnits } from './requests';
import { OrgUnitLabel, getOrgUnitAncestors } from '../../utils';
import { OrgUnitTreeviewPicker } from './OrgUnitTreeviewPicker';
import { SettingsPopper } from './SettingsPopper.tsx';
import { MESSAGES } from './messages';
import { getChildrenData, getRootData, searchOrgUnits } from './requests';
import {
formatInitialSelectedIds,
formatInitialSelectedParents,
tooltip,
makeTreeviewLabel,
orgUnitTreeviewStatusIconsStyle,
tooltip,
} from './utils';

const useStyles = makeStyles(orgUnitTreeviewStatusIconsStyle);
Expand All @@ -47,9 +48,12 @@ const OrgUnitTreeviewModal = ({
errors,
}) => {
const theme = useTheme();
const { formatMessage } = useSafeIntl();
const classes = useStyles();
const [displayTypes, setDisplayTypes] = useState(true);
const [settings, setSettings] = useState({
displayTypes: true,
displayRejected: false,
displayNew: false,
});

const [selectedOrgUnits, setSelectedOrgUnits] = useState(initialSelection);

Expand Down Expand Up @@ -111,16 +115,28 @@ const OrgUnitTreeviewModal = ({
[selectedOrgUnitsIdsCopy, selectedOrgUnitParentsCopy],
);

const { displayTypes, displayRejected, displayNew } = settings;

const validationStatus = `VALID${displayRejected ? ',REJECTED' : ''}${
displayNew ? ',NEW' : ''
}`;

const getRootDataWithSource = useCallback(async () => {
if (version) return getRootData(version, 'version');
return getRootData(source);
}, [source, version]);
if (version) return getRootData(version, 'version', validationStatus);
return getRootData(source, 'source', validationStatus);
}, [source, version, validationStatus]);

const searchOrgUnitsWithSource = useCallback(
async (value, count) => {
return searchOrgUnits({ value, count, source, version });
return searchOrgUnits({
value,
count,
source,
version,
validationStatus,
});
},
[source, version],
[source, version, validationStatus],
);

const resetSelection = useCallback(() => {
Expand Down Expand Up @@ -186,45 +202,44 @@ const OrgUnitTreeviewModal = ({
maxWidth="sm"
allowConfirm={selectedOrgUnitsIds?.length > 0}
>
<TreeViewWithSearch
getChildrenData={getChildrenData}
getRootData={getRootDataWithSource}
label={makeTreeviewLabel(
classes,
showStatusIconInTree,
displayTypes,
)}
toggleOnLabelClick={toggleOnLabelClick}
onSelect={onOrgUnitSelect}
request={searchOrgUnitsWithSource}
makeDropDownText={orgUnit => <OrgUnitLabel orgUnit={orgUnit} />}
toolTip={tooltip}
parseNodeIds={getOrgUnitAncestors}
multiselect={multiselect}
preselected={selectedOrgUnitsIds}
preexpanded={selectedOrgUnitParents}
selectedData={selectedOrgUnits}
onUpdate={onUpdate}
allowSelection={item => {
if (allowedTypes.length === 0) return true;
return allowedTypes.includes(item.org_unit_type_id);
}}
/>
<Box
position="absolute"
bottom={theme.spacing(3)}
left={theme.spacing(4)}
sx={{
position: 'absolute',
top: theme.spacing(1),
right: theme.spacing(2),
}}
>
<FormControlLabel
control={
<Switch
size="small"
checked={displayTypes}
onChange={() => setDisplayTypes(!displayTypes)}
color="primary"
/>
}
label={formatMessage(MESSAGES.displayTypes)}
<SettingsPopper setSettings={setSettings} settings={settings} />
</Box>
<Box mt={1}>
<TreeViewWithSearch
getChildrenData={getChildrenData}
getRootData={getRootDataWithSource}
label={makeTreeviewLabel(
classes,
showStatusIconInTree,
displayTypes,
)}
toggleOnLabelClick={toggleOnLabelClick}
onSelect={onOrgUnitSelect}
request={searchOrgUnitsWithSource}
makeDropDownText={orgUnit => (
<OrgUnitLabel orgUnit={orgUnit} />
)}
toolTip={tooltip}
parseNodeIds={getOrgUnitAncestors}
multiselect={multiselect}
queryOptions={{ keepPreviousData: true }}
preselected={selectedOrgUnitsIds}
preexpanded={selectedOrgUnitParents}
selectedData={selectedOrgUnits}
onUpdate={onUpdate}
allowSelection={item => {
if (allowedTypes.length === 0) return true;
return allowedTypes.includes(item.org_unit_type_id);
}}
dependency={validationStatus}
childrenDependency={validationStatus}
/>
</Box>
</ConfirmCancelDialogComponent>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
import CancelOutlinedIcon from '@mui/icons-material/CancelOutlined';
import SettingsIcon from '@mui/icons-material/Settings';
import {
Box,
FormControlLabel,
IconButton,
Paper,
Popper,
Switch,
} from '@mui/material';
import { useSafeIntl } from 'bluesquare-components';
import React, {
Dispatch,
FunctionComponent,
MouseEvent,
SetStateAction,
useState,
} from 'react';
import { SxStyles } from '../../../../types/general';
import { MESSAGES } from './messages';

export type Settings = {
displayTypes: boolean;
displayRejected: boolean;
displayNew: boolean;
};

const styles: SxStyles = {
popper: {
zIndex: 1300,
},
closeButton: {
position: 'absolute',
right: 0,
top: 5,
zIndex: 1301,
},
paper: {
padding: theme => theme.spacing(1, 3, 2, 2),
position: 'relative',
},
};

const settingKeys: string[] = ['displayTypes', 'displayRejected', 'displayNew'];

type Props = {
settings: Settings;
setSettings: Dispatch<SetStateAction<Settings>>;
};

export const SettingsPopper: FunctionComponent<Props> = ({
settings,
setSettings,
}) => {
const [anchorEl, setAnchorEl] = useState<null | HTMLElement>(null);

const { formatMessage } = useSafeIntl();
const handleClick = (event: MouseEvent<HTMLElement>) => {
setAnchorEl(anchorEl ? null : event.currentTarget);
};
const handleChangeSettings = (setting: string) => {
setSettings({
...settings,
[setting]: !settings[setting],
});
};
const open = Boolean(anchorEl);
return (
<Box>
<IconButton onClick={handleClick}>
<SettingsIcon color="primary" />
</IconButton>
<Popper
sx={styles.popper}
open={open}
anchorEl={anchorEl}
placement="right"
>
<IconButton
size="small"
onClick={handleClick}
sx={styles.closeButton}
>
<CancelOutlinedIcon color="primary" fontSize="small" />
</IconButton>
<Paper sx={styles.paper} elevation={1}>
{settingKeys.map(settingKey => (
<Box key={settingKey} py={0.5}>
<FormControlLabel
control={
<Switch
size="small"
checked={settings[settingKey]}
onChange={() =>
handleChangeSettings(settingKey)
}
color="primary"
/>
}
label={formatMessage(MESSAGES[settingKey])}
/>
</Box>
))}
</Paper>
</Popper>
</Box>
);
};
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,14 @@ const MESSAGES = defineMessages({
id: 'blsq.treeview.displayTypes',
defaultMessage: 'Show organisation unit types',
},
displayRejected: {
id: 'blsq.treeview.displayRejected',
defaultMessage: 'Show rejected organisation unit',
},
displayNew: {
id: 'blsq.treeview.displayNew',
defaultMessage: 'Show new organisation unit types',
},
});

export { MESSAGES };
Loading

0 comments on commit 5311e98

Please sign in to comment.