mirror of https://github.com/grafana/grafana
Themes: Switch theme without reload using global shortcut (#32180)
* Themes: Switch theme without reload using global shortcut * Review updatespull/32016/head
parent
79f0cf7874
commit
5821783068
@ -0,0 +1,14 @@ |
||||
import { UserPreferencesDTO } from 'app/types'; |
||||
import { backendSrv } from './backend_srv'; |
||||
|
||||
export class PreferencesService { |
||||
constructor(private resourceUri: string) {} |
||||
|
||||
update(preferences: UserPreferencesDTO): Promise<any> { |
||||
return backendSrv.put(`/api/${this.resourceUri}/preferences`, preferences); |
||||
} |
||||
|
||||
load(): Promise<UserPreferencesDTO> { |
||||
return backendSrv.get<UserPreferencesDTO>(`/api/${this.resourceUri}/preferences`); |
||||
} |
||||
} |
@ -0,0 +1,43 @@ |
||||
import { getTheme } from '@grafana/ui'; |
||||
import { ThemeChangedEvent } from 'app/types/events'; |
||||
import appEvents from '../app_events'; |
||||
import { config } from '../config'; |
||||
import { PreferencesService } from './PreferencesService'; |
||||
|
||||
export async function toggleTheme(runtimeOnly: boolean) { |
||||
const currentTheme = config.theme; |
||||
const newTheme = getTheme(currentTheme.isDark ? 'light' : 'dark'); |
||||
appEvents.publish(new ThemeChangedEvent(newTheme)); |
||||
|
||||
if (runtimeOnly) { |
||||
return; |
||||
} |
||||
|
||||
// Add css file for new theme
|
||||
const newCssLink = document.createElement('link'); |
||||
newCssLink.rel = 'stylesheet'; |
||||
newCssLink.href = config.bootData.themePaths[newTheme.type]; |
||||
document.body.appendChild(newCssLink); |
||||
|
||||
// Remove old css file
|
||||
const bodyLinks = document.getElementsByTagName('link'); |
||||
for (let i = 0; i < bodyLinks.length; i++) { |
||||
const link = bodyLinks[i]; |
||||
|
||||
if (link.href && link.href.indexOf(`build/grafana.${currentTheme.type}`) > 0) { |
||||
// Remove existing link after a 500ms to allow new css to load to avoid flickering
|
||||
// If we add new css at the same time we remove current one the page will be rendered without css
|
||||
// As the new css file is loading
|
||||
setTimeout(() => link.remove(), 500); |
||||
} |
||||
} |
||||
|
||||
// Persist new theme
|
||||
const service = new PreferencesService('user'); |
||||
const currentPref = await service.load(); |
||||
|
||||
await service.update({ |
||||
...currentPref, |
||||
theme: newTheme.type, |
||||
}); |
||||
} |
@ -1,71 +0,0 @@ |
||||
import { coreModule, NavModelSrv } from 'app/core/core'; |
||||
import { dateTimeFormat, dateTimeFormatTimeAgo } from '@grafana/data'; |
||||
import { UserSession } from 'app/types'; |
||||
import { getBackendSrv } from '@grafana/runtime'; |
||||
import { promiseToDigest } from 'app/core/utils/promiseToDigest'; |
||||
import { IScope } from 'angular'; |
||||
|
||||
export class ProfileCtrl { |
||||
sessions: object[] = []; |
||||
navModel: any; |
||||
|
||||
/** @ngInject */ |
||||
constructor(private $scope: IScope, navModelSrv: NavModelSrv) { |
||||
this.getUserSessions(); |
||||
this.navModel = navModelSrv.getNav('profile', 'profile-settings', 0); |
||||
} |
||||
|
||||
getUserSessions() { |
||||
promiseToDigest(this.$scope)( |
||||
getBackendSrv() |
||||
.get('/api/user/auth-tokens') |
||||
.then((sessions: UserSession[]) => { |
||||
sessions.reverse(); |
||||
|
||||
const found = sessions.findIndex((session: UserSession) => { |
||||
return session.isActive; |
||||
}); |
||||
|
||||
if (found) { |
||||
const now = sessions[found]; |
||||
sessions.splice(found, found); |
||||
sessions.unshift(now); |
||||
} |
||||
|
||||
this.sessions = sessions.map((session: UserSession) => { |
||||
return { |
||||
id: session.id, |
||||
isActive: session.isActive, |
||||
seenAt: dateTimeFormatTimeAgo(session.seenAt), |
||||
createdAt: dateTimeFormat(session.createdAt, { format: 'MMMM DD, YYYY' }), |
||||
clientIp: session.clientIp, |
||||
browser: session.browser, |
||||
browserVersion: session.browserVersion, |
||||
os: session.os, |
||||
osVersion: session.osVersion, |
||||
device: session.device, |
||||
}; |
||||
}); |
||||
}) |
||||
); |
||||
} |
||||
|
||||
revokeUserSession(tokenId: number) { |
||||
promiseToDigest(this.$scope)( |
||||
getBackendSrv() |
||||
.post('/api/user/revoke-auth-token', { |
||||
authTokenId: tokenId, |
||||
}) |
||||
.then(() => { |
||||
this.sessions = this.sessions.filter((session: UserSession) => { |
||||
if (session.id === tokenId) { |
||||
return false; |
||||
} |
||||
return true; |
||||
}); |
||||
}) |
||||
); |
||||
} |
||||
} |
||||
|
||||
coreModule.controller('ProfileCtrl', ProfileCtrl); |
@ -0,0 +1,7 @@ |
||||
import { TimeZone } from '@grafana/data'; |
||||
|
||||
export interface UserPreferencesDTO { |
||||
timezone: TimeZone; |
||||
homeDashboardId: number; |
||||
theme: string; |
||||
} |
Loading…
Reference in new issue