334e16a6cf
1. All {{ivy-codemirror}} components need 'refreshing' when they become
visible via our own `didAppear` method on the `{{code-editor}}`
component
(also see:)
- https://github.com/hashicorp/consul/pull/4190#discussion_r193270223
- 73db111db8 (r225264296)
2. On initial investigation, it looks like the component we are using
for the code editor doesn't distinguish between setting its `value`
programatically and a `keyup` event, i.e. an interaction from the user.
We currently pretend that whenever its `value` changes, it is a `keyup`
event. This means that when we reset the `value` to `""`
programmatically for form resetting purposes, a 'pretend keyup' event
would also be fired, which would in turn kick off the validation, which
would fail and show an error message for empty values in other fields of
the form - something that is perfectly valid if you haven't typed
anything yet. We solved this by checking for `isPristine` on fields that
are allowed to be empty before you have typed anything.
88 lines
2.8 KiB
JavaScript
88 lines
2.8 KiB
JavaScript
import ChildSelectorComponent from './child-selector';
|
|
import { get, set } from '@ember/object';
|
|
import { inject as service } from '@ember/service';
|
|
import updateArrayObject from 'consul-ui/utils/update-array-object';
|
|
|
|
const ERROR_PARSE_RULES = 'Failed to parse ACL rules';
|
|
const ERROR_INVALID_POLICY = 'Invalid service policy';
|
|
const ERROR_NAME_EXISTS = 'Invalid Policy: A Policy with Name';
|
|
|
|
export default ChildSelectorComponent.extend({
|
|
repo: service('repository/policy/component'),
|
|
datacenterRepo: service('repository/dc/component'),
|
|
name: 'policy',
|
|
type: 'policy',
|
|
classNames: ['policy-selector'],
|
|
init: function() {
|
|
this._super(...arguments);
|
|
const source = get(this, 'source');
|
|
if (source) {
|
|
const event = 'save';
|
|
this.listen(source, event, e => {
|
|
this.actions[event].bind(this)(...e.data);
|
|
});
|
|
}
|
|
},
|
|
reset: function(e) {
|
|
this._super(...arguments);
|
|
set(this, 'isScoped', false);
|
|
set(this, 'datacenters', get(this, 'datacenterRepo').findAll());
|
|
},
|
|
refreshCodeEditor: function(e, target) {
|
|
const selector = '.code-editor';
|
|
get(this, 'dom')
|
|
.component(selector, target)
|
|
.didAppear();
|
|
},
|
|
error: function(e) {
|
|
const item = get(this, 'item');
|
|
const err = e.error;
|
|
if (typeof err.errors !== 'undefined') {
|
|
const error = err.errors[0];
|
|
let prop = 'Rules';
|
|
let message = error.detail;
|
|
switch (true) {
|
|
case message.indexOf(ERROR_PARSE_RULES) === 0:
|
|
case message.indexOf(ERROR_INVALID_POLICY) === 0:
|
|
prop = 'Rules';
|
|
message = error.detail;
|
|
break;
|
|
case message.indexOf(ERROR_NAME_EXISTS) === 0:
|
|
prop = 'Name';
|
|
message = message.substr(ERROR_NAME_EXISTS.indexOf(':') + 1);
|
|
break;
|
|
}
|
|
if (prop) {
|
|
item.addError(prop, message);
|
|
}
|
|
} else {
|
|
// TODO: Conponents can't throw, use onerror
|
|
throw err;
|
|
}
|
|
},
|
|
actions: {
|
|
open: function(e) {
|
|
this.refreshCodeEditor(e, e.target.parentElement);
|
|
},
|
|
loadItem: function(e, item, items) {
|
|
const target = e.target;
|
|
// the Details expander toggle, only load on opening
|
|
if (target.checked) {
|
|
const value = item;
|
|
this.refreshCodeEditor(e, target.parentNode);
|
|
if (get(item, 'template') === 'service-identity') {
|
|
return;
|
|
}
|
|
// potentially the item could change between load, so we don't check
|
|
// anything to see if its already loaded here
|
|
const repo = get(this, 'repo');
|
|
// TODO: Temporarily add dc here, will soon be serialized onto the policy itself
|
|
const dc = get(this, 'dc');
|
|
const slugKey = repo.getSlugKey();
|
|
const slug = get(value, slugKey);
|
|
updateArrayObject(items, repo.findBySlug(slug, dc), slugKey, slug);
|
|
}
|
|
},
|
|
},
|
|
});
|