mirror of
https://github.com/YunoHost/yunohost-admin.git
synced 2024-09-03 20:06:15 +02:00
commit
218e544bbe
6 changed files with 129 additions and 53 deletions
|
@ -19,10 +19,7 @@
|
|||
</template>
|
||||
|
||||
<slot v-if="!noFooter" name="buttons" slot="buttons">
|
||||
<b-button
|
||||
type="submit" variant="success"
|
||||
:form="id" :disabled="disabled"
|
||||
>
|
||||
<b-button type="submit" variant="success" :form="id">
|
||||
{{ submitText ? submitText : $t('save') }}
|
||||
</b-button>
|
||||
</slot>
|
||||
|
@ -45,9 +42,6 @@ export default {
|
|||
},
|
||||
|
||||
computed: {
|
||||
disabled () {
|
||||
return false // this.validation ? this.validation.$invalid : false
|
||||
},
|
||||
errorFeedback () {
|
||||
if (this.serverError) return this.serverError
|
||||
else if (this.validation && this.validation.$anyError) {
|
||||
|
|
82
app/src/components/globals/TabForm.vue
Normal file
82
app/src/components/globals/TabForm.vue
Normal file
|
@ -0,0 +1,82 @@
|
|||
<template>
|
||||
<b-tab no-body>
|
||||
<template #title>
|
||||
<icon :iname="icon" /> {{ name }}
|
||||
</template>
|
||||
|
||||
<b-card-body>
|
||||
<slot name="disclaimer" />
|
||||
|
||||
|
||||
<b-form
|
||||
:id="id" :inline="inline" :class="formClasses"
|
||||
@submit.prevent="onSubmit" novalidate
|
||||
>
|
||||
<slot name="default" />
|
||||
|
||||
<slot name="server-error">
|
||||
<b-alert
|
||||
variant="danger" class="my-3" icon="ban"
|
||||
:show="errorFeedback !== ''" v-html="errorFeedback"
|
||||
/>
|
||||
</slot>
|
||||
</b-form>
|
||||
</b-card-body>
|
||||
|
||||
<b-card-footer>
|
||||
<b-button type="submit" variant="success" :form="id">
|
||||
{{ submitText ? submitText : $t('save') }}
|
||||
</b-button>
|
||||
</b-card-footer>
|
||||
</b-tab>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
|
||||
export default {
|
||||
name: 'TabForm',
|
||||
|
||||
props: {
|
||||
id: { type: String, default: 'ynh-form' },
|
||||
submitText: { type: String, default: null },
|
||||
validation: { type: Object, default: null },
|
||||
serverError: { type: String, default: '' },
|
||||
inline: { type: Boolean, default: false },
|
||||
formClasses: { type: [Array, String, Object], default: null },
|
||||
name: { type: String, required: true },
|
||||
icon: { type: String, default: 'wrench' }
|
||||
},
|
||||
|
||||
computed: {
|
||||
errorFeedback () {
|
||||
if (this.serverError) return this.serverError
|
||||
else if (this.validation && this.validation.$anyError) {
|
||||
return this.$i18n.t('form_errors.invalid_form')
|
||||
} else return ''
|
||||
}
|
||||
},
|
||||
|
||||
methods: {
|
||||
onSubmit (e) {
|
||||
const v = this.validation
|
||||
if (v) {
|
||||
v.$touch()
|
||||
if (v.$pending || v.$invalid) return
|
||||
}
|
||||
this.$emit('submit', e)
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.card-footer {
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
align-items: center;
|
||||
|
||||
& > *:not(:first-child) {
|
||||
margin-left: .5rem;
|
||||
}
|
||||
}
|
||||
</style>
|
|
@ -47,28 +47,29 @@ export default {
|
|||
|
||||
<style lang="scss" scoped>
|
||||
#top-bar {
|
||||
margin-bottom: 2rem;
|
||||
margin-bottom: 1rem;
|
||||
flex-wrap: wrap-reverse;
|
||||
|
||||
.top-bar-group {
|
||||
display: flex;
|
||||
margin-bottom: 1rem;
|
||||
}
|
||||
|
||||
@include media-breakpoint-down(xs) {
|
||||
.top-bar-group {
|
||||
flex-direction: column-reverse;
|
||||
}
|
||||
|
||||
::v-deep .btn:not(:first-of-type) {
|
||||
margin-bottom: .25rem;
|
||||
}
|
||||
}
|
||||
|
||||
@include media-breakpoint-down(sm) {
|
||||
flex-direction: column-reverse;
|
||||
|
||||
#top-bar-left ~ #top-bar-right {
|
||||
margin-bottom: 1rem;
|
||||
#top-bar-right {
|
||||
margin-bottom: .75rem;
|
||||
|
||||
::v-deep > * {
|
||||
margin-bottom: .25rem;
|
||||
}
|
||||
}
|
||||
|
||||
.top-bar-group {
|
||||
|
|
|
@ -63,3 +63,13 @@ export default {
|
|||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
::v-deep .custom-file-label {
|
||||
color: $input-placeholder-color;
|
||||
|
||||
.btn-danger + .b-form-file & {
|
||||
color: $input-color;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
|
@ -218,8 +218,7 @@ export function formatYunoHostArgument (arg) {
|
|||
validation.required = validators.required
|
||||
}
|
||||
if (arg.pattern && arg.type !== 'tags') {
|
||||
// validation.pattern = validators.helpers.withMessage(arg.pattern.error,
|
||||
validation.pattern = validators.helpers.regex(arg.pattern.error, new RegExp(arg.pattern.regexp))
|
||||
validation.pattern = validators.helpers.regex(formatI18nField(arg.pattern.error), new RegExp(arg.pattern.regexp))
|
||||
}
|
||||
validation.remote = validators.helpers.withParams(error, (v) => {
|
||||
const result = !error.message
|
||||
|
|
|
@ -1,41 +1,32 @@
|
|||
<template>
|
||||
<view-base :queries="queries" @queries-response="onQueriesResponse" skeleton="card-form-skeleton">
|
||||
<template v-if="panels" #default>
|
||||
<b-tabs pills card vertical>
|
||||
<b-tab v-for="{ name, id: id_, sections, help, serverError } in panels"
|
||||
:key="id_"
|
||||
:title="name"
|
||||
<b-card v-if="panels" no-body>
|
||||
<b-tabs fill pills card>
|
||||
<tab-form
|
||||
v-for="{ name, id: id_, sections, help, serverError } in panels" :key="id_"
|
||||
v-bind="{ name, id: id_ + '-form', validation: $v.forms[id_], serverError }"
|
||||
>
|
||||
<template #title>
|
||||
<icon iname="wrench" /> {{ name }}
|
||||
<template v-if="help" #disclaimer>
|
||||
<div class="alert alert-info" v-html="help" />
|
||||
</template>
|
||||
<card-form
|
||||
:key="id_"
|
||||
:title="name" icon="wrench" title-tag="h2"
|
||||
:validation="$v.forms[id_]" :id="id_ + '-form'" :server-error="serverError"
|
||||
@submit.prevent="applyConfig(id_)"
|
||||
>
|
||||
<template v-if="help" #disclaimer>
|
||||
<div class="alert alert-info" v-html="help" />
|
||||
</template>
|
||||
|
||||
<template v-for="section in sections">
|
||||
<div :key="section.id" class="mb-5" v-if="isVisible(section.visible, section)">
|
||||
<b-card-title v-if="section.name" title-tag="h3">
|
||||
{{ section.name }} <small v-if="section.help">{{ section.help }}</small>
|
||||
</b-card-title>
|
||||
<template v-for="(field, fname) in section.fields">
|
||||
<form-field :key="fname" v-model="forms[id_][fname]"
|
||||
:validation="$v.forms[id_][fname]"
|
||||
v-if="isVisible(field.visible, field)" v-bind="field"
|
||||
/>
|
||||
</template>
|
||||
</div>
|
||||
</template>
|
||||
</card-form>
|
||||
</b-tab>
|
||||
<template v-for="section in sections">
|
||||
<div v-if="isVisible(section.visible, section)" :key="section.id" class="mb-5">
|
||||
<b-card-title v-if="section.name" title-tag="h3">
|
||||
{{ section.name }} <small v-if="section.help">{{ section.help }}</small>
|
||||
</b-card-title>
|
||||
|
||||
<template v-for="(field, fname) in section.fields">
|
||||
<form-field
|
||||
v-if="isVisible(field.visible, field)" :key="fname"
|
||||
v-model="forms[id_][fname]" v-bind="field" :validation="$v.forms[id_][fname]"
|
||||
/>
|
||||
</template>
|
||||
</div>
|
||||
</template>
|
||||
</tab-form>
|
||||
</b-tabs>
|
||||
</template>
|
||||
</b-card>
|
||||
|
||||
<!-- if no config panel -->
|
||||
<b-alert v-else-if="panels === null" variant="warning">
|
||||
|
@ -117,6 +108,7 @@ export default {
|
|||
// This value should be updated magically when vuejs will detect isVisible changed
|
||||
return field.isVisible
|
||||
},
|
||||
|
||||
onQueriesResponse (data) {
|
||||
if (!data.panels || data.panels.length === 0) {
|
||||
this.panels = null
|
||||
|
@ -182,12 +174,10 @@ export default {
|
|||
}
|
||||
}
|
||||
</script>
|
||||
<style>
|
||||
h3.card-title {
|
||||
|
||||
<style lang="scss" scoped>
|
||||
h3 {
|
||||
margin-bottom: 1em;
|
||||
border-bottom: solid 1px #aaa;
|
||||
}
|
||||
.form-control::placeholder, .form-file-text {
|
||||
color: #6d7780;
|
||||
}
|
||||
</style>
|
||||
|
|
Loading…
Add table
Reference in a new issue