fix(boards): add missing upload button for background in settings (#2853)
This commit is contained in:
@@ -1,13 +1,15 @@
|
|||||||
"use client";
|
"use client";
|
||||||
|
|
||||||
import { Autocomplete, Button, Center, Grid, Group, Popover, Stack, Text } from "@mantine/core";
|
import { startTransition } from "react";
|
||||||
|
import { ActionIcon, Autocomplete, Button, Center, Grid, Group, Popover, Stack, Text } from "@mantine/core";
|
||||||
import { useDebouncedValue } from "@mantine/hooks";
|
import { useDebouncedValue } from "@mantine/hooks";
|
||||||
import { IconPhotoOff } from "@tabler/icons-react";
|
import { IconPhotoOff, IconUpload } from "@tabler/icons-react";
|
||||||
|
|
||||||
import { clientApi } from "@homarr/api/client";
|
import { clientApi } from "@homarr/api/client";
|
||||||
import { useSession } from "@homarr/auth/client";
|
import { useSession } from "@homarr/auth/client";
|
||||||
import { backgroundImageAttachments, backgroundImageRepeats, backgroundImageSizes } from "@homarr/definitions";
|
import { backgroundImageAttachments, backgroundImageRepeats, backgroundImageSizes } from "@homarr/definitions";
|
||||||
import { useZodForm } from "@homarr/form";
|
import { useZodForm } from "@homarr/form";
|
||||||
|
import { UploadMedia } from "@homarr/forms-collection";
|
||||||
import type { TranslationObject } from "@homarr/translation";
|
import type { TranslationObject } from "@homarr/translation";
|
||||||
import { useI18n } from "@homarr/translation/client";
|
import { useI18n } from "@homarr/translation/client";
|
||||||
import type { SelectItemWithDescriptionBadge } from "@homarr/ui";
|
import type { SelectItemWithDescriptionBadge } from "@homarr/ui";
|
||||||
@@ -62,58 +64,76 @@ export const BackgroundSettingsContent = ({ board }: Props) => {
|
|||||||
<Stack>
|
<Stack>
|
||||||
<Grid>
|
<Grid>
|
||||||
<Grid.Col span={12}>
|
<Grid.Col span={12}>
|
||||||
<Autocomplete
|
<Group wrap="nowrap" gap="xs" w="100%" align="start">
|
||||||
leftSection={
|
<Autocomplete
|
||||||
form.values.backgroundImageUrl &&
|
flex={1}
|
||||||
form.values.backgroundImageUrl.trim().length >= 2 && (
|
leftSection={
|
||||||
<Popover width={300} withArrow>
|
form.values.backgroundImageUrl &&
|
||||||
<Popover.Target>
|
form.values.backgroundImageUrl.trim().length >= 2 && (
|
||||||
<Center h="100%">
|
<Popover width={300} withArrow>
|
||||||
<ImagePreview src={form.values.backgroundImageUrl} w={20} h={20} />
|
<Popover.Target>
|
||||||
</Center>
|
<Center h="100%">
|
||||||
</Popover.Target>
|
<ImagePreview src={form.values.backgroundImageUrl} w={20} h={20} />
|
||||||
<Popover.Dropdown>
|
</Center>
|
||||||
<ImagePreview src={form.values.backgroundImageUrl} w="100%" />
|
</Popover.Target>
|
||||||
</Popover.Dropdown>
|
<Popover.Dropdown>
|
||||||
</Popover>
|
<ImagePreview src={form.values.backgroundImageUrl} w="100%" />
|
||||||
)
|
</Popover.Dropdown>
|
||||||
}
|
</Popover>
|
||||||
// We filter it on the server
|
)
|
||||||
filter={({ options }) => options}
|
}
|
||||||
label={t("board.field.backgroundImageUrl.label")}
|
// We filter it on the server
|
||||||
placeholder={`${t("board.field.backgroundImageUrl.placeholder")}...`}
|
filter={({ options }) => options}
|
||||||
renderOption={({ option }) => {
|
label={t("board.field.backgroundImageUrl.label")}
|
||||||
const current = imageMap.get(option.value);
|
placeholder={`${t("board.field.backgroundImageUrl.placeholder")}...`}
|
||||||
if (!current) return null;
|
renderOption={({ option }) => {
|
||||||
|
const current = imageMap.get(option.value);
|
||||||
|
if (!current) return null;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Group gap="sm">
|
<Group gap="sm">
|
||||||
<ImagePreview src={option.value} w={20} h={20} />
|
<ImagePreview src={option.value} w={20} h={20} />
|
||||||
<Stack gap={0}>
|
<Stack gap={0}>
|
||||||
<Text size="sm">{current.name}</Text>
|
<Text size="sm">{current.name}</Text>
|
||||||
<Text size="xs" c="dimmed">
|
<Text size="xs" c="dimmed">
|
||||||
{option.value}
|
{option.value}
|
||||||
</Text>
|
</Text>
|
||||||
</Stack>
|
</Stack>
|
||||||
</Group>
|
</Group>
|
||||||
);
|
);
|
||||||
}}
|
}}
|
||||||
data={[
|
data={[
|
||||||
{
|
{
|
||||||
group: t("board.field.backgroundImageUrl.group.your"),
|
group: t("board.field.backgroundImageUrl.group.your"),
|
||||||
items: images
|
items: images
|
||||||
.filter((media) => media.creatorId === session?.user.id)
|
.filter((media) => media.creatorId === session?.user.id)
|
||||||
.map((media) => `/api/user-medias/${media.id}`),
|
.map((media) => `/api/user-medias/${media.id}`),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
group: t("board.field.backgroundImageUrl.group.other"),
|
group: t("board.field.backgroundImageUrl.group.other"),
|
||||||
items: images
|
items: images
|
||||||
.filter((media) => media.creatorId !== session?.user.id)
|
.filter((media) => media.creatorId !== session?.user.id)
|
||||||
.map((media) => `/api/user-medias/${media.id}`),
|
.map((media) => `/api/user-medias/${media.id}`),
|
||||||
},
|
},
|
||||||
]}
|
]}
|
||||||
{...form.getInputProps("backgroundImageUrl")}
|
{...form.getInputProps("backgroundImageUrl")}
|
||||||
/>
|
/>
|
||||||
|
{session?.user.permissions.includes("media-upload") && (
|
||||||
|
<UploadMedia
|
||||||
|
onSuccess={({ url }) =>
|
||||||
|
startTransition(() => {
|
||||||
|
form.setFieldValue("backgroundImageUrl", url);
|
||||||
|
})
|
||||||
|
}
|
||||||
|
>
|
||||||
|
{({ onClick, loading }) => (
|
||||||
|
<ActionIcon onClick={onClick} loading={loading} mt={24} size={36} variant="default">
|
||||||
|
<IconUpload size={16} stroke={1.5} />
|
||||||
|
</ActionIcon>
|
||||||
|
)}
|
||||||
|
</UploadMedia>
|
||||||
|
)}
|
||||||
|
</Group>
|
||||||
</Grid.Col>
|
</Grid.Col>
|
||||||
<Grid.Col span={12}>
|
<Grid.Col span={12}>
|
||||||
<SelectWithDescriptionBadge
|
<SelectWithDescriptionBadge
|
||||||
|
|||||||
Reference in New Issue
Block a user