diff --git a/src/Calendar/index.ts b/src/Calendar/index.ts index 28f199a..1acb001 100644 --- a/src/Calendar/index.ts +++ b/src/Calendar/index.ts @@ -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(); + } } } diff --git a/src/EventGrouping/DayGrouping.ts b/src/EventGrouping/DayGrouping.ts new file mode 100644 index 0000000..ee4b8b6 --- /dev/null +++ b/src/EventGrouping/DayGrouping.ts @@ -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 }); + } +} diff --git a/src/EventGrouping/EventGrouping.ts b/src/EventGrouping/EventGrouping.ts new file mode 100644 index 0000000..27930b6 --- /dev/null +++ b/src/EventGrouping/EventGrouping.ts @@ -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; +} diff --git a/src/EventGrouping/MonthGrouping.ts b/src/EventGrouping/MonthGrouping.ts new file mode 100644 index 0000000..eadcc42 --- /dev/null +++ b/src/EventGrouping/MonthGrouping.ts @@ -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 }); + } +} diff --git a/src/EventGrouping/WeekGrouping.ts b/src/EventGrouping/WeekGrouping.ts new file mode 100644 index 0000000..4af0350 --- /dev/null +++ b/src/EventGrouping/WeekGrouping.ts @@ -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 }); + } +} diff --git a/src/EventGrouping/index.test.ts b/src/EventGrouping/index.test.ts deleted file mode 100644 index 4812b56..0000000 --- a/src/EventGrouping/index.test.ts +++ /dev/null @@ -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); - }); -}); diff --git a/src/EventGrouping/index.ts b/src/EventGrouping/index.ts index 48b390d..a1874ba 100644 --- a/src/EventGrouping/index.ts +++ b/src/EventGrouping/index.ts @@ -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 }; diff --git a/src/EventGrouping/tests/DayGrouping.test.ts b/src/EventGrouping/tests/DayGrouping.test.ts new file mode 100644 index 0000000..1026497 --- /dev/null +++ b/src/EventGrouping/tests/DayGrouping.test.ts @@ -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); + }); +}); diff --git a/src/EventGrouping/tests/MonthGrouping.test.ts b/src/EventGrouping/tests/MonthGrouping.test.ts new file mode 100644 index 0000000..65e7839 --- /dev/null +++ b/src/EventGrouping/tests/MonthGrouping.test.ts @@ -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); + }); +}); diff --git a/src/EventGrouping/tests/WeekGrouping.test.ts b/src/EventGrouping/tests/WeekGrouping.test.ts new file mode 100644 index 0000000..c1d96a3 --- /dev/null +++ b/src/EventGrouping/tests/WeekGrouping.test.ts @@ -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); + }); +}); diff --git a/src/EventGrouping/tests/mockSortedEvents.ts b/src/EventGrouping/tests/mockSortedEvents.ts new file mode 100644 index 0000000..afec477 --- /dev/null +++ b/src/EventGrouping/tests/mockSortedEvents.ts @@ -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", + }, +]; diff --git a/src/EventGroupingHtmlRenderer/DayRenderer.ts b/src/EventGroupingHtmlRenderer/DayRenderer.ts index f67925d..2c40bc0 100644 --- a/src/EventGroupingHtmlRenderer/DayRenderer.ts +++ b/src/EventGroupingHtmlRenderer/DayRenderer.ts @@ -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"; } diff --git a/src/EventGroupingHtmlRenderer/MonthRenderer.ts b/src/EventGroupingHtmlRenderer/MonthRenderer.ts index e3cbf96..cc89ec0 100644 --- a/src/EventGroupingHtmlRenderer/MonthRenderer.ts +++ b/src/EventGroupingHtmlRenderer/MonthRenderer.ts @@ -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"; } diff --git a/src/EventGroupingHtmlRenderer/Renderer.ts b/src/EventGroupingHtmlRenderer/Renderer.ts index 574ee7b..0fdb0a7 100644 --- a/src/EventGroupingHtmlRenderer/Renderer.ts +++ b/src/EventGroupingHtmlRenderer/Renderer.ts @@ -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)); diff --git a/src/EventGroupingHtmlRenderer/WeekRenderer.ts b/src/EventGroupingHtmlRenderer/WeekRenderer.ts index d86a979..3c7da81 100644 --- a/src/EventGroupingHtmlRenderer/WeekRenderer.ts +++ b/src/EventGroupingHtmlRenderer/WeekRenderer.ts @@ -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"; } diff --git a/src/EventGroupingHtmlRenderer/index.ts b/src/EventGroupingHtmlRenderer/index.ts new file mode 100644 index 0000000..7debdb0 --- /dev/null +++ b/src/EventGroupingHtmlRenderer/index.ts @@ -0,0 +1,5 @@ +import DayRenderer from "./DayRenderer"; +import WeekRenderer from "./WeekRenderer"; +import MonthRenderer from "./MonthRenderer"; + +export { DayRenderer, WeekRenderer, MonthRenderer }; diff --git a/src/joplin-plugin-event-calendar.ts b/src/joplin-plugin-event-calendar.ts index 926cc08..30fb5eb 100644 --- a/src/joplin-plugin-event-calendar.ts +++ b/src/joplin-plugin-event-calendar.ts @@ -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 `
${contentHtml.outerHTML}
`; } catch (error) { console.log(error); } - return `
${contentHtml.outerHTML}
`; }; }, assets: function () {