From 8728fa5207524e9aee26d68eafe1b6fff367d749 Mon Sep 17 00:00:00 2001 From: Elias Schneider Date: Mon, 12 Dec 2022 11:54:13 +0100 Subject: [PATCH] feat: add description field to share --- backend/prisma/schema.prisma | 1 + backend/src/share/dto/createShare.dto.ts | 6 ++ backend/src/share/dto/share.dto.ts | 3 + backend/src/user/dto/publicUser.dto.ts | 2 +- frontend/src/components/share/FileList.tsx | 56 ++++++++++--------- .../upload/modals/showCreateUploadModal.tsx | 42 ++++++++------ frontend/src/pages/share/[shareId].tsx | 23 +++++--- frontend/src/pages/upload.tsx | 18 +++--- frontend/src/services/share.service.ts | 21 ++++--- frontend/src/types/share.type.ts | 9 +++ 10 files changed, 108 insertions(+), 73 deletions(-) diff --git a/backend/prisma/schema.prisma b/backend/prisma/schema.prisma index 65e18a8..04b0733 100644 --- a/backend/prisma/schema.prisma +++ b/backend/prisma/schema.prisma @@ -39,6 +39,7 @@ model Share { isZipReady Boolean @default(false) views Int @default(0) expiration DateTime + description String? creatorId String? creator User? @relation(fields: [creatorId], references: [id], onDelete: Cascade) diff --git a/backend/src/share/dto/createShare.dto.ts b/backend/src/share/dto/createShare.dto.ts index ecb817a..d6a1b1c 100644 --- a/backend/src/share/dto/createShare.dto.ts +++ b/backend/src/share/dto/createShare.dto.ts @@ -1,9 +1,11 @@ import { Type } from "class-transformer"; import { IsEmail, + IsOptional, IsString, Length, Matches, + MaxLength, ValidateNested, } from "class-validator"; import { ShareSecurityDTO } from "./shareSecurity.dto"; @@ -19,6 +21,10 @@ export class CreateShareDTO { @IsString() expiration: string; + @MaxLength(512) + @IsOptional() + description: string; + @IsEmail({}, { each: true }) recipients: string[]; diff --git a/backend/src/share/dto/share.dto.ts b/backend/src/share/dto/share.dto.ts index 7f3571a..19324f5 100644 --- a/backend/src/share/dto/share.dto.ts +++ b/backend/src/share/dto/share.dto.ts @@ -17,6 +17,9 @@ export class ShareDTO { @Type(() => PublicUserDTO) creator: PublicUserDTO; + @Expose() + description: string; + from(partial: Partial) { return plainToClass(ShareDTO, partial, { excludeExtraneousValues: true }); } diff --git a/backend/src/user/dto/publicUser.dto.ts b/backend/src/user/dto/publicUser.dto.ts index e14269f..01c5e22 100644 --- a/backend/src/user/dto/publicUser.dto.ts +++ b/backend/src/user/dto/publicUser.dto.ts @@ -1,4 +1,4 @@ import { PickType } from "@nestjs/mapped-types"; import { UserDTO } from "./user.dto"; -export class PublicUserDTO extends PickType(UserDTO, ["email"] as const) {} +export class PublicUserDTO extends PickType(UserDTO, ["username"] as const) {} diff --git a/frontend/src/components/share/FileList.tsx b/frontend/src/components/share/FileList.tsx index daa03ab..af650ed 100644 --- a/frontend/src/components/share/FileList.tsx +++ b/frontend/src/components/share/FileList.tsx @@ -9,35 +9,10 @@ const FileList = ({ shareId, isLoading, }: { - files: any[]; + files?: any[]; shareId: string; isLoading: boolean; }) => { - const rows = files.map((file) => ( - - {file.name} - {byteStringToHumanSizeString(file.size)} - - {file.uploadingState ? ( - file.uploadingState != "finished" ? ( - - ) : ( - - ) - ) : ( - { - await shareService.downloadFile(shareId, file.id); - }} - > - - - )} - - - )); - return ( @@ -47,7 +22,34 @@ const FileList = ({ - {isLoading ? skeletonRows : rows} + + {isLoading + ? skeletonRows + : files!.map((file) => ( + + + + + + ))} +
{file.name}{byteStringToHumanSizeString(file.size)} + {file.uploadingState ? ( + file.uploadingState != "finished" ? ( + + ) : ( + + ) + ) : ( + { + await shareService.downloadFile(shareId, file.id); + }} + > + + + )} +
); }; diff --git a/frontend/src/components/upload/modals/showCreateUploadModal.tsx b/frontend/src/components/upload/modals/showCreateUploadModal.tsx index c9a44ad..c103a39 100644 --- a/frontend/src/components/upload/modals/showCreateUploadModal.tsx +++ b/frontend/src/components/upload/modals/showCreateUploadModal.tsx @@ -12,6 +12,7 @@ import { Select, Stack, Text, + Textarea, TextInput, Title, } from "@mantine/core"; @@ -22,7 +23,7 @@ import { useState } from "react"; import { TbAlertCircle } from "react-icons/tb"; import * as yup from "yup"; import shareService from "../../../services/share.service"; -import { ShareSecurity } from "../../../types/share.type"; +import { CreateShare } from "../../../types/share.type"; import ExpirationPreview from "../ExpirationPreview"; const showCreateUploadModal = ( @@ -32,12 +33,7 @@ const showCreateUploadModal = ( allowUnauthenticatedShares: boolean; enableEmailRecepients: boolean; }, - uploadCallback: ( - id: string, - expiration: string, - recipients: string[], - security: ShareSecurity - ) => void + uploadCallback: (createShare: CreateShare) => void ) => { return modals.openModal({ title: Share, @@ -54,12 +50,7 @@ const CreateUploadModalBody = ({ uploadCallback, options, }: { - uploadCallback: ( - id: string, - expiration: string, - recipients: string[], - security: ShareSecurity - ) => void; + uploadCallback: (createShare: CreateShare) => void; options: { isUserSignedIn: boolean; allowUnauthenticatedShares: boolean; @@ -88,6 +79,7 @@ const CreateUploadModalBody = ({ recipients: [] as string[], password: undefined, maxViews: undefined, + description: undefined, expiration_num: 1, expiration_unit: "-days", never_expires: false, @@ -116,9 +108,15 @@ const CreateUploadModalBody = ({ const expiration = form.values.never_expires ? "never" : form.values.expiration_num + form.values.expiration_unit; - uploadCallback(values.link, expiration, values.recipients, { - password: values.password, - maxViews: values.maxViews, + uploadCallback({ + id: values.link, + expiration: expiration, + recipients: values.recipients, + description: values.description, + security: { + password: values.password, + maxViews: values.maxViews, + }, }); modals.closeAll(); } @@ -258,6 +256,18 @@ const CreateUploadModalBody = ({ )} + + Description + + +