feat: refactor the publish time input box and add a scheduled publish warning

This commit is contained in:
DIYgod 2023-05-16 19:32:33 +01:00
parent 0a9a5b3714
commit f138acc154
No known key found for this signature in database
13 changed files with 80 additions and 62 deletions

View File

@ -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",

View File

@ -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:

View File

@ -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

View File

@ -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>

View File

@ -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])

View File

@ -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])

View File

@ -2,7 +2,7 @@ import { create } from "zustand"
export const initialEditorState = {
title: "",
publishedAt: new Date().toISOString(),
publishedAt: "",
published: false,
excerpt: "",
slug: "",

View File

@ -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 (

View File

@ -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": "この記事は以下のリンクからアクセス可能になります",

View File

@ -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": "此文章將可通過以下連結瀏覽",

View File

@ -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": "此文章将可通过以下链接访问",

View File

@ -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

View File

@ -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,