mirror of
https://github.com/taskgenius/taskgenius-plugin.git
synced 2026-07-22 06:40:25 +00:00
refactor(calendar): use built-in DateFnsAdapter from @taskgenius/calendar
Remove redundant custom date adapter implementations in favor of the DateFnsAdapter exported directly from @taskgenius/calendar library. - Delete local DateFnsAdapter utility class - Remove inline NormalizedDateFnsAdapter from calendar component - Import DateFnsAdapter from @taskgenius/calendar package
This commit is contained in:
parent
82a20200a3
commit
5fb5ff6268
2 changed files with 3 additions and 476 deletions
|
|
@ -25,6 +25,7 @@ import {
|
|||
import {
|
||||
Calendar,
|
||||
type DateAdapter,
|
||||
DateFnsAdapter,
|
||||
hideWeekends,
|
||||
workingHours,
|
||||
onlyDays,
|
||||
|
|
@ -82,171 +83,6 @@ export interface CalendarEvent extends Task {
|
|||
badge?: boolean;
|
||||
}
|
||||
|
||||
class NormalizedDateFnsAdapter implements DateAdapter<Date> {
|
||||
constructor(private readonly fns: typeof dateFns) {}
|
||||
|
||||
private normalizeFormat(formatStr?: string) {
|
||||
if (!formatStr) return formatStr;
|
||||
// Align legacy moment-style tokens with date-fns v4 requirements
|
||||
return formatStr
|
||||
.replace(/Y{2,4}/g, (token) => token.toLowerCase())
|
||||
.replace(/D{1,2}/g, (token) => token.toLowerCase());
|
||||
}
|
||||
|
||||
create(date?: string | Date) {
|
||||
if (!date) return new Date();
|
||||
if (date instanceof Date) return new Date(date);
|
||||
return this.fns.parseISO(date);
|
||||
}
|
||||
|
||||
parse(dateStr: string, formatStr?: string) {
|
||||
const normalizedFormat = this.normalizeFormat(formatStr);
|
||||
if (!normalizedFormat) {
|
||||
return this.fns.parseISO(dateStr);
|
||||
}
|
||||
return this.fns.parse(dateStr, normalizedFormat, new Date());
|
||||
}
|
||||
|
||||
format(date: Date, formatStr: string) {
|
||||
return this.fns.format(
|
||||
date,
|
||||
this.normalizeFormat(formatStr) ?? formatStr,
|
||||
);
|
||||
}
|
||||
|
||||
year(date: Date) {
|
||||
return this.fns.getYear(date);
|
||||
}
|
||||
|
||||
month(date: Date) {
|
||||
return this.fns.getMonth(date);
|
||||
}
|
||||
|
||||
date(date: Date) {
|
||||
return this.fns.getDate(date);
|
||||
}
|
||||
|
||||
day(date: Date) {
|
||||
return this.fns.getDay(date);
|
||||
}
|
||||
|
||||
hour(date: Date) {
|
||||
return this.fns.getHours(date);
|
||||
}
|
||||
|
||||
minute(date: Date) {
|
||||
return this.fns.getMinutes(date);
|
||||
}
|
||||
|
||||
setHour(date: Date, hour: number) {
|
||||
return this.fns.setHours(date, hour);
|
||||
}
|
||||
|
||||
setMinute(date: Date, minute: number) {
|
||||
return this.fns.setMinutes(date, minute);
|
||||
}
|
||||
|
||||
add(date: Date, amount: number, unit: string) {
|
||||
switch (unit) {
|
||||
case "year":
|
||||
return this.fns.addYears(date, amount);
|
||||
case "month":
|
||||
return this.fns.addMonths(date, amount);
|
||||
case "week":
|
||||
return this.fns.addWeeks(date, amount);
|
||||
case "day":
|
||||
return this.fns.addDays(date, amount);
|
||||
case "hour":
|
||||
return this.fns.addHours(date, amount);
|
||||
case "minute":
|
||||
return this.fns.addMinutes(date, amount);
|
||||
default:
|
||||
return date;
|
||||
}
|
||||
}
|
||||
|
||||
diff(date1: Date, date2: Date, unit: string) {
|
||||
switch (unit) {
|
||||
case "year":
|
||||
return this.fns.differenceInYears(date1, date2);
|
||||
case "month":
|
||||
return this.fns.differenceInMonths(date1, date2);
|
||||
case "week":
|
||||
return this.fns.differenceInWeeks(date1, date2);
|
||||
case "day":
|
||||
return this.fns.differenceInDays(date1, date2);
|
||||
case "hour":
|
||||
return this.fns.differenceInHours(date1, date2);
|
||||
case "minute":
|
||||
return this.fns.differenceInMinutes(date1, date2);
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
startOf(date: Date, unit: string) {
|
||||
switch (unit) {
|
||||
case "year":
|
||||
return this.fns.startOfYear(date);
|
||||
case "month":
|
||||
return this.fns.startOfMonth(date);
|
||||
case "week":
|
||||
return this.fns.startOfWeek(date);
|
||||
case "day":
|
||||
return this.fns.startOfDay(date);
|
||||
case "hour":
|
||||
return this.fns.startOfHour(date);
|
||||
case "minute":
|
||||
return this.fns.startOfMinute(date);
|
||||
default:
|
||||
return date;
|
||||
}
|
||||
}
|
||||
|
||||
endOf(date: Date, unit: string) {
|
||||
switch (unit) {
|
||||
case "year":
|
||||
return this.fns.endOfYear(date);
|
||||
case "month":
|
||||
return this.fns.endOfMonth(date);
|
||||
case "week":
|
||||
return this.fns.endOfWeek(date);
|
||||
case "day":
|
||||
return this.fns.endOfDay(date);
|
||||
case "hour":
|
||||
return this.fns.endOfHour(date);
|
||||
case "minute":
|
||||
return this.fns.endOfMinute(date);
|
||||
default:
|
||||
return date;
|
||||
}
|
||||
}
|
||||
|
||||
isBefore(date1: Date, date2: Date, unit?: string) {
|
||||
if (!unit) return this.fns.isBefore(date1, date2);
|
||||
return this.fns.isBefore(
|
||||
this.startOf(date1, unit),
|
||||
this.startOf(date2, unit),
|
||||
);
|
||||
}
|
||||
|
||||
isAfter(date1: Date, date2: Date, unit?: string) {
|
||||
if (!unit) return this.fns.isAfter(date1, date2);
|
||||
return this.fns.isAfter(
|
||||
this.startOf(date1, unit),
|
||||
this.startOf(date2, unit),
|
||||
);
|
||||
}
|
||||
|
||||
isSame(date1: Date, date2: Date, unit?: string) {
|
||||
if (!unit) return this.fns.isEqual(date1, date2);
|
||||
return this.fns.isEqual(
|
||||
this.startOf(date1, unit),
|
||||
this.startOf(date2, unit),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Main CalendarComponent class
|
||||
*/
|
||||
|
|
@ -886,7 +722,7 @@ export class CalendarComponent extends Component {
|
|||
},
|
||||
// Use custom view registry for agenda/year views
|
||||
viewRegistry: isAgendaOrYear ? this.viewRegistry : undefined,
|
||||
dateAdapter: new NormalizedDateFnsAdapter(dateFns),
|
||||
dateAdapter: new DateFnsAdapter(dateFns),
|
||||
events: this.convertTasksToTGEvents(),
|
||||
showEventCounts: cc.showEventCounts ?? true,
|
||||
dateFormats: {
|
||||
|
|
@ -974,7 +810,7 @@ export class CalendarComponent extends Component {
|
|||
)
|
||||
: undefined,
|
||||
},
|
||||
dateAdapter: new NormalizedDateFnsAdapter(dateFns),
|
||||
dateAdapter: new DateFnsAdapter(dateFns),
|
||||
events: this.convertTasksToTGEvents(),
|
||||
showEventCounts: true,
|
||||
dateFormats: {
|
||||
|
|
|
|||
|
|
@ -1,309 +0,0 @@
|
|||
/**
|
||||
* DateFnsAdapter - Adapter for @taskgenius/calendar using date-fns
|
||||
*
|
||||
* This adapter bridges date-fns with @taskgenius/calendar's DateAdapter interface,
|
||||
* allowing the calendar to use date-fns for all date operations.
|
||||
*/
|
||||
|
||||
import {
|
||||
parse,
|
||||
format,
|
||||
startOfDay,
|
||||
startOfWeek,
|
||||
startOfMonth,
|
||||
startOfYear,
|
||||
endOfDay,
|
||||
endOfWeek,
|
||||
endOfMonth,
|
||||
endOfYear,
|
||||
addDays,
|
||||
addWeeks,
|
||||
addMonths,
|
||||
addYears,
|
||||
subDays,
|
||||
subWeeks,
|
||||
subMonths,
|
||||
subYears,
|
||||
differenceInDays,
|
||||
differenceInWeeks,
|
||||
differenceInMonths,
|
||||
differenceInYears,
|
||||
isSameDay,
|
||||
isSameWeek,
|
||||
isSameMonth,
|
||||
isSameYear,
|
||||
isBefore,
|
||||
isAfter,
|
||||
getDay,
|
||||
getDaysInMonth,
|
||||
isValid,
|
||||
parseISO,
|
||||
} from "date-fns";
|
||||
|
||||
/**
|
||||
* Time unit types supported by the adapter
|
||||
*/
|
||||
type TimeUnit = "day" | "week" | "month" | "year" | "hour" | "minute";
|
||||
|
||||
/**
|
||||
* DateAdapter interface that must be implemented
|
||||
* This is the contract expected by @taskgenius/calendar
|
||||
*/
|
||||
interface DateAdapter<T> {
|
||||
create(date?: string | Date | T): T;
|
||||
parse(dateStr: string, format?: string): T;
|
||||
format(date: T, format: string): string;
|
||||
startOf(date: T, unit: TimeUnit): T;
|
||||
endOf(date: T, unit: TimeUnit): T;
|
||||
add(date: T, amount: number, unit: TimeUnit): T;
|
||||
subtract(date: T, amount: number, unit: TimeUnit): T;
|
||||
diff(date1: T, date2: T, unit: TimeUnit): number;
|
||||
isSame(date1: T, date2: T, unit?: TimeUnit): boolean;
|
||||
isBefore(date: T, compare: T): boolean;
|
||||
isAfter(date: T, compare: T): boolean;
|
||||
getDay(date: T): number;
|
||||
getDaysInMonth(date: T): number;
|
||||
}
|
||||
|
||||
/**
|
||||
* DateFnsAdapter implementation using date-fns library
|
||||
*/
|
||||
export class DateFnsAdapter implements DateAdapter<Date> {
|
||||
/**
|
||||
* Create a Date object from various input types
|
||||
*/
|
||||
create(date?: string | Date): Date {
|
||||
if (!date) {
|
||||
return new Date();
|
||||
}
|
||||
if (date instanceof Date) {
|
||||
return new Date(date);
|
||||
}
|
||||
if (typeof date === "string") {
|
||||
// Try to parse ISO format first
|
||||
const parsed = parseISO(date);
|
||||
if (isValid(parsed)) {
|
||||
return parsed;
|
||||
}
|
||||
// Fallback to native Date constructor
|
||||
return new Date(date);
|
||||
}
|
||||
return new Date();
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse a date string with optional format
|
||||
*/
|
||||
parse(dateStr: string, formatStr?: string): Date {
|
||||
if (!formatStr) {
|
||||
// Default to ISO format
|
||||
const parsed = parseISO(dateStr);
|
||||
if (isValid(parsed)) {
|
||||
return parsed;
|
||||
}
|
||||
return new Date(dateStr);
|
||||
}
|
||||
|
||||
// Use date-fns parse with format
|
||||
const parsed = parse(dateStr, formatStr, new Date());
|
||||
if (!isValid(parsed)) {
|
||||
throw new Error(`Invalid date string: ${dateStr}`);
|
||||
}
|
||||
return parsed;
|
||||
}
|
||||
|
||||
/**
|
||||
* Format a date to string
|
||||
*/
|
||||
format(date: Date, formatStr: string): string {
|
||||
return format(date, formatStr);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the start of a time unit
|
||||
*/
|
||||
startOf(date: Date, unit: TimeUnit): Date {
|
||||
switch (unit) {
|
||||
case "day":
|
||||
return startOfDay(date);
|
||||
case "week":
|
||||
return startOfWeek(date);
|
||||
case "month":
|
||||
return startOfMonth(date);
|
||||
case "year":
|
||||
return startOfYear(date);
|
||||
case "hour":
|
||||
// date-fns doesn't have startOfHour, so we set minutes and seconds to 0
|
||||
const hourStart = new Date(date);
|
||||
hourStart.setMinutes(0, 0, 0);
|
||||
return hourStart;
|
||||
case "minute":
|
||||
// Set seconds and milliseconds to 0
|
||||
const minuteStart = new Date(date);
|
||||
minuteStart.setSeconds(0, 0);
|
||||
return minuteStart;
|
||||
default:
|
||||
return startOfDay(date);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the end of a time unit
|
||||
*/
|
||||
endOf(date: Date, unit: TimeUnit): Date {
|
||||
switch (unit) {
|
||||
case "day":
|
||||
return endOfDay(date);
|
||||
case "week":
|
||||
return endOfWeek(date);
|
||||
case "month":
|
||||
return endOfMonth(date);
|
||||
case "year":
|
||||
return endOfYear(date);
|
||||
case "hour":
|
||||
// Set to last millisecond of the hour
|
||||
const hourEnd = new Date(date);
|
||||
hourEnd.setMinutes(59, 59, 999);
|
||||
return hourEnd;
|
||||
case "minute":
|
||||
// Set to last millisecond of the minute
|
||||
const minuteEnd = new Date(date);
|
||||
minuteEnd.setSeconds(59, 999);
|
||||
return minuteEnd;
|
||||
default:
|
||||
return endOfDay(date);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Add time to a date
|
||||
*/
|
||||
add(date: Date, amount: number, unit: TimeUnit): Date {
|
||||
switch (unit) {
|
||||
case "day":
|
||||
return addDays(date, amount);
|
||||
case "week":
|
||||
return addWeeks(date, amount);
|
||||
case "month":
|
||||
return addMonths(date, amount);
|
||||
case "year":
|
||||
return addYears(date, amount);
|
||||
case "hour":
|
||||
return new Date(date.getTime() + amount * 60 * 60 * 1000);
|
||||
case "minute":
|
||||
return new Date(date.getTime() + amount * 60 * 1000);
|
||||
default:
|
||||
return addDays(date, amount);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Subtract time from a date
|
||||
*/
|
||||
subtract(date: Date, amount: number, unit: TimeUnit): Date {
|
||||
switch (unit) {
|
||||
case "day":
|
||||
return subDays(date, amount);
|
||||
case "week":
|
||||
return subWeeks(date, amount);
|
||||
case "month":
|
||||
return subMonths(date, amount);
|
||||
case "year":
|
||||
return subYears(date, amount);
|
||||
case "hour":
|
||||
return new Date(date.getTime() - amount * 60 * 60 * 1000);
|
||||
case "minute":
|
||||
return new Date(date.getTime() - amount * 60 * 1000);
|
||||
default:
|
||||
return subDays(date, amount);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculate difference between two dates
|
||||
*/
|
||||
diff(date1: Date, date2: Date, unit: TimeUnit): number {
|
||||
switch (unit) {
|
||||
case "day":
|
||||
return differenceInDays(date1, date2);
|
||||
case "week":
|
||||
return differenceInWeeks(date1, date2);
|
||||
case "month":
|
||||
return differenceInMonths(date1, date2);
|
||||
case "year":
|
||||
return differenceInYears(date1, date2);
|
||||
case "hour":
|
||||
return Math.floor((date1.getTime() - date2.getTime()) / (60 * 60 * 1000));
|
||||
case "minute":
|
||||
return Math.floor((date1.getTime() - date2.getTime()) / (60 * 1000));
|
||||
default:
|
||||
return differenceInDays(date1, date2);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if two dates are the same
|
||||
*/
|
||||
isSame(date1: Date, date2: Date, unit?: TimeUnit): boolean {
|
||||
if (!unit) {
|
||||
return date1.getTime() === date2.getTime();
|
||||
}
|
||||
|
||||
switch (unit) {
|
||||
case "day":
|
||||
return isSameDay(date1, date2);
|
||||
case "week":
|
||||
return isSameWeek(date1, date2);
|
||||
case "month":
|
||||
return isSameMonth(date1, date2);
|
||||
case "year":
|
||||
return isSameYear(date1, date2);
|
||||
case "hour":
|
||||
return (
|
||||
isSameDay(date1, date2) &&
|
||||
date1.getHours() === date2.getHours()
|
||||
);
|
||||
case "minute":
|
||||
return (
|
||||
isSameDay(date1, date2) &&
|
||||
date1.getHours() === date2.getHours() &&
|
||||
date1.getMinutes() === date2.getMinutes()
|
||||
);
|
||||
default:
|
||||
return isSameDay(date1, date2);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if date is before compare date
|
||||
*/
|
||||
isBefore(date: Date, compare: Date): boolean {
|
||||
return isBefore(date, compare);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if date is after compare date
|
||||
*/
|
||||
isAfter(date: Date, compare: Date): boolean {
|
||||
return isAfter(date, compare);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get day of week (0 = Sunday, 6 = Saturday)
|
||||
*/
|
||||
getDay(date: Date): number {
|
||||
return getDay(date);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get number of days in the month
|
||||
*/
|
||||
getDaysInMonth(date: Date): number {
|
||||
return getDaysInMonth(date);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Export a singleton instance for convenience
|
||||
*/
|
||||
export const dateFnsAdapter = new DateFnsAdapter();
|
||||
Loading…
Reference in a new issue