diff --git a/frontend/src/components/PostEditForm.tsx b/frontend/src/components/PostEditForm.tsx index 3ac2077..24d2dcc 100644 --- a/frontend/src/components/PostEditForm.tsx +++ b/frontend/src/components/PostEditForm.tsx @@ -5,7 +5,7 @@ import PostOriginalCreatedTimeField from '@/components/PostOriginalCreatedTimeFi import Label from '@/components/common/Label' import { Button } from '@/components/ui/button' import { toast } from '@/components/ui/use-toast' -import { apiPut } from '@/lib/api' +import { updatePost } from '@/lib/posts' import type { FC } from 'react' @@ -44,19 +44,17 @@ export default (({ post, onSave }: Props) => { const handleSubmit = async () => { try { - const data = await apiPut ( - `/posts/${ post.id }`, - { title, tags, parent_post_ids: parentPostIds, - original_created_from: originalCreatedFrom, - original_created_before: originalCreatedBefore }, - { headers: { 'Content-Type': 'multipart/form-data' } }) + const data = + await updatePost ({ id: post.id, versionNo: post.versionNo + 1, + title, tags, parentPostIds, + originalCreatedFrom, originalCreatedBefore }) onSave ({ ...post, title: data.title, tags: data.tags, parentPosts: data.parentPosts, childPosts: data.childPosts, siblingPosts: data.siblingPosts, - originalCreatedFrom: data.originalCreatedFrom, + originalCreatedFrom: data.originalCreatedFrom, originalCreatedBefore: data.originalCreatedBefore } as Post) toast ({ description: '更新しました.' }) } diff --git a/frontend/src/lib/posts.ts b/frontend/src/lib/posts.ts index 57907dc..4197148 100644 --- a/frontend/src/lib/posts.ts +++ b/frontend/src/lib/posts.ts @@ -1,4 +1,4 @@ -import { apiDelete, apiGet, apiPost } from '@/lib/api' +import { apiDelete, apiGet, apiPost, apiPut } from '@/lib/api' import type { FetchPostsParams, Post, PostVersion } from '@/types' @@ -42,6 +42,25 @@ export const fetchPostChanges = async ( page, limit } }) +export const updatePost = async ( + post: { id: number + versionNo: number + title: string | null + tags: string + parentPostIds: string + originalCreatedFrom: string | null + originalCreatedBefore: string | null }, +) => + await apiPut ( + `/posts/${ post.id }`, + { version_no: post.versionNo, + title: post.title, + tags: post.tags, + parent_post_ids: post.parentPostIds, + original_created_from: post.originalCreatedFrom, + original_created_before: post.originalCreatedBefore }) + + export const toggleViewedFlg = async (id: string, viewed: boolean): Promise => { await (viewed ? apiPost : apiDelete) (`/posts/${ id }/viewed`) } diff --git a/frontend/src/pages/posts/PostHistoryPage.tsx b/frontend/src/pages/posts/PostHistoryPage.tsx index 2977527..0545b93 100644 --- a/frontend/src/pages/posts/PostHistoryPage.tsx +++ b/frontend/src/pages/posts/PostHistoryPage.tsx @@ -11,13 +11,14 @@ import Pagination from '@/components/common/Pagination' import MainArea from '@/components/layout/MainArea' import { toast } from '@/components/ui/use-toast' import { SITE_TITLE } from '@/config' -import { apiPut } from '@/lib/api' -import { fetchPostChanges } from '@/lib/posts' +import { fetchPostChanges, updatePost } from '@/lib/posts' import { postsKeys, tagsKeys } from '@/lib/queryKeys' import { fetchTag } from '@/lib/tags' import { cn, dateString, originalCreatedAtString } from '@/lib/utils' -import type { FC } from 'react' +import type { FC, MouseEvent } from 'react' + +import type { PostVersion } from '@/types' const renderDiff = (diff: { current: string | null; prev: string | null }) => ( @@ -62,6 +63,45 @@ export default (() => { const qc = useQueryClient () + const handleRevert = async (e: MouseEvent, change: PostVersion) => { + e.preventDefault () + + if (!(confirm (`『${ change.title.current || change.url.current }』を版 ${ + change.versionNo } に差戻します.\nよろしいですか?`))) + return + + try + { + const id = change.postId + const versionNo = change.latestVersionNo + 1 + const title = change.title.current + const tags = + change.tags + .filter (t => t.type !== 'removed') + .map (t => t.name) + .filter (t => t.slice (0, 5) !== 'nico:') + .join (' ') + const parentPostIds = + (change.parentPosts ?? []) + .filter (p => p.type !== 'removed') + .map (p => p.id) + .join (' ') + const originalCreatedFrom = change.originalCreatedFrom.current + const originalCreatedBefore = change.originalCreatedBefore.current + await updatePost ({ id, versionNo, title, tags, parentPostIds, + originalCreatedFrom, originalCreatedBefore }) + + qc.invalidateQueries ({ queryKey: postsKeys.root }) + qc.invalidateQueries ({ queryKey: tagsKeys.root }) + + toast ({ description: '差戻しました.' }) + } + catch + { + toast ({ description: '差戻に失敗……' }) + } + } + useEffect (() => { document.querySelector ('table')?.scrollIntoView ({ behavior: 'smooth' }) }, [location.search]) @@ -231,46 +271,7 @@ export default (() => { {dateString (change.createdAt)} - { - e.preventDefault () - - if (!(confirm ( - `『${ change.title.current - || change.url.current }』を版 ${ - change.versionNo } に差戻します.\nよろしいですか?`))) - return - - try - { - await apiPut ( - `/posts/${ change.postId }`, - { title: change.title.current, - tags: change.tags - .filter (t => t.type !== 'removed') - .map (t => t.name) - .filter (t => t.slice (0, 5) !== 'nico:') - .join (' '), - parent_post_ids: - (change.parentPosts ?? []) - .filter (p => p.type !== 'removed') - .map (p => p.id) - .join (' '), - original_created_from: - change.originalCreatedFrom.current, - original_created_before: - change.originalCreatedBefore.current }) - - qc.invalidateQueries ({ queryKey: postsKeys.root }) - qc.invalidateQueries ({ queryKey: tagsKeys.root }) - toast ({ description: '差戻しました.' }) - } - catch - { - toast ({ description: '差戻に失敗……' }) - } - }}> + await handleRevert (e, change)}> 復元 diff --git a/frontend/src/types.ts b/frontend/src/types.ts index 5fb8078..e552f69 100644 --- a/frontend/src/types.ts +++ b/frontend/src/types.ts @@ -121,6 +121,7 @@ export type Platform = typeof PLATFORMS[number] export type Post = { id: number + versionNo: number url: string title: string | null thumbnail: string | null @@ -146,6 +147,7 @@ export type PostTagChange = { export type PostVersion = { postId: number + latestVersionNo: number versionNo: number eventType: 'create' | 'update' | 'discard' | 'restore' title: { current: string | null; prev: string | null }