Merge pull request #33 from provectus/redesign-topics-adding-custom-params-design

redesign-topics-adding-custom-params-design
This commit is contained in:
Azat Gataullin 2020-04-20 12:31:40 +03:00 committed by GitHub
commit fb9e9c580e
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 76 additions and 92 deletions

View file

@ -1,26 +1,20 @@
import React from 'react'; import React from 'react';
import CustomParamButton, { CustomParamButtonType } from './CustomParamButton'; import CustomParamButton, { CustomParamButtonType } from './CustomParamButton';
import { isFirstParam } from './CustomParams';
interface Props { interface Props {
index: string; index: string;
onAdd: (event: React.MouseEvent<HTMLButtonElement>) => void;
onRemove: (index: string) => void; onRemove: (index: string) => void;
} }
const CustomParamAction: React.FC<Props> = ({ const CustomParamAction: React.FC<Props> = ({ index, onRemove }) => (
index,
onAdd,
onRemove,
}) => (
<> <>
<label className='label'>&nbsp;</label> <label className="label">&nbsp;</label>
{ <CustomParamButton
isFirstParam(index) className="is-danger"
? <CustomParamButton className="is-success" type={CustomParamButtonType.plus} onClick={onAdd} /> type={CustomParamButtonType.minus}
: <CustomParamButton className="is-danger" type={CustomParamButtonType.minus} onClick={() => onRemove(index)} /> onClick={() => onRemove(index)}
} />
</> </>
) );
export default CustomParamAction; export default CustomParamAction;

View file

@ -6,21 +6,28 @@ export enum CustomParamButtonType {
} }
interface Props { interface Props {
onClick: (event: React.MouseEvent<HTMLButtonElement>) => void, onClick: (event: React.MouseEvent<HTMLButtonElement>) => void;
className: string; className: string;
type: CustomParamButtonType; type: CustomParamButtonType;
btnText?: string;
} }
const CustomParamButton: React.FC<Props> = ({ const CustomParamButton: React.FC<Props> = ({
onClick, onClick,
className, className,
type, type,
btnText,
}) => ( }) => (
<button className={`button ${className} is-outlined`} onClick={onClick}> <button
type="button"
className={`button ${className} is-outlined`}
onClick={onClick}
>
{btnText && <span>{btnText}</span>}
<span className="icon"> <span className="icon">
<i className={`fas fa-lg ${type}`}></i> <i className={`fas fa-lg ${type}`} />
</span> </span>
</button> </button>
) );
export default CustomParamButton; export default CustomParamButton;

View file

@ -1,8 +1,8 @@
import React from 'react'; import React from 'react';
import { useFormContext, ErrorMessage } from 'react-hook-form'; import { useFormContext, ErrorMessage } from 'react-hook-form';
import CustomParamOptions from './CustomParamOptions';
import { isFirstParam, INDEX_PREFIX } from './CustomParams';
import { TopicFormCustomParam } from 'redux/interfaces'; import { TopicFormCustomParam } from 'redux/interfaces';
import CustomParamOptions from './CustomParamOptions';
import { INDEX_PREFIX } from './CustomParams';
interface Props { interface Props {
isDisabled: boolean; isDisabled: boolean;
@ -10,19 +10,10 @@ interface Props {
name: string; name: string;
} }
const CustomParamSelect: React.FC<Props> = ({ const CustomParamSelect: React.FC<Props> = ({ isDisabled, index, name }) => {
isDisabled, const { register, errors, getValues, triggerValidation } = useFormContext();
index,
name,
}) => {
const { register, unregister, errors, getValues, triggerValidation } = useFormContext();
const optInputName = `${index}[name]`; const optInputName = `${index}[name]`;
React.useEffect(
() => { if (isFirstParam(index)) { unregister(optInputName) } },
);
const selectedMustBeUniq = (selected: string) => { const selectedMustBeUniq = (selected: string) => {
const values = getValues({ nest: true }); const values = getValues({ nest: true });
const customParamsValues: TopicFormCustomParam = values.customParams; const customParamsValues: TopicFormCustomParam = values.customParams;
@ -30,11 +21,12 @@ const CustomParamSelect: React.FC<Props> = ({
let valid = true; let valid = true;
for (const [key, customParam] of Object.entries(customParamsValues)) { for (const [key, customParam] of Object.entries(customParamsValues)) {
if (`${INDEX_PREFIX}.${key}` === index) { continue; } if (`${INDEX_PREFIX}.${key}` !== index) {
if (selected === customParam.name) { if (selected === customParam.name) {
valid = false; valid = false;
break; break;
}; }
}
} }
return valid ? true : 'Custom Parameter must be unique'; return valid ? true : 'Custom Parameter must be unique';
@ -48,7 +40,7 @@ const CustomParamSelect: React.FC<Props> = ({
name={optInputName} name={optInputName}
ref={register({ ref={register({
required: 'Custom Parameter is required.', required: 'Custom Parameter is required.',
validate: { unique: selected => selectedMustBeUniq(selected) }, validate: { unique: (selected) => selectedMustBeUniq(selected) },
})} })}
onChange={() => triggerValidation(optInputName)} onChange={() => triggerValidation(optInputName)}
disabled={isDisabled} disabled={isDisabled}

View file

@ -1,7 +1,6 @@
import React from 'react'; import React from 'react';
import { useFormContext, ErrorMessage } from 'react-hook-form'; import { useFormContext, ErrorMessage } from 'react-hook-form';
import { CUSTOM_PARAMS_OPTIONS } from './customParamsOptions'; import { CUSTOM_PARAMS_OPTIONS } from './customParamsOptions';
import { isFirstParam } from './CustomParams';
interface Props { interface Props {
isDisabled: boolean; isDisabled: boolean;
@ -16,7 +15,7 @@ const CustomParamValue: React.FC<Props> = ({
name, name,
defaultValue, defaultValue,
}) => { }) => {
const { register, unregister, errors, watch, setValue } = useFormContext(); const { register, errors, watch, setValue } = useFormContext();
const selectInputName = `${index}[name]`; const selectInputName = `${index}[name]`;
const valInputName = `${index}[value]`; const valInputName = `${index}[value]`;
const selectedParamName = watch(selectInputName, name); const selectedParamName = watch(selectInputName, name);
@ -31,12 +30,6 @@ const CustomParamValue: React.FC<Props> = ({
} }
}, [selectedParamName]); }, [selectedParamName]);
React.useEffect(() => {
if (isFirstParam(index)) {
unregister(valInputName);
}
});
return ( return (
<> <>
<label className="label">Value</label> <label className="label">Value</label>

View file

@ -5,22 +5,20 @@ import { TopicFormCustomParams } from 'redux/interfaces';
import CustomParamSelect from './CustomParamSelect'; import CustomParamSelect from './CustomParamSelect';
import CustomParamValue from './CustomParamValue'; import CustomParamValue from './CustomParamValue';
import CustomParamAction from './CustomParamAction'; import CustomParamAction from './CustomParamAction';
import CustomParamButton, { CustomParamButtonType } from './CustomParamButton';
const DEFAULT_INDEX = 'default';
export const INDEX_PREFIX = 'customParams'; export const INDEX_PREFIX = 'customParams';
export const isFirstParam = (index: string) => (index === DEFAULT_INDEX);
interface Props { interface Props {
isSubmitting: boolean; isSubmitting: boolean;
} }
const CustomParams: React.FC<Props> = ({ const CustomParams: React.FC<Props> = ({ isSubmitting }) => {
isSubmitting, const [formCustomParams, setFormCustomParams] = React.useState<
}) => { TopicFormCustomParams
>({
const [formCustomParams, setFormCustomParams] = React.useState<TopicFormCustomParams>({ byIndex: {},
byIndex: { [DEFAULT_INDEX]: { name: '', value: '' } }, allIndexes: [],
allIndexes: [DEFAULT_INDEX],
}); });
const onAdd = (event: React.MouseEvent<HTMLButtonElement>) => { const onAdd = (event: React.MouseEvent<HTMLButtonElement>) => {
@ -34,31 +32,36 @@ const CustomParams: React.FC<Props> = ({
...formCustomParams.byIndex, ...formCustomParams.byIndex,
[newIndex]: { name: '', value: '' }, [newIndex]: { name: '', value: '' },
}, },
allIndexes: [ allIndexes: [newIndex, ...formCustomParams.allIndexes],
formCustomParams.allIndexes[0],
newIndex,
...formCustomParams.allIndexes.slice(1),
],
}); });
} };
const onRemove = (index: string) => { const onRemove = (index: string) => {
setFormCustomParams({ setFormCustomParams({
...formCustomParams, ...formCustomParams,
byIndex: omit(formCustomParams.byIndex, index), byIndex: omit(formCustomParams.byIndex, index),
allIndexes: reject(formCustomParams.allIndexes, (i) => (i === index)), allIndexes: reject(formCustomParams.allIndexes, (i) => i === index),
}); });
} };
return ( return (
<> <>
{ <div className="columns">
formCustomParams.allIndexes.map((index) => ( <div className="column">
<CustomParamButton
className="is-success"
type={CustomParamButtonType.plus}
onClick={onAdd}
btnText="Add Custom Parameter"
/>
</div>
</div>
{formCustomParams.allIndexes.map((index) => (
<div className="columns is-centered" key={index}> <div className="columns is-centered" key={index}>
<div className="column"> <div className="column">
<CustomParamSelect <CustomParamSelect
index={index} index={index}
isDisabled={isFirstParam(index) || isSubmitting} isDisabled={isSubmitting}
name={formCustomParams.byIndex[index].name} name={formCustomParams.byIndex[index].name}
/> />
</div> </div>
@ -66,22 +69,17 @@ const CustomParams: React.FC<Props> = ({
<div className="column"> <div className="column">
<CustomParamValue <CustomParamValue
index={index} index={index}
isDisabled={isFirstParam(index) || isSubmitting} isDisabled={isSubmitting}
name={formCustomParams.byIndex[index].name} name={formCustomParams.byIndex[index].name}
defaultValue={formCustomParams.byIndex[index].value} defaultValue={formCustomParams.byIndex[index].value}
/> />
</div> </div>
<div className="column is-narrow"> <div className="column is-narrow">
<CustomParamAction <CustomParamAction index={index} onRemove={onRemove} />
index={index}
onAdd={onAdd}
onRemove={onRemove}
/>
</div> </div>
</div> </div>
)) ))}
}
</> </>
); );
}; };