diff --git a/.changelog/9442.txt b/.changelog/9442.txt new file mode 100644 index 000000000..afdd67d20 --- /dev/null +++ b/.changelog/9442.txt @@ -0,0 +1,4 @@ +```release-note:feature +ui: Add additional search/filter status pills for viewing and removing current +filters in listing views +``` diff --git a/ui/packages/consul-ui/.template-lintrc.js b/ui/packages/consul-ui/.template-lintrc.js index c654b15ca..8f185a67d 100644 --- a/ui/packages/consul-ui/.template-lintrc.js +++ b/ui/packages/consul-ui/.template-lintrc.js @@ -31,6 +31,8 @@ module.exports = { 'no-unnecessary-component-helper': false, 'link-href-attributes': false, + // we need to be able to say tabindex={{@tabindex}} + 'no-positive-tabindex': false, 'no-bare-strings': false, }, diff --git a/ui/packages/consul-ui/app/components/action/index.hbs b/ui/packages/consul-ui/app/components/action/index.hbs index 75484eb11..34667ae4c 100644 --- a/ui/packages/consul-ui/app/components/action/index.hbs +++ b/ui/packages/consul-ui/app/components/action/index.hbs @@ -19,9 +19,9 @@ {{~/if~}} {{~else~}} {{~/if}} \ No newline at end of file diff --git a/ui/packages/consul-ui/app/components/confirmation-alert/index.hbs b/ui/packages/consul-ui/app/components/confirmation-alert/index.hbs index 803ccd23c..6df616206 100644 --- a/ui/packages/consul-ui/app/components/confirmation-alert/index.hbs +++ b/ui/packages/consul-ui/app/components/confirmation-alert/index.hbs @@ -14,6 +14,7 @@ diff --git a/ui/packages/consul-ui/app/components/consul/acl/search-bar/index.hbs b/ui/packages/consul-ui/app/components/consul/acl/search-bar/index.hbs index c5beb16ad..978dc749b 100644 --- a/ui/packages/consul-ui/app/components/consul/acl/search-bar/index.hbs +++ b/ui/packages/consul-ui/app/components/consul/acl/search-bar/index.hbs @@ -1,59 +1,127 @@ - + + + <:search as |search|> + +{{#if @filter.searchproperty}} + + + + {{t "common.search.searchproperty"}} + + + + {{#let components.Optgroup components.Option as |Optgroup Option|}} + {{#each @filter.searchproperty.default as |prop|}} + + {{/each}} + {{/let}} + + + {{/if}} + + + <:filter as |search|> + + + + {{t "components.consul.acl.search-bar.kind.name"}} + + + + {{#let components.Optgroup components.Option as |Optgroup Option|}} + {{#each (array "management" "client") as |state|}} + + {{/each}} + {{/let}} + + + + <:sort as |search|> + + + + {{#let (from-entries (array + (array "Name:asc" (t "common.sort.alpha.asc")) + (array "Name:desc" (t "common.sort.alpha.desc")) + )) + as |selectable| + }} + {{get selectable @sort.value}} + {{/let}} + + + + {{#let components.Optgroup components.Option as |Optgroup Option|}} + + + + + {{/let}} + + + + diff --git a/ui/packages/consul-ui/app/components/consul/health-check/search-bar/index.hbs b/ui/packages/consul-ui/app/components/consul/health-check/search-bar/index.hbs index abf590933..78392f665 100644 --- a/ui/packages/consul-ui/app/components/consul/health-check/search-bar/index.hbs +++ b/ui/packages/consul-ui/app/components/consul/health-check/search-bar/index.hbs @@ -1,140 +1,190 @@ - \ No newline at end of file + + + + \ No newline at end of file diff --git a/ui/packages/consul-ui/app/components/consul/intention/search-bar/index.hbs b/ui/packages/consul-ui/app/components/consul/intention/search-bar/index.hbs index 5b65c1b97..0ffc6a0e0 100644 --- a/ui/packages/consul-ui/app/components/consul/intention/search-bar/index.hbs +++ b/ui/packages/consul-ui/app/components/consul/intention/search-bar/index.hbs @@ -1,102 +1,140 @@ - \ No newline at end of file + {{/let}} + + + + \ No newline at end of file diff --git a/ui/packages/consul-ui/app/components/consul/kv/search-bar/index.hbs b/ui/packages/consul-ui/app/components/consul/kv/search-bar/index.hbs index 0652216a1..9636e9bc5 100644 --- a/ui/packages/consul-ui/app/components/consul/kv/search-bar/index.hbs +++ b/ui/packages/consul-ui/app/components/consul/kv/search-bar/index.hbs @@ -1,68 +1,128 @@ - \ No newline at end of file + + + <:search as |search|> + +{{#if @filter.searchproperty}} + + + + {{t "common.search.searchproperty"}} + + + + {{#let components.Optgroup components.Option as |Optgroup Option|}} + {{#each @filter.searchproperty.default as |prop|}} + + {{/each}} + {{/let}} + + + {{/if}} + + + <:filter as |search|> + + + + {{t "components.consul.kv.search-bar.kind.name"}} + + + + {{#let components.Optgroup components.Option as |Optgroup Option|}} + {{#each (array "folder" "key") as |item|}} + + {{/each}} + {{/let}} + + + + <:sort as |search|> + + + + {{#let (from-entries (array + (array "Key:asc" (t "common.sort.alpha.asc")) + (array "Key:desc" (t "common.sort.alpha.desc")) + (array "Kind:asc" (t "components.consul.kv.search-bar.sort.kind.asc")) + (array "Kind:desc" (t "components.consul.kv.search-bar.sort.kind.desc")) + )) + as |selectable| + }} + {{get selectable @sort.value}} + {{/let}} + + + + {{#let components.Optgroup components.Option as |Optgroup Option|}} + + + + + + + + + {{/let}} + + + + diff --git a/ui/packages/consul-ui/app/components/consul/node/search-bar/index.hbs b/ui/packages/consul-ui/app/components/consul/node/search-bar/index.hbs index c87fec9e4..703d1be05 100644 --- a/ui/packages/consul-ui/app/components/consul/node/search-bar/index.hbs +++ b/ui/packages/consul-ui/app/components/consul/node/search-bar/index.hbs @@ -1,90 +1,131 @@ - \ No newline at end of file + + + <:sort as |search|> + + + + {{#let (from-entries (array + (array "Node:asc" (t "common.sort.alpha.asc")) + (array "Node:desc" (t "common.sort.alpha.desc")) + (array "Status:asc" (t "common.sort.status.asc")) + (array "Status:desc" (t "common.sort.status.desc")) + )) + as |selectable| + }} + {{get selectable @sort.value}} + {{/let}} + + + + {{#let components.Optgroup components.Option as |Optgroup Option|}} + + + + + + + + + {{/let}} + + + + \ No newline at end of file diff --git a/ui/packages/consul-ui/app/components/consul/nspace/search-bar/index.hbs b/ui/packages/consul-ui/app/components/consul/nspace/search-bar/index.hbs index ab47be81b..1742d99f2 100644 --- a/ui/packages/consul-ui/app/components/consul/nspace/search-bar/index.hbs +++ b/ui/packages/consul-ui/app/components/consul/nspace/search-bar/index.hbs @@ -1,63 +1,98 @@ - \ No newline at end of file + + + \ No newline at end of file diff --git a/ui/packages/consul-ui/app/components/consul/policy/search-bar/index.hbs b/ui/packages/consul-ui/app/components/consul/policy/search-bar/index.hbs index 5572c00dc..538be653c 100644 --- a/ui/packages/consul-ui/app/components/consul/policy/search-bar/index.hbs +++ b/ui/packages/consul-ui/app/components/consul/policy/search-bar/index.hbs @@ -1,101 +1,145 @@ - + + + <:sort as |search|> + + + + {{#let (from-entries (array + (array "Name:asc" (t "common.sort.alpha.asc")) + (array "Name:desc" (t "common.sort.alpha.desc")) + )) + as |selectable| + }} + {{get selectable @sort.value}} + {{/let}} + + + + {{#let components.Optgroup components.Option as |Optgroup Option|}} + + + + + {{/let}} + + + + diff --git a/ui/packages/consul-ui/app/components/consul/role/search-bar/index.hbs b/ui/packages/consul-ui/app/components/consul/role/search-bar/index.hbs index 0aae4f197..d4b5dc237 100644 --- a/ui/packages/consul-ui/app/components/consul/role/search-bar/index.hbs +++ b/ui/packages/consul-ui/app/components/consul/role/search-bar/index.hbs @@ -1,68 +1,104 @@ - + + + diff --git a/ui/packages/consul-ui/app/components/consul/service-instance/search-bar/index.hbs b/ui/packages/consul-ui/app/components/consul/service-instance/search-bar/index.hbs index 71fb5c27e..aa83582da 100644 --- a/ui/packages/consul-ui/app/components/consul/service-instance/search-bar/index.hbs +++ b/ui/packages/consul-ui/app/components/consul/service-instance/search-bar/index.hbs @@ -1,111 +1,156 @@ - + + + + diff --git a/ui/packages/consul-ui/app/components/consul/service/search-bar/index.hbs b/ui/packages/consul-ui/app/components/consul/service/search-bar/index.hbs index 007bd3e9d..4c487e9f3 100644 --- a/ui/packages/consul-ui/app/components/consul/service/search-bar/index.hbs +++ b/ui/packages/consul-ui/app/components/consul/service/search-bar/index.hbs @@ -1,135 +1,190 @@ - + + + + + {{t "components.consul.service.search-bar.kind"}} + + + + {{#let components.Optgroup components.Option as |Optgroup Option|}} + + + {{#each (array "ingress-gateway" "terminating-gateway" "mesh-gateway") as |kind|}} + + {{/each}} + + + {{#each (array "in-mesh" "not-in-mesh") as |state|}} + + {{/each}} + + {{/let}} + + + {{#if (gt @sources.length 0)}} + + + + {{t "common.search.source"}} + + + + {{#let components.Optgroup components.Option as |Optgroup Option|}} + {{#each @sources as |source|}} + + {{/each}} + {{/let}} + + + {{/if}} + + <:sort as |search|> + + + + {{#let (from-entries (array + (array "Name:asc" (t "common.sort.alpha.asc")) + (array "Name:desc" (t "common.sort.alpha.desc")) + (array "Status:asc" (t "common.sort.status.asc")) + (array "Status:desc" (t "common.sort.status.desc")) + )) + as |selectable| + }} + {{get selectable @sort.value}} + {{/let}} + + + + {{#let components.Optgroup components.Option as |Optgroup Option|}} + + + + + + + + + {{/let}} + + + + diff --git a/ui/packages/consul-ui/app/components/consul/token/search-bar/index.hbs b/ui/packages/consul-ui/app/components/consul/token/search-bar/index.hbs index e5cdacd1c..f7d13be10 100644 --- a/ui/packages/consul-ui/app/components/consul/token/search-bar/index.hbs +++ b/ui/packages/consul-ui/app/components/consul/token/search-bar/index.hbs @@ -1,83 +1,125 @@ - + {{/let}} + + + + diff --git a/ui/packages/consul-ui/app/components/consul/upstream-instance/search-bar/index.hbs b/ui/packages/consul-ui/app/components/consul/upstream-instance/search-bar/index.hbs index 2111718bb..cc3fb877f 100644 --- a/ui/packages/consul-ui/app/components/consul/upstream-instance/search-bar/index.hbs +++ b/ui/packages/consul-ui/app/components/consul/upstream-instance/search-bar/index.hbs @@ -1,63 +1,96 @@ - + + + diff --git a/ui/packages/consul-ui/app/components/consul/upstream/search-bar/index.hbs b/ui/packages/consul-ui/app/components/consul/upstream/search-bar/index.hbs index 9cdc7242a..e8e00687a 100644 --- a/ui/packages/consul-ui/app/components/consul/upstream/search-bar/index.hbs +++ b/ui/packages/consul-ui/app/components/consul/upstream/search-bar/index.hbs @@ -1,86 +1,126 @@ - + + + <:sort as |search|> + + + + {{#let (from-entries (array + (array "Name:asc" (t "common.sort.alpha.asc")) + (array "Name:desc" (t "common.sort.alpha.desc")) + (array "Status:asc" (t "common.sort.status.asc")) + (array "Status:desc" (t "common.sort.status.desc")) + )) + as |selectable| + }} + {{get selectable @sort.value}} + {{/let}} + + + + {{#let components.Optgroup components.Option as |Optgroup Option|}} + + + + + + + + + {{/let}} + + + + diff --git a/ui/packages/consul-ui/app/components/data-collection/index.js b/ui/packages/consul-ui/app/components/data-collection/index.js index bf9e905af..49780a957 100644 --- a/ui/packages/consul-ui/app/components/data-collection/index.js +++ b/ui/packages/consul-ui/app/components/data-collection/index.js @@ -1,6 +1,6 @@ import Component from '@glimmer/component'; import { inject as service } from '@ember/service'; -import { computed, action } from '@ember/object'; +import { computed, get, action } from '@ember/object'; import { alias } from '@ember/object/computed'; import { tracked } from '@glimmer/tracking'; import { sort } from '@ember/object/computed'; @@ -32,18 +32,19 @@ export default class DataCollectionComponent extends Component { return this.term || this.args.search || ''; } - @computed('type', 'searchMethod', 'filtered', 'searchProperties') + @computed('type', 'searchMethod', 'filtered', 'args.filters') get searchable() { + const searchproperties = + get(this, 'args.filters.searchproperty.value') || get(this, 'args.filters.searchproperty'); const Searchable = typeof this.searchMethod === 'string' ? this.searchableMap[this.searchMethod] : this.args.searchable; + return new Searchable(this.filtered, { finders: Object.fromEntries( Object.entries(this.searchService.predicate(this.type)).filter(([key, value]) => { - return typeof this.searchProperties === 'undefined' - ? true - : this.searchProperties.includes(key); + return typeof searchproperties === 'undefined' ? true : searchproperties.includes(key); }) ), }); @@ -89,7 +90,13 @@ export default class DataCollectionComponent extends Component { if (typeof predicate === 'undefined') { return this.content.slice(); } - return this.content.filter(predicate(this.args.filters)); + const filters = Object.entries(this.args.filters) + .filter(([key, value]) => Boolean(value)) + .map(([key, value]) => { + const val = typeof value !== 'string' ? value.value : value; + return [key, val]; + }); + return this.content.filter(predicate(Object.fromEntries(filters))); } @computed('args.{items.[],items.content.[]}') diff --git a/ui/packages/consul-ui/app/components/popover-select/index.hbs b/ui/packages/consul-ui/app/components/popover-select/index.hbs index a3ceb2cde..527505654 100644 --- a/ui/packages/consul-ui/app/components/popover-select/index.hbs +++ b/ui/packages/consul-ui/app/components/popover-select/index.hbs @@ -9,7 +9,7 @@ (component 'popover-select/optgroup' components=components) (component 'popover-select/option' select=this components=components - onclick=(queue + onclick=(pipe (action "click") (if multiple (noop) menu.toggle) ) diff --git a/ui/packages/consul-ui/app/components/popover-select/index.js b/ui/packages/consul-ui/app/components/popover-select/index.js index 4062c054e..cd8bc330e 100644 --- a/ui/packages/consul-ui/app/components/popover-select/index.js +++ b/ui/packages/consul-ui/app/components/popover-select/index.js @@ -6,47 +6,50 @@ export default Component.extend(Slotted, { tagName: '', dom: service('dom'), multiple: false, - subtractive: false, + required: false, onchange: function() {}, addOption: function(option) { if (typeof this._options === 'undefined') { this._options = new Set(); } - if (this.subtractive) { - if (!option.selected) { - this._options.add(option.value); - } - } else { - if (option.selected) { - this._options.add(option.value); - } - } + this._options.add(option); }, removeOption: function(option) { - this._options.delete(option.value); + this._options.delete(option); }, actions: { - click: function(e, value) { - let options = [value]; - if (this.multiple) { - if (this._options.has(value)) { - this._options.delete(value); - } else { - this._options.add(value); + click: function(option, e) { + // required={{true}} ? + if (!this.multiple) { + if (option.selected && this.required) { + return e; + } + [...this._options] + .filter(item => item !== option) + .forEach(item => { + item.selected = false; + }); + } else { + if (option.selected && this.required) { + const other = [...this._options].find(item => item !== option && item.selected); + if (!other) { + return e; + } } - options = this._options; } + option.selected = !option.selected; this.onchange( this.dom.setEventTargetProperties(e, { - selected: target => value, + selected: target => option.args.value, selectedItems: target => { - return [...options].join(','); + return [...this._options] + .filter(item => item.selected) + .map(item => item.args.value) + .join(','); }, }) ); - }, - change: function(option, e) { - this.onchange(this.dom.setEventTargetProperty(e, 'selected', selected => option)); + return e; }, }, }); diff --git a/ui/packages/consul-ui/app/components/popover-select/optgroup/index.hbs b/ui/packages/consul-ui/app/components/popover-select/optgroup/index.hbs index 2847a4ce4..c26431e2c 100644 --- a/ui/packages/consul-ui/app/components/popover-select/optgroup/index.hbs +++ b/ui/packages/consul-ui/app/components/popover-select/optgroup/index.hbs @@ -1,7 +1,7 @@ -{{#let components.MenuSeparator as |MenuSeparator|}} +{{#let @components.MenuSeparator as |MenuSeparator|}} - {{label}} + {{@label}} {{yield}} diff --git a/ui/packages/consul-ui/app/components/popover-select/optgroup/index.js b/ui/packages/consul-ui/app/components/popover-select/optgroup/index.js deleted file mode 100644 index 479865264..000000000 --- a/ui/packages/consul-ui/app/components/popover-select/optgroup/index.js +++ /dev/null @@ -1,5 +0,0 @@ -import Component from '@ember/component'; - -export default Component.extend({ - tagName: '', -}); diff --git a/ui/packages/consul-ui/app/components/popover-select/option/index.hbs b/ui/packages/consul-ui/app/components/popover-select/option/index.hbs index 86119b1e9..8c7274494 100644 --- a/ui/packages/consul-ui/app/components/popover-select/option/index.hbs +++ b/ui/packages/consul-ui/app/components/popover-select/option/index.hbs @@ -1,9 +1,13 @@ -{{#let components.MenuItem as |MenuItem|}} +{{#let @components.MenuItem as |MenuItem|}} {{yield}} diff --git a/ui/packages/consul-ui/app/components/popover-select/option/index.js b/ui/packages/consul-ui/app/components/popover-select/option/index.js index 910dcd517..dea8a82c0 100644 --- a/ui/packages/consul-ui/app/components/popover-select/option/index.js +++ b/ui/packages/consul-ui/app/components/popover-select/option/index.js @@ -1,20 +1,16 @@ -import Component from '@ember/component'; -import { inject as service } from '@ember/service'; +import Component from '@glimmer/component'; +import { tracked } from '@glimmer/tracking'; +import { action } from '@ember/object'; -export default Component.extend({ - tagName: '', - dom: service('dom'), - didInsertElement: function() { - this._super(...arguments); - this.select.addOption(this); - }, - willDestroyElement: function() { - this._super(...arguments); - this.select.removeOption(this); - }, - actions: { - click: function(e) { - this.onclick(e, this.value); - }, - }, -}); +export default class Option extends Component { + @tracked selected; + + @action + connect() { + this.args.select.addOption(this); + } + @action + disconnect() { + this.args.select.removeOption(this); + } +} diff --git a/ui/packages/consul-ui/app/components/search-bar/README.mdx b/ui/packages/consul-ui/app/components/search-bar/README.mdx deleted file mode 100644 index 9abd12924..000000000 --- a/ui/packages/consul-ui/app/components/search-bar/README.mdx +++ /dev/null @@ -1,61 +0,0 @@ -## SearchBar - -```handlebars - -``` - -### Arguments - -| Argument | Type | Default | Description | -| --- | --- | --- | --- | -| `value` | `String` | | The string `value` of the freetext search bar | -| `onsearch` | `Function` | | The action to fire when the freetext search bar changes. Emits a native event with a `target.value` property containing the text typed into the search bar | -| `options` | `Array` | | An array of Key/Values pairs to use for options for either a filter interface or a sort interface | -| `selected` | `Object` | | An object containing a Key/Value pair of the currently selected option | -| `onchange` | `Function` | | The action to fire when the filter/sort changes. Emits an Event-like object, when filtering this has a `target.value` property containg the key of the selected filter, when sorting this has a `target.selected` property containing the selected Key/Value pair | -| `secondary` | `string` | | String identifier to signify what type of secondary filter to show. Currently only value here is 'sort' | - -`SearchBar` is used for a variety of searching behaviours, freetext searching, filtering and sorting. It is also slot based to enable you to completely overwrite the secondary search if need be. - -### Examples - -```handlebars -{{! Freetext only search bar}} - -``` - -```handlebars -{{! Freetext and filter search bar}} - -``` - -```handlebars -{{! Freetext and sort search bar}} - -``` - -### See - -- [Component Source Code](./index.js) -- [Template Source Code](./index.hbs) - ---- diff --git a/ui/packages/consul-ui/app/components/search-bar/index.hbs b/ui/packages/consul-ui/app/components/search-bar/index.hbs index b1f01a285..f42e9cca7 100644 --- a/ui/packages/consul-ui/app/components/search-bar/index.hbs +++ b/ui/packages/consul-ui/app/components/search-bar/index.hbs @@ -1,31 +1,68 @@ -{{yield}} -
- {{#yield-slot name="primary"}} -
- {{yield}} -
- {{else}} - - {{/yield-slot}} - {{#yield-slot name="secondary"}} -
- {{yield}} -
- {{else}} - {{#if options}} - {{#if (eq secondary 'sort')}} - {{else}} - - {{/if}} - {{/if}} - {{/yield-slot}} - + diff --git a/ui/packages/consul-ui/app/components/search-bar/index.js b/ui/packages/consul-ui/app/components/search-bar/index.js index a7be4db13..7fefbe8ef 100644 --- a/ui/packages/consul-ui/app/components/search-bar/index.js +++ b/ui/packages/consul-ui/app/components/search-bar/index.js @@ -1,6 +1,34 @@ -import Component from '@ember/component'; -import Slotted from 'block-slots'; +import Component from '@glimmer/component'; +import { action } from '@ember/object'; +import { diff, filters } from './utils'; -export default Component.extend(Slotted, { - tagName: '', -}); +export default class SearchBar extends Component { + // only show the filter status bar if we have searchproperty filters or + // normal types of filters, and we are currently filtering by either of those + get isFiltered() { + const searchproperty = this.args.filter.searchproperty || { default: [], value: [] }; + return ( + diff(searchproperty.default, searchproperty.value).length > 0 || + Object.entries(this.args.filter).some(([key, value]) => { + return key !== 'searchproperty' && typeof value.value !== 'undefined'; + }) + ); + } + + // convert the object based filters to an array of iterable filters ready for + // rendering + get filters() { + return filters(this.args.filter); + } + + @action + removeAllFilters() { + Object.values(this.args.filter).forEach((value, i) => { + // put in a little queue to ensure query params are unset properly + // ideally this would be done outside of the component + // TODO: Look to see if this can be moved to serializeQueryParam + // so we we aren't polluting components with queryParam related things + setTimeout(() => value.change(value.default || []), 1 * i); + }); + } +} diff --git a/ui/packages/consul-ui/app/components/search-bar/index.scss b/ui/packages/consul-ui/app/components/search-bar/index.scss new file mode 100644 index 000000000..d0b14a955 --- /dev/null +++ b/ui/packages/consul-ui/app/components/search-bar/index.scss @@ -0,0 +1,60 @@ +.search-bar { + &-status { + & { + border-bottom: $decor-border-100; + border-bottom-color: $gray-200; + } + .remove-all button { + @extend %anchor; + } + li:not(.remove-all) { + & { + @extend %pill-200; + border: $decor-border-100; + border-color: $gray-200; + color: $gray-600; + } + button { + cursor: pointer; + } + button::before { + @extend %with-cancel-plain-mask, %as-pseudo; + color: $gray-600; + margin-top: 1px; + margin-right: 0.2rem; + } + } + & { + padding: .5rem 0; + padding-left: .5rem; + } + dt::after { + content: ':'; + padding-right: 0.3rem; + } + & > dl > dt { + float: left; + } + dt { + white-space: nowrap; + } + li { + display: inline-flex; + } + li:not(:last-child) { + margin-right: 0.3rem; + margin-bottom: 0.3rem; + } + li:not(.remove-all) { + & { + padding: 0 0.2rem; + } + dl { + display: flex; + } + button { + padding: 0; + } + } + } +} diff --git a/ui/packages/consul-ui/app/components/search-bar/pageobject.js b/ui/packages/consul-ui/app/components/search-bar/pageobject.js deleted file mode 100644 index 363086463..000000000 --- a/ui/packages/consul-ui/app/components/search-bar/pageobject.js +++ /dev/null @@ -1,7 +0,0 @@ -export default (search, secondary = () => {}) => scope => { - return { - scope: scope, - ...search(), - ...secondary(), - }; -}; diff --git a/ui/packages/consul-ui/app/components/search-bar/remove-filter/index.hbs b/ui/packages/consul-ui/app/components/search-bar/remove-filter/index.hbs new file mode 100644 index 000000000..78e9975d5 --- /dev/null +++ b/ui/packages/consul-ui/app/components/search-bar/remove-filter/index.hbs @@ -0,0 +1,7 @@ +
  • + + {{yield}} +
  • diff --git a/ui/packages/consul-ui/app/components/search-bar/utils.js b/ui/packages/consul-ui/app/components/search-bar/utils.js new file mode 100644 index 000000000..d56a6580c --- /dev/null +++ b/ui/packages/consul-ui/app/components/search-bar/utils.js @@ -0,0 +1,38 @@ +export const diff = (a, b) => { + return a.filter(item => !b.includes(item)); +}; +/** + * filters accepts the args.filter @attribute which is shaped like + * {filterName: {default: ['Node', 'Address'], value: ['Address']}, ...} + * It will turn this into an array of 'filters' shaped like + * [{key: 'filterName', value: 'Address', selected: ["Node"]}] + * importantly 'selected' isn't what is currently 'selected' it is what selected + * will be once you remove this filter + * There is more explanation in the unit tests for this function so thats worthwhile + * checking if you are in amongst this + */ +export const filters = filters => { + return Object.entries(filters) + .filter(([key, value]) => { + if (key === 'searchproperty') { + return diff(value.default, value.value).length > 0; + } + return (value.value || []).length > 0; + }) + .reduce((prev, [key, value]) => { + return prev.concat( + value.value.map(item => { + const obj = { + key: key, + value: item, + }; + if (key !== 'searchproperty') { + obj.selected = diff(value.value, [item]); + } else { + obj.selected = value.value.length === 1 ? value.default : diff(value.value, [item]); + } + return obj; + }) + ); + }, []); +}; diff --git a/ui/packages/consul-ui/app/filter/predicates/acl.js b/ui/packages/consul-ui/app/filter/predicates/acl.js index 126d210e2..dfc15b58c 100644 --- a/ui/packages/consul-ui/app/filter/predicates/acl.js +++ b/ui/packages/consul-ui/app/filter/predicates/acl.js @@ -1,5 +1,5 @@ export default { - kinds: { + kind: { management: (item, value) => item.Type === value, client: (item, value) => item.Type === value, }, diff --git a/ui/packages/consul-ui/app/filter/predicates/health-check.js b/ui/packages/consul-ui/app/filter/predicates/health-check.js index ae7b32949..49d60f459 100644 --- a/ui/packages/consul-ui/app/filter/predicates/health-check.js +++ b/ui/packages/consul-ui/app/filter/predicates/health-check.js @@ -1,14 +1,14 @@ export default { - statuses: { + status: { passing: (item, value) => item.Status === value, warning: (item, value) => item.Status === value, critical: (item, value) => item.Status === value, }, - kinds: { + kind: { service: (item, value) => item.Kind === value, node: (item, value) => item.Kind === value, }, - checks: { + check: { serf: (item, value) => item.Type === '', script: (item, value) => item.Type === value, http: (item, value) => item.Type === value, diff --git a/ui/packages/consul-ui/app/filter/predicates/intention.js b/ui/packages/consul-ui/app/filter/predicates/intention.js index 3f884de0f..30646b8dd 100644 --- a/ui/packages/consul-ui/app/filter/predicates/intention.js +++ b/ui/packages/consul-ui/app/filter/predicates/intention.js @@ -1,5 +1,5 @@ export default { - accesses: { + access: { allow: (item, value) => item.Action === value, deny: (item, value) => item.Action === value, 'app-aware': (item, value) => typeof item.Action === 'undefined', diff --git a/ui/packages/consul-ui/app/filter/predicates/kv.js b/ui/packages/consul-ui/app/filter/predicates/kv.js index 19cf277f1..8df7da9f7 100644 --- a/ui/packages/consul-ui/app/filter/predicates/kv.js +++ b/ui/packages/consul-ui/app/filter/predicates/kv.js @@ -1,5 +1,5 @@ export default { - kinds: { + kind: { folder: (item, value) => item.isFolder, key: (item, value) => !item.isFolder, }, diff --git a/ui/packages/consul-ui/app/filter/predicates/node.js b/ui/packages/consul-ui/app/filter/predicates/node.js index 14de99255..dc8e641c0 100644 --- a/ui/packages/consul-ui/app/filter/predicates/node.js +++ b/ui/packages/consul-ui/app/filter/predicates/node.js @@ -1,5 +1,5 @@ export default { - statuses: { + status: { passing: (item, value) => item.Status === value, warning: (item, value) => item.Status === value, critical: (item, value) => item.Status === value, diff --git a/ui/packages/consul-ui/app/filter/predicates/policy.js b/ui/packages/consul-ui/app/filter/predicates/policy.js index d3a6ca4ee..c5308357a 100644 --- a/ui/packages/consul-ui/app/filter/predicates/policy.js +++ b/ui/packages/consul-ui/app/filter/predicates/policy.js @@ -1,11 +1,11 @@ import setHelpers from 'mnemonist/set'; export default { - kinds: { + kind: { 'global-management': (item, value) => item.isGlobalManagement, standard: (item, value) => !item.isGlobalManagement, }, - dcs: (item, values) => { + datacenter: (item, values) => { return ( typeof item.Datacenters === 'undefined' || setHelpers.intersectionSize(values, new Set(item.Datacenters)) > 0 diff --git a/ui/packages/consul-ui/app/filter/predicates/service-instance.js b/ui/packages/consul-ui/app/filter/predicates/service-instance.js index ee0b46498..76111c576 100644 --- a/ui/packages/consul-ui/app/filter/predicates/service-instance.js +++ b/ui/packages/consul-ui/app/filter/predicates/service-instance.js @@ -1,12 +1,13 @@ import setHelpers from 'mnemonist/set'; export default { - statuses: { + status: { passing: (item, value) => item.Status === value, warning: (item, value) => item.Status === value, critical: (item, value) => item.Status === value, + empty: (item, value) => item.MeshChecks.length === 0, }, - sources: (item, values) => { + source: (item, values) => { return setHelpers.intersectionSize(values, new Set(item.ExternalSources || [])) !== 0; }, }; diff --git a/ui/packages/consul-ui/app/filter/predicates/service.js b/ui/packages/consul-ui/app/filter/predicates/service.js index d90ea2846..f9a7d4a1f 100644 --- a/ui/packages/consul-ui/app/filter/predicates/service.js +++ b/ui/packages/consul-ui/app/filter/predicates/service.js @@ -1,7 +1,7 @@ import setHelpers from 'mnemonist/set'; export default { - kinds: { + kind: { 'ingress-gateway': (item, value) => item.Kind === value, 'terminating-gateway': (item, value) => item.Kind === value, 'mesh-gateway': (item, value) => item.Kind === value, @@ -9,16 +9,17 @@ export default { 'in-mesh': (item, value) => item.InMesh, 'not-in-mesh': (item, value) => !item.InMesh, }, - statuses: { + status: { passing: (item, value) => item.MeshStatus === value, warning: (item, value) => item.MeshStatus === value, critical: (item, value) => item.MeshStatus === value, + empty: (item, value) => item.MeshChecksTotal === 0, }, - instances: { + instance: { registered: (item, value) => item.InstanceCount > 0, 'not-registered': (item, value) => item.InstanceCount === 0, }, - sources: (item, values) => { + source: (item, values) => { return setHelpers.intersectionSize(values, new Set(item.ExternalSources || [])) !== 0; }, }; diff --git a/ui/packages/consul-ui/app/filter/predicates/token.js b/ui/packages/consul-ui/app/filter/predicates/token.js index 3efcea84a..31dd06ea5 100644 --- a/ui/packages/consul-ui/app/filter/predicates/token.js +++ b/ui/packages/consul-ui/app/filter/predicates/token.js @@ -1,5 +1,5 @@ export default { - kinds: { + kind: { 'global-management': (item, value) => item.isGlobalManagement, global: (item, value) => !item.Local, local: (item, value) => item.Local, diff --git a/ui/packages/consul-ui/app/models/role.js b/ui/packages/consul-ui/app/models/role.js index 18bcc2841..1a58194d2 100644 --- a/ui/packages/consul-ui/app/models/role.js +++ b/ui/packages/consul-ui/app/models/role.js @@ -17,7 +17,9 @@ export default class Role extends Model { @attr('number') SyncTime; @attr('number') CreateIndex; @attr('number') ModifyIndex; - // frontend only for ordering where CreateIndex can't be used + // frontend only for ordering where CreateIndex can't be used i.e. for when + // we need to order items that aren't yet saved to the backend, for example + // in the role-selector @attr('number') CreateTime; // TODO: Figure out whether we need this or not @attr() Datacenters; // string[] diff --git a/ui/packages/consul-ui/app/models/service.js b/ui/packages/consul-ui/app/models/service.js index dc1f3a8d0..ddebe4f58 100644 --- a/ui/packages/consul-ui/app/models/service.js +++ b/ui/packages/consul-ui/app/models/service.js @@ -48,6 +48,16 @@ export default class Service extends Model { @attr() meta; // {} + @computed('ChecksPassing', 'ChecksWarning', 'ChecksCritical') + get ChecksTotal() { + return this.ChecksPassing + this.ChecksWarning + this.ChecksCritical; + } + + @computed('MeshChecksPassing', 'MeshChecksWarning', 'MeshChecksCritical') + get MeshChecksTotal() { + return this.MeshChecksPassing + this.MeshChecksWarning + this.MeshChecksCritical; + } + /* Mesh properties involve both the service and the associated proxy */ @computed('ConnectedWithProxy', 'ConnectedWithGateway') get MeshEnabled() { diff --git a/ui/packages/consul-ui/app/routes/dc/acls/index.js b/ui/packages/consul-ui/app/routes/dc/acls/index.js index 6c621b127..c5761cc43 100644 --- a/ui/packages/consul-ui/app/routes/dc/acls/index.js +++ b/ui/packages/consul-ui/app/routes/dc/acls/index.js @@ -1,13 +1,11 @@ import { inject as service } from '@ember/service'; import Route from 'consul-ui/routing/route'; -import { hash } from 'rsvp'; import { get } from '@ember/object'; import WithAclActions from 'consul-ui/mixins/acl/with-actions'; export default class IndexRoute extends Route.extend(WithAclActions) { @service('repository/acl') repo; - @service('settings') settings; queryParams = { @@ -19,24 +17,25 @@ export default class IndexRoute extends Route.extend(WithAclActions) { }, }; - beforeModel(transition) { - return this.settings.findBySlug('token').then(token => { - // If you don't have a token set or you have a - // token set with AccessorID set to not null (new ACL mode) - // then rewrite to the new acls - if (!token || get(token, 'AccessorID') !== null) { - // If you return here, you get a TransitionAborted error in the tests only - // everything works fine either way checking things manually - this.replaceWith('dc.acls.tokens'); - } - }); + async beforeModel(transition) { + const token = await this.settings.findBySlug('token'); + // If you don't have a token set or you have a + // token set with AccessorID set to not null (new ACL mode) + // then rewrite to the new acls + if (!token || get(token, 'AccessorID') !== null) { + // If you return here, you get a TransitionAborted error in the tests only + // everything works fine either way checking things manually + this.replaceWith('dc.acls.tokens'); + } } - model(params) { - return hash({ - items: this.repo.findAllByDatacenter(this.modelFor('dc').dc.Name), - token: this.settings.findBySlug('token'), - }); + async model(params) { + const _items = this.repo.findAllByDatacenter(this.modelFor('dc').dc.Name); + const _token = this.settings.findBySlug('token'); + return { + items: await _items, + token: await _token, + }; } setupController(controller, model) { diff --git a/ui/packages/consul-ui/app/routes/dc/acls/policies/index.js b/ui/packages/consul-ui/app/routes/dc/acls/policies/index.js index b24ac000b..394f4c6f2 100644 --- a/ui/packages/consul-ui/app/routes/dc/acls/policies/index.js +++ b/ui/packages/consul-ui/app/routes/dc/acls/policies/index.js @@ -9,7 +9,9 @@ export default class IndexRoute extends Route.extend(WithPolicyActions) { queryParams = { sortBy: 'sort', - dc: 'dc', + datacenter: { + as: 'dc', + }, kind: 'kind', searchproperty: { as: 'searchproperty', @@ -29,6 +31,7 @@ export default class IndexRoute extends Route.extend(WithPolicyActions) { this.modelFor('nspace').nspace.substr(1) ), }), + searchProperties: this.queryParams.searchproperty.empty[0], }); } diff --git a/ui/packages/consul-ui/app/routes/dc/acls/roles/index.js b/ui/packages/consul-ui/app/routes/dc/acls/roles/index.js index f2f594461..46c14f493 100644 --- a/ui/packages/consul-ui/app/routes/dc/acls/roles/index.js +++ b/ui/packages/consul-ui/app/routes/dc/acls/roles/index.js @@ -27,6 +27,7 @@ export default class IndexRoute extends Route.extend(WithRoleActions) { this.modelFor('nspace').nspace.substr(1) ), }), + searchProperties: this.queryParams.searchproperty.empty[0], }); } diff --git a/ui/packages/consul-ui/app/routes/dc/acls/tokens/index.js b/ui/packages/consul-ui/app/routes/dc/acls/tokens/index.js index 06deafc92..bfc26b5f9 100644 --- a/ui/packages/consul-ui/app/routes/dc/acls/tokens/index.js +++ b/ui/packages/consul-ui/app/routes/dc/acls/tokens/index.js @@ -21,16 +21,15 @@ export default class IndexRoute extends Route.extend(WithTokenActions) { }, }; - beforeModel(transition) { - return this.settings.findBySlug('token').then(token => { - // If you have a token set with AccessorID set to null (legacy mode) - // then rewrite to the old acls - if (token && get(token, 'AccessorID') === null) { - // If you return here, you get a TransitionAborted error in the tests only - // everything works fine either way checking things manually - this.replaceWith('dc.acls'); - } - }); + async beforeModel(transition) { + const token = await this.settings.findBySlug('token'); + // If you have a token set with AccessorID set to null (legacy mode) + // then rewrite to the old acls + if (token && get(token, 'AccessorID') === null) { + // If you return here, you get a TransitionAborted error in the tests only + // everything works fine either way checking things manually + this.replaceWith('dc.acls'); + } } model(params) { @@ -43,6 +42,7 @@ export default class IndexRoute extends Route.extend(WithTokenActions) { }), nspace: this.modelFor('nspace').nspace.substr(1), token: this.settings.findBySlug('token'), + searchProperties: this.queryParams.searchproperty.empty[0], }); } diff --git a/ui/packages/consul-ui/app/routes/dc/intentions/index.js b/ui/packages/consul-ui/app/routes/dc/intentions/index.js index 65479ab4b..4195ad9fb 100644 --- a/ui/packages/consul-ui/app/routes/dc/intentions/index.js +++ b/ui/packages/consul-ui/app/routes/dc/intentions/index.js @@ -14,10 +14,11 @@ export default class IndexRoute extends Route { }, }; - model(params) { + async model(params) { return { dc: this.modelFor('dc').dc.Name, nspace: this.modelFor('nspace').nspace.substr(1), + searchProperties: this.queryParams.searchproperty.empty[0], }; } diff --git a/ui/packages/consul-ui/app/routes/dc/nodes/index.js b/ui/packages/consul-ui/app/routes/dc/nodes/index.js index fea305f73..aa0b1d764 100644 --- a/ui/packages/consul-ui/app/routes/dc/nodes/index.js +++ b/ui/packages/consul-ui/app/routes/dc/nodes/index.js @@ -1,6 +1,5 @@ import { inject as service } from '@ember/service'; import Route from 'consul-ui/routing/route'; -import { hash } from 'rsvp'; export default class IndexRoute extends Route { @service('data-source/service') data; @@ -18,13 +17,16 @@ export default class IndexRoute extends Route { }, }; - model(params) { + async model(params) { const dc = this.modelFor('dc').dc.Name; const nspace = this.modelFor('nspace').nspace.substr(1); - return hash({ - items: this.data.source(uri => uri`/${nspace}/${dc}/nodes`), - leader: this.data.source(uri => uri`/${nspace}/${dc}/leader`), - }); + const items = this.data.source(uri => uri`/${nspace}/${dc}/nodes`); + const leader = this.data.source(uri => uri`/${nspace}/${dc}/leader`); + return { + items: await items, + leader: await leader, + searchProperties: this.queryParams.searchproperty.empty[0], + }; } setupController(controller, model) { diff --git a/ui/packages/consul-ui/app/routes/dc/nspaces/index.js b/ui/packages/consul-ui/app/routes/dc/nspaces/index.js index d1e339a96..811616cf2 100644 --- a/ui/packages/consul-ui/app/routes/dc/nspaces/index.js +++ b/ui/packages/consul-ui/app/routes/dc/nspaces/index.js @@ -1,6 +1,5 @@ import { inject as service } from '@ember/service'; import Route from 'consul-ui/routing/route'; -import { hash } from 'rsvp'; import WithNspaceActions from 'consul-ui/mixins/nspace/with-actions'; export default class IndexRoute extends Route.extend(WithNspaceActions) { @@ -19,10 +18,11 @@ export default class IndexRoute extends Route.extend(WithNspaceActions) { }, }; - model(params) { - return hash({ - items: this.data.source(uri => uri`/*/*/namespaces`), - }); + async model(params) { + return { + items: await this.data.source(uri => uri`/*/*/namespaces`), + searchProperties: this.queryParams.searchproperty.empty[0], + }; } setupController(controller, model) { diff --git a/ui/packages/consul-ui/app/routes/dc/services/index.js b/ui/packages/consul-ui/app/routes/dc/services/index.js index 3cbb1cce3..879621028 100644 --- a/ui/packages/consul-ui/app/routes/dc/services/index.js +++ b/ui/packages/consul-ui/app/routes/dc/services/index.js @@ -27,6 +27,7 @@ export default class IndexRoute extends Route { dc, nspace, items, + searchProperties: this.queryParams.searchproperty.empty[0], }; } diff --git a/ui/packages/consul-ui/app/routes/dc/services/instance/healthchecks.js b/ui/packages/consul-ui/app/routes/dc/services/instance/healthchecks.js index cf650e9b1..8fcf2a7a0 100644 --- a/ui/packages/consul-ui/app/routes/dc/services/instance/healthchecks.js +++ b/ui/packages/consul-ui/app/routes/dc/services/instance/healthchecks.js @@ -4,7 +4,6 @@ export default class HealthchecksRoute extends Route { queryParams = { sortBy: 'sort', status: 'status', - kind: 'kind', check: 'check', searchproperty: { as: 'searchproperty', diff --git a/ui/packages/consul-ui/app/routes/dc/services/show/intentions/index.js b/ui/packages/consul-ui/app/routes/dc/services/show/intentions/index.js index 5184a777c..0468f0295 100644 --- a/ui/packages/consul-ui/app/routes/dc/services/show/intentions/index.js +++ b/ui/packages/consul-ui/app/routes/dc/services/show/intentions/index.js @@ -14,11 +14,12 @@ export default class IndexRoute extends Route { }, }; - model(params) { + async model(params) { return { dc: this.modelFor('dc').dc.Name, nspace: this.modelFor('nspace').nspace.substr(1) || 'default', slug: this.paramsFor('dc.services.show').name, + searchProperties: this.queryParams.searchproperty.empty[0], }; } diff --git a/ui/packages/consul-ui/app/routes/dc/services/show/services.js b/ui/packages/consul-ui/app/routes/dc/services/show/services.js index 22f1ecf9e..dd2abff12 100644 --- a/ui/packages/consul-ui/app/routes/dc/services/show/services.js +++ b/ui/packages/consul-ui/app/routes/dc/services/show/services.js @@ -25,13 +25,12 @@ export default class ServicesRoute extends Route { .slice(0, -1) .join('.'); const name = this.modelFor(parent).slug; - const gatewayServices = await this.data.source( - uri => uri`/${nspace}/${dc}/gateways/for-service/${name}` - ); + const items = await this.data.source(uri => uri`/${nspace}/${dc}/gateways/for-service/${name}`); return { dc, nspace, - gatewayServices, + items, + searchProperties: this.queryParams.searchproperty.empty[0], }; } diff --git a/ui/packages/consul-ui/app/styles/components.scss b/ui/packages/consul-ui/app/styles/components.scss index b1bafe475..6e7983ece 100644 --- a/ui/packages/consul-ui/app/styles/components.scss +++ b/ui/packages/consul-ui/app/styles/components.scss @@ -53,6 +53,7 @@ @import 'consul-ui/components/freetext-filter'; @import 'consul-ui/components/informed-action'; @import 'consul-ui/components/tab-nav'; +@import 'consul-ui/components/search-bar'; @import 'consul-ui/components/consul/tomography/graph'; @import 'consul-ui/components/consul/discovery-chain'; diff --git a/ui/packages/consul-ui/app/styles/layout.scss b/ui/packages/consul-ui/app/styles/layout.scss index 786e100f8..b8963f085 100644 --- a/ui/packages/consul-ui/app/styles/layout.scss +++ b/ui/packages/consul-ui/app/styles/layout.scss @@ -18,7 +18,7 @@ html[data-route$='edit'] .app-view > header + div > *:first-child { /* if it is a filter bar and the thing after the filter bar is a p then it also */ /* needs a top margun :S */ %app-view-content .tab-section > *:first-child:not(.filter-bar):not(table), -%app-view-content .tab-section > .filter-bar + p, +%app-view-content .tab-section > .search-bar + p, %app-view-content .tab-section .consul-health-check-list { margin-top: 1.25em; } diff --git a/ui/packages/consul-ui/app/styles/typography.scss b/ui/packages/consul-ui/app/styles/typography.scss index a4196e48a..8948d39fe 100644 --- a/ui/packages/consul-ui/app/styles/typography.scss +++ b/ui/packages/consul-ui/app/styles/typography.scss @@ -17,7 +17,7 @@ h3 { %radio-card header, fieldset > header, %main-nav-horizontal-action, -%app-view-content div > dl > dt, +%definition-table dt, %table caption, %tbody-th, %form-element > span { diff --git a/ui/packages/consul-ui/app/templates/dc/acls/index.hbs b/ui/packages/consul-ui/app/templates/dc/acls/index.hbs index 71051c7fe..7bf7b3da5 100644 --- a/ui/packages/consul-ui/app/templates/dc/acls/index.hbs +++ b/ui/packages/consul-ui/app/templates/dc/acls/index.hbs @@ -1,83 +1,93 @@ {{page-title 'ACLs'}} -{{#let (hash - kinds=(if kind (split kind ',') undefined) -) as |filters|}} - {{#let (or sortBy "Name:asc") as |sort|}} - - - - - -

    - ACL Tokens {{format-number items.length}} total -

    - -
    - - Create - - - {{#if (gt items.length 0) }} - + + - {{/if}} - - - - - + +

    + ACL Tokens {{format-number items.length}} total +

    + +
    + + Create + + + {{#if (gt items.length 0) }} + + {{/if}} + + + + + + + + + + +

    + {{#if (gt items.length 0)}} + No ACLs found + {{else}} + Welcome to ACLs + {{/if}} +

    +
    + +

    + {{#if (gt items.length 0)}} + No ACLs where found matching that search, or you may not have access to view the ACLs you are searching for. + {{else}} + There don't seem to be any ACLs yet, or you may not have access to view ACLs yet. + {{/if}} +

    +
    +
    +
    +
    +
    +
    - @ondelete={{route-action 'delete'}} - @onuse={{route-action 'use'}} - @onclone={{route-action 'clone'}} - > - - - - - -

    - {{#if (gt items.length 0)}} - No ACLs found - {{else}} - Welcome to ACLs - {{/if}} -

    -
    - -

    - {{#if (gt items.length 0)}} - No ACLs where found matching that search, or you may not have access to view the ACLs you are searching for. - {{else}} - There don't seem to be any ACLs yet, or you may not have access to view ACLs yet. - {{/if}} -

    -
    -
    -
    - -
    - - {{/let}} {{/let}} diff --git a/ui/packages/consul-ui/app/templates/dc/acls/policies/index.hbs b/ui/packages/consul-ui/app/templates/dc/acls/policies/index.hbs index 63a8dc213..afbad1918 100644 --- a/ui/packages/consul-ui/app/templates/dc/acls/policies/index.hbs +++ b/ui/packages/consul-ui/app/templates/dc/acls/policies/index.hbs @@ -3,104 +3,118 @@ {{else}} {{page-title 'Access Controls'}} {{/if}} -{{#let (hash - kinds=(if kind (split kind ',') undefined) - dcs=(if dc (split dc ',') undefined) - searchproperties=(if (not-eq searchproperty undefined) - (split searchproperty ',') - (array 'Name' 'Description') +{{#let + + (hash + value=(or sortBy "Name:asc") + change=(action (mut sortBy) value="target.selected") ) -) as |filters|}} - {{#let (or sortBy "Name:asc") as |sort|}} - - - - - -

    - Access Controls -

    -
    - - {{#if isAuthorized }} - {{partial 'dc/acls/nav'}} + + (hash + kind=(hash + value=(if kind (split kind ',') undefined) + change=(action (mut kind) value="target.selectedItems") + ) + datacenter=(hash + value=(if datacenter (split datacenter ',') undefined) + change=(action (mut datacenter) value="target.selectedItems") + ) + searchproperty=(hash + value=(if (not-eq searchproperty undefined) + (split searchproperty ',') + searchProperties + ) + change=(action (mut searchproperty) value="target.selectedItems") + default=searchProperties + ) + ) + + items + +as |sort filters items|}} + + + + + +

    + Access Controls +

    +
    + + {{#if isAuthorized }} + {{partial 'dc/acls/nav'}} + {{/if}} + + + Create + + + {{#if (gt items.length 0) }} + {{/if}} - - - Create - - - {{#if (gt items.length 0) }} - + + + + + + + + +

    + {{#if (gt items.length 0)}} + No policies found + {{else}} + Welcome to Policies + {{/if}} +

    +
    + +

    + {{#if (gt items.length 0)}} + No policies where found matching that search, or you may not have access to view the policies you are searching for. + {{else}} + There don't seem to be any policies, or you may not have access to view policies yet. + {{/if}} +

    +
    + + + + +
    +
    +
    +
    +
    - @sort={{sort}} - @onsort={{action (mut sortBy) value="target.selected"}} - - @filter={{filters}} - @onfilter={{hash - searchproperty=(action (mut searchproperty) value="target.selectedItems") - dc=(action (mut dc) value="target.selectedItems") - kind=(action (mut kind) value="target.selectedItems") - }} - /> - {{/if}} -
    - - - - - - - - -

    - {{#if (gt items.length 0)}} - No policies found - {{else}} - Welcome to Policies - {{/if}} -

    -
    - -

    - {{#if (gt items.length 0)}} - No policies where found matching that search, or you may not have access to view the policies you are searching for. - {{else}} - There don't seem to be any policies, or you may not have access to view policies yet. - {{/if}} -

    -
    - - - - -
    -
    -
    -
    -
    - {{/let}} {{/let}} \ No newline at end of file diff --git a/ui/packages/consul-ui/app/templates/dc/acls/roles/index.hbs b/ui/packages/consul-ui/app/templates/dc/acls/roles/index.hbs index 265755ea5..5cc11ccb5 100644 --- a/ui/packages/consul-ui/app/templates/dc/acls/roles/index.hbs +++ b/ui/packages/consul-ui/app/templates/dc/acls/roles/index.hbs @@ -4,13 +4,28 @@ {{page-title 'Access Controls'}} {{/if}} -{{#let (hash - searchproperties=(if (not-eq searchproperty undefined) - (split searchproperty ',') - (array 'Name' 'Description' 'Policy') +{{#let + + (hash + value=(or sortBy "Name:asc") + change=(action (mut sortBy) value="target.selected") ) -) as |filters|}} - {{#let (or sortBy "Name:asc") as |sort|}} + + (hash + searchproperty=(hash + value=(if (not-eq searchproperty undefined) + (split searchproperty ',') + searchProperties + ) + change=(action (mut searchproperty) value="target.selectedItems") + default=searchProperties + ) + ) + + items + +as |sort filters items|}} + {{/if}} - {{/let}} {{/let}} \ No newline at end of file diff --git a/ui/packages/consul-ui/app/templates/dc/acls/tokens/index.hbs b/ui/packages/consul-ui/app/templates/dc/acls/tokens/index.hbs index 19582e631..849ba3cc1 100644 --- a/ui/packages/consul-ui/app/templates/dc/acls/tokens/index.hbs +++ b/ui/packages/consul-ui/app/templates/dc/acls/tokens/index.hbs @@ -4,110 +4,122 @@ {{page-title 'Access Controls'}} {{/if}} -{{#let (hash - kinds=(if kind (split kind ',') undefined) - searchproperties=(if (not-eq searchproperty undefined) - (split searchproperty ',') - (array 'Description' 'Policy' 'Role') +{{#let + + (hash + value=(or sortBy "CreateTime:desc") + change=(action (mut sortBy) value="target.selected") ) -) as |filters|}} - {{#let (or sortBy "CreateTime:desc") as |sort|}} - - - - - -

    - Access Controls -

    -
    - - {{#if isAuthorized }} - {{partial 'dc/acls/nav'}} - {{/if}} - - - Create - - - {{#if (gt items.length 0)}} - - {{/if}} - - - {{#if (token/is-legacy items)}} - - -

    Update

    -
    - -

    We have upgraded our ACL System to allow the creation of reusable policies that can be applied to tokens. Read more about the changes and how to upgrade legacy tokens in our documentation.

    -
    -
    - {{/if}} - - - - - - - -

    - {{#if (gt items.length 0)}} - No tokens found - {{else}} - Welcome to ACL Tokens - {{/if}} -

    -
    - -

    - {{#if (gt items.length 0)}} - No tokens where found matching that search, or you may not have access to view the tokens you are searching for. - {{else}} - There don't seem to be any tokens, or you may not have access to view tokens yet. - {{/if}} -

    -
    -
    -
    -
    -
    -
    - {{/let}} + items + +as |sort filters items|}} + + + + + + +

    + Access Controls +

    +
    + + {{#if isAuthorized }} + {{partial 'dc/acls/nav'}} + {{/if}} + + + Create + + + {{#if (gt items.length 0)}} + + {{/if}} + + + {{#if (token/is-legacy items)}} + + +

    Update

    +
    + +

    We have upgraded our ACL System to allow the creation of reusable policies that can be applied to tokens. Read more about the changes and how to upgrade legacy tokens in our documentation.

    +
    +
    + {{/if}} + + + + + + + +

    + {{#if (gt items.length 0)}} + No tokens found + {{else}} + Welcome to ACL Tokens + {{/if}} +

    +
    + +

    + {{#if (gt items.length 0)}} + No tokens where found matching that search, or you may not have access to view the tokens you are searching for. + {{else}} + There don't seem to be any tokens, or you may not have access to view tokens yet. + {{/if}} +

    +
    +
    +
    +
    +
    +
    {{/let}} diff --git a/ui/packages/consul-ui/app/templates/dc/intentions/index.hbs b/ui/packages/consul-ui/app/templates/dc/intentions/index.hbs index 429ca59b0..5341b3c64 100644 --- a/ui/packages/consul-ui/app/templates/dc/intentions/index.hbs +++ b/ui/packages/consul-ui/app/templates/dc/intentions/index.hbs @@ -6,104 +6,115 @@ -{{#let api.data as |items|}} - {{#let (hash - accesses=(if access (split access ',') undefined) - searchproperties=(if (not-eq searchproperty undefined) - (split searchproperty ',') - (array 'SourceName' 'DestinationName') +{{#let + + (hash + value=(or sortBy "Action:asc") + change=(action (mut sortBy) value="target.selected") + ) + + (hash + access=(hash + value=(if access (split access ',') undefined) + change=(action (mut access) value="target.selectedItems") ) - ) as |filters|}} - {{#let (or sortBy "Action:asc") as |sort|}} - - -

    - Intentions {{format-number items.length}} total -

    - -
    - - Create - - + searchproperty=(hash + value=(if (not-eq searchproperty undefined) + (split searchproperty ',') + searchProperties + ) + change=(action (mut searchproperty) value="target.selectedItems") + default=searchProperties + ) + ) - {{#if (gt items.length 0) }} - - {{/if}} + + +

    + Intentions {{format-number items.length}} total +

    + +
    + + Create + + - +{{#if (gt items.length 0) }} + +{{/if}} + +
    + + - - - - - - - - - - - - -

    - {{#if (gt items.length 0)}} - No intentions found - {{else}} - Welcome to Intentions - {{/if}} -

    -
    - -

    - {{#if (gt items.length 0)}} - No intentions where found matching that search, or you may not have access to view the intentions you are searching for. - {{else}} - There don't seem to be any intentions, or you may not have access to view intentions yet. - {{/if}} -

    -
    - - - - -
    -
    -
    -
    -
    + @sort={{sort.value}} + @filters={{filters}} + @search={{search}} + @items={{items}} + as |collection|> + + + + + + + + + +

    + {{#if (gt items.length 0)}} + No intentions found + {{else}} + Welcome to Intentions + {{/if}} +

    +
    + +

    + {{#if (gt items.length 0)}} + No intentions where found matching that search, or you may not have access to view the intentions you are searching for. + {{else}} + There don't seem to be any intentions, or you may not have access to view intentions yet. + {{/if}} +

    +
    + + + + +
    +
    +
    -
    - {{/let}} - {{/let}} + +
    + + {{/let}} \ No newline at end of file diff --git a/ui/packages/consul-ui/app/templates/dc/kv/index.hbs b/ui/packages/consul-ui/app/templates/dc/kv/index.hbs index 970361cd6..667137cfa 100644 --- a/ui/packages/consul-ui/app/templates/dc/kv/index.hbs +++ b/ui/packages/consul-ui/app/templates/dc/kv/index.hbs @@ -1,8 +1,21 @@ {{page-title 'Key/Value'}} -{{#let (hash - kinds=(if kind (split kind ',') undefined) -) as |filters|}} - {{#let (or sortBy "Kind:asc") as |sort|}} +{{#let + + (hash + value=(or sortBy "Kind:asc") + change=(action (mut sortBy) value="target.selected") + ) + + (hash + kind=(hash + value=(if kind (split kind ',') undefined) + change=(action (mut kind) value="target.selectedItems") + ) + ) + + items + +as |sort filters items|}} {{#if (not-eq parent.Key '/') }} @@ -31,12 +44,8 @@ @onsearch={{action (mut search) value="target.value"}} @sort={{sort}} - @onsort={{action (mut sortBy) value="target.selected"}} @filter={{filters}} - @onfilter={{hash - kind=(action (mut kind) value="target.selectedItems") - }} /> {{/if}} @@ -57,7 +66,7 @@ - {{/let}} {{/let}} \ No newline at end of file diff --git a/ui/packages/consul-ui/app/templates/dc/nodes/index.hbs b/ui/packages/consul-ui/app/templates/dc/nodes/index.hbs index a57a4435f..172d1965f 100644 --- a/ui/packages/consul-ui/app/templates/dc/nodes/index.hbs +++ b/ui/packages/consul-ui/app/templates/dc/nodes/index.hbs @@ -1,14 +1,31 @@ {{page-title 'Nodes'}} -{{#let (hash - statuses=(if status (split status ',') undefined) - searchproperties=(if (not-eq searchproperty undefined) - (split searchproperty ',') - (array 'Node' 'Address' 'Meta') +{{#let + + (hash + value=(or sortBy "Status:asc") + change=(action (mut sortBy) value="target.selected") ) -) as |filters|}} -{{#let (or sortBy "Status:asc") as |sort|}} + + (hash + status=(hash + value=(if status (split status ',') undefined) + change=(action (mut status) value="target.selectedItems") + ) + searchproperty=(hash + value=(if (not-eq searchproperty undefined) + (split searchproperty ',') + searchProperties + ) + change=(action (mut searchproperty) value="target.selectedItems") + default=searchProperties + ) + ) + + items + +as |sort filters items|}}

    @@ -23,20 +40,15 @@ @onsearch={{action (mut search) value="target.value"}} @sort={{sort}} - @onsort={{action (mut sortBy) value="target.selected"}} @filter={{filters}} - @onfilter={{hash - searchproperty=(action (mut searchproperty) value="target.selectedItems") - status=(action (mut status) value="target.selectedItems") - }} /> {{/if}} - {{/let}} {{/let}} \ No newline at end of file diff --git a/ui/packages/consul-ui/app/templates/dc/nodes/show/healthchecks.hbs b/ui/packages/consul-ui/app/templates/dc/nodes/show/healthchecks.hbs index 0cb9d223d..6f3cd0e35 100644 --- a/ui/packages/consul-ui/app/templates/dc/nodes/show/healthchecks.hbs +++ b/ui/packages/consul-ui/app/templates/dc/nodes/show/healthchecks.hbs @@ -1,40 +1,55 @@ -{{#let (hash - statuses=(if status (split status ',') undefined) - kinds=(if kind (split kind ',') undefined) - checks=(if check (split check ',') undefined) - searchproperties=(if (not-eq searchproperty undefined) - (split searchproperty ',') - searchProperties +{{#let + + (hash + value=(or sortBy "Status:asc") + change=(action (mut sortBy) value="target.selected") ) -) as |filters|}} - {{#let (or sortBy "Status:asc") as |sort|}} + + (hash + status=(hash + value=(if status (split status ',') undefined) + change=(action (mut status) value="target.selectedItems") + ) + kind=(hash + value=(if kind (split kind ',') undefined) + change=(action (mut kind) value="target.selectedItems") + ) + check=(hash + value=(if check (split check ',') undefined) + change=(action (mut check) value="target.selectedItems") + ) + searchproperty=(hash + value=(if (not-eq searchproperty undefined) + (split searchproperty ',') + searchProperties + ) + change=(action (mut searchproperty) value="target.selectedItems") + default=searchProperties + ) + ) + + item.Checks + +as |sort filters items|}}
    - {{#if (gt item.Checks.length 0) }} + {{#if (gt items.length 0) }} {{/if}}

    - This node has no health checks{{#if (gt item.Checks.length 0)}} matching that search{{/if}}. + This node has no health checks{{#if (gt items.length 0)}} matching that search{{/if}}.

    - {{/let}} {{/let}} \ No newline at end of file diff --git a/ui/packages/consul-ui/app/templates/dc/nodes/show/services.hbs b/ui/packages/consul-ui/app/templates/dc/nodes/show/services.hbs index 491a13c14..1d1000fa6 100644 --- a/ui/packages/consul-ui/app/templates/dc/nodes/show/services.hbs +++ b/ui/packages/consul-ui/app/templates/dc/nodes/show/services.hbs @@ -1,13 +1,32 @@ -{{#let (hash - statuses=(if status (split status ',') undefined) - sources=(if source (split source ',') undefined) - searchproperties=(if (not-eq searchproperty undefined) - (split searchproperty ',') - searchProperties +{{#let + + (hash + value=(or sortBy "Status:asc") + change=(action (mut sortBy) value="target.selected") ) -) as |filters|}} - {{#let (or sortBy "Status:asc") as |sort|}} - {{#let (reject-by 'Service.Kind' 'connect-proxy' item.Services) as |items|}} + + (hash + status=(hash + value=(if status (split status ',') undefined) + change=(action (mut status) value="target.selectedItems") + ) + source=(hash + value=(if source (split source ',') undefined) + change=(action (mut source) value="target.selectedItems") + ) + searchproperty=(hash + value=(if (not-eq searchproperty undefined) + (split searchproperty ',') + searchProperties + ) + change=(action (mut searchproperty) value="target.selectedItems") + default=searchProperties + ) + ) + + (reject-by 'Service.Kind' 'connect-proxy' item.Services) + +as |sort filters items|}}
    {{#if (gt items.length 0) }} @@ -18,20 +37,14 @@ @searchproperties={{searchProperties}} @sort={{sort}} - @onsort={{action (mut sortBy) value="target.selected"}} @filter={{filters}} - @onfilter={{hash - searchproperty=(action (mut searchproperty) value="target.selectedItems") - status=(action (mut status) value="target.selectedItems") - source=(action (mut source) value="target.selectedItems") - }} /> {{/if}} {{! filter out any sidecar proxies }}
    - {{/let}} - {{/let}} {{/let}} \ No newline at end of file diff --git a/ui/packages/consul-ui/app/templates/dc/nspaces/index.hbs b/ui/packages/consul-ui/app/templates/dc/nspaces/index.hbs index b3397375c..a3a9eadd5 100644 --- a/ui/packages/consul-ui/app/templates/dc/nspaces/index.hbs +++ b/ui/packages/consul-ui/app/templates/dc/nspaces/index.hbs @@ -1,12 +1,27 @@ {{page-title 'Namespaces'}} -{{#let (hash - searchproperties=(if (not-eq searchproperty undefined) - (split searchproperty ',') - (array 'Name' 'Description' 'Policy' 'Role') + +{{#let + + (hash + value=(or sortBy "Name:asc") + change=(action (mut sortBy) value="target.selected") ) -) as |filters|}} - {{#let (or sortBy "Name:asc") as |sort|}} - + + (hash + searchproperty=(hash + value=(if (not-eq searchproperty undefined) + (split searchproperty ',') + searchProperties + ) + change=(action (mut searchproperty) value="target.selectedItems") + default=searchProperties + ) + ) + + items + +as |sort filters items|}} + {{/if}} - {{/let}} {{/let}} \ No newline at end of file diff --git a/ui/packages/consul-ui/app/templates/dc/services/index.hbs b/ui/packages/consul-ui/app/templates/dc/services/index.hbs index 2b65e33e7..892539567 100644 --- a/ui/packages/consul-ui/app/templates/dc/services/index.hbs +++ b/ui/packages/consul-ui/app/templates/dc/services/index.hbs @@ -4,15 +4,31 @@ {{#let - (or sortBy "Status:asc") + (hash + value=(or sortBy "Status:asc") + change=(action (mut sortBy) value="target.selected") + ) (hash - statuses=(if status (split status ',') undefined) - kinds=(if kind (split kind ',') undefined) - sources=(if source (split source ',') undefined) - searchproperties=(if (not-eq searchproperty undefined) - (split searchproperty ',') - (array 'Name' 'Tags') + status=(hash + value=(if status (split status ',') undefined) + change=(action (mut status) value="target.selectedItems") + ) + kind=(hash + value=(if kind (split kind ',') undefined) + change=(action (mut kind) value="target.selectedItems") + ) + source=(hash + value=(if source (split source ',') undefined) + change=(action (mut source) value="target.selectedItems") + ) + searchproperty=(hash + value=(if (not-eq searchproperty undefined) + (split searchproperty ',') + searchProperties + ) + change=(action (mut searchproperty) value="target.selectedItems") + default=searchProperties ) ) @@ -36,22 +52,16 @@ as |sort filters items|}} @onsearch={{action (mut search) value="target.value"}} @sort={{sort}} - @onsort={{action (mut sortBy) value="target.selected"}} @filter={{filters}} - @onfilter={{hash - searchproperty=(action (mut searchproperty) value="target.selectedItems") - status=(action (mut status) value="target.selectedItems") - kind=(action (mut kind) value="target.selectedItems") - source=(action (mut source) value="target.selectedItems") - }} + /> {{/if}} - {{#if (gt item.MeshChecks.length 0) }} + {{#if (gt items.length 0) }} {{/if}}

    - This instance has no health checks{{#if (gt item.MeshChecks.length 0)}} matching that search{{/if}}. + This instance has no health checks{{#if (gt items.length 0)}} matching that search{{/if}}.

    @@ -54,5 +65,4 @@
    - {{/let}} {{/let}} diff --git a/ui/packages/consul-ui/app/templates/dc/services/instance/upstreams.hbs b/ui/packages/consul-ui/app/templates/dc/services/instance/upstreams.hbs index 6ea8d7c32..6cb5bd5e9 100644 --- a/ui/packages/consul-ui/app/templates/dc/services/instance/upstreams.hbs +++ b/ui/packages/consul-ui/app/templates/dc/services/instance/upstreams.hbs @@ -1,12 +1,26 @@
    -{{#let (hash - searchproperties=(if (not-eq searchproperty undefined) - (split searchproperty ',') - searchProperties +{{#let + + (hash + value=(or sortBy "DestinationName:asc") + change=(action (mut sortBy) value="target.selected") ) -) as |filters|}} - {{#let (or sortBy "DestinationName:asc") as |sort|}} - {{#if (gt proxy.Service.Proxy.Upstreams.length 0)}} + + (hash + searchproperty=(hash + value=(if (not-eq searchproperty undefined) + (split searchproperty ',') + searchProperties + ) + change=(action (mut searchproperty) value="target.selectedItems") + default=searchProperties + ) + ) + + proxy.Service.Proxy.Upstreams + +as |sort filters items|}} + {{#if (gt items.length 0)}} {{/if}}

    - This service has no upstreams{{#if (gt proxy.Service.Proxy.Upstreams.length 0)}} matching that search{{/if}}. + This service has no upstreams{{#if (gt items.length 0)}} matching that search{{/if}}.

    - {{/let}} {{/let}}
    \ No newline at end of file diff --git a/ui/packages/consul-ui/app/templates/dc/services/show/instances.hbs b/ui/packages/consul-ui/app/templates/dc/services/show/instances.hbs index 39e2fb59e..cb6c553ca 100644 --- a/ui/packages/consul-ui/app/templates/dc/services/show/instances.hbs +++ b/ui/packages/consul-ui/app/templates/dc/services/show/instances.hbs @@ -1,36 +1,49 @@
    -{{#let (hash - statuses=(if status (split status ',') undefined) - sources=(if source (split source ',') undefined) - searchproperties=(if (not-eq searchproperty undefined) - (split searchproperty ',') - searchProperties +{{#let + + (hash + value=(or sortBy "Status:asc") + change=(action (mut sortBy) value="target.selected") ) -) as |filters|}} - {{#let (or sortBy "Status:asc") as |sort|}} + + (hash + status=(hash + value=(if status (split status ',') undefined) + change=(action (mut status) value="target.selectedItems") + ) + source=(hash + value=(if source (split source ',') undefined) + change=(action (mut source) value="target.selectedItems") + ) + searchproperty=(hash + value=(if (not-eq searchproperty undefined) + (split searchproperty ',') + searchProperties + ) + change=(action (mut searchproperty) value="target.selectedItems") + default=searchProperties + ) + ) + + items + +as |sort filters items|}} {{#if (gt items.length 0) }} {{/if}} {{! Service > Service Instance view doesn't require filtering of proxies }} - {{/let}} {{/let}}
    diff --git a/ui/packages/consul-ui/app/templates/dc/services/show/intentions/index.hbs b/ui/packages/consul-ui/app/templates/dc/services/show/intentions/index.hbs index b8a7e2257..3a2135d84 100644 --- a/ui/packages/consul-ui/app/templates/dc/services/show/intentions/index.hbs +++ b/ui/packages/consul-ui/app/templates/dc/services/show/intentions/index.hbs @@ -12,74 +12,83 @@ as |api|>
    -{{#let api.data as |items|}} - {{#let (hash - accesses=(if access (split access ',') undefined) - searchproperties=(if (not-eq searchproperty undefined) - (split searchproperty ',') - (array 'SourceName' 'DestinationName') +{{#let + + (hash + value=(or sortBy "Action:asc") + change=(action (mut sortBy) value="target.selected") + ) + + (hash + access=(hash + value=(if access (split access ',') undefined) + change=(action (mut access) value="target.selectedItems") ) - ) as |filters|}} - {{#let (or sortBy "Action:asc") as |sort|}} -
    - - Create - + searchproperty=(hash + value=(if (not-eq searchproperty undefined) + (split searchproperty ',') + searchProperties + ) + change=(action (mut searchproperty) value="target.selectedItems") + default=searchProperties + ) + ) + + api.data + +as |sort filters items|}} +
    + + Create + {{#if (gt items.length 0) }} - + @filter={{filters}} + /> {{/if}} - + + - - - - - - - - - - - - -

    - There are no intentions {{if (gt items.length 0) 'found '}} for this service. -

    -
    -
    -
    -
    -
    -
    -
    - {{/let}} - {{/let}} + @sort={{sort.value}} + @filters={{filters}} + @search={{search}} + @items={{items}} + as |collection|> + + + + + + + + + + +

    + There are no intentions {{if (gt items.length 0) 'found '}} for this service. +

    +
    +
    +
    + + + +
    {{/let}}
    diff --git a/ui/packages/consul-ui/app/templates/dc/services/show/services.hbs b/ui/packages/consul-ui/app/templates/dc/services/show/services.hbs index dec7ccb52..a080c2363 100644 --- a/ui/packages/consul-ui/app/templates/dc/services/show/services.hbs +++ b/ui/packages/consul-ui/app/templates/dc/services/show/services.hbs @@ -1,27 +1,39 @@ - +
    -{{#let (hash - instances=(if instance (split instance ',') undefined) - searchproperties=(if (not-eq searchproperty undefined) - (split searchproperty ',') - (array 'Name' 'Tags') +{{#let + + (hash + value=(or sortBy "Status:asc") + change=(action (mut sortBy) value="target.selected") ) -) as |filters|}} - {{#let (or sortBy "Name:asc") as |sort|}} -{{#if (gt gatewayServices.length 0)}} + + (hash + instance=(hash + value=(if instance (split instance ',') undefined) + change=(action (mut instance) value="target.selectedItems") + ) + searchproperty=(hash + value=(if (not-eq searchproperty undefined) + (split searchproperty ',') + searchProperties + ) + change=(action (mut searchproperty) value="target.selectedItems") + default=searchProperties + ) + ) + + items + +as |sort filters items|}} +{{#if (gt items.length 0)}} {{/if}}

    @@ -30,10 +42,10 @@

    - There are no linked services{{#if (gt gatewayServices.length 0)}} matching that search{{/if}}. + There are no linked services{{#if (gt items.length 0)}} matching that search{{/if}}.

    - {{/let}} {{/let}}
    diff --git a/ui/packages/consul-ui/app/templates/dc/services/show/upstreams.hbs b/ui/packages/consul-ui/app/templates/dc/services/show/upstreams.hbs index bb67a0044..f6f54c8f0 100644 --- a/ui/packages/consul-ui/app/templates/dc/services/show/upstreams.hbs +++ b/ui/packages/consul-ui/app/templates/dc/services/show/upstreams.hbs @@ -1,27 +1,39 @@ - +
    -{{#let (hash - instances=(if instance (split instance ',') undefined) - searchproperties=(if (not-eq searchproperty undefined) - (split searchproperty ',') - (array 'Name' 'Tags') +{{#let + + (hash + value=(or sortBy "Status:asc") + change=(action (mut sortBy) value="target.selected") ) -) as |filters|}} - {{#let (or sortBy "Status:asc") as |sort|}} -{{#if (gt gatewayServices.length 0)}} + + (hash + instance=(hash + value=(if instance (split instance ',') undefined) + change=(action (mut instance) value="target.selectedItems") + ) + searchproperty=(hash + value=(if (not-eq searchproperty undefined) + (split searchproperty ',') + searchProperties + ) + change=(action (mut searchproperty) value="target.selectedItems") + default=searchProperties + ) + ) + + items + +as |sort filters items|}} +{{#if (gt items.length 0)}} {{/if}}

    @@ -29,10 +41,10 @@

    - There are no upstreams{{#if (gt gatewayServices.length 0)}} matching that search{{/if}}. + There are no upstreams{{#if (gt items.length 0)}} matching that search{{/if}}.

    - {{/let}} {{/let}}
    diff --git a/ui/packages/consul-ui/app/utils/intl/missing-message.js b/ui/packages/consul-ui/app/utils/intl/missing-message.js new file mode 100644 index 000000000..f156fb93c --- /dev/null +++ b/ui/packages/consul-ui/app/utils/intl/missing-message.js @@ -0,0 +1,9 @@ +// if we can't find the message, take the last part of the identifier and +// ucfirst it so it looks human +export default function missingMessage(key, locales) { + const last = key + .split('.') + .pop() + .replaceAll('-', ' '); + return `${last.substr(0, 1).toUpperCase()}${last.substr(1)}`; +} diff --git a/ui/packages/consul-ui/tests/integration/components/search-bar-test.js b/ui/packages/consul-ui/tests/integration/components/search-bar-test.js deleted file mode 100644 index 91b178009..000000000 --- a/ui/packages/consul-ui/tests/integration/components/search-bar-test.js +++ /dev/null @@ -1,24 +0,0 @@ -import { module, test } from 'qunit'; -import { setupRenderingTest } from 'ember-qunit'; -import { render } from '@ember/test-helpers'; -import { hbs } from 'ember-cli-htmlbars'; - -module('Integration | Component | search-bar', function(hooks) { - setupRenderingTest(hooks); - - test('it renders', async function(assert) { - // Set any properties with this.set('myProperty', 'value'); - this.set('search', function(e) {}); - - await render(hbs``); - - assert.equal(this.element.textContent.trim(), 'Search'); - - // Template block usage: - await render(hbs` - - `); - - assert.equal(this.element.textContent.trim(), 'Search'); - }); -}); diff --git a/ui/packages/consul-ui/tests/pages.js b/ui/packages/consul-ui/tests/pages.js index cef83a67b..351276307 100644 --- a/ui/packages/consul-ui/tests/pages.js +++ b/ui/packages/consul-ui/tests/pages.js @@ -6,7 +6,6 @@ import { collection, text, isPresent, - triggerable, } from 'ember-cli-page-object'; import { alias } from 'ember-cli-page-object/macros'; @@ -26,9 +25,7 @@ import pageFactory from 'consul-ui/components/hashicorp-consul/pageobject'; import radiogroup from 'consul-ui/components/radio-group/pageobject'; import tabgroup from 'consul-ui/components/tab-nav/pageobject'; import authFormFactory from 'consul-ui/components/auth-form/pageobject'; -import freetextFilterFactory from 'consul-ui/components/freetext-filter/pageobject'; -import searchBarFactory from 'consul-ui/components/search-bar/pageobject'; import emptyStateFactory from 'consul-ui/components/empty-state/pageobject'; import policyFormFactory from 'consul-ui/components/policy-form/pageobject'; @@ -82,11 +79,6 @@ const cancelable = createCancelable(clickable, is); // components const tokenList = tokenListFactory(clickable, attribute, collection, deletable); const authForm = authFormFactory(submitable, clickable, attribute); -const freetextFilter = freetextFilterFactory(triggerable); -const catalogToolbar = searchBarFactory(freetextFilter); -const aclFilter = searchBarFactory(freetextFilter, () => - radiogroup('type', ['', 'management', 'client']) -); const policyForm = policyFormFactory(submitable, cancelable, radiogroup, text); const policySelector = policySelectorFactory(clickable, deletable, collection, alias, policyForm); const roleForm = roleFormFactory(submitable, cancelable, policySelector); @@ -160,18 +152,7 @@ export default { radiogroup ) ), - service: create( - service( - visitable, - clickable, - attribute, - collection, - text, - consulIntentionList, - catalogToolbar, - tabgroup - ) - ), + service: create(service(visitable, clickable, attribute, collection, text, consulIntentionList, tabgroup)), instance: create( instance( visitable, @@ -199,7 +180,7 @@ export default { ), kvs: create(kvs(visitable, creatable, consulKvList)), kv: create(kv(visitable, attribute, submitable, deletable, cancelable, clickable)), - acls: create(acls(visitable, deletable, creatable, clickable, attribute, collection, aclFilter)), + acls: create(acls(visitable, deletable, creatable, clickable, attribute, collection)), acl: create(acl(visitable, submitable, deletable, cancelable, clickable)), policies: create(policies(visitable, creatable, consulPolicyList, popoverSelect)), policy: create(policy(visitable, submitable, deletable, cancelable, clickable, tokenList)), diff --git a/ui/packages/consul-ui/tests/pages/dc/acls/index.js b/ui/packages/consul-ui/tests/pages/dc/acls/index.js index a460f81dd..ec335ed87 100644 --- a/ui/packages/consul-ui/tests/pages/dc/acls/index.js +++ b/ui/packages/consul-ui/tests/pages/dc/acls/index.js @@ -1,4 +1,4 @@ -export default function(visitable, deletable, creatable, clickable, attribute, collection, filter) { +export default function(visitable, deletable, creatable, clickable, attribute, collection) { return creatable({ visit: visitable('/:dc/acls'), acls: collection( @@ -11,6 +11,5 @@ export default function(visitable, deletable, creatable, clickable, attribute, c confirmUse: clickable('[data-test-confirm-use]'), }) ), - filter: filter('[data-test-acl-filter]'), }); } diff --git a/ui/packages/consul-ui/tests/pages/dc/services/show.js b/ui/packages/consul-ui/tests/pages/dc/services/show.js index 5f2d7b366..7936ce8a4 100644 --- a/ui/packages/consul-ui/tests/pages/dc/services/show.js +++ b/ui/packages/consul-ui/tests/pages/dc/services/show.js @@ -1,13 +1,4 @@ -export default function( - visitable, - clickable, - attribute, - collection, - text, - intentions, - filter, - tabs -) { +export default function(visitable, clickable, attribute, collection, text, intentions, tabs) { const page = { visit: visitable('/:dc/services/:service'), externalSource: attribute('data-test-external-source', '[data-test-external-source]', { @@ -28,7 +19,6 @@ export default function( 'routing', 'tags', ]), - filter: filter(), // TODO: These need to somehow move to subpages instances: collection('.consul-service-instance-list > ul > li:not(:first-child)', { address: text('[data-test-address]'), diff --git a/ui/packages/consul-ui/tests/unit/components/search-bar/filters-test.js b/ui/packages/consul-ui/tests/unit/components/search-bar/filters-test.js new file mode 100644 index 000000000..08c444c65 --- /dev/null +++ b/ui/packages/consul-ui/tests/unit/components/search-bar/filters-test.js @@ -0,0 +1,154 @@ +import { filters } from 'consul-ui/components/search-bar/utils'; +import { module, test } from 'qunit'; + +module('Unit | Component | search-bar/filters', function() { + test('it correctly reshapes the filter data', function(assert) { + [ + // basic filter, returns a single filter button when clicked + // resets selected/queryparam to empty + { + filters: { + status: { + value: ['passing'], + }, + }, + expected: [ + { + key: 'status', + value: 'passing', + selected: [], + }, + ], + }, + // basic filters, returns multiple filter button when clicked + // sets selected/queryparam to the left over single filter + { + filters: { + status: { + value: ['passing', 'warning'], + }, + }, + expected: [ + { + key: 'status', + value: 'passing', + selected: ['warning'], + }, + { + key: 'status', + value: 'warning', + selected: ['passing'], + }, + ], + }, + // basic filters, returns multiple filter button when clicked + // sets selected/queryparam to the left over multiple filters + { + filters: { + status: { + value: ['passing', 'warning', 'critical'], + }, + }, + expected: [ + { + key: 'status', + value: 'passing', + selected: ['warning', 'critical'], + }, + { + key: 'status', + value: 'warning', + selected: ['passing', 'critical'], + }, + { + key: 'status', + value: 'critical', + selected: ['passing', 'warning'], + }, + ], + }, + // basic filters, returns multiple filter button when clicked + // sets selected/queryparam to the left over multiple filters + // also search property multiple filter, sets the selected/queryparam to + // the left of single searchproperty filter + { + filters: { + status: { + value: ['passing', 'warning', 'critical'], + }, + searchproperties: { + default: ['Node', 'Address', 'Meta'], + value: ['Node', 'Address'], + }, + }, + expected: [ + { + key: 'status', + value: 'passing', + selected: ['warning', 'critical'], + }, + { + key: 'status', + value: 'warning', + selected: ['passing', 'critical'], + }, + { + key: 'status', + value: 'critical', + selected: ['passing', 'warning'], + }, + { + key: 'searchproperties', + value: 'Node', + selected: ['Address'], + }, + { + key: 'searchproperties', + value: 'Address', + selected: ['Node'], + }, + ], + }, + // basic filters, returns multiple filter button when clicked + // sets selected/queryparam to the left over multiple filters + // also search property single filter, resets the selected/queryparam to + // empty + { + filters: { + status: { + value: ['passing', 'warning', 'critical'], + }, + searchproperties: { + default: ['Node', 'Address', 'Meta'], + value: ['Node'], + }, + }, + expected: [ + { + key: 'status', + value: 'passing', + selected: ['warning', 'critical'], + }, + { + key: 'status', + value: 'warning', + selected: ['passing', 'critical'], + }, + { + key: 'status', + value: 'critical', + selected: ['passing', 'warning'], + }, + { + key: 'searchproperties', + value: 'Node', + selected: [], + }, + ], + }, + ].forEach(item => { + const actual = filters(item.filters); + assert.deepEqual(actual, item.expected); + }); + }); +}); diff --git a/ui/packages/consul-ui/tests/unit/filter/predicates/intention-test.js b/ui/packages/consul-ui/tests/unit/filter/predicates/intention-test.js index 26d67ff26..eaae3c9a2 100644 --- a/ui/packages/consul-ui/tests/unit/filter/predicates/intention-test.js +++ b/ui/packages/consul-ui/tests/unit/filter/predicates/intention-test.js @@ -20,7 +20,7 @@ module('Unit | Filter | Predicates | intention', function() { expected = [items[0]]; actual = items.filter( predicate({ - accesses: ['allow'], + access: ['allow'], }) ); assert.deepEqual(actual, expected); @@ -28,7 +28,7 @@ module('Unit | Filter | Predicates | intention', function() { expected = [items[1]]; actual = items.filter( predicate({ - accesses: ['deny'], + access: ['deny'], }) ); assert.deepEqual(actual, expected); @@ -36,7 +36,7 @@ module('Unit | Filter | Predicates | intention', function() { expected = items; actual = items.filter( predicate({ - accesses: ['allow', 'deny'], + access: ['allow', 'deny'], }) ); assert.deepEqual(actual, expected); diff --git a/ui/packages/consul-ui/tests/unit/filter/predicates/service-test.js b/ui/packages/consul-ui/tests/unit/filter/predicates/service-test.js index 004da9948..01f3e600c 100644 --- a/ui/packages/consul-ui/tests/unit/filter/predicates/service-test.js +++ b/ui/packages/consul-ui/tests/unit/filter/predicates/service-test.js @@ -20,7 +20,7 @@ module('Unit | Filter | Predicates | service', function() { expected = [items[0]]; actual = items.filter( predicate({ - instances: ['registered'], + instance: ['registered'], }) ); assert.deepEqual(actual, expected); @@ -28,7 +28,7 @@ module('Unit | Filter | Predicates | service', function() { expected = [items[1]]; actual = items.filter( predicate({ - instances: ['not-registered'], + instance: ['not-registered'], }) ); assert.deepEqual(actual, expected); @@ -36,7 +36,7 @@ module('Unit | Filter | Predicates | service', function() { expected = items; actual = items.filter( predicate({ - instances: ['registered', 'not-registered'], + instance: ['registered', 'not-registered'], }) ); assert.deepEqual(actual, expected); @@ -60,7 +60,7 @@ module('Unit | Filter | Predicates | service', function() { expected = [items[0]]; actual = items.filter( predicate({ - statuses: ['passing'], + status: ['passing'], }) ); assert.deepEqual(actual, expected); @@ -68,7 +68,7 @@ module('Unit | Filter | Predicates | service', function() { expected = [items[1]]; actual = items.filter( predicate({ - statuses: ['warning'], + status: ['warning'], }) ); assert.deepEqual(actual, expected); @@ -76,7 +76,7 @@ module('Unit | Filter | Predicates | service', function() { expected = items; actual = items.filter( predicate({ - statuses: ['passing', 'warning', 'critical'], + status: ['passing', 'warning', 'critical'], }) ); assert.deepEqual(actual, expected); @@ -98,7 +98,7 @@ module('Unit | Filter | Predicates | service', function() { expected = [items[0]]; actual = items.filter( predicate({ - kinds: ['ingress-gateway'], + kind: ['ingress-gateway'], }) ); assert.deepEqual(actual, expected); @@ -106,7 +106,7 @@ module('Unit | Filter | Predicates | service', function() { expected = [items[1]]; actual = items.filter( predicate({ - kinds: ['mesh-gateway'], + kind: ['mesh-gateway'], }) ); assert.deepEqual(actual, expected); @@ -114,7 +114,7 @@ module('Unit | Filter | Predicates | service', function() { expected = items; actual = items.filter( predicate({ - kinds: ['ingress-gateway', 'mesh-gateway', 'service'], + kind: ['ingress-gateway', 'mesh-gateway', 'service'], }) ); assert.deepEqual(actual, expected); @@ -142,9 +142,9 @@ module('Unit | Filter | Predicates | service', function() { expected = [items[0]]; actual = items.filter( predicate({ - kinds: ['ingress-gateway'], - statuses: ['passing'], - instances: ['registered'], + kind: ['ingress-gateway'], + status: ['passing'], + instance: ['registered'], }) ); assert.deepEqual(actual, expected); @@ -152,9 +152,9 @@ module('Unit | Filter | Predicates | service', function() { expected = [items[1]]; actual = items.filter( predicate({ - kinds: ['mesh-gateway'], - statuses: ['warning'], - instances: ['registered'], + kind: ['mesh-gateway'], + status: ['warning'], + instance: ['registered'], }) ); assert.deepEqual(actual, expected); @@ -162,9 +162,9 @@ module('Unit | Filter | Predicates | service', function() { expected = items; actual = items.filter( predicate({ - kinds: ['ingress-gateway', 'mesh-gateway', 'service'], - statuses: ['passing', 'warning', 'critical'], - instances: ['registered', 'not-registered'], + kind: ['ingress-gateway', 'mesh-gateway', 'service'], + status: ['passing', 'warning', 'critical'], + instance: ['registered', 'not-registered'], }) ); assert.deepEqual(actual, expected); diff --git a/ui/packages/consul-ui/translations/en-us.yaml b/ui/packages/consul-ui/translations/en-us.yaml index 84e4adae4..f80096fd0 100644 --- a/ui/packages/consul-ui/translations/en-us.yaml +++ b/ui/packages/consul-ui/translations/en-us.yaml @@ -1 +1,158 @@ common: + brand: + consul: Consul + terraform: Terraform + nomad: Nomad + vault: Vault + aws: AWS + kubernetes: Kubernetes + ui: + remove: Remove {item} + filtered-by: Filtered by {item} + name: Name + creation: Creation + consul: + name: Name + passing: Passing + warning: Warning + critical: Critical + registered: Registered + not-registered: Not Registered + empty: No checks + tags: Tags + service: Service + gateway: Gateway + mesh: Mesh + ingress-gateway: Ingress Gateway + terminating-gateway: Terminating Gateway + mesh-gateway: Mesh Gateway + status: Health Status + service-name: Service Name + node-name: Node Name + accessorid: AccessorID + datacenter: Datacenter + localbindaddress: Local Bind Address + localbindport: Local Bind Port + destinationname: Destination Name + sourcename: Source Name + search: + search: Search + searchproperty: Search Across + source: Source + critical: Failing + in-mesh: In service mesh + not-in-mesh: Not in service mesh + sort: + alpha: + asc: A to Z + desc: Z to A + numeric: + asc: Ascending + desc: Descending + age: + asc: Oldest to Newest + desc: Newest to Oldest + status: + asc: Unhealthy to Healthy + desc: Healthy to Unhealthy + +components: + consul: + service: + search-bar: + kind: Service Type + in-mesh: In service mesh + not-in-mesh: Not in service mesh + upstream: + search-bar: + instance: + name: Type + service-instance: + search-bar: + sort: + name: + name: Service Name + health-check: + search-bar: + kind: + name: Kind + options: + service: Service Check + node: Node Check + check: + name: Type + options: + alias: alias + docker: docker + grpc: grpc + http: http + script: script + serf: serf + tcp: tcp + ttl: ttl + sort: + name: + name: Check Name + kind: + name: Check Type + asc: Service to Node + desc: Node to Service + acl: + search-bar: + kind: + name: Type + options: + management: Management + client: Client + token: + search-bar: + kind: + name: Type + options: + global-management: Global Management + global: Global Scope + local: Local Scope + policy: + search-bar: + kind: + name: Type + options: + global-management: Global Management + standard: Standard + kv: + search-bar: + kind: + name: Type + options: + folder: Folder + key: Key + sort: + kind: + asc: Folders to Keys + desc: Keys to Folders + intention: + search-bar: + access: + name: Permission + options: + allow: Allow + deny: Deny + app-aware: App aware + sort: + access: + name: Permission + asc: Allow to Deny + desc: Deny to Allow + source-name: + name: Source + asc: "Source: A to Z" + desc: "Source: Z to A" + destination-name: + name: Destination + asc: "Destination: A to Z" + desc: "Destination: Z to A" + precedence: + name: Precedence + asc: Ascending + desc: Descending +