Refactoring; Separated EventGrouping class into separate classes for Day, Week, Month. Logic moved upstream into Calendar class. Simplified render selection in interface
This commit is contained in:
parent
1e3688ca04
commit
722ddb41e5
@ -1,13 +1,17 @@
|
||||
import { GroupTypes } from "../types";
|
||||
import Config from "../Config/Config";
|
||||
import Events from "../Events/";
|
||||
import EventGrouping from "../EventGrouping";
|
||||
import { DayGrouping, WeekGrouping, MonthGrouping } from "../EventGrouping";
|
||||
import {
|
||||
DayRenderer,
|
||||
WeekRenderer,
|
||||
MonthRenderer,
|
||||
} from "../EventGroupingHtmlRenderer";
|
||||
|
||||
export default class Calendar {
|
||||
private readonly jsonContent: object;
|
||||
public config: Config;
|
||||
public events: Events;
|
||||
public eventGrouping: EventGrouping;
|
||||
|
||||
constructor(json) {
|
||||
this.jsonContent = json;
|
||||
@ -15,9 +19,22 @@ export default class Calendar {
|
||||
groupType: json["group"] ? json["group"].charAt(0) : GroupTypes.Day,
|
||||
});
|
||||
this.events = new Events(json["events"]);
|
||||
this.eventGrouping = new EventGrouping(
|
||||
this.events.sortedEvents,
|
||||
this.config.groupType
|
||||
);
|
||||
}
|
||||
|
||||
render(): HTMLDivElement {
|
||||
switch (this.config.groupType) {
|
||||
case GroupTypes.Day:
|
||||
return new DayRenderer(
|
||||
new DayGrouping(this.events.sortedEvents)
|
||||
).render();
|
||||
case GroupTypes.Week:
|
||||
return new WeekRenderer(
|
||||
new WeekGrouping(this.events.sortedEvents)
|
||||
).render();
|
||||
case GroupTypes.Month:
|
||||
return new MonthRenderer(
|
||||
new MonthGrouping(this.events.sortedEvents)
|
||||
).render();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
34
src/EventGrouping/DayGrouping.ts
Normal file
34
src/EventGrouping/DayGrouping.ts
Normal file
@ -0,0 +1,34 @@
|
||||
import EventGrouping from "./EventGrouping";
|
||||
import { Event, Groups } from "../types";
|
||||
import { add, differenceInCalendarDays } from "date-fns";
|
||||
|
||||
export default class DayGrouping extends EventGrouping {
|
||||
constructor(sortedEvents: Event[]) {
|
||||
super(sortedEvents);
|
||||
this.groups = this.group();
|
||||
}
|
||||
|
||||
group(): Groups {
|
||||
const numberOfGroups = differenceInCalendarDays(
|
||||
this.lastEvent.date,
|
||||
this.firstEvent.date
|
||||
);
|
||||
|
||||
return this.sortedEvents.reduce((prev, event) => {
|
||||
const groupNumber = differenceInCalendarDays(
|
||||
event.date,
|
||||
this.firstEvent.date
|
||||
);
|
||||
|
||||
prev[groupNumber].push(event);
|
||||
|
||||
return prev;
|
||||
}, this.generateEmptyGroups(numberOfGroups));
|
||||
}
|
||||
|
||||
public getDateFromGroupIndex(index: number): Date {
|
||||
const startDate = this.firstEvent.date;
|
||||
|
||||
return add(startDate, { days: index });
|
||||
}
|
||||
}
|
||||
28
src/EventGrouping/EventGrouping.ts
Normal file
28
src/EventGrouping/EventGrouping.ts
Normal file
@ -0,0 +1,28 @@
|
||||
import { Event, Groups } from "../types";
|
||||
|
||||
export default abstract class EventGrouping {
|
||||
protected readonly sortedEvents: Event[];
|
||||
protected readonly firstEvent: Event;
|
||||
protected readonly lastEvent: Event;
|
||||
public groups: Groups;
|
||||
|
||||
protected constructor(sortedEvents: Event[]) {
|
||||
this.sortedEvents = sortedEvents;
|
||||
this.firstEvent = this.sortedEvents[0];
|
||||
this.lastEvent = this.sortedEvents[this.sortedEvents.length - 1];
|
||||
}
|
||||
|
||||
protected generateEmptyGroups(length: number): Groups {
|
||||
const groups = [];
|
||||
|
||||
for (let i = 0; i <= length; i += 1) {
|
||||
groups.push([]);
|
||||
}
|
||||
|
||||
return groups;
|
||||
}
|
||||
|
||||
public abstract getDateFromGroupIndex(index: number): Date;
|
||||
|
||||
public abstract group(): Groups;
|
||||
}
|
||||
34
src/EventGrouping/MonthGrouping.ts
Normal file
34
src/EventGrouping/MonthGrouping.ts
Normal file
@ -0,0 +1,34 @@
|
||||
import EventGrouping from "./EventGrouping";
|
||||
import { Event, Groups } from "../types";
|
||||
import { add, differenceInCalendarMonths } from "date-fns";
|
||||
|
||||
export default class MonthGrouping extends EventGrouping {
|
||||
constructor(sortedEvents: Event[]) {
|
||||
super(sortedEvents);
|
||||
this.groups = this.group();
|
||||
}
|
||||
|
||||
group(): Groups {
|
||||
const numberOfGroups = differenceInCalendarMonths(
|
||||
this.lastEvent.date,
|
||||
this.firstEvent.date
|
||||
);
|
||||
|
||||
return this.sortedEvents.reduce((prev, event) => {
|
||||
const groupNumber = differenceInCalendarMonths(
|
||||
event.date,
|
||||
this.firstEvent.date
|
||||
);
|
||||
|
||||
prev[groupNumber].push(event);
|
||||
|
||||
return prev;
|
||||
}, this.generateEmptyGroups(numberOfGroups));
|
||||
}
|
||||
|
||||
public getDateFromGroupIndex(index: number): Date {
|
||||
const startDate = this.firstEvent.date;
|
||||
|
||||
return add(startDate, { months: index });
|
||||
}
|
||||
}
|
||||
34
src/EventGrouping/WeekGrouping.ts
Normal file
34
src/EventGrouping/WeekGrouping.ts
Normal file
@ -0,0 +1,34 @@
|
||||
import EventGrouping from "./EventGrouping";
|
||||
import { Event, Groups } from "../types";
|
||||
import { add, differenceInCalendarWeeks } from "date-fns";
|
||||
|
||||
export default class WeekGrouping extends EventGrouping {
|
||||
constructor(sortedEvents: Event[]) {
|
||||
super(sortedEvents);
|
||||
this.groups = this.group();
|
||||
}
|
||||
|
||||
group(): Groups {
|
||||
const numberOfGroups = differenceInCalendarWeeks(
|
||||
this.lastEvent.date,
|
||||
this.firstEvent.date
|
||||
);
|
||||
|
||||
return this.sortedEvents.reduce((prev, event) => {
|
||||
const groupNumber = differenceInCalendarWeeks(
|
||||
event.date,
|
||||
this.firstEvent.date
|
||||
);
|
||||
|
||||
prev[groupNumber].push(event);
|
||||
|
||||
return prev;
|
||||
}, this.generateEmptyGroups(numberOfGroups));
|
||||
}
|
||||
|
||||
public getDateFromGroupIndex(index: number): Date {
|
||||
const startDate = this.firstEvent.date;
|
||||
|
||||
return add(startDate, { weeks: index });
|
||||
}
|
||||
}
|
||||
@ -1,57 +0,0 @@
|
||||
const EventGrouping = require("./index").default;
|
||||
const { GroupTypes } = require("../types");
|
||||
|
||||
const mockSortedEvents = [
|
||||
{
|
||||
date: new Date(2022, 3, 20),
|
||||
title: "first day of spring",
|
||||
},
|
||||
{
|
||||
date: new Date(2022, 3, 25),
|
||||
title: "my birthday",
|
||||
},
|
||||
{
|
||||
date: new Date(2022, 3, 25),
|
||||
title: "buy cake for 27th",
|
||||
},
|
||||
{
|
||||
date: new Date(2022, 3, 27),
|
||||
title: "d's birthday",
|
||||
},
|
||||
];
|
||||
|
||||
describe("groupEventsByDay should", () => {
|
||||
const eventGrouping = new EventGrouping(mockSortedEvents, GroupTypes.Day);
|
||||
|
||||
test("generate the correct number of groups", () => {
|
||||
expect(eventGrouping.groups.length).toEqual(8);
|
||||
});
|
||||
|
||||
test("place into the same group, events that occur on the same day", () => {
|
||||
expect(eventGrouping.groups[5].length).toEqual(2);
|
||||
});
|
||||
});
|
||||
|
||||
describe("groupEventsByWeek should", () => {
|
||||
const eventGrouping = new EventGrouping(mockSortedEvents, GroupTypes.Week);
|
||||
|
||||
test("generate the correct number of groups", () => {
|
||||
expect(eventGrouping.groups.length).toEqual(2);
|
||||
});
|
||||
|
||||
test("place into the same group, events that occur on the same week", () => {
|
||||
expect(eventGrouping.groups[1].length).toEqual(3);
|
||||
});
|
||||
});
|
||||
|
||||
describe("groupEventsByMonth should", () => {
|
||||
const eventGrouping = new EventGrouping(mockSortedEvents, GroupTypes.Month);
|
||||
|
||||
test("generate the correct number of groups", () => {
|
||||
expect(eventGrouping.groups.length).toEqual(1);
|
||||
});
|
||||
|
||||
test("place into the same group, events that occur on the same month", () => {
|
||||
expect(eventGrouping.groups[0].length).toEqual(4);
|
||||
});
|
||||
});
|
||||
@ -1,112 +1,5 @@
|
||||
import {
|
||||
add,
|
||||
differenceInCalendarDays,
|
||||
differenceInCalendarWeeks,
|
||||
differenceInCalendarMonths,
|
||||
} from "date-fns";
|
||||
import DayGrouping from "./DayGrouping";
|
||||
import WeekGrouping from "./WeekGrouping";
|
||||
import MonthGrouping from "./MonthGrouping";
|
||||
|
||||
import { Event, Groups, GroupTypes } from "../types";
|
||||
|
||||
export default class EventGrouping {
|
||||
private readonly sortedEvents: Event[];
|
||||
private readonly firstEvent: Event;
|
||||
private readonly lastEvent: Event;
|
||||
public readonly groupType: GroupTypes;
|
||||
public readonly groups: Groups;
|
||||
|
||||
public static generateEmptyGroups(length: number): Groups {
|
||||
const groups = [];
|
||||
|
||||
for (let i = 0; i <= length; i += 1) {
|
||||
groups.push([]);
|
||||
}
|
||||
|
||||
return groups;
|
||||
}
|
||||
|
||||
constructor(sortedEvents: Event[], groupType: GroupTypes) {
|
||||
this.sortedEvents = sortedEvents;
|
||||
this.firstEvent = this.sortedEvents[0];
|
||||
this.lastEvent = this.sortedEvents[this.sortedEvents.length - 1];
|
||||
this.groupType = groupType;
|
||||
this.groups = this.group(groupType);
|
||||
}
|
||||
|
||||
private group(groupType: GroupTypes): Groups {
|
||||
switch (groupType) {
|
||||
case GroupTypes.Day:
|
||||
return this.byDay();
|
||||
case GroupTypes.Week:
|
||||
return this.byWeek();
|
||||
case GroupTypes.Month:
|
||||
return this.byMonth();
|
||||
}
|
||||
}
|
||||
|
||||
private byDay(): Groups {
|
||||
const numberOfGroups = differenceInCalendarDays(
|
||||
this.lastEvent.date,
|
||||
this.firstEvent.date
|
||||
);
|
||||
|
||||
return this.sortedEvents.reduce((prev, event) => {
|
||||
const groupNumber = differenceInCalendarDays(
|
||||
event.date,
|
||||
this.firstEvent.date
|
||||
);
|
||||
|
||||
prev[groupNumber].push(event);
|
||||
|
||||
return prev;
|
||||
}, EventGrouping.generateEmptyGroups(numberOfGroups));
|
||||
}
|
||||
|
||||
private byWeek(): Groups {
|
||||
const numberOfGroups = differenceInCalendarWeeks(
|
||||
this.lastEvent.date,
|
||||
this.firstEvent.date
|
||||
);
|
||||
|
||||
return this.sortedEvents.reduce((prev, event) => {
|
||||
const groupNumber = differenceInCalendarWeeks(
|
||||
event.date,
|
||||
this.firstEvent.date
|
||||
);
|
||||
|
||||
prev[groupNumber].push(event);
|
||||
|
||||
return prev;
|
||||
}, EventGrouping.generateEmptyGroups(numberOfGroups));
|
||||
}
|
||||
|
||||
private byMonth(): Groups {
|
||||
const numberOfGroups = differenceInCalendarMonths(
|
||||
this.lastEvent.date,
|
||||
this.firstEvent.date
|
||||
);
|
||||
|
||||
return this.sortedEvents.reduce((prev, event) => {
|
||||
const groupNumber = differenceInCalendarMonths(
|
||||
event.date,
|
||||
this.firstEvent.date
|
||||
);
|
||||
|
||||
prev[groupNumber].push(event);
|
||||
|
||||
return prev;
|
||||
}, EventGrouping.generateEmptyGroups(numberOfGroups));
|
||||
}
|
||||
|
||||
public getDateFromGroupIndex(index: number): Date {
|
||||
const startDate = this.firstEvent.date;
|
||||
|
||||
switch (this.groupType) {
|
||||
case GroupTypes.Day:
|
||||
return add(startDate, { days: index });
|
||||
case GroupTypes.Week:
|
||||
return add(startDate, { weeks: index });
|
||||
case GroupTypes.Month:
|
||||
return add(startDate, { months: index });
|
||||
}
|
||||
}
|
||||
}
|
||||
export { DayGrouping, WeekGrouping, MonthGrouping };
|
||||
|
||||
15
src/EventGrouping/tests/DayGrouping.test.ts
Normal file
15
src/EventGrouping/tests/DayGrouping.test.ts
Normal file
@ -0,0 +1,15 @@
|
||||
const { GroupTypes } = require("../../types");
|
||||
const DayGrouping = require("../DayGrouping").default;
|
||||
const mockSortedEvents = require("./mockSortedEvents").default;
|
||||
|
||||
describe("groupEventsByDay should", () => {
|
||||
const eventGrouping = new DayGrouping(mockSortedEvents, GroupTypes.Day);
|
||||
|
||||
test("generate the correct number of groups", () => {
|
||||
expect(eventGrouping.groups.length).toEqual(8);
|
||||
});
|
||||
|
||||
test("place into the same group, events that occur on the same day", () => {
|
||||
expect(eventGrouping.groups[5].length).toEqual(2);
|
||||
});
|
||||
});
|
||||
15
src/EventGrouping/tests/MonthGrouping.test.ts
Normal file
15
src/EventGrouping/tests/MonthGrouping.test.ts
Normal file
@ -0,0 +1,15 @@
|
||||
const { GroupTypes } = require("../../types");
|
||||
const MonthGrouping = require("../MonthGrouping").default;
|
||||
const mockSortedEvents = require("./mockSortedEvents").default;
|
||||
|
||||
describe("groupEventsByMonth should", () => {
|
||||
const eventGrouping = new MonthGrouping(mockSortedEvents, GroupTypes.Month);
|
||||
|
||||
test("generate the correct number of groups", () => {
|
||||
expect(eventGrouping.groups.length).toEqual(1);
|
||||
});
|
||||
|
||||
test("place into the same group, events that occur on the same month", () => {
|
||||
expect(eventGrouping.groups[0].length).toEqual(4);
|
||||
});
|
||||
});
|
||||
15
src/EventGrouping/tests/WeekGrouping.test.ts
Normal file
15
src/EventGrouping/tests/WeekGrouping.test.ts
Normal file
@ -0,0 +1,15 @@
|
||||
const { GroupTypes } = require("../../types");
|
||||
const WeekGrouping = require("../WeekGrouping").default;
|
||||
const mockSortedEvents = require("./mockSortedEvents").default;
|
||||
|
||||
describe("groupEventsByWeek should", () => {
|
||||
const eventGrouping = new WeekGrouping(mockSortedEvents, GroupTypes.Week);
|
||||
|
||||
test("generate the correct number of groups", () => {
|
||||
expect(eventGrouping.groups.length).toEqual(2);
|
||||
});
|
||||
|
||||
test("place into the same group, events that occur on the same week", () => {
|
||||
expect(eventGrouping.groups[1].length).toEqual(3);
|
||||
});
|
||||
});
|
||||
18
src/EventGrouping/tests/mockSortedEvents.ts
Normal file
18
src/EventGrouping/tests/mockSortedEvents.ts
Normal file
@ -0,0 +1,18 @@
|
||||
export default [
|
||||
{
|
||||
date: new Date(2022, 3, 20),
|
||||
title: "first day of spring",
|
||||
},
|
||||
{
|
||||
date: new Date(2022, 3, 25),
|
||||
title: "my birthday",
|
||||
},
|
||||
{
|
||||
date: new Date(2022, 3, 25),
|
||||
title: "buy cake for 27th",
|
||||
},
|
||||
{
|
||||
date: new Date(2022, 3, 27),
|
||||
title: "d's birthday",
|
||||
},
|
||||
];
|
||||
@ -1,8 +1,8 @@
|
||||
import EventGrouping from "../EventGrouping";
|
||||
import { DayGrouping } from "../EventGrouping";
|
||||
import Renderer from "./Renderer";
|
||||
|
||||
export default class DayRenderer extends Renderer {
|
||||
constructor(eventGrouping: EventGrouping) {
|
||||
constructor(eventGrouping: DayGrouping) {
|
||||
super(eventGrouping);
|
||||
this.container.className += " scale-day";
|
||||
}
|
||||
|
||||
@ -1,8 +1,8 @@
|
||||
import EventGrouping from "../EventGrouping";
|
||||
import { MonthGrouping } from "../EventGrouping";
|
||||
import Renderer from "./Renderer";
|
||||
|
||||
export default class MonthRenderer extends Renderer {
|
||||
constructor(eventGrouping: EventGrouping) {
|
||||
constructor(eventGrouping: MonthGrouping) {
|
||||
super(eventGrouping);
|
||||
this.container.className += " scale-month";
|
||||
}
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
import { format } from "date-fns";
|
||||
import { generateRandomColor } from "../utilities";
|
||||
import EventGrouping from "../EventGrouping";
|
||||
import EventGrouping from "../EventGrouping/EventGrouping";
|
||||
import { Event } from "../types";
|
||||
|
||||
export default abstract class Renderer {
|
||||
@ -105,7 +105,7 @@ export default abstract class Renderer {
|
||||
return html;
|
||||
}
|
||||
|
||||
public render() {
|
||||
public render(): HTMLDivElement {
|
||||
const groups = this.renderGroups();
|
||||
|
||||
groups.forEach((group) => this.container.appendChild(group));
|
||||
|
||||
@ -1,9 +1,10 @@
|
||||
import { getWeek } from "date-fns";
|
||||
import EventGrouping from "../EventGrouping";
|
||||
|
||||
import { WeekGrouping } from "../EventGrouping";
|
||||
import Renderer from "./Renderer";
|
||||
|
||||
export default class WeekRenderer extends Renderer {
|
||||
constructor(eventGrouping: EventGrouping) {
|
||||
constructor(eventGrouping: WeekGrouping) {
|
||||
super(eventGrouping);
|
||||
this.container.className += " scale-week";
|
||||
}
|
||||
|
||||
5
src/EventGroupingHtmlRenderer/index.ts
Normal file
5
src/EventGroupingHtmlRenderer/index.ts
Normal file
@ -0,0 +1,5 @@
|
||||
import DayRenderer from "./DayRenderer";
|
||||
import WeekRenderer from "./WeekRenderer";
|
||||
import MonthRenderer from "./MonthRenderer";
|
||||
|
||||
export { DayRenderer, WeekRenderer, MonthRenderer };
|
||||
@ -1,11 +1,6 @@
|
||||
import { GroupTypes } from "./types";
|
||||
|
||||
const YAML = require("yaml");
|
||||
|
||||
import Calendar from "./Calendar/";
|
||||
import DayRenderer from "./EventGroupingHtmlRenderer/DayRenderer";
|
||||
import WeekRenderer from "./EventGroupingHtmlRenderer/WeekRenderer";
|
||||
import MonthRenderer from "./EventGroupingHtmlRenderer/MonthRenderer";
|
||||
|
||||
export default function () {
|
||||
return {
|
||||
@ -32,27 +27,16 @@ export default function () {
|
||||
const token = tokens[idx];
|
||||
if (token.info !== "joplin-plugin-event-calendar")
|
||||
return defaultRender(tokens, idx, options, env, self);
|
||||
let jsonContent: object;
|
||||
let calendar: Calendar;
|
||||
let contentHtml = document.createElement("div");
|
||||
try {
|
||||
jsonContent = YAML.parse(markdownIt.utils.escapeHtml(token.content));
|
||||
calendar = new Calendar(jsonContent);
|
||||
switch (calendar.config.groupTypes) {
|
||||
case GroupTypes.Day:
|
||||
contentHtml = new DayRenderer(calendar.eventGrouping).render();
|
||||
break;
|
||||
case GroupTypes.Week:
|
||||
contentHtml = new WeekRenderer(calendar.eventGrouping).render();
|
||||
break;
|
||||
case GroupTypes.Month:
|
||||
contentHtml = new MonthRenderer(calendar.eventGrouping).render();
|
||||
break;
|
||||
}
|
||||
const jsonContent = YAML.parse(
|
||||
markdownIt.utils.escapeHtml(token.content)
|
||||
);
|
||||
const calendar = new Calendar(jsonContent);
|
||||
const contentHtml = calendar.render();
|
||||
return `<div class="joplin-editable">${contentHtml.outerHTML}</div>`;
|
||||
} catch (error) {
|
||||
console.log(error);
|
||||
}
|
||||
return `<div class="joplin-editable">${contentHtml.outerHTML}</div>`;
|
||||
};
|
||||
},
|
||||
assets: function () {
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user