import React, { Fragment } from 'react'; import { set } from 'react-redux-values'; import { Margin } from 'styled-components-spacing'; import { compose } from 'react-apollo'; import { destroy, reset } from 'redux-form'; import ReduxForm from 'declarative-redux-form'; import { connect } from 'react-redux'; import get from 'lodash.get'; import remcalc from 'remcalc'; import { AffinityIcon, Button, H3, Divider, KeyValue } from 'joyent-ui-toolkit'; import Title from '@components/create-instance/title'; import { Rule, Header } from '@components/create-instance/affinity'; import Description from '@components/description'; import { fieldError } from '@root/constants'; const FORM_NAME_CREATE = 'CREATE-INSTANCE-AFFINITY-ADD'; const FORM_NAME_EDIT = i => `CREATE-INSTANCE-AFFINITY-EDIT-${i}`; const RULE_DEFAULTS = { 'rule-instance-name': '', 'rule-instance-conditional': 'must', 'rule-instance-placement': 'same', 'rule-instance-tag-key-pattern': 'equalling', 'rule-instance-tag-value-pattern': 'equalling', 'rule-instance-name-pattern': 'equalling', 'rule-instance-tag-value': '', 'rule-instance-tag-key': '', 'rule-type': 'name' }; export const Affinity = ({ affinityRules = [], expanded, proceeded, addOpen, handleAddAffinityRules, handleRemoveAffinityRule, handleUpdateAffinityRule, shouldAsyncValidate, handleAsyncValidation, handleToggleExpanded, handleCancelEdit, handleChangeAddOpen, handleEdit, rule, step }) => ( } > Affinity {expanded ? ( Control placement of instances on the physical servers. Design applications to adapt at failure by distributing application components. Instances are only provisioned when the exact criteria is met.{' '} Read the docs ) : null} {proceeded ? (

{affinityRules.length} Affinity Rule

) : null} {affinityRules.map((rule, index) => ( handleUpdateAffinityRule(index, newValue)} > {props => ( } method="edit" input={props => } type="an affinity rule" onToggleExpanded={() => handleToggleExpanded(index)} onCancel={() => handleCancelEdit(index)} onRemove={() => handleRemoveAffinityRule(index)} /> )} ))} {props => expanded && addOpen ? ( } type="an affinity rule" expanded noRemove onCancel={() => handleChangeAddOpen(false)} /> ) : null } {expanded ? ( {!addOpen && affinityRules.length === 0 ? ( ) : null} ) : proceeded ? ( ) : null} {expanded || proceeded ? : null}
); export default compose( connect(({ values, form }, ownProps) => { const proceeded = get(values, 'create-instance-affinity-proceeded', false); const addOpen = get(values, 'create-instance-affinity-add-open', false); const affinityRules = get(values, 'create-instance-affinity', []); const rule = get(form, `${FORM_NAME_CREATE}.values`, {}); return { proceeded: proceeded || affinityRules.length, addOpen, affinityRules, rule }; }), connect(null, (dispatch, { affinityRules = [], rule, history }) => ({ shouldAsyncValidate: ({ trigger }) => trigger === 'change', handleAsyncValidation: async rule => { const validName = /^[a-zA-Z_.-]{1,16}$/.test(rule['rule-instance-name']); const validKey = /^[a-zA-Z_.-]{1,16}$/.test( rule['rule-instance-tag-key'] ); const validValue = /^[a-zA-Z_.-]{1,16}$/.test( rule['rule-instance-tag-value'] ); if (validName && validKey && validValue) { return; } // eslint-disable-next-line no-throw-literal throw { 'rule-instance-name': fieldError, 'rule-instance-tag-key': fieldError, 'rule-instance-tag-value': fieldError }; }, handleEdit: () => { return history.push(`/~create/affinity${history.location.search}`); }, handleAddAffinityRules: ({ ...rule }) => { const toggleToClosed = set({ name: `create-instance-affinity-add-open`, value: false }); const appendAffinityRule = set({ name: `create-instance-affinity`, value: affinityRules.concat([ { ...RULE_DEFAULTS, ...rule, expanded: false } ]) }); return dispatch([ destroy(FORM_NAME_CREATE), toggleToClosed, appendAffinityRule ]); }, handleUpdateAffinityRule: (index, newAffinityRule) => { affinityRules[index] = { ...newAffinityRule, expanded: false }; return dispatch([ destroy(FORM_NAME_EDIT(index)), set({ name: `create-instance-affinity`, value: affinityRules.slice() }) ]); }, handleChangeAddOpen: value => { return dispatch([ reset(FORM_NAME_CREATE), set({ name: `create-instance-affinity-add-open`, value }) ]); }, handleToggleExpanded: index => { affinityRules[index] = { ...affinityRules[index], expanded: !affinityRules[index].expanded }; return dispatch( set({ name: `create-instance-affinity`, value: affinityRules.slice() }) ); }, handleCancelEdit: index => { affinityRules[index] = { ...affinityRules[index], expanded: false }; return dispatch([ reset(FORM_NAME_EDIT(index)), set({ name: `create-instance-affinity`, value: affinityRules.slice() }) ]); }, handleRemoveAffinityRule: index => { affinityRules.splice(index, 1); return dispatch([ destroy(FORM_NAME_EDIT(index)), set({ name: `create-instance-affinity`, value: affinityRules.slice() }) ]); } })) )(Affinity);