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

Merge pull request #140 from weseek/feat/139-custom-script

Feat/139 custom script
Yuki Takei 8 лет назад
Родитель
Сommit
f35b3c5a60

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

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

+ 1 - 0
lib/form/index.js

@@ -19,6 +19,7 @@ module.exports = {
     plugin: require('./admin/plugin'),
     plugin: require('./admin/plugin'),
     markdown: require('./admin/markdown'),
     markdown: require('./admin/markdown'),
     customcss: require('./admin/customcss'),
     customcss: require('./admin/customcss'),
+    customscript: require('./admin/customscript'),
     custombehavior: require('./admin/custombehavior'),
     custombehavior: require('./admin/custombehavior'),
     customlayout: require('./admin/customlayout'),
     customlayout: require('./admin/customlayout'),
     customfeatures: require('./admin/customfeatures'),
     customfeatures: require('./admin/customfeatures'),

+ 25 - 8
lib/models/config.js

@@ -68,6 +68,7 @@ module.exports = function(crowi) {
       'plugin:isEnabledPlugins' : true,
       'plugin:isEnabledPlugins' : true,
 
 
       'customize:css' : '',
       'customize:css' : '',
+      'customize:script' : '',
       'customize:behavior' : 'crowi',
       'customize:behavior' : 'crowi',
       'customize:layout' : 'crowi',
       'customize:layout' : 'crowi',
       'customize:isEnabledTimeline' : true,
       'customize:isEnabledTimeline' : true,
@@ -123,8 +124,9 @@ module.exports = function(crowi) {
     originalConfig[ns] = newNSConfig;
     originalConfig[ns] = newNSConfig;
     crowi.setConfig(originalConfig);
     crowi.setConfig(originalConfig);
 
 
-    // uglify and store
-    Config.generateUglifiedCustomCss(originalConfig);
+    // initialize custom css/script
+    Config.initCustomCss(originalConfig);
+    Config.initCustomScript(originalConfig);
   };
   };
 
 
   // Execute only once for installing application
   // Execute only once for installing application
@@ -225,8 +227,9 @@ module.exports = function(crowi) {
 
 
         debug('Config loaded', config);
         debug('Config loaded', config);
 
 
-        // uglify and store
-        Config.generateUglifiedCustomCss(config);
+        // initialize custom css/script
+        Config.initCustomCss(config);
+        Config.initCustomScript(config);
 
 
         return callback(null, config);
         return callback(null, config);
       });
       });
@@ -288,18 +291,32 @@ module.exports = function(crowi) {
   };
   };
 
 
   /**
   /**
-   * uglify store custom css strings
+   * initialize custom css strings
    */
    */
-  configSchema.statics.generateUglifiedCustomCss = function(config)
+  configSchema.statics.initCustomCss = function(config)
   {
   {
     const key = 'customize:css';
     const key = 'customize:css';
     const rawCss = getValueForCrowiNS(config, key);
     const rawCss = getValueForCrowiNS(config, key);
-    this.uglifiedCustomCss = uglifycss.processString(rawCss);
+    // uglify and store
+    this._customCss = uglifycss.processString(rawCss);
   }
   }
 
 
   configSchema.statics.customCss = function(config)
   configSchema.statics.customCss = function(config)
   {
   {
-    return this.uglifiedCustomCss;
+    return this._customCss;
+  }
+
+  configSchema.statics.initCustomScript = function(config)
+  {
+    const key = 'customize:script';
+    const rawScript = getValueForCrowiNS(config, key);
+    // store as is
+    this._customScript = rawScript;
+  }
+
+  configSchema.statics.customScript = function(config)
+  {
+    return this._customScript;
   }
   }
 
 
   configSchema.statics.behaviorType = function(config)
   configSchema.statics.behaviorType = function(config)

+ 1 - 0
lib/routes/index.js

@@ -54,6 +54,7 @@ module.exports = function(crowi, app) {
   // markdown admin
   // markdown admin
   app.get('/admin/customize'                , loginRequired(crowi, app) , middleware.adminRequired() , admin.customize.index);
   app.get('/admin/customize'                , loginRequired(crowi, app) , middleware.adminRequired() , admin.customize.index);
   app.post('/_api/admin/customize/css'      , loginRequired(crowi, app) , middleware.adminRequired() , csrf, form.admin.customcss, admin.api.customizeSetting);
   app.post('/_api/admin/customize/css'      , loginRequired(crowi, app) , middleware.adminRequired() , csrf, form.admin.customcss, admin.api.customizeSetting);
+  app.post('/_api/admin/customize/script'   , loginRequired(crowi, app) , middleware.adminRequired() , csrf, form.admin.customscript, 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/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/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);
   app.post('/_api/admin/customize/features' , loginRequired(crowi, app) , middleware.adminRequired() , csrf, form.admin.customfeatures, admin.api.customizeSetting);

+ 4 - 0
lib/util/swigFunctions.js

@@ -55,6 +55,10 @@ module.exports = function(crowi, app, req, locals) {
     return Config.customCss();
     return Config.customCss();
   }
   }
 
 
+  locals.customScript = function() {
+    return Config.customScript();
+  }
+
   locals.behaviorType = function() {
   locals.behaviorType = function() {
     var config = crowi.getConfig()
     var config = crowi.getConfig()
     return Config.behaviorType(config);
     return Config.behaviorType(config);

+ 75 - 7
lib/views/admin/customize.html

@@ -209,7 +209,7 @@
       <fieldset>
       <fieldset>
         <legend>カスタムCSS</legend>
         <legend>カスタムCSS</legend>
 
 
-        <p class="help-block">
+        <p class="well">
           システム全体に適用されるCSSを記述できます。<br>
           システム全体に適用されるCSSを記述できます。<br>
           変更の反映はページの更新が必要です。
           変更の反映はページの更新が必要です。
         </p>
         </p>
@@ -236,11 +236,57 @@
       </fieldset>
       </fieldset>
       </form>
       </form>
 
 
+
+      <form action="/_api/admin/customize/script" method="post" class="form-horizontal" id="cutomscriptSettingForm" role="form">
+      <fieldset>
+        <legend>カスタムスクリプト</legend>
+
+        <p class="well">
+          システム全体に適用されるJavaScriptを記述できます。<br>
+          変更の反映はページの更新が必要です。
+        </p>
+
+        <p class="help-block">
+          Available Placeholders:
+          <dl class="dl-horizontal">
+            <dt><code>crowi</code></dt>
+            <dd>Crowi context instance</dd>
+            <dt><code>Crowi</code></dt>
+            <dd>Crowi legacy instance (jQuery based)</dd>
+            <dt><code>crowiRenderer</code></dt>
+            <dd>Crowi Renderer instance</dd>
+            <dt><code>crowiPlugin</code></dt>
+            <dd>crowi-plus plugin manager instance</dd>
+          </dl>
+        </p>
+
+        <div class="form-group">
+          <div class="col-xs-12">
+            <textarea id="taCustomScript" class="form-control" type="textarea" name="settingForm[customize:script]" rows="20">{{ settingForm['customize:script'] }}</textarea>
+          </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>
+
     </div>
     </div>
   </div>
   </div>
 
 
   <script>
   <script>
-    $('#cutomcssSettingForm, #cutomlayoutSettingForm, #cutombehaviorSettingForm, #customfeaturesSettingForm').each(function() {
+    $('#cutomcssSettingForm, #cutomscriptSettingForm, #cutomlayoutSettingForm, #cutombehaviorSettingForm, #customfeaturesSettingForm').each(function() {
       $(this).submit(function()
       $(this).submit(function()
       {
       {
         function showMessage(formId, msg, status) {
         function showMessage(formId, msg, status) {
@@ -291,9 +337,10 @@
   </script>
   </script>
 
 
   <!-- CodeMirror -->
   <!-- CodeMirror -->
-  <script src="https://cdn.jsdelivr.net/g/codemirror@4.5.0(codemirror.min.js+addon/lint/css-lint.js+mode/css/css.js+addon/hint/css-hint.js+addon/hint/show-hint.js+addon/edit/matchbrackets.js+addon/edit/closebrackets.js),jquery.ui@1.11.4"></script>
+  <script src="https://cdn.jsdelivr.net/g/codemirror@4.5.0(codemirror.min.js+addon/lint/css-lint.js+addon/lint/javascript-lint.js+mode/css/css.js+mode/javascript/javascript.js+addon/hint/css-hint.js+addon/hint/javascript-hint.js+addon/hint/show-hint.js+addon/edit/matchbrackets.js+addon/edit/closebrackets.js),jquery.ui@1.11.4"></script>
   <script>
   <script>
-    var editor = CodeMirror.fromTextArea(document.getElementById('taCustomCss'), {
+    // Configure for CSS editor
+    var editorCss = CodeMirror.fromTextArea(document.getElementById('taCustomCss'), {
       mode: "css",
       mode: "css",
       lineNumbers: true,
       lineNumbers: true,
       tabSize: 2,
       tabSize: 2,
@@ -303,13 +350,34 @@
       autoCloseBrackets: true,
       autoCloseBrackets: true,
       extraKeys: {"Ctrl-Space": "autocomplete"},
       extraKeys: {"Ctrl-Space": "autocomplete"},
     });
     });
-    editor.on('change', function(cm, change) {
+    editorCss.on('change', function(cm, change) {
+      cm.save();
+    });
+    // resizable with jquery.ui
+    $(editorCss.getWrapperElement()).resizable({
+      resize: function() {
+        editorCss.setSize($(this).width(), $(this).height());
+      }
+    });
+
+    // Configure for JavaScript editor
+    var editorScript = CodeMirror.fromTextArea(document.getElementById('taCustomScript'), {
+      mode: "javascript",
+      lineNumbers: true,
+      tabSize: 2,
+      indentUnit: 2,
+      theme: 'eclipse',
+      matchBrackets: true,
+      autoCloseBrackets: true,
+      extraKeys: {"Ctrl-Space": "autocomplete"},
+    });
+    editorScript.on('change', function(cm, change) {
       cm.save();
       cm.save();
     });
     });
     // resizable with jquery.ui
     // resizable with jquery.ui
-    $(editor.getWrapperElement()).resizable({
+    $(editorScript.getWrapperElement()).resizable({
       resize: function() {
       resize: function() {
-        editor.setSize($(this).width(), $(this).height());
+        editorScript.setSize($(this).width(), $(this).height());
       }
       }
     });
     });
 
 

+ 3 - 0
lib/views/layout/admin.html

@@ -5,3 +5,6 @@
   <script src="{{ webpack_asset('legacy-admin').js }}" defer></script>
   <script src="{{ webpack_asset('legacy-admin').js }}" defer></script>
 {% endblock %}
 {% endblock %}
 
 
+{# disable custom script in admin page #}
+{% block custom_script %}
+{% endblock %}

+ 6 - 0
lib/views/layout/layout.html

@@ -182,4 +182,10 @@
 {{ local_config|json|safe }}
 {{ local_config|json|safe }}
 </script>
 </script>
 
 
+{% block custom_script %}
+<script>
+  {{ customScript() }}
+</script>
+{% endblock %}
+
 </html>
 </html>