From 251f450df63d37ceab8113ad813190bc8bd7a286 Mon Sep 17 00:00:00 2001 From: Joas Schilling Date: Mon, 23 May 2022 17:58:47 +0200 Subject: [PATCH 1/8] User status automation background job Signed-off-by: Joas Schilling --- apps/dav/lib/AppInfo/Application.php | 6 ++ .../BackgroundJob/UserStatusAutomation.php | 96 +++++++++++++++++++ .../lib/Listener/UserPreferenceListener.php | 59 ++++++++++++ 3 files changed, 161 insertions(+) create mode 100644 apps/dav/lib/BackgroundJob/UserStatusAutomation.php create mode 100644 apps/dav/lib/Listener/UserPreferenceListener.php diff --git a/apps/dav/lib/AppInfo/Application.php b/apps/dav/lib/AppInfo/Application.php index fe8405e09e2..86749862626 100644 --- a/apps/dav/lib/AppInfo/Application.php +++ b/apps/dav/lib/AppInfo/Application.php @@ -85,6 +85,7 @@ use OCA\DAV\Listener\CardListener; use OCA\DAV\Listener\ClearPhotoCacheListener; use OCA\DAV\Listener\SubscriptionListener; use OCA\DAV\Listener\TrustedServerRemovedListener; +use OCA\DAV\Listener\UserPreferenceListener; use OCA\DAV\Search\ContactsSearchProvider; use OCA\DAV\Search\EventsSearchProvider; use OCA\DAV\Search\TasksSearchProvider; @@ -96,6 +97,8 @@ use OCP\AppFramework\Bootstrap\IBootstrap; use OCP\AppFramework\Bootstrap\IRegistrationContext; use OCP\AppFramework\IAppContainer; use OCP\Calendar\IManager as ICalendarManager; +use OCP\Config\BeforePreferenceDeletedEvent; +use OCP\Config\BeforePreferenceSetEvent; use OCP\Contacts\IManager as IContactsManager; use OCP\IServerContainer; use OCP\IUser; @@ -186,6 +189,9 @@ class Application extends App implements IBootstrap { $context->registerEventListener(CardUpdatedEvent::class, ClearPhotoCacheListener::class); $context->registerEventListener(TrustedServerRemovedEvent::class, TrustedServerRemovedListener::class); + $context->registerEventListener(BeforePreferenceDeletedEvent::class, UserPreferenceListener::class); + $context->registerEventListener(BeforePreferenceSetEvent::class, UserPreferenceListener::class); + $context->registerNotifierService(Notifier::class); $context->registerCalendarProvider(CalendarProvider::class); diff --git a/apps/dav/lib/BackgroundJob/UserStatusAutomation.php b/apps/dav/lib/BackgroundJob/UserStatusAutomation.php new file mode 100644 index 00000000000..18f8de7deda --- /dev/null +++ b/apps/dav/lib/BackgroundJob/UserStatusAutomation.php @@ -0,0 +1,96 @@ + + * + * @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 . + * + */ + +namespace OCA\DAV\BackgroundJob; + +use OCA\DAV\CalDAV\Schedule\Plugin; +use OCP\AppFramework\Utility\ITimeFactory; +use OCP\BackgroundJob\IJobList; +use OCP\BackgroundJob\TimedJob; +use OCP\IConfig; +use OCP\IDBConnection; +use Psr\Log\LoggerInterface; +use Sabre\VObject\Reader; + +class UserStatusAutomation extends TimedJob { + protected IDBConnection $connection; + protected IJobList $jobList; + protected LoggerInterface $logger; + protected IConfig $config; + + public function __construct(ITimeFactory $timeFactory, + IDBConnection $connection, + IJobList $jobList, + LoggerInterface $logger, + IConfig $config) { + parent::__construct($timeFactory); + $this->connection = $connection; + $this->jobList = $jobList; + $this->logger = $logger; + $this->config = $config; + + $this->setInterval(1); // FIXME $this->setInterval(240); + } + + /** + * @inheritDoc + */ + protected function run($argument) { + if (!isset($argument['userId'])) { + $this->jobList->remove(self::class, $argument); + $this->logger->info('Removing invalid ' . self::class . ' background job'); + return; + } + + $userId = $argument['userId']; + $automationEnabled = $this->config->getUserValue($userId, 'dav', 'user_status_automation', 'no') === 'yes'; + if (!$automationEnabled) { + $this->logger->info('Removing ' . self::class . ' background job for user "' . $userId . '" because the setting is disabled'); + $this->jobList->remove(self::class, $argument); + return; + } + + $propertyPath = 'calendars/' . $userId . '/inbox'; + $propertyName = '{' . Plugin::NS_CALDAV . '}calendar-availability'; + + $query = $this->connection->getQueryBuilder(); + $query->select('propertyvalue') + ->from('properties') + ->where($query->expr()->eq('userid', $query->createNamedParameter($userId))) + ->andWhere($query->expr()->eq('propertypath', $query->createNamedParameter($propertyPath))) + ->where($query->expr()->eq('propertyname', $query->createNamedParameter($propertyName))) + ->setMaxResults(1); + + $result = $query->executeQuery(); + $property = $result->fetchOne(); + $result->closeCursor(); + + if (!$property) { + $this->logger->info('Removing ' . self::class . ' background job for user "' . $userId . '" because the user has no availability settings'); + $this->jobList->remove(self::class, $argument); + return; + } + + $this->logger->debug('User status automation ran'); + } +} diff --git a/apps/dav/lib/Listener/UserPreferenceListener.php b/apps/dav/lib/Listener/UserPreferenceListener.php new file mode 100644 index 00000000000..947f6d3fd01 --- /dev/null +++ b/apps/dav/lib/Listener/UserPreferenceListener.php @@ -0,0 +1,59 @@ + + * + * @author Joas Schilling + * + * @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 . + * + */ +namespace OCA\DAV\Listener; + +use OCA\DAV\BackgroundJob\UserStatusAutomation; +use OCP\BackgroundJob\IJobList; +use OCP\Config\BeforePreferenceDeletedEvent; +use OCP\Config\BeforePreferenceSetEvent; +use OCP\EventDispatcher\Event; +use OCP\EventDispatcher\IEventListener; + +class UserPreferenceListener implements IEventListener { + + protected IJobList $jobList; + + public function __construct(IJobList $jobList) { + $this->jobList = $jobList; + } + + public function handle(Event $event): void { + if ($event instanceof BeforePreferenceSetEvent) { + if ($event->getAppId() === 'dav' && $event->getConfigKey() === 'user_status_automation' && $event->getConfigValue() === 'yes') { + $event->setValid(true); + + // Not the cleanest way, but we just add the job in the before event. + // If something ever turns wrong the first execution will remove the job again. + // We also first delete the current job, so the next run time is reset. + $this->jobList->remove(UserStatusAutomation::class, ['userId' => $event->getUserId()]); + $this->jobList->add(UserStatusAutomation::class, ['userId' => $event->getUserId()]); + } + } elseif ($event instanceof BeforePreferenceDeletedEvent) { + if ($event->getAppId() === 'dav' && $event->getConfigKey() === 'user_status_automation') { + $event->setValid(true); + } + } + } +} From fdcf3eafd614612f5a55a9e03b2370d26dfdedcc Mon Sep 17 00:00:00 2001 From: Joas Schilling Date: Tue, 24 May 2022 14:11:42 +0200 Subject: [PATCH 2/8] Fix determination of cron job run Signed-off-by: Joas Schilling --- .../composer/composer/autoload_classmap.php | 2 + .../dav/composer/composer/autoload_static.php | 2 + .../BackgroundJob/UserStatusAutomation.php | 99 +++++++++++++++++-- 3 files changed, 95 insertions(+), 8 deletions(-) diff --git a/apps/dav/composer/composer/autoload_classmap.php b/apps/dav/composer/composer/autoload_classmap.php index 8c1bcf17516..b01ae68e43a 100644 --- a/apps/dav/composer/composer/autoload_classmap.php +++ b/apps/dav/composer/composer/autoload_classmap.php @@ -22,6 +22,7 @@ return array( 'OCA\\DAV\\BackgroundJob\\RegisterRegenerateBirthdayCalendars' => $baseDir . '/../lib/BackgroundJob/RegisterRegenerateBirthdayCalendars.php', 'OCA\\DAV\\BackgroundJob\\UpdateCalendarResourcesRoomsBackgroundJob' => $baseDir . '/../lib/BackgroundJob/UpdateCalendarResourcesRoomsBackgroundJob.php', 'OCA\\DAV\\BackgroundJob\\UploadCleanup' => $baseDir . '/../lib/BackgroundJob/UploadCleanup.php', + 'OCA\\DAV\\BackgroundJob\\UserStatusAutomation' => $baseDir . '/../lib/BackgroundJob/UserStatusAutomation.php', 'OCA\\DAV\\BulkUpload\\BulkUploadPlugin' => $baseDir . '/../lib/BulkUpload/BulkUploadPlugin.php', 'OCA\\DAV\\BulkUpload\\MultipartRequestParser' => $baseDir . '/../lib/BulkUpload/MultipartRequestParser.php', 'OCA\\DAV\\CalDAV\\Activity\\Backend' => $baseDir . '/../lib/CalDAV/Activity/Backend.php', @@ -247,6 +248,7 @@ return array( 'OCA\\DAV\\Listener\\ClearPhotoCacheListener' => $baseDir . '/../lib/Listener/ClearPhotoCacheListener.php', 'OCA\\DAV\\Listener\\SubscriptionListener' => $baseDir . '/../lib/Listener/SubscriptionListener.php', 'OCA\\DAV\\Listener\\TrustedServerRemovedListener' => $baseDir . '/../lib/Listener/TrustedServerRemovedListener.php', + 'OCA\\DAV\\Listener\\UserPreferenceListener' => $baseDir . '/../lib/Listener/UserPreferenceListener.php', 'OCA\\DAV\\Migration\\BuildCalendarSearchIndex' => $baseDir . '/../lib/Migration/BuildCalendarSearchIndex.php', 'OCA\\DAV\\Migration\\BuildCalendarSearchIndexBackgroundJob' => $baseDir . '/../lib/Migration/BuildCalendarSearchIndexBackgroundJob.php', 'OCA\\DAV\\Migration\\BuildSocialSearchIndex' => $baseDir . '/../lib/Migration/BuildSocialSearchIndex.php', diff --git a/apps/dav/composer/composer/autoload_static.php b/apps/dav/composer/composer/autoload_static.php index 29085a868de..4c9a1dcc793 100644 --- a/apps/dav/composer/composer/autoload_static.php +++ b/apps/dav/composer/composer/autoload_static.php @@ -37,6 +37,7 @@ class ComposerStaticInitDAV 'OCA\\DAV\\BackgroundJob\\RegisterRegenerateBirthdayCalendars' => __DIR__ . '/..' . '/../lib/BackgroundJob/RegisterRegenerateBirthdayCalendars.php', 'OCA\\DAV\\BackgroundJob\\UpdateCalendarResourcesRoomsBackgroundJob' => __DIR__ . '/..' . '/../lib/BackgroundJob/UpdateCalendarResourcesRoomsBackgroundJob.php', 'OCA\\DAV\\BackgroundJob\\UploadCleanup' => __DIR__ . '/..' . '/../lib/BackgroundJob/UploadCleanup.php', + 'OCA\\DAV\\BackgroundJob\\UserStatusAutomation' => __DIR__ . '/..' . '/../lib/BackgroundJob/UserStatusAutomation.php', 'OCA\\DAV\\BulkUpload\\BulkUploadPlugin' => __DIR__ . '/..' . '/../lib/BulkUpload/BulkUploadPlugin.php', 'OCA\\DAV\\BulkUpload\\MultipartRequestParser' => __DIR__ . '/..' . '/../lib/BulkUpload/MultipartRequestParser.php', 'OCA\\DAV\\CalDAV\\Activity\\Backend' => __DIR__ . '/..' . '/../lib/CalDAV/Activity/Backend.php', @@ -262,6 +263,7 @@ class ComposerStaticInitDAV 'OCA\\DAV\\Listener\\ClearPhotoCacheListener' => __DIR__ . '/..' . '/../lib/Listener/ClearPhotoCacheListener.php', 'OCA\\DAV\\Listener\\SubscriptionListener' => __DIR__ . '/..' . '/../lib/Listener/SubscriptionListener.php', 'OCA\\DAV\\Listener\\TrustedServerRemovedListener' => __DIR__ . '/..' . '/../lib/Listener/TrustedServerRemovedListener.php', + 'OCA\\DAV\\Listener\\UserPreferenceListener' => __DIR__ . '/..' . '/../lib/Listener/UserPreferenceListener.php', 'OCA\\DAV\\Migration\\BuildCalendarSearchIndex' => __DIR__ . '/..' . '/../lib/Migration/BuildCalendarSearchIndex.php', 'OCA\\DAV\\Migration\\BuildCalendarSearchIndexBackgroundJob' => __DIR__ . '/..' . '/../lib/Migration/BuildCalendarSearchIndexBackgroundJob.php', 'OCA\\DAV\\Migration\\BuildSocialSearchIndex' => __DIR__ . '/..' . '/../lib/Migration/BuildSocialSearchIndex.php', diff --git a/apps/dav/lib/BackgroundJob/UserStatusAutomation.php b/apps/dav/lib/BackgroundJob/UserStatusAutomation.php index 18f8de7deda..21e37571c2b 100644 --- a/apps/dav/lib/BackgroundJob/UserStatusAutomation.php +++ b/apps/dav/lib/BackgroundJob/UserStatusAutomation.php @@ -23,14 +23,19 @@ declare(strict_types=1); namespace OCA\DAV\BackgroundJob; +use DateTime; use OCA\DAV\CalDAV\Schedule\Plugin; use OCP\AppFramework\Utility\ITimeFactory; use OCP\BackgroundJob\IJobList; use OCP\BackgroundJob\TimedJob; +use OCP\DB\QueryBuilder\IQueryBuilder; use OCP\IConfig; use OCP\IDBConnection; use Psr\Log\LoggerInterface; +use Sabre\VObject\Component\Available; +use Sabre\VObject\Component\VAvailability; use Sabre\VObject\Reader; +use Sabre\VObject\Recur\RRuleIterator; class UserStatusAutomation extends TimedJob { protected IDBConnection $connection; @@ -49,7 +54,9 @@ class UserStatusAutomation extends TimedJob { $this->logger = $logger; $this->config = $config; - $this->setInterval(1); // FIXME $this->setInterval(240); + // Interval 0 might look weird, but the last_checked is always moved + // to the next time we need this and then it's 0 seconds ago. + $this->setInterval(0); } /** @@ -70,6 +77,88 @@ class UserStatusAutomation extends TimedJob { return; } + $property = $this->getAvailabilityFromPropertiesTable($userId); + + if (!$property) { + $this->logger->info('Removing ' . self::class . ' background job for user "' . $userId . '" because the user has no availability settings'); + $this->jobList->remove(self::class, $argument); + return; + } + + $isCurrentlyAvailable = false; + $nextPotentialToggles = []; + + $now = new \DateTime('now'); + $lastMidnight = (clone $now)->setTime(0, 0); + + $vObject = Reader::read($property); + foreach ($vObject->getComponents() as $component) { + if ($component->name !== 'VAVAILABILITY') { + continue; + } + /** @var VAvailability $component */ + $availables = $component->getComponents(); + foreach ($availables as $available) { + /** @var Available $available */ + if ($available->name === 'AVAILABLE') { + /** @var \DateTimeInterface $effectiveStart */ + /** @var \DateTimeInterface $effectiveEnd */ + [$effectiveStart, $effectiveEnd] = $available->getEffectiveStartEnd(); + + try { + $it = new RRuleIterator((string) $available->RRULE, $effectiveStart); + $it->fastForward($lastMidnight); + + $startToday = $it->current(); + if ($startToday && $startToday <= $now) { + $duration = $effectiveStart->diff($effectiveEnd); + $endToday = $startToday->add($duration); + if ($endToday > $now) { + // User is currently available + // Also queuing the end time as next status toggle + $isCurrentlyAvailable = true; + $nextPotentialToggles[] = $endToday->getTimestamp(); + } + + // Availability enabling already done for today, + // so jump to the next recurrence to find the next status toggle + $it->next(); + } + + if ($it->current()) { + $nextPotentialToggles[] = $it->current()->getTimestamp(); + } + } catch (\Exception $e) { + $this->logger->error($e->getMessage(), ['exception' => $e]); + } + } + } + } + + $nextAutomaticToggle = min($nextPotentialToggles); + $this->setLastRunToNextToggleTime($userId, $nextAutomaticToggle - 1); + + // FIXME Currently available so disable DND + $isCurrentlyAvailable = (bool)$isCurrentlyAvailable; + $this->logger->debug('User status automation ran'); + } + + protected function setLastRunToNextToggleTime(string $userId, int $timestamp): void { + $query = $this->connection->getQueryBuilder(); + + $query->update('jobs') + ->set('last_run', $query->createNamedParameter($timestamp, IQueryBuilder::PARAM_INT)) + ->where($query->expr()->eq('id', $query->createNamedParameter($this->getId(), IQueryBuilder::PARAM_INT))); + $query->executeStatement(); + + $this->logger->debug('Updated user status automation last_run to ' . $timestamp . ' for user ' . $userId); + } + + /** + * @param string $userId + * @return false|string + */ + protected function getAvailabilityFromPropertiesTable(string $userId) { $propertyPath = 'calendars/' . $userId . '/inbox'; $propertyName = '{' . Plugin::NS_CALDAV . '}calendar-availability'; @@ -85,12 +174,6 @@ class UserStatusAutomation extends TimedJob { $property = $result->fetchOne(); $result->closeCursor(); - if (!$property) { - $this->logger->info('Removing ' . self::class . ' background job for user "' . $userId . '" because the user has no availability settings'); - $this->jobList->remove(self::class, $argument); - return; - } - - $this->logger->debug('User status automation ran'); + return $property; } } From 5dee54d70bcd207c9b96a4cf6bb58f82fe9fbba9 Mon Sep 17 00:00:00 2001 From: Joas Schilling Date: Tue, 24 May 2022 14:40:59 +0200 Subject: [PATCH 3/8] Add status automation Signed-off-by: Joas Schilling --- .../dav/lib/BackgroundJob/UserStatusAutomation.php | 14 ++++++++++++-- lib/public/UserStatus/IUserStatus.php | 12 ++++++++++++ 2 files changed, 24 insertions(+), 2 deletions(-) diff --git a/apps/dav/lib/BackgroundJob/UserStatusAutomation.php b/apps/dav/lib/BackgroundJob/UserStatusAutomation.php index 21e37571c2b..0ead7aa0514 100644 --- a/apps/dav/lib/BackgroundJob/UserStatusAutomation.php +++ b/apps/dav/lib/BackgroundJob/UserStatusAutomation.php @@ -31,6 +31,8 @@ use OCP\BackgroundJob\TimedJob; use OCP\DB\QueryBuilder\IQueryBuilder; use OCP\IConfig; use OCP\IDBConnection; +use OCP\UserStatus\IManager; +use OCP\UserStatus\IUserStatus; use Psr\Log\LoggerInterface; use Sabre\VObject\Component\Available; use Sabre\VObject\Component\VAvailability; @@ -41,17 +43,20 @@ class UserStatusAutomation extends TimedJob { protected IDBConnection $connection; protected IJobList $jobList; protected LoggerInterface $logger; + protected IManager $manager; protected IConfig $config; public function __construct(ITimeFactory $timeFactory, IDBConnection $connection, IJobList $jobList, LoggerInterface $logger, + IManager $manager, IConfig $config) { parent::__construct($timeFactory); $this->connection = $connection; $this->jobList = $jobList; $this->logger = $logger; + $this->manager = $manager; $this->config = $config; // Interval 0 might look weird, but the last_checked is always moved @@ -138,8 +143,13 @@ class UserStatusAutomation extends TimedJob { $nextAutomaticToggle = min($nextPotentialToggles); $this->setLastRunToNextToggleTime($userId, $nextAutomaticToggle - 1); - // FIXME Currently available so disable DND - $isCurrentlyAvailable = (bool)$isCurrentlyAvailable; + if ($isCurrentlyAvailable) { + $this->manager->revertUserStatus($userId, IUserStatus::MESSAGE_AVAILABILITY, IUserStatus::DND); + } else { + // The DND status automation is more important than the "Away - In call" so we also restore that one if it exists. + $this->manager->revertUserStatus($userId, IUserStatus::MESSAGE_CALL, IUserStatus::AWAY); + $this->manager->setUserStatus($userId, IUserStatus::MESSAGE_AVAILABILITY, IUserStatus::DND, true); + } $this->logger->debug('User status automation ran'); } diff --git a/lib/public/UserStatus/IUserStatus.php b/lib/public/UserStatus/IUserStatus.php index bf743dea08d..8803b328ad5 100644 --- a/lib/public/UserStatus/IUserStatus.php +++ b/lib/public/UserStatus/IUserStatus.php @@ -64,6 +64,18 @@ interface IUserStatus { */ public const INVISIBLE = 'invisible'; + /** + * @var string + * @since 25.0.0 + */ + public const MESSAGE_CALL = 'call'; + + /** + * @var string + * @since 25.0.0 + */ + public const MESSAGE_AVAILABILITY = 'availability'; + /** * Get the user this status is connected to * From 4f7f4d74db0464b255eeedd4890b0604540e1e60 Mon Sep 17 00:00:00 2001 From: Joas Schilling Date: Tue, 24 May 2022 15:49:34 +0200 Subject: [PATCH 4/8] Add UI to opt-in on the status automation Signed-off-by: Joas Schilling --- .../dav/lib/Settings/AvailabilitySettings.php | 25 ++++++++++ apps/dav/src/service/PreferenceService.js | 50 +++++++++++++++++++ apps/dav/src/views/Availability.vue | 17 +++++++ dist/dav-settings-personal-availability.js | 4 +- ...tings-personal-availability.js.LICENSE.txt | 21 ++++++++ .../dav-settings-personal-availability.js.map | 2 +- 6 files changed, 116 insertions(+), 3 deletions(-) create mode 100644 apps/dav/src/service/PreferenceService.js diff --git a/apps/dav/lib/Settings/AvailabilitySettings.php b/apps/dav/lib/Settings/AvailabilitySettings.php index 9a163e21edb..2bafdfab9d7 100644 --- a/apps/dav/lib/Settings/AvailabilitySettings.php +++ b/apps/dav/lib/Settings/AvailabilitySettings.php @@ -27,10 +27,35 @@ namespace OCA\DAV\Settings; use OCA\DAV\AppInfo\Application; use OCP\AppFramework\Http\TemplateResponse; +use OCP\AppFramework\Services\IInitialState; +use OCP\IConfig; +use OCP\IUserSession; use OCP\Settings\ISettings; class AvailabilitySettings implements ISettings { + protected IUserSession $userSession; + protected IConfig $config; + protected IInitialState $initialState; + + public function __construct(IUserSession $userSession, + IConfig $config, + IInitialState $initialState) { + $this->userSession = $userSession; + $this->config = $config; + $this->initialState = $initialState; + } + public function getForm(): TemplateResponse { + $this->initialState->provideInitialState( + 'user_status_automation', + $this->config->getUserValue( + $this->userSession->getUser()->getUID(), + 'dav', + 'user_status_automation', + 'no' + ) + ); + return new TemplateResponse(Application::APP_ID, 'settings-personal-availability'); } diff --git a/apps/dav/src/service/PreferenceService.js b/apps/dav/src/service/PreferenceService.js new file mode 100644 index 00000000000..6b8d29029b5 --- /dev/null +++ b/apps/dav/src/service/PreferenceService.js @@ -0,0 +1,50 @@ +/** + * @copyright 2022 Joas Schilling + * + * @author Joas Schilling + * + * @license AGPL-3.0-or-later + * + * 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 . + */ + +import axios from '@nextcloud/axios' +import { generateOcsUrl } from '@nextcloud/router' + +/** + * Enable user status automation based on availability + */ +export async function enableUserStatusAutomation() { + return await axios.post( + generateOcsUrl('/apps/provisioning_api/api/v1/config/users/{appId}/{configKey}', { + appId: 'dav', + configKey: 'user_status_automation', + }), + { + configValue: 'yes', + } + ) +} + +/** + * Disable user status automation based on availability + */ +export async function disableUserStatusAutomation() { + return await axios.delete( + generateOcsUrl('/apps/provisioning_api/api/v1/config/users/{appId}/{configKey}', { + appId: 'dav', + configKey: 'user_status_automation', + }) + ) +} diff --git a/apps/dav/src/views/Availability.vue b/apps/dav/src/views/Availability.vue index f3b3ec34bd2..0441f5e9dc7 100644 --- a/apps/dav/src/views/Availability.vue +++ b/apps/dav/src/views/Availability.vue @@ -24,6 +24,10 @@ :l10n-saturday="$t('dav', 'Saturday')" :l10n-sunday="$t('dav', 'Sunday')" /> + + {{ $t('dav', 'Automatically set user status to "Do not distrub" outside of visibility to mute all notifications.') }} + +