generated from tpl/obsidian-sample-plugin
129 lines
3.2 KiB
Svelte
129 lines
3.2 KiB
Svelte
<script lang="ts">
|
|
import { chart } from "@ui/directives/chart";
|
|
import { ALL_TIME } from "@ui/stores/date-filter.svelte";
|
|
import { getMetadataContext } from "@ui/stores/metadata.svelte";
|
|
import { getReadingLogContext } from "@ui/stores/reading-log.svelte";
|
|
import { getSettingsContext } from "@ui/stores/settings.svelte";
|
|
import { Color } from "@utils/color";
|
|
import type { ChartConfiguration } from "chart.js";
|
|
|
|
const settingsStore = getSettingsContext();
|
|
const store = getMetadataContext();
|
|
const readingLog = getReadingLogContext();
|
|
|
|
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 pages = new Map<number, number>();
|
|
for (const item of items) {
|
|
let key: number;
|
|
if (store.filterYear === ALL_TIME) {
|
|
key = item.date.year();
|
|
} else if (store.filterMonth === ALL_TIME) {
|
|
key = item.date.month();
|
|
} else {
|
|
key = item.date.date();
|
|
}
|
|
|
|
const pageCount = pages.get(key) ?? 0;
|
|
pages.set(key, pageCount + item.pageCount);
|
|
|
|
const bookCount = books.get(key) ?? 0;
|
|
books.set(key, bookCount + 1);
|
|
}
|
|
|
|
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);
|
|
}
|
|
}
|
|
}
|
|
|
|
const labels = Array.from(books.keys())
|
|
.sort((a, b) => a - b)
|
|
.map((key) =>
|
|
store.filterYear === ALL_TIME || isMonthly
|
|
? key
|
|
: // @ts-expect-error Moment is provided by Obsidian
|
|
moment().month(key).format("MMM"),
|
|
);
|
|
const sortedBooks = Array.from(books.entries())
|
|
.sort((a, b) => a[0] - b[0])
|
|
.map((b) => b[1]);
|
|
const sortedPages = Array.from(pages.entries())
|
|
.sort((a, b) => a[0] - b[0])
|
|
.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 {
|
|
type: "line",
|
|
data: {
|
|
labels,
|
|
datasets,
|
|
},
|
|
options: {
|
|
scales: {
|
|
y: {
|
|
type: "linear",
|
|
display: true,
|
|
position: "left",
|
|
ticks: { beginAtZero: true },
|
|
},
|
|
y1: {
|
|
type: "linear",
|
|
display: !isMonthly,
|
|
position: "right",
|
|
grid: { drawOnChartArea: false },
|
|
},
|
|
},
|
|
},
|
|
} as ChartConfiguration;
|
|
});
|
|
</script>
|
|
|
|
<canvas use:chart={config}></canvas>
|