From a97f66e0111345eb6c223ad3ff27a2108ee9e430 Mon Sep 17 00:00:00 2001 From: Dharini Jeeva Date: Wed, 17 Jul 2024 10:22:52 -0700 Subject: [PATCH 01/14] =?UTF-8?q?feat:=20=F0=9F=8E=B8=20settings=20page=20?= =?UTF-8?q?(#2395)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * feat: 🎸 settings page --- .../scopes/scope/projects/settings/index.js | 8 ++ ui/desktop/app/router.js | 3 + .../routes/scopes/scope/projects/settings.js | 8 ++ .../scopes/scope/projects/settings/index.js | 8 ++ .../app/templates/scopes/scope/projects.hbs | 4 + .../scopes/scope/projects/settings.hbs | 14 ++++ .../scopes/scope/projects/settings/index.hbs | 6 ++ .../projects/settings/index-test.js | 84 +++++++++++++++++++ .../scope/projects/settings/index-test.js | 22 +++++ .../scopes/scope/projects/settings-test.js | 16 ++++ .../scope/projects/settings/index-test.js | 16 ++++ 11 files changed, 189 insertions(+) create mode 100644 ui/desktop/app/controllers/scopes/scope/projects/settings/index.js create mode 100644 ui/desktop/app/routes/scopes/scope/projects/settings.js create mode 100644 ui/desktop/app/routes/scopes/scope/projects/settings/index.js create mode 100644 ui/desktop/app/templates/scopes/scope/projects/settings.hbs create mode 100644 ui/desktop/app/templates/scopes/scope/projects/settings/index.hbs create mode 100644 ui/desktop/tests/acceptance/projects/settings/index-test.js create mode 100644 ui/desktop/tests/unit/controllers/scopes/scope/projects/settings/index-test.js create mode 100644 ui/desktop/tests/unit/routes/scopes/scope/projects/settings-test.js create mode 100644 ui/desktop/tests/unit/routes/scopes/scope/projects/settings/index-test.js diff --git a/ui/desktop/app/controllers/scopes/scope/projects/settings/index.js b/ui/desktop/app/controllers/scopes/scope/projects/settings/index.js new file mode 100644 index 0000000000..b345316375 --- /dev/null +++ b/ui/desktop/app/controllers/scopes/scope/projects/settings/index.js @@ -0,0 +1,8 @@ +/** + * Copyright (c) HashiCorp, Inc. + * SPDX-License-Identifier: BUSL-1.1 + */ + +import Controller from '@ember/controller'; + +export default class ScopesScopeProjectsSettingsIndexController extends Controller {} diff --git a/ui/desktop/app/router.js b/ui/desktop/app/router.js index 2e841f68e4..12cb417bf3 100644 --- a/ui/desktop/app/router.js +++ b/ui/desktop/app/router.js @@ -26,6 +26,9 @@ Router.map(function () { this.route('sessions', function () { this.route('session', { path: ':session_id' }, function () {}); }); + this.route('settings', function () { + this.route('setting', function () {}); + }); }); }); }); diff --git a/ui/desktop/app/routes/scopes/scope/projects/settings.js b/ui/desktop/app/routes/scopes/scope/projects/settings.js new file mode 100644 index 0000000000..d8c221a80e --- /dev/null +++ b/ui/desktop/app/routes/scopes/scope/projects/settings.js @@ -0,0 +1,8 @@ +/** + * Copyright (c) HashiCorp, Inc. + * SPDX-License-Identifier: BUSL-1.1 + */ + +import Route from '@ember/routing/route'; + +export default class ScopesScopeProjectsSettingsRoute extends Route {} diff --git a/ui/desktop/app/routes/scopes/scope/projects/settings/index.js b/ui/desktop/app/routes/scopes/scope/projects/settings/index.js new file mode 100644 index 0000000000..531ec047aa --- /dev/null +++ b/ui/desktop/app/routes/scopes/scope/projects/settings/index.js @@ -0,0 +1,8 @@ +/** + * Copyright (c) HashiCorp, Inc. + * SPDX-License-Identifier: BUSL-1.1 + */ + +import Route from '@ember/routing/route'; + +export default class ScopesScopeProjectsSettingsIndexRoute extends Route {} diff --git a/ui/desktop/app/templates/scopes/scope/projects.hbs b/ui/desktop/app/templates/scopes/scope/projects.hbs index 6b190ac882..93ea576cca 100644 --- a/ui/desktop/app/templates/scopes/scope/projects.hbs +++ b/ui/desktop/app/templates/scopes/scope/projects.hbs @@ -15,6 +15,10 @@ {{t 'resources.session.title_plural'}} + + + {{t 'titles.settings'}} + diff --git a/ui/desktop/app/templates/scopes/scope/projects/settings.hbs b/ui/desktop/app/templates/scopes/scope/projects/settings.hbs new file mode 100644 index 0000000000..73c06654bf --- /dev/null +++ b/ui/desktop/app/templates/scopes/scope/projects/settings.hbs @@ -0,0 +1,14 @@ +{{! + Copyright (c) HashiCorp, Inc. + SPDX-License-Identifier: BUSL-1.1 +}} + + + +

+ {{t 'titles.settings'}} + {{! TODO: Add a link to the settings documentation }} + {{! }} +

+
+
\ No newline at end of file diff --git a/ui/desktop/app/templates/scopes/scope/projects/settings/index.hbs b/ui/desktop/app/templates/scopes/scope/projects/settings/index.hbs new file mode 100644 index 0000000000..d14e217751 --- /dev/null +++ b/ui/desktop/app/templates/scopes/scope/projects/settings/index.hbs @@ -0,0 +1,6 @@ +{{! + Copyright (c) HashiCorp, Inc. + SPDX-License-Identifier: BUSL-1.1 +}} + +{{outlet}} \ No newline at end of file diff --git a/ui/desktop/tests/acceptance/projects/settings/index-test.js b/ui/desktop/tests/acceptance/projects/settings/index-test.js new file mode 100644 index 0000000000..01f5b4950b --- /dev/null +++ b/ui/desktop/tests/acceptance/projects/settings/index-test.js @@ -0,0 +1,84 @@ +/** + * Copyright (c) HashiCorp, Inc. + * SPDX-License-Identifier: BUSL-1.1 + */ + +import { module, test } from 'qunit'; +import { currentURL, click, visit } from '@ember/test-helpers'; +import { setupApplicationTest } from 'ember-qunit'; +import setupMirage from 'ember-cli-mirage/test-support/setup-mirage'; +import { authenticateSession } from 'ember-simple-auth/test-support'; +import WindowMockIPC from '../../../helpers/window-mock-ipc'; + +module('Acceptance | projects | settings | index', function (hooks) { + setupApplicationTest(hooks); + setupMirage(hooks); + + const instances = { + scopes: { + global: null, + org: null, + project: null, + }, + authMethods: { + global: null, + }, + target: null, + target2: null, + session: null, + }; + + const urls = { + scopes: { + global: null, + org: null, + }, + authenticate: { + global: null, + methods: { + global: null, + }, + }, + projects: null, + targets: null, + settings: null, + }; + + const setDefaultClusterUrl = (test) => { + const windowOrigin = window.location.origin; + const clusterUrl = test.owner.lookup('service:clusterUrl'); + clusterUrl.rendererClusterUrl = windowOrigin; + }; + + hooks.beforeEach(function () { + authenticateSession(); + // Generate scopes + instances.scopes.global = this.server.create('scope', { + id: 'global', + name: 'Global', + }); + const globalScope = { id: 'global', type: 'global' }; + instances.scopes.org = this.server.create('scope', { + type: 'org', + scope: globalScope, + }); + const orgScope = { id: instances.scopes.org.id, type: 'org' }; + instances.scopes.project = this.server.create('scope', { + type: 'project', + scope: orgScope, + }); + urls.scopes.org = `/scopes/${instances.scopes.org.id}`; + urls.scopes.global = `/scopes/${instances.scopes.global.id}`; + urls.projects = `${urls.scopes.org}/projects`; + urls.settings = `${urls.projects}/settings`; + + this.owner.register('service:browser/window', WindowMockIPC); + setDefaultClusterUrl(this); + }); + + test('can navigate to the settings page', async function (assert) { + await visit(urls.projects); + await click(`[href="${urls.settings}"]`); + assert.strictEqual(currentURL(), urls.settings); + }); +}); diff --git a/ui/desktop/tests/unit/controllers/scopes/scope/projects/settings/index-test.js b/ui/desktop/tests/unit/controllers/scopes/scope/projects/settings/index-test.js new file mode 100644 index 0000000000..c642cd49f0 --- /dev/null +++ b/ui/desktop/tests/unit/controllers/scopes/scope/projects/settings/index-test.js @@ -0,0 +1,22 @@ +/** + * Copyright (c) HashiCorp, Inc. + * SPDX-License-Identifier: BUSL-1.1 + */ + +import { module, test } from 'qunit'; +import { setupTest } from 'ember-qunit'; + +module( + 'Unit | Controller | scopes/scope/projects/settings/index', + function (hooks) { + setupTest(hooks); + + // TODO: Replace this with your real tests. + test('it exists', function (assert) { + let controller = this.owner.lookup( + 'controller:scopes/scope/projects/settings/index', + ); + assert.ok(controller); + }); + }, +); diff --git a/ui/desktop/tests/unit/routes/scopes/scope/projects/settings-test.js b/ui/desktop/tests/unit/routes/scopes/scope/projects/settings-test.js new file mode 100644 index 0000000000..29f4a85dd6 --- /dev/null +++ b/ui/desktop/tests/unit/routes/scopes/scope/projects/settings-test.js @@ -0,0 +1,16 @@ +/** + * Copyright (c) HashiCorp, Inc. + * SPDX-License-Identifier: BUSL-1.1 + */ + +import { module, test } from 'qunit'; +import { setupTest } from 'ember-qunit'; + +module('Unit | Route | scopes/scope/projects/settings', function (hooks) { + setupTest(hooks); + + test('it exists', function (assert) { + let route = this.owner.lookup('route:scopes/scope/projects/settings'); + assert.ok(route); + }); +}); diff --git a/ui/desktop/tests/unit/routes/scopes/scope/projects/settings/index-test.js b/ui/desktop/tests/unit/routes/scopes/scope/projects/settings/index-test.js new file mode 100644 index 0000000000..e27c7aca1d --- /dev/null +++ b/ui/desktop/tests/unit/routes/scopes/scope/projects/settings/index-test.js @@ -0,0 +1,16 @@ +/** + * Copyright (c) HashiCorp, Inc. + * SPDX-License-Identifier: BUSL-1.1 + */ + +import { module, test } from 'qunit'; +import { setupTest } from 'ember-qunit'; + +module('Unit | Route | scopes/scope/projects/settings/index', function (hooks) { + setupTest(hooks); + + test('it exists', function (assert) { + let route = this.owner.lookup('route:scopes/scope/projects/settings/index'); + assert.ok(route); + }); +}); From 25b3a940a3d5fc6aaaf19185b378c39ca60dc289 Mon Sep 17 00:00:00 2001 From: Dharini Jeeva Date: Wed, 31 Jul 2024 15:30:03 -0700 Subject: [PATCH 02/14] Icu 14400 add a section for version info cli and dc (#2409) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * chore: 🤖 cli info --- addons/api/mirage/scenarios/ipc.js | 9 ++++ addons/core/translations/en-us.yaml | 4 ++ addons/core/translations/errors/en-us.yaml | 2 + addons/core/translations/states/en-us.yaml | 3 ++ .../app/components/settings-card/index.hbs | 41 +++++++++++++++ ui/desktop/app/router.js | 4 +- .../scopes/scope/projects/settings/index.js | 34 +++++++++++- ui/desktop/app/styles/app.scss | 23 ++++++++ .../scopes/scope/projects/settings.hbs | 5 +- .../scopes/scope/projects/settings/index.hbs | 52 ++++++++++++++++++- ui/desktop/electron-app/src/ipc/handlers.js | 16 ++++++ .../projects/settings/index-test.js | 13 +++++ .../components/settings-card-test.js | 41 +++++++++++++++ 13 files changed, 241 insertions(+), 6 deletions(-) create mode 100644 ui/desktop/app/components/settings-card/index.hbs create mode 100644 ui/desktop/tests/integration/components/settings-card-test.js diff --git a/addons/api/mirage/scenarios/ipc.js b/addons/api/mirage/scenarios/ipc.js index d2b54b917a..6366fbb6c0 100644 --- a/addons/api/mirage/scenarios/ipc.js +++ b/addons/api/mirage/scenarios/ipc.js @@ -190,6 +190,15 @@ export default function initializeMockIPC(server, config) { isClientAgentRunning() { return false; } + cacheDaemonStatus() { + return { version: 'Boundary v1.0.0' }; + } + getCliVersion() { + return { versionNumber: '1.0.0' }; + } + getDesktopVersion() { + return { desktopVersion: '1.0.0' }; + } } /** diff --git a/addons/core/translations/en-us.yaml b/addons/core/translations/en-us.yaml index ce1c90291a..e7c06f9415 100644 --- a/addons/core/translations/en-us.yaml +++ b/addons/core/translations/en-us.yaml @@ -44,6 +44,10 @@ titles: not-set: Not set year: '{numberOfYears, plural, =1 {# year} other {# years}}' days: '{days, plural, =1 {# day} other {# days}}' + application: Application + cli: CLI + cache-daemon: Cache Daemon + client: Client 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 diff --git a/addons/core/translations/errors/en-us.yaml b/addons/core/translations/errors/en-us.yaml index 525883d68a..d8893de1a1 100644 --- a/addons/core/translations/errors/en-us.yaml +++ b/addons/core/translations/errors/en-us.yaml @@ -27,3 +27,5 @@ onboarding-failed: required-field: This is a required field. client-agent-failed: sessions: Unable to retrieve sessions from the client agent. +settings-cache: + title: There is a problem with the cache daemon diff --git a/addons/core/translations/states/en-us.yaml b/addons/core/translations/states/en-us.yaml index ce37d4afa0..4ecf3007a1 100644 --- a/addons/core/translations/states/en-us.yaml +++ b/addons/core/translations/states/en-us.yaml @@ -14,6 +14,9 @@ active-public: Public recording: Recording completed: Completed failed: Failed +installed: Installed +not-running: Not Running +running: Running loading: title: Loading all items... description: All of your {resource} are still loading. Please wait while we finish loading everything on screen. diff --git a/ui/desktop/app/components/settings-card/index.hbs b/ui/desktop/app/components/settings-card/index.hbs new file mode 100644 index 0000000000..a27036983f --- /dev/null +++ b/ui/desktop/app/components/settings-card/index.hbs @@ -0,0 +1,41 @@ +{{! + Copyright (c) HashiCorp, Inc. + SPDX-License-Identifier: BUSL-1.1 +}} + + + +
+ + + {{@header}} + + + {{#if (has-block 'action')}} +
+ {{! this will contain buttons }} + {{yield to='action'}} +
+ {{/if}} + + {{#if @state}} +
+ +
+ {{/if}} +
+ + {{#if @description}} + + {{@description}} + + {{/if}} + + {{! this yields the body from consumer }} + {{#if (has-block 'body')}} +
+ {{yield to='body'}} +
+ {{/if}} + +
\ No newline at end of file diff --git a/ui/desktop/app/router.js b/ui/desktop/app/router.js index 12cb417bf3..3c90604165 100644 --- a/ui/desktop/app/router.js +++ b/ui/desktop/app/router.js @@ -26,9 +26,7 @@ Router.map(function () { this.route('sessions', function () { this.route('session', { path: ':session_id' }, function () {}); }); - this.route('settings', function () { - this.route('setting', function () {}); - }); + this.route('settings', function () {}); }); }); }); diff --git a/ui/desktop/app/routes/scopes/scope/projects/settings/index.js b/ui/desktop/app/routes/scopes/scope/projects/settings/index.js index 531ec047aa..e8b47aa48b 100644 --- a/ui/desktop/app/routes/scopes/scope/projects/settings/index.js +++ b/ui/desktop/app/routes/scopes/scope/projects/settings/index.js @@ -4,5 +4,37 @@ */ import Route from '@ember/routing/route'; +import { inject as service } from '@ember/service'; -export default class ScopesScopeProjectsSettingsIndexRoute extends Route {} +export default class ScopesScopeProjectsSettingsIndexRoute extends Route { + @service ipc; + + async model() { + let cacheDaemonStatus, + formattedCacheVersion, + formattedCliVersion, + formattedDesktopVersion; + const { versionNumber: cliVersion } = + await this.ipc.invoke('getCliVersion'); + formattedCliVersion = `v${cliVersion}`; + const { desktopVersion } = await this.ipc.invoke('getDesktopVersion'); + formattedDesktopVersion = `v${desktopVersion}`; + try { + cacheDaemonStatus = await this.ipc.invoke('cacheDaemonStatus'); + } catch (e) { + return { + formattedCliVersion, + formattedCacheVersion, + formattedDesktopVersion, + error: e, + }; + } + const { version } = cacheDaemonStatus; + formattedCacheVersion = version.match(/v\d+\.\d+\.\d+/)?.[0]; + return { + formattedCliVersion, + formattedCacheVersion, + formattedDesktopVersion, + }; + } +} diff --git a/ui/desktop/app/styles/app.scss b/ui/desktop/app/styles/app.scss index c79d9a83f3..baa97b134f 100644 --- a/ui/desktop/app/styles/app.scss +++ b/ui/desktop/app/styles/app.scss @@ -662,3 +662,26 @@ $chevron-down: url("data:image/svg+xml;utf-8,

{{t 'titles.settings'}} @@ -11,4 +11,7 @@ {{! }}

+ + {{outlet}} + \ No newline at end of file diff --git a/ui/desktop/app/templates/scopes/scope/projects/settings/index.hbs b/ui/desktop/app/templates/scopes/scope/projects/settings/index.hbs index d14e217751..9551c3f239 100644 --- a/ui/desktop/app/templates/scopes/scope/projects/settings/index.hbs +++ b/ui/desktop/app/templates/scopes/scope/projects/settings/index.hbs @@ -3,4 +3,54 @@ SPDX-License-Identifier: BUSL-1.1 }} -{{outlet}} \ No newline at end of file + + <:body> +
+
+ + {{t 'titles.client'}} + + + {{@model.formattedDesktopVersion}} + +
+
+ + {{t 'titles.cli'}} + + + {{@model.formattedCliVersion}} + +
+
+ + {{t 'titles.cache-daemon'}} + + + {{#if @model.formattedCacheVersion}} + {{@model.formattedCacheVersion}} + + {{else}} + + {{/if}} + +
+
+ {{#if @model.error}} + + {{t 'errors.settings-cache.title'}} + {{#if @model.error.message}} + {{@model.error.message}} + {{/if}} + + {{/if}} + +
\ No newline at end of file diff --git a/ui/desktop/electron-app/src/ipc/handlers.js b/ui/desktop/electron-app/src/ipc/handlers.js index 8207eb0359..8adb8bb71f 100644 --- a/ui/desktop/electron-app/src/ipc/handlers.js +++ b/ui/desktop/electron-app/src/ipc/handlers.js @@ -16,6 +16,7 @@ const pty = require('node-pty'); const which = require('which'); const cacheDaemonManager = require('../services/cache-daemon-manager'); const clientAgentDaemonManager = require('../services/client-agent-daemon-manager'); +const { releaseVersion } = require('../../config/config.js'); /** * Returns the current runtime clusterUrl, which is used by the main thread to @@ -195,6 +196,21 @@ handle('isClientAgentRunning', async () => { } }); +/** + * Gets boundary cli version + */ +handle('getCliVersion', async () => boundaryCli.version()); + +/** + * Returns desktop version + */ +handle('getDesktopVersion', async () => ({ desktopVersion: releaseVersion })); + +/** + * Returns the Cache daemon status + */ +handle('cacheDaemonStatus', async () => await cacheDaemonManager.status()); + /** * Handler to help create terminal windows. We don't use the helper `handle` method * as we need access to the event and don't need to be using `ipcMain.handle`. diff --git a/ui/desktop/tests/acceptance/projects/settings/index-test.js b/ui/desktop/tests/acceptance/projects/settings/index-test.js index 01f5b4950b..0d953151dd 100644 --- a/ui/desktop/tests/acceptance/projects/settings/index-test.js +++ b/ui/desktop/tests/acceptance/projects/settings/index-test.js @@ -9,10 +9,12 @@ import { setupApplicationTest } from 'ember-qunit'; import setupMirage from 'ember-cli-mirage/test-support/setup-mirage'; import { authenticateSession } from 'ember-simple-auth/test-support'; import WindowMockIPC from '../../../helpers/window-mock-ipc'; +import setupStubs from 'api/test-support/handlers/cache-daemon-search'; module('Acceptance | projects | settings | index', function (hooks) { setupApplicationTest(hooks); setupMirage(hooks); + setupStubs(hooks); const instances = { scopes: { @@ -70,10 +72,21 @@ module('Acceptance | projects | settings | index', function (hooks) { urls.scopes.org = `/scopes/${instances.scopes.org.id}`; urls.scopes.global = `/scopes/${instances.scopes.global.id}`; urls.projects = `${urls.scopes.org}/projects`; + urls.settings = `${urls.projects}/settings`; this.owner.register('service:browser/window', WindowMockIPC); setDefaultClusterUrl(this); + + this.ipcStub + .withArgs('getDesktopVersion') + .returns({ desktopVersion: '0.1.0' }); + this.ipcStub + .withArgs('getCliVersion') + .returns({ versionNumber: 'Boundary CLI v0.1.0' }); + this.ipcStub + .withArgs('cacheDaemonStatus') + .returns({ version: 'Boundary CLI v0.1.0' }); }); test('can navigate to the settings page', async function (assert) { diff --git a/ui/desktop/tests/integration/components/settings-card-test.js b/ui/desktop/tests/integration/components/settings-card-test.js new file mode 100644 index 0000000000..b022512df6 --- /dev/null +++ b/ui/desktop/tests/integration/components/settings-card-test.js @@ -0,0 +1,41 @@ +/** + * Copyright (c) HashiCorp, Inc. + * SPDX-License-Identifier: BUSL-1.1 + */ + +import { module, test } from 'qunit'; +import { setupRenderingTest } from 'ember-qunit'; +import { render, find } from '@ember/test-helpers'; +import { hbs } from 'ember-cli-htmlbars'; + +module('Integration | Component | settings card', function (hooks) { + setupRenderingTest(hooks); + + test('it renders', async function (assert) { + await render(hbs` + <:body> + <:action> + `); + assert.ok(find('.hds-card__container')); + }); + + test('header renders an icon when defined', async function (assert) { + await render(hbs` + + <:body> + <:action> + + `); + + assert.ok(find('.hds-card__container')); + assert.ok(find('.header-and-icon')); + assert.strictEqual( + this.element.textContent.trim(), + 'This is a heading test', + ); + }); +}); From 777380e19ff4e1012aaef0f2f58997f7b1471a28 Mon Sep 17 00:00:00 2001 From: Dharini Jeeva Date: Tue, 6 Aug 2024 12:21:44 -0700 Subject: [PATCH 03/14] Add theme selection (#2428) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * fix: 🐛 remove theme from main menu bar and move to settings pag * chore: 🤖 move toggletheme to app controller --- addons/core/translations/en-us.yaml | 1 + ui/desktop/app/controllers/application.js | 28 +++++++++++- .../scopes/scope/projects/settings/index.js | 44 ++++++++++++++++++- ui/desktop/app/routes/application.js | 33 ++------------ ui/desktop/app/templates/application.hbs | 35 --------------- .../scopes/scope/projects/settings/index.hbs | 19 ++++++++ .../tests/acceptance/authentication-test.js | 42 +----------------- .../projects/settings/index-test.js | 40 ++++++++++++++++- 8 files changed, 132 insertions(+), 110 deletions(-) diff --git a/addons/core/translations/en-us.yaml b/addons/core/translations/en-us.yaml index e7c06f9415..dd29f04735 100644 --- a/addons/core/translations/en-us.yaml +++ b/addons/core/translations/en-us.yaml @@ -48,6 +48,7 @@ titles: cli: CLI cache-daemon: Cache Daemon client: Client + color-theme: Color Theme 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 diff --git a/ui/desktop/app/controllers/application.js b/ui/desktop/app/controllers/application.js index 511049c938..4cd4a56371 100644 --- a/ui/desktop/app/controllers/application.js +++ b/ui/desktop/app/controllers/application.js @@ -5,8 +5,8 @@ import Controller from '@ember/controller'; import { inject as service } from '@ember/service'; +import { getOwner } from '@ember/application'; import { action } from '@ember/object'; - export default class ApplicationController extends Controller { // =services @@ -49,4 +49,30 @@ export default class ApplicationController extends Controller { close() { this.ipc.invoke('closeWindow'); } + + /** + * Applies the specified color theme to the root ember element. + * @param {string} theme - "light", "dark", or nullish (system default) + */ + @action + toggleTheme(theme) { + const rootElementSelector = getOwner(this).rootElement; + const rootEl = getOwner(this) + .lookup('service:-document') + .querySelector(rootElementSelector); + this.session.set('data.theme', theme); + switch (theme) { + case 'light': + rootEl.classList.add('rose-theme-light'); + rootEl.classList.remove('rose-theme-dark'); + break; + case 'dark': + rootEl.classList.add('rose-theme-dark'); + rootEl.classList.remove('rose-theme-light'); + break; + default: + rootEl.classList.remove('rose-theme-dark'); + rootEl.classList.remove('rose-theme-light'); + } + } } diff --git a/ui/desktop/app/controllers/scopes/scope/projects/settings/index.js b/ui/desktop/app/controllers/scopes/scope/projects/settings/index.js index b345316375..4c3e88696f 100644 --- a/ui/desktop/app/controllers/scopes/scope/projects/settings/index.js +++ b/ui/desktop/app/controllers/scopes/scope/projects/settings/index.js @@ -3,6 +3,46 @@ * SPDX-License-Identifier: BUSL-1.1 */ -import Controller from '@ember/controller'; +import Controller, { inject as controller } from '@ember/controller'; +import { inject as service } from '@ember/service'; +import { action } from '@ember/object'; -export default class ScopesScopeProjectsSettingsIndexController extends Controller {} +const THEMES = [ + { + label: 'system', + value: 'system-default-theme', + }, + { + label: 'light', + value: 'light', + }, + { + label: 'dark', + value: 'dark', + }, +]; + +export default class ScopesScopeProjectsSettingsIndexController extends Controller { + @controller('application') application; + // Services + + @service session; + + // Methods + + /** + * Returns available themes + */ + get themes() { + return THEMES; + } + + /** + * Calls the Application controller's toggleTheme method + * @param {string} theme - "light", "dark", or nullish (system default) + */ + @action + toggleTheme({ target: { value: theme } }) { + return this.application.toggleTheme(theme); + } +} diff --git a/ui/desktop/app/routes/application.js b/ui/desktop/app/routes/application.js index 4d9e491b41..b939cd0ff0 100644 --- a/ui/desktop/app/routes/application.js +++ b/ui/desktop/app/routes/application.js @@ -7,7 +7,6 @@ import Route from '@ember/routing/route'; import { inject as service } from '@ember/service'; import { action } from '@ember/object'; import { A } from '@ember/array'; -import { getOwner } from '@ember/application'; import { notifyError } from 'core/decorators/notify'; export default class ApplicationRoute extends Route { @@ -34,9 +33,11 @@ export default class ApplicationRoute extends Route { async beforeModel() { this.intl.setLocale(['en-us']); await this.session.setup(); - const theme = this.session.get('data.theme'); - this.toggleTheme(theme); await this.clusterUrl.updateClusterUrl(); + const theme = this.session.get('data.theme'); + /* eslint-disable-next-line ember/no-controller-access-in-routes */ + const controller = this.controllerFor(this.routeName); + controller.toggleTheme(theme); // Add token to cache daemon after a successful authentication restoration if (this.session.isAuthenticated) { @@ -77,30 +78,4 @@ export default class ApplicationRoute extends Route { } return true; } - - /** - * Applies the specified color theme to the root ember element. - * @param {string} theme - "light", "dark", or nullish (system default) - */ - @action - toggleTheme(theme) { - const rootElementSelector = getOwner(this).rootElement; - const rootEl = getOwner(this) - .lookup('service:-document') - .querySelector(rootElementSelector); - this.session.set('data.theme', theme); - switch (theme) { - case 'light': - rootEl.classList.add('rose-theme-light'); - rootEl.classList.remove('rose-theme-dark'); - break; - case 'dark': - rootEl.classList.add('rose-theme-dark'); - rootEl.classList.remove('rose-theme-light'); - break; - default: - rootEl.classList.remove('rose-theme-dark'); - rootEl.classList.remove('rose-theme-light'); - } - } } diff --git a/ui/desktop/app/templates/application.hbs b/ui/desktop/app/templates/application.hbs index 3b4913ed3a..ba816f415a 100644 --- a/ui/desktop/app/templates/application.hbs +++ b/ui/desktop/app/templates/application.hbs @@ -53,41 +53,6 @@ {{t 'actions.deauthenticate'}} - - - - - - - - - - - - - - - - - - {{/if}} diff --git a/ui/desktop/app/templates/scopes/scope/projects/settings/index.hbs b/ui/desktop/app/templates/scopes/scope/projects/settings/index.hbs index 9551c3f239..8d69126967 100644 --- a/ui/desktop/app/templates/scopes/scope/projects/settings/index.hbs +++ b/ui/desktop/app/templates/scopes/scope/projects/settings/index.hbs @@ -52,5 +52,24 @@ {{/if}} {{/if}} + + + {{t 'titles.color-theme'}} + + {{#each this.themes as |theme|}} + + {{/each}} + + \ No newline at end of file diff --git a/ui/desktop/tests/acceptance/authentication-test.js b/ui/desktop/tests/acceptance/authentication-test.js index 6e2856afda..f7cf69da73 100644 --- a/ui/desktop/tests/acceptance/authentication-test.js +++ b/ui/desktop/tests/acceptance/authentication-test.js @@ -4,14 +4,7 @@ */ import { module, test } from 'qunit'; -import { - visit, - currentURL, - fillIn, - click, - find, - getRootElement, -} from '@ember/test-helpers'; +import { visit, currentURL, fillIn, click, find } from '@ember/test-helpers'; import { setupApplicationTest } from 'ember-qunit'; import setupMirage from 'ember-cli-mirage/test-support/setup-mirage'; import { Response } from 'miragejs'; @@ -219,39 +212,6 @@ module('Acceptance | authentication', function (hooks) { ); }); - test('color theme is applied from session data', async function (assert) { - assert.expect(12); - authenticateSession({ - scope: { - id: instances.scopes.global.id, - type: instances.scopes.global.type, - }, - }); - await visit(urls.scopes.org); - // system default - assert.notOk(currentSession().get('data.theme')); - assert.notOk(getRootElement().classList.contains('rose-theme-light')); - assert.notOk(getRootElement().classList.contains('rose-theme-dark')); - // toggle light mode - await click('[name="theme"][value="light"]'); - assert.strictEqual(currentSession().get('data.theme'), 'light'); - assert.ok(getRootElement().classList.contains('rose-theme-light')); - assert.notOk(getRootElement().classList.contains('rose-theme-dark')); - // toggle dark mode - await click('[name="theme"][value="dark"]'); - assert.strictEqual(currentSession().get('data.theme'), 'dark'); - assert.notOk(getRootElement().classList.contains('rose-theme-light')); - assert.ok(getRootElement().classList.contains('rose-theme-dark')); - // toggle system default - await click('[name="theme"][value="system-default-theme"]'); - assert.strictEqual( - currentSession().get('data.theme'), - 'system-default-theme', - ); - assert.notOk(getRootElement().classList.contains('rose-theme-light')); - assert.notOk(getRootElement().classList.contains('rose-theme-dark')); - }); - test('org scopes with no auth methods are not visible in dropdown', async function (assert) { await visit(urls.authenticate.methods.global); diff --git a/ui/desktop/tests/acceptance/projects/settings/index-test.js b/ui/desktop/tests/acceptance/projects/settings/index-test.js index 0d953151dd..c8624383bd 100644 --- a/ui/desktop/tests/acceptance/projects/settings/index-test.js +++ b/ui/desktop/tests/acceptance/projects/settings/index-test.js @@ -4,10 +4,19 @@ */ import { module, test } from 'qunit'; -import { currentURL, click, visit } from '@ember/test-helpers'; +import { + currentURL, + click, + visit, + getRootElement, + select, +} from '@ember/test-helpers'; import { setupApplicationTest } from 'ember-qunit'; import setupMirage from 'ember-cli-mirage/test-support/setup-mirage'; -import { authenticateSession } from 'ember-simple-auth/test-support'; +import { + authenticateSession, + currentSession, +} from 'ember-simple-auth/test-support'; import WindowMockIPC from '../../../helpers/window-mock-ipc'; import setupStubs from 'api/test-support/handlers/cache-daemon-search'; @@ -94,4 +103,31 @@ module('Acceptance | projects | settings | index', function (hooks) { await click(`[href="${urls.settings}"]`); assert.strictEqual(currentURL(), urls.settings); }); + + test('color theme is applied from session data', async function (assert) { + await visit(urls.settings); + + // system default + assert.notOk(currentSession().get('data.theme')); + assert.notOk(getRootElement().classList.contains('rose-theme-light')); + assert.notOk(getRootElement().classList.contains('rose-theme-dark')); + // toggle light mode + await select('[name="theme"]', 'light'); + assert.strictEqual(currentSession().get('data.theme'), 'light'); + assert.ok(getRootElement().classList.contains('rose-theme-light')); + assert.notOk(getRootElement().classList.contains('rose-theme-dark')); + // toggle dark mode + await select('[name="theme"]', 'dark'); + assert.strictEqual(currentSession().get('data.theme'), 'dark'); + assert.notOk(getRootElement().classList.contains('rose-theme-light')); + assert.ok(getRootElement().classList.contains('rose-theme-dark')); + // toggle system default + await select('[name="theme"]', 'system-default-theme'); + assert.strictEqual( + currentSession().get('data.theme'), + 'system-default-theme', + ); + assert.notOk(getRootElement().classList.contains('rose-theme-light')); + assert.notOk(getRootElement().classList.contains('rose-theme-dark')); + }); }); From 0b9357e9b3e9639d7da908f8d5323bdd1af5739d Mon Sep 17 00:00:00 2001 From: Dharini Jeeva Date: Tue, 6 Aug 2024 16:14:27 -0700 Subject: [PATCH 04/14] =?UTF-8?q?chore:=20=F0=9F=A4=96=20add=20user=20info?= =?UTF-8?q?=20(#2425)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * chore: 🤖 add user info --- addons/core/translations/states/en-us.yaml | 2 + .../settings-card/application/index.hbs | 76 +++++++++++++++++++ .../settings-card/application/index.js | 30 ++++++++ .../app/components/settings-card/index.hbs | 9 +-- .../components/settings-card/user/index.hbs | 49 ++++++++++++ .../components/settings-card/user/index.js | 61 +++++++++++++++ .../scopes/scope/projects/settings/index.js | 29 +------ ui/desktop/app/styles/app.scss | 14 +++- .../scopes/scope/projects/settings/index.hbs | 72 +----------------- .../projects/settings/index-test.js | 11 +++ .../components/settings-card-test.js | 41 ++++++++++ 11 files changed, 289 insertions(+), 105 deletions(-) create mode 100644 ui/desktop/app/components/settings-card/application/index.hbs create mode 100644 ui/desktop/app/components/settings-card/application/index.js create mode 100644 ui/desktop/app/components/settings-card/user/index.hbs create mode 100644 ui/desktop/app/components/settings-card/user/index.js diff --git a/addons/core/translations/states/en-us.yaml b/addons/core/translations/states/en-us.yaml index 4ecf3007a1..15893d59d1 100644 --- a/addons/core/translations/states/en-us.yaml +++ b/addons/core/translations/states/en-us.yaml @@ -17,6 +17,8 @@ failed: Failed installed: Installed not-running: Not Running running: Running +authenticated: Authenticated +unauthenticated: Unauthenticated loading: title: Loading all items... description: All of your {resource} are still loading. Please wait while we finish loading everything on screen. diff --git a/ui/desktop/app/components/settings-card/application/index.hbs b/ui/desktop/app/components/settings-card/application/index.hbs new file mode 100644 index 0000000000..a9aeed743d --- /dev/null +++ b/ui/desktop/app/components/settings-card/application/index.hbs @@ -0,0 +1,76 @@ +{{! + Copyright (c) HashiCorp, Inc. + SPDX-License-Identifier: BUSL-1.1 +}} + + + <:body> +
+
+ + {{t 'titles.client'}} + + + {{@model.formattedDesktopVersion}} + +
+
+ + {{t 'titles.cli'}} + + + {{@model.formattedCliVersion}} + +
+
+ + {{t 'titles.cache-daemon'}} + + + {{#if @model.formattedCacheVersion}} + {{@model.formattedCacheVersion}} + + {{else}} + + {{/if}} + + +
+
+ {{#if @model.error}} + + {{t 'errors.settings-cache.title'}} + {{#if @model.error.message}} + {{@model.error.message}} + {{/if}} + + {{/if}} + + + {{t 'titles.color-theme'}} + + {{#each this.themes as |theme|}} + + {{/each}} + + + +
\ No newline at end of file diff --git a/ui/desktop/app/components/settings-card/application/index.js b/ui/desktop/app/components/settings-card/application/index.js new file mode 100644 index 0000000000..4bd00b484a --- /dev/null +++ b/ui/desktop/app/components/settings-card/application/index.js @@ -0,0 +1,30 @@ +/** + * Copyright (c) HashiCorp, Inc. + * SPDX-License-Identifier: BUSL-1.1 + */ + +import Component from '@glimmer/component'; + +const THEMES = [ + { + label: 'system', + value: 'system-default-theme', + }, + { + label: 'light', + value: 'light', + }, + { + label: 'dark', + value: 'dark', + }, +]; + +export default class SettingsApplicationComponent extends Component { + /** + * Returns available themes + */ + get themes() { + return THEMES; + } +} diff --git a/ui/desktop/app/components/settings-card/index.hbs b/ui/desktop/app/components/settings-card/index.hbs index a27036983f..93e501885e 100644 --- a/ui/desktop/app/components/settings-card/index.hbs +++ b/ui/desktop/app/components/settings-card/index.hbs @@ -11,6 +11,10 @@ {{@header}} + {{#if (has-block 'state')}} + {{yield to='state'}} + {{/if}} + {{#if (has-block 'action')}}
{{! this will contain buttons }} @@ -18,11 +22,6 @@
{{/if}} - {{#if @state}} -
- -
- {{/if}} {{#if @description}} diff --git a/ui/desktop/app/components/settings-card/user/index.hbs b/ui/desktop/app/components/settings-card/user/index.hbs new file mode 100644 index 0000000000..39df6bf76d --- /dev/null +++ b/ui/desktop/app/components/settings-card/user/index.hbs @@ -0,0 +1,49 @@ +{{! + Copyright (c) HashiCorp, Inc. + SPDX-License-Identifier: BUSL-1.1 +}} + + + <:state> + {{#if this.isAuthenticated}} + + {{else}} + + {{/if}} + + <:body> +
+
+ + {{t 'resources.auth-method.title'}} + + + {{this.authMethod}} + +
+
+ + {{t 'form.username.label'}} + + + {{this.userInfo}} + +
+
+ + + <:action> + + +
\ No newline at end of file diff --git a/ui/desktop/app/components/settings-card/user/index.js b/ui/desktop/app/components/settings-card/user/index.js new file mode 100644 index 0000000000..917437b6fc --- /dev/null +++ b/ui/desktop/app/components/settings-card/user/index.js @@ -0,0 +1,61 @@ +/** + * Copyright (c) HashiCorp, Inc. + * SPDX-License-Identifier: BUSL-1.1 + */ + +import Component from '@glimmer/component'; +import { inject as service } from '@ember/service'; +import { action } from '@ember/object'; + +export default class SettingsUserInfoComponent extends Component { + // =services + + @service session; + @service intl; + + /** + * Returns the username of the current user + * @type {string} + */ + get userInfo() { + const { + data: { + authenticated: { username }, + }, + } = this.session; + return username; + } + + /** + * Returns true if user is authenticated + * @type {boolean} + */ + get isAuthenticated() { + const { isAuthenticated } = this.session; + return isAuthenticated; + } + + /** + * Returns the type of authmethod used by the user + * @type {string} + */ + get authMethod() { + const { + data: { + authenticated: { authenticator }, + }, + } = this.session; + const formattedAuthenticatorType = authenticator.split(':')[1]; + return this.intl.t(`resources.account.types.${formattedAuthenticatorType}`); + } + + // =actions + + /** + * Delegates invalidation to the session service. + */ + @action + invalidateSession() { + this.session.invalidate(); + } +} diff --git a/ui/desktop/app/controllers/scopes/scope/projects/settings/index.js b/ui/desktop/app/controllers/scopes/scope/projects/settings/index.js index 4c3e88696f..f6502c0e19 100644 --- a/ui/desktop/app/controllers/scopes/scope/projects/settings/index.js +++ b/ui/desktop/app/controllers/scopes/scope/projects/settings/index.js @@ -4,39 +4,12 @@ */ import Controller, { inject as controller } from '@ember/controller'; -import { inject as service } from '@ember/service'; import { action } from '@ember/object'; -const THEMES = [ - { - label: 'system', - value: 'system-default-theme', - }, - { - label: 'light', - value: 'light', - }, - { - label: 'dark', - value: 'dark', - }, -]; - export default class ScopesScopeProjectsSettingsIndexController extends Controller { @controller('application') application; - // Services - - @service session; - - // Methods - - /** - * Returns available themes - */ - get themes() { - return THEMES; - } + //actions /** * Calls the Application controller's toggleTheme method * @param {string} theme - "light", "dark", or nullish (system default) diff --git a/ui/desktop/app/styles/app.scss b/ui/desktop/app/styles/app.scss index baa97b134f..8023ae9537 100644 --- a/ui/desktop/app/styles/app.scss +++ b/ui/desktop/app/styles/app.scss @@ -665,14 +665,17 @@ $chevron-down: url("data:image/svg+xml;utf-8, - <:body> -
-
- - {{t 'titles.client'}} - - - {{@model.formattedDesktopVersion}} - -
-
- - {{t 'titles.cli'}} - - - {{@model.formattedCliVersion}} - -
-
- - {{t 'titles.cache-daemon'}} - - - {{#if @model.formattedCacheVersion}} - {{@model.formattedCacheVersion}} - - {{else}} - - {{/if}} - -
-
- {{#if @model.error}} - - {{t 'errors.settings-cache.title'}} - {{#if @model.error.message}} - {{@model.error.message}} - {{/if}} - - {{/if}} - - - {{t 'titles.color-theme'}} - - {{#each this.themes as |theme|}} - - {{/each}} - - - - \ No newline at end of file + + \ No newline at end of file diff --git a/ui/desktop/tests/acceptance/projects/settings/index-test.js b/ui/desktop/tests/acceptance/projects/settings/index-test.js index c8624383bd..20b7edbe84 100644 --- a/ui/desktop/tests/acceptance/projects/settings/index-test.js +++ b/ui/desktop/tests/acceptance/projects/settings/index-test.js @@ -20,6 +20,8 @@ import { import WindowMockIPC from '../../../helpers/window-mock-ipc'; import setupStubs from 'api/test-support/handlers/cache-daemon-search'; +const SIGNOUT_SELECTOR = '[data-test-signout-button]'; + module('Acceptance | projects | settings | index', function (hooks) { setupApplicationTest(hooks); setupMirage(hooks); @@ -130,4 +132,13 @@ module('Acceptance | projects | settings | index', function (hooks) { assert.notOk(getRootElement().classList.contains('rose-theme-light')); assert.notOk(getRootElement().classList.contains('rose-theme-dark')); }); + + test('clicking signout button logs out the user', async function (assert) { + authenticateSession({ username: 'testuser' }); + assert.expect(2); + await visit(urls.settings); + assert.ok(currentSession().isAuthenticated); + await click(SIGNOUT_SELECTOR); + assert.notOk(currentSession().isAuthenticated); + }); }); diff --git a/ui/desktop/tests/integration/components/settings-card-test.js b/ui/desktop/tests/integration/components/settings-card-test.js index b022512df6..ba40ce407f 100644 --- a/ui/desktop/tests/integration/components/settings-card-test.js +++ b/ui/desktop/tests/integration/components/settings-card-test.js @@ -8,6 +8,10 @@ import { setupRenderingTest } from 'ember-qunit'; import { render, find } from '@ember/test-helpers'; import { hbs } from 'ember-cli-htmlbars'; +const USERNAME_SELECTOR = '[data-test-username]'; +const AUTH_METHOD_SELECTOR = '[data-test-auth-method]'; +const SIGNOUT_SELECTOR = '[data-test-signout-button]'; + module('Integration | Component | settings card', function (hooks) { setupRenderingTest(hooks); @@ -38,4 +42,41 @@ module('Integration | Component | settings card', function (hooks) { 'This is a heading test', ); }); + + test('displays userinfo card correctly', async function (assert) { + this.authMethod = 'OIDC'; + this.userInfo = 'testuser'; + await render(hbs` + + <:body> +
+
+ + {{this.authMethod}} + +
+
+ + {{this.userInfo}} + +
+
+ + <:action> + + +
+ `); + assert.dom(AUTH_METHOD_SELECTOR).hasText('OIDC'); + assert.dom(USERNAME_SELECTOR).hasText('testuser'); + assert.dom(SIGNOUT_SELECTOR).hasText('sign out'); + }); }); From e4f43941979557315564b3dc8963fe62ad8e10e0 Mon Sep 17 00:00:00 2001 From: Zhihe Li Date: Wed, 14 Aug 2024 13:26:35 -0400 Subject: [PATCH 05/14] Icu 14403 add dropdown to select and save log verbosity (#2431) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * feat: 🎸 Add logging settings card ✅ Closes: https://hashicorp.atlassian.net/browse/ICU-14403 --- addons/core/translations/en-us.yaml | 20 ++- .../settings-card/application/index.hbs | 80 ++++----- .../components/settings-card/logs/index.hbs | 33 ++++ .../components/settings-card/logs/index.js | 25 +++ .../components/settings-card/user/index.hbs | 32 ++-- .../scopes/scope/projects/settings/index.js | 24 ++- ui/desktop/app/styles/app.scss | 24 +-- .../scopes/scope/projects/settings/index.hbs | 3 +- ui/desktop/electron-app/package.json | 1 + ui/desktop/electron-app/src/index.js | 3 +- ui/desktop/electron-app/src/ipc/handlers.js | 34 +++- .../src/services/electron-store-manager.js | 20 +++ ui/desktop/electron-app/yarn.lock | 168 ++++++++++++++---- .../components/settings-card-test.js | 43 +---- .../components/settings-card/logs-test.js | 49 +++++ .../components/settings-card/user-test.js | 79 ++++++++ 16 files changed, 476 insertions(+), 162 deletions(-) create mode 100644 ui/desktop/app/components/settings-card/logs/index.hbs create mode 100644 ui/desktop/app/components/settings-card/logs/index.js create mode 100644 ui/desktop/electron-app/src/services/electron-store-manager.js create mode 100644 ui/desktop/tests/integration/components/settings-card/logs-test.js create mode 100644 ui/desktop/tests/integration/components/settings-card/user-test.js diff --git a/addons/core/translations/en-us.yaml b/addons/core/translations/en-us.yaml index dd29f04735..43d9d4d607 100644 --- a/addons/core/translations/en-us.yaml +++ b/addons/core/translations/en-us.yaml @@ -44,11 +44,6 @@ titles: not-set: Not set year: '{numberOfYears, plural, =1 {# year} other {# years}}' days: '{days, plural, =1 {# day} other {# days}}' - application: Application - cli: CLI - cache-daemon: Cache Daemon - client: Client - color-theme: Color Theme 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 @@ -110,3 +105,18 @@ unsupported-controller: releases-page: Go to releases page change-cluster-url: Change cluster URL error: Unable to download supported version of desktop app. You’ll need to download version 1.7.1 from the releases page +settings: + application: Application + cli: CLI + cache-daemon: Cache Daemon + client: Client + color-theme: Color Theme + logs: + title: Logs + logging-level: Logging level + log-location: Log location + levels: + error: Error + warn: Warn + info: Info + debug: Debug diff --git a/ui/desktop/app/components/settings-card/application/index.hbs b/ui/desktop/app/components/settings-card/application/index.hbs index a9aeed743d..fa20d0076e 100644 --- a/ui/desktop/app/components/settings-card/application/index.hbs +++ b/ui/desktop/app/components/settings-card/application/index.hbs @@ -3,47 +3,45 @@ SPDX-License-Identifier: BUSL-1.1 }} - + <:body> -
-
- - {{t 'titles.client'}} - - - {{@model.formattedDesktopVersion}} - -
-
- - {{t 'titles.cli'}} - - - {{@model.formattedCliVersion}} - -
-
- - {{t 'titles.cache-daemon'}} - - - {{#if @model.formattedCacheVersion}} - {{@model.formattedCacheVersion}} - - {{else}} - - {{/if}} +
+ + {{t 'settings.client'}} + + + {{@model.formattedDesktopVersion}} + +
+
+ + {{t 'settings.cli'}} + + + {{@model.formattedCliVersion}} + +
+
+ + {{t 'settings.cache-daemon'}} + + + {{#if @model.formattedCacheVersion}} + {{@model.formattedCacheVersion}} + + {{else}} + + {{/if}} - -
+
{{#if @model.error}} @@ -56,11 +54,11 @@ - {{t 'titles.color-theme'}} + {{t 'settings.color-theme'}} {{#each this.themes as |theme|}}
{{#if @description}} - + {{@description}} {{/if}} diff --git a/ui/desktop/app/components/settings-card/server/index.hbs b/ui/desktop/app/components/settings-card/server/index.hbs new file mode 100644 index 0000000000..cee93da88b --- /dev/null +++ b/ui/desktop/app/components/settings-card/server/index.hbs @@ -0,0 +1,41 @@ +{{! + Copyright (c) HashiCorp, Inc. + SPDX-License-Identifier: BUSL-1.1 +}} + + + <:state> + {{#if @model.serverInformation}} + + {{/if}} + + <:body> +
+ + {{t 'settings.provider'}} + + + {{this.providerName}} + +
+
+ + {{t 'form.cluster-url.label'}} + + +
+ + +
\ No newline at end of file diff --git a/ui/desktop/app/components/settings-card/server/index.js b/ui/desktop/app/components/settings-card/server/index.js new file mode 100644 index 0000000000..07187a372f --- /dev/null +++ b/ui/desktop/app/components/settings-card/server/index.js @@ -0,0 +1,26 @@ +/** + * Copyright (c) HashiCorp, Inc. + * SPDX-License-Identifier: BUSL-1.1 + */ + +import Component from '@glimmer/component'; +import { inject as service } from '@ember/service'; + +export default class SettingsCardServerComponent extends Component { + // =services + @service intl; + + // =attributes + /** + * Returns the provider name for HCP and generic name for non HCP servers + * @type {string} + */ + get providerName() { + const regex = /boundary\.(hashicorp|hcp)/; + if (this.args.model.serverInformation?.match(regex)) { + return this.intl.t('settings.hcp'); + } else { + return this.intl.t('settings.self-managed'); + } + } +} diff --git a/ui/desktop/app/routes/scopes/scope/projects/settings/index.js b/ui/desktop/app/routes/scopes/scope/projects/settings/index.js index 82c26d5dd4..09fb66aae7 100644 --- a/ui/desktop/app/routes/scopes/scope/projects/settings/index.js +++ b/ui/desktop/app/routes/scopes/scope/projects/settings/index.js @@ -10,6 +10,7 @@ export default class ScopesScopeProjectsSettingsIndexRoute extends Route { // =services @service ipc; @service session; + @service clusterUrl; // =methods async model() { @@ -48,6 +49,7 @@ export default class ScopesScopeProjectsSettingsIndexRoute extends Route { const logLevel = await this.ipc.invoke('getLogLevel'); const logPath = await this.ipc.invoke('getLogPath'); + const serverInformation = this.clusterUrl.rendererClusterUrl; return { cacheDaemonErrors, @@ -56,6 +58,7 @@ export default class ScopesScopeProjectsSettingsIndexRoute extends Route { formattedDesktopVersion, logLevel, logPath, + serverInformation, }; } } diff --git a/ui/desktop/app/styles/app.scss b/ui/desktop/app/styles/app.scss index 4b44e9f91c..f052b25ae7 100644 --- a/ui/desktop/app/styles/app.scss +++ b/ui/desktop/app/styles/app.scss @@ -674,6 +674,10 @@ $chevron-down: url("data:image/svg+xml;utf-8, { + const windowOrigin = 'hashicorp.cloud'; + const clusterUrl = test.owner.lookup('service:clusterUrl'); + clusterUrl.rendererClusterUrl = windowOrigin; + }; + + setDefaultClusterUrl(this); + + test('it displays HCP cluster url in server information section', async function (assert) { + await render(hbs``); + assert.dom(SERVER_NAME).hasText('HashiCorp Cloud Platform'); + assert.dom(SERVER_URL).hasText('hashicorp.cloud'); + }); + + test('it displays non HCP cluster url in server information section', async function (assert) { + this.owner.lookup('service:clusterUrl').rendererClusterUrl = + 'everythingelse'; + await render(hbs``); + assert.dom(SERVER_NAME).hasText('Self-Managed'); + assert.dom(SERVER_URL).hasText('everythingelse'); + }); +}); From edaf19f59bd52ba66dca19ce8be312368bb93aac Mon Sep 17 00:00:00 2001 From: Zhihe Li Date: Tue, 20 Aug 2024 19:28:43 -0400 Subject: [PATCH 08/14] =?UTF-8?q?feat:=20=F0=9F=8E=B8=20Add=20section=20fo?= =?UTF-8?q?r=20client=20agent=20in=20settings=20(#2442)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * feat: 🎸 Add section for client agent in settings ✅ Closes: https://hashicorp.atlassian.net/browse/ICU-14780 --- addons/api/mirage/scenarios/ipc.js | 14 ++-- addons/core/translations/actions/en-us.yaml | 2 + addons/core/translations/en-us.yaml | 7 ++ addons/core/translations/errors/en-us.yaml | 2 - addons/core/translations/states/en-us.yaml | 1 + .../settings-card/application/index.hbs | 14 ++-- .../settings-card/client-agent/index.hbs | 63 ++++++++++++++ .../settings-card/client-agent/index.js | 68 +++++++++++++++ .../app/components/settings-card/index.hbs | 5 +- .../components/settings-card/logs/index.js | 10 +++ .../components/settings-card/user/index.js | 1 + .../app/routes/scopes/scope/projects.js | 2 + .../scopes/scope/projects/settings/index.js | 62 +++++++++----- .../scopes/scope/projects/settings/index.hbs | 1 + .../electron-app/src/helpers/spawn-promise.js | 5 +- ui/desktop/electron-app/src/ipc/handlers.js | 17 +++- .../services/client-agent-daemon-manager.js | 46 +++++++++- ui/desktop/tests/helpers/window-mock-ipc.js | 21 +++++ .../settings-card/application-test.js | 58 ++++++------- .../settings-card/client-agent-test.js | 84 +++++++++++++++++++ 20 files changed, 403 insertions(+), 80 deletions(-) create mode 100644 ui/desktop/app/components/settings-card/client-agent/index.hbs create mode 100644 ui/desktop/app/components/settings-card/client-agent/index.js create mode 100644 ui/desktop/tests/integration/components/settings-card/client-agent-test.js diff --git a/addons/api/mirage/scenarios/ipc.js b/addons/api/mirage/scenarios/ipc.js index 6524593916..62e17c9c54 100644 --- a/addons/api/mirage/scenarios/ipc.js +++ b/addons/api/mirage/scenarios/ipc.js @@ -199,18 +199,18 @@ export default function initializeMockIPC(server, config) { getDesktopVersion() { return { desktopVersion: '1.0.0' }; } - getLogLevel() { - return 'debug'; - } - - setLogLevel() { - return 'warn'; + return 'info'; } - getLogPath() { return '~/.config/Boundary/logs/desktop-client.log'; } + setLogLevel() {} + clientAgentStatus() { + return { version: '0.0.1-dev', status: 'running' }; + } + pauseClientAgent() {} + resumeClientAgent() {} } /** diff --git a/addons/core/translations/actions/en-us.yaml b/addons/core/translations/actions/en-us.yaml index 6ab0b3bbec..f23351b08a 100644 --- a/addons/core/translations/actions/en-us.yaml +++ b/addons/core/translations/actions/en-us.yaml @@ -22,6 +22,8 @@ back: Back view: View retry: Retry play: Play +pause: Pause +resume: Resume get-topic-help: Get help for this topic copy-to-clipboard: Copy to Clipboard copy-error-detail-to-clipboard: Copy error detail to clipboard diff --git a/addons/core/translations/en-us.yaml b/addons/core/translations/en-us.yaml index 4d642b5ef5..8cf9176cfc 100644 --- a/addons/core/translations/en-us.yaml +++ b/addons/core/translations/en-us.yaml @@ -109,7 +109,11 @@ settings: application: Application cli: CLI cache-daemon: Cache Daemon + client-agent: + title: Boundary Client Agent + description: Required to use Transparent Sessions client: Client + version: Version color-theme: Color Theme provider: Provider hcp: HashiCorp Cloud Platform @@ -127,3 +131,6 @@ settings: warn: Warn info: Info debug: Debug + alerts: + cache-daemon: There may be a problem with the cache daemon + client-agent: There may be a problem with the client agent diff --git a/addons/core/translations/errors/en-us.yaml b/addons/core/translations/errors/en-us.yaml index 7c5207a33c..525883d68a 100644 --- a/addons/core/translations/errors/en-us.yaml +++ b/addons/core/translations/errors/en-us.yaml @@ -27,5 +27,3 @@ onboarding-failed: required-field: This is a required field. client-agent-failed: sessions: Unable to retrieve sessions from the client agent. -settings-cache: - title: There may be a problem with the cache daemon diff --git a/addons/core/translations/states/en-us.yaml b/addons/core/translations/states/en-us.yaml index 15893d59d1..c3d36f289c 100644 --- a/addons/core/translations/states/en-us.yaml +++ b/addons/core/translations/states/en-us.yaml @@ -17,6 +17,7 @@ failed: Failed installed: Installed not-running: Not Running running: Running +paused: Paused authenticated: Authenticated unauthenticated: Unauthenticated loading: diff --git a/ui/desktop/app/components/settings-card/application/index.hbs b/ui/desktop/app/components/settings-card/application/index.hbs index 1e91984fec..b8539a6b1d 100644 --- a/ui/desktop/app/components/settings-card/application/index.hbs +++ b/ui/desktop/app/components/settings-card/application/index.hbs @@ -10,7 +10,7 @@ {{t 'settings.client'}} - {{@model.formattedDesktopVersion}} + {{@model.desktopVersion}}
@@ -18,7 +18,7 @@ {{t 'settings.cli'}} - {{@model.formattedCliVersion}} + {{@model.cliVersion}}
@@ -26,8 +26,8 @@ {{t 'settings.cache-daemon'}} - {{#if @model.formattedCacheVersion}} - {{@model.formattedCacheVersion}} + {{#if @model.cacheDaemonStatus.version}} + {{@model.cacheDaemonStatus.version}}
- {{#if @model.cacheDaemonErrors}} + {{#if @model.cacheDaemonStatus.errors}} - {{t 'errors.settings-cache.title'}} + {{t 'settings.alerts.cache-daemon'}} - {{#each @model.cacheDaemonErrors as |error|}} + {{#each @model.cacheDaemonStatus.errors as |error|}} {{#if error.name}} {{error.name}}: diff --git a/ui/desktop/app/components/settings-card/client-agent/index.hbs b/ui/desktop/app/components/settings-card/client-agent/index.hbs new file mode 100644 index 0000000000..b04aec8b93 --- /dev/null +++ b/ui/desktop/app/components/settings-card/client-agent/index.hbs @@ -0,0 +1,63 @@ +{{! + Copyright (c) HashiCorp, Inc. + SPDX-License-Identifier: BUSL-1.1 +}} + +{{#if this.isClientAgentActive}} + + <:state> + {{#if this.isClientAgentStatusRunning}} + + {{else}} + + {{/if}} + + <:body> +
+ + {{t 'settings.version'}} + + + {{@model.clientAgentStatus.version}} + +
+ {{#if @model.clientAgentStatus.errors}} + + {{t 'settings.alerts.client-agent'}} + + {{#each @model.clientAgentStatus.errors as |error|}} + + {{error.message}} + + {{/each}} + + + {{/if}} + + + <:action> + + +
+{{/if}} \ No newline at end of file diff --git a/ui/desktop/app/components/settings-card/client-agent/index.js b/ui/desktop/app/components/settings-card/client-agent/index.js new file mode 100644 index 0000000000..2ba238c340 --- /dev/null +++ b/ui/desktop/app/components/settings-card/client-agent/index.js @@ -0,0 +1,68 @@ +/** + * Copyright (c) HashiCorp, Inc. + * SPDX-License-Identifier: BUSL-1.1 + */ + +import Component from '@glimmer/component'; +import { inject as service } from '@ember/service'; +import { action } from '@ember/object'; +import { loading } from 'ember-loading'; +import { notifyError } from 'core/decorators/notify'; + +export default class SettingsCardClientAgentComponent extends Component { + // =services + @service ipc; + @service router; + @service loading; + + // =attributes + + /** + * Checks if the status returned by the client agent is "running" + * @return {boolean} + */ + get isClientAgentStatusRunning() { + return this.args.model.clientAgentStatus?.status === 'running'; + } + + /** + * Checks if the client agent is actively running + * @return {boolean} + */ + get isClientAgentActive() { + return ( + this.args.model.clientAgentStatus?.status === 'running' || + this.args.model.clientAgentStatus?.status === 'paused' + ); + } + + /** + * Return the button icon based on the current state of the client agent + * @return {string} + */ + get buttonIcon() { + if (this.loading.isLoading) { + return 'loading'; + } else { + return this.isClientAgentStatusRunning ? 'pause' : 'play'; + } + } + + // =actions + + /** + * Changes the state of the client agent based on the current state. + * @return {Promise} + */ + @action + @loading + @notifyError(({ message }) => message) + async changeClientAgentState() { + if (this.isClientAgentStatusRunning) { + await this.ipc.invoke('pauseClientAgent'); + } else { + await this.ipc.invoke('resumeClientAgent'); + } + await this.router.refresh(); + } +} diff --git a/ui/desktop/app/components/settings-card/index.hbs b/ui/desktop/app/components/settings-card/index.hbs index 80d79e3d40..5694a12c1c 100644 --- a/ui/desktop/app/components/settings-card/index.hbs +++ b/ui/desktop/app/components/settings-card/index.hbs @@ -4,7 +4,6 @@ }} -
@@ -20,11 +19,10 @@ {{yield to='action'}}
{{/if}} - {{#if @description}} - + {{@description}} {{/if}} @@ -35,5 +33,4 @@ {{yield to='body'}} {{/if}} -
\ No newline at end of file diff --git a/ui/desktop/app/components/settings-card/logs/index.js b/ui/desktop/app/components/settings-card/logs/index.js index 22b26234e3..40a14c4e57 100644 --- a/ui/desktop/app/components/settings-card/logs/index.js +++ b/ui/desktop/app/components/settings-card/logs/index.js @@ -13,11 +13,21 @@ export default class SettingsCardLogsComponent extends Component { // =attributes + /** + * Returns the list of available log levels + * @return {string[]} + */ get logLevels() { return ['error', 'warn', 'info', 'debug']; } // =methods + + /** + * Sets the log level to the selected value + * @param value + * @return {Promise} + */ @action async selectLogLevel({ target: { value } }) { await this.ipc.invoke('setLogLevel', value); diff --git a/ui/desktop/app/components/settings-card/user/index.js b/ui/desktop/app/components/settings-card/user/index.js index 917437b6fc..0c946ae303 100644 --- a/ui/desktop/app/components/settings-card/user/index.js +++ b/ui/desktop/app/components/settings-card/user/index.js @@ -13,6 +13,7 @@ export default class SettingsUserInfoComponent extends Component { @service session; @service intl; + // =attributes /** * Returns the username of the current user * @type {string} diff --git a/ui/desktop/app/routes/scopes/scope/projects.js b/ui/desktop/app/routes/scopes/scope/projects.js index d8f6e0bbba..a4160ed1c4 100644 --- a/ui/desktop/app/routes/scopes/scope/projects.js +++ b/ui/desktop/app/routes/scopes/scope/projects.js @@ -64,6 +64,8 @@ export default class ScopesScopeProjectsRoute extends Route { ); if (isClientAgentRunning) { this.job.start(); + } else { + this.job.stop(); } } diff --git a/ui/desktop/app/routes/scopes/scope/projects/settings/index.js b/ui/desktop/app/routes/scopes/scope/projects/settings/index.js index 09fb66aae7..4f4766c6c1 100644 --- a/ui/desktop/app/routes/scopes/scope/projects/settings/index.js +++ b/ui/desktop/app/routes/scopes/scope/projects/settings/index.js @@ -14,26 +14,38 @@ export default class ScopesScopeProjectsSettingsIndexRoute extends Route { // =methods async model() { - let cacheDaemonStatus, - formattedCacheVersion, - formattedCliVersion, - formattedDesktopVersion, - cacheDaemonErrors = []; - const { versionNumber: cliVersion } = await this.ipc.invoke('getCliVersion'); - formattedCliVersion = `v${cliVersion}`; const { desktopVersion } = await this.ipc.invoke('getDesktopVersion'); - formattedDesktopVersion = `v${desktopVersion}`; + const cacheDaemonStatus = await this.getCacheStatus(); + const clientAgentStatus = await this.getClientAgentStatus(); + const logLevel = await this.ipc.invoke('getLogLevel'); + const logPath = await this.ipc.invoke('getLogPath'); + const serverInformation = this.clusterUrl.rendererClusterUrl; + + return { + desktopVersion: `v${desktopVersion}`, + cliVersion: `v${cliVersion}`, + cacheDaemonStatus, + clientAgentStatus, + logLevel, + logPath, + serverInformation, + }; + } + + async getCacheStatus() { + let cacheDaemonStatus; + let cacheDaemonStatusError = []; try { cacheDaemonStatus = await this.ipc.invoke('cacheDaemonStatus'); } catch (e) { - cacheDaemonErrors.push(e); + cacheDaemonStatusError.push(e); } const { version, users } = cacheDaemonStatus ?? {}; - formattedCacheVersion = version?.match(/v\d+\.\d+\.\d+/)?.[0]; + const cacheVersion = version?.match(/v\d+\.\d+\.\d+/)?.[0]; // Grab the errors from each resource const userId = this.session.data.authenticated.user_id; @@ -45,20 +57,24 @@ export default class ScopesScopeProjectsSettingsIndexRoute extends Route { message: resource.last_error.error, name: resource.name, })) ?? []; - cacheDaemonErrors = [...cacheDaemonErrors, ...resourceErrors]; - const logLevel = await this.ipc.invoke('getLogLevel'); - const logPath = await this.ipc.invoke('getLogPath'); - const serverInformation = this.clusterUrl.rendererClusterUrl; + const errors = [...cacheDaemonStatusError, ...resourceErrors]; + return { version: cacheVersion, errors }; + } - return { - cacheDaemonErrors, - formattedCliVersion, - formattedCacheVersion, - formattedDesktopVersion, - logLevel, - logPath, - serverInformation, - }; + async getClientAgentStatus() { + let clientAgentStatus; + let clientAgentStatusError = []; + try { + clientAgentStatus = await this.ipc.invoke('clientAgentStatus'); + } catch (e) { + clientAgentStatusError.push(e); + } + + const { version, status, errors: errorMessages } = clientAgentStatus ?? {}; + const statusErrors = errorMessages?.map((message) => ({ message })) ?? []; + + const errors = [...clientAgentStatusError, ...statusErrors]; + return { version: `v${version}`, status, errors }; } } diff --git a/ui/desktop/app/templates/scopes/scope/projects/settings/index.hbs b/ui/desktop/app/templates/scopes/scope/projects/settings/index.hbs index 1d07b63a88..d7b5cd04a8 100644 --- a/ui/desktop/app/templates/scopes/scope/projects/settings/index.hbs +++ b/ui/desktop/app/templates/scopes/scope/projects/settings/index.hbs @@ -4,6 +4,7 @@ }} + \ No newline at end of file diff --git a/ui/desktop/electron-app/src/helpers/spawn-promise.js b/ui/desktop/electron-app/src/helpers/spawn-promise.js index bf6c7e9968..8835509e09 100644 --- a/ui/desktop/electron-app/src/helpers/spawn-promise.js +++ b/ui/desktop/electron-app/src/helpers/spawn-promise.js @@ -99,10 +99,11 @@ module.exports = { * Spawn a child process and return a promise. * Resolves on any output from stdout or stderr. * @param command + * @param options */ - spawn(command) { + spawn(command, options) { return new Promise((resolve, reject) => { - const childProcess = spawn(path(), command); + const childProcess = spawn(path(), command, options); childProcess.stdout.on('data', (data) => { resolve({ childProcess, stdout: data.toString() }); }); diff --git a/ui/desktop/electron-app/src/ipc/handlers.js b/ui/desktop/electron-app/src/ipc/handlers.js index f529ffae1a..6cd8263fa0 100644 --- a/ui/desktop/electron-app/src/ipc/handlers.js +++ b/ui/desktop/electron-app/src/ipc/handlers.js @@ -197,6 +197,21 @@ handle('isClientAgentRunning', async () => { } }); +/** + * Returns the client agent's status + */ +handle('clientAgentStatus', async () => clientAgentDaemonManager.status()); + +/** + * Pauses the client agent + */ +handle('pauseClientAgent', async () => clientAgentDaemonManager.pause()); + +/** + * Resumes the client agent + */ +handle('resumeClientAgent', async () => clientAgentDaemonManager.resume()); + /** * Gets boundary cli version */ @@ -210,7 +225,7 @@ handle('getDesktopVersion', async () => ({ desktopVersion: releaseVersion })); /** * Returns the Cache daemon status */ -handle('cacheDaemonStatus', async () => await cacheDaemonManager.status()); +handle('cacheDaemonStatus', async () => cacheDaemonManager.status()); /** * Returns the current log level diff --git a/ui/desktop/electron-app/src/services/client-agent-daemon-manager.js b/ui/desktop/electron-app/src/services/client-agent-daemon-manager.js index 9111f2bd95..9764ff712d 100644 --- a/ui/desktop/electron-app/src/services/client-agent-daemon-manager.js +++ b/ui/desktop/electron-app/src/services/client-agent-daemon-manager.js @@ -15,7 +15,11 @@ class ClientAgentDaemonManager { */ async status() { const clientAgentStatusCommand = ['client-agent', 'status', '-format=json']; - const { stdout, stderr } = spawnSync(clientAgentStatusCommand); + // The status command can take a while to execute if it's not running as it + // retries multiple times so we should set a timeout to not wait too long + const { stderr, stdout } = await spawn(clientAgentStatusCommand, { + timeout: 500, + }); let parsedResponse = jsonify(stdout); if (parsedResponse?.status_code === 200) { @@ -47,6 +51,46 @@ class ClientAgentDaemonManager { log.warn('Client Agent Sessions:', stderr); return generateErrorPromise(stderr); } + + /** + * Pauses the client agent daemon. + * @return {Promise<*>} + */ + async pause() { + const clientAgentPauseCommand = ['client-agent', 'pause', '-format=json']; + // We use spawn here as pausing can take a while to execute and using spawnSync + // can cause the app to completely freeze and be unresponsive during that time + const { stderr, stdout } = await spawn(clientAgentPauseCommand, { + timeout: 10000, + }); + + let parsedResponse = jsonify(stdout); + if (parsedResponse?.status_code === 200) { + return parsedResponse.item; + } + + log.warn('Client Agent Pause:', stderr); + return generateErrorPromise(stderr); + } + + /** + * Resumes the client agent daemon. + * @return {Promise<*>} + */ + async resume() { + const clientAgentResumeCommand = ['client-agent', 'resume', '-format=json']; + const { stderr, stdout } = await spawn(clientAgentResumeCommand, { + timeout: 10000, + }); + + let parsedResponse = jsonify(stdout); + if (parsedResponse?.status_code === 200) { + return parsedResponse.item; + } + + log.warn('Client Agent Resume:', stderr); + return generateErrorPromise(stderr); + } } // Export an instance so we get a singleton diff --git a/ui/desktop/tests/helpers/window-mock-ipc.js b/ui/desktop/tests/helpers/window-mock-ipc.js index 5f1244e29e..d48fef131f 100644 --- a/ui/desktop/tests/helpers/window-mock-ipc.js +++ b/ui/desktop/tests/helpers/window-mock-ipc.js @@ -34,6 +34,27 @@ class MockIPC { isClientAgentRunning() { return false; } + cacheDaemonStatus() { + return { version: 'Boundary v1.0.0' }; + } + getCliVersion() { + return { versionNumber: '1.0.0' }; + } + getDesktopVersion() { + return { desktopVersion: '1.0.0' }; + } + getLogLevel() { + return 'info'; + } + getLogPath() { + return '~/.config/Boundary/logs/desktop-client.log'; + } + setLogLevel() {} + clientAgentStatus() { + return { version: '0.0.1-dev', status: 'running' }; + } + pauseClientAgent() {} + resumeClientAgent() {} } /** diff --git a/ui/desktop/tests/integration/components/settings-card/application-test.js b/ui/desktop/tests/integration/components/settings-card/application-test.js index afed0dc8fc..2c59ecd378 100644 --- a/ui/desktop/tests/integration/components/settings-card/application-test.js +++ b/ui/desktop/tests/integration/components/settings-card/application-test.js @@ -18,13 +18,18 @@ module('Integration | Component | settings-card/application', function (hooks) { setupRenderingTest(hooks); setupIntl(hooks); + let model; + + hooks.beforeEach(() => { + model = { + cacheDaemonStatus: { version: 'v4.0.0', errors: [] }, + desktopVersion: 'v2.0.0', + cliVersion: 'v3.0.0', + }; + }); + test('it renders', async function (assert) { - this.set('model', { - cacheDaemonErrors: [], - formattedDesktopVersion: 'v2.0.0', - formattedCliVersion: 'v3.0.0', - formattedCacheVersion: 'v4.0.0', - }); + this.set('model', model); this.set('toggleTheme', () => {}); await render( @@ -37,21 +42,17 @@ module('Integration | Component | settings-card/application', function (hooks) { }); test('it renders errors', async function (assert) { - this.set('model', { - cacheDaemonErrors: [ - { - message: `this is a resolvable alias error`, - name: 'resolvable-alias', - }, - { - message: `this is a target error`, - name: 'target', - }, - ], - formattedDesktopVersion: 'v2.0.0', - formattedCliVersion: 'v3.0.0', - formattedCacheVersion: 'v4.0.0', - }); + model.cacheDaemonStatus.errors = [ + { + message: `this is a resolvable alias error`, + name: 'resolvable-alias', + }, + { + message: `this is a target error`, + name: 'target', + }, + ]; + this.set('model', model); this.set('toggleTheme', () => {}); await render( @@ -66,12 +67,7 @@ module('Integration | Component | settings-card/application', function (hooks) { }); test('it indicates when cache daemon is running', async function (assert) { - this.set('model', { - cacheDaemonErrors: [], - formattedDesktopVersion: 'v2.0.0', - formattedCliVersion: 'v3.0.0', - formattedCacheVersion: 'v4.0.0', - }); + this.set('model', model); this.set('toggleTheme', () => {}); await render( @@ -80,12 +76,8 @@ module('Integration | Component | settings-card/application', function (hooks) { assert.dom(CACHE_DAEMON_VERSION).hasText('v4.0.0 Running'); - this.set('model', { - cacheDaemonErrors: [], - formattedDesktopVersion: 'v2.0.0', - formattedCliVersion: 'v3.0.0', - formattedCacheVersion: '', - }); + model.cacheDaemonStatus.version = ''; + this.set('model', structuredClone(model)); assert.dom(CACHE_DAEMON_VERSION).hasText('Not Running'); }); }); diff --git a/ui/desktop/tests/integration/components/settings-card/client-agent-test.js b/ui/desktop/tests/integration/components/settings-card/client-agent-test.js new file mode 100644 index 0000000000..45e8ae6af8 --- /dev/null +++ b/ui/desktop/tests/integration/components/settings-card/client-agent-test.js @@ -0,0 +1,84 @@ +/** + * Copyright (c) HashiCorp, Inc. + * SPDX-License-Identifier: BUSL-1.1 + */ + +import { module, test } from 'qunit'; +import { setupRenderingTest } from 'ember-qunit'; +import { render } from '@ember/test-helpers'; +import { hbs } from 'ember-cli-htmlbars'; +import { setupIntl } from 'ember-intl/test-support'; + +const STATUS_BADGE = '.hds-badge'; +const ACTION_BUTTON = 'button'; +const CARD_CONTAINER = 'hds-card__container'; +const ERROR_MESSAGES = '.hds-alert__description > p'; +const LAST_ERROR_MESSAGE = '.hds-alert__description > p:last-child'; + +module( + 'Integration | Component | settings-card/client-agent', + function (hooks) { + setupRenderingTest(hooks); + setupIntl(hooks); + + test('it renders running badge and pause button', async function (assert) { + this.set('model', { + clientAgentStatus: { + status: 'running', + errors: [], + }, + }); + + await render(hbs``); + + assert.dom(STATUS_BADGE).hasText('Running'); + assert.dom(ACTION_BUTTON).hasText('Pause'); + }); + + test('it renders paused badge and resume button', async function (assert) { + this.set('model', { + clientAgentStatus: { + status: 'paused', + errors: [], + }, + }); + + await render(hbs``); + + assert.dom(STATUS_BADGE).hasText('Paused'); + assert.dom(ACTION_BUTTON).hasText('Resume'); + }); + + test('it does not render component if there is no status', async function (assert) { + this.set('model', { + clientAgentStatus: { + errors: [{ message: 'agent is offline' }], + }, + }); + + await render(hbs``); + + assert.dom(STATUS_BADGE).doesNotExist(); + assert.dom(ACTION_BUTTON).doesNotExist(); + assert.dom(CARD_CONTAINER).doesNotExist(); + }); + + test('it renders errors', async function (assert) { + this.set('model', { + clientAgentStatus: { + status: 'running', + errors: [ + { message: 'agent is wonky' }, + { message: 'another error' }, + { message: 'big oof' }, + ], + }, + }); + + await render(hbs``); + + assert.dom(ERROR_MESSAGES).isVisible({ count: 3 }); + assert.dom(LAST_ERROR_MESSAGE).hasText('big oof'); + }); + }, +); From 695d9d413dac317e01312ab9413716d24585d391 Mon Sep 17 00:00:00 2001 From: Dharini Jeeva Date: Tue, 20 Aug 2024 16:46:28 -0700 Subject: [PATCH 09/14] =?UTF-8?q?fix:=20=F0=9F=90=9B=20remove=20connected?= =?UTF-8?q?=20lable=20(#2446)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- addons/core/translations/en-us.yaml | 1 - ui/desktop/app/components/settings-card/server/index.hbs | 9 --------- 2 files changed, 10 deletions(-) diff --git a/addons/core/translations/en-us.yaml b/addons/core/translations/en-us.yaml index 8cf9176cfc..d398d28547 100644 --- a/addons/core/translations/en-us.yaml +++ b/addons/core/translations/en-us.yaml @@ -118,7 +118,6 @@ settings: provider: Provider hcp: HashiCorp Cloud Platform self-managed: Self-managed - connected: Connected server: title: Server description: Boundary connects you to targets using this server managed by your organization. diff --git a/ui/desktop/app/components/settings-card/server/index.hbs b/ui/desktop/app/components/settings-card/server/index.hbs index cee93da88b..2a289e60ca 100644 --- a/ui/desktop/app/components/settings-card/server/index.hbs +++ b/ui/desktop/app/components/settings-card/server/index.hbs @@ -8,15 +8,6 @@ @icon='cloud' @description={{t 'settings.server.description'}} > - <:state> - {{#if @model.serverInformation}} - - {{/if}} - <:body>
From 12669306479e0ef4b53d242a450055b42ea6f665 Mon Sep 17 00:00:00 2001 From: Zhihe Li Date: Wed, 21 Aug 2024 14:29:17 -0400 Subject: [PATCH 10/14] =?UTF-8?q?chore:=20=F0=9F=A4=96=20Remove=20client?= =?UTF-8?q?=20agent=20feature=20flag=20(#2449)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../app/routes/scopes/scope/projects.js | 25 ++++++++----------- .../scopes/scope/projects/sessions/session.js | 2 -- ui/desktop/config/environment.js | 7 +----- 3 files changed, 11 insertions(+), 23 deletions(-) diff --git a/ui/desktop/app/routes/scopes/scope/projects.js b/ui/desktop/app/routes/scopes/scope/projects.js index a4160ed1c4..736c8a190b 100644 --- a/ui/desktop/app/routes/scopes/scope/projects.js +++ b/ui/desktop/app/routes/scopes/scope/projects.js @@ -36,7 +36,6 @@ export default class ScopesScopeProjectsRoute extends Route { @service clientAgentSessions; @service pollster; @service flashMessages; - @service features; // =methods @@ -52,21 +51,17 @@ export default class ScopesScopeProjectsRoute extends Route { * @return {Promise} */ async model() { - if (this.features.isEnabled('client-agent')) { - // Setup the poller job - if (!this.job) { - this.boundPoller = this.poller.bind(this); - this.job = this.pollster.findOrCreateJob(this.boundPoller, 2000); - } + // Setup the poller job + if (!this.job) { + this.boundPoller = this.poller.bind(this); + this.job = this.pollster.findOrCreateJob(this.boundPoller, 2000); + } - const isClientAgentRunning = await this.ipc.invoke( - 'isClientAgentRunning', - ); - if (isClientAgentRunning) { - this.job.start(); - } else { - this.job.stop(); - } + const isClientAgentRunning = await this.ipc.invoke('isClientAgentRunning'); + if (isClientAgentRunning) { + this.job.start(); + } else { + this.job.stop(); } const { id: scope_id } = this.modelFor('scopes.scope'); diff --git a/ui/desktop/app/routes/scopes/scope/projects/sessions/session.js b/ui/desktop/app/routes/scopes/scope/projects/sessions/session.js index 53ea5d197e..2fe6171ef3 100644 --- a/ui/desktop/app/routes/scopes/scope/projects/sessions/session.js +++ b/ui/desktop/app/routes/scopes/scope/projects/sessions/session.js @@ -14,7 +14,6 @@ export default class ScopesScopeProjectsSessionsSessionRoute extends Route { @service clientAgentSessions; @service flashMessages; @service intl; - @service features; // =methods @@ -30,7 +29,6 @@ export default class ScopesScopeProjectsSessionsSessionRoute extends Route { // If we don't have any credentials, we'll try to fetch them from the client agent in case this session // was initiated through the client agent. if ( - this.features.isEnabled('client-agent') && !session.credentials.length && (await this.ipc.invoke('isClientAgentRunning')) ) { diff --git a/ui/desktop/config/environment.js b/ui/desktop/config/environment.js index d3ae0cfaf7..801c944cfd 100644 --- a/ui/desktop/config/environment.js +++ b/ui/desktop/config/environment.js @@ -60,9 +60,7 @@ module.exports = function (environment) { timeout: 4000, }, - featureFlags: { - 'client-agent': false, - }, + featureFlags: {}, }; if (environment === 'development') { @@ -80,9 +78,6 @@ module.exports = function (environment) { ENV['ember-cli-mirage'].enabled = process.env.ENABLE_MIRAGE ? JSON.parse(process.env.ENABLE_MIRAGE) : true; - - // Enable features in development - ENV.featureFlags['client-agent'] = true; } if (environment === 'test') { From 6cd2f0f7d88170b7c4a37a17c132cfa8f664f9a2 Mon Sep 17 00:00:00 2001 From: Zhihe Li Date: Fri, 23 Aug 2024 15:21:34 -0400 Subject: [PATCH 11/14] =?UTF-8?q?fix:=20=F0=9F=90=9B=20Fix=20windows=20han?= =?UTF-8?q?ging=20when=20client=20agent=20isn't=20running=20(#2459)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../electron-app/src/helpers/spawn-promise.js | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/ui/desktop/electron-app/src/helpers/spawn-promise.js b/ui/desktop/electron-app/src/helpers/spawn-promise.js index 8835509e09..e057c04988 100644 --- a/ui/desktop/electron-app/src/helpers/spawn-promise.js +++ b/ui/desktop/electron-app/src/helpers/spawn-promise.js @@ -90,9 +90,9 @@ module.exports = { }, }); - const { stdout, stderr } = childProcess; + const { stdout, stderr, error } = childProcess; - return { stdout: stdout?.toString(), stderr: stderr?.toString() }; + return { stdout: stdout?.toString(), stderr: stderr?.toString(), error }; }, /** @@ -111,6 +111,19 @@ module.exports = { resolve({ childProcess, stderr: data.toString() }); }); childProcess.on('error', (err) => reject(err)); + + // In case the process has no stdio and didn't error out, resolve a + // promise once the child process closes so we're not waiting forever. + // Windows doesn't seem to return any error nor any output from stderr when + // a timeout occurs so this guarantees we return a response to the caller. + // Otherwise this should not get hit as we should be returning a response + // from one of the handlers above. + childProcess.on('close', () => + resolve({ + childProcess, + stderr: JSON.stringify({ error: 'Process was closed.' }), + }), + ); }); }, }; From c8abc3845a7787a9c4b2dffc2e290af9425901b8 Mon Sep 17 00:00:00 2001 From: Dharini Jeeva Date: Thu, 5 Sep 2024 11:11:36 -0700 Subject: [PATCH 12/14] =?UTF-8?q?fix:=20=F0=9F=90=9B=20pass=20current=20us?= =?UTF-8?q?l=20to=20maintain=20session=20(#2472)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ✅ Closes: https://hashicorp.atlassian.net/browse/ICU-14963 --- ui/desktop/app/components/settings-card/client-agent/index.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ui/desktop/app/components/settings-card/client-agent/index.js b/ui/desktop/app/components/settings-card/client-agent/index.js index 2ba238c340..f75d5ff08e 100644 --- a/ui/desktop/app/components/settings-card/client-agent/index.js +++ b/ui/desktop/app/components/settings-card/client-agent/index.js @@ -63,6 +63,6 @@ export default class SettingsCardClientAgentComponent extends Component { } else { await this.ipc.invoke('resumeClientAgent'); } - await this.router.refresh(); + await this.router.refresh('scopes.scope.projects.settings'); } } From 20e6df522a4cd696bec1fa4d0e3f9a53c9e35677 Mon Sep 17 00:00:00 2001 From: Zhihe Li Date: Thu, 5 Sep 2024 18:03:45 -0400 Subject: [PATCH 13/14] =?UTF-8?q?feat:=20=F0=9F=8E=B8=20Hide=20daemon=20er?= =?UTF-8?q?rors=20initially=20(#2477)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * feat: 🎸 Hide daemon errors initially ✅ Closes: https://hashicorp.atlassian.net/browse/ICU-14961 * feat: 🎸 Move the user and server cards up in settings ✅ Closes: https://hashicorp.atlassian.net/browse/ICU-14962 --- addons/core/translations/actions/en-us.yaml | 2 ++ .../settings-card/application/index.hbs | 21 ++++++++++++------- .../settings-card/client-agent/index.hbs | 15 ++++++++----- .../scopes/scope/projects/settings/index.hbs | 4 ++-- .../settings-card/application-test.js | 13 ++++++++---- .../settings-card/client-agent-test.js | 11 +++++++--- 6 files changed, 44 insertions(+), 22 deletions(-) diff --git a/addons/core/translations/actions/en-us.yaml b/addons/core/translations/actions/en-us.yaml index f23351b08a..0eefc7a680 100644 --- a/addons/core/translations/actions/en-us.yaml +++ b/addons/core/translations/actions/en-us.yaml @@ -62,3 +62,5 @@ yes: Yes no: No narrow-results: Narrow results overflow-options: Overflow Options +show-errors: Show Errors +hide-errors: Hide Errors diff --git a/ui/desktop/app/components/settings-card/application/index.hbs b/ui/desktop/app/components/settings-card/application/index.hbs index b8539a6b1d..4828b0214a 100644 --- a/ui/desktop/app/components/settings-card/application/index.hbs +++ b/ui/desktop/app/components/settings-card/application/index.hbs @@ -47,14 +47,19 @@ {{t 'settings.alerts.cache-daemon'}} - {{#each @model.cacheDaemonStatus.errors as |error|}} - - {{#if error.name}} - {{error.name}}: - {{/if}} - {{error.message}} - - {{/each}} + + {{#each @model.cacheDaemonStatus.errors as |error|}} + + {{#if error.name}} + {{error.name}}: + {{/if}} + {{error.message}} + + {{/each}} + {{/if}} diff --git a/ui/desktop/app/components/settings-card/client-agent/index.hbs b/ui/desktop/app/components/settings-card/client-agent/index.hbs index b04aec8b93..4daedad109 100644 --- a/ui/desktop/app/components/settings-card/client-agent/index.hbs +++ b/ui/desktop/app/components/settings-card/client-agent/index.hbs @@ -37,11 +37,16 @@ {{t 'settings.alerts.client-agent'}} - {{#each @model.clientAgentStatus.errors as |error|}} - - {{error.message}} - - {{/each}} + + {{#each @model.clientAgentStatus.errors as |error|}} + + {{error.message}} + + {{/each}} + {{/if}} diff --git a/ui/desktop/app/templates/scopes/scope/projects/settings/index.hbs b/ui/desktop/app/templates/scopes/scope/projects/settings/index.hbs index d7b5cd04a8..5220d737d5 100644 --- a/ui/desktop/app/templates/scopes/scope/projects/settings/index.hbs +++ b/ui/desktop/app/templates/scopes/scope/projects/settings/index.hbs @@ -3,8 +3,8 @@ SPDX-License-Identifier: BUSL-1.1 }} - - + + \ No newline at end of file diff --git a/ui/desktop/tests/integration/components/settings-card/application-test.js b/ui/desktop/tests/integration/components/settings-card/application-test.js index 2c59ecd378..a5ac67e80f 100644 --- a/ui/desktop/tests/integration/components/settings-card/application-test.js +++ b/ui/desktop/tests/integration/components/settings-card/application-test.js @@ -5,14 +5,15 @@ import { module, test } from 'qunit'; import { setupRenderingTest } from 'ember-qunit'; -import { render } from '@ember/test-helpers'; +import { click, render } from '@ember/test-helpers'; import { hbs } from 'ember-cli-htmlbars'; import { setupIntl } from 'ember-intl/test-support'; const CACHE_DAEMON_VERSION = '[data-test-cache-version]'; -const ERROR_MESSAGES = '.hds-alert__description > p'; -const FIRST_ERROR_MESSAGE = '.hds-alert__description > p:first-child'; -const LAST_ERROR_MESSAGE = '.hds-alert__description > p:last-child'; +const ERROR_MESSAGES = '.hds-reveal__content > p'; +const REVEAL_BUTTON = '.hds-reveal button'; +const FIRST_ERROR_MESSAGE = '.hds-reveal__content > p:first-child'; +const LAST_ERROR_MESSAGE = '.hds-reveal__content > p:last-child'; module('Integration | Component | settings-card/application', function (hooks) { setupRenderingTest(hooks); @@ -59,6 +60,10 @@ module('Integration | Component | settings-card/application', function (hooks) { hbs``, ); + assert.dom(ERROR_MESSAGES).doesNotExist(); + + await click(REVEAL_BUTTON); + assert.dom(ERROR_MESSAGES).isVisible({ count: 2 }); assert .dom(FIRST_ERROR_MESSAGE) diff --git a/ui/desktop/tests/integration/components/settings-card/client-agent-test.js b/ui/desktop/tests/integration/components/settings-card/client-agent-test.js index 45e8ae6af8..f8208ddcc4 100644 --- a/ui/desktop/tests/integration/components/settings-card/client-agent-test.js +++ b/ui/desktop/tests/integration/components/settings-card/client-agent-test.js @@ -5,15 +5,16 @@ import { module, test } from 'qunit'; import { setupRenderingTest } from 'ember-qunit'; -import { render } from '@ember/test-helpers'; +import { click, render } from '@ember/test-helpers'; import { hbs } from 'ember-cli-htmlbars'; import { setupIntl } from 'ember-intl/test-support'; const STATUS_BADGE = '.hds-badge'; const ACTION_BUTTON = 'button'; +const REVEAL_BUTTON = '.hds-reveal button'; const CARD_CONTAINER = 'hds-card__container'; -const ERROR_MESSAGES = '.hds-alert__description > p'; -const LAST_ERROR_MESSAGE = '.hds-alert__description > p:last-child'; +const ERROR_MESSAGES = '.hds-reveal__content > p'; +const LAST_ERROR_MESSAGE = '.hds-reveal__content > p:last-child'; module( 'Integration | Component | settings-card/client-agent', @@ -77,6 +78,10 @@ module( await render(hbs``); + assert.dom(ERROR_MESSAGES).doesNotExist(); + + await click(REVEAL_BUTTON); + assert.dom(ERROR_MESSAGES).isVisible({ count: 3 }); assert.dom(LAST_ERROR_MESSAGE).hasText('big oof'); }); From ace65eab3ab118d8465fbc0b39e3b908c8c2f770 Mon Sep 17 00:00:00 2001 From: Zhihe Li Date: Fri, 20 Sep 2024 11:41:47 -0400 Subject: [PATCH 14/14] =?UTF-8?q?fix:=20=F0=9F=90=9B=20Fix=20theme=20selec?= =?UTF-8?q?tor=20not=20properly=20selecting=20option=20(#2495)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ui/desktop/app/components/settings-card/application/index.js | 4 ++++ .../integration/components/settings-card/application-test.js | 2 +- .../integration/components/settings-card/client-agent-test.js | 2 +- .../tests/integration/components/settings-card/logs-test.js | 2 +- .../tests/integration/components/settings-card/server-test.js | 2 +- .../tests/integration/components/settings-card/user-test.js | 2 +- 6 files changed, 9 insertions(+), 5 deletions(-) diff --git a/ui/desktop/app/components/settings-card/application/index.js b/ui/desktop/app/components/settings-card/application/index.js index 4bd00b484a..6e38af3d54 100644 --- a/ui/desktop/app/components/settings-card/application/index.js +++ b/ui/desktop/app/components/settings-card/application/index.js @@ -4,6 +4,7 @@ */ import Component from '@glimmer/component'; +import { inject as service } from '@ember/service'; const THEMES = [ { @@ -21,6 +22,9 @@ const THEMES = [ ]; export default class SettingsApplicationComponent extends Component { + // =services + @service session; + /** * Returns available themes */ diff --git a/ui/desktop/tests/integration/components/settings-card/application-test.js b/ui/desktop/tests/integration/components/settings-card/application-test.js index a5ac67e80f..0909621400 100644 --- a/ui/desktop/tests/integration/components/settings-card/application-test.js +++ b/ui/desktop/tests/integration/components/settings-card/application-test.js @@ -17,7 +17,7 @@ const LAST_ERROR_MESSAGE = '.hds-reveal__content > p:last-child'; module('Integration | Component | settings-card/application', function (hooks) { setupRenderingTest(hooks); - setupIntl(hooks); + setupIntl(hooks, 'en-us'); let model; diff --git a/ui/desktop/tests/integration/components/settings-card/client-agent-test.js b/ui/desktop/tests/integration/components/settings-card/client-agent-test.js index f8208ddcc4..bf85439ef0 100644 --- a/ui/desktop/tests/integration/components/settings-card/client-agent-test.js +++ b/ui/desktop/tests/integration/components/settings-card/client-agent-test.js @@ -20,7 +20,7 @@ module( 'Integration | Component | settings-card/client-agent', function (hooks) { setupRenderingTest(hooks); - setupIntl(hooks); + setupIntl(hooks, 'en-us'); test('it renders running badge and pause button', async function (assert) { this.set('model', { diff --git a/ui/desktop/tests/integration/components/settings-card/logs-test.js b/ui/desktop/tests/integration/components/settings-card/logs-test.js index 4131c3e786..7dd622ecee 100644 --- a/ui/desktop/tests/integration/components/settings-card/logs-test.js +++ b/ui/desktop/tests/integration/components/settings-card/logs-test.js @@ -11,7 +11,7 @@ import { setupIntl } from 'ember-intl/test-support'; module('Integration | Component | settings-card/logs', function (hooks) { setupRenderingTest(hooks); - setupIntl(hooks); + setupIntl(hooks, 'en-us'); const SELECTED_OPTION = 'select option:checked'; const COPY_BUTTON_TEXT = '.hds-copy-snippet__text'; diff --git a/ui/desktop/tests/integration/components/settings-card/server-test.js b/ui/desktop/tests/integration/components/settings-card/server-test.js index f1b4a53f4f..7bc997a7ba 100644 --- a/ui/desktop/tests/integration/components/settings-card/server-test.js +++ b/ui/desktop/tests/integration/components/settings-card/server-test.js @@ -14,7 +14,7 @@ const SERVER_URL = '[data-test-server-url]'; module('Integration | Component | settings-card/server', function (hooks) { setupRenderingTest(hooks); - setupIntl(hooks); + setupIntl(hooks, 'en-us'); const setDefaultClusterUrl = (test) => { const windowOrigin = 'hashicorp.cloud'; diff --git a/ui/desktop/tests/integration/components/settings-card/user-test.js b/ui/desktop/tests/integration/components/settings-card/user-test.js index daa1bf0483..91bd82cd4b 100644 --- a/ui/desktop/tests/integration/components/settings-card/user-test.js +++ b/ui/desktop/tests/integration/components/settings-card/user-test.js @@ -23,7 +23,7 @@ const AUTHENTICATION_BADGE = '.hds-badge__text'; module('Integration | Component | settings-card/user', function (hooks) { setupRenderingTest(hooks); - setupIntl(hooks); + setupIntl(hooks, 'en-us'); test('it renders password correctly', async function (assert) { this.owner.register(