Improve Project Navigation in Sidebar for Admin UI (#2829)

* When clicking on project in list, go to targets page

* Move Sessions link to bottom of main list on Project scope sidebar

* Add backlink to Orgs

* Add backlink to Global

* Fix some tests

* test: 💍 fix a couple more tests

---------

Co-authored-by: Lisbet Alvarez <lisbet.alvarez@hashicorp.com>
Co-authored-by: Lisbet Alvarez <107949262+lisbet-alvarez@users.noreply.github.com>
This commit is contained in:
authored and GitHub committed 2025-06-09 16:48:59 -07:00
1 parent f738e71657
commit f255a470cd
6 files changed
+29 -30

No files matched your search

+2 -2
View File
@@ -36,9 +36,9 @@ export default class ScopesScopeIndexRoute extends Route {
return this.router.transitionTo('onboarding');
}
// If this a project scope, there are no further sub scopes, so show edit
// If this a project scope, there are no further sub scopes, so show targets
if (model.isProject) {
return this.router.transitionTo('scopes.scope.edit');
return this.router.transitionTo('scopes.scope.targets');
}
// For all other scope types (global and org), show sub scopes
+15 -16
View File
@@ -92,20 +92,19 @@
{{/if}}
{{#if @model.isOrg}}
<Nav.Title>{{t
'titles.scope-level'
scope=(t 'resources.org.title')
}}</Nav.Title>
{{#if this.session.data.authenticated.isGlobal}}
<Nav.Link
@icon='org'
@text={{t 'resources.org.title_plural'}}
<Nav.BackLink
@text={{t 'titles.back-link' scope=(t 'titles.global')}}
@route='scopes.scope.scopes'
@model='global'
/>
{{/if}}
<Nav.Title>{{t
'titles.scope-level'
scope=(t 'resources.org.title')
}}</Nav.Title>
<Nav.Link
@icon='grid'
@text={{t 'resources.project.title_plural'}}
@@ -135,14 +134,6 @@
<Nav.Title>{{t 'titles.project-actions'}}</Nav.Title>
{{#if (can 'navigate model' @model collection='sessions')}}
<Nav.Link
@icon='entry-point'
@text={{t 'resources.session.title_plural'}}
@route='scopes.scope.sessions'
/>
{{/if}}
{{#if (can 'navigate model' @model collection='targets')}}
<Nav.Link
@icon='target'
@@ -167,6 +158,14 @@
/>
{{/if}}
{{#if (can 'navigate model' @model collection='sessions')}}
<Nav.Link
@icon='entry-point'
@text={{t 'resources.session.title_plural'}}
@route='scopes.scope.sessions'
/>
{{/if}}
<Nav.Title>{{t
'titles.scope-iam'
scope=(t 'resources.project.title')
@@ -102,7 +102,7 @@ module('Acceptance | roles | org-scope', function (hooks) {
await click(commonSelectors.HREF(urls.roleScopes));
await click(commonSelectors.TABLE_RESOURCE_LINK(scopeUrl));
assert.strictEqual(currentURL(), `${scopeUrl}/edit`);
assert.strictEqual(currentURL(), `${scopeUrl}/targets`);
});
test('user can navigate to parent scope from role grant scopes', async function (assert) {
+6 -6
View File
@@ -47,8 +47,8 @@ module('Acceptance | scopes', function (hooks) {
projectScope: null,
newProjectScope: null,
project2Scope: null,
projectScopeEdit: null,
project2ScopeEdit: null,
projectTargets: null,
project2Targets: null,
};
hooks.beforeEach(async function () {
@@ -82,8 +82,8 @@ module('Acceptance | scopes', function (hooks) {
urls.newProjectScope = `${urls.orgScopes}/new`;
urls.projectScope = `/scopes/${instances.scopes.project.id}`;
urls.project2Scope = `/scopes/${instances.scopes.project2.id}`;
urls.projectScopeEdit = `${urls.projectScope}/edit`;
urls.project2ScopeEdit = `${urls.project2Scope}/edit`;
urls.projectTargets = `${urls.projectScope}/targets`;
urls.project2Targets = `${urls.project2Scope}/targets`;
// Generate resource counter
getScopeCount = (type) => this.server.schema.scopes.where({ type }).length;
await authenticateSession({ isGlobal: true, username: 'admin' });
@@ -135,12 +135,12 @@ module('Acceptance | scopes', function (hooks) {
await visit(urls.projectScope);
await a11yAudit();
assert.strictEqual(currentURL(), urls.projectScopeEdit);
assert.strictEqual(currentURL(), urls.projectTargets);
await click(SCOPES_DROPDOWN_BTN);
await click(SCOPES_DROPDOWN_SELECTOR(urls.project2Scope));
assert.strictEqual(currentURL(), urls.project2ScopeEdit);
assert.strictEqual(currentURL(), urls.project2Targets);
});
test('can create new org scopes', async function (assert) {
@@ -116,11 +116,10 @@ module('Acceptance | targets | read', function (hooks) {
test('cannot navigate to an ssh target form without proper authorization', async function (assert) {
featuresService.enable('ssh-target');
await visit(urls.projectScope);
instances.sshTarget.authorized_actions =
instances.sshTarget.authorized_actions.filter((item) => item !== 'read');
await click(commonSelectors.HREF(urls.targets));
await visit(urls.projectScope);
assert.dom(commonSelectors.TABLE_RESOURCE_LINK(urls.tcpTarget)).isVisible();
assert
@@ -130,11 +129,10 @@ module('Acceptance | targets | read', function (hooks) {
test('cannot navigate to a tcp target form without proper authorization', async function (assert) {
featuresService.enable('ssh-target');
await visit(urls.projectScope);
instances.tcpTarget.authorized_actions =
instances.tcpTarget.authorized_actions.filter((item) => item !== 'read');
await click(commonSelectors.HREF(urls.targets));
await visit(urls.projectScope);
assert.dom(commonSelectors.TABLE_RESOURCE_LINK(urls.sshTarget)).isVisible();
assert
@@ -37,6 +37,7 @@ module('Unit | Controller | scopes/scope/targets/index', function (hooks) {
};
const urls = {
orgScope: null,
projectScope: null,
targets: null,
target: null,
@@ -71,6 +72,7 @@ module('Unit | Controller | scopes/scope/targets/index', function (hooks) {
scope: instances.scopes.global,
});
urls.orgScope = `/scopes/${instances.scopes.org.id}/scopes`;
urls.projectScope = `/scopes/${instances.scopes.project.id}`;
urls.targets = `${urls.projectScope}/targets`;
urls.target = `${urls.targets}/${instances.target.id}`;
@@ -164,7 +166,7 @@ module('Unit | Controller | scopes/scope/targets/index', function (hooks) {
});
test('delete action destroys specified model', async function (assert) {
await visit(urls.projectScope);
await visit(urls.orgScope);
const target = await store.findRecord('target', instances.target.id);
const targetCount = getTargetCount();