aboutsummaryrefslogtreecommitdiffstats
path: root/apps/settings/src/components/PersonalInfo/shared/AccountPropertySection.vue
diff options
context:
space:
mode:
Diffstat (limited to 'apps/settings/src/components/PersonalInfo/shared/AccountPropertySection.vue')
-rw-r--r--apps/settings/src/components/PersonalInfo/shared/AccountPropertySection.vue171
1 files changed, 69 insertions, 102 deletions
diff --git a/apps/settings/src/components/PersonalInfo/shared/AccountPropertySection.vue b/apps/settings/src/components/PersonalInfo/shared/AccountPropertySection.vue
index c9b74eeb3f4..d039641ec72 100644
--- a/apps/settings/src/components/PersonalInfo/shared/AccountPropertySection.vue
+++ b/apps/settings/src/components/PersonalInfo/shared/AccountPropertySection.vue
@@ -1,94 +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/>.
- -
+ - SPDX-FileCopyrightText: 2022 Nextcloud GmbH and Nextcloud contributors
+ - SPDX-License-Identifier: AGPL-3.0-or-later
-->
<template>
<section>
- <HeaderBar :scope.sync="scope"
- :readable.sync="readable"
+ <HeaderBar :scope="scope"
+ :readable="readable"
:input-id="inputId"
- :is-editable="isEditable" />
+ :is-editable="isEditable"
+ @update:scope="(scope) => $emit('update:scope', scope)" />
<div v-if="isEditable" class="property">
- <textarea v-if="multiLine"
+ <NcTextArea v-if="multiLine"
:id="inputId"
- :placeholder="placeholder"
- :value="value"
- rows="8"
autocapitalize="none"
autocomplete="off"
+ :error="hasError || !!helperText"
+ :helper-text="helperText"
+ label-outside
+ :placeholder="placeholder"
+ rows="8"
spellcheck="false"
- @input="onPropertyChange" />
- <input v-else
+ :success="isSuccess"
+ :value.sync="inputValue" />
+ <NcInputField v-else
:id="inputId"
ref="input"
- :placeholder="placeholder"
- :type="type"
- :value="value"
- :aria-describedby="helperText ? `${name}-helper-text` : undefined"
autocapitalize="none"
- spellcheck="false"
:autocomplete="autocomplete"
- @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>
+ :error="hasError || !!helperText"
+ :helper-text="helperText"
+ label-outside
+ :placeholder="placeholder"
+ spellcheck="false"
+ :success="isSuccess"
+ :type="type"
+ :value.sync="inputValue" />
</div>
<span v-else>
{{ value || t('settings', 'No {property} set', { property: readable.toLocaleLowerCase() }) }}
</span>
-
- <p v-if="helperText"
- :id="`${name}-helper-text`"
- class="property__helper-text-message property__helper-text-message--error">
- <AlertCircle class="property__helper-text-message__icon" :size="18" />
- {{ helperText }}
- </p>
</section>
</template>
<script>
import debounce from 'debounce'
+import NcInputField from '@nextcloud/vue/components/NcInputField'
+import NcTextArea from '@nextcloud/vue/components/NcTextArea'
-import AlertCircle from 'vue-material-design-icons/AlertCircleOutline.vue'
-import AlertOctagon from 'vue-material-design-icons/AlertOctagon.vue'
-import Check from 'vue-material-design-icons/Check.vue'
-
-import HeaderBar from '../shared/HeaderBar.vue'
+import HeaderBar from './HeaderBar.vue'
import { savePrimaryAccountProperty } from '../../../service/PersonalInfo/PersonalInfoService.js'
-import { handleError } from '../../../utils/handlers.js'
+import { handleError } from '../../../utils/handlers.ts'
export default {
name: 'AccountPropertySection',
components: {
- AlertCircle,
- AlertOctagon,
- Check,
HeaderBar,
+ NcInputField,
+ NcTextArea,
},
props: {
@@ -138,12 +110,14 @@ export default {
},
},
+ emits: ['update:scope', 'update:value'],
+
data() {
return {
initialValue: this.value,
- helperText: null,
- showCheckmarkIcon: false,
- showErrorIcon: false,
+ helperText: '',
+ isSuccess: false,
+ hasError: false,
}
},
@@ -151,28 +125,37 @@ export default {
inputId() {
return `account-property-${this.name}`
},
- },
- methods: {
- onPropertyChange(e) {
- this.$emit('update:value', e.target.value)
- this.debouncePropertyChange(e.target.value.trim())
+ inputValue: {
+ get() {
+ return this.value
+ },
+ set(value) {
+ this.$emit('update:value', value)
+ this.debouncePropertyChange(value.trim())
+ },
},
- debouncePropertyChange: debounce(async function(value) {
- this.helperText = null
- if (this.$refs.input && this.$refs.input.validationMessage) {
- this.helperText = this.$refs.input.validationMessage
- return
- }
- if (this.onValidate && !this.onValidate(value)) {
- return
- }
- await this.updateProperty(value)
- }, 500),
+ debouncePropertyChange() {
+ return debounce(async function(value) {
+ this.helperText = this.$refs.input?.$refs.input?.validationMessage || ''
+ if (this.helperText !== '') {
+ return
+ }
+ this.hasError = this.onValidate && !this.onValidate(value)
+ if (this.hasError) {
+ this.helperText = t('settings', 'Invalid value')
+ return
+ }
+ await this.updateProperty(value)
+ }, 1000)
+ },
+ },
+ methods: {
async updateProperty(value) {
try {
+ this.hasError = false
const responseData = await savePrimaryAccountProperty(
this.name,
value,
@@ -195,13 +178,11 @@ export default {
if (this.onSave) {
this.onSave(value)
}
- this.showCheckmarkIcon = true
- setTimeout(() => { this.showCheckmarkIcon = false }, 2000)
+ this.isSuccess = true
+ setTimeout(() => { this.isSuccess = false }, 2000)
} else {
- this.$emit('update:value', this.initialValue)
handleError(error, errorMessage)
- this.showErrorIcon = true
- setTimeout(() => { this.showErrorIcon = false }, 2000)
+ this.hasError = true
}
},
},
@@ -212,34 +193,20 @@ export default {
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%;
- }
-
- input {
- grid-area: 1 / 1;
- width: 100%;
- }
+ display: flex;
+ flex-direction: row;
+ align-items: start;
+ gap: 4px;
.property__actions-container {
- grid-area: 1 / 1;
+ margin-top: 6px;
justify-self: flex-end;
align-self: flex-end;
- height: 30px;
display: flex;
gap: 0 2px;
- margin-right: 5px;
+ margin-inline-end: 5px;
margin-bottom: 5px;
}
}
@@ -250,7 +217,7 @@ section {
align-items: center;
&__icon {
- margin-right: 8px;
+ margin-inline-end: 8px;
align-self: start;
margin-top: 4px;
}