lint fix and formatted
linter / quality (push) Successful in 1m20s
tests / ci (8.4) (push) Successful in 1m20s

This commit is contained in:
2026-04-11 16:37:58 +02:00
parent 23a66852a6
commit e5d11c940b
38 changed files with 339 additions and 261 deletions
+10 -4
View File
@@ -26,11 +26,17 @@ const eslintConfig = [
{ {
ignores: [ ignores: [
'**/dist/**', '**/dist/**',
'vite/**',
'public/**',
'node_modules/**', 'node_modules/**',
'.github/**',
// aus vorheriger .prettierignore '**/*.yml',
'**/*.yaml',
'docker-compose.yml',
'docker/**',
'vendor/**',
'storage/**',
'bootstrap/cache/**',
'public/build/**',
'public/hot',
'resources/js/components/ui/**', 'resources/js/components/ui/**',
'resources/views/mail/**', 'resources/views/mail/**',
], ],
+4 -4
View File
@@ -77,7 +77,7 @@ const rightNavItems: NavItem[] = [
<template> <template>
<div> <div>
<div class="border-b border-sidebar-border/80"> <div class="border-sidebar-border/80 border-b">
<div class="mx-auto flex h-16 items-center px-4 md:max-w-7xl"> <div class="mx-auto flex h-16 items-center px-4 md:max-w-7xl">
<!-- Mobile Menu --> <!-- Mobile Menu -->
<div class="lg:hidden"> <div class="lg:hidden">
@@ -108,7 +108,7 @@ const rightNavItems: NavItem[] = [
v-for="item in mainNavItems" v-for="item in mainNavItems"
:key="item.title" :key="item.title"
:href="item.href" :href="item.href"
class="flex items-center gap-x-3 rounded-lg px-3 py-2 text-sm font-medium hover:bg-accent" class="hover:bg-accent flex items-center gap-x-3 rounded-lg px-3 py-2 text-sm font-medium"
:class=" :class="
whenCurrentUrl( whenCurrentUrl(
item.href, item.href,
@@ -243,7 +243,7 @@ const rightNavItems: NavItem[] = [
<Button <Button
variant="ghost" variant="ghost"
size="icon" size="icon"
class="relative size-10 w-auto rounded-full p-1 focus-within:ring-2 focus-within:ring-primary" class="focus-within:ring-primary relative size-10 w-auto rounded-full p-1 focus-within:ring-2"
> >
<Avatar <Avatar
class="size-8 overflow-hidden rounded-full" class="size-8 overflow-hidden rounded-full"
@@ -271,7 +271,7 @@ const rightNavItems: NavItem[] = [
<div <div
v-if="props.breadcrumbs.length > 1" v-if="props.breadcrumbs.length > 1"
class="flex w-full border-b border-sidebar-border/70" class="border-sidebar-border/70 flex w-full border-b"
> >
<div <div
class="mx-auto flex h-12 w-full items-center justify-start px-4 text-neutral-500 md:max-w-7xl" class="mx-auto flex h-12 w-full items-center justify-start px-4 text-neutral-500 md:max-w-7xl"
+2 -2
View File
@@ -4,12 +4,12 @@ import AppLogoIcon from '@/components/AppLogoIcon.vue';
<template> <template>
<div <div
class="flex aspect-square size-8 items-center justify-center rounded-md bg-sidebar-primary text-sidebar-primary-foreground" class="bg-sidebar-primary text-sidebar-primary-foreground flex aspect-square size-8 items-center justify-center rounded-md"
> >
<AppLogoIcon class="size-5 fill-current text-white dark:text-black" /> <AppLogoIcon class="size-5 fill-current text-white dark:text-black" />
</div> </div>
<div class="ml-1 grid flex-1 text-left text-sm"> <div class="ml-1 grid flex-1 text-left text-sm">
<span class="mb-0.5 truncate leading-tight font-semibold" <span class="mb-0.5 truncate font-semibold leading-tight"
>Laravel Starter Kit</span >Laravel Starter Kit</span
> >
</div> </div>
+1 -1
View File
@@ -15,7 +15,7 @@ withDefaults(
<template> <template>
<header <header
class="flex h-16 shrink-0 items-center gap-2 border-b border-sidebar-border/70 px-6 transition-[width,height] ease-linear group-has-data-[collapsible=icon]/sidebar-wrapper:h-12 md:px-4" class="border-sidebar-border/70 group-has-data-[collapsible=icon]/sidebar-wrapper:h-12 flex h-16 shrink-0 items-center gap-2 border-b px-6 transition-[width,height] ease-linear md:px-4"
> >
<div class="flex items-center gap-2"> <div class="flex items-center gap-2">
<SidebarTrigger class="-ml-1" /> <SidebarTrigger class="-ml-1" />
+1 -1
View File
@@ -22,7 +22,7 @@ const tabs = [
:class="[ :class="[
'flex items-center rounded-md px-3.5 py-1.5 transition-colors', 'flex items-center rounded-md px-3.5 py-1.5 transition-colors',
appearance === value appearance === value
? 'bg-white shadow-xs dark:bg-neutral-700 dark:text-neutral-100' ? 'shadow-xs bg-white dark:bg-neutral-700 dark:text-neutral-100'
: 'text-neutral-500 hover:bg-neutral-200/60 hover:text-black dark:text-neutral-400 dark:hover:bg-neutral-700/60', : 'text-neutral-500 hover:bg-neutral-200/60 hover:text-black dark:text-neutral-400 dark:hover:bg-neutral-700/60',
]" ]"
> >
+1 -1
View File
@@ -21,7 +21,7 @@ withDefaults(defineProps<Props>(), {
> >
{{ title }} {{ title }}
</h2> </h2>
<p v-if="description" class="text-sm text-muted-foreground"> <p v-if="description" class="text-muted-foreground text-sm">
{{ description }} {{ description }}
</p> </p>
</header> </header>
+1 -1
View File
@@ -33,7 +33,7 @@ defineExpose({
@click="showPassword = !showPassword" @click="showPassword = !showPassword"
:class=" :class="
cn( cn(
'absolute inset-y-0 right-0 flex items-center rounded-r-md px-3 text-muted-foreground hover:text-foreground focus-visible:ring-[3px] focus-visible:ring-ring focus-visible:outline-none', 'text-muted-foreground hover:text-foreground focus-visible:ring-ring absolute inset-y-0 right-0 flex items-center rounded-r-md px-3 focus-visible:outline-none focus-visible:ring-[3px]',
) )
" "
:aria-label="showPassword ? 'Hide password' : 'Show password'" :aria-label="showPassword ? 'Hide password' : 'Show password'"
+1 -1
View File
@@ -18,7 +18,7 @@ defineProps<Props>();
:tabindex="tabindex" :tabindex="tabindex"
:method="method" :method="method"
:as="as" :as="as"
class="text-foreground underline decoration-neutral-300 underline-offset-4 transition-colors duration-300 ease-out hover:decoration-current! dark:decoration-neutral-500" class="text-foreground hover:decoration-current! underline decoration-neutral-300 underline-offset-4 transition-colors duration-300 ease-out dark:decoration-neutral-500"
> >
<slot /> <slot />
</Link> </Link>
+4 -4
View File
@@ -13,7 +13,7 @@ defineProps<{
<template> <template>
<ul class="space-y-3"> <ul class="space-y-3">
<li v-for="node in nodes" :key="node.id"> <li v-for="node in nodes" :key="node.id">
<div class="rounded-xl border border-border px-4 py-4"> <div class="border-border rounded-xl border px-4 py-4">
<div class="flex flex-wrap items-center gap-2"> <div class="flex flex-wrap items-center gap-2">
<Link <Link
:href=" :href="
@@ -22,7 +22,7 @@ defineProps<{
ticket: node.id, ticket: node.id,
}) })
" "
class="font-medium text-foreground transition hover:text-primary" class="text-foreground hover:text-primary font-medium transition"
> >
{{ node.ticket_key }} {{ node.ticket_key }}
</Link> </Link>
@@ -32,14 +32,14 @@ defineProps<{
</Badge> </Badge>
</div> </div>
<div class="mt-2 text-sm text-foreground"> <div class="text-foreground mt-2 text-sm">
{{ node.title }} {{ node.title }}
</div> </div>
</div> </div>
<div <div
v-if="node.children.length > 0" v-if="node.children.length > 0"
class="mt-3 border-l border-border pl-4" class="border-border mt-3 border-l pl-4"
> >
<TicketTreeList <TicketTreeList
:nodes="node.children" :nodes="node.children"
@@ -51,7 +51,7 @@ onMounted(async () => {
</CardHeader> </CardHeader>
<CardContent> <CardContent>
<div <div
class="flex flex-col gap-3 select-none sm:flex-row sm:items-center sm:justify-between" class="flex select-none flex-col gap-3 sm:flex-row sm:items-center sm:justify-between"
> >
<Button @click="toggleRecoveryCodesVisibility" class="w-fit"> <Button @click="toggleRecoveryCodesVisibility" class="w-fit">
<component <component
@@ -93,13 +93,13 @@ onMounted(async () => {
<div v-else class="mt-3 space-y-3"> <div v-else class="mt-3 space-y-3">
<div <div
ref="recoveryCodeSectionRef" ref="recoveryCodeSectionRef"
class="grid gap-1 rounded-lg bg-muted p-4 font-mono text-sm" class="bg-muted grid gap-1 rounded-lg p-4 font-mono text-sm"
> >
<div v-if="!recoveryCodesList.length" class="space-y-2"> <div v-if="!recoveryCodesList.length" class="space-y-2">
<div <div
v-for="n in 8" v-for="n in 8"
:key="n" :key="n"
class="h-4 animate-pulse rounded bg-muted-foreground/20" class="bg-muted-foreground/20 h-4 animate-pulse rounded"
></div> ></div>
</div> </div>
<div <div
@@ -110,7 +110,7 @@ onMounted(async () => {
{{ code }} {{ code }}
</div> </div>
</div> </div>
<p class="text-xs text-muted-foreground select-none"> <p class="text-muted-foreground select-none text-xs">
Each recovery code can be used once to access your Each recovery code can be used once to access your
account and will be removed after use. If you need more, account and will be removed after use. If you need more,
click click
+13 -13
View File
@@ -114,10 +114,10 @@ watch(
<DialogContent class="sm:max-w-md"> <DialogContent class="sm:max-w-md">
<DialogHeader class="flex items-center justify-center"> <DialogHeader class="flex items-center justify-center">
<div <div
class="mb-3 w-auto rounded-full border border-border bg-card p-0.5 shadow-sm" class="border-border bg-card mb-3 w-auto rounded-full border p-0.5 shadow-sm"
> >
<div <div
class="relative overflow-hidden rounded-full border border-border bg-muted p-2.5" class="border-border bg-muted relative overflow-hidden rounded-full border p-2.5"
> >
<div <div
class="absolute inset-0 grid grid-cols-5 opacity-50" class="absolute inset-0 grid grid-cols-5 opacity-50"
@@ -125,7 +125,7 @@ watch(
<div <div
v-for="i in 5" v-for="i in 5"
:key="`col-${i}`" :key="`col-${i}`"
class="border-r border-border last:border-r-0" class="border-border border-r last:border-r-0"
/> />
</div> </div>
<div <div
@@ -134,11 +134,11 @@ watch(
<div <div
v-for="i in 5" v-for="i in 5"
:key="`row-${i}`" :key="`row-${i}`"
class="border-b border-border last:border-b-0" class="border-border border-b last:border-b-0"
/> />
</div> </div>
<ScanLine <ScanLine
class="relative z-20 size-6 text-foreground" class="text-foreground relative z-20 size-6"
/> />
</div> </div>
</div> </div>
@@ -158,11 +158,11 @@ watch(
class="relative mx-auto flex max-w-md items-center overflow-hidden" class="relative mx-auto flex max-w-md items-center overflow-hidden"
> >
<div <div
class="relative mx-auto aspect-square w-64 overflow-hidden rounded-lg border border-border" class="border-border relative mx-auto aspect-square w-64 overflow-hidden rounded-lg border"
> >
<div <div
v-if="!qrCodeSvg" v-if="!qrCodeSvg"
class="absolute inset-0 z-10 flex aspect-square h-auto w-full animate-pulse items-center justify-center bg-background" class="bg-background absolute inset-0 z-10 flex aspect-square h-auto w-full animate-pulse items-center justify-center"
> >
<Spinner class="size-6" /> <Spinner class="size-6" />
</div> </div>
@@ -194,9 +194,9 @@ watch(
class="relative flex w-full items-center justify-center" class="relative flex w-full items-center justify-center"
> >
<div <div
class="absolute inset-0 top-1/2 h-px w-full bg-border" class="bg-border absolute inset-0 top-1/2 h-px w-full"
/> />
<span class="relative bg-card px-2 py-1" <span class="bg-card relative px-2 py-1"
>or, enter the code manually</span >or, enter the code manually</span
> >
</div> </div>
@@ -205,11 +205,11 @@ watch(
class="flex w-full items-center justify-center space-x-2" class="flex w-full items-center justify-center space-x-2"
> >
<div <div
class="flex w-full items-stretch overflow-hidden rounded-xl border border-border" class="border-border flex w-full items-stretch overflow-hidden rounded-xl border"
> >
<div <div
v-if="!manualSetupKey" v-if="!manualSetupKey"
class="flex h-full w-full items-center justify-center bg-muted p-3" class="bg-muted flex h-full w-full items-center justify-center p-3"
> >
<Spinner /> <Spinner />
</div> </div>
@@ -218,11 +218,11 @@ watch(
type="text" type="text"
readonly readonly
:value="manualSetupKey" :value="manualSetupKey"
class="h-full w-full bg-background p-3 text-foreground" class="bg-background text-foreground h-full w-full p-3"
/> />
<button <button
@click="copy(manualSetupKey || '')" @click="copy(manualSetupKey || '')"
class="relative block h-auto border-l border-border px-3 hover:bg-muted" class="border-border hover:bg-muted relative block h-auto border-l px-3"
> >
<Check <Check
v-if="copied" v-if="copied"
+1 -1
View File
@@ -31,7 +31,7 @@ const showAvatar = computed(
<div class="grid flex-1 text-left text-sm leading-tight"> <div class="grid flex-1 text-left text-sm leading-tight">
<span class="truncate font-medium">{{ user.name }}</span> <span class="truncate font-medium">{{ user.name }}</span>
<span v-if="showEmail" class="truncate text-xs text-muted-foreground">{{ <span v-if="showEmail" class="text-muted-foreground truncate text-xs">{{
user.email user.email
}}</span> }}</span>
</div> </div>
+2 -2
View File
@@ -18,7 +18,7 @@ defineProps<{
<template> <template>
<div <div
class="flex min-h-svh flex-col items-center justify-center gap-6 bg-muted p-6 md:p-10" class="bg-muted flex min-h-svh flex-col items-center justify-center gap-6 p-6 md:p-10"
> >
<div class="flex w-full max-w-md flex-col gap-6"> <div class="flex w-full max-w-md flex-col gap-6">
<Link <Link
@@ -34,7 +34,7 @@ defineProps<{
<div class="flex flex-col gap-6"> <div class="flex flex-col gap-6">
<Card class="rounded-xl"> <Card class="rounded-xl">
<CardHeader class="px-10 pt-8 pb-0 text-center"> <CardHeader class="px-10 pb-0 pt-8 text-center">
<CardTitle class="text-xl">{{ title }}</CardTitle> <CardTitle class="text-xl">{{ title }}</CardTitle>
<CardDescription> <CardDescription>
{{ description }} {{ description }}
@@ -11,7 +11,7 @@ defineProps<{
<template> <template>
<div <div
class="flex min-h-svh flex-col items-center justify-center gap-6 bg-background p-6 md:p-10" class="bg-background flex min-h-svh flex-col items-center justify-center gap-6 p-6 md:p-10"
> >
<div class="w-full max-w-sm"> <div class="w-full max-w-sm">
<div class="flex flex-col gap-8"> <div class="flex flex-col gap-8">
@@ -31,7 +31,7 @@ defineProps<{
</Link> </Link>
<div class="space-y-2 text-center"> <div class="space-y-2 text-center">
<h1 class="text-xl font-medium">{{ title }}</h1> <h1 class="text-xl font-medium">{{ title }}</h1>
<p class="text-center text-sm text-muted-foreground"> <p class="text-muted-foreground text-center text-sm">
{{ description }} {{ description }}
</p> </p>
</div> </div>
@@ -17,7 +17,7 @@ defineProps<{
class="relative grid h-dvh flex-col items-center justify-center px-8 sm:px-0 lg:max-w-none lg:grid-cols-2 lg:px-0" class="relative grid h-dvh flex-col items-center justify-center px-8 sm:px-0 lg:max-w-none lg:grid-cols-2 lg:px-0"
> >
<div <div
class="relative hidden h-full flex-col bg-muted p-10 text-white lg:flex dark:border-r" class="bg-muted relative hidden h-full flex-col p-10 text-white lg:flex dark:border-r"
> >
<div class="absolute inset-0 bg-zinc-900" /> <div class="absolute inset-0 bg-zinc-900" />
<Link <Link
@@ -36,7 +36,7 @@ defineProps<{
<h1 class="text-xl font-medium tracking-tight" v-if="title"> <h1 class="text-xl font-medium tracking-tight" v-if="title">
{{ title }} {{ title }}
</h1> </h1>
<p class="text-sm text-muted-foreground" v-if="description"> <p class="text-muted-foreground text-sm" v-if="description">
{{ description }} {{ description }}
</p> </p>
</div> </div>
+1 -1
View File
@@ -43,7 +43,7 @@ const { isCurrentOrParentUrl } = useCurrentUrl();
<div class="flex flex-col lg:flex-row lg:space-x-12"> <div class="flex flex-col lg:flex-row lg:space-x-12">
<aside class="w-full max-w-xl lg:w-48"> <aside class="w-full max-w-xl lg:w-48">
<nav <nav
class="flex flex-col space-y-1 space-x-0" class="flex flex-col space-x-0 space-y-1"
aria-label="Settings" aria-label="Settings"
> >
<Button <Button
+4 -4
View File
@@ -22,23 +22,23 @@ const breadcrumbs: BreadcrumbItem[] = [
> >
<div class="grid auto-rows-min gap-4 md:grid-cols-3"> <div class="grid auto-rows-min gap-4 md:grid-cols-3">
<div <div
class="relative aspect-video overflow-hidden rounded-xl border border-sidebar-border/70 dark:border-sidebar-border" class="border-sidebar-border/70 dark:border-sidebar-border relative aspect-video overflow-hidden rounded-xl border"
> >
<PlaceholderPattern /> <PlaceholderPattern />
</div> </div>
<div <div
class="relative aspect-video overflow-hidden rounded-xl border border-sidebar-border/70 dark:border-sidebar-border" class="border-sidebar-border/70 dark:border-sidebar-border relative aspect-video overflow-hidden rounded-xl border"
> >
<PlaceholderPattern /> <PlaceholderPattern />
</div> </div>
<div <div
class="relative aspect-video overflow-hidden rounded-xl border border-sidebar-border/70 dark:border-sidebar-border" class="border-sidebar-border/70 dark:border-sidebar-border relative aspect-video overflow-hidden rounded-xl border"
> >
<PlaceholderPattern /> <PlaceholderPattern />
</div> </div>
</div> </div>
<div <div
class="relative min-h-[100vh] flex-1 rounded-xl border border-sidebar-border/70 md:min-h-min dark:border-sidebar-border" class="border-sidebar-border/70 dark:border-sidebar-border relative min-h-[100vh] flex-1 rounded-xl border md:min-h-min"
> >
<PlaceholderPattern /> <PlaceholderPattern />
</div> </div>
+15 -15
View File
@@ -21,7 +21,7 @@ withDefaults(
class="flex min-h-screen flex-col items-center bg-[#FDFDFC] p-6 text-[#1b1b18] lg:justify-center lg:p-8 dark:bg-[#0a0a0a]" class="flex min-h-screen flex-col items-center bg-[#FDFDFC] p-6 text-[#1b1b18] lg:justify-center lg:p-8 dark:bg-[#0a0a0a]"
> >
<header <header
class="mb-6 w-full max-w-[335px] text-sm not-has-[nav]:hidden lg:max-w-4xl" class="not-has-[nav]:hidden mb-6 w-full max-w-[335px] text-sm lg:max-w-4xl"
> >
<nav class="flex items-center justify-end gap-4"> <nav class="flex items-center justify-end gap-4">
<Link <Link
@@ -49,13 +49,13 @@ withDefaults(
</nav> </nav>
</header> </header>
<div <div
class="flex w-full items-center justify-center opacity-100 transition-opacity duration-750 lg:grow starting:opacity-0" class="duration-750 starting:opacity-0 flex w-full items-center justify-center opacity-100 transition-opacity lg:grow"
> >
<main <main
class="flex w-full max-w-[335px] flex-col-reverse overflow-hidden rounded-lg lg:max-w-4xl lg:flex-row" class="flex w-full max-w-[335px] flex-col-reverse overflow-hidden rounded-lg lg:max-w-4xl lg:flex-row"
> >
<div <div
class="flex-1 rounded-br-lg rounded-bl-lg bg-white p-6 pb-12 text-[13px] leading-[20px] shadow-[inset_0px_0px_0px_1px_rgba(26,26,0,0.16)] lg:rounded-tl-lg lg:rounded-br-none lg:p-20 dark:bg-[#161615] dark:text-[#EDEDEC] dark:shadow-[inset_0px_0px_0px_1px_#fffaed2d]" class="flex-1 rounded-bl-lg rounded-br-lg bg-white p-6 pb-12 text-[13px] leading-[20px] shadow-[inset_0px_0px_0px_1px_rgba(26,26,0,0.16)] lg:rounded-br-none lg:rounded-tl-lg lg:p-20 dark:bg-[#161615] dark:text-[#EDEDEC] dark:shadow-[inset_0px_0px_0px_1px_#fffaed2d]"
> >
<h1 class="mb-1 font-medium">Let's get started</h1> <h1 class="mb-1 font-medium">Let's get started</h1>
<p class="mb-2 text-[#706f6c] dark:text-[#A1A09A]"> <p class="mb-2 text-[#706f6c] dark:text-[#A1A09A]">
@@ -64,7 +64,7 @@ withDefaults(
</p> </p>
<ul class="mb-4 flex flex-col lg:mb-6"> <ul class="mb-4 flex flex-col lg:mb-6">
<li <li
class="relative flex items-center gap-4 py-2 before:absolute before:top-1/2 before:bottom-0 before:left-[0.4rem] before:border-l before:border-[#e3e3e0] dark:before:border-[#3E3E3A]" class="relative flex items-center gap-4 py-2 before:absolute before:bottom-0 before:left-[0.4rem] before:top-1/2 before:border-l before:border-[#e3e3e0] dark:before:border-[#3E3E3A]"
> >
<span <span
class="relative bg-white py-1 dark:bg-[#161615]" class="relative bg-white py-1 dark:bg-[#161615]"
@@ -103,7 +103,7 @@ withDefaults(
</span> </span>
</li> </li>
<li <li
class="relative flex items-center gap-4 py-2 before:absolute before:top-0 before:bottom-1/2 before:left-[0.4rem] before:border-l before:border-[#e3e3e0] dark:before:border-[#3E3E3A]" class="relative flex items-center gap-4 py-2 before:absolute before:bottom-1/2 before:left-[0.4rem] before:top-0 before:border-l before:border-[#e3e3e0] dark:before:border-[#3E3E3A]"
> >
<span <span
class="relative bg-white py-1 dark:bg-[#161615]" class="relative bg-white py-1 dark:bg-[#161615]"
@@ -155,11 +155,11 @@ withDefaults(
</ul> </ul>
</div> </div>
<div <div
class="relative -mb-px aspect-[335/364] w-full shrink-0 overflow-hidden rounded-t-lg bg-[#fff2f2] lg:mb-0 lg:-ml-px lg:aspect-auto lg:w-[438px] lg:rounded-t-none lg:rounded-r-lg dark:bg-[#1D0002]" class="relative -mb-px aspect-[335/364] w-full shrink-0 overflow-hidden rounded-t-lg bg-[#fff2f2] lg:-ml-px lg:mb-0 lg:aspect-auto lg:w-[438px] lg:rounded-r-lg lg:rounded-t-none dark:bg-[#1D0002]"
> >
<!-- Laravel Logo --> <!-- Laravel Logo -->
<svg <svg
class="w-full max-w-none translate-y-0 text-[#F53003] opacity-100 transition-all duration-750 dark:text-[#F61500] starting:opacity-0 motion-safe:starting:translate-y-6" class="duration-750 starting:opacity-0 motion-safe:starting:translate-y-6 w-full max-w-none translate-y-0 text-[#F53003] opacity-100 transition-all dark:text-[#F61500]"
viewBox="0 0 438 104" viewBox="0 0 438 104"
fill="none" fill="none"
xmlns="http://www.w3.org/2000/svg" xmlns="http://www.w3.org/2000/svg"
@@ -196,13 +196,13 @@ withDefaults(
<!-- 13 --> <!-- 13 -->
<svg <svg
class="relative -mt-[6.6rem] -ml-8 w-[438px] max-w-none [--stroke-color:#1B1B18] lg:ml-0 dark:[--stroke-color:#FF750F]" class="relative -ml-8 -mt-[6.6rem] w-[438px] max-w-none [--stroke-color:#1B1B18] lg:ml-0 dark:[--stroke-color:#FF750F]"
viewBox="0 0 440 392" viewBox="0 0 440 392"
fill="none" fill="none"
xmlns="http://www.w3.org/2000/svg" xmlns="http://www.w3.org/2000/svg"
> >
<g <g
class="text-[#1B1B18] opacity-100 mix-blend-darken transition-all delay-300 duration-750 dark:text-black dark:mix-blend-normal starting:opacity-0" class="duration-750 starting:opacity-0 text-[#1B1B18] opacity-100 mix-blend-darken transition-all delay-300 dark:text-black dark:mix-blend-normal"
> >
<mask <mask
id="path-1-mask" id="path-1-mask"
@@ -250,7 +250,7 @@ withDefaults(
</g> </g>
<g <g
class="text-[#F3BEC7] opacity-100 transition-all delay-400 duration-750 dark:text-[#4B0600] starting:opacity-0 motion-safe:starting:-translate-x-[26px]" class="delay-400 duration-750 starting:opacity-0 motion-safe:starting:-translate-x-[26px] text-[#F3BEC7] opacity-100 transition-all dark:text-[#4B0600]"
> >
<mask <mask
id="path-2-mask" id="path-2-mask"
@@ -298,7 +298,7 @@ withDefaults(
</g> </g>
<g <g
class="text-[#F8B803] opacity-100 mix-blend-color transition-all delay-400 duration-750 dark:text-[#391800] dark:mix-blend-hard-light starting:opacity-0 motion-safe:starting:-translate-x-[51px]" class="delay-400 duration-750 starting:opacity-0 motion-safe:starting:-translate-x-[51px] text-[#F8B803] opacity-100 mix-blend-color transition-all dark:text-[#391800] dark:mix-blend-hard-light"
> >
<mask <mask
id="path-3-mask" id="path-3-mask"
@@ -346,7 +346,7 @@ withDefaults(
</g> </g>
<g <g
class="text-[#F3BEC7] opacity-100 mix-blend-multiply transition-all delay-400 duration-750 dark:text-[#733000] dark:mix-blend-normal starting:opacity-0 motion-safe:starting:-translate-x-[78px]" class="delay-400 duration-750 starting:opacity-0 motion-safe:starting:-translate-x-[78px] text-[#F3BEC7] opacity-100 mix-blend-multiply transition-all dark:text-[#733000] dark:mix-blend-normal"
> >
<mask <mask
id="path-4-mask" id="path-4-mask"
@@ -394,7 +394,7 @@ withDefaults(
</g> </g>
<g <g
class="text-[#F3BEC7] opacity-100 mix-blend-hard-light transition-all delay-400 duration-750 dark:text-[#4B0600] starting:opacity-0 motion-safe:starting:-translate-x-[102px]" class="delay-400 duration-750 starting:opacity-0 motion-safe:starting:-translate-x-[102px] text-[#F3BEC7] opacity-100 mix-blend-hard-light transition-all dark:text-[#4B0600]"
> >
<mask <mask
id="path-5-mask" id="path-5-mask"
@@ -442,11 +442,11 @@ withDefaults(
</g> </g>
</svg> </svg>
<div <div
class="absolute inset-0 rounded-t-lg shadow-[inset_0px_0px_0px_1px_rgba(26,26,0,0.16)] lg:rounded-t-none lg:rounded-r-lg dark:shadow-[inset_0px_0px_0px_1px_#fffaed2d]" class="absolute inset-0 rounded-t-lg shadow-[inset_0px_0px_0px_1px_rgba(26,26,0,0.16)] lg:rounded-r-lg lg:rounded-t-none dark:shadow-[inset_0px_0px_0px_1px_#fffaed2d]"
></div> ></div>
</div> </div>
</main> </main>
</div> </div>
<div class="hidden h-14.5 lg:block"></div> <div class="h-14.5 hidden lg:block"></div>
</div> </div>
</template> </template>
+6 -6
View File
@@ -62,17 +62,17 @@ const breadcrumbs: BreadcrumbItem[] = [
<CardContent class="p-0"> <CardContent class="p-0">
<div <div
v-if="users.length === 0" v-if="users.length === 0"
class="p-6 text-sm text-muted-foreground" class="text-muted-foreground p-6 text-sm"
> >
No users exist yet. No users exist yet.
</div> </div>
<div v-else class="overflow-x-auto"> <div v-else class="overflow-x-auto">
<table <table
class="min-w-full divide-y divide-border text-sm" class="divide-border min-w-full divide-y text-sm"
> >
<thead <thead
class="bg-muted/40 text-left text-muted-foreground" class="bg-muted/40 text-muted-foreground text-left"
> >
<tr> <tr>
<th class="px-4 py-3 font-medium">User</th> <th class="px-4 py-3 font-medium">User</th>
@@ -85,7 +85,7 @@ const breadcrumbs: BreadcrumbItem[] = [
</th> </th>
</tr> </tr>
</thead> </thead>
<tbody class="divide-y divide-border"> <tbody class="divide-border divide-y">
<tr <tr
v-for="user in users" v-for="user in users"
:key="user.id" :key="user.id"
@@ -93,12 +93,12 @@ const breadcrumbs: BreadcrumbItem[] = [
> >
<td class="px-4 py-4"> <td class="px-4 py-4">
<div <div
class="font-medium text-foreground" class="text-foreground font-medium"
> >
{{ user.name }} {{ user.name }}
</div> </div>
</td> </td>
<td class="px-4 py-4 text-muted-foreground"> <td class="text-muted-foreground px-4 py-4">
{{ user.email }} {{ user.email }}
</td> </td>
<td class="px-4 py-4"> <td class="px-4 py-4">
+1 -1
View File
@@ -56,7 +56,7 @@ defineProps<{
</div> </div>
</Form> </Form>
<div class="space-x-1 text-center text-sm text-muted-foreground"> <div class="text-muted-foreground space-x-1 text-center text-sm">
<span>Or, return to</span> <span>Or, return to</span>
<TextLink :href="login()">log in</TextLink> <TextLink :href="login()">log in</TextLink>
</div> </div>
+1 -1
View File
@@ -99,7 +99,7 @@ defineProps<{
</div> </div>
<div <div
class="text-center text-sm text-muted-foreground" class="text-muted-foreground text-center text-sm"
v-if="canRegister" v-if="canRegister"
> >
Don't have an account? Don't have an account?
+1 -1
View File
@@ -93,7 +93,7 @@ import { store } from '@/routes/register';
</Button> </Button>
</div> </div>
<div class="text-center text-sm text-muted-foreground"> <div class="text-muted-foreground text-center text-sm">
Already have an account? Already have an account?
<TextLink <TextLink
:href="login()" :href="login()"
@@ -84,11 +84,11 @@ const code = ref<string>('');
<Button type="submit" class="w-full" :disabled="processing" <Button type="submit" class="w-full" :disabled="processing"
>Continue</Button >Continue</Button
> >
<div class="text-center text-sm text-muted-foreground"> <div class="text-muted-foreground text-center text-sm">
<span>or you can </span> <span>or you can </span>
<button <button
type="button" type="button"
class="text-foreground underline decoration-neutral-300 underline-offset-4 transition-colors duration-300 ease-out hover:decoration-current! dark:decoration-neutral-500" class="text-foreground hover:decoration-current! underline decoration-neutral-300 underline-offset-4 transition-colors duration-300 ease-out dark:decoration-neutral-500"
@click="() => toggleRecoveryMode(clearErrors)" @click="() => toggleRecoveryMode(clearErrors)"
> >
{{ authConfigContent.buttonText }} {{ authConfigContent.buttonText }}
@@ -116,11 +116,11 @@ const code = ref<string>('');
>Continue</Button >Continue</Button
> >
<div class="text-center text-sm text-muted-foreground"> <div class="text-muted-foreground text-center text-sm">
<span>or you can </span> <span>or you can </span>
<button <button
type="button" type="button"
class="text-foreground underline decoration-neutral-300 underline-offset-4 transition-colors duration-300 ease-out hover:decoration-current! dark:decoration-neutral-500" class="text-foreground hover:decoration-current! underline decoration-neutral-300 underline-offset-4 transition-colors duration-300 ease-out dark:decoration-neutral-500"
@click="() => toggleRecoveryMode(clearErrors)" @click="() => toggleRecoveryMode(clearErrors)"
> >
{{ authConfigContent.buttonText }} {{ authConfigContent.buttonText }}
+16 -16
View File
@@ -81,10 +81,10 @@ const hasPermission = (
<CardContent class="p-0"> <CardContent class="p-0">
<div class="overflow-x-auto"> <div class="overflow-x-auto">
<table <table
class="min-w-full divide-y divide-border text-sm" class="divide-border min-w-full divide-y text-sm"
> >
<thead <thead
class="bg-muted/40 text-left text-muted-foreground" class="bg-muted/40 text-muted-foreground text-left"
> >
<tr> <tr>
<th class="px-4 py-3 font-medium">User</th> <th class="px-4 py-3 font-medium">User</th>
@@ -99,18 +99,18 @@ const hasPermission = (
</th> </th>
</tr> </tr>
</thead> </thead>
<tbody class="divide-y divide-border"> <tbody class="divide-border divide-y">
<tr <tr
v-for="user in users" v-for="user in users"
:key="user.id" :key="user.id"
class="bg-background align-top" class="bg-background align-top"
> >
<td <td
class="px-4 py-4 font-medium text-foreground" class="text-foreground px-4 py-4 font-medium"
> >
{{ user.name }} {{ user.name }}
</td> </td>
<td class="px-4 py-4 text-muted-foreground"> <td class="text-muted-foreground px-4 py-4">
{{ user.email }} {{ user.email }}
</td> </td>
<td class="px-4 py-4"> <td class="px-4 py-4">
@@ -126,7 +126,7 @@ const hasPermission = (
<label <label
v-for="option in permissionOptions" v-for="option in permissionOptions"
:key="`${user.id}-${option.value}`" :key="`${user.id}-${option.value}`"
class="inline-flex items-center gap-2 rounded-lg border border-border px-3 py-2 text-sm" class="border-border inline-flex items-center gap-2 rounded-lg border px-3 py-2 text-sm"
> >
<input <input
type="checkbox" type="checkbox"
@@ -139,7 +139,7 @@ const hasPermission = (
option.value, option.value,
) )
" "
class="size-4 rounded border-input text-primary focus:ring-ring" class="border-input text-primary focus:ring-ring size-4 rounded"
/> />
<span>{{ option.label }}</span> <span>{{ option.label }}</span>
</label> </label>
@@ -157,7 +157,7 @@ const hasPermission = (
</Form> </Form>
</td> </td>
<td <td
class="px-4 py-4 text-right text-muted-foreground" class="text-muted-foreground px-4 py-4 text-right"
> >
Direct Direct
</td> </td>
@@ -180,7 +180,7 @@ const hasPermission = (
<CardContent class="p-0"> <CardContent class="p-0">
<div <div
v-if="teams.length === 0" v-if="teams.length === 0"
class="p-6 text-sm text-muted-foreground" class="text-muted-foreground p-6 text-sm"
> >
No teams exist yet. Create teams first to assign No teams exist yet. Create teams first to assign
inherited permissions. inherited permissions.
@@ -188,10 +188,10 @@ const hasPermission = (
<div v-else class="overflow-x-auto"> <div v-else class="overflow-x-auto">
<table <table
class="min-w-full divide-y divide-border text-sm" class="divide-border min-w-full divide-y text-sm"
> >
<thead <thead
class="bg-muted/40 text-left text-muted-foreground" class="bg-muted/40 text-muted-foreground text-left"
> >
<tr> <tr>
<th class="px-4 py-3 font-medium">Team</th> <th class="px-4 py-3 font-medium">Team</th>
@@ -208,14 +208,14 @@ const hasPermission = (
</th> </th>
</tr> </tr>
</thead> </thead>
<tbody class="divide-y divide-border"> <tbody class="divide-border divide-y">
<tr <tr
v-for="team in teams" v-for="team in teams"
:key="team.id" :key="team.id"
class="bg-background align-top" class="bg-background align-top"
> >
<td <td
class="px-4 py-4 font-medium text-foreground" class="text-foreground px-4 py-4 font-medium"
> >
{{ team.name }} {{ team.name }}
</td> </td>
@@ -249,7 +249,7 @@ const hasPermission = (
<label <label
v-for="option in permissionOptions" v-for="option in permissionOptions"
:key="`${team.id}-${option.value}`" :key="`${team.id}-${option.value}`"
class="inline-flex items-center gap-2 rounded-lg border border-border px-3 py-2 text-sm" class="border-border inline-flex items-center gap-2 rounded-lg border px-3 py-2 text-sm"
> >
<input <input
type="checkbox" type="checkbox"
@@ -262,7 +262,7 @@ const hasPermission = (
option.value, option.value,
) )
" "
class="size-4 rounded border-input text-primary focus:ring-ring" class="border-input text-primary focus:ring-ring size-4 rounded"
/> />
<span>{{ option.label }}</span> <span>{{ option.label }}</span>
</label> </label>
@@ -280,7 +280,7 @@ const hasPermission = (
</Form> </Form>
</td> </td>
<td <td
class="px-4 py-4 text-right text-muted-foreground" class="text-muted-foreground px-4 py-4 text-right"
> >
Inherited Inherited
</td> </td>
+14 -14
View File
@@ -113,7 +113,7 @@ const hasTicketMetadata =
<select <select
id="ticket_type_id" id="ticket_type_id"
name="ticket_type_id" name="ticket_type_id"
class="rounded-md border border-input bg-background px-3 py-2 text-sm shadow-xs transition-[color,box-shadow] outline-none focus-visible:border-ring focus-visible:ring-[3px] focus-visible:ring-ring/50" class="border-input bg-background shadow-xs focus-visible:border-ring focus-visible:ring-ring/50 rounded-md border px-3 py-2 text-sm outline-none transition-[color,box-shadow] focus-visible:ring-[3px]"
> >
<option <option
v-for="ticketType in ticketTypes" v-for="ticketType in ticketTypes"
@@ -133,7 +133,7 @@ const hasTicketMetadata =
<select <select
id="ticket_priority_id" id="ticket_priority_id"
name="ticket_priority_id" name="ticket_priority_id"
class="rounded-md border border-input bg-background px-3 py-2 text-sm shadow-xs transition-[color,box-shadow] outline-none focus-visible:border-ring focus-visible:ring-[3px] focus-visible:ring-ring/50" class="border-input bg-background shadow-xs focus-visible:border-ring focus-visible:ring-ring/50 rounded-md border px-3 py-2 text-sm outline-none transition-[color,box-shadow] focus-visible:ring-[3px]"
> >
<option <option
v-for="ticketPriority in ticketPriorities" v-for="ticketPriority in ticketPriorities"
@@ -155,7 +155,7 @@ const hasTicketMetadata =
id="description" id="description"
name="description" name="description"
rows="4" rows="4"
class="rounded-md border border-input bg-background px-3 py-2 text-sm shadow-xs transition-[color,box-shadow] outline-none focus-visible:border-ring focus-visible:ring-[3px] focus-visible:ring-ring/50" class="border-input bg-background shadow-xs focus-visible:border-ring focus-visible:ring-ring/50 rounded-md border px-3 py-2 text-sm outline-none transition-[color,box-shadow] focus-visible:ring-[3px]"
placeholder="Describe the expected behavior and relevant context." placeholder="Describe the expected behavior and relevant context."
/> />
<InputError :message="errors.description" /> <InputError :message="errors.description" />
@@ -169,7 +169,7 @@ const hasTicketMetadata =
id="acceptance_criteria" id="acceptance_criteria"
name="acceptance_criteria" name="acceptance_criteria"
rows="4" rows="4"
class="rounded-md border border-input bg-background px-3 py-2 text-sm shadow-xs transition-[color,box-shadow] outline-none focus-visible:border-ring focus-visible:ring-[3px] focus-visible:ring-ring/50" class="border-input bg-background shadow-xs focus-visible:border-ring focus-visible:ring-ring/50 rounded-md border px-3 py-2 text-sm outline-none transition-[color,box-shadow] focus-visible:ring-[3px]"
placeholder="List the conditions that must be true before this ticket is done." placeholder="List the conditions that must be true before this ticket is done."
/> />
<InputError :message="errors.acceptance_criteria" /> <InputError :message="errors.acceptance_criteria" />
@@ -212,17 +212,17 @@ const hasTicketMetadata =
<CardContent class="p-0"> <CardContent class="p-0">
<div <div
v-if="tickets.length === 0" v-if="tickets.length === 0"
class="p-6 text-sm text-muted-foreground" class="text-muted-foreground p-6 text-sm"
> >
No backlog tickets exist yet. No backlog tickets exist yet.
</div> </div>
<div v-else class="overflow-x-auto"> <div v-else class="overflow-x-auto">
<table <table
class="min-w-full divide-y divide-border text-sm" class="divide-border min-w-full divide-y text-sm"
> >
<thead <thead
class="bg-muted/40 text-left text-muted-foreground" class="bg-muted/40 text-muted-foreground text-left"
> >
<tr> <tr>
<th class="px-4 py-3 font-medium">Key</th> <th class="px-4 py-3 font-medium">Key</th>
@@ -239,7 +239,7 @@ const hasTicketMetadata =
</th> </th>
</tr> </tr>
</thead> </thead>
<tbody class="divide-y divide-border"> <tbody class="divide-border divide-y">
<tr <tr
v-for="ticket in tickets" v-for="ticket in tickets"
:key="ticket.id" :key="ticket.id"
@@ -267,21 +267,21 @@ const hasTicketMetadata =
ticket: ticket.id, ticket: ticket.id,
}) })
" "
class="font-medium text-foreground transition hover:text-primary" class="text-foreground hover:text-primary font-medium transition"
> >
{{ ticket.title }} {{ ticket.title }}
</Link> </Link>
<div <div
v-if="ticket.description" v-if="ticket.description"
class="mt-1 line-clamp-2 text-muted-foreground" class="text-muted-foreground mt-1 line-clamp-2"
> >
{{ ticket.description }} {{ ticket.description }}
</div> </div>
</td> </td>
<td class="px-4 py-4 text-muted-foreground"> <td class="text-muted-foreground px-4 py-4">
{{ ticket.ticket_type.name }} {{ ticket.ticket_type.name }}
</td> </td>
<td class="px-4 py-4 text-muted-foreground"> <td class="text-muted-foreground px-4 py-4">
{{ ticket.ticket_priority.name }} {{ ticket.ticket_priority.name }}
</td> </td>
<td v-if="canEditTickets" class="px-4 py-4"> <td v-if="canEditTickets" class="px-4 py-4">
@@ -305,7 +305,7 @@ const hasTicketMetadata =
/> />
<select <select
name="board_column_id" name="board_column_id"
class="min-w-44 rounded-md border border-input bg-background px-3 py-2 text-sm shadow-xs transition-[color,box-shadow] outline-none focus-visible:border-ring focus-visible:ring-[3px] focus-visible:ring-ring/50" class="border-input bg-background shadow-xs focus-visible:border-ring focus-visible:ring-ring/50 min-w-44 rounded-md border px-3 py-2 text-sm outline-none transition-[color,box-shadow] focus-visible:ring-[3px]"
> >
<option <option
v-for="boardColumn in boardColumns" v-for="boardColumn in boardColumns"
@@ -326,7 +326,7 @@ const hasTicketMetadata =
<span <span
v-else v-else
class="text-sm text-muted-foreground" class="text-muted-foreground text-sm"
> >
Add board columns first. Add board columns first.
</span> </span>
+9 -6
View File
@@ -108,7 +108,7 @@ const statusOptions = [
:key="boardColumn.id" :key="boardColumn.id"
class="flex h-full flex-col gap-0 overflow-hidden" class="flex h-full flex-col gap-0 overflow-hidden"
> >
<CardHeader class="border-b bg-muted/20"> <CardHeader class="bg-muted/20 border-b">
<div class="flex items-start justify-between gap-3"> <div class="flex items-start justify-between gap-3">
<div> <div>
<CardTitle>{{ boardColumn.name }}</CardTitle> <CardTitle>{{ boardColumn.name }}</CardTitle>
@@ -127,7 +127,7 @@ const statusOptions = [
<CardContent class="flex flex-1 flex-col gap-4 p-4"> <CardContent class="flex flex-1 flex-col gap-4 p-4">
<div <div
v-if="(boardColumn.tickets?.length ?? 0) === 0" v-if="(boardColumn.tickets?.length ?? 0) === 0"
class="rounded-xl border border-dashed border-border px-4 py-6 text-sm text-muted-foreground" class="border-border text-muted-foreground rounded-xl border border-dashed px-4 py-6 text-sm"
> >
No tickets are currently in this column. No tickets are currently in this column.
</div> </div>
@@ -169,7 +169,7 @@ const statusOptions = [
ticket: ticket.id, ticket: ticket.id,
}) })
" "
class="transition hover:text-primary" class="hover:text-primary transition"
> >
{{ ticket.title }} {{ ticket.title }}
</Link> </Link>
@@ -181,7 +181,10 @@ const statusOptions = [
{{ ticket.description }} {{ ticket.description }}
</CardDescription> </CardDescription>
<CardDescription <CardDescription
v-if="ticket.is_blocked && ticket.blocked_comment" v-if="
ticket.is_blocked &&
ticket.blocked_comment
"
class="mt-2 text-amber-900 dark:text-amber-200" class="mt-2 text-amber-900 dark:text-amber-200"
> >
{{ ticket.blocked_comment }} {{ ticket.blocked_comment }}
@@ -206,7 +209,7 @@ const statusOptions = [
/> />
<label <label
:for="`ticket-status-${ticket.id}`" :for="`ticket-status-${ticket.id}`"
class="text-xs font-medium tracking-wide text-muted-foreground uppercase" class="text-muted-foreground text-xs font-medium uppercase tracking-wide"
> >
Move ticket Move ticket
</label> </label>
@@ -219,7 +222,7 @@ const statusOptions = [
:value=" :value="
ticket.board_column_id ?? '' ticket.board_column_id ?? ''
" "
class="min-w-44 rounded-md border border-input bg-background px-3 py-2 text-sm shadow-xs transition-[color,box-shadow] outline-none focus-visible:border-ring focus-visible:ring-[3px] focus-visible:ring-ring/50" class="border-input bg-background shadow-xs focus-visible:border-ring focus-visible:ring-ring/50 min-w-44 rounded-md border px-3 py-2 text-sm outline-none transition-[color,box-shadow] focus-visible:ring-[3px]"
> >
<option <option
v-for="statusOption in statusOptions" v-for="statusOption in statusOptions"
+2 -2
View File
@@ -76,9 +76,9 @@ const breadcrumbs: BreadcrumbItem[] = [
placeholder="CORE" placeholder="CORE"
class="uppercase" class="uppercase"
/> />
<p class="text-sm text-muted-foreground"> <p class="text-muted-foreground text-sm">
Example ticket keys will look like Example ticket keys will look like
<span class="font-medium text-foreground" <span class="text-foreground font-medium"
>CORE-1</span >CORE-1</span
>. >.
</p> </p>
+3 -3
View File
@@ -48,7 +48,7 @@ const breadcrumbs: BreadcrumbItem[] = [
<div <div
v-if="projects.length === 0" v-if="projects.length === 0"
class="rounded-xl border border-dashed px-6 py-10 text-center text-sm text-muted-foreground" class="text-muted-foreground rounded-xl border border-dashed px-6 py-10 text-center text-sm"
> >
No projects exist yet. Create the first one to start building No projects exist yet. Create the first one to start building
out board, backlog, and settings areas. out board, backlog, and settings areas.
@@ -62,7 +62,7 @@ const breadcrumbs: BreadcrumbItem[] = [
class="group block" class="group block"
> >
<Card <Card
class="h-full border-border/80 transition-colors group-hover:border-primary/40" class="border-border/80 group-hover:border-primary/40 h-full transition-colors"
> >
<CardHeader class="gap-3"> <CardHeader class="gap-3">
<div class="flex items-start justify-between gap-3"> <div class="flex items-start justify-between gap-3">
@@ -80,7 +80,7 @@ const breadcrumbs: BreadcrumbItem[] = [
</CardHeader> </CardHeader>
<CardContent <CardContent
class="flex items-center gap-2 text-sm text-muted-foreground" class="text-muted-foreground flex items-center gap-2 text-sm"
> >
<Folder class="size-4" /> <Folder class="size-4" />
Open board, backlog, and settings hub Open board, backlog, and settings hub
+2 -2
View File
@@ -130,7 +130,7 @@ const projectAreas = [
> >
<CardHeader> <CardHeader>
<div <div
class="mb-3 flex size-10 items-center justify-center rounded-full bg-muted text-foreground" class="bg-muted text-foreground mb-3 flex size-10 items-center justify-center rounded-full"
> >
<component :is="area.icon" class="size-5" /> <component :is="area.icon" class="size-5" />
</div> </div>
@@ -139,7 +139,7 @@ const projectAreas = [
area.description area.description
}}</CardDescription> }}</CardDescription>
</CardHeader> </CardHeader>
<CardContent class="text-sm text-muted-foreground"> <CardContent class="text-muted-foreground text-sm">
Use the project shortcuts above to open this area. Use the project shortcuts above to open this area.
</CardContent> </CardContent>
</Card> </Card>
+86 -72
View File
@@ -141,7 +141,8 @@ const selectedBranchRepositoryConnection = computed(
); );
const selectedBranchRepositoryHasPersonalAccess = computed( const selectedBranchRepositoryHasPersonalAccess = computed(
() => selectedBranchRepositoryConnection.value?.has_personal_access ?? false, () =>
selectedBranchRepositoryConnection.value?.has_personal_access ?? false,
); );
const initializeBranchCreationForm = (): void => { const initializeBranchCreationForm = (): void => {
@@ -174,7 +175,11 @@ watch(
() => branchCreationForm.repository_connection_id, () => branchCreationForm.repository_connection_id,
() => branchCreationForm.branch_name, () => branchCreationForm.branch_name,
], ],
([isOpen, repositoryConnectionId, branchName], _previousValues, onCleanup) => { (
[isOpen, repositoryConnectionId, branchName],
_previousValues,
onCleanup,
) => {
if (!isOpen) { if (!isOpen) {
return; return;
} }
@@ -412,7 +417,7 @@ const formatDateTime = (value: string): string => {
:disabled=" :disabled="
!canEditTicket || form.processing !canEditTicket || form.processing
" "
class="rounded-md border border-input bg-background px-3 py-2 text-sm shadow-xs transition-[color,box-shadow] outline-none focus-visible:border-ring focus-visible:ring-[3px] focus-visible:ring-ring/50 disabled:cursor-not-allowed disabled:opacity-60" class="border-input bg-background shadow-xs focus-visible:border-ring focus-visible:ring-ring/50 rounded-md border px-3 py-2 text-sm outline-none transition-[color,box-shadow] focus-visible:ring-[3px] disabled:cursor-not-allowed disabled:opacity-60"
> >
<option <option
v-for="ticketType in ticketTypes" v-for="ticketType in ticketTypes"
@@ -437,7 +442,7 @@ const formatDateTime = (value: string): string => {
:disabled=" :disabled="
!canEditTicket || form.processing !canEditTicket || form.processing
" "
class="rounded-md border border-input bg-background px-3 py-2 text-sm shadow-xs transition-[color,box-shadow] outline-none focus-visible:border-ring focus-visible:ring-[3px] focus-visible:ring-ring/50 disabled:cursor-not-allowed disabled:opacity-60" class="border-input bg-background shadow-xs focus-visible:border-ring focus-visible:ring-ring/50 rounded-md border px-3 py-2 text-sm outline-none transition-[color,box-shadow] focus-visible:ring-[3px] disabled:cursor-not-allowed disabled:opacity-60"
> >
<option <option
v-for="ticketPriority in ticketPriorities" v-for="ticketPriority in ticketPriorities"
@@ -465,7 +470,7 @@ const formatDateTime = (value: string): string => {
:disabled=" :disabled="
!canEditTicket || form.processing !canEditTicket || form.processing
" "
class="rounded-md border border-input bg-background px-3 py-2 text-sm shadow-xs transition-[color,box-shadow] outline-none focus-visible:border-ring focus-visible:ring-[3px] focus-visible:ring-ring/50 disabled:cursor-not-allowed disabled:opacity-60" class="border-input bg-background shadow-xs focus-visible:border-ring focus-visible:ring-ring/50 rounded-md border px-3 py-2 text-sm outline-none transition-[color,box-shadow] focus-visible:ring-[3px] disabled:cursor-not-allowed disabled:opacity-60"
> >
<option value="">No parent ticket</option> <option value="">No parent ticket</option>
<option <option
@@ -492,7 +497,7 @@ const formatDateTime = (value: string): string => {
:disabled=" :disabled="
!canEditTicket || form.processing !canEditTicket || form.processing
" "
class="rounded-md border border-input bg-background px-3 py-2 text-sm shadow-xs transition-[color,box-shadow] outline-none focus-visible:border-ring focus-visible:ring-[3px] focus-visible:ring-ring/50 disabled:cursor-not-allowed disabled:opacity-60" class="border-input bg-background shadow-xs focus-visible:border-ring focus-visible:ring-ring/50 rounded-md border px-3 py-2 text-sm outline-none transition-[color,box-shadow] focus-visible:ring-[3px] disabled:cursor-not-allowed disabled:opacity-60"
/> />
<InputError <InputError
:message="form.errors.description" :message="form.errors.description"
@@ -510,14 +515,16 @@ const formatDateTime = (value: string): string => {
:disabled=" :disabled="
!canEditTicket || form.processing !canEditTicket || form.processing
" "
class="rounded-md border border-input bg-background px-3 py-2 text-sm shadow-xs transition-[color,box-shadow] outline-none focus-visible:border-ring focus-visible:ring-[3px] focus-visible:ring-ring/50 disabled:cursor-not-allowed disabled:opacity-60" class="border-input bg-background shadow-xs focus-visible:border-ring focus-visible:ring-ring/50 rounded-md border px-3 py-2 text-sm outline-none transition-[color,box-shadow] focus-visible:ring-[3px] disabled:cursor-not-allowed disabled:opacity-60"
/> />
<InputError <InputError
:message="form.errors.acceptance_criteria" :message="form.errors.acceptance_criteria"
/> />
</div> </div>
<div class="grid gap-3 rounded-xl border border-border p-4"> <div
class="border-border grid gap-3 rounded-xl border p-4"
>
<div class="flex items-center gap-3"> <div class="flex items-center gap-3">
<input <input
id="is_blocked" id="is_blocked"
@@ -526,7 +533,7 @@ const formatDateTime = (value: string): string => {
:disabled=" :disabled="
!canEditTicket || form.processing !canEditTicket || form.processing
" "
class="size-4 rounded border-input text-primary focus:ring-ring" class="border-input text-primary focus:ring-ring size-4 rounded"
/> />
<Label for="is_blocked"> <Label for="is_blocked">
Mark ticket as blocked Mark ticket as blocked
@@ -544,7 +551,7 @@ const formatDateTime = (value: string): string => {
:disabled=" :disabled="
!canEditTicket || form.processing !canEditTicket || form.processing
" "
class="rounded-md border border-input bg-background px-3 py-2 text-sm shadow-xs transition-[color,box-shadow] outline-none focus-visible:border-ring focus-visible:ring-[3px] focus-visible:ring-ring/50 disabled:cursor-not-allowed disabled:opacity-60" class="border-input bg-background shadow-xs focus-visible:border-ring focus-visible:ring-ring/50 rounded-md border px-3 py-2 text-sm outline-none transition-[color,box-shadow] focus-visible:ring-[3px] disabled:cursor-not-allowed disabled:opacity-60"
placeholder="Describe what currently blocks progress on this ticket." placeholder="Describe what currently blocks progress on this ticket."
/> />
<InputError <InputError
@@ -558,7 +565,7 @@ const formatDateTime = (value: string): string => {
<h3 class="text-sm font-semibold"> <h3 class="text-sm font-semibold">
Custom fields Custom fields
</h3> </h3>
<p class="text-sm text-muted-foreground"> <p class="text-muted-foreground text-sm">
Project-configured fields can be tracked Project-configured fields can be tracked
directly on the ticket. directly on the ticket.
</p> </p>
@@ -566,7 +573,7 @@ const formatDateTime = (value: string): string => {
<div <div
v-if="ticketFieldDefinitions.length === 0" v-if="ticketFieldDefinitions.length === 0"
class="rounded-xl border border-dashed border-border px-4 py-6 text-sm text-muted-foreground" class="border-border text-muted-foreground rounded-xl border border-dashed px-4 py-6 text-sm"
> >
No custom fields are configured for this No custom fields are configured for this
project yet. project yet.
@@ -600,7 +607,7 @@ const formatDateTime = (value: string): string => {
!canEditTicket || !canEditTicket ||
form.processing form.processing
" "
class="rounded-md border border-input bg-background px-3 py-2 text-sm shadow-xs transition-[color,box-shadow] outline-none focus-visible:border-ring focus-visible:ring-[3px] focus-visible:ring-ring/50 disabled:cursor-not-allowed disabled:opacity-60" class="border-input bg-background shadow-xs focus-visible:border-ring focus-visible:ring-ring/50 rounded-md border px-3 py-2 text-sm outline-none transition-[color,box-shadow] focus-visible:ring-[3px] disabled:cursor-not-allowed disabled:opacity-60"
> >
<option value="">Unassigned</option> <option value="">Unassigned</option>
<option <option
@@ -664,9 +671,9 @@ const formatDateTime = (value: string): string => {
<div class="space-y-1.5"> <div class="space-y-1.5">
<CardTitle>Branches</CardTitle> <CardTitle>Branches</CardTitle>
<CardDescription> <CardDescription>
Matching branches are discovered from Matching branches are discovered from linked
linked repositories when the branch name repositories when the branch name starts
starts with this ticket key. with this ticket key.
</CardDescription> </CardDescription>
</div> </div>
@@ -699,7 +706,9 @@ const formatDateTime = (value: string): string => {
@submit.prevent="submitBranchCreation" @submit.prevent="submitBranchCreation"
> >
<div class="grid gap-2"> <div class="grid gap-2">
<Label for="repository_connection_id"> <Label
for="repository_connection_id"
>
Repository Repository
</Label> </Label>
<select <select
@@ -710,11 +719,13 @@ const formatDateTime = (value: string): string => {
:disabled=" :disabled="
branchCreationForm.processing branchCreationForm.processing
" "
class="rounded-md border border-input bg-background px-3 py-2 text-sm shadow-xs transition-[color,box-shadow] outline-none focus-visible:border-ring focus-visible:ring-[3px] focus-visible:ring-ring/50 disabled:cursor-not-allowed disabled:opacity-60" class="border-input bg-background shadow-xs focus-visible:border-ring focus-visible:ring-ring/50 rounded-md border px-3 py-2 text-sm outline-none transition-[color,box-shadow] focus-visible:ring-[3px] disabled:cursor-not-allowed disabled:opacity-60"
> >
<option <option
v-for="repositoryConnection in linkedRepositoryConnections" v-for="repositoryConnection in linkedRepositoryConnections"
:key="repositoryConnection.id" :key="
repositoryConnection.id
"
:value=" :value="
String( String(
repositoryConnection.id, repositoryConnection.id,
@@ -764,9 +775,7 @@ const formatDateTime = (value: string): string => {
: 'border-amber-200 bg-amber-50 text-amber-900 dark:border-amber-900/70 dark:bg-amber-950/40 dark:text-amber-100' : 'border-amber-200 bg-amber-50 text-amber-900 dark:border-amber-900/70 dark:bg-amber-950/40 dark:text-amber-100'
" "
> >
<div <div class="flex items-start gap-3">
class="flex items-start gap-3"
>
<CheckCircle2 <CheckCircle2
v-if=" v-if="
branchNameValidation?.is_valid branchNameValidation?.is_valid
@@ -784,8 +793,8 @@ const formatDateTime = (value: string): string => {
{{ {{
isCheckingBranchName isCheckingBranchName
? 'Checking whether this branch name is valid and still available...' ? 'Checking whether this branch name is valid and still available...'
: branchNameValidation?.message ?? : (branchNameValidation?.message ??
'Select a linked repository to validate the branch name.' 'Select a linked repository to validate the branch name.')
}} }}
</p> </p>
</div> </div>
@@ -797,10 +806,10 @@ const formatDateTime = (value: string): string => {
selectedBranchRepositoryConnection !== selectedBranchRepositoryConnection !==
null null
" "
class="rounded-xl border border-dashed border-border px-4 py-4" class="border-border rounded-xl border border-dashed px-4 py-4"
> >
<p <p
class="text-sm text-muted-foreground" class="text-muted-foreground text-sm"
> >
You can only create branches in You can only create branches in
repositories that match one of repositories that match one of
@@ -814,9 +823,7 @@ const formatDateTime = (value: string): string => {
class="mt-3" class="mt-3"
> >
<Link <Link
:href=" :href="editGitConnections()"
editGitConnections()
"
> >
Open Git connections Open Git connections
</Link> </Link>
@@ -828,8 +835,7 @@ const formatDateTime = (value: string): string => {
type="button" type="button"
variant="secondary" variant="secondary"
@click=" @click="
isCreateBranchDialogOpen = isCreateBranchDialogOpen = false
false
" "
> >
Cancel Cancel
@@ -855,7 +861,7 @@ const formatDateTime = (value: string): string => {
<CardContent class="space-y-4"> <CardContent class="space-y-4">
<div <div
v-if="visibleRepositoryBranches.length === 0" v-if="visibleRepositoryBranches.length === 0"
class="rounded-xl border border-dashed border-border px-4 py-6 text-sm text-muted-foreground" class="border-border text-muted-foreground rounded-xl border border-dashed px-4 py-6 text-sm"
> >
No matching branches were found across the No matching branches were found across the
linked repositories you can access. linked repositories you can access.
@@ -865,9 +871,10 @@ const formatDateTime = (value: string): string => {
<div <div
v-for="repositoryBranch in visibleRepositoryBranches" v-for="repositoryBranch in visibleRepositoryBranches"
:key=" :key="
repositoryBranch.repository_connection.id repositoryBranch.repository_connection
.id
" "
class="rounded-xl border border-border px-4 py-4" class="border-border rounded-xl border px-4 py-4"
> >
<div <div
class="flex flex-wrap items-center gap-2" class="flex flex-wrap items-center gap-2"
@@ -889,7 +896,7 @@ const formatDateTime = (value: string): string => {
</div> </div>
<p <p
class="mt-2 text-sm text-muted-foreground" class="text-muted-foreground mt-2 text-sm"
> >
{{ {{
repositoryBranch repositoryBranch
@@ -906,14 +913,18 @@ const formatDateTime = (value: string): string => {
class="mt-3 space-y-3" class="mt-3 space-y-3"
> >
<p <p
class="text-sm text-muted-foreground" class="text-muted-foreground text-sm"
> >
Connect a matching Git account in Connect a matching Git account in
your user settings to inspect your user settings to inspect
branches for this repository. branches for this repository.
</p> </p>
<Button as-child variant="outline" size="sm"> <Button
as-child
variant="outline"
size="sm"
>
<Link :href="editGitConnections()"> <Link :href="editGitConnections()">
Open Git connections Open Git connections
</Link> </Link>
@@ -927,7 +938,10 @@ const formatDateTime = (value: string): string => {
{{ repositoryBranch.error }} {{ repositoryBranch.error }}
</div> </div>
<div v-else class="mt-3 flex flex-wrap gap-2"> <div
v-else
class="mt-3 flex flex-wrap gap-2"
>
<Badge <Badge
v-for="branch in repositoryBranch.branches" v-for="branch in repositoryBranch.branches"
:key="branch.name" :key="branch.name"
@@ -964,7 +978,7 @@ const formatDateTime = (value: string): string => {
ticket: ticket.id, ticket: ticket.id,
}) })
" "
class="grid gap-4 rounded-xl border border-dashed border-border p-4" class="border-border grid gap-4 rounded-xl border border-dashed p-4"
v-slot="{ errors, processing }" v-slot="{ errors, processing }"
> >
<div class="grid gap-2"> <div class="grid gap-2">
@@ -974,7 +988,7 @@ const formatDateTime = (value: string): string => {
<select <select
id="ticket_link_type_id" id="ticket_link_type_id"
name="ticket_link_type_id" name="ticket_link_type_id"
class="rounded-md border border-input bg-background px-3 py-2 text-sm shadow-xs transition-[color,box-shadow] outline-none focus-visible:border-ring focus-visible:ring-[3px] focus-visible:ring-ring/50" class="border-input bg-background shadow-xs focus-visible:border-ring focus-visible:ring-ring/50 rounded-md border px-3 py-2 text-sm outline-none transition-[color,box-shadow] focus-visible:ring-[3px]"
> >
<option <option
v-for="ticketLinkType in ticketLinkTypes" v-for="ticketLinkType in ticketLinkTypes"
@@ -996,7 +1010,7 @@ const formatDateTime = (value: string): string => {
<select <select
id="linked_ticket_id" id="linked_ticket_id"
name="linked_ticket_id" name="linked_ticket_id"
class="rounded-md border border-input bg-background px-3 py-2 text-sm shadow-xs transition-[color,box-shadow] outline-none focus-visible:border-ring focus-visible:ring-[3px] focus-visible:ring-ring/50" class="border-input bg-background shadow-xs focus-visible:border-ring focus-visible:ring-ring/50 rounded-md border px-3 py-2 text-sm outline-none transition-[color,box-shadow] focus-visible:ring-[3px]"
> >
<option <option
v-for="ticketLinkOption in ticketLinkOptions" v-for="ticketLinkOption in ticketLinkOptions"
@@ -1013,17 +1027,14 @@ const formatDateTime = (value: string): string => {
/> />
</div> </div>
<Button <Button type="submit" :disabled="processing">
type="submit"
:disabled="processing"
>
Save link Save link
</Button> </Button>
</Form> </Form>
<div <div
v-if="linkedTickets.length === 0" v-if="linkedTickets.length === 0"
class="rounded-xl border border-dashed border-border px-4 py-6 text-sm text-muted-foreground" class="border-border text-muted-foreground rounded-xl border border-dashed px-4 py-6 text-sm"
> >
No ticket links are configured for this ticket No ticket links are configured for this ticket
yet. yet.
@@ -1033,9 +1044,11 @@ const formatDateTime = (value: string): string => {
<div <div
v-for="linkedTicket in linkedTickets" v-for="linkedTicket in linkedTickets"
:key="linkedTicket.id" :key="linkedTicket.id"
class="rounded-xl border border-border px-4 py-4" class="border-border rounded-xl border px-4 py-4"
> >
<div class="flex flex-wrap items-center gap-2"> <div
class="flex flex-wrap items-center gap-2"
>
<Badge variant="secondary"> <Badge variant="secondary">
{{ {{
linkedTicket.ticket_link_type linkedTicket.ticket_link_type
@@ -1050,7 +1063,7 @@ const formatDateTime = (value: string): string => {
.linked_ticket.id, .linked_ticket.id,
}) })
" "
class="font-medium text-foreground transition hover:text-primary" class="text-foreground hover:text-primary font-medium transition"
> >
{{ {{
linkedTicket.linked_ticket linkedTicket.linked_ticket
@@ -1058,7 +1071,9 @@ const formatDateTime = (value: string): string => {
}} }}
</Link> </Link>
</div> </div>
<p class="mt-2 text-sm text-muted-foreground"> <p
class="text-muted-foreground mt-2 text-sm"
>
{{ linkedTicket.linked_ticket.title }} {{ linkedTicket.linked_ticket.title }}
</p> </p>
@@ -1069,8 +1084,7 @@ const formatDateTime = (value: string): string => {
{ {
project: project.id, project: project.id,
ticket: ticket.id, ticket: ticket.id,
ticketLink: ticketLink: linkedTicket.id,
linkedTicket.id,
}, },
) )
" "
@@ -1106,7 +1120,7 @@ const formatDateTime = (value: string): string => {
v-if=" v-if="
visibleRepositoryPullRequests.length === 0 visibleRepositoryPullRequests.length === 0
" "
class="rounded-xl border border-dashed border-border px-4 py-6 text-sm text-muted-foreground" class="border-border text-muted-foreground rounded-xl border border-dashed px-4 py-6 text-sm"
> >
No matching pull requests were found across the No matching pull requests were found across the
linked repositories you can access. linked repositories you can access.
@@ -1119,7 +1133,7 @@ const formatDateTime = (value: string): string => {
repositoryPullRequest repositoryPullRequest
.repository_connection.id .repository_connection.id
" "
class="rounded-xl border border-border px-4 py-4" class="border-border rounded-xl border px-4 py-4"
> >
<div <div
class="flex flex-wrap items-center gap-2" class="flex flex-wrap items-center gap-2"
@@ -1141,7 +1155,7 @@ const formatDateTime = (value: string): string => {
</div> </div>
<p <p
class="mt-2 text-sm text-muted-foreground" class="text-muted-foreground mt-2 text-sm"
> >
{{ {{
repositoryPullRequest repositoryPullRequest
@@ -1158,14 +1172,18 @@ const formatDateTime = (value: string): string => {
class="mt-3 space-y-3" class="mt-3 space-y-3"
> >
<p <p
class="text-sm text-muted-foreground" class="text-muted-foreground text-sm"
> >
Connect a matching Git account in Connect a matching Git account in
your user settings to inspect pull your user settings to inspect pull
requests for this repository. requests for this repository.
</p> </p>
<Button as-child variant="outline" size="sm"> <Button
as-child
variant="outline"
size="sm"
>
<Link :href="editGitConnections()"> <Link :href="editGitConnections()">
Open Git connections Open Git connections
</Link> </Link>
@@ -1183,7 +1201,7 @@ const formatDateTime = (value: string): string => {
<div <div
v-for="pullRequest in repositoryPullRequest.pull_requests" v-for="pullRequest in repositoryPullRequest.pull_requests"
:key="pullRequest.html_url" :key="pullRequest.html_url"
class="rounded-xl border border-border/70 px-4 py-3" class="border-border/70 rounded-xl border px-4 py-3"
> >
<div <div
class="flex flex-wrap items-center gap-2" class="flex flex-wrap items-center gap-2"
@@ -1192,26 +1210,22 @@ const formatDateTime = (value: string): string => {
#{{ pullRequest.number }} #{{ pullRequest.number }}
</Badge> </Badge>
<Badge variant="secondary"> <Badge variant="secondary">
{{ {{ pullRequest.status }}
pullRequest.status
}}
</Badge> </Badge>
<a <a
:href="pullRequest.html_url" :href="pullRequest.html_url"
target="_blank" target="_blank"
rel="noreferrer" rel="noreferrer"
class="font-medium text-foreground transition hover:text-primary" class="text-foreground hover:text-primary font-medium transition"
> >
{{ pullRequest.title }} {{ pullRequest.title }}
</a> </a>
</div> </div>
<p <p
class="mt-2 text-sm text-muted-foreground" class="text-muted-foreground mt-2 text-sm"
> >
Source branch: Source branch:
{{ {{ pullRequest.source_branch }}
pullRequest.source_branch
}}
</p> </p>
</div> </div>
</div> </div>
@@ -1232,7 +1246,7 @@ const formatDateTime = (value: string): string => {
<CardContent> <CardContent>
<div <div
v-if="childTicketTree.length === 0" v-if="childTicketTree.length === 0"
class="rounded-xl border border-dashed border-border px-4 py-6 text-sm text-muted-foreground" class="border-border text-muted-foreground rounded-xl border border-dashed px-4 py-6 text-sm"
> >
No child tickets are assigned to this ticket No child tickets are assigned to this ticket
yet. yet.
@@ -1260,7 +1274,7 @@ const formatDateTime = (value: string): string => {
v-if=" v-if="
(ticket.worklog_entries?.length ?? 0) === 0 (ticket.worklog_entries?.length ?? 0) === 0
" "
class="rounded-xl border border-dashed border-border px-4 py-6 text-sm text-muted-foreground" class="border-border text-muted-foreground rounded-xl border border-dashed px-4 py-6 text-sm"
> >
No worklog entries exist for this ticket yet. No worklog entries exist for this ticket yet.
</div> </div>
@@ -1269,7 +1283,7 @@ const formatDateTime = (value: string): string => {
<div <div
v-for="worklogEntry in ticket.worklog_entries" v-for="worklogEntry in ticket.worklog_entries"
:key="worklogEntry.id" :key="worklogEntry.id"
class="rounded-xl border border-border px-4 py-4" class="border-border rounded-xl border px-4 py-4"
> >
<div <div
class="flex flex-wrap items-center gap-2" class="flex flex-wrap items-center gap-2"
@@ -1278,7 +1292,7 @@ const formatDateTime = (value: string): string => {
{{ worklogEntry.entry_type }} {{ worklogEntry.entry_type }}
</Badge> </Badge>
<span <span
class="text-sm font-medium text-foreground" class="text-foreground text-sm font-medium"
> >
{{ {{
worklogEntry.actor?.name ?? worklogEntry.actor?.name ??
@@ -1286,11 +1300,11 @@ const formatDateTime = (value: string): string => {
}} }}
</span> </span>
</div> </div>
<p class="mt-3 text-sm text-foreground"> <p class="text-foreground mt-3 text-sm">
{{ worklogEntry.summary }} {{ worklogEntry.summary }}
</p> </p>
<p <p
class="mt-2 text-xs text-muted-foreground" class="text-muted-foreground mt-2 text-xs"
> >
{{ {{
formatDateTime( formatDateTime(
@@ -89,7 +89,7 @@ const breadcrumbs: BreadcrumbItem[] = [
<CardContent class="flex flex-wrap gap-3"> <CardContent class="flex flex-wrap gap-3">
<Badge class="px-3 py-1">Backlog</Badge> <Badge class="px-3 py-1">Backlog</Badge>
<p class="text-sm text-muted-foreground"> <p class="text-muted-foreground text-sm">
Tickets will later be valid only in backlog or in one of Tickets will later be valid only in backlog or in one of
the ordered columns below. the ordered columns below.
</p> </p>
@@ -148,7 +148,7 @@ const breadcrumbs: BreadcrumbItem[] = [
<CardContent class="space-y-4 p-6"> <CardContent class="space-y-4 p-6">
<div <div
v-if="boardColumns.length === 0" v-if="boardColumns.length === 0"
class="text-sm text-muted-foreground" class="text-muted-foreground text-sm"
> >
No board columns exist yet. No board columns exist yet.
</div> </div>
@@ -156,7 +156,7 @@ const breadcrumbs: BreadcrumbItem[] = [
<div <div
v-for="column in boardColumns" v-for="column in boardColumns"
:key="column.id" :key="column.id"
class="rounded-xl border border-border p-4" class="border-border rounded-xl border p-4"
> >
<Form <Form
v-bind=" v-bind="
@@ -105,7 +105,7 @@ const breadcrumbs: BreadcrumbItem[] = [
project.id, project.id,
) )
" "
class="space-y-4 rounded-xl border border-dashed border-border p-4" class="border-border space-y-4 rounded-xl border border-dashed p-4"
v-slot="{ errors, processing }" v-slot="{ errors, processing }"
> >
<div class="grid gap-2"> <div class="grid gap-2">
@@ -127,7 +127,7 @@ const breadcrumbs: BreadcrumbItem[] = [
<div <div
v-for="ticketType in ticketTypes" v-for="ticketType in ticketTypes"
:key="ticketType.id" :key="ticketType.id"
class="rounded-xl border border-border p-4" class="border-border rounded-xl border p-4"
> >
<Form <Form
v-bind=" v-bind="
@@ -155,7 +155,7 @@ const breadcrumbs: BreadcrumbItem[] = [
}} }}
</Badge> </Badge>
<p <p
class="text-xs tracking-wide text-muted-foreground uppercase" class="text-muted-foreground text-xs uppercase tracking-wide"
> >
Position {{ ticketType.position }} Position {{ ticketType.position }}
</p> </p>
@@ -243,7 +243,7 @@ const breadcrumbs: BreadcrumbItem[] = [
project.id, project.id,
) )
" "
class="space-y-4 rounded-xl border border-dashed border-border p-4" class="border-border space-y-4 rounded-xl border border-dashed p-4"
v-slot="{ errors, processing }" v-slot="{ errors, processing }"
> >
<div class="grid gap-2"> <div class="grid gap-2">
@@ -267,7 +267,7 @@ const breadcrumbs: BreadcrumbItem[] = [
<div <div
v-for="ticketPriority in ticketPriorities" v-for="ticketPriority in ticketPriorities"
:key="ticketPriority.id" :key="ticketPriority.id"
class="rounded-xl border border-border p-4" class="border-border rounded-xl border p-4"
> >
<Form <Form
v-bind=" v-bind="
@@ -361,7 +361,7 @@ const breadcrumbs: BreadcrumbItem[] = [
project.id, project.id,
) )
" "
class="space-y-4 rounded-xl border border-dashed border-border p-4" class="border-border space-y-4 rounded-xl border border-dashed p-4"
v-slot="{ errors, processing }" v-slot="{ errors, processing }"
> >
<div class="grid gap-2"> <div class="grid gap-2">
@@ -380,7 +380,7 @@ const breadcrumbs: BreadcrumbItem[] = [
<select <select
id="field-type" id="field-type"
name="field_type" name="field_type"
class="rounded-md border border-input bg-background px-3 py-2 text-sm shadow-xs transition-[color,box-shadow] outline-none focus-visible:border-ring focus-visible:ring-[3px] focus-visible:ring-ring/50" class="border-input bg-background shadow-xs focus-visible:border-ring focus-visible:ring-ring/50 rounded-md border px-3 py-2 text-sm outline-none transition-[color,box-shadow] focus-visible:ring-[3px]"
> >
<option <option
v-for="option in fieldTypeOptions" v-for="option in fieldTypeOptions"
@@ -401,7 +401,7 @@ const breadcrumbs: BreadcrumbItem[] = [
<div <div
v-for="fieldDefinition in ticketFieldDefinitions" v-for="fieldDefinition in ticketFieldDefinitions"
:key="fieldDefinition.id" :key="fieldDefinition.id"
class="rounded-xl border border-border p-4" class="border-border rounded-xl border p-4"
> >
<Form <Form
v-bind=" v-bind="
@@ -436,7 +436,7 @@ const breadcrumbs: BreadcrumbItem[] = [
<select <select
:id="`field-type-${fieldDefinition.id}`" :id="`field-type-${fieldDefinition.id}`"
name="field_type" name="field_type"
class="rounded-md border border-input bg-background px-3 py-2 text-sm shadow-xs transition-[color,box-shadow] outline-none focus-visible:border-ring focus-visible:ring-[3px] focus-visible:ring-ring/50" class="border-input bg-background shadow-xs focus-visible:border-ring focus-visible:ring-ring/50 rounded-md border px-3 py-2 text-sm outline-none transition-[color,box-shadow] focus-visible:ring-[3px]"
> >
<option <option
v-for="option in fieldTypeOptions" v-for="option in fieldTypeOptions"
@@ -465,7 +465,9 @@ const breadcrumbs: BreadcrumbItem[] = [
type="number" type="number"
min="1" min="1"
:max="ticketFieldDefinitions.length" :max="ticketFieldDefinitions.length"
:default-value="fieldDefinition.position" :default-value="
fieldDefinition.position
"
required required
/> />
<InputError :message="errors.position" /> <InputError :message="errors.position" />
@@ -521,7 +523,7 @@ const breadcrumbs: BreadcrumbItem[] = [
project.id, project.id,
) )
" "
class="space-y-4 rounded-xl border border-dashed border-border p-4" class="border-border space-y-4 rounded-xl border border-dashed p-4"
v-slot="{ errors, processing }" v-slot="{ errors, processing }"
> >
<div class="grid gap-2"> <div class="grid gap-2">
@@ -545,7 +547,7 @@ const breadcrumbs: BreadcrumbItem[] = [
<div <div
v-for="ticketLinkType in ticketLinkTypes" v-for="ticketLinkType in ticketLinkTypes"
:key="ticketLinkType.id" :key="ticketLinkType.id"
class="rounded-xl border border-border p-4" class="border-border rounded-xl border p-4"
> >
<Form <Form
v-bind=" v-bind="
@@ -47,7 +47,9 @@ const breadcrumbs: BreadcrumbItem[] = [
]; ];
const selectableRepositorySources = computed(() => const selectableRepositorySources = computed(() =>
props.availableRepositorySources.filter((source) => source.repositories.length > 0), props.availableRepositorySources.filter(
(source) => source.repositories.length > 0,
),
); );
const repositoryConnectionById = computed( const repositoryConnectionById = computed(
@@ -271,7 +273,7 @@ const submitUpdate = (): void => {
Open Git connections Open Git connections
</Link> </Link>
</Button> </Button>
<p class="text-sm text-muted-foreground"> <p class="text-muted-foreground text-sm">
Without a matching personal connection, KanbanGit only Without a matching personal connection, KanbanGit only
shows the repository name and links you to your user shows the repository name and links you to your user
settings. settings.
@@ -293,7 +295,7 @@ const submitUpdate = (): void => {
<CardContent> <CardContent>
<div <div
v-if="selectableRepositorySources.length === 0" v-if="selectableRepositorySources.length === 0"
class="rounded-xl border border-dashed border-border px-4 py-6 text-sm text-muted-foreground" class="border-border text-muted-foreground rounded-xl border border-dashed px-4 py-6 text-sm"
> >
Add a personal Git connection first, or fix an Add a personal Git connection first, or fix an
existing connection that currently cannot load existing connection that currently cannot load
@@ -311,13 +313,17 @@ const submitUpdate = (): void => {
</Label> </Label>
<select <select
id="create-user-git-connection" id="create-user-git-connection"
v-model="createForm.user_git_connection_id" v-model="
class="rounded-md border border-input bg-background px-3 py-2 text-sm shadow-xs transition-[color,box-shadow] outline-none focus-visible:border-ring focus-visible:ring-[3px] focus-visible:ring-ring/50" createForm.user_git_connection_id
"
class="border-input bg-background shadow-xs focus-visible:border-ring focus-visible:ring-ring/50 rounded-md border px-3 py-2 text-sm outline-none transition-[color,box-shadow] focus-visible:ring-[3px]"
> >
<option <option
v-for="source in selectableRepositorySources" v-for="source in selectableRepositorySources"
:key="source.user_git_connection_id" :key="source.user_git_connection_id"
:value="source.user_git_connection_id" :value="
source.user_git_connection_id
"
> >
{{ {{
`${source.provider_label} · ${source.account_login} @ ${source.base_url}` `${source.provider_label} · ${source.account_login} @ ${source.base_url}`
@@ -326,7 +332,8 @@ const submitUpdate = (): void => {
</select> </select>
<InputError <InputError
:message=" :message="
createForm.errors.user_git_connection_id createForm.errors
.user_git_connection_id
" "
/> />
</div> </div>
@@ -340,7 +347,7 @@ const submitUpdate = (): void => {
v-model=" v-model="
createForm.provider_repository_id createForm.provider_repository_id
" "
class="rounded-md border border-input bg-background px-3 py-2 text-sm shadow-xs transition-[color,box-shadow] outline-none focus-visible:border-ring focus-visible:ring-[3px] focus-visible:ring-ring/50" class="border-input bg-background shadow-xs focus-visible:border-ring focus-visible:ring-ring/50 rounded-md border px-3 py-2 text-sm outline-none transition-[color,box-shadow] focus-visible:ring-[3px]"
> >
<option <option
v-for="repository in createRepositories" v-for="repository in createRepositories"
@@ -358,7 +365,8 @@ const submitUpdate = (): void => {
</select> </select>
<InputError <InputError
:message=" :message="
createForm.errors.provider_repository_id createForm.errors
.provider_repository_id
" "
/> />
</div> </div>
@@ -382,9 +390,9 @@ const submitUpdate = (): void => {
<CardHeader> <CardHeader>
<CardTitle>Relink repository</CardTitle> <CardTitle>Relink repository</CardTitle>
<CardDescription> <CardDescription>
Update an existing project repository Update an existing project repository connection
connection by choosing a different repository by choosing a different repository from one of
from one of your personal Git connections. your personal Git connections.
</CardDescription> </CardDescription>
</CardHeader> </CardHeader>
@@ -402,7 +410,7 @@ const submitUpdate = (): void => {
v-model=" v-model="
updateForm.repository_connection_id updateForm.repository_connection_id
" "
class="rounded-md border border-input bg-background px-3 py-2 text-sm shadow-xs transition-[color,box-shadow] outline-none focus-visible:border-ring focus-visible:ring-[3px] focus-visible:ring-ring/50" class="border-input bg-background shadow-xs focus-visible:border-ring focus-visible:ring-ring/50 rounded-md border px-3 py-2 text-sm outline-none transition-[color,box-shadow] focus-visible:ring-[3px]"
> >
<option <option
v-for="repositoryConnection in repositoryConnections" v-for="repositoryConnection in repositoryConnections"
@@ -422,13 +430,17 @@ const submitUpdate = (): void => {
</Label> </Label>
<select <select
id="update-user-git-connection" id="update-user-git-connection"
v-model="updateForm.user_git_connection_id" v-model="
class="rounded-md border border-input bg-background px-3 py-2 text-sm shadow-xs transition-[color,box-shadow] outline-none focus-visible:border-ring focus-visible:ring-[3px] focus-visible:ring-ring/50" updateForm.user_git_connection_id
"
class="border-input bg-background shadow-xs focus-visible:border-ring focus-visible:ring-ring/50 rounded-md border px-3 py-2 text-sm outline-none transition-[color,box-shadow] focus-visible:ring-[3px]"
> >
<option <option
v-for="source in selectableRepositorySources" v-for="source in selectableRepositorySources"
:key="source.user_git_connection_id" :key="source.user_git_connection_id"
:value="source.user_git_connection_id" :value="
source.user_git_connection_id
"
> >
{{ {{
`${source.provider_label} · ${source.account_login} @ ${source.base_url}` `${source.provider_label} · ${source.account_login} @ ${source.base_url}`
@@ -437,7 +449,8 @@ const submitUpdate = (): void => {
</select> </select>
<InputError <InputError
:message=" :message="
updateForm.errors.user_git_connection_id updateForm.errors
.user_git_connection_id
" "
/> />
</div> </div>
@@ -451,7 +464,7 @@ const submitUpdate = (): void => {
v-model=" v-model="
updateForm.provider_repository_id updateForm.provider_repository_id
" "
class="rounded-md border border-input bg-background px-3 py-2 text-sm shadow-xs transition-[color,box-shadow] outline-none focus-visible:border-ring focus-visible:ring-[3px] focus-visible:ring-ring/50" class="border-input bg-background shadow-xs focus-visible:border-ring focus-visible:ring-ring/50 rounded-md border px-3 py-2 text-sm outline-none transition-[color,box-shadow] focus-visible:ring-[3px]"
> >
<option <option
v-for="repository in updateRepositories" v-for="repository in updateRepositories"
@@ -469,7 +482,8 @@ const submitUpdate = (): void => {
</select> </select>
<InputError <InputError
:message=" :message="
updateForm.errors.provider_repository_id updateForm.errors
.provider_repository_id
" "
/> />
</div> </div>
@@ -500,7 +514,7 @@ const submitUpdate = (): void => {
<CardContent class="space-y-4 p-6"> <CardContent class="space-y-4 p-6">
<div <div
v-if="repositoryConnections.length === 0" v-if="repositoryConnections.length === 0"
class="rounded-xl border border-dashed border-border px-4 py-6 text-sm text-muted-foreground" class="border-border text-muted-foreground rounded-xl border border-dashed px-4 py-6 text-sm"
> >
No repositories are linked to this project yet. No repositories are linked to this project yet.
</div> </div>
@@ -508,20 +522,24 @@ const submitUpdate = (): void => {
<div <div
v-for="repositoryConnection in repositoryConnections" v-for="repositoryConnection in repositoryConnections"
:key="repositoryConnection.id" :key="repositoryConnection.id"
class="rounded-xl border border-border p-4" class="border-border rounded-xl border p-4"
> >
<div <div
class="flex flex-col gap-4 sm:flex-row sm:items-start sm:justify-between" class="flex flex-col gap-4 sm:flex-row sm:items-start sm:justify-between"
> >
<div class="space-y-2"> <div class="space-y-2">
<div class="flex flex-wrap items-center gap-2"> <div
class="flex flex-wrap items-center gap-2"
>
<Badge> <Badge>
{{ {{
repositoryConnection.provider_label repositoryConnection.provider_label
}} }}
</Badge> </Badge>
<Badge variant="secondary"> <Badge variant="secondary">
{{ repositoryConnection.base_url }} {{
repositoryConnection.base_url
}}
</Badge> </Badge>
</div> </div>
<div> <div>
@@ -530,7 +548,9 @@ const submitUpdate = (): void => {
repositoryConnection.repository_full_name repositoryConnection.repository_full_name
}} }}
</p> </p>
<p class="text-sm text-muted-foreground"> <p
class="text-muted-foreground text-sm"
>
{{ {{
repositoryConnection.repository_name repositoryConnection.repository_name
}} }}
@@ -574,8 +594,10 @@ const submitUpdate = (): void => {
</div> </div>
<p <p
v-if="!repositoryConnection.has_personal_access" v-if="
class="mt-3 text-sm text-muted-foreground" !repositoryConnection.has_personal_access
"
class="text-muted-foreground mt-3 text-sm"
> >
This project link is visible, but you need a This project link is visible, but you need a
matching Git connection in your user matching Git connection in your user
@@ -625,14 +647,14 @@ const submitUpdate = (): void => {
<div <div
v-for="source in availableRepositorySources" v-for="source in availableRepositorySources"
:key="source.user_git_connection_id" :key="source.user_git_connection_id"
class="rounded-xl border border-border p-4" class="border-border rounded-xl border p-4"
> >
<div class="flex flex-wrap items-center gap-2"> <div class="flex flex-wrap items-center gap-2">
<Badge>{{ source.provider_label }}</Badge> <Badge>{{ source.provider_label }}</Badge>
<span class="text-sm font-medium"> <span class="text-sm font-medium">
{{ source.account_login }} {{ source.account_login }}
</span> </span>
<span class="text-xs text-muted-foreground"> <span class="text-muted-foreground text-xs">
{{ source.base_url }} {{ source.base_url }}
</span> </span>
</div> </div>
@@ -646,10 +668,11 @@ const submitUpdate = (): void => {
<p <p
v-else v-else
class="mt-3 text-sm text-muted-foreground" class="text-muted-foreground mt-3 text-sm"
> >
{{ source.repositories.length }} repositories {{ source.repositories.length }}
available through this connection. repositories available through this
connection.
</p> </p>
</div> </div>
</CardContent> </CardContent>
+45 -17
View File
@@ -41,7 +41,7 @@ const breadcrumbItems: BreadcrumbItem[] = [
title="Git connections" title="Git connections"
description="Add your personal Git provider credentials here. Project repository links will use these connections to fetch repositories, branches, and pull requests you can access." description="Add your personal Git provider credentials here. Project repository links will use these connections to fetch repositories, branches, and pull requests you can access."
/> />
<p class="text-sm text-muted-foreground"> <p class="text-muted-foreground text-sm">
Each user needs their own application key. Without a Each user needs their own application key. Without a
matching personal connection, KanbanGit can only show matching personal connection, KanbanGit can only show
repository names and will link you back to this page. repository names and will link you back to this page.
@@ -71,7 +71,11 @@ const breadcrumbItems: BreadcrumbItem[] = [
class="space-y-4" class="space-y-4"
v-slot="{ errors, processing }" v-slot="{ errors, processing }"
> >
<input name="provider" type="hidden" value="gitea" /> <input
name="provider"
type="hidden"
value="gitea"
/>
<div class="grid gap-2"> <div class="grid gap-2">
<Label for="base_url">Gitea base URL</Label> <Label for="base_url">Gitea base URL</Label>
@@ -87,7 +91,9 @@ const breadcrumbItems: BreadcrumbItem[] = [
</div> </div>
<div class="grid gap-2"> <div class="grid gap-2">
<Label for="api_token">Application token</Label> <Label for="api_token"
>Application token</Label
>
<Input <Input
id="api_token" id="api_token"
name="api_token" name="api_token"
@@ -117,7 +123,7 @@ const breadcrumbItems: BreadcrumbItem[] = [
<CardContent class="space-y-4 p-6"> <CardContent class="space-y-4 p-6">
<div <div
v-if="gitConnections.length === 0" v-if="gitConnections.length === 0"
class="rounded-xl border border-dashed border-border px-4 py-6 text-sm text-muted-foreground" class="border-border text-muted-foreground rounded-xl border border-dashed px-4 py-6 text-sm"
> >
No Git connections have been added yet. No Git connections have been added yet.
</div> </div>
@@ -125,30 +131,40 @@ const breadcrumbItems: BreadcrumbItem[] = [
<div <div
v-for="gitConnection in gitConnections" v-for="gitConnection in gitConnections"
:key="gitConnection.id" :key="gitConnection.id"
class="rounded-xl border border-border p-4" class="border-border rounded-xl border p-4"
> >
<div <div
class="mb-4 flex flex-wrap items-start justify-between gap-3" class="mb-4 flex flex-wrap items-start justify-between gap-3"
> >
<div class="space-y-1"> <div class="space-y-1">
<div class="flex flex-wrap items-center gap-2"> <div
<Badge>{{ gitConnection.provider_label }}</Badge> class="flex flex-wrap items-center gap-2"
>
<Badge>{{
gitConnection.provider_label
}}</Badge>
<span class="text-sm font-medium"> <span class="text-sm font-medium">
{{ gitConnection.account_login }} {{
gitConnection.account_login
}}
</span> </span>
</div> </div>
<p class="text-sm text-muted-foreground"> <p
class="text-muted-foreground text-sm"
>
{{ {{
gitConnection.account_name ?? gitConnection.account_name ??
'Unnamed remote account' 'Unnamed remote account'
}} }}
</p> </p>
<p class="text-xs text-muted-foreground"> <p
class="text-muted-foreground text-xs"
>
{{ gitConnection.base_url }} {{ gitConnection.base_url }}
</p> </p>
</div> </div>
<p class="text-xs text-muted-foreground"> <p class="text-muted-foreground text-xs">
Remote user ID: Remote user ID:
{{ gitConnection.provider_user_id }} {{ gitConnection.provider_user_id }}
</p> </p>
@@ -170,21 +186,29 @@ const breadcrumbItems: BreadcrumbItem[] = [
/> />
<div class="grid gap-2"> <div class="grid gap-2">
<Label :for="`base-url-${gitConnection.id}`"> <Label
:for="`base-url-${gitConnection.id}`"
>
Gitea base URL Gitea base URL
</Label> </Label>
<Input <Input
:id="`base-url-${gitConnection.id}`" :id="`base-url-${gitConnection.id}`"
name="base_url" name="base_url"
type="url" type="url"
:default-value="gitConnection.base_url" :default-value="
gitConnection.base_url
"
required required
/> />
<InputError :message="errors.base_url" /> <InputError
:message="errors.base_url"
/>
</div> </div>
<div class="grid gap-2"> <div class="grid gap-2">
<Label :for="`token-${gitConnection.id}`"> <Label
:for="`token-${gitConnection.id}`"
>
New application token New application token
</Label> </Label>
<Input <Input
@@ -194,10 +218,14 @@ const breadcrumbItems: BreadcrumbItem[] = [
required required
placeholder="Paste a new token to verify and save" placeholder="Paste a new token to verify and save"
/> />
<InputError :message="errors.api_token" /> <InputError
:message="errors.api_token"
/>
</div> </div>
<div class="flex flex-wrap justify-between gap-3"> <div
class="flex flex-wrap justify-between gap-3"
>
<Button <Button
type="submit" type="submit"
variant="outline" variant="outline"
+2 -2
View File
@@ -81,12 +81,12 @@ const user = computed(() => page.props.auth.user);
</div> </div>
<div v-if="mustVerifyEmail && !user.email_verified_at"> <div v-if="mustVerifyEmail && !user.email_verified_at">
<p class="-mt-4 text-sm text-muted-foreground"> <p class="text-muted-foreground -mt-4 text-sm">
Your email address is unverified. Your email address is unverified.
<Link <Link
:href="send()" :href="send()"
as="button" as="button"
class="text-foreground underline decoration-neutral-300 underline-offset-4 transition-colors duration-300 ease-out hover:decoration-current! dark:decoration-neutral-500" class="text-foreground hover:decoration-current! underline decoration-neutral-300 underline-offset-4 transition-colors duration-300 ease-out dark:decoration-neutral-500"
> >
Click here to resend the verification email. Click here to resend the verification email.
</Link> </Link>
+2 -2
View File
@@ -144,7 +144,7 @@ onUnmounted(() => clearTwoFactorAuthData());
v-if="!twoFactorEnabled" v-if="!twoFactorEnabled"
class="flex flex-col items-start justify-start space-y-4" class="flex flex-col items-start justify-start space-y-4"
> >
<p class="text-sm text-muted-foreground"> <p class="text-muted-foreground text-sm">
When you enable two-factor authentication, you will be When you enable two-factor authentication, you will be
prompted for a secure pin during login. This pin can be prompted for a secure pin during login. This pin can be
retrieved from a TOTP-supported application on your retrieved from a TOTP-supported application on your
@@ -175,7 +175,7 @@ onUnmounted(() => clearTwoFactorAuthData());
v-else v-else
class="flex flex-col items-start justify-start space-y-4" class="flex flex-col items-start justify-start space-y-4"
> >
<p class="text-sm text-muted-foreground"> <p class="text-muted-foreground text-sm">
You will be prompted for a secure, random pin during You will be prompted for a secure, random pin during
login, which you can retrieve from the TOTP-supported login, which you can retrieve from the TOTP-supported
application on your phone. application on your phone.
+3 -3
View File
@@ -137,7 +137,7 @@ const breadcrumbs: BreadcrumbItem[] = [
:id="`team-members-${team.id}`" :id="`team-members-${team.id}`"
name="user_ids[]" name="user_ids[]"
multiple multiple
class="min-h-44 rounded-md border border-input bg-background px-3 py-2 text-sm shadow-xs transition-[color,box-shadow] outline-none focus-visible:border-ring focus-visible:ring-[3px] focus-visible:ring-ring/50" class="border-input bg-background shadow-xs focus-visible:border-ring focus-visible:ring-ring/50 min-h-44 rounded-md border px-3 py-2 text-sm outline-none transition-[color,box-shadow] focus-visible:ring-[3px]"
> >
<option <option
v-for="user in users" v-for="user in users"
@@ -150,7 +150,7 @@ const breadcrumbs: BreadcrumbItem[] = [
{{ user.name }} ({{ user.email }}) {{ user.name }} ({{ user.email }})
</option> </option>
</select> </select>
<p class="text-sm text-muted-foreground"> <p class="text-muted-foreground text-sm">
Hold Cmd or Ctrl to select multiple Hold Cmd or Ctrl to select multiple
users. users.
</p> </p>
@@ -168,7 +168,7 @@ const breadcrumbs: BreadcrumbItem[] = [
</Card> </Card>
<Card v-if="teams.length === 0"> <Card v-if="teams.length === 0">
<CardContent class="p-6 text-sm text-muted-foreground"> <CardContent class="text-muted-foreground p-6 text-sm">
No teams exist yet. No teams exist yet.
</CardContent> </CardContent>
</Card> </Card>
+2
View File
@@ -1,4 +1,6 @@
import type { Auth } from '@/types/auth'; import type { Auth } from '@/types/auth';
import type { Page, Router } from '@inertiajs/core';
import { createHeadManager } from '@inertiajs/vue3';
// Extend ImportMeta interface for Vite... // Extend ImportMeta interface for Vite...
declare module 'vite/client' { declare module 'vite/client' {