Jelajahi Sumber

Merge branch 'support/share-link-for-outside-for-merge' into feat/create-route-for-share-access-page

itizawa 5 tahun lalu
induk
melakukan
2d7c726fb8

+ 7 - 2
CHANGES.md

@@ -1,9 +1,14 @@
 # CHANGES
 
-## v4.0.2-RC
+## v4.0.3-RC
+
+* Fix: Editor doesn't work on mobile
+* Fix: navbar is broken on Safari
+
+## v4.0.2
 
 * Fix: Internal Server Error occurred when the guest user access to the pages that has likes
-* Fix: Some buttons are broken in Safari
+* Fix: Some buttons are broken on Safari
 
 ## v4.0.1
 

+ 1 - 1
package.json

@@ -1,6 +1,6 @@
 {
   "name": "growi",
-  "version": "4.0.2-RC",
+  "version": "4.0.3-RC",
   "description": "Team collaboration software using markdown",
   "tags": [
     "wiki",

+ 5 - 0
resource/locales/en-US/translation.json

@@ -678,5 +678,10 @@
     "export_menu": "Export Menu",
     "download": "Download",
     "delete": "Delete"
+  },
+  "login": {
+    "Sign in error": "Login error",
+    "Registration successful": "Registration successful",
+    "Setup": "Setup"
   }
 }

+ 5 - 0
resource/locales/ja/translation.json

@@ -667,5 +667,10 @@
     "export_menu": "エクスポートメニュー",
     "download": "ダウンロード",
     "delete": "削除"
+  },
+  "login": {
+    "Sign in error": "ログインエラー",
+    "Registration successful": "登録完了",
+    "Setup": "セットアップ"
   }
 }

+ 2 - 2
src/client/js/components/PageEditor.jsx

@@ -289,7 +289,7 @@ class PageEditor extends React.Component {
 
     return (
       <div className="d-flex flex-wrap">
-        <div className="page-editor-editor-container" style={{ flex: 1 }}>
+        <div className="page-editor-editor-container flex-grow-1 flex-basis-0 mw-0">
           <Editor
             ref={(c) => { this.editor = c }}
             value={this.state.markdown}
@@ -305,7 +305,7 @@ class PageEditor extends React.Component {
             onSave={this.onSaveWithShortcut}
           />
         </div>
-        <div className="d-none d-xl-block page-editor-preview-container" style={{ flex: 1 }}>
+        <div className="d-none d-xl-block page-editor-preview-container flex-grow-1 flex-basis-0 mw-0">
           <Preview
             markdown={this.state.markdown}
             // eslint-disable-next-line no-return-assign

+ 8 - 4
src/client/js/components/PageEditor/TextAreaEditor.jsx

@@ -3,6 +3,8 @@ import React from 'react';
 
 import InterceptorManager from '@commons/service/interceptor-manager';
 
+import { Input } from 'reactstrap';
+
 import AbstractEditor from './AbstractEditor';
 
 import pasteHelper from './PasteHelper';
@@ -21,6 +23,8 @@ export default class TextAreaEditor extends AbstractEditor {
       isGfmMode: this.props.isGfmMode,
     };
 
+    this.textarea = React.createRef();
+
     this.init();
 
     this.handleEnterKey = this.handleEnterKey.bind(this);
@@ -249,10 +253,10 @@ export default class TextAreaEditor extends AbstractEditor {
   render() {
     return (
       <React.Fragment>
-        <input
-          componentClass="textarea"
-          className="textarea-editor"
-          inputRef={(ref) => { this.textarea = ref }}
+        <Input
+          type="textarea"
+          className="textarea-editor shadow-none"
+          innerRef={(c) => { this.textarea = c }}
           defaultValue={this.state.value}
           onChange={(e) => {
           if (this.props.onChange != null) {

+ 7 - 7
src/client/js/components/SearchForm.jsx

@@ -62,37 +62,37 @@ class SearchForm extends React.Component {
         </caption>
         <tbody>
           <tr>
-            <th className="text-right py-2">
+            <th className="py-2">
               <code>word1</code> <code>word2</code><br></br>
               <small>({ t('search_help.and.syntax help') })</small>
             </th>
             <td><h6 className="m-0">{ t('search_help.and.desc', { word1: 'word1', word2: 'word2' }) }</h6></td>
           </tr>
           <tr>
-            <th className="text-right py-2">
+            <th className="py-2">
               <code>&quot;This is GROWI&quot;</code><br></br>
               <small>({ t('search_help.phrase.syntax help') })</small>
             </th>
             <td><h6 className="m-0">{ t('search_help.phrase.desc', { phrase: 'This is GROWI' }) }</h6></td>
           </tr>
           <tr>
-            <th className="text-right py-2"><code>-keyword</code></th>
+            <th className="py-2"><code>-keyword</code></th>
             <td><h6 className="m-0">{ t('search_help.exclude.desc', { word: 'keyword' }) }</h6></td>
           </tr>
           <tr>
-            <th className="text-right py-2"><code>prefix:/user/</code></th>
+            <th className="py-2"><code>prefix:/user/</code></th>
             <td><h6 className="m-0">{ t('search_help.prefix.desc', { path: '/user/' }) }</h6></td>
           </tr>
           <tr>
-            <th className="text-right py-2"><code>-prefix:/user/</code></th>
+            <th className="py-2"><code>-prefix:/user/</code></th>
             <td><h6 className="m-0">{ t('search_help.exclude_prefix.desc', { path: '/user/' }) }</h6></td>
           </tr>
           <tr>
-            <th className="text-right py-2"><code>tag:wiki</code></th>
+            <th className="py-2"><code>tag:wiki</code></th>
             <td><h6 className="m-0">{ t('search_help.tag.desc', { tag: 'wiki' }) }</h6></td>
           </tr>
           <tr>
-            <th className="text-right py-2"><code>-tag:wiki</code></th>
+            <th className="py-2"><code>-tag:wiki</code></th>
             <td><h6 className="m-0">{ t('search_help.exclude_tag.desc', { tag: 'wiki' }) }</h6></td>
           </tr>
         </tbody>

+ 0 - 1
src/client/styles/scss/_layout.scss

@@ -15,7 +15,6 @@ body {
 }
 
 #page-wrapper {
-  min-width: 0;
   margin-top: $grw-navbar-height + $grw-navbar-border-width;
 }
 

+ 3 - 0
src/client/styles/scss/_navbar.scss

@@ -1,5 +1,8 @@
 .grw-navbar {
+  border-top: 0;
+  border-right: 0;
   border-bottom: $grw-navbar-border-width solid;
+  border-left: 0;
 
   .grw-navbar-toggler {
     padding: 0.5rem;

+ 4 - 10
src/client/styles/scss/_on-edit.scss

@@ -26,8 +26,10 @@ body.on-edit {
   }
 
   // show
-  .d-edit-block {
-    display: block !important;
+  .d-edit-sm-block {
+    @include media-breakpoint-up(sm) {
+      display: block !important;
+    }
   }
 
   // hide unnecessary elements
@@ -134,14 +136,6 @@ body.on-edit {
     }
   }
 
-  // deal with word wrap problem
-  // see: https://qiita.com/mpyw/items/dfc63c1fed5dfc5eda26
-  .page-editor-editor-container,
-  .page-editor-preview-container {
-    min-width: 0;
-    overflow-wrap: break-word;
-  }
-
   /*********************
    * Navigation styles
    */

+ 5 - 0
src/client/styles/scss/_override-bootstrap.scss

@@ -130,4 +130,9 @@
     margin-bottom: 18px;
     overflow: hidden;
   }
+
+  .text-break {
+    word-break: break-word;
+    overflow-wrap: break-word;
+  }
 }

+ 57 - 3
src/client/styles/scss/_search.scss

@@ -66,13 +66,22 @@
     border-bottom-left-radius: 40px;
   }
 
+  .search-typeahead {
+    // corner radius
+    border-top-right-radius: 40px;
+    border-bottom-right-radius: 40px;
+    .rbt-input-main {
+      padding-right: 58px;
+      // corner radius
+      border-top-right-radius: 40px;
+      border-bottom-right-radius: 40px;
+    }
+  }
+
   // using react-bootstrap-typeahead
   // see: https://github.com/ericgio/react-bootstrap-typeahead
   .rbt-input.form-control {
     height: 30px;
-    border-top-right-radius: 40px;
-    border-bottom-right-radius: 40px;
-
     .rbt-input-wrapper {
       margin-left: 8px;
     }
@@ -120,6 +129,22 @@
       @include media-breakpoint-up(md) {
         width: 300px;
       }
+      @include media-breakpoint-up(lg) {
+        // focus
+        &.focus {
+          width: 400px;
+        }
+      }
+      @include media-breakpoint-up(xl) {
+        width: 350px;
+        // focus
+        &.focus {
+          width: 450px;
+        }
+      }
+    }
+    .search-typeahead {
+      border-radius: 0 25px 25px 0;
     }
   }
 }
@@ -210,3 +235,32 @@
     display: table-header-group;
   }
 }
+
+@include media-breakpoint-down(sm) {
+  .grw-search-table {
+    th {
+      text-align: right;
+    }
+  
+    td {
+      overflow-wrap: anywhere;
+      white-space: normal !important;
+    }
+  
+    @include media-breakpoint-down(xs) {
+      th,
+      td {
+        display: block;
+      }
+      
+      th {
+        text-align: left;
+      }
+      
+      td {
+        border-top: none !important;
+        padding-top: 0 !important;
+      }
+    }
+  }
+}

+ 3 - 0
src/client/styles/scss/atoms/_nav.scss

@@ -1,6 +1,9 @@
 .nav-tabs .grw-main-nav-item-left {
   width: $grw-nav-main-left-tab-width;
   text-align: center;
+  @include media-breakpoint-down(xs) {
+    width: 45px;
+  }
 
   .nav-link {
     padding-right: 0;

+ 8 - 0
src/client/styles/scss/style-app.scss

@@ -75,6 +75,14 @@
  * Helper Classes
  */
 
+.mw-0 {
+  min-width: 0;
+}
+
+.flex-basis-0 {
+  flex-basis: 0;
+}
+
 .picture {
   width: 24px;
   height: 24px;

+ 0 - 12
src/client/styles/scss/theme/_apply-colors-light.scss

@@ -38,18 +38,6 @@ $table-hover-bg: $bgcolor-table-hover;
   background-color: darken($bgcolor-global, 5%);
 }
 
-/*
- * GROWI search-top
- */
-.search-top {
-  .btn-group-dropdown-scope .dropdown-toggle {
-    background-color: rgba($bgcolor-global, 0.8);
-  }
-  .rbt-input.form-control {
-    background-color: rgba($bgcolor-global, 0.9);
-  }
-}
-
 /*
  * GROWI subnavigation
  */

+ 5 - 0
src/client/styles/scss/theme/_apply-colors.scss

@@ -154,6 +154,11 @@ pre:not(.hljs):not(.CodeMirror-line) {
   .btn-secondary.dropdown-toggle {
     @include button-variant($bgcolor-search-top-dropdown, $bgcolor-search-top-dropdown);
   }
+
+  // for https://youtrack.weseek.co.jp/issue/GW-2603
+  .search-typeahead {
+    background-color: rgba($bgcolor-global, 0.9);
+  }
 }
 
 .grw-sidebar {

+ 1 - 1
src/lib/components/PagePathHierarchicalLink.jsx

@@ -46,7 +46,7 @@ const PagePathHierarchicalLink = (props) => {
   const RootElm = ({ children }) => {
     return props.isInnerElem
       ? <>{children}</>
-      : <span className="grw-page-path-hierarchical-link">{children}</span>;
+      : <span className="grw-page-path-hierarchical-link text-break">{children}</span>;
   };
 
   return (

+ 8 - 12
src/server/views/layout-growi/base/layout.html

@@ -15,20 +15,16 @@
 </header>
 {% endblock %}
 
-<div class="container-fluid">
-  <div class="row">
-    <div id="main" class="main col-md-12 {% if page %}{{ css.grant(page) }}{% endif %} {% block main_css_class %}{% endblock %}">
-      {% block content_main_before %}
-      {% endblock %}
+<div id="main" class="main container-fluid {% 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 %}
+  {% endblock content_main %}
 
-      {% block content_main_after %}
-      {% endblock %}
-    </div><!-- /.main -->
-  </div><!-- /.row -->
-</div><!-- /.container-fluid -->
+  {% block content_main_after %}
+  {% endblock %}
+</div><!-- /.main -->
 
 <footer class="footer">
   {% include '../../widget/system-version.html' %}

+ 6 - 8
src/server/views/layout-growi/widget/liker-and-seenusers.html

@@ -1,16 +1,14 @@
 <div class="liker-and-seenusers">
-  <div class="text-right">
-    {% if page.liker.length > 10 %}<span class="text-muted">..</span>{% endif %}
-    <span id="liker-list" class="mr-3" data-user-ids="{{ page.liker|slice(-9)|default([])|join(',') }}"></span>
+  <div class="text-truncate text-muted text-right" style="direction: rtl;">
     <span class="text-info">
-      <i class="icon-fw icon-like"></i><span class="liker-user-count">{{ page.liker.length|default(0) }}</span>
+      <span class="liker-user-count">{{ page.liker.length|default(0) }}</span><i class="icon-fw icon-like"></i>
     </span>
+    <span id="liker-list" class="mr-1" data-user-ids="{{ page.liker|slice(-15)|default([])|reverse|join(',') }}"></span>
   </div>
-  <div class="text-right">
-    {% if page.seenUsers.length > 10 %}<span class="text-muted">..</span>{% endif %}
-    <span id="seen-user-list" class="mr-3" data-user-ids="{{ page.seenUsers|slice(-9)|default([])|join(',') }}"></span>
+  <div class="text-truncate text-muted text-right" style="direction: rtl;">
     <span class="text-danger">
-      <i class="icon-fw fa fa-paw"></i><span class="seen-user-count">{{ page.seenUsers.length|default(0) }}</span>
+      <span class="seen-user-count">{{ page.seenUsers.length|default(0) }}</span><i class="fa fa-fw fa-paw"></i>
     </span>
+    <span id="seen-user-list" class="mr-1" data-user-ids="{{ page.seenUsers|slice(-15)|default([])|reverse|join(',') }}"></span>
   </div>
 </div>

+ 1 - 1
src/server/views/layout/layout.html

@@ -118,7 +118,7 @@
     {# Sidebar #}
     <div id="grw-sidebar-wrapper"></div>
 
-    <div class="flex-grow-1">
+    <div class="flex-fill mw-0">
       {% block head_warn_alert_siteurl_undefined %}{% include '../widget/alert_siteurl_undefined.html' %}{% endblock %}
 
       {# Search #}

+ 3 - 3
src/server/views/login/error.html

@@ -2,7 +2,7 @@
 
 {% block html_base_css %}error nologin{% endblock %}
 
-{% block html_title %}{{ customizeService.generateCustomTitleForFixedPageName('セットアップ') }}{% endblock %}
+{% block html_title %}{{ customizeService.generateCustomTitleForFixedPageName(t('login.Setup')) }}{% endblock %}
 
 
 
@@ -33,11 +33,11 @@
       <div class="mb-4 login-form-errors text-center">
         {% if reason === 'registered'%}
         <div class="alert alert-success">
-          <h2>登録完了</h2>
+          <h2>{{ t('login.Registration successful') }}</h2>
         </div>
         {% else %}
         <div class="alert alert-warning">
-            <h2>ログインエラー</h2>
+            <h2>{{ t('login.Sign in error') }}</h2>
         </div>
         {% endif %}
       </div>

+ 1 - 1
src/server/views/widget/not_found_tabs.html

@@ -15,6 +15,6 @@
     </a>
   </li>
 
-  <div id="page-editor-path-nav" class="d-none d-edit-block ml-2"></div>
+  <div id="page-editor-path-nav" class="d-none d-edit-sm-block ml-2"></div>
   {% endif %}
 </ul>

+ 6 - 6
src/server/views/widget/page_tabs.html

@@ -6,7 +6,7 @@
   #}
   <li class="nav-item grw-main-nav-item-left">
     <a class="nav-link active" href="#revision-body" role="tab" data-toggle="tab">
-      <i class="icon-control-play"></i> View
+      <i class="icon-control-play icon-fw"></i><span class="d-none d-sm-inline">View</span>
     </a>
   </li>
 
@@ -19,7 +19,7 @@
           data-toggle="tooltip" data-placement="top" data-container="body" title="{{ t('Not available for guest') }}"
         {% endif %}
       >
-        <i class="icon-note"></i> {{ t('Edit') }}
+        <i class="icon-note icon-fw"></i><span class="d-none d-sm-inline">{{ t('Edit') }}</span>
       </a>
     </li>
 
@@ -32,12 +32,12 @@
           data-toggle="tooltip" data-placement="top" data-container="body" title="{{ t('Not available for guest') }}"
         {% endif %}
       >
-        <i class="fa fa-file-text-o"></i> {{ t('HackMD') }}
+        <i class="fa fa-fw fa-file-text-o"></i><span class="d-none d-sm-inline">{{ t('HackMD') }}</span>
       </a>
     </li>
     {% endif %}
 
-    <div id="page-editor-path-nav" class="d-none d-edit-block ml-2"></div>
+    <div id="page-editor-path-nav" class="d-none d-edit-sm-block ml-2"></div>
   {% endif %}
 
   {#
@@ -51,7 +51,7 @@
   {% if not page.isTopPage() %}
     <li class="nav-item">
       <a href="?presentation=1" class="nav-link toggle-presentation">
-        <i class="icon-film"></i><span class="d-none d-md-inline"> {{ t('Presentation Mode') }}</span>
+        <i class="icon-film icon-fw"></i><span class="d-none d-md-inline">{{ t('Presentation Mode') }}</span>
       </a>
     </li>
   {% endif %}
@@ -59,7 +59,7 @@
   <!-- revision-history -->
   <li class="nav-item">
     <a class="nav-link" href="#revision-history" role="tab" data-toggle="tab">
-      <i class="icon-layers"></i><span class="d-none d-md-inline"> {{ t('History') }}</span>
+      <i class="icon-layers icon-fw"></i><span class="d-none d-md-inline">{{ t('History') }}</span>
     </a>
   </li>
 

+ 1 - 1
src/server/views/widget/page_tabs_kibela.html

@@ -36,7 +36,7 @@
     </li>
     {% endif %}
 
-    <div id="page-editor-path-nav" class="d-none d-edit-block ml-2"></div>
+    <div id="page-editor-path-nav" class="d-none d-edit-sm-block ml-2"></div>
 
   {% endif %}
 

+ 12 - 4
src/server/views/widget/user_page_content.html

@@ -2,20 +2,28 @@
   <ul class="nav nav-tabs user-page-content-menu mb-4" role="tablist">
     <li class="nav-item">
       <a class="nav-link active" href="#user-bookmark-list" role="tab" data-toggle="tab">
-        <i class="icon-star"></i> Bookmarks
+        <i class="icon-star"></i>
+        <span class="d-none d-sm-inline">Bookmarks</span>
       </a>
     </li>
     <li class="nav-item">
       <a class="nav-link" href="#user-created-list" role="tab" data-toggle="tab">
-        <i class="icon-clock"></i> Recently Created
+        <i class="icon-clock"></i>
+        <span class="d-none d-sm-inline">Recently Created</span>
       </a>
     </li>
     <li class="nav-item">
-      <a class="nav-link" href="#user-draft-list" role="tab" data-toggle="tab"><i class="icon-docs"></i> My Drafts</a>
+      <a class="nav-link" href="#user-draft-list" role="tab" data-toggle="tab">
+        <i class="icon-docs"></i>
+        <span class="d-none d-sm-inline">My Drafts</span>
+      </a>
     </li>
     {% if user._id.toString() == pageUser._id.toString() %}
     <li class="nav-item">
-      <a class="nav-link" href="/me" role="tab"><i class="icon-wrench"></i> Settings</a>
+      <a class="nav-link" href="/me" role="tab">
+        <i class="icon-wrench"></i>
+        <span class="d-none d-sm-inline">Settings</span>
+      </a>
     </li>
     {% endif %}
   </ul>