feat(git): add environment timeline visualization and branch commit APIs
Implement a new Git environment timeline component to visualize dashboard versions across different deployment stages (Development, Pre-production, and Production). This includes new backend endpoints and frontend services to support historical data retrieval and version comparison. - Add `get_branch_commits` and `get_commit_diff` endpoints to backend API and Git service. - Implement `GitEnvironmentTimeline` Svelte component for visual representation of deployment history. - Update `GitManagerModel` to manage timeline state, including environment histories and version selection for comparison. - Add `getBranchCommits` and `getCommitDiff` methods to `gitService`. - Improve UX by separating the branch selector from the version map. - Add comprehensive i18n support for the new visualization features.
This commit is contained in:
@@ -27,10 +27,10 @@
|
||||
import { onMount } from 'svelte';
|
||||
import { t } from '$lib/i18n/index.svelte.js';
|
||||
import { Button, HelpTooltip, Icon } from '$lib/ui';
|
||||
import { addToast } from '$lib/toasts.svelte.js';
|
||||
import { resolveDefaultConfig } from '../../../services/git-utils.js';
|
||||
import { GitManagerModel } from '$lib/models/GitManagerModel.svelte.ts';
|
||||
import { ROUTES } from '$lib/routes';
|
||||
import BranchSelector from './BranchSelector.svelte';
|
||||
import DeploymentModal from './DeploymentModal.svelte';
|
||||
import ConflictResolver from './ConflictResolver.svelte';
|
||||
import GitInitPanel from './GitInitPanel.svelte';
|
||||
@@ -41,6 +41,8 @@
|
||||
import GitLifecycleHeader from './GitLifecycleHeader.svelte';
|
||||
import CreateBranchDialog from './CreateBranchDialog.svelte';
|
||||
import MergeDialog from './MergeDialog.svelte';
|
||||
import GitEnvironmentTimeline from './GitEnvironmentTimeline.svelte';
|
||||
import BranchSelector from './BranchSelector.svelte';
|
||||
|
||||
let { dashboardId, envId = null, dashboardTitle = '', show = $bindable(false) } = $props();
|
||||
|
||||
@@ -249,14 +251,49 @@
|
||||
preferredDeployTargetStage={model.preferredDeployTargetStage}
|
||||
onRecommendedAction={handleRecommendedAction}
|
||||
/>
|
||||
<div class="flex flex-wrap items-center justify-between gap-3 rounded-lg border border-border bg-surface-page px-4 py-3">
|
||||
<div class="text-sm font-medium text-text">{$t.git?.branch_label || 'Ветка:'}</div>
|
||||
<div class="flex w-full items-center gap-1 sm:w-72"><BranchSelector {dashboardId} envId={model.resolvedEnvId} bind:currentBranch={model.currentBranch} onchange={(event) => model.handleBranchChanged(event)} onmerge={handleOpenMergeDialog} /><HelpTooltip text={$t.git?.hint_branch_selector || ''} ariaLabel={$t.git?.help_aria || 'Справка'} /></div>
|
||||
|
||||
<!-- Branch selector moved here per UX review: separate from version map to avoid confusion -->
|
||||
<div class="flex items-center gap-3 mb-2">
|
||||
<div class="text-xs font-medium text-text-muted uppercase tracking-wide">Рабочая ветка (текущие изменения):</div>
|
||||
<div class="flex-1 max-w-[280px]">
|
||||
<BranchSelector
|
||||
{dashboardId}
|
||||
envId={model.resolvedEnvId}
|
||||
bind:currentBranch={model.currentBranch}
|
||||
onchange={(event) => model.handleBranchChanged(event)}
|
||||
onmerge={handleOpenMergeDialog}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- BI dashboard version timeline: focused on status map. Operations below in tabs. -->
|
||||
<GitEnvironmentTimeline
|
||||
branches={model.branches}
|
||||
environmentHistories={model.environmentHistories}
|
||||
historiesLoading={model.environmentHistoriesLoading}
|
||||
{dashboardId}
|
||||
envId={model.resolvedEnvId}
|
||||
bind:currentBranch={model.currentBranch}
|
||||
onBranchChange={(event) => model.handleBranchChanged(event)}
|
||||
onMerge={handleOpenMergeDialog}
|
||||
selectedA={model.selectedVersionA}
|
||||
selectedB={model.selectedVersionB}
|
||||
onSelectVersion={(hash, secondary) => model.selectVersion(hash, secondary)}
|
||||
onClearSelection={() => model.clearVersionSelection()}
|
||||
onRequestDiff={async () => {
|
||||
const res = await model.getSelectedVersionsDiff();
|
||||
if (res?.diff) {
|
||||
model.workspaceDiff = res.diff;
|
||||
model.activeTab = 'workspace';
|
||||
addToast($t.git?.viz_diff_ready || 'Dashboard changes loaded for comparison', 'success');
|
||||
}
|
||||
}}
|
||||
/>
|
||||
|
||||
<div class="flex flex-wrap items-center gap-1 border-b border-border pb-0" role="tablist" aria-label={$t.git?.management || 'Управление Git'}>
|
||||
<button class={`relative -mb-px inline-flex items-center gap-2 rounded-t-lg px-4 py-2.5 text-sm font-medium transition-colors ${model.activeTab === 'workspace' ? 'border border-b-white bg-surface-card text-primary shadow-sm' : 'border border-transparent text-text-muted hover:bg-surface-muted hover:text-text'}`} onclick={() => (model.activeTab = 'workspace')} role="tab" aria-selected={model.activeTab === 'workspace'} aria-controls="git-tab-panel" id="git-tab-workspace" tabindex={model.activeTab === 'workspace' ? 0 : -1}>
|
||||
<Icon name="edit" size={16} strokeWidth={2} />
|
||||
{$t.git?.tab_workspace || 'Фиксация изменений'}
|
||||
{$t.git?.tab_workspace || 'Изменения'}
|
||||
<HelpTooltip text={$t.git?.hint_workspace || ''} ariaLabel={$t.git?.help_aria || 'Справка'} />
|
||||
</button>
|
||||
<button class={`relative -mb-px inline-flex items-center gap-2 rounded-t-lg px-4 py-2.5 text-sm font-medium transition-colors ${model.activeTab === 'release' ? 'border border-b-white bg-surface-card text-primary shadow-sm' : 'border border-transparent text-text-muted hover:bg-surface-muted hover:text-text'}`} onclick={() => (model.activeTab = 'release')} role="tab" aria-selected={model.activeTab === 'release'} aria-controls="git-tab-panel" id="git-tab-release" tabindex={model.activeTab === 'release' ? 0 : -1}>
|
||||
|
||||
Reference in New Issue
Block a user