diff --git a/package.json b/package.json index 2422235..3244168 100644 --- a/package.json +++ b/package.json @@ -13,8 +13,8 @@ }, "dependencies": { "obsidian": "obsidianmd/obsidian-api#master", - "obsidian-calendar-ui": "0.3.12", - "obsidian-daily-notes-interface": "0.9.0", + "obsidian-calendar-ui": "0.4.0", + "obsidian-daily-notes-interface": "0.9.4", "svelte": "3.35.0", "tslib": "2.1.0" }, diff --git a/src/io/periodicNotes.ts b/src/io/periodicNotes.ts new file mode 100644 index 0000000..10ea339 --- /dev/null +++ b/src/io/periodicNotes.ts @@ -0,0 +1,100 @@ +import type { Moment } from "moment"; +import type { TFile } from "obsidian"; +import { + createDailyNote, + createWeeklyNote, + createMonthlyNote, + createYearlyNote, + getDailyNoteSettings, + getWeeklyNoteSettings, + getMonthlyNoteSettings, + getYearlyNoteSettings, +} from "obsidian-daily-notes-interface"; + +import type { ISettings } from "src/settings"; +import { createConfirmationDialog } from "src/ui/modal"; + +export enum Period { + Daily = "Daily", + Weekly = "Weekly", + Monthly = "Monthly", + Yearly = "Yearly" +} + +export const getDateForPeriodicNote = (date: Moment, noteType: Period) => { + switch (noteType) { + case Period.Daily: + return date; + case Period.Weekly: + return date.startOf("week"); + case Period.Monthly: + return date.startOf("month"); + case Period.Yearly: + return date.startOf("year"); + } + } +const getCreateNoteFunction = (noteType: Period) => { + switch (noteType) { + case Period.Daily: + return createDailyNote; + case Period.Weekly: + return createWeeklyNote; + case Period.Monthly: + return createMonthlyNote; + case Period.Yearly: + return createYearlyNote; + } +}; + +const getNoteSettingsGetter = (noteType: Period) => { + switch (noteType) { + case Period.Daily: + return getDailyNoteSettings; + case Period.Weekly: + return getWeeklyNoteSettings; + case Period.Monthly: + return getMonthlyNoteSettings; + case Period.Yearly: + return getYearlyNoteSettings; + } +}; + +/** + * Create a Daily Note for a given date. + */ +export async function tryToCreatePeriodicNote( + date: Moment, + inNewSplit: boolean, + settings: ISettings, + noteType: Period, + cb?: (newFile: TFile) => void +): Promise { + const noteCreator = getCreateNoteFunction(noteType); + const noteSettingsGetter = getNoteSettingsGetter(noteType); + + const { workspace } = window.app; + const { format } = noteSettingsGetter(); + const filename = date.format(format); + + + const createFile = async () => { + const note = await noteCreator(date); + const leaf = inNewSplit + ? workspace.splitActiveLeaf() + : workspace.getUnpinnedLeaf(); + + await leaf.openFile(note, { active: true }); + cb?.(note); + }; + + if (settings.shouldConfirmBeforeCreate) { + createConfirmationDialog({ + cta: "Create", + onAccept: createFile, + text: `File ${filename} does not exist. Would you like to create it?`, + title: `New ${noteType} Note test`, + }); + } else { + await createFile(); + } +} diff --git a/src/ui/Calendar.svelte b/src/ui/Calendar.svelte index d2ab227..75b83b8 100644 --- a/src/ui/Calendar.svelte +++ b/src/ui/Calendar.svelte @@ -22,6 +22,7 @@ export let onHoverWeek: (date: Moment, targetEl: EventTarget) => boolean; export let onClickDay: (date: Moment, isMetaPressed: boolean) => boolean; export let onClickWeek: (date: Moment, isMetaPressed: boolean) => boolean; + export let onClickMonth: (date: Moment, isMetaPressed: boolean) => boolean; export let onContextMenuDay: (date: Moment, event: MouseEvent) => boolean; export let onContextMenuWeek: (date: Moment, event: MouseEvent) => boolean; @@ -62,6 +63,7 @@ {onContextMenuWeek} {onClickDay} {onClickWeek} + {onClickMonth} bind:displayedMonth localeData={today.localeData()} selectedId={$activeFile} diff --git a/src/view.ts b/src/view.ts index 043a967..01c254c 100644 --- a/src/view.ts +++ b/src/view.ts @@ -10,8 +10,7 @@ import { FileView, TFile, ItemView, WorkspaceLeaf } from "obsidian"; import { get } from "svelte/store"; import { TRIGGER_ON_OPEN, VIEW_TYPE_CALENDAR } from "src/constants"; -import { tryToCreateDailyNote } from "src/io/dailyNotes"; -import { tryToCreateWeeklyNote } from "src/io/weeklyNotes"; +import { getDateForPeriodicNote, tryToCreatePeriodicNote, Period } from "src/io/periodicNotes"; import type { ISettings } from "src/settings"; import Calendar from "./ui/Calendar.svelte"; @@ -33,6 +32,7 @@ export default class CalendarView extends ItemView { this.openOrCreateDailyNote = this.openOrCreateDailyNote.bind(this); this.openOrCreateWeeklyNote = this.openOrCreateWeeklyNote.bind(this); + this.openOrCreateMonthlyNote = this.openOrCreateMonthlyNote.bind(this); this.onNoteSettingsUpdate = this.onNoteSettingsUpdate.bind(this); this.onFileCreated = this.onFileCreated.bind(this); @@ -105,6 +105,7 @@ export default class CalendarView extends ItemView { props: { onClickDay: this.openOrCreateDailyNote, onClickWeek: this.openOrCreateWeeklyNote, + onClickMonth: this.openOrCreateMonthlyNote, onHoverDay: this.onHoverDay, onHoverWeek: this.onHoverWeek, onContextMenuDay: this.onContextMenuDay, @@ -255,45 +256,21 @@ export default class CalendarView extends ItemView { } } - async openOrCreateWeeklyNote( - date: Moment, - inNewSplit: boolean - ): Promise { - const { workspace } = this.app; - - const startOfWeek = date.clone().startOf("week"); - - const existingFile = getWeeklyNote(date, get(weeklyNotes)); - - if (!existingFile) { - // File doesn't exist - tryToCreateWeeklyNote(startOfWeek, inNewSplit, this.settings, (file) => { - activeFile.setFile(file); - }); - return; - } - - const leaf = inNewSplit - ? workspace.splitActiveLeaf() - : workspace.getUnpinnedLeaf(); - await leaf.openFile(existingFile); - - activeFile.setFile(existingFile); - workspace.setActiveLeaf(leaf, true, true) - } - - async openOrCreateDailyNote( + async openOrCreatePeriodicNote( + noteType: Period, date: Moment, - inNewSplit: boolean + inNewSplit: boolean, ): Promise { const { workspace } = this.app; - const existingFile = getDailyNote(date, get(dailyNotes)); + const periodicNoteDate = getDateForPeriodicNote(date, noteType); + const existingFile = getDailyNote(periodicNoteDate, get(dailyNotes)); if (!existingFile) { // File doesn't exist - tryToCreateDailyNote( + tryToCreatePeriodicNote( date, inNewSplit, this.settings, + Period.Daily, (dailyNote: TFile) => { activeFile.setFile(dailyNote); } @@ -310,4 +287,27 @@ export default class CalendarView extends ItemView { activeFile.setFile(existingFile); } + + async openOrCreateDailyNote( + date: Moment, + inNewSplit: boolean + ) { + this.openOrCreatePeriodicNote(Period.Daily, date, inNewSplit); + } + + async openOrCreateWeeklyNote( + date: Moment, + inNewSplit: boolean + ) { + this.openOrCreatePeriodicNote(Period.Weekly, date, inNewSplit); + } + + async openOrCreateMonthlyNote( + date: Moment, + inNewSplit: boolean + ) { + this.openOrCreatePeriodicNote(Period.Monthly, date, inNewSplit); + } + + } diff --git a/yarn.lock b/yarn.lock index 5aa56a9..768933b 100644 --- a/yarn.lock +++ b/yarn.lock @@ -602,6 +602,13 @@ dependencies: "@types/tern" "*" +"@types/codemirror@5.60.8": + version "5.60.8" + resolved "https://registry.yarnpkg.com/@types/codemirror/-/codemirror-5.60.8.tgz#b647d04b470e8e1836dd84b2879988fc55c9de68" + integrity sha512-VjFgDF/eB+Aklcy15TtOTLQeMjTo07k7KAjql8OK5Dirr7a6sJY4T1uVBDuTVG9VEmn1uUsohOpYnVfgC6/jyw== + dependencies: + "@types/tern" "*" + "@types/estree@*": version "0.0.47" resolved "https://registry.yarnpkg.com/@types/estree/-/estree-0.0.47.tgz#d7a51db20f0650efec24cd04994f523d93172ed4" @@ -3074,6 +3081,11 @@ moment@*, moment@2.29.1: resolved "https://registry.yarnpkg.com/moment/-/moment-2.29.1.tgz#b2be769fa31940be9eeea6469c075e35006fa3d3" integrity sha512-kHmoybcPV8Sqy59DwNDY3Jefr64lK/by/da0ViFcuA4DH0vQg5Q6Ze5VimxkfQNSC+Mls/Kx53s7TjP1RhFEDQ== +moment@2.29.4: + version "2.29.4" + resolved "https://registry.yarnpkg.com/moment/-/moment-2.29.4.tgz#3dbe052889fe7c1b2ed966fcb3a77328964ef108" + integrity sha512-5LC9SOxjSc2HF6vO2CyuTDNivEdoz2IvyJJGj6X8DJ0eFyfszE0QiEd+iXmBvUP3WHxSjFH/vIsA0EN00cgr8w== + ms@2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8" @@ -3219,14 +3231,21 @@ obsidian-daily-notes-interface@0.8.4: obsidian obsidianmd/obsidian-api#master tslib "2.1.0" -obsidian-daily-notes-interface@0.9.0: - version "0.9.0" - resolved "https://registry.yarnpkg.com/obsidian-daily-notes-interface/-/obsidian-daily-notes-interface-0.9.0.tgz#6a8996917899097c99ed62264a28e231a297d3c6" - integrity sha512-vzqOLgjTJi+jeT654eRgyEA2PfqeNI23Fe955VwqnRpAjkarr6qcllpC9cs1XBgpjmRm/XRIqXFdLsO+1z1RGg== +obsidian-daily-notes-interface@0.9.4: + version "0.9.4" + resolved "https://registry.yarnpkg.com/obsidian-daily-notes-interface/-/obsidian-daily-notes-interface-0.9.4.tgz#df085c5aa4c8c2b2b810185d4d9dc24344cb7604" + integrity sha512-PILoRtZUB5wEeGnDQAPMlkVlXwDYoxkLR8Wl4STU2zLNwhcq9kKvQexiXi7sfjGlpTnL+LeAOfEVWyeVndneKg== dependencies: obsidian obsidianmd/obsidian-api#master tslib "2.1.0" +"obsidian@github:obsidianmd/obsidian-api#master": + version "1.5.7" + resolved "https://codeload.github.com/obsidianmd/obsidian-api/tar.gz/8b2eda0f24285636c8aa116972643e5233a23dc1" + dependencies: + "@types/codemirror" "5.60.8" + moment "2.29.4" + obsidian@obsidianmd/obsidian-api#master: version "0.11.11" resolved "https://codeload.github.com/obsidianmd/obsidian-api/tar.gz/dbfa19ad7aa6557f0ecff962065c3f540bc77e27"