From 891041c9653ae3f31cbe0b01963f3f92fe089568 Mon Sep 17 00:00:00 2001 From: Evan Fiordeliso Date: Sat, 12 Jul 2025 16:43:18 -0400 Subject: [PATCH] Add A to Z Challenge --- manifest.json | 2 +- package.json | 2 +- src/main.ts | 2 + src/ui/code-blocks/AToZChallengeCodeBlock.ts | 26 +++ .../AToZChallengeCodeBlockView.svelte | 194 ++++++++++++++++++ .../code-blocks/ReadingCalendarCodeBlock.ts | 2 +- .../ReadingCalendarCodeBlockView.svelte | 4 +- src/ui/code-blocks/ReadingLogCodeBlock.ts | 2 +- src/ui/code-blocks/ReadingStatsCodeBlock.ts | 2 +- src/ui/code-blocks/ShelfCodeBlockView.svelte | 5 +- .../ReadingLogEntryEditModalView.svelte | 4 +- src/ui/stores/date-filter.svelte.ts | 47 ++++- src/ui/stores/metadata.svelte.ts | 18 +- src/ui/stores/reading-log.svelte.ts | 2 +- versions.json | 3 +- 15 files changed, 297 insertions(+), 18 deletions(-) create mode 100644 src/ui/code-blocks/AToZChallengeCodeBlock.ts create mode 100644 src/ui/code-blocks/AToZChallengeCodeBlockView.svelte diff --git a/manifest.json b/manifest.json index 08d3ec9..2c810d7 100644 --- a/manifest.json +++ b/manifest.json @@ -1,7 +1,7 @@ { "id": "obsidian-book-tracker", "name": "Book Tracker", - "version": "1.1.0", + "version": "1.2.0", "minAppVersion": "0.15.0", "description": "Simplifies tracking your reading progress and managing your book collection in Obsidian.", "author": "FiFiTiDo", diff --git a/package.json b/package.json index cbde538..7ecc852 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "obsidian-book-tracker", - "version": "1.1.0", + "version": "1.2.0", "description": "Simplifies tracking your reading progress and managing your book collection in Obsidian.", "main": "main.js", "scripts": { diff --git a/src/main.ts b/src/main.ts index e83485c..6212094 100644 --- a/src/main.ts +++ b/src/main.ts @@ -25,6 +25,7 @@ import { CreateBookFromGoodreadsUrlCommand } from "@commands/CreateBookFromGoodr import { registerShelfCodeBlockProcessor } from "@ui/code-blocks/ShelfCodeBlock"; import { ReloadReadingLogCommand } from "@commands/ReloadReadingLogCommand"; import { registerReadingCalendarCodeBlockProcessor } from "@ui/code-blocks/ReadingCalendarCodeBlock"; +import { registerAToZChallengeCodeBlockProcessor } from "@ui/code-blocks/AToZChallengeCodeBlock"; export default class BookTrackerPlugin extends Plugin { public settings: BookTrackerPluginSettings; @@ -91,6 +92,7 @@ export default class BookTrackerPlugin extends Plugin { registerReadingStatsCodeBlockProcessor(this); registerShelfCodeBlockProcessor(this); registerReadingCalendarCodeBlockProcessor(this); + registerAToZChallengeCodeBlockProcessor(this); } onunload() {} diff --git a/src/ui/code-blocks/AToZChallengeCodeBlock.ts b/src/ui/code-blocks/AToZChallengeCodeBlock.ts new file mode 100644 index 0000000..9083b7e --- /dev/null +++ b/src/ui/code-blocks/AToZChallengeCodeBlock.ts @@ -0,0 +1,26 @@ +import { registerCodeBlockRenderer } from "."; +import { SvelteCodeBlockRenderer } from "./SvelteCodeBlockRenderer"; +import AToZChallengeCodeBlockView from "./AToZChallengeCodeBlockView.svelte"; +import type BookTrackerPlugin from "@src/main"; +import z from "zod/v4"; + +export function registerAToZChallengeCodeBlockProcessor( + plugin: BookTrackerPlugin +): void { + registerCodeBlockRenderer( + plugin, + "a-to-z-challenge", + (source, el) => + new SvelteCodeBlockRenderer( + AToZChallengeCodeBlockView, + plugin, + source, + el + ) + ); +} + +export const AToZChallengeSettingsSchema = z.object({ + coverProperty: z.string(), + titleProperty: z.string(), +}); diff --git a/src/ui/code-blocks/AToZChallengeCodeBlockView.svelte b/src/ui/code-blocks/AToZChallengeCodeBlockView.svelte new file mode 100644 index 0000000..404495a --- /dev/null +++ b/src/ui/code-blocks/AToZChallengeCodeBlockView.svelte @@ -0,0 +1,194 @@ + + +
+
+ +

Started: {startDate.format("YYYY-MM-DD")}

+

Ended: {endDate?.format("YYYY-MM-DD") ?? "N/A"}

+
+
+ {#each alphabet as letter} +
+ {#if items[letter]} + {@const item = items[letter]} + + {item.coverAlt} + + {:else} +
{letter}
+ {/if} +
+ {/each} +
+
+ + diff --git a/src/ui/code-blocks/ReadingCalendarCodeBlock.ts b/src/ui/code-blocks/ReadingCalendarCodeBlock.ts index 41a800a..76daedb 100644 --- a/src/ui/code-blocks/ReadingCalendarCodeBlock.ts +++ b/src/ui/code-blocks/ReadingCalendarCodeBlock.ts @@ -9,7 +9,7 @@ export function registerReadingCalendarCodeBlockProcessor( ): void { registerCodeBlockRenderer( plugin, - "readingcalendar", + "reading-calendar", (source, el) => new SvelteCodeBlockRenderer( ReadingCalendarCodeBlockView, diff --git a/src/ui/code-blocks/ReadingCalendarCodeBlockView.svelte b/src/ui/code-blocks/ReadingCalendarCodeBlockView.svelte index 2593779..fbfe071 100644 --- a/src/ui/code-blocks/ReadingCalendarCodeBlockView.svelte +++ b/src/ui/code-blocks/ReadingCalendarCodeBlockView.svelte @@ -24,7 +24,9 @@ const settingsStore = createSettings(plugin); setSettingsContext(settingsStore); - const metadataStore = createMetadata(plugin, null); + const metadataStore = createMetadata(plugin, { + statusFilter: null, + }); setMetadataContext(metadataStore); const readingLog = createReadingLog(plugin.readingLog); diff --git a/src/ui/code-blocks/ReadingLogCodeBlock.ts b/src/ui/code-blocks/ReadingLogCodeBlock.ts index 710834f..b0b215e 100644 --- a/src/ui/code-blocks/ReadingLogCodeBlock.ts +++ b/src/ui/code-blocks/ReadingLogCodeBlock.ts @@ -8,7 +8,7 @@ export function registerReadingLogCodeBlockProcessor( ): void { registerCodeBlockRenderer( plugin, - "readinglog", + "reading-log", (source, el) => new SvelteCodeBlockRenderer( ReadingLogCodeBlockView, diff --git a/src/ui/code-blocks/ReadingStatsCodeBlock.ts b/src/ui/code-blocks/ReadingStatsCodeBlock.ts index 939de04..3e62830 100644 --- a/src/ui/code-blocks/ReadingStatsCodeBlock.ts +++ b/src/ui/code-blocks/ReadingStatsCodeBlock.ts @@ -10,7 +10,7 @@ export function registerReadingStatsCodeBlockProcessor( ): void { registerCodeBlockRenderer( plugin, - "readingstats", + "reading-stats", (source, el) => new SvelteCodeBlockRenderer( ReadingStatsCodeBlockView, diff --git a/src/ui/code-blocks/ShelfCodeBlockView.svelte b/src/ui/code-blocks/ShelfCodeBlockView.svelte index f275d02..0b6e08a 100644 --- a/src/ui/code-blocks/ShelfCodeBlockView.svelte +++ b/src/ui/code-blocks/ShelfCodeBlockView.svelte @@ -26,7 +26,10 @@ const settingsStore = createSettings(plugin); setSettingsContext(settingsStore); - const metadataStore = createMetadata(plugin, settings.statusFilter, true); + const metadataStore = createMetadata(plugin, { + statusFilter: settings.statusFilter, + initialMonth: true, + }); setMetadataContext(metadataStore); let view = $state(settings.defaultView); diff --git a/src/ui/modals/ReadingLogEntryEditModalView.svelte b/src/ui/modals/ReadingLogEntryEditModalView.svelte index 6b8adf5..8f4e824 100644 --- a/src/ui/modals/ReadingLogEntryEditModalView.svelte +++ b/src/ui/modals/ReadingLogEntryEditModalView.svelte @@ -23,7 +23,9 @@ const settingsStore = createSettings(plugin); setSettingsContext(settingsStore); - const metadataStore = createMetadata(plugin, null); + const metadataStore = createMetadata(plugin, { + statusFilter: null, + }); let editMode = $derived(entry !== undefined); let book = $state(entry?.book ?? ""); diff --git a/src/ui/stores/date-filter.svelte.ts b/src/ui/stores/date-filter.svelte.ts index 51cd0da..b779420 100644 --- a/src/ui/stores/date-filter.svelte.ts +++ b/src/ui/stores/date-filter.svelte.ts @@ -9,17 +9,56 @@ export interface DateFilterStore { get filterMonths(): { label: string; value: number }[]; } +export interface DateFilterStoreOptions { + /** + * If true, the filter month will be set to the current month + * If a number is provided, the filter month will be set to the provided month + * + * @default false + */ + initialMonth?: boolean | number; + + /** + * If true, the filter year will be set to the current year + * If a number is provided, the filter year will be set to the provided year + * + * @default true + */ + initialYear?: boolean | number; + + /** + * If true, the month filter will be disabled + * + * @default false + */ + disableMonthFilter?: boolean; +} + export function createDateFilter( data: () => T[], selector: (item: T) => Moment, - initialMonth?: boolean + { + initialMonth = false, + initialYear = true, + disableMonthFilter = false, + }: DateFilterStoreOptions ): DateFilterStore & { filteredData: T[]; } { const today = new Date(); - let filterYear: number | typeof ALL_TIME = $state(today.getFullYear()); + let filterYear: number | typeof ALL_TIME = $state( + typeof initialYear === "number" + ? initialYear + : initialYear + ? today.getFullYear() + : ALL_TIME + ); let filterMonth: number | typeof ALL_TIME = $state( - initialMonth ? today.getMonth() + 1 : ALL_TIME + typeof initialMonth === "number" + ? initialMonth + : initialMonth + ? today.getMonth() + 1 + : ALL_TIME ); const filteredData = $derived.by(() => { return data() @@ -30,7 +69,7 @@ export function createDateFilter( return false; } - if (filterMonth !== ALL_TIME) { + if (filterMonth !== ALL_TIME && !disableMonthFilter) { if (date.month() !== filterMonth - 1) { return false; } diff --git a/src/ui/stores/metadata.svelte.ts b/src/ui/stores/metadata.svelte.ts index 51c64f1..3fa0de4 100644 --- a/src/ui/stores/metadata.svelte.ts +++ b/src/ui/stores/metadata.svelte.ts @@ -7,7 +7,11 @@ import { setSettingsContext, } from "./settings.svelte"; import type BookTrackerPlugin from "@src/main"; -import { createDateFilter, type DateFilterStore } from "./date-filter.svelte"; +import { + createDateFilter, + type DateFilterStore, + type DateFilterStoreOptions, +} from "./date-filter.svelte"; import type { ReadingState } from "@src/types"; import type { BookTrackerPluginSettings } from "@ui/settings"; @@ -49,10 +53,16 @@ function getMetadata( return metadata; } +interface MetadataStoreOptions extends DateFilterStoreOptions { + /** + * The reading state to filter by + */ + statusFilter?: ReadingState | null; +} + export function createMetadata( plugin: BookTrackerPlugin, - statusFilter: ReadingState | null = STATUS_READ, - initialMonth?: boolean + { statusFilter = STATUS_READ, ...dateFilterOpts }: MetadataStoreOptions = {} ): MetadataStore { let settingsStore = getSettingsContext(); if (!settingsStore) { @@ -97,7 +107,7 @@ export function createMetadata( f.frontmatter[settingsStore.settings.endDateProperty] ); }, - initialMonth + dateFilterOpts ); return { diff --git a/src/ui/stores/reading-log.svelte.ts b/src/ui/stores/reading-log.svelte.ts index dc95da5..f5ed19a 100644 --- a/src/ui/stores/reading-log.svelte.ts +++ b/src/ui/stores/reading-log.svelte.ts @@ -18,7 +18,7 @@ export function createReadingLog(readingLog: ReadingLog): ReadingLogStore { const dateFilter = createDateFilter( () => entries, (entry) => entry.createdAt, - true + { initialMonth: true } ); async function addEntry(entry: ReadingLogEntry): Promise { diff --git a/versions.json b/versions.json index 908e85c..8846fba 100644 --- a/versions.json +++ b/versions.json @@ -1,4 +1,5 @@ { "1.0.0": "0.15.0", - "1.1.0": "0.15.0" + "1.1.0": "0.15.0", + "1.2.0": "0.15.0" } \ No newline at end of file