Skip to content

Commit 21ee11b

Browse files
committed
fully duplicate audit including images
1 parent cfcdc45 commit 21ee11b

2 files changed

Lines changed: 114 additions & 27 deletions

File tree

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

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

1616
import { PrismaService } from '../prisma.service';
1717
import * as RGAA from '../rgaa.json';
@@ -21,7 +21,6 @@ import { CRITERIA_BY_AUDIT_TYPE } from './criteria';
2121
import { FileStorageService } from './file-storage.service';
2222
import { UpdateAuditDto } from './update-audit.dto';
2323
import { UpdateResultsDto } from './update-results.dto';
24-
import { writeFile } from 'fs/promises';
2524

2625
const AUDIT_EDIT_INCLUDE: Prisma.AuditInclude = {
2726
recipients: true,
@@ -893,7 +892,7 @@ export class AuditService {
893892
}
894893

895894
async duplicateAudit(uniqueId: string, newAuditName: string) {
896-
const o = await this.prisma.audit.findUnique({
895+
const originalAudit = await this.prisma.audit.findUnique({
897896
where: { editUniqueId: uniqueId },
898897
include: {
899898
environments: true,
@@ -909,23 +908,96 @@ export class AuditService {
909908
},
910909
});
911910

912-
if (!o) {
911+
if (!originalAudit) {
913912
return;
914913
}
915914

916-
// console.dir(originalAudit, { depth: null });
917-
918-
// await writeFile('audit.json', JSON.stringify(originalAudit, null, 2));
915+
const duplicateEditUniqueId = nanoid();
916+
const duplicateConsultUniqueId = nanoid();
917+
918+
/**
919+
Object storing duplicate exampleImage creation data mapped by
920+
- page id
921+
- result id
922+
- example id
923+
924+
This object is used within the call to prisma.audit.create() to duplicate the example images.
925+
926+
Example content:
927+
```
928+
{
929+
'page-id': {
930+
'result-id': {
931+
'example-id': {
932+
filename: 'foo',
933+
...
934+
}
935+
}
936+
}
937+
}
938+
```
939+
*/
940+
const imagesCreateData: {
941+
[pageId: string]: {
942+
[resultId: string]: object;
943+
};
944+
} = {};
945+
946+
/**
947+
* contains s3 file duplications which will be executed together by calling
948+
* `fileStorageService.duplicateMultipleFiles()`
949+
*/
950+
const imageDuplications: { originalKey: string; destinationKey: string }[] =
951+
[];
952+
953+
originalAudit.pages.forEach((p) => {
954+
p.results.forEach((r) => {
955+
r.exampleImages.forEach((e, i) => {
956+
const randomPrefix = nanoid();
957+
958+
const key = `audits/${duplicateEditUniqueId}/${randomPrefix}/${e.originalFilename}`;
959+
const thumbnailKey = `audits/${duplicateEditUniqueId}/${randomPrefix}/thumbnail_${e.originalFilename}`;
960+
961+
const publicUrl = this.fileStorageService.getPublicUrl(key);
962+
const thumbnailUrl =
963+
this.fileStorageService.getPublicUrl(thumbnailKey);
964+
965+
imageDuplications.push(
966+
{
967+
originalKey: e.key,
968+
destinationKey: key,
969+
},
970+
{
971+
originalKey: e.thumbnailKey,
972+
destinationKey: thumbnailKey,
973+
},
974+
);
975+
976+
setWith(
977+
imagesCreateData,
978+
[p.id, r.id, e.id],
979+
{
980+
originalFilename: e.originalFilename,
981+
url: publicUrl,
982+
size: e.size,
983+
key: key,
984+
thumbnailUrl: thumbnailUrl,
985+
thumbnailKey: thumbnailKey,
986+
},
987+
Object,
988+
);
989+
});
990+
});
991+
});
919992

920-
const editUniqueId = nanoid();
921-
const consultUniqueId = nanoid();
993+
await this.fileStorageService.duplicateMultipleFiles(imageDuplications);
922994

923995
const newAudit = await this.prisma.audit.create({
924996
data: {
925-
...omit(o, ['id', 'auditTraceId']),
997+
...omit(originalAudit, ['id', 'auditTraceId']),
926998

927-
editUniqueId,
928-
consultUniqueId,
999+
editUniqueId: duplicateEditUniqueId,
1000+
consultUniqueId: duplicateConsultUniqueId,
9291001

9301002
procedureName: newAuditName,
9311003

@@ -935,29 +1007,23 @@ export class AuditService {
9351007

9361008
environments: {
9371009
createMany: {
938-
data: o.environments.map((e) => omit(e, ['id', 'auditUniqueId'])),
1010+
data: originalAudit.environments.map((e) =>
1011+
omit(e, ['id', 'auditUniqueId']),
1012+
),
9391013
},
9401014
},
9411015

9421016
pages: {
943-
create: o.pages.map((p) => ({
1017+
create: originalAudit.pages.map((p) => ({
9441018
name: p.name,
9451019
url: p.url,
9461020
results: {
9471021
create: p.results.map((r) => ({
9481022
...omit(r, ['id', 'pageId']),
9491023
exampleImages: {
950-
// TODO: duplicate images too
951-
create: [
952-
// {
953-
// originalFilename: 'string',
954-
// url: 'string',
955-
// size: 123,
956-
// key: 'string',
957-
// thumbnailUrl: 'string',
958-
// thumbnailKey: 'string',
959-
// },
960-
],
1024+
create: r.exampleImages.map(
1025+
(e) => imagesCreateData[p.id][r.id][e.id],
1026+
),
9611027
},
9621028
})),
9631029
},
@@ -966,8 +1032,8 @@ export class AuditService {
9661032

9671033
auditTrace: {
9681034
create: {
969-
auditConsultUniqueId: consultUniqueId,
970-
auditEditUniqueId: editUniqueId,
1035+
auditConsultUniqueId: duplicateConsultUniqueId,
1036+
auditEditUniqueId: duplicateEditUniqueId,
9711037
},
9721038
},
9731039
},

confiture-rest-api/src/audits/file-storage.service.ts

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import {
33
PutObjectCommand,
44
DeleteObjectCommand,
55
DeleteObjectsCommand,
6+
CopyObjectCommand,
67
} from '@aws-sdk/client-s3';
78
import { Injectable } from '@nestjs/common';
89
import { ConfigService } from '@nestjs/config';
@@ -56,4 +57,24 @@ export class FileStorageService {
5657

5758
await this.s3Client.send(command);
5859
}
60+
61+
async duplicateMultipleFiles(
62+
duplications: { originalKey: string; destinationKey: string }[],
63+
) {
64+
await Promise.all(
65+
duplications
66+
.map(
67+
(d) =>
68+
new CopyObjectCommand({
69+
Bucket: this.config.get<string>('S3_BUCKET'),
70+
CopySource: `/${this.config.get<string>('S3_BUCKET')}/${
71+
d.originalKey
72+
}`,
73+
Key: d.destinationKey,
74+
ACL: 'public-read',
75+
}),
76+
)
77+
.map((command) => this.s3Client.send(command)),
78+
);
79+
}
5980
}

0 commit comments

Comments
 (0)