From be13272eb186fc4b50708385f4c57eec1e1660bc Mon Sep 17 00:00:00 2001 From: bot-hermes Date: Fri, 14 Aug 2026 01:01:33 +0000 Subject: [PATCH] feat(ui): issues tabs in GitLab MR and GitHub PR views Add an Issues tab alongside the merge-request / pull-request content in the context panel's PR surface for both providers. The tab lists open issues lazily and expands a selected issue into an inline detail view (body, labels, assignees, comments) with a back action. Read-only: no issue create, update, or close actions. Adds 15 i18n keys across all 11 locales. --- .../ui/src/components/views/GitLabMrView.tsx | 27 ++ .../src/components/views/PullRequestView.tsx | 68 ++- .../views/git/GitHubIssuesSection.tsx | 400 ++++++++++++++++++ .../views/git/GitLabIssuesSection.tsx | 378 +++++++++++++++++ packages/ui/src/lib/i18n/messages/de.ts | 15 + packages/ui/src/lib/i18n/messages/en.ts | 15 + packages/ui/src/lib/i18n/messages/es.ts | 15 + packages/ui/src/lib/i18n/messages/fr.ts | 15 + packages/ui/src/lib/i18n/messages/ja.ts | 15 + packages/ui/src/lib/i18n/messages/ko.ts | 15 + packages/ui/src/lib/i18n/messages/pl.ts | 15 + packages/ui/src/lib/i18n/messages/pt-BR.ts | 15 + packages/ui/src/lib/i18n/messages/uk.ts | 15 + packages/ui/src/lib/i18n/messages/zh-CN.ts | 15 + packages/ui/src/lib/i18n/messages/zh-TW.ts | 15 + 15 files changed, 1022 insertions(+), 16 deletions(-) create mode 100644 packages/ui/src/components/views/git/GitHubIssuesSection.tsx create mode 100644 packages/ui/src/components/views/git/GitLabIssuesSection.tsx diff --git a/packages/ui/src/components/views/GitLabMrView.tsx b/packages/ui/src/components/views/GitLabMrView.tsx index 31948e71..174e50e4 100644 --- a/packages/ui/src/components/views/GitLabMrView.tsx +++ b/packages/ui/src/components/views/GitLabMrView.tsx @@ -5,6 +5,8 @@ import { Button } from '@/components/ui/button'; import { ScrollShadow } from '@/components/ui/ScrollShadow'; import { ScrollableOverlay } from '@/components/ui/ScrollableOverlay'; import { SimpleMarkdownRenderer } from '@/components/chat/MarkdownRenderer'; +import { SortableTabsStrip } from '@/components/ui/sortable-tabs-strip'; +import { GitLabIssuesSection } from '@/components/views/git/GitLabIssuesSection'; import { useRuntimeAPIs } from '@/hooks/useRuntimeAPIs'; import { useEffectiveDirectory } from '@/hooks/useEffectiveDirectory'; import { useGitStatus, useGitStore } from '@/stores/useGitStore'; @@ -83,6 +85,10 @@ export const GitLabMrView: React.FC = () => { setSettingsDialogOpen(true); }, [setSettingsDialogOpen, setSettingsPage]); + // Local tab selection between the merge-request and issues surfaces. Not + // persisted: reopening the panel always lands on merge requests. + const [activeTab, setActiveTab] = React.useState<'mr' | 'issues'>('mr'); + // ---- Current-branch merge request -------------------------------------- const [branchMr, setBranchMr] = React.useState(null); @@ -558,6 +564,23 @@ export const GitLabMrView: React.FC = () => { preventOverscroll >
+
+ setActiveTab(tabId as 'mr' | 'issues')} + layoutMode="fit" + variant="active-pill" + activePillButtonClassName="h-7" + /> +
+ + {activeTab === 'mr' ? ( + <>
{t('contextPanel.gitlabMr.title')}
{t('contextPanel.gitlabMr.listSectionTitle')}
@@ -921,6 +944,10 @@ export const GitLabMrView: React.FC = () => {
)} + + ) : ( + + )}
); diff --git a/packages/ui/src/components/views/PullRequestView.tsx b/packages/ui/src/components/views/PullRequestView.tsx index baade489..9fc3facd 100644 --- a/packages/ui/src/components/views/PullRequestView.tsx +++ b/packages/ui/src/components/views/PullRequestView.tsx @@ -13,7 +13,9 @@ import type { GitRemote } from '@/lib/api/types'; import { useI18n } from '@/lib/i18n'; import { ScrollShadow } from '@/components/ui/ScrollShadow'; import { ScrollableOverlay } from '@/components/ui/ScrollableOverlay'; +import { SortableTabsStrip } from '@/components/ui/sortable-tabs-strip'; import { PullRequestSection } from './git/PullRequestSection'; +import { GitHubIssuesSection } from './git/GitHubIssuesSection'; import { deriveBaseBranch } from './git/baseBranch'; const normalizePath = (value?: string | null): string => @@ -240,14 +242,23 @@ export const PullRequestView: React.FC = () => { worktreeMetadata?.createdFromBranch, ]); - if (!currentDirectory || !currentBranch) { - return ( -
- -
{t('gitView.pullRequest.title')}
-
{t('gitView.pullRequest.createHint')}
-
- ); + // Local tab selection between the pull-request and issues surfaces. Not + // persisted: reopening the panel always lands on pull requests. + const [activeTab, setActiveTab] = React.useState<'pr' | 'issues'>('pr'); + + // Empty state for the pull-request surface: returned full-height when there + // is no effective directory, and shown inside the "Pull requests" tab when + // the current branch has not resolved (issues need no branch, PRs do). + const prEmptyState = ( +
+ +
{t('gitView.pullRequest.title')}
+
{t('gitView.pullRequest.createHint')}
+
+ ); + + if (!currentDirectory) { + return prEmptyState; } return ( @@ -258,14 +269,39 @@ export const PullRequestView: React.FC = () => { disableHorizontal preventOverscroll > - +
+
+ setActiveTab(tabId as 'pr' | 'issues')} + layoutMode="fit" + variant="active-pill" + activePillButtonClassName="h-7" + /> +
+ + {activeTab === 'pr' ? ( + currentBranch ? ( + + ) : ( +
{prEmptyState}
+ ) + ) : ( + + )} +
); }; diff --git a/packages/ui/src/components/views/git/GitHubIssuesSection.tsx b/packages/ui/src/components/views/git/GitHubIssuesSection.tsx new file mode 100644 index 00000000..147da17d --- /dev/null +++ b/packages/ui/src/components/views/git/GitHubIssuesSection.tsx @@ -0,0 +1,400 @@ +import React from 'react'; +import { Icon } from '@/components/icon/Icon'; +import { Button } from '@/components/ui/button'; +import { SimpleMarkdownRenderer } from '@/components/chat/MarkdownRenderer'; +import { useRuntimeAPIs } from '@/hooks/useRuntimeAPIs'; +import { useUIStore } from '@/stores/useUIStore'; +import { formatDateTimeForPreference } from '@/lib/timeFormat'; +import type { + GitHubIssue, + GitHubIssueComment, + GitHubIssueSummary, + GitHubRepoSelector, +} from '@/lib/api/types'; +import { useI18n } from '@/lib/i18n'; + +const issueStateColor = (state: string): string => { + switch (state) { + case 'closed': + return 'var(--pr-closed)'; + default: + return 'var(--pr-open)'; + } +}; + +const issueLabelBadgeClass = + 'inline-flex items-center rounded border border-border/60 bg-surface-elevated px-1.5 py-px typography-micro text-foreground'; + +/** + * Open GitHub issues for the context panel's pull-request view. List and detail + * are fetched lazily: the parent only mounts this component while the Issues + * tab is active. Read-only by design — no create, update, or close actions. + * + * The parent does not gate on GitHub auth state, so the connection state is + * derived from the API results themselves (`connected === false` renders a + * not-connected state with a settings CTA). + */ +export const GitHubIssuesSection: React.FC<{ directory: string }> = ({ directory }) => { + const { t } = useI18n(); + const { github } = useRuntimeAPIs(); + const setSettingsDialogOpen = useUIStore((state) => state.setSettingsDialogOpen); + const setSettingsPage = useUIStore((state) => state.setSettingsPage); + const timeFormatPreference = useUIStore((state) => state.timeFormatPreference); + + // ---- Open issues list ---------------------------------------------------- + + const [issues, setIssues] = React.useState([]); + const [listPage, setListPage] = React.useState(1); + const [listHasMore, setListHasMore] = React.useState(false); + const [listLoading, setListLoading] = React.useState(false); + const [listLoadingMore, setListLoadingMore] = React.useState(false); + const [listError, setListError] = React.useState(null); + const [listNotConnected, setListNotConnected] = React.useState(false); + const [retryToken, setRetryToken] = React.useState(0); + + // ---- Selected issue detail ------------------------------------------------ + + const [selectedNumber, setSelectedNumber] = React.useState(null); + const [selectedSourceRepo, setSelectedSourceRepo] = React.useState< + (GitHubRepoSelector & { source: string }) | null + >(null); + const [issue, setIssue] = React.useState(null); + const [comments, setComments] = React.useState([]); + const [detailLoading, setDetailLoading] = React.useState(false); + const [detailError, setDetailError] = React.useState(null); + + const retry = React.useCallback(() => setRetryToken((value) => value + 1), []); + + const openGitHubSettings = React.useCallback(() => { + setSettingsPage('git'); + setSettingsDialogOpen(true); + }, [setSettingsDialogOpen, setSettingsPage]); + + // A different repository invalidates the previously loaded list and detail so + // a stale repository's issues never leak into the new one. + React.useEffect(() => { + setIssues([]); + setListPage(1); + setListHasMore(false); + setListLoading(false); + setListLoadingMore(false); + setListError(null); + setListNotConnected(false); + setSelectedNumber(null); + setSelectedSourceRepo(null); + setIssue(null); + setComments([]); + setDetailLoading(false); + setDetailError(null); + }, [directory]); + + React.useEffect(() => { + if (!github?.issuesList) { + return; + } + let cancelled = false; + setListLoading(true); + setListError(null); + setListNotConnected(false); + void github + .issuesList(directory, { page: 1 }) + .then((result) => { + if (cancelled) { + return; + } + if (result.connected === false) { + setListNotConnected(true); + return; + } + setIssues(result.issues ?? []); + setListPage(result.page ?? 1); + setListHasMore(Boolean(result.hasMore)); + }) + .catch((error) => { + if (!cancelled) { + setListError(error instanceof Error ? error.message : String(error)); + } + }) + .finally(() => { + if (!cancelled) { + setListLoading(false); + } + }); + return () => { + cancelled = true; + }; + }, [directory, github, retryToken]); + + const loadMore = React.useCallback(async () => { + if (!github?.issuesList || listLoadingMore || listLoading || !listHasMore) { + return; + } + setListLoadingMore(true); + try { + const next = await github.issuesList(directory, { page: listPage + 1 }); + if (next.connected === false) { + setListNotConnected(true); + return; + } + setIssues((previous) => [...previous, ...(next.issues ?? [])]); + setListPage(next.page ?? listPage + 1); + setListHasMore(Boolean(next.hasMore)); + } catch (error) { + setListError(error instanceof Error ? error.message : String(error)); + } finally { + setListLoadingMore(false); + } + }, [directory, github, listHasMore, listLoading, listLoadingMore, listPage]); + + // Selecting a row remembers the summary's sourceRepo too: the server route + // resolves the repo from the directory, but cross-repo issues need the + // explicit sourceRepo to fetch the issue and its comments. + const selectIssue = React.useCallback((item: GitHubIssueSummary) => { + setSelectedNumber(item.number); + setSelectedSourceRepo(item.sourceRepo ?? null); + }, []); + + // Fetch the issue and its comments in parallel whenever a row is selected. A + // cancelled flag keeps a stale selection from overwriting a newer one. + React.useEffect(() => { + if (selectedNumber === null || !github?.issueGet || !github.issueComments) { + return; + } + let cancelled = false; + setDetailLoading(true); + setDetailError(null); + setIssue(null); + setComments([]); + const sourceRepo = selectedSourceRepo ?? null; + void Promise.all([ + github.issueGet(directory, selectedNumber, { sourceRepo }), + github.issueComments(directory, selectedNumber, { sourceRepo }), + ]) + .then(([issueResult, commentsResult]) => { + if (cancelled) { + return; + } + if (issueResult.connected === false || commentsResult.connected === false) { + setDetailError(t('gitView.pr.githubNotConnected')); + return; + } + if (!issueResult.issue) { + setDetailError(t('session.githubIssuePicker.error.issueNotFound')); + return; + } + setIssue(issueResult.issue); + setComments(commentsResult.comments ?? []); + }) + .catch((error) => { + if (!cancelled) { + setDetailError(error instanceof Error ? error.message : String(error)); + } + }) + .finally(() => { + if (!cancelled) { + setDetailLoading(false); + } + }); + return () => { + cancelled = true; + }; + }, [directory, github, selectedNumber, selectedSourceRepo, t]); + + const backToIssues = React.useCallback(() => { + setSelectedNumber(null); + setSelectedSourceRepo(null); + setIssue(null); + setComments([]); + setDetailLoading(false); + setDetailError(null); + }, []); + + const formatTimestamp = React.useCallback((value?: string) => { + if (!value) { + return ''; + } + const timestamp = Date.parse(value); + if (!Number.isFinite(timestamp)) { + return value; + } + return formatDateTimeForPreference(timestamp, timeFormatPreference, { + year: 'numeric', + month: 'short', + day: 'numeric', + hour: 'numeric', + minute: '2-digit', + }); + }, [timeFormatPreference]); + + if (selectedNumber !== null) { + return ( +
+
+ +
+ + {detailLoading ? ( +
+ + {t('session.githubIssuePicker.loading.issues')} +
+ ) : detailError ? ( +
+
{detailError}
+ +
+ ) : issue ? ( + <> +
+
+ #{issue.number} {issue.title} +
+
+ + + + {issue.labels?.map((label) => ( + {label.name} + ))} +
+ {issue.assignees && issue.assignees.length > 0 ? ( +
+ {issue.assignees.map((assignee) => assignee.name?.trim() || assignee.login).join(', ')} +
+ ) : null} + +
+ +
+
{t('gitView.pr.field.description')}
+ {issue.body?.trim() ? ( + + ) : ( +
{t('gitView.pr.noDescription')}
+ )} +
+ +
+
{t('gitView.pr.segment.comments')}
+ {comments.length > 0 ? ( + comments.map((comment) => ( +
+
+ + {comment.author?.name?.trim() || comment.author?.login || ''} + + {comment.createdAt ? ( + {formatTimestamp(comment.createdAt)} + ) : null} +
+ +
+ )) + ) : ( +
{t('gitView.pullRequest.issues.detail.commentsEmpty')}
+ )} +
+ + ) : null} +
+ ); + } + + return ( +
+
+
{t('gitView.pullRequest.issues.listSectionTitle')}
+
+ + {!github?.issuesList ? ( +
{t('gitView.pullRequest.issues.empty')}
+ ) : listNotConnected ? ( +
+ +
{t('gitView.pr.githubNotConnected')}
+ +
+ ) : listLoading ? ( +
+ + {t('session.githubIssuePicker.loading.issues')} +
+ ) : listError ? ( +
+
{t('gitView.pullRequest.issues.error.loadFailed')}
+
{listError}
+ +
+ ) : issues.length === 0 ? ( +
{t('gitView.pullRequest.issues.empty')}
+ ) : ( +
+ {issues.map((item) => ( +
selectIssue(item)} + > +
+

+ #{item.number} + {item.title} +

+ {item.labels && item.labels.length > 0 ? ( +

+ {item.labels.map((label) => ( + {label.name} + ))} +

+ ) : null} +
+ event.stopPropagation()} + aria-label={t('gitView.pullRequest.issues.detail.openInGitHub')} + className="hidden size-5 flex-shrink-0 items-center justify-center text-muted-foreground transition-colors hover:text-foreground group-hover:flex" + > + + +
+ ))} + + {listHasMore ? ( +
+ +
+ ) : null} +
+ )} +
+ ); +}; diff --git a/packages/ui/src/components/views/git/GitLabIssuesSection.tsx b/packages/ui/src/components/views/git/GitLabIssuesSection.tsx new file mode 100644 index 00000000..0006cc39 --- /dev/null +++ b/packages/ui/src/components/views/git/GitLabIssuesSection.tsx @@ -0,0 +1,378 @@ +import React from 'react'; +import { Icon } from '@/components/icon/Icon'; +import { Button } from '@/components/ui/button'; +import { SimpleMarkdownRenderer } from '@/components/chat/MarkdownRenderer'; +import { useRuntimeAPIs } from '@/hooks/useRuntimeAPIs'; +import { useUIStore } from '@/stores/useUIStore'; +import { formatDateTimeForPreference } from '@/lib/timeFormat'; +import type { GitLabIssue, GitLabIssueComment, GitLabIssueSummary } from '@/lib/api/types'; +import { useI18n } from '@/lib/i18n'; + +const issueStateColor = (state: string): string => { + switch (state) { + case 'closed': + return 'var(--pr-closed)'; + default: + return 'var(--pr-open)'; + } +}; + +const issueLabelBadgeClass = + 'inline-flex items-center rounded border border-border/60 bg-surface-elevated px-1.5 py-px typography-micro text-foreground'; + +/** + * Open GitLab issues for the context panel's MR view. List and detail are + * fetched lazily: the parent only mounts this component while the Issues tab + * is active. Read-only by design — no create, update, or close actions. + */ +export const GitLabIssuesSection: React.FC<{ directory: string }> = ({ directory }) => { + const { t } = useI18n(); + const { gitlab } = useRuntimeAPIs(); + const setSettingsDialogOpen = useUIStore((state) => state.setSettingsDialogOpen); + const setSettingsPage = useUIStore((state) => state.setSettingsPage); + const timeFormatPreference = useUIStore((state) => state.timeFormatPreference); + + // ---- Open issues list ---------------------------------------------------- + + const [issues, setIssues] = React.useState([]); + const [listPage, setListPage] = React.useState(1); + const [listHasMore, setListHasMore] = React.useState(false); + const [listLoading, setListLoading] = React.useState(false); + const [listLoadingMore, setListLoadingMore] = React.useState(false); + const [listError, setListError] = React.useState(null); + const [listNotConnected, setListNotConnected] = React.useState(false); + const [retryToken, setRetryToken] = React.useState(0); + + // ---- Selected issue detail ------------------------------------------------ + + const [selectedNumber, setSelectedNumber] = React.useState(null); + const [issue, setIssue] = React.useState(null); + const [comments, setComments] = React.useState([]); + const [detailLoading, setDetailLoading] = React.useState(false); + const [detailError, setDetailError] = React.useState(null); + + const retry = React.useCallback(() => setRetryToken((value) => value + 1), []); + + const openGitLabSettings = React.useCallback(() => { + setSettingsPage('git'); + setSettingsDialogOpen(true); + }, [setSettingsDialogOpen, setSettingsPage]); + + // A different repository invalidates the previously loaded list and detail so + // a stale repository's issues never leak into the new one. + React.useEffect(() => { + setIssues([]); + setListPage(1); + setListHasMore(false); + setListLoading(false); + setListLoadingMore(false); + setListError(null); + setListNotConnected(false); + setSelectedNumber(null); + setIssue(null); + setComments([]); + setDetailLoading(false); + setDetailError(null); + }, [directory]); + + React.useEffect(() => { + if (!gitlab?.issuesList) { + return; + } + let cancelled = false; + setListLoading(true); + setListError(null); + setListNotConnected(false); + void gitlab + .issuesList(directory, { page: 1 }) + .then((result) => { + if (cancelled) { + return; + } + if (result.connected === false) { + setListNotConnected(true); + return; + } + setIssues(result.issues ?? []); + setListPage(result.page ?? 1); + setListHasMore(Boolean(result.hasMore)); + }) + .catch((error) => { + if (!cancelled) { + setListError(error instanceof Error ? error.message : String(error)); + } + }) + .finally(() => { + if (!cancelled) { + setListLoading(false); + } + }); + return () => { + cancelled = true; + }; + }, [directory, gitlab, retryToken]); + + const loadMore = React.useCallback(async () => { + if (!gitlab?.issuesList || listLoadingMore || listLoading || !listHasMore) { + return; + } + setListLoadingMore(true); + try { + const next = await gitlab.issuesList(directory, { page: listPage + 1 }); + if (next.connected === false) { + setListNotConnected(true); + return; + } + setIssues((previous) => [...previous, ...(next.issues ?? [])]); + setListPage(next.page ?? listPage + 1); + setListHasMore(Boolean(next.hasMore)); + } catch (error) { + setListError(error instanceof Error ? error.message : String(error)); + } finally { + setListLoadingMore(false); + } + }, [directory, gitlab, listHasMore, listLoading, listLoadingMore, listPage]); + + // Fetch the issue and its comments in parallel whenever a row is selected. A + // cancelled flag keeps a stale selection from overwriting a newer one. + React.useEffect(() => { + if (selectedNumber === null || !gitlab?.issueGet || !gitlab.issueComments) { + return; + } + let cancelled = false; + setDetailLoading(true); + setDetailError(null); + setIssue(null); + setComments([]); + void Promise.all([ + gitlab.issueGet(directory, selectedNumber), + gitlab.issueComments(directory, selectedNumber), + ]) + .then(([issueResult, commentsResult]) => { + if (cancelled) { + return; + } + if (issueResult.connected === false || commentsResult.connected === false) { + setDetailError(t('contextPanel.gitlabMr.error.notConnected')); + return; + } + if (!issueResult.issue) { + setDetailError(t('session.gitlabIssuePicker.error.issueNotFound')); + return; + } + setIssue(issueResult.issue); + setComments(commentsResult.comments ?? []); + }) + .catch((error) => { + if (!cancelled) { + setDetailError(error instanceof Error ? error.message : String(error)); + } + }) + .finally(() => { + if (!cancelled) { + setDetailLoading(false); + } + }); + return () => { + cancelled = true; + }; + }, [directory, gitlab, selectedNumber, t]); + + const backToIssues = React.useCallback(() => { + setSelectedNumber(null); + setIssue(null); + setComments([]); + setDetailLoading(false); + setDetailError(null); + }, []); + + const formatTimestamp = React.useCallback((value?: string) => { + if (!value) { + return ''; + } + const timestamp = Date.parse(value); + if (!Number.isFinite(timestamp)) { + return value; + } + return formatDateTimeForPreference(timestamp, timeFormatPreference, { + year: 'numeric', + month: 'short', + day: 'numeric', + hour: 'numeric', + minute: '2-digit', + }); + }, [timeFormatPreference]); + + if (selectedNumber !== null) { + return ( +
+
+ +
+ + {detailLoading ? ( +
+ + {t('contextPanel.gitlabMr.loading')} +
+ ) : detailError ? ( +
+
{detailError}
+ +
+ ) : issue ? ( + <> +
+
+ #{issue.number} {issue.title} +
+
+ + + {issue.state === 'closed' ? t('contextPanel.gitlabMr.state.closed') : t('contextPanel.gitlabMr.state.opened')} + + {issue.labels.map((label) => ( + {label} + ))} +
+ {issue.assignees && issue.assignees.length > 0 ? ( +
+ {issue.assignees.map((assignee) => assignee.name?.trim() || assignee.username).join(', ')} +
+ ) : null} + +
+ +
+
{t('gitView.pr.field.description')}
+ {issue.body?.trim() ? ( + + ) : ( +
{t('gitView.pr.noDescription')}
+ )} +
+ +
+
{t('gitView.pr.segment.comments')}
+ {comments.length > 0 ? ( + comments.map((comment) => ( +
+
+ + {comment.author?.name?.trim() || comment.author?.username || ''} + + {comment.createdAt ? ( + {formatTimestamp(comment.createdAt)} + ) : null} +
+ +
+ )) + ) : ( +
{t('gitView.pr.comments.empty')}
+ )} +
+ + ) : null} +
+ ); + } + + return ( +
+
+
{t('contextPanel.gitlabMr.issues.listSectionTitle')}
+
+ + {!gitlab?.issuesList ? ( +
{t('contextPanel.gitlabMr.issues.empty')}
+ ) : listNotConnected ? ( +
+ +
{t('contextPanel.gitlabMr.error.notConnected')}
+ +
+ ) : listLoading ? ( +
+ + {t('contextPanel.gitlabMr.loading')} +
+ ) : listError ? ( +
+
{t('contextPanel.gitlabMr.issues.error.loadFailed')}
+
{listError}
+ +
+ ) : issues.length === 0 ? ( +
{t('contextPanel.gitlabMr.issues.empty')}
+ ) : ( +
+ {issues.map((item) => ( +
setSelectedNumber(item.number)} + > +
+

+ #{item.number} + {item.title} +

+ {item.labels.length > 0 ? ( +

+ {item.labels.map((label) => ( + {label} + ))} +

+ ) : null} +
+ event.stopPropagation()} + aria-label={t('contextPanel.gitlabMr.openInGitLab')} + className="hidden size-5 flex-shrink-0 items-center justify-center text-muted-foreground transition-colors hover:text-foreground group-hover:flex" + > + + +
+ ))} + + {listHasMore ? ( +
+ +
+ ) : null} +
+ )} +
+ ); +}; diff --git a/packages/ui/src/lib/i18n/messages/de.ts b/packages/ui/src/lib/i18n/messages/de.ts index fe775e01..802f9c88 100644 --- a/packages/ui/src/lib/i18n/messages/de.ts +++ b/packages/ui/src/lib/i18n/messages/de.ts @@ -977,6 +977,14 @@ export const dict = { 'gitView.pr.toast.updatePrFailed': 'Fehler beim Aktualisieren des Pull-Requests', 'gitView.pullRequest.createHint': 'Erstelle und verwalte Pull-Requests aus diesem Branch.', 'gitView.pullRequest.availableOnFeatureBranches': 'Verfügbar, wenn der aktuelle Branch einen Pull-Request öffnen kann.', + 'gitView.pullRequest.issues.detail.back': 'Zurück zu den Problemen', + 'gitView.pullRequest.issues.detail.commentsEmpty': 'Keine Kommentare', + 'gitView.pullRequest.issues.detail.openInGitHub': 'Auf GitHub öffnen', + 'gitView.pullRequest.issues.empty': 'Keine offenen Probleme', + 'gitView.pullRequest.issues.error.loadFailed': 'Fehler beim Laden der Probleme', + 'gitView.pullRequest.issues.listSectionTitle': 'Offene Probleme', + 'gitView.pullRequest.tabs.issues': 'Probleme', + 'gitView.pullRequest.tabs.pullRequests': 'Pull-Requests', 'gitView.pullRequest.title': 'Pull-Request', 'gitView.tabs.worktree': 'Worktree', 'gitView.toast.abortOperationFailed': 'Fehler beim Abbrechen der Operation', @@ -2985,6 +2993,8 @@ export const dict = { 'contextPanel.editorEmpty.title': 'Kein Kontext ausgewählt', 'contextPanel.editorEmpty.description': 'Wählen Sie etwas aus der Seitenleiste aus, um Kontext anzuzeigen.', 'contextPanel.gitlabMr.title': 'Merge-Requests', + 'contextPanel.gitlabMr.tabs.mergeRequests': 'Merge-Requests', + 'contextPanel.gitlabMr.tabs.issues': 'Probleme', 'contextPanel.gitlabMr.branchSectionTitle': 'Aktueller Zweig', 'contextPanel.gitlabMr.openMrTitle': 'Offene Merge-Requests', 'contextPanel.gitlabMr.listSectionTitle': 'In diesem Repository', @@ -3003,6 +3013,11 @@ export const dict = { 'contextPanel.gitlabMr.error.notConnected': 'GitLab ist nicht verbunden', 'contextPanel.gitlabMr.empty.noActiveProject': 'Kein aktives Projekt', 'contextPanel.gitlabMr.actions.openSettings': 'Einstellungen öffnen', + 'contextPanel.gitlabMr.issues.detail.back': 'Zurück zu den Problemen', + 'contextPanel.gitlabMr.issues.detail.commentsEmpty': 'Keine Kommentare', + 'contextPanel.gitlabMr.issues.empty': 'Keine offenen Probleme', + 'contextPanel.gitlabMr.issues.error.loadFailed': 'Fehler beim Laden der Probleme', + 'contextPanel.gitlabMr.issues.listSectionTitle': 'Offene Probleme', 'contextPanel.gitlabMr.createMr.title': 'Neuer Merge-Request', 'contextPanel.gitlabMr.createMr.sourceBranch': 'Quellbranch', 'contextPanel.gitlabMr.createMr.targetBranch': 'Zielbranch', diff --git a/packages/ui/src/lib/i18n/messages/en.ts b/packages/ui/src/lib/i18n/messages/en.ts index 037daa74..61eed6cf 100644 --- a/packages/ui/src/lib/i18n/messages/en.ts +++ b/packages/ui/src/lib/i18n/messages/en.ts @@ -1046,6 +1046,14 @@ export const dict = { 'gitView.pr.toast.updatePrFailed': 'Failed to update pull request', 'gitView.pullRequest.createHint': 'Create and manage pull requests from this branch.', 'gitView.pullRequest.availableOnFeatureBranches': 'Available when the current branch can open a pull request.', + 'gitView.pullRequest.issues.detail.back': 'Back to issues', + 'gitView.pullRequest.issues.detail.commentsEmpty': 'No comments', + 'gitView.pullRequest.issues.detail.openInGitHub': 'Open in GitHub', + 'gitView.pullRequest.issues.empty': 'No open issues', + 'gitView.pullRequest.issues.error.loadFailed': 'Failed to load issues', + 'gitView.pullRequest.issues.listSectionTitle': 'Open issues', + 'gitView.pullRequest.tabs.issues': 'Issues', + 'gitView.pullRequest.tabs.pullRequests': 'Pull requests', 'gitView.pullRequest.title': 'Pull request', 'gitView.tabs.worktree': 'Worktree', 'gitView.toast.abortOperationFailed': 'Failed to abort operation', @@ -1122,6 +1130,8 @@ export const dict = { 'contextPanel.editorEmpty.title': 'No file open', 'contextPanel.editorEmpty.description': 'Pick a file from the tree to start editing.', 'contextPanel.gitlabMr.title': 'Merge requests', + 'contextPanel.gitlabMr.tabs.mergeRequests': 'Merge requests', + 'contextPanel.gitlabMr.tabs.issues': 'Issues', 'contextPanel.gitlabMr.branchSectionTitle': 'Current branch', 'contextPanel.gitlabMr.openMrTitle': 'Open merge requests', 'contextPanel.gitlabMr.listSectionTitle': 'In this repository', @@ -1140,6 +1150,11 @@ export const dict = { 'contextPanel.gitlabMr.error.notConnected': 'GitLab is not connected', 'contextPanel.gitlabMr.empty.noActiveProject': 'No active project', 'contextPanel.gitlabMr.actions.openSettings': 'Open settings', + 'contextPanel.gitlabMr.issues.detail.back': 'Back to issues', + 'contextPanel.gitlabMr.issues.detail.commentsEmpty': 'No comments', + 'contextPanel.gitlabMr.issues.empty': 'No open issues', + 'contextPanel.gitlabMr.issues.error.loadFailed': 'Failed to load issues', + 'contextPanel.gitlabMr.issues.listSectionTitle': 'Open issues', 'contextPanel.gitlabMr.createMr.title': 'New merge request', 'contextPanel.gitlabMr.createMr.sourceBranch': 'Source branch', 'contextPanel.gitlabMr.createMr.targetBranch': 'Target branch', diff --git a/packages/ui/src/lib/i18n/messages/es.ts b/packages/ui/src/lib/i18n/messages/es.ts index cf5a6e76..4819a701 100644 --- a/packages/ui/src/lib/i18n/messages/es.ts +++ b/packages/ui/src/lib/i18n/messages/es.ts @@ -1047,6 +1047,14 @@ export const dict: Record = { "gitView.pr.toast.updatePrFailed": "No se pudo actualizar la PR", "gitView.pullRequest.createHint": "Crea y gestiona PR desde esta rama.", "gitView.pullRequest.availableOnFeatureBranches": "Disponible cuando la rama actual puede abrir un PR.", + "gitView.pullRequest.issues.detail.back": "Volver a issues", + "gitView.pullRequest.issues.detail.commentsEmpty": "Sin comentarios", + "gitView.pullRequest.issues.detail.openInGitHub": "Abrir en GitHub", + "gitView.pullRequest.issues.empty": "No hay issues abiertos", + "gitView.pullRequest.issues.error.loadFailed": "Error al cargar los issues", + "gitView.pullRequest.issues.listSectionTitle": "Issues abiertos", + "gitView.pullRequest.tabs.issues": "Issues", + "gitView.pullRequest.tabs.pullRequests": "Pull requests", "gitView.pullRequest.title": "PR", "gitView.tabs.worktree": "Árbol de trabajo", "gitView.toast.abortOperationFailed": "No se pudo abortar la operación", @@ -1123,6 +1131,8 @@ export const dict: Record = { "contextPanel.editorEmpty.title": "Ningún archivo abierto", "contextPanel.editorEmpty.description": "Elige un archivo del árbol para empezar a editar.", "contextPanel.gitlabMr.title": "Solicitudes de fusión", + "contextPanel.gitlabMr.tabs.mergeRequests": "Solicitudes de fusión", + "contextPanel.gitlabMr.tabs.issues": "Issues", "contextPanel.gitlabMr.branchSectionTitle": "Rama actual", "contextPanel.gitlabMr.openMrTitle": "Solicitudes de fusión abiertas", "contextPanel.gitlabMr.listSectionTitle": "En este repositorio", @@ -1141,6 +1151,11 @@ export const dict: Record = { "contextPanel.gitlabMr.error.notConnected": "GitLab no está conectado", "contextPanel.gitlabMr.empty.noActiveProject": "Sin proyecto activo", "contextPanel.gitlabMr.actions.openSettings": "Abrir ajustes", + "contextPanel.gitlabMr.issues.detail.back": "Volver a issues", + "contextPanel.gitlabMr.issues.detail.commentsEmpty": "Sin comentarios", + "contextPanel.gitlabMr.issues.empty": "No hay issues abiertos", + "contextPanel.gitlabMr.issues.error.loadFailed": "Error al cargar los issues", + "contextPanel.gitlabMr.issues.listSectionTitle": "Issues abiertos", "contextPanel.gitlabMr.createMr.title": "Nueva solicitud de fusión", "contextPanel.gitlabMr.createMr.sourceBranch": "Rama de origen", "contextPanel.gitlabMr.createMr.targetBranch": "Rama de destino", diff --git a/packages/ui/src/lib/i18n/messages/fr.ts b/packages/ui/src/lib/i18n/messages/fr.ts index 66ae258e..c9fb2766 100644 --- a/packages/ui/src/lib/i18n/messages/fr.ts +++ b/packages/ui/src/lib/i18n/messages/fr.ts @@ -866,6 +866,14 @@ export const dict = { 'gitView.pr.toast.updatePrFailed': 'Échec de la mise à jour de la PR', 'gitView.pullRequest.createHint': 'Créez et gérez les PR depuis cette branche.', 'gitView.pullRequest.availableOnFeatureBranches': 'Disponible lorsque la branche actuelle peut ouvrir une PR.', + 'gitView.pullRequest.issues.detail.back': 'Retour aux problèmes', + 'gitView.pullRequest.issues.detail.commentsEmpty': 'Aucun commentaire', + 'gitView.pullRequest.issues.detail.openInGitHub': 'Ouvrir dans GitHub', + 'gitView.pullRequest.issues.empty': 'Aucun problème ouvert', + 'gitView.pullRequest.issues.error.loadFailed': 'Échec du chargement des problèmes', + 'gitView.pullRequest.issues.listSectionTitle': 'Problèmes ouverts', + 'gitView.pullRequest.tabs.issues': 'Problèmes', + 'gitView.pullRequest.tabs.pullRequests': 'Pull requests', 'gitView.pullRequest.title': 'PR', 'gitView.tabs.worktree': 'Worktree', 'gitView.toast.abortOperationFailed': 'Échec de l\'annulation de l\'opération', @@ -942,6 +950,8 @@ export const dict = { 'contextPanel.editorEmpty.title': 'Aucun fichier ouvert', 'contextPanel.editorEmpty.description': 'Choisissez un fichier dans l’arborescence pour commencer.', 'contextPanel.gitlabMr.title': 'Demandes de fusion', + 'contextPanel.gitlabMr.tabs.mergeRequests': 'Demandes de fusion', + 'contextPanel.gitlabMr.tabs.issues': 'Problèmes', 'contextPanel.gitlabMr.branchSectionTitle': 'Branche actuelle', 'contextPanel.gitlabMr.openMrTitle': 'Demandes de fusion ouvertes', 'contextPanel.gitlabMr.listSectionTitle': 'Dans ce dépôt', @@ -960,6 +970,11 @@ export const dict = { 'contextPanel.gitlabMr.error.notConnected': 'GitLab n\'est pas connecté', 'contextPanel.gitlabMr.empty.noActiveProject': 'Aucun projet actif', 'contextPanel.gitlabMr.actions.openSettings': 'Ouvrir les paramètres', + 'contextPanel.gitlabMr.issues.detail.back': 'Retour aux problèmes', + 'contextPanel.gitlabMr.issues.detail.commentsEmpty': 'Aucun commentaire', + 'contextPanel.gitlabMr.issues.empty': 'Aucun problème ouvert', + 'contextPanel.gitlabMr.issues.error.loadFailed': 'Échec du chargement des problèmes', + 'contextPanel.gitlabMr.issues.listSectionTitle': 'Problèmes ouverts', 'contextPanel.gitlabMr.createMr.title': 'Nouvelle demande de fusion', 'contextPanel.gitlabMr.createMr.sourceBranch': 'Branche source', 'contextPanel.gitlabMr.createMr.targetBranch': 'Branche cible', diff --git a/packages/ui/src/lib/i18n/messages/ja.ts b/packages/ui/src/lib/i18n/messages/ja.ts index d217e66e..059cd1c5 100644 --- a/packages/ui/src/lib/i18n/messages/ja.ts +++ b/packages/ui/src/lib/i18n/messages/ja.ts @@ -1043,6 +1043,14 @@ export const dict: Record = { 'gitView.pr.toast.updatePrFailed': 'プルリクエストの更新に失敗しました', 'gitView.pullRequest.createHint': 'このブランチからプルリクエストを作成・管理します。', 'gitView.pullRequest.availableOnFeatureBranches': '現在のブランチがプルリクエストを開ける場合に利用可能です。', + 'gitView.pullRequest.issues.detail.back': 'Issueに戻る', + 'gitView.pullRequest.issues.detail.commentsEmpty': 'コメントはありません', + 'gitView.pullRequest.issues.detail.openInGitHub': 'GitHubで開く', + 'gitView.pullRequest.issues.empty': '開いているIssueはありません', + 'gitView.pullRequest.issues.error.loadFailed': 'Issueの読み込みに失敗しました', + 'gitView.pullRequest.issues.listSectionTitle': '開いているIssue', + 'gitView.pullRequest.tabs.issues': 'Issue', + 'gitView.pullRequest.tabs.pullRequests': 'プルリクエスト', 'gitView.pullRequest.title': 'プルリクエスト', 'gitView.tabs.worktree': 'ワークツリー', 'gitView.toast.abortOperationFailed': '操作の中止に失敗しました', @@ -1119,6 +1127,8 @@ export const dict: Record = { 'contextPanel.editorEmpty.title': 'ファイルが開かれていません', 'contextPanel.editorEmpty.description': 'ツリーからファイルを選んで編集を始めましょう。', 'contextPanel.gitlabMr.title': 'マージリクエスト', + 'contextPanel.gitlabMr.tabs.mergeRequests': 'マージリクエスト', + 'contextPanel.gitlabMr.tabs.issues': 'Issue', 'contextPanel.gitlabMr.branchSectionTitle': '現在のブランチ', 'contextPanel.gitlabMr.openMrTitle': '開いているマージリクエスト', 'contextPanel.gitlabMr.listSectionTitle': 'このリポジトリ内', @@ -1137,6 +1147,11 @@ export const dict: Record = { 'contextPanel.gitlabMr.error.notConnected': 'GitLab に接続されていません', 'contextPanel.gitlabMr.empty.noActiveProject': 'アクティブなプロジェクトがありません', 'contextPanel.gitlabMr.actions.openSettings': '設定を開く', + 'contextPanel.gitlabMr.issues.detail.back': 'Issueに戻る', + 'contextPanel.gitlabMr.issues.detail.commentsEmpty': 'コメントはありません', + 'contextPanel.gitlabMr.issues.empty': '開いているIssueはありません', + 'contextPanel.gitlabMr.issues.error.loadFailed': 'Issueの読み込みに失敗しました', + 'contextPanel.gitlabMr.issues.listSectionTitle': '開いているIssue', 'contextPanel.gitlabMr.createMr.title': '新しいマージリクエスト', 'contextPanel.gitlabMr.createMr.sourceBranch': 'ソースブランチ', 'contextPanel.gitlabMr.createMr.targetBranch': 'ターゲットブランチ', diff --git a/packages/ui/src/lib/i18n/messages/ko.ts b/packages/ui/src/lib/i18n/messages/ko.ts index 889cc9e6..fa689ace 100644 --- a/packages/ui/src/lib/i18n/messages/ko.ts +++ b/packages/ui/src/lib/i18n/messages/ko.ts @@ -1047,6 +1047,14 @@ export const dict: Record = { 'gitView.pr.toast.updatePrFailed': 'PR 업데이트 실패', 'gitView.pullRequest.createHint': '이 브랜치에서 PR을 만들고 관리하세요.', 'gitView.pullRequest.availableOnFeatureBranches': '현재 브랜치에서 PR을 열 수 있을 때 사용할 수 있습니다.', + 'gitView.pullRequest.issues.detail.back': '이슈로 돌아가기', + 'gitView.pullRequest.issues.detail.commentsEmpty': '댓글 없음', + 'gitView.pullRequest.issues.detail.openInGitHub': 'GitHub에서 열기', + 'gitView.pullRequest.issues.empty': '열린 이슈가 없습니다', + 'gitView.pullRequest.issues.error.loadFailed': '이슈를 불러오지 못했습니다', + 'gitView.pullRequest.issues.listSectionTitle': '열린 이슈', + 'gitView.pullRequest.tabs.issues': '이슈', + 'gitView.pullRequest.tabs.pullRequests': '풀 리퀘스트', 'gitView.pullRequest.title': 'PR', 'gitView.tabs.worktree': '워크트리', 'gitView.toast.abortOperationFailed': '작업 중단 실패', @@ -1123,6 +1131,8 @@ export const dict: Record = { 'contextPanel.editorEmpty.title': '열린 파일 없음', 'contextPanel.editorEmpty.description': '트리에서 파일을 선택해 편집을 시작하세요.', 'contextPanel.gitlabMr.title': '병합 요청', + 'contextPanel.gitlabMr.tabs.mergeRequests': '병합 요청', + 'contextPanel.gitlabMr.tabs.issues': '이슈', 'contextPanel.gitlabMr.branchSectionTitle': '현재 브랜치', 'contextPanel.gitlabMr.openMrTitle': '열린 병합 요청', 'contextPanel.gitlabMr.listSectionTitle': '이 저장소', @@ -1141,6 +1151,11 @@ export const dict: Record = { 'contextPanel.gitlabMr.error.notConnected': 'GitLab에 연결되지 않았습니다', 'contextPanel.gitlabMr.empty.noActiveProject': '활성 프로젝트가 없습니다', 'contextPanel.gitlabMr.actions.openSettings': '설정 열기', + 'contextPanel.gitlabMr.issues.detail.back': '이슈로 돌아가기', + 'contextPanel.gitlabMr.issues.detail.commentsEmpty': '댓글 없음', + 'contextPanel.gitlabMr.issues.empty': '열린 이슈가 없습니다', + 'contextPanel.gitlabMr.issues.error.loadFailed': '이슈를 불러오지 못했습니다', + 'contextPanel.gitlabMr.issues.listSectionTitle': '열린 이슈', 'contextPanel.gitlabMr.createMr.title': '새 병합 요청', 'contextPanel.gitlabMr.createMr.sourceBranch': '소스 브랜치', 'contextPanel.gitlabMr.createMr.targetBranch': '대상 브랜치', diff --git a/packages/ui/src/lib/i18n/messages/pl.ts b/packages/ui/src/lib/i18n/messages/pl.ts index 3b0b82f5..4d9c4670 100644 --- a/packages/ui/src/lib/i18n/messages/pl.ts +++ b/packages/ui/src/lib/i18n/messages/pl.ts @@ -1459,6 +1459,8 @@ export const dict: Record = { 'contextPanel.editorEmpty.title': 'Brak otwartego pliku', 'contextPanel.editorEmpty.description': 'Wybierz plik z drzewa, aby rozpocząć edycję.', 'contextPanel.gitlabMr.title': 'Żądania scalenia', + 'contextPanel.gitlabMr.tabs.mergeRequests': 'Żądania scalenia', + 'contextPanel.gitlabMr.tabs.issues': 'Zgłoszenia', 'contextPanel.gitlabMr.branchSectionTitle': 'Bieżąca gałąź', 'contextPanel.gitlabMr.openMrTitle': 'Otwarte żądania scalenia', 'contextPanel.gitlabMr.listSectionTitle': 'W tym repozytorium', @@ -1477,6 +1479,11 @@ export const dict: Record = { 'contextPanel.gitlabMr.error.notConnected': 'GitLab nie jest połączony', 'contextPanel.gitlabMr.empty.noActiveProject': 'Brak aktywnego projektu', 'contextPanel.gitlabMr.actions.openSettings': 'Otwórz ustawienia', + 'contextPanel.gitlabMr.issues.detail.back': 'Wróć do zgłoszeń', + 'contextPanel.gitlabMr.issues.detail.commentsEmpty': 'Brak komentarzy', + 'contextPanel.gitlabMr.issues.empty': 'Brak otwartych zgłoszeń', + 'contextPanel.gitlabMr.issues.error.loadFailed': 'Nie udało się załadować zgłoszeń', + 'contextPanel.gitlabMr.issues.listSectionTitle': 'Otwarte zgłoszenia', 'contextPanel.gitlabMr.createMr.title': 'Nowe żądanie scalenia', 'contextPanel.gitlabMr.createMr.sourceBranch': 'Gałąź źródłowa', 'contextPanel.gitlabMr.createMr.targetBranch': 'Gałąź docelowa', @@ -2305,6 +2312,14 @@ export const dict: Record = { 'gitView.pr.toast.titleRequired': 'Tytuł jest wymagany', 'gitView.pr.toast.updatePrFailed': 'Nie udało się zaktualizować pull requesta', 'gitView.pullRequest.createHint': 'Utwórz i zarządzaj pull requestami z tej gałęzi.', + 'gitView.pullRequest.issues.detail.back': 'Wróć do zgłoszeń', + 'gitView.pullRequest.issues.detail.commentsEmpty': 'Brak komentarzy', + 'gitView.pullRequest.issues.detail.openInGitHub': 'Otwórz w GitHub', + 'gitView.pullRequest.issues.empty': 'Brak otwartych zgłoszeń', + 'gitView.pullRequest.issues.error.loadFailed': 'Nie udało się załadować zgłoszeń', + 'gitView.pullRequest.issues.listSectionTitle': 'Otwarte zgłoszenia', + 'gitView.pullRequest.tabs.issues': 'Zgłoszenia', + 'gitView.pullRequest.tabs.pullRequests': 'Pull requesty', 'gitView.pullRequest.title': 'Pull request', 'gitView.stash.confirmButton': 'Potwierdź', 'gitView.stash.description': 'Opis', diff --git a/packages/ui/src/lib/i18n/messages/pt-BR.ts b/packages/ui/src/lib/i18n/messages/pt-BR.ts index 0a9fd27b..6d8e96e4 100644 --- a/packages/ui/src/lib/i18n/messages/pt-BR.ts +++ b/packages/ui/src/lib/i18n/messages/pt-BR.ts @@ -1047,6 +1047,14 @@ export const dict: Record = { "gitView.pr.toast.updatePrFailed": "Não foi possível atualizar a PR", "gitView.pullRequest.createHint": "Crie e gerencie PRs desta branch.", "gitView.pullRequest.availableOnFeatureBranches": "Disponível quando a branch atual pode abrir uma PR.", + "gitView.pullRequest.issues.detail.back": "Voltar para issues", + "gitView.pullRequest.issues.detail.commentsEmpty": "Sem comentários", + "gitView.pullRequest.issues.detail.openInGitHub": "Abrir no GitHub", + "gitView.pullRequest.issues.empty": "Nenhuma issue aberta", + "gitView.pullRequest.issues.error.loadFailed": "Falha ao carregar issues", + "gitView.pullRequest.issues.listSectionTitle": "Issues abertas", + "gitView.pullRequest.tabs.issues": "Issues", + "gitView.pullRequest.tabs.pullRequests": "Pull requests", "gitView.pullRequest.title": "PR", "gitView.tabs.worktree": "Worktree", "gitView.toast.abortOperationFailed": "Não foi possível abortar a operación", @@ -1123,6 +1131,8 @@ export const dict: Record = { "contextPanel.editorEmpty.title": "Nenhum arquivo aberto", "contextPanel.editorEmpty.description": "Escolha um arquivo na árvore para começar a editar.", "contextPanel.gitlabMr.title": "Solicitações de merge", + "contextPanel.gitlabMr.tabs.mergeRequests": "Solicitações de merge", + "contextPanel.gitlabMr.tabs.issues": "Issues", "contextPanel.gitlabMr.branchSectionTitle": "Branch atual", "contextPanel.gitlabMr.openMrTitle": "Solicitações de merge abertas", "contextPanel.gitlabMr.listSectionTitle": "Neste repositório", @@ -1141,6 +1151,11 @@ export const dict: Record = { "contextPanel.gitlabMr.error.notConnected": "GitLab não está conectado", "contextPanel.gitlabMr.empty.noActiveProject": "Nenhum projeto ativo", "contextPanel.gitlabMr.actions.openSettings": "Abrir configurações", + "contextPanel.gitlabMr.issues.detail.back": "Voltar para issues", + "contextPanel.gitlabMr.issues.detail.commentsEmpty": "Sem comentários", + "contextPanel.gitlabMr.issues.empty": "Nenhuma issue aberta", + "contextPanel.gitlabMr.issues.error.loadFailed": "Falha ao carregar issues", + "contextPanel.gitlabMr.issues.listSectionTitle": "Issues abertas", "contextPanel.gitlabMr.createMr.title": "Nova solicitação de merge", "contextPanel.gitlabMr.createMr.sourceBranch": "Branch de origem", "contextPanel.gitlabMr.createMr.targetBranch": "Branch de destino", diff --git a/packages/ui/src/lib/i18n/messages/uk.ts b/packages/ui/src/lib/i18n/messages/uk.ts index 60eacc77..a5cb84ea 100644 --- a/packages/ui/src/lib/i18n/messages/uk.ts +++ b/packages/ui/src/lib/i18n/messages/uk.ts @@ -1047,6 +1047,14 @@ export const dict: Record = { "gitView.pr.toast.updatePrFailed": "Не вдалося оновити PR", "gitView.pullRequest.createHint": "Створюйте PR з цієї гілки та керуйте ними.", "gitView.pullRequest.availableOnFeatureBranches": "Доступно, коли поточна гілка може відкрити PR.", + "gitView.pullRequest.issues.detail.back": "Назад до issue", + "gitView.pullRequest.issues.detail.commentsEmpty": "Немає коментарів", + "gitView.pullRequest.issues.detail.openInGitHub": "Відкрити в GitHub", + "gitView.pullRequest.issues.empty": "Немає відкритих issue", + "gitView.pullRequest.issues.error.loadFailed": "Не вдалося завантажити issue", + "gitView.pullRequest.issues.listSectionTitle": "Відкриті issue", + "gitView.pullRequest.tabs.issues": "Issue", + "gitView.pullRequest.tabs.pullRequests": "Pull requests", "gitView.pullRequest.title": "PR", "gitView.tabs.worktree": "Worktree", "gitView.toast.abortOperationFailed": "Не вдалося перервати операцію", @@ -1123,6 +1131,8 @@ export const dict: Record = { "contextPanel.editorEmpty.title": "Файл не відкрито", "contextPanel.editorEmpty.description": "Виберіть файл у дереві, щоб почати редагування.", "contextPanel.gitlabMr.title": "Запити на злиття", + "contextPanel.gitlabMr.tabs.mergeRequests": "Запити на злиття", + "contextPanel.gitlabMr.tabs.issues": "Issue", "contextPanel.gitlabMr.branchSectionTitle": "Поточна гілка", "contextPanel.gitlabMr.openMrTitle": "Відкриті запити на злиття", "contextPanel.gitlabMr.listSectionTitle": "У цьому репозиторії", @@ -1141,6 +1151,11 @@ export const dict: Record = { "contextPanel.gitlabMr.error.notConnected": "GitLab не підключено", "contextPanel.gitlabMr.empty.noActiveProject": "Немає активного проєкту", "contextPanel.gitlabMr.actions.openSettings": "Відкрити налаштування", + "contextPanel.gitlabMr.issues.detail.back": "Назад до issue", + "contextPanel.gitlabMr.issues.detail.commentsEmpty": "Немає коментарів", + "contextPanel.gitlabMr.issues.empty": "Немає відкритих issue", + "contextPanel.gitlabMr.issues.error.loadFailed": "Не вдалося завантажити issue", + "contextPanel.gitlabMr.issues.listSectionTitle": "Відкриті issue", "contextPanel.gitlabMr.createMr.title": "Новий запит на злиття", "contextPanel.gitlabMr.createMr.sourceBranch": "Вихідна гілка", "contextPanel.gitlabMr.createMr.targetBranch": "Цільова гілка", diff --git a/packages/ui/src/lib/i18n/messages/zh-CN.ts b/packages/ui/src/lib/i18n/messages/zh-CN.ts index b332b9d2..8f2d2d3c 100644 --- a/packages/ui/src/lib/i18n/messages/zh-CN.ts +++ b/packages/ui/src/lib/i18n/messages/zh-CN.ts @@ -1047,6 +1047,14 @@ export const dict: Record = { 'gitView.pr.toast.updatePrFailed': '更新拉取请求失败', 'gitView.pullRequest.createHint': '从当前分支创建并管理拉取请求。', 'gitView.pullRequest.availableOnFeatureBranches': '当前分支可以打开 PR 时可用。', + 'gitView.pullRequest.issues.detail.back': '返回 Issue 列表', + 'gitView.pullRequest.issues.detail.commentsEmpty': '暂无评论', + 'gitView.pullRequest.issues.detail.openInGitHub': '在 GitHub 中打开', + 'gitView.pullRequest.issues.empty': '没有打开的 Issue', + 'gitView.pullRequest.issues.error.loadFailed': '加载 Issue 失败', + 'gitView.pullRequest.issues.listSectionTitle': '打开的 Issue', + 'gitView.pullRequest.tabs.issues': 'Issue', + 'gitView.pullRequest.tabs.pullRequests': '拉取请求', 'gitView.pullRequest.title': '拉取请求', 'gitView.tabs.worktree': '工作树', 'gitView.toast.abortOperationFailed': '中止操作失败', @@ -1123,6 +1131,8 @@ export const dict: Record = { 'contextPanel.editorEmpty.title': '未打开文件', 'contextPanel.editorEmpty.description': '从文件树中选择一个文件开始编辑。', 'contextPanel.gitlabMr.title': '合并请求', + 'contextPanel.gitlabMr.tabs.mergeRequests': '合并请求', + 'contextPanel.gitlabMr.tabs.issues': 'Issue', 'contextPanel.gitlabMr.branchSectionTitle': '当前分支', 'contextPanel.gitlabMr.openMrTitle': '打开的合并请求', 'contextPanel.gitlabMr.listSectionTitle': '在此仓库中', @@ -1141,6 +1151,11 @@ export const dict: Record = { 'contextPanel.gitlabMr.error.notConnected': 'GitLab 未连接', 'contextPanel.gitlabMr.empty.noActiveProject': '没有活动的项目', 'contextPanel.gitlabMr.actions.openSettings': '打开设置', + 'contextPanel.gitlabMr.issues.detail.back': '返回 Issue 列表', + 'contextPanel.gitlabMr.issues.detail.commentsEmpty': '暂无评论', + 'contextPanel.gitlabMr.issues.empty': '没有打开的 Issue', + 'contextPanel.gitlabMr.issues.error.loadFailed': '加载 Issue 失败', + 'contextPanel.gitlabMr.issues.listSectionTitle': '打开的 Issue', 'contextPanel.gitlabMr.createMr.title': '新建合并请求', 'contextPanel.gitlabMr.createMr.sourceBranch': '源分支', 'contextPanel.gitlabMr.createMr.targetBranch': '目标分支', diff --git a/packages/ui/src/lib/i18n/messages/zh-TW.ts b/packages/ui/src/lib/i18n/messages/zh-TW.ts index 72ed7f4a..70f961fb 100644 --- a/packages/ui/src/lib/i18n/messages/zh-TW.ts +++ b/packages/ui/src/lib/i18n/messages/zh-TW.ts @@ -1059,6 +1059,14 @@ export const dict: Record = { 'gitView.pr.toast.updatePrFailed': '更新 Pull Request 失敗', 'gitView.pullRequest.createHint': '從目前分支建立並管理 Pull Request。', 'gitView.pullRequest.availableOnFeatureBranches': '目前分支可以開啟 PR 時可用。', + 'gitView.pullRequest.issues.detail.back': '返回 Issue 列表', + 'gitView.pullRequest.issues.detail.commentsEmpty': '沒有留言', + 'gitView.pullRequest.issues.detail.openInGitHub': '在 GitHub 中開啟', + 'gitView.pullRequest.issues.empty': '沒有開啟的 Issue', + 'gitView.pullRequest.issues.error.loadFailed': '載入 Issue 失敗', + 'gitView.pullRequest.issues.listSectionTitle': '開啟的 Issue', + 'gitView.pullRequest.tabs.issues': 'Issue', + 'gitView.pullRequest.tabs.pullRequests': 'Pull Request', 'gitView.pullRequest.title': 'Pull Request', 'gitView.tabs.worktree': 'Worktree', 'gitView.toast.abortOperationFailed': '中止操作失敗', @@ -1135,6 +1143,8 @@ export const dict: Record = { 'contextPanel.editorEmpty.title': '未開啟檔案', 'contextPanel.editorEmpty.description': '從檔案樹選擇檔案開始編輯。', 'contextPanel.gitlabMr.title': '合併請求', + 'contextPanel.gitlabMr.tabs.mergeRequests': '合併請求', + 'contextPanel.gitlabMr.tabs.issues': 'Issue', 'contextPanel.gitlabMr.branchSectionTitle': '目前分支', 'contextPanel.gitlabMr.openMrTitle': '已開啟的合併請求', 'contextPanel.gitlabMr.listSectionTitle': '在此存放庫中', @@ -1153,6 +1163,11 @@ export const dict: Record = { 'contextPanel.gitlabMr.error.notConnected': 'GitLab 未連線', 'contextPanel.gitlabMr.empty.noActiveProject': '沒有使用中的專案', 'contextPanel.gitlabMr.actions.openSettings': '開啟設定', + 'contextPanel.gitlabMr.issues.detail.back': '返回 Issue 列表', + 'contextPanel.gitlabMr.issues.detail.commentsEmpty': '沒有留言', + 'contextPanel.gitlabMr.issues.empty': '沒有開啟的 Issue', + 'contextPanel.gitlabMr.issues.error.loadFailed': '載入 Issue 失敗', + 'contextPanel.gitlabMr.issues.listSectionTitle': '開啟的 Issue', 'contextPanel.gitlabMr.createMr.title': '新增合併請求', 'contextPanel.gitlabMr.createMr.sourceBranch': '來源分支', 'contextPanel.gitlabMr.createMr.targetBranch': '目標分支',