mirror of
https://github.com/frappe/books.git
synced 2026-08-24 10:04:45 -05:00
184 lines
4.0 KiB
Vue
184 lines
4.0 KiB
Vue
<template>
|
|
<div class="bg-white">
|
|
<page-header :breadcrumbs="breadcrumbs" />
|
|
<div class="form-container col-sm-8 col-lg-6 mx-2 mt-4">
|
|
<form-actions
|
|
v-if="shouldRenderForm"
|
|
:doc="doc"
|
|
@save="save"
|
|
@submit="submit"
|
|
@revert="revert"
|
|
@print="print"
|
|
:links="links"
|
|
/>
|
|
<hr class="mb-3" />
|
|
<form-layout
|
|
v-if="shouldRenderForm"
|
|
:doc="doc"
|
|
:fields="meta.fields"
|
|
:layout="meta.layout"
|
|
:invalid="isFormInvalid"
|
|
/>
|
|
</div>
|
|
</div>
|
|
</template>
|
|
<script>
|
|
import frappe from 'frappejs';
|
|
import FormActions from 'frappejs/ui/components/Form/FormActions';
|
|
import FormLayout from 'frappejs/ui/components/Form/FormLayout';
|
|
import PageHeader from '@/components/PageHeader';
|
|
|
|
export default {
|
|
name: 'FormView',
|
|
props: ['doctype', 'name'],
|
|
components: {
|
|
PageHeader,
|
|
FormActions,
|
|
FormLayout
|
|
},
|
|
watch: {
|
|
name(newValue, oldValue) {
|
|
if (newValue !== oldValue) {
|
|
this.loadDoc();
|
|
}
|
|
}
|
|
},
|
|
data() {
|
|
return {
|
|
doc: null,
|
|
links: [],
|
|
isFormInvalid: false,
|
|
notFound: false
|
|
};
|
|
},
|
|
computed: {
|
|
breadcrumbs() {
|
|
if (this.doc)
|
|
return [
|
|
{
|
|
title: this.meta.label,
|
|
route: '#/list/' + this.doctype
|
|
},
|
|
{
|
|
title: this.doc._notInserted
|
|
? 'New ' + this.meta.label
|
|
: this.doc.name,
|
|
route: ''
|
|
}
|
|
];
|
|
},
|
|
shouldRenderForm() {
|
|
return this.name && this.doc;
|
|
},
|
|
meta() {
|
|
return frappe.getMeta(this.doctype);
|
|
}
|
|
},
|
|
created() {
|
|
this.loadDoc();
|
|
},
|
|
methods: {
|
|
async loadDoc() {
|
|
if (!this.name) return;
|
|
try {
|
|
// need to de-reference to let vue know that doc is changed
|
|
this.doc = null;
|
|
this.doc = await frappe.getDoc(this.doctype, this.name);
|
|
|
|
if (
|
|
this.doc._notInserted &&
|
|
this.meta.fields.map(df => df.fieldname).includes('name')
|
|
) {
|
|
// For a user editable name field,
|
|
// it should be unset since it is autogenerated
|
|
this.doc.set('name', '');
|
|
}
|
|
|
|
if (this.defaultValues) {
|
|
for (let fieldname in this.defaultValues) {
|
|
const value = this.defaultValues[fieldname];
|
|
this.doc.set(fieldname, value);
|
|
}
|
|
}
|
|
|
|
this.setLinks();
|
|
this.doc.on('change', this.setLinks);
|
|
} catch (e) {
|
|
this.notFound = true;
|
|
this.$router.push(
|
|
`/list/${this.doctype === 'Party' ? 'Customer' : this.doctype}`
|
|
); //if reloaded while insert new Item,Invoice etc form.
|
|
}
|
|
},
|
|
async save() {
|
|
this.setValidity();
|
|
if (this.isFormInvalid) return;
|
|
|
|
try {
|
|
if (this.doc._notInserted) {
|
|
await this.doc.insert();
|
|
} else {
|
|
await this.doc.update();
|
|
}
|
|
|
|
this.$emit('save', this.doc);
|
|
} catch (e) {
|
|
console.error(e);
|
|
throw e;
|
|
}
|
|
},
|
|
|
|
async submit() {
|
|
this.doc.set('submitted', 1);
|
|
try {
|
|
await this.save();
|
|
} catch (e) {
|
|
this.doc.set('submitted', 0);
|
|
this.doc.set('_dirty', false);
|
|
}
|
|
},
|
|
|
|
async revert() {
|
|
this.doc.set('submitted', 0);
|
|
try {
|
|
await this.save();
|
|
} catch (e) {
|
|
this.doc.set('submitted', 1);
|
|
this.doc._dirty = false;
|
|
}
|
|
},
|
|
|
|
print() {
|
|
this.$router.push(`/print/${this.doctype}/${this.name}`);
|
|
},
|
|
|
|
setLinks() {
|
|
if (this.meta.links) {
|
|
let links = [];
|
|
for (let link of this.meta.links) {
|
|
if (link.condition(this)) {
|
|
link.handler = () => {
|
|
link.action(this);
|
|
};
|
|
links.push(link);
|
|
}
|
|
}
|
|
this.links = links;
|
|
}
|
|
},
|
|
|
|
setValidity() {
|
|
const form = this.$el.querySelector('form');
|
|
let validity = form.checkValidity();
|
|
this.isFormInvalid = !validity;
|
|
}
|
|
}
|
|
};
|
|
</script>
|
|
<style>
|
|
.table th,
|
|
.table td {
|
|
vertical-align: middle;
|
|
}
|
|
</style>
|