diff --git a/packages/web/package.json b/packages/web/package.json index 7cf6a3472..9a453c0e0 100644 --- a/packages/web/package.json +++ b/packages/web/package.json @@ -21,6 +21,7 @@ "react-dom": "^16.12.0", "react-modal": "^3.11.1", "react-scripts": "3.3.0", + "react-select": "^3.1.0", "resize-observer-polyfill": "^1.5.1", "socket.io-client": "^2.3.0", "sql-formatter": "^2.3.3", diff --git a/packages/web/src/datagrid/DataGridContextMenu.js b/packages/web/src/datagrid/DataGridContextMenu.js index 7ff2b39de..90a33f7b5 100644 --- a/packages/web/src/datagrid/DataGridContextMenu.js +++ b/packages/web/src/datagrid/DataGridContextMenu.js @@ -8,6 +8,7 @@ export default function DataGridContextMenu({ insertNewRow, setNull, reload, + exportGrid, }) { return ( <> @@ -31,6 +32,9 @@ export default function DataGridContextMenu({ Set NULL + + Export + ); } diff --git a/packages/web/src/datagrid/DataGridCore.js b/packages/web/src/datagrid/DataGridCore.js index 1a990de6e..bf54a8da0 100644 --- a/packages/web/src/datagrid/DataGridCore.js +++ b/packages/web/src/datagrid/DataGridCore.js @@ -42,6 +42,7 @@ import LoadingInfo from '../widgets/LoadingInfo'; import ErrorInfo from '../widgets/ErrorInfo'; import showModal from '../modals/showModal'; import ErrorMessageModal from '../modals/ErrorMessageModal'; +import ImportExportModal from '../modals/ImportExportModal'; const GridContainer = styled.div` position: absolute; @@ -537,6 +538,7 @@ export default function DataGridCore(props) { insertNewRow={insertNewRow} reload={() => display.reload()} setNull={setNull} + exportGrid={exportGrid} /> ); }; @@ -591,6 +593,10 @@ export default function DataGridCore(props) { copyToClipboard(); } + function exportGrid() { + showModal((modalState) => ); + } + function setCellValue(chs, cell, value) { return setChangeSetValue( chs, diff --git a/packages/web/src/impexp/ImportExportConfigurator.js b/packages/web/src/impexp/ImportExportConfigurator.js new file mode 100644 index 000000000..ca53e4d3a --- /dev/null +++ b/packages/web/src/impexp/ImportExportConfigurator.js @@ -0,0 +1,110 @@ +import React from 'react'; +import FormStyledButton from '../widgets/FormStyledButton'; +import { Formik, Form, useFormik, useFormikContext } from 'formik'; +import styled from 'styled-components'; +import Select from 'react-select'; +import { FontIcon } from '../icons'; +import { FormButtonRow, FormSubmit, FormReactSelect, FormConnectionSelect, FormDatabaseSelect } from '../utility/forms'; +import { useConnectionList, useDatabaseList } from '../utility/metadataLoaders'; + +const Wrapper = styled.div` + display: flex; +`; + +const Column = styled.div` + margin: 10px; + flex: 1; +`; + +const StyledSelect = styled(Select)` + // min-width: 350px; +`; + +const OptionsWrapper = styled.div` + margin-left: 10px; +`; + +const Label = styled.div` + margin: 5px; + margin-top: 15px; + color: #777; +`; + +function DatabaseSelector() { + const connections = useConnectionList(); + const connectionOptions = React.useMemo( + () => + (connections || []).map((conn) => ({ + value: conn._id, + label: conn.displayName || conn.server, + })), + [connections] + ); + + // const databases = useDatabaseList({ conid: _id }); + + return ( + <> + + + + ); +} + +function SourceTargetConfig({ + isSource = false, + isTarget = false, + storageTypeField, + connectionIdField, + databaseNameField, +}) { + const types = [ + { value: 'database', label: 'Database' }, + { value: 'csv', label: 'CSV file(s)' }, + { value: 'json', label: 'JSON file(s)' }, + ]; + const { values } = useFormikContext(); + return ( + + {isSource && } + {isTarget && } + + {values[storageTypeField] == 'database' && ( + <> + + + + + + )} + + ); +} + +export default function ImportExportConfigurator() { + return ( + +
+ + + + +
+
+ ); +} diff --git a/packages/web/src/modals/ImportExportModal.js b/packages/web/src/modals/ImportExportModal.js new file mode 100644 index 000000000..6d2f49d5d --- /dev/null +++ b/packages/web/src/modals/ImportExportModal.js @@ -0,0 +1,26 @@ +import React from 'react'; +import ModalBase from './ModalBase'; +import FormStyledButton from '../widgets/FormStyledButton'; +import styled from 'styled-components'; +import Select from 'react-select'; +import { FontIcon } from '../icons'; +import { FormButtonRow, FormSubmit } from '../utility/forms'; +import ModalHeader from './ModalHeader'; +import ModalFooter from './ModalFooter'; +import ModalContent from './ModalContent'; +import { useConnectionList, useDatabaseList } from '../utility/metadataLoaders'; +import ImportExportConfigurator from '../impexp/ImportExportConfigurator'; + +export default function ImportExportModal({ modalState }) { + return ( + + Import/Export + + + + + + + + ); +} diff --git a/packages/web/src/utility/forms.js b/packages/web/src/utility/forms.js index 8f22f6a73..ba3f3e743 100644 --- a/packages/web/src/utility/forms.js +++ b/packages/web/src/utility/forms.js @@ -1,8 +1,11 @@ import React from 'react'; import styled from 'styled-components'; +import Select from 'react-select'; import { TextField, SelectField } from './inputs'; import { Field, useFormikContext } from 'formik'; import FormStyledButton from '../widgets/FormStyledButton'; +import { useConnectionList, useDatabaseList } from './metadataLoaders'; +import useSocket from './SocketProvider'; export const FormRow = styled.div` display: flex; @@ -80,3 +83,46 @@ export function FormRadioGroupItem({ name, text, value }) { ); } + +export function FormReactSelect({ options, name }) { + const { setFieldValue, values } = useFormikContext(); + return ( +