From fbeee9ad8d0d4b609f300726ba3c8087863d709a Mon Sep 17 00:00:00 2001 From: Sergii Kostyrko Date: Mon, 26 Aug 2024 14:32:04 +0300 Subject: [PATCH] feat: add indexing --- src/components/DatePicker.vue | 4 +- src/components/obsidian/ObsidianButton.vue | 8 ++- .../obsidian/ObsidianNumberInput.vue | 8 +++ src/defaults.ts | 3 +- src/journals/journal.ts | 50 ++++++++++++++++++- src/journals/journals-index.ts | 6 +-- src/settings/JournalSettingsEdit.vue | 46 +++++++++++++++++ src/types/settings.types.ts | 3 +- 8 files changed, 119 insertions(+), 9 deletions(-) diff --git a/src/components/DatePicker.vue b/src/components/DatePicker.vue index c25b368..e0857f1 100644 --- a/src/components/DatePicker.vue +++ b/src/components/DatePicker.vue @@ -11,10 +11,12 @@ const props = withDefaults( placeholder?: string; previewFormat?: string; disabled?: boolean; + tooltip?: string; }>(), { placeholder: "Pick a date", previewFormat: "YYYY-MM-DD", + tooltip: "Pick a date", }, ); @@ -48,7 +50,7 @@ function openPickerModal() { diff --git a/src/components/obsidian/ObsidianButton.vue b/src/components/obsidian/ObsidianButton.vue index 3a52b46..aa914ce 100644 --- a/src/components/obsidian/ObsidianButton.vue +++ b/src/components/obsidian/ObsidianButton.vue @@ -4,11 +4,17 @@ defineProps<{ cta?: boolean; warning?: boolean; type?: "button" | "submit" | "reset"; + tooltip?: string; }>(); diff --git a/src/components/obsidian/ObsidianNumberInput.vue b/src/components/obsidian/ObsidianNumberInput.vue index 30fbfe4..242daf2 100644 --- a/src/components/obsidian/ObsidianNumberInput.vue +++ b/src/components/obsidian/ObsidianNumberInput.vue @@ -4,6 +4,7 @@ defineProps<{ disabled?: boolean; min?: number; max?: number; + narrow?: boolean; }>(); const model = defineModel(); @@ -13,6 +14,7 @@ const model = defineModel(); (); spellcheck="false" /> + + diff --git a/src/defaults.ts b/src/defaults.ts index 5a40f2d..73cf90f 100644 --- a/src/defaults.ts +++ b/src/defaults.ts @@ -44,8 +44,9 @@ export const defaultJournalSettings: JournalSettings = { enabled: false, anchorDate: "", anchorIndex: 1, + allowBefore: false, type: "increment", - resetAfter: 0, + resetAfter: 2, secondary: false, secondaryAncorIndex: 1, }, diff --git a/src/journals/journal.ts b/src/journals/journal.ts index e2af13a..d234028 100644 --- a/src/journals/journal.ts +++ b/src/journals/journal.ts @@ -71,7 +71,7 @@ export class Journal { return await this.#buildMetadata(interval); } - async next(metadata: JournalMetadata, existing = false): Promise { + async next(metadata: JournalInterval, existing = false): Promise { if (existing) { const nextExstingMetadata = plugin$.value.index.findNext(this.id, metadata); if (nextExstingMetadata) return nextExstingMetadata; @@ -84,7 +84,7 @@ export class Journal { return await this.#buildMetadata(interval); } - async previous(metadata: JournalMetadata, existing = false): Promise { + async previous(metadata: JournalInterval, existing = false): Promise { if (existing) { const previousExstingMetadata = plugin$.value.index.findPrevious(this.id, metadata); if (previousExstingMetadata) return previousExstingMetadata; @@ -198,6 +198,7 @@ export class Journal { id: this.id, start_date: interval.start_date, end_date: interval.start_date, + index: await this.#resolveIndex(interval), }; return metadata; } @@ -250,4 +251,49 @@ export class Journal { return true; } + + async #resolveIndex(interval: JournalInterval): Promise { + if (!this.#config.value.index.enabled) return undefined; + if (!this.#config.value.index.anchorDate || !this.#config.value.index.anchorIndex) return undefined; + const before = await this.previous(interval, true); + if (before && before.index) { + const repeats = this.#intervalResolver.countRepeats(before.end_date, interval.start_date); + let index = before.index + repeats; + if (this.#config.value.index.type === "reset_after") { + index %= this.#config.value.index.resetAfter; + } + return index; + } + const after = await this.next(interval, true); + if (after && after.index) { + const repeats = this.#intervalResolver.countRepeats(interval.end_date, after.start_date); + let index = after.index - repeats; + if (this.#config.value.index.type === "reset_after" && index < 0) { + index *= -1; + } + return index; + } + const anchor = date(this.#config.value.index.anchorDate); + if (!anchor.isValid()) return undefined; + if ( + anchor.isAfter(interval.start_date) && + this.#config.value.index.type === "increment" && + !this.#config.value.index.allowBefore + ) + return undefined; + if (anchor.isBefore(interval.start_date)) { + const repeats = this.#intervalResolver.countRepeats(this.#config.value.index.anchorDate, interval.start_date); + let index = this.#config.value.index.anchorIndex + repeats; + if (this.#config.value.index.type === "reset_after") { + index %= this.#config.value.index.resetAfter; + } + return index; + } + const repeats = this.#intervalResolver.countRepeats(interval.end_date, this.#config.value.index.anchorDate); + let index = this.#config.value.index.anchorIndex - repeats; + if (this.#config.value.index.type === "reset_after" && index < 0) { + index *= -1; + } + return index; + } } diff --git a/src/journals/journals-index.ts b/src/journals/journals-index.ts index 9d85128..de53c84 100644 --- a/src/journals/journals-index.ts +++ b/src/journals/journals-index.ts @@ -2,7 +2,7 @@ import { Component, type TAbstractFile, TFile, moment, type FrontMatterCache } f import { app$ } from "../stores/obsidian.store"; import { computed, ref, type ComputedRef } from "vue"; import IntervalTree from "@flatten-js/interval-tree"; -import type { JournalMetadata } from "../types/journal.types"; +import type { JournalInterval, JournalMetadata } from "../types/journal.types"; import { FRONTMATTER_END_DATE_KEY, FRONTMATTER_ID_KEY, @@ -38,13 +38,13 @@ export class JournalsIndex extends Component { return list.find((entry) => entry.id === journalId); } - findNext(journalId: string, metadata: JournalMetadata): JournalMetadata | null { + findNext(journalId: string, metadata: JournalInterval): JournalMetadata | null { const date = moment(metadata.end_date).add(1, "day").toDate().getTime(); const list = this.#intervalTree.search([date, Infinity]); return list.find((entry) => entry.id === journalId); } - findPrevious(journalId: string, metadata: JournalMetadata): JournalMetadata | null { + findPrevious(journalId: string, metadata: JournalInterval): JournalMetadata | null { const date = moment(metadata.start_date).subtract(1, "day").toDate().getTime(); const list = this.#intervalTree.search([0, date]); return list.findLast((entry) => entry.id === journalId); diff --git a/src/settings/JournalSettingsEdit.vue b/src/settings/JournalSettingsEdit.vue index 99909a2..c562d61 100644 --- a/src/settings/JournalSettingsEdit.vue +++ b/src/settings/JournalSettingsEdit.vue @@ -10,6 +10,7 @@ import ObsidianNumberInput from "../components/obsidian/ObsidianNumberInput.vue" import ObsidianIconButton from "../components/obsidian/ObsidianIconButton.vue"; import ObsidianButton from "../components/obsidian/ObsidianButton.vue"; import ObsidianDropdown from "../components/obsidian/ObsidianDropdown.vue"; +import ObsidianToggle from "../components/obsidian/ObsidianToggle.vue"; import FolderInput from "../components/FolderInput.vue"; import DateFormatPreview from "../components/DateFormatPreview.vue"; import VariableReferenceHint from "../components/VariableReferenceHint.vue"; @@ -51,6 +52,14 @@ function deleteCommand(index: number): void { pluginSettings$.value.showReloadHint = true; } +watch( + () => journal.value.start, + (value) => { + if (value) { + journal.value.index.anchorDate = value; + } + }, +); watch( () => journal.value.end.type, () => { @@ -102,6 +111,43 @@ watch( + + + + + + + diff --git a/src/types/settings.types.ts b/src/types/settings.types.ts index a580ab3..159fa07 100644 --- a/src/types/settings.types.ts +++ b/src/types/settings.types.ts @@ -98,7 +98,8 @@ export interface JournalSettings { enabled: boolean; anchorDate: string; anchorIndex: number; - type: "increment" | "year_reset" | "reset_after"; + allowBefore: boolean; + type: "increment" | "reset_after"; resetAfter: number; secondary: boolean; secondaryAncorIndex: number;