From c7e709c4d0055b0cf423d2e2467b09c63d4f081c Mon Sep 17 00:00:00 2001 From: dswbx Date: Fri, 29 Aug 2025 12:45:44 +0200 Subject: [PATCH] docs: updated sdk and elements --- app/src/ui/elements/media/Dropzone.tsx | 51 +++++++- .../ui/elements/media/DropzoneContainer.tsx | 23 ++++ .../docs/(documentation)/usage/elements.mdx | 12 +- .../docs/(documentation)/usage/sdk.mdx | 117 ++++++++++++++++++ 4 files changed, 192 insertions(+), 11 deletions(-) diff --git a/app/src/ui/elements/media/Dropzone.tsx b/app/src/ui/elements/media/Dropzone.tsx index 27a01424..908c49a3 100644 --- a/app/src/ui/elements/media/Dropzone.tsx +++ b/app/src/ui/elements/media/Dropzone.tsx @@ -46,24 +46,73 @@ export type DropzoneRenderProps = { }; export type DropzoneProps = { + /** + * Get the upload info for a file + */ getUploadInfo: (file: { path: string }) => { url: string; headers?: Headers; method?: string }; + /** + * Handle the deletion of a file + */ handleDelete: (file: { path: string }) => Promise; + /** + * The initial items to display + */ initialItems?: FileState[]; - flow?: "start" | "end"; + /** + * Maximum number of media items that can be uploaded + */ maxItems?: number; + /** + * The allowed mime types + */ allowedMimeTypes?: string[]; + /** + * If true, the media item will be overwritten on entity media uploads if limit was reached + */ overwrite?: boolean; + /** + * If true, the media items will be uploaded automatically + */ autoUpload?: boolean; + /** + * Whether to add new items to the start or end of the list + * @default "start" + */ + flow?: "start" | "end"; + /** + * The on rejected callback + */ onRejected?: (files: FileWithPath[]) => void; + /** + * The on deleted callback + */ onDeleted?: (file: { path: string }) => void; + /** + * The on uploaded all callback + */ onUploadedAll?: (files: FileStateWithData[]) => void; + /** + * The on uploaded callback + */ onUploaded?: (file: FileStateWithData) => void; + /** + * The on clicked callback + */ onClick?: (file: FileState) => void; + /** + * The placeholder to use + */ placeholder?: { show?: boolean; text?: string; }; + /** + * The footer to render + */ footer?: ReactNode; + /** + * The children to render + */ children?: ReactNode | ((props: DropzoneRenderProps) => ReactNode); }; diff --git a/app/src/ui/elements/media/DropzoneContainer.tsx b/app/src/ui/elements/media/DropzoneContainer.tsx index 2f695a94..46cef55b 100644 --- a/app/src/ui/elements/media/DropzoneContainer.tsx +++ b/app/src/ui/elements/media/DropzoneContainer.tsx @@ -10,15 +10,38 @@ import { mediaItemsToFileStates } from "./helper"; import { useInViewport } from "@mantine/hooks"; export type DropzoneContainerProps = { + /** + * The initial items to display + * @default [] + */ initialItems?: MediaFieldSchema[] | false; + /** + * Whether to use infinite scrolling + * @default false + */ infinite?: boolean; + /** + * If given, the initial media items fetched will be from this entity + * @default undefined + */ entity?: { name: string; id: PrimaryFieldType; field: string; }; + /** + * The media config + * @default undefined + */ media?: Pick; + /** + * Query to filter the media items + */ query?: RepoQueryIn; + /** + * Whether to use a random filename + * @default false + */ randomFilename?: boolean; } & Omit, "initialItems">; diff --git a/docs/content/docs/(documentation)/usage/elements.mdx b/docs/content/docs/(documentation)/usage/elements.mdx index d034a6e7..239687fc 100644 --- a/docs/content/docs/(documentation)/usage/elements.mdx +++ b/docs/content/docs/(documentation)/usage/elements.mdx @@ -44,16 +44,8 @@ export default function UserAvatar() { #### Props -- `initialItems?: xMediaFieldSchema[]`: Initial items to display, must be an array of media objects. -- `entity?: { name: string; id: number; field: string }`: If given, the initial media items fetched will be from this entity. -- `query?: RepoQueryIn`: Query to filter the media items. -- `overwrite?: boolean`: If true, the media item will be overwritten on entity media uploads if limit was reached. -- `maxItems?: number`: Maximum number of media items that can be uploaded. -- `autoUpload?: boolean`: If true, the media items will be uploaded automatically. -- `onRejected?: (files: FileWithPath[]) => void`: Callback when a file is rejected. -- `onDeleted?: (file: FileState) => void`: Callback when a file is deleted. -- `onUploaded?: (file: FileState) => void`: Callback when a file is uploaded. -- `placeholder?: { show?: boolean; text?: string }`: Placeholder text to show when no media items are present. + + #### Customize Rendering diff --git a/docs/content/docs/(documentation)/usage/sdk.mdx b/docs/content/docs/(documentation)/usage/sdk.mdx index a0c6f632..70c194ab 100644 --- a/docs/content/docs/(documentation)/usage/sdk.mdx +++ b/docs/content/docs/(documentation)/usage/sdk.mdx @@ -199,6 +199,37 @@ To delete many records of an entity, use the `deleteMany` method: const { data } = await api.data.deleteMany("posts", { views: { $lte: 1 } }); ``` +### `data.readManyByReference([entity], [id], [reference], [query])` + +To retrieve records from a related entity by following a reference, use the `readManyByReference` method: + +```ts +const { data } = await api.data.readManyByReference("posts", 1, "comments", { + limit: 5, + sort: "-created_at", +}); +``` + +### `data.count([entity], [where])` + +To count records in an entity that match certain criteria, use the `count` method: + +```ts +const { data } = await api.data.count("posts", { + views: { $gt: 100 } +}); +``` + +### `data.exists([entity], [where])` + +To check if any records exist in an entity that match certain criteria, use the `exists` method: + +```ts +const { data } = await api.data.exists("posts", { + title: "Hello, World!" +}); +``` + ## Auth (`api.auth`) Access the `Auth` specific API methods at `api.auth`. If there is successful authentication, the @@ -241,3 +272,89 @@ To retrieve the current user, use the `me` method: ```ts const { data } = await api.auth.me(); ``` + +## Media (`api.media`) + +Access the `Media` specific API methods at `api.media`. + +### `media.listFiles()` + +To retrieve a list of all uploaded files, use the `listFiles` method: + +```ts +const { data } = await api.media.listFiles(); +// ^? FileListObject[] +``` + +### `media.getFile([filename])` + +To retrieve a file as a readable stream, use the `getFile` method: + +```ts +const { data } = await api.media.getFile("image.jpg"); +// ^? ReadableStream +``` + +### `media.getFileStream([filename])` + +To get a file stream directly, use the `getFileStream` method: + +```ts +const stream = await api.media.getFileStream("image.jpg"); +// ^? ReadableStream +``` + +### `media.download([filename])` + +To download a file as a File object, use the `download` method: + +```ts +const file = await api.media.download("image.jpg"); +// ^? File +``` + +### `media.upload([item], [options])` + +To upload a file, use the `upload` method. The item can be any of: +- `File` object +- `Request` object +- `Response` object +- `string` (URL) +- `ReadableStream` +- `Buffer` +- `Blob` + +```ts +// Upload a File object +const { data } = await api.media.upload(item); + +// Upload from a URL +const { data } = await api.media.upload("https://example.com/image.jpg"); + +// Upload with custom options +const { data } = await api.media.upload(item, { + filename: "custom-name.jpg", +}); +``` + +### `media.uploadToEntity([entity], [id], [field], [item], [options])` + +To upload a file directly to an entity field, use the `uploadToEntity` method: + +```ts +const { data } = await api.media.uploadToEntity( + "posts", + 1, + "image", + item +); +``` + +### `media.deleteFile([filename])` + +To delete a file, use the `deleteFile` method: + +```ts +const { data } = await api.media.deleteFile("image.jpg"); +``` +