[enh] Remote validation error displayed on field

This commit is contained in:
ljf 2021-08-31 16:05:40 +02:00
parent 5e554bb4a2
commit ad04197287
5 changed files with 33 additions and 13 deletions

View file

@ -49,6 +49,7 @@ class APIBadRequestError extends APIError {
super(method, response, errorData) super(method, response, errorData)
this.name = 'APIBadRequestError' this.name = 'APIBadRequestError'
this.key = errorData.error_key this.key = errorData.error_key
this.data = errorData
} }
} }

View file

@ -11,8 +11,8 @@
<slot name="server-error"> <slot name="server-error">
<b-alert <b-alert
variant="danger" class="my-3" variant="danger" class="my-3" icon="ban"
:show="serverError !== ''" v-html="serverError" :show="errorFeedback !== ''" v-html="errorFeedback"
/> />
</slot> </slot>
</b-form> </b-form>
@ -47,6 +47,12 @@ export default {
computed: { computed: {
disabled () { disabled () {
return this.validation ? this.validation.$invalid : false return this.validation ? this.validation.$invalid : false
},
errorFeedback () {
if (this.serverError) return this.serverError
else if (this.validation && this.validation.$invalid) {
return this.$t('invalid_form')
} else return ''
} }
}, },

View file

@ -58,6 +58,7 @@ export function adressToFormValue (address) {
export function formatYunoHostArgument (arg) { export function formatYunoHostArgument (arg) {
let value = (arg.value !== undefined) ? arg.value : (arg.current_value !== undefined) ? arg.current_value : null let value = (arg.value !== undefined) ? arg.value : (arg.current_value !== undefined) ? arg.current_value : null
const validation = {} const validation = {}
const error = { message: null }
arg.ask = formatI18nField(arg.ask) arg.ask = formatI18nField(arg.ask)
const field = { const field = {
component: undefined, component: undefined,
@ -214,6 +215,12 @@ export function formatYunoHostArgument (arg) {
// validation.pattern = validators.helpers.withMessage(arg.pattern.error, // 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(arg.pattern.error, new RegExp(arg.pattern.regexp))
} }
validation.remote = validators.helpers.withParams(error, (v) => {
const result = !error.message
error.message = null
return result
})
// field.props['title'] = field.pattern.error // field.props['title'] = field.pattern.error
// Default value if still `null` // Default value if still `null`
@ -242,7 +249,8 @@ export function formatYunoHostArgument (arg) {
value, value,
field, field,
// Return null instead of empty object if there's no validation // Return null instead of empty object if there's no validation
validation: Object.keys(validation).length === 0 ? null : validation validation: Object.keys(validation).length === 0 ? null : validation,
error
} }
} }
@ -259,6 +267,7 @@ export function formatYunoHostArguments (args, name = null) {
const form = {} const form = {}
const fields = {} const fields = {}
const validations = {} const validations = {}
const errors = {}
// FIXME yunohost should add the label field by default // FIXME yunohost should add the label field by default
if (name) { if (name) {
@ -270,13 +279,14 @@ export function formatYunoHostArguments (args, name = null) {
} }
for (const arg of args) { for (const arg of args) {
const { value, field, validation } = formatYunoHostArgument(arg) const { value, field, validation, error } = formatYunoHostArgument(arg)
fields[arg.name] = field fields[arg.name] = field
form[arg.name] = value form[arg.name] = value
if (validation) validations[arg.name] = validation if (validation) validations[arg.name] = validation
errors[arg.name] = error
} }
return { form, fields, validations } return { form, fields, validations, errors }
} }
export function pFileReader (file, output, key) { export function pFileReader (file, output, key) {

View file

@ -181,6 +181,7 @@
"passwordLenght": "Password must be at least 8 characters long.", "passwordLenght": "Password must be at least 8 characters long.",
"passwordMatch": "Passwords don't match.", "passwordMatch": "Passwords don't match.",
"required": "Field is required.", "required": "Field is required.",
"remote": "{message}",
"pattern": "{type}" "pattern": "{type}"
}, },
"form_input_example": "Example: {example}", "form_input_example": "Example: {example}",

View file

@ -23,7 +23,7 @@
/> />
</template> </template>
</div> </div>
</card-form> </card-form> {{ errors.main.str }}
</template> </template>
<!-- if no config panel --> <!-- if no config panel -->
@ -60,6 +60,7 @@ export default {
], ],
panels: undefined, panels: undefined,
forms: undefined, forms: undefined,
errors: undefined,
validations: null validations: null
} }
}, },
@ -87,18 +88,21 @@ export default {
const forms = {} const forms = {}
const validations_ = {} const validations_ = {}
const errors_ = {}
const panels_ = [] const panels_ = []
for (const { id, name, help, sections } of data.panel) { for (const { id, name, help, sections } of data.panel) {
const panel_ = { id, name, sections: [] } const panel_ = { id, name, sections: [] }
if (help) panel_.help = formatI18nField(help) if (help) panel_.help = formatI18nField(help)
forms[id] = {} forms[id] = {}
validations_[id] = {} validations_[id] = {}
errors_[id] = {}
for (const { name, help, options } of sections) { for (const { name, help, options } of sections) {
const section_ = { name } const section_ = { name }
if (help) section_.help = formatI18nField(help) if (help) section_.help = formatI18nField(help)
const { form, fields, validations } = formatYunoHostArguments(options) const { form, fields, validations, errors } = formatYunoHostArguments(options)
Object.assign(forms[id], form) Object.assign(forms[id], form)
Object.assign(validations_[id], validations) Object.assign(validations_[id], validations)
Object.assign(errors_[id], errors)
panel_.sections.push({ name, fields }) panel_.sections.push({ name, fields })
} }
panels_.push(panel_) panels_.push(panel_)
@ -107,24 +111,22 @@ export default {
this.forms = forms this.forms = forms
this.validations = { forms: validations_ } this.validations = { forms: validations_ }
this.panels = panels_ this.panels = panels_
this.errors = errors_
}, },
applyConfig (id_) { applyConfig (id_) {
console.debug(this.forms[id_])
formatFormData(this.forms[id_], { promise: true, removeEmpty: false, removeNull: 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(
`apps/${this.id}/config`, { key: id_, args }, { key: 'apps.update_config', name: this.id } `apps/${this.id}/config`, { key: id_, args }, { key: 'apps.update_config', name: this.id }
).then(response => { ).then(response => {
// FIXME what should be done ?
/* eslint-disable-next-line */
console.log('SUCCESS', response)
}).catch(err => { }).catch(err => {
if (err.name !== 'APIBadRequestError') throw err if (err.name !== 'APIBadRequestError') throw err
const panel = this.panels.find(({ id }) => id_ === id) const panel = this.panels.find(({ id }) => id_ === id)
this.$set(panel, 'serverError', err.message) if (err.data.field) {
this.errors[id_][err.data.field].message = err.message
} else this.$set(panel, 'serverError', err.message)
}) })
}) })
} }