diff --git a/src/commands/Dashboard.ts b/src/commands/Dashboard.ts index b5a454ab..3e3e85d2 100644 --- a/src/commands/Dashboard.ts +++ b/src/commands/Dashboard.ts @@ -15,6 +15,7 @@ import { Template } from './Template'; import { Notifications } from '../helpers/Notifications'; import { Settings } from '../pagesView/models/Settings'; import { Extension } from '../helpers/Extension'; +import { parseJSON } from 'date-fns'; export class Dashboard { @@ -181,6 +182,8 @@ export class Dashboard { fmModified: file.mtime, fmFilePath: file.filePath, fmFileName: file.fileName, + fmDraft: article?.data.draft ? "Draft" : "Published", + fmYear: article?.data[dateField] ? parseJSON(article?.data[dateField]).getFullYear() : null, // Make sure these are always set title: article?.data.title, slug: article?.data.slug, diff --git a/src/helpers/GroupBy.ts b/src/helpers/GroupBy.ts new file mode 100644 index 00000000..435be14a --- /dev/null +++ b/src/helpers/GroupBy.ts @@ -0,0 +1,6 @@ +export const groupBy = (array: any[], key: string) => { + return array.reduce((result, currentValue) => { + (result[currentValue[key]] = result[currentValue[key]] || []).push(currentValue); + return result; + }, {}); +}; \ No newline at end of file diff --git a/src/pagesView/components/Dashboard.tsx b/src/pagesView/components/Dashboard.tsx index 56270794..f679dc56 100644 --- a/src/pagesView/components/Dashboard.tsx +++ b/src/pagesView/components/Dashboard.tsx @@ -9,6 +9,7 @@ import useDarkMode from '../../hooks/useDarkMode'; import usePages from '../hooks/usePages'; import { SponsorMsg } from './SponsorMsg'; import { WelcomeScreen } from './WelcomeScreen'; +import { GroupOption } from '../constants/GroupOption'; export interface IDashboardProps { showWelcome: boolean; @@ -22,7 +23,7 @@ export const Dashboard: React.FunctionComponent = ({showWelcome const [ search, setSearch ] = React.useState(null); const [ tag, setTag ] = React.useState(null); const [ category, setCategory ] = React.useState(null); - const [ group, setGroup ] = React.useState(null); + const [ group, setGroup ] = React.useState(GroupOption.none); const { pageItems } = usePages(pages, tab, sorting, folder, search, tag, category); useDarkMode(); @@ -56,13 +57,13 @@ export const Dashboard: React.FunctionComponent = ({showWelcome switchFolder={(folderName: string | null) => setFolder(folderName)} switchTag={(tagId: string | null) => setTag(tagId)} switchCategory={(categoryId: string | null) => setCategory(categoryId)} - switchGroup={(groupName: string | null) => setGroup(groupName)} + switchGroup={(groupId: GroupOption) => setGroup(groupId)} onSearch={(value: string | null) => setSearch(value)} settings={settings} /> -
- { loading ? : } +
+ { loading ? : }
diff --git a/src/pagesView/components/Header/Grouping.tsx b/src/pagesView/components/Header/Grouping.tsx index fd596ea1..15e4a39d 100644 --- a/src/pagesView/components/Header/Grouping.tsx +++ b/src/pagesView/components/Header/Grouping.tsx @@ -1,14 +1,38 @@ +import { Menu } from '@headlessui/react'; import * as React from 'react'; +import { GroupOption } from '../../constants/GroupOption'; +import { MenuButton, MenuItem, MenuItems } from '../Menu'; export interface IGroupingProps { - crntGroup: string | null; - switchGroup: (group: string | null) => void; + group: GroupOption; + switchGroup: (group: GroupOption) => void; } -export const Grouping: React.FunctionComponent = (props: React.PropsWithChildren) => { - return ( - <> +export const groupOptions = [ + { name: "None", id: GroupOption.none }, + { name: "Year", id: GroupOption.Year }, + { name: "Draft/Published", id: GroupOption.Draft }, +]; - +export const Grouping: React.FunctionComponent = ({group, switchGroup}: React.PropsWithChildren) => { + const crntGroup = groupOptions.find(x => x.id === group); + + return ( +
+ + + + + {groupOptions.map((option) => ( + + ))} + + +
); }; \ No newline at end of file diff --git a/src/pagesView/components/Header/Header.tsx b/src/pagesView/components/Header/Header.tsx index 5c67b7a2..b1fecfe3 100644 --- a/src/pagesView/components/Header/Header.tsx +++ b/src/pagesView/components/Header/Header.tsx @@ -12,6 +12,7 @@ import { Startup } from '../Startup'; import { Button } from '../Button'; import { Navigation } from '../Navigation'; import { Grouping } from '.'; +import { GroupOption } from '../../constants/GroupOption'; export interface IHeaderProps { settings: Settings; @@ -42,8 +43,8 @@ export interface IHeaderProps { switchCategory: (category: string | null) => void; // Grouping - crntGroup: string | null; - switchGroup: (groupId: string | null) => void; + crntGroup: GroupOption; + switchGroup: (groupId: GroupOption) => void; } export const Header: React.FunctionComponent = ({currentTab, currentSorting, switchSorting, switchTab, totalPages, crntFolder, folders, switchFolder, onSearch, settings, switchTag, crntTag, switchCategory, crntCategory, crntGroup, switchGroup}: React.PropsWithChildren) => { @@ -73,7 +74,7 @@ export const Header: React.FunctionComponent = ({currentTab, curre - +
diff --git a/src/pagesView/components/Overview.tsx b/src/pagesView/components/Overview.tsx index 8644b110..ae68bd08 100644 --- a/src/pagesView/components/Overview.tsx +++ b/src/pagesView/components/Overview.tsx @@ -1,5 +1,9 @@ +import { Disclosure } from '@headlessui/react'; +import { ChevronRightIcon } from '@heroicons/react/solid'; import * as React from 'react'; +import { groupBy } from '../../helpers/GroupBy'; import { FrontMatterIcon } from '../../viewpanel/components/Icons/FrontMatterIcon'; +import { GroupOption } from '../constants/GroupOption'; import { Page } from '../models/Page'; import { Settings } from '../models/Settings'; import { Item } from './Item'; @@ -7,11 +11,13 @@ import { List } from './List'; export interface IOverviewProps { pages: Page[]; + grouping: GroupOption; settings: Settings; } -export const Overview: React.FunctionComponent = ({pages, settings}: React.PropsWithChildren) => { +export const Overview: React.FunctionComponent = ({pages, settings, grouping}: React.PropsWithChildren) => { + const [ open, setOpen ] = React.useState(true); if (!pages || !pages.length) { return ( @@ -32,6 +38,46 @@ export const Overview: React.FunctionComponent = ({pages, settin ); } + 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 }) => ( + <> + +

+ + {GroupOption[grouping]}: {groupId} ({groupedPages[groupId].length}) +

+
+ + + + {groupedPages[groupId].map((page: Page) => ( + + ))} + + + + )} +
+ )) + } + + ); + } + return ( {pages.map(page => ( diff --git a/src/pagesView/constants/GroupOption.ts b/src/pagesView/constants/GroupOption.ts new file mode 100644 index 00000000..bd0f18e0 --- /dev/null +++ b/src/pagesView/constants/GroupOption.ts @@ -0,0 +1,7 @@ + + +export enum GroupOption { + none = 1, + Year, + Draft +} \ No newline at end of file diff --git a/src/pagesView/models/Page.ts b/src/pagesView/models/Page.ts index e990216d..536ecd69 100644 --- a/src/pagesView/models/Page.ts +++ b/src/pagesView/models/Page.ts @@ -5,6 +5,8 @@ export interface Page { fmFilePath: string; fmFileName: string; fmModified: number; + fmDraft: "Draft" | "Published", + fmYear: number | null; title: string; slug: string;