2
0
mirror of https://github.com/frappe/books.git synced 2025-01-10 18:24:40 +00:00
books/src/pages/QuickEditForm.vue

279 lines
7.3 KiB
Vue
Raw Normal View History

2019-10-04 20:18:10 +00:00
<template>
<div class="border-l h-full">
<div class="flex items-center justify-between px-4 pt-4">
<div class="flex items-center">
<Button :icon="true" @click="routeToPrevious">
<feather-icon name="x" class="w-4 h-4" />
</Button>
<span v-if="statusText" class="ml-2 text-base text-gray-600">{{
statusText
}}</span>
</div>
<div class="flex items-stretch">
2019-12-03 13:32:34 +00:00
<Dropdown
v-if="actions && actions.length"
:items="actions"
right
class="text-base"
>
<template v-slot="{ toggleDropdown }">
<Button
class="text-gray-900"
:icon="true"
@click="toggleDropdown()"
>
<feather-icon name="more-horizontal" class="w-4 h-4" />
</Button>
</template>
</Dropdown>
<Button
:icon="true"
@click="insertDoc"
type="primary"
v-if="doc && doc._notInserted"
class="ml-2 text-white text-xs"
>
{{ _('Save') }}
</Button>
<Button
:icon="true"
@click="submitDoc"
type="primary"
v-if="
meta &&
meta.isSubmittable &&
doc &&
!doc.submitted &&
!doc._notInserted
"
class="ml-2 text-white text-xs"
>
{{ _('Submit') }}
</Button>
</div>
2019-10-04 20:18:10 +00:00
</div>
<div class="px-4 pt-2 pb-4 flex items-center justify-center" v-if="doc">
<div class="flex flex-col items-center">
<FormControl
v-if="imageField"
:df="imageField"
:value="doc[imageField.fieldname]"
@change="value => valueChange(imageField, value)"
size="small"
class="mb-1"
:letter-placeholder="
doc[titleField.fieldname] ? doc[titleField.fieldname][0] : null
"
/>
<FormControl
input-class="text-center"
ref="titleControl"
v-if="titleField"
:df="titleField"
:value="doc[titleField.fieldname]"
@change="value => valueChange(titleField, value)"
@input="setTitleSize"
/>
</div>
2019-10-04 20:18:10 +00:00
</div>
<div class="px-4 text-xs text-red-600 py-2" v-if="errorMessage">
{{ errorMessage }}
</div>
<TwoColumnForm
ref="form"
v-if="doc"
:doc="doc"
:fields="fields"
:autosave="true"
:column-ratio="[1.1, 2]"
:validate-form="validateForm"
/>
2019-10-04 20:18:10 +00:00
</div>
</template>
<script>
import frappe from 'frappejs';
import { _ } from 'frappejs';
2019-10-04 20:18:10 +00:00
import Button from '@/components/Button';
import FormControl from '@/components/Controls/FormControl';
import TwoColumnForm from '@/components/TwoColumnForm';
import Dropdown from '@/components/Dropdown';
import { deleteDocWithPrompt, openQuickEdit } from '@/utils';
2019-10-04 20:18:10 +00:00
export default {
name: 'QuickEditForm',
props: ['doctype', 'name', 'values', 'hideFields'],
2019-10-04 20:18:10 +00:00
components: {
Button,
FormControl,
TwoColumnForm,
Dropdown
2019-10-04 20:18:10 +00:00
},
2019-10-06 12:33:21 +00:00
provide() {
let vm = this;
2019-10-06 12:33:21 +00:00
return {
doctype: this.doctype,
name: this.name,
get doc() {
return vm.doc;
}
};
2019-10-06 12:33:21 +00:00
},
2019-10-04 20:18:10 +00:00
data() {
return {
doc: null,
titleField: null,
imageField: null,
statusText: null,
validateForm: false,
errorMessage: null
2019-10-04 20:18:10 +00:00
};
},
async created() {
await this.fetchMetaAndDoc();
},
errorCaptured(err, vm, info) {
this.errorMessage = err.message;
},
computed: {
meta() {
return frappe.getMeta(this.doctype);
},
fields() {
return this.meta
.getQuickEditFields()
.filter(df => !(this.hideFields || []).includes(df.fieldname));
},
actions() {
if (!this.doc) return null;
let deleteAction = {
component: {
template: `<span class="text-red-700">{{ _('Delete') }}</span>`
},
condition: doc => !doc.isNew() && !doc.submitted,
action: () => {
this.deleteDoc().then(() => {
this.routeToList();
});
}
};
let actions = [...(this.meta.actions || []), deleteAction]
.filter(d => (d.condition ? d.condition(this.doc) : true))
.map(d => {
return {
label: d.label,
component: d.component,
action: d.action.bind(this, this.doc, this.$router)
};
});
return actions;
}
},
methods: {
async fetchMetaAndDoc() {
this.titleField = this.meta.getField(this.meta.titleField);
this.imageField = this.meta.getField('image');
await this.fetchDoc();
// setup the title field
2019-12-03 13:32:34 +00:00
if (this.doc.isNew() && this.doc[this.titleField.fieldname]) {
if (!this.titleField.readOnly) {
this.doc.set(this.titleField.fieldname, '');
setTimeout(() => {
this.$refs.titleControl.focus();
}, 300);
} else {
this.doc.set(this.titleField.fieldname, 'New ' + this.doc.doctype);
}
}
// set default values
if (this.values) {
this.doc.set(this.values);
}
// set title size
this.setTitleSize();
},
valueChange(df, value) {
this.$refs.form.onChange(df, value);
},
async fetchDoc() {
try {
this.doc = await frappe.getDoc(this.doctype, this.name);
this.doc.once('afterRename', () => {
openQuickEdit({
doctype: this.doctype,
name: this.doc.name
});
});
this.doc.on('beforeUpdate', () => {
this.statusText = _('Saving...');
});
this.doc.on('afterUpdate', () => {
setTimeout(() => {
this.statusText = null;
}, 500);
});
} catch (e) {
this.$router.back();
}
},
insertDoc() {
let requiredFields = this.fields.filter(df => df.required);
if (requiredFields.some(df => this.doc[df.fieldname] == null)) {
this.validateForm = true;
return;
}
this.validateForm = false;
this.errorMessage = null;
this.doc.insert().catch(e => {
if (e.name === 'DuplicateEntryError') {
this.errorMessage = _('{0} {1} already exists.', [
this.doctype,
this.doc.name
]);
} else {
this.errorMessage = _('An error occurred.');
}
});
},
2019-11-08 19:58:58 +00:00
submitDoc() {
this.doc.submit();
},
deleteDoc() {
2019-12-03 08:15:12 +00:00
return deleteDocWithPrompt(this.doc).catch(e => {
if (e.name === 'LinkValidationError') {
this.errorMessage = _('{0} {1} is linked with existing records.', [
this.doctype,
this.doc.name
]);
} else {
this.errorMessage = _('An error occurred.');
}
throw e;
});
},
routeToList() {
this.$router.push(`/list/${this.doctype}`);
},
routeToPrevious() {
this.$router.back();
},
setTitleSize() {
if (this.$refs.titleControl) {
let input = this.$refs.titleControl.getInput();
let value = input.value;
2019-12-03 13:32:34 +00:00
let valueLength = (value || '').length + 1;
if (valueLength < 7) {
valueLength = 7;
}
input.size = valueLength;
}
}
2019-10-04 20:18:10 +00:00
}
};
</script>