feat: start a project from another one's configuration
Creating a project can name one the creator owns or administers: its statuses, transitions, types, areas, custom fields and automation rules are copied once (paused rules stay paused; rules assigning to someone who is not in the new project are left out). GraphQL templateProjectId, REST template (id or key), MCP create_project template, and a select in the web's new-project form. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -55,6 +55,15 @@ export class CreateProjectInput {
|
||||
@IsOptional()
|
||||
@IsBoolean()
|
||||
isPublic?: boolean;
|
||||
|
||||
@Field(() => ID, {
|
||||
nullable: true,
|
||||
description:
|
||||
'A project you own or administer to start from: its statuses, transitions, types, areas, custom fields and automation rules are copied',
|
||||
})
|
||||
@IsOptional()
|
||||
@IsUUID()
|
||||
templateProjectId?: string | null;
|
||||
}
|
||||
|
||||
@InputType()
|
||||
|
||||
@@ -151,7 +151,11 @@ export class ProjectResolver {
|
||||
@CurrentUser() me: User,
|
||||
@Args('input') input: CreateProjectInput,
|
||||
) {
|
||||
return this.projects.create(me.id, input);
|
||||
const { templateProjectId, ...fields } = input;
|
||||
return this.projects.create(me.id, {
|
||||
...fields,
|
||||
templateId: templateProjectId,
|
||||
});
|
||||
}
|
||||
|
||||
@Mutation(() => CommandResultGql)
|
||||
|
||||
@@ -87,10 +87,21 @@ export class CreateProjectDto {
|
||||
@IsOptional()
|
||||
@IsBoolean()
|
||||
isPublic?: boolean;
|
||||
|
||||
@ApiPropertyOptional({
|
||||
type: String,
|
||||
nullable: true,
|
||||
example: 'API',
|
||||
description:
|
||||
'A project you own or administer (id or key) to start from: its statuses, transitions, types, areas, custom fields and automation rules are copied',
|
||||
})
|
||||
@IsOptional()
|
||||
@IsString()
|
||||
template?: string | null;
|
||||
}
|
||||
|
||||
export class UpdateProjectDto extends PartialType(
|
||||
OmitType(CreateProjectDto, ['key'] as const),
|
||||
OmitType(CreateProjectDto, ['key', 'template'] as const),
|
||||
) {
|
||||
@ApiPropertyOptional({
|
||||
description:
|
||||
|
||||
@@ -83,8 +83,12 @@ export class ProjectsController {
|
||||
@ApiOperation({ summary: 'Create a project (you become its owner)' })
|
||||
@ApiCreatedResponse({ type: CommandResultDto })
|
||||
@ApiCommandErrors()
|
||||
create(@CurrentUser() me: User, @Body() body: CreateProjectDto) {
|
||||
return this.projects.create(me.id, body);
|
||||
async create(@CurrentUser() me: User, @Body() body: CreateProjectDto) {
|
||||
const { template, ...fields } = body;
|
||||
return this.projects.create(me.id, {
|
||||
...fields,
|
||||
templateId: template ? await this.refs.projectId(me.id, template) : null,
|
||||
});
|
||||
}
|
||||
|
||||
@Get(':project')
|
||||
|
||||
Reference in New Issue
Block a user