diff --git a/ui/admin/app/controllers/scopes/scope/host-catalogs/index.js b/ui/admin/app/controllers/scopes/scope/host-catalogs/index.js
index 144785a7d..ab91bdd0c 100644
--- a/ui/admin/app/controllers/scopes/scope/host-catalogs/index.js
+++ b/ui/admin/app/controllers/scopes/scope/host-catalogs/index.js
@@ -21,11 +21,19 @@ export default class ScopesScopeHostCatalogsIndexController extends Controller {
// =attributes
- queryParams = ['search', 'page', 'pageSize'];
+ queryParams = [
+ 'search',
+ 'page',
+ 'pageSize',
+ 'sortAttribute',
+ 'sortDirection',
+ ];
@tracked search;
@tracked page = 1;
@tracked pageSize = 10;
+ @tracked sortAttribute;
+ @tracked sortDirection;
/**
* If can list (at least): return default welcome message.
@@ -138,4 +146,16 @@ export default class ScopesScopeHostCatalogsIndexController extends Controller {
changeCredentialType(hostCatalog, credentialType) {
hostCatalog.credentialType = credentialType;
}
+
+ /**
+ * Set sort values and sets page to 1
+ * @param {string} sortBy
+ * @param {string} sortOrder
+ */
+ @action
+ onSort(sortBy, sortOrder) {
+ this.sortAttribute = sortBy;
+ this.sortDirection = sortOrder;
+ this.page = 1;
+ }
}
diff --git a/ui/admin/app/routes/scopes/scope/host-catalogs/index.js b/ui/admin/app/routes/scopes/scope/host-catalogs/index.js
index 144dbefac..ee4bb32f3 100644
--- a/ui/admin/app/routes/scopes/scope/host-catalogs/index.js
+++ b/ui/admin/app/routes/scopes/scope/host-catalogs/index.js
@@ -26,6 +26,14 @@ export default class ScopesScopeHostCatalogsIndexRoute extends Route {
pageSize: {
refreshModel: true,
},
+ sortAttribute: {
+ refreshModel: true,
+ replace: true,
+ },
+ sortDirection: {
+ refreshModel: true,
+ replace: true,
+ },
};
// =methods
@@ -41,7 +49,14 @@ export default class ScopesScopeHostCatalogsIndexRoute extends Route {
}
retrieveData = restartableTask(
- async ({ search, page, pageSize, useDebounce }) => {
+ async ({
+ search,
+ page,
+ pageSize,
+ sortAttribute,
+ sortDirection,
+ useDebounce,
+ }) => {
if (useDebounce) {
await timeout(250);
}
@@ -55,13 +70,18 @@ export default class ScopesScopeHostCatalogsIndexRoute extends Route {
'plugin.name': [],
};
+ const sort = {
+ attribute: sortAttribute,
+ direction: sortDirection,
+ };
+
let hostCatalogs;
let totalItems = 0;
let doHostCatalogsExist = false;
if (this.can.can('list model', scope, { collection: 'host-catalogs' })) {
hostCatalogs = await this.store.query('host-catalog', {
scope_id,
- query: { search, filters },
+ query: { search, filters, sort },
page,
pageSize,
});
diff --git a/ui/admin/app/templates/scopes/scope/host-catalogs/index.hbs b/ui/admin/app/templates/scopes/scope/host-catalogs/index.hbs
index 86ec12589..2af8de961 100644
--- a/ui/admin/app/templates/scopes/scope/host-catalogs/index.hbs
+++ b/ui/admin/app/templates/scopes/scope/host-catalogs/index.hbs
@@ -46,45 +46,58 @@
{{#if @model.hostCatalogs}}
+ <:head as |H|>
+
+ {{t 'form.name.label'}}
+ {{t 'form.type.label'}}
+ {{t 'form.id.label'}}
+
+
<:body as |B|>
-
-
- {{#if (can 'read host-catalog' B.data)}}
-
- {{B.data.displayName}}
-
- {{else}}
-
- {{B.data.displayName}}
-
- {{/if}}
- {{B.data.description}}
-
-
-
-
-
-
-
-
+ {{#each @model.hostCatalogs as |data|}}
+
+
+ {{#if (can 'read host-catalog' data)}}
+
+ {{data.displayName}}
+
+ {{else}}
+
+ {{data.displayName}}
+
+ {{/if}}
+ {{data.description}}
+
+
+
+
+
+
+
+
+ {{/each}}
+
{
+ return this.server.create('host-catalog', {
+ scope: instances.scopes.project,
+ type: TYPE_HOST_CATALOG_STATIC,
+ created_time: `${year}-01-01T00:00:00Z`,
+ name: `Host catalogs ${year}`,
+ });
+ });
+
+ await visit(urls.hostCatalogs);
+
+ assert.dom(commonSelectors.TABLE_ROWS).exists({ count: years.length });
+ years.forEach((year, index) => {
+ // nth-child index starts at 1
+ assert
+ .dom(commonSelectors.TABLE_ROW(index + 1))
+ .containsText(`Host catalogs ${year}`);
+ });
+ });
+
+ test.each(
+ 'sorting',
+ {
+ 'on name': {
+ attribute: {
+ key: 'name',
+ values: ['Alpha', 'Delta', 'Beta', 'Gamma', 'Epsilon'],
+ },
+ expectedAscendingSort: ['Alpha', 'Beta', 'Delta', 'Epsilon', 'Gamma'],
+ column: 1,
+ },
+ 'on id': {
+ attribute: {
+ key: 'id',
+ values: ['hc_1000', 'hc_0001', 'hc_0100', 'hc_0010'],
+ },
+ expectedAscendingSort: ['hc_0001', 'hc_0010', 'hc_0100', 'hc_1000'],
+ column: 3,
+ },
+ },
+ async function (assert, input) {
+ this.server.schema.hostCatalogs.all().destroy();
+ faker.helpers.shuffle(input.attribute.values).forEach((value) => {
+ this.server.create('host-catalog', {
+ [input.attribute.key]: value,
+ scope: instances.scopes.project,
+ });
+ });
+
+ await visit(urls.hostCatalogs);
+
+ // click the sort button again to sort in ascending order
+ await click(commonSelectors.TABLE_SORT_BTN(input.column));
+ assert.true(currentURL().includes('sortDirection=asc'));
+ assert.true(
+ currentURL().includes(`sortAttribute=${input.attribute.key}`),
+ );
+ assert
+ .dom(commonSelectors.TABLE_SORT_BTN_ARROW_UP(input.column))
+ .isVisible();
+
+ assert
+ .dom(commonSelectors.TABLE_ROWS)
+ .isVisible({ count: input.attribute.values.length });
+
+ input.expectedAscendingSort.forEach((expected, index) => {
+ // nth-child index starts at 1
+ assert.dom(commonSelectors.TABLE_ROW(index + 1)).containsText(expected);
+ });
+
+ // click the sort button again to sort in descending order
+ await click(commonSelectors.TABLE_SORT_BTN(input.column));
+ assert.true(currentURL().includes('sortDirection=desc'));
+ assert.true(
+ currentURL().includes(`sortAttribute=${input.attribute.key}`),
+ );
+ assert
+ .dom(commonSelectors.TABLE_SORT_BTN_ARROW_DOWN(input.column))
+ .isVisible();
+
+ input.expectedAscendingSort.toReversed().forEach((expected, index) => {
+ // nth-child index starts at 1
+ assert.dom(commonSelectors.TABLE_ROW(index + 1)).containsText(expected);
+ });
+ },
+ );
});