+ git config
This commit is contained in:
@@ -23,6 +23,8 @@
|
||||
import { openDrawerForTask } from "$lib/stores/taskDrawer.js";
|
||||
import { api } from "$lib/api.js";
|
||||
import { debounce } from "$lib/utils/debounce.js";
|
||||
import { addToast } from "$lib/toasts.js";
|
||||
import { gitService } from "../../services/gitService.js";
|
||||
import MappingTable from "$components/MappingTable.svelte";
|
||||
|
||||
// State
|
||||
@@ -65,6 +67,8 @@
|
||||
|
||||
// Validation state
|
||||
let validatingIds = new Set();
|
||||
let gitBusyIds = new Set();
|
||||
let cachedGitConfigs = [];
|
||||
|
||||
// Environment options - will be loaded from API
|
||||
let environments = [];
|
||||
@@ -142,7 +146,12 @@
|
||||
id: d.id,
|
||||
title: d.title,
|
||||
slug: d.slug,
|
||||
gitStatus: d.git_status?.sync_status?.toLowerCase() || null,
|
||||
git: {
|
||||
status: d.git_status?.sync_status?.toLowerCase() || "no_repo",
|
||||
branch: d.git_status?.branch || null,
|
||||
hasRepo: d.git_status?.has_repo === true,
|
||||
hasChangesForCommit: d.git_status?.has_changes_for_commit === true,
|
||||
},
|
||||
lastTask: d.last_task
|
||||
? {
|
||||
status: d.last_task.status?.toLowerCase() || null,
|
||||
@@ -510,6 +519,147 @@
|
||||
}
|
||||
}
|
||||
|
||||
function isGitBusy(dashboardId) {
|
||||
return gitBusyIds.has(dashboardId);
|
||||
}
|
||||
|
||||
function setGitBusy(dashboardId, busy) {
|
||||
if (busy) {
|
||||
gitBusyIds.add(dashboardId);
|
||||
} else {
|
||||
gitBusyIds.delete(dashboardId);
|
||||
}
|
||||
gitBusyIds = new Set(gitBusyIds);
|
||||
}
|
||||
|
||||
async function ensureGitConfigs() {
|
||||
if (cachedGitConfigs.length > 0) return cachedGitConfigs;
|
||||
cachedGitConfigs = await gitService.getConfigs();
|
||||
return cachedGitConfigs;
|
||||
}
|
||||
|
||||
function updateDashboardGitState(dashboardId, nextGit) {
|
||||
dashboards = dashboards.map((dashboard) =>
|
||||
dashboard.id === dashboardId
|
||||
? { ...dashboard, git: { ...dashboard.git, ...nextGit } }
|
||||
: dashboard,
|
||||
);
|
||||
}
|
||||
|
||||
async function refreshDashboardGitState(dashboardId) {
|
||||
try {
|
||||
const status = await gitService.getStatus(dashboardId);
|
||||
updateDashboardGitState(dashboardId, {
|
||||
status: status?.is_dirty ? "diff" : "ok",
|
||||
branch: status?.current_branch || null,
|
||||
hasRepo: true,
|
||||
hasChangesForCommit: Boolean(status?.is_dirty),
|
||||
});
|
||||
} catch (_err) {
|
||||
updateDashboardGitState(dashboardId, {
|
||||
status: "no_repo",
|
||||
branch: null,
|
||||
hasRepo: false,
|
||||
hasChangesForCommit: false,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
async function handleGitInit(dashboard) {
|
||||
setGitBusy(dashboard.id, true);
|
||||
try {
|
||||
const configs = await ensureGitConfigs();
|
||||
if (!configs.length) {
|
||||
addToast($t.git?.no_servers_configured || "No Git config found", "error");
|
||||
return;
|
||||
}
|
||||
|
||||
const config = configs[0];
|
||||
const defaultRemote = config?.default_repository
|
||||
? `${String(config.url || "").replace(/\/$/, "")}/${config.default_repository}.git`
|
||||
: "";
|
||||
const remoteUrl = prompt($t.git?.remote_url || "Remote URL", defaultRemote);
|
||||
if (!remoteUrl) return;
|
||||
|
||||
await gitService.initRepository(dashboard.id, config.id, remoteUrl.trim());
|
||||
addToast($t.git?.init_success || "Repository initialized", "success");
|
||||
await refreshDashboardGitState(dashboard.id);
|
||||
} catch (err) {
|
||||
addToast(err?.message || "Git init failed", "error");
|
||||
} finally {
|
||||
setGitBusy(dashboard.id, false);
|
||||
}
|
||||
}
|
||||
|
||||
async function handleGitSync(dashboard) {
|
||||
setGitBusy(dashboard.id, true);
|
||||
try {
|
||||
await gitService.sync(dashboard.id, selectedEnv || null);
|
||||
addToast($t.git?.sync_success || "Synced", "success");
|
||||
await refreshDashboardGitState(dashboard.id);
|
||||
} catch (err) {
|
||||
addToast(err?.message || "Git sync failed", "error");
|
||||
} finally {
|
||||
setGitBusy(dashboard.id, false);
|
||||
}
|
||||
}
|
||||
|
||||
async function handleGitCommit(dashboard) {
|
||||
if (!dashboard.git?.hasRepo) {
|
||||
addToast($t.git?.not_linked || "Repository not linked", "error");
|
||||
return;
|
||||
}
|
||||
if (!dashboard.git?.hasChangesForCommit) {
|
||||
addToast($t.git?.nothing_to_commit || "No changes to commit", "error");
|
||||
return;
|
||||
}
|
||||
|
||||
const message = prompt(
|
||||
$t.git?.commit_message || "Commit message",
|
||||
`Update dashboard ${dashboard.title}`,
|
||||
);
|
||||
if (!message?.trim()) return;
|
||||
|
||||
setGitBusy(dashboard.id, true);
|
||||
try {
|
||||
await gitService.commit(dashboard.id, message.trim());
|
||||
addToast($t.git?.commit_success || "Committed", "success");
|
||||
await refreshDashboardGitState(dashboard.id);
|
||||
} catch (err) {
|
||||
addToast(err?.message || "Git commit failed", "error");
|
||||
} finally {
|
||||
setGitBusy(dashboard.id, false);
|
||||
}
|
||||
}
|
||||
|
||||
async function handleGitPull(dashboard) {
|
||||
if (!dashboard.git?.hasRepo) return;
|
||||
setGitBusy(dashboard.id, true);
|
||||
try {
|
||||
await gitService.pull(dashboard.id);
|
||||
addToast($t.git?.pull_success || "Pulled", "success");
|
||||
await refreshDashboardGitState(dashboard.id);
|
||||
} catch (err) {
|
||||
addToast(err?.message || "Git pull failed", "error");
|
||||
} finally {
|
||||
setGitBusy(dashboard.id, false);
|
||||
}
|
||||
}
|
||||
|
||||
async function handleGitPush(dashboard) {
|
||||
if (!dashboard.git?.hasRepo) return;
|
||||
setGitBusy(dashboard.id, true);
|
||||
try {
|
||||
await gitService.push(dashboard.id);
|
||||
addToast($t.git?.push_success || "Pushed", "success");
|
||||
await refreshDashboardGitState(dashboard.id);
|
||||
} catch (err) {
|
||||
addToast(err?.message || "Git push failed", "error");
|
||||
} finally {
|
||||
setGitBusy(dashboard.id, false);
|
||||
}
|
||||
}
|
||||
|
||||
// Get task status icon
|
||||
function getTaskStatusIcon(status) {
|
||||
if (!status) return "";
|
||||
@@ -736,19 +886,24 @@
|
||||
|
||||
<!-- Git Status -->
|
||||
<div class="col-span-2">
|
||||
{#if dashboard.gitStatus}
|
||||
<div class="flex flex-col gap-1">
|
||||
<span
|
||||
class="status-badge {getStatusBadgeClass(dashboard.gitStatus)}"
|
||||
class="status-badge {dashboard.git?.hasRepo ? 'bg-blue-100 text-blue-800' : 'bg-gray-100 text-gray-700'}"
|
||||
>
|
||||
{#if dashboard.gitStatus.toLowerCase() === "ok"}
|
||||
✓ {$t.dashboard?.status_synced }
|
||||
{:else if dashboard.gitStatus.toLowerCase() === "diff"}
|
||||
! {$t.dashboard?.status_diff }
|
||||
{/if}
|
||||
{dashboard.git?.hasRepo
|
||||
? ($t.dashboard?.status_repo || "Repo")
|
||||
: ($t.dashboard?.status_no_repo || "No Repo")}
|
||||
</span>
|
||||
{:else}
|
||||
<span class="text-gray-400">-</span>
|
||||
{/if}
|
||||
{#if dashboard.git?.hasRepo}
|
||||
<span
|
||||
class="status-badge {dashboard.git?.hasChangesForCommit ? 'bg-yellow-100 text-yellow-800' : 'bg-green-100 text-green-800'}"
|
||||
>
|
||||
{dashboard.git?.hasChangesForCommit
|
||||
? ($t.dashboard?.status_changes || "Diff")
|
||||
: ($t.dashboard?.status_no_changes || "Synced")}
|
||||
</span>
|
||||
{/if}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Last Task -->
|
||||
@@ -785,6 +940,73 @@
|
||||
<!-- Actions -->
|
||||
<div class="col-span-3 flex items-center">
|
||||
<div class="flex items-center gap-1">
|
||||
{#if !dashboard.git?.hasRepo}
|
||||
<button
|
||||
class="p-2 rounded border border-gray-200 hover:bg-gray-50 hover:border-gray-300 transition-colors disabled:opacity-50 disabled:cursor-not-allowed"
|
||||
on:click={() => handleGitInit(dashboard)}
|
||||
disabled={isGitBusy(dashboard.id)}
|
||||
title={$t.git?.init_repo || "Init Git repository"}
|
||||
>
|
||||
<svg
|
||||
width="14"
|
||||
height="14"
|
||||
viewBox="0 0 24 24"
|
||||
fill="none"
|
||||
stroke="currentColor"
|
||||
stroke-width="2"
|
||||
>
|
||||
<path d="M12 5v14M5 12h14" />
|
||||
</svg>
|
||||
</button>
|
||||
{:else}
|
||||
<button
|
||||
class="p-2 rounded border border-gray-200 hover:bg-gray-50 hover:border-gray-300 transition-colors disabled:opacity-50 disabled:cursor-not-allowed"
|
||||
on:click={() => handleGitSync(dashboard)}
|
||||
disabled={isGitBusy(dashboard.id)}
|
||||
title={$t.git?.sync || "Sync from Superset"}
|
||||
>
|
||||
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
|
||||
<path d="M21 12a9 9 0 1 1-3-6.7" />
|
||||
<polyline points="21 3 21 9 15 9" />
|
||||
</svg>
|
||||
</button>
|
||||
<button
|
||||
class="p-2 rounded border border-gray-200 hover:bg-gray-50 hover:border-gray-300 transition-colors disabled:opacity-50 disabled:cursor-not-allowed"
|
||||
on:click={() => handleGitCommit(dashboard)}
|
||||
disabled={isGitBusy(dashboard.id) || !dashboard.git?.hasChangesForCommit}
|
||||
title={$t.git?.commit || "Commit"}
|
||||
>
|
||||
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
|
||||
<path d="M12 3v12" />
|
||||
<path d="M7 10l5 5 5-5" />
|
||||
<path d="M5 21h14" />
|
||||
</svg>
|
||||
</button>
|
||||
<button
|
||||
class="p-2 rounded border border-gray-200 hover:bg-gray-50 hover:border-gray-300 transition-colors disabled:opacity-50 disabled:cursor-not-allowed"
|
||||
on:click={() => handleGitPull(dashboard)}
|
||||
disabled={isGitBusy(dashboard.id)}
|
||||
title={$t.git?.pull || "Pull"}
|
||||
>
|
||||
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
|
||||
<path d="M12 3v12" />
|
||||
<path d="M17 10l-5 5-5-5" />
|
||||
<path d="M5 21h14" />
|
||||
</svg>
|
||||
</button>
|
||||
<button
|
||||
class="p-2 rounded border border-gray-200 hover:bg-gray-50 hover:border-gray-300 transition-colors disabled:opacity-50 disabled:cursor-not-allowed"
|
||||
on:click={() => handleGitPush(dashboard)}
|
||||
disabled={isGitBusy(dashboard.id)}
|
||||
title={$t.git?.push || "Push"}
|
||||
>
|
||||
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
|
||||
<path d="M12 21V9" />
|
||||
<path d="M7 14l5-5 5 5" />
|
||||
<path d="M5 3h14" />
|
||||
</svg>
|
||||
</button>
|
||||
{/if}
|
||||
<button
|
||||
class="p-2 rounded border border-gray-200 hover:bg-gray-50 hover:border-gray-300 transition-colors disabled:opacity-50 disabled:cursor-not-allowed"
|
||||
on:click={() => handleAction(dashboard, "migrate")}
|
||||
|
||||
Reference in New Issue
Block a user