|
|
@@ -1,24 +1,81 @@
|
|
|
-import React from 'react';
|
|
|
+import React, { useMemo, useCallback } from 'react';
|
|
|
|
|
|
-type AttachmentProps = {
|
|
|
- className?: string,
|
|
|
- url: string,
|
|
|
- attachmentName: string,
|
|
|
- attachmentId: string,
|
|
|
-}
|
|
|
+import { UserPicture } from '@growi/ui';
|
|
|
+import prettyBytes from 'pretty-bytes';
|
|
|
|
|
|
-export const Attachment = React.memo((props: AttachmentProps): JSX.Element => {
|
|
|
- const { className, url, attachmentName } = props;
|
|
|
+import { useSWRxAttachments } from '~/stores/attachment';
|
|
|
+import { useCurrentPageId } from '~/stores/page';
|
|
|
+
|
|
|
+export const Attachment: React.FC<{
|
|
|
+ attachmentId: string
|
|
|
+}> = React.memo(({ attachmentId }) => {
|
|
|
+ const { data: pageId } = useCurrentPageId();
|
|
|
+ // TODO: We need to be able to get it from all pages if there are a lot of attachments.
|
|
|
+ const { data: dataAttachments, remove } = useSWRxAttachments(pageId, 1);
|
|
|
+
|
|
|
+ const attachment = useMemo(() => {
|
|
|
+ if (dataAttachments == null) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ return dataAttachments.attachments.find(item => item._id === attachmentId);
|
|
|
+ }, [attachmentId, dataAttachments]);
|
|
|
+
|
|
|
+ const handleAttachmentDelete = useCallback(async() => {
|
|
|
+ if (attachment == null) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ try {
|
|
|
+ await remove({ attachment_id: attachment._id });
|
|
|
+ // TODO: success notification
|
|
|
+ }
|
|
|
+ catch (err) {
|
|
|
+ // TODO: error handling
|
|
|
+ }
|
|
|
+ }, [attachment, remove]);
|
|
|
+
|
|
|
+ // TODO: update fo attachment is not found
|
|
|
+ // TODO: fix hydration failed error
|
|
|
+ if (attachment == null) {
|
|
|
+ return (
|
|
|
+ <div className='text-muted'>This attachment not found.</div>
|
|
|
+ );
|
|
|
+ }
|
|
|
|
|
|
return (
|
|
|
- <div className="card">
|
|
|
- <h3 className="card-title m-0">Remark Attachment Component</h3>
|
|
|
+ <div className="card my-3" style={{ width: 'fit-content' }}>
|
|
|
<div className="card-body">
|
|
|
- <a className={className} href={url}>
|
|
|
- {attachmentName}
|
|
|
- </a>
|
|
|
+ <div className='row'>
|
|
|
+ {/* TODO: Design check */}
|
|
|
+ <div className='col-2'>
|
|
|
+ <i className='icon-doc' style={{ fontSize: '2.7rem' }}/>
|
|
|
+ </div>
|
|
|
+ <div className='col-10'>
|
|
|
+ <div>
|
|
|
+ <a href={attachment.downloadPathProxied}>{attachment.originalName}</a>
|
|
|
+ <span className='ml-2'>
|
|
|
+ <a className="attachment-download" href={attachment.downloadPathProxied}>
|
|
|
+ <i className="icon-cloud-download" />
|
|
|
+ </a>
|
|
|
+ </span>
|
|
|
+ <span className='ml-2'>
|
|
|
+ <a className="text-danger attachment-delete" onClick={handleAttachmentDelete}>
|
|
|
+ <i className="icon-trash" />
|
|
|
+ </a>
|
|
|
+ </span>
|
|
|
+ </div>
|
|
|
+ <div>
|
|
|
+ <UserPicture user={attachment.creator} size="sm"></UserPicture>
|
|
|
+ {/* TODO: check locale */}
|
|
|
+ <span className='ml-2 text-muted'>{new Date(attachment.createdAt).toLocaleString('ja-JP')}</span>
|
|
|
+ <span className='border-left ml-2 pl-2 text-muted'>{prettyBytes(attachment.fileSize)}</span>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
</div>
|
|
|
</div>
|
|
|
+
|
|
|
);
|
|
|
});
|
|
|
Attachment.displayName = 'Attachment';
|