2
0
mirror of https://github.com/frappe/books.git synced 2024-09-20 19:29:02 +00:00
books/client/view/controls/table.js

172 lines
5.4 KiB
JavaScript
Raw Normal View History

2018-02-06 17:14:07 +00:00
const frappe = require('frappejs');
const BaseControl = require('./base');
const DataTable = require('frappe-datatable');
const controls = require('./index');
2018-02-07 13:23:52 +00:00
const Modal = require('frappejs/client/ui/modal');
2018-02-06 17:14:07 +00:00
class TableControl extends BaseControl {
make() {
2018-02-15 09:53:28 +00:00
this.makeWrapper();
this.makeDatatable();
this.setupToolbar();
}
2018-02-07 13:23:52 +00:00
2018-02-15 09:53:28 +00:00
makeWrapper() {
this.wrapper = frappe.ui.add('div', 'table-wrapper', this.getInputParent());
this.wrapper.innerHTML =
`<div class="datatable-wrapper"></div>
<div class="table-toolbar">
<button type="button" class="btn btn-sm btn-outline-secondary btn-add">
${frappe._("Add")}</button>
<button type="button" class="btn btn-sm btn-outline-secondary btn-remove">
${frappe._("Remove")}</button>
</div>`;
2018-02-13 11:54:57 +00:00
}
2018-02-07 13:23:52 +00:00
2018-02-13 11:54:57 +00:00
makeDatatable() {
this.datatable = new DataTable(this.wrapper.querySelector('.datatable-wrapper'), {
columns: this.getColumns(),
data: this.getTableData(),
takeAvailableSpace: true,
addCheckboxColumn: true,
getEditor: this.getTableInput.bind(this),
});
}
2018-02-06 17:14:07 +00:00
2018-02-13 11:54:57 +00:00
setupToolbar() {
this.wrapper.querySelector('.btn-add').addEventListener('click', async (event) => {
this.doc[this.fieldname].push({});
await this.doc.commit();
this.refresh();
});
this.wrapper.querySelector('.btn-remove').addEventListener('click', async (event) => {
let checked = this.datatable.rowmanager.getCheckedRows();
this.doc[this.fieldname] = this.doc[this.fieldname].filter(d => !checked.includes(d.idx));
await this.doc.commit();
this.refresh();
this.datatable.rowmanager.checkAll(false);
});
2018-02-06 17:14:07 +00:00
}
2018-02-08 09:38:47 +00:00
getInputValue() {
2018-02-06 17:14:07 +00:00
return this.doc[this.fieldname];
}
2018-02-08 09:38:47 +00:00
setInputValue(value) {
2018-02-08 11:45:32 +00:00
this.datatable.refresh(this.getTableData(value));
2018-02-15 16:39:50 +00:00
this.datatable.setDimensions();
2018-02-06 17:14:07 +00:00
}
2018-02-08 11:45:32 +00:00
getTableData(value) {
return value || this.getDefaultData();
2018-02-06 17:14:07 +00:00
}
2018-02-08 11:45:32 +00:00
getTableInput(colIndex, rowIndex, value, parent) {
2018-02-06 17:14:07 +00:00
let field = this.datatable.getColumn(colIndex).field;
2018-02-07 13:23:52 +00:00
if (field.fieldtype==='Text') {
2018-02-09 12:55:55 +00:00
// text in modal
parent = this.getControlModal(field).getBody();
2018-02-07 13:23:52 +00:00
}
2018-02-09 12:55:55 +00:00
return this.getControl(field, parent);
2018-02-07 13:23:52 +00:00
}
2018-02-08 11:45:32 +00:00
getControl(field, parent) {
field.onlyInput = true;
2018-02-08 09:38:47 +00:00
const control = controls.makeControl({field: field, parent: parent});
2018-02-06 17:14:07 +00:00
2018-02-09 12:55:55 +00:00
// change will be triggered by datatable
control.skipChangeEvent = true;
2018-02-06 17:17:34 +00:00
return {
initValue: (value, rowIndex, column) => {
2018-02-12 09:42:26 +00:00
column.activeControl = control;
2018-02-13 11:54:57 +00:00
control.parentControl = this;
2018-02-06 17:14:07 +00:00
control.doc = this.doc[this.fieldname][rowIndex];
control.set_focus();
2018-02-08 09:38:47 +00:00
return control.setInputValue(value);
2018-02-06 17:17:34 +00:00
},
2018-02-08 11:45:32 +00:00
setValue: async (value, rowIndex, column) => {
2018-02-09 12:55:55 +00:00
control.handleChange();
2018-02-06 17:17:34 +00:00
},
getValue: () => {
2018-02-08 09:38:47 +00:00
return control.getInputValue();
2018-02-06 17:14:07 +00:00
}
}
2018-02-07 13:23:52 +00:00
}
2018-02-09 12:55:55 +00:00
getControlModal(field) {
2018-02-08 11:45:32 +00:00
this.modal = new Modal({
2018-02-07 13:23:52 +00:00
title: frappe._('Edit {0}', field.label),
body: '',
2018-02-09 12:55:55 +00:00
primary: {
label: frappe._('Submit'),
action: (modal) => {
this.datatable.cellmanager.submitEditing();
modal.hide();
}
2018-02-07 13:23:52 +00:00
}
});
this.modal.on('hide', () => {
2018-02-07 16:44:59 +00:00
this.datatable.cellmanager.deactivateEditing();
2018-02-09 12:55:55 +00:00
this.datatable.cellmanager.$focusedCell.focus();
});
2018-02-07 13:23:52 +00:00
2018-02-09 12:55:55 +00:00
return this.modal;
2018-02-06 17:14:07 +00:00
}
2018-02-08 11:45:32 +00:00
getColumns() {
return this.getChildFields().map(field => {
2018-02-06 17:14:07 +00:00
return {
id: field.fieldname,
field: field,
content: field.label,
width: 120,
2018-02-09 12:55:55 +00:00
editable: field.disabled ? false : true,
sortable: false,
resizable: true,
dropdown: false,
2018-02-06 17:14:07 +00:00
align: ['Int', 'Float', 'Currency'].includes(field.fieldtype) ? 'right' : 'left',
format: (value) => frappe.format(value, field)
}
});
}
2018-02-08 11:45:32 +00:00
getChildFields() {
2018-02-09 12:55:55 +00:00
return frappe.getMeta(this.childtype).fields.filter(f => f.hidden ? false : true);
2018-02-06 17:14:07 +00:00
}
2018-02-08 11:45:32 +00:00
getDefaultData() {
2018-02-06 17:14:07 +00:00
// build flat table
if (!this.doc) {
return [];
}
if (!this.doc[this.fieldname]) {
2018-02-12 09:42:26 +00:00
this.doc[this.fieldname] = [{idx: 0}];
2018-02-06 17:14:07 +00:00
}
return this.doc[this.fieldname];
}
2018-02-12 09:42:26 +00:00
checkValidity() {
let data = this.getTableData();
for (let rowIndex=0; rowIndex < data.length; rowIndex++) {
let row = data[rowIndex];
for (let column of this.datatable.datamanager.columns) {
if (column.field && column.field.required) {
let value = row[column.field.fieldname];
if (value==='' || value===undefined || value===null) {
let $cell = this.datatable.cellmanager.getCell$(column.colIndex, rowIndex);
this.datatable.cellmanager.activateEditing($cell);
return false;
}
}
}
}
return true;
}
2018-02-06 17:14:07 +00:00
};
module.exports = TableControl;