mirror of https://github.com/status-im/consul.git
ui: Remove old style 'filterable' searching (#9356)
* Switch upstream-instances to use new style of searchable * Add search action to DataCollection plus basic README * Use DataCollection for PowerSelect searching in child-selectors * Remove old style filterable search for role/policies and instances * Remove old helpers/components related to search/sort/filter
This commit is contained in:
parent
4dbc1b7b59
commit
2c3b6aec05
|
@ -1,7 +0,0 @@
|
||||||
{{yield}}
|
|
||||||
<YieldSlot @name="content" @params={{block-params items}}>{{yield}}</YieldSlot>
|
|
||||||
{{#if (gt items.length 0)}}
|
|
||||||
<YieldSlot @name="set" @params={{block-params items}}>{{yield}}</YieldSlot>
|
|
||||||
{{else}}
|
|
||||||
<YieldSlot @name="empty">{{yield}}</YieldSlot>
|
|
||||||
{{/if}}
|
|
|
@ -1,28 +0,0 @@
|
||||||
import Component from '@ember/component';
|
|
||||||
import { get, set } from '@ember/object';
|
|
||||||
import { inject as service } from '@ember/service';
|
|
||||||
import Slotted from 'block-slots';
|
|
||||||
|
|
||||||
export default Component.extend(Slotted, {
|
|
||||||
tagName: '',
|
|
||||||
dom: service('dom'),
|
|
||||||
init: function() {
|
|
||||||
this._super(...arguments);
|
|
||||||
this._listeners = this.dom.listeners();
|
|
||||||
},
|
|
||||||
willDestroyElement: function() {
|
|
||||||
this._listeners.remove();
|
|
||||||
this._super(...arguments);
|
|
||||||
},
|
|
||||||
didReceiveAttrs: function() {
|
|
||||||
this._super(...arguments);
|
|
||||||
if (this.items !== this.dispatcher.data) {
|
|
||||||
this._listeners.remove();
|
|
||||||
this._listeners.add(this.dispatcher, {
|
|
||||||
change: e => set(this, 'items', e.target.data),
|
|
||||||
});
|
|
||||||
set(this, 'items', get(this.dispatcher, 'data'));
|
|
||||||
}
|
|
||||||
this.dispatcher.search(this.terms);
|
|
||||||
},
|
|
||||||
});
|
|
|
@ -1,4 +1,5 @@
|
||||||
<div
|
<div
|
||||||
|
class="child-selector {{type}}-child-selector"
|
||||||
...attributes
|
...attributes
|
||||||
>
|
>
|
||||||
{{yield}}
|
{{yield}}
|
||||||
|
@ -11,18 +12,28 @@
|
||||||
@onchange={{action (mut allOptions) value="data"}}
|
@onchange={{action (mut allOptions) value="data"}}
|
||||||
/>
|
/>
|
||||||
{{/if}}
|
{{/if}}
|
||||||
|
<DataCollection
|
||||||
|
@type={{type}}
|
||||||
|
@sort='Name:asc'
|
||||||
|
@filters={{hash
|
||||||
|
searchproperties=(array 'Name')
|
||||||
|
}}
|
||||||
|
@items={{options}}
|
||||||
|
as |collection|>
|
||||||
<PowerSelect
|
<PowerSelect
|
||||||
@searchEnabled={{true}}
|
@searchEnabled={{true}}
|
||||||
@search={{action "search"}}
|
@search={{action collection.search}}
|
||||||
@options={{options}}
|
@options={{options}}
|
||||||
@loadingMessage="Loading..."
|
@loadingMessage="Loading..."
|
||||||
@searchMessage="No possible options"
|
@searchMessage="No possible options"
|
||||||
@searchPlaceholder={{placeholder}}
|
@searchPlaceholder={{placeholder}}
|
||||||
@onOpen={{action (mut isOpen) true}}
|
@onOpen={{action (mut isOpen) true}}
|
||||||
@onClose={{action (mut isOpen) false}}
|
@onClose={{action (mut isOpen) false}}
|
||||||
@onChange={{action "change" "items[]" items}} as |item|>
|
@onChange={{action "change" "items[]" items}}
|
||||||
|
as |item|>
|
||||||
<YieldSlot @name="option" @params={{block-params item}}>{{yield}}</YieldSlot>
|
<YieldSlot @name="option" @params={{block-params item}}>{{yield}}</YieldSlot>
|
||||||
</PowerSelect>
|
</PowerSelect>
|
||||||
|
</DataCollection>
|
||||||
</label>
|
</label>
|
||||||
{{#if (gt items.length 0)}}
|
{{#if (gt items.length 0)}}
|
||||||
<YieldSlot @name="set">{{yield}}</YieldSlot>
|
<YieldSlot @name="set">{{yield}}</YieldSlot>
|
||||||
|
|
|
@ -15,8 +15,6 @@ export default Component.extend(Slotted, {
|
||||||
type: '',
|
type: '',
|
||||||
|
|
||||||
dom: service('dom'),
|
dom: service('dom'),
|
||||||
search: service('search'),
|
|
||||||
sort: service('sort'),
|
|
||||||
formContainer: service('form'),
|
formContainer: service('form'),
|
||||||
|
|
||||||
item: alias('form.data'),
|
item: alias('form.data'),
|
||||||
|
@ -26,7 +24,6 @@ export default Component.extend(Slotted, {
|
||||||
init: function() {
|
init: function() {
|
||||||
this._super(...arguments);
|
this._super(...arguments);
|
||||||
this._listeners = this.dom.listeners();
|
this._listeners = this.dom.listeners();
|
||||||
this.searchable = this.search.searchable(this.type);
|
|
||||||
this.form = this.formContainer.form(this.type);
|
this.form = this.formContainer.form(this.type);
|
||||||
this.form.clear({ Datacenter: this.dc, Namespace: this.nspace });
|
this.form.clear({ Datacenter: this.dc, Namespace: this.nspace });
|
||||||
},
|
},
|
||||||
|
@ -34,14 +31,10 @@ export default Component.extend(Slotted, {
|
||||||
this._super(...arguments);
|
this._super(...arguments);
|
||||||
this._listeners.remove();
|
this._listeners.remove();
|
||||||
},
|
},
|
||||||
sortedOptions: sort('allOptions.[]', 'comparator'),
|
options: computed('selectedOptions.[]', 'allOptions.[]', function() {
|
||||||
comparator: computed(function() {
|
|
||||||
return this.sort.comparator(this.type)();
|
|
||||||
}),
|
|
||||||
options: computed('selectedOptions.[]', 'sortedOptions.[]', function() {
|
|
||||||
// It's not massively important here that we are defaulting `items` and
|
// It's not massively important here that we are defaulting `items` and
|
||||||
// losing reference as its just to figure out the diff
|
// losing reference as its just to figure out the diff
|
||||||
let options = this.sortedOptions || [];
|
let options = this.allOptions || [];
|
||||||
const items = this.selectedOptions || [];
|
const items = this.selectedOptions || [];
|
||||||
if (get(items, 'length') > 0) {
|
if (get(items, 'length') > 0) {
|
||||||
// filter out any items from the available options that have already been
|
// filter out any items from the available options that have already been
|
||||||
|
@ -49,7 +42,6 @@ export default Component.extend(Slotted, {
|
||||||
// TODO: find a proper ember-data diff
|
// TODO: find a proper ember-data diff
|
||||||
options = options.filter(item => !items.findBy('ID', get(item, 'ID')));
|
options = options.filter(item => !items.findBy('ID', get(item, 'ID')));
|
||||||
}
|
}
|
||||||
this.searchable.add(options);
|
|
||||||
return options;
|
return options;
|
||||||
}),
|
}),
|
||||||
save: task(function*(item, items, success = function() {}) {
|
save: task(function*(item, items, success = function() {}) {
|
||||||
|
@ -72,19 +64,6 @@ export default Component.extend(Slotted, {
|
||||||
}
|
}
|
||||||
}),
|
}),
|
||||||
actions: {
|
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() {
|
reset: function() {
|
||||||
this.form.clear({ Datacenter: this.dc, Namespace: this.nspace });
|
this.form.clear({ Datacenter: this.dc, Namespace: this.nspace });
|
||||||
},
|
},
|
||||||
|
|
|
@ -2,65 +2,61 @@
|
||||||
class="consul-upstream-instance-list"
|
class="consul-upstream-instance-list"
|
||||||
...attributes
|
...attributes
|
||||||
>
|
>
|
||||||
{{#if (gt this.items.length 0)}}
|
<ul>
|
||||||
<ul>
|
{{#each @items as |item|}}
|
||||||
{{#each this.items as |item|}}
|
<li>
|
||||||
<li>
|
<div class="header">
|
||||||
<div class="header">
|
<p>
|
||||||
<p>
|
{{item.DestinationName}}
|
||||||
{{item.DestinationName}}
|
</p>
|
||||||
</p>
|
</div>
|
||||||
</div>
|
<div class="detail">
|
||||||
<div class="detail">
|
{{#if (env 'CONSUL_NSPACES_ENABLED')}}
|
||||||
{{#if (env 'CONSUL_NSPACES_ENABLED')}}
|
{{#if (not-eq item.DestinationType 'prepared_query')}}
|
||||||
{{#if (not-eq item.DestinationType 'prepared_query')}}
|
<dl class="nspace">
|
||||||
<dl class="nspace">
|
<dt>
|
||||||
<dt>
|
<Tooltip>
|
||||||
<Tooltip>
|
Namespace
|
||||||
Namespace
|
</Tooltip>
|
||||||
</Tooltip>
|
</dt>
|
||||||
</dt>
|
<dd>
|
||||||
<dd>
|
{{or item.DestinationNamespace 'default'}}
|
||||||
{{or item.DestinationNamespace 'default'}}
|
</dd>
|
||||||
</dd>
|
</dl>
|
||||||
</dl>
|
|
||||||
{{/if}}
|
|
||||||
{{/if}}
|
{{/if}}
|
||||||
{{#if (and (not-eq item.Datacenter @dc) (not-eq item.Datacenter ""))}}
|
{{/if}}
|
||||||
<dl class="datacenter">
|
{{#if (and (not-eq item.Datacenter @dc) (not-eq item.Datacenter ""))}}
|
||||||
<dt>
|
<dl class="datacenter">
|
||||||
<Tooltip>
|
<dt>
|
||||||
Datacenter
|
<Tooltip>
|
||||||
</Tooltip>
|
Datacenter
|
||||||
</dt>
|
</Tooltip>
|
||||||
<dd>
|
</dt>
|
||||||
{{item.Datacenter}}
|
<dd>
|
||||||
</dd>
|
{{item.Datacenter}}
|
||||||
</dl>
|
</dd>
|
||||||
{{/if}}
|
</dl>
|
||||||
{{#if (gt item.LocalBindPort 0)}}
|
{{/if}}
|
||||||
|
{{#if (gt item.LocalBindPort 0)}}
|
||||||
{{#let (concat (or item.LocalBindAddress '127.0.0.1') ':' item.LocalBindPort) as |combinedAddress|}}
|
{{#let (concat (or item.LocalBindAddress '127.0.0.1') ':' item.LocalBindPort) as |combinedAddress|}}
|
||||||
<dl class="local-bind-address">
|
<dl class="local-bind-address">
|
||||||
<dt>
|
<dt>
|
||||||
<span>
|
<span>
|
||||||
Address
|
Address
|
||||||
</span>
|
</span>
|
||||||
</dt>
|
</dt>
|
||||||
<dd>
|
<dd>
|
||||||
<CopyButton
|
<CopyButton
|
||||||
@value={{combinedAddress}}
|
@value={{combinedAddress}}
|
||||||
@name="Address"
|
@name="Address"
|
||||||
/>
|
/>
|
||||||
{{combinedAddress}}
|
{{combinedAddress}}
|
||||||
</dd>
|
</dd>
|
||||||
</dl>
|
</dl>
|
||||||
{{/let}}
|
{{/let}}
|
||||||
{{/if}}
|
{{/if}}
|
||||||
</div>
|
</div>
|
||||||
</li>
|
</li>
|
||||||
{{/each}}
|
{{/each}}
|
||||||
</ul>
|
</ul>
|
||||||
{{else}}
|
|
||||||
{{yield api to="empty"}}
|
|
||||||
{{/if}}
|
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -1,24 +0,0 @@
|
||||||
import Component from '@glimmer/component';
|
|
||||||
import { inject as service } from '@ember/service';
|
|
||||||
import { sort } from '@ember/object/computed';
|
|
||||||
|
|
||||||
export default class ConsulUpstreamInstanceList extends Component {
|
|
||||||
@service('sort') sort;
|
|
||||||
@service('search') search;
|
|
||||||
|
|
||||||
@sort('searched', 'comparator') sorted;
|
|
||||||
|
|
||||||
get items() {
|
|
||||||
return this.sorted;
|
|
||||||
}
|
|
||||||
get searched() {
|
|
||||||
if (typeof this.args.search === 'undefined') {
|
|
||||||
return this.args.items;
|
|
||||||
}
|
|
||||||
const predicate = this.search.predicate('upstream-instance');
|
|
||||||
return this.args.items.filter(predicate(this.args.search));
|
|
||||||
}
|
|
||||||
get comparator() {
|
|
||||||
return this.sort.comparator('upstream-instance')(this.args.sort);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -2,11 +2,33 @@
|
||||||
class="consul-upstream-instance-search-bar filter-bar"
|
class="consul-upstream-instance-search-bar filter-bar"
|
||||||
...attributes
|
...attributes
|
||||||
>
|
>
|
||||||
<FreetextFilter
|
<div class="search">
|
||||||
@onsearch={{action @onsearch}}
|
<FreetextFilter
|
||||||
@value={{@search}}
|
@onsearch={{action @onsearch}}
|
||||||
@placeholder="Search"
|
@value={{@search}}
|
||||||
/>
|
@placeholder="Search"
|
||||||
|
>
|
||||||
|
<PopoverSelect
|
||||||
|
class="type-search-properties"
|
||||||
|
@position="right"
|
||||||
|
@onchange={{action @onfilter.searchproperty}}
|
||||||
|
@multiple={{true}}
|
||||||
|
as |components|>
|
||||||
|
<BlockSlot @name="selected">
|
||||||
|
<span>
|
||||||
|
Search across
|
||||||
|
</span>
|
||||||
|
</BlockSlot>
|
||||||
|
<BlockSlot @name="options">
|
||||||
|
{{#let components.Optgroup components.Option as |Optgroup Option|}}
|
||||||
|
{{#each @searchproperties as |prop|}}
|
||||||
|
<Option @value={{prop}} @selected={{contains prop @filter.searchproperties}}>{{prop}}</Option>
|
||||||
|
{{/each}}
|
||||||
|
{{/let}}
|
||||||
|
</BlockSlot>
|
||||||
|
</PopoverSelect>
|
||||||
|
</FreetextFilter>
|
||||||
|
</div>
|
||||||
<div class="sort">
|
<div class="sort">
|
||||||
{{#let (or @sort 'DestinationName:asc') as |sort|}}
|
{{#let (or @sort 'DestinationName:asc') as |sort|}}
|
||||||
<PopoverSelect
|
<PopoverSelect
|
||||||
|
|
|
@ -0,0 +1,47 @@
|
||||||
|
## DataSource
|
||||||
|
|
||||||
|
```handlebars
|
||||||
|
<DataCollection
|
||||||
|
@search={{''}}
|
||||||
|
@sort={{''}}
|
||||||
|
@filter={{hash
|
||||||
|
searchproperties=(array)
|
||||||
|
}}
|
||||||
|
@items={{array}}
|
||||||
|
as |collection|>
|
||||||
|
{{collection.items.length}}
|
||||||
|
<collection.Collection>
|
||||||
|
Has Results
|
||||||
|
</collection.Collection>
|
||||||
|
<collection.Empty>
|
||||||
|
Is Empty
|
||||||
|
</collection.Empty>
|
||||||
|
</DataCollection>
|
||||||
|
```
|
||||||
|
|
||||||
|
### Arguments
|
||||||
|
|
||||||
|
| Argument | Type | Default | Description |
|
||||||
|
| --- | --- | --- | --- |
|
||||||
|
| `items` | `Array` | [] | The collection of data to search/sort/filter |
|
||||||
|
| `search` | `String` | '' | A search term to use for searching |
|
||||||
|
| `sort` | `String` | '' | A sort term to use for sorting on ('Name:asc') |
|
||||||
|
| `filter` | `Object` | | An object whose properties are the properties/values to filter on |
|
||||||
|
|
||||||
|
### Yields
|
||||||
|
|
||||||
|
The DataCollection yields an object containing the following:
|
||||||
|
|
||||||
|
| Property | Type | Description |
|
||||||
|
| --- | --- | --- |
|
||||||
|
| `items` | `Array` | The resulting collection of data after searching/sorting/filtering |
|
||||||
|
| `search` | `Function` | An action used to perform a search - takes a single string argument that should be the search term |
|
||||||
|
| `Collection` | `Component` | A slot-like component that only renders when the items in the collection is greater than 0 |
|
||||||
|
| `Empty` | `Component` | A slot-like component that only renders when the items in the collection is 0 |
|
||||||
|
|
||||||
|
### See
|
||||||
|
|
||||||
|
- [Component Source Code](./index.js)
|
||||||
|
- [Template Source Code](./index.hbs)
|
||||||
|
|
||||||
|
---
|
|
@ -1,4 +1,6 @@
|
||||||
|
{{did-update (action (fn (set this 'term') '') @search)}}
|
||||||
{{yield (hash
|
{{yield (hash
|
||||||
|
search=(action this.search)
|
||||||
items=this.items
|
items=this.items
|
||||||
Collection=(if (gt this.items.length 0) (component 'anonymous') '')
|
Collection=(if (gt this.items.length 0) (component 'anonymous') '')
|
||||||
Empty=(if (eq this.items.length 0) (component 'anonymous') '')
|
Empty=(if (eq this.items.length 0) (component 'anonymous') '')
|
||||||
|
|
|
@ -1,18 +1,32 @@
|
||||||
import Component from '@glimmer/component';
|
import Component from '@glimmer/component';
|
||||||
import { inject as service } from '@ember/service';
|
import { inject as service } from '@ember/service';
|
||||||
import { computed } from '@ember/object';
|
import { computed, get, action } from '@ember/object';
|
||||||
|
import { tracked } from '@glimmer/tracking';
|
||||||
import { sort } from '@ember/object/computed';
|
import { sort } from '@ember/object/computed';
|
||||||
import { defineProperty } from '@ember/object';
|
import { defineProperty } from '@ember/object';
|
||||||
|
|
||||||
export default class DataCollectionComponent extends Component {
|
export default class DataCollectionComponent extends Component {
|
||||||
@service('filter') filter;
|
@service('filter') filter;
|
||||||
@service('sort') sort;
|
@service('sort') sort;
|
||||||
@service('search') search;
|
@service('search') searchService;
|
||||||
|
|
||||||
|
@tracked term = '';
|
||||||
|
|
||||||
get type() {
|
get type() {
|
||||||
return this.args.type;
|
return this.args.type;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@computed('term', 'args.search')
|
||||||
|
get searchTerm() {
|
||||||
|
return this.term || this.args.search || '';
|
||||||
|
}
|
||||||
|
|
||||||
|
@action
|
||||||
|
search(term) {
|
||||||
|
this.term = term;
|
||||||
|
return this.items;
|
||||||
|
}
|
||||||
|
|
||||||
@computed('args.items', 'args.items.content')
|
@computed('args.items', 'args.items.content')
|
||||||
get content() {
|
get content() {
|
||||||
// TODO: Temporary little hack to ensure we detect DataSource proxy
|
// TODO: Temporary little hack to ensure we detect DataSource proxy
|
||||||
|
@ -37,17 +51,17 @@ export default class DataCollectionComponent extends Component {
|
||||||
return this.sorted;
|
return this.sorted;
|
||||||
}
|
}
|
||||||
|
|
||||||
@computed('type', 'filtered', 'args.filters.searchproperties', 'args.search')
|
@computed('type', 'filtered', 'args.filters.searchproperties', 'searchTerm')
|
||||||
get searched() {
|
get searched() {
|
||||||
if (typeof this.args.search === 'undefined') {
|
if (typeof this.searchTerm === '') {
|
||||||
return this.filtered;
|
return this.filtered;
|
||||||
}
|
}
|
||||||
const predicate = this.search.predicate(this.type);
|
const predicate = this.searchService.predicate(this.type);
|
||||||
const options = {};
|
const options = {};
|
||||||
if (typeof this.args.filters.searchproperties !== 'undefined') {
|
if (typeof get(this, 'args.filters.searchproperties') !== 'undefined') {
|
||||||
options.properties = this.args.filters.searchproperties;
|
options.properties = this.args.filters.searchproperties;
|
||||||
}
|
}
|
||||||
return this.filtered.filter(predicate(this.args.search, options));
|
return this.filtered.filter(predicate(this.searchTerm, options));
|
||||||
}
|
}
|
||||||
|
|
||||||
@computed('type', 'content', 'args.filters')
|
@computed('type', 'content', 'args.filters')
|
||||||
|
|
|
@ -1,9 +0,0 @@
|
||||||
import Helper from '@ember/component/helper';
|
|
||||||
import { inject as service } from '@ember/service';
|
|
||||||
|
|
||||||
export default Helper.extend({
|
|
||||||
sort: service('sort'),
|
|
||||||
compute([type, key], hash) {
|
|
||||||
return this.sort.comparator(type)(key);
|
|
||||||
},
|
|
||||||
});
|
|
|
@ -1,9 +0,0 @@
|
||||||
import Helper from '@ember/component/helper';
|
|
||||||
import { inject as service } from '@ember/service';
|
|
||||||
|
|
||||||
export default Helper.extend({
|
|
||||||
search: service('search'),
|
|
||||||
compute([type, items], hash) {
|
|
||||||
return this.search.searchable(type).add(items);
|
|
||||||
},
|
|
||||||
});
|
|
|
@ -1,46 +0,0 @@
|
||||||
import { helper } from '@ember/component/helper';
|
|
||||||
import { slugify } from 'consul-ui/helpers/slugify';
|
|
||||||
export const selectableKeyValues = function(params = [], hash = {}) {
|
|
||||||
let selected;
|
|
||||||
|
|
||||||
const items = params.map(function(item, i) {
|
|
||||||
let key, value;
|
|
||||||
switch (typeof item) {
|
|
||||||
case 'string':
|
|
||||||
key = slugify([item]);
|
|
||||||
value = item;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
if (item.length > 1) {
|
|
||||||
key = item[0];
|
|
||||||
value = item[1];
|
|
||||||
} else {
|
|
||||||
key = slugify([item[0]]);
|
|
||||||
value = item[0];
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
const kv = {
|
|
||||||
key: key,
|
|
||||||
value: value,
|
|
||||||
};
|
|
||||||
switch (typeof hash.selected) {
|
|
||||||
case 'string':
|
|
||||||
if (hash.selected === item[0]) {
|
|
||||||
selected = kv;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case 'number':
|
|
||||||
if (hash.selected === i) {
|
|
||||||
selected = kv;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
return kv;
|
|
||||||
});
|
|
||||||
return {
|
|
||||||
items: items,
|
|
||||||
selected: typeof selected === 'undefined' ? items[0] : selected,
|
|
||||||
};
|
|
||||||
};
|
|
||||||
export default helper(selectableKeyValues);
|
|
|
@ -7,6 +7,10 @@ export default class UpstreamsRoute extends Route {
|
||||||
as: 'filter',
|
as: 'filter',
|
||||||
replace: true,
|
replace: true,
|
||||||
},
|
},
|
||||||
|
searchproperty: {
|
||||||
|
as: 'searchproperty',
|
||||||
|
empty: [['DestinationName', 'LocalBindAddress', 'LocalBindPort']],
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
model() {
|
model() {
|
||||||
|
@ -14,7 +18,10 @@ export default class UpstreamsRoute extends Route {
|
||||||
.split('.')
|
.split('.')
|
||||||
.slice(0, -1)
|
.slice(0, -1)
|
||||||
.join('.');
|
.join('.');
|
||||||
return this.modelFor(parent);
|
return {
|
||||||
|
...this.modelFor(parent),
|
||||||
|
searchProperties: this.queryParams.searchproperty.empty[0],
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
setupController(controller, model) {
|
setupController(controller, model) {
|
||||||
|
|
|
@ -1,21 +0,0 @@
|
||||||
import { get } from '@ember/object';
|
|
||||||
export default function(filterable) {
|
|
||||||
return filterable(function(item, { s = '' }) {
|
|
||||||
const term = s.toLowerCase();
|
|
||||||
return (
|
|
||||||
get(item, 'Service')
|
|
||||||
.toLowerCase()
|
|
||||||
.indexOf(term) !== -1 ||
|
|
||||||
get(item, 'ID')
|
|
||||||
.toLowerCase()
|
|
||||||
.indexOf(term) !== -1 ||
|
|
||||||
(get(item, 'Tags') || []).some(function(item) {
|
|
||||||
return item.toLowerCase().indexOf(term) !== -1;
|
|
||||||
}) ||
|
|
||||||
get(item, 'Port')
|
|
||||||
.toString()
|
|
||||||
.toLowerCase()
|
|
||||||
.indexOf(term) !== -1
|
|
||||||
);
|
|
||||||
});
|
|
||||||
}
|
|
|
@ -1,14 +0,0 @@
|
||||||
import { get } from '@ember/object';
|
|
||||||
export default function(filterable) {
|
|
||||||
return filterable(function(item, { s = '' }) {
|
|
||||||
const sLower = s.toLowerCase();
|
|
||||||
return (
|
|
||||||
get(item, 'Name')
|
|
||||||
.toLowerCase()
|
|
||||||
.indexOf(sLower) !== -1 ||
|
|
||||||
get(item, 'Description')
|
|
||||||
.toLowerCase()
|
|
||||||
.indexOf(sLower) !== -1
|
|
||||||
);
|
|
||||||
});
|
|
||||||
}
|
|
|
@ -1,20 +0,0 @@
|
||||||
import { get } from '@ember/object';
|
|
||||||
export default function(filterable) {
|
|
||||||
return filterable(function(item, { s = '' }) {
|
|
||||||
const sLower = s.toLowerCase();
|
|
||||||
return (
|
|
||||||
get(item, 'Name')
|
|
||||||
.toLowerCase()
|
|
||||||
.indexOf(sLower) !== -1 ||
|
|
||||||
get(item, 'Description')
|
|
||||||
.toLowerCase()
|
|
||||||
.indexOf(sLower) !== -1 ||
|
|
||||||
(get(item, 'Policies') || []).some(function(item) {
|
|
||||||
return item.Name.toLowerCase().indexOf(sLower) !== -1;
|
|
||||||
}) ||
|
|
||||||
(get(item, 'ServiceIdentities') || []).some(function(item) {
|
|
||||||
return item.ServiceName.toLowerCase().indexOf(sLower) !== -1;
|
|
||||||
})
|
|
||||||
);
|
|
||||||
});
|
|
||||||
}
|
|
|
@ -1,15 +0,0 @@
|
||||||
import { get } from '@ember/object';
|
|
||||||
export default function(filterable) {
|
|
||||||
return filterable(function(item, { s = '' }) {
|
|
||||||
const term = s.toLowerCase();
|
|
||||||
return (
|
|
||||||
get(item, 'Node.Node')
|
|
||||||
.toLowerCase()
|
|
||||||
.indexOf(term) !== -1 ||
|
|
||||||
get(item, 'Service.ID')
|
|
||||||
.toLowerCase()
|
|
||||||
.indexOf(term) !== -1 ||
|
|
||||||
`${get(item, 'Service.Address')}:${get(item, 'Service.Port')}`.indexOf(term) !== -1
|
|
||||||
);
|
|
||||||
});
|
|
||||||
}
|
|
|
@ -1,12 +1,10 @@
|
||||||
export default () => term => item => {
|
export default {
|
||||||
const lowerTerm = term.toLowerCase();
|
DestinationName: (item, value) =>
|
||||||
return Object.entries(item)
|
item.DestinationName.toLowerCase().indexOf(value.toLowerCase()) !== -1,
|
||||||
.filter(([key, value]) => key !== 'DestinationType')
|
LocalBindAddress: (item, value) =>
|
||||||
.some(
|
item.LocalBindAddress.toLowerCase().indexOf(value.toLowerCase()) !== -1,
|
||||||
([key, value]) =>
|
LocalBindPort: (item, value) =>
|
||||||
value
|
item.LocalBindPort.toString()
|
||||||
.toString()
|
.toLowerCase()
|
||||||
.toLowerCase()
|
.indexOf(value.toLowerCase()) !== -1,
|
||||||
.indexOf(lowerTerm) !== -1
|
|
||||||
);
|
|
||||||
};
|
};
|
||||||
|
|
|
@ -14,20 +14,6 @@ import role from 'consul-ui/search/predicates/role';
|
||||||
import policy from 'consul-ui/search/predicates/policy';
|
import policy from 'consul-ui/search/predicates/policy';
|
||||||
import nspace from 'consul-ui/search/predicates/nspace';
|
import nspace from 'consul-ui/search/predicates/nspace';
|
||||||
|
|
||||||
import filteredRole from 'consul-ui/search/filters/role';
|
|
||||||
import filteredPolicy from 'consul-ui/search/filters/policy';
|
|
||||||
// service instance
|
|
||||||
import nodeService from 'consul-ui/search/filters/node/service';
|
|
||||||
import serviceNode from 'consul-ui/search/filters/service/node';
|
|
||||||
|
|
||||||
import filterableFactory from 'consul-ui/utils/search/filterable';
|
|
||||||
const filterable = filterableFactory();
|
|
||||||
const searchables = {
|
|
||||||
serviceInstance: serviceNode(filterable),
|
|
||||||
nodeservice: nodeService(filterable),
|
|
||||||
role: filteredRole(filterable),
|
|
||||||
policy: filteredPolicy(filterable),
|
|
||||||
};
|
|
||||||
export const search = spec => {
|
export const search = spec => {
|
||||||
let possible = Object.keys(spec);
|
let possible = Object.keys(spec);
|
||||||
return (term, options = {}) => {
|
return (term, options = {}) => {
|
||||||
|
@ -47,7 +33,7 @@ const predicates = {
|
||||||
intention: search(intention),
|
intention: search(intention),
|
||||||
service: search(service),
|
service: search(service),
|
||||||
['service-instance']: search(serviceInstance),
|
['service-instance']: search(serviceInstance),
|
||||||
['upstream-instance']: upstreamInstance(),
|
['upstream-instance']: search(upstreamInstance),
|
||||||
['health-check']: search(healthCheck),
|
['health-check']: search(healthCheck),
|
||||||
node: search(node),
|
node: search(node),
|
||||||
kv: search(kv),
|
kv: search(kv),
|
||||||
|
@ -58,9 +44,6 @@ const predicates = {
|
||||||
nspace: search(nspace),
|
nspace: search(nspace),
|
||||||
};
|
};
|
||||||
export default class SearchService extends Service {
|
export default class SearchService extends Service {
|
||||||
searchable(name) {
|
|
||||||
return searchables[name];
|
|
||||||
}
|
|
||||||
predicate(name) {
|
predicate(name) {
|
||||||
return predicates[name];
|
return predicates[name];
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,37 +1,53 @@
|
||||||
<div class="tab-section">
|
<div class="tab-section">
|
||||||
<div role="tabpanel">
|
<div role="tabpanel">
|
||||||
{{#let (or sortBy "DestinationName:asc") as |sort|}}
|
{{#let (hash
|
||||||
{{#if (gt proxy.Service.Proxy.Upstreams.length 0)}}
|
searchproperties=(if (not-eq searchproperty undefined)
|
||||||
<input type="checkbox" id="toolbar-toggle" />
|
(split searchproperty ',')
|
||||||
<Consul::UpstreamInstance::SearchBar
|
searchProperties
|
||||||
@search={{search}}
|
)
|
||||||
@onsearch={{action (mut search) value="target.value"}}
|
) as |filters|}}
|
||||||
|
{{#let (or sortBy "DestinationName:asc") as |sort|}}
|
||||||
|
{{#if (gt proxy.Service.Proxy.Upstreams.length 0)}}
|
||||||
|
<input type="checkbox" id="toolbar-toggle" />
|
||||||
|
<Consul::UpstreamInstance::SearchBar
|
||||||
|
@search={{search}}
|
||||||
|
@onsearch={{action (mut search) value="target.value"}}
|
||||||
|
@searchproperties={{searchProperties}}
|
||||||
|
|
||||||
@sort={{sort}}
|
@sort={{sort}}
|
||||||
@onsort={{action (mut sortBy) value="target.selected"}}
|
@onsort={{action (mut sortBy) value="target.selected"}}
|
||||||
/>
|
|
||||||
<Consul::UpstreamInstance::List
|
@filter={{filters}}
|
||||||
@search={{search}}
|
@onfilter={{hash
|
||||||
@sort={{sort}}
|
searchproperty=(action (mut searchproperty) value="target.selectedItems")
|
||||||
@items={{proxy.Service.Proxy.Upstreams}}
|
}}
|
||||||
@dc={{dc}}
|
/>
|
||||||
@nspace={{nspace}}
|
<DataCollection
|
||||||
>
|
@type="upstream-instance"
|
||||||
<:empty>
|
@sort={{sort}}
|
||||||
<EmptyState>
|
@filters={{filters}}
|
||||||
<BlockSlot @name="body">
|
@search={{search}}
|
||||||
<p>
|
@items={{proxy.Service.Proxy.Upstreams}}
|
||||||
{{#if search.length}}
|
as |collection|>
|
||||||
No upstreams where found matching that search.
|
<collection.Collection>
|
||||||
{{else}}
|
<Consul::UpstreamInstance::List
|
||||||
This service has no upstreams.
|
@items={{collection.items}}
|
||||||
{{/if}}
|
@dc={{dc}}
|
||||||
</p>
|
@nspace={{nspace}}
|
||||||
</BlockSlot>
|
/>
|
||||||
</EmptyState>
|
</collection.Collection>
|
||||||
</:empty>
|
<collection.Empty>
|
||||||
</Consul::UpstreamInstance::List>
|
<EmptyState>
|
||||||
{{/if}}
|
<BlockSlot @name="body">
|
||||||
|
<p>
|
||||||
|
This service has no upstreams{{#if (gt proxy.Service.Proxy.Upstreams.length 0)}} matching that search{{/if}}.
|
||||||
|
</p>
|
||||||
|
</BlockSlot>
|
||||||
|
</EmptyState>
|
||||||
|
</collection.Empty>
|
||||||
|
</DataCollection>
|
||||||
|
{{/if}}
|
||||||
|
{{/let}}
|
||||||
{{/let}}
|
{{/let}}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
|
@ -1,49 +0,0 @@
|
||||||
import RSVP from 'rsvp';
|
|
||||||
export default function(EventTarget = RSVP.EventTarget, P = Promise) {
|
|
||||||
// TODO: Class-ify
|
|
||||||
return function(filter) {
|
|
||||||
return EventTarget.mixin({
|
|
||||||
value: '',
|
|
||||||
_data: [],
|
|
||||||
add: function(data) {
|
|
||||||
this.data = this._data = data;
|
|
||||||
return this;
|
|
||||||
},
|
|
||||||
find: function(terms = []) {
|
|
||||||
this.value = terms
|
|
||||||
.filter(function(item) {
|
|
||||||
return typeof item === 'string' && item !== '';
|
|
||||||
})
|
|
||||||
.map(function(term) {
|
|
||||||
return term.trim();
|
|
||||||
});
|
|
||||||
return P.resolve(
|
|
||||||
this.value.reduce(function(prev, term) {
|
|
||||||
return prev.filter(item => {
|
|
||||||
return filter(item, { s: term });
|
|
||||||
});
|
|
||||||
}, this._data)
|
|
||||||
);
|
|
||||||
},
|
|
||||||
search: function(terms = []) {
|
|
||||||
// specifically no return here we return `this` instead
|
|
||||||
// right now filtering is sync but we introduce an async
|
|
||||||
// flow now for later on
|
|
||||||
this.find(Array.isArray(terms) ? terms : [terms]).then(data => {
|
|
||||||
// TODO: For the moment, lets just fake a target
|
|
||||||
this.data = data;
|
|
||||||
this.trigger('change', {
|
|
||||||
target: {
|
|
||||||
value: this.value.join('\n'),
|
|
||||||
// TODO: selectedOptions is what <select> uses, consider that
|
|
||||||
data: data,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
// not returned
|
|
||||||
return data;
|
|
||||||
});
|
|
||||||
return this;
|
|
||||||
},
|
|
||||||
});
|
|
||||||
};
|
|
||||||
}
|
|
|
@ -1,24 +0,0 @@
|
||||||
import { module, skip } from 'qunit';
|
|
||||||
import { setupRenderingTest } from 'ember-qunit';
|
|
||||||
import { render } from '@ember/test-helpers';
|
|
||||||
import hbs from 'htmlbars-inline-precompile';
|
|
||||||
|
|
||||||
module('Integration | Component | changeable set', function(hooks) {
|
|
||||||
setupRenderingTest(hooks);
|
|
||||||
|
|
||||||
skip('it renders', async function(assert) {
|
|
||||||
// Set any properties with this.set('myProperty', 'value');
|
|
||||||
// Handle any actions with this.on('myAction', function(val) { ... });
|
|
||||||
|
|
||||||
await render(hbs`{{changeable-set}}`);
|
|
||||||
|
|
||||||
assert.equal(this.element.textContent.trim(), '');
|
|
||||||
|
|
||||||
// Template block usage:
|
|
||||||
await render(hbs`
|
|
||||||
{{#changeable-set}}
|
|
||||||
{{/changeable-set}}
|
|
||||||
`);
|
|
||||||
assert.equal(this.element.textContent.trim(), '');
|
|
||||||
});
|
|
||||||
});
|
|
|
@ -1,49 +0,0 @@
|
||||||
import { selectableKeyValues } from 'consul-ui/helpers/selectable-key-values';
|
|
||||||
import { module, test } from 'qunit';
|
|
||||||
|
|
||||||
module('Unit | Helper | selectable-key-values', function() {
|
|
||||||
test('it turns arrays into key values and selects the first item by default', function(assert) {
|
|
||||||
const actual = selectableKeyValues([
|
|
||||||
['key-1', 'value-1'],
|
|
||||||
['key-2', 'value-2'],
|
|
||||||
]);
|
|
||||||
assert.equal(actual.items.length, 2);
|
|
||||||
assert.deepEqual(actual.selected, { key: 'key-1', value: 'value-1' });
|
|
||||||
});
|
|
||||||
test('it turns arrays into key values and selects the defined key', function(assert) {
|
|
||||||
const actual = selectableKeyValues(
|
|
||||||
[
|
|
||||||
['key-1', 'value-1'],
|
|
||||||
['key-2', 'value-2'],
|
|
||||||
],
|
|
||||||
{
|
|
||||||
selected: 'key-2',
|
|
||||||
}
|
|
||||||
);
|
|
||||||
assert.equal(actual.items.length, 2);
|
|
||||||
assert.deepEqual(actual.selected, { key: 'key-2', value: 'value-2' });
|
|
||||||
});
|
|
||||||
test('it turns arrays into key values and selects the defined index', function(assert) {
|
|
||||||
const actual = selectableKeyValues(
|
|
||||||
[
|
|
||||||
['key-1', 'value-1'],
|
|
||||||
['key-2', 'value-2'],
|
|
||||||
],
|
|
||||||
{
|
|
||||||
selected: 1,
|
|
||||||
}
|
|
||||||
);
|
|
||||||
assert.equal(actual.items.length, 2);
|
|
||||||
assert.deepEqual(actual.selected, { key: 'key-2', value: 'value-2' });
|
|
||||||
});
|
|
||||||
test('it turns arrays with only one element into key values and selects the defined index', function(assert) {
|
|
||||||
const actual = selectableKeyValues([['Value 1'], ['Value 2']], { selected: 1 });
|
|
||||||
assert.equal(actual.items.length, 2);
|
|
||||||
assert.deepEqual(actual.selected, { key: 'value-2', value: 'Value 2' });
|
|
||||||
});
|
|
||||||
test('it turns strings into key values and selects the defined index', function(assert) {
|
|
||||||
const actual = selectableKeyValues(['Value 1', 'Value 2'], { selected: 1 });
|
|
||||||
assert.equal(actual.items.length, 2);
|
|
||||||
assert.deepEqual(actual.selected, { key: 'value-2', value: 'Value 2' });
|
|
||||||
});
|
|
||||||
});
|
|
|
@ -1,94 +0,0 @@
|
||||||
import getFilter from 'consul-ui/search/filters/node/service';
|
|
||||||
import { module, test } from 'qunit';
|
|
||||||
|
|
||||||
module('Unit | Search | Filter | node/service', function() {
|
|
||||||
const filter = getFilter(cb => cb);
|
|
||||||
test('items are found by properties', function(assert) {
|
|
||||||
[
|
|
||||||
{
|
|
||||||
Service: 'service-HIT',
|
|
||||||
ID: 'id',
|
|
||||||
Port: 8500,
|
|
||||||
Tags: [],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
Service: 'service',
|
|
||||||
ID: 'id-HiT',
|
|
||||||
Port: 8500,
|
|
||||||
Tags: [],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
Service: 'service',
|
|
||||||
ID: 'id',
|
|
||||||
Port: 8500,
|
|
||||||
Tags: ['tag', 'tag-withHiT'],
|
|
||||||
},
|
|
||||||
].forEach(function(item) {
|
|
||||||
const actual = filter(item, {
|
|
||||||
s: 'hit',
|
|
||||||
});
|
|
||||||
assert.ok(actual);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
test('items are found by port (non-string)', function(assert) {
|
|
||||||
[
|
|
||||||
{
|
|
||||||
Service: 'service',
|
|
||||||
ID: 'id',
|
|
||||||
Port: 8500,
|
|
||||||
Tags: ['tag', 'tag'],
|
|
||||||
},
|
|
||||||
].forEach(function(item) {
|
|
||||||
const actual = filter(item, {
|
|
||||||
s: '8500',
|
|
||||||
});
|
|
||||||
assert.ok(actual);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
test('items are not found', function(assert) {
|
|
||||||
[
|
|
||||||
{
|
|
||||||
Service: 'service',
|
|
||||||
ID: 'id',
|
|
||||||
Port: 8500,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
Service: 'service',
|
|
||||||
ID: 'id',
|
|
||||||
Port: 8500,
|
|
||||||
Tags: ['one', 'two'],
|
|
||||||
},
|
|
||||||
].forEach(function(item) {
|
|
||||||
const actual = filter(item, {
|
|
||||||
s: 'hit',
|
|
||||||
});
|
|
||||||
assert.notOk(actual);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
test('tags can be empty', function(assert) {
|
|
||||||
[
|
|
||||||
{
|
|
||||||
Service: 'service',
|
|
||||||
ID: 'id',
|
|
||||||
Port: 8500,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
Service: 'service',
|
|
||||||
ID: 'id',
|
|
||||||
Port: 8500,
|
|
||||||
Tags: null,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
Service: 'service',
|
|
||||||
ID: 'id',
|
|
||||||
Port: 8500,
|
|
||||||
Tags: [],
|
|
||||||
},
|
|
||||||
].forEach(function(item) {
|
|
||||||
const actual = filter(item, {
|
|
||||||
s: 'hit',
|
|
||||||
});
|
|
||||||
assert.notOk(actual);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
|
@ -1,36 +0,0 @@
|
||||||
import getFilter from 'consul-ui/search/filters/policy';
|
|
||||||
import { module, test } from 'qunit';
|
|
||||||
|
|
||||||
module('Unit | Search | Filter | policy', function() {
|
|
||||||
const filter = getFilter(cb => cb);
|
|
||||||
test('items are found by properties', function(assert) {
|
|
||||||
[
|
|
||||||
{
|
|
||||||
Name: 'name-HIT',
|
|
||||||
Description: 'description',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
Name: 'name',
|
|
||||||
Description: 'desc-HIT-ription',
|
|
||||||
},
|
|
||||||
].forEach(function(item) {
|
|
||||||
const actual = filter(item, {
|
|
||||||
s: 'hit',
|
|
||||||
});
|
|
||||||
assert.ok(actual);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
test('items are not found', function(assert) {
|
|
||||||
[
|
|
||||||
{
|
|
||||||
Name: 'name',
|
|
||||||
Description: 'description',
|
|
||||||
},
|
|
||||||
].forEach(function(item) {
|
|
||||||
const actual = filter(item, {
|
|
||||||
s: 'hit',
|
|
||||||
});
|
|
||||||
assert.notOk(actual);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
|
@ -1,74 +0,0 @@
|
||||||
import getFilter from 'consul-ui/search/filters/service/node';
|
|
||||||
import { module, test } from 'qunit';
|
|
||||||
|
|
||||||
module('Unit | Search | Filter | service/node', function() {
|
|
||||||
const filter = getFilter(cb => cb);
|
|
||||||
test('items are found by properties', function(assert) {
|
|
||||||
[
|
|
||||||
{
|
|
||||||
Service: {
|
|
||||||
ID: 'hit',
|
|
||||||
},
|
|
||||||
Node: {
|
|
||||||
Node: 'node',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
Service: {
|
|
||||||
ID: 'id',
|
|
||||||
},
|
|
||||||
Node: {
|
|
||||||
Node: 'nodeHiT',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
].forEach(function(item) {
|
|
||||||
const actual = filter(item, {
|
|
||||||
s: 'hit',
|
|
||||||
});
|
|
||||||
assert.ok(actual);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
test('items are found by address:port', function(assert) {
|
|
||||||
const instance = {
|
|
||||||
Service: {
|
|
||||||
ID: 'id',
|
|
||||||
Address: '0.0.0.0',
|
|
||||||
Port: 8000,
|
|
||||||
},
|
|
||||||
Node: {
|
|
||||||
Node: 'node-0',
|
|
||||||
},
|
|
||||||
};
|
|
||||||
['0.0.0.0', '8000', '0:8000', '0.0.0.0:8000'].forEach(function(item) {
|
|
||||||
let actual = filter(instance, {
|
|
||||||
s: item,
|
|
||||||
});
|
|
||||||
assert.ok(actual);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
test('items are not found', function(assert) {
|
|
||||||
[
|
|
||||||
{
|
|
||||||
Service: {
|
|
||||||
ID: 'ID',
|
|
||||||
},
|
|
||||||
Node: {
|
|
||||||
Node: 'node',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
Service: {
|
|
||||||
ID: 'id',
|
|
||||||
},
|
|
||||||
Node: {
|
|
||||||
Node: 'node',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
].forEach(function(item) {
|
|
||||||
const actual = filter(item, {
|
|
||||||
s: 'hit',
|
|
||||||
});
|
|
||||||
assert.notOk(actual);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
|
@ -0,0 +1,29 @@
|
||||||
|
import predicates from 'consul-ui/search/predicates/policy';
|
||||||
|
import { search as create } from 'consul-ui/services/search';
|
||||||
|
import { module, test } from 'qunit';
|
||||||
|
|
||||||
|
module('Unit | Search | Predicate | policy', function() {
|
||||||
|
const search = create(predicates);
|
||||||
|
test('items are found by properties', function(assert) {
|
||||||
|
const actual = [
|
||||||
|
{
|
||||||
|
Name: 'name-HIT',
|
||||||
|
Description: 'description',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Name: 'name',
|
||||||
|
Description: 'desc-HIT-ription',
|
||||||
|
},
|
||||||
|
].filter(search('hit'));
|
||||||
|
assert.equal(actual.length, 2);
|
||||||
|
});
|
||||||
|
test('items are not found', function(assert) {
|
||||||
|
const actual = [
|
||||||
|
{
|
||||||
|
Name: 'name',
|
||||||
|
Description: 'description',
|
||||||
|
},
|
||||||
|
].filter(search('hit'));
|
||||||
|
assert.equal(actual.length, 0);
|
||||||
|
});
|
||||||
|
});
|
|
@ -1,10 +1,11 @@
|
||||||
import getFilter from 'consul-ui/search/filters/role';
|
import predicates from 'consul-ui/search/predicates/role';
|
||||||
|
import { search as create } from 'consul-ui/services/search';
|
||||||
import { module, test } from 'qunit';
|
import { module, test } from 'qunit';
|
||||||
|
|
||||||
module('Unit | Search | Filter | role', function() {
|
module('Unit | Search | Predicate | role', function() {
|
||||||
const filter = getFilter(cb => cb);
|
const search = create(predicates);
|
||||||
test('items are found by properties', function(assert) {
|
test('items are found by properties', function(assert) {
|
||||||
[
|
const actual = [
|
||||||
{
|
{
|
||||||
Name: 'name-HIT',
|
Name: 'name-HIT',
|
||||||
Description: 'description',
|
Description: 'description',
|
||||||
|
@ -28,15 +29,11 @@ module('Unit | Search | Filter | role', function() {
|
||||||
{ ServiceName: 'service-identity-HIT' },
|
{ ServiceName: 'service-identity-HIT' },
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
].forEach(function(item) {
|
].filter(search('hit'));
|
||||||
const actual = filter(item, {
|
assert.equal(actual.length, 4);
|
||||||
s: 'hit',
|
|
||||||
});
|
|
||||||
assert.ok(actual);
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
test('items are not found', function(assert) {
|
test('items are not found', function(assert) {
|
||||||
[
|
const actual = [
|
||||||
{
|
{
|
||||||
Name: 'name',
|
Name: 'name',
|
||||||
Description: 'description',
|
Description: 'description',
|
||||||
|
@ -53,15 +50,11 @@ module('Unit | Search | Filter | role', function() {
|
||||||
Description: 'description',
|
Description: 'description',
|
||||||
ServiceIdenitities: [{ ServiceName: 'si' }, { ServiceName: 'si-second' }],
|
ServiceIdenitities: [{ ServiceName: 'si' }, { ServiceName: 'si-second' }],
|
||||||
},
|
},
|
||||||
].forEach(function(item) {
|
].filter(search('hit'));
|
||||||
const actual = filter(item, {
|
assert.equal(actual.length, 0);
|
||||||
s: 'hit',
|
|
||||||
});
|
|
||||||
assert.notOk(actual);
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
test('arraylike things can be empty', function(assert) {
|
test('arraylike things can be empty', function(assert) {
|
||||||
[
|
const actual = [
|
||||||
{
|
{
|
||||||
Name: 'name',
|
Name: 'name',
|
||||||
Description: 'description',
|
Description: 'description',
|
||||||
|
@ -79,11 +72,7 @@ module('Unit | Search | Filter | role', function() {
|
||||||
Policies: [],
|
Policies: [],
|
||||||
ServiceIdentities: [],
|
ServiceIdentities: [],
|
||||||
},
|
},
|
||||||
].forEach(function(item) {
|
].filter(search('hit'));
|
||||||
const actual = filter(item, {
|
assert.equal(actual.length, 0);
|
||||||
s: 'hit',
|
|
||||||
});
|
|
||||||
assert.notOk(actual);
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
});
|
});
|
|
@ -1,10 +0,0 @@
|
||||||
import searchFilterable from 'consul-ui/utils/search/filterable';
|
|
||||||
import { module, test } from 'qunit';
|
|
||||||
|
|
||||||
module('Unit | Utility | search/filterable', function() {
|
|
||||||
// Replace this with your real tests.
|
|
||||||
test('it works', function(assert) {
|
|
||||||
let result = searchFilterable();
|
|
||||||
assert.ok(result);
|
|
||||||
});
|
|
||||||
});
|
|
Loading…
Reference in New Issue