feat: refactor the publish time input box and add a scheduled publish warning
This commit is contained in:
parent
0a9a5b3714
commit
f138acc154
|
|
@ -51,6 +51,7 @@
|
|||
"@iconify-json/mingcute": "^1.1.6",
|
||||
"@lezer/highlight": "^1.1.4",
|
||||
"@mantine/core": "^6.0.10",
|
||||
"@mantine/dates": "^6.0.11",
|
||||
"@monaco-editor/react": "4.5.1",
|
||||
"@popperjs/core": "^2.11.7",
|
||||
"@prisma/client": "^4.14.0",
|
||||
|
|
|
|||
|
|
@ -69,7 +69,10 @@ dependencies:
|
|||
version: 1.1.4
|
||||
'@mantine/core':
|
||||
specifier: ^6.0.10
|
||||
version: 6.0.10(@emotion/react@11.10.8)(@mantine/hooks@6.0.10)(@types/react@18.2.6)(react-dom@18.2.0)(react@18.2.0)
|
||||
version: 6.0.10(@emotion/react@11.10.8)(@mantine/hooks@6.0.9)(@types/react@18.2.6)(react-dom@18.2.0)(react@18.2.0)
|
||||
'@mantine/dates':
|
||||
specifier: ^6.0.11
|
||||
version: 6.0.11(@mantine/core@6.0.10)(@mantine/hooks@6.0.9)(dayjs@1.11.7)(react@18.2.0)
|
||||
'@monaco-editor/react':
|
||||
specifier: 4.5.1
|
||||
version: 4.5.1(monaco-editor@0.37.1)(react-dom@18.2.0)(react@18.2.0)
|
||||
|
|
@ -3517,27 +3520,6 @@ packages:
|
|||
'@lit-labs/ssr-dom-shim': 1.1.0
|
||||
dev: false
|
||||
|
||||
/@mantine/core@6.0.10(@emotion/react@11.10.8)(@mantine/hooks@6.0.10)(@types/react@18.2.6)(react-dom@18.2.0)(react@18.2.0):
|
||||
resolution: {integrity: sha512-Q8HdRTBkQDs6LEtklpYm6efz2WaV6T5rvgjUOfXq0z44G/XYM+P1B1BSFnHvUDkeWYLcGkK6aPI5Uxc0GEN04w==}
|
||||
peerDependencies:
|
||||
'@mantine/hooks': 6.0.10
|
||||
react: '>=16.8.0'
|
||||
react-dom: '>=16.8.0'
|
||||
dependencies:
|
||||
'@floating-ui/react': 0.19.2(react-dom@18.2.0)(react@18.2.0)
|
||||
'@mantine/hooks': 6.0.10(react@18.2.0)
|
||||
'@mantine/styles': 6.0.10(@emotion/react@11.10.8)(react-dom@18.2.0)(react@18.2.0)
|
||||
'@mantine/utils': 6.0.10(react@18.2.0)
|
||||
'@radix-ui/react-scroll-area': 1.0.2(react-dom@18.2.0)(react@18.2.0)
|
||||
react: 18.2.0
|
||||
react-dom: 18.2.0(react@18.2.0)
|
||||
react-remove-scroll: 2.5.5(@types/react@18.2.6)(react@18.2.0)
|
||||
react-textarea-autosize: 8.3.4(@types/react@18.2.6)(react@18.2.0)
|
||||
transitivePeerDependencies:
|
||||
- '@emotion/react'
|
||||
- '@types/react'
|
||||
dev: false
|
||||
|
||||
/@mantine/core@6.0.10(@emotion/react@11.10.8)(@mantine/hooks@6.0.9)(@types/react@18.2.6)(react-dom@18.2.0)(react@18.2.0):
|
||||
resolution: {integrity: sha512-Q8HdRTBkQDs6LEtklpYm6efz2WaV6T5rvgjUOfXq0z44G/XYM+P1B1BSFnHvUDkeWYLcGkK6aPI5Uxc0GEN04w==}
|
||||
peerDependencies:
|
||||
|
|
@ -3559,11 +3541,18 @@ packages:
|
|||
- '@types/react'
|
||||
dev: false
|
||||
|
||||
/@mantine/hooks@6.0.10(react@18.2.0):
|
||||
resolution: {integrity: sha512-rxH5/CxmUs1mUZAj27Fza4SH07HV1XyrL7L9wwhZdMLg+oDEaAs8BMz8lsOIHOCro9ZDh+Mm7QAbEW8HcvmYJg==}
|
||||
/@mantine/dates@6.0.11(@mantine/core@6.0.10)(@mantine/hooks@6.0.9)(dayjs@1.11.7)(react@18.2.0):
|
||||
resolution: {integrity: sha512-R0+fZQoTH8ioiAiVA7RFBsO6NL4MPz3d1lin2QCi/rj3ICp/+8X+AG4jN1Uy+xtWgfPB+hjp5RJASyUa0hNqtw==}
|
||||
peerDependencies:
|
||||
'@mantine/core': 6.0.11
|
||||
'@mantine/hooks': 6.0.11
|
||||
dayjs: '>=1.0.0'
|
||||
react: '>=16.8.0'
|
||||
dependencies:
|
||||
'@mantine/core': 6.0.10(@emotion/react@11.10.8)(@mantine/hooks@6.0.9)(@types/react@18.2.6)(react-dom@18.2.0)(react@18.2.0)
|
||||
'@mantine/hooks': 6.0.9(react@18.2.0)
|
||||
'@mantine/utils': 6.0.11(react@18.2.0)
|
||||
dayjs: 1.11.7
|
||||
react: 18.2.0
|
||||
dev: false
|
||||
|
||||
|
|
@ -3613,6 +3602,14 @@ packages:
|
|||
react: 18.2.0
|
||||
dev: false
|
||||
|
||||
/@mantine/utils@6.0.11(react@18.2.0):
|
||||
resolution: {integrity: sha512-ijkEAaKEhZCw7HSWsGMQZsvfmQKmJXmPoQ1LeEwcH3vjZalPk9pQjSPPfUdTeX9ZAv095XWmfVMiNV8+xvM0OQ==}
|
||||
peerDependencies:
|
||||
react: '>=16.8.0'
|
||||
dependencies:
|
||||
react: 18.2.0
|
||||
dev: false
|
||||
|
||||
/@mantine/utils@6.0.9(react@18.2.0):
|
||||
resolution: {integrity: sha512-zEDZixO8dw2ZSNZiQ1g7S+Bq2q4E8ps6bvpyZsxpiXBdh3g2H0WOEdJdDpBTiTRPWotSlU1kaKN3tOplCRDQ2Q==}
|
||||
peerDependencies:
|
||||
|
|
|
|||
|
|
@ -18,6 +18,7 @@ import toast from "react-hot-toast"
|
|||
import { shallow } from "zustand/shallow"
|
||||
|
||||
import type { EditorView } from "@codemirror/view"
|
||||
import { DateInput } from "@mantine/dates"
|
||||
import { useQueryClient } from "@tanstack/react-query"
|
||||
|
||||
import { PageContent } from "~/components/common/PageContent"
|
||||
|
|
@ -33,7 +34,6 @@ import { TagInput } from "~/components/ui/TagInput"
|
|||
import { UniLink } from "~/components/ui/UniLink"
|
||||
import { toolbars } from "~/editor"
|
||||
import { editorUpload } from "~/editor/Multimedia"
|
||||
import { useDate } from "~/hooks/useDate"
|
||||
import {
|
||||
Values,
|
||||
initialEditorState,
|
||||
|
|
@ -61,11 +61,6 @@ import {
|
|||
} from "~/queries/page"
|
||||
import { useGetSite } from "~/queries/site"
|
||||
|
||||
const getInputDatetimeValue = (date: Date | string, dayjs: any) => {
|
||||
const str = dayjs(date).format()
|
||||
return str.substring(0, ((str.indexOf("T") | 0) + 6) | 0)
|
||||
}
|
||||
|
||||
export default function SubdomainEditor() {
|
||||
const router = useRouter()
|
||||
const queryClient = useQueryClient()
|
||||
|
|
@ -721,32 +716,55 @@ const EditorExtraProperties: FC<{
|
|||
(state) => pick(state, ["publishedAt", "slug", "excerpt", "tags"]),
|
||||
shallow,
|
||||
)
|
||||
const date = useDate()
|
||||
const { t } = useTranslation("dashboard")
|
||||
const site = useGetSite(subdomain)
|
||||
|
||||
return (
|
||||
<div className="h-full overflow-auto flex-shrink-0 w-[280px] border-l bg-zinc-50 p-5 space-y-5">
|
||||
<div>
|
||||
<Input
|
||||
type="datetime-local"
|
||||
label={t("Publish at") || ""}
|
||||
isBlock
|
||||
<label className="form-label" htmlFor="publishAt">
|
||||
{t("Publish at")}
|
||||
</label>
|
||||
<DateInput
|
||||
className=""
|
||||
allowDeselect
|
||||
clearable
|
||||
valueFormat="YYYY-MM-DD, h:mm a"
|
||||
name="publishAt"
|
||||
id="publishAt"
|
||||
value={getInputDatetimeValue(values.publishedAt, date.dayjs)}
|
||||
onChange={(e: ChangeEvent<HTMLInputElement>) => {
|
||||
try {
|
||||
const value = date.inLocalTimezone(e.target.value).toISOString()
|
||||
updateValue("publishedAt", value)
|
||||
} catch (error) {}
|
||||
value={values.publishedAt ? new Date(values.publishedAt) : undefined}
|
||||
onChange={(value: Date | null) => {
|
||||
if (value) {
|
||||
updateValue("publishedAt", value.toISOString())
|
||||
} else {
|
||||
updateValue("publishedAt", "")
|
||||
}
|
||||
}}
|
||||
help={t(
|
||||
styles={{
|
||||
input: {
|
||||
borderRadius: "0.5rem",
|
||||
borderColor: "var(--border-color)",
|
||||
height: "2.5rem",
|
||||
"&:focus-within": {
|
||||
borderColor: "var(--theme-color)",
|
||||
},
|
||||
},
|
||||
}}
|
||||
/>
|
||||
<div className="text-xs text-gray-400 mt-1">
|
||||
{t(
|
||||
`This ${
|
||||
isPost ? "post" : "page"
|
||||
} will be accessible from this time`,
|
||||
} will be accessible from this time. Leave blank to use the current time.`,
|
||||
)}
|
||||
/>
|
||||
</div>
|
||||
{values.publishedAt > new Date().toISOString() && (
|
||||
<div className="text-xs mt-1 text-red-500">
|
||||
{t(
|
||||
"The post is currently unavailable as its publication date has been scheduled for a future time.",
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
<div>
|
||||
<Input
|
||||
|
|
|
|||
|
|
@ -71,7 +71,10 @@ export const PublishButton: React.FC<{
|
|||
)}
|
||||
</ButtonGroup>
|
||||
{showDropdown && (
|
||||
<div className="absolute right-0 min-w-[200px] pt-2" ref={dropdownRef}>
|
||||
<div
|
||||
className="absolute right-0 min-w-[200px] pt-2 z-10"
|
||||
ref={dropdownRef}
|
||||
>
|
||||
<div className="bg-white py-2 rounded-lg shadow-modal">
|
||||
{published && (
|
||||
<div>
|
||||
|
|
|
|||
|
|
@ -32,9 +32,6 @@ export function useDate() {
|
|||
formatToISO: (date: string | Date) => {
|
||||
return dayjs(date || undefined).toISOString()
|
||||
},
|
||||
inLocalTimezone: (date: string | Date) => {
|
||||
return dayjs(date).tz().toDate()
|
||||
},
|
||||
}
|
||||
}, [i18n.resolvedLanguage])
|
||||
|
||||
|
|
|
|||
|
|
@ -32,9 +32,6 @@ export async function useDate() {
|
|||
formatToISO: (date: string | Date) => {
|
||||
return dayjs(date || undefined).toISOString()
|
||||
},
|
||||
inLocalTimezone: (date: string | Date) => {
|
||||
return dayjs(date).tz().toDate()
|
||||
},
|
||||
}
|
||||
}, [i18n.resolvedLanguage])
|
||||
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@ import { create } from "zustand"
|
|||
|
||||
export const initialEditorState = {
|
||||
title: "",
|
||||
publishedAt: new Date().toISOString(),
|
||||
publishedAt: "",
|
||||
published: false,
|
||||
excerpt: "",
|
||||
slug: "",
|
||||
|
|
|
|||
|
|
@ -47,6 +47,8 @@ export const expandCrossbellNote = async (
|
|||
expandedNote.metadata.content.frontMatter = rendered.frontMatter
|
||||
}
|
||||
expandedNote.metadata.content.slug = getNoteSlug(expandedNote)
|
||||
expandedNote.metadata.content.date_published =
|
||||
expandedNote.metadata.content.date_published || new Date().toISOString()
|
||||
|
||||
if (useStat) {
|
||||
const stat = await (
|
||||
|
|
|
|||
|
|
@ -62,8 +62,9 @@
|
|||
"Update": "更新",
|
||||
"Discard Changes": "変更を破棄",
|
||||
"Publish at": "公開日時",
|
||||
"This post will be accessible from this time": "この記事は、この時間からアクセス可能になります",
|
||||
"This page will be accessible from this time": "このページは、この時間からアクセス可能になります",
|
||||
"This post will be accessible from this time. Leave blank to use the current time.": "この記事は以下の日時からアクセス可能になります。現在の日時を使用する場合は空白のままにしてください。",
|
||||
"This page will be accessible from this time. Leave blank to use the current time.": "このページは以下の日時からアクセス可能になります。現在の日時を使用する場合は空白のままにしてください。",
|
||||
"The post is currently unavailable as its publication date has been scheduled for a future time.": "この記事は現在利用できません。公開日時が未来に設定されています。",
|
||||
"Post slug": "記事スラッグ",
|
||||
"Page slug": "ページスラッグ",
|
||||
"This post will be accessible at": "この記事は以下のリンクからアクセス可能になります",
|
||||
|
|
|
|||
|
|
@ -66,8 +66,9 @@
|
|||
"Update": "更新",
|
||||
"Discard Changes": "捨棄變更",
|
||||
"Publish at": "發布時間",
|
||||
"This post will be accessible from this time": "此文章將從此時間開始可瀏覽",
|
||||
"This page will be accessible from this time": "此頁面將從此時間開始可瀏覽",
|
||||
"This post will be accessible from this time. Leave blank to use the current time.": "文章將在此時間後可訪問。留空則使用當前時間。",
|
||||
"This page will be accessible from this time. Leave blank to use the current time.": "頁面將在此時間後可訪問。留空則使用當前時間。",
|
||||
"The post is currently unavailable as its publication date has been scheduled for a future time.": "該帖子目前無法使用,因為它的發布日期已被安排在未來。",
|
||||
"Post slug": "文章短連結",
|
||||
"Page slug": "頁面短連結",
|
||||
"This post will be accessible at": "此文章將可通過以下連結瀏覽",
|
||||
|
|
|
|||
|
|
@ -68,8 +68,9 @@
|
|||
"Update": "更新",
|
||||
"Discard Changes": "放弃变更",
|
||||
"Publish at": "发布时间",
|
||||
"This post will be accessible from this time": "此文章将从此时间开始可访问",
|
||||
"This page will be accessible from this time": "此页面将从此时间开始可访问",
|
||||
"This post will be accessible from this time. Leave blank to use the current time.": "此文章将从此时间开始可访问。留空则使用当前时间。",
|
||||
"This page will be accessible from this time. Leave blank to use the current time.": "此页面将从此时间开始可访问。留空则使用当前时间。",
|
||||
"The post is currently unavailable as its publication date has been scheduled for a future time.": "此文章当前不可用,因为它的发布日期已被定为将来的某个时间。",
|
||||
"Post slug": "文章短链接",
|
||||
"Page slug": "页面短链接",
|
||||
"This post will be accessible at": "此文章将可通过以下链接访问",
|
||||
|
|
|
|||
|
|
@ -6,7 +6,9 @@ export const getPageVisibility = (note?: ExpandedNote) => {
|
|||
if (!note?.noteId) {
|
||||
return PageVisibilityEnum.Draft
|
||||
} else if (
|
||||
dayjs(note.metadata?.content?.date_published).isBefore(new Date())
|
||||
!note.metadata?.content?.date_published ||
|
||||
dayjs(note.metadata?.content?.date_published).isBefore(new Date()) ||
|
||||
dayjs(note.metadata?.content?.date_published).isSame(new Date())
|
||||
) {
|
||||
if (note.local) {
|
||||
return PageVisibilityEnum.Modified
|
||||
|
|
|
|||
|
|
@ -95,9 +95,7 @@ export async function createOrUpdatePage(
|
|||
mime_type: "text/markdown",
|
||||
},
|
||||
}),
|
||||
...(input.publishedAt && {
|
||||
date_published: input.publishedAt,
|
||||
}),
|
||||
date_published: input.publishedAt || new Date().toISOString(),
|
||||
...(input.excerpt && {
|
||||
summary: {
|
||||
content: input.excerpt,
|
||||
|
|
|
|||
Loading…
Reference in New Issue