Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Cnh/front/enable permissions on infra #10988

Draft
wants to merge 8 commits into
base: dev
Choose a base branch
from
6 changes: 5 additions & 1 deletion front/public/locales/en/common/common.json
Original file line number Diff line number Diff line change
Expand Up @@ -20,5 +20,9 @@
},
"begin": "Start",
"end": "End",
"value": "value"
"value": "value",
"authorization": {
"permission": "Permission",
"permissionDenied": "You don't have permission to perform this action"
}
}
1 change: 1 addition & 0 deletions front/public/locales/en/translation.json
Original file line number Diff line number Diff line change
Expand Up @@ -162,6 +162,7 @@
}
},
"infra-locked": "Please note that you will not be able to save any changes.",
"infra-readonly": "Please note that you are in read-only mode on this infra",
"list": {
"error": "An error occurred while loading the data",
"filter-level": "Error level",
Expand Down
6 changes: 5 additions & 1 deletion front/public/locales/fr/common/common.json
Original file line number Diff line number Diff line change
Expand Up @@ -20,5 +20,9 @@
},
"begin": "Début",
"end": "Fin",
"value": "Valeur"
"value": "Valeur",
"authorization": {
"permission": "Permission",
"permissionDenied": "Vous n'avez pas la permission de réaliser cette action"
}
}
1 change: 1 addition & 0 deletions front/public/locales/fr/translation.json
Original file line number Diff line number Diff line change
Expand Up @@ -157,6 +157,7 @@
}
},
"infra-locked": "Attention, vous ne pourrez pas sauvegarder de modification.",
"infra-readonly": "Attention, vous ête en lecture seule sur cette infra",
"list": {
"filter-type": "Type d'anomalie",
"total-all": "{{count}} erreurs et avertissements trouvés",
Expand Down
31 changes: 28 additions & 3 deletions front/src/applications/editor/Editor.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@ import type { switchProps } from 'applications/editor/tools/switchProps';
import type { CommonToolState } from 'applications/editor/tools/types';
import { centerMapOnObject, selectEntities } from 'applications/editor/tools/utils';
import type { ObjectType } from 'common/api/osrdEditoastApi';
import useCheckPrivilege from 'common/authorization/hooks/useCheckPrivilege';
import useProtectedActionByPrivilege from 'common/authorization/hooks/useProtectedActionByPrivilege';
import { useModal } from 'common/BootstrapSNCF/ModalSNCF';
import { LoaderState } from 'common/Loaders';
import MapButtons from 'common/Map/Buttons/MapButtons';
Expand Down Expand Up @@ -119,6 +121,21 @@ const Editor = () => {
});
};

const protectedAction = useCallback(
useProtectedActionByPrivilege({
resourceType: 'infra',
resourceId: infraID,
requiredPrivilege: 'can_write',
}),
[infraID]
);

const userCanEditInfra = useCheckPrivilege({
resourceType: 'infra',
resourceId: infraID,
requiredPrivilege: 'can_write',
});

const context = useMemo<EditorContextType<CommonToolState>>(
() => ({
t,
Expand Down Expand Up @@ -157,6 +174,7 @@ const Editor = () => {
viewport,
mapStyle,
},
protectedAction,
}),
[
context,
Expand Down Expand Up @@ -399,8 +417,15 @@ const Editor = () => {
})}
</div>
<div className="panel-container">
{isLocked && (
<div className="infra-locked bg-yellow">{t('Editor.infra-errors.infra-locked')}</div>
{!userCanEditInfra && (
<div className="infra-editor-warning-banner bg-yellow">
{t('Editor.infra-errors.infra-readonly')}
</div>
)}
{isLocked && userCanEditInfra && (
<div className="infra-editor-warning-banner bg-yellow">
{t('Editor.infra-errors.infra-locked')}
</div>
)}
{toolAndState.tool.leftPanelComponent && (
<div className="panel-box">
Expand Down Expand Up @@ -448,7 +473,7 @@ const Editor = () => {
editorState.issues.total > 0 && (
<div className="error-box">
<InfraErrorMapControl mapRef={mapRef.current} switchTool={switchTool} />
<InfraErrorCorrector />
<InfraErrorCorrector protectedAction={protectedAction} />
</div>
)}
</div>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,11 @@ import { getEditorState } from 'reducers/editor/selectors';

import InfraErrorCorrectorModal from './InfraErrorCorrectorModal';

const InfraErrorCorrector = () => {
const InfraErrorCorrector = ({
protectedAction,
}: {
protectedAction: (action: () => void) => void;
}) => {
const { t } = useTranslation();
const { openModal } = useModal();
const editorState = useSelector(getEditorState);
Expand All @@ -18,9 +22,11 @@ const InfraErrorCorrector = () => {
type="button"
title={t('Editor.nav.infra-error-corrector')}
className="btn btn-sm py-1 px-2 shadow d-flex align-items-center justify-content-center"
onClick={() => {
openModal(<InfraErrorCorrectorModal />);
}}
onClick={() =>
protectedAction(() => {
openModal(<InfraErrorCorrectorModal />);
})
}
disabled={total === 0}
aria-label="Magic Wand"
>
Expand Down
56 changes: 35 additions & 21 deletions front/src/applications/editor/tools/pointEdition/tool-factory.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -79,10 +79,12 @@ function getPointEditionTool<T extends EditorPoint>({
false
);
},
async onClick({ setIsFormSubmited }) {
if (setIsFormSubmited) {
setIsFormSubmited(true);
}
onClick({ setIsFormSubmited, protectedAction }) {
protectedAction?.(() => {
if (setIsFormSubmited) {
setIsFormSubmited(true);
}
});
},
},
{
Expand Down Expand Up @@ -121,23 +123,35 @@ function getPointEditionTool<T extends EditorPoint>({
isDisabled({ state }) {
return state.initialEntity.properties.id === NEW_ENTITY_ID;
},
onClick({ infraID, openModal, closeModal, forceRender, state, setState, dispatch, t }) {
openModal(
<ConfirmModal
title={t(`Editor.tools.${id}-edition.actions.delete-entity`)}
onConfirm={async () => {
await dispatch(
// We have to put state.initialEntity in array because delete initially works with selection which can get multiple elements
save(infraID, { delete: [state.initialEntity] })
);
setState(getInitialState());
closeModal();
forceRender();
}}
>
<p>{t(`Editor.tools.${id}-edition.actions.confirm-delete-entity`).toString()}</p>
</ConfirmModal>
);
onClick({
infraID,
openModal,
closeModal,
forceRender,
state,
setState,
dispatch,
t,
protectedAction,
}) {
protectedAction?.(() => {
openModal(
<ConfirmModal
title={t(`Editor.tools.${id}-edition.actions.delete-entity`)}
onConfirm={async () => {
await dispatch(
// We have to put state.initialEntity in array because delete initially works with selection which can get multiple elements
save(infraID, { delete: [state.initialEntity] })
);
setState(getInitialState());
closeModal();
forceRender();
}}
>
<p>{t(`Editor.tools.${id}-edition.actions.confirm-delete-entity`).toString()}</p>
</ConfirmModal>
);
});
},
},
],
Expand Down
122 changes: 68 additions & 54 deletions front/src/applications/editor/tools/rangeEdition/tool-factory.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -107,39 +107,41 @@ function getRangeEditionTool<T extends EditorRange>({
if (canSave) return !canSave(state);
return false;
},
async onClick({ state, setState, dispatch, infraID }) {
const { initialEntity, entity } = state;
if (!isEqual(entity, initialEntity)) {
const res = await dispatch(
save(
infraID,
!isNew(entity)
onClick({ state, setState, dispatch, infraID, protectedAction }) {
protectedAction?.(async () => {
const { initialEntity, entity } = state;
if (!isEqual(entity, initialEntity)) {
const res = await dispatch(
save(
infraID,
!isNew(entity)
? {
update: [
{
source: initialEntity,
target: entity,
},
],
}
: { create: [entity] }
)
);
const { railjson } = res[0];
const { id: entityId } = railjson;

const savedEntity =
entityId && entityId !== entity.properties.id
? {
update: [
{
source: initialEntity,
target: entity,
},
],
...entity,
properties: { ...entity.properties, id: `${entityId}` },
}
: { create: [entity] }
)
);
const { railjson } = res[0];
const { id: entityId } = railjson;

const savedEntity =
entityId && entityId !== entity.properties.id
? {
...entity,
properties: { ...entity.properties, id: `${entityId}` },
}
: entity;
setState({
entity: cloneDeep(savedEntity),
initialEntity: cloneDeep(savedEntity),
});
}
: entity;
setState({
entity: cloneDeep(savedEntity),
initialEntity: cloneDeep(savedEntity),
});
}
});
},
},
{
Expand Down Expand Up @@ -175,29 +177,41 @@ function getRangeEditionTool<T extends EditorRange>({
isDisabled({ state }) {
return state.initialEntity.properties.id === NEW_ENTITY_ID;
},
onClick({ infraID, openModal, closeModal, forceRender, state, setState, dispatch, t }) {
openModal(
<ConfirmModal
title={t(
`Editor.tools.${objectTypeEdition}-edition.actions.delete-${objectTypeAction}`
)}
onConfirm={async () => {
await dispatch(
// We have to put state.initialEntity in array because delete initially works with selection which can get multiple elements
save(infraID, { delete: [state.initialEntity] })
);
setState(getInitialState());
closeModal();
forceRender();
}}
>
<p>
{t(
`Editor.tools.${objectTypeEdition}-edition.actions.confirm-delete-${objectTypeAction}`
).toString()}
</p>
</ConfirmModal>
);
onClick({
infraID,
openModal,
closeModal,
forceRender,
state,
setState,
dispatch,
t,
protectedAction,
}) {
protectedAction?.(() => {
openModal(
<ConfirmModal
title={t(
`Editor.tools.${objectTypeEdition}-edition.actions.delete-${objectTypeAction}`
)}
onConfirm={async () => {
await dispatch(
// We have to put state.initialEntity in array because delete initially works with selection which can get multiple elements
save(infraID, { delete: [state.initialEntity] })
);
setState(getInitialState());
closeModal();
forceRender();
}}
>
<p>
{t(
`Editor.tools.${objectTypeEdition}-edition.actions.confirm-delete-${objectTypeAction}`
).toString()}
</p>
</ConfirmModal>
);
});
},
},
],
Expand Down
Loading