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",
"eslint": "^6.8.0",
"eslint-plugin-react": "^7.17.0",
"formik": "^2.1.0",
"json-stable-stringify": "^1.0.1",
"localforage": "^1.9.0",
"react": "^16.12.0",

View File

@@ -6,8 +6,8 @@ import useDimensions from '../utility/useDimensions';
import { HorizontalSplitter } from '../widgets/Splitter';
import WidgetColumnBar, { WidgetColumnBarItem } from '../widgets/WidgetColumnBar';
import { FormCheckboxField, FormSelectField } from '../utility/forms';
import { Formik, Form } from 'formik';
import DataChart from './DataChart';
import { FormProvider } from '../utility/FormProvider';
const LeftContainer = styled.div`
background-color: ${(props) => props.theme.manager_background};
@@ -21,36 +21,34 @@ export default function ChartEditor({ data }) {
const availableColumnNames = data ? data.structure.columns.map((x) => x.columnName) : [];
return (
<Formik initialValues={{ chartType: 'bar' }} onSubmit={() => {}}>
<Form>
<HorizontalSplitter initialValue="300px" size={managerSize} setSize={setManagerSize}>
<LeftContainer theme={theme}>
<WidgetColumnBar>
<WidgetColumnBarItem title="Style" name="style" height="40%">
<FormSelectField label="Chart type" name="chartType">
<option value="bar">Bar</option>
<option value="line">Line</option>
</FormSelectField>
</WidgetColumnBarItem>
<WidgetColumnBarItem title="Data" name="data">
<FormSelectField label="Label column" name="labelColumn">
<option value=""></option>
{availableColumnNames.map((col) => (
<option value={col} key={col}>
{col}
</option>
))}
</FormSelectField>
<FormProvider initialValues={{ chartType: 'bar' }}>
<HorizontalSplitter initialValue="300px" size={managerSize} setSize={setManagerSize}>
<LeftContainer theme={theme}>
<WidgetColumnBar>
<WidgetColumnBarItem title="Style" name="style" height="40%">
<FormSelectField label="Chart type" name="chartType">
<option value="bar">Bar</option>
<option value="line">Line</option>
</FormSelectField>
</WidgetColumnBarItem>
<WidgetColumnBarItem title="Data" name="data">
<FormSelectField label="Label column" name="labelColumn">
<option value=""></option>
{availableColumnNames.map((col) => (
<FormCheckboxField label={col} name={`dataColumn_${col}`} key={col} />
<option value={col} key={col}>
{col}
</option>
))}
</WidgetColumnBarItem>
</WidgetColumnBar>
</LeftContainer>
</FormSelectField>
{availableColumnNames.map((col) => (
<FormCheckboxField label={col} name={`dataColumn_${col}`} key={col} />
))}
</WidgetColumnBarItem>
</WidgetColumnBar>
</LeftContainer>
<DataChart data={data} />
</HorizontalSplitter>
</Form>
</Formik>
<DataChart data={data} />
</HorizontalSplitter>
</FormProvider>
);
}

View File

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

View File

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

View File

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

View File

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

View File

@@ -1,15 +1,14 @@
import React from 'react';
import axios from '../utility/axios';
import ModalBase from './ModalBase';
import { FormButtonRow, FormButton, FormTextField, FormSelectField, FormSubmit } from '../utility/forms';
import { TextField } from '../utility/inputs';
import { Formik, Form } from 'formik';
import { FormButton, FormTextField, FormSelectField, FormSubmit } from '../utility/forms';
import ModalHeader from './ModalHeader';
import ModalFooter from './ModalFooter';
import ModalContent from './ModalContent';
import useExtensions from '../utility/useExtensions';
import LoadingInfo from '../widgets/LoadingInfo';
import { FontIcon } from '../icons';
import { FormProvider } from '../utility/FormProvider';
// import FormikForm from '../utility/FormikForm';
export default function ConnectionModal({ modalState, connection = undefined }) {
@@ -41,49 +40,47 @@ export default function ConnectionModal({ modalState, connection = undefined })
return (
<ModalBase modalState={modalState}>
<ModalHeader modalState={modalState}>{connection ? 'Edit connection' : 'Add connection'}</ModalHeader>
<Formik onSubmit={handleSubmit} initialValues={connection || { server: 'localhost', engine: 'mssql' }}>
<Form>
<ModalContent>
<FormSelectField label="Database engine" name="engine">
<option value=""></option>
{extensions.drivers.map((driver) => (
<option value={driver.engine} key={driver.engine}>
{driver.title}
</option>
))}
{/* <option value="mssql">Microsoft SQL Server</option>
<FormProvider initialValues={connection || { server: 'localhost', engine: 'mssql' }}>
<ModalContent>
<FormSelectField label="Database engine" name="engine">
<option value=""></option>
{extensions.drivers.map((driver) => (
<option value={driver.engine} key={driver.engine}>
{driver.title}
</option>
))}
{/* <option value="mssql">Microsoft SQL Server</option>
<option value="mysql">MySQL</option>
<option value="postgres">Postgre SQL</option> */}
</FormSelectField>
<FormTextField label="Server" name="server" />
<FormTextField label="Port" name="port" />
<FormTextField label="User" name="user" />
<FormTextField label="Password" name="password" type="password" />
<FormTextField label="Display name" name="displayName" />
{!isTesting && sqlConnectResult && sqlConnectResult.msgtype == 'connected' && (
<div>
Connected: <FontIcon icon="img ok" /> {sqlConnectResult.version}
</div>
)}
{!isTesting && sqlConnectResult && sqlConnectResult.msgtype == 'error' && (
<div>
Connect failed: <FontIcon icon="img error" /> {sqlConnectResult.error}
</div>
)}
{isTesting && <LoadingInfo message="Testing connection" />}
</ModalContent>
</FormSelectField>
<FormTextField label="Server" name="server" />
<FormTextField label="Port" name="port" />
<FormTextField label="User" name="user" />
<FormTextField label="Password" name="password" type="password" />
<FormTextField label="Display name" name="displayName" />
{!isTesting && sqlConnectResult && sqlConnectResult.msgtype == 'connected' && (
<div>
Connected: <FontIcon icon="img ok" /> {sqlConnectResult.version}
</div>
)}
{!isTesting && sqlConnectResult && sqlConnectResult.msgtype == 'error' && (
<div>
Connect failed: <FontIcon icon="img error" /> {sqlConnectResult.error}
</div>
)}
{isTesting && <LoadingInfo message="Testing connection" />}
</ModalContent>
<ModalFooter>
{isTesting ? (
<FormButton text="Cancel" onClick={handleCancel} />
) : (
<FormButton text="Test" onClick={handleTest} />
)}
<ModalFooter>
{isTesting ? (
<FormButton value="Cancel" onClick={handleCancel} />
) : (
<FormButton value="Test" onClick={handleTest} />
)}
<FormSubmit text="Save" />
</ModalFooter>
</Form>
</Formik>
<FormSubmit value="Save" onClick={handleSubmit} />
</ModalFooter>
</FormProvider>
</ModalBase>
);
}

View File

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

View File

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

View File

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

View File

@@ -3,10 +3,10 @@ import axios from '../utility/axios';
import ModalBase from './ModalBase';
import { FormButtonRow, FormButton, FormTextField, FormSelectField, FormSubmit } from '../utility/forms';
import { TextField } from '../utility/inputs';
import { Formik, Form } from 'formik';
import ModalHeader from './ModalHeader';
import ModalContent from './ModalContent';
import ModalFooter from './ModalFooter';
import { FormProvider } from '../utility/FormProvider';
// import FormikForm from '../utility/FormikForm';
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 (
<ModalBase modalState={modalState}>
<ModalHeader modalState={modalState}>Save file</ModalHeader>
<Formik onSubmit={handleSubmit} initialValues={{ name }}>
<Form>
<ModalContent>
<FormTextField label="File name" name="name" />
</ModalContent>
<ModalFooter>
<FormSubmit text="Save" />
</ModalFooter>
</Form>
</Formik>
<FormProvider initialValues={{ name }}>
<ModalContent>
<FormTextField label="File name" name="name" />
</ModalContent>
<ModalFooter>
<FormSubmit value="Save" onClick={handleSubmit} />
</ModalFooter>
</FormProvider>
</ModalBase>
);
}

View File

@@ -2,12 +2,19 @@ import React from 'react';
import ModalBase from './ModalBase';
import FormStyledButton from '../widgets/FormStyledButton';
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 ModalFooter from './ModalFooter';
import ModalContent from './ModalContent';
import { Formik, Form } from 'formik';
import { TextField } from '../utility/inputs';
import { FormProvider } from '../utility/FormProvider';
const Wrapper = styled.div`
display: flex;
@@ -104,30 +111,28 @@ export default function SetFilterModal({ modalState, onFilter, filterType, condi
return (
<ModalBase modalState={modalState}>
<Formik onSubmit={handleOk} initialValues={{ condition1, condition2: '=', joinOperator: ' ' }}>
<Form>
<ModalHeader modalState={modalState}>Set filter</ModalHeader>
<ModalContent>
<FormRow>Show rows where</FormRow>
<FormRow>
<Select filterType={filterType} name="condition1" />
<FormTextFieldRaw name="value1" editorRef={editorRef} />
</FormRow>
<FormRow>
<FormRadioGroupItem name="joinOperator" value=" " text="And" />
<FormRadioGroupItem name="joinOperator" value="," text="Or" />
</FormRow>
<FormRow>
<Select filterType={filterType} name="condition2" />
<FormTextFieldRaw name="value2" />
</FormRow>
</ModalContent>
<ModalFooter>
<FormSubmit text="OK" />
<FormStyledButton type="button" value="Close" onClick={modalState.close} />
</ModalFooter>
</Form>
</Formik>
<FormProvider initialValues={{ condition1, condition2: '=', joinOperator: ' ' }}>
<ModalHeader modalState={modalState}>Set filter</ModalHeader>
<ModalContent>
<FormRow>Show rows where</FormRow>
<FormRow>
<Select filterType={filterType} name="condition1" />
<FormTextFieldRaw name="value1" editorRef={editorRef} />
</FormRow>
<FormRow>
<FormRadioGroupItem name="joinOperator" value=" " text="And" />
<FormRadioGroupItem name="joinOperator" value="," text="Or" />
</FormRow>
<FormRow>
<Select filterType={filterType} name="condition2" />
<FormTextFieldRaw name="value2" />
</FormRow>
</ModalContent>
<ModalFooter>
<FormSubmit value="OK" onClick={handleOk} />
<FormStyledButton type="button" value="Close" onClick={modalState.close} />
</ModalFooter>
</FormProvider>
</ModalBase>
);
}

View File

@@ -1,16 +1,8 @@
import React from 'react';
import _ from 'lodash';
import styled from 'styled-components';
import {
FormTextField,
FormSubmit,
FormArchiveFolderSelect,
FormRow,
FormLabel,
FormSelectField,
FormCheckboxField,
} from './forms';
import { Formik, Form, useFormikContext } from 'formik';
import { FormTextField, FormSelectField, FormCheckboxField } from './forms';
import { useForm } from './FormProvider';
const FormArgumentsWrapper = styled.div``;
@@ -35,7 +27,7 @@ function FormArgument({ arg, namePrefix }) {
}
export default function FormArgumentList({ args, onChangeValues = undefined, namePrefix }) {
const { values } = useFormikContext();
const { values } = useForm();
React.useEffect(() => {
if (onChangeValues) onChangeValues(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 Creatable from 'react-select/creatable';
import { TextField, SelectField, CheckboxField } from './inputs';
import { Field, useFormikContext } from 'formik';
import FormStyledButton from '../widgets/FormStyledButton';
import {
useConnectionList,
@@ -12,10 +11,10 @@ import {
useArchiveFolders,
useArchiveFiles,
} from './metadataLoaders';
import useSocket from './SocketProvider';
import getAsArray from './getAsArray';
import axios from './axios';
import useTheme from '../theme/useTheme';
import { useForm } from './FormProvider';
export const FormRow = styled.div`
display: flex;
@@ -35,23 +34,32 @@ export const FormLabel = styled.div`
export const FormValue = styled.div``;
export function FormTextFieldRaw({ ...other }) {
return <Field {...other} as={TextField} />;
export function FormTextFieldRaw({ name, focused = false, ...other }) {
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 (
<FormRow>
<FormLabel>{label}</FormLabel>
<FormValue>
<FormTextFieldRaw {...other} />
<FormTextFieldRaw name={name} focused={focused} {...other} />
</FormValue>
</FormRow>
);
}
export function FormCheckboxFieldRaw({ name = undefined, defaultValue = undefined, ...other }) {
const { values, setFieldValue } = useFormikContext();
const { values, setFieldValue } = useForm();
const handleChange = (event) => {
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 (
<Field {...other} as={SelectField}>
<SelectField {...other} value={values[name]} onChange={handleChange}>
{children}
</Field>
</SelectField>
);
}
export function FormSelectField({ label, children = null, ...other }) {
export function FormSelectField({ label, name, children = null, ...other }) {
return (
<FormRow>
<FormLabel>{label}</FormLabel>
<FormValue>
<FormSelectFieldRaw {...other}>{children}</FormSelectFieldRaw>
<FormSelectFieldRaw name={name} {...other}>
{children}
</FormSelectFieldRaw>
</FormValue>
</FormRow>
);
}
export function FormSubmit({ text }) {
return <FormStyledButton type="submit" value={text} />;
export function FormSubmit({ onClick, value, ...other }) {
const { values } = useForm();
return <FormStyledButton type="submit" value={value} onClick={() => onClick(values)} {...other} />;
}
export function FormButton({ text, onClick, ...other }) {
const { values } = useFormikContext();
return <FormStyledButton type="button" value={text} onClick={() => onClick(values)} {...other} />;
export function FormButton({ onClick, value, ...other }) {
const { values } = useForm();
return <FormStyledButton type="button" value={value} onClick={() => onClick(values)} {...other} />;
}
export function FormRadioGroupItem({ name, text, value }) {
const { setFieldValue, values } = useFormikContext();
const { setFieldValue, values } = useForm();
return (
<div>
<input
@@ -117,7 +132,7 @@ export function FormRadioGroupItem({ name, text, value }) {
}
export function FormReactSelect({ options, name, isMulti = false, Component = Select, ...other }) {
const { setFieldValue, values } = useFormikContext();
const { setFieldValue, values } = useForm();
const theme = useTheme();
return (
@@ -177,7 +192,7 @@ export function FormConnectionSelect({ name }) {
}
export function FormDatabaseSelect({ conidName, name }) {
const { values } = useFormikContext();
const { values } = useForm();
const databases = useDatabaseList({ conid: values[conidName] });
const databaseOptions = React.useMemo(
() =>
@@ -193,7 +208,7 @@ export function FormDatabaseSelect({ conidName, name }) {
}
export function FormSchemaSelect({ conidName, databaseName, name }) {
const { values } = useFormikContext();
const { values } = useForm();
const dbinfo = useDatabaseInfo({ conid: values[conidName], database: values[databaseName] });
const schemaOptions = React.useMemo(
() =>
@@ -209,7 +224,7 @@ export function FormSchemaSelect({ conidName, databaseName, name }) {
}
export function FormTablesSelect({ conidName, databaseName, schemaName, name }) {
const { values } = useFormikContext();
const { values } = useForm();
const dbinfo = useDatabaseInfo({ conid: values[conidName], database: values[databaseName] });
const tablesOptions = React.useMemo(
() =>
@@ -243,7 +258,7 @@ export function FormArchiveFilesSelect({ folderName, name }) {
}
export function FormArchiveFolderSelect({ name, additionalFolders = [], ...other }) {
const { setFieldValue } = useFormikContext();
const { setFieldValue } = useForm();
const folders = useArchiveFolders();
const folderOptions = React.useMemo(
() => [

View File

@@ -4,6 +4,7 @@ import styled from 'styled-components';
import { FontIcon } from '../icons';
import dimensions from '../theme/dimensions';
import useTheme from '../theme/useTheme';
import { useForm } from '../utility/FormProvider';
const ButtonDiv = styled.div`
padding: 5px 15px;
@@ -58,3 +59,12 @@ export default function LargeButton({ children, onClick, icon = undefined, disab
</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"
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:
version "4.2.0"
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"
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:
version "0.1.2"
resolved "https://registry.yarnpkg.com/forwarded/-/forwarded-0.1.2.tgz#98c23dab1175657b8c0573e8ceccd91b0ff18c84"
@@ -7317,11 +7298,6 @@ locate-path@^5.0.0:
dependencies:
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:
version "3.0.0"
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"
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:
version "3.2.0"
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"
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:
version "0.0.33"
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"
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"
resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.10.0.tgz#c3c19f95973fb0a62973fb09d90d961ee43e5c8a"
integrity sha512-qOebF53frne81cf0S9B41ByenJ3/IuH8yJKngAX35CmiZySA0khhkovshKK+jGCaMnVomla7gVlIcc3EvKPbTQ==