split admin settings in 2 components, get ready for multiple approval settings

Signed-off-by: Julien Veyssier <eneiluj@posteo.net>
This commit is contained in:
Julien Veyssier 2021-03-15 18:43:27 +01:00
Родитель bf6fac8e04
Коммит 91b3a491d2
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 4141FEE162030638
2 изменённых файлов: 236 добавлений и 195 удалений

Просмотреть файл

@ -7,83 +7,10 @@
<p class="settings-hint">
{{ t('approval', '') }}
</p>
<div class="approval-user">
<label for="user">
<span class="icon icon-user" />
{{ t('approval', 'User') }}
</label>
<Multiselect
class="approval-user-input"
label="displayName"
:clear-on-select="true"
:hide-selected="false"
:internal-search="false"
:loading="loadingUsers"
:options="formattedSuggestions"
:placeholder="t('welcome', 'Who can approve?')"
:preselect-first="false"
:preserve-search="false"
:searchable="true"
:user-select="true"
@search-change="asyncFind"
@select="supportContactSelected">
<template #option="{option}">
<Avatar
class="approval-avatar-option"
:user="option.user"
:show-user-status="false" />
<span>
{{ option.displayName }}
</span>
</template>
<template #noOptions>
{{ t('welcome', 'No recommendations. Start typing.') }}
</template>
<template #noResult>
{{ t('welcome', 'No result.') }}
</template>
</Multiselect>
<div v-if="state.user_name && state.user_id"
class="selected-user">
<Avatar
:size="20"
:user="state.user_id"
:tooltip-message="state.user_id"
:show-user-status="false" />
<span>
{{ state.user_name }}
</span>
</div>
</div>
<div class="grid-form">
<label for="pending">
<span class="icon" :style="'background-image: url(' + tagPendingIconUrl + ');'" />
{{ t('approval', 'Pending tag') }}
</label>
<MultiselectTags id="pending"
v-model="state.tag_pending"
:label="t('approval', 'Select pending tag')"
:multiple="false"
@input="onTagInput" />
<label for="approved">
<span class="icon" :style="'background-image: url(' + tagApprovedIconUrl + ');'" />
{{ t('approval', 'Approved tag') }}
</label>
<MultiselectTags id="approved"
v-model="state.tag_approved"
:label="t('approval', 'Select approved tag')"
:multiple="false"
@input="onTagInput" />
<label for="rejected">
<span class="icon" :style="'background-image: url(' + tagRejectedIconUrl + ');'" />
{{ t('approval', 'Rejected tag') }}
</label>
<MultiselectTags id="rejected"
v-model="state.tag_rejected"
:label="t('approval', 'Select rejected tag')"
:multiple="false"
@input="onTagInput" />
</div>
<ApprovalSetting v-for="(setting, id) in settings"
:key="id"
v-model="settings[id]"
@input="onSettingInput(id, $event)" />
<div class="create-tag">
<label for="create-tag-input">
<span class="icon icon-tag" />
@ -104,22 +31,18 @@
<script>
import { loadState } from '@nextcloud/initial-state'
import { generateUrl, generateOcsUrl } from '@nextcloud/router'
import { getCurrentUser } from '@nextcloud/auth'
import { generateUrl } from '@nextcloud/router'
import axios from '@nextcloud/axios'
import { showSuccess, showError } from '@nextcloud/dialogs'
import '@nextcloud/dialogs/styles/toast.scss'
import Avatar from '@nextcloud/vue/dist/Components/Avatar'
import Multiselect from '@nextcloud/vue/dist/Components/Multiselect'
import MultiselectTags from '@nextcloud/vue/dist/Components/MultiselectTags'
import ApprovalSetting from './ApprovalSetting'
export default {
name: 'AdminSettings',
components: {
Avatar,
Multiselect,
MultiselectTags,
ApprovalSetting,
},
props: [],
@ -127,59 +50,49 @@ export default {
data() {
return {
state: loadState('approval', 'admin-config'),
tagPendingIconUrl: generateUrl('/svg/core/actions/tag?color=0082c9'),
tagApprovedIconUrl: generateUrl('/svg/core/actions/tag?color=46ba61'),
tagRejectedIconUrl: generateUrl('/svg/core/actions/tag?color=e9322d'),
loadingUsers: false,
suggestions: [],
query: '',
currentUser: getCurrentUser(),
newTagName: '',
settings: {},
}
},
computed: {
formattedSuggestions() {
const result = this.suggestions.map((s) => {
return {
user: s.id,
displayName: s.label,
icon: 'icon-user',
multiselectKey: s.id + s.label,
}
})
if (this.currentUser) {
const lowerCurrent = this.currentUser.displayName.toLowerCase()
const lowerQuery = this.query.toLowerCase()
if (this.query === '' || lowerCurrent.match(lowerQuery)) {
result.push({
user: this.currentUser.uid,
displayName: this.currentUser.displayName,
icon: 'icon-user',
multiselectKey: this.currentUser.uid + this.currentUser.displayName,
})
}
}
return result
},
},
watch: {
},
mounted() {
// TODO correctly load multiple values from state
this.settings = {
33: {
tagPending: this.state.tag_pending,
tagApproved: this.state.tag_approved,
tagRejected: this.state.tag_rejected,
users: this.state.user_id
? [
{
user: this.state.user_id,
displayName: this.state.user_name,
},
]
: [],
},
}
},
methods: {
onTagInput() {
if (this.state.tag_pending && this.state.tag_approved && this.state.tag_rejected) {
const values = {
tag_pending: this.state.tag_pending,
tag_approved: this.state.tag_approved,
tag_rejected: this.state.tag_rejected,
}
this.saveOptions(values)
}
onSettingInput(id, setting) {
console.debug('INPUTTUTUTU ' + id)
console.debug(setting)
console.debug(this.settings)
// TODO correctly save values, send setting ID etc...
this.saveOptions({
tag_pending: setting.tagPending,
tag_approved: setting.tagApproved,
tag_rejected: setting.tagRejected,
user_id: setting.users[0]?.user || '',
user_name: setting.users[0]?.displayName || '',
})
},
saveOptions(values) {
const req = {
@ -197,41 +110,6 @@ export default {
}).then(() => {
})
},
asyncFind(query) {
this.query = query
if (query === '') {
this.suggestions = []
return
}
this.loadingUsers = true
console.debug(query)
const url = generateOcsUrl('core/autocomplete/get', 2).replace(/\/$/, '')
axios.get(url, {
params: {
format: 'json',
search: query,
itemType: ' ',
itemId: ' ',
shareTypes: [],
},
}).then((response) => {
console.debug(response)
this.suggestions = response.data.ocs.data
}).catch((error) => {
console.error(error)
}).then(() => {
this.loadingUsers = false
})
},
supportContactSelected(user) {
console.debug(user)
this.state.user_id = user.user
this.state.user_name = user.displayName
this.saveOptions({
user_id: this.state.user_id,
user_name: this.state.user_name,
})
},
onCreateTag() {
if (this.newTagName) {
const req = {
@ -257,48 +135,16 @@ export default {
</script>
<style scoped lang="scss">
::v-deep .multiselect__input {
height: 34px !important;
}
#approval_prefs {
.icon {
display: inline-block;
width: 32px;
}
.approval-user {
margin-left: 30px;
display: flex;
> label {
width: 250px;
}
.selected-user {
display: flex;
align-items: center;
* {
margin-left: 5px;
}
}
}
.grid-form {
max-width: 500px;
display: grid;
grid-template: 1fr / 1fr 1fr;
margin-left: 30px;
.icon {
width: 16px;
height: 16px;
margin: 0 5px -3px 5px;
}
label {
line-height: 38px;
}
input {
width: 100%;
}
}
.create-tag {
margin-top: 20px;

Просмотреть файл

@ -0,0 +1,195 @@
<template>
<div class="approval_setting">
<span class="icon icon-user" />
<div class="approval-user">
<Multiselect
class="approval-user-input"
label="displayName"
track-by="user"
:value="value.users"
:multiple="true"
:clear-on-select="false"
:hide-selected="false"
:internal-search="false"
:loading="loadingUsers"
:options="formattedSuggestions"
:placeholder="t('welcome', 'Who can approve?')"
:preselect-first="false"
:preserve-search="false"
:searchable="true"
:user-select="true"
@search-change="asyncFind"
@update:value="update('users', $event)">
<template #option="{option}">
<Avatar
class="approval-avatar-option"
:user="option.user"
:show-user-status="false" />
<span>
{{ option.displayName }}
</span>
</template>
<template #singleLabel="{ option }">
<ListItemIcon v-bind="option"
:title="option.displayName + 'lalala'"
:avatar-size="24"
:no-margin="true" />
</template>
<template #noOptions>
{{ t('welcome', 'No recommendations. Start typing.') }}
</template>
<template #noResult>
{{ t('welcome', 'No result.') }}
</template>
</Multiselect>
<!--div v-if="state.user_name && state.user_id"
class="selected-user">
<Avatar
:size="20"
:user="state.user_id"
:tooltip-message="state.user_id"
:show-user-status="false" />
<span>
{{ state.user_name }}
</span>
</div-->
</div>
<span class="icon" :style="'background-image: url(' + tagPendingIconUrl + ');'" />
<MultiselectTags class="tag-select"
:value="value.tagPending"
:label="t('approval', 'Select pending tag')"
:multiple="false"
@input="update('tagPending', $event)" />
<span class="icon" :style="'background-image: url(' + tagApprovedIconUrl + ');'" />
<MultiselectTags class="tag-select"
:value="value.tagApproved"
:label="t('approval', 'Select approved tag')"
:multiple="false"
@input="update('tagApproved', $event)" />
<span class="icon" :style="'background-image: url(' + tagRejectedIconUrl + ');'" />
<MultiselectTags class="tag-select"
:value="value.tagRejected"
:label="t('approval', 'Select rejected tag')"
:multiple="false"
@input="update('tagRejected', $event)" />
</div>
</template>
<script>
import { getCurrentUser } from '@nextcloud/auth'
import { generateUrl, generateOcsUrl } from '@nextcloud/router'
import axios from '@nextcloud/axios'
import Avatar from '@nextcloud/vue/dist/Components/Avatar'
import Multiselect from '@nextcloud/vue/dist/Components/Multiselect'
import MultiselectTags from '@nextcloud/vue/dist/Components/MultiselectTags'
import ListItemIcon from '@nextcloud/vue/dist/Components/ListItemIcon'
export default {
name: 'ApprovalSetting',
components: {
Avatar,
Multiselect,
MultiselectTags,
ListItemIcon,
},
props: {
value: {
type: Object,
required: true,
},
},
data() {
return {
tagPendingIconUrl: generateUrl('/svg/core/actions/tag?color=0082c9'),
tagApprovedIconUrl: generateUrl('/svg/core/actions/tag?color=46ba61'),
tagRejectedIconUrl: generateUrl('/svg/core/actions/tag?color=e9322d'),
loadingUsers: false,
suggestions: [],
query: '',
currentUser: getCurrentUser(),
}
},
computed: {
formattedSuggestions() {
const result = this.suggestions.map((s) => {
return {
user: s.id,
displayName: s.label,
icon: 'icon-user',
}
})
if (this.currentUser && this.query) {
const lowerCurrent = this.currentUser.displayName.toLowerCase()
const lowerQuery = this.query.toLowerCase()
if (lowerCurrent.match(lowerQuery)) {
result.push({
user: this.currentUser.uid,
displayName: this.currentUser.displayName,
icon: 'icon-user',
})
}
}
return result
},
},
watch: {
},
mounted() {
},
methods: {
update(key, value) {
this.$emit('input', { ...this.value, [key]: value })
},
asyncFind(query) {
this.query = query
if (query === '') {
this.suggestions = []
return
}
this.loadingUsers = true
console.debug(query)
const url = generateOcsUrl('core/autocomplete/get', 2).replace(/\/$/, '')
axios.get(url, {
params: {
format: 'json',
search: query,
itemType: ' ',
itemId: ' ',
shareTypes: [],
},
}).then((response) => {
console.debug(response)
this.suggestions = response.data.ocs.data
}).catch((error) => {
console.error(error)
}).then(() => {
this.loadingUsers = false
})
},
},
}
</script>
<style scoped lang="scss">
.approval_setting {
display: flex;
align-items: center;
.tag-select {
width: 200px;
}
.icon {
width: 16px;
height: 16px;
margin: 0 5px -3px 15px;
}
}
</style>