refactor elements connection to store
This commit is contained in:
parent
9a299ba8cc
commit
0dc196fab3
@ -9,7 +9,7 @@
|
||||
"@testing-library/jest-dom": "^4.2.4",
|
||||
"@testing-library/react": "^9.3.2",
|
||||
"@testing-library/user-event": "^7.1.2",
|
||||
"antd": "^4.6.2",
|
||||
"antd": "^4.6.4",
|
||||
"axios": "^0.20.0",
|
||||
"body-parser": "^1.19.0",
|
||||
"class-validator": "^0.12.2",
|
||||
@ -22,7 +22,7 @@
|
||||
"http-errors": "^1.8.0",
|
||||
"lodash": "^4.17.20",
|
||||
"mobx": "^5.15.6",
|
||||
"mobx-react": "^6.2.5",
|
||||
"mobx-react": "^6.3.0",
|
||||
"morgan": "^1.10.0",
|
||||
"mssql": "^6.2.1",
|
||||
"nodemon": "^2.0.4",
|
||||
|
||||
@ -1,12 +1,13 @@
|
||||
import { Divider as AntDivider, Tabs } from 'antd';
|
||||
import Background from 'client/Elements/Background';
|
||||
import { SecondaryText, SecondaryColoredText } from 'client/Elements/Text';
|
||||
import { Flex, Box } from 'client/UIKit/grid';
|
||||
import { SecondaryColoredText } from 'client/Elements/Text';
|
||||
import { withStoreValue } from 'client/hocs/withStore';
|
||||
import colors from 'client/UIKit/colors';
|
||||
import { Flex } from 'client/UIKit/grid';
|
||||
import mq from 'client/UIKit/mq';
|
||||
import React from 'react';
|
||||
import styled from 'styled-components';
|
||||
import sectionsList from './list';
|
||||
import colors from 'client/UIKit/colors';
|
||||
import mq from 'client/UIKit/mq';
|
||||
|
||||
const ElementTitle = styled.h5`
|
||||
color: rgba(0, 0, 0, 0.75);
|
||||
@ -20,27 +21,18 @@ const BreakLine = styled.div`
|
||||
width: 100%;
|
||||
`;
|
||||
|
||||
const VerticalDivider = styled.div`
|
||||
${mq.desktop`
|
||||
width: 1px;
|
||||
margin: 6px 2px;
|
||||
background: rgb(0,0,0);
|
||||
background: linear-gradient(0deg, rgba(0,0,0,0) 0%, rgba(0,0,0,0.08) 20%, rgba(0,0,0,0.08) 80%, rgba(0,0,0,0) 100%);
|
||||
// background: rgba(0,0,0,0.12);
|
||||
`}
|
||||
`;
|
||||
|
||||
const BlockWrapper = styled.div`
|
||||
border: 1px solid black;
|
||||
`;
|
||||
|
||||
const renderElements = ({ elements }) => {
|
||||
return elements.map((element, ie) => {
|
||||
const { title: elementTitle, Component, props: elementProps } = element;
|
||||
const {
|
||||
title: elementTitle,
|
||||
Component: Element,
|
||||
props: elementProps,
|
||||
} = element;
|
||||
const Component = withStoreValue(Element)(elementProps);
|
||||
return (
|
||||
<Flex flexDirection="column" key={ie}>
|
||||
<ElementTitle>{elementTitle}</ElementTitle>
|
||||
<Component {...elementProps} />
|
||||
<Component />
|
||||
</Flex>
|
||||
);
|
||||
});
|
||||
@ -91,7 +83,7 @@ const renderGroups = ({ groups }) => {
|
||||
return (
|
||||
<React.Fragment key={ig}>
|
||||
{blocksTitle && (
|
||||
<AntDivider style={{ margin: '8px 0', color: colors.blueTemp[200] }}>
|
||||
<AntDivider style={{ margin: '16px 0', color: colors.blueTemp[200] }}>
|
||||
{blocksTitle}
|
||||
</AntDivider>
|
||||
)}
|
||||
@ -103,7 +95,7 @@ const renderGroups = ({ groups }) => {
|
||||
});
|
||||
};
|
||||
|
||||
const Sections = (props) => (
|
||||
const Sections = props => (
|
||||
<Background {...props}>
|
||||
<Tabs type="line">
|
||||
{sectionsList.map((section, is) => {
|
||||
|
||||
@ -1,15 +1,11 @@
|
||||
import { Button as AntButton } from 'antd';
|
||||
import { useStatus } from 'client/hooks/useStatus';
|
||||
import { Status } from 'core/types/statuses';
|
||||
import React from 'react';
|
||||
|
||||
const Button = ({ type, size, name, text, onClick }) => {
|
||||
const { status } = useStatus(name);
|
||||
|
||||
const Button = ({ status, onClick, text, ...props }) => {
|
||||
return (
|
||||
<AntButton
|
||||
type={type}
|
||||
size={size}
|
||||
{...props}
|
||||
disabled={status === Status.Disabled}
|
||||
onClick={onClick}
|
||||
>
|
||||
|
||||
@ -1,24 +1,13 @@
|
||||
import { Checkbox as AntCheckbox, Form } from 'antd';
|
||||
import { useStatus } from 'client/hooks/useStatus';
|
||||
import { useStoreValue } from 'client/hooks/useStoreValue';
|
||||
import { DEFAULT_DEBOUNCE_DELAY } from 'core/constants/debounce';
|
||||
import { Status } from 'core/types/statuses';
|
||||
import { observer } from 'mobx-react';
|
||||
import React from 'react';
|
||||
|
||||
const Checkbox = ({ name, readonly, valueName, computedValue }) => {
|
||||
const { value, setCurrentValue } = useStoreValue({
|
||||
computedValue,
|
||||
valueName,
|
||||
debounceDelay: DEFAULT_DEBOUNCE_DELAY,
|
||||
});
|
||||
const { status } = useStatus(name);
|
||||
|
||||
const Checkbox = ({ value, setCurrentValue, status, ...props }) => {
|
||||
return (
|
||||
<Form.Item>
|
||||
<AntCheckbox
|
||||
{...props}
|
||||
disabled={status === Status.Disabled}
|
||||
readonly={readonly}
|
||||
checked={value}
|
||||
onChange={e => setCurrentValue(e.target.checked)}
|
||||
/>
|
||||
@ -26,4 +15,4 @@ const Checkbox = ({ name, readonly, valueName, computedValue }) => {
|
||||
);
|
||||
};
|
||||
|
||||
export default observer(Checkbox);
|
||||
export default Checkbox;
|
||||
|
||||
@ -1,60 +1,20 @@
|
||||
import { Form, Input as AntInput } from 'antd';
|
||||
import { useStatus } from 'client/hooks/useStatus';
|
||||
import { useStoreValue } from 'client/hooks/useStoreValue';
|
||||
import { TEXT_INPUT_DEBOUNCE_DELAY } from 'core/constants/debounce';
|
||||
import { Status } from 'core/types/statuses';
|
||||
import { observer } from 'mobx-react';
|
||||
import React from 'react';
|
||||
import { useValidation } from 'client/hooks/useValidation';
|
||||
|
||||
const Input = ({
|
||||
name,
|
||||
readonly,
|
||||
type,
|
||||
validation,
|
||||
rules,
|
||||
pattern,
|
||||
prefix,
|
||||
suffix,
|
||||
placeholder,
|
||||
addonBefore,
|
||||
addonAfter,
|
||||
valueName,
|
||||
computedValue,
|
||||
value,
|
||||
setCurrentValue,
|
||||
status,
|
||||
validateStatus,
|
||||
message,
|
||||
...props
|
||||
}) => {
|
||||
const { value, setCurrentValue, debouncedValue } = useStoreValue({
|
||||
computedValue,
|
||||
valueName,
|
||||
debounceDelay: TEXT_INPUT_DEBOUNCE_DELAY,
|
||||
});
|
||||
const { status } = useStatus(name);
|
||||
|
||||
const { isValid, validateStatus, message } = useValidation({
|
||||
elementName: name,
|
||||
value: debouncedValue,
|
||||
validation: validation || {
|
||||
errorMessage: '',
|
||||
validator: () => {},
|
||||
},
|
||||
});
|
||||
|
||||
return (
|
||||
<Form.Item
|
||||
hasFeedback
|
||||
validateStatus={validateStatus}
|
||||
help={message}
|
||||
rules={rules}
|
||||
>
|
||||
<Form.Item hasFeedback validateStatus={validateStatus} help={message}>
|
||||
<AntInput
|
||||
prefix={prefix}
|
||||
suffix={suffix}
|
||||
{...props}
|
||||
disabled={status === Status.Disabled}
|
||||
readOnly={readonly}
|
||||
type={type}
|
||||
placeholder={placeholder}
|
||||
pattern={pattern}
|
||||
addonBefore={addonBefore}
|
||||
addonAfter={addonAfter}
|
||||
value={value}
|
||||
onChange={e => setCurrentValue(e.target.value)}
|
||||
/>
|
||||
@ -62,4 +22,4 @@ const Input = ({
|
||||
);
|
||||
};
|
||||
|
||||
export default observer(Input);
|
||||
export default Input;
|
||||
|
||||
@ -1,44 +1,14 @@
|
||||
import { InputNumber as AntInputNumber, Form } from 'antd';
|
||||
import { useStatus } from 'client/hooks/useStatus';
|
||||
import { useStoreValue } from 'client/hooks/useStoreValue';
|
||||
import { Form, InputNumber as AntInputNumber } from 'antd';
|
||||
import { Status } from 'core/types/statuses';
|
||||
import { observer } from 'mobx-react';
|
||||
import React from 'react';
|
||||
import { TEXT_INPUT_DEBOUNCE_DELAY } from 'core/constants/debounce';
|
||||
|
||||
const InputNumber = ({
|
||||
name,
|
||||
readonly,
|
||||
min,
|
||||
max,
|
||||
step,
|
||||
formatter,
|
||||
parser,
|
||||
placeholder,
|
||||
valueName,
|
||||
computedValue,
|
||||
}) => {
|
||||
const { value, setCurrentValue } = useStoreValue({
|
||||
computedValue,
|
||||
valueName,
|
||||
debounceDelay: TEXT_INPUT_DEBOUNCE_DELAY,
|
||||
});
|
||||
const { status } = useStatus(name);
|
||||
|
||||
const InputNumber = ({ value, setCurrentValue, status, ...props }) => {
|
||||
return (
|
||||
<Form.Item>
|
||||
<AntInputNumber
|
||||
{...props}
|
||||
disabled={status === Status.Disabled}
|
||||
readOnly={readonly}
|
||||
placeholder={placeholder}
|
||||
style={{
|
||||
width: '100%',
|
||||
}}
|
||||
min={min}
|
||||
max={max}
|
||||
step={step}
|
||||
formatter={formatter}
|
||||
parser={parser}
|
||||
style={styles}
|
||||
onChange={value => setCurrentValue(value)}
|
||||
value={value}
|
||||
/>
|
||||
@ -46,4 +16,8 @@ const InputNumber = ({
|
||||
);
|
||||
};
|
||||
|
||||
export default observer(InputNumber);
|
||||
const styles = {
|
||||
width: '100%',
|
||||
};
|
||||
|
||||
export default InputNumber;
|
||||
|
||||
@ -1,16 +1,12 @@
|
||||
import React from 'react';
|
||||
import styled from 'styled-components';
|
||||
import { useStoreValue } from 'client/hooks/useStoreValue';
|
||||
import { observer } from 'mobx-react';
|
||||
|
||||
const TextWrapper = styled.div``;
|
||||
const Text = styled.span`
|
||||
font-size: 0.85rem;
|
||||
`;
|
||||
|
||||
const Label = ({ name, computedValue, valueName }) => {
|
||||
const { value } = useStoreValue({ computedValue, valueName });
|
||||
|
||||
const Label = ({ value }) => {
|
||||
//TODO: Hide if no value
|
||||
|
||||
return (
|
||||
@ -20,4 +16,4 @@ const Label = ({ name, computedValue, valueName }) => {
|
||||
);
|
||||
};
|
||||
|
||||
export default observer(Label);
|
||||
export default Label;
|
||||
|
||||
@ -1,24 +1,19 @@
|
||||
import { Radio as AntRadio, Form } from 'antd';
|
||||
import { useOptions } from 'client/hooks/useOptions';
|
||||
import { useStatus } from 'client/hooks/useStatus';
|
||||
import { useStoreValue } from 'client/hooks/useStoreValue';
|
||||
import { DEFAULT_DEBOUNCE_DELAY } from 'core/constants/debounce';
|
||||
import { Form, Radio as AntRadio } from 'antd';
|
||||
import { Status } from 'core/types/statuses';
|
||||
import { observer } from 'mobx-react';
|
||||
import React from 'react';
|
||||
|
||||
const Radio = ({ name, style, computedValue, valueName }) => {
|
||||
const { value, setCurrentValue } = useStoreValue({
|
||||
computedValue,
|
||||
valueName,
|
||||
debounceDelay: DEFAULT_DEBOUNCE_DELAY,
|
||||
});
|
||||
const { status } = useStatus(name);
|
||||
const { options } = useOptions(name);
|
||||
|
||||
const Radio = ({
|
||||
value,
|
||||
setCurrentValue,
|
||||
status,
|
||||
options,
|
||||
style,
|
||||
...props
|
||||
}) => {
|
||||
return (
|
||||
<Form.Item>
|
||||
<AntRadio.Group
|
||||
{...props}
|
||||
disabled={status === Status.Disabled}
|
||||
buttonStyle={style === 'button' && 'solid'}
|
||||
value={value}
|
||||
@ -51,4 +46,4 @@ const styles = {
|
||||
},
|
||||
};
|
||||
|
||||
export default observer(Radio);
|
||||
export default Radio;
|
||||
|
||||
@ -1,26 +1,20 @@
|
||||
import { Select as AntSelect, Form } from 'antd';
|
||||
import { useStatus } from 'client/hooks/useStatus';
|
||||
import { useStoreValue } from 'client/hooks/useStoreValue';
|
||||
import { Form, Select as AntSelect } from 'antd';
|
||||
import { Status } from 'core/types/statuses';
|
||||
import { observer } from 'mobx-react';
|
||||
import React from 'react';
|
||||
import { useOptions } from 'client/hooks/useOptions';
|
||||
import { DEFAULT_DEBOUNCE_DELAY } from 'core/constants/debounce';
|
||||
|
||||
const Select = ({ name, showSearch, computedValue, valueName }) => {
|
||||
const { value, setCurrentValue } = useStoreValue({
|
||||
computedValue,
|
||||
valueName,
|
||||
debounceDelay: DEFAULT_DEBOUNCE_DELAY,
|
||||
});
|
||||
const { status } = useStatus(name);
|
||||
const { options, filter } = useOptions(name);
|
||||
|
||||
const Select = ({
|
||||
value,
|
||||
setCurrentValue,
|
||||
status,
|
||||
options,
|
||||
filter,
|
||||
...props
|
||||
}) => {
|
||||
return (
|
||||
<Form.Item>
|
||||
<AntSelect
|
||||
{...props}
|
||||
disabled={status === Status.Disabled}
|
||||
showSearch={showSearch}
|
||||
optionFilterProp="children"
|
||||
filterOption={filter}
|
||||
value={value}
|
||||
@ -40,4 +34,4 @@ const Select = ({ name, showSearch, computedValue, valueName }) => {
|
||||
);
|
||||
};
|
||||
|
||||
export default observer(Select);
|
||||
export default Select;
|
||||
|
||||
@ -1,22 +1,12 @@
|
||||
import { Form, Switch as AntSwitch } from 'antd';
|
||||
import { useStatus } from 'client/hooks/useStatus';
|
||||
import { useStoreValue } from 'client/hooks/useStoreValue';
|
||||
import { DEFAULT_DEBOUNCE_DELAY } from 'core/constants/debounce';
|
||||
import { Status } from 'core/types/statuses';
|
||||
import { observer } from 'mobx-react';
|
||||
import React from 'react';
|
||||
|
||||
const Switch = ({ name, valueName, computedValue }) => {
|
||||
const { value, setCurrentValue } = useStoreValue({
|
||||
computedValue,
|
||||
valueName,
|
||||
debounceDelay: DEFAULT_DEBOUNCE_DELAY,
|
||||
});
|
||||
const { status } = useStatus(name);
|
||||
|
||||
const Switch = ({ value, setCurrentValue, status, ...props }) => {
|
||||
return (
|
||||
<Form.Item>
|
||||
<AntSwitch
|
||||
{...props}
|
||||
disabled={status === Status.Disabled}
|
||||
checked={value}
|
||||
onChange={(checked, event) => {
|
||||
@ -27,4 +17,4 @@ const Switch = ({ name, valueName, computedValue }) => {
|
||||
);
|
||||
};
|
||||
|
||||
export default observer(Switch);
|
||||
export default Switch;
|
||||
|
||||
@ -1,35 +1,19 @@
|
||||
import { Input as AntInput } from 'antd';
|
||||
import { useStatus } from 'client/hooks/useStatus';
|
||||
import { useStoreValue } from 'client/hooks/useStoreValue';
|
||||
import { Form, Input as AntInput } from 'antd';
|
||||
import { Status } from 'core/types/statuses';
|
||||
import { observer } from 'mobx-react';
|
||||
import React from 'react';
|
||||
import { TEXT_INPUT_DEBOUNCE_DELAY } from 'core/constants/debounce';
|
||||
|
||||
const TextArea = ({
|
||||
name,
|
||||
readonly,
|
||||
placeholder,
|
||||
valueName,
|
||||
computedValue,
|
||||
}) => {
|
||||
const { value, setCurrentValue } = useStoreValue({
|
||||
computedValue,
|
||||
valueName,
|
||||
debounceDelay: TEXT_INPUT_DEBOUNCE_DELAY,
|
||||
});
|
||||
const { status } = useStatus(name);
|
||||
|
||||
const TextArea = ({ value, setCurrentValue, status, ...props }) => {
|
||||
return (
|
||||
<AntInput.TextArea
|
||||
autoSize={{ minRows: 5, maxRows: 8 }}
|
||||
disabled={status === Status.Disabled}
|
||||
readOnly={readonly}
|
||||
placeholder={placeholder}
|
||||
value={value}
|
||||
onChange={e => setCurrentValue(e.target.value)}
|
||||
/>
|
||||
<Form.Item>
|
||||
<AntInput.TextArea
|
||||
{...props}
|
||||
autoSize={{ minRows: 5, maxRows: 8 }}
|
||||
disabled={status === Status.Disabled}
|
||||
value={value}
|
||||
onChange={e => setCurrentValue(e.target.value)}
|
||||
/>
|
||||
</Form.Item>
|
||||
);
|
||||
};
|
||||
|
||||
export default observer(TextArea);
|
||||
export default TextArea;
|
||||
|
||||
47
src/client/hocs/withStore.js
Normal file
47
src/client/hocs/withStore.js
Normal file
@ -0,0 +1,47 @@
|
||||
import { useOptions } from 'client/hooks/useOptions';
|
||||
import { useStatus } from 'client/hooks/useStatus';
|
||||
import { useStoreValue } from 'client/hooks/useStoreValue';
|
||||
import { useValidation } from 'client/hooks/useValidation';
|
||||
import { DEFAULT_DEBOUNCE_DELAY } from 'core/constants/debounce';
|
||||
import { observer } from 'mobx-react';
|
||||
import React from 'react';
|
||||
|
||||
export const withStoreValue = Component => ({
|
||||
name,
|
||||
valueName,
|
||||
computedValue,
|
||||
validation,
|
||||
...params
|
||||
}) => {
|
||||
const ComponentWithStore = () => {
|
||||
const { value, setCurrentValue, debouncedValue } = useStoreValue({
|
||||
computedValue,
|
||||
valueName,
|
||||
debounceDelay: DEFAULT_DEBOUNCE_DELAY,
|
||||
});
|
||||
const { status } = useStatus(name);
|
||||
const { isValid, validateStatus, message } = useValidation({
|
||||
elementName: name,
|
||||
value: debouncedValue,
|
||||
validation: validation || {
|
||||
errorMessage: '',
|
||||
validator: () => {},
|
||||
},
|
||||
});
|
||||
const { options, filter } = useOptions(name);
|
||||
|
||||
return (
|
||||
<Component
|
||||
value={value}
|
||||
setCurrentValue={setCurrentValue}
|
||||
status={status}
|
||||
validateStatus={validateStatus}
|
||||
message={message}
|
||||
options={options}
|
||||
filter={filter}
|
||||
{...params}
|
||||
/>
|
||||
);
|
||||
};
|
||||
return observer(ComponentWithStore);
|
||||
};
|
||||
@ -1,25 +0,0 @@
|
||||
import React, { ComponentType } from "react";
|
||||
// import hoistNonReactStatics from "hoist-non-react-statics";
|
||||
import { useStores } from "../hooks/useStores";
|
||||
import { useObserver } from "mobx-react";
|
||||
|
||||
export type TWithStoreHOC = <P extends unknown>(
|
||||
Component: ComponentType<P>
|
||||
) => (props: P) => JSX.Element;
|
||||
|
||||
export const withStore: TWithStoreHOC = (WrappedComponent) => (props) => {
|
||||
const ComponentWithStore = () => {
|
||||
const stores = useStores();
|
||||
|
||||
return <WrappedComponent {...props} stores={stores} />;
|
||||
};
|
||||
|
||||
ComponentWithStore.defaultProps = { ...WrappedComponent.defaultProps };
|
||||
ComponentWithStore.displayName = `WithStores(${
|
||||
WrappedComponent.name || WrappedComponent.displayName
|
||||
})`;
|
||||
|
||||
// hoistNonReactStatics(ComponentWithStore, WrappedComponent);
|
||||
|
||||
return <ComponentWithStore />;
|
||||
};
|
||||
@ -1,2 +1 @@
|
||||
export const TEXT_INPUT_DEBOUNCE_DELAY = 650;
|
||||
export const DEFAULT_DEBOUNCE_DELAY = 0;
|
||||
export const DEFAULT_DEBOUNCE_DELAY = 250;
|
||||
|
||||
Reference in New Issue
Block a user