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

Merge pull request #1336 from weseek/create-behavior-settings-frontside

Create behavior settings frontside
Yuki Takei 6 лет назад
Родитель
Сommit
441fc8bfa0

+ 2 - 1
resource/locales/en-US/translation.json

@@ -677,7 +677,8 @@
     "attach_title_header_desc": "Add page path to the first line as h1 section when create new page",
     "recent_created__n_draft_num_desc": "Number of Recently Created Pages & Drafts Displayed",
     "recently_created_n_draft_num_desc": "Number of recently created pages and drafts displayed on user page",
-    "update_layout_success": "Succeeded to update layout"
+    "update_layout_success": "Succeeded to update layout",
+    "update_behavior_success": "Succeeded to update behavior"
   },
 
   "user_management": {

+ 2 - 1
resource/locales/ja/translation.json

@@ -661,7 +661,8 @@
     "attach_title_header_desc": "新規作成したページの1行目に、ページのパスを h1 セクションとして挿入します。",
     "recent_created__n_draft_num_desc": "最近作成したページと下書きの表示数",
     "recently_created_n_draft_num_desc": "ホーム画面の Recently Created での、1ページの表示数を設定します。",
-    "update_layout_success": "レイアウトを更新しました"
+    "update_layout_success": "レイアウトを更新しました",
+    "update_behavior_success": "挙動を更新しました"
   },
 
   "user_management": {

+ 27 - 0
src/client/js/components/Admin/Common/AdminUpdateButtonRow.jsx

@@ -0,0 +1,27 @@
+import React from 'react';
+import PropTypes from 'prop-types';
+import { withTranslation } from 'react-i18next';
+
+class AdminUpdateButtonRow extends React.PureComponent {
+
+  render() {
+    const { t } = this.props;
+
+    return (
+      <div className="row my-3">
+        <div className="col-xs-offset-4 col-xs-5">
+          <button type="button" className="btn btn-primary" onClick={this.props.onClick}>{ t('Update') }</button>
+        </div>
+      </div>
+    );
+  }
+
+}
+
+AdminUpdateButtonRow.propTypes = {
+  t: PropTypes.func.isRequired, // i18next
+
+  onClick: PropTypes.func.isRequired,
+};
+
+export default withTranslation()(AdminUpdateButtonRow);

+ 5 - 3
src/client/js/components/Admin/Customize/Customize.jsx

@@ -7,6 +7,7 @@ import AppContainer from '../../../services/AppContainer';
 
 import { createSubscribedElement } from '../../UnstatedUtils';
 import CustomizeLayoutSetting from './CustomizeLayoutSetting';
+import CustomizeBehaviorSetting from './CustomizeBehaviorSetting';
 
 class Customize extends React.Component {
 
@@ -15,11 +16,12 @@ class Customize extends React.Component {
 
     return (
       <Fragment>
-        <div className="row my-3">
+        <div className="my-3">
           <CustomizeLayoutSetting />
         </div>
-        <legend>{t('customize_page.Behavior')}</legend>
-        {/* 挙動フォームの react componentをここで呼ぶ(GW-246) */}
+        <div className="my-3">
+          <CustomizeBehaviorSetting />
+        </div>
         <legend>{t('customize_page.Function')}</legend>
         {/* 機能フォームの react componentをここで呼ぶ(GW-276) */}
         <legend>{t('customize_page.Code Highlight')}</legend>

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

@@ -0,0 +1,38 @@
+import React from 'react';
+import PropTypes from 'prop-types';
+import { withTranslation } from 'react-i18next';
+
+class CustomizeBehaviorOption extends React.PureComponent {
+
+  render() {
+
+    return (
+      <React.Fragment>
+        <h4>
+          <div className="radio radio-primary">
+            <input type="radio" id={`radioBehavior${this.props.behaviorType}`} checked={this.props.isSelected} onChange={this.props.onSelected} />
+            <label htmlFor={`radioBehavior${this.props.behaviorType}`}>
+              {/* eslint-disable-next-line react/no-danger */}
+              <span dangerouslySetInnerHTML={{ __html: this.props.labelHtml }} />
+            </label>
+          </div>
+        </h4>
+        {/* render layout description */}
+        {this.props.children}
+      </React.Fragment>
+    );
+  }
+
+}
+
+CustomizeBehaviorOption.propTypes = {
+  t: PropTypes.func.isRequired, // i18next
+
+  behaviorType: PropTypes.string.isRequired,
+  labelHtml: PropTypes.string.isRequired,
+  isSelected: PropTypes.bool.isRequired,
+  onSelected: PropTypes.func.isRequired,
+  children: PropTypes.object.isRequired,
+};
+
+export default withTranslation()(CustomizeBehaviorOption);

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

@@ -0,0 +1,100 @@
+import React from 'react';
+import PropTypes from 'prop-types';
+import { withTranslation } from 'react-i18next';
+
+import loggerFactory from '@alias/logger';
+
+import { createSubscribedElement } from '../../UnstatedUtils';
+import { toastSuccess, toastError } from '../../../util/apiNotification';
+
+import AppContainer from '../../../services/AppContainer';
+
+import AdminCustomizeContainer from '../../../services/AdminCustomizeContainer';
+import CustomizeBehaviorOption from './CustomizeBehaviorOption';
+import AdminUpdateButtonRow from '../Common/AdminUpdateButtonRow';
+
+const logger = loggerFactory('growi:importer');
+
+class CustomizeBehaviorSetting extends React.Component {
+
+  constructor(props) {
+    super(props);
+
+    this.onClickSubmit = this.onClickSubmit.bind(this);
+  }
+
+  async onClickSubmit() {
+    const { t, adminCustomizeContainer } = this.props;
+
+    try {
+      await adminCustomizeContainer.updateCustomizeBehavior();
+      toastSuccess(t('customize_page.update_behavior_success'));
+    }
+    catch (err) {
+      toastError(err);
+      logger.error(err);
+    }
+  }
+
+  render() {
+    const { t, adminCustomizeContainer } = this.props;
+
+    return (
+      <React.Fragment>
+        <h2>{t('customize_page.Behavior')}</h2>
+        <div className="row">
+          <div className="col-xs-6">
+            <CustomizeBehaviorOption
+              behaviorType="growi"
+              isSelected={adminCustomizeContainer.state.currentBehavior === 'growi'}
+              onSelected={() => adminCustomizeContainer.switchBehaviorType('growi')}
+              labelHtml='GROWI Simplified Behavior <small class="text-success">(Recommended)</small>'
+            >
+              {/* TODO i18n */}
+              <ul>
+                <li>Both of <code>/page</code> and <code>/page/</code> shows the same page</li>
+                <li><code>/nonexistent_page</code> shows editing form</li>
+                <li>All pages shows the list of sub pages <b>if using GROWI Enhanced Layout</b></li>
+              </ul>
+            </CustomizeBehaviorOption>
+          </div>
+
+          <div className="col-xs-6">
+            <CustomizeBehaviorOption
+              behaviorType="crowi-plus"
+              isSelected={adminCustomizeContainer.state.currentBehavior === 'crowi-plus'}
+              onSelected={() => adminCustomizeContainer.switchBehaviorType('crowi-plus')}
+              labelHtml="Crowi Classic Behavior"
+            >
+              {/* TODO i18n */}
+              <ul>
+                <li><code>/page</code> shows the page</li>
+                <li><code>/page/</code> shows the list of sub pages</li>
+                <ul>
+                  <li>If portal is applied to <code>/page/</code> , the portal and the list of sub pages are shown</li>
+                </ul>
+                <li><code>/nonexistent_page</code> shows editing form</li>
+                <li><code>/nonexistent_page/</code> the list of sub pages</li>
+              </ul>
+            </CustomizeBehaviorOption>
+          </div>
+        </div>
+
+        <AdminUpdateButtonRow onClick={this.onClickSubmit} />
+      </React.Fragment>
+    );
+  }
+
+}
+
+const CustomizeBehaviorSettingWrapper = (props) => {
+  return createSubscribedElement(CustomizeBehaviorSetting, props, [AppContainer, AdminCustomizeContainer]);
+};
+
+CustomizeBehaviorSetting.propTypes = {
+  t: PropTypes.func.isRequired, // i18next
+  appContainer: PropTypes.instanceOf(AppContainer).isRequired,
+  adminCustomizeContainer: PropTypes.instanceOf(AdminCustomizeContainer).isRequired,
+};
+
+export default withTranslation()(CustomizeBehaviorSettingWrapper);

+ 2 - 2
src/client/js/components/Admin/Customize/CustomizeLayoutOption.jsx

@@ -8,7 +8,7 @@ class CustomizeLayoutOption extends React.Component {
     const { layoutType } = this.props;
 
     return (
-      <div className="col-sm-4">
+      <React.Fragment>
         <h4>
           <div className="radio radio-primary">
             <input type="radio" id={`radio-layout-${layoutType}`} checked={this.props.isSelected} onChange={this.props.onSelected} />
@@ -23,7 +23,7 @@ class CustomizeLayoutOption extends React.Component {
         </a>
         {/* render layout description */}
         {this.props.children}
-      </div>
+      </React.Fragment>
     );
   }
 

+ 50 - 44
src/client/js/components/Admin/Customize/CustomizeLayoutOptions.jsx

@@ -14,52 +14,58 @@ class CustomizeLayoutOptions extends React.Component {
     const { adminCustomizeContainer } = this.props;
 
     return (
-      <React.Fragment>
-        <CustomizeLayoutOption
-          layoutType="crowi-plus"
-          isSelected={adminCustomizeContainer.state.currentLayout === 'growi'}
-          onSelected={() => adminCustomizeContainer.switchLayoutType('growi')}
-          labelHtml={'GROWI Enhanced Layout <small className="text-success">(Recommended)</small>'}
-        >
-          {/* TODO i18n */}
-          <h4>Simple and Clear</h4>
-          <ul>
-            <li>Full screen layout and thin margins/paddings</li>
-            <li>Show and post comments at the bottom of the page</li>
-            <li>Affix Table-of-contents</li>
-          </ul>
-        </CustomizeLayoutOption>
+      <div className="row">
+        <div className="col-sm-4">
+          <CustomizeLayoutOption
+            layoutType="crowi-plus"
+            isSelected={adminCustomizeContainer.state.currentLayout === 'growi'}
+            onSelected={() => adminCustomizeContainer.switchLayoutType('growi')}
+            labelHtml={'GROWI Enhanced Layout <small class="text-success">(Recommended)</small>'}
+          >
+            {/* TODO i18n */}
+            <h4>Simple and Clear</h4>
+            <ul>
+              <li>Full screen layout and thin margins/paddings</li>
+              <li>Show and post comments at the bottom of the page</li>
+              <li>Affix Table-of-contents</li>
+            </ul>
+          </CustomizeLayoutOption>
+        </div>
 
-        <CustomizeLayoutOption
-          layoutType="kibela"
-          isSelected={adminCustomizeContainer.state.currentLayout === 'kibela'}
-          onSelected={() => adminCustomizeContainer.switchLayoutType('kibela')}
-          labelHtml="Kibela Like Layout"
-        >
-          {/* TODO i18n */}
-          <h4>Easy Viewing Structure</h4>
-          <ul>
-            <li>Center aligned contents</li>
-            <li>Show and post comments at the bottom of the page</li>
-            <li>Affix Table-of-contents</li>
-          </ul>
-        </CustomizeLayoutOption>
+        <div className="col-sm-4">
+          <CustomizeLayoutOption
+            layoutType="kibela"
+            isSelected={adminCustomizeContainer.state.currentLayout === 'kibela'}
+            onSelected={() => adminCustomizeContainer.switchLayoutType('kibela')}
+            labelHtml="Kibela Like Layout"
+          >
+            {/* TODO i18n */}
+            <h4>Easy Viewing Structure</h4>
+            <ul>
+              <li>Center aligned contents</li>
+              <li>Show and post comments at the bottom of the page</li>
+              <li>Affix Table-of-contents</li>
+            </ul>
+          </CustomizeLayoutOption>
+        </div>
 
-        <CustomizeLayoutOption
-          layoutType="classic"
-          isSelected={adminCustomizeContainer.state.currentLayout === 'crowi'}
-          onSelected={() => adminCustomizeContainer.switchLayoutType('crowi')}
-          labelHtml="Crowi Classic Layout"
-        >
-          {/* TODO i18n */}
-          <h4>Separated Functions</h4>
-          <ul>
-            <li>Collapsible Sidebar</li>
-            <li>Show and post comments in Sidebar</li>
-            <li>Collapsible Table-of-contents</li>
-          </ul>
-        </CustomizeLayoutOption>
-      </React.Fragment>
+        <div className="col-sm-4">
+          <CustomizeLayoutOption
+            layoutType="classic"
+            isSelected={adminCustomizeContainer.state.currentLayout === 'crowi'}
+            onSelected={() => adminCustomizeContainer.switchLayoutType('crowi')}
+            labelHtml="Crowi Classic Layout"
+          >
+            {/* TODO i18n */}
+            <h4>Separated Functions</h4>
+            <ul>
+              <li>Collapsible Sidebar</li>
+              <li>Show and post comments in Sidebar</li>
+              <li>Collapsible Table-of-contents</li>
+            </ul>
+          </CustomizeLayoutOption>
+        </div>
+      </div>
     );
   }
 

+ 2 - 5
src/client/js/components/Admin/Customize/CustomizeLayoutSetting.jsx

@@ -12,6 +12,7 @@ import AppContainer from '../../../services/AppContainer';
 import CustomizeLayoutOptions from './CustomizeLayoutOptions';
 import CustomizeThemeOptions from './CustomizeThemeOptions';
 import AdminCustomizeContainer from '../../../services/AdminCustomizeContainer';
+import AdminUpdateButtonRow from '../Common/AdminUpdateButtonRow';
 
 const logger = loggerFactory('growi:importer');
 
@@ -58,11 +59,7 @@ class CustomizeLayoutSetting extends React.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>
+        <AdminUpdateButtonRow onClick={this.onClickSubmit} />
       </React.Fragment>
     );
   }

+ 17 - 1
src/client/js/services/AdminCustomizeContainer.js

@@ -14,9 +14,9 @@ export default class AdminCustomizeContainer extends Container {
     this.state = {
       currentTheme: appContainer.config.themeType,
       currentLayout: appContainer.config.layoutType,
+      currentBehavior: appContainer.config.behaviorType,
     };
 
-    this.switchLayoutType = this.switchLayoutType.bind(this);
   }
 
   /**
@@ -44,6 +44,13 @@ export default class AdminCustomizeContainer extends Container {
     this.setState({ currentTheme: themeName });
   }
 
+  /**
+   * Switch behaviorType
+   */
+  switchBehaviorType(behaviorName) {
+    this.setState({ currentBehavior: behaviorName });
+  }
+
   /**
    * Update layout
    * @memberOf AdminCustomizeContainer
@@ -58,4 +65,13 @@ export default class AdminCustomizeContainer extends Container {
     return customizedParams;
   }
 
+  /**
+   * Update behavior
+   * @memberOf AdminCustomizeContainer
+   * @return {string} Behavior
+   */
+  async updateCustomizeBehavior() {
+    // TODO GW-497 create apiV3
+  }
+
 }