Przeglądaj źródła

Merge pull request #1326 from weseek/reactify-admin/create-theme-setting-frontside

Reactify admin/create theme setting frontside
itizawa 6 lat temu
rodzic
commit
9a8adb7b22

+ 0 - 1
src/client/js/components/Admin/Customize/Customize.jsx

@@ -16,7 +16,6 @@ class Customize extends React.Component {
     return (
       <Fragment>
         <div className="row my-3">
-          <h2>{t('customize_page.Layout')}</h2>
           <CustomizeLayoutSetting />
         </div>
         <legend>{t('customize_page.Behavior')}</legend>

+ 19 - 4
src/client/js/components/Admin/Customize/CustomizeLayoutSetting.jsx

@@ -8,9 +8,10 @@ import { createSubscribedElement } from '../../UnstatedUtils';
 import { toastSuccess, toastError } from '../../../util/apiNotification';
 
 import AppContainer from '../../../services/AppContainer';
-import AdminCustomizeContainer from '../../../services/AdminCustomizeContainer';
 
 import CustomizeLayoutOptions from './CustomizeLayoutOptions';
+import CustomizeThemeOptions from './CustomizeThemeOptions';
+import AdminCustomizeContainer from '../../../services/AdminCustomizeContainer';
 
 const logger = loggerFactory('growi:importer');
 
@@ -36,19 +37,33 @@ class CustomizeLayoutSetting extends React.Component {
     }
   }
 
+  renderDevAlert() {
+    if (process.env.NODE_ENV === 'development') {
+      return (
+        <div className="alert alert-warning">
+          <strong>DEBUG MESSAGE:</strong> development build では、リアルタイムプレビューが無効になります
+        </div>
+      );
+    }
+  }
+
+
   render() {
     const { t } = this.props;
 
     return (
-      <form>
+      <React.Fragment>
+        <h2>{t('customize_page.Layout')}</h2>
         <CustomizeLayoutOptions />
-        {/* TODO GW-245 create themeForm Component */}
+        <h2>{ t('customize_page.Theme') }</h2>
+        {this.renderDevAlert()}
+        <CustomizeThemeOptions />
         <div className="form-group my-3">
           <div className="col-xs-offset-4 col-xs-5">
             <div className="btn btn-primary" onClick={this.onClickSubmit}>{ t('Update') }</div>
           </div>
         </div>
-      </form>
+      </React.Fragment>
     );
   }
 

+ 91 - 0
src/client/js/components/Admin/Customize/CustomizeThemeOptions.jsx

@@ -0,0 +1,91 @@
+import React from 'react';
+import PropTypes from 'prop-types';
+
+import { createSubscribedElement } from '../../UnstatedUtils';
+
+import AppContainer from '../../../services/AppContainer';
+import ThemeColorBox from './ThemeColorBox';
+import AdminCustomizeContainer from '../../../services/AdminCustomizeContainer';
+
+class CustomizeThemeOptions extends React.Component {
+
+  render() {
+    const { adminCustomizeContainer } = this.props;
+    const { currentLayout, currentTheme } = adminCustomizeContainer.state;
+
+    const lightTheme = [{
+      name: 'default', bg: '#ffffff', topbar: '#334455', theme: '#112744',
+    }, {
+      name: 'nature', bg: '#f9fff3', topbar: '#118050', theme: '#460039',
+    }, {
+      name: 'mono-blue', bg: '#F7FBFD', topbar: '#00587A', theme: '#00587A',
+    }, {
+      name: 'wood', bg: '#fffefb', topbar: '#aaa45f', theme: '#dddebf',
+    }, {
+      name: 'island', bg: '#8ecac0', topbar: '#0c2a44', theme: '#cef2ef',
+    }, {
+      name: 'christmas', bg: '#fffefb', topbar: '#b3000c', theme: '#017e20',
+    }, {
+      name: 'antarctic', bg: '#ffffff', topbar: '#000080', theme: '#99cccc',
+    }];
+
+    const darkTheme = [{
+      name: 'default-dark', bg: '#212731', topbar: '#151515', theme: '#f75b36',
+    }, {
+      name: 'future', bg: '#16282D', topbar: '#011414', theme: '#04B4AE',
+    }, {
+      name: 'blue-night', bg: '#061F2F', topbar: '#27343B', theme: '#0090C8',
+    }, {
+      name: 'halloween', bg: '#030003', topbar: '#cc5d1f', theme: '#e9af2b',
+    }];
+
+    return (
+      <div id="themeOptions" className={`${currentLayout === 'kibela' && 'disabled'}`}>
+        {/* Light Themes  */}
+        <div className="d-flex">
+          {lightTheme.map((theme) => {
+            return (
+              <ThemeColorBox
+                key={theme.name}
+                isSelected={currentTheme === theme.name}
+                onSelected={() => adminCustomizeContainer.switchThemeType(theme.name)}
+                name={theme.name}
+                bg={theme.bg}
+                topbar={theme.topbar}
+                theme={theme.theme}
+              />
+            );
+          })}
+        </div>
+        {/* Dark Themes  */}
+        <div className="d-flex mt-3">
+          {darkTheme.map((theme) => {
+            return (
+              <ThemeColorBox
+                key={theme.name}
+                isSelected={currentTheme === theme.name}
+                onSelected={() => adminCustomizeContainer.switchThemeType(theme.name)}
+                name={theme.name}
+                bg={theme.bg}
+                topbar={theme.topbar}
+                theme={theme.theme}
+              />
+            );
+          })}
+        </div>
+      </div>
+    );
+  }
+
+}
+
+const CustomizeThemeOptionsWrapper = (props) => {
+  return createSubscribedElement(CustomizeThemeOptions, props, [AppContainer, AdminCustomizeContainer]);
+};
+
+CustomizeThemeOptions.propTypes = {
+  appContainer: PropTypes.instanceOf(AppContainer).isRequired,
+  adminCustomizeContainer: PropTypes.instanceOf(AdminCustomizeContainer).isRequired,
+};
+
+export default CustomizeThemeOptionsWrapper;

+ 45 - 0
src/client/js/components/Admin/Customize/ThemeColorBox.jsx

@@ -0,0 +1,45 @@
+import React from 'react';
+import PropTypes from 'prop-types';
+
+
+class ThemeColorBox extends React.PureComponent {
+
+  render() {
+    const { name } = this.props;
+
+    return (
+      <div
+        id={`theme-option-${name}`}
+        className={`theme-option-container d-flex flex-column align-items-center ${this.props.isSelected && 'active'}`}
+        onClick={this.props.onSelected}
+      >
+        <a
+          className={`m-0 ${name} theme-button`}
+          id={name}
+        >
+          <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 64 64" width="64" height="64">
+            <g>
+              <path d="M -1 -1 L65 -1 L65 65 L-1 65 L-1 -1 Z" fill={this.props.bg}></path>
+              <path d="M -1 -1 L65 -1 L65 15 L-1 15 L-1 -1 Z" fill={this.props.topbar}></path>
+              <path d="M 44 15 L65 15 L65 65 L44 65 L44 15 Z" fill={this.props.theme}></path>
+            </g>
+          </svg>
+        </a>
+        <span className="theme-option-name"><b>{ name }</b></span>
+      </div>
+    );
+  }
+
+}
+
+
+ThemeColorBox.propTypes = {
+  isSelected: PropTypes.bool.isRequired,
+  onSelected: PropTypes.func.isRequired,
+  name: PropTypes.string.isRequired,
+  bg: PropTypes.string.isRequired,
+  topbar: PropTypes.string.isRequired,
+  theme: PropTypes.string.isRequired,
+};
+
+export default ThemeColorBox;

+ 12 - 0
src/client/js/services/AdminCustomizeContainer.js

@@ -12,6 +12,7 @@ export default class AdminCustomizeContainer extends Container {
     this.appContainer = appContainer;
 
     this.state = {
+      currentTheme: appContainer.config.themeType,
       currentLayout: appContainer.config.layoutType,
     };
 
@@ -32,6 +33,17 @@ export default class AdminCustomizeContainer extends Container {
     this.setState({ currentLayout: lauoutName });
   }
 
+  /**
+   * Switch themeType
+   */
+  switchThemeType(themeName) {
+    // can't choose theme when kibela
+    if (this.state.currentLayout === 'kibela') {
+      return;
+    }
+    this.setState({ currentTheme: themeName });
+  }
+
   updateCustomizeLayout() {
     // TODO GW-479 post api
   }

+ 1 - 0
src/server/models/config.js

@@ -173,6 +173,7 @@ module.exports = function(crowi) {
       },
       behaviorType: crowi.configManager.getConfig('crowi', 'customize:behavior'),
       layoutType: crowi.configManager.getConfig('crowi', 'customize:layout'),
+      themeType: crowi.configManager.getConfig('crowi', 'customize:theme'),
       isEnabledLinebreaks: crowi.configManager.getConfig('markdown', 'markdown:isEnabledLinebreaks'),
       isEnabledLinebreaksInComments: crowi.configManager.getConfig('markdown', 'markdown:isEnabledLinebreaksInComments'),
       isEnabledXssPrevention: crowi.configManager.getConfig('markdown', 'markdown:xss:isEnabledPrevention'),