UI: Move legacy ACLs, KVs and Intentions to use form
functionality (#4936)
Change legacy acls, kvs and intentions to use `form`s
This commit is contained in:
parent
d6fd3f799c
commit
5eed6dcef6
|
@ -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);
|
||||
},
|
||||
},
|
||||
});
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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);
|
||||
},
|
||||
},
|
||||
});
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
|
|
6
ui-v2/app/forms/acl.js
Normal file
6
ui-v2/app/forms/acl.js
Normal file
|
@ -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);
|
||||
}
|
6
ui-v2/app/forms/intention.js
Normal file
6
ui-v2/app/forms/intention.js
Normal file
|
@ -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);
|
||||
}
|
6
ui-v2/app/forms/kv.js
Normal file
6
ui-v2/app/forms/kv.js
Normal file
|
@ -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);
|
||||
}
|
|
@ -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, {})
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -14,7 +14,7 @@
|
|||
</div>
|
||||
<label class="type-text">
|
||||
<span>Policy <a href="{{env 'CONSUL_DOCUMENTATION_URL'}}/guides/acl.html#rule-specification" rel="help noopener noreferrer" target="_blank">(HCL Format)</a></span>
|
||||
{{code-editor class=(if item.error.Rules 'error') name='Rules' value=item.Rules syntax="hcl" onkeyup=(action 'change')}}
|
||||
{{code-editor class=(if item.error.Rules 'error') name='Rules' value=item.Rules syntax="hcl" onkeyup=(action 'change' 'Rules')}}
|
||||
</label>
|
||||
{{#if create }}
|
||||
<label class="type-text">
|
||||
|
|
|
@ -18,7 +18,7 @@
|
|||
<label class="type-text{{if item.error.Value ' has-error'}}">
|
||||
<span>Value</span>
|
||||
{{#if json}}
|
||||
{{ code-editor value=(atob item.Value) onkeyup=(action 'change') }}
|
||||
{{code-editor value=(atob item.Value) onkeyup=(action 'change' 'value')}}
|
||||
{{else}}
|
||||
<textarea autofocus={{not create}} name="value" oninput={{action 'change'}}>{{atob item.Value}}</textarea>
|
||||
{{/if}}
|
||||
|
|
|
@ -2,7 +2,7 @@ import { moduleFor, test } from 'ember-qunit';
|
|||
|
||||
moduleFor('controller:dc/acls/create', 'Unit | Controller | dc/acls/create', {
|
||||
// Specify the other units that are required for this test.
|
||||
// needs: ['controller:foo']
|
||||
needs: ['service:dom', 'service:form'],
|
||||
});
|
||||
|
||||
// Replace this with your real tests.
|
||||
|
|
|
@ -2,7 +2,7 @@ import { moduleFor, test } from 'ember-qunit';
|
|||
|
||||
moduleFor('controller:dc/acls/edit', 'Unit | Controller | dc/acls/edit', {
|
||||
// Specify the other units that are required for this test.
|
||||
// needs: ['controller:foo']
|
||||
needs: ['service:dom', 'service:form'],
|
||||
});
|
||||
|
||||
// Replace this with your real tests.
|
||||
|
|
|
@ -2,7 +2,7 @@ import { moduleFor, test } from 'ember-qunit';
|
|||
|
||||
moduleFor('controller:dc/intentions/create', 'Unit | Controller | dc/intentions/create', {
|
||||
// Specify the other units that are required for this test.
|
||||
// needs: ['controller:foo']
|
||||
needs: ['service:dom', 'service:form'],
|
||||
});
|
||||
|
||||
// Replace this with your real tests.
|
||||
|
|
|
@ -2,7 +2,7 @@ import { moduleFor, test } from 'ember-qunit';
|
|||
|
||||
moduleFor('controller:dc/intentions/edit', 'Unit | Controller | dc/intentions/edit', {
|
||||
// Specify the other units that are required for this test.
|
||||
// needs: ['controller:foo']
|
||||
needs: ['service:dom', 'service:form'],
|
||||
});
|
||||
|
||||
// Replace this with your real tests.
|
||||
|
|
|
@ -2,7 +2,7 @@ import { moduleFor, test } from 'ember-qunit';
|
|||
|
||||
moduleFor('controller:dc/kv/create', 'Unit | Controller | dc/kv/create', {
|
||||
// Specify the other units that are required for this test.
|
||||
needs: ['service:btoa'],
|
||||
needs: ['service:btoa', 'service:dom', 'service:form'],
|
||||
});
|
||||
|
||||
// Replace this with your real tests.
|
||||
|
|
|
@ -2,7 +2,7 @@ import { moduleFor, test } from 'ember-qunit';
|
|||
|
||||
moduleFor('controller:dc/kv/edit', 'Unit | Controller | dc/kv/edit', {
|
||||
// Specify the other units that are required for this test.
|
||||
needs: ['service:btoa'],
|
||||
needs: ['service:btoa', 'service:dom', 'service:form'],
|
||||
});
|
||||
|
||||
// Replace this with your real tests.
|
||||
|
|
|
@ -2,7 +2,7 @@ import { moduleFor, test } from 'ember-qunit';
|
|||
|
||||
moduleFor('controller:dc/kv/root-create', 'Unit | Controller | dc/kv/root-create', {
|
||||
// Specify the other units that are required for this test.
|
||||
needs: ['service:btoa'],
|
||||
needs: ['service:btoa', 'service:dom', 'service:form'],
|
||||
});
|
||||
|
||||
// Replace this with your real tests.
|
||||
|
|
Loading…
Reference in a new issue