diff --git a/ui/app/controllers/csi/volumes/index.js b/ui/app/controllers/csi/volumes/index.js index aa63bb51b..20aad2406 100644 --- a/ui/app/controllers/csi/volumes/index.js +++ b/ui/app/controllers/csi/volumes/index.js @@ -3,6 +3,7 @@ import { computed } from '@ember/object'; import { alias, readOnly } from '@ember/object/computed'; import Controller, { inject as controller } from '@ember/controller'; import SortableFactory from 'nomad-ui/mixins/sortable-factory'; +import Searchable from 'nomad-ui/mixins/searchable'; import { lazyClick } from 'nomad-ui/helpers/lazy-click'; export default Controller.extend( @@ -13,6 +14,7 @@ export default Controller.extend( 'nodesHealthyProportion', 'provider', ]), + Searchable, { system: service(), userSettings: service(), @@ -22,6 +24,7 @@ export default Controller.extend( queryParams: { currentPage: 'page', + searchTerm: 'search', sortProperty: 'sort', sortDescending: 'desc', }, @@ -32,6 +35,10 @@ export default Controller.extend( sortProperty: 'id', sortDescending: false, + searchProps: computed(() => ['name']), + fuzzySearchProps: computed(() => ['name']), + fuzzySearchEnabled: true, + /** Visible volumes are those that match the selected namespace */ @@ -49,14 +56,8 @@ export default Controller.extend( }), listToSort: alias('visibleVolumes'), - sortedVolumes: alias('listSorted'), - - // TODO: Remove once this page gets search capability - resetPagination() { - if (this.currentPage != null) { - this.set('currentPage', 1); - } - }, + listToSearch: alias('listSorted'), + sortedVolumes: alias('listSearched'), actions: { gotoVolume(volume, event) { diff --git a/ui/app/templates/csi/volumes/index.hbs b/ui/app/templates/csi/volumes/index.hbs index 6b4b41faf..67f5493f7 100644 --- a/ui/app/templates/csi/volumes/index.hbs +++ b/ui/app/templates/csi/volumes/index.hbs @@ -9,6 +9,17 @@ {{#if isForbidden}} {{partial "partials/forbidden-message"}} {{else}} +
+
+ {{#if model.length}} + {{search-box + data-test-volumes-search + searchTerm=(mut searchTerm) + onChange=(action resetPagination) + placeholder="Search volumes..."}} + {{/if}} +
+
{{#if sortedVolumes}} {{#list-pagination source=sortedVolumes @@ -60,10 +71,17 @@ {{/list-pagination}} {{else}}
-

No Volumes

-

- The cluster currently has no CSI Volumes. -

+ {{#if (eq model.length 0)}} +

No Volumes

+

+ The cluster currently has no CSI Volumes. +

+ {{else if searchTerm}} +

No Matches

+

+ No volumes match the term {{searchTerm}} +

+ {{/if}}
{{/if}} {{/if}} diff --git a/ui/tests/acceptance/volumes-list-test.js b/ui/tests/acceptance/volumes-list-test.js index 4aff4b92f..d86ff72ce 100644 --- a/ui/tests/acceptance/volumes-list-test.js +++ b/ui/tests/acceptance/volumes-list-test.js @@ -101,6 +101,30 @@ module('Acceptance | volumes list', function(hooks) { assert.equal(VolumesList.emptyState.headline, 'No Volumes'); }); + test('when there are volumes, but no matches for a search result, there is an empty message', async function(assert) { + server.create('csi-volume', { id: 'cat 1' }); + server.create('csi-volume', { id: 'cat 2' }); + + await VolumesList.visit(); + + await VolumesList.search('dog'); + assert.ok(VolumesList.isEmpty); + assert.equal(VolumesList.emptyState.headline, 'No Matches'); + }); + + test('searching resets the current page', async function(assert) { + server.createList('csi-volume', VolumesList.pageSize + 1); + + await VolumesList.visit(); + await VolumesList.nextPage(); + + assert.equal(currentURL(), '/csi/volumes?page=2'); + + await VolumesList.search('foobar'); + + assert.equal(currentURL(), '/csi/volumes?search=foobar'); + }); + test('when the namespace query param is set, only matching volumes are shown and the namespace value is forwarded to app state', async function(assert) { server.createList('namespace', 2); const volume1 = server.create('csi-volume', { namespaceId: server.db.namespaces[0].id }); diff --git a/ui/tests/pages/storage/volumes/list.js b/ui/tests/pages/storage/volumes/list.js index 85687f7b0..36b17a239 100644 --- a/ui/tests/pages/storage/volumes/list.js +++ b/ui/tests/pages/storage/volumes/list.js @@ -1,4 +1,12 @@ -import { clickable, collection, create, isPresent, text, visitable } from 'ember-cli-page-object'; +import { + clickable, + collection, + create, + fillable, + isPresent, + text, + visitable, +} from 'ember-cli-page-object'; import error from 'nomad-ui/tests/pages/components/error'; import pageSizeSelect from 'nomad-ui/tests/pages/components/page-size-select'; @@ -8,6 +16,8 @@ export default create({ visit: visitable('/csi/volumes'), + search: fillable('[data-test-volumes-search] input'), + volumes: collection('[data-test-volume-row]', { name: text('[data-test-volume-name]'), schedulable: text('[data-test-volume-schedulable]'),