Browse Source

improve reply component, add timestamp and reply number

Klaudiusz Dembler 4 years ago
parent
commit
0e8e1d8ba1
2 changed files with 93 additions and 34 deletions
  1. 88 34
      pioneer/packages/joy-forum/src/ViewReply.tsx
  2. 5 0
      types/src/forum.ts

+ 88 - 34
pioneer/packages/joy-forum/src/ViewReply.tsx

@@ -2,7 +2,8 @@ import React, { useState } from 'react';
 import styled from 'styled-components';
 import { Link } from 'react-router-dom';
 import ReactMarkdown from 'react-markdown';
-import { Segment, Button } from 'semantic-ui-react';
+import Tooltip from 'react-tooltip';
+import { Segment, Button, Icon } from 'semantic-ui-react';
 
 import { Post, Category, Thread } from '@joystream/types/forum';
 import { Moderate } from './Moderate';
@@ -10,11 +11,42 @@ import { JoyWarn } from '@polkadot/joy-utils/JoyStatus';
 import { useMyAccount } from '@polkadot/joy-utils/MyAccountContext';
 import { IfIAmForumSudo } from './ForumSudo';
 import { MemberPreview } from '@polkadot/joy-members/MemberPreview';
-import { FlexCenter } from '@polkadot/joy-utils/FlexCenter';
 
-const ReplyDetails = styled(ReactMarkdown)`
+const HORIZONTAL_PADDING = '1em';
+const ReplyMarkdown = styled(ReactMarkdown)`
   font-size: 1.15rem;
 `;
+const ReplyContainer = styled(Segment)`
+  && {
+    padding: 0;
+  }
+  overflow: hidden;
+`;
+const ReplyHeader = styled.div`
+  background-color: #fafcfc;
+`;
+const ReplyHeaderAuthorRow = styled.div`
+  padding: 0.7em ${HORIZONTAL_PADDING};
+`;
+const ReplyHeaderDetailsRow = styled.div`
+  padding: 0.5em ${HORIZONTAL_PADDING};
+  border-top: 1px dashed rgba(34, 36, 38, .15);
+  border-bottom: 1px solid rgba(34, 36, 38, .15);
+  display: flex;
+  justify-content: space-between;
+`;
+const ReplyContent = styled.div`
+  padding: 1em ${HORIZONTAL_PADDING};
+`;
+const ReplyFooter = styled.div`
+  border-top: 1px solid rgba(34, 36, 38, .15);
+  background-color: #fafcfc;
+  padding: 0.5em ${HORIZONTAL_PADDING};
+`;
+const ReplyFooterActionsRow = styled.div`
+  display: flex;
+  justify-content: space-between;
+`;
 
 type ViewReplyProps = {
   reply: Post;
@@ -33,7 +65,7 @@ export function ViewReply (props: ViewReplyProps) {
   }
 
   const renderReplyDetails = () => {
-    return <ReplyDetails className='JoyMemo--full' source={reply.current_text} linkTarget='_blank' />;
+    return <ReplyMarkdown className='JoyMemo--full' source={reply.current_text} linkTarget='_blank' />;
   };
 
   const renderModerationRationale = () => {
@@ -51,43 +83,65 @@ export function ViewReply (props: ViewReplyProps) {
       return null;
     }
     const isMyPost = reply.author_id.eq(myAddress);
-    return <span className='JoyInlineActions' style={{ marginLeft: '.5rem' }}>
-      {isMyPost &&
-        <Link
-          to={`/forum/replies/${id.toString()}/edit`}
-          className='ui small button'
-        >
-          <i className='pencil alternate icon' />
-          Edit
-        </Link>
-      }
+    return <ReplyFooterActionsRow>
+      <div>
+        {isMyPost &&
+          <Button as={Link} to={`/forum/replies/${id.toString()}/edit`} size="mini">
+            <Icon name="pencil" />
+            Edit
+          </Button>
+        }
 
-      <IfIAmForumSudo>
-        <Button
-          type='button'
-          size='small'
-          content={'Moderate'}
-          onClick={() => setShowModerateForm(!showModerateForm)}
-        />
-      </IfIAmForumSudo>
-    </span>;
+        <IfIAmForumSudo>
+          <Button
+            size="mini"
+            onClick={() => setShowModerateForm(!showModerateForm)}
+          >
+            Moderate
+          </Button>
+        </IfIAmForumSudo>
+      </div>
+      <Button size="mini">
+        <Icon name="quote left" />
+        Quote
+      </Button>
+    </ReplyFooterActionsRow>;
   };
 
+  const replyDate = reply.created_at.momentDate;
+
   return (
-    <Segment>
-      <FlexCenter>
-        <MemberPreview accountId={reply.author_id} />
-        {renderActions()}
-      </FlexCenter>
-      <div style={{ marginTop: '1rem' }}>
-        {showModerateForm &&
-          <Moderate id={id} onCloseForm={() => setShowModerateForm(false)} />
-        }
+    <ReplyContainer>
+      <ReplyHeader>
+        <ReplyHeaderAuthorRow>
+          <MemberPreview accountId={reply.author_id} />
+        </ReplyHeaderAuthorRow>
+        <ReplyHeaderDetailsRow>
+          <span data-tip data-for="reply-full-date">
+            {replyDate.fromNow()}
+          </span>
+          <Tooltip id="reply-full-date" place="top" effect="solid">
+            {replyDate.toLocaleString()}
+          </Tooltip>
+          <a>
+            #{reply.nr_in_thread.toNumber()}
+          </a>
+        </ReplyHeaderDetailsRow>
+      </ReplyHeader>
+
+      <ReplyContent>
         {reply.moderated
           ? renderModerationRationale()
           : renderReplyDetails()
         }
-      </div>
-    </Segment>
+      </ReplyContent>
+
+      <ReplyFooter>
+        {renderActions()}
+        {showModerateForm &&
+          <Moderate id={id} onCloseForm={() => setShowModerateForm(false)} />
+        }
+      </ReplyFooter>
+    </ReplyContainer>
   );
 }

+ 5 - 0
types/src/forum.ts

@@ -1,6 +1,7 @@
 import { getTypeRegistry, bool, u16, u32, u64, Text, Option, Vec as Vector} from '@polkadot/types';
 import { AccountId, Moment, BlockNumber } from '@polkadot/types/interfaces';
 import { GenericAccountId } from '@polkadot/types';
+import moment from 'moment';
 
 import { JoyStruct } from './JoyStruct';
 
@@ -27,6 +28,10 @@ export class BlockchainTimestamp extends JoyStruct<BlockchainTimestampType> {
     return this.getField('time');
   }
 
+  get momentDate (): moment.Moment {
+    return moment(this.time.toNumber());
+  }
+
   static newEmpty (): BlockchainTimestamp {
     return new BlockchainTimestamp({} as BlockchainTimestampType);
   }