2
0
mirror of https://github.com/frappe/books.git synced 2024-12-23 03:19:01 +00:00

refactor models are now js and better file naming for models

This commit is contained in:
Rushabh Mehta 2018-02-16 18:43:46 +05:30
parent cb446ba49f
commit 2422e33ec0
54 changed files with 320 additions and 476 deletions

2
.gitignore vendored
View File

@ -1,7 +1,7 @@
node_modules node_modules
.DS_Store .DS_Store
Thumbs.db Thumbs.db
test.db *test.db
*.log *.log
.cache .cache

2
app.js
View File

@ -2,5 +2,5 @@ const server = require('frappejs/server');
server.start({ server.start({
backend: 'sqllite', backend: 'sqllite',
connection_params: {dbPath: 'test.db'} connectionParams: {dbPath: 'test.db'}
}); });

View File

@ -14,16 +14,14 @@ module.exports = class Database {
} }
async migrate() { async migrate() {
for (let doctype in frappe.modules) { for (let doctype in frappe.models) {
// check if controller module // check if controller module
if (frappe.modules[doctype].Meta) { let meta = frappe.getMeta(doctype);
let meta = frappe.getMeta(doctype); if (!meta.isSingle) {
if (!meta.isSingle) { if (await this.tableExists(doctype)) {
if (await this.tableExists(doctype)) { await this.alterTable(doctype);
await this.alterTable(doctype); } else {
} else { await this.createTable(doctype);
await this.createTable(doctype);
}
} }
} }
} }
@ -53,7 +51,7 @@ module.exports = class Database {
} }
getColumnDefinition(df) { getColumnDefinition(df) {
return `${df.fieldname} ${this.type_map[df.fieldtype]} ${df.required && !df.default ? "not null" : ""} ${df.default ? `default ${df.default}` : ""}` // return `${df.fieldname} ${this.type_map[df.fieldtype]} ${ ? "PRIMARY KEY" : ""} ${df.required && !df.default ? "NOT NULL" : ""} ${df.default ? `DEFAULT ${df.default}` : ""}`
} }
async alterTable(doctype) { async alterTable(doctype) {
@ -89,7 +87,7 @@ module.exports = class Database {
doc.name = doctype; doc.name = doctype;
} else { } else {
if (!name) { if (!name) {
throw frappe.errors.ValueError('name is mandatory'); throw new frappe.errors.ValueError('name is mandatory');
} }
doc = await this.getOne(doctype, name, fields); doc = await this.getOne(doctype, name, fields);
} }
@ -113,7 +111,7 @@ module.exports = class Database {
async getSingle(doctype) { async getSingle(doctype) {
let values = await this.getAll({ let values = await this.getAll({
doctype: 'Single Value', doctype: 'SingleValue',
fields: ['fieldname', 'value'], fields: ['fieldname', 'value'],
filters: { parent: doctype }, filters: { parent: doctype },
order_by: 'fieldname', order_by: 'fieldname',
@ -217,7 +215,7 @@ module.exports = class Database {
let value = doc[field.fieldname]; let value = doc[field.fieldname];
if (value) { if (value) {
let singleValue = frappe.newDoc({ let singleValue = frappe.newDoc({
doctype: 'Single Value', doctype: 'SingleValue',
parent: doctype, parent: doctype,
fieldname: field.fieldname, fieldname: field.fieldname,
value: value value: value
@ -228,7 +226,7 @@ module.exports = class Database {
} }
async deleteSingleValues(name) { async deleteSingleValues(name) {
// await frappe.db.run('delete from single_value where parent=?', name) // await frappe.db.run('delete from SingleValue where parent=?', name)
} }
prepareChild(parenttype, parent, child, field, idx) { prepareChild(parenttype, parent, child, field, idx) {
@ -275,7 +273,7 @@ module.exports = class Database {
// delete children // delete children
let tableFields = frappe.getMeta(doctype).getTableFields(); let tableFields = frappe.getMeta(doctype).getTableFields();
for (let field of tableFields) { for (let field of tableFields) {
await this.deleteChildren(frappe.slug(field.childtype), name); await this.deleteChildren(field.childtype, name);
} }
} }

View File

@ -45,7 +45,7 @@ module.exports = class mysqlDatabase extends Database{
} }
async runCreateTableQuery(doctype, columns, values){ async runCreateTableQuery(doctype, columns, values){
const query = `CREATE TABLE IF NOT EXISTS ${frappe.slug(doctype)} ( const query = `CREATE TABLE IF NOT EXISTS ${doctype} (
${columns.join(", ")})`; ${columns.join(", ")})`;
return await this.run(query, values); return await this.run(query, values);
@ -62,7 +62,7 @@ module.exports = class mysqlDatabase extends Database{
async runAlterTableQuery(doctype) { async runAlterTableQuery(doctype) {
await this.run(`ALTER TABLE ${frappe.slug(doctype)} ADD COLUMN ${this.get_column_definition(df)}`, values); await this.run(`ALTER TABLE ${doctype} ADD COLUMN ${this.get_column_definition(df)}`, values);
} }
getOne(doctype, name, fields = '*') { getOne(doctype, name, fields = '*') {
@ -70,7 +70,7 @@ module.exports = class mysqlDatabase extends Database{
fields = this.prepareFields(fields); fields = this.prepareFields(fields);
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
this.conn.get(`select ${fields} from ${frappe.slug(doctype)} this.conn.get(`select ${fields} from ${doctype}
where name = ?`, name, where name = ?`, name,
(err, row) => { (err, row) => {
resolve(row || {}); resolve(row || {});
@ -86,7 +86,7 @@ module.exports = class mysqlDatabase extends Database{
doc.name = frappe.getRandomName(); doc.name = frappe.getRandomName();
} }
return await this.run(`insert into ${frappe.slug(doctype)} return await this.run(`insert into ${doctype}
(${fields.map(field => field.fieldname).join(", ")}) (${fields.map(field => field.fieldname).join(", ")})
values (${placeholders})`, this.getFormattedValues(fields, doc)); values (${placeholders})`, this.getFormattedValues(fields, doc));
} }
@ -99,19 +99,19 @@ module.exports = class mysqlDatabase extends Database{
// additional name for where clause // additional name for where clause
values.push(doc.name); values.push(doc.name);
return await this.run(`update ${frappe.slug(doctype)} return await this.run(`update ${doctype}
set ${assigns.join(", ")} where name=?`, values); set ${assigns.join(", ")} where name=?`, values);
} }
async runDeleteOtherChildren(field, added) { async runDeleteOtherChildren(field, added) {
await this.run(`delete from ${frappe.slug(field.childtype)} await this.run(`delete from ${field.childtype}
where where
parent = ? and parent = ? and
name not in (${added.slice(1).map(d => '?').join(', ')})`, added); name not in (${added.slice(1).map(d => '?').join(', ')})`, added);
} }
async deleteOne(doctype, name) { async deleteOne(doctype, name) {
return await this.run(`delete from ${frappe.slug(doctype)} where name=?`, name); return await this.run(`delete from ${doctype} where name=?`, name);
} }
async deleteChildren(parenttype, parent) { async deleteChildren(parenttype, parent) {
@ -127,7 +127,7 @@ module.exports = class mysqlDatabase extends Database{
let conditions = this.getFilterConditions(filters); let conditions = this.getFilterConditions(filters);
this.conn.all(`select ${fields.join(", ")} this.conn.all(`select ${fields.join(", ")}
from ${frappe.slug(doctype)} from ${doctype}
${conditions.conditions ? "where" : ""} ${conditions.conditions} ${conditions.conditions ? "where" : ""} ${conditions.conditions}
${order_by ? ("order by " + order_by) : ""} ${order_by ? (order || "asc") : ""} ${order_by ? ("order by " + order_by) : ""} ${order_by ? (order || "asc") : ""}
${limit ? ("limit " + limit) : ""} ${start ? ("offset " + start) : ""}`, conditions.values, ${limit ? ("limit " + limit) : ""} ${start ? ("offset " + start) : ""}`, conditions.values,

View File

@ -15,7 +15,7 @@ module.exports = class RESTClient {
async insert(doctype, doc) { async insert(doctype, doc) {
doc.doctype = doctype; doc.doctype = doctype;
let url = this.getURL('/api/resource', frappe.slug(doctype)); let url = this.getURL('/api/resource', doctype);
return await this.fetch(url, { return await this.fetch(url, {
method: 'POST', method: 'POST',
body: JSON.stringify(doc) body: JSON.stringify(doc)
@ -23,7 +23,7 @@ module.exports = class RESTClient {
} }
async get(doctype, name) { async get(doctype, name) {
let url = this.getURL('/api/resource', frappe.slug(doctype), name); let url = this.getURL('/api/resource', doctype, name);
return await this.fetch(url, { return await this.fetch(url, {
method: 'GET', method: 'GET',
headers: this.getHeaders() headers: this.getHeaders()
@ -31,7 +31,7 @@ module.exports = class RESTClient {
} }
async getAll({ doctype, fields, filters, start, limit, sort_by, order }) { async getAll({ doctype, fields, filters, start, limit, sort_by, order }) {
let url = this.getURL('/api/resource', frappe.slug(doctype)); let url = this.getURL('/api/resource', doctype);
url = url + "?" + this.getQueryString({ url = url + "?" + this.getQueryString({
fields: JSON.stringify(fields), fields: JSON.stringify(fields),
@ -49,7 +49,7 @@ module.exports = class RESTClient {
async update(doctype, doc) { async update(doctype, doc) {
doc.doctype = doctype; doc.doctype = doctype;
let url = this.getURL('/api/resource', frappe.slug(doctype), doc.name); let url = this.getURL('/api/resource', doctype, doc.name);
return await this.fetch(url, { return await this.fetch(url, {
method: 'PUT', method: 'PUT',
@ -58,7 +58,7 @@ module.exports = class RESTClient {
} }
async delete(doctype, name) { async delete(doctype, name) {
let url = this.getURL('/api/resource', frappe.slug(doctype), name); let url = this.getURL('/api/resource', doctype, name);
return await this.fetch(url, { return await this.fetch(url, {
method: 'DELETE', method: 'DELETE',
@ -66,7 +66,7 @@ module.exports = class RESTClient {
} }
async deleteMany(doctype, names) { async deleteMany(doctype, names) {
let url = this.getURL('/api/resource', frappe.slug(doctype)); let url = this.getURL('/api/resource', doctype);
return await this.fetch(url, { return await this.fetch(url, {
method: 'DELETE', method: 'DELETE',
@ -79,7 +79,7 @@ module.exports = class RESTClient {
} }
async getValue(doctype, name, fieldname) { async getValue(doctype, name, fieldname) {
let url = this.getURL('/api/resource', frappe.slug(doctype), name, fieldname); let url = this.getURL('/api/resource', doctype, name, fieldname);
return (await this.fetch(url, { return (await this.fetch(url, {
method: 'GET', method: 'GET',

View File

@ -29,14 +29,14 @@ module.exports = class sqliteDatabase extends Database {
} }
async runCreateTableQuery(doctype, columns, values) { async runCreateTableQuery(doctype, columns, values) {
const query = `CREATE TABLE IF NOT EXISTS ${frappe.slug(doctype)} ( const query = `CREATE TABLE IF NOT EXISTS ${doctype} (
${columns.join(", ")})`; ${columns.join(", ")})`;
return await this.run(query, values); return await this.run(query, values);
} }
getColumnDefinition(df) { getColumnDefinition(df) {
return `${df.fieldname} ${this.type_map[df.fieldtype]} ${df.required && !df.default ? "not null" : ""} ${df.default ? `default ${df.default}` : ""}` return `${df.fieldname} ${this.type_map[df.fieldtype]} ${ df.fieldname==="name" ? "PRIMARY KEY" : ""} ${df.required && !df.default ? "NOT NULL" : ""} ${df.default ? `DEFAULT ${df.default}` : ""}`
} }
async getTableColumns(doctype) { async getTableColumns(doctype) {
@ -44,13 +44,13 @@ module.exports = class sqliteDatabase extends Database {
} }
async runAlterTableQuery(doctype, field, values) { async runAlterTableQuery(doctype, field, values) {
await this.run(`ALTER TABLE ${frappe.slug(doctype)} ADD COLUMN ${this.getColumnDefinition(field)}`, values); await this.run(`ALTER TABLE ${doctype} ADD COLUMN ${this.getColumnDefinition(field)}`, values);
} }
getOne(doctype, name, fields = '*') { getOne(doctype, name, fields = '*') {
fields = this.prepareFields(fields); fields = this.prepareFields(fields);
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
this.conn.get(`select ${fields} from ${frappe.slug(doctype)} this.conn.get(`select ${fields} from ${doctype}
where name = ?`, name, where name = ?`, name,
(err, row) => { (err, row) => {
resolve(row || {}); resolve(row || {});
@ -66,7 +66,7 @@ module.exports = class sqliteDatabase extends Database {
doc.name = frappe.getRandomName(); doc.name = frappe.getRandomName();
} }
return await this.run(`insert into ${frappe.slug(doctype)} return await this.run(`insert into ${doctype}
(${fields.map(field => field.fieldname).join(", ")}) (${fields.map(field => field.fieldname).join(", ")})
values (${placeholders})`, this.getFormattedValues(fields, doc)); values (${placeholders})`, this.getFormattedValues(fields, doc));
} }
@ -79,21 +79,21 @@ module.exports = class sqliteDatabase extends Database {
// additional name for where clause // additional name for where clause
values.push(doc.name); values.push(doc.name);
return await this.run(`update ${frappe.slug(doctype)} return await this.run(`update ${doctype}
set ${assigns.join(", ")} where name=?`, values); set ${assigns.join(", ")} where name=?`, values);
} }
async runDeleteOtherChildren(field, added) { async runDeleteOtherChildren(field, added) {
// delete other children // delete other children
// `delete from doctype where parent = ? and name not in (?, ?, ?)}` // `delete from doctype where parent = ? and name not in (?, ?, ?)}`
await this.run(`delete from ${frappe.slug(field.childtype)} await this.run(`delete from ${field.childtype}
where where
parent = ? and parent = ? and
name not in (${added.slice(1).map(d => '?').join(', ')})`, added); name not in (${added.slice(1).map(d => '?').join(', ')})`, added);
} }
async deleteOne(doctype, name) { async deleteOne(doctype, name) {
return await this.run(`delete from ${frappe.slug(doctype)} where name=?`, name); return await this.run(`delete from ${doctype} where name=?`, name);
} }
async deleteChildren(parenttype, parent) { async deleteChildren(parenttype, parent) {
@ -101,7 +101,7 @@ module.exports = class sqliteDatabase extends Database {
} }
async deleteSingleValues(name) { async deleteSingleValues(name) {
await frappe.db.run('delete from single_value where parent=?', name) await frappe.db.run('delete from SingleValue where parent=?', name)
} }
getAll({ doctype, fields, filters, start, limit, order_by = 'modified', order = 'desc' } = {}) { getAll({ doctype, fields, filters, start, limit, order_by = 'modified', order = 'desc' } = {}) {
@ -111,7 +111,7 @@ module.exports = class sqliteDatabase extends Database {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
let conditions = this.getFilterConditions(filters); let conditions = this.getFilterConditions(filters);
let query = `select ${fields.join(", ")} let query = `select ${fields.join(", ")}
from ${frappe.slug(doctype)} from ${doctype}
${conditions.conditions ? "where" : ""} ${conditions.conditions} ${conditions.conditions ? "where" : ""} ${conditions.conditions}
${order_by ? ("order by " + order_by) : ""} ${order_by ? (order || "asc") : ""} ${order_by ? ("order by " + order_by) : ""} ${order_by ? (order || "asc") : ""}
${limit ? ("limit " + limit) : ""} ${start ? ("offset " + start) : ""}`; ${limit ? ("limit " + limit) : ""} ${start ? ("offset " + start) : ""}`;

View File

@ -4,7 +4,7 @@ const Router = require('frappejs/common/router');
const Page = require('frappejs/client/view/page'); const Page = require('frappejs/client/view/page');
const FormPage = require('frappejs/client/desk/formpage'); const FormPage = require('frappejs/client/desk/formpage');
const ListPage = require('frappejs/client/desk/listpage'); const ListPage = require('frappejs/client/desk/listpage');
const Navbar = require('./navbar'); // const Navbar = require('./navbar');
const DeskMenu = require('./menu'); const DeskMenu = require('./menu');
const FormModal = require('frappejs/client/desk/formmodal'); const FormModal = require('frappejs/client/desk/formmodal');

View File

@ -15,7 +15,7 @@ module.exports = class ListPage extends Page {
hasRoute: hasRoute hasRoute: hasRoute
}); });
this.list = new (view.getList_class(doctype))({ this.list = new (view.geListClass(doctype))({
doctype: doctype, doctype: doctype,
parent: this.body, parent: this.body,
page: this page: this

View File

@ -8,7 +8,9 @@ module.exports = {
async start({server, columns = 2}) { async start({server, columns = 2}) {
window.frappe = frappe; window.frappe = frappe;
frappe.init(); frappe.init();
common.init_libs(frappe); frappe.registerLibs(common);
frappe.registerModels(require('frappejs/models'));
frappe.registerModels(require('../models'));
frappe.fetch = window.fetch.bind(); frappe.fetch = window.fetch.bind();
frappe.db = await new RESTClient({server: server}); frappe.db = await new RESTClient({server: server});

View File

@ -153,10 +153,15 @@ mark {
.data-table { .data-table {
.body-scrollable { .body-scrollable {
border-bottom: 0px !important; border-bottom: 0px !important;
tr:first-child {
.data-table-col {
border-top: 0px !important;
}
}
} }
thead td { thead td {
border-bottom: 0px !important;
background-color: $gray-200 !important; background-color: $gray-200 !important;
} }

View File

@ -140,7 +140,7 @@ class BaseControl {
if (this.parentControl) { if (this.parentControl) {
// its a child // its a child
this.doc[this.fieldname] = value; this.doc[this.fieldname] = value;
await this.parentControl.doc.set(this.fieldname, this.parentControl.getInputValue()); await this.parentControl.doc.applyChange(this.fieldname);
} else { } else {
// parent // parent
await this.doc.set(this.fieldname, value); await this.doc.set(this.fieldname, value);

View File

@ -11,7 +11,6 @@ class LinkControl extends BaseControl {
setupAwesomplete() { setupAwesomplete() {
this.awesomplete = new Awesomplete(this.input, { this.awesomplete = new Awesomplete(this.input, {
autoFirst: true,
minChars: 0, minChars: 0,
maxItems: 99, maxItems: 99,
filter: () => true, filter: () => true,
@ -23,7 +22,7 @@ class LinkControl extends BaseControl {
// action to add new item // action to add new item
list.push({ list.push({
label:frappe._('+ New {0}', this.target), label: frappe._('+ New {0}', this.label),
value: '__newItem', value: '__newItem',
}); });

View File

@ -55,7 +55,11 @@ class TableControl extends BaseControl {
setInputValue(value) { setInputValue(value) {
this.datatable.refresh(this.getTableData(value)); this.datatable.refresh(this.getTableData(value));
this.datatable.setDimensions(); this.refreshToolbar();
}
refreshToolbar() {
this.wrapper.querySelector('.table-toolbar').classList.toggle('hide', this.disabled ? true : false);
} }
getTableData(value) { getTableData(value) {
@ -124,7 +128,7 @@ class TableControl extends BaseControl {
field: field, field: field,
content: field.label, content: field.label,
width: 120, width: 120,
editable: field.disabled ? false : true, editable: (this.disabled || field.disabled) ? false : true,
sortable: false, sortable: false,
resizable: true, resizable: true,
dropdown: false, dropdown: false,

View File

@ -71,7 +71,7 @@ module.exports = class BaseForm extends Observable {
if (this.meta.settings && this.actions.includes('settings')) { if (this.meta.settings && this.actions.includes('settings')) {
let menu = this.container.getDropdown(frappe._('Menu')); let menu = this.container.getDropdown(frappe._('Menu'));
menu.addItem(frappe._('Settings...'), () => { menu.addItem(frappe._('Settings...'), () => {
frappe.desk.showFormModal(frappe.slug(this.meta.settings), this.meta.settings); frappe.desk.showFormModal(this.meta.settings, this.meta.settings);
}); });
} }
@ -99,13 +99,14 @@ module.exports = class BaseForm extends Observable {
} }
setTitle() { setTitle() {
const doctype = this.doc.meta.name; const doctypeLabel = this.doc.meta.label || this.doc.meta.name;
if (this.doc.meta.isSingle || !this.doc.meta.showTitle) { if (this.doc.meta.isSingle || !this.doc.meta.showTitle) {
this.container.setTitle(doctype); this.container.setTitle(doctypeLabel);
} else if (this.doc._notInserted) { } else if (this.doc._notInserted) {
this.container.setTitle(frappe._('New {0}', doctype)); this.container.setTitle(frappe._('New {0}', doctypeLabel));
} else { } else {
this.container.setTitle(`${doctype} ${this.doc.name}`); this.container.setTitle(`${doctypeLabel} ${this.doc.name}`);
} }
} }

View File

@ -1,23 +1,12 @@
const BaseList = require('frappejs/client/view/list'); const BaseList = require('frappejs/client/view/list');
const BaseForm = require('frappejs/client/view/form'); const BaseForm = require('frappejs/client/view/form');
const frappe = require('frappejs');
module.exports = { module.exports = {
getFormClass(doctype) { getFormClass(doctype) {
return this.get_view_class(doctype, 'Form', BaseForm); return (frappe.views['Form'] && frappe.views['Form'][doctype]) || BaseForm;
}, },
getList_class(doctype) { geListClass(doctype) {
return this.get_view_class(doctype, 'List', BaseList); return (frappe.views['List'] && frappe.views['List'][doctype]) || BaseList;
},
get_view_class(doctype, class_name, default_class) {
let client_module = this.get_client_module(doctype);
if (client_module && client_module[class_name]) {
return client_module[class_name];
} else {
return default_class;
}
},
get_client_module(doctype) {
return frappe.modules[`${doctype}_client`];
} }
} }

View File

@ -77,7 +77,7 @@ module.exports = class BaseList {
makeToolbar() { makeToolbar() {
this.makeSearch(); this.makeSearch();
this.btnNew = this.page.addButton(frappe._('New'), 'btn-primary', async () => { this.btnNew = this.page.addButton(frappe._('New'), 'btn-primary', async () => {
await frappe.router.setRoute('new', frappe.slug(this.doctype)); await frappe.router.setRoute('new', this.doctype);
}) })
this.btnDelete = this.page.addButton(frappe._('Delete'), 'btn-secondary hide', async () => { this.btnDelete = this.page.addButton(frappe._('Delete'), 'btn-secondary hide', async () => {
await frappe.db.deleteMany(this.doctype, this.getCheckedRowNames()); await frappe.db.deleteMany(this.doctype, this.getCheckedRowNames());

View File

@ -1,17 +1,17 @@
const utils = require('../utils'); const utils = require('../utils');
const number_format = require('../utils/number_format'); const number_format = require('../utils/number_format');
const format = require('../utils/format'); const format = require('../utils/format');
const model = require('../model');
const _session = require('../session');
const errors = require('./errors'); const errors = require('./errors');
const BaseDocument = require('frappejs/model/document');
const BaseMeta = require('frappejs/model/meta');
module.exports = { module.exports = {
init_libs(frappe) { initLibs(frappe) {
Object.assign(frappe, utils); Object.assign(frappe, utils);
Object.assign(frappe, number_format); Object.assign(frappe, number_format);
Object.assign(frappe, format); Object.assign(frappe, format);
frappe.model = model;
frappe._session = _session;
frappe.errors = errors; frappe.errors = errors;
frappe.BaseDocument = BaseDocument;
frappe.BaseMeta = BaseMeta;
} }
} }

View File

@ -1,3 +1,4 @@
module.exports = { module.exports = {
async init() { async init() {
if (this._initialized) return; if (this._initialized) return;
@ -15,13 +16,29 @@ module.exports = {
initGlobals() { initGlobals() {
this.metaCache = {}; this.metaCache = {};
this.modules = {}; this.models = {};
this.forms = {};
this.views = {};
this.docs = {}; this.docs = {};
this.flags = { this.flags = {
cache_docs: false cache_docs: false
} }
}, },
registerLibs(common) {
// add standard libs and utils to frappe
common.initLibs(this);
},
registerModels(models) {
Object.assign(this.models, models);
},
registerView(view, doctype, module) {
if (!this.views[view]) this.views[view] = {};
this.views[view][doctype] = module;
},
addToCache(doc) { addToCache(doc) {
if (!this.flags.cache_docs) return; if (!this.flags.cache_docs) return;
@ -42,31 +59,32 @@ module.exports = {
getMeta(doctype) { getMeta(doctype) {
if (!this.metaCache[doctype]) { if (!this.metaCache[doctype]) {
this.metaCache[doctype] = new (this.getMetaClass(doctype))(); let model = this.models[doctype];
if (!model) {
throw `${doctype} is not a registered doctype`;
}
let metaClass = model.metaClass || this.BaseMeta;
this.metaCache[doctype] = new metaClass(model);
} }
return this.metaCache[doctype];
},
getMetaClass(doctype) { return this.metaCache[doctype];
doctype = this.slug(doctype);
if (this.modules[doctype] && this.modules[doctype].Meta) {
return this.modules[doctype].Meta;
} else {
return this.BaseMeta;
}
}, },
async getDoc(doctype, name) { async getDoc(doctype, name) {
let doc = this.getDocFromCache(doctype, name); let doc = this.getDocFromCache(doctype, name);
if (!doc) { if (!doc) {
let controllerClass = this.getControllerClass(doctype); doc = new (this.getDocumentClass(doctype))({doctype:doctype, name: name});
doc = new controllerClass({doctype:doctype, name: name});
await doc.load(); await doc.load();
this.addToCache(doc); this.addToCache(doc);
} }
return doc; return doc;
}, },
getDocumentClass(doctype) {
const meta = this.getMeta(doctype);
return meta.documentClass || this.BaseDocument;
},
async getSingle(doctype) { async getSingle(doctype) {
return await this.getDoc(doctype, doctype); return await this.getDoc(doctype, doctype);
}, },
@ -85,21 +103,11 @@ module.exports = {
}, },
newDoc(data) { newDoc(data) {
let controllerClass = this.getControllerClass(data.doctype); let doc = new (this.getDocumentClass(data.doctype))(data);
let doc = new controllerClass(data);
doc.setDefaults(); doc.setDefaults();
return doc; return doc;
}, },
getControllerClass(doctype) {
doctype = this.slug(doctype);
if (this.modules[doctype] && this.modules[doctype].Document) {
return this.modules[doctype].Document;
} else {
return this.BaseDocument;
}
},
async getNewDoc(doctype) { async getNewDoc(doctype) {
let doc = this.newDoc({doctype: doctype}); let doc = this.newDoc({doctype: doctype});
doc._notInserted = true; doc._notInserted = true;
@ -113,10 +121,7 @@ module.exports = {
}, },
login(user='guest', user_key) { login(user='guest', user_key) {
this.session = new this._session.Session(user); this.session = {user: user};
if (user && user_key) {
this.authenticate(user_key);
}
}, },
close() { close() {

View File

@ -1,5 +1,6 @@
const frappe = require('frappejs'); const frappe = require('frappejs');
const Observable = require('frappejs/utils/observable'); const Observable = require('frappejs/utils/observable');
const model = require('./index');
module.exports = class BaseDocument extends Observable { module.exports = class BaseDocument extends Observable {
constructor(data) { constructor(data) {
@ -34,12 +35,16 @@ module.exports = class BaseDocument extends Observable {
// set value and trigger change // set value and trigger change
async set(fieldname, value) { async set(fieldname, value) {
this[fieldname] = await this.validateField(fieldname, value); this[fieldname] = await this.validateField(fieldname, value);
if (await this.applyFormulae()) { await this.applyChange(fieldname);
}
async applyChange(fieldname) {
if (await this.applyFormula()) {
// multiple changes // multiple changes
await this.trigger('change', { doc: this }); await this.trigger('change', { doc: this });
} else { } else {
// no other change, trigger control refresh // no other change, trigger control refresh
await this.trigger('change', { doc: this, fieldname: fieldname, value: value }); await this.trigger('change', { doc: this, fieldname: fieldname });
} }
} }
@ -55,9 +60,9 @@ module.exports = class BaseDocument extends Observable {
} }
if (this.meta.settings) { if (this.meta.settings) {
const number_series = (await this.getSettings()).number_series; const numberSeries = (await this.getSettings()).numberSeries;
if(number_series) { if(numberSeries) {
this.name = await frappe.model.getSeriesNext(number_series); this.name = await model.getSeriesNext(numberSeries);
} }
} }
@ -165,8 +170,8 @@ module.exports = class BaseDocument extends Observable {
} }
} }
async applyFormulae() { async applyFormula() {
if (!this.meta.hasFormulae()) { if (!this.meta.hasFormula()) {
return false; return false;
} }
@ -180,7 +185,7 @@ module.exports = class BaseDocument extends Observable {
// for each row // for each row
for (let row of this[tablefield.fieldname]) { for (let row of this[tablefield.fieldname]) {
for (let field of formulaFields) { for (let field of formulaFields) {
row[field.fieldname] = await eval(field.formula); row[field.fieldname] = await field.formula(row, doc);
} }
} }
} }
@ -188,7 +193,7 @@ module.exports = class BaseDocument extends Observable {
// parent // parent
for (let field of this.meta.getFormulaFields()) { for (let field of this.meta.getFormulaFields()) {
doc[field.fieldname] = eval(field.formula); doc[field.fieldname] = await field.formula(doc);
} }
return true; return true;
@ -200,7 +205,7 @@ module.exports = class BaseDocument extends Observable {
this.setStandardValues(); this.setStandardValues();
this.setKeywords(); this.setKeywords();
this.setChildIdx(); this.setChildIdx();
await this.applyFormulae(); await this.applyFormula();
await this.trigger('validate'); await this.trigger('validate');
} }

View File

@ -4,12 +4,12 @@ module.exports = {
async getSeriesNext(prefix) { async getSeriesNext(prefix) {
let series; let series;
try { try {
series = await frappe.getDoc('Number Series', prefix); series = await frappe.getDoc('NumberSeries', prefix);
} catch (e) { } catch (e) {
if (!e.status_code || e.status_code !== 404) { if (!e.status_code || e.status_code !== 404) {
throw e; throw e;
} }
series = frappe.newDoc({doctype: 'Number Series', name: prefix, current: 0}); series = frappe.newDoc({doctype: 'NumberSeries', name: prefix, current: 0});
await series.insert(); await series.insert();
} }
let next = await series.next() let next = await series.next()

View File

@ -1,5 +1,6 @@
const BaseDocument = require('./document'); const BaseDocument = require('./document');
const frappe = require('frappejs'); const frappe = require('frappejs');
const model = require('./index')
module.exports = class BaseMeta extends BaseDocument { module.exports = class BaseMeta extends BaseDocument {
constructor(data) { constructor(data) {
@ -36,21 +37,21 @@ module.exports = class BaseMeta extends BaseDocument {
return this._formulaFields; return this._formulaFields;
} }
hasFormulae() { hasFormula() {
if (this._hasFormulae===undefined) { if (this._hasFormula===undefined) {
this._hasFormulae = false; this._hasFormula = false;
if (this.getFormulaFields().length) { if (this.getFormulaFields().length) {
this._hasFormulae = true; this._hasFormula = true;
} else { } else {
for (let tablefield of this.getTableFields()) { for (let tablefield of this.getTableFields()) {
if (frappe.getMeta(tablefield.childtype).getFormulaFields().length) { if (frappe.getMeta(tablefield.childtype).getFormulaFields().length) {
this._hasFormulae = true; this._hasFormula = true;
break; break;
} }
} }
} }
} }
return this._hasFormulae; return this._hasFormula;
} }
async set(fieldname, value) { async set(fieldname, value) {
@ -76,7 +77,7 @@ module.exports = class BaseMeta extends BaseDocument {
const doctype_fields = this.fields.map((field) => field.fieldname); const doctype_fields = this.fields.map((field) => field.fieldname);
// standard fields // standard fields
for (let field of frappe.model.common_fields) { for (let field of model.common_fields) {
if (frappe.db.type_map[field.fieldtype] && !doctype_fields.includes(field.fieldname)) { if (frappe.db.type_map[field.fieldtype] && !doctype_fields.includes(field.fieldname)) {
_add(field); _add(field);
} }
@ -84,14 +85,14 @@ module.exports = class BaseMeta extends BaseDocument {
if (this.isChild) { if (this.isChild) {
// child fields // child fields
for (let field of frappe.model.child_fields) { for (let field of model.child_fields) {
if (frappe.db.type_map[field.fieldtype] && !doctype_fields.includes(field.fieldname)) { if (frappe.db.type_map[field.fieldtype] && !doctype_fields.includes(field.fieldname)) {
_add(field); _add(field);
} }
} }
} else { } else {
// parent fields // parent fields
for (let field of frappe.model.parent_fields) { for (let field of model.parent_fields) {
if (frappe.db.type_map[field.fieldtype] && !doctype_fields.includes(field.fieldname)) { if (frappe.db.type_map[field.fieldtype] && !doctype_fields.includes(field.fieldname)) {
_add(field); _add(field);
} }

View File

@ -1,5 +1,6 @@
{ module.exports = {
"name": "Number Series", "name": "NumberSeries",
"documentClass": require('./NumberSeriesDocument.js'),
"doctype": "DocType", "doctype": "DocType",
"isSingle": 0, "isSingle": 0,
"isChild": 0, "isChild": 0,

View File

@ -0,0 +1,15 @@
const BaseDocument = require('frappejs/model/document');
module.exports = class NumberSeries extends BaseDocument {
validate() {
if (this.current===null || this.current===undefined) {
this.current = 0;
}
}
async next() {
this.validate();
this.current++;
await this.update();
return this.current;
}
}

View File

@ -1,5 +1,5 @@
{ module.exports = {
"name": "Single Value", "name": "SingleValue",
"doctype": "DocType", "doctype": "DocType",
"isSingle": 0, "isSingle": 0,
"isChild": 0, "isChild": 0,

View File

@ -1,5 +1,5 @@
{ module.exports = {
"name": "System Settings", "name": "SystemSettings",
"doctype": "DocType", "doctype": "DocType",
"isSingle": 1, "isSingle": 1,
"isChild": 0, "isChild": 0,

View File

@ -1,15 +1,11 @@
const BaseList = require('frappejs/client/view/list'); const BaseList = require('frappejs/client/view/list');
class ToDoList extends BaseList { module.exports = class ToDoList extends BaseList {
getFields() { getFields() {
return ['name', 'subject', 'status']; return ['name', 'subject', 'status'];
} }
getRowHTML(data) { getRowHTML(data) {
let symbol = data.status=="Closed" ? "✔" : ""; let symbol = data.status=="Closed" ? "✔" : "";
return `<a href="#edit/todo/${data.name}">${symbol} ${data.subject}</a>`; return `<a href="#edit/ToDo/${data.name}">${symbol} ${data.subject}</a>`;
} }
} }
module.exports = {
List: ToDoList
}

View File

@ -1,5 +1,5 @@
{ module.exports = {
"name": "User Role", "name": "UserRole",
"doctype": "DocType", "doctype": "DocType",
"isSingle": 0, "isSingle": 0,
"isChild": 1, "isChild": 1,

View File

@ -1,27 +0,0 @@
const BaseMeta = require('frappejs/model/meta');
const BaseDocument = require('frappejs/model/document');
class NumberSeriesMeta extends BaseMeta {
setupMeta() {
Object.assign(this, require('./number_series.json'));
}
}
class NumberSeries extends BaseDocument {
validate() {
if (this.current===null || this.current===undefined) {
this.current = 0;
}
}
async next() {
this.validate();
this.current++;
await this.update();
return this.current;
}
}
module.exports = {
Document: NumberSeries,
Meta: NumberSeriesMeta
};

View File

@ -1,16 +1,15 @@
const BaseMeta = require('frappejs/model/meta');
const BaseDocument = require('frappejs/model/document');
class RoleMeta extends BaseMeta {
setupMeta() {
Object.assign(this, require('./role.json'));
}
}
class Role extends BaseDocument {
}
module.exports = { module.exports = {
Document: Role, "name": "Role",
Meta: RoleMeta "doctype": "DocType",
}; "isSingle": 0,
"isChild": 0,
"keywordFields": [],
"fields": [
{
"fieldname": "name",
"label": "Name",
"fieldtype": "Data",
"required": 1
}
]
}

View File

@ -1,15 +0,0 @@
{
"name": "Role",
"doctype": "DocType",
"isSingle": 0,
"isChild": 0,
"keywordFields": [],
"fields": [
{
"fieldname": "name",
"label": "Name",
"fieldtype": "Data",
"required": 1
}
]
}

View File

@ -1,17 +1,21 @@
const BaseMeta = require('frappejs/model/meta');
const BaseDocument = require('frappejs/model/document');
class SessionMeta extends BaseMeta {
setupMeta() {
Object.assign(this, require('./session.json'));
}
}
class Session extends BaseDocument {
}
module.exports = { module.exports = {
Document: Session, "name": "Session",
Meta: SessionMeta "doctype": "DocType",
}; "isSingle": 0,
"isChild": 0,
"keywordFields": [],
"fields": [
{
"fieldname": "username",
"label": "Username",
"fieldtype": "Data",
"required": 1
},
{
"fieldname": "password",
"label": "Password",
"fieldtype": "Password",
"required": 1
}
]
}

View File

@ -1,21 +0,0 @@
{
"name": "Session",
"doctype": "DocType",
"isSingle": 0,
"isChild": 0,
"keywordFields": [],
"fields": [
{
"fieldname": "username",
"label": "Username",
"fieldtype": "Data",
"required": 1
},
{
"fieldname": "password",
"label": "Password",
"fieldtype": "Password",
"required": 1
}
]
}

View File

@ -1,16 +0,0 @@
const BaseMeta = require('frappejs/model/meta');
const BaseDocument = require('frappejs/model/document');
class SingleValueMeta extends BaseMeta {
setupMeta() {
Object.assign(this, require('./single_value.json'));
}
}
class SingleValue extends BaseDocument {
}
module.exports = {
Document: SingleValue,
Meta: SingleValueMeta
};

View File

@ -1,16 +0,0 @@
const BaseMeta = require('frappejs/model/meta');
const BaseDocument = require('frappejs/model/document');
class SystemSettingsMeta extends BaseMeta {
setupMeta() {
Object.assign(this, require('./system_settings.json'));
}
}
class SystemSettings extends BaseDocument {
}
module.exports = {
Document: SystemSettings,
Meta: SystemSettingsMeta
};

View File

@ -1,21 +1,34 @@
const BaseMeta = require('frappejs/model/meta');
const BaseDocument = require('frappejs/model/document');
class ToDoMeta extends BaseMeta {
setupMeta() {
Object.assign(this, require('./todo.json'));
}
}
class ToDo extends BaseDocument {
validate() {
if (!this.status) {
this.status = 'Open';
}
}
}
module.exports = { module.exports = {
Document: ToDo, "autoname": "random",
Meta: ToDoMeta "name": "ToDo",
}; "doctype": "DocType",
"isSingle": 0,
"keywordFields": [
"subject",
"description"
],
"fields": [
{
"fieldname": "subject",
"label": "Subject",
"fieldtype": "Data",
"required": 1
},
{
"fieldname": "status",
"label": "Status",
"fieldtype": "Select",
"options": [
"Open",
"Closed"
],
"default": "Open",
"required": 1
},
{
"fieldname": "description",
"label": "Description",
"fieldtype": "Text"
}
]
}

View File

@ -1,34 +0,0 @@
{
"autoname": "hash",
"name": "ToDo",
"doctype": "DocType",
"isSingle": 0,
"keywordFields": [
"subject",
"description"
],
"fields": [
{
"fieldname": "subject",
"label": "Subject",
"fieldtype": "Data",
"required": 1
},
{
"fieldname": "status",
"label": "Status",
"fieldtype": "Select",
"options": [
"Open",
"Closed"
],
"default": "Open",
"required": 1
},
{
"fieldname": "description",
"label": "Description",
"fieldtype": "Text"
}
]
}

View File

@ -1,16 +1,30 @@
const BaseMeta = require('frappejs/model/meta');
const BaseDocument = require('frappejs/model/document');
class UserMeta extends BaseMeta {
setupMeta() {
Object.assign(this, require('./user.json'));
}
}
class User extends BaseDocument {
}
module.exports = { module.exports = {
Document: User, "name": "User",
Meta: UserMeta "doctype": "DocType",
}; "isSingle": 0,
"isChild": 0,
"keywordFields": [
"name",
"full_name"
],
"fields": [
{
"fieldname": "name",
"label": "Name",
"fieldtype": "Data",
"required": 1
},
{
"fieldname": "full_name",
"label": "Full Name",
"fieldtype": "Data",
"required": 1
},
{
"fieldname": "roles",
"label": "Roles",
"fieldtype": "Table",
"childtype": "UserRole"
}
]
}

View File

@ -1,30 +0,0 @@
{
"name": "User",
"doctype": "DocType",
"isSingle": 0,
"isChild": 0,
"keywordFields": [
"name",
"full_name"
],
"fields": [
{
"fieldname": "name",
"label": "Name",
"fieldtype": "Data",
"required": 1
},
{
"fieldname": "full_name",
"label": "Full Name",
"fieldtype": "Data",
"required": 1
},
{
"fieldname": "roles",
"label": "Roles",
"fieldtype": "Table",
"childtype": "User Role"
}
]
}

View File

@ -1,16 +0,0 @@
const BaseMeta = require('frappejs/model/meta');
const BaseDocument = require('frappejs/model/document');
class UserRoleMeta extends BaseMeta {
setupMeta() {
Object.assign(this, require('./user_role.json'));
}
}
class UserRole extends BaseDocument {
}
module.exports = {
Document: UserRole,
Meta: UserRoleMeta
};

10
models/index.js Normal file
View File

@ -0,0 +1,10 @@
module.exports = {
NumberSeries: require('./doctype/NumberSeries/NumberSeries.js'),
Role: require('./doctype/Role/Role.js'),
Session: require('./doctype/Session/Session.js'),
SingleValue: require('./doctype/SingleValue/SingleValue.js'),
SystemSettings: require('./doctype/SystemSettings/SystemSettings.js'),
ToDo: require('./doctype/ToDo/ToDo.js'),
User: require('./doctype/User/User.js'),
UserRole: require('./doctype/UserRole/UserRole.js')
}

View File

@ -1,24 +1,25 @@
const backends = {}; const backends = {};
backends.sqlite = require('frappejs/backends/sqlite'); backends.sqlite = require('frappejs/backends/sqlite');
backends.mysql = require('frappejs/backends/mysql'); //backends.mysql = require('frappejs/backends/mysql');
const express = require('express'); const express = require('express');
const app = express(); const app = express();
const frappe = require('frappejs'); const frappe = require('frappejs');
const rest_api = require('./rest_api') const rest_api = require('./rest_api');
const init_models = require('frappejs/server/init_models'); const frappeModels = require('frappejs/models');
const common = require('frappejs/common'); const common = require('frappejs/common');
const bodyParser = require('body-parser'); const bodyParser = require('body-parser');
const path = require('path');
module.exports = { module.exports = {
async start({backend, connection_params, models_path}) { async start({backend, connectionParams, models}) {
await this.init(); await this.init();
this.init_models(models_path); if (models) {
frappe.registerModels(models);
}
// database // database
await this.init_db({backend:backend, connection_params:connection_params}); await this.initDb({backend:backend, connectionParams:connectionParams});
// app // app
app.use(bodyParser.json()); app.use(bodyParser.json());
@ -33,22 +34,15 @@ module.exports = {
frappe.server = app.listen(frappe.config.port); frappe.server = app.listen(frappe.config.port);
}, },
init_models(models_path) {
// import frappe modules
init_models(path.join(path.dirname(require.resolve('frappejs')), 'models'));
// import modules from the app
init_models(models_path);
},
async init() { async init() {
await frappe.init(); await frappe.init();
common.init_libs(frappe); frappe.registerModels(frappeModels);
frappe.registerLibs(common);
await frappe.login(); await frappe.login();
}, },
async init_db({backend, connection_params}) { async initDb({backend, connectionParams}) {
frappe.db = await new backends[backend](connection_params); frappe.db = await new backends[backend](connectionParams);
await frappe.db.connect(); await frappe.db.connect();
await frappe.db.migrate(); await frappe.db.migrate();
}, },

View File

@ -1,23 +0,0 @@
const frappe = require('frappejs');
const walk = require('walk');
const path = require('path');
module.exports = function(models_path) {
if (!models_path) {
return;
}
walk.walkSync(models_path, {
listeners: {
file: (basepath, file_data, next) => {
const doctype = path.basename(path.dirname(basepath));
const name = path.basename(basepath);
const file_path = path.resolve(basepath, file_data.name);
if (doctype==='doctype' && file_data.name.endsWith('.js')) {
frappe.modules[file_data.name.slice(0, -3)] = require(file_path);
}
next();
}
}
});
}

View File

@ -1,17 +0,0 @@
const frappe = require('frappejs');
class Session {
constructor(user, user_key) {
this.user = user || 'guest';
if (this.user !== 'guest') {
this.login(user_key);
}
}
login(user_key) {
// could be password, sessionid, otp
}
}
module.exports = { Session: Session };

View File

@ -1,12 +1,15 @@
const server = require('frappejs/server'); const server = require('frappejs/server');
const frappe = require('frappejs');
module.exports = { module.exports = {
async init_sqlite() { async initSqlite({dbPath = '_test.db', models} = {}) {
server.init(); server.init();
server.init_models(); if (models) {
server.init_db({ frappe.registerModels(models);
}
await server.initDb({
backend: 'sqlite', backend: 'sqlite',
connection_params: {dbPath: 'test.db'} connectionParams: {dbPath: dbPath},
}); });
} }
} }

View File

@ -4,7 +4,7 @@ const helpers = require('./helpers');
describe('Controller', () => { describe('Controller', () => {
before(async function() { before(async function() {
await helpers.init_sqlite(); await helpers.initSqlite();
}); });
it('should call controller method', async () => { it('should call controller method', async () => {

View File

@ -4,7 +4,7 @@ const helpers = require('./helpers');
describe('Database', () => { describe('Database', () => {
before(async function() { before(async function() {
await helpers.init_sqlite(); await helpers.initSqlite();
}); });
it('should insert and get values', async () => { it('should insert and get values', async () => {

View File

@ -4,7 +4,7 @@ const helpers = require('./helpers');
describe('Document', () => { describe('Document', () => {
before(async function() { before(async function() {
await helpers.init_sqlite(); await helpers.initSqlite();
}); });
it('should insert a doc', async () => { it('should insert a doc', async () => {
@ -68,8 +68,8 @@ describe('Document', () => {
}); });
it('should add, fetch and delete documents with children', async() => { it('should add, fetch and delete documents with children', async() => {
await frappe.newDoc({doctype: 'Role', name: 'Test Role'}).insert(); await frappe.insert({doctype: 'Role', name: 'Test Role'});
await frappe.newDoc({doctype: 'Role', name: 'Test Role 1'}).insert(); await frappe.insert({doctype: 'Role', name: 'Test Role 1'});
let user = frappe.newDoc({ let user = frappe.newDoc({
doctype: 'User', doctype: 'User',

View File

@ -4,7 +4,7 @@ const helpers = require('./helpers');
describe('Meta', () => { describe('Meta', () => {
before(async function() { before(async function() {
await helpers.init_sqlite(); await helpers.initSqlite();
}); });
it('should get init from json file', () => { it('should get init from json file', () => {

View File

@ -4,11 +4,11 @@ const helpers = require('./helpers');
describe('Models', () => { describe('Models', () => {
before(async function() { before(async function() {
await helpers.init_sqlite(); await helpers.initSqlite();
}); });
it('should get todo json', () => { it('should get todo json', () => {
let todo = frappe.getMeta('todo'); let todo = frappe.getMeta('ToDo');
assert.equal(todo.isSingle, 0); assert.equal(todo.isSingle, 0);
}); });
}); });

View File

@ -1,10 +1,10 @@
const server = require('frappejs/server'); // const server = require('frappejs/server');
server.start({ // server.start({
backend: 'mysql', // backend: 'mysql',
connection_params: { // connectionParams: {
host : "test_frappejs", // host : "test_frappejs",
username : "test_frappejs", // username : "test_frappejs",
password : "test_frappejs", // password : "test_frappejs",
db_name : "test_frappejs" // db_name : "test_frappejs"
} // }
}); // });

View File

@ -1,16 +1,17 @@
const assert = require('assert'); const assert = require('assert');
const frappe = require('frappejs'); const frappe = require('frappejs');
const helpers = require('./helpers'); const helpers = require('./helpers');
const model = require('frappejs/model')
describe('Number Series', () => { describe('NumberSeries', () => {
before(async function() { before(async function() {
await helpers.init_sqlite(); await helpers.initSqlite();
}); });
it('should start a series and get next value', async () => { it('should start a series and get next value', async () => {
frappe.db.delete('Number Series', 'test-series-') frappe.db.delete('NumberSeries', 'test-series-')
assert.equal(await frappe.model.getSeriesNext('test-series-'), 'test-series-1'); assert.equal(await model.getSeriesNext('test-series-'), 'test-series-1');
assert.equal(await frappe.model.getSeriesNext('test-series-'), 'test-series-2'); assert.equal(await model.getSeriesNext('test-series-'), 'test-series-2');
assert.equal(await frappe.model.getSeriesNext('test-series-'), 'test-series-3'); assert.equal(await model.getSeriesNext('test-series-'), 'test-series-3');
}); });
}); });

View File

@ -17,12 +17,12 @@ describe('Router', () => {
let router = new Router(); let router = new Router();
router.add('/edit/:doctype', 'catch'); router.add('/edit/:doctype', 'catch');
router.add('/edit/:doctype/:name', 'all'); router.add('/edit/:doctype/:name', 'all');
router.add('/edit/todo/:name', 'todo'); router.add('/edit/ToDo/:name', 'ToDo');
router.add('/edit/todo/mytest', 'static'); router.add('/edit/ToDo/mytest', 'static');
assert.equal(router.match('/edit/todo/test').handler, 'todo'); assert.equal(router.match('/edit/ToDo/test').handler, 'ToDo');
assert.equal(router.match('/edit/user/test').handler, 'all'); assert.equal(router.match('/edit/user/test').handler, 'all');
assert.equal(router.match('/edit/todo/mytest').handler, 'static'); assert.equal(router.match('/edit/ToDo/mytest').handler, 'static');
assert.equal(router.match('/edit/user').handler, 'catch'); assert.equal(router.match('/edit/user').handler, 'catch');
}); });

View File

@ -3,6 +3,6 @@ const server = require('frappejs/server');
if (require.main === module) { if (require.main === module) {
server.start({ server.start({
backend: 'sqlite', backend: 'sqlite',
connection_params: {dbPath: 'test.db'} connectionParams: {dbPath: 'test.db'}
}); });
} }

View File

@ -4,21 +4,21 @@ const helpers = require('./helpers');
describe('Single Documents', () => { describe('Single Documents', () => {
before(async function() { before(async function() {
await helpers.init_sqlite(); await helpers.initSqlite();
}); });
it('should set a single value', async () => { it('should set a single value', async () => {
let systemSettings = await frappe.getSingle('System Settings'); let systemSettings = await frappe.getSingle('SystemSettings');
systemSettings.dateFormat = 'dd/mm/yyyy'; systemSettings.dateFormat = 'dd/mm/yyyy';
await systemSettings.update(); await systemSettings.update();
systemSettings = await frappe.getSingle('System Settings'); systemSettings = await frappe.getSingle('SystemSettings');
assert.equal(systemSettings.dateFormat, 'dd/mm/yyyy'); assert.equal(systemSettings.dateFormat, 'dd/mm/yyyy');
systemSettings.dateFormat = 'mm/dd/yyyy'; systemSettings.dateFormat = 'mm/dd/yyyy';
await systemSettings.update(); await systemSettings.update();
systemSettings = await frappe.getSingle('System Settings'); systemSettings = await frappe.getSingle('SystemSettings');
assert.equal(systemSettings.dateFormat, 'mm/dd/yyyy'); assert.equal(systemSettings.dateFormat, 'mm/dd/yyyy');
}); });
}); });