Add export parameters to ResultTabs and QueryTab components

This commit is contained in:
Stela Augustinova
2026-04-13 13:16:17 +02:00
parent 22967d123d
commit 07fae27ad6
3 changed files with 273 additions and 219 deletions
+245 -215
View File
@@ -1,217 +1,247 @@
<script context="module" lang="ts">
import { __t } from '../translations';
const getCurrentEditor = () => getActiveComponent('JslDataGridCore');
registerCommand({
id: 'jslTableGrid.export',
category: __t('command.dataGrid', { defaultMessage: 'Data grid' }),
name: __t('command.dataGrid.export', { defaultMessage: 'Export' }),
icon: 'icon export',
keyText: 'CtrlOrCommand+E',
testEnabled: () => getCurrentEditor() != null,
onClick: () => getCurrentEditor().exportGrid(),
});
async function loadDataPage(props, offset, limit) {
const { jslid, display, formatterFunction } = props;
const response = await apiCall('jsldata/get-rows', {
jslid,
offset,
limit,
formatterFunction,
filters: display ? display.compileJslFilters() : null,
sort: display.config.sort,
});
return response;
}
function dataPageAvailable(props) {
return true;
}
async function loadRowCount(props) {
const { jslid } = props;
const response = await apiCall('jsldata/get-stats', { jslid });
return response.rowCount;
}
export let formatterPlugin;
export let formatterFunction;
</script>
<script lang="ts">
import _ from 'lodash';
import { registerQuickExportHandler } from '../buttons/ToolStripExportButton.svelte';
import registerCommand from '../commands/registerCommand';
import { apiCall, apiOff, apiOn } from '../utility/api';
import { registerMenu } from '../utility/contextMenu';
import createActivator, { getActiveComponent } from '../utility/createActivator';
import createQuickExportMenu from '../utility/createQuickExportMenu';
import { exportQuickExportFile } from '../utility/exportFileTools';
import useEffect from '../utility/useEffect';
import ChangeSetGrider from './ChangeSetGrider';
import LoadingDataGridCore from './LoadingDataGridCore.svelte';
import { openImportExportTab } from '../utility/importExportTools';
export let jslid;
export let display;
export let formatterFunction;
export let changeSetState;
export let dispatchChangeSet;
export let macroPreview;
export let macroValues;
export let onPublishedCellsChanged;
export const activator = createActivator('JslDataGridCore', false);
export let setLoadedRows;
let publishedCells = [];
let loadedRows = [];
let domGrid;
let changeIndex = 0;
let rowCountLoaded = null;
const throttleLoadNext = _.throttle(() => domGrid?.resetLoadedAll(), 500);
const handleJslDataStats = stats => {
if (stats.changeIndex < changeIndex) return;
changeIndex = stats.changeIndex;
rowCountLoaded = stats.rowCount;
throttleLoadNext();
};
$: effect = useEffect(() => onJslId(jslid));
function onJslId(jslidVal) {
if (jslidVal) {
apiOn(`jsldata-stats-${jslidVal}`, handleJslDataStats);
return () => {
apiOff(`jsldata-stats-${jslidVal}`, handleJslDataStats);
};
} else {
return () => {};
}
}
$: $effect;
let grider;
$: {
if (macroPreview) {
grider = new ChangeSetGrider(
loadedRows,
changeSetState,
dispatchChangeSet,
display,
macroPreview,
macroValues,
publishedCells,
true
);
}
}
$: {
if (!macroPreview) {
grider = new ChangeSetGrider(
loadedRows,
changeSetState,
dispatchChangeSet,
display,
undefined,
undefined,
undefined,
true
);
}
}
// $: grider = new RowsArrayGrider(loadedRows);
export function exportGrid() {
const initialValues = {} as any;
const archiveMatch = jslid.match(/^archive:\/\/([^/]+)\/(.*)$/);
if (archiveMatch) {
initialValues.sourceStorageType = 'archive';
initialValues.sourceArchiveFolder = archiveMatch[1];
initialValues.sourceList = [archiveMatch[2]];
initialValues[`columns_${archiveMatch[2]}`] = display.getExportColumnMap();
} else {
initialValues.sourceStorageType = 'jsldata';
initialValues.sourceJslId = jslid;
initialValues.sourceList = ['query-data'];
initialValues[`columns_query-data`] = display.getExportColumnMap();
}
openImportExportTab(initialValues);
// showModal(ImportExportModal, { initialValues });
}
const quickExportHandler = fmt => async () => {
const archiveMatch = jslid.match(/^archive:\/\/([^/]+)\/(.*)$/);
if (archiveMatch) {
exportQuickExportFile(
archiveMatch[2],
{
functionName: 'archiveReader',
props: {
folderName: archiveMatch[1],
fileName: archiveMatch[2],
},
},
fmt,
display.getExportColumnMap()
);
} else {
exportQuickExportFile(
'Query',
{
functionName: 'jslDataReader',
props: {
jslid,
},
},
fmt,
display.getExportColumnMap()
);
}
};
registerQuickExportHandler(quickExportHandler);
registerMenu(() =>
createQuickExportMenu(
quickExportHandler,
{
command: 'jslTableGrid.export',
},
{ tag: 'export' }
)
);
function handleSetLoadedRows(rows) {
loadedRows = rows;
setLoadedRows?.(rows);
}
</script>
<LoadingDataGridCore
bind:this={domGrid}
{...$$props}
setLoadedRows={handleSetLoadedRows}
onPublishedCellsChanged={value => {
publishedCells = value;
if (onPublishedCellsChanged) {
onPublishedCellsChanged(value);
}
}}
{loadDataPage}
{dataPageAvailable}
{loadRowCount}
{grider}
{rowCountLoaded}
const getCurrentEditor = () => getActiveComponent('JslDataGridCore');
registerCommand({
id: 'jslTableGrid.export',
category: __t('command.dataGrid', { defaultMessage: 'Data grid' }),
name: __t('command.dataGrid.export', { defaultMessage: 'Export' }),
icon: 'icon export',
keyText: 'CtrlOrCommand+E',
testEnabled: () => getCurrentEditor() != null,
onClick: () => getCurrentEditor().exportGrid(),
});
async function loadDataPage(props, offset, limit) {
const { jslid, display, formatterFunction } = props;
const response = await apiCall('jsldata/get-rows', {
jslid,
offset,
limit,
formatterFunction,
filters: display ? display.compileJslFilters() : null,
sort: display.config.sort,
});
return response;
}
function dataPageAvailable(props) {
return true;
}
async function loadRowCount(props) {
const { jslid } = props;
const response = await apiCall('jsldata/get-stats', { jslid });
return response.rowCount;
}
export let formatterPlugin;
export let formatterFunction;
</script>
<script lang="ts">
import _ from 'lodash';
import { registerQuickExportHandler } from '../buttons/ToolStripExportButton.svelte';
import registerCommand from '../commands/registerCommand';
import { apiCall, apiOff, apiOn } from '../utility/api';
import { registerMenu } from '../utility/contextMenu';
import createActivator, { getActiveComponent } from '../utility/createActivator';
import createQuickExportMenu from '../utility/createQuickExportMenu';
import { exportQuickExportFile } from '../utility/exportFileTools';
import { extractShellConnectionHostable, extractShellHostConnection } from '../impexp/createImpExpScript';
import { getConnectionInfo } from '../utility/metadataLoaders';
import useEffect from '../utility/useEffect';
import ChangeSetGrider from './ChangeSetGrider';
import LoadingDataGridCore from './LoadingDataGridCore.svelte';
import { openImportExportTab } from '../utility/importExportTools';
export let jslid;
export let display;
export let formatterFunction;
export let changeSetState;
export let dispatchChangeSet;
export let macroPreview;
export let macroValues;
export let onPublishedCellsChanged;
export let exportQuery = null;
export let exportConid = null;
export let exportDatabase = null;
export const activator = createActivator('JslDataGridCore', false);
export let setLoadedRows;
let publishedCells = [];
let loadedRows = [];
let domGrid;
let changeIndex = 0;
let rowCountLoaded = null;
const throttleLoadNext = _.throttle(() => domGrid?.resetLoadedAll(), 500);
const handleJslDataStats = stats => {
if (stats.changeIndex < changeIndex) return;
changeIndex = stats.changeIndex;
rowCountLoaded = stats.rowCount;
throttleLoadNext();
};
$: effect = useEffect(() => onJslId(jslid));
function onJslId(jslidVal) {
if (jslidVal) {
apiOn(`jsldata-stats-${jslidVal}`, handleJslDataStats);
return () => {
apiOff(`jsldata-stats-${jslidVal}`, handleJslDataStats);
};
} else {
return () => {};
}
}
$: $effect;
let grider;
$: {
if (macroPreview) {
grider = new ChangeSetGrider(
loadedRows,
changeSetState,
dispatchChangeSet,
display,
macroPreview,
macroValues,
publishedCells,
true
);
}
}
$: {
if (!macroPreview) {
grider = new ChangeSetGrider(
loadedRows,
changeSetState,
dispatchChangeSet,
display,
undefined,
undefined,
undefined,
true
);
}
}
// $: grider = new RowsArrayGrider(loadedRows);
export async function exportGrid() {
const initialValues = {} as any;
const archiveMatch = jslid.match(/^archive:\/\/([^/]+)\/(.*)$/);
if (archiveMatch) {
initialValues.sourceStorageType = 'archive';
initialValues.sourceArchiveFolder = archiveMatch[1];
initialValues.sourceList = [archiveMatch[2]];
initialValues[`columns_${archiveMatch[2]}`] = display.getExportColumnMap();
} else if (exportQuery && exportConid) {
initialValues.sourceStorageType = 'query';
initialValues.sourceConnectionId = exportConid;
initialValues.sourceDatabaseName = exportDatabase;
initialValues.sourceQuery = exportQuery;
initialValues.sourceQueryType = 'native';
initialValues.sourceList = ['query-data'];
initialValues[`columns_query-data`] = display.getExportColumnMap();
} else {
initialValues.sourceStorageType = 'jsldata';
initialValues.sourceJslId = jslid;
initialValues.sourceList = ['query-data'];
initialValues[`columns_query-data`] = display.getExportColumnMap();
}
openImportExportTab(initialValues);
// showModal(ImportExportModal, { initialValues });
}
const quickExportHandler = fmt => async () => {
const archiveMatch = jslid.match(/^archive:\/\/([^/]+)\/(.*)$/);
if (archiveMatch) {
exportQuickExportFile(
archiveMatch[2],
{
functionName: 'archiveReader',
props: {
folderName: archiveMatch[1],
fileName: archiveMatch[2],
},
},
fmt,
display.getExportColumnMap()
);
} else if (exportQuery && exportConid) {
const coninfo = await getConnectionInfo({ conid: exportConid });
exportQuickExportFile(
'Query',
{
functionName: 'queryReader',
props: {
...extractShellConnectionHostable(coninfo, exportDatabase),
queryType: 'native',
query: exportQuery,
},
hostConnection: extractShellHostConnection(coninfo, exportDatabase),
},
fmt,
display.getExportColumnMap()
);
} else {
exportQuickExportFile(
'Query',
{
functionName: 'jslDataReader',
props: {
jslid,
},
},
fmt,
display.getExportColumnMap()
);
}
};
registerQuickExportHandler(quickExportHandler);
registerMenu(() =>
createQuickExportMenu(
quickExportHandler,
{
command: 'jslTableGrid.export',
},
{ tag: 'export' }
)
);
function handleSetLoadedRows(rows) {
loadedRows = rows;
setLoadedRows?.(rows);
}
</script>
<LoadingDataGridCore
bind:this={domGrid}
{...$$props}
setLoadedRows={handleSetLoadedRows}
onPublishedCellsChanged={value => {
publishedCells = value;
if (onPublishedCellsChanged) {
onPublishedCellsChanged(value);
}
}}
{loadDataPage}
{dataPageAvailable}
{loadRowCount}
{grider}
{rowCountLoaded}
/>
+23 -4
View File
@@ -21,6 +21,9 @@
export let resultCount;
export let onSetFrontMatterField;
export let onGetFrontMatter;
export let exportConid = null;
export let exportDatabase = null;
export let exportQuery = null;
onMount(() => {
allResultsInOneTab = $allResultsInOneTabDefault;
@@ -82,10 +85,20 @@
isResult: true,
component: JslDataGrid,
resultIndex: info.resultIndex,
props: { jslid: info.jslid, driver, onOpenChart: () => handleOpenChart(info.resultIndex) },
props: {
jslid: info.jslid,
driver,
onOpenChart: () => handleOpenChart(info.resultIndex),
exportConid,
exportDatabase,
exportQuery,
},
}))),
...charts.map((info, index) => ({
label: _t('resultTabs.chartNumber', { defaultMessage: 'Chart {number}', values: { number: info.resultIndex + 1 } }),
label: _t('resultTabs.chartNumber', {
defaultMessage: 'Chart {number}',
values: { number: info.resultIndex + 1 },
}),
isChart: true,
resultIndex: info.resultIndex,
component: JslChart,
@@ -175,8 +188,14 @@
tabs={allTabs}
menu={resultInfos.length > 0 && [
oneTab
? { text: _t('resultTabs.everyResultInSingleTab', { defaultMessage: 'Every result in single tab' }), onClick: () => setOneTabValue(false) }
: { text: _t('resultTabs.allResultsInOneTab', { defaultMessage: 'All results in one tab' }), onClick: () => setOneTabValue(true) },
? {
text: _t('resultTabs.everyResultInSingleTab', { defaultMessage: 'Every result in single tab' }),
onClick: () => setOneTabValue(false),
}
: {
text: _t('resultTabs.allResultsInOneTab', { defaultMessage: 'All results in one tab' }),
onClick: () => setOneTabValue(true),
},
]}
onUserChange={value => {
if (allTabs[value].isChart) {
+5
View File
@@ -232,6 +232,7 @@
let splitterInitialValue = undefined;
let autoDetectCharts = false;
let domResultTabs;
let lastExecutedSql = null;
const queryRowsLimitLocalStorageKey = `tabdata_limitRows_${tabid}`;
function getInitialRowsLimit() {
@@ -386,6 +387,7 @@
return;
}
lastExecutedSql = sql;
executeStartLine = startLine;
executeNumber++;
visibleResultTabs = true;
@@ -784,6 +786,9 @@
{driver}
onSetFrontMatterField={handleSetFrontMatterField}
onGetFrontMatter={() => getSqlFrontMatter($editorValue, yaml)}
exportConid={conid}
exportDatabase={database}
exportQuery={queryRowsLimit ? lastExecutedSql : null}
>
<svelte:fragment slot="0">
<SocketMessageView