192 lines
8.3 KiB
Vue
192 lines
8.3 KiB
Vue
<script setup lang="ts">
|
|
import { Link } from '@inertiajs/vue3';
|
|
import { ExternalLink, GitPullRequest } from 'lucide-vue-next';
|
|
import { computed } from 'vue';
|
|
import FeedbackState from '@/components/FeedbackState.vue';
|
|
import { Badge } from '@/components/ui/badge';
|
|
import { Button } from '@/components/ui/button';
|
|
import {
|
|
Card,
|
|
CardContent,
|
|
CardDescription,
|
|
CardHeader,
|
|
CardTitle,
|
|
} from '@/components/ui/card';
|
|
import { useLocalization } from '@/composables/useLocalization';
|
|
import { edit as editGitConnections } from '@/routes/git-connections';
|
|
import type { TicketGitPullRequestsProps } from '@/types/ticket-detail';
|
|
|
|
const props = defineProps<TicketGitPullRequestsProps>();
|
|
const { t } = useLocalization();
|
|
|
|
const visibleRepositories = computed(() =>
|
|
props.repositoryPullRequests.filter(
|
|
(repositoryPullRequest) =>
|
|
repositoryPullRequest.pull_requests.length > 0 ||
|
|
repositoryPullRequest.error !== null ||
|
|
!repositoryPullRequest.repository_connection.has_personal_access,
|
|
),
|
|
);
|
|
</script>
|
|
|
|
<template>
|
|
<Card class="min-w-0 gap-0 overflow-hidden">
|
|
<CardHeader class="border-b">
|
|
<CardTitle class="flex items-center gap-2">
|
|
<GitPullRequest
|
|
class="text-primary size-5 shrink-0"
|
|
aria-hidden="true"
|
|
/>
|
|
{{ t('ticketDetail.pullRequests') }}
|
|
</CardTitle>
|
|
<CardDescription
|
|
>{ t('ticketDetail.pullRequestsDescription') }}</CardDescription
|
|
>
|
|
</CardHeader>
|
|
|
|
<CardContent class="grid gap-4 pt-6">
|
|
<FeedbackState
|
|
v-if="repositoryPullRequests.length === 0"
|
|
state="empty"
|
|
:title="t('ticketDetail.noLinkedRepositories')"
|
|
:description="t('ticketDetail.noLinkedRepositoriesDescription')"
|
|
/>
|
|
|
|
<FeedbackState
|
|
v-else-if="visibleRepositories.length === 0"
|
|
state="empty"
|
|
:title="t('tickets.noPullRequests')"
|
|
:description="t('tickets.noPullRequestsDescription')"
|
|
/>
|
|
|
|
<article
|
|
v-for="repositoryPullRequest in visibleRepositories"
|
|
v-else
|
|
:key="repositoryPullRequest.repository_connection.id"
|
|
class="border-border grid min-w-0 gap-4 rounded-lg border p-4"
|
|
>
|
|
<header class="grid min-w-0 gap-2">
|
|
<div class="flex min-w-0 flex-wrap items-center gap-2">
|
|
<Badge variant="secondary">
|
|
{{
|
|
repositoryPullRequest.repository_connection
|
|
.provider_label
|
|
}}
|
|
</Badge>
|
|
<a
|
|
:href="
|
|
repositoryPullRequest.repository_connection
|
|
.repository_url
|
|
"
|
|
target="_blank"
|
|
rel="noopener noreferrer"
|
|
:aria-label="
|
|
t('ticketDetail.openRepositoryExternal', {
|
|
repository:
|
|
repositoryPullRequest
|
|
.repository_connection
|
|
.repository_full_name,
|
|
provider:
|
|
repositoryPullRequest
|
|
.repository_connection
|
|
.provider_label,
|
|
})
|
|
"
|
|
class="hover:text-primary focus-visible:ring-ring/35 group flex min-w-0 items-center gap-1.5 rounded-sm font-medium outline-none transition-colors focus-visible:ring-2"
|
|
>
|
|
<span class="wrap-anywhere">{{
|
|
repositoryPullRequest.repository_connection
|
|
.repository_full_name
|
|
}}</span>
|
|
<ExternalLink
|
|
class="size-3.5 shrink-0 opacity-60 transition-opacity group-hover:opacity-100"
|
|
aria-hidden="true"
|
|
/>
|
|
</a>
|
|
</div>
|
|
<p class="text-muted-foreground text-xs">
|
|
{{
|
|
repositoryPullRequest.repository_connection.base_url
|
|
}}
|
|
</p>
|
|
</header>
|
|
|
|
<FeedbackState
|
|
v-if="
|
|
!repositoryPullRequest.repository_connection
|
|
.has_personal_access
|
|
"
|
|
state="empty"
|
|
:title="t('ticketDetail.gitAccessRequired')"
|
|
:description="t('ticketDetail.inspectPullRequests')"
|
|
>
|
|
<Button
|
|
as-child
|
|
variant="outline"
|
|
size="sm"
|
|
class="justify-self-start"
|
|
>
|
|
<Link :href="editGitConnections()">{{
|
|
t('ticketDetail.openGitConnections')
|
|
}}</Link>
|
|
</Button>
|
|
</FeedbackState>
|
|
|
|
<FeedbackState
|
|
v-else-if="repositoryPullRequest.error"
|
|
state="error"
|
|
:title="t('ticketDetail.pullRequestsUnavailable')"
|
|
:description="repositoryPullRequest.error"
|
|
/>
|
|
|
|
<ul v-else class="grid min-w-0 gap-3">
|
|
<li
|
|
v-for="pullRequest in repositoryPullRequest.pull_requests"
|
|
:key="pullRequest.html_url"
|
|
class="border-border/70 bg-muted/20 grid min-w-0 gap-2 rounded-md border px-4 py-3"
|
|
>
|
|
<div class="flex min-w-0 flex-wrap items-center gap-2">
|
|
<Badge variant="outline">
|
|
#{{ pullRequest.number }}
|
|
</Badge>
|
|
<Badge variant="secondary">
|
|
{{ pullRequest.status }}
|
|
</Badge>
|
|
<a
|
|
:href="pullRequest.html_url"
|
|
target="_blank"
|
|
rel="noopener noreferrer"
|
|
:aria-label="
|
|
t('ticketDetail.openPullRequestExternal', {
|
|
number: pullRequest.number,
|
|
provider:
|
|
repositoryPullRequest
|
|
.repository_connection
|
|
.provider_label,
|
|
})
|
|
"
|
|
class="hover:text-primary focus-visible:ring-ring/35 group flex min-w-0 items-center gap-1.5 rounded-sm font-medium outline-none transition-colors focus-visible:ring-2"
|
|
>
|
|
<span class="wrap-anywhere">{{
|
|
pullRequest.title
|
|
}}</span>
|
|
<ExternalLink
|
|
class="size-3.5 shrink-0 opacity-60 transition-opacity group-hover:opacity-100"
|
|
aria-hidden="true"
|
|
/>
|
|
</a>
|
|
</div>
|
|
<p class="text-muted-foreground text-xs">
|
|
{{
|
|
t('ticketDetail.sourceBranch', {
|
|
name: pullRequest.source_branch,
|
|
})
|
|
}}
|
|
</p>
|
|
</li>
|
|
</ul>
|
|
</article>
|
|
</CardContent>
|
|
</Card>
|
|
</template>
|