forked from nextcloud/calendar
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
This commit adds support for adding circles as attendees to a calendar event. The relationship between the imported group and members will be compliant with the iCal specification. A circle with the title "testcircle" will be added as an attendee with iCal attributes "CUTYPE=GROUP` and uri "mailto:circle+CIRCLEID@CIRCLE_INSTANCE". Members of the circle will be imported as standard attendees. Each member gets assigned to the circle group entry by assigning them to the group uri using the iCal member property: "MEMBER='mailto:circle+CIRCLEID@CIRCLE_INSTANCE'". Searching for circles is only enabled if the circles app is activated. Circles added to the list of attendees get imported only once and are not synced yet. While adding a circle, a notice about this is shown to the user. Only members of local circles which are local users get imported. Rendering groups in the frontend is done in a separate PR nextcloud#5396 Signed-off-by: Jonas Heinrich <[email protected]>
- Loading branch information
Jonas Heinrich
committed
Nov 1, 2023
1 parent
4382955
commit db6fa20
Showing
10 changed files
with
326 additions
and
8 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -5,9 +5,12 @@ | |
* Calendar App | ||
* | ||
* @author Georg Ehrke | ||
* @copyright 2018 Georg Ehrke <[email protected]> | ||
* @author Thomas Müller | ||
* @author Jonas Heinrich | ||
* | ||
* @copyright 2018 Georg Ehrke <[email protected]> | ||
* @copyright 2016 Thomas Müller <[email protected]> | ||
* @copyright 2023 Jonas Heinrich <[email protected]> | ||
* | ||
* This library is free software; you can redistribute it and/or | ||
* modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE | ||
|
@@ -54,6 +57,8 @@ | |
['name' => 'contact#searchAttendee', 'url' => '/v1/autocompletion/attendee', 'verb' => 'POST'], | ||
['name' => 'contact#searchLocation', 'url' => '/v1/autocompletion/location', 'verb' => 'POST'], | ||
['name' => 'contact#searchPhoto', 'url' => '/v1/autocompletion/photo', 'verb' => 'POST'], | ||
// Circles | ||
['name' => 'contact#getCircleMembers', 'url' => '/v1/circles/getmembers', 'verb' => 'GET'], | ||
// Settings | ||
['name' => 'settings#setConfig', 'url' => '/v1/config/{key}', 'verb' => 'POST'], | ||
// Tools | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -7,10 +7,12 @@ | |
* @author Georg Ehrke | ||
* @author Jakob Röhrl | ||
* @author Christoph Wurst | ||
* @author Jonas Heinrich | ||
* | ||
* @copyright 2019 Georg Ehrke <[email protected]> | ||
* @copyright 2019 Jakob Röhrl <[email protected]> | ||
* @copyright 2019 Christoph Wurst <[email protected]> | ||
* @copyright 2023 Jonas Heinrich <[email protected]> | ||
* | ||
* This library is free software; you can redistribute it and/or | ||
* modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE | ||
|
@@ -28,11 +30,15 @@ | |
*/ | ||
namespace OCA\Calendar\Controller; | ||
|
||
use OCA\Circles\Exceptions\CircleNotFoundException; | ||
use OCP\App\IAppManager; | ||
use OCP\AppFramework\Controller; | ||
use OCP\AppFramework\Http; | ||
use OCP\AppFramework\Http\JSONResponse; | ||
use OCP\AppFramework\QueryException; | ||
use OCP\Contacts\IManager; | ||
use OCP\IRequest; | ||
use OCP\IUserManager; | ||
|
||
/** | ||
* Class ContactController | ||
|
@@ -43,6 +49,12 @@ class ContactController extends Controller { | |
/** @var IManager */ | ||
private $contactsManager; | ||
|
||
/** @var IAppManager */ | ||
private $appManager; | ||
|
||
/** @var IUserManager */ | ||
private $userManager; | ||
|
||
/** | ||
* ContactController constructor. | ||
* | ||
|
@@ -52,9 +64,13 @@ class ContactController extends Controller { | |
*/ | ||
public function __construct(string $appName, | ||
IRequest $request, | ||
IManager $contacts) { | ||
IManager $contacts, | ||
IAppManager $appManager, | ||
IUserManager $userManager) { | ||
parent::__construct($appName, $request); | ||
$this->contactsManager = $contacts; | ||
$this->appManager = $appManager; | ||
$this->userManager = $userManager; | ||
} | ||
|
||
/** | ||
|
@@ -173,6 +189,66 @@ public function searchAttendee(string $search):JSONResponse { | |
return new JSONResponse($contacts); | ||
} | ||
|
||
/** | ||
* Query members of a circle by circleId | ||
* | ||
* @param string $circleId CircleId to query for members | ||
* @return JSONResponse | ||
* @throws Exception | ||
* @throws \OCP\AppFramework\QueryException | ||
* | ||
* @NoAdminRequired | ||
*/ | ||
public function getCircleMembers(string $circleId):JSONResponse { | ||
if (!$this->appManager->isEnabledForUser('circles') || !class_exists('\OCA\Circles\Api\v1\Circles')) { | ||
return []; | ||
} | ||
if (!$this->contactsManager->isEnabled()) { | ||
return new JSONResponse(); | ||
} | ||
|
||
try { | ||
$circle = \OCA\Circles\Api\v1\Circles::detailsCircle($circleId, true); | ||
} catch (QueryException $ex) { | ||
return null; | ||
} catch (CircleNotFoundException $ex) { | ||
return null; | ||
} | ||
|
||
if (!$circle) { | ||
return null; | ||
} | ||
|
||
$circleMembers = $circle->getInheritedMembers(); | ||
|
||
foreach ($circleMembers as $circleMember) { | ||
if ($circleMember->isLocal()) { | ||
|
||
$circleMemberUserId = $circleMember->getUserId(); | ||
|
||
$user = $this->userManager->get($circleMemberUserId); | ||
|
||
if ($user === null) { | ||
throw new ServiceException('Could not find organizer'); | ||
} | ||
|
||
$contacts[] = [ | ||
'commonName' => $circleMember->getDisplayName(), | ||
'calendarUserType' => 'INDIVIDUAL', | ||
'email' => $user->getEMailAddress(), | ||
'isUser' => true, | ||
'avatar' => $circleMemberUserId, | ||
'hasMultipleEMails' => false, | ||
'dropdownName' => $circleMember->getDisplayName(), | ||
'member' => 'mailto:circle+' . $circleId . '@' . $circleMember->getInstance(), | ||
]; | ||
} | ||
} | ||
|
||
return new JSONResponse($contacts); | ||
} | ||
|
||
|
||
/** | ||
* Get a contact's photo based on their email-address | ||
* | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -6,8 +6,10 @@ | |
* | ||
* @author Georg Ehrke | ||
* @author Richard Steinmetz <[email protected]> | ||
* @author Jonas Heinrich <[email protected]> | ||
* @copyright 2019 Georg Ehrke <[email protected]> | ||
* @copyright Copyright (c) 2022 Informatyka Boguslawski sp. z o.o. sp.k., http://www.ib.pl/ | ||
* @copyright 2023 Jonas Heinrich <[email protected]> | ||
* | ||
* This library is free software; you can redistribute it and/or | ||
* modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE | ||
|
@@ -25,6 +27,7 @@ | |
*/ | ||
namespace OCA\Calendar\Controller; | ||
|
||
use OC\App\CompareVersion; | ||
use OCA\Calendar\Service\Appointments\AppointmentConfigService; | ||
use OCP\App\IAppManager; | ||
use OCP\AppFramework\Controller; | ||
|
@@ -51,6 +54,9 @@ class ViewController extends Controller { | |
/** @var IAppManager */ | ||
private $appManager; | ||
|
||
/** @var CompareVersion */ | ||
private $compareVersion; | ||
|
||
/** @var string */ | ||
private $userId; | ||
|
||
|
@@ -62,13 +68,15 @@ public function __construct(string $appName, | |
AppointmentConfigService $appointmentConfigService, | ||
IInitialState $initialStateService, | ||
IAppManager $appManager, | ||
CompareVersion $compareVersion, | ||
?string $userId, | ||
IAppData $appData) { | ||
parent::__construct($appName, $request); | ||
$this->config = $config; | ||
$this->appointmentConfigService = $appointmentConfigService; | ||
$this->initialStateService = $initialStateService; | ||
$this->appManager = $appManager; | ||
$this->compareVersion = $compareVersion; | ||
$this->userId = $userId; | ||
$this->appData = $appData; | ||
} | ||
|
@@ -117,6 +125,11 @@ public function index():TemplateResponse { | |
$talkApiVersion = version_compare($this->appManager->getAppVersion('spreed'), '12.0.0', '>=') ? 'v4' : 'v1'; | ||
$tasksEnabled = $this->appManager->isEnabledForUser('tasks'); | ||
|
||
$circleVersion = $this->appManager->getAppVersion('circles'); | ||
$isCirclesEnabled = $this->appManager->isEnabledForUser('circles') === true; | ||
// if circles is not installed, we use 0.0.0 | ||
$isCircleVersionCompatible = $this->compareVersion->isCompatible($circleVersion ? $circleVersion : '0.0.0', '22'); | ||
|
||
$this->initialStateService->provideInitialState('app_version', $appVersion); | ||
$this->initialStateService->provideInitialState('event_limit', $eventLimit); | ||
$this->initialStateService->provideInitialState('first_run', $firstRun); | ||
|
@@ -138,6 +151,7 @@ public function index():TemplateResponse { | |
$this->initialStateService->provideInitialState('disable_appointments', $disableAppointments); | ||
$this->initialStateService->provideInitialState('can_subscribe_link', $canSubscribeLink); | ||
$this->initialStateService->provideInitialState('show_resources', $showResources); | ||
$this->initialStateService->provideInitialState('isCirclesEnabled', $isCirclesEnabled && $isCircleVersionCompatible); | ||
|
||
return new TemplateResponse($this->appName, 'main'); | ||
} | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,8 +1,10 @@ | ||
<!-- | ||
- @copyright Copyright (c) 2019 Georg Ehrke <[email protected]> | ||
- @copyright Copyright (c) 2023 Jonas Heinrich <[email protected]> | ||
- | ||
- @author Georg Ehrke <[email protected]> | ||
- @author Richard Steinmetz <[email protected]> | ||
- @author Jonas Heinrich <[email protected]> | ||
- | ||
- @license AGPL-3.0-or-later | ||
- | ||
|
@@ -25,6 +27,7 @@ | |
<div> | ||
<InviteesListSearch v-if="!isReadOnly && !isSharedWithMe && hasUserEmailAddress" | ||
:already-invited-emails="alreadyInvitedEmails" | ||
:organizer="calendarObjectInstance.organizer" | ||
@add-attendee="addAttendee" /> | ||
<OrganizerListItem v-if="hasOrganizer" | ||
:is-read-only="isReadOnly || isSharedWithMe" | ||
|
@@ -189,7 +192,7 @@ export default { | |
}, | ||
}, | ||
methods: { | ||
addAttendee({ commonName, email, calendarUserType, language, timezoneId }) { | ||
addAttendee({ commonName, email, calendarUserType, language, timezoneId, member }) { | ||
this.$store.commit('addAttendee', { | ||
calendarObjectInstance: this.calendarObjectInstance, | ||
commonName, | ||
|
@@ -201,6 +204,7 @@ export default { | |
language, | ||
timezoneId, | ||
organizer: this.$store.getters.getCurrentUserPrincipal, | ||
member, | ||
}) | ||
}, | ||
removeAttendee(attendee) { | ||
|
Oops, something went wrong.