2
0
mirror of https://github.com/frappe/books.git synced 2025-01-22 14:48:25 +00:00

[Fixes] #98 UI Issues 05-08-2019

This commit is contained in:
thefalconx33 2019-08-14 13:13:49 +05:30
parent 88021193fc
commit 54e115b030
49 changed files with 868 additions and 402 deletions

View File

@ -271,7 +271,7 @@
"currency_fraction_units": 100,
"currency_name": "Belize Dollar",
"currency_symbol": "$",
"date_format": "mm-dd-yyyy",
"date_format": "MM-dd-yyyy",
"number_format": "#,###.##",
"timezones": [
"America/Belize"
@ -356,7 +356,7 @@
"currency_fraction": "Centavo",
"currency_fraction_units": 100,
"currency_symbol": "R$",
"date_format": "dd/mm/yyyy",
"date_format": "dd/MM/yyyy",
"number_format": "#.###,##",
"timezones": [
"America/Araguaina",
@ -463,7 +463,7 @@
"currency_fraction_units": 100,
"currency_name": "Canadian Dollar",
"currency_symbol": "$",
"date_format": "mm-dd-yyyy",
"date_format": "MM-dd-yyyy",
"number_format": "#,###.##",
"timezones": [
"America/Atikokan",
@ -563,7 +563,7 @@
"code": "cn",
"currency": "CNY",
"currency_name": "Yuan Renminbi",
"date_format": "yyyy-mm-dd",
"date_format": "yyyy-MM-dd",
"number_format": "#,###.##",
"timezones": [
"Asia/Chongqing",
@ -884,7 +884,7 @@
"currency_fraction_units": 100,
"currency_symbol": "\u20ac",
"number_format": "# ###,##",
"date_format": "dd/mm/yyyy",
"date_format": "dd/MM/yyyy",
"timezones": [
"Europe/Paris"
]
@ -1136,7 +1136,7 @@
"currency_fraction_units": 100,
"currency_name": "Forint",
"currency_symbol": "Ft",
"date_format": "yyyy-mm-dd",
"date_format": "yyyy-MM-dd",
"number_format": "#.###",
"timezones": [
"Europe/Budapest"
@ -1161,6 +1161,7 @@
"currency_fraction_units": 100,
"currency_name": "Indian Rupee",
"currency_symbol": "\u20b9",
"date_format": "dd/MM/yyyy",
"number_format": "#,##,###.##",
"timezones": [
"Asia/Kolkata"
@ -1247,7 +1248,7 @@
"currency_fraction_units": 100,
"currency_symbol": "\u20ac",
"number_format": "#.###,##",
"date_format": "dd/mm/yyyy",
"date_format": "dd/MM/yyyy",
"timezones": [
"Europe/Rome"
],
@ -1471,7 +1472,7 @@
"currency_fraction_units": 100,
"currency_name": "Lithuanian Litas",
"currency_symbol": "Lt",
"date_format": "yyyy-mm-dd",
"date_format": "yyyy-MM-dd",
"number_format": "# ###,##",
"timezones": [
"Europe/Vilnius"
@ -1674,7 +1675,7 @@
"currency_fraction_units": 100,
"currency_name": "Tugrik",
"currency_symbol": "\u20ae",
"date_format": "yyyy-mm-dd",
"date_format": "yyyy-MM-dd",
"number_format": "#,###.##",
"timezones": [
"Asia/Choibalsan",
@ -1911,7 +1912,7 @@
"currency_fraction": "Cent",
"currency_fraction_units": 100,
"currency_symbol": "$",
"date_format": "mm-dd-yyyy",
"date_format": "MM-dd-yyyy",
"number_format": "#,###.##",
"timezones": [
"Pacific/Palau"
@ -1974,7 +1975,7 @@
"currency_fraction_units": 100,
"currency_name": "Philippine Peso",
"currency_symbol": "\u20b1",
"date_format": "mm-dd-yyyy",
"date_format": "MM-dd-yyyy",
"number_format": "#,###.##",
"timezones": [
"Asia/Manila"
@ -2278,7 +2279,7 @@
"currency_fraction_units": 100,
"currency_name": "Rand",
"currency_symbol": "R",
"date_format": "yyyy-mm-dd",
"date_format": "yyyy-MM-dd",
"number_format": "# ###.##",
"timezones": [
"Africa/Johannesburg"
@ -2398,7 +2399,7 @@
"Taiwan": {
"code": "tw",
"currency": "TWD",
"date_format": "yyyy-mm-dd",
"date_format": "yyyy-MM-dd",
"number_format": "#,###.##"
},
"Tajikistan": {
@ -2591,7 +2592,7 @@
"smallest_currency_fraction_value": 0.05,
"currency_name": "US Dollar",
"currency_symbol": "$",
"date_format": "mm-dd-yyyy",
"date_format": "MM-dd-yyyy",
"number_format": "#,###.##",
"timezones": [
"America/Adak",

View File

@ -13,26 +13,33 @@ module.exports = {
fieldtype: 'Data',
required: 1
},
{
fieldname: 'rootType',
label: 'Root Type',
fieldtype: 'Select',
options: [
'Select...',
'Asset',
'Liability',
'Equity',
'Income',
'Expense'
],
required: 1
},
{
fieldname: 'parentAccount',
label: 'Parent Account',
fieldtype: 'Link',
target: 'Account',
getFilters: (query, doc) => {
console.log(doc);
return {
isGroup: 1,
rootType: doc.rootType
const filter = {
isGroup: 1
};
doc.rootType ? (filter.rootType = doc.rootType) : '';
return filter;
}
},
{
fieldname: 'rootType',
label: 'Root Type',
fieldtype: 'Select',
options: ['', 'Asset', 'Liability', 'Equity', 'Income', 'Expense'],
required: 1
},
{
fieldname: 'accountType',
label: 'Account Type',

View File

@ -1,124 +1,141 @@
module.exports = {
"name": "Address",
"doctype": "DocType",
"isSingle": 0,
"keywordFields": [
"name"
],
pageSettings: {
hideTitle: true
name: 'Address',
doctype: 'DocType',
isSingle: 0,
keywordFields: ['name'],
pageSettings: {
hideTitle: true
},
fields: [
{
fieldname: 'name',
label: 'Address Title',
fieldtype: 'Data',
defaultValue: 'Work',
required: 1
},
// "naming": "autoincrement",
"fields": [
{
"fieldname": "name",
"label": "Address Title",
"fieldtype": "Data",
"required": 1
},
{
"fieldname": "addressType",
"label": "Address Type",
"fieldtype": "Select",
"options": [
"Billing", "Shipping", "Office",
"Personal", "Plant", "Postal",
"Shop", "Subsidary", "Warehouse",
"Current", "Permanent", "Other"
]
},
{
"fieldname": "addressLine1",
"label": "Address Line 1",
"fieldtype": "Data",
"required": 1
},
{
"fieldname": "addressLine2",
"label": "Address Line 2",
"fieldtype": "Data"
},
{
"fieldname": "city",
"label": "City / Town",
"fieldtype": "Data",
"required": 1
},
{
"fieldname": "state",
"label": "State",
"fieldtype": "Data"
},
{
"fieldname": "country",
"label": "Country",
"fieldtype": "Data",
"required": 1
},
{
"fieldname": "postalCode",
"label": "Postal Code",
"fieldtype": "Data"
},
{
"fieldname": "emailAddress",
"label": "Email Address",
"fieldtype": "Data"
},
{
"fieldname": "phone",
"label": "Phone",
"fieldtype": "Data"
},
{
"fieldname": "fax",
"label": "Fax",
"fieldtype": "Data"
},
{
"fieldname": "isPreferredBilling",
"label": "Preferred Billing Address",
"fieldtype": "Check"
},
{
"fieldname": "isShippingBilling",
"label": "Preferred Shipping Address",
"fieldtype": "Check"
}
],
// events: {
// validate: (doc) => {
// }
// },
listSettings: {
getFields(list) {
return ['name', 'addressType'];
},
getRowHTML(list, data) {
return `<div class="col-11">${list.getNameHTML(data)} (${data.addressType})</div>`;
}
{
fieldname: 'addressType',
label: 'Address Type',
fieldtype: 'Select',
options: [
'Billing',
'Shipping',
'Office',
'Personal',
'Plant',
'Postal',
'Shop',
'Subsidary',
'Warehouse',
'Current',
'Permanent',
'Other'
]
},
{
fieldname: 'addressLine1',
label: 'Address Line 1',
fieldtype: 'Data',
required: 1
},
{
fieldname: 'addressLine2',
label: 'Address Line 2',
fieldtype: 'Data'
},
{
fieldname: 'city',
label: 'City / Town',
fieldtype: 'Data',
required: 1
},
{
fieldname: 'state',
label: 'State',
fieldtype: 'Data'
},
{
fieldname: 'country',
label: 'Country',
fieldtype: 'Data',
required: 1
},
{
fieldname: 'postalCode',
label: 'Postal Code',
fieldtype: 'Data'
},
{
fieldname: 'emailAddress',
label: 'Email Address',
fieldtype: 'Data'
},
{
fieldname: 'phone',
label: 'Phone',
fieldtype: 'Data'
},
{
fieldname: 'fax',
label: 'Fax',
fieldtype: 'Data'
},
{
fieldname: 'isPreferredBilling',
label: 'Preferred Billing Address',
fieldtype: 'Check'
},
{
fieldname: 'isShippingBilling',
label: 'Preferred Shipping Address',
fieldtype: 'Check'
}
],
layout: [
// section 1
// events: {
// validate: (doc) => {
// }
// },
listSettings: {
getFields(list) {
return ['name', 'addressType'];
},
getRowHTML(list, data) {
return `<div class="col-11">${list.getNameHTML(data)} (${
data.addressType
})</div>`;
}
},
layout: [
// section 1
{
columns: [
{
columns: [
{
fields: [
"name", "addressType", "addressLine1",
"addressLine2", "city", "country", "state",
"postalCode"
]
},
{
fields: [
"emailAddress", "phone", "fax", "isPreferredBilling", "isShippingBilling"
]
}
]
fields: [
'name',
'addressType',
'addressLine1',
'addressLine2',
'city',
'country',
'state',
'postalCode'
]
},
{
fields: [
'emailAddress',
'phone',
'fax',
'isPreferredBilling',
'isShippingBilling'
]
}
]
}
]
}
]
};

View File

@ -0,0 +1,16 @@
module.exports = {
name: 'Color',
doctype: 'DocType',
fields: [
{
fieldname: 'name',
fieldtype: 'Data',
label: 'Color'
},
{
fieldname: 'hexvalue',
fieldtype: 'Data',
label: 'Hex Value'
}
]
};

View File

@ -12,13 +12,15 @@ module.exports = {
{
fieldname: 'type',
fieldtype: 'Select',
options: ['', 'Bar', 'Line', 'Percentage'],
label: 'Chart Type'
options: ['Bar', 'Line', 'Percentage'],
label: 'Chart Type',
defaultValue: 'Bar'
},
{
fieldname: 'color',
fieldtype: 'Data',
label: 'Color'
fieldtype: 'Link',
label: 'Color',
target: 'Color'
}
]
};

View File

@ -4,11 +4,6 @@ module.exports = {
doctype: 'DocType',
isSingle: 1,
fields: [
{
fieldname: 'name',
fieldtype: 'Data',
label: 'Dashboard Name'
},
{
fieldname: 'charts',
fieldtype: 'Table',

View File

@ -6,7 +6,7 @@
</div>
</div>
<div ref="printComponent" class="col-8 bg-white mt-4 mx-auto border shadow">
<div class="print-format" style="padding: 3.5rem;">
<div class="print-format" style="padding: 3.5rem; font-size: 8pt !important;">
<div>
<h3 class="text-center">GSTR3B-Form</h3>
<h5>GSTIN: &nbsp; {{ jsonData.gstin }}</h5>
@ -292,7 +292,6 @@ export default {
<style>
.print-format {
font-size: 8pt !important;
}
.disabled {
background-color: #d9d9d9;

View File

@ -101,5 +101,49 @@ module.exports = {
}
]
}
],
links: [
{
label: 'New Sales Invoice',
condition: form => !form.doc._notInserted,
action: async form => {
const invoice = await frappe.getNewDoc('SalesInvoice');
invoice.items = [
{
item: form.doc.name,
rate: form.doc.rate,
tax: form.doc.tax
}
];
invoice.on('afterInsert', async () => {
form.$formModal.close();
form.$router.push({
path: `/edit/PurchaseInvoice/${invoice.name}`
});
});
await form.$formModal.open(invoice);
}
},
{
label: 'New Purchase Invoice',
condition: form => !form.doc._notInserted,
action: async form => {
const invoice = await frappe.getNewDoc('PurchaseInvoice');
invoice.items = [
{
item: form.doc.name,
rate: form.doc.rate,
tax: form.doc.tax
}
];
invoice.on('afterInsert', async () => {
form.$formModal.close();
form.$router.push({
path: `/edit/PurchaseInvoice/${invoice.name}`
});
});
await form.$formModal.open(invoice);
}
}
]
};

View File

@ -2,88 +2,79 @@ const frappe = require('frappejs');
const utils = require('../../../accounting/utils');
module.exports = {
name: "JournalEntry",
doctype: "DocType",
isSingle: 0,
isChild: 0,
isSubmittable: 1,
keywordFields: ["name"],
showTitle: true,
settings: "JournalEntrySettings",
fields: [
{
fieldname: "date",
label: "Date",
fieldtype: "Date"
},
{
fieldname: "entryType",
label: "Entry Type",
fieldtype: "Select",
options: [
"Journal Entry",
"Bank Entry",
"Cash Entry",
"Credit Card Entry",
"Debit Note",
"Credit Note",
"Contra Entry",
"Excise Entry",
"Write Off Entry",
"Opening Entry",
"Depreciation Entry"
],
required: 1
},
{
fieldname: "accounts",
label: "Account Entries",
fieldtype: "Table",
childtype: "JournalEntryAccount",
required: true
},
{
fieldname: "referenceNumber",
label: "Reference Number",
fieldtype: "Data",
},
{
fieldname: "referenceDate",
label: "Reference Date",
fieldtype: "Date",
},
{
fieldname: "userRemark",
label: "User Remark",
fieldtype: "Text",
}
],
layout: [
// section 1
{
columns: [
{ fields: [ "date" ] },
{ fields: [ "entryType" ] },
]
},
// section 2
{
columns: [
{ fields: ["accounts"]},
]
},
// section 3
{
columns: [
{ fields: [ "referenceNumber"] },
{ fields: [ "referenceDate"] }
]
},
// section 4
{
columns: [{ fields: [ "userRemark" ] }],
}
]
}
label: 'Journal Entry',
name: 'JournalEntry',
doctype: 'DocType',
isSingle: 0,
isChild: 0,
isSubmittable: 1,
keywordFields: ['name'],
showTitle: true,
settings: 'JournalEntrySettings',
fields: [
{
fieldname: 'entryType',
label: 'Entry Type',
fieldtype: 'Select',
options: [
'Journal Entry',
'Bank Entry',
'Cash Entry',
'Credit Card Entry',
'Debit Note',
'Credit Note',
'Contra Entry',
'Excise Entry',
'Write Off Entry',
'Opening Entry',
'Depreciation Entry'
],
required: 1
},
{
fieldname: 'date',
label: 'Date',
fieldtype: 'Date'
},
{
fieldname: 'accounts',
label: 'Account Entries',
fieldtype: 'Table',
childtype: 'JournalEntryAccount',
required: true
},
{
fieldname: 'referenceNumber',
label: 'Reference Number',
fieldtype: 'Data'
},
{
fieldname: 'referenceDate',
label: 'Reference Date',
fieldtype: 'Date'
},
{
fieldname: 'userRemark',
label: 'User Remark',
fieldtype: 'Text'
}
],
layout: [
// section 1
{
columns: [{ fields: ['entryType'] }, { fields: ['date'] }]
},
// section 2
{
columns: [{ fields: ['accounts'] }]
},
// section 3
{
columns: [{ fields: ['referenceNumber'] }, { fields: ['referenceDate'] }]
},
// section 4
{
columns: [{ fields: ['userRemark'] }]
}
]
};

View File

@ -3,7 +3,6 @@ module.exports = {
label: 'Party',
doctype: 'DocType',
isSingle: 0,
istable: 0,
keywordFields: ['name'],
fields: [
{
@ -42,22 +41,64 @@ module.exports = {
}
],
getFormTitle(doc) {
if (doc.customer) return 'Customer';
return 'Supplier';
},
getListTitle(doc) {
if (doc.customer) return 'Customer';
return 'Supplier';
},
links: [
{
label: 'New Sales Invoice',
condition: form => form.doc.customer,
action: async form => {
const invoice = await frappe.getNewDoc('SalesInvoice');
invoice.customer = form.doc.name;
invoice.account = form.doc.defaultAccount;
invoice.on('afterInsert', async () => {
form.$formModal.close();
form.$router.push({
path: `/edit/SalesInvoice/${invoice.name}`
});
});
await form.$formModal.open(invoice);
}
},
{
label: 'Sales Invoices',
condition: form => form.doc.customer,
action: form => {
form.$router.push({
path: `/report/sales-register?&customer=${form.doc.name}`
path: `/list/SalesInvoice?customer=${form.doc.name}`
});
}
},
{
label: 'New Purchase Invoice',
condition: form => form.doc.supplier,
action: async form => {
const invoice = await frappe.getNewDoc('PurchaseInvoice');
invoice.supplier = form.doc.name;
invoice.account = form.doc.defaultAccount;
invoice.on('afterInsert', async () => {
form.$formModal.close();
form.$router.push({
path: `/edit/PurchaseInvoice/${invoice.name}`
});
});
await form.$formModal.open(invoice);
}
},
{
label: 'Purchase Invoices',
condition: form => form.doc.supplier,
action: form => {
form.$router.push({
path: `/report/purchase-register?&supplier=${form.doc.name}`
path: `/list/PurchaseInvoice?supplier=${form.doc.name}`
});
}
},

View File

@ -0,0 +1,7 @@
import { _ } from 'frappejs/utils';
export default {
doctype: 'Party',
title: filters => (filters.customer ? 'Customer' : 'Supplier'),
columns: ['name', 'defaultAccount', 'address']
};

View File

@ -9,12 +9,6 @@ module.exports = {
keywordFields: [],
settings: 'PaymentSettings',
fields: [
{
fieldname: 'date',
label: 'Posting Date',
fieldtype: 'Date'
// default: new Date().toISOString().substring(0, 10)
},
{
fieldname: 'party',
label: 'Party',
@ -22,6 +16,12 @@ module.exports = {
target: 'Party',
required: 1
},
{
fieldname: 'date',
label: 'Posting Date',
fieldtype: 'Date',
defaultValue: new Date().toISOString()
},
{
fieldname: 'account',
label: 'From Account',
@ -95,7 +95,10 @@ module.exports = {
fieldtype: 'Currency',
required: 1,
disabled: true,
formula: doc => doc.getSum('for', 'amount')
formula: doc => {
console.log(doc.getSum('for', 'amount'));
return frappe.format(doc.getSum('for', 'amount'), 'Currency');
}
},
{
fieldname: 'writeoff',
@ -115,10 +118,10 @@ module.exports = {
{
columns: [
{
fields: ['date', 'account']
fields: ['party', 'account']
},
{
fields: ['party', 'paymentAccount']
fields: ['date', 'paymentAccount']
}
]
},

View File

@ -7,7 +7,11 @@ export default {
columns: [
'party',
{
label: 'Payment',
label: 'Status',
fieldname: 'status',
fieldtype: 'Select',
size: 'small',
options: ['Status...', 'Reconciled', 'Not Reconciled'],
getValue(doc) {
if (
doc.submitted === 1 &&
@ -27,10 +31,9 @@ export default {
return indicators.ORANGE;
}
},
'account',
'amount',
'paymentType',
'date',
'clearanceDate',
'name'
'amount'
]
};

View File

@ -1,28 +1,31 @@
module.exports = {
name: "PaymentFor",
label: "Payment For",
isSingle: 0,
isChild: 1,
keywordFields: [],
fields: [
{
fieldname: "referenceType",
label: "Reference Type",
fieldtype: "Data",
required: 1
},
{
fieldname: "referenceName",
label: "Reference Name",
fieldtype: "DynamicLink",
references: "referenceType",
required: 1
},
{
fieldname: "amount",
label: "Amount",
fieldtype: "Currency",
required: 1
},
]
}
name: 'PaymentFor',
label: 'Payment For',
isSingle: 0,
isChild: 1,
keywordFields: [],
fields: [
{
fieldname: 'referenceType',
label: 'Reference Type',
fieldtype: 'Data',
required: 1
},
{
fieldname: 'referenceName',
label: 'Reference Name',
fieldtype: 'DynamicLink',
references: 'referenceType',
required: 1
},
{
fieldname: 'amount',
label: 'Amount',
fieldtype: 'Currency',
formula: (row, doc) => {
doc.getFrom(doc.referenceType, doc.referenceName, 'grandTotal');
},
required: 1
}
]
};

View File

@ -16,7 +16,8 @@ module.exports = {
{
fieldname: 'date',
label: 'Date',
fieldtype: 'Date'
fieldtype: 'Date',
defaultValue: new Date().toISOString()
},
{
fieldname: 'supplier',

View File

@ -8,6 +8,10 @@ export default {
'supplier',
{
label: 'Status',
fieldname: 'status',
fieldtype: 'Select',
size: 'small',
options: ['Status...', 'Paid', 'Pending'],
getValue(doc) {
if (doc.submitted === 1 && doc.outstandingAmount === 0.0) {
return 'Paid';
@ -21,8 +25,8 @@ export default {
return indicators.ORANGE;
}
},
'grandTotal',
'date',
'grandTotal',
'outstandingAmount'
]
};

View File

@ -19,8 +19,8 @@ module.exports = {
{
fieldname: 'date',
label: 'Date',
fieldtype: 'Date'
// default: (new Date()).toISOString()
fieldtype: 'Date',
defaultValue: new Date().toISOString()
},
{
fieldname: 'customer',
@ -70,7 +70,7 @@ module.exports = {
fieldname: 'netTotal',
label: 'Net Total',
fieldtype: 'Currency',
formula: doc => doc.getSum('items', 'amount'),
formula: doc => frappe.format(doc.getSum('items', 'amount'), 'Currency'),
disabled: true,
readOnly: 1
},

View File

@ -68,13 +68,14 @@ module.exports = class SalesInvoice extends BaseDocument {
getGrandTotal() {
this.makeTaxSummary();
let grandTotal = this.netTotal;
let grandTotal = frappe.parseNumber(this.netTotal);
if (this.taxes) {
for (let row of this.taxes) {
grandTotal += row.amount;
}
}
grandTotal = Math.floor(grandTotal * 100) / 100;
return grandTotal;
return frappe.format(grandTotal, 'Currency');
}
};

View File

@ -8,6 +8,10 @@ export default {
'customer',
{
label: 'Status',
fieldname: 'status',
fieldtype: 'Select',
size: 'small',
options: ['Status..', 'Paid', 'Pending'],
getValue(doc) {
if (doc.submitted === 1 && doc.outstandingAmount === 0.0) {
return 'Paid';
@ -21,8 +25,8 @@ export default {
return indicators.ORANGE;
}
},
'grandTotal',
'date',
'grandTotal',
'outstandingAmount'
]
};

View File

@ -17,10 +17,18 @@
@changeColor="changeColor($event)"
@changeTemplate="changeTemplate($event)"
@changeFont="changeFont($event)"
@updateTemplateView="updateTemplateView"
/>
</div>
<div class="col-8 bg-white mt-4 mx-auto border shadow" ref="printComponent">
<component :themeColor="themeColor" :font="font" :is="template" v-if="doc" :doc="doc" />
<component
:themeColor="themeColor"
:font="font"
:is="template"
v-if="doc"
:doc="doc"
:key="usedForReRender"
/>
</div>
</div>
</div>
@ -48,7 +56,8 @@ export default {
showInvoiceCustomizer: false,
themeColor: undefined,
template: undefined,
font: undefined
font: undefined,
usedForReRender: 0
};
},
async created() {
@ -76,14 +85,17 @@ export default {
await this.loadInvoice();
this.showInvoiceCustomizer = !this.showInvoiceCustomizer;
},
async changeColor(color) {
changeColor(color) {
this.themeColor = color;
},
async changeTemplate(template) {
changeTemplate(template) {
this.template = invoiceTemplates[template];
},
async changeFont(font) {
changeFont(font) {
this.font = font;
},
updateTemplateView() {
this.usedForReRender += 1;
}
}
};

View File

@ -20,7 +20,7 @@ module.exports = {
fieldtype: 'Select',
options: ['Basic I', 'Basic II', 'Modern'],
required: 1,
default: 'Basic I'
defaultValue: 'Basic I'
},
{
fieldname: 'font',
@ -28,14 +28,14 @@ module.exports = {
fieldtype: 'Select',
options: ['Montserrat', 'Open Sans', 'Oxygen', 'Merriweather'],
required: 1,
default: 'Montserrat'
defaultValue: 'Montserrat'
},
{
fieldname: 'themeColor',
label: 'Theme Color',
fieldtype: 'Data',
required: 1,
default: '#000000',
defaultValue: '#000000',
hidden: 1
}
]

View File

@ -3,6 +3,7 @@ module.exports = {
SetupWizard: require('./doctype/SetupWizard/SetupWizard'),
DashboardSettings: require('./doctype/DashboardSettings/DashboardSettings'),
DashboardChart: require('./doctype/DashboardChart/DashboardChart'),
Color: require('./doctype/Color/Color'),
Account: require('./doctype/Account/Account.js'),
AccountingSettings: require('./doctype/AccountingSettings/AccountingSettings'),
CompanySettings: require('./doctype/CompanySettings/CompanySettings'),

View File

@ -2,6 +2,8 @@ const frappe = require('frappejs');
class BankReconciliation {
async run(params) {
if (!Object.keys(params).length) return [];
const filters = {};
if (params.paymentAccount) filters.paymentAccount = params.paymentAccount;
if (params.party) filters.party = params.party;

View File

@ -6,7 +6,9 @@ module.exports = {
{
fieldtype: 'Link',
target: 'Account',
label: 'Payement Account',
size: 'small',
placeholder: 'Payment Account',
label: 'Payment Account',
fieldname: 'paymentAccount',
getFilters: () => {
return {
@ -18,20 +20,36 @@ module.exports = {
{
fieldtype: 'Link',
target: 'Party',
size: 'small',
label: 'Party',
placeholder: 'Party',
fieldname: 'party'
},
{
fieldtype: 'Date',
size: 'small',
placeholder: 'From Date',
label: 'From Date',
fieldname: 'fromDate'
},
{
fieldtype: 'Date',
size: 'small',
placeholder: 'To Date',
label: 'To Date',
fieldname: 'toDate'
}
],
linkFields: [
{
label: 'Clear Filters',
type: 'secondary',
action: async report => {
await report.getReportData({});
report.usedToReRender += 1;
}
}
],
getColumns() {
return [
{

View File

@ -2,6 +2,8 @@ const frappe = require('frappejs');
class GeneralLedger {
async run(params) {
if (!Object.keys(params).length) return [];
const filters = {};
if (params.account) filters.account = params.account;
if (params.party) filters.party = params.party;

View File

@ -5,12 +5,15 @@ const viewConfig = {
filterFields: [
{
fieldtype: 'Select',
options: ['', 'SalesInvoice', 'Payment', 'PurchaseInvoice'],
options: ['Select...', 'SalesInvoice', 'Payment', 'PurchaseInvoice'],
size: 'small',
label: 'Reference Type',
fieldname: 'referenceType'
},
{
fieldtype: 'DynamicLink',
size: 'small',
placeholder: 'Reference Name',
references: 'referenceType',
label: 'Reference Name',
fieldname: 'referenceName'
@ -18,6 +21,8 @@ const viewConfig = {
{
fieldtype: 'Link',
target: 'Account',
size: 'small',
placeholder: 'Account',
label: 'Account',
fieldname: 'account'
},
@ -25,21 +30,35 @@ const viewConfig = {
fieldtype: 'Link',
target: 'Party',
label: 'Party',
size: 'small',
placeholder: 'Party',
fieldname: 'party'
},
{
fieldtype: 'Date',
size: 'small',
placeholder: 'From Date',
label: 'From Date',
fieldname: 'fromDate'
},
{
fieldtype: 'Date',
size: 'small',
placeholder: 'To Date',
label: 'To Date',
fieldname: 'toDate'
}
],
method: 'general-ledger',
linkFields: [
{
label: 'Clear Filters',
type: 'secondary',
action: async report => {
await report.getReportData({});
report.usedToReRender += 1;
}
},
{
label: 'Export',
type: 'primary',
@ -70,13 +89,6 @@ const viewConfig = {
props: await getReportDetails()
});
}
},
{
label: 'Clear Filters',
type: 'secondary',
action: async report => {
await report.$router.push(`/report/general-ledger`);
}
}
],
getColumns() {

View File

@ -10,29 +10,29 @@ module.exports = {
'B2C-Large',
'B2C-Small',
'Nil Rated, Exempted and Non GST supplies'
]
],
size: 'small'
},
{
fieldtype: 'Data',
label: 'Place',
size: 'small',
placeholder: 'Place',
fieldname: 'place'
},
{
fieldtype: 'Date',
label: 'From Date',
size: 'small',
placeholder: 'From Date',
fieldname: 'fromDate'
},
{
fieldtype: 'Date',
label: 'To Date',
size: 'small',
placeholder: 'To Date',
fieldname: 'toDate'
},
{
fieldtype: 'Select',
label: 'Report Type',
fieldname: 'reportType',
options: ['', 'GSTR-1', 'GSTR-2', 'GSTR-3B'],
hidden: 1
}
],
linkFields: [
@ -66,6 +66,14 @@ module.exports = {
props: await getReportDetails()
});
}
},
{
label: 'Clear Filters',
type: 'secondary',
action: async report => {
await report.getReportData({});
report.usedToReRender += 1;
}
}
],

View File

@ -2,6 +2,8 @@ const BaseGSTR = require('./BaseGSTR');
class GSTR1 extends BaseGSTR {
async run(params) {
if (!Object.keys(params).length) return [];
let filters = {};
if (params.toDate || params.fromDate) {
filters.date = [];

View File

@ -2,6 +2,8 @@ const BaseGSTR = require('./BaseGSTR');
class GSTR2 extends BaseGSTR {
async run(params) {
if (!Object.keys(params).length) return [];
let filters = {};
if (params.toDate || params.fromDate) {
filters.date = [];

View File

@ -2,6 +2,8 @@ const frappe = require('frappejs');
class PurchaseRegister {
async run({ fromDate, toDate, supplier }) {
if (!fromDate && !toDate && !supplier) return { rows: [] };
let filters = {};
if (supplier) {
filters.supplier = supplier;

View File

@ -8,6 +8,8 @@ module.exports = {
target: 'Party',
label: 'Supplier Name',
fieldname: 'supplier',
size: 'small',
placeholder: 'Supplier Name',
getFilters: query => {
if (query)
return {
@ -23,10 +25,29 @@ module.exports = {
{
fieldtype: 'Date',
fieldname: 'fromDate',
size: 'small',
placeholder: 'From Date',
label: 'From Date',
required: 1
},
{ fieldtype: 'Date', fieldname: 'toDate', label: 'To Date', required: 1 }
{
fieldtype: 'Date',
size: 'small',
placeholder: 'To Date',
fieldname: 'toDate',
label: 'To Date',
required: 1
}
],
linkFields: [
{
label: 'Clear Filters',
type: 'secondary',
action: async report => {
await report.getReportData({});
report.usedToReRender += 1;
}
}
],
getColumns() {
return [

View File

@ -2,6 +2,8 @@ const frappe = require('frappejs');
class SalesRegister {
async run({ fromDate, toDate, customer }) {
if (!fromDate && !toDate && !customer) return { rows: [] };
let filters = {};
if (customer) {
filters.customer = customer;

View File

@ -7,6 +7,8 @@ module.exports = {
fieldtype: 'Link',
target: 'Party',
label: 'Customer Name',
size: 'small',
placeholder: 'Customer Name',
fieldname: 'customer',
getFilters: query => {
if (query)
@ -23,10 +25,29 @@ module.exports = {
{
fieldtype: 'Date',
fieldname: 'fromDate',
size: 'small',
placeholder: 'From Date',
label: 'From Date',
required: 1
},
{ fieldtype: 'Date', fieldname: 'toDate', label: 'To Date', required: 1 }
{
fieldtype: 'Date',
size: 'small',
placeholder: 'To Date',
fieldname: 'toDate',
label: 'To Date',
required: 1
}
],
linkFields: [
{
label: 'Clear Filters',
type: 'secondary',
action: async report => {
await report.getReportData({});
report.usedToReRender += 1;
}
}
],
getColumns() {
return [

View File

@ -5,6 +5,9 @@ const {
module.exports = class TrialBalance {
async run({ fromDate, toDate }) {
if (!fromDate && !toDate) {
return { rows: [] };
}
const promises = ['Asset', 'Expense', 'Income', 'Liability', 'Equity'].map(
rootType => {
return getTrialBalance({ rootType, fromDate, toDate });

View File

@ -8,9 +8,28 @@ module.exports = {
fieldtype: 'Date',
fieldname: 'fromDate',
label: 'From Date',
size: 'small',
placeholder: 'From Date',
required: 1
},
{ fieldtype: 'Date', fieldname: 'toDate', label: 'To Date', required: 1 }
{
fieldtype: 'Date',
size: 'small',
placeholder: 'To Date',
fieldname: 'toDate',
label: 'To Date',
required: 1
}
],
linkFields: [
{
label: 'Clear Filters',
type: 'secondary',
action: async report => {
await report.getReportData({});
report.usedToReRender += 1;
}
}
],
getColumns(data) {
const columns = [

View File

@ -12,7 +12,10 @@
<div class="row">
<div class="col-12 mt-4">
<form-layout :doc="doc" :fields="fields" @updateDoc="saveDoc" />
<sketch-picker v-model="color" />
<sketch-picker v-model="color" class="shadow-none" />
<div class="mt-3">
<f-button secondary @click="openCompanySettings">{{ _('Company Settings') }}</f-button>
</div>
</div>
</div>
</div>
@ -56,6 +59,14 @@ export default {
this.doc.themeColor = this.color.hex;
await this.doc.update();
this.$emit('closeInvoiceCustomizer');
},
async openCompanySettings() {
const settings = await frappe.getSingle('CompanySettings');
settings.on('afterSave', async () => {
this.$formModal.close();
this.$emit('updateTemplateView');
});
this.$formModal.open(settings);
}
},
watch: {

View File

@ -4,13 +4,17 @@
>
<h5 class="m-0" v-if="title">{{ title }}</h5>
<div v-if="breadcrumbs">
<a v-for="(item, index) in clickableBreadcrumbs" :key="index" :href="item.route">
<h5 class="breadCrumbRoute">
{{ item.title }}
<feather-icon name="chevron-right" style="color: #212529 !important;"></feather-icon>
</h5>
</a>
<h5 class="breadCrumbRoute">{{ lastBreadcrumb.title }}</h5>
<span v-for="(item, index) in breadcrumbs" :key="index">
<a v-if="item.route.length != 0" :href="item.route">
<h5 class="breadCrumbRoute">{{ item.title }}</h5>
</a>
<h5 v-else class="breadCrumbRoute">{{ item.title }}</h5>
<feather-icon
v-if="index != breadcrumbs.length - 1"
name="chevron-right"
style="color: #212529 !important;"
></feather-icon>
</span>
</div>
<div class="col-4 p-1">
<SearchBar />
@ -40,7 +44,7 @@ export default {
.page-header {
position: sticky;
top: 0;
z-index: 1;
z-index: 10;
}
.breadCrumbRoute {
display: inline;

View File

@ -64,8 +64,29 @@ export default {
this.companyName = await sidebarConfig.getTitle();
this.dbFileName = await sidebarConfig.getDbName();
this.groups = sidebarConfig.getGroups();
this.setActive();
},
methods: {
setActive() {
let currentRoute = this.$route.fullPath;
// check each group items
this.groups.forEach(title => {
// filter items which contains the current route
sidebarConfig.getItems(title).filter(item => {
// check for substring 'list' 'SalesInvoice' etc.
let found = true;
currentRoute.split('/').forEach(str => {
if (str.length) {
item.route.indexOf(str) != -1 ? '' : (found = false);
}
});
if (found) {
this.toggleGroup(title);
}
return found;
});
});
},
isCurrentRoute(route) {
if (this.activeGroup) return false;
return this.$route.fullPath === route;
@ -100,6 +121,7 @@ export default {
}
.page-sidebar {
height: 100vh;
min-width: 208px;
}
.sidebar-item {

View File

@ -74,17 +74,75 @@ import Toasted from 'vue-toasted';
});
await doc.update();
const systemSettings = await frappe.getSingle('SystemSettings');
await systemSettings.set({
dateFormat: countryList[country]['date_format'] || 'yyyy-MM-dd'
});
await systemSettings.update();
await setupAccountsAndDashboard(bankName);
await setupRegionalChanges(country);
frappe.events.trigger('show-desk');
});
async function setupAccountsAndDashboard(bankName) {
await frappe.call({
method: 'import-coa'
});
const accountDoc = await frappe.newDoc({
doctype: 'Account'
});
Object.assign(accountDoc, {
name: bankName,
rootType: 'Asset',
parentAccount: 'Bank Accounts',
accountType: 'Bank'
});
accountDoc.insert();
const dashboardSettings = await frappe.getSingle('DashboardSettings');
const accounts = await frappe.db.getAll({
doctype: 'Account',
filters: { parentAccount: ['in', ['', undefined, null]] }
});
const colors = [
{ name: 'Red', hexvalue: '#d32f2f' },
{ name: 'Green', hexvalue: '#388e3c' },
{ name: 'Blue', hexvalue: '#0288d1' },
{ name: 'Yellow', hexvalue: '#cddc39' }
];
colors.forEach(async color => {
const c = await frappe.newDoc({ doctype: 'Color' });
c.set(color);
c.insert();
});
let charts = [];
accounts.forEach(account => {
charts.push({
account: account.name,
type: 'Bar',
color: colors[Math.floor(Math.random() * 4)].name
});
});
await dashboardSettings.set({
charts
});
await dashboardSettings.update();
}
async function setupRegionalChanges(country) {
const generateRegionalTaxes = require('../models/doctype/Tax/RegionalChanges');
await generateRegionalTaxes(country);
if (country === 'India') {
frappe.models.Party = require('../models/doctype/Party/RegionalChanges');
await frappe.db.migrate();
}
frappe.events.trigger('show-desk');
});
}
async function connectToLocalDatabase(filepath) {
try {

View File

@ -32,7 +32,7 @@ export default {
this.chartData.push({
title: c.account,
type: c.type.toLowerCase(),
color: c.color,
color: await frappe.db.getValue('Color', c.color, 'hexvalue'),
data: {
labels,
datasets

View File

@ -56,14 +56,8 @@ export default {
if (this.doc)
return [
{
title: this.meta.label || this.doctype,
route: '#/list/' + this.doctype
},
{
title: this.doc._notInserted
? 'New ' + (this.meta.label || this.doctype)
: this.doc.name,
route: ''
title: this.getFormTitle(),
route: '#/list/' + this.getListTitle()
}
];
},
@ -75,6 +69,13 @@ export default {
}
},
created() {
if (!this.defaults) {
this.defaults = {};
}
this.meta.fields.map(field => {
if (field.defaultValue)
this.defaults[field.fieldname] = field.defaultValue;
});
this.loadDoc();
},
methods: {
@ -94,9 +95,9 @@ export default {
this.doc.set('name', '');
}
if (this.defaultValues) {
for (let fieldname in this.defaultValues) {
const value = this.defaultValues[fieldname];
if (this.defaults) {
for (let fieldname in this.defaults) {
const value = this.defaults[fieldname];
this.doc.set(fieldname, value);
}
}
@ -105,9 +106,25 @@ export default {
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.
}
},
getFormTitle() {
try {
// For different list/form based on same doctype since they will have different title
return (
this.meta.getFormTitle(this.doc) || this.meta.label || this.doctype
);
} catch (e) {
return this.meta.label || this.doctype;
}
},
getListTitle() {
try {
// For different list/form based on same doctype
// Since they will have different list route
return this.meta.getListTitle(this.doc);
} catch (e) {
return this.doctype;
}
},
async save() {

View File

@ -1,12 +1,19 @@
<template>
<div class="list-container">
<list-row class="text-muted rounded-top bg-light">
<list-cell v-for="column in columns" :key="column.label">{{ column.label }}</list-cell>
<list-cell
v-for="column in columns"
:key="column.label"
:class="['Float', 'Currency'].includes(column.fieldtype) ? 'text-right':''"
>{{ column.label }}</list-cell>
</list-row>
<list-row v-for="doc in data" :key="doc.name" @click.native="openForm(doc.name)">
<list-cell v-for="column in columns" :key="column.label" class="d-flex align-items-center">
<indicator v-if="column.getIndicator" :color="column.getIndicator(doc)" class="mr-2" />
<span>{{ frappe.format(column.getValue(doc), column.fieldtype || {}) }}</span>
<span
style="width: 100%"
:class="['Float', 'Currency'].includes(column.fieldtype) ? 'text-right':''"
>{{ frappe.format(column.getValue(doc), column.fieldtype || {}) }}</span>
</list-cell>
</list-row>
</div>
@ -18,28 +25,31 @@ import ListCell from './ListCell';
export default {
name: 'List',
props: ['listConfig'],
props: ['listConfig', 'filters'],
components: {
ListRow,
ListCell
},
watch: {
listConfig(oldValue, newValue) {
if (
oldValue.doctype !== newValue.doctype ||
// To differntiate Customer and Supplier List based on same Party Doctype
oldValue.title !== newValue.title
) {
if (oldValue.doctype !== newValue.doctype) {
this.setupColumnsAndData();
}
}
},
data() {
return {
columns: [],
data: []
};
},
computed: {
columns() {
return this.prepareColumns();
},
meta() {
return frappe.getMeta(this.listConfig.doctype);
}
},
async mounted() {
await this.setupColumnsAndData();
frappe.listView.on('filterList', this.updateData.bind(this));
@ -47,28 +57,40 @@ export default {
methods: {
async setupColumnsAndData() {
this.doctype = this.listConfig.doctype;
this.meta = frappe.getMeta(this.doctype);
await this.prepareColumns();
await this.updateData();
},
openForm(name) {
this.$router.push(`/edit/${this.doctype}/${name}`);
},
async updateData(keywords) {
let filters = this.listConfig.filters || null;
if (keywords) {
if (!filters) filters = {};
filters.keywords = ['like', keywords];
}
async updateData(filters) {
if (!filters) filters = this.getFilters();
// since passing filters as URL params which is String
filters = this.formatFilters(filters);
this.data = await frappe.db.getAll({
doctype: this.doctype,
fields: ['*'],
filters
});
},
getFilters() {
let filters = {};
Object.assign(filters, this.listConfig.filters || {});
Object.assign(filters, this.filters);
return filters;
},
formatFilters(filters) {
for (let key in filters) {
let value = filters[key];
this.meta.fields.forEach(field => {
if (field.fieldname === key) {
filters[key] = frappe.format(value, field.fieldtype);
}
});
}
return filters;
},
prepareColumns() {
this.columns = this.listConfig.columns
return this.listConfig.columns
.map(col => {
if (typeof col === 'string') {
const field = this.meta.getField(col);

View File

@ -0,0 +1,45 @@
<template>
<div :key="usedToReRender">
<div
class="mr-2 d-flex"
v-for="filter in Object.keys(currentFilters)"
:key="filter"
style="user-select: none; "
>
<span
class="p-0 pl-2 py-1 badge badge-light border lead d-flex align-items-center font-weight-normal"
>
{{ filter }} = "{{ currentFilters[filter] }}"
<feather-icon class="mb-1 mx-2" name="x" @click.native="removeFilter(filter)" />
</span>
</div>
</div>
</template>
<script>
export default {
name: 'ListFilters',
props: ['filters'],
data() {
return {
currentFilters: this.filters,
usedToReRender: 0
};
},
computed: {
filterValues() {
return this.currentFilters;
}
},
methods: {
removeFilter(filter) {
delete this.currentFilters[filter];
frappe.listView.trigger('filterList', this.currentFilters);
this.usedToReRender += 1;
}
}
};
</script>
<style scoped>
</style>

View File

@ -1,26 +1,23 @@
<template>
<div class="row">
<div class="col-6 d-flex">
<!-- <search-bar class="mr-2" @change="keyword => filterList(keyword)" /> -->
<div class="d-flex mt-2">
<div style="flex: 1;">
<list-filters :filters="filters"></list-filters>
</div>
<div class="col-6 d-flex flex-row-reverse">
<f-button primary @click="$emit('newClick')">{{ _('New {0}', listConfig.title) }}</f-button>
<div class="d-flex flex-column-reverse" style="padding-bottom: 1rem;">
<f-button primary @click="$emit('newClick')">{{ _('New {0}', title) }}</f-button>
</div>
</div>
</template>
<script>
import SearchBar from '@/components/SearchBar';
import ListFilters from './ListFilters';
export default {
name: 'ListToolbar',
props: ['listConfig'],
props: ['title', 'filters'],
components: {
SearchBar
},
methods: {
filterList(keyword) {
frappe.listView.trigger('filterList', keyword);
}
ListFilters
}
};
</script>

View File

@ -1,14 +1,9 @@
<template>
<div class="bg-white">
<page-header :title="listConfig.title" />
<page-header :title="title" />
<div class="px-4 py-3">
<list-toolbar
:listConfig="listConfig"
@newClick="openNewForm"
@filterList="keyword => filterList(keyword)"
class="mb-4"
/>
<list :listConfig="listConfig" />
<list-toolbar :title="title" :filters="filters" @newClick="openNewForm" class="mb-2" />
<list :listConfig="listConfig" :filters="filters" />
</div>
</div>
</template>
@ -22,7 +17,7 @@ import listConfigs from './listConfig';
export default {
name: 'ListView',
props: ['listName'],
props: ['listName', 'filters'],
components: {
PageHeader,
ListToolbar,
@ -38,6 +33,9 @@ export default {
if (this.listConfig.filters) {
doc.set(this.listConfig.filters);
}
if (this.filters) {
doc.set(this.filters);
}
this.$router.push(`/edit/${doctype}/${doc.name}`);
doc.on('afterInsert', () => {
this.$router.push(`/edit/${doctype}/${doc.name}`);
@ -58,6 +56,13 @@ export default {
});
this.$router.go(-1);
}
},
title() {
try {
return this.listConfig.title(this.filters);
} catch (e) {
return this.listConfig.title;
}
}
}
};

View File

@ -1,11 +1,11 @@
<template>
<div>
<div class="px-3">
<div class="row pb-4 d-flex">
<div>
<div class="pb-4 d-flex">
<page-header :breadcrumbs="breadcrumbs" style="flex-grow: 1;" />
<report-links class="d-flex flex-row-reverse" v-if="linksExists" :links="links"></report-links>
</div>
<div class="row pb-4 pl-1">
<div class="pl-1">
<report-filters
class="col-12"
v-if="shouldRenderFields"
@ -13,9 +13,10 @@
:filterDoc="filterDoc"
:filterDefaults="filters"
@change="getReportData"
:key="usedToReRender"
></report-filters>
</div>
<div class="pt-2 pr-2 pl-2" ref="datatable" v-once></div>
<div class="pt-2 px-4" ref="datatable" v-once></div>
</div>
<not-found v-if="!reportConfig" />
</div>
@ -34,6 +35,7 @@ export default {
data() {
return {
currentFilters: this.filters,
usedToReRender: 0,
filterDoc: undefined,
links: []
};
@ -43,7 +45,7 @@ export default {
return [
{
title: 'Reports',
route: '#/reportList'
route: ''
},
{
title: this.reportConfig.title,
@ -94,14 +96,22 @@ export default {
}
if (this.datatable) {
if (rows.length) this.datatable.refresh(rows, columns);
if (rows.length) {
this.datatable.refresh(rows, columns);
} else {
// remove all rows form datatable
this.datatable.wrapper.innerHTML = '';
this.datatable = undefined;
}
} else {
this.datatable = new DataTable(this.$refs.datatable, {
columns: columns,
data: rows,
treeView: this.reportConfig.treeView || false,
cellHeight: 35
});
if (rows.length) {
this.datatable = new DataTable(this.$refs.datatable, {
columns: columns,
data: rows,
treeView: this.reportConfig.treeView || false,
cellHeight: 35
});
}
}
return [rows, columns];
},

View File

@ -1,9 +1,9 @@
<template>
<div>
<page-header title="Settings" />
<div class="row">
<div class="col-12 bg-white border p-5">
<div class="col-9 col-lg-6 ml-1">
<div>
<div class="col-9 col-lg-7 col-xl-6 mx-2 mt-4">
<div>
<setting-section doctype="AccountingSettings" />
<hr class="mt-4" />
<setting-section doctype="CompanySettings" />

View File

@ -15,7 +15,7 @@
:doc="doc"
:fields="fields"
:layout="layout"
:currentSection="currentSection"
:currentSection="compCurrentSection"
/>
<div class="d-flex justify-content-between">
<div>
@ -80,6 +80,9 @@ export default {
}
},
computed: {
compCurrentSection() {
return this.currentSection;
},
fields() {
return this.meta.fields;
},

View File

@ -29,7 +29,13 @@ const routes = [
path: '/list/:listName',
name: 'ListView',
component: ListView,
props: true
props: route => {
const { listName } = route.params;
return {
listName,
filters: route.query
};
}
},
{
path: '/edit/:doctype/:name',