Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add birthday calendar configuration to groupware personal settings UI #33397

Closed
wants to merge 10 commits into from
1 change: 1 addition & 0 deletions apps/dav/appinfo/info.xml
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@
<settings>
<admin>OCA\DAV\Settings\CalDAVSettings</admin>
<personal>OCA\DAV\Settings\AvailabilitySettings</personal>
<personal>OCA\DAV\Settings\BirthdayCalendarSettings</personal>
</settings>

<activity>
Expand Down
1 change: 1 addition & 0 deletions apps/dav/composer/composer/autoload_classmap.php
Original file line number Diff line number Diff line change
Expand Up @@ -294,6 +294,7 @@
'OCA\\DAV\\Search\\TasksSearchProvider' => $baseDir . '/../lib/Search/TasksSearchProvider.php',
'OCA\\DAV\\Server' => $baseDir . '/../lib/Server.php',
'OCA\\DAV\\Settings\\AvailabilitySettings' => $baseDir . '/../lib/Settings/AvailabilitySettings.php',
'OCA\\DAV\\Settings\\BirthdayCalendarSettings' => $baseDir . '/../lib/Settings/BirthdayCalendarSettings.php',
'OCA\\DAV\\Settings\\CalDAVSettings' => $baseDir . '/../lib/Settings/CalDAVSettings.php',
'OCA\\DAV\\Storage\\PublicOwnerWrapper' => $baseDir . '/../lib/Storage/PublicOwnerWrapper.php',
'OCA\\DAV\\SystemTag\\SystemTagMappingNode' => $baseDir . '/../lib/SystemTag/SystemTagMappingNode.php',
Expand Down
1 change: 1 addition & 0 deletions apps/dav/composer/composer/autoload_static.php
Original file line number Diff line number Diff line change
Expand Up @@ -309,6 +309,7 @@ class ComposerStaticInitDAV
'OCA\\DAV\\Search\\TasksSearchProvider' => __DIR__ . '/..' . '/../lib/Search/TasksSearchProvider.php',
'OCA\\DAV\\Server' => __DIR__ . '/..' . '/../lib/Server.php',
'OCA\\DAV\\Settings\\AvailabilitySettings' => __DIR__ . '/..' . '/../lib/Settings/AvailabilitySettings.php',
'OCA\\DAV\\Settings\\BirthdayCalendarSettings' => __DIR__ . '/..' . '/../lib/Settings/BirthdayCalendarSettings.php',
'OCA\\DAV\\Settings\\CalDAVSettings' => __DIR__ . '/..' . '/../lib/Settings/CalDAVSettings.php',
'OCA\\DAV\\Storage\\PublicOwnerWrapper' => __DIR__ . '/..' . '/../lib/Storage/PublicOwnerWrapper.php',
'OCA\\DAV\\SystemTag\\SystemTagMappingNode' => __DIR__ . '/..' . '/../lib/SystemTag/SystemTagMappingNode.php',
Expand Down
3 changes: 2 additions & 1 deletion apps/dav/l10n/en_GB.js
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@ OC.L10N.register(
"Birthday calendars will be generated by a background job." : "Birthday calendars will be generated by a background job.",
"Hence they will not be available immediately after enabling but will show up after some time." : "Hence they will not be available immediately after enabling but will show up after some time.",
"Hello %s," : "Hello %s,",
"When:" : "When:"
"When:" : "When:",
"No reminder on birthday" : "None"
cneukom marked this conversation as resolved.
Show resolved Hide resolved
},
"nplurals=2; plural=(n != 1);");
5 changes: 3 additions & 2 deletions apps/dav/l10n/en_GB.json
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@
"Birthday calendars will be generated by a background job." : "Birthday calendars will be generated by a background job.",
"Hence they will not be available immediately after enabling but will show up after some time." : "Hence they will not be available immediately after enabling but will show up after some time.",
"Hello %s," : "Hello %s,",
"When:" : "When:"
"When:" : "When:",
"No reminder on birthday" : "None"
},"pluralForm" :"nplurals=2; plural=(n != 1);"
}
}
39 changes: 32 additions & 7 deletions apps/dav/lib/Listener/UserPreferenceListener.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
declare(strict_types=1);
/**
* @copyright Copyright (c) 2022 Joas Schilling <coding@schilljs.com>
* @copyright Copyright (c) 2022 Cédric Neukom <github@webguy.ch>
*
* @author Joas Schilling <coding@schilljs.com>
*
Expand All @@ -24,6 +25,7 @@
*/
namespace OCA\DAV\Listener;

use DateInterval;
use OCA\DAV\BackgroundJob\UserStatusAutomation;
use OCP\BackgroundJob\IJobList;
use OCP\Config\BeforePreferenceDeletedEvent;
Expand All @@ -41,14 +43,37 @@ public function __construct(IJobList $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);
if ($event->getAppId() === 'dav') {
switch ($event->getConfigKey()) {
case 'user_status_automation':
if ($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()]);
}
break;

// 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()]);
case 'birthdayCalendarReminderOffset':
$configValue = $event->getConfigValue();
if (empty($configValue)) {
$event->setValid(true);
break;
}
if ($configValue[0] === '-') {
$configValue = substr($configValue, 1);
}
try {
new DateInterval($configValue);
$event->setValid(true);
} catch (\Exception $e) {
// Client attempted with an invalid duration string, do nothing
}
break;
}
}
} elseif ($event instanceof BeforePreferenceDeletedEvent) {
if ($event->getAppId() === 'dav' && $event->getConfigKey() === 'user_status_automation') {
Expand Down
67 changes: 67 additions & 0 deletions apps/dav/lib/Settings/BirthdayCalendarSettings.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
<?php
/*
* @copyright 2022 Cédric Neukom <github@webguy.ch>
*
* @author 2022 Cédric Neukom <github@webguy.ch>
*
* @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/>.
*/

declare(strict_types=1);

namespace OCA\DAV\Settings;

use OCA\DAV\AppInfo\Application;
use OCP\AppFramework\Http\TemplateResponse;
use OCP\AppFramework\Services\IInitialState;
use OCP\IConfig;
use OCP\Settings\ISettings;

class BirthdayCalendarSettings implements ISettings {
protected IConfig $config;
protected IInitialState $initialState;
protected ?string $userId;

public function __construct(IConfig $config,
IInitialState $initialState,
?string $userId) {
$this->config = $config;
$this->initialState = $initialState;
$this->userId = $userId;
}

public function getForm(): TemplateResponse {
$this->initialState->provideInitialState(
cneukom marked this conversation as resolved.
Show resolved Hide resolved
'userBirthdayCalendar',
$this->config->getUserValue(
$this->userId,
'dav',
'user_status_automation',
cneukom marked this conversation as resolved.
Show resolved Hide resolved
'no'
)
);

return new TemplateResponse(Application::APP_ID, 'settings-personal-birthday-calendar');
}

public function getSection(): string {
return 'groupware';
}

public function getPriority(): int {
return 20;
}
}
89 changes: 89 additions & 0 deletions apps/dav/src/service/BirthdayCalendarService.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
/**
* @copyright 2022 Cédric Neukom <github@webguy.ch>
*
* @author 2022 Cédric Neukom <github@webguy.ch>
*
* @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 <http://www.gnu.org/licenses/>.
*/
import axios from '@nextcloud/axios'
import { generateOcsUrl } from '@nextcloud/router'
import { getClient } from '../dav/client'

const CALDAV_BIRTHDAY_CALENDAR = 'contact_birthdays'

/**
* Checks if the birthday calendar is currently enabled by looking it up at the DAV server
*
* @returns {Promise<boolean>}
*/
export async function isBirthdayCalendarEnabled() {
const client = getClient('calendars')
try {
await client.customRequest(CALDAV_BIRTHDAY_CALENDAR, {
method: 'PROPFIND',
})
return true
} catch (e) {
if (e.status === 404) {
return false
} else {
throw e
}
}
}

/**
* Disable birthday calendar
*
* @returns {Promise<void>}
*/
export async function disableBirthdayCalendar() {
const client = getClient('calendars')
await client.customRequest(CALDAV_BIRTHDAY_CALENDAR, {
method: 'DELETE',
})
}

/**
* Enable birthday calendar
*
* @returns {Promise<void>}
*/
export async function enableBirthdayCalendar() {
const client = getClient('calendars')
await client.customRequest('', {
method: 'POST',
data: '<x3:enable-birthday-calendar xmlns:x3="http://nextcloud.com/ns"/>',
})
}

/**
* Save birthday reminder offset. Value must be a duration (e.g. -PT15H)
*
* @param reminderOffset
* @returns {Promise<AxiosResponse<any>>}
*/
export async function saveBirthdayReminder(reminderOffset) {
return await axios.post(
generateOcsUrl('/apps/provisioning_api/api/v1/config/users/{appId}/{configKey}', {
appId: 'dav',
configKey: 'birthdayCalendarReminderOffset',
}),
{
configValue: reminderOffset,
}
)
}
9 changes: 9 additions & 0 deletions apps/dav/src/settings-personal-birthday-calendar.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import Vue from 'vue'
import { translate } from '@nextcloud/l10n'
import BirthdayCalendarSettings from './views/BirthdayCalendarSettings'

Vue.prototype.$t = translate

const View = Vue.extend(BirthdayCalendarSettings);

(new View({})).$mount('#settings-personal-birthday-calendar')
Loading