diff --git a/package.json b/package.json index 8f94e057..4c902a9e 100644 --- a/package.json +++ b/package.json @@ -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", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 5b0a1fd9..31025fc5 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -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: diff --git a/src/app/dashboard/[subdomain]/editor/page.tsx b/src/app/dashboard/[subdomain]/editor/page.tsx index fb513e53..0d5ab838 100644 --- a/src/app/dashboard/[subdomain]/editor/page.tsx +++ b/src/app/dashboard/[subdomain]/editor/page.tsx @@ -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 (
- + {t("Publish at")} + + ) => { - 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)", + }, + }, + }} + /> +
+ {t( `This ${ isPost ? "post" : "page" - } will be accessible from this time`, + } will be accessible from this time. Leave blank to use the current time.`, )} - /> +
+ {values.publishedAt > new Date().toISOString() && ( +
+ {t( + "The post is currently unavailable as its publication date has been scheduled for a future time.", + )} +
+ )}
{showDropdown && ( -
+
{published && (
diff --git a/src/hooks/useDate.ts b/src/hooks/useDate.ts index fa75c2e4..d20c88cf 100644 --- a/src/hooks/useDate.ts +++ b/src/hooks/useDate.ts @@ -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]) diff --git a/src/hooks/useDateServer.ts b/src/hooks/useDateServer.ts index 1f7c6836..27eaa8d2 100644 --- a/src/hooks/useDateServer.ts +++ b/src/hooks/useDateServer.ts @@ -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]) diff --git a/src/hooks/useEdtiorState.ts b/src/hooks/useEdtiorState.ts index baafe63c..8fb5261a 100644 --- a/src/hooks/useEdtiorState.ts +++ b/src/hooks/useEdtiorState.ts @@ -2,7 +2,7 @@ import { create } from "zustand" export const initialEditorState = { title: "", - publishedAt: new Date().toISOString(), + publishedAt: "", published: false, excerpt: "", slug: "", diff --git a/src/lib/expand-unit.ts b/src/lib/expand-unit.ts index 49599c8a..7b48101e 100644 --- a/src/lib/expand-unit.ts +++ b/src/lib/expand-unit.ts @@ -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 ( diff --git a/src/lib/i18n/locales/ja/dashboard.json b/src/lib/i18n/locales/ja/dashboard.json index 1549a708..20acd9d3 100644 --- a/src/lib/i18n/locales/ja/dashboard.json +++ b/src/lib/i18n/locales/ja/dashboard.json @@ -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": "この記事は以下のリンクからアクセス可能になります", diff --git a/src/lib/i18n/locales/zh-TW/dashboard.json b/src/lib/i18n/locales/zh-TW/dashboard.json index 6f33b857..ed528688 100644 --- a/src/lib/i18n/locales/zh-TW/dashboard.json +++ b/src/lib/i18n/locales/zh-TW/dashboard.json @@ -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": "此文章將可通過以下連結瀏覽", diff --git a/src/lib/i18n/locales/zh/dashboard.json b/src/lib/i18n/locales/zh/dashboard.json index 23c3b8bc..0fbff85b 100644 --- a/src/lib/i18n/locales/zh/dashboard.json +++ b/src/lib/i18n/locales/zh/dashboard.json @@ -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": "此文章将可通过以下链接访问", diff --git a/src/lib/page-helpers.ts b/src/lib/page-helpers.ts index d10fa260..d3349235 100644 --- a/src/lib/page-helpers.ts +++ b/src/lib/page-helpers.ts @@ -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 diff --git a/src/models/page.model.ts b/src/models/page.model.ts index 463b4d21..899f368b 100644 --- a/src/models/page.model.ts +++ b/src/models/page.model.ts @@ -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,