Add live contact search to invitee input

The static datalist only carried the first 50 address book
contacts, so typed fragments could not match anything beyond
that. A new read-only GET /contacts/search endpoint queries
the full address book per keystroke, and a small vanilla JS
combobox shows the results and replaces only the fragment
after the last separator, so comma-separated lists keep
working. The server-rendered datalist remains as the no-JS
fallback; the JS removes the list attribute at runtime so
the native popup does not double the custom one.
This commit is contained in:
stefan.tollkuehn committed 2026-10-22 18:50:46 +02:00
1 parent 0e5b190971
commit cc1fd4e508
7 files changed
+352 -19

No files matched your search

+42
View File
@@ -6,6 +6,7 @@ namespace OCA\AToCal\Tests\Unit\Controller;
use OCA\AToCal\Controller\CalendarController;
use OCP\App\IAppManager;
use OCP\AppFramework\Http\DataResponse;
use OCP\AppFramework\Http\RedirectResponse;
use OCP\AppFramework\Http\TemplateResponse;
use OCP\Calendar\ICalendar;
@@ -898,4 +899,45 @@ class CalendarControllerTest extends TestCase
$this->assertSame('alice@example.com, not-an-email', $params['attendees']);
$this->assertSame('5::personal', $params['calendarId']);
}
/*
* searchContacts()
*/
public function testSearchContactsReturnsMatches(): void
{
$this->contactsManager->expects($this->once())->method('search')
->with('ali', ['FN', 'EMAIL'])
->willReturn([
['FN' => 'Alice Example', 'EMAIL' => 'alice@example.com'],
]);
$c = $this->newController();
$response = $c->searchContacts('ali');
$this->assertInstanceOf(DataResponse::class, $response);
$this->assertSame(
[['email' => 'alice@example.com', 'name' => 'Alice Example']],
$response->getData()
);
}
public function testSearchContactsCapsResults(): void
{
$contacts = array_map(
static fn (int $i): array => [
'FN' => "Person $i",
'EMAIL' => "person$i@example.com",
],
range(1, 60)
);
$this->contactsManager->method('search')->willReturn($contacts);
$c = $this->newController();
$response = $c->searchContacts('person');
$this->assertCount(50, $response->getData());
}
}