removed formik, used own FormProvider instead

This commit is contained in:
Jan Prochazka
2020-12-05 16:16:04 +01:00
parent 1644587072
commit a3837083da
17 changed files with 248 additions and 266 deletions

View File

@@ -17,7 +17,6 @@
"dbgate-tools": "^1.0.0", "dbgate-tools": "^1.0.0",
"eslint": "^6.8.0", "eslint": "^6.8.0",
"eslint-plugin-react": "^7.17.0", "eslint-plugin-react": "^7.17.0",
"formik": "^2.1.0",
"json-stable-stringify": "^1.0.1", "json-stable-stringify": "^1.0.1",
"localforage": "^1.9.0", "localforage": "^1.9.0",
"react": "^16.12.0", "react": "^16.12.0",

View File

@@ -6,8 +6,8 @@ import useDimensions from '../utility/useDimensions';
import { HorizontalSplitter } from '../widgets/Splitter'; import { HorizontalSplitter } from '../widgets/Splitter';
import WidgetColumnBar, { WidgetColumnBarItem } from '../widgets/WidgetColumnBar'; import WidgetColumnBar, { WidgetColumnBarItem } from '../widgets/WidgetColumnBar';
import { FormCheckboxField, FormSelectField } from '../utility/forms'; import { FormCheckboxField, FormSelectField } from '../utility/forms';
import { Formik, Form } from 'formik';
import DataChart from './DataChart'; import DataChart from './DataChart';
import { FormProvider } from '../utility/FormProvider';
const LeftContainer = styled.div` const LeftContainer = styled.div`
background-color: ${(props) => props.theme.manager_background}; background-color: ${(props) => props.theme.manager_background};
@@ -21,8 +21,7 @@ export default function ChartEditor({ data }) {
const availableColumnNames = data ? data.structure.columns.map((x) => x.columnName) : []; const availableColumnNames = data ? data.structure.columns.map((x) => x.columnName) : [];
return ( return (
<Formik initialValues={{ chartType: 'bar' }} onSubmit={() => {}}> <FormProvider initialValues={{ chartType: 'bar' }}>
<Form>
<HorizontalSplitter initialValue="300px" size={managerSize} setSize={setManagerSize}> <HorizontalSplitter initialValue="300px" size={managerSize} setSize={setManagerSize}>
<LeftContainer theme={theme}> <LeftContainer theme={theme}>
<WidgetColumnBar> <WidgetColumnBar>
@@ -50,7 +49,6 @@ export default function ChartEditor({ data }) {
<DataChart data={data} /> <DataChart data={data} />
</HorizontalSplitter> </HorizontalSplitter>
</Form> </FormProvider>
</Formik>
); );
} }

View File

@@ -7,7 +7,7 @@ import useDimensions from '../utility/useDimensions';
import { HorizontalSplitter } from '../widgets/Splitter'; import { HorizontalSplitter } from '../widgets/Splitter';
import WidgetColumnBar, { WidgetColumnBarItem } from '../widgets/WidgetColumnBar'; import WidgetColumnBar, { WidgetColumnBarItem } from '../widgets/WidgetColumnBar';
import { FormSelectField } from '../utility/forms'; import { FormSelectField } from '../utility/forms';
import { Formik, Form, useFormikContext } from 'formik'; import { useForm } from '../utility/FormProvider';
const ChartWrapper = styled.div` const ChartWrapper = styled.div`
flex: 1; flex: 1;
@@ -75,7 +75,7 @@ function createChartData(freeData, labelColumn, dataColumns) {
export default function DataChart({ data }) { export default function DataChart({ data }) {
const [containerRef, { height: containerHeight, width: containerWidth }] = useDimensions(); const [containerRef, { height: containerHeight, width: containerWidth }] = useDimensions();
const { values } = useFormikContext(); const { values } = useForm();
const { labelColumn } = values; const { labelColumn } = values;
const dataColumns = []; const dataColumns = [];

View File

@@ -1,8 +1,7 @@
import React from 'react'; import React from 'react';
import _ from 'lodash'; import _ from 'lodash';
import { Formik, Form, useFormikContext } from 'formik';
import FormArgumentList from '../utility/FormArgumentList'; import FormArgumentList from '../utility/FormArgumentList';
import { FormProvider } from '../utility/FormProvider';
export default function MacroParameters({ args, onChangeValues, macroValues, namePrefix }) { export default function MacroParameters({ args, onChangeValues, macroValues, namePrefix }) {
if (!args || args.length == 0) return null; if (!args || args.length == 0) return null;
@@ -11,10 +10,8 @@ export default function MacroParameters({ args, onChangeValues, macroValues, nam
...macroValues, ...macroValues,
}; };
return ( return (
<Formik initialValues={initialValues} onSubmit={() => {}}> <FormProvider initialValues={initialValues}>
<Form>
<FormArgumentList args={args} onChangeValues={onChangeValues} namePrefix={namePrefix} /> <FormArgumentList args={args} onChangeValues={onChangeValues} namePrefix={namePrefix} />
</Form> </FormProvider>
</Formik>
); );
} }

View File

@@ -1,7 +1,6 @@
import React from 'react'; import React from 'react';
import _ from 'lodash'; import _ from 'lodash';
import FormStyledButton from '../widgets/FormStyledButton'; import FormStyledButton from '../widgets/FormStyledButton';
import { useFormikContext } from 'formik';
import styled from 'styled-components'; import styled from 'styled-components';
import { import {
FormReactSelect, FormReactSelect,
@@ -30,6 +29,7 @@ import useExtensions from '../utility/useExtensions';
import UploadButton from '../utility/UploadButton'; import UploadButton from '../utility/UploadButton';
import useShowModal from '../modals/showModal'; import useShowModal from '../modals/showModal';
import ChangeDownloadUrlModal from '../modals/ChangeDownloadUrlModal'; import ChangeDownloadUrlModal from '../modals/ChangeDownloadUrlModal';
import { useForm } from '../utility/FormProvider';
const Container = styled.div` const Container = styled.div`
// max-height: 50vh; // max-height: 50vh;
@@ -142,7 +142,7 @@ async function addFilesToSourceList(extensions, files, values, setValues, prefer
} }
function ElectronFilesInput() { function ElectronFilesInput() {
const { values, setValues } = useFormikContext(); const { values, setValues } = useForm();
const electron = getElectron(); const electron = getElectron();
const [isLoading, setIsLoading] = React.useState(false); const [isLoading, setIsLoading] = React.useState(false);
const extensions = useExtensions(); const extensions = useExtensions();
@@ -195,7 +195,7 @@ function FilesInput({ setPreviewSource = undefined }) {
const theme = useTheme(); const theme = useTheme();
const electron = getElectron(); const electron = getElectron();
const showModal = useShowModal(); const showModal = useShowModal();
const { values, setValues } = useFormikContext(); const { values, setValues } = useForm();
const extensions = useExtensions(); const extensions = useExtensions();
const doAddUrl = (url) => { const doAddUrl = (url) => {
addFilesToSourceList( addFilesToSourceList(
@@ -239,7 +239,7 @@ function SourceTargetConfig({
}) { }) {
const extensions = useExtensions(); const extensions = useExtensions();
const theme = useTheme(); const theme = useTheme();
const { values, setFieldValue } = useFormikContext(); const { values, setFieldValue } = useForm();
const types = const types =
values[storageTypeField] == 'jsldata' values[storageTypeField] == 'jsldata'
? [{ value: 'jsldata', label: 'Query result data', directions: ['source'] }] ? [{ value: 'jsldata', label: 'Query result data', directions: ['source'] }]
@@ -375,7 +375,7 @@ function SourceTargetConfig({
} }
function SourceName({ name }) { function SourceName({ name }) {
const { values, setFieldValue } = useFormikContext(); const { values, setFieldValue } = useForm();
const theme = useTheme(); const theme = useTheme();
const showModal = useShowModal(); const showModal = useShowModal();
const obj = values[`sourceFile_${name}`]; const obj = values[`sourceFile_${name}`];
@@ -412,7 +412,7 @@ function SourceName({ name }) {
} }
export default function ImportExportConfigurator({ uploadedFile = undefined, onChangePreview = undefined }) { export default function ImportExportConfigurator({ uploadedFile = undefined, onChangePreview = undefined }) {
const { values, setFieldValue, setValues } = useFormikContext(); const { values, setFieldValue, setValues } = useForm();
const targetDbinfo = useDatabaseInfo({ conid: values.targetConnectionId, database: values.targetDatabaseName }); const targetDbinfo = useDatabaseInfo({ conid: values.targetConnectionId, database: values.targetDatabaseName });
const sourceConnectionInfo = useConnectionInfo({ conid: values.sourceConnectionId }); const sourceConnectionInfo = useConnectionInfo({ conid: values.sourceConnectionId });
const { engine: sourceEngine } = sourceConnectionInfo || {}; const { engine: sourceEngine } = sourceConnectionInfo || {};

View File

@@ -1,38 +1,33 @@
import React from 'react'; import React from 'react';
import axios from '../utility/axios';
import ModalBase from './ModalBase'; import ModalBase from './ModalBase';
import { FormButtonRow, FormButton, FormTextField, FormSelectField, FormSubmit } from '../utility/forms'; import { FormButton, FormSubmit, FormTextField } from '../utility/forms';
import { TextField } from '../utility/inputs';
import { Formik, Form } from 'formik';
import ModalHeader from './ModalHeader'; import ModalHeader from './ModalHeader';
import ModalContent from './ModalContent'; import ModalContent from './ModalContent';
import ModalFooter from './ModalFooter'; import ModalFooter from './ModalFooter';
import FormStyledButton from '../widgets/FormStyledButton'; import FormStyledButton from '../widgets/FormStyledButton';
// import FormikForm from '../utility/FormikForm'; import { FormProvider } from '../utility/FormProvider';
export default function ChangeDownloadUrlModal({ modalState, url = '', onConfirm = undefined }) { export default function ChangeDownloadUrlModal({ modalState, url = '', onConfirm = undefined }) {
const textFieldRef = React.useRef(null); // const textFieldRef = React.useRef(null);
React.useEffect(() => { // React.useEffect(() => {
if (textFieldRef.current) textFieldRef.current.focus(); // if (textFieldRef.current) textFieldRef.current.focus();
}, [textFieldRef.current]); // }, [textFieldRef.current]);
const handleSubmit = async (values) => { const handleSubmit = async (values) => {
onConfirm(values.url); onConfirm(values.url);
modalState.close(); modalState.close();
}; };
return ( return (
<ModalBase modalState={modalState}> <ModalBase modalState={modalState}>
<ModalHeader modalState={modalState}>Dwonload imported file from web</ModalHeader> <ModalHeader modalState={modalState}>Download imported file from web</ModalHeader>
<Formik onSubmit={handleSubmit} initialValues={{ url }}> <FormProvider initialValues={{ url }}>
<Form>
<ModalContent> <ModalContent>
<FormTextField label="URL" name="url" editorRef={textFieldRef} style={{ width: '30vw' }} /> <FormTextField label="URL" name="url" style={{ width: '30vw' }} focused />
</ModalContent> </ModalContent>
<ModalFooter> <ModalFooter>
<FormSubmit text="OK" /> <FormSubmit value="OK" onClick={handleSubmit} />
<FormStyledButton value="Cancel" onClick={() => modalState.close()} /> <FormStyledButton value="Cancel" onClick={() => modalState.close()} />
</ModalFooter> </ModalFooter>
</Form> </FormProvider>
</Formik>
</ModalBase> </ModalBase>
); );
} }

View File

@@ -1,15 +1,14 @@
import React from 'react'; import React from 'react';
import axios from '../utility/axios'; import axios from '../utility/axios';
import ModalBase from './ModalBase'; import ModalBase from './ModalBase';
import { FormButtonRow, FormButton, FormTextField, FormSelectField, FormSubmit } from '../utility/forms'; import { FormButton, FormTextField, FormSelectField, FormSubmit } from '../utility/forms';
import { TextField } from '../utility/inputs';
import { Formik, Form } from 'formik';
import ModalHeader from './ModalHeader'; import ModalHeader from './ModalHeader';
import ModalFooter from './ModalFooter'; import ModalFooter from './ModalFooter';
import ModalContent from './ModalContent'; import ModalContent from './ModalContent';
import useExtensions from '../utility/useExtensions'; import useExtensions from '../utility/useExtensions';
import LoadingInfo from '../widgets/LoadingInfo'; import LoadingInfo from '../widgets/LoadingInfo';
import { FontIcon } from '../icons'; import { FontIcon } from '../icons';
import { FormProvider } from '../utility/FormProvider';
// import FormikForm from '../utility/FormikForm'; // import FormikForm from '../utility/FormikForm';
export default function ConnectionModal({ modalState, connection = undefined }) { export default function ConnectionModal({ modalState, connection = undefined }) {
@@ -41,8 +40,7 @@ export default function ConnectionModal({ modalState, connection = undefined })
return ( return (
<ModalBase modalState={modalState}> <ModalBase modalState={modalState}>
<ModalHeader modalState={modalState}>{connection ? 'Edit connection' : 'Add connection'}</ModalHeader> <ModalHeader modalState={modalState}>{connection ? 'Edit connection' : 'Add connection'}</ModalHeader>
<Formik onSubmit={handleSubmit} initialValues={connection || { server: 'localhost', engine: 'mssql' }}> <FormProvider initialValues={connection || { server: 'localhost', engine: 'mssql' }}>
<Form>
<ModalContent> <ModalContent>
<FormSelectField label="Database engine" name="engine"> <FormSelectField label="Database engine" name="engine">
<option value=""></option> <option value=""></option>
@@ -75,15 +73,14 @@ export default function ConnectionModal({ modalState, connection = undefined })
<ModalFooter> <ModalFooter>
{isTesting ? ( {isTesting ? (
<FormButton text="Cancel" onClick={handleCancel} /> <FormButton value="Cancel" onClick={handleCancel} />
) : ( ) : (
<FormButton text="Test" onClick={handleTest} /> <FormButton value="Test" onClick={handleTest} />
)} )}
<FormSubmit text="Save" /> <FormSubmit value="Save" onClick={handleSubmit} />
</ModalFooter> </ModalFooter>
</Form> </FormProvider>
</Formik>
</ModalBase> </ModalBase>
); );
} }

View File

@@ -1,11 +1,11 @@
import React from 'react'; import React from 'react';
import axios from '../utility/axios'; import axios from '../utility/axios';
import ModalBase from './ModalBase'; import ModalBase from './ModalBase';
import { FormTextField, FormSubmit } from '../utility/forms'; import { FormButton, FormSubmit, FormTextField } from '../utility/forms';
import { Formik, Form } from 'formik';
import ModalHeader from './ModalHeader'; import ModalHeader from './ModalHeader';
import ModalContent from './ModalContent'; import ModalContent from './ModalContent';
import ModalFooter from './ModalFooter'; import ModalFooter from './ModalFooter';
import { FormProvider } from '../utility/FormProvider';
export default function CreateDatabaseModal({ modalState, conid }) { export default function CreateDatabaseModal({ modalState, conid }) {
const handleSubmit = async (values) => { const handleSubmit = async (values) => {
@@ -17,16 +17,14 @@ export default function CreateDatabaseModal({ modalState, conid }) {
return ( return (
<ModalBase modalState={modalState}> <ModalBase modalState={modalState}>
<ModalHeader modalState={modalState}>Create database</ModalHeader> <ModalHeader modalState={modalState}>Create database</ModalHeader>
<Formik onSubmit={handleSubmit} initialValues={{ name: 'newdb' }}> <FormProvider initialValues={{ name: 'newdb' }}>
<Form>
<ModalContent> <ModalContent>
<FormTextField label="Database name" name="name" /> <FormTextField label="Database name" name="name" />
</ModalContent> </ModalContent>
<ModalFooter> <ModalFooter>
<FormSubmit text="Create" /> <FormSubmit value="Create" onClick={handleSubmit} />
</ModalFooter> </ModalFooter>
</Form> </FormProvider>
</Formik>
</ModalBase> </ModalBase>
); );
} }

View File

@@ -2,7 +2,6 @@ import React from 'react';
import moment from 'moment'; import moment from 'moment';
import ModalBase from './ModalBase'; import ModalBase from './ModalBase';
import FormStyledButton from '../widgets/FormStyledButton'; import FormStyledButton from '../widgets/FormStyledButton';
import { Formik, Form, useFormikContext } from 'formik';
import styled from 'styled-components'; import styled from 'styled-components';
import ModalHeader from './ModalHeader'; import ModalHeader from './ModalHeader';
import ModalFooter from './ModalFooter'; import ModalFooter from './ModalFooter';
@@ -21,9 +20,10 @@ import PreviewDataGrid from '../impexp/PreviewDataGrid';
import useSocket from '../utility/SocketProvider'; import useSocket from '../utility/SocketProvider';
import LoadingInfo from '../widgets/LoadingInfo'; import LoadingInfo from '../widgets/LoadingInfo';
import { FontIcon } from '../icons'; import { FontIcon } from '../icons';
import LargeButton from '../widgets/LargeButton'; import LargeButton, { LargeFormButton } from '../widgets/LargeButton';
import { getDefaultFileFormat } from '../utility/fileformats'; import { getDefaultFileFormat } from '../utility/fileformats';
import useExtensions from '../utility/useExtensions'; import useExtensions from '../utility/useExtensions';
import { FormProvider, useForm } from '../utility/FormProvider';
const headerHeight = '60px'; const headerHeight = '60px';
const footerHeight = '100px'; const footerHeight = '100px';
@@ -54,7 +54,7 @@ const WidgetColumnWrapper = styled.div`
border-left: 1px solid ${(props) => props.theme.border}; border-left: 1px solid ${(props) => props.theme.border};
`; `;
const StyledForm = styled(Form)` const FormWrapper = styled.div`
position: fixed; position: fixed;
top: 0; top: 0;
left: 0; left: 0;
@@ -92,7 +92,7 @@ const FooterButtons = styled.div`
function GenerateSctriptButton({ modalState }) { function GenerateSctriptButton({ modalState }) {
const setOpenedTabs = useSetOpenedTabs(); const setOpenedTabs = useSetOpenedTabs();
const { values } = useFormikContext(); const { values } = useForm();
const extensions = useExtensions(); const extensions = useExtensions();
const handleGenerateScript = async () => { const handleGenerateScript = async () => {
@@ -116,18 +116,6 @@ function GenerateSctriptButton({ modalState }) {
); );
} }
function RunButton() {
const { submitForm } = useFormikContext();
const handleSubmit = () => {
submitForm();
};
return (
<LargeButton onClick={handleSubmit} icon="icon run">
Run
</LargeButton>
);
}
export default function ImportExportModal({ export default function ImportExportModal({
modalState, modalState,
initialValues, initialValues,
@@ -194,8 +182,7 @@ export default function ImportExportModal({
return ( return (
<ModalBase modalState={modalState} fullScreen isFlex> <ModalBase modalState={modalState} fullScreen isFlex>
<Formik <FormProvider
onSubmit={handleExecute}
initialValues={{ initialValues={{
sourceStorageType: 'database', sourceStorageType: 'database',
targetStorageType: importToArchive ? 'archive' : getDefaultFileFormat(extensions).storageType, targetStorageType: importToArchive ? 'archive' : getDefaultFileFormat(extensions).storageType,
@@ -204,7 +191,7 @@ export default function ImportExportModal({
...initialValues, ...initialValues,
}} }}
> >
<StyledForm> <FormWrapper>
<ModalHeader modalState={modalState}>Import/Export {busy && <FontIcon icon="icon loading" />}</ModalHeader> <ModalHeader modalState={modalState}>Import/Export {busy && <FontIcon icon="icon loading" />}</ModalHeader>
<Wrapper> <Wrapper>
<ContentWrapper theme={theme}> <ContentWrapper theme={theme}>
@@ -236,7 +223,9 @@ export default function ImportExportModal({
Cancel Cancel
</LargeButton> </LargeButton>
) : ( ) : (
<RunButton /> <LargeFormButton onClick={handleExecute} icon="icon run">
Run
</LargeFormButton>
)} )}
<GenerateSctriptButton modalState={modalState} /> <GenerateSctriptButton modalState={modalState} />
<LargeButton onClick={modalState.close} icon="icon close"> <LargeButton onClick={modalState.close} icon="icon close">
@@ -244,8 +233,8 @@ export default function ImportExportModal({
</LargeButton> </LargeButton>
</FooterButtons> </FooterButtons>
</Footer> </Footer>
</StyledForm> </FormWrapper>
</Formik> </FormProvider>
</ModalBase> </ModalBase>
); );
} }

View File

@@ -1,11 +1,11 @@
import React from 'react'; import React from 'react';
import ModalBase from './ModalBase'; import ModalBase from './ModalBase';
import { FormTextField, FormSubmit, FormArchiveFolderSelect, FormRow, FormLabel } from '../utility/forms'; import { FormTextField, FormSubmit, FormArchiveFolderSelect, FormRow, FormLabel } from '../utility/forms';
import { Formik, Form } from 'formik';
import styled from 'styled-components'; import styled from 'styled-components';
import ModalHeader from './ModalHeader'; import ModalHeader from './ModalHeader';
import ModalContent from './ModalContent'; import ModalContent from './ModalContent';
import ModalFooter from './ModalFooter'; import ModalFooter from './ModalFooter';
import { FormProvider } from '../utility/FormProvider';
const SelectWrapper = styled.div` const SelectWrapper = styled.div`
width: 150px; width: 150px;
@@ -22,8 +22,7 @@ export default function SaveArchiveModal({ file = 'new-table', folder = 'default
return ( return (
<ModalBase modalState={modalState}> <ModalBase modalState={modalState}>
<ModalHeader modalState={modalState}>Save to archive</ModalHeader> <ModalHeader modalState={modalState}>Save to archive</ModalHeader>
<Formik onSubmit={handleSubmit} initialValues={{ file, folder }}> <FormProvider initialValues={{ file, folder }}>
<Form>
<ModalContent> <ModalContent>
{/* <Label>Archive folder</Label> */} {/* <Label>Archive folder</Label> */}
<FormRow> <FormRow>
@@ -35,10 +34,9 @@ export default function SaveArchiveModal({ file = 'new-table', folder = 'default
<FormTextField label="File name" name="file" /> <FormTextField label="File name" name="file" />
</ModalContent> </ModalContent>
<ModalFooter> <ModalFooter>
<FormSubmit text="Save" /> <FormSubmit value="Save" onClick={handleSubmit} />
</ModalFooter> </ModalFooter>
</Form> </FormProvider>
</Formik>
</ModalBase> </ModalBase>
); );
} }

View File

@@ -3,10 +3,10 @@ import axios from '../utility/axios';
import ModalBase from './ModalBase'; import ModalBase from './ModalBase';
import { FormButtonRow, FormButton, FormTextField, FormSelectField, FormSubmit } from '../utility/forms'; import { FormButtonRow, FormButton, FormTextField, FormSelectField, FormSubmit } from '../utility/forms';
import { TextField } from '../utility/inputs'; import { TextField } from '../utility/inputs';
import { Formik, Form } from 'formik';
import ModalHeader from './ModalHeader'; import ModalHeader from './ModalHeader';
import ModalContent from './ModalContent'; import ModalContent from './ModalContent';
import ModalFooter from './ModalFooter'; import ModalFooter from './ModalFooter';
import { FormProvider } from '../utility/FormProvider';
// import FormikForm from '../utility/FormikForm'; // import FormikForm from '../utility/FormikForm';
export default function SaveFileModal({ data, folder, format, modalState, name, onSave = undefined }) { export default function SaveFileModal({ data, folder, format, modalState, name, onSave = undefined }) {
@@ -19,16 +19,14 @@ export default function SaveFileModal({ data, folder, format, modalState, name,
return ( return (
<ModalBase modalState={modalState}> <ModalBase modalState={modalState}>
<ModalHeader modalState={modalState}>Save file</ModalHeader> <ModalHeader modalState={modalState}>Save file</ModalHeader>
<Formik onSubmit={handleSubmit} initialValues={{ name }}> <FormProvider initialValues={{ name }}>
<Form>
<ModalContent> <ModalContent>
<FormTextField label="File name" name="name" /> <FormTextField label="File name" name="name" />
</ModalContent> </ModalContent>
<ModalFooter> <ModalFooter>
<FormSubmit text="Save" /> <FormSubmit value="Save" onClick={handleSubmit} />
</ModalFooter> </ModalFooter>
</Form> </FormProvider>
</Formik>
</ModalBase> </ModalBase>
); );
} }

View File

@@ -2,12 +2,19 @@ import React from 'react';
import ModalBase from './ModalBase'; import ModalBase from './ModalBase';
import FormStyledButton from '../widgets/FormStyledButton'; import FormStyledButton from '../widgets/FormStyledButton';
import styled from 'styled-components'; import styled from 'styled-components';
import { FormButtonRow, FormSubmit, FormSelectFieldRaw, FormRow, FormRadioGroupItem, FormTextFieldRaw } from '../utility/forms'; import {
FormButtonRow,
FormSubmit,
FormSelectFieldRaw,
FormRow,
FormRadioGroupItem,
FormTextFieldRaw,
} from '../utility/forms';
import ModalHeader from './ModalHeader'; import ModalHeader from './ModalHeader';
import ModalFooter from './ModalFooter'; import ModalFooter from './ModalFooter';
import ModalContent from './ModalContent'; import ModalContent from './ModalContent';
import { Formik, Form } from 'formik';
import { TextField } from '../utility/inputs'; import { TextField } from '../utility/inputs';
import { FormProvider } from '../utility/FormProvider';
const Wrapper = styled.div` const Wrapper = styled.div`
display: flex; display: flex;
@@ -104,8 +111,7 @@ export default function SetFilterModal({ modalState, onFilter, filterType, condi
return ( return (
<ModalBase modalState={modalState}> <ModalBase modalState={modalState}>
<Formik onSubmit={handleOk} initialValues={{ condition1, condition2: '=', joinOperator: ' ' }}> <FormProvider initialValues={{ condition1, condition2: '=', joinOperator: ' ' }}>
<Form>
<ModalHeader modalState={modalState}>Set filter</ModalHeader> <ModalHeader modalState={modalState}>Set filter</ModalHeader>
<ModalContent> <ModalContent>
<FormRow>Show rows where</FormRow> <FormRow>Show rows where</FormRow>
@@ -123,11 +129,10 @@ export default function SetFilterModal({ modalState, onFilter, filterType, condi
</FormRow> </FormRow>
</ModalContent> </ModalContent>
<ModalFooter> <ModalFooter>
<FormSubmit text="OK" /> <FormSubmit value="OK" onClick={handleOk} />
<FormStyledButton type="button" value="Close" onClick={modalState.close} /> <FormStyledButton type="button" value="Close" onClick={modalState.close} />
</ModalFooter> </ModalFooter>
</Form> </FormProvider>
</Formik>
</ModalBase> </ModalBase>
); );
} }

View File

@@ -1,16 +1,8 @@
import React from 'react'; import React from 'react';
import _ from 'lodash'; import _ from 'lodash';
import styled from 'styled-components'; import styled from 'styled-components';
import { import { FormTextField, FormSelectField, FormCheckboxField } from './forms';
FormTextField, import { useForm } from './FormProvider';
FormSubmit,
FormArchiveFolderSelect,
FormRow,
FormLabel,
FormSelectField,
FormCheckboxField,
} from './forms';
import { Formik, Form, useFormikContext } from 'formik';
const FormArgumentsWrapper = styled.div``; const FormArgumentsWrapper = styled.div``;
@@ -35,7 +27,7 @@ function FormArgument({ arg, namePrefix }) {
} }
export default function FormArgumentList({ args, onChangeValues = undefined, namePrefix }) { export default function FormArgumentList({ args, onChangeValues = undefined, namePrefix }) {
const { values } = useFormikContext(); const { values } = useForm();
React.useEffect(() => { React.useEffect(() => {
if (onChangeValues) onChangeValues(values); if (onChangeValues) onChangeValues(values);
}, [values]); }, [values]);

View File

@@ -0,0 +1,25 @@
import React from 'react';
const FormContext = React.createContext(null);
export function FormProvider({ children, initialValues }) {
const [values, setValues] = React.useState(initialValues);
const setFieldValue = React.useCallback(
(field, value) =>
setValues((v) => ({
...v,
[field]: value,
})),
[setValues]
);
const provider = {
values,
setValues,
setFieldValue,
};
return <FormContext.Provider value={provider}>{children}</FormContext.Provider>;
}
export function useForm() {
return React.useContext(FormContext);
}

View File

@@ -3,7 +3,6 @@ import styled from 'styled-components';
import Select from 'react-select'; import Select from 'react-select';
import Creatable from 'react-select/creatable'; import Creatable from 'react-select/creatable';
import { TextField, SelectField, CheckboxField } from './inputs'; import { TextField, SelectField, CheckboxField } from './inputs';
import { Field, useFormikContext } from 'formik';
import FormStyledButton from '../widgets/FormStyledButton'; import FormStyledButton from '../widgets/FormStyledButton';
import { import {
useConnectionList, useConnectionList,
@@ -12,10 +11,10 @@ import {
useArchiveFolders, useArchiveFolders,
useArchiveFiles, useArchiveFiles,
} from './metadataLoaders'; } from './metadataLoaders';
import useSocket from './SocketProvider';
import getAsArray from './getAsArray'; import getAsArray from './getAsArray';
import axios from './axios'; import axios from './axios';
import useTheme from '../theme/useTheme'; import useTheme from '../theme/useTheme';
import { useForm } from './FormProvider';
export const FormRow = styled.div` export const FormRow = styled.div`
display: flex; display: flex;
@@ -35,23 +34,32 @@ export const FormLabel = styled.div`
export const FormValue = styled.div``; export const FormValue = styled.div``;
export function FormTextFieldRaw({ ...other }) { export function FormTextFieldRaw({ name, focused = false, ...other }) {
return <Field {...other} as={TextField} />; const { values, setFieldValue } = useForm();
const handleChange = (event) => {
setFieldValue(name, event.target.value);
};
const textFieldRef = React.useRef(null);
React.useEffect(() => {
if (textFieldRef.current && focused) textFieldRef.current.focus();
}, [textFieldRef.current, focused]);
return <TextField {...other} value={values[name]} onChange={handleChange} editorRef={textFieldRef} />;
} }
export function FormTextField({ label, ...other }) { export function FormTextField({ name, label, focused = false, ...other }) {
return ( return (
<FormRow> <FormRow>
<FormLabel>{label}</FormLabel> <FormLabel>{label}</FormLabel>
<FormValue> <FormValue>
<FormTextFieldRaw {...other} /> <FormTextFieldRaw name={name} focused={focused} {...other} />
</FormValue> </FormValue>
</FormRow> </FormRow>
); );
} }
export function FormCheckboxFieldRaw({ name = undefined, defaultValue = undefined, ...other }) { export function FormCheckboxFieldRaw({ name = undefined, defaultValue = undefined, ...other }) {
const { values, setFieldValue } = useFormikContext(); const { values, setFieldValue } = useForm();
const handleChange = (event) => { const handleChange = (event) => {
setFieldValue(name, event.target.checked); setFieldValue(name, event.target.checked);
}; };
@@ -72,36 +80,43 @@ export function FormCheckboxField({ label, ...other }) {
); );
} }
export function FormSelectFieldRaw({ children, ...other }) { export function FormSelectFieldRaw({ children, name, ...other }) {
const { values, setFieldValue } = useForm();
const handleChange = (event) => {
setFieldValue(name, event.target.value);
};
return ( return (
<Field {...other} as={SelectField}> <SelectField {...other} value={values[name]} onChange={handleChange}>
{children} {children}
</Field> </SelectField>
); );
} }
export function FormSelectField({ label, children = null, ...other }) { export function FormSelectField({ label, name, children = null, ...other }) {
return ( return (
<FormRow> <FormRow>
<FormLabel>{label}</FormLabel> <FormLabel>{label}</FormLabel>
<FormValue> <FormValue>
<FormSelectFieldRaw {...other}>{children}</FormSelectFieldRaw> <FormSelectFieldRaw name={name} {...other}>
{children}
</FormSelectFieldRaw>
</FormValue> </FormValue>
</FormRow> </FormRow>
); );
} }
export function FormSubmit({ text }) { export function FormSubmit({ onClick, value, ...other }) {
return <FormStyledButton type="submit" value={text} />; const { values } = useForm();
return <FormStyledButton type="submit" value={value} onClick={() => onClick(values)} {...other} />;
} }
export function FormButton({ text, onClick, ...other }) { export function FormButton({ onClick, value, ...other }) {
const { values } = useFormikContext(); const { values } = useForm();
return <FormStyledButton type="button" value={text} onClick={() => onClick(values)} {...other} />; return <FormStyledButton type="button" value={value} onClick={() => onClick(values)} {...other} />;
} }
export function FormRadioGroupItem({ name, text, value }) { export function FormRadioGroupItem({ name, text, value }) {
const { setFieldValue, values } = useFormikContext(); const { setFieldValue, values } = useForm();
return ( return (
<div> <div>
<input <input
@@ -117,7 +132,7 @@ export function FormRadioGroupItem({ name, text, value }) {
} }
export function FormReactSelect({ options, name, isMulti = false, Component = Select, ...other }) { export function FormReactSelect({ options, name, isMulti = false, Component = Select, ...other }) {
const { setFieldValue, values } = useFormikContext(); const { setFieldValue, values } = useForm();
const theme = useTheme(); const theme = useTheme();
return ( return (
@@ -177,7 +192,7 @@ export function FormConnectionSelect({ name }) {
} }
export function FormDatabaseSelect({ conidName, name }) { export function FormDatabaseSelect({ conidName, name }) {
const { values } = useFormikContext(); const { values } = useForm();
const databases = useDatabaseList({ conid: values[conidName] }); const databases = useDatabaseList({ conid: values[conidName] });
const databaseOptions = React.useMemo( const databaseOptions = React.useMemo(
() => () =>
@@ -193,7 +208,7 @@ export function FormDatabaseSelect({ conidName, name }) {
} }
export function FormSchemaSelect({ conidName, databaseName, name }) { export function FormSchemaSelect({ conidName, databaseName, name }) {
const { values } = useFormikContext(); const { values } = useForm();
const dbinfo = useDatabaseInfo({ conid: values[conidName], database: values[databaseName] }); const dbinfo = useDatabaseInfo({ conid: values[conidName], database: values[databaseName] });
const schemaOptions = React.useMemo( const schemaOptions = React.useMemo(
() => () =>
@@ -209,7 +224,7 @@ export function FormSchemaSelect({ conidName, databaseName, name }) {
} }
export function FormTablesSelect({ conidName, databaseName, schemaName, name }) { export function FormTablesSelect({ conidName, databaseName, schemaName, name }) {
const { values } = useFormikContext(); const { values } = useForm();
const dbinfo = useDatabaseInfo({ conid: values[conidName], database: values[databaseName] }); const dbinfo = useDatabaseInfo({ conid: values[conidName], database: values[databaseName] });
const tablesOptions = React.useMemo( const tablesOptions = React.useMemo(
() => () =>
@@ -243,7 +258,7 @@ export function FormArchiveFilesSelect({ folderName, name }) {
} }
export function FormArchiveFolderSelect({ name, additionalFolders = [], ...other }) { export function FormArchiveFolderSelect({ name, additionalFolders = [], ...other }) {
const { setFieldValue } = useFormikContext(); const { setFieldValue } = useForm();
const folders = useArchiveFolders(); const folders = useArchiveFolders();
const folderOptions = React.useMemo( const folderOptions = React.useMemo(
() => [ () => [

View File

@@ -4,6 +4,7 @@ import styled from 'styled-components';
import { FontIcon } from '../icons'; import { FontIcon } from '../icons';
import dimensions from '../theme/dimensions'; import dimensions from '../theme/dimensions';
import useTheme from '../theme/useTheme'; import useTheme from '../theme/useTheme';
import { useForm } from '../utility/FormProvider';
const ButtonDiv = styled.div` const ButtonDiv = styled.div`
padding: 5px 15px; padding: 5px 15px;
@@ -58,3 +59,12 @@ export default function LargeButton({ children, onClick, icon = undefined, disab
</ButtonDiv> </ButtonDiv>
); );
} }
export function LargeFormButton({ children, onClick, icon = undefined, disabled = undefined }) {
const { values } = useForm();
return (
<LargeButton icon={icon} disabled={disabled} onClick={() => onClick(values)}>
{children}
</LargeButton>
);
}

View File

@@ -3932,11 +3932,6 @@ deep-is@~0.1.3:
resolved "https://registry.yarnpkg.com/deep-is/-/deep-is-0.1.3.tgz#b369d6fb5dbc13eecf524f91b070feedc357cf34" resolved "https://registry.yarnpkg.com/deep-is/-/deep-is-0.1.3.tgz#b369d6fb5dbc13eecf524f91b070feedc357cf34"
integrity sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ= integrity sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ=
deepmerge@^2.1.1:
version "2.2.1"
resolved "https://registry.yarnpkg.com/deepmerge/-/deepmerge-2.2.1.tgz#5d3ff22a01c00f645405a2fbc17d0778a1801170"
integrity sha512-R9hc1Xa/NOBi9WRVUWg19rl1UB7Tt4kuPd+thNJgFZoxXsTz7ncaPaeIm+40oSGuP33DfMb4sZt1QIGiJzC4EA==
default-gateway@^4.2.0: default-gateway@^4.2.0:
version "4.2.0" version "4.2.0"
resolved "https://registry.yarnpkg.com/default-gateway/-/default-gateway-4.2.0.tgz#167104c7500c2115f6dd69b0a536bb8ed720552b" resolved "https://registry.yarnpkg.com/default-gateway/-/default-gateway-4.2.0.tgz#167104c7500c2115f6dd69b0a536bb8ed720552b"
@@ -5230,20 +5225,6 @@ form-data@~2.3.2:
combined-stream "^1.0.6" combined-stream "^1.0.6"
mime-types "^2.1.12" mime-types "^2.1.12"
formik@^2.1.0:
version "2.1.3"
resolved "https://registry.yarnpkg.com/formik/-/formik-2.1.3.tgz#bd168011436393c8426a70cf8dfa5ddbbb95fd23"
integrity sha512-twK9sxWt+M2NSXxHBw6TiXNJ72iPVhgUUjeZMD8RYQC+VU7Hrxu6ElCz1xGmbT0q2DbHk4IxoupCkGEPwERzEA==
dependencies:
deepmerge "^2.1.1"
hoist-non-react-statics "^3.3.0"
lodash "^4.17.14"
lodash-es "^4.17.14"
react-fast-compare "^2.0.1"
scheduler "^0.18.0"
tiny-warning "^1.0.2"
tslib "^1.10.0"
forwarded@~0.1.2: forwarded@~0.1.2:
version "0.1.2" version "0.1.2"
resolved "https://registry.yarnpkg.com/forwarded/-/forwarded-0.1.2.tgz#98c23dab1175657b8c0573e8ceccd91b0ff18c84" resolved "https://registry.yarnpkg.com/forwarded/-/forwarded-0.1.2.tgz#98c23dab1175657b8c0573e8ceccd91b0ff18c84"
@@ -7317,11 +7298,6 @@ locate-path@^5.0.0:
dependencies: dependencies:
p-locate "^4.1.0" p-locate "^4.1.0"
lodash-es@^4.17.14:
version "4.17.15"
resolved "https://registry.yarnpkg.com/lodash-es/-/lodash-es-4.17.15.tgz#21bd96839354412f23d7a10340e5eac6ee455d78"
integrity sha512-rlrc3yU3+JNOpZ9zj5pQtxnx2THmvRykwL4Xlxoa8I9lHBlVbbyPhgyPMioxVZ4NqyxaVVtaJnzsyOidQIhyyQ==
lodash._reinterpolate@^3.0.0: lodash._reinterpolate@^3.0.0:
version "3.0.0" version "3.0.0"
resolved "https://registry.yarnpkg.com/lodash._reinterpolate/-/lodash._reinterpolate-3.0.0.tgz#0ccf2d89166af03b3663c796538b75ac6e114d9d" resolved "https://registry.yarnpkg.com/lodash._reinterpolate/-/lodash._reinterpolate-3.0.0.tgz#0ccf2d89166af03b3663c796538b75ac6e114d9d"
@@ -9770,11 +9746,6 @@ react-error-overlay@^6.0.5:
resolved "https://registry.yarnpkg.com/react-error-overlay/-/react-error-overlay-6.0.5.tgz#55d59c2a3810e8b41922e0b4e5f85dcf239bd533" resolved "https://registry.yarnpkg.com/react-error-overlay/-/react-error-overlay-6.0.5.tgz#55d59c2a3810e8b41922e0b4e5f85dcf239bd533"
integrity sha512-+DMR2k5c6BqMDSMF8hLH0vYKtKTeikiFW+fj0LClN+XZg4N9b8QUAdHC62CGWNLTi/gnuuemNcNcTFrCvK1f+A== integrity sha512-+DMR2k5c6BqMDSMF8hLH0vYKtKTeikiFW+fj0LClN+XZg4N9b8QUAdHC62CGWNLTi/gnuuemNcNcTFrCvK1f+A==
react-fast-compare@^2.0.1:
version "2.0.4"
resolved "https://registry.yarnpkg.com/react-fast-compare/-/react-fast-compare-2.0.4.tgz#e84b4d455b0fec113e0402c329352715196f81f9"
integrity sha512-suNP+J1VU1MWFKcyt7RtjiSWUjvidmQSlqu+eHslq+342xCbGTYmC0mEhPCOHxlW0CywylOC1u2DFAT+bv4dBw==
react-fast-compare@^3.1.1: react-fast-compare@^3.1.1:
version "3.2.0" version "3.2.0"
resolved "https://registry.yarnpkg.com/react-fast-compare/-/react-fast-compare-3.2.0.tgz#641a9da81b6a6320f270e89724fb45a0b39e43bb" resolved "https://registry.yarnpkg.com/react-fast-compare/-/react-fast-compare-3.2.0.tgz#641a9da81b6a6320f270e89724fb45a0b39e43bb"
@@ -11477,11 +11448,6 @@ timsort@^0.3.0:
resolved "https://registry.yarnpkg.com/timsort/-/timsort-0.3.0.tgz#405411a8e7e6339fe64db9a234de11dc31e02bd4" resolved "https://registry.yarnpkg.com/timsort/-/timsort-0.3.0.tgz#405411a8e7e6339fe64db9a234de11dc31e02bd4"
integrity sha1-QFQRqOfmM5/mTbmiNN4R3DHgK9Q= integrity sha1-QFQRqOfmM5/mTbmiNN4R3DHgK9Q=
tiny-warning@^1.0.2:
version "1.0.3"
resolved "https://registry.yarnpkg.com/tiny-warning/-/tiny-warning-1.0.3.tgz#94a30db453df4c643d0fd566060d60a875d84754"
integrity sha512-lBN9zLN/oAf68o3zNXYrdCt1kP8WsiGW8Oo2ka41b2IM5JL/S1CTyX1rW0mb/zSuJun0ZUrDxx4sqvYS2FWzPA==
tmp@^0.0.33: tmp@^0.0.33:
version "0.0.33" version "0.0.33"
resolved "https://registry.yarnpkg.com/tmp/-/tmp-0.0.33.tgz#6d34335889768d21b2bcda0aa277ced3b1bfadf9" resolved "https://registry.yarnpkg.com/tmp/-/tmp-0.0.33.tgz#6d34335889768d21b2bcda0aa277ced3b1bfadf9"
@@ -11607,7 +11573,7 @@ ts-pnp@1.1.5, ts-pnp@^1.1.2:
resolved "https://registry.yarnpkg.com/ts-pnp/-/ts-pnp-1.1.5.tgz#840e0739c89fce5f3abd9037bb091dbff16d9dec" resolved "https://registry.yarnpkg.com/ts-pnp/-/ts-pnp-1.1.5.tgz#840e0739c89fce5f3abd9037bb091dbff16d9dec"
integrity sha512-ti7OGMOUOzo66wLF3liskw6YQIaSsBgc4GOAlWRnIEj8htCxJUxskanMUoJOD6MDCRAXo36goXJZch+nOS0VMA== integrity sha512-ti7OGMOUOzo66wLF3liskw6YQIaSsBgc4GOAlWRnIEj8htCxJUxskanMUoJOD6MDCRAXo36goXJZch+nOS0VMA==
tslib@^1.10.0, tslib@^1.8.1, tslib@^1.9.0: tslib@^1.8.1, tslib@^1.9.0:
version "1.10.0" version "1.10.0"
resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.10.0.tgz#c3c19f95973fb0a62973fb09d90d961ee43e5c8a" resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.10.0.tgz#c3c19f95973fb0a62973fb09d90d961ee43e5c8a"
integrity sha512-qOebF53frne81cf0S9B41ByenJ3/IuH8yJKngAX35CmiZySA0khhkovshKK+jGCaMnVomla7gVlIcc3EvKPbTQ== integrity sha512-qOebF53frne81cf0S9B41ByenJ3/IuH8yJKngAX35CmiZySA0khhkovshKK+jGCaMnVomla7gVlIcc3EvKPbTQ==