diff --git a/CHANGELOG.md b/CHANGELOG.md index 4a06d080..f81e3bc3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,7 @@ ### 🎨 Enhancements - [#686](https://github.com/estruyf/vscode-front-matter/issues/686): Allow script authors to ask questions during script execution +- [#688](https://github.com/estruyf/vscode-front-matter/issues/688): Allow to show the scheduled articles in the content dashboard (filter and group) ### ⚡️ Optimizations diff --git a/l10n/bundle.l10n.json b/l10n/bundle.l10n.json index 2bcf9160..1f807936 100644 --- a/l10n/bundle.l10n.json +++ b/l10n/bundle.l10n.json @@ -84,6 +84,7 @@ "dashboard.contents.status.draft": "Draft", "dashboard.contents.status.published": "Published", + "dashboard.contents.status.scheduled": "Scheduled", "dashboard.dataView.dataForm.modify": "Modify the data", "dashboard.dataView.dataForm.add": "Add new data", @@ -122,6 +123,7 @@ "dashboard.header.navigation.allArticles": "All articles", "dashboard.header.navigation.published": "Published", + "dashboard.header.navigation.scheduled": "Scheduled", "dashboard.header.navigation.draft": "In draft", "dashboard.header.header.createContent": "Create content", diff --git a/src/dashboardWebView/components/Contents/Item.tsx b/src/dashboardWebView/components/Contents/Item.tsx index 84240b60..7d88bde2 100644 --- a/src/dashboardWebView/components/Contents/Item.tsx +++ b/src/dashboardWebView/components/Contents/Item.tsx @@ -110,7 +110,7 @@ export const Item: React.FunctionComponent = ({ statusHtml ? (
) : ( - cardFields?.state && draftField && draftField.name && + cardFields?.state && draftField && draftField.name && ) } @@ -214,7 +214,7 @@ export const Item: React.FunctionComponent = ({
- {draftField && draftField.name && } + {draftField && draftField.name && }
diff --git a/src/dashboardWebView/components/Contents/Overview.tsx b/src/dashboardWebView/components/Contents/Overview.tsx index c5e7b9bd..492214a5 100644 --- a/src/dashboardWebView/components/Contents/Overview.tsx +++ b/src/dashboardWebView/components/Contents/Overview.tsx @@ -66,6 +66,44 @@ export const Overview: React.FunctionComponent = ({ [grouping] ); + const { groupKeys, groupedPages } = useMemo(() => { + if (grouping === GroupOption.none) { + return { groupKeys: [], groupedPages: {} }; + } + + let groupedPages = groupBy(pages, grouping === GroupOption.Year ? 'fmYear' : 'fmDraft'); + let groupKeys = Object.keys(groupedPages); + + if (grouping === GroupOption.Year) { + groupKeys = groupKeys.sort((a, b) => { + return parseInt(b) - parseInt(a); + }); + } else if (grouping === GroupOption.Draft && settings?.draftField?.type !== 'choice') { + const isInverted = settings?.draftField?.invert; + const allPublished: Page[] = groupedPages['Published'] || []; + const allDrafts: Page[] = groupedPages['Draft'] || []; + + if (allPublished.length > 0) { + const drafts = !isInverted ? allDrafts : allPublished; + const published = (!isInverted ? allPublished : allDrafts).filter((page) => !page.fmPublished || page.fmPublished <= Date.now()); + const scheduled = (!isInverted ? allPublished : allDrafts).filter((page) => page.fmPublished && page.fmPublished > Date.now()); + + delete groupedPages["Published"]; + delete groupedPages["Draft"]; + + groupKeys = ['Scheduled', ...groupKeys]; + groupedPages = { + "Scheduled": scheduled, + "Published": published, + "Draft": drafts, + ...groupedPages, + } + } + } + + return { groupKeys, groupedPages }; + }, [pages, grouping, settings?.draftField]); + React.useEffect(() => { messageHandler.request(DashboardMessage.getPinnedItems).then((items) => { setIsReady(true); @@ -99,40 +137,33 @@ export const Overview: React.FunctionComponent = ({ } if (grouping !== GroupOption.none) { - const groupedPages = groupBy(pages, grouping === GroupOption.Year ? 'fmYear' : 'fmDraft'); - let groupKeys = Object.keys(groupedPages); - - if (grouping === GroupOption.Year) { - groupKeys = groupKeys.sort((a, b) => { - return parseInt(b) - parseInt(a); - }); - } - return ( <> {groupKeys.map((groupId, idx) => ( - - {({ open }) => ( - <> - -

- - {groupName(groupId, groupedPages)} -

-
+ groupedPages[groupId].length > 0 && ( + + {({ open }) => ( + <> + +

+ + {groupName(groupId, groupedPages)} +

+
- - - {groupedPages[groupId].map((page: Page) => ( - - ))} - - - - )} -
+ + + {groupedPages[groupId].map((page: Page) => ( + + ))} + + + + )} +
+ ) ))} ); diff --git a/src/dashboardWebView/components/Contents/Status.tsx b/src/dashboardWebView/components/Contents/Status.tsx index 659c8c31..611ca28e 100644 --- a/src/dashboardWebView/components/Contents/Status.tsx +++ b/src/dashboardWebView/components/Contents/Status.tsx @@ -7,15 +7,18 @@ import { LocalizationKey } from '../../../localization'; export interface IStatusProps { draft: boolean | string; + published: number | null | undefined; } export const Status: React.FunctionComponent = ({ - draft + draft, + published }: React.PropsWithChildren) => { const settings = useRecoilValue(SettingsAtom); const tabInfo = useRecoilValue(TabInfoAtom); const draftField = useMemo(() => settings?.draftField, [settings]); + const isFuture = useMemo(() => published ? published > Date.now() : false, [published]); const draftValue = useMemo(() => { if (draftField && draftField.type === 'choice') { @@ -51,13 +54,18 @@ export const Status: React.FunctionComponent = ({ inline-block px-2 py-1 leading-none rounded-sm font-semibold uppercase tracking-wide text-xs ${draftValue ? 'bg-[var(--vscode-statusBarItem-errorBackground)] text-[var(--vscode-statusBarItem-errorForeground)]' : - 'bg-[var(--vscode-badge-background)] text-[var(--vscode-badge-foreground)]' + isFuture ? + 'bg-[var(--vscode-statusBarItem-warningBackground)] text-[var(--vscode-statusBarItem-warningForeground)]' : + 'bg-[var(--vscode-badge-background)] text-[var(--vscode-badge-foreground)]' }`} > { draftValue ? - l10n.t(LocalizationKey.dashboardContentsStatusDraft) : - l10n.t(LocalizationKey.dashboardContentsStatusPublished) + l10n.t(LocalizationKey.dashboardContentsStatusDraft) : ( + isFuture ? + l10n.t(LocalizationKey.dashboardContentsStatusScheduled) : + l10n.t(LocalizationKey.dashboardContentsStatusPublished) + ) } ); diff --git a/src/dashboardWebView/components/Header/Navigation.tsx b/src/dashboardWebView/components/Header/Navigation.tsx index 2452b122..7ccc7d6b 100644 --- a/src/dashboardWebView/components/Header/Navigation.tsx +++ b/src/dashboardWebView/components/Header/Navigation.tsx @@ -51,6 +51,11 @@ export const Navigation: React.FunctionComponent = ({ if (settings?.draftField?.type === 'boolean' && tabInfo && Object.keys(tabInfo).length > 1) { crntTabs.push({ name: l10n.t(LocalizationKey.dashboardHeaderNavigationPublished), id: Tab.Published }); + + if (tabInfo.scheduled) { + crntTabs.push({ name: l10n.t(LocalizationKey.dashboardHeaderNavigationScheduled), id: Tab.Scheduled }); + } + crntTabs.push({ name: l10n.t(LocalizationKey.dashboardHeaderNavigationDraft), id: Tab.Draft }); } diff --git a/src/dashboardWebView/constants/Tab.ts b/src/dashboardWebView/constants/Tab.ts index 6a037795..69ffaa84 100644 --- a/src/dashboardWebView/constants/Tab.ts +++ b/src/dashboardWebView/constants/Tab.ts @@ -1,5 +1,6 @@ export enum Tab { All = 'all', Published = 'published', - Draft = 'draft' + Draft = 'draft', + Scheduled = 'scheduled' } diff --git a/src/dashboardWebView/hooks/usePages.tsx b/src/dashboardWebView/hooks/usePages.tsx index 98f3dc6e..46640188 100644 --- a/src/dashboardWebView/hooks/usePages.tsx +++ b/src/dashboardWebView/hooks/usePages.tsx @@ -152,23 +152,32 @@ export default function usePages(pages: Page[]) { const usesDraft = crntPages.some(x => typeof x[draftFieldName] !== 'undefined'); if (usesDraft) { - const drafts = crntPages.filter( + const allDrafts = crntPages.filter( (page) => page[draftFieldName] == true || page[draftFieldName] === 'true' ); - const published = crntPages.filter( + const allPublished = crntPages.filter( (page) => page[draftFieldName] == false || page[draftFieldName] === 'false' || typeof page[draftFieldName] === 'undefined' ); - draftTypes[Tab.Draft] = draftField?.invert ? published.length : drafts.length; - draftTypes[Tab.Published] = draftField?.invert ? drafts.length : published.length; + // If the invert is set, the drafts become published and vice versa + const isInverted = draftField?.invert; + const drafts = !isInverted ? allDrafts : allPublished; + const published = (!isInverted ? allPublished : allDrafts).filter((page) => !page.fmPublished || page.fmPublished <= Date.now()); + const scheduled = (!isInverted ? allPublished : allDrafts).filter((page) => page.fmPublished && page.fmPublished > Date.now()); + + draftTypes[Tab.Draft] = drafts.length; + draftTypes[Tab.Published] = published.length; + draftTypes[Tab.Scheduled] = scheduled.length; if (tab === Tab.Published) { - crntPages = draftField?.invert ? drafts : published; + crntPages = published; } else if (tab === Tab.Draft) { - crntPages = draftField?.invert ? published : drafts; + crntPages = drafts; + } else if (tab === Tab.Scheduled) { + crntPages = scheduled; } else { crntPages = crntPages; } diff --git a/src/localization/localization.enum.ts b/src/localization/localization.enum.ts index 64c5e11c..2591c1be 100644 --- a/src/localization/localization.enum.ts +++ b/src/localization/localization.enum.ts @@ -283,6 +283,10 @@ export enum LocalizationKey { * Published */ dashboardContentsStatusPublished = 'dashboard.contents.status.published', + /** + * Scheduled + */ + dashboardContentsStatusScheduled = 'dashboard.contents.status.scheduled', /** * Modify the data */ @@ -391,6 +395,10 @@ export enum LocalizationKey { * Published */ dashboardHeaderNavigationPublished = 'dashboard.header.navigation.published', + /** + * Scheduled + */ + dashboardHeaderNavigationScheduled = 'dashboard.header.navigation.scheduled', /** * In draft */