Fix KAN-3 project template flows

This commit is contained in:
2026-09-08 10:25:52 +00:00
parent db8855a056
commit fed6a282a4
13 changed files with 143 additions and 91 deletions
+33 -20
View File
@@ -27,44 +27,57 @@ class CreateProject
{
return DB::transaction(function () use ($attributes, $actor): Project {
$project = Project::query()->create(Arr::only($attributes, ['key', 'name']));
$baseTemplate = $this->createProjectBaseTemplate->handle($project);
$creationMode = Arr::get($attributes, 'creation_mode', 'scratch');
$sourceTemplateId = Arr::get($attributes, 'source_template_id');
$baseTemplate = null;
$sourceTemplate = null;
$project->forceFill([
'project_template_id' => $baseTemplate->id,
])->save();
if ($creationMode === 'template' && $sourceTemplateId !== null) {
$sourceTemplate = ProjectTemplate::query()
->published()
->findOrFail((int) $sourceTemplateId);
$project->forceFill([
'project_template_id' => $sourceTemplate->id,
])->save();
} else {
$baseTemplate = $this->createProjectBaseTemplate->handle($project);
$project->forceFill([
'project_template_id' => $baseTemplate->id,
])->save();
}
$project = $project->fresh() ?? $project;
$this->initializeProjectTicketMetadata->handle($project);
$this->permissionService->grant($actor, Permission::ProjectAdmin, $project);
$creationMode = $attributes['creation_mode'] ?? 'scratch';
if ($creationMode === 'duplicate' && isset($attributes['source_project_id'])) {
$sourceProject = Project::query()->findOrFail((int) $attributes['source_project_id']);
if ($creationMode === 'duplicate' && Arr::get($attributes, 'source_project_id') !== null) {
$sourceProject = Project::query()->findOrFail((int) Arr::get($attributes, 'source_project_id'));
$this->duplicateProjectConfiguration->handle(
$sourceProject,
$project,
array_values($attributes['copy_areas'] ?? []),
array_values(Arr::get($attributes, 'copy_areas', [])),
);
}
if ($creationMode === 'template' && isset($attributes['source_template_id'])) {
$template = ProjectTemplate::query()->findOrFail((int) $attributes['source_template_id']);
if ($creationMode === 'template' && $sourceTemplate !== null) {
$this->duplicateProjectConfiguration->apply(
$project,
$template->configuration_snapshot ?? [],
$project->fresh() ?? $project,
$sourceTemplate->configuration_snapshot ?? [],
);
}
$baseTemplate->forceFill([
'configuration_snapshot' => $this->duplicateProjectConfiguration->export(
$project->fresh() ?? $project,
DuplicateProjectConfiguration::copyableAreas(),
),
])->save();
if ($baseTemplate !== null) {
$baseTemplate->forceFill([
'configuration_snapshot' => $this->duplicateProjectConfiguration->export(
$project->fresh() ?? $project,
DuplicateProjectConfiguration::copyableAreas(),
),
])->save();
}
return $project->fresh() ?? $project;
});
@@ -69,7 +69,7 @@ class ResolveProjectTemplateState
'effectiveConfiguration' => array_replace($templateConfiguration, array_intersect_key($currentConfiguration, $overriddenAreaValues)),
'inheritedAreas' => $inheritedAreas,
'inheritedConfiguration' => array_intersect_key($templateConfiguration, $inheritedAreaValues),
'inheritsFromTemplate' => true,
'inheritsFromTemplate' => $projectTemplate->is_published,
'overriddenAreas' => $overriddenAreas,
'overriddenConfiguration' => array_intersect_key($currentConfiguration, $overriddenAreaValues),
'templateConfiguration' => $templateConfiguration,
+8 -40
View File
@@ -59,83 +59,51 @@ class Project extends Model
public function boardColumns(): HasMany
{
return $this->hasMany(
BoardColumn::class,
$this->project_template_id === null ? 'project_id' : 'project_template_id',
$this->project_template_id === null ? 'id' : 'project_template_id',
)
return $this->hasMany(BoardColumn::class)
->orderBy('position');
}
public function ticketFieldDefinitions(): HasMany
{
return $this->hasMany(
TicketFieldDefinition::class,
$this->project_template_id === null ? 'project_id' : 'project_template_id',
$this->project_template_id === null ? 'id' : 'project_template_id',
)
return $this->hasMany(TicketFieldDefinition::class)
->orderBy('position');
}
public function ticketPriorities(): HasMany
{
return $this->hasMany(
TicketPriority::class,
$this->project_template_id === null ? 'project_id' : 'project_template_id',
$this->project_template_id === null ? 'id' : 'project_template_id',
)
return $this->hasMany(TicketPriority::class)
->orderBy('position');
}
public function ticketLinkTypes(): HasMany
{
return $this->hasMany(
TicketLinkType::class,
$this->project_template_id === null ? 'project_id' : 'project_template_id',
$this->project_template_id === null ? 'id' : 'project_template_id',
)
return $this->hasMany(TicketLinkType::class)
->orderBy('position');
}
public function ticketStatuses(): HasMany
{
return $this->hasMany(
TicketStatus::class,
$this->project_template_id === null ? 'project_id' : 'project_template_id',
$this->project_template_id === null ? 'id' : 'project_template_id',
)
return $this->hasMany(TicketStatus::class)
->orderBy('board_column_id')
->orderBy('position');
}
public function ticketTypes(): HasMany
{
return $this->hasMany(
TicketType::class,
$this->project_template_id === null ? 'project_id' : 'project_template_id',
$this->project_template_id === null ? 'id' : 'project_template_id',
)
return $this->hasMany(TicketType::class)
->orderBy('position');
}
public function repositoryConnections(): HasMany
{
return $this->hasMany(
RepositoryConnection::class,
$this->project_template_id === null ? 'project_id' : 'project_template_id',
$this->project_template_id === null ? 'id' : 'project_template_id',
)
return $this->hasMany(RepositoryConnection::class)
->orderBy('provider')
->orderBy('repository_full_name');
}
public function notificationActions(): HasMany
{
return $this->hasMany(
NotificationAction::class,
$this->project_template_id === null ? 'project_id' : 'project_template_id',
$this->project_template_id === null ? 'id' : 'project_template_id',
)
return $this->hasMany(NotificationAction::class)
->orderBy('name')
->orderBy('id');
}