Added option for grouping by year (for handling events that span multiple years)
This commit is contained in:
parent
1d848131a3
commit
a936de4285
@ -4,7 +4,7 @@ This is a plugin for the [Joplin](https://joplinapp.org/) note-taking app.
|
||||
|
||||
It creates a calendar view of events that have been specified using the [YAML](https://yaml.org/) syntax within a fenced block.
|
||||
|
||||
- Organises events into "groupings"; you can group events by **day**, **week** or by **month**
|
||||
- Organises events into "groupings"; you can group events by **day**, **week**, **month** or **year**
|
||||
- Focus is on readability and simplicity of content, which is why the **YAML** is simple in structure
|
||||
|
||||
###### Example Day view
|
||||
@ -13,10 +13,11 @@ It creates a calendar view of events that have been specified using the [YAML](h
|
||||
|
||||
## Features
|
||||
|
||||
- A grouping that contains no events will show the **date** (day grouping), **week number** (week grouping), or **month** (month grouping)
|
||||
- A grouping that contains no events will show the **date** (day grouping), **week number** (week grouping), **month** (month grouping), or **year** (year grouping)
|
||||
- If a grouping falls under the **current date**, it is highlighted in yellow
|
||||
- Events can be specified in **any order**
|
||||
- Events can be assigned an **icon** 🎁 such as an emoji
|
||||
- Events without an icon will use the first 2 characters from the title
|
||||
|
||||
## How to use
|
||||
|
||||
@ -40,7 +41,7 @@ Events are specified using the YAML syntax, with the following keys:
|
||||
> Sets the grouping for the view
|
||||
> - _**optional**_
|
||||
> - **default** `day`
|
||||
> - **accepts** : `day`, `week`, `month`, `d`, `w`, `m`
|
||||
> - **accepts** : `day`, `week`, `month`, `year`, `d`, `w`, `m`, `y`
|
||||
|
||||
### events:
|
||||
> Each individual event is a list with its own properties
|
||||
|
||||
@ -1,7 +1,17 @@
|
||||
import { GroupTypes } from "../types";
|
||||
import Events from "../Events/";
|
||||
import { DayGrouping, WeekGrouping, MonthGrouping } from "../EventGrouping";
|
||||
import { DayRenderer, WeekRenderer, MonthRenderer } from "../HtmlRenderer";
|
||||
import {
|
||||
DayGrouping,
|
||||
MonthGrouping,
|
||||
WeekGrouping,
|
||||
YearGrouping,
|
||||
} from "../EventGrouping";
|
||||
import {
|
||||
DayRenderer,
|
||||
MonthRenderer,
|
||||
WeekRenderer,
|
||||
YearRenderer,
|
||||
} from "../HtmlRenderer";
|
||||
|
||||
export default class Calendar {
|
||||
public readonly jsonContent: object;
|
||||
@ -30,6 +40,10 @@ export default class Calendar {
|
||||
return new MonthRenderer(
|
||||
new MonthGrouping(this.events.sortedEvents)
|
||||
).render();
|
||||
case GroupTypes.Year:
|
||||
return new YearRenderer(
|
||||
new YearGrouping(this.events.sortedEvents)
|
||||
).render();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
42
src/EventGrouping/YearGrouping.ts
Normal file
42
src/EventGrouping/YearGrouping.ts
Normal file
@ -0,0 +1,42 @@
|
||||
import EventGrouping from "./EventGrouping";
|
||||
import { Event, Groups } from "../types";
|
||||
import {
|
||||
add,
|
||||
differenceInCalendarYears,
|
||||
isThisYear as dateFnsIsThisYear,
|
||||
} from "date-fns";
|
||||
|
||||
export default class YearGrouping extends EventGrouping {
|
||||
static isThisYear(date: Date): boolean {
|
||||
return dateFnsIsThisYear(date);
|
||||
}
|
||||
|
||||
constructor(sortedEvents: Event[]) {
|
||||
super(sortedEvents);
|
||||
this.groups = this.group();
|
||||
}
|
||||
|
||||
group(): Groups {
|
||||
const numberOfGroups = differenceInCalendarYears(
|
||||
this.lastEvent.date,
|
||||
this.firstEvent.date
|
||||
);
|
||||
|
||||
return this.sortedEvents.reduce((prev, event) => {
|
||||
const groupNumber = differenceInCalendarYears(
|
||||
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, { years: index });
|
||||
}
|
||||
}
|
||||
@ -1,5 +1,6 @@
|
||||
import DayGrouping from "./DayGrouping";
|
||||
import WeekGrouping from "./WeekGrouping";
|
||||
import MonthGrouping from "./MonthGrouping";
|
||||
import YearGrouping from "./YearGrouping";
|
||||
|
||||
export { DayGrouping, WeekGrouping, MonthGrouping };
|
||||
export { DayGrouping, WeekGrouping, MonthGrouping, YearGrouping };
|
||||
|
||||
30
src/HtmlRenderer/Year/GroupYearRenderer.ts
Normal file
30
src/HtmlRenderer/Year/GroupYearRenderer.ts
Normal file
@ -0,0 +1,30 @@
|
||||
import { Event } from "../../types";
|
||||
import { YearGrouping } from "../../EventGrouping";
|
||||
|
||||
import GroupRenderer from "../Abstract/GroupRenderer";
|
||||
|
||||
export default class GroupYearRenderer extends GroupRenderer {
|
||||
constructor(group: Event[], groupDate: Date, groupIndex: number) {
|
||||
super(group, groupDate, groupIndex);
|
||||
|
||||
if (YearGrouping.isThisYear(groupDate)) {
|
||||
this.highlightGroup();
|
||||
}
|
||||
}
|
||||
|
||||
protected renderDateAsIcon(eventDate, groupIndex): HTMLSpanElement {
|
||||
const html = document.createElement("span");
|
||||
html.className = "icon";
|
||||
|
||||
html.textContent = eventDate.toLocaleDateString(undefined, {
|
||||
year: "numeric",
|
||||
});
|
||||
html.className += " primary";
|
||||
|
||||
if (YearGrouping.isThisYear(eventDate)) {
|
||||
html.className += " highlighted";
|
||||
}
|
||||
|
||||
return html;
|
||||
}
|
||||
}
|
||||
19
src/HtmlRenderer/Year/index.ts
Normal file
19
src/HtmlRenderer/Year/index.ts
Normal file
@ -0,0 +1,19 @@
|
||||
import { Event } from "../../types";
|
||||
import { YearGrouping } from "../../EventGrouping";
|
||||
import Renderer from "../Abstract/Renderer";
|
||||
import GroupYearRenderer from "./GroupYearRenderer";
|
||||
|
||||
export default class YearRenderer extends Renderer {
|
||||
constructor(eventGrouping: YearGrouping) {
|
||||
super(eventGrouping);
|
||||
this.container.className += " scale-year";
|
||||
}
|
||||
|
||||
protected renderGroups(
|
||||
group: Event[],
|
||||
groupDate: Date,
|
||||
groupIndex: number
|
||||
): HTMLDivElement {
|
||||
return new GroupYearRenderer(group, groupDate, groupIndex).render();
|
||||
}
|
||||
}
|
||||
@ -1,5 +1,6 @@
|
||||
import DayRenderer from "./Day/";
|
||||
import WeekRenderer from "./Week/";
|
||||
import MonthRenderer from "./Month/";
|
||||
import DayRenderer from "./Day";
|
||||
import WeekRenderer from "./Week";
|
||||
import MonthRenderer from "./Month";
|
||||
import YearRenderer from "./Year";
|
||||
|
||||
export { DayRenderer, WeekRenderer, MonthRenderer };
|
||||
export { DayRenderer, WeekRenderer, MonthRenderer, YearRenderer };
|
||||
|
||||
@ -2,6 +2,7 @@ export enum GroupTypes {
|
||||
Day = "D",
|
||||
Week = "W",
|
||||
Month = "M",
|
||||
Year = "Y",
|
||||
}
|
||||
|
||||
export interface Event {
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user