fix(dashboard): git filter shows 'pending' instead of 'no_repo' for dashboards without repo
The frontend defaulted git status to 'pending' when git_status was null, but the backend returns 'no_repo' for such dashboards. This mismatch caused the git filter to show 'pending' as an option that matched nothing, making all dashboards disappear with no way to recover. Fixed by aligning the frontend fallback to 'no_repo' to match backend.
This commit is contained in:
@@ -56,6 +56,8 @@ export class DashboardHubModel {
|
||||
// ── Core state ────────────────────────────────────────────────
|
||||
selectedEnv: string | null = $state(null);
|
||||
allDashboards: import("./Dashboards.FiltersModel.svelte.ts").DashboardRow[] = $state([]);
|
||||
/** Larger dataset for filter options (loaded via loadDashboardSearchOptions, up to 100) */
|
||||
filterOptionsDashboards: import("./Dashboards.FiltersModel.svelte.ts").DashboardRow[] = $state([]);
|
||||
dashboards: import("./Dashboards.FiltersModel.svelte.ts").DashboardRow[] = $state([]);
|
||||
filteredDashboards: import("./Dashboards.FiltersModel.svelte.ts").DashboardRow[] = $state([]);
|
||||
isLoading: boolean = $state(true);
|
||||
@@ -63,6 +65,8 @@ export class DashboardHubModel {
|
||||
|
||||
// ── Validation popover ────────────────────────────────────────
|
||||
validationStatuses: Record<string, any> = $state({});
|
||||
/** Version counter bumped after each fetchValidationStatuses — triggers grid re-render */
|
||||
validationVersion: number = $state(0);
|
||||
openValidationPopover: string | null = $state(null);
|
||||
validationPopoverPosition: { left: number; top: number } = $state({ left: 0, top: 0 });
|
||||
validationStatusLoading: boolean = $state(false);
|
||||
@@ -181,11 +185,15 @@ export class DashboardHubModel {
|
||||
}
|
||||
|
||||
getFilterOptions(column: any): string[] {
|
||||
return this.filters.getFilterOptions(this.allDashboards as any, this.validationStatuses);
|
||||
const data = this.filterOptionsDashboards.length > this.allDashboards.length
|
||||
? this.filterOptionsDashboards : this.allDashboards;
|
||||
return this.filters.getFilterOptions(column, data as any, this.validationStatuses);
|
||||
}
|
||||
|
||||
getVisibleFilterOptions(column: any): string[] {
|
||||
return this.filters.getVisibleFilterOptions(column, this.allDashboards as any, this.validationStatuses);
|
||||
const data = this.filterOptionsDashboards.length > this.allDashboards.length
|
||||
? this.filterOptionsDashboards : this.allDashboards;
|
||||
return this.filters.getVisibleFilterOptions(column, data as any, this.validationStatuses);
|
||||
}
|
||||
|
||||
toggleFilterDropdown(column: any, event: Event | undefined, panelWidth?: number): void {
|
||||
@@ -356,7 +364,7 @@ export class DashboardHubModel {
|
||||
branch: d.git_status?.branch || null,
|
||||
hasRepo: d.git_status?.has_repo === true,
|
||||
hasChangesForCommit: d.git_status?.has_changes_for_commit === true,
|
||||
} : { status: "pending", branch: null, hasRepo: null, hasChangesForCommit: false },
|
||||
} : { status: "no_repo", branch: null, hasRepo: null, hasChangesForCommit: false },
|
||||
lastTask: d.last_task ? {
|
||||
status: normalizeTaskStatus(d.last_task.status),
|
||||
validationStatus: normalizeValidationStatus(d.last_task.validation_status),
|
||||
@@ -387,10 +395,29 @@ export class DashboardHubModel {
|
||||
search: query || undefined, page_size: 100, page_context: 'other',
|
||||
apply_profile_default: false, override_show_all: true,
|
||||
});
|
||||
this.searchableDashboardOptions = (response?.dashboards || []).map((d: any) => ({
|
||||
const raw = response?.dashboards || [];
|
||||
this.searchableDashboardOptions = raw.map((d: any) => ({
|
||||
id: d.id, name: d.title, subtitle: d.slug || '',
|
||||
hint: d.last_modified ? formatDate(d.last_modified) : '',
|
||||
}));
|
||||
// Also store for filter options (lightweight DashboardRow mapping)
|
||||
this.filterOptionsDashboards = raw.map((d: any) => {
|
||||
const owners = normalizeOwners(d.owners);
|
||||
const hasGitStatus = !!d.git_status;
|
||||
return {
|
||||
id: d.id, title: d.title, slug: d.slug,
|
||||
changedOn: d.last_modified || null,
|
||||
changedOnLabel: formatDate(d.last_modified),
|
||||
owners,
|
||||
actorLabel: owners.length > 0 ? owners.join(", ") : "-",
|
||||
git: hasGitStatus ? {
|
||||
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,
|
||||
} : { status: "no_repo", branch: null, hasRepo: null, hasChangesForCommit: false },
|
||||
} as any;
|
||||
});
|
||||
} catch {
|
||||
this.searchableDashboardOptions = [];
|
||||
console.warn('[DashboardHub] loadDashboardSearchOptions failed');
|
||||
@@ -405,7 +432,7 @@ export class DashboardHubModel {
|
||||
const ids = this.dashboards.map((d: any) => d.id).filter(Boolean);
|
||||
if (ids.length === 0) return;
|
||||
const result = await api.getValidationStatusBatch(this.selectedEnv, ids.join(","));
|
||||
if (result && typeof result === "object") this.validationStatuses = result;
|
||||
if (result && typeof result === "object") { this.validationStatuses = result; this.validationVersion++; }
|
||||
} catch { /* graceful no-op */ }
|
||||
finally { this.validationStatusLoading = false; }
|
||||
}
|
||||
@@ -433,7 +460,7 @@ export class DashboardHubModel {
|
||||
this.total = result.total;
|
||||
this.totalPages = result.totalPages;
|
||||
this.selection.updateSelectionState(this.filteredDashboards as any, this.dashboards as any);
|
||||
void this.hydrateVisibleGitStatusesBatch();
|
||||
void this.hydrateVisibleGitStatusesBatch().catch(() => {});
|
||||
void this.fetchValidationStatuses();
|
||||
}
|
||||
|
||||
|
||||
@@ -98,22 +98,22 @@ export class DashboardsFiltersModel {
|
||||
|
||||
getColumnCellValue(dashboard: DashboardRow, column: FilterColumn, validationStatuses: Record<string, any>): string {
|
||||
if (column === "title") return dashboard.title || "-";
|
||||
if (column === "git_status") return String(dashboard.git?.status || "pending").toLowerCase();
|
||||
if (column === "git_status") return String(dashboard.git?.status || "no_repo").toLowerCase();
|
||||
if (column === "validation_status") return this.getValidationLabelForCell(dashboard, validationStatuses);
|
||||
if (column === "changed_on") return dashboard.changedOn ? String(dashboard.changedOn).slice(0, 10) : "-";
|
||||
if (column === "actor") return dashboard.actorLabel || "-";
|
||||
return "-";
|
||||
}
|
||||
|
||||
getFilterOptions(allDashboards: DashboardRow[], validationStatuses: Record<string, any>): string[] {
|
||||
getFilterOptions(column: FilterColumn, allDashboards: DashboardRow[], validationStatuses: Record<string, any>): string[] {
|
||||
return Array.from(new SvelteSet(
|
||||
allDashboards.map(d => this.getColumnCellValue(d, "title", validationStatuses)).filter(Boolean)
|
||||
allDashboards.map(d => this.getColumnCellValue(d, column, validationStatuses)).filter(Boolean)
|
||||
)).sort((a, b) => a.localeCompare(b, "ru"));
|
||||
}
|
||||
|
||||
getVisibleFilterOptions(column: FilterColumn, allDashboards: DashboardRow[], validationStatuses: Record<string, any>): string[] {
|
||||
const searchText = (this.columnFilterSearch[column] || "").toLowerCase();
|
||||
return this.getFilterOptions(allDashboards, validationStatuses).filter(v => v.toLowerCase().includes(searchText));
|
||||
return this.getFilterOptions(column, allDashboards, validationStatuses).filter(v => v.toLowerCase().includes(searchText));
|
||||
}
|
||||
|
||||
toggleFilterDropdown(column: FilterColumn, event: Event | undefined, panelWidth = 256): void {
|
||||
|
||||
Reference in New Issue
Block a user