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

Merge branch 'master' into feat/admin-typescriptzation-integrate

ryoji-s 3 лет назад
Родитель
Сommit
39129eb9ab

+ 6 - 2
packages/app/src/components/PageAttachment.tsx

@@ -5,7 +5,8 @@ import React, {
 import { HasObjectId, IAttachment } from '@growi/core';
 
 import { useSWRxAttachments } from '~/stores/attachment';
-import { useEditingMarkdown, useCurrentPageId, useIsGuestUser } from '~/stores/context';
+import { useCurrentPageId, useIsGuestUser } from '~/stores/context';
+import { useSWRxCurrentPage } from '~/stores/page';
 
 import { DeleteAttachmentModal } from './PageAttachment/DeleteAttachmentModal';
 import { PageAttachmentList } from './PageAttachment/PageAttachmentList';
@@ -17,10 +18,13 @@ const checkIfFileInUse = (markdown: string, attachment): boolean => {
 };
 
 const PageAttachment = (): JSX.Element => {
+
+  const { data: currentPage } = useSWRxCurrentPage();
+  const markdown = currentPage?.revision.body;
+
   // Static SWRs
   const { data: pageId } = useCurrentPageId();
   const { data: isGuestUser } = useIsGuestUser();
-  const { data: markdown } = useEditingMarkdown();
 
   // States
   const [pageNumber, setPageNumber] = useState(1);

+ 11 - 15
packages/app/src/components/PageAttachment/PageAttachmentList.tsx

@@ -1,11 +1,9 @@
 import React from 'react';
 
-
 import { HasObjectId, IAttachment } from '@growi/core';
 import { Attachment } from '@growi/ui';
 import { useTranslation } from 'next-i18next';
 
-
 type Props = {
   attachments: (IAttachment & HasObjectId)[],
   inUse: { [id: string]: boolean },
@@ -24,22 +22,20 @@ export const PageAttachmentList = (props: Props): JSX.Element => {
     return <>{t('No_attachments_yet')}</>;
   }
 
-  const attachmentList = attachments.map((attachment) => {
-    return (
-      <Attachment
-        key={`page:attachment:${attachment._id}`}
-        attachment={attachment}
-        inUse={inUse[attachment._id] || false}
-        onAttachmentDeleteClicked={onAttachmentDeleteClicked}
-        isUserLoggedIn={isUserLoggedIn}
-      />
-    );
-  });
-
   return (
     <div>
       <ul className="pl-2">
-        {attachmentList}
+        {attachments.map((attachment) => {
+          return (
+            <Attachment
+              key={`page:attachment:${attachment._id}`}
+              attachment={attachment}
+              inUse={inUse[attachment._id] || false}
+              onAttachmentDeleteClicked={onAttachmentDeleteClicked}
+              isUserLoggedIn={isUserLoggedIn}
+            />
+          );
+        })}
       </ul>
     </div>
   );

+ 3 - 4
packages/app/src/components/PageEditor.tsx

@@ -15,8 +15,8 @@ import { apiGet, apiPostForm } from '~/client/util/apiv1-client';
 import { getOptionsToSave } from '~/client/util/editor';
 import { IEditorMethods } from '~/interfaces/editor-methods';
 import {
-  useCurrentPagePath, useCurrentPathname, useCurrentPageId, useEditingMarkdown,
-  useIsEditable, useIsIndentSizeForced, useIsUploadableFile, useIsUploadableImage,
+  useCurrentPagePath, useCurrentPathname, useCurrentPageId,
+  useIsEditable, useIsIndentSizeForced, useIsUploadableFile, useIsUploadableImage, useEditingMarkdown,
 } from '~/stores/context';
 import {
   useCurrentIndentSize, useSWRxSlackChannels, useIsSlackEnabled, useIsTextlintEnabled, usePageTagsForEditors,
@@ -55,10 +55,9 @@ const PageEditor = React.memo((): JSX.Element => {
   const { data: currentPagePath } = useCurrentPagePath();
   const { data: currentPathname } = useCurrentPathname();
   const { data: currentPage, mutate: mutateCurrentPage } = useSWRxCurrentPage();
-  const { data: editingMarkdown } = useEditingMarkdown();
   const { data: grantData, mutate: mutateGrant } = useSelectedGrant();
   const { data: pageTags } = usePageTagsForEditors(pageId);
-
+  const { data: editingMarkdown } = useEditingMarkdown();
   const { data: isEditable } = useIsEditable();
   const { data: editorMode, mutate: mutateEditorMode } = useEditorMode();
   const { data: isMobile } = useIsMobile();

+ 1 - 0
packages/app/src/pages/[[...path]].page.tsx

@@ -247,6 +247,7 @@ const GrowiPage: NextPage<Props> = (props: Props) => {
 
   useSWRxCurrentPage(undefined, pageWithMeta?.data ?? null); // store initial data
   useEditingMarkdown(pageWithMeta?.data.revision?.body ?? '');
+
   const { data: dataPageInfo } = useSWRxPageInfo(pageId);
   const { data: grantData } = useSWRxIsGrantNormalized(pageId);
   const { mutate: mutateSelectedGrant } = useSelectedGrant();

+ 4 - 0
packages/core/src/interfaces/attachment.ts

@@ -8,4 +8,8 @@ export type IAttachment = {
 
   // virtual property
   filePathProxied: string,
+
+  fileFormat: string,
+  downloadPathProxied: string,
+  originalName: string,
 };

+ 0 - 86
packages/ui/src/components/Attachment/Attachment.jsx

@@ -1,86 +0,0 @@
-import React from 'react';
-
-import PropTypes from 'prop-types';
-
-
-import { UserPicture } from '../User/UserPicture';
-
-export class Attachment extends React.Component {
-
-  constructor(props) {
-    super(props);
-
-    this._onAttachmentDeleteClicked = this._onAttachmentDeleteClicked.bind(this);
-  }
-
-  iconNameByFormat(format) {
-    if (format.match(/image\/.+/i)) {
-      return 'icon-picture';
-    }
-
-    return 'icon-doc';
-  }
-
-  _onAttachmentDeleteClicked(event) {
-    if (this.props.onAttachmentDeleteClicked != null) {
-      this.props.onAttachmentDeleteClicked(this.props.attachment);
-    }
-  }
-
-  render() {
-    const attachment = this.props.attachment;
-    const formatIcon = this.iconNameByFormat(attachment.fileFormat);
-
-    let fileInUse = '';
-    if (this.props.inUse) {
-      fileInUse = <span className="attachment-in-use badge badge-pill badge-info">In Use</span>;
-    }
-
-    const fileType = <span className="attachment-filetype badge badge-pill badge-secondary">{attachment.fileFormat}</span>;
-
-    const btnDownload = (this.props.isUserLoggedIn)
-      ? (
-        <a className="attachment-download" href={attachment.downloadPathProxied}>
-          <i className="icon-cloud-download" />
-        </a>
-      )
-      : '';
-
-    const btnTrash = (this.props.isUserLoggedIn)
-      ? (
-        /* eslint-disable-next-line */
-        <a className="text-danger attachment-delete" onClick={this._onAttachmentDeleteClicked}>
-          <i className="icon-trash" />
-        </a>
-      )
-      : '';
-
-    return (
-      <div className="attachment mb-2">
-        <span className="mr-1 attachment-userpicture">
-          <UserPicture user={attachment.creator} size="sm"></UserPicture>
-        </span>
-        <a className="mr-2" href={attachment.filePathProxied} target="_blank" rel="noopener noreferrer">
-          <i className={formatIcon}></i> {attachment.originalName}
-        </a>
-        <span className="mr-2">{fileType}</span>
-        <span className="mr-2">{fileInUse}</span>
-        <span className="mr-2">{btnDownload}</span>
-        <span className="mr-2">{btnTrash}</span>
-      </div>
-    );
-  }
-
-}
-
-Attachment.propTypes = {
-  attachment: PropTypes.object.isRequired,
-  inUse: PropTypes.bool,
-  onAttachmentDeleteClicked: PropTypes.func,
-  isUserLoggedIn: PropTypes.bool,
-};
-
-Attachment.defaultProps = {
-  inUse: false,
-  isUserLoggedIn: false,
-};

+ 58 - 0
packages/ui/src/components/Attachment/Attachment.tsx

@@ -0,0 +1,58 @@
+import React from 'react';
+
+import { HasObjectId, IAttachment } from '@growi/core';
+
+import { UserPicture } from '../User/UserPicture';
+
+type AttachmentProps = {
+  attachment: IAttachment & HasObjectId,
+  inUse: boolean,
+  onAttachmentDeleteClicked?: (attachment: IAttachment & HasObjectId) => void,
+  isUserLoggedIn?: boolean,
+};
+
+export const Attachment = (props: AttachmentProps): JSX.Element => {
+
+  const {
+    attachment, inUse, isUserLoggedIn, onAttachmentDeleteClicked,
+  } = props;
+
+  const _onAttachmentDeleteClicked = () => {
+    if (onAttachmentDeleteClicked != null) {
+      onAttachmentDeleteClicked(attachment);
+    }
+  };
+
+  const formatIcon = (attachment.fileFormat.match(/image\/.+/i)) ? 'icon-picture' : 'icon-doc';
+  const btnDownload = (isUserLoggedIn)
+    ? (
+      <a className="attachment-download" href={attachment.downloadPathProxied}>
+        <i className="icon-cloud-download" />
+      </a>
+    )
+    : '';
+  const btnTrash = (isUserLoggedIn)
+    ? (
+      <a className="text-danger attachment-delete" onClick={_onAttachmentDeleteClicked}>
+        <i className="icon-trash" />
+      </a>
+    )
+    : '';
+  const fileType = <span className="attachment-filetype badge badge-pill badge-secondary">{attachment.fileFormat}</span>;
+  const fileInUse = (inUse) ? <span className="attachment-in-use badge badge-pill badge-info">In Use</span> : '';
+
+  return (
+    <div className="attachment mb-2">
+      <span className="mr-1 attachment-userpicture">
+        <UserPicture user={attachment.creator} size="sm"></UserPicture>
+      </span>
+      <a className="mr-2" href={attachment.filePathProxied} target="_blank" rel="noopener noreferrer">
+        <i className={formatIcon}></i> {attachment.originalName}
+      </a>
+      <span className="mr-2">{fileType}</span>
+      <span className="mr-2">{fileInUse}</span>
+      <span className="mr-2">{btnDownload}</span>
+      <span className="mr-2">{btnTrash}</span>
+    </div>
+  );
+};