diff --git a/VoidCat/spa/src/app/src/Admin/Admin.tsx b/VoidCat/spa/src/app/src/Admin/Admin.tsx index 8485396..112583a 100644 --- a/VoidCat/spa/src/app/src/Admin/Admin.tsx +++ b/VoidCat/spa/src/app/src/Admin/Admin.tsx @@ -4,7 +4,6 @@ import {useSelector} from "react-redux"; import {Navigate} from "react-router-dom"; import {AdminProfile} from "@void-cat/api"; -import {FileList} from "../Components/Shared/FileList"; import {UserList} from "./UserList"; import {VoidButton} from "../Components/Shared/VoidButton"; import VoidModal from "../Components/Shared/VoidModal"; @@ -12,6 +11,7 @@ import EditUser from "./EditUser"; import useApi from "Hooks/UseApi"; import {RootState} from "Store"; +import ImageGrid from "../Components/Shared/ImageGrid"; export function Admin() { const auth = useSelector((state: RootState) => state.login.jwt); @@ -41,7 +41,7 @@ export function Admin() { ]}/>

Files

- AdminApi.adminListFiles(r)} actions={(i) => { + AdminApi.adminListFiles(r)} actions={(i) => { return deleteFile(i.id)}>Delete diff --git a/VoidCat/spa/src/app/src/Components/Shared/FileList.tsx b/VoidCat/spa/src/app/src/Components/Shared/FileList.tsx index 96adace..e7daae1 100644 --- a/VoidCat/spa/src/app/src/Components/Shared/FileList.tsx +++ b/VoidCat/spa/src/app/src/Components/Shared/FileList.tsx @@ -65,7 +65,7 @@ export function FileList(props: FileListProps) { loadFileList().catch(console.error) }, [page]); - if (accessDenied === true) { + if (accessDenied) { return

Access Denied

; } diff --git a/VoidCat/spa/src/app/src/Components/Shared/ImageGrid.css b/VoidCat/spa/src/app/src/Components/Shared/ImageGrid.css new file mode 100644 index 0000000..4ec764d --- /dev/null +++ b/VoidCat/spa/src/app/src/Components/Shared/ImageGrid.css @@ -0,0 +1,18 @@ +.image-grid { + display: flex; + flex-direction: row; + flex-wrap: wrap; +} + +.image-grid > div { + width: 100px; + cursor: pointer; + display: flex; + align-items: center; + justify-content: center; + overflow: hidden; +} + +.image-grid img, .image-grid video, .image-grid audio { + width: stretch; +} \ No newline at end of file diff --git a/VoidCat/spa/src/app/src/Components/Shared/ImageGrid.tsx b/VoidCat/spa/src/app/src/Components/Shared/ImageGrid.tsx new file mode 100644 index 0000000..1bc23e4 --- /dev/null +++ b/VoidCat/spa/src/app/src/Components/Shared/ImageGrid.tsx @@ -0,0 +1,103 @@ +import "./ImageGrid.css"; + +import {ApiError, PagedRequest, PagedResponse, PagedSortBy, PageSortOrder, VoidFileResponse} from "@void-cat/api"; +import {ReactNode, useEffect, useState} from "react"; +import {useDispatch} from "react-redux"; +import {logout} from "../../LoginState"; +import {PageSelector} from "./PageSelector"; +import {useNavigate} from "react-router-dom"; + +interface ImageGridProps { + actions?: (f: VoidFileResponse) => ReactNode + loadPage: (req: PagedRequest) => Promise> +} + +export default function ImageGrid(props: ImageGridProps) { + const navigate = useNavigate(); + const loadPage = props.loadPage; + const actions = props.actions; + const dispatch = useDispatch(); + const [files, setFiles] = useState>(); + const [page, setPage] = useState(0); + const pageSize = 20; + const [accessDenied, setAccessDenied] = useState(); + + async function loadFileList() { + try { + const pageReq = { + page: page, + pageSize, + sortBy: PagedSortBy.Date, + sortOrder: PageSortOrder.Dsc + }; + const rsp = await loadPage(pageReq); + setFiles(rsp); + } catch (e) { + console.error(e); + if (e instanceof ApiError) { + if (e.statusCode === 401) { + dispatch(logout()); + } else if (e.statusCode === 403) { + setAccessDenied(true); + } + } + } + } + + useEffect(() => { + loadFileList().catch(console.error) + }, [page]); + + function renderPreview(info: VoidFileResponse) { + const link = `/d/${info.id}`; + + if (info.metadata) { + switch (info.metadata.mimeType) { + case "image/avif": + case "image/bmp": + case "image/gif": + case "image/svg+xml": + case "image/tiff": + case "image/webp": + case "image/jpg": + case "image/jpeg": + case "image/png": { + return {info.metadata.name}/; + } + case "audio/aac": + case "audio/opus": + case "audio/wav": + case "audio/webm": + case "audio/midi": + case "audio/mpeg": + case "audio/ogg": { + return