diff --git a/apps/client/src/features/base/types/base.types.ts b/apps/client/src/features/base/types/base.types.ts index 6dc86024a..391eea5d0 100644 --- a/apps/client/src/features/base/types/base.types.ts +++ b/apps/client/src/features/base/types/base.types.ts @@ -154,6 +154,8 @@ export type SearchSpec = { mode?: 'trgm' | 'fts'; }; +export const NO_VALUE_CHOICE_ID = '__no_value'; + export type ViewConfig = { sorts?: ViewSortConfig[]; filter?: FilterGroup; @@ -161,6 +163,10 @@ export type ViewConfig = { hiddenPropertyIds?: string[]; propertyWidths?: Record; propertyOrder?: string[]; + // Kanban + groupByPropertyId?: string; + hiddenChoiceIds?: string[]; + choiceOrder?: string[]; }; export type IBaseView = { diff --git a/apps/server/src/core/base/base.schemas.ts b/apps/server/src/core/base/base.schemas.ts index 9d06bfa18..5c7dcc10a 100644 --- a/apps/server/src/core/base/base.schemas.ts +++ b/apps/server/src/core/base/base.schemas.ts @@ -410,6 +410,8 @@ const viewFilterGroupSchema: z.ZodType = z.lazy(() => }), ); +export const NO_VALUE_CHOICE_ID = '__no_value'; + export const viewConfigSchema = z .object({ sorts: z.array(viewSortSchema).optional(), @@ -418,6 +420,12 @@ export const viewConfigSchema = z hiddenPropertyIds: z.array(z.uuid()).optional(), propertyWidths: z.record(z.string(), z.number().positive()).optional(), propertyOrder: z.array(z.uuid()).optional(), + // Kanban-only fields. `hiddenChoiceIds` and `choiceOrder` accept + // `z.string()` (not `z.uuid()`) because the NO_VALUE_CHOICE_ID + // sentinel ('__no_value') lives in the same array as choice uuids. + groupByPropertyId: z.uuid().optional(), + hiddenChoiceIds: z.array(z.string()).optional(), + choiceOrder: z.array(z.string()).optional(), }) .passthrough();