Skip to content

Commit

Permalink
feat: support collection options in nextjs publishing (#1277)
Browse files Browse the repository at this point in the history
* chore: add util to grab custom header content

* chore: add DendronCustomHead component

* feat: add custom head content to head of every note

* chore: fix typo

* feat: support collection options in nextjs publishing

* chore: make collection items into a component

* chore: clean up utils

* chore: remove just-the-doc specific css classes

* chore: fix tag closing

* chore: minor fixes

Co-authored-by: Kevin Lin <kevinslin8@gmail.com>
Co-authored-by: Kevin <kevin@dendron.so>
  • Loading branch information
3 people committed Sep 3, 2021
1 parent 8e6dce5 commit ddaedd4
Show file tree
Hide file tree
Showing 7 changed files with 123 additions and 13 deletions.
2 changes: 1 addition & 1 deletion packages/common-frontend/src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import _ from "lodash";
export enum LoadingStatus {
IDLE = "idle",
PENDING = "pending",
FUFILLED = "fufilled",
FULFILLED = "fulfilled",
}

export type EngineSliceState = {
Expand Down
73 changes: 73 additions & 0 deletions packages/nextjs-template/components/DendronCollection.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
import { NoteProps } from "@dendronhq/common-all";
import { getNoteUrl } from "../utils/links";
import _ from "lodash";
import Link from "next/link";
import { DateTime } from "luxon";

export function DendronCollectionItem(props: {
note: NoteProps;
noteIndex: NoteProps;
}) {
const { note, noteIndex } = props;
const href = getNoteUrl({ note, noteIndex });
let publishedDate: string | undefined;
try {
publishedDate = _.get(note, "custom.date", false)
? ISO2FormattedDate(note.custom.date, DateTime.DATE_SHORT)
: millisToFormattedDate(note.created, DateTime.DATE_SHORT);
} catch (err) {
throw Error(`no date found for note ${note.id}`);
}

return (
<div>
<article itemScope itemType="https://schema.org/CreativeWork">
<h2 itemProp="headline">
<Link href={href}>{note.title}</Link>
</h2>
{!_.isUndefined(publishedDate) && <p>{publishedDate}</p>}
{_.has(note, "custom.excerpt") && (
<p itemProp="description">{note.custom.excerpt}</p>
)}
</article>
</div>
);
}

export function prepChildrenForCollection(
note: NoteProps,
notes: any,
noteIndex: NoteProps
) {
if (note.children.length <= 0) {
return;
}
// console.log({note, notes, noteIndex});
let children = note.children.map((id) => notes[id]);
children = _.sortBy(children, (ent) => {
if (_.has(ent, "custom.date")) {
const dt = DateTime.fromISO(ent.custom.date);
return dt.toMillis();
}
return ent.created;
});
if (_.get(note, "custom.sort_order", "normal") === "reverse") {
children = _.reverse(children);
}
return children;
}

function ISO2FormattedDate(time: string, format: Intl.DateTimeFormatOptions) {
const dt = DateTime.fromISO(time);
return dt.toLocaleString(format);
}

function millisToJSDate(ts: number) {
const dt = DateTime.fromMillis(_.toInteger(ts));
return dt.toJSDate();
}

function millisToFormattedDate(ts: number, format: Intl.DateTimeFormatOptions) {
const dt = DateTime.fromMillis(ts);
return dt.toLocaleString(format);
}
53 changes: 45 additions & 8 deletions packages/nextjs-template/pages/notes/[id].tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,15 +15,35 @@ import React from "react";
import DendronSEO from "../../components/DendronSEO";
import DendronCustomHead from "../../components/DendronCustomHead";
import DendronSpinner from "../../components/DendronSpinner";
import {
DendronCollectionItem,
prepChildrenForCollection,
} from "../../components/DendronCollection";
import { useCombinedDispatch, useCombinedSelector } from "../../features";
import { browserEngineSlice } from "../../features/engine";
import { getCustomHead, getNoteBody, getNoteMeta, getNotes } from "../../utils/build";
import {
getCustomHead,
getNoteBody,
getNoteMeta,
getNotes,
} from "../../utils/build";
import { DendronCommonProps, NoteRouterQuery } from "../../utils/types";
import { NoteProps } from "@dendronhq/common-all";

export type NotePageProps = InferGetStaticPropsType<typeof getStaticProps> &
DendronCommonProps;
DendronCommonProps & { // `InferGetStaticPropsType` doesn't get right types for some reason, hence the manual override here
customHeadContent: string | null;
noteIndex: NoteProps;
};

export default function Note({ note, body, customHeadContent, ...rest }: NotePageProps) {
export default function Note({
note,
body,
collectionChildren,
noteIndex,
customHeadContent,
...rest
}: NotePageProps) {
const logger = createLogger("Note");
const router = useRouter();
const [bodyFromState, setBody] =
Expand All @@ -45,7 +65,7 @@ export default function Note({ note, body, customHeadContent, ...rest }: NotePag
// loaded page statically
if (id === note.id) {
dispatch(
browserEngineSlice.actions.setLoadingStatus(LoadingStatus.FUFILLED)
browserEngineSlice.actions.setLoadingStatus(LoadingStatus.FULFILLED)
);
logger.info({ ctx: "updateNoteBody:exit", id, state: "id = note.id" });
return;
Expand All @@ -57,7 +77,7 @@ export default function Note({ note, body, customHeadContent, ...rest }: NotePag
const contents = await resp.text();
setBody(contents);
dispatch(
browserEngineSlice.actions.setLoadingStatus(LoadingStatus.FUFILLED)
browserEngineSlice.actions.setLoadingStatus(LoadingStatus.FULFILLED)
);
});
}, [id]);
Expand All @@ -68,11 +88,18 @@ export default function Note({ note, body, customHeadContent, ...rest }: NotePag
return <DendronSpinner />;
}

const maybeCollection = note.custom.has_collection
? collectionChildren.map((child: NoteProps) =>
DendronCollectionItem({ note: child, noteIndex })
)
: null;

return (
<>
<DendronSEO />
<DendronCustomHead content={customHeadContent}/>
{customHeadContent && <DendronCustomHead content={customHeadContent} />}
<DendronNote noteContent={noteBody} />
{maybeCollection}
</>
);
}
Expand All @@ -97,12 +124,22 @@ export const getStaticProps: GetStaticProps = async (
if (!_.isString(id)) {
throw Error("id required");
}

const [body, note] = await Promise.all([getNoteBody(id), getNoteMeta(id)]);
const customHeadContent = await getCustomHead();
const noteData = getNotes();
const customHeadContent: string | null = await getCustomHead();
const { notes, noteIndex } = noteData;

const collectionChildren = note.custom.has_collection
? prepChildrenForCollection(note, notes, noteIndex)
: null;

return {
props: {
body,
note,
body,
noteIndex,
collectionChildren,
customHeadContent,
},
};
Expand Down
2 changes: 1 addition & 1 deletion packages/nextjs-template/utils/build.ts
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ export function getPublicDir() {
export async function getCustomHead() {
const config = await getConfig();
const customHeadPathConfig = config.site.customHeaderPath;
if(_.isUndefined(customHeadPathConfig)) {
if (_.isUndefined(customHeadPathConfig)) {
return null;
}
const publicDir = getPublicDir();
Expand Down
2 changes: 1 addition & 1 deletion packages/plugin-core/src/commands/NoteLookupCommand.ts
Original file line number Diff line number Diff line change
Expand Up @@ -246,7 +246,7 @@ export class NoteLookupCommand extends BaseCommand<
!_.includes(
[
DendronQuickPickState.PENDING_NEXT_PICK,
DendronQuickPickState.FUFILLED,
DendronQuickPickState.FULFILLED,
],
quickpick.state
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -173,7 +173,7 @@ export class NoteLookupProvider implements ILookupProviderV3 {
// last chance to cancel
lc.cancelToken.cancel();
if (!this.opts.noHidePickerOnAccept) {
picker.state = DendronQuickPickState.FUFILLED;
picker.state = DendronQuickPickState.FULFILLED;
picker.hide();
}
const onAcceptHookResp = await Promise.all(
Expand Down
2 changes: 1 addition & 1 deletion packages/plugin-core/src/components/lookup/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ export enum DendronQuickPickState {
/**
* Finished taking request
*/
FUFILLED = "FUFILLED",
FULFILLED = "FULFILLED",
/**
* About to show a new picker. Old picker will be hidden but we are still gathering further input
*/
Expand Down

0 comments on commit ddaedd4

Please sign in to comment.