diff --git a/package-lock.json b/package-lock.json
index a10ff67..eb8e5e4 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -1,12 +1,12 @@
{
"name": "workbench",
- "version": "1.8.0",
+ "version": "1.8.1",
"lockfileVersion": 2,
"requires": true,
"packages": {
"": {
"name": "workbench",
- "version": "1.8.0",
+ "version": "1.8.1",
"dependencies": {
"@mozilla/readability": "^0.3.0",
"buffer": "^6.0.3",
diff --git a/package.json b/package.json
index 9598d39..407b52d 100644
--- a/package.json
+++ b/package.json
@@ -23,7 +23,7 @@
"@types/mozilla-readability": "^0.2.0",
"@types/turndown": "^5.0.1"
},
- "version": "1.8.0",
+ "version": "1.8.1",
"samepage": {
"extends": "node_modules/roamjs-components/package.json"
}
diff --git a/src/features/WeeklyNoteNav.tsx b/src/features/WeeklyNoteNav.tsx
new file mode 100644
index 0000000..73d4ea1
--- /dev/null
+++ b/src/features/WeeklyNoteNav.tsx
@@ -0,0 +1,33 @@
+import { Button } from "@blueprintjs/core";
+import React from "react";
+
+type WeeklyNoteNavProps = {
+ nextTitle: string;
+ onNavigate: (pageName: string) => void;
+ prevTitle: string;
+};
+
+const WeeklyNoteNav = ({
+ nextTitle,
+ onNavigate,
+ prevTitle,
+}: WeeklyNoteNavProps) => (
+
+
+);
+
+export default WeeklyNoteNav;
diff --git a/src/features/weekly-notes.ts b/src/features/weekly-notes.ts
index 0d077f2..fe29167 100644
--- a/src/features/weekly-notes.ts
+++ b/src/features/weekly-notes.ts
@@ -3,6 +3,8 @@ import _dateFnsFormat from "date-fns/format";
import _parse from "date-fns/parse";
import addWeeks from "date-fns/addWeeks";
import subWeeks from "date-fns/subWeeks";
+import React from "react";
+import ReactDOM from "react-dom";
import { createConfigObserver } from "roamjs-components/components/ConfigPage";
import TextPanel from "roamjs-components/components/ConfigPanels/TextPanel";
import FlagPanel from "roamjs-components/components/ConfigPanels/FlagPanel";
@@ -31,6 +33,7 @@ import {
Field,
UnionField,
} from "roamjs-components/components/ConfigPanels/types";
+import WeeklyNoteNav from "./WeeklyNoteNav";
const ID = "weekly-notes";
const DAYS = [
@@ -45,6 +48,8 @@ const DAYS = [
const DATE_REGEX = new RegExp(`{(${DAYS.join("|")}):(.*?)}`, "g");
const FORMAT_DEFAULT_VALUE = "{monday:MM/dd yyyy} - {sunday:MM/dd yyyy}";
const CONFIG = `roam/js/${ID}`;
+const ROAM_TITLE_CONTAINER_CLASS = "rm-title-display-container";
+const WEEKLY_NOTE_NAV_ID = "roamjs-weekly-mode-nav";
const formatCache = { current: "" };
const getFormat = (tree?: TreeNode[]) =>
@@ -412,8 +417,85 @@ export const toggleFeature = (
return { dateArray: [], formats, valid: false };
};
+ const getWeeklyNavigationTitles = (title: string) => {
+ const { dateArray, valid, formats } = getFormatDateData(title);
+ if (!valid) return null;
+
+ const formattedDateArray = dateArray
+ .map((d, i) => ({
+ cur: dateFnsFormat(d, formats[i]),
+ prev: dateFnsFormat(subWeeks(d, 1), formats[i]),
+ next: dateFnsFormat(addWeeks(d, 1), formats[i]),
+ }))
+ .filter(
+ (info): info is { cur: string; prev: string; next: string } =>
+ !!info.cur && !!info.prev && !!info.next
+ );
+ const prevTitle = formattedDateArray.reduce(
+ (acc, info) => acc.replace(info.cur, info.prev),
+ title
+ );
+ const nextTitle = formattedDateArray.reduce(
+ (acc, info) => acc.replace(info.cur, info.next),
+ title
+ );
+
+ return { prevTitle, nextTitle };
+ };
+
+ let weeklyNoteNavHeader: HTMLHeadingElement | null = null;
+ const removeWeeklyNoteNav = (header?: HTMLElement) => {
+ if (header && header !== weeklyNoteNavHeader) return;
+
+ const nav = document.getElementById(WEEKLY_NOTE_NAV_ID);
+ if (nav) {
+ ReactDOM.unmountComponentAtNode(nav);
+ nav.remove();
+ }
+ weeklyNoteNavHeader = null;
+ };
+
+ const renderWeeklyNoteNav = (
+ header: HTMLHeadingElement,
+ title = getPageTitleValueByHtmlElement(header),
+ expectedTitle = ""
+ ) => {
+ if (!header.closest(".roam-article")) return false;
+ if (expectedTitle && title !== expectedTitle) return false;
+
+ removeWeeklyNoteNav();
+
+ const weeklyNavigationTitles = getWeeklyNavigationTitles(title);
+ if (!weeklyNavigationTitles) return false;
+
+ const headerContainer = header.closest(`.${ROAM_TITLE_CONTAINER_CLASS}`);
+ const insertionPoint = headerContainer || header;
+ const navContainer = document.createElement("div");
+ navContainer.id = WEEKLY_NOTE_NAV_ID;
+ insertionPoint.insertAdjacentElement("afterend", navContainer);
+
+ ReactDOM.render(
+ React.createElement(WeeklyNoteNav, {
+ nextTitle: weeklyNavigationTitles.nextTitle,
+ onNavigate: navigateToPage,
+ prevTitle: weeklyNavigationTitles.prevTitle,
+ }),
+ navContainer
+ );
+ weeklyNoteNavHeader = header;
+
+ return true;
+ };
+
+ const renderCurrentWeeklyNoteNav = (expectedTitle = "") => {
+ const header = document.querySelector(
+ ".roam-article h1.rm-title-display"
+ );
+ if (header) renderWeeklyNoteNav(header, undefined, expectedTitle);
+ };
+
const hashListener = (newUrl: string) => {
- document.getElementById("roamjs-weekly-mode-nav")?.remove?.();
+ removeWeeklyNoteNav();
const urlUid = newUrl.match(/\/page\/(.*)$/)?.[1];
if (urlUid) {
const title = getPageTitleByPageUid(urlUid);
@@ -421,48 +503,8 @@ export const toggleFeature = (
formatCache.current = "";
return;
}
- const { dateArray, valid, formats } = getFormatDateData(title);
- if (valid) {
- const formattedDateArray = dateArray
- .map((d, i) => ({
- cur: dateFnsFormat(d, formats[i]),
- prev: dateFnsFormat(subWeeks(d, 1), formats[i]),
- next: dateFnsFormat(addWeeks(d, 1), formats[i]),
- }))
- .filter(
- (info): info is { cur: string; prev: string; next: string } =>
- !!info.cur && !!info.prev && !!info.next
- );
- const prevTitle = formattedDateArray.reduce(
- (acc, info) => acc.replace(info.cur, info.prev),
- title
- );
- const nextTitle = formattedDateArray.reduce(
- (acc, info) => acc.replace(info.cur, info.next),
- title
- );
- setTimeout(() => {
- const header = document.querySelector(
- ".roam-article h1.rm-title-display"
- ) as HTMLHeadingElement;
- const headerContainer = header.parentElement;
- const buttonContainer = document.createElement("div");
- buttonContainer.style.display = "flex";
- buttonContainer.style.justifyContent = "space-between";
- buttonContainer.style.marginBottom = "32px";
- buttonContainer.id = "roamjs-weekly-mode-nav";
- headerContainer?.appendChild(buttonContainer);
-
- const makeButton = (pagename: string, label: string) => {
- const button = document.createElement("button");
- button.className = "bp3-button";
- button.onclick = () => navigateToPage(pagename);
- button.innerText = label;
- buttonContainer.appendChild(button);
- };
- makeButton(prevTitle, "Last Week");
- makeButton(nextTitle, "Next Week");
- });
+ if (getWeeklyNavigationTitles(title)) {
+ setTimeout(() => renderCurrentWeeklyNoteNav(title));
}
}
};
@@ -472,6 +514,7 @@ export const toggleFeature = (
unloads.add(() =>
window.removeEventListener("hashchange", wrappedListener)
);
+ unloads.add(removeWeeklyNoteNav);
const autoLoad = getFullTreeByParentUid(
getPageUidByPageTitle(CONFIG)
@@ -486,6 +529,7 @@ export const toggleFeature = (
callback: (header: HTMLElement) => {
const title = getPageTitleValueByHtmlElement(header);
const { valid } = getFormatDateData(title);
+ renderWeeklyNoteNav(header as HTMLHeadingElement, title);
if (valid) {
header.onmousedown = (e) => {
if (!e.shiftKey) {
@@ -498,6 +542,7 @@ export const toggleFeature = (
};
}
},
+ removeCallback: removeWeeklyNoteNav,
});
unloads.add(() => h1Observer.disconnect());
} else {