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

Merge branch 'feat/transplant-tabs-to-modal-for-master-merge' into feat/gw-3308-seenuser

oshikishintaro 5 лет назад
Родитель
Сommit
af250b2f44

+ 2 - 0
resource/locales/en_US/translation.json

@@ -45,6 +45,7 @@
   "List View": "List",
   "Timeline View": "Timeline",
   "History": "History",
+  "attachment_data": "Attachment Data",
   "Presentation Mode": "Presentation",
   "Not available for guest": "Not available for guest",
   "username": "Username",
@@ -108,6 +109,7 @@
   "Specified users only": "Specified users only",
   "Only me": "Only me",
   "Only inside the group": "Only inside the group",
+  "page_list": "Page List",
   "page_list_and_search_results": "Page list / Search results",
   "scope_of_page_disclosure": "Scope of page disclosure",
   "set_point": "Set point",

+ 3 - 1
resource/locales/ja_JP/translation.json

@@ -43,8 +43,9 @@
   "Example": "例",
   "Taro Yamada": "山田 太郎",
   "List View": "リスト表示",
-  "Timeline View": "タイムライン表示",
+  "Timeline View": "タイムライン",
   "History": "更新履歴",
+  "attachment_data": "添付データ",
   "Presentation Mode": "プレゼンテーション",
   "Not available for guest": "ゲストユーザーは利用できません",
   "username": "ユーザー名",
@@ -107,6 +108,7 @@
   "Specified users": "特定ユーザーのみ",
   "Only me": "自分のみ",
   "Only inside the group": "特定グループのみ",
+  "page_list": "ページリスト",
   "page_list_and_search_results": "ページリスト・検索結果",
   "scope_of_page_disclosure": "ページの公開範囲",
   "set_point": "設定値",

+ 4 - 2
resource/locales/zh_CN/translation.json

@@ -45,7 +45,8 @@
 	"Taro Yamada": "John Doe",
 	"List View": "列表",
 	"Timeline View": "时间线",
-	"History": "历史",
+  "History": "历史",
+  "attachment_data": "Attachment Data",
 	"Presentation Mode": "演示文稿",
 	"Not available for guest": "Not available for guest",
 	"username": "用户名",
@@ -113,7 +114,8 @@
 	"Anyone with the link": "任何人",
 	"Specified users only": "仅指定用户",
 	"Only me": "只有我",
-	"Only inside the group": "仅组内",
+  "Only inside the group": "仅组内",
+  "page_list": "Page List",
 	"page_list_and_search_results": "页面列表/搜索结果",
 	"scope_of_page_disclosure": "页面公开范围",
 	"set_point": "设定值",

+ 1 - 0
src/client/js/components/Attachment.jsx

@@ -8,6 +8,7 @@ const Attachment = () => (
     width="20"
     height="20"
   >
+    <rect width="14" height="14" fillOpacity="0" />
     <g className="cls-1">
       <path
         d="M2.9,13a2,2,0,0,1-1.44-.63,2.28,2.28,0,0,1,0-3.23l7-7.38a2.48,2.48,0,0,1,1.22-.7,2.61,

+ 103 - 0
src/client/js/components/PageAccessoriesModal.jsx

@@ -0,0 +1,103 @@
+import React from 'react';
+import PropTypes from 'prop-types';
+
+import {
+  Modal, ModalBody, Nav, NavItem, NavLink, TabContent,
+} from 'reactstrap';
+
+import { withTranslation } from 'react-i18next';
+
+import PageList from './PageList';
+import TimeLine from './TimeLine';
+import RecentChanges from './RecentChanges';
+import Attachment from './Attachment';
+
+import { withUnstatedContainers } from './UnstatedUtils';
+import PageContainer from '../services/PageContainer';
+
+const PageAccessoriesModal = (props) => {
+  const { t } = props;
+
+  function closeModalHandler() {
+    if (props.onClose == null) {
+      return;
+    }
+    props.onClose();
+  }
+
+  function switchTabHandler(clickedTab) {
+    if (props.onSwitch == null) {
+      return;
+    }
+    props.onSwitch(clickedTab);
+  }
+
+  return (
+    <React.Fragment>
+      <Modal
+        size="lg"
+        isOpen={props.isOpen}
+        toggle={closeModalHandler}
+        className="grw-page-accessories-modal"
+      >
+        <ModalBody>
+          <Nav className="nav-title border-bottom">
+            <NavItem className={`nav-link ${props.activeTab === 'pageList' && 'active'}`}>
+              <NavLink
+                onClick={() => { switchTabHandler('pageList') }}
+              >
+                <PageList />
+                { t('page_list') }
+              </NavLink>
+            </NavItem>
+            <NavItem className={`nav-link ${props.activeTab === 'timeLine' && 'active'}`}>
+              <NavLink
+                onClick={() => { switchTabHandler('timeLine') }}
+              >
+                <TimeLine />
+                { t('Timeline View') }
+              </NavLink>
+            </NavItem>
+            <NavItem className={`nav-link ${props.activeTab === 'recentChanges' && 'active'}`}>
+              <NavLink
+                onClick={() => { switchTabHandler('recentChanges') }}
+              >
+                <RecentChanges />
+                { t('History') }
+              </NavLink>
+            </NavItem>
+            <NavItem className={`nav-link ${props.activeTab === 'attachment' && 'active'}`}>
+              <NavLink
+                onClick={() => { switchTabHandler('attachment') }}
+              >
+                <Attachment />
+                { t('attachment_data') }
+              </NavLink>
+            </NavItem>
+          </Nav>
+          <TabContent>
+          </TabContent>
+        </ModalBody>
+      </Modal>
+    </React.Fragment>
+  );
+};
+
+
+/**
+ * Wrapper component for using unstated
+ */
+const PageAccessoriesModalWrapper = withUnstatedContainers(PageAccessoriesModal, [PageContainer]);
+
+
+PageAccessoriesModal.propTypes = {
+  t: PropTypes.func.isRequired, //  i18next
+  pageContainer: PropTypes.instanceOf(PageContainer).isRequired,
+
+  isOpen: PropTypes.bool.isRequired,
+  onClose: PropTypes.func,
+  activeTab: PropTypes.string.isRequired,
+  onSwitch: PropTypes.func,
+};
+
+export default withTranslation()(PageAccessoriesModalWrapper);

+ 1 - 0
src/client/js/components/PageList.jsx

@@ -8,6 +8,7 @@ const PageList = () => (
     width="20"
     height="20"
   >
+    <rect width="14" height="14" fillOpacity="0" />
     <path d="M12.63,2.72H1.37a.54.54,0,0,1,0-1.08H12.63a.54.54,0,0,1,0,1.08Z" />
     <path d="M11.82,5.94H1.37a.55.55,0,0,1,0-1.09H11.82a.55.55,0,1,1,0,1.09Z" />
     <path d="M9.41,9.15h-8a.54.54,0,0,1,0-1.08h8a.54.54,0,0,1,0,1.08Z" />

+ 1 - 0
src/client/js/components/RecentChanges.jsx

@@ -8,6 +8,7 @@ const RecentChanges = () => (
     width="20"
     height="20"
   >
+    <rect width="14" height="14" fillOpacity="0" />
     <path
       d="M7.94.94A6.13,6.13,0,0,0,1.89,7v.1L.67,5.89a.38.38,0,0,0-.55,0,.39.39,0,0,0,0,.56L2.36,8.69,4.6,6.45a.4.4,0,0,0,0-.56.39.39,0,0,0-.56,
       0L2.68,7.25V7A5.33,5.33,0,0,1,7.94,1.73,5.33,5.33,0,0,1,13.21,7a5.34,5.34,0,0,1-5.27,5.27H7.86A5,5,0,0,1,4,10.38a.4.4,0,0,0-.55-.07.4.4,0,

+ 1 - 0
src/client/js/components/TimeLine.jsx

@@ -8,6 +8,7 @@ const TimeLine = () => (
     width="20"
     height="20"
   >
+    <rect width="14" height="14" fillOpacity="0" />
     <path
       d="M13.6,4.6a1.2,1.2,0,0,1-1.2,1.2,1,1,0,0,1-.3,0L10,7.89a1.1,1.1,0,0,1,0,.31,1.2,1.2,0,1,1-2.4,0,1.1,1.1,0,0,1,
       0-.31L6.11,6.36a1.3,1.3,0,0,1-.62,0L2.75,9.1a1,1,0,0,1,0,.3A1.2,1.2,0,1,1,1.6,8.2a1,1,0,0,1,.3,0L4.64,

+ 41 - 7
src/client/js/components/TopOfTableContents.jsx

@@ -1,4 +1,4 @@
-import React from 'react';
+import React, { useState } from 'react';
 import PropTypes from 'prop-types';
 
 import { withTranslation } from 'react-i18next';
@@ -10,26 +10,61 @@ import TimeLine from './TimeLine';
 import RecentChanges from './RecentChanges';
 import Attachment from './Attachment';
 
+import PageAccessoriesModal from './PageAccessoriesModal';
+
 import { withUnstatedContainers } from './UnstatedUtils';
 
 const TopOfTableContents = (props) => {
 
+  const [isPageAccessoriesModalShown, setIsPageAccessoriesModalShown] = useState(false);
+  const [activeTab, setActiveTab] = useState('');
+  // Prevent unnecessary rendering
+  const [activeComponents, setActiveComponents] = useState(new Set(['']));
+
+  function openPageAccessoriesModal(activeTab) {
+    setIsPageAccessoriesModalShown(true);
+    setActiveTab(activeTab);
+  }
+
+  function switchActiveTab(clickedTab) {
+    activeComponents.add(clickedTab);
+    setActiveComponents(activeComponents);
+    setActiveTab(clickedTab);
+  }
+
+  function closePageAccessoriesModal() {
+    setIsPageAccessoriesModalShown(false);
+  }
+
+  function renderModal() {
+    return (
+      <>
+        <PageAccessoriesModal
+          isOpen={isPageAccessoriesModalShown}
+          onClose={closePageAccessoriesModal}
+          activeTab={activeTab}
+          onSwitch={switchActiveTab}
+        />
+      </>
+    );
+  }
+
   return (
     <>
       <div className="top-of-table-contents d-flex align-items-end pb-1">
-        <button type="button" className="bg-transparent border-0">
+        <button type="button" className="bg-transparent border-0" onClick={() => openPageAccessoriesModal('pageList')}>
           <PageList />
         </button>
 
-        <button type="button" className="bg-transparent border-0">
+        <button type="button" className="bg-transparent border-0 active" onClick={() => openPageAccessoriesModal('timeLine')}>
           <TimeLine />
         </button>
 
-        <button type="button" className="bg-transparent border-0">
+        <button type="button" className="bg-transparent border-0" onClick={() => openPageAccessoriesModal('recentChanges')}>
           <RecentChanges />
         </button>
 
-        <button type="button" className="bg-transparent border-0">
+        <button type="button" className="bg-transparent border-0" onClick={() => openPageAccessoriesModal('attachment')}>
           <Attachment />
         </button>
         {/* [TODO: setting Footprints' icon by GW-3308] */}
@@ -40,11 +75,10 @@ const TopOfTableContents = (props) => {
         >
         </div>
       </div>
+      {renderModal()}
     </>
   );
-
 };
-
 /**
  * Wrapper component for using unstated
  */

+ 6 - 0
src/client/styles/scss/_layout_growi.scss

@@ -22,6 +22,12 @@
     }
   }
 
+  .grw-page-accessories-modal {
+    .table-top-icon {
+      margin-right: 5px;
+    }
+  }
+
   .revision-toc {
     position: sticky;
     // growisubnavigation + grw-navbar-boder

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

@@ -254,6 +254,18 @@ pre:not(.hljs):not(.CodeMirror-line) {
   }
 }
 
+.grw-page-accessories-modal {
+  .nav-title {
+    color: $color-link;
+  }
+  .table-top-icon {
+    fill: $color-link;
+  }
+  .active {
+    border-bottom: 2px solid $color-link;
+  }
+}
+
 /*
  * cards
  */