Skip to content

Commit

Permalink
Create Talk rooms for appointments
Browse files Browse the repository at this point in the history
Signed-off-by: Christoph Wurst <[email protected]>
  • Loading branch information
ChristophWurst committed Apr 20, 2023
1 parent 422604b commit ac52bb6
Show file tree
Hide file tree
Showing 18 changed files with 347 additions and 35 deletions.
2 changes: 1 addition & 1 deletion appinfo/info.xml
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
* ☑️ Tasks! See tasks with a due date directly in the calendar
* 🙈 **We’re not reinventing the wheel!** Based on the great [c-dav library](https://github.com/nextcloud/cdav-library), [ical.js](https://github.com/mozilla-comm/ical.js) and [fullcalendar](https://github.com/fullcalendar/fullcalendar) libraries.
]]></description>
<version>4.4.0-alpha.1</version>
<version>4.4.0-alpha.2</version>
<licence>agpl</licence>
<author>Anna Larch</author>
<author homepage="https://github.com/nextcloud/groupware">Nextcloud Groupware Team</author>
Expand Down
3 changes: 3 additions & 0 deletions lib/AppInfo/Application.php
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@
namespace OCA\Calendar\AppInfo;

use OCA\Calendar\Dashboard\CalendarWidget;
use OCA\Calendar\Events\AppointmentBookedEvent;
use OCA\Calendar\Listener\AppointmentBookedListener;
use OCA\Calendar\Listener\UserDeletedListener;
use OCA\Calendar\Notification\Notifier;
use OCA\Calendar\Profile\AppointmentsAction;
Expand Down Expand Up @@ -56,6 +58,7 @@ public function register(IRegistrationContext $context): void {
$context->registerProfileLinkAction(AppointmentsAction::class);
}

$context->registerEventListener(AppointmentBookedEvent::class, AppointmentBookedListener::class);
$context->registerEventListener(UserDeletedEvent::class, UserDeletedListener::class);

$context->registerNotifierService(Notifier::class);
Expand Down
10 changes: 7 additions & 3 deletions lib/Controller/AppointmentConfigController.php
Original file line number Diff line number Diff line change
Expand Up @@ -164,7 +164,8 @@ public function create(
?array $calendarFreeBusyUris = null,
?int $start = null,
?int $end = null,
?int $futureLimit = null): JsonResponse {
?int $futureLimit = null,
?bool $createTalkRoom = false): JsonResponse {
if ($this->userId === null) {
return JsonResponse::fail();
}
Expand Down Expand Up @@ -192,7 +193,8 @@ public function create(
$calendarFreeBusyUris,
$start,
$end,
$futureLimit
$futureLimit,
$createTalkRoom
);
return JsonResponse::success($appointmentConfig);
} catch (ServiceException $e) {
Expand Down Expand Up @@ -240,7 +242,8 @@ public function update(
?array $calendarFreeBusyUris = null,
?int $start = null,
?int $end = null,
?int $futureLimit = null): JsonResponse {
?int $futureLimit = null,
?bool $createTalkRoom = false): JsonResponse {
if ($this->userId === null) {
return JsonResponse::fail(null, Http::STATUS_NOT_FOUND);
}
Expand Down Expand Up @@ -274,6 +277,7 @@ public function update(
$appointmentConfig->setStart($start);
$appointmentConfig->setEnd($end);
$appointmentConfig->setFutureLimit($futureLimit);
$appointmentConfig->setCreateTalkRoom($createTalkRoom === true);

try {
$appointmentConfig = $this->appointmentConfigService->update($appointmentConfig);
Expand Down
9 changes: 8 additions & 1 deletion lib/Db/AppointmentConfig.php
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,8 @@
* @method void setDailyMax(?int $max)
* @method int|null getFutureLimit()
* @method void setFutureLimit(?int $limit)
* @method int|null getCreateTalkRoom()
* @method void setCreateTalkRoom(bool $create)
*/
class AppointmentConfig extends Entity implements JsonSerializable {
/** @var string */
Expand Down Expand Up @@ -127,6 +129,9 @@ class AppointmentConfig extends Entity implements JsonSerializable {
/** @var int|null */
protected $futureLimit;

/** @var bool */
protected $createTalkRoom;

/** @var string */
public const VISIBILITY_PUBLIC = 'PUBLIC';

Expand All @@ -143,6 +148,7 @@ public function __construct() {
$this->addType('timeBeforeNextSlot', 'int');
$this->addType('dailyMax', 'int');
$this->addType('futureLimit', 'int');
$this->addType('createTalkRoom', 'boolean');
}

/**
Expand Down Expand Up @@ -205,7 +211,8 @@ public function jsonSerialize() {
'totalLength' => $this->getTotalLength(),
'timeBeforeNextSlot' => $this->getTimeBeforeNextSlot(),
'dailyMax' => $this->getDailyMax(),
'futureLimit' => $this->getFutureLimit()
'futureLimit' => $this->getFutureLimit(),
'createTalkRoom' => $this->getCreateTalkRoom(),
];
}
}
15 changes: 15 additions & 0 deletions lib/Db/Booking.php
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,13 @@ class Booking extends Entity implements JsonSerializable {
/** @var bool */
protected $confirmed;

/**
* Transient talk URL
*
* @var string|null
*/
private $talkUrl;

public function __construct() {
$this->addType('id', 'integer');
$this->addType('apptConfigId', 'integer');
Expand All @@ -110,4 +117,12 @@ public function jsonSerialize() {
'confirmed' => $this->isConfirmed(),
];
}

public function getTalkUrl(): ?string {
return $this->talkUrl;
}

public function setTalkUrl(string $talkUrl): void {
$this->talkUrl = $talkUrl;
}
}
54 changes: 54 additions & 0 deletions lib/Events/AppointmentBookedEvent.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
<?php

declare(strict_types=1);

/*
* @copyright 2022 Christoph Wurst <[email protected]>
*
* @author 2022 Christoph Wurst <[email protected]>
*
* @license GNU AGPL version 3 or any later version
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/

namespace OCA\Calendar\Events;

use OCA\Calendar\Db\AppointmentConfig;
use OCA\Calendar\Db\Booking;
use OCP\EventDispatcher\Event;

class AppointmentBookedEvent extends Event {

/** @var Booking */
private $booking;
/** @var AppointmentConfig */

private $config;

public function __construct(Booking $booking, AppointmentConfig $config) {
parent::__construct();

$this->booking = $booking;
$this->config = $config;
}

public function getBooking(): Booking {
return $this->booking;
}

public function getConfig(): AppointmentConfig {
return $this->config;
}
}
100 changes: 100 additions & 0 deletions lib/Listener/AppointmentBookedListener.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
<?php

declare(strict_types=1);

/*
* @copyright 2022 Christoph Wurst <[email protected]>
*
* @author 2022 Christoph Wurst <[email protected]>
*
* @license GNU AGPL version 3 or any later version
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/

namespace OCA\Calendar\Listener;

use OCA\Calendar\Events\AppointmentBookedEvent;
use OCP\EventDispatcher\Event;
use OCP\EventDispatcher\IEventListener;
use OCP\IL10N;
use OCP\IUserManager;
use OCP\Talk\IBroker;
use Psr\Log\LoggerInterface;

class AppointmentBookedListener implements IEventListener {

/** @var IBroker */
private $broker;

/** @var IUserManager */
private $userManager;

private IL10N $l10n;

/** @var LoggerInterface */
private $logger;

public function __construct(IBroker $broker,
IUserManager $userManager,
IL10N $l10n,
LoggerInterface $logger) {
$this->broker = $broker;
$this->userManager = $userManager;
$this->l10n = $l10n;
$this->logger = $logger;
}

public function handle(Event $event): void {
if (!($event instanceof AppointmentBookedEvent)) {
// Don't care
return;
}

if (!$event->getConfig()->getCreateTalkRoom()) {
$this->logger->debug('Booked appointment of config {config} does not need a Talk room', [
'config' => $event->getConfig()->getId(),
]);
return;
}

if (!$this->broker->hasBackend()) {
$this->logger->warning('Can not create Talk room for config {config} because there is no backend', [
'config' => $event->getConfig()->getId(),
]);
return;
}

$organizer = $this->userManager->get($event->getConfig()->getUserId());
if ($organizer === null) {
$this->logger->error('Could not find appointment owner {uid}', [
'uid' => $event->getConfig()->getUserId(),
]);
return;
}
$conversationName = $this->l10n->t('%s with %s', [
$event->getConfig()->getName(),
$event->getBooking()->getDisplayName(),
]);
$conversation = $this->broker->createConversation(
$conversationName,
[$organizer],
$this->broker->newConversationOptions(),
);
$event->getBooking()->setTalkUrl(
$conversation->getAbsoluteUrl(),
);
}

}
55 changes: 55 additions & 0 deletions lib/Migration/Version4004Date20230414163505.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
<?php

declare(strict_types=1);

/*
* @copyright 2022 Christoph Wurst <[email protected]>
*
* @author 2022 Christoph Wurst <[email protected]>
*
* @license GNU AGPL version 3 or any later version
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/

namespace OCA\Calendar\Migration;

use Closure;
use OCP\DB\ISchemaWrapper;
use OCP\DB\Types;
use OCP\Migration\IOutput;
use OCP\Migration\SimpleMigrationStep;

class Version4004Date20230414163505 extends SimpleMigrationStep {

/**
* @param IOutput $output
* @param Closure $schemaClosure The `\Closure` returns a `ISchemaWrapper`
* @param array $options
* @return null|ISchemaWrapper
*/
public function changeSchema(IOutput $output, Closure $schemaClosure, array $options): ?ISchemaWrapper {
/** @var ISchemaWrapper $schema */
$schema = $schemaClosure();

$table = $schema->getTable('calendar_appt_configs');
$table->addColumn('create_talk_room', Types::BOOLEAN, [
'notnull' => false,
'default' => false,
]);

return $schema;
}

}
22 changes: 3 additions & 19 deletions lib/Service/Appointments/AppointmentConfigService.php
Original file line number Diff line number Diff line change
Expand Up @@ -142,24 +142,6 @@ public function findByIdAndUser(int $id, string $userId): AppointmentConfig {
}

/**
* @param string $name
* @param string $description
* @param string|null $location
* @param string $visibility
* @param string $userId
* @param string $targetCalendarUri
* @param array $availability
* @param int $length
* @param int $increment
* @param int $preparationDuration
* @param int $followupDuration
* @param int $buffer
* @param int|null $dailyMax
* @param string[] $calendarFreeBusyUris
* @param int|null $start
* @param int|null $end
* @param int|null $futureLimit
* @return AppointmentConfig
* @throws ServiceException
*/
public function create(string $name,
Expand All @@ -178,7 +160,8 @@ public function create(string $name,
?array $calendarFreeBusyUris = [],
?int $start = null,
?int $end = null,
?int $futureLimit = null): AppointmentConfig {
?int $futureLimit = null,
?bool $createTalkRoom = false): AppointmentConfig {
try {
$appointmentConfig = new AppointmentConfig();
$appointmentConfig->setToken($this->random->generate(12, ISecureRandom::CHAR_HUMAN_READABLE));
Expand All @@ -199,6 +182,7 @@ public function create(string $name,
$appointmentConfig->setStart($start);
$appointmentConfig->setEnd($end);
$appointmentConfig->setFutureLimit($futureLimit);
$appointmentConfig->setCreateTalkRoom($createTalkRoom === true);

return $this->mapper->insert($appointmentConfig);
} catch (DbException $e) {
Expand Down
Loading

0 comments on commit ac52bb6

Please sign in to comment.