diff --git a/ui/admin/app/controllers/scopes/scope/auth-methods/index.js b/ui/admin/app/controllers/scopes/scope/auth-methods/index.js
index 5a12091a6..334c95eb2 100644
--- a/ui/admin/app/controllers/scopes/scope/auth-methods/index.js
+++ b/ui/admin/app/controllers/scopes/scope/auth-methods/index.js
@@ -28,6 +28,8 @@ export default class ScopesScopeAuthMethodsIndexController extends Controller {
{ primary: { type: 'array' } },
'page',
'pageSize',
+ 'sortAttribute',
+ 'sortDirection',
];
@tracked search;
@@ -35,6 +37,8 @@ export default class ScopesScopeAuthMethodsIndexController extends Controller {
@tracked primary = [];
@tracked page = 1;
@tracked pageSize = 10;
+ @tracked sortAttribute;
+ @tracked sortDirection;
/**
* True if the current scope has a primary auth method set.
@@ -326,4 +330,16 @@ export default class ScopesScopeAuthMethodsIndexController extends Controller {
async changeState(authMethod, state) {
await authMethod.changeState(state);
}
+
+ /**
+ * 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/auth-methods/index.js b/ui/admin/app/routes/scopes/scope/auth-methods/index.js
index 2ca60c9d2..00f8de14b 100644
--- a/ui/admin/app/routes/scopes/scope/auth-methods/index.js
+++ b/ui/admin/app/routes/scopes/scope/auth-methods/index.js
@@ -35,6 +35,14 @@ export default class ScopesScopeAuthMethodsIndexRoute extends Route {
pageSize: {
refreshModel: true,
},
+ sortAttribute: {
+ refreshModel: true,
+ replace: true,
+ },
+ sortDirection: {
+ refreshModel: true,
+ replace: true,
+ },
};
// =methods
@@ -50,7 +58,16 @@ export default class ScopesScopeAuthMethodsIndexRoute extends Route {
}
retrieveData = restartableTask(
- async ({ search, types, primary, page, pageSize, useDebounce }) => {
+ async ({
+ search,
+ types,
+ primary,
+ page,
+ pageSize,
+ sortAttribute,
+ sortDirection,
+ useDebounce,
+ }) => {
if (useDebounce) {
await timeout(250);
}
@@ -63,6 +80,11 @@ export default class ScopesScopeAuthMethodsIndexRoute extends Route {
is_primary: [],
};
+ const sort = {
+ attribute: sortAttribute,
+ direction: sortDirection,
+ };
+
types.forEach((type) => {
filters.type.push({ equals: type });
});
@@ -82,7 +104,7 @@ export default class ScopesScopeAuthMethodsIndexRoute extends Route {
'auth-method',
{
scope_id,
- query: { search, filters },
+ query: { search, filters, sort },
page,
pageSize,
},
diff --git a/ui/admin/app/templates/scopes/scope/auth-methods/index.hbs b/ui/admin/app/templates/scopes/scope/auth-methods/index.hbs
index 0268f9fab..5922d8727 100644
--- a/ui/admin/app/templates/scopes/scope/auth-methods/index.hbs
+++ b/ui/admin/app/templates/scopes/scope/auth-methods/index.hbs
@@ -94,80 +94,102 @@
{{#if @model.authMethods}}
+ <:head as |H|>
+
+ {{t 'form.name.label'}}
+ {{t 'form.type.label'}}
+ {{t 'form.id.label'}}
+ {{t
+ 'resources.auth-method.titles.primary'
+ }}
+ {{t 'titles.actions'}}
+
+
+
<:body as |B|>
-
-
- {{#if (can 'read auth-method' B.data)}}
-
- {{B.data.displayName}}
-
- {{else}}
- {{B.data.displayName}}
- {{/if}}
-
- {{B.data.description}}
-
-
-
-
-
-
-
-
-
- {{#if B.data.isPrimary}}
-
- {{/if}}
-
-
- {{#if (can 'makePrimary auth-method' B.data)}}
-
-
- {{#unless B.data.isPrimary}}
-
- {{t 'resources.auth-method.actions.make-primary'}}
-
- {{/unless}}
- {{#if B.data.isPrimary}}
-
- {{t 'resources.auth-method.actions.remove-as-primary'}}
-
- {{/if}}
-
- {{/if}}
-
-
+ {{#each @model.authMethods as |data|}}
+
+ {{! Name }}
+
+ {{#if (can 'read auth-method' data)}}
+
+ {{data.displayName}}
+
+ {{else}}
+ {{data.displayName}}
+ {{/if}}
+
+ {{data.description}}
+
+
+ {{! Type }}
+
+
+
+ {{! ID }}
+
+
+
+ {{! isPrimary }}
+
+ {{#if data.isPrimary}}
+
+ {{/if}}
+
+ {{! Actions }}
+
+ {{#if (can 'makePrimary auth-method' data)}}
+
+
+ {{#unless data.isPrimary}}
+
+ {{t 'resources.auth-method.actions.make-primary'}}
+
+ {{/unless}}
+ {{#if data.isPrimary}}
+
+ {{t
+ 'resources.auth-method.actions.remove-as-primary'
+ }}
+
+ {{/if}}
+
+ {{/if}}
+
+
+ {{/each}}
{
+ return this.server.create('auth-method', {
+ scope: instances.scopes.org,
+ type: TYPE_AUTH_METHOD_PASSWORD,
+ created_time: `${year}-01-01T00:00:00Z`,
+ name: `Auth-method ${year}`,
+ });
+ });
+
+ await visit(urls.authMethods);
+
+ 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(`Auth-method ${year}`);
+ });
+ });
+
+ test.each(
+ 'sorting',
+ {
+ 'on name': {
+ attribute: {
+ key: 'name',
+ values: ['Alpha', 'Beta', 'Delta', 'Gamma', 'Epsilon'],
+ },
+ expectedAscendingSort: ['Alpha', 'Beta', 'Delta', 'Epsilon', 'Gamma'],
+ column: 1,
+ },
+ 'on type': {
+ attribute: {
+ key: 'type',
+ values: ['Password', 'Oidc', 'Oidc', 'Password', 'Ldap'],
+ },
+ expectedAscendingSort: ['Ldap', 'Oidc', 'Oidc', 'Password', 'Password'],
+ column: 2,
+ },
+ 'on id': {
+ attribute: {
+ key: 'id',
+ values: ['am_1000', 'am_0001', 'am_0100', 'am_0010'],
+ },
+ expectedAscendingSort: ['am_0001', 'am_0010', 'am_0100', 'am_1000'],
+ column: 3,
+ },
+ },
+ async function (assert, input) {
+ this.server.schema.authMethods.all().destroy();
+ faker.helpers.shuffle(input.attribute.values).forEach((value) => {
+ this.server.create('auth-method', {
+ [input.attribute.key]: value,
+ scope: instances.scopes.org,
+ });
+ });
+
+ await visit(urls.authMethods);
+
+ // 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);
+ });
+ },
+ );
});