preview in import dialog

This commit is contained in:
Jan Prochazka
2020-11-15 09:43:44 +01:00
parent 844ebf129a
commit 075146403a
10 changed files with 142 additions and 22 deletions

View File

@@ -14,8 +14,8 @@ import {
} from '../utility/forms';
import { useArchiveFiles, useConnectionInfo, useDatabaseInfo } from '../utility/metadataLoaders';
import TableControl, { TableColumn } from '../utility/TableControl';
import { TextField, SelectField } from '../utility/inputs';
import { getActionOptions, getTargetName, isFileStorage } from './createImpExpScript';
import { TextField, SelectField, CheckboxField } from '../utility/inputs';
import { createPreviewReader, getActionOptions, getTargetName, isFileStorage } from './createImpExpScript';
import getElectron from '../utility/getElectron';
import ErrorInfo from '../widgets/ErrorInfo';
import getAsArray from '../utility/getAsArray';
@@ -86,7 +86,7 @@ function getFileFilters(storageType) {
return res;
}
async function addFilesToSourceList(files, values, setFieldValue, preferedStorageType) {
async function addFilesToSourceList(files, values, setFieldValue, preferedStorageType, setPreviewSource) {
const newSources = [];
const storage = preferedStorageType || values.sourceStorageType;
for (const file of getAsArray(files)) {
@@ -116,6 +116,9 @@ async function addFilesToSourceList(files, values, setFieldValue, preferedStorag
if (preferedStorageType && preferedStorageType != values.sourceStorageType) {
setFieldValue('sourceStorageType', preferedStorageType);
}
if (setPreviewSource && newSources.length == 1) {
setPreviewSource(newSources[0]);
}
}
function ElectronFilesInput() {
@@ -308,7 +311,7 @@ function SourceName({ name }) {
);
}
export default function ImportExportConfigurator({ uploadedFile = undefined }) {
export default function ImportExportConfigurator({ uploadedFile = undefined, onChangePreview = undefined }) {
const { values, setFieldValue } = useFormikContext();
const targetDbinfo = useDatabaseInfo({ conid: values.targetConnectionId, database: values.targetDatabaseName });
const sourceConnectionInfo = useConnectionInfo({ conid: values.sourceConnectionId });
@@ -316,6 +319,7 @@ export default function ImportExportConfigurator({ uploadedFile = undefined }) {
const { sourceList } = values;
const { setUploadListener } = useUploadsProvider();
const theme = useTheme();
const [previewSource, setPreviewSource] = React.useState(null);
const handleUpload = React.useCallback(
(file) => {
@@ -328,7 +332,8 @@ export default function ImportExportConfigurator({ uploadedFile = undefined }) {
],
values,
setFieldValue,
!sourceList || sourceList.length == 0 ? file.storageType : null
!sourceList || sourceList.length == 0 ? file.storageType : null,
setPreviewSource
);
// setFieldValue('sourceList', [...(sourceList || []), file.originalName]);
},
@@ -348,6 +353,21 @@ export default function ImportExportConfigurator({ uploadedFile = undefined }) {
}
}, []);
const supportsPreview = ['csv', 'jsonl', 'excel'].includes(values.sourceStorageType);
const handleChangePreviewSource = async () => {
if (previewSource && supportsPreview) {
const reader = await createPreviewReader(values, previewSource);
if (onChangePreview) onChangePreview(reader);
} else {
onChangePreview(null);
}
};
React.useEffect(() => {
handleChangePreviewSource();
}, [previewSource, supportsPreview]);
return (
<Container>
<Wrapper>
@@ -396,6 +416,21 @@ export default function ImportExportConfigurator({ uploadedFile = undefined }) {
/>
)}
/>
<TableColumn
fieldName="preview"
header="Preview"
formatter={(row) =>
supportsPreview ? (
<CheckboxField
checked={previewSource == row}
onChange={(e) => {
if (e.target.checked) setPreviewSource(row);
else setPreviewSource(null);
}}
/>
) : null
}
/>
</TableControl>
</Container>
);

View File

@@ -0,0 +1,59 @@
import { createGridCache, createGridConfig, FreeTableGridDisplay } from '@dbgate/datalib';
import React from 'react';
import DataGridCore from '../datagrid/DataGridCore';
import RowsArrayGrider from '../datagrid/RowsArrayGrider';
import axios from '../utility/axios';
import ErrorInfo from '../widgets/ErrorInfo';
import LoadingInfo from '../widgets/LoadingInfo';
export default function PreviewDataGrid({ reader, ...other }) {
const [isLoading, setIsLoading] = React.useState(false);
const [errorMessage, setErrorMessage] = React.useState(null);
const [model, setModel] = React.useState(null);
const [config, setConfig] = React.useState(createGridConfig());
const [cache, setCache] = React.useState(createGridCache());
const [grider, setGrider] = React.useState(null);
const handleLoadInitialData = async () => {
try {
if (!reader) {
setModel(null);
setGrider(null);
return;
}
setIsLoading(true);
const resp = await axios.post('runners/load-reader', reader);
// @ts-ignore
setModel(resp.data);
setGrider(new RowsArrayGrider(resp.data.rows));
setIsLoading(false);
} catch (err) {
setIsLoading(false);
const errorMessage = (err && err.response && err.response.data && err.response.data.error) || 'Loading failed';
setErrorMessage(errorMessage);
console.error(err.response);
}
};
React.useEffect(() => {
handleLoadInitialData();
}, [reader]);
const display = React.useMemo(() => new FreeTableGridDisplay(model, config, setConfig, cache, setCache), [
model,
config,
cache,
grider,
]);
if (isLoading) {
return <LoadingInfo wrapper message="Loading data" />;
}
if (errorMessage) {
return <ErrorInfo message={errorMessage} />;
}
if (!grider) return null;
return <DataGridCore {...other} grider={grider} display={display} />;
}

View File

@@ -211,3 +211,19 @@ export function getActionOptions(source, values, targetDbinfo) {
}
return res;
}
export async function createPreviewReader(values, sourceName) {
const [sourceConnection, sourceDriver] = await getConnection(
values.sourceStorageType,
values.sourceConnectionId,
values.sourceDatabaseName
);
const [functionName, props] = getSourceExpr(sourceName, values, sourceConnection, sourceDriver);
return {
functionName,
props: {
...props,
limitRows: 100,
},
};
}