Просмотр исходного кода

persist config 'customize:theme:forceColorScheme'

Yuki Takei 3 лет назад
Родитель
Сommit
90f276d3e5

+ 3 - 3
packages/app/src/components/Admin/Customize/CustomizeThemeOptions.tsx

@@ -9,7 +9,7 @@ import { ThemeColorBox } from './ThemeColorBox';
 type Props = {
   availableThemes: GrowiThemeMetadata[],
   selectedTheme?: string,
-  onSelected?: (themeName: string) => void,
+  onSelected?: (themeName: string, schemeType: GrowiThemeSchemeType) => void,
 };
 
 const CustomizeThemeOptions = (props: Props): JSX.Element => {
@@ -36,7 +36,7 @@ const CustomizeThemeOptions = (props: Props): JSX.Element => {
                 key={theme.name}
                 isSelected={selectedTheme != null && selectedTheme === theme.name}
                 metadata={theme}
-                onSelected={() => onSelected?.(theme.name)}
+                onSelected={() => onSelected?.(theme.name, theme.schemeType)}
               />
             );
           })}
@@ -52,7 +52,7 @@ const CustomizeThemeOptions = (props: Props): JSX.Element => {
                 key={theme.name}
                 isSelected={selectedTheme != null && selectedTheme === theme.name}
                 metadata={theme}
-                onSelected={() => onSelected?.(theme.name)}
+                onSelected={() => onSelected?.(theme.name, theme.schemeType)}
               />
             );
           })}

+ 9 - 6
packages/app/src/components/Admin/Customize/CustomizeThemeSetting.tsx

@@ -1,9 +1,9 @@
 import React, { useCallback, useEffect, useState } from 'react';
 
+import { GrowiThemeSchemeType } from '@growi/core';
 import { PresetThemes, PresetThemesMetadatas } from '@growi/preset-themes';
 import { useTranslation } from 'next-i18next';
 
-import { apiv3Put } from '~/client/util/apiv3-client';
 import { toastSuccess, toastError, toastWarning } from '~/client/util/toastr';
 import { useSWRxGrowiThemeSetting } from '~/stores/admin/customize';
 
@@ -20,26 +20,29 @@ type Props = {
 const CustomizeThemeSetting = (props: Props): JSX.Element => {
   const { t } = useTranslation();
 
-  const { data, error } = useSWRxGrowiThemeSetting();
+  const { data, error, update } = useSWRxGrowiThemeSetting();
   const [currentTheme, setCurrentTheme] = useState(data?.currentTheme);
+  const [currentForcedColorScheme, setCurrentForcedColorScheme] = useState(data?.currentForcedColorScheme);
 
   useEffect(() => {
     setCurrentTheme(data?.currentTheme);
   }, [data?.currentTheme]);
 
-  const selectedHandler = useCallback((themeName: string) => {
+  const selectedHandler = useCallback((themeName: string, schemeType: GrowiThemeSchemeType) => {
     setCurrentTheme(themeName);
+    setCurrentForcedColorScheme(schemeType === GrowiThemeSchemeType.BOTH ? undefined : schemeType);
   }, []);
 
   const submitHandler = useCallback(async() => {
-    if (currentTheme == null) {
+    if (currentTheme == null || currentForcedColorScheme == null) {
       toastWarning('The selected theme is undefined');
       return;
     }
 
     try {
-      await apiv3Put('/customize-setting/theme', {
+      await update({
         theme: currentTheme,
+        forcedColorScheme: currentForcedColorScheme,
       });
 
       toastSuccess(t('toaster.update_successed', { target: t('admin:customize_settings.theme'), ns: 'commons' }));
@@ -47,7 +50,7 @@ const CustomizeThemeSetting = (props: Props): JSX.Element => {
     catch (err) {
       toastError(err);
     }
-  }, [currentTheme, t]);
+  }, [currentForcedColorScheme, currentTheme, t, update]);
 
   const availableThemes = data?.pluginThemesMetadatas == null
     ? PresetThemesMetadatas

+ 2 - 1
packages/app/src/interfaces/customize.ts

@@ -1,4 +1,4 @@
-import { GrowiThemeMetadata } from '@growi/core';
+import type { ColorScheme, GrowiThemeMetadata } from '@growi/core';
 
 export type IResLayoutSetting = {
   isContainerFluid: boolean,
@@ -6,5 +6,6 @@ export type IResLayoutSetting = {
 
 export type IResGrowiTheme = {
   currentTheme: string,
+  currentForcedColorScheme: ColorScheme,
   pluginThemesMetadatas: GrowiThemeMetadata[],
 }

+ 1 - 0
packages/app/src/server/models/config.ts

@@ -116,6 +116,7 @@ export const defaultCrowiConfigs: { [key: string]: any } = {
   'customize:highlightJsStyle' : 'github',
   'customize:highlightJsStyleBorder' : false,
   'customize:theme' : PresetThemes.DEFAULT,
+  'customize:theme:forcedColorScheme' : null,
   'customize:isContainerFluid' : false,
   'customize:isEnabledTimeline' : true,
   'customize:isEnabledAttachTitleHeader' : false,

+ 5 - 1
packages/app/src/server/routes/apiv3/customize-setting.js

@@ -112,6 +112,7 @@ module.exports = (crowi) => {
     ],
     theme: [
       body('theme').isString(),
+      body('forcedColorScheme').isString().optional({ nullable: true }),
     ],
     sidebar: [
       body('isSidebarDrawerMode').isBoolean(),
@@ -274,6 +275,7 @@ module.exports = (crowi) => {
 
     try {
       const currentTheme = await crowi.configManager.getConfig('crowi', 'customize:theme');
+      const currentForcedColorScheme = await crowi.configManager.getConfig('crowi', 'customize:theme:forcedColorScheme');
 
       // retrieve plugin manifests
       const GrowiPluginModel = mongoose.model('GrowiPlugin');
@@ -283,7 +285,7 @@ module.exports = (crowi) => {
         .map(themePlugin => themePlugin.meta.themes)
         .flat();
 
-      return res.apiv3({ currentTheme, pluginThemesMetadatas });
+      return res.apiv3({ currentTheme, currentForcedColorScheme, pluginThemesMetadatas });
     }
     catch (err) {
       const msg = 'Error occurred in getting theme';
@@ -318,12 +320,14 @@ module.exports = (crowi) => {
   router.put('/theme', loginRequiredStrictly, adminRequired, addActivity, validator.theme, apiV3FormValidator, async(req, res) => {
     const requestParams = {
       'customize:theme': req.body.theme,
+      'customize:theme:forcedColorScheme': req.body.forcedColorScheme,
     };
 
     try {
       await crowi.configManager.updateConfigsInTheSameNamespace('crowi', requestParams);
       const customizedParams = {
         theme: await crowi.configManager.getConfig('crowi', 'customize:theme'),
+        forcedColorScheme: await crowi.configManager.getConfig('crowi', 'customize:theme:forcedColorScheme'),
       };
       const parameters = { action: SupportedAction.ACTION_ADMIN_THEME_UPDATE };
       activityEvent.emit('update', res.locals.activity._id, parameters);

+ 9 - 3
packages/app/src/stores/admin/customize.tsx

@@ -1,5 +1,6 @@
 import { useCallback } from 'react';
 
+import { ColorScheme } from '@growi/core';
 import useSWR, { SWRResponse } from 'swr';
 import useSWRImmutable from 'swr/immutable';
 
@@ -27,7 +28,11 @@ export const useSWRxLayoutSetting = (): SWRResponse<IResLayoutSetting, Error> &
   };
 };
 
-export const useSWRxGrowiThemeSetting = (): SWRResponse<IResGrowiTheme, Error> => {
+type UpdateThemeArgs = {
+  theme: string,
+  forcedColorScheme: ColorScheme | null,
+}
+export const useSWRxGrowiThemeSetting = (): SWRResponse<IResGrowiTheme, Error> & updateConfigMethodForAdmin<UpdateThemeArgs> => {
 
   const fetcher = useCallback(async() => {
     const res = await apiv3Get<IResGrowiTheme>('/customize-setting/theme');
@@ -36,8 +41,9 @@ export const useSWRxGrowiThemeSetting = (): SWRResponse<IResGrowiTheme, Error> =
 
   const swrResponse = useSWR('/customize-setting/theme', fetcher);
 
-  const update = async(theme: string) => {
-    await apiv3Put('/customize-setting/layout', { theme });
+  const update = async({ theme, forcedColorScheme }: UpdateThemeArgs) => {
+
+    await apiv3Put('/customize-setting/theme', { theme, forcedColorScheme });
 
     if (swrResponse.data == null) {
       swrResponse.mutate();

+ 1 - 0
packages/core/src/index.ts

@@ -14,6 +14,7 @@ export * as pageUtils from './utils/page-utils';
 // export all
 export * from './plugin/interfaces/option-parser';
 export * from './interfaces/attachment';
+export * from './interfaces/color-scheme';
 export * from './interfaces/common';
 export * from './interfaces/growi-facade';
 export * from './interfaces/growi-theme-metadata';

+ 5 - 0
packages/core/src/interfaces/color-scheme.ts

@@ -0,0 +1,5 @@
+export const ColorScheme = {
+  LIGHT: 'light',
+  DARK: 'dark',
+} as const;
+export type ColorScheme = typeof ColorScheme[keyof typeof ColorScheme];

+ 3 - 2
packages/core/src/interfaces/growi-theme-metadata.ts

@@ -1,7 +1,8 @@
+import { ColorScheme } from './color-scheme';
+
 export const GrowiThemeSchemeType = {
+  ...ColorScheme,
   BOTH: 'both',
-  LIGHT: 'light',
-  DARK: 'dark',
 } as const;
 export type GrowiThemeSchemeType = typeof GrowiThemeSchemeType[keyof typeof GrowiThemeSchemeType];