import { Component } from '../../lib/vues6/vues6.js' import { utility } from '../service/Utility.service.js' import { location_service } from '../service/Location.service.js' import { resource_service } from '../service/Resource.service.js' import { action_service } from '../service/Action.service.js' const template = `
{{ access_msg }}

{{ title }}

{{ t['common.loading'] }}...

{{ field.error }} {{ field.error }} {{ field.error }} {{ field.error }} {{ field.error }}
{{ error_message }} {{ other_message }}
` const title_map = { insert: 'Create', update: 'Edit', view: 'View', } export default class FormComponent extends Component { static get selector() { return 'cobalt-form' } static get template() { return template } static get props() { return ['resource', 'form_id', 'initial_mode'] } constructor() { super() this.definition = {} this.data = {} this.uuid = '' this.title = '' this.error_message = '' this.other_message = '' this.access_msg = '' this.can_access = false this.is_ready = false this.mode = '' this.id = '' this.t = {} } reset() { this.definition = {} this.data = {} this.uuid = '' this.title = '' this.error_message = '' this.other_message = '' this.is_ready = false } async vue_on_create(internal = false) { this.t = await T( 'common.loading', 'common.confirm', 'common.save', 'common.not_permission', 'common.item_saved', 'common.unknown_error', 'common.field_required', 'common.confirmation_not_match', 'common.invalid_json' ) if ( !internal ) { this.mode = this.initial_mode this.id = this.form_id this.resource_class = await resource_service.get(this.resource) if ( await this.resource_class.can(this.mode) ) { this.can_access = true this.access_msg = true } else { this.can_access = false this.access_msg = this.t['common.not_permission'].replace('ACTION', this.mode) return } } else { this.reset() } this.uuid = utility.uuid() await this.init() await this.load() } async init() { this.definition = this.resource_class.form_definition for ( const field of this.definition.fields ) { if ( field.type.startsWith('select.dynamic') ) { field._options = field._options || field.options const rsc = await resource_service.get(field._options.resource) const other_params = field._options.other_params || {} field.options = (await rsc.list(other_params)).map(item => { return { display: typeof field._options.display === 'function' ? field._options.display(item) : item[field._options.display || 'display'], value: typeof field._options.value === 'function' ? field._options.value(item) : item[field._options.value || 'display'], } }) } } } async load() { if (this.mode !== 'insert') { this.data = await this.resource_class.get(this.id) } for ( const field of this.definition.fields ) { if ( field.type.endsWith('.multiple') && !this.data[field.field] ) { this.data[field.field] = [] } if ( field.type === 'json' ) { this.data[field.field] = JSON.stringify(this.data[field.field], undefined, 4) } } this.title = title_map[this.mode] + ' ' + this.resource_class.item this.is_ready = true this.$nextTick(() => { if ( this.mode !== 'view' ) this.$refs.input[0].focus() }) } async on_create() { this.id = this.data.id this.mode = 'update' if ( this.definition.handlers && this.definition.handlers.insert ) { await action_service.perform(this.definition.handlers.insert) } await this.vue_on_create(true) location_service.set_query(`mode=update&id=${this.id}`) } async on_update() { if ( this.definition.handlers && this.definition.handlers.update ) { await action_service.perform(this.definition.handlers.update) } } data_to_save() { const data = Object.assign({}, this.data) for ( const field of this.definition.fields ) { if ( field.type === 'json' ) { data[field.field] = JSON.parse(data[field.field]) } } return data } data_to_restore(data) { const new_data = Object.assign({}, data) for ( const field of this.definition.fields ) { if ( field.type === 'json' ) { new_data[field.field] = JSON.stringify(data[field.field], undefined, 4) } } this.data = new_data } async save_click() { if ( !this.validate() ) return try { if (this.mode === 'insert') { this.data_to_restore(await this.resource_class.create(this.data_to_save())) await this.on_create() } else if (this.mode === 'update') { await this.resource_class.update(this.id, this.data_to_save()) await this.on_update() } this.error_message = '' this.other_message = this.t['common.item_saved'].replace('ITEM', this.resource_class.item) } catch (e) { console.error(e) if ( e.response && e.response.data && e.response.data.message ) this.error_message = e.response.data.message else this.error_message = this.t['common.unknown_error'] } } is_json(string) { try { JSON.parse(string) return true } catch (e) { return false } } validate() { let valid = true for ( const field of this.definition.fields ) { if ( (Array.isArray(field.required) ? field.required.includes(this.mode) : field.required) && (!(field.field in this.data) || !this.data[field.field]) ) { field.error = this.t['common.field_required'] valid = false } else if ( field.type === 'password' && this.data[field.field] !== this.data[field.field + '-confirm'] ) { field.error = field.name + ' ' + this.t['common.confirmation_not_match'] valid = false } else if ( field.type === 'json' && !this.is_json(this.data[field.field]) ) { field.error = field.name + ' ' + this.t['common.invalid_json'] valid = false } else { field.error = '' } } this.$forceUpdate() return valid } back() { return action_service.perform({ text: '', type: 'resource', resource: this.resource, action: 'list', }) } do_nothing() {} }