-
-
Notifications
You must be signed in to change notification settings - Fork 4.1k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(dav): implement personal absence settings
Signed-off-by: Richard Steinmetz <richard@steinmetz.cloud>
- Loading branch information
Showing
12 changed files
with
561 additions
and
191 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
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
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
94 changes: 94 additions & 0 deletions
94
apps/dav/lib/Controller/AvailabilitySettingsController.php
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 |
---|---|---|
@@ -0,0 +1,94 @@ | ||
<?php | ||
|
||
declare(strict_types=1); | ||
|
||
/** | ||
* @copyright Copyright (c) 2023 Richard Steinmetz <richard@steinmetz.cloud> | ||
* | ||
* @author Richard Steinmetz <richard@steinmetz.cloud> | ||
* | ||
* @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 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 General Public License for more details. | ||
* | ||
* You should have received a copy of the GNU General Public License | ||
* along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
* | ||
*/ | ||
|
||
namespace OCA\DAV\Controller; | ||
|
||
use DateTimeImmutable; | ||
use OCA\DAV\AppInfo\Application; | ||
use OCA\DAV\Service\AbsenceService; | ||
use OCP\AppFramework\Controller; | ||
use OCP\AppFramework\Http; | ||
use OCP\AppFramework\Http\Attribute\NoAdminRequired; | ||
use OCP\AppFramework\Http\JSONResponse; | ||
use OCP\AppFramework\Http\Response; | ||
use OCP\IRequest; | ||
|
||
class AvailabilitySettingsController extends Controller { | ||
public function __construct( | ||
IRequest $request, | ||
private ?string $userId, | ||
private AbsenceService $absenceService, | ||
) { | ||
parent::__construct(Application::APP_ID, $request); | ||
} | ||
|
||
/** | ||
* @throws \OCP\DB\Exception | ||
* @throws \Exception | ||
*/ | ||
#[NoAdminRequired] | ||
public function updateAbsence( | ||
string $firstDay, | ||
string $lastDay, | ||
string $status, | ||
string $message, | ||
): Response { | ||
$userId = $this->userId; | ||
if ($userId === null) { | ||
return new JSONResponse([], Http::STATUS_FORBIDDEN); | ||
} | ||
|
||
$parsedFirstDay = new DateTimeImmutable($firstDay); | ||
$parsedLastDay = new DateTimeImmutable($lastDay); | ||
if ($parsedFirstDay->getTimestamp() >= $parsedLastDay->getTimestamp()) { | ||
throw new \Exception('First day is on or after last day'); | ||
} | ||
|
||
$absence = $this->absenceService->createOrUpdateAbsence( | ||
$userId, | ||
$firstDay, | ||
$lastDay, | ||
$status, | ||
$message, | ||
); | ||
return new JSONResponse($absence); | ||
} | ||
|
||
/** | ||
* @throws \OCP\DB\Exception | ||
*/ | ||
#[NoAdminRequired] | ||
public function clearAbsence(): Response { | ||
$userId = $this->userId; | ||
if ($userId === null) { | ||
return new JSONResponse([], Http::STATUS_FORBIDDEN); | ||
} | ||
|
||
$this->absenceService->clearAbsence($userId); | ||
return new JSONResponse([]); | ||
} | ||
|
||
} |
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
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 |
---|---|---|
@@ -0,0 +1,160 @@ | ||
<!-- | ||
- @copyright Copyright (c) 2023 Richard Steinmetz <richard@steinmetz.cloud> | ||
- | ||
- @author Richard Steinmetz <richard@steinmetz.cloud> | ||
- | ||
- @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 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 General Public License for more details. | ||
- | ||
- You should have received a copy of the GNU General Public License | ||
- along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
- | ||
--> | ||
|
||
<template> | ||
<div class="absence"> | ||
<div class="absence__dates"> | ||
<NcDateTimePickerNative id="absence-first-day" | ||
v-model="firstDay" | ||
:label="$t('dav', 'First day')" | ||
class="absence__dates__picker" /> | ||
<NcDateTimePickerNative id="absence-last-day" | ||
v-model="lastDay" | ||
:label="$t('dav', 'Last day (inclusive)')" | ||
class="absence__dates__picker" /> | ||
</div> | ||
<NcTextField :value.sync="status" :label="$t('dav', 'Short absence status')" /> | ||
<NcTextArea :value.sync="message" :label="$t('dav', 'Long absence Message')" /> | ||
|
||
<div class="absence__buttons"> | ||
<NcButton :disabled="loading || !valid" | ||
type="primary" | ||
@click="saveForm"> | ||
{{ $t('dav', 'Save') }} | ||
</NcButton> | ||
<NcButton :disabled="loading || !valid" | ||
type="error" | ||
@click="clearAbsence"> | ||
{{ $t('dav', 'Disable absence') }} | ||
</NcButton> | ||
</div> | ||
</div> | ||
</template> | ||
|
||
<script> | ||
import NcButton from '@nextcloud/vue/dist/Components/NcButton.js' | ||
import NcTextField from '@nextcloud/vue/dist/Components/NcTextField.js' | ||
import NcTextArea from '@nextcloud/vue/dist/Components/NcTextArea.js' | ||
import NcDateTimePickerNative from '@nextcloud/vue/dist/Components/NcDateTimePickerNative.js' | ||
import { generateUrl } from '@nextcloud/router' | ||
import axios from '@nextcloud/axios' | ||
import { formatDateAsYMD } from '../utils/date.js' | ||
import { loadState } from '@nextcloud/initial-state' | ||
import { showError } from '@nextcloud/dialogs' | ||
|
||
export default { | ||
name: 'AbsenceForm', | ||
components: { | ||
NcButton, | ||
NcTextField, | ||
NcTextArea, | ||
NcDateTimePickerNative, | ||
}, | ||
data() { | ||
const { firstDay, lastDay, status, message } = loadState('dav', 'absence', {}) | ||
|
||
return { | ||
loading: false, | ||
status: status ?? '', | ||
message: message ?? '', | ||
firstDay: firstDay ? new Date(firstDay) : new Date(), | ||
lastDay: lastDay ? new Date(lastDay) : null, | ||
} | ||
}, | ||
computed: { | ||
/** | ||
* @return {boolean} | ||
*/ | ||
valid() { | ||
return !!this.firstDay | ||
&& !!this.lastDay | ||
&& !!this.status | ||
&& this.lastDay > this.firstDay | ||
}, | ||
}, | ||
methods: { | ||
resetForm() { | ||
this.status = '' | ||
this.message = '' | ||
this.firstDay = new Date() | ||
this.lastDay = null | ||
}, | ||
async saveForm() { | ||
if (!this.valid) { | ||
return | ||
} | ||
|
||
this.loading = true | ||
try { | ||
await axios.post(generateUrl('/apps/dav/settings/absence'), { | ||
firstDay: formatDateAsYMD(this.firstDay), | ||
lastDay: formatDateAsYMD(this.lastDay), | ||
status: this.status, | ||
message: this.message, | ||
}) | ||
} catch (error) { | ||
showError(this.$t('dav', 'Failed to save your absence settings')) | ||
} finally { | ||
this.loading = false | ||
} | ||
}, | ||
async clearAbsence() { | ||
this.loading = true | ||
try { | ||
await axios.delete(generateUrl('/apps/dav/settings/absence')) | ||
this.resetForm() | ||
} catch (error) { | ||
// TODO: Handle error | ||
} finally { | ||
this.loading = false | ||
} | ||
}, | ||
}, | ||
} | ||
</script> | ||
|
||
<style lang="scss" scoped> | ||
.absence { | ||
display: flex; | ||
flex-direction: column; | ||
gap: 5px; | ||
|
||
&__dates { | ||
display: flex; | ||
gap: 10px; | ||
width: 100%; | ||
|
||
&__picker { | ||
flex: 1 auto; | ||
|
||
::v-deep .native-datetime-picker--input { | ||
margin-bottom: 0; | ||
} | ||
} | ||
} | ||
|
||
&__buttons { | ||
display: flex; | ||
gap: 5px; | ||
} | ||
} | ||
</style> |
Oops, something went wrong.