fix(server): week notes broken due to misuse of transactions

This commit is contained in:
Elian Doran 2025-05-16 19:09:54 +03:00
parent e946bde939
commit 1d58b285de
No known key found for this signature in database
2 changed files with 41 additions and 35 deletions

View File

@ -6,7 +6,6 @@ import attributeService from "./attributes.js";
import cloningService from "./cloning.js"; import cloningService from "./cloning.js";
import dayjs from "dayjs"; import dayjs from "dayjs";
import hoistedNoteService from "./hoisted_note.js"; import hoistedNoteService from "./hoisted_note.js";
import i18next from "i18next";
import isSameOrAfter from "dayjs/plugin/isSameOrAfter.js"; import isSameOrAfter from "dayjs/plugin/isSameOrAfter.js";
import noteService from "./notes.js"; import noteService from "./notes.js";
import optionService from "./options.js"; import optionService from "./options.js";
@ -16,6 +15,7 @@ import searchContext from "../services/search/search_context.js";
import searchService from "../services/search/services/search.js"; import searchService from "../services/search/services/search.js";
import sql from "./sql.js"; import sql from "./sql.js";
import { t } from "i18next"; import { t } from "i18next";
import { ordinal } from "./i18n.js";
dayjs.extend(isSameOrAfter); dayjs.extend(isSameOrAfter);
dayjs.extend(quarterOfYear); dayjs.extend(quarterOfYear);
@ -67,24 +67,7 @@ function getTimeUnitReplacements(timeUnit: TimeUnit): string[] {
return units.slice(0, index + 1).flatMap(unit => baseReplacements[unit]); return units.slice(0, index + 1).flatMap(unit => baseReplacements[unit]);
} }
async function ordinal(date: Dayjs, lng: string) { function getJournalNoteTitle(
const localeMap: Record<string, string> = {
cn: "zh-cn",
tw: "zh-tw"
};
const dayjsLocale = localeMap[lng] || lng;
try {
await import(`dayjs/locale/${dayjsLocale}.js`);
} catch (err) {
console.warn(`Could not load locale ${dayjsLocale}`, err);
}
return dayjs(date).locale(dayjsLocale).format("Do");
}
async function getJournalNoteTitle(
rootNote: BNote, rootNote: BNote,
timeUnit: TimeUnit, timeUnit: TimeUnit,
dateObj: Dayjs, dateObj: Dayjs,
@ -102,7 +85,7 @@ async function getJournalNoteTitle(
const monthName = t(MONTH_TRANSLATION_IDS[dateObj.month()]); const monthName = t(MONTH_TRANSLATION_IDS[dateObj.month()]);
const weekDay = t(WEEKDAY_TRANSLATION_IDS[dateObj.day()]); const weekDay = t(WEEKDAY_TRANSLATION_IDS[dateObj.day()]);
const numberStr = number.toString(); const numberStr = number.toString();
const ordinalStr = await ordinal(dateObj, i18next.language); const ordinalStr = ordinal(dateObj);
const allReplacements: Record<string, string> = { const allReplacements: Record<string, string> = {
// Common date formats // Common date formats
@ -228,7 +211,7 @@ function getQuarterNumberStr(date: Dayjs) {
return `${date.year()}-Q${date.quarter()}`; return `${date.year()}-Q${date.quarter()}`;
} }
async function getQuarterNote(quarterStr: string, _rootNote: BNote | null = null): Promise<BNote> { function getQuarterNote(quarterStr: string, _rootNote: BNote | null = null): BNote {
const rootNote = _rootNote || getRootCalendarNote(); const rootNote = _rootNote || getRootCalendarNote();
quarterStr = quarterStr.trim().substring(0, 7); quarterStr = quarterStr.trim().substring(0, 7);
@ -247,7 +230,7 @@ async function getQuarterNote(quarterStr: string, _rootNote: BNote | null = null
const quarterStartDate = dayjs().year(parseInt(yearStr)).month(firstMonth).date(1); const quarterStartDate = dayjs().year(parseInt(yearStr)).month(firstMonth).date(1);
const yearNote = getYearNote(yearStr, rootNote); const yearNote = getYearNote(yearStr, rootNote);
const noteTitle = await getJournalNoteTitle( const noteTitle = getJournalNoteTitle(
rootNote, "quarter", quarterStartDate, quarterNumber rootNote, "quarter", quarterStartDate, quarterNumber
); );
@ -269,7 +252,7 @@ async function getQuarterNote(quarterStr: string, _rootNote: BNote | null = null
return quarterNote as unknown as BNote; return quarterNote as unknown as BNote;
} }
async function getMonthNote(dateStr: string, _rootNote: BNote | null = null): Promise<BNote> { function getMonthNote(dateStr: string, _rootNote: BNote | null = null): BNote {
const rootNote = _rootNote || getRootCalendarNote(); const rootNote = _rootNote || getRootCalendarNote();
const monthStr = dateStr.substring(0, 7); const monthStr = dateStr.substring(0, 7);
@ -286,12 +269,12 @@ async function getMonthNote(dateStr: string, _rootNote: BNote | null = null): Pr
let monthParentNote; let monthParentNote;
if (rootNote.hasLabel("enableQuarterNote")) { if (rootNote.hasLabel("enableQuarterNote")) {
monthParentNote = await getQuarterNote(getQuarterNumberStr(dayjs(dateStr)), rootNote); monthParentNote = getQuarterNote(getQuarterNumberStr(dayjs(dateStr)), rootNote);
} else { } else {
monthParentNote = getYearNote(dateStr, rootNote); monthParentNote = getYearNote(dateStr, rootNote);
} }
const noteTitle = await getJournalNoteTitle( const noteTitle = getJournalNoteTitle(
rootNote, "month", dayjs(dateStr), parseInt(monthNumber) rootNote, "month", dayjs(dateStr), parseInt(monthNumber)
); );
@ -408,7 +391,7 @@ function getWeekFirstDayNote(dateStr: string, rootNote: BNote | null = null) {
* @param _rootNote a {@link BNote} representing the calendar root, or {@code null} or not specified to use the default root calendar note. * @param _rootNote a {@link BNote} representing the calendar root, or {@code null} or not specified to use the default root calendar note.
* @returns a Promise that resolves to the {@link BNote} corresponding to the week note. * @returns a Promise that resolves to the {@link BNote} corresponding to the week note.
*/ */
async function getWeekNote(weekStr: string, _rootNote: BNote | null = null): Promise<BNote | null> { function getWeekNote(weekStr: string, _rootNote: BNote | null = null): BNote | null {
const rootNote = _rootNote || getRootCalendarNote(); const rootNote = _rootNote || getRootCalendarNote();
if (!rootNote.hasLabel("enableWeekNote")) { if (!rootNote.hasLabel("enableWeekNote")) {
return null; return null;
@ -435,10 +418,10 @@ async function getWeekNote(weekStr: string, _rootNote: BNote | null = null): Pro
const startMonth = startDate.month(); const startMonth = startDate.month();
const endMonth = endDate.month(); const endMonth = endDate.month();
const monthNote = await getMonthNote(startDate.format("YYYY-MM-DD"), rootNote); const monthNote = getMonthNote(startDate.format("YYYY-MM-DD"), rootNote);
const noteTitle = await getJournalNoteTitle(rootNote, "week", startDate, weekNumber); const noteTitle = getJournalNoteTitle(rootNote, "week", startDate, weekNumber);
sql.transactional(async () => { sql.transactional(() => {
weekNote = createNote(monthNote, noteTitle); weekNote = createNote(monthNote, noteTitle);
attributeService.createLabel(weekNote.noteId, WEEK_LABEL, weekStr); attributeService.createLabel(weekNote.noteId, WEEK_LABEL, weekStr);
@ -452,7 +435,7 @@ async function getWeekNote(weekStr: string, _rootNote: BNote | null = null): Pro
// If the week spans different months, clone the week note in the other month as well // If the week spans different months, clone the week note in the other month as well
if (startMonth !== endMonth) { if (startMonth !== endMonth) {
const secondMonthNote = await getMonthNote(endDate.format("YYYY-MM-DD"), rootNote); const secondMonthNote = getMonthNote(endDate.format("YYYY-MM-DD"), rootNote);
cloningService.cloneNoteToParentNote(weekNote.noteId, secondMonthNote.noteId); cloningService.cloneNoteToParentNote(weekNote.noteId, secondMonthNote.noteId);
} }
}); });
@ -460,7 +443,7 @@ async function getWeekNote(weekStr: string, _rootNote: BNote | null = null): Pro
return weekNote as unknown as BNote; return weekNote as unknown as BNote;
} }
async function getDayNote(dateStr: string, _rootNote: BNote | null = null): Promise<BNote> { function getDayNote(dateStr: string, _rootNote: BNote | null = null): BNote {
const rootNote = _rootNote || getRootCalendarNote(); const rootNote = _rootNote || getRootCalendarNote();
dateStr = dateStr.trim().substring(0, 10); dateStr = dateStr.trim().substring(0, 10);
@ -476,13 +459,13 @@ async function getDayNote(dateStr: string, _rootNote: BNote | null = null): Prom
let dateParentNote; let dateParentNote;
if (rootNote.hasLabel("enableWeekNote")) { if (rootNote.hasLabel("enableWeekNote")) {
dateParentNote = await getWeekNote(getWeekNumberStr(dayjs(dateStr)), rootNote); dateParentNote = getWeekNote(getWeekNumberStr(dayjs(dateStr)), rootNote);
} else { } else {
dateParentNote = await getMonthNote(dateStr, rootNote); dateParentNote = getMonthNote(dateStr, rootNote);
} }
const dayNumber = dateStr.substring(8, 10); const dayNumber = dateStr.substring(8, 10);
const noteTitle = await getJournalNoteTitle( const noteTitle = getJournalNoteTitle(
rootNote, "day", dayjs(dateStr), parseInt(dayNumber) rootNote, "day", dayjs(dateStr), parseInt(dayNumber)
); );

View File

@ -5,20 +5,43 @@ import { join } from "path";
import { getResourceDir } from "./utils.js"; import { getResourceDir } from "./utils.js";
import hidden_subtree from "./hidden_subtree.js"; import hidden_subtree from "./hidden_subtree.js";
import { LOCALES, type Locale } from "@triliumnext/commons"; import { LOCALES, type Locale } from "@triliumnext/commons";
import dayjs, { Dayjs } from "dayjs";
const DAYJS_LOCALE_MAP: Record<string, string> = {
cn: "zh-cn",
tw: "zh-tw"
};
let dayjsLocale: string;
export async function initializeTranslations() { export async function initializeTranslations() {
const resourceDir = getResourceDir(); const resourceDir = getResourceDir();
const Backend = (await import("i18next-fs-backend")).default; const Backend = (await import("i18next-fs-backend")).default;
const locale = getCurrentLanguage();
// Initialize translations // Initialize translations
await i18next.use(Backend).init({ await i18next.use(Backend).init({
lng: getCurrentLanguage(), lng: locale,
fallbackLng: "en", fallbackLng: "en",
ns: "server", ns: "server",
backend: { backend: {
loadPath: join(resourceDir, "assets/translations/{{lng}}/{{ns}}.json") loadPath: join(resourceDir, "assets/translations/{{lng}}/{{ns}}.json")
} }
}); });
// Initialize dayjs locale.
dayjsLocale = DAYJS_LOCALE_MAP[locale] ?? locale;
try {
await import(`dayjs/locale/${dayjsLocale}.js`);
} catch (err) {
console.warn(`Could not load locale ${dayjsLocale}`, err);
}
}
export function ordinal(date: Dayjs) {
return dayjs(date)
.locale(dayjsLocale)
.format("Do");
} }
export function getLocales(): Locale[] { export function getLocales(): Locale[] {