diff --git a/backend/prisma/migrations/20240501154254_share_name_property/migration.sql b/backend/prisma/migrations/20240501154254_share_name_property/migration.sql new file mode 100644 index 00000000..2b47009e --- /dev/null +++ b/backend/prisma/migrations/20240501154254_share_name_property/migration.sql @@ -0,0 +1,2 @@ +-- AlterTable +ALTER TABLE "Share" ADD COLUMN "name" TEXT; diff --git a/backend/prisma/schema.prisma b/backend/prisma/schema.prisma index c83a9f04..8cd4a6c0 100644 --- a/backend/prisma/schema.prisma +++ b/backend/prisma/schema.prisma @@ -75,6 +75,7 @@ model Share { id String @id @default(uuid()) createdAt DateTime @default(now()) + name String? uploadLocked Boolean @default(false) isZipReady Boolean @default(false) views Int @default(0) diff --git a/backend/src/reverseShare/dto/reverseShareTokenWithShares.ts b/backend/src/reverseShare/dto/reverseShareTokenWithShares.ts index a496ffb6..b4243d1c 100644 --- a/backend/src/reverseShare/dto/reverseShareTokenWithShares.ts +++ b/backend/src/reverseShare/dto/reverseShareTokenWithShares.ts @@ -13,7 +13,7 @@ export class ReverseShareTokenWithShares extends OmitType(ReverseShareDTO, [ @Type(() => OmitType(MyShareDTO, ["recipients", "hasPassword"] as const)) shares: Omit< MyShareDTO, - "recipients" | "files" | "from" | "fromList" | "hasPassword" + "recipients" | "files" | "from" | "fromList" | "hasPassword" | "size" >[]; @Expose() diff --git a/backend/src/share/dto/createShare.dto.ts b/backend/src/share/dto/createShare.dto.ts index d6a1b1c2..479b9643 100644 --- a/backend/src/share/dto/createShare.dto.ts +++ b/backend/src/share/dto/createShare.dto.ts @@ -18,6 +18,10 @@ export class CreateShareDTO { @Length(3, 50) id: string; + @Length(3, 30) + @IsOptional() + name: string; + @IsString() expiration: string; diff --git a/backend/src/share/dto/share.dto.ts b/backend/src/share/dto/share.dto.ts index 317a3019..daf471ce 100644 --- a/backend/src/share/dto/share.dto.ts +++ b/backend/src/share/dto/share.dto.ts @@ -6,6 +6,9 @@ export class ShareDTO { @Expose() id: string; + @Expose() + name?: string; + @Expose() expiration: Date; @@ -23,6 +26,9 @@ export class ShareDTO { @Expose() hasPassword: boolean; + @Expose() + size: number; + from(partial: Partial) { return plainToClass(ShareDTO, partial, { excludeExtraneousValues: true }); } diff --git a/backend/src/share/share.service.ts b/backend/src/share/share.service.ts index c4831740..85821f1b 100644 --- a/backend/src/share/share.service.ts +++ b/backend/src/share/share.service.ts @@ -214,6 +214,7 @@ export class ShareService { return shares.map((share) => { return { ...share, + size: share.files.reduce((acc, file) => acc + parseInt(file.size), 0), recipients: share.recipients.map((recipients) => recipients.email), }; }); diff --git a/backend/test/newman-system-tests.json b/backend/test/newman-system-tests.json index 0c2b8b74..16f16440 100644 --- a/backend/test/newman-system-tests.json +++ b/backend/test/newman-system-tests.json @@ -432,7 +432,7 @@ " const responseBody = pm.response.json();", " pm.expect(responseBody).to.have.property(\"id\")", " pm.expect(responseBody).to.have.property(\"expiration\")", - " pm.expect(Object.keys(responseBody).length).be.equal(3)", + " pm.expect(Object.keys(responseBody).length).be.equal(4)", "});", "" ], @@ -626,7 +626,7 @@ " const responseBody = pm.response.json();", " pm.expect(responseBody).to.have.property(\"id\")", " pm.expect(responseBody).to.have.property(\"expiration\")", - " pm.expect(Object.keys(responseBody).length).be.equal(3)", + " pm.expect(Object.keys(responseBody).length).be.equal(4)", "});", "" ], diff --git a/frontend/src/components/account/showShareInformationsModal.tsx b/frontend/src/components/account/showShareInformationsModal.tsx index 3852e384..f4c62ed6 100644 --- a/frontend/src/components/account/showShareInformationsModal.tsx +++ b/frontend/src/components/account/showShareInformationsModal.tsx @@ -17,13 +17,9 @@ const showShareInformationsModal = ( const t = translateOutsideContext(); const link = `${appUrl}/s/${share.id}`; - let shareSize: number = 0; - for (let file of share.files as FileMetaData[]) - shareSize += parseInt(file.size); - - const formattedShareSize = byteToHumanSizeString(shareSize); + const formattedShareSize = byteToHumanSizeString(share.size); const formattedMaxShareSize = byteToHumanSizeString(maxShareSize); - const shareSizeProgress = (shareSize / maxShareSize) * 100; + const shareSizeProgress = (share.size / maxShareSize) * 100; const formattedCreatedAt = moment(share.createdAt).format("LLL"); const formattedExpiration = @@ -42,12 +38,18 @@ const showShareInformationsModal = ( {share.id} + + + :{" "} + + {share.name || "-"} + :{" "} - {share.description || "No description"} + {share.description || "-"} @@ -75,15 +77,15 @@ const showShareInformationsModal = ( - {shareSize / maxShareSize < 0.1 && ( + {share.size / maxShareSize < 0.1 && ( {formattedShareSize} )} = 0.1 ? formattedShareSize : ""} - style={{ width: shareSize / maxShareSize < 0.1 ? "70%" : "80%" }} + label={share.size / maxShareSize >= 0.1 ? formattedShareSize : ""} + style={{ width: share.size / maxShareSize < 0.1 ? "70%" : "80%" }} size="xl" radius="xl" /> diff --git a/frontend/src/components/upload/modals/showCreateUploadModal.tsx b/frontend/src/components/upload/modals/showCreateUploadModal.tsx index 249e8317..6d34af1a 100644 --- a/frontend/src/components/upload/modals/showCreateUploadModal.tsx +++ b/frontend/src/components/upload/modals/showCreateUploadModal.tsx @@ -92,11 +92,16 @@ const CreateUploadModalBody = ({ .matches(new RegExp("^[a-zA-Z0-9_-]*$"), { message: t("upload.modal.link.error.invalid"), }), + name: yup + .string() + .transform((value) => value || undefined) + .min(3, t("common.error.too-short", { length: 3 })) + .max(30, t("common.error.too-long", { length: 30 })), password: yup .string() .transform((value) => value || undefined) - .min(3) - .max(30), + .min(3, t("common.error.too-short", { length: 3 })) + .max(30, t("common.error.too-long", { length: 30 })), maxViews: yup .number() .transform((value) => value || undefined) @@ -105,6 +110,7 @@ const CreateUploadModalBody = ({ const form = useForm({ initialValues: { + name: undefined, link: generatedLink, recipients: [] as string[], password: undefined, @@ -154,6 +160,7 @@ const CreateUploadModalBody = ({ uploadCallback( { id: values.link, + name: values.name, expiration: expirationString, recipients: values.recipients, description: values.description, @@ -308,14 +315,21 @@ const CreateUploadModalBody = ({ - + +