project map script | semantic parcer

This commit is contained in:
2026-01-01 16:58:21 +03:00
parent a747a163c8
commit 4c6fc8256d
84 changed files with 10178 additions and 537 deletions

View File

@@ -69,7 +69,7 @@
sortDirection = "asc";
}
}
// [/DEF:handleSort]
// [/DEF:handleSort:Function]
// [DEF:handleSelectionChange:Function]
// @PURPOSE: Handles individual checkbox changes.
@@ -83,7 +83,7 @@
selectedIds = newSelected;
dispatch('selectionChanged', newSelected);
}
// [/DEF:handleSelectionChange]
// [/DEF:handleSelectionChange:Function]
// [DEF:handleSelectAll:Function]
// @PURPOSE: Handles select all checkbox.
@@ -101,7 +101,7 @@
selectedIds = newSelected;
dispatch('selectionChanged', newSelected);
}
// [/DEF:handleSelectAll]
// [/DEF:handleSelectAll:Function]
// [DEF:goToPage:Function]
// @PURPOSE: Changes current page.
@@ -110,7 +110,7 @@
currentPage = page;
}
}
// [/DEF:goToPage]
// [/DEF:goToPage:Function]
</script>
@@ -202,4 +202,4 @@
/* Component styles */
</style>
<!-- [/DEF:DashboardGrid] -->
<!-- [/DEF:DashboardGrid:Component] -->

View File

@@ -28,7 +28,7 @@
console.log("[DynamicForm][Action] Submitting form data.", { formData });
dispatch('submit', formData);
}
// [/DEF:handleSubmit]
// [/DEF:handleSubmit:Function]
// [DEF:initializeForm:Function]
/**
@@ -41,7 +41,7 @@
}
}
}
// [/DEF:initializeForm]
// [/DEF:initializeForm:Function]
initializeForm();
</script>
@@ -85,4 +85,4 @@
</form>
<!-- [/SECTION] -->
<!-- [/DEF:DynamicForm] -->
<!-- [/DEF:DynamicForm:Component] -->

View File

@@ -31,7 +31,7 @@
selectedId = target.value;
dispatch('change', { id: selectedId });
}
// [/DEF:handleSelect]
// [/DEF:handleSelect:Function]
</script>
<!-- [SECTION: TEMPLATE] -->
@@ -55,4 +55,4 @@
/* Component specific styles */
</style>
<!-- [/DEF:EnvSelector] -->
<!-- [/DEF:EnvSelector:Component] -->

View File

@@ -1,3 +1,10 @@
<!-- [DEF:Footer:Component] -->
<!--
@SEMANTICS: footer, layout, copyright
@PURPOSE: Displays the application footer with copyright information.
@LAYER: UI
-->
<footer class="bg-white border-t p-4 mt-8 text-center text-gray-500 text-sm">
&copy; 2025 Superset Tools. All rights reserved.
</footer>
<!-- [/DEF:Footer:Component] -->

View File

@@ -29,7 +29,7 @@
function updateMapping(sourceUuid: string, targetUuid: string) {
dispatch('update', { sourceUuid, targetUuid });
}
// [/DEF:updateMapping]
// [/DEF:updateMapping:Function]
// [DEF:getSuggestion:Function]
/**
@@ -38,7 +38,7 @@
function getSuggestion(sourceUuid: string) {
return suggestions.find(s => s.source_db_uuid === sourceUuid);
}
// [/DEF:getSuggestion]
// [/DEF:getSuggestion:Function]
</script>
<!-- [SECTION: TEMPLATE] -->
@@ -91,4 +91,4 @@
/* Component specific styles */
</style>
<!-- [/DEF:MappingTable] -->
<!-- [/DEF:MappingTable:Component] -->

View File

@@ -24,6 +24,7 @@
const dispatch = createEventDispatcher();
// [DEF:resolve:Function]
// @PURPOSE: Dispatches the resolution event with the selected mapping.
function resolve() {
if (!selectedTargetUuid) return;
dispatch('resolve', {
@@ -33,14 +34,15 @@
});
show = false;
}
// [/DEF:resolve]
// [/DEF:resolve:Function]
// [DEF:cancel:Function]
// @PURPOSE: Cancels the mapping resolution modal.
function cancel() {
dispatch('cancel');
show = false;
}
// [/DEF:cancel]
// [/DEF:cancel:Function]
</script>
<!-- [SECTION: TEMPLATE] -->
@@ -109,4 +111,4 @@
/* Modal specific styles */
</style>
<!-- [/DEF:MissingMappingModal] -->
<!-- [/DEF:MissingMappingModal:Component] -->

View File

@@ -1,3 +1,10 @@
<!-- [DEF:Navbar:Component] -->
<!--
@SEMANTICS: navbar, navigation, header, layout
@PURPOSE: Main navigation bar for the application.
@LAYER: UI
@RELATION: USES -> $app/stores
-->
<script>
import { page } from '$app/stores';
</script>
@@ -36,3 +43,4 @@
</a>
</nav>
</header>
<!-- [/DEF:Navbar:Component] -->

View File

@@ -18,6 +18,8 @@
let passwords = {};
let submitting = false;
// [DEF:handleSubmit:Function]
// @PURPOSE: Validates and dispatches the passwords to resume the task.
function handleSubmit() {
if (submitting) return;
@@ -32,11 +34,15 @@
dispatch('resume', { passwords });
// Reset submitting state is handled by parent or on close
}
// [/DEF:handleSubmit:Function]
// [DEF:handleCancel:Function]
// @PURPOSE: Cancels the password prompt.
function handleCancel() {
dispatch('cancel');
show = false;
}
// [/DEF:handleCancel:Function]
// Reset passwords when modal opens/closes
$: if (!show) {
@@ -120,4 +126,4 @@
</div>
</div>
{/if}
<!-- [/DEF:PasswordPrompt] -->
<!-- [/DEF:PasswordPrompt:Component] -->

View File

@@ -15,6 +15,8 @@
let error = "";
let interval;
// [DEF:fetchTasks:Function]
// @PURPOSE: Fetches the list of recent tasks from the API.
async function fetchTasks() {
try {
const res = await fetch('/api/tasks?limit=10');
@@ -41,7 +43,10 @@
loading = false;
}
}
// [/DEF:fetchTasks:Function]
// [DEF:clearTasks:Function]
// @PURPOSE: Clears tasks from the history, optionally filtered by status.
async function clearTasks(status = null) {
if (!confirm('Are you sure you want to clear tasks?')) return;
try {
@@ -57,7 +62,10 @@
error = e.message;
}
}
// [/DEF:clearTasks:Function]
// [DEF:selectTask:Function]
// @PURPOSE: Selects a task and fetches its full details.
async function selectTask(task) {
try {
// Fetch the full task details (including logs) before setting it as selected
@@ -74,7 +82,10 @@
selectedTask.set(task);
}
}
// [/DEF:selectTask:Function]
// [DEF:getStatusColor:Function]
// @PURPOSE: Returns the CSS color class for a given task status.
function getStatusColor(status) {
switch (status) {
case 'SUCCESS': return 'bg-green-100 text-green-800';
@@ -85,15 +96,22 @@
default: return 'bg-gray-100 text-gray-800';
}
}
// [/DEF:getStatusColor:Function]
// [DEF:onMount:Function]
// @PURPOSE: Initializes the component by fetching tasks and starting polling.
onMount(() => {
fetchTasks();
interval = setInterval(fetchTasks, 5000); // Poll every 5s
});
// [/DEF:onMount:Function]
// [DEF:onDestroy:Function]
// @PURPOSE: Cleans up the polling interval when the component is destroyed.
onDestroy(() => {
clearInterval(interval);
});
// [/DEF:onDestroy:Function]
</script>
<div class="bg-white shadow overflow-hidden sm:rounded-lg mb-8">
@@ -176,4 +194,4 @@
</ul>
{/if}
</div>
<!-- [/DEF:TaskHistory] -->
<!-- [/DEF:TaskHistory:Component] -->

View File

@@ -15,6 +15,8 @@
const dispatch = createEventDispatcher();
// [DEF:getStatusColor:Function]
// @PURPOSE: Returns the CSS color class for a given task status.
function getStatusColor(status: string) {
switch (status) {
case 'SUCCESS': return 'bg-green-100 text-green-800';
@@ -26,7 +28,10 @@
default: return 'bg-gray-100 text-gray-800';
}
}
// [/DEF:getStatusColor:Function]
// [DEF:formatTime:Function]
// @PURPOSE: Formats a date string using date-fns.
function formatTime(dateStr: string | null) {
if (!dateStr) return 'N/A';
try {
@@ -35,10 +40,14 @@
return 'Invalid date';
}
}
// [/DEF:formatTime:Function]
// [DEF:handleTaskClick:Function]
// @PURPOSE: Dispatches a select event when a task is clicked.
function handleTaskClick(taskId: string) {
dispatch('select', { id: taskId });
}
// [/DEF:handleTaskClick:Function]
</script>
<div class="bg-white shadow overflow-hidden sm:rounded-md">
@@ -91,4 +100,4 @@
{/if}
</div>
<!-- [/DEF:TaskList] -->
<!-- [/DEF:TaskList:Component] -->

View File

@@ -22,6 +22,8 @@
let autoScroll = true;
let logContainer;
// [DEF:fetchLogs:Function]
// @PURPOSE: Fetches logs for the current task.
async function fetchLogs() {
if (!taskId) return;
try {
@@ -35,7 +37,10 @@
loading = false;
}
}
// [/DEF:fetchLogs:Function]
// [DEF:scrollToBottom:Function]
// @PURPOSE: Scrolls the log container to the bottom.
function scrollToBottom() {
if (logContainer) {
setTimeout(() => {
@@ -43,7 +48,10 @@
}, 0);
}
}
// [/DEF:scrollToBottom:Function]
// [DEF:handleScroll:Function]
// @PURPOSE: Updates auto-scroll preference based on scroll position.
function handleScroll() {
if (!logContainer) return;
// If user scrolls up, disable auto-scroll
@@ -51,12 +59,18 @@
const atBottom = scrollHeight - scrollTop - clientHeight < 50;
autoScroll = atBottom;
}
// [/DEF:handleScroll:Function]
// [DEF:close:Function]
// @PURPOSE: Closes the log viewer modal.
function close() {
dispatch('close');
show = false;
}
// [/DEF:close:Function]
// [DEF:getLogLevelColor:Function]
// @PURPOSE: Returns the CSS color class for a given log level.
function getLogLevelColor(level) {
switch (level) {
case 'INFO': return 'text-blue-600';
@@ -66,6 +80,7 @@
default: return 'text-gray-800';
}
}
// [/DEF:getLogLevelColor:Function]
// React to changes in show/taskId
$: if (show && taskId) {
@@ -82,9 +97,12 @@
if (interval) clearInterval(interval);
}
// [DEF:onDestroy:Function]
// @PURPOSE: Cleans up the polling interval.
onDestroy(() => {
if (interval) clearInterval(interval);
});
// [/DEF:onDestroy:Function]
</script>
{#if show}
@@ -150,4 +168,4 @@
</div>
</div>
{/if}
<!-- [/DEF:TaskLogViewer] -->
<!-- [/DEF:TaskLogViewer:Component] -->

View File

@@ -127,8 +127,10 @@
}
};
}
// [/DEF:connect]
// [/DEF:connect:Function]
// [DEF:fetchTargetDatabases:Function]
// @PURPOSE: Fetches the list of databases in the target environment.
async function fetchTargetDatabases() {
const task = get(selectedTask);
if (!task || !task.params.to_env) return;
@@ -147,7 +149,10 @@
console.error('Failed to fetch target databases', e);
}
}
// [/DEF:fetchTargetDatabases:Function]
// [DEF:handleMappingResolve:Function]
// @PURPOSE: Handles the resolution of a missing database mapping.
async function handleMappingResolve(event) {
const task = get(selectedTask);
const { sourceDbUuid, targetDbUuid, targetDbName } = event.detail;
@@ -187,7 +192,10 @@
addToast('Failed to resolve mapping: ' + e.message, 'error');
}
}
// [/DEF:handleMappingResolve:Function]
// [DEF:handlePasswordResume:Function]
// @PURPOSE: Handles the submission of database passwords to resume a task.
async function handlePasswordResume(event) {
const task = get(selectedTask);
const { passwords } = event.detail;
@@ -206,7 +214,10 @@
addToast('Failed to resume task: ' + e.message, 'error');
}
}
// [/DEF:handlePasswordResume:Function]
// [DEF:startDataTimeout:Function]
// @PURPOSE: Starts a timeout to detect when the log stream has stalled.
function startDataTimeout() {
waitingForData = false;
dataTimeout = setTimeout(() => {
@@ -215,14 +226,19 @@
}
}, 5000);
}
// [/DEF:startDataTimeout:Function]
// [DEF:resetDataTimeout:Function]
// @PURPOSE: Resets the data stall timeout.
function resetDataTimeout() {
clearTimeout(dataTimeout);
waitingForData = false;
startDataTimeout();
}
// [/DEF:resetDataTimeout:Function]
// [DEF:onMount:Function]
// @PURPOSE: Initializes the component and subscribes to task selection changes.
onMount(() => {
// Subscribe to selectedTask changes
const unsubscribe = selectedTask.subscribe(task => {
@@ -246,7 +262,7 @@
});
return unsubscribe;
});
// [/DEF:onMount]
// [/DEF:onMount:Function]
// [DEF:onDestroy:Function]
/**
@@ -260,7 +276,7 @@
ws.close();
}
});
// [/DEF:onDestroy]
// [/DEF:onDestroy:Function]
</script>
<!-- [SECTION: TEMPLATE] -->
@@ -360,4 +376,4 @@
/>
<!-- [/SECTION] -->
<!-- [/DEF:TaskRunner] -->
<!-- [/DEF:TaskRunner:Component] -->

View File

@@ -28,4 +28,4 @@
</div>
<!-- [/SECTION] -->
<!-- [/DEF:Toast] -->
<!-- [/DEF:Toast:Component] -->