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:
1 parent
25b3a940a3
commit
777380e19f
8 files changed
+132
-110
No files matched your search
@@ -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
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -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');
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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'));
|
||||
});
|
||||
});
|
||||
Reference in new issue
Block a user