feat(icons): add upload button to icon picker (#1859)

This commit is contained in:
Meier Lukas
2025-01-04 22:43:30 +01:00
committed by GitHub
parent 1562eae4d7
commit 1e9098d052
3 changed files with 96 additions and 44 deletions

View File

@@ -1,15 +1,40 @@
"use client";
import type { JSX } from "react";
import { Button, FileButton } from "@mantine/core";
import { IconUpload } from "@tabler/icons-react";
import { clientApi } from "@homarr/api/client";
import { revalidatePathActionAsync } from "@homarr/common/client";
import type { MaybePromise } from "@homarr/common/types";
import { showErrorNotification, showSuccessNotification } from "@homarr/notifications";
import { useI18n } from "@homarr/translation/client";
import { supportedMediaUploadFormats } from "@homarr/validation";
export const UploadMedia = () => {
export const UploadMediaButton = () => {
const t = useI18n();
const onSettledAsync = async () => {
await revalidatePathActionAsync("/manage/medias");
};
return (
<UploadMedia onSettled={onSettledAsync}>
{({ onClick, loading }) => (
<Button onClick={onClick} loading={loading} rightSection={<IconUpload size={16} stroke={1.5} />}>
{t("media.action.upload.label")}
</Button>
)}
</UploadMedia>
);
};
interface UploadMediaProps {
children: (props: { onClick: () => void; loading: boolean }) => JSX.Element;
onSettled?: () => MaybePromise<void>;
onSuccess?: (media: { id: string; url: string }) => MaybePromise<void>;
}
export const UploadMedia = ({ children, onSettled, onSuccess }: UploadMediaProps) => {
const t = useI18n();
const { mutateAsync, isPending } = clientApi.media.uploadMedia.useMutation();
@@ -18,10 +43,14 @@ export const UploadMedia = () => {
const formData = new FormData();
formData.append("file", file);
await mutateAsync(formData, {
onSuccess() {
async onSuccess(mediaId) {
showSuccessNotification({
message: t("media.action.upload.notification.success.message"),
});
await onSuccess?.({
id: mediaId,
url: `/api/user-medias/${mediaId}`,
});
},
onError() {
showErrorNotification({
@@ -29,18 +58,14 @@ export const UploadMedia = () => {
});
},
async onSettled() {
await revalidatePathActionAsync("/manage/medias");
await onSettled?.();
},
});
};
return (
<FileButton onChange={handleFileUploadAsync} accept={supportedMediaUploadFormats.join(",")}>
{({ onClick }) => (
<Button onClick={onClick} loading={isPending} rightSection={<IconUpload size={16} stroke={1.5} />}>
{t("media.action.upload.label")}
</Button>
)}
{({ onClick }) => children({ onClick, loading: isPending })}
</FileButton>
);
};

View File

@@ -16,7 +16,7 @@ import { DynamicBreadcrumb } from "~/components/navigation/dynamic-breadcrumb";
import { CopyMedia } from "./_actions/copy-media";
import { DeleteMedia } from "./_actions/delete-media";
import { IncludeFromAllUsersSwitch } from "./_actions/show-all";
import { UploadMedia } from "./_actions/upload-media";
import { UploadMediaButton } from "./_actions/upload-media";
const searchParamsSchema = z.object({
search: z.string().optional(),
@@ -61,7 +61,7 @@ export default async function GroupsListPage(props: MediaListPageProps) {
)}
</Group>
{session.user.permissions.includes("media-upload") && <UploadMedia />}
{session.user.permissions.includes("media-upload") && <UploadMediaButton />}
</Group>
<Table striped highlightOnHover>
<TableThead>