diff --git a/.eslintrc.json b/.eslintrc.json
index 8968cf5e8f..e5d5724f64 100644
--- a/.eslintrc.json
+++ b/.eslintrc.json
@@ -147,6 +147,7 @@
],
"rules": {
+ "prefer-arrow-callback": "error",
"react/function-component-definition": "off",
"no-tabs": "off",
"no-console":["error",{"allow":["warn","error"]}],
diff --git a/hat/assets/js/apps/Iaso/constants/menu.tsx b/hat/assets/js/apps/Iaso/constants/menu.tsx
index 5dbe5a4000..d99be26dcf 100644
--- a/hat/assets/js/apps/Iaso/constants/menu.tsx
+++ b/hat/assets/js/apps/Iaso/constants/menu.tsx
@@ -55,7 +55,7 @@ import { DropdownOptions } from '../types/utils';
import { PluginsContext } from '../utils';
import { useCurrentUser } from '../utils/usersUtils';
import MESSAGES from './messages';
-import { CHANGE_REQUEST, CONFIGURATION } from './urls';
+import { CHANGE_REQUEST, CHANGE_REQUEST_CONFIG, CONFIGURATION } from './urls';
// !! remove permission property if the menu has a subMenu !!
const menuItems = (
@@ -206,7 +206,7 @@ const menuItems = (
},
{
label: formatMessage(MESSAGES.configuration),
- key: CHANGE_REQUEST,
+ key: CHANGE_REQUEST_CONFIG,
icon: props => ,
subMenu: [
{
diff --git a/hat/assets/js/apps/Iaso/constants/urls.ts b/hat/assets/js/apps/Iaso/constants/urls.ts
index ab07a99a8a..d37a0c76cc 100644
--- a/hat/assets/js/apps/Iaso/constants/urls.ts
+++ b/hat/assets/js/apps/Iaso/constants/urls.ts
@@ -37,10 +37,12 @@ const orgUnitDetailsLogsParams = paginationPathParamsWithPrefix(LOGS_PREFIX);
const orgUnitDetailsFormsParams = paginationPathParamsWithPrefix(FORMS_PREFIX);
export const CHANGE_REQUEST = 'changeRequest';
+export const CHANGE_REQUEST_CONFIG = 'changeRequestConfig';
export const CONFIGURATION = 'configuration';
const ORG_UNITS = 'orgunits';
const ORG_UNITS_CHANGE_REQUEST = `${ORG_UNITS}/${CHANGE_REQUEST}`;
-const ORG_UNITS_CONFIGURATION_CHANGE_REQUESTS = `${ORG_UNITS_CHANGE_REQUEST}/${CONFIGURATION}`;
+const ORG_UNITS_CHANGE_REQUEST_CONFIG = `${ORG_UNITS}/${CHANGE_REQUEST_CONFIG}`;
+const ORG_UNITS_CONFIGURATION_CHANGE_REQUESTS = `${ORG_UNITS_CHANGE_REQUEST_CONFIG}/${CONFIGURATION}`;
// TODO export to blsq-comp
export type RouteConfig = {
@@ -195,21 +197,9 @@ export const baseRouteConfigs: Record = {
url: ORG_UNITS_CONFIGURATION_CHANGE_REQUESTS,
params: [
'accountId',
- 'parent_id',
- 'groups',
'org_unit_type_id',
- 'status',
- 'created_at_after',
- 'created_at_before',
- 'forms',
- 'userIds',
- 'userRoles',
- 'withLocation',
- 'projectIds',
- 'paymentStatus',
+ 'project_id',
...paginationPathParams,
- 'paymentIds',
- 'potentialPaymentIds',
],
},
registry: {
@@ -350,7 +340,13 @@ export const baseRouteConfigs: Record = {
},
groupSets: {
url: 'orgunits/groupSets',
- params: ['accountId', 'search', 'sourceVersion', 'projectsIds', ...paginationPathParams],
+ params: [
+ 'accountId',
+ 'search',
+ 'sourceVersion',
+ 'projectsIds',
+ ...paginationPathParams,
+ ],
},
groupSetDetail: {
url: 'orgunits/groupSet',
diff --git a/hat/assets/js/apps/Iaso/domains/app/translations/en.json b/hat/assets/js/apps/Iaso/domains/app/translations/en.json
index 0f06304619..7642ff5d74 100644
--- a/hat/assets/js/apps/Iaso/domains/app/translations/en.json
+++ b/hat/assets/js/apps/Iaso/domains/app/translations/en.json
@@ -320,8 +320,8 @@
"iaso.groups.sourceVersion": "Source version",
"iaso.groups.update": "Update group",
"iaso.groupsets.dialog.delete": "Are you sure you want to delete this groupset?",
- "iaso.groupsets.dialog.deleteText":"This operation cannot be undone.",
- "iaso.groupsets.groupBelonging": "Groups belonging",
+ "iaso.groupsets.dialog.deleteText": "This operation cannot be undone.",
+ "iaso.groupsets.groupBelonging": "Groups belonging",
"iaso.groupsets.validation.field_required": "Ce champ est obligatoire",
"iaso.hospital": "Hospital",
"iaso.instance.coordinate": "Coordinates",
@@ -595,6 +595,7 @@
"iaso.label.name": "Name",
"iaso.label.needsAuthentication": "Authentification required",
"iaso.label.newOrgUnit": "New org. unit",
+ "iaso.label.next": "Next",
"iaso.label.no": "No",
"iaso.label.noDifference": "No difference",
"iaso.label.noGeographicalData": "Without geography",
@@ -900,6 +901,16 @@
"iaso.orgUnitsTypes.projects": "Projects",
"iaso.orgUnitsTypes.subTypesErrors": "A sub org unit type cannot be a parent too ({typeName})",
"iaso.orgUnitsTypes.update": "Update org unit type",
+ "iaso.oucrc.closedDate": "Closing Date",
+ "iaso.oucrc.editableReferenceFormIds": "Editable Reference Forms",
+ "iaso.oucrc.groupSetIds": "Group Sets",
+ "iaso.oucrc.orgUnitsEditable": "Should OrgUnits of this type be editable?",
+ "iaso.oucrc.otherGroupIds": "Other Groups",
+ "iaso.oucrc.oucrcCreateModalTitle": "OrgUnit Change Request Configuration - Creation",
+ "iaso.oucrc.oucrcCreateModalTitle2": "OrgUnit Change Request Configuration - Creation 2nd step",
+ "iaso.oucrc.oucrcCreateUpdateModalTitle": "OrgUnit Change Request Configuration - Update",
+ "iaso.oucrc.possibleParentTypeIds": "Possible New Parent Types",
+ "iaso.oucrc.possibleTypeIds": "Possible New Types",
"iaso.page.deleteError": "Error removing embedded link",
"iaso.page.deleteSuccess": "Embedded link successfully removed",
"iaso.page.viewpages": "View embedded link. {linebreak} New tab: ctrl + click",
@@ -1179,6 +1190,7 @@
"iaso.snackBar.fetchFormsError": "An error occurred while fetching forms list",
"iaso.snackBar.fetchFormVersionsError": "An error occurred while fetching form versions",
"iaso.snackBar.fetchGroupsError": "An error occurred while fetching groups list",
+ "iaso.snackBar.fetchGroupSetsError": "An error occurred while fetching group sets list",
"iaso.snackBar.fetchingLogDetailError": "An error occurred while fetching log details",
"iaso.snackBar.fetchInstanceDictError": "An error occurred while fetching instances list",
"iaso.snackBar.fetchInstanceError": "An error occurred while fetching instance detail",
@@ -1498,4 +1510,4 @@
"trypelim.permissions.zones": "Zones",
"trypelim.permissions.zones_edit": "Edit zones",
"trypelim.permissions.zones_shapes_edit": "Edit zone shapes"
-}
+}
\ No newline at end of file
diff --git a/hat/assets/js/apps/Iaso/domains/app/translations/fr.json b/hat/assets/js/apps/Iaso/domains/app/translations/fr.json
index d34dd1389c..597a89aa15 100644
--- a/hat/assets/js/apps/Iaso/domains/app/translations/fr.json
+++ b/hat/assets/js/apps/Iaso/domains/app/translations/fr.json
@@ -595,6 +595,7 @@
"iaso.label.name": "Nom",
"iaso.label.needsAuthentication": "Authentification requise",
"iaso.label.newOrgUnit": "Nouvelle unité d'org.",
+ "iaso.label.next": "Suivant",
"iaso.label.no": "Non",
"iaso.label.noDifference": "Aucune différence",
"iaso.label.noGeographicalData": "Sans données géographiques",
@@ -900,6 +901,16 @@
"iaso.orgUnitsTypes.projects": "Projets",
"iaso.orgUnitsTypes.subTypesErrors": "Un sous type d'unité d'organisation ne peut pas aussi être parent ({typeName})",
"iaso.orgUnitsTypes.update": "Mettre à jour le type d'unité d'organisation",
+ "iaso.oucrc.closedDate": "Date de fermeture",
+ "iaso.oucrc.editableReferenceFormIds": "Formulaires de référence modifiables",
+ "iaso.oucrc.groupSetIds": "Ensembles de groupes",
+ "iaso.oucrc.orgUnitsEditable": "Les unités d'organisation de ce type doivent-elles être modifiables ?",
+ "iaso.oucrc.otherGroupIds": "Autres groupes",
+ "iaso.oucrc.oucrcCreateModalTitle": "Configuration de demande de changement d'unité d'organisation - Création",
+ "iaso.oucrc.oucrcCreateModalTitle2": "Configuration de demande de changement d'unité d'organisation - Deuxième étape de création",
+ "iaso.oucrc.oucrcCreateUpdateModalTitle": "Configuration de demande de changement d'unité d'organisation - Mise à jour",
+ "iaso.oucrc.possibleParentTypeIds": "Types de parents possibles",
+ "iaso.oucrc.possibleTypeIds": "Nouveaux types possibles",
"iaso.page.deleteError": "Erreur lors de la suppression du lien intégré",
"iaso.page.deleteSuccess": "Lien intégré supprimée",
"iaso.page.viewpages": "Voir le lien intégré. {linebreak} Nouvel onglet: ctrl + click",
@@ -1179,6 +1190,7 @@
"iaso.snackBar.fetchFormsError": "Une erreur est survenue en récupérant la liste des formulaires",
"iaso.snackBar.fetchFormVersionsError": "Une erreur est survenue en récupérant les version du formulaire",
"iaso.snackBar.fetchGroupsError": "Une erreur est survenue en récupérant la liste des groupes",
+ "iaso.snackBar.fetchGroupSetsError": "Une erreur est survenue en récupérant la liste des group sets",
"iaso.snackBar.fetchingLogDetailError": "Une erreur est survenu en récupérant l'historique",
"iaso.snackBar.fetchInstanceDictError": "Une erreur est survenue en récupérant la liste des soumissions",
"iaso.snackBar.fetchInstanceError": "Une erreur est survenue en récupérant le detail de la soumission",
diff --git a/hat/assets/js/apps/Iaso/domains/orgUnits/configuration/Dialog/ConfirmDeleteModal.tsx b/hat/assets/js/apps/Iaso/domains/orgUnits/configuration/Dialog/ConfirmDeleteModal.tsx
index 275f6f9dfb..1a12c67253 100644
--- a/hat/assets/js/apps/Iaso/domains/orgUnits/configuration/Dialog/ConfirmDeleteModal.tsx
+++ b/hat/assets/js/apps/Iaso/domains/orgUnits/configuration/Dialog/ConfirmDeleteModal.tsx
@@ -6,15 +6,15 @@ import {
useSafeIntl,
} from 'bluesquare-components';
-import MESSAGES from '../messages';
-import { OrgUnitChangeRequestConfig } from '../types';
import { DeleteIconButton } from '../../../../components/Buttons/DeleteIconButton';
import { useDeleteOrgUnitChangeRequestConfig } from '../hooks/api/useDeleteOrgUnitChangeRequestConfig';
+import MESSAGES from '../messages';
+import { OrgUnitChangeRequestConfigurationFull } from '../types';
type Props = {
isOpen: boolean;
closeDialog: () => void;
- config: OrgUnitChangeRequestConfig;
+ config: OrgUnitChangeRequestConfigurationFull;
};
const ConfirmDeleteModal: FunctionComponent = ({
diff --git a/hat/assets/js/apps/Iaso/domains/orgUnits/configuration/Dialog/OrgUnitChangeRequestConfigDialog.tsx b/hat/assets/js/apps/Iaso/domains/orgUnits/configuration/Dialog/OrgUnitChangeRequestConfigDialog.tsx
new file mode 100644
index 0000000000..05555477c9
--- /dev/null
+++ b/hat/assets/js/apps/Iaso/domains/orgUnits/configuration/Dialog/OrgUnitChangeRequestConfigDialog.tsx
@@ -0,0 +1,272 @@
+import { Typography } from '@mui/material';
+import {
+ ConfirmCancelModal,
+ LoadingSpinner,
+ makeFullModal,
+ useSafeIntl,
+} from 'bluesquare-components';
+import { useFormik } from 'formik';
+import { isEqual } from 'lodash';
+import React, { FunctionComponent, useCallback, useEffect } from 'react';
+import { EditIconButton } from '../../../../components/Buttons/EditIconButton';
+import InputComponent from '../../../../components/forms/InputComponent';
+import { useTranslatedErrors } from '../../../../libs/validation';
+import { useGetGroupDropdown } from '../../hooks/requests/useGetGroups';
+import { useGetGroupSetsDropdown } from '../../hooks/requests/useGetGroupSets';
+import { useGetOrgUnitTypesDropdownOptions } from '../../orgUnitTypes/hooks/useGetOrgUnitTypesDropdownOptions';
+import { editableFieldsManyToManyFields } from '../constants';
+import { useGetFormDropdownOptions } from '../hooks/api/useGetFormDropdownOptions';
+import { useRetrieveOrgUnitChangeRequestConfig } from '../hooks/api/useRetrieveOrgUnitChangeRequestConfig';
+import { useSaveOrgUnitChangeRequestConfiguration } from '../hooks/api/useSaveOrgUnitChangeRequestConfiguration';
+import { useOrgUnitsEditableFieldsOptions } from '../hooks/useOrgUnitEditableFieldsOptions';
+import { useOrgUnitsEditableOptions } from '../hooks/useOrgUnitsEditableOptions';
+import { useValidationSchemaOUCRC } from '../hooks/useValidationSchemaOUCRC';
+import MESSAGES from '../messages';
+import {
+ OrgUnitChangeRequestConfiguration,
+ OrgUnitChangeRequestConfigurationForm,
+} from '../types';
+
+type Props = {
+ config: OrgUnitChangeRequestConfiguration;
+ isOpen: boolean;
+ closeDialog: () => void;
+};
+
+// we should filter forms, groups, groupsets, types using correct project id
+/// marquer les types comme requis
+
+const OrgUnitChangeRequestConfigDialog: FunctionComponent = ({
+ config,
+ isOpen,
+ closeDialog,
+}) => {
+ const configValidationSchema = useValidationSchemaOUCRC();
+ const {
+ values,
+ setFieldValue,
+ isValid,
+ handleSubmit,
+ isSubmitting,
+ errors,
+ touched,
+ setFieldTouched,
+ setValues,
+ } = useFormik({
+ initialValues: {
+ projectId: config.project.id,
+ orgUnitTypeId: config.orgUnitType.id,
+ orgUnitsEditable: undefined,
+ editableFields: undefined,
+ possibleTypeIds: undefined,
+ possibleParentTypeIds: undefined,
+ groupSetIds: undefined,
+ editableReferenceFormIds: undefined,
+ otherGroupIds: undefined,
+ },
+ validationSchema: configValidationSchema,
+ onSubmit: (newValues: OrgUnitChangeRequestConfigurationForm) => {
+ saveConfig({
+ configId: config.id,
+ data: newValues,
+ });
+ closeDialog();
+ },
+ });
+ const { data: fetchedConfig, isLoading: isLoadingFullConfig } =
+ useRetrieveOrgUnitChangeRequestConfig(config?.id);
+ useEffect(() => {
+ if (fetchedConfig) {
+ setValues(fetchedConfig);
+ }
+ }, [fetchedConfig, setValues]);
+ const { data: orgUnitTypeOptions } = useGetOrgUnitTypesDropdownOptions(
+ config.project.id,
+ );
+ const { data: groupOptions } = useGetGroupDropdown({
+ defaultVersion: 'true',
+ });
+ const { data: formOptions } = useGetFormDropdownOptions(
+ config.orgUnitType.id,
+ config.project.id,
+ );
+ const { data: groupSetOptions } = useGetGroupSetsDropdown();
+ const { mutateAsync: saveConfig } =
+ useSaveOrgUnitChangeRequestConfiguration();
+ const orgUnitsEditableOptions = useOrgUnitsEditableOptions();
+ const orgUnitEditableFieldsOptions = useOrgUnitsEditableFieldsOptions();
+ const { formatMessage } = useSafeIntl();
+ const getErrors = useTranslatedErrors({
+ errors,
+ touched,
+ formatMessage,
+ messages: MESSAGES,
+ });
+
+ const onChange = useCallback(
+ (keyValue, value) => {
+ setFieldTouched(keyValue, true);
+ setFieldValue(keyValue, value);
+ },
+ [setFieldValue, setFieldTouched],
+ );
+
+ const onChangeEditableFields = useCallback(
+ (keyValue, value) => {
+ // if a many-to-many field has some value, but the field is removed from editableFields, we need to clean the field
+ if (value) {
+ const split = value.split(',');
+ editableFieldsManyToManyFields.forEach(field => {
+ if (!split.includes(field)) {
+ setFieldValue(field, undefined);
+ }
+ });
+ }
+ onChange(keyValue, value);
+ },
+ [onChange, setFieldValue],
+ );
+
+ const onChangeOrgUnitsEditable = useCallback(
+ (keyValue, value) => {
+ // if we say that the org units are no longer editable, we need to clean everything up
+ const boolValue = value === 'true';
+ if (!boolValue) {
+ editableFieldsManyToManyFields.forEach(field => {
+ setFieldValue(field, undefined);
+ });
+ setFieldValue('editableFields', undefined);
+ setFieldValue('groupSetIds', undefined);
+ }
+ onChange(keyValue, boolValue);
+ },
+ [onChange, setFieldValue],
+ );
+ const allowConfirm = isValid && !isSubmitting && !isEqual(touched, {});
+ return (
+ null}
+ id="oucrcDialogCreate"
+ dataTestId="add-org-unit-config-button"
+ titleMessage={
+ config?.id
+ ? formatMessage(MESSAGES.oucrcCreateUpdateModalTitle)
+ : formatMessage(MESSAGES.oucrcCreateSecondStepModalTitle)
+ }
+ closeDialog={closeDialog}
+ maxWidth="sm"
+ allowConfirm={allowConfirm}
+ cancelMessage={MESSAGES.cancel}
+ confirmMessage={
+ config?.id
+ ? MESSAGES.oucrcModalUpdateButton
+ : MESSAGES.oucrcModalCreateButton
+ }
+ onConfirm={() => handleSubmit()}
+ onCancel={() => {
+ closeDialog();
+ }}
+ >
+ {isLoadingFullConfig && }
+
+ {formatMessage(MESSAGES.project)}: {config.project.name}
+
+
+ {formatMessage(MESSAGES.orgUnitType)}: {config.orgUnitType.name}
+
+
+ {values?.orgUnitsEditable && (
+
+ )}
+ {values?.orgUnitsEditable && (
+
+ )}
+ {values?.editableFields?.includes('possibleTypeIds') && (
+
+ )}
+ {values?.editableFields?.includes('possibleParentTypeIds') && (
+
+ )}
+ {values?.editableFields?.includes('editableReferenceFormIds') && (
+
+ )}
+ {values?.editableFields?.includes('otherGroupIds') && (
+
+ )}
+
+ );
+};
+
+const modalWithButton = makeFullModal(
+ OrgUnitChangeRequestConfigDialog,
+ EditIconButton,
+);
+
+export {
+ OrgUnitChangeRequestConfigDialog as OrgUnitChangeRequestConfigDialogCreateSecondStep,
+ modalWithButton as OrgUnitChangeRequestConfigDialogUpdate
+};
+
diff --git a/hat/assets/js/apps/Iaso/domains/orgUnits/configuration/Dialog/OrgUnitChangeRequestConfigDialogCreateFirstStep.tsx b/hat/assets/js/apps/Iaso/domains/orgUnits/configuration/Dialog/OrgUnitChangeRequestConfigDialogCreateFirstStep.tsx
new file mode 100644
index 0000000000..e6c6923849
--- /dev/null
+++ b/hat/assets/js/apps/Iaso/domains/orgUnits/configuration/Dialog/OrgUnitChangeRequestConfigDialogCreateFirstStep.tsx
@@ -0,0 +1,151 @@
+import {
+ AddButton,
+ ConfirmCancelModal,
+ makeFullModal,
+ useSafeIntl,
+} from 'bluesquare-components';
+import { useFormik } from 'formik';
+import { isEqual } from 'lodash';
+import React, { FunctionComponent, useCallback } from 'react';
+import * as Yup from 'yup';
+import InputComponent from '../../../../components/forms/InputComponent';
+import { useTranslatedErrors } from '../../../../libs/validation';
+import { useGetProjectsDropdownOptions } from '../../../projects/hooks/requests';
+import { useGetOUCRCCheckAvailabilityDropdownOptions } from '../hooks/api/useGetOUCRCCheckAvailabilityDropdownOptions';
+import MESSAGES from '../messages';
+
+type Props = {
+ isOpen: boolean;
+ closeDialog: () => void;
+ // eslint-disable-next-line no-unused-vars
+ openCreationSecondStepDialog: (config: object) => void;
+};
+
+const useCreationSchema = () => {
+ const { formatMessage } = useSafeIntl();
+ return Yup.object().shape({
+ projectId: Yup.string()
+ .nullable()
+ .required(formatMessage(MESSAGES.requiredField)),
+ orgUnitTypeId: Yup.string()
+ .nullable()
+ .required(formatMessage(MESSAGES.requiredField)),
+ });
+};
+
+const OrgUnitChangeRequestConfigDialogCreateFirstStep: FunctionComponent<
+ Props
+> = ({ isOpen, closeDialog, openCreationSecondStepDialog }) => {
+ const creationSchema = useCreationSchema();
+ const {
+ values,
+ setFieldValue,
+ isValid,
+ handleSubmit,
+ isSubmitting,
+ errors,
+ touched,
+ setFieldTouched,
+ } = useFormik({
+ initialValues: {
+ projectId: undefined,
+ orgUnitTypeId: undefined,
+ },
+ validationSchema: creationSchema,
+ onSubmit: () => {
+ const projectOption = allProjects?.find(
+ project => `${project.value}` === `${values.projectId}`,
+ );
+ const orgUnitTypeOption = orgUnitTypeOptions?.find(
+ orgUnitType =>
+ `${orgUnitType.value}` === `${values.orgUnitTypeId}`,
+ );
+ openCreationSecondStepDialog({
+ project: projectOption
+ ? {
+ id: projectOption.value,
+ name: projectOption.label,
+ }
+ : undefined,
+ orgUnitType: orgUnitTypeOption
+ ? {
+ id: orgUnitTypeOption.value,
+ name: orgUnitTypeOption.label,
+ }
+ : undefined,
+ });
+ },
+ });
+
+ const { formatMessage } = useSafeIntl();
+ const getErrors = useTranslatedErrors({
+ errors,
+ touched,
+ formatMessage,
+ messages: MESSAGES,
+ });
+
+ const { data: allProjects, isFetching: isFetchingProjects } =
+ useGetProjectsDropdownOptions(false);
+ const { data: orgUnitTypeOptions, isFetching: isFetchingOrgUnitTypes } =
+ useGetOUCRCCheckAvailabilityDropdownOptions(values.projectId);
+
+ const onChange = useCallback(
+ (keyValue, value) => {
+ setFieldTouched(keyValue, true);
+ setFieldValue(keyValue, value);
+ },
+ [setFieldValue, setFieldTouched],
+ );
+
+ const allowConfirm = isValid && !isSubmitting && !isEqual(touched, {});
+
+ return (
+ null}
+ id="oucrcDialogCreate"
+ dataTestId="add-org-unit-config-button"
+ titleMessage={formatMessage(MESSAGES.oucrcCreateModalTitle)}
+ closeDialog={closeDialog}
+ maxWidth="xs"
+ allowConfirm={allowConfirm}
+ cancelMessage={MESSAGES.cancel}
+ confirmMessage={MESSAGES.next}
+ onConfirm={() => handleSubmit()}
+ onCancel={() => {
+ closeDialog();
+ }}
+ >
+
+
+
+ );
+};
+
+const modalWithButton = makeFullModal(
+ OrgUnitChangeRequestConfigDialogCreateFirstStep,
+ AddButton,
+);
+
+export { modalWithButton as OrgUnitChangeRequestConfigDialogCreateFirstStep };
diff --git a/hat/assets/js/apps/Iaso/domains/orgUnits/configuration/Filter/OrgUnitChangeRequestConfigsFilter.tsx b/hat/assets/js/apps/Iaso/domains/orgUnits/configuration/Filter/OrgUnitChangeRequestConfigsFilter.tsx
index eb2ef4532e..917d4d85c0 100644
--- a/hat/assets/js/apps/Iaso/domains/orgUnits/configuration/Filter/OrgUnitChangeRequestConfigsFilter.tsx
+++ b/hat/assets/js/apps/Iaso/domains/orgUnits/configuration/Filter/OrgUnitChangeRequestConfigsFilter.tsx
@@ -1,14 +1,14 @@
-import React, { FunctionComponent } from 'react';
import { Box, Grid } from '@mui/material';
import { useSafeIntl } from 'bluesquare-components';
-import { useFilterState } from '../../../../hooks/useFilterState';
+import React, { FunctionComponent } from 'react';
+import { FilterButton } from '../../../../components/FilterButton';
import InputComponent from '../../../../components/forms/InputComponent';
import { baseUrls } from '../../../../constants/urls';
-import { useGetOrgUnitTypesDropdownOptions } from '../../orgUnitTypes/hooks/useGetOrgUnitTypesDropdownOptions';
-import { OrgUnitChangeRequestConfigsParams } from '../types';
+import { useFilterState } from '../../../../hooks/useFilterState';
import { useGetProjectsDropdownOptions } from '../../../projects/hooks/requests';
+import { useGetOrgUnitTypesDropdownOptions } from '../../orgUnitTypes/hooks/useGetOrgUnitTypesDropdownOptions';
import MESSAGES from '../messages';
-import { FilterButton } from '../../../../components/FilterButton';
+import { OrgUnitChangeRequestConfigsParams } from '../types';
const baseUrl = baseUrls.orgUnitsChangeRequestConfiguration;
type Props = { params: OrgUnitChangeRequestConfigsParams };
@@ -30,7 +30,7 @@ export const OrgUnitChangeRequestConfigsFilter: FunctionComponent = ({
= ({
labelString={formatMessage(MESSAGES.orgUnitType)}
/>
-
-
+
+
({
...commonStyles(theme),
@@ -19,12 +24,23 @@ export const OrgUnitChangeRequestConfigs: FunctionComponent = () => {
const params = useParamsObject(
baseUrls.orgUnitsChangeRequestConfiguration,
) as unknown as OrgUnitChangeRequestConfigsParams;
+
const { data, isFetching } = useGetOrgUnitChangeRequestConfigs(params);
+ const [isCreationSecondStepDialogOpen, setIsCreationSecondStepDialogOpen] =
+ useState(false);
+ const [config, setConfig] = useState();
+
+ const handleSecondStep = useCallback(
+ newConfig => {
+ setConfig(newConfig);
+ setIsCreationSecondStepDialogOpen(true);
+ },
+ [setIsCreationSecondStepDialogOpen, setConfig],
+ );
const classes: Record = useStyles();
const { formatMessage } = useSafeIntl();
-
return (
{
- {
- // TODO
- }}
+
+ {isCreationSecondStepDialogOpen && config && (
+ {
+ setIsCreationSecondStepDialogOpen(false);
+ }}
+ config={config}
+ />
+ )}
{
- // TODO
- }}
+ onEditClicked={handleSecondStep}
/>
diff --git a/hat/assets/js/apps/Iaso/domains/orgUnits/configuration/Tables/EditableFieldsCell.tsx b/hat/assets/js/apps/Iaso/domains/orgUnits/configuration/Tables/EditableFieldsCell.tsx
new file mode 100644
index 0000000000..4f086fb45c
--- /dev/null
+++ b/hat/assets/js/apps/Iaso/domains/orgUnits/configuration/Tables/EditableFieldsCell.tsx
@@ -0,0 +1,38 @@
+/* eslint-disable camelcase */
+import { Box, Chip } from '@mui/material';
+import { textPlaceholder, useSafeIntl } from 'bluesquare-components';
+import React, { useMemo } from 'react';
+import { computeEditableFields } from '../hooks/api/useRetrieveOrgUnitChangeRequestConfig';
+import MESSAGES from '../messages';
+import { OrgUnitChangeRequestConfigurationFull } from '../types';
+
+export const EditableFieldsCell = ({
+ row: { original },
+}: {
+ row: { original: OrgUnitChangeRequestConfigurationFull };
+}) => {
+ const { formatMessage } = useSafeIntl();
+ const editableFields = useMemo(
+ () => computeEditableFields(original),
+ [original],
+ );
+
+ if (editableFields.length === 0) {
+ return textPlaceholder;
+ }
+
+ return (
+
+ {editableFields.map(field => (
+
+ ))}
+
+ );
+};
diff --git a/hat/assets/js/apps/Iaso/domains/orgUnits/configuration/Tables/OrgUnitChangeRequestConfigsTable.tsx b/hat/assets/js/apps/Iaso/domains/orgUnits/configuration/Tables/OrgUnitChangeRequestConfigsTable.tsx
index 4e48abb72b..2f34275268 100644
--- a/hat/assets/js/apps/Iaso/domains/orgUnits/configuration/Tables/OrgUnitChangeRequestConfigsTable.tsx
+++ b/hat/assets/js/apps/Iaso/domains/orgUnits/configuration/Tables/OrgUnitChangeRequestConfigsTable.tsx
@@ -1,25 +1,26 @@
+import { Column, useSafeIntl } from 'bluesquare-components';
import React, {
- FunctionComponent,
Dispatch,
+ FunctionComponent,
SetStateAction,
- useMemo,
useCallback,
+ useMemo,
} from 'react';
-import { Column, useSafeIntl } from 'bluesquare-components';
+import { EditIconButton } from '../../../../components/Buttons/EditIconButton';
+import { DateTimeCell } from '../../../../components/Cells/DateTimeCell';
import { TableWithDeepLink } from '../../../../components/tables/TableWithDeepLink';
import { baseUrls } from '../../../../constants/urls';
+import { ConfirmDeleteModal } from '../Dialog/ConfirmDeleteModal';
+import MESSAGES from '../messages';
import {
OrgUnitChangeRequestConfigsPaginated,
OrgUnitChangeRequestConfigsParams,
- OrgUnitChangeRequestConfig,
+ OrgUnitChangeRequestConfiguration,
} from '../types';
-import MESSAGES from '../messages';
-import { DateTimeCell } from '../../../../components/Cells/DateTimeCell';
-import { EditIconButton } from '../../../../components/Buttons/EditIconButton';
-import { ConfirmDeleteModal } from '../Dialog/ConfirmDeleteModal';
+import { EditableFieldsCell } from './EditableFieldsCell';
const useColumns = (
- onEditClicked: Dispatch>,
+ onEditClicked: Dispatch>,
): Column[] => {
const { formatMessage } = useSafeIntl();
// @ts-ignore
@@ -56,8 +57,8 @@ const useColumns = (
{
Header: formatMessage(MESSAGES.editable_fields),
id: 'editable_fields',
- accessor: row => row.editable_fields.join(', '),
- width: 600,
+ sortable: false,
+ Cell: EditableFieldsCell,
},
{
Header: formatMessage(MESSAGES.actions),
@@ -66,7 +67,12 @@ const useColumns = (
sortable: false,
Cell: settings => {
const handleEdit = useCallback(() => {
- onEditClicked(settings.row.original);
+ const configToUpdate = {
+ id: settings.row.original.id,
+ project: settings.row.original.project,
+ orgUnitType: settings.row.original.org_unit_type,
+ };
+ onEditClicked(configToUpdate);
}, [settings.row.original]);
return (
<>
@@ -87,7 +93,7 @@ const useColumns = (
type Props = {
data: OrgUnitChangeRequestConfigsPaginated | undefined;
isFetching: boolean;
- onEditClicked: Dispatch>;
+ onEditClicked: Dispatch>;
params: OrgUnitChangeRequestConfigsParams;
};
export const baseUrl = baseUrls.orgUnitsChangeRequestConfiguration;
diff --git a/hat/assets/js/apps/Iaso/domains/orgUnits/configuration/constants.ts b/hat/assets/js/apps/Iaso/domains/orgUnits/configuration/constants.ts
index c04885c24e..eda4c27b07 100644
--- a/hat/assets/js/apps/Iaso/domains/orgUnits/configuration/constants.ts
+++ b/hat/assets/js/apps/Iaso/domains/orgUnits/configuration/constants.ts
@@ -1 +1,31 @@
-export const apiUrl = '/api/orgunits/changes/configs/';
+export const apiUrlOUCRC = '/api/orgunits/changes/configs/';
+export const apiUrlOUCRCCheckAvailability = `${apiUrlOUCRC}check_availability/`;
+export const apiUrlForms = '/api/forms/';
+export const editableFields = [
+ 'name',
+ // 'aliases', commented out because right now the feature is not ready yet
+ 'openingDate',
+ 'closedDate',
+ 'location',
+ 'possibleTypeIds',
+ 'possibleParentTypeIds',
+ 'editableReferenceFormIds',
+ 'otherGroupIds',
+];
+export const mappingEditableFieldsForBackend = {
+ name: 'name',
+ // 'aliases': 'aliases', commented out because right now the feature is not ready yet
+ openingDate: 'opening_date',
+ closedDate: 'closing_date',
+ location: 'location',
+ possibleTypeIds: 'org_unit_type',
+ possibleParentTypeIds: 'parent_type',
+ editableReferenceFormIds: 'editable_reference_forms',
+ otherGroupIds: 'other_groups',
+};
+export const editableFieldsManyToManyFields = [
+ 'possibleTypeIds',
+ 'possibleParentTypeIds',
+ 'editableReferenceFormIds',
+ 'otherGroupIds',
+];
diff --git a/hat/assets/js/apps/Iaso/domains/orgUnits/configuration/hooks/api/useDeleteOrgUnitChangeRequestConfig.ts b/hat/assets/js/apps/Iaso/domains/orgUnits/configuration/hooks/api/useDeleteOrgUnitChangeRequestConfig.ts
index f1834fa0b0..5df2bfdbdf 100644
--- a/hat/assets/js/apps/Iaso/domains/orgUnits/configuration/hooks/api/useDeleteOrgUnitChangeRequestConfig.ts
+++ b/hat/assets/js/apps/Iaso/domains/orgUnits/configuration/hooks/api/useDeleteOrgUnitChangeRequestConfig.ts
@@ -1,16 +1,22 @@
import { UseMutationResult } from 'react-query';
import { useSnackMutation } from '../../../../../libs/apiHooks';
-import { apiUrl } from '../../constants';
-import { OrgUnitChangeRequestConfig } from '../../types';
import { deleteRequest } from '../../../../../libs/Api';
+import { apiUrlOUCRC } from '../../constants';
+import { OrgUnitChangeRequestConfigurationFull } from '../../types';
-const deleteOrgUnitChangeRequestConfigs = (config: OrgUnitChangeRequestConfig) => {
- return deleteRequest(`${apiUrl}/${config.id}/`) as Promise;
+const deleteOrgUnitChangeRequestConfigs = (
+ config: OrgUnitChangeRequestConfigurationFull,
+) => {
+ return deleteRequest(`${apiUrlOUCRC}${config.id}/`) as Promise;
};
export const useDeleteOrgUnitChangeRequestConfig = (): UseMutationResult =>
useSnackMutation({
mutationFn: deleteOrgUnitChangeRequestConfigs,
- invalidateQueryKey: 'getOrgUnitChangeRequestConfigs',
+ invalidateQueryKey: [
+ 'useRetrieveOrgUnitChangeRequestConfig',
+ 'getOrgUnitChangeRequestConfigs',
+ 'checkAvailabilityOrgUnitChangeRequestConfigs',
+ ],
});
diff --git a/hat/assets/js/apps/Iaso/domains/orgUnits/configuration/hooks/api/useGetFormDropdownOptions.ts b/hat/assets/js/apps/Iaso/domains/orgUnits/configuration/hooks/api/useGetFormDropdownOptions.ts
new file mode 100644
index 0000000000..989f84cbd5
--- /dev/null
+++ b/hat/assets/js/apps/Iaso/domains/orgUnits/configuration/hooks/api/useGetFormDropdownOptions.ts
@@ -0,0 +1,35 @@
+import { UseQueryResult } from 'react-query';
+
+import { useSnackQuery } from '../../../../../libs/apiHooks';
+import { getRequest } from '../../../../../libs/Api';
+
+import { Form } from '../../../../forms/types/forms';
+import { DropdownOptions } from '../../../../../types/utils';
+import { apiUrlForms } from '../../constants';
+
+export const useGetFormDropdownOptions = (
+ orgUnitTypeId: number,
+): UseQueryResult[], Error> => {
+ const url = `${apiUrlForms}?orgUnitTypeIds=${orgUnitTypeId}`;
+ return useSnackQuery({
+ queryKey: ['useGetFormDropdownOptions', url],
+ queryFn: () => getRequest(url),
+ options: {
+ enabled: Boolean(orgUnitTypeId),
+ staleTime: 1000 * 60 * 15, // in MS
+ cacheTime: 1000 * 60 * 5,
+ keepPreviousData: true,
+ retry: false,
+ select: data => {
+ return (
+ data?.forms?.map((form: Form) => {
+ return {
+ value: form.id,
+ label: form.name,
+ };
+ }) ?? []
+ );
+ },
+ },
+ });
+};
diff --git a/hat/assets/js/apps/Iaso/domains/orgUnits/configuration/hooks/api/useGetOUCRCCheckAvailabilityDropdownOptions.ts b/hat/assets/js/apps/Iaso/domains/orgUnits/configuration/hooks/api/useGetOUCRCCheckAvailabilityDropdownOptions.ts
new file mode 100644
index 0000000000..64e62d32c0
--- /dev/null
+++ b/hat/assets/js/apps/Iaso/domains/orgUnits/configuration/hooks/api/useGetOUCRCCheckAvailabilityDropdownOptions.ts
@@ -0,0 +1,32 @@
+import { UseQueryResult } from 'react-query';
+import { getRequest } from '../../../../../libs/Api';
+import { useSnackQuery } from '../../../../../libs/apiHooks';
+
+import { apiUrlOUCRCCheckAvailability } from '../../constants';
+import { OrgUnitType } from '../../types';
+import { DropdownOptions } from '../../../../../types/utils';
+
+export const useGetOUCRCCheckAvailabilityDropdownOptions = (
+ projectId?: number,
+): UseQueryResult[], Error> => {
+ const url = `${apiUrlOUCRCCheckAvailability}?project_id=${projectId}`;
+ return useSnackQuery({
+ queryKey: ['checkAvailabilityOrgUnitChangeRequestConfigs', url],
+ queryFn: () => getRequest(url),
+ options: {
+ enabled: Boolean(projectId),
+ staleTime: 1000 * 60 * 15, // in MS
+ cacheTime: 1000 * 60 * 5,
+ keepPreviousData: true,
+ retry: false,
+ select: data => {
+ return (
+ data?.map((orgUnitType: OrgUnitType) => ({
+ value: orgUnitType.id,
+ label: orgUnitType.name,
+ })) ?? []
+ );
+ },
+ },
+ });
+};
diff --git a/hat/assets/js/apps/Iaso/domains/orgUnits/configuration/hooks/api/useGetOrgUnitChangeRequestConfigs.ts b/hat/assets/js/apps/Iaso/domains/orgUnits/configuration/hooks/api/useGetOrgUnitChangeRequestConfigs.ts
index e45fbcf509..5cea58eff7 100644
--- a/hat/assets/js/apps/Iaso/domains/orgUnits/configuration/hooks/api/useGetOrgUnitChangeRequestConfigs.ts
+++ b/hat/assets/js/apps/Iaso/domains/orgUnits/configuration/hooks/api/useGetOrgUnitChangeRequestConfigs.ts
@@ -4,7 +4,7 @@ import { getRequest } from '../../../../../libs/Api';
import { useSnackQuery } from '../../../../../libs/apiHooks';
import { useLocale } from '../../../../app/contexts/LocaleContext';
-import { apiUrl } from '../../constants';
+import { apiUrlOUCRC } from '../../constants';
import {
OrgUnitChangeRequestConfigsPaginated,
OrgUnitChangeRequestConfigsParams,
@@ -26,7 +26,7 @@ export const useGetOrgUnitChangeRequestConfigs = (
page: params.page,
};
- const url = makeUrlWithParams(apiUrl, apiParams);
+ const url = makeUrlWithParams(apiUrlOUCRC, apiParams);
return useSnackQuery({
// Including locale in the query key because we need to make a call to update translations coming from the backend
queryKey: ['getOrgUnitChangeRequestConfigs', url, locale],
diff --git a/hat/assets/js/apps/Iaso/domains/orgUnits/configuration/hooks/api/useRetrieveOrgUnitChangeRequestConfig.ts b/hat/assets/js/apps/Iaso/domains/orgUnits/configuration/hooks/api/useRetrieveOrgUnitChangeRequestConfig.ts
new file mode 100644
index 0000000000..eacaf808e0
--- /dev/null
+++ b/hat/assets/js/apps/Iaso/domains/orgUnits/configuration/hooks/api/useRetrieveOrgUnitChangeRequestConfig.ts
@@ -0,0 +1,65 @@
+import { UseQueryResult } from 'react-query';
+import { getRequest } from '../../../../../libs/Api';
+import { useSnackQuery } from '../../../../../libs/apiHooks';
+
+import { apiUrlOUCRC } from '../../constants';
+import {
+ OrgUnitChangeRequestConfigurationForm,
+ OrgUnitChangeRequestConfigurationFull,
+} from '../../types';
+
+const retrieveOrgUnitChangeRequestConfig = (url: string) => {
+ return getRequest(url) as Promise;
+};
+
+const fieldMapping: { [key: string]: string } = {
+ opening_date: 'openingDate',
+ closing_date: 'closedDate',
+ org_unit_type: 'possibleTypeIds',
+ parent_type: 'possibleParentTypeIds',
+ editable_reference_forms: 'editableReferenceFormIds',
+ other_groups: 'otherGroupIds',
+};
+
+export const computeEditableFields = (
+ data: OrgUnitChangeRequestConfigurationFull,
+): string[] => {
+ return (data.editable_fields || []).map(field => {
+ return fieldMapping[field] || field;
+ });
+};
+
+const mapAndJoin = (items: any[] = []) => items?.map(item => item.id).join(',');
+
+export const useRetrieveOrgUnitChangeRequestConfig = (
+ configId?: number,
+): UseQueryResult => {
+ const url = `${apiUrlOUCRC}${configId}/`;
+ return useSnackQuery({
+ queryKey: ['useRetrieveOrgUnitChangeRequestConfig', configId],
+ queryFn: () => retrieveOrgUnitChangeRequestConfig(url),
+ options: {
+ enabled: Boolean(configId),
+ staleTime: 1000 * 60 * 15, // in MS
+ cacheTime: 1000 * 60 * 5,
+ keepPreviousData: true,
+ select: (data: OrgUnitChangeRequestConfigurationFull) => {
+ return {
+ projectId: data.project.id,
+ orgUnitTypeId: data.org_unit_type.id,
+ orgUnitsEditable: data.org_units_editable,
+ editableFields: computeEditableFields(data).join(','),
+ possibleTypeIds: mapAndJoin(data.possible_types),
+ possibleParentTypeIds: mapAndJoin(
+ data.possible_parent_types,
+ ),
+ groupSetIds: mapAndJoin(data.group_sets),
+ editableReferenceFormIds: mapAndJoin(
+ data.editable_reference_forms,
+ ),
+ otherGroupIds: mapAndJoin(data.other_groups),
+ };
+ },
+ },
+ });
+};
diff --git a/hat/assets/js/apps/Iaso/domains/orgUnits/configuration/hooks/api/useSaveOrgUnitChangeRequestConfiguration.ts b/hat/assets/js/apps/Iaso/domains/orgUnits/configuration/hooks/api/useSaveOrgUnitChangeRequestConfiguration.ts
new file mode 100644
index 0000000000..8e786a8eb6
--- /dev/null
+++ b/hat/assets/js/apps/Iaso/domains/orgUnits/configuration/hooks/api/useSaveOrgUnitChangeRequestConfiguration.ts
@@ -0,0 +1,99 @@
+import { UseMutationResult } from 'react-query';
+import { patchRequest, postRequest } from '../../../../../libs/Api';
+import { useSnackMutation } from '../../../../../libs/apiHooks';
+
+import { apiUrlOUCRC, mappingEditableFieldsForBackend } from '../../constants';
+import { OrgUnitChangeRequestConfigurationForm } from '../../types';
+
+const cleanEditableFieldsForSaving = (editableFields?: string): string[] => {
+ if (!editableFields) {
+ return [];
+ }
+ return editableFields.split(',').map(field => {
+ return mappingEditableFieldsForBackend[field];
+ });
+};
+
+// All the many to many fields are added if they have a value
+const splitAndMapToNumbers = (str?: string) => {
+ return str?.trim() ? str.split(',').map(Number) : [];
+};
+
+type ApiValues = {
+ org_units_editable: boolean;
+ project_id?: number;
+ org_unit_type_id?: number;
+ editable_fields?: string[];
+ possible_type_ids?: number[];
+ possible_parent_type_ids?: number[];
+ group_set_ids?: number[];
+ editable_reference_form_ids?: number[];
+ other_group_ids?: number[];
+};
+
+const mapValuesForSaving = (
+ configId: number | undefined,
+ values: OrgUnitChangeRequestConfigurationForm,
+): ApiValues => {
+ const apiValues: ApiValues = {
+ org_units_editable: values.orgUnitsEditable ?? false,
+ };
+ // These two fields can't be updated so they are only set for creation
+ if (!configId) {
+ apiValues.project_id = values.projectId;
+ apiValues.org_unit_type_id = values.orgUnitTypeId;
+ }
+
+ // This field must be cleaned because the backend accepts only some values
+ apiValues.editable_fields = cleanEditableFieldsForSaving(
+ values.editableFields,
+ );
+
+ apiValues.possible_type_ids = splitAndMapToNumbers(values.possibleTypeIds);
+ apiValues.possible_parent_type_ids = splitAndMapToNumbers(
+ values.possibleParentTypeIds,
+ );
+ apiValues.group_set_ids = splitAndMapToNumbers(values.groupSetIds);
+ apiValues.editable_reference_form_ids = splitAndMapToNumbers(
+ values.editableReferenceFormIds,
+ );
+ apiValues.other_group_ids = splitAndMapToNumbers(values.otherGroupIds);
+ return apiValues;
+};
+
+const patchOUCRC = async (configId: number, body: ApiValues): Promise => {
+ const url = `${apiUrlOUCRC}${configId}/`;
+ return patchRequest(url, body);
+};
+
+const postOUCRC = async (body: ApiValues): Promise => {
+ return postRequest({
+ url: `${apiUrlOUCRC}`,
+ data: body,
+ });
+};
+
+export const useSaveOrgUnitChangeRequestConfiguration =
+ (): UseMutationResult => {
+ const ignoreErrorCodes = [400];
+ return useSnackMutation({
+ mutationFn: ({
+ configId,
+ data,
+ }: {
+ configId: number | undefined;
+ data: OrgUnitChangeRequestConfigurationForm;
+ }) => {
+ const formattedData = mapValuesForSaving(configId, data);
+ return configId
+ ? patchOUCRC(configId, formattedData)
+ : postOUCRC(formattedData);
+ },
+ ignoreErrorCodes,
+ invalidateQueryKey: [
+ 'useRetrieveOrgUnitChangeRequestConfig',
+ 'getOrgUnitChangeRequestConfigs',
+ 'checkAvailabilityOrgUnitChangeRequestConfigs',
+ ],
+ });
+ };
diff --git a/hat/assets/js/apps/Iaso/domains/orgUnits/configuration/hooks/useOrgUnitEditableFieldsOptions.ts b/hat/assets/js/apps/Iaso/domains/orgUnits/configuration/hooks/useOrgUnitEditableFieldsOptions.ts
new file mode 100644
index 0000000000..9c55b5f8b4
--- /dev/null
+++ b/hat/assets/js/apps/Iaso/domains/orgUnits/configuration/hooks/useOrgUnitEditableFieldsOptions.ts
@@ -0,0 +1,15 @@
+import { useSafeIntl } from 'bluesquare-components';
+import { editableFields } from '../constants';
+import MESSAGES from '../messages';
+import { DropdownOptions } from '../../../../types/utils';
+
+export const useOrgUnitsEditableFieldsOptions =
+ (): DropdownOptions[] => {
+ const { formatMessage } = useSafeIntl();
+ return editableFields.map(field => {
+ return {
+ value: field,
+ label: formatMessage(MESSAGES[field]),
+ };
+ });
+ };
diff --git a/hat/assets/js/apps/Iaso/domains/orgUnits/configuration/hooks/useOrgUnitsEditableOptions.ts b/hat/assets/js/apps/Iaso/domains/orgUnits/configuration/hooks/useOrgUnitsEditableOptions.ts
new file mode 100644
index 0000000000..73ba060397
--- /dev/null
+++ b/hat/assets/js/apps/Iaso/domains/orgUnits/configuration/hooks/useOrgUnitsEditableOptions.ts
@@ -0,0 +1,17 @@
+import { useSafeIntl } from 'bluesquare-components';
+import { DropdownOptions } from '../../../../types/utils';
+import MESSAGES from '../messages';
+
+export const useOrgUnitsEditableOptions = (): DropdownOptions[] => {
+ const { formatMessage } = useSafeIntl();
+ return [
+ {
+ label: formatMessage(MESSAGES.orgUnitsEditableYes),
+ value: true,
+ },
+ {
+ label: formatMessage(MESSAGES.orgUnitsEditableNo),
+ value: false,
+ },
+ ];
+};
diff --git a/hat/assets/js/apps/Iaso/domains/orgUnits/configuration/hooks/useValidationSchemaOUCRC.ts b/hat/assets/js/apps/Iaso/domains/orgUnits/configuration/hooks/useValidationSchemaOUCRC.ts
new file mode 100644
index 0000000000..c8fc7b4309
--- /dev/null
+++ b/hat/assets/js/apps/Iaso/domains/orgUnits/configuration/hooks/useValidationSchemaOUCRC.ts
@@ -0,0 +1,73 @@
+import { useSafeIntl } from 'bluesquare-components';
+import * as yup from 'yup';
+import MESSAGES from '../messages';
+
+yup.addMethod(
+ yup.string,
+ 'isMultiSelectValid',
+ function isMultiSelectValid(formatMessage) {
+ return this.test('isMultiSelectValid', '', (value, context) => {
+ const { path, createError, parent } = context;
+ if (!parent.editableFields && !parent.groupSetIds) {
+ return createError({
+ path,
+ message: formatMessage(MESSAGES.requiredField),
+ });
+ }
+ const splitFields = parent.editableFields || [];
+ const isFieldPopulated = parent[path];
+ if (!isFieldPopulated && splitFields.includes(path)) {
+ return createError({
+ path,
+ message: formatMessage(MESSAGES.requiredField),
+ });
+ }
+ return true;
+ });
+ },
+);
+
+export const useValidationSchemaOUCRC = () => {
+ const { formatMessage } = useSafeIntl();
+ return yup.object().shape({
+ projectId: yup
+ .string()
+ .nullable()
+ .required(formatMessage(MESSAGES.requiredField)),
+ orgUnitTypeId: yup
+ .string()
+ .nullable()
+ .required(formatMessage(MESSAGES.requiredField)),
+ orgUnitsEditable: yup
+ .boolean()
+ .nullable()
+ .required(formatMessage(MESSAGES.requiredField)),
+ editableFields: yup.string().nullable(),
+ possibleTypeIds: yup
+ .string()
+ .nullable()
+ .when('orgUnitsEditable', {
+ is: true,
+ then: yup.string().nullable().isMultiSelectValid(formatMessage),
+ otherwise: yup.string().nullable(),
+ }),
+ possibleParentTypeIds: yup
+ .string()
+ .nullable()
+ .when('orgUnitsEditable', {
+ is: true,
+ then: yup.string().nullable().isMultiSelectValid(formatMessage),
+ otherwise: yup.string().nullable(),
+ }),
+ groupSetIds: yup
+ .string()
+ .nullable()
+ .when('orgUnitsEditable', {
+ is: true,
+ then: yup.string().nullable().isMultiSelectValid(formatMessage),
+ otherwise: yup.string().nullable(),
+ }),
+ editableReferenceFormIds: yup.string().nullable(),
+ otherGroupIds: yup.string().nullable(),
+ });
+};
diff --git a/hat/assets/js/apps/Iaso/domains/orgUnits/configuration/messages.ts b/hat/assets/js/apps/Iaso/domains/orgUnits/configuration/messages.ts
index 54d4417198..25531bf043 100644
--- a/hat/assets/js/apps/Iaso/domains/orgUnits/configuration/messages.ts
+++ b/hat/assets/js/apps/Iaso/domains/orgUnits/configuration/messages.ts
@@ -61,6 +61,95 @@ const MESSAGES = defineMessages({
id: 'iaso.label.updated_by',
defaultMessage: 'Updated by',
},
+ close: {
+ id: 'iaso.label.close',
+ defaultMessage: 'Close',
+ },
+ next: {
+ id: 'iaso.label.next',
+ defaultMessage: 'Next',
+ },
+ oucrcCreateModalTitle: {
+ id: 'iaso.oucrc.oucrcCreateModalTitle',
+ defaultMessage: 'OrgUnit Change Request Configuration - Creation',
+ },
+ oucrcCreateSecondStepModalTitle: {
+ id: 'iaso.oucrc.oucrcCreateModalTitle2',
+ defaultMessage:
+ 'OrgUnit Change Request Configuration - Creation 2nd step',
+ },
+ oucrcCreateUpdateModalTitle: {
+ id: 'iaso.oucrc.oucrcCreateUpdateModalTitle',
+ defaultMessage: 'OrgUnit Change Request Configuration - Update',
+ },
+ requiredField: {
+ id: 'iaso.forms.error.fieldRequired',
+ defaultMessage: 'This field is required',
+ },
+ orgUnitsEditable: {
+ id: 'iaso.oucrc.orgUnitsEditable',
+ defaultMessage: 'Should OrgUnits of this type be editable?',
+ },
+ orgUnitsEditableYes: {
+ id: 'iaso.forms.yes',
+ defaultMessage: 'Yes',
+ },
+ orgUnitsEditableNo: {
+ id: 'iaso.forms.no',
+ defaultMessage: 'No',
+ },
+ name: {
+ id: 'iaso.label.name',
+ defaultMessage: 'Name',
+ },
+ aliases: {
+ id: 'iaso.forms.aliases',
+ defaultMessage: 'Aliases',
+ },
+ openingDate: {
+ id: 'iaso.changeRequest.openingDate',
+ defaultMessage: 'Opening Date',
+ },
+ closedDate: {
+ id: 'iaso.oucrc.closedDate',
+ defaultMessage: 'Closing Date',
+ },
+ location: {
+ id: 'iaso.label.location',
+ defaultMessage: 'Location',
+ },
+ editableFields: {
+ id: 'iaso.label.editableFields',
+ defaultMessage: 'Editable Fields',
+ },
+ possibleTypeIds: {
+ id: 'iaso.oucrc.possibleTypeIds',
+ defaultMessage: 'Possible New Types',
+ },
+ possibleParentTypeIds: {
+ id: 'iaso.oucrc.possibleParentTypeIds',
+ defaultMessage: 'Possible New Parent Types',
+ },
+ groupSetIds: {
+ id: 'iaso.oucrc.groupSetIds',
+ defaultMessage: 'Group Sets',
+ },
+ editableReferenceFormIds: {
+ id: 'iaso.oucrc.editableReferenceFormIds',
+ defaultMessage: 'Editable Reference Forms',
+ },
+ otherGroupIds: {
+ id: 'iaso.oucrc.otherGroupIds',
+ defaultMessage: 'Other Groups',
+ },
+ oucrcModalCreateButton: {
+ id: 'iaso.label.create',
+ defaultMessage: 'Create',
+ },
+ oucrcModalUpdateButton: {
+ id: 'iaso.mappings.label.update',
+ defaultMessage: 'Update',
+ },
});
export default MESSAGES;
diff --git a/hat/assets/js/apps/Iaso/domains/orgUnits/configuration/types.ts b/hat/assets/js/apps/Iaso/domains/orgUnits/configuration/types.ts
index 257efe5710..0b8e5a697b 100644
--- a/hat/assets/js/apps/Iaso/domains/orgUnits/configuration/types.ts
+++ b/hat/assets/js/apps/Iaso/domains/orgUnits/configuration/types.ts
@@ -15,9 +15,25 @@ export type OrgUnitType = {
id: number;
name: string;
};
+
+export type GroupSet = {
+ id: number;
+ name: string;
+};
+
+export type Form = {
+ id: number;
+ name: string;
+};
+
+export type Group = {
+ id: number;
+ name: string;
+};
+
export type NestedUser = Partial;
-export type OrgUnitChangeRequestConfig = {
+export type OrgUnitChangeRequestConfigListElement = {
id: number;
project: Project;
org_unit_type: OrgUnitType;
@@ -29,6 +45,41 @@ export type OrgUnitChangeRequestConfig = {
updated_at: number;
};
-export interface OrgUnitChangeRequestConfigsPaginated extends Pagination {
- results: OrgUnitChangeRequestConfig[];
+export type OrgUnitChangeRequestConfigurationFull = {
+ id: number;
+ project: Project;
+ org_unit_type: OrgUnitType;
+ org_units_editable?: boolean;
+ editable_fields?: string[];
+ possible_types?: Array;
+ possible_parent_types?: Array;
+ group_sets?: Array;
+ editable_reference_forms?: Array