diff --git a/ui-v2/app/components/phrase-editor.js b/ui-v2/app/components/phrase-editor.js index e280b571c1e9..4eb7bce817fc 100644 --- a/ui-v2/app/components/phrase-editor.js +++ b/ui-v2/app/components/phrase-editor.js @@ -1,44 +1,67 @@ import Component from '@ember/component'; import { get, set } from '@ember/object'; +import { inject as service } from '@ember/service'; export default Component.extend({ + dom: service('dom'), classNames: ['phrase-editor'], item: '', - remove: function(index, e) { - this.items.removeAt(index, 1); - this.onchange(e); + didInsertElement: function() { + this._super(...arguments); + // TODO: use {{ref}} + this.input = get(this, 'dom').element('input', this.element); }, - add: function(e) { - const value = get(this, 'item').trim(); - if (value !== '') { - set(this, 'item', ''); - const currentItems = get(this, 'items') || []; - const items = new Set(currentItems).add(value); - if (items.size > currentItems.length) { - set(this, 'items', [...items]); - this.onchange(e); + onchange: function(e) {}, + search: function(e) { + // TODO: Temporarily continue supporting `searchable` + let searchable = get(this, 'searchable'); + if (searchable) { + if (!Array.isArray(searchable)) { + searchable = [searchable]; } + searchable.forEach(item => { + item.search(get(this, 'value')); + }); } + this.onchange(e); }, - onkeydown: function(e) { - switch (e.keyCode) { - case 8: - if (e.target.value == '' && this.items.length > 0) { - this.remove(this.items.length - 1); + oninput: function(e) {}, + onkeydown: function(e) {}, + actions: { + keydown: function(e) { + switch (e.keyCode) { + case 8: // backspace + if (e.target.value == '' && get(this, 'value').length > 0) { + this.actions.remove.bind(this)(get(this, 'value').length - 1); + } + break; + case 27: // escape + set(this, 'value', []); + this.search({ target: this }); + break; + } + this.onkeydown({ target: this }); + }, + input: function(e) { + set(this, 'item', e.target.value); + this.oninput({ target: this }); + }, + remove: function(index, e) { + get(this, 'value').removeAt(index, 1); + this.search({ target: this }); + this.input.focus(); + }, + add: function(e) { + const item = get(this, 'item').trim(); + if (item !== '') { + set(this, 'item', ''); + const currentItems = get(this, 'value') || []; + const items = new Set(currentItems).add(item); + if (items.size > currentItems.length) { + set(this, 'value', [...items]); + this.search({ target: this }); } - break; - } - }, - oninput: function(e) { - set(this, 'item', e.target.value); - }, - onchange: function(e) { - let searchable = get(this, 'searchable'); - if (!Array.isArray(searchable)) { - searchable = [searchable]; - } - searchable.forEach(item => { - item.search(get(this, 'items')); - }); + } + }, }, }); diff --git a/ui-v2/app/styles/base/components/pill/layout.scss b/ui-v2/app/styles/base/components/pill/layout.scss index 6b4b05f39b12..95b1e132ea81 100644 --- a/ui-v2/app/styles/base/components/pill/layout.scss +++ b/ui-v2/app/styles/base/components/pill/layout.scss @@ -8,4 +8,5 @@ padding: 0; height: 10px; margin-right: 3px; + font-size: 0; } diff --git a/ui-v2/app/templates/components/phrase-editor.hbs b/ui-v2/app/templates/components/phrase-editor.hbs index 480849c5f979..d0e8d5e74ed1 100644 --- a/ui-v2/app/templates/components/phrase-editor.hbs +++ b/ui-v2/app/templates/components/phrase-editor.hbs @@ -1,11 +1,11 @@ - - \ No newline at end of file diff --git a/ui-v2/app/templates/dc/services/index.hbs b/ui-v2/app/templates/dc/services/index.hbs index eb323e1a4acb..6a1cf8de7282 100644 --- a/ui-v2/app/templates/dc/services/index.hbs +++ b/ui-v2/app/templates/dc/services/index.hbs @@ -10,7 +10,12 @@ {{/block-slot}} {{#block-slot 'toolbar'}} {{#if (gt items.length 0) }} - {{#phrase-editor placeholder=(if (eq terms.length 0) 'service:name tag:name status:critical search-term' '') items=terms searchable=searchable}}{{/phrase-editor}} + {{phrase-editor + placeholder='service:name tag:name status:critical search-term' + value=(slice 0 terms.length terms) + onchange=(action (mut terms) value='target.value') + searchable=searchable + }} {{/if}} {{/block-slot}} {{#block-slot 'content'}} diff --git a/ui-v2/tests/integration/components/phrase-editor-test.js b/ui-v2/tests/integration/components/phrase-editor-test.js index 1ce41299bd57..5d8de0aa3bee 100644 --- a/ui-v2/tests/integration/components/phrase-editor-test.js +++ b/ui-v2/tests/integration/components/phrase-editor-test.js @@ -5,30 +5,45 @@ moduleForComponent('phrase-editor', 'Integration | Component | phrase editor', { integration: true, }); -test('it renders', function(assert) { - // Set any properties with this.set('myProperty', 'value'); - // Handle any actions with this.on('myAction', function(val) { ... }); - - this.render(hbs`{{phrase-editor}}`); - - assert.equal( +test('it renders a phrase', function(assert) { + this.set('value', ['phrase']); + this.render(hbs`{{phrase-editor value=value}}`); + assert.notEqual( this.$() .text() - .trim(), - 'Search' + .trim() + .indexOf('phrase'), + -1 ); - - // Template block usage: - this.render(hbs` - {{#phrase-editor}} - template block text - {{/phrase-editor}} - `); - - assert.equal( +}); +test('it calls onchange when a phrase is removed by clicking the phrase remove button and refocuses', function(assert) { + assert.expect(3); + this.set('value', ['phrase']); + this.on('change', function(e) { + assert.equal(e.target.value.length, 0); + }); + this.render(hbs`{{phrase-editor value=value onchange=(action 'change')}}`); + assert.notEqual( this.$() .text() - .trim(), - 'Search' + .trim() + .indexOf('phrase'), + -1 ); + const $input = this.$('input'); + const $button = this.$('button'); + $button.trigger('click'); + assert.equal(document.activeElement, $input.get(0)); +}); +test('it calls onchange when a phrase is added', function(assert) { + assert.expect(1); + this.on('change', function(e) { + assert.equal(e.target.value.length, 2); + }); + this.set('value', ['phrase']); + this.render(hbs`{{phrase-editor value=value onchange=(action 'change')}}`); + const $input = this.$('input'); + $input.get(0).value = 'phrase 2'; + $input.trigger('input'); + $input.trigger('search'); });