diff --git a/ui-v2/app/controllers/dc/acls/edit.js b/ui-v2/app/controllers/dc/acls/edit.js index a1c86d279811..2c1d2d17fe5d 100644 --- a/ui-v2/app/controllers/dc/acls/edit.js +++ b/ui-v2/app/controllers/dc/acls/edit.js @@ -1,30 +1,31 @@ import Controller from '@ember/controller'; -import { set } from '@ember/object'; -import Changeset from 'ember-changeset'; -import validations from 'consul-ui/validations/acl'; -import lookupValidator from 'ember-changeset-validations'; +import { inject as service } from '@ember/service'; +import { get } from '@ember/object'; export default Controller.extend({ + builder: service('form'), + dom: service('dom'), + init: function() { + this._super(...arguments); + this.form = get(this, 'builder').form('acl'); + }, setProperties: function(model) { - this.changeset = new Changeset(model.item, lookupValidator(validations), validations); - this._super({ - ...model, - ...{ - item: this.changeset, - }, - }); + // essentially this replaces the data with changesets + this._super( + Object.keys(model).reduce((prev, key, i) => { + switch (key) { + case 'item': + prev[key] = this.form.setData(prev[key]).getData(); + break; + } + return prev; + }, model) + ); }, actions: { - change: function(e) { - const target = e.target || { name: 'Rules', value: e }; - switch (target.name) { - case 'Type': - set(this.changeset, target.name, target.value); - break; - case 'Rules': - set(this, 'item.Rules', target.value); - break; - } + change: function(e, value, item) { + const event = get(this, 'dom').normalizeEvent(e, value); + get(this, 'form').handleEvent(event); }, }, }); diff --git a/ui-v2/app/controllers/dc/acls/policies/edit.js b/ui-v2/app/controllers/dc/acls/policies/edit.js index 1c02cbfaf153..9c1564324287 100644 --- a/ui-v2/app/controllers/dc/acls/policies/edit.js +++ b/ui-v2/app/controllers/dc/acls/policies/edit.js @@ -25,8 +25,8 @@ export default Controller.extend({ }, actions: { change: function(e, value, item) { - const form = get(this, 'form'); const event = get(this, 'dom').normalizeEvent(e, value); + const form = get(this, 'form'); try { form.handleEvent(event); } catch (err) { diff --git a/ui-v2/app/controllers/dc/acls/tokens/edit.js b/ui-v2/app/controllers/dc/acls/tokens/edit.js index a10c6e10e6e0..f40050260317 100644 --- a/ui-v2/app/controllers/dc/acls/tokens/edit.js +++ b/ui-v2/app/controllers/dc/acls/tokens/edit.js @@ -45,8 +45,8 @@ export default Controller.extend({ .didAppear(); }, change: function(e, value, item) { - const form = get(this, 'form'); const event = get(this, 'dom').normalizeEvent(e, value); + const form = get(this, 'form'); try { form.handleEvent(event); } catch (err) { diff --git a/ui-v2/app/controllers/dc/intentions/edit.js b/ui-v2/app/controllers/dc/intentions/edit.js index 0773435c3a18..1999614a74a9 100644 --- a/ui-v2/app/controllers/dc/intentions/edit.js +++ b/ui-v2/app/controllers/dc/intentions/edit.js @@ -1,13 +1,15 @@ import Controller from '@ember/controller'; +import { inject as service } from '@ember/service'; import { get, set } from '@ember/object'; -import Changeset from 'ember-changeset'; -import lookupValidator from 'ember-changeset-validations'; - -import validations from 'consul-ui/validations/intention'; export default Controller.extend({ + dom: service('dom'), + builder: service('form'), + init: function() { + this._super(...arguments); + this.form = get(this, 'builder').form('intention'); + }, setProperties: function(model) { - this.changeset = new Changeset(model.item, lookupValidator(validations), validations); const sourceName = get(model.item, 'SourceName'); const destinationName = get(model.item, 'DestinationName'); let source = model.items.findBy('Name', sourceName); @@ -23,7 +25,7 @@ export default Controller.extend({ this._super({ ...model, ...{ - item: this.changeset, + item: this.form.setData(model.item).getData(), SourceName: source, DestinationName: destination, }, @@ -36,37 +38,44 @@ export default Controller.extend({ isUnique: function(term) { return !get(this, 'items').findBy('Name', term); }, - change: function(e, value, _target) { - // normalize back to standard event - const target = e.target || { ..._target, ...{ name: e, value: value } }; - let name, selected; - name = selected = target.value; - // TODO: - // linter needs this here? + change: function(e, value, item) { + const event = get(this, 'dom').normalizeEvent(e, value); + const form = get(this, 'form'); + const target = event.target; + + let name; + let selected; let match; switch (target.name) { - case 'Description': - case 'Action': - set(this.changeset, target.name, target.value); - break; case 'SourceName': case 'DestinationName': + name = selected = target.value; + // Names can be selected Service EmberObjects or typed in strings + // if its not a string, use the `Name` from the Service EmberObject if (typeof name !== 'string') { name = get(target.value, 'Name'); } - // linter doesn't like const here + // see if the name is already in the list match = get(this, 'items').filterBy('Name', name); if (match.length === 0) { + // if its not make a new 'fake' Service that doesn't exist yet + // and add it to the possible services to make an intention between selected = { Name: name }; - // linter doesn't mind const here? const items = [selected].concat(this.items.toArray()); set(this, 'items', items); } - set(this.changeset, target.name, name); + // mutate the value with the string name + // which will be handled by the form + target.value = name; + // these are 'non-form' variables so not on `item` + // these variables also exist in the template so we know + // the current selection + // basically the difference between + // `item.DestinationName` and just `DestinationName` set(this, target.name, selected); break; } - this.changeset.validate(); + form.handleEvent(event); }, }, }); diff --git a/ui-v2/app/controllers/dc/kv/edit.js b/ui-v2/app/controllers/dc/kv/edit.js index 33f263290932..bdfeb18a639f 100644 --- a/ui-v2/app/controllers/dc/kv/edit.js +++ b/ui-v2/app/controllers/dc/kv/edit.js @@ -2,41 +2,56 @@ import Controller from '@ember/controller'; import { get, set } from '@ember/object'; import { inject as service } from '@ember/service'; -import Changeset from 'ember-changeset'; -import validations from 'consul-ui/validations/kv'; -import lookupValidator from 'ember-changeset-validations'; export default Controller.extend({ - json: true, + dom: service('dom'), + builder: service('form'), encoder: service('btoa'), + json: true, + init: function() { + this._super(...arguments); + this.form = get(this, 'builder').form('kv'); + }, setProperties: function(model) { - // TODO: Potentially save whether json has been clicked to the model, - // setting set(this, 'json', true) here will force the form to always default to code=on - // even if the user has selected code=off on another KV - // ideally we would save the value per KV, but I'd like to not do that on the model - // a set(this, 'json', valueFromSomeStorageJustForThisKV) would be added here - this.changeset = new Changeset(model.item, lookupValidator(validations), validations); - this._super({ - ...model, - ...{ - item: this.changeset, - }, - }); + // essentially this replaces the data with changesets + this._super( + Object.keys(model).reduce((prev, key, i) => { + switch (key) { + case 'item': + prev[key] = this.form.setData(prev[key]).getData(); + break; + } + return prev; + }, model) + ); }, actions: { - change: function(e) { - const target = e.target || { name: 'value', value: e }; - var parent; - switch (target.name) { - case 'additional': - parent = get(this, 'parent.Key'); - set(this.changeset, 'Key', `${parent !== '/' ? parent : ''}${target.value}`); - break; - case 'json': - set(this, 'json', !get(this, 'json')); - break; - case 'value': - set(this, 'item.Value', get(this, 'encoder').execute(target.value)); - break; + change: function(e, value, item) { + const event = get(this, 'dom').normalizeEvent(e, value); + const form = get(this, 'form'); + try { + form.handleEvent(event); + } catch (err) { + const target = event.target; + let parent; + switch (target.name) { + case 'value': + set(this.item, 'Value', get(this, 'encoder').execute(target.value)); + break; + case 'additional': + parent = get(this, 'parent.Key'); + set(this.item, 'Key', `${parent !== '/' ? parent : ''}${target.value}`); + break; + case 'json': + // TODO: Potentially save whether json has been clicked to the model, + // setting set(this, 'json', true) here will force the form to always default to code=on + // even if the user has selected code=off on another KV + // ideally we would save the value per KV, but I'd like to not do that on the model + // a set(this, 'json', valueFromSomeStorageJustForThisKV) would be added here + set(this, 'json', !get(this, 'json')); + break; + default: + throw err; + } } }, }, diff --git a/ui-v2/app/forms/acl.js b/ui-v2/app/forms/acl.js new file mode 100644 index 000000000000..7a7051ef6bc4 --- /dev/null +++ b/ui-v2/app/forms/acl.js @@ -0,0 +1,6 @@ +import validations from 'consul-ui/validations/acl'; +import builderFactory from 'consul-ui/utils/form/builder'; +const builder = builderFactory(); +export default function(name = '', v = validations, form = builder) { + return form(name, {}).setValidators(v); +} diff --git a/ui-v2/app/forms/intention.js b/ui-v2/app/forms/intention.js new file mode 100644 index 000000000000..40e8e155e5f9 --- /dev/null +++ b/ui-v2/app/forms/intention.js @@ -0,0 +1,6 @@ +import validations from 'consul-ui/validations/intention'; +import builderFactory from 'consul-ui/utils/form/builder'; +const builder = builderFactory(); +export default function(name = '', v = validations, form = builder) { + return form(name, {}).setValidators(v); +} diff --git a/ui-v2/app/forms/kv.js b/ui-v2/app/forms/kv.js new file mode 100644 index 000000000000..c993fab64c11 --- /dev/null +++ b/ui-v2/app/forms/kv.js @@ -0,0 +1,6 @@ +import validations from 'consul-ui/validations/kv'; +import builderFactory from 'consul-ui/utils/form/builder'; +const builder = builderFactory(); +export default function(name = '', v = validations, form = builder) { + return form(name, {}).setValidators(v); +} diff --git a/ui-v2/app/forms/token.js b/ui-v2/app/forms/token.js index 3a0e0bb82e97..b5cc218812d8 100644 --- a/ui-v2/app/forms/token.js +++ b/ui-v2/app/forms/token.js @@ -1,6 +1,6 @@ -import builderFactory from 'consul-ui/utils/form/builder'; import validations from 'consul-ui/validations/token'; import policy from 'consul-ui/forms/policy'; +import builderFactory from 'consul-ui/utils/form/builder'; const builder = builderFactory(); export default function(name = '', v = validations, form = builder) { return form(name, {}) diff --git a/ui-v2/app/initializers/form.js b/ui-v2/app/initializers/form.js index 099e98036c74..1c9c24b5cebf 100644 --- a/ui-v2/app/initializers/form.js +++ b/ui-v2/app/initializers/form.js @@ -1,11 +1,17 @@ +import kv from 'consul-ui/forms/kv'; +import acl from 'consul-ui/forms/acl'; import token from 'consul-ui/forms/token'; import policy from 'consul-ui/forms/policy'; +import intention from 'consul-ui/forms/intention'; export function initialize(application) { // Service-less injection using private properties at a per-project level const FormBuilder = application.resolveRegistration('service:form'); const forms = { + kv: kv(), + acl: acl(), token: token(), policy: policy(), + intention: intention(), }; FormBuilder.reopen({ form: function(name) { diff --git a/ui-v2/app/templates/dc/acls/-form.hbs b/ui-v2/app/templates/dc/acls/-form.hbs index b0ec83363c52..c6dac4d759d3 100644 --- a/ui-v2/app/templates/dc/acls/-form.hbs +++ b/ui-v2/app/templates/dc/acls/-form.hbs @@ -14,7 +14,7 @@ {{#if create }}