diff --git a/packages/api/src/api/rest/activites.queries.ts b/packages/api/src/api/rest/activites.queries.ts index d03e594cf8426ff5874589e1c6d53e0992d1e48c..91488220231a52ded8797baf51f5b1f730f85855 100644 --- a/packages/api/src/api/rest/activites.queries.ts +++ b/packages/api/src/api/rest/activites.queries.ts @@ -12,6 +12,7 @@ import { IUpdateActiviteDbQuery, IActiviteDeleteDbQuery, IGetActivitesSuperDbQuery, + IResetActiviteStatusDbQuery, } from './activites.queries.types' import { ActiviteDocument, @@ -95,7 +96,33 @@ export const updateActiviteQuery = ( const updateActiviteDb = sql< Redefine<IUpdateActiviteDbQuery, { userId: string; dateSaisie: CaminoDate; activiteId: ActiviteId; activiteStatutId: ActivitesStatutId; contenu: Contenu }, void> >`update titres_activites set utilisateur_id = $userId!, date_saisie = $dateSaisie!, activite_statut_id = $activiteStatutId!, contenu = $contenu! where id = $activiteId;` +export type ResetActiviteStatusQueryErrors = UpdateActiviteQueryErrors +export const resetActiviteStatusQuery = ( + pool: Pool, + user: User, + activiteId: ActiviteId, + titreTypeId: SimplePromiseFn<TitreTypeId>, + titresAdministrationsLocales: SimplePromiseFn<AdministrationId[]>, + entreprisesTitulairesOuAmodiataires: SimplePromiseFn<EntrepriseId[]> +): Effect.Effect<void, CaminoError<ResetActiviteStatusQueryErrors>> => + Effect.Do.pipe( + Effect.bind('canEditActivite', () => + Effect.tryPromise({ + try: () => canEditActivite(user, titreTypeId, titresAdministrationsLocales, entreprisesTitulairesOuAmodiataires, ACTIVITES_STATUTS_IDS.DEPOSE), + catch: error => ({ message: miseAJourActiviteInterdite, detail: 'Appel à canEditActivite échoué', extra: error }), + }) + ), + Effect.filterOrFail( + ({ canEditActivite }) => canEditActivite, + () => ({ message: miseAJourActiviteInterdite, detail: "Utilisateur n'a pas le droit de modifier cette activité", extra: { activiteId } }) + ), + Effect.tap(() => effectDbQueryAndValidate(resetActiviteStatusDb, { activiteId, activiteStatutId: ACTIVITES_STATUTS_IDS.EN_CONSTRUCTION }, pool, z.void())), + Effect.flatMap(() => Effect.void) + ) +const resetActiviteStatusDb = sql< + Redefine<IResetActiviteStatusDbQuery, { activiteId: ActiviteId; activiteStatutId: ActivitesStatutId }, void> +>`update titres_activites set activite_statut_id = $activiteStatutId! where id = $activiteId;` export const contenuValidator = z.record(z.string(), z.record(z.string(), z.unknown().optional()).optional()).nullable() export type Contenu = z.infer<typeof contenuValidator> diff --git a/packages/api/src/api/rest/activites.queries.types.ts b/packages/api/src/api/rest/activites.queries.types.ts index 5e6a94c7da58d77456bc9db9c80717b3a454b192..299cdbef201bd0b89a9cd7d9de19013a253cf8f5 100644 --- a/packages/api/src/api/rest/activites.queries.types.ts +++ b/packages/api/src/api/rest/activites.queries.types.ts @@ -21,6 +21,21 @@ export interface IUpdateActiviteDbQuery { result: IUpdateActiviteDbResult; } +/** 'ResetActiviteStatusDb' parameters type */ +export interface IResetActiviteStatusDbParams { + activiteId?: string | null | void; + activiteStatutId: string; +} + +/** 'ResetActiviteStatusDb' return type */ +export type IResetActiviteStatusDbResult = void; + +/** 'ResetActiviteStatusDb' query type */ +export interface IResetActiviteStatusDbQuery { + params: IResetActiviteStatusDbParams; + result: IResetActiviteStatusDbResult; +} + /** 'GetActiviteByIdQuery' parameters type */ export interface IGetActiviteByIdQueryParams { activiteId: string; diff --git a/packages/api/src/api/rest/activites.test.integration.ts b/packages/api/src/api/rest/activites.test.integration.ts index 94ec45f38ec0b2ab1bdb2c43f5d2258d4adf153b..74d3405835639d5b7a4e8fd0e0965789a20aedd4 100644 --- a/packages/api/src/api/rest/activites.test.integration.ts +++ b/packages/api/src/api/rest/activites.test.integration.ts @@ -22,6 +22,9 @@ import { DOCUMENTS_TYPES_IDS } from 'camino-common/src/static/documentsTypes' import { copyFileSync, mkdirSync } from 'node:fs' import { tempDocumentNameValidator } from 'camino-common/src/document' import { SectionWithValue } from 'camino-common/src/sections' +import { newEntrepriseId } from 'camino-common/src/entreprise' +import { testBlankUser } from 'camino-common/src/tests-utils' +import { entrepriseUpsert } from '../../database/queries/entreprises' const dir = `${process.cwd()}/files/tmp/` @@ -148,4 +151,94 @@ describe('updateActivite', () => { expect(newDocumentIds).toContain(activite1DocumentId) expect(activite.activite_documents).toHaveLength(2) }) + + test('réinitialise une activité', async () => { + const titreId = newTitreId('titre-id-reset-activite') + const entrepriseId = newEntrepriseId('entrepriseid-reset-activite') + await entrepriseUpsert({ + id: entrepriseId, + nom: 'Mon Entreprise', + archive: false, + }) + const titre: ITitreInsert = { + id: titreId, + nom: 'mon titre', + typeId: TITRES_TYPES_IDS.AUTORISATION_DE_RECHERCHE_METAUX, + titreStatutId: TitresStatutIds.Valide, + publicLecture: true, + propsTitreEtapesIds: { points: 'titre-id-demarche-id-dpu-reset-activite', titulaires: 'titre-id-demarche-id-dpu-reset-activite' }, + demarches: [ + { + id: newDemarcheId('titre-id-demarche-id-reset-activite'), + titreId: titreId, + typeId: DEMARCHES_TYPES_IDS.Octroi, + statutId: DemarchesStatutsIds.Accepte, + publicLecture: true, + machineId: null, + etapes: [ + { + id: newEtapeId('titre-id-demarche-id-dpu-reset-activite'), + typeId: ETAPES_TYPES.publicationDeDecisionAuJORF, + ordre: 0, + titreDemarcheId: newDemarcheId('titre-id-demarche-id-reset-activite'), + statutId: ETAPES_STATUTS.ACCEPTE, + date: toCaminoDate('2020-02-02'), + titulaireIds: [entrepriseId], + administrationsLocales: ['dea-guyane-01'], + isBrouillon: ETAPE_IS_NOT_BROUILLON, + }, + ], + }, + ], + } + + await insertTitreGraph(titre) + + const activiteId = activiteIdValidator.parse('activite1Id-reset') + await knex.raw( + `INSERT INTO titres_activites ( id, titre_id, utilisateur_id, "date", date_saisie, contenu, type_id, activite_statut_id, annee, periode_id, sections, suppression, slug) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?,?,?,?,?)`, + [ + activiteId, + titreId, + null, + toCaminoDate('2021-01-01'), + null, + null, + ACTIVITES_TYPES_IDS["rapport trimestriel d'exploitation d'or en Guyane"], + ACTIVITES_STATUTS_IDS.DEPOSE, + 2023, + 1, + [JSON.stringify({ id: 'id', elements: [{ id: 'element', type: 'number', optionnel: true }] })], + false, + 'slug', + ] + ) + + let tested = await restNewPutCall(dbPool, '/rest/activites/:activiteId/reset-depot', { activiteId: activiteId }, undefined, {}) + + expect(tested.body).toMatchInlineSnapshot(` + { + "message": "Accès interdit", + "status": 403, + } + `) + + tested = await restNewPutCall(dbPool, '/rest/activites/:activiteId/reset-depot', { activiteId: activiteId }, { ...testBlankUser, role: 'entreprise', entrepriseIds: [entrepriseId] }, {}) + + expect(tested.body).toMatchInlineSnapshot(` + { + "message": "Droit insuffisants pour éditer l'activité", + "status": 403, + } + `) + tested = await restNewPutCall(dbPool, '/rest/activites/:activiteId/reset-depot', { activiteId: activiteId }, userSuper, {}) + expect(tested.body).toMatchInlineSnapshot(` + { + "id": "activite1Id-reset", + } +`) + tested = await restCall(dbPool, '/rest/activites/:activiteId', { activiteId }, userSuper) + const activite: Activite = tested.body + expect(activite.activite_statut_id).toStrictEqual(ACTIVITES_STATUTS_IDS.EN_CONSTRUCTION) + }) }) diff --git a/packages/api/src/api/rest/activites.ts b/packages/api/src/api/rest/activites.ts index b84b5b6137c8efd80a4141083a9a9f7acb6536ef..078442a38612b726cd2827321622c22e1444957d 100644 --- a/packages/api/src/api/rest/activites.ts +++ b/packages/api/src/api/rest/activites.ts @@ -19,6 +19,8 @@ import { UpdateActiviteQueryErrors, DeleteActiviteDocumentErrors, getActivitesSuper, + resetActiviteStatusQuery, + ResetActiviteStatusQueryErrors, } from './activites.queries' import { NewDownload } from './fichiers' import { SimplePromiseFn, isNonEmptyArray, memoize } from 'camino-common/src/typescript-tools' @@ -65,6 +67,60 @@ const extractContenuFromSectionWithValue = (sections: Section[], sectionsWithVal return contenu } +const activiteNonDeposeeError = 'Seule une activité déposée peut être réinitialisée' as const +type ResetActiviteDepotErrors = + | GetActiviteByIdErrors + | typeof canEditActiviteError + | typeof editionDeLActiviteImpossible + | typeof activiteNonDeposeeError + | ResetActiviteStatusQueryErrors + | EffectDbQueryAndValidateErrors +export const resetActiviteDepot: RestNewPutCall<'/rest/activites/:activiteId/reset-depot'> = (rootPipe): Effect.Effect<{ id: ActiviteId }, CaminoApiError<ResetActiviteDepotErrors>> => + rootPipe.pipe( + Effect.let('titreTypeId', ({ params, pool }) => memoize(() => callAndExit(titreTypeIdByActiviteId(params.activiteId, pool)))), + Effect.let('administrationsLocales', ({ params, pool }) => memoize(() => administrationsLocalesByActiviteId(params.activiteId, pool))), + Effect.let('entreprisesTitulairesOuAmodiataires', ({ params, pool }) => memoize(() => entreprisesTitulairesOuAmoditairesByActiviteId(params.activiteId, pool))), + Effect.bind('result', ({ params, pool, titreTypeId, administrationsLocales, entreprisesTitulairesOuAmodiataires, user }) => + getActiviteById(params.activiteId, pool, user, titreTypeId, administrationsLocales, entreprisesTitulairesOuAmodiataires) + ), + Effect.tap(({ user, titreTypeId, administrationsLocales, entreprisesTitulairesOuAmodiataires, result }) => + Effect.tryPromise({ + try: () => canEditActivite(user, titreTypeId, administrationsLocales, entreprisesTitulairesOuAmodiataires, result.activite_statut_id), + catch: e => ({ message: canEditActiviteError, extra: e }), + }).pipe( + Effect.filterOrFail( + canRead => canRead, + () => ({ message: editionDeLActiviteImpossible }) + ) + ) + ), + Effect.filterOrFail( + ({ result }) => result.activite_statut_id === ACTIVITES_STATUTS_IDS.DEPOSE, + () => ({ message: activiteNonDeposeeError }) + ), + Effect.tap(({ pool, user, result, titreTypeId, administrationsLocales, entreprisesTitulairesOuAmodiataires }) => + resetActiviteStatusQuery(pool, user, result.id, titreTypeId, administrationsLocales, entreprisesTitulairesOuAmodiataires) + ), + Effect.map(({ result }) => ({ id: result.id })), + Effect.mapError(caminoError => + Match.value(caminoError.message).pipe( + Match.when("Pas d'activité trouvée", () => ({ ...caminoError, status: HTTP_STATUS.NOT_FOUND })), + Match.when('Seule une activité déposée peut être réinitialisée', () => ({ ...caminoError, status: HTTP_STATUS.BAD_REQUEST })), + Match.whenOr("Droit insuffisants pour éditer l'activité", "Interdiction d'éditer une activité", () => ({ + ...caminoError, + status: HTTP_STATUS.FORBIDDEN, + })), + Match.whenOr( + "Impossible d'exécuter la requête dans la base de données", + "Impossible de vérifier si on peut éditer l'activité", + "Lecture de l'activité impossible", + 'Les données en base ne correspondent pas à ce qui est attendu', + () => ({ ...caminoError, status: HTTP_STATUS.INTERNAL_SERVER_ERROR }) + ), + Match.exhaustive + ) + ) + ) const canEditActiviteError = "Impossible de vérifier si on peut éditer l'activité" as const const editionDeLActiviteImpossible = "Droit insuffisants pour éditer l'activité" as const diff --git a/packages/api/src/server/rest.ts b/packages/api/src/server/rest.ts index 2844cba4b3ebe0e3ff483ace18d3bfffa950710b..a6cea66f49bbb650c48b42f881a4d4cddb856e77 100644 --- a/packages/api/src/server/rest.ts +++ b/packages/api/src/server/rest.ts @@ -44,7 +44,7 @@ import { createEtape, deleteEtape, deposeEtape, getEtape, getEtapeAvis, getEtape import { ZodType, z } from 'zod' import { getCommunes } from '../api/rest/communes' import { SendFileOptions } from 'express-serve-static-core' -import { activiteDocumentDownload, getActivite, updateActivite, deleteActivite, getActivitesForTDBSuper } from '../api/rest/activites' +import { activiteDocumentDownload, getActivite, updateActivite, deleteActivite, getActivitesForTDBSuper, resetActiviteDepot } from '../api/rest/activites' import { isNotNullNorUndefined, isNullOrUndefined } from 'camino-common/src/typescript-tools' import { getDemarcheByIdOrSlugApi, demarcheSupprimer, demarcheCreer, getDemarchesEnConcurrence, getResultatEnConcurrence } from '../api/rest/demarches' import { geojsonImport, geojsonImportPoints, geojsonImportForages, getPerimetreInfosByDemarche, getPerimetreInfosByEtape } from '../api/rest/perimetre' @@ -238,6 +238,7 @@ const restRouteImplementations: Readonly<{ [key in CaminoRestRoute]: Transform<k '/rest/etapes/:etapeId/etapeDocuments': { newGetCall: getEtapeDocuments, ...CaminoRestRoutes['/rest/etapes/:etapeId/etapeDocuments'] }, '/rest/etapes/:etapeId/etapeAvis': { newGetCall: getEtapeAvis, ...CaminoRestRoutes['/rest/etapes/:etapeId/etapeAvis'] }, '/rest/activites/:activiteId': { getCall: getActivite, newPutCall: updateActivite, deleteCall: deleteActivite, ...CaminoRestRoutes['/rest/activites/:activiteId'] }, + '/rest/activites/:activiteId/reset-depot': { newPutCall: resetActiviteDepot, ...CaminoRestRoutes['/rest/activites/:activiteId/reset-depot'] }, '/rest/activitesSuper': { newGetCall: getActivitesForTDBSuper, ...CaminoRestRoutes['/rest/activitesSuper'] }, '/rest/communes': { newGetCall: getCommunes, ...CaminoRestRoutes['/rest/communes'] }, '/rest/mutations': { newGetCall: getRestMutations, ...CaminoRestRoutes['/rest/mutations'] }, diff --git a/packages/api/tests/_utils/index.ts b/packages/api/tests/_utils/index.ts index 2fd0eb99613049a51924ee93e0402c1b99884eb4..77f10ce41b2f6e5a3a0723bab0fc606bea4d9cad 100644 --- a/packages/api/tests/_utils/index.ts +++ b/packages/api/tests/_utils/index.ts @@ -25,14 +25,15 @@ import { import { z } from 'zod' import { newUtilisateurId } from '../../src/database/models/_format/id-create' import { idUserKeycloakRecognised } from '../keycloak' -import { isNotNullNorUndefined, isNullOrUndefined } from 'camino-common/src/typescript-tools' +import { isNotNullNorUndefined } from 'camino-common/src/typescript-tools' import { config } from '../../src/config/index' -import { createUtilisateur, getUtilisateurById } from '../../src/database/queries/utilisateurs.queries' +import { createUtilisateur, newGetUtilisateurById } from '../../src/database/queries/utilisateurs.queries' import { MachineInfo } from 'camino-common/src/machines' import { DemarcheId } from 'camino-common/src/demarche' import { DemarcheTypeId } from 'camino-common/src/static/demarchesTypes' import { TitreTypeId } from 'camino-common/src/static/titresTypes' import { CaminoMachineId } from 'camino-common/src/validators/machine' +import { callAndExit } from '../../src/tools/fp-tools' export const queryImport = (nom: string): string => fs @@ -154,12 +155,15 @@ export const userGenerate = async (pool: Pool, user: TestUser): Promise<UserNotN if (isAdministrationRole(user.role)) { idToBuild += `-${(user as AdminUserNotNull).administrationId}` } + if ('entrepriseIds' in user) { + idToBuild += `-${user.entrepriseIds.join('-')}` + } } const id = newUtilisateurId(idToBuild) - - const userInDb = await getUtilisateurById(pool, id, userSuper) - if (isNullOrUndefined(userInDb)) { + try { + return await callAndExit(newGetUtilisateurById(pool, id, userSuper)) + } catch (_) { const newUser = await createUtilisateur(pool, { ...user, id, @@ -174,8 +178,6 @@ export const userGenerate = async (pool: Pool, user: TestUser): Promise<UserNotN return newUser } - - return userInDb } const userTokenGenerate = async (pool: Pool, user: TestUser) => { const userInDb = await userGenerate(pool, user) diff --git a/packages/common/src/rest.ts b/packages/common/src/rest.ts index 732b5eb9b4864c0e8235a8a38dafc9a71cda7791..5f4288253ab5234e5bcf3f77decc7c8a7137791d 100644 --- a/packages/common/src/rest.ts +++ b/packages/common/src/rest.ts @@ -125,6 +125,7 @@ const IDS = [ '/rest/etapes/:etapeId/depot', '/rest/etapes', '/rest/activites/:activiteId', + '/rest/activites/:activiteId/reset-depot', '/rest/activitesSuper', '/rest/geojson/import/:geoSystemeId', '/rest/geojson_points/import/:geoSystemeId', @@ -251,6 +252,10 @@ export const CaminoRestRoutes = { newPut: { input: activiteEditionValidator, output: z.object({ id: activiteIdValidator }) }, delete: true, }, + '/rest/activites/:activiteId/reset-depot': { + params: z.object({ activiteId: activiteIdOrSlugValidator }), + newPut: { input: z.object({}), output: z.object({ id: activiteIdValidator }) }, + }, '/rest/activitesSuper': { newGet: { output: z.array(activiteSuperValidator) }, params: noParamsValidator, diff --git a/packages/ui/src/components/activite.stories.tsx b/packages/ui/src/components/activite.stories.tsx index fd7cab091cb2aed801c91b0b2f16723a402a588c..f626486a614bbe0e5f31868877f44708dc2f811a 100644 --- a/packages/ui/src/components/activite.stories.tsx +++ b/packages/ui/src/components/activite.stories.tsx @@ -35,15 +35,21 @@ const activite: Activite = { }, } const deposerActiviteAction = action('deposerActiviteAction') +const resetActiviteAction = action('resetActiviteAction') const supprimerActiviteAction = action('supprimerActiviteAction') const getActiviteAction = action('getActiviteAction') -const apiClient: Pick<ActiviteApiClient, 'deposerActivite' | 'supprimerActivite' | 'getActivite'> = { +const apiClient: Pick<ActiviteApiClient, 'deposerActivite' | 'supprimerActivite' | 'getActivite' | 'resetActiviteStatus'> = { deposerActivite: (...params: unknown[]) => { deposerActiviteAction(params) return Promise.resolve() }, + resetActiviteStatus: (...params) => { + resetActiviteAction(params) + + return Promise.resolve({ id: params[0] }) + }, supprimerActivite(activiteId: ActiviteId) { supprimerActiviteAction(activiteId) @@ -102,6 +108,36 @@ export const Deposable: StoryFn = () => ( /> ) +export const Deposee: StoryFn = () => ( + <PureActivite + apiClient={{ + ...apiClient, + getActivite(activiteId) { + getActiviteAction(activiteId) + + return Promise.resolve({ ...activite, deposable: true, modification: true, activite_statut_id: ACTIVITES_STATUTS_IDS.DEPOSE }) + }, + }} + activiteId={activite.id} + user={{ ...testBlankUser, role: 'super' }} + /> +) + +export const DeposeeCompteExploitant: StoryFn = () => ( + <PureActivite + apiClient={{ + ...apiClient, + getActivite(activiteId) { + getActiviteAction(activiteId) + + return Promise.resolve({ ...activite, deposable: false, modification: false, activite_statut_id: ACTIVITES_STATUTS_IDS.DEPOSE }) + }, + }} + activiteId={activite.id} + user={{ ...testBlankUser, role: 'entreprise', entrepriseIds: [] }} + /> +) + export const Supprimable: StoryFn = () => ( <PureActivite apiClient={{ diff --git a/packages/ui/src/components/activite.stories_snapshots_ACompleter.html b/packages/ui/src/components/activite.stories_snapshots_ACompleter.html index 2e11f38baf6ac3f57f5f2fb1f6e8984ecaec3f68..f56c913fc1838cacd10bc09531fbbddffedbee85 100644 --- a/packages/ui/src/components/activite.stories_snapshots_ACompleter.html +++ b/packages/ui/src/components/activite.stories_snapshots_ACompleter.html @@ -12,6 +12,7 @@ <div class="fr-grid-row fr-grid-row--top fr-mt-4w"> <h1 class="fr-m-0">Rapport d'exploitation (permis et concessions W) - Année 2022</h1> <div class="fr-m-0 noprint" style="margin-left: auto !important; display: flex; gap: 1rem;"> + <!----> <!----><a href="/mocked-href" title="modifier l'activité" class="fr-btn fr-btn--primary fr-icon-edit-line" aria-label="modifier l'activité">modifier l'activité</a><button class="fr-btn fr-btn--primary fr-btn--md" disabled="" title="déposer l'activité" aria-label="déposer l'activité" type="button">Déposer</button> </div> </div> @@ -62,4 +63,5 @@ </div> <!----> <!----> + <!----> </div> \ No newline at end of file diff --git a/packages/ui/src/components/activite.stories_snapshots_Deposable.html b/packages/ui/src/components/activite.stories_snapshots_Deposable.html index c0216090816b7404465ccc63c79b6f54cdd63426..883878e2ee4bfe265d3e193348ce0c3077a7b539 100644 --- a/packages/ui/src/components/activite.stories_snapshots_Deposable.html +++ b/packages/ui/src/components/activite.stories_snapshots_Deposable.html @@ -12,6 +12,7 @@ <div class="fr-grid-row fr-grid-row--top fr-mt-4w"> <h1 class="fr-m-0">Rapport d'exploitation (permis et concessions M) - Année 2022</h1> <div class="fr-m-0 noprint" style="margin-left: auto !important; display: flex; gap: 1rem;"> + <!----> <!----><a href="/mocked-href" title="modifier l'activité" class="fr-btn fr-btn--secondary fr-icon-edit-line" aria-label="modifier l'activité">modifier l'activité</a><button class="fr-btn fr-btn--primary fr-btn--md" title="déposer l'activité" aria-label="déposer l'activité" type="button">Déposer</button> </div> </div> @@ -62,4 +63,5 @@ </div> <!----> <!----> + <!----> </div> \ No newline at end of file diff --git a/packages/ui/src/components/activite.stories_snapshots_Deposee.html b/packages/ui/src/components/activite.stories_snapshots_Deposee.html new file mode 100644 index 0000000000000000000000000000000000000000..f5b64721f8890c14518a9c43f520b7f561b53a2f --- /dev/null +++ b/packages/ui/src/components/activite.stories_snapshots_Deposee.html @@ -0,0 +1,67 @@ +<div> + <nav role="navigation" class="fr-breadcrumb" aria-label="vous êtes ici :"><button class="fr-breadcrumb__button" aria-expanded="false" aria-controls="breadcrumb-1">Voir le fil d’Ariane</button> + <div class="fr-collapse" id="breadcrumb-1"> + <ol class="fr-breadcrumb__list"> + <li><a href="/mocked-href" title="Accueil" class="fr-breadcrumb__link" aria-label="Accueil">Accueil</a> </li> + <li><a href="/mocked-href" title="Activités" class="fr-breadcrumb__link" aria-label="Activités">Activités</a> </li> + <li><a href="/mocked-href" title="Nom du titre" class="fr-breadcrumb__link" aria-label="Nom du titre">Nom du titre</a> </li> + <li><a class="fr-breadcrumb__link" aria-current="page">Rapport d'exploitation (permis et concessions M) - Année 2022</a></li> + </ol> + </div> + </nav> + <div class="fr-grid-row fr-grid-row--top fr-mt-4w"> + <h1 class="fr-m-0">Rapport d'exploitation (permis et concessions M) - Année 2022</h1> + <div class="fr-m-0 noprint" style="margin-left: auto !important; display: flex; gap: 1rem;"> + <!----><button class="fr-btn fr-btn--primary fr-btn--md" title="réinitialiser l'activité" aria-label="réinitialiser l'activité" type="button">Réinitialiser</button><a href="/mocked-href" title="modifier l'activité" class="fr-btn fr-btn--secondary fr-icon-edit-line" aria-label="modifier l'activité">modifier l'activité</a> + <!----> + </div> + </div> + <div> + <h2>Nom du titre</h2> + <p style="z-index: unset; margin-bottom: 0px; white-space: nowrap; text-overflow: ellipsis; overflow: hidden;" class="fr-badge fr-badge--md fr-badge--green-bourgeon" title="déposé" aria-label="déposé">déposé</p> + <div class="fr-pt-1w"><span class="fr-icon-calendar-line fr-icon--sm fr-mr-1w" style="color: var(--text-title-blue-france);" aria-hidden="true"></span>Modifié le 01-01-2022</div> + <div class="fr-pt-1w"> + <div> + <p>La production annuelle est requise en vertu des <a href="https://www.legifrance.gouv.fr/codes/section_lc/LEGITEXT000006069577/LEGISCTA000006179968" target="_blank" title="Page de l'article - site externe">article 1519</a>, <a href="https://www.legifrance.gouv.fr/codes/id/LEGIARTI000043663002" target="_blank" title="Page de l'article - site externe">article 1587</a> et <a href="https://www.legifrance.gouv.fr/codes/section_lc/LEGITEXT000006069577/LEGISCTA000006162672?init=true&page=1&query=1588&searchField=ALL&tab_selection=all&anchor=LEGIARTI000006306371#LEGIARTI000006306371" target="_blank" title="Page de l'article - site externe">article 1588</a> du code général des impôts relatifs au calcul de la redevance départementale et communale des mines (RDCM).</p> + <p>Le rapport annuel d'exploitation est requis en vertu de l'<a href="https://www.legifrance.gouv.fr/codes/id/LEGIARTI000023505020/2021-04-14/" target="_blank" title="Page de l'article - site externe">article L. 172-1</a> du code minier et <a href="https://www.legifrance.gouv.fr/loda/article_lc/LEGIARTI000033196097" target="_blank" title="Page de l'article - site externe">article 35</a> du décret 2006/649 du 2 juin 2006.</p> + </div> + <div> + <h3 class="fr-m-0 fr-pt-4w">Nom de section</h3> + <div class="fr-pt-2w"> + <div class="fr-h6 fr-m-0">Un radio button</div> + <div><span>Oui<!----></span> + <!----> + </div> + </div> + </div> + <div> + <div class="fr-table fr-table--no-scroll" style="overflow: auto;"> + <div class="fr-table__wrapper" style="width: auto;"> + <div class="fr-table__container"> + <div class="fr-table__content"> + <table style="display: table; width: 100%;"> + <caption>Documents de l'activité</caption> + <thead> + <tr> + <th scope="col">Nom</th> + <th scope="col">Description</th> + </tr> + </thead> + <tbody> + <tr> + <td><a href="/apiUrl/download/activiteDocuments/id1" title="Télécharger le document Rapport environnemental d'exploration - nouvelle fenêtre" target="_blank">Rapport environnemental d'exploration</a></td> + <td><span class="">description</span></td> + </tr> + </tbody> + </table> + </div> + </div> + </div> + </div> + </div> + </div> + </div> + <!----> + <!----> + <!----> +</div> \ No newline at end of file diff --git a/packages/ui/src/components/activite.stories_snapshots_DeposeeCompteExploitant.html b/packages/ui/src/components/activite.stories_snapshots_DeposeeCompteExploitant.html new file mode 100644 index 0000000000000000000000000000000000000000..2c4a8f9b1e61c4e88d1fc47ad4d28600f30b7f1b --- /dev/null +++ b/packages/ui/src/components/activite.stories_snapshots_DeposeeCompteExploitant.html @@ -0,0 +1,67 @@ +<div> + <nav role="navigation" class="fr-breadcrumb" aria-label="vous êtes ici :"><button class="fr-breadcrumb__button" aria-expanded="false" aria-controls="breadcrumb-1">Voir le fil d’Ariane</button> + <div class="fr-collapse" id="breadcrumb-1"> + <ol class="fr-breadcrumb__list"> + <li><a href="/mocked-href" title="Accueil" class="fr-breadcrumb__link" aria-label="Accueil">Accueil</a> </li> + <li><a href="/mocked-href" title="Activités" class="fr-breadcrumb__link" aria-label="Activités">Activités</a> </li> + <li><a href="/mocked-href" title="Nom du titre" class="fr-breadcrumb__link" aria-label="Nom du titre">Nom du titre</a> </li> + <li><a class="fr-breadcrumb__link" aria-current="page">Rapport d'exploitation (permis et concessions M) - Année 2022</a></li> + </ol> + </div> + </nav> + <div class="fr-grid-row fr-grid-row--top fr-mt-4w"> + <h1 class="fr-m-0">Rapport d'exploitation (permis et concessions M) - Année 2022</h1> + <div class="fr-m-0 noprint" style="margin-left: auto !important; display: flex; gap: 1rem;"> + <!----> + <!----> + </div> + </div> + <div> + <h2>Nom du titre</h2> + <p style="z-index: unset; margin-bottom: 0px; white-space: nowrap; text-overflow: ellipsis; overflow: hidden;" class="fr-badge fr-badge--md fr-badge--green-bourgeon" title="déposé" aria-label="déposé">déposé</p> + <div class="fr-pt-1w"><span class="fr-icon-calendar-line fr-icon--sm fr-mr-1w" style="color: var(--text-title-blue-france);" aria-hidden="true"></span>Modifié le 01-01-2022</div> + <div class="fr-pt-1w"> + <div> + <p>La production annuelle est requise en vertu des <a href="https://www.legifrance.gouv.fr/codes/section_lc/LEGITEXT000006069577/LEGISCTA000006179968" target="_blank" title="Page de l'article - site externe">article 1519</a>, <a href="https://www.legifrance.gouv.fr/codes/id/LEGIARTI000043663002" target="_blank" title="Page de l'article - site externe">article 1587</a> et <a href="https://www.legifrance.gouv.fr/codes/section_lc/LEGITEXT000006069577/LEGISCTA000006162672?init=true&page=1&query=1588&searchField=ALL&tab_selection=all&anchor=LEGIARTI000006306371#LEGIARTI000006306371" target="_blank" title="Page de l'article - site externe">article 1588</a> du code général des impôts relatifs au calcul de la redevance départementale et communale des mines (RDCM).</p> + <p>Le rapport annuel d'exploitation est requis en vertu de l'<a href="https://www.legifrance.gouv.fr/codes/id/LEGIARTI000023505020/2021-04-14/" target="_blank" title="Page de l'article - site externe">article L. 172-1</a> du code minier et <a href="https://www.legifrance.gouv.fr/loda/article_lc/LEGIARTI000033196097" target="_blank" title="Page de l'article - site externe">article 35</a> du décret 2006/649 du 2 juin 2006.</p> + </div> + <div> + <h3 class="fr-m-0 fr-pt-4w">Nom de section</h3> + <div class="fr-pt-2w"> + <div class="fr-h6 fr-m-0">Un radio button</div> + <div><span>Oui<!----></span> + <!----> + </div> + </div> + </div> + <div> + <div class="fr-table fr-table--no-scroll" style="overflow: auto;"> + <div class="fr-table__wrapper" style="width: auto;"> + <div class="fr-table__container"> + <div class="fr-table__content"> + <table style="display: table; width: 100%;"> + <caption>Documents de l'activité</caption> + <thead> + <tr> + <th scope="col">Nom</th> + <th scope="col">Description</th> + </tr> + </thead> + <tbody> + <tr> + <td><a href="/apiUrl/download/activiteDocuments/id1" title="Télécharger le document Rapport environnemental d'exploration - nouvelle fenêtre" target="_blank">Rapport environnemental d'exploration</a></td> + <td><span class="">description</span></td> + </tr> + </tbody> + </table> + </div> + </div> + </div> + </div> + </div> + </div> + </div> + <!----> + <!----> + <!----> +</div> \ No newline at end of file diff --git a/packages/ui/src/components/activite.stories_snapshots_Supprimable.html b/packages/ui/src/components/activite.stories_snapshots_Supprimable.html index c464a1f84e99a4cac1510a77249fa407673c131c..514eb8b2d5ddd9899c62fd8d545199e4c60c061a 100644 --- a/packages/ui/src/components/activite.stories_snapshots_Supprimable.html +++ b/packages/ui/src/components/activite.stories_snapshots_Supprimable.html @@ -13,7 +13,9 @@ <h1 class="fr-m-0">Rapport d'exploitation (permis et concessions M) - Année 2022</h1> <div class="fr-m-0 noprint" style="margin-left: auto !important; display: flex; gap: 1rem;"><button class="fr-btn fr-btn--tertiary fr-btn--md fr-icon-delete-bin-line" title="supprimer l'activité" aria-label="supprimer l'activité" type="button"> <!----> - </button><a href="/mocked-href" title="modifier l'activité" class="fr-btn fr-btn--primary fr-icon-edit-line" aria-label="modifier l'activité">modifier l'activité</a><button class="fr-btn fr-btn--primary fr-btn--md" disabled="" title="déposer l'activité" aria-label="déposer l'activité" type="button">Déposer</button></div> + </button> + <!----><a href="/mocked-href" title="modifier l'activité" class="fr-btn fr-btn--primary fr-icon-edit-line" aria-label="modifier l'activité">modifier l'activité</a><button class="fr-btn fr-btn--primary fr-btn--md" disabled="" title="déposer l'activité" aria-label="déposer l'activité" type="button">Déposer</button> + </div> </div> <div> <h2>Nom du titre</h2> @@ -62,4 +64,5 @@ </div> <!----> <!----> + <!----> </div> \ No newline at end of file diff --git a/packages/ui/src/components/activite.tsx b/packages/ui/src/components/activite.tsx index 165b71596b5548d64b1141bbc68e525cc312c376..98f27e9a4c33f22eb8fd0251102c336a2d9f1ec3 100644 --- a/packages/ui/src/components/activite.tsx +++ b/packages/ui/src/components/activite.tsx @@ -40,16 +40,24 @@ export const Activite = defineComponent(() => { interface Props { user: User activiteId: ActiviteIdOrSlug | null - apiClient: Pick<ActiviteApiClient, 'getActivite' | 'deposerActivite' | 'supprimerActivite'> + apiClient: Pick<ActiviteApiClient, 'getActivite' | 'deposerActivite' | 'supprimerActivite' | 'resetActiviteStatus'> } export const PureActivite = defineComponent<Props>(props => { const activiteData = ref<AsyncData<CommonActivite>>({ status: 'LOADING' }) - const apiClient = { + const apiClient: Pick<ActiviteApiClient, 'getActivite' | 'deposerActivite' | 'supprimerActivite' | 'resetActiviteStatus'> = { ...props.apiClient, deposerActivite: async (activiteId: ActiviteId) => { await props.apiClient.deposerActivite(activiteId) await retrieveActivite(activiteId) }, + resetActiviteStatus: async activiteId => { + const value = await props.apiClient.resetActiviteStatus(activiteId) + if ('message' in value) { + return value + } + await retrieveActivite(activiteId) + return value + }, } const retrieveActivite = async (activiteId: ActiviteIdOrSlug | null) => { diff --git a/packages/ui/src/components/activite/activite-api-client.ts b/packages/ui/src/components/activite/activite-api-client.ts index 32f8daa1ca7092efea8c9174c973c0b6aaa47727..2e2e79dfc982f146e06b1026a5ba66a77a8f36cb 100644 --- a/packages/ui/src/components/activite/activite-api-client.ts +++ b/packages/ui/src/components/activite/activite-api-client.ts @@ -28,6 +28,7 @@ export interface ActiviteApiClient { getActivite: (activiteIdOrSlug: ActiviteIdOrSlug) => Promise<Activite> deposerActivite: (activiteId: ActiviteId) => Promise<void> supprimerActivite: (activiteId: ActiviteId) => Promise<void> + resetActiviteStatus: (activiteId: ActiviteId) => Promise<{ id: ActiviteId } | CaminoError<string>> updateActivite: ( activiteId: ActiviteId, activiteTypeId: ActivitesTypesId, @@ -119,6 +120,7 @@ export const activiteApiClient: ActiviteApiClient = { activiteId, }) }, + resetActiviteStatus: activiteId => newPutWithJson('/rest/activites/:activiteId/reset-depot', { activiteId }, {}), updateActivite: async ( activiteId: ActiviteId, _activiteTypeId: ActivitesTypesId, diff --git a/packages/ui/src/components/activite/preview.stories.tsx b/packages/ui/src/components/activite/preview.stories.tsx index c4d0d5754b071350fc597a8f3dafbedfc7ce8b50..abbf5629ecb5e30d2f5eab9d37c22838745defe2 100644 --- a/packages/ui/src/components/activite/preview.stories.tsx +++ b/packages/ui/src/components/activite/preview.stories.tsx @@ -168,14 +168,20 @@ const activite: Activite = { }, } const deposerActiviteAction = action('deposerActiviteAction') +const resetActiviteAction = action('resetActiviteAction') const supprimerActiviteAction = action('supprimerActiviteAction') -const apiClient: Pick<ActiviteApiClient, 'deposerActivite' | 'supprimerActivite'> = { +const apiClient: Pick<ActiviteApiClient, 'deposerActivite' | 'supprimerActivite' | 'resetActiviteStatus'> = { deposerActivite: (...params: unknown[]) => { deposerActiviteAction(params) return Promise.resolve() }, + resetActiviteStatus: (...params) => { + resetActiviteAction(params) + + return Promise.resolve({ id: params[0] }) + }, supprimerActivite(activiteId) { supprimerActiviteAction(activiteId) diff --git a/packages/ui/src/components/activite/preview.stories_snapshots_ACompleter.html b/packages/ui/src/components/activite/preview.stories_snapshots_ACompleter.html index 8f7f355be8dd27b8efcc2313e9d154dddb92b1ce..7649e8f0ce8a3eae00011f3bb3e841f5ac4e23a6 100644 --- a/packages/ui/src/components/activite/preview.stories_snapshots_ACompleter.html +++ b/packages/ui/src/components/activite/preview.stories_snapshots_ACompleter.html @@ -12,6 +12,7 @@ <div class="fr-grid-row fr-grid-row--top fr-mt-4w"> <h1 class="fr-m-0">Rapport d'exploitation (permis et concessions W) - Année 2022</h1> <div class="fr-m-0 noprint" style="margin-left: auto !important; display: flex; gap: 1rem;"> + <!----> <!----><a href="/mocked-href" title="modifier l'activité" class="fr-btn fr-btn--primary fr-icon-edit-line" aria-label="modifier l'activité">modifier l'activité</a><button class="fr-btn fr-btn--primary fr-btn--md" disabled="" title="déposer l'activité" aria-label="déposer l'activité" type="button">Déposer</button> </div> </div> @@ -92,4 +93,5 @@ </div> <!----> <!----> + <!----> </div> \ No newline at end of file diff --git a/packages/ui/src/components/activite/preview.stories_snapshots_Defaut.html b/packages/ui/src/components/activite/preview.stories_snapshots_Defaut.html index dbf050b50fbff31a6c600c088a0841448d26e826..23fc58c2373fe503d70b732cc044abdfad99d8d7 100644 --- a/packages/ui/src/components/activite/preview.stories_snapshots_Defaut.html +++ b/packages/ui/src/components/activite/preview.stories_snapshots_Defaut.html @@ -93,4 +93,5 @@ </div> <!----> <!----> + <!----> </div> \ No newline at end of file diff --git a/packages/ui/src/components/activite/preview.stories_snapshots_Deposable.html b/packages/ui/src/components/activite/preview.stories_snapshots_Deposable.html index 90f179946540f1fa3dc017e3d1a7347e82ba9700..a84553a3c7d38ffccb479526e2b9f4fd24b1051d 100644 --- a/packages/ui/src/components/activite/preview.stories_snapshots_Deposable.html +++ b/packages/ui/src/components/activite/preview.stories_snapshots_Deposable.html @@ -12,6 +12,7 @@ <div class="fr-grid-row fr-grid-row--top fr-mt-4w"> <h1 class="fr-m-0">Rapport d'exploitation (permis et concessions M) - Année 2022</h1> <div class="fr-m-0 noprint" style="margin-left: auto !important; display: flex; gap: 1rem;"> + <!----> <!----><a href="/mocked-href" title="modifier l'activité" class="fr-btn fr-btn--secondary fr-icon-edit-line" aria-label="modifier l'activité">modifier l'activité</a><button class="fr-btn fr-btn--primary fr-btn--md" title="déposer l'activité" aria-label="déposer l'activité" type="button">Déposer</button> </div> </div> @@ -92,4 +93,5 @@ </div> <!----> <!----> + <!----> </div> \ No newline at end of file diff --git a/packages/ui/src/components/activite/preview.stories_snapshots_Supprimable.html b/packages/ui/src/components/activite/preview.stories_snapshots_Supprimable.html index 5c8ef9ff2d57c2280f13e76e592aa2a7e1152674..33913690621f66de1e1080befb2743b5b6bf0294 100644 --- a/packages/ui/src/components/activite/preview.stories_snapshots_Supprimable.html +++ b/packages/ui/src/components/activite/preview.stories_snapshots_Supprimable.html @@ -13,7 +13,9 @@ <h1 class="fr-m-0">Rapport d'exploitation (permis et concessions M) - Année 2022</h1> <div class="fr-m-0 noprint" style="margin-left: auto !important; display: flex; gap: 1rem;"><button class="fr-btn fr-btn--tertiary fr-btn--md fr-icon-delete-bin-line" title="supprimer l'activité" aria-label="supprimer l'activité" type="button"> <!----> - </button><a href="/mocked-href" title="modifier l'activité" class="fr-btn fr-btn--primary fr-icon-edit-line" aria-label="modifier l'activité">modifier l'activité</a><button class="fr-btn fr-btn--primary fr-btn--md" disabled="" title="déposer l'activité" aria-label="déposer l'activité" type="button">Déposer</button></div> + </button> + <!----><a href="/mocked-href" title="modifier l'activité" class="fr-btn fr-btn--primary fr-icon-edit-line" aria-label="modifier l'activité">modifier l'activité</a><button class="fr-btn fr-btn--primary fr-btn--md" disabled="" title="déposer l'activité" aria-label="déposer l'activité" type="button">Déposer</button> + </div> </div> <div> <h2>Nom du titre</h2> @@ -92,4 +94,5 @@ </div> <!----> <!----> + <!----> </div> \ No newline at end of file diff --git a/packages/ui/src/components/activite/preview.tsx b/packages/ui/src/components/activite/preview.tsx index 98e7cfec5bf0ad0564d0398c52085ef3372144d3..9b823cc088c3f7730ee5acdab0f7e61b49fe27bc 100644 --- a/packages/ui/src/components/activite/preview.tsx +++ b/packages/ui/src/components/activite/preview.tsx @@ -16,10 +16,11 @@ import { capitalize } from 'camino-common/src/strings' import { ActiviteStatut } from '../_common/activite-statut' import { ModifiedDate } from '../_common/modified-date' import { TableRow } from '../_ui/table' +import { ActiviteResetPopup } from './reset-popup' interface Props { activite: Activite - apiClient: Pick<ActiviteApiClient, 'deposerActivite' | 'supprimerActivite'> + apiClient: Pick<ActiviteApiClient, 'deposerActivite' | 'supprimerActivite' | 'resetActiviteStatus'> } const documentColumns = [ @@ -34,14 +35,21 @@ export const Preview = defineComponent<Props>(props => { deposePopupVisible.value = true } const closeDeposePopup = () => { - deposePopupVisible.value = !deposePopupVisible.value + deposePopupVisible.value = false + } + const resetPopupVisible = ref(false) + const resetPopupOpen = () => { + resetPopupVisible.value = true + } + const closeResetPopup = () => { + resetPopupVisible.value = false } const removePopupVisible = ref(false) const removePopupOpen = () => { removePopupVisible.value = true } const closeRemovePopup = () => { - removePopupVisible.value = !removePopupVisible.value + removePopupVisible.value = false } const activiteType = computed<ActiviteType>(() => ActivitesTypes[props.activite.type_id]) @@ -92,6 +100,9 @@ export const Preview = defineComponent<Props>(props => { {props.activite.suppression ? <DsfrButtonIcon buttonType="tertiary" title="supprimer l'activité" onClick={removePopupOpen} icon="fr-icon-delete-bin-line" /> : null} {props.activite.modification ? ( <> + {props.activite.activite_statut_id === ACTIVITES_STATUTS_IDS.DEPOSE ? ( + <DsfrButton buttonType="primary" title="réinitialiser l'activité" label="Réinitialiser" onClick={resetPopupOpen} /> + ) : null} <DsfrLink buttonType={props.activite.deposable ? 'secondary' : 'primary'} label={null} @@ -122,6 +133,7 @@ export const Preview = defineComponent<Props>(props => { </div> </div> {deposePopupVisible.value ? <ActiviteDeposePopup close={closeDeposePopup} activite={props.activite} apiClient={props.apiClient} /> : null} + {resetPopupVisible.value ? <ActiviteResetPopup close={closeResetPopup} activite={props.activite} apiClient={props.apiClient} /> : null} {removePopupVisible.value ? <ActiviteRemovePopup close={closeRemovePopup} activite={props.activite} apiClient={props.apiClient} /> : null} </div> ) diff --git a/packages/ui/src/components/activite/reset-popup.stories.tsx b/packages/ui/src/components/activite/reset-popup.stories.tsx new file mode 100644 index 0000000000000000000000000000000000000000..a3b8c6ff66f3f883d200ba8524864117bd4ee7b9 --- /dev/null +++ b/packages/ui/src/components/activite/reset-popup.stories.tsx @@ -0,0 +1,26 @@ +import { Meta, StoryFn } from '@storybook/vue3' +import { action } from '@storybook/addon-actions' +import { activiteIdValidator } from 'camino-common/src/activite' +import { ActiviteResetPopup } from './reset-popup' +import { ActiviteApiClient } from './activite-api-client' + +const meta: Meta = { + title: 'Components/Activite/ResetPopup', + // @ts-ignore @storybook/vue3 n'aime pas les composants tsx + component: ActiviteResetPopup, +} +export default meta + +const close = action('close') +const resetActiviteAction = action('resetActiviteAction') + +const apiClient: Pick<ActiviteApiClient, 'resetActiviteStatus'> = { + resetActiviteStatus: (...params) => { + resetActiviteAction(params) + + return Promise.resolve({ id: params[0] }) + }, +} +export const Default: StoryFn = () => ( + <ActiviteResetPopup close={close} apiClient={apiClient} activite={{ id: activiteIdValidator.parse('activiteId'), type_id: 'gra', titre: { nom: 'Titre 1', slug: 'slug' } }} /> +) diff --git a/packages/ui/src/components/activite/reset-popup.stories_snapshots_Default.html b/packages/ui/src/components/activite/reset-popup.stories_snapshots_Default.html new file mode 100644 index 0000000000000000000000000000000000000000..53861d97bdcdeefb0f6c5720207d5073fc656712 --- /dev/null +++ b/packages/ui/src/components/activite/reset-popup.stories_snapshots_Default.html @@ -0,0 +1,33 @@ +<!--teleport start--> +<div> + <dialog id="monId" class="fr-modal fr-modal--opened" open="" aria-modal="true" role="dialog" aria-labelledby="monId-title" style="z-index: 1000001;"> + <div class="fr-container fr-container--fluid fr-container-md"> + <div class="fr-grid-row fr-grid-row--center"> + <div class="fr-col-12 fr-col-md-8 fr-col-lg-6"> + <div class="fr-modal__body"> + <div class="fr-modal__header"><button class="fr-btn--close fr-btn" aria-controls="monId" title="Fermer">Fermer</button></div> + <div class="fr-modal__content"> + <h1 id="monId-title" class="fr-modal__title"><span class="fr-icon-arrow-right-line fr-icon--lg" aria-hidden="true"></span>Réinitialisation</h1> + <div class="fr-container"> + <div class="fr-alert fr-alert--warning"> + <p class="fr-alert__title fr-h4">Attention : cette opération est définitive et ne peut pas être annulée.</p>Ce <span class="fr-text--bold"> rapport d'exploitation (permis et concessions M)</span> du titre<span class="fr-text--bold"> Titre 1</span> va passer de <p style="z-index: unset; margin-bottom: 0px; white-space: nowrap; text-overflow: ellipsis; overflow: hidden;" class="fr-badge fr-badge--md fr-badge--green-bourgeon" title="déposé" aria-label="déposé">déposé</p> à <p style="z-index: unset; margin-bottom: 0px; white-space: nowrap; text-overflow: ellipsis; overflow: hidden;" class="fr-badge fr-badge--md fr-badge--orange-terre-battue" title="en construction" aria-label="en construction">en construction</p>.<p>Les données seront conservées.</p> + </div> + <!----> + </div> + </div> + <div class="fr-modal__footer"> + <div style="display: flex; width: 100%; justify-content: end; align-items: center; gap: 1rem;"> + <!----> + <ul class="fr-btns-group fr-btns-group--right fr-btns-group--inline-reverse fr-btns-group--inline-lg fr-btns-group--icon-left" style="width: auto;"> + <li><button class="fr-btn fr-btn--icon-left fr-icon-check-line fr-btn--primary fr-btn--md" title="Réinitialiser" aria-label="Réinitialiser" type="button">Réinitialiser</button></li> + <li><button class="fr-btn fr-btn--icon-left fr-icon-arrow-go-back-fill fr-btn--secondary fr-btn--md" title="Annuler" aria-label="Annuler" aria-controls="monId" type="button">Annuler</button></li> + </ul> + </div> + </div> + </div> + </div> + </div> + </div> + </dialog> +</div> +<!--teleport end--> \ No newline at end of file diff --git a/packages/ui/src/components/activite/reset-popup.tsx b/packages/ui/src/components/activite/reset-popup.tsx new file mode 100644 index 0000000000000000000000000000000000000000..e379d7489234db887ae987836660c4826219dece --- /dev/null +++ b/packages/ui/src/components/activite/reset-popup.tsx @@ -0,0 +1,44 @@ +import { FunctionalPopup } from '../_ui/functional-popup' +import { ActiviteApiClient } from './activite-api-client' +import { Activite } from 'camino-common/src/activite' +import { Alert } from '../_ui/alert' +import { ActivitesTypes } from 'camino-common/src/static/activitesTypes' +import { defineComponent } from 'vue' +import { ActiviteStatut } from '../_common/activite-statut' +import { ACTIVITES_STATUTS_IDS } from 'camino-common/src/static/activitesStatuts' + +interface Props { + close: () => void + apiClient: Pick<ActiviteApiClient, 'resetActiviteStatus'> + activite: Pick<Activite, 'id' | 'titre' | 'type_id'> +} +export const ActiviteResetPopup = defineComponent<Props>(props => { + const content = () => ( + <Alert + type="warning" + title="Attention : cette opération est définitive et ne peut pas être annulée." + description={ + <> + Ce <span class="fr-text--bold"> {ActivitesTypes[props.activite.type_id].nom}</span> du titre + <span class="fr-text--bold"> {props.activite.titre.nom}</span> va passer de <ActiviteStatut activiteStatutId={ACTIVITES_STATUTS_IDS.DEPOSE} /> à{' '} + <ActiviteStatut activiteStatutId={ACTIVITES_STATUTS_IDS.EN_CONSTRUCTION} />.<p>Les données seront conservées.</p> + </> + } + /> + ) + + return () => ( + <FunctionalPopup + title="Réinitialisation" + content={content} + close={props.close} + validate={{ + action: () => props.apiClient.resetActiviteStatus(props.activite.id), + text: 'Réinitialiser', + }} + canValidate={true} + /> + ) +}) +// @ts-ignore waiting for https://github.com/vuejs/core/issues/7833 +ActiviteResetPopup.props = ['close', 'apiClient', 'activite'] diff --git a/packages/ui/src/components/mutations.tsx b/packages/ui/src/components/mutations.tsx index 11d5b61f089b7957ed0914d50fcf8f131de8e702..dad77f0638f973e6c1ee1380e10a54821faa38f3 100644 --- a/packages/ui/src/components/mutations.tsx +++ b/packages/ui/src/components/mutations.tsx @@ -53,6 +53,19 @@ const PathToExplanation: FunctionalComponent<{ mutation: Mutation }> = props => </CaminoRouterLink> </> ) + case '/rest/activites/:activiteId/reset-depot': + return ( + <> + Réinitialisation{' '} + <CaminoRouterLink + title={`Aller vers l'activité ${props.mutation.camino_variables.activiteId}`} + isDisabled={false} + to={{ name: 'activite', params: { activiteId: props.mutation.camino_variables.activiteId } }} + > + d'une activité + </CaminoRouterLink> + </> + ) case '/rest/demarches': return <>{baseText} d'une démarche</> case '/rest/etapes':