diff --git a/app/package.json b/app/package.json
index ee6e12a84..27935a874 100755
--- a/app/package.json
+++ b/app/package.json
@@ -41,7 +41,7 @@
"react-d3-tree": "1.10.3",
"react-draft-wysiwyg": "1.13.2",
"react-dropzone": "11.0.1",
- "react-modal": "3.1.8",
+ "react-modal": "3.11.2",
"react-router-hash-link": "1.2.0",
"react-scripts": "3.4.1",
"react-select": "1.1.0",
diff --git a/app/src/js/applications/concepts/home-container.js b/app/src/js/applications/concepts/home-container.js
index b2a401dc8..8f5710d2f 100755
--- a/app/src/js/applications/concepts/home-container.js
+++ b/app/src/js/applications/concepts/home-container.js
@@ -1,4 +1,4 @@
-import React, { Component } from 'react';
+import React, { useEffect } from 'react';
import { connect } from 'react-redux';
import { Loading } from '@inseefr/wilco';
import ConceptsHome from './home';
@@ -6,20 +6,15 @@ import { NOT_LOADED } from 'js/constants';
import loadConceptList from 'js/actions/concepts/list';
import { Auth } from 'bauhaus-utilities';
-class ConceptsHomeContainer extends Component {
- componentWillMount() {
- if (!this.props.concepts) {
- this.props.loadConceptList();
+const ConceptsHomeContainer = ({ concepts, permission, loadConceptList }) => {
+ useEffect(() => {
+ if (!concepts) {
+ loadConceptList();
}
- }
-
- render() {
- const { concepts, permission } = this.props;
-
- if (!concepts) return ;
- return ;
- }
-}
+ }, [concepts, loadConceptList]);
+ if (!concepts) return ;
+ return ;
+};
const mapStateToProps = state => {
const permission = Auth.getPermission(state);
diff --git a/app/src/js/applications/concepts/visualization/home-container.js b/app/src/js/applications/concepts/visualization/home-container.js
index bd350feeb..9b283ce3d 100644
--- a/app/src/js/applications/concepts/visualization/home-container.js
+++ b/app/src/js/applications/concepts/visualization/home-container.js
@@ -72,10 +72,8 @@ class ConceptVisualizationContainer extends Component {
}
}
render() {
- const { validationRequested } = this.state;
- const { deletionRequested } = this.state;
- const { validationStatus } = this.props;
- const { deleteStatus } = this.props;
+ const { validationRequested, deletionRequested } = this.state;
+ const { validationStatus, deleteStatus } = this.props;
if (validationRequested && validationStatus !== OK) {
//if validation is OK: nothing to do. We stay on this page and the concept will
@@ -128,21 +126,19 @@ class ConceptVisualizationContainer extends Component {
}
return (
- <>
-
- >
+
);
}
return ;
diff --git a/app/src/js/applications/concepts/visualization/home.js b/app/src/js/applications/concepts/visualization/home.js
index 54ad97795..fc18e0c62 100644
--- a/app/src/js/applications/concepts/visualization/home.js
+++ b/app/src/js/applications/concepts/visualization/home.js
@@ -1,4 +1,4 @@
-import React, { Component } from 'react';
+import React, { useState, useCallback } from 'react';
import { PropTypes } from 'prop-types';
import { ErrorBloc } from '@inseefr/wilco';
import ConceptVisualizationControls from './controls';
@@ -14,106 +14,88 @@ import { propTypes as permissionOverviewPropTypes } from 'js/utils/auth/permissi
import { getModalMessage } from 'js/utils/concepts/build-validation-message';
import { CheckSecondLang, DateUtils, PageTitleBlock } from 'bauhaus-utilities';
-class ConceptVisualization extends Component {
- constructor(props) {
- super(props);
- this.state = {
- modalValid: false,
- };
- this.handleClickValidation = () => {
- const {
- id,
- general: { valid },
- } = this.props;
- if (valid) this.setState({ modalValid: true });
- else this.props.validateConcept(id);
- };
- this.handleCancelValidation = () => this.setState({ modalValid: false });
+const ConceptVisualization = ({
+ id,
+ permission,
+ links,
+ notes,
+ secondLang,
+ langs,
+ serverSideError,
+ general,
+ validateConcept,
+ deleteConcept,
+}) => {
+ const [modalValid, setModalValid] = useState(false);
- this.handleConfirmValidation = () => {
- this.handleCancelValidation();
- this.props.validateConcept(this.props.id);
- };
+ const handleClickValidation = useCallback(() => {
+ if (general.valid) setModalValid(true);
+ else validateConcept(id);
+ }, [id, general, validateConcept]);
- this.handleClickDeletion = () => this.props.deleteConcept(this.props.id);
- }
+ const handleCancelValidation = useCallback(() => {
+ setModalValid(false);
+ }, []);
+ const handleConfirmValidation = useCallback(() => {
+ this.handleCancelValidation();
+ validateConcept(id);
+ }, [id, validateConcept]);
+ const handleClickDeletion = useCallback(() => {
+ deleteConcept(id);
+ }, [id, deleteConcept]);
- render() {
- const {
- id,
- permission,
- general,
- links,
- notes,
- secondLang,
- langs,
- serverSideError,
- } = this.props;
- const { modalValid } = this.state;
- const {
- conceptVersion,
- creator,
- isValidated,
- prefLabelLg1,
- prefLabelLg2,
- valid,
- } = general;
+ const modalButtons = [
+ {
+ label: D.btnCancel,
+ action: handleCancelValidation,
+ style: 'primary',
+ },
+ {
+ label: D.btnValid,
+ action: handleConfirmValidation,
+ style: 'primary',
+ },
+ ];
- const modalButtons = [
- {
- label: D.btnCancel,
- action: this.handleCancelValidation,
- style: 'primary',
- },
- {
- label: D.btnValid,
- action: this.handleConfirmValidation,
- style: 'primary',
- },
- ];
-
- return (
- <>
-
-
-
-
-
-
+ return (
+ <>
+
-
- >
- );
- }
-}
+
+
+
+
+
+
+
+
+ >
+ );
+};
ConceptVisualization.propTypes = {
id: PropTypes.string, // not available for creation
diff --git a/app/src/js/applications/operations/msd/pages/sims-creation/sims-creation.scss b/app/src/js/applications/operations/msd/pages/sims-creation/sims-creation.scss
index 68802e776..59140747d 100644
--- a/app/src/js/applications/operations/msd/pages/sims-creation/sims-creation.scss
+++ b/app/src/js/applications/operations/msd/pages/sims-creation/sims-creation.scss
@@ -34,3 +34,21 @@
.bauhaus-sims-field__RICH_TEXT_2col {
@include rich-text(1em);
}
+
+.bauhaus-sims-geography-field {
+ display: flex;
+
+ .form-group {
+ flex-grow: 1;
+ div[class$='singleValue'] {
+ overflow: visible;
+ }
+ }
+ .btn-group {
+ margin-left: 1em;
+
+ .btn {
+ min-height: 38px;
+ }
+ }
+}
diff --git a/app/src/js/applications/operations/msd/pages/sims-creation/sims-field.js b/app/src/js/applications/operations/msd/pages/sims-creation/sims-field.js
index b2eaa46cc..3110fc120 100644
--- a/app/src/js/applications/operations/msd/pages/sims-creation/sims-field.js
+++ b/app/src/js/applications/operations/msd/pages/sims-creation/sims-field.js
@@ -6,11 +6,11 @@ import DatePickerRmes from 'js/applications/shared/date-picker-rmes';
import InputRmes from 'js/applications/shared/input-rmes';
import { EditorMarkdownToolbar, ArrayUtils } from 'bauhaus-utilities';
import { Editor } from 'react-draft-wysiwyg';
-
+import SimsGeographyField from './sims-geography-field';
import { Note, getLang, Select } from '@inseefr/wilco';
import './sims-field.scss';
-const { RICH_TEXT, TEXT, DATE, CODE_LIST, ORGANIZATION } = rangeType;
+const { RICH_TEXT, TEXT, DATE, CODE_LIST, ORGANIZATION, GEOGRAPHY } = rangeType;
const SimsCodeListSelect = props => {
let value;
@@ -166,6 +166,8 @@ class Field extends PureComponent {
multi={unbounded}
/>
)}
+
+ {msd.rangeType === GEOGRAPHY && }
)
}
diff --git a/app/src/js/applications/operations/msd/pages/sims-creation/sims-geography-field.js b/app/src/js/applications/operations/msd/pages/sims-creation/sims-geography-field.js
new file mode 100644
index 000000000..fd21c2161
--- /dev/null
+++ b/app/src/js/applications/operations/msd/pages/sims-creation/sims-geography-field.js
@@ -0,0 +1,107 @@
+import React, { useState, useMemo } from 'react';
+import { Select } from '@inseefr/wilco';
+import D from 'js/i18n';
+
+const geographies = [
+ { labelLg1: 'Somme', labelLg2: 'Somme', value: '3' },
+ { labelLg1: 'Aisne', labelLg2: 'Aisne', value: '5' },
+ { labelLg1: 'Haut de France', labelLg2: 'Haut de France', value: '6' },
+ { labelLg1: 'Paris', labelLg2: 'Paris', value: '7' },
+ { labelLg1: 'Bourgogne', labelLg2: 'Bourgogne', value: '8' },
+];
+
+const SimsGeographyLabel = ({ geography }) => (
+ <>
+ {geography.labelLg1} ({geography.labelLg2})
+ >
+);
+const SimsGeographyField = props => {
+ const [value, setValue] = useState(null);
+ const [excludes] = useState([
+ { labelLg1: 'Nord', labelLg2: 'Nord', value: '1' },
+ { labelLg1: 'Pas de Calais', labelLg2: 'Pas de Calais', value: '2' },
+ ]);
+ const [includes] = useState([
+ { labelLg1: 'Ecosse', labelLg2: 'Scotland', value: '9' },
+ ]);
+
+ const options = useMemo(() => {
+ return geographies.map(geography => ({
+ value: geography.value,
+ label: ,
+ }));
+ }, []);
+
+ const excludedItems = excludes.map(geography => (
+
+ <>
+
+
+ >
+
+ ));
+ const includedItems = includes.map(geography => (
+
+ <>
+
+
+ >
+
+ ));
+
+ return (
+ <>
+
+
+
+
+
+
Zones géographiques inclues
+ {includedItems}
+
+
+
Zones géographiques exclues
+ {excludedItems}
+
+
+ >
+ );
+};
+
+export default SimsGeographyField;
diff --git a/app/src/js/constants/app.js b/app/src/js/constants/app.js
index 7a38f4bd9..715198a6e 100644
--- a/app/src/js/constants/app.js
+++ b/app/src/js/constants/app.js
@@ -13,6 +13,7 @@ export const FAILURE = 'FAILURE';
export const PENDING = 'PENDING';
export const OK = 'OK';
+export const KO = 'KO';
export const VERSIONING = 'VERSIONING';
export const NO_VERSIONING = 'NO_VERSIONING';
diff --git a/app/src/js/reducers/index.js b/app/src/js/reducers/index.js
index 6ee5fc519..5266ca8ea 100755
--- a/app/src/js/reducers/index.js
+++ b/app/src/js/reducers/index.js
@@ -14,8 +14,9 @@ import classificationsReducers from './classifications';
import operationsReducers from './operations';
import codesListReducers from './operations/codesList';
import organisationsReducers from './operations/organisations';
+import { Stores } from 'bauhaus-utilities';
-import remoteCalls, * as remoteCallsSelectors from './remote-calls';
+import remoteCalls from './remote-calls';
export default combineReducers({
app,
@@ -97,13 +98,13 @@ export const getLangs = state => {
};
export const getStatus = (state, op) =>
- remoteCallsSelectors.getStatus(state.remoteCalls, op);
+ Stores.RemoteCalls.getStatus(state.remoteCalls, op);
export const getError = (state, op) =>
- remoteCallsSelectors.getError(state.remoteCalls, op);
+ Stores.RemoteCalls.getError(state.remoteCalls, op);
export const getNewlyCreatedId = state =>
- remoteCallsSelectors.getNewlyCreatedId(state.remoteCalls);
+ Stores.RemoteCalls.getNewlyCreatedId(state.remoteCalls);
export const getFamily = state => {
return state.operationsFamiliesCurrent || {};
diff --git a/app/src/js/reducers/remote-calls.js b/app/src/js/reducers/remote-calls.js
index bba59d0cd..7aef77a18 100644
--- a/app/src/js/reducers/remote-calls.js
+++ b/app/src/js/reducers/remote-calls.js
@@ -1,15 +1,33 @@
-import { PENDING, OK } from 'js/constants';
+import { PENDING, OK, KO } from 'js/constants';
import * as A from 'js/actions/constants';
+const trackResetReducer = (state = {}, actions) => {
+ const newState = Object.keys(state).reduce((acc, value) => {
+ if (actions.includes(value)) {
+ return acc;
+ }
+ return {
+ ...acc,
+ [value]: state[value],
+ };
+ }, {});
+
+ return newState;
+};
+
export const trackActionReducer = actions => (state = {}, action) => {
const startActions = [];
const successActions = [];
const failActions = [];
- actions.forEach(([start, sucess, fail]) => {
+ const resetActions = [];
+
+ actions.forEach(([start, sucess, fail, reset = []]) => {
startActions.push(start);
successActions.push(sucess);
failActions.push(fail);
+ resetActions.push(...reset);
});
+
if (startActions.indexOf(action.type) !== -1) {
return {
...state,
@@ -34,14 +52,29 @@ export const trackActionReducer = actions => (state = {}, action) => {
return {
...state,
[startActions[failIndex]]: {
- status: 'KO',
+ status: KO,
...action.payload,
},
};
}
}
+
+ if (resetActions.includes(action.type)) {
+ const stateToDelete = actions
+ .filter(actions => {
+ return actions[3]?.includes(action.type);
+ })
+ .reduce(
+ (acc, actions) => [...acc, actions[0], actions[1], actions[2]],
+ []
+ );
+
+ return trackResetReducer(state, stateToDelete);
+ }
+
return state;
};
+
/**
* Reducer to keep track of POST and PUT calls
*
@@ -52,12 +85,16 @@ export const trackActionReducer = actions => (state = {}, action) => {
* but for creation and updates of concepts, we's better track the status within the
* COLLECTION reducer (-> creating a temporary id for `CREATE_ACTION` action)
*
-
*/
export default trackActionReducer([
[A.CREATE_CONCEPT, A.CREATE_CONCEPT_SUCCESS],
[A.UPDATE_CONCEPT, A.UPDATE_CONCEPT_SUCCESS, A.UPDATE_CONCEPT_FAILURE],
- [A.DELETE_CONCEPT, A.DELETE_CONCEPT_SUCCESS, A.DELETE_CONCEPT_FAILURE],
+ [
+ A.DELETE_CONCEPT,
+ A.DELETE_CONCEPT_SUCCESS,
+ A.DELETE_CONCEPT_FAILURE,
+ [A.LOAD_CONCEPT_GENERAL_SUCCESS, A.LOAD_CONCEPT_LIST_SUCCESS],
+ ],
[A.EXPORT_CONCEPT_LIST, A.EXPORT_CONCEPT_LIST_SUCCESS],
[A.SEND_CONCEPT, A.SEND_CONCEPT_SUCCESS],
[A.VALIDATE_CONCEPT_LIST, A.VALIDATE_CONCEPT_LIST_SUCCESS],
@@ -70,14 +107,3 @@ export default trackActionReducer([
[A.DELETE_ROLE, A.DELETE_ROLE_SUCCESS],
[A.EXPORT_VARBOOK, A.EXPORT_VARBOOK_SUCCESS],
]);
-
-export const getStatus = (state, actionType) => {
- return state[actionType] && state[actionType].status;
-};
-
-export const getError = (state, actionType) => {
- return state[actionType] && state[actionType].err;
-};
-
-export const getNewlyCreatedId = state =>
- state[A.CREATE_CONCEPT] && state[A.CREATE_CONCEPT].id;
diff --git a/app/src/js/utils/msd/index.js b/app/src/js/utils/msd/index.js
index c355bd2a2..76536fb2a 100644
--- a/app/src/js/utils/msd/index.js
+++ b/app/src/js/utils/msd/index.js
@@ -61,4 +61,5 @@ export const rangeType = {
CODE_LIST: 'CODE_LIST',
RICH_TEXT: 'RICH_TEXT',
ORGANIZATION: 'ORGANIZATION',
+ GEOGRAPHY: 'GEOGRAPHY',
};
diff --git a/packages/utilities/src/components/confirmation-delete/index.js b/packages/utilities/src/components/confirmation-delete/index.js
index 1ece1726e..ea07193f6 100644
--- a/packages/utilities/src/components/confirmation-delete/index.js
+++ b/packages/utilities/src/components/confirmation-delete/index.js
@@ -21,7 +21,7 @@ export default ({ className, handleNo, handleYes }) => {
{D.confirmationDelete}
-