configStore.tsx 2.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104
  1. import moment from 'moment-timezone';
  2. import * as qs from 'query-string';
  3. import Reflux from 'reflux';
  4. import {setLocale} from 'app/locale';
  5. import {Config} from 'app/types';
  6. type ConfigStoreInterface = {
  7. config: Config;
  8. get<K extends keyof Config>(key: K): Config[K];
  9. set<K extends keyof Config>(key: K, value: Config[K]): void;
  10. getConfig(): Config;
  11. updateTheme(theme: 'light' | 'dark'): void;
  12. loadInitialData(config: Config): void;
  13. };
  14. const configStoreConfig: Reflux.StoreDefinition & ConfigStoreInterface = {
  15. // When the app is booted we will _immediately_ hydrate the config store,
  16. // effecively ensureing this is not empty.
  17. config: {} as Config,
  18. init(): void {
  19. this.config = {} as Config;
  20. },
  21. get(key) {
  22. return this.config[key];
  23. },
  24. set(key, value) {
  25. this.config = {
  26. ...this.config,
  27. [key]: value,
  28. };
  29. this.trigger({[key]: value});
  30. },
  31. /**
  32. * This is only called by media query listener so that we can control
  33. * the auto switching of color schemes without affecting manual toggle
  34. */
  35. updateTheme(theme) {
  36. if (this.config.user?.options.theme !== 'system') {
  37. return;
  38. }
  39. this.set('theme', theme);
  40. },
  41. getConfig() {
  42. return this.config;
  43. },
  44. loadInitialData(config): void {
  45. const shouldUseDarkMode = config.user?.options.theme === 'dark';
  46. this.config = {
  47. ...config,
  48. features: new Set(config.features || []),
  49. theme: shouldUseDarkMode ? 'dark' : 'light',
  50. };
  51. // Language code is passed from django
  52. let languageCode = config.languageCode;
  53. // TODO(dcramer): abstract this out of ConfigStore
  54. if (config.user) {
  55. config.user.permissions = new Set(config.user.permissions);
  56. moment.tz.setDefault(config.user.options.timezone);
  57. let queryString: qs.ParsedQuery = {};
  58. // Parse query string for `lang`
  59. try {
  60. queryString = qs.parse(window.location.search) || {};
  61. } catch (err) {
  62. // ignore if this fails to parse
  63. // this can happen if we have an invalid query string
  64. // e.g. unencoded "%"
  65. }
  66. let queryStringLang = queryString.lang;
  67. if (Array.isArray(queryStringLang)) {
  68. queryStringLang = queryStringLang[0];
  69. }
  70. languageCode = queryStringLang || config.user.options.language || languageCode;
  71. }
  72. // Priority:
  73. // "?lang=en" --> user configuration options --> django request.LANGUAGE_CODE --> "en"
  74. setLocale(languageCode || 'en');
  75. this.trigger(config);
  76. },
  77. };
  78. type ConfigStore = Reflux.Store & ConfigStoreInterface;
  79. const ConfigStore = Reflux.createStore(configStoreConfig) as ConfigStore;
  80. export default ConfigStore;