@forcecalendar/core 2.1.11 → 2.1.13
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/core/events/EventStore.js +23 -24
- package/core/events/RecurrenceEngine.js +12 -0
- package/package.json +1 -1
|
@@ -415,33 +415,32 @@ export class EventStore {
|
|
|
415
415
|
events = events.filter(e => !e.allDay);
|
|
416
416
|
}
|
|
417
417
|
|
|
418
|
-
|
|
419
|
-
const processed = new Set();
|
|
420
|
-
|
|
421
|
-
events.forEach(event => {
|
|
422
|
-
if (processed.has(event.id)) return;
|
|
423
|
-
|
|
424
|
-
// Start a new group with this event
|
|
425
|
-
const group = [event];
|
|
426
|
-
processed.add(event.id);
|
|
418
|
+
if (events.length === 0) return [];
|
|
427
419
|
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
const currentEvent = group[i];
|
|
432
|
-
|
|
433
|
-
events.forEach(otherEvent => {
|
|
434
|
-
if (!processed.has(otherEvent.id) && currentEvent.overlaps(otherEvent)) {
|
|
435
|
-
group.push(otherEvent);
|
|
436
|
-
processed.add(otherEvent.id);
|
|
437
|
-
}
|
|
438
|
-
});
|
|
420
|
+
// Sweep-line approach: sort by start, then merge overlapping intervals
|
|
421
|
+
// O(n log n) instead of O(n²)
|
|
422
|
+
events.sort((a, b) => a.start - b.start || b.end - a.end);
|
|
439
423
|
|
|
440
|
-
|
|
424
|
+
const groups = [];
|
|
425
|
+
let currentGroup = [events[0]];
|
|
426
|
+
let groupEnd = events[0].end;
|
|
427
|
+
|
|
428
|
+
for (let i = 1; i < events.length; i++) {
|
|
429
|
+
const event = events[i];
|
|
430
|
+
if (event.start < groupEnd) {
|
|
431
|
+
// Overlaps with current group
|
|
432
|
+
currentGroup.push(event);
|
|
433
|
+
if (event.end > groupEnd) {
|
|
434
|
+
groupEnd = event.end;
|
|
435
|
+
}
|
|
436
|
+
} else {
|
|
437
|
+
// No overlap — start new group
|
|
438
|
+
groups.push(currentGroup);
|
|
439
|
+
currentGroup = [event];
|
|
440
|
+
groupEnd = event.end;
|
|
441
441
|
}
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
});
|
|
442
|
+
}
|
|
443
|
+
groups.push(currentGroup);
|
|
445
444
|
|
|
446
445
|
return groups;
|
|
447
446
|
}
|
|
@@ -165,6 +165,18 @@ export class RecurrenceEngine {
|
|
|
165
165
|
const next = new Date(currentDate);
|
|
166
166
|
|
|
167
167
|
switch (rule.freq) {
|
|
168
|
+
case 'SECONDLY':
|
|
169
|
+
next.setSeconds(next.getSeconds() + rule.interval);
|
|
170
|
+
break;
|
|
171
|
+
|
|
172
|
+
case 'MINUTELY':
|
|
173
|
+
next.setMinutes(next.getMinutes() + rule.interval);
|
|
174
|
+
break;
|
|
175
|
+
|
|
176
|
+
case 'HOURLY':
|
|
177
|
+
next.setHours(next.getHours() + rule.interval);
|
|
178
|
+
break;
|
|
179
|
+
|
|
168
180
|
case 'DAILY':
|
|
169
181
|
next.setDate(next.getDate() + rule.interval);
|
|
170
182
|
break;
|