progress indicator in exports

This commit is contained in:
SPRINX0\prochazka
2025-03-04 13:55:36 +01:00
parent 4006f03444
commit 0c104d5d29
8 changed files with 87 additions and 12 deletions

View File

@@ -107,6 +107,10 @@ module.exports = {
} }
}, },
handle_progress(runid, { progressName, status }) {
socket.emit(`runner-progress-${runid}`, { progressName, status });
},
rejectRequest(runid, error) { rejectRequest(runid, error) {
if (this.requests[runid]) { if (this.requests[runid]) {
const { reject } = this.requests[runid]; const { reject } = this.requests[runid];

View File

@@ -10,7 +10,15 @@ const streamPipeline = require('../utility/streamPipeline');
* @returns {Promise} * @returns {Promise}
*/ */
async function copyStream(input, output, options) { async function copyStream(input, output, options) {
const { columns } = options || {}; const { columns, progressName } = options || {};
if (progressName) {
process.send({
msgtype: 'progress',
progressName,
status: 'running',
});
}
const transforms = []; const transforms = [];
if (columns) { if (columns) {
@@ -22,6 +30,14 @@ async function copyStream(input, output, options) {
try { try {
await streamPipeline(input, transforms, output); await streamPipeline(input, transforms, output);
if (progressName) {
process.send({
msgtype: 'progress',
progressName,
status: 'done',
});
}
} catch (err) { } catch (err) {
process.send({ process.send({
msgtype: 'copyStreamError', msgtype: 'copyStreamError',
@@ -30,6 +46,15 @@ async function copyStream(input, output, options) {
...err, ...err,
}, },
}); });
if (progressName) {
process.send({
msgtype: 'progress',
progressName,
status: 'error',
});
}
throw err; throw err;
} }
} }

View File

@@ -41,12 +41,13 @@ export class ScriptWriter {
this.packageNames.push(packageName); this.packageNames.push(packageName);
} }
copyStream(sourceVar, targetVar, colmapVar = null) { copyStream(sourceVar, targetVar, colmapVar = null, progressName?: string) {
if (colmapVar) { let opts = '{';
this._put(`await dbgateApi.copyStream(${sourceVar}, ${targetVar}, {columns: ${colmapVar}});`); if (colmapVar) opts += `columns: ${colmapVar}, `;
} else { if (progressName) opts += `progressName: "${progressName}", `;
this._put(`await dbgateApi.copyStream(${sourceVar}, ${targetVar});`); opts += '}';
}
this._put(`await dbgateApi.copyStream(${sourceVar}, ${targetVar}, ${opts});`);
} }
dumpDatabase(options) { dumpDatabase(options) {
@@ -117,12 +118,13 @@ export class ScriptWriterJson {
}); });
} }
copyStream(sourceVar, targetVar, colmapVar = null) { copyStream(sourceVar, targetVar, colmapVar = null, progressName?: string) {
this.commands.push({ this.commands.push({
type: 'copyStream', type: 'copyStream',
sourceVar, sourceVar,
targetVar, targetVar,
colmapVar, colmapVar,
progressName,
}); });
} }
@@ -183,7 +185,7 @@ export function jsonScriptToJavascript(json) {
script.assignValue(cmd.variableName, cmd.jsonValue); script.assignValue(cmd.variableName, cmd.jsonValue);
break; break;
case 'copyStream': case 'copyStream':
script.copyStream(cmd.sourceVar, cmd.targetVar, cmd.colmapVar); script.copyStream(cmd.sourceVar, cmd.targetVar, cmd.colmapVar, cmd.progressName);
break; break;
case 'endLine': case 'endLine':
script.endLine(); script.endLine();

View File

@@ -20,7 +20,7 @@
import { createEventDispatcher } from 'svelte'; import { createEventDispatcher } from 'svelte';
import FontIcon from '../icons/FontIcon.svelte'; import FontIcon from '../icons/FontIcon.svelte';
export let columns: TableControlColumn[]; export let columns: (TableControlColumn | false)[];
export let rows; export let rows;
export let focusOnCreate = false; export let focusOnCreate = false;
export let selectable = false; export let selectable = false;

View File

@@ -149,6 +149,7 @@
'icon download': 'mdi mdi-download', 'icon download': 'mdi mdi-download',
'icon text': 'mdi mdi-text', 'icon text': 'mdi mdi-text',
'icon ai': 'mdi mdi-head-lightbulb', 'icon ai': 'mdi mdi-head-lightbulb',
'icon wait': 'mdi mdi-timer-sand',
'icon run': 'mdi mdi-play', 'icon run': 'mdi mdi-play',
'icon chevron-down': 'mdi mdi-chevron-down', 'icon chevron-down': 'mdi mdi-chevron-down',

View File

@@ -104,6 +104,7 @@
$: sourceList = $values.sourceList; $: sourceList = $values.sourceList;
let targetEditKey = 0; let targetEditKey = 0;
export let progressHolder = null;
const previewSource = writable(null); const previewSource = writable(null);
@@ -231,11 +232,16 @@
header: 'Target', header: 'Target',
slot: 1, slot: 1,
}, },
{ supportsPreview && {
fieldName: 'preview', fieldName: 'preview',
header: 'Preview', header: 'Preview',
slot: 0, slot: 0,
}, },
!!progressHolder && {
fieldName: 'status',
header: 'Status',
slot: 3,
},
{ {
fieldName: 'columns', fieldName: 'columns',
header: 'Columns', header: 'Columns',
@@ -296,6 +302,17 @@
>{columnCount > 0 ? `(${columnCount} columns)` : '(copy from source)'} >{columnCount > 0 ? `(${columnCount} columns)` : '(copy from source)'}
</Link> </Link>
</svelte:fragment> </svelte:fragment>
<svelte:fragment slot="3" let:row>
{#if progressHolder[row]?.status == 'running'}
<FontIcon icon="icon loading" /> Running
{:else if progressHolder[row]?.status == 'error'}
<FontIcon icon="img error" /> Error
{:else if progressHolder[row]?.status == 'done'}
<FontIcon icon="img ok" /> Done
{:else}
<FontIcon icon="icon wait" /> Queued
{/if}
</svelte:fragment>
</TableControl> </TableControl>
{/key} {/key}
</div> </div>

View File

@@ -233,7 +233,7 @@ export default async function createImpExpScript(extensions, values, forceScript
script.assignValue(colmapVar, colmap); script.assignValue(colmapVar, colmap);
} }
script.copyStream(sourceVar, targetVar, colmapVar); script.copyStream(sourceVar, targetVar, colmapVar, sourceName);
script.endLine(); script.endLine();
} }
return script.getScript(values.schedule); return script.getScript(values.schedule);

View File

@@ -65,6 +65,7 @@
export let savedFile; export let savedFile;
export let savedFilePath; export let savedFilePath;
let progressHolder = null;
const refreshArchiveFolderRef = createRef(null); const refreshArchiveFolderRef = createRef(null);
const formValues = writable({}); const formValues = writable({});
@@ -179,6 +180,7 @@
const handleExecute = async e => { const handleExecute = async e => {
if (busy) return; if (busy) return;
progressHolder = {};
const values = $formValues as any; const values = $formValues as any;
busy = true; busy = true;
const script = await createImpExpScript($extensions, values); const script = await createImpExpScript($extensions, values);
@@ -228,6 +230,29 @@
title: `${getSourceTargetTitle('source', values)}->${getSourceTargetTitle('target', values)}(${values.sourceList?.length || 0})`, title: `${getSourceTargetTitle('source', values)}->${getSourceTargetTitle('target', values)}(${values.sourceList?.length || 0})`,
})); }));
} }
const handleProgress = progress => {
progressHolder = {
...progressHolder,
[progress.progressName]: {
...progressHolder[progress.progressName],
...progress,
},
};
};
$: progressEffect = useEffect(() => {
if (runnerId) {
const eventName = `runner-progress-${runnerId}`;
apiOn(eventName, handleProgress);
return () => {
apiOff(eventName, handleProgress);
};
}
return () => {};
});
$progressEffect;
</script> </script>
<ToolStripContainer> <ToolStripContainer>
@@ -237,6 +262,7 @@
<ImportExportConfigurator <ImportExportConfigurator
bind:this={domConfigurator} bind:this={domConfigurator}
{previewReaderStore} {previewReaderStore}
{progressHolder}
isTabActive={tabid == $activeTabId} isTabActive={tabid == $activeTabId}
/> />