refactor: 💡 remove route-action usage in admin ui (#2534)

✅ Closes: https://hashicorp.atlassian.net/browse/ICU-12945
This commit is contained in:
Lisbet Alvarez authored and GitHub committed 2024-10-28 09:23:08 -07:00
1 parent e842eb001d
commit 01a2d8e9a6
14 files changed
+261 -101

No files matched your search

-69
View File
@@ -1,69 +0,0 @@
/**
* Copyright (c) HashiCorp, Inc.
* SPDX-License-Identifier: BUSL-1.1
*/
import Helper from '@ember/component/helper';
import { inject as service } from '@ember/service';
import { join } from '@ember/runloop';
import { runInDebug, assert } from '@ember/debug';
import { A } from '@ember/array';
/**
* This helper is a modern update on ember-route-action-helper, which is
* now unmaintained.
*
* See https://github.com/DockYard/ember-route-action-helper
*/
export default class RouteActionHelper extends Helper {
// =services
@service router;
// =attributes
get routes() {
const { currentInfos, mapBy } = this.currentInfos;
return A(currentInfos).mapBy(mapBy).reverse();
}
get currentInfos() {
// eslint-disable-next-line ember/no-private-routing-service
const routerLib = this.router._router._routerMicrolib;
return {
currentInfos:
routerLib.currentRouteInfos || routerLib.currentHandlerInfos,
mapBy: (routerLib.currentRouteInfos && 'route') || 'handler',
};
}
// =methods
compute([actionName, ...outerArgs]) {
const { action, handler } = this.getRouteWithAction(actionName);
runInDebug(() => {
assert(
`
[boundary-core-helper-route-action]
Unable to find action ${actionName}
`,
handler,
);
});
return (...innerArgs) =>
join(handler, action, ...outerArgs.concat(innerArgs));
}
getRouteWithAction(actionName) {
let action;
const handler = A(this.routes).find((route) => {
const actions = route.actions || route._actions;
action = actions[actionName];
return typeof action === 'function';
});
return { action, handler };
}
}
-6
View File
@@ -1,6 +0,0 @@
/**
* Copyright (c) HashiCorp, Inc.
* SPDX-License-Identifier: BUSL-1.1
*/
export { default } from 'core/helpers/route-action';
-1
View File
@@ -18,7 +18,6 @@ module.exports = {
'is-loading',
],
},
'no-route-action': false,
},
overrides: [
{
@@ -57,4 +57,22 @@ export default class ScopesScopeGroupsGroupAddMembersController extends Controll
async cancel() {
await this.router.replaceWith('scopes.scope.groups.group.members');
}
/**
* Calls filterBy action located in the route.
* @param {string} field
* @param {[ScopeModel]} value
*/
@action
callFilterBy(field, value) {
this.send('filterBy', field, value);
}
/**
* Calls clearAllFilters action located in the route.
*/
@action
callClearAllFilters() {
this.send('clearAllFilters');
}
}
@@ -56,4 +56,22 @@ export default class ScopesScopeRolesRoleAddPrincipalsController extends Control
cancel() {
this.router.replaceWith('scopes.scope.roles.role.principals');
}
/**
* Calls filterBy action located in the route.
* @param {string} field
* @param {[ScopeModel]} value
*/
@action
callFilterBy(field, value) {
this.send('filterBy', field, value);
}
/**
* Calls clearAllFilters action located in the route.
*/
@action
callClearAllFilters() {
this.send('clearAllFilters');
}
}
@@ -39,6 +39,15 @@ export default class ScopesScopeWorkersIndexController extends Controller {
return `${tag.key} = ${tag.value}`;
}
/**
* Determine equality between two tags based on both key and value.
* @param {object} firstTag
* @param {object} secondTag
*/
isEqual(firstTag, secondTag) {
return firstTag.key === secondTag.key && firstTag.value === secondTag.value;
}
// =actions
/**
@@ -96,4 +105,30 @@ export default class ScopesScopeWorkersIndexController extends Controller {
await this.router.replaceWith('scopes.scope.workers');
await this.router.refresh();
}
/**
* Calls filterBy action located in the route.
* @param {string} field
* @param {[object]} value
*/
@action
callFilterBy(field, value) {
this.send('filterBy', field, value);
}
/**
* Calls clearAllFilters action located in the route.
*/
@action
callClearAllFilters() {
this.send('clearAllFilters');
}
/**
* Refreshes worker data.
*/
@action
refresh() {
this.router.refresh('scopes.scope.workers');
}
}
@@ -5,7 +5,6 @@
import Route from '@ember/routing/route';
import { inject as service } from '@ember/service';
import { action } from '@ember/object';
export default class ScopesScopeWorkersRoute extends Route {
// =services
@@ -35,12 +34,4 @@ export default class ScopesScopeWorkersRoute extends Route {
return this.store.query('worker', { scope_id });
}
}
/**
* Refreshes worker data.
*/
@action
refresh() {
return super.refresh(...arguments);
}
}
@@ -98,11 +98,6 @@ export default class ScopesScopeWorkersIndexRoute extends Route {
this.refresh();
}
@action
isEqual(firstTag, secondTag) {
return firstTag.key === secondTag.key && firstTag.value === secondTag.value;
}
setupController(controller) {
const scope = this.modelFor('scopes.scope');
super.setupController(...arguments);
@@ -43,7 +43,7 @@
@name={{filter.name}}
@items={{this.flatSortedScopes}}
@selectedItems={{filter.selectedValue}}
@onChange={{route-action 'filterBy' filter.name}}
@onChange={{fn this.callFilterBy filter.name}}
as |group|
>
<li
@@ -72,7 +72,7 @@
<Rose::Button
@style='inline-link-action'
@iconLeft='flight-icons/svg/x-16'
{{on 'click' (route-action 'clearAllFilters')}}
{{on 'click' this.callClearAllFilters}}
>{{t 'actions.clear-all-filters'}}
</Rose::Button>
{{/if}}
@@ -43,7 +43,7 @@
@name={{filter.name}}
@items={{this.flatSortedScopes}}
@selectedItems={{filter.selectedValue}}
@onChange={{route-action 'filterBy' filter.name}}
@onChange={{fn this.callFilterBy filter.name}}
as |group|
>
<li
@@ -72,7 +72,7 @@
<Rose::Button
@style='inline-link-action'
@iconLeft='flight-icons/svg/x-16'
{{on 'click' (route-action 'clearAllFilters')}}
{{on 'click' this.callClearAllFilters}}
>{{t 'actions.clear-all-filters'}}
</Rose::Button>
{{/if}}
@@ -55,8 +55,8 @@
@name={{key}}
@items={{tags}}
@selectedItems={{filter.selectedValue}}
@onChange={{route-action 'filterBy' filter.name}}
@itemEqualityFunc={{route-action 'isEqual'}}
@onChange={{fn this.callFilterBy filter.name}}
@itemEqualityFunc={{this.isEqual}}
as |group|
>
<dropdown.item class='indent-label-1'>
@@ -78,7 +78,7 @@
<Rose::Button
@style='inline-link-action'
@iconLeft='flight-icons/svg/x-16'
{{on 'click' (route-action 'clearAllFilters')}}
{{on 'click' this.callClearAllFilters}}
>{{t 'actions.clear-all-filters'}}
</Rose::Button>
{{/if}}
@@ -86,7 +86,7 @@
</toolbar.primary>
<toolbar.secondary>
<ToolbarRefresher @onClick={{route-action 'refresh'}} />
<ToolbarRefresher @onClick={{this.refresh}} />
</toolbar.secondary>
</Rose::Toolbar>
@@ -4,18 +4,111 @@
*/
import { module, test } from 'qunit';
import { setupTest } from 'admin/tests/helpers';
import { setupTest } from 'ember-qunit';
import { visit } from '@ember/test-helpers';
import setupMirage from 'ember-cli-mirage/test-support/setup-mirage';
import { authenticateSession } from 'ember-simple-auth/test-support';
module(
'Unit | Controller | scopes/scope/groups/group/add-members',
function (hooks) {
setupTest(hooks);
setupMirage(hooks);
test('it exists', function (assert) {
let controller = this.owner.lookup(
let store;
let controller;
const instances = {
scopes: {
global: null,
org: null,
},
group: null,
user: null,
};
const urls = {
globalScope: null,
addMembers: null,
};
hooks.beforeEach(function () {
authenticateSession({});
store = this.owner.lookup('service:store');
controller = this.owner.lookup(
'controller:scopes/scope/groups/group/add-members',
);
instances.scopes.global = this.server.create('scope', { id: 'global' });
instances.scopes.org = this.server.create('scope', {
type: 'org',
scope: { id: 'global', type: 'global' },
});
instances.group = this.server.create('group', {
scope: instances.scopes.global,
});
instances.user = this.server.create('user', {
scope: instances.scopes.global,
});
urls.globalScope = `/scopes/global`;
urls.addMembers = `${urls.globalScope}/groups/${instances.group.id}/add-members`;
});
test('it exists', function (assert) {
assert.ok(controller);
});
test('flatSortedScopes returns array of sorted scopes', async function (assert) {
const globalScope = await store.findRecord(
'scope',
instances.scopes.global.id,
);
const orgScope = await store.findRecord('scope', instances.scopes.org.id);
await visit(urls.addMembers);
assert.deepEqual(controller.flatSortedScopes, [globalScope, orgScope]);
});
test('addMembers action adds users to specified model', async function (assert) {
await visit(urls.addMembers);
const group = await store.findRecord('group', instances.group.id);
const user = await store.findRecord('user', instances.user.id);
assert.deepEqual(group.members, []);
await controller.addMembers(group, [instances.user.id]);
assert.deepEqual(group.members, [user]);
});
test('callFilterBy action adds expected property values to route', async function (assert) {
const route = this.owner.lookup(
'route:scopes/scope/groups/group/add-members',
);
await visit(urls.addMembers);
const scope = await store.findRecord('scope', instances.scopes.global.id);
assert.notOk(route.scope);
controller.callFilterBy('scope', [scope]);
assert.deepEqual(route.scope, [scope]);
});
test('callClearAllFilters action removes all filter values from route', async function (assert) {
const route = this.owner.lookup(
'route:scopes/scope/groups/group/add-members',
);
await visit(urls.addMembers);
const scope = await store.findRecord('scope', instances.scopes.global.id);
route.scope = [scope];
assert.deepEqual(route.scope, [scope]);
controller.callClearAllFilters();
assert.deepEqual(route.scope, []);
});
},
);
@@ -21,6 +21,8 @@ module(
const instances = {
scopes: {
global: null,
org: null,
project: null,
},
role: null,
user: null,
@@ -39,6 +41,14 @@ module(
);
instances.scopes.global = this.server.create('scope', { id: 'global' });
instances.scopes.org = this.server.create('scope', {
type: 'org',
scope: { id: 'global', type: 'global' },
});
instances.scopes.project = this.server.create('scope', {
type: 'project',
scope: { id: instances.scopes.org.id, type: 'org' },
});
instances.role = this.server.create('role', {
scopeId: 'global',
});
@@ -54,6 +64,25 @@ module(
assert.ok(controller);
});
test('flatSortedScopes returns array of sorted scopes', async function (assert) {
const globalScope = await store.findRecord(
'scope',
instances.scopes.global.id,
);
const orgScope = await store.findRecord('scope', instances.scopes.org.id);
const projectScope = await store.findRecord(
'scope',
instances.scopes.project.id,
);
await visit(urls.addPrincipals);
assert.deepEqual(controller.flatSortedScopes, [
globalScope,
orgScope,
projectScope,
]);
});
test('addPrincipals action adds principals to specified model', async function (assert) {
await visit(urls.addPrincipals);
const role = await store.findRecord('role', instances.role.id);
@@ -70,5 +99,34 @@ module(
},
]);
});
test('callFilterBy action adds expected property values to route', async function (assert) {
const route = this.owner.lookup(
'route:scopes/scope/roles/role/add-principals',
);
await visit(urls.addPrincipals);
const scope = await store.findRecord('scope', instances.scopes.global.id);
assert.notOk(route.scope);
controller.callFilterBy('scope', [scope]);
assert.deepEqual(route.scope, [scope]);
});
test('callClearAllFilters action removes all filter values from route', async function (assert) {
const route = this.owner.lookup(
'route:scopes/scope/roles/role/add-principals',
);
await visit(urls.addPrincipals);
const scope = await store.findRecord('scope', instances.scopes.global.id);
route.scope = [scope];
assert.deepEqual(route.scope, [scope]);
controller.callClearAllFilters();
assert.deepEqual(route.scope, []);
});
},
);
@@ -39,6 +39,7 @@ module('Unit | Controller | scopes/scope/workers/index', function (hooks) {
instances.scopes.global = this.server.create('scope', { id: 'global' });
instances.worker = this.server.create('worker', {
scope: instances.scopes.global,
config_tags: { type: ['dev'] },
});
urls.globalScope = `/scopes/global`;
@@ -81,4 +82,31 @@ module('Unit | Controller | scopes/scope/workers/index', function (hooks) {
assert.strictEqual(getWorkerCount(), workerCount - 1);
});
test('callFilterBy action adds expected property values to route', async function (assert) {
const route = this.owner.lookup('route:scopes/scope/workers/index');
await visit(urls.workers);
const tag = { key: 'type', value: 'dev', type: 'config' };
assert.notOk(route.tags);
controller.callFilterBy('tags', [tag]);
assert.deepEqual(route.tags, [tag]);
});
test('callClearAllFilters action removes all filter values from route', async function (assert) {
const route = this.owner.lookup('route:scopes/scope/workers/index');
await visit(urls.workers);
const tag = { key: 'type', value: 'dev', type: 'config' };
controller.callFilterBy('tags', [tag]);
assert.deepEqual(route.tags, [
{ key: 'type', value: 'dev', type: 'config' },
]);
controller.callClearAllFilters();
assert.deepEqual(route.tags, []);
});
});