diff --git a/ui-v2/app/components/form-component.js b/ui-v2/app/components/form-component.js index 5a6e5f393a..c3c91011f3 100644 --- a/ui-v2/app/components/form-component.js +++ b/ui-v2/app/components/form-component.js @@ -23,16 +23,24 @@ export default Component.extend(WithListeners, SlotsMixin, { actions: { change: function(e, value, item) { let event = get(this, 'dom').normalizeEvent(e, value); + // currently form-components don't deal with deeply nested forms, only top level + // we therefore grab the end of the nest off here, + // so role[policy][Rules] will end up as policy[Rules] + // but also policy[Rules] will end up as Rules + // for now we look for a [ so we know whether this component is deeply + // nested or not and we pass the name through as an optional argument to handleEvent + // once this component handles deeply nested forms this can go const matches = [...event.target.name.matchAll(propRe)]; const prop = matches[matches.length - 1][0]; - event = get(this, 'dom').normalizeEvent( - `${get(this, 'type')}[${prop}]`, - event.target.value, - event.target - ); + let name; + if (prop.indexOf('[') === -1) { + name = `${get(this, 'type')}[${prop}]`; + } else { + name = prop; + } const form = get(this, 'form'); try { - form.handleEvent(event); + form.handleEvent(event, name); this.onchange({ target: this }); } catch (err) { throw err; diff --git a/ui-v2/app/utils/form/builder.js b/ui-v2/app/utils/form/builder.js index feba1adbfd..4a7b5e1c04 100644 --- a/ui-v2/app/utils/form/builder.js +++ b/ui-v2/app/utils/form/builder.js @@ -56,9 +56,11 @@ export default function(changeset = defaultChangeset, getFormNameProperty = pars _children[child.getName()] = child; return this; }, - handleEvent: function(e) { + handleEvent: function(e, targetName) { const target = e.target; - const parts = getFormNameProperty(target.name); + // currently we only use targetName in {{form-component}} for handling deeply + // nested forms, once {{form-component}} handles deeply nested forms targetName can go + const parts = getFormNameProperty(targetName || target.name); // split the form element name from `name[prop]` const name = parts[0]; const prop = parts[1]; diff --git a/ui-v2/tests/acceptance/dc/acls/policies/update.feature b/ui-v2/tests/acceptance/dc/acls/policies/update.feature index de9f77effe..b10f538b40 100644 --- a/ui-v2/tests/acceptance/dc/acls/policies/update.feature +++ b/ui-v2/tests/acceptance/dc/acls/policies/update.feature @@ -5,6 +5,7 @@ Feature: dc / acls / policies / update: ACL Policy Update And 1 policy model from yaml --- ID: policy-id + Datacenters: [] --- And 3 token models When I visit the policy page for yaml @@ -21,12 +22,16 @@ Feature: dc / acls / policies / update: ACL Policy Update Description: [Description] Rules: [Rules] --- + And I click validDatacenters + And I click datacenter And I submit Then a PUT request is made to "/v1/acl/policy/policy-id?dc=datacenter" with the body from yaml --- Name: [Name] Description: [Description] Rules: [Rules] + Datacenters: + - datacenter --- Then the url should be /datacenter/acls/policies And "[data-notification]" has the "notification-update" class diff --git a/ui-v2/tests/pages.js b/ui-v2/tests/pages.js index d3c5c2f752..5047067251 100644 --- a/ui-v2/tests/pages.js +++ b/ui-v2/tests/pages.js @@ -69,7 +69,7 @@ export default { policies: create( policies(visitable, deletable, creatable, clickable, attribute, collection, freetextFilter) ), - policy: create(policy(visitable, submitable, deletable, cancelable, tokenList)), + policy: create(policy(visitable, submitable, deletable, cancelable, clickable, tokenList)), roles: create( roles(visitable, deletable, creatable, clickable, attribute, collection, freetextFilter) ), diff --git a/ui-v2/tests/pages/dc/acls/policies/edit.js b/ui-v2/tests/pages/dc/acls/policies/edit.js index 847c7261bf..57e80a0cb3 100644 --- a/ui-v2/tests/pages/dc/acls/policies/edit.js +++ b/ui-v2/tests/pages/dc/acls/policies/edit.js @@ -1,10 +1,12 @@ -export default function(visitable, submitable, deletable, cancelable, tokenList) { +export default function(visitable, submitable, deletable, cancelable, clickable, tokenList) { return { visit: visitable(['/:dc/acls/policies/:policy', '/:dc/acls/policies/create']), ...submitable({}, 'form > div'), ...cancelable({}, 'form > div'), ...deletable({}, 'form > div'), tokens: tokenList(), + validDatacenters: clickable('[name="policy[isScoped]"]'), + datacenter: clickable('[name="policy[Datacenters]"]'), deleteModal: { resetScope: true, scope: '[data-test-delete-modal]',