This commit is contained in:
@@ -44,7 +44,7 @@ class PostsController < ApplicationController
|
||||
filtered_posts
|
||||
.joins("LEFT JOIN (#{ pt_max_sql }) pt_max ON pt_max.post_id = posts.id")
|
||||
.reselect('posts.*', Arel.sql("#{ updated_at_all_sql } AS updated_at_all"))
|
||||
.preload(tags: [:materials, { tag_name: :wiki_page }])
|
||||
.preload(tags: [:deerjikists, :materials, { tag_name: :wiki_page }])
|
||||
.with_attached_thumbnail
|
||||
|
||||
q = q.where('posts.url LIKE ?', "%#{ url }%") if url
|
||||
@@ -95,7 +95,7 @@ class PostsController < ApplicationController
|
||||
end
|
||||
|
||||
def random
|
||||
post = filtered_posts.preload(tags: [:materials, { tag_name: :wiki_page }])
|
||||
post = filtered_posts.preload(tags: [:deerjikists, :materials, { tag_name: :wiki_page }])
|
||||
.order('RAND()')
|
||||
.first
|
||||
return head :not_found unless post
|
||||
@@ -104,7 +104,7 @@ class PostsController < ApplicationController
|
||||
end
|
||||
|
||||
def show
|
||||
post = Post.includes(tags: [:materials, { tag_name: :wiki_page }]).find_by(id: params[:id])
|
||||
post = Post.includes(tags: [:deerjikists, :materials, { tag_name: :wiki_page }]).find_by(id: params[:id])
|
||||
return head :not_found unless post
|
||||
|
||||
render json: PostRepr.base(post, current_user)
|
||||
@@ -173,8 +173,12 @@ class PostsController < ApplicationController
|
||||
return head :unauthorized unless current_user
|
||||
return head :forbidden unless current_user.gte_member?
|
||||
|
||||
base_version_no = parse_base_version_no
|
||||
force = truthy_param?(params[:force])
|
||||
merge = truthy_param?(params[:merge])
|
||||
return head :bad_request if force && merge
|
||||
|
||||
base_version_no = nil
|
||||
base_version_no = parse_base_version_no unless force
|
||||
|
||||
title = params[:title].presence
|
||||
tag_names = params[:tags].to_s.split
|
||||
@@ -186,12 +190,17 @@ class PostsController < ApplicationController
|
||||
conflict_json = nil
|
||||
|
||||
ApplicationRecord.transaction do
|
||||
post = Post.find(params[:id].to_i)
|
||||
post = Post.lock.find(params[:id].to_i)
|
||||
|
||||
base_version = post.post_versions.find_by!(version_no: base_version_no)
|
||||
base_version = nil
|
||||
base_snapshot = nil
|
||||
current_snapshot = nil
|
||||
unless force
|
||||
base_version = post.post_versions.find_by!(version_no: base_version_no)
|
||||
|
||||
base_snapshot = post_snapshot_from_version(base_version)
|
||||
current_snapshot = post_snapshot_from_record(post)
|
||||
base_snapshot = post_snapshot_from_version(base_version)
|
||||
current_snapshot = post_snapshot_from_record(post)
|
||||
end
|
||||
incoming_snapshot = post_incoming_snapshot(post,
|
||||
title:,
|
||||
original_created_from:,
|
||||
@@ -199,29 +208,28 @@ class PostsController < ApplicationController
|
||||
tag_names:,
|
||||
parent_post_ids:)
|
||||
|
||||
if !(force) && post.version_no != base_version_no
|
||||
conflict_json = post_conflict_json(post:,
|
||||
base_version_no:,
|
||||
base_snapshot:,
|
||||
current_snapshot:,
|
||||
incoming_snapshot:)
|
||||
raise ActiveRecord::Rollback
|
||||
end
|
||||
snapshot_to_apply =
|
||||
if post.version_no == base_version_no || force
|
||||
incoming_snapshot
|
||||
else
|
||||
changes = post_snapshot_changes(base_snapshot, current_snapshot, incoming_snapshot)
|
||||
conflicts = changes.select { |change| change[:conflict] }
|
||||
|
||||
PostVersionRecorder.ensure_snapshot!(post, created_by_user: current_user)
|
||||
if merge && conflicts.empty?
|
||||
merge_post_snapshots(base_snapshot, current_snapshot, incoming_snapshot)
|
||||
else
|
||||
conflict_json = post_conflict_json(post:,
|
||||
base_version_no:,
|
||||
base_snapshot:,
|
||||
current_snapshot:,
|
||||
incoming_snapshot:,
|
||||
changes:,
|
||||
conflicts:)
|
||||
raise ActiveRecord::Rollback
|
||||
end
|
||||
end
|
||||
|
||||
post.update!(title:, original_created_from:, original_created_before:)
|
||||
|
||||
normalised_tags = Tag.normalise_tags!(tag_names, with_tagme: false)
|
||||
TagVersioning.record_tag_snapshots!(normalised_tags, created_by_user: current_user)
|
||||
|
||||
tags = post.tags.nico.to_a + normalised_tags
|
||||
tags = Tag.expand_parent_tags(tags)
|
||||
sync_post_tags!(post, tags)
|
||||
|
||||
sync_parent_posts!(post, parent_post_ids)
|
||||
|
||||
PostVersionRecorder.record!(post:, event_type: :update, created_by_user: current_user)
|
||||
apply_post_snapshot!(post, snapshot_to_apply)
|
||||
end
|
||||
|
||||
return render json: conflict_json, status: :conflict if conflict_json
|
||||
@@ -253,7 +261,7 @@ class PostsController < ApplicationController
|
||||
pts = pts.where(post_id: id) if id.present?
|
||||
pts = pts.where(tag_id:) if tag_id.present?
|
||||
pts = pts.includes(:post, :created_user, :deleted_user,
|
||||
tag: [:materials, { tag_name: :wiki_page }])
|
||||
tag: [:deerjikists, :materials, { tag_name: :wiki_page }])
|
||||
|
||||
events = []
|
||||
pts.each do |pt|
|
||||
@@ -446,11 +454,11 @@ class PostsController < ApplicationController
|
||||
{ title: version.title,
|
||||
original_created_from: snapshot_time(version.original_created_from),
|
||||
original_created_before: snapshot_time(version.original_created_before),
|
||||
tag_names: version.tags.to_s.split.sort,
|
||||
tag_names: version.tags.to_s.split.filter { !(_1.start_with?('nico:')) }.sort,
|
||||
parent_post_ids: snapshot_parent_post_ids_from_version(version) }
|
||||
end
|
||||
|
||||
def post_snapshot_form_record post
|
||||
def post_snapshot_from_record post
|
||||
{ title: post.title,
|
||||
original_created_from: snapshot_time(post.original_created_from),
|
||||
original_created_before: snapshot_time(post.original_created_before),
|
||||
@@ -460,7 +468,7 @@ class PostsController < ApplicationController
|
||||
|
||||
def post_incoming_snapshot post, title:, original_created_from:, original_created_before:,
|
||||
tag_names:, parent_post_ids:
|
||||
{ title:
|
||||
{ title:,
|
||||
original_created_from: snapshot_time(original_created_from),
|
||||
original_created_before: snapshot_time(original_created_before),
|
||||
tag_names: incoming_tag_names_for_snapshot(post, tag_names),
|
||||
@@ -488,17 +496,16 @@ class PostsController < ApplicationController
|
||||
|
||||
def incoming_tag_names_for_snapshot post, raw_tag_names
|
||||
manual_names = normalised_manual_tag_names_for_snapshot(raw_tag_names)
|
||||
nico_names = post.tags.nico.joins(:tag_name).pluck('tag_names.name')
|
||||
|
||||
existing_tags =
|
||||
Tag
|
||||
.joins(:tag_name)
|
||||
.where(tag_names: { name: manual_names + nico_names })
|
||||
.where(tag_names: { name: manual_names })
|
||||
.to_a
|
||||
|
||||
expanded_names = Tag.expand_parent_tags(existing_tags).map(&:name)
|
||||
|
||||
(manual_names + nico_names + expanded_names).uniq.sort
|
||||
(manual_names + expanded_names).uniq.sort
|
||||
end
|
||||
|
||||
def normalised_manual_tag_names_for_snapshot raw_tag_names
|
||||
@@ -528,10 +535,7 @@ class PostsController < ApplicationController
|
||||
end
|
||||
|
||||
def post_conflict_json post:, base_version_no:, base_snapshot:,
|
||||
current_snapshot:, incoming_snapshot:
|
||||
changes = post_snapshot_changes(base_snapshot, current_snapshot, incoming_snapshot)
|
||||
conflicts = changes.select { |change| change[:conflict] }
|
||||
|
||||
current_snapshot:, incoming_snapshot:, changes:, conflicts:
|
||||
{ error: 'conflict',
|
||||
message: '競合が発生しました.',
|
||||
post_id: post.id,
|
||||
@@ -548,9 +552,9 @@ class PostsController < ApplicationController
|
||||
def post_snapshot_changes base_snapshot, current_snapshot, incoming_snapshot
|
||||
[scalar_snapshot_change(:title, 'タイトル',
|
||||
base_snapshot, current_snapshot, incoming_snapshot),
|
||||
scalar_snapshot_change(:original_created_from, '元コンテンツ作成日時(開始)',
|
||||
scalar_snapshot_change(:original_created_from, 'オリジナルの作成日時(以降)',
|
||||
base_snapshot, current_snapshot, incoming_snapshot),
|
||||
scalar_snapshot_change(:original_created_before, '元コンテンツ作成日時(終了)',
|
||||
scalar_snapshot_change(:original_created_before, 'オリジナルの作成日時(より前)',
|
||||
base_snapshot, current_snapshot, incoming_snapshot),
|
||||
set_snapshot_change(:tag_names, 'タグ',
|
||||
base_snapshot, current_snapshot, incoming_snapshot),
|
||||
@@ -606,4 +610,37 @@ class PostsController < ApplicationController
|
||||
added_by_me:, removed_by_me:
|
||||
(added_by_current & removed_by_me).present? || (removed_by_current & added_by_me).present?
|
||||
end
|
||||
|
||||
def apply_post_snapshot! post, snapshot
|
||||
PostVersionRecorder.ensure_snapshot!(post, created_by_user: current_user)
|
||||
|
||||
post.update!(title: snapshot[:title],
|
||||
original_created_from: snapshot[:original_created_from],
|
||||
original_created_before: snapshot[:original_created_before])
|
||||
|
||||
tags = Tag.normalise_tags!(snapshot[:tag_names], with_tagme: false)
|
||||
TagVersioning.record_tag_snapshots!(tags, created_by_user: current_user)
|
||||
|
||||
tags = Tag.expand_parent_tags(tags)
|
||||
sync_post_tags!(post, tags)
|
||||
|
||||
sync_parent_posts!(post, snapshot[:parent_post_ids])
|
||||
|
||||
PostVersionRecorder.record!(post:, event_type: :update, created_by_user: current_user)
|
||||
end
|
||||
|
||||
def merge_post_snapshots base_snapshot, current_snapshot, incoming_snapshot
|
||||
[:title, :original_created_from, :original_created_before, :tag_names, :parent_post_ids].map {
|
||||
[_1, merge_scaler_snapshot_value(base_snapshot[_1],
|
||||
current_snapshot[_1],
|
||||
incoming_snapshot[_1])]
|
||||
}.to_h
|
||||
end
|
||||
|
||||
def merge_scaler_snapshot_value base, current, mine
|
||||
return mine if current == base
|
||||
return current if mine == base || current == mine
|
||||
|
||||
raise ArgumentError, '競合してゐる項目はマージできません.'
|
||||
end
|
||||
end
|
||||
|
||||
@@ -136,6 +136,7 @@ class Tag < ApplicationRecord
|
||||
tn = tn.canonical if tn.canonical_id?
|
||||
|
||||
Tag.find_undiscard_or_create_by!(tag_name_id: tn.id) do |t|
|
||||
t.version_no = TagVersion.where(tag_id: t.id).order(version_no: :desc).first || 1
|
||||
t.category = category
|
||||
end
|
||||
rescue ActiveRecord::RecordNotUnique
|
||||
|
||||
+15
-10
@@ -8,6 +8,7 @@ import { BrowserRouter,
|
||||
|
||||
import RouteBlockerOverlay from '@/components/RouteBlockerOverlay'
|
||||
import TopNav from '@/components/TopNav'
|
||||
import DialogueProvider from '@/components/dialogues/DialogueProvider'
|
||||
import { Toaster } from '@/components/ui/toaster'
|
||||
import { apiPost, isApiError } from '@/lib/api'
|
||||
import DeerjikistDetailPage from '@/pages/deerjikists/DeerjikistDetailPage'
|
||||
@@ -138,17 +139,21 @@ export default (() => {
|
||||
return (
|
||||
<>
|
||||
<RouteBlockerOverlay/>
|
||||
|
||||
<BrowserRouter>
|
||||
<LayoutGroup>
|
||||
<motion.div
|
||||
layout="position"
|
||||
transition={{ layout: { duration: .2, ease: 'easeOut' } }}
|
||||
className="flex flex-col h-dvh w-full overflow-y-hidden">
|
||||
<TopNav user={user}/>
|
||||
<RouteTransitionWrapper user={user} setUser={setUser}/>
|
||||
</motion.div>
|
||||
</LayoutGroup>
|
||||
<Toaster/>
|
||||
<DialogueProvider>
|
||||
<LayoutGroup>
|
||||
<motion.div
|
||||
layout="position"
|
||||
transition={{ layout: { duration: .2, ease: 'easeOut' } }}
|
||||
className="flex flex-col h-dvh w-full overflow-y-hidden">
|
||||
<TopNav user={user}/>
|
||||
<RouteTransitionWrapper user={user} setUser={setUser}/>
|
||||
</motion.div>
|
||||
</LayoutGroup>
|
||||
|
||||
<Toaster/>
|
||||
</DialogueProvider>
|
||||
</BrowserRouter>
|
||||
</>)
|
||||
}) satisfies FC
|
||||
|
||||
@@ -3,6 +3,7 @@ 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 { updatePost } from '@/lib/posts'
|
||||
@@ -41,29 +42,68 @@ export default (({ post, onSave }: Props) => {
|
||||
const [tags, setTags] = useState<string> ('')
|
||||
const [title, setTitle] = useState (post.title)
|
||||
|
||||
const handleSubmit = async () => {
|
||||
const dialogue = useDialogue ()
|
||||
|
||||
const update = async (...args: Parameters<typeof updatePost>) => {
|
||||
try
|
||||
{
|
||||
const data =
|
||||
await updatePost ({ id: post.id, versionNo: post.versionNo + 1,
|
||||
title, tags, parentPostIds,
|
||||
originalCreatedFrom, originalCreatedBefore })
|
||||
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,
|
||||
originalCreatedFrom: data.originalCreatedFrom,
|
||||
originalCreatedBefore: data.originalCreatedBefore } as Post)
|
||||
toast ({ description: '更新しました.' })
|
||||
}
|
||||
catch
|
||||
catch (e)
|
||||
{
|
||||
toast ({ description: '更新はできなかったよ……' })
|
||||
if (e.response.status !== 409)
|
||||
{
|
||||
toast ({ description: '更新はできなかったよ……' })
|
||||
return
|
||||
}
|
||||
|
||||
const action = await dialogue.choice ({
|
||||
title: '競合が発生しました.',
|
||||
description: (
|
||||
<div>
|
||||
<p>ほかの耕作員が先に更新してゐます.</p>
|
||||
<p>現在の変更をどう扱ひますか?</p>
|
||||
</div>),
|
||||
choices: [{ 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 => {
|
||||
e.preventDefault ()
|
||||
|
||||
await update ({ id: post.id, title, tags, parentPostIds,
|
||||
originalCreatedFrom, originalCreatedBefore },
|
||||
{ baseVersionNo: post.versionNo })
|
||||
}
|
||||
|
||||
useEffect (() => {
|
||||
setTags(tagsToStr (post.tags))
|
||||
}, [post])
|
||||
|
||||
@@ -0,0 +1,184 @@
|
||||
import { createContext, useCallback, useContext, useMemo, useState } from 'react'
|
||||
|
||||
import { Button } from '@/components/ui/button'
|
||||
import { Dialog,
|
||||
DialogContent,
|
||||
DialogDescription,
|
||||
DialogFooter,
|
||||
DialogTitle } from '@/components/ui/dialog'
|
||||
|
||||
import type { FC, ReactNode } from 'react'
|
||||
|
||||
type DialogueVariant = 'default' | 'danger'
|
||||
|
||||
type ConfirmOptions = { title: string
|
||||
description?: ReactNode
|
||||
confirmText?: string
|
||||
cancelText?: string
|
||||
variant?: DialogueVariant }
|
||||
|
||||
type AlertOptions = { title: string
|
||||
description?: ReactNode
|
||||
okText?: string }
|
||||
|
||||
type Choice<T extends string> = { value: T
|
||||
label: string
|
||||
variant?: DialogueVariant }
|
||||
|
||||
type ChoiceOptions<T extends string> = { title: string
|
||||
description?: ReactNode
|
||||
choices: Choice<T>[]
|
||||
cancelText?: string }
|
||||
|
||||
type DialogueRequest =
|
||||
| { id: number
|
||||
kind: 'confirm'
|
||||
options: ConfirmOptions
|
||||
resolve: (value: boolean) => void }
|
||||
| { id: number
|
||||
kind: 'alert'
|
||||
options: AlertOptions
|
||||
resolve: () => void }
|
||||
| { id: number
|
||||
kind: 'choice'
|
||||
options: ChoiceOptions<string>
|
||||
resolve: (value: string | null) => void }
|
||||
|
||||
type DialogueAPI =
|
||||
{ confirm: (options: ConfirmOptions) => Promise<boolean>
|
||||
alert: (options: AlertOptions) => Promise<void>
|
||||
choice: <T extends string> (options: ChoiceOptions<T>) => Promise<T | null> }
|
||||
|
||||
const DialogueContext = createContext<DialogueAPI | null> (null)
|
||||
|
||||
let nextDialogueId = 1
|
||||
|
||||
type Props = { children: ReactNode }
|
||||
|
||||
|
||||
export default (({ children }: Props) => {
|
||||
const [queue, setQueue] = useState<DialogueRequest[]> ([])
|
||||
|
||||
const push = useCallback ((request: Omit<DialogueRequest, 'id'>) => {
|
||||
const id = nextDialogueId
|
||||
++nextDialogueId
|
||||
|
||||
setQueue (q => [...q, { ...request, id } as DialogueRequest])
|
||||
}, [])
|
||||
|
||||
const closeActive = useCallback ((result?: unknown) => {
|
||||
setQueue (q => {
|
||||
const [active, ...rest] = q
|
||||
|
||||
if (!(active))
|
||||
return rest
|
||||
|
||||
switch (active.kind)
|
||||
{
|
||||
case 'confirm':
|
||||
active.resolve (Boolean (result))
|
||||
break
|
||||
|
||||
case 'alert':
|
||||
active.resolve ()
|
||||
break
|
||||
|
||||
case 'choice':
|
||||
active.resolve ((result ?? null) as string | null)
|
||||
break
|
||||
}
|
||||
|
||||
return rest
|
||||
})
|
||||
}, [])
|
||||
|
||||
const api = useMemo<DialogueAPI> (() => ({
|
||||
confirm: options => new Promise<boolean> (resolve => {
|
||||
push ({ kind: 'confirm', options, resolve })
|
||||
}),
|
||||
alert: options => new Promise<void> (resolve => {
|
||||
push ({ kind: 'alert', options, resolve })
|
||||
}),
|
||||
choice: options => new Promise (resolve => {
|
||||
push ({ kind: 'choice',
|
||||
options: options as ChoiceOptions<string>,
|
||||
resolve: resolve as (value: string | null) => void })
|
||||
}) }), [push])
|
||||
|
||||
const active = queue[0]
|
||||
|
||||
return (
|
||||
<DialogueContext.Provider value={api}>
|
||||
{children}
|
||||
|
||||
<Dialog
|
||||
open={Boolean (active)}
|
||||
onOpenChange={open => {
|
||||
if (!(open))
|
||||
closeActive (active?.kind !== 'confirm' && null)
|
||||
}}>
|
||||
{active && (
|
||||
<DialogContent>
|
||||
<DialogTitle>{active.options.title}</DialogTitle>
|
||||
|
||||
{active.options.description && (
|
||||
<DialogDescription asChild>
|
||||
<div>{active.options.description}</div>
|
||||
</DialogDescription>)}
|
||||
|
||||
<DialogFooter>
|
||||
{active.kind === 'confirm' && (
|
||||
<>
|
||||
<Button
|
||||
variant="outline"
|
||||
onClick={() => closeActive (false)}>
|
||||
{active.options.cancelText ?? '取消'}
|
||||
</Button>
|
||||
|
||||
<Button
|
||||
variant={(active.options.variant === 'danger')
|
||||
? 'destructive'
|
||||
: 'default'}
|
||||
onClick={() => closeActive (true)}>
|
||||
{active.options.confirmText ?? '確定'}
|
||||
</Button>
|
||||
</>)}
|
||||
|
||||
{active.kind === 'alert' && (
|
||||
<Button onClick={() => closeActive ()}>
|
||||
{active.options.okText ?? '確定'}
|
||||
</Button>)}
|
||||
|
||||
{active.kind === 'choice' && (
|
||||
<>
|
||||
<Button
|
||||
variant="outline"
|
||||
onClick={() => closeActive (null)}>
|
||||
{active.options.cancelText ?? '取消'}
|
||||
</Button>
|
||||
|
||||
{active.options.choices.map (choice => (
|
||||
<Button
|
||||
key={choice.value}
|
||||
variant={(choice.variant === 'danger')
|
||||
? 'destructive'
|
||||
: 'default'}
|
||||
onClick={() => closeActive (choice.value)}>
|
||||
{choice.label}
|
||||
</Button>))}
|
||||
</>)}
|
||||
</DialogFooter>
|
||||
</DialogContent>)}
|
||||
</Dialog>
|
||||
</DialogueContext.Provider>)
|
||||
}) satisfies FC<Props>
|
||||
|
||||
|
||||
export const useDialogue = () => {
|
||||
const dialogue = useContext (DialogueContext)
|
||||
|
||||
if (!(dialogue))
|
||||
throw new Error ('useDialogue must be used inside DialogueProvider')
|
||||
|
||||
return dialogue
|
||||
}
|
||||
@@ -44,21 +44,26 @@ export const fetchPostChanges = async (
|
||||
|
||||
export const updatePost = async (
|
||||
post: { id: number
|
||||
versionNo: number
|
||||
title: string | null
|
||||
tags: string
|
||||
parentPostIds: string
|
||||
originalCreatedFrom: string | null
|
||||
originalCreatedBefore: string | null },
|
||||
{ baseVersionNo, force, merge }: {
|
||||
baseVersionNo?: number
|
||||
force?: boolean
|
||||
merge?: boolean }
|
||||
) =>
|
||||
await apiPut<Post> (
|
||||
`/posts/${ post.id }`,
|
||||
{ version_no: post.versionNo,
|
||||
title: post.title,
|
||||
{ title: post.title,
|
||||
tags: post.tags,
|
||||
parent_post_ids: post.parentPostIds,
|
||||
original_created_from: post.originalCreatedFrom,
|
||||
original_created_before: post.originalCreatedBefore })
|
||||
original_created_before: post.originalCreatedBefore },
|
||||
{ params: { ...(baseVersionNo && { base_version_no: String (baseVersionNo) }),
|
||||
force: force ? '1' : '0',
|
||||
merge: merge ? '1' : '0' } })
|
||||
|
||||
|
||||
export const toggleViewedFlg = async (id: string, viewed: boolean): Promise<void> => {
|
||||
|
||||
@@ -73,7 +73,6 @@ export default (() => {
|
||||
try
|
||||
{
|
||||
const id = change.postId
|
||||
const versionNo = change.latestVersionNo + 1
|
||||
const title = change.title.current
|
||||
const tags =
|
||||
change.tags
|
||||
@@ -88,8 +87,9 @@ export default (() => {
|
||||
.join (' ')
|
||||
const originalCreatedFrom = change.originalCreatedFrom.current
|
||||
const originalCreatedBefore = change.originalCreatedBefore.current
|
||||
await updatePost ({ id, versionNo, title, tags, parentPostIds,
|
||||
originalCreatedFrom, originalCreatedBefore })
|
||||
await updatePost ({ id, title, tags, parentPostIds,
|
||||
originalCreatedFrom, originalCreatedBefore },
|
||||
{ force: true })
|
||||
|
||||
qc.invalidateQueries ({ queryKey: postsKeys.root })
|
||||
qc.invalidateQueries ({ queryKey: tagsKeys.root })
|
||||
|
||||
Reference in New Issue
Block a user