From bd2189088599ed3410bd12ae95ed1444b0f5f978 Mon Sep 17 00:00:00 2001 From: Evan Fiordeliso Date: Sun, 29 Jun 2025 18:41:54 -0400 Subject: [PATCH] Add entry create button --- package.json | 1 + pnpm-lock.yaml | 14 ++++ src/components/ReadingLogEntryEditor.svelte | 54 ++++++++++--- src/components/ReadingLogViewer.svelte | 86 +++++++++++++++------ src/settings/suggesters/book.ts | 34 ++++++++ src/utils/storage.ts | 6 +- src/views/reading-log-entry-edit-modal.ts | 1 + src/views/reading-log-new-entry-modal.ts | 30 +++++++ 8 files changed, 192 insertions(+), 34 deletions(-) create mode 100644 src/settings/suggesters/book.ts create mode 100644 src/views/reading-log-new-entry-modal.ts diff --git a/package.json b/package.json index cc3bed0..3a7e3c4 100644 --- a/package.json +++ b/package.json @@ -30,6 +30,7 @@ "sass": "^1.89.2", "svelte": "^5.34.8", "svelte-check": "^4.2.2", + "svelte-popperjs": "^1.3.2", "svelte-preprocess": "^6.0.3", "tslib": "2.4.0", "typescript": "5.0.4" diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 4e8decd..f9544d6 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -59,6 +59,9 @@ importers: svelte-check: specifier: ^4.2.2 version: 4.2.2(picomatch@4.0.2)(svelte@5.34.8)(typescript@5.0.4) + svelte-popperjs: + specifier: ^1.3.2 + version: 1.3.2(@popperjs/core@2.11.8)(svelte@5.34.8) svelte-preprocess: specifier: ^6.0.3 version: 6.0.3(postcss@8.5.6)(sass@1.89.2)(svelte@5.34.8)(typescript@5.0.4) @@ -1444,6 +1447,12 @@ packages: svelte: ^4.0.0 || ^5.0.0-next.0 typescript: '>=5.0.0' + svelte-popperjs@1.3.2: + resolution: {integrity: sha512-fwrErlkvngL876WXRnL3OLlfk/n9YkZwwLxuKRpZOYCJLt1zrwhoKTXS+/sRgDveD/zd6GQ35hV89EOip+NBGA==} + peerDependencies: + '@popperjs/core': '>=2' + svelte: '>=3' + svelte-preprocess@6.0.3: resolution: {integrity: sha512-PLG2k05qHdhmRG7zR/dyo5qKvakhm8IJ+hD2eFRQmMLHp7X3eJnjeupUtvuRpbNiF31RjVw45W+abDwHEmP5OA==} engines: {node: '>= 18.0.0'} @@ -3050,6 +3059,11 @@ snapshots: transitivePeerDependencies: - picomatch + svelte-popperjs@1.3.2(@popperjs/core@2.11.8)(svelte@5.34.8): + dependencies: + '@popperjs/core': 2.11.8 + svelte: 5.34.8 + svelte-preprocess@6.0.3(postcss@8.5.6)(sass@1.89.2)(svelte@5.34.8)(typescript@5.0.4): dependencies: svelte: 5.34.8 diff --git a/src/components/ReadingLogEntryEditor.svelte b/src/components/ReadingLogEntryEditor.svelte index 922bf2d..e960b70 100644 --- a/src/components/ReadingLogEntryEditor.svelte +++ b/src/components/ReadingLogEntryEditor.svelte @@ -1,15 +1,21 @@
-

Edit Reading Log Entry

+

{editMode ? "Edit" : "Create"} Reading Log Entry

+ + + +
@@ -95,7 +123,13 @@ .fields { display: grid; grid-template-columns: max-content 1fr; - gap: var(--size-4-2); + gap: var(--size-4-4); + align-items: center; + + input:disabled { + color: var(--text-muted); + cursor: not-allowed; + } } } } diff --git a/src/components/ReadingLogViewer.svelte b/src/components/ReadingLogViewer.svelte index 289efb0..e6a1ec1 100644 --- a/src/components/ReadingLogViewer.svelte +++ b/src/components/ReadingLogViewer.svelte @@ -2,8 +2,9 @@ import type { ReadingLog } from "@utils/storage"; import type { ReadingLogEntry } from "@src/types"; import type { App } from "obsidian"; - import { Edit, Trash } from "lucide-svelte"; + import { Edit, Trash, Plus } from "lucide-svelte"; import { ReadingLogEntryEditModal } from "@views/reading-log-entry-edit-modal"; + import { ReadingLogNewEntryModal } from "@views/reading-log-new-entry-modal"; const ALL_TIME = "ALL_TIME"; @@ -68,6 +69,16 @@ ), ); + function createEntry() { + const modal = new ReadingLogNewEntryModal(app); + modal.once("submit", async (event) => { + modal.close(); + await readingLog.addRawEntry(event.entry); + reload(); + }); + modal.open(); + } + function editEntry(i: number, entry: ReadingLogEntry) { const modal = new ReadingLogEntryEditModal(app, entry); modal.once("submit", async (event) => { @@ -86,28 +97,36 @@
-
- - +
+
+ + +
+
+ +
@@ -155,6 +174,27 @@ @use "../styles/utils"; .obt-reading-log-viewer { + .controls { + display: grid; + grid-template-columns: 1fr 1fr; + align-items: center; + + .right { + text-align: right; + + button.create-entry { + display: inline-flex; + gap: var(--size-2-2); + align-items: center; + + :global(svg) { + width: var(--icon-s); + height: var(--icon-s); + } + } + } + } + .year-filter:has(> option.all-time:checked) + .month-filter { display: none; } diff --git a/src/settings/suggesters/book.ts b/src/settings/suggesters/book.ts new file mode 100644 index 0000000..6e2d8c3 --- /dev/null +++ b/src/settings/suggesters/book.ts @@ -0,0 +1,34 @@ +// Credits go to Liam's Periodic Notes Plugin: https://github.com/liamcain/obsidian-periodic-notes + +import { TAbstractFile, TFile } from "obsidian"; +import { TextInputSuggest } from "./core"; + +export class BookSuggest extends TextInputSuggest { + getSuggestions(inputStr: string): TFile[] { + const abstractFiles = this.app.vault.getAllLoadedFiles(); + const files: TFile[] = []; + const lowerCaseInputStr = inputStr.toLowerCase(); + + abstractFiles.forEach((file: TAbstractFile) => { + if ( + file instanceof TFile && + file.extension === "md" && + file.basename.toLowerCase().contains(lowerCaseInputStr) + ) { + files.push(file); + } + }); + + return files; + } + + renderSuggestion(file: TFile, el: HTMLElement): void { + el.setText(file.basename); + } + + selectSuggestion(file: TFile): void { + this.inputEl.value = file.basename; + this.inputEl.trigger("input"); + this.close(); + } +} diff --git a/src/utils/storage.ts b/src/utils/storage.ts index 1a813e7..0908e50 100644 --- a/src/utils/storage.ts +++ b/src/utils/storage.ts @@ -93,7 +93,11 @@ export class ReadingLog { createdAt: new Date(), }; - this.entries.push(newEntry); + await this.addRawEntry(newEntry); + } + + public async addRawEntry(entry: ReadingLogEntry) { + this.entries.push(entry); await this.storeEntries(); } diff --git a/src/views/reading-log-entry-edit-modal.ts b/src/views/reading-log-entry-edit-modal.ts index 932b846..beb9533 100644 --- a/src/views/reading-log-entry-edit-modal.ts +++ b/src/views/reading-log-entry-edit-modal.ts @@ -21,6 +21,7 @@ export class ReadingLogEntryEditModal extends EventEmitter< constructor(app: App, entry: ReadingLogEntry) { super(app, ReadingLogEntryEditor, { props: { + app, entry, onSubmit: (entry: ReadingLogEntry) => this.emit("submit", new SubmitEvent(entry)), diff --git a/src/views/reading-log-new-entry-modal.ts b/src/views/reading-log-new-entry-modal.ts new file mode 100644 index 0000000..2971fbd --- /dev/null +++ b/src/views/reading-log-new-entry-modal.ts @@ -0,0 +1,30 @@ +import ReadingLogEntryEditor from "@components/ReadingLogEntryEditor.svelte"; +import type { ReadingLogEntry } from "@src/types"; +import { Event, EventEmitter } from "@utils/event"; +import { App } from "obsidian"; +import { SvelteModal } from "./svelte-modal"; + +export class SubmitEvent extends Event { + constructor(public readonly entry: ReadingLogEntry) { + super(); + } +} + +interface ReadingLogNewEntryModalEventMap { + submit: SubmitEvent; +} + +export class ReadingLogNewEntryModal extends EventEmitter< + ReadingLogNewEntryModalEventMap, + typeof SvelteModal +>(SvelteModal) { + constructor(app: App) { + super(app, ReadingLogEntryEditor, { + props: { + app, + onSubmit: (entry: ReadingLogEntry) => + this.emit("submit", new SubmitEvent(entry)), + }, + }); + } +}