diff --git a/packages/api/src/controllers/uploads.js b/packages/api/src/controllers/uploads.js
index d593bf104..54407d4da 100644
--- a/packages/api/src/controllers/uploads.js
+++ b/packages/api/src/controllers/uploads.js
@@ -2,6 +2,21 @@ const path = require('path');
const { uploadsdir } = require('../utility/directories');
const uuidv1 = require('uuid/v1');
+const extensions = [
+ {
+ ext: '.xlsx',
+ type: 'excel',
+ },
+ {
+ ext: '.jsonl',
+ type: 'jsonl',
+ },
+ {
+ ext: '.csv',
+ type: 'csv',
+ },
+];
+
module.exports = {
upload_meta: {
method: 'post',
@@ -16,10 +31,21 @@ module.exports = {
const uploadName = uuidv1();
const filePath = path.join(uploadsdir(), uploadName);
console.log(`Uploading file ${data.name}, size=${data.size}`);
+ let storageType = null;
+ let shortName = data.name;
+ for (const { ext, type } of extensions) {
+ if (data.name.endsWith(ext)) {
+ storageType = type;
+ shortName = data.name.slice(0, -ext.length);
+ }
+ }
data.mv(filePath, () => {
res.json({
originalName: data.name,
+ shortName,
+ storageType,
uploadName,
+ filePath,
});
});
},
diff --git a/packages/web/src/App.js b/packages/web/src/App.js
index 4dcbe3e0c..2ca0f2093 100644
--- a/packages/web/src/App.js
+++ b/packages/web/src/App.js
@@ -13,6 +13,7 @@ import {
import { SocketProvider } from './utility/SocketProvider';
import ConnectionsPinger from './utility/ConnectionsPinger';
import { ModalLayerProvider } from './modals/showModal';
+import UploadsProvider from './utility/UploadsProvider';
function App() {
return (
@@ -26,7 +27,9 @@ function App() {
-
+
+
+
diff --git a/packages/web/src/DragAndDropFileTarget.js b/packages/web/src/DragAndDropFileTarget.js
new file mode 100644
index 000000000..2041aa49b
--- /dev/null
+++ b/packages/web/src/DragAndDropFileTarget.js
@@ -0,0 +1,53 @@
+import React from 'react';
+import styled from 'styled-components';
+
+const TargetStyled = styled.div`
+ position: fixed;
+ display: flex;
+ top: 0;
+ left: 0;
+ right: 0;
+ bottom: 0;
+ background: #aaaaff;
+ align-items: center;
+ justify-content: space-around;
+ z-index: 1000;
+`;
+
+const InfoBox = styled.div``;
+
+const IconWrapper = styled.div`
+ display: flex;
+ justify-content: space-around;
+ font-size: 50px;
+ margin-bottom: 20px;
+`;
+
+const InfoWrapper = styled.div`
+ display: flex;
+ justify-content: space-around;
+ margin-top: 10px;
+`;
+
+const TitleWrapper = styled.div`
+ font-size: 30px;
+ display: flex;
+ justify-content: space-around;
+`;
+
+export default function DragAndDropFileTarget({ isDragActive, inputProps }) {
+ return (
+ !!isDragActive && (
+
+
+
+
+
+ Drop the files to upload to DbGate
+ Supported file types: csv, MS Excel, json-lines
+
+
+
+ )
+ );
+}
diff --git a/packages/web/src/Screen.js b/packages/web/src/Screen.js
index a2ce0db8f..62d891f6a 100644
--- a/packages/web/src/Screen.js
+++ b/packages/web/src/Screen.js
@@ -3,7 +3,6 @@
import React from 'react';
import theme from './theme';
import styled from 'styled-components';
-import { useDropzone } from 'react-dropzone';
import TabsPanel from './TabsPanel';
import TabContent from './TabContent';
import WidgetIconPanel from './widgets/WidgetIconPanel';
@@ -13,7 +12,8 @@ import ToolBar from './widgets/Toolbar';
import StatusBar from './widgets/StatusBar';
import { useSplitterDrag, HorizontalSplitHandle } from './widgets/Splitter';
import { ModalLayer } from './modals/showModal';
-import resolveApi from './utility/resolveApi';
+import DragAndDropFileTarget from './DragAndDropFileTarget';
+import { useUploadsZone } from './utility/UploadsProvider';
const BodyDiv = styled.div`
position: fixed;
@@ -98,15 +98,6 @@ const ScreenHorizontalSplitHandle = styled(HorizontalSplitHandle)`
bottom: ${theme.statusBar.height}px;
`;
-const DragAndDropTarget = styled.div`
- position: fixed;
- top: 0;
- left: 0;
- right: 0;
- bottom: 0;
- background: red;
-`;
-
export default function Screen() {
const currentWidget = useCurrentWidget();
const leftPanelWidth = useLeftPanelWidth();
@@ -117,42 +108,7 @@ export default function Screen() {
const toolbarPortalRef = React.useRef();
const onSplitDown = useSplitterDrag('clientX', (diff) => setLeftPanelWidth((v) => v + diff));
- const onDrop = React.useCallback((files) => {
- // Do something with the files
- console.log('FILES', files);
- files.forEach(async (file) => {
- if (parseInt(file.size, 10) >= 4 * 1024 * 1024) {
- // to big file
- return;
- }
-
- const formData = new FormData();
- formData.append('data', file);
-
- const fetchOptions = {
- method: 'POST',
- body: formData,
- };
-
- const apiBase = resolveApi();
- const resp = await fetch(`${apiBase}/uploads/upload`, fetchOptions);
- const event = await resp.json();
-
- return event;
-
- // const reader = new FileReader();
-
- // reader.onabort = () => console.log('file reading was aborted');
- // reader.onerror = () => console.log('file reading has failed');
- // reader.onload = () => {
- // // Do whatever you want with the file contents
- // const binaryStr = reader.result;
- // console.log(binaryStr);
- // };
- // reader.readAsArrayBuffer(file);
- });
- }, []);
- const { getRootProps, getInputProps, isDragActive } = useDropzone({ onDrop });
+ const { getRootProps, getInputProps, isDragActive } = useUploadsZone();
return (
@@ -184,12 +140,7 @@ export default function Screen() {
- {!!isDragActive && (
-
- Drop the files here ...
- {' '}
-
- )}
+
);
}
diff --git a/packages/web/src/impexp/ImportExportConfigurator.js b/packages/web/src/impexp/ImportExportConfigurator.js
index 58341aa60..2ef09f7a2 100644
--- a/packages/web/src/impexp/ImportExportConfigurator.js
+++ b/packages/web/src/impexp/ImportExportConfigurator.js
@@ -22,6 +22,7 @@ import getAsArray from '../utility/getAsArray';
import axios from '../utility/axios';
import LoadingInfo from '../widgets/LoadingInfo';
import SqlEditor from '../sqleditor/SqlEditor';
+import { useUploadsProvider } from '../utility/UploadsProvider';
const Container = styled.div`
max-height: 50vh;
@@ -62,6 +63,11 @@ const SqlWrapper = styled.div`
width: 20vw;
`;
+const DragWrapper = styled.div`
+ padding: 10px;
+ background: #ddd;
+`;
+
function getFileFilters(storageType) {
const res = [];
if (storageType == 'csv') res.push({ name: 'CSV files', extensions: ['csv'] });
@@ -141,7 +147,7 @@ function FilesInput() {
if (electron) {
return ;
}
- return ;
+ return Drag & drop imported files here;
}
function SourceTargetConfig({
@@ -287,12 +293,43 @@ function SourceName({ name }) {
);
}
-export default function ImportExportConfigurator() {
+export default function ImportExportConfigurator({ uploadedFile = undefined }) {
const { values, setFieldValue } = useFormikContext();
const targetDbinfo = useDatabaseInfo({ conid: values.targetConnectionId, database: values.targetDatabaseName });
const sourceConnectionInfo = useConnectionInfo({ conid: values.sourceConnectionId });
const { engine: sourceEngine } = sourceConnectionInfo || {};
const { sourceList } = values;
+ const { uploadListener, setUploadListener } = useUploadsProvider();
+
+ const handleUpload = React.useCallback(
+ (file) => {
+ addFilesToSourceList(
+ [
+ {
+ full: file.filePath,
+ name: file.shortName,
+ },
+ ],
+ values,
+ setFieldValue
+ );
+ // setFieldValue('sourceList', [...(sourceList || []), file.originalName]);
+ },
+ [setFieldValue, sourceList]
+ );
+
+ React.useEffect(() => {
+ setUploadListener(() => handleUpload);
+ return () => {
+ setUploadListener(null);
+ };
+ }, [handleUpload]);
+
+ React.useEffect(() => {
+ if (uploadedFile) {
+ handleUpload(uploadedFile);
+ }
+ }, []);
return (
diff --git a/packages/web/src/modals/ImportExportModal.js b/packages/web/src/modals/ImportExportModal.js
index 5d7ca4cec..f3d309759 100644
--- a/packages/web/src/modals/ImportExportModal.js
+++ b/packages/web/src/modals/ImportExportModal.js
@@ -38,7 +38,7 @@ function GenerateSctriptButton({ modalState }) {
return ;
}
-export default function ImportExportModal({ modalState, initialValues }) {
+export default function ImportExportModal({ modalState, initialValues, uploadedFile = undefined }) {
const [executeNumber, setExecuteNumber] = React.useState(0);
const [runnerId, setRunnerId] = React.useState(null);
const archive = useCurrentArchive();
@@ -69,7 +69,7 @@ export default function ImportExportModal({ modalState, initialValues }) {