mirror of
https://github.com/zadam/trilium.git
synced 2025-12-06 07:24:25 +01:00
chore(react/launch_bar): bring back week highlighting
This commit is contained in:
parent
20f44cc64f
commit
185e5691a4
@ -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<HTMLElement>;
|
||||
private $weekHeader!: JQuery<HTMLElement>;
|
||||
private $monthSelect!: JQuery<HTMLElement>;
|
||||
private $yearSelect!: JQuery<HTMLElement>;
|
||||
private $next!: JQuery<HTMLElement>;
|
||||
private $previous!: JQuery<HTMLElement>;
|
||||
private $nextYear!: JQuery<HTMLElement>;
|
||||
private $previousYear!: JQuery<HTMLElement>;
|
||||
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<string[]>(`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();
|
||||
}
|
||||
}
|
||||
@ -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*/`
|
||||
<div class="dropdown right-dropdown-widget">
|
||||
<button type="button" data-bs-toggle="dropdown"
|
||||
aria-haspopup="true" aria-expanded="false"
|
||||
class="bx right-dropdown-button launcher-button">
|
||||
<div class="tooltip-trigger"></div>
|
||||
</button>
|
||||
|
||||
<div class="dropdown-menu"></div>
|
||||
</div>
|
||||
`;
|
||||
|
||||
export default class RightDropdownButtonWidget extends BasicWidget {
|
||||
protected iconClass: string;
|
||||
protected title: string;
|
||||
protected dropdownTpl: string;
|
||||
protected settings: { titlePlacement: PopoverPlacement };
|
||||
protected $dropdownMenu!: JQuery<HTMLElement>;
|
||||
protected dropdown!: Dropdown;
|
||||
protected $tooltip!: JQuery<HTMLElement>;
|
||||
protected tooltip!: Tooltip;
|
||||
private dropdownClass?: string;
|
||||
public $dropdownContent!: JQuery<HTMLElement>;
|
||||
|
||||
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<void> {}
|
||||
}
|
||||
@ -31,6 +31,7 @@ export interface CalendarArgs {
|
||||
activeDate: Dayjs | null;
|
||||
onDateClicked(date: string, e: TargetedMouseEvent<HTMLAnchorElement>): void;
|
||||
onWeekClicked?: (week: string, e: TargetedMouseEvent<HTMLAnchorElement>) => void;
|
||||
weekNotes: string[];
|
||||
}
|
||||
|
||||
export default function Calendar(args: CalendarArgs) {
|
||||
@ -77,7 +78,7 @@ function PreviousMonthDays({ date, info: { dates, weekNumbers }, ...args }: { da
|
||||
|
||||
return (
|
||||
<>
|
||||
<CalendarWeek date={date} weekNumber={weekNumbers[0]} onWeekClicked={args.onWeekClicked} />
|
||||
<CalendarWeek date={date} weekNumber={weekNumbers[0]} {...args} />
|
||||
{dates.map(date => <CalendarDay date={date} dateNotesForMonth={dateNotesForPrevMonth} className="calendar-date-prev-month" {...args} />)}
|
||||
</>
|
||||
)
|
||||
@ -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(<CalendarWeek date={dateCursor} weekNumber={weekNumber} onWeekClicked={args.onWeekClicked} />)
|
||||
items.push(<CalendarWeek date={dateCursor} weekNumber={weekNumber} {...args}/>)
|
||||
}
|
||||
|
||||
items.push(<CalendarDay date={dateCursor} dateNotesForMonth={dateNotesForCurMonth} {...args} />)
|
||||
@ -141,18 +142,25 @@ function CalendarDay({ date, dateNotesForMonth, className, activeDate, todaysDat
|
||||
);
|
||||
}
|
||||
|
||||
function CalendarWeek({ date, weekNumber, onWeekClicked }: { weekNumber: number } & Pick<CalendarArgs, "date" | "onWeekClicked">) {
|
||||
function CalendarWeek({ date, weekNumber, weekNotes, onWeekClicked }: { weekNumber: number, weekNotes: string[] } & Pick<CalendarArgs, "date" | "onWeekClicked">) {
|
||||
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 (
|
||||
<a
|
||||
className="calendar-week-number calendar-date"
|
||||
onClick={(e) => 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}</a>
|
||||
)
|
||||
}
|
||||
|
||||
return (<span className="calendar-week-number calendar-week-number-disabled">{weekNumber}</span>);
|
||||
return (
|
||||
<span
|
||||
className="calendar-week-number calendar-week-number-disabled"
|
||||
data-calendar-week-number={weekNumber}
|
||||
>{weekNumber}</span>);
|
||||
}
|
||||
|
||||
export function getMonthInformation(date: Dayjs, firstDayISO: number, firstDayOfWeekISO: number) {
|
||||
|
||||
@ -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<Dayjs>();
|
||||
const dropdownRef = useRef<Dropdown>(null);
|
||||
const [ enableWeekNotes, setEnableWeekNotes ] = useState(false);
|
||||
const [ weekNotes, setWeekNotes ] = useState<string[]>([]);
|
||||
const calendarRootRef = useRef<FNote>();
|
||||
|
||||
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<string[]>(`attribute-values/weekNote`).then(setWeekNotes);
|
||||
}
|
||||
}
|
||||
|
||||
return (
|
||||
@ -91,6 +99,7 @@ export default function CalendarWidget({ launcherNote }: { launcherNote: FNote }
|
||||
}
|
||||
e.stopPropagation();
|
||||
} : undefined}
|
||||
weekNotes={weekNotes}
|
||||
{...calendarArgs}
|
||||
/>
|
||||
</div>}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user