mirror of
https://github.com/bulwarkmail/native.git
synced 2026-11-02 08:07:11 +00:00
feat: search events in the calendar
This commit is contained in:
@@ -34,7 +34,7 @@ import {
|
||||
queryEvents,
|
||||
isCalendarAccessDenied,
|
||||
} from '../calendar';
|
||||
import { useCalendarStore } from '../../stores/calendar-store';
|
||||
import { searchCalendarEvents, useCalendarStore } from '../../stores/calendar-store';
|
||||
import { useSettingsStore } from '../../stores/settings-store';
|
||||
import { saveOccurrenceEdit, deleteOccurrence, type SeriesEdit } from '../../lib/recurrence-scope-edit';
|
||||
import { editorTimesChanged, editorTimesFromEvent, eventTimeFieldsToSave } from '../../lib/event-editor-times';
|
||||
@@ -754,6 +754,24 @@ live('live Stalwart calendar', () => {
|
||||
}, 60_000);
|
||||
});
|
||||
|
||||
describe('event search', () => {
|
||||
it('finds an event outside the loaded window by a word of its title, and a series by its stored event', async () => {
|
||||
await connectSingleton();
|
||||
const word = RUN.replace(/[^a-z0-9]/gi, '');
|
||||
await createEvent({ '@type': 'Event', title: `${RUN} ${word}single`, start: '2027-12-10T09:00:00', duration: 'PT1H', timeZone: 'Europe/Berlin' } as Partial<CalendarEvent>, calendarId);
|
||||
await createEvent(seriesData(`${word}series`, '2027-01-04T10:00:00', 4), calendarId);
|
||||
await useCalendarStore.getState().fetchCalendars();
|
||||
|
||||
const single = await searchCalendarEvents([`${word}single`]);
|
||||
expect(single.map((e) => e.title)).toEqual([`${RUN} ${word}single`]);
|
||||
const series = await searchCalendarEvents([`${word}series`]);
|
||||
expect(series).toHaveLength(1);
|
||||
expect(series[0].recurrenceRules?.[0]?.count).toBe(4);
|
||||
// Every word has to match.
|
||||
expect(await searchCalendarEvents([`${word}single`, 'nosuchwordanywhere'])).toEqual([]);
|
||||
}, 60_000);
|
||||
});
|
||||
|
||||
describe('a zero-length event (#837)', () => {
|
||||
it('ends at its start, stored without a duration or imported from an .ics', async () => {
|
||||
await connectSingleton();
|
||||
|
||||
@@ -1010,6 +1010,30 @@ export async function findEventsByUid(uid: string, accountId?: string): Promise<
|
||||
return getEvents(ids, accountId);
|
||||
}
|
||||
|
||||
/**
|
||||
* The ids of the events a CalendarEvent/query `filter` finds (the event
|
||||
* search's `text` conditions), latest start first, at most `limit`. Not
|
||||
* limited to a date window: a series is found by its stored event.
|
||||
*/
|
||||
export async function searchEventIds(
|
||||
filter: Record<string, unknown>,
|
||||
accountId?: string,
|
||||
limit = 100,
|
||||
): Promise<string[]> {
|
||||
const account = accountId || jmapClient.accountId;
|
||||
return withCalendarTimeZone(async (timeZone) => {
|
||||
const args: Record<string, unknown> = {
|
||||
accountId: account,
|
||||
filter,
|
||||
sort: [{ property: 'start', isAscending: false }],
|
||||
limit,
|
||||
};
|
||||
if (timeZone) args.timeZone = timeZone;
|
||||
const res = await jmapClient.request([['CalendarEvent/query', args, '0']], USING);
|
||||
return methodResult<{ ids: string[] }>(res).ids ?? [];
|
||||
});
|
||||
}
|
||||
|
||||
// `sendSchedulingMessages` asks Stalwart to deliver iMIP (RFC 6047) invitation
|
||||
// / reply / cancellation emails to participants. We pass it whenever an event
|
||||
// has participants so creating/updating/deleting a meeting notifies attendees.
|
||||
|
||||
Reference in New Issue
Block a user