diff --git a/apps/client/src/widgets/buttons/calendar.ts b/apps/client/src/widgets/buttons/calendar.ts deleted file mode 100644 index 4406bd2b7..000000000 --- a/apps/client/src/widgets/buttons/calendar.ts +++ /dev/null @@ -1,109 +0,0 @@ -import { t } from "../../services/i18n.js"; -import dateNoteService from "../../services/date_notes.js"; -import server from "../../services/server.js"; -import appContext from "../../components/app_context.js"; -import RightDropdownButtonWidget from "./right_dropdown_button.js"; -import toastService from "../../services/toast.js"; -import options from "../../services/options.js"; -import { Dropdown } from "bootstrap"; -import type { EventData } from "../../components/app_context.js"; -import { dayjs, type Dayjs } from "@triliumnext/commons"; -import type { AttributeRow, OptionDefinitions } from "@triliumnext/commons"; - -interface WeekCalculationOptions { - firstWeekType: number; - minDaysInFirstWeek: number; -} - -export default class CalendarWidget extends RightDropdownButtonWidget { - private $month!: JQuery; - private $weekHeader!: JQuery; - private $monthSelect!: JQuery; - private $yearSelect!: JQuery; - private $next!: JQuery; - private $previous!: JQuery; - private $nextYear!: JQuery; - private $previousYear!: JQuery; - private monthDropdown!: Dropdown; - // stored in ISO 1–7 - private firstDayOfWeekISO!: number; - private weekCalculationOptions!: WeekCalculationOptions; - private activeDate: Dayjs | null = null; - private todaysDate!: Dayjs; - private date!: Dayjs; - private weekNoteEnable: boolean = false; - private weekNotes: string[] = []; - - constructor(title: string = "", icon: string = "") { - super(title, icon, DROPDOWN_TPL, "calendar-dropdown-menu"); - } - - doRender() { - super.doRender(); - - this.$month = this.$dropdownContent.find('[data-calendar-area="month"]'); - - this.manageFirstDayOfWeek(); - this.initWeekCalculation(); - - // Handle click events for the entire calendar widget - this.$dropdownContent.on("click", (e) => { - const $target = $(e.target); - - // Keep dropdown open when clicking on month select button or year selector area - if ($target.closest('.btn.dropdown-toggle.select-button').length) { - e.stopPropagation(); - return; - } - - // Hide dropdown for all other cases - this.monthDropdown.hide(); - // Prevent dismissing the calendar popup by clicking on an empty space inside it. - e.stopPropagation(); - }); - } - - initWeekCalculation() { - this.weekCalculationOptions = { - firstWeekType: options.getInt("firstWeekOfYear") || 0, - minDaysInFirstWeek: options.getInt("minDaysInFirstWeek") || 4 - }; - } - - async dropdownShown() { - await this.getWeekNoteEnable(); - this.weekNotes = await server.get(`attribute-values/weekNote`); - this.init( ?? null); - } - - createWeekNumber(weekNumber: number) { - - let $newWeekNumber; - - if (this.weekNoteEnable) { - if (this.weekNotes.includes(weekNoteId)) { - $newWeekNumber.addClass("calendar-date-exists").attr("data-href", `#root/${weekNoteId}`); - } - } else { - - } - - $newWeekNumber.addClass("calendar-week-number").attr("data-calendar-week-number", weekNoteId); - return $newWeekNumber; - } - - async entitiesReloadedEvent({ loadResults }: EventData<"entitiesReloaded">) { - const WEEK_OPTIONS: (keyof OptionDefinitions)[] = [ - "firstDayOfWeek", - "firstWeekOfYear", - "minDaysInFirstWeek", - ]; - if (!WEEK_OPTIONS.some(opt => loadResults.getOptionNames().includes(opt))) { - return; - } - - this.manageFirstDayOfWeek(); - this.initWeekCalculation(); - this.createMonth(); - } -} diff --git a/apps/client/src/widgets/buttons/right_dropdown_button.ts b/apps/client/src/widgets/buttons/right_dropdown_button.ts deleted file mode 100644 index 45915c254..000000000 --- a/apps/client/src/widgets/buttons/right_dropdown_button.ts +++ /dev/null @@ -1,86 +0,0 @@ -import { handleRightToLeftPlacement } from "../../services/utils.js"; -import BasicWidget from "../basic_widget.js"; -import { Tooltip, Dropdown } from "bootstrap"; -type PopoverPlacement = Tooltip.PopoverPlacement; - -const TPL = /*html*/` - -`; - -export default class RightDropdownButtonWidget extends BasicWidget { - protected iconClass: string; - protected title: string; - protected dropdownTpl: string; - protected settings: { titlePlacement: PopoverPlacement }; - protected $dropdownMenu!: JQuery; - protected dropdown!: Dropdown; - protected $tooltip!: JQuery; - protected tooltip!: Tooltip; - private dropdownClass?: string; - public $dropdownContent!: JQuery; - - constructor(title: string, iconClass: string, dropdownTpl: string, dropdownClass?: string) { - super(); - - this.iconClass = iconClass; - this.title = title; - this.dropdownTpl = dropdownTpl; - this.dropdownClass = dropdownClass; - - this.settings = { - titlePlacement: "right" - }; - } - - doRender() { - this.$widget = $(TPL); - this.$dropdownMenu = this.$widget.find(".dropdown-menu"); - if (this.dropdownClass) { - this.$dropdownMenu.addClass(this.dropdownClass); - } - this.dropdown = Dropdown.getOrCreateInstance(this.$widget.find("[data-bs-toggle='dropdown']")[0], { - popperConfig: { - placement: this.settings.titlePlacement, - } - }); - - this.$tooltip = this.$widget.find(".tooltip-trigger").attr("title", this.title); - this.tooltip = new Tooltip(this.$tooltip[0], { - placement: handleRightToLeftPlacement(this.settings.titlePlacement), - fallbackPlacements: [ handleRightToLeftPlacement(this.settings.titlePlacement) ] - }); - - this.$widget - .find(".right-dropdown-button") - .addClass(this.iconClass) - .on("click", () => this.tooltip.hide()) - .on("mouseenter", () => this.tooltip.show()) - .on("mouseleave", () => this.tooltip.hide()); - - this.$widget.on("show.bs.dropdown", async () => { - await this.dropdownShown(); - - const rect = this.$dropdownMenu[0].getBoundingClientRect(); - const windowHeight = $(window).height() || 0; - const pixelsToBottom = windowHeight - rect.bottom; - - if (pixelsToBottom < 0) { - this.$dropdownMenu.css("top", pixelsToBottom); - } - }); - - this.$dropdownContent = $(this.dropdownTpl); - this.$widget.find(".dropdown-menu").append(this.$dropdownContent); - } - - // to be overridden - async dropdownShown(): Promise {} -} diff --git a/apps/client/src/widgets/launch_bar/Calendar.tsx b/apps/client/src/widgets/launch_bar/Calendar.tsx index b058dd8c5..2b7225db5 100644 --- a/apps/client/src/widgets/launch_bar/Calendar.tsx +++ b/apps/client/src/widgets/launch_bar/Calendar.tsx @@ -31,6 +31,7 @@ export interface CalendarArgs { activeDate: Dayjs | null; onDateClicked(date: string, e: TargetedMouseEvent): void; onWeekClicked?: (week: string, e: TargetedMouseEvent) => void; + weekNotes: string[]; } export default function Calendar(args: CalendarArgs) { @@ -77,7 +78,7 @@ function PreviousMonthDays({ date, info: { dates, weekNumbers }, ...args }: { da return ( <> - + {dates.map(date => )} ) @@ -97,7 +98,7 @@ function CurrentMonthDays({ date, firstDayOfWeekISO, ...args }: { date: Dayjs, f while (dateCursor.month() === currentMonth) { const weekNumber = getWeekNumber(dateCursor, firstDayOfWeekISO); if (dateCursor.isoWeekday() === firstDayOfWeekISO) { - items.push() + items.push() } items.push() @@ -141,18 +142,25 @@ function CalendarDay({ date, dateNotesForMonth, className, activeDate, todaysDat ); } -function CalendarWeek({ date, weekNumber, onWeekClicked }: { weekNumber: number } & Pick) { +function CalendarWeek({ date, weekNumber, weekNotes, onWeekClicked }: { weekNumber: number, weekNotes: string[] } & Pick) { + const weekString = date.local().format('YYYY-') + 'W' + String(weekNumber).padStart(2, '0'); + if (onWeekClicked) { - const weekNoteId = date.local().format('YYYY-') + 'W' + String(weekNumber).padStart(2, '0'); return ( onWeekClicked(weekNoteId, e)} + className={clsx("calendar-week-number", "calendar-date", + weekNotes.includes(weekString) && "calendar-date-exists")} + data-calendar-week-number={weekNumber} + onClick={(e) => onWeekClicked(weekString, e)} >{weekNumber} ) } - return ({weekNumber}); + return ( + {weekNumber}); } export function getMonthInformation(date: Dayjs, firstDayISO: number, firstDayOfWeekISO: number) { diff --git a/apps/client/src/widgets/launch_bar/CalendarWidget.tsx b/apps/client/src/widgets/launch_bar/CalendarWidget.tsx index 617dd8c80..70c4dc76a 100644 --- a/apps/client/src/widgets/launch_bar/CalendarWidget.tsx +++ b/apps/client/src/widgets/launch_bar/CalendarWidget.tsx @@ -13,6 +13,7 @@ import toast from "../../services/toast"; import date_notes from "../../services/date_notes"; import { Dropdown } from "bootstrap"; import search from "../../services/search"; +import server from "../../services/server"; const MONTHS = [ t("calendar.january"), @@ -35,6 +36,7 @@ export default function CalendarWidget({ launcherNote }: { launcherNote: FNote } const [ date, setDate ] = useState(); const dropdownRef = useRef(null); const [ enableWeekNotes, setEnableWeekNotes ] = useState(false); + const [ weekNotes, setWeekNotes ] = useState([]); const calendarRootRef = useRef(); async function checkEnableWeekNotes() { @@ -45,7 +47,13 @@ export default function CalendarWidget({ launcherNote }: { launcherNote: FNote } } if (!calendarRootRef.current) return; - setEnableWeekNotes(calendarRootRef.current.hasLabel("enableWeekNote")); + + const enableWeekNotes = calendarRootRef.current.hasLabel("enableWeekNote"); + setEnableWeekNotes(enableWeekNotes); + + if (enableWeekNotes) { + server.get(`attribute-values/weekNote`).then(setWeekNotes); + } } return ( @@ -91,6 +99,7 @@ export default function CalendarWidget({ launcherNote }: { launcherNote: FNote } } e.stopPropagation(); } : undefined} + weekNotes={weekNotes} {...calendarArgs} /> }