Skip to content

Commit 07d18b5

Browse files
bellangerqhissalht
andauthored
Dupliquer un audit (#377)
* create duplicate modal * add alert * update dropdown styles + add icons * plug duplication into api * duplicate everything except example images * try to conditionally show alert * fully duplicate audit including images * add audit duplication history * add doc to duplicateAudit() * show duplication alert based on history state * send email on audit duplication * use original audit name as hint for copy * use correct deep selector synttax * update changelog --------- Co-authored-by: Adrien Boutigny <adrien@slash-tmp.dev>
1 parent bb03539 commit 07d18b5

17 files changed

Lines changed: 624 additions & 81 deletions

File tree

CHANGELOG.md

Lines changed: 23 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -2,26 +2,32 @@
22

33
Tous les changements notables de Ara sont documentés ici avec leur date, leur catégorie (nouvelle fonctionnalité, correction de bug ou autre changement) et leur pull request (PR) associée.
44

5-
# 12/05/2023
5+
## 16/05/2023
6+
7+
### Nouvelles fonctionnalités 🚀
8+
9+
- Ajout d’un bouton pour dupliquer un audit terminé ([#377](https://github.com/DISIC/Ara/pull/377))
10+
11+
## 12/05/2023
612

713
### Correction 🐛
814

915
- Vérifie le poids des images d'exemple avant de les envoyer au serveur ([#394](https://github.com/DISIC/Ara/pull/394))
1016

11-
# 11/05/2023
17+
## 11/05/2023
1218

1319
### Correction 🐛
1420

1521
- Corrige l'application de l'état transverse d'un critère via le switch "Sur toutes les pages" qui était parfois ignoré.
1622

17-
# 10/05/2023
23+
## 10/05/2023
1824

1925
### Correction 🐛
2026

2127
- Corrige une erreur qui survenait lorsqu'un champ de formulaire de type URL contenait un espace ([#386](https://github.com/DISIC/Ara/pull/386))
2228
- Corrige l'ordre des erreurs dans l'onglet "Détail des résultats" du rapport d'audit ([#389](https://github.com/DISIC/Ara/pull/389))
2329

24-
## Autres changements ⚙️
30+
### Autres changements ⚙️
2531

2632
- Les accordéons "Description de la ou des erreurs" et "Recommandation de correction" sont remplacés par un unique accordéon "Description et recommandation" ([#390](https://github.com/DISIC/Ara/pull/390))
2733

@@ -34,78 +40,78 @@ Tous les changements notables de Ara sont documentés ici avec leur date, leur c
3440

3541
## 04/05/2023
3642

37-
## Autres changements ⚙️
43+
### Autres changements ⚙️
3844

3945
- Ajout d’une notification pour signaler qu’un email avec les liens importants a été envoyé lors de la création d’un audit ([#368](https://github.com/DISIC/Ara/pull/368))
4046

4147
## 03/05/2023
4248

43-
## Nouvelles fonctionnalités 🚀
49+
### Nouvelles fonctionnalités 🚀
4450

4551
- Remplacement des filtres de thématique par des ancres lors de la réalisation d’un audit ([#362](https://github.com/DISIC/Ara/pull/362))
4652

4753
## 28/04/2023
4854

49-
## Autres changements ⚙️
55+
### Autres changements ⚙️
5056

5157
- Modifications mineures de la page d’accueil ([#361](https://github.com/DISIC/Ara/pull/361))
5258

5359
## 19/04/2023
5460

55-
## Nouvelles fonctionnalités 🚀
61+
### Nouvelles fonctionnalités 🚀
5662

5763
- Ajout d'une aide à la saisie en Markdown accessible en cliquant sur le bouton "Markdown pris en compte" en dessous des champs texte concernés ([#350](https://github.com/DISIC/Ara/pull/350))
5864

5965
## 05/04/2023
6066

61-
## Nouvelles fonctionnalités 🚀
67+
### Nouvelles fonctionnalités 🚀
6268

6369
- Lors de la création d'un audit, envoie d'un email contenant les liens vers l'audit et le rapport ([#314](https://github.com/DISIC/Ara/pull/314))
6470

65-
## Autres changements ⚙️
71+
### Autres changements ⚙️
6672

6773
- Mise à jour du titre de la page de génération d’audit ([#345](https://github.com/DISIC/Ara/pull/345))
6874
- Ajout du métier "Auditeur / Auditrice accessibilité" dans le formulaire de retour ([#346](https://github.com/DISIC/Ara/pull/346))
6975

7076
## 30/03/2023
7177

72-
## Nouvelles fonctionnalités 🚀
78+
### Nouvelles fonctionnalités 🚀
7379

7480
- Ajout d’un bouton pour afficher ou cacher la barre latérale des filtres ([#322](https://github.com/DISIC/Ara/pull/322))
7581

7682
## 24/03/2023
7783

78-
## Nouvelles fonctionnalités 🚀
84+
### Nouvelles fonctionnalités 🚀
7985

8086
- Ajout d’un filtre pour cacher les tests et références des critères ([#329](https://github.com/DISIC/Ara/pull/329))
8187

82-
## Autres changements ⚙️
88+
### Autres changements ⚙️
8389

8490
- Petits ajustements d’affichage du contenu de la page Contexte d’un audit ([#331](https://github.com/DISIC/Ara/pull/331))
8591
- Mise à jour du wording pour la saisie d’un moyen de contact dans la déclaration ([#330](https://github.com/DISIC/Ara/pull/330))
8692

8793
## 23/03/2023
8894

89-
## Nouvelles fonctionnalités 🚀
95+
### Nouvelles fonctionnalités 🚀
9096

9197
- Ajout d’un interrupteur pour marquer le résultat d’un critère comme transverse sur toutes les pages ([#317](https://github.com/DISIC/Ara/pull/317))
9298

93-
## Autres changements ⚙️
99+
### Autres changements ⚙️
94100

95101
- Mise à jour du DSFR en version `1.9.0` ([#326](https://github.com/DISIC/Ara/pull/326))
96102
- Mise à jour de l’adresse email de contact : ara@design.numerique.gouv.fr ([#328](https://github.com/DISIC/Ara/pull/328))
97103

98104
## 08/03/2023
99105

100-
## Nouvelles fonctionnalités 🚀
106+
### Nouvelles fonctionnalités 🚀
101107

102108
- Ajout d’un lien de retour en haut de page pendant l’audit ([#316](https://github.com/DISIC/Ara/pull/316))
103109

104110
### Correction 🐛
105111

106112
- Améliore la gestion du focus à la fermeture des modales ([#297](https://github.com/DISIC/Ara/pull/297))
107113

108-
## Autres changements ⚙️
114+
### Autres changements ⚙️
109115

110116
- Un seul des 2 moyens de contact est obligatoire : email ou URL vers un formulaire ([#313](https://github.com/DISIC/Ara/pull/313))
111117

confiture-rest-api/package.json

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,12 +32,15 @@
3232
"@nestjs/platform-express": "^9.4.0",
3333
"@nestjs/swagger": "^6.3.0",
3434
"@prisma/client": "^4.1.1",
35+
"@types/lodash": "^4.14.194",
3536
"@vegardit/prisma-generator-nestjs-dto": "^1.5.1",
3637
"class-transformer": "^0.5.1",
3738
"class-validator": "^0.13.2",
3839
"got": "^11.8.5",
3940
"handlebars": "^4.7.7",
4041
"joi": "^17.6.0",
42+
"lodash": "^4.17.21",
43+
"lodash-es": "^4.17.21",
4144
"mjml": "^4.14.1",
4245
"morgan": "^1.10.0",
4346
"nanoid": "^3.3.4",
@@ -54,6 +57,7 @@
5457
"@nestjs/testing": "^9.2.1",
5558
"@types/express": "^4.17.13",
5659
"@types/jest": "27.4.1",
60+
"@types/lodash-es": "^4.17.7",
5761
"@types/mjml": "^4.7.1",
5862
"@types/multer": "^1.4.7",
5963
"@types/node": "^16.0.0",
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
-- AlterTable
2+
ALTER TABLE "Audit" ADD COLUMN "sourceAuditId" INTEGER;
3+
4+
-- AddForeignKey
5+
ALTER TABLE "Audit" ADD CONSTRAINT "Audit_sourceAuditId_fkey" FOREIGN KEY ("sourceAuditId") REFERENCES "Audit"("id") ON DELETE SET NULL ON UPDATE CASCADE;

confiture-rest-api/prisma/schema.prisma

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,11 @@ model Audit {
7575
consultUniqueId String @unique
7676
auditTraceId Int @unique
7777
auditTrace AuditTrace @relation(fields: [auditTraceId], references: [id])
78+
79+
// Audit duplication history
80+
sourceAudit Audit? @relation("AuditDuplicationHistory", fields: [sourceAuditId], references: [id])
81+
sourceAuditId Int?
82+
auditCopies Audit[] @relation("AuditDuplicationHistory")
7883
7984
@@unique([editUniqueId, consultUniqueId])
8085
}

confiture-rest-api/src/audits/audit.service.ts

Lines changed: 164 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import {
1111
} from '@prisma/client';
1212
import { nanoid } from 'nanoid';
1313
import sharp from 'sharp';
14+
import { omit, setWith } from 'lodash';
1415

1516
import { PrismaService } from '../prisma.service';
1617
import * as RGAA from '../rgaa.json';
@@ -25,6 +26,11 @@ const AUDIT_EDIT_INCLUDE: Prisma.AuditInclude = {
2526
recipients: true,
2627
environments: true,
2728
pages: true,
29+
sourceAudit: {
30+
select: {
31+
procedureName: true,
32+
},
33+
},
2834
};
2935

3036
@Injectable()
@@ -889,4 +895,162 @@ export class AuditService {
889895

890896
return testedCount === expectedCount;
891897
}
898+
899+
async duplicateAudit(sourceUniqueId: string, newAuditName: string) {
900+
const originalAudit = await this.prisma.audit.findUnique({
901+
where: { editUniqueId: sourceUniqueId },
902+
include: {
903+
environments: true,
904+
pages: {
905+
include: {
906+
results: {
907+
include: {
908+
exampleImages: true,
909+
},
910+
},
911+
},
912+
},
913+
},
914+
});
915+
916+
if (!originalAudit) {
917+
return;
918+
}
919+
920+
const duplicateEditUniqueId = nanoid();
921+
const duplicateConsultUniqueId = nanoid();
922+
923+
/**
924+
Object storing duplicate exampleImage creation data mapped by
925+
- page id
926+
- result id
927+
- example id
928+
929+
This object is used within the call to prisma.audit.create() to duplicate the example images.
930+
931+
Example content:
932+
```
933+
{
934+
'page-id': {
935+
'result-id': {
936+
'example-id': {
937+
filename: 'foo',
938+
...
939+
}
940+
}
941+
}
942+
}
943+
```
944+
*/
945+
const imagesCreateData: {
946+
[pageId: string]: {
947+
[resultId: string]: object;
948+
};
949+
} = {};
950+
951+
/**
952+
* contains s3 file duplications which will be executed together by calling
953+
* `fileStorageService.duplicateMultipleFiles()`
954+
*/
955+
const imageDuplications: { originalKey: string; destinationKey: string }[] =
956+
[];
957+
958+
originalAudit.pages.forEach((p) => {
959+
p.results.forEach((r) => {
960+
r.exampleImages.forEach((e) => {
961+
const randomPrefix = nanoid();
962+
963+
const key = `audits/${duplicateEditUniqueId}/${randomPrefix}/${e.originalFilename}`;
964+
const thumbnailKey = `audits/${duplicateEditUniqueId}/${randomPrefix}/thumbnail_${e.originalFilename}`;
965+
966+
const publicUrl = this.fileStorageService.getPublicUrl(key);
967+
const thumbnailUrl =
968+
this.fileStorageService.getPublicUrl(thumbnailKey);
969+
970+
imageDuplications.push(
971+
{
972+
originalKey: e.key,
973+
destinationKey: key,
974+
},
975+
{
976+
originalKey: e.thumbnailKey,
977+
destinationKey: thumbnailKey,
978+
},
979+
);
980+
981+
setWith(
982+
imagesCreateData,
983+
[p.id, r.id, e.id],
984+
{
985+
originalFilename: e.originalFilename,
986+
url: publicUrl,
987+
size: e.size,
988+
key: key,
989+
thumbnailUrl: thumbnailUrl,
990+
thumbnailKey: thumbnailKey,
991+
},
992+
Object,
993+
);
994+
});
995+
});
996+
});
997+
998+
await this.fileStorageService.duplicateMultipleFiles(imageDuplications);
999+
1000+
const newAudit = await this.prisma.audit.create({
1001+
data: {
1002+
...omit(originalAudit, ['id', 'auditTraceId', 'sourceAuditId']),
1003+
1004+
// link new audit with the original
1005+
sourceAudit: {
1006+
connect: {
1007+
editUniqueId: sourceUniqueId,
1008+
},
1009+
},
1010+
1011+
editUniqueId: duplicateEditUniqueId,
1012+
consultUniqueId: duplicateConsultUniqueId,
1013+
1014+
procedureName: newAuditName,
1015+
1016+
creationDate: new Date(),
1017+
editionDate: undefined,
1018+
publicationDate: undefined,
1019+
1020+
environments: {
1021+
createMany: {
1022+
data: originalAudit.environments.map((e) =>
1023+
omit(e, ['id', 'auditUniqueId']),
1024+
),
1025+
},
1026+
},
1027+
1028+
pages: {
1029+
create: originalAudit.pages.map((p) => ({
1030+
name: p.name,
1031+
url: p.url,
1032+
results: {
1033+
create: p.results.map((r) => ({
1034+
...omit(r, ['id', 'pageId']),
1035+
exampleImages: {
1036+
create: r.exampleImages.map(
1037+
(e) => imagesCreateData[p.id][r.id][e.id],
1038+
),
1039+
},
1040+
})),
1041+
},
1042+
})),
1043+
},
1044+
1045+
auditTrace: {
1046+
create: {
1047+
auditConsultUniqueId: duplicateConsultUniqueId,
1048+
auditEditUniqueId: duplicateEditUniqueId,
1049+
},
1050+
},
1051+
},
1052+
});
1053+
1054+
return newAudit;
1055+
}
8921056
}

0 commit comments

Comments
 (0)