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

success to show nav bar with custom nav bar

kaori 5 лет назад
Родитель
Сommit
fd394fe213

+ 5 - 0
src/client/js/app.jsx

@@ -15,6 +15,9 @@ import PageComments from './components/PageComments';
 import PageTimeline from './components/PageTimeline';
 import CommentEditorLazyRenderer from './components/PageComment/CommentEditorLazyRenderer';
 import PageManagement from './components/Page/PageManagement';
+
+import CustomNavbar from './components/CustomNavbar';
+
 import TrashPageAlert from './components/Page/TrashPageAlert';
 import PageStatusAlert from './components/PageStatusAlert';
 import RecentCreated from './components/RecentCreated/RecentCreated';
@@ -71,6 +74,8 @@ Object.assign(componentMappings, {
 
   'grw-page-status-alert-container': <PageStatusAlert />,
 
+  'custom-nav-bar': <CustomNavbar />,
+
   'trash-page-alert': <TrashPageAlert />,
 
   'page-timeline': <PageTimeline />,

+ 148 - 0
src/client/js/components/CustomNavbar.jsx

@@ -0,0 +1,148 @@
+import React, { useEffect, useState } from 'react';
+import PropTypes from 'prop-types';
+
+import {
+  Nav, NavItem, NavLink, TabContent, TabPane,
+} from 'reactstrap';
+
+import { withTranslation } from 'react-i18next';
+
+
+import PageListIcon from './Icons/PageListIcon';
+import TimeLineIcon from './Icons/TimeLineIcon';
+import RecentChangesIcon from './Icons/RecentChangesIcon';
+import AttachmentIcon from './Icons/AttachmentIcon';
+import ShareLinkIcon from './Icons/ShareLinkIcon';
+
+import { withUnstatedContainers } from './UnstatedUtils';
+import PageAccessoriesContainer from '../services/PageAccessoriesContainer';
+import PageAttachment from './PageAttachment';
+import PageTimeline from './PageTimeline';
+import PageList from './PageList';
+import PageHistory from './PageHistory';
+import ShareLink from './ShareLink/ShareLink';
+
+
+const navTabMapping = {
+  pagelist: {
+    icon: <PageListIcon />,
+    i18n: 'page_list',
+    index: 0,
+  },
+  timeline:  {
+    icon: <TimeLineIcon />,
+    i18n: 'Timeline View',
+    index: 1,
+  },
+  pageHistory: {
+    icon: <RecentChangesIcon />,
+    i18n: 'History',
+    index: 2,
+  },
+  attachment: {
+    icon: <AttachmentIcon />,
+    i18n: 'attachment_data',
+    index: 3,
+  },
+  shareLink: {
+    icon: <ShareLinkIcon />,
+    i18n: 'share_links.share_link_management',
+    index: 4,
+  },
+};
+
+
+const CustomNavbar = (props) => {
+  const { t, pageAccessoriesContainer } = props;
+  const { switchActiveTab } = pageAccessoriesContainer;
+  const { activeTab } = pageAccessoriesContainer.state;
+
+  const [sliderWidth, setSliderWidth] = useState(null);
+  const [sliderMarginLeft, setSliderMarginLeft] = useState(null);
+
+  // Might make this dynamic for px, %, pt, em
+  function getPercentage(min, max) {
+    return min / max * 100;
+  }
+
+  useEffect(() => {
+    if (activeTab === '') {
+      return;
+    }
+
+    const navTitle = document.getElementById('nav-title');
+    const navTabs = document.querySelectorAll('li.nav-link');
+
+    if (navTitle == null || navTabs == null) {
+      return;
+    }
+
+    let tempML = 0;
+
+    const styles = [].map.call(navTabs, (el) => {
+      const width = getPercentage(el.offsetWidth, navTitle.offsetWidth);
+      const marginLeft = tempML;
+      tempML += width;
+      return { width, marginLeft };
+    });
+
+    const { width, marginLeft } = styles[navTabMapping[activeTab].index];
+
+    setSliderWidth(width);
+    setSliderMarginLeft(marginLeft);
+
+  }, [activeTab]);
+
+
+  return (
+    <React.Fragment>
+      <Nav className="nav-title" id="nav-title">
+        {Object.entries(navTabMapping).map(([key, value]) => {
+              return (
+                <NavItem key={key} type="button" className={`p-0 nav-link ${activeTab === key && 'active'}`}>
+                  <NavLink onClick={() => { switchActiveTab(key) }}>
+                    {value.icon}
+                    {t(value.i18n)}
+                  </NavLink>
+                </NavItem>
+              );
+            })}
+      </Nav>
+      <hr className="my-0 grw-nav-slide-hr border-none" style={{ width: `${sliderWidth}%`, marginLeft: `${sliderMarginLeft}%` }} />
+      <TabContent activeTab={activeTab} className="p-5">
+        <TabPane tabId="pagelist">
+          {pageAccessoriesContainer.state.activeComponents.has('pagelist') && <PageList />}
+        </TabPane>
+        <TabPane tabId="timeline">
+          {pageAccessoriesContainer.state.activeComponents.has('timeline') && <PageTimeline /> }
+        </TabPane>
+        <TabPane tabId="pageHistory">
+          <div className="overflow-auto">
+            {pageAccessoriesContainer.state.activeComponents.has('pageHistory') && <PageHistory /> }
+          </div>
+        </TabPane>
+        <TabPane tabId="attachment">
+          {pageAccessoriesContainer.state.activeComponents.has('attachment') && <PageAttachment />}
+        </TabPane>
+        <TabPane tabId="shareLink">
+          {pageAccessoriesContainer.state.activeComponents.has('shareLink') && <ShareLink />}
+        </TabPane>
+      </TabContent>
+    </React.Fragment>
+  );
+};
+
+/**
+ * Wrapper component for using unstated
+ */
+const PageAccessoriesModalWrapper = withUnstatedContainers(CustomNavbar, [PageAccessoriesContainer]);
+
+CustomNavbar.propTypes = {
+  t: PropTypes.func.isRequired, //  i18next
+  // pageContainer: PropTypes.instanceOf(PageContainer).isRequired,
+  pageAccessoriesContainer: PropTypes.instanceOf(PageAccessoriesContainer).isRequired,
+  isOpen: PropTypes.bool.isRequired,
+  onClose: PropTypes.func,
+};
+
+export default withTranslation()(PageAccessoriesModalWrapper);

+ 1 - 0
src/server/views/widget/page_alerts.html

@@ -79,6 +79,7 @@
 
     {% if isTrashPage() %}
       <div id="trash-page-alert"></div>
+      <div id="custom-nav-bar"></div>
     {% endif %}
   </div>
 </div>