@forcecalendar/core 2.1.14 → 2.1.16
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.
|
@@ -345,8 +345,16 @@ export class RecurrenceEngine {
|
|
|
345
345
|
}
|
|
346
346
|
return exceptionDate.toDateString() === dateStr;
|
|
347
347
|
}
|
|
348
|
-
// Simple date exception
|
|
348
|
+
// Simple date exception — if the exception has a specific time component
|
|
349
|
+
// (not midnight), match by timestamp to avoid excluding all occurrences on that day
|
|
349
350
|
const exceptionDate = exDate instanceof Date ? exDate : new Date(exDate);
|
|
351
|
+
const hasTime =
|
|
352
|
+
exceptionDate.getHours() !== 0 ||
|
|
353
|
+
exceptionDate.getMinutes() !== 0 ||
|
|
354
|
+
exceptionDate.getSeconds() !== 0;
|
|
355
|
+
if (hasTime) {
|
|
356
|
+
return Math.abs(exceptionDate.getTime() - dateTime) < 1000;
|
|
357
|
+
}
|
|
350
358
|
return exceptionDate.toDateString() === dateStr;
|
|
351
359
|
});
|
|
352
360
|
}
|
|
@@ -10,9 +10,37 @@ export class EventSearch {
|
|
|
10
10
|
// Search index for performance
|
|
11
11
|
this.searchIndex = new Map();
|
|
12
12
|
this.indexFields = ['title', 'description', 'location', 'category'];
|
|
13
|
+
this._indexDirty = false;
|
|
13
14
|
|
|
14
15
|
// Build initial index
|
|
15
16
|
this.rebuildIndex();
|
|
17
|
+
|
|
18
|
+
// Subscribe to EventStore changes to keep index in sync
|
|
19
|
+
if (this.eventStore && typeof this.eventStore.subscribe === 'function') {
|
|
20
|
+
this._unsubscribe = this.eventStore.subscribe(change => {
|
|
21
|
+
if (change.type === 'batch') {
|
|
22
|
+
this._indexDirty = true;
|
|
23
|
+
} else if (
|
|
24
|
+
change.type === 'add' ||
|
|
25
|
+
change.type === 'update' ||
|
|
26
|
+
change.type === 'remove' ||
|
|
27
|
+
change.type === 'clear'
|
|
28
|
+
) {
|
|
29
|
+
this._indexDirty = true;
|
|
30
|
+
}
|
|
31
|
+
});
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* Destroy the search engine and unsubscribe from store changes
|
|
37
|
+
*/
|
|
38
|
+
destroy() {
|
|
39
|
+
if (this._unsubscribe) {
|
|
40
|
+
this._unsubscribe();
|
|
41
|
+
this._unsubscribe = null;
|
|
42
|
+
}
|
|
43
|
+
this.searchIndex.clear();
|
|
16
44
|
}
|
|
17
45
|
|
|
18
46
|
/**
|
|
@@ -34,6 +62,9 @@ export class EventSearch {
|
|
|
34
62
|
return [];
|
|
35
63
|
}
|
|
36
64
|
|
|
65
|
+
// Rebuild index if stale
|
|
66
|
+
this._ensureIndex();
|
|
67
|
+
|
|
37
68
|
// Normalize query
|
|
38
69
|
const normalizedQuery = caseSensitive ? query : query.toLowerCase();
|
|
39
70
|
const queryTerms = this.tokenize(normalizedQuery);
|
|
@@ -443,11 +474,22 @@ export class EventSearch {
|
|
|
443
474
|
}
|
|
444
475
|
}
|
|
445
476
|
|
|
477
|
+
/**
|
|
478
|
+
* Ensure the search index is up to date
|
|
479
|
+
* @private
|
|
480
|
+
*/
|
|
481
|
+
_ensureIndex() {
|
|
482
|
+
if (this._indexDirty) {
|
|
483
|
+
this.rebuildIndex();
|
|
484
|
+
}
|
|
485
|
+
}
|
|
486
|
+
|
|
446
487
|
/**
|
|
447
488
|
* Rebuild search index
|
|
448
489
|
*/
|
|
449
490
|
rebuildIndex() {
|
|
450
491
|
this.searchIndex.clear();
|
|
492
|
+
this._indexDirty = false;
|
|
451
493
|
const events = this.eventStore.getAllEvents();
|
|
452
494
|
|
|
453
495
|
for (const event of events) {
|