|
- import { useEffect, useState } from 'react'
-
- import PostFormTagsArea from '@/components/PostFormTagsArea'
- import PostOriginalCreatedTimeField from '@/components/PostOriginalCreatedTimeField'
- import Label from '@/components/common/Label'
- import { useDialogue } from '@/components/dialogues/DialogueProvider'
- import { Button } from '@/components/ui/button'
- import { toast } from '@/components/ui/use-toast'
- import { isApiError } from '@/lib/api'
- import { updatePost } from '@/lib/posts'
- import { msToTime } from '@/lib/utils'
-
- import type { FC, FormEvent } from 'react'
-
- import type { Post, Tag } from '@/types'
-
-
- const tagsToStr = (tags: Tag[]): string => {
- const result: Tag[] = []
-
- const walk = (tag: Tag) => {
- const { children, ...rest } = tag
- result.push (rest)
- children?.forEach (walk)
- }
-
- tags.filter (t => t.category !== 'nico').forEach (walk)
-
- return [...(new Set (result.map (t => `${ t.name }${ t.sections.map (s => `[${ msToTime (s.beginMs) }-${ msToTime (s.endMs) }]`).join ('') }`)))].join (' ')
- }
-
-
- type Props = { post: Post
- onSave: (newPost: Post) => void }
-
-
- const PostEditForm: FC<Props> = ({ post, onSave }) => {
- const [disabled, setDisabled] = useState (false)
- const [originalCreatedBefore, setOriginalCreatedBefore] =
- useState<string | null> (post.originalCreatedBefore)
- const [originalCreatedFrom, setOriginalCreatedFrom] =
- useState<string | null> (post.originalCreatedFrom)
- const [parentPostIds, setParentPostIds] =
- useState ((post.parentPosts ?? []).map (p => p.id).join (' '))
- const [tags, setTags] = useState<string> ('')
- const [title, setTitle] = useState (post.title)
-
- const dialogue = useDialogue ()
-
- const update = async (...args: Parameters<typeof updatePost>) => {
- try
- {
- const data = await updatePost (...args)
- onSave ({ ...post,
- versionNo: data.versionNo,
- title: data.title,
- tags: data.tags,
- parentPosts: data.parentPosts,
- childPosts: data.childPosts,
- siblingPosts: data.siblingPosts,
- originalCreatedFrom: data.originalCreatedFrom,
- originalCreatedBefore: data.originalCreatedBefore } as Post)
- toast ({ description: '更新しました.' })
- }
- catch (e)
- {
- const response = isApiError<{ mergeable?: boolean }> (e) ? e.response : undefined
-
- if (response?.status !== 409)
- {
- toast ({ description: '更新はできなかったよ……' })
- return
- }
-
- const action = await dialogue.choice ({
- title: '競合が発生しました.',
- description: (
- <div>
- <p>ほかの耕作員が先に更新してゐます.</p>
- <p>現在の変更をどう扱ひますか?</p>
- </div>),
- choices: [...(response?.data?.mergeable ? [{ value: 'merge', label: '差分をマージ' }] : []),
- { value: 'overwrite', label: '強制上書き', variant: 'danger' }] })
-
- if (action === 'merge')
- {
- // TODO: 差分 UI
- await update ({ id: post.id, title, tags, parentPostIds,
- originalCreatedFrom, originalCreatedBefore },
- { baseVersionNo: post.versionNo, merge: true })
- return
- }
-
- if (action === 'overwrite')
- {
- await update ({ id: post.id, title, tags, parentPostIds,
- originalCreatedFrom, originalCreatedBefore },
- { baseVersionNo: post.versionNo, force: true })
- return
- }
- }
- }
-
- const handleSubmit = async (e: FormEvent) => {
- e.preventDefault ()
-
- setDisabled (true)
- try
- {
- await update ({ id: post.id, title, tags, parentPostIds,
- originalCreatedFrom, originalCreatedBefore },
- { baseVersionNo: post.versionNo })
- }
- finally
- {
- setDisabled (false)
- }
- }
-
- useEffect (() => {
- setTags(tagsToStr (post.tags))
- }, [post])
-
- return (
- <form onSubmit={handleSubmit} className="max-w-xl pt-2 space-y-4">
- {/* タイトル */}
- <div>
- <Label>タイトル</Label>
- <input
- type="text"
- disabled={disabled}
- className="w-full border rounded p-2"
- value={title ?? ''}
- onChange={ev => setTitle (ev.target.value)}/>
- </div>
-
- {/* 親投稿 */}
- <div>
- <Label>親投稿</Label>
- <input
- type="text"
- disabled={disabled}
- value={parentPostIds}
- onChange={e => setParentPostIds (e.target.value)}
- className="w-full border p-2 rounded"/>
- </div>
-
- {/* タグ */}
- <PostFormTagsArea
- disabled={disabled}
- tags={tags}
- setTags={setTags}/>
-
- {/* オリジナルの作成日時 */}
- <PostOriginalCreatedTimeField
- disabled={disabled}
- originalCreatedFrom={originalCreatedFrom}
- setOriginalCreatedFrom={setOriginalCreatedFrom}
- originalCreatedBefore={originalCreatedBefore}
- setOriginalCreatedBefore={setOriginalCreatedBefore}/>
-
- {/* 送信 */}
- <Button
- type="submit"
- disabled={disabled}>
- 更新
- </Button>
- </form>)
- }
-
- export default PostEditForm
|