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:
1 parent
0e5b190971
commit
cc1fd4e508
7 files changed
+352
-19
No files matched your search
@@ -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());
|
||||
}
|
||||
}
|
||||
+49
-13
@@ -3,21 +3,57 @@
|
||||
declare(strict_types=1);
|
||||
|
||||
/*
|
||||
* Minimal stand-in for the server class OC_Util, which is not part
|
||||
* of the OCP vendor package. Records addStyle() calls for assertions.
|
||||
* Minimal stand-ins for server classes that are not part of
|
||||
* the OCP vendor package. OC_Util records addStyle() calls,
|
||||
* the OC classes satisfy the lookups that OCP\Util::addScript()
|
||||
* triggers for app scripts.
|
||||
*/
|
||||
if (!class_exists(\OC_Util::class, false)) {
|
||||
class OC_Util
|
||||
namespace OC {
|
||||
class AppScriptDependency
|
||||
{
|
||||
/** @var list<array{string, ?string, bool}> */
|
||||
public static array $styles = [];
|
||||
public function __construct(string $app, array $deps = []) {}
|
||||
|
||||
public static function addStyle(
|
||||
string $application,
|
||||
?string $file = null,
|
||||
bool $prepend = false
|
||||
): void {
|
||||
self::$styles[] = [$application, $file, $prepend];
|
||||
}
|
||||
public function addDep(string $dep): void {}
|
||||
}
|
||||
}
|
||||
|
||||
namespace {
|
||||
class OC
|
||||
{
|
||||
public static ?object $server = null;
|
||||
}
|
||||
|
||||
class AToCalFakeL10NFactory
|
||||
{
|
||||
public function findLanguage(string $app): string
|
||||
{
|
||||
return 'en';
|
||||
}
|
||||
}
|
||||
|
||||
class AToCalFakeServer
|
||||
{
|
||||
public function get(string $serviceName): AToCalFakeL10NFactory
|
||||
{
|
||||
return new AToCalFakeL10NFactory();
|
||||
}
|
||||
}
|
||||
|
||||
if (!class_exists('OC_Util', false)) {
|
||||
class OC_Util
|
||||
{
|
||||
/** @var list<array{string, ?string, bool}> */
|
||||
public static array $styles = [];
|
||||
|
||||
public static function addStyle(
|
||||
string $application,
|
||||
?string $file = null,
|
||||
bool $prepend = false
|
||||
): void {
|
||||
self::$styles[] = [$application, $file, $prepend];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
OC::$server ??= new AToCalFakeServer();
|
||||
}
|
||||
Reference in new issue
Block a user