mirror of
https://github.com/YunoHost/yunohost-admin.git
synced 2024-09-03 20:06:15 +02:00
[enh] Tags choices, textarea from files
This commit is contained in:
parent
5557c57252
commit
f0637c7dd7
8 changed files with 50 additions and 23 deletions
|
@ -103,7 +103,6 @@ export default {
|
||||||
const validation = this.validation
|
const validation = this.validation
|
||||||
if (validation && validation.$anyError) {
|
if (validation && validation.$anyError) {
|
||||||
const [type, errData] = this.findError(validation.$params, validation)
|
const [type, errData] = this.findError(validation.$params, validation)
|
||||||
console.log(type, errData)
|
|
||||||
return this.$i18n.t('form_errors.' + type, errData)
|
return this.$i18n.t('form_errors.' + type, errData)
|
||||||
}
|
}
|
||||||
return ''
|
return ''
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
<template>
|
<template>
|
||||||
<vue-showdown :markdown="label" />
|
<vue-showdown :markdown="label" flavor="github"/>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
|
|
|
@ -4,6 +4,9 @@
|
||||||
:id="id"
|
:id="id"
|
||||||
:placeholder="placeholder"
|
:placeholder="placeholder"
|
||||||
:required="required"
|
:required="required"
|
||||||
|
separator=" ,;"
|
||||||
|
:limit="limit"
|
||||||
|
remove-on-delete
|
||||||
:state="state"
|
:state="state"
|
||||||
v-on="$listeners"
|
v-on="$listeners"
|
||||||
@blur="$parent.$emit('touch', name)"
|
@blur="$parent.$emit('touch', name)"
|
||||||
|
@ -16,13 +19,14 @@ export default {
|
||||||
|
|
||||||
data () {
|
data () {
|
||||||
return {
|
return {
|
||||||
tags: null
|
tags: this.value
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
props: {
|
props: {
|
||||||
value: { type: Array, default: null },
|
value: { type: Array, default: null },
|
||||||
id: { type: String, default: null },
|
id: { type: String, default: null },
|
||||||
placeholder: { type: String, default: null },
|
placeholder: { type: String, default: null },
|
||||||
|
limit: { type: Number, default: null },
|
||||||
required: { type: Boolean, default: false },
|
required: { type: Boolean, default: false },
|
||||||
state: { type: Boolean, default: null },
|
state: { type: Boolean, default: null },
|
||||||
name: { type: String, default: null }
|
name: { type: String, default: null }
|
||||||
|
|
|
@ -67,12 +67,15 @@
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
export default {
|
export default {
|
||||||
name: 'TagsSelectize',
|
name: 'TagsSelectizeItem',
|
||||||
|
|
||||||
props: {
|
props: {
|
||||||
value: { type: Array, required: true },
|
value: { type: Array, required: true },
|
||||||
options: { type: Array, required: true },
|
options: { type: Array, required: true },
|
||||||
id: { type: String, required: true },
|
id: { type: String, required: true },
|
||||||
|
placeholder: { type: String, default: null },
|
||||||
|
limit: { type: Number, default: null },
|
||||||
|
name: { type: String, default: null },
|
||||||
itemsName: { type: String, required: true },
|
itemsName: { type: String, required: true },
|
||||||
disabledItems: { type: Array, default: () => ([]) },
|
disabledItems: { type: Array, default: () => ([]) },
|
||||||
// By default `addTag` and `removeTag` have to be executed manually by listening to 'tag-update'.
|
// By default `addTag` and `removeTag` have to be executed manually by listening to 'tag-update'.
|
|
@ -5,8 +5,7 @@
|
||||||
:placeholder="placeholder"
|
:placeholder="placeholder"
|
||||||
:required="required"
|
:required="required"
|
||||||
:state="state"
|
:state="state"
|
||||||
rows="3"
|
rows="4"
|
||||||
max-rows="6"
|
|
||||||
v-on="$listeners"
|
v-on="$listeners"
|
||||||
@blur="$parent.$emit('touch', name)"
|
@blur="$parent.$emit('touch', name)"
|
||||||
/>
|
/>
|
||||||
|
|
|
@ -108,12 +108,15 @@ export function formatYunoHostArgument (arg) {
|
||||||
props: ['id:name', 'choices']
|
props: ['id:name', 'choices']
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
types: ['select', 'user', 'domain'],
|
types: ['user', 'domain'],
|
||||||
name: 'SelectItem',
|
name: 'SelectItem',
|
||||||
props: ['id:name', 'choices'],
|
props: ['id:name', 'choices'],
|
||||||
callback: function () {
|
callback: function () {
|
||||||
field.link = { name: arg.type + '-list', text: i18n.t(`manage_${arg.type}s`) }
|
field.link = { name: arg.type + '-list', text: i18n.t(`manage_${arg.type}s`) }
|
||||||
field.props.choices = store.getters[arg.type + 'sAsChoices']
|
field.props.choices = store.getters[arg.type + 'sAsChoices']
|
||||||
|
if (value) {
|
||||||
|
return
|
||||||
|
}
|
||||||
if (arg.type === 'domain') {
|
if (arg.type === 'domain') {
|
||||||
value = store.getters.mainDomain
|
value = store.getters.mainDomain
|
||||||
} else {
|
} else {
|
||||||
|
@ -139,24 +142,37 @@ export function formatYunoHostArgument (arg) {
|
||||||
{
|
{
|
||||||
types: ['tags'],
|
types: ['tags'],
|
||||||
name: 'TagsItem',
|
name: 'TagsItem',
|
||||||
props: defaultProps
|
props: defaultProps.concat(['limit', 'placeholder', 'options:choices', 'tagIcon:icon']),
|
||||||
|
callback: function () {
|
||||||
|
if (arg.choices) {
|
||||||
|
this.name = 'TagsSelectizeItem'
|
||||||
|
field.props.auto = true
|
||||||
|
field.props.itemsName = ''
|
||||||
|
field.props.label = arg.placeholder
|
||||||
|
}
|
||||||
|
if (typeof value === 'string') {
|
||||||
|
value = value.split(',')
|
||||||
|
} else if (!value) {
|
||||||
|
value = []
|
||||||
|
}
|
||||||
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
types: ['boolean'],
|
types: ['boolean'],
|
||||||
name: 'CheckboxItem',
|
name: 'CheckboxItem',
|
||||||
props: ['id:name', 'choices'],
|
props: ['id:name', 'choices'],
|
||||||
callback: function () {
|
callback: function () {
|
||||||
if (typeof arg.default === 'number') {
|
if (value !== null && value !== undefined) {
|
||||||
value = arg.default === 1
|
value = ['1', 'yes', 'y', 'true'].includes(String(value).toLowerCase())
|
||||||
} else {
|
} else if (arg.default !== null && arg.default !== undefined) {
|
||||||
value = arg.default || false
|
value = ['1', 'yes', 'y', 'true'].includes(String(arg.default).toLowerCase())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
types: ['success', 'info', 'warning', 'danger'],
|
types: ['alert'],
|
||||||
name: 'ReadOnlyAlertItem',
|
name: 'ReadOnlyAlertItem',
|
||||||
props: ['type', 'label:ask', 'icon'],
|
props: ['type:style', 'label:ask', 'icon'],
|
||||||
readonly: true
|
readonly: true
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -174,9 +190,9 @@ export function formatYunoHostArgument (arg) {
|
||||||
// Search the component bind to the type
|
// Search the component bind to the type
|
||||||
const component = components.find(element => element.types.includes(arg.type))
|
const component = components.find(element => element.types.includes(arg.type))
|
||||||
if (component === undefined) throw new TypeError('Unknown type: ' + arg.type)
|
if (component === undefined) throw new TypeError('Unknown type: ' + arg.type)
|
||||||
field.component = component.name
|
|
||||||
// Callback use for specific behaviour
|
// Callback use for specific behaviour
|
||||||
if (component.callback) component.callback()
|
if (component.callback) component.callback()
|
||||||
|
field.component = component.name
|
||||||
// Affect properties to the field Item
|
// Affect properties to the field Item
|
||||||
for (let prop of component.props) {
|
for (let prop of component.props) {
|
||||||
prop = prop.split(':')
|
prop = prop.split(':')
|
||||||
|
@ -200,6 +216,9 @@ export function formatYunoHostArgument (arg) {
|
||||||
|
|
||||||
// field.props['title'] = field.pattern.error
|
// field.props['title'] = field.pattern.error
|
||||||
// Default value if still `null`
|
// Default value if still `null`
|
||||||
|
if (value === null && arg.current_value) {
|
||||||
|
value = arg.current_value
|
||||||
|
}
|
||||||
if (value === null && arg.default) {
|
if (value === null && arg.default) {
|
||||||
value = arg.default
|
value = arg.default
|
||||||
}
|
}
|
||||||
|
@ -300,7 +319,7 @@ export function formatFormDataValue (value) {
|
||||||
*/
|
*/
|
||||||
export async function formatFormData (
|
export async function formatFormData (
|
||||||
formData,
|
formData,
|
||||||
{ extract = null, flatten = false, removeEmpty = true, promise = false } = {}
|
{ extract = null, flatten = false, removeEmpty = true, removeNull = false, promise = false } = {}
|
||||||
) {
|
) {
|
||||||
const output = {
|
const output = {
|
||||||
data: {},
|
data: {},
|
||||||
|
@ -315,6 +334,8 @@ export async function formatFormData (
|
||||||
|
|
||||||
if (removeEmpty && isEmptyValue(value)) {
|
if (removeEmpty && isEmptyValue(value)) {
|
||||||
continue
|
continue
|
||||||
|
} else if (removeNull && (value === null || value === undefined)) {
|
||||||
|
continue
|
||||||
} else if (value instanceof File) {
|
} else if (value instanceof File) {
|
||||||
promises.push(pFileReader(value, output[type], key))
|
promises.push(pFileReader(value, output[type], key))
|
||||||
} else if (flatten && isObjectLiteral(value)) {
|
} else if (flatten && isObjectLiteral(value)) {
|
||||||
|
|
|
@ -110,7 +110,8 @@ export default {
|
||||||
},
|
},
|
||||||
|
|
||||||
applyConfig (id_) {
|
applyConfig (id_) {
|
||||||
formatFormData(this.forms[id_], { promise: true }).then((formatedData) => {
|
formatFormData(this.forms[id_], { promise: true, removeEmpty: false, removeNull: true }).then((formatedData) => {
|
||||||
|
console.debug(formatedData)
|
||||||
const args = objectToParams(formatedData)
|
const args = objectToParams(formatedData)
|
||||||
|
|
||||||
api.put(
|
api.put(
|
||||||
|
|
|
@ -44,7 +44,7 @@
|
||||||
</p>
|
</p>
|
||||||
</template>
|
</template>
|
||||||
<template v-else>
|
<template v-else>
|
||||||
<tags-selectize
|
<tags-selectize-item
|
||||||
v-model="group.members" :options="usersOptions"
|
v-model="group.members" :options="usersOptions"
|
||||||
:id="groupName + '-users'" :label="$t('group_add_member')"
|
:id="groupName + '-users'" :label="$t('group_add_member')"
|
||||||
tag-icon="user" items-name="users"
|
tag-icon="user" items-name="users"
|
||||||
|
@ -60,7 +60,7 @@
|
||||||
<strong>{{ $t('permissions') }}</strong>
|
<strong>{{ $t('permissions') }}</strong>
|
||||||
</b-col>
|
</b-col>
|
||||||
<b-col>
|
<b-col>
|
||||||
<tags-selectize
|
<tags-selectize-item
|
||||||
v-model="group.permissions" :options="permissionsOptions"
|
v-model="group.permissions" :options="permissionsOptions"
|
||||||
:id="groupName + '-perms'" :label="$t('group_add_permission')"
|
:id="groupName + '-perms'" :label="$t('group_add_permission')"
|
||||||
tag-icon="key-modern" items-name="permissions"
|
tag-icon="key-modern" items-name="permissions"
|
||||||
|
@ -83,7 +83,7 @@
|
||||||
</b-col>
|
</b-col>
|
||||||
|
|
||||||
<b-col>
|
<b-col>
|
||||||
<tags-selectize
|
<tags-selectize-item
|
||||||
v-model="userGroups[userName].permissions" :options="permissionsOptions"
|
v-model="userGroups[userName].permissions" :options="permissionsOptions"
|
||||||
:id="userName + '-perms'" :label="$t('group_add_permission')"
|
:id="userName + '-perms'" :label="$t('group_add_permission')"
|
||||||
tag-icon="key-modern" items-name="permissions"
|
tag-icon="key-modern" items-name="permissions"
|
||||||
|
@ -94,7 +94,7 @@
|
||||||
<hr :key="index">
|
<hr :key="index">
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<tags-selectize
|
<tags-selectize-item
|
||||||
v-model="activeUserGroups" :options="usersOptions"
|
v-model="activeUserGroups" :options="usersOptions"
|
||||||
id="user-groups" :label="$t('group_add_member')"
|
id="user-groups" :label="$t('group_add_member')"
|
||||||
no-tags items-name="users"
|
no-tags items-name="users"
|
||||||
|
@ -109,7 +109,7 @@ import Vue from 'vue'
|
||||||
|
|
||||||
import api from '@/api'
|
import api from '@/api'
|
||||||
import { isEmptyValue } from '@/helpers/commons'
|
import { isEmptyValue } from '@/helpers/commons'
|
||||||
import TagsSelectize from '@/components/TagsSelectize'
|
import TagsSelectizeItem from '@/components/globals/formItems/TagsSelectizeItem'
|
||||||
|
|
||||||
// TODO add global search with type (search by: group, user, permission)
|
// TODO add global search with type (search by: group, user, permission)
|
||||||
// TODO add vuex store update on inputs ?
|
// TODO add vuex store update on inputs ?
|
||||||
|
@ -117,7 +117,7 @@ export default {
|
||||||
name: 'GroupList',
|
name: 'GroupList',
|
||||||
|
|
||||||
components: {
|
components: {
|
||||||
TagsSelectize
|
TagsSelectizeItem
|
||||||
},
|
},
|
||||||
|
|
||||||
data () {
|
data () {
|
||||||
|
|
Loading…
Reference in a new issue