[WEB-5158] chore: calendar start of week alignment fix and code refactoring #7978
This commit is contained in:
parent
f94da68597
commit
38cdf756a5
3 changed files with 56 additions and 9 deletions
|
|
@ -1,10 +1,13 @@
|
|||
import { observable, action, makeObservable, runInAction, computed } from "mobx";
|
||||
import { observable, action, makeObservable, runInAction, computed, reaction } from "mobx";
|
||||
|
||||
// helpers
|
||||
import { computedFn } from "mobx-utils";
|
||||
import type { ICalendarPayload, ICalendarWeek } from "@plane/types";
|
||||
import { EStartOfTheWeek } from "@plane/types";
|
||||
import { generateCalendarData, getWeekNumberOfDate } from "@plane/utils";
|
||||
// types
|
||||
import type { IIssueRootStore } from "./root.store";
|
||||
|
||||
export interface ICalendarStore {
|
||||
calendarFilters: {
|
||||
activeMonthDate: Date;
|
||||
|
|
@ -15,6 +18,7 @@ export interface ICalendarStore {
|
|||
// action
|
||||
updateCalendarFilters: (filters: Partial<{ activeMonthDate: Date; activeWeekDate: Date }>) => void;
|
||||
updateCalendarPayload: (date: Date) => void;
|
||||
regenerateCalendar: () => void;
|
||||
|
||||
// computed
|
||||
allWeeksOfActiveMonth:
|
||||
|
|
@ -38,8 +42,10 @@ export class CalendarStore implements ICalendarStore {
|
|||
activeWeekDate: new Date(),
|
||||
};
|
||||
calendarPayload: ICalendarPayload | null = null;
|
||||
// root store
|
||||
rootStore;
|
||||
|
||||
constructor() {
|
||||
constructor(_rootStore: IIssueRootStore) {
|
||||
makeObservable(this, {
|
||||
loader: observable.ref,
|
||||
error: observable.ref,
|
||||
|
|
@ -51,6 +57,7 @@ export class CalendarStore implements ICalendarStore {
|
|||
// actions
|
||||
updateCalendarFilters: action,
|
||||
updateCalendarPayload: action,
|
||||
regenerateCalendar: action,
|
||||
|
||||
//computed
|
||||
allWeeksOfActiveMonth: computed,
|
||||
|
|
@ -58,7 +65,17 @@ export class CalendarStore implements ICalendarStore {
|
|||
allDaysOfActiveWeek: computed,
|
||||
});
|
||||
|
||||
this.rootStore = _rootStore;
|
||||
this.initCalendar();
|
||||
|
||||
// Watch for changes in startOfWeek preference and regenerate calendar
|
||||
reaction(
|
||||
() => this.rootStore.rootStore.user.userProfile.data?.start_of_the_week,
|
||||
() => {
|
||||
// Regenerate calendar when startOfWeek preference changes
|
||||
this.regenerateCalendar();
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
get allWeeksOfActiveMonth() {
|
||||
|
|
@ -138,14 +155,32 @@ export class CalendarStore implements ICalendarStore {
|
|||
if (!this.calendarPayload) return null;
|
||||
|
||||
const nextDate = new Date(date);
|
||||
const startOfWeek = this.rootStore.rootStore.user.userProfile.data?.start_of_the_week ?? EStartOfTheWeek.SUNDAY;
|
||||
|
||||
runInAction(() => {
|
||||
this.calendarPayload = generateCalendarData(this.calendarPayload, nextDate);
|
||||
this.calendarPayload = generateCalendarData(this.calendarPayload, nextDate, startOfWeek);
|
||||
});
|
||||
};
|
||||
|
||||
initCalendar = () => {
|
||||
const newCalendarPayload = generateCalendarData(null, new Date());
|
||||
const startOfWeek = this.rootStore.rootStore.user.userProfile.data?.start_of_the_week ?? EStartOfTheWeek.SUNDAY;
|
||||
const newCalendarPayload = generateCalendarData(null, new Date(), startOfWeek);
|
||||
|
||||
runInAction(() => {
|
||||
this.calendarPayload = newCalendarPayload;
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Force complete regeneration of calendar data
|
||||
* This should be called when startOfWeek preference changes
|
||||
*/
|
||||
regenerateCalendar = () => {
|
||||
const startOfWeek = this.rootStore.rootStore.user.userProfile.data?.start_of_the_week ?? EStartOfTheWeek.SUNDAY;
|
||||
const { activeMonthDate } = this.calendarFilters;
|
||||
|
||||
// Force complete regeneration by passing null to clear all cached data
|
||||
const newCalendarPayload = generateCalendarData(null, activeMonthDate, startOfWeek);
|
||||
|
||||
runInAction(() => {
|
||||
this.calendarPayload = newCalendarPayload;
|
||||
|
|
|
|||
|
|
@ -266,7 +266,7 @@ export class IssueRootStore implements IIssueRootStore {
|
|||
this.archivedIssues = new ArchivedIssues(this, this.archivedIssuesFilter);
|
||||
|
||||
this.issueKanBanView = new IssueKanBanViewStore(this);
|
||||
this.issueCalendarView = new CalendarStore();
|
||||
this.issueCalendarView = new CalendarStore(this);
|
||||
|
||||
this.projectEpicsFilter = new ProjectEpicsFilter(this);
|
||||
this.projectEpics = new ProjectEpics(this, this.projectEpicsFilter);
|
||||
|
|
|
|||
|
|
@ -7,9 +7,14 @@ import { getWeekNumberOfDate, renderFormattedPayloadDate } from "./datetime";
|
|||
* @returns {ICalendarPayload} calendar payload to render the calendar
|
||||
* @param {ICalendarPayload | null} currentStructure current calendar payload
|
||||
* @param {Date} startDate date of the month to render
|
||||
* @param {EStartOfTheWeek} startOfWeek the day to start the week on
|
||||
* @description Returns calendar payload to render the calendar, if currentStructure is null, it will generate the payload for the month of startDate, else it will construct the payload for the month of startDate and append it to the currentStructure
|
||||
*/
|
||||
export const generateCalendarData = (currentStructure: ICalendarPayload | null, startDate: Date): ICalendarPayload => {
|
||||
export const generateCalendarData = (
|
||||
currentStructure: ICalendarPayload | null,
|
||||
startDate: Date,
|
||||
startOfWeek: EStartOfTheWeek = EStartOfTheWeek.SUNDAY
|
||||
): ICalendarPayload => {
|
||||
const calendarData: ICalendarPayload = currentStructure ?? {};
|
||||
|
||||
const startMonth = startDate.getMonth();
|
||||
|
|
@ -19,10 +24,15 @@ export const generateCalendarData = (currentStructure: ICalendarPayload | null,
|
|||
const year = currentDate.getFullYear();
|
||||
const month = currentDate.getMonth();
|
||||
const totalDaysInMonth = new Date(year, month + 1, 0).getDate();
|
||||
const firstDayOfMonth = new Date(year, month, 1).getDay(); // Sunday is 0, Monday is 1, ..., Saturday is 6
|
||||
const firstDayOfMonthRaw = new Date(year, month, 1).getDay(); // Sunday is 0, Monday is 1, ..., Saturday is 6
|
||||
|
||||
// Adjust firstDayOfMonth based on startOfWeek preference
|
||||
// This calculates how many empty cells we need at the start of the calendar
|
||||
const firstDayOfMonth = (firstDayOfMonthRaw - startOfWeek + 7) % 7;
|
||||
|
||||
calendarData[`y-${year}`] ||= {};
|
||||
calendarData[`y-${year}`][`m-${month}`] ||= {};
|
||||
// Always reset the month data to ensure clean regeneration with correct startOfWeek
|
||||
calendarData[`y-${year}`][`m-${month}`] = {};
|
||||
|
||||
const numWeeks = Math.ceil((totalDaysInMonth + firstDayOfMonth) / 7);
|
||||
|
||||
|
|
@ -50,7 +60,9 @@ export const generateCalendarData = (currentStructure: ICalendarPayload | null,
|
|||
};
|
||||
}
|
||||
|
||||
calendarData[`y-${year}`][`m-${month}`][`w-${weekNumber}`] = currentWeekObject;
|
||||
// Use sequential week index instead of calculated week number for the key
|
||||
// This ensures weeks are grouped correctly regardless of startOfWeek preference
|
||||
calendarData[`y-${year}`][`m-${month}`][`w-${week}`] = currentWeekObject;
|
||||
}
|
||||
|
||||
return calendarData;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue