mirror of
https://github.com/TriliumNext/Notes.git
synced 2025-08-11 11:02:27 +08:00
feat: 🎸 add week numbers
This commit is contained in:
parent
ec06503104
commit
0ed957dd77
@ -29,7 +29,7 @@ const DROPDOWN_TPL = `
|
|||||||
<div class="calendar-dropdown-widget">
|
<div class="calendar-dropdown-widget">
|
||||||
<style>
|
<style>
|
||||||
.calendar-dropdown-widget {
|
.calendar-dropdown-widget {
|
||||||
width: 350px;
|
width: 380px;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
@ -59,10 +59,13 @@ const DROPDOWN_TPL = `
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="calendar-week">
|
<div class="calendar-container">
|
||||||
</div>
|
<div class="calendar-week-numbers"></div>
|
||||||
|
<div class="calendar-main">
|
||||||
|
<div class="calendar-week"></div>
|
||||||
<div class="calendar-body" data-calendar-area="month"></div>
|
<div class="calendar-body" data-calendar-area="month"></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>`;
|
</div>`;
|
||||||
|
|
||||||
const DAYS_OF_WEEK = [t("calendar.sun"), t("calendar.mon"), t("calendar.tue"), t("calendar.wed"), t("calendar.thu"), t("calendar.fri"), t("calendar.sat")];
|
const DAYS_OF_WEEK = [t("calendar.sun"), t("calendar.mon"), t("calendar.tue"), t("calendar.wed"), t("calendar.thu"), t("calendar.fri"), t("calendar.sat")];
|
||||||
@ -71,9 +74,15 @@ interface DateNotesForMonth {
|
|||||||
[date: string]: string;
|
[date: string]: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
interface WeekCalculationOptions {
|
||||||
|
firstWeekType: number;
|
||||||
|
minDaysInFirstWeek: number;
|
||||||
|
}
|
||||||
|
|
||||||
export default class CalendarWidget extends RightDropdownButtonWidget {
|
export default class CalendarWidget extends RightDropdownButtonWidget {
|
||||||
private $month!: JQuery<HTMLElement>;
|
private $month!: JQuery<HTMLElement>;
|
||||||
private $weekHeader!: JQuery<HTMLElement>;
|
private $weekHeader!: JQuery<HTMLElement>;
|
||||||
|
private $weekNumbers!: JQuery<HTMLElement>;
|
||||||
private $monthSelect!: JQuery<HTMLElement>;
|
private $monthSelect!: JQuery<HTMLElement>;
|
||||||
private $yearSelect!: JQuery<HTMLElement>;
|
private $yearSelect!: JQuery<HTMLElement>;
|
||||||
private $next!: JQuery<HTMLElement>;
|
private $next!: JQuery<HTMLElement>;
|
||||||
@ -82,6 +91,7 @@ export default class CalendarWidget extends RightDropdownButtonWidget {
|
|||||||
private $previousYear!: JQuery<HTMLElement>;
|
private $previousYear!: JQuery<HTMLElement>;
|
||||||
private monthDropdown!: Dropdown;
|
private monthDropdown!: Dropdown;
|
||||||
private firstDayOfWeek!: number;
|
private firstDayOfWeek!: number;
|
||||||
|
private weekCalculationOptions!: WeekCalculationOptions;
|
||||||
private activeDate: Date | null = null;
|
private activeDate: Date | null = null;
|
||||||
private todaysDate!: Date;
|
private todaysDate!: Date;
|
||||||
private date!: Date;
|
private date!: Date;
|
||||||
@ -95,8 +105,10 @@ export default class CalendarWidget extends RightDropdownButtonWidget {
|
|||||||
|
|
||||||
this.$month = this.$dropdownContent.find('[data-calendar-area="month"]');
|
this.$month = this.$dropdownContent.find('[data-calendar-area="month"]');
|
||||||
this.$weekHeader = this.$dropdownContent.find(".calendar-week");
|
this.$weekHeader = this.$dropdownContent.find(".calendar-week");
|
||||||
|
this.$weekNumbers = this.$dropdownContent.find(".calendar-week-numbers");
|
||||||
|
|
||||||
this.manageFirstDayOfWeek();
|
this.manageFirstDayOfWeek();
|
||||||
|
this.initWeekCalculation();
|
||||||
|
|
||||||
// Month navigation
|
// Month navigation
|
||||||
this.$monthSelect = this.$dropdownContent.find('[data-calendar-input="month"]');
|
this.$monthSelect = this.$dropdownContent.find('[data-calendar-input="month"]');
|
||||||
@ -187,6 +199,52 @@ export default class CalendarWidget extends RightDropdownButtonWidget {
|
|||||||
this.$weekHeader.html(localeDaysOfWeek.map((el) => `<span>${el}</span>`).join(''));
|
this.$weekHeader.html(localeDaysOfWeek.map((el) => `<span>${el}</span>`).join(''));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
initWeekCalculation() {
|
||||||
|
this.weekCalculationOptions = {
|
||||||
|
firstWeekType: options.getInt("firstWeekOfYear") || 0,
|
||||||
|
minDaysInFirstWeek: options.getInt("minDaysInFirstWeek") || 4
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
getWeekNumber(date: Date): number {
|
||||||
|
const utcDate = new Date(Date.UTC(date.getUTCFullYear(), date.getUTCMonth(), date.getUTCDate()));
|
||||||
|
|
||||||
|
const year = utcDate.getUTCFullYear();
|
||||||
|
const jan1 = new Date(Date.UTC(year, 0, 1));
|
||||||
|
const jan1Day = jan1.getUTCDay();
|
||||||
|
|
||||||
|
let firstWeekStart = new Date(jan1);
|
||||||
|
|
||||||
|
let dayOffset = (jan1Day - this.firstDayOfWeek + 7) % 7;
|
||||||
|
firstWeekStart.setUTCDate(firstWeekStart.getUTCDate() - dayOffset);
|
||||||
|
|
||||||
|
switch (this.weekCalculationOptions.firstWeekType) {
|
||||||
|
case 1: {
|
||||||
|
const thursday = new Date(firstWeekStart);
|
||||||
|
const day = thursday.getUTCDay();
|
||||||
|
const offset = (4 - day + 7) % 7;
|
||||||
|
thursday.setUTCDate(thursday.getUTCDate() + offset);
|
||||||
|
if (thursday.getUTCFullYear() < year) {
|
||||||
|
firstWeekStart.setUTCDate(firstWeekStart.getUTCDate() + 7);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 2: {
|
||||||
|
const daysInFirstWeek = 7 - dayOffset;
|
||||||
|
if (daysInFirstWeek < this.weekCalculationOptions.minDaysInFirstWeek) {
|
||||||
|
firstWeekStart.setUTCDate(firstWeekStart.getUTCDate() + 7);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
// case 0 is default: week containing Jan 1
|
||||||
|
}
|
||||||
|
|
||||||
|
const diffMillis = utcDate.getTime() - firstWeekStart.getTime();
|
||||||
|
const diffDays = Math.floor(diffMillis / (24 * 60 * 60 * 1000));
|
||||||
|
|
||||||
|
return Math.floor(diffDays / 7) + 1;
|
||||||
|
}
|
||||||
|
|
||||||
async dropdownShown() {
|
async dropdownShown() {
|
||||||
this.init(appContext.tabManager.getActiveContextNote()?.getOwnedLabelValue("dateNote") ?? null);
|
this.init(appContext.tabManager.getActiveContextNote()?.getOwnedLabelValue("dateNote") ?? null);
|
||||||
}
|
}
|
||||||
@ -246,13 +304,19 @@ export default class CalendarWidget extends RightDropdownButtonWidget {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async createMonth() {
|
async createMonth() {
|
||||||
const month = utils.formatDateISO(this.date).substr(0, 7);
|
const month = utils.formatDateISO(this.date).substring(0, 7);
|
||||||
const dateNotesForMonth: DateNotesForMonth = await server.get(`special-notes/notes-for-month/${month}`);
|
const dateNotesForMonth: DateNotesForMonth = await server.get(`special-notes/notes-for-month/${month}`);
|
||||||
|
|
||||||
this.$month.empty();
|
this.$month.empty();
|
||||||
|
this.$weekNumbers.empty();
|
||||||
|
|
||||||
const currentMonth = this.date.getMonth();
|
const currentMonth = this.date.getMonth();
|
||||||
|
const weekNumbers: Set<number> = new Set();
|
||||||
|
|
||||||
while (this.date.getMonth() === currentMonth) {
|
while (this.date.getMonth() === currentMonth) {
|
||||||
|
const safeDate = new Date(Date.UTC(this.date.getFullYear(), this.date.getMonth(), this.date.getDate()));
|
||||||
|
weekNumbers.add(this.getWeekNumber(safeDate));
|
||||||
|
|
||||||
const $day = this.createDay(dateNotesForMonth, this.date.getDate(), this.date.getDay());
|
const $day = this.createDay(dateNotesForMonth, this.date.getDate(), this.date.getDay());
|
||||||
|
|
||||||
this.$month.append($day);
|
this.$month.append($day);
|
||||||
@ -265,14 +329,24 @@ export default class CalendarWidget extends RightDropdownButtonWidget {
|
|||||||
|
|
||||||
this.$monthSelect.text(MONTHS[this.date.getMonth()]);
|
this.$monthSelect.text(MONTHS[this.date.getMonth()]);
|
||||||
this.$yearSelect.val(this.date.getFullYear());
|
this.$yearSelect.val(this.date.getFullYear());
|
||||||
|
|
||||||
|
for (const weekNumber of weekNumbers) {
|
||||||
|
const $weekNumber = $("<div>")
|
||||||
|
.addClass("calendar-week-number")
|
||||||
|
.text(weekNumber);
|
||||||
|
this.$weekNumbers.append($weekNumber);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async entitiesReloadedEvent({ loadResults }: EventData<"entitiesReloaded">) {
|
async entitiesReloadedEvent({ loadResults }: EventData<"entitiesReloaded">) {
|
||||||
if (!loadResults.getOptionNames().includes("firstDayOfWeek")) {
|
if (!loadResults.getOptionNames().includes("firstDayOfWeek") &&
|
||||||
|
!loadResults.getOptionNames().includes("firstWeekOfYear") &&
|
||||||
|
!loadResults.getOptionNames().includes("minDaysInFirstWeek")) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
this.manageFirstDayOfWeek();
|
this.manageFirstDayOfWeek();
|
||||||
|
this.initWeekCalculation();
|
||||||
this.createMonth();
|
this.createMonth();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -67,7 +67,34 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.calendar-dropdown-widget .calendar-header .dropdown-toggle::after {
|
.calendar-dropdown-widget .calendar-header .dropdown-toggle::after {
|
||||||
border: unset; /* Disable the dropdown arrow */
|
border: unset;
|
||||||
|
/* Disable the dropdown arrow */
|
||||||
|
}
|
||||||
|
|
||||||
|
.calendar-container {
|
||||||
|
display: flex;
|
||||||
|
}
|
||||||
|
|
||||||
|
.calendar-dropdown-widget .calendar-week-numbers {
|
||||||
|
width: 30px;
|
||||||
|
border-right: 1px solid var(--main-border-color);
|
||||||
|
padding-right: 5px;
|
||||||
|
margin-right: 5px;
|
||||||
|
padding-top: 2.4rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.calendar-dropdown-widget .calendar-week-number {
|
||||||
|
/* height: 2.4rem; */
|
||||||
|
/* line-height: 2.4rem; */
|
||||||
|
text-align: center;
|
||||||
|
color: var(--muted-text-color);
|
||||||
|
font-size: 0.9em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.calendar-main {
|
||||||
|
flex: 1;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
}
|
}
|
||||||
|
|
||||||
.calendar-dropdown-widget .calendar-week {
|
.calendar-dropdown-widget .calendar-week {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user