Merge pull request #33 from provectus/redesign-topics-adding-custom-params-design
redesign-topics-adding-custom-params-design
This commit is contained in:
commit
fb9e9c580e
5 changed files with 76 additions and 92 deletions
|
@ -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'> </label>
|
<label className="label"> </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;
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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}
|
||||||
|
@ -57,7 +49,7 @@ const CustomParamSelect: React.FC<Props> = ({
|
||||||
<CustomParamOptions />
|
<CustomParamOptions />
|
||||||
</select>
|
</select>
|
||||||
<p className="help is-danger">
|
<p className="help is-danger">
|
||||||
<ErrorMessage errors={errors} name={optInputName}/>
|
<ErrorMessage errors={errors} name={optInputName} />
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
</>
|
</>
|
||||||
|
|
|
@ -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>
|
||||||
|
|
|
@ -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>
|
||||||
))
|
))}
|
||||||
}
|
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
Loading…
Add table
Reference in a new issue