Merge branch 'pr/Innei/290' into dev
This commit is contained in:
commit
445cd11b3f
|
|
@ -13,6 +13,7 @@
|
|||
"Site Duration": "サイトの運営期間",
|
||||
"days": "日",
|
||||
"Deleted!": "削除されました!",
|
||||
"Fail to Deleted." : "削除できませんでした。",
|
||||
"Converted!": "変換されました!",
|
||||
"Failed to convert.": "変換に失敗しました。",
|
||||
"All Posts": "すべての記事",
|
||||
|
|
@ -24,7 +25,7 @@
|
|||
"Scheduled": "予約済み",
|
||||
"scheduled": "予約済み",
|
||||
"published and local modified": "公開済みで、ローカルでの編集あり",
|
||||
"Others on Crossbell": "Crossbellに関するその他の情報",
|
||||
"Others on Crossbell": "Crossbell に関するその他の情報",
|
||||
"link post-vs-page": "https://wordpress.com/ja/support/post-vs-page/",
|
||||
"posts description": "記事は、時間順に表示されます。読者に新しいコンテンツを提供し続けることで、ブログのフォローワが増えるでしょう。<2>記事</2>",
|
||||
"pages description": "ページは日付に影響を受けることがありません。「私たちについて」「お問い合わせ」などのようにページを活用しましょう。<2>ページ</2>",
|
||||
|
|
@ -54,7 +55,7 @@
|
|||
"Link": "リンク",
|
||||
"Image": "画像",
|
||||
"Upload Image": "画像をアップロード",
|
||||
"Tip: xLog Flavored Markdown": "ヒント:xLog風のマークダウン",
|
||||
"Tip: xLog Flavored Markdown": "ヒント:xLog 風のマークダウン",
|
||||
"Preview": "プレビュー",
|
||||
"Publish": "公開",
|
||||
"Update": "更新",
|
||||
|
|
@ -73,7 +74,7 @@
|
|||
"Social Platforms": "ソーシャルプラットフォーム",
|
||||
"Navigation": "ナビゲーション",
|
||||
"Domains": "ドメイン",
|
||||
"Custom CSS": "カスタムCSS",
|
||||
"Custom CSS": "カスタム CSS",
|
||||
"Operators": "オペレーター",
|
||||
"Export data": "データのエクスポート",
|
||||
"Site Settings": "サイト設定",
|
||||
|
|
@ -82,37 +83,37 @@
|
|||
"Supports both pictures and videos.": "画像と動画の両方に対応しています。",
|
||||
"Name": "名前",
|
||||
"Description": "説明",
|
||||
"Integrate Google Analytics": "Google Analyticsと紐付けします。Measurement IDの検索方法については、<2>こちらの文章</2>をご覧ください。",
|
||||
"Integrate Google Analytics": "Google Analytics と紐付けします。Measurement ID の検索方法については、<2>こちらの文章</2>をご覧ください。",
|
||||
"Save": "保存",
|
||||
"Tips": "ヒント",
|
||||
"social tips": {
|
||||
"p1": "紐付けしたプラットフォームの標識は、画面の右下隅に表示されます。",
|
||||
"p2": "xLogは<2>こちらのプラットフォーム</2>と紐付け可能です。(紐付けに成功すると自動的にそのロゴとリンクが表示されます。)その他のプラットフォームの場合、デフォルトのロゴが表示されます。もしサポートして欲しいプラットフォームがありましたら、是非IssueあるいはPRを作成して、xLogをより完成度の高いプラットフォームにさせましょう。",
|
||||
"p3": "<2>xSync</2>を使用して、Twitter、Telegram、Medium、Substackなどのプラットフォームに紐付けし、コンテンツを自動的に同期することもできます。同期設定を行った場合、ここにも表示されます。"
|
||||
"p2": "xLog は<2>こちらのプラットフォーム</2>と紐付け可能です。(紐付けに成功すると自動的にそのロゴとリンクが表示されます。)その他のプラットフォームの場合、デフォルトのロゴが表示されます。もしサポートして欲しいプラットフォームがありましたら、是非 Issue あるいは PR を作成して、xLog をより完成度の高いプラットフォームにさせましょう。",
|
||||
"p3": "<2>xSync</2>を使用して、Twitter、Telegram、Medium、Substack などのプラットフォームに紐付けし、コンテンツを自動的に同期することもできます。同期設定を行った場合、ここにも表示されます。"
|
||||
},
|
||||
"Platform": "プラットフォーム",
|
||||
"Identity": "アイデンティティ",
|
||||
"Remove": "削除",
|
||||
"New Item": "新しいアイテム",
|
||||
"xLog provides some out-of-the-box built-in pages": "xLogにはいくつすぐ使えるページテンプレートがあります。",
|
||||
"xLog provides some out-of-the-box built-in pages": "xLog にはいくつすぐ使えるページテンプレートがあります。",
|
||||
"Home page": "ホームページ",
|
||||
"Archives page": "アーカイブページ",
|
||||
"Tag page": "タグページ",
|
||||
"NFT Showcase page": "NFTショーケースページ",
|
||||
"NFT Showcase page": "NFT ショーケースページ",
|
||||
"Label": "ラベル",
|
||||
"URL": "URL",
|
||||
"subdomain": "サブドメイン",
|
||||
"Custom Domain": "カスタムドメイン",
|
||||
"Set the following record on your DNS provider to active your custom domain": "カスタムドメインを有効にするには、DNSプロバイダーに次のレコードを設定してください。",
|
||||
"Set the following record on your DNS provider to active your custom domain": "カスタムドメインを有効にするには、DNS プロバイダーに次のレコードを設定してください。",
|
||||
"Scope: These styles will be applied to your entire blog, including this dashboard.": "適用範囲:これらのスタイルは、このダッシュボードを含むブログ全体に適用されます。",
|
||||
"Support": "サポート",
|
||||
"CSS variables: xLog provides some built-in CSS variables": "CSS変数:xLogはいくつかのビルトインCSS変数を提供しています。",
|
||||
"CSS variables: xLog provides some built-in CSS variables": "CSS 変数:xLog はいくつかのビルトイン CSS 変数を提供しています。",
|
||||
"Address": "住所",
|
||||
"Character": "キャラクター",
|
||||
"New operator": "新しいオペレーター",
|
||||
"Operator Address": "オペレーターアドレス",
|
||||
"Operator Character Check": "オペレーターキャラクターチェック",
|
||||
"Warning": "警告",
|
||||
"Operators have permissions to enter your dashboard, change your settings(excluding xLog subdomain) and post, modify, delete contents on your site.": "シャドー認証では、ダッシュボードへのアクセス、設定の変更(xLogサブドメインを除く)、サイトのコンテンツの公開・修正・削除が可能です。",
|
||||
"Operators have permissions to enter your dashboard, change your settings(excluding xLog subdomain) and post, modify, delete contents on your site.": "シャドー認証では、ダッシュボードへのアクセス、設定の変更(xLog サブドメインを除く)、サイトのコンテンツの公開・修正・削除が可能です。",
|
||||
"Add": "新規"
|
||||
}
|
||||
|
|
|
|||
|
|
@ -15,6 +15,7 @@
|
|||
"Site Duration": "網站運作時間",
|
||||
"days": "天",
|
||||
"Deleted!": "刪掉了哦!",
|
||||
"Fail to Deleted." : "删除失败",
|
||||
"Converted!": "轉換成功!",
|
||||
"Failed to convert.": "轉換失敗。",
|
||||
"All Posts": "所有文章",
|
||||
|
|
|
|||
|
|
@ -15,6 +15,7 @@
|
|||
"Site Duration": "站点运行时间",
|
||||
"days": "天",
|
||||
"Deleted!" : "已删除!",
|
||||
"Fail to Deleted." : "删除失败",
|
||||
"Converted!" : "已转换!",
|
||||
"Failed to convert." : "转换失败。",
|
||||
"All Posts": "所有文章",
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import { Fragment, useEffect, useMemo, useState } from "react"
|
||||
import { FC, Fragment, useEffect, useMemo, useState } from "react"
|
||||
import { getPageVisibility } from "~/lib/page-helpers"
|
||||
import { useDate } from "~/hooks/useDate"
|
||||
import { TabItem, Tabs } from "../ui/Tabs"
|
||||
|
|
@ -25,6 +25,7 @@ import { Tooltip } from "../ui/Tooltip"
|
|||
import { APP_NAME } from "~/lib/env"
|
||||
import { Trans, useTranslation } from "next-i18next"
|
||||
import { readFiles } from "~/lib/read-files"
|
||||
import { useGetState } from "~/hooks/useGetState"
|
||||
|
||||
export const PagesManager: React.FC<{
|
||||
isPost: boolean
|
||||
|
|
@ -40,38 +41,9 @@ export const PagesManager: React.FC<{
|
|||
[router.query.visibility],
|
||||
)
|
||||
|
||||
const deletePage = useDeletePage()
|
||||
const createOrUpdatePage = useCreateOrUpdatePage()
|
||||
const [convertToastId, setConvertToastId] = useState("")
|
||||
const [deleteToastId, setDeleteToastId] = useState("")
|
||||
const { t } = useTranslation(["dashboard", "site"])
|
||||
const date = useDate()
|
||||
|
||||
useEffect(() => {
|
||||
if (deletePage.isSuccess) {
|
||||
toast.success(t("Deleted!"), {
|
||||
id: deleteToastId,
|
||||
})
|
||||
}
|
||||
}, [deletePage.isSuccess, deleteToastId, t])
|
||||
|
||||
useEffect(() => {
|
||||
if (createOrUpdatePage.isSuccess) {
|
||||
toast.success(t("Converted!"), {
|
||||
id: convertToastId,
|
||||
})
|
||||
} else if (createOrUpdatePage.isError) {
|
||||
toast.error(t("Failed to convert."), {
|
||||
id: convertToastId,
|
||||
})
|
||||
}
|
||||
}, [
|
||||
createOrUpdatePage.isSuccess,
|
||||
createOrUpdatePage.isError,
|
||||
convertToastId,
|
||||
t,
|
||||
])
|
||||
|
||||
const pages = useGetPagesBySite({
|
||||
type: isPost ? "post" : "page",
|
||||
site: subdomain!,
|
||||
|
|
@ -125,91 +97,6 @@ export const PagesManager: React.FC<{
|
|||
}
|
||||
|
||||
const queryClient = useQueryClient()
|
||||
const getPageMenuItems = (page: Note) => {
|
||||
const isCrossbell = !page.applications?.includes("xlog")
|
||||
return [
|
||||
{
|
||||
text: "Edit",
|
||||
icon: <span className="i-mingcute:edit-line inline-block"></span>,
|
||||
onClick() {
|
||||
router.push(getPageEditLink(page))
|
||||
},
|
||||
},
|
||||
{
|
||||
text:
|
||||
"Convert to " +
|
||||
(isCrossbell
|
||||
? `${APP_NAME} ${isPost ? "Post" : "Page"}`
|
||||
: isPost
|
||||
? "Page"
|
||||
: "Post"),
|
||||
icon: <span className="i-mingcute:transfer-3-line inline-block"></span>,
|
||||
onClick() {
|
||||
const toastId = toast.loading("Converting...")
|
||||
if (isCrossbell) {
|
||||
setConvertToastId(toastId)
|
||||
createOrUpdatePage.mutate({
|
||||
published: true,
|
||||
pageId: page.id,
|
||||
siteId: subdomain,
|
||||
tags: page.tags
|
||||
?.filter((tag) => tag !== "post" && tag !== "page")
|
||||
?.join(", "),
|
||||
isPost: isPost,
|
||||
applications: page.applications,
|
||||
})
|
||||
} else {
|
||||
if (!page.metadata) {
|
||||
const data = getStorage(`draft-${subdomain}-${page.id}`)
|
||||
data.isPost = !isPost
|
||||
setStorage(`draft-${subdomain}-${page.id}`, data)
|
||||
queryClient.invalidateQueries(["getPagesBySite", subdomain])
|
||||
queryClient.invalidateQueries(["getPage", page.id])
|
||||
toast.success("Converted!", {
|
||||
id: toastId,
|
||||
})
|
||||
} else {
|
||||
setConvertToastId(toastId)
|
||||
createOrUpdatePage.mutate({
|
||||
published: true,
|
||||
pageId: page.id,
|
||||
siteId: subdomain,
|
||||
tags: page.tags
|
||||
?.filter((tag) => tag !== "post" && tag !== "page")
|
||||
?.join(", "),
|
||||
isPost: !isPost,
|
||||
applications: page.applications,
|
||||
})
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
{
|
||||
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,
|
||||
})
|
||||
}
|
||||
},
|
||||
},
|
||||
]
|
||||
}
|
||||
|
||||
const importFile = () => {
|
||||
const input = document.createElement("input")
|
||||
|
|
@ -365,7 +252,7 @@ export const PagesManager: React.FC<{
|
|||
</div>
|
||||
<div className="w-10 flex-shrink-0">
|
||||
<Menu>
|
||||
{({ open }: { open: boolean }) => (
|
||||
{({ open, close }) => (
|
||||
<>
|
||||
<Menu.Button as={Fragment}>
|
||||
<button
|
||||
|
|
@ -380,27 +267,12 @@ export const PagesManager: React.FC<{
|
|||
<i className="i-mingcute:more-1-line text-2xl" />
|
||||
</button>
|
||||
</Menu.Button>
|
||||
<Menu.Items className="text-sm absolute z-20 right-0 bg-white shadow-modal rounded-lg overflow-hidden py-2 w-64">
|
||||
{getPageMenuItems(page).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()
|
||||
}}
|
||||
>
|
||||
<span className="inline-flex">
|
||||
{item.icon}
|
||||
</span>
|
||||
<span>{t(item.text)}</span>
|
||||
</button>
|
||||
</Menu.Item>
|
||||
)
|
||||
})}
|
||||
</Menu.Items>
|
||||
|
||||
<MenuItems
|
||||
isPost={isPost}
|
||||
page={page}
|
||||
onClick={close}
|
||||
/>
|
||||
</>
|
||||
)}
|
||||
</Menu>
|
||||
|
|
@ -435,3 +307,181 @@ export const PagesManager: React.FC<{
|
|||
</DashboardMain>
|
||||
)
|
||||
}
|
||||
|
||||
const usePageEditLink = (page: { id: string }, isPost: boolean) => {
|
||||
const router = useRouter()
|
||||
const subdomain = router.query.subdomain as string
|
||||
|
||||
return `/dashboard/${subdomain}/editor?id=${page.id}&type=${
|
||||
isPost ? "post" : "page"
|
||||
}`
|
||||
}
|
||||
|
||||
const usePageMenuItems = ({
|
||||
page,
|
||||
isPost,
|
||||
}: {
|
||||
page: Note
|
||||
isPost: boolean
|
||||
}) => {
|
||||
const isCrossbell = !page.applications?.includes("xlog")
|
||||
const router = useRouter()
|
||||
const createOrUpdatePage = useCreateOrUpdatePage()
|
||||
|
||||
const editLink = usePageEditLink(page, isPost)
|
||||
const subdomain = router.query.subdomain as string
|
||||
const queryClient = useQueryClient()
|
||||
const deletePage = useDeletePage()
|
||||
|
||||
const [convertToastId, setConvertToastId] = useState("")
|
||||
const [deleteToastId, setDeleteToastId] = useState("")
|
||||
|
||||
const getDeleteToastId = useGetState(deleteToastId)
|
||||
const getCurrentToastId = useGetState(convertToastId)
|
||||
const { t } = useTranslation(["dashboard", "site"])
|
||||
|
||||
useEffect(() => {
|
||||
if (deletePage.isSuccess) {
|
||||
toast.success(t("Deleted!"), {
|
||||
id: getDeleteToastId(),
|
||||
})
|
||||
}
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [deletePage.isSuccess])
|
||||
|
||||
useEffect(() => {
|
||||
if (deletePage.isError) {
|
||||
toast.error(t("Fail to Deleted."), {
|
||||
id: getDeleteToastId(),
|
||||
})
|
||||
}
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [deletePage.isError])
|
||||
|
||||
useEffect(() => {
|
||||
if (createOrUpdatePage.isSuccess) {
|
||||
toast.success(t("Converted!"), {
|
||||
id: getCurrentToastId(),
|
||||
})
|
||||
} else if (createOrUpdatePage.isError) {
|
||||
toast.error(t("Failed to convert."), {
|
||||
id: getCurrentToastId(),
|
||||
})
|
||||
}
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [createOrUpdatePage.isSuccess, createOrUpdatePage.isError])
|
||||
|
||||
return [
|
||||
{
|
||||
text: "Edit",
|
||||
icon: <span className="i-mingcute:edit-line inline-block"></span>,
|
||||
onClick() {
|
||||
router.push(editLink)
|
||||
},
|
||||
},
|
||||
{
|
||||
text:
|
||||
"Convert to " +
|
||||
(isCrossbell
|
||||
? `${APP_NAME} ${isPost ? "Post" : "Page"}`
|
||||
: isPost
|
||||
? "Page"
|
||||
: "Post"),
|
||||
icon: <span className="i-mingcute:transfer-3-line inline-block"></span>,
|
||||
onClick() {
|
||||
const toastId = toast.loading("Converting...")
|
||||
if (isCrossbell) {
|
||||
setConvertToastId(toastId)
|
||||
createOrUpdatePage.mutate({
|
||||
published: true,
|
||||
pageId: page.id,
|
||||
siteId: subdomain,
|
||||
tags: page.tags
|
||||
?.filter((tag) => tag !== "post" && tag !== "page")
|
||||
?.join(", "),
|
||||
isPost: isPost,
|
||||
applications: page.applications,
|
||||
})
|
||||
} else {
|
||||
if (!page.metadata) {
|
||||
const data = getStorage(`draft-${subdomain}-${page.id}`)
|
||||
data.isPost = !isPost
|
||||
setStorage(`draft-${subdomain}-${page.id}`, data)
|
||||
queryClient.invalidateQueries(["getPagesBySite", subdomain])
|
||||
queryClient.invalidateQueries(["getPage", page.id])
|
||||
toast.success("Converted!", {
|
||||
id: toastId,
|
||||
})
|
||||
} else {
|
||||
setConvertToastId(toastId)
|
||||
createOrUpdatePage.mutate({
|
||||
published: true,
|
||||
pageId: page.id,
|
||||
siteId: subdomain,
|
||||
tags: page.tags
|
||||
?.filter((tag) => tag !== "post" && tag !== "page")
|
||||
?.join(", "),
|
||||
isPost: !isPost,
|
||||
applications: page.applications,
|
||||
})
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
{
|
||||
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,
|
||||
})
|
||||
}
|
||||
},
|
||||
},
|
||||
]
|
||||
}
|
||||
|
||||
const MenuItems: FC<{
|
||||
isPost: boolean
|
||||
page: Note
|
||||
onClick: () => void
|
||||
}> = ({ isPost, page, onClick: onClose }) => {
|
||||
const { t } = useTranslation(["dashboard", "site"])
|
||||
|
||||
return (
|
||||
<Menu.Items className="text-sm absolute z-20 right-0 bg-white shadow-modal rounded-lg overflow-hidden py-2 w-64">
|
||||
{usePageMenuItems({ page, isPost }).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>
|
||||
)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,8 @@
|
|||
import { useEffect, useRef } from "react"
|
||||
|
||||
export const useGetState = (state: any) => {
|
||||
const ref = useRef(state)
|
||||
|
||||
useEffect(() => void (ref.current = state), [state])
|
||||
return () => ref.current
|
||||
}
|
||||
Loading…
Reference in New Issue