diff options
Diffstat (limited to 'apps')
18 files changed, 144 insertions, 23 deletions
diff --git a/apps/provisioning_api/lib/Controller/AUserData.php b/apps/provisioning_api/lib/Controller/AUserData.php index 44087a91791..eb881db45e0 100644 --- a/apps/provisioning_api/lib/Controller/AUserData.php +++ b/apps/provisioning_api/lib/Controller/AUserData.php @@ -179,6 +179,7 @@ abstract class AUserData extends OCSController { IAccountManager::PROPERTY_HEADLINE, IAccountManager::PROPERTY_BIOGRAPHY, IAccountManager::PROPERTY_PROFILE_ENABLED, + IAccountManager::PROPERTY_PRONOUNS, ] as $propertyName) { $property = $userAccount->getProperty($propertyName); $data[$propertyName] = $property->getValue(); diff --git a/apps/provisioning_api/lib/Controller/UsersController.php b/apps/provisioning_api/lib/Controller/UsersController.php index 4cab2341b00..e65585902bc 100644 --- a/apps/provisioning_api/lib/Controller/UsersController.php +++ b/apps/provisioning_api/lib/Controller/UsersController.php @@ -761,6 +761,7 @@ class UsersController extends AUserData { $permittedFields[] = IAccountManager::PROPERTY_HEADLINE; $permittedFields[] = IAccountManager::PROPERTY_BIOGRAPHY; $permittedFields[] = IAccountManager::PROPERTY_PROFILE_ENABLED; + $permittedFields[] = IAccountManager::PROPERTY_PRONOUNS; return new DataResponse($permittedFields); } @@ -944,6 +945,8 @@ class UsersController extends AUserData { $permittedFields[] = IAccountManager::PROPERTY_BIOGRAPHY; $permittedFields[] = IAccountManager::PROPERTY_PROFILE_ENABLED; $permittedFields[] = IAccountManager::PROPERTY_BIRTHDATE; + $permittedFields[] = IAccountManager::PROPERTY_PRONOUNS; + $permittedFields[] = IAccountManager::PROPERTY_PHONE . self::SCOPE_SUFFIX; $permittedFields[] = IAccountManager::PROPERTY_ADDRESS . self::SCOPE_SUFFIX; $permittedFields[] = IAccountManager::PROPERTY_WEBSITE . self::SCOPE_SUFFIX; @@ -955,8 +958,8 @@ class UsersController extends AUserData { $permittedFields[] = IAccountManager::PROPERTY_BIOGRAPHY . self::SCOPE_SUFFIX; $permittedFields[] = IAccountManager::PROPERTY_PROFILE_ENABLED . self::SCOPE_SUFFIX; $permittedFields[] = IAccountManager::PROPERTY_BIRTHDATE . self::SCOPE_SUFFIX; - $permittedFields[] = IAccountManager::PROPERTY_AVATAR . self::SCOPE_SUFFIX; + $permittedFields[] = IAccountManager::PROPERTY_PRONOUNS . self::SCOPE_SUFFIX; // If admin they can edit their own quota and manager $isAdmin = $this->groupManager->isAdmin($currentLoggedInUser->getUID()); @@ -997,6 +1000,7 @@ class UsersController extends AUserData { $permittedFields[] = IAccountManager::PROPERTY_HEADLINE; $permittedFields[] = IAccountManager::PROPERTY_BIOGRAPHY; $permittedFields[] = IAccountManager::PROPERTY_PROFILE_ENABLED; + $permittedFields[] = IAccountManager::PROPERTY_PRONOUNS; $permittedFields[] = self::USER_FIELD_QUOTA; $permittedFields[] = self::USER_FIELD_NOTIFICATION_EMAIL; $permittedFields[] = self::USER_FIELD_MANAGER; @@ -1141,6 +1145,7 @@ class UsersController extends AUserData { case IAccountManager::PROPERTY_HEADLINE: case IAccountManager::PROPERTY_BIOGRAPHY: case IAccountManager::PROPERTY_BIRTHDATE: + case IAccountManager::PROPERTY_PRONOUNS: $userAccount = $this->accountManager->getAccount($targetUser); try { $userProperty = $userAccount->getProperty($key); @@ -1189,6 +1194,7 @@ class UsersController extends AUserData { case IAccountManager::PROPERTY_PROFILE_ENABLED . self::SCOPE_SUFFIX: case IAccountManager::PROPERTY_BIRTHDATE . self::SCOPE_SUFFIX: case IAccountManager::PROPERTY_AVATAR . self::SCOPE_SUFFIX: + case IAccountManager::PROPERTY_PRONOUNS . self::SCOPE_SUFFIX: $propertyName = substr($key, 0, strlen($key) - strlen(self::SCOPE_SUFFIX)); $userAccount = $this->accountManager->getAccount($targetUser); $userProperty = $userAccount->getProperty($propertyName); diff --git a/apps/provisioning_api/lib/ResponseDefinitions.php b/apps/provisioning_api/lib/ResponseDefinitions.php index 90cc09b345b..fec68021209 100644 --- a/apps/provisioning_api/lib/ResponseDefinitions.php +++ b/apps/provisioning_api/lib/ResponseDefinitions.php @@ -56,6 +56,8 @@ namespace OCA\Provisioning_API; * phoneScope?: Provisioning_APIUserDetailsScope, * profile_enabled: string, * profile_enabledScope?: Provisioning_APIUserDetailsScope, + * pronouns: string, + * pronounsScope?: Provisioning_APIUserDetailsScope, * quota: Provisioning_APIUserDetailsQuota, * role: string, * roleScope?: Provisioning_APIUserDetailsScope, diff --git a/apps/provisioning_api/openapi-administration.json b/apps/provisioning_api/openapi-administration.json index 3834de8a700..3490e6829e9 100644 --- a/apps/provisioning_api/openapi-administration.json +++ b/apps/provisioning_api/openapi-administration.json @@ -99,6 +99,7 @@ "organisation", "phone", "profile_enabled", + "pronouns", "quota", "role", "subadmin", @@ -226,6 +227,12 @@ "profile_enabledScope": { "$ref": "#/components/schemas/UserDetailsScope" }, + "pronouns": { + "type": "string" + }, + "pronounsScope": { + "$ref": "#/components/schemas/UserDetailsScope" + }, "quota": { "$ref": "#/components/schemas/UserDetailsQuota" }, diff --git a/apps/provisioning_api/openapi-full.json b/apps/provisioning_api/openapi-full.json index 6577efebed9..461a9b0734a 100644 --- a/apps/provisioning_api/openapi-full.json +++ b/apps/provisioning_api/openapi-full.json @@ -146,6 +146,7 @@ "organisation", "phone", "profile_enabled", + "pronouns", "quota", "role", "subadmin", @@ -273,6 +274,12 @@ "profile_enabledScope": { "$ref": "#/components/schemas/UserDetailsScope" }, + "pronouns": { + "type": "string" + }, + "pronounsScope": { + "$ref": "#/components/schemas/UserDetailsScope" + }, "quota": { "$ref": "#/components/schemas/UserDetailsQuota" }, diff --git a/apps/provisioning_api/openapi.json b/apps/provisioning_api/openapi.json index ef07072460e..3a5f253d0b6 100644 --- a/apps/provisioning_api/openapi.json +++ b/apps/provisioning_api/openapi.json @@ -146,6 +146,7 @@ "organisation", "phone", "profile_enabled", + "pronouns", "quota", "role", "subadmin", @@ -273,6 +274,12 @@ "profile_enabledScope": { "$ref": "#/components/schemas/UserDetailsScope" }, + "pronouns": { + "type": "string" + }, + "pronounsScope": { + "$ref": "#/components/schemas/UserDetailsScope" + }, "quota": { "$ref": "#/components/schemas/UserDetailsQuota" }, diff --git a/apps/provisioning_api/tests/Controller/UsersControllerTest.php b/apps/provisioning_api/tests/Controller/UsersControllerTest.php index 0f82fc53ba6..3fcac1290db 100644 --- a/apps/provisioning_api/tests/Controller/UsersControllerTest.php +++ b/apps/provisioning_api/tests/Controller/UsersControllerTest.php @@ -990,6 +990,7 @@ class UsersControllerTest extends TestCase { IAccountManager::PROPERTY_HEADLINE => ['value' => 'headline'], IAccountManager::PROPERTY_BIOGRAPHY => ['value' => 'biography'], IAccountManager::PROPERTY_PROFILE_ENABLED => ['value' => '1'], + IAccountManager::PROPERTY_PRONOUNS => ['value' => 'they/them'], ]); $this->config ->method('getUserValue') @@ -1068,6 +1069,7 @@ class UsersControllerTest extends TestCase { 'profile_enabled' => '1', 'notify_email' => null, 'manager' => '', + 'pronouns' => 'they/them', ]; $this->assertEquals($expected, $this->invokePrivate($this->api, 'getUserData', ['UID'])); } @@ -1171,6 +1173,7 @@ class UsersControllerTest extends TestCase { IAccountManager::PROPERTY_HEADLINE => ['value' => 'headline'], IAccountManager::PROPERTY_BIOGRAPHY => ['value' => 'biography'], IAccountManager::PROPERTY_PROFILE_ENABLED => ['value' => '1'], + IAccountManager::PROPERTY_PRONOUNS => ['value' => 'they/them'], ]); $this->l10nFactory @@ -1209,6 +1212,7 @@ class UsersControllerTest extends TestCase { 'profile_enabled' => '1', 'notify_email' => null, 'manager' => '', + 'pronouns' => 'they/them', ]; $this->assertEquals($expected, $this->invokePrivate($this->api, 'getUserData', ['UID'])); } @@ -1351,6 +1355,7 @@ class UsersControllerTest extends TestCase { IAccountManager::PROPERTY_HEADLINE => ['value' => 'headline'], IAccountManager::PROPERTY_BIOGRAPHY => ['value' => 'biography'], IAccountManager::PROPERTY_PROFILE_ENABLED => ['value' => '1'], + IAccountManager::PROPERTY_PRONOUNS => ['value' => 'they/them'], ]); $this->l10nFactory @@ -1388,6 +1393,7 @@ class UsersControllerTest extends TestCase { 'profile_enabled' => '1', 'notify_email' => null, 'manager' => '', + 'pronouns' => 'they/them', ]; $this->assertEquals($expected, $this->invokePrivate($this->api, 'getUserData', ['UID'])); } @@ -1729,6 +1735,7 @@ class UsersControllerTest extends TestCase { [IAccountManager::PROPERTY_HEADLINE, 'Hi', 'Hello'], [IAccountManager::PROPERTY_BIOGRAPHY, 'A biography', 'Another biography'], [IAccountManager::PROPERTY_PROFILE_ENABLED, '1', '0'], + [IAccountManager::PROPERTY_PRONOUNS, 'they/them', 'he/him'], ]; } @@ -1806,6 +1813,7 @@ class UsersControllerTest extends TestCase { [IAccountManager::PROPERTY_HEADLINE, IAccountManager::SCOPE_LOCAL, IAccountManager::SCOPE_FEDERATED], [IAccountManager::PROPERTY_BIOGRAPHY, IAccountManager::SCOPE_LOCAL, IAccountManager::SCOPE_FEDERATED], [IAccountManager::PROPERTY_PROFILE_ENABLED, IAccountManager::SCOPE_LOCAL, IAccountManager::SCOPE_FEDERATED], + [IAccountManager::PROPERTY_PRONOUNS, IAccountManager::SCOPE_LOCAL, IAccountManager::SCOPE_FEDERATED], ]; } @@ -3690,7 +3698,8 @@ class UsersControllerTest extends TestCase { 'role' => 'role', 'headline' => 'headline', 'biography' => 'biography', - 'profile_enabled' => '1' + 'profile_enabled' => '1', + 'pronouns' => 'they/them', ] ); @@ -3711,6 +3720,7 @@ class UsersControllerTest extends TestCase { 'headline' => 'headline', 'biography' => 'biography', 'profile_enabled' => '1', + 'pronouns' => 'they/them', ]; $this->assertSame($expected, $api->getCurrentUser()->getData()); @@ -3775,7 +3785,8 @@ class UsersControllerTest extends TestCase { 'role' => 'role', 'headline' => 'headline', 'biography' => 'biography', - 'profile_enabled' => '1' + 'profile_enabled' => '1', + 'pronouns' => 'they/them', ]; $api->expects($this->exactly(2)) @@ -4115,6 +4126,7 @@ class UsersControllerTest extends TestCase { IAccountManager::PROPERTY_HEADLINE, IAccountManager::PROPERTY_BIOGRAPHY, IAccountManager::PROPERTY_PROFILE_ENABLED, + IAccountManager::PROPERTY_PRONOUNS, ]], [true, ISetDisplayNameBackend::class, [ IAccountManager::PROPERTY_DISPLAYNAME, @@ -4130,6 +4142,7 @@ class UsersControllerTest extends TestCase { IAccountManager::PROPERTY_HEADLINE, IAccountManager::PROPERTY_BIOGRAPHY, IAccountManager::PROPERTY_PROFILE_ENABLED, + IAccountManager::PROPERTY_PRONOUNS, ]], [true, UserInterface::class, [ IAccountManager::PROPERTY_EMAIL, @@ -4144,6 +4157,7 @@ class UsersControllerTest extends TestCase { IAccountManager::PROPERTY_HEADLINE, IAccountManager::PROPERTY_BIOGRAPHY, IAccountManager::PROPERTY_PROFILE_ENABLED, + IAccountManager::PROPERTY_PRONOUNS, ]], ]; } diff --git a/apps/settings/lib/Controller/UsersController.php b/apps/settings/lib/Controller/UsersController.php index 4ee359b6fe9..eb401f85536 100644 --- a/apps/settings/lib/Controller/UsersController.php +++ b/apps/settings/lib/Controller/UsersController.php @@ -335,6 +335,8 @@ class UsersController extends Controller { ?string $fediverseScope = null, ?string $birthdate = null, ?string $birthdateScope = null, + ?string $pronouns = null, + ?string $pronounsScope = null ) { $user = $this->userSession->getUser(); if (!$user instanceof IUser) { @@ -375,6 +377,7 @@ class UsersController extends Controller { IAccountManager::PROPERTY_TWITTER => ['value' => $twitter, 'scope' => $twitterScope], IAccountManager::PROPERTY_FEDIVERSE => ['value' => $fediverse, 'scope' => $fediverseScope], IAccountManager::PROPERTY_BIRTHDATE => ['value' => $birthdate, 'scope' => $birthdateScope], + IAccountManager::PROPERTY_PRONOUNS => ['value' => $pronouns, 'scope' => $pronounsScope], ]; $allowUserToChangeDisplayName = $this->config->getSystemValueBool('allow_user_to_change_display_name', true); foreach ($updatable as $property => $data) { @@ -418,6 +421,8 @@ class UsersController extends Controller { 'fediverseScope' => $userAccount->getProperty(IAccountManager::PROPERTY_FEDIVERSE)->getScope(), 'birthdate' => $userAccount->getProperty(IAccountManager::PROPERTY_BIRTHDATE)->getValue(), 'birthdateScope' => $userAccount->getProperty(IAccountManager::PROPERTY_BIRTHDATE)->getScope(), + 'pronouns' => $userAccount->getProperty(IAccountManager::PROPERTY_PRONOUNS)->getValue(), + 'pronounsScope' => $userAccount->getProperty(IAccountManager::PROPERTY_PRONOUNS)->getScope(), 'message' => $this->l10n->t('Settings saved'), ], ], diff --git a/apps/settings/lib/Settings/Personal/PersonalInfo.php b/apps/settings/lib/Settings/Personal/PersonalInfo.php index bfac996de2f..232fea8bd73 100644 --- a/apps/settings/lib/Settings/Personal/PersonalInfo.php +++ b/apps/settings/lib/Settings/Personal/PersonalInfo.php @@ -143,6 +143,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', AUserData::USER_FIELD_FIRST_DAY_OF_WEEK), + 'pronouns' => $this->getProperty($account, IAccountManager::PROPERTY_PRONOUNS), ]; $accountParameters = [ diff --git a/apps/settings/src/components/PersonalInfo/PronounsSection.vue b/apps/settings/src/components/PersonalInfo/PronounsSection.vue new file mode 100644 index 00000000000..fb35b1800c5 --- /dev/null +++ b/apps/settings/src/components/PersonalInfo/PronounsSection.vue @@ -0,0 +1,45 @@ +<!-- + - SPDX-FileCopyrightText: 2024 Nextcloud GmbH and Nextcloud contributors + - SPDX-License-Identifier: AGPL-3.0-or-later +--> + +<template> + <AccountPropertySection v-bind.sync="pronouns" + :placeholder="randomPronounsPlaceholder" /> +</template> + +<script> +import { loadState } from '@nextcloud/initial-state' + +import AccountPropertySection from './shared/AccountPropertySection.vue' + +import { NAME_READABLE_ENUM } from '../../constants/AccountPropertyConstants.js' + +const { pronouns } = loadState('settings', 'personalInfoParameters', {}) + +export default { + name: 'PronounsSection', + + components: { + AccountPropertySection, + }, + + data() { + return { + pronouns: { ...pronouns, readable: NAME_READABLE_ENUM[pronouns.name] }, + } + }, + + computed: { + randomPronounsPlaceholder() { + const pronouns = [ + this.t('settings', 'she/her'), + this.t('settings', 'he/him'), + this.t('settings', 'they/them'), + ] + const pronounsExample = pronouns[Math.floor(Math.random() * pronouns.length)] + return this.t('settings', `Your pronouns. E.g. ${pronounsExample}`, { pronounsExample }) + }, + }, +} +</script> diff --git a/apps/settings/src/constants/AccountPropertyConstants.js b/apps/settings/src/constants/AccountPropertyConstants.js index 8ddfc867ec5..4b475b54ab4 100644 --- a/apps/settings/src/constants/AccountPropertyConstants.js +++ b/apps/settings/src/constants/AccountPropertyConstants.js @@ -15,19 +15,20 @@ export const ACCOUNT_PROPERTY_ENUM = Object.freeze({ ADDRESS: 'address', AVATAR: 'avatar', BIOGRAPHY: 'biography', + BIRTHDATE: 'birthdate', DISPLAYNAME: 'displayname', EMAIL_COLLECTION: 'additional_mail', EMAIL: 'email', + FEDIVERSE: 'fediverse', HEADLINE: 'headline', NOTIFICATION_EMAIL: 'notify_email', - FEDIVERSE: 'fediverse', ORGANISATION: 'organisation', PHONE: 'phone', PROFILE_ENABLED: 'profile_enabled', + PRONOUNS: 'pronouns', ROLE: 'role', TWITTER: 'twitter', WEBSITE: 'website', - BIRTHDATE: 'birthdate', }) /** Enum of account properties to human readable account property names */ @@ -35,18 +36,19 @@ export const ACCOUNT_PROPERTY_READABLE_ENUM = Object.freeze({ ADDRESS: t('settings', 'Location'), AVATAR: t('settings', 'Profile picture'), BIOGRAPHY: t('settings', 'About'), + BIRTHDATE: t('settings', 'Date of birth'), DISPLAYNAME: t('settings', 'Full name'), EMAIL_COLLECTION: t('settings', 'Additional email'), EMAIL: t('settings', 'Email'), + FEDIVERSE: t('settings', 'Fediverse (e.g. Mastodon)'), HEADLINE: t('settings', 'Headline'), ORGANISATION: t('settings', 'Organisation'), PHONE: t('settings', 'Phone number'), PROFILE_ENABLED: t('settings', 'Profile'), + PRONOUNS: t('settings', 'Pronouns'), ROLE: t('settings', 'Role'), TWITTER: t('settings', 'X (formerly Twitter)'), - FEDIVERSE: t('settings', 'Fediverse (e.g. Mastodon)'), WEBSITE: t('settings', 'Website'), - BIRTHDATE: t('settings', 'Date of birth'), }) export const NAME_READABLE_ENUM = Object.freeze({ @@ -65,6 +67,7 @@ export const NAME_READABLE_ENUM = Object.freeze({ [ACCOUNT_PROPERTY_ENUM.FEDIVERSE]: ACCOUNT_PROPERTY_READABLE_ENUM.FEDIVERSE, [ACCOUNT_PROPERTY_ENUM.WEBSITE]: ACCOUNT_PROPERTY_READABLE_ENUM.WEBSITE, [ACCOUNT_PROPERTY_ENUM.BIRTHDATE]: ACCOUNT_PROPERTY_READABLE_ENUM.BIRTHDATE, + [ACCOUNT_PROPERTY_ENUM.PRONOUNS]: ACCOUNT_PROPERTY_READABLE_ENUM.PRONOUNS, }) /** Enum of profile specific sections to human readable names */ @@ -89,6 +92,7 @@ export const PROPERTY_READABLE_KEYS_ENUM = Object.freeze({ [ACCOUNT_PROPERTY_READABLE_ENUM.FEDIVERSE]: ACCOUNT_PROPERTY_ENUM.FEDIVERSE, [ACCOUNT_PROPERTY_READABLE_ENUM.WEBSITE]: ACCOUNT_PROPERTY_ENUM.WEBSITE, [ACCOUNT_PROPERTY_READABLE_ENUM.BIRTHDATE]: ACCOUNT_PROPERTY_ENUM.BIRTHDATE, + [ACCOUNT_PROPERTY_READABLE_ENUM.PRONOUNS]: ACCOUNT_PROPERTY_ENUM.PRONOUNS, }) /** @@ -134,6 +138,7 @@ export const PROPERTY_READABLE_SUPPORTED_SCOPES_ENUM = Object.freeze({ [ACCOUNT_PROPERTY_READABLE_ENUM.FEDIVERSE]: [SCOPE_ENUM.LOCAL, SCOPE_ENUM.PRIVATE], [ACCOUNT_PROPERTY_READABLE_ENUM.WEBSITE]: [SCOPE_ENUM.LOCAL, SCOPE_ENUM.PRIVATE], [ACCOUNT_PROPERTY_READABLE_ENUM.BIRTHDATE]: [SCOPE_ENUM.LOCAL, SCOPE_ENUM.PRIVATE], + [ACCOUNT_PROPERTY_READABLE_ENUM.PRONOUNS]: [SCOPE_ENUM.LOCAL, SCOPE_ENUM.PRIVATE], }) /** List of readable account properties which aren't published to the lookup server */ diff --git a/apps/settings/src/main-personal-info.js b/apps/settings/src/main-personal-info.js index 0a1e983c576..c28f14ee477 100644 --- a/apps/settings/src/main-personal-info.js +++ b/apps/settings/src/main-personal-info.js @@ -9,24 +9,25 @@ import { loadState } from '@nextcloud/initial-state' import { translate as t } from '@nextcloud/l10n' import AvatarSection from './components/PersonalInfo/AvatarSection.vue' +import BiographySection from './components/PersonalInfo/BiographySection.vue' +import BirthdaySection from './components/PersonalInfo/BirthdaySection.vue' import DetailsSection from './components/PersonalInfo/DetailsSection.vue' import DisplayNameSection from './components/PersonalInfo/DisplayNameSection.vue' import EmailSection from './components/PersonalInfo/EmailSection/EmailSection.vue' -import PhoneSection from './components/PersonalInfo/PhoneSection.vue' -import LocationSection from './components/PersonalInfo/LocationSection.vue' -import WebsiteSection from './components/PersonalInfo/WebsiteSection.vue' -import TwitterSection from './components/PersonalInfo/TwitterSection.vue' import FediverseSection from './components/PersonalInfo/FediverseSection.vue' +import FirstDayOfWeekSection from './components/PersonalInfo/FirstDayOfWeekSection.vue' +import HeadlineSection from './components/PersonalInfo/HeadlineSection.vue' import LanguageSection from './components/PersonalInfo/LanguageSection/LanguageSection.vue' import LocaleSection from './components/PersonalInfo/LocaleSection/LocaleSection.vue' -import ProfileSection from './components/PersonalInfo/ProfileSection/ProfileSection.vue' +import LocationSection from './components/PersonalInfo/LocationSection.vue' import OrganisationSection from './components/PersonalInfo/OrganisationSection.vue' -import RoleSection from './components/PersonalInfo/RoleSection.vue' -import HeadlineSection from './components/PersonalInfo/HeadlineSection.vue' -import BiographySection from './components/PersonalInfo/BiographySection.vue' +import PhoneSection from './components/PersonalInfo/PhoneSection.vue' +import ProfileSection from './components/PersonalInfo/ProfileSection/ProfileSection.vue' import ProfileVisibilitySection from './components/PersonalInfo/ProfileVisibilitySection/ProfileVisibilitySection.vue' -import BirthdaySection from './components/PersonalInfo/BirthdaySection.vue' -import FirstDayOfWeekSection from './components/PersonalInfo/FirstDayOfWeekSection.vue' +import PronounsSection from './components/PersonalInfo/PronounsSection.vue' +import RoleSection from './components/PersonalInfo/RoleSection.vue' +import TwitterSection from './components/PersonalInfo/TwitterSection.vue' +import WebsiteSection from './components/PersonalInfo/WebsiteSection.vue' __webpack_nonce__ = getCSPNonce() @@ -39,18 +40,19 @@ Vue.mixin({ }) const AvatarView = Vue.extend(AvatarSection) +const BirthdayView = Vue.extend(BirthdaySection) const DetailsView = Vue.extend(DetailsSection) const DisplayNameView = Vue.extend(DisplayNameSection) const EmailView = Vue.extend(EmailSection) -const PhoneView = Vue.extend(PhoneSection) -const LocationView = Vue.extend(LocationSection) -const WebsiteView = Vue.extend(WebsiteSection) -const TwitterView = Vue.extend(TwitterSection) const FediverseView = Vue.extend(FediverseSection) +const FirstDayOfWeekView = Vue.extend(FirstDayOfWeekSection) const LanguageView = Vue.extend(LanguageSection) const LocaleView = Vue.extend(LocaleSection) -const BirthdayView = Vue.extend(BirthdaySection) -const FirstDayOfWeekView = Vue.extend(FirstDayOfWeekSection) +const LocationView = Vue.extend(LocationSection) +const PhoneView = Vue.extend(PhoneSection) +const PronounsView = Vue.extend(PronounsSection) +const TwitterView = Vue.extend(TwitterSection) +const WebsiteView = Vue.extend(WebsiteSection) new AvatarView().$mount('#vue-avatar-section') new DetailsView().$mount('#vue-details-section') @@ -65,6 +67,7 @@ new LanguageView().$mount('#vue-language-section') new LocaleView().$mount('#vue-locale-section') new FirstDayOfWeekView().$mount('#vue-fdow-section') new BirthdayView().$mount('#vue-birthday-section') +new PronounsView().$mount('#vue-pronouns-section') if (profileEnabledGlobally) { const ProfileView = Vue.extend(ProfileSection) diff --git a/apps/settings/templates/settings/personal/personal.info.php b/apps/settings/templates/settings/personal/personal.info.php index 92b29961baf..e622663fba7 100644 --- a/apps/settings/templates/settings/personal/personal.info.php +++ b/apps/settings/templates/settings/personal/personal.info.php @@ -44,6 +44,9 @@ script('settings', [ <div id="vue-displayname-section"></div> </div> <div class="personal-settings-setting-box"> + <div id="vue-pronouns-section"></div> + </div> + <div class="personal-settings-setting-box"> <div id="vue-email-section"></div> </div> <div class="personal-settings-setting-box"> diff --git a/apps/user_ldap/lib/Configuration.php b/apps/user_ldap/lib/Configuration.php index d436c5c4240..9de180cad76 100644 --- a/apps/user_ldap/lib/Configuration.php +++ b/apps/user_ldap/lib/Configuration.php @@ -80,6 +80,8 @@ use Psr\Log\LoggerInterface; * @property string $ldapAttributeHeadline * @property string $ldapAttributeBiography * @property string $ldapAdminGroup + * @property string $ldapAttributeBirthDate + * @property string $ldapAttributePronouns */ class Configuration { public const AVATAR_PREFIX_DEFAULT = 'default'; @@ -179,6 +181,7 @@ class Configuration { 'ldapAdminGroup' => '', 'ldapAttributeBirthDate' => null, 'ldapAttributeAnniversaryDate' => null, + 'ldapAttributePronouns' => null, ]; public function __construct(string $configPrefix, bool $autoRead = true) { @@ -315,6 +318,7 @@ class Configuration { case 'ldapAttributeBiography': case 'ldapAttributeBirthDate': case 'ldapAttributeAnniversaryDate': + case 'ldapAttributePronouns': $readMethod = 'getLcValue'; break; case 'ldapUserDisplayName': @@ -559,6 +563,7 @@ class Configuration { 'ldap_admin_group' => '', 'ldap_attr_birthdate' => '', 'ldap_attr_anniversarydate' => '', + 'ldap_attr_pronouns' => '', ]; } @@ -638,6 +643,7 @@ class Configuration { 'ldap_admin_group' => 'ldapAdminGroup', 'ldap_attr_birthdate' => 'ldapAttributeBirthDate', 'ldap_attr_anniversarydate' => 'ldapAttributeAnniversaryDate', + 'ldap_attr_pronouns' => 'ldapAttributePronouns', ]; return $array; } diff --git a/apps/user_ldap/lib/Connection.php b/apps/user_ldap/lib/Connection.php index 54dba6d858a..b74c964eb72 100644 --- a/apps/user_ldap/lib/Connection.php +++ b/apps/user_ldap/lib/Connection.php @@ -85,6 +85,7 @@ use Psr\Log\LoggerInterface; * @property string $ldapAttributeBiography * @property string $ldapAdminGroup * @property string $ldapAttributeBirthDate + * @property string $ldapAttributePronouns */ class Connection extends LDAPUtility { private ?\LDAP\Connection $ldapConnectionRes = null; diff --git a/apps/user_ldap/lib/User/Manager.php b/apps/user_ldap/lib/User/Manager.php index 227990401c2..bf1da54823c 100644 --- a/apps/user_ldap/lib/User/Manager.php +++ b/apps/user_ldap/lib/User/Manager.php @@ -142,6 +142,7 @@ class Manager { $this->access->getConnection()->ldapAttributeHeadline, $this->access->getConnection()->ldapAttributeBiography, $this->access->getConnection()->ldapAttributeBirthDate, + $this->access->getConnection()->ldapAttributePronouns, ]; $homeRule = (string)$this->access->getConnection()->homeFolderNamingRule; diff --git a/apps/user_ldap/lib/User/User.php b/apps/user_ldap/lib/User/User.php index 3423455e819..f2a9ba49f2f 100644 --- a/apps/user_ldap/lib/User/User.php +++ b/apps/user_ldap/lib/User/User.php @@ -320,6 +320,12 @@ class User { ]); } } + //User Profile Field - pronouns + $attr = strtolower($this->connection->ldapAttributePronouns); + if (!empty($attr)) { + $profileValues[\OCP\Accounts\IAccountManager::PROPERTY_PRONOUNS] + = $ldapEntry[$attr][0] ?? ''; + } // check for changed data and cache just for TTL checking $checksum = hash('sha256', json_encode($profileValues)); $this->connection->writeToCache($cacheKey, $checksum // write array to cache. is waste of cache space diff --git a/apps/user_ldap/templates/settings.php b/apps/user_ldap/templates/settings.php index 4fb24655000..4be24095e99 100644 --- a/apps/user_ldap/templates/settings.php +++ b/apps/user_ldap/templates/settings.php @@ -139,6 +139,7 @@ style('user_ldap', 'settings'); <p><label for="ldap_attr_headline"> <?php p($l->t('Headline Field')); ?></label><input type="text" id="ldap_attr_headline" name="ldap_attr_headline" title="<?php p($l->t('User profile Headline will be set from the specified attribute')); ?>" data-default="<?php p($_['ldap_attr_headline_default']); ?>"></p> <p><label for="ldap_attr_biography"> <?php p($l->t('Biography Field')); ?></label><input type="text" id="ldap_attr_biography" name="ldap_attr_biography" title="<?php p($l->t('User profile Biography will be set from the specified attribute')); ?>" data-default="<?php p($_['ldap_attr_biography_default']); ?>"></p> <p><label for="ldap_attr_birthdate"> <?php p($l->t('Birthdate Field')); ?></label><input type="text" id="ldap_attr_birthdate" name="ldap_attr_birthdate" title="<?php p($l->t('User profile Date of birth will be set from the specified attribute')); ?>" data-default="<?php p($_['ldap_attr_birthdate_default']); ?>"></p> + <p></p><label for="ldap_attr_pronouns"> <?php p($l->t('Pronouns Field')); ?></label><input type="text" id="ldap_attr_pronouns" name="ldap_attr_pronouns" title="<?php p($l->t('User profile Pronouns will be set from the specified attribute')); ?>" data-default="<?php p($_['ldap_attr_pronouns_default']); ?>"></p> </div> </div> <?php print_unescaped($_['settingControls']); ?> |