-
Notifications
You must be signed in to change notification settings - Fork 71
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
16 changed files
with
843 additions
and
10 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,67 @@ | ||
import React, { useState } from 'react' | ||
import { CommentUserIcon, CommentThreadStart, CommentThreadEnd } from './Share' | ||
import { CommentViewing } from './Viewing' | ||
import { CommentEditing } from './Editing' | ||
import clsx from 'clsx' | ||
|
||
const CommentCompanyLink = ({ user }) => { | ||
if (!user.company || !user.adviser) return <></> | ||
return ( | ||
<a className="thread-comment__company-link" href={user.url}> | ||
<img className="thread-comment__company-logo" src={user.logo_url} /> | ||
</a> | ||
) | ||
} | ||
|
||
const Comment = ({ | ||
comment, | ||
currentUser, | ||
isLatest, | ||
isValidating, | ||
availableEmojis, | ||
onDeleteComment, | ||
onUpdateComment, | ||
className, | ||
...props | ||
}) => { | ||
const [editing, setEditing] = useState(false) | ||
|
||
return ( | ||
<div | ||
className={clsx('thread-comment', { 'is-latest': isLatest }, className)} | ||
{...props} | ||
> | ||
{/* | ||
id="latest-comment"は最新のコメントへのリンク先です | ||
アプリ内の複数箇所でリンク先として設定されています | ||
*/} | ||
{isLatest && <div id='latest-comment' />} | ||
<CommentThreadStart> | ||
<a className="thread-comment__user-link" href={comment.user.url}> | ||
<CommentUserIcon user={comment.user} /> | ||
</a> | ||
<CommentCompanyLink user={comment.user} /> | ||
</CommentThreadStart> | ||
<CommentThreadEnd> | ||
{editing | ||
? <CommentEditing | ||
comment={comment} | ||
isValidating={isValidating} | ||
onStopEditing={() => setEditing(false)} | ||
onUpdateComment={onUpdateComment} | ||
/> | ||
: <CommentViewing | ||
comment={comment} | ||
currentUser={currentUser} | ||
availableEmojis={availableEmojis} | ||
onStartEditing={() => setEditing(true)} | ||
onDeleteComment={onDeleteComment} | ||
/>} | ||
</CommentThreadEnd> | ||
</div> | ||
) | ||
} | ||
|
||
export { | ||
Comment, | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,143 @@ | ||
import React, { useState, useRef } from 'react' | ||
import { | ||
CommentThreadStart, | ||
CommentThreadEnd, | ||
CommentUserIcon, | ||
CommentTab, | ||
} from './Share' | ||
import * as Markdown from '../Markdown' | ||
import * as Card from '../ui/Card' | ||
import { useTextarea } from './useTextarea' | ||
import toast from '../../toast' | ||
|
||
/* コメントフォーム */ | ||
const CommentForm = ({ | ||
onCreateCommentAndWatch, | ||
onCreateCheck, | ||
onBecomeResponsibleMentor, | ||
isCheckable, | ||
isPreventCommentAndCheck, | ||
currentUser, | ||
}) => { | ||
const [description, setDescription] = useState('') | ||
const isValidDescrption = description.length > 0 | ||
// 'comment' | 'preview' | ||
const [activeTab, setActiveTab] = useState('comment') | ||
const isActive = (tab) => tab === activeTab | ||
const textareaRef = useRef(null) | ||
const previewRef = useRef(null) | ||
useTextarea(textareaRef) | ||
const [isPosting, setIsPosting] = useState(false) | ||
|
||
// Markdownのプレビュー要素の削除 | ||
const removePreviewLastChild = () => { | ||
while (previewRef.current.lastChild) { | ||
previewRef.current.removeChild(previewRef.current.lastChild) | ||
} | ||
} | ||
|
||
const handleClickCreateComment = () => { | ||
setIsPosting(true) | ||
try { | ||
// コメントの作成とWatchをして、担当者になる | ||
onCreateCommentAndWatch(description) | ||
onBecomeResponsibleMentor() | ||
toast.methods.toast('コメントを投稿して担当者になりました') | ||
} catch (error) { | ||
toast.methods.toast('コメントの投稿に失敗しました', 'error') | ||
} finally { | ||
// クリーンアップ | ||
setDescription('') | ||
removePreviewLastChild() | ||
setActiveTab('comment') | ||
setIsPosting(false) | ||
// this.resizeTextarea() | ||
} | ||
} | ||
|
||
const handleClickCreateCommentAndCheck = () => { | ||
if (isPreventCommentAndCheck()) return | ||
setIsPosting(true) | ||
try { | ||
// コメントの作成とWatchをして、確認OKにする | ||
onCreateCommentAndWatch(description) | ||
onCreateCheck() | ||
toast.methods.toast('コメントを投稿して確認OKにしました') | ||
} catch (error) { | ||
toast.methods.toast('コメントの投稿に失敗しました', 'error') | ||
} finally { | ||
// クリーンアップ | ||
setDescription('') | ||
removePreviewLastChild() | ||
setActiveTab('comment') | ||
setIsPosting(false) | ||
// this.resizeTextarea() | ||
} | ||
} | ||
|
||
return ( | ||
<div className="thread-comment-form"> | ||
{/* ログインユーザーのプロフィール画像 */} | ||
<CommentThreadStart> | ||
<CommentUserIcon | ||
user={currentUser} | ||
/> | ||
</CommentThreadStart> | ||
{/* コメントフォーム本体 */} | ||
<CommentThreadEnd> | ||
<Card.Root className='thread-comment-form__form'> | ||
{/* フォームのエディターモードとプレビューモードの切り替え */} | ||
<CommentTab isActive={isActive} setActiveTab={setActiveTab}/> | ||
{/* Markdownエディターとプレビュー */} | ||
<Markdown.Root> | ||
<Markdown.Item isActive={isActive('comment')}> | ||
<Markdown.Form> | ||
<Markdown.Textarea | ||
id='js-new-comment' | ||
variant='warning' | ||
data-preview='#new-comment-preview' | ||
data-input='#new-comment-file-input' | ||
name='new_comment[description]' | ||
description={description} | ||
setDescription={setDescription} | ||
ref={textareaRef} | ||
/> | ||
<Markdown.File id='new-comment-file-input' /> | ||
</Markdown.Form> | ||
</Markdown.Item> | ||
<Markdown.Item isActive={isActive('preview')}> | ||
<Markdown.Preview id='new-comment-preview' ref={previewRef} /> | ||
</Markdown.Item> | ||
</Markdown.Root> | ||
<Card.Footer> | ||
{/* コメント送信ボタン */} | ||
<Card.FooterItem> | ||
<button | ||
id='js-shortcut-post-comment' | ||
className='a-button is-sm is-primary is-block' | ||
onClick={handleClickCreateComment} | ||
disabled={!isValidDescrption || isPosting} | ||
> | ||
コメントする | ||
</button> | ||
</Card.FooterItem> | ||
{/* コメント・確認OK送信ボタン */} | ||
{isCheckable && | ||
<Card.FooterItem> | ||
<button | ||
className='a-button is-sm is-danger is-block' | ||
onClick={handleClickCreateCommentAndCheck} | ||
disabled={!isValidDescrption || isPosting} | ||
> | ||
<i className="fa-solid fa-check" /> 確認OKにする | ||
</button> | ||
</Card.FooterItem> | ||
} | ||
</Card.Footer> | ||
</Card.Root> | ||
</CommentThreadEnd> | ||
</div> | ||
) | ||
} | ||
|
||
export default CommentForm |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,45 @@ | ||
import React from 'react' | ||
|
||
const Placeholder = () => { | ||
return ( | ||
<div className="thread-comment"> | ||
<div className="thread-comment__start"> | ||
<div className="thread-comment__user-icon a-user-icon a-placeholder"></div> | ||
</div> | ||
<div className="thread-comment__end"> | ||
<div className="a-card is-loading"> | ||
<div className="card-header"> | ||
<div className="thread-comment__title"> | ||
<div className="thread-comment__title-link a-placeholder"></div> | ||
</div> | ||
<div className="thread-comment__created-at a-placeholder"></div> | ||
</div> | ||
<hr className="a-border-tint" /> | ||
<div className="thread-comment__description"> | ||
<div className="a-long-text is-md a-placeholder"> | ||
<p></p> | ||
<p></p> | ||
<p></p> | ||
<p></p> | ||
<p></p> | ||
<p></p> | ||
</div> | ||
</div> | ||
</div> | ||
</div> | ||
</div> | ||
) | ||
} | ||
|
||
const CommentPlaceholder = () => { | ||
const placeholderCount = 3 | ||
return( | ||
<div id="comments" className="thread-comments loading"> | ||
{Array.from({ length: placeholderCount }, (_, index) => ( | ||
<Placeholder key={index} /> | ||
))} | ||
</div> | ||
) | ||
} | ||
|
||
export default CommentPlaceholder |
Oops, something went wrong.