semantic markup update
This commit is contained in:
@@ -24,6 +24,8 @@
|
||||
// [DEF:handleFormSubmit:Function]
|
||||
/**
|
||||
* @purpose Handles form submission for task creation.
|
||||
* @pre event.detail contains form parameters.
|
||||
* @post Task is created and selectedTask is updated.
|
||||
* @param {CustomEvent} event - The submit event from DynamicForm.
|
||||
*/
|
||||
async function handleFormSubmit(event) {
|
||||
@@ -44,6 +46,8 @@
|
||||
// [DEF:navigate:Function]
|
||||
/**
|
||||
* @purpose Changes the current page and resets state.
|
||||
* @pre Target page name is provided.
|
||||
* @post currentPage store is updated and selection state is reset.
|
||||
* @param {string} page - Target page name.
|
||||
*/
|
||||
function navigate(page) {
|
||||
|
||||
@@ -61,6 +61,8 @@
|
||||
|
||||
// [DEF:handleSort:Function]
|
||||
// @PURPOSE: Toggles sort direction or changes sort column.
|
||||
// @PRE: column name is provided.
|
||||
// @POST: sortColumn and sortDirection state updated.
|
||||
function handleSort(column: keyof DashboardMetadata) {
|
||||
if (sortColumn === column) {
|
||||
sortDirection = sortDirection === "asc" ? "desc" : "asc";
|
||||
@@ -73,6 +75,8 @@
|
||||
|
||||
// [DEF:handleSelectionChange:Function]
|
||||
// @PURPOSE: Handles individual checkbox changes.
|
||||
// @PRE: dashboard ID and checked status provided.
|
||||
// @POST: selectedIds array updated and selectionChanged event dispatched.
|
||||
function handleSelectionChange(id: number, checked: boolean) {
|
||||
let newSelected = [...selectedIds];
|
||||
if (checked) {
|
||||
@@ -87,6 +91,8 @@
|
||||
|
||||
// [DEF:handleSelectAll:Function]
|
||||
// @PURPOSE: Handles select all checkbox.
|
||||
// @PRE: checked status provided.
|
||||
// @POST: selectedIds array updated for all paginated items and event dispatched.
|
||||
function handleSelectAll(checked: boolean) {
|
||||
let newSelected = [...selectedIds];
|
||||
if (checked) {
|
||||
@@ -105,6 +111,8 @@
|
||||
|
||||
// [DEF:goToPage:Function]
|
||||
// @PURPOSE: Changes current page.
|
||||
// @PRE: page index is provided.
|
||||
// @POST: currentPage state updated if within valid range.
|
||||
function goToPage(page: number) {
|
||||
if (page >= 0 && page < totalPages) {
|
||||
currentPage = page;
|
||||
|
||||
@@ -23,6 +23,8 @@
|
||||
// [DEF:handleSubmit:Function]
|
||||
/**
|
||||
* @purpose Dispatches the submit event with the form data.
|
||||
* @pre formData contains user input.
|
||||
* @post 'submit' event is dispatched with formData.
|
||||
*/
|
||||
function handleSubmit() {
|
||||
console.log("[DynamicForm][Action] Submitting form data.", { formData });
|
||||
@@ -33,6 +35,8 @@
|
||||
// [DEF:initializeForm:Function]
|
||||
/**
|
||||
* @purpose Initialize form data with default values from the schema.
|
||||
* @pre schema is provided and contains properties.
|
||||
* @post formData is initialized with default values or empty strings.
|
||||
*/
|
||||
function initializeForm() {
|
||||
if (schema && schema.properties) {
|
||||
|
||||
@@ -24,6 +24,8 @@
|
||||
// [DEF:handleSelect:Function]
|
||||
/**
|
||||
* @purpose Dispatches the selection change event.
|
||||
* @pre event.target must be an HTMLSelectElement.
|
||||
* @post selectedId is updated and 'change' event is dispatched.
|
||||
* @param {Event} event - The change event from the select element.
|
||||
*/
|
||||
function handleSelect(event: Event) {
|
||||
|
||||
@@ -25,6 +25,8 @@
|
||||
// [DEF:updateMapping:Function]
|
||||
/**
|
||||
* @purpose Updates a mapping for a specific source database.
|
||||
* @pre sourceUuid and targetUuid are provided.
|
||||
* @post 'update' event is dispatched.
|
||||
*/
|
||||
function updateMapping(sourceUuid: string, targetUuid: string) {
|
||||
dispatch('update', { sourceUuid, targetUuid });
|
||||
@@ -34,6 +36,8 @@
|
||||
// [DEF:getSuggestion:Function]
|
||||
/**
|
||||
* @purpose Finds a suggestion for a source database.
|
||||
* @pre sourceUuid is provided.
|
||||
* @post Returns matching suggestion object or undefined.
|
||||
*/
|
||||
function getSuggestion(sourceUuid: string) {
|
||||
return suggestions.find(s => s.source_db_uuid === sourceUuid);
|
||||
|
||||
@@ -25,6 +25,8 @@
|
||||
|
||||
// [DEF:resolve:Function]
|
||||
// @PURPOSE: Dispatches the resolution event with the selected mapping.
|
||||
// @PRE: selectedTargetUuid must be set.
|
||||
// @POST: 'resolve' event is dispatched and modal is hidden.
|
||||
function resolve() {
|
||||
if (!selectedTargetUuid) return;
|
||||
dispatch('resolve', {
|
||||
@@ -38,6 +40,8 @@
|
||||
|
||||
// [DEF:cancel:Function]
|
||||
// @PURPOSE: Cancels the mapping resolution modal.
|
||||
// @PRE: Modal is open.
|
||||
// @POST: 'cancel' event is dispatched and modal is hidden.
|
||||
function cancel() {
|
||||
dispatch('cancel');
|
||||
show = false;
|
||||
|
||||
@@ -20,6 +20,8 @@
|
||||
|
||||
// [DEF:handleSubmit:Function]
|
||||
// @PURPOSE: Validates and dispatches the passwords to resume the task.
|
||||
// @PRE: All database passwords must be entered.
|
||||
// @POST: 'resume' event is dispatched with passwords.
|
||||
function handleSubmit() {
|
||||
if (submitting) return;
|
||||
|
||||
@@ -38,6 +40,8 @@
|
||||
|
||||
// [DEF:handleCancel:Function]
|
||||
// @PURPOSE: Cancels the password prompt.
|
||||
// @PRE: Modal is open.
|
||||
// @POST: 'cancel' event is dispatched and show is set to false.
|
||||
function handleCancel() {
|
||||
dispatch('cancel');
|
||||
show = false;
|
||||
|
||||
@@ -17,6 +17,8 @@
|
||||
|
||||
// [DEF:fetchTasks:Function]
|
||||
// @PURPOSE: Fetches the list of recent tasks from the API.
|
||||
// @PRE: None.
|
||||
// @POST: tasks array is updated and selectedTask status synchronized.
|
||||
async function fetchTasks() {
|
||||
try {
|
||||
const res = await fetch('/api/tasks?limit=10');
|
||||
@@ -47,6 +49,8 @@
|
||||
|
||||
// [DEF:clearTasks:Function]
|
||||
// @PURPOSE: Clears tasks from the history, optionally filtered by status.
|
||||
// @PRE: User confirms deletion via prompt.
|
||||
// @POST: Tasks are deleted from backend and list is re-fetched.
|
||||
async function clearTasks(status = null) {
|
||||
if (!confirm('Are you sure you want to clear tasks?')) return;
|
||||
try {
|
||||
@@ -66,6 +70,8 @@
|
||||
|
||||
// [DEF:selectTask:Function]
|
||||
// @PURPOSE: Selects a task and fetches its full details.
|
||||
// @PRE: task object is provided.
|
||||
// @POST: selectedTask store is updated with full task details.
|
||||
async function selectTask(task) {
|
||||
try {
|
||||
// Fetch the full task details (including logs) before setting it as selected
|
||||
@@ -86,6 +92,8 @@
|
||||
|
||||
// [DEF:getStatusColor:Function]
|
||||
// @PURPOSE: Returns the CSS color class for a given task status.
|
||||
// @PRE: status string is provided.
|
||||
// @POST: Returns tailwind color class string.
|
||||
function getStatusColor(status) {
|
||||
switch (status) {
|
||||
case 'SUCCESS': return 'bg-green-100 text-green-800';
|
||||
@@ -100,6 +108,8 @@
|
||||
|
||||
// [DEF:onMount:Function]
|
||||
// @PURPOSE: Initializes the component by fetching tasks and starting polling.
|
||||
// @PRE: Component is mounting.
|
||||
// @POST: Tasks are fetched and 5s polling interval is started.
|
||||
onMount(() => {
|
||||
fetchTasks();
|
||||
interval = setInterval(fetchTasks, 5000); // Poll every 5s
|
||||
@@ -108,6 +118,8 @@
|
||||
|
||||
// [DEF:onDestroy:Function]
|
||||
// @PURPOSE: Cleans up the polling interval when the component is destroyed.
|
||||
// @PRE: Component is being destroyed.
|
||||
// @POST: Polling interval is cleared.
|
||||
onDestroy(() => {
|
||||
clearInterval(interval);
|
||||
});
|
||||
|
||||
@@ -17,6 +17,8 @@
|
||||
|
||||
// [DEF:getStatusColor:Function]
|
||||
// @PURPOSE: Returns the CSS color class for a given task status.
|
||||
// @PRE: status string is provided.
|
||||
// @POST: Returns tailwind color class string.
|
||||
function getStatusColor(status: string) {
|
||||
switch (status) {
|
||||
case 'SUCCESS': return 'bg-green-100 text-green-800';
|
||||
@@ -32,6 +34,8 @@
|
||||
|
||||
// [DEF:formatTime:Function]
|
||||
// @PURPOSE: Formats a date string using date-fns.
|
||||
// @PRE: dateStr is a valid date string or null.
|
||||
// @POST: Returns human-readable relative time string.
|
||||
function formatTime(dateStr: string | null) {
|
||||
if (!dateStr) return 'N/A';
|
||||
try {
|
||||
@@ -44,6 +48,8 @@
|
||||
|
||||
// [DEF:handleTaskClick:Function]
|
||||
// @PURPOSE: Dispatches a select event when a task is clicked.
|
||||
// @PRE: taskId is provided.
|
||||
// @POST: 'select' event is dispatched with task ID.
|
||||
function handleTaskClick(taskId: string) {
|
||||
dispatch('select', { id: taskId });
|
||||
}
|
||||
|
||||
@@ -24,6 +24,8 @@
|
||||
|
||||
// [DEF:fetchLogs:Function]
|
||||
// @PURPOSE: Fetches logs for the current task.
|
||||
// @PRE: taskId must be set.
|
||||
// @POST: logs array is updated with data from taskService.
|
||||
async function fetchLogs() {
|
||||
if (!taskId) return;
|
||||
try {
|
||||
@@ -41,6 +43,8 @@
|
||||
|
||||
// [DEF:scrollToBottom:Function]
|
||||
// @PURPOSE: Scrolls the log container to the bottom.
|
||||
// @PRE: logContainer element must be bound.
|
||||
// @POST: logContainer scrollTop is set to scrollHeight.
|
||||
function scrollToBottom() {
|
||||
if (logContainer) {
|
||||
setTimeout(() => {
|
||||
@@ -52,6 +56,8 @@
|
||||
|
||||
// [DEF:handleScroll:Function]
|
||||
// @PURPOSE: Updates auto-scroll preference based on scroll position.
|
||||
// @PRE: logContainer scroll event fired.
|
||||
// @POST: autoScroll boolean is updated.
|
||||
function handleScroll() {
|
||||
if (!logContainer) return;
|
||||
// If user scrolls up, disable auto-scroll
|
||||
@@ -63,6 +69,8 @@
|
||||
|
||||
// [DEF:close:Function]
|
||||
// @PURPOSE: Closes the log viewer modal.
|
||||
// @PRE: Modal is open.
|
||||
// @POST: Modal is closed and close event is dispatched.
|
||||
function close() {
|
||||
dispatch('close');
|
||||
show = false;
|
||||
@@ -71,6 +79,8 @@
|
||||
|
||||
// [DEF:getLogLevelColor:Function]
|
||||
// @PURPOSE: Returns the CSS color class for a given log level.
|
||||
// @PRE: level string is provided.
|
||||
// @POST: Returns tailwind color class string.
|
||||
function getLogLevelColor(level) {
|
||||
switch (level) {
|
||||
case 'INFO': return 'text-blue-600';
|
||||
@@ -99,6 +109,8 @@
|
||||
|
||||
// [DEF:onDestroy:Function]
|
||||
// @PURPOSE: Cleans up the polling interval.
|
||||
// @PRE: Component is being destroyed.
|
||||
// @POST: Polling interval is cleared.
|
||||
onDestroy(() => {
|
||||
if (interval) clearInterval(interval);
|
||||
});
|
||||
|
||||
@@ -38,6 +38,8 @@
|
||||
// [DEF:connect:Function]
|
||||
/**
|
||||
* @purpose Establishes WebSocket connection with exponential backoff.
|
||||
* @pre selectedTask must be set in the store.
|
||||
* @post WebSocket instance created and listeners attached.
|
||||
*/
|
||||
function connect() {
|
||||
const task = get(selectedTask);
|
||||
@@ -131,6 +133,8 @@
|
||||
|
||||
// [DEF:fetchTargetDatabases:Function]
|
||||
// @PURPOSE: Fetches the list of databases in the target environment.
|
||||
// @PRE: task must be selected and have a target environment parameter.
|
||||
// @POST: targetDatabases array is populated with database objects.
|
||||
async function fetchTargetDatabases() {
|
||||
const task = get(selectedTask);
|
||||
if (!task || !task.params.to_env) return;
|
||||
@@ -153,6 +157,8 @@
|
||||
|
||||
// [DEF:handleMappingResolve:Function]
|
||||
// @PURPOSE: Handles the resolution of a missing database mapping.
|
||||
// @PRE: event.detail contains sourceDbUuid, targetDbUuid, and targetDbName.
|
||||
// @POST: Mapping is saved and task is resumed.
|
||||
async function handleMappingResolve(event) {
|
||||
const task = get(selectedTask);
|
||||
const { sourceDbUuid, targetDbUuid, targetDbName } = event.detail;
|
||||
@@ -196,6 +202,8 @@
|
||||
|
||||
// [DEF:handlePasswordResume:Function]
|
||||
// @PURPOSE: Handles the submission of database passwords to resume a task.
|
||||
// @PRE: event.detail contains passwords dictionary.
|
||||
// @POST: Task resume endpoint is called with passwords.
|
||||
async function handlePasswordResume(event) {
|
||||
const task = get(selectedTask);
|
||||
const { passwords } = event.detail;
|
||||
@@ -218,6 +226,8 @@
|
||||
|
||||
// [DEF:startDataTimeout:Function]
|
||||
// @PURPOSE: Starts a timeout to detect when the log stream has stalled.
|
||||
// @PRE: None.
|
||||
// @POST: dataTimeout is set to check connection status after 5s.
|
||||
function startDataTimeout() {
|
||||
waitingForData = false;
|
||||
dataTimeout = setTimeout(() => {
|
||||
@@ -230,6 +240,8 @@
|
||||
|
||||
// [DEF:resetDataTimeout:Function]
|
||||
// @PURPOSE: Resets the data stall timeout.
|
||||
// @PRE: dataTimeout must be active.
|
||||
// @POST: dataTimeout is cleared and restarted.
|
||||
function resetDataTimeout() {
|
||||
clearTimeout(dataTimeout);
|
||||
waitingForData = false;
|
||||
@@ -239,6 +251,8 @@
|
||||
|
||||
// [DEF:onMount:Function]
|
||||
// @PURPOSE: Initializes the component and subscribes to task selection changes.
|
||||
// @PRE: Svelte component is mounting.
|
||||
// @POST: Store subscription is created and returned for cleanup.
|
||||
onMount(() => {
|
||||
// Subscribe to selectedTask changes
|
||||
const unsubscribe = selectedTask.subscribe(task => {
|
||||
@@ -267,6 +281,8 @@
|
||||
// [DEF:onDestroy:Function]
|
||||
/**
|
||||
* @purpose Close WebSocket connection when the component is destroyed.
|
||||
* @pre Component is being destroyed.
|
||||
* @post WebSocket is closed and timeouts are cleared.
|
||||
*/
|
||||
onDestroy(() => {
|
||||
clearTimeout(reconnectTimeout);
|
||||
|
||||
@@ -25,6 +25,8 @@
|
||||
|
||||
// [DEF:handleSubmit:Function]
|
||||
// @PURPOSE: Submits the connection form to the backend.
|
||||
// @PRE: All required fields (name, host, database, username, password) must be filled.
|
||||
// @POST: A new connection is created via the connection service and a success event is dispatched.
|
||||
async function handleSubmit() {
|
||||
if (!name || !host || !database || !username || !password) {
|
||||
addToast('Please fill in all required fields', 'warning');
|
||||
@@ -47,6 +49,11 @@
|
||||
}
|
||||
// [/DEF:handleSubmit:Function]
|
||||
|
||||
// [DEF:resetForm:Function]
|
||||
/* @PURPOSE: Resets the connection form fields to their default values.
|
||||
@PRE: None.
|
||||
@POST: All form input variables are reset.
|
||||
*/
|
||||
function resetForm() {
|
||||
name = '';
|
||||
host = '';
|
||||
@@ -55,6 +62,7 @@
|
||||
username = '';
|
||||
password = '';
|
||||
}
|
||||
// [/DEF:resetForm:Function]
|
||||
</script>
|
||||
|
||||
<!-- [SECTION: TEMPLATE] -->
|
||||
|
||||
@@ -19,6 +19,8 @@
|
||||
|
||||
// [DEF:fetchConnections:Function]
|
||||
// @PURPOSE: Fetches the list of connections from the backend.
|
||||
// @PRE: None.
|
||||
// @POST: connections array is populated.
|
||||
async function fetchConnections() {
|
||||
isLoading = true;
|
||||
try {
|
||||
@@ -33,6 +35,8 @@
|
||||
|
||||
// [DEF:handleDelete:Function]
|
||||
// @PURPOSE: Deletes a connection configuration.
|
||||
// @PRE: id is provided and user confirms deletion.
|
||||
// @POST: Connection is deleted from backend and list is reloaded.
|
||||
async function handleDelete(id) {
|
||||
if (!confirm('Are you sure you want to delete this connection?')) return;
|
||||
|
||||
|
||||
@@ -28,6 +28,8 @@
|
||||
|
||||
// [DEF:fetchData:Function]
|
||||
// @PURPOSE: Fetches environments and saved connections.
|
||||
// @PRE: None.
|
||||
// @POST: envs and connections arrays are populated.
|
||||
async function fetchData() {
|
||||
try {
|
||||
const envsRes = await fetch('/api/environments');
|
||||
@@ -41,6 +43,8 @@
|
||||
|
||||
// [DEF:handleRunMapper:Function]
|
||||
// @PURPOSE: Triggers the MapperPlugin task.
|
||||
// @PRE: selectedEnv and datasetId are set; source-specific fields are valid.
|
||||
// @POST: Mapper task is started and selectedTask is updated.
|
||||
async function handleRunMapper() {
|
||||
if (!selectedEnv || !datasetId) {
|
||||
addToast('Please fill in required fields', 'warning');
|
||||
|
||||
@@ -22,6 +22,8 @@
|
||||
|
||||
// [DEF:fetchEnvironments:Function]
|
||||
// @PURPOSE: Fetches the list of available environments.
|
||||
// @PRE: None.
|
||||
// @POST: envs array is populated.
|
||||
async function fetchEnvironments() {
|
||||
try {
|
||||
const res = await fetch('/api/environments');
|
||||
@@ -34,6 +36,8 @@
|
||||
|
||||
// [DEF:handleSearch:Function]
|
||||
// @PURPOSE: Triggers the SearchPlugin task.
|
||||
// @PRE: selectedEnv and searchQuery must be set.
|
||||
// @POST: Task is started and polling begins.
|
||||
async function handleSearch() {
|
||||
if (!selectedEnv || !searchQuery) {
|
||||
addToast('Please select environment and enter query', 'warning');
|
||||
@@ -61,6 +65,8 @@
|
||||
|
||||
// [DEF:startPolling:Function]
|
||||
// @PURPOSE: Polls for task completion and results.
|
||||
// @PRE: taskId is provided.
|
||||
// @POST: pollInterval is set and results are updated on success.
|
||||
function startPolling(taskId) {
|
||||
if (pollInterval) clearInterval(pollInterval);
|
||||
|
||||
|
||||
@@ -10,6 +10,8 @@ const API_BASE_URL = '/api';
|
||||
|
||||
// [DEF:getWsUrl:Function]
|
||||
// @PURPOSE: Returns the WebSocket URL for a specific task, with fallback logic.
|
||||
// @PRE: taskId is provided.
|
||||
// @POST: Returns valid WebSocket URL string.
|
||||
// @PARAM: taskId (string) - The ID of the task.
|
||||
// @RETURN: string - The WebSocket URL.
|
||||
export const getWsUrl = (taskId) => {
|
||||
@@ -25,6 +27,8 @@ export const getWsUrl = (taskId) => {
|
||||
|
||||
// [DEF:fetchApi:Function]
|
||||
// @PURPOSE: Generic GET request wrapper.
|
||||
// @PRE: endpoint string is provided.
|
||||
// @POST: Returns Promise resolving to JSON data or throws on error.
|
||||
// @PARAM: endpoint (string) - API endpoint.
|
||||
// @RETURN: Promise<any> - JSON response.
|
||||
async function fetchApi(endpoint) {
|
||||
@@ -45,6 +49,8 @@ async function fetchApi(endpoint) {
|
||||
|
||||
// [DEF:postApi:Function]
|
||||
// @PURPOSE: Generic POST request wrapper.
|
||||
// @PRE: endpoint and body are provided.
|
||||
// @POST: Returns Promise resolving to JSON data or throws on error.
|
||||
// @PARAM: endpoint (string) - API endpoint.
|
||||
// @PARAM: body (object) - Request payload.
|
||||
// @RETURN: Promise<any> - JSON response.
|
||||
@@ -72,6 +78,8 @@ async function postApi(endpoint, body) {
|
||||
|
||||
// [DEF:requestApi:Function]
|
||||
// @PURPOSE: Generic request wrapper.
|
||||
// @PRE: endpoint and method are provided.
|
||||
// @POST: Returns Promise resolving to JSON data or throws on error.
|
||||
async function requestApi(endpoint, method = 'GET', body = null) {
|
||||
try {
|
||||
console.log(`[api.requestApi][Action] ${method} to context={{'endpoint': '${endpoint}'}}`);
|
||||
|
||||
@@ -38,6 +38,8 @@ export const taskLogs = writable([]);
|
||||
|
||||
// [DEF:fetchPlugins:Function]
|
||||
// @PURPOSE: Fetches plugins from the API and updates the plugins store.
|
||||
// @PRE: None.
|
||||
// @POST: plugins store is updated with data from the API.
|
||||
export async function fetchPlugins() {
|
||||
try {
|
||||
console.log("[stores.fetchPlugins][Action] Fetching plugins.");
|
||||
@@ -52,6 +54,8 @@ export async function fetchPlugins() {
|
||||
|
||||
// [DEF:fetchTasks:Function]
|
||||
// @PURPOSE: Fetches tasks from the API and updates the tasks store.
|
||||
// @PRE: None.
|
||||
// @POST: tasks store is updated with data from the API.
|
||||
export async function fetchTasks() {
|
||||
try {
|
||||
console.log("[stores.fetchTasks][Action] Fetching tasks.");
|
||||
|
||||
@@ -12,6 +12,8 @@ export const toasts = writable([]);
|
||||
|
||||
// [DEF:addToast:Function]
|
||||
// @PURPOSE: Adds a new toast message.
|
||||
// @PRE: message string is provided.
|
||||
// @POST: New toast is added to the store and scheduled for removal.
|
||||
// @PARAM: message (string) - The message text.
|
||||
// @PARAM: type (string) - The type of toast (info, success, error).
|
||||
// @PARAM: duration (number) - Duration in ms before the toast is removed.
|
||||
@@ -25,6 +27,8 @@ export function addToast(message, type = 'info', duration = 3000) {
|
||||
|
||||
// [DEF:removeToast:Function]
|
||||
// @PURPOSE: Removes a toast message by ID.
|
||||
// @PRE: id is provided.
|
||||
// @POST: Toast is removed from the store.
|
||||
// @PARAM: id (string) - The ID of the toast to remove.
|
||||
function removeToast(id) {
|
||||
console.log(`[toasts.removeToast][Action] Removing toast context={{'id': '${id}'}}`);
|
||||
|
||||
@@ -17,6 +17,8 @@
|
||||
// [DEF:onMount:Function]
|
||||
/**
|
||||
* @purpose Fetch plugins when the component mounts.
|
||||
* @pre Component is mounting.
|
||||
* @post plugins store is populated with available tools.
|
||||
*/
|
||||
onMount(async () => {
|
||||
console.log("[Dashboard][Entry] Component mounted, fetching plugins.");
|
||||
@@ -27,6 +29,8 @@
|
||||
// [DEF:selectPlugin:Function]
|
||||
/**
|
||||
* @purpose Selects a plugin to display its form.
|
||||
* @pre plugin object is provided.
|
||||
* @post selectedPlugin store is updated.
|
||||
* @param {Object} plugin - The plugin object to select.
|
||||
*/
|
||||
function selectPlugin(plugin) {
|
||||
|
||||
@@ -50,6 +50,8 @@
|
||||
// [DEF:loadSettings:Function]
|
||||
/**
|
||||
* @purpose Loads settings from the backend.
|
||||
* @pre Component mounted or refresh requested.
|
||||
* @post settings object is populated with backend data.
|
||||
*/
|
||||
async function loadSettings() {
|
||||
try {
|
||||
@@ -67,6 +69,8 @@
|
||||
// [DEF:handleSaveGlobal:Function]
|
||||
/**
|
||||
* @purpose Saves global settings to the backend.
|
||||
* @pre settings.settings contains valid configuration.
|
||||
* @post Backend global settings are updated.
|
||||
*/
|
||||
async function handleSaveGlobal() {
|
||||
try {
|
||||
@@ -84,6 +88,8 @@
|
||||
// [DEF:handleAddOrUpdateEnv:Function]
|
||||
/**
|
||||
* @purpose Adds or updates an environment.
|
||||
* @pre newEnv contains valid environment details.
|
||||
* @post Environment list is updated on backend and reloaded locally.
|
||||
*/
|
||||
async function handleAddOrUpdateEnv() {
|
||||
try {
|
||||
@@ -108,6 +114,8 @@
|
||||
// [DEF:handleDeleteEnv:Function]
|
||||
/**
|
||||
* @purpose Deletes an environment.
|
||||
* @pre id of environment to delete is provided.
|
||||
* @post Environment is removed from backend and list is reloaded.
|
||||
* @param {string} id - The ID of the environment to delete.
|
||||
*/
|
||||
async function handleDeleteEnv(id) {
|
||||
@@ -129,6 +137,8 @@
|
||||
// [DEF:handleTestEnv:Function]
|
||||
/**
|
||||
* @purpose Tests the connection to an environment.
|
||||
* @pre Environment ID is valid.
|
||||
* @post Connection test result is displayed via toast.
|
||||
* @param {string} id - The ID of the environment to test.
|
||||
*/
|
||||
async function handleTestEnv(id) {
|
||||
@@ -152,6 +162,8 @@
|
||||
// [DEF:editEnv:Function]
|
||||
/**
|
||||
* @purpose Sets the form to edit an existing environment.
|
||||
* @pre env object is provided.
|
||||
* @post newEnv is populated with env data and editingEnvId is set.
|
||||
* @param {Object} env - The environment object to edit.
|
||||
*/
|
||||
function editEnv(env) {
|
||||
@@ -163,6 +175,8 @@
|
||||
// [DEF:resetEnvForm:Function]
|
||||
/**
|
||||
* @purpose Resets the environment form.
|
||||
* @pre None.
|
||||
* @post newEnv is reset to initial state and editingEnvId is cleared.
|
||||
*/
|
||||
function resetEnvForm() {
|
||||
newEnv = {
|
||||
|
||||
@@ -14,6 +14,11 @@
|
||||
pluginsStore.set(data.plugins);
|
||||
}
|
||||
|
||||
// [DEF:selectPlugin:Function]
|
||||
/* @PURPOSE: Handles plugin selection and navigation.
|
||||
@PRE: plugin object must be provided.
|
||||
@POST: Navigates to migration or sets selectedPlugin store.
|
||||
*/
|
||||
function selectPlugin(plugin) {
|
||||
console.log(`[Dashboard][Action] Selecting plugin: ${plugin.id}`);
|
||||
if (plugin.id === 'superset-migration') {
|
||||
@@ -22,7 +27,13 @@
|
||||
selectedPlugin.set(plugin);
|
||||
}
|
||||
}
|
||||
// [/DEF:selectPlugin:Function]
|
||||
|
||||
// [DEF:handleFormSubmit:Function]
|
||||
/* @PURPOSE: Handles task creation from dynamic form submission.
|
||||
@PRE: event.detail must contain task parameters.
|
||||
@POST: Task is created via API and selectedTask store is updated.
|
||||
*/
|
||||
async function handleFormSubmit(event) {
|
||||
console.log("[App.handleFormSubmit][Action] Handling form submission for task creation.");
|
||||
const params = event.detail;
|
||||
@@ -36,6 +47,7 @@
|
||||
console.error(`[App.handleFormSubmit][Coherence:Failed] Task creation failed error=${error}`);
|
||||
}
|
||||
}
|
||||
// [/DEF:handleFormSubmit:Function]
|
||||
</script>
|
||||
|
||||
<div class="container mx-auto p-4">
|
||||
|
||||
@@ -1,5 +1,10 @@
|
||||
import { api } from '../lib/api';
|
||||
|
||||
// [DEF:load:Function]
|
||||
/* @PURPOSE: Loads initial plugin data for the dashboard.
|
||||
@PRE: None.
|
||||
@POST: Returns an object with plugins or an error message.
|
||||
*/
|
||||
/** @type {import('./$types').PageLoad} */
|
||||
export async function load() {
|
||||
try {
|
||||
@@ -15,3 +20,4 @@ export async function load() {
|
||||
};
|
||||
}
|
||||
}
|
||||
// [/DEF:load:Function]
|
||||
|
||||
@@ -51,6 +51,7 @@
|
||||
// [DEF:fetchEnvironments:Function]
|
||||
/**
|
||||
* @purpose Fetches the list of environments from the API.
|
||||
* @pre None.
|
||||
* @post environments state is updated.
|
||||
*/
|
||||
async function fetchEnvironments() {
|
||||
@@ -69,6 +70,7 @@
|
||||
// [DEF:fetchDashboards:Function]
|
||||
/**
|
||||
* @purpose Fetches dashboards for the selected source environment.
|
||||
* @pre envId is a valid environment ID.
|
||||
* @param envId The environment ID.
|
||||
* @post dashboards state is updated.
|
||||
*/
|
||||
@@ -93,6 +95,8 @@
|
||||
// [DEF:fetchDatabases:Function]
|
||||
/**
|
||||
* @purpose Fetches databases from both environments and gets suggestions.
|
||||
* @pre sourceEnvId and targetEnvId must be set.
|
||||
* @post sourceDatabases, targetDatabases, mappings, and suggestions are updated.
|
||||
*/
|
||||
async function fetchDatabases() {
|
||||
if (!sourceEnvId || !targetEnvId) return;
|
||||
@@ -128,6 +132,8 @@
|
||||
// [DEF:handleMappingUpdate:Function]
|
||||
/**
|
||||
* @purpose Saves a mapping to the backend.
|
||||
* @pre event.detail contains sourceUuid and targetUuid.
|
||||
* @post Mapping is saved and local mappings list is updated.
|
||||
*/
|
||||
async function handleMappingUpdate(event: CustomEvent) {
|
||||
const { sourceUuid, targetUuid } = event.detail;
|
||||
@@ -162,6 +168,8 @@
|
||||
|
||||
// [DEF:handleViewLogs:Function]
|
||||
// @PURPOSE: Opens the log viewer for a specific task.
|
||||
// @PRE: event.detail contains task object.
|
||||
// @POST: logViewer state updated and showLogViewer set to true.
|
||||
function handleViewLogs(event: CustomEvent) {
|
||||
const task = event.detail;
|
||||
logViewerTaskId = task.id;
|
||||
@@ -172,6 +180,8 @@
|
||||
|
||||
// [DEF:handlePasswordPrompt:Function]
|
||||
// @PURPOSE: Reactive logic to show password prompt when a task is awaiting input.
|
||||
// @PRE: selectedTask status is AWAITING_INPUT.
|
||||
// @POST: showPasswordPrompt set to true with request data.
|
||||
// This is triggered by TaskRunner or TaskHistory when a task needs input
|
||||
// For now, we rely on the WebSocket or manual check.
|
||||
// Ideally, TaskHistory or TaskRunner emits an event when input is needed.
|
||||
@@ -194,6 +204,8 @@
|
||||
|
||||
// [DEF:handleResumeMigration:Function]
|
||||
// @PURPOSE: Resumes a migration task with provided passwords.
|
||||
// @PRE: event.detail contains passwords.
|
||||
// @POST: resumeTask is called and showPasswordPrompt is hidden on success.
|
||||
async function handleResumeMigration(event: CustomEvent) {
|
||||
if (!$selectedTask) return;
|
||||
|
||||
@@ -214,6 +226,7 @@
|
||||
/**
|
||||
* @purpose Starts the migration process.
|
||||
* @pre sourceEnvId and targetEnvId must be set and different.
|
||||
* @post Migration task is started and selectedTask is updated.
|
||||
*/
|
||||
async function startMigration() {
|
||||
if (!sourceEnvId || !targetEnvId) {
|
||||
|
||||
@@ -32,6 +32,8 @@
|
||||
|
||||
// [DEF:fetchEnvironments:Function]
|
||||
// @PURPOSE: Fetches the list of environments.
|
||||
// @PRE: None.
|
||||
// @POST: environments array is populated.
|
||||
async function fetchEnvironments() {
|
||||
try {
|
||||
const response = await fetch('/api/environments');
|
||||
@@ -50,6 +52,8 @@
|
||||
// [DEF:fetchDatabases:Function]
|
||||
/**
|
||||
* @purpose Fetches databases from both environments and gets suggestions.
|
||||
* @pre sourceEnvId and targetEnvId must be set.
|
||||
* @post sourceDatabases, targetDatabases, mappings, and suggestions are updated.
|
||||
*/
|
||||
async function fetchDatabases() {
|
||||
if (!sourceEnvId || !targetEnvId) return;
|
||||
@@ -86,6 +90,8 @@
|
||||
// [DEF:handleUpdate:Function]
|
||||
/**
|
||||
* @purpose Saves a mapping to the backend.
|
||||
* @pre event.detail contains sourceUuid and targetUuid.
|
||||
* @post Mapping is saved and local mappings list is updated.
|
||||
*/
|
||||
async function handleUpdate(event: CustomEvent) {
|
||||
const { sourceUuid, targetUuid } = event.detail;
|
||||
|
||||
@@ -21,6 +21,11 @@
|
||||
|
||||
let editingEnvId = null;
|
||||
|
||||
// [DEF:handleSaveGlobal:Function]
|
||||
/* @PURPOSE: Saves global application settings.
|
||||
@PRE: settings.settings must contain valid configuration.
|
||||
@POST: Global settings are updated via API.
|
||||
*/
|
||||
async function handleSaveGlobal() {
|
||||
try {
|
||||
console.log("[Settings.handleSaveGlobal][Action] Saving global settings.");
|
||||
@@ -32,7 +37,13 @@
|
||||
addToast('Failed to save global settings', 'error');
|
||||
}
|
||||
}
|
||||
// [/DEF:handleSaveGlobal:Function]
|
||||
|
||||
// [DEF:handleAddOrUpdateEnv:Function]
|
||||
/* @PURPOSE: Adds a new environment or updates an existing one.
|
||||
@PRE: newEnv must contain valid environment details.
|
||||
@POST: Environment is saved and page is reloaded to reflect changes.
|
||||
*/
|
||||
async function handleAddOrUpdateEnv() {
|
||||
try {
|
||||
console.log(`[Settings.handleAddOrUpdateEnv][Action] ${editingEnvId ? 'Updating' : 'Adding'} environment.`);
|
||||
@@ -54,7 +65,13 @@
|
||||
addToast('Failed to save environment', 'error');
|
||||
}
|
||||
}
|
||||
// [/DEF:handleAddOrUpdateEnv:Function]
|
||||
|
||||
// [DEF:handleDeleteEnv:Function]
|
||||
/* @PURPOSE: Deletes a Superset environment.
|
||||
@PRE: id must be a valid environment ID.
|
||||
@POST: Environment is removed and page is reloaded.
|
||||
*/
|
||||
async function handleDeleteEnv(id) {
|
||||
if (confirm('Are you sure you want to delete this environment?')) {
|
||||
try {
|
||||
@@ -69,7 +86,13 @@
|
||||
}
|
||||
}
|
||||
}
|
||||
// [/DEF:handleDeleteEnv:Function]
|
||||
|
||||
// [DEF:handleTestEnv:Function]
|
||||
/* @PURPOSE: Tests the connection to a Superset environment.
|
||||
@PRE: id must be a valid environment ID.
|
||||
@POST: Displays success or error toast based on connection result.
|
||||
*/
|
||||
async function handleTestEnv(id) {
|
||||
try {
|
||||
console.log(`[Settings.handleTestEnv][Action] Testing environment: ${id}`);
|
||||
@@ -86,12 +109,24 @@
|
||||
addToast('Failed to test connection', 'error');
|
||||
}
|
||||
}
|
||||
// [/DEF:handleTestEnv:Function]
|
||||
|
||||
// [DEF:editEnv:Function]
|
||||
/* @PURPOSE: Populates the environment form for editing.
|
||||
@PRE: env object must be provided.
|
||||
@POST: newEnv and editingEnvId are updated.
|
||||
*/
|
||||
function editEnv(env) {
|
||||
newEnv = { ...env };
|
||||
editingEnvId = env.id;
|
||||
}
|
||||
// [/DEF:editEnv:Function]
|
||||
|
||||
// [DEF:resetEnvForm:Function]
|
||||
/* @PURPOSE: Resets the environment creation/edit form to default state.
|
||||
@PRE: None.
|
||||
@POST: newEnv is cleared and editingEnvId is set to null.
|
||||
*/
|
||||
function resetEnvForm() {
|
||||
newEnv = {
|
||||
id: '',
|
||||
@@ -103,6 +138,7 @@
|
||||
};
|
||||
editingEnvId = null;
|
||||
}
|
||||
// [/DEF:resetEnvForm:Function]
|
||||
</script>
|
||||
|
||||
<div class="container mx-auto p-4">
|
||||
|
||||
@@ -1,5 +1,10 @@
|
||||
import { api } from '../../lib/api';
|
||||
|
||||
// [DEF:load:Function]
|
||||
/* @PURPOSE: Loads application settings and environment list.
|
||||
@PRE: API must be reachable.
|
||||
@POST: Returns settings object or default values on error.
|
||||
*/
|
||||
/** @type {import('./$types').PageLoad} */
|
||||
export async function load() {
|
||||
try {
|
||||
@@ -21,3 +26,4 @@ export async function load() {
|
||||
};
|
||||
}
|
||||
}
|
||||
// [/DEF:load:Function]
|
||||
|
||||
@@ -10,11 +10,17 @@
|
||||
|
||||
let listComponent;
|
||||
|
||||
// [DEF:handleSuccess:Function]
|
||||
/* @PURPOSE: Refreshes the connection list after a successful creation.
|
||||
@PRE: listComponent must be bound.
|
||||
@POST: Triggers the fetchConnections method on the list component.
|
||||
*/
|
||||
function handleSuccess() {
|
||||
if (listComponent) {
|
||||
listComponent.fetchConnections();
|
||||
}
|
||||
}
|
||||
// [/DEF:handleSuccess:Function]
|
||||
</script>
|
||||
|
||||
<div class="max-w-7xl mx-auto py-6 sm:px-6 lg:px-8">
|
||||
|
||||
@@ -13,6 +13,11 @@
|
||||
let showBackupModal = false;
|
||||
let selectedEnvId = '';
|
||||
|
||||
// [DEF:loadInitialData:Function]
|
||||
/* @PURPOSE: Loads tasks and environments on page initialization.
|
||||
@PRE: API must be reachable.
|
||||
@POST: tasks and environments variables are populated.
|
||||
*/
|
||||
async function loadInitialData() {
|
||||
try {
|
||||
loading = true;
|
||||
@@ -28,7 +33,13 @@
|
||||
loading = false;
|
||||
}
|
||||
}
|
||||
// [/DEF:loadInitialData:Function]
|
||||
|
||||
// [DEF:refreshTasks:Function]
|
||||
/* @PURPOSE: Periodically refreshes the task list.
|
||||
@PRE: API must be reachable.
|
||||
@POST: tasks variable is updated if data is valid.
|
||||
*/
|
||||
async function refreshTasks() {
|
||||
try {
|
||||
const data = await getTasks();
|
||||
@@ -40,11 +51,23 @@
|
||||
console.error('Failed to refresh tasks:', error);
|
||||
}
|
||||
}
|
||||
// [/DEF:refreshTasks:Function]
|
||||
|
||||
// [DEF:handleSelectTask:Function]
|
||||
/* @PURPOSE: Updates the selected task ID when a task is clicked.
|
||||
@PRE: event.detail.id must be provided.
|
||||
@POST: selectedTaskId is updated.
|
||||
*/
|
||||
function handleSelectTask(event) {
|
||||
selectedTaskId = event.detail.id;
|
||||
}
|
||||
// [/DEF:handleSelectTask:Function]
|
||||
|
||||
// [DEF:handleRunBackup:Function]
|
||||
/* @PURPOSE: Triggers a manual backup task for the selected environment.
|
||||
@PRE: selectedEnvId must not be empty.
|
||||
@POST: Backup task is created and task list is refreshed.
|
||||
*/
|
||||
async function handleRunBackup() {
|
||||
if (!selectedEnvId) {
|
||||
addToast('Please select an environment', 'error');
|
||||
@@ -61,6 +84,7 @@
|
||||
console.error('Failed to start backup:', error);
|
||||
}
|
||||
}
|
||||
// [/DEF:handleRunBackup:Function]
|
||||
|
||||
onMount(() => {
|
||||
loadInitialData();
|
||||
|
||||
@@ -4,6 +4,11 @@
|
||||
|
||||
const API_BASE = '/api/settings/connections';
|
||||
|
||||
// [DEF:getConnections:Function]
|
||||
/* @PURPOSE: Fetch a list of saved connections.
|
||||
@PRE: None.
|
||||
@POST: Returns a promise resolving to an array of connections.
|
||||
*/
|
||||
/**
|
||||
* Fetch a list of saved connections.
|
||||
* @returns {Promise<Array>} List of connections.
|
||||
@@ -15,7 +20,13 @@ export async function getConnections() {
|
||||
}
|
||||
return await response.json();
|
||||
}
|
||||
// [/DEF:getConnections:Function]
|
||||
|
||||
// [DEF:createConnection:Function]
|
||||
/* @PURPOSE: Create a new connection configuration.
|
||||
@PRE: connectionData must be a valid object.
|
||||
@POST: Returns a promise resolving to the created connection.
|
||||
*/
|
||||
/**
|
||||
* Create a new connection configuration.
|
||||
* @param {Object} connectionData - The connection data.
|
||||
@@ -36,7 +47,13 @@ export async function createConnection(connectionData) {
|
||||
}
|
||||
return await response.json();
|
||||
}
|
||||
// [/DEF:createConnection:Function]
|
||||
|
||||
// [DEF:deleteConnection:Function]
|
||||
/* @PURPOSE: Delete a connection configuration.
|
||||
@PRE: connectionId must be a valid string.
|
||||
@POST: Returns a promise that resolves when deletion is complete.
|
||||
*/
|
||||
/**
|
||||
* Delete a connection configuration.
|
||||
* @param {string} connectionId - The ID of the connection to delete.
|
||||
@@ -49,4 +66,5 @@ export async function deleteConnection(connectionId) {
|
||||
if (!response.ok) {
|
||||
throw new Error(`Failed to delete connection: ${response.statusText}`);
|
||||
}
|
||||
}
|
||||
}
|
||||
// [/DEF:deleteConnection:Function]
|
||||
@@ -4,6 +4,11 @@
|
||||
|
||||
const API_BASE = '/api/tasks';
|
||||
|
||||
// [DEF:getTasks:Function]
|
||||
/* @PURPOSE: Fetch a list of tasks with pagination and optional status filter.
|
||||
@PRE: limit and offset are numbers.
|
||||
@POST: Returns a promise resolving to a list of tasks.
|
||||
*/
|
||||
/**
|
||||
* Fetch a list of tasks with pagination and optional status filter.
|
||||
* @param {number} limit - Maximum number of tasks to return.
|
||||
@@ -26,7 +31,13 @@ export async function getTasks(limit = 10, offset = 0, status = null) {
|
||||
}
|
||||
return await response.json();
|
||||
}
|
||||
// [/DEF:getTasks:Function]
|
||||
|
||||
// [DEF:getTask:Function]
|
||||
/* @PURPOSE: Fetch details for a specific task.
|
||||
@PRE: taskId must be provided.
|
||||
@POST: Returns a promise resolving to task details.
|
||||
*/
|
||||
/**
|
||||
* Fetch details for a specific task.
|
||||
* @param {string} taskId - The ID of the task.
|
||||
@@ -39,7 +50,13 @@ export async function getTask(taskId) {
|
||||
}
|
||||
return await response.json();
|
||||
}
|
||||
// [/DEF:getTask:Function]
|
||||
|
||||
// [DEF:getTaskLogs:Function]
|
||||
/* @PURPOSE: Fetch logs for a specific task.
|
||||
@PRE: taskId must be provided.
|
||||
@POST: Returns a promise resolving to a list of log entries.
|
||||
*/
|
||||
/**
|
||||
* Fetch logs for a specific task.
|
||||
* @param {string} taskId - The ID of the task.
|
||||
@@ -55,7 +72,13 @@ export async function getTaskLogs(taskId) {
|
||||
const task = await getTask(taskId);
|
||||
return task.logs || [];
|
||||
}
|
||||
// [/DEF:getTaskLogs:Function]
|
||||
|
||||
// [DEF:resumeTask:Function]
|
||||
/* @PURPOSE: Resume a task that is awaiting input (e.g., passwords).
|
||||
@PRE: taskId and passwords must be provided.
|
||||
@POST: Returns a promise resolving to the updated task object.
|
||||
*/
|
||||
/**
|
||||
* Resume a task that is awaiting input (e.g., passwords).
|
||||
* @param {string} taskId - The ID of the task.
|
||||
@@ -77,7 +100,13 @@ export async function resumeTask(taskId, passwords) {
|
||||
}
|
||||
return await response.json();
|
||||
}
|
||||
// [/DEF:resumeTask:Function]
|
||||
|
||||
// [DEF:resolveTask:Function]
|
||||
/* @PURPOSE: Resolve a task that is awaiting mapping.
|
||||
@PRE: taskId and resolutionParams must be provided.
|
||||
@POST: Returns a promise resolving to the updated task object.
|
||||
*/
|
||||
/**
|
||||
* Resolve a task that is awaiting mapping.
|
||||
* @param {string} taskId - The ID of the task.
|
||||
@@ -99,7 +128,13 @@ export async function resolveTask(taskId, resolutionParams) {
|
||||
}
|
||||
return await response.json();
|
||||
}
|
||||
// [/DEF:resolveTask:Function]
|
||||
|
||||
// [DEF:clearTasks:Function]
|
||||
/* @PURPOSE: Clear tasks based on status.
|
||||
@PRE: status is a string or null.
|
||||
@POST: Returns a promise that resolves when tasks are cleared.
|
||||
*/
|
||||
/**
|
||||
* Clear tasks based on status.
|
||||
* @param {string|null} status - Filter by task status (optional).
|
||||
@@ -117,4 +152,5 @@ export async function clearTasks(status = null) {
|
||||
if (!response.ok) {
|
||||
throw new Error(`Failed to clear tasks: ${response.statusText}`);
|
||||
}
|
||||
}
|
||||
}
|
||||
// [/DEF:clearTasks:Function]
|
||||
@@ -4,6 +4,11 @@
|
||||
|
||||
const API_BASE = '/api/tasks';
|
||||
|
||||
// [DEF:runTask:Function]
|
||||
/* @PURPOSE: Start a new task for a given plugin.
|
||||
@PRE: pluginId and params must be provided.
|
||||
@POST: Returns a promise resolving to the task instance.
|
||||
*/
|
||||
/**
|
||||
* Start a new task for a given plugin.
|
||||
* @param {string} pluginId - The ID of the plugin to run.
|
||||
@@ -25,7 +30,13 @@ export async function runTask(pluginId, params) {
|
||||
}
|
||||
return await response.json();
|
||||
}
|
||||
// [/DEF:runTask:Function]
|
||||
|
||||
// [DEF:getTaskStatus:Function]
|
||||
/* @PURPOSE: Fetch details for a specific task (to poll status or get result).
|
||||
@PRE: taskId must be provided.
|
||||
@POST: Returns a promise resolving to task details.
|
||||
*/
|
||||
/**
|
||||
* Fetch details for a specific task (to poll status or get result).
|
||||
* @param {string} taskId - The ID of the task.
|
||||
@@ -37,4 +48,5 @@ export async function getTaskStatus(taskId) {
|
||||
throw new Error(`Failed to fetch task ${taskId}: ${response.statusText}`);
|
||||
}
|
||||
return await response.json();
|
||||
}
|
||||
}
|
||||
// [/DEF:getTaskStatus:Function]
|
||||
Reference in New Issue
Block a user