Sfoglia il codice sorgente

Merge pull request #1809 from weseek/feat/sidebar-by-atlaskit

Feat/sidebar by atlaskit
Yuki Takei 6 anni fa
parent
commit
00baa0648c

+ 3 - 0
babel.config.js

@@ -26,6 +26,9 @@ module.exports = function(api) {
         },
         },
       },
       },
     ],
     ],
+    [
+      '@babel/plugin-proposal-class-properties', { loose: true },
+    ],
   ];
   ];
 
 
   return {
   return {

+ 5 - 0
package.json

@@ -152,7 +152,11 @@
       "handsontable: v7.0.0 or above is no loger MIT lisence."
       "handsontable: v7.0.0 or above is no loger MIT lisence."
     ],
     ],
     "@alienfast/i18next-loader": "^1.0.16",
     "@alienfast/i18next-loader": "^1.0.16",
+    "@atlaskit/drawer": "^5.3.5",
+    "@atlaskit/logo": "^12.3.3",
+    "@atlaskit/navigation-next": "^8.0.2",
     "@babel/core": "^7.4.5",
     "@babel/core": "^7.4.5",
+    "@babel/plugin-proposal-class-properties": "^7.8.3",
     "@babel/polyfill": "^7.4.4",
     "@babel/polyfill": "^7.4.4",
     "@babel/preset-env": "^7.4.5",
     "@babel/preset-env": "^7.4.5",
     "@babel/preset-react": "^7.0.0",
     "@babel/preset-react": "^7.0.0",
@@ -233,6 +237,7 @@
     "socket.io-client": "^2.0.3",
     "socket.io-client": "^2.0.3",
     "sticky-events": "^3.1.3",
     "sticky-events": "^3.1.3",
     "style-loader": "^1.0.0",
     "style-loader": "^1.0.0",
+    "styled-components": "^5.0.1",
     "stylelint": "^13.2.0",
     "stylelint": "^13.2.0",
     "stylelint-config-recess-order": "^2.0.1",
     "stylelint-config-recess-order": "^2.0.1",
     "swagger-jsdoc": "^3.4.0",
     "swagger-jsdoc": "^3.4.0",

+ 3 - 0
src/client/js/bootstrap.jsx

@@ -5,6 +5,7 @@ import Xss from '@commons/service/xss';
 
 
 import HeaderSearchBox from './components/HeaderSearchBox';
 import HeaderSearchBox from './components/HeaderSearchBox';
 import PersonalDropdown from './components/Navbar/PersonalDropdown';
 import PersonalDropdown from './components/Navbar/PersonalDropdown';
+import Sidebar from './components/Sidebar';
 import StaffCredit from './components/StaffCredit/StaffCredit';
 import StaffCredit from './components/StaffCredit/StaffCredit';
 
 
 import AppContainer from './services/AppContainer';
 import AppContainer from './services/AppContainer';
@@ -40,6 +41,8 @@ const componentMappings = {
   'search-sidebar': <HeaderSearchBox crowi={appContainer} />,
   'search-sidebar': <HeaderSearchBox crowi={appContainer} />,
   'personal-dropdown': <PersonalDropdown />,
   'personal-dropdown': <PersonalDropdown />,
 
 
+  'grw-sidebar': <Sidebar />,
+
   'staff-credit': <StaffCredit />,
   'staff-credit': <StaffCredit />,
 };
 };
 
 

+ 34 - 0
src/client/js/components/GrowiLogo.jsx

@@ -0,0 +1,34 @@
+import React from 'react';
+
+const GrowiLogo = () => (
+  <svg
+    xmlns="http://www.w3.org/2000/svg"
+    width="32"
+    height="32"
+    viewBox="0 0 226.44 196.11"
+  >
+    <path
+      d="M56.61 196.11L169.83 196.11 226.44 98.06 188.7 98.06 150.96 163.43 75.48 163.43 56.61 196.11z"
+      className="group2"
+    >
+    </path>
+    <path
+      // eslint-disable-next-line max-len
+      d="M75.48 98.05L94.35 65.37 150.96 65.38 207.57 65.37 207.57 65.38 226.44 98.06 169.83 98.06 113.22 98.06 94.39 130.66 94.3 130.66 84.92 114.4 75.48 98.05z"
+      className="group1"
+    >
+    </path>
+    <path
+      d="M0 98.06L56.6 0 113.22 0.01 169.83 0.01 169.83 0.01 188.69 32.68 132.09 32.69 75.47 32.69 18.86 130.74 0 98.06z"
+      className="group1"
+    >
+    </path>
+    <path
+      d="M75.48 163.43L56.61 130.74 37.71 163.46 47.15 179.81 56.54 196.07 56.63 196.07 75.48 163.43z"
+      className="group1"
+    >
+    </path>
+  </svg>
+);
+
+export default GrowiLogo;

+ 110 - 0
src/client/js/components/Sidebar.jsx

@@ -0,0 +1,110 @@
+import React from 'react';
+// import PropTypes from 'prop-types';
+
+import { withTranslation } from 'react-i18next';
+
+import BacklogIcon from '@atlaskit/icon/glyph/backlog';
+import BoardIcon from '@atlaskit/icon/glyph/board';
+import GraphLineIcon from '@atlaskit/icon/glyph/graph-line';
+import ShortcutIcon from '@atlaskit/icon/glyph/shortcut';
+import { JiraWordmark } from '@atlaskit/logo';
+
+import {
+  GroupHeading,
+  HeaderSection,
+  Item,
+  LayoutManager,
+  MenuSection,
+  NavigationProvider,
+  Separator,
+  Wordmark,
+  ThemeProvider, modeGenerator,
+} from '@atlaskit/navigation-next';
+
+import { createSubscribedElement } from './UnstatedUtils';
+import AppContainer from '../services/AppContainer';
+
+import SidebarNav from './Sidebar/SidebarNav';
+
+class Sidebar extends React.Component {
+
+  static propTypes = {
+  };
+
+  state = {
+  };
+
+  renderSidebarContents = () => (
+    <>
+      <HeaderSection>
+        { () => (
+          <div className="grw-product-nav-header">
+            <Wordmark wordmark={JiraWordmark} />
+          </div>
+        ) }
+      </HeaderSection>
+      <MenuSection>
+        { () => (
+          <div className="grw-product-nav-menu">
+            <Item
+              before={BacklogIcon}
+              text="Backlog"
+              isSelected
+            />
+            <Item
+              before={BoardIcon}
+              text="Active sprints"
+            />
+            <Item
+              before={GraphLineIcon}
+              text="Reports"
+            />
+            <Separator />
+            <GroupHeading>Shortcuts</GroupHeading>
+            <Item before={ShortcutIcon} text="Project space" />
+            <Item before={ShortcutIcon} text="Looooooooooooooooooooooooooooooong Menu" />
+          </div>
+        ) }
+      </MenuSection>
+    </>
+  );
+
+  render() {
+    return (
+      <ThemeProvider
+        theme={theme => ({
+          ...theme,
+          context: 'product',
+          mode: modeGenerator({
+            product: { text: '#ffffff', background: '#334455' },
+          }),
+        })}
+      >
+        <NavigationProvider>
+          <LayoutManager
+            globalNavigation={SidebarNav}
+            productNavigation={() => null}
+            containerNavigation={this.renderSidebarContents}
+            experimental_flyoutOnHover
+            experimental_alternateFlyoutBehaviour
+            // experimental_fullWidthFlyout
+            shouldHideGlobalNavShadow
+            showContextualNavigation
+          >
+          </LayoutManager>
+        </NavigationProvider>
+      </ThemeProvider>
+    );
+  }
+
+}
+
+
+/**
+ * Wrapper component for using unstated
+ */
+const SidebarWrapper = (props) => {
+  return createSubscribedElement(Sidebar, props, [AppContainer]);
+};
+
+export default withTranslation()(SidebarWrapper);

+ 64 - 0
src/client/js/components/Sidebar/SidebarNav.jsx

@@ -0,0 +1,64 @@
+import React from 'react';
+// import PropTypes from 'prop-types';
+
+import { withTranslation } from 'react-i18next';
+
+import EditIcon from '@atlaskit/icon/glyph/edit';
+import TrayIcon from '@atlaskit/icon/glyph/tray';
+
+import {
+  GlobalNav,
+} from '@atlaskit/navigation-next';
+import Drawer from '@atlaskit/drawer';
+
+import { createSubscribedElement } from '../UnstatedUtils';
+import AppContainer from '../../services/AppContainer';
+
+import GrowiLogo from '../GrowiLogo';
+
+class SidebarNav extends React.Component {
+
+  propTypes = {
+  };
+
+  state = {
+    isDrawerOpen: false,
+  };
+
+  openDrawer = () => this.setState({ isDrawerOpen: true });
+
+  closeDrawer = () => this.setState({ isDrawerOpen: false });
+
+  render() {
+    const { isDrawerOpen } = this.state;
+    return (
+      <>
+        <div className="grw-logo">
+          <GrowiLogo />
+        </div>
+        <GlobalNav
+          primaryItems={[
+            { id: 'create', icon: EditIcon, label: 'Create' },
+            {
+              id: 'drawer', icon: TrayIcon, label: 'Drawer', onClick: this.openDrawer,
+            },
+          ]}
+          secondaryItems={[]}
+        />
+        <Drawer onClose={this.closeDrawer} isOpen={isDrawerOpen} width="wide">
+          <code>Drawer contents</code>
+        </Drawer>
+      </>
+    );
+  }
+
+}
+
+/**
+ * Wrapper component for using unstated
+ */
+const SidebarNavWrapper = (props) => {
+  return createSubscribedElement(SidebarNav, props, [AppContainer]);
+};
+
+export default withTranslation()(SidebarNavWrapper);

+ 11 - 7
src/client/styles/scss/_layout.scss

@@ -10,13 +10,11 @@
   padding-top: 10px !important;
   padding-top: 10px !important;
 }
 }
 
 
-.logo {
-  .logo-mark {
-    svg {
-      width: $grw-logo-width;
-      height: $grw-navbar-height;
-      padding: ($grw-logo-width - $grw-logomark-width) / 2;
-    }
+.grw-logo {
+  svg {
+    width: $grw-logo-width;
+    height: $grw-navbar-height;
+    padding: ($grw-logo-width - $grw-logomark-width) / 2;
   }
   }
   /*
   /*
   .logo-text {
   .logo-text {
@@ -32,6 +30,12 @@
   font-weight: bold;
   font-weight: bold;
 }
 }
 
 
+.grw-sidebar {
+  .ak-navigation-resize-button {
+    top: 110px;
+  }
+}
+
 /*
 /*
   * header
   * header
   */
   */

+ 24 - 17
src/client/styles/scss/theme/_apply-colors.scss

@@ -49,37 +49,38 @@ $link-hover-color: $color-link-hover;
 //== Apply to GROWI Elements
 //== Apply to GROWI Elements
 //
 //
 
 
-.logo {
+.grw-logo {
   // set transition for fill
   // set transition for fill
   svg * {
   svg * {
     transition: fill 0.8s ease-out;
     transition: fill 0.8s ease-out;
   }
   }
 
 
-  .logo-mark {
-    svg {
-      fill: $fillcolor-logo-mark;
+  svg {
+    fill: $fillcolor-logo-mark;
+  }
 
 
-      &:hover {
-        .group1 {
-          fill: $growi-green;
-        }
+  &:hover {
+    svg {
+      .group1 {
+        fill: $growi-green;
+      }
 
 
-        .group2 {
-          fill: $growi-blue;
-        }
+      .group2 {
+        fill: $growi-blue;
       }
       }
     }
     }
   }
   }
 }
 }
 
 
 .grw-navbar {
 .grw-navbar {
-  background: $bgcolor-navbar;
+  // TODO: coloring
+  // background: $bgcolor-navbar;
+  // .nav-item > .nav-link {
+  //   color: white;
+  // }
+  background: darken($bgcolor-global, 8%);
   .nav-item > .nav-link {
   .nav-item > .nav-link {
-    color: white;
-  }
-
-  .logo {
-    background-color: darken($bgcolor-navbar, 10%);
+    color: #333;
   }
   }
 }
 }
 
 
@@ -87,6 +88,12 @@ $link-hover-color: $color-link-hover;
   background: darken($bgcolor-global, 2%);
   background: darken($bgcolor-global, 2%);
 }
 }
 
 
+.grw-sidebar {
+  .grw-logo {
+    background-color: darken($bgcolor-navbar, 10%);
+  }
+}
+
 /*
 /*
  * code color of inline-code
  * code color of inline-code
  */
  */

+ 52 - 109
src/server/views/layout/layout.html

@@ -71,128 +71,71 @@
   data-userlang="{% if user %}{{ user.lang }}{% endif %}"
   data-userlang="{% if user %}{{ user.lang }}{% endif %}"
  >
  >
 
 
-<div id="wrapper">
-  <!-- Navigation -->
-  {% block layout_head_nav %}
-  <nav class="navbar grw-navbar navbar-expand-sm navbar-dark mb-0 p-0">
-    <!-- 1 GROWI logo -->
-    <div class="navbar-brand">
-      <a class="logo d-block" href="/">
-        <div class="logo-mark d-inline-block">{% include '../widget/logo.html' %}</div>
-        {#
-        <span class="logo-text mx-2">
-          {% set appTitle = appService.getAppTitle() %}
-          {% set appTitleFontSize = getAppTitleFontSize(appTitle) %}
-          <text x="0" y="{{22+appTitleFontSize/2}}" font-size="{{appTitleFontSize}}">
-            {% block title %}{{ appTitle }}{% endblock %}
-          </text>
-        </span>
-        #}
-      </a>
-    </div>
+<div id="wrapper" class="d-flex">
 
 
-    <ul class="navbar-nav mr-auto">
-      {#
-      <!-- 2 side nav open -->
-      <a class="open-close d-none d-md-block mx-3 waves-effect waves-light">
-        <i class="ti-menu"></i>
-      </a>
-      #}
-      {#  disabled temporary -- 2019.05.13 Yuki Takei
-      <li class="nav-item">
-        <a class="nav-link" href="/tags">
-          <i class="tag-icon icon-tag"></i><span>{{ t('Tags') }}</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>
-        {#  disabled temporary -- 2019.05.13 Yuki Takei
-        <li>
-          <li class="nav-item-admin">
-            <a href="/tags">
-              <i class="tag-icon icon-tag"></i><span>{{ t('Tags') }}</span>
-            </a>
-          </li>
-        </li>
-        #}
+  {# Sidebar #}
+  <nav>
+    <div id="grw-sidebar" class="grw-sidebar"></div>
+  </nav>
+
+  <div class="flex-grow-1">
+
+    {% block layout_head_nav %}
+    <nav class="navbar grw-navbar navbar-expand-sm navbar-dark mb-0 p-0">
+      {# Navbar Left #}
+      <ul class="navbar-nav mr-auto pl-4">
         <li>
         <li>
           {% if isSearchServiceConfigured() %}
           {% if isSearchServiceConfigured() %}
           <div class="navbar-form navbar-left search-top" role="search" id="search-top"></div>
           <div class="navbar-form navbar-left search-top" role="search" id="search-top"></div>
           {% endif %}
           {% endif %}
         </li>
         </li>
       </ul>
       </ul>
-    </ul>
-
-    <!-- 5 user action -->
-    <ul class="navbar-nav">
-      {% if user and user.admin %}
-      <li class="nav-item">
-        <a class="nav-link" href="/admin">
-          <i class="icon-settings mr-2"></i>
-          <span class="d-none d-md-inline-block">{{ t('Admin') }}</span>
-        </a>
-      </li>
-      {% endif %}
-
-      {% if user %}
-      <li class="nav-item">
-        <a class="nav-link" href="#" data-target="#create-page" data-toggle="modal">
-          <i class="icon-pencil mr-2"></i>
-          <span class="d-none d-md-inline-block">{{ t('New') }}</span>
-        </a>
-      </li>
-      <li class="nav-item">
-        <a class="nav-link" href="https://docs.growi.org/" target="_blank">
-          <i class="icon-question mr-2"></i><span class="d-none d-md-inline-block mr-2">{{ t('Help') }}</span><span class="text-muted small"><i class="icon-share-alt"></i></span>
-        </a>
-      </li>
-      <li id="personal-dropdown" class="nav-item dropdown"></li>
-      {% else %}
-      <li id="login-user" class="nav-item"><a class="nav-link" href="/login">Login</a></li>
-      {% endif %}
-      {% if getConfig('crowi', 'app:confidential') %}
-      <li class="nav-item confidential text-light">{{ getConfig('crowi', 'app:confidential') }}</li>
-      {% endif %}
-    </ul>
 
 
-  </nav>
-  {% include '../modal/create_page.html' %}
-  {% endblock  %} {# layout_head_nav #}
-
-  <!-- 6 header widget area -->
-  {% block head_warn_alert_siteurl_undefined %}{% include '../widget/alert_siteurl_undefined.html' %}{% endblock %}
-  {% block head_warn_breaking_changes %}{% include '../widget/alert_breaking_changes.html' %}{% endblock %}
-
-  {% block sidebar %}
-  <!-- Left navbar-header -->
-  {#
-  <div class="navbar-default sidebar hidden-print" 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 isSearchServiceConfigured() %}
-          <div class="search-sidebar" role="search" id="search-sidebar"></div>
-          {% endif %}
+      {# Navbar Right #}
+      <ul class="navbar-nav">
+        {% if user and user.admin %}
+        <li class="nav-item">
+          <a class="nav-link" href="/admin">
+            <i class="icon-settings mr-2"></i>
+            <span class="d-none d-md-inline-block">{{ t('Admin') }}</span>
+          </a>
         </li>
         </li>
+        {% endif %}
 
 
-        <li class="tbd"><a href="#">(TBD) Create /Sidebar</a></li>
+        {% if user %}
+        <li class="nav-item">
+          <a class="nav-link" href="#" data-target="#create-page" data-toggle="modal">
+            <i class="icon-pencil mr-2"></i>
+            <span class="d-none d-md-inline-block">{{ t('New') }}</span>
+          </a>
+        </li>
+        <li class="nav-item">
+          <a class="nav-link" href="https://docs.growi.org/" target="_blank">
+            <i class="icon-question mr-2"></i><span class="d-none d-md-inline-block mr-2">{{ t('Help') }}</span><span class="text-muted small"><i class="icon-share-alt"></i></span>
+          </a>
+        </li>
+        <li id="personal-dropdown" class="nav-item dropdown"></li>
+        {% else %}
+        <li id="login-user" class="nav-item"><a class="nav-link" href="/login">Login</a></li>
+        {% endif %}
+        {% if getConfig('crowi', 'app:confidential') %}
+        <li class="nav-item confidential text-light">{{ getConfig('crowi', 'app:confidential') }}</li>
+        {% endif %}
       </ul>
       </ul>
+
+    </nav>
+    {% include '../modal/create_page.html' %}
+    {% endblock  %} {# layout_head_nav #}
+
+    {% block head_warn_alert_siteurl_undefined %}{% include '../widget/alert_siteurl_undefined.html' %}{% endblock %}
+    {% block head_warn_breaking_changes %}{% include '../widget/alert_breaking_changes.html' %}{% endblock %}
+
+    <div id="page-wrapper">
+      {% block layout_main %}
+      {% endblock %} {# layout_main #}
     </div>
     </div>
-  </div>
-  #}
-  <!-- Left navbar-header end -->
-  {% endblock %}
 
 
-  <!-- 8 Page Content -->
-  <div id="page-wrapper">
-    {% block layout_main %}
-    {% endblock %} {# layout_main #}
-  </div><!-- /#page-wrapper -->
+  </div>
 
 
 </div><!-- /#wrapper -->
 </div><!-- /#wrapper -->
 
 

File diff suppressed because it is too large
+ 673 - 12
yarn.lock


Some files were not shown because too many files changed in this diff