mirror of
https://github.com/DeNNiiInc/dbgate.git
synced 2026-04-21 22:16:00 +00:00
import export configurator WIP
This commit is contained in:
@@ -8,6 +8,7 @@ export default function DataGridContextMenu({
|
||||
insertNewRow,
|
||||
setNull,
|
||||
reload,
|
||||
exportGrid,
|
||||
}) {
|
||||
return (
|
||||
<>
|
||||
@@ -31,6 +32,9 @@ export default function DataGridContextMenu({
|
||||
<DropDownMenuItem onClick={setNull} keyText="Ctrl+0">
|
||||
Set NULL
|
||||
</DropDownMenuItem>
|
||||
<DropDownMenuItem onClick={exportGrid} >
|
||||
Export
|
||||
</DropDownMenuItem>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -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) => <ImportExportModal modalState={modalState} />);
|
||||
}
|
||||
|
||||
function setCellValue(chs, cell, value) {
|
||||
return setChangeSetValue(
|
||||
chs,
|
||||
|
||||
110
packages/web/src/impexp/ImportExportConfigurator.js
Normal file
110
packages/web/src/impexp/ImportExportConfigurator.js
Normal file
@@ -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 (
|
||||
<>
|
||||
<Label>Server</Label>
|
||||
<StyledSelect
|
||||
options={connectionOptions}
|
||||
// defaultValue={type}
|
||||
// onChange={setType}
|
||||
menuPortalTarget={document.body}
|
||||
/>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
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 (
|
||||
<Column>
|
||||
{isSource && <Label>Source configuration</Label>}
|
||||
{isTarget && <Label>Target configuration</Label>}
|
||||
<FormReactSelect options={types} name={storageTypeField} />
|
||||
{values[storageTypeField] == 'database' && (
|
||||
<>
|
||||
<Label>Server</Label>
|
||||
<FormConnectionSelect name={connectionIdField} />
|
||||
<Label>Database</Label>
|
||||
<FormDatabaseSelect conidName={connectionIdField} name={databaseNameField} />
|
||||
</>
|
||||
)}
|
||||
</Column>
|
||||
);
|
||||
}
|
||||
|
||||
export default function ImportExportConfigurator() {
|
||||
return (
|
||||
<Formik onSubmit={null} initialValues={{ sourceStorageType: 'database', targetStorageType: 'csv' }}>
|
||||
<Form>
|
||||
<Wrapper>
|
||||
<SourceTargetConfig
|
||||
isSource
|
||||
storageTypeField="sourceStorageType"
|
||||
connectionIdField="sourceConnectionId"
|
||||
databaseNameField="sourceDatabaseName"
|
||||
/>
|
||||
<SourceTargetConfig
|
||||
isTarget
|
||||
storageTypeField="targetStorageType"
|
||||
connectionIdField="targetConnectionId"
|
||||
databaseNameField="targetDatabaseName"
|
||||
/>
|
||||
</Wrapper>
|
||||
</Form>
|
||||
</Formik>
|
||||
);
|
||||
}
|
||||
26
packages/web/src/modals/ImportExportModal.js
Normal file
26
packages/web/src/modals/ImportExportModal.js
Normal file
@@ -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 (
|
||||
<ModalBase modalState={modalState}>
|
||||
<ModalHeader modalState={modalState}>Import/Export</ModalHeader>
|
||||
<ModalContent>
|
||||
<ImportExportConfigurator />
|
||||
</ModalContent>
|
||||
<ModalFooter>
|
||||
<FormStyledButton type="button" value="Close" onClick={modalState.close} />
|
||||
</ModalFooter>
|
||||
</ModalBase>
|
||||
);
|
||||
}
|
||||
@@ -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 }) {
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export function FormReactSelect({ options, name }) {
|
||||
const { setFieldValue, values } = useFormikContext();
|
||||
return (
|
||||
<Select
|
||||
options={options}
|
||||
defaultValue={options.find((x) => x.value == values[name])}
|
||||
onChange={(item) => setFieldValue(name, item ? item.value : null)}
|
||||
menuPortalTarget={document.body}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
export function FormConnectionSelect({ name }) {
|
||||
const connections = useConnectionList();
|
||||
const connectionOptions = React.useMemo(
|
||||
() =>
|
||||
(connections || []).map((conn) => ({
|
||||
value: conn._id,
|
||||
label: conn.displayName || conn.server,
|
||||
})),
|
||||
[connections]
|
||||
);
|
||||
|
||||
if (connectionOptions.length == 0) return <div>Not available</div>;
|
||||
return <FormReactSelect options={connectionOptions} name={name} />;
|
||||
}
|
||||
|
||||
export function FormDatabaseSelect({ conidName, name }) {
|
||||
const { values } = useFormikContext();
|
||||
const databases = useDatabaseList({ conid: values[conidName] });
|
||||
const databaseOptions = React.useMemo(
|
||||
() =>
|
||||
(databases || []).map((db) => ({
|
||||
value: db.name,
|
||||
label: db.name,
|
||||
})),
|
||||
[databases]
|
||||
);
|
||||
|
||||
if (databaseOptions.length == 0) return <div>Not available</div>;
|
||||
return <FormReactSelect options={databaseOptions} name={name} />;
|
||||
}
|
||||
|
||||
@@ -58,6 +58,9 @@ export default function useFetch({
|
||||
}, [...indicators]);
|
||||
|
||||
React.useEffect(() => {
|
||||
if (reloadTrigger && !socket) {
|
||||
console.error('Socket not available, reloadTrigger not planned');
|
||||
}
|
||||
if (reloadTrigger && socket) {
|
||||
for (const item of getAsArray(reloadTrigger)) {
|
||||
socket.on(item, handleReload);
|
||||
|
||||
Reference in New Issue
Block a user