зеркало из https://github.com/nextcloud/server.git
feat: add profile pronouns
Signed-off-by: John Molakvoæ (skjnldsv) <skjnldsv@protonmail.com>
This commit is contained in:
Родитель
dc71cb7c3a
Коммит
26abc86eca
|
@ -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();
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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"
|
||||
},
|
||||
|
|
|
@ -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"
|
||||
},
|
||||
|
|
|
@ -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"
|
||||
},
|
||||
|
|
|
@ -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,
|
||||
]],
|
||||
];
|
||||
}
|
||||
|
|
|
@ -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'),
|
||||
],
|
||||
],
|
||||
|
|
|
@ -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 = [
|
||||
|
|
|
@ -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>
|
|
@ -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 */
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -43,6 +43,9 @@ script('settings', [
|
|||
<div class="personal-settings-setting-box">
|
||||
<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>
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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']); ?>
|
||||
|
|
|
@ -75,6 +75,7 @@ Feature: provisioning
|
|||
| role |
|
||||
| headline |
|
||||
| biography |
|
||||
| pronouns |
|
||||
| profile_enabled |
|
||||
Given As an "brand-new-user"
|
||||
Then user "brand-new-user" has editable fields
|
||||
|
@ -90,6 +91,7 @@ Feature: provisioning
|
|||
| role |
|
||||
| headline |
|
||||
| biography |
|
||||
| pronouns |
|
||||
| profile_enabled |
|
||||
Then user "self" has editable fields
|
||||
| displayname |
|
||||
|
@ -104,6 +106,7 @@ Feature: provisioning
|
|||
| role |
|
||||
| headline |
|
||||
| biography |
|
||||
| pronouns |
|
||||
| profile_enabled |
|
||||
|
||||
Scenario: Edit a user
|
||||
|
@ -570,7 +573,7 @@ Feature: provisioning
|
|||
And group "new-group" does not exist
|
||||
|
||||
Scenario: Delete a group with special characters
|
||||
Given As an "admin"
|
||||
Given As an "admin"
|
||||
And group "España" exists
|
||||
When sending "DELETE" to "/cloud/groups/España"
|
||||
Then the OCS status code should be "100"
|
||||
|
|
|
@ -11,6 +11,7 @@
|
|||
<div class="profile__header__container__placeholder" />
|
||||
<div class="profile__header__container__displayname">
|
||||
<h2>{{ displayname || userId }}</h2>
|
||||
<span v-if="pronouns" class="profile__header__container__pronouns">· {{ pronouns }}</span>
|
||||
<NcButton v-if="isCurrentUser"
|
||||
type="primary"
|
||||
:href="settingsUrl">
|
||||
|
@ -177,6 +178,7 @@ export default defineComponent({
|
|||
biography: null as string|null,
|
||||
actions: [] as IProfileAction[],
|
||||
isUserAvatarVisible: false,
|
||||
pronouns: null as string|null,
|
||||
})
|
||||
|
||||
return {
|
||||
|
|
Различия файлов скрыты, потому что одна или несколько строк слишком длинны
Различия файлов скрыты, потому что одна или несколько строк слишком длинны
Различия файлов скрыты, потому что одна или несколько строк слишком длинны
Различия файлов скрыты, потому что одна или несколько строк слишком длинны
Различия файлов скрыты, потому что одна или несколько строк слишком длинны
Различия файлов скрыты, потому что одна или несколько строк слишком длинны
|
@ -64,19 +64,20 @@ class AccountManager implements IAccountManager {
|
|||
* The list of default scopes for each property.
|
||||
*/
|
||||
public const DEFAULT_SCOPES = [
|
||||
self::PROPERTY_DISPLAYNAME => self::SCOPE_FEDERATED,
|
||||
self::PROPERTY_ADDRESS => self::SCOPE_LOCAL,
|
||||
self::PROPERTY_WEBSITE => self::SCOPE_LOCAL,
|
||||
self::PROPERTY_EMAIL => self::SCOPE_FEDERATED,
|
||||
self::PROPERTY_AVATAR => self::SCOPE_FEDERATED,
|
||||
self::PROPERTY_PHONE => self::SCOPE_LOCAL,
|
||||
self::PROPERTY_TWITTER => self::SCOPE_LOCAL,
|
||||
self::PROPERTY_FEDIVERSE => self::SCOPE_LOCAL,
|
||||
self::PROPERTY_ORGANISATION => self::SCOPE_LOCAL,
|
||||
self::PROPERTY_ROLE => self::SCOPE_LOCAL,
|
||||
self::PROPERTY_HEADLINE => self::SCOPE_LOCAL,
|
||||
self::PROPERTY_BIOGRAPHY => self::SCOPE_LOCAL,
|
||||
self::PROPERTY_BIRTHDATE => self::SCOPE_LOCAL,
|
||||
self::PROPERTY_DISPLAYNAME => self::SCOPE_FEDERATED,
|
||||
self::PROPERTY_EMAIL => self::SCOPE_FEDERATED,
|
||||
self::PROPERTY_FEDIVERSE => self::SCOPE_LOCAL,
|
||||
self::PROPERTY_HEADLINE => self::SCOPE_LOCAL,
|
||||
self::PROPERTY_ORGANISATION => self::SCOPE_LOCAL,
|
||||
self::PROPERTY_PHONE => self::SCOPE_LOCAL,
|
||||
self::PROPERTY_PRONOUNS => self::SCOPE_FEDERATED,
|
||||
self::PROPERTY_ROLE => self::SCOPE_LOCAL,
|
||||
self::PROPERTY_TWITTER => self::SCOPE_LOCAL,
|
||||
self::PROPERTY_WEBSITE => self::SCOPE_LOCAL,
|
||||
];
|
||||
|
||||
public function __construct(
|
||||
|
@ -679,6 +680,12 @@ class AccountManager implements IAccountManager {
|
|||
'name' => self::PROPERTY_PROFILE_ENABLED,
|
||||
'value' => $this->isProfileEnabledByDefault($this->config) ? '1' : '0',
|
||||
],
|
||||
|
||||
[
|
||||
'name' => self::PROPERTY_PRONOUNS,
|
||||
'value' => '',
|
||||
'scope' => $scopes[self::PROPERTY_PRONOUNS],
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
|
|
|
@ -66,6 +66,7 @@ class ProfileManager implements IProfileManager {
|
|||
IAccountManager::PROPERTY_HEADLINE,
|
||||
IAccountManager::PROPERTY_ORGANISATION,
|
||||
IAccountManager::PROPERTY_ROLE,
|
||||
IAccountManager::PROPERTY_PRONOUNS,
|
||||
];
|
||||
|
||||
public function __construct(
|
||||
|
@ -222,7 +223,7 @@ class ProfileManager implements IProfileManager {
|
|||
/**
|
||||
* Return the profile parameters of the target user that are visible to the visiting user
|
||||
* in an associative array
|
||||
* @return array{userId: string, address?: string|null, biography?: string|null, displayname?: string|null, headline?: string|null, isUserAvatarVisible?: bool, organisation?: string|null, role?: string|null, actions: list<array{id: string, icon: string, title: string, target: ?string}>}
|
||||
* @return array{userId: string, address?: string|null, biography?: string|null, displayname?: string|null, headline?: string|null, isUserAvatarVisible?: bool, organisation?: string|null, pronouns?: non-falsy-string|null, role?: string|null, actions: list<array{id: string, icon: string, title: string, target: ?string}>}
|
||||
*/
|
||||
public function getProfileFields(IUser $targetUser, ?IUser $visitingUser): array {
|
||||
$account = $this->accountManager->getAccount($targetUser);
|
||||
|
@ -241,6 +242,7 @@ class ProfileManager implements IProfileManager {
|
|||
case IAccountManager::PROPERTY_HEADLINE:
|
||||
case IAccountManager::PROPERTY_ORGANISATION:
|
||||
case IAccountManager::PROPERTY_ROLE:
|
||||
case IAccountManager::PROPERTY_PRONOUNS:
|
||||
$profileParameters[$property] =
|
||||
$this->isProfileFieldVisible($property, $targetUser, $visitingUser)
|
||||
// Explicitly set to null when value is empty string
|
||||
|
@ -399,6 +401,10 @@ class ProfileManager implements IProfileManager {
|
|||
'appId' => self::CORE_APP_ID,
|
||||
'displayId' => $this->l10nFactory->get('lib')->t('Role'),
|
||||
],
|
||||
IAccountManager::PROPERTY_PRONOUNS => [
|
||||
'appId' => self::CORE_APP_ID,
|
||||
'displayId' => $this->l10nFactory->get('lib')->t('Pronouns'),
|
||||
],
|
||||
];
|
||||
|
||||
$paramMetadata = array_merge($actionsMetadata, $propertiesMetadata);
|
||||
|
|
|
@ -161,26 +161,32 @@ interface IAccountManager {
|
|||
*/
|
||||
public const PROPERTY_BIRTHDATE = 'birthdate';
|
||||
|
||||
/**
|
||||
* @since 31.0.0
|
||||
*/
|
||||
public const PROPERTY_PRONOUNS = 'pronouns';
|
||||
|
||||
/**
|
||||
* The list of allowed properties
|
||||
*
|
||||
* @since 25.0.0
|
||||
*/
|
||||
public const ALLOWED_PROPERTIES = [
|
||||
self::PROPERTY_AVATAR,
|
||||
self::PROPERTY_DISPLAYNAME,
|
||||
self::PROPERTY_PHONE,
|
||||
self::PROPERTY_EMAIL,
|
||||
self::PROPERTY_WEBSITE,
|
||||
self::PROPERTY_ADDRESS,
|
||||
self::PROPERTY_TWITTER,
|
||||
self::PROPERTY_FEDIVERSE,
|
||||
self::PROPERTY_ORGANISATION,
|
||||
self::PROPERTY_ROLE,
|
||||
self::PROPERTY_HEADLINE,
|
||||
self::PROPERTY_AVATAR,
|
||||
self::PROPERTY_BIOGRAPHY,
|
||||
self::PROPERTY_PROFILE_ENABLED,
|
||||
self::PROPERTY_BIRTHDATE,
|
||||
self::PROPERTY_DISPLAYNAME,
|
||||
self::PROPERTY_EMAIL,
|
||||
self::PROPERTY_FEDIVERSE,
|
||||
self::PROPERTY_HEADLINE,
|
||||
self::PROPERTY_ORGANISATION,
|
||||
self::PROPERTY_PHONE,
|
||||
self::PROPERTY_PROFILE_ENABLED,
|
||||
self::PROPERTY_PRONOUNS,
|
||||
self::PROPERTY_ROLE,
|
||||
self::PROPERTY_TWITTER,
|
||||
self::PROPERTY_WEBSITE,
|
||||
];
|
||||
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче