diff --git a/addons/api/mirage/scenarios/ipc.js b/addons/api/mirage/scenarios/ipc.js index d2b54b917..6366fbb6c 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 ce1c90291..e7c06f941 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 525883d68..d8893de1a 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 ce37d4afa..4ecf3007a 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 000000000..a27036983 --- /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 12cb417bf..3c9060416 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 531ec047a..e8b47aa48 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 c79d9a83f..baa97b134 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 d14e21775..9551c3f23 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 8207eb035..8adb8bb71 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 01f5b4950..0d953151d 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 000000000..b022512df --- /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', + ); + }); +});