mirror of
https://github.com/frappe/books.git
synced 2024-12-23 11:29:03 +00:00
incr: type observable
- convert several to ES6
This commit is contained in:
parent
507a500edb
commit
47e6493699
@ -1,15 +1,13 @@
|
|||||||
const utils = require('../utils');
|
export default async function initLibs(frappe) {
|
||||||
const format = require('../utils/format');
|
const utils = await import('../utils');
|
||||||
const errors = require('./errors');
|
const format = await import('../utils/format');
|
||||||
const BaseDocument = require('frappe/model/document');
|
const errors = await import('./errors');
|
||||||
const BaseMeta = require('frappe/model/meta');
|
const BaseMeta = await import('frappe/model/meta');
|
||||||
|
const BaseDocument = await import('frappe/model/document');
|
||||||
|
|
||||||
module.exports = {
|
Object.assign(frappe, utils.default);
|
||||||
initLibs(frappe) {
|
Object.assign(frappe, format.default);
|
||||||
Object.assign(frappe, utils);
|
frappe.errors = errors.default;
|
||||||
Object.assign(frappe, format);
|
frappe.BaseDocument = BaseDocument.default;
|
||||||
frappe.errors = errors;
|
frappe.BaseMeta = BaseMeta.default;
|
||||||
frappe.BaseDocument = BaseDocument;
|
}
|
||||||
frappe.BaseMeta = BaseMeta;
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
120
frappe/index.js
120
frappe/index.js
@ -1,25 +1,25 @@
|
|||||||
const Observable = require('./utils/observable');
|
import initLibs from 'frappe/common';
|
||||||
const { T, t } = require('./utils/translation');
|
import { getMoneyMaker } from 'pesa';
|
||||||
const utils = require('./utils');
|
import { markRaw } from 'vue';
|
||||||
const { getMoneyMaker } = require('pesa');
|
import utils from './utils';
|
||||||
const {
|
import {
|
||||||
DEFAULT_INTERNAL_PRECISION,
|
|
||||||
DEFAULT_DISPLAY_PRECISION,
|
DEFAULT_DISPLAY_PRECISION,
|
||||||
} = require('./utils/consts');
|
DEFAULT_INTERNAL_PRECISION,
|
||||||
const { markRaw } = require('vue');
|
} from './utils/consts';
|
||||||
|
import Observable from './utils/observable';
|
||||||
|
import { t, T } from './utils/translation';
|
||||||
|
|
||||||
module.exports = {
|
class Frappe {
|
||||||
isElectron: false,
|
isElectron = false;
|
||||||
isServer: false,
|
isServer = false;
|
||||||
|
|
||||||
initializeAndRegister(customModels = {}, force = false) {
|
async initializeAndRegister(customModels = {}, force = false) {
|
||||||
this.init(force);
|
this.init(force);
|
||||||
const common = require('frappe/common');
|
await initLibs(this);
|
||||||
this.registerLibs(common);
|
const coreModels = await import('frappe/models');
|
||||||
const coreModels = require('frappe/models');
|
this.registerModels(coreModels.default);
|
||||||
this.registerModels(coreModels);
|
|
||||||
this.registerModels(customModels);
|
this.registerModels(customModels);
|
||||||
},
|
}
|
||||||
|
|
||||||
async initializeMoneyMaker(currency) {
|
async initializeMoneyMaker(currency) {
|
||||||
currency ??= 'XXX';
|
currency ??= 'XXX';
|
||||||
@ -65,26 +65,19 @@ module.exports = {
|
|||||||
display,
|
display,
|
||||||
wrapper: markRaw,
|
wrapper: markRaw,
|
||||||
});
|
});
|
||||||
},
|
}
|
||||||
|
|
||||||
init(force) {
|
init(force) {
|
||||||
if (this._initialized && !force) return;
|
if (this._initialized && !force) return;
|
||||||
this.initConfig();
|
|
||||||
this.initGlobals();
|
|
||||||
this.docs = new Observable();
|
|
||||||
this.events = new Observable();
|
|
||||||
this._initialized = true;
|
|
||||||
},
|
|
||||||
|
|
||||||
initConfig() {
|
// Initialize Config
|
||||||
this.config = {
|
this.config = {
|
||||||
serverURL: '',
|
serverURL: '',
|
||||||
backend: 'sqlite',
|
backend: 'sqlite',
|
||||||
port: 8000,
|
port: 8000,
|
||||||
};
|
};
|
||||||
},
|
|
||||||
|
|
||||||
initGlobals() {
|
// Initialize Globals
|
||||||
this.metaCache = {};
|
this.metaCache = {};
|
||||||
this.models = {};
|
this.models = {};
|
||||||
this.forms = {};
|
this.forms = {};
|
||||||
@ -92,15 +85,15 @@ module.exports = {
|
|||||||
this.flags = {};
|
this.flags = {};
|
||||||
this.methods = {};
|
this.methods = {};
|
||||||
this.errorLog = [];
|
this.errorLog = [];
|
||||||
|
|
||||||
// temp params while calling routes
|
// temp params while calling routes
|
||||||
this.temp = {};
|
this.temp = {};
|
||||||
this.params = {};
|
this.params = {};
|
||||||
},
|
|
||||||
|
|
||||||
registerLibs(common) {
|
this.docs = new Observable();
|
||||||
// add standard libs and utils to frappe
|
this.events = new Observable();
|
||||||
common.initLibs(this);
|
this._initialized = true;
|
||||||
},
|
}
|
||||||
|
|
||||||
registerModels(models) {
|
registerModels(models) {
|
||||||
// register models from app/models/index.js
|
// register models from app/models/index.js
|
||||||
@ -126,7 +119,7 @@ module.exports = {
|
|||||||
|
|
||||||
this.models[doctype] = metaDefinition;
|
this.models[doctype] = metaDefinition;
|
||||||
}
|
}
|
||||||
},
|
}
|
||||||
|
|
||||||
getModels(filterFunction) {
|
getModels(filterFunction) {
|
||||||
let models = [];
|
let models = [];
|
||||||
@ -134,12 +127,12 @@ module.exports = {
|
|||||||
models.push(this.models[doctype]);
|
models.push(this.models[doctype]);
|
||||||
}
|
}
|
||||||
return filterFunction ? models.filter(filterFunction) : models;
|
return filterFunction ? models.filter(filterFunction) : models;
|
||||||
},
|
}
|
||||||
|
|
||||||
registerView(view, name, module) {
|
registerView(view, name, module) {
|
||||||
if (!this.views[view]) this.views[view] = {};
|
if (!this.views[view]) this.views[view] = {};
|
||||||
this.views[view][name] = module;
|
this.views[view][name] = module;
|
||||||
},
|
}
|
||||||
|
|
||||||
registerMethod({ method, handler }) {
|
registerMethod({ method, handler }) {
|
||||||
this.methods[method] = handler;
|
this.methods[method] = handler;
|
||||||
@ -156,7 +149,7 @@ module.exports = {
|
|||||||
})
|
})
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
},
|
}
|
||||||
|
|
||||||
async call({ method, args }) {
|
async call({ method, args }) {
|
||||||
if (this.isServer) {
|
if (this.isServer) {
|
||||||
@ -177,7 +170,7 @@ module.exports = {
|
|||||||
body: JSON.stringify(args || {}),
|
body: JSON.stringify(args || {}),
|
||||||
});
|
});
|
||||||
return await response.json();
|
return await response.json();
|
||||||
},
|
}
|
||||||
|
|
||||||
addToCache(doc) {
|
addToCache(doc) {
|
||||||
if (!this.docs) return;
|
if (!this.docs) return;
|
||||||
@ -199,7 +192,7 @@ module.exports = {
|
|||||||
this.docs.trigger('change', params);
|
this.docs.trigger('change', params);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
},
|
}
|
||||||
|
|
||||||
removeFromCache(doctype, name) {
|
removeFromCache(doctype, name) {
|
||||||
try {
|
try {
|
||||||
@ -207,7 +200,7 @@ module.exports = {
|
|||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.warn(`Document ${doctype} ${name} does not exist`);
|
console.warn(`Document ${doctype} ${name} does not exist`);
|
||||||
}
|
}
|
||||||
},
|
}
|
||||||
|
|
||||||
isDirty(doctype, name) {
|
isDirty(doctype, name) {
|
||||||
return (
|
return (
|
||||||
@ -217,13 +210,13 @@ module.exports = {
|
|||||||
this.docs[doctype][name]._dirty) ||
|
this.docs[doctype][name]._dirty) ||
|
||||||
false
|
false
|
||||||
);
|
);
|
||||||
},
|
}
|
||||||
|
|
||||||
getDocFromCache(doctype, name) {
|
getDocFromCache(doctype, name) {
|
||||||
if (this.docs && this.docs[doctype] && this.docs[doctype][name]) {
|
if (this.docs && this.docs[doctype] && this.docs[doctype][name]) {
|
||||||
return this.docs[doctype][name];
|
return this.docs[doctype][name];
|
||||||
}
|
}
|
||||||
},
|
}
|
||||||
|
|
||||||
getMeta(doctype) {
|
getMeta(doctype) {
|
||||||
if (!this.metaCache[doctype]) {
|
if (!this.metaCache[doctype]) {
|
||||||
@ -231,12 +224,13 @@ module.exports = {
|
|||||||
if (!model) {
|
if (!model) {
|
||||||
throw new Error(`${doctype} is not a registered doctype`);
|
throw new Error(`${doctype} is not a registered doctype`);
|
||||||
}
|
}
|
||||||
|
|
||||||
let metaClass = model.metaClass || this.BaseMeta;
|
let metaClass = model.metaClass || this.BaseMeta;
|
||||||
this.metaCache[doctype] = new metaClass(model);
|
this.metaCache[doctype] = new metaClass(model);
|
||||||
}
|
}
|
||||||
|
|
||||||
return this.metaCache[doctype];
|
return this.metaCache[doctype];
|
||||||
},
|
}
|
||||||
|
|
||||||
async getDoc(doctype, name, options = { skipDocumentCache: false }) {
|
async getDoc(doctype, name, options = { skipDocumentCache: false }) {
|
||||||
let doc = options.skipDocumentCache
|
let doc = options.skipDocumentCache
|
||||||
@ -251,16 +245,16 @@ module.exports = {
|
|||||||
this.addToCache(doc);
|
this.addToCache(doc);
|
||||||
}
|
}
|
||||||
return doc;
|
return doc;
|
||||||
},
|
}
|
||||||
|
|
||||||
getDocumentClass(doctype) {
|
getDocumentClass(doctype) {
|
||||||
const meta = this.getMeta(doctype);
|
const meta = this.getMeta(doctype);
|
||||||
return meta.documentClass || this.BaseDocument;
|
return meta.documentClass || this.BaseDocument;
|
||||||
},
|
}
|
||||||
|
|
||||||
async getSingle(doctype) {
|
async getSingle(doctype) {
|
||||||
return await this.getDoc(doctype, doctype);
|
return await this.getDoc(doctype, doctype);
|
||||||
},
|
}
|
||||||
|
|
||||||
async getDuplicate(doc) {
|
async getDuplicate(doc) {
|
||||||
const newDoc = await this.getNewDoc(doc.doctype);
|
const newDoc = await this.getNewDoc(doc.doctype);
|
||||||
@ -277,7 +271,7 @@ module.exports = {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
return newDoc;
|
return newDoc;
|
||||||
},
|
}
|
||||||
|
|
||||||
getNewDoc(doctype, cacheDoc = true) {
|
getNewDoc(doctype, cacheDoc = true) {
|
||||||
let doc = this.newDoc({ doctype: doctype });
|
let doc = this.newDoc({ doctype: doctype });
|
||||||
@ -287,7 +281,7 @@ module.exports = {
|
|||||||
this.addToCache(doc);
|
this.addToCache(doc);
|
||||||
}
|
}
|
||||||
return doc;
|
return doc;
|
||||||
},
|
}
|
||||||
|
|
||||||
async newCustomDoc(fields) {
|
async newCustomDoc(fields) {
|
||||||
let doc = new this.BaseDocument({ isCustom: 1, fields });
|
let doc = new this.BaseDocument({ isCustom: 1, fields });
|
||||||
@ -295,22 +289,22 @@ module.exports = {
|
|||||||
doc.name = this.getRandomString();
|
doc.name = this.getRandomString();
|
||||||
this.addToCache(doc);
|
this.addToCache(doc);
|
||||||
return doc;
|
return doc;
|
||||||
},
|
}
|
||||||
|
|
||||||
createMeta(fields) {
|
createMeta(fields) {
|
||||||
let meta = new this.BaseMeta({ isCustom: 1, fields });
|
let meta = new this.BaseMeta({ isCustom: 1, fields });
|
||||||
return meta;
|
return meta;
|
||||||
},
|
}
|
||||||
|
|
||||||
newDoc(data) {
|
newDoc(data) {
|
||||||
let doc = new (this.getDocumentClass(data.doctype))(data);
|
let doc = new (this.getDocumentClass(data.doctype))(data);
|
||||||
doc.setDefaults();
|
doc.setDefaults();
|
||||||
return doc;
|
return doc;
|
||||||
},
|
}
|
||||||
|
|
||||||
async insert(data) {
|
async insert(data) {
|
||||||
return await this.newDoc(data).insert();
|
return await this.newDoc(data).insert();
|
||||||
},
|
}
|
||||||
|
|
||||||
async syncDoc(data) {
|
async syncDoc(data) {
|
||||||
let doc;
|
let doc;
|
||||||
@ -322,7 +316,7 @@ module.exports = {
|
|||||||
doc = this.newDoc(data);
|
doc = this.newDoc(data);
|
||||||
await doc.insert();
|
await doc.insert();
|
||||||
}
|
}
|
||||||
},
|
}
|
||||||
|
|
||||||
// only for client side
|
// only for client side
|
||||||
async login(email, password) {
|
async login(email, password) {
|
||||||
@ -354,7 +348,7 @@ module.exports = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return response;
|
return response;
|
||||||
},
|
}
|
||||||
|
|
||||||
async signup(email, fullName, password) {
|
async signup(email, fullName, password) {
|
||||||
let response = await fetch(this.getServerURL() + '/api/signup', {
|
let response = await fetch(this.getServerURL() + '/api/signup', {
|
||||||
@ -371,11 +365,11 @@ module.exports = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return response;
|
return response;
|
||||||
},
|
}
|
||||||
|
|
||||||
getServerURL() {
|
getServerURL() {
|
||||||
return this.config.serverURL || '';
|
return this.config.serverURL || '';
|
||||||
},
|
}
|
||||||
|
|
||||||
close() {
|
close() {
|
||||||
this.db.close();
|
this.db.close();
|
||||||
@ -383,11 +377,15 @@ module.exports = {
|
|||||||
if (this.server) {
|
if (this.server) {
|
||||||
this.server.close();
|
this.server.close();
|
||||||
}
|
}
|
||||||
},
|
}
|
||||||
t,
|
|
||||||
T,
|
store = {
|
||||||
store: {
|
|
||||||
isDevelopment: false,
|
isDevelopment: false,
|
||||||
appVersion: '',
|
appVersion: '',
|
||||||
},
|
};
|
||||||
};
|
t = t;
|
||||||
|
T = T;
|
||||||
|
}
|
||||||
|
|
||||||
|
export { T, t };
|
||||||
|
export default new Frappe();
|
||||||
|
@ -1,12 +1,12 @@
|
|||||||
const frappe = require('frappe');
|
import telemetry from '@/telemetry/telemetry';
|
||||||
const Observable = require('frappe/utils/observable');
|
import { Verb } from '@/telemetry/types';
|
||||||
const naming = require('./naming');
|
import frappe from 'frappe';
|
||||||
const { isPesa } = require('../utils/index');
|
import Observable from 'frappe/utils/observable';
|
||||||
const { DEFAULT_INTERNAL_PRECISION } = require('../utils/consts');
|
import { DEFAULT_INTERNAL_PRECISION } from '../utils/consts';
|
||||||
const { Verb } = require('@/telemetry/types');
|
import { isPesa } from '../utils/index';
|
||||||
const { default: telemetry } = require('@/telemetry/telemetry');
|
import { setName } from './naming';
|
||||||
|
|
||||||
module.exports = class BaseDocument extends Observable {
|
export default class Document extends Observable {
|
||||||
constructor(data) {
|
constructor(data) {
|
||||||
super();
|
super();
|
||||||
this.fetchValuesCache = {};
|
this.fetchValuesCache = {};
|
||||||
@ -171,7 +171,7 @@ module.exports = class BaseDocument extends Observable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
_initChild(data, key) {
|
_initChild(data, key) {
|
||||||
if (data instanceof BaseDocument) {
|
if (data instanceof Document) {
|
||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -189,7 +189,7 @@ module.exports = class BaseDocument extends Observable {
|
|||||||
data.name = frappe.getRandomString();
|
data.name = frappe.getRandomString();
|
||||||
}
|
}
|
||||||
|
|
||||||
const childDoc = new BaseDocument(data);
|
const childDoc = new Document(data);
|
||||||
childDoc.setDefaults();
|
childDoc.setDefaults();
|
||||||
return childDoc;
|
return childDoc;
|
||||||
}
|
}
|
||||||
@ -549,10 +549,6 @@ module.exports = class BaseDocument extends Observable {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async setName() {
|
|
||||||
await naming.setName(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
async commit() {
|
async commit() {
|
||||||
// re-run triggers
|
// re-run triggers
|
||||||
this.setKeywords();
|
this.setKeywords();
|
||||||
@ -562,7 +558,7 @@ module.exports = class BaseDocument extends Observable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async insert() {
|
async insert() {
|
||||||
await this.setName();
|
await setName(this);
|
||||||
this.setStandardValues();
|
this.setStandardValues();
|
||||||
await this.commit();
|
await this.commit();
|
||||||
await this.validateInsert();
|
await this.validateInsert();
|
||||||
@ -745,7 +741,7 @@ module.exports = class BaseDocument extends Observable {
|
|||||||
await doc.set(updateMap);
|
await doc.set(updateMap);
|
||||||
await doc.insert();
|
await doc.insert();
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
|
|
||||||
function getPreDefaultValues(fieldtype) {
|
function getPreDefaultValues(fieldtype) {
|
||||||
switch (fieldtype) {
|
switch (fieldtype) {
|
||||||
|
@ -1,16 +1,16 @@
|
|||||||
const BaseDocument = require('./document');
|
import frappe from 'frappe';
|
||||||
const frappe = require('frappe');
|
import { indicators as indicatorColor } from '../../src/colors';
|
||||||
const model = require('./index');
|
import Document from './document';
|
||||||
const { indicators: indicatorColor } = require('../../src/colors');
|
import model from './index';
|
||||||
|
|
||||||
module.exports = class BaseMeta extends BaseDocument {
|
export default class BaseMeta extends Document {
|
||||||
constructor(data) {
|
constructor(data) {
|
||||||
if (data.basedOn) {
|
if (data.basedOn) {
|
||||||
let config = frappe.models[data.basedOn];
|
let config = frappe.models[data.basedOn];
|
||||||
Object.assign(data, config, {
|
Object.assign(data, config, {
|
||||||
name: data.name,
|
name: data.name,
|
||||||
label: data.label,
|
label: data.label,
|
||||||
filters: data.filters
|
filters: data.filters,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
super(data);
|
super(data);
|
||||||
@ -30,7 +30,7 @@ module.exports = class BaseMeta extends BaseDocument {
|
|||||||
|
|
||||||
processFields() {
|
processFields() {
|
||||||
// add name field
|
// add name field
|
||||||
if (!this.fields.find(df => df.fieldname === 'name') && !this.isSingle) {
|
if (!this.fields.find((df) => df.fieldname === 'name') && !this.isSingle) {
|
||||||
this.fields = [
|
this.fields = [
|
||||||
{
|
{
|
||||||
label: frappe.t`ID`,
|
label: frappe.t`ID`,
|
||||||
@ -42,7 +42,7 @@ module.exports = class BaseMeta extends BaseDocument {
|
|||||||
].concat(this.fields);
|
].concat(this.fields);
|
||||||
}
|
}
|
||||||
|
|
||||||
this.fields = this.fields.map(df => {
|
this.fields = this.fields.map((df) => {
|
||||||
// name field is always required
|
// name field is always required
|
||||||
if (df.fieldname === 'name') {
|
if (df.fieldname === 'name') {
|
||||||
df.required = 1;
|
df.required = 1;
|
||||||
@ -75,7 +75,7 @@ module.exports = class BaseMeta extends BaseDocument {
|
|||||||
* dataFields = meta.getFieldsWith({ fieldtype: 'Data' })
|
* dataFields = meta.getFieldsWith({ fieldtype: 'Data' })
|
||||||
*/
|
*/
|
||||||
getFieldsWith(filters) {
|
getFieldsWith(filters) {
|
||||||
return this.fields.filter(df => {
|
return this.fields.filter((df) => {
|
||||||
let match = true;
|
let match = true;
|
||||||
for (const key in filters) {
|
for (const key in filters) {
|
||||||
const value = filters[key];
|
const value = filters[key];
|
||||||
@ -93,7 +93,7 @@ module.exports = class BaseMeta extends BaseDocument {
|
|||||||
getTableFields() {
|
getTableFields() {
|
||||||
if (this._tableFields === undefined) {
|
if (this._tableFields === undefined) {
|
||||||
this._tableFields = this.fields.filter(
|
this._tableFields = this.fields.filter(
|
||||||
field => field.fieldtype === 'Table'
|
(field) => field.fieldtype === 'Table'
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
return this._tableFields;
|
return this._tableFields;
|
||||||
@ -101,7 +101,7 @@ module.exports = class BaseMeta extends BaseDocument {
|
|||||||
|
|
||||||
getFormulaFields() {
|
getFormulaFields() {
|
||||||
if (this._formulaFields === undefined) {
|
if (this._formulaFields === undefined) {
|
||||||
this._formulaFields = this.fields.filter(field => field.formula);
|
this._formulaFields = this.fields.filter((field) => field.formula);
|
||||||
}
|
}
|
||||||
return this._formulaFields;
|
return this._formulaFields;
|
||||||
}
|
}
|
||||||
@ -141,7 +141,7 @@ module.exports = class BaseMeta extends BaseDocument {
|
|||||||
this._validFields = [];
|
this._validFields = [];
|
||||||
this._validFieldsWithChildren = [];
|
this._validFieldsWithChildren = [];
|
||||||
|
|
||||||
const _add = field => {
|
const _add = (field) => {
|
||||||
this._validFields.push(field);
|
this._validFields.push(field);
|
||||||
this._validFieldsWithChildren.push(field);
|
this._validFieldsWithChildren.push(field);
|
||||||
};
|
};
|
||||||
@ -160,7 +160,7 @@ module.exports = class BaseMeta extends BaseDocument {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
const doctypeFields = this.fields.map(field => field.fieldname);
|
const doctypeFields = this.fields.map((field) => field.fieldname);
|
||||||
|
|
||||||
// standard fields
|
// standard fields
|
||||||
for (let field of model.commonFields) {
|
for (let field of model.commonFields) {
|
||||||
@ -176,7 +176,7 @@ module.exports = class BaseMeta extends BaseDocument {
|
|||||||
_add({
|
_add({
|
||||||
fieldtype: 'Check',
|
fieldtype: 'Check',
|
||||||
fieldname: 'submitted',
|
fieldname: 'submitted',
|
||||||
label: frappe.t`Submitted`
|
label: frappe.t`Submitted`,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -241,8 +241,8 @@ module.exports = class BaseMeta extends BaseDocument {
|
|||||||
this._keywordFields = this.keywordFields;
|
this._keywordFields = this.keywordFields;
|
||||||
if (!(this._keywordFields && this._keywordFields.length && this.fields)) {
|
if (!(this._keywordFields && this._keywordFields.length && this.fields)) {
|
||||||
this._keywordFields = this.fields
|
this._keywordFields = this.fields
|
||||||
.filter(field => field.fieldtype !== 'Table' && field.required)
|
.filter((field) => field.fieldtype !== 'Table' && field.required)
|
||||||
.map(field => field.fieldname);
|
.map((field) => field.fieldname);
|
||||||
}
|
}
|
||||||
if (!(this._keywordFields && this._keywordFields.length)) {
|
if (!(this._keywordFields && this._keywordFields.length)) {
|
||||||
this._keywordFields = ['name'];
|
this._keywordFields = ['name'];
|
||||||
@ -253,7 +253,7 @@ module.exports = class BaseMeta extends BaseDocument {
|
|||||||
|
|
||||||
getQuickEditFields() {
|
getQuickEditFields() {
|
||||||
if (this.quickEditFields) {
|
if (this.quickEditFields) {
|
||||||
return this.quickEditFields.map(fieldname => this.getField(fieldname));
|
return this.quickEditFields.map((fieldname) => this.getField(fieldname));
|
||||||
}
|
}
|
||||||
return this.getFieldsWith({ required: 1 });
|
return this.getFieldsWith({ required: 1 });
|
||||||
}
|
}
|
||||||
@ -271,10 +271,12 @@ module.exports = class BaseMeta extends BaseDocument {
|
|||||||
// values given as string
|
// values given as string
|
||||||
validValues = options.split('\n');
|
validValues = options.split('\n');
|
||||||
}
|
}
|
||||||
|
|
||||||
if (typeof options[0] === 'object') {
|
if (typeof options[0] === 'object') {
|
||||||
// options as array of {label, value} pairs
|
// options as array of {label, value} pairs
|
||||||
validValues = options.map(o => o.value);
|
validValues = options.map((o) => o.value);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!validValues.includes(value)) {
|
if (!validValues.includes(value)) {
|
||||||
throw new frappe.errors.ValueError(
|
throw new frappe.errors.ValueError(
|
||||||
// prettier-ignore
|
// prettier-ignore
|
||||||
@ -287,7 +289,7 @@ module.exports = class BaseMeta extends BaseDocument {
|
|||||||
async trigger(event, params = {}) {
|
async trigger(event, params = {}) {
|
||||||
Object.assign(params, {
|
Object.assign(params, {
|
||||||
doc: this,
|
doc: this,
|
||||||
name: event
|
name: event,
|
||||||
});
|
});
|
||||||
|
|
||||||
await super.trigger(event, params);
|
await super.trigger(event, params);
|
||||||
@ -300,8 +302,8 @@ module.exports = class BaseMeta extends BaseDocument {
|
|||||||
key: 'submitted',
|
key: 'submitted',
|
||||||
colors: {
|
colors: {
|
||||||
0: indicatorColor.GRAY,
|
0: indicatorColor.GRAY,
|
||||||
1: indicatorColor.BLUE
|
1: indicatorColor.BLUE,
|
||||||
}
|
},
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -323,4 +325,4 @@ module.exports = class BaseMeta extends BaseDocument {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
|
@ -1,122 +1,119 @@
|
|||||||
const { getPaddedName } = require('@/utils');
|
import frappe from 'frappe';
|
||||||
const frappe = require('frappe');
|
import { getRandomString } from 'frappe/utils';
|
||||||
const { getRandomString } = require('frappe/utils');
|
|
||||||
|
|
||||||
module.exports = {
|
export async function isNameAutoSet(doctype) {
|
||||||
async isNameAutoSet(doctype) {
|
const doc = frappe.getNewDoc(doctype);
|
||||||
const doc = frappe.getNewDoc(doctype);
|
if (doc.meta.naming === 'autoincrement') {
|
||||||
if (doc.meta.naming === 'autoincrement') {
|
return true;
|
||||||
return true;
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if (!doc.meta.settings) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
const { numberSeries } = await doc.getSettings();
|
|
||||||
if (numberSeries) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
if (!doc.meta.settings) {
|
||||||
return false;
|
return false;
|
||||||
},
|
}
|
||||||
|
|
||||||
async setName(doc) {
|
const { numberSeries } = await doc.getSettings();
|
||||||
if (frappe.isServer) {
|
if (numberSeries) {
|
||||||
// if is server, always name again if autoincrement or other
|
return true;
|
||||||
if (doc.meta.naming === 'autoincrement') {
|
}
|
||||||
doc.name = await this.getNextId(doc.doctype);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Current, per doc number series
|
return false;
|
||||||
if (doc.numberSeries) {
|
}
|
||||||
doc.name = await this.getSeriesNext(doc.numberSeries, doc.doctype);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Legacy, using doc settings for number series
|
export async function setName(doc) {
|
||||||
if (doc.meta.settings) {
|
if (frappe.isServer) {
|
||||||
const numberSeries = (await doc.getSettings()).numberSeries;
|
// if is server, always name again if autoincrement or other
|
||||||
if (!numberSeries) {
|
if (doc.meta.naming === 'autoincrement') {
|
||||||
return;
|
doc.name = await getNextId(doc.doctype);
|
||||||
}
|
|
||||||
|
|
||||||
doc.name = await this.getSeriesNext(numberSeries, doc.doctype);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (doc.name) {
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// name === doctype for Single
|
// Current, per doc number series
|
||||||
if (doc.meta.isSingle) {
|
if (doc.numberSeries) {
|
||||||
doc.name = doc.meta.name;
|
doc.name = await getSeriesNext(doc.numberSeries, doc.doctype);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// assign a random name by default
|
// Legacy, using doc settings for number series
|
||||||
// override doc to set a name
|
if (doc.meta.settings) {
|
||||||
if (!doc.name) {
|
const numberSeries = (await doc.getSettings()).numberSeries;
|
||||||
doc.name = getRandomString();
|
if (!numberSeries) {
|
||||||
}
|
return;
|
||||||
},
|
|
||||||
|
|
||||||
async getNextId(doctype) {
|
|
||||||
// get the last inserted row
|
|
||||||
let lastInserted = await this.getLastInserted(doctype);
|
|
||||||
let name = 1;
|
|
||||||
if (lastInserted) {
|
|
||||||
let lastNumber = parseInt(lastInserted.name);
|
|
||||||
if (isNaN(lastNumber)) lastNumber = 0;
|
|
||||||
name = lastNumber + 1;
|
|
||||||
}
|
|
||||||
return (name + '').padStart(9, '0');
|
|
||||||
},
|
|
||||||
|
|
||||||
async getLastInserted(doctype) {
|
|
||||||
const lastInserted = await frappe.db.getAll({
|
|
||||||
doctype: doctype,
|
|
||||||
fields: ['name'],
|
|
||||||
limit: 1,
|
|
||||||
order_by: 'creation',
|
|
||||||
order: 'desc',
|
|
||||||
});
|
|
||||||
return lastInserted && lastInserted.length ? lastInserted[0] : null;
|
|
||||||
},
|
|
||||||
|
|
||||||
async getSeriesNext(prefix, doctype) {
|
|
||||||
let series;
|
|
||||||
|
|
||||||
try {
|
|
||||||
series = await frappe.getDoc('NumberSeries', prefix);
|
|
||||||
} catch (e) {
|
|
||||||
if (!e.statusCode || e.statusCode !== 404) {
|
|
||||||
throw e;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
await this.createNumberSeries(prefix, doctype);
|
doc.name = await getSeriesNext(numberSeries, doc.doctype);
|
||||||
series = await frappe.getDoc('NumberSeries', prefix);
|
|
||||||
}
|
|
||||||
|
|
||||||
return await series.next(doctype);
|
|
||||||
},
|
|
||||||
|
|
||||||
async createNumberSeries(prefix, referenceType, start = 1001) {
|
|
||||||
const exists = await frappe.db.exists('NumberSeries', prefix);
|
|
||||||
if (exists) {
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const series = frappe.newDoc({
|
if (doc.name) {
|
||||||
doctype: 'NumberSeries',
|
return;
|
||||||
name: prefix,
|
}
|
||||||
start,
|
|
||||||
referenceType,
|
|
||||||
});
|
|
||||||
|
|
||||||
await series.insert();
|
// name === doctype for Single
|
||||||
},
|
if (doc.meta.isSingle) {
|
||||||
};
|
doc.name = doc.meta.name;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// assign a random name by default
|
||||||
|
// override doc to set a name
|
||||||
|
if (!doc.name) {
|
||||||
|
doc.name = getRandomString();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function getNextId(doctype) {
|
||||||
|
// get the last inserted row
|
||||||
|
let lastInserted = await getLastInserted(doctype);
|
||||||
|
let name = 1;
|
||||||
|
if (lastInserted) {
|
||||||
|
let lastNumber = parseInt(lastInserted.name);
|
||||||
|
if (isNaN(lastNumber)) lastNumber = 0;
|
||||||
|
name = lastNumber + 1;
|
||||||
|
}
|
||||||
|
return (name + '').padStart(9, '0');
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function getLastInserted(doctype) {
|
||||||
|
const lastInserted = await frappe.db.getAll({
|
||||||
|
doctype: doctype,
|
||||||
|
fields: ['name'],
|
||||||
|
limit: 1,
|
||||||
|
order_by: 'creation',
|
||||||
|
order: 'desc',
|
||||||
|
});
|
||||||
|
return lastInserted && lastInserted.length ? lastInserted[0] : null;
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function getSeriesNext(prefix, doctype) {
|
||||||
|
let series;
|
||||||
|
|
||||||
|
try {
|
||||||
|
series = await frappe.getDoc('NumberSeries', prefix);
|
||||||
|
} catch (e) {
|
||||||
|
if (!e.statusCode || e.statusCode !== 404) {
|
||||||
|
throw e;
|
||||||
|
}
|
||||||
|
|
||||||
|
await createNumberSeries(prefix, doctype);
|
||||||
|
series = await frappe.getDoc('NumberSeries', prefix);
|
||||||
|
}
|
||||||
|
|
||||||
|
return await series.next(doctype);
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function createNumberSeries(prefix, referenceType, start = 1001) {
|
||||||
|
const exists = await frappe.db.exists('NumberSeries', prefix);
|
||||||
|
if (exists) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const series = frappe.newDoc({
|
||||||
|
doctype: 'NumberSeries',
|
||||||
|
name: prefix,
|
||||||
|
start,
|
||||||
|
referenceType,
|
||||||
|
});
|
||||||
|
|
||||||
|
await series.insert();
|
||||||
|
}
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
const frappe = require('frappe');
|
import frappe from 'frappe';
|
||||||
|
|
||||||
module.exports = async function runPatches(patchList) {
|
export default async function runPatches(patchList) {
|
||||||
const patchesAlreadyRun = (
|
const patchesAlreadyRun = (
|
||||||
await frappe.db.knex('PatchRun').select('name')
|
await frappe.db.knex('PatchRun').select('name')
|
||||||
).map(({ name }) => name);
|
).map(({ name }) => name);
|
||||||
@ -12,7 +12,7 @@ module.exports = async function runPatches(patchList) {
|
|||||||
|
|
||||||
await runPatch(patch);
|
await runPatch(patch);
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
|
|
||||||
async function runPatch({ patchName, patchFunction }) {
|
async function runPatch({ patchName, patchFunction }) {
|
||||||
try {
|
try {
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
const { t } = require('frappe');
|
import { t } from 'frappe';
|
||||||
|
import NumberSeries from './NumberSeriesDocument.js';
|
||||||
|
|
||||||
const referenceTypeMap = {
|
const referenceTypeMap = {
|
||||||
SalesInvoice: t`Invoice`,
|
SalesInvoice: t`Invoice`,
|
||||||
@ -13,9 +14,10 @@ const referenceTypeMap = {
|
|||||||
'-': t`None`,
|
'-': t`None`,
|
||||||
};
|
};
|
||||||
|
|
||||||
module.exports = {
|
export default {
|
||||||
name: 'NumberSeries',
|
name: 'NumberSeries',
|
||||||
documentClass: require('./NumberSeriesDocument.js'),
|
label: t`Number Series`,
|
||||||
|
documentClass: NumberSeries,
|
||||||
doctype: 'DocType',
|
doctype: 'DocType',
|
||||||
isSingle: 0,
|
isSingle: 0,
|
||||||
isChild: 0,
|
isChild: 0,
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
const { getPaddedName } = require('@/utils');
|
import { getPaddedName } from '@/utils';
|
||||||
const frappe = require('frappe');
|
import frappe from 'frappe';
|
||||||
const BaseDocument = require('frappe/model/document');
|
import BaseDocument from 'frappe/model/document';
|
||||||
|
|
||||||
module.exports = class NumberSeries extends BaseDocument {
|
export default class NumberSeries extends BaseDocument {
|
||||||
validate() {
|
validate() {
|
||||||
if (!this.current) {
|
if (!this.current) {
|
||||||
this.current = this.start;
|
this.current = this.start;
|
||||||
@ -34,4 +34,4 @@ module.exports = class NumberSeries extends BaseDocument {
|
|||||||
getPaddedName(next) {
|
getPaddedName(next) {
|
||||||
return getPaddedName(this.name, next, this.padZeros);
|
return getPaddedName(this.name, next, this.padZeros);
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
|
@ -1,13 +1,25 @@
|
|||||||
module.exports = {
|
import File from './doctype/File/File.js';
|
||||||
NumberSeries: require('./doctype/NumberSeries/NumberSeries.js'),
|
import NumberSeries from './doctype/NumberSeries/NumberSeries.js';
|
||||||
PrintFormat: require('./doctype/PrintFormat/PrintFormat.js'),
|
import PatchRun from './doctype/PatchRun/PatchRun.js';
|
||||||
Role: require('./doctype/Role/Role.js'),
|
import PrintFormat from './doctype/PrintFormat/PrintFormat.js';
|
||||||
Session: require('./doctype/Session/Session.js'),
|
import Role from './doctype/Role/Role.js';
|
||||||
SingleValue: require('./doctype/SingleValue/SingleValue.js'),
|
import Session from './doctype/Session/Session.js';
|
||||||
SystemSettings: require('./doctype/SystemSettings/SystemSettings.js'),
|
import SingleValue from './doctype/SingleValue/SingleValue.js';
|
||||||
ToDo: require('./doctype/ToDo/ToDo.js'),
|
import SystemSettings from './doctype/SystemSettings/SystemSettings.js';
|
||||||
User: require('./doctype/User/User.js'),
|
import ToDo from './doctype/ToDo/ToDo.js';
|
||||||
UserRole: require('./doctype/UserRole/UserRole.js'),
|
import User from './doctype/User/User.js';
|
||||||
File: require('./doctype/File/File.js'),
|
import UserRole from './doctype/UserRole/UserRole.js';
|
||||||
PatchRun: require('./doctype/PatchRun/PatchRun.js')
|
|
||||||
|
export default {
|
||||||
|
NumberSeries,
|
||||||
|
PrintFormat,
|
||||||
|
Role,
|
||||||
|
Session,
|
||||||
|
SingleValue,
|
||||||
|
SystemSettings,
|
||||||
|
ToDo,
|
||||||
|
User,
|
||||||
|
UserRole,
|
||||||
|
File,
|
||||||
|
PatchRun,
|
||||||
};
|
};
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
const luxon = require('luxon');
|
import frappe from 'frappe';
|
||||||
const frappe = require('frappe');
|
import { DateTime } from 'luxon';
|
||||||
const { DEFAULT_DISPLAY_PRECISION, DEFAULT_LOCALE } = require('./consts');
|
import { DEFAULT_DISPLAY_PRECISION, DEFAULT_LOCALE } from './consts';
|
||||||
|
|
||||||
module.exports = {
|
export default {
|
||||||
format(value, df, doc) {
|
format(value, df, doc) {
|
||||||
if (!df) {
|
if (!df) {
|
||||||
return value;
|
return value;
|
||||||
@ -25,10 +25,10 @@ module.exports = {
|
|||||||
|
|
||||||
if (typeof value === 'string') {
|
if (typeof value === 'string') {
|
||||||
// ISO String
|
// ISO String
|
||||||
value = luxon.DateTime.fromISO(value);
|
value = DateTime.fromISO(value);
|
||||||
} else if (Object.prototype.toString.call(value) === '[object Date]') {
|
} else if (Object.prototype.toString.call(value) === '[object Date]') {
|
||||||
// JS Date
|
// JS Date
|
||||||
value = luxon.DateTime.fromJSDate(value);
|
value = DateTime.fromJSDate(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
value = value.toFormat(dateFormat);
|
value = value.toFormat(dateFormat);
|
||||||
|
@ -1,128 +0,0 @@
|
|||||||
module.exports = class Observable {
|
|
||||||
constructor() {
|
|
||||||
this._observable = {
|
|
||||||
isHot: {},
|
|
||||||
eventQueue: {},
|
|
||||||
listeners: {},
|
|
||||||
onceListeners: {}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// getter, setter stubs, so Observable can be used as a simple Document
|
|
||||||
get(key) {
|
|
||||||
return this[key];
|
|
||||||
}
|
|
||||||
|
|
||||||
set(key, value) {
|
|
||||||
this[key] = value;
|
|
||||||
this.trigger('change', {
|
|
||||||
doc: this,
|
|
||||||
fieldname: key
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
on(event, listener) {
|
|
||||||
this._addListener('listeners', event, listener);
|
|
||||||
if (this._observable.socketClient) {
|
|
||||||
this._observable.socketClient.on(event, listener);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// remove listener
|
|
||||||
off(event, listener) {
|
|
||||||
for (let type of ['listeners', 'onceListeners']) {
|
|
||||||
let index = this._observable[type][event] && this._observable[type][event].indexOf(listener);
|
|
||||||
if (index) {
|
|
||||||
this._observable[type][event].splice(index, 1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
once(event, listener) {
|
|
||||||
this._addListener('onceListeners', event, listener);
|
|
||||||
}
|
|
||||||
|
|
||||||
async trigger(event, params, throttle = false) {
|
|
||||||
if (throttle) {
|
|
||||||
if (this._throttled(event, params, throttle)) return;
|
|
||||||
params = [params]
|
|
||||||
}
|
|
||||||
|
|
||||||
await this._executeTriggers(event, params);
|
|
||||||
}
|
|
||||||
|
|
||||||
async _executeTriggers(event, params) {
|
|
||||||
let response = await this._triggerEvent('listeners', event, params);
|
|
||||||
if (response === false) return false;
|
|
||||||
|
|
||||||
response = await this._triggerEvent('onceListeners', event, params);
|
|
||||||
if (response === false) return false;
|
|
||||||
|
|
||||||
// emit via socket
|
|
||||||
if (this._observable.socketServer) {
|
|
||||||
this._observable.socketServer.emit(event, params);
|
|
||||||
}
|
|
||||||
|
|
||||||
// clear once-listeners
|
|
||||||
if (this._observable.onceListeners && this._observable.onceListeners[event]) {
|
|
||||||
delete this._observable.onceListeners[event];
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
clearListeners() {
|
|
||||||
this._observable.listeners = {};
|
|
||||||
this._observable.onceListeners = {};
|
|
||||||
}
|
|
||||||
|
|
||||||
bindSocketClient(socket) {
|
|
||||||
// also send events with sockets
|
|
||||||
this._observable.socketClient = socket;
|
|
||||||
}
|
|
||||||
|
|
||||||
bindSocketServer(socket) {
|
|
||||||
// also send events with sockets
|
|
||||||
this._observable.socketServer = socket;
|
|
||||||
}
|
|
||||||
|
|
||||||
_throttled(event, params, throttle) {
|
|
||||||
if (this._observable.isHot[event]) {
|
|
||||||
// hot, add to queue
|
|
||||||
if (!this._observable.eventQueue[event]) this._observable.eventQueue[event] = [];
|
|
||||||
this._observable.eventQueue[event].push(params);
|
|
||||||
|
|
||||||
// aleady hot, quit
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
this._observable.isHot[event] = true;
|
|
||||||
|
|
||||||
// cool-off
|
|
||||||
setTimeout(() => {
|
|
||||||
this._observable.isHot[event] = false;
|
|
||||||
|
|
||||||
// flush queue
|
|
||||||
if (this._observable.eventQueue[event]) {
|
|
||||||
let _queuedParams = this._observable.eventQueue[event];
|
|
||||||
this._observable.eventQueue[event] = null;
|
|
||||||
this._executeTriggers(event, _queuedParams);
|
|
||||||
}
|
|
||||||
}, throttle);
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
_addListener(type, event, listener) {
|
|
||||||
if (!this._observable[type][event]) {
|
|
||||||
this._observable[type][event] = [];
|
|
||||||
}
|
|
||||||
this._observable[type][event].push(listener);
|
|
||||||
}
|
|
||||||
|
|
||||||
async _triggerEvent(type, event, params) {
|
|
||||||
if (this._observable[type][event]) {
|
|
||||||
for (let listener of this._observable[type][event]) {
|
|
||||||
await listener(params);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
170
frappe/utils/observable.ts
Normal file
170
frappe/utils/observable.ts
Normal file
@ -0,0 +1,170 @@
|
|||||||
|
enum EventType {
|
||||||
|
Listeners = '_listeners',
|
||||||
|
OnceListeners = '_onceListeners',
|
||||||
|
}
|
||||||
|
|
||||||
|
export default class Observable {
|
||||||
|
[key: string]: unknown;
|
||||||
|
_isHot: Map<string, boolean>;
|
||||||
|
_eventQueue: Map<string, unknown[]>;
|
||||||
|
_map: Map<string, unknown>;
|
||||||
|
_listeners: Map<string, Function[]>;
|
||||||
|
_onceListeners: Map<string, Function[]>;
|
||||||
|
|
||||||
|
constructor() {
|
||||||
|
this._map = new Map();
|
||||||
|
this._isHot = new Map();
|
||||||
|
this._eventQueue = new Map();
|
||||||
|
this._listeners = new Map();
|
||||||
|
this._onceListeners = new Map();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Getter to use Observable as a regular document.
|
||||||
|
*
|
||||||
|
* @param key
|
||||||
|
* @returns
|
||||||
|
*/
|
||||||
|
get(key: string): unknown {
|
||||||
|
return this[key];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Setter to use Observable as a regular document.
|
||||||
|
*
|
||||||
|
* @param key
|
||||||
|
* @param value
|
||||||
|
*/
|
||||||
|
set(key: string, value: unknown) {
|
||||||
|
this[key] = value;
|
||||||
|
this.trigger('change', {
|
||||||
|
doc: this,
|
||||||
|
fieldname: key,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets a `listener` that executes every time `event` is triggered
|
||||||
|
*
|
||||||
|
* @param event : name of the event for which the listener is set
|
||||||
|
* @param listener : listener that is executed when the event is triggered
|
||||||
|
*/
|
||||||
|
on(event: string, listener: Function) {
|
||||||
|
this._addListener(EventType.Listeners, event, listener);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets a `listener` that execture `once`: executes once when `event` is
|
||||||
|
* triggered then deletes itself
|
||||||
|
*
|
||||||
|
* @param event : name of the event for which the listener is set
|
||||||
|
* @param listener : listener that is executed when the event is triggered
|
||||||
|
*/
|
||||||
|
once(event: string, listener: Function) {
|
||||||
|
this._addListener(EventType.OnceListeners, event, listener);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Remove a listener from an event for both 'on' and 'once'
|
||||||
|
*
|
||||||
|
* @param event : name of the event from which to remove the listener
|
||||||
|
* @param listener : listener that was set for the event
|
||||||
|
*/
|
||||||
|
off(event: string, listener: Function) {
|
||||||
|
this._removeListener(EventType.Listeners, event, listener);
|
||||||
|
this._removeListener(EventType.OnceListeners, event, listener);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Remove all the listeners.
|
||||||
|
*/
|
||||||
|
clear() {
|
||||||
|
this._listeners.clear();
|
||||||
|
this._onceListeners.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Triggers the event's listener function.
|
||||||
|
*
|
||||||
|
* @param event : name of the event to be triggered.
|
||||||
|
* @param params : params to pass to the listeners.
|
||||||
|
* @param throttle : wait time before triggering the event.
|
||||||
|
*/
|
||||||
|
|
||||||
|
async trigger(event: string, params: unknown, throttle: number = 0) {
|
||||||
|
let isHot = false;
|
||||||
|
if (throttle > 0) {
|
||||||
|
isHot = this._throttled(event, params, throttle);
|
||||||
|
params = [params];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isHot) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
await this._executeTriggers(event, params);
|
||||||
|
}
|
||||||
|
|
||||||
|
_removeListener(type: EventType, event: string, listener: Function) {
|
||||||
|
const listeners = (this[type].get(event) ?? []).filter(
|
||||||
|
(l) => l !== listener
|
||||||
|
);
|
||||||
|
this[type].set(event, listeners);
|
||||||
|
}
|
||||||
|
|
||||||
|
async _executeTriggers(event: string, params?: unknown) {
|
||||||
|
await this._triggerEvent(EventType.Listeners, event, params);
|
||||||
|
await this._triggerEvent(EventType.OnceListeners, event, params);
|
||||||
|
this._onceListeners.delete(event);
|
||||||
|
}
|
||||||
|
|
||||||
|
_throttled(event: string, params: unknown, throttle: number) {
|
||||||
|
/**
|
||||||
|
* Throttled events execute after `throttle` ms, during this period
|
||||||
|
* isHot is true, i.e it's going to execute.
|
||||||
|
*/
|
||||||
|
|
||||||
|
if (!this._eventQueue.has(event)) {
|
||||||
|
this._eventQueue.set(event, []);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this._isHot.get(event)) {
|
||||||
|
this._eventQueue.get(event)!.push(params);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
this._isHot.set(event, true);
|
||||||
|
|
||||||
|
setTimeout(() => {
|
||||||
|
this._isHot.set(event, false);
|
||||||
|
|
||||||
|
const params = this._eventQueue.get(event);
|
||||||
|
if (params !== undefined) {
|
||||||
|
this._executeTriggers(event, params);
|
||||||
|
this._eventQueue.delete(event);
|
||||||
|
}
|
||||||
|
}, throttle);
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
_addListener(type: EventType, event: string, listener: Function) {
|
||||||
|
this._initLiseners(type, event);
|
||||||
|
this[type].get(event)!.push(listener);
|
||||||
|
}
|
||||||
|
|
||||||
|
_initLiseners(type: EventType, event: string) {
|
||||||
|
if (this[type].has(event)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
this[type].set(event, []);
|
||||||
|
}
|
||||||
|
|
||||||
|
async _triggerEvent(type: EventType, event: string, params?: unknown) {
|
||||||
|
const listeners = this[type].get(event) ?? [];
|
||||||
|
for (const listener of listeners) {
|
||||||
|
await listener(params);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -1,5 +1,5 @@
|
|||||||
import frappe from 'frappe';
|
import frappe from 'frappe';
|
||||||
import naming from 'frappe/model/naming';
|
import { createNumberSeries } from 'frappe/model/naming';
|
||||||
import GSTR3BServer from '../models/doctype/GSTR3B/GSTR3BServer.js';
|
import GSTR3BServer from '../models/doctype/GSTR3B/GSTR3BServer.js';
|
||||||
import JournalEntryServer from '../models/doctype/JournalEntry/JournalEntryServer.js';
|
import JournalEntryServer from '../models/doctype/JournalEntry/JournalEntryServer.js';
|
||||||
import PartyServer from '../models/doctype/Party/PartyServer.js';
|
import PartyServer from '../models/doctype/Party/PartyServer.js';
|
||||||
@ -20,10 +20,10 @@ export default async function postStart() {
|
|||||||
frappe.metaCache = {};
|
frappe.metaCache = {};
|
||||||
|
|
||||||
// init naming series if missing
|
// init naming series if missing
|
||||||
await naming.createNumberSeries('SINV-', 'SalesInvoice');
|
await createNumberSeries('SINV-', 'SalesInvoice');
|
||||||
await naming.createNumberSeries('PINV-', 'PurchaseInvoice');
|
await createNumberSeries('PINV-', 'PurchaseInvoice');
|
||||||
await naming.createNumberSeries('PAY-', 'Payment');
|
await createNumberSeries('PAY-', 'Payment');
|
||||||
await naming.createNumberSeries('JV-', 'JournalEntry');
|
await createNumberSeries('JV-', 'JournalEntry');
|
||||||
// await naming.createNumberSeries('QTN-', 'QuotationSettings');
|
// await naming.createNumberSeries('QTN-', 'QuotationSettings');
|
||||||
// await naming.createNumberSeries('SO-', 'SalesOrderSettings');
|
// await naming.createNumberSeries('SO-', 'SalesOrderSettings');
|
||||||
// await naming.createNumberSeries('OF-', 'FulfillmentSettings');
|
// await naming.createNumberSeries('OF-', 'FulfillmentSettings');
|
||||||
|
10
src/App.vue
10
src/App.vue
@ -33,9 +33,9 @@
|
|||||||
import WindowsTitleBar from '@/components/WindowsTitleBar';
|
import WindowsTitleBar from '@/components/WindowsTitleBar';
|
||||||
import config from '@/config';
|
import config from '@/config';
|
||||||
import {
|
import {
|
||||||
connectToLocalDatabase,
|
connectToLocalDatabase,
|
||||||
postSetup,
|
postSetup,
|
||||||
purgeCache
|
purgeCache,
|
||||||
} from '@/initialization';
|
} from '@/initialization';
|
||||||
import { IPC_ACTIONS, IPC_MESSAGES } from '@/messages';
|
import { IPC_ACTIONS, IPC_MESSAGES } from '@/messages';
|
||||||
import { ipcRenderer } from 'electron';
|
import { ipcRenderer } from 'electron';
|
||||||
@ -131,10 +131,10 @@ export default {
|
|||||||
routeTo('/get-started');
|
routeTo('/get-started');
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
changeDbFile() {
|
async changeDbFile() {
|
||||||
config.set('lastSelectedFilePath', null);
|
config.set('lastSelectedFilePath', null);
|
||||||
telemetry.stop();
|
telemetry.stop();
|
||||||
purgeCache(true);
|
await purgeCache(true);
|
||||||
this.activeScreen = 'DatabaseSelector';
|
this.activeScreen = 'DatabaseSelector';
|
||||||
},
|
},
|
||||||
async setupCanceled() {
|
async setupCanceled() {
|
||||||
|
@ -6,7 +6,7 @@ import {
|
|||||||
MandatoryError,
|
MandatoryError,
|
||||||
ValidationError,
|
ValidationError,
|
||||||
} from 'frappe/common/errors';
|
} from 'frappe/common/errors';
|
||||||
import BaseDocument from 'frappe/model/document';
|
import Document from 'frappe/model/document';
|
||||||
import config, { ConfigKeys, TelemetrySetting } from './config';
|
import config, { ConfigKeys, TelemetrySetting } from './config';
|
||||||
import { IPC_ACTIONS, IPC_MESSAGES } from './messages';
|
import { IPC_ACTIONS, IPC_MESSAGES } from './messages';
|
||||||
import telemetry from './telemetry/telemetry';
|
import telemetry from './telemetry/telemetry';
|
||||||
@ -110,7 +110,7 @@ export function handleError(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getErrorMessage(e: Error, doc?: BaseDocument): string {
|
export function getErrorMessage(e: Error, doc?: Document): string {
|
||||||
let errorMessage = e.message || t`An error occurred.`;
|
let errorMessage = e.message || t`An error occurred.`;
|
||||||
|
|
||||||
const { doctype, name }: { doctype?: unknown; name?: unknown } = doc ?? {};
|
const { doctype, name }: { doctype?: unknown; name?: unknown } = doc ?? {};
|
||||||
@ -125,7 +125,7 @@ export function getErrorMessage(e: Error, doc?: BaseDocument): string {
|
|||||||
return errorMessage;
|
return errorMessage;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function handleErrorWithDialog(error: Error, doc?: BaseDocument) {
|
export function handleErrorWithDialog(error: Error, doc?: Document) {
|
||||||
const errorMessage = getErrorMessage(error, doc);
|
const errorMessage = getErrorMessage(error, doc);
|
||||||
handleError(false, error, { errorMessage, doc });
|
handleError(false, error, { errorMessage, doc });
|
||||||
|
|
||||||
|
@ -106,7 +106,7 @@ export async function connectToLocalDatabase(filePath) {
|
|||||||
return { connectionSuccess: true, reason: '' };
|
return { connectionSuccess: true, reason: '' };
|
||||||
}
|
}
|
||||||
|
|
||||||
export function purgeCache(purgeAll = false) {
|
export async function purgeCache(purgeAll = false) {
|
||||||
const filterFunction = purgeAll
|
const filterFunction = purgeAll
|
||||||
? () => true
|
? () => true
|
||||||
: (d) => frappe.docs[d][d] instanceof frappe.BaseMeta;
|
: (d) => frappe.docs[d][d] instanceof frappe.BaseMeta;
|
||||||
@ -120,7 +120,7 @@ export function purgeCache(purgeAll = false) {
|
|||||||
|
|
||||||
if (purgeAll) {
|
if (purgeAll) {
|
||||||
delete frappe.db;
|
delete frappe.db;
|
||||||
frappe.initializeAndRegister(models, true);
|
await frappe.initializeAndRegister(models, true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -25,7 +25,7 @@ import { setLanguageMap, stringifyCircular } from './utils';
|
|||||||
frappe.isServer = true;
|
frappe.isServer = true;
|
||||||
frappe.isElectron = true;
|
frappe.isElectron = true;
|
||||||
|
|
||||||
frappe.initializeAndRegister(models);
|
await frappe.initializeAndRegister(models);
|
||||||
|
|
||||||
ipcRenderer.send = getErrorHandled(ipcRenderer.send);
|
ipcRenderer.send = getErrorHandled(ipcRenderer.send);
|
||||||
ipcRenderer.invoke = getErrorHandled(ipcRenderer.invoke);
|
ipcRenderer.invoke = getErrorHandled(ipcRenderer.invoke);
|
||||||
|
@ -89,25 +89,23 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import frappe from 'frappe';
|
|
||||||
import TwoColumnForm from '@/components/TwoColumnForm';
|
|
||||||
import FormControl from '@/components/Controls/FormControl';
|
import FormControl from '@/components/Controls/FormControl';
|
||||||
import setupCompany from './setupCompany';
|
|
||||||
import Popover from '@/components/Popover';
|
|
||||||
import config from '@/config';
|
|
||||||
import path from 'path';
|
|
||||||
import fs from 'fs';
|
|
||||||
import { purgeCache, connectToLocalDatabase } from '@/initialization';
|
|
||||||
import { setLanguageMap, showMessageDialog } from '@/utils';
|
|
||||||
import {
|
|
||||||
handleErrorWithDialog,
|
|
||||||
getErrorMessage,
|
|
||||||
showErrorDialog,
|
|
||||||
} from '../../errorHandling';
|
|
||||||
import Slide from './Slide.vue';
|
|
||||||
import LanguageSelector from '@/components/Controls/LanguageSelector.vue';
|
import LanguageSelector from '@/components/Controls/LanguageSelector.vue';
|
||||||
import { ipcRenderer } from 'electron';
|
import Popover from '@/components/Popover';
|
||||||
|
import TwoColumnForm from '@/components/TwoColumnForm';
|
||||||
|
import config from '@/config';
|
||||||
|
import { connectToLocalDatabase, purgeCache } from '@/initialization';
|
||||||
import { IPC_MESSAGES } from '@/messages';
|
import { IPC_MESSAGES } from '@/messages';
|
||||||
|
import { setLanguageMap, showMessageDialog } from '@/utils';
|
||||||
|
import { ipcRenderer } from 'electron';
|
||||||
|
import frappe from 'frappe';
|
||||||
|
import fs from 'fs';
|
||||||
|
import path from 'path';
|
||||||
|
import {
|
||||||
|
getErrorMessage, handleErrorWithDialog, showErrorDialog
|
||||||
|
} from '../../errorHandling';
|
||||||
|
import setupCompany from './setupCompany';
|
||||||
|
import Slide from './Slide.vue';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'SetupWizard',
|
name: 'SetupWizard',
|
||||||
@ -209,7 +207,7 @@ export default {
|
|||||||
const filePath = config.get('lastSelectedFilePath');
|
const filePath = config.get('lastSelectedFilePath');
|
||||||
renameDbFile(filePath);
|
renameDbFile(filePath);
|
||||||
|
|
||||||
purgeCache();
|
await purgeCache();
|
||||||
|
|
||||||
const { connectionSuccess, reason } = await connectToLocalDatabase(
|
const { connectionSuccess, reason } = await connectToLocalDatabase(
|
||||||
filePath
|
filePath
|
||||||
|
Loading…
Reference in New Issue
Block a user