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

Merge remote-tracking branch 'origin/feature/284-add-custom-title-tag-contents' into rc/3.0.0

# Conflicts:
#	lib/form/index.js
#	lib/models/config.js
#	lib/routes/index.js
#	lib/util/swigFunctions.js
#	lib/views/admin/customize.html
Yuki Takei 8 лет назад
Родитель
Сommit
f071d2a1c5

+ 9 - 0
lib/form/admin/customtitle.js

@@ -0,0 +1,9 @@
+'use strict';
+
+var form = require('express-form')
+  , field = form.field
+  ;
+
+module.exports = form(
+  field('settingForm[customize:title]')
+);

+ 1 - 0
lib/form/index.js

@@ -24,6 +24,7 @@ module.exports = {
     customscript: require('./admin/customscript'),
     customheader: require('./admin/customheader'),
     customtheme: require('./admin/customtheme'),
+    customtitle: require('./admin/customtitle'),
     custombehavior: require('./admin/custombehavior'),
     customlayout: require('./admin/customlayout'),
     customfeatures: require('./admin/customfeatures'),

+ 7 - 0
lib/models/config.js

@@ -85,6 +85,7 @@ module.exports = function(crowi) {
       'customize:css' : '',
       'customize:script' : '',
       'customize:header' : '',
+      'customize:title' : '',
       'customize:highlightJsStyle' : 'github',
       'customize:highlightJsStyleBorder' : false,
       'customize:theme' : 'default',
@@ -367,6 +368,12 @@ module.exports = function(crowi) {
     return getValueForCrowiNS(config, key);
   }
 
+  configSchema.statics.customTitle = function(config)
+  {
+    const key = 'customize:title';
+    return getValueForCrowiNS(config, key);
+  }
+
   configSchema.statics.behaviorType = function(config)
   {
     const key = 'customize:behavior';

+ 1 - 0
lib/routes/index.js

@@ -75,6 +75,7 @@ module.exports = function(crowi, app) {
   app.post('/_api/admin/customize/script'   , loginRequired(crowi, app) , middleware.adminRequired() , csrf, form.admin.customscript, admin.api.customizeSetting);
   app.post('/_api/admin/customize/header'   , loginRequired(crowi, app) , middleware.adminRequired() , csrf, form.admin.customheader, admin.api.customizeSetting);
   app.post('/_api/admin/customize/theme'    , loginRequired(crowi, app) , middleware.adminRequired() , csrf, form.admin.customtheme, admin.api.customizeSetting);
+  app.post('/_api/admin/customize/title'    , loginRequired(crowi, app) , middleware.adminRequired() , csrf, form.admin.customtitle, admin.api.customizeSetting);
   app.post('/_api/admin/customize/behavior' , loginRequired(crowi, app) , middleware.adminRequired() , csrf, form.admin.custombehavior, admin.api.customizeSetting);
   app.post('/_api/admin/customize/layout'   , loginRequired(crowi, app) , middleware.adminRequired() , csrf, form.admin.customlayout, admin.api.customizeSetting);
   app.post('/_api/admin/customize/features' , loginRequired(crowi, app) , middleware.adminRequired() , csrf, form.admin.customfeatures, admin.api.customizeSetting);

+ 8 - 0
lib/util/swigFunctions.js

@@ -120,6 +120,14 @@ module.exports = function(crowi, app, req, locals) {
     return Config.theme(config);
   }
 
+  locals.customTitle = function() {
+    var config = crowi.getConfig();
+    var title = Config.customTitle(config);
+    var app_title = config.crowi['app:title'] ? config.crowi['app:title'] : 'Crowi';
+    var custom_title = title.replace('{{sitename}}', app_title);
+    return custom_title;
+  }
+
   locals.behaviorType = function() {
     var config = crowi.getConfig()
     return Config.behaviorType(config);

+ 43 - 1
lib/views/admin/customize.html

@@ -334,6 +334,48 @@ export  $initHighlight;</code></pre>
       </fieldset>
       </form>
 
+      <form action="/_api/admin/customize/title" method="post" class="form-horizontal" id="customtitleSettingForm" role="form">
+        <fieldset>
+          <legend>カスタムヘッダーTitle</legend>
+
+          <p class="well">
+            ヘッダーの&lt;title&gt;タグのコンテンツをカスタムできる。サイト名を入れたい位置に、&#123;&#123;sitename&#125;&#125;
+            パスを入れたい位置に&#123;&#123;path&#125;&#125;を置くことでそれぞれの値に自動置換されます。それ以外の部分は自由に記述して下さい。<br>
+          </p>
+
+          <p class="help-block">
+            Examples:
+            <pre><code>&#123;&#123;sitename&#125;&#125; hoge - &#123;&#123;path&#125;&#125;</code></pre>
+          </p>
+
+          <p class="help-block">
+            Output:
+            <pre><code>&lt;title&gt;GROWI hoge - /xxx/yyy/zzz/Sandbox&lt;&#047;title&gt;</code></pre>
+          </p>
+
+          <div class="form-group">
+            <div class="col-xs-12">
+              <div id="custom-title-editor"></div>
+              <input type="hidden" id="inputCustomTitle" name="settingForm[customize:title]" value="{{ settingForm['customize:title'] }}">
+            </div>
+            <div class="col-xs-12">
+              <p class="help-block text-right">
+                <i class="fa fa-fw fa-keyboard-o" aria-hidden="true"></i>
+                Ctrl+Space でコード補完
+              </p>
+            </div>
+          </div>
+
+          <div class="form-group">
+            <div class="col-xs-offset-5 col-xs-6">
+              <input type="hidden" name="_csrf" value="{{ csrf() }}">
+              <button type="submit" class="btn btn-primary">更新</button>
+            </div>
+          </div>
+
+        </fieldset>
+        </form>
+
       <form action="/_api/admin/customize/css" method="post" class="form-horizontal" id="cutomcssSettingForm" role="form">
       <fieldset>
         <legend>{{ t('customize_page.Custom CSS') }}</legend>
@@ -432,7 +474,7 @@ window.addEventListener('load', (event) => {
   {% parent %}
   <script>
     $(`#customthemeSettingForm, #cutomlayoutSettingForm, #cutombehaviorSettingForm, #cutomhighlightJsStyleSettingForm,
-       #customfeaturesSettingForm, #cutomheaderSettingForm, #cutomcssSettingForm, #cutomscriptSettingForm`
+       #customfeaturesSettingForm, #cutomheaderSettingForm, #cutomcssSettingForm, #cutomscriptSettingForm, #customtitleSettingForm`
     ).each(function() {
       $(this).submit(function()
       {

+ 11 - 0
resource/js/app.js

@@ -26,6 +26,7 @@ import SearchTypeahead  from './components/SearchTypeahead';
 import CustomCssEditor  from './components/Admin/CustomCssEditor';
 import CustomScriptEditor from './components/Admin/CustomScriptEditor';
 import CustomHeaderEditor from './components/Admin/CustomHeaderEditor';
+import CustomTitleEditor from './components/Admin/CustomTitleEditor';
 
 import * as entities from 'entities';
 
@@ -212,6 +213,16 @@ if (customHeaderEditorElem != null) {
     customHeaderEditorElem
   )
 }
+const customTitleEditorElem = document.getElementById('custom-title-editor');
+if (customTitleEditorElem != null) {
+  // get input[type=hidden] element
+  const customTitleInputElem = document.getElementById('inputCustomTitle');
+
+  ReactDOM.render(
+    <CustomTitleEditor inputElem={customTitleInputElem} />,
+    customTitleEditorElem
+  )
+}
 
 // うわーもうー
 $('a[data-toggle="tab"][href="#revision-history"]').on('show.bs.tab', function() {

+ 60 - 0
resource/js/components/Admin/CustomTitleEditor.js

@@ -0,0 +1,60 @@
+import React from 'react';
+import PropTypes from 'prop-types';
+
+import { UnControlled as CodeMirror } from 'react-codemirror2';
+require('codemirror/lib/codemirror.css');
+require('codemirror/addon/display/autorefresh');
+require('codemirror/addon/hint/show-hint');
+require('codemirror/addon/edit/matchbrackets');
+require('codemirror/addon/edit/closebrackets');
+require('codemirror/mode/htmlmixed/htmlmixed');
+require('codemirror/theme/eclipse.css');
+
+require('jquery-ui/ui/widgets/resizable');
+
+export default class CustomTitleEditor extends React.Component {
+
+  constructor(props) {
+    super(props);
+  }
+
+  render() {
+    // get initial value from inputElem
+
+    const value = this.props.inputElem.value;
+
+    return (
+      <CodeMirror
+        value={value}
+        autoFocus={true}
+        options={{
+          mode: 'htmlmixed',
+          lineNumbers: true,
+          tabSize: 2,
+          indentUnit: 2,
+          theme: 'eclipse',
+          autoRefresh: true,
+          matchBrackets: true,
+          autoCloseBrackets: true,
+          extraKeys: {'Ctrl-Space': 'autocomplete'},
+        }}
+        editorDidMount={(editor, next) => {
+          // resizable with jquery.ui
+          $(editor.getWrapperElement()).resizable({
+            resize: function() {
+              editor.setSize($(this).width(), $(this).height());
+            }
+          });
+        }}
+        onChange={(editor, data, value) => {
+          this.props.inputElem.value = value;
+        }}
+      />
+    );
+  }
+
+}
+
+CustomTitleEditor.propTypes = {
+  inputElem: PropTypes.object.isRequired,
+};