diff --git a/CHANGELOG.md b/CHANGELOG.md
index ad3cfd9e..4f348a54 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -2,6 +2,12 @@
All notable changes to this project will be documented in this file.
This project adheres to [Semantic Versioning](http://semver.org/).
+## [2.1.4] - 2018-03-18
+
+### Added
+
+- Add advanced filtering to the excludedEvents configuration of the default calendar module
+
## [2.2.2] - 2018-01-02
### Added
diff --git a/modules/default/calendar/README.md b/modules/default/calendar/README.md
index 8ce9608b..2481b77b 100644
--- a/modules/default/calendar/README.md
+++ b/modules/default/calendar/README.md
@@ -46,7 +46,7 @@ The following properties can be configured:
| `urgency` | When using a timeFormat of `absolute`, the `urgency` setting allows you to display events within a specific time frame as `relative`. This allows events within a certain time frame to be displayed as relative (in xx days) while others are displayed as absolute dates
**Possible values:** a positive integer representing the number of days for which you want a relative date, for example `7` (for 7 days)
**Default value:** `7`
| `broadcastEvents` | If this property is set to true, the calendar will broadcast all the events to all other modules with the notification message: `CALENDAR_EVENTS`. The event objects are stored in an array and contain the following fields: `title`, `startDate`, `endDate`, `fullDayEvent`, `location` and `geo`.
**Possible values:** `true`, `false`
**Default value:** `true`
| `hidePrivate` | Hides private calendar events.
**Possible values:** `true` or `false`
**Default value:** `false`
-| `excludedEvents` | An array of words / phrases from event titles that will be excluded from being shown.
**Example:** `['Birthday', 'Hide This Event']`
**Default value:** `[]`
+| `excludedEvents` | An array of words / phrases from event titles that will be excluded from being shown.
Additionally advanced filter objects can be passed in. Below is the configuration for the advance filtering object.
**Required**
`filterBy` - string used to determine if filter is applied.
**Optional**
`until` - Time before an event to display it Ex: [`'3 days'`, `'2 months'`, `'1 week'`]
`caseSensitive` - By default, excludedEvents are case insensitive, set this to true to enforce case sensitivity
**Example:** `['Birthday', 'Hide This Event', {filterBy: 'Payment', until: '6 days', caseSensitive: true}]`
**Default value:** `[]`
### Calendar configuration
diff --git a/modules/default/calendar/calendarfetcher.js b/modules/default/calendar/calendarfetcher.js
index 12495f78..911eaba4 100644
--- a/modules/default/calendar/calendarfetcher.js
+++ b/modules/default/calendar/calendarfetcher.js
@@ -113,11 +113,38 @@ var CalendarFetcher = function(url, reloadInterval, excludedEvents, maximumEntri
title = event.description;
}
- var excluded = false;
+ var excluded = false,
+ dateFilter = null;
+
for (var f in excludedEvents) {
- var filter = excludedEvents[f];
- if (title.toLowerCase().includes(filter.toLowerCase())) {
- excluded = true;
+ var filter = excludedEvents[f],
+ testTitle = title.toLowerCase(),
+ until = null;
+
+ if (filter instanceof Object) {
+ if (typeof filter.until !== "undefined") {
+ until = filter.until;
+ }
+
+ // If additional advanced filtering is added in, this section
+ // must remain last as we overwrite the filter object with the
+ // filterBy string
+ if (filter.caseSensitive) {
+ filter = filter.filterBy;
+ testTitle = title;
+ } else {
+ filter = filter.filterBy.toLowerCase();
+ }
+ } else {
+ filter = filter.toLowerCase();
+ }
+
+ if (testTitle.includes(filter)) {
+ if (until) {
+ dateFilter = until;
+ } else {
+ excluded = true;
+ }
break;
}
}
@@ -137,6 +164,11 @@ var CalendarFetcher = function(url, reloadInterval, excludedEvents, maximumEntri
for (var d in dates) {
startDate = moment(new Date(dates[d]));
endDate = moment(parseInt(startDate.format("x")) + duration, "x");
+
+ if (timeFilterApplies(now, endDate, dateFilter)) {
+ continue;
+ }
+
if (endDate.format("x") > now) {
newEvents.push({
title: title,
@@ -171,6 +203,10 @@ var CalendarFetcher = function(url, reloadInterval, excludedEvents, maximumEntri
continue;
}
+ if (timeFilterApplies(now, endDate, dateFilter)) {
+ continue;
+ }
+
// Every thing is good. Add it to the list.
newEvents.push({
@@ -236,6 +272,28 @@ var CalendarFetcher = function(url, reloadInterval, excludedEvents, maximumEntri
return false;
};
+ /* timeFilterApplies()
+ * Determines if the user defined time filter should apply
+ *
+ * argument now Date - Date object using previously created object for consistency
+ * argument endDate Moment - Moment object representing the event end date
+ * argument filter string - The time to subtract from the end date to determine if an event should be shown
+ *
+ * return bool - The event should be filtered out
+ */
+ var timeFilterApplies = function(now, endDate, filter) {
+ if (filter) {
+ var until = filter.split(" "),
+ value = parseInt(until[0]),
+ increment = until[1].slice("-1") === "s" ? until[1] : until[1] + "s", // Massage the data for moment js
+ filterUntil = moment(endDate.format()).subtract(value, increment);
+
+ return now < filterUntil.format("x");
+ }
+
+ return false;
+ };
+
/* public methods */
/* startFetch()