Add 80+ additional icons from FontAwesome (#6803)
* Add 80+ additional icons from FontAwesome * fix: color switch transition, add 6 more icons to fill out grid * Add strict validation for collection icon * fix: Avoid import from app in server
This commit is contained in:
@@ -174,6 +174,7 @@ describe("#collections.move", () => {
|
||||
token: admin.getJwtToken(),
|
||||
id: collection.id,
|
||||
index: "P",
|
||||
icon: "flame",
|
||||
},
|
||||
});
|
||||
const body = await res.json();
|
||||
@@ -181,6 +182,20 @@ describe("#collections.move", () => {
|
||||
expect(body.success).toBe(true);
|
||||
});
|
||||
|
||||
it("should return error when icon is not valid", async () => {
|
||||
const team = await buildTeam();
|
||||
const admin = await buildAdmin({ teamId: team.id });
|
||||
const collection = await buildCollection({ teamId: team.id });
|
||||
const res = await server.post("/api/collections.move", {
|
||||
body: {
|
||||
token: admin.getJwtToken(),
|
||||
id: collection.id,
|
||||
icon: "nonsRence",
|
||||
},
|
||||
});
|
||||
expect(res.status).toEqual(400);
|
||||
});
|
||||
|
||||
it("should return error when index is not valid", async () => {
|
||||
const team = await buildTeam();
|
||||
const admin = await buildAdmin({ teamId: team.id });
|
||||
|
||||
@@ -2,11 +2,20 @@ import isUndefined from "lodash/isUndefined";
|
||||
import { z } from "zod";
|
||||
import { randomElement } from "@shared/random";
|
||||
import { CollectionPermission, FileOperationFormat } from "@shared/types";
|
||||
import { IconLibrary } from "@shared/utils/IconLibrary";
|
||||
import { colorPalette } from "@shared/utils/collections";
|
||||
import { Collection } from "@server/models";
|
||||
import { ValidateColor, ValidateIcon, ValidateIndex } from "@server/validation";
|
||||
import { ValidateColor, ValidateIndex } from "@server/validation";
|
||||
import { BaseSchema } from "../schema";
|
||||
|
||||
function zodEnumFromObjectKeys<
|
||||
TI extends Record<string, any>,
|
||||
R extends string = TI extends Record<infer R, any> ? R : never
|
||||
>(input: TI): z.ZodEnum<[R, ...R[]]> {
|
||||
const [firstKey, ...otherKeys] = Object.keys(input) as [R, ...R[]];
|
||||
return z.enum([firstKey, ...otherKeys]);
|
||||
}
|
||||
|
||||
export const CollectionsCreateSchema = BaseSchema.extend({
|
||||
body: z.object({
|
||||
name: z.string(),
|
||||
@@ -20,12 +29,7 @@ export const CollectionsCreateSchema = BaseSchema.extend({
|
||||
.nullish()
|
||||
.transform((val) => (isUndefined(val) ? null : val)),
|
||||
sharing: z.boolean().default(true),
|
||||
icon: z
|
||||
.string()
|
||||
.max(ValidateIcon.maxLength, {
|
||||
message: `Must be ${ValidateIcon.maxLength} or fewer characters long`,
|
||||
})
|
||||
.optional(),
|
||||
icon: zodEnumFromObjectKeys(IconLibrary.mapping).optional(),
|
||||
sort: z
|
||||
.object({
|
||||
field: z.union([z.literal("title"), z.literal("index")]),
|
||||
@@ -171,12 +175,7 @@ export const CollectionsUpdateSchema = BaseSchema.extend({
|
||||
id: z.string().uuid(),
|
||||
name: z.string().optional(),
|
||||
description: z.string().nullish(),
|
||||
icon: z
|
||||
.string()
|
||||
.max(ValidateIcon.maxLength, {
|
||||
message: `Must be ${ValidateIcon.maxLength} or fewer characters long`,
|
||||
})
|
||||
.nullish(),
|
||||
icon: zodEnumFromObjectKeys(IconLibrary.mapping).nullish(),
|
||||
permission: z.nativeEnum(CollectionPermission).nullish(),
|
||||
color: z
|
||||
.string()
|
||||
|
||||
@@ -246,7 +246,3 @@ export class ValidateColor {
|
||||
public static regex = /(^#[0-9A-F]{6}$)|(^#[0-9A-F]{3}$)/i;
|
||||
public static message = "Must be a hex value (please use format #FFFFFF)";
|
||||
}
|
||||
|
||||
export class ValidateIcon {
|
||||
public static maxLength = 50;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user