Files
bknd/app/src/ui/elements/media/DropzoneContainer.tsx
2025-01-16 16:21:32 +01:00

94 lines
2.6 KiB
TypeScript

import type { RepoQuery, RepoQueryIn } from "data";
import type { MediaFieldSchema } from "media/AppMedia";
import type { TAppMediaConfig } from "media/media-schema";
import { useId } from "react";
import { useApi, useBaseUrl, useEntityQuery, useInvalidate } from "ui/client";
import { useEvent } from "ui/hooks/use-event";
import { Dropzone, type DropzoneProps, type DropzoneRenderProps, type FileState } from "./Dropzone";
import { mediaItemsToFileStates } from "./helper";
export type DropzoneContainerProps = {
children?: (props: DropzoneRenderProps) => JSX.Element;
initialItems?: MediaFieldSchema[];
entity?: {
name: string;
id: number;
field: string;
};
query?: RepoQueryIn;
} & Partial<Pick<TAppMediaConfig, "basepath" | "entity_name" | "storage">> &
Partial<DropzoneProps>;
export function DropzoneContainer({
initialItems,
basepath = "/api/media",
storage = {},
entity_name = "media",
entity,
query,
...props
}: DropzoneContainerProps) {
const id = useId();
const baseUrl = useBaseUrl();
const api = useApi();
const invalidate = useInvalidate();
const limit = query?.limit ? query?.limit : props.maxItems ? props.maxItems : 50;
const $q = useEntityQuery(
entity_name as "media",
undefined,
{
...query,
limit,
where: entity
? {
reference: `${entity.name}.${entity.field}`,
entity_id: entity.id,
...query?.where
}
: query?.where
},
{ enabled: !initialItems }
);
const getUploadInfo = useEvent((file) => {
const url = entity
? api.media.getEntityUploadUrl(entity.name, entity.id, entity.field)
: api.media.getFileUploadUrl(file);
return {
url,
headers: api.media.getUploadHeaders(),
method: "POST"
};
});
const refresh = useEvent(async () => {
if (entity) {
invalidate((api) => api.data.readOne(entity.name, entity.id));
}
await $q.mutate();
});
const handleDelete = useEvent(async (file: FileState) => {
return api.media.deleteFile(file.path);
});
const actualItems = initialItems ?? (($q.data || []) as MediaFieldSchema[]);
const _initialItems = mediaItemsToFileStates(actualItems, { baseUrl });
const key = id + JSON.stringify(_initialItems);
return (
<Dropzone
key={id + key}
getUploadInfo={getUploadInfo}
handleDelete={handleDelete}
onUploaded={refresh}
onDeleted={refresh}
autoUpload
initialItems={_initialItems}
{...props}
/>
);
}