diff options
author | John Molakvoæ (skjnldsv) <skjnldsv@protonmail.com> | 2024-09-17 21:41:45 +0200 |
---|---|---|
committer | John Molakvoæ (skjnldsv) <skjnldsv@protonmail.com> | 2024-09-17 22:20:36 +0200 |
commit | 26abc86eca7cf6ae95f20e1dc180774d11892aab (patch) | |
tree | c646582f842066e92b8cce3ddc593e3bef0a24b7 /apps/settings | |
parent | dc71cb7c3a94eeea69f647f248f3bcbfcecdbe2b (diff) | |
download | nextcloud-server-26abc86eca7cf6ae95f20e1dc180774d11892aab.tar.gz nextcloud-server-26abc86eca7cf6ae95f20e1dc180774d11892aab.zip |
feat: add profile pronouns
Signed-off-by: John Molakvoæ (skjnldsv) <skjnldsv@protonmail.com>
Diffstat (limited to 'apps/settings')
6 files changed, 82 insertions, 20 deletions
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"> |