2
0
mirror of https://github.com/frappe/books.git synced 2024-11-13 00:46:28 +00:00

Render ListView based on listConfig

This commit is contained in:
Faris Ansari 2018-10-23 02:02:37 +05:30
parent 550c2708d2
commit bd3b266a69
14 changed files with 123 additions and 124 deletions

View File

@ -26,9 +26,8 @@ module.exports = {
fieldtype: 'Link', fieldtype: 'Link',
target: 'Party', target: 'Party',
required: 1, required: 1,
getFilters: (query, control) => { getFilters: (query) => {
return { return {
keywords: ['like', query],
customer: 1 customer: 1
}; };
} }
@ -38,7 +37,7 @@ module.exports = {
label: 'Account', label: 'Account',
fieldtype: 'Link', fieldtype: 'Link',
target: 'Account', target: 'Account',
formula: (doc) => doc.getFrom('Party', doc.customer , 'default_account'), formula: (doc) => doc.getFrom('Party', doc.customer , 'defaultAccount'),
getFilters: (query, control) => { getFilters: (query, control) => {
return { return {
keywords: ['like', query], keywords: ['like', query],
@ -145,37 +144,5 @@ module.exports = {
await form.$formModal.open(payment); await form.$formModal.open(payment);
} }
} }
], ]
listSettings: {
getFields(list) {
return ['name', 'customer', 'grandTotal', 'submitted'];
},
getRowHTML(list, data) {
return `<div class='col-3'>${list.getNameHTML(data)}</div>
<div class='col-4 text-muted'>${data.customer}</div>
<div class='col-4 text-muted text-right'>${frappe.format(data.grandTotal, 'Currency')}</div>`;
}
},
listView: {
columns: [
'customer',
{
label: 'Status',
getValue(doc) {
return doc.submitted ? 'Paid' : 'Pending';
}
},
'grandTotal',
'date',
{
label: 'INV #',
getValue(doc) {
return doc.name;
}
}
]
}
}; };

View File

@ -0,0 +1,23 @@
import { _ } from 'frappejs/utils';
export default {
doctype: 'Invoice',
title: _('Invoice'),
columns: [
'customer',
{
label: 'Status',
getValue(doc) {
return doc.submitted ? 'Paid' : 'Pending';
}
},
'grandTotal',
'date',
{
label: 'INV #',
getValue(doc) {
return doc.name;
}
}
]
}

View File

@ -80,11 +80,5 @@ module.exports = {
{ fields: ['tax'] } { fields: ['tax'] }
] ]
} }
], ]
listView: {
columns: [
'name',
'description'
]
}
}; };

View File

@ -0,0 +1,10 @@
import { _ } from 'frappejs/utils';
export default {
doctype: 'Item',
title: _('Item'),
columns: [
'name',
'description'
]
}

View File

@ -1,13 +1,12 @@
const BaseList = require('frappejs/client/view/list'); import { _ } from 'frappejs/utils';
const frappe = require('frappejs');
module.exports = class CustomerList extends BaseList { export default {
constructor({doctype, parent, fields, page}) { doctype: 'Party',
super({doctype: 'Party', parent: parent, fields: fields, page: page}); title: _('Customer'),
} columns: [
getFilters() { 'name'
let filters = super.getFilters(); ],
filters.customer = 1; filters: {
return filters; customer: 1
} }
} }

View File

@ -14,13 +14,12 @@ module.exports = {
"required": 1 "required": 1
}, },
{ {
fieldname: 'default_account', fieldname: 'defaultAccount',
label: 'Default Account', label: 'Default Account',
fieldtype: 'Link', fieldtype: 'Link',
target: 'Account', target: 'Account',
getFilters: (query, control) => { getFilters: (query, control) => {
return { return {
keywords: ['like', query],
isGroup: 0, isGroup: 0,
accountType: 'Receivable' accountType: 'Receivable'
}; };
@ -48,12 +47,5 @@ module.exports = {
}); });
} }
} }
], ]
listView: {
columns: [
'name'
]
}
} }

View File

@ -20,7 +20,7 @@ export default {
}, },
{ {
label: 'Customers', label: 'Customers',
route: '/list/Party' route: '/list/Customer'
}, },
{ {
label: 'Items', label: 'Items',

View File

@ -52,30 +52,33 @@ export default {
return frappe.getMeta(this.doctype); return frappe.getMeta(this.doctype);
} }
}, },
async created() { created() {
if (!this.name) return; this.loadDoc();
try {
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);
}
}
} catch (e) {
this.notFound = true;
}
this.setLinks();
this.doc.on('change', this.setLinks);
}, },
methods: { methods: {
async loadDoc() {
if (!this.name) return;
try {
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);
}
}
} catch (e) {
this.notFound = true;
}
this.setLinks();
this.doc.on('change', this.setLinks);
},
async save() { async save() {
this.setValidity(); this.setValidity();
if (this.isFormInvalid) return; if (this.isFormInvalid) return;
@ -132,8 +135,3 @@ export default {
} }
} }
</script> </script>
<style>
.form-container {
}
</style>

View File

@ -13,23 +13,24 @@
</div> </div>
</template> </template>
<script> <script>
import frappe from 'frappejs';
import ListRow from './ListRow'; import ListRow from './ListRow';
import ListCell from './ListCell'; import ListCell from './ListCell';
export default { export default {
name: 'List', name: 'List',
props: ['doctype'], props: ['listConfig'],
watch: {
doctype(oldValue, newValue) {
if (oldValue !== newValue) {
this.setupColumnsAndData();
}
}
},
components: { components: {
ListRow, ListRow,
ListCell ListCell
}, },
watch: {
listConfig(oldValue, newValue) {
if (oldValue.doctype !== newValue.doctype) {
this.setupColumnsAndData();
}
}
},
data() { data() {
return { return {
columns: [], columns: [],
@ -42,6 +43,9 @@ export default {
}, },
methods: { methods: {
setupColumnsAndData() { setupColumnsAndData() {
this.doctype = this.listConfig.doctype;
this.meta = frappe.getMeta(this.doctype);
this.prepareColumns(); this.prepareColumns();
this.updateData(); this.updateData();
}, },
@ -49,11 +53,10 @@ export default {
this.$router.push(`/edit/${this.doctype}/${name}`); this.$router.push(`/edit/${this.doctype}/${name}`);
}, },
async updateData(keywords) { async updateData(keywords) {
let filters = null; let filters = this.listConfig.filters || null;
if (keywords) { if (keywords) {
filters = { if (!filters) filters = {};
keywords: ['like', keywords] filters.keywords = ['like', keywords];
}
} }
this.data = await frappe.db.getAll({ this.data = await frappe.db.getAll({
doctype: this.doctype, doctype: this.doctype,
@ -62,7 +65,7 @@ export default {
}); });
}, },
prepareColumns() { prepareColumns() {
this.columns = this.meta.listView.columns.map(col => { this.columns = this.listConfig.columns.map(col => {
if (typeof col === 'string') { if (typeof col === 'string') {
const field = this.meta.getField(col); const field = this.meta.getField(col);
if (!field) return null; if (!field) return null;
@ -77,11 +80,6 @@ export default {
return col; return col;
}).filter(Boolean); }).filter(Boolean);
} }
},
computed: {
meta() {
return frappe.getMeta(this.doctype);
}
} }
}; };
</script> </script>

View File

@ -4,7 +4,7 @@
<search-input class="mr-2" @change="keyword => filterList(keyword)"/> <search-input class="mr-2" @change="keyword => filterList(keyword)"/>
</div> </div>
<div class="col-6 d-flex flex-row-reverse"> <div class="col-6 d-flex flex-row-reverse">
<f-button primary @click="$emit('newClick')">{{ _('New {0}', doctype) }}</f-button> <f-button primary @click="$emit('newClick')">{{ _('New {0}', listConfig.title) }}</f-button>
</div> </div>
</div> </div>
</template> </template>
@ -13,7 +13,7 @@ import SearchInput from '@/components/SearchInput';
export default { export default {
name: 'ListToolbar', name: 'ListToolbar',
props: ['doctype'], props: ['listConfig'],
components: { components: {
SearchInput SearchInput
}, },

View File

@ -1,15 +1,15 @@
<template> <template>
<div class="bg-light"> <div class="bg-light">
<page-header :title="meta.label || meta.name" /> <page-header :title="listConfig.title" />
<div class="px-4 py-3"> <div class="px-4 py-3">
<list-toolbar <list-toolbar
:doctype="doctype" :listConfig="listConfig"
@newClick="openNewForm" @newClick="openNewForm"
@filterList="keyword => filterList(keyword)" @filterList="keyword => filterList(keyword)"
class="mb-4" class="mb-4"
/> />
<list <list
:doctype="doctype" :listConfig="listConfig"
/> />
</div> </div>
</div> </div>
@ -20,27 +20,35 @@ import Observable from 'frappejs/utils/observable';
import PageHeader from '@/components/PageHeader'; import PageHeader from '@/components/PageHeader';
import ListToolbar from './ListToolbar'; import ListToolbar from './ListToolbar';
import List from './List'; import List from './List';
import listConfigs from './listConfig';
export default { export default {
name: 'ListView', name: 'ListView',
props: ['doctype'], props: ['listName'],
components: { components: {
PageHeader, PageHeader,
ListToolbar, ListToolbar,
List List
}, },
computed: {
meta() {
return frappe.getMeta(this.doctype);
}
},
created() { created() {
frappe.listView = new Observable(); frappe.listView = new Observable();
}, },
methods: { methods: {
async openNewForm() { async openNewForm() {
const doc = await frappe.getNewDoc(this.doctype); const doctype = this.listConfig.doctype;
this.$router.push(`/edit/${this.doctype}/${doc.name}`); const doc = await frappe.getNewDoc(doctype);
if (this.listConfig.filters) {
doc.set(this.listConfig.filters);
}
this.$router.push(`/edit/${doctype}/${doc.name}`);
doc.on('afterInsert', () => {
this.$router.push(`/edit/${doctype}/${doc.name}`);
});
}
},
computed: {
listConfig() {
return listConfigs[this.listName];
} }
} }
} }

View File

@ -0,0 +1,9 @@
import Invoice from '../../../models/doctype/Invoice/InvoiceList';
import Customer from '../../../models/doctype/Party/CustomerList';
import Item from '../../../models/doctype/Item/ItemList';
export default {
Invoice,
Customer,
Item
}

View File

@ -14,7 +14,7 @@ Vue.use(Router);
const routes = [ const routes = [
{ {
path: '/list/:doctype', path: '/list/:listName',
name: 'ListView', name: 'ListView',
component: ListView, component: ListView,
props: true props: true

View File

@ -1,5 +1,6 @@
@import "variables.scss"; @import "variables.scss";
@import "~bootstrap/scss/bootstrap"; @import "~bootstrap/scss/bootstrap";
@import "~frappe-datatable/dist/frappe-datatable.css";
html { html {
font-size: 14px; font-size: 14px;