feat: delete confirmation
This commit is contained in:
parent
b9b99be994
commit
b1a880cd34
|
|
@ -1,6 +1,6 @@
|
|||
import { useTranslation } from "next-i18next"
|
||||
import { useRouter } from "next/router"
|
||||
import React from "react"
|
||||
import React, { useState } from "react"
|
||||
import toast from "react-hot-toast"
|
||||
import type { Note, Notes } from "unidata.js"
|
||||
|
||||
|
|
@ -12,6 +12,8 @@ import { APP_NAME } from "~/lib/env"
|
|||
import { delStorage, getStorage, setStorage } from "~/lib/storage"
|
||||
import { useCreateOrUpdatePage, useDeletePage } from "~/queries/page"
|
||||
|
||||
import { DeleteConfirmationModal } from "./DeleteConfirmationModal"
|
||||
|
||||
export const PagesManagerBatchSelectActionTab: React.FC<{
|
||||
isPost: boolean
|
||||
isNotxLogContent: boolean
|
||||
|
|
@ -136,61 +138,77 @@ export const PagesManagerBatchSelectActionTab: React.FC<{
|
|||
{
|
||||
text: "Delete",
|
||||
onClick: async () => {
|
||||
// Start message
|
||||
const toastId = toast.loading("Deleting...")
|
||||
|
||||
// Find all selected
|
||||
const selectedPages: Note[] = []
|
||||
pages.data?.pages.map((page) =>
|
||||
page.list?.map((page) => {
|
||||
if (batchSelected.includes(page.id)) {
|
||||
selectedPages.push(page)
|
||||
}
|
||||
}),
|
||||
)
|
||||
|
||||
// Delete all // TODO: use multicall to optimize
|
||||
try {
|
||||
await Promise.all(
|
||||
selectedPages.map((page) => {
|
||||
if (!page.metadata) {
|
||||
// Is draft
|
||||
delStorage(`draft-${subdomain}-${page.id}`)
|
||||
} else {
|
||||
// Is Note
|
||||
return deletePage.mutateAsync({
|
||||
site: subdomain,
|
||||
id: page.id,
|
||||
})
|
||||
}
|
||||
}),
|
||||
)
|
||||
|
||||
toast.success(t("Deleted!"), {
|
||||
id: toastId,
|
||||
})
|
||||
} catch (e) {
|
||||
toast.error(t("Fail to Deleted."), {
|
||||
// It should be "Failed to delete.", but the translation key is that so :shrug:
|
||||
id: toastId,
|
||||
})
|
||||
}
|
||||
|
||||
// Refresh site data
|
||||
await Promise.all([
|
||||
queryClient.refetchQueries(["getPagesBySite", subdomain]),
|
||||
...selectedPages.map((page) =>
|
||||
queryClient.refetchQueries(["getPage", page.id]),
|
||||
),
|
||||
])
|
||||
|
||||
// Unselect all
|
||||
setBatchSelected([])
|
||||
setDeleteConfirmModalOpen(true)
|
||||
},
|
||||
},
|
||||
]
|
||||
|
||||
return <Tabs items={tabItems} />
|
||||
const [deleteConfirmModalOpen, setDeleteConfirmModalOpen] =
|
||||
useState<boolean>(false)
|
||||
const onDelete = async () => {
|
||||
// Start message
|
||||
const toastId = toast.loading("Deleting...")
|
||||
|
||||
// Find all selected
|
||||
const selectedPages: Note[] = []
|
||||
pages.data?.pages.map((page) =>
|
||||
page.list?.map((page) => {
|
||||
if (batchSelected.includes(page.id)) {
|
||||
selectedPages.push(page)
|
||||
}
|
||||
}),
|
||||
)
|
||||
|
||||
// Delete all // TODO: use multicall to optimize
|
||||
try {
|
||||
await Promise.all(
|
||||
selectedPages.map((page) => {
|
||||
if (!page.metadata) {
|
||||
// Is draft
|
||||
delStorage(`draft-${subdomain}-${page.id}`)
|
||||
} else {
|
||||
// Is Note
|
||||
return deletePage.mutateAsync({
|
||||
site: subdomain,
|
||||
id: page.id,
|
||||
})
|
||||
}
|
||||
}),
|
||||
)
|
||||
|
||||
toast.success(t("Deleted!"), {
|
||||
id: toastId,
|
||||
})
|
||||
} catch (e) {
|
||||
toast.error(t("Fail to Deleted."), {
|
||||
// It should be "Failed to delete.", but the translation key is that so :shrug:
|
||||
id: toastId,
|
||||
})
|
||||
}
|
||||
|
||||
// Refresh site data
|
||||
await Promise.all([
|
||||
queryClient.refetchQueries(["getPagesBySite", subdomain]),
|
||||
...selectedPages.map((page) =>
|
||||
queryClient.refetchQueries(["getPage", page.id]),
|
||||
),
|
||||
])
|
||||
|
||||
// Unselect all
|
||||
setBatchSelected([])
|
||||
}
|
||||
|
||||
return (
|
||||
<>
|
||||
<Tabs items={tabItems} />
|
||||
<DeleteConfirmationModal
|
||||
open={deleteConfirmModalOpen}
|
||||
setOpen={setDeleteConfirmModalOpen}
|
||||
onConfirm={onDelete}
|
||||
isPost={isPost}
|
||||
/>
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
export default PagesManagerBatchSelectActionTab
|
||||
|
|
|
|||
|
|
@ -14,6 +14,8 @@ import { delStorage, getStorage, setStorage } from "~/lib/storage"
|
|||
import { useCreateOrUpdatePage, useDeletePage } from "~/queries/page"
|
||||
import { useGetSite } from "~/queries/site"
|
||||
|
||||
import { DeleteConfirmationModal } from "./DeleteConfirmationModal"
|
||||
|
||||
const usePageEditLink = (page: { id: string }, isPost: boolean) => {
|
||||
const router = useRouter()
|
||||
const subdomain = router.query.subdomain as string
|
||||
|
|
@ -167,24 +169,7 @@ export const PagesManagerMenu: FC<{
|
|||
text: "Delete",
|
||||
icon: <span className="i-mingcute:delete-2-line inline-block"></span>,
|
||||
onClick() {
|
||||
if (!page.metadata) {
|
||||
const toastId = toast.loading("Deleting...")
|
||||
delStorage(`draft-${subdomain}-${page.id}`)
|
||||
Promise.all([
|
||||
queryClient.refetchQueries(["getPagesBySite", subdomain]),
|
||||
queryClient.refetchQueries(["getPage", page.id]),
|
||||
]).then(() => {
|
||||
toast.success("Deleted!", {
|
||||
id: toastId,
|
||||
})
|
||||
})
|
||||
} else {
|
||||
setDeleteToastId(toast.loading("Deleting..."))
|
||||
deletePage.mutate({
|
||||
site: subdomain,
|
||||
id: page.id,
|
||||
})
|
||||
}
|
||||
setDeleteConfirmModalOpen(true)
|
||||
},
|
||||
},
|
||||
]
|
||||
|
|
@ -199,26 +184,57 @@ export const PagesManagerMenu: FC<{
|
|||
}
|
||||
}, [])
|
||||
|
||||
const [deleteConfirmModalOpen, setDeleteConfirmModalOpen] =
|
||||
useState<boolean>(false)
|
||||
const onDelete = () => {
|
||||
if (!page.metadata) {
|
||||
const toastId = toast.loading("Deleting...")
|
||||
delStorage(`draft-${subdomain}-${page.id}`)
|
||||
Promise.all([
|
||||
queryClient.refetchQueries(["getPagesBySite", subdomain]),
|
||||
queryClient.refetchQueries(["getPage", page.id]),
|
||||
]).then(() => {
|
||||
toast.success("Deleted!", {
|
||||
id: toastId,
|
||||
})
|
||||
})
|
||||
} else {
|
||||
setDeleteToastId(toast.loading("Deleting..."))
|
||||
deletePage.mutate({
|
||||
site: subdomain,
|
||||
id: page.id,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
return (
|
||||
<Menu.Items className="text-sm absolute z-20 right-0 bg-white shadow-modal rounded-lg overflow-hidden py-2 w-64 ring-1 ring-border">
|
||||
{items.map((item) => {
|
||||
return (
|
||||
<Menu.Item key={item.text}>
|
||||
<button
|
||||
type="button"
|
||||
className="h-10 flex w-full space-x-2 items-center px-3 hover:bg-gray-100"
|
||||
onClick={(e) => {
|
||||
e.preventDefault()
|
||||
item.onClick()
|
||||
onClose()
|
||||
}}
|
||||
>
|
||||
<span className="inline-flex">{item.icon}</span>
|
||||
<span>{t(item.text)}</span>
|
||||
</button>
|
||||
</Menu.Item>
|
||||
)
|
||||
})}
|
||||
</Menu.Items>
|
||||
<>
|
||||
<Menu.Items className="text-sm absolute z-20 right-0 bg-white shadow-modal rounded-lg overflow-hidden py-2 w-64 ring-1 ring-border">
|
||||
{items.map((item) => {
|
||||
return (
|
||||
<Menu.Item key={item.text}>
|
||||
<button
|
||||
type="button"
|
||||
className="h-10 flex w-full space-x-2 items-center px-3 hover:bg-gray-100"
|
||||
onClick={(e) => {
|
||||
e.preventDefault()
|
||||
item.onClick()
|
||||
onClose()
|
||||
}}
|
||||
>
|
||||
<span className="inline-flex">{item.icon}</span>
|
||||
<span>{t(item.text)}</span>
|
||||
</button>
|
||||
</Menu.Item>
|
||||
)
|
||||
})}
|
||||
</Menu.Items>
|
||||
<DeleteConfirmationModal
|
||||
open={deleteConfirmModalOpen}
|
||||
setOpen={setDeleteConfirmModalOpen}
|
||||
onConfirm={onDelete}
|
||||
isPost={isPost}
|
||||
/>
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@ import { useEffect, useRef, useState } from "react"
|
|||
import useOnClickOutside from "use-onclickoutside"
|
||||
|
||||
import { Button, ButtonGroup } from "../ui/Button"
|
||||
import { DeleteConfirmationModal } from "./DeleteConfirmationModal"
|
||||
|
||||
export const PublishButton: React.FC<{
|
||||
save: (published: boolean) => void
|
||||
|
|
@ -10,7 +11,8 @@ export const PublishButton: React.FC<{
|
|||
isSaving: boolean
|
||||
isDisabled: boolean
|
||||
twitterShareUrl?: string
|
||||
}> = ({ save, published, isSaving, isDisabled, twitterShareUrl }) => {
|
||||
isPost: boolean
|
||||
}> = ({ save, published, isSaving, isDisabled, twitterShareUrl, isPost }) => {
|
||||
const [showDropdown, setShowDropdown] = useState(false)
|
||||
const dropdownRef = useRef<HTMLDivElement | null>(null)
|
||||
const triggerRef = useRef<HTMLButtonElement | null>(null)
|
||||
|
|
@ -27,6 +29,9 @@ export const PublishButton: React.FC<{
|
|||
}
|
||||
}, [isSaving])
|
||||
|
||||
const [deleteConfirmModalOpen, setDeleteConfirmModalOpen] =
|
||||
useState<boolean>(false)
|
||||
|
||||
return (
|
||||
<div className="relative">
|
||||
<ButtonGroup>
|
||||
|
|
@ -69,7 +74,7 @@ export const PublishButton: React.FC<{
|
|||
</button>
|
||||
<button
|
||||
className="flex w-full h-8 hover:bg-zinc-100 items-center px-5"
|
||||
onClick={() => save(false)}
|
||||
onClick={() => setDeleteConfirmModalOpen(true)}
|
||||
>
|
||||
<i className="i-mingcute:delete-2-line mr-1"></i>
|
||||
{t("Delete")}
|
||||
|
|
@ -79,6 +84,14 @@ export const PublishButton: React.FC<{
|
|||
</div>
|
||||
</div>
|
||||
)}
|
||||
<DeleteConfirmationModal
|
||||
open={deleteConfirmModalOpen}
|
||||
setOpen={setDeleteConfirmModalOpen}
|
||||
onConfirm={() => {
|
||||
save(false)
|
||||
}}
|
||||
isPost={isPost}
|
||||
/>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -563,6 +563,7 @@ export default function SubdomainEditor() {
|
|||
visibility !== PageVisibilityEnum.Modified &&
|
||||
visibility !== PageVisibilityEnum.Draft
|
||||
}
|
||||
isPost={isPost}
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
|
|
|
|||
Loading…
Reference in New Issue