diff --git a/addons/core/translations/en-us.yaml b/addons/core/translations/en-us.yaml
index 1850af1bf..861961573 100644
--- a/addons/core/translations/en-us.yaml
+++ b/addons/core/translations/en-us.yaml
@@ -18,9 +18,7 @@ titles:
home: Home
iam: IAM
new: New
- resources: Resources
details: Details
- general: General
overview: Overview
settings: Settings
empty-set: No Items Yet
@@ -46,6 +44,11 @@ titles:
days: '{days, plural, =1 {# day} other {# days}}'
workers: Workers
no-worker-filter: No worker filter added
+ scope-level: '{scope} Level'
+ scope-iam: '{scope} IAM'
+ project-actions: Project Actions
+ user-menu: User Menu
+ back-link: 'Back to {scope}'
descriptions:
empty-set: There are no items to display yet. You may be able to add items or try back later.
cluster-url-initialization: To get started, please enter your cluster URL
@@ -57,6 +60,9 @@ descriptions:
provider: This is the provider for this host catalog. The format of the host set filters are specific to each provider.
no-search-results: Sorry, we weren't able to find any {resource} for "{query}".
no-filter-results: Sorry, we weren’t able to find any {resource} within the filtered parameters.
+ and-more: ...and more
+ view-all-orgs: 'View all orgs ({total})'
+ view-all-projects: 'View all projects ({total})'
questions:
delete-confirm: Are you sure you want to delete this resource?
remove-confirm: Are you sure you want to remove this association?
diff --git a/addons/rose/addon/styles/hds/overrides.scss b/addons/rose/addon/styles/hds/overrides.scss
index 4d645d135..b6fb09825 100644
--- a/addons/rose/addon/styles/hds/overrides.scss
+++ b/addons/rose/addon/styles/hds/overrides.scss
@@ -53,3 +53,20 @@ form {
color: inherit;
}
}
+
+// TODO: This is a temporary fix that ensures changing the color theme won't alter the dropdown colors.
+.app-frame-sidebar-style-overrides .side-nav-style-overrides {
+ .hds-dropdown-toggle-button,
+ .hds-dropdown-toggle-icon {
+ background: var(--token-side-nav-color-surface-primary);
+
+ &:hover {
+ background: var(--token-side-nav-color-surface-interactive-hover);
+ }
+
+ &:active,
+ &:focus {
+ background: var(--token-side-nav-color-surface-primary);
+ }
+ }
+}
diff --git a/addons/rose/app/styles/rose/components/_frame.scss b/addons/rose/app/styles/rose/components/_frame.scss
index c4afa29e6..dc79aec59 100644
--- a/addons/rose/app/styles/rose/components/_frame.scss
+++ b/addons/rose/app/styles/rose/components/_frame.scss
@@ -7,7 +7,7 @@
@use '../utilities/type';
@use '../variables/media';
-$l: sizing.rems(l); // 16
+$l: sizing.rems(l); // 24
$m: sizing.rems(m); // 16
$s: sizing.rems(s); // 12
$xs: sizing.rems(xs); // 8
@@ -36,11 +36,22 @@ $xxxxs: sizing.rems(xxxxs); // 1
border-bottom: $xxxxs solid var(--header-border-color);
border-top-left-radius: $xxxs;
border-top-right-radius: $xxxs;
+ display: flex;
+ align-items: center;
+ column-gap: $xs;
+
+ h2 {
+ margin: $m 0;
+ }
}
.rose-frame-body {
$body-padding: $l;
padding: $body-padding;
+
+ p {
+ margin-bottom: $m;
+ }
}
}
diff --git a/addons/rose/package.json b/addons/rose/package.json
index 2a9e48e94..f850919bc 100644
--- a/addons/rose/package.json
+++ b/addons/rose/package.json
@@ -30,7 +30,7 @@
},
"dependencies": {
"@embroider/test-setup": "^2.1.1",
- "@hashicorp/design-system-components": "^4.13.0",
+ "@hashicorp/design-system-components": "^4.18.1",
"codemirror": "5.65.7",
"ember-auto-import": "^2.10.0",
"ember-cli-babel": "^8.2.0",
diff --git a/e2e-tests/admin/pages/aliases.js b/e2e-tests/admin/pages/aliases.js
index e384a9382..c9012016c 100644
--- a/e2e-tests/admin/pages/aliases.js
+++ b/e2e-tests/admin/pages/aliases.js
@@ -15,10 +15,13 @@ export class AliasesPage extends BaseResourcePage {
* @param {string} targetId ID of the target
* @returns Name of the alias
*/
- async createAliasForTarget(alias, targetId) {
+ async createAliasForTarget(alias, targetId, orgName) {
const aliasName = 'Alias ' + nanoid();
- await this.page.getByRole('link', { name: 'Orgs', exact: true }).click();
+ await this.page
+ .getByRole('link', { name: `Back to ${orgName}`, exact: true })
+ .click();
+ await this.page.getByRole('link', { name: 'Orgs' }).click();
await this.page.getByRole('link', { name: 'Aliases' }).click();
await expect(
this.page
diff --git a/e2e-tests/admin/pages/auth-methods.js b/e2e-tests/admin/pages/auth-methods.js
index b1d40c71d..7371af69b 100644
--- a/e2e-tests/admin/pages/auth-methods.js
+++ b/e2e-tests/admin/pages/auth-methods.js
@@ -16,7 +16,7 @@ export class AuthMethodsPage extends BaseResourcePage {
async createPasswordAuthMethod() {
const authMethodName = 'Auth Method ' + nanoid();
await this.page
- .getByRole('navigation', { name: 'IAM' })
+ .getByRole('navigation', { name: 'Application local navigation' })
.getByRole('link', { name: 'Auth Methods' })
.click();
await this.page.getByRole('button', { name: 'New' }).click();
@@ -43,7 +43,7 @@ export class AuthMethodsPage extends BaseResourcePage {
async createOidcAuthMethod(issuer, clientId, clientSecret, boundaryAddr) {
const authMethodName = 'Auth Method ' + nanoid();
await this.page
- .getByRole('navigation', { name: 'IAM' })
+ .getByRole('navigation', { name: 'Application local navigation' })
.getByRole('link', { name: 'Auth Methods' })
.click();
await this.page.getByRole('button', { name: 'New' }).click();
@@ -130,7 +130,7 @@ export class AuthMethodsPage extends BaseResourcePage {
*/
async makeAuthMethodPrimary() {
await this.page
- .getByRole('navigation', { name: 'IAM' })
+ .getByRole('navigation', { name: 'Application local navigation' })
.getByRole('link', { name: 'Auth Methods' })
.click();
await this.page.getByLabel('Manage').click();
diff --git a/e2e-tests/admin/pages/credential-stores.js b/e2e-tests/admin/pages/credential-stores.js
index 0eb6b8d6e..e99f6f9da 100644
--- a/e2e-tests/admin/pages/credential-stores.js
+++ b/e2e-tests/admin/pages/credential-stores.js
@@ -17,7 +17,7 @@ export class CredentialStoresPage extends BaseResourcePage {
async createStaticCredentialStore() {
const credentialStoreName = 'Credential Store ' + nanoid();
await this.page
- .getByRole('navigation', { name: 'Resources' })
+ .getByRole('navigation', { name: 'Application local navigation' })
.getByRole('link', { name: 'Credential Stores' })
.click();
await this.page.getByRole('link', { name: 'New', exact: true }).click();
@@ -47,7 +47,7 @@ export class CredentialStoresPage extends BaseResourcePage {
async createVaultCredentialStore(vaultAddr, clientToken) {
const credentialStoreName = 'Credential Store ' + nanoid();
await this.page
- .getByRole('navigation', { name: 'Resources' })
+ .getByRole('navigation', { name: 'Application local navigation' })
.getByRole('link', { name: 'Credential Stores' })
.click();
await this.page.getByRole('link', { name: 'New', exact: true }).click();
@@ -84,7 +84,7 @@ export class CredentialStoresPage extends BaseResourcePage {
) {
const credentialStoreName = 'Credential Store ' + nanoid();
await this.page
- .getByRole('navigation', { name: 'Resources' })
+ .getByRole('navigation', { name: 'Application local navigation' })
.getByRole('link', { name: 'Credential Stores' })
.click();
await this.page.getByRole('link', { name: 'New', exact: true }).click();
diff --git a/e2e-tests/admin/pages/groups.js b/e2e-tests/admin/pages/groups.js
index 0d6fde530..b15133a61 100644
--- a/e2e-tests/admin/pages/groups.js
+++ b/e2e-tests/admin/pages/groups.js
@@ -16,7 +16,7 @@ export class GroupsPage extends BaseResourcePage {
async createGroup() {
const groupName = 'Group ' + nanoid();
await this.page
- .getByRole('navigation', { name: 'IAM' })
+ .getByRole('navigation', { name: 'Application local navigation' })
.getByRole('link', { name: 'Groups' })
.click();
await this.page.getByRole('link', { name: 'New', exact: true }).click();
diff --git a/e2e-tests/admin/pages/host-catalogs.js b/e2e-tests/admin/pages/host-catalogs.js
index f2a6af1f4..805b984c8 100644
--- a/e2e-tests/admin/pages/host-catalogs.js
+++ b/e2e-tests/admin/pages/host-catalogs.js
@@ -16,7 +16,7 @@ export class HostCatalogsPage extends BaseResourcePage {
async createHostCatalog() {
const hostCatalogName = 'Host Catalog ' + nanoid();
await this.page
- .getByRole('navigation', { name: 'Resources' })
+ .getByRole('navigation', { name: 'Application local navigation' })
.getByRole('link', { name: 'Host Catalogs' })
.click();
await expect(
diff --git a/e2e-tests/admin/pages/login.js b/e2e-tests/admin/pages/login.js
index b6228ce64..618b5d578 100644
--- a/e2e-tests/admin/pages/login.js
+++ b/e2e-tests/admin/pages/login.js
@@ -18,7 +18,10 @@ export class LoginPage extends BaseResourcePage {
await this.page.getByLabel('Password', { exact: true }).fill(password);
await this.page.getByRole('button', { name: 'Sign In' }).click();
await expect(
- this.page.getByRole('navigation', { name: 'General' }),
+ this.page.getByRole('navigation', {
+ // TODO: Uncomment line below once both UIs have been refactored to use HDS side nav.
+ // name: 'Application local navigation',
+ }),
).toBeVisible();
await expect(this.page.getByText(loginName)).toBeEnabled();
}
diff --git a/e2e-tests/admin/pages/orgs.js b/e2e-tests/admin/pages/orgs.js
index 0694f6b53..58776b109 100644
--- a/e2e-tests/admin/pages/orgs.js
+++ b/e2e-tests/admin/pages/orgs.js
@@ -16,7 +16,7 @@ export class OrgsPage extends BaseResourcePage {
async createOrg() {
const orgName = 'Org ' + nanoid();
await this.page
- .getByRole('navigation', { name: 'General' })
+ .getByRole('navigation', { name: 'Application local navigation' })
.getByRole('link', { name: 'Orgs' })
.click();
await this.page.getByRole('link', { name: 'New Org' }).click();
diff --git a/e2e-tests/admin/pages/projects.js b/e2e-tests/admin/pages/projects.js
index 05c9b3d05..d689678c0 100644
--- a/e2e-tests/admin/pages/projects.js
+++ b/e2e-tests/admin/pages/projects.js
@@ -16,7 +16,7 @@ export class ProjectsPage extends BaseResourcePage {
async createProject() {
const projectName = 'Project ' + nanoid();
await this.page
- .getByRole('navigation', { name: 'General' })
+ .getByRole('navigation', { name: 'Application local navigation' })
.getByRole('link', { name: 'Projects' })
.click();
await this.page.getByRole('link', { name: 'New', exact: true }).click();
diff --git a/e2e-tests/admin/pages/roles.js b/e2e-tests/admin/pages/roles.js
index f9937a2bd..ef4a3e7f4 100644
--- a/e2e-tests/admin/pages/roles.js
+++ b/e2e-tests/admin/pages/roles.js
@@ -16,7 +16,7 @@ export class RolesPage extends BaseResourcePage {
const roleName = 'Role ' + nanoid();
await this.page
- .getByRole('navigation', { name: 'IAM' })
+ .getByRole('navigation', { name: 'Application local navigation' })
.getByRole('link', { name: 'Roles' })
.click();
await this.page.getByRole('link', { name: 'New Role' }).click();
diff --git a/e2e-tests/admin/pages/sessions.js b/e2e-tests/admin/pages/sessions.js
index a4158536f..230dd7cbf 100644
--- a/e2e-tests/admin/pages/sessions.js
+++ b/e2e-tests/admin/pages/sessions.js
@@ -14,7 +14,7 @@ export class SessionsPage extends BasePage {
*/
async waitForSessionToBeVisible(targetName) {
await this.page
- .getByRole('navigation', { name: 'Resources' })
+ .getByRole('navigation', { name: 'Application local navigation' })
.getByRole('link', { name: 'Sessions' })
.click();
let i = 0;
diff --git a/e2e-tests/admin/pages/targets.js b/e2e-tests/admin/pages/targets.js
index 7d79e82c7..f05a5db76 100644
--- a/e2e-tests/admin/pages/targets.js
+++ b/e2e-tests/admin/pages/targets.js
@@ -17,7 +17,7 @@ export class TargetsPage extends BaseResourcePage {
async createTarget(port) {
const targetName = 'Target ' + nanoid();
await this.page
- .getByRole('navigation', { name: 'Resources' })
+ .getByRole('navigation', { name: 'Application local navigation' })
.getByRole('link', { name: 'Targets' })
.click();
await this.page.getByRole('link', { name: 'New', exact: true }).click();
@@ -44,7 +44,7 @@ export class TargetsPage extends BaseResourcePage {
async createTargetWithAddress(address, port) {
const targetName = 'Target ' + nanoid();
await this.page
- .getByRole('navigation', { name: 'Resources' })
+ .getByRole('navigation', { name: 'Application local navigation' })
.getByRole('link', { name: 'Targets' })
.click();
await this.page.getByRole('link', { name: 'New', exact: true }).click();
@@ -73,7 +73,7 @@ export class TargetsPage extends BaseResourcePage {
async createTargetWithAddressAndAlias(address, port, alias) {
const targetName = 'Target ' + nanoid();
await this.page
- .getByRole('navigation', { name: 'Resources' })
+ .getByRole('navigation', { name: 'Application local navigation' })
.getByRole('link', { name: 'Targets' })
.click();
await this.page.getByRole('link', { name: 'New', exact: true }).click();
@@ -109,7 +109,7 @@ export class TargetsPage extends BaseResourcePage {
async createTcpTargetWithAddressEnt(address, port) {
const targetName = 'Target ' + nanoid();
await this.page
- .getByRole('navigation', { name: 'Resources' })
+ .getByRole('navigation', { name: 'Application local navigation' })
.getByRole('link', { name: 'Targets' })
.click();
await this.page.getByRole('link', { name: 'New', exact: true }).click();
@@ -140,7 +140,7 @@ export class TargetsPage extends BaseResourcePage {
async createSshTargetEnt(port) {
const targetName = 'Target ' + nanoid();
await this.page
- .getByRole('navigation', { name: 'Resources' })
+ .getByRole('navigation', { name: 'Application local navigation' })
.getByRole('link', { name: 'Targets' })
.click();
await this.page.getByRole('link', { name: 'New', exact: true }).click();
@@ -172,7 +172,7 @@ export class TargetsPage extends BaseResourcePage {
async createSshTargetWithAddressEnt(address, port) {
const targetName = 'Target ' + nanoid();
await this.page
- .getByRole('navigation', { name: 'Resources' })
+ .getByRole('navigation', { name: 'Application local navigation' })
.getByRole('link', { name: 'Targets' })
.click();
await this.page.getByRole('link', { name: 'New', exact: true }).click();
@@ -206,7 +206,7 @@ export class TargetsPage extends BaseResourcePage {
async createSshTargetWithAddressAndAlias(address, port, alias) {
const targetName = 'Target ' + nanoid();
await this.page
- .getByRole('navigation', { name: 'Resources' })
+ .getByRole('navigation', { name: 'Application local navigation' })
.getByRole('link', { name: 'Targets' })
.click();
await this.page.getByRole('link', { name: 'New', exact: true }).click();
@@ -349,7 +349,7 @@ export class TargetsPage extends BaseResourcePage {
*/
async addBrokeredCredentialsToTarget(targetName, credentialName) {
await this.page
- .getByRole('navigation', { name: 'Resources' })
+ .getByRole('navigation', { name: 'Application local navigation' })
.getByRole('link', { name: 'Targets' })
.click();
await expect(
@@ -397,7 +397,7 @@ export class TargetsPage extends BaseResourcePage {
*/
async addInjectedCredentialsToTarget(targetName, credentialName) {
await this.page
- .getByRole('navigation', { name: 'Resources' })
+ .getByRole('navigation', { name: 'Application local navigation' })
.getByRole('link', { name: 'Targets' })
.click();
await expect(
diff --git a/e2e-tests/admin/pages/users.js b/e2e-tests/admin/pages/users.js
index 60ee8406b..c3d639a00 100644
--- a/e2e-tests/admin/pages/users.js
+++ b/e2e-tests/admin/pages/users.js
@@ -16,7 +16,7 @@ export class UsersPage extends BaseResourcePage {
async createUser() {
const userName = 'User ' + nanoid();
await this.page
- .getByRole('navigation', { name: 'IAM' })
+ .getByRole('navigation', { name: 'Application local navigation' })
.getByRole('link', { name: 'Users' })
.click();
await this.page.getByRole('link', { name: 'New', exact: true }).click();
diff --git a/e2e-tests/admin/tests/alias-ent.spec.js b/e2e-tests/admin/tests/alias-ent.spec.js
index 08ecd3f1c..20f7d4384 100644
--- a/e2e-tests/admin/tests/alias-ent.spec.js
+++ b/e2e-tests/admin/tests/alias-ent.spec.js
@@ -92,7 +92,7 @@ test.describe('Aliases (Enterprise)', () => {
// Clear destination from alias
await page
- .getByRole('navigation', { name: 'Resources' })
+ .getByRole('navigation', { name: 'Application local navigation' })
.getByRole('link', { name: 'Targets' })
.click();
await page.getByRole('link', { name: targetName }).click();
@@ -270,10 +270,10 @@ test.describe('Aliases (Enterprise)', () => {
alias = 'example.alias.' + nanoid();
const aliasesPage = new AliasesPage(page);
- await aliasesPage.createAliasForTarget(alias, targetId);
+ await aliasesPage.createAliasForTarget(alias, targetId, orgName);
connect = await boundaryCli.connectSshToAlias(alias);
await page
- .getByRole('navigation', { name: 'General' })
+ .getByRole('navigation', { name: 'Application local navigation' })
.getByRole('link', { name: 'Orgs' })
.click();
await page.getByRole('link', { name: orgName }).click();
diff --git a/e2e-tests/admin/tests/alias.spec.js b/e2e-tests/admin/tests/alias.spec.js
index 7bfd759e9..431ccb972 100644
--- a/e2e-tests/admin/tests/alias.spec.js
+++ b/e2e-tests/admin/tests/alias.spec.js
@@ -75,7 +75,7 @@ test.describe('Aliases', () => {
// Clear destination from alias
await page
- .getByRole('navigation', { name: 'Resources' })
+ .getByRole('navigation', { name: 'Application local navigation' })
.getByRole('link', { name: 'Targets' })
.click();
await page.getByRole('link', { name: targetName }).click();
@@ -230,7 +230,7 @@ test.describe('Aliases', () => {
alias = 'example.alias.' + nanoid();
const aliasesPage = new AliasesPage(page);
- await aliasesPage.createAliasForTarget(alias, targetId);
+ await aliasesPage.createAliasForTarget(alias, targetId, orgName);
await page.getByRole('link', { name: 'Orgs', exact: true }).click();
await expect(page.getByRole('heading', { name: 'Orgs' })).toBeVisible();
await page.getByRole('link', { name: orgName }).click();
diff --git a/e2e-tests/admin/tests/auth-method-ldap.spec.js b/e2e-tests/admin/tests/auth-method-ldap.spec.js
index 1e535cf8f..abd8fbb2f 100644
--- a/e2e-tests/admin/tests/auth-method-ldap.spec.js
+++ b/e2e-tests/admin/tests/auth-method-ldap.spec.js
@@ -52,7 +52,7 @@ test(
const orgsPage = new OrgsPage(page);
orgName = await orgsPage.createOrg();
await page
- .getByRole('navigation', { name: 'IAM' })
+ .getByRole('navigation', { name: 'Application local navigation' })
.getByRole('link', { name: 'Auth Methods' })
.click();
await page.getByRole('button', { name: 'New' }).click();
@@ -191,7 +191,7 @@ test(
// View the LDAP account and verify account attributes
await page.getByRole('link', { name: orgName }).click();
await page
- .getByRole('navigation', { name: 'IAM' })
+ .getByRole('navigation', { name: 'Application local navigation' })
.getByRole('link', { name: 'Auth Methods' })
.click();
await page.getByRole('link', { name: ldapAuthMethodName }).click();
@@ -280,7 +280,7 @@ test(
// View the User account and verify attributes
await page
- .getByRole('navigation', { name: 'IAM' })
+ .getByRole('navigation', { name: 'Application local navigation' })
.getByRole('link', { name: 'Users' })
.click();
await page.getByRole('link', { name: userName }).click();
diff --git a/e2e-tests/admin/tests/auth-method-oidc-vault.spec.js b/e2e-tests/admin/tests/auth-method-oidc-vault.spec.js
index 9741cb49a..f441121df 100644
--- a/e2e-tests/admin/tests/auth-method-oidc-vault.spec.js
+++ b/e2e-tests/admin/tests/auth-method-oidc-vault.spec.js
@@ -32,7 +32,6 @@ test(
async ({
page,
context,
- baseURL,
controllerAddr,
adminAuthMethodId,
adminLoginName,
@@ -52,7 +51,7 @@ test(
userName,
password,
email,
- baseURL,
+ controllerAddr,
);
policyName = authPolicyName;
@@ -71,7 +70,7 @@ test(
issuer,
clientId,
clientSecret,
- baseURL,
+ controllerAddr,
);
// Change OIDC Auth Method state to active-public
@@ -134,9 +133,7 @@ test(
).toBeVisible();
// Log back in as an admin
- // WORKAROUND: Currently, users logging using OIDC don't have a username
- // displayed in the UI, so there's no simple locator to access this menu.
- await page.locator('details').filter({ hasText: 'Sign Out' }).click();
+ await page.getByRole('button', { name: 'User Menu' }).click();
await page.getByRole('button', { name: 'Sign Out' }).click();
await expect(page.getByRole('button', { name: 'Sign In' })).toBeVisible();
await loginPage.login(adminLoginName, adminPassword);
@@ -152,7 +149,7 @@ test(
.getByText(orgName),
).toBeVisible();
await page
- .getByRole('navigation', { name: 'IAM' })
+ .getByRole('navigation', { name: 'Application local navigation' })
.getByRole('link', { name: 'Auth Methods' })
.click();
await page.getByRole('link', { name: oidcAuthMethodName }).click();
@@ -241,7 +238,7 @@ test(
// View the User account and verify attributes
await page
- .getByRole('navigation', { name: 'IAM' })
+ .getByRole('navigation', { name: 'Application local navigation' })
.getByRole('link', { name: 'Users' })
.click();
await page
diff --git a/e2e-tests/admin/tests/auth-method-password.spec.js b/e2e-tests/admin/tests/auth-method-password.spec.js
index 708684eb9..b7ad3e6e6 100644
--- a/e2e-tests/admin/tests/auth-method-password.spec.js
+++ b/e2e-tests/admin/tests/auth-method-password.spec.js
@@ -75,7 +75,7 @@ test(
// Set a new password on the account
await page
- .getByRole('navigation', { name: 'General' })
+ .getByRole('navigation', { name: 'Application local navigation' })
.getByRole('link', { name: 'Orgs' })
.click();
await page.getByRole('link', { name: orgName }).click();
@@ -85,7 +85,7 @@ test(
.getByText(orgName),
).toBeVisible();
await page
- .getByRole('navigation', { name: 'IAM' })
+ .getByRole('navigation', { name: 'Application local navigation' })
.getByRole('link', { name: 'Auth Methods' })
.click();
await page.getByRole('link', { name: authMethodName }).click();
diff --git a/e2e-tests/admin/tests/dynamic-host-catalog-aws-ent.spec.js b/e2e-tests/admin/tests/dynamic-host-catalog-aws-ent.spec.js
index 116569a9c..b3b7658a4 100644
--- a/e2e-tests/admin/tests/dynamic-host-catalog-aws-ent.spec.js
+++ b/e2e-tests/admin/tests/dynamic-host-catalog-aws-ent.spec.js
@@ -49,7 +49,7 @@ test.describe('AWS', () => {
// Create host catalog
const hostCatalogName = 'Host Catalog ' + nanoid();
await page
- .getByRole('navigation', { name: 'Resources' })
+ .getByRole('navigation', { name: 'Application local navigation' })
.getByRole('link', { name: 'Host Catalogs' })
.click();
await page.getByRole('link', { name: 'New', exact: true }).click();
@@ -164,7 +164,7 @@ test.describe('AWS', () => {
await hostCatalogsPage.createHostCatalog();
const newHostSetName = await hostCatalogsPage.createHostSet();
await page
- .getByRole('navigation', { name: 'Resources' })
+ .getByRole('navigation', { name: 'Application local navigation' })
.getByRole('link', { name: 'Targets' })
.click();
await page.getByRole('link', { name: targetName }).click();
diff --git a/e2e-tests/admin/tests/dynamic-host-catalog-aws.spec.js b/e2e-tests/admin/tests/dynamic-host-catalog-aws.spec.js
index 05cb97bb3..1a4b1d525 100644
--- a/e2e-tests/admin/tests/dynamic-host-catalog-aws.spec.js
+++ b/e2e-tests/admin/tests/dynamic-host-catalog-aws.spec.js
@@ -49,7 +49,7 @@ test.describe('AWS', () => {
// Create host catalog
const hostCatalogName = 'Host Catalog ' + nanoid();
await page
- .getByRole('navigation', { name: 'Resources' })
+ .getByRole('navigation', { name: 'Application local navigation' })
.getByRole('link', { name: 'Host Catalogs' })
.click();
await page.getByRole('link', { name: 'New', exact: true }).click();
@@ -164,7 +164,7 @@ test.describe('AWS', () => {
await hostCatalogsPage.createHostCatalog();
const newHostSetName = await hostCatalogsPage.createHostSet();
await page
- .getByRole('navigation', { name: 'Resources' })
+ .getByRole('navigation', { name: 'Application local navigation' })
.getByRole('link', { name: 'Targets' })
.click();
await page.getByRole('link', { name: targetName }).click();
diff --git a/e2e-tests/admin/tests/global-settings.spec.js b/e2e-tests/admin/tests/global-settings.spec.js
index 1d6f16e3e..2c257ad1c 100644
--- a/e2e-tests/admin/tests/global-settings.spec.js
+++ b/e2e-tests/admin/tests/global-settings.spec.js
@@ -42,7 +42,7 @@ test(
// Navigate to orgs page when done
await page
- .getByRole('navigation', { name: 'General' })
+ .getByRole('navigation', { name: 'Application local navigation' })
.getByRole('link', { name: 'Orgs' })
.click();
await expect(page.getByRole('heading', { name: 'Orgs' })).toBeVisible();
diff --git a/e2e-tests/admin/tests/pagination.spec.js b/e2e-tests/admin/tests/pagination.spec.js
index ab4d4cdbb..970a996d1 100644
--- a/e2e-tests/admin/tests/pagination.spec.js
+++ b/e2e-tests/admin/tests/pagination.spec.js
@@ -34,7 +34,7 @@ test(
await page.getByRole('link', { name: org.name }).click();
await page.getByRole('link', { name: project.name }).click();
await page
- .getByRole('navigation', { name: 'Resources' })
+ .getByRole('navigation', { name: 'Application local navigation' })
.getByRole('link', { name: 'Targets' })
.click();
await expect(
diff --git a/e2e-tests/admin/tests/session-recording-aws-ent.spec.js b/e2e-tests/admin/tests/session-recording-aws-ent.spec.js
index f0bb6470a..5316e7737 100644
--- a/e2e-tests/admin/tests/session-recording-aws-ent.spec.js
+++ b/e2e-tests/admin/tests/session-recording-aws-ent.spec.js
@@ -62,6 +62,9 @@ test(
const projectName = await projectsPage.createProject();
// Create storage bucket
+ await page
+ .getByRole('link', { name: `Back to ${orgName}`, exact: true })
+ .click();
await page.getByRole('link', { name: 'Orgs', exact: true }).click();
const storageBucketsPage = new StorageBucketsPage(page);
const storageBucketName = await storageBucketsPage.createStorageBucketAws(
@@ -107,6 +110,9 @@ test(
await targetsPage.enableSessionRecording(storageBucketName);
// Create storage policy in org scope: keep session recordings forever
+ await page
+ .getByRole('link', { name: `Back to ${orgName}`, exact: true })
+ .click();
await page.getByRole('link', { name: 'Orgs', exact: true }).click();
await expect(page.getByRole('heading', { name: 'Orgs' })).toBeVisible();
await page.getByRole('link', { name: orgName }).click();
@@ -146,9 +152,12 @@ test(
await boundaryCli.waitForSessionRecording(storageBucket.id);
// Play back session recording
+ await page
+ .getByRole('link', { name: `Back to ${orgName}`, exact: true })
+ .click();
await page.getByRole('link', { name: 'Orgs', exact: true }).click();
await page
- .getByRole('navigation', { name: 'General' })
+ .getByRole('navigation', { name: 'Application local navigation' })
.getByRole('link', { name: 'Session Recordings', exact: true })
.click();
await page
diff --git a/e2e-tests/admin/tests/session-recording-minio-ent.spec.js b/e2e-tests/admin/tests/session-recording-minio-ent.spec.js
index 92c715549..f4de834c3 100644
--- a/e2e-tests/admin/tests/session-recording-minio-ent.spec.js
+++ b/e2e-tests/admin/tests/session-recording-minio-ent.spec.js
@@ -115,6 +115,9 @@ test(
await targetsPage.enableSessionRecording(storageBucketName);
// Create storage policy in org scope: keep session recordings forever
+ await page
+ .getByRole('link', { name: `Back to ${orgName}`, exact: true })
+ .click();
await page.getByRole('link', { name: 'Orgs', exact: true }).click();
await expect(page.getByRole('heading', { name: 'Orgs' })).toBeVisible();
await page.getByRole('link', { name: orgName }).click();
@@ -154,9 +157,12 @@ test(
await boundaryCli.waitForSessionRecording(storageBucket.id);
// Play back session recording
+ await page
+ .getByRole('link', { name: `Back to ${orgName}`, exact: true })
+ .click();
await page.getByRole('link', { name: 'Orgs', exact: true }).click();
await page
- .getByRole('navigation', { name: 'General' })
+ .getByRole('navigation', { name: 'Application local navigation' })
.getByRole('link', { name: 'Session Recordings', exact: true })
.click();
await page
diff --git a/e2e-tests/admin/tests/target-ent.spec.js b/e2e-tests/admin/tests/target-ent.spec.js
index a24152aed..7e2425307 100644
--- a/e2e-tests/admin/tests/target-ent.spec.js
+++ b/e2e-tests/admin/tests/target-ent.spec.js
@@ -190,7 +190,7 @@ test(
// Create another host set
await page
- .getByRole('navigation', { name: 'Resources' })
+ .getByRole('navigation', { name: 'Application local navigation' })
.getByRole('link', { name: 'Host Catalogs' })
.click();
await page.getByRole('link', { name: hostCatalogName }).click();
diff --git a/e2e-tests/admin/tests/target.spec.js b/e2e-tests/admin/tests/target.spec.js
index 527da097a..9b5b45d2b 100644
--- a/e2e-tests/admin/tests/target.spec.js
+++ b/e2e-tests/admin/tests/target.spec.js
@@ -49,7 +49,7 @@ test(
// Create another host set
await page
- .getByRole('navigation', { name: 'Resources' })
+ .getByRole('navigation', { name: 'Application local navigation' })
.getByRole('link', { name: 'Host Catalogs' })
.click();
await page.getByRole('link', { name: hostCatalogName }).click();
diff --git a/e2e-tests/admin/tests/worker-ent.spec.js b/e2e-tests/admin/tests/worker-ent.spec.js
index a1d75f185..b26ab5571 100644
--- a/e2e-tests/admin/tests/worker-ent.spec.js
+++ b/e2e-tests/admin/tests/worker-ent.spec.js
@@ -14,7 +14,7 @@ test(
await page.goto('/');
await page
- .getByRole('navigation', { name: 'General' })
+ .getByRole('navigation', { name: 'Application local navigation' })
.getByRole('link', { name: 'Workers' })
.click();
await page.getByRole('link', { name: 'New', exact: true }).click();
diff --git a/e2e-tests/admin/tests/worker-tags.spec.js b/e2e-tests/admin/tests/worker-tags.spec.js
index 32687a545..6fc032a45 100644
--- a/e2e-tests/admin/tests/worker-tags.spec.js
+++ b/e2e-tests/admin/tests/worker-tags.spec.js
@@ -17,7 +17,7 @@ test(
await page.goto('/');
await page
- .getByRole('navigation', { name: 'General' })
+ .getByRole('navigation', { name: 'Application local navigation' })
.getByRole('link', { name: 'Workers' })
.click();
await expect(
@@ -102,7 +102,7 @@ test(
// Check tag in worker dialog
await page
- .getByRole('navigation', { name: 'General' })
+ .getByRole('navigation', { name: 'Application local navigation' })
.getByRole('link', { name: 'Workers' })
.click();
await expect(
diff --git a/e2e-tests/admin/tests/worker.spec.js b/e2e-tests/admin/tests/worker.spec.js
index a45985996..30fe2b251 100644
--- a/e2e-tests/admin/tests/worker.spec.js
+++ b/e2e-tests/admin/tests/worker.spec.js
@@ -14,7 +14,7 @@ test(
await page.goto('/');
await page
- .getByRole('navigation', { name: 'General' })
+ .getByRole('navigation', { name: 'Application local navigation' })
.getByRole('link', { name: 'Workers' })
.click();
await page.getByRole('link', { name: 'New', exact: true }).click();
diff --git a/ui/admin/app/components/roles/role/actions/index.hbs b/ui/admin/app/components/roles/role/actions/index.hbs
index b9ac239b8..4be1034a3 100644
--- a/ui/admin/app/components/roles/role/actions/index.hbs
+++ b/ui/admin/app/components/roles/role/actions/index.hbs
@@ -8,7 +8,7 @@
{{#if (can 'addPrincipals role' @model)}}
{{t 'resources.role.principal.actions.add-principals'}}
diff --git a/ui/admin/app/components/scope-picker/index.hbs b/ui/admin/app/components/scope-picker/index.hbs
new file mode 100644
index 000000000..a3a504808
--- /dev/null
+++ b/ui/admin/app/components/scope-picker/index.hbs
@@ -0,0 +1,99 @@
+{{!
+ Copyright (c) HashiCorp, Inc.
+ SPDX-License-Identifier: BUSL-1.1
+}}
+
+
+ {{#let this.currentScope as |scope|}}
+
+ {{/let}}
+
+
+ {{t 'titles.global'}}
+
+
+ {{#if this.scope.orgsList}}
+
+
+
+ {{/if}}
+
+ {{#each this.truncatedOrgsList as |org|}}
+
+ {{org.displayName}}
+
+ {{/each}}
+
+ {{#if (gt this.scope.orgsList.length 5)}}
+
+
+ {{t
+ 'descriptions.view-all-orgs'
+ total=this.scope.orgsList.length
+ }}
+ {{/if}}
+
+ {{! All project scopes in org are only loaded when current scope is of project type. }}
+ {{#if this.scope.project}}
+
+
+ {{#each this.truncatedProjectsList as |project|}}
+
+ {{project.displayName}}
+
+ {{/each}}
+
+ {{#if (gt this.scope.projectsList.length 5)}}
+
+
+ {{t
+ 'descriptions.view-all-projects'
+ total=this.scope.projectsList.length
+ }}
+ {{/if}}
+ {{/if}}
+
\ No newline at end of file
diff --git a/ui/admin/app/components/scope-picker/index.js b/ui/admin/app/components/scope-picker/index.js
new file mode 100644
index 000000000..ad62181cc
--- /dev/null
+++ b/ui/admin/app/components/scope-picker/index.js
@@ -0,0 +1,48 @@
+/**
+ * Copyright (c) HashiCorp, Inc.
+ * SPDX-License-Identifier: BUSL-1.1
+ */
+
+import Component from '@glimmer/component';
+import { inject as service } from '@ember/service';
+import orderBy from 'lodash/orderBy';
+
+export default class ScopePickerIndexComponent extends Component {
+ // =services
+
+ @service intl;
+ @service scope;
+ @service session;
+
+ // =attributes
+
+ /**
+ * Returns display name and icon for current scope.
+ * @type {object}
+ */
+ get currentScope() {
+ if (this.scope.project) {
+ return { name: this.scope.project.displayName, icon: 'grid' };
+ } else if (this.scope.org.isOrg) {
+ return { name: this.scope.org.displayName, icon: 'org' };
+ } else {
+ return { name: this.intl.t('titles.global'), icon: 'globe' };
+ }
+ }
+
+ /**
+ * Returns first five orgs ordered by most recently updated.
+ * @type {[ScopeModel]}
+ */
+ get truncatedOrgsList() {
+ return orderBy(this.scope.orgsList, 'updated_time', 'desc').slice(0, 5);
+ }
+
+ /**
+ * Returns first five projects ordered by most recently updated.
+ * @type {[ScopeModel]}
+ */
+ get truncatedProjectsList() {
+ return orderBy(this.scope.projectsList, 'updated_time', 'desc').slice(0, 5);
+ }
+}
diff --git a/ui/admin/app/controllers/application.js b/ui/admin/app/controllers/application.js
index 8ed63bcf7..6a554d4d1 100644
--- a/ui/admin/app/controllers/application.js
+++ b/ui/admin/app/controllers/application.js
@@ -30,6 +30,7 @@ export default class ApplicationController extends Controller {
@service features;
@service featureEdition;
@service flashMessages;
+ @service router;
/**
* Returns available themes
@@ -39,6 +40,13 @@ export default class ApplicationController extends Controller {
return THEMES;
}
+ get showSideNav() {
+ return (
+ this.router.currentRouteName.startsWith('scopes.scope') &&
+ this.session.isAuthenticated
+ );
+ }
+
// =actions
/**
diff --git a/ui/admin/app/controllers/scopes/index.js b/ui/admin/app/controllers/scopes/index.js
deleted file mode 100644
index 13ea3b901..000000000
--- a/ui/admin/app/controllers/scopes/index.js
+++ /dev/null
@@ -1,13 +0,0 @@
-/**
- * Copyright (c) HashiCorp, Inc.
- * SPDX-License-Identifier: BUSL-1.1
- */
-
-import Controller from '@ember/controller';
-import { service } from '@ember/service';
-
-export default class ScopesIndexController extends Controller {
- // =services
-
- @service session;
-}
diff --git a/ui/admin/app/controllers/scopes/scope.js b/ui/admin/app/controllers/scopes/scope.js
index 80a51e631..21ccaca37 100644
--- a/ui/admin/app/controllers/scopes/scope.js
+++ b/ui/admin/app/controllers/scopes/scope.js
@@ -10,4 +10,5 @@ export default class ScopesScopeController extends Controller {
// =services
@service session;
+ @service scope;
}
diff --git a/ui/admin/app/routes/account.js b/ui/admin/app/routes/account.js
index 9d3bc8ed7..a8adeba1a 100644
--- a/ui/admin/app/routes/account.js
+++ b/ui/admin/app/routes/account.js
@@ -15,9 +15,14 @@ export default class AccountRoute extends Route {
// =methods
/**
- * If arriving here unauthenticated, redirect to index for further processing.
+ * If arriving here unauthenticated, redirect to index for further processing
+ * else redirect to change-password route since account route is empty.
*/
beforeModel() {
- if (!this.session.isAuthenticated) this.router.transitionTo('index');
+ if (!this.session.isAuthenticated) {
+ this.router.transitionTo('index');
+ } else {
+ this.router.transitionTo('account.change-password');
+ }
}
}
diff --git a/ui/admin/app/routes/scopes/scope.js b/ui/admin/app/routes/scopes/scope.js
index c7220cac9..f7705c345 100644
--- a/ui/admin/app/routes/scopes/scope.js
+++ b/ui/admin/app/routes/scopes/scope.js
@@ -72,29 +72,5 @@ export default class ScopesScopeRoute extends Route {
this.scope.project = selectedProject;
this.scope.orgsList = orgs;
this.scope.projectsList = projects;
- this.scopes = { orgs, projects, selectedOrg, selectedProject };
- // Update the controller (if exists), since setupController is only
- // called once the first time the route is activated. It is not called
- // again on route refreshes.
- /* eslint-disable-next-line ember/no-controller-access-in-routes */
- if (this.controller) this.setControllerProperties(this.scopes);
- }
-
- /**
- * Adds the scopes hash to the controller context (see `afterModel`).
- * @param {Controller} controller
- */
- setupController(/* controller */) {
- super.setupController(...arguments);
- this.setControllerProperties(this.scopes);
- }
-
- /**
- * Updates the controller's `scopes`.
- * @param {array} scopes
- */
- setControllerProperties(scopes) {
- /* eslint-disable-next-line ember/no-controller-access-in-routes */
- this.controller.setProperties({ scopes });
}
}
diff --git a/ui/admin/app/styles/app.scss b/ui/admin/app/styles/app.scss
index 2ee969578..eead2cadc 100644
--- a/ui/admin/app/styles/app.scss
+++ b/ui/admin/app/styles/app.scss
@@ -173,8 +173,6 @@
// Onboarding styles
.create-resources {
- display: flex;
- align-items: flex-start;
width: sizing.rems(xl) * 15;
.create-resources-form {
@@ -185,7 +183,6 @@
.hds-form-group {
margin-top: sizing.rems(l);
- justify-content: center;
.image-container {
display: flex;
@@ -1083,3 +1080,15 @@
margin-bottom: 0;
}
}
+
+// scope picker
+.scope-picker {
+ &__toggle-button {
+ width: 100%;
+ }
+
+ li:has(.indentation),
+ li.indentation {
+ margin-left: 1.5rem;
+ }
+}
diff --git a/ui/admin/app/templates/account/change-password.hbs b/ui/admin/app/templates/account/change-password.hbs
index 39ad90232..d6fd7858c 100644
--- a/ui/admin/app/templates/account/change-password.hbs
+++ b/ui/admin/app/templates/account/change-password.hbs
@@ -5,32 +5,26 @@
{{page-title (t 'actions.change-password')}}
-
-
-
-
-
+
+
-
- {{t 'actions.change-password'}}
-
+
+
+ <:header>
+
+ {{t
+ 'actions.change-password'
+ }}
+
+ <:body>
+
+
+
+
-
-
-
-
-
-
-
-
-
-
- {{t 'titles.documentation'}}
-
-
-
-
\ No newline at end of file
+
+
\ No newline at end of file
diff --git a/ui/admin/app/templates/application.hbs b/ui/admin/app/templates/application.hbs
index 7374139aa..12585bb5f 100644
--- a/ui/admin/app/templates/application.hbs
+++ b/ui/admin/app/templates/application.hbs
@@ -5,113 +5,116 @@
{{page-title (app-name)}}
-
+
+
- {{/if}}
-
-
-
-
-
+
{{outlet}}
-
+
-
+
+
+ {{t 'titles.documentation'}}
+
+
+
+
{{#if this.flashMessages.queue}}
diff --git a/ui/admin/app/templates/onboarding/index.hbs b/ui/admin/app/templates/onboarding/index.hbs
index 5a5bb223e..c78aae327 100644
--- a/ui/admin/app/templates/onboarding/index.hbs
+++ b/ui/admin/app/templates/onboarding/index.hbs
@@ -3,10 +3,13 @@
SPDX-License-Identifier: BUSL-1.1
}}
-
-
+
+
<:header>
- {{t 'onboarding.add-target.titles.have-a-target'}}
+
+ {{t
+ 'onboarding.add-target.titles.have-a-target'
+ }}
<:body>
{{t 'onboarding.add-target.descriptions.setup-first-target'}}
diff --git a/ui/admin/app/templates/onboarding/success.hbs b/ui/admin/app/templates/onboarding/success.hbs
index 01e8d8915..488950126 100644
--- a/ui/admin/app/templates/onboarding/success.hbs
+++ b/ui/admin/app/templates/onboarding/success.hbs
@@ -4,10 +4,14 @@
}}
{{page-title (t 'titles.success')}}
-
-
+
+
+
<:header>
- {{t 'onboarding.success.titles.connect'}}
+
+ {{t
+ 'onboarding.success.titles.connect'
+ }}
<:body>
{{! We have created }}
@@ -27,7 +31,6 @@
{{! Download Desktop client }}
{{t 'onboarding.success.descriptions.download'}}
diff --git a/ui/admin/app/templates/scopes/index.hbs b/ui/admin/app/templates/scopes/index.hbs
deleted file mode 100644
index 5f7437f28..000000000
--- a/ui/admin/app/templates/scopes/index.hbs
+++ /dev/null
@@ -1,30 +0,0 @@
-{{!
- Copyright (c) HashiCorp, Inc.
- SPDX-License-Identifier: BUSL-1.1
-}}
-
-{{outlet}}
-
-{{#unless @model}}
-
-
-
-
-
-
-
-
-
-
-
-
-
- {{t 'titles.documentation'}}
-
-
-
-
-{{/unless}}
\ No newline at end of file
diff --git a/ui/admin/app/templates/scopes/scope.hbs b/ui/admin/app/templates/scopes/scope.hbs
index ab94e6edc..4942104e9 100644
--- a/ui/admin/app/templates/scopes/scope.hbs
+++ b/ui/admin/app/templates/scopes/scope.hbs
@@ -16,14 +16,14 @@
{{#if @model.isProject}}
{{page-title (t 'resources.org.title_plural')}}
- {{page-title this.scopes.selectedOrg.displayName}}
+ {{page-title this.scope.org.displayName}}
{{page-title (t 'resources.project.title_plural')}}
{{page-title @model.displayName}}
{{/if}}
-
+
+ {{#if @model.isGlobal}}
+ {{t 'titles.scope-level' scope=(t 'titles.global')}}
- {{#if this.session.isAuthenticated}}
-
+
- {{#if @model.isGlobal}}
-
-
-
- {{t 'resources.org.title_plural'}}
-
+ {{#if (can 'navigate scope' @model collection='session-recordings')}}
+
+ {{/if}}
- {{#if (can 'navigate scope' @model collection='session-recordings')}}
-
-
- {{t 'resources.session-recording.title_plural'}}
-
- {{/if}}
- {{#if (can 'navigate scope' @model collection='storage-buckets')}}
-
-
- {{t 'resources.storage-bucket.title_plural'}}
-
- {{/if}}
- {{#if (can 'navigate scope' @model collection='policies')}}
-
-
- {{t 'resources.policy.title_plural'}}
-
- {{/if}}
- {{#if (can 'navigate scope' @model collection='aliases')}}
-
-
- {{t 'resources.alias.title_plural'}}
-
- {{/if}}
- {{#if
- (and
- (can 'navigate worker' @model collection='workers')
- (feature-flag 'byow')
- )
- }}
-
-
- {{t 'titles.workers'}}
-
- {{/if}}
-
- {{/if}}
+ {{#if (can 'navigate scope' @model collection='storage-buckets')}}
+
+ {{/if}}
- {{#if @model.isOrg}}
-
- {{#if this.session.data.authenticated.isGlobal}}
-
-
- {{t 'resources.org.title_plural'}}
-
- {{/if}}
-
-
- {{t 'resources.project.title_plural'}}
-
+ {{#if (can 'navigate scope' @model collection='policies')}}
+
+ {{/if}}
- {{#if (can 'navigate scope' @model collection='policies')}}
-
-
- {{t 'resources.policy.title_plural'}}
-
- {{/if}}
-
+ {{#if (can 'navigate scope' @model collection='aliases')}}
+
+ {{/if}}
- {{/if}}
+ {{#if
+ (and
+ (can 'navigate worker' @model collection='workers')
+ (feature-flag 'byow')
+ )
+ }}
+
+ {{/if}}
- {{#if @model.isProject}}
-
- {{#if this.session.data.authenticated.isGlobal}}
-
-
- {{t 'resources.org.title_plural'}}
-
- {{/if}}
-
-
- {{t 'resources.project.title_plural'}}
-
-
-
-
- {{#if (can 'navigate model' @model collection='sessions')}}
-
-
- {{t 'resources.session.title_plural'}}
-
- {{/if}}
- {{#if (can 'navigate model' @model collection='targets')}}
-
-
- {{t 'resources.target.title_plural'}}
-
- {{/if}}
- {{#if (can 'navigate model' @model collection='host-catalogs')}}
-
-
- {{t 'resources.host-catalog.title_plural'}}
-
- {{/if}}
- {{#if (can 'navigate model' @model collection='credential-stores')}}
-
-
- {{t 'resources.credential-store.title_plural'}}
-
- {{/if}}
-
- {{/if}}
-
-
- {{! Users are available only for org/global scopes }}
- {{#unless @model.isProject}}
- {{#if (can 'navigate model' @model collection='users')}}
-
-
- {{t 'resources.user.title_plural'}}
-
- {{/if}}
- {{/unless}}
-
- {{! Groups and roles are available for all scopes }}
- {{#if (can 'navigate model' @model collection='groups')}}
-
-
- {{t 'resources.group.title_plural'}}
-
- {{/if}}
- {{#if (can 'navigate model' @model collection='roles')}}
-
-
- {{t 'resources.role.title_plural'}}
-
- {{/if}}
-
- {{! Auth methods are available only for org/global scopes }}
- {{#unless @model.isProject}}
- {{#if (can 'navigate model' @model collection='auth-methods')}}
-
-
- {{t 'resources.auth-method.title_plural'}}
-
- {{/if}}
- {{/unless}}
-
-
- {{#if (and @model.isGlobal (feature-flag 'ssh-session-recording'))}}
- {{#if this.session.data.authenticated.isGlobal}}
-
-
- {{t 'resources.global.messages.settings.title'}}
-
-
- {{/if}}
- {{/if}}
-
- {{#if @model.isOrg}}
- {{#if this.session.data.authenticated.isGlobal}}
-
-
- {{t 'resources.org.messages.settings.title'}}
-
-
- {{/if}}
- {{/if}}
-
- {{#if @model.isProject}}
-
-
- {{t 'resources.project.messages.settings.title'}}
-
-
- {{/if}}
-
-
+ {{t 'titles.scope-iam' scope=(t 'titles.global')}}
{{/if}}
-
-
- {{outlet}}
-
-
-
-
- {{t 'titles.documentation'}}
-
-
-
-
\ No newline at end of file
+ {{#if @model.isOrg}}
+
{{t
+ 'titles.scope-level'
+ scope=(t 'resources.org.title')
+ }}
+
+ {{#if this.session.data.authenticated.isGlobal}}
+
+ {{/if}}
+
+
+
+ {{#if (can 'navigate scope' @model collection='policies')}}
+
+ {{/if}}
+
+
{{t
+ 'titles.scope-iam'
+ scope=(t 'resources.org.title')
+ }}
+ {{/if}}
+
+ {{#if @model.isProject}}
+
+
+
{{t 'titles.project-actions'}}
+
+ {{#if (can 'navigate model' @model collection='sessions')}}
+
+ {{/if}}
+
+ {{#if (can 'navigate model' @model collection='targets')}}
+
+ {{/if}}
+
+ {{#if (can 'navigate model' @model collection='host-catalogs')}}
+
+ {{/if}}
+
+ {{#if (can 'navigate model' @model collection='credential-stores')}}
+
+ {{/if}}
+
+
{{t
+ 'titles.scope-iam'
+ scope=(t 'resources.project.title')
+ }}
+ {{/if}}
+
+ {{! Users are available only for org/global scopes }}
+ {{#unless @model.isProject}}
+ {{#if (can 'navigate model' @model collection='users')}}
+
+ {{/if}}
+ {{/unless}}
+
+ {{! Groups and roles are available for all scopes }}
+ {{#if (can 'navigate model' @model collection='groups')}}
+
+ {{/if}}
+ {{#if (can 'navigate model' @model collection='roles')}}
+
+ {{/if}}
+
+ {{! Auth methods are available only for org/global scopes }}
+ {{#unless @model.isProject}}
+ {{#if (can 'navigate model' @model collection='auth-methods')}}
+
+ {{/if}}
+ {{/unless}}
+
+ {{#if (and @model.isGlobal (feature-flag 'ssh-session-recording'))}}
+ {{#if this.session.data.authenticated.isGlobal}}
+
{{t 'titles.settings'}}
+
+
+ {{/if}}
+ {{/if}}
+
+ {{#if @model.isOrg}}
+ {{#if this.session.data.authenticated.isGlobal}}
+
{{t 'titles.settings'}}
+
+
+ {{/if}}
+ {{/if}}
+
+ {{#if @model.isProject}}
+
{{t 'titles.settings'}}
+
+
+ {{/if}}
+
+
+{{outlet}}
\ No newline at end of file
diff --git a/ui/admin/app/templates/scopes/scope/-sidebar.hbs b/ui/admin/app/templates/scopes/scope/-sidebar.hbs
deleted file mode 100644
index 10151e826..000000000
--- a/ui/admin/app/templates/scopes/scope/-sidebar.hbs
+++ /dev/null
@@ -1,23 +0,0 @@
-{{!
- Copyright (c) HashiCorp, Inc.
- SPDX-License-Identifier: BUSL-1.1
-}}
-
-
-
-
- {{t 'resources.user.title_plural'}}
-
-
-
- {{t 'resources.group.title_plural'}}
-
-
-
- {{t 'resources.role.title_plural'}}
-
-
-
- {{t 'resources.auth-method.title_plural'}}
-
-
\ No newline at end of file
diff --git a/ui/admin/app/templates/scopes/scope/aliases/alias/index.hbs b/ui/admin/app/templates/scopes/scope/aliases/alias/index.hbs
index bd97059fe..fca455cd6 100644
--- a/ui/admin/app/templates/scopes/scope/aliases/alias/index.hbs
+++ b/ui/admin/app/templates/scopes/scope/aliases/alias/index.hbs
@@ -33,7 +33,7 @@
{{#if (or perms.canUpdate perms.canDelete)}}
-
+
{{#if (and perms.canUpdate @model.destination_id)}}
<:header>
- {{t 'actions.authenticate'}}
+
+ {{t
+ 'actions.authenticate'
+ }}
<:body>
- {{t
+ {{t
'auth.descriptions.authenticating-with-org'
name=@model.scope.displayName
- }}
+ }}
{{#if (or perms.canUpdate perms.canDelete)}}
-
+
`tbody [data-test-grant-scope-row="${id}"]`;
const TABLE_ROW_SELECTOR = 'tbody tr';
- const MANAGE_DROPDOWN_SELECTOR = '.hds-dropdown-toggle-button';
+ const MANAGE_DROPDOWN_SELECTOR = '[data-test-manage-roles-dropdown] button';
const MANAGE_SCOPES_SELECTOR = '[data-test-manage-dropdown-scopes]';
const SEARCH_INPUT_SELECTOR = '.search-filtering [type="search"]';
const NO_SCOPES_MSG_SELECTOR = '.role-grant-scopes div';
diff --git a/ui/admin/tests/acceptance/scopes-test.js b/ui/admin/tests/acceptance/scopes-test.js
index d4d1b45fc..e0897ea30 100644
--- a/ui/admin/tests/acceptance/scopes-test.js
+++ b/ui/admin/tests/acceptance/scopes-test.js
@@ -18,10 +18,8 @@ module('Acceptance | scopes', function (hooks) {
setupMirage(hooks);
setupIndexedDb(hooks);
- const ORG_SCOPES_DROPDOWN_SELECTOR = (url) =>
- `.rose-header-nav .rose-dropdown [href="${url}"]`;
- const PROJECT_SCOPES_DROPDOWN_SELECTOR = (url) =>
- `.rose-header-nav .rose-dropdown + .rose-dropdown [href="${url}"]`;
+ const SCOPES_DROPDOWN_BTN = '.scope-picker button';
+ const SCOPES_DROPDOWN_SELECTOR = (url) => `.scope-picker [href="${url}"]`;
const SAVE_BUTTON_SELECTOR = '[type="submit"]';
const CANCEL_BUTTON_SELECTOR = '.rose-form-actions [type="button"]';
const NAME_FIELD_SELECTOR = '[name="name"]';
@@ -118,26 +116,29 @@ module('Acceptance | scopes', function (hooks) {
assert.strictEqual(currentURL(), urls.orgScopes);
});
- test('can navigate among org scopes via header navigation', async function (assert) {
+ test('can navigate among org scopes via side-nav', async function (assert) {
await visit(urls.globalScope);
await a11yAudit();
assert.strictEqual(currentURL(), urls.globalScope);
- await click(ORG_SCOPES_DROPDOWN_SELECTOR(urls.orgScope));
+ await click(SCOPES_DROPDOWN_BTN);
+ await click(SCOPES_DROPDOWN_SELECTOR(urls.orgScope));
assert.strictEqual(currentURL(), urls.orgScopes);
- await click(ORG_SCOPES_DROPDOWN_SELECTOR(urls.org2Scope));
+ await click(SCOPES_DROPDOWN_BTN);
+ await click(SCOPES_DROPDOWN_SELECTOR(urls.org2Scope));
assert.strictEqual(currentURL(), urls.org2Scopes);
});
- test('can navigate among project scopes via header navigation', async function (assert) {
+ test('can navigate among project scopes via side-nav', async function (assert) {
await visit(urls.projectScope);
await a11yAudit();
assert.strictEqual(currentURL(), urls.projectScopeEdit);
- await click(PROJECT_SCOPES_DROPDOWN_SELECTOR(urls.project2Scope));
+ await click(SCOPES_DROPDOWN_BTN);
+ await click(SCOPES_DROPDOWN_SELECTOR(urls.project2Scope));
assert.strictEqual(currentURL(), urls.project2ScopeEdit);
});
diff --git a/ui/admin/tests/acceptance/scopes/list-test.js b/ui/admin/tests/acceptance/scopes/list-test.js
index 57c3411f3..1d15466b4 100644
--- a/ui/admin/tests/acceptance/scopes/list-test.js
+++ b/ui/admin/tests/acceptance/scopes/list-test.js
@@ -4,7 +4,7 @@
*/
import { module, test } from 'qunit';
-import { visit, fillIn, waitFor } from '@ember/test-helpers';
+import { currentURL, visit, fillIn, waitFor } from '@ember/test-helpers';
import { setupApplicationTest } from 'admin/tests/helpers';
import setupMirage from 'ember-cli-mirage/test-support/setup-mirage';
import { setupIndexedDb } from 'api/test-support/helpers/indexed-db';
@@ -28,6 +28,7 @@ module('Acceptance | scopes | list', function (hooks) {
};
const urls = {
+ scopes: null,
globalScope: null,
orgScope: null,
};
@@ -50,12 +51,20 @@ module('Acceptance | scopes | list', function (hooks) {
type: 'project',
scope: { id: instances.scopes.org1.id, type: 'org' },
});
- urls.globalScope = `/scopes/global/scopes`;
+
+ urls.scopes = '/scopes';
+ urls.globalScope = '/scopes/global/scopes';
urls.orgScope = `/scopes/${instances.scopes.org1.id}/scopes`;
await authenticateSession({});
});
- test('user can search for a specifc org scope by id', async function (assert) {
+ test('user gets redirected to scopes list view', async function (assert) {
+ await visit(urls.scopes);
+
+ assert.strictEqual(currentURL(), urls.globalScope);
+ });
+
+ test('user can search for a specific org scope by id', async function (assert) {
await visit(urls.globalScope);
assert
@@ -102,7 +111,7 @@ module('Acceptance | scopes | list', function (hooks) {
.doesNotExist();
});
- test('user can search for a specifc project scope by id', async function (assert) {
+ test('user can search for a specific project scope by id', async function (assert) {
await visit(urls.orgScope);
assert
diff --git a/ui/admin/tests/acceptance/session-recordings/list-test.js b/ui/admin/tests/acceptance/session-recordings/list-test.js
index 8cda56987..00e09f5ef 100644
--- a/ui/admin/tests/acceptance/session-recordings/list-test.js
+++ b/ui/admin/tests/acceptance/session-recordings/list-test.js
@@ -134,7 +134,9 @@ module('Acceptance | session recordings | list', function (hooks) {
].includes('list'),
);
assert.dom(`[href="${urls.sessionRecordings}"]`).exists();
- assert.dom('[title="General"]').includesText(SESSION_RECORDING_TITLE);
+ assert
+ .dom(commonSelectors.SIDEBAR_NAV_CONTENT)
+ .includesText(SESSION_RECORDING_TITLE);
// Visit session recordings
await click(`[href="${urls.sessionRecordings}"]`);
@@ -153,7 +155,9 @@ module('Acceptance | session recordings | list', function (hooks) {
'session-recordings'
].includes('list'),
);
- assert.dom('[title="General"]').doesNotIncludeText(SESSION_RECORDING_TITLE);
+ assert
+ .dom(commonSelectors.SIDEBAR_NAV_CONTENT)
+ .doesNotIncludeText(SESSION_RECORDING_TITLE);
assert.dom(`[href="${urls.sessionRecordings}"]`).doesNotExist();
});
diff --git a/ui/admin/tests/acceptance/sessions/list-test.js b/ui/admin/tests/acceptance/sessions/list-test.js
index 64ae35055..4571f8149 100644
--- a/ui/admin/tests/acceptance/sessions/list-test.js
+++ b/ui/admin/tests/acceptance/sessions/list-test.js
@@ -127,7 +127,7 @@ module('Acceptance | sessions | list', function (hooks) {
);
assert
- .dom(commonSelectors.RESOURCES_SIDEBAR_NAV_LINK(urls.sessions))
+ .dom(commonSelectors.SIDEBAR_NAV_LINK(urls.sessions))
.doesNotExist();
});
diff --git a/ui/admin/tests/acceptance/storage-buckets/delete-test.js b/ui/admin/tests/acceptance/storage-buckets/delete-test.js
index 40eb1a32c..d54d3b9c0 100644
--- a/ui/admin/tests/acceptance/storage-buckets/delete-test.js
+++ b/ui/admin/tests/acceptance/storage-buckets/delete-test.js
@@ -20,7 +20,7 @@ module('Acceptance | storage-buckets | delete', function (hooks) {
let features;
let getStorageBucketCount;
- const DROPDOWN_BUTTON_SELECTOR = '.hds-dropdown-toggle-icon';
+ const DROPDOWN_BUTTON_SELECTOR = 'tbody tr td:last-child button';
const DELETE_DROPDOWN_SELECTOR = '.hds-dropdown-list-item [type="button"]';
const NOTIFICATION_MSG_TEXT = 'Deleted successfully.';
diff --git a/ui/admin/tests/acceptance/storage-buckets/list-test.js b/ui/admin/tests/acceptance/storage-buckets/list-test.js
index 7e52f8406..d363a032b 100644
--- a/ui/admin/tests/acceptance/storage-buckets/list-test.js
+++ b/ui/admin/tests/acceptance/storage-buckets/list-test.js
@@ -94,7 +94,7 @@ module('Acceptance | storage-buckets | list', function (hooks) {
].includes('create'),
);
assert
- .dom(commonSelectors.GENERAL_SIDEBAR_NAV_LINK(urls.storageBuckets))
+ .dom(commonSelectors.SIDEBAR_NAV_LINK(urls.storageBuckets))
.doesNotExist();
// Tests that correct message is displayed when no buckets exist
@@ -177,7 +177,7 @@ module('Acceptance | storage-buckets | list', function (hooks) {
await visit(urls.globalScope);
assert.false(featuresService.isEnabled('ssh-session-recording'));
assert
- .dom(commonSelectors.GENERAL_SIDEBAR_NAV_LINK(urls.storageBuckets))
+ .dom(commonSelectors.SIDEBAR_NAV_LINK(urls.storageBuckets))
.doesNotExist();
});
diff --git a/ui/admin/tests/acceptance/targets/brokered-credential-sources-test.js b/ui/admin/tests/acceptance/targets/brokered-credential-sources-test.js
index 9e79c37ef..85e190533 100644
--- a/ui/admin/tests/acceptance/targets/brokered-credential-sources-test.js
+++ b/ui/admin/tests/acceptance/targets/brokered-credential-sources-test.js
@@ -309,7 +309,7 @@ module('Acceptance | targets | brokered credential sources', function (hooks) {
const availableCredentialsCount = getCredentialCount();
await visit(urls.brokeredCredentialSources);
assert.strictEqual(findAll('tbody tr').length, credentialLibraryCount);
- await click('.hds-dropdown-toggle-icon');
+ await click('tbody tr td:last-child .hds-dropdown-toggle-icon');
await click('tbody tr .hds-dropdown-list-item button');
assert.strictEqual(findAll('tbody tr').length, credentialLibraryCount - 1);
await visit(urls.addBrokeredCredentialSources);
@@ -327,7 +327,7 @@ module('Acceptance | targets | brokered credential sources', function (hooks) {
const availableCredentialsCount = getCredentialLibraryCount();
await visit(urls.brokeredCredentialSources);
assert.strictEqual(findAll('tbody tr').length, credentialCount);
- await click('.hds-dropdown-toggle-icon');
+ await click('tbody tr td:last-child .hds-dropdown-toggle-icon');
await click('tbody tr .hds-dropdown-list-item button');
assert.strictEqual(findAll('tbody tr').length, credentialCount - 1);
await visit(urls.addBrokeredCredentialSources);
@@ -365,7 +365,7 @@ module('Acceptance | targets | brokered credential sources', function (hooks) {
const count = getCredentialLibraryCount();
await visit(urls.brokeredCredentialSources);
assert.strictEqual(findAll('tbody tr').length, count);
- await click('.hds-dropdown-toggle-icon');
+ await click('tbody tr td:last-child .hds-dropdown-toggle-icon');
await click('tbody tr .hds-dropdown-list-item button');
assert.dom(commonSelectors.ALERT_TOAST_BODY).isVisible();
});
@@ -389,7 +389,7 @@ module('Acceptance | targets | brokered credential sources', function (hooks) {
const count = getCredentialCount();
await visit(urls.brokeredCredentialSources);
assert.strictEqual(findAll('tbody tr').length, count);
- await click('.hds-dropdown-toggle-icon');
+ await click('tbody tr td:last-child .hds-dropdown-toggle-icon');
await click('tbody tr .hds-dropdown-list-item button');
assert.dom(commonSelectors.ALERT_TOAST_BODY).isVisible();
});
diff --git a/ui/admin/tests/acceptance/targets/host-sources-test.js b/ui/admin/tests/acceptance/targets/host-sources-test.js
index 6b9c52e06..6f2253e1b 100644
--- a/ui/admin/tests/acceptance/targets/host-sources-test.js
+++ b/ui/admin/tests/acceptance/targets/host-sources-test.js
@@ -130,7 +130,7 @@ module('Acceptance | targets | host-sources', function (hooks) {
await visit(urls.target);
await click(`[href="${urls.targetHostSources}"]`);
- await click('.hds-dropdown-toggle-icon');
+ await click('tbody tr td:last-child .hds-dropdown-toggle-icon');
await click('tbody tr .hds-dropdown-list-item button');
assert.strictEqual(getTargetHostSetCount(), targetHostSetCount - 1);
@@ -166,7 +166,7 @@ module('Acceptance | targets | host-sources', function (hooks) {
await visit(urls.target);
await click(`[href="${urls.targetHostSources}"]`);
- await click('.hds-dropdown-toggle-icon');
+ await click('tbody tr td:last-child .hds-dropdown-toggle-icon');
await click('tbody tr .hds-dropdown-list-item button');
assert.dom('tbody tr').exists({ count: targetHostSetCount });
@@ -216,7 +216,7 @@ module('Acceptance | targets | host-sources', function (hooks) {
assert.dom('tbody tr').exists({ count: targetHostSetCount });
// first, remove a target host set (otherwise none would be available to add)
- await click('.hds-dropdown-toggle-icon');
+ await click('tbody tr td:last-child .hds-dropdown-toggle-icon');
await click('tbody tr .hds-dropdown-list-item button');
assert.dom('tbody tr').exists({ count: targetHostSetCount - 1 });
diff --git a/ui/admin/tests/acceptance/targets/injected-application-credential-sources-test.js b/ui/admin/tests/acceptance/targets/injected-application-credential-sources-test.js
index a12a97f80..d5e80f580 100644
--- a/ui/admin/tests/acceptance/targets/injected-application-credential-sources-test.js
+++ b/ui/admin/tests/acceptance/targets/injected-application-credential-sources-test.js
@@ -331,7 +331,7 @@ module(
const credentialLibraryCount = getCredentialLibraryCount();
await visit(urls.injectedApplicationCredentialSources);
assert.strictEqual(findAll('tbody tr').length, credentialLibraryCount);
- await click('.hds-dropdown-toggle-icon');
+ await click('tbody tr td:last-child .hds-dropdown-toggle-icon');
await click('tbody tr .hds-dropdown-list-item button');
assert.strictEqual(
findAll('tbody tr').length,
@@ -353,7 +353,7 @@ module(
const credentialCount = getCredentialCount();
await visit(urls.injectedApplicationCredentialSources);
assert.strictEqual(findAll('tbody tr').length, credentialCount);
- await click('.hds-dropdown-toggle-icon');
+ await click('tbody tr td:last-child .hds-dropdown-toggle-icon');
await click('tbody tr .hds-dropdown-list-item button');
assert.strictEqual(findAll('tbody tr').length, credentialCount - 1);
await visit(urls.addInjectedApplicationCredentialSources);
@@ -390,7 +390,7 @@ module(
const count = getCredentialLibraryCount();
await visit(urls.injectedApplicationCredentialSources);
assert.strictEqual(findAll('tbody tr').length, count);
- await click('.hds-dropdown-toggle-icon');
+ await click('tbody tr td:last-child .hds-dropdown-toggle-icon');
await click('tbody tr .hds-dropdown-list-item button');
assert.dom(commonSelectors.ALERT_TOAST_BODY).isVisible();
});
@@ -416,7 +416,7 @@ module(
const count = getCredentialCount();
await visit(urls.injectedApplicationCredentialSources);
assert.strictEqual(findAll('tbody tr').length, count);
- await click('.hds-dropdown-toggle-icon');
+ await click('tbody tr td:last-child .hds-dropdown-toggle-icon');
await click('tbody tr .hds-dropdown-list-item button');
assert.dom(commonSelectors.ALERT_TOAST_BODY).isVisible();
});
diff --git a/ui/admin/tests/acceptance/targets/list-test.js b/ui/admin/tests/acceptance/targets/list-test.js
index ee4d379f4..029437179 100644
--- a/ui/admin/tests/acceptance/targets/list-test.js
+++ b/ui/admin/tests/acceptance/targets/list-test.js
@@ -17,6 +17,7 @@ import { setupIndexedDb } from 'api/test-support/helpers/indexed-db';
import { authenticateSession } from 'ember-simple-auth/test-support';
import { TYPE_TARGET_TCP, TYPE_TARGET_SSH } from 'api/models/target';
import { STATUS_SESSION_ACTIVE } from 'api/models/session';
+import * as commonSelectors from 'admin/tests/helpers/selectors';
module('Acceptance | targets | list', function (hooks) {
setupApplicationTest(hooks);
@@ -122,9 +123,7 @@ module('Acceptance | targets | list', function (hooks) {
'create',
),
);
- assert
- .dom('[title="Resources"] a:nth-of-type(2)')
- .doesNotIncludeText('Targets');
+ assert.dom(commonSelectors.SIDEBAR_NAV_CONTENT).doesNotIncludeText('Targets');
});
test('user can navigate to index with only create action', async function (assert) {
diff --git a/ui/admin/tests/acceptance/targets/manage-alias-test.js b/ui/admin/tests/acceptance/targets/manage-alias-test.js
index 81ee1648a..84b78d197 100644
--- a/ui/admin/tests/acceptance/targets/manage-alias-test.js
+++ b/ui/admin/tests/acceptance/targets/manage-alias-test.js
@@ -17,7 +17,7 @@ module('Acceptance | targets | manage-alias', function (hooks) {
let aliasResourceTwo, aliasResourceOne, getAliasCount;
const ALIASES_SIDEBAR = '.target-sidebar-aliases';
const ALIASES_SIDEBAR_LIST = '.link-list-item';
- const DROPDOWN_ACTION = '.hds-dropdown-toggle-button__text';
+ const DROPDOWN_ACTION = '[data-test-manage-target-alias] button';
const CLEAR_BTN_SELECTOR = '.hds-dropdown-list-item--color-action button';
const DELETE_BTN_SELECTOR = '.hds-dropdown-list-item--color-critical button';
const LINK_TO_NEW_ALIAS = '.target-sidebar-aliases .hds-button';
diff --git a/ui/admin/tests/helpers/selectors.js b/ui/admin/tests/helpers/selectors.js
index 7806f375c..a9ed2a376 100644
--- a/ui/admin/tests/helpers/selectors.js
+++ b/ui/admin/tests/helpers/selectors.js
@@ -35,11 +35,10 @@ export const PAGE_MESSAGE_LINK =
export const HREF = (url) => `[href="${url}"]`;
-export const GENERAL_SIDEBAR_NAV_LINK = (url) =>
- `[title="General"] a[href="${url}"]`;
-export const RESOURCES_SIDEBAR_NAV_LINK = (url) =>
- `[title="Resources"] a[href="${url}"]`;
-export const IAM_SIDEBAR_NAV_LINK = (url) => `[title="IAM"] a[href="${url}"]`;
+export const SIDEBAR_NAV_LINK = (url) => `.hds-side-nav__content a[href="${url}"]`;
+export const SIDEBAR_NAV_CONTENT = '.hds-side-nav__content';
+export const SIDEBAR_USER_DROPDOWN =
+ '[data-test-side-nav-user-dropdown] button';
export const ALERT_TOAST = '[data-test-toast-notification]';
export const ALERT_TOAST_BODY =
diff --git a/ui/admin/tests/integration/components/scope-picker/index-test.js b/ui/admin/tests/integration/components/scope-picker/index-test.js
new file mode 100644
index 000000000..e0817db31
--- /dev/null
+++ b/ui/admin/tests/integration/components/scope-picker/index-test.js
@@ -0,0 +1,204 @@
+/**
+ * Copyright (c) HashiCorp, Inc.
+ * SPDX-License-Identifier: BUSL-1.1
+ */
+
+import { module, test } from 'qunit';
+import { setupRenderingTest } from 'admin/tests/helpers';
+import { render } from '@ember/test-helpers';
+import { hbs } from 'ember-cli-htmlbars';
+import { click } from '@ember/test-helpers';
+import setupMirage from 'ember-cli-mirage/test-support/setup-mirage';
+import { setupIntl } from 'ember-intl/test-support';
+
+module('Integration | Component | scope-picker/index', function (hooks) {
+ setupRenderingTest(hooks);
+ setupMirage(hooks);
+ setupIntl(hooks, 'en-us');
+
+ const SCOPE_PICKER_DROPDOWN = '.scope-picker button';
+ const SCOPE_PICKER_DROPDOWN_ICON = '.hds-dropdown-toggle-button__icon svg';
+ const ORG_ADD_MORE_TEXT = '[data-test-scope-picker-org-and-more-text]';
+ const ORG_LIST_ITEM = '[data-test-scope-picker-org-item]';
+ const ORG_LIST_COUNT = '[data-test-scope-picker-org-count]';
+ const PROJECT_LIST_ITEM = '[data-test-scope-picker-project-item]';
+ const PROJECT_ADD_MORE_TEXT =
+ '[data-test-scope-picker-project-and-more-text]';
+ const PROJECT_LIST_COUNT = '[data-test-scope-picker-project-count]';
+ const SELECTED_SCOPE_CHECK = (id) => `[href="/scopes/${id}"] .hds-icon-check`;
+
+ let global;
+ let scopeService;
+ let store;
+
+ hooks.beforeEach(async function () {
+ store = this.owner.lookup('service:store');
+ scopeService = this.owner.lookup('service:scope');
+
+ this.server.create('scope', { id: 'global' });
+ global = await store.findRecord('scope', 'global');
+ });
+
+ test('it renders correct content when there are more than five orgs', async function (assert) {
+ const orgs = this.server.createList('scope', 6, {
+ type: 'org',
+ scope: { id: 'global', type: 'global' },
+ });
+ this.server.createList('scope', 2, {
+ type: 'project',
+ scope: { id: orgs[0].id, type: 'org' },
+ });
+ scopeService.org = global;
+ scopeService.orgsList = await store.query('scope', { scope_id: 'global' });
+ scopeService.projectsList = await store.query('scope', {
+ scope_id: orgs[0].id,
+ });
+
+ await render(hbs``);
+ await click(SCOPE_PICKER_DROPDOWN);
+
+ assert.dom(ORG_ADD_MORE_TEXT).isVisible();
+ // Scope picker should always render five or less orgs.
+ assert.dom(ORG_LIST_ITEM).isVisible({ count: 5 });
+ assert.dom(ORG_LIST_COUNT).includesText(`(${orgs.length})`);
+ // Project scopes do not render when a project hasn't been selected.
+ assert.dom(PROJECT_LIST_ITEM).doesNotExist();
+ });
+
+ test('it renders correct content when there are five or less orgs', async function (assert) {
+ const orgs = this.server.createList('scope', 4, {
+ type: 'org',
+ scope: { id: 'global', type: 'global' },
+ });
+ this.server.createList('scope', 2, {
+ type: 'project',
+ scope: { id: orgs[0].id, type: 'org' },
+ });
+ scopeService.org = global;
+ scopeService.orgsList = await store.query('scope', { scope_id: 'global' });
+ scopeService.projectsList = await store.query('scope', {
+ scope_id: orgs[0].id,
+ });
+
+ await render(hbs``);
+ await click(SCOPE_PICKER_DROPDOWN);
+
+ assert.dom(ORG_ADD_MORE_TEXT).doesNotExist();
+ // Scope picker should always render five or less orgs.
+ assert.dom(ORG_LIST_ITEM).isVisible({ count: 4 });
+ assert.dom(ORG_LIST_COUNT).doesNotExist();
+ // Project scopes do not render when a project hasn't been selected.
+ assert.dom(PROJECT_LIST_ITEM).doesNotExist();
+ });
+
+ test('it renders correct content when there are more than five projects', async function (assert) {
+ const orgs = this.server.createList('scope', 2, {
+ type: 'org',
+ scope: { id: 'global', type: 'global' },
+ });
+ this.server.createList('scope', 6, {
+ type: 'project',
+ scope: { id: orgs[0].id, type: 'org' },
+ });
+ const projects = await store.query('scope', { scope_id: orgs[0].id });
+ scopeService.org = global;
+ scopeService.project = projects[0];
+ scopeService.orgsList = await store.query('scope', { scope_id: 'global' });
+ scopeService.projectsList = projects;
+
+ await render(hbs``);
+ await click(SCOPE_PICKER_DROPDOWN);
+
+ assert.dom(SCOPE_PICKER_DROPDOWN).hasText(scopeService.project.displayName);
+ assert.dom(PROJECT_ADD_MORE_TEXT).isVisible();
+ // Scope picker should always render five or less projects.
+ assert.dom(PROJECT_LIST_ITEM).isVisible({ count: 5 });
+ assert.dom(PROJECT_LIST_ITEM).hasClass('indentation');
+ assert.dom(PROJECT_LIST_COUNT).includesText(`(${projects.length})`);
+ assert.dom(PROJECT_LIST_COUNT).hasClass('indentation');
+ assert.dom(ORG_LIST_ITEM).isVisible({ count: orgs.length });
+ });
+
+ test('it renders correct content when there are five or less projects', async function (assert) {
+ const orgs = this.server.createList('scope', 5, {
+ type: 'org',
+ scope: { id: 'global', type: 'global' },
+ });
+ this.server.createList('scope', 4, {
+ type: 'project',
+ scope: { id: orgs[0].id, type: 'org' },
+ });
+ const projects = await store.query('scope', { scope_id: orgs[0].id });
+ scopeService.org = global;
+ scopeService.project = projects[0];
+ scopeService.orgsList = await store.query('scope', { scope_id: 'global' });
+ scopeService.projectsList = projects;
+
+ await render(hbs``);
+ await click(SCOPE_PICKER_DROPDOWN);
+
+ assert.dom(SCOPE_PICKER_DROPDOWN).hasText(scopeService.project.displayName);
+ assert.dom(PROJECT_ADD_MORE_TEXT).doesNotExist();
+ // Scope picker should always render five or less projects.
+ assert.dom(PROJECT_LIST_ITEM).isVisible({ count: projects.length });
+ assert.dom(PROJECT_LIST_ITEM).hasClass('indentation');
+ assert.dom(PROJECT_LIST_COUNT).doesNotExist();
+ assert.dom(ORG_LIST_ITEM).isVisible({ count: orgs.length });
+ });
+
+ test('it renders correct dropdown button text and icon when selected scope is global type', async function (assert) {
+ this.server.create('scope', {
+ type: 'org',
+ scope: { id: 'global', type: 'global' },
+ });
+ scopeService.org = global;
+ scopeService.orgsList = await store.query('scope', { scope_id: 'global' });
+
+ await render(hbs``);
+ await click(SCOPE_PICKER_DROPDOWN);
+
+ assert.dom(SCOPE_PICKER_DROPDOWN).hasText('Global');
+ assert.dom(SCOPE_PICKER_DROPDOWN_ICON).hasClass('hds-icon-globe');
+ assert.dom(SELECTED_SCOPE_CHECK('global')).isVisible();
+ });
+
+ test('it renders correct dropdown button text and icon when selected scope is org type', async function (assert) {
+ this.server.create('scope', {
+ type: 'org',
+ scope: { id: 'global', type: 'global' },
+ });
+
+ scopeService.orgsList = await store.query('scope', { scope_id: 'global' });
+ scopeService.org = scopeService.orgsList[0];
+
+ await render(hbs``);
+ await click(SCOPE_PICKER_DROPDOWN);
+
+ assert.dom(SCOPE_PICKER_DROPDOWN).hasText(scopeService.org.displayName);
+ assert.dom(SCOPE_PICKER_DROPDOWN_ICON).hasClass('hds-icon-org');
+ assert.dom(SELECTED_SCOPE_CHECK(scopeService.org.id)).isVisible();
+ });
+
+ test('it renders correct dropdown button text and icon when selected scope is project type', async function (assert) {
+ const org = this.server.create('scope', {
+ type: 'org',
+ scope: { id: 'global', type: 'global' },
+ });
+ this.server.createList('scope', 2, {
+ type: 'project',
+ scope: { id: org.id, type: 'org' },
+ });
+ const projects = await store.query('scope', { scope_id: org.id });
+ scopeService.org = global;
+ scopeService.project = projects[0];
+ scopeService.orgsList = await store.query('scope', { scope_id: 'global' });
+ scopeService.projectsList = projects;
+
+ await render(hbs``);
+ await click(SCOPE_PICKER_DROPDOWN);
+
+ assert.dom(SCOPE_PICKER_DROPDOWN).hasText(scopeService.project.displayName);
+ assert.dom(SCOPE_PICKER_DROPDOWN_ICON).hasClass('hds-icon-grid');
+ assert.dom(SELECTED_SCOPE_CHECK(scopeService.project.id)).isVisible();
+ });
+});
diff --git a/yarn.lock b/yarn.lock
index 892acfabc..2f7d68cb0 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -4545,6 +4545,196 @@ __metadata:
languageName: node
linkType: hard
+"@codemirror/autocomplete@npm:^6.0.0, @codemirror/autocomplete@npm:^6.7.1":
+ version: 6.18.6
+ resolution: "@codemirror/autocomplete@npm:6.18.6"
+ dependencies:
+ "@codemirror/language": "npm:^6.0.0"
+ "@codemirror/state": "npm:^6.0.0"
+ "@codemirror/view": "npm:^6.17.0"
+ "@lezer/common": "npm:^1.0.0"
+ checksum: 10c0/65069493978b2af7c600af5020a8873270a8bc9a6820da192bf28b03535f1a0127aa5767eb30d9bfa5d36c61186ee2766925625e8a6c731194e7def0d882fb84
+ languageName: node
+ linkType: hard
+
+"@codemirror/commands@npm:^6.8.0":
+ version: 6.8.1
+ resolution: "@codemirror/commands@npm:6.8.1"
+ dependencies:
+ "@codemirror/language": "npm:^6.0.0"
+ "@codemirror/state": "npm:^6.4.0"
+ "@codemirror/view": "npm:^6.27.0"
+ "@lezer/common": "npm:^1.1.0"
+ checksum: 10c0/da61311f4c39036f93fbe518c673f2464902cf1b64b071319b14b7d690315b72828de4bc12f28be78eeac6e8b8bd8800d4e7921dc37977f78baac4dd49c5b4bf
+ languageName: node
+ linkType: hard
+
+"@codemirror/lang-css@npm:^6.0.0":
+ version: 6.3.1
+ resolution: "@codemirror/lang-css@npm:6.3.1"
+ dependencies:
+ "@codemirror/autocomplete": "npm:^6.0.0"
+ "@codemirror/language": "npm:^6.0.0"
+ "@codemirror/state": "npm:^6.0.0"
+ "@lezer/common": "npm:^1.0.2"
+ "@lezer/css": "npm:^1.1.7"
+ checksum: 10c0/339387c5a1b90076ae41017e66d7da70dd2aca4e5e4d012c95df33d0f6e740410cf1fb53c4845e3814636d587ce6eff05ebca3173dcfc564a1f646d24f299180
+ languageName: node
+ linkType: hard
+
+"@codemirror/lang-go@npm:^6.0.1":
+ version: 6.0.1
+ resolution: "@codemirror/lang-go@npm:6.0.1"
+ dependencies:
+ "@codemirror/autocomplete": "npm:^6.0.0"
+ "@codemirror/language": "npm:^6.6.0"
+ "@codemirror/state": "npm:^6.0.0"
+ "@lezer/common": "npm:^1.0.0"
+ "@lezer/go": "npm:^1.0.0"
+ checksum: 10c0/7bd2a6268859c61745177500b7261a18c1ae1adcb7a1ae2806de9258b67dc3560379a371b7533d456d139f4535ca2b7e591754cafc939335ea659b5739caa0f5
+ languageName: node
+ linkType: hard
+
+"@codemirror/lang-html@npm:^6.0.0":
+ version: 6.4.9
+ resolution: "@codemirror/lang-html@npm:6.4.9"
+ dependencies:
+ "@codemirror/autocomplete": "npm:^6.0.0"
+ "@codemirror/lang-css": "npm:^6.0.0"
+ "@codemirror/lang-javascript": "npm:^6.0.0"
+ "@codemirror/language": "npm:^6.4.0"
+ "@codemirror/state": "npm:^6.0.0"
+ "@codemirror/view": "npm:^6.17.0"
+ "@lezer/common": "npm:^1.0.0"
+ "@lezer/css": "npm:^1.1.0"
+ "@lezer/html": "npm:^1.3.0"
+ checksum: 10c0/0d6197aa645cc0a9da33789ea30423d4b8320b8e636c8587c7fcf58bdf90ea6934451d84ccbd9dd60dbc7046428204d7c986bd742c2cc459bee7c9653258db70
+ languageName: node
+ linkType: hard
+
+"@codemirror/lang-javascript@npm:^6.0.0, @codemirror/lang-javascript@npm:^6.2.2":
+ version: 6.2.3
+ resolution: "@codemirror/lang-javascript@npm:6.2.3"
+ dependencies:
+ "@codemirror/autocomplete": "npm:^6.0.0"
+ "@codemirror/language": "npm:^6.6.0"
+ "@codemirror/lint": "npm:^6.0.0"
+ "@codemirror/state": "npm:^6.0.0"
+ "@codemirror/view": "npm:^6.17.0"
+ "@lezer/common": "npm:^1.0.0"
+ "@lezer/javascript": "npm:^1.0.0"
+ checksum: 10c0/6f7c2563325a4b9ea13aadf92e8d4fa0b4da6b6ea6f623e8a593732b7965b863bf66ca2273202954c70d4f9a2bdc74dcb03bb8100300f4c08d5834afe8f2aede
+ languageName: node
+ linkType: hard
+
+"@codemirror/lang-json@npm:^6.0.1":
+ version: 6.0.1
+ resolution: "@codemirror/lang-json@npm:6.0.1"
+ dependencies:
+ "@codemirror/language": "npm:^6.0.0"
+ "@lezer/json": "npm:^1.0.0"
+ checksum: 10c0/c70301ba43d44dbd1ff0ccab6ec6e3fb9825d61d4854b4839441a8144a9c96997acdad16d93199d157308dd80088a5e9f14b66f395c7e79f4dadc6b4e70ce8a8
+ languageName: node
+ linkType: hard
+
+"@codemirror/lang-markdown@npm:^6.3.2":
+ version: 6.3.2
+ resolution: "@codemirror/lang-markdown@npm:6.3.2"
+ dependencies:
+ "@codemirror/autocomplete": "npm:^6.7.1"
+ "@codemirror/lang-html": "npm:^6.0.0"
+ "@codemirror/language": "npm:^6.3.0"
+ "@codemirror/state": "npm:^6.0.0"
+ "@codemirror/view": "npm:^6.0.0"
+ "@lezer/common": "npm:^1.2.1"
+ "@lezer/markdown": "npm:^1.0.0"
+ checksum: 10c0/dc1c8449cf320def12d2d9bbcba24a697513431650cc5a97413de9b70fc514521e1a677351f45cc73081ac1ff58812554ba580929a1f722d21ae66233f944499
+ languageName: node
+ linkType: hard
+
+"@codemirror/lang-sql@npm:^6.8.0":
+ version: 6.8.0
+ resolution: "@codemirror/lang-sql@npm:6.8.0"
+ dependencies:
+ "@codemirror/autocomplete": "npm:^6.0.0"
+ "@codemirror/language": "npm:^6.0.0"
+ "@codemirror/state": "npm:^6.0.0"
+ "@lezer/common": "npm:^1.2.0"
+ "@lezer/highlight": "npm:^1.0.0"
+ "@lezer/lr": "npm:^1.0.0"
+ checksum: 10c0/a2500e4cebf6c074c89338a020332c44094e7a6eead04ad6d7e423173a4f4637a6021fdbf68935a2f23550eb7b1d1d078855b3d3bf84b50ab7ad1ff01a95d463
+ languageName: node
+ linkType: hard
+
+"@codemirror/lang-yaml@npm:^6.1.2":
+ version: 6.1.2
+ resolution: "@codemirror/lang-yaml@npm:6.1.2"
+ dependencies:
+ "@codemirror/autocomplete": "npm:^6.0.0"
+ "@codemirror/language": "npm:^6.0.0"
+ "@codemirror/state": "npm:^6.0.0"
+ "@lezer/common": "npm:^1.2.0"
+ "@lezer/highlight": "npm:^1.2.0"
+ "@lezer/lr": "npm:^1.0.0"
+ "@lezer/yaml": "npm:^1.0.0"
+ checksum: 10c0/fc993c5e24baee0212d587c652ee7633792533c1b1e5b708d5e4f6c29e6164a3563958fd6a3bb402a64f565f7bab7edbda6c8b8cd8bfecfd0b7294f0dcf998a8
+ languageName: node
+ linkType: hard
+
+"@codemirror/language@npm:^6.0.0, @codemirror/language@npm:^6.10.3, @codemirror/language@npm:^6.3.0, @codemirror/language@npm:^6.4.0, @codemirror/language@npm:^6.6.0":
+ version: 6.11.0
+ resolution: "@codemirror/language@npm:6.11.0"
+ dependencies:
+ "@codemirror/state": "npm:^6.0.0"
+ "@codemirror/view": "npm:^6.23.0"
+ "@lezer/common": "npm:^1.1.0"
+ "@lezer/highlight": "npm:^1.0.0"
+ "@lezer/lr": "npm:^1.0.0"
+ style-mod: "npm:^4.0.0"
+ checksum: 10c0/a8e45ef6dbccc5a7389f277b026412eeecc4ce3dfd806f77f34a8d85df20e257b3b5d0da26c59d9f024e7109542614c62cfa708158da447b0ae97b8fd8476fa9
+ languageName: node
+ linkType: hard
+
+"@codemirror/legacy-modes@npm:^6.4.2":
+ version: 6.5.0
+ resolution: "@codemirror/legacy-modes@npm:6.5.0"
+ dependencies:
+ "@codemirror/language": "npm:^6.0.0"
+ checksum: 10c0/f1d8432e96a0647a22901a065cd074391ca8daf879e92cf87d9fbae15a40777a77fe4fc2076591319d32c47f5793b203a64c1e941de088c317e7ece5d14aa1b8
+ languageName: node
+ linkType: hard
+
+"@codemirror/lint@npm:^6.0.0, @codemirror/lint@npm:^6.8.4":
+ version: 6.8.5
+ resolution: "@codemirror/lint@npm:6.8.5"
+ dependencies:
+ "@codemirror/state": "npm:^6.0.0"
+ "@codemirror/view": "npm:^6.35.0"
+ crelt: "npm:^1.0.5"
+ checksum: 10c0/3ae3ca239575e81255d6968f73d444335fcbc576eccf96a070cf5d838b3121814e6e0a92a4c5450672ce8178e3f5595bdba00a704915ce29fb0218968e383941
+ languageName: node
+ linkType: hard
+
+"@codemirror/state@npm:^6.0.0, @codemirror/state@npm:^6.4.0, @codemirror/state@npm:^6.5.0":
+ version: 6.5.2
+ resolution: "@codemirror/state@npm:6.5.2"
+ dependencies:
+ "@marijn/find-cluster-break": "npm:^1.0.0"
+ checksum: 10c0/1ef773394e32c077a8cfc1ec6d881aefb1918876f82161748e505c38d143aa1c6893c314cfec91097d28f704ec07b2a6c6b75abd435086208974256dee997282
+ languageName: node
+ linkType: hard
+
+"@codemirror/view@npm:^6.0.0, @codemirror/view@npm:^6.17.0, @codemirror/view@npm:^6.23.0, @codemirror/view@npm:^6.27.0, @codemirror/view@npm:^6.35.0, @codemirror/view@npm:^6.36.2":
+ version: 6.36.5
+ resolution: "@codemirror/view@npm:6.36.5"
+ dependencies:
+ "@codemirror/state": "npm:^6.5.0"
+ style-mod: "npm:^4.1.0"
+ w3c-keyname: "npm:^2.2.4"
+ checksum: 10c0/013dc47cb4dde111f4f0818f7c3ee5e4f505359f26d891ca5bbc839a674da8ac201b4d091c5ad73a889f950d4aeb402f2b4c7fcf1e075cc15a3138792dd9e3f0
+ languageName: node
+ linkType: hard
+
"@csstools/css-parser-algorithms@npm:^2.3.0":
version: 2.3.0
resolution: "@csstools/css-parser-algorithms@npm:2.3.0"
@@ -5151,19 +5341,6 @@ __metadata:
languageName: node
linkType: hard
-"@ember/render-modifiers@npm:^2.0.5":
- version: 2.0.5
- resolution: "@ember/render-modifiers@npm:2.0.5"
- dependencies:
- "@embroider/macros": "npm:^1.0.0"
- ember-cli-babel: "npm:^7.26.11"
- ember-modifier-manager-polyfill: "npm:^1.2.0"
- peerDependencies:
- ember-source: ^3.8 || ^4.0.0
- checksum: 10c0/0c4efae860cf57b27fe743c2a20731bb8cc10c81020e526c4dac9eb0955c91a50064b88d5d926fef150a2201d4a7dcb5b12fa584298ea09f2aa886015856cb29
- languageName: node
- linkType: hard
-
"@ember/render-modifiers@npm:^2.1.0":
version: 2.1.0
resolution: "@ember/render-modifiers@npm:2.1.0"
@@ -5228,16 +5405,6 @@ __metadata:
languageName: node
linkType: hard
-"@embroider/addon-shim@npm:1.8.3":
- version: 1.8.3
- resolution: "@embroider/addon-shim@npm:1.8.3"
- dependencies:
- "@embroider/shared-internals": "npm:^1.8.3"
- semver: "npm:^7.3.5"
- checksum: 10c0/b28336ae60450615c0d9831d02ab2838b02ff98fc704af782a7d43dd714eea305e7ad2a9411a828d2802e833e345eb982dbd89d4c9696a0f50c1f203ff240c7b
- languageName: node
- linkType: hard
-
"@embroider/addon-shim@npm:^1.0.0, @embroider/addon-shim@npm:^1.2.0, @embroider/addon-shim@npm:^1.3.0, @embroider/addon-shim@npm:^1.6.0, @embroider/addon-shim@npm:^1.7.1, @embroider/addon-shim@npm:^1.8.3, @embroider/addon-shim@npm:^1.8.4, @embroider/addon-shim@npm:^1.8.6, @embroider/addon-shim@npm:^1.8.7, @embroider/addon-shim@npm:^1.8.9, @embroider/addon-shim@npm:^1.9.0":
version: 1.9.0
resolution: "@embroider/addon-shim@npm:1.9.0"
@@ -5250,7 +5417,7 @@ __metadata:
languageName: node
linkType: hard
-"@embroider/macros@npm:^0.50.0 || ^1.0.0, @embroider/macros@npm:^1.0.0, @embroider/macros@npm:^1.10.0, @embroider/macros@npm:^1.13.0, @embroider/macros@npm:^1.13.1, @embroider/macros@npm:^1.13.2, @embroider/macros@npm:^1.16.1, @embroider/macros@npm:^1.16.5, @embroider/macros@npm:^1.16.9, @embroider/macros@npm:^1.8.1":
+"@embroider/macros@npm:^0.50.0 || ^1.0.0, @embroider/macros@npm:^1.0.0, @embroider/macros@npm:^1.10.0, @embroider/macros@npm:^1.13.1, @embroider/macros@npm:^1.13.2, @embroider/macros@npm:^1.16.5, @embroider/macros@npm:^1.16.9, @embroider/macros@npm:^1.8.1":
version: 1.16.9
resolution: "@embroider/macros@npm:1.16.9"
dependencies:
@@ -5292,6 +5459,27 @@ __metadata:
languageName: node
linkType: hard
+"@embroider/macros@npm:^1.16.10":
+ version: 1.16.13
+ resolution: "@embroider/macros@npm:1.16.13"
+ dependencies:
+ "@embroider/shared-internals": "npm:2.9.0"
+ assert-never: "npm:^1.2.1"
+ babel-import-util: "npm:^2.0.0"
+ ember-cli-babel: "npm:^7.26.6"
+ find-up: "npm:^5.0.0"
+ lodash: "npm:^4.17.21"
+ resolve: "npm:^1.20.0"
+ semver: "npm:^7.3.2"
+ peerDependencies:
+ "@glint/template": ^1.0.0
+ peerDependenciesMeta:
+ "@glint/template":
+ optional: true
+ checksum: 10c0/eb116afe0aed464f3b6838b8464f589297f4804f5ae935d5bc209afac936a4b920f3de3c8b3ca67fe68595379af058e22493e2ed87fd070771c07c6af4a7fb04
+ languageName: node
+ linkType: hard
+
"@embroider/macros@npm:^1.16.11":
version: 1.16.12
resolution: "@embroider/macros@npm:1.16.12"
@@ -5353,22 +5541,6 @@ __metadata:
languageName: node
linkType: hard
-"@embroider/shared-internals@npm:^1.8.3":
- version: 1.8.3
- resolution: "@embroider/shared-internals@npm:1.8.3"
- dependencies:
- babel-import-util: "npm:^1.1.0"
- ember-rfc176-data: "npm:^0.3.17"
- fs-extra: "npm:^9.1.0"
- js-string-escape: "npm:^1.0.1"
- lodash: "npm:^4.17.21"
- resolve-package-path: "npm:^4.0.1"
- semver: "npm:^7.3.5"
- typescript-memoize: "npm:^1.0.1"
- checksum: 10c0/fa8eaa988d7b9f70482a350f673dfc269524d1c4c0cc046d8795453f515a4b107d6c0f1ecef1ee3ac26aeee67b85b2804cf575e945bea5b2c572aedb0970524d
- languageName: node
- linkType: hard
-
"@embroider/test-setup@npm:^2.1.1":
version: 2.1.1
resolution: "@embroider/test-setup@npm:2.1.1"
@@ -5379,11 +5551,11 @@ __metadata:
languageName: node
linkType: hard
-"@embroider/util@npm:^1.0.0":
- version: 1.12.0
- resolution: "@embroider/util@npm:1.12.0"
+"@embroider/util@npm:^1.13.2":
+ version: 1.13.2
+ resolution: "@embroider/util@npm:1.13.2"
dependencies:
- "@embroider/macros": "npm:^1.13.0"
+ "@embroider/macros": "npm:^1.16.5"
broccoli-funnel: "npm:^3.0.5"
ember-cli-babel: "npm:^7.26.11"
peerDependencies:
@@ -5395,27 +5567,7 @@ __metadata:
optional: true
"@glint/template":
optional: true
- checksum: 10c0/960455102444a7d517e071c695df343b298d095fe55824fca8269bac13c34baa29da6a6d593e8f7972949e51b6d4b6580b99ca098347c2d36e09466f0668dc94
- languageName: node
- linkType: hard
-
-"@embroider/util@npm:^1.13.1":
- version: 1.13.1
- resolution: "@embroider/util@npm:1.13.1"
- dependencies:
- "@embroider/macros": "npm:^1.16.1"
- broccoli-funnel: "npm:^3.0.5"
- ember-cli-babel: "npm:^7.26.11"
- peerDependencies:
- "@glint/environment-ember-loose": ^1.0.0
- "@glint/template": ^1.0.0
- ember-source: "*"
- peerDependenciesMeta:
- "@glint/environment-ember-loose":
- optional: true
- "@glint/template":
- optional: true
- checksum: 10c0/98f8eda2e56c1c423b6d22693461ed1685bbc283a95d0a377b1529567301a3ba2d21dd4a8f3d89a05ebd4c561b7c0832a7850d8432b3ccc4861553a1c49e4bbe
+ checksum: 10c0/2183f99e6c1c27b07c273aff4c985f7af95d2eb37c3bcf9c198b76c79f25a76c87c7782c9766e785fb42ca71349b71314789a208f2e1ec233a546fb6454f8731
languageName: node
linkType: hard
@@ -5475,29 +5627,29 @@ __metadata:
languageName: node
linkType: hard
-"@floating-ui/core@npm:^1.0.0":
- version: 1.6.2
- resolution: "@floating-ui/core@npm:1.6.2"
+"@floating-ui/core@npm:^1.6.0":
+ version: 1.6.9
+ resolution: "@floating-ui/core@npm:1.6.9"
dependencies:
- "@floating-ui/utils": "npm:^0.2.0"
- checksum: 10c0/db2621dc682e7f043d6f118d087ae6a6bfdacf40b26ede561760dd53548c16e2e7c59031e013e37283801fa307b55e6de65bf3b316b96a054e4a6a7cb937c59e
+ "@floating-ui/utils": "npm:^0.2.9"
+ checksum: 10c0/77debdfc26bc36c6f5ae1f26ab3c15468215738b3f5682af4e1915602fa21ba33ad210273f31c9d2da1c531409929e1afb1138b1608c6b54a0f5853ee84c340d
languageName: node
linkType: hard
-"@floating-ui/dom@npm:^1.6.3":
- version: 1.6.5
- resolution: "@floating-ui/dom@npm:1.6.5"
+"@floating-ui/dom@npm:^1.6.12":
+ version: 1.6.13
+ resolution: "@floating-ui/dom@npm:1.6.13"
dependencies:
- "@floating-ui/core": "npm:^1.0.0"
- "@floating-ui/utils": "npm:^0.2.0"
- checksum: 10c0/ebdc14806f786e60df8e7cc2c30bf9cd4d75fe734f06d755588bbdef2f60d0a0f21dffb14abdc58dea96e5577e2e366feca6d66ba962018efd1bc91a3ece4526
+ "@floating-ui/core": "npm:^1.6.0"
+ "@floating-ui/utils": "npm:^0.2.9"
+ checksum: 10c0/272242d2eb6238ffcee0cb1f3c66e0eafae804d5d7b449db5ecf904bc37d31ad96cf575a9e650b93c1190f64f49a684b1559d10e05ed3ec210628b19116991a9
languageName: node
linkType: hard
-"@floating-ui/utils@npm:^0.2.0":
- version: 0.2.2
- resolution: "@floating-ui/utils@npm:0.2.2"
- checksum: 10c0/b2becdcafdf395af1641348da0031ff1eaad2bc60c22e14bd3abad4acfe2c8401e03097173d89a2f646a99b75819a78ef21ebb2572cab0042a56dd654b0065cd
+"@floating-ui/utils@npm:^0.2.9":
+ version: 0.2.9
+ resolution: "@floating-ui/utils@npm:0.2.9"
+ checksum: 10c0/48bbed10f91cb7863a796cc0d0e917c78d11aeb89f98d03fc38d79e7eb792224a79f538ed8a2d5d5584511d4ca6354ef35f1712659fd569868e342df4398ad6f
languageName: node
linkType: hard
@@ -5780,42 +5932,62 @@ __metadata:
languageName: node
linkType: hard
-"@hashicorp/design-system-components@npm:^4.13.0":
- version: 4.13.1
- resolution: "@hashicorp/design-system-components@npm:4.13.1"
+"@hashicorp/design-system-components@npm:^4.18.1":
+ version: 4.18.1
+ resolution: "@hashicorp/design-system-components@npm:4.18.1"
dependencies:
- "@ember/render-modifiers": "npm:^2.0.5"
+ "@codemirror/commands": "npm:^6.8.0"
+ "@codemirror/lang-go": "npm:^6.0.1"
+ "@codemirror/lang-javascript": "npm:^6.2.2"
+ "@codemirror/lang-json": "npm:^6.0.1"
+ "@codemirror/lang-markdown": "npm:^6.3.2"
+ "@codemirror/lang-sql": "npm:^6.8.0"
+ "@codemirror/lang-yaml": "npm:^6.1.2"
+ "@codemirror/language": "npm:^6.10.3"
+ "@codemirror/legacy-modes": "npm:^6.4.2"
+ "@codemirror/lint": "npm:^6.8.4"
+ "@codemirror/state": "npm:^6.5.0"
+ "@codemirror/view": "npm:^6.36.2"
+ "@ember/render-modifiers": "npm:^2.1.0"
"@ember/string": "npm:^3.1.1"
"@ember/test-waiters": "npm:^3.1.0"
- "@embroider/addon-shim": "npm:^1.8.7"
- "@floating-ui/dom": "npm:^1.6.3"
- "@hashicorp/design-system-tokens": "npm:^2.2.1"
- "@hashicorp/flight-icons": "npm:^3.7.0"
- decorator-transforms: "npm:^1.1.0"
- ember-a11y-refocus: "npm:^4.1.3"
+ "@embroider/addon-shim": "npm:^1.9.0"
+ "@embroider/macros": "npm:^1.16.10"
+ "@embroider/util": "npm:^1.13.2"
+ "@floating-ui/dom": "npm:^1.6.12"
+ "@hashicorp/design-system-tokens": "npm:^2.3.0"
+ "@hashicorp/flight-icons": "npm:^3.10.0"
+ "@lezer/highlight": "npm:^1.2.1"
+ "@nullvoxpopuli/ember-composable-helpers": "npm:^5.2.9"
+ clipboard-polyfill: "npm:^4.1.1"
+ codemirror-lang-hcl: "npm:^0.0.0-beta.2"
+ decorator-transforms: "npm:^2.3.0"
+ ember-a11y-refocus: "npm:^4.1.4"
ember-cli-sass: "npm:^11.0.1"
- ember-composable-helpers: "npm:^5.0.0"
- ember-element-helper: "npm:^0.8.5"
- ember-focus-trap: "npm:^1.1.0"
+ ember-concurrency: "npm:^4.0.2"
+ ember-element-helper: "npm:^0.8.6"
+ ember-focus-trap: "npm:^1.1.1"
ember-get-config: "npm:^2.1.1"
- ember-modifier: "npm:^4.1.0"
- ember-power-select: "npm:^8.2.0"
+ ember-modifier: "npm:^4.2.0"
+ ember-power-select: "npm:^8.6.2"
ember-stargate: "npm:^0.4.3"
ember-style-modifier: "npm:^4.4.0"
ember-truth-helpers: "npm:^4.0.3"
- prismjs: "npm:^1.29.0"
- sass: "npm:^1.69.5"
+ luxon: "npm:^2.3.2 || ^3.4.2"
+ prismjs: "npm:^1.30.0"
+ sass: "npm:^1.83.0"
+ tabbable: "npm:^6.2.0"
tippy.js: "npm:^6.3.7"
peerDependencies:
ember-source: ^3.28.0 || ^4.0.0 || ^5.3.0
- checksum: 10c0/40ee62de9e8d8aa2f6686d9059f16cf9b07894757de573a5ac4e35a5e02f8020a5ee2fc3fda048b05ab64b9c1edbab756e7a493d1c9f8f059fad86ae5687ce2d
+ checksum: 10c0/d2f82198534fb2060bd425e9fa92655a86cc4c104a990526e95dd0179dcd12b7fba2350960b1ba2558150b1c524ce2e78612d779cfadf7a3d6022d852174b383
languageName: node
linkType: hard
-"@hashicorp/design-system-tokens@npm:^2.2.1":
- version: 2.2.1
- resolution: "@hashicorp/design-system-tokens@npm:2.2.1"
- checksum: 10c0/aa893c1e3d72eff5a6dee0065fcb8542b4a50d93ea95ccea552c79daa7ef8dcb3cfda2f129eaf1e12c45921e1ae9b1f79c782be75ea8fc30beaebfbefe811b97
+"@hashicorp/design-system-tokens@npm:^2.3.0":
+ version: 2.3.0
+ resolution: "@hashicorp/design-system-tokens@npm:2.3.0"
+ checksum: 10c0/df7ac4d014048cf307d7cc1b97e08255b9497f697a9c0286daacd8223ba1574f075d1221bc2f15a13ebfa9a3563ec83f04b3c89c11ba6ac7f13f67d3bef3e335
languageName: node
linkType: hard
@@ -5833,10 +6005,10 @@ __metadata:
languageName: node
linkType: hard
-"@hashicorp/flight-icons@npm:^3.7.0":
- version: 3.7.0
- resolution: "@hashicorp/flight-icons@npm:3.7.0"
- checksum: 10c0/9aaec7f0033e6a37755e3eccd1747272ca930fbc3b06db49d902447cc86a0fde3a421f69bc60438bf93f94bc686592db43fbd62483b78127baa2d43af8e912fb
+"@hashicorp/flight-icons@npm:^3.10.0":
+ version: 3.10.0
+ resolution: "@hashicorp/flight-icons@npm:3.10.0"
+ checksum: 10c0/f49b7d4be3eecfeef55c7bb4fa02902662813b0ada8488c32d831bdfe491cd154d5f239ad54774f3047d67c6f95d9340ccdb84bd01b15a9ea958f1ce8f38b43d
languageName: node
linkType: hard
@@ -6254,6 +6426,107 @@ __metadata:
languageName: node
linkType: hard
+"@lezer/common@npm:^1.0.0, @lezer/common@npm:^1.0.2, @lezer/common@npm:^1.1.0, @lezer/common@npm:^1.2.0, @lezer/common@npm:^1.2.1":
+ version: 1.2.3
+ resolution: "@lezer/common@npm:1.2.3"
+ checksum: 10c0/fe9f8e111080ef94037a34ca2af1221c8d01c1763ba5ecf708a286185c76119509a5d19d924c8842172716716ddce22d7834394670c4a9432f0ba9f3b7c0f50d
+ languageName: node
+ linkType: hard
+
+"@lezer/css@npm:^1.1.0, @lezer/css@npm:^1.1.7":
+ version: 1.1.11
+ resolution: "@lezer/css@npm:1.1.11"
+ dependencies:
+ "@lezer/common": "npm:^1.2.0"
+ "@lezer/highlight": "npm:^1.0.0"
+ "@lezer/lr": "npm:^1.0.0"
+ checksum: 10c0/88579811f10d73a54e1ef8daa9e3ddd2bbdb4531ae151141a8c1c938659d9c375b5fa46d2a7ab15b2e024f269057d561c57a4f06c758c5aac0918df4482bad7f
+ languageName: node
+ linkType: hard
+
+"@lezer/go@npm:^1.0.0":
+ version: 1.0.0
+ resolution: "@lezer/go@npm:1.0.0"
+ dependencies:
+ "@lezer/common": "npm:^1.2.0"
+ "@lezer/highlight": "npm:^1.0.0"
+ "@lezer/lr": "npm:^1.0.0"
+ checksum: 10c0/0a28007d04134f923d6a650da73dfca942bbe6b667351b582c5ef9541aacc6ac9fdb318cc57b560f962d49a85c1b1ddc8dd93caec8e21bfa4224ede40fcfc73d
+ languageName: node
+ linkType: hard
+
+"@lezer/highlight@npm:^1.0.0, @lezer/highlight@npm:^1.1.3, @lezer/highlight@npm:^1.2.0, @lezer/highlight@npm:^1.2.1":
+ version: 1.2.1
+ resolution: "@lezer/highlight@npm:1.2.1"
+ dependencies:
+ "@lezer/common": "npm:^1.0.0"
+ checksum: 10c0/51b4c08596a0dfeec6a7b7ed90a7f2743ab42e7e8ff8b89707fd042860e4e133dbd8243639fcaf077305ae6c303aa74e69794015eb16cb34741f5ac6721f283c
+ languageName: node
+ linkType: hard
+
+"@lezer/html@npm:^1.3.0":
+ version: 1.3.10
+ resolution: "@lezer/html@npm:1.3.10"
+ dependencies:
+ "@lezer/common": "npm:^1.2.0"
+ "@lezer/highlight": "npm:^1.0.0"
+ "@lezer/lr": "npm:^1.0.0"
+ checksum: 10c0/a7e782f9e9c5c5ffaa4a6fcf4ea5284e62c8fd3f0d378c86738b57077c002cbb013aeeb8aaae292b9517fea8b959216ce7af053269329962f6df2c7f9c2c8d99
+ languageName: node
+ linkType: hard
+
+"@lezer/javascript@npm:^1.0.0":
+ version: 1.4.21
+ resolution: "@lezer/javascript@npm:1.4.21"
+ dependencies:
+ "@lezer/common": "npm:^1.2.0"
+ "@lezer/highlight": "npm:^1.1.3"
+ "@lezer/lr": "npm:^1.3.0"
+ checksum: 10c0/ddbfee18aa87f6bffd3ac255b96c9e9ab61c9d44adfaba08c538e742e7264ecf6a238d253214d3330420d341a826f193232a9d4454126e75854e2bea2cbb703c
+ languageName: node
+ linkType: hard
+
+"@lezer/json@npm:^1.0.0":
+ version: 1.0.3
+ resolution: "@lezer/json@npm:1.0.3"
+ dependencies:
+ "@lezer/common": "npm:^1.2.0"
+ "@lezer/highlight": "npm:^1.0.0"
+ "@lezer/lr": "npm:^1.0.0"
+ checksum: 10c0/e91c957cc0825e927b55fbcd233d7ee0b39f9c2a89d9475489f394b7eba2b59e5f480d157a12d5cd6ae6f14bc99f9ccd8e8113baad498199ef1b13c49105f546
+ languageName: node
+ linkType: hard
+
+"@lezer/lr@npm:^1.0.0, @lezer/lr@npm:^1.3.0, @lezer/lr@npm:^1.4.0":
+ version: 1.4.2
+ resolution: "@lezer/lr@npm:1.4.2"
+ dependencies:
+ "@lezer/common": "npm:^1.0.0"
+ checksum: 10c0/22bb5d0d4b33d0de5eb0706b7e5b5f2d20f570e112d9110009bd35b62ff10f2eb4eff8da4cf373dd4ddf5e06a304120b8f039add7ed9997c981c13945d5329cd
+ languageName: node
+ linkType: hard
+
+"@lezer/markdown@npm:^1.0.0":
+ version: 1.4.2
+ resolution: "@lezer/markdown@npm:1.4.2"
+ dependencies:
+ "@lezer/common": "npm:^1.0.0"
+ "@lezer/highlight": "npm:^1.0.0"
+ checksum: 10c0/b3916a50f94cdf382d1742b2b84fc14d4d531351b79c2c1580a451fa8704653aba083ea1ad4ef631faf548a82fe805f617175123ba26384c5aa9388703191dd7
+ languageName: node
+ linkType: hard
+
+"@lezer/yaml@npm:^1.0.0":
+ version: 1.0.3
+ resolution: "@lezer/yaml@npm:1.0.3"
+ dependencies:
+ "@lezer/common": "npm:^1.2.0"
+ "@lezer/highlight": "npm:^1.0.0"
+ "@lezer/lr": "npm:^1.4.0"
+ checksum: 10c0/cef3d0c0a2c48a7e0f36ccc0af948da9394d17b164dcbaf0187d9b472fd4f628b3107d7a4041045181488f1966a94ae65640c932fc8d3bf8c3597813cfb86ae0
+ languageName: node
+ linkType: hard
+
"@lint-todo/utils@npm:^13.0.3":
version: 13.0.3
resolution: "@lint-todo/utils@npm:13.0.3"
@@ -6278,6 +6551,13 @@ __metadata:
languageName: node
linkType: hard
+"@marijn/find-cluster-break@npm:^1.0.0":
+ version: 1.0.2
+ resolution: "@marijn/find-cluster-break@npm:1.0.2"
+ checksum: 10c0/1a17a60b16083cc5f7ce89d7b7d8aa87ce4099723e3e9e34e229ef2cd8a980e69d481ca8ee90ffedfec5119af1aed581642fb60ed0365e7e90634c81ea6b630f
+ languageName: node
+ linkType: hard
+
"@miragejs/pretender-node-polyfill@npm:^0.1.0":
version: 0.1.2
resolution: "@miragejs/pretender-node-polyfill@npm:0.1.2"
@@ -6363,6 +6643,161 @@ __metadata:
languageName: node
linkType: hard
+"@nullvoxpopuli/ember-composable-helpers@npm:^5.2.9":
+ version: 5.2.10
+ resolution: "@nullvoxpopuli/ember-composable-helpers@npm:5.2.10"
+ dependencies:
+ "@embroider/addon-shim": "npm:^1.9.0"
+ decorator-transforms: "npm:^2.3.0"
+ ember-functions-as-helper-polyfill: "npm:^2.1.2"
+ checksum: 10c0/16907bec08f0840ff89023d4fbedeb65385270522c27e2f111a8dff5a2bc166067769b325ef5ab3e2c59e0ce5068dd5fc0706a2d5cb1343a4b6a5b9f52f36c57
+ languageName: node
+ linkType: hard
+
+"@parcel/watcher-android-arm64@npm:2.5.1":
+ version: 2.5.1
+ resolution: "@parcel/watcher-android-arm64@npm:2.5.1"
+ conditions: os=android & cpu=arm64
+ languageName: node
+ linkType: hard
+
+"@parcel/watcher-darwin-arm64@npm:2.5.1":
+ version: 2.5.1
+ resolution: "@parcel/watcher-darwin-arm64@npm:2.5.1"
+ conditions: os=darwin & cpu=arm64
+ languageName: node
+ linkType: hard
+
+"@parcel/watcher-darwin-x64@npm:2.5.1":
+ version: 2.5.1
+ resolution: "@parcel/watcher-darwin-x64@npm:2.5.1"
+ conditions: os=darwin & cpu=x64
+ languageName: node
+ linkType: hard
+
+"@parcel/watcher-freebsd-x64@npm:2.5.1":
+ version: 2.5.1
+ resolution: "@parcel/watcher-freebsd-x64@npm:2.5.1"
+ conditions: os=freebsd & cpu=x64
+ languageName: node
+ linkType: hard
+
+"@parcel/watcher-linux-arm-glibc@npm:2.5.1":
+ version: 2.5.1
+ resolution: "@parcel/watcher-linux-arm-glibc@npm:2.5.1"
+ conditions: os=linux & cpu=arm & libc=glibc
+ languageName: node
+ linkType: hard
+
+"@parcel/watcher-linux-arm-musl@npm:2.5.1":
+ version: 2.5.1
+ resolution: "@parcel/watcher-linux-arm-musl@npm:2.5.1"
+ conditions: os=linux & cpu=arm & libc=musl
+ languageName: node
+ linkType: hard
+
+"@parcel/watcher-linux-arm64-glibc@npm:2.5.1":
+ version: 2.5.1
+ resolution: "@parcel/watcher-linux-arm64-glibc@npm:2.5.1"
+ conditions: os=linux & cpu=arm64 & libc=glibc
+ languageName: node
+ linkType: hard
+
+"@parcel/watcher-linux-arm64-musl@npm:2.5.1":
+ version: 2.5.1
+ resolution: "@parcel/watcher-linux-arm64-musl@npm:2.5.1"
+ conditions: os=linux & cpu=arm64 & libc=musl
+ languageName: node
+ linkType: hard
+
+"@parcel/watcher-linux-x64-glibc@npm:2.5.1":
+ version: 2.5.1
+ resolution: "@parcel/watcher-linux-x64-glibc@npm:2.5.1"
+ conditions: os=linux & cpu=x64 & libc=glibc
+ languageName: node
+ linkType: hard
+
+"@parcel/watcher-linux-x64-musl@npm:2.5.1":
+ version: 2.5.1
+ resolution: "@parcel/watcher-linux-x64-musl@npm:2.5.1"
+ conditions: os=linux & cpu=x64 & libc=musl
+ languageName: node
+ linkType: hard
+
+"@parcel/watcher-win32-arm64@npm:2.5.1":
+ version: 2.5.1
+ resolution: "@parcel/watcher-win32-arm64@npm:2.5.1"
+ conditions: os=win32 & cpu=arm64
+ languageName: node
+ linkType: hard
+
+"@parcel/watcher-win32-ia32@npm:2.5.1":
+ version: 2.5.1
+ resolution: "@parcel/watcher-win32-ia32@npm:2.5.1"
+ conditions: os=win32 & cpu=ia32
+ languageName: node
+ linkType: hard
+
+"@parcel/watcher-win32-x64@npm:2.5.1":
+ version: 2.5.1
+ resolution: "@parcel/watcher-win32-x64@npm:2.5.1"
+ conditions: os=win32 & cpu=x64
+ languageName: node
+ linkType: hard
+
+"@parcel/watcher@npm:^2.4.1":
+ version: 2.5.1
+ resolution: "@parcel/watcher@npm:2.5.1"
+ dependencies:
+ "@parcel/watcher-android-arm64": "npm:2.5.1"
+ "@parcel/watcher-darwin-arm64": "npm:2.5.1"
+ "@parcel/watcher-darwin-x64": "npm:2.5.1"
+ "@parcel/watcher-freebsd-x64": "npm:2.5.1"
+ "@parcel/watcher-linux-arm-glibc": "npm:2.5.1"
+ "@parcel/watcher-linux-arm-musl": "npm:2.5.1"
+ "@parcel/watcher-linux-arm64-glibc": "npm:2.5.1"
+ "@parcel/watcher-linux-arm64-musl": "npm:2.5.1"
+ "@parcel/watcher-linux-x64-glibc": "npm:2.5.1"
+ "@parcel/watcher-linux-x64-musl": "npm:2.5.1"
+ "@parcel/watcher-win32-arm64": "npm:2.5.1"
+ "@parcel/watcher-win32-ia32": "npm:2.5.1"
+ "@parcel/watcher-win32-x64": "npm:2.5.1"
+ detect-libc: "npm:^1.0.3"
+ is-glob: "npm:^4.0.3"
+ micromatch: "npm:^4.0.5"
+ node-addon-api: "npm:^7.0.0"
+ node-gyp: "npm:latest"
+ dependenciesMeta:
+ "@parcel/watcher-android-arm64":
+ optional: true
+ "@parcel/watcher-darwin-arm64":
+ optional: true
+ "@parcel/watcher-darwin-x64":
+ optional: true
+ "@parcel/watcher-freebsd-x64":
+ optional: true
+ "@parcel/watcher-linux-arm-glibc":
+ optional: true
+ "@parcel/watcher-linux-arm-musl":
+ optional: true
+ "@parcel/watcher-linux-arm64-glibc":
+ optional: true
+ "@parcel/watcher-linux-arm64-musl":
+ optional: true
+ "@parcel/watcher-linux-x64-glibc":
+ optional: true
+ "@parcel/watcher-linux-x64-musl":
+ optional: true
+ "@parcel/watcher-win32-arm64":
+ optional: true
+ "@parcel/watcher-win32-ia32":
+ optional: true
+ "@parcel/watcher-win32-x64":
+ optional: true
+ checksum: 10c0/8f35073d0c0b34a63d4c8d2213482f0ebc6a25de7b2cdd415d19cb929964a793cb285b68d1d50bfb732b070b3c82a2fdb4eb9c250eab709a1cd9d63345455a82
+ languageName: node
+ linkType: hard
+
"@pkgjs/parseargs@npm:^0.11.0":
version: 0.11.0
resolution: "@pkgjs/parseargs@npm:0.11.0"
@@ -7886,13 +8321,6 @@ __metadata:
languageName: node
linkType: hard
-"babel-import-util@npm:^1.1.0":
- version: 1.1.0
- resolution: "babel-import-util@npm:1.1.0"
- checksum: 10c0/ad9c0bec7958dde954d010883dba14cbcf860a6f47789c2546f2e65f9be870d2729ecf3be167a615ec7aab92732d578db3f58d5439341f177c0173f37f7bef73
- languageName: node
- linkType: hard
-
"babel-import-util@npm:^1.3.0":
version: 1.3.0
resolution: "babel-import-util@npm:1.3.0"
@@ -9520,6 +9948,15 @@ __metadata:
languageName: node
linkType: hard
+"chokidar@npm:^4.0.0":
+ version: 4.0.3
+ resolution: "chokidar@npm:4.0.3"
+ dependencies:
+ readdirp: "npm:^4.0.1"
+ checksum: 10c0/a58b9df05bb452f7d105d9e7229ac82fa873741c0c40ddcc7bb82f8a909fbe3f7814c9ebe9bc9a2bef9b737c0ec6e2d699d179048ef06ad3ec46315df0ebe6ad
+ languageName: node
+ linkType: hard
+
"chownr@npm:^2.0.0":
version: 2.0.0
resolution: "chownr@npm:2.0.0"
@@ -9697,6 +10134,13 @@ __metadata:
languageName: node
linkType: hard
+"clipboard-polyfill@npm:^4.1.1":
+ version: 4.1.1
+ resolution: "clipboard-polyfill@npm:4.1.1"
+ checksum: 10c0/951f1e9f76687cf3633c1f7744beddda3d226d82fb7be821759cce83a87439f5f6e13370af166321579153d35ffcb5173dd2d6e067c22ebe5215c28632f1c566
+ languageName: node
+ linkType: hard
+
"clipboard@npm:^2.0.11":
version: 2.0.11
resolution: "clipboard@npm:2.0.11"
@@ -9771,6 +10215,17 @@ __metadata:
languageName: node
linkType: hard
+"codemirror-lang-hcl@npm:^0.0.0-beta.2":
+ version: 0.0.0-beta.2
+ resolution: "codemirror-lang-hcl@npm:0.0.0-beta.2"
+ dependencies:
+ "@codemirror/language": "npm:^6.0.0"
+ "@lezer/highlight": "npm:^1.0.0"
+ "@lezer/lr": "npm:^1.0.0"
+ checksum: 10c0/a87886f4b027a10a8917ca8b9b46b624bb43a8b6d037c8b9df4cd3bedf8c555dbb019cad9479630f7f70f7317f594de82c21b4b3b2496cb7d1abf2eeca6d1119
+ languageName: node
+ linkType: hard
+
"codemirror@npm:5.65.7":
version: 5.65.7
resolution: "codemirror@npm:5.65.7"
@@ -10255,6 +10710,13 @@ __metadata:
languageName: node
linkType: hard
+"crelt@npm:^1.0.5":
+ version: 1.0.6
+ resolution: "crelt@npm:1.0.6"
+ checksum: 10c0/e0fb76dff50c5eb47f2ea9b786c17f9425c66276025adee80876bdbf4a84ab72e899e56d3928431ab0cb057a105ef704df80fe5726ef0f7b1658f815521bdf09
+ languageName: node
+ linkType: hard
+
"cross-dirname@npm:^0.1.0":
version: 0.1.0
resolution: "cross-dirname@npm:0.1.0"
@@ -10559,7 +11021,7 @@ __metadata:
languageName: node
linkType: hard
-"decorator-transforms@npm:^1.0.1, decorator-transforms@npm:^1.1.0":
+"decorator-transforms@npm:^1.0.1":
version: 1.2.1
resolution: "decorator-transforms@npm:1.2.1"
dependencies:
@@ -10579,6 +11041,16 @@ __metadata:
languageName: node
linkType: hard
+"decorator-transforms@npm:^2.3.0":
+ version: 2.3.0
+ resolution: "decorator-transforms@npm:2.3.0"
+ dependencies:
+ "@babel/plugin-syntax-decorators": "npm:^7.23.3"
+ babel-import-util: "npm:^3.0.0"
+ checksum: 10c0/c7741b81f0061e0f4e8e660db6d1c3e7e176896ca71d0cbd478ad3bce85f7354bbe5747afcbbb6f36bd6341af27fd2c1281b9cb9be72ed07a42b8b70ecd7dce2
+ languageName: node
+ linkType: hard
+
"dedent@npm:^1.0.0":
version: 1.5.3
resolution: "dedent@npm:1.5.3"
@@ -10775,6 +11247,15 @@ __metadata:
languageName: node
linkType: hard
+"detect-libc@npm:^1.0.3":
+ version: 1.0.3
+ resolution: "detect-libc@npm:1.0.3"
+ bin:
+ detect-libc: ./bin/detect-libc.js
+ checksum: 10c0/4da0deae9f69e13bc37a0902d78bf7169480004b1fed3c19722d56cff578d16f0e11633b7fbf5fb6249181236c72e90024cbd68f0b9558ae06e281f47326d50d
+ languageName: node
+ linkType: hard
+
"detect-libc@npm:^2.0.1":
version: 2.0.2
resolution: "detect-libc@npm:2.0.2"
@@ -11042,7 +11523,7 @@ __metadata:
languageName: node
linkType: hard
-"ember-a11y-refocus@npm:^4.1.3":
+"ember-a11y-refocus@npm:^4.1.4":
version: 4.1.4
resolution: "ember-a11y-refocus@npm:4.1.4"
dependencies:
@@ -11941,7 +12422,7 @@ __metadata:
languageName: node
linkType: hard
-"ember-concurrency@npm:^4.0.3":
+"ember-concurrency@npm:^4.0.2, ember-concurrency@npm:^4.0.3":
version: 4.0.3
resolution: "ember-concurrency@npm:4.0.3"
dependencies:
@@ -12046,15 +12527,14 @@ __metadata:
languageName: node
linkType: hard
-"ember-element-helper@npm:^0.8.5":
- version: 0.8.5
- resolution: "ember-element-helper@npm:0.8.5"
+"ember-element-helper@npm:^0.8.6":
+ version: 0.8.7
+ resolution: "ember-element-helper@npm:0.8.7"
dependencies:
- "@embroider/addon-shim": "npm:1.8.3"
- "@embroider/util": "npm:^1.0.0"
+ "@embroider/addon-shim": "npm:^1.8.3"
peerDependencies:
ember-source: ^3.8 || ^4.0.0 || >= 5.0.0
- checksum: 10c0/601269155e06114d8475c99b02452751561324fef4ef26d31dc510306210493a231600b42589499d4a5a68ebc9e1c097716df64124d0bc94883e6c0a2bea6f25
+ checksum: 10c0/7e1f4a5e381927254b9c39e93c897786b8efe7f15fb27f4a92649ff6c97ffe1be0e47540d3f23aba412f7e54f67dffcb8da91acf7d1e3f44b36f5cae035ae758
languageName: node
linkType: hard
@@ -12117,15 +12597,15 @@ __metadata:
languageName: node
linkType: hard
-"ember-focus-trap@npm:^1.1.0":
- version: 1.1.0
- resolution: "ember-focus-trap@npm:1.1.0"
+"ember-focus-trap@npm:^1.1.1":
+ version: 1.1.1
+ resolution: "ember-focus-trap@npm:1.1.1"
dependencies:
"@embroider/addon-shim": "npm:^1.0.0"
focus-trap: "npm:^6.7.1"
peerDependencies:
- ember-source: ^4.0.0 || ^5.0.0
- checksum: 10c0/6777db639fcc4edd684a427a353619b04f22dc3e2de93bf06a8512aabf0f2d1a2d6ebde7fefa8784107b522e0d6c2c1fb54e55a92133a9dd9da57b464e0bf050
+ ember-source: ">= 4.0.0"
+ checksum: 10c0/f48837802f763dbd0feb5e73bc0512bcadf7b324d5473447c747609330a50de311d0d27cbef2b8fe16ac9f06b13483e761ba5092d7c90a562b2120c16ac17edc
languageName: node
linkType: hard
@@ -12303,7 +12783,7 @@ __metadata:
languageName: node
linkType: hard
-"ember-modifier@npm:^3.2.7 || ^4.1.0":
+"ember-modifier@npm:^3.2.7 || ^4.1.0, ember-modifier@npm:^4.2.0":
version: 4.2.0
resolution: "ember-modifier@npm:4.2.0"
dependencies:
@@ -12339,25 +12819,25 @@ __metadata:
languageName: node
linkType: hard
-"ember-power-select@npm:^8.2.0":
- version: 8.2.0
- resolution: "ember-power-select@npm:8.2.0"
+"ember-power-select@npm:^8.6.2":
+ version: 8.7.0
+ resolution: "ember-power-select@npm:8.7.0"
dependencies:
- "@embroider/addon-shim": "npm:^1.8.7"
- "@embroider/util": "npm:^1.13.1"
- decorator-transforms: "npm:^1.1.0"
+ "@embroider/addon-shim": "npm:^1.9.0"
+ "@embroider/util": "npm:^1.13.2"
+ decorator-transforms: "npm:^2.3.0"
ember-assign-helper: "npm:^0.5.0"
ember-lifeline: "npm:^7.0.0"
- ember-modifier: "npm:^4.1.0"
+ ember-modifier: "npm:^4.2.0"
ember-truth-helpers: "npm:^4.0.3"
peerDependencies:
- "@ember/test-helpers": ^2.9.4 || ^3.2.1
- "@glimmer/component": ^1.1.2
+ "@ember/test-helpers": ^2.9.4 || ^3.2.1 || ^4.0.2 || ^5.0.0
+ "@glimmer/component": ^1.1.2 || ^2.0.0
"@glimmer/tracking": ^1.1.2
- ember-basic-dropdown: ^8.1.0
+ ember-basic-dropdown: ^8.5.0
ember-concurrency: ^4.0.2
ember-source: ^3.28.0 || ^4.0.0 || >=5.0.0
- checksum: 10c0/19312b83d928027187bfccf7120489ce230d12265f3338e3dcc65b0456acfb5a20a0cf8924c042582ffae593ff9370e1bfd847f72f71ef6da181e62b61a27466
+ checksum: 10c0/1d635b6f5bc549dd25b48cf00a71e7a13a7fcef8efb5d95a3a82687f08b9c3e1181fc9890c541d4118d468638a857fa5f9b3daa55d57a9b938b5b88ca1c43508
languageName: node
linkType: hard
@@ -15268,6 +15748,13 @@ __metadata:
languageName: node
linkType: hard
+"immutable@npm:^5.0.2":
+ version: 5.1.1
+ resolution: "immutable@npm:5.1.1"
+ checksum: 10c0/5fd129ee9e448884003cc4f9e43bb91bab3b39dfeb3b49ddfb8bd563e0620eb47ae1f5b3ef96615d3ec38b52ab9a966dcacf9e39df00ed1a8ad062ddfba01cdf
+ languageName: node
+ linkType: hard
+
"import-fresh@npm:^3.2.1":
version: 3.3.0
resolution: "import-fresh@npm:3.3.0"
@@ -17351,6 +17838,13 @@ __metadata:
languageName: node
linkType: hard
+"luxon@npm:^2.3.2 || ^3.4.2":
+ version: 3.6.1
+ resolution: "luxon@npm:3.6.1"
+ checksum: 10c0/906d57a9dc4d1de9383f2e9223e378c298607c1b4d17b6657b836a3cd120feb1c1de3b5d06d846a3417e1ca764de8476e8c23b3cd4083b5cdb870adcb06a99d5
+ languageName: node
+ linkType: hard
+
"magic-string@npm:^0.25.7":
version: 0.25.7
resolution: "magic-string@npm:0.25.7"
@@ -18387,6 +18881,15 @@ __metadata:
languageName: node
linkType: hard
+"node-addon-api@npm:^7.0.0":
+ version: 7.1.1
+ resolution: "node-addon-api@npm:7.1.1"
+ dependencies:
+ node-gyp: "npm:latest"
+ checksum: 10c0/fb32a206276d608037fa1bcd7e9921e177fe992fc610d098aa3128baca3c0050fc1e014fa007e9b3874cf865ddb4f5bd9f43ccb7cbbbe4efaff6a83e920b17e9
+ languageName: node
+ linkType: hard
+
"node-api-version@npm:^0.2.0":
version: 0.2.0
resolution: "node-api-version@npm:0.2.0"
@@ -19629,13 +20132,20 @@ __metadata:
languageName: node
linkType: hard
-"prismjs@npm:^1.27.0, prismjs@npm:^1.29.0":
+"prismjs@npm:^1.27.0":
version: 1.29.0
resolution: "prismjs@npm:1.29.0"
checksum: 10c0/d906c4c4d01b446db549b4f57f72d5d7e6ccaca04ecc670fb85cea4d4b1acc1283e945a9cbc3d81819084a699b382f970e02f9d1378e14af9808d366d9ed7ec6
languageName: node
linkType: hard
+"prismjs@npm:^1.30.0":
+ version: 1.30.0
+ resolution: "prismjs@npm:1.30.0"
+ checksum: 10c0/f56205bfd58ef71ccfcbcb691fd0eb84adc96c6ff21b0b69fc6fdcf02be42d6ef972ba4aed60466310de3d67733f6a746f89f2fb79c00bf217406d465b3e8f23
+ languageName: node
+ linkType: hard
+
"prismjs@npm:~1.27.0":
version: 1.27.0
resolution: "prismjs@npm:1.27.0"
@@ -20096,6 +20606,13 @@ __metadata:
languageName: node
linkType: hard
+"readdirp@npm:^4.0.1":
+ version: 4.1.2
+ resolution: "readdirp@npm:4.1.2"
+ checksum: 10c0/60a14f7619dec48c9c850255cd523e2717001b0e179dc7037cfa0895da7b9e9ab07532d324bfb118d73a710887d1e35f79c495fa91582784493e085d18c72c62
+ languageName: node
+ linkType: hard
+
"readdirp@npm:~3.6.0":
version: 3.6.0
resolution: "readdirp@npm:3.6.0"
@@ -20826,7 +21343,7 @@ __metadata:
"@embroider/test-setup": "npm:^2.1.1"
"@glimmer/component": "npm:^1.1.2"
"@glimmer/tracking": "npm:^1.1.2"
- "@hashicorp/design-system-components": "npm:^4.13.0"
+ "@hashicorp/design-system-components": "npm:^4.18.1"
babel-loader: "npm:^9.2.1"
babel-plugin-ember-modules-api-polyfill: "npm:^2.12.0"
babel-plugin-htmlbars-inline-precompile: "npm:3"
@@ -21040,6 +21557,23 @@ __metadata:
languageName: node
linkType: hard
+"sass@npm:^1.83.0":
+ version: 1.86.2
+ resolution: "sass@npm:1.86.2"
+ dependencies:
+ "@parcel/watcher": "npm:^2.4.1"
+ chokidar: "npm:^4.0.0"
+ immutable: "npm:^5.0.2"
+ source-map-js: "npm:>=0.6.2 <2.0.0"
+ dependenciesMeta:
+ "@parcel/watcher":
+ optional: true
+ bin:
+ sass: sass.js
+ checksum: 10c0/fe40b63a19e867f460369d495bcdc979598c0b105c9d52164a7e9cc4e12ab91c27337702a1b58575f7da8fd08256b85fd2f34cc8275eb7c57699bfc5029f54a3
+ languageName: node
+ linkType: hard
+
"sax@npm:~1.2.4":
version: 1.2.4
resolution: "sax@npm:1.2.4"
@@ -22103,6 +22637,13 @@ __metadata:
languageName: node
linkType: hard
+"style-mod@npm:^4.0.0, style-mod@npm:^4.1.0":
+ version: 4.1.2
+ resolution: "style-mod@npm:4.1.2"
+ checksum: 10c0/ad4d870b3642b0e42ecc7be0e106dd14b7af11985e34fee8de34e5e38c3214bfc96fa7055acea86d75a3a59ddea3f6a8c6641001a66494d7df72d09685e3fadb
+ languageName: node
+ linkType: hard
+
"style-search@npm:^0.1.0":
version: 0.1.0
resolution: "style-search@npm:0.1.0"
@@ -22412,6 +22953,13 @@ __metadata:
languageName: node
linkType: hard
+"tabbable@npm:^6.2.0":
+ version: 6.2.0
+ resolution: "tabbable@npm:6.2.0"
+ checksum: 10c0/ced8b38f05f2de62cd46836d77c2646c42b8c9713f5bd265daf0e78ff5ac73d3ba48a7ca45f348bafeef29b23da7187c72250742d37627883ef89cbd7fa76898
+ languageName: node
+ linkType: hard
+
"table@npm:^6.8.1":
version: 6.8.1
resolution: "table@npm:6.8.1"
@@ -23372,6 +23920,13 @@ __metadata:
languageName: node
linkType: hard
+"w3c-keyname@npm:^2.2.4":
+ version: 2.2.8
+ resolution: "w3c-keyname@npm:2.2.8"
+ checksum: 10c0/37cf335c90efff31672ebb345577d681e2177f7ff9006a9ad47c68c5a9d265ba4a7b39d6c2599ceea639ca9315584ce4bd9c9fbf7a7217bfb7a599e71943c4c4
+ languageName: node
+ linkType: hard
+
"walk-sync@npm:^0.2.5":
version: 0.2.7
resolution: "walk-sync@npm:0.2.7"