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

Merge branch 'rc/3.0.0' into feat/grouping-users

Tatsuya 8 лет назад
Родитель
Сommit
89a0c9f873
100 измененных файлов с 2309 добавлено и 2462 удалено
  1. 63 0
      .eslintrc.js
  2. 0 1
      .gitignore
  3. 0 14
      .jshintrc
  4. 22 2
      CHANGES.md
  5. 11 1
      THIRD-PARTY-NOTICES.md
  6. 3 3
      config/env.dev.js
  7. 15 5
      config/webpack.common.js
  8. 3 0
      config/webpack.dev.js
  9. 3 0
      config/webpack.prod.js
  10. 19 52
      lib/crowi/dev.js
  11. 18 5
      lib/crowi/index.js
  12. 10 0
      lib/form/admin/customhighlightJsStyle.js
  13. 9 0
      lib/form/admin/customtheme.js
  14. 9 0
      lib/form/admin/customtitle.js
  15. 3 0
      lib/form/index.js
  16. 43 45
      lib/locales/en-US/translation.json
  17. 41 46
      lib/locales/ja/translation.json
  18. 28 0
      lib/models/config.js
  19. 8 7
      lib/plugins/plugin-utils.js
  20. 15 1
      lib/routes/admin.js
  21. 3 0
      lib/routes/index.js
  22. 3 1
      lib/routes/page.js
  23. 2 2
      lib/util/middlewares.js
  24. 41 0
      lib/util/swigFunctions.js
  25. 12 17
      lib/views/_form.html
  26. 7 6
      lib/views/admin/app.html
  27. 193 18
      lib/views/admin/customize.html
  28. 16 14
      lib/views/admin/external-accounts.html
  29. 7 3
      lib/views/admin/index.html
  30. 9 9
      lib/views/admin/markdown.html
  31. 13 13
      lib/views/admin/notification.html
  32. 2 2
      lib/views/admin/search.html
  33. 18 18
      lib/views/admin/security.html
  34. 31 25
      lib/views/admin/user-group-detail.html
  35. 31 27
      lib/views/admin/user-groups.html
  36. 85 63
      lib/views/admin/users.html
  37. 9 9
      lib/views/admin/widget/menu.html
  38. 7 7
      lib/views/admin/widget/passport/ldap.html
  39. 7 0
      lib/views/admin/widget/theme-colorbox.html
  40. 0 48
      lib/views/crowi-plus/base/not_found_nosidebar.html
  41. 0 48
      lib/views/crowi-plus/base/page_list_nosidebar.html
  42. 0 48
      lib/views/crowi-plus/base/page_nosidebar.html
  43. 0 72
      lib/views/crowi-plus/base/user_page_nosidebar.html
  44. 0 34
      lib/views/crowi-plus/not_found.html
  45. 0 57
      lib/views/crowi-plus/page.html
  46. 0 48
      lib/views/crowi-plus/page_list.html
  47. 0 24
      lib/views/crowi-plus/user_page.html
  48. 0 69
      lib/views/crowi-plus/widget/header.html
  49. 2 2
      lib/views/customlayout-selector/not_found.html
  50. 2 2
      lib/views/customlayout-selector/page.html
  51. 2 2
      lib/views/customlayout-selector/page_list.html
  52. 2 2
      lib/views/customlayout-selector/user_page.html
  53. 0 15
      lib/views/index.html
  54. 82 58
      lib/views/installer.html
  55. 90 74
      lib/views/invited.html
  56. 51 0
      lib/views/layout-crowi/base/layout.html
  57. 41 0
      lib/views/layout-crowi/not_found.html
  58. 68 0
      lib/views/layout-crowi/page.html
  59. 98 0
      lib/views/layout-crowi/page_list.html
  60. 19 0
      lib/views/layout-crowi/user_page.html
  61. 33 0
      lib/views/layout-growi/base/layout.html
  62. 20 0
      lib/views/layout-growi/not_found.html
  63. 63 0
      lib/views/layout-growi/page.html
  64. 60 0
      lib/views/layout-growi/page_list.html
  65. 67 0
      lib/views/layout-growi/user_page.html
  66. 5 5
      lib/views/layout-growi/widget/comments.html
  67. 51 0
      lib/views/layout-growi/widget/header.html
  68. 0 57
      lib/views/layout/2column.html
  69. 5 1
      lib/views/layout/admin.html
  70. 129 112
      lib/views/layout/layout.html
  71. 0 22
      lib/views/layout/single-nologin.html
  72. 0 45
      lib/views/layout/single.html
  73. 252 205
      lib/views/login.html
  74. 35 38
      lib/views/login/error.html
  75. 12 10
      lib/views/me/api_token.html
  76. 21 21
      lib/views/me/external-accounts.html
  77. 63 75
      lib/views/me/index.html
  78. 12 16
      lib/views/me/password.html
  79. 29 31
      lib/views/modal/create_page.html
  80. 36 20
      lib/views/modal/delete.html
  81. 17 8
      lib/views/modal/duplicate.html
  82. 1 1
      lib/views/modal/page_name_warning.html
  83. 5 5
      lib/views/modal/put_back.html
  84. 17 8
      lib/views/modal/rename.html
  85. 1 1
      lib/views/modal/shortcuts.html
  86. 3 3
      lib/views/modal/unportalize.html
  87. 25 1
      lib/views/modal/what_is_portal.html
  88. 0 95
      lib/views/not_found.html
  89. 0 273
      lib/views/page.html
  90. 0 288
      lib/views/page_list.html
  91. 5 4
      lib/views/page_presentation.html
  92. 14 7
      lib/views/search.html
  93. 3 5
      lib/views/user/bookmarks.html
  94. 3 5
      lib/views/user/recent-create.html
  95. 0 81
      lib/views/user_page.html
  96. 4 0
      lib/views/widget/create_portal.html
  97. 16 0
      lib/views/widget/favicon.html
  98. 6 0
      lib/views/widget/header-button-bookmark.html
  99. 7 0
      lib/views/widget/header-button-like.html
  100. 13 0
      lib/views/widget/header-buttons-lg.html

+ 63 - 0
.eslintrc.js

@@ -0,0 +1,63 @@
+module.exports = {
+  "env": {
+    "browser": true,
+    "commonjs": true,
+    "es6": true,
+    "node": true
+  },
+  "extends": "eslint:recommended",
+  "parserOptions": {
+    "ecmaFeatures": {
+      "experimentalObjectRestSpread": true,
+      "jsx": true
+    },
+    "sourceType": "module"
+  },
+  "plugins": [
+    "react"
+  ],
+  "rules": {
+    "brace-style": [
+      "error",
+      "stroustrup", { "allowSingleLine": true }
+    ],
+    "comma-spacing": [
+      "error",
+      { "before": false, "after": true }
+    ],
+    "func-call-spacing": [
+      "error",
+      "never"
+    ],
+    "indent": [
+      "error",
+      2
+    ],
+    "key-spacing": [
+      "error", { "beforeColon": false, "afterColon": true }
+    ],
+    "keyword-spacing": [
+      "error", {}
+    ],
+    "linebreak-style": [
+      "error",
+      "unix"
+    ],
+    "quotes": [
+      "error",
+      "single"
+    ],
+    "semi": [
+      "error",
+      "always"
+    ],
+    "space-before-blocks": [
+      "error",
+      "always"
+    ],
+    "space-before-function-paren": [
+      "error",
+      "never"
+    ]
+  }
+};

+ 0 - 1
.gitignore

@@ -7,7 +7,6 @@ npm-debug.log.*
 .DS_Store
 .DS_Store
 .Trash-*
 .Trash-*
 ehthumbs.db
 ehthumbs.db
-Icon?
 Thumbs.db
 Thumbs.db
 
 
 # Node Files #
 # Node Files #

+ 0 - 14
.jshintrc

@@ -1,14 +0,0 @@
-{
-  "curly": true,
-  "eqnull": false,
-  "forin": true,
-  "freeze": true,
-  "immed": true,
-  "indent": 2,
-  "laxcomma": true,
-  "newcap": true,
-  "node": true,
-  "quotmark": "single",
-  "trailing": true,
-  "undef": true
-}

+ 22 - 2
CHANGES.md

@@ -1,9 +1,29 @@
 CHANGES
 CHANGES
 ========
 ========
 
 
-## 2.4.4-RC
+## 3.0.0-RC
 
 
-* 
+* Feature: Group Access Control List
+* Feature: Add theme selector
+* Support: Add dark theme
+* Support: Refreshing bootstrap theme and icons
+* Support: Use Browsersync instead of easy-livereload
+* Support: Upgrade libs
+    * react-bootstrap
+    * react-bootstrap-typeahead
+    * react-clipboard.js
+
+## 2.4.4
+
+* Feature: Autoformat Markdown Table
+* Feature: highlight.js Theme Selector
+* Fix: The bug of updating numbering list by codemirror
+* Fix: Template LangProcessor doesn't work
+    * Introduced by 2.4.0
+* Support: Apply ESLint
+* Support: Upgrade libs
+    * react, react-dom
+    * codemirror, react-codemirror2
 
 
 ## 2.4.3
 ## 2.4.3
 
 

+ 11 - 1
THIRD-PARTY-NOTICES.md

@@ -14,7 +14,7 @@ https://github.com/weseek/crowi-plus.
 
 
 1. crowi/crowi (https://github.com/crowi/crowi)
 1. crowi/crowi (https://github.com/crowi/crowi)
 2. Microsoft/vscode (https://github.com/Microsoft/vscode)
 2. Microsoft/vscode (https://github.com/Microsoft/vscode)
-
+3. stephenhutchings/typicons.font (https://github.com/stephenhutchings/typicons.font)
 
 
 
 
 License Notice for Crowi
 License Notice for Crowi
@@ -78,3 +78,13 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 SOFTWARE.
 SOFTWARE.
 
 
 ```
 ```
+
+
+License Notice for Typicons
+------------------------
+
+https://creativecommons.org/licenses/by-sa/3.0/
+
+```
+Copyright (c) 2018 Stephen Hutchings
+```

+ 3 - 3
config/env.dev.js

@@ -5,15 +5,15 @@ module.exports = {
   // REDIS_URL: 'redis://localhost:6379/crowi',
   // REDIS_URL: 'redis://localhost:6379/crowi',
   // ELASTICSEARCH_URI: 'http://localhost:9200/crowi',
   // ELASTICSEARCH_URI: 'http://localhost:9200/crowi',
   PLUGIN_NAMES_TOBE_LOADED: [
   PLUGIN_NAMES_TOBE_LOADED: [
-    // 'crowi-plugin-lsx',
-    // 'crowi-plugin-pukiwiki-like-linker',
+    // 'growi-plugin-lsx',
+    // 'growi-plugin-pukiwiki-like-linker',
   ],
   ],
   // filters for debug
   // filters for debug
   DEBUG: [
   DEBUG: [
     // 'express:*',
     // 'express:*',
     // 'crowi:*',
     // 'crowi:*',
     'crowi:crowi',
     'crowi:crowi',
-    'crowi:crowi:dev',
+    // 'crowi:crowi:dev',
     'crowi:crowi:express-init',
     'crowi:crowi:express-init',
     'crowi:models:external-account',
     'crowi:models:external-account',
     // 'crowi:routes:login',
     // 'crowi:routes:login',

+ 15 - 5
config/webpack.common.js

@@ -10,7 +10,7 @@ const helpers = require('./helpers');
  */
  */
 const AssetsPlugin = require('assets-webpack-plugin');
 const AssetsPlugin = require('assets-webpack-plugin');
 const CommonsChunkPlugin = require('webpack/lib/optimize/CommonsChunkPlugin');
 const CommonsChunkPlugin = require('webpack/lib/optimize/CommonsChunkPlugin');
-const LodashModuleReplacementPlugin = require('lodash-webpack-plugin');;
+const ExtractTextPlugin = require('extract-text-webpack-plugin');
 
 
 /*
 /*
  * Webpack configuration
  * Webpack configuration
@@ -27,8 +27,10 @@ module.exports = function (options) {
       'legacy-admin':         './resource/js/legacy/crowi-admin',
       'legacy-admin':         './resource/js/legacy/crowi-admin',
       'legacy-presentation':  './resource/js/legacy/crowi-presentation',
       'legacy-presentation':  './resource/js/legacy/crowi-presentation',
       'plugin':               './resource/js/plugin',
       'plugin':               './resource/js/plugin',
-      'style':                './resource/styles',
-      'style-presentation':   './resource/styles/presentation',
+      'style':                './resource/styles/scss/style.scss',
+      'style-theme-default':  './resource/styles/scss/theme/default.scss',
+      'style-theme-default-dark':  './resource/styles/scss/theme/default-dark.scss',
+      'style-presentation':   './resource/styles/scss/style-presentation.scss',
     },
     },
     externals: {
     externals: {
       // require("jquery") is external and available
       // require("jquery") is external and available
@@ -53,17 +55,27 @@ module.exports = function (options) {
             }
             }
           }]
           }]
         },
         },
+        {
+          test: /\.scss$/,
+          use: ExtractTextPlugin.extract({
+            fallback: 'style-loader',
+            use: 'css-loader!sass-loader'
+          }),
+          include: [helpers.root('resource/styles/scss')]
+        },
         {
         {
           test: /\.css$/,
           test: /\.css$/,
           use: ['style-loader', 'css-loader'],
           use: ['style-loader', 'css-loader'],
           // comment out 'include' spec for crowi-plugins
           // comment out 'include' spec for crowi-plugins
           // include: [helpers.root('resource')]
           // include: [helpers.root('resource')]
+          exclude: [helpers.root('resource/styles/scss')]
         },
         },
         {
         {
           test: /\.scss$/,
           test: /\.scss$/,
           use: ['style-loader', 'css-loader', 'sass-loader'],
           use: ['style-loader', 'css-loader', 'sass-loader'],
           // comment out 'include' spec for crowi-plugins
           // comment out 'include' spec for crowi-plugins
           // include: [helpers.root('resource')]
           // include: [helpers.root('resource')]
+          exclude: [helpers.root('resource/styles/scss')]
         },
         },
         /*
         /*
          * File loader for supporting images, for example, in CSS files.
          * File loader for supporting images, for example, in CSS files.
@@ -102,8 +114,6 @@ module.exports = function (options) {
         chunks: ['commons', 'plugin'],
         chunks: ['commons', 'plugin'],
       }),
       }),
 
 
-      new LodashModuleReplacementPlugin,
-
       // ignore
       // ignore
       new webpack.IgnorePlugin(/^\.\/lib\/deflate\.js/, /markdown-it-plantuml/),
       new webpack.IgnorePlugin(/^\.\/lib\/deflate\.js/, /markdown-it-plantuml/),
 
 

+ 3 - 0
config/webpack.dev.js

@@ -13,6 +13,7 @@ const commonConfig = require('./webpack.common.js');
  * Webpack Plugins
  * Webpack Plugins
  */
  */
 const CommonsChunkPlugin = require('webpack/lib/optimize/CommonsChunkPlugin');
 const CommonsChunkPlugin = require('webpack/lib/optimize/CommonsChunkPlugin');
+const ExtractTextPlugin = require('extract-text-webpack-plugin');
 const DllBundlesPlugin = require('webpack-dll-bundles-plugin').DllBundlesPlugin;
 const DllBundlesPlugin = require('webpack-dll-bundles-plugin').DllBundlesPlugin;
 const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin;
 const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin;
 
 
@@ -51,6 +52,8 @@ module.exports = function (options) {
     },
     },
     plugins: [
     plugins: [
 
 
+      new ExtractTextPlugin('[name].bundle.css'),
+
       new DllBundlesPlugin({
       new DllBundlesPlugin({
         bundles: {
         bundles: {
           vendor: [
           vendor: [

+ 3 - 0
config/webpack.prod.js

@@ -11,6 +11,7 @@ const commonConfig = require('./webpack.common.js'); // the settings that are co
  * Webpack Plugins
  * Webpack Plugins
  */
  */
 const CommonsChunkPlugin = require('webpack/lib/optimize/CommonsChunkPlugin');
 const CommonsChunkPlugin = require('webpack/lib/optimize/CommonsChunkPlugin');
+const ExtractTextPlugin = require('extract-text-webpack-plugin');
 const UglifyJsPlugin = require('webpack/lib/optimize/UglifyJsPlugin');
 const UglifyJsPlugin = require('webpack/lib/optimize/UglifyJsPlugin');
 const OptimizeJsPlugin = require('optimize-js-plugin');
 const OptimizeJsPlugin = require('optimize-js-plugin');
 const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin;
 const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin;
@@ -45,6 +46,8 @@ module.exports = function (env) {
         }
         }
       }),
       }),
 
 
+      new ExtractTextPlugin('[name].[contenthash].css'),
+
       new OptimizeJsPlugin({
       new OptimizeJsPlugin({
         sourceMap: false
         sourceMap: false
       }),
       }),

+ 19 - 52
lib/crowi/dev.js

@@ -6,7 +6,7 @@ const helpers = require('./helpers');
 
 
 const swig = require('swig-templates');
 const swig = require('swig-templates');
 const onHeaders = require('on-headers')
 const onHeaders = require('on-headers')
-const LRWebSocketServer = require('livereload-server/lib/server');
+
 
 
 class CrowiDev {
 class CrowiDev {
 
 
@@ -21,11 +21,10 @@ class CrowiDev {
   }
   }
 
 
   init() {
   init() {
-    this.requireForLiveReload();
+    this.requireForAutoReloadServer();
 
 
     this.initPromiseRejectionWarningHandler();
     this.initPromiseRejectionWarningHandler();
     this.initSwig();
     this.initSwig();
-    this.hackLRWebSocketServer();
   }
   }
 
 
   initPromiseRejectionWarningHandler() {
   initPromiseRejectionWarningHandler() {
@@ -38,44 +37,15 @@ class CrowiDev {
   }
   }
 
 
   /**
   /**
-   * require files for live reloading
+   * require files for node-dev auto reloading
    */
    */
-  requireForLiveReload() {
-    // environment file
-    require(path.join(this.crowi.rootDir, 'config', 'env.dev.js'));
-
+  requireForAutoReloadServer() {
     // load all json files for live reloading
     // load all json files for live reloading
     fs.readdirSync(this.crowi.localeDir).map((dirname) => {
     fs.readdirSync(this.crowi.localeDir).map((dirname) => {
       require(path.join(this.crowi.localeDir, dirname, 'translation.json'));
       require(path.join(this.crowi.localeDir, dirname, 'translation.json'));
     });
     });
   }
   }
 
 
-  /**
-   * prevent to crash socket with:
-   * -------------------------------------------------
-   * Error: read ECONNRESET
-   *     at exports._errnoException (util.js:1022:11)
-   *     at TCP.onread (net.js:569:26)
-   * -------------------------------------------------
-   *
-   * @see https://github.com/napcs/node-livereload/pull/15
-   *
-   * @memberOf CrowiDev
-   */
-  hackLRWebSocketServer() {
-    const orgCreateConnection = LRWebSocketServer.prototype._createConnection;
-
-    // replace https://github.com/livereload/livereload-server/blob/v0.2.3/lib/server.coffee#L74
-    LRWebSocketServer.prototype._createConnection = function(socket) {
-      // call original method with substituting 'this' obj
-      orgCreateConnection.call(this, socket);
-
-      socket.on('error', (err) => {
-        console.warn(`[WARN] An insignificant error occured in client socket: '${err}'`);
-      });
-    }
-  }
-
   /**
   /**
    *
    *
    *
    *
@@ -86,7 +56,7 @@ class CrowiDev {
    */
    */
   setup(server, app) {
   setup(server, app) {
     this.setupHeaderDebugger(app);
     this.setupHeaderDebugger(app);
-    this.setupEasyLiveReload(app);
+    this.setupBrowserSync(app);
   }
   }
 
 
   setupHeaderDebugger(app) {
   setupHeaderDebugger(app) {
@@ -100,23 +70,20 @@ class CrowiDev {
     });
     });
   }
   }
 
 
-  setupEasyLiveReload(app) {
-    if (!helpers.hasProcessFlag('livereload')) {
-      return;
-    }
-
-    debug('setupEasyLiveReload');
-
-    const livereload = require('easy-livereload');
-    app.use(livereload({
-      watchDirs: [
-        path.join(this.crowi.viewsDir),
-        path.join(this.crowi.publicDir),
-      ],
-      checkFunc: function(x) {
-        return /\.(html|css|js)$/.test(x);
-      },
-    }));
+  setupBrowserSync(app) {
+    debug('setupBrowserSync');
+
+    const browserSync = require('browser-sync');
+    const bs = browserSync.create().init({
+      logSnippet: false,
+      notify: false,
+      files: [
+        `${this.crowi.viewsDir}/**/*.html`,
+        `${this.crowi.publicDir}/**/*.js`,
+        `${this.crowi.publicDir}/**/*.css`,
+      ]
+    });
+    app.use(require('connect-browser-sync')(bs));
   }
   }
 
 
   loadPlugins(app) {
   loadPlugins(app) {

+ 18 - 5
lib/crowi/index.js

@@ -9,6 +9,7 @@ var debug = require('debug')('crowi:crowi')
 
 
   , mongoose    = require('mongoose')
   , mongoose    = require('mongoose')
 
 
+  , eazyLogger = require('eazy-logger')
   , helpers = require('./helpers')
   , helpers = require('./helpers')
   , models = require('../models')
   , models = require('../models')
   ;
   ;
@@ -16,6 +17,13 @@ var debug = require('debug')('crowi:crowi')
 function Crowi (rootdir, env)
 function Crowi (rootdir, env)
 {
 {
   var self = this;
   var self = this;
+  // this.logger = easyLogger.Logger({
+  //   prefix: '[{green:GROWI}]'
+  // });
+  this.logger = eazyLogger.Logger({
+    prefix: "[{green:GROWI}] ",
+    useLevelPrefixes: false,
+  });
 
 
   this.version = pkg.version;
   this.version = pkg.version;
   this.runtimeVersions = undefined;   // initialized by scanRuntimeVersions()
   this.runtimeVersions = undefined;   // initialized by scanRuntimeVersions()
@@ -368,12 +376,17 @@ Crowi.prototype.start = function() {
     .then(function(app) {
     .then(function(app) {
       server = http.createServer(app).listen(self.port, function() {
       server = http.createServer(app).listen(self.port, function() {
         debug(`[${self.node_env}] Express server listening on port ${self.port}`);
         debug(`[${self.node_env}] Express server listening on port ${self.port}`);
-      });
 
 
-      // setup
-      if (self.node_env === 'development') {
-        self.crowiDev.setup(server, app);
-      }
+        self.logger.info('{bold:Server URLs:}');
+        self.logger.unprefixed('info','{grey:=======================================}');
+        self.logger.unprefixed('info',`         APP: {magenta:http:://localhost:${self.port}}`);
+        self.logger.unprefixed('info','{grey:=======================================}');
+
+        // setup for dev
+        if (self.node_env === 'development') {
+          self.crowiDev.setup(server, app);
+        }
+      });
 
 
       io = require('socket.io')(server);
       io = require('socket.io')(server);
       io.sockets.on('connection', function (socket) {
       io.sockets.on('connection', function (socket) {

+ 10 - 0
lib/form/admin/customhighlightJsStyle.js

@@ -0,0 +1,10 @@
+'use strict';
+
+var form = require('express-form')
+  , field = form.field
+  ;
+
+module.exports = form(
+  field('settingForm[customize:highlightJsStyle]'),
+  field('settingForm[customize:highlightJsStyleBorder]').trim().toBooleanStrict()
+);

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

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

+ 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]')
+);

+ 3 - 0
lib/form/index.js

@@ -23,9 +23,12 @@ module.exports = {
     customcss: require('./admin/customcss'),
     customcss: require('./admin/customcss'),
     customscript: require('./admin/customscript'),
     customscript: require('./admin/customscript'),
     customheader: require('./admin/customheader'),
     customheader: require('./admin/customheader'),
+    customtheme: require('./admin/customtheme'),
+    customtitle: require('./admin/customtitle'),
     custombehavior: require('./admin/custombehavior'),
     custombehavior: require('./admin/custombehavior'),
     customlayout: require('./admin/customlayout'),
     customlayout: require('./admin/customlayout'),
     customfeatures: require('./admin/customfeatures'),
     customfeatures: require('./admin/customfeatures'),
+    customhighlightJsStyle: require('./admin/customhighlightJsStyle'),
     userInvite: require('./admin/userInvite'),
     userInvite: require('./admin/userInvite'),
     slackIwhSetting: require('./admin/slackIwhSetting'),
     slackIwhSetting: require('./admin/slackIwhSetting'),
     slackSetting: require('./admin/slackSetting'),
     slackSetting: require('./admin/slackSetting'),

+ 43 - 45
lib/locales/en-US/translation.json

@@ -47,6 +47,7 @@
   "View diff": "View diff",
   "View diff": "View diff",
 
 
   "User ID": "User ID",
   "User ID": "User ID",
+  "Home": "Home",
   "User Settings": "User Settings",
   "User Settings": "User Settings",
   "User Information": "User Information",
   "User Information": "User Information",
   "Basic Info": "Basic Info",
   "Basic Info": "Basic Info",
@@ -131,7 +132,6 @@
   "New password": "New password",
   "New password": "New password",
   "Re-enter new password": "Re-enter new password",
   "Re-enter new password": "Re-enter new password",
   "Password is not set": "Password is not set",
   "Password is not set": "Password is not set",
-  "You can sign in with email and password": "You can sign in with <code>%s</code> and password",
 
 
   "API Settings": "API Settings",
   "API Settings": "API Settings",
   "API Token Settings": "API Token Settings",
   "API Token Settings": "API Token Settings",
@@ -145,6 +145,7 @@
       "notice": {
       "notice": {
           "version": "This is not the current version.",
           "version": "This is not the current version.",
           "moved": "This page was moved from <code>%s</code>",
           "moved": "This page was moved from <code>%s</code>",
+          "duplicated": "This page was duplicated from <code>%s</code>",
           "unlinked": "Redirect pages to this page have been deleted.",
           "unlinked": "Redirect pages to this page have been deleted.",
           "restricted": "Access to this page is restricted"
           "restricted": "Access to this page is restricted"
       }
       }
@@ -252,11 +253,11 @@
     "Plugin settings": "Plugin settings",
     "Plugin settings": "Plugin settings",
     "Enable plugin loading": "Enable plugin loading",
     "Enable plugin loading": "Enable plugin loading",
     "Load plugins": "Load plugins",
     "Load plugins": "Load plugins",
-    "valid": "Valid",
-    "invalid": "Invalid"
+    "Enable": "Enable",
+    "Disable": "Disable"
 
 
   },
   },
- "security_setting": {
+  "security_setting": {
     "Basic authentication": "Basic authentication",
     "Basic authentication": "Basic authentication",
     "Security settings": "Security settings",
     "Security settings": "Security settings",
     "Guest users access": "Guest users access",
     "Guest users access": "Guest users access",
@@ -271,8 +272,7 @@
     "only_those":" Only those whose e-mail address including the company address can register.",
     "only_those":" Only those whose e-mail address including the company address can register.",
     "insert_single":"Please insert single e-mail address per line.",
     "insert_single":"Please insert single e-mail address per line.",
     "Authentication mechanism settings":"Authentication mechanism settings"
     "Authentication mechanism settings":"Authentication mechanism settings"
-
- },
+  },
 
 
   "markdown_setting": {
   "markdown_setting": {
     "markdown_rendering": "You can change Markdown rendering settings.",
     "markdown_rendering": "You can change Markdown rendering settings.",
@@ -281,47 +281,45 @@
     "validate_comment": "Validate Line Break in the comment section",
     "validate_comment": "Validate Line Break in the comment section",
     "treat_comment": "Treat line breaking in the comment section as <code>&lt;br&gt;</code> in HTML",
     "treat_comment": "Treat line breaking in the comment section as <code>&lt;br&gt;</code> in HTML",
     "TBD": "(TBD: Markdown function in the comment section has not been implemented yet)"
     "TBD": "(TBD: Markdown function in the comment section has not been implemented yet)"
+  },
 
 
-     },
-
-     "customize_page": {
-       "Behavior": "Behavior",
-       "Layout": "Layout",
-        "Function": "Function",
-        "function_choose": "You can choose Valid/Invalid of the function",
-        "Timeline function": "Timeline function",
-        "subpage_display": "You can show the timeline of the subpages.",
-        "performance_decrease": "If there are many subpages, performance decreases while page loading.",
-        "list_page_display": "You can speed up list page display by invalidating.",
-        "tab_switch": "Save tab-switching in the browser",
-        "save_edit": "Save edit tab and history tab switching in the browser and make it object for forward/back command of the browser.",
-        "by_invalidating": "By invalidating, you can make page transition as the only object for forward/back command of the browser.",
-        "Custom CSS": "Custom CSS",
-        "write_CSS": "You can write CSS that is applied to whole system.",
-        "reflect_change": "You need to reload the page to reflect the change.",
-        "ctrl_space": "Ctrl+Space to Autocomplete",
-        "Custom script": "Custom script",
-        "write_java": "You can write Javascript that is applied to whole system."
-
-
- },
+  "customize_page": {
+    "Behavior": "Behavior",
+    "Layout": "Layout",
+    "Function": "Function",
+    "function_choose": "You can choose Valid/Invalid of the function",
+    "Timeline function": "Timeline function",
+    "Code Highlight": "Code Highlight",
+    "Theme": "Theme",
+    "subpage_display": "You can show the timeline of the subpages.",
+    "performance_decrease": "If there are many subpages, performance decreases while page loading.",
+    "list_page_display": "You can speed up list page display by invalidating.",
+    "tab_switch": "Save tab-switching in the browser",
+    "save_edit": "Save edit tab and history tab switching in the browser and make it object for forward/back command of the browser.",
+    "by_invalidating": "By invalidating, you can make page transition as the only object for forward/back command of the browser.",
+    "Custom CSS": "Custom CSS",
+    "write_CSS": "You can write CSS that is applied to whole system.",
+    "reflect_change": "You need to reload the page to reflect the change.",
+    "ctrl_space": "Ctrl+Space to Autocomplete",
+    "Custom script": "Custom script",
+    "write_java": "You can write Javascript that is applied to whole system."
+  },
 
 
   "user_management": {
   "user_management": {
-        "User management": "User management",
-        "invite_users": "Invite new users",
-        "external_account": "External account management",
-        "user_list": "List of users",
-        "Date created": "Date created",
-        "Last login": "Last login",
-        "Manage": "Manage",
-        "Edit menu": "Edit menu",
-        "Reissue password": "Reissue password",
-        "Status":"Status",
-        "Deactivate account":"Deactivate account",
-        "your_own":"You cannot deactivate your own account",
-        "Administrator menu":"Administrator menu",
-        "cannot_remove":"You cannot remove yourself from administrator"
-
+    "User management": "User management",
+    "invite_users": "Invite new users",
+    "external_account": "External account management",
+    "user_list": "List of users",
+    "Date created": "Date created",
+    "Last login": "Last login",
+    "Manage": "Manage",
+    "Edit menu": "Edit menu",
+    "Reissue password": "Reissue password",
+    "Status":"Status",
+    "Deactivate account":"Deactivate account",
+    "your_own":"You cannot deactivate your own account",
+    "Administrator menu":"Administrator menu",
+    "cannot_remove":"You cannot remove yourself from administrator"
+  }
 
 
-      }
 }
 }

+ 41 - 46
lib/locales/ja/translation.json

@@ -44,6 +44,7 @@
   "View diff": "差分を見る",
   "View diff": "差分を見る",
 
 
   "User ID": "ユーザーID",
   "User ID": "ユーザーID",
+  "Home": "ホーム",
   "User Settings": "ユーザー設定",
   "User Settings": "ユーザー設定",
   "User Information": "ユーザー情報",
   "User Information": "ユーザー情報",
   "Basic Info": "ユーザーの基本情報",
   "Basic Info": "ユーザーの基本情報",
@@ -76,7 +77,6 @@
   "Table of Contents": "目次",
   "Table of Contents": "目次",
   "Management Wiki Home": "Wiki管理トップ",
   "Management Wiki Home": "Wiki管理トップ",
   "App settings": "アプリ設定",
   "App settings": "アプリ設定",
-  "Security settings": "セキュリティ設定",
   "Markdown settings": "Markdown設定",
   "Markdown settings": "Markdown設定",
   "Customize": "カスタマイズ",
   "Customize": "カスタマイズ",
   "Notification settings": "通知設定",
   "Notification settings": "通知設定",
@@ -84,7 +84,6 @@
   "UserGroup management": "グループ管理",
   "UserGroup management": "グループ管理",
   "Basic settings": "基本設定",
   "Basic settings": "基本設定",
   "Basic authentication": "Basic認証",
   "Basic authentication": "Basic認証",
-  "Password": "パスワード",
   "Guest users access": "ゲストユーザーのアクセス",
   "Guest users access": "ゲストユーザーのアクセス",
   "Register limitation": "登録の制限",
   "Register limitation": "登録の制限",
   "The contents entered here will be shown in the header etc": "ここに入力した内容は、ヘッダー等に表示されます。",
   "The contents entered here will be shown in the header etc": "ここに入力した内容は、ヘッダー等に表示されます。",
@@ -147,7 +146,6 @@
   "New password": "新しいパスワード",
   "New password": "新しいパスワード",
   "Re-enter new password": "(確認用)",
   "Re-enter new password": "(確認用)",
   "Password is not set": "パスワードが設定されていません",
   "Password is not set": "パスワードが設定されていません",
-  "You can sign in with email and password": "<code>%s</code> と設定されたパスワードの組み合わせでログイン可能になります。",
 
 
   "Security settings": "セキュリティ設定",
   "Security settings": "セキュリティ設定",
 
 
@@ -160,6 +158,7 @@
       "notice": {
       "notice": {
           "version": "これは現在の版ではありません。",
           "version": "これは現在の版ではありません。",
           "moved": "このページは <code>%s</code> から移動しました。",
           "moved": "このページは <code>%s</code> から移動しました。",
+          "duplicated": "このページは <code>%s</code> から複製されました。",
           "unlinked": "このページへのリダイレクトは削除されました。",
           "unlinked": "このページへのリダイレクトは削除されました。",
           "restricted": "このページの閲覧は制限されています"
           "restricted": "このページの閲覧は制限されています"
       }
       }
@@ -269,8 +268,8 @@
     "Plugin settings": "プラグイン設定",
     "Plugin settings": "プラグイン設定",
     "Enable plugin loading": "プラグインの読み込みを有効にします。",
     "Enable plugin loading": "プラグインの読み込みを有効にします。",
     "Load plugins": "プラグインを読み込む",
     "Load plugins": "プラグインを読み込む",
-    "valid": "有効",
-    "invalid": "無効"
+    "Enable": "有効",
+    "Disable": "無効"
 
 
    },
    },
 
 
@@ -290,7 +289,6 @@
     "insert_single":"1行に1メールアドレス入力してください。",
     "insert_single":"1行に1メールアドレス入力してください。",
     "Authentication mechanism settings":"認証機構設定"
     "Authentication mechanism settings":"認証機構設定"
   },
   },
-
   "markdown_setting": {
   "markdown_setting": {
     "markdown_rendering": "Markdownレンダリングの設定を変更できます。",
     "markdown_rendering": "Markdownレンダリングの設定を変更できます。",
     "validate Line Break": "Line Break を有効にする",
     "validate Line Break": "Line Break を有効にする",
@@ -301,48 +299,45 @@
 
 
   },
   },
 
 
-     "customize_page": {
-       "Behavior": "挙動",
-       "Layout": "レイアウト",
-       "Function": "機能",
-       "function_choose": "機能の有効/無効を選択できます。",
-       "Timeline function": "タイムライン機能",
-       "subpage_display": "配下ページのタイムラインを表示できます。",
-       "performance_decrease": "配下ページが多い場合はページロード時のパフォーマンスが落ちます。",
-       "list_page_display": "無効化することでリストページの表示を高速化できます。",
-       "tab_switch":"タブ変更をブラウザ履歴に保存",
-       "save_edit": "編集タブやヒストリータブ等の切り替えをブラウザ履歴に保存し、ブラウザの戻る/進む操作の対象にします。",
-       "by_invalidating": "無効化することで、ページ遷移のみを戻る/進む操作の対象にすることができます。",
-       "Custom CSS": "カスタム CSS",
-        "write_CSS": " システム全体に適用されるCSSを記述できます。",
-        "reflect_change": "変更の反映はページの更新が必要です。",
-        "ctrl_space": "Ctrl+Space でコード補完",
-        "Custom script": "カスタムスクリプト",
-        "write_java": "システム全体に適用されるJavaScriptを記述できます。"
-
- },
-
-     "user_management": {
-        "User management": "ユーザー管理",
-        "invite_users": "新規ユーザーの招待",
-        "external_account": "外部アカウントの管理",
-        "user_list": "ユーザー一覧",
-        "Date created": "作成日",
-        "Last login": "最終ログイン",
-        "Manage": "操作",
-        "Edit menu": "編集メニュー",
-        "Reissue password": "パスワードの再発行",
-        "Status":"ステータス",
-        "Deactivate account":"アカウント停止",
-        "your_own":"自分自身のアカウントを停止することはできません",
-        "Administrator menu":"管理者メニュー",
-        "cannot_remove":"自分自身を管理者から外すことはできません"
-
-
-
+  "customize_page": {
+    "Behavior": "挙動",
+    "Layout": "レイアウト",
+    "Function": "機能",
+    "function_choose": "機能の有効/無効を選択できます。",
+    "Timeline function": "タイムライン機能",
+    "Code Highlight": "コードハイライト",
+    "Theme": "テーマ",
+    "subpage_display": "配下ページのタイムラインを表示できます。",
+    "performance_decrease": "配下ページが多い場合はページロード時のパフォーマンスが落ちます。",
+    "list_page_display": "無効化することでリストページの表示を高速化できます。",
+    "tab_switch": "タブ変更をブラウザ履歴に保存",
+    "save_edit": "編集タブやヒストリータブ等の切り替えをブラウザ履歴に保存し、ブラウザの戻る/進む操作の対象にします。",
+    "by_invalidating": "無効化することで、ページ遷移のみを戻る/進む操作の対象にすることができます。",
+    "Custom CSS": "カスタム CSS",
+    "write_CSS": " システム全体に適用されるCSSを記述できます。",
+    "reflect_change": "変更の反映はページの更新が必要です。",
+    "ctrl_space": "Ctrl+Space でコード補完",
+    "Custom script": "カスタムスクリプト",
+    "write_java": "システム全体に適用されるJavaScriptを記述できます。"
 
 
+  },
 
 
+  "user_management": {
+    "User management": "ユーザー管理",
+    "invite_users": "新規ユーザーの招待",
+    "external_account": "外部アカウントの管理",
+    "user_list": "ユーザー一覧",
+    "Date created": "作成日",
+    "Last login": "最終ログイン",
+    "Manage": "操作",
+    "Edit menu": "編集メニュー",
+    "Reissue password": "パスワードの再発行",
+    "Status": "ステータス",
+    "Deactivate account": "アカウント停止",
+    "your_own": "自分自身のアカウントを停止することはできません",
+    "Administrator menu": "管理者メニュー",
+    "cannot_remove": "自分自身を管理者から外すことはできません"
+  }
 
 
-      }
 }
 }
 
 

+ 28 - 0
lib/models/config.js

@@ -85,6 +85,10 @@ module.exports = function(crowi) {
       'customize:css' : '',
       'customize:css' : '',
       'customize:script' : '',
       'customize:script' : '',
       'customize:header' : '',
       'customize:header' : '',
+      'customize:title' : '',
+      'customize:highlightJsStyle' : 'github',
+      'customize:highlightJsStyleBorder' : false,
+      'customize:theme' : 'default',
       'customize:behavior' : 'crowi',
       'customize:behavior' : 'crowi',
       'customize:layout' : 'crowi',
       'customize:layout' : 'crowi',
       'customize:isEnabledTimeline' : true,
       'customize:isEnabledTimeline' : true,
@@ -358,6 +362,18 @@ module.exports = function(crowi) {
     return getValueForCrowiNS(config, key);
     return getValueForCrowiNS(config, key);
   }
   }
 
 
+  configSchema.statics.theme = function(config)
+  {
+    const key = 'customize:theme';
+    return getValueForCrowiNS(config, key);
+  }
+
+  configSchema.statics.customTitle = function(config)
+  {
+    const key = 'customize:title';
+    return getValueForCrowiNS(config, key);
+  }
+
   configSchema.statics.behaviorType = function(config)
   configSchema.statics.behaviorType = function(config)
   {
   {
     const key = 'customize:behavior';
     const key = 'customize:behavior';
@@ -370,6 +386,18 @@ module.exports = function(crowi) {
     return getValueForCrowiNS(config, key);
     return getValueForCrowiNS(config, key);
   }
   }
 
 
+  configSchema.statics.highlightJsStyle = function(config)
+  {
+    const key = 'customize:highlightJsStyle';
+    return getValueForCrowiNS(config, key);
+  }
+
+  configSchema.statics.highlightJsStyleBorder = function(config)
+  {
+    const key = 'customize:highlightJsStyleBorder';
+    return getValueForCrowiNS(config, key);
+  }
+
   configSchema.statics.isEnabledTimeline = function(config)
   configSchema.statics.isEnabledTimeline = function(config)
   {
   {
     const key = 'customize:isEnabledTimeline';
     const key = 'customize:isEnabledTimeline';

+ 8 - 7
lib/plugins/plugin-utils.js

@@ -11,10 +11,10 @@ class PluginUtils {
    * return a definition objects that has following structure:
    * return a definition objects that has following structure:
    *
    *
    * {
    * {
-   *   name: 'crowi-plugin-X',
-   *   meta: require('crowi-plugin-X'),
+   *   name: 'growi-plugin-X',
+   *   meta: require('growi-plugin-X'),
    *   entries: [
    *   entries: [
-   *     'crowi-plugin-X/lib/client-entry'
+   *     'growi-plugin-X/lib/client-entry'
    *   ]
    *   ]
    * }
    * }
    *
    *
@@ -42,13 +42,14 @@ class PluginUtils {
   }
   }
 
 
   /**
   /**
-   * list plugin module objects that starts with 'crowi-plugin-'
+   * list plugin module objects
+   *  that starts with 'growi-plugin-' or 'crowi-plugin-'
    * borrowing from: https://github.com/hexojs/hexo/blob/d1db459c92a4765620343b95789361cbbc6414c5/lib/hexo/load_plugins.js#L17
    * borrowing from: https://github.com/hexojs/hexo/blob/d1db459c92a4765620343b95789361cbbc6414c5/lib/hexo/load_plugins.js#L17
    *
    *
    * @returns array of objects
    * @returns array of objects
    *   [
    *   [
-   *     { name: 'crowi-plugin-...', version: '1.0.0' },
-   *     { name: 'crowi-plugin-...', version: '1.0.0' },
+   *     { name: 'growi-plugin-...', version: '1.0.0' },
+   *     { name: 'growi-plugin-...', version: '1.0.0' },
    *     ...
    *     ...
    *   ]
    *   ]
    *
    *
@@ -69,7 +70,7 @@ class PluginUtils {
 
 
     let objs = {};
     let objs = {};
     Object.keys(deps).forEach((name) => {
     Object.keys(deps).forEach((name) => {
-      if (/^crowi-plugin-/.test(name)) {
+      if (/^(crowi|growi)-plugin-/.test(name)) {
         objs[name] = deps[name];
         objs[name] = deps[name];
       }
       }
     });
     });

+ 15 - 1
lib/routes/admin.js

@@ -134,8 +134,22 @@ module.exports = function(crowi, app) {
     var settingForm;
     var settingForm;
     settingForm = Config.setupCofigFormData('crowi', req.config);
     settingForm = Config.setupCofigFormData('crowi', req.config);
 
 
+    const highlightJsCssSelectorOptions = {
+      "github":           { name: '[Light] Github',         border: false },
+      "github-gist":      { name: '[Light] Github Gist',    border: true },
+      "atom-one-light":   { name: '[Light] Atom One Light', border: true },
+      "xcode":            { name: '[Light] Xcode',          border: true },
+      "vs":               { name: '[Light] Vs',             border: true },
+      "atom-one-dark":    { name: '[Dark] Atom One Dark',   border: false },
+      "hybrid":           { name: '[Dark] Hybrid',          border: false },
+      "monokai":          { name: '[Dark] Monokai',         border: false },
+      "tomorrow-night":   { name: '[Dark] Tomorrow Night',  border: false },
+      "vs2015":           { name: '[Dark] Vs 2015',         border: false },
+    }
+
     return res.render('admin/customize', {
     return res.render('admin/customize', {
       settingForm: settingForm,
       settingForm: settingForm,
+      highlightJsCssSelectorOptions: highlightJsCssSelectorOptions
     });
     });
   };
   };
 
 
@@ -385,7 +399,7 @@ module.exports = function(crowi, app) {
     User.findById(id, function(err, userData) {
     User.findById(id, function(err, userData) {
       userData.statusActivate(function(err, userData) {
       userData.statusActivate(function(err, userData) {
         if (err === null) {
         if (err === null) {
-          req.flash('successMessage', userData.name + 'さんのアカウントを承認しました');
+          req.flash('successMessage', userData.name + 'さんのアカウントを有効化しました');
         } else {
         } else {
           req.flash('errorMessage', '更新に失敗しました。');
           req.flash('errorMessage', '更新に失敗しました。');
           debug(err, userData);
           debug(err, userData);

+ 3 - 0
lib/routes/index.js

@@ -74,9 +74,12 @@ module.exports = function(crowi, app) {
   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/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/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/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);
+  app.post('/_api/admin/customize/highlightJsStyle' , loginRequired(crowi, app) , middleware.adminRequired() , csrf, form.admin.customhighlightJsStyle, admin.api.customizeSetting);
 
 
   // search admin
   // search admin
   app.get('/admin/search'              , loginRequired(crowi, app) , middleware.adminRequired() , admin.search.index);
   app.get('/admin/search'              , loginRequired(crowi, app) , middleware.adminRequired() , admin.search.index);

+ 3 - 1
lib/routes/page.js

@@ -161,6 +161,7 @@ module.exports = function(crowi, app) {
     var renderVars = {
     var renderVars = {
       page: null,
       page: null,
       path: path,
       path: path,
+      isPortal: false,
       pages: [],
       pages: [],
       tree: [],
       tree: [],
     };
     };
@@ -168,6 +169,7 @@ module.exports = function(crowi, app) {
     Page.hasPortalPage(path, req.user, req.query.revision)
     Page.hasPortalPage(path, req.user, req.query.revision)
     .then(function(portalPage) {
     .then(function(portalPage) {
       renderVars.page = portalPage;
       renderVars.page = portalPage;
+      renderVars.isPortal = (portalPage != null);
 
 
       if (portalPage) {
       if (portalPage) {
         renderVars.revision = portalPage.revision;
         renderVars.revision = portalPage.revision;
@@ -417,7 +419,7 @@ module.exports = function(crowi, app) {
   function renderPage(pageData, req, res) {
   function renderPage(pageData, req, res) {
     // create page
     // create page
     if (!pageData) {
     if (!pageData) {
-      return res.render('page', {
+      return res.render('customlayout-selector/not_found', {
         author: {},
         author: {},
         page: false,
         page: false,
       });
       });

+ 2 - 2
lib/util/middlewares.js

@@ -89,7 +89,7 @@ exports.swigFilters = function(app, swig) {
       return user.image;
       return user.image;
     }
     }
     else {
     else {
-      return '/images/userpicture.png';
+      return '/images/icons/user.svg';
     }
     }
   };
   };
 
 
@@ -165,7 +165,7 @@ exports.swigFilters = function(app, swig) {
 
 
     swig.setFilter('picture', function(user) {
     swig.setFilter('picture', function(user) {
       if (!user) {
       if (!user) {
-        return '/images/userpicture.png';
+        return '/images/icons/user.svg';
       }
       }
 
 
       if (user.isGravatarEnabled === true) {
       if (user.isGravatarEnabled === true) {

+ 41 - 0
lib/util/swigFunctions.js

@@ -25,6 +25,18 @@ module.exports = function(crowi, app, req, locals) {
     return req.csrfToken;
     return req.csrfToken;
   };
   };
 
 
+  locals.getAppTitleFontSize = function(appTitle) {
+    let fontSize = 22;
+    if (appTitle.length < 13) { /* do nothing */ }
+    else if (appTitle.length < 21) {
+      fontSize -= 3 * (Math.floor((appTitle.length - 13) / 3) + 1);
+    }
+    else  {
+      fontSize = 11;
+    }
+    return fontSize;
+  }
+
   /**
   /**
    * return true if enabled
    * return true if enabled
    */
    */
@@ -58,6 +70,12 @@ module.exports = function(crowi, app, req, locals) {
   }
   }
 
 
   locals.googleLoginEnabled = function() {
   locals.googleLoginEnabled = function() {
+    // return false if Passport is enabled
+    // because official crowi mechanism is not used.
+    if (locals.isEnabledPassport()) {
+      return false;
+    }
+
     var config = crowi.getConfig()
     var config = crowi.getConfig()
     return config.crowi['google:clientId'] && config.crowi['google:clientSecret'];
     return config.crowi['google:clientId'] && config.crowi['google:clientSecret'];
   };
   };
@@ -97,6 +115,19 @@ module.exports = function(crowi, app, req, locals) {
     return Config.customHeader(config);
     return Config.customHeader(config);
   }
   }
 
 
+  locals.theme = function() {
+    var config = crowi.getConfig()
+    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() {
   locals.behaviorType = function() {
     var config = crowi.getConfig()
     var config = crowi.getConfig()
     return Config.behaviorType(config);
     return Config.behaviorType(config);
@@ -107,6 +138,16 @@ module.exports = function(crowi, app, req, locals) {
     return Config.layoutType(config);
     return Config.layoutType(config);
   }
   }
 
 
+  locals.highlightJsStyle = function() {
+    var config = crowi.getConfig()
+    return Config.highlightJsStyle(config);
+  }
+
+  locals.highlightJsStyleBorder = function() {
+    var config = crowi.getConfig()
+    return Config.highlightJsStyleBorder(config);
+  }
+
   locals.isEnabledTimeline = function() {
   locals.isEnabledTimeline = function() {
     var config = crowi.getConfig()
     var config = crowi.getConfig()
     return Config.isEnabledTimeline(config);
     return Config.isEnabledTimeline(config);

+ 12 - 17
lib/views/_form.html

@@ -21,25 +21,20 @@
   <input type="hidden" id="form-body" name="pageForm[body]" value="{% if pageForm.body %}{{ pageForm.body }}{% endif %}">
   <input type="hidden" id="form-body" name="pageForm[body]" value="{% if pageForm.body %}{{ pageForm.body }}{% endif %}">
   <input type="hidden" name="pageForm[path]" value="{{ path }}">
   <input type="hidden" name="pageForm[path]" value="{{ path }}">
   <input type="hidden" name="pageForm[currentRevision]" value="{{ pageForm.currentRevision|default(page.revision._id.toString()) }}">
   <input type="hidden" name="pageForm[currentRevision]" value="{{ pageForm.currentRevision|default(page.revision._id.toString()) }}">
-  <div class="form-submit-group form-group form-inline">
-    {#<button class="btn btn-default">
-      <i class="fa fa-file-text"></i>
-      ファイルを追加 ...
-    </button>#}
-
-    <div class="pull-left">
+  <div class="page-editor-footer form-submit-group form-group form-inline
+      d-flex align-items-center justify-content-between">
+    <div>
       <div id="page-editor-options-selector"></div>
       <div id="page-editor-options-selector"></div>
     </div>
     </div>
 
 
-    <div class="pull-right form-inline page-form-setting" id="page-form-setting" data-slack-configured="{{ slackConfigured() }}">
+    <div class="form-inline page-form-setting d-flex align-items-center" id="page-form-setting" data-slack-configured="{{ slackConfigured() }}">
       {% if slackConfigured() %}
       {% if slackConfigured() %}
-      <span class="input-group extended-setting">
-        <span class="input-group-addon">
-          <label>
-            <i class="fa fa-slack"></i>
-            <input class="" type="checkbox" name="pageForm[notify][slack][on]" value="1">
-          </label>
-        </span>
+      <span class="input-group input-group-sm input-group-slack extended-setting m-r-5">
+        <div class="input-group-addon">
+          <img id="slack-mark-white" src="/images/icons/slack/mark-monochrome_white.svg" width="18" height="18">
+          <img id="slack-mark-black" src="/images/icons/slack/mark-monochrome_black.svg" width="18" height="18">
+          <input class="" type="checkbox" name="pageForm[notify][slack][on]" value="1">
+        </div>
         <input class="form-control" type="text" name="pageForm[notify][slack][channel]" value="{{ page.extended.slack|default('') }}" placeholder="slack-channel-name"
         <input class="form-control" type="text" name="pageForm[notify][slack][channel]" value="{{ page.extended.slack|default('') }}" placeholder="slack-channel-name"
           id="page-form-slack-channel"
           id="page-form-slack-channel"
           data-toggle="popover"
           data-toggle="popover"
@@ -54,7 +49,7 @@
       {% if forceGrant %}
       {% if forceGrant %}
       <input type="hidden" name="pageForm[grant]" value="{{ forceGrant }}">
       <input type="hidden" name="pageForm[grant]" value="{{ forceGrant }}">
       {% else %}
       {% else %}
-      <select name="pageForm[grant]" class="form-control">
+      <select name="pageForm[grant]" class="m-r-5 selectpicker btn-group-sm">
         {% for grantId, grantLabel in consts.pageGrants %}
         {% for grantId, grantLabel in consts.pageGrants %}
         <option value="{{ grantId }}" {% if pageForm.grant|default(page.grant) == grantId %}selected{% endif %} {% if grantId == 5 && userRelatedGroups.length == 0 %}disabled{% endif %}>{{ t(grantLabel) }}</option>
         <option value="{{ grantId }}" {% if pageForm.grant|default(page.grant) == grantId %}selected{% endif %} {% if grantId == 5 && userRelatedGroups.length == 0 %}disabled{% endif %}>{{ t(grantLabel) }}</option>
         {% endfor %}
         {% endfor %}
@@ -68,7 +63,7 @@
       </select>
       </select>
       {% endif %}
       {% endif %}
       <input type="hidden" id="edit-form-csrf" name="_csrf" value="{{ csrf() }}">
       <input type="hidden" id="edit-form-csrf" name="_csrf" value="{{ csrf() }}">
-      <input type="submit" class="btn btn-primary" id="edit-form-submit" value="{{ t('Update Page') }}" />
+      <button type="submit" class="btn btn-primary btn-submit" id="edit-form-submit">{{ t('Update') }}</button>
     </div>
     </div>
   </div>
   </div>
 </form>
 </form>

+ 7 - 6
lib/views/admin/app.html

@@ -2,7 +2,7 @@
 
 
 {% block html_title %}{{ t('App settings') }} · {% endblock %}
 {% block html_title %}{{ t('App settings') }} · {% endblock %}
 
 
-{% block content_head %}
+{% block content_header %}
 <div class="header-wrap">
 <div class="header-wrap">
   <header id="page-header">
   <header id="page-header">
     <h1 class="title" id="">{{ t('App settings') }}</h1>
     <h1 class="title" id="">{{ t('App settings') }}</h1>
@@ -133,7 +133,7 @@
         {{ t("app_setting.No_SMTP_setting") }}<br>
         {{ t("app_setting.No_SMTP_setting") }}<br>
           <br>
           <br>
 
 
-          <span class="text-danger"><i class="fa fa-warning"></i> {{ t("app_setting.change_setting") }}</span>
+          <span class="text-danger"><i class="ti-unlink"></i> {{ t("app_setting.change_setting") }}</span>
         </p>
         </p>
 
 
         <div class="form-group">
         <div class="form-group">
@@ -183,14 +183,15 @@
         <div class="form-group">
         <div class="form-group">
           <label for="settingForm[plugin:isEnabledPlugins]" class="col-xs-3 control-label">{{ t('app_setting.Load plugins') }}</label>
           <label for="settingForm[plugin:isEnabledPlugins]" class="col-xs-3 control-label">{{ t('app_setting.Load plugins') }}</label>
           <div class="col-xs-6">
           <div class="col-xs-6">
+
             <div class="btn-group btn-toggle" data-toggle="buttons">
             <div class="btn-group btn-toggle" data-toggle="buttons">
-              <label class="btn btn-default {% if settingForm['plugin:isEnabledPlugins'] %}active{% endif %}" data-active-class="primary">
+              <label class="btn btn-default btn-rounded btn-outline {% if settingForm['plugin:isEnabledPlugins'] %}active{% endif %}" data-active-class="primary">
                 <input name="settingForm[plugin:isEnabledPlugins]" value="true" type="radio"
                 <input name="settingForm[plugin:isEnabledPlugins]" value="true" type="radio"
-                    {% if true === settingForm['plugin:isEnabledPlugins'] %}checked{% endif %}> {{ t('app_setting.valid') }}
+                    {% if true === settingForm['plugin:isEnabledPlugins'] %}checked{% endif %}> ON
               </label>
               </label>
-              <label class="btn btn-default {% if !settingForm['plugin:isEnabledPlugins'] %}active{% endif %}" data-active-class="primary">
+              <label class="btn btn-default btn-rounded btn-outline {% if !settingForm['plugin:isEnabledPlugins'] %}active{% endif %}" data-active-class="default">
                 <input name="settingForm[plugin:isEnabledPlugins]" value="false" type="radio"
                 <input name="settingForm[plugin:isEnabledPlugins]" value="false" type="radio"
-                    {% if !settingForm['plugin:isEnabledPlugins'] %}checked{% endif %}> {{ t('app_setting.invalid') }}
+                    {% if !settingForm['plugin:isEnabledPlugins'] %}checked{% endif %}> OFF
               </label>
               </label>
             </div>
             </div>
           </div>
           </div>

+ 193 - 18
lib/views/admin/customize.html

@@ -2,11 +2,15 @@
 
 
 {% block html_title %}{{ t('Customize') }} {% endblock %}
 {% block html_title %}{{ t('Customize') }} {% endblock %}
 
 
+{% block style_css_block %}
+  <link rel="stylesheet" href="{{ webpack_asset('style').css }}">
+  <link rel="stylesheet" id="jssDefault" {# append id for theme selector #} href="{{ webpack_asset('style-theme-' + theme()).css }}">
+{% endblock %}
+
 {% block html_additional_headers %}
 {% block html_additional_headers %}
+  {% parent %}
   <!-- CodeMirror -->
   <!-- CodeMirror -->
-  <link rel="stylesheet" href="https://cdn.jsdelivr.net/g/codemirror@4.5.0(codemirror.css+addon/hint/show-hint.css)">
   <link rel="stylesheet" href="https://cdn.jsdelivr.net/jquery.ui/1.11.4/jquery-ui.min.css">
   <link rel="stylesheet" href="https://cdn.jsdelivr.net/jquery.ui/1.11.4/jquery-ui.min.css">
-  <link rel="stylesheet" href="https://cdn.jsdelivr.net/codemirror/4.5.0/theme/eclipse.css">
   <style>
   <style>
     .CodeMirror {
     .CodeMirror {
       border: 1px solid #eee;
       border: 1px solid #eee;
@@ -14,8 +18,7 @@
   </style>
   </style>
 {% endblock %}
 {% endblock %}
 
 
-
-{% block content_head %}
+{% block content_header %}
 <div class="header-wrap">
 <div class="header-wrap">
   <header id="page-header">
   <header id="page-header">
     <h1 class="title" id="">{{ t('Customize') }} </h1>
     <h1 class="title" id="">{{ t('Customize') }} </h1>
@@ -45,6 +48,36 @@
     </div>
     </div>
     <div class="col-md-9">
     <div class="col-md-9">
 
 
+      <form action="/_api/admin/customize/theme" method="post" class="form-horizontal" id="customthemeSettingForm" role="form">
+        <fieldset>
+          <legend>{{ t('customize_page.Theme') }}</legend>
+
+          <div id="themeOptions" class="d-flex">
+            <a id="theme-option-default" href="#"
+                class="default {% if 'default' === settingForm['customize:theme'] %}active{% endif %}"
+                onclick="selectTheme('default')"
+                data-theme="{{ webpack_asset('style-theme-default').css }}">
+              {% include 'widget/theme-colorbox.html' %}
+            </a>
+            <a id="theme-option-default-dark" href="#"
+                class="default-dark {% if 'default-dark' === settingForm['customize:theme'] %}active{% endif %}"
+                onclick="selectTheme('default-dark')"
+                data-theme="{{ webpack_asset('style-theme-default-dark').css }}">
+              {% include 'widget/theme-colorbox.html' %}
+            </a>
+          </div>
+
+          <div class="form-group">
+            <div class="col-xs-offset-5 col-xs-6">
+              <input type="hidden" id="hiddenInputTheme" name="settingForm[customize:theme]" value="{{ settingForm['customize:theme'] }}">
+              <input type="hidden" name="_csrf" value="{{ csrf() }}">
+              <button type="submit" class="btn btn-primary">{{ t('Update') }}</button>
+            </div>
+          </div>
+
+        </fieldset>
+      </form>
+
       <form action="/_api/admin/customize/behavior" method="post" class="form-horizontal" id="cutombehaviorSettingForm" role="form">
       <form action="/_api/admin/customize/behavior" method="post" class="form-horizontal" id="cutombehaviorSettingForm" role="form">
       <fieldset>
       <fieldset>
         <legend>{{ t('customize_page.Behavior') }}</legend>
         <legend>{{ t('customize_page.Behavior') }}</legend>
@@ -143,7 +176,6 @@
       </fieldset>
       </fieldset>
       </form>
       </form>
 
 
-
       <form action="/_api/admin/customize/features" method="post" class="form-horizontal" id="customfeaturesSettingForm" role="form">
       <form action="/_api/admin/customize/features" method="post" class="form-horizontal" id="customfeaturesSettingForm" role="form">
       <fieldset>
       <fieldset>
       <legend>{{ t('customize_page.Function') }}</legend>
       <legend>{{ t('customize_page.Function') }}</legend>
@@ -153,13 +185,13 @@
           <label for="settingForm[customize:isEnabledTimeline]" class="col-xs-3 control-label">{{ t('customize_page.Timeline function') }}</label>
           <label for="settingForm[customize:isEnabledTimeline]" class="col-xs-3 control-label">{{ t('customize_page.Timeline function') }}</label>
           <div class="col-xs-9">
           <div class="col-xs-9">
             <div class="btn-group btn-toggle" data-toggle="buttons">
             <div class="btn-group btn-toggle" data-toggle="buttons">
-              <label class="btn btn-default {% if settingForm['customize:isEnabledTimeline'] %}active{% endif %}" data-active-class="primary">
+              <label class="btn btn-default btn-rounded btn-outline {% if settingForm['customize:isEnabledTimeline'] %}active{% endif %}" data-active-class="primary">
                 <input name="settingForm[customize:isEnabledTimeline]" value="true" type="radio"
                 <input name="settingForm[customize:isEnabledTimeline]" value="true" type="radio"
-                    {% if true === settingForm['customize:isEnabledTimeline'] %}checked{% endif %}> {{ t('Valid') }}
+                    {% if true === settingForm['customize:isEnabledTimeline'] %}checked{% endif %}> ON
               </label>
               </label>
-              <label class="btn btn-default {% if !settingForm['customize:isEnabledTimeline'] %}active{% endif %}" data-active-class="primary">
+              <label class="btn btn-default btn-rounded btn-outline {% if !settingForm['customize:isEnabledTimeline'] %}active{% endif %}" data-active-class="default">
                 <input name="settingForm[customize:isEnabledTimeline]" value="false" type="radio"
                 <input name="settingForm[customize:isEnabledTimeline]" value="false" type="radio"
-                    {% if !settingForm['customize:isEnabledTimeline'] %}checked{% endif %}> {{ t('Invalid') }}
+                    {% if !settingForm['customize:isEnabledTimeline'] %}checked{% endif %}> OFF
               </label>
               </label>
             </div>
             </div>
 
 
@@ -177,13 +209,13 @@
           <label for="settingForm[customize:isSavedStatesOfTabChanges]" class="col-xs-3 control-label">{{ t("customize_page.tab_switch") }}</label>
           <label for="settingForm[customize:isSavedStatesOfTabChanges]" class="col-xs-3 control-label">{{ t("customize_page.tab_switch") }}</label>
           <div class="col-xs-9">
           <div class="col-xs-9">
             <div class="btn-group btn-toggle" data-toggle="buttons">
             <div class="btn-group btn-toggle" data-toggle="buttons">
-              <label class="btn btn-default {% if settingForm['customize:isSavedStatesOfTabChanges'] %}active{% endif %}" data-active-class="primary">
+              <label class="btn btn-default btn-rounded btn-outline {% if settingForm['customize:isSavedStatesOfTabChanges'] %}active{% endif %}" data-active-class="primary">
                 <input name="settingForm[customize:isSavedStatesOfTabChanges]" value="true" type="radio"
                 <input name="settingForm[customize:isSavedStatesOfTabChanges]" value="true" type="radio"
-                    {% if true === settingForm['customize:isSavedStatesOfTabChanges'] %}checked{% endif %}> {{ t('Valid') }}
+                    {% if true === settingForm['customize:isSavedStatesOfTabChanges'] %}checked{% endif %}> ON
               </label>
               </label>
-              <label class="btn btn-default {% if !settingForm['customize:isSavedStatesOfTabChanges'] %}active{% endif %}" data-active-class="primary">
+              <label class="btn btn-default btn-rounded btn-outline {% if !settingForm['customize:isSavedStatesOfTabChanges'] %}active{% endif %}" data-active-class="default">
                 <input name="settingForm[customize:isSavedStatesOfTabChanges]" value="false" type="radio"
                 <input name="settingForm[customize:isSavedStatesOfTabChanges]" value="false" type="radio"
-                    {% if !settingForm['customize:isSavedStatesOfTabChanges'] %}checked{% endif %}> {{ t('Invalid') }}
+                    {% if !settingForm['customize:isSavedStatesOfTabChanges'] %}checked{% endif %}> OFF
               </label>
               </label>
             </div>
             </div>
 
 
@@ -204,6 +236,67 @@
       </fieldset>
       </fieldset>
       </form>
       </form>
 
 
+      <form action="/_api/admin/customize/highlightJsStyle" method="post" class="form-horizontal" id="cutomhighlightJsStyleSettingForm" role="form">
+        <fieldset>
+          <legend>{{ t('customize_page.Code Highlight') }}</legend>
+          <div class="form-group">
+            <label for="settingForm[customize:highlightJsStyle]" class="col-xs-3 control-label">{{ t('customize_page.Theme') }}</label>
+            <div class="col-xs-9">
+              <select class="form-control selectpicker" name="settingForm[customize:highlightJsStyle]" onChange="selectHighlightJsStyle(event)">
+                {% for key in Object.keys(highlightJsCssSelectorOptions) %}
+                  <option value={{key}} {% if key == highlightJsStyle() %} selected {% endif %}>{{highlightJsCssSelectorOptions[key].name}}</option>
+                {% endfor %}
+              </select>
+            </div>
+          </div>
+
+          <div class="form-group">
+            <label for="settingForm[customize:highlightJsStyleBorder]" class="col-xs-3 control-label">(TBD) Border</label>
+            <div class="col-xs-9">
+              <div class="btn-group btn-toggle" data-toggle="buttons">
+                <label class="btn btn-default btn-rounded btn-outline {% if settingForm['customize:highlightJsStyleBorder'] %}active{% endif %}" data-active-class="primary">
+                  <input name="settingForm[customize:highlightJsStyleBorder]" value="true" type="radio"
+                      {% if true === settingForm['customize:highlightJsStyleBorder'] %}checked{% endif %}> ON
+                </label>
+                <label class="btn btn-default btn-rounded btn-outline {% if !settingForm['customize:highlightJsStyleBorder'] %}active{% endif %}" data-active-class="default">
+                  <input name="settingForm[customize:highlightJsStyleBorder]" value="false" type="radio"
+                      {% if !settingForm['customize:highlightJsStyleBorder'] %}checked{% endif %}> OFF
+                </label>
+              </div>
+            </div>
+          </div>
+
+          <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/highlight.js@9.12.0/styles/{{ highlightJsStyle() }}.css" class="highlightJsCss">
+
+          <p class="help-block">
+            Examples:
+            <pre class="hljs"><code class="highlightjs-demo">function $initHighlight(block, cls) {
+  try {
+    if (cls.search(/\bno\-highlight\b/) != -1)
+      return process(block, true, 0x0F) +
+              ` class="${cls}"`;
+  } catch (e) {
+    /* handle exception */
+  }
+  for (var i = 0 / 2; i < classes.length; i++) {
+    if (checkCondition(classes[i]) === undefined)
+      console.log('undefined');
+  }
+}
+
+export  $initHighlight;</code></pre>
+          </p>
+
+          <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">{{ t('Update') }}</button>
+            </div>
+          </div>
+
+        </fieldset>
+      </form>
+
       <form action="/_api/admin/customize/header" method="post" class="form-horizontal" id="cutomheaderSettingForm" role="form">
       <form action="/_api/admin/customize/header" method="post" class="form-horizontal" id="cutomheaderSettingForm" role="form">
       <fieldset>
       <fieldset>
         <legend>カスタムヘッダーHTML</legend>
         <legend>カスタムヘッダーHTML</legend>
@@ -215,7 +308,7 @@
 
 
         <p class="help-block">
         <p class="help-block">
           Examples:
           Examples:
-          <pre><code>&lt;script src="https://cdn.jsdelivr.net/gh/highlightjs/cdn-release@9.12.0/build/languages/yaml.min.js" defer&gt;&lt;script&gt;</script></code></pre>
+          <pre class="hljs"><code>&lt;script src="https://cdn.jsdelivr.net/gh/highlightjs/cdn-release@9.12.0/build/languages/yaml.min.js" defer&gt;&lt;/script&gt;</code></pre>
         </p>
         </p>
 
 
         <div class="form-group">
         <div class="form-group">
@@ -234,13 +327,55 @@
         <div class="form-group">
         <div class="form-group">
           <div class="col-xs-offset-5 col-xs-6">
           <div class="col-xs-offset-5 col-xs-6">
             <input type="hidden" name="_csrf" value="{{ csrf() }}">
             <input type="hidden" name="_csrf" value="{{ csrf() }}">
-            <button type="submit" class="btn btn-primary">更新</button>
+            <button type="submit" class="btn btn-primary">{{ t('Update') }}</button>
           </div>
           </div>
         </div>
         </div>
 
 
       </fieldset>
       </fieldset>
       </form>
       </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">
       <form action="/_api/admin/customize/css" method="post" class="form-horizontal" id="cutomcssSettingForm" role="form">
       <fieldset>
       <fieldset>
         <legend>{{ t('customize_page.Custom CSS') }}</legend>
         <legend>{{ t('customize_page.Custom CSS') }}</legend>
@@ -301,7 +436,7 @@
         </p>
         </p>
         <p class="help-block">
         <p class="help-block">
           Examples:
           Examples:
-<pre><code>console.log($('.main-container'));
+<pre class="hljs"><code>console.log($('.main-container'));
 
 
 window.addEventListener('load', (event) => {
 window.addEventListener('load', (event) => {
   console.log('config: ', crowi.config);
   console.log('config: ', crowi.config);
@@ -333,9 +468,14 @@ window.addEventListener('load', (event) => {
 
 
     </div>
     </div>
   </div>
   </div>
+{% endblock content_main %}
 
 
+{% block body_end %}
+  {% parent %}
   <script>
   <script>
-    $('#cutomcssSettingForm, #cutomscriptSettingForm, #cutomlayoutSettingForm, #cutombehaviorSettingForm, #customfeaturesSettingForm, #cutomheaderSettingForm').each(function() {
+    $(`#customthemeSettingForm, #cutomlayoutSettingForm, #cutombehaviorSettingForm, #cutomhighlightJsStyleSettingForm,
+       #customfeaturesSettingForm, #cutomheaderSettingForm, #cutomcssSettingForm, #cutomscriptSettingForm, #customtitleSettingForm`
+    ).each(function() {
       $(this).submit(function()
       $(this).submit(function()
       {
       {
         function showMessage(formId, msg, status) {
         function showMessage(formId, msg, status) {
@@ -383,10 +523,45 @@ window.addEventListener('load', (event) => {
       });
       });
     });
     });
 
 
+    /*
+     * highlight.js style switcher
+     */
+    hljs.initHighlightingOnLoad()
+
+    function selectHighlightJsStyle(event) {
+      var highlightJsCssDOM = $(".highlightJsCss")[0]
+      // selected value
+      var val = event.target.value
+      // replace css url
+      // see https://regex101.com/r/gBNZYu/4
+      highlightJsCssDOM.href = highlightJsCssDOM.href.replace(/[^/]+\.css$/, `${val}.css`);
+    }
+
+    /*
+     * Theme Selector
+     */
+    options = {
+      hasPreview: false,
+      fullPath: '',
+      cookie: {
+        isManagingLoad: false
+      }
+    };
+    $(document).ready(function() {
+      $('#themeOptions').styleSwitcher(options);
+    });
+
+    function selectTheme(theme) {
+      // update hidden
+      $('#hiddenInputTheme').val(theme);
+      // update .active class
+      $('#themeOptions .active').removeClass('active');
+      $(`#themeOptions #theme-option-${theme}`).addClass('active');
+    }
   </script>
   </script>
 
 
 </div>
 </div>
-{% endblock content_main %}
+{% endblock %}
 
 
 {% block content_footer %}
 {% block content_footer %}
 {% endblock content_footer %}
 {% endblock content_footer %}

+ 16 - 14
lib/views/admin/external-accounts.html

@@ -2,7 +2,7 @@
 
 
 {% block html_title %}外部アカウント管理 · {% endblock %}
 {% block html_title %}外部アカウント管理 · {% endblock %}
 
 
-{% block content_head %}
+{% block content_header %}
 <div class="header-wrap">
 <div class="header-wrap">
   <header id="page-header">
   <header id="page-header">
     <h1 class="title" id="">ユーザー管理/外部アカウント管理</h1>
     <h1 class="title" id="">ユーザー管理/外部アカウント管理</h1>
@@ -41,14 +41,14 @@
     <div class="col-md-9">
     <div class="col-md-9">
       <p>
       <p>
         <a class="btn btn-default" href="/admin/users">
         <a class="btn btn-default" href="/admin/users">
-          <i class="fa fa-arrow-left" aria-hidden="true"></i>
+          <i class="icon-fw ti-arrow-left" aria-hidden="true"></i>
           ユーザー管理に戻る
           ユーザー管理に戻る
         </a>
         </a>
       </p>
       </p>
 
 
       <h2>外部アカウント一覧</h2>
       <h2>外部アカウント一覧</h2>
 
 
-      <table class="table table-hover table-striped table-bordered table-user-list">
+      <table class="table table-bordered table-user-list">
         <thead>
         <thead>
           <tr>
           <tr>
             <th width="120px">Authentication Provider</th>
             <th width="120px">Authentication Provider</th>
@@ -62,12 +62,12 @@
                   data-animation="false" data-html="true"
                   data-animation="false" data-html="true"
                   data-content="<small>関連付けられているユーザーがパスワードを設定しているかどうかを表示します</small>">
                   data-content="<small>関連付けられているユーザーがパスワードを設定しているかどうかを表示します</small>">
                 <small>
                 <small>
-                  <i class="fa fa-info-circle" aria-hidden="true"></i>
+                  <i class="icon-question" aria-hidden="true"></i>
                 </small>
                 </small>
               </a>
               </a>
             </th>
             </th>
-            <th width="100px">作成日</th>
-            <th width="90px">操作</th>
+            <th width="100px">{{ t('user_management.Date created') }}</th>
+            <th width="70px"></th>
           </tr>
           </tr>
         </thead>
         </thead>
         <tbody>
         <tbody>
@@ -96,16 +96,18 @@
               <div class="btn-group admin-user-menu">
               <div class="btn-group admin-user-menu">
 
 
                 <button type="button" class="btn btn-default btn-sm dropdown-toggle" data-toggle="dropdown">
                 <button type="button" class="btn btn-default btn-sm dropdown-toggle" data-toggle="dropdown">
-                  編集
-                  <span class="caret"></span>
+                  <i class="icon-settings"></i> <span class="caret"></span>
                 </button>
                 </button>
                 <ul class="dropdown-menu" role="menu">
                 <ul class="dropdown-menu" role="menu">
-                  <li class="dropdown-header">編集メニュー</li>
-                  <li class="dropdown-button">
-                    <form action="/admin/users/external-accounts/{{ account.accountId }}/remove" method="post">
-                      <input type="hidden" name="_csrf" value="{{ csrf() }}">
-                      <button type="submit" class="btn btn-block btn-danger">削除する</button>
-                    </form>
+                  <li class="dropdown-header">{{ t('user_management.Edit menu') }}</li>
+                  <form id="form_remove_{{ account.accountId }}" action="/admin/users/external-accounts/{{ account.accountId }}/remove" method="post">
+                    <input type="hidden" name="_csrf" value="{{ csrf() }}">
+                  </form>
+                  <li>
+                    <a href="javascript:form_remove_{{ account.accountId }}.submit()">
+                      <i class="icon-fw icon-fire text-danger"></i>
+                      削除する
+                    </a>
                   </li>
                   </li>
                 </ul>{# end of .dropdown-menu #}
                 </ul>{# end of .dropdown-menu #}
 
 

+ 7 - 3
lib/views/admin/index.html

@@ -2,7 +2,7 @@
 
 
 {% block html_title %}{{ t('admin_top.Management Wiki') }}· {{ path }}{% endblock %}
 {% block html_title %}{{ t('admin_top.Management Wiki') }}· {{ path }}{% endblock %}
 
 
-{% block content_head %}
+{% block content_header %}
 <div class="header-wrap">
 <div class="header-wrap">
   <header id="page-header">
   <header id="page-header">
     <h1 class="title" id=""> {{ t('admin_top.Management Wiki') }}</h1>
     <h1 class="title" id=""> {{ t('admin_top.Management Wiki') }}</h1>
@@ -29,7 +29,9 @@
       {{ t("admin_top.assign_administrator") }}
       {{ t("admin_top.assign_administrator") }}
       </p>
       </p>
 
 
-      <h3>{{ t('admin_top.System Information') }}</h3>
+      <legend>
+        <h2>{{ t('admin_top.System Information') }}</h2>
+      </legend>
       <table class="table table-bordered">
       <table class="table table-bordered">
         <tr>
         <tr>
           <th class="col-sm-4">crowi-plus</th>
           <th class="col-sm-4">crowi-plus</th>
@@ -49,7 +51,9 @@
         </tr>
         </tr>
       </table>
       </table>
 
 
-      <h3>{{ t('admin_top.List of installed plugins') }}</h3>
+      <legend>
+        <h2>{{ t('admin_top.List of installed plugins') }}</h2>
+      </legend>
       <table class="table table-bordered">
       <table class="table table-bordered">
         <th class="text-center">
         <th class="text-center">
           {{ t('admin_top.Package name') }}
           {{ t('admin_top.Package name') }}

+ 9 - 9
lib/views/admin/markdown.html

@@ -3,7 +3,7 @@
 {% block html_title %}{{ t('Markdown settings') }}
 {% block html_title %}{{ t('Markdown settings') }}
  · {{ path }}{% endblock %}
  · {{ path }}{% endblock %}
 
 
-{% block content_head %}
+{% block content_header %}
 <div class="header-wrap">
 <div class="header-wrap">
   <header id="page-header">
   <header id="page-header">
     <h1 class="title" id="">{{ t('Markdown settings') }}</h1>
     <h1 class="title" id="">{{ t('Markdown settings') }}</h1>
@@ -48,13 +48,13 @@
           </label>
           </label>
           <div class="col-xs-5">
           <div class="col-xs-5">
             <div class="btn-group btn-toggle" data-toggle="buttons">
             <div class="btn-group btn-toggle" data-toggle="buttons">
-              <label class="btn btn-default {% if markdownSetting['markdown:isEnabledLinebreaks'] %}active{% endif %}" data-active-class="primary">
+              <label class="btn btn-default btn-rounded btn-outline {% if markdownSetting['markdown:isEnabledLinebreaks'] %}active{% endif %}" data-active-class="primary">
                 <input name="markdownSetting[markdown:isEnabledLinebreaks]" value="true" type="radio"
                 <input name="markdownSetting[markdown:isEnabledLinebreaks]" value="true" type="radio"
-                    {% if true === markdownSetting['markdown:isEnabledLinebreaks'] %}checked{% endif %}> {{ t('valid') }}
+                    {% if true === markdownSetting['markdown:isEnabledLinebreaks'] %}checked{% endif %}> ON
               </label>
               </label>
-              <label class="btn btn-default {% if !markdownSetting['markdown:isEnabledLinebreaks'] %}active{% endif %}" data-active-class="primary">
+              <label class="btn btn-default btn-rounded btn-outline {% if !markdownSetting['markdown:isEnabledLinebreaks'] %}active{% endif %}" data-active-class="default">
                 <input name="markdownSetting[markdown:isEnabledLinebreaks]" value="false" type="radio"
                 <input name="markdownSetting[markdown:isEnabledLinebreaks]" value="false" type="radio"
-                    {% if !markdownSetting['markdown:isEnabledLinebreaks'] %}checked{% endif %}> {{ t('invalid') }}
+                    {% if !markdownSetting['markdown:isEnabledLinebreaks'] %}checked{% endif %}> OFF
               </label>
               </label>
             </div>
             </div>
             <p class="help-block">{{ t("markdown_setting.treat_text") }}
             <p class="help-block">{{ t("markdown_setting.treat_text") }}
@@ -68,13 +68,13 @@
           </label>
           </label>
           <div class="col-xs-5">
           <div class="col-xs-5">
             <div class="btn-group btn-toggle" data-toggle="buttons">
             <div class="btn-group btn-toggle" data-toggle="buttons">
-              <label class="btn btn-default {% if markdownSetting['markdown:isEnabledLinebreaksInComments'] %}active{% endif %}" data-active-class="primary">
+              <label class="btn btn-default btn-rounded btn-outline {% if markdownSetting['markdown:isEnabledLinebreaksInComments'] %}active{% endif %}" data-active-class="primary">
                 <input name="markdownSetting[markdown:isEnabledLinebreaksInComments]" value="true" type="radio"
                 <input name="markdownSetting[markdown:isEnabledLinebreaksInComments]" value="true" type="radio"
-                    {% if true === markdownSetting['markdown:isEnabledLinebreaksInComments'] %}checked{% endif %}> {{ t('valid') }}
+                    {% if true === markdownSetting['markdown:isEnabledLinebreaksInComments'] %}checked{% endif %}> ON
               </label>
               </label>
-              <label class="btn btn-default {% if !markdownSetting['markdown:isEnabledLinebreaksInComments'] %}active{% endif %}" data-active-class="primary">
+              <label class="btn btn-default btn-rounded btn-outline {% if !markdownSetting['markdown:isEnabledLinebreaksInComments'] %}active{% endif %}" data-active-class="default">
                 <input name="markdownSetting[markdown:isEnabledLinebreaksInComments]" value="false" type="radio"
                 <input name="markdownSetting[markdown:isEnabledLinebreaksInComments]" value="false" type="radio"
-                    {% if !markdownSetting['markdown:isEnabledLinebreaksInComments'] %}checked{% endif %}> {{ t('invalid') }}
+                    {% if !markdownSetting['markdown:isEnabledLinebreaksInComments'] %}checked{% endif %}> OFF
               </label>
               </label>
             </div>
             </div>
             <p class="help-block">{{ t("markdown_setting.treat_comment") }}<br>{{ t("markdown_setting.TBD") }}</p>
             <p class="help-block">{{ t("markdown_setting.treat_comment") }}<br>{{ t("markdown_setting.TBD") }}</p>

+ 13 - 13
lib/views/admin/notification.html

@@ -2,7 +2,7 @@
 
 
 {% block html_title %}{{ t('Notification settings') }} · {{ path }}{% endblock %}
 {% block html_title %}{{ t('Notification settings') }} · {{ path }}{% endblock %}
 
 
-{% block content_head %}
+{% block content_header %}
 <div class="header-wrap">
 <div class="header-wrap">
   <header id="page-header">
   <header id="page-header">
     <h1 class="title" id="">{{ t('Notification settings') }}</h1>
     <h1 class="title" id="">{{ t('Notification settings') }}</h1>
@@ -38,10 +38,10 @@
 
 
       <ul class="nav nav-tabs" role="tablist">
       <ul class="nav nav-tabs" role="tablist">
         <li class="active">
         <li class="active">
-          <a href="#slack-app" data-toggle="tab" role="tab"><i class="fa fa-slack"></i> Slack App</a>
+          <a href="#slack-app" data-toggle="tab" role="tab"><i class="icon-settings"></i> Slack App</a>
         </li>
         </li>
         <li role="tab">
         <li role="tab">
-          <a href="#slack-incoming-webhooks" data-toggle="tab" role="tab"><i class="fa fa-slack"></i> Slack Incoming Webhooks</a>
+          <a href="#slack-incoming-webhooks" data-toggle="tab" role="tab"><i class="icon-settings"></i> Slack Incoming Webhooks</a>
         </li>
         </li>
       </ul>
       </ul>
 
 
@@ -52,8 +52,8 @@
             <fieldset>
             <fieldset>
               <legend>Slack App Configuration</legend>
               <legend>Slack App Configuration</legend>
 
 
-              <p class="well text-warning">
-                <i class="fa fa-warning"></i> NOT RECOMMENDED
+              <p class="well">
+                <i class="icon-fw icon-exclamation text-danger"></i><span class="text-danger">NOT RECOMMENDED</span>
                 <br><br>
                 <br><br>
                 This is the way that compatible with the official Crowi,<br>
                 This is the way that compatible with the official Crowi,<br>
                 but not recommended in crowi-plus because it is too complex.
                 but not recommended in crowi-plus because it is too complex.
@@ -88,16 +88,16 @@
           <div class="text-center">
           <div class="text-center">
             {% if hasSlackToken %}
             {% if hasSlackToken %}
             <p>Crowi and Slack is already <strong>connected</strong>. You can re-connect to refresh and overwirte the token with your Slack account.</p>
             <p>Crowi and Slack is already <strong>connected</strong>. You can re-connect to refresh and overwirte the token with your Slack account.</p>
-            <a class="btn btn-warning" href="/admin/notification/slackSetting/disconnect">
-              <i class="fa fa-slack"></i> Disconnect from Slack
+            <a class="btn btn-warning btn-rounded" href="/admin/notification/slackSetting/disconnect">
+              <i class="icon-power"></i> Disconnect from Slack
             </a>
             </a>
-            <a class="btn btn-default" href="{{ slackAuthUrl }}" target="_blank">
-              <i class="fa fa-slack"></i> Reconnect to Slack
+            <a class="btn btn-success btn-outline btn-rounded" href="{{ slackAuthUrl }}" target="_blank">
+              <i class="icon-login"></i> Reconnect to Slack
             </a>
             </a>
             {% else %}
             {% else %}
             <p>Slack clientId and clientSecret is configured. Now, you can connect with Slack.</p>
             <p>Slack clientId and clientSecret is configured. Now, you can connect with Slack.</p>
-            <a class="btn btn-primary" href="{{ slackAuthUrl }}" target="_blank">
-              <i class="fa fa-slack"></i> Connect to Slack
+            <a class="btn btn-primary btn-outline2 btn-rounded" href="{{ slackAuthUrl }}" target="_blank">
+              <i class="icon-login"></i> Connect to Slack
             </a>
             </a>
             {% endif %}
             {% endif %}
           </div>
           </div>
@@ -107,7 +107,7 @@
           {# {% if not hasSlackWebClientConfig %} #}
           {# {% if not hasSlackWebClientConfig %} #}
           <hr>
           <hr>
           <h3>
           <h3>
-            <i class="fa fa-question-circle" aria-hidden="true"></i>
+            <i class="icon-question" aria-hidden="true"></i>
             <a href="#collapseHelpForApp" data-toggle="collapse">How to configure Slack App?</a>
             <a href="#collapseHelpForApp" data-toggle="collapse">How to configure Slack App?</a>
           </h3>
           </h3>
 
 
@@ -217,7 +217,7 @@
 
 
           <hr>
           <hr>
           <h3>
           <h3>
-            <i class="fa fa-question-circle" aria-hidden="true"></i>
+            <i class="icon-question" aria-hidden="true"></i>
             <a href="#collapseHelpForIwh" data-toggle="collapse">How to configure Incoming Webhooks?</a>
             <a href="#collapseHelpForIwh" data-toggle="collapse">How to configure Incoming Webhooks?</a>
           </h3>
           </h3>
 
 

+ 2 - 2
lib/views/admin/search.html

@@ -2,7 +2,7 @@
 
 
 {% block html_title %}検索管理 · {{ path }}{% endblock %}
 {% block html_title %}検索管理 · {{ path }}{% endblock %}
 
 
-{% block content_head %}
+{% block content_header %}
 <div class="header-wrap">
 <div class="header-wrap">
   <header id="page-header">
   <header id="page-header">
     <h1 class="title" id="">検索管理</h1>
     <h1 class="title" id="">検索管理</h1>
@@ -42,7 +42,7 @@
         <div class="form-group">
         <div class="form-group">
           <label for="" class="col-xs-3 control-label">Index Build</label>
           <label for="" class="col-xs-3 control-label">Index Build</label>
           <div class="col-xs-6">
           <div class="col-xs-6">
-            <button type="submit" class="btn btn-primary">Build Now</button>
+            <button type="submit" class="btn btn-inverse">Build Now</button>
             <p class="help-block">
             <p class="help-block">
               Force rebuild index.<br>
               Force rebuild index.<br>
               Click "Build Now" to delete and create mapping file and add all pages.<br>
               Click "Build Now" to delete and create mapping file and add all pages.<br>

+ 18 - 18
lib/views/admin/security.html

@@ -2,7 +2,7 @@
 
 
 {% block html_title %}{{ t('Security settings') }} · {% endblock %}
 {% block html_title %}{{ t('Security settings') }} · {% endblock %}
 
 
-{% block content_head %}
+{% block content_header %}
 <div class="header-wrap">
 <div class="header-wrap">
   <header id="page-header">
   <header id="page-header">
     <h1 class="title" id="">{{ t('Security settings') }}</h1>
     <h1 class="title" id="">{{ t('Security settings') }}</h1>
@@ -38,7 +38,7 @@
 
 
       <form action="/_api/admin/security/general" method="post" class="form-horizontal" id="generalSetting" role="form">
       <form action="/_api/admin/security/general" method="post" class="form-horizontal" id="generalSetting" role="form">
         <fieldset>
         <fieldset>
-        <legend>{{ t('security_setting.Security settings') }}</legend>
+        <legend class="alert-anchor">{{ t('security_setting.Security settings') }}</legend>
 
 
           <div class="form-group">
           <div class="form-group">
             <label for="settingForm[security:registrationMode]" class="col-xs-3 control-label">{{ t('Basic authentication') }}</label>
             <label for="settingForm[security:registrationMode]" class="col-xs-3 control-label">{{ t('Basic authentication') }}</label>
@@ -61,7 +61,7 @@
           <div class="form-group">
           <div class="form-group">
             <label for="settingForm[security:restrictGuestMode]" class="col-xs-3 control-label">{{ t('Guest users access') }}</label>
             <label for="settingForm[security:restrictGuestMode]" class="col-xs-3 control-label">{{ t('Guest users access') }}</label>
             <div class="col-xs-6">
             <div class="col-xs-6">
-              <select class="form-control" name="settingForm[security:restrictGuestMode]" value="{{ settingForm['security:restrictGuestMode'] }}">
+              <select class="form-control selectpicker" name="settingForm[security:restrictGuestMode]" value="{{ settingForm['security:restrictGuestMode'] }}">
                 {% for modeValue, modeLabel in consts.restrictGuestMode %}
                 {% for modeValue, modeLabel in consts.restrictGuestMode %}
                 <option value="{{ modeValue }}" {% if modeValue == settingForm['security:restrictGuestMode'] %}selected{% endif %} >{{ modeLabel }}</option>
                 <option value="{{ modeValue }}" {% if modeValue == settingForm['security:restrictGuestMode'] %}selected{% endif %} >{{ modeLabel }}</option>
                 {% endfor %}
                 {% endfor %}
@@ -72,7 +72,7 @@
           <div class="form-group">
           <div class="form-group">
             <label for="settingForm[security:registrationMode]" class="col-xs-3 control-label">{{ t('Register limitation') }}</label>
             <label for="settingForm[security:registrationMode]" class="col-xs-3 control-label">{{ t('Register limitation') }}</label>
             <div class="col-xs-6">
             <div class="col-xs-6">
-              <select class="form-control" name="settingForm[security:registrationMode]" value="{{ settingForm['security:registrationMode'] }}">
+              <select class="form-control selectpicker" name="settingForm[security:registrationMode]" value="{{ settingForm['security:registrationMode'] }}">
                 {% for modeValue, modeLabel in consts.registrationMode %}
                 {% for modeValue, modeLabel in consts.registrationMode %}
                 <option value="{{ modeValue }}" {% if modeValue == settingForm['security:registrationMode'] %}selected{% endif %} >{{ modeLabel }}</option>
                 <option value="{{ modeValue }}" {% if modeValue == settingForm['security:registrationMode'] %}selected{% endif %} >{{ modeLabel }}</option>
                 {% endfor %}
                 {% endfor %}
@@ -100,9 +100,9 @@
         </fieldset>
         </fieldset>
       </form>
       </form>
 
 
-      <form action="/_api/admin/security/mechanism" method="post" class="form-horizontal" id="mechanismSetting" role="form">
+      <form action="/_api/admin/security/mechanism" method="post" class="form-horizontal m-t-30" id="mechanismSetting" role="form">
         <fieldset>
         <fieldset>
-          <legend>{{ t('Selecting authentication mechanism') }}</legend>
+          <legend class="alert-anchor">{{ t('Selecting authentication mechanism') }}</legend>
           <p class="alert alert-info"><b>NOTE: </b>Restarting the server is needed if you switch the auth mechanism.</p>
           <p class="alert alert-info"><b>NOTE: </b>Restarting the server is needed if you switch the auth mechanism.</p>
           <div class="form-group">
           <div class="form-group">
             <div class="col-xs-6">
             <div class="col-xs-6">
@@ -145,7 +145,7 @@
       </form>
       </form>
 
 
 
 
-      <div class="auth-mechanism-configurations">
+      <div class="auth-mechanism-configurations m-t-10">
 
 
         <legend>{{ t('security_setting.Authentication mechanism settings') }}</legend>
         <legend>{{ t('security_setting.Authentication mechanism settings') }}</legend>
 
 
@@ -155,18 +155,18 @@
           <p class="alert alert-warning"
           <p class="alert alert-warning"
               {% if !isRestartingServerNeeded %}style="display: none;"{% endif %}>
               {% if !isRestartingServerNeeded %}style="display: none;"{% endif %}>
             <b>
             <b>
-              <i class="fa fa-exclamation-circle" aria-hidden="true"></i>
+              <i class="icon-exclamation" aria-hidden="true"></i>
               Restarting the server is needed.
               Restarting the server is needed.
             </b>
             </b>
             The server is running with Passport authentication mechanism.
             The server is running with Passport authentication mechanism.
           </p>
           </p>
 
 
-          <form action="/_api/admin/security/google" method="post" class="form-horizontal " id="googleSetting" role="form"
+          <form action="/_api/admin/security/google" method="post" class="form-horizontal" id="googleSetting" role="form"
               {% if isRestartingServerNeeded %}style="opacity: 0.4;"{% endif %}>
               {% if isRestartingServerNeeded %}style="opacity: 0.4;"{% endif %}>
 
 
             <fieldset>
             <fieldset>
               <h4>Google 設定</h4>
               <h4>Google 設定</h4>
-              <p class="well">
+              <p class="well alert-anchor">
                 Google Cloud Platform の <a href="https://console.cloud.google.com/apis/credentials">API Manager</a>
                 Google Cloud Platform の <a href="https://console.cloud.google.com/apis/credentials">API Manager</a>
                 から OAuth2 Client ID を作成すると、Google アカウントにコネクトして登録やログインが可能になります。
                 から OAuth2 Client ID を作成すると、Google アカウントにコネクトして登録やログインが可能になります。
               </p>
               </p>
@@ -217,30 +217,30 @@
           <p class="alert alert-warning"
           <p class="alert alert-warning"
               {% if !isRestartingServerNeeded %}style="display: none;"{% endif %}>
               {% if !isRestartingServerNeeded %}style="display: none;"{% endif %}>
             <b>
             <b>
-              <i class="fa fa-exclamation-circle" aria-hidden="true"></i>
+              <i class="icon-exclamation" aria-hidden="true"></i>
               Restarting the server is needed.
               Restarting the server is needed.
             </b>
             </b>
             The server is running with Official Crowi authentication mechanism.
             The server is running with Official Crowi authentication mechanism.
           </p>
           </p>
           <ul class="nav nav-tabs" role="tablist" {% if isRestartingServerNeeded %}style="opacity: 0.4;"{% endif %}>
           <ul class="nav nav-tabs" role="tablist" {% if isRestartingServerNeeded %}style="opacity: 0.4;"{% endif %}>
             <li class="active">
             <li class="active">
-              <a href="#passport-ldap" data-toggle="tab" role="tab"><i class="fa fa-sitemap"></i> LDAP</a>
+              <a href="#passport-ldap" data-toggle="tab" role="tab"><i class="icon-organization"></i> LDAP</a>
             </li>
             </li>
             <li>
             <li>
-              <a href="#passport-google-oauth" data-toggle="tab" role="tab"><i class="fa fa-google"></i> Google OAuth</a>
+              <a href="#passport-google-oauth" data-toggle="tab" role="tab"><i class="icon-social-google"></i> Google OAuth</a>
             </li>
             </li>
             <li>
             <li>
-              <a href="#passport-facebook" data-toggle="tab" role="tab"><i class="fa fa-facebook"></i> Facebook</a>
+              <a href="#passport-facebook" data-toggle="tab" role="tab"><i class="icon-social-facebook"></i> Facebook</a>
             </li>
             </li>
             <li>
             <li>
-              <a href="#passport-twitter" data-toggle="tab" role="tab"><i class="fa fa-twitter"></i> Twitter</a>
+              <a href="#passport-twitter" data-toggle="tab" role="tab"><i class="icon-social-twitter"></i> Twitter</a>
             </li>
             </li>
             <li>
             <li>
-              <a href="#passport-github" data-toggle="tab" role="tab"><i class="fa fa-github"></i> Github</a>
+              <a href="#passport-github" data-toggle="tab" role="tab"><i class="icon-social-github"></i> Github</a>
             </li>
             </li>
           </ul>
           </ul>
 
 
-          <div class="tab-content" {% if isRestartingServerNeeded %}style="opacity: 0.4;"{% endif %}>
+          <div class="tab-content p-t-10" {% if isRestartingServerNeeded %}style="opacity: 0.4;"{% endif %}>
             <div id="passport-ldap" class="tab-pane active" role="tabpanel" >
             <div id="passport-ldap" class="tab-pane active" role="tabpanel" >
               {% include './widget/passport/ldap.html' with { settingForm: settingForm } %}
               {% include './widget/passport/ldap.html' with { settingForm: settingForm } %}
             </div>
             </div>
@@ -282,7 +282,7 @@
           var $message = $('<p class="alert"></p>');
           var $message = $('<p class="alert"></p>');
           $message.addClass('alert-' + status);
           $message.addClass('alert-' + status);
           $message.html(msg.replace('\n', '<br>'));
           $message.html(msg.replace('\n', '<br>'));
-          $message.insertAfter('#' + formId + ' legend');
+          $message.insertAfter('#' + formId + ' .alert-anchor');
 
 
           if (status == 'success') {
           if (status == 'success') {
             setTimeout(function()
             setTimeout(function()

+ 31 - 25
lib/views/admin/user-group-detail.html

@@ -2,7 +2,7 @@
 
 
 {% block html_title %}グループ管理 · {% endblock %}
 {% block html_title %}グループ管理 · {% endblock %}
 
 
-{% block content_head %}
+{% block content_header %}
 <div class="header-wrap">
 <div class="header-wrap">
   <header id="page-header">
   <header id="page-header">
     <h1 class="title" id="">グループ管理(グループ詳細)</h1>
     <h1 class="title" id="">グループ管理(グループ詳細)</h1>
@@ -32,7 +32,10 @@
     </div>
     </div>
 
 
     <div class="col-md-9">
     <div class="col-md-9">
-          <a href="/admin/user-groups"><i class="fa fa-arrow-left"></i> グループ一覧に戻る</a>
+      <a href="/admin/user-groups" class="btn btn-default">
+        <i class="icon-fw ti-arrow-left" aria-hidden="true"></i>
+        グループ一覧に戻る
+      </a>
 
 
       <div class="modal fade" id="admin-add-user-group-relation-modal">
       <div class="modal fade" id="admin-add-user-group-relation-modal">
         <div class="modal-dialog">
         <div class="modal-dialog">
@@ -40,27 +43,27 @@
             <div class="modal-header">
             <div class="modal-header">
               <button type="button" class="close" data-dismiss="modal" aria-hidden="true">&times;</button>
               <button type="button" class="close" data-dismiss="modal" aria-hidden="true">&times;</button>
               <h4 class="modal-title">
               <h4 class="modal-title">
-                グループにユーザを追加します</h4>
+                グループへのユーザー追加
+              </h4>
             </div>
             </div>
 
 
             <div class="modal-body">
             <div class="modal-body">
               <p>
               <p>
-                ユーザ名を入力してください。
+                <strong>方法1.</strong> ユーザ名を入力して追加
               </p>
               </p>
               <form class="form-inline" role="form" action="/admin/user-group-relation/create" method="post">
               <form class="form-inline" role="form" action="/admin/user-group-relation/create" method="post">
                 <div class="form-group">
                 <div class="form-group">
-                  <label for="inputRelatedUserName">Add related user:</label>
                   <input type="text" name="user_name" class="form-control input-sm" id="inputRelatedUserName" placeholder="username">
                   <input type="text" name="user_name" class="form-control input-sm" id="inputRelatedUserName" placeholder="username">
                 </div>
                 </div>
                 <input type="hidden" name="user_group_id" value="{{userGroup.id}}">
                 <input type="hidden" name="user_group_id" value="{{userGroup.id}}">
                 <input type="hidden" name="_csrf" value="{{ csrf() }}">
                 <input type="hidden" name="_csrf" value="{{ csrf() }}">
-                <button type="submit" class="btn btn-sm btn-danger">実行</button>
+                <button type="submit" class="btn btn-sm btn-success">追加</button>
               </form>
               </form>
 
 
               {% if 0 < notRelatedusers.length %}
               {% if 0 < notRelatedusers.length %}
               <hr>
               <hr>
               <p>
               <p>
-                ユーザ名を選択してください。
+                <strong>方法2.</strong> ユーザーを下のリストから選択
               </p>
               </p>
 
 
               <ul class="list-inline">
               <ul class="list-inline">
@@ -85,7 +88,7 @@
         <!-- /.modal-dialog -->
         <!-- /.modal-dialog -->
       </div>
       </div>
 
 
-      <div class="form-box">
+      <div class="m-t-20 form-box">
         <form action="/admin/user-group/{{userGroup.id}}/update" method="post" class="form-horizontal" role="form">
         <form action="/admin/user-group/{{userGroup.id}}/update" method="post" class="form-horizontal" role="form">
           <fieldset>
           <fieldset>
             <legend>基本情報</legend>
             <legend>基本情報</legend>
@@ -111,7 +114,7 @@
         </form>
         </form>
       </div>
       </div>
 
 
-      <div class="form-box">
+      <div class="m-t-20 form-box">
         <fieldset>
         <fieldset>
           <legend>グループ画像の設定</legend>
           <legend>グループ画像の設定</legend>
           <div class="form-group col-sm-8">
           <div class="form-group col-sm-8">
@@ -125,7 +128,7 @@
               </label>
               </label>
               <div class="col-sm-8">
               <div class="col-sm-8">
                 <p>
                 <p>
-                  <img src="{{ userGroup|uploadedpicture }}" width="64" id="settingUserPicture">
+                  <img src="{{ userGroup|uploadedpicture }}" id="settingUserPicture" class="picture picture-lg img-circle">
                   <br>
                   <br>
                 </p>
                 </p>
                 <p>
                 <p>
@@ -160,9 +163,9 @@
         </fieldset>
         </fieldset>
       </div><!-- /.form-box -->
       </div><!-- /.form-box -->
 
 
-      <legend>ユーザー一覧</legend>
+      <legend class="m-t-20">ユーザー一覧</legend>
 
 
-      <table class="table table-hover table-striped table-bordered table-user-list">
+      <table class="table table-bordered table-user-list">
         <thead>
         <thead>
           <tr>
           <tr>
             <th width="100px">#</th>
             <th width="100px">#</th>
@@ -172,7 +175,7 @@
             <th>名前</th>
             <th>名前</th>
             <th width="100px">作成日</th>
             <th width="100px">作成日</th>
             <th width="150px">最終ログイン</th>
             <th width="150px">最終ログイン</th>
-            <th width="90px">操作</th>
+            <th width="70px"></th>
           </tr>
           </tr>
         </thead>
         </thead>
         <tbody>
         <tbody>
@@ -180,7 +183,7 @@
           {% set sUser = sRelation.relatedUser%}
           {% set sUser = sRelation.relatedUser%}
           <tr>
           <tr>
             <td>
             <td>
-              <img src="{{ sRelation.relatedUser|picture }}" class="picture picture-rounded" />
+              <img src="{{ sRelation.relatedUser|picture }}" class="picture img-circle" />
             </td>
             </td>
             <td>
             <td>
               <strong>{{ sRelation.relatedUser.username }}</strong>
               <strong>{{ sRelation.relatedUser.username }}</strong>
@@ -193,17 +196,16 @@
             <td>
             <td>
               <div class="btn-group admin-user-menu">
               <div class="btn-group admin-user-menu">
                 <button type="button" class="btn btn-default btn-sm dropdown-toggle" data-toggle="dropdown">
                 <button type="button" class="btn btn-default btn-sm dropdown-toggle" data-toggle="dropdown">
-                  編集
-                  <span class="caret"></span>
+                  <i class="icon-settings"></i> <span class="caret"></span>
                 </button>
                 </button>
                 <ul class="dropdown-menu" role="menu">
                 <ul class="dropdown-menu" role="menu">
-                  <li class="dropdown-header">編集メニュー</li>
-                  <li class="divider"></li>
-                  <li class="dropdown-button">
-                    <form action="/admin/user-group-relation/{{userGroup.name}}/remove-relation/{{ sRelation._id.toString() }}" method="post">
-                      <input type="hidden" name="_csrf" value="{{ csrf() }}">
-                      <button type="submit" class="btn btn-block btn-danger">グループから外す</button>
-                    </form>
+                  <form id="form_removeFromGroup_{{ sUser.id }}" action="/admin/user-group-relation/{{userGroup.name}}/remove-relation/{{ sRelation._id.toString() }}" method="post">
+                    <input type="hidden" name="_csrf" value="{{ csrf() }}">
+                  </form>
+                  <li>
+                    <a href="javascript:form_removeFromGroup_{{ sUser.id }}.submit()">
+                      <i class="icon-fw icon-user-unfollow"></i> グループから外す
+                    </a>
                   </li>
                   </li>
                 </ul>
                 </ul>
               </div>
               </div>
@@ -214,7 +216,11 @@
           {% if 0 < notRelatedusers.length %}
           {% if 0 < notRelatedusers.length %}
           <tr>
           <tr>
             <td></td>
             <td></td>
-            <td><button type="button" class="btn btn-primary" data-target="#admin-add-user-group-relation-modal" data-toggle="modal"><i class="fa fa-plus"></i></button></td>
+            <td class="text-center">
+              <button class="btn btn-default" data-target="#admin-add-user-group-relation-modal" data-toggle="modal">
+                <i class="ti-plus"></i>
+              </button>
+            </td>
             <td></td>
             <td></td>
             <td></td>
             <td></td>
             <td></td>
             <td></td>
@@ -226,7 +232,7 @@
 
 
       <!-- {% include '../widget/pager.html' with {path: "/admin/user-group-detail", pager: pager} %} -->
       <!-- {% include '../widget/pager.html' with {path: "/admin/user-group-detail", pager: pager} %} -->
 
 
-      <legend>ページ一覧</legend>
+      <legend class="m-t-20">ページ一覧</legend>
 
 
       {% if pageGroupRelations.length == 0 %}<p>グループが閲覧権限を保有するページはありません</p>{% endif %}
       {% if pageGroupRelations.length == 0 %}<p>グループが閲覧権限を保有するページはありません</p>{% endif %}
       {% include '../widget/page_list.html' with { pages: pageGroupRelations, pagePropertyName: 'targetPage' } %}
       {% include '../widget/page_list.html' with { pages: pageGroupRelations, pagePropertyName: 'targetPage' } %}

+ 31 - 27
lib/views/admin/user-groups.html

@@ -2,7 +2,7 @@
 
 
 {% block html_title %}グループ管理 · {% endblock %}
 {% block html_title %}グループ管理 · {% endblock %}
 
 
-{% block content_head %}
+{% block content_header %}
 <div class="header-wrap">
 <div class="header-wrap">
   <header id="page-header">
   <header id="page-header">
     <h1 class="title" id="">グループ管理</h1>
     <h1 class="title" id="">グループ管理</h1>
@@ -73,24 +73,30 @@
       <div class="modal fade" id="admin-delete-user-group-modal">
       <div class="modal fade" id="admin-delete-user-group-modal">
         <div class="modal-dialog">
         <div class="modal-dialog">
           <div class="modal-content">
           <div class="modal-content">
-            <div class="modal-header">
+            <div class="modal-header bg-danger">
               <button type="button" class="close" data-dismiss="modal" aria-hidden="true">&times;</button>
               <button type="button" class="close" data-dismiss="modal" aria-hidden="true">&times;</button>
-              <h4 class="modal-title"><code id="admin-delete-user-group-name"></code>グループを削除しますか?</h4>
+              <div class="modal-title">
+                <i class="icon icon-fire"></i> グループの削除
+              </div>
             </div>
             </div>
 
 
             <div class="modal-body">
             <div class="modal-body">
-              <p>
+              <dl>
+                <dt>グループ名</dt>
+                <dd><span id="admin-delete-user-group-name"></span></dd>
+              </dl>
+              <span class="text-danger">
                 グループの削除を行うと元に戻すことはできませんのでご注意ください。
                 グループの削除を行うと元に戻すことはできませんのでご注意ください。
-              </p>
-
-              <form action="/admin/user-group.remove" method="post" id="admin-user-groups-delete">
+              </span>
+            </div>
+            <div class="modal-footer">
+              <form action="/admin/user-group.remove" method="post" id="admin-user-groups-delete" class="text-right">
                 <input type="hidden" name="user_group_id" value="">
                 <input type="hidden" name="user_group_id" value="">
                 <input type="hidden" name="_csrf" value="{{ csrf() }}">
                 <input type="hidden" name="_csrf" value="{{ csrf() }}">
-                <button type="submit" value="" class="btn btn-danger">
-                  実行
+                <button type="submit" value="" class="btn btn-sm btn-danger">
+                  <i class="icon icon-fire"></i> 削除
                 </button>
                 </button>
               </form>
               </form>
-
             </div>
             </div>
 
 
           </div>
           </div>
@@ -101,21 +107,21 @@
 
 
       <h2>グループ一覧</h2>
       <h2>グループ一覧</h2>
 
 
-      <table class="table table-hover table-striped table-bordered table-user-list">
+      <table class="table table-bordered table-user-list">
         <thead>
         <thead>
           <tr>
           <tr>
             <th width="100px">#</th>
             <th width="100px">#</th>
-            <th>名前</th>
+            <th>{{ t('Name') }}</th>
             <th>ユーザ一覧</th>
             <th>ユーザ一覧</th>
             <th width="100px">作成日</th>
             <th width="100px">作成日</th>
-            <th width="90px">操作</th>
+            <th width="70px"></th>
           </tr>
           </tr>
         </thead>
         </thead>
         <tbody>
         <tbody>
           {% for sGroup in userGroups %}
           {% for sGroup in userGroups %}
           <tr>
           <tr>
             <td>
             <td>
-              <img src="{{ sGroup|picture }}" class="picture picture-rounded" />
+              <img src="{{ sGroup|picture }}" class="picture img-circle" />
             </td>
             </td>
             <td>{{ sGroup.name }}</td>
             <td>{{ sGroup.name }}</td>
             <td><ul class="list-inline">
             <td><ul class="list-inline">
@@ -127,24 +133,22 @@
             <td>
             <td>
               <div class="btn-group admin-group-menu">
               <div class="btn-group admin-group-menu">
                 <button type="button" class="btn btn-default btn-sm dropdown-toggle" data-toggle="dropdown">
                 <button type="button" class="btn btn-default btn-sm dropdown-toggle" data-toggle="dropdown">
-                  操作
-                  <span class="caret"></span>
+                  <i class="icon-settings"></i> <span class="caret"></span>
                 </button>
                 </button>
                 <ul class="dropdown-menu" role="menu">
                 <ul class="dropdown-menu" role="menu">
-                  <li class="dropdown-header">メニュー</li>
-                  <li class="divider"></li>
-
-                  <li class="dropdown-button">
-                    <a href="/admin/user-group-detail/{{sGroup.name}}" class="btn btn-block btn-default">詳細</a>
+                  <li>
+                    <a href="/admin/user-group-detail/{{sGroup.name}}">
+                      <i class="icon-fw icon-note"></i> 編集
+                    </a>
                   </li>
                   </li>
 
 
-                  <li class="dropdown-button">
+                  <li>
                     <a href="#"
                     <a href="#"
-                      data-user-group-id="{{ sGroup._id.toString() }}"
-                      data-user-group-name="{{ sGroup.name.toString() }}"
-                      data-target="#admin-delete-user-group-modal"
-                      data-toggle="modal" class="btn btn-block btn-danger">
-                      グループの削除
+                        data-user-group-id="{{ sGroup._id.toString() }}"
+                        data-user-group-name="{{ sGroup.name.toString() }}"
+                        data-target="#admin-delete-user-group-modal"
+                        data-toggle="modal">
+                      <i class="icon-fw icon-fire text-danger"></i> 削除する
                     </a>
                     </a>
                   </li>
                   </li>
 
 

+ 85 - 63
lib/views/admin/users.html

@@ -2,7 +2,7 @@
 
 
 {% block html_title %}{{ t('user_management.User management') }}· {% endblock %}
 {% block html_title %}{{ t('user_management.User management') }}· {% endblock %}
 
 
-{% block content_head %}
+{% block content_header %}
 <div class="header-wrap">
 <div class="header-wrap">
   <header id="page-header">
   <header id="page-header">
     <h1 class="title" id="">{{ t('user_management.User management') }}</h1>
     <h1 class="title" id="">{{ t('user_management.User management') }}</h1>
@@ -33,9 +33,11 @@
 
 
     <div class="col-md-9">
     <div class="col-md-9">
       <p>
       <p>
-        <button data-toggle="collapse" class="btn btn-default" href="#inviteUserForm">{{ t("user_management.invite_users") }}</button>
-        <a class="btn btn-default" href="/admin/users/external-accounts">
-          <i class="fa fa-user-plus" aria-hidden="true"></i>
+        <button data-toggle="collapse" class="btn btn-default" href="#inviteUserForm">
+          {{ t("user_management.invite_users") }}
+        </button>
+        <a class="btn btn-default btn-outline" href="/admin/users/external-accounts">
+          <i class="icon-user-follow" aria-hidden="true"></i>
           {{ t("user_management.external_account") }}
           {{ t("user_management.external_account") }}
         </a>
         </a>
       </p>
       </p>
@@ -63,7 +65,7 @@
 
 
             <div class="modal-header">
             <div class="modal-header">
               <button type="button" class="close" data-dismiss="modal" aria-hidden="true">&times;</button>
               <button type="button" class="close" data-dismiss="modal" aria-hidden="true">&times;</button>
-              <h4 class="modal-title">ユーザーを招待しました</h4>
+              <div class="modal-title">ユーザーを招待しました</div>
             </div>
             </div>
 
 
             <div class="modal-body">
             <div class="modal-body">
@@ -86,7 +88,7 @@
           <div class="modal-content">
           <div class="modal-content">
             <div class="modal-header">
             <div class="modal-header">
               <button type="button" class="close" data-dismiss="modal" aria-hidden="true">&times;</button>
               <button type="button" class="close" data-dismiss="modal" aria-hidden="true">&times;</button>
-              <h4 class="modal-title">パスワードを新規発行しますか?</h4>
+              <div class="modal-title">パスワードを新規発行しますか?</div>
             </div>
             </div>
 
 
             <div class="modal-body">
             <div class="modal-body">
@@ -117,7 +119,7 @@
 
 
             <div class="modal-header">
             <div class="modal-header">
               <button type="button" class="close" data-dismiss="modal" aria-hidden="true">&times;</button>
               <button type="button" class="close" data-dismiss="modal" aria-hidden="true">&times;</button>
-              <h4 class="modal-title">Password reset!</h4>
+              <div class="modal-title">Password reset!</div>
             </div>
             </div>
 
 
             <div class="modal-body">
             <div class="modal-body">
@@ -138,7 +140,7 @@
 
 
       <h2>{{ t("user_management.user_list") }}</h2>
       <h2>{{ t("user_management.user_list") }}</h2>
 
 
-      <table class="table table-hover table-striped table-bordered table-user-list">
+      <table class="table table-default table-bordered table-user-list">
         <thead>
         <thead>
           <tr>
           <tr>
             <th width="100px">#</th>
             <th width="100px">#</th>
@@ -148,16 +150,17 @@
             <th>{{ t('Email') }}</th>
             <th>{{ t('Email') }}</th>
             <th width="100px">{{ t('user_management.Date created') }}</th>
             <th width="100px">{{ t('user_management.Date created') }}</th>
             <th width="150px">{{ t('user_management.Last login') }}</th>
             <th width="150px">{{ t('user_management.Last login') }}</th>
-            <th width="90px">{{ t('user_management.Manage') }}</th>
+            <th width="70px"></th>
           </tr>
           </tr>
         </thead>
         </thead>
         <tbody>
         <tbody>
           {% for sUser in users %}
           {% for sUser in users %}
+          {% set sUserId = sUser._id.toString() %}
           <tr>
           <tr>
             <td>
             <td>
-              <img src="{{ sUser|picture }}" class="picture picture-rounded" />
+              <img src="{{ sUser|picture }}" class="picture img-circle" />
               {% if sUser.admin %}
               {% if sUser.admin %}
-              <span class="label label-primary label-admin">
+              <span class="label label-inverse label-admin">
                 Admin
                 Admin
               </span>
               </span>
               {% endif %}
               {% endif %}
@@ -180,22 +183,18 @@
             </td>
             </td>
             <td>
             <td>
               <div class="btn-group admin-user-menu">
               <div class="btn-group admin-user-menu">
-                <button type="button" class="btn btn-default btn-sm dropdown-toggle" data-toggle="dropdown">
-                  {{ t('Edit') }}
-                  <span class="caret"></span>
+                <button type="button" class="btn btn-sm btn-default dropdown-toggle" data-toggle="dropdown">
+                  <i class="icon-settings"></i> <span class="caret"></span>
                 </button>
                 </button>
                 <ul class="dropdown-menu" role="menu">
                 <ul class="dropdown-menu" role="menu">
                   <li class="dropdown-header">{{ t('user_management.Edit menu') }}</li>
                   <li class="dropdown-header">{{ t('user_management.Edit menu') }}</li>
                   <li>
                   <li>
-                    <a href="">{{ t('Edit') }}</a>
-
-                  </li>
-                  <li class="dropdown-button">
                     <a href="#"
                     <a href="#"
-                      data-user-id="{{ sUser._id.toString() }}"
-                      data-user-email="{{ sUser.email }}"
-                      data-target="#admin-password-reset-modal"
-                      data-toggle="modal" class="btn btn-block btn-default">
+                        data-user-id="{{ sUserId }}"
+                        data-user-email="{{ sUser.email }}"
+                        data-target="#admin-password-reset-modal"
+                        data-toggle="modal">
+                      <i class="icon-fw icon-key"></i>
                       {{ t('user_management.Reissue password') }}
                       {{ t('user_management.Reissue password') }}
                     </a>
                     </a>
                   </li>
                   </li>
@@ -203,52 +202,65 @@
                   <li class="dropdown-header">{{ t('user_management.Status') }}</li>
                   <li class="dropdown-header">{{ t('user_management.Status') }}</li>
 
 
                   {% if sUser.status == 1 %}
                   {% if sUser.status == 1 %}
-                  <li class="dropdown-button">
-                    <form action="/admin/user/{{ sUser._id.toString() }}/activate" method="post">
-                      <input type="hidden" name="_csrf" value="{{ csrf() }}">
-                      <button type="submit" class="btn btn-block btn-info">承認する</button>
-                    </form>
+                  <form id="form_activate_{{ sUserId }}" action="/admin/user/{{ sUserId }}/activate" method="post">
+                    <input type="hidden" name="_csrf" value="{{ csrf() }}">
+                  </form>
+                  <li>
+                    <a href="javascript:form_activate_{{ sUserId }}.submit()">
+                      <i class="icon-fw icon-user-following"></i> 承認する
+                    </a>
                   </li>
                   </li>
                   {% endif  %}
                   {% endif  %}
 
 
                   {% if sUser.status == 2 %}
                   {% if sUser.status == 2 %}
-                  <li class="dropdown-button">
+                  <form id="form_suspend_{{ sUserId }}" action="/admin/user/{{ sUserId }}/suspend" method="post">
+                    <input type="hidden" name="_csrf" value="{{ csrf() }}">
+                  </form>
+                  <li>
                     {% if sUser.username != user.username %}
                     {% if sUser.username != user.username %}
-                    <form action="/admin/user/{{ sUser._id.toString() }}/suspend" method="post">
-                      <input type="hidden" name="_csrf" value="{{ csrf() }}">
-                      <button type="submit" class="btn btn-block btn-warning">{{ t('user_management.Deactivate account') }}</button>
-                    </form>
+                    <a href="javascript:form_suspend_{{ sUserId }}.submit()">
+                      <i class="icon-fw icon-ban"></i>
+                      {{ t('user_management.Deactivate account') }}
+                    </a>
                     {% else %}
                     {% else %}
-                    <button class="btn btn-block btn-warning" disabled>{{ t('user_management.Deactivate account') }}</button>
-                    <br>
-                    <p class="alert alert-danger">{{ t("user_management.your_own") }}</p>
+                    <a disabled>
+                      <i class="icon-fw icon-ban"></i>
+                      {{ t('user_management.Deactivate account') }}
+                    </a>
+                    <p class="alert alert-danger m-l-10 m-r-10 p-10">{{ t("user_management.your_own") }}</p>
                     {% endif %}
                     {% endif %}
                   </li>
                   </li>
                   {% endif %}
                   {% endif %}
 
 
                   {% if sUser.status == 3 %}
                   {% if sUser.status == 3 %}
-                  <li class="dropdown-button">
-                    <form action="/admin/user/{{ sUser._id.toString() }}/activate" method="post">
-                      <input type="hidden" name="_csrf" value="{{ csrf() }}">
-                      <button type="submit" class="btn btn-block btn-default">元に戻す</button>
-                    </form>
+                  <form id="form_activate_{{ sUserId }}" action="/admin/user/{{ sUserId }}/activate" method="post">
+                    <input type="hidden" name="_csrf" value="{{ csrf() }}">
+                  </form>
+                  <form id="form_remove_{{ sUserId }}" action="/admin/user/{{ sUserId }}/remove" method="post">
+                    <input type="hidden" name="_csrf" value="{{ csrf() }}">
+                  </form>
+                  <li>
+                    <a href="javascript:form_activate_{{ sUserId }}.submit()">
+                      <i class="icon-fw icon-action-redo"></i> 元に戻す
+                    </a>
                   </li>
                   </li>
-                  <li class="dropdown-button">
+                  <li>
                     {# label は同じだけど、こっちは論理削除 #}
                     {# label は同じだけど、こっちは論理削除 #}
-                    <form action="/admin/user/{{ sUser._id.toString() }}/remove" method="post">
-                      <input type="hidden" name="_csrf" value="{{ csrf() }}">
-                      <button type="submit" class="btn btn-block btn-danger">削除する</button>
-                    </form>
+                    <a href="javascript:form_remove_{{ sUserId }}.submit()">
+                      <i class="icon-fw icon-fire text-danger"></i> 削除する
+                    </a>
                   </li>
                   </li>
                   {% endif  %}
                   {% endif  %}
 
 
                   {% if sUser.status == 1 || sUser.status == 5 %}
                   {% if sUser.status == 1 || sUser.status == 5 %}
+                  <form id="form_removeCompletely_{{ sUserId }}" action="/admin/user/{{ sUser._id.toString() }}/removeCompletely" method="post">
+                    <input type="hidden" name="_csrf" value="{{ csrf() }}">
+                  </form>
                   <li class="dropdown-button">
                   <li class="dropdown-button">
                     {# label は同じだけど、こっちは物理削除 #}
                     {# label は同じだけど、こっちは物理削除 #}
-                    <form action="/admin/user/{{ sUser._id.toString() }}/removeCompletely" method="post">
-                      <input type="hidden" name="_csrf" value="{{ csrf() }}">
-                      <button type="submit" class="btn btn-block btn-danger">削除する</button>
-                    </form>
+                    <a href="javascript:form_removeCompletely_{{ sUserId }}.submit()">
+                      <i class="icon-fw icon-fire text-danger"></i> 削除する
+                    </a>
                   </li>
                   </li>
                   {% endif  %}
                   {% endif  %}
 
 
@@ -256,23 +268,33 @@
                   <li class="divider"></li>
                   <li class="divider"></li>
                   <li class="dropdown-header">{{ t('user_management.Administrator menu') }}</li>
                   <li class="dropdown-header">{{ t('user_management.Administrator menu') }}</li>
 
 
-                  <li class="dropdown-button">
-                    {% if sUser.admin %}
-                      {% if sUser.username != user.username %}
-                      <form action="/admin/user/{{ sUser._id.toString() }}/removeFromAdmin" method="post">
-                        <input type="hidden" name="_csrf" value="{{ csrf() }}">
-                        <button type="submit" class="btn btn-block btn-danger">管理者からはずす</button>
-                      </form>
-                      {% else %}
-                      <p class="alert alert-danger">{{ t("user_management.cannot_remove") }}</p>
-                      {% endif %}
+                  {% if sUser.admin %}
+                  <form id="form_removeFromAdmin_{{ sUserId }}" action="/admin/user/{{ sUser._id.toString() }}/removeFromAdmin" method="post">
+                    <input type="hidden" name="_csrf" value="{{ csrf() }}">
+                  </form>
+                  <li>
+                    {% if sUser.username != user.username %}
+                      <a href="javascript:form_removeFromAdmin_{{ sUserId }}.submit()">
+                        <i class="icon-fw icon-user-unfollow"></i> 管理者からはずす
+                      </a>
                     {% else %}
                     {% else %}
-                      <form action="/admin/user/{{ sUser._id.toString() }}/makeAdmin" method="post">
-                        <input type="hidden" name="_csrf" value="{{ csrf() }}">
-                        <button type="submit" class="btn btn-block btn-primary">管理者にする</button>
-                      </form>
+                      <a disabled>
+                        <i class="icon-fw icon-user-unfollow"></i> 管理者からはずす
+                      </a>
+                      <p class="alert alert-danger m-l-10 m-r-10 p-10">{{ t("user_management.cannot_remove") }}</p>
                     {% endif %}
                     {% endif %}
                   </li>
                   </li>
+                  {% else %}
+                  <form id="form_makeAdmin_{{ sUserId }}" action="/admin/user/{{ sUser._id.toString() }}/makeAdmin" method="post">
+                    <input type="hidden" name="_csrf" value="{{ csrf() }}">
+                  </form>
+                  <li>
+                    <a href="javascript:form_makeAdmin_{{ sUserId }}.submit()">
+                      <i class="icon-fw icon-magic-wand"></i> 管理者にする
+                    </a>
+                  </li>
+                  {% endif %}
+
                   {% endif %}
                   {% endif %}
                 </ul>
                 </ul>
               </div>
               </div>

+ 9 - 9
lib/views/admin/widget/menu.html

@@ -2,15 +2,15 @@
   {% set current = 'index' %}
   {% set current = 'index' %}
 {% endif  %}
 {% endif  %}
 <ul class="nav nav-pills nav-stacked">
 <ul class="nav nav-pills nav-stacked">
-  <li class="{% if current == 'index'%}active{% endif %}"><a href="/admin"><i class="fa fa-cube"></i> {{ t('Management Wiki Home') }}</a></li>
-  <li class="{% if current == 'app'%}active{% endif %}"><a href="/admin/app"><i class="fa fa-gears"></i>{{ t('App settings') }}</a></li>
-  <li class="{% if current == 'security'%}active{% endif %}"><a href="/admin/security"><i class="fa fa-shield"></i> {{ t('Security settings') }}</a></li>
-  <li class="{% if current == 'markdown'%}active{% endif %}"><a href="/admin/markdown"><i class="fa fa-pencil"></i> {{ t('Markdown settings') }}</a></li>
-  <li class="{% if current == 'customize'%}active{% endif %}"><a href="/admin/customize"><i class="fa fa-object-group"></i> {{ t('Customize') }}</a></li>
-  <li class="{% if current == 'notification'%}active{% endif %}"><a href="/admin/notification"><i class="fa fa-bell"></i> {{ t('Notification settings') }}</a></li>
-  <li class="{% if current == 'user' || current == 'external-account' %}active{% endif %}"><a href="/admin/users"><i class="fa fa-users"></i> {{ t('User management') }}</a></li>
-  <li class="{% if current == 'user-group'%}active{% endif %}"><a href="/admin/user-groups"><i class="fa fa-users"></i> {{ t('UserGroup management') }}</a></li>
+  <li class="{% if current == 'index'%}active{% endif %}"><a href="/admin"><i class="icon-fw icon-home"></i> {{ t('Management Wiki Home') }}</a></li>
+  <li class="{% if current == 'app'%}active{% endif %}"><a href="/admin/app"><i class="icon-fw icon-settings"></i> {{ t('App settings') }}</a></li>
+  <li class="{% if current == 'security'%}active{% endif %}"><a href="/admin/security"><i class="icon-fw icon-shield"></i> {{ t('Security settings') }}</a></li>
+  <li class="{% if current == 'markdown'%}active{% endif %}"><a href="/admin/markdown"><i class="icon-fw icon-note"></i> {{ t('Markdown settings') }}</a></li>
+  <li class="{% if current == 'customize'%}active{% endif %}"><a href="/admin/customize"><i class="icon-fw icon-wrench"></i> {{ t('Customize') }}</a></li>
+  <li class="{% if current == 'notification'%}active{% endif %}"><a href="/admin/notification"><i class="icon-fw icon-bell"></i> {{ t('Notification settings') }}</a></li>
+  <li class="{% if current == 'user' || current == 'external-account' %}active{% endif %}"><a href="/admin/users"><i class="icon-fw icon-user"></i> {{ t('User management') }}</a></li>
+  <li class="{% if current == 'user-group'%}active{% endif %}"><a href="/admin/user-groups"><i class="icon-fw icon-people"></i> {{ t('UserGroup management') }}</a></li>
   {% if searchConfigured() %}
   {% if searchConfigured() %}
-  <li class="{% if current == 'search'%}active{% endif %}"><a href="/admin/search"><i class="fa fa-search"></i> 検索管理</a></li>
+  <li class="{% if current == 'search'%}active{% endif %}"><a href="/admin/search"><i class="icon-fw icon-magnifier"></i> 検索管理</a></li>
   {% endif %}
   {% endif %}
 </ul>
 </ul>

+ 7 - 7
lib/views/admin/widget/passport/ldap.html

@@ -9,13 +9,13 @@
       <label for="{{nameForIsLdapEnabled}}" class="col-xs-3 control-label">Use LDAP</label>
       <label for="{{nameForIsLdapEnabled}}" class="col-xs-3 control-label">Use LDAP</label>
       <div class="col-xs-6">
       <div class="col-xs-6">
         <div class="btn-group btn-toggle" data-toggle="buttons">
         <div class="btn-group btn-toggle" data-toggle="buttons">
-          <label class="btn btn-default {% if isLdapEnabled %}active{% endif %}" data-active-class="primary">
+          <label class="btn btn-default btn-rounded btn-outline {% if isLdapEnabled %}active{% endif %}" data-active-class="primary">
             <input name="{{nameForIsLdapEnabled}}" value="true" type="radio"
             <input name="{{nameForIsLdapEnabled}}" value="true" type="radio"
-                {% if true === isLdapEnabled %}checked{% endif %}> Enable
+                {% if true === isLdapEnabled %}checked{% endif %}> ON
           </label>
           </label>
-          <label class="btn btn-default {% if !isLdapEnabled %}active{% endif %}" data-active-class="primary">
+          <label class="btn btn-default btn-rounded btn-outline {% if !isLdapEnabled %}active{% endif %}" data-active-class="default">
             <input name="{{nameForIsLdapEnabled}}" value="false" type="radio"
             <input name="{{nameForIsLdapEnabled}}" value="false" type="radio"
-                {% if !isLdapEnabled %}checked{% endif %}> Disable
+                {% if !isLdapEnabled %}checked{% endif %}> OFF
           </label>
           </label>
         </div>
         </div>
       </div>
       </div>
@@ -43,11 +43,11 @@
         <label for="{{nameForIsUserBind}}" class="col-xs-3 control-label">Binding Mode</label>
         <label for="{{nameForIsUserBind}}" class="col-xs-3 control-label">Binding Mode</label>
         <div class="col-xs-6">
         <div class="col-xs-6">
           <div class="btn-group btn-toggle" data-toggle="buttons">
           <div class="btn-group btn-toggle" data-toggle="buttons">
-            <label class="btn btn-default {% if !isUserBind %}active{% endif %}" data-active-class="primary">
+            <label class="btn btn-default btn-rounded btn-outline {% if !isUserBind %}active{% endif %}" data-active-class="primary">
               <input name="{{nameForIsUserBind}}" value="false" type="radio"
               <input name="{{nameForIsUserBind}}" value="false" type="radio"
                   {% if !isUserBind %}checked{% endif %}> Manager Bind
                   {% if !isUserBind %}checked{% endif %}> Manager Bind
             </label>
             </label>
-            <label class="btn btn-default {% if isUserBind %}active{% endif %}" data-active-class="primary">
+            <label class="btn btn-default btn-rounded btn-outline {% if isUserBind %}active{% endif %}" data-active-class="primary">
               <input name="{{nameForIsUserBind}}" value="true" type="radio"
               <input name="{{nameForIsUserBind}}" value="true" type="radio"
                   {% if isUserBind %}checked{% endif %}> User Bind
                   {% if isUserBind %}checked{% endif %}> User Bind
             </label>
             </label>
@@ -284,7 +284,7 @@
 
 
       <div class="modal-header">
       <div class="modal-header">
         <button type="button" class="close" data-dismiss="modal" aria-hidden="true">&times;</button>
         <button type="button" class="close" data-dismiss="modal" aria-hidden="true">&times;</button>
-        <h4 class="modal-title">{{ t('Test LDAP Account') }}</h4>
+        <div class="modal-title">{{ t('Test LDAP Account') }}</div>
       </div>
       </div>
 
 
       <div class="modal-body">
       <div class="modal-body">

+ 7 - 0
lib/views/admin/widget/theme-colorbox.html

@@ -0,0 +1,7 @@
+<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 64 64" width="64" height="64">
+  <g>
+    <path class="color1" d="M -1 -1 L65 -1 L65 65 L-1 65 L-1 -1 Z" fill="#ccc"></path>
+    <path class="color2" d="M -1 -1 L65 -1 L65 15 L-1 15 L-1 -1 Z" fill="#000"></path>
+    <path class="color3" d="M 44 15 L65 15 L65 65 L44 65 L44 15 Z" fill="#300"></path>
+  </g>
+</svg>

+ 0 - 48
lib/views/crowi-plus/base/not_found_nosidebar.html

@@ -1,48 +0,0 @@
-{% extends '../../not_found.html' %}
-
-
-{% block layout_sidebar %}
-{% endblock %}
-
-
-{% block layout_main %}
-<div id="main" class="main col-md-12 {% if page %}{{ css.grant(page) }}{% endif %} {% block main_css_class %}{% endblock %}">
-  {% if page && page.grant != 1 %}
-  <p class="page-grant">
-    <i class="fa fa-lock"></i> {{ consts.pageGrants[page.grant] }} ({{ t('Browsing of this page is restricted') }})
-  </p>
-  {% endif %}
-  {% if page && page.grant == 2 %}
-  <p class="alert alert-info">
-    {{ t('Shareable Link') }}
-    <input type="text" class="copy-link form-control" value="{{ baseUrl }}/{{ page._id.toString() }}" readonly>
-  </p>
-  {% endif %}
-  <article>
-    {% block content_head %}
-      {% parent %}
-    {% endblock %}
-
-    {% block content_main_before %}
-    {% endblock %}
-
-    {% block content_main %}
-      {% parent %}
-    {% endblock content_main %}
-
-    {% block content_main_after %}
-    {% endblock %}
-
-    {% block content_footer %}
-      {% parent %}
-    {% endblock %}
-  </article>
-</div>
-
-{% endblock %} {# layout_main #}
-
-
-{% block footer %}
-  {% parent %}
-  {% include '../widget/system-version.html' %}
-{% endblock %}

+ 0 - 48
lib/views/crowi-plus/base/page_list_nosidebar.html

@@ -1,48 +0,0 @@
-{% extends '../../page_list.html' %}
-
-
-{% block layout_sidebar %}
-{% endblock %}
-
-
-{% block layout_main %}
-<div id="main" class="main col-md-12 {% if page %}{{ css.grant(page) }}{% endif %} {% block main_css_class %}{% endblock %}">
-  {% if page && page.grant != 1 %}
-  <p class="page-grant">
-    <i class="fa fa-lock"></i> {{ consts.pageGrants[page.grant] }} ({{ t('Browsing of this page is restricted') }})
-  </p>
-  {% endif %}
-  {% if page && page.grant == 2 %}
-  <p class="alert alert-info">
-    {{ t('Shareable Link') }}
-    <input type="text" class="copy-link form-control" value="{{ baseUrl }}/{{ page._id.toString() }}" readonly>
-  </p>
-  {% endif %}
-  <article>
-    {% block content_head %}
-      {% parent %}
-    {% endblock %}
-
-    {% block content_main_before %}
-    {% endblock %}
-
-    {% block content_main %}
-      {% parent %}
-    {% endblock content_main %}
-
-    {% block content_main_after %}
-    {% endblock %}
-
-    {% block content_footer %}
-      {% parent %}
-    {% endblock %}
-  </article>
-</div>
-
-{% endblock %} {# layout_main #}
-
-
-{% block footer %}
-  {% parent %}
-  {% include '../widget/system-version.html' %}
-{% endblock %}

+ 0 - 48
lib/views/crowi-plus/base/page_nosidebar.html

@@ -1,48 +0,0 @@
-{% extends '../../page.html' %}
-
-
-{% block layout_sidebar %}
-{% endblock %}
-
-
-{% block layout_main %}
-<div id="main" class="main col-md-12 {% if page %}{{ css.grant(page) }}{% endif %} {% block main_css_class %}{% endblock %}">
-  {% if page && page.grant != 1 %}
-  <p class="page-grant">
-    <i class="fa fa-lock"></i> {{ consts.pageGrants[page.grant] }} ({{ t('Browsing of this page is restricted') }})
-  </p>
-  {% endif %}
-  {% if page && page.grant == 2 %}
-  <p class="alert alert-info">
-    {{ t('Shareable Link') }}
-    <input type="text" class="copy-link form-control" value="{{ baseUrl }}/{{ page._id.toString() }}" readonly>
-  </p>
-  {% endif %}
-  <article>
-    {% block content_head %}
-      {% parent %}
-    {% endblock %}
-
-    {% block content_main_before %}
-    {% endblock %}
-
-    {% block content_main %}
-      {% parent %}
-    {% endblock content_main %}
-
-    {% block content_main_after %}
-    {% endblock %}
-
-    {% block content_footer %}
-      {% parent %}
-    {% endblock %}
-  </article>
-</div>
-
-{% endblock %} {# layout_main #}
-
-
-{% block footer %}
-  {% parent %}
-  {% include '../widget/system-version.html' %}
-{% endblock %}

+ 0 - 72
lib/views/crowi-plus/base/user_page_nosidebar.html

@@ -1,72 +0,0 @@
-{% extends '../../user_page.html' %}
-
-
-{% block layout_sidebar %}
-{% endblock %}
-
-
-{% block layout_main %}
-<div id="main" class="main col-md-12 {% if page %}{{ css.grant(page) }}{% endif %} {% block main_css_class %}{% endblock %}">
-  {% if page && page.grant != 1 %}
-  <p class="page-grant">
-    <i class="fa fa-lock"></i> {{ consts.pageGrants[page.grant] }} ({{ t('Browsing of this page is restricted') }})
-  </p>
-  {% endif %}
-  {% if page && page.grant == 2 %}
-  <p class="alert alert-info">
-    {{ t('Shareable Link') }}
-    <input type="text" class="copy-link form-control" value="{{ baseUrl }}/{{ page._id.toString() }}" readonly>
-  </p>
-  {% endif %}
-  <article>
-    <div class="container-fluid">
-      <div class="row">
-
-        <div class="col-lg-10 col-md-9">
-
-          {#
-           # ensure to insert 'content_head' block to col-xx-xx
-           #
-           #   Because this block has content like 'Bookmarks' or 'Recent Created' whose height changes dynamically,
-           #   setting of 'revision-toc' (affix) is hindered.
-           #}
-
-          {% block content_head %}
-            {% parent %}
-          {% endblock %}
-
-          {% block content_main_before %}
-          {% endblock %}
-
-          {% block content_main %}
-            {% parent %}
-          {% endblock content_main %}
-
-        </div> {# /.col- #}
-
-        {# relocate #revision-toc #}
-        <div class="col-lg-2 col-md-3 visible-lg visible-md">
-          <div id="revision-toc" class="revision-toc" data-spy="affix" data-offset-top="54">
-            <div id="revision-toc-content" class="revision-toc-content"></div>
-          </div>
-        </div> {# /.col- #}
-
-      </div>
-    </div>
-
-    {% block content_main_after %}
-    {% endblock %}
-
-    {% block content_footer %}
-      {% parent %}
-    {% endblock %}
-  </article>
-</div>
-
-{% endblock %} {# layout_main #}
-
-
-{% block footer %}
-  {% parent %}
-  {% include '../widget/system-version.html' %}
-{% endblock %}

+ 0 - 34
lib/views/crowi-plus/not_found.html

@@ -1,34 +0,0 @@
-{% extends 'base/not_found_nosidebar.html' %}
-
-{% block main_css_class %}
-  main-crowi-plus-customized
-  {% parent %}
-{% endblock %}
-
-{% block content_head %}
-
-  {% block content_head_before %}
-  {% endblock %}
-
-  {% include 'widget/header.html' %}
-
-  {% block content_head_after %}
-  {% endblock %}
-
-{% endblock %} {# /content_head #}
-
-
-{% block content_main %}
-  <div class="container-fluid">
-    <div class="row">
-
-      <div class="col-lg-10 col-md-9">
-
-        {% parent %}
-
-      </div> {# /.col- #}
-
-    </div>
-
-  </div>
-{% endblock %}

+ 0 - 57
lib/views/crowi-plus/page.html

@@ -1,57 +0,0 @@
-{% extends 'base/page_nosidebar.html' %}
-
-{% block main_css_class %}
-  main-crowi-plus-customized
-  {% parent %}
-{% endblock %}
-
-{% block content_head %}
-
-  {% block content_head_before %}
-  {% endblock %}
-
-  {% include 'widget/header.html' %}
-
-  {% block content_head_after %}
-  {% endblock %}
-
-{% endblock %} {# /content_head #}
-
-{% block content_main %}
-  <div class="container-fluid">
-    <div class="row">
-
-      <div class="col-lg-10 col-md-9">
-
-        {% parent %}
-
-        {# force remove #revision-toc from #content_main of parent #}
-        <script>
-          $('#revision-toc').remove();
-        </script>
-
-      </div> {# /.col- #}
-
-      {# relocate #revision-toc #}
-      <div class="col-lg-2 col-md-3 visible-lg visible-md">
-        <div id="revision-toc" class="revision-toc" data-spy="affix" data-offset-top="128">
-          <div id="revision-toc-content" class="revision-toc-content"></div>
-        </div>
-      </div> {# /.col- #}
-
-    </div>
-
-    {% if 'crowi-plus' === behaviorType() %}
-    <div class="row page-list">
-      <div class="col-md-12">
-        {% include './widget/page_list_container.html' %}
-      </div>
-    </div>
-    {% endif %}
-
-  </div>
-{% endblock %}
-
-{% block content_main_after %}
-  {% include 'widget/comments.html' %}
-{% endblock %}

+ 0 - 48
lib/views/crowi-plus/page_list.html

@@ -1,48 +0,0 @@
-{% extends 'base/page_list_nosidebar.html' %}
-
-{% block main_css_class %}
-  main-crowi-plus-customized
-  {% parent %}
-{% endblock %}
-
-{% block content_head %}
-
-  {% block content_head_before %}
-  {% endblock %}
-
-  {% include 'widget/header.html' %}
-
-  {% block content_head_after %}
-  {% endblock %}
-
-{% endblock %} {# /content_head #}
-
-
-{% block content_main %}
-  <div class="container-fluid">
-    <div class="row">
-
-      <div class="col-lg-10 col-md-9">
-
-        {% parent %}
-
-        {# force remove #revision-toc from #content_main of parent #}
-        <script>
-          $('#revision-toc').remove();
-
-          // hide unportalize button
-          $('.portal > .nav > .dropdown').remove();
-        </script>
-
-      </div> {# /.col- #}
-
-      {# relocate #revision-toc #}
-      <div class="col-lg-2 col-md-3 visible-lg visible-md">
-        <div id="revision-toc" class="revision-toc" data-spy="affix" data-offset-top="100">
-          <div id="revision-toc-content" class="revision-toc-content"></div>
-        </div>
-      </div> {# /.col- #}
-
-    </div>
-  </div>
-{% endblock %}

+ 0 - 24
lib/views/crowi-plus/user_page.html

@@ -1,24 +0,0 @@
-{% extends 'base/user_page_nosidebar.html' %}
-
-{% block main_css_class %}
-  main-crowi-plus-customized
-  {% parent %}
-{% endblock %}
-
-{% block content_head %}
-  {% parent %}
-{% endblock %} {# /content_head #}
-
-
-{% block content_main %}
-  {% parent %}
-
-  {# force remove #revision-toc from #content_main of parent #}
-  <script>
-    $('#revision-toc').remove();
-  </script>
-{% endblock %}
-
-{% block content_main_after %}
-  {% include 'widget/comments.html' %}
-{% endblock %}

+ 0 - 69
lib/views/crowi-plus/widget/header.html

@@ -1,69 +0,0 @@
-<div class="header-wrap">
-  <header id="page-header">
-    <div class="flex-title-line">
-      <div class="title-logo-container hidden-xs hidden-sm">
-        <a href="/">
-          <img alt="Crowi" src="/logo/32x32_g.png" />
-        </a>
-      </div>
-      <div class="title-container">
-        <h1 class="title flex-item-title" id="revision-path"></h1>
-        <div id="revision-url" class="url-line"></div>
-      </div>
-      {% if page %}
-      <div class="flex-item-action">
-        {% if user %}
-        <button
-            data-csrftoken="{{ csrf() }}"
-            data-liked="{% if page.isLiked(user) %}1{% else %}0{% endif %}"
-            class="like-button btn btn-default btn-sm {% if page.isLiked(user) %}active{% endif %}"
-        ><i class="fa fa-thumbs-o-up"></i></button>
-        {% endif %}
-      </div>
-      <div class="flex-item-action">
-        {% if user %}
-        <span id="bookmark-button">
-          <p class="bookmark-link">
-            <i class="fa fa-star-o"></i>
-          </p>
-        </span>
-        {% endif %}
-      </div>
-
-      <ul class="authors visible-md visible-lg">
-        <li>
-          <div class="creator-picture">
-            <a href="{{ userPageRoot(page.creator) }}">
-              <img src="{{ page.creator|default(author)|picture }}" class="picture picture-rounded"><br>
-            </a>
-          </div>
-          <div class="">
-            <div>Created by <a href="{{ userPageRoot(page.creator) }}">{{ page.creator.name|default(author.name) }}</a></div>
-            <div class="text-muted">{{ page.createdAt|datetz('Y/m/d H:i:s') }}</div>
-          </div>
-        </li>
-        <li>
-          <div class="creator-picture">
-            <a href="{{ userPageRoot(page.lastUpdateUser) }}">
-              <img src="{{ page.lastUpdateUser|default(author)|picture }}" class="picture picture-rounded"><br>
-            </a>
-          </div>
-          <div class="">
-            <div>Updated by <a href="{{ userPageRoot(page.lastUpdateUser) }}">{{ page.lastUpdateUser.name|default(author.name) }}</a></div>
-            <div class="text-muted">{{ page.updatedAt|datetz('Y/m/d H:i:s') }}</div>
-          </div>
-        </li>
-      </ul>
-      {% endif %}
-
-      {% if not page and ('/' === path or 'crowi' === behaviorType()) and not isUserPageList(path) and !isTrashPage() %}
-      <div class="portal-form-button">
-        <button class="btn btn-primary" id="create-portal-button" {% if not user %}disabled{% endif %}>Create Portal</button>
-        <p class="help-block"><a href="#" data-target="#help-portal" data-toggle="modal"><i class="fa fa-question-circle"></i> What is Portal?</a></p>
-      </div>
-      {% endif %}
-
-    </div>
-
-  </header>
-</div>

+ 2 - 2
lib/views/customlayout-selector/not_found.html

@@ -1,5 +1,5 @@
 {% if 'crowi-plus' === layoutType() %}
 {% if 'crowi-plus' === layoutType() %}
-  {% include '../crowi-plus/not_found.html' %}
+  {% include '../layout-growi/not_found.html' %}
 {% else %}
 {% else %}
-  {% include '../not_found.html' %}
+  {% include '../layout-crowi/not_found.html' %}
 {% endif %}
 {% endif %}

+ 2 - 2
lib/views/customlayout-selector/page.html

@@ -1,5 +1,5 @@
 {% if 'crowi-plus' === layoutType() %}
 {% if 'crowi-plus' === layoutType() %}
-  {% include '../crowi-plus/page.html' %}
+  {% include '../layout-growi/page.html' %}
 {% else %}
 {% else %}
-  {% include '../page.html' %}
+  {% include '../layout-crowi/page.html' %}
 {% endif %}
 {% endif %}

+ 2 - 2
lib/views/customlayout-selector/page_list.html

@@ -1,5 +1,5 @@
 {% if 'crowi-plus' === layoutType() %}
 {% if 'crowi-plus' === layoutType() %}
-  {% include '../crowi-plus/page_list.html' %}
+  {% include '../layout-growi/page_list.html' %}
 {% else %}
 {% else %}
-  {% include '../page_list.html' %}
+  {% include '../layout-crowi/page_list.html' %}
 {% endif %}
 {% endif %}

+ 2 - 2
lib/views/customlayout-selector/user_page.html

@@ -1,5 +1,5 @@
 {% if 'crowi-plus' === layoutType() %}
 {% if 'crowi-plus' === layoutType() %}
-  {% include '../crowi-plus/user_page.html' %}
+  {% include '../layout-growi/user_page.html' %}
 {% else %}
 {% else %}
-  {% include '../user_page.html' %}
+  {% include '../layout-crowi/user_page.html' %}
 {% endif %}
 {% endif %}

+ 0 - 15
lib/views/index.html

@@ -1,15 +0,0 @@
-{% extends 'layout/2column.html' %}
-
-{% block content_head %}
-<header>
-  <h2>Index</h2>
-</header>
-{% endblock %}
-
-{% block content_main %}
-
-  {% for page in pages %}
-    <a href="/{{ page.path }}">{{ page.path }} ({{page.updatedAt|date('Y-m-d H:i:s O')}})</a><br />
-  {% endfor %}
-
-{% endblock %}

+ 82 - 58
lib/views/installer.html

@@ -1,89 +1,113 @@
-{% extends 'layout/single-nologin.html' %}
+{% extends 'layout/layout.html' %}
+
+{% block html_base_css %}installer nologin{% endblock %}
 
 
 {% block html_title %}セットアップ {% endblock %}
 {% block html_title %}セットアップ {% endblock %}
 
 
-{% block content_main %}
 
 
 
 
-<div class="login-dialog-container col-md-5">
+{#
+ # Remove default contents
+ #}
+{% block html_head_loading_legacy %}
+{% endblock %}
+{% block html_head_loading_app %}
+{% endblock %}
+{% block layout_head_nav %}
+{% endblock %}
+{% block sidebar %}
+{% endblock %}
 
 
-<div class="installer-header">
-  <img src="/logo/135x32.png" alt="Crowi">
-  <h1>
-    Crowi のセットアップへようこそ!
-  </h1>
-</div>
 
 
 
 
-<div class="login-dialog"  id="login-dialog">
-  <div class="login-dialog-inner">
-    <h2>管理者の作成</h2>
+{% block layout_main %}
 
 
-    <p class="text-info">
-    はじめに、管理者アカウントを作成してください。
-    </p>
+<div class="main container-fluid">
 
 
-    {% if req.form.errors.length > 0 %}
-    <div class="alert alert-danger">
-      <ul>
-      {% for error in req.form.errors %}
-        <li>{{ error }}</li>
-      {% endfor %}
-      </ul>
-    </div>
-    {% endif %}
+  <div class="row">
 
 
-    <form role="form" action="/installer/createAdmin" method="post">
-      <label>ユーザーID</label>
-      <div class="input-group" id="input-group-username">
-        <span class="input-group-addon"><strong>@</strong></span>
-        <input type="text" class="form-control" placeholder="記入例: taroyama" name="registerForm[username]" value="{{ req.body.registerForm.username }}" required>
-      </div>
-      <p class="help-block">
-      <span id="help-block-username" class="text-danger"></span>
-      ユーザーIDは、ユーザーページのURLなどに利用されます。半角英数字と一部の記号のみ利用できます。
-      </p>
-
-      <label>名前</label>
-      <div class="input-group">
-        <span class="input-group-addon"><i class="fa fa-user"></i></span>
-        <input type="text" class="form-control" placeholder="記入例: 山田 太郎" name="registerForm[name]" value="{{ req.body.registerForm.name }}" required>
-      </div>
+    <div class="login-header col-sm-offset-4 col-sm-4">
+      <div class="logo">{% include 'widget/logo.html' %}</div>
+      <h1>GROWI</h1>
 
 
-      <label >メールアドレス</label>
-      <div class="input-group">
-        <span class="input-group-addon"><i class="fa fa-envelope"></i></span>
-        <input type="email" class="form-control" placeholder="E-mail" name="registerForm[email]" value="{{ googleEmail|default(req.body.registerForm.email) }}" required>
+      <div class="login-form-errors">
+        {% if req.form.errors.length > 0 %}
+        <div class="alert alert-danger">
+          <ul>
+          {% for error in req.form.errors %}
+            <li>{{ error }}</li>
+          {% endfor %}
+          </ul>
+        </div>
+        {% endif %}
       </div>
       </div>
+    </div>
 
 
-      <label>パスワード</label>
-      <div class="input-group">
-        <span class="input-group-addon"><i class="fa fa-key"></i></span>
-        <input type="password" class="form-control" placeholder="Password" name="registerForm[password]" required>
-      </div>
-      <p class="help-block">
-      パスワードは6文字以上の半角英数字または記号
+    <div class="login-dialog p-t-10 p-b-10 col-sm-offset-4 col-sm-4" id="login-dialog">
+      <p class="alert alert-success">
+        <strong>最初のアカウントの作成</strong><br>
+        <small>初めに作成するアカウントは、自動的に管理者権限が付与されます</small>
       </p>
       </p>
 
 
-      <input type="hidden" name="_csrf" value="{{ csrf() }}">
-      <input type="submit" class="btn btn-primary btn-lg btn-block" value="作成">
-    </form>
+      <form role="form" action="/installer/createAdmin" method="post" id="register-form">
+
+        <div class="input-group" id="input-group-username">
+          <span class="input-group-addon"><i class="icon-user"></i></span>
+          <input type="text" class="form-control" placeholder="{{ t('User ID') }}" name="registerForm[username]" value="{{ req.body.registerForm.username }}" required>
+        </div>
+        <p class="help-block">
+          <span id="help-block-username"></span>
+        </p>
+
+        <div class="input-group">
+          <span class="input-group-addon"><i class="icon-tag"></i></span>
+          <input type="text" class="form-control" placeholder="{{ t('Name') }}" name="registerForm[name]" value="{{ googleName|default(req.body.registerForm.name) }}" required>
+        </div>
+
+        <div class="input-group">
+          <span class="input-group-addon"><i class="icon-envelope"></i></span>
+          <input type="email" class="form-control" placeholder="{{ t('Email') }}" name="registerForm[email]" value="{{ googleEmail|default(req.body.registerForm.email) }}" required>
+        </div>
+
+        <div class="input-group">
+          <span class="input-group-addon"><i class="icon-lock"></i></span>
+          <input type="password" class="form-control" placeholder="{{ t('Password') }}" name="registerForm[password]" required>
+        </div>
+
+        <input type="hidden" name="_csrf" value="{{ csrf() }}">
+        <div class="input-group m-t-30 m-b-20 d-flex justify-content-center">
+          <button type="submit" class="fcbtn btn btn-success btn-1b btn-register">
+            <span class="btn-label"><i class="icon-user-follow"></i></span>
+            {{ t('Create') }}
+          </button>
+        </div>
+
+        <div class="input-group m-t-30 d-flex justify-content-center">
+          <a href="https://growi.org" class="link-growi-org">
+            <span class="growi">GROWI</span>.<span class="org">ORG
+          </a>
+        </div>
+      </form>
+    </div>
 
 
-  </div>
-</div>
+  </div>{# /.row #}
 
 
-</div>
+</div>{# /.main #}
 
 
 <script>
 <script>
 $(function() {
 $(function() {
   $('#register-form input[name="registerForm[username]"]').change(function(e) {
   $('#register-form input[name="registerForm[username]"]').change(function(e) {
     var username = $(this).val();
     var username = $(this).val();
+    $('#login-dialog').removeClass('has-error');
     $('#input-group-username').removeClass('has-error');
     $('#input-group-username').removeClass('has-error');
     $('#help-block-username').html("");
     $('#help-block-username').html("");
 
 
     $.getJSON('/_api/check_username', {username: username}, function(json) {
     $.getJSON('/_api/check_username', {username: username}, function(json) {
       if (!json.valid) {
       if (!json.valid) {
-        $('#help-block-username').html('<i class="fa fa-warning"></i>このユーザーIDは利用できません。<br>');
+        $('#help-block-username').html(
+          '<i class="icon-fw icon-ban"></i>このユーザーIDは利用できません。'
+        );
+        $('#login-dialog').addClass('has-error');
         $('#input-group-username').addClass('has-error');
         $('#input-group-username').addClass('has-error');
       }
       }
     });
     });

+ 90 - 74
lib/views/invited.html

@@ -1,111 +1,127 @@
-{% extends 'layout/single-nologin.html' %}
+{% extends 'layout/layout.html' %}
+
+{% block html_base_css %}invited nologin{% endblock %}
 
 
 {% block html_title %}Registration · {% endblock %}
 {% block html_title %}Registration · {% endblock %}
 
 
-{% block content_main %}
 
 
-<h1 class="login-page">
-  {% if config.crowi['app:title'] == 'Crowi' %}
-    <img src="/logo/135x32.png" alt="Crowi">
-  {% else %}
-    {{ config.crowi['app:title'] }}<br>
-    <img src="/logo/100x11_w.png" alt="powered by Crowi">
-  {% endif %}
-</h1>
 
 
-<div class="login-dialog-container flip-container col-md-5">
+{#
+  # Remove default contents
+  #}
+ {% block html_head_loading_legacy %}
+ {% endblock %}
+ {% block html_head_loading_app %}
+ {% endblock %}
+ {% block layout_head_nav %}
+ {% endblock %}
+ {% block sidebar %}
+ {% endblock %}
 
 
-<div class="login-dialog" id="login-dialog">
 
 
-  <div class="login-dialog-inner front">
-    <h2>ユーザー情報入力</h2>
 
 
-    <p>
-    ようこそ!<br>
-    はじめに、あなたのことを教えて下さい。
-    </p>
+ {% block layout_main %}
 
 
-    <div id="login-form-errors">
-      {% set message = req.flash('warningMessage') %}
-      {% if message.length %}
-      <div class="alert alert-danger">
-        {{ message }}
-      </div>
-      {% endif %}
-
-      {% if req.form.errors.length > 0 %}
-      <div class="alert alert-danger">
-        <ul>
-        {% for error in req.form.errors %}
-          <li>{{ error }}</li>
-        {% endfor %}
-        </ul>
-      </div>
-      {% endif %}
-    </div>
-    <form role="form" id="invited-form" action="/login/activateInvited" method="post">
+<div class="main container-fluid">
 
 
-      <label>メールアドレス</label>
-      <div class="input-group">
-        <span class="input-group-addon"><i class="fa fa-envelope"></i></span>
-        <input type="text" class="form-control" disabled value="{{ user.email }}">
-      </div>
-      <p class="help-block">
-      このメールアドレスで招待を受け取っています。
-      </p>
+  <div class="row">
 
 
-      <label>ユーザーID</label>
-      <div class="input-group" id="input-group-username">
-        <span class="input-group-addon"><strong>@</strong></span>
-        <input type="text" class="form-control" placeholder="記入例: taroyama" name="invitedForm[username]" value="{{ req.body.invitedForm.username }}" required>
-      </div>
-      <p class="help-block">
-      <span id="help-block-username" class="text-danger"></span>
-      ユーザーIDは、ユーザーページのURLなどに利用されます。半角英数字と一部の記号のみ利用できます。
-      </p>
+    <div class="login-header col-sm-offset-4 col-sm-4">
+      <div class="logo">{% include 'widget/logo.html' %}</div>
+      <h1>GROWI</h1>
 
 
-      <label>名前</label>
-      <div class="input-group">
-        <span class="input-group-addon"><i class="fa fa-user"></i></span>
-        <input type="text" class="form-control" placeholder="記入例: 山田 太郎" name="invitedForm[name]" value="{{ req.body.invitedForm.name }}" required>
-      </div>
+      <div id="login-form-errors">
+        {% set message = req.flash('warningMessage') %}
+        {% if message.length %}
+        <div class="alert alert-danger">
+          {{ message }}
+        </div>
+        {% endif %}
 
 
-      <label>パスワード</label>
-      <div class="input-group">
-        <span class="input-group-addon"><i class="fa fa-key"></i></span>
-        <input type="password" class="form-control" placeholder="Password" name="invitedForm[password]" required>
+        {% if req.form.errors.length > 0 %}
+        <div class="alert alert-danger">
+          <ul>
+          {% for error in req.form.errors %}
+            <li>{{ error }}</li>
+          {% endfor %}
+          </ul>
+        </div>
+        {% endif %}
       </div>
       </div>
-      <p class="help-block">
-      現在、仮パスワードでログインしています。新しいパスワードを決定してください。<br>
-      パスワードは6文字以上の半角英数字または記号
+    </div>
+
+    <div class="login-dialog p-t-10 p-b-10 col-sm-offset-4 col-sm-4" id="login-dialog">
+      <p class="alert alert-success">
+        <strong>アカウントの作成</strong><br>
+        <small>招待を受け取ったメールアドレスでアカウントを作成します</small>
       </p>
       </p>
 
 
-      <input type="hidden" name="_csrf" value="{{ csrf() }}">
-      <input type="submit" class="btn btn-primary btn-lg btn-block" value="登録を完了">
-    </form>
+      <form role="form" action="/installer/activateInvited" method="post" id="invited-form">
+
+        <div class="input-group">
+          <span class="input-group-addon"><i class="icon-envelope"></i></span>
+          <input type="text" class="form-control" disabled value="{{ user.email }}">
+        </div>
+
+        <div class="input-group" id="input-group-username">
+          <span class="input-group-addon"><i class="icon-user"></i></span>
+          <input type="text" class="form-control" placeholder="{{ t('User ID') }}" name="invitedForm[username]" value="{{ req.body.invitedForm.username }}" required>
+        </div>
+        <p class="help-block">
+          <span id="help-block-username"></span>
+        </p>
+
+        <div class="input-group">
+          <span class="input-group-addon"><i class="icon-tag"></i></span>
+          <input type="text" class="form-control" placeholder="{{ t('Name') }}" name="invitedForm[name]" value="{{ googleName|default(req.body.invitedForm.name) }}" required>
+        </div>
+
+
+        <div class="input-group">
+          <span class="input-group-addon"><i class="icon-lock"></i></span>
+          <input type="password" class="form-control" placeholder="{{ t('Password') }}" name="invitedForm[password]" required>
+        </div>
+
+        <input type="hidden" name="_csrf" value="{{ csrf() }}">
+        <div class="input-group m-t-30 m-b-20 d-flex justify-content-center">
+          <button type="submit" class="fcbtn btn btn-success btn-1b btn-register">
+            <span class="btn-label"><i class="icon-user-follow"></i></span>
+            {{ t('Create') }}
+          </button>
+        </div>
+
+        <div class="input-group m-t-30 d-flex justify-content-center">
+          <a href="https://growi.org" class="link-growi-org">
+            <span class="growi">GROWI</span>.<span class="org">ORG
+          </a>
+        </div>
+      </form>
+    </div>
 
 
-    <hr>
+  </div>{# /.row #}
 
 
-  </div>
-</div>
+</div>{# /.main #}
 
 
 <script>
 <script>
 $(function() {
 $(function() {
   $('#invited-form input[name="invitedForm[username]"]').change(function(e) {
   $('#invited-form input[name="invitedForm[username]"]').change(function(e) {
     var username = $(this).val();
     var username = $(this).val();
+    $('#login-dialog').removeClass('has-error');
     $('#input-group-username').removeClass('has-error');
     $('#input-group-username').removeClass('has-error');
     $('#help-block-username').html("");
     $('#help-block-username').html("");
 
 
     $.getJSON('/_api/check_username', {username: username}, function(json) {
     $.getJSON('/_api/check_username', {username: username}, function(json) {
       if (!json.valid) {
       if (!json.valid) {
-        $('#help-block-username').html('<i class="fa fa-warning"></i>このユーザーIDは利用できません。<br>');
+        $('#help-block-username').html(
+          '<i class="icon-fw icon-ban"></i>このユーザーIDは利用できません。'
+        );
+        $('#login-dialog').addClass('has-error');
         $('#input-group-username').addClass('has-error');
         $('#input-group-username').addClass('has-error');
       }
       }
     });
     });
   });
   });
 });
 });
 </script>
 </script>
-</div>
 
 
 {% endblock %}
 {% endblock %}
 
 

+ 51 - 0
lib/views/layout-crowi/base/layout.html

@@ -0,0 +1,51 @@
+{% extends '../../layout/layout.html' %}
+
+
+{% block layout_main %}
+<div class="container-fluid">
+
+  <a href="" class=" hidden-xs hidden-sm layout-control" id="toggle-sidebar">
+    <i class="ti-angle-right"></i><i class="ti-angle-left"></i> <span class="hide-on-affix-top"></span>
+  </a>
+  <aside class="crowi-sidebar col-md-3 hidden-xs hidden-sm hidden-print">
+
+    {% block side_header %}
+    {% endblock %}
+
+    <div class="side-content">
+      {% block side_content %}
+      {% endblock %}
+    </div>
+
+    {% block side_footer %}
+    {% endblock %}
+
+    {% include '../../widget/system-version.html' %}
+  </aside>
+
+  <div class="row bg-title">
+    <div class="col-md-9">
+      {% block content_header %}
+      {% endblock %}
+    </div>
+  </div><!-- /.bg-title -->
+
+  <div class="row">
+    <div id="main" class="main m-t-15 col-md-9 {% if page %}{{ css.grant(page) }}{% endif %} {% block main_css_class %}{% endblock %}">
+      {% block content_main_before %}
+      {% endblock %}
+
+      {% block content_main %}
+      {% endblock content_main %}
+
+      {% block content_main_after %}
+      {% endblock %}
+
+      {% block content_footer %}
+      {% endblock %}
+
+    </div>
+  </div>
+
+</div><!-- /.container-fluid -->
+{% endblock %} {# layout_main #}

+ 41 - 0
lib/views/layout-crowi/not_found.html

@@ -0,0 +1,41 @@
+{% extends 'base/layout.html' %}
+
+{% block content_header %}
+
+  {% block content_header_before %}
+  {% endblock %}
+
+  <div class="header-wrap">
+    <header id="page-header">
+      <div class="flex-title-line">
+        <div>
+          <h1 class="title flex-item-title" id="revision-path"></h1>
+          <div id="revision-url" class="url-line"></div>
+        </div>
+      </div>
+
+    </header>
+  </div>
+
+  {% block content_header_after %}
+  {% endblock %}
+
+{% endblock %} {# /content_head #}
+
+
+{% block content_main_before %}
+  {% include '../widget/page_alerts.html' %}
+{% endblock %}
+
+
+{% block content_main %}
+  {% include '../widget/not_found_content.html' %}
+{% endblock %}
+
+
+{% block content_main_after %}
+{% endblock %}
+
+
+{% block content_footer %}
+{% endblock %}

+ 68 - 0
lib/views/layout-crowi/page.html

@@ -0,0 +1,68 @@
+{% extends 'base/layout.html' %}
+
+
+{% block content_header %}
+
+  {% block content_header_before %}
+  {% endblock %}
+
+  <div class="header-wrap">
+    <header id="page-header">
+      <div class="d-flex align-items-center">
+        <div class="title-container">
+          <h1 class="title flex-item-title" id="revision-path"></h1>
+          <div id="revision-url" class="url-line"></div>
+        </div>
+        {% include '../widget/header-buttons.html' %}
+      </div>
+    </header>
+  </div>
+
+  {% block content_header_after %}
+  {% endblock %}
+
+{% endblock %}
+
+
+{% block content_main_before %}
+{% endblock %}
+
+
+{% block content_main %}
+  {% include '../widget/page_content.html' %}
+{% endblock %}
+
+
+{% block content_main_after %}
+{% endblock %}
+
+
+{% block content_footer %}
+  {% if page %}
+    {% include '../widget/page_attachments.html' %}
+  {% endif %}
+{% endblock %}
+
+{% block side_header %}
+  {% if page and not page.isDeleted() %}
+    {% include '../widget/page_side_header.html' %}
+  {% endif %}
+{% endblock %} {# side_header #}
+
+{% block side_content %}
+  {% if page and not page.isDeleted() %}
+    {% include '../widget/page_side_content.html' %}
+  {% endif %}
+{% endblock %}
+
+{% block layout_footer %}
+{% endblock %}
+
+{% block body_end %}
+  <div id="presentation-layer" class="fullscreen-layer">
+    <div id="presentation-container"></div>
+  </div>
+  <div id="crowi-modals">
+    {% include '../widget/page_modals.html' %}
+  </div>
+{% endblock %}

+ 98 - 0
lib/views/layout-crowi/page_list.html

@@ -0,0 +1,98 @@
+{% extends 'base/layout.html' %}
+
+
+{% block html_base_attr %}
+  data-spy="scroll"
+  data-target="#search-result-list"
+{% endblock %}
+
+{% block content_header %}
+
+{% block content_header_before %}
+{% endblock %}
+
+<div class="header-wrap">
+  <header id="page-header" class="{% if page %}has-page{% endif %}">
+
+    <div class="d-flex align-items-center">
+      <div class="title-container">
+        <div class="d-flex">
+          <h1 class="title flex-item-title" id="revision-path"></h1>
+          {% if false %} {# Disable temporaly -- 2018.03.08 Yuki Takei #}
+          {% if searchConfigured() && !isTopPage() && !isTrashPage() %}
+          <form id="search-listpage-form" class="m-l-10 input-group search-input-group hidden-xs hidden-sm"
+              data-toggle="tooltip" data-placement="bottom" title="{{ path }} 以下から検索" data-container="body">
+            <div class="input-group">
+              <input id="search-listpage-input" type="text" class="form-control input-sm" data-path="{{ path }}" placeholder="Search for...">
+              <span class="input-group-btn">
+                <button class="btn btn-default btn-sm"><i class="icon-magnifier"></i></button>
+              </span>
+            </div><!-- /input-group -->
+            <a class="search-listpage-clear" id="search-listpage-clear"><i class="fa fa-times-circle"></i></a>
+          </form>
+          {% endif %}
+          {% endif %}
+        </div>
+        <div id="revision-url" class="url-line"></div>
+      </div>
+      {% include '../widget/header-buttons.html' %}
+    </div>
+
+  </header>
+</div>
+
+{% endblock %}
+
+{% block content_main %}
+
+  {% block content_main_before %}
+  {% endblock %}
+
+  {# page-list-search should be fully managed by react.js,
+  # but now the header and page list content is rendered separately by the server,
+  # so now bind the values through the hidden fields.
+  #}
+  {% if false %} {# Disable temporaly -- 2018.03.08 Yuki Takei #}
+  {% if searchConfigured() && !isTopPage() && !isTrashPage() %}
+  <div id="page-list-search">
+  </div>
+  {% endif %}
+  {% endif %}
+
+  {% include '../widget/page_content.html' %}
+
+  <div class="row page-list m-t-30">
+    <div class="col-md-12">
+      {% include '../widget/page_list_and_timeline.html' %}
+    </div>
+  </div>
+
+{% endblock %}
+
+
+{% block content_main_after %}
+{% endblock %}
+
+
+{% block content_footer %}
+<footer>
+</footer>
+{% endblock %}
+
+
+{% block side_header %}
+
+{% if not page and not isUserPageList(path) and !isTrashPage() %}
+  {% include '../widget/create_portal.html' %}
+{% else %}
+  {% include '../widget/page_side_header.html' %}
+{% endif %}
+
+{% endblock %} {# side_header #}
+
+{% block body_end %}
+<div id="crowi-modals">
+  {% include '../modal/what_is_portal.html' %}
+  {% include '../modal/unportalize.html' %}
+</div>
+{% endblock %} {# body_end #}

+ 19 - 0
lib/views/layout-crowi/user_page.html

@@ -0,0 +1,19 @@
+{% extends 'page.html' %}
+
+{% block main_css_class %}user-page{% endblock %}
+
+
+{% block content_header %}
+  {% if pageUser %}
+    {% include '../widget/user_page_header.html' %}
+  {% else %}
+    {% parent %}
+  {% endif %}
+{% endblock %}
+
+
+{% block content_main_before %}
+  <div class="m-b-30 user-page-content-container">
+    {% include '../widget/user_page_content.html' %}
+  </div>
+{% endblock %}

+ 33 - 0
lib/views/layout-growi/base/layout.html

@@ -0,0 +1,33 @@
+{% extends '../../layout/layout.html' %}
+
+
+{% block layout_main %}
+<div class="container-fluid">
+
+  <div class="row bg-title">
+    <div class="col-xs-12">
+      {% block content_header %}
+      {% endblock %}
+    </div>
+  </div><!-- /.bg-title -->
+
+  <div class="row">
+    <div id="main" class="main m-t-15 col-md-12 {% if page %}{{ css.grant(page) }}{% endif %} {% block main_css_class %}{% endblock %}">
+      {% block content_main_before %}
+      {% endblock %}
+
+      {% block content_main %}
+      {% endblock content_main %}
+
+      {% block content_main_after %}
+      {% endblock %}
+    </div>
+
+  </div>
+
+</div><!-- /.container-fluid -->
+
+<footer class="footer">
+  {% include '../../widget/system-version.html' %}
+</footer>
+{% endblock %} {# layout_main #}

+ 20 - 0
lib/views/layout-growi/not_found.html

@@ -0,0 +1,20 @@
+{% extends 'base/layout.html' %}
+
+
+{% block content_header %}
+  {% include 'widget/header.html' %}
+{% endblock %}
+
+
+{% block content_main_before %}
+  {% include '../widget/page_alerts.html' %}
+{% endblock %}
+
+
+{% block content_main %}
+  <div class="row">
+    <div class="col-lg-10 col-md-9">
+      {% include '../widget/not_found_content.html' %}
+    </div> {# /.col- #}
+  </div>
+{% endblock %}

+ 63 - 0
lib/views/layout-growi/page.html

@@ -0,0 +1,63 @@
+{% extends 'base/layout.html' %}
+
+
+{% block content_header %}
+  {% include 'widget/header.html' %}
+{% endblock %}
+
+
+{% block content_main_before %}
+{% endblock %}
+
+
+{% block content_main %}
+  <div class="row">
+
+    <div class="col-lg-10 col-md-9">
+
+      {% include '../widget/page_content.html' %}
+
+      {# force remove #revision-toc from #content_main of parent #}
+      <script>
+        $('#revision-toc').remove();
+      </script>
+
+    </div> {# /.col- #}
+
+    {# relocate #revision-toc #}
+    <div class="col-lg-2 col-md-3 revision-toc-container hidden-sm hidden-xs">
+      <div id="revision-toc" class="revision-toc" data-spy="affix" data-offset-top="80">
+        <div id="revision-toc-content" class="revision-toc-content"></div>
+      </div>
+    </div> {# /.col- #}
+
+  </div>
+
+  {% if 'crowi-plus' === behaviorType() %}
+  <div class="row page-list m-t-30">
+    <div class="col-md-12">
+      {% include '../widget/page_list_and_timeline.html' %}
+    </div>
+  </div>
+  {% endif %}
+{% endblock %}
+
+
+{% block content_main_after %}
+  {% include 'widget/comments.html' %}
+
+  {% if page %}
+    {% include '../widget/page_attachments.html' %}
+  {% endif %}
+{% endblock %}
+
+
+{% block body_end %}
+  <div id="presentation-layer" class="fullscreen-layer">
+    <div id="presentation-container"></div>
+  </div>
+
+  <div id="crowi-modals">
+    {% include '../widget/page_modals.html' %}
+  </div>
+{% endblock %}

+ 60 - 0
lib/views/layout-growi/page_list.html

@@ -0,0 +1,60 @@
+{% extends 'base/layout.html' %}
+
+
+{% block content_header %}
+  {% include 'widget/header.html' %}
+{% endblock %}
+
+
+{% block content_main_before %}
+{% endblock %}
+
+
+{% block content_main %}
+  <div class="row">
+
+    <div class="col-lg-10 col-md-9">
+
+      {% include '../widget/page_content.html' %}
+
+      {# force remove #revision-toc from #content_main of parent #}
+      <script>
+        $('#revision-toc').remove();
+      </script>
+
+    </div> {# /.col- #}
+
+    {# relocate #revision-toc #}
+    <div class="col-lg-2 col-md-3 revision-toc-container hidden-sm hidden-xs">
+      <div id="revision-toc" class="revision-toc" data-spy="affix" data-offset-top="80">
+        <div id="revision-toc-content" class="revision-toc-content"></div>
+      </div>
+    </div> {# /.col- #}
+
+  </div>
+
+  <div class="row page-list m-t-30">
+    <div class="col-md-12">
+      {% include '../widget/page_list_and_timeline.html' %}
+    </div>
+  </div>
+{% endblock %}
+
+
+{% block content_footer %}
+  {% if page %}
+    {% include '../widget/page_attachments.html' %}
+  {% endif %}
+{% endblock %}
+
+
+{% block body_end %}
+  <div id="presentation-layer" class="fullscreen-layer">
+    <div id="presentation-container"></div>
+  </div>
+  <div id="crowi-modals">
+    {% include '../widget/page_modals.html' %}
+    {% include '../modal/what_is_portal.html' %}
+    {% include '../modal/unportalize.html' %}
+  </div>
+{% endblock %}

+ 67 - 0
lib/views/layout-growi/user_page.html

@@ -0,0 +1,67 @@
+{% extends 'page.html' %}
+
+{% block main_css_class %}
+  {% parent %}
+  user-page
+{% endblock %}
+
+{% block content_header %}
+  {% if pageUser %}
+    {% include '../widget/user_page_header.html' %}
+  {% else %}
+    {% parent %}
+  {% endif %}
+{% endblock %}
+
+
+{% block content_main %}
+  <div class="row">
+
+    <div class="col-lg-10 col-md-9">
+
+      {#
+        # ensure to insert 'user_page_content' widget to here
+        #
+        #   Because this block has content like 'Bookmarks' or 'Recent Created' whose height changes dynamically,
+        #   setting of 'revision-toc' (affix) is hindered.
+        #}
+      <div class="m-b-30 user-page-content-container">
+        {% include '../widget/user_page_content.html' %}
+      </div>
+
+      {% block content_main_before %}
+        {% parent %}
+      {% endblock %}
+
+      {% include '../widget/page_content.html' %}
+
+      {# force remove #revision-toc from #content_main of parent #}
+      <script>
+        $('#revision-toc').remove();
+      </script>
+
+    </div> {# /.col- #}
+
+    {# relocate #revision-toc #}
+    <div class="col-lg-2 col-md-3 revision-toc-container hidden-sm hidden-xs">
+      <div id="revision-toc" class="revision-toc" data-spy="affix" data-offset-top="75">
+        <div id="revision-toc-content" class="revision-toc-content"></div>
+      </div>
+    </div> {# /.col- #}
+
+  </div>
+
+  {% if 'crowi-plus' === behaviorType() %}
+  <div class="row page-list m-t-30">
+    <div class="col-md-12">
+      {% include '../widget/page_list_and_timeline.html' %}
+    </div>
+  </div>
+  {% endif %}
+
+{% endblock %}
+
+
+{% block content_main_after %}
+  {% include 'widget/comments.html' %}
+{% endblock %}

+ 5 - 5
lib/views/crowi-plus/widget/comments.html → lib/views/layout-growi/widget/comments.html

@@ -2,17 +2,17 @@
 
 
   <div class="page-comments col-lg-7 col-md-9">
   <div class="page-comments col-lg-7 col-md-9">
 
 
-    <h4><i class="fa fa-comments"></i> Comments</h4>
+    <h4><i class="icon-fw icon-bubbles"></i> Comments</h4>
 
 
     <div class="page-comments-list" id="page-comments-list">
     <div class="page-comments-list" id="page-comments-list">
       {# transplanted to PageComments React component -- 2017.06.02 Yuki Takei
       {# transplanted to PageComments React component -- 2017.06.02 Yuki Takei
       <div class="page-comments-list-newer collapse" id="page-comments-list-newer"></div>
       <div class="page-comments-list-newer collapse" id="page-comments-list-newer"></div>
 
 
-      <a class="page-comments-list-toggle-newer text-center" data-toggle="collapse" href="#page-comments-list-newer"><i class="fa fa-angle-double-up"></i> Comments for Newer Revision <i class="fa fa-angle-double-up"></i></a>
+      <a class="page-comments-list-toggle-newer text-center" data-toggle="collapse" href="#page-comments-list-newer"><i class="ti-angle-double-up"></i> Comments for Newer Revision <i class="ti-angle-double-up"></i></a>
 
 
       <div class="page-comments-list-current" id="page-comments-list-current"></div>
       <div class="page-comments-list-current" id="page-comments-list-current"></div>
 
 
-      <a class="page-comments-list-toggle-older text-center" data-toggle="collapse" href="#page-comments-list-older"><i class="fa fa-angle-double-down"></i> Comments for Older Revision <i class="fa fa-angle-double-down"></i></a>
+      <a class="page-comments-list-toggle-older text-center" data-toggle="collapse" href="#page-comments-list-older"><i class="ti-angle-double-down"></i> Comments for Older Revision <i class="ti-angle-double-down"></i></a>
 
 
       <div class="page-comments-list-older collapse in" id="page-comments-list-older"></div>
       <div class="page-comments-list-older collapse in" id="page-comments-list-older"></div>
       #}
       #}
@@ -22,7 +22,7 @@
     <form class="form page-comment-form" id="page-comment-form" onsubmit="return false;">
     <form class="form page-comment-form" id="page-comment-form" onsubmit="return false;">
       <div class="comment-form">
       <div class="comment-form">
         <div class="comment-form-user">
         <div class="comment-form-user">
-            <img src="{{ user|picture }}" class="picture picture-rounded" width="25" alt="{{ user.name }}" title="{{ user.name }}" />
+            <img src="{{ user|picture }}" class="picture img-circle" width="25" alt="{{ user.name }}" title="{{ user.name }}" />
         </div>
         </div>
         <div class="comment-form-main">
         <div class="comment-form-main">
           <div class="comment-write" id="comment-write">
           <div class="comment-write" id="comment-write">
@@ -35,7 +35,7 @@
             <input type="hidden" name="commentForm[revision_id]" value="{{ revision._id.toString() }}">
             <input type="hidden" name="commentForm[revision_id]" value="{{ revision._id.toString() }}">
             <div class="pull-right">
             <div class="pull-right">
               <span class="text-danger" id="comment-form-message"></span>
               <span class="text-danger" id="comment-form-message"></span>
-              <button type="submit" id="comment-form-button" class="btn btn-primary form-inline" {% if not user %}disabled{% endif %}>
+              <button type="submit" id="comment-form-button" class="fcbtn btn btn-sm btn-outline btn-rounded btn-primary btn-1b" {% if not user %}disabled{% endif %}>
                 Comment
                 Comment
               </button>
               </button>
             </div>
             </div>

+ 51 - 0
lib/views/layout-growi/widget/header.html

@@ -0,0 +1,51 @@
+<div class="header-wrap">
+  <header id="page-header">
+    <div class="d-flex align-items-center">
+      <div class="title-logo-container hidden-xs hidden-sm">
+        <a class="logo" href="/">
+          <div class="logo-mark">{% include '../../widget/logo.html' %}</div>
+        </a>
+      </div>
+      <div class="title-container">
+        <h1 class="title flex-item-title" id="revision-path"></h1>
+        <div id="revision-url" class="url-line"></div>
+      </div>
+      {% if page %}
+      {% include '../../widget/header-buttons.html' %}
+
+      <ul class="authors hidden-sm hidden-xs">
+        <li>
+          <div class="d-flex align-items-center">
+            <a class="m-r-5" href="{{ userPageRoot(page.creator) }}">
+              <img src="{{ page.creator|default(author)|picture }}" class="picture img-circle">
+            </a>
+            <div>
+              <div>Created by <a href="{{ userPageRoot(page.creator) }}">{{ page.creator.name|default(author.name) }}</a></div>
+              <div class="text-muted">{{ page.createdAt|datetz('Y/m/d H:i:s') }}</div>
+            </div>
+          </div>
+        </li>
+        <li class="m-t-5">
+          <div class="d-flex align-items-center">
+            <a class="m-r-5" href="{{ userPageRoot(page.lastUpdateUser) }}">
+              <img src="{{ page.lastUpdateUser|default(author)|picture }}" class="picture img-circle">
+            </a>
+            <div>
+              <div>Updated by <a href="{{ userPageRoot(page.lastUpdateUser) }}">{{ page.lastUpdateUser.name|default(author.name) }}</a></div>
+              <div class="text-muted">{{ page.updatedAt|datetz('Y/m/d H:i:s') }}</div>
+            </div>
+          </div>
+        </li>
+      </ul>
+      {% endif %}
+
+      {% if not page and ('/' === path or 'crowi' === behaviorType()) and not isUserPageList(path) and !isTrashPage() %}
+        {% if '/' === path.slice(-1) %}
+          {% include '../../widget/create_portal.html' %}
+        {% endif %}
+      {% endif %}
+
+    </div>
+
+  </header>
+</div>

+ 0 - 57
lib/views/layout/2column.html

@@ -1,57 +0,0 @@
-{% extends 'layout.html' %}
-
-{% block layout_sidebar %}
-
-<a href="" class=" hidden-xs hidden-sm layout-control" id="toggle-sidebar"><i class="fa fa-chevron-right"></i> <span class="hide-on-affix-top"></span></a>
-<aside class="sidebar col-md-3 hidden-xs hidden-sm hidden-print">
-
-  {% block side_header %}
-  {% endblock %}
-
-  <div class="side-content">
-    {% block side_content %}
-    {% endblock %}
-  </div>
-
-  {% block side_footer %}
-  {% endblock %}
-
-  <div id="footer-container" class="footer">
-    <footer class="">
-      <p>
-        <a href="https://github.com/weseek/crowi-plus">crowi-plus</a> {{ crowiVersion() }}
-        <a href="" class="pull-right" data-target="#shortcuts-modal" data-toggle="modal"><i class="fa fa-keyboard-o"></i>&nbsp;<span class="cmd-key"></span>-/</a>
-      </p>
-    </footer>
-  </div>
-</aside>
-
-{% endblock %} {# layout_sidebar #}
-
-{% block layout_main %}
-<div id="main" class="main col-md-9 {% if page %}{{ css.grant(page) }}{% endif %} {% block main_css_class %}{% endblock %}">
-  {% if page && page.grant != 1 %}
-  <p class="page-grant">
-    <i class="fa fa-lock"></i> {{ consts.pageGrants[page.grant] }} ({{ t('Browsing of this page is restricted') }})
-  </p>
-  {% endif %}
-  {% if page && page.grant == 2 %}
-  <p class="alert alert-info">
-    {{ t('Shareable Link') }}
-    <input type="text" class="copy-link form-control" value="{{ baseUrl }}/{{ page._id.toString() }}" readonly>
-  </p>
-  {% endif %}
-  <article>
-    {% block content_head %}
-    {% endblock %}
-
-    {% block content_main %}
-    //
-    {% endblock content_main %}
-
-    {% block content_footer %}
-    {% endblock %}
-  </article>
-</div>
-
-{% endblock %} {# layout_main #}

+ 5 - 1
lib/views/layout/admin.html

@@ -1,4 +1,8 @@
-{% extends 'single.html' %}
+{% extends '../layout-growi/base/layout.html' %}
+
+
+{% block main_css_class %}admin-page{% endblock %}
+
 
 
 {% block html_additional_headers %}
 {% block html_additional_headers %}
   {% parent %}
   {% parent %}

+ 129 - 112
lib/views/layout/layout.html

@@ -4,8 +4,7 @@
 <head>
 <head>
   <meta charset="utf-8">
   <meta charset="utf-8">
   <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
   <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
-
-  <title>{% block html_title %}{% endblock %} {{ config.crowi['app:title']|default('Crowi') }}</title>
+  <title>{% block html_title %}{{ path|path2name }} · {{ path }}{% endblock %} {{ config.crowi['app:title']|default('Crowi') }}</title>
   <meta name="description" content="">
   <meta name="description" content="">
   <meta name="author" content="">
   <meta name="author" content="">
 
 
@@ -13,14 +12,7 @@
 
 
   <meta name="apple-mobile-web-app-title" content="{{ config.crowi['app:title']|default('Crowi') }}">
   <meta name="apple-mobile-web-app-title" content="{{ config.crowi['app:title']|default('Crowi') }}">
 
 
-  <link rel="shortcut icon" href="/favicon.ico" type="image/x-icon" />
-  <link rel="apple-touch-icon"                 href="/apple-touch-icon.png">
-  <link rel="apple-touch-icon" sizes="72x72"   href="/apple-touch-icon-72x72.png">
-  <link rel="apple-touch-icon" sizes="120x120" href="/apple-touch-icon-120x120.png">
-  <link rel="apple-touch-icon" sizes="180x180" href="/apple-touch-icon-180x180.png">
-  <link rel="icon" type="image/png" href="/favicon-32x32.png" sizes="32x32">
-  <link rel="icon" type="image/png" href="/favicon-96x96.png" sizes="96x96">
-  <link rel="icon" type="image/png" href="/android-chrome-192x192.png" sizes="192x192">
+  {% include '../widget/favicon.html' %}
 
 
   {{ customHeader() }}
   {{ customHeader() }}
 
 
@@ -72,26 +64,41 @@ gh/highlightjs/cdn-release@9.12.0/build/languages/yaml.min.js
   {% if env === 'development' %}
   {% if env === 'development' %}
     <script src="/dll/vendor.dll.js"></script>
     <script src="/dll/vendor.dll.js"></script>
     <script src="{{ webpack_asset('dev').js }}" async></script>
     <script src="{{ webpack_asset('dev').js }}" async></script>
+    <!-- Browsersync -->
+    <script id="__bs_script__">//<![CDATA[
+      document.write("<script async src='http://HOST:3001/browser-sync/browser-sync-client.js?v=2.23.6'><\/script>".replace("HOST", location.hostname));
+    //]]></script>
   {% endif %}
   {% endif %}
 
 
-  <script src="{{ webpack_asset('style').js }}"></script>
   <script src="{{ webpack_asset('commons').js }}" defer></script>
   <script src="{{ webpack_asset('commons').js }}" defer></script>
   {% if isEnabledPlugins() %}
   {% if isEnabledPlugins() %}
-    <script src="{{ webpack_asset('plugin').js }}" defer></script>
+  <script src="{{ webpack_asset('plugin').js }}" defer></script>
   {% endif %}
   {% endif %}
   {% block html_head_loading_legacy %}
   {% block html_head_loading_legacy %}
-    <script src="{{ webpack_asset('legacy').js }}" defer></script>
+  <script src="{{ webpack_asset('legacy').js }}" defer></script>
   {% endblock %}
   {% endblock %}
+  {% block html_head_loading_app %}
   <script src="{{ webpack_asset('app').js }}" defer></script>
   <script src="{{ webpack_asset('app').js }}" defer></script>
+  {% endblock %}
+
+  <!-- styles -->
+  {% block style_css_block %}
+  <link rel="stylesheet" href="{{ webpack_asset('style').css }}">
+  <link rel="stylesheet" href="{{ webpack_asset('style-theme-' + theme()).css }}">
+  {% endblock %}
 
 
   <!-- Google Fonts -->
   <!-- Google Fonts -->
   <link href='https://fonts.googleapis.com/css?family=Lato:400,700' rel='stylesheet' type='text/css'>
   <link href='https://fonts.googleapis.com/css?family=Lato:400,700' rel='stylesheet' type='text/css'>
   <!-- Font Awesome -->
   <!-- Font Awesome -->
   <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/font-awesome@4.7.0/css/font-awesome.min.css">
   <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/font-awesome@4.7.0/css/font-awesome.min.css">
+  <!-- Themify Icons -->
+  <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/cd-themify-icons@0.0.1/index.min.css">
+  <!-- Simple Line icons -->
+  <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/simple-line-icons@2.4.1/css/simple-line-icons.min.css">
   <!-- emojione -->
   <!-- emojione -->
   <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/emojione@3.1.2/extras/css/emojione.min.css">
   <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/emojione@3.1.2/extras/css/emojione.min.css">
   <!-- highlight.js -->
   <!-- highlight.js -->
-  <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/highlight.js@9.12.0/styles/github.css">
+  <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/highlight.js@9.12.0/styles/{{ highlightJsStyle() }}.css">
 
 
   {% block html_additional_headers %}{% endblock %}
   {% block html_additional_headers %}{% endblock %}
 
 
@@ -103,117 +110,127 @@ gh/highlightjs/cdn-release@9.12.0/build/languages/yaml.min.js
 
 
 {% block html_body %}
 {% block html_body %}
 <body
 <body
-  class="crowi main-container {% block html_base_css %}{% endblock %} {% if 'crowi-plus' === layoutType() %}crowi-plus{% endif %}"
+  class="main-container content-wrapper {% block html_base_css %}{% endblock %}
+      {% if 'crowi' === layoutType() %}crowi{% endif %}
+      {% if 'crowi-plus' === layoutType() %}growi{% endif %}"
   data-me="{{ user._id.toString() }}"
   data-me="{{ user._id.toString() }}"
   data-plugin-enabled="{{ isEnabledPlugins() }}"
   data-plugin-enabled="{{ isEnabledPlugins() }}"
- {% block html_base_attr %}{% endblock %}
+  {% block html_base_attr %}{% endblock %}
   data-csrftoken="{{ csrf() }}"
   data-csrftoken="{{ csrf() }}"
   data-current-username="{% if user %}{{ user.username }}{% endif %}"
   data-current-username="{% if user %}{{ user.username }}{% endif %}"
  >
  >
 
 
-{% block layout_head_nav %}
-<nav class="crowi-header navbar navbar-default" role="navigation">
-  <!-- Brand and toggle get grouped for better mobile display -->
-  <div class="navbar-header">
-    <a class="navbar-brand" href="/">
-      <img alt="Crowi" src="/logo/32x32.png" width="16">
-      <span class="hidden-xs">{% block title %}{{ config.crowi['app:title']|default('Crowi') }}{% endblock %}</span>
-    </a>
-  {% if searchConfigured() %}
-  <div class="navbar-form navbar-left search-top" role="search" id="search-top">
-  </div>
-  {% endif %}
+<div id="wrapper">
+  <!-- Navigation -->
+  {% block layout_head_nav %}
+  <nav class="navbar navbar-default navbar-static-top m-b-0">
+    <div class="navbar-header">
+      <a class="navbar-toggle hidden-sm hidden-md hidden-lg " href="javascript:void(0)" data-toggle="collapse" data-target=".navbar-collapse">
+        <i class="ti-menu"></i>
+      </a>
+      <div class="top-left-part">
+        <a class="logo" href="/">
+          <b>
+            <div class="logo-mark">{% include '../widget/logo.html' %}</div>
+          </b>
+          <span class="hidden-xs" style="color: black">
+            {% set appTitle = config.crowi['app:title'] | default('GROWI') %}
+            {% set appTitleFontSize = getAppTitleFontSize(appTitle) %}
+            <span class="logo-text">
+              <svg xmlns="http://www.w3.org/2000/svg">
+                <text x="0" y="{{22+appTitleFontSize/2}}" font-size="{{appTitleFontSize}}">
+                  {% block title %}{{ appTitle }}{% endblock %}
+                </text>
+              </svg>
+            </span>
+          </span>
+        </a>
+      </div>
+
+      <ul class="nav navbar-top-links navbar-left hidden-xs">
+        <li>
+          <a class="open-close hidden-xs waves-effect waves-light">
+            <i class="ti-menu"></i>
+          </a>
+        </li>
+        <li>
+          {% if searchConfigured() %}
+          <div class="navbar-form navbar-left search-top" role="search" id="search-top"></div>
+          {% endif %}
+        </li>
+      </ul>
+
+      <ul class="nav navbar-top-links navbar-right pull-right">
+        {% if user and user.admin %}
+        <li id="">
+          <a href="/admin" id="link-mypage">
+            <i class="icon-settings"></i> {{ t('Admin') }}
+          </a>
+        </li>
+        {% endif %}
+
+        {% if user %}
+        <li id="" class="dropdown">
+          <a href="#" data-target="#create-page" data-toggle="modal">
+            <i class="icon-pencil"></i> {{ t('New') }}
+          </a>
+        </li>
+        <li class="dropdown">
+          <a class="dropdown-toggle waves-effect waves-light" data-toggle="dropdown">
+            <img src="{{ user|picture }}" class="picture img-circle" width="25" /> {{ user.name }}
+          </a>
+          <ul class="dropdown-menu">
+            <li><a href="/user/{{ user.username }}"><i class="icon-fw icon-home"></i>{{ t('Home') }}</a></li>
+            <li><a href="/me"><i class="icon-fw icon-wrench"></i>{{ t('User Settings') }}</a></li>
+            <li role="separator" class="divider"></li>
+            <li><a href="/trash"><i class="icon-fw icon-trash"></i>{{ t('Deleted Pages') }}</a></li>
+            <li role="separator" class="divider"></li>
+            <li><a href="/logout"><i class="icon-fw icon-power"></i>{{ t('Sign out') }}</a></li>
+          </ul>
+          <!-- /.dropdown-messages -->
+        </li>
+        {% else %}
+        <li id="login-user"><a href="/login">Login</a></li>
+        {% endif %}
+        {% if config.crowi['app:confidential'] && config.crowi['app:confidential'] != '' %}
+        <li class="confidential"><a href="#">{{ config.crowi['app:confidential'] }}</a></li>
+        {% endif %}
+      </ul>
+    </div><!-- /.navbar-header -->
+  </nav>
+  {% include '../modal/create_page.html' %}
+  {% endblock  %} {# layout_head_nav #}
+
+  {% block sidebar %}
+  <!-- Left navbar-header -->
+  <div class="navbar-default sidebar" role="navigation">
+    <div class="sidebar-nav navbar-collapse slimscrollsidebar">
+      <ul class="nav" id="side-menu">
+        <li class="sidebar-search hidden-sm hidden-md hidden-lg">
+          {% if searchConfigured() %}
+          <div class="search-sidebar" role="search" id="search-sidebar"></div>
+          {% endif %}
+        </li>
+
+        <li><a href="#">(TBD) Create /Sidebar</a></li>
+      </ul>
+    </div>
   </div>
   </div>
+  <!-- Left navbar-header end -->
+  {% endblock %}
 
 
+  <!-- Page Content -->
+  <div id="page-wrapper">
+    {% block layout_main %}
+    {% endblock %} {# layout_main #}
+  </div><!-- /#page-wrapper -->
 
 
-  <button type="button" class="navbar-toggle" data-toggle="collapse" data-target="#navbarCollapse">
-    <span class="sr-only">Toggle navigation</span>
-    <span class="icon-bar"></span>
-    <span class="icon-bar"></span>
-    <span class="icon-bar"></span>
-  </button>
-  <!-- Collect the nav links, forms, and other content for toggling -->
-  <div class="collapse navbar-collapse" id="navbarCollapse">
-
-    <ul class="nav navbar-nav navbar-right">
-
-      {% if user and user.admin %}
-      <li id="">
-        <a href="/admin" id="link-mypage">
-          <i class="fa fa-cube"></i> {{ t('Admin') }}
-        </a>
-      </li>
-      {% endif %}
-      {#
-      <li id="">
-        <a href="#" id="createPage">
-          <i class="fa fa-plus"> 新規</i>
-        </a>
-      </li>
-      #}
-      {% if user %}
-      {#
-      <li id="" class="notif">
-        <a href="" id="notif-opener">
-          <i class="fa fa-globe"></i> <span class="badge badge-danger">6</span>
-        </a>
-      </li>
-      #}
-      <li id="" class="dropdown">
-        <button class="btn btn-default create-page-button" data-target="#create-page" data-toggle="modal">
-          <i class="fa fa-pencil"></i> {{ t('New') }}
-        </button>
-      </li>
-      <li id="login-user">
-        <a href="/user/{{ user.username }}" id="link-mypage">
-          <img src="{{ user|picture }}" class="picture picture-rounded" width="25" /> {{ user.name }}
-        </a>
-      </li>
-      <li class="dropdown">
-        <a href="#" class="dropdown-toggle" data-toggle="dropdown"><i class="fa fa-bars"></i> <label class="sr-only">メニュー</label></a>
-        <ul class="dropdown-menu">
-          <li><a href="/me"><i class="fa fa-gears"></i> {{ t('User Settings') }}</a></li>
-          <li class="divider"></li>
-          <li><a href="/trash/"><i class="fa fa-trash-o"></i> {{ t('Deleted Pages') }}</a></li>
-          <li class="divider"></li>
-          <li><a href="/logout"><i class="fa fa-sign-out"></i> {{ t('Sign out') }}</a></li>
-          {# <li><a href="#">今日の日報を作成</a></li> #}
-          {# <li class="divider"></li> #}
-          {# <li class="divider"></li> #}
-          {# <li><a href="#">ログアウト</a></li> #}
-        </ul>
-      </li>
-      {% else %}
-      <li id="login-user"><a href="/login"><i class="fa fa-user"></i> Login</a></li>
-      {% endif %}
-      {% if config.crowi['app:confidential'] && config.crowi['app:confidential'] != '' %}
-      <li class="confidential"><a href="#">{{ config.crowi['app:confidential'] }}</a></li>
-      {% endif %}
-    </ul>
-  </div><!-- /.navbar-collapse -->
-</nav>
-{% include '../modal/create_page.html' %}
-{% endblock  %} {# layout_head_nav #}
-
-<div class="container-fluid">
-  <div class="row">
-
-  {% block layout_sidebar %}
-  {% endblock %} {# layout_sidebar #}
-
-  {% block layout_main %}
-  {% endblock %} {# layout_main #}
-
-{% block footer %}
-{% endblock %}
+</div><!-- /#wrapper -->
 
 
-  </div> {# /.row #}
-</div> {# /.container-fluid #}
+{% include '../modal/shortcuts.html' %}
 
 
 {% block body_end %}
 {% block body_end %}
 {% endblock %}
 {% endblock %}
-
-{% include '../modal/shortcuts.html' %}
 </body>
 </body>
 {% endblock %}
 {% endblock %}
 
 

+ 0 - 22
lib/views/layout/single-nologin.html

@@ -1,22 +0,0 @@
-{% extends 'layout.html' %}
-
-{% block html_base_css %}single nologin{% endblock %}
-
-{% block layout_head_nav %}
-{% endblock  %} {# layout_head_nav #}
-
-{% block layout_sidebar %}
-{% endblock  %} {# layout_sidebar  #}
-
-{% block layout_main %}
-
-  {% block content_head %}
-  {% endblock %}
-
-  {% block content_main %}
-  {% endblock content_main %}
-
-  {% block content_footer %}
-  {% endblock %}
-
-{% endblock %} {# layout_main #}

+ 0 - 45
lib/views/layout/single.html

@@ -1,45 +0,0 @@
-{% extends 'layout.html' %}
-
-{% block layout_main %}
-<div id="main" class="main col-md-12">
-  <article>
-    {% block content_head %}
-    {% endblock %}
-
-    {% block content_main %}
-    {% endblock content_main %}
-
-    {% block content_footer %}
-    {% endblock %}
-  </article>
-</div>
-
-{% endblock %} {# layout_main #}
-
-{% block footer %}
-{% parent %}
-<div class="system-version">
-  <span>
-    <a href="https://github.com/weseek/crowi-plus">crowi-plus</a> {{ crowiVersion() }}
-  </span>
-  <span>
-    <a href="" data-target="#shortcuts-modal" data-toggle="modal"><i class="fa fa-keyboard-o"></i>&nbsp;<span class="cmd-key"></span>-/</a>
-  </span>
-</div>
-<script>
-  /*
-  * add classes to cmd-key by OS
-  */
-  var platform = navigator.platform.toLowerCase();
-  var isMac = (platform.indexOf('mac') > -1);
-
-  document.querySelectorAll('.system-version .cmd-key').forEach((element) => {
-    if (isMac) {
-      element.classList.add('mac');
-    }
-    else {
-      element.classList.add('win', 'key-longer');
-    }
-  })
-</script>
-{% endblock %}

+ 252 - 205
lib/views/login.html

@@ -1,241 +1,288 @@
-{% extends 'layout/single-nologin.html' %}
+{% extends 'layout/layout.html' %}
+
+{% block html_base_css %}login-page nologin{% endblock %}
 
 
 {% block html_title %}{{ t('Sign in') }} · {% endblock %}
 {% block html_title %}{{ t('Sign in') }} · {% endblock %}
 
 
-{% block content_main %}
 
 
-<h1 class="login-page">
-  {% if config.crowi['app:title'] == 'Crowi' %}
-    <img src="/logo/135x32.png" alt="Crowi">
-  {% else %}
-    {{ config.crowi['app:title'] }}<br>
-    <img src="/logo/100x11_w.png" alt="powered by Crowi">
-  {% endif %}
-</h1>
 
 
-<div class="login-dialog-container flip-container col-md-5">
+{#
+ # Remove default contents
+ #}
+{% block html_head_loading_legacy %}
+{% endblock %}
+{% block html_head_loading_app %}
+{% endblock %}
+{% block layout_head_nav %}
+{% endblock %}
+{% block sidebar %}
+{% endblock %}
 
 
-<div class="login-dialog flipper {% if req.query.register or req.body.registerForm or isRegistering or googleId %}to-flip{% endif %}" id="login-dialog">
 
 
-  <div class="login-dialog-inner front">
-    <h2>{{ t('Sign in') }}</h2>
 
 
-    <div id="login-form-errors">
-      {% if isLdapSetupFailed() %}
-      <div class="alert alert-warning">
-        LDAP is enabled but the configuration has something wrong.<br>
-        <small>(set the environment variables <code>DEBUG=crowi:service:PassportService</code> and get the logs)</small>
-      </div>
-      {% endif %}
-
-      {#
-       # The case that there already exists a user whose username matches ID of the newly created LDAP user
-       # https://github.com/weseek/crowi-plus/issues/193
-       #}
-      {% set isDuplicatedUsernameExceptionOccured = req.flash('isDuplicatedUsernameExceptionOccured') %}
-      {% if isDuplicatedUsernameExceptionOccured != null %}
-      <div class="alert alert-warning">
-        <i class="fa fa-fw fa-info-circle"></i>
-        <strong>DuplicatedUsernameException occured</strong>
-        <p>
-          Your LDAP authentication was succeess, but a new user could not be created.
-          See the issue <a href="https://github.com/weseek/crowi-plus/issues/193">#193</a>.
-        </p>
-      </div>
-      {% endif %}
+{% block layout_main %}
 
 
-      {% set success = req.flash('successMessage') %}
-      {% if success.length %}
-      <div class="alert alert-success">
-        {{ success }}
-      </div>
-      {% endif %}
+<div class="main container-fluid">
 
 
-      {% set warn = req.flash('warningMessage') %}
-      {% if warn.length %}
-      {% for w in warn %}
-      <div class="alert alert-warning">
-        {{ w }}
-      </div>
-      {% endfor %}
-      {% endif %}
-
-      {% set error = req.flash('errorMessage') %}
-      {% if error.length %}
-      {% for e in error %}
-      <div class="alert alert-danger">
-        {{ e }}
-      </div>
-      {% endfor %}
-      {% endif %}
-
-      {% if req.form.errors.length > 0 %}
-      <div class="alert alert-danger">
-        <ul>
-        {% for error in req.form.errors %}
-          <li>{{ error }}</li>
-        {% endfor %}
-        </ul>
-      </div>
-      {% endif %}
-    </div>
-    <form role="form" action="/login" method="post">
-      <div class="input-group">
-        <span class="input-group-addon"><i class="fa fa-fw fa-user"></i></span>
-        <input type="text" class="form-control" placeholder="Username or E-mail" name="loginForm[username]">
-        {% if isLdapSetup() %}
-        <span class="input-group-addon">
-          <small class="text-primary">
-            <i class="fa fa-fw fa-check-circle"></i> LDAP
-          </small>
-        </span>
+  <div class="row">
+    <div class="login-header col-sm-offset-4 col-sm-4">
+      <div class="logo">{% include 'widget/logo.html' %}</div>
+      <h1>
+        {{ config.crowi['app:title'] || 'GROWI' }}
+      </h1>
+
+      <div class="login-form-errors">
+        {% if isLdapSetupFailed() %}
+        <div class="alert alert-warning small">
+          <strong><i class="icon-fw icon-info"></i>LDAP is enabled but the configuration has something wrong.</strong>
+          <br>
+          (Please set the environment variables <code>DEBUG=crowi:service:PassportService</code> to get the logs)
+        </div>
         {% endif %}
         {% endif %}
-      </div>
 
 
-      <div class="input-group">
-        <span class="input-group-addon"><i class="fa fa-fw fa-key"></i></span>
-        <input type="password" class="form-control" placeholder="Password" name="loginForm[password]">
-      </div>
+        {#
+        # The case that there already exists a user whose username matches ID of the newly created LDAP user
+        # https://github.com/weseek/crowi-plus/issues/193
+        #}
+        {% set isDuplicatedUsernameExceptionOccured = req.flash('isDuplicatedUsernameExceptionOccured') %}
+        {% if isDuplicatedUsernameExceptionOccured != null %}
+        <div class="alert alert-warning small">
+          <p><strong><i class="icon-fw icon-ban"></i>DuplicatedUsernameException occured</strong></p>
+          <p>
+            Your LDAP authentication was succeess, but a new user could not be created.
+            See the issue <a href="https://github.com/weseek/crowi-plus/issues/193">#193</a>.
+          </p>
+        </div>
+        {% endif %}
 
 
-      <input type="hidden" name="_csrf" value="{{ csrf() }}">
-      <input type="submit" class="btn btn-primary btn-lg btn-block" value="{{ t('Sign in') }}">
-    </form>
+        {% set success = req.flash('successMessage') %}
+        {% if success.length %}
+        <div class="alert alert-success">
+          {{ success }}
+        </div>
+        {% endif %}
 
 
-    <hr>
+        {% set warn = req.flash('warningMessage') %}
+        {% if warn.length %}
+        {% for w in warn %}
+        <div class="alert alert-warning">
+          {{ w }}
+        </div>
+        {% endfor %}
+        {% endif %}
 
 
-    <div class="row">
-      {% if googleLoginEnabled() %}
-      <div class="col-md-8">
-        <p>{{ t('Sign in by Google Account') }}</p>
-        <form role="form" action="/login/google" method="get">
-          <button type="submit" class="btn btn-block btn-google"><i class="fa fa-google-plus-square"></i> {{ t('Sign in') }}</button>
-          <input type="hidden" name="_csrf" value="{{ csrf() }}">
-        </form>
+        {% set error = req.flash('errorMessage') %}
+        {% if error.length %}
+        {% for e in error %}
+        <div class="alert alert-danger">
+          {{ e }}
+        </div>
+        {% endfor %}
+        {% endif %}
+
+        {% if req.form.errors.length > 0 %}
+        <div class="alert alert-danger">
+          <ul>
+          {% for error in req.form.errors %}
+            <li>{{ error }}</li>
+          {% endfor %}
+          </ul>
+        </div>
+        {% endif %}
+      </div>
+      <div id="register-form-errors">
+        {% set message = req.flash('registerWarningMessage') %}
+        {% if message.length %}
+        <div class="alert alert-danger">
+          {% for msg in message %}
+          {{ msg }}<br>
+          {% endfor  %}
+        </div>
+        {% endif %}
       </div>
       </div>
-      {% endif %}
     </div>
     </div>
 
 
-    {% if config.crowi['security:registrationMode'] != 'Closed' %}
-    <p class="bottom-text"><a href="#register" id="register"><i class="fa fa-pencil"></i> {{ t('Sign up is here') }}</a></p>
-    {% endif %}
-  </div>
+    <div class="login-dialog p-b-10 col-sm-offset-4 col-sm-4 flipper {% if req.query.register or req.body.registerForm or isRegistering or googleId %}to-flip{% endif %}" id="login-dialog">
+
+      <div class="front">
+        <form role="form" action="/login" method="post">
+          <div class="input-group">
+            <span class="input-group-addon"><i class="icon-user"></i></span>
+            <input type="text" class="form-control" placeholder="Username or E-mail" name="loginForm[username]">
+            {% if isLdapSetup() %}
+            <span class="input-group-addon">
+              <small class="text-success">
+                <i class="icon-fw icon-check"></i> LDAP
+              </small>
+            </span>
+            {% endif %}
+          </div>
+
+          <div class="input-group">
+            <span class="input-group-addon"><i class="icon-lock"></i></span>
+            <input type="password" class="form-control" placeholder="Password" name="loginForm[password]">
+          </div>
+
+          <div class="input-group m-t-30 m-b-20 d-flex justify-content-center">
+            <input type="hidden" name="_csrf" value="{{ csrf() }}">
+            <button type="submit" class="fcbtn btn btn-danger btn-1b btn-login">
+              <span class="btn-label"><i class="icon-login"></i></span>
+              {{ t('Sign in') }}
+            </button>
+          </div>
+        </form>
 
 
-  {% if config.crowi['security:registrationMode'] != 'Closed' %}
-  <div class="register-dialog-inner back">
-
-    <h2>{{ t('Sign up') }}</h2>
-
-    {% if config.crowi['security:registrationMode'] == 'Restricted' %}
-    <p class="alert alert-warning">
-      {{ t('page_register.notice.restricted') }}<br>
-      {{ t('page_register.notice.restricted_defail') }}
-    </p>
-    {% endif %}
-
-    {% if googleId %}
-    <div class="google-info alert alert-info">
-      {% if googleImage %}
-      <p class="text-center">
-        <img src="{{ googleImage }}" class="picture picture-rounded picture-lg">
-      </p>
-      {% endif %}
-      <code>{{ googleEmail }}</code> {{ t('page_register with this Google Account') }}<br>
-      {{ t('page_register.notice.google_account_continue') }}
-    </div>
-    {% endif %}
-
-    <div id="register-form-errors">
-      {% set message = req.flash('registerWarningMessage') %}
-      {% if message.length %}
-      <div class="alert alert-danger">
-        {% for msg in message %}
-        {{ msg }}<br>
-        {% endfor  %}
-      </div>
-      {% endif %}
+        {% if googleLoginEnabled() %}
+        <hr>
+
+        <div class="input-group m-t-15 m-b-10 mx-auto">
+          <form role="form" action="/login/google" method="get">
+            <input type="hidden" name="_csrf" value="{{ csrf() }}">
+            <button type="submit" class="fcbtn btn btn-danger btn-1b btn-login-google">
+              <span class="btn-label"><i class="icon-social-google"></i></span>
+              {{ t('Sign in') }}
+            </button>
+            <div class="small text-right">by Google Account</div>
+          </form>
+        </div>
+        {% endif %}
 
 
-      {% if req.form.errors.length > 0 %}
-      <div class="alert alert-danger">
-        <ul>
-        {% for error in req.form.errors %}
-          <li>{{ error }}</li>
-        {% endfor %}
-        </ul>
+        <hr>
+
+        {% if config.crowi['security:registrationMode'] != 'Closed' %}
+        <div class="row">
+          <div class="col-xs-12 text-right">
+            <a href="#register" id="register" class="link-switch">
+              <i class="ti-check-box"></i> {{ t('Sign up is here') }}
+            </a>
+          </div>
+        </div>
+        {% endif %}
       </div>
       </div>
-      {% endif %}
-    </div>
 
 
-    <form role="form" method="post" action="/register" id="register-form">
-      <input type="hidden" class="form-control" name="registerForm[googleId]" value="{{ googleId|default(req.body.registerForm.googleId) }}">
 
 
-      <label>{{ t('User ID') }}</label>
-      <div class="input-group" id="input-group-username">
-        <span class="input-group-addon"><strong>@</strong></span>
-        <input type="text" class="form-control" placeholder="{{ t('Example') }}: taroyama" name="registerForm[username]" value="{{ req.body.registerForm.username }}" required>
-      </div>
-      <p class="help-block">
-      <span id="help-block-username" class="text-danger"></span>
-      {{ t('page_register.form_help.user_id') }}
-      </p>
-
-      <label>{{ t('Name') }}</label>
-      <div class="input-group">
-        <span class="input-group-addon"><i class="fa fa-user"></i></span>
-        <input type="text" class="form-control" placeholder="{{ t('Example') }}: {{ t('Taro Yamada') }}" name="registerForm[name]" value="{{ googleName|default(req.body.registerForm.name) }}" required>
-      </div>
+      {% if config.crowi['security:registrationMode'] != 'Closed' %}
+      <div class="back">
+        {% if config.crowi['security:registrationMode'] == 'Restricted' %}
+        <p class="alert alert-warning">
+          {{ t('page_register.notice.restricted') }}<br>
+          {{ t('page_register.notice.restricted_defail') }}
+        </p>
+        {% endif %}
 
 
-      <label>{{ t('Email') }}</label>
-      <div class="input-group">
-        <span class="input-group-addon"><i class="fa fa-envelope"></i></span>
-        <input type="email" class="form-control" placeholder="E-mail" name="registerForm[email]" value="{{ googleEmail|default(req.body.registerForm.email) }}" required>
-      </div>
-      {% if config.crowi['security:registrationWhiteList'] && config.crowi['security:registrationWhiteList'].length %}
-      <p class="help-block">
-        {{ t('page_register.form_help.email') }}
-      </p>
-      <ul>
-        {% for em in config.crowi['security:registrationWhiteList'] %}
-        <li><code>{{ em }}</code></li>
-        {% endfor %}
-      </ul>
-      {% endif %}
+        {% if googleId %}
+        <div class="google-info alert alert-info">
+          {% if googleImage %}
+          <p class="text-center">
+            <img src="{{ googleImage }}" class="img-circle img-circle-lg">
+          </p>
+          {% endif %}
+          <code>{{ googleEmail }}</code> {{ t('page_register with this Google Account') }}<br>
+          {{ t('page_register.notice.google_account_continue') }}
+        </div>
+        {% endif %}
 
 
-      <label>{{ t('Password') }}</label>
-      <div class="input-group">
-        <span class="input-group-addon"><i class="fa fa-key"></i></span>
-        <input type="password" class="form-control" placeholder="Password" name="registerForm[password]" required>
-      </div>
-      <p class="help-block">
-        {{ t('page_register.form_help.password') }}
-      </p>
-
-      {% if googleImage %}
-        <input type="hidden" name="registerForm[googleImage]" value="{{ googleImage }}">
-      {% endif  %}
-      <input type="hidden" name="_csrf" value="{{ csrf() }}">
-      <input type="submit" class="btn btn-primary btn-lg btn-block" value="{{ t('Sign up') }}">
-    </form>
-
-    <hr>
-
-    <div class="row">
-      {% if googleLoginEnabled() %}
-      <div class="col-md-6">
-        <p>{{ t('Sign up with Google Account') }}</p>
-        <form role="form" method="post" action="/register/google">
+        <form role="form" method="post" action="/register" id="register-form">
+          <input type="hidden" class="form-control" name="registerForm[googleId]" value="{{ googleId|default(req.body.registerForm.googleId) }}">
+
+          <div class="input-group" id="input-group-username">
+            <span class="input-group-addon"><i class="icon-user"></i></span>
+            <input type="text" class="form-control" placeholder="{{ t('User ID') }}" name="registerForm[username]" value="{{ req.body.registerForm.username }}" required>
+          </div>
+          <p class="help-block">
+            <span id="help-block-username"></span>
+          </p>
+
+          <div class="input-group">
+            <span class="input-group-addon"><i class="icon-tag"></i></span>
+            <input type="text" class="form-control" placeholder="{{ t('Name') }}" name="registerForm[name]" value="{{ googleName|default(req.body.registerForm.name) }}" required>
+          </div>
+
+          <div class="input-group">
+            <span class="input-group-addon"><i class="icon-envelope"></i></span>
+            <input type="email" class="form-control" placeholder="{{ t('Email') }}" name="registerForm[email]" value="{{ googleEmail|default(req.body.registerForm.email) }}" required>
+          </div>
+          {% if config.crowi['security:registrationWhiteList'] && config.crowi['security:registrationWhiteList'].length %}
+          <p class="help-block">
+            {{ t('page_register.form_help.email') }}
+          </p>
+          <ul>
+            {% for em in config.crowi['security:registrationWhiteList'] %}
+            <li><code>{{ em }}</code></li>
+            {% endfor %}
+          </ul>
+          {% endif %}
+
+          <div class="input-group">
+            <span class="input-group-addon"><i class="icon-lock"></i></span>
+            <input type="password" class="form-control" placeholder="{{ t('Password') }}" name="registerForm[password]" required>
+          </div>
+
+          {% if googleImage %}
+            <input type="hidden" name="registerForm[googleImage]" value="{{ googleImage }}">
+          {% endif  %}
           <input type="hidden" name="_csrf" value="{{ csrf() }}">
           <input type="hidden" name="_csrf" value="{{ csrf() }}">
-          <button type="submit" class="btn btn-block btn-google"><i class="fa fa-google-plus-square"></i> {{ t('Login') }}</button>
+
+          <div class="input-group m-t-30 m-b-20 d-flex justify-content-center">
+            <button type="submit" class="fcbtn btn btn-success btn-1b btn-register">
+              <span class="btn-label"><i class="icon-user-follow"></i></span>
+              {{ t('Sign up') }}
+            </button>
+          </div>
         </form>
         </form>
+
+        <hr>
+
+        <div class="row">
+          <div class="col-xs-12 text-right">
+            <a href="#login" id="login" class="link-switch">
+              <i class="icon-fw icon-login"></i>{{ t('Sign in is here') }}
+            </a>
+          </div>
+        </div>
       </div>
       </div>
-      {% endif %}
+      {% endif %} {# if registrationMode == Closed #}
+
+      <a href="https://growi.org" class="link-growi-org">
+        <span class="growi">GROWI</span>.<span class="org">ORG
+      </a>
+
     </div>
     </div>
 
 
-    <p class="bottom-text"><a href="#login" id="login"><i class="fa fa-sign-out"></i> {{ t('Sign in is here') }}</a></p>
   </div>
   </div>
-  {% endif %} {# if registrationMode == Closed #}
 
 
 </div>
 </div>
 
 
-</div>
+{% endblock %}
+
 
 
+{% block body_end %}
+<script>
+  // login
+  $('#register').on('click', function() {
+    $('#login-dialog').addClass('to-flip');
+    return false;
+  });
+  $('#login').on('click', function() {
+    $('#login-dialog').removeClass('to-flip');
+    return false;
+  });
+
+  $('#register-form input[name="registerForm[username]"]').change(function(e) {
+    var username = $(this).val();
+    $('#login-dialog').removeClass('has-error');
+    $('#input-group-username').removeClass('has-error');
+    $('#help-block-username').html("");
+
+    $.getJSON('/_api/check_username', {username: username}, function(json) {
+      if (!json.valid) {
+        $('#help-block-username').html(
+          '<i class="icon-fw icon-ban"></i> This User ID is not available.'
+        );
+        $('#login-dialog').addClass('has-error');
+        $('#input-group-username').addClass('has-error');
+      }
+    });
+  });
+</script>
 {% endblock %}
 {% endblock %}

+ 35 - 38
lib/views/login/error.html

@@ -1,56 +1,53 @@
-{% extends '../layout/single-nologin.html' %}
+{% extends '../layout/layout.html' %}
 
 
-{% block html_title %}Error · {% endblock %}
+{% block html_base_css %}error nologin{% endblock %}
 
 
-{% block content_main %}
+{% block html_title %}セットアップ {% endblock %}
 
 
-<h1 class="login-page">
-  {% if config.crowi['app:title'] == 'Crowi' %}
-    <img src="/logo/135x32.png" alt="Crowi">
-  {% else %}
-    {{ config.crowi['app:title'] }}<br>
-    <img src="/logo/100x11_w.png" alt="powered by Crowi">
-  {% endif %}
-</h1>
 
 
-<div class="login-dialog-container flip-container col-md-5">
 
 
-<div class="login-dialog" id="login-dialog">
+{#
+ # Remove default contents
+ #}
+{% block html_head_loading_legacy %}
+{% endblock %}
+{% block html_head_loading_app %}
+{% endblock %}
+{% block layout_head_nav %}
+{% endblock %}
+{% block sidebar %}
+{% endblock %}
 
 
-  <div class="login-dialog-inner front">
-    {% if reason === 'registered'%}
 
 
-      <h2>登録完了</h2>
 
 
-      <p class="text-center">
-        <i class="fa fa-smile-o fa-3x"></i>
-      </p>
-      <hr>
-      <div class="alert alert-info text-center">
-        {{ reasonMessage }}
-      </div>
+{% block layout_main %}
+
+<div class="main container-fluid">
 
 
-    {% else %}
+  <div class="row">
 
 
-      <h2>ログインエラー</h2>
+    <div class="login-header col-sm-offset-4 col-sm-4">
+      <div class="logo">{% include '../widget/logo.html' %}</div>
+      <h1>GROWI</h1>
 
 
-      <p class="text-center">
-        <i class="fa fa-meh-o fa-3x"></i>
-      </p>
-      <hr>
-      {% if reasonMessage != '' %}
-      <div class="alert alert-danger text-center">
-        {{ reasonMessage }}
+      <div class="m-b-15 login-form-errors text-center">
+        {% if reason === 'registered'%}
+        <div class="alert alert-success">
+          <h2>登録完了</h2>
+        </div>
+        {% else %}
+        <div class="alert alert-warning">
+            <h2>ログインエラー</h2>
+        </div>
+        {% endif %}
       </div>
       </div>
-      {% endif %}
 
 
-    {% endif %}
+      <p>{{ reasonMessage }}</p>
+    </div>
 
 
-  </div>
 
 
-</div>
+  </div>{# /.row #}
 
 
-</div>
+</div>{# /.main #}
 
 
 {% endblock %}
 {% endblock %}
-

+ 12 - 10
lib/views/me/api_token.html

@@ -1,12 +1,12 @@
-{% extends '../layout/2column.html' %}
+{% extends '../layout-growi/base/layout.html' %}
 
 
 
 
 {% block html_title %}{{ t('API Settings') }} · {{ path }}{% endblock %}
 {% block html_title %}{{ t('API Settings') }} · {{ path }}{% endblock %}
 
 
-{% block content_head %}
+{% block content_header %}
 <div class="header-wrap">
 <div class="header-wrap">
   <header id="page-header">
   <header id="page-header">
-  <h1 class="title" id="">{{ t('User Settings') }}</h1>
+  <h1 class="title" id="">{{ t('API Settings') }}</h1>
   </header>
   </header>
 </div>
 </div>
 {% endblock %}
 {% endblock %}
@@ -15,10 +15,12 @@
 <div class="content-main">
 <div class="content-main">
 
 
   <ul class="nav nav-tabs">
   <ul class="nav nav-tabs">
-    <li><a href="/me"><i class="fa fa-gears"></i> {{ t('User Information') }}</a></li>
-    <li><a href="/me/external-accounts"><i class="fa fa-user-plus"></i> {{ t('External Accounts') }}</a></li>
-    <li><a href="/me/password"><i class="fa fa-key"></i> {{ t('Password Settings') }}</a></li>
-    <li class="active"><a href="/me/apiToken"><i class="fa fa-rocket"></i> {{ t('API Settings') }}</a></li>
+    <li><a href="/me"><i class="icon-user"></i> {{ t('User Information') }}</a></li>
+    {% if isEnabledPassport() %}
+    <li><a href="/me/external-accounts"><i class="icon-share-alt"></i> {{ t('External Accounts') }}</a></li>
+    {% endif %}
+    <li><a href="/me/password"><i class="icon-lock"></i> {{ t('Password Settings') }}</a></li>
+    <li class="active"><a href="/me/apiToken"><i class="icon-paper-plane"></i> {{ t('API Settings') }}</a></li>
   </ul>
   </ul>
 
 
   <div class="tab-content">
   <div class="tab-content">
@@ -40,7 +42,7 @@
   </div>
   </div>
   {% endif %}
   {% endif %}
 
 
-  <div id="form-box">
+  <div class="form-box m-t-20">
 
 
     <form action="/me/apiToken" method="post" class="form-horizontal" role="form">
     <form action="/me/apiToken" method="post" class="form-horizontal" role="form">
     <fieldset>
     <fieldset>
@@ -59,7 +61,7 @@
       </div>
       </div>
 
 
       <div class="form-group">
       <div class="form-group">
-        <div class="col-xs-offset-3 col-xs-10">
+        <div class="col-xs-offset-3 col-xs-9">
 
 
           <p class="alert alert-warning">
           <p class="alert alert-warning">
             {{ t('page_me_apitoken.notice.update_token1') }}<br>
             {{ t('page_me_apitoken.notice.update_token1') }}<br>
@@ -82,5 +84,5 @@
 {% block content_footer %}
 {% block content_footer %}
 {% endblock %}
 {% endblock %}
 
 
-{% block footer %}
+{% block layout_footer %}
 {% endblock %}
 {% endblock %}

+ 21 - 21
lib/views/me/external-accounts.html

@@ -1,11 +1,11 @@
-{% extends '../layout/2column.html' %}
+{% extends '../layout-growi/base/layout.html' %}
 
 
 {% block html_title %}{{ t('Password Settings') }} · {{ path }}{% endblock %}
 {% block html_title %}{{ t('Password Settings') }} · {{ path }}{% endblock %}
 
 
-{% block content_head %}
+{% block content_header %}
 <div class="header-wrap">
 <div class="header-wrap">
   <header id="page-header">
   <header id="page-header">
-    <h1 class="title" id="">{{ t('User Settings') }}</h1>
+    <h1 class="title" id="">{{ t('Password Settings') }}</h1>
   </header>
   </header>
 </div>
 </div>
 {% endblock %}
 {% endblock %}
@@ -14,10 +14,10 @@
 <div class="content-main">
 <div class="content-main">
 
 
   <ul class="nav nav-tabs">
   <ul class="nav nav-tabs">
-    <li><a href="/me"><i class="fa fa-gears"></i> {{ t('User Information') }}</a></li>
-    <li class="active"><a href="/me/external-accounts"><i class="fa fa-user-plus"></i> {{ t('External Accounts') }}</a></li>
-    <li><a href="/me/password"><i class="fa fa-key"></i> {{ t('Password Settings') }}</a></li>
-    <li><a href="/me/apiToken"><i class="fa fa-rocket"></i> {{ t('API Settings') }}</a></li>
+    <li><a href="/me"><i class="icon-user"></i> {{ t('User Information') }}</a></li>
+    <li class="active"><a href="/me/external-accounts"><i class="icon-share-alt"></i> {{ t('External Accounts') }}</a></li>
+    <li><a href="/me/password"><i class="icon-lock"></i> {{ t('Password Settings') }}</a></li>
+    <li><a href="/me/apiToken"><i class="icon-paper-plane"></i> {{ t('API Settings') }}</a></li>
   </ul>
   </ul>
 
 
   <div class="tab-content">
   <div class="tab-content">
@@ -58,9 +58,9 @@
 
 
 
 
 
 
-  <legend style="line-height: 1.7em;">
+  <legend class="m-t-20" style="line-height: 1.7em;">
     <button class="btn btn-default btn-sm pull-right" data-target="#create-external-account" data-toggle="modal">
     <button class="btn btn-default btn-sm pull-right" data-target="#create-external-account" data-toggle="modal">
-      <i class="fa fa-plus-circle" aria-hidden="true"></i>
+      <i class="icon-plus" aria-hidden="true"></i>
       Add
       Add
     </button>
     </button>
     {{ t('External Accounts') }}
     {{ t('External Accounts') }}
@@ -68,7 +68,7 @@
 
 
   <div class="row">
   <div class="row">
     <div class="col-md-12">
     <div class="col-md-12">
-      <table class="table table-hover table-striped table-bordered table-user-list">
+      <table class="table table-bordered table-user-list">
         <thead>
         <thead>
           <tr>
           <tr>
             <th width="120px">Authentication Provider</th>
             <th width="120px">Authentication Provider</th>
@@ -111,37 +111,37 @@
     <div class="modal-dialog">
     <div class="modal-dialog">
       <div class="modal-content">
       <div class="modal-content">
 
 
-        <div class="modal-header">
+        <div class="modal-header bg-info">
           <button type="button" class="close" data-dismiss="modal" aria-hidden="true">&times;</button>
           <button type="button" class="close" data-dismiss="modal" aria-hidden="true">&times;</button>
-          <h4 class="modal-title">{{ t('Create External Account') }}</h4>
+          <div class="modal-title">{{ t('Create External Account') }}</div>
         </div>
         </div>
 
 
         <div class="modal-body">
         <div class="modal-body">
 
 
           <ul class="nav nav-tabs passport-settings" role="tablist">
           <ul class="nav nav-tabs passport-settings" role="tablist">
             <li class="active">
             <li class="active">
-              <a href="#passport-ldap" data-toggle="tab" role="tab"><i class="fa fa-sitemap"></i> LDAP</a>
+              <a href="#passport-ldap" data-toggle="tab" role="tab"><i class="icon-organization"></i> LDAP</a>
             </li>
             </li>
             <li>
             <li>
-              <a href="#passport-google-oauth" data-toggle="tab" role="tab"><i class="fa fa-google"></i> Google OAuth</a>
+              <a href="#passport-google-oauth" data-toggle="tab" role="tab"><i class="icon-social-google"></i> Google OAuth</a>
             </li>
             </li>
             <li>
             <li>
-              <a href="#passport-facebook" data-toggle="tab" role="tab"><i class="fa fa-facebook"></i> Facebook</a>
+              <a href="#passport-facebook" data-toggle="tab" role="tab"><i class="icon-social-facebook"></i> Facebook</a>
             </li>
             </li>
             <li>
             <li>
-              <a href="#passport-twitter" data-toggle="tab" role="tab"><i class="fa fa-twitter"></i> Twitter</a>
+              <a href="#passport-twitter" data-toggle="tab" role="tab"><i class="icon-social-twitter"></i> Twitter</a>
             </li>
             </li>
             <li>
             <li>
-              <a href="#passport-github" data-toggle="tab" role="tab"><i class="fa fa-github"></i> Github</a>
+              <a href="#passport-github" data-toggle="tab" role="tab"><i class="icon-social-github"></i> Github</a>
             </li>
             </li>
           </ul>
           </ul>
 
 
-          <div class="tab-content passport-settings">
+          <div class="tab-content passport-settings m-t-15">
             <div id="passport-ldap" class="tab-pane active" role="tabpanel" >
             <div id="passport-ldap" class="tab-pane active" role="tabpanel" >
               <div id="formLdapAssociationContainer">
               <div id="formLdapAssociationContainer">
                 {% include '../widget/passport/ldap-association-tester.html' %}
                 {% include '../widget/passport/ldap-association-tester.html' %}
                 <div class="clearfix">
                 <div class="clearfix">
-                  <button type="button" class="btn btn-primary pull-right" onclick="associateLdap()">
+                  <button type="button" class="btn btn-info pull-right" onclick="associateLdap()">
                     <i class="fa fa-plus-circle" aria-hidden="true"></i>
                     <i class="fa fa-plus-circle" aria-hidden="true"></i>
                     {{ t('Add') }}
                     {{ t('Add') }}
                   </button>
                   </button>
@@ -192,7 +192,7 @@
 
 
         <div class="modal-header">
         <div class="modal-header">
           <button type="button" class="close" data-dismiss="modal" aria-hidden="true">&times;</button>
           <button type="button" class="close" data-dismiss="modal" aria-hidden="true">&times;</button>
-          <h4 class="modal-title">{{ t('Diassociate External Account') }}</h4>
+          <div class="modal-title">{{ t('Diassociate External Account') }}</div>
         </div>
         </div>
 
 
         <div class="modal-body">
         <div class="modal-body">
@@ -247,5 +247,5 @@
 {% block content_footer %}
 {% block content_footer %}
 {% endblock %}
 {% endblock %}
 
 
-{% block footer %}
+{% block layout_footer %}
 {% endblock %}
 {% endblock %}

+ 63 - 75
lib/views/me/index.html

@@ -1,8 +1,8 @@
-{% extends '../layout/2column.html' %}
+{% extends '../layout-growi/base/layout.html' %}
 
 
 {% block html_title %}{{ t('User Settings') }} · {{ path }}{% endblock %}
 {% block html_title %}{{ t('User Settings') }} · {{ path }}{% endblock %}
 
 
-{% block content_head %}
+{% block content_header %}
 <div class="header-wrap">
 <div class="header-wrap">
   <header id="page-header">
   <header id="page-header">
     <h1 class="title" id="">{{ t('User Settings') }}</h1>
     <h1 class="title" id="">{{ t('User Settings') }}</h1>
@@ -14,10 +14,12 @@
 <div class="content-main">
 <div class="content-main">
 
 
   <ul class="nav nav-tabs">
   <ul class="nav nav-tabs">
-    <li class="active"><a href="/me"><i class="fa fa-gears"></i> {{ t('User Information') }}</a></li>
-    <li><a href="/me/external-accounts"><i class="fa fa-user-plus"></i> {{ t('External Accounts') }}</a></li>
-    <li><a href="/me/password"><i class="fa fa-key"></i> {{ t('Password Settings') }}</a></li>
-    <li><a href="/me/apiToken"><i class="fa fa-rocket"></i> {{ t('API Settings') }}</a></li>
+    <li class="active"><a href="/me"><i class="icon-user"></i> {{ t('User Information') }}</a></li>
+    {% if isEnabledPassport() %}
+    <li><a href="/me/external-accounts"><i class="icon-share-alt"></i> {{ t('External Accounts') }}</a></li>
+    {% endif %}
+    <li><a href="/me/password"><i class="icon-lock"></i> {{ t('Password Settings') }}</a></li>
+    <li><a href="/me/apiToken"><i class="icon-paper-plane"></i> {{ t('API Settings') }}</a></li>
   </ul>
   </ul>
 
 
   <div class="tab-content">
   <div class="tab-content">
@@ -47,7 +49,7 @@
   {% endif %}
   {% endif %}
 
 
 
 
-  <div class="form-box">
+  <div class="form-box m-t-20">
     <form action="/me" method="post" class="form-horizontal" role="form">
     <form action="/me" method="post" class="form-horizontal" role="form">
       <fieldset>
       <fieldset>
         <legend>{{ t('Basic Info') }}</legend>
         <legend>{{ t('Basic Info') }}</legend>
@@ -91,7 +93,7 @@
     </form>
     </form>
   </div>
   </div>
 
 
-  <div class="form-box">
+  <div class="form-box m-t-20">
 
 
     <!-- separeted form tag -->
     <!-- separeted form tag -->
     <form action="/me/imagetype" id="formImageType" method="post" class="form" role="form"></form>
     <form action="/me/imagetype" id="formImageType" method="post" class="form" role="form"></form>
@@ -100,13 +102,13 @@
 
 
       <legend>{{ t('Set Profile Image') }}</legend>
       <legend>{{ t('Set Profile Image') }}</legend>
 
 
-      <div class="form-group col-sm-offset-1 col-sm-3">
+      <div class="form-group col-md-2 col-sm-offset-1 col-sm-4">
         <div class="radio">
         <div class="radio">
           <h4>
           <h4>
             <input type="radio" form="formImageType" name="imagetypeForm[isGravatarEnabled]" value="true" {% if user.isGravatarEnabled %}checked="checked"{% endif %}>
             <input type="radio" form="formImageType" name="imagetypeForm[isGravatarEnabled]" value="true" {% if user.isGravatarEnabled %}checked="checked"{% endif %}>
             <img src="https://gravatar.com/avatar/00000000000000000000000000000000?s=24" /> Gravatar
             <img src="https://gravatar.com/avatar/00000000000000000000000000000000?s=24" /> Gravatar
             <a href="https://gravatar.com/">
             <a href="https://gravatar.com/">
-              <small><i class="fa fa-external-link" aria-hidden="true"></i></small>
+              <small><i class="icon-arrow-right-circle" aria-hidden="true"></i></small>
             </a>
             </a>
           </h4>
           </h4>
         </div>
         </div>
@@ -114,7 +116,7 @@
         <img src="{{ user|gravatar }}" width="64">
         <img src="{{ user|gravatar }}" width="64">
       </div><!-- /.col-sm* -->
       </div><!-- /.col-sm* -->
 
 
-      <div class="form-group col-sm-8">
+      <div class="form-group col-md-4 col-sm-7">
         <div class="radio">
         <div class="radio">
           <h4>
           <h4>
             <input type="radio" form="formImageType" name="imagetypeForm[isGravatarEnabled]" value="false" {% if !user.isGravatarEnabled  %}checked="checked"{% endif %}>
             <input type="radio" form="formImageType" name="imagetypeForm[isGravatarEnabled]" value="false" {% if !user.isGravatarEnabled  %}checked="checked"{% endif %}>
@@ -128,7 +130,7 @@
           </label>
           </label>
           <div class="col-sm-8">
           <div class="col-sm-8">
             <p>
             <p>
-            <img src="{{ user|uploadedpicture }}" width="64" id="settingUserPicture"><br>
+            <img src="{{ user|uploadedpicture }}" class="picture picture-lg img-circle" id="settingUserPicture"><br>
             </p>
             </p>
             <p>
             <p>
             {% if user.image %}
             {% if user.image %}
@@ -148,7 +150,7 @@
             {% if isUploadable() %}
             {% if isUploadable() %}
             <form action="/_api/me/picture/upload" id="pictureUploadForm" method="post" class="form-horizontal" role="form" enctype="multipart/form-data">
             <form action="/_api/me/picture/upload" id="pictureUploadForm" method="post" class="form-horizontal" role="form" enctype="multipart/form-data">
               <input name="userPicture" type="file" accept="image/*">
               <input name="userPicture" type="file" accept="image/*">
-              <div id="pictureUploadFormProgress">
+              <div id="pictureUploadFormProgress" class="d-flex align-items-center">
               </div>
               </div>
             </form>
             </form>
             {% else %}
             {% else %}
@@ -179,7 +181,7 @@
         return false;
         return false;
       }
       }
 
 
-      $('#pictureUploadFormProgress').html('<img src="/images/loading_s.gif"> アップロード中...');
+      $('#pictureUploadFormProgress').html('<div class="speeding-wheel-sm m-r-5"></div> アップロード中...');
       $.ajax($form.attr("action"), {
       $.ajax($form.attr("action"), {
         type: 'post',
         type: 'post',
         processData: false,
         processData: false,
@@ -205,68 +207,54 @@
   });
   });
   </script>
   </script>
 
 
-  <div class="row">
-    {% if googleLoginEnabled() %}
-
-    <div class="col-sm-6"> {# Google Connect #}
-
-      <div class="form-box">
-        <form action="/me/auth/google" method="post" class="form-horizontal" role="form">
-          <fieldset>
-            <legend><i class="fa fa-google-plus-square"></i> {{ t('Google Setting') }}</legend>
-
-            {% set wmessage = req.flash('warningMessage.auth.google') %}
-            {% if wmessage.length %}
-            <div class="alert alert-danger">
-              {{ wmessage }}
-            </div>
-            {% endif %}
-
-            <div class="form-group">
-            {% if user.googleId %}
-
-            <div class="col-sm-12">
-              <p>
-                {{ t('Connected') }}
-
-                <input type="submit" name="disconnectGoogle" class="btn btn-default" value="{{ t('Disconnect') }}">
-              </p>
-              <p class="help-block">
-                {{ t('page_me.form_help.google_disconnect1') }}<br>
-                {{ t('page_me.form_help.google_disconnect2') }}
-              </p>
-            </div>
-
-            {% else %}
-
-            <div class="col-sm-12">
-              <div class="text-center">
-                <input type="submit" name="connectGoogle" class="btn btn-google" value="Googleコネクト">
-              </div>
-              <p class="help-block">
-                {{ t('page_me.form_help.google_connect1') }}<br>
-              </p>
-              {% if config.crowi['security:registrationWhiteList'] && config.crowi['security:registrationWhiteList'].length %}
-              <p class="help-block">
-                {{ t('page_register.form_help.email') }}<br>
-                {{ t('page_me.form_help.google_connect2') }}
-              </p>
-              <ul>
-                {% for em in config.crowi['security:registrationWhiteList'] %}
-                <li><code>{{ em }}</code></li>
-                {% endfor %}
-              </ul>
-              {% endif %}
-            </div>
+  {% if googleLoginEnabled() %}
+  <div class="form-box">
+    <legend>{{ t('Google Setting') }}</legend>
+    <form action="/me/auth/google" method="post" class="form-horizontal col-sm-12" role="form">
+      <fieldset>
+        {% set wmessage = req.flash('warningMessage.auth.google') %}
+        {% if wmessage.length %}
+        <div class="alert alert-danger">
+          {{ wmessage }}
+        </div>
+        {% endif %}
 
 
-            {% endif %}
+        <div class="form-group">
+        {% if user.googleId %}
+        <div>
+          <p>
+            <input type="submit" name="disconnectGoogle" class="btn btn-default" value="{{ t('Disconnect') }}">
+          </p>
+          <p class="help-block">
+            {{ t('page_me.form_help.google_disconnect1') }}<br>
+            {{ t('page_me.form_help.google_disconnect2') }}
+          </p>
+        </div>
+        {% else %}
+        <div>
+          <div class="text-center">
+            <input type="submit" name="connectGoogle" class="btn btn-google" value="Googleコネクト">
           </div>
           </div>
-        </fieldset>
-      </form>
-    </div> {# /Google Connect #}
-    {% endif %}
-
+          <p class="help-block">
+            {{ t('page_me.form_help.google_connect1') }}<br>
+          </p>
+          {% if config.crowi['security:registrationWhiteList'] && config.crowi['security:registrationWhiteList'].length %}
+          <p class="help-block">
+            {{ t('page_register.form_help.email') }}<br>
+            {{ t('page_me.form_help.google_connect2') }}
+          </p>
+          <ul>
+            {% for em in config.crowi['security:registrationWhiteList'] %}
+            <li><code>{{ em }}</code></li>
+            {% endfor %}
+          </ul>
+          {% endif %}
+        </div>
+        {% endif %}
+      </fieldset>
+    </form>
   </div>
   </div>
+  {% endif %}
 
 
   </div> {# end of .tab-contents #}
   </div> {# end of .tab-contents #}
 
 
@@ -305,5 +293,5 @@
 {% block content_footer %}
 {% block content_footer %}
 {% endblock content_footer %}
 {% endblock content_footer %}
 
 
-{% block footer %}
-{% endblock footer %}
+{% block layout_footer %}
+{% endblock layout_footer %}

+ 12 - 16
lib/views/me/password.html

@@ -1,11 +1,11 @@
-{% extends '../layout/2column.html' %}
+{% extends '../layout-growi/base/layout.html' %}
 
 
 {% block html_title %}{{ t('Password Settings') }} · {{ path }}{% endblock %}
 {% block html_title %}{{ t('Password Settings') }} · {{ path }}{% endblock %}
 
 
-{% block content_head %}
+{% block content_header %}
 <div class="header-wrap">
 <div class="header-wrap">
   <header id="page-header">
   <header id="page-header">
-    <h1 class="title" id="">{{ t('User Settings') }}</h1>
+    <h1 class="title" id="">{{ t('Password Settings') }}</h1>
   </header>
   </header>
 </div>
 </div>
 {% endblock %}
 {% endblock %}
@@ -14,10 +14,12 @@
 <div class="content-main">
 <div class="content-main">
 
 
   <ul class="nav nav-tabs">
   <ul class="nav nav-tabs">
-    <li><a href="/me"><i class="fa fa-gears"></i> {{ t('User Information') }}</a></li>
-    <li><a href="/me/external-accounts"><i class="fa fa-user-plus"></i> {{ t('External Accounts') }}</a></li>
-    <li class="active"><a href="/me/password"><i class="fa fa-key"></i> {{ t('Password Settings') }}</a></li>
-    <li><a href="/me/apiToken"><i class="fa fa-rocket"></i> {{ t('API Settings') }}</a></li>
+    <li><a href="/me"><i class="icon-user"></i> {{ t('User Information') }}</a></li>
+    {% if isEnabledPassport() %}
+    <li><a href="/me/external-accounts"><i class="icon-share-alt"></i> {{ t('External Accounts') }}</a></li>
+    {% endif %}
+    <li class="active"><a href="/me/password"><i class="icon-lock"></i> {{ t('Password Settings') }}</a></li>
+    <li><a href="/me/apiToken"><i class="icon-paper-plane"></i> {{ t('API Settings') }}</a></li>
   </ul>
   </ul>
 
 
   <div class="tab-content">
   <div class="tab-content">
@@ -45,13 +47,7 @@
   </div>
   </div>
   {% endif %}
   {% endif %}
 
 
-  {% if user.email %}
-  <p>
-    {{ t('You can sign in with email and password', user.email) }}
-  </p>
-  {% endif %}
-
-  <div id="form-box">
+  <div id="form-box" class="m-t-20">
 
 
     <form action="/me/password" method="post" class="form-horizontal" role="form">
     <form action="/me/password" method="post" class="form-horizontal" role="form">
     <fieldset>
     <fieldset>
@@ -85,7 +81,7 @@
 
 
 
 
       <div class="form-group">
       <div class="form-group">
-        <div class="col-xs-offset-2 col-xs-10">
+        <div class="text-center">
           <button type="submit" class="btn btn-primary">{{ t('Update') }}</button>
           <button type="submit" class="btn btn-primary">{{ t('Update') }}</button>
         </div>
         </div>
       </div>
       </div>
@@ -102,5 +98,5 @@
 {% block content_footer %}
 {% block content_footer %}
 {% endblock %}
 {% endblock %}
 
 
-{% block footer %}
+{% block layout_footer %}
 {% endblock %}
 {% endblock %}

+ 29 - 31
lib/views/modal/create_page.html

@@ -2,49 +2,47 @@
   <div class="modal-dialog">
   <div class="modal-dialog">
     <div class="modal-content">
     <div class="modal-content">
 
 
-      <div class="modal-header">
+      <div class="modal-header bg-primary">
         <button type="button" class="close" data-dismiss="modal" aria-hidden="true">&times;</button>
         <button type="button" class="close" data-dismiss="modal" aria-hidden="true">&times;</button>
-        <h4 class="modal-title">{{ t('New Page') }}</h4>
+        <div class="modal-title">{{ t('New Page') }}</div>
       </div>
       </div>
 
 
       <div class="modal-body">
       <div class="modal-body">
 
 
-        <form class="form-horizontal" id="create-page-today" role="form">
-          <fieldset>
-            <div class="col-xs-12">
-              <h4>{{ t("Create today's") }}</h4>
-            </div>
-            <div class="col-xs-10">
-              <span class="page-today-prefix">{{ userPageRoot(user) }}/</span>
-              <input type="text" data-prefix="{{ userPageRoot(user) }}/" class="page-today-input1 form-control text-center" value="{{ t('Memo') }}" id="" name="">
-              <span class="page-today-suffix">/{{ now|datetz('Y/m/d') }}/</span>
-              <input type="text" data-prefix="/{{ now|datetz('Y/m/d') }}/" class="page-today-input2 form-control" id="page-today-input2" name="" placeholder="{{ t('Input page name (optional)') }}">
-            </div>
-            <div class="col-xs-2">
-              <button type="submit" class="btn btn-primary">{{ t('Create') }}</button>
+        <form class="row form-horizontal" id="create-page-today" role="form">
+          <fieldset class="col-xs-12">
+            <legend>{{ t("Create today's") }}</legend>
+            <div class="d-flex create-page-input-container">
+              <div class="create-page-input-row d-flex align-items-center">
+                <span class="page-today-prefix">{{ userPageRoot(user) }}/</span>
+                <input type="text" data-prefix="{{ userPageRoot(user) }}/" class="page-today-input1 form-control text-center" value="{{ t('Memo') }}" id="" name="">
+                <span class="page-today-suffix">/{{ now|datetz('Y/m/d') }}/</span>
+                <input type="text" data-prefix="/{{ now|datetz('Y/m/d') }}/" class="page-today-input2 form-control" id="page-today-input2" name="" placeholder="{{ t('Input page name (optional)') }}">
+              </div>
+              <div class="create-page-button-container">
+                <button type="submit" class="fcbtn btn btn-outline btn-rounded btn-primary btn-1b"><i class="icon-fw icon-doc"></i>{{ t('Create') }}</button>
+              </div>
             </div>
             </div>
           </fieldset>
           </fieldset>
         </form>
         </form>
-        <hr>
 
 
-        <form class="form-horizontal" id="create-page-under-tree" role="form">
-          <fieldset>
-            <div class="col-xs-12 create-page-under-tree-label">
-              <h4>{{ t('Create under', parentPath(path)) }}</h4>
-            </div>
-            <div class="col-xs-10">
-              {% if searchConfigured() %}
-              <div class="clearfix" id="page-name-inputter"></div>
-              {% else %}
-              <input type="text" value="{{ parentPath(path) }}" class="page-name-input form-control " placeholder="{{ t('Input page name') }}" required />
-              {% endif %}
-            </div>
-            <div class="col-xs-2">
-              <button type="submit" class="btn btn-primary">{{ t('Create') }}</button>
+        <form class="row form-horizontal m-t-15" id="create-page-under-tree" role="form">
+          <fieldset class="col-xs-12">
+            <legend>{{ t('Create under', parentPath(path)) }}</legend>
+            <div class="d-flex create-page-input-container">
+              <div class="create-page-input-row d-flex align-items-center">
+                {% if searchConfigured() %}
+                <div id="page-name-inputter"></div>
+                {% else %}
+                <input type="text" value="{{ parentPath(path) }}" class="page-name-input form-control " placeholder="{{ t('Input page name') }}" required />
+                {% endif %}
+              </div>
+              <div class="create-page-button-container">
+                <button type="submit" class="fcbtn btn btn-outline btn-rounded btn-primary btn-1b"><i class="icon-fw icon-doc"></i>{{ t('Create') }}</button>
+              </div>
             </div>
             </div>
           </fieldset>
           </fieldset>
         </form>
         </form>
-        <hr>
 
 
       </div><!-- /.modal-body -->
       </div><!-- /.modal-body -->
 
 

+ 36 - 20
lib/views/modal/delete.html

@@ -4,9 +4,15 @@
 
 
       <form role="form" id="delete-page-form" onsubmit="return false;">
       <form role="form" id="delete-page-form" onsubmit="return false;">
 
 
-        <div class="modal-header">
+        <div class="modal-header {% if page.isDeleted() %}bg-danger{% endif %}">
           <button type="button" class="close" data-dismiss="modal" aria-hidden="true">&times;</button>
           <button type="button" class="close" data-dismiss="modal" aria-hidden="true">&times;</button>
-          <h4 class="modal-title"><i class="fa fa-trash-o"></i> {{ t('modal_delete.label.Delete Page') }}</h4>
+          <div class="modal-title">
+            {% if page.isDeleted() %}
+            <i class="icon-fw icon-fire"></i> {{ t('modal_delete.label.completely') }}
+            {% else %}
+            <i class="icon-fw icon-trash"></i> {{ t('modal_delete.label.Delete Page') }}
+            {% endif %}
+          </div>
         </div>
         </div>
         <div class="modal-body">
         <div class="modal-body">
           <div class="form-group">
           <div class="form-group">
@@ -15,24 +21,34 @@
           </div>
           </div>
         </div>
         </div>
         <div class="modal-footer">
         <div class="modal-footer">
-          <p><small class="pull-left" id="delete-errors"></small></p>
-          <input type="hidden" name="_csrf" value="{{ csrf() }}">
-          <input type="hidden" name="path" value="{{ page.path }}">
-          <input type="hidden" name="page_id" value="{{ page._id.toString() }}">
-          <input type="hidden" name="revision_id" value="{{ page.revision._id.toString() }}">
-          <label class="checkbox-inline text-danger">
-            <input type="checkbox" name="recursively">{{ t('modal_delete.label.recursively') }}
-          </label>
-          {% if page.isDeleted() %}
-            <input type="hidden" name="completely" value="true">
-            <button type="submit" class="btn btn-danger delete-button"><i class="fa fa-times-circle" aria-hidden="true"></i> {{ t('Delete Completely') }}</button>
-          {% else %}
-            <label class="checkbox-inline text-danger">
-              <input type="checkbox" name="completely">{{ t('modal_delete.label.completely') }}
-            </label>
-            <button type="submit" class="btn btn-danger delete-button">Delete</button>
-          {% endif %}
-        </div>
+          <div class="d-flex justify-content-between">
+            <p><small id="delete-errors"></small></p>
+            <div>
+              <input type="hidden" name="_csrf" value="{{ csrf() }}">
+              <input type="hidden" name="path" value="{{ page.path }}">
+              <input type="hidden" name="page_id" value="{{ page._id.toString() }}">
+              <input type="hidden" name="revision_id" value="{{ page.revision._id.toString() }}">
+              <label class="checkbox-inline">
+                <input type="checkbox" name="recursively">{{ t('modal_delete.label.recursively') }}
+              </label>
+              {% if page.isDeleted() %}
+                <input type="hidden" name="completely" value="true">
+                <button type="submit" class="m-l-10 btn btn-sm btn-danger delete-button">
+                  <i class="icon-fire" aria-hidden="true"></i>
+                  {{ t('Delete Completely') }}
+                </button>
+              {% else %}
+                <label class="checkbox-inline text-danger">
+                  <input type="checkbox" name="completely">{{ t('modal_delete.label.completely') }}
+                </label>
+                <button type="submit" class="m-l-10 btn btn-sm btn-default delete-button">
+                  <i class="icon-trash" aria-hidden="true"></i>
+                  {{ t('Delete') }}
+                </button>
+              {% endif %}
+            </div>
+          </div>
+        </div><!-- /.modal-footer -->
 
 
       </form>
       </form>
       </div><!-- /.modal-content -->
       </div><!-- /.modal-content -->

+ 17 - 8
lib/views/modal/duplicate.html

@@ -4,9 +4,9 @@
 
 
       <form role="form" id="duplicatePageForm" onsubmit="return false;">
       <form role="form" id="duplicatePageForm" onsubmit="return false;">
 
 
-        <div class="modal-header">
+        <div class="modal-header bg-primary">
           <button type="button" class="close" data-dismiss="modal" aria-hidden="true">&times;</button>
           <button type="button" class="close" data-dismiss="modal" aria-hidden="true">&times;</button>
-          <h4 class="modal-title">{{ t('modal_duplicate.label.Duplicate page') }}</h4>
+          <div class="modal-title">{{ t('modal_duplicate.label.Duplicate page') }}</div>
         </div>
         </div>
         <div class="modal-body">
         <div class="modal-body">
             <div class="form-group">
             <div class="form-group">
@@ -22,12 +22,21 @@
             </div>
             </div>
         </div>
         </div>
         <div class="modal-footer">
         <div class="modal-footer">
-          <p><small class="pull-left" id="duplicatePageNameCheck"></small></p>
-          <input type="hidden" name="_csrf" value="{{ csrf() }}">
-          <input type="hidden" name="path" value="{{ page.path }}">
-          <input type="hidden" name="page_id" value="{{ page._id.toString() }}">
-          <input type="hidden" name="revision_id" value="{{ page.revision._id.toString() }}">
-          <input type="submit" class="btn btn-primary" value="Duplicate page">
+          <div class="d-flex justify-content-between">
+            <p>
+              <span class="text-danger msg-already-exists">
+                <strong><i class="icon-fw icon-ban"></i>{{ t('Page is already exists.') }}</strong>
+              </span>
+              <small id="linkToNewPage" class="msg-already-exists"></small>
+            </p>
+            <div>
+              <input type="hidden" name="_csrf" value="{{ csrf() }}">
+              <input type="hidden" name="path" value="{{ page.path }}">
+              <input type="hidden" name="page_id" value="{{ page._id.toString() }}">
+              <input type="hidden" name="revision_id" value="{{ page.revision._id.toString() }}">
+              <button type="submit" class="btn btn-primary">Duplicate page</button>
+            </div>
+          </div>
         </div>
         </div>
 
 
       </form>
       </form>

+ 1 - 1
lib/views/modal/page_name_warning.html

@@ -4,7 +4,7 @@
 
 
       <div class="modal-header">
       <div class="modal-header">
         <button type="button" class="close" data-dismiss="modal" aria-hidden="true">&times;</button>
         <button type="button" class="close" data-dismiss="modal" aria-hidden="true">&times;</button>
-        <h4 class="modal-title">ページ名に関するヒント</h4>
+        <div class="modal-title">ページ名に関するヒント</div>
       </div>
       </div>
       <div class="modal-body alert alert-danger">
       <div class="modal-body alert alert-danger">
 
 

+ 5 - 5
lib/views/modal/put_back.html

@@ -4,9 +4,9 @@
 
 
       <form role="form" id="revert-delete-page-form" onsubmit="return false;">
       <form role="form" id="revert-delete-page-form" onsubmit="return false;">
 
 
-        <div class="modal-header">
+        <div class="modal-header bg-info">
           <button type="button" class="close" data-dismiss="modal" aria-hidden="true">&times;</button>
           <button type="button" class="close" data-dismiss="modal" aria-hidden="true">&times;</button>
-          <h4 class="modal-title"><i class="fa fa-trash-o"></i> {{ t('modal_putBack.label.Put Back Page') }}</h4>
+          <div class="modal-title"><i class="icon-action-undo"></i> {{ t('modal_putBack.label.Put Back Page') }}</div>
         </div>
         </div>
         <div class="modal-body">
         <div class="modal-body">
           <div class="form-group">
           <div class="form-group">
@@ -19,11 +19,11 @@
           <input type="hidden" name="_csrf" value="{{ csrf() }}">
           <input type="hidden" name="_csrf" value="{{ csrf() }}">
           <input type="hidden" name="path" value="{{ page.path }}">
           <input type="hidden" name="path" value="{{ page.path }}">
           <input type="hidden" name="page_id" value="{{ page._id.toString() }}">
           <input type="hidden" name="page_id" value="{{ page._id.toString() }}">
-          <label class="checkbox-inline text-danger">
+          <label class="checkbox-inline">
             <input type="checkbox" name="recursively" checked> {{ t('modal_putBack.label.recursively') }}
             <input type="checkbox" name="recursively" checked> {{ t('modal_putBack.label.recursively') }}
           </label>
           </label>
-          <button type="submit" class="btn btn-default btn-sm putBack-button">
-            <i class="fa fa-undo" aria-hidden="true"></i>
+          <button type="submit" class="btn btn-sm btn-info putBack-button">
+            <i class="icon-action-undo" aria-hidden="true"></i>
             {{ t('Put Back') }}
             {{ t('Put Back') }}
           </button>
           </button>
         </div>
         </div>

+ 17 - 8
lib/views/modal/rename.html

@@ -4,9 +4,9 @@
 
 
       <form role="form" id="renamePageForm" onsubmit="return false;">
       <form role="form" id="renamePageForm" onsubmit="return false;">
 
 
-        <div class="modal-header">
+        <div class="modal-header bg-primary">
           <button type="button" class="close" data-dismiss="modal" aria-hidden="true">&times;</button>
           <button type="button" class="close" data-dismiss="modal" aria-hidden="true">&times;</button>
-          <h4 class="modal-title">{{ t('Rename page') }}</h4>
+          <div class="modal-title">{{ t('Rename page') }}</div>
         </div>
         </div>
         <div class="modal-body">
         <div class="modal-body">
             <div class="form-group">
             <div class="form-group">
@@ -43,12 +43,21 @@
             {# </div> #}
             {# </div> #}
         </div>
         </div>
         <div class="modal-footer">
         <div class="modal-footer">
-          <p><small class="pull-left" id="newPageNameCheck"></small></p>
-          <input type="hidden" name="_csrf" value="{{ csrf() }}">
-          <input type="hidden" name="path" value="{{ page.path }}">
-          <input type="hidden" name="page_id" value="{{ page._id.toString() }}">
-          <input type="hidden" name="revision_id" value="{{ page.revision._id.toString() }}">
-          <input type="submit" class="btn btn-primary" value="Rename!">
+          <div class="d-flex justify-content-between">
+            <p>
+              <span class="text-danger msg-already-exists">
+                <strong><i class="icon-fw icon-ban"></i>{{ t('Page is already exists.') }}</strong>
+              </span>
+              <small id="linkToNewPage" class="msg-already-exists"></small>
+            </p>
+            <div>
+              <input type="hidden" name="_csrf" value="{{ csrf() }}">
+              <input type="hidden" name="path" value="{{ page.path }}">
+              <input type="hidden" name="page_id" value="{{ page._id.toString() }}">
+              <input type="hidden" name="revision_id" value="{{ page.revision._id.toString() }}">
+              <button type="submit" class="btn btn-primary">Rename</button>
+            </div>
+          </div>
         </div>
         </div>
 
 
       </form>
       </form>

+ 1 - 1
lib/views/modal/shortcuts.html

@@ -4,7 +4,7 @@
 
 
       <div class="modal-header">
       <div class="modal-header">
         <button type="button" class="close" data-dismiss="modal" aria-hidden="true">&times;</button>
         <button type="button" class="close" data-dismiss="modal" aria-hidden="true">&times;</button>
-        <h4 class="modal-title">{{ t('Shortcuts') }}</h4>
+        <div class="modal-title">{{ t('Shortcuts') }}</div>
       </div>
       </div>
 
 
       <div class="modal-body">
       <div class="modal-body">

+ 3 - 3
lib/views/modal/unportalize.html

@@ -9,9 +9,9 @@
 
 
       <form role="form" id="unportalize-form" onsubmit="return false;">
       <form role="form" id="unportalize-form" onsubmit="return false;">
 
 
-        <div class="modal-header">
+        <div class="modal-header bg-warning">
           <button type="button" class="close" data-dismiss="modal" aria-hidden="true">&times;</button>
           <button type="button" class="close" data-dismiss="modal" aria-hidden="true">&times;</button>
-          <h4 class="modal-title">ポータル化を解除する</h4>
+          <div class="modal-title">ポータル化を解除する</div>
         </div>
         </div>
         <div class="modal-body">
         <div class="modal-body">
           <ul>
           <ul>
@@ -42,7 +42,7 @@
           <input type="hidden" class="form-control" name="new_path" id="newPageName" value="{{ unportalizedPath }}">
           <input type="hidden" class="form-control" name="new_path" id="newPageName" value="{{ unportalizedPath }}">
           <input type="hidden" name="page_id" value="{{ page._id.toString() }}">
           <input type="hidden" name="page_id" value="{{ page._id.toString() }}">
           <input type="hidden" name="revision_id" value="{{ page.revision._id.toString() }}">
           <input type="hidden" name="revision_id" value="{{ page.revision._id.toString() }}">
-          <input type="submit" class="btn btn-primary" value="Unportalize!">
+          <button type="submit" class="btn btn-warning">Unportalize</button>
         </div>
         </div>
 
 
       </form>
       </form>

+ 25 - 1
lib/views/modal/what_is_portal.html

@@ -4,7 +4,7 @@
 
 
       <div class="modal-header">
       <div class="modal-header">
         <button type="button" class="close" data-dismiss="modal" aria-hidden="true">&times;</button>
         <button type="button" class="close" data-dismiss="modal" aria-hidden="true">&times;</button>
-        <h4 class="modal-title">What is Portal?</h4>
+        <div class="modal-title">What is Portal?</div>
       </div>
       </div>
 
 
       <div class="modal-body">
       <div class="modal-body">
@@ -55,3 +55,27 @@
   </div><!-- /.modal-dialog -->
   </div><!-- /.modal-dialog -->
 </div><!-- /.modal -->
 </div><!-- /.modal -->
 
 
+<div class="modal fade portal-warning-modal" id="portal-warning-modal">
+  <div class="modal-dialog">
+    <div class="modal-content">
+
+      <div class="modal-header">
+        <button type="button" class="close" data-dismiss="modal" aria-hidden="true">&times;</button>
+        <div class="modal-title">ポータルに関するヒント</div>
+      </div>
+      <div class="modal-body">
+
+        <strong>Warning!</strong><br>
+
+        <p>既に <strong><a href="{{ path|removeLastSlash }}">{{ path|removeLastSlash }}</a></strong> のページが存在します。</p>
+
+        <p>
+          <a href="{{ path|removeLastSlash }}">{{ path|removeLastSlash }}</a> をポータル化するには、
+          <a href="{{ path|removeLastSlash }}">{{ path|removeLastSlash }}</a> に移動し、「ページを移動」させてください。<br>
+          <a href="{{ path|removeLastSlash }}">{{ path|removeLastSlash }}</a> とは別に、このページ(<code>{{ path }}</code>)にポータルを作成する場合、このまま編集を続けて作成してください。
+        </p>
+
+      </div>
+    </div>
+  </div>
+</div>

+ 0 - 95
lib/views/not_found.html

@@ -1,95 +0,0 @@
-{% extends 'layout/2column.html' %}
-
-{% block content_head %}
-
-  {% block content_head_before %}
-  {% endblock %}
-
-  <div class="header-wrap">
-    <header id="page-header">
-      <p class="stopper"><a href="#" data-affix-disable="#page-header"><i class="fa fa-chevron-up"></i></a></p>
-
-      <div class="flex-title-line">
-        <div>
-          <h1 class="title flex-item-title" id="revision-path"></h1>
-          <div id="revision-url" class="url-line"></div>
-        </div>
-      </div>
-
-    </header>
-  </div>
-
-  {% block content_head_after %}
-  {% endblock %}
-
-{% endblock %} {# /content_head #}
-
-{% block content_main %}
-
-{% block content_main_before %}
-  <h2 class="message-not-found text-muted">
-    <i class="fa fa-info-circle" aria-hidden="true"></i>
-    Page is not found
-  </h2>
-{% endblock %}
-
-<div id="content-main" class="content-main content-main-not-found page-list"
-  data-path="{{ path }}"
-  data-path-shortname="{{ path|path2name }}"
-  data-current-user="{% if user %}{{ user._id.toString() }}{% endif %}"
-  >
-
-  <ul class="nav nav-tabs hidden-print">
-    <li class="active"><a href="#revision-body" data-toggle="tab">{{ t('List View') }}</a></li>
-
-    <li>
-      <a {% if user %}href="#edit-form" data-toggle="tab"{% endif %} class="edit-button {% if not user %}edit-button-disabled{% endif %}">
-        <i class="fa fa-pencil-square-o"></i> {{ t('Create') }}
-      </a>
-    </li>
-
-    {% if user %}
-    <li class="dropdown pull-right">
-      <a href="#" onclick="history.back();"><i class="fa fa-times"></i> {{ t('Cancel') }}</a>
-    </li>
-    {% endif %}
-  </ul>
-
-  <div class="tab-content wiki-content">
-    {% if req.query.renamed %}
-    <div class="alert alert-info alert-moved">
-      <span>
-        <strong>{{ t('Moved') }}: </strong> {{ t('page_page.notice.moved', req.query.renamed) }}
-      </span>
-    </div>
-    {% endif %}
-    {% if req.query.unlinked %}
-    <div class="alert alert-info">
-      <strong>{{ t('Unlinked') }}: </strong> {{ t('page_page.notice.unlinked') }}
-    </div>
-    {% endif %}
-
-    {# list view #}
-    <div class="active tab-pane page-list-container" id="revision-body">
-      {% if pages.length == 0 %}
-        There are no pages under <strong>{{ path }}</strong>.
-      {% endif  %}
-
-      {% include 'widget/page_list.html' with { pages: pages, pager: pager, viewConfig: viewConfig } %}
-    </div>
-
-    {# edit view #}
-    <div class="edit-form tab-pane {% if req.body.pageForm %}active{% endif %}" id="edit-form">
-      {% include '_form.html' %}
-    </div>
-
-  </div>
-</div>
-
-{% block content_main_after %}
-{% endblock %}
-
-{% endblock %}
-
-{% block content_footer %}
-{% endblock %}

+ 0 - 273
lib/views/page.html

@@ -1,273 +0,0 @@
-{% extends 'layout/2column.html' %}
-
-{% block html_title %}{{ path|path2name }} · {{ path }}{% endblock %}
-
-{% block content_head %}
-
-{% block content_head_before %}
-{% endblock %}
-
-<div class="header-wrap">
-  <header id="page-header">
-    <p class="stopper"><a href="#" data-affix-disable="#page-header"><i class="fa fa-chevron-up"></i></a></p>
-
-    <div class="flex-title-line">
-      <h1 class="title flex-item-title" id="revision-path"></h1>
-      {% if page %}
-      <div class="flex-item-action">
-        {% if user %}
-        <span id="bookmark-button">
-          <p class="bookmark-link">
-            <i class="fa fa-star-o"></i>
-          </p>
-        </span>
-        {% endif %}
-      </div>
-      <div class="flex-item-action visible-xs visible-sm">
-        {% if user %}
-        <button
-            data-csrftoken="{{ csrf() }}"
-            data-liked="{% if page.isLiked(user) %}1{% else %}0{% endif %}"
-            class="like-button btn btn-default btn-sm {% if page.isLiked(user) %}active{% endif %}"
-        ><i class="fa fa-thumbs-o-up"></i></button>
-        {% endif %}
-      </div>
-      {% endif %}
-    </div>
-
-    <div id="revision-url" class="url-line"></div>
-  </header>
-</div>
-
-{% block content_head_after %}
-{% endblock %}
-
-{% endblock %}
-
-{% block content_main %}
-
-{% block content_main_before %}
-{% endblock %}
-
-<div id="content-main" class="content-main {% if not page or req.body.pageForm %}on-edit{% endif %}"
-  data-path="{{ path }}"
-  data-path-shortname="{{ path|path2name }}"
-  data-page-id="{% if page %}{{ page._id.toString() }}{% endif %}"
-  data-current-user="{% if user %}{{ user._id.toString() }}{% endif %}"
-  data-page-revision-id="{% if revision %}{{ revision._id.toString() }}{% endif %}"
-  data-page-revision-created="{% if revision %}{{ revision.createdAt|datetz('U') }}{% endif %}"
-  data-page-is-seen="{% if page and page.isSeenUser(user) %}1{% else %}0{% endif %}"
-  >
-
-  {% if not page %}
-  <ul class="nav nav-tabs hidden-print">
-    <li><a>Create: {{ path }}</a></li>
-    <li class="dropdown pull-right">
-      <a href="#" onclick="history.back();"><i class="fa fa-times"></i> {{ t('Cancel') }}</a>
-    </li>
-  </ul>
-  <div class="tab-content">
-    <div class="edit-form">
-    {% include '_form.html' %}
-    </div>
-  </div>
-
-  {% else %}
-
-  {% if page.isDeleted() %}
-  <div class="alert alert-danger alert-trash">
-    <div>
-      {% if user %}
-      <ul class="list-inline pull-right">
-        <li>
-          <a href="#" class="btn btn-default btn-sm" data-target="#putBackPage" data-toggle="modal"><i class="fa fa-undo" aria-hidden="true"></i> {{ t('Put Back') }}</a>
-        </li>
-        <li>
-          <a href="#" class="btn btn-danger btn-sm" data-target="#deletePage" data-toggle="modal"><i class="fa fa-times-circle" aria-hidden="true"></i> {{ t('Delete Completely') }}</a>
-        </li>
-      </ul>{# /.pull-right #}
-      {% endif %}
-
-      <i class="fa fa-trash-o" aria-hidden="true"></i>
-      This page is in the trash.<br>
-      Deleted by <img src="{{ page.lastUpdateUser|picture }}" class="picture picture-sm picture-rounded"> {{ page.lastUpdateUser.name }} at {{ page.updatedAt|datetz('Y-m-d H:i:s') }}
-    </div>
-  </div>
-  {% endif %}
-
-  {% if not page.isDeleted() %}
-  <ul class="nav nav-tabs hidden-print">
-    <li class=" {% if not req.body.pageForm %}active{% endif %}" data-toggle="tooltip" {# data-title="あなたの 確認待ち です" title="" data-placement="bottom" data-trigger="manual" data-tooltip-stay #}>
-      <a href="#revision-body" data-toggle="tab">
-      <i class="fa fa-magic"></i>
-      {#
-        <span class="label label-danger" style=""> 承認待ち</span>
-      #}
-      </a>
-    </li>
-
-    <li {% if req.body.pageForm %}class="active"{% endif %}>
-      <a {% if user %}href="#edit-form" data-toggle="tab"{% endif %} class="edit-button {% if not user %}edit-button-disabled{% endif %}">
-        <i class="fa fa-pencil-square-o"></i> {{ t('Edit') }}
-      </a>
-    </li>
-
-
-    <li class="dropdown pull-right">
-      <a class="dropdown-toggle {% if not user %}dropdown-disabled{% endif %}" {% if user %}data-toggle="dropdown" href="#"{% endif %}>
-        <i class="fa fa-wrench"></i> <span class="caret"></span>
-      </a>
-      <ul class="dropdown-menu">
-       <li><a href="#" data-target="#renamePage" data-toggle="modal"><i class="fa fa-share"></i> {{ t('Move') }}</a></li>
-       <li class="divider"></li>
-       <li><a href="#" data-target="#duplicatePage" data-toggle="modal"><i class="fa fa-clone"></i> {{ t('Duplicate') }}</a></li>
-       {% if isDeletablePage() %}
-       <li class="divider"></li>
-       <li class=""><a href="#" data-target="#deletePage" data-toggle="modal"><i class="fa fa-trash-o text-danger"></i> {{ t('Delete') }}</a></li>
-       {% endif %}
-      </ul>
-    </li>
-    {% if page %}
-    <li class="pull-right"><a href="#revision-history" data-toggle="tab"><i class="fa fa-history"></i> History</a></li>
-    <li class="pull-right"><a href="?presentation=1" class="toggle-presentation"><i class="fa fa-film"></i> {{ t('Presentation Mode') }}</a></li>
-    {% endif %}
-  </ul>
-  {% endif %}
-
-  <div class="tab-content wiki-content">
-  {% if req.query.renamed and not page.isDeleted() %}
-  <div class="alert alert-info alert-moved">
-    <span>
-      <strong>{{ t('Moved') }}: </strong> {{ t('page_page.notice.moved', req.query.renamed) }}
-    </span>
-  </div>
-  {% endif %}
-  {% if req.query.redirectFrom and not page.isDeleted() %}
-  <div class="alert alert-info alert-moved">
-    <div>
-      {% if user %}
-      <form role="form" id="unlink-page-form" onsubmit="return false;">
-        <input type="hidden" name="_csrf" value="{{ csrf() }}">
-        <input type="hidden" name="path" value="{{ page.path }}">
-        <input type="hidden" name="page_id" value="{{ page._id.toString() }}">
-        <button type="submit" class="btn btn-default btn-sm pull-right">
-          <i class="fa fa-unlink" aria-hidden="true"></i>
-          Unlink
-        </button>
-      </form>
-      {% endif %}
-      <span>
-        <strong>{{ t('Moved') }}: </strong> {{ t('page_page.notice.moved', req.query.redirectFrom) }}
-      </span>
-    </div>
-  </div>
-  {% endif %}
-  {% if req.query.unlinked %}
-  <div class="alert alert-info alert-unlinked">
-    <strong>{{ t('Unlinked') }}: </strong> {{ t('page_page.notice.unlinked') }}
-  </div>
-  {% endif %}
-
-
-  {% if not page.isLatestRevision() %}
-  <div class="alert alert-warning">
-    <strong>{{ t('Warning') }}: </strong> {{ t('page_page.notice.version') }} <i class="fa fa-magic"></i> <a href="{{ page.path }}">{{ t('Show latest') }}</a>
-  </div>
-  {% endif %}
-
-{#
-  <div class="panel panel-default">
-    <div class="panel-heading">承認待ち</div>
-    <div class="panel-body">
-      ほげほげ
-    </div>
-  </div>
-#}
-    <script type="text/template" id="raw-text-original">{{ revision.body }}</script>
-
-    {# formatted text #}
-    <div class="tab-pane {% if not req.body.pageForm %}active{% endif %}" id="revision-body">
-      <div class="revision-toc" id="revision-toc">
-        <a data-toggle="collapse" data-parent="#revision-toc" href="#revision-toc-content" class="revision-toc-head">{{ t('Table of Contents') }}</a>
-        <div id="revision-toc-content" class="revision-toc-content collapse in"></div>
-      </div>
-      <div id="page"></div>
-    </div>
-
-    {# edit form #}
-    {% if not page.isDeleted() %}
-    <div class="edit-form tab-pane {% if req.body.pageForm %}active{% endif %}" id="edit-form">
-      {% include '_form.html' %}
-    </div>
-    {% endif %}
-
-    {# raw revision history #}
-    {% if not page %}
-    {% else %}
-    <div class="tab-pane revision-history" id="revision-history">
-    </div>
-    {% endif %}
-
-  </div>
-  {% endif %}
-
-  <div id="notifPageEdited" class="fk-notif fk-notif-danger"><i class="fa fa-exclamation-triangle"></i> <span class="edited-user"></span> {{ t('edited this page') }} <a href="javascript:location.reload();"><i class="fa fa-angle-double-right"></i> {{ t('Load latest') }}</a></div>
-</div>
-
-{% block content_main_after %}
-{% endblock %}
-
-{% endblock %}
-
-{% block content_footer %}
-
-
-{% if page %}
-<div class="page-attachments meta" id="page-attachment">
-</div>
-
-<p class="page-meta meta">
-  Path: <span id="pagePath">{{ page.path }}</span><br>
-  {# for BC #}
-  {% if page.lastUpdateUser %}
-    Last updated at {{ page.updatedAt|datetz('Y-m-d H:i:s') }} by <img src="{{ page.lastUpdateUser|picture }}" class="picture picture-rounded"> {{ page.lastUpdateUser.name }}<br>
-  {% else %}
-    Last updated at {{ page.revision.createdAt|datetz('Y-m-d H:i:s') }} by <img src="{{ page.revision.author|picture }}" class="picture picture-rounded"> {{ page.revision.author.name }}<br>
-  {% endif %}
-  {# /for BC #}
-  Created at {{ page.createdAt|datetz('Y-m-d H:i:s') }} by <img src="{{ page.creator|default(page.creator)|picture }}" class="picture picture-rounded"> {{ page.creator.name }}<br>
-</p>
-{% endif %}
-
-{% endblock %}
-
-{% block side_header %}
-  {% if not page.isDeleted() %}
-    {% include 'widget/page_side_header.html' %}
-  {% endif %}
-{% endblock %} {# side_header #}
-
-{% block side_content %}
-  {% if not page.isDeleted() %}
-    {% include 'widget/page_side_content.html' %}
-  {% endif %}
-{% endblock %}
-
-{% block footer %}
-{% endblock %}
-
-{% block body_end %}
-  {% parent %}
-
-<div id="presentation-layer" class="fullscreen-layer">
-  <div id="presentation-container"></div>
-</div>
-
-<div id="crowi-modals">
-  {% include 'modal/rename.html' %}
-  {% include 'modal/delete.html' %}
-  {% include 'modal/duplicate.html' %}
-  {% include 'modal/put_back.html' %}
-  {% include 'modal/page_name_warning.html' %}
-</div>
-{% endblock %}

+ 0 - 288
lib/views/page_list.html

@@ -1,288 +0,0 @@
-{% extends 'layout/2column.html' %}
-
-{% block html_title %}{{ path|path2name }} · {{ path }}{% endblock %}
-
-{% block html_base_attr %}
-  data-spy="scroll"
-  data-target="#search-result-list"
-{% endblock %}
-
-{% block content_head %}
-
-{% block content_head_before %}
-{% endblock %}
-
-<div class="header-wrap">
-  <header class="portal-header {% if page %}has-page{% endif %}">
-
-    <div class="flex-title-line">
-      <h1 class="title flex-item-title">
-        <span id="revision-path"></span>
-        {% if searchConfigured() && !isTopPage() && !isTrashPage() %}
-        <form class="input-group search-input-group hidden-xs hidden-sm" data-toggle="tooltip" data-placement="bottom" title="{{ path }} 以下から検索" id="search-listpage-form">
-          <div class="input-group">
-            <input id="#search-listpage-input" type="text" class="form-control" data-path="{{ path }}" placeholder="Search for...">
-            <span class="input-group-btn">
-              <button class="btn btn-default"><i class="fa fa-search"></i></button>
-            </span>
-          </div><!-- /input-group -->
-          <a class="search-listpage-clear" id="search-listpage-clear"><i class="fa fa-times-circle"></i></a>
-        </form>
-        {% endif %}
-      </h1>
-
-      {% if page %}
-      <div class="flex-item-action">
-        {% if user %}
-        <span id="bookmark-button" data-csrftoken="{{ csrf() }}"></span>
-        {% endif %}
-      </div>
-      <div class="flex-item-action visible-xs visible-sm">
-        {% if user %}
-        <button
-            data-csrftoken="{{ csrf() }}"
-            data-liked="{% if page.isLiked(user) %}1{% else %}0{% endif %}"
-            class="like-button btn btn-default btn-sm {% if page.isLiked(user) %}active{% endif %}"
-        ><i class="fa fa-thumbs-o-up"></i></button>
-        {% endif %}
-      </div>
-      {% endif %}
-    </div>
-
-    <div id="revision-url" class="url-line"></div>
-
-  </header>
-</div>
-
-{% endblock %}
-
-{% block content_main %}
-
-{% block content_main_before %}
-{% endblock %}
-
-{# page-list-search should be fully managed by react.js,
- # but now the header and page list content is rendered separately by the server,
- # so now bind the values through the hidden fields.
- #}
-{% if searchConfigured() && !isTopPage() && !isTrashPage() %}
-<div id="page-list-search">
-</div>
-{% endif %}
-
-<div class="page-list content-main {% if req.body.pageForm %}on-edit{% endif %}"
-  id="content-main"
-  data-path="{{ path }}"
-  data-path-shortname="{{ path|path2name }}"
-  data-page-portal="{% if page and page.isPortal() %}1{% else %}0{% endif %}"
-  data-page-id="{% if page %}{{ page._id.toString() }}{% endif %}"
-  data-current-user="{% if user %}{{ user._id.toString() }}{% endif %}"
-  data-page-revision-id="{% if revision %}{{ revision._id.toString() }}{% endif %}"
-  data-page-revision-created="{% if revision %}{{ revision.createdAt|datetz('U') }}{% endif %}"
-  data-page-is-seen="{% if page and page.isSeenUser(user) %}1{% else %}0{% endif %}"
-  >
-
-<div class="portal {% if not page or req.query.offset > 0 %}hide{% endif %}">
-
-  <ul class="nav nav-tabs hidden-print">
-   {# portal tab #}
-    <li class=" {% if not req.body.pageForm %}active{% endif %}">
-      {% if page %}
-      <a href="#revision-body" data-toggle="tab">
-        <i class="fa fa-magic"></i>
-        PORTAL
-      </a>
-      {% else %}
-      <a>Create Portal: {{ path }}</a>
-      {% endif %}
-    </li>
-    <li {% if req.body.pageForm %}class="active"{% endif %}>
-      <a {% if user %}href="#edit-form" data-toggle="tab"{% endif %} class="edit-button {% if not user %}edit-button-disabled{% endif %}">
-        <i class="fa fa-pencil-square-o"></i> {{ t('Edit') }}
-      </a>
-    </li>
-
-    {% if not page %}
-    <li class="pull-right close-button">
-      <a href="#" id="portal-form-close">
-        <i class="fa fa-times"></i>
-      </a>
-    </li>
-    {% else %}
-    <li class="dropdown pull-right">
-      <a class="dropdown-toggle {% if not user %}dropdown-disabled{% endif %}" {% if user %}data-toggle="dropdown" href="#"{% endif %}>
-        <i class="fa fa-wrench"></i> <span class="caret"></span>
-      </a>
-      <ul class="dropdown-menu">
-        <li><a href="#" data-target="#unportalize" data-toggle="modal"><i class="fa fa-share"></i> {{ t('Unportalize') }}</a></li>
-      </ul>
-    </li>
-    <li class="pull-right"><a href="#revision-history" data-toggle="tab"><i class="fa fa-history"></i> History</a></li>
-    {% endif %}
-  </ul>
-
-  <div class="tab-content">
-  {% if page and not page.isLatestRevision() %}
-  <div class="alert alert-warning">
-    <strong>{{ t('Warning') }}: </strong> {{ t('page.notice.version') }} <i class="fa fa-magic"></i> <a href="{{ page.path }}">最新のポータルを表示</a>
-  </div>
-  {% endif %}
-    <div class="tab-pane {% if not req.body.pageForm %}active{% endif %}" id="revision-body">
-      <div id="page"></div>
-    </div>
-
-    <script type="text/template" id="raw-text-original">{{ page.revision.body }}</script>
-
-    <div class="tab-pane edit-form portal-form {% if req.body.pageForm %}active{% endif %}" id="edit-form">
-      {% include '_form.html' with {forceGrant: 1} %}
-    </div>
-
-    <div class="tab-pane revision-history" id="revision-history">
-      <h1><i class="fa fa-history"></i> History</h1>
-      {% if not page %}
-      {% else %}
-      <div class="revision-history-list">
-        {% for tr in tree %}
-        <div class="revision-hisory-outer">
-          <img src="{{ tr.author|picture }}" class="picture picture-rounded">
-          <div class="revision-history-main">
-            <div class="revision-history-author">
-              <strong>{% if tr.author %}{{ tr.author.username }}{% else %}-{% endif %}</strong>
-            </div>
-            <div class="revision-history-comment">
-            </div>
-            <div class="revision-history-meta">
-              {{ tr.createdAt|datetz('Y-m-d H:i:s') }}
-              <br>
-              <a href="?revision={{ tr._id.toString() }}"><i class="fa fa-history"></i> {{ t('View this version') }}</a>
-              <a class="diff-view" data-revision-id="{{ tr._id.toString() }}">
-                <i id="diff-icon-{{ tr._id.toString() }}" class="fa fa-arrow-circle-right"></i> {{ t('View diff') }}
-              </a>
-              <div class="" id="diff-display-{{ tr._id.toString()}}" style="display: none"></div>
-            </div>
-          </div>
-        </div>
-        {% endfor %}
-      </div>
-      {% endif %}
-    </div>
-  </div>
-
-</div> {# /.portal #}
-
-<div class="page-list-container">
-  <ul class="nav nav-tabs">
-      <li class="active"><a href="#view-list" data-toggle="tab">{{ t('List View') }}</a></li>
-      {% if isEnabledTimeline() %}
-      <li><a href="#view-timeline" data-toggle="tab">{{ t('Timeline View') }}</a></li>
-      {% endif %}
-  </ul>
-
-  <div class="tab-content">
-    {% if pages.length == 0 %}
-
-      {% if isTrashPage() %}
-      No deleted pages.
-      {% else %}
-      There are no pages under <strong>{{ path }}</strong>.
-
-      <h3>Next Actions</h3>
-
-      <ul>
-        <li>Create portal page?
-          <ul>
-            <li>Great! To create the portal of <strong>{{ path }}</strong>, click "Create Portal" button.</li>
-          </ul>
-        </li>
-        <li>Create the under page directly?
-          <ul>
-            <li>Nice. To create the page under <strong>{{ path }}</strong> directly, type the page name on your browser.</li>
-          </ul>
-        </li>
-      </ul>
-      {% endif %}
-    {% endif  %}
-
-    {# list view #}
-    <div class="active tab-pane fade page-list-container in" id="view-list">
-      {% include 'widget/page_list.html' with { pages: pages, pager: pager, viewConfig: viewConfig } %}
-    </div>
-
-    {# timeline view #}
-    {% if isEnabledTimeline() %}
-    <div class="tab-pane" id="view-timeline" data-shown=0>
-      {% for page in pages %}
-      <div class="timeline-body" id="id-{{ page.id }}" data-page-path="{{ page.path }}">
-        <h3 class="revision-path"><a href="{{ page.path }}">{{ page.path }}</a></h3>
-        <div class="revision-body wiki"></div>
-        <script type="text/template">{{ page.revision.body }}</script>
-      </div>
-      <hr>
-      {% endfor %}
-    </div>
-    {% endif %}
-  </div>
-</div>
-
-
-</div> {# /.content-main #}
-
-{% block content_main_after %}
-{% endblock %}
-
-{% endblock %}
-
-
-{% block content_footer %}
-<footer>
-
-</footer>
-{% endblock %}
-
-
-{% block side_header %}
-
-{% if not page and not isUserPageList(path) and !isTrashPage() %}
-<div class="portal-side">
-  <div class="portal-form-button">
-    <button class="btn btn-primary" id="create-portal-button">Create Portal</button>
-    <p class="help-block"><a href="#" data-target="#help-portal" data-toggle="modal"><i class="fa fa-question-circle"></i> What is Portal?</a></p>
-  </div>
-
-</div>
-{% else %}
-  {% include 'widget/page_side_header.html' %}
-{% endif %}
-
-{% endblock %} {# side_header #}
-
-{% block body_end %}
-<div id="crowi-modals">
-  {% include 'modal/what_is_portal.html' %}
-  {% include 'modal/unportalize.html' %}
-</div>
-<div class="modal fade portal-warning-modal" id="portal-warning-modal">
-  <div class="modal-dialog">
-    <div class="modal-content">
-
-      <div class="modal-header">
-        <button type="button" class="close" data-dismiss="modal" aria-hidden="true">&times;</button>
-        <h4 class="modal-title">ポータルに関するヒント</h4>
-      </div>
-      <div class="modal-body alert alert-danger">
-
-        <strong>Warning!</strong><br>
-
-        <p>既に <strong><a href="{{ path|removeLastSlash }}">{{ path|removeLastSlash }}</a></strong> のページが存在します。</p>
-
-        <p>
-          <a href="{{ path|removeLastSlash }}">{{ path|removeLastSlash }}</a> をポータル化するには、
-          <a href="{{ path|removeLastSlash }}">{{ path|removeLastSlash }}</a> に移動し、「ページを移動」させてください。<br>
-          <a href="{{ path|removeLastSlash }}">{{ path|removeLastSlash }}</a> とは別に、このページ(<code>{{ path }}</code>)にポータルを作成する場合、このまま編集を続けて作成してください。
-        </p>
-
-      </div>
-    </div>
-  </div>
-</div>
-{% endblock %} {# body_end #}

+ 5 - 4
lib/views/page_presentation.html

@@ -39,17 +39,18 @@ gh/highlightjs/cdn-release@9.12.0/build/languages/yaml.min.js
       <script src="{{ webpack_asset('dev').js }}" async></script>
       <script src="{{ webpack_asset('dev').js }}" async></script>
     {% endif %}
     {% endif %}
 
 
-    <script src="{{ webpack_asset('style').js }}"></script>
-    <script src="{{ webpack_asset('style-presentation').js }}"></script>
     <script src="{{ webpack_asset('commons').js }}" defer></script>
     <script src="{{ webpack_asset('commons').js }}" defer></script>
     <script src="{{ webpack_asset('legacy-presentation').js }}" defer></script>
     <script src="{{ webpack_asset('legacy-presentation').js }}" defer></script>
 
 
     <title>{{ path|path2name }} | {{ path }}</title>
     <title>{{ path|path2name }} | {{ path }}</title>
 
 
+    <!-- styles -->
+    <link rel="stylesheet" href="{{ webpack_asset('style').css }}">
+    <link rel="stylesheet" href="{{ webpack_asset('style-theme-default').css }}">
+    <link rel="stylesheet" href="{{ webpack_asset('style-presentation').css }}">
+
     <!-- Google Fonts -->
     <!-- Google Fonts -->
     <link href='https://fonts.googleapis.com/css?family=Lato:400,700' rel='stylesheet' type='text/css'>
     <link href='https://fonts.googleapis.com/css?family=Lato:400,700' rel='stylesheet' type='text/css'>
-    <!-- highlight.js -->
-    <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/highlight.js@9.12.0/styles/github.css">
 
 
     <style>
     <style>
       {{ customCss() }}
       {{ customCss() }}

+ 14 - 7
lib/views/search.html

@@ -1,16 +1,23 @@
-{% extends 'layout/single.html' %}
+{% extends 'layout/layout.html' %}
 
 
-{% block main_css_class %}search-page{% endblock %}
 {% block html_base_attr %}
 {% block html_base_attr %}
   data-spy="scroll"
   data-spy="scroll"
   data-target="#search-result-list"
   data-target="#search-result-list"
 {% endblock %}
 {% endblock %}
 
 
-{% block html_title %}Search {% endblock %}
 
 
-{% block content_main %}
+{% block layout_main %}
+<div class="container-fluid">
 
 
-<div class="" id="search-page">
-</div>
+  <div class="row">
+    <div id="main" class="main m-t-15 col-md-12 search-page">
+      <div class="" id="search-page"></div>
+    </div>
+  </div>
 
 
-{% endblock %}
+</div><!-- /.container-fluid -->
+
+<footer class="footer">
+  {% include 'widget/system-version.html' %}
+</footer>
+{% endblock %} {# layout_main #}

+ 3 - 5
lib/views/user/bookmarks.html

@@ -1,14 +1,12 @@
-{% extends '../layout/2column.html' %}
+{% extends '../layout/layout.html' %}
 
 
 {% block main_css_class %}bookmark-page{% endblock %}
 {% block main_css_class %}bookmark-page{% endblock %}
 
 
 {% block html_title %}{{ pageUser.name }}'s Bookmarks · {% endblock %}
 {% block html_title %}{{ pageUser.name }}'s Bookmarks · {% endblock %}
 
 
-{% block content_head %}
+{% block content_header %}
 <div class="header-wrap">
 <div class="header-wrap">
   <header id="page-header">
   <header id="page-header">
-    <p class="stopper"><a href="#" data-affix-disable="#page-header"><i class="fa fa-chevron-up"></i></a></p>
-
     <h1 class="title">{{ pageUser.name }}'s Bookmarks</h1>
     <h1 class="title">{{ pageUser.name }}'s Bookmarks</h1>
   </header>
   </header>
 </div>
 </div>
@@ -28,5 +26,5 @@
 {% block side_content %}
 {% block side_content %}
 {% endblock %}
 {% endblock %}
 
 
-{% block footer %}
+{% block layout_footer %}
 {% endblock %}
 {% endblock %}

+ 3 - 5
lib/views/user/recent-create.html

@@ -1,14 +1,12 @@
-{% extends '../layout/2column.html' %}
+{% extends '../layout/layout.html' %}
 
 
 {% block main_css_class %}recent-create-page{% endblock %}
 {% block main_css_class %}recent-create-page{% endblock %}
 
 
 {% block html_title %}{{ pageUser.name }}'s Recent Created Pages 揃 {% endblock %}
 {% block html_title %}{{ pageUser.name }}'s Recent Created Pages 揃 {% endblock %}
 
 
-{% block content_head %}
+{% block content_header %}
 <div class="header-wrap">
 <div class="header-wrap">
   <header id="page-header">
   <header id="page-header">
-    <p class="stopper"><a href="#" data-affix-disable="#page-header"><i class="fa fa-chevron-up"></i></a></p>
-
     <h1 class="title">{{ pageUser.name }}'s Created Pages</h1>
     <h1 class="title">{{ pageUser.name }}'s Created Pages</h1>
   </header>
   </header>
 </div>
 </div>
@@ -28,5 +26,5 @@
 {% block side_content %}
 {% block side_content %}
 {% endblock %}
 {% endblock %}
 
 
-{% block footer %}
+{% block layout_footer %}
 {% endblock %}
 {% endblock %}

+ 0 - 81
lib/views/user_page.html

@@ -1,81 +0,0 @@
-{% extends 'page.html' %}
-
-{% block main_css_class %}user-page{% endblock %}
-
-{% block content_head %}
-
-{% if pageUser %}
-
-<div class="header-wrap">
-  <h1 class="title" id="revision-path"></h1>
-  <div class="user-page-header">
-  {% if page %}
-    <span id="bookmark-button" data-csrftoken="{{ csrf() }}"></span>
-  {% endif %}
-    <div class="pull-left user-page-picture">
-      <img src="{{ pageUser|picture }}" class="picture picture-rounded">
-    </div>
-    <div class="user-page-meta">
-      <h2>{{ pageUser.name }}</h2>
-      <ul>
-        <li class="user-page-username"><i class="fa fa-user"></i> @{{ pageUser.username }}</li>
-        <li class="user-page-email"><i class="fa fa-envelope-o"></i> {{ pageUser.email }}</li>
-        {% if pageUser.introduction %}
-        <li class="user-page-introduction"><p>{{ pageUser.introduction|nl2br }}</p></li>
-        {% endif %}
-      </ul>
-    </div>
-  </div>
-
-
-  <div class="user-page-content">
-    <ul class="nav nav-tabs user-page-content-menu">
-      <li class="active">
-        <a href="#user-bookmark-list" data-toggle="tab"><i class="fa fa-star"></i> Bookmarks</a>
-      </li>
-      <li>
-        <a href="#user-created-list" data-toggle="tab"><i class="fa fa-pencil"></i> Recent Created</a>
-      </li>
-      {% if user._id.toString() == pageUser._id.toString() %}
-      <li>
-        <a href="/me"><i class="fa fa-gears"></i> Settings</a>
-      </li>
-      {% endif %}
-    </ul>
-    <div class="user-page-content-tab tab-content">
-
-      <div class="tab-pane user-bookmark-list page-list active" id="user-bookmark-list">
-        <div class="page-list-container">
-          {% if bookmarkList.length == 0 %}
-          No bookmarks yet.
-          {% else %}
-            {% include 'widget/page_list.html' with { pages: bookmarkList, pagePropertyName: 'page' } %}
-            <div class="user-page-list-additional-link">
-              <a href="/user/{{ pageUser.username }}/bookmarks"><i class="fa fa-angle-double-right"></i> See bookmarks</a>
-            </div>
-          {% endif %}
-        </div>
-      </div>
-
-      <div class="tab-pane user-created-list page-list" id="user-created-list">
-        <div class="page-list-container">
-          {% if createdList.length == 0 %}
-          No created pages yet.
-          {% else %}
-            {% include 'widget/page_list.html' with { pages: createdList } %}
-            <div class="user-page-list-additional-link">
-              <a href="/user/{{ pageUser.username }}/recent-create"><i class="fa fa-angle-double-right"></i> See created pages</a>
-            </div>
-          {% endif %}
-        </div>
-      </div>
-    </div>
-  </div>
-</div>
-
-{% else %}
-  {% parent %}
-{% endif %}
-
-{% endblock %}
-

+ 4 - 0
lib/views/widget/create_portal.html

@@ -0,0 +1,4 @@
+<div class="portal-form-button">
+  <button class="btn btn-primary" id="create-portal-button" {% if not user %}disabled{% endif %}>Create Portal</button>
+  <p class="help-block"><a href="#" data-target="#help-portal" data-toggle="modal"><i class="icon-question"></i> What is Portal?</a></p>
+</div>

+ 16 - 0
lib/views/widget/favicon.html

@@ -0,0 +1,16 @@
+<link rel="apple-touch-icon" sizes="57x57" href="/images/icons/favicon/apple-icon-57x57.png">
+<link rel="apple-touch-icon" sizes="60x60" href="/images/icons/favicon/apple-icon-60x60.png">
+<link rel="apple-touch-icon" sizes="72x72" href="/images/icons/favicon/apple-icon-72x72.png">
+<link rel="apple-touch-icon" sizes="76x76" href="/images/icons/favicon/apple-icon-76x76.png">
+<link rel="apple-touch-icon" sizes="114x114" href="/images/icons/favicon/apple-icon-114x114.png">
+<link rel="apple-touch-icon" sizes="120x120" href="/images/icons/favicon/apple-icon-120x120.png">
+<link rel="apple-touch-icon" sizes="144x144" href="/images/icons/favicon/apple-icon-144x144.png">
+<link rel="apple-touch-icon" sizes="152x152" href="/images/icons/favicon/apple-icon-152x152.png">
+<link rel="apple-touch-icon" sizes="180x180" href="/images/icons/favicon/apple-icon-180x180.png">
+<link rel="icon" type="image/png" sizes="192x192"  href="/images/icons/favicon/android-icon-192x192.png">
+<link rel="icon" type="image/png" sizes="32x32" href="/images/icons/favicon/favicon-32x32.png">
+<link rel="icon" type="image/png" sizes="96x96" href="/images/icons/favicon/favicon-96x96.png">
+<link rel="icon" type="image/png" sizes="16x16" href="/images/icons/favicon/favicon-16x16.png">
+<meta name="msapplication-TileColor" content="#4f5467">
+<meta name="msapplication-TileImage" content="/images/icons/favicon/ms-icon-144x144.png">
+<meta name="theme-color" content="#4f5467">

+ 6 - 0
lib/views/widget/header-button-bookmark.html

@@ -0,0 +1,6 @@
+{# This widget will be rendered by React #}
+{% if not size == null %}
+  <span id="bookmark-button-{{size}}"></span>
+{% else %}
+  <span id="bookmark-button"></span>
+{% endif %}

+ 7 - 0
lib/views/widget/header-button-like.html

@@ -0,0 +1,7 @@
+<button
+    data-csrftoken="{{ csrf() }}"
+    data-liked="{% if page.isLiked(user) %}1{% else %}0{% endif %}"
+    class="like-button btn btn-default btn-outline btn-circle
+          {% if not size == null %}btn-{{size}}{% endif %}
+          {% if page.isLiked(user) %}active{% endif %}"
+><i class="icon-like"></i></button>

+ 13 - 0
lib/views/widget/header-buttons-lg.html

@@ -0,0 +1,13 @@
+{% if page %}
+  {% set opts = { size: 'lg' }  %}
+  <div>
+    {% if user %}
+      {% include 'header-button-like.html' with opts %}
+    {% endif %}
+  </div>
+  <div class="m-l-5">
+    {% if user %}
+      {% include 'header-button-bookmark.html' with opts %}
+    {% endif %}
+  </div>
+{% endif %}

Некоторые файлы не были показаны из-за большого количества измененных файлов