From 777380e19ff4e1012aaef0f2f58997f7b1471a28 Mon Sep 17 00:00:00 2001 From: Dharini Jeeva Date: Tue, 6 Aug 2024 12:21:44 -0700 Subject: [PATCH] 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 e7c06f941..dd29f0473 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 511049c93..4cd4a5637 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 b34531637..4c3e88696 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 4d9e491b4..b939cd0ff 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 3b4913ed3..ba816f415 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 9551c3f23..8d6912696 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 6e2856afd..f7cf69da7 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 0d953151d..c8624383b 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')); + }); });