edited notes: recognize dateNote label value TODAY, MONTH, YEAR

This commit is contained in:
contributor 2025-11-11 19:54:51 +02:00
parent 6134722b70
commit fda2fb9392
2 changed files with 128 additions and 1 deletions

View File

@ -0,0 +1,76 @@
import { describe, expect, it, vi, beforeEach, afterEach } from 'vitest';
import dayjs from "dayjs";
import { resolveDateParams } from "./edited-notes.js";
function resolveAsDate(dateStr: string) {
return resolveDateParams(dateStr).date;
}
describe("edited-notes::resolveAsDate", () => {
beforeEach(() => {
// Set a fixed date and time before each test
vi.useFakeTimers();
vi.setSystemTime(new Date('2012-11-10T23:22:21Z')); // NOTE!!: Date wrap in my timezone
});
afterEach(() => {
// Restore real timers after each test
vi.useRealTimers();
});
it("resolves 'TODAY' to today's date", () => {
const expectedDate = dayjs().format("YYYY-MM-DD");
const resolvedDate = resolveAsDate("TODAY");
expect(resolvedDate).toBe(expectedDate);
});
it("resolves 'MONTH' to current month", () => {
const expectedMonth = dayjs().format("YYYY-MM");
const resolvedMonth = resolveAsDate("MONTH");
expect(resolvedMonth).toBe(expectedMonth);
});
it("resolves 'YEAR' to current year", () => {
const expectedYear = dayjs().format("YYYY");
const resolvedYear = resolveAsDate("YEAR");
expect(resolvedYear).toBe(expectedYear);
});
it("resolves 'TODAY-1' to yesterday's date", () => {
const expectedDate = dayjs().subtract(1, "day").format("YYYY-MM-DD");
const resolvedDate = resolveAsDate("TODAY-1");
expect(resolvedDate).toBe(expectedDate);
});
it("resolves 'MONTH-2' to 2 months ago", () => {
const expectedMonth = dayjs().subtract(2, "month").format("YYYY-MM");
const resolvedMonth = resolveAsDate("MONTH-2");
expect(resolvedMonth).toBe(expectedMonth);
});
it("resolves 'YEAR+1' to next year", () => {
const expectedYear = dayjs().add(1, "year").format("YYYY");
const resolvedYear = resolveAsDate("YEAR+1");
expect(resolvedYear).toBe(expectedYear);
});
it("returns original string for unrecognized keyword", () => {
const unrecognizedString = "NOT_A_DYNAMIC_DATE";
const resolvedString = resolveAsDate(unrecognizedString);
expect(resolvedString).toBe(unrecognizedString);
});
it("returns original string for partially recognized keyword", () => {
const partialString = "TODAY-";
const resolvedString = resolveAsDate(partialString);
expect(resolvedString).toBe(partialString);
});
it("resolves 'today' (lowercase) to today's date", () => {
const expectedDate = dayjs().format("YYYY-MM-DD");
const resolvedDate = resolveAsDate("today");
expect(resolvedDate).toBe(expectedDate);
});
});

View File

@ -6,6 +6,7 @@ import type { Request } from "express";
import { NotePojo } from "../../becca/becca-interface.js";
import type BNote from "../../becca/entities/bnote.js";
import { EditedNotesResponse } from "@triliumnext/commons";
import dayjs from "dayjs";
interface NotePath {
noteId: string;
@ -20,6 +21,9 @@ interface NotePojoWithNotePath extends NotePojo {
}
function getEditedNotesOnDate(req: Request) {
const resolvedDateParams = resolveDateParams(req.params.date);
const sqlParams = { date: resolvedDateParams.date + "%" };
const noteIds = sql.getColumn<string>(/*sql*/`\
SELECT notes.*
@ -35,7 +39,7 @@ function getEditedNotesOnDate(req: Request) {
)
ORDER BY isDeleted
LIMIT 50`,
{ date: `${req.params.date}%` }
sqlParams
);
let notes = becca.getNotes(noteIds, true);
@ -81,6 +85,53 @@ function getNotePathData(note: BNote): NotePath | undefined {
}
}
function formatDateFromKeywordAndDelta(keyword: string, delta: number): string {
const formatMap = new Map<string, { format: string, addUnit: dayjs.UnitType }>([
["today", { format: "YYYY-MM-DD", addUnit: "day" }],
["month", { format: "YYYY-MM", addUnit: "month" }],
["year", { format: "YYYY", addUnit: "year" }]
]);
const handler = formatMap.get(keyword);
if (!handler) {
throw new Error(`Unrecognized keyword: ${keyword}`);
}
const date = dayjs().add(delta, handler.addUnit);
return date.format(handler.format);
}
interface DateValue {
// kind: "date",
date: string,
}
type DateFilter = DateValue;
/**
* Resolves date keyword with optional delta (e.g., "TODAY-1") to date
* @param dateStr date keyword (TODAY, MONTH, YEAR) or date in format YYYY-MM-DD (or beggining)
* @returns
*/
export function resolveDateParams(dateStr: string): DateFilter {
const match = dateStr.match(/^(today|month|year)([+-]\d+)?$/i);
if (!match) {
return {
date: `${dateStr}`
}
}
const keyword = match[1].toLowerCase();
const delta = match[2] ? parseInt(match[2]) : 0;
const date = formatDateFromKeywordAndDelta(keyword, delta);
return {
date: `${date}`
}
}
export default {
getEditedNotesOnDate,
};