Add theme selection (#2428)

* fix: 🐛 remove theme from main menu bar and move to settings pag

* chore: 🤖 move toggletheme to app controller
This commit is contained in:
Dharini Jeeva authored and Zhihe Li committed 2024-09-24 11:58:24 -04:00
1 parent 25b3a940a3
commit 777380e19f
8 files changed
+132 -110

No files matched your search

+1
View File
@@ -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
+27 -1
View File
@@ -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');
}
}
}
@@ -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);
}
}
+4 -29
View File
@@ -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');
}
}
}
-35
View File
@@ -53,41 +53,6 @@
<dropdown.button {{on 'click' this.invalidateSession}}>
{{t 'actions.deauthenticate'}}
</dropdown.button>
<dropdown.separator />
<dropdown.section @title={{t 'actions.toggle-color-theme'}}>
<Rose::Form as |form|>
<form.radioGroup
@name='theme'
@selectedValue={{or
this.session.data.theme
'system-default-theme'
}}
@changed={{route-action 'toggleTheme'}}
as |radioGroup|
>
<dropdown.item>
<radioGroup.radio
@label={{t 'themes.system'}}
@value='system-default-theme'
/>
</dropdown.item>
<dropdown.item>
<radioGroup.radio
@label={{t 'themes.light'}}
@value='light'
/>
</dropdown.item>
<dropdown.item>
<radioGroup.radio
@label={{t 'themes.dark'}}
@value='dark'
/>
</dropdown.item>
</form.radioGroup>
</Rose::Form>
</dropdown.section>
</utilities.dropdown>
{{/if}}
@@ -52,5 +52,24 @@
{{/if}}
</Hds::Alert>
{{/if}}
<Hds::Form::Select::Field
name='theme'
@width='30%'
{{on 'change' this.toggleTheme}}
as |F|
>
<F.Label>{{t 'titles.color-theme'}}</F.Label>
<F.Options>
{{#each this.themes as |theme|}}
<option
value={{theme.value}}
selected={{eq this.session.data.theme theme.value}}
>
{{t (concat 'themes.' theme.label)}}
</option>
{{/each}}
</F.Options>
</Hds::Form::Select::Field>
</:body>
</SettingsCard>
@@ -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);
@@ -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'));
});
});