generated from tpl/obsidian-sample-plugin
			Use reading log for books and pages chart when filtering by month
This commit is contained in:
		
							parent
							
								
									d9cfb3df36
								
							
						
					
					
						commit
						31cfa881c7
					
				| 
						 | 
					@ -11,7 +11,7 @@
 | 
				
			||||||
		plugin: BookTrackerPlugin;
 | 
							plugin: BookTrackerPlugin;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	let { plugin }: Props = $props();
 | 
						const { plugin }: Props = $props();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	function bookUri(book: string) {
 | 
						function bookUri(book: string) {
 | 
				
			||||||
		const v = encodeURIComponent(plugin.app.vault.getName());
 | 
							const v = encodeURIComponent(plugin.app.vault.getName());
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -23,20 +23,32 @@
 | 
				
			||||||
	import type BookTrackerPlugin from "@src/main";
 | 
						import type BookTrackerPlugin from "@src/main";
 | 
				
			||||||
	import BookCountStat from "@ui/components/stats/BookCountStat.svelte";
 | 
						import BookCountStat from "@ui/components/stats/BookCountStat.svelte";
 | 
				
			||||||
	import { ALL_TIME } from "@ui/stores/date-filter.svelte";
 | 
						import { ALL_TIME } from "@ui/stores/date-filter.svelte";
 | 
				
			||||||
 | 
						import {
 | 
				
			||||||
 | 
							createReadingLog,
 | 
				
			||||||
 | 
							setReadingLogContext,
 | 
				
			||||||
 | 
						} from "@ui/stores/reading-log.svelte";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	interface Props {
 | 
						interface Props {
 | 
				
			||||||
		plugin: BookTrackerPlugin;
 | 
							plugin: BookTrackerPlugin;
 | 
				
			||||||
		source: string;
 | 
							source: string;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	let { plugin, source }: Props = $props();
 | 
						const { plugin, source }: Props = $props();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	let settingsStore = createSettings(plugin);
 | 
						const settingsStore = createSettings(plugin);
 | 
				
			||||||
	setSettingsContext(settingsStore);
 | 
						setSettingsContext(settingsStore);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	let metadataStore = createMetadata(plugin);
 | 
						const metadataStore = createMetadata(plugin);
 | 
				
			||||||
	setMetadataContext(metadataStore);
 | 
						setMetadataContext(metadataStore);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						const readingLogStore = createReadingLog(plugin.readingLog);
 | 
				
			||||||
 | 
						setReadingLogContext(readingLogStore);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						$effect(() => {
 | 
				
			||||||
 | 
							readingLogStore.filterYear = metadataStore.filterYear;
 | 
				
			||||||
 | 
							readingLogStore.filterMonth = metadataStore.filterMonth;
 | 
				
			||||||
 | 
						});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	let sections = $state<ReadingStatsSection[]>([]);
 | 
						let sections = $state<ReadingStatsSection[]>([]);
 | 
				
			||||||
	let error = $state<string | null>(null);
 | 
						let error = $state<string | null>(null);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -68,7 +80,10 @@
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	});
 | 
						});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	onDestroy(() => metadataStore.destroy());
 | 
						onDestroy(() => {
 | 
				
			||||||
 | 
							metadataStore.destroy();
 | 
				
			||||||
 | 
							readingLogStore.destroy();
 | 
				
			||||||
 | 
						});
 | 
				
			||||||
</script>
 | 
					</script>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
<div class="obt-reading-stats">
 | 
					<div class="obt-reading-stats">
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -15,7 +15,7 @@
 | 
				
			||||||
		color?: "rainbow" | ColorName;
 | 
							color?: "rainbow" | ColorName;
 | 
				
			||||||
	};
 | 
						};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	let {
 | 
						const {
 | 
				
			||||||
		property,
 | 
							property,
 | 
				
			||||||
		horizontal,
 | 
							horizontal,
 | 
				
			||||||
		sortByLabel = false,
 | 
							sortByLabel = false,
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -2,28 +2,46 @@
 | 
				
			||||||
	import { chart } from "@ui/directives/chart";
 | 
						import { chart } from "@ui/directives/chart";
 | 
				
			||||||
	import { ALL_TIME } from "@ui/stores/date-filter.svelte";
 | 
						import { ALL_TIME } from "@ui/stores/date-filter.svelte";
 | 
				
			||||||
	import { getMetadataContext } from "@ui/stores/metadata.svelte";
 | 
						import { getMetadataContext } from "@ui/stores/metadata.svelte";
 | 
				
			||||||
 | 
						import { getReadingLogContext } from "@ui/stores/reading-log.svelte";
 | 
				
			||||||
	import { getSettingsContext } from "@ui/stores/settings.svelte";
 | 
						import { getSettingsContext } from "@ui/stores/settings.svelte";
 | 
				
			||||||
	import { Color } from "@utils/color";
 | 
						import { Color } from "@utils/color";
 | 
				
			||||||
	import type { ChartConfiguration } from "chart.js";
 | 
						import type { ChartConfiguration } from "chart.js";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	const settings = getSettingsContext().settings;
 | 
						const settingsStore = getSettingsContext();
 | 
				
			||||||
	const store = getMetadataContext();
 | 
						const store = getMetadataContext();
 | 
				
			||||||
	const config = $derived.by(() => {
 | 
						const readingLog = getReadingLogContext();
 | 
				
			||||||
		const items = store.metadata.map((f) => ({
 | 
					 | 
				
			||||||
			pageCount: f.frontmatter[settings.pageCountProperty],
 | 
					 | 
				
			||||||
			date: f.frontmatter[settings.endDateProperty],
 | 
					 | 
				
			||||||
		}));
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						const isMonthly = $derived(
 | 
				
			||||||
 | 
							store.filterYear !== ALL_TIME && store.filterMonth !== ALL_TIME,
 | 
				
			||||||
 | 
						);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						const items = $derived(
 | 
				
			||||||
 | 
							isMonthly
 | 
				
			||||||
 | 
								? readingLog.entries.map((entry) => ({
 | 
				
			||||||
 | 
										pageCount: entry.pagesRead,
 | 
				
			||||||
 | 
										date: entry.createdAt,
 | 
				
			||||||
 | 
									}))
 | 
				
			||||||
 | 
								: store.metadata.map((f) => ({
 | 
				
			||||||
 | 
										pageCount:
 | 
				
			||||||
 | 
											f.frontmatter[settingsStore.settings.pageCountProperty],
 | 
				
			||||||
 | 
										// @ts-expect-error Moment is provided by Obsidian
 | 
				
			||||||
 | 
										date: moment(
 | 
				
			||||||
 | 
											f.frontmatter[settingsStore.settings.endDateProperty],
 | 
				
			||||||
 | 
										),
 | 
				
			||||||
 | 
									})),
 | 
				
			||||||
 | 
						);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						const config = $derived.by(() => {
 | 
				
			||||||
		const books = new Map<number, number>();
 | 
							const books = new Map<number, number>();
 | 
				
			||||||
		const pages = new Map<number, number>();
 | 
							const pages = new Map<number, number>();
 | 
				
			||||||
		for (const item of items) {
 | 
							for (const item of items) {
 | 
				
			||||||
			// @ts-expect-error Moment is provided by Obsidian
 | 
					 | 
				
			||||||
			const date = moment(item.date);
 | 
					 | 
				
			||||||
			let key: number;
 | 
								let key: number;
 | 
				
			||||||
			if (store.filterYear === ALL_TIME) {
 | 
								if (store.filterYear === ALL_TIME) {
 | 
				
			||||||
				key = date.year();
 | 
									key = item.date.year();
 | 
				
			||||||
 | 
								} else if (store.filterMonth === ALL_TIME) {
 | 
				
			||||||
 | 
									key = item.date.month();
 | 
				
			||||||
			} else {
 | 
								} else {
 | 
				
			||||||
				key = date.month();
 | 
									key = item.date.date();
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			const pageCount = pages.get(key) ?? 0;
 | 
								const pageCount = pages.get(key) ?? 0;
 | 
				
			||||||
| 
						 | 
					@ -33,10 +51,26 @@
 | 
				
			||||||
			books.set(key, bookCount + 1);
 | 
								books.set(key, bookCount + 1);
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							console.log(pages);
 | 
				
			||||||
 | 
							if (isMonthly && typeof store.filterMonth === "number") {
 | 
				
			||||||
 | 
								// @ts-expect-error Moment is provided by Obsidian
 | 
				
			||||||
 | 
								const daysInMonth = moment()
 | 
				
			||||||
 | 
									.month(store.filterMonth - 1)
 | 
				
			||||||
 | 
									.daysInMonth();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								for (let i = 1; i <= daysInMonth; i++) {
 | 
				
			||||||
 | 
									if (!pages.has(i)) {
 | 
				
			||||||
 | 
										books.set(i, 0);
 | 
				
			||||||
 | 
										pages.set(i, 0);
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							console.log(pages);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		const labels = Array.from(books.keys())
 | 
							const labels = Array.from(books.keys())
 | 
				
			||||||
			.sort((a, b) => a - b)
 | 
								.sort((a, b) => a - b)
 | 
				
			||||||
			.map((key) =>
 | 
								.map((key) =>
 | 
				
			||||||
				store.filterYear === ALL_TIME
 | 
									store.filterYear === ALL_TIME || isMonthly
 | 
				
			||||||
					? key
 | 
										? key
 | 
				
			||||||
					: // @ts-expect-error Moment is provided by Obsidian
 | 
										: // @ts-expect-error Moment is provided by Obsidian
 | 
				
			||||||
						moment().month(key).format("MMM"),
 | 
											moment().month(key).format("MMM"),
 | 
				
			||||||
| 
						 | 
					@ -48,26 +82,30 @@
 | 
				
			||||||
			.sort((a, b) => a[0] - b[0])
 | 
								.sort((a, b) => a[0] - b[0])
 | 
				
			||||||
			.map((p) => p[1]);
 | 
								.map((p) => p[1]);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							let datasets = [
 | 
				
			||||||
 | 
								{
 | 
				
			||||||
 | 
									label: "Pages",
 | 
				
			||||||
 | 
									data: sortedPages,
 | 
				
			||||||
 | 
									borderColor: Color.fromName("blue").hex,
 | 
				
			||||||
 | 
									backgroundColor: Color.fromName("blue").alpha(0.5).rgba,
 | 
				
			||||||
 | 
									yAxisID: isMonthly ? "y" : "y1",
 | 
				
			||||||
 | 
								},
 | 
				
			||||||
 | 
							];
 | 
				
			||||||
 | 
							if (!isMonthly) {
 | 
				
			||||||
 | 
								datasets.push({
 | 
				
			||||||
 | 
									label: "Books",
 | 
				
			||||||
 | 
									data: sortedBooks,
 | 
				
			||||||
 | 
									borderColor: Color.fromName("red").hex,
 | 
				
			||||||
 | 
									backgroundColor: Color.fromName("red").alpha(0.5).rgba,
 | 
				
			||||||
 | 
									yAxisID: "y",
 | 
				
			||||||
 | 
								});
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		return {
 | 
							return {
 | 
				
			||||||
			type: "line",
 | 
								type: "line",
 | 
				
			||||||
			data: {
 | 
								data: {
 | 
				
			||||||
				labels,
 | 
									labels,
 | 
				
			||||||
				datasets: [
 | 
									datasets,
 | 
				
			||||||
					{
 | 
					 | 
				
			||||||
						label: "Books",
 | 
					 | 
				
			||||||
						data: sortedBooks,
 | 
					 | 
				
			||||||
						borderColor: Color.fromName("red").hex,
 | 
					 | 
				
			||||||
						backgroundColor: Color.fromName("red").alpha(0.5).rgba,
 | 
					 | 
				
			||||||
						yAxisID: "y",
 | 
					 | 
				
			||||||
					},
 | 
					 | 
				
			||||||
					{
 | 
					 | 
				
			||||||
						label: "Pages",
 | 
					 | 
				
			||||||
						data: sortedPages,
 | 
					 | 
				
			||||||
						borderColor: Color.fromName("blue").hex,
 | 
					 | 
				
			||||||
						backgroundColor: Color.fromName("blue").alpha(0.5).rgba,
 | 
					 | 
				
			||||||
						yAxisID: "y1",
 | 
					 | 
				
			||||||
					},
 | 
					 | 
				
			||||||
				],
 | 
					 | 
				
			||||||
			},
 | 
								},
 | 
				
			||||||
			options: {
 | 
								options: {
 | 
				
			||||||
				scales: {
 | 
									scales: {
 | 
				
			||||||
| 
						 | 
					@ -75,16 +113,13 @@
 | 
				
			||||||
						type: "linear",
 | 
											type: "linear",
 | 
				
			||||||
						display: true,
 | 
											display: true,
 | 
				
			||||||
						position: "left",
 | 
											position: "left",
 | 
				
			||||||
 | 
											ticks: { beginAtZero: true },
 | 
				
			||||||
					},
 | 
										},
 | 
				
			||||||
					y1: {
 | 
										y1: {
 | 
				
			||||||
						type: "linear",
 | 
											type: "linear",
 | 
				
			||||||
						display: true,
 | 
											display: !isMonthly,
 | 
				
			||||||
						position: "right",
 | 
											position: "right",
 | 
				
			||||||
 | 
											grid: { drawOnChartArea: false },
 | 
				
			||||||
						// grid line settings
 | 
					 | 
				
			||||||
						grid: {
 | 
					 | 
				
			||||||
							drawOnChartArea: false, // only want the grid lines for one axis to show up
 | 
					 | 
				
			||||||
						},
 | 
					 | 
				
			||||||
					},
 | 
										},
 | 
				
			||||||
				},
 | 
									},
 | 
				
			||||||
			},
 | 
								},
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -17,7 +17,7 @@
 | 
				
			||||||
		color?: PieChartColor;
 | 
							color?: PieChartColor;
 | 
				
			||||||
	};
 | 
						};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	let { property, groups, unit, unitPlural, responsive, color }: Props =
 | 
						const { property, groups, unit, unitPlural, responsive, color }: Props =
 | 
				
			||||||
		$props();
 | 
							$props();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	const store = createPropertyStore(property);
 | 
						const store = createPropertyStore(property);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -7,8 +7,7 @@
 | 
				
			||||||
		property: string;
 | 
							property: string;
 | 
				
			||||||
	};
 | 
						};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	let { label, property }: Props = $props();
 | 
						const { label, property }: Props = $props();
 | 
				
			||||||
 | 
					 | 
				
			||||||
	const store = createPropertyStore(property);
 | 
						const store = createPropertyStore(property);
 | 
				
			||||||
	const avg = $derived.by(() => {
 | 
						const avg = $derived.by(() => {
 | 
				
			||||||
		if (store.propertyData.length === 0) {
 | 
							if (store.propertyData.length === 0) {
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -6,8 +6,7 @@
 | 
				
			||||||
		label: string;
 | 
							label: string;
 | 
				
			||||||
	};
 | 
						};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	let { label }: Props = $props();
 | 
						const { label }: Props = $props();
 | 
				
			||||||
 | 
					 | 
				
			||||||
	const store = getMetadataContext();
 | 
						const store = getMetadataContext();
 | 
				
			||||||
	const count = $derived(store.metadata.length);
 | 
						const count = $derived(store.metadata.length);
 | 
				
			||||||
</script>
 | 
					</script>
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -7,8 +7,7 @@
 | 
				
			||||||
		property: string;
 | 
							property: string;
 | 
				
			||||||
	};
 | 
						};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	let { label, property }: Props = $props();
 | 
						const { label, property }: Props = $props();
 | 
				
			||||||
 | 
					 | 
				
			||||||
	const store = createPropertyStore(property);
 | 
						const store = createPropertyStore(property);
 | 
				
			||||||
	const count = $derived(store.propertyData.length);
 | 
						const count = $derived(store.propertyData.length);
 | 
				
			||||||
</script>
 | 
					</script>
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,13 +1,10 @@
 | 
				
			||||||
<script lang="ts">
 | 
					<script lang="ts">
 | 
				
			||||||
	import type { Readable } from "svelte/store";
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	type Props = {
 | 
						type Props = {
 | 
				
			||||||
		label: string;
 | 
							label: string;
 | 
				
			||||||
		value: number;
 | 
							value: number;
 | 
				
			||||||
	};
 | 
						};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	let { label, value }: Props = $props();
 | 
						const { label, value }: Props = $props();
 | 
				
			||||||
 | 
					 | 
				
			||||||
	const numberFormatter = new Intl.NumberFormat("en-US", {
 | 
						const numberFormatter = new Intl.NumberFormat("en-US", {
 | 
				
			||||||
		maximumFractionDigits: 2,
 | 
							maximumFractionDigits: 2,
 | 
				
			||||||
	});
 | 
						});
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -7,8 +7,7 @@
 | 
				
			||||||
		property: string;
 | 
							property: string;
 | 
				
			||||||
	};
 | 
						};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	let { label, property }: Props = $props();
 | 
						const { label, property }: Props = $props();
 | 
				
			||||||
 | 
					 | 
				
			||||||
	const store = createPropertyStore(property);
 | 
						const store = createPropertyStore(property);
 | 
				
			||||||
	const total = $derived(
 | 
						const total = $derived(
 | 
				
			||||||
		store.propertyData.reduce((acc, f) => acc + f.value, 0),
 | 
							store.propertyData.reduce((acc, f) => acc + f.value, 0),
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -63,6 +63,9 @@ export function chart<
 | 
				
			||||||
				| ChartConfigurationCustomTypesPerDataset<Type, Data, Label>
 | 
									| ChartConfigurationCustomTypesPerDataset<Type, Data, Label>
 | 
				
			||||||
		) => {
 | 
							) => {
 | 
				
			||||||
			chart.data = config.data;
 | 
								chart.data = config.data;
 | 
				
			||||||
 | 
								if (config.options) {
 | 
				
			||||||
 | 
									chart.options = config.options;
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
			chart.update();
 | 
								chart.update();
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
		destroy: () => {
 | 
							destroy: () => {
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -44,7 +44,7 @@ export function createDateFilter<T>(
 | 
				
			||||||
		data().forEach((item) => {
 | 
							data().forEach((item) => {
 | 
				
			||||||
			years.add(selector(item).year());
 | 
								years.add(selector(item).year());
 | 
				
			||||||
		});
 | 
							});
 | 
				
			||||||
		return Array.from(years).sort((a, b) => a - b);
 | 
							return Array.from(years).sort((a, b) => b - a);
 | 
				
			||||||
	});
 | 
						});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	const filterMonths = $derived.by(() => {
 | 
						const filterMonths = $derived.by(() => {
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in New Issue