feat: overhaul project workspace navigation
linter / quality (pull_request) Successful in 1m28s
tests / ci (8.4) (pull_request) Successful in 1m47s

This commit is contained in:
2026-07-18 17:52:25 +02:00
parent a46695c2eb
commit ff796aa10a
45 changed files with 1790 additions and 995 deletions
@@ -2,8 +2,8 @@
namespace Tests\Feature\Projects;
use App\Actions\ProjectTicketMetadata\InitializeProjectTicketMetadata;
use App\Actions\Projects\DuplicateProjectConfiguration;
use App\Actions\ProjectTicketMetadata\InitializeProjectTicketMetadata;
use App\Models\Project;
use App\Models\ProjectTemplate;
use App\Models\Ticket;
@@ -60,19 +60,23 @@ class ProjectTicketMetadataSettingsControllerTest extends TestCase
$this->syncProjectPermissions($project, $user, ['edit']);
$this->actingAs($user)
->get(route('projects.settings.metadata', $project))
->get(route('projects.settings.index', [
'project' => $project,
'section' => 'metadata',
]))
->assertOk()
->assertInertia(fn (Assert $page) => $page
->component('projects/settings/Metadata')
->component('projects/Settings')
->where('activeSection', 'metadata')
->where('project.show_author', true)
->where('project.show_story_points', false)
->where('ticketTypes.0.name', 'Task')
->where('ticketTypes.1.name', 'Release')
->where('ticketTypes.1.is_parent', true)
->where('ticketTypes.2.name', 'Bug')
->where('ticketLinkTypes.0.label', 'Relates to')
->where('templateState.templateName', 'Issue Tracker Template')
->where('templateState.overriddenAreas.0.value', DuplicateProjectConfiguration::COPY_PROJECT_SETTINGS),
->where('sectionData.ticketTypes.0.name', 'Task')
->where('sectionData.ticketTypes.1.name', 'Release')
->where('sectionData.ticketTypes.1.is_parent', true)
->where('sectionData.ticketTypes.2.name', 'Bug')
->where('sectionData.ticketLinkTypes.0.label', 'Relates to')
->where('sectionData.templateState.templateName', 'Issue Tracker Template')
->where('sectionData.templateState.overriddenAreas.0.value', DuplicateProjectConfiguration::COPY_PROJECT_SETTINGS),
);
}
@@ -91,7 +95,7 @@ class ProjectTicketMetadataSettingsControllerTest extends TestCase
'is_parent' => '1',
'name' => 'Bug',
])
->assertRedirect(route('projects.settings.metadata', $project))
->assertRedirect(route('projects.settings.index', ['project' => $project, 'section' => 'metadata']))
->assertSessionHas('status', 'Bug type was added.');
$this->assertDatabaseHas('ticket_types', [
@@ -124,7 +128,7 @@ class ProjectTicketMetadataSettingsControllerTest extends TestCase
'name' => 'Standard Release',
'position' => 2,
])
->assertRedirect(route('projects.settings.metadata', $project))
->assertRedirect(route('projects.settings.index', ['project' => $project, 'section' => 'metadata']))
->assertSessionHas('status', 'Standard Release type was updated.');
$this->assertDatabaseHas('ticket_types', [
@@ -152,7 +156,7 @@ class ProjectTicketMetadataSettingsControllerTest extends TestCase
'show_author' => false,
'show_story_points' => false,
])
->assertRedirect(route('projects.settings.metadata', $project))
->assertRedirect(route('projects.settings.index', ['project' => $project, 'section' => 'metadata']))
->assertSessionHas('status', 'Settings have been updated.');
$this->assertDatabaseHas('projects', [
@@ -196,7 +200,7 @@ class ProjectTicketMetadataSettingsControllerTest extends TestCase
$this->actingAs($user)
->delete(route('projects.settings.metadata.types.destroy', [$project, $ticketType]))
->assertRedirect(route('projects.settings.metadata', $project))
->assertRedirect(route('projects.settings.index', ['project' => $project, 'section' => 'metadata']))
->assertSessionHas('status', 'The last ticket type cannot be deleted.');
$this->assertDatabaseHas('ticket_types', [
@@ -248,7 +252,7 @@ class ProjectTicketMetadataSettingsControllerTest extends TestCase
->delete(route('projects.settings.metadata.types.destroy', [$project, $taskType]), [
'replacement_ticket_type_id' => $releaseType->id,
])
->assertRedirect(route('projects.settings.metadata', $project))
->assertRedirect(route('projects.settings.index', ['project' => $project, 'section' => 'metadata']))
->assertSessionHas('status', 'Task type was removed.');
$this->assertDatabaseMissing('ticket_types', [
@@ -327,7 +331,7 @@ class ProjectTicketMetadataSettingsControllerTest extends TestCase
->delete(route('projects.settings.metadata.types.destroy', [$project, $releaseType]), [
'replacement_ticket_type_id' => $epicType->id,
])
->assertRedirect(route('projects.settings.metadata', $project))
->assertRedirect(route('projects.settings.index', ['project' => $project, 'section' => 'metadata']))
->assertSessionHas('status', 'Release type was removed.');
$this->assertDatabaseHas('tickets', [
@@ -354,19 +358,19 @@ class ProjectTicketMetadataSettingsControllerTest extends TestCase
->post(route('projects.settings.metadata.priorities.store', $project), [
'name' => 'Low',
])
->assertRedirect(route('projects.settings.metadata', $project));
->assertRedirect(route('projects.settings.index', ['project' => $project, 'section' => 'metadata']));
$this->actingAs($user)
->patch(route('projects.settings.metadata.priorities.update', [$project, $priority]), [
'name' => 'Urgent',
'position' => 2,
])
->assertRedirect(route('projects.settings.metadata', $project))
->assertRedirect(route('projects.settings.index', ['project' => $project, 'section' => 'metadata']))
->assertSessionHas('status', 'Urgent priority was updated.');
$this->actingAs($user)
->delete(route('projects.settings.metadata.priorities.destroy', [$project, $priority]))
->assertRedirect(route('projects.settings.metadata', $project))
->assertRedirect(route('projects.settings.index', ['project' => $project, 'section' => 'metadata']))
->assertSessionHas('status', 'Urgent priority was removed.');
$this->assertDatabaseMissing('ticket_priorities', [
@@ -394,7 +398,7 @@ class ProjectTicketMetadataSettingsControllerTest extends TestCase
'label' => 'Reviewer',
'field_type' => 'user',
])
->assertRedirect(route('projects.settings.metadata', $project))
->assertRedirect(route('projects.settings.index', ['project' => $project, 'section' => 'metadata']))
->assertSessionHas('status', 'Reviewer field was added.');
$this->actingAs($user)
@@ -403,7 +407,7 @@ class ProjectTicketMetadataSettingsControllerTest extends TestCase
'field_type' => 'number',
'position' => 2,
])
->assertRedirect(route('projects.settings.metadata', $project))
->assertRedirect(route('projects.settings.index', ['project' => $project, 'section' => 'metadata']))
->assertSessionHas('status', 'Risk score field was updated.');
$this->assertDatabaseHas('ticket_field_definitions', [
@@ -453,7 +457,7 @@ class ProjectTicketMetadataSettingsControllerTest extends TestCase
'name' => 'Blocks',
'counterpart_name' => 'Blocked by',
])
->assertRedirect(route('projects.settings.metadata', $project))
->assertRedirect(route('projects.settings.index', ['project' => $project, 'section' => 'metadata']))
->assertSessionHas('status', 'Blocks link type was added.');
$this->assertDatabaseHas('ticket_link_types', [
@@ -468,7 +472,7 @@ class ProjectTicketMetadataSettingsControllerTest extends TestCase
'counterpart_name' => 'Required by',
'position' => 2,
])
->assertRedirect(route('projects.settings.metadata', $project))
->assertRedirect(route('projects.settings.index', ['project' => $project, 'section' => 'metadata']))
->assertSessionHas('status', 'Depends on link type was updated.');
$this->assertDatabaseHas('ticket_link_types', [
@@ -479,7 +483,7 @@ class ProjectTicketMetadataSettingsControllerTest extends TestCase
$this->actingAs($user)
->delete(route('projects.settings.metadata.link-types.destroy', [$project, $ticketLinkType]))
->assertRedirect(route('projects.settings.metadata', $project))
->assertRedirect(route('projects.settings.index', ['project' => $project, 'section' => 'metadata']))
->assertSessionHas('status', 'Depends on link type was removed.');
$this->assertDatabaseMissing('ticket_link_types', [