Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/nextcloud/server.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
path: root/apps
diff options
context:
space:
mode:
authorChristopher Ng <chrng8@gmail.com>2022-07-15 07:17:20 +0300
committerChristopher Ng <chrng8@gmail.com>2022-08-25 21:08:39 +0300
commitc5c70daa663cab80eb362b0312099fc2e71312e9 (patch)
treee606711c35c8ccb1f99d3f1284e3352b49059ff2 /apps
parent696a48ae975d7f9cf1ea80d35e6d93c103daa7c3 (diff)
Modularize shared account property components
Signed-off-by: Christopher Ng <chrng8@gmail.com>
Diffstat (limited to 'apps')
-rw-r--r--apps/settings/lib/Settings/Personal/PersonalInfo.php12
-rw-r--r--apps/settings/src/components/PersonalInfo/BiographySection.vue (renamed from apps/settings/src/components/PersonalInfo/BiographySection/BiographySection.vue)38
-rw-r--r--apps/settings/src/components/PersonalInfo/BiographySection/Biography.vue184
-rw-r--r--apps/settings/src/components/PersonalInfo/DisplayNameSection.vue66
-rw-r--r--apps/settings/src/components/PersonalInfo/DisplayNameSection/DisplayName.vue180
-rw-r--r--apps/settings/src/components/PersonalInfo/DisplayNameSection/DisplayNameSection.vue86
-rw-r--r--apps/settings/src/components/PersonalInfo/EmailSection/Email.vue14
-rw-r--r--apps/settings/src/components/PersonalInfo/EmailSection/EmailSection.vue22
-rw-r--r--apps/settings/src/components/PersonalInfo/HeadlineSection.vue (renamed from apps/settings/src/components/PersonalInfo/HeadlineSection/HeadlineSection.vue)37
-rw-r--r--apps/settings/src/components/PersonalInfo/HeadlineSection/Headline.vue175
-rw-r--r--apps/settings/src/components/PersonalInfo/LanguageSection/Language.vue14
-rw-r--r--apps/settings/src/components/PersonalInfo/LanguageSection/LanguageSection.vue19
-rw-r--r--apps/settings/src/components/PersonalInfo/OrganisationSection.vue (renamed from apps/settings/src/components/PersonalInfo/OrganisationSection/OrganisationSection.vue)37
-rw-r--r--apps/settings/src/components/PersonalInfo/OrganisationSection/Organisation.vue175
-rw-r--r--apps/settings/src/components/PersonalInfo/ProfileSection/ProfileCheckbox.vue8
-rw-r--r--apps/settings/src/components/PersonalInfo/ProfileSection/ProfileSection.vue14
-rw-r--r--apps/settings/src/components/PersonalInfo/ProfileVisibilitySection/ProfileVisibilitySection.vue8
-rw-r--r--apps/settings/src/components/PersonalInfo/ProfileVisibilitySection/VisibilityDropdown.vue9
-rw-r--r--apps/settings/src/components/PersonalInfo/RoleSection.vue (renamed from apps/settings/src/components/PersonalInfo/RoleSection/RoleSection.vue)37
-rw-r--r--apps/settings/src/components/PersonalInfo/RoleSection/Role.vue175
-rw-r--r--apps/settings/src/components/PersonalInfo/shared/AccountPropertySection.vue265
-rw-r--r--apps/settings/src/components/PersonalInfo/shared/FederationControl.vue30
-rw-r--r--apps/settings/src/components/PersonalInfo/shared/HeaderBar.vue40
-rw-r--r--apps/settings/src/constants/AccountPropertyConstants.js16
-rw-r--r--apps/settings/src/main-personal-info.js18
-rw-r--r--apps/settings/src/utils/validate.js12
26 files changed, 496 insertions, 1195 deletions
diff --git a/apps/settings/lib/Settings/Personal/PersonalInfo.php b/apps/settings/lib/Settings/Personal/PersonalInfo.php
index fbbee7b81bb..c60f39025e8 100644
--- a/apps/settings/lib/Settings/Personal/PersonalInfo.php
+++ b/apps/settings/lib/Settings/Personal/PersonalInfo.php
@@ -135,7 +135,6 @@ class PersonalInfo implements ISettings {
$totalSpace = \OC_Helper::humanFileSize($storageInfo['total']);
}
- $languageParameters = $this->getLanguageMap($user);
$localeParameters = $this->getLocales($user);
$messageParameters = $this->getMessageParameters($account);
@@ -148,12 +147,6 @@ class PersonalInfo implements ISettings {
'federationEnabled' => $federationEnabled,
'lookupServerUploadEnabled' => $lookupServerUploadEnabled,
'avatarScope' => $account->getProperty(IAccountManager::PROPERTY_AVATAR)->getScope(),
- 'displayNameChangeSupported' => $user->canChangeDisplayName(),
- 'displayName' => $account->getProperty(IAccountManager::PROPERTY_DISPLAYNAME)->getValue(),
- 'displayNameScope' => $account->getProperty(IAccountManager::PROPERTY_DISPLAYNAME)->getScope(),
- 'email' => $account->getProperty(IAccountManager::PROPERTY_EMAIL)->getValue(),
- 'emailScope' => $account->getProperty(IAccountManager::PROPERTY_EMAIL)->getScope(),
- 'emailVerification' => $account->getProperty(IAccountManager::PROPERTY_EMAIL)->getVerified(),
'phone' => $account->getProperty(IAccountManager::PROPERTY_PHONE)->getValue(),
'phoneScope' => $account->getProperty(IAccountManager::PROPERTY_PHONE)->getScope(),
'address' => $account->getProperty(IAccountManager::PROPERTY_ADDRESS)->getValue(),
@@ -167,7 +160,7 @@ class PersonalInfo implements ISettings {
'groups' => $this->getGroups($user),
'isFairUseOfFreePushService' => $this->isFairUseOfFreePushService(),
'profileEnabledGlobally' => $this->profileManager->isProfileEnabled(),
- ] + $messageParameters + $languageParameters + $localeParameters;
+ ] + $messageParameters + $localeParameters;
$personalInfoParameters = [
'userId' => $uid,
@@ -213,6 +206,7 @@ class PersonalInfo implements ISettings {
*/
private function getProperty(IAccount $account, string $property): array {
$property = [
+ 'name' => $account->getProperty($property)->getName(),
'value' => $account->getProperty($property)->getValue(),
'scope' => $account->getProperty($property)->getScope(),
'verified' => $account->getProperty($property)->getVerified(),
@@ -262,6 +256,7 @@ class PersonalInfo implements ISettings {
*/
private function getEmailMap(IAccount $account): array {
$systemEmail = [
+ 'name' => $account->getProperty(IAccountManager::PROPERTY_EMAIL)->getName(),
'value' => $account->getProperty(IAccountManager::PROPERTY_EMAIL)->getValue(),
'scope' => $account->getProperty(IAccountManager::PROPERTY_EMAIL)->getScope(),
'verified' => $account->getProperty(IAccountManager::PROPERTY_EMAIL)->getVerified(),
@@ -270,6 +265,7 @@ class PersonalInfo implements ISettings {
$additionalEmails = array_map(
function (IAccountProperty $property) {
return [
+ 'name' => $property->getName(),
'value' => $property->getValue(),
'scope' => $property->getScope(),
'verified' => $property->getVerified(),
diff --git a/apps/settings/src/components/PersonalInfo/BiographySection/BiographySection.vue b/apps/settings/src/components/PersonalInfo/BiographySection.vue
index c8464f7b243..30c240dee1a 100644
--- a/apps/settings/src/components/PersonalInfo/BiographySection/BiographySection.vue
+++ b/apps/settings/src/components/PersonalInfo/BiographySection.vue
@@ -1,9 +1,9 @@
<!--
- - @copyright 2021, Christopher Ng <chrng8@gmail.com>
+ - @copyright 2022 Christopher Ng <chrng8@gmail.com>
-
- @author Christopher Ng <chrng8@gmail.com>
-
- - @license GNU AGPL version 3 or any later version
+ - @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 Affero General Public License as
@@ -12,7 +12,7 @@
-
- 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
+ - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU Affero General Public License for more details.
-
- You should have received a copy of the GNU Affero General Public License
@@ -21,23 +21,17 @@
-->
<template>
- <section>
- <HeaderBar :account-property="accountProperty"
- label-for="biography"
- :scope.sync="biography.scope" />
-
- <Biography :biography.sync="biography.value"
- :scope.sync="biography.scope" />
- </section>
+ <AccountPropertySection v-bind.sync="biography"
+ :placeholder="t('settings', 'Your biography')"
+ :multi-line="true" />
</template>
<script>
import { loadState } from '@nextcloud/initial-state'
-import Biography from './Biography'
-import HeaderBar from '../shared/HeaderBar'
+import AccountPropertySection from './shared/AccountPropertySection.vue'
-import { ACCOUNT_PROPERTY_READABLE_ENUM } from '../../../constants/AccountPropertyConstants'
+import { NAME_READABLE_ENUM } from '../../constants/AccountPropertyConstants.js'
const { biography } = loadState('settings', 'personalInfoParameters', {})
@@ -45,25 +39,13 @@ export default {
name: 'BiographySection',
components: {
- Biography,
- HeaderBar,
+ AccountPropertySection,
},
data() {
return {
- accountProperty: ACCOUNT_PROPERTY_READABLE_ENUM.BIOGRAPHY,
- biography,
+ biography: { ...biography, readable: NAME_READABLE_ENUM[biography.name] },
}
},
}
</script>
-
-<style lang="scss" scoped>
-section {
- padding: 10px 10px;
-
- &::v-deep button:disabled {
- cursor: default;
- }
-}
-</style>
diff --git a/apps/settings/src/components/PersonalInfo/BiographySection/Biography.vue b/apps/settings/src/components/PersonalInfo/BiographySection/Biography.vue
deleted file mode 100644
index 48c2bf4ff77..00000000000
--- a/apps/settings/src/components/PersonalInfo/BiographySection/Biography.vue
+++ /dev/null
@@ -1,184 +0,0 @@
-<!--
- - @copyright 2021, Christopher Ng <chrng8@gmail.com>
- -
- - @author Christopher Ng <chrng8@gmail.com>
- -
- - @license GNU AGPL version 3 or any later version
- -
- - This program is free software: you can redistribute it and/or modify
- - it under the terms of the GNU Affero 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 Affero General Public License for more details.
- -
- - You should have received a copy of the GNU Affero General Public License
- - along with this program. If not, see <http://www.gnu.org/licenses/>.
- -
--->
-
-<template>
- <div class="biography">
- <textarea id="biography"
- :placeholder="t('settings', 'Your biography')"
- :value="biography"
- rows="8"
- autocapitalize="none"
- autocomplete="off"
- autocorrect="off"
- @input="onBiographyChange" />
-
- <div class="biography__actions-container">
- <transition name="fade">
- <span v-if="showCheckmarkIcon" class="icon-checkmark" />
- <span v-else-if="showErrorIcon" class="icon-error" />
- </transition>
- </div>
- </div>
-</template>
-
-<script>
-import { showError } from '@nextcloud/dialogs'
-import { emit } from '@nextcloud/event-bus'
-import debounce from 'debounce'
-
-import { ACCOUNT_PROPERTY_ENUM } from '../../../constants/AccountPropertyConstants'
-import { savePrimaryAccountProperty } from '../../../service/PersonalInfo/PersonalInfoService'
-import logger from '../../../logger'
-
-export default {
- name: 'Biography',
-
- props: {
- biography: {
- type: String,
- required: true,
- },
- scope: {
- type: String,
- required: true,
- },
- },
-
- data() {
- return {
- initialBiography: this.biography,
- localScope: this.scope,
- showCheckmarkIcon: false,
- showErrorIcon: false,
- }
- },
-
- methods: {
- onBiographyChange(e) {
- this.$emit('update:biography', e.target.value)
- this.debounceBiographyChange(e.target.value.trim())
- },
-
- debounceBiographyChange: debounce(async function(biography) {
- await this.updatePrimaryBiography(biography)
- }, 500),
-
- async updatePrimaryBiography(biography) {
- try {
- const responseData = await savePrimaryAccountProperty(ACCOUNT_PROPERTY_ENUM.BIOGRAPHY, biography)
- this.handleResponse({
- biography,
- status: responseData.ocs?.meta?.status,
- })
- } catch (e) {
- this.handleResponse({
- errorMessage: t('settings', 'Unable to update biography'),
- error: e,
- })
- }
- },
-
- handleResponse({ biography, status, errorMessage, error }) {
- if (status === 'ok') {
- // Ensure that local state reflects server state
- this.initialBiography = biography
- emit('settings:biography:updated', biography)
- this.showCheckmarkIcon = true
- setTimeout(() => { this.showCheckmarkIcon = false }, 2000)
- } else {
- showError(errorMessage)
- logger.error(errorMessage, error)
- this.showErrorIcon = true
- setTimeout(() => { this.showErrorIcon = false }, 2000)
- }
- },
-
- onScopeChange(scope) {
- this.$emit('update:scope', scope)
- },
- },
-}
-</script>
-
-<style lang="scss" scoped>
-.biography {
- display: grid;
- align-items: center;
-
- textarea {
- resize: vertical;
- grid-area: 1 / 1;
- width: 100%;
- margin: 3px 3px 3px 0;
- padding: 7px 6px;
- color: var(--color-main-text);
- border: 1px solid var(--color-border-dark);
- border-radius: var(--border-radius);
- background-color: var(--color-main-background);
- font-family: var(--font-face);
- cursor: text;
-
- &:hover,
- &:focus,
- &:active {
- border-color: var(--color-primary-element) !important;
- outline: none !important;
- }
- }
-
- .biography__actions-container {
- grid-area: 1 / 1;
- justify-self: flex-end;
- align-self: flex-end;
- height: 30px;
-
- display: flex;
- gap: 0 2px;
- margin-right: 5px;
- margin-bottom: 5px;
-
- .icon-checkmark,
- .icon-error {
- height: 30px !important;
- min-height: 30px !important;
- width: 30px !important;
- min-width: 30px !important;
- top: 0;
- right: 0;
- float: none;
- }
- }
-}
-
-.fade-enter,
-.fade-leave-to {
- opacity: 0;
-}
-
-.fade-enter-active {
- transition: opacity 200ms ease-out;
-}
-
-.fade-leave-active {
- transition: opacity 300ms ease-out;
-}
-</style>
diff --git a/apps/settings/src/components/PersonalInfo/DisplayNameSection.vue b/apps/settings/src/components/PersonalInfo/DisplayNameSection.vue
new file mode 100644
index 00000000000..dd5f97966ac
--- /dev/null
+++ b/apps/settings/src/components/PersonalInfo/DisplayNameSection.vue
@@ -0,0 +1,66 @@
+<!--
+ - @copyright 2022 Christopher Ng <chrng8@gmail.com>
+ -
+ - @author Christopher Ng <chrng8@gmail.com>
+ -
+ - @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 Affero 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 Affero General Public License for more details.
+ -
+ - You should have received a copy of the GNU Affero General Public License
+ - along with this program. If not, see <http://www.gnu.org/licenses/>.
+ -
+-->
+
+<template>
+ <AccountPropertySection v-bind.sync="displayName"
+ :placeholder="t('settings', 'Your full name')"
+ :is-editable="displayNameChangeSupported"
+ :on-validate="onValidate"
+ :on-save="onSave" />
+</template>
+
+<script>
+import { loadState } from '@nextcloud/initial-state'
+import { emit } from '@nextcloud/event-bus'
+
+import AccountPropertySection from './shared/AccountPropertySection.vue'
+
+import { NAME_READABLE_ENUM } from '../../constants/AccountPropertyConstants.js'
+
+const { displayName } = loadState('settings', 'personalInfoParameters', {})
+const { displayNameChangeSupported } = loadState('settings', 'accountParameters', {})
+
+export default {
+ name: 'DisplayNameSection',
+
+ components: {
+ AccountPropertySection,
+ },
+
+ data() {
+ return {
+ displayName: { ...displayName, readable: NAME_READABLE_ENUM[displayName.name] },
+ displayNameChangeSupported,
+ }
+ },
+
+ methods: {
+ onValidate(value) {
+ return value !== ''
+ },
+
+ onSave(value) {
+ emit('settings:display-name:updated', value)
+ },
+ }
+}
+</script>
diff --git a/apps/settings/src/components/PersonalInfo/DisplayNameSection/DisplayName.vue b/apps/settings/src/components/PersonalInfo/DisplayNameSection/DisplayName.vue
deleted file mode 100644
index 58252bfbd63..00000000000
--- a/apps/settings/src/components/PersonalInfo/DisplayNameSection/DisplayName.vue
+++ /dev/null
@@ -1,180 +0,0 @@
-<!--
- - @copyright 2021, Christopher Ng <chrng8@gmail.com>
- -
- - @author Christopher Ng <chrng8@gmail.com>
- -
- - @license GNU AGPL version 3 or any later version
- -
- - This program is free software: you can redistribute it and/or modify
- - it under the terms of the GNU Affero 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 Affero General Public License for more details.
- -
- - You should have received a copy of the GNU Affero General Public License
- - along with this program. If not, see <http://www.gnu.org/licenses/>.
- -
--->
-
-<template>
- <div class="displayname">
- <input id="displayname"
- type="text"
- :placeholder="t('settings', 'Your full name')"
- :value="displayName"
- autocapitalize="none"
- autocomplete="on"
- autocorrect="off"
- @input="onDisplayNameChange">
-
- <div class="displayname__actions-container">
- <transition name="fade">
- <span v-if="showCheckmarkIcon" class="icon-checkmark" />
- <span v-else-if="showErrorIcon" class="icon-error" />
- </transition>
- </div>
- </div>
-</template>
-
-<script>
-import { showError } from '@nextcloud/dialogs'
-import { emit } from '@nextcloud/event-bus'
-import debounce from 'debounce'
-
-import { ACCOUNT_PROPERTY_ENUM } from '../../../constants/AccountPropertyConstants'
-import { savePrimaryAccountProperty } from '../../../service/PersonalInfo/PersonalInfoService'
-import { validateStringInput } from '../../../utils/validate'
-import logger from '../../../logger'
-
-// TODO Global avatar updating on events (e.g. updating the displayname) is currently being handled by global js, investigate using https://github.com/nextcloud/nextcloud-event-bus for global avatar updating
-
-export default {
- name: 'DisplayName',
-
- props: {
- displayName: {
- type: String,
- required: true,
- },
- scope: {
- type: String,
- required: true,
- },
- },
-
- data() {
- return {
- initialDisplayName: this.displayName,
- localScope: this.scope,
- showCheckmarkIcon: false,
- showErrorIcon: false,
- }
- },
-
- methods: {
- onDisplayNameChange(e) {
- this.$emit('update:display-name', e.target.value)
- this.debounceDisplayNameChange(e.target.value.trim())
- },
-
- debounceDisplayNameChange: debounce(async function(displayName) {
- if (validateStringInput(displayName)) {
- await this.updatePrimaryDisplayName(displayName)
- }
- }, 500),
-
- async updatePrimaryDisplayName(displayName) {
- try {
- const responseData = await savePrimaryAccountProperty(ACCOUNT_PROPERTY_ENUM.DISPLAYNAME, displayName)
- this.handleResponse({
- displayName,
- status: responseData.ocs?.meta?.status,
- })
- } catch (e) {
- this.handleResponse({
- errorMessage: t('settings', 'Unable to update full name'),
- error: e,
- })
- }
- },
-
- handleResponse({ displayName, status, errorMessage, error }) {
- if (status === 'ok') {
- // Ensure that local state reflects server state
- this.initialDisplayName = displayName
- emit('settings:display-name:updated', displayName)
- this.showCheckmarkIcon = true
- setTimeout(() => { this.showCheckmarkIcon = false }, 2000)
- } else {
- showError(errorMessage)
- logger.error(errorMessage, error)
- this.showErrorIcon = true
- setTimeout(() => { this.showErrorIcon = false }, 2000)
- }
- },
-
- onScopeChange(scope) {
- this.$emit('update:scope', scope)
- },
- },
-}
-</script>
-
-<style lang="scss" scoped>
-.displayname {
- display: grid;
- align-items: center;
-
- input {
- grid-area: 1 / 1;
- width: 100%;
- height: 34px;
- margin: 3px 3px 3px 0;
- padding: 7px 6px;
- color: var(--color-main-text);
- border: 1px solid var(--color-border-dark);
- border-radius: var(--border-radius);
- background-color: var(--color-main-background);
- font-family: var(--font-face);
- cursor: text;
- }
-
- .displayname__actions-container {
- grid-area: 1 / 1;
- justify-self: flex-end;
- height: 30px;
-
- display: flex;
- gap: 0 2px;
- margin-right: 5px;
-
- .icon-checkmark,
- .icon-error {
- height: 30px !important;
- min-height: 30px !important;
- width: 30px !important;
- min-width: 30px !important;
- top: 0;
- right: 0;
- float: none;
- }
- }
-}
-
-.fade-enter,
-.fade-leave-to {
- opacity: 0;
-}
-
-.fade-enter-active {
- transition: opacity 200ms ease-out;
-}
-
-.fade-leave-active {
- transition: opacity 300ms ease-out;
-}
-</style>
diff --git a/apps/settings/src/components/PersonalInfo/DisplayNameSection/DisplayNameSection.vue b/apps/settings/src/components/PersonalInfo/DisplayNameSection/DisplayNameSection.vue
deleted file mode 100644
index d808369e9fb..00000000000
--- a/apps/settings/src/components/PersonalInfo/DisplayNameSection/DisplayNameSection.vue
+++ /dev/null
@@ -1,86 +0,0 @@
-<!--
- - @copyright 2021, Christopher Ng <chrng8@gmail.com>
- -
- - @author Christopher Ng <chrng8@gmail.com>
- -
- - @license GNU AGPL version 3 or any later version
- -
- - This program is free software: you can redistribute it and/or modify
- - it under the terms of the GNU Affero 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 Affero General Public License for more details.
- -
- - You should have received a copy of the GNU Affero General Public License
- - along with this program. If not, see <http://www.gnu.org/licenses/>.
- -
--->
-
-<template>
- <section>
- <HeaderBar :account-property="accountProperty"
- label-for="displayname"
- :is-editable="displayNameChangeSupported"
- :is-valid-section="isValidSection"
- :scope.sync="displayName.scope" />
-
- <template v-if="displayNameChangeSupported">
- <DisplayName :display-name.sync="displayName.value"
- :scope.sync="displayName.scope" />
- </template>
-
- <span v-else>
- {{ displayName.value || t('settings', 'No full name set') }}
- </span>
- </section>
-</template>
-
-<script>
-import { loadState } from '@nextcloud/initial-state'
-
-import DisplayName from './DisplayName'
-import HeaderBar from '../shared/HeaderBar'
-
-import { ACCOUNT_PROPERTY_READABLE_ENUM } from '../../../constants/AccountPropertyConstants'
-import { validateStringInput } from '../../../utils/validate'
-
-const { displayName } = loadState('settings', 'personalInfoParameters', {})
-const { displayNameChangeSupported } = loadState('settings', 'accountParameters', {})
-
-export default {
- name: 'DisplayNameSection',
-
- components: {
- DisplayName,
- HeaderBar,
- },
-
- data() {
- return {
- accountProperty: ACCOUNT_PROPERTY_READABLE_ENUM.DISPLAYNAME,
- displayNameChangeSupported,
- displayName,
- }
- },
-
- computed: {
- isValidSection() {
- return validateStringInput(this.displayName.value)
- },
- },
-}
-</script>
-
-<style lang="scss" scoped>
-section {
- padding: 10px 10px;
-
- &::v-deep button:disabled {
- cursor: default;
- }
-}
-</style>
diff --git a/apps/settings/src/components/PersonalInfo/EmailSection/Email.vue b/apps/settings/src/components/PersonalInfo/EmailSection/Email.vue
index be837baf2bd..bdcc1bdd753 100644
--- a/apps/settings/src/components/PersonalInfo/EmailSection/Email.vue
+++ b/apps/settings/src/components/PersonalInfo/EmailSection/Email.vue
@@ -40,7 +40,7 @@
</transition>
<template v-if="!primary">
- <FederationControl :account-property="accountProperty"
+ <FederationControl :readable="propertyReadable"
:additional="true"
:additional-value="email"
:disabled="federationDisabled"
@@ -85,10 +85,10 @@ import Check from 'vue-material-design-icons/Check'
import { showError } from '@nextcloud/dialogs'
import debounce from 'debounce'
-import FederationControl from '../shared/FederationControl'
-import logger from '../../../logger'
+import FederationControl from '../shared/FederationControl.vue'
+import logger from '../../../logger.js'
-import { ACCOUNT_PROPERTY_READABLE_ENUM, VERIFICATION_ENUM } from '../../../constants/AccountPropertyConstants'
+import { ACCOUNT_PROPERTY_READABLE_ENUM, VERIFICATION_ENUM } from '../../../constants/AccountPropertyConstants.js'
import {
removeAdditionalEmail,
saveAdditionalEmail,
@@ -96,8 +96,8 @@ import {
saveNotificationEmail,
savePrimaryEmail,
updateAdditionalEmail,
-} from '../../../service/PersonalInfo/EmailService'
-import { validateEmail } from '../../../utils/validate'
+} from '../../../service/PersonalInfo/EmailService.js'
+import { validateEmail } from '../../../utils/validate.js'
export default {
name: 'Email',
@@ -139,7 +139,7 @@ export default {
data() {
return {
- accountProperty: ACCOUNT_PROPERTY_READABLE_ENUM.EMAIL,
+ propertyReadable: ACCOUNT_PROPERTY_READABLE_ENUM.EMAIL,
initialEmail: this.email,
localScope: this.scope,
saveAdditionalEmailScope,
diff --git a/apps/settings/src/components/PersonalInfo/EmailSection/EmailSection.vue b/apps/settings/src/components/PersonalInfo/EmailSection/EmailSection.vue
index 3463daa5755..6bfb8bfee8b 100644
--- a/apps/settings/src/components/PersonalInfo/EmailSection/EmailSection.vue
+++ b/apps/settings/src/components/PersonalInfo/EmailSection/EmailSection.vue
@@ -22,8 +22,8 @@
<template>
<section>
- <HeaderBar :account-property="accountProperty"
- label-for="email"
+ <HeaderBar :input-id="inputId"
+ :readable="primaryEmail.readable"
:handle-scope-change="savePrimaryEmailScope"
:is-editable="true"
:is-multi-value-supported="true"
@@ -65,13 +65,13 @@
import { loadState } from '@nextcloud/initial-state'
import { showError } from '@nextcloud/dialogs'
-import Email from './Email'
-import HeaderBar from '../shared/HeaderBar'
+import Email from './Email.vue'
+import HeaderBar from '../shared/HeaderBar.vue'
-import { ACCOUNT_PROPERTY_READABLE_ENUM, DEFAULT_ADDITIONAL_EMAIL_SCOPE } from '../../../constants/AccountPropertyConstants'
-import { savePrimaryEmail, savePrimaryEmailScope, removeAdditionalEmail } from '../../../service/PersonalInfo/EmailService'
-import { validateEmail } from '../../../utils/validate'
-import logger from '../../../logger'
+import { ACCOUNT_PROPERTY_READABLE_ENUM, DEFAULT_ADDITIONAL_EMAIL_SCOPE, NAME_READABLE_ENUM } from '../../../constants/AccountPropertyConstants.js'
+import { savePrimaryEmail, savePrimaryEmailScope, removeAdditionalEmail } from '../../../service/PersonalInfo/EmailService.js'
+import { validateEmail } from '../../../utils/validate.js'
+import logger from '../../../logger.js'
const { emailMap: { additionalEmails, primaryEmail, notificationEmail } } = loadState('settings', 'personalInfoParameters', {})
const { displayNameChangeSupported } = loadState('settings', 'accountParameters', {})
@@ -89,7 +89,7 @@ export default {
accountProperty: ACCOUNT_PROPERTY_READABLE_ENUM.EMAIL,
additionalEmails: additionalEmails.map(properties => ({ ...properties, key: this.generateUniqueKey() })),
displayNameChangeSupported,
- primaryEmail,
+ primaryEmail: { ...primaryEmail, readable: NAME_READABLE_ENUM[primaryEmail.name] },
savePrimaryEmailScope,
notificationEmail,
}
@@ -103,6 +103,10 @@ export default {
return null
},
+ inputId() {
+ return `account-property-${this.primaryEmail.name}`
+ },
+
isValidSection() {
return validateEmail(this.primaryEmail.value)
&& this.additionalEmails.map(({ value }) => value).every(validateEmail)
diff --git a/apps/settings/src/components/PersonalInfo/HeadlineSection/HeadlineSection.vue b/apps/settings/src/components/PersonalInfo/HeadlineSection.vue
index 1a608d2fc02..0275c1df80b 100644
--- a/apps/settings/src/components/PersonalInfo/HeadlineSection/HeadlineSection.vue
+++ b/apps/settings/src/components/PersonalInfo/HeadlineSection.vue
@@ -1,9 +1,9 @@
<!--
- - @copyright 2021, Christopher Ng <chrng8@gmail.com>
+ - @copyright 2022 Christopher Ng <chrng8@gmail.com>
-
- @author Christopher Ng <chrng8@gmail.com>
-
- - @license GNU AGPL version 3 or any later version
+ - @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 Affero General Public License as
@@ -12,7 +12,7 @@
-
- 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
+ - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU Affero General Public License for more details.
-
- You should have received a copy of the GNU Affero General Public License
@@ -21,23 +21,16 @@
-->
<template>
- <section>
- <HeaderBar :account-property="accountProperty"
- label-for="headline"
- :scope.sync="headline.scope" />
-
- <Headline :headline.sync="headline.value"
- :scope.sync="headline.scope" />
- </section>
+ <AccountPropertySection v-bind.sync="headline"
+ :placeholder="t('settings', 'Your headline')" />
</template>
<script>
import { loadState } from '@nextcloud/initial-state'
-import Headline from './Headline'
-import HeaderBar from '../shared/HeaderBar'
+import AccountPropertySection from './shared/AccountPropertySection.vue'
-import { ACCOUNT_PROPERTY_READABLE_ENUM } from '../../../constants/AccountPropertyConstants'
+import { NAME_READABLE_ENUM } from '../../constants/AccountPropertyConstants.js'
const { headline } = loadState('settings', 'personalInfoParameters', {})
@@ -45,25 +38,13 @@ export default {
name: 'HeadlineSection',
components: {
- Headline,
- HeaderBar,
+ AccountPropertySection,
},
data() {
return {
- accountProperty: ACCOUNT_PROPERTY_READABLE_ENUM.HEADLINE,
- headline,
+ headline: { ...headline, readable: NAME_READABLE_ENUM[headline.name] },
}
},
}
</script>
-
-<style lang="scss" scoped>
-section {
- padding: 10px 10px;
-
- &::v-deep button:disabled {
- cursor: default;
- }
-}
-</style>
diff --git a/apps/settings/src/components/PersonalInfo/HeadlineSection/Headline.vue b/apps/settings/src/components/PersonalInfo/HeadlineSection/Headline.vue
deleted file mode 100644
index 4cb7d63b522..00000000000
--- a/apps/settings/src/components/PersonalInfo/HeadlineSection/Headline.vue
+++ /dev/null
@@ -1,175 +0,0 @@
-<!--
- - @copyright 2021, Christopher Ng <chrng8@gmail.com>
- -
- - @author Christopher Ng <chrng8@gmail.com>
- -
- - @license GNU AGPL version 3 or any later version
- -
- - This program is free software: you can redistribute it and/or modify
- - it under the terms of the GNU Affero 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 Affero General Public License for more details.
- -
- - You should have received a copy of the GNU Affero General Public License
- - along with this program. If not, see <http://www.gnu.org/licenses/>.
- -
--->
-
-<template>
- <div class="headline">
- <input id="headline"
- type="text"
- :placeholder="t('settings', 'Your headline')"
- :value="headline"
- autocapitalize="none"
- autocomplete="on"
- autocorrect="off"
- @input="onHeadlineChange">
-
- <div class="headline__actions-container">
- <transition name="fade">
- <span v-if="showCheckmarkIcon" class="icon-checkmark" />
- <span v-else-if="showErrorIcon" class="icon-error" />
- </transition>
- </div>
- </div>
-</template>
-
-<script>
-import { showError } from '@nextcloud/dialogs'
-import { emit } from '@nextcloud/event-bus'
-import debounce from 'debounce'
-
-import { ACCOUNT_PROPERTY_ENUM } from '../../../constants/AccountPropertyConstants'
-import { savePrimaryAccountProperty } from '../../../service/PersonalInfo/PersonalInfoService'
-import logger from '../../../logger'
-
-export default {
- name: 'Headline',
-
- props: {
- headline: {
- type: String,
- required: true,
- },
- scope: {
- type: String,
- required: true,
- },
- },
-
- data() {
- return {
- initialHeadline: this.headline,
- localScope: this.scope,
- showCheckmarkIcon: false,
- showErrorIcon: false,
- }
- },
-
- methods: {
- onHeadlineChange(e) {
- this.$emit('update:headline', e.target.value)
- this.debounceHeadlineChange(e.target.value.trim())
- },
-
- debounceHeadlineChange: debounce(async function(headline) {
- await this.updatePrimaryHeadline(headline)
- }, 500),
-
- async updatePrimaryHeadline(headline) {
- try {
- const responseData = await savePrimaryAccountProperty(ACCOUNT_PROPERTY_ENUM.HEADLINE, headline)
- this.handleResponse({
- headline,
- status: responseData.ocs?.meta?.status,
- })
- } catch (e) {
- this.handleResponse({
- errorMessage: t('settings', 'Unable to update headline'),
- error: e,
- })
- }
- },
-
- handleResponse({ headline, status, errorMessage, error }) {
- if (status === 'ok') {
- // Ensure that local state reflects server state
- this.initialHeadline = headline
- emit('settings:headline:updated', headline)
- this.showCheckmarkIcon = true
- setTimeout(() => { this.showCheckmarkIcon = false }, 2000)
- } else {
- showError(errorMessage)
- logger.error(errorMessage, error)
- this.showErrorIcon = true
- setTimeout(() => { this.showErrorIcon = false }, 2000)
- }
- },
-
- onScopeChange(scope) {
- this.$emit('update:scope', scope)
- },
- },
-}
-</script>
-
-<style lang="scss" scoped>
-.headline {
- display: grid;
- align-items: center;
-
- input {
- grid-area: 1 / 1;
- width: 100%;
- height: 34px;
- margin: 3px 3px 3px 0;
- padding: 7px 6px;
- color: var(--color-main-text);
- border: 1px solid var(--color-border-dark);
- border-radius: var(--border-radius);
- background-color: var(--color-main-background);
- font-family: var(--font-face);
- cursor: text;
- }
-
- .headline__actions-container {
- grid-area: 1 / 1;
- justify-self: flex-end;
- height: 30px;
-
- display: flex;
- gap: 0 2px;
- margin-right: 5px;
-
- .icon-checkmark,
- .icon-error {
- height: 30px !important;
- min-height: 30px !important;
- width: 30px !important;
- min-width: 30px !important;
- top: 0;
- right: 0;
- float: none;
- }
- }
-}
-
-.fade-enter,
-.fade-leave-to {
- opacity: 0;
-}
-
-.fade-enter-active {
- transition: opacity 200ms ease-out;
-}
-
-.fade-leave-active {
- transition: opacity 300ms ease-out;
-}
-</style>
diff --git a/apps/settings/src/components/PersonalInfo/LanguageSection/Language.vue b/apps/settings/src/components/PersonalInfo/LanguageSection/Language.vue
index 99dadd449ce..8b2f8e3d0cc 100644
--- a/apps/settings/src/components/PersonalInfo/LanguageSection/Language.vue
+++ b/apps/settings/src/components/PersonalInfo/LanguageSection/Language.vue
@@ -22,7 +22,7 @@
<template>
<div class="language">
- <select id="language"
+ <select :id="inputId"
:placeholder="t('settings', 'Language')"
@change="onLanguageChange">
<option v-for="commonLanguage in commonLanguages"
@@ -53,15 +53,19 @@
<script>
import { showError } from '@nextcloud/dialogs'
-import { ACCOUNT_SETTING_PROPERTY_ENUM } from '../../../constants/AccountPropertyConstants'
-import { savePrimaryAccountProperty } from '../../../service/PersonalInfo/PersonalInfoService'
-import { validateLanguage } from '../../../utils/validate'
-import logger from '../../../logger'
+import { ACCOUNT_SETTING_PROPERTY_ENUM } from '../../../constants/AccountPropertyConstants.js'
+import { savePrimaryAccountProperty } from '../../../service/PersonalInfo/PersonalInfoService.js'
+import { validateLanguage } from '../../../utils/validate.js'
+import logger from '../../../logger.js'
export default {
name: 'Language',
props: {
+ inputId: {
+ type: String,
+ default: null,
+ },
commonLanguages: {
type: Array,
required: true,
diff --git a/apps/settings/src/components/PersonalInfo/LanguageSection/LanguageSection.vue b/apps/settings/src/components/PersonalInfo/LanguageSection/LanguageSection.vue
index 90882b23869..fdc1d31d10c 100644
--- a/apps/settings/src/components/PersonalInfo/LanguageSection/LanguageSection.vue
+++ b/apps/settings/src/components/PersonalInfo/LanguageSection/LanguageSection.vue
@@ -22,11 +22,12 @@
<template>
<section>
- <HeaderBar :account-property="accountProperty"
- label-for="language" />
+ <HeaderBar :input-id="inputId"
+ :readable="propertyReadable" />
<template v-if="isEditable">
- <Language :common-languages="commonLanguages"
+ <Language :input-id="inputId"
+ :common-languages="commonLanguages"
:other-languages="otherLanguages"
:language.sync="language" />
</template>
@@ -40,10 +41,10 @@
<script>
import { loadState } from '@nextcloud/initial-state'
-import Language from './Language'
-import HeaderBar from '../shared/HeaderBar'
+import Language from './Language.vue'
+import HeaderBar from '../shared/HeaderBar.vue'
-import { ACCOUNT_SETTING_PROPERTY_READABLE_ENUM } from '../../../constants/AccountPropertyConstants'
+import { ACCOUNT_SETTING_PROPERTY_ENUM, ACCOUNT_SETTING_PROPERTY_READABLE_ENUM } from '../../../constants/AccountPropertyConstants.js'
const { languageMap: { activeLanguage, commonLanguages, otherLanguages } } = loadState('settings', 'personalInfoParameters', {})
@@ -57,7 +58,7 @@ export default {
data() {
return {
- accountProperty: ACCOUNT_SETTING_PROPERTY_READABLE_ENUM.LANGUAGE,
+ propertyReadable: ACCOUNT_SETTING_PROPERTY_READABLE_ENUM.LANGUAGE,
commonLanguages,
otherLanguages,
language: activeLanguage,
@@ -65,6 +66,10 @@ export default {
},
computed: {
+ inputId() {
+ return `account-setting-${ACCOUNT_SETTING_PROPERTY_ENUM.LANGUAGE}`
+ },
+
isEditable() {
return Boolean(this.language)
},
diff --git a/apps/settings/src/components/PersonalInfo/OrganisationSection/OrganisationSection.vue b/apps/settings/src/components/PersonalInfo/OrganisationSection.vue
index b436b2edd0b..7a85d2fd647 100644
--- a/apps/settings/src/components/PersonalInfo/OrganisationSection/OrganisationSection.vue
+++ b/apps/settings/src/components/PersonalInfo/OrganisationSection.vue
@@ -1,9 +1,9 @@
<!--
- - @copyright 2021, Christopher Ng <chrng8@gmail.com>
+ - @copyright 2022 Christopher Ng <chrng8@gmail.com>
-
- @author Christopher Ng <chrng8@gmail.com>
-
- - @license GNU AGPL version 3 or any later version
+ - @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 Affero General Public License as
@@ -12,7 +12,7 @@
-
- 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
+ - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU Affero General Public License for more details.
-
- You should have received a copy of the GNU Affero General Public License
@@ -21,23 +21,16 @@
-->
<template>
- <section>
- <HeaderBar :account-property="accountProperty"
- label-for="organisation"
- :scope.sync="organisation.scope" />
-
- <Organisation :organisation.sync="organisation.value"
- :scope.sync="organisation.scope" />
- </section>
+ <AccountPropertySection v-bind.sync="organisation"
+ :placeholder="t('settings', 'Your organisation')" />
</template>
<script>
import { loadState } from '@nextcloud/initial-state'
-import Organisation from './Organisation'
-import HeaderBar from '../shared/HeaderBar'
+import AccountPropertySection from './shared/AccountPropertySection.vue'
-import { ACCOUNT_PROPERTY_READABLE_ENUM } from '../../../constants/AccountPropertyConstants'
+import { NAME_READABLE_ENUM } from '../../constants/AccountPropertyConstants.js'
const { organisation } = loadState('settings', 'personalInfoParameters', {})
@@ -45,25 +38,13 @@ export default {
name: 'OrganisationSection',
components: {
- Organisation,
- HeaderBar,
+ AccountPropertySection,
},
data() {
return {
- accountProperty: ACCOUNT_PROPERTY_READABLE_ENUM.ORGANISATION,
- organisation,
+ organisation: { ...organisation, readable: NAME_READABLE_ENUM[organisation.name] },
}
},
}
</script>
-
-<style lang="scss" scoped>
-section {
- padding: 10px 10px;
-
- &::v-deep button:disabled {
- cursor: default;
- }
-}
-</style>
diff --git a/apps/settings/src/components/PersonalInfo/OrganisationSection/Organisation.vue b/apps/settings/src/components/PersonalInfo/OrganisationSection/Organisation.vue
deleted file mode 100644
index 4f69d7b6b9a..00000000000
--- a/apps/settings/src/components/PersonalInfo/OrganisationSection/Organisation.vue
+++ /dev/null
@@ -1,175 +0,0 @@
-<!--
- - @copyright 2021, Christopher Ng <chrng8@gmail.com>
- -
- - @author Christopher Ng <chrng8@gmail.com>
- -
- - @license GNU AGPL version 3 or any later version
- -
- - This program is free software: you can redistribute it and/or modify
- - it under the terms of the GNU Affero 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 Affero General Public License for more details.
- -
- - You should have received a copy of the GNU Affero General Public License
- - along with this program. If not, see <http://www.gnu.org/licenses/>.
- -
--->
-
-<template>
- <div class="organisation">
- <input id="organisation"
- type="text"
- :placeholder="t('settings', 'Your organisation')"
- :value="organisation"
- autocapitalize="none"
- autocomplete="on"
- autocorrect="off"
- @input="onOrganisationChange">
-
- <div class="organisation__actions-container">
- <transition name="fade">
- <span v-if="showCheckmarkIcon" class="icon-checkmark" />
- <span v-else-if="showErrorIcon" class="icon-error" />
- </transition>
- </div>
- </div>
-</template>
-
-<script>
-import { showError } from '@nextcloud/dialogs'
-import { emit } from '@nextcloud/event-bus'
-import debounce from 'debounce'
-
-import { ACCOUNT_PROPERTY_ENUM } from '../../../constants/AccountPropertyConstants'
-import { savePrimaryAccountProperty } from '../../../service/PersonalInfo/PersonalInfoService'
-import logger from '../../../logger'
-
-export default {
- name: 'Organisation',
-
- props: {
- organisation: {
- type: String,
- required: true,
- },
- scope: {
- type: String,
- required: true,
- },
- },
-
- data() {
- return {
- initialOrganisation: this.organisation,
- localScope: this.scope,
- showCheckmarkIcon: false,
- showErrorIcon: false,
- }
- },
-
- methods: {
- onOrganisationChange(e) {
- this.$emit('update:organisation', e.target.value)
- this.debounceOrganisationChange(e.target.value.trim())
- },
-
- debounceOrganisationChange: debounce(async function(organisation) {
- await this.updatePrimaryOrganisation(organisation)
- }, 500),
-
- async updatePrimaryOrganisation(organisation) {
- try {
- const responseData = await savePrimaryAccountProperty(ACCOUNT_PROPERTY_ENUM.ORGANISATION, organisation)
- this.handleResponse({
- organisation,
- status: responseData.ocs?.meta?.status,
- })
- } catch (e) {
- this.handleResponse({
- errorMessage: t('settings', 'Unable to update organisation'),
- error: e,
- })
- }
- },
-
- handleResponse({ organisation, status, errorMessage, error }) {
- if (status === 'ok') {
- // Ensure that local state reflects server state
- this.initialOrganisation = organisation
- emit('settings:organisation:updated', organisation)
- this.showCheckmarkIcon = true
- setTimeout(() => { this.showCheckmarkIcon = false }, 2000)
- } else {
- showError(errorMessage)
- logger.error(errorMessage, error)
- this.showErrorIcon = true
- setTimeout(() => { this.showErrorIcon = false }, 2000)
- }
- },
-
- onScopeChange(scope) {
- this.$emit('update:scope', scope)
- },
- },
-}
-</script>
-
-<style lang="scss" scoped>
-.organisation {
- display: grid;
- align-items: center;
-
- input {
- grid-area: 1 / 1;
- width: 100%;
- height: 34px;
- margin: 3px 3px 3px 0;
- padding: 7px 6px;
- color: var(--color-main-text);
- border: 1px solid var(--color-border-dark);
- border-radius: var(--border-radius);
- background-color: var(--color-main-background);
- font-family: var(--font-face);
- cursor: text;
- }
-
- .organisation__actions-container {
- grid-area: 1 / 1;
- justify-self: flex-end;
- height: 30px;
-
- display: flex;
- gap: 0 2px;
- margin-right: 5px;
-
- .icon-checkmark,
- .icon-error {
- height: 30px !important;
- min-height: 30px !important;
- width: 30px !important;
- min-width: 30px !important;
- top: 0;
- right: 0;
- float: none;
- }
- }
-}
-
-.fade-enter,
-.fade-leave-to {
- opacity: 0;
-}
-
-.fade-enter-active {
- transition: opacity 200ms ease-out;
-}
-
-.fade-leave-active {
- transition: opacity 300ms ease-out;
-}
-</style>
diff --git a/apps/settings/src/components/PersonalInfo/ProfileSection/ProfileCheckbox.vue b/apps/settings/src/components/PersonalInfo/ProfileSection/ProfileCheckbox.vue
index da3d509c2f5..0ab9445e1f9 100644
--- a/apps/settings/src/components/PersonalInfo/ProfileSection/ProfileCheckbox.vue
+++ b/apps/settings/src/components/PersonalInfo/ProfileSection/ProfileCheckbox.vue
@@ -37,10 +37,10 @@
import { showError } from '@nextcloud/dialogs'
import { emit } from '@nextcloud/event-bus'
-import { savePrimaryAccountProperty } from '../../../service/PersonalInfo/PersonalInfoService'
-import { validateBoolean } from '../../../utils/validate'
-import { ACCOUNT_PROPERTY_ENUM } from '../../../constants/AccountPropertyConstants'
-import logger from '../../../logger'
+import { savePrimaryAccountProperty } from '../../../service/PersonalInfo/PersonalInfoService.js'
+import { validateBoolean } from '../../../utils/validate.js'
+import { ACCOUNT_PROPERTY_ENUM } from '../../../constants/AccountPropertyConstants.js'
+import logger from '../../../logger.js'
export default {
name: 'ProfileCheckbox',
diff --git a/apps/settings/src/components/PersonalInfo/ProfileSection/ProfileSection.vue b/apps/settings/src/components/PersonalInfo/ProfileSection/ProfileSection.vue
index 0196b3161a7..2f1cc935f22 100644
--- a/apps/settings/src/components/PersonalInfo/ProfileSection/ProfileSection.vue
+++ b/apps/settings/src/components/PersonalInfo/ProfileSection/ProfileSection.vue
@@ -22,7 +22,7 @@
<template>
<section>
- <HeaderBar :account-property="accountProperty" />
+ <HeaderBar :readable="propertyReadable" />
<ProfileCheckbox :profile-enabled.sync="profileEnabled" />
@@ -39,12 +39,12 @@
import { loadState } from '@nextcloud/initial-state'
import { subscribe, unsubscribe } from '@nextcloud/event-bus'
-import EditProfileAnchorLink from './EditProfileAnchorLink'
-import HeaderBar from '../shared/HeaderBar'
-import ProfileCheckbox from './ProfileCheckbox'
-import ProfilePreviewCard from './ProfilePreviewCard'
+import EditProfileAnchorLink from './EditProfileAnchorLink.vue'
+import HeaderBar from '../shared/HeaderBar.vue'
+import ProfileCheckbox from './ProfileCheckbox.vue'
+import ProfilePreviewCard from './ProfilePreviewCard.vue'
-import { ACCOUNT_PROPERTY_READABLE_ENUM } from '../../../constants/AccountPropertyConstants'
+import { ACCOUNT_PROPERTY_READABLE_ENUM } from '../../../constants/AccountPropertyConstants.js'
const {
organisation: { value: organisation },
@@ -65,7 +65,7 @@ export default {
data() {
return {
- accountProperty: ACCOUNT_PROPERTY_READABLE_ENUM.PROFILE_ENABLED,
+ propertyReadable: ACCOUNT_PROPERTY_READABLE_ENUM.PROFILE_ENABLED,
organisation,
displayName,
profileEnabled,
diff --git a/apps/settings/src/components/PersonalInfo/ProfileVisibilitySection/ProfileVisibilitySection.vue b/apps/settings/src/components/PersonalInfo/ProfileVisibilitySection/ProfileVisibilitySection.vue
index 16a46fee969..eab49f11f49 100644
--- a/apps/settings/src/components/PersonalInfo/ProfileVisibilitySection/ProfileVisibilitySection.vue
+++ b/apps/settings/src/components/PersonalInfo/ProfileVisibilitySection/ProfileVisibilitySection.vue
@@ -24,7 +24,7 @@
<!-- TODO remove this inline margin placeholder once the settings layout is updated -->
<section id="profile-visibility"
:style="{ marginLeft }">
- <HeaderBar :account-property="heading" />
+ <HeaderBar :readable="heading" />
<em :class="{ disabled }">
{{ t('settings', 'The more restrictive setting of either visibility or scope is respected on your Profile. For example, if visibility is set to "Show to everyone" and scope is set to "Private", "Private" is respected.') }}
@@ -47,9 +47,9 @@
import { loadState } from '@nextcloud/initial-state'
import { subscribe, unsubscribe } from '@nextcloud/event-bus'
-import HeaderBar from '../shared/HeaderBar'
-import VisibilityDropdown from './VisibilityDropdown'
-import { PROFILE_READABLE_ENUM } from '../../../constants/AccountPropertyConstants'
+import HeaderBar from '../shared/HeaderBar.vue'
+import VisibilityDropdown from './VisibilityDropdown.vue'
+import { PROFILE_READABLE_ENUM } from '../../../constants/AccountPropertyConstants.js'
const { profileConfig } = loadState('settings', 'profileParameters', {})
const { profileEnabled } = loadState('settings', 'personalInfoParameters', false)
diff --git a/apps/settings/src/components/PersonalInfo/ProfileVisibilitySection/VisibilityDropdown.vue b/apps/settings/src/components/PersonalInfo/ProfileVisibilitySection/VisibilityDropdown.vue
index e5251522b22..b148fa97a4d 100644
--- a/apps/settings/src/components/PersonalInfo/ProfileVisibilitySection/VisibilityDropdown.vue
+++ b/apps/settings/src/components/PersonalInfo/ProfileVisibilitySection/VisibilityDropdown.vue
@@ -43,10 +43,9 @@ import { subscribe, unsubscribe } from '@nextcloud/event-bus'
import NcMultiselect from '@nextcloud/vue/dist/Components/NcMultiselect'
-import { saveProfileParameterVisibility } from '../../../service/ProfileService'
-import { validateStringInput } from '../../../utils/validate'
-import { VISIBILITY_PROPERTY_ENUM } from '../../../constants/ProfileConstants'
-import logger from '../../../logger'
+import { saveProfileParameterVisibility } from '../../../service/ProfileService.js'
+import { VISIBILITY_PROPERTY_ENUM } from '../../../constants/ProfileConstants.js'
+import logger from '../../../logger.js'
const { profileEnabled } = loadState('settings', 'personalInfoParameters', false)
@@ -112,7 +111,7 @@ export default {
const { name: visibility } = visibilityObject
this.$emit('update:visibility', visibility)
- if (validateStringInput(visibility)) {
+ if (visibility !== '') {
await this.updateVisibility(visibility)
}
}
diff --git a/apps/settings/src/components/PersonalInfo/RoleSection/RoleSection.vue b/apps/settings/src/components/PersonalInfo/RoleSection.vue
index b3e95bc8153..ab9b9c910fe 100644
--- a/apps/settings/src/components/PersonalInfo/RoleSection/RoleSection.vue
+++ b/apps/settings/src/components/PersonalInfo/RoleSection.vue
@@ -1,9 +1,9 @@
<!--
- - @copyright 2021, Christopher Ng <chrng8@gmail.com>
+ - @copyright 2022 Christopher Ng <chrng8@gmail.com>
-
- @author Christopher Ng <chrng8@gmail.com>
-
- - @license GNU AGPL version 3 or any later version
+ - @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 Affero General Public License as
@@ -12,7 +12,7 @@
-
- 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
+ - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU Affero General Public License for more details.
-
- You should have received a copy of the GNU Affero General Public License
@@ -21,23 +21,16 @@
-->
<template>
- <section>
- <HeaderBar :account-property="accountProperty"
- label-for="role"
- :scope.sync="role.scope" />
-
- <Role :role.sync="role.value"
- :scope.sync="role.scope" />
- </section>
+ <AccountPropertySection v-bind.sync="role"
+ :placeholder="t('settings', 'Your role')" />
</template>
<script>
import { loadState } from '@nextcloud/initial-state'
-import Role from './Role'
-import HeaderBar from '../shared/HeaderBar'
+import AccountPropertySection from './shared/AccountPropertySection.vue'
-import { ACCOUNT_PROPERTY_READABLE_ENUM } from '../../../constants/AccountPropertyConstants'
+import { NAME_READABLE_ENUM } from '../../constants/AccountPropertyConstants.js'
const { role } = loadState('settings', 'personalInfoParameters', {})
@@ -45,25 +38,13 @@ export default {
name: 'RoleSection',
components: {
- Role,
- HeaderBar,
+ AccountPropertySection,
},
data() {
return {
- accountProperty: ACCOUNT_PROPERTY_READABLE_ENUM.ROLE,
- role,
+ role: { ...role, readable: NAME_READABLE_ENUM[role.name] },
}
},
}
</script>
-
-<style lang="scss" scoped>
-section {
- padding: 10px 10px;
-
- &::v-deep button:disabled {
- cursor: default;
- }
-}
-</style>
diff --git a/apps/settings/src/components/PersonalInfo/RoleSection/Role.vue b/apps/settings/src/components/PersonalInfo/RoleSection/Role.vue
deleted file mode 100644
index 4add0d04d0d..00000000000
--- a/apps/settings/src/components/PersonalInfo/RoleSection/Role.vue
+++ /dev/null
@@ -1,175 +0,0 @@
-<!--
- - @copyright 2021, Christopher Ng <chrng8@gmail.com>
- -
- - @author Christopher Ng <chrng8@gmail.com>
- -
- - @license GNU AGPL version 3 or any later version
- -
- - This program is free software: you can redistribute it and/or modify
- - it under the terms of the GNU Affero 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 Affero General Public License for more details.
- -
- - You should have received a copy of the GNU Affero General Public License
- - along with this program. If not, see <http://www.gnu.org/licenses/>.
- -
--->
-
-<template>
- <div class="role">
- <input id="role"
- type="text"
- :placeholder="t('settings', 'Your role')"
- :value="role"
- autocapitalize="none"
- autocomplete="on"
- autocorrect="off"
- @input="onRoleChange">
-
- <div class="role__actions-container">
- <transition name="fade">
- <span v-if="showCheckmarkIcon" class="icon-checkmark" />
- <span v-else-if="showErrorIcon" class="icon-error" />
- </transition>
- </div>
- </div>
-</template>
-
-<script>
-import { showError } from '@nextcloud/dialogs'
-import { emit } from '@nextcloud/event-bus'
-import debounce from 'debounce'
-
-import { ACCOUNT_PROPERTY_ENUM } from '../../../constants/AccountPropertyConstants'
-import { savePrimaryAccountProperty } from '../../../service/PersonalInfo/PersonalInfoService'
-import logger from '../../../logger'
-
-export default {
- name: 'Role',
-
- props: {
- role: {
- type: String,
- required: true,
- },
- scope: {
- type: String,
- required: true,
- },
- },
-
- data() {
- return {
- initialRole: this.role,
- localScope: this.scope,
- showCheckmarkIcon: false,
- showErrorIcon: false,
- }
- },
-
- methods: {
- onRoleChange(e) {
- this.$emit('update:role', e.target.value)
- this.debounceRoleChange(e.target.value.trim())
- },
-
- debounceRoleChange: debounce(async function(role) {
- await this.updatePrimaryRole(role)
- }, 500),
-
- async updatePrimaryRole(role) {
- try {
- const responseData = await savePrimaryAccountProperty(ACCOUNT_PROPERTY_ENUM.ROLE, role)
- this.handleResponse({
- role,
- status: responseData.ocs?.meta?.status,
- })
- } catch (e) {
- this.handleResponse({
- errorMessage: t('settings', 'Unable to update role'),
- error: e,
- })
- }
- },
-
- handleResponse({ role, status, errorMessage, error }) {
- if (status === 'ok') {
- // Ensure that local state reflects server state
- this.initialRole = role
- emit('settings:role:updated', role)
- this.showCheckmarkIcon = true
- setTimeout(() => { this.showCheckmarkIcon = false }, 2000)
- } else {
- showError(errorMessage)
- logger.error(errorMessage, error)
- this.showErrorIcon = true
- setTimeout(() => { this.showErrorIcon = false }, 2000)
- }
- },
-
- onScopeChange(scope) {
- this.$emit('update:scope', scope)
- },
- },
-}
-</script>
-
-<style lang="scss" scoped>
-.role {
- display: grid;
- align-items: center;
-
- input {
- grid-area: 1 / 1;
- width: 100%;
- height: 34px;
- margin: 3px 3px 3px 0;
- padding: 7px 6px;
- color: var(--color-main-text);
- border: 1px solid var(--color-border-dark);
- border-radius: var(--border-radius);
- background-color: var(--color-main-background);
- font-family: var(--font-face);
- cursor: text;
- }
-
- .role__actions-container {
- grid-area: 1 / 1;
- justify-self: flex-end;
- height: 30px;
-
- display: flex;
- gap: 0 2px;
- margin-right: 5px;
-
- .icon-checkmark,
- .icon-error {
- height: 30px !important;
- min-height: 30px !important;
- width: 30px !important;
- min-width: 30px !important;
- top: 0;
- right: 0;
- float: none;
- }
- }
-}
-
-.fade-enter,
-.fade-leave-to {
- opacity: 0;
-}
-
-.fade-enter-active {
- transition: opacity 200ms ease-out;
-}
-
-.fade-leave-active {
- transition: opacity 300ms ease-out;
-}
-</style>
diff --git a/apps/settings/src/components/PersonalInfo/shared/AccountPropertySection.vue b/apps/settings/src/components/PersonalInfo/shared/AccountPropertySection.vue
new file mode 100644
index 00000000000..351af504682
--- /dev/null
+++ b/apps/settings/src/components/PersonalInfo/shared/AccountPropertySection.vue
@@ -0,0 +1,265 @@
+<!--
+ - @copyright 2022 Christopher Ng <chrng8@gmail.com>
+ -
+ - @author Christopher Ng <chrng8@gmail.com>
+ -
+ - @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 Affero 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 Affero General Public License for more details.
+ -
+ - You should have received a copy of the GNU Affero General Public License
+ - along with this program. If not, see <http://www.gnu.org/licenses/>.
+ -
+-->
+
+<template>
+ <section>
+ <HeaderBar :scope.sync="scope"
+ :readable.sync="readable"
+ :input-id="inputId"
+ :is-editable="isEditable" />
+
+ <div v-if="isEditable" class="property">
+ <textarea v-if="multiLine"
+ :id="inputId"
+ :placeholder="placeholder"
+ :value="value"
+ rows="8"
+ autocapitalize="none"
+ autocomplete="off"
+ autocorrect="off"
+ @input="onPropertyChange" />
+ <input v-else
+ :id="inputId"
+ :placeholder="placeholder"
+ :type="type"
+ :value="value"
+ autocapitalize="none"
+ autocomplete="on"
+ autocorrect="off"
+ @input="onPropertyChange">
+
+ <div class="property__actions-container">
+ <transition name="fade">
+ <Check v-if="showCheckmarkIcon" :size="20" />
+ <AlertOctagon v-else-if="showErrorIcon" :size="20" />
+ </transition>
+ </div>
+ </div>
+ <span v-else>
+ {{ value || t('settings', 'No {property} set', { property: readable.toLocaleLowerCase() }) }}
+ </span>
+ </section>
+</template>
+
+<script>
+import debounce from 'debounce'
+import { showError } from '@nextcloud/dialogs'
+
+import Check from 'vue-material-design-icons/Check'
+import AlertOctagon from 'vue-material-design-icons/AlertOctagon'
+
+import HeaderBar from '../shared/HeaderBar.vue'
+
+import { savePrimaryAccountProperty } from '../../../service/PersonalInfo/PersonalInfoService.js'
+import logger from '../../../logger.js'
+
+export default {
+ name: 'AccountPropertySection',
+
+ components: {
+ AlertOctagon,
+ Check,
+ HeaderBar,
+ },
+
+ props: {
+ name: {
+ type: String,
+ required: true,
+ },
+ value: {
+ type: String,
+ required: true,
+ },
+ scope: {
+ type: String,
+ required: true,
+ },
+ readable: {
+ type: String,
+ required: true,
+ },
+ placeholder: {
+ type: String,
+ required: true,
+ },
+ type: {
+ type: String,
+ default: 'text',
+ },
+ isEditable: {
+ type: Boolean,
+ default: true,
+ },
+ multiLine: {
+ type: Boolean,
+ default: false,
+ },
+ onValidate: {
+ type: Function,
+ default: null,
+ },
+ onSave: {
+ type: Function,
+ default: null,
+ },
+ },
+
+ data() {
+ return {
+ initialValue: this.value,
+ showCheckmarkIcon: false,
+ showErrorIcon: false,
+ }
+ },
+
+ computed: {
+ inputId() {
+ return `account-property-${this.name}`
+ },
+ },
+
+ methods: {
+ onPropertyChange(e) {
+ this.$emit('update:value', e.target.value)
+ this.debouncePropertyChange(e.target.value.trim())
+ },
+
+ debouncePropertyChange: debounce(async function(value) {
+ if (this.onValidate && !this.onValidate(value)) {
+ return
+ }
+ await this.updateProperty(value)
+ }, 500),
+
+ async updateProperty(value) {
+ try {
+ const responseData = await savePrimaryAccountProperty(
+ this.name,
+ value,
+ )
+ this.handleResponse({
+ value,
+ status: responseData.ocs?.meta?.status,
+ })
+ } catch (e) {
+ this.handleResponse({
+ errorMessage: t('settings', 'Unable to update {property}', { property: this.readable.toLocaleLowerCase() }),
+ error: e,
+ })
+ }
+ },
+
+ handleResponse({ value, status, errorMessage, error }) {
+ if (status === 'ok') {
+ this.initialValue = value
+ if (this.onSave) {
+ this.onSave(value)
+ }
+ this.showCheckmarkIcon = true
+ setTimeout(() => { this.showCheckmarkIcon = false }, 2000)
+ } else {
+ this.$emit('update:value', this.initialValue)
+ showError(errorMessage)
+ logger.error(errorMessage, error)
+ this.showErrorIcon = true
+ setTimeout(() => { this.showErrorIcon = false }, 2000)
+ }
+ },
+ },
+}
+</script>
+
+<style lang="scss" scoped>
+section {
+ padding: 10px 10px;
+
+ &::v-deep button:disabled {
+ cursor: default;
+ }
+
+ .property {
+ display: grid;
+ align-items: center;
+
+ textarea {
+ resize: vertical;
+ grid-area: 1 / 1;
+ width: 100%;
+ margin: 3px 3px 3px 0;
+ padding: 7px 6px;
+ color: var(--color-main-text);
+ border: 1px solid var(--color-border-dark);
+ border-radius: var(--border-radius);
+ background-color: var(--color-main-background);
+ font-family: var(--font-face);
+ cursor: text;
+
+ &:hover,
+ &:focus,
+ &:active {
+ border-color: var(--color-primary-element) !important;
+ outline: none !important;
+ }
+ }
+
+ input {
+ grid-area: 1 / 1;
+ width: 100%;
+ height: 34px;
+ margin: 3px 3px 3px 0;
+ padding: 7px 6px;
+ color: var(--color-main-text);
+ border: 1px solid var(--color-border-dark);
+ border-radius: var(--border-radius);
+ background-color: var(--color-main-background);
+ font-family: var(--font-face);
+ cursor: text;
+ }
+
+ .property__actions-container {
+ grid-area: 1 / 1;
+ justify-self: flex-end;
+ align-self: flex-end;
+ height: 30px;
+
+ display: flex;
+ gap: 0 2px;
+ margin-right: 5px;
+ margin-bottom: 5px;
+ }
+ }
+
+ .fade-enter,
+ .fade-leave-to {
+ opacity: 0;
+ }
+
+ .fade-enter-active {
+ transition: opacity 200ms ease-out;
+ }
+
+ .fade-leave-active {
+ transition: opacity 300ms ease-out;
+ }
+}
+</style>
diff --git a/apps/settings/src/components/PersonalInfo/shared/FederationControl.vue b/apps/settings/src/components/PersonalInfo/shared/FederationControl.vue
index af2b9670ed1..555b917ad1f 100644
--- a/apps/settings/src/components/PersonalInfo/shared/FederationControl.vue
+++ b/apps/settings/src/components/PersonalInfo/shared/FederationControl.vue
@@ -43,17 +43,19 @@ import NcActions from '@nextcloud/vue/dist/Components/NcActions'
import { loadState } from '@nextcloud/initial-state'
import { showError } from '@nextcloud/dialogs'
-import FederationControlAction from './FederationControlAction'
+import FederationControlAction from './FederationControlAction.vue'
import {
ACCOUNT_PROPERTY_READABLE_ENUM,
+ ACCOUNT_SETTING_PROPERTY_READABLE_ENUM,
+ PROFILE_READABLE_ENUM,
PROPERTY_READABLE_KEYS_ENUM,
PROPERTY_READABLE_SUPPORTED_SCOPES_ENUM,
SCOPE_ENUM, SCOPE_PROPERTY_ENUM,
UNPUBLISHED_READABLE_PROPERTIES,
-} from '../../../constants/AccountPropertyConstants'
-import { savePrimaryAccountPropertyScope } from '../../../service/PersonalInfo/PersonalInfoService'
-import logger from '../../../logger'
+} from '../../../constants/AccountPropertyConstants.js'
+import { savePrimaryAccountPropertyScope } from '../../../service/PersonalInfo/PersonalInfoService.js'
+import logger from '../../../logger.js'
const { lookupServerUploadEnabled } = loadState('settings', 'accountParameters', {})
@@ -66,10 +68,10 @@ export default {
},
props: {
- accountProperty: {
+ readable: {
type: String,
required: true,
- validator: (value) => Object.values(ACCOUNT_PROPERTY_READABLE_ENUM).includes(value),
+ validator: (value) => Object.values(ACCOUNT_PROPERTY_READABLE_ENUM).includes(value) || Object.values(ACCOUNT_SETTING_PROPERTY_READABLE_ENUM).includes(value) || value === PROFILE_READABLE_ENUM.PROFILE_VISIBILITY,
},
additional: {
type: Boolean,
@@ -95,14 +97,14 @@ export default {
data() {
return {
- accountPropertyLowerCase: this.accountProperty.toLocaleLowerCase(),
+ readableLowerCase: this.readable.toLocaleLowerCase(),
initialScope: this.scope,
}
},
computed: {
ariaLabel() {
- return t('settings', 'Change scope level of {accountProperty}, current scope is {scope}', { accountProperty: this.accountPropertyLowerCase, scope: this.scopeDisplayNameLowerCase })
+ return t('settings', 'Change scope level of {property}, current scope is {scope}', { property: this.readableLowerCase, scope: this.scopeDisplayNameLowerCase })
},
scopeDisplayNameLowerCase() {
@@ -118,15 +120,15 @@ export default {
},
supportedScopes() {
- if (lookupServerUploadEnabled && !UNPUBLISHED_READABLE_PROPERTIES.includes(this.accountProperty)) {
+ if (lookupServerUploadEnabled && !UNPUBLISHED_READABLE_PROPERTIES.includes(this.readable)) {
return [
- ...PROPERTY_READABLE_SUPPORTED_SCOPES_ENUM[this.accountProperty],
+ ...PROPERTY_READABLE_SUPPORTED_SCOPES_ENUM[this.readable],
SCOPE_ENUM.FEDERATED,
SCOPE_ENUM.PUBLISHED,
]
}
- return PROPERTY_READABLE_SUPPORTED_SCOPES_ENUM[this.accountProperty]
+ return PROPERTY_READABLE_SUPPORTED_SCOPES_ENUM[this.readable]
},
},
@@ -143,14 +145,14 @@ export default {
async updatePrimaryScope(scope) {
try {
- const responseData = await savePrimaryAccountPropertyScope(PROPERTY_READABLE_KEYS_ENUM[this.accountProperty], scope)
+ const responseData = await savePrimaryAccountPropertyScope(PROPERTY_READABLE_KEYS_ENUM[this.readable], scope)
this.handleResponse({
scope,
status: responseData.ocs?.meta?.status,
})
} catch (e) {
this.handleResponse({
- errorMessage: t('settings', 'Unable to update federation scope of the primary {accountProperty}', { accountProperty: this.accountPropertyLowerCase }),
+ errorMessage: t('settings', 'Unable to update federation scope of the primary {property}', { property: this.readableLowerCase }),
error: e,
})
}
@@ -165,7 +167,7 @@ export default {
})
} catch (e) {
this.handleResponse({
- errorMessage: t('settings', 'Unable to update federation scope of additional {accountProperty}', { accountProperty: this.accountPropertyLowerCase }),
+ errorMessage: t('settings', 'Unable to update federation scope of additional {property}', { property: this.readableLowerCase }),
error: e,
})
}
diff --git a/apps/settings/src/components/PersonalInfo/shared/HeaderBar.vue b/apps/settings/src/components/PersonalInfo/shared/HeaderBar.vue
index f353e673b81..bd6cc437928 100644
--- a/apps/settings/src/components/PersonalInfo/shared/HeaderBar.vue
+++ b/apps/settings/src/components/PersonalInfo/shared/HeaderBar.vue
@@ -22,14 +22,14 @@
<template>
<h3 :class="{ 'setting-property': isSettingProperty, 'profile-property': isProfileProperty }">
- <label :for="labelFor">
+ <label :for="inputId">
<!-- Already translated as required by prop validator -->
- {{ accountProperty }}
+ {{ readable }}
</label>
<template v-if="scope">
<FederationControl class="federation-control"
- :account-property="accountProperty"
+ :readable="readable"
:scope.sync="localScope"
@update:scope="onScopeChange" />
</template>
@@ -49,10 +49,16 @@
</template>
<script>
-import FederationControl from './FederationControl'
import NcButton from '@nextcloud/vue/dist/Components/NcButton'
import Plus from 'vue-material-design-icons/Plus'
-import { ACCOUNT_PROPERTY_READABLE_ENUM, ACCOUNT_SETTING_PROPERTY_READABLE_ENUM, PROFILE_READABLE_ENUM } from '../../../constants/AccountPropertyConstants'
+
+import FederationControl from './FederationControl.vue'
+
+import {
+ ACCOUNT_PROPERTY_READABLE_ENUM,
+ ACCOUNT_SETTING_PROPERTY_READABLE_ENUM,
+ PROFILE_READABLE_ENUM,
+} from '../../../constants/AccountPropertyConstants.js'
export default {
name: 'HeaderBar',
@@ -64,11 +70,19 @@ export default {
},
props: {
- accountProperty: {
+ scope: {
+ type: String,
+ default: null,
+ },
+ readable: {
type: String,
required: true,
validator: (value) => Object.values(ACCOUNT_PROPERTY_READABLE_ENUM).includes(value) || Object.values(ACCOUNT_SETTING_PROPERTY_READABLE_ENUM).includes(value) || value === PROFILE_READABLE_ENUM.PROFILE_VISIBILITY,
},
+ inputId: {
+ type: String,
+ default: null,
+ },
isEditable: {
type: Boolean,
default: true,
@@ -79,15 +93,7 @@ export default {
},
isValidSection: {
type: Boolean,
- default: false,
- },
- labelFor: {
- type: String,
- default: '',
- },
- scope: {
- type: String,
- default: null,
+ default: true,
},
},
@@ -99,11 +105,11 @@ export default {
computed: {
isProfileProperty() {
- return this.accountProperty === ACCOUNT_PROPERTY_READABLE_ENUM.PROFILE_ENABLED
+ return this.readable === ACCOUNT_PROPERTY_READABLE_ENUM.PROFILE_ENABLED
},
isSettingProperty() {
- return Object.values(ACCOUNT_SETTING_PROPERTY_READABLE_ENUM).includes(this.accountProperty)
+ return Object.values(ACCOUNT_SETTING_PROPERTY_READABLE_ENUM).includes(this.readable)
},
},
diff --git a/apps/settings/src/constants/AccountPropertyConstants.js b/apps/settings/src/constants/AccountPropertyConstants.js
index 941e20a912a..17debe27c55 100644
--- a/apps/settings/src/constants/AccountPropertyConstants.js
+++ b/apps/settings/src/constants/AccountPropertyConstants.js
@@ -61,6 +61,22 @@ export const ACCOUNT_PROPERTY_READABLE_ENUM = Object.freeze({
WEBSITE: t('settings', 'Website'),
})
+export const NAME_READABLE_ENUM = Object.freeze({
+ [ACCOUNT_PROPERTY_ENUM.ADDRESS]: ACCOUNT_PROPERTY_READABLE_ENUM.ADDRESS,
+ [ACCOUNT_PROPERTY_ENUM.AVATAR]: ACCOUNT_PROPERTY_READABLE_ENUM.AVATAR,
+ [ACCOUNT_PROPERTY_ENUM.BIOGRAPHY]: ACCOUNT_PROPERTY_READABLE_ENUM.BIOGRAPHY,
+ [ACCOUNT_PROPERTY_ENUM.DISPLAYNAME]: ACCOUNT_PROPERTY_READABLE_ENUM.DISPLAYNAME,
+ [ACCOUNT_PROPERTY_ENUM.EMAIL_COLLECTION]: ACCOUNT_PROPERTY_READABLE_ENUM.EMAIL_COLLECTION,
+ [ACCOUNT_PROPERTY_ENUM.EMAIL]: ACCOUNT_PROPERTY_READABLE_ENUM.EMAIL,
+ [ACCOUNT_PROPERTY_ENUM.HEADLINE]: ACCOUNT_PROPERTY_READABLE_ENUM.HEADLINE,
+ [ACCOUNT_PROPERTY_ENUM.ORGANISATION]: ACCOUNT_PROPERTY_READABLE_ENUM.ORGANISATION,
+ [ACCOUNT_PROPERTY_ENUM.PHONE]: ACCOUNT_PROPERTY_READABLE_ENUM.PHONE,
+ [ACCOUNT_PROPERTY_ENUM.PROFILE_ENABLED]: ACCOUNT_PROPERTY_READABLE_ENUM.PROFILE_ENABLED,
+ [ACCOUNT_PROPERTY_ENUM.ROLE]: ACCOUNT_PROPERTY_READABLE_ENUM.ROLE,
+ [ACCOUNT_PROPERTY_ENUM.TWITTER]: ACCOUNT_PROPERTY_READABLE_ENUM.TWITTER,
+ [ACCOUNT_PROPERTY_ENUM.WEBSITE]: ACCOUNT_PROPERTY_READABLE_ENUM.WEBSITE,
+})
+
/** Enum of profile specific sections to human readable names */
export const PROFILE_READABLE_ENUM = Object.freeze({
PROFILE_VISIBILITY: t('settings', 'Profile visibility'),
diff --git a/apps/settings/src/main-personal-info.js b/apps/settings/src/main-personal-info.js
index d3cfd3ec9cc..b133604a6ac 100644
--- a/apps/settings/src/main-personal-info.js
+++ b/apps/settings/src/main-personal-info.js
@@ -26,15 +26,15 @@ import { loadState } from '@nextcloud/initial-state'
import { translate as t } from '@nextcloud/l10n'
import '@nextcloud/dialogs/styles/toast.scss'
-import DisplayNameSection from './components/PersonalInfo/DisplayNameSection/DisplayNameSection'
-import EmailSection from './components/PersonalInfo/EmailSection/EmailSection'
-import LanguageSection from './components/PersonalInfo/LanguageSection/LanguageSection'
-import ProfileSection from './components/PersonalInfo/ProfileSection/ProfileSection'
-import OrganisationSection from './components/PersonalInfo/OrganisationSection/OrganisationSection'
-import RoleSection from './components/PersonalInfo/RoleSection/RoleSection'
-import HeadlineSection from './components/PersonalInfo/HeadlineSection/HeadlineSection'
-import BiographySection from './components/PersonalInfo/BiographySection/BiographySection'
-import ProfileVisibilitySection from './components/PersonalInfo/ProfileVisibilitySection/ProfileVisibilitySection'
+import DisplayNameSection from './components/PersonalInfo/DisplayNameSection.vue'
+import EmailSection from './components/PersonalInfo/EmailSection/EmailSection.vue'
+import LanguageSection from './components/PersonalInfo/LanguageSection/LanguageSection.vue'
+import ProfileSection from './components/PersonalInfo/ProfileSection/ProfileSection.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 ProfileVisibilitySection from './components/PersonalInfo/ProfileVisibilitySection/ProfileVisibilitySection.vue'
__webpack_nonce__ = btoa(getRequestToken())
diff --git a/apps/settings/src/utils/validate.js b/apps/settings/src/utils/validate.js
index 58d42863f4e..83af1d94fbb 100644
--- a/apps/settings/src/utils/validate.js
+++ b/apps/settings/src/utils/validate.js
@@ -29,18 +29,6 @@
import { VALIDATE_EMAIL_REGEX } from '../constants/AccountPropertyConstants'
/**
- * Validate the string input
- *
- * Generic validator just to check that input is not an empty string*
- *
- * @param {string} input the input
- * @return {boolean}
- */
-export function validateStringInput(input) {
- return input !== ''
-}
-
-/**
* Validate the email input
*
* Compliant with PHP core FILTER_VALIDATE_EMAIL validator*