toggleTheme.ts 1.6 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455
  1. import { createTheme } from '@grafana/data';
  2. import { ThemeChangedEvent } from '@grafana/runtime';
  3. import appEvents from '../app_events';
  4. import { config } from '../config';
  5. import { contextSrv } from '../core';
  6. import { PreferencesService } from './PreferencesService';
  7. export async function toggleTheme(runtimeOnly: boolean) {
  8. const currentTheme = config.theme;
  9. const newTheme = createTheme({
  10. colors: {
  11. mode: currentTheme.isDark ? 'light' : 'dark',
  12. },
  13. });
  14. appEvents.publish(new ThemeChangedEvent(newTheme));
  15. if (runtimeOnly) {
  16. return;
  17. }
  18. // Add css file for new theme
  19. const newCssLink = document.createElement('link');
  20. newCssLink.rel = 'stylesheet';
  21. newCssLink.href = config.bootData.themePaths[newTheme.colors.mode];
  22. document.body.appendChild(newCssLink);
  23. // Remove old css file
  24. const bodyLinks = document.getElementsByTagName('link');
  25. for (let i = 0; i < bodyLinks.length; i++) {
  26. const link = bodyLinks[i];
  27. if (link.href && link.href.indexOf(`build/grafana.${currentTheme.type}`) > 0) {
  28. // Remove existing link after a 500ms to allow new css to load to avoid flickering
  29. // If we add new css at the same time we remove current one the page will be rendered without css
  30. // As the new css file is loading
  31. setTimeout(() => link.remove(), 500);
  32. }
  33. }
  34. if (!contextSrv.isSignedIn) {
  35. return;
  36. }
  37. // Persist new theme
  38. const service = new PreferencesService('user');
  39. const currentPref = await service.load();
  40. await service.update({
  41. ...currentPref,
  42. theme: newTheme.colors.mode,
  43. });
  44. }