feat: board settings (#137)
* refactor: improve user feedback for general board settings section * wip: add board settings for background and colors, move danger zone to own file, refactor code * feat: add shade selector * feat: add slider for opacity * fix: issue with invalid hex values for color preview * refactor: add shared mutation hook for saving partial board settings with invalidate query * fix: add cleanup for not applied changes to logo and page title * feat: add layout settings * feat: add empty custom css section to board settings * refactor: improve layout of board logo on mobile * feat: add theme provider for board colors * refactor: add auto contrast for better contrast of buttons with low primary shade * feat: add background for boards * feat: add opacity for boards * feat: add rename board * feat: add visibility and delete of board settings * fix: issue that wrong data is updated with update board method * refactor: improve danger zone button placement for mobile * fix: board not revalidated when already in boards layout * refactor: improve board color preview * refactor: change save button color to teal, add placeholders for general board settings * chore: update initial migration * refactor: remove unnecessary div * chore: address pull request feedback * fix: ci issues * fix: deepsource issues * chore: address pull request feedback * fix: formatting issue * chore: address pull request feedback
This commit is contained in:
@@ -1,7 +1,15 @@
|
||||
import { z } from "zod";
|
||||
|
||||
import {
|
||||
backgroundImageAttachments,
|
||||
backgroundImageRepeats,
|
||||
backgroundImageSizes,
|
||||
} from "@homarr/definitions";
|
||||
|
||||
import { commonItemSchema, createSectionSchema } from "./shared";
|
||||
|
||||
const hexColorSchema = z.string().regex(/^#[0-9A-Fa-f]{6}$/);
|
||||
|
||||
const boardNameSchema = z
|
||||
.string()
|
||||
.min(1)
|
||||
@@ -12,36 +20,56 @@ const byNameSchema = z.object({
|
||||
name: boardNameSchema,
|
||||
});
|
||||
|
||||
const saveGeneralSettingsSchema = z.object({
|
||||
pageTitle: z
|
||||
.string()
|
||||
.nullable()
|
||||
.transform((value) => (value?.trim().length === 0 ? null : value)),
|
||||
metaTitle: z
|
||||
.string()
|
||||
.nullable()
|
||||
.transform((value) => (value?.trim().length === 0 ? null : value)),
|
||||
logoImageUrl: z
|
||||
.string()
|
||||
.nullable()
|
||||
.transform((value) => (value?.trim().length === 0 ? null : value)),
|
||||
faviconImageUrl: z
|
||||
.string()
|
||||
.nullable()
|
||||
.transform((value) => (value?.trim().length === 0 ? null : value)),
|
||||
boardId: z.string(),
|
||||
const renameSchema = z.object({
|
||||
id: z.string(),
|
||||
name: boardNameSchema,
|
||||
});
|
||||
|
||||
const changeVisibilitySchema = z.object({
|
||||
id: z.string(),
|
||||
visibility: z.enum(["public", "private"]),
|
||||
});
|
||||
|
||||
const trimmedNullableString = z
|
||||
.string()
|
||||
.nullable()
|
||||
.transform((value) => (value?.trim().length === 0 ? null : value));
|
||||
|
||||
const savePartialSettingsSchema = z
|
||||
.object({
|
||||
pageTitle: trimmedNullableString,
|
||||
metaTitle: trimmedNullableString,
|
||||
logoImageUrl: trimmedNullableString,
|
||||
faviconImageUrl: trimmedNullableString,
|
||||
backgroundImageUrl: trimmedNullableString,
|
||||
backgroundImageAttachment: z.enum(backgroundImageAttachments.values),
|
||||
backgroundImageRepeat: z.enum(backgroundImageRepeats.values),
|
||||
backgroundImageSize: z.enum(backgroundImageSizes.values),
|
||||
primaryColor: hexColorSchema,
|
||||
secondaryColor: hexColorSchema,
|
||||
opacity: z.number().min(0).max(100),
|
||||
customCss: z.string().max(16384),
|
||||
columnCount: z.number().min(1).max(24),
|
||||
})
|
||||
.partial()
|
||||
.and(
|
||||
z.object({
|
||||
id: z.string(),
|
||||
}),
|
||||
);
|
||||
|
||||
const saveSchema = z.object({
|
||||
boardId: z.string(),
|
||||
id: z.string(),
|
||||
sections: z.array(createSectionSchema(commonItemSchema)),
|
||||
});
|
||||
|
||||
const createSchema = z.object({ name: z.string() });
|
||||
const createSchema = z.object({ name: boardNameSchema });
|
||||
|
||||
export const boardSchemas = {
|
||||
byName: byNameSchema,
|
||||
saveGeneralSettings: saveGeneralSettingsSchema,
|
||||
savePartialSettings: savePartialSettingsSchema,
|
||||
save: saveSchema,
|
||||
create: createSchema,
|
||||
rename: renameSchema,
|
||||
changeVisibility: changeVisibilitySchema,
|
||||
};
|
||||
|
||||
@@ -48,21 +48,6 @@ const createEmptySchema = <TItemSchema extends z.ZodTypeAny>(
|
||||
items: z.array(itemSchema),
|
||||
});
|
||||
|
||||
const createSidebarSchema = <TItemSchema extends z.ZodTypeAny>(
|
||||
itemSchema: TItemSchema,
|
||||
) =>
|
||||
z.object({
|
||||
id: z.string(),
|
||||
kind: z.literal("sidebar"),
|
||||
position: z.union([z.literal(0), z.literal(1)]),
|
||||
items: z.array(itemSchema),
|
||||
});
|
||||
|
||||
export const createSectionSchema = <TItemSchema extends z.ZodTypeAny>(
|
||||
itemSchema: TItemSchema,
|
||||
) =>
|
||||
z.union([
|
||||
createCategorySchema(itemSchema),
|
||||
createEmptySchema(itemSchema),
|
||||
createSidebarSchema(itemSchema),
|
||||
]);
|
||||
) => z.union([createCategorySchema(itemSchema), createEmptySchema(itemSchema)]);
|
||||
|
||||
Reference in New Issue
Block a user