feat: add domains, ideas, layouts, widgets API modules
- Add DomainsModule with full CRUD, search, and activity logging - Add IdeasModule with quick capture endpoint - Add LayoutsModule for user dashboard layouts - Add WidgetsModule for widget definitions (read-only) - Update ActivityService with domain/idea logging methods - Register all new modules in AppModule
This commit is contained in:
22
apps/api/src/ideas/dto/capture-idea.dto.ts
Normal file
22
apps/api/src/ideas/dto/capture-idea.dto.ts
Normal file
@@ -0,0 +1,22 @@
|
||||
import {
|
||||
IsString,
|
||||
IsOptional,
|
||||
MinLength,
|
||||
MaxLength,
|
||||
} from "class-validator";
|
||||
|
||||
/**
|
||||
* DTO for quick capturing ideas with minimal fields
|
||||
* Intended for rapid idea capture without complex categorization
|
||||
*/
|
||||
export class CaptureIdeaDto {
|
||||
@IsString({ message: "content must be a string" })
|
||||
@MinLength(1, { message: "content must not be empty" })
|
||||
@MaxLength(50000, { message: "content must not exceed 50000 characters" })
|
||||
content!: string;
|
||||
|
||||
@IsOptional()
|
||||
@IsString({ message: "title must be a string" })
|
||||
@MaxLength(500, { message: "title must not exceed 500 characters" })
|
||||
title?: string;
|
||||
}
|
||||
56
apps/api/src/ideas/dto/create-idea.dto.ts
Normal file
56
apps/api/src/ideas/dto/create-idea.dto.ts
Normal file
@@ -0,0 +1,56 @@
|
||||
import { IdeaStatus, TaskPriority } from "@prisma/client";
|
||||
import {
|
||||
IsString,
|
||||
IsOptional,
|
||||
IsEnum,
|
||||
IsArray,
|
||||
IsUUID,
|
||||
IsObject,
|
||||
MinLength,
|
||||
MaxLength,
|
||||
} from "class-validator";
|
||||
|
||||
/**
|
||||
* DTO for creating a new idea
|
||||
*/
|
||||
export class CreateIdeaDto {
|
||||
@IsOptional()
|
||||
@IsString({ message: "title must be a string" })
|
||||
@MaxLength(500, { message: "title must not exceed 500 characters" })
|
||||
title?: string;
|
||||
|
||||
@IsString({ message: "content must be a string" })
|
||||
@MinLength(1, { message: "content must not be empty" })
|
||||
@MaxLength(50000, { message: "content must not exceed 50000 characters" })
|
||||
content!: string;
|
||||
|
||||
@IsOptional()
|
||||
@IsUUID("4", { message: "domainId must be a valid UUID" })
|
||||
domainId?: string;
|
||||
|
||||
@IsOptional()
|
||||
@IsUUID("4", { message: "projectId must be a valid UUID" })
|
||||
projectId?: string;
|
||||
|
||||
@IsOptional()
|
||||
@IsEnum(IdeaStatus, { message: "status must be a valid IdeaStatus" })
|
||||
status?: IdeaStatus;
|
||||
|
||||
@IsOptional()
|
||||
@IsEnum(TaskPriority, { message: "priority must be a valid TaskPriority" })
|
||||
priority?: TaskPriority;
|
||||
|
||||
@IsOptional()
|
||||
@IsString({ message: "category must be a string" })
|
||||
@MaxLength(100, { message: "category must not exceed 100 characters" })
|
||||
category?: string;
|
||||
|
||||
@IsOptional()
|
||||
@IsArray({ message: "tags must be an array" })
|
||||
@IsString({ each: true, message: "each tag must be a string" })
|
||||
tags?: string[];
|
||||
|
||||
@IsOptional()
|
||||
@IsObject({ message: "metadata must be an object" })
|
||||
metadata?: Record<string, unknown>;
|
||||
}
|
||||
4
apps/api/src/ideas/dto/index.ts
Normal file
4
apps/api/src/ideas/dto/index.ts
Normal file
@@ -0,0 +1,4 @@
|
||||
export { CreateIdeaDto } from "./create-idea.dto";
|
||||
export { CaptureIdeaDto } from "./capture-idea.dto";
|
||||
export { UpdateIdeaDto } from "./update-idea.dto";
|
||||
export { QueryIdeasDto } from "./query-ideas.dto";
|
||||
52
apps/api/src/ideas/dto/query-ideas.dto.ts
Normal file
52
apps/api/src/ideas/dto/query-ideas.dto.ts
Normal file
@@ -0,0 +1,52 @@
|
||||
import { IdeaStatus } from "@prisma/client";
|
||||
import {
|
||||
IsUUID,
|
||||
IsOptional,
|
||||
IsEnum,
|
||||
IsInt,
|
||||
Min,
|
||||
Max,
|
||||
IsString,
|
||||
} from "class-validator";
|
||||
import { Type } from "class-transformer";
|
||||
|
||||
/**
|
||||
* DTO for querying ideas with filters and pagination
|
||||
*/
|
||||
export class QueryIdeasDto {
|
||||
@IsUUID("4", { message: "workspaceId must be a valid UUID" })
|
||||
workspaceId!: string;
|
||||
|
||||
@IsOptional()
|
||||
@IsEnum(IdeaStatus, { message: "status must be a valid IdeaStatus" })
|
||||
status?: IdeaStatus;
|
||||
|
||||
@IsOptional()
|
||||
@IsUUID("4", { message: "domainId must be a valid UUID" })
|
||||
domainId?: string;
|
||||
|
||||
@IsOptional()
|
||||
@IsUUID("4", { message: "projectId must be a valid UUID" })
|
||||
projectId?: string;
|
||||
|
||||
@IsOptional()
|
||||
@IsString({ message: "category must be a string" })
|
||||
category?: string;
|
||||
|
||||
@IsOptional()
|
||||
@IsString({ message: "search must be a string" })
|
||||
search?: string;
|
||||
|
||||
@IsOptional()
|
||||
@Type(() => Number)
|
||||
@IsInt({ message: "page must be an integer" })
|
||||
@Min(1, { message: "page must be at least 1" })
|
||||
page?: number;
|
||||
|
||||
@IsOptional()
|
||||
@Type(() => Number)
|
||||
@IsInt({ message: "limit must be an integer" })
|
||||
@Min(1, { message: "limit must be at least 1" })
|
||||
@Max(100, { message: "limit must not exceed 100" })
|
||||
limit?: number;
|
||||
}
|
||||
58
apps/api/src/ideas/dto/update-idea.dto.ts
Normal file
58
apps/api/src/ideas/dto/update-idea.dto.ts
Normal file
@@ -0,0 +1,58 @@
|
||||
import { IdeaStatus, TaskPriority } from "@prisma/client";
|
||||
import {
|
||||
IsString,
|
||||
IsOptional,
|
||||
IsEnum,
|
||||
IsArray,
|
||||
IsUUID,
|
||||
IsObject,
|
||||
MinLength,
|
||||
MaxLength,
|
||||
} from "class-validator";
|
||||
|
||||
/**
|
||||
* DTO for updating an existing idea
|
||||
* All fields are optional to support partial updates
|
||||
*/
|
||||
export class UpdateIdeaDto {
|
||||
@IsOptional()
|
||||
@IsString({ message: "title must be a string" })
|
||||
@MaxLength(500, { message: "title must not exceed 500 characters" })
|
||||
title?: string;
|
||||
|
||||
@IsOptional()
|
||||
@IsString({ message: "content must be a string" })
|
||||
@MinLength(1, { message: "content must not be empty" })
|
||||
@MaxLength(50000, { message: "content must not exceed 50000 characters" })
|
||||
content?: string;
|
||||
|
||||
@IsOptional()
|
||||
@IsUUID("4", { message: "domainId must be a valid UUID" })
|
||||
domainId?: string;
|
||||
|
||||
@IsOptional()
|
||||
@IsUUID("4", { message: "projectId must be a valid UUID" })
|
||||
projectId?: string;
|
||||
|
||||
@IsOptional()
|
||||
@IsEnum(IdeaStatus, { message: "status must be a valid IdeaStatus" })
|
||||
status?: IdeaStatus;
|
||||
|
||||
@IsOptional()
|
||||
@IsEnum(TaskPriority, { message: "priority must be a valid TaskPriority" })
|
||||
priority?: TaskPriority;
|
||||
|
||||
@IsOptional()
|
||||
@IsString({ message: "category must be a string" })
|
||||
@MaxLength(100, { message: "category must not exceed 100 characters" })
|
||||
category?: string;
|
||||
|
||||
@IsOptional()
|
||||
@IsArray({ message: "tags must be an array" })
|
||||
@IsString({ each: true, message: "each tag must be a string" })
|
||||
tags?: string[];
|
||||
|
||||
@IsOptional()
|
||||
@IsObject({ message: "metadata must be an object" })
|
||||
metadata?: Record<string, unknown>;
|
||||
}
|
||||
Reference in New Issue
Block a user