From abeb3f95d93102d4e701c37043f4e2765ffdfb26 Mon Sep 17 00:00:00 2001 From: Victor Tavares <7974934+victorkt@users.noreply.github.com> Date: Sat, 25 Apr 2020 10:56:51 +0100 Subject: [PATCH] fix: constraint type when editing was always string (#61) * fix: constraint type when editing was always string * remove console.log * fixes --- .../ConstraintFields/ConstraintFields.js | 12 +-- .../DistributionFields/DistributionFields.js | 2 +- web/src/helpers/index.js | 19 +++++ web/src/{views/FlagForm => helpers}/models.js | 74 ++++++++++++++----- web/src/views/FlagForm/FlagForm.js | 2 +- .../components/FlagDetails/FlagDetails.js | 2 +- .../components/RuleFields/RuleFields.js | 2 +- .../components/VariantFields/VariantFields.js | 2 +- .../components/FlagsToolbar/AddFlagButton.js | 2 +- web/src/views/SegmentForm/SegmentForm.js | 4 +- .../components/RuleFields/RuleFields.js | 2 +- .../SegmentDetails/SegmentDetails.js | 5 +- web/src/views/SegmentForm/models.js | 51 ------------- 13 files changed, 93 insertions(+), 86 deletions(-) rename web/src/{views/FlagForm => helpers}/models.js (71%) delete mode 100644 web/src/views/SegmentForm/models.js diff --git a/web/src/components/ConstraintFields/ConstraintFields.js b/web/src/components/ConstraintFields/ConstraintFields.js index d54460f..69fb345 100644 --- a/web/src/components/ConstraintFields/ConstraintFields.js +++ b/web/src/components/ConstraintFields/ConstraintFields.js @@ -16,7 +16,7 @@ import RemoveIcon from '@material-ui/icons/RemoveCircleOutline'; import AddIcon from '@material-ui/icons/AddCircleOutline'; import { makeStyles } from '@material-ui/styles'; import ChipInput from 'material-ui-chip-input' -import { VariantTypes } from '../../views/FlagForm/models'; +import { VariantTypes } from '../../helpers'; import { VariantType } from '../../views/FlagForm/copy'; const useStyles = makeStyles(theme => ({ @@ -147,11 +147,11 @@ const ConstraintFields = props => { required onChange={e => { onUpdateConstraint(e); - switch (e.target.value) { - case VariantTypes.BOOLEAN: - return onUpdateConstraint({ target: { name: 'values', value: [false] } }); - default: - return onUpdateConstraint({ target: { name: 'values', value: [] } }); + // reset constraint value + if (e.target.value === VariantTypes.BOOLEAN) { + return onUpdateConstraint({ target: { name: 'values', value: [false] } }); + } else { + return onUpdateConstraint({ target: { name: 'values', value: [] } }); } }} labelWidth={30} diff --git a/web/src/components/DistributionFields/DistributionFields.js b/web/src/components/DistributionFields/DistributionFields.js index 7bbdcb8..73a5f5e 100644 --- a/web/src/components/DistributionFields/DistributionFields.js +++ b/web/src/components/DistributionFields/DistributionFields.js @@ -3,7 +3,7 @@ import { Chip, Grid, TextField, Typography } from '@material-ui/core'; import { makeStyles } from '@material-ui/styles'; import PropTypes from 'prop-types'; import { isNumber } from 'lodash'; -import { VariantTypes } from '../../views/FlagForm/models'; +import { VariantTypes } from '../../helpers'; import { BooleanType } from '../../views/FlagForm/copy'; const useStyles = makeStyles(theme => ({ diff --git a/web/src/helpers/index.js b/web/src/helpers/index.js index 08559dc..7a5e180 100755 --- a/web/src/helpers/index.js +++ b/web/src/helpers/index.js @@ -1 +1,20 @@ export { cast } from './cast'; +export { + newFlag, + newVariant, + newRule, + newConstraint, + newDistribution, + formatFlag, + formatVariant, + formatRule, + formatConstraint, + formatDistribution, + newSegment, + newSegmentRule, + formatSegment, + formatSegmentRule, + OperationTypes, + PercentageRollout, + VariantTypes, +} from './models'; diff --git a/web/src/views/FlagForm/models.js b/web/src/helpers/models.js similarity index 71% rename from web/src/views/FlagForm/models.js rename to web/src/helpers/models.js index a7fdcab..e4c3188 100644 --- a/web/src/views/FlagForm/models.js +++ b/web/src/helpers/models.js @@ -1,13 +1,24 @@ import { v1 as uuid } from 'uuid'; import { get, isArray, isNil } from 'lodash'; -import { Operations, VariantType } from './copy'; -import { cast } from '../../helpers'; - -export const OperationTypes = Object.keys(Operations) - .reduce((ops, op) => ({ ...ops, [op]: op }), {}); - -export const VariantTypes = Object.keys(VariantType) - .reduce((vts, vt) => ({ ...vts, [vt]: vt.toLowerCase() }), {}); +import { cast } from '.'; + +const Operations = [ + 'ONE_OF', 'NOT_ONE_OF', + 'GREATER', 'GREATER_OR_EQUAL', + 'LOWER', 'LOWER_OR_EQUAL', + 'EXISTS', 'DOESNT_EXIST', + 'CONTAINS', 'DOESNT_CONTAIN', + 'STARTS_WITH', 'DOESNT_START_WITH', + 'ENDS_WITH', 'DOESNT_END_WITH', + 'MATCHES_REGEX', 'DOESNT_MATCH_REGEX', + 'IS_IN_SEGMENT', 'ISNT_IN_SEGMENT', + 'IS_IN_NETWORK', +]; +export const OperationTypes = Operations.reduce((ops, op) => ( + { ...ops, [op]: op } +), {}); + +export const VariantTypes = { BOOLEAN: 'boolean', NUMBER: 'number', STRING: 'string' }; export const PercentageRollout = 'ROLLOUT'; @@ -65,15 +76,18 @@ export const newRule = (rule = {}, variants) => { } }; -export const newConstraint = (constraint = {}) => ({ - __new: !constraint.id, - id: constraint.id || uuid(), - property: constraint.property || '', - operation: constraint.operation || OperationTypes.ONE_OF, - values: constraint.values || [], - type: constraint.type !== undefined ? constraint.type : - constraint.value !== undefined ? typeof constraint.value : VariantTypes.STRING, -}); +export const newConstraint = (constraint = {}) => { + const values = constraint.values || []; + return { + __new: !constraint.id, + id: constraint.id || uuid(), + property: constraint.property || '', + operation: constraint.operation || OperationTypes.ONE_OF, + values, + type: constraint.type !== undefined ? constraint.type : + values[0] !== undefined ? typeof values[0] : VariantTypes.STRING, + } +}; export const newDistribution = (distribution = {}) => ({ __new: !distribution.id, @@ -117,6 +131,32 @@ export const formatDistribution = (distribution, variantsRef) => ({ percentage: distribution.percentage, }); +export const newSegment = (segment = {}) => ({ + __new: !segment.id, + id: segment.id || uuid(), + name: segment.name || '', + description: segment.description || '', + rules: segment.rules ? segment.rules.map(r => newSegmentRule(r)) : [], +}); + +export const newSegmentRule = (rule = {}) => ({ + __new: !rule.id, + id: rule.id || uuid(), + constraints: rule.constraints ? + rule.constraints.map(c => newConstraint(c)) : + [newConstraint()], +}); + +export const formatSegment = segment => ({ + key: segment.key, + name: segment.name, + description: segment.description, +}); + +export const formatSegmentRule = rule => ({ + constraints: rule.constraints.map(c => formatConstraint(c)), +}); + const createNewVariants = (type) => { switch (type) { case VariantTypes.NUMBER: diff --git a/web/src/views/FlagForm/FlagForm.js b/web/src/views/FlagForm/FlagForm.js index edfe021..604e716 100755 --- a/web/src/views/FlagForm/FlagForm.js +++ b/web/src/views/FlagForm/FlagForm.js @@ -17,7 +17,7 @@ import { UPDATE_FLAG_RULE_QUERY, UPDATE_VARIANT_QUERY, } from './queries'; -import { formatFlag, formatRule, formatVariant, newFlag, VariantTypes } from './models'; +import { formatFlag, formatRule, formatVariant, newFlag, VariantTypes } from '../../helpers'; const useStyles = makeStyles(theme => ({ root: { diff --git a/web/src/views/FlagForm/components/FlagDetails/FlagDetails.js b/web/src/views/FlagForm/components/FlagDetails/FlagDetails.js index 56981a5..7ded0a1 100755 --- a/web/src/views/FlagForm/components/FlagDetails/FlagDetails.js +++ b/web/src/views/FlagForm/components/FlagDetails/FlagDetails.js @@ -25,7 +25,7 @@ import { Link } from 'react-router-dom'; import { reject, set } from 'lodash'; import slugify from '@sindresorhus/slugify'; import { DeleteFlagDialog, RuleFields, VariantFields } from '../'; -import { newConstraint, newFlag, newRule, newVariant, VariantTypes } from '../../models'; +import { newConstraint, newFlag, newRule, newVariant, VariantTypes } from '../../../../helpers'; import { BooleanType } from '../../copy'; const AllowMaxVariants = 5; diff --git a/web/src/views/FlagForm/components/RuleFields/RuleFields.js b/web/src/views/FlagForm/components/RuleFields/RuleFields.js index 45bd1d7..0a3d46b 100644 --- a/web/src/views/FlagForm/components/RuleFields/RuleFields.js +++ b/web/src/views/FlagForm/components/RuleFields/RuleFields.js @@ -7,7 +7,7 @@ import ConstraintFields from '../../../../components/ConstraintFields'; import DistributionFields from '../../../../components/DistributionFields'; import * as copy from '../../copy'; import { BooleanType } from '../../copy'; -import { OperationTypes, PercentageRollout, VariantTypes } from '../../models'; +import { OperationTypes, PercentageRollout, VariantTypes } from '../../../../helpers'; const AllowMaxConstraints = 5; diff --git a/web/src/views/FlagForm/components/VariantFields/VariantFields.js b/web/src/views/FlagForm/components/VariantFields/VariantFields.js index 3e8e888..42f531a 100644 --- a/web/src/views/FlagForm/components/VariantFields/VariantFields.js +++ b/web/src/views/FlagForm/components/VariantFields/VariantFields.js @@ -14,7 +14,7 @@ import { import { makeStyles } from '@material-ui/styles'; import RemoveIcon from '@material-ui/icons/RemoveCircleOutline'; import AddIcon from '@material-ui/icons/AddCircleOutline'; -import { VariantTypes } from '../../models'; +import { VariantTypes } from '../../../../helpers'; import { BooleanType, VariantType } from '../../copy'; const useStyles = makeStyles(theme => ({ diff --git a/web/src/views/FlagList/components/FlagsToolbar/AddFlagButton.js b/web/src/views/FlagList/components/FlagsToolbar/AddFlagButton.js index aa71a90..8628466 100644 --- a/web/src/views/FlagList/components/FlagsToolbar/AddFlagButton.js +++ b/web/src/views/FlagList/components/FlagsToolbar/AddFlagButton.js @@ -10,7 +10,7 @@ import MenuItem from '@material-ui/core/MenuItem'; import MenuList from '@material-ui/core/MenuList'; import { makeStyles } from '@material-ui/styles'; import { Link } from 'react-router-dom'; -import { VariantTypes } from '../../../FlagForm/models'; +import { VariantTypes } from '../../../../helpers'; const options = [ { name: 'Add boolean flag', to: { pathname: '/flags/new', flagType: VariantTypes.BOOLEAN } }, diff --git a/web/src/views/SegmentForm/SegmentForm.js b/web/src/views/SegmentForm/SegmentForm.js index 7a88207..2856356 100755 --- a/web/src/views/SegmentForm/SegmentForm.js +++ b/web/src/views/SegmentForm/SegmentForm.js @@ -14,7 +14,7 @@ import { UPDATE_SEGMENT_QUERY, UPDATE_SEGMENT_RULE_QUERY, } from './queries'; -import { formatRule, formatSegment, newSegment } from './models'; +import { formatSegmentRule, formatSegment, newSegment } from '../../helpers'; const useStyles = makeStyles(theme => ({ root: { @@ -59,7 +59,7 @@ const SegmentForm = () => { const variables = { id: rule.id, segmentId: segment.id, - input: formatRule(rule, variantsRef), + input: formatSegmentRule(rule, variantsRef), }; if (rule.__new) { return createRule({ variables }); diff --git a/web/src/views/SegmentForm/components/RuleFields/RuleFields.js b/web/src/views/SegmentForm/components/RuleFields/RuleFields.js index d4593bf..adb47e2 100644 --- a/web/src/views/SegmentForm/components/RuleFields/RuleFields.js +++ b/web/src/views/SegmentForm/components/RuleFields/RuleFields.js @@ -5,7 +5,7 @@ import { makeStyles } from '@material-ui/styles'; import DeleteOutlineIcon from '@material-ui/icons/DeleteOutline'; import ConstraintFields from '../../../../components/ConstraintFields'; import * as copy from '../../copy'; -import { OperationTypes } from '../../models'; +import { OperationTypes } from '../../../../helpers'; const AllowMaxConstraints = 5; diff --git a/web/src/views/SegmentForm/components/SegmentDetails/SegmentDetails.js b/web/src/views/SegmentForm/components/SegmentDetails/SegmentDetails.js index 33c56d3..93c13e0 100755 --- a/web/src/views/SegmentForm/components/SegmentDetails/SegmentDetails.js +++ b/web/src/views/SegmentForm/components/SegmentDetails/SegmentDetails.js @@ -17,7 +17,7 @@ import DeleteIcon from '@material-ui/icons/Delete'; import { Link } from 'react-router-dom'; import { reject, set } from 'lodash'; import { DeleteSegmentDialog, RuleFields } from '../'; -import { newConstraint, newRule } from '../../models'; +import { newConstraint, newSegmentRule } from '../../../../helpers'; const AllowMaxRules = 5; @@ -40,8 +40,7 @@ const SegmentDetails = props => { const [deletedItems, setDeletedItems] = React.useState([]); const classes = useStyles(); - // TODO: delete segments from flag rules - const handleAddRule = () => setSegment({ ...segment, rules: [...segment.rules, newRule()] }); + const handleAddRule = () => setSegment({ ...segment, rules: [...segment.rules, newSegmentRule()] }); const handleDelRule = rule => () => { setDeletedItems([...deletedItems, { type: 'rule', id: rule.id, segmentId: segment.id }]); setSegment({ ...segment, rules: reject(segment.rules, r => r === rule) }); diff --git a/web/src/views/SegmentForm/models.js b/web/src/views/SegmentForm/models.js deleted file mode 100644 index d1f6aba..0000000 --- a/web/src/views/SegmentForm/models.js +++ /dev/null @@ -1,51 +0,0 @@ -import { v1 as uuid } from 'uuid'; -import { isArray } from 'lodash'; -import { Operations } from './copy'; -import { VariantTypes } from '../FlagForm/models'; -import { cast } from '../../helpers'; - -export const OperationTypes = Object.keys(Operations) - .reduce((ops, op) => ({ ...ops, [op]: op }), {}); - -export const newSegment = (segment = {}) => ({ - __new: !segment.id, - id: segment.id || uuid(), - name: segment.name || '', - description: segment.description || '', - rules: segment.rules ? segment.rules.map(r => newRule(r)) : [], -}); - -export const newRule = (rule = {}) => ({ - __new: !rule.id, - id: rule.id || uuid(), - constraints: rule.constraints ? - rule.constraints.map(c => newConstraint(c)) : - [newConstraint()], -}); - -export const newConstraint = (constraint = {}) => ({ - __new: !constraint.id, - id: constraint.id || uuid(), - property: constraint.property || '', - operation: constraint.operation || OperationTypes.ONE_OF, - values: constraint.values || [], - type: constraint.type !== undefined ? constraint.type : - constraint.value !== undefined ? typeof constraint.value : VariantTypes.STRING, -}); - -export const formatSegment = segment => ({ - key: segment.key, - name: segment.name, - description: segment.description, -}); - -export const formatRule = rule => ({ - constraints: rule.constraints.map(c => formatConstraint(c)), -}); - -export const formatConstraint = constraint => ({ - property: constraint.property, - operation: constraint.operation, - values: isArray(constraint.values) && constraint.values.length > 0 ? - constraint.values.map(v => cast(v, constraint.type)) : [], -});