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
+15 -8
View File
@@ -15,7 +15,8 @@ import {
import { Input } from '@/components/ui/input';
import { Label } from '@/components/ui/label';
import AppLayout from '@/layouts/AppLayout.vue';
import { index, show } from '@/routes/projects/index';
import { index } from '@/routes/projects/index';
import { index as boardIndex } from '@/routes/projects/board';
import {
board as boardSettings,
general as generalSettings,
@@ -35,7 +36,7 @@ const breadcrumbs: BreadcrumbItem[] = [
},
{
title: props.project.name,
href: show(props.project.id),
href: boardIndex(props.project.id),
},
{
title: 'Board settings',
@@ -79,11 +80,15 @@ const statusAllowsTarget = (
</script>
<template>
<AppLayout :breadcrumbs="breadcrumbs" :project="project">
<Head :title="`${project.name} board settings`" />
<component
:is="embedded ? 'div' : AppLayout"
v-bind="embedded ? {} : { breadcrumbs, project }"
>
<Head v-if="!embedded" :title="`${project.name} board settings`" />
<div class="app-page">
<div :class="embedded ? 'space-y-6' : 'app-page'">
<div
v-if="!embedded"
class="flex flex-col gap-4 sm:flex-row sm:items-start sm:justify-between"
>
<div class="space-y-3">
@@ -126,12 +131,14 @@ const statusAllowsTarget = (
</Button>
<Button as-child variant="outline">
<Link :href="show(project.id)">Back to project</Link>
<Link :href="boardIndex(project.id)"
>Back to project</Link
>
</Button>
</div>
</div>
<div v-if="status" class="status-success">
<div v-if="!embedded && status" class="status-success">
{{ status }}
</div>
@@ -684,5 +691,5 @@ const statusAllowsTarget = (
</Card>
</div>
</div>
</AppLayout>
</component>
</template>
@@ -15,7 +15,8 @@ import {
import { Input } from '@/components/ui/input';
import { Label } from '@/components/ui/label';
import AppLayout from '@/layouts/AppLayout.vue';
import { index, show } from '@/routes/projects/index';
import { index } from '@/routes/projects/index';
import { index as boardIndex } from '@/routes/projects/board';
import {
board as boardSettings,
general as generalSettings,
@@ -35,7 +36,7 @@ const breadcrumbs: BreadcrumbItem[] = [
},
{
title: props.project.name,
href: show(props.project.id),
href: boardIndex(props.project.id),
},
{
title: 'General settings',
@@ -122,11 +123,15 @@ const submitDelete = (): void => {
</script>
<template>
<AppLayout :breadcrumbs="breadcrumbs" :project="project">
<Head :title="`${project.name} general settings`" />
<component
:is="embedded ? 'div' : AppLayout"
v-bind="embedded ? {} : { breadcrumbs, project }"
>
<Head v-if="!embedded" :title="`${project.name} general settings`" />
<div class="app-page">
<div :class="embedded ? 'space-y-6' : 'app-page'">
<div
v-if="!embedded"
class="flex flex-col gap-4 sm:flex-row sm:items-start sm:justify-between"
>
<div class="space-y-3">
@@ -165,12 +170,14 @@ const submitDelete = (): void => {
</Button>
<Button as-child variant="outline">
<Link :href="show(project.id)">Back to project</Link>
<Link :href="boardIndex(project.id)"
>Back to project</Link
>
</Button>
</div>
</div>
<div v-if="status" class="status-success">
<div v-if="!embedded && status" class="status-success">
{{ status }}
</div>
@@ -477,5 +484,5 @@ const submitDelete = (): void => {
</CardContent>
</Card>
</div>
</AppLayout>
</component>
</template>
@@ -15,7 +15,8 @@ import {
import { Input } from '@/components/ui/input';
import { Label } from '@/components/ui/label';
import AppLayout from '@/layouts/AppLayout.vue';
import { index, show } from '@/routes/projects/index';
import { index } from '@/routes/projects/index';
import { index as boardIndex } from '@/routes/projects/board';
import {
board as boardSettings,
general as generalSettings,
@@ -38,7 +39,7 @@ const breadcrumbs: BreadcrumbItem[] = [
},
{
title: props.project.name,
href: show(props.project.id),
href: boardIndex(props.project.id),
},
{
title: 'Ticket settings',
@@ -51,11 +52,15 @@ const replacementTicketTypes = (ticketTypeId: number) =>
</script>
<template>
<AppLayout :breadcrumbs="breadcrumbs" :project="project">
<Head :title="`${project.name} ticket settings`" />
<component
:is="embedded ? 'div' : AppLayout"
v-bind="embedded ? {} : { breadcrumbs, project }"
>
<Head v-if="!embedded" :title="`${project.name} ticket settings`" />
<div class="app-page">
<div :class="embedded ? 'space-y-6' : 'app-page'">
<div
v-if="!embedded"
class="flex flex-col gap-4 sm:flex-row sm:items-start sm:justify-between"
>
<div class="space-y-3">
@@ -98,13 +103,15 @@ const replacementTicketTypes = (ticketTypeId: number) =>
</Button>
<Button as-child variant="outline">
<Link :href="show(project.id)">Back to project</Link>
<Link :href="boardIndex(project.id)"
>Back to project</Link
>
</Button>
</div>
</div>
<div
v-if="status"
v-if="!embedded && status"
:class="[
'rounded-xl border px-4 py-3 text-sm',
error
@@ -812,5 +819,5 @@ const replacementTicketTypes = (ticketTypeId: number) =>
</Card>
</div>
</div>
</AppLayout>
</component>
</template>
@@ -16,7 +16,8 @@ import {
import { Input } from '@/components/ui/input';
import { Label } from '@/components/ui/label';
import AppLayout from '@/layouts/AppLayout.vue';
import { index, show } from '@/routes/projects/index';
import { index } from '@/routes/projects/index';
import { index as boardIndex } from '@/routes/projects/board';
import {
board as boardSettings,
general as generalSettings,
@@ -26,24 +27,13 @@ import {
} from '@/routes/projects/settings';
import type {
BreadcrumbItem,
NotificationFilterFormState,
NotificationFilterPayload,
ProjectNotificationSettingsPageProps,
} from '@/types';
import type { NotificationActionFilterModel } from '@/types/models/notification-action-filter-model';
import type { NotificationActionModel } from '@/types/models/notification-action-model';
type NotificationFilterFormState = {
attribute: string;
id: string;
operator: string;
value: string;
};
type NotificationFilterPayload = {
attribute: string;
operator: string;
value: string | string[] | null;
};
const props = defineProps<ProjectNotificationSettingsPageProps>();
const defaultCreateChannel =
@@ -79,7 +69,7 @@ const breadcrumbs: BreadcrumbItem[] = [
},
{
title: props.project.name,
href: show(props.project.id),
href: boardIndex(props.project.id),
},
{
title: 'Notification settings',
@@ -252,11 +242,18 @@ const notificationActionTimestamp = (
</script>
<template>
<AppLayout :breadcrumbs="breadcrumbs" :project="project">
<Head :title="`${project.name} notification settings`" />
<component
:is="embedded ? 'div' : AppLayout"
v-bind="embedded ? {} : { breadcrumbs, project }"
>
<Head
v-if="!embedded"
:title="`${project.name} notification settings`"
/>
<div class="app-page">
<div :class="embedded ? 'space-y-6' : 'app-page'">
<div
v-if="!embedded"
class="flex flex-col gap-4 sm:flex-row sm:items-start sm:justify-between"
>
<div class="space-y-3">
@@ -299,12 +296,14 @@ const notificationActionTimestamp = (
</Button>
<Button as-child variant="outline">
<Link :href="show(project.id)">Back to project</Link>
<Link :href="boardIndex(project.id)"
>Back to project</Link
>
</Button>
</div>
</div>
<div v-if="status" class="status-success">
<div v-if="!embedded && status" class="status-success">
{{ status }}
</div>
@@ -1240,5 +1239,5 @@ const notificationActionTimestamp = (
</div>
</div>
</div>
</AppLayout>
</component>
</template>
@@ -16,7 +16,8 @@ import {
import { Label } from '@/components/ui/label';
import AppLayout from '@/layouts/AppLayout.vue';
import { edit as editGitConnections } from '@/routes/git-connections/index';
import { index, show } from '@/routes/projects/index';
import { index } from '@/routes/projects/index';
import { index as boardIndex } from '@/routes/projects/board';
import {
board as boardSettings,
general as generalSettings,
@@ -42,7 +43,7 @@ const breadcrumbs: BreadcrumbItem[] = [
},
{
title: props.project.name,
href: show(props.project.id),
href: boardIndex(props.project.id),
},
{
title: 'Repository settings',
@@ -218,11 +219,15 @@ const submitUpdate = (): void => {
</script>
<template>
<AppLayout :breadcrumbs="breadcrumbs" :project="project">
<Head :title="`${project.name} repository settings`" />
<component
:is="embedded ? 'div' : AppLayout"
v-bind="embedded ? {} : { breadcrumbs, project }"
>
<Head v-if="!embedded" :title="`${project.name} repository settings`" />
<div class="app-page">
<div :class="embedded ? 'space-y-6' : 'app-page'">
<div
v-if="!embedded"
class="flex flex-col gap-4 sm:flex-row sm:items-start sm:justify-between"
>
<div class="space-y-3">
@@ -265,12 +270,14 @@ const submitUpdate = (): void => {
</Button>
<Button as-child variant="outline">
<Link :href="show(project.id)">Back to project</Link>
<Link :href="boardIndex(project.id)"
>Back to project</Link
>
</Button>
</div>
</div>
<div v-if="status" class="status-success">
<div v-if="!embedded && status" class="status-success">
{{ status }}
</div>
@@ -724,5 +731,5 @@ const submitUpdate = (): void => {
</div>
</div>
</div>
</AppLayout>
</component>
</template>