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

Merge pull request #6805 from weseek/fix/staff-credit

fix: Staff credit
Yuki Takei 3 лет назад
Родитель
Сommit
84612a510b

BIN
packages/app/public/static/fonts/PressStart2P.ttf


+ 1 - 1
packages/app/src/components/Hotkeys/HotkeysDetector.jsx

@@ -1,6 +1,6 @@
 import React, { useMemo, useCallback } from 'react';
-import PropTypes from 'prop-types';
 
+import PropTypes from 'prop-types';
 import { GlobalHotKeys } from 'react-hotkeys';
 
 import HotkeyStroke from '~/client/models/HotkeyStroke';

+ 3 - 4
packages/app/src/components/Hotkeys/HotkeysManager.jsx

@@ -1,13 +1,12 @@
 import React, { useState } from 'react';
 
 import HotkeysDetector from './HotkeysDetector';
-
-import ShowStaffCredit from './Subscribers/ShowStaffCredit';
-import SwitchToMirrorMode from './Subscribers/SwitchToMirrorMode';
-import ShowShortcutsModal from './Subscribers/ShowShortcutsModal';
 import CreatePage from './Subscribers/CreatePage';
 import EditPage from './Subscribers/EditPage';
 import FocusToGlobalSearch from './Subscribers/FocusToGlobalSearch';
+import ShowShortcutsModal from './Subscribers/ShowShortcutsModal';
+import ShowStaffCredit from './Subscribers/ShowStaffCredit';
+import SwitchToMirrorMode from './Subscribers/SwitchToMirrorMode';
 
 // define supported components list
 const SUPPORTED_COMPONENTS = [

+ 0 - 143
packages/app/src/components/StaffCredit/StaffCredit.jsx

@@ -1,143 +0,0 @@
-import React from 'react';
-
-import PropTypes from 'prop-types';
-import {
-  Modal, ModalBody,
-} from 'reactstrap';
-
-import { apiv3Get } from '~/client/util/apiv3-client';
-import loggerFactory from '~/utils/logger';
-
-
-/**
- * Page staff credit component
- *
- * @export
- * @class StaffCredit
- * @extends {React.Component}
- */
-
-// eslint-disable-next-line no-unused-vars
-const logger = loggerFactory('growi:cli:StaffCredit');
-
-class StaffCredit extends React.Component {
-
-  constructor(props) {
-
-    super(props);
-    this.state = {
-      isShown: true,
-      contributors: null,
-    };
-    this.deleteCredit = this.deleteCredit.bind(this);
-  }
-
-  // to delete the staffCredit and to inform that to Hotkeys.jsx
-  deleteCredit() {
-    if (this.state.isShown) {
-      this.setState({ isShown: false });
-    }
-  }
-
-  renderMembers(memberGroup, keyPrefix) {
-    // construct members elements
-    const members = memberGroup.members.map((member) => {
-      return (
-        <div className={memberGroup.additionalClass} key={`${keyPrefix}-${member.name}-container`}>
-          <span className="dev-position" key={`${keyPrefix}-${member.name}-position`}>
-            {/* position or '&nbsp;' */}
-            { member.position || '\u00A0' }
-          </span>
-          <p className="dev-name" key={`${keyPrefix}-${member.name}`}>{member.name}</p>
-        </div>
-      );
-    });
-    return (
-      <React.Fragment key={`${keyPrefix}-fragment`}>
-        {members}
-      </React.Fragment>
-    );
-  }
-
-  renderContributors() {
-    if (this.state.isShown) {
-      const credit = this.state.contributors.map((contributor) => {
-        // construct members elements
-        const memberGroups = contributor.memberGroups.map((memberGroup, idx) => {
-          return this.renderMembers(memberGroup, `${contributor.sectionName}-group${idx}`);
-        });
-        return (
-          <React.Fragment key={`${contributor.sectionName}-fragment`}>
-            <div className={`row ${contributor.additionalClass}`} key={`${contributor.sectionName}-row`}>
-              <h2 className="col-md-12 dev-team staff-credit-mt-10rem staff-credit-mb-6rem" key={contributor.sectionName}>{contributor.sectionName}</h2>
-              {memberGroups}
-            </div>
-            <div className="clearfix"></div>
-          </React.Fragment>
-        );
-      });
-      return (
-        <div className="text-center staff-credit-content" onClick={this.deleteCredit}>
-          <h1 className="staff-credit-mb-6rem">GROWI Contributors</h1>
-          <div className="clearfix"></div>
-          {credit}
-        </div>
-      );
-    }
-    return null;
-  }
-
-  async componentDidMount() {
-    const res = await apiv3Get('/staffs');
-    const contributors = res.data.contributors;
-    this.setState({ contributors });
-
-    setTimeout(() => {
-      // px / sec
-      const scrollSpeed = 200;
-      const target = $('.credit-curtain');
-      const scrollTargetHeight = target.children().innerHeight();
-      const duration = scrollTargetHeight / scrollSpeed * 1000;
-      target.animate({ scrollTop: scrollTargetHeight }, duration, 'linear');
-      target.slimScroll({
-        height: target.innerHeight(),
-        // Able to scroll after automatic schooling is complete so set "bottom" to allow scrolling from the bottom.
-        start: 'bottom',
-        color: '#FFFFFF',
-      });
-    }, 10);
-  }
-
-  render() {
-    const { onClosed } = this.props;
-
-    if (this.state.contributors === null) {
-      return <></>;
-    }
-
-    return (
-      <Modal
-        isOpen={this.state.isShown}
-        onClosed={() => {
-          if (onClosed != null) {
-            onClosed();
-          }
-        }}
-        toggle={this.deleteCredit}
-        scrollable
-        className="staff-credit"
-      >
-        <ModalBody className="credit-curtain">
-          {this.renderContributors()}
-        </ModalBody>
-      </Modal>
-    );
-  }
-
-}
-
-StaffCredit.propTypes = {
-  onClosed: PropTypes.func,
-};
-
-export default StaffCredit;

+ 5 - 4
packages/app/src/styles/_staff_credit.scss → packages/app/src/components/StaffCredit/StaffCredit.module.scss

@@ -1,5 +1,5 @@
 // Staff Credit
-.staff-credit {
+.staff-credit :global {
   // attached !important for updating from .modal-dialog class style
   width: 80vw !important;
   max-width: unset !important;
@@ -17,13 +17,14 @@
     background-color: black;
     background-image: radial-gradient(rgba(50, 100, 100, 0.75), black 120%);
   }
-  &::after {
+
+  .background {
     position: absolute;
     top: 0;
     left: 0;
     width: 100%;
     height: 100%;
-    content: '';
+    pointer-events: none;
     background: repeating-linear-gradient(0deg, rgba(black, 0.15), rgba(black, 0.15) 2px, transparent 2px, transparent 4px);
   }
 
@@ -35,7 +36,7 @@
   h6,
   .dev-position,
   .dev-name {
-    font-family: 'Press Start 2P', $font-family-for-staff-credit;
+    font-family: 'Press Start 2P', Lato, -apple-system, BlinkMacSystemFont, 'Hiragino Kaku Gothic ProN', Meiryo, sans-serif;
     color: white;
   }
 

+ 139 - 0
packages/app/src/components/StaffCredit/StaffCredit.tsx

@@ -0,0 +1,139 @@
+import React, { useCallback, useState } from 'react';
+
+import { animateScroll } from 'react-scroll';
+import {
+  Modal, ModalBody,
+} from 'reactstrap';
+
+import { useSWRxStaffs } from '~/stores/staff';
+import loggerFactory from '~/utils/logger';
+
+
+import styles from './StaffCredit.module.scss';
+
+
+// eslint-disable-next-line no-unused-vars
+const logger = loggerFactory('growi:cli:StaffCredit');
+
+
+type Props = {
+  onClosed?: () => void,
+}
+
+const StaffCredit = (props: Props): JSX.Element => {
+
+  const { onClosed } = props;
+
+  const { data: contributors } = useSWRxStaffs();
+
+  const [isScrolling, setScrolling] = useState(false);
+
+
+  const closeHandler = useCallback(() => {
+    if (onClosed != null) {
+      onClosed();
+    }
+  }, [onClosed]);
+
+  const contentsClickedHandler = useCallback(() => {
+    if (isScrolling) {
+      setScrolling(false);
+    }
+    else {
+      closeHandler();
+    }
+  }, [closeHandler, isScrolling]);
+
+  const renderMembers = useCallback((memberGroup, keyPrefix) => {
+    // construct members elements
+    const members = memberGroup.members.map((member) => {
+      return (
+        <div className={memberGroup.additionalClass} key={`${keyPrefix}-${member.name}-container`}>
+          <span className="dev-position" key={`${keyPrefix}-${member.name}-position`}>
+            {/* position or '&nbsp;' */}
+            { member.position || '\u00A0' }
+          </span>
+          <p className="dev-name" key={`${keyPrefix}-${member.name}`}>{member.name}</p>
+        </div>
+      );
+    });
+    return (
+      <React.Fragment key={`${keyPrefix}-fragment`}>
+        {members}
+      </React.Fragment>
+    );
+  }, []);
+
+  const renderContributors = useCallback(() => {
+    if (contributors == null) {
+      return <></>;
+    }
+
+    const credit = contributors.map((contributor) => {
+      // construct members elements
+      const memberGroups = contributor.memberGroups.map((memberGroup, idx) => {
+        return renderMembers(memberGroup, `${contributor.sectionName}-group${idx}`);
+      });
+      return (
+        <React.Fragment key={`${contributor.sectionName}-fragment`}>
+          <div className={`row ${contributor.additionalClass}`} key={`${contributor.sectionName}-row`}>
+            <h2 className="col-md-12 dev-team staff-credit-mt-10rem staff-credit-mb-6rem" key={contributor.sectionName}>{contributor.sectionName}</h2>
+            {memberGroups}
+          </div>
+          <div className="clearfix"></div>
+        </React.Fragment>
+      );
+    });
+    return (
+      <div className="text-center staff-credit-content" onClick={contentsClickedHandler}>
+        <h1 className="staff-credit-mb-6rem">GROWI Contributors</h1>
+        <div className="clearfix"></div>
+        {credit}
+      </div>
+    );
+  }, [contentsClickedHandler, contributors, renderMembers]);
+
+
+  const openedHandler = useCallback(() => {
+    // init
+    animateScroll.scrollTo(0, { containerId: 'modalBody', duration: 0 });
+
+    setScrolling(true);
+
+    // start scrolling
+    animateScroll.scrollToBottom({
+      containerId: 'modalBody',
+      smooth: 'linear',
+      delay: 200,
+      duration: (scrollDistanceInPx: number) => {
+        const scrollSpeed = 200;
+        return scrollDistanceInPx / scrollSpeed * 1000;
+      },
+    });
+  }, []);
+
+
+  const isLoaded = contributors !== undefined;
+
+  if (contributors == null) {
+    return <></>;
+  }
+
+  return (
+    <Modal
+      isOpen={isLoaded}
+      toggle={closeHandler}
+      scrollable
+      className={`staff-credit ${styles['staff-credit']}`}
+      onOpened={openedHandler}
+    >
+      <ModalBody id="modalBody" className="credit-curtain">
+        {renderContributors()}
+      </ModalBody>
+      <div className="background"></div>
+    </Modal>
+  );
+
+};
+
+export default StaffCredit;

+ 1 - 0
packages/app/src/pages/_document.page.tsx

@@ -28,6 +28,7 @@ class GrowiDocument extends Document {
           {renderScriptTagsByGroup('basis')}
           {renderStyleTagsByGroup('basis')}
           */}
+          <link rel='preload' href="/static/fonts/PressStart2P.ttf" as="font" type="font/ttf" />
         </Head>
         <body>
           <Main />

+ 12 - 0
packages/app/src/stores/staff.tsx

@@ -0,0 +1,12 @@
+import useSWR, { SWRResponse } from 'swr';
+
+import { apiv3Get } from '~/client/util/apiv3-client';
+
+export const useSWRxStaffs = (): SWRResponse<any, Error> => {
+  return useSWR(
+    '/staffs',
+    endpoint => apiv3Get(endpoint).then((response) => {
+      return response.data.contributors;
+    }),
+  );
+};

+ 6 - 0
packages/app/src/styles/_fonts.scss

@@ -0,0 +1,6 @@
+@font-face {
+  font-family: 'Press Start 2P';
+  font-style: normal;
+  font-weight: normal;
+  src: url('/static/fonts/PressStart2P.ttf');
+}

+ 0 - 1
packages/app/src/styles/_variables.scss

@@ -9,7 +9,6 @@ $grw-marker-blue: #6cf;
 $grw-marker-cyan: #6ff;
 $grw-marker-green: #6f6;
 
-$font-family-for-staff-credit: Lato, -apple-system, BlinkMacSystemFont, 'Hiragino Kaku Gothic ProN', Meiryo, sans-serif !default;
 $font-family-monospace-not-strictly: Monaco, Menlo, Consolas, 'Courier New', MeiryoKe_Gothic, monospace;
 
 //== Layout

+ 1 - 1
packages/app/src/styles/style-next.scss

@@ -46,6 +46,7 @@
 // @import 'create-page';
 // @import 'draft';
 @import 'editor';
+@import 'fonts';
 // @import 'handsontable';
 @import 'layout';
 // @import 'login';
@@ -69,7 +70,6 @@
 @import 'tag';
 // @import 'toc';
 // @import 'user';
-// @import 'staff_credit';
 // @import 'waves';
 @import 'wiki';
 // @import 'sharelink';