diff --git a/src/app/_helpers/collections/difference.spec.ts b/src/app/_helpers/collections/difference.spec.ts
new file mode 100644
index 00000000..ea9fab3d
--- /dev/null
+++ b/src/app/_helpers/collections/difference.spec.ts
@@ -0,0 +1,25 @@
+/*
+ * Copyright (C) 2022 StApps
+ * This program is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation, version 3.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program. If not, see .
+ */
+
+import {differenceBy} from './difference';
+
+describe('differenceBy', function () {
+ it('should return the difference of two arrays', function () {
+ const a = [1, 2, 3, 4, 5];
+ const b = [1, 2, 3];
+
+ expect(differenceBy(a, b, it => it)).toEqual([4, 5]);
+ });
+});
diff --git a/src/app/_helpers/collections/difference.ts b/src/app/_helpers/collections/difference.ts
new file mode 100644
index 00000000..dc012234
--- /dev/null
+++ b/src/app/_helpers/collections/difference.ts
@@ -0,0 +1,27 @@
+/*
+ * Copyright (C) 2022 StApps
+ * This program is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation, version 3.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program. If not, see .
+ */
+
+/**
+ * Returns the difference between two arrays.
+ */
+export function differenceBy(
+ a: T[],
+ b: T[],
+ transform: (item: T) => unknown,
+) {
+ const disallowed = new Set(b.map(transform));
+
+ return a.filter(item => !disallowed.has(transform(item)));
+}
diff --git a/src/app/_helpers/collections/group-by.ts b/src/app/_helpers/collections/group-by.ts
index 688ae807..b17ccc0b 100644
--- a/src/app/_helpers/collections/group-by.ts
+++ b/src/app/_helpers/collections/group-by.ts
@@ -21,7 +21,7 @@ export function groupBy(
group: (item: T) => string | undefined,
): Record {
return collection.reduce((accumulator: Record, item) => {
- const key = group(item) || '';
+ const key = group(item) ?? '';
accumulator[key] = accumulator[key] ?? [];
accumulator[key].push(item);
return accumulator;
diff --git a/src/app/_helpers/collections/uniq.spec.ts b/src/app/_helpers/collections/uniq.spec.ts
new file mode 100644
index 00000000..ca8e4a56
--- /dev/null
+++ b/src/app/_helpers/collections/uniq.spec.ts
@@ -0,0 +1,26 @@
+/*
+ * Copyright (C) 2022 StApps
+ * This program is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation, version 3.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program. If not, see .
+ */
+
+import {uniqBy} from './uniq';
+
+describe('uniq', function () {
+ it('should return an array with unique values', function () {
+ const array = [
+ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
+ ];
+ const result = uniqBy(array, it => it);
+ expect(result).toEqual([1, 2, 3, 4, 5, 6, 7, 8, 9, 10]);
+ });
+});
diff --git a/src/app/_helpers/collections/uniq.ts b/src/app/_helpers/collections/uniq.ts
new file mode 100644
index 00000000..4d88d258
--- /dev/null
+++ b/src/app/_helpers/collections/uniq.ts
@@ -0,0 +1,29 @@
+/*
+ * Copyright (C) 2022 StApps
+ * This program is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation, version 3.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program. If not, see .
+ */
+
+/**
+ * Filter out duplicates from an array.
+ */
+export function uniqBy(
+ array: T[],
+ transform: (item: T) => string | number,
+): T[] {
+ return Object.values(
+ array.reduce((accumulator, current) => {
+ accumulator[transform(current)] = current;
+ return accumulator;
+ }, {} as Record),
+ );
+}
diff --git a/src/app/modules/data/chips/add-event-popover.component.ts b/src/app/modules/data/chips/add-event-popover.component.ts
index acb45177..cce63201 100644
--- a/src/app/modules/data/chips/add-event-popover.component.ts
+++ b/src/app/modules/data/chips/add-event-popover.component.ts
@@ -35,6 +35,8 @@ import {ThingTranslatePipe} from '../../../translation/thing-translate.pipe';
import {groupBy, groupByProperty} from '../../../_helpers/collections/group-by';
import {mapValues} from '../../../_helpers/collections/map-values';
import {stringSortBy} from '../../../_helpers/collections/string-sort';
+import {uniqBy} from '../../../_helpers/collections/uniq';
+import {differenceBy} from '../../../_helpers/collections/difference';
enum Selection {
ON = 2,
@@ -267,13 +269,16 @@ export class AddEventPopoverComponent implements OnInit, OnDestroy {
async onCommit(save: boolean) {
if (save) {
const {selected, unselected} = this.getSelection();
- console.log(selected, unselected);
- this.scheduleProvider.partialEvents$.next([
- ...new Set([
- ...this.partialDateSeries.filter(it => !unselected.includes(it)),
- ...selected,
- ]),
- ]);
+
+ this.scheduleProvider.partialEvents$.next(
+ uniqBy(
+ [
+ ...differenceBy(this.partialDateSeries, unselected, it => it.uid),
+ ...selected,
+ ],
+ it => it.uid,
+ ),
+ );
}
await this.popoverController.dismiss();
diff --git a/src/app/modules/schedule/page/grid/schedule-day.component.ts b/src/app/modules/schedule/page/grid/schedule-day.component.ts
index f4c0d190..50830880 100644
--- a/src/app/modules/schedule/page/grid/schedule-day.component.ts
+++ b/src/app/modules/schedule/page/grid/schedule-day.component.ts
@@ -1,16 +1,16 @@
/*
- * Copyright (C) 2021 StApps
- * This program is free software: you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the Free
- * Software Foundation, version 3.
+ * Copyright (C) 2022 StApps
+ * This program is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation, version 3.
*
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
- * more details.
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
*
- * You should have received a copy of the GNU General Public License along with
- * this program. If not, see .
+ * You should have received a copy of the GNU General Public License along with
+ * this program. If not, see .
*/
import {Component, Input} from '@angular/core';
import moment from 'moment';
@@ -40,7 +40,10 @@ export class ScheduleDayComponent {
dateSeriesGroups?: ScheduleEvent[][];
@Input() set dateSeries(value: Record) {
- if (!value) return;
+ if (!value) {
+ delete this.dateSeriesGroups;
+ return;
+ }
this.dateSeriesGroups = groupRangeOverlaps(
Object.values(value),