Merge pull request #421 from YunoHost/enh-misc-fix

Enh misc fix
This commit is contained in:
Alexandre Aubin 2022-01-05 17:49:11 +01:00 committed by GitHub
commit 218e544bbe
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
6 changed files with 129 additions and 53 deletions

View file

@ -19,10 +19,7 @@
</template> </template>
<slot v-if="!noFooter" name="buttons" slot="buttons"> <slot v-if="!noFooter" name="buttons" slot="buttons">
<b-button <b-button type="submit" variant="success" :form="id">
type="submit" variant="success"
:form="id" :disabled="disabled"
>
{{ submitText ? submitText : $t('save') }} {{ submitText ? submitText : $t('save') }}
</b-button> </b-button>
</slot> </slot>
@ -45,9 +42,6 @@ export default {
}, },
computed: { computed: {
disabled () {
return false // this.validation ? this.validation.$invalid : false
},
errorFeedback () { errorFeedback () {
if (this.serverError) return this.serverError if (this.serverError) return this.serverError
else if (this.validation && this.validation.$anyError) { else if (this.validation && this.validation.$anyError) {

View 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>

View file

@ -47,28 +47,29 @@ export default {
<style lang="scss" scoped> <style lang="scss" scoped>
#top-bar { #top-bar {
margin-bottom: 2rem; margin-bottom: 1rem;
flex-wrap: wrap-reverse; flex-wrap: wrap-reverse;
.top-bar-group { .top-bar-group {
display: flex; display: flex;
margin-bottom: 1rem;
} }
@include media-breakpoint-down(xs) { @include media-breakpoint-down(xs) {
.top-bar-group { .top-bar-group {
flex-direction: column-reverse; flex-direction: column-reverse;
} }
::v-deep .btn:not(:first-of-type) {
margin-bottom: .25rem;
}
} }
@include media-breakpoint-down(sm) { @include media-breakpoint-down(sm) {
flex-direction: column-reverse; flex-direction: column-reverse;
#top-bar-left ~ #top-bar-right { #top-bar-right {
margin-bottom: 1rem; margin-bottom: .75rem;
::v-deep > * {
margin-bottom: .25rem;
}
} }
.top-bar-group { .top-bar-group {

View file

@ -63,3 +63,13 @@ export default {
} }
} }
</script> </script>
<style lang="scss" scoped>
::v-deep .custom-file-label {
color: $input-placeholder-color;
.btn-danger + .b-form-file & {
color: $input-color;
}
}
</style>

View file

@ -218,8 +218,7 @@ export function formatYunoHostArgument (arg) {
validation.required = validators.required validation.required = validators.required
} }
if (arg.pattern && arg.type !== 'tags') { if (arg.pattern && arg.type !== 'tags') {
// validation.pattern = validators.helpers.withMessage(arg.pattern.error, validation.pattern = validators.helpers.regex(formatI18nField(arg.pattern.error), new RegExp(arg.pattern.regexp))
validation.pattern = validators.helpers.regex(arg.pattern.error, new RegExp(arg.pattern.regexp))
} }
validation.remote = validators.helpers.withParams(error, (v) => { validation.remote = validators.helpers.withParams(error, (v) => {
const result = !error.message const result = !error.message

View file

@ -1,41 +1,32 @@
<template> <template>
<view-base :queries="queries" @queries-response="onQueriesResponse" skeleton="card-form-skeleton"> <view-base :queries="queries" @queries-response="onQueriesResponse" skeleton="card-form-skeleton">
<template v-if="panels" #default> <b-card v-if="panels" no-body>
<b-tabs pills card vertical> <b-tabs fill pills card>
<b-tab v-for="{ name, id: id_, sections, help, serverError } in panels" <tab-form
:key="id_" v-for="{ name, id: id_, sections, help, serverError } in panels" :key="id_"
:title="name" v-bind="{ name, id: id_ + '-form', validation: $v.forms[id_], serverError }"
>
<template #title>
<icon iname="wrench" /> {{ name }}
</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> <template v-if="help" #disclaimer>
<div class="alert alert-info" v-html="help" /> <div class="alert alert-info" v-html="help" />
</template> </template>
<template v-for="section in sections"> <template v-for="section in sections">
<div :key="section.id" class="mb-5" v-if="isVisible(section.visible, section)"> <div v-if="isVisible(section.visible, section)" :key="section.id" class="mb-5">
<b-card-title v-if="section.name" title-tag="h3"> <b-card-title v-if="section.name" title-tag="h3">
{{ section.name }} <small v-if="section.help">{{ section.help }}</small> {{ section.name }} <small v-if="section.help">{{ section.help }}</small>
</b-card-title> </b-card-title>
<template v-for="(field, fname) in section.fields"> <template v-for="(field, fname) in section.fields">
<form-field :key="fname" v-model="forms[id_][fname]" <form-field
:validation="$v.forms[id_][fname]" v-if="isVisible(field.visible, field)" :key="fname"
v-if="isVisible(field.visible, field)" v-bind="field" v-model="forms[id_][fname]" v-bind="field" :validation="$v.forms[id_][fname]"
/> />
</template> </template>
</div> </div>
</template> </template>
</card-form> </tab-form>
</b-tab>
</b-tabs> </b-tabs>
</template> </b-card>
<!-- if no config panel --> <!-- if no config panel -->
<b-alert v-else-if="panels === null" variant="warning"> <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 // This value should be updated magically when vuejs will detect isVisible changed
return field.isVisible return field.isVisible
}, },
onQueriesResponse (data) { onQueriesResponse (data) {
if (!data.panels || data.panels.length === 0) { if (!data.panels || data.panels.length === 0) {
this.panels = null this.panels = null
@ -182,12 +174,10 @@ export default {
} }
} }
</script> </script>
<style>
h3.card-title { <style lang="scss" scoped>
h3 {
margin-bottom: 1em; margin-bottom: 1em;
border-bottom: solid 1px #aaa; border-bottom: solid 1px #aaa;
} }
.form-control::placeholder, .form-file-text {
color: #6d7780;
}
</style> </style>