diff --git a/src/app/dashboard/_actions/fileActions.ts b/src/app/dashboard/_actions/fileActions.ts index 5e7ed30..ca99fee 100644 --- a/src/app/dashboard/_actions/fileActions.ts +++ b/src/app/dashboard/_actions/fileActions.ts @@ -11,10 +11,22 @@ export async function createDataFileServerAction(file: NewDataFile): Promise +export async function getDataFilesPaginatedServerAction(skip: number, take?: number): Promise { const client = await getDatabaseClientAsync() - const files = await client.getDataFilesPaginatedAsync(skip, take) + const files = await client.getDataFilesPaginatedAsync(skip, take ?? Number(process.env.PAGINATION_PAGE_SIZE)) return files } + +export async function getDataFileDetailsServerAction(fileId: string): Promise +{ + const client = await getDatabaseClientAsync() + const file = await client.getDataFileDetailsAsync(fileId) + return file +} + +export async function deleteDataFileServerAction(fileId: string): Promise +{ + const client = await getDatabaseClientAsync() + await client.deleteDataFileAsync(fileId) +} diff --git a/src/app/dashboard/files/_components/FilesView.tsx b/src/app/dashboard/files/_components/FilesView.tsx index efef846..beecdc3 100644 --- a/src/app/dashboard/files/_components/FilesView.tsx +++ b/src/app/dashboard/files/_components/FilesView.tsx @@ -1,8 +1,16 @@ 'use client' -import { createDataFileServerAction, getDataFilesPaginatedServerAction } from '@/app/dashboard/_actions/fileActions' +import +{ + createDataFileServerAction, + deleteDataFileServerAction, + getDataFileDetailsServerAction, + getDataFilesPaginatedServerAction +} from '@/app/dashboard/_actions/fileActions' + import { FileListItem } from '@/app/dashboard/files/_components/FileListItem' import { NewFileDialog } from '@/app/dashboard/files/_components/NewFileDialog' +import { ViewFileDialog, invokeViewFileRequest } from '@/app/dashboard/files/_components/ViewFileDialog' import { invokeLoadingModal } from '@/components/LoadingModal' import { NewDataFile } from '@/modules/database/requestTypes' import { DataFileSearchItem, DataFilesPaginatedResponse } from '@/modules/database/responseTypes' @@ -18,7 +26,7 @@ export function FilesView(props: DataFilesPaginatedResponse) async function fileUploadHandler(fileData: NewDataFile) { - const invokeLoading = (display: boolean) => invokeLoadingModal({ display, textOverride: 'Uploading Image' }) + const invokeLoading = (display: boolean) => invokeLoadingModal({ display, textOverride: 'Uploading File' }) invokeLoading(true) @@ -28,34 +36,55 @@ export function FilesView(props: DataFilesPaginatedResponse) invokeLoading(false) } + async function fileViewHandler(fileId: string) + { + const invokeLoading = (display: boolean) => invokeLoadingModal({ display, textOverride: 'Loading File' }) + + invokeLoading(true) + { + const file = await getDataFileDetailsServerAction(fileId) + invokeViewFileRequest(file) + } + invokeLoading(false) + } + + async function fileDeleteHandler(fileId: string) + { + const invokeLoading = (display: boolean) => invokeLoadingModal({ display, textOverride: 'Deleting File' }) + + invokeLoading(true) + + await deleteDataFileServerAction(fileId) + await resetPagination() + + invokeLoading(false) + } + async function resetPagination() { - const files = await getDataFilesPaginatedServerAction(0, process.env.PAGINATION_PAGE_SIZE) + const files = await getDataFilesPaginatedServerAction(0) setDataFilesSearches({ 1: files.fileDetails }) setTotalFiles(files.totalFiles) setPagination(files.request) + setPage(1) } async function paginationHandler(_event: React.ChangeEvent, value: number) { - if (dataFilesSearches[value]) + if (!dataFilesSearches[value]) { - setPage(value) - return - } - - const invokeLoading = (display: boolean) => invokeLoadingModal({ display, textOverride: 'Loading' }) + const invokeLoading = (display: boolean) => invokeLoadingModal({ display, textOverride: 'Loading' }) - invokeLoading(true) - { - // BUG: Review pagination issue - need to remove images before I can test - throw new Error('NEEDS WORK') - const result = await getDataFilesPaginatedServerAction((value - 1) * pagination.take, pagination.take) - const newDataFilesSearches = { ...dataFilesSearches } - newDataFilesSearches[value] = result.fileDetails - setDataFilesSearches(newDataFilesSearches) + invokeLoading(true) + { + const result = await getDataFilesPaginatedServerAction((value - 1) * pagination.take, pagination.take) + const newDataFilesSearches = { ...dataFilesSearches } + newDataFilesSearches[value] = result.fileDetails + setDataFilesSearches(newDataFilesSearches) + } + invokeLoading(false) } - invokeLoading(false) + setPage(value) } @@ -64,7 +93,7 @@ export function FilesView(props: DataFilesPaginatedResponse) {dataFilesSearches[page].map((file) => ( - { }} /> + fileViewHandler(file.id)} /> ))} @@ -90,6 +119,7 @@ export function FilesView(props: DataFilesPaginatedResponse) /> + ) } diff --git a/src/app/dashboard/files/_components/NewFileDialog.tsx b/src/app/dashboard/files/_components/NewFileDialog.tsx index e6b9f69..eee4f60 100644 --- a/src/app/dashboard/files/_components/NewFileDialog.tsx +++ b/src/app/dashboard/files/_components/NewFileDialog.tsx @@ -53,7 +53,7 @@ export function NewFileDialog(props: Props) if (!dataFile) return invokeConfirmationModal({ - description: 'Are you sure you want to upload this image?', + description: 'Are you sure you want to upload this file?', onConfirmed: (confirmed) => { if (confirmed) diff --git a/src/app/dashboard/files/_components/ViewFileDialog.tsx b/src/app/dashboard/files/_components/ViewFileDialog.tsx new file mode 100644 index 0000000..517c91c --- /dev/null +++ b/src/app/dashboard/files/_components/ViewFileDialog.tsx @@ -0,0 +1,127 @@ +'use client' + +import { FileTypeIcon } from '@/app/dashboard/files/_components/FileTypeIcon' +import { invokeConfirmationModal } from '@/components/ConfirmationModal' +import { ImageBox } from '@/components/ImageBox' +import { createEvent } from '@/modules/custom-events/createEvent' +import { DataFileDetails } from '@/modules/database/responseTypes' +import { Button, Card, Dialog, DialogActions, DialogContent, DialogTitle, InputAdornment, List, ListItem, ListItemText, ListSubheader, TextField } from '@mui/material' +import { useState } from 'react' + +const viewFileRequestEvent = createEvent('viewFileRequest') + +export const invokeViewFileRequest = viewFileRequestEvent.callEvent + +const defaultState = { + display: false, + delete: false +} + +type Props = { + onFileDelete: (fileId: string) => void +} + +export function ViewFileDialog(props: Props) +{ + const { onFileDelete } = props + + const [state, setState] = useState(defaultState) + const [dataFile, setDataFile] = useState(null) + + viewFileRequestEvent.useEvent((file) => + { + setState({ ...defaultState, display: true }) + setDataFile(file) + }) + + function cancelHandler() + { + setState(defaultState) + } + + function deleteStartHandler() + { + if (!dataFile) return + + invokeConfirmationModal({ + description: 'Are you sure you want to delete this file?', + onConfirmed: (confirmed) => + { + if (confirmed) + { + setState({ ...state, display: false, delete: true }) + } + } + }) + } + + function exitHandler() + { + if (dataFile && state.delete) onFileDelete(dataFile.id) + setState(defaultState) + setDataFile(null) + } + + return ( + + File View + + {dataFile && (<> + + + + ), + }} + defaultValue={dataFile?.name} + disabled + /> + {dataFile.hasThumbnail && ( + + )} + + {Object.entries(dataFile.meta).length > 0 && ( + + Meta} + > + {Object.entries(dataFile.meta).map(([key, value]) => ( + + + + ))} + + + + )} + )} + + + + + + + ) +}