semantics
This commit is contained in:
@@ -6,8 +6,8 @@
|
||||
|
||||
@SEMANTICS: dashboard, grid, selection, pagination
|
||||
@PURPOSE: Displays a grid of dashboards with selection and pagination.
|
||||
@LAYER: Component
|
||||
@RELATION: USED_BY -> frontend/src/routes/migration/+page.svelte
|
||||
@LAYER Component
|
||||
@RELATION USED_BY -> [frontend/src/routes/migration/+page.svelte]
|
||||
|
||||
@INVARIANT: Selected IDs must be a subset of available dashboards.
|
||||
-->
|
||||
|
||||
@@ -4,8 +4,8 @@
|
||||
<!--
|
||||
@SEMANTICS: form, schema, dynamic, json-schema
|
||||
@PURPOSE: Generates a form dynamically based on a JSON schema.
|
||||
@LAYER: UI
|
||||
@RELATION: BINDS_TO -> onsubmit callback
|
||||
@LAYER UI
|
||||
@RELATION BINDS_TO -> [onsubmit callback]
|
||||
|
||||
@PROPS:
|
||||
- schema: Object - JSON schema for the form.
|
||||
|
||||
@@ -4,8 +4,8 @@
|
||||
<!--
|
||||
@SEMANTICS: environment, selector, dropdown, migration
|
||||
@PURPOSE: Provides a UI component for selecting source and target environments.
|
||||
@LAYER: Feature
|
||||
@RELATION: BINDS_TO -> environments store
|
||||
@LAYER Feature
|
||||
@RELATION BINDS_TO -> [environments store]
|
||||
|
||||
@INVARIANT: Source and target environments must be selectable from the list of configured environments.
|
||||
-->
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
<!--
|
||||
@SEMANTICS: footer, layout, copyright
|
||||
@PURPOSE: Displays the application footer with copyright information.
|
||||
@LAYER: UI
|
||||
@LAYER UI
|
||||
-->
|
||||
<footer class="bg-white border-t p-4 mt-8 text-center text-gray-500 text-sm">
|
||||
© 2025 Superset Tools. All rights reserved.
|
||||
|
||||
@@ -4,8 +4,8 @@
|
||||
<!--
|
||||
@SEMANTICS: mapping, table, database, editor
|
||||
@PURPOSE: Displays and allows editing of database mappings.
|
||||
@LAYER: Feature
|
||||
@RELATION: BINDS_TO -> mappings state
|
||||
@LAYER Feature
|
||||
@RELATION BINDS_TO -> [mappings state]
|
||||
|
||||
@INVARIANT: Each source database can be mapped to one target database.
|
||||
-->
|
||||
|
||||
@@ -4,9 +4,9 @@
|
||||
<!--
|
||||
@SEMANTICS: modal, mapping, prompt, migration
|
||||
@PURPOSE: Prompts the user to provide a database mapping when one is missing during migration.
|
||||
@LAYER: Feature
|
||||
@RELATION: BINDS_TO -> onresolve
|
||||
@RELATION: BINDS_TO -> oncancel
|
||||
@LAYER Feature
|
||||
@RELATION BINDS_TO -> [EXT:frontend:onresolve]
|
||||
@RELATION BINDS_TO -> [EXT:frontend:oncancel]
|
||||
|
||||
@INVARIANT: Modal blocks migration progress until resolved or cancelled.
|
||||
-->
|
||||
|
||||
@@ -4,10 +4,10 @@
|
||||
<!--
|
||||
@SEMANTICS: navbar, navigation, header, layout
|
||||
@PURPOSE: Main navigation bar for the application.
|
||||
@LAYER: UI
|
||||
@RELATION: BINDS_TO -> [authStore]
|
||||
@RELATION: BINDS_TO -> [i18n]
|
||||
@RELATION: DEPENDS_ON -> [LanguageSwitcher]
|
||||
@LAYER UI
|
||||
@RELATION BINDS_TO -> [EXT:frontend:authStore]
|
||||
@RELATION BINDS_TO -> [EXT:frontend:i18n]
|
||||
@RELATION DEPENDS_ON -> [LanguageSwitcher]
|
||||
|
||||
@UX_STATE: Idle -> Navigation links and settings menus are visible.
|
||||
@UX_STATE: Authenticated -> User identity and logout action are rendered.
|
||||
|
||||
@@ -4,10 +4,10 @@
|
||||
<!--
|
||||
@SEMANTICS: password, prompt, modal, input, security
|
||||
@PURPOSE: A modal component to prompt the user for database passwords when a migration task is paused.
|
||||
@LAYER: UI
|
||||
@RELATION: USES -> frontend/src/lib/api.js (inferred)
|
||||
@RELATION: BINDS_TO -> onresume
|
||||
@RELATION: BINDS_TO -> oncancel
|
||||
@LAYER UI
|
||||
@RELATION USES -> [EXT:path:frontend/src/lib/api.js (inferred)]
|
||||
@RELATION BINDS_TO -> [EXT:frontend:onresume]
|
||||
@RELATION BINDS_TO -> [EXT:frontend:oncancel]
|
||||
-->
|
||||
<script>
|
||||
let {
|
||||
|
||||
@@ -4,8 +4,8 @@
|
||||
<!--
|
||||
@SEMANTICS: dashboard, grid, selection, pagination
|
||||
@PURPOSE: Displays a grid of dashboards with selection and pagination.
|
||||
@LAYER: Component
|
||||
@RELATION: USED_BY -> frontend/src/routes/migration/+page.svelte
|
||||
@LAYER Component
|
||||
@RELATION USED_BY -> [frontend/src/routes/migration/+page.svelte]
|
||||
|
||||
@INVARIANT: Selected IDs must be a subset of available dashboards.
|
||||
-->
|
||||
|
||||
@@ -5,9 +5,9 @@
|
||||
<script>
|
||||
/**
|
||||
* @PURPOSE: Blocking startup wizard for creating the first Superset environment from zero-state screens.
|
||||
* @LAYER: UI
|
||||
* @RELATION: CALLS -> api
|
||||
* @RELATION: CALLS -> environmentContext
|
||||
* @LAYER UI
|
||||
* @RELATION CALLS -> api
|
||||
* @RELATION CALLS -> environmentContext
|
||||
* @INVARIANT: When open, wizard keeps user on an actionable setup path until the first environment exists.
|
||||
*
|
||||
* @UX_STATE: Intro -> Explains why dashboard screen is blocked.
|
||||
|
||||
@@ -4,9 +4,9 @@
|
||||
<!--
|
||||
@SEMANTICS: task, history, list, status, monitoring
|
||||
@PURPOSE: Displays a list of recent tasks with their status and allows selecting them for viewing logs.
|
||||
@LAYER: UI
|
||||
@RELATION: USES -> stores
|
||||
@RELATION: USES -> frontend/src/lib/api.js (inferred)
|
||||
@LAYER UI
|
||||
@RELATION USES -> [EXT:frontend:stores]
|
||||
@RELATION USES -> [EXT:path:frontend/src/lib/api.js (inferred)]
|
||||
-->
|
||||
<script>
|
||||
import { onMount, onDestroy } from 'svelte';
|
||||
|
||||
@@ -4,8 +4,8 @@
|
||||
<!--
|
||||
@SEMANTICS: tasks, list, status, history
|
||||
@PURPOSE: Displays a list of tasks with their status and execution details.
|
||||
@LAYER: Component
|
||||
@RELATION: USES -> api.js
|
||||
@LAYER Component
|
||||
@RELATION USES -> [EXT:frontend:api.js]
|
||||
-->
|
||||
|
||||
<script lang="ts">
|
||||
|
||||
@@ -6,9 +6,9 @@
|
||||
|
||||
@SEMANTICS: task, log, viewer, inline, realtime
|
||||
@PURPOSE: Displays task logs inline (in drawer) or as modal. Merges real-time WebSocket logs with polled historical logs.
|
||||
@LAYER: UI
|
||||
@RELATION: USES -> taskService
|
||||
@RELATION: USES -> TaskLogPanel
|
||||
@LAYER UI
|
||||
@RELATION USES -> [EXT:frontend:taskService]
|
||||
@RELATION USES -> [TaskLogPanel]
|
||||
@INVARIANT: Real-time logs are always appended without duplicates.
|
||||
-->
|
||||
<script>
|
||||
|
||||
@@ -6,8 +6,8 @@
|
||||
|
||||
@SEMANTICS: task, runner, logs, websocket
|
||||
@PURPOSE: Connects to a WebSocket to display real-time logs for a running task with filtering support.
|
||||
@LAYER: UI
|
||||
@RELATION: DEPENDS_ON -> TaskLogPanel
|
||||
@LAYER UI
|
||||
@RELATION DEPENDS_ON -> [TaskLogPanel]
|
||||
-->
|
||||
<script>
|
||||
// [SECTION: IMPORTS]
|
||||
@@ -51,7 +51,7 @@
|
||||
const task = get(selectedTask);
|
||||
if (!task || connectionStatus === 'completed') return;
|
||||
|
||||
console.log(`[TaskRunner][Entry] Connecting to logs for task: ${task.id} (Attempt ${reconnectAttempts + 1}) filters: source=${selectedSource}, level=${selectedLevel}`);
|
||||
console.log(`[EXT:frontend:TaskRunner][Entry] Connecting to logs for task: ${task.id} (Attempt ${reconnectAttempts + 1}) filters: source=${selectedSource}, level=${selectedLevel}`);
|
||||
connectionStatus = 'connecting';
|
||||
|
||||
let wsUrl = getWsUrl(task.id);
|
||||
@@ -69,7 +69,7 @@
|
||||
ws = new WebSocket(wsUrl);
|
||||
|
||||
ws.onopen = () => {
|
||||
console.log('[TaskRunner][Coherence:OK] WebSocket connection established');
|
||||
console.log('[EXT:frontend:TaskRunner][Coherence:OK] WebSocket connection established');
|
||||
connectionStatus = 'connected';
|
||||
reconnectAttempts = 0;
|
||||
startDataTimeout();
|
||||
@@ -121,24 +121,24 @@
|
||||
}
|
||||
|
||||
ws.onerror = (error) => {
|
||||
console.error('[TaskRunner][Coherence:Failed] WebSocket error:', error);
|
||||
console.error('[EXT:frontend:TaskRunner][Coherence:Failed] WebSocket error:', error);
|
||||
connectionStatus = 'disconnected';
|
||||
};
|
||||
|
||||
ws.onclose = (event) => {
|
||||
console.log(`[TaskRunner][Exit] WebSocket connection closed (Code: ${event.code})`);
|
||||
console.log(`[EXT:frontend:TaskRunner][Exit] WebSocket connection closed (Code: ${event.code})`);
|
||||
clearTimeout(dataTimeout);
|
||||
waitingForData = false;
|
||||
|
||||
if (connectionStatus !== 'completed' && reconnectAttempts < maxReconnectAttempts) {
|
||||
const delay = Math.min(initialReconnectDelay * Math.pow(2, reconnectAttempts), maxReconnectDelay);
|
||||
console.log(`[TaskRunner][Action] Reconnecting in ${delay}ms...`);
|
||||
console.log(`[EXT:frontend:TaskRunner][Action] Reconnecting in ${delay}ms...`);
|
||||
reconnectTimeout = setTimeout(() => {
|
||||
reconnectAttempts++;
|
||||
connect();
|
||||
}, delay);
|
||||
} else if (reconnectAttempts >= maxReconnectAttempts) {
|
||||
console.error('[TaskRunner][Coherence:Failed] Max reconnect attempts reached.');
|
||||
console.error('[EXT:frontend:TaskRunner][Coherence:Failed] Max reconnect attempts reached.');
|
||||
addToast($t.tasks?.log_stream_failed, 'error');
|
||||
}
|
||||
};
|
||||
@@ -158,7 +158,7 @@
|
||||
selectedSource = source;
|
||||
selectedLevel = level;
|
||||
|
||||
console.log(`[TaskRunner] Filter changed, reconnecting WebSocket: source=${source}, level=${level}`);
|
||||
console.log(`[EXT:frontend:TaskRunner] Filter changed, reconnecting WebSocket: source=${source}, level=${level}`);
|
||||
|
||||
// Clear current logs when filter changes to avoid confusion
|
||||
taskLogs.set([]);
|
||||
@@ -290,14 +290,14 @@
|
||||
onMount(() => {
|
||||
const unsubscribe = selectedTask.subscribe(task => {
|
||||
if (task) {
|
||||
console.log(`[TaskRunner][Action] Task selected: ${task.id}. Initializing connection.`);
|
||||
console.log(`[EXT:frontend:TaskRunner][Action] Task selected: ${task.id}. Initializing connection.`);
|
||||
if (ws) ws.close();
|
||||
clearTimeout(reconnectTimeout);
|
||||
reconnectAttempts = 0;
|
||||
connectionStatus = 'disconnected';
|
||||
|
||||
if (task.logs && Array.isArray(task.logs)) {
|
||||
console.log(`[TaskRunner] Loaded ${task.logs.length} existing logs.`);
|
||||
console.log(`[EXT:frontend:TaskRunner] Loaded ${task.logs.length} existing logs.`);
|
||||
taskLogs.set(task.logs);
|
||||
} else {
|
||||
taskLogs.set([]);
|
||||
@@ -315,7 +315,7 @@
|
||||
clearTimeout(reconnectTimeout);
|
||||
clearTimeout(dataTimeout);
|
||||
if (ws) {
|
||||
console.log("[TaskRunner][Action] Closing WebSocket connection.");
|
||||
console.log("[EXT:frontend:TaskRunner][Action] Closing WebSocket connection.");
|
||||
ws.close();
|
||||
}
|
||||
});
|
||||
|
||||
@@ -4,8 +4,8 @@
|
||||
<!--
|
||||
@SEMANTICS: toast, notification, feedback, ui
|
||||
@PURPOSE: Displays transient notifications (toasts) in the bottom-right corner.
|
||||
@LAYER: UI
|
||||
@RELATION: BINDS_TO -> toasts
|
||||
@LAYER UI
|
||||
@RELATION BINDS_TO -> [EXT:frontend:toasts]
|
||||
|
||||
@UX_STATE: Empty -> Toast viewport stays mounted without visible notifications.
|
||||
@UX_STATE: Visible -> Active toast items render with type-specific emphasis.
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
// #region TaskLogViewerTest:Module [TYPE Function]
|
||||
// @SEMANTICS: tests, task-log, viewer, mount, components
|
||||
// @PURPOSE: Unit tests for TaskLogViewer component by mounting it and observing the DOM.
|
||||
// @LAYER: UI (Tests)
|
||||
// @RELATION: DEPENDS_ON -> [TaskLogViewer]
|
||||
// @LAYER UI (Tests)
|
||||
// @RELATION DEPENDS_ON -> [TaskLogViewer]
|
||||
// @INVARIANT: Duplicate logs are never appended. Polling only active for in-progress tasks.
|
||||
// @TEST_CONTRACT: TaskLogViewerPropsAndLogStream -> RenderedLogTimeline
|
||||
// @TEST_SCENARIO: historical_and_realtime_merge -> Historical logs render and realtime logs append without duplication.
|
||||
|
||||
@@ -4,11 +4,11 @@
|
||||
<!--
|
||||
@SEMANTICS: auth, route-guard, permission, redirect, session-validation
|
||||
@PURPOSE: Enforces authenticated and authorized access before protected route content is rendered.
|
||||
@LAYER: UI
|
||||
@RELATION: [BINDS_TO] ->[authStore]
|
||||
@RELATION: [CALLS] ->[goto]
|
||||
@RELATION: [DEPENDS_ON] ->[Permissions]
|
||||
@RELATION: [CALLS] ->[fetchApi]
|
||||
@LAYER UI
|
||||
@RELATION BINDS_TO ->[EXT:frontend:authStore]
|
||||
@RELATION CALLS ->[EXT:frontend:goto]
|
||||
@RELATION DEPENDS_ON ->[EXT:internal:Permissions]
|
||||
@RELATION CALLS ->[EXT:frontend:fetchApi]
|
||||
@INVARIANT: Unauthenticated users are redirected to /login, unauthorized users are redirected to fallbackPath, and protected slot renders only when access is verified.
|
||||
@UX_STATE: Idle -> Component mounted, verification not yet started.
|
||||
@UX_STATE: Loading -> Spinner is rendered while auth/session/permission validation is in progress.
|
||||
|
||||
@@ -4,8 +4,8 @@
|
||||
<!--
|
||||
@SEMANTICS: backup, list, table
|
||||
@PURPOSE: Displays a list of existing backups.
|
||||
@LAYER: Component
|
||||
@RELATION: USED_BY -> frontend/src/components/backups/BackupManager.svelte
|
||||
@LAYER Component
|
||||
@RELATION USED_BY -> [frontend/src/components/backups/BackupManager.svelte]
|
||||
-->
|
||||
|
||||
<script lang="ts">
|
||||
|
||||
@@ -4,9 +4,9 @@
|
||||
<!--
|
||||
@SEMANTICS: backup, manager, orchestrator
|
||||
@PURPOSE: Main container for backup management, handling creation and listing.
|
||||
@LAYER: Feature
|
||||
@RELATION: USES -> BackupList
|
||||
@RELATION: USES -> api
|
||||
@LAYER Feature
|
||||
@RELATION USES -> [BackupList]
|
||||
@RELATION USES -> [EXT:frontend:api]
|
||||
|
||||
@INVARIANT: Only one backup task can be triggered at a time from the UI.
|
||||
-->
|
||||
@@ -56,8 +56,8 @@
|
||||
* @returns {Promise<void>}
|
||||
* @side_effect Updates local state variables.
|
||||
*/
|
||||
// @RELATION: CALLS -> api.getEnvironmentsList
|
||||
// @RELATION: CALLS -> api.requestApi
|
||||
// @RELATION CALLS -> api.getEnvironmentsList
|
||||
// @RELATION CALLS -> api.requestApi
|
||||
function getSubpath(path: string): string {
|
||||
if (!path || path === 'backups') return '';
|
||||
return path.replace(/^backups\/?/, '');
|
||||
@@ -70,7 +70,7 @@
|
||||
}
|
||||
|
||||
async function loadData() {
|
||||
console.log("[BackupManager][Entry] Loading data.");
|
||||
console.log("[EXT:frontend:BackupManager][Entry] Loading data.");
|
||||
loading = true;
|
||||
try {
|
||||
const subpath = getSubpath(currentPath);
|
||||
@@ -94,9 +94,9 @@
|
||||
is_directory: file.mime_type === 'directory',
|
||||
status: 'success'
|
||||
}));
|
||||
console.log("[BackupManager][Action] Data loaded successfully.");
|
||||
console.log("[EXT:frontend:BackupManager][Action] Data loaded successfully.");
|
||||
} catch (error) {
|
||||
console.error("[BackupManager][Coherence:Failed] Load failed", error);
|
||||
console.error("[EXT:frontend:BackupManager][Coherence:Failed] Load failed", error);
|
||||
} finally {
|
||||
loading = false;
|
||||
}
|
||||
@@ -113,7 +113,7 @@
|
||||
* @returns {Promise<void>}
|
||||
* @side_effect Dispatches a toast notification.
|
||||
*/
|
||||
// @RELATION: CALLS -> api.createTask
|
||||
// @RELATION CALLS -> api.createTask
|
||||
// #region handleUpdateSchedule:Function [TYPE Function]
|
||||
/**
|
||||
* @purpose Updates the backup schedule for the selected environment.
|
||||
@@ -123,7 +123,7 @@
|
||||
async function handleUpdateSchedule() {
|
||||
if (!selectedEnvId) return;
|
||||
|
||||
console.log(`[BackupManager][Action] Updating schedule for env: ${selectedEnvId}`);
|
||||
console.log(`[EXT:frontend:BackupManager][Action] Updating schedule for env: ${selectedEnvId}`);
|
||||
savingSchedule = true;
|
||||
try {
|
||||
await api.updateEnvironmentSchedule(selectedEnvId, {
|
||||
@@ -139,7 +139,7 @@
|
||||
: e
|
||||
);
|
||||
} catch (error) {
|
||||
console.error("[BackupManager][Coherence:Failed] Schedule update failed", error);
|
||||
console.error("[EXT:frontend:BackupManager][Coherence:Failed] Schedule update failed", error);
|
||||
} finally {
|
||||
savingSchedule = false;
|
||||
}
|
||||
@@ -152,14 +152,14 @@
|
||||
return;
|
||||
}
|
||||
|
||||
console.log(`[BackupManager][Action] Triggering backup for env: ${selectedEnvId}`);
|
||||
console.log(`[EXT:frontend:BackupManager][Action] Triggering backup for env: ${selectedEnvId}`);
|
||||
creating = true;
|
||||
try {
|
||||
await api.createTask('superset-backup', { environment_id: selectedEnvId });
|
||||
addToast($t.common.success, 'success');
|
||||
console.log("[BackupManager][Coherence:OK] Backup task triggered.");
|
||||
console.log("[EXT:frontend:BackupManager][Coherence:OK] Backup task triggered.");
|
||||
} catch (error) {
|
||||
console.error("[BackupManager][Coherence:Failed] Create failed", error);
|
||||
console.error("[EXT:frontend:BackupManager][Coherence:Failed] Create failed", error);
|
||||
} finally {
|
||||
creating = false;
|
||||
}
|
||||
|
||||
@@ -4,11 +4,11 @@
|
||||
<!--
|
||||
@SEMANTICS: git, branch, selection, checkout
|
||||
@PURPOSE: UI для выбора и создания веток Git.
|
||||
@LAYER: Component
|
||||
@RELATION: CALLS -> gitService.getBranches
|
||||
@RELATION: CALLS -> GitServiceBranch
|
||||
@RELATION: CALLS -> gitService.createBranch
|
||||
@RELATION: BINDS_TO -> onchange
|
||||
@LAYER Component
|
||||
@RELATION CALLS -> [gitService.getBranches]
|
||||
@RELATION CALLS -> [GitServiceBranch]
|
||||
@RELATION CALLS -> [gitService.createBranch]
|
||||
@RELATION BINDS_TO -> [onchange]
|
||||
-->
|
||||
|
||||
<script>
|
||||
@@ -54,13 +54,13 @@
|
||||
* @post branches обновлен.
|
||||
*/
|
||||
async function loadBranches() {
|
||||
console.log(`[BranchSelector][Action] Loading branches for dashboard ${dashboardId}`);
|
||||
console.log(`[EXT:frontend:BranchSelector][Action] Loading branches for dashboard ${dashboardId}`);
|
||||
loading = true;
|
||||
try {
|
||||
branches = await gitService.getBranches(dashboardId, envId);
|
||||
console.log(`[BranchSelector][Coherence:OK] Loaded ${branches.length} branches`);
|
||||
console.log(`[EXT:frontend:BranchSelector][Coherence:OK] Loaded ${branches.length} branches`);
|
||||
} catch (e) {
|
||||
console.error(`[BranchSelector][Coherence:Failed] ${e.message}`);
|
||||
console.error(`[EXT:frontend:BranchSelector][Coherence:Failed] ${e.message}`);
|
||||
toast($t.git?.load_branches_failed, 'error');
|
||||
} finally {
|
||||
loading = false;
|
||||
@@ -86,15 +86,15 @@
|
||||
* @post currentBranch обновлен, родительский callback вызван.
|
||||
*/
|
||||
async function handleCheckout(branchName) {
|
||||
console.log(`[BranchSelector][Action] Checking out branch ${branchName}`);
|
||||
console.log(`[EXT:frontend:BranchSelector][Action] Checking out branch ${branchName}`);
|
||||
try {
|
||||
await gitService.checkoutBranch(dashboardId, branchName, envId);
|
||||
currentBranch = branchName;
|
||||
onchange({ branch: branchName });
|
||||
toast($t.git?.switched_to?.replace('{branch}', branchName), 'success');
|
||||
console.log(`[BranchSelector][Coherence:OK] Checked out ${branchName}`);
|
||||
console.log(`[EXT:frontend:BranchSelector][Coherence:OK] Checked out ${branchName}`);
|
||||
} catch (e) {
|
||||
console.error(`[BranchSelector][Coherence:Failed] ${e.message}`);
|
||||
console.error(`[EXT:frontend:BranchSelector][Coherence:Failed] ${e.message}`);
|
||||
toast(e.message, 'error');
|
||||
}
|
||||
}
|
||||
@@ -108,16 +108,16 @@
|
||||
*/
|
||||
async function handleCreate() {
|
||||
if (!newBranchName) return;
|
||||
console.log(`[BranchSelector][Action] Creating branch ${newBranchName} from ${currentBranch}`);
|
||||
console.log(`[EXT:frontend:BranchSelector][Action] Creating branch ${newBranchName} from ${currentBranch}`);
|
||||
try {
|
||||
await gitService.createBranch(dashboardId, newBranchName, currentBranch, envId);
|
||||
toast($t.git?.created_branch?.replace('{branch}', newBranchName), 'success');
|
||||
showCreate = false;
|
||||
newBranchName = '';
|
||||
await loadBranches();
|
||||
console.log(`[BranchSelector][Coherence:OK] Branch created`);
|
||||
console.log(`[EXT:frontend:BranchSelector][Coherence:OK] Branch created`);
|
||||
} catch (e) {
|
||||
console.error(`[BranchSelector][Coherence:Failed] ${e.message}`);
|
||||
console.error(`[EXT:frontend:BranchSelector][Coherence:Failed] ${e.message}`);
|
||||
toast(e.message, 'error');
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,8 +4,8 @@
|
||||
<!--
|
||||
@SEMANTICS: git, history, commits, audit
|
||||
@PURPOSE: Displays the commit history for a specific dashboard.
|
||||
@LAYER: Component
|
||||
@RELATION: CALLS -> gitService.getHistory
|
||||
@LAYER Component
|
||||
@RELATION CALLS -> [gitService.getHistory]
|
||||
-->
|
||||
|
||||
<script>
|
||||
|
||||
@@ -6,8 +6,8 @@
|
||||
|
||||
@SEMANTICS: git, commit, modal, version_control, diff
|
||||
@PURPOSE: Модальное окно для создания коммита с просмотром изменений (diff).
|
||||
@LAYER: Component
|
||||
@RELATION: CALLS -> [GitServiceClient]
|
||||
@LAYER Component
|
||||
@RELATION CALLS -> [EXT:frontend:GitServiceClient]
|
||||
@UX_STATE: Ready -> Commit message, status, and diff preview are available for the selected repository.
|
||||
@UX_STATE: Submitting -> Commit actions stay disabled while the commit request is in flight.
|
||||
-->
|
||||
|
||||
@@ -4,8 +4,8 @@
|
||||
<!--
|
||||
@SEMANTICS: git, conflict, resolution, merge
|
||||
@PURPOSE: UI for resolving merge conflicts (Keep Mine / Keep Theirs).
|
||||
@LAYER: Component
|
||||
@RELATION: BINDS_TO -> onresolve
|
||||
@LAYER Component
|
||||
@RELATION BINDS_TO -> [EXT:frontend:onresolve]
|
||||
|
||||
@INVARIANT: User must resolve all conflicts before saving.
|
||||
-->
|
||||
@@ -40,7 +40,7 @@
|
||||
*/
|
||||
function resolve(file, strategy) {
|
||||
console.log(
|
||||
`[ConflictResolver][Action] Resolving ${file} with ${strategy}`,
|
||||
`[EXT:frontend:ConflictResolver][Action] Resolving ${file} with ${strategy}`,
|
||||
);
|
||||
resolutions[file] = strategy;
|
||||
resolutions = { ...resolutions }; // Trigger update
|
||||
@@ -59,7 +59,7 @@
|
||||
const unresolved = conflicts.filter((c) => !resolutions[c.file_path]);
|
||||
if (unresolved.length > 0) {
|
||||
console.warn(
|
||||
`[ConflictResolver][Coherence:Failed] ${unresolved.length} unresolved conflicts`,
|
||||
`[EXT:frontend:ConflictResolver][Coherence:Failed] ${unresolved.length} unresolved conflicts`,
|
||||
);
|
||||
toast(
|
||||
`Please resolve all conflicts first. (${unresolved.length} remaining)`,
|
||||
@@ -69,7 +69,7 @@
|
||||
}
|
||||
|
||||
// 2. Implementation
|
||||
console.log(`[ConflictResolver][Coherence:OK] All conflicts resolved`);
|
||||
console.log(`[EXT:frontend:ConflictResolver][Coherence:OK] All conflicts resolved`);
|
||||
onresolve(resolutions);
|
||||
show = false;
|
||||
}
|
||||
|
||||
@@ -4,9 +4,9 @@
|
||||
<!--
|
||||
@SEMANTICS: deployment, git, environment, modal
|
||||
@PURPOSE: Modal for deploying a dashboard to a target environment.
|
||||
@LAYER: Component
|
||||
@RELATION: CALLS -> GitService
|
||||
@RELATION: DISPATCHES -> deploy
|
||||
@LAYER Component
|
||||
@RELATION CALLS -> [GitService]
|
||||
@RELATION DISPATCHES -> [deploy]
|
||||
|
||||
@INVARIANT: Cannot deploy without a selected environment.
|
||||
-->
|
||||
@@ -82,7 +82,7 @@
|
||||
* @side_effect Updates environments state.
|
||||
*/
|
||||
async function loadEnvironments() {
|
||||
console.log(`[DeploymentModal][Action] Loading environments`);
|
||||
console.log(`[EXT:frontend:DeploymentModal][Action] Loading environments`);
|
||||
loading = true;
|
||||
try {
|
||||
environments = await api.getEnvironmentsList();
|
||||
@@ -94,10 +94,10 @@
|
||||
selectedEnv = (candidates[0]?.id) || "";
|
||||
}
|
||||
console.log(
|
||||
`[DeploymentModal][Coherence:OK] Loaded ${environments.length} environments`,
|
||||
`[EXT:frontend:DeploymentModal][Coherence:OK] Loaded ${environments.length} environments`,
|
||||
);
|
||||
} catch (e) {
|
||||
console.error(`[DeploymentModal][Coherence:Failed] ${e.message}`);
|
||||
console.error(`[EXT:frontend:DeploymentModal][Coherence:Failed] ${e.message}`);
|
||||
toast($t.migration?.loading_envs_failed, "error");
|
||||
} finally {
|
||||
loading = false;
|
||||
@@ -122,7 +122,7 @@
|
||||
return;
|
||||
}
|
||||
}
|
||||
console.log(`[DeploymentModal][Action] Deploying to ${selectedEnv}`);
|
||||
console.log(`[EXT:frontend:DeploymentModal][Action] Deploying to ${selectedEnv}`);
|
||||
deploying = true;
|
||||
try {
|
||||
const result = await gitService.deploy(dashboardId, selectedEnv, envId);
|
||||
@@ -131,9 +131,9 @@
|
||||
"success",
|
||||
);
|
||||
show = false;
|
||||
console.log(`[DeploymentModal][Coherence:OK] Deployment triggered`);
|
||||
console.log(`[EXT:frontend:DeploymentModal][Coherence:OK] Deployment triggered`);
|
||||
} catch (e) {
|
||||
console.error(`[DeploymentModal][Coherence:Failed] ${e.message}`);
|
||||
console.error(`[EXT:frontend:DeploymentModal][Coherence:Failed] ${e.message}`);
|
||||
toast(e.message, "error");
|
||||
} finally {
|
||||
deploying = false;
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
<!-- @BRIEF Git initialization panel: select config, create remote repo, init local repo. -->
|
||||
<!-- @LAYER UI -->
|
||||
<!-- @RELATION DEPENDS_ON -> [GitUtils] -->
|
||||
<!-- @RELATION CALLS -> [gitService] -->
|
||||
<!-- @RELATION CALLS -> [EXT:frontend:gitService] -->
|
||||
<!-- @UX_STATE Idle -> Config selector, remote URL input, create/init buttons. -->
|
||||
<!-- @UX_STATE Loading -> Buttons disabled, spinner visible. -->
|
||||
<script>
|
||||
|
||||
@@ -6,10 +6,10 @@
|
||||
<!-- @RELATION USES -> [GitReleasePanel] -->
|
||||
<!-- @RELATION USES -> [GitOperationsPanel] -->
|
||||
<!-- @RELATION USES -> [GitMergeDialog] -->
|
||||
<!-- @RELATION USES -> [BranchSelector] -->
|
||||
<!-- @RELATION USES -> [DeploymentModal] -->
|
||||
<!-- @RELATION USES -> [ConflictResolver] -->
|
||||
<!-- @RELATION CALLS -> [gitService] -->
|
||||
<!-- @RELATION USES -> [EXT:frontend:BranchSelector] -->
|
||||
<!-- @RELATION USES -> [EXT:frontend:DeploymentModal] -->
|
||||
<!-- @RELATION USES -> [EXT:frontend:ConflictResolver] -->
|
||||
<!-- @RELATION CALLS -> [EXT:frontend:gitService] -->
|
||||
<!-- @RELATION DEPENDS_ON -> [GitUtils] -->
|
||||
<!-- @RELATION DEPENDS_ON -> [UseGitManager] -->
|
||||
<!-- @RATIONALE Decomposed from 1220→~370 lines by extracting sub-panels, utils, and composable handlers per INV_7. -->
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
<!-- @BRIEF Unfinished merge recovery dialog: abort, continue, resolve conflicts. -->
|
||||
<!-- @LAYER UI -->
|
||||
<!-- @RELATION DEPENDS_ON -> [GitUtils] -->
|
||||
<!-- @RELATION CALLS -> [gitService] -->
|
||||
<!-- @RELATION CALLS -> [EXT:frontend:gitService] -->
|
||||
<!-- @UX_STATE Open -> Dialog with merge context, status, and action buttons. -->
|
||||
<!-- @UX_STATE Loading -> Recovery state loading spinner. -->
|
||||
<script>
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
<!-- @BRIEF Git release panel: promote branches via MR or direct mode. -->
|
||||
<!-- @LAYER UI -->
|
||||
<!-- @RELATION DEPENDS_ON -> [GitUtils] -->
|
||||
<!-- @RELATION CALLS -> [gitService] -->
|
||||
<!-- @RELATION CALLS -> [EXT:frontend:gitService] -->
|
||||
<!-- @UX_STATE Idle -> Pipeline status and promote button. -->
|
||||
<!-- @UX_STATE Advanced -> Expandable branch/reason settings. -->
|
||||
<script>
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
<!-- @BRIEF Git workspace panel: sync, commit message input, diff viewer, commit action. -->
|
||||
<!-- @LAYER UI -->
|
||||
<!-- @RELATION DEPENDS_ON -> [GitUtils] -->
|
||||
<!-- @RELATION CALLS -> [gitService] -->
|
||||
<!-- @RELATION CALLS -> [EXT:frontend:gitService] -->
|
||||
<!-- @UX_STATE Idle -> Commit form with diff viewer. -->
|
||||
<!-- @UX_STATE Loading -> GeneratingMessage spinner, workspace loading. -->
|
||||
<!-- @UX_STATE Error -> Toast on failure. -->
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
// #region GitManagerUnfinishedMergeIntegrationTest:Module [TYPE Function]
|
||||
// @SEMANTICS: git-manager, unfinished-merge, dialog, integration-test
|
||||
// @PURPOSE: Protect unresolved-merge dialog contract in GitManager pull flow.
|
||||
// @RELATION: DEPENDS_ON -> [GitManager]
|
||||
// @RELATION DEPENDS_ON -> [GitManager]
|
||||
|
||||
import { describe, it, expect } from 'vitest';
|
||||
import fs from 'node:fs';
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
// #region UseGitManager [C:3] [TYPE Module] [SEMANTICS git, handlers, composable, orchestration]
|
||||
// @BRIEF Composable for GitManager handler functions — extracted to reduce component size per INV_7.
|
||||
// @RELATION DEPENDS_ON -> [gitService]
|
||||
// @RELATION DEPENDS_ON -> [EXT:frontend:gitService]
|
||||
// @RELATION DEPENDS_ON -> [GitUtils]
|
||||
// @RATIONALE Extracted handler logic from GitManager (1220→~350 lines) to meet INV_7 <150 line contract limit.
|
||||
import { gitService } from '../../services/gitService';
|
||||
|
||||
@@ -5,8 +5,8 @@
|
||||
@UX_STATE: Loading -> Default
|
||||
|
||||
@PURPOSE: UI component for previewing generated dataset documentation before saving.
|
||||
@LAYER: UI
|
||||
@RELATION: DEPENDS_ON -> backend/src/plugins/llm_analysis/plugin.py
|
||||
@LAYER UI
|
||||
@RELATION DEPENDS_ON -> [EXT:path:backend/src/plugins/llm_analysis/plugin.py]
|
||||
-->
|
||||
|
||||
<script>
|
||||
|
||||
@@ -5,8 +5,8 @@
|
||||
@UX_STATE: Loading -> Default
|
||||
|
||||
@PURPOSE: UI form for managing LLM provider configurations.
|
||||
@LAYER: UI
|
||||
@RELATION: DEPENDS_ON -> requestApi
|
||||
@LAYER UI
|
||||
@RELATION DEPENDS_ON -> [EXT:frontend:requestApi]
|
||||
-->
|
||||
|
||||
<script>
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
<!-- #region ValidationReport [C:3] [TYPE Component] [SEMANTICS llm, validation, report, issues, dashboard] -->
|
||||
<!-- @BRIEF Displays the results of an LLM-based dashboard validation task with status, issues, and recommendations. -->
|
||||
<!-- @LAYER UI -->
|
||||
<!-- @RELATION DEPENDS_ON -> [DashboardValidationService] -->
|
||||
<!-- @RELATION CALLS -> [api_module] -->
|
||||
<!-- @RELATION DEPENDS_ON -> [EXT:frontend:DashboardValidationService] -->
|
||||
<!-- @RELATION CALLS -> [EXT:frontend:api_module] -->
|
||||
<!-- @PURPOSE: Displays the results of an LLM-based dashboard validation task. -->
|
||||
|
||||
<script>
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
// #region ProviderConfigIntegrationTest [C:3] [TYPE Module] [SEMANTICS llm, provider-config, integration-test, edit-flow, delete-flow]
|
||||
// @PURPOSE: Protect edit, submit, test, and delete interaction contracts in LLM provider settings UI.
|
||||
// @LAYER: UI Tests
|
||||
// @LAYER UI (Tests)
|
||||
// @RELATION DEPENDS_ON -> [ProviderConfig]
|
||||
// @INVARIANT: Edit action keeps explicit click handler and opens normalized edit form.
|
||||
// @INVARIANT: Masked API keys are excluded from save/test/fetch-models payloads.
|
||||
@@ -15,7 +15,7 @@ const COMPONENT_PATH = path.resolve(
|
||||
);
|
||||
|
||||
// #region provider_config_edit_contract_tests:Function [TYPE Function]
|
||||
// @RELATION: BINDS_TO -> [ProviderConfigIntegrationTest]
|
||||
// @RELATION BINDS_TO -> [EXT:frontend:ProviderConfigIntegrationTest]
|
||||
// @PURPOSE: Validate edit and delete handler wiring plus normalized edit form state mapping.
|
||||
// @PRE: ProviderConfig component source exists in expected path.
|
||||
// @POST: Contract checks ensure edit click cannot degrade into no-op flow.
|
||||
|
||||
@@ -6,8 +6,8 @@
|
||||
|
||||
@SEMANTICS: storage, files, list, table
|
||||
@PURPOSE: Displays a table of files with metadata and actions.
|
||||
@LAYER: UI
|
||||
@RELATION: DEPENDS_ON -> storageService
|
||||
@LAYER UI
|
||||
@RELATION DEPENDS_ON -> [storageService]
|
||||
|
||||
@PROPS: files (Array) - List of StoredFile objects.
|
||||
@EVENTS: ondelete/onnavigate callback props - Raised when a file is deleted or navigation is requested.
|
||||
|
||||
@@ -6,8 +6,8 @@
|
||||
|
||||
@SEMANTICS: storage, upload, files
|
||||
@PURPOSE: Provides a form for uploading files to a specific category.
|
||||
@LAYER: UI
|
||||
@RELATION: DEPENDS_ON -> storageService
|
||||
@LAYER UI
|
||||
@RELATION DEPENDS_ON -> [storageService]
|
||||
|
||||
@PROPS: None
|
||||
@EVENTS: onuploaded callback prop - Invoked when a file is successfully uploaded.
|
||||
|
||||
@@ -2,11 +2,11 @@
|
||||
<!-- @BRIEF Component component: components/tasks/LogEntryRow.svelte -->
|
||||
<!-- @LAYER UI -->
|
||||
<!--
|
||||
@RELATION: USES -> App
|
||||
@RELATION USES -> [EXT:frontend:App]
|
||||
|
||||
@SEMANTICS: log, entry, row, ui
|
||||
@PURPOSE: Renders a single log entry with stacked layout optimized for narrow drawer panels.
|
||||
@LAYER: UI
|
||||
@LAYER UI
|
||||
@UX_STATE: Idle -> Displays log entry with color-coded level and source badges.
|
||||
-->
|
||||
<script>
|
||||
|
||||
@@ -2,11 +2,11 @@
|
||||
<!-- @BRIEF Component component: components/tasks/LogFilterBar.svelte -->
|
||||
<!-- @LAYER UI -->
|
||||
<!--
|
||||
@RELATION: USES -> App
|
||||
@RELATION USES -> [EXT:frontend:App]
|
||||
|
||||
@SEMANTICS: log, filter, ui
|
||||
@PURPOSE: Compact filter toolbar for logs — level, source, and text search in a single dense row.
|
||||
@LAYER: UI
|
||||
@LAYER UI
|
||||
@UX_STATE: Idle -> Shows filter controls
|
||||
@UX_STATE: Active -> Filters applied, clear button visible
|
||||
-->
|
||||
|
||||
@@ -4,9 +4,9 @@
|
||||
<!--
|
||||
@SEMANTICS: task, log, panel, filter, list
|
||||
@PURPOSE: Combines log filtering and display into a single cohesive light-themed panel.
|
||||
@LAYER: UI
|
||||
@RELATION: USES -> LogFilterBar
|
||||
@RELATION: USES -> LogEntryRow
|
||||
@LAYER UI
|
||||
@RELATION USES -> [LogFilterBar]
|
||||
@RELATION USES -> [LogEntryRow]
|
||||
@INVARIANT: Must always display logs in chronological order and respect auto-scroll preference.
|
||||
@UX_STATE: Empty -> Displays "No logs" message
|
||||
@UX_STATE: Populated -> Displays list of LogEntryRow components
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<!-- #region TaskResultPanel [C:2] [TYPE Component] [SEMANTICS task, result, summary, status, plugin] -->
|
||||
<!-- @BRIEF Displays formatted task result summary with status badges and result details. -->
|
||||
<!-- @LAYER UI -->
|
||||
<!-- @RELATION DEPENDS_ON -> [i18n] -->
|
||||
<!-- @RELATION DEPENDS_ON -> [EXT:frontend:i18n] -->
|
||||
<!-- @UX_STATE Empty -> No task selected, placeholder shown. -->
|
||||
<!-- @UX_STATE Loaded -> Task result displayed with status color coding. -->
|
||||
<script>
|
||||
|
||||
@@ -4,8 +4,8 @@
|
||||
<!--
|
||||
@SEMANTICS: debug, tool, api, structure
|
||||
@PURPOSE: UI component for system diagnostics and debugging API responses.
|
||||
@LAYER: UI
|
||||
@RELATION: USES -> frontend/src/services/toolsService.js
|
||||
@LAYER UI
|
||||
@RELATION USES -> [EXT:path:frontend/src/services/toolsService.js]
|
||||
-->
|
||||
<script>
|
||||
// [SECTION: IMPORTS]
|
||||
|
||||
@@ -4,8 +4,8 @@
|
||||
<!--
|
||||
@SEMANTICS: mapper, tool, dataset, sqllab, excel
|
||||
@PURPOSE: UI component for mapping dataset column verbose names using Superset SQL Lab or Excel files.
|
||||
@LAYER: UI
|
||||
@RELATION: USES -> frontend/src/services/toolsService.js
|
||||
@LAYER UI
|
||||
@RELATION USES -> [EXT:path:frontend/src/services/toolsService.js]
|
||||
-->
|
||||
<script>
|
||||
// [SECTION: IMPORTS]
|
||||
|
||||
Reference in New Issue
Block a user