open-consul/ui-v2/app/components/child-selector/index.js
John Cowen 6126f24acd
ui: Remove with-listeners mixin (#8142)
This mixin was a very thin mixin over the top of our listeners utility,
and we have been gradually preferring using the utility straight rather
than using the mixin. This commit removes the last places where we still
used the mixin, and also potentially the last few places where we
continued to use the old API for our listeners utility.
2020-06-18 14:54:31 +01:00

121 lines
3.7 KiB
JavaScript

import Component from '@ember/component';
import { get, set, computed } from '@ember/object';
import { alias } from '@ember/object/computed';
import { inject as service } from '@ember/service';
import Slotted from 'block-slots';
export default Component.extend(Slotted, {
onchange: function() {},
tagName: '',
error: function() {},
type: '',
dom: service('dom'),
container: service('search'),
formContainer: service('form'),
item: alias('form.data'),
selectedOptions: alias('items'),
init: function() {
this._super(...arguments);
this._listeners = this.dom.listeners();
this.searchable = this.container.searchable(this.type);
this.form = this.formContainer.form(this.type);
this.form.clear({ Datacenter: this.dc, Namespace: this.nspace });
},
willDestroyElement: function() {
this._super(...arguments);
this._listeners.remove();
},
options: computed('selectedOptions.[]', 'allOptions.[]', function() {
// It's not massively important here that we are defaulting `items` and
// losing reference as its just to figure out the diff
let options = this.allOptions || [];
const items = this.selectedOptions || [];
if (get(items, 'length') > 0) {
// find a proper ember-data diff
options = options.filter(item => !items.findBy('ID', get(item, 'ID')));
this.searchable.add(options);
}
return options;
}),
actions: {
search: function(term) {
// TODO: make sure we can either search before things are loaded
// or wait until we are loaded, guess power select take care of that
return new Promise(resolve => {
const remove = this._listeners.add(this.searchable, {
change: e => {
remove();
resolve(e.target.data);
},
});
this.searchable.search(term);
});
},
reset: function() {
this.form.clear({ Datacenter: this.dc, Namespace: this.nspace });
},
save: function(item, items, success = function() {}) {
// Specifically this saves an 'new' option/child
// and then adds it to the selectedOptions, not options
const repo = this.repo;
set(item, 'CreateTime', new Date().getTime());
// TODO: temporary async
// this should be `set(this, 'item', repo.persist(item));`
// need to be sure that its saved before adding/closing the modal for now
// and we don't open the modal on prop change yet
item = repo.persist(item);
this._listeners.add(item, {
message: e => {
this.actions.change.apply(this, [
{
target: {
name: 'items[]',
value: items,
},
},
items,
e.data,
]);
item.willDestroy();
success();
},
error: e => {
item.willDestroy();
this.error(e);
},
});
},
remove: function(item, items) {
const prop = this.repo.getSlugKey();
const value = get(item, prop);
const pos = items.findIndex(function(item) {
return get(item, prop) === value;
});
if (pos !== -1) {
return items.removeAt(pos, 1);
}
this.onchange({ target: this });
},
change: function(e, value, item) {
const event = this.dom.normalizeEvent(...arguments);
const items = value;
switch (event.target.name) {
case 'items[]':
set(item, 'CreateTime', new Date().getTime());
// this always happens synchronously
items.pushObject(item);
// TODO: Fire a proper event
this.onchange({ target: this });
break;
default:
}
},
},
});