feat(settings): allow to set own timezone in personal settings

Signed-off-by: Ferdinand Thiessen <opensource@fthiessen.de>
pull/54470/head
Ferdinand Thiessen 2 months ago
parent c40350d2e4
commit 0dd8e5e32e
No known key found for this signature in database
GPG Key ID: 45FAE7268762B400
  1. 2
      apps/provisioning_api/lib/Controller/AUserDataOCSController.php
  2. 8
      apps/provisioning_api/lib/Controller/UsersController.php
  3. 1
      apps/provisioning_api/lib/ResponseDefinitions.php
  4. 3
      apps/provisioning_api/tests/Controller/UsersControllerTest.php
  5. 1
      apps/settings/lib/Settings/Personal/PersonalInfo.php
  6. 43
      apps/settings/src/components/PersonalInfo/TimezoneSection.vue
  7. 2
      apps/settings/src/constants/AccountPropertyConstants.ts
  8. 3
      apps/settings/src/main-personal-info.js
  9. 3
      apps/settings/templates/settings/personal/personal.info.php

@ -43,6 +43,7 @@ abstract class AUserDataOCSController extends OCSController {
public const USER_FIELD_DISPLAYNAME = 'display';
public const USER_FIELD_LANGUAGE = 'language';
public const USER_FIELD_LOCALE = 'locale';
public const USER_FIELD_TIMEZONE = 'timezone';
public const USER_FIELD_FIRST_DAY_OF_WEEK = 'first_day_of_week';
public const USER_FIELD_PASSWORD = 'password';
public const USER_FIELD_QUOTA = 'quota';
@ -187,6 +188,7 @@ abstract class AUserDataOCSController extends OCSController {
$data['groups'] = $gids;
$data[self::USER_FIELD_LANGUAGE] = $this->l10nFactory->getUserLanguage($targetUserObject);
$data[self::USER_FIELD_LOCALE] = $this->config->getUserValue($targetUserObject->getUID(), 'core', 'locale');
$data[self::USER_FIELD_TIMEZONE] = $this->config->getUserValue($targetUserObject->getUID(), 'core', 'timezone');
$data[self::USER_FIELD_NOTIFICATION_EMAIL] = $targetUserObject->getPrimaryEMailAddress();
$backend = $targetUserObject->getBackend();

@ -954,6 +954,7 @@ class UsersController extends AUserDataOCSController {
$permittedFields[] = self::USER_FIELD_PASSWORD;
$permittedFields[] = self::USER_FIELD_NOTIFICATION_EMAIL;
$permittedFields[] = self::USER_FIELD_TIMEZONE;
if (
$this->config->getSystemValue('force_language', false) === false
|| $this->groupManager->isAdmin($currentLoggedInUser->getUID())
@ -1028,6 +1029,7 @@ class UsersController extends AUserDataOCSController {
$permittedFields[] = self::USER_FIELD_PASSWORD;
$permittedFields[] = self::USER_FIELD_LANGUAGE;
$permittedFields[] = self::USER_FIELD_LOCALE;
$permittedFields[] = self::USER_FIELD_TIMEZONE;
$permittedFields[] = self::USER_FIELD_FIRST_DAY_OF_WEEK;
$permittedFields[] = IAccountManager::PROPERTY_PHONE;
$permittedFields[] = IAccountManager::PROPERTY_ADDRESS;
@ -1122,6 +1124,12 @@ class UsersController extends AUserDataOCSController {
}
$this->config->setUserValue($targetUser->getUID(), 'core', 'locale', $value);
break;
case self::USER_FIELD_TIMEZONE:
if (!in_array($value, \DateTimeZone::listIdentifiers())) {
throw new OCSException($this->l10n->t('Invalid timezone'), 101);
}
$this->config->setUserValue($targetUser->getUID(), 'core', 'timezone', $value);
break;
case self::USER_FIELD_FIRST_DAY_OF_WEEK:
$intValue = (int)$value;
if ($intValue < -1 || $intValue > 6) {

@ -65,6 +65,7 @@ namespace OCA\Provisioning_API;
* roleScope?: Provisioning_APIUserDetailsScope,
* storageLocation?: string,
* subadmin: list<string>,
* timezone: string,
* twitter: string,
* twitterScope?: Provisioning_APIUserDetailsScope,
* bluesky: string,

@ -1225,6 +1225,7 @@ class UsersControllerTest extends TestCase {
'groups' => ['group0', 'group1', 'group2'],
'language' => 'de',
'locale' => null,
'timezone' => null,
'backendCapabilities' => [
'setDisplayName' => true,
'setPassword' => true,
@ -1372,6 +1373,7 @@ class UsersControllerTest extends TestCase {
'groups' => [],
'language' => 'da',
'locale' => null,
'timezone' => null,
'backendCapabilities' => [
'setDisplayName' => true,
'setPassword' => true,
@ -1557,6 +1559,7 @@ class UsersControllerTest extends TestCase {
'groups' => [],
'language' => 'ru',
'locale' => null,
'timezone' => null,
'backendCapabilities' => [
'setDisplayName' => false,
'setPassword' => false,

@ -110,6 +110,7 @@ class PersonalInfo implements ISettings {
'biography' => $this->getProperty($account, IAccountManager::PROPERTY_BIOGRAPHY),
'birthdate' => $this->getProperty($account, IAccountManager::PROPERTY_BIRTHDATE),
'firstDayOfWeek' => $this->config->getUserValue($uid, 'core', AUserDataOCSController::USER_FIELD_FIRST_DAY_OF_WEEK),
'timezone' => $this->config->getUserValue($uid, 'core', 'timezone', ''),
'pronouns' => $this->getProperty($account, IAccountManager::PROPERTY_PRONOUNS),
];

@ -0,0 +1,43 @@
<!--
- SPDX-FileCopyrightText: 2025 Nextcloud GmbH and Nextcloud contributors
- SPDX-License-Identifier: AGPL-3.0-or-later
-->
<script setup lang="ts">
import { loadState } from '@nextcloud/initial-state'
import { t } from '@nextcloud/l10n'
import { ref, watch } from 'vue'
import NcTimezonePicker from '@nextcloud/vue/components/NcTimezonePicker'
import HeaderBar from './shared/HeaderBar.vue'
import { savePrimaryAccountProperty } from '../../service/PersonalInfo/PersonalInfoService.js'
const { timezone: currentTimezone } = loadState<{ timezone: string }>('settings', 'personalInfoParameters')
const inputId = 'account-property-timezone'
const timezone = ref(currentTimezone)
watch(timezone, () => {
savePrimaryAccountProperty('timezone', timezone.value)
})
</script>
<template>
<section class="timezone-section">
<HeaderBar :input-id="inputId"
:readable="t('settings', 'Timezone')" />
<NcTimezonePicker v-model="timezone"
class="timezone-section__picker"
:input-id="inputId" />
</section>
</template>
<style scoped lang="scss">
.timezone-section {
padding: 10px;
&__picker {
margin-top: 6px;
width: 100%;
}
}
</style>

@ -108,6 +108,7 @@ export const ACCOUNT_SETTING_PROPERTY_ENUM = Object.freeze({
LANGUAGE: 'language',
LOCALE: 'locale',
FIRST_DAY_OF_WEEK: 'first_day_of_week',
TIMEZONE: 'timezone',
})
/** Enum of account setting properties to human readable setting properties */
@ -115,6 +116,7 @@ export const ACCOUNT_SETTING_PROPERTY_READABLE_ENUM = Object.freeze({
LANGUAGE: t('settings', 'Language'),
LOCALE: t('settings', 'Locale'),
FIRST_DAY_OF_WEEK: t('settings', 'First day of week'),
TIMEZONE: t('settings', 'timezone'),
})
/** Enum of scopes */

@ -26,6 +26,7 @@ import ProfileSection from './components/PersonalInfo/ProfileSection/ProfileSect
import ProfileVisibilitySection from './components/PersonalInfo/ProfileVisibilitySection/ProfileVisibilitySection.vue'
import PronounsSection from './components/PersonalInfo/PronounsSection.vue'
import RoleSection from './components/PersonalInfo/RoleSection.vue'
import TimezoneSection from './components/PersonalInfo/TimezoneSection.vue'
import TwitterSection from './components/PersonalInfo/TwitterSection.vue'
import BlueskySection from './components/PersonalInfo/BlueskySection.vue'
import WebsiteSection from './components/PersonalInfo/WebsiteSection.vue'
@ -47,6 +48,7 @@ const DisplayNameView = Vue.extend(DisplayNameSection)
const EmailView = Vue.extend(EmailSection)
const FediverseView = Vue.extend(FediverseSection)
const FirstDayOfWeekView = Vue.extend(FirstDayOfWeekSection)
const TimezoneView = Vue.extend(TimezoneSection)
const LanguageView = Vue.extend(LanguageSection)
const LocaleView = Vue.extend(LocaleSection)
const LocationView = Vue.extend(LocationSection)
@ -69,6 +71,7 @@ new FediverseView().$mount('#vue-fediverse-section')
new LanguageView().$mount('#vue-language-section')
new LocaleView().$mount('#vue-locale-section')
new FirstDayOfWeekView().$mount('#vue-fdow-section')
new TimezoneView().$mount('#vue-timezone-section')
new BirthdayView().$mount('#vue-birthday-section')
new PronounsView().$mount('#vue-pronouns-section')

@ -67,6 +67,9 @@ script('settings', [
<div class="personal-settings-setting-box">
<div id="vue-fdow-section"></div>
</div>
<div class="personal-settings-setting-box">
<div id="vue-timezone-section"></div>
</div>
<div class="personal-settings-setting-box">
<div id="vue-website-section"></div>
</div>

Loading…
Cancel
Save