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

3654 lines
770 KiB
JavaScript
Raw Normal View History

2018-01-08 12:29:49 +00:00
/******/ (function(modules) { // webpackBootstrap
/******/ // The module cache
/******/ var installedModules = {};
/******/
/******/ // The require function
/******/ function __webpack_require__(moduleId) {
/******/
/******/ // Check if module is in cache
/******/ if(installedModules[moduleId]) {
/******/ return installedModules[moduleId].exports;
/******/ }
/******/ // Create a new module (and put it into the cache)
/******/ var module = installedModules[moduleId] = {
/******/ i: moduleId,
/******/ l: false,
/******/ exports: {}
/******/ };
/******/
/******/ // Execute the module function
/******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);
/******/
/******/ // Flag the module as loaded
/******/ module.l = true;
/******/
/******/ // Return the exports of the module
/******/ return module.exports;
/******/ }
/******/
/******/
/******/ // expose the modules object (__webpack_modules__)
/******/ __webpack_require__.m = modules;
/******/
/******/ // expose the module cache
/******/ __webpack_require__.c = installedModules;
/******/
/******/ // define getter function for harmony exports
/******/ __webpack_require__.d = function(exports, name, getter) {
/******/ if(!__webpack_require__.o(exports, name)) {
/******/ Object.defineProperty(exports, name, {
/******/ configurable: false,
/******/ enumerable: true,
/******/ get: getter
/******/ });
/******/ }
/******/ };
/******/
/******/ // getDefaultExport function for compatibility with non-harmony modules
/******/ __webpack_require__.n = function(module) {
/******/ var getter = module && module.__esModule ?
/******/ function getDefault() { return module['default']; } :
/******/ function getModuleExports() { return module; };
/******/ __webpack_require__.d(getter, 'a', getter);
/******/ return getter;
/******/ };
/******/
/******/ // Object.prototype.hasOwnProperty.call
/******/ __webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };
/******/
/******/ // __webpack_public_path__
/******/ __webpack_require__.p = "/";
/******/
/******/ // Load entry module and return exports
2018-01-25 10:05:24 +00:00
/******/ return __webpack_require__(__webpack_require__.s = 7);
2018-01-08 12:29:49 +00:00
/******/ })
/************************************************************************/
/******/ ([
/* 0 */
/***/ (function(module, exports) {
module.exports = {
async init() {
if (this._initialized) return;
this.init_config();
this.init_globals();
this._initialized = true;
},
init_config() {
this.config = {
backend: 'sqlite',
port: 8000
};
},
init_globals() {
this.meta_cache = {};
2018-01-24 11:52:34 +00:00
this.modules = {};
this.docs = {};
this.flags = {
cache_docs: false
}
},
2018-01-08 12:29:49 +00:00
add_to_cache(doc) {
if (!this.flags.cache_docs) return;
2018-01-08 12:29:49 +00:00
// add to `docs` cache
if (doc.doctype && doc.name) {
if (!this.docs[doc.doctype]) {
this.docs[doc.doctype] = {};
}
this.docs[doc.doctype][doc.name] = doc;
}
},
2018-01-08 12:29:49 +00:00
get_doc_from_cache(doctype, name) {
if (this.docs[doctype] && this.docs[doctype][name]) {
return this.docs[doctype][name];
}
},
2018-01-08 12:29:49 +00:00
get_meta(doctype) {
if (!this.meta_cache[doctype]) {
2018-01-24 11:52:34 +00:00
this.meta_cache[doctype] = new (this.get_meta_class(doctype))();
}
return this.meta_cache[doctype];
},
2018-01-24 11:52:34 +00:00
get_meta_class(doctype) {
doctype = this.slug(doctype);
2018-01-24 11:52:34 +00:00
if (this.modules[doctype] && this.modules[doctype].Meta) {
return this.modules[doctype].Meta;
} else {
return this.BaseMeta;
}
},
async get_doc(data, name) {
if (typeof data==='string' && typeof name==='string') {
let doc = this.get_doc_from_cache(data, name);
if (!doc) {
2018-01-24 11:52:34 +00:00
let controller_class = this.get_controller_class(data);
doc = new controller_class({doctype:data, name: name});
await doc.load();
this.add_to_cache(doc);
}
return doc;
} else {
2018-01-24 11:52:34 +00:00
let controller_class = this.get_controller_class(data.doctype);
var doc = new controller_class(data);
}
return doc;
},
2018-01-24 11:52:34 +00:00
get_controller_class(doctype) {
doctype = this.slug(doctype);
if (this.modules[doctype] && this.modules[doctype].Document) {
return this.modules[doctype].Document;
} else {
return this.BaseDocument;
}
},
async get_new_doc(doctype) {
let doc = await frappe.get_doc({doctype: doctype});
doc.set_name();
doc.__not_inserted = true;
this.add_to_cache(doc);
return doc;
},
async insert(data) {
const doc = await this.get_doc(data);
return await doc.insert();
},
login(user='guest', user_key) {
this.session = new this._session.Session(user);
if (user && user_key) {
this.authenticate(user_key);
}
},
2018-01-08 12:29:49 +00:00
close() {
this.db.close();
2018-01-08 12:29:49 +00:00
if (this.server) {
this.server.close();
}
}
2018-01-08 12:29:49 +00:00
};
/***/ }),
/* 1 */
2018-01-10 10:50:57 +00:00
/***/ (function(module, exports, __webpack_require__) {
const frappe = __webpack_require__(0);
2018-01-24 11:52:34 +00:00
module.exports = class BaseDocument {
constructor(data) {
this.handlers = {};
this.setup();
Object.assign(this, data);
}
setup() {
// add handlers
}
clear_handlers() {
this.handlers = {};
}
add_handler(key, method) {
if (!this.handlers[key]) {
this.handlers[key] = [];
}
this.handlers[key].push(method || key);
}
2018-01-25 10:05:24 +00:00
get(fieldname) {
return this[fieldname];
2018-01-24 11:52:34 +00:00
}
2018-01-25 10:05:24 +00:00
// set value and trigger change
async set(fieldname, value) {
this[fieldname] = await this.validate_field(fieldname, value);
await this.trigger('change', {doc: this, fieldname: fieldname, value: value});
2018-01-24 11:52:34 +00:00
}
set_name() {
// assign a random name by default
// override this to set a name
if (!this.name) {
this.name = Math.random().toString(36).substr(3);
}
}
set_keywords() {
let keywords = [];
for (let fieldname of this.meta.get_keyword_fields()) {
keywords.push(this[fieldname]);
}
this.keywords = keywords.join(', ');
}
get meta() {
if (!this._meta) {
this._meta = frappe.get_meta(this.doctype);
}
return this._meta;
}
append(key, document) {
if (!this[key]) {
this[key] = [];
}
this[key].push(this.init_doc(document));
}
init_doc(data) {
if (data.prototype instanceof Document) {
return data;
} else {
return new Document(d);
}
}
2018-01-25 10:05:24 +00:00
async validate_field (key, value) {
2018-01-24 11:52:34 +00:00
let df = this.meta.get_field(key);
if (df.fieldtype=='Select') {
2018-01-25 10:05:24 +00:00
return this.meta.validate_select(df, value);
2018-01-24 11:52:34 +00:00
}
2018-01-25 10:05:24 +00:00
return value;
2018-01-24 11:52:34 +00:00
}
get_valid_dict() {
let doc = {};
for(let df of this.meta.get_valid_fields()) {
doc[df.fieldname] = this.get(df.fieldname);
}
return doc;
}
set_standard_values() {
let now = new Date();
if (this.docstatus === null || this.docstatus === undefined) {
this.docstatus = 0;
}
if (!this.owner) {
this.owner = frappe.session.user;
this.creation = now;
}
this.modified_by = frappe.session.user;
this.modified = now;
}
async load() {
let data = await frappe.db.get(this.doctype, this.name);
if (data.name) {
Object.assign(this, data);
} else {
throw new frappe.errors.NotFound(`Not Found: ${this.doctype} ${this.name}`);
}
}
async insert() {
this.set_name();
this.set_standard_values();
this.set_keywords();
2018-01-25 10:05:24 +00:00
await this.trigger('validate');
await this.trigger('before_insert');
2018-01-24 11:52:34 +00:00
await frappe.db.insert(this.doctype, this.get_valid_dict());
2018-01-25 10:05:24 +00:00
await this.trigger('after_insert');
await this.trigger('after_save');
2018-01-24 11:52:34 +00:00
}
async delete() {
await this.trigger('before_delete');
await frappe.db.delete(this.doctype, this.name);
await this.trigger('after_delete');
}
2018-01-25 10:05:24 +00:00
async trigger(key, params) {
if (this.handlers[key]) {
for (let method of this.handlers[key]) {
if (typeof method === 'string') {
await this[method](params);
} else {
await method(params);
2018-01-24 11:52:34 +00:00
}
}
}
}
async update() {
this.set_standard_values();
this.set_keywords();
2018-01-25 10:05:24 +00:00
await this.trigger('validate');
await this.trigger('before_update');
2018-01-24 11:52:34 +00:00
await frappe.db.update(this.doctype, this.get_valid_dict());
2018-01-25 10:05:24 +00:00
await this.trigger('after_update');
await this.trigger('after_save');
2018-01-24 11:52:34 +00:00
return this;
}
};
/***/ }),
/* 2 */
/***/ (function(module, exports, __webpack_require__) {
const frappe = __webpack_require__(0);
2018-01-10 10:50:57 +00:00
class BaseControl {
2018-01-23 12:47:56 +00:00
constructor(docfield, form) {
Object.assign(this, docfield);
2018-01-23 12:47:56 +00:00
this.form = form;
if (!this.fieldname) {
this.fieldname = frappe.slug(this.label);
}
2018-01-23 12:47:56 +00:00
this.parent = form.form;
if (this.setup) {
this.setup();
}
}
2018-01-10 10:50:57 +00:00
bind(doc) {
this.doc = doc;
this.set_doc_value();
}
2018-01-10 10:50:57 +00:00
refresh() {
this.make();
this.set_doc_value();
}
2018-01-10 10:50:57 +00:00
set_doc_value() {
if (this.doc) {
this.set_input_value(this.doc.get(this.fieldname));
}
}
2018-01-10 10:50:57 +00:00
make() {
if (!this.form_group) {
this.make_form_group();
this.make_label();
this.make_input();
this.set_input_name();
this.make_description();
this.bind_change_event();
}
}
2018-01-10 10:50:57 +00:00
make_form_group() {
this.form_group = frappe.ui.add('div', 'form-group', this.parent);
}
2018-01-10 10:50:57 +00:00
make_label() {
this.label_element = frappe.ui.add('label', null, this.form_group);
this.label_element.textContent = this.label;
}
2018-01-10 10:50:57 +00:00
make_input() {
this.input = frappe.ui.add('input', 'form-control', this.form_group);
2018-01-25 10:05:24 +00:00
this.input.setAttribute('autocomplete', 'off');
}
2018-01-10 10:50:57 +00:00
set_input_name() {
this.input.setAttribute('name', this.fieldname);
}
2018-01-10 10:50:57 +00:00
make_description() {
if (this.description) {
this.description_element = frappe.ui.add('small', 'form-text text-muted', this.form_group);
this.description_element.textContent = this.description;
}
}
2018-01-10 10:50:57 +00:00
set_input_value(value) {
2018-01-25 10:05:24 +00:00
this.input.value = this.format(value);
}
format(value) {
if (value === undefined || value === null) {
value = '';
}
2018-01-25 10:05:24 +00:00
return value;
}
2018-01-10 10:50:57 +00:00
2018-01-25 10:05:24 +00:00
async get_parsed_value() {
return await this.parse(this.input.value);
}
2018-01-10 10:50:57 +00:00
2018-01-25 10:05:24 +00:00
get_input_value() {
return this.input.value;
}
async parse(value) {
return value;
}
2018-01-10 10:50:57 +00:00
async validate(value) {
return value;
}
2018-01-10 10:50:57 +00:00
bind_change_event() {
this.input.addEventListener('change', (e) => this.handle_change(e));
}
2018-01-10 10:50:57 +00:00
async handle_change(e) {
2018-01-25 10:05:24 +00:00
let value = await this.parse(this.get_input_value());
value = await this.validate(value);
2018-01-25 10:05:24 +00:00
if (this.doc[this.fieldname] !== value) {
await this.doc.set(this.fieldname, value);
}
}
2018-01-24 11:52:34 +00:00
disable() {
this.input.setAttribute('disabled', 'disabled');
}
enable() {
this.input.removeAttribute('disabled');
}
2018-01-10 10:50:57 +00:00
}
module.exports = BaseControl;
/***/ }),
2018-01-24 11:52:34 +00:00
/* 3 */
/***/ (function(module, exports, __webpack_require__) {
2018-01-08 12:29:49 +00:00
2018-01-24 11:52:34 +00:00
const BaseDocument = __webpack_require__(1);
const frappe = __webpack_require__(0);
2018-01-08 12:29:49 +00:00
2018-01-24 11:52:34 +00:00
module.exports = class BaseMeta extends BaseDocument {
constructor(data) {
super(data);
this.event_handlers = {};
this.list_options = {
fields: ['name', 'modified']
};
if (this.setup_meta) {
this.setup_meta();
2018-01-08 12:29:49 +00:00
}
}
2018-01-24 11:52:34 +00:00
get_field(fieldname) {
if (!this.field_map) {
this.field_map = {};
for (let df of this.fields) {
this.field_map[df.fieldname] = df;
}
2018-01-08 12:29:49 +00:00
}
2018-01-24 11:52:34 +00:00
return this.field_map[fieldname];
2018-01-08 12:29:49 +00:00
}
2018-01-24 11:52:34 +00:00
on(key, fn) {
if (!this.event_handlers[key]) {
this.event_handlers[key] = [];
2018-01-08 12:29:49 +00:00
}
2018-01-24 11:52:34 +00:00
this.event_handlers[key].push(fn);
2018-01-08 12:29:49 +00:00
}
2018-01-24 11:52:34 +00:00
async set(fieldname, value) {
this[fieldname] = value;
await this.trigger(fieldname);
2018-01-08 12:29:49 +00:00
}
2018-01-24 11:52:34 +00:00
get(fieldname) {
return this[fieldname];
2018-01-08 12:29:49 +00:00
}
2018-01-24 11:52:34 +00:00
get_valid_fields() {
if (!this._valid_fields) {
this._valid_fields = [];
2018-01-08 12:29:49 +00:00
2018-01-24 11:52:34 +00:00
const doctype_fields = this.fields.map((df) => df.fieldname);
2018-01-08 12:29:49 +00:00
2018-01-24 11:52:34 +00:00
// standard fields
for (let df of frappe.model.standard_fields) {
if (frappe.db.type_map[df.fieldtype] && !doctype_fields.includes(df.fieldname)) {
this._valid_fields.push(df);
}
}
2018-01-08 12:29:49 +00:00
2018-01-24 11:52:34 +00:00
// parent fields
if (this.istable) {
for (let df of frappe.model.child_fields) {
if (frappe.db.type_map[df.fieldtype] && !doctype_fields.includes(df.fieldname)) {
this._valid_fields.push(df);
}
}
}
// doctype fields
for (let df of this.fields) {
if (frappe.db.type_map[df.fieldtype]) {
this._valid_fields.push(df);
}
}
}
return this._valid_fields;
2018-01-08 12:29:49 +00:00
}
2018-01-24 11:52:34 +00:00
get_keyword_fields() {
return this.keyword_fields || this.meta.fields.filter(df => df.reqd).map(df => df.fieldname);
2018-01-08 12:29:49 +00:00
}
2018-01-24 11:52:34 +00:00
validate_select(df, value) {
let options = df.options;
if (typeof options === 'string') {
// values given as string
options = df.options.split('\n');
}
if (!options.includes(value)) {
throw new frappe.errors.ValueError(`${value} must be one of ${options.join(", ")}`);
}
2018-01-25 10:05:24 +00:00
return value;
2018-01-08 12:29:49 +00:00
}
2018-01-24 11:52:34 +00:00
async trigger(key, event = {}) {
Object.assign(event, {
doc: this,
name: key
});
if (this.event_handlers[key]) {
for (var handler of this.event_handlers[key]) {
await handler(event);
2018-01-08 12:29:49 +00:00
}
}
}
}
2018-01-24 11:52:34 +00:00
/***/ }),
/* 4 */
/***/ (function(module, exports, __webpack_require__) {
2018-01-08 12:29:49 +00:00
2018-01-24 11:52:34 +00:00
const frappe = __webpack_require__(0);
2018-01-08 12:29:49 +00:00
2018-01-24 11:52:34 +00:00
module.exports = class BaseList {
constructor({doctype, parent, fields}) {
this.doctype = doctype;
this.parent = parent;
this.fields = fields;
2018-01-08 12:29:49 +00:00
2018-01-24 11:52:34 +00:00
this.meta = frappe.get_meta(this.doctype);
2018-01-08 12:29:49 +00:00
2018-01-24 11:52:34 +00:00
this.start = 0;
this.page_length = 20;
2018-01-08 12:29:49 +00:00
2018-01-24 11:52:34 +00:00
this.body = null;
this.rows = [];
this.data = [];
}
2018-01-08 12:29:49 +00:00
2018-01-24 11:52:34 +00:00
async run() {
this.make_body();
2018-01-08 12:29:49 +00:00
2018-01-24 11:52:34 +00:00
let data = await this.get_data();
2018-01-08 12:29:49 +00:00
2018-01-24 11:52:34 +00:00
for (let i=0; i< Math.min(this.page_length, data.length); i++) {
this.render_row(this.start + i, data[i]);
}
2018-01-08 12:29:49 +00:00
2018-01-24 11:52:34 +00:00
if (this.start > 0) {
this.data = this.data.concat(data);
} else {
this.data = data;
}
2018-01-10 10:50:57 +00:00
2018-01-24 11:52:34 +00:00
this.clear_empty_rows();
this.update_more(data.length > this.page_length);
}
2018-01-10 10:50:57 +00:00
2018-01-24 11:52:34 +00:00
async get_data() {
return await frappe.db.get_all({
doctype: this.doctype,
fields: this.get_fields(),
filters: this.get_filters(),
start: this.start,
limit: this.page_length + 1
});
}
2018-01-10 10:50:57 +00:00
2018-01-24 11:52:34 +00:00
get_fields() {
return ['name'];
}
2018-01-10 10:50:57 +00:00
2018-01-24 11:52:34 +00:00
async append() {
this.start += this.page_length;
await this.run();
}
get_filters() {
let filters = {};
if (this.search_input.value) {
filters.keywords = ['like', '%' + this.search_input.value + '%'];
}
2018-01-24 11:52:34 +00:00
return filters;
}
2018-01-10 10:50:57 +00:00
2018-01-24 11:52:34 +00:00
make_body() {
if (!this.body) {
this.make_toolbar();
//this.make_new();
this.body = frappe.ui.add('div', 'list-body', this.parent);
this.make_more_btn();
}
}
2018-01-10 10:50:57 +00:00
2018-01-24 11:52:34 +00:00
make_toolbar() {
this.toolbar = frappe.ui.add('div', 'list-toolbar', this.parent);
this.toolbar.innerHTML = `
<div class="row">
<div class="col-md-6 col-9">
<div class="input-group list-search mb-2">
<input class="form-control" type="text" placeholder="Search...">
<div class="input-group-append">
<button class="btn btn-outline-secondary btn-search">Search</button>
</div>
</div>
</div>
<div class="col-md-3 col-3">
<a href="#new/${frappe.slug(this.doctype)}" class="btn btn-outline-primary">
New
</a>
</div>
</div>
`;
this.search_input = this.toolbar.querySelector('input');
this.search_input.addEventListener('keypress', (event) => {
if (event.keyCode===13) {
this.run();
}
});
this.search_button = this.toolbar.querySelector('.btn-search');
this.search_button.addEventListener('click', (event) => {
this.run();
});
}
2018-01-10 10:50:57 +00:00
2018-01-24 11:52:34 +00:00
make_more_btn() {
this.more_btn = frappe.ui.add('button', 'btn btn-secondary hide', this.parent);
this.more_btn.textContent = 'More';
this.more_btn.addEventListener('click', () => {
this.append();
})
}
2018-01-08 12:29:49 +00:00
2018-01-24 11:52:34 +00:00
render_row(i, data) {
let row = this.get_row(i);
row.innerHTML = this.get_row_html(data);
row.style.display = 'block';
}
2018-01-08 12:29:49 +00:00
2018-01-24 11:52:34 +00:00
get_row_html(data) {
2018-01-25 10:05:24 +00:00
return `<a href="#edit/${this.doctype}/${data.name}">${data.name}</a>`;
}
2018-01-10 10:50:57 +00:00
2018-01-24 11:52:34 +00:00
get_row(i) {
if (!this.rows[i]) {
this.rows[i] = frappe.ui.add('div', 'list-row py-2', this.body);
}
2018-01-24 11:52:34 +00:00
return this.rows[i];
}
2018-01-10 10:50:57 +00:00
2018-01-24 11:52:34 +00:00
clear_empty_rows() {
if (this.rows.length > this.data.length) {
for (let i=this.data.length; i < this.rows.length; i++) {
let row = this.get_row(i);
row.innerHTML = '';
row.style.display = 'none';
}
}
}
2018-01-10 10:50:57 +00:00
2018-01-24 11:52:34 +00:00
update_more(show) {
if (show) {
this.more_btn.classList.remove('hide');
} else {
this.more_btn.classList.add('hide');
}
}
2018-01-10 10:50:57 +00:00
2018-01-24 11:52:34 +00:00
};
/***/ }),
/* 5 */
/***/ (function(module, exports, __webpack_require__) {
const frappe = __webpack_require__(0);
2018-01-25 10:05:24 +00:00
const controls = __webpack_require__(29);
2018-01-24 11:52:34 +00:00
module.exports = class BaseForm {
constructor({doctype, parent, submit_label='Submit'}) {
this.parent = parent;
this.doctype = doctype;
this.submit_label = submit_label;
this.controls = {};
this.controls_list = [];
this.meta = frappe.get_meta(this.doctype);
if (this.setup) {
this.setup();
}
2018-01-24 11:52:34 +00:00
this.make();
}
2018-01-10 10:50:57 +00:00
2018-01-24 11:52:34 +00:00
make() {
if (this.body || !this.parent) {
return;
}
2018-01-24 11:52:34 +00:00
this.body = frappe.ui.add('div', 'form-body', this.parent);
this.make_toolbar();
this.form = frappe.ui.add('form', null, this.body);
for(let df of this.meta.fields) {
if (controls.get_control_class(df.fieldtype)) {
let control = controls.make_control(df, this);
this.controls_list.push(control);
this.controls[df.fieldname] = control;
}
}
}
2018-01-10 10:50:57 +00:00
2018-01-24 11:52:34 +00:00
make_toolbar() {
this.toolbar = frappe.ui.add('div', 'form-toolbar text-right', this.body);
this.toolbar.innerHTML = `
<button class="btn btn-outline-secondary btn-delete">Delete</button>
<button class="btn btn-primary btn-submit">Save</button>
`
this.btn_submit = this.toolbar.querySelector('.btn-submit');;
this.btn_submit.addEventListener('click', async (event) => {
this.submit();
event.preventDefault();
})
this.btn_delete = this.toolbar.querySelector('.btn-delete');
this.btn_delete.addEventListener('click', async () => {
await this.doc.delete();
this.show_alert('Deleted', 'success');
});
}
2018-01-10 10:50:57 +00:00
2018-01-24 11:52:34 +00:00
show_alert(message, type) {
this.clear_alert();
this.alert = frappe.ui.add('div', `alert alert-${type}`, this.body);
this.alert.textContent = message;
}
clear_alert() {
if (this.alert) {
frappe.ui.remove(this.alert);
this.alert = null;
}
}
2018-01-10 10:50:57 +00:00
2018-01-24 11:52:34 +00:00
async use(doc, is_new = false) {
if (this.doc) {
// clear handlers of outgoing doc
this.doc.clear_handlers();
}
this.clear_alert();
this.doc = doc;
this.is_new = is_new;
for (let control of this.controls_list) {
control.bind(this.doc);
}
2018-01-25 10:05:24 +00:00
// refresh value in control
this.doc.add_handler('change', (params) => {
let control = this.controls[params.fieldname];
if (control && control.get_input_value() !== control.format(params.fieldname)) {
control.set_doc_value();
}
});
}
2018-01-10 10:50:57 +00:00
2018-01-24 11:52:34 +00:00
async submit() {
try {
if (this.is_new || this.doc.__not_inserted) {
await this.doc.insert();
} else {
await this.doc.update();
}
2018-01-24 11:52:34 +00:00
await this.refresh();
this.show_alert('Saved', 'success');
} catch (e) {
this.show_alert('Failed', 'danger');
}
}
2018-01-24 11:52:34 +00:00
refresh() {
for(let control of this.controls_list) {
control.refresh();
}
}
2018-01-10 10:50:57 +00:00
2018-01-24 11:52:34 +00:00
}
2018-01-10 10:50:57 +00:00
/***/ }),
2018-01-24 11:52:34 +00:00
/* 6 */
2018-01-10 10:50:57 +00:00
/***/ (function(module, exports, __webpack_require__) {
2018-01-25 10:05:24 +00:00
const BaseControl = __webpack_require__(2);
2018-01-10 10:50:57 +00:00
2018-01-25 10:05:24 +00:00
class FloatControl extends BaseControl {
make() {
super.make();
this.input.setAttribute('type', 'text');
this.input.classList.add('text-right');
}
};
module.exports = FloatControl;
/***/ }),
/* 7 */
/***/ (function(module, exports, __webpack_require__) {
__webpack_require__(8);
const client = __webpack_require__(13);
2018-01-10 10:50:57 +00:00
2018-01-09 13:40:33 +00:00
// start server
client.start({
server: 'localhost:8000',
container: document.querySelector('.wrapper'),
2018-01-09 13:40:33 +00:00
}).then(() => {
2018-01-10 10:50:57 +00:00
2018-01-24 11:52:34 +00:00
// require modules
2018-01-25 10:05:24 +00:00
frappe.modules.todo = __webpack_require__(37);
frappe.modules.account = __webpack_require__(39);
frappe.modules.item = __webpack_require__(41);
frappe.modules.todo_client = __webpack_require__(43);
frappe.modules.account_client = __webpack_require__(44);
2018-01-09 13:40:33 +00:00
2018-01-23 08:00:08 +00:00
frappe.desk.add_sidebar_item('ToDo', '#list/todo');
frappe.desk.add_sidebar_item('Accounts', '#list/account');
2018-01-25 10:05:24 +00:00
frappe.desk.add_sidebar_item('Items', '#list/item');
2018-01-23 08:00:08 +00:00
frappe.router.default = '#list/todo';
2018-01-08 12:29:49 +00:00
frappe.router.show(window.location.hash);
2018-01-09 13:40:33 +00:00
});
2018-01-08 12:29:49 +00:00
/***/ }),
2018-01-25 10:05:24 +00:00
/* 8 */
2018-01-08 12:29:49 +00:00
/***/ (function(module, exports, __webpack_require__) {
// style-loader: Adds some css to the DOM by adding a <style> tag
// load the styles
2018-01-25 10:05:24 +00:00
var content = __webpack_require__(9);
2018-01-08 12:29:49 +00:00
if(typeof content === 'string') content = [[module.i, content, '']];
// Prepare cssTransformation
var transform;
var options = {"hmr":true}
options.transform = transform
// add the styles to the DOM
2018-01-25 10:05:24 +00:00
var update = __webpack_require__(11)(content, options);
2018-01-08 12:29:49 +00:00
if(content.locals) module.exports = content.locals;
// Hot Module Replacement
if(false) {
// When the styles change, update the <style> tags
if(!content.locals) {
2018-01-23 12:26:11 +00:00
module.hot.accept("!!../node_modules/css-loader/index.js!../node_modules/postcss-loader/lib/index.js??ref--0-2!../node_modules/sass-loader/lib/loader.js!./main.scss", function() {
var newContent = require("!!../node_modules/css-loader/index.js!../node_modules/postcss-loader/lib/index.js??ref--0-2!../node_modules/sass-loader/lib/loader.js!./main.scss");
2018-01-08 12:29:49 +00:00
if(typeof newContent === 'string') newContent = [[module.id, newContent, '']];
update(newContent);
});
}
// When the module is disposed, remove the <style> tags
module.hot.dispose(function() { update(); });
}
/***/ }),
2018-01-25 10:05:24 +00:00
/* 9 */
2018-01-23 12:26:11 +00:00
/***/ (function(module, exports, __webpack_require__) {
2018-01-25 10:05:24 +00:00
exports = module.exports = __webpack_require__(10)(false);
2018-01-23 12:26:11 +00:00
// imports
// module
exports.push([module.i, "/*!\n * Bootstrap v4.0.0 (https://getbootstrap.com)\n * Copyright 2011-2018 The Bootstrap Authors\n * Copyright 2011-2018 Twitter, Inc.\n * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)\n */\n*, *::before, *::after {\n -webkit-box-sizing: border-box;\n box-sizing: border-box; }\nhtml {\n font-family: sans-serif;\n line-height: 1.15;\n -webkit-text-size-adjust: 100%;\n -ms-text-size-adjust: 100%;\n -ms-overflow-style: scrollbar;\n -webkit-tap-highlight-color: transparent; }\n@-ms-viewport {\n width: device-width; }\narticle, aside, dialog, figcaption, figure, footer, header, hgroup, main, nav, section {\n display: block; }\nbody {\n margin: 0;\n font-family: -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, \"Helvetica Neue\", Arial, sans-serif, \"Apple Color Emoji\", \"Segoe UI Emoji\", \"Segoe UI Symbol\";\n font-size: 1rem;\n font-weight: 400;\n line-height: 1.5;\n color: #212529;\n text-align: left;\n background-color: #fff; }\n[tabindex=\"-1\"]:focus {\n outline: 0 !important; }\nhr {\n -webkit-box-sizing: content-box;\n box-sizing: content-box;\n height: 0;\n overflow: visible; }\nh1, h2, h3, h4, h5, h6 {\n margin-top: 0;\n margin-bottom: 0.5rem; }\np {\n margin-top: 0;\n margin-bottom: 1rem; }\nabbr[title], abbr[data-original-title] {\n text-decoration: underline;\n -webkit-text-decoration: underline dotted;\n text-decoration: underline dotted;\n cursor: help;\n border-bottom: 0; }\naddress {\n margin-bottom: 1rem;\n font-style: normal;\n line-height: inherit; }\nol, ul, dl {\n margin-top: 0;\n margin-bottom: 1rem; }\nol ol, ul ul, ol ul, ul ol {\n margin-bottom: 0; }\ndt {\n font-weight: 700; }\ndd {\n margin-bottom: .5rem;\n margin-left: 0; }\nblockquote {\n margin: 0 0 1rem; }\ndfn {\n font-style: italic; }\nb, strong {\n font-weight: bolder; }\nsmall {\n font-size: 80%; }\nsub, sup {\n position: relative;\n font-size: 75%;\n line-height: 0;\n vertical-align: baseline; }\nsub {\n bottom: -.25em; }\nsup {\n top: -.5em; }\na {\n color: #007bff;\n text-decoration: none;\n background-color: transparent;\n -webkit-text-decoration-skip: objects; }\na:hover {\n color: #0056b3;\n text-decoration: underline; }\na:not([href]):not([tabindex]) {\n color: inherit;\n text-decoration: none; }\na:not([href]):not([tabindex]):hover, a:not([href]):not([tabindex]):focus {\n color: inherit;\n text-decoration: none; }\na:not([href]):not([tabindex]):focus {\n outline: 0; }\npre, code, kbd, samp {\n font-family: monospace, monospace;\n font-size: 1em; }\npre {\n margin-top: 0;\n margin-bottom: 1rem;\n overflow: auto;\n -ms-overflow-style: scrollbar; }\nfigure {\n margin: 0 0 1rem; }\nimg {\n vertical-align: middle;\n border-style: none; }\nsvg:not(:root) {\n overflow: hidden; }\ntable {\n border-collapse: collapse; }\ncaption {\n padding-top: 0.75rem;\n padding-bottom: 0.75rem;\n color: #6c757d;\n text-align: left;\n caption-side: bottom; }\nth {\n text-align: inherit; }\nlabel {\n display: inline-block;\n margin-bottom: .5rem; }\nbutton {\n border-radius: 0; }\nbutton:focus {\n outline: 1px dotted;\n outline: 5px auto -webkit-focus-ring-color; }\ninput, button, select, optgroup, textarea {\n margin: 0;\n font-family: inherit;\n font-size: inherit;\n line-height: inherit; }\nbutton, input {\n overflow: visible; }\nbutton, select {\n text-transform: none; }\nbutton, html [type=\"button\"], [type=\"reset\"], [type=\"submit\"] {\n -webkit-appearance: button; }\nbutton::-moz-focus-inner, [type=\"button\"]::-moz-focus-inner, [type=\"reset\"]::-moz-focus-inner, [type=\"submit\"]::-moz-focus-inner {\n padding: 0;\n border-style: none; }\ninput[type=\"radio\"], input[type=\"checkbox\"] {\n -webkit-box-sizing: border-box;\n box-sizing: border-box;\n padding: 0; }\ninput[type=\"date\"], input[type=\"time\"], input[type=\"datetime-local\"], input[type=\"month\"] {\n -webkit-appearance: listbox; }\ntextarea {\n overflow: auto;\n resize: vertical; }
// exports
2018-01-08 12:29:49 +00:00
/***/ }),
2018-01-25 10:05:24 +00:00
/* 10 */
2018-01-23 12:26:11 +00:00
/***/ (function(module, exports) {
/*
MIT License http://www.opensource.org/licenses/mit-license.php
Author Tobias Koppers @sokra
*/
// css base code, injected by the css-loader
module.exports = function(useSourceMap) {
var list = [];
// return the list of modules as css string
list.toString = function toString() {
return this.map(function (item) {
var content = cssWithMappingToString(item, useSourceMap);
if(item[2]) {
return "@media " + item[2] + "{" + content + "}";
} else {
return content;
}
}).join("");
};
// import a list of modules into the list
list.i = function(modules, mediaQuery) {
if(typeof modules === "string")
modules = [[null, modules, ""]];
var alreadyImportedModules = {};
for(var i = 0; i < this.length; i++) {
var id = this[i][0];
if(typeof id === "number")
alreadyImportedModules[id] = true;
}
for(i = 0; i < modules.length; i++) {
var item = modules[i];
// skip already imported module
// this implementation is not 100% perfect for weird media query combinations
// when a module is imported multiple times with different media queries.
// I hope this will never occur (Hey this way we have smaller bundles)
if(typeof item[0] !== "number" || !alreadyImportedModules[item[0]]) {
if(mediaQuery && !item[2]) {
item[2] = mediaQuery;
} else if(mediaQuery) {
item[2] = "(" + item[2] + ") and (" + mediaQuery + ")";
}
list.push(item);
}
}
};
return list;
};
function cssWithMappingToString(item, useSourceMap) {
var content = item[1] || '';
var cssMapping = item[3];
if (!cssMapping) {
return content;
}
if (useSourceMap && typeof btoa === 'function') {
var sourceMapping = toComment(cssMapping);
var sourceURLs = cssMapping.sources.map(function (source) {
return '/*# sourceURL=' + cssMapping.sourceRoot + source + ' */'
});
return [content].concat(sourceURLs).concat([sourceMapping]).join('\n');
}
return [content].join('\n');
}
// Adapted from convert-source-map (MIT)
function toComment(sourceMap) {
// eslint-disable-next-line no-undef
var base64 = btoa(unescape(encodeURIComponent(JSON.stringify(sourceMap))));
var data = 'sourceMappingURL=data:application/json;charset=utf-8;base64,' + base64;
return '/*# ' + data + ' */';
}
/***/ }),
2018-01-25 10:05:24 +00:00
/* 11 */
2018-01-08 12:29:49 +00:00
/***/ (function(module, exports, __webpack_require__) {
/*
MIT License http://www.opensource.org/licenses/mit-license.php
Author Tobias Koppers @sokra
*/
var stylesInDom = {};
var memoize = function (fn) {
var memo;
return function () {
if (typeof memo === "undefined") memo = fn.apply(this, arguments);
return memo;
};
};
var isOldIE = memoize(function () {
// Test for IE <= 9 as proposed by Browserhacks
// @see http://browserhacks.com/#hack-e71d8692f65334173fee715c222cb805
// Tests for existence of standard globals is to allow style-loader
// to operate correctly into non-standard environments
// @see https://github.com/webpack-contrib/style-loader/issues/177
return window && document && document.all && !window.atob;
});
var getElement = (function (fn) {
var memo = {};
return function(selector) {
if (typeof memo[selector] === "undefined") {
var styleTarget = fn.call(this, selector);
// Special case to return head of iframe instead of iframe itself
if (styleTarget instanceof window.HTMLIFrameElement) {
try {
// This will throw an exception if access to iframe is blocked
// due to cross-origin restrictions
styleTarget = styleTarget.contentDocument.head;
} catch(e) {
styleTarget = null;
}
}
memo[selector] = styleTarget;
}
return memo[selector]
};
})(function (target) {
return document.querySelector(target)
});
var singleton = null;
var singletonCounter = 0;
var stylesInsertedAtTop = [];
2018-01-25 10:05:24 +00:00
var fixUrls = __webpack_require__(12);
2018-01-08 12:29:49 +00:00
module.exports = function(list, options) {
if (typeof DEBUG !== "undefined" && DEBUG) {
if (typeof document !== "object") throw new Error("The style-loader cannot be used in a non-browser environment");
}
options = options || {};
options.attrs = typeof options.attrs === "object" ? options.attrs : {};
// Force single-tag solution on IE6-9, which has a hard limit on the # of <style>
// tags it will allow on a page
if (!options.singleton && typeof options.singleton !== "boolean") options.singleton = isOldIE();
// By default, add <style> tags to the <head> element
if (!options.insertInto) options.insertInto = "head";
// By default, add <style> tags to the bottom of the target
if (!options.insertAt) options.insertAt = "bottom";
var styles = listToStyles(list, options);
addStylesToDom(styles, options);
return function update (newList) {
var mayRemove = [];
for (var i = 0; i < styles.length; i++) {
var item = styles[i];
var domStyle = stylesInDom[item.id];
domStyle.refs--;
mayRemove.push(domStyle);
}
if(newList) {
var newStyles = listToStyles(newList, options);
addStylesToDom(newStyles, options);
}
for (var i = 0; i < mayRemove.length; i++) {
var domStyle = mayRemove[i];
if(domStyle.refs === 0) {
for (var j = 0; j < domStyle.parts.length; j++) domStyle.parts[j]();
delete stylesInDom[domStyle.id];
}
}
};
};
function addStylesToDom (styles, options) {
for (var i = 0; i < styles.length; i++) {
var item = styles[i];
var domStyle = stylesInDom[item.id];
if(domStyle) {
domStyle.refs++;
for(var j = 0; j < domStyle.parts.length; j++) {
domStyle.parts[j](item.parts[j]);
}
for(; j < item.parts.length; j++) {
domStyle.parts.push(addStyle(item.parts[j], options));
}
} else {
var parts = [];
for(var j = 0; j < item.parts.length; j++) {
parts.push(addStyle(item.parts[j], options));
}
stylesInDom[item.id] = {id: item.id, refs: 1, parts: parts};
}
}
}
function listToStyles (list, options) {
var styles = [];
var newStyles = {};
for (var i = 0; i < list.length; i++) {
var item = list[i];
var id = options.base ? item[0] + options.base : item[0];
var css = item[1];
var media = item[2];
var sourceMap = item[3];
var part = {css: css, media: media, sourceMap: sourceMap};
if(!newStyles[id]) styles.push(newStyles[id] = {id: id, parts: [part]});
else newStyles[id].parts.push(part);
}
return styles;
}
function insertStyleElement (options, style) {
var target = getElement(options.insertInto)
if (!target) {
throw new Error("Couldn't find a style target. This probably means that the value for the 'insertInto' parameter is invalid.");
}
var lastStyleElementInsertedAtTop = stylesInsertedAtTop[stylesInsertedAtTop.length - 1];
if (options.insertAt === "top") {
if (!lastStyleElementInsertedAtTop) {
target.insertBefore(style, target.firstChild);
} else if (lastStyleElementInsertedAtTop.nextSibling) {
target.insertBefore(style, lastStyleElementInsertedAtTop.nextSibling);
} else {
target.appendChild(style);
}
stylesInsertedAtTop.push(style);
} else if (options.insertAt === "bottom") {
target.appendChild(style);
} else if (typeof options.insertAt === "object" && options.insertAt.before) {
var nextSibling = getElement(options.insertInto + " " + options.insertAt.before);
target.insertBefore(style, nextSibling);
} else {
throw new Error("[Style Loader]\n\n Invalid value for parameter 'insertAt' ('options.insertAt') found.\n Must be 'top', 'bottom', or Object.\n (https://github.com/webpack-contrib/style-loader#insertat)\n");
}
}
function removeStyleElement (style) {
if (style.parentNode === null) return false;
style.parentNode.removeChild(style);
var idx = stylesInsertedAtTop.indexOf(style);
if(idx >= 0) {
stylesInsertedAtTop.splice(idx, 1);
}
}
function createStyleElement (options) {
var style = document.createElement("style");
options.attrs.type = "text/css";
addAttrs(style, options.attrs);
insertStyleElement(options, style);
return style;
}
function createLinkElement (options) {
var link = document.createElement("link");
options.attrs.type = "text/css";
options.attrs.rel = "stylesheet";
addAttrs(link, options.attrs);
insertStyleElement(options, link);
return link;
}
function addAttrs (el, attrs) {
Object.keys(attrs).forEach(function (key) {
el.setAttribute(key, attrs[key]);
});
}
function addStyle (obj, options) {
var style, update, remove, result;
// If a transform function was defined, run it on the css
if (options.transform && obj.css) {
result = options.transform(obj.css);
if (result) {
// If transform returns a value, use that instead of the original css.
// This allows running runtime transformations on the css.
obj.css = result;
} else {
// If the transform function returns a falsy value, don't add this css.
// This allows conditional loading of css
return function() {
// noop
};
}
}
if (options.singleton) {
var styleIndex = singletonCounter++;
style = singleton || (singleton = createStyleElement(options));
update = applyToSingletonTag.bind(null, style, styleIndex, false);
remove = applyToSingletonTag.bind(null, style, styleIndex, true);
} else if (
obj.sourceMap &&
typeof URL === "function" &&
typeof URL.createObjectURL === "function" &&
typeof URL.revokeObjectURL === "function" &&
typeof Blob === "function" &&
typeof btoa === "function"
) {
style = createLinkElement(options);
update = updateLink.bind(null, style, options);
remove = function () {
removeStyleElement(style);
if(style.href) URL.revokeObjectURL(style.href);
};
} else {
style = createStyleElement(options);
update = applyToTag.bind(null, style);
remove = function () {
removeStyleElement(style);
};
}
update(obj);
return function updateStyle (newObj) {
if (newObj) {
if (
newObj.css === obj.css &&
newObj.media === obj.media &&
newObj.sourceMap === obj.sourceMap
) {
return;
}
update(obj = newObj);
} else {
remove();
}
};
}
var replaceText = (function () {
var textStore = [];
return function (index, replacement) {
textStore[index] = replacement;
return textStore.filter(Boolean).join('\n');
};
})();
function applyToSingletonTag (style, index, remove, obj) {
var css = remove ? "" : obj.css;
if (style.styleSheet) {
style.styleSheet.cssText = replaceText(index, css);
} else {
var cssNode = document.createTextNode(css);
var childNodes = style.childNodes;
if (childNodes[index]) style.removeChild(childNodes[index]);
if (childNodes.length) {
style.insertBefore(cssNode, childNodes[index]);
} else {
style.appendChild(cssNode);
}
}
}
function applyToTag (style, obj) {
var css = obj.css;
var media = obj.media;
if(media) {
style.setAttribute("media", media)
}
if(style.styleSheet) {
style.styleSheet.cssText = css;
} else {
while(style.firstChild) {
style.removeChild(style.firstChild);
}
style.appendChild(document.createTextNode(css));
}
}
function updateLink (link, options, obj) {
var css = obj.css;
var sourceMap = obj.sourceMap;
/*
If convertToAbsoluteUrls isn't defined, but sourcemaps are enabled
and there is no publicPath defined then lets turn convertToAbsoluteUrls
on by default. Otherwise default to the convertToAbsoluteUrls option
directly
*/
var autoFixUrls = options.convertToAbsoluteUrls === undefined && sourceMap;
if (options.convertToAbsoluteUrls || autoFixUrls) {
css = fixUrls(css);
}
if (sourceMap) {
// http://stackoverflow.com/a/26603875
css += "\n/*# sourceMappingURL=data:application/json;base64," + btoa(unescape(encodeURIComponent(JSON.stringify(sourceMap)))) + " */";
}
var blob = new Blob([css], { type: "text/css" });
var oldSrc = link.href;
link.href = URL.createObjectURL(blob);
if(oldSrc) URL.revokeObjectURL(oldSrc);
}
/***/ }),
2018-01-25 10:05:24 +00:00
/* 12 */
2018-01-08 12:29:49 +00:00
/***/ (function(module, exports) {
/**
* When source maps are enabled, `style-loader` uses a link element with a data-uri to
* embed the css on the page. This breaks all relative urls because now they are relative to a
* bundle instead of the current page.
*
* One solution is to only use full urls, but that may be impossible.
*
* Instead, this function "fixes" the relative urls to be absolute according to the current page location.
*
* A rudimentary test suite is located at `test/fixUrls.js` and can be run via the `npm test` command.
*
*/
module.exports = function (css) {
// get current location
var location = typeof window !== "undefined" && window.location;
if (!location) {
throw new Error("fixUrls requires window.location");
}
// blank or null?
if (!css || typeof css !== "string") {
return css;
}
var baseUrl = location.protocol + "//" + location.host;
var currentDir = baseUrl + location.pathname.replace(/\/[^\/]*$/, "/");
// convert each url(...)
/*
This regular expression is just a way to recursively match brackets within
a string.
/url\s*\( = Match on the word "url" with any whitespace after it and then a parens
( = Start a capturing group
(?: = Start a non-capturing group
[^)(] = Match anything that isn't a parentheses
| = OR
\( = Match a start parentheses
(?: = Start another non-capturing groups
[^)(]+ = Match anything that isn't a parentheses
| = OR
\( = Match a start parentheses
[^)(]* = Match anything that isn't a parentheses
\) = Match a end parentheses
) = End Group
*\) = Match anything and then a close parens
) = Close non-capturing group
* = Match anything
) = Close capturing group
\) = Match a close parens
/gi = Get all matches, not the first. Be case insensitive.
*/
var fixedCss = css.replace(/url\s*\(((?:[^)(]|\((?:[^)(]+|\([^)(]*\))*\))*)\)/gi, function(fullMatch, origUrl) {
// strip quotes (if they exist)
var unquotedOrigUrl = origUrl
.trim()
.replace(/^"(.*)"$/, function(o, $1){ return $1; })
.replace(/^'(.*)'$/, function(o, $1){ return $1; });
// already a full url? no change
if (/^(#|data:|http:\/\/|https:\/\/|file:\/\/\/)/i.test(unquotedOrigUrl)) {
return fullMatch;
}
// convert the url to a full url
var newUrl;
if (unquotedOrigUrl.indexOf("//") === 0) {
//TODO: should we add protocol?
newUrl = unquotedOrigUrl;
} else if (unquotedOrigUrl.indexOf("/") === 0) {
// path should be relative to the base url
newUrl = baseUrl + unquotedOrigUrl; // already starts with '/'
} else {
// path should be relative to current directory
newUrl = currentDir + unquotedOrigUrl.replace(/^\.\//, ""); // Strip leading './'
}
// send back the fixed url(...)
return "url(" + JSON.stringify(newUrl) + ")";
});
// send back the fixed css
return fixedCss;
};
/***/ }),
2018-01-25 10:05:24 +00:00
/* 13 */
2018-01-08 12:29:49 +00:00
/***/ (function(module, exports, __webpack_require__) {
2018-01-25 10:05:24 +00:00
const common = __webpack_require__(14);
const RESTClient = __webpack_require__(20);
2018-01-09 13:40:33 +00:00
const frappe = __webpack_require__(0);
2018-01-25 10:05:24 +00:00
frappe.ui = __webpack_require__(23);
const Desk = __webpack_require__(25);
2018-01-08 12:29:49 +00:00
2018-01-09 13:40:33 +00:00
module.exports = {
2018-01-16 07:16:50 +00:00
async start({server}) {
window.frappe = frappe;
frappe.init();
common.init_libs(frappe);
2018-01-09 13:40:33 +00:00
frappe.fetch = window.fetch.bind();
frappe.db = await new RESTClient({server: server});
2018-01-08 12:29:49 +00:00
frappe.flags.cache_docs = true;
frappe.desk = new Desk();
await frappe.login();
}
2018-01-09 13:40:33 +00:00
};
2018-01-08 12:29:49 +00:00
2018-01-09 13:40:33 +00:00
/***/ }),
2018-01-25 10:05:24 +00:00
/* 14 */
2018-01-09 13:40:33 +00:00
/***/ (function(module, exports, __webpack_require__) {
2018-01-08 12:29:49 +00:00
2018-01-25 10:05:24 +00:00
const utils = __webpack_require__(15);
const model = __webpack_require__(17);
2018-01-24 11:52:34 +00:00
const BaseDocument = __webpack_require__(1);
const BaseMeta = __webpack_require__(3);
2018-01-25 10:05:24 +00:00
const _session = __webpack_require__(18);
const errors = __webpack_require__(19);
2018-01-08 12:29:49 +00:00
2018-01-09 13:40:33 +00:00
module.exports = {
init_libs(frappe) {
Object.assign(frappe, utils);
frappe.model = model;
2018-01-24 11:52:34 +00:00
frappe.BaseDocument = BaseDocument;
frappe.BaseMeta = BaseMeta;
frappe._session = _session;
frappe.errors = errors;
}
2018-01-09 13:40:33 +00:00
}
2018-01-08 12:29:49 +00:00
2018-01-09 13:40:33 +00:00
/***/ }),
2018-01-25 10:05:24 +00:00
/* 15 */
/***/ (function(module, exports, __webpack_require__) {
2018-01-08 12:29:49 +00:00
2018-01-25 10:05:24 +00:00
let utils = {};
Object.assign(utils, __webpack_require__(16));
Object.assign(utils, {
slug(text) {
return text.toLowerCase().replace(/ /g, '_');
2018-01-24 11:52:34 +00:00
},
2018-01-08 12:29:49 +00:00
2018-01-24 11:52:34 +00:00
async_handler(fn) {
return (req, res, next) => Promise.resolve(fn(req, res, next))
.catch((err) => {
console.log(err);
// handle error
res.status(err.status_code || 500).send({error: err.message});
});
},
async sleep(seconds) {
return new Promise(resolve => {
setTimeout(resolve, seconds * 1000);
});
}
2018-01-25 10:05:24 +00:00
});
module.exports = utils;
/***/ }),
/* 16 */
/***/ (function(module, exports) {
const number_formats = {
"#,###.##": { fraction_sep: ".", group_sep: ",", precision: 2 },
"#.###,##": { fraction_sep: ",", group_sep: ".", precision: 2 },
"# ###.##": { fraction_sep: ".", group_sep: " ", precision: 2 },
"# ###,##": { fraction_sep: ",", group_sep: " ", precision: 2 },
"#'###.##": { fraction_sep: ".", group_sep: "'", precision: 2 },
"#, ###.##": { fraction_sep: ".", group_sep: ", ", precision: 2 },
"#,##,###.##": { fraction_sep: ".", group_sep: ",", precision: 2 },
"#,###.###": { fraction_sep: ".", group_sep: ",", precision: 3 },
"#.###": { fraction_sep: "", group_sep: ".", precision: 0 },
"#,###": { fraction_sep: "", group_sep: ",", precision: 0 },
2018-01-24 11:52:34 +00:00
}
2018-01-25 10:05:24 +00:00
module.exports = {
// parse a formatted number string
// from "4,555,000.34" -> 4555000.34
parse_number(number, format='#,###.##') {
if (!number) {
return 0;
}
if (typeof number === 'number') {
return number;
}
const info = this.get_format_info(format);
return parseFloat(this.remove_separator(number, info.group_sep));
},
format_number(number, format = '#,###.##', precision = null) {
if (!number) {
number = 0;
}
let info = this.get_format_info(format);
if (precision) {
info.precision = precision;
}
let is_negative = false;
number = this.parse_number(number);
if (number < 0) {
is_negative = true;
}
number = Math.abs(number);
number = number.toFixed(info.precision);
var parts = number.split('.');
// get group position and parts
var group_position = info.group_sep ? 3 : 0;
if (group_position) {
var integer = parts[0];
var str = '';
var offset = integer.length % group_position;
for (var i = integer.length; i >= 0; i--) {
var l = this.remove_separator(str, info.group_sep).length;
if (format == "#,##,###.##" && str.indexOf(",") != -1) { // INR
group_position = 2;
l += 1;
}
str += integer.charAt(i);
if (l && !((l + 1) % group_position) && i != 0) {
str += info.group_sep;
}
}
parts[0] = str.split("").reverse().join("");
}
if (parts[0] + "" == "") {
parts[0] = "0";
}
// join decimal
parts[1] = (parts[1] && info.fraction_sep) ? (info.fraction_sep + parts[1]) : "";
// join
return (is_negative ? "-" : "") + parts[0] + parts[1];
},
get_format_info(format) {
let format_info = number_formats[format];
if (!format_info) {
throw `Unknown number format "${format}"`;
}
return format_info;
},
round(num, precision) {
var is_negative = num < 0 ? true : false;
var d = parseInt(precision || 0);
var m = Math.pow(10, d);
var n = +(d ? Math.abs(num) * m : Math.abs(num)).toFixed(8); // Avoid rounding errors
var i = Math.floor(n), f = n - i;
var r = ((!precision && f == 0.5) ? ((i % 2 == 0) ? i : i + 1) : Math.round(n));
r = d ? r / m : r;
return is_negative ? -r : r;
},
remove_separator(text, sep) {
return text.replace(new RegExp(sep === "." ? "\\." : sep, "g"), '');
}
};
2018-01-08 12:29:49 +00:00
2018-01-24 11:52:34 +00:00
/***/ }),
2018-01-25 10:05:24 +00:00
/* 17 */
2018-01-24 11:52:34 +00:00
/***/ (function(module, exports) {
2018-01-08 12:29:49 +00:00
2018-01-24 11:52:34 +00:00
module.exports = {
standard_fields: [
{
fieldname: 'name', fieldtype: 'Data', reqd: 1
},
{
fieldname: 'owner', fieldtype: 'Link', reqd: 1, options: 'User'
},
{
fieldname: 'modified_by', fieldtype: 'Link', reqd: 1, options: 'User'
},
{
fieldname: 'creation', fieldtype: 'Datetime', reqd: 1
},
{
fieldname: 'modified', fieldtype: 'Datetime', reqd: 1
},
{
fieldname: 'keywords', fieldtype: 'Text'
},
{
fieldname: 'docstatus', fieldtype: 'Int', reqd: 1, default: 0
}
],
child_fields: [
{
fieldname: 'idx', fieldtype: 'Int', reqd: 1
},
{
fieldname: 'parent', fieldtype: 'Data', reqd: 1
},
{
fieldname: 'parenttype', fieldtype: 'Link', reqd: 1, options: 'DocType'
},
{
fieldname: 'parentfield', fieldtype: 'Data', reqd: 1
}
]
};
2018-01-08 12:29:49 +00:00
/***/ }),
2018-01-25 10:05:24 +00:00
/* 18 */
2018-01-08 12:29:49 +00:00
/***/ (function(module, exports, __webpack_require__) {
const frappe = __webpack_require__(0);
class Session {
constructor(user, user_key) {
this.user = user || 'guest';
if (this.user !== 'guest') {
this.login(user_key);
}
}
2018-01-08 12:29:49 +00:00
login(user_key) {
// could be password, sessionid, otp
}
2018-01-08 12:29:49 +00:00
}
module.exports = { Session: Session };
2018-01-16 07:16:50 +00:00
/***/ }),
2018-01-25 10:05:24 +00:00
/* 19 */
2018-01-16 07:16:50 +00:00
/***/ (function(module, exports) {
class BaseError extends Error {
constructor(status_code, ...params) {
super(...params);
this.status_code = status_code;
}
}
class ValidationError extends BaseError {
constructor(...params) { super(417, ...params); }
}
module.exports = {
ValidationError: ValidationError,
ValueError: class ValueError extends ValidationError { },
NotFound: class NotFound extends BaseError {
constructor(...params) { super(404, ...params); }
},
Forbidden: class Forbidden extends BaseError {
constructor(...params) { super(403, ...params); }
},
}
2018-01-08 12:29:49 +00:00
/***/ }),
2018-01-25 10:05:24 +00:00
/* 20 */
2018-01-08 12:29:49 +00:00
/***/ (function(module, exports, __webpack_require__) {
const frappe = __webpack_require__(0);
2018-01-25 10:05:24 +00:00
const path = __webpack_require__(21);
2018-01-08 12:29:49 +00:00
module.exports = class RESTClient {
constructor({server, protocol='http'}) {
this.server = server;
this.protocol = protocol;
2018-01-10 10:50:57 +00:00
this.init_type_map();
2018-01-10 10:50:57 +00:00
this.json_headers = {
'Accept': 'application/json',
'Content-Type': 'application/json'
}
}
2018-01-08 12:29:49 +00:00
connect() {
2018-01-08 12:29:49 +00:00
}
2018-01-08 12:29:49 +00:00
async insert(doctype, doc) {
doc.doctype = doctype;
let url = this.protocol + '://' + path.join(this.server, `/api/resource/${frappe.slug(doctype)}`);
let response = await frappe.fetch(url, {
method: 'POST',
headers: this.json_headers,
body: JSON.stringify(doc)
});
2018-01-08 12:29:49 +00:00
return await response.json();
}
2018-01-08 12:29:49 +00:00
async get(doctype, name) {
let url = this.protocol + '://' + path.join(this.server, `/api/resource/${frappe.slug(doctype)}/${name}`);
let response = await frappe.fetch(url, {
method: 'GET',
headers: this.json_headers
});
return await response.json();
}
2018-01-08 12:29:49 +00:00
async get_all({doctype, fields, filters, start, limit, sort_by, order}) {
let url = this.protocol + '://' + path.join(this.server, `/api/resource/${frappe.slug(doctype)}`);
2018-01-11 10:00:13 +00:00
url = url + "?" + this.get_query_string({
fields: JSON.stringify(fields),
filters: JSON.stringify(filters),
start: start,
limit: limit,
sort_by: sort_by,
order: order
});
2018-01-11 10:00:13 +00:00
let response = await frappe.fetch(url, {
method: 'GET',
headers: this.json_headers
});
return await response.json();
2018-01-08 12:29:49 +00:00
}
2018-01-08 12:29:49 +00:00
async update(doctype, doc) {
doc.doctype = doctype;
let url = this.protocol + '://' + path.join(this.server, `/api/resource/${frappe.slug(doctype)}/${doc.name}`);
let response = await frappe.fetch(url, {
method: 'PUT',
headers: this.json_headers,
body: JSON.stringify(doc)
});
2018-01-08 12:29:49 +00:00
return await response.json();
}
2018-01-08 12:29:49 +00:00
async delete(doctype, name) {
let url = this.protocol + '://' + path.join(this.server, `/api/resource/${frappe.slug(doctype)}/${name}`);
2018-01-08 12:29:49 +00:00
let response = await frappe.fetch(url, {
method: 'DELETE',
headers: this.json_headers
});
2018-01-08 12:29:49 +00:00
return await response.json();
}
2018-01-08 12:29:49 +00:00
get_query_string(params) {
return Object.keys(params)
.map(k => params[k] != null ? encodeURIComponent(k) + '=' + encodeURIComponent(params[k]) : null)
.filter(v => v)
.join('&');
}
2018-01-11 10:00:13 +00:00
2018-01-23 13:18:02 +00:00
async get_value(doctype, name, fieldname) {
let url = this.protocol + '://' + path.join(this.server, `/api/resource/${frappe.slug(doctype)}/${name}/${fieldname}`);
let response = await frappe.fetch(url, {
method: 'GET',
headers: this.json_headers
});
return (await response.json()).value;
}
init_type_map() {
this.type_map = {
'Currency': true
,'Int': true
,'Float': true
,'Percent': true
,'Check': true
,'Small Text': true
,'Long Text': true
,'Code': true
,'Text Editor': true
,'Date': true
,'Datetime': true
,'Time': true
,'Text': true
,'Data': true
,'Link': true
,'Dynamic Link':true
,'Password': true
,'Select': true
,'Read Only': true
,'Attach': true
,'Attach Image':true
,'Signature': true
,'Color': true
,'Barcode': true
,'Geolocation': true
}
}
2018-01-10 10:50:57 +00:00
close() {
2018-01-08 12:29:49 +00:00
}
2018-01-08 12:29:49 +00:00
}
/***/ }),
2018-01-25 10:05:24 +00:00
/* 21 */
2018-01-08 12:29:49 +00:00
/***/ (function(module, exports, __webpack_require__) {
/* WEBPACK VAR INJECTION */(function(process) {// Copyright Joyent, Inc. and other Node contributors.
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to permit
// persons to whom the Software is furnished to do so, subject to the
// following conditions:
//
// The above copyright notice and this permission notice shall be included
// in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
// USE OR OTHER DEALINGS IN THE SOFTWARE.
// resolves . and .. elements in a path array with directory names there
// must be no slashes, empty elements, or device names (c:\) in the array
// (so also no leading and trailing slashes - it does not distinguish
// relative and absolute paths)
function normalizeArray(parts, allowAboveRoot) {
// if the path tries to go above the root, `up` ends up > 0
var up = 0;
for (var i = parts.length - 1; i >= 0; i--) {
var last = parts[i];
if (last === '.') {
parts.splice(i, 1);
} else if (last === '..') {
parts.splice(i, 1);
up++;
} else if (up) {
parts.splice(i, 1);
up--;
}
}
// if the path is allowed to go above the root, restore leading ..s
if (allowAboveRoot) {
for (; up--; up) {
parts.unshift('..');
}
}
return parts;
}
// Split a filename into [root, dir, basename, ext], unix version
// 'root' is just a slash, or nothing.
var splitPathRe =
/^(\/?|)([\s\S]*?)((?:\.{1,2}|[^\/]+?|)(\.[^.\/]*|))(?:[\/]*)$/;
var splitPath = function(filename) {
return splitPathRe.exec(filename).slice(1);
};
// path.resolve([from ...], to)
// posix version
exports.resolve = function() {
var resolvedPath = '',
resolvedAbsolute = false;
for (var i = arguments.length - 1; i >= -1 && !resolvedAbsolute; i--) {
var path = (i >= 0) ? arguments[i] : process.cwd();
// Skip empty and invalid entries
if (typeof path !== 'string') {
throw new TypeError('Arguments to path.resolve must be strings');
} else if (!path) {
continue;
}
resolvedPath = path + '/' + resolvedPath;
resolvedAbsolute = path.charAt(0) === '/';
}
// At this point the path should be resolved to a full absolute path, but
// handle relative paths to be safe (might happen when process.cwd() fails)
// Normalize the path
resolvedPath = normalizeArray(filter(resolvedPath.split('/'), function(p) {
return !!p;
}), !resolvedAbsolute).join('/');
return ((resolvedAbsolute ? '/' : '') + resolvedPath) || '.';
};
// path.normalize(path)
// posix version
exports.normalize = function(path) {
var isAbsolute = exports.isAbsolute(path),
trailingSlash = substr(path, -1) === '/';
// Normalize the path
path = normalizeArray(filter(path.split('/'), function(p) {
return !!p;
}), !isAbsolute).join('/');
if (!path && !isAbsolute) {
path = '.';
}
if (path && trailingSlash) {
path += '/';
}
return (isAbsolute ? '/' : '') + path;
};
// posix version
exports.isAbsolute = function(path) {
return path.charAt(0) === '/';
};
// posix version
exports.join = function() {
var paths = Array.prototype.slice.call(arguments, 0);
return exports.normalize(filter(paths, function(p, index) {
if (typeof p !== 'string') {
throw new TypeError('Arguments to path.join must be strings');
}
return p;
}).join('/'));
};
// path.relative(from, to)
// posix version
exports.relative = function(from, to) {
from = exports.resolve(from).substr(1);
to = exports.resolve(to).substr(1);
function trim(arr) {
var start = 0;
for (; start < arr.length; start++) {
if (arr[start] !== '') break;
}
var end = arr.length - 1;
for (; end >= 0; end--) {
if (arr[end] !== '') break;
}
if (start > end) return [];
return arr.slice(start, end - start + 1);
}
var fromParts = trim(from.split('/'));
var toParts = trim(to.split('/'));
var length = Math.min(fromParts.length, toParts.length);
var samePartsLength = length;
for (var i = 0; i < length; i++) {
if (fromParts[i] !== toParts[i]) {
samePartsLength = i;
break;
}
}
var outputParts = [];
for (var i = samePartsLength; i < fromParts.length; i++) {
outputParts.push('..');
}
outputParts = outputParts.concat(toParts.slice(samePartsLength));
return outputParts.join('/');
};
exports.sep = '/';
exports.delimiter = ':';
exports.dirname = function(path) {
var result = splitPath(path),
root = result[0],
dir = result[1];
if (!root && !dir) {
// No dirname whatsoever
return '.';
}
if (dir) {
// It has a dirname, strip trailing slash
dir = dir.substr(0, dir.length - 1);
}
return root + dir;
};
exports.basename = function(path, ext) {
var f = splitPath(path)[2];
// TODO: make this comparison case-insensitive on windows?
if (ext && f.substr(-1 * ext.length) === ext) {
f = f.substr(0, f.length - ext.length);
}
return f;
};
2018-01-24 11:52:34 +00:00
exports.extname = function(path) {
return splitPath(path)[3];
};
function filter (xs, f) {
if (xs.filter) return xs.filter(f);
var res = [];
for (var i = 0; i < xs.length; i++) {
if (f(xs[i], i, xs)) res.push(xs[i]);
}
return res;
}
// String.prototype.substr - negative index don't work in IE8
var substr = 'ab'.substr(-1) === 'b'
? function (str, start, len) { return str.substr(start, len) }
: function (str, start, len) {
if (start < 0) start = str.length + start;
return str.substr(start, len);
}
;
2018-01-25 10:05:24 +00:00
/* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(22)))
2018-01-24 11:52:34 +00:00
/***/ }),
2018-01-25 10:05:24 +00:00
/* 22 */
2018-01-24 11:52:34 +00:00
/***/ (function(module, exports) {
// shim for using process in browser
var process = module.exports = {};
// cached from whatever global is present so that test runners that stub it
// don't break things. But we need to wrap it in a try catch in case it is
// wrapped in strict mode code which doesn't define any globals. It's inside a
// function because try/catches deoptimize in certain engines.
var cachedSetTimeout;
var cachedClearTimeout;
function defaultSetTimout() {
throw new Error('setTimeout has not been defined');
}
function defaultClearTimeout () {
throw new Error('clearTimeout has not been defined');
}
(function () {
try {
if (typeof setTimeout === 'function') {
cachedSetTimeout = setTimeout;
} else {
cachedSetTimeout = defaultSetTimout;
}
} catch (e) {
cachedSetTimeout = defaultSetTimout;
}
try {
if (typeof clearTimeout === 'function') {
cachedClearTimeout = clearTimeout;
} else {
cachedClearTimeout = defaultClearTimeout;
}
} catch (e) {
cachedClearTimeout = defaultClearTimeout;
}
} ())
function runTimeout(fun) {
if (cachedSetTimeout === setTimeout) {
//normal enviroments in sane situations
return setTimeout(fun, 0);
}
// if setTimeout wasn't available but was latter defined
if ((cachedSetTimeout === defaultSetTimout || !cachedSetTimeout) && setTimeout) {
cachedSetTimeout = setTimeout;
return setTimeout(fun, 0);
}
try {
// when when somebody has screwed with setTimeout but no I.E. maddness
return cachedSetTimeout(fun, 0);
} catch(e){
try {
// When we are in I.E. but the script has been evaled so I.E. doesn't trust the global object when called normally
return cachedSetTimeout.call(null, fun, 0);
} catch(e){
// same as above but when it's a version of I.E. that must have the global object for 'this', hopfully our context correct otherwise it will throw a global error
return cachedSetTimeout.call(this, fun, 0);
}
}
}
function runClearTimeout(marker) {
if (cachedClearTimeout === clearTimeout) {
//normal enviroments in sane situations
return clearTimeout(marker);
}
// if clearTimeout wasn't available but was latter defined
if ((cachedClearTimeout === defaultClearTimeout || !cachedClearTimeout) && clearTimeout) {
cachedClearTimeout = clearTimeout;
return clearTimeout(marker);
}
try {
// when when somebody has screwed with setTimeout but no I.E. maddness
return cachedClearTimeout(marker);
} catch (e){
try {
// When we are in I.E. but the script has been evaled so I.E. doesn't trust the global object when called normally
return cachedClearTimeout.call(null, marker);
} catch (e){
// same as above but when it's a version of I.E. that must have the global object for 'this', hopfully our context correct otherwise it will throw a global error.
// Some versions of I.E. have different rules for clearTimeout vs setTimeout
return cachedClearTimeout.call(this, marker);
}
}
}
var queue = [];
var draining = false;
var currentQueue;
var queueIndex = -1;
function cleanUpNextTick() {
if (!draining || !currentQueue) {
return;
}
draining = false;
if (currentQueue.length) {
queue = currentQueue.concat(queue);
} else {
queueIndex = -1;
}
if (queue.length) {
drainQueue();
}
}
function drainQueue() {
if (draining) {
return;
}
var timeout = runTimeout(cleanUpNextTick);
draining = true;
var len = queue.length;
while(len) {
currentQueue = queue;
queue = [];
while (++queueIndex < len) {
if (currentQueue) {
currentQueue[queueIndex].run();
}
}
queueIndex = -1;
len = queue.length;
}
currentQueue = null;
draining = false;
runClearTimeout(timeout);
}
process.nextTick = function (fun) {
var args = new Array(arguments.length - 1);
if (arguments.length > 1) {
for (var i = 1; i < arguments.length; i++) {
args[i - 1] = arguments[i];
}
}
queue.push(new Item(fun, args));
if (queue.length === 1 && !draining) {
runTimeout(drainQueue);
}
};
// v8 likes predictible objects
function Item(fun, array) {
this.fun = fun;
this.array = array;
}
Item.prototype.run = function () {
this.fun.apply(null, this.array);
};
process.title = 'browser';
process.browser = true;
process.env = {};
process.argv = [];
process.version = ''; // empty string to avoid regexp issues
process.versions = {};
function noop() {}
process.on = noop;
process.addListener = noop;
process.once = noop;
process.off = noop;
process.removeListener = noop;
process.removeAllListeners = noop;
process.emit = noop;
process.prependListener = noop;
process.prependOnceListener = noop;
process.listeners = function (name) { return [] }
process.binding = function (name) {
throw new Error('process.binding is not supported');
2018-01-08 12:29:49 +00:00
};
2018-01-24 11:52:34 +00:00
process.cwd = function () { return '/' };
process.chdir = function (dir) {
throw new Error('process.chdir is not supported');
};
process.umask = function() { return 0; };
2018-01-08 12:29:49 +00:00
/***/ }),
2018-01-25 10:05:24 +00:00
/* 23 */
2018-01-08 12:29:49 +00:00
/***/ (function(module, exports, __webpack_require__) {
const frappe = __webpack_require__(0);
2018-01-25 10:05:24 +00:00
const Dropdown = __webpack_require__(24);
2018-01-08 12:29:49 +00:00
2018-01-09 13:40:33 +00:00
module.exports = {
add(tag, className, parent) {
let element = document.createElement(tag);
if (className) {
for (let c of className.split(' ')) {
this.add_class(element, c);
}
}
if (parent) {
parent.appendChild(element);
}
return element;
},
2018-01-09 13:40:33 +00:00
remove(element) {
element.parentNode.removeChild(element);
},
2018-01-10 10:50:57 +00:00
add_class(element, className) {
if (element.classList) {
element.classList.add(className);
} else {
element.className += " " + className;
}
},
2018-01-09 13:40:33 +00:00
remove_class(element, className) {
if (element.classList) {
element.classList.remove(className);
} else {
element.className = element.className.replace(new RegExp('(^|\\b)' + className.split(' ').join('|') + '(\\b|$)', 'gi'), ' ');
}
},
2018-01-11 10:00:13 +00:00
toggle(element, default_display = '') {
element.style.display = element.style.display === 'none' ? default_display : 'none';
},
2018-01-11 10:00:13 +00:00
make_dropdown(label, parent, btn_class = 'btn-secondary') {
return new Dropdown({parent: parent, label:label, btn_class:btn_class});
}
2018-01-09 13:40:33 +00:00
}
/***/ }),
2018-01-25 10:05:24 +00:00
/* 24 */
2018-01-09 13:40:33 +00:00
/***/ (function(module, exports, __webpack_require__) {
const frappe = __webpack_require__(0);
class Dropdown {
constructor({parent, label, btn_class = 'btn-secondary', items = []}) {
Object.assign(this, arguments[0]);
2018-01-09 13:40:33 +00:00
this.dropdown_items = [];
this.setup_background_click();
this.make();
2018-01-09 13:40:33 +00:00
// init items
if (this.items) {
for (item of this.items) {
this.add_item(item.label, item.action);
}
}
}
setup_background_click() {
if (!document.dropdown_setup) {
frappe.dropdowns = [];
// setup hiding all dropdowns on click
document.addEventListener('click', (event) => {
for (let d of frappe.dropdowns) {
if (d.button !== event.target) {
d.collapse();
}
}
});
document.dropdown_setup = true;
}
frappe.dropdowns.push(this);
}
make() {
this.dropdown = frappe.ui.add('div', 'dropdown', this.parent);
this.make_button();
this.dropdown_menu = frappe.ui.add('div', 'dropdown-menu', this.dropdown);
}
make_button() {
this.button = frappe.ui.add('button', 'btn ' + this.btn_class,
this.dropdown);
frappe.ui.add_class(this.button, 'dropdown-toggle');
this.button.textContent = this.label;
this.button.addEventListener('click', () => {
this.toggle();
});
}
expand() {
this.dropdown.classList.add('show');
this.dropdown_menu.classList.add('show');
}
collapse() {
this.dropdown.classList.remove('show');
this.dropdown_menu.classList.remove('show');
}
toggle() {
this.dropdown.classList.toggle('show');
this.dropdown_menu.classList.toggle('show');
}
add_item(label, action) {
2018-01-16 07:16:50 +00:00
let item = frappe.ui.add('button', 'dropdown-item', this.dropdown_menu);
item.textContent = label;
2018-01-16 07:16:50 +00:00
item.setAttribute('type', 'button');
if (typeof action === 'string') {
item.src = action;
2018-01-16 07:16:50 +00:00
item.addEventListener('click', async () => {
await frappe.router.set_route(action);
this.toggle();
});
} else {
item.addEventListener('click', async () => {
await action();
this.toggle();
});
}
this.dropdown_items.push(item);
}
2018-01-09 13:40:33 +00:00
float_right() {
frappe.ui.add_class(this.dropdown, 'float-right');
frappe.ui.add_class(this.dropdown_menu, 'dropdown-menu-right');
}
2018-01-09 13:40:33 +00:00
}
module.exports = Dropdown;
2018-01-09 13:40:33 +00:00
/***/ }),
2018-01-25 10:05:24 +00:00
/* 25 */
2018-01-09 13:40:33 +00:00
/***/ (function(module, exports, __webpack_require__) {
const frappe = __webpack_require__(0);
2018-01-25 10:05:24 +00:00
const Search = __webpack_require__(26);
const Router = __webpack_require__(27);
const Page = __webpack_require__(28);
2018-01-24 11:52:34 +00:00
const BaseList = __webpack_require__(4);
const BaseForm = __webpack_require__(5);
2018-01-25 10:05:24 +00:00
const Navbar = __webpack_require__(36);
2018-01-09 13:40:33 +00:00
module.exports = class Desk {
constructor() {
frappe.router = new Router();
frappe.router.listen();
2018-01-09 13:40:33 +00:00
2018-01-23 08:00:08 +00:00
let body = document.querySelector('body');
this.navbar = new Navbar();
this.container = frappe.ui.add('div', 'container-fluid', body);
2018-01-09 13:40:33 +00:00
2018-01-23 08:00:08 +00:00
this.container_row = frappe.ui.add('div', 'row', this.container)
this.sidebar = frappe.ui.add('div', 'col-md-2 p-3 sidebar', this.container_row);
this.body = frappe.ui.add('div', 'col-md-10 p-3 main', this.container_row);
2018-01-09 13:40:33 +00:00
this.sidebar_items = [];
this.pages = {
lists: {},
forms: {}
};
2018-01-09 13:40:33 +00:00
this.init_routes();
2018-01-09 13:40:33 +00:00
// this.search = new Search(this.nav);
}
2018-01-09 13:40:33 +00:00
init_routes() {
2018-01-23 08:00:08 +00:00
frappe.router.add('not-found', async (params) => {
if (!this.not_found_page) {
this.not_found_page = new Page('Not Found');
}
await this.not_found_page.show();
this.not_found_page.render_error('Not Found', params ? params.route : '');
})
frappe.router.add('list/:doctype', async (params) => {
let page = this.get_list_page(params.doctype);
await page.show(params);
});
2018-01-09 13:40:33 +00:00
frappe.router.add('edit/:doctype/:name', async (params) => {
let page = this.get_form_page(params.doctype);
await page.show(params);
})
2018-01-09 13:40:33 +00:00
frappe.router.add('new/:doctype', async (params) => {
let doc = await frappe.get_new_doc(params.doctype);
2018-01-25 10:05:24 +00:00
// unset the name, its local
await frappe.router.set_route('edit', doc.doctype, doc.name);
await doc.set('name', '');
});
2018-01-09 13:40:33 +00:00
}
2018-01-09 13:40:33 +00:00
get_list_page(doctype) {
if (!this.pages.lists[doctype]) {
2018-01-24 11:52:34 +00:00
let page = new Page('List ' + frappe.get_meta(doctype).name);
page.list = new (this.get_view_class(doctype, 'List', BaseList))({
doctype: doctype,
parent: page.body
});
page.on('show', async () => {
await page.list.run();
});
this.pages.lists[doctype] = page;
}
return this.pages.lists[doctype];
}
2018-01-09 13:40:33 +00:00
get_form_page(doctype) {
if (!this.pages.forms[doctype]) {
2018-01-24 11:52:34 +00:00
let page = new Page('Edit ' + frappe.get_meta(doctype).name);
page.form = new (this.get_view_class(doctype, 'Form', BaseForm))({
doctype: doctype,
parent: page.body
});
page.on('show', async (params) => {
try {
page.doc = await frappe.get_doc(params.doctype, params.name);
page.form.use(page.doc);
} catch (e) {
page.render_error(e.status_code, e.message);
}
});
this.pages.forms[doctype] = page;
}
return this.pages.forms[doctype];
}
2018-01-09 13:40:33 +00:00
2018-01-24 11:52:34 +00:00
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`];
}
add_sidebar_item(label, action) {
let item = frappe.ui.add('a', '', frappe.ui.add('p', null, frappe.desk.sidebar));
item.textContent = label;
if (typeof action === 'string') {
item.href = action;
} else {
item.addEventHandler('click', () => {
action();
});
}
}
}
2018-01-09 13:40:33 +00:00
/***/ }),
2018-01-25 10:05:24 +00:00
/* 26 */
2018-01-09 13:40:33 +00:00
/***/ (function(module, exports, __webpack_require__) {
const frappe = __webpack_require__(0);
module.exports = class Search {
constructor(parent) {
this.input = frappe.ui.add('input', 'form-control nav-search', parent);
this.input.addEventListener('keypress', function(event) {
if (event.keyCode===13) {
let list = frappe.router.current_page.list;
if (list) {
list.search_text = this.value;
list.run();
}
}
})
}
}
2018-01-11 10:00:13 +00:00
/***/ }),
2018-01-25 10:05:24 +00:00
/* 27 */
/***/ (function(module, exports, __webpack_require__) {
2018-01-08 12:29:49 +00:00
const frappe = __webpack_require__(0);
2018-01-08 12:29:49 +00:00
module.exports = class Router {
constructor() {
this.current_page = null;
this.static_routes = [];
this.dynamic_routes = [];
}
2018-01-08 12:29:49 +00:00
add(route, handler) {
let page = {handler: handler, route: route};
2018-01-08 12:29:49 +00:00
// '/todo/:name/:place'.match(/:([^/]+)/g);
page.param_keys = route.match(/:([^/]+)/g);
2018-01-11 10:00:13 +00:00
if (page.param_keys) {
// make expression
2018-01-23 08:00:08 +00:00
// '/todo/:name/:place'.replace(/\/:([^/]+)/g, "\/([^/]+)");
2018-01-16 07:16:50 +00:00
page.depth = route.split('/').length;
2018-01-23 08:00:08 +00:00
page.expression = route.replace(/\/:([^/]+)/g, "\/([^/]+)");
this.dynamic_routes.push(page);
this.sort_dynamic_routes();
} else {
this.static_routes.push(page);
this.sort_static_routes();
}
}
2018-01-08 12:29:49 +00:00
sort_dynamic_routes() {
2018-01-16 07:16:50 +00:00
// routes with more parts first
this.dynamic_routes = this.dynamic_routes.sort((a, b) => {
2018-01-16 07:16:50 +00:00
if (a.depth < b.depth) {
return 1;
2018-01-16 07:16:50 +00:00
} else if (a.depth > b.depth) {
return -1;
} else {
2018-01-16 07:16:50 +00:00
if (a.param_keys.length !== b.param_keys.length) {
return a.param_keys.length > b.param_keys.length ? 1 : -1;
} else {
return a.route.length > b.route.length ? 1 : -1;
}
}
})
}
2018-01-08 12:29:49 +00:00
sort_static_routes() {
// longer routes on first
this.static_routes = this.static_routes.sort((a, b) => {
return a.route.length > b.route.length ? 1 : -1;
});
}
2018-01-08 12:29:49 +00:00
2018-01-24 11:52:34 +00:00
listen() {
window.addEventListener('hashchange', (event) => {
this.show(window.location.hash);
});
}
2018-01-24 11:52:34 +00:00
set_route(...parts) {
const route = parts.join('/');
window.location.hash = route;
}
2018-01-24 11:52:34 +00:00
async show(route) {
if (route && route[0]==='#') {
route = route.substr(1);
}
2018-01-24 11:52:34 +00:00
if (!route) {
route = this.default;
}
2018-01-24 11:52:34 +00:00
let page = this.match(route);
2018-01-24 11:52:34 +00:00
if (page) {
if (typeof page.handler==='function') {
await page.handler(page.params);
} else {
await page.handler.show(page.params);
}
2018-01-24 11:52:34 +00:00
} else {
await this.match('not-found').handler({route: route});
}
}
2018-01-24 11:52:34 +00:00
match(route) {
// match static
for(let page of this.static_routes) {
if (page.route === route) {
return {handler: page.handler};
}
}
2018-01-08 12:29:49 +00:00
2018-01-24 11:52:34 +00:00
// match dynamic
for(let page of this.dynamic_routes) {
let matches = route.match(new RegExp(page.expression));
if (matches && matches.length == page.param_keys.length + 1) {
let params = {}
for (let i=0; i < page.param_keys.length; i++) {
params[page.param_keys[i].substr(1)] = matches[i + 1];
}
return {handler:page.handler, params: params};
}
}
}
}
2018-01-08 12:29:49 +00:00
/***/ }),
2018-01-25 10:05:24 +00:00
/* 28 */
2018-01-08 12:29:49 +00:00
/***/ (function(module, exports, __webpack_require__) {
const frappe = __webpack_require__(0);
2018-01-09 13:40:33 +00:00
2018-01-24 11:52:34 +00:00
module.exports = class Page {
constructor(title) {
this.handlers = {};
this.title = title;
this.make();
}
2018-01-08 12:29:49 +00:00
make() {
2018-01-24 11:52:34 +00:00
this.wrapper = frappe.ui.add('div', 'page hide', frappe.desk.body);
this.body = frappe.ui.add('div', 'page-body', this.wrapper);
}
2018-01-08 12:29:49 +00:00
2018-01-24 11:52:34 +00:00
hide() {
this.wrapper.classList.add('hide');
this.trigger('hide');
}
2018-01-23 08:00:08 +00:00
2018-01-24 11:52:34 +00:00
async show(params) {
if (frappe.router.current_page) {
frappe.router.current_page.hide();
}
this.wrapper.classList.remove('hide');
this.body.classList.remove('hide');
2018-01-11 10:00:13 +00:00
2018-01-24 11:52:34 +00:00
if (this.page_error) {
this.page_error.classList.add('hide');
}
2018-01-11 10:00:13 +00:00
2018-01-24 11:52:34 +00:00
frappe.router.current_page = this;
document.title = this.title;
2018-01-08 12:29:49 +00:00
2018-01-24 11:52:34 +00:00
await this.trigger('show', params);
}
2018-01-10 10:50:57 +00:00
2018-01-24 11:52:34 +00:00
render_error(title, message) {
if (!this.page_error) {
this.page_error = frappe.ui.add('div', 'page-error', this.wrapper);
}
2018-01-24 11:52:34 +00:00
this.body.classList.add('hide');
this.page_error.classList.remove('hide');
this.page_error.innerHTML = `<h3 class="text-extra-muted">${title ? title : ""}</h3><p class="text-muted">${message ? message : ""}</p>`;
}
2018-01-10 10:50:57 +00:00
2018-01-24 11:52:34 +00:00
on(event, fn) {
if (!this.handlers[event]) this.handlers[event] = [];
this.handlers[event].push(fn);
}
2018-01-09 13:40:33 +00:00
2018-01-24 11:52:34 +00:00
async trigger(event, params) {
if (this.handlers[event]) {
for (let handler of this.handlers[event]) {
await handler(params);
}
}
}
2018-01-09 13:40:33 +00:00
}
/***/ }),
2018-01-25 10:05:24 +00:00
/* 29 */
2018-01-09 13:40:33 +00:00
/***/ (function(module, exports, __webpack_require__) {
const control_classes = {
2018-01-25 10:05:24 +00:00
Data: __webpack_require__(30),
Text: __webpack_require__(31),
Select: __webpack_require__(32),
Link: __webpack_require__(33),
Float: __webpack_require__(6),
Currency: __webpack_require__(35)
2018-01-08 12:29:49 +00:00
}
module.exports = {
get_control_class(fieldtype) {
return control_classes[fieldtype];
},
make_control(field, parent) {
const control_class = this.get_control_class(field.fieldtype);
let control = new control_class(field, parent);
control.make();
return control;
}
2018-01-09 13:40:33 +00:00
}
/***/ }),
2018-01-25 10:05:24 +00:00
/* 30 */
2018-01-09 13:40:33 +00:00
/***/ (function(module, exports, __webpack_require__) {
2018-01-24 11:52:34 +00:00
const BaseControl = __webpack_require__(2);
2018-01-09 13:40:33 +00:00
class DataControl extends BaseControl {
make() {
super.make();
this.input.setAttribute('type', 'text');
}
2018-01-08 12:29:49 +00:00
};
2018-01-09 13:40:33 +00:00
module.exports = DataControl;
/***/ }),
2018-01-25 10:05:24 +00:00
/* 31 */
2018-01-09 13:40:33 +00:00
/***/ (function(module, exports, __webpack_require__) {
2018-01-24 11:52:34 +00:00
const BaseControl = __webpack_require__(2);
2018-01-09 13:40:33 +00:00
2018-01-10 10:50:57 +00:00
class TextControl extends BaseControl {
make_input() {
this.input = frappe.ui.add('textarea', 'form-control', this.form_group);
}
make() {
super.make();
this.input.setAttribute('rows', '8');
}
2018-01-10 10:50:57 +00:00
};
2018-01-09 13:40:33 +00:00
2018-01-10 10:50:57 +00:00
module.exports = TextControl;
2018-01-09 13:40:33 +00:00
2018-01-10 10:50:57 +00:00
/***/ }),
2018-01-25 10:05:24 +00:00
/* 32 */
2018-01-10 10:50:57 +00:00
/***/ (function(module, exports, __webpack_require__) {
2018-01-09 13:40:33 +00:00
2018-01-24 11:52:34 +00:00
const BaseControl = __webpack_require__(2);
2018-01-09 13:40:33 +00:00
2018-01-10 10:50:57 +00:00
class SelectControl extends BaseControl {
make_input() {
this.input = frappe.ui.add('select', 'form-control', this.form_group);
2018-01-09 13:40:33 +00:00
let options = this.options;
if (typeof options==='string') {
options = options.split('\n');
}
2018-01-09 13:40:33 +00:00
for (let value of options) {
let option = frappe.ui.add('option', null, this.input);
option.textContent = value;
option.setAttribute('value', value);
}
}
make() {
super.make();
this.input.setAttribute('row', '3');
}
2018-01-10 10:50:57 +00:00
};
2018-01-09 13:40:33 +00:00
2018-01-10 10:50:57 +00:00
module.exports = SelectControl;
2018-01-09 13:40:33 +00:00
2018-01-10 10:50:57 +00:00
/***/ }),
2018-01-25 10:05:24 +00:00
/* 33 */
2018-01-23 12:26:11 +00:00
/***/ (function(module, exports, __webpack_require__) {
const frappe = __webpack_require__(0);
2018-01-24 11:52:34 +00:00
const BaseControl = __webpack_require__(2);
2018-01-25 10:05:24 +00:00
const Awesomplete = __webpack_require__(34);
2018-01-23 12:26:11 +00:00
class LinkControl extends BaseControl {
make() {
super.make();
2018-01-23 12:47:56 +00:00
this.input.setAttribute('type', 'text');
this.awesomplete = new Awesomplete(this.input, {
autoFirst: true,
minChars: 0,
maxItems: 99
});
2018-01-23 12:26:11 +00:00
2018-01-23 12:47:56 +00:00
// rebuild the list on input
this.input.addEventListener('input', async (event) => {
this.awesomplete.list = await this.get_list(this.input.value);
});
}
async get_list(query) {
return (await frappe.db.get_all({
doctype: this.options,
filters: this.get_filters(query),
limit: 50
})).map(d => d.name);
}
get_filters(query) {
return { keywords: ["like", query] }
2018-01-23 12:26:11 +00:00
}
};
module.exports = LinkControl;
/***/ }),
2018-01-25 10:05:24 +00:00
/* 34 */
2018-01-23 12:26:11 +00:00
/***/ (function(module, exports) {
/**
* Simple, lightweight, usable local autocomplete library for modern browsers
* Because there werent enough autocomplete scripts in the world? Because Im completely insane and have NIH syndrome? Probably both. :P
* @author Lea Verou http://leaverou.github.io/awesomplete
* MIT license
*/
(function () {
var _ = function (input, o) {
var me = this;
// Setup
this.isOpened = false;
this.input = $(input);
this.input.setAttribute("autocomplete", "off");
this.input.setAttribute("aria-autocomplete", "list");
o = o || {};
configure(this, {
minChars: 2,
maxItems: 10,
autoFirst: false,
data: _.DATA,
filter: _.FILTER_CONTAINS,
sort: o.sort === false ? false : _.SORT_BYLENGTH,
item: _.ITEM,
replace: _.REPLACE
}, o);
this.index = -1;
// Create necessary elements
this.container = $.create("div", {
className: "awesomplete",
around: input
});
this.ul = $.create("ul", {
hidden: "hidden",
inside: this.container
});
this.status = $.create("span", {
className: "visually-hidden",
role: "status",
"aria-live": "assertive",
"aria-relevant": "additions",
inside: this.container
});
// Bind events
this._events = {
input: {
"input": this.evaluate.bind(this),
"blur": this.close.bind(this, { reason: "blur" }),
"keydown": function(evt) {
var c = evt.keyCode;
// If the dropdown `ul` is in view, then act on keydown for the following keys:
// Enter / Esc / Up / Down
if(me.opened) {
if (c === 13 && me.selected) { // Enter
evt.preventDefault();
me.select();
}
else if (c === 27) { // Esc
me.close({ reason: "esc" });
}
else if (c === 38 || c === 40) { // Down/Up arrow
evt.preventDefault();
me[c === 38? "previous" : "next"]();
}
}
}
},
form: {
"submit": this.close.bind(this, { reason: "submit" })
},
ul: {
"mousedown": function(evt) {
var li = evt.target;
if (li !== this) {
while (li && !/li/i.test(li.nodeName)) {
li = li.parentNode;
}
if (li && evt.button === 0) { // Only select on left click
evt.preventDefault();
me.select(li, evt.target);
}
}
}
}
};
$.bind(this.input, this._events.input);
$.bind(this.input.form, this._events.form);
$.bind(this.ul, this._events.ul);
if (this.input.hasAttribute("list")) {
this.list = "#" + this.input.getAttribute("list");
this.input.removeAttribute("list");
}
else {
this.list = this.input.getAttribute("data-list") || o.list || [];
}
_.all.push(this);
};
_.prototype = {
set list(list) {
if (Array.isArray(list)) {
this._list = list;
}
else if (typeof list === "string" && list.indexOf(",") > -1) {
this._list = list.split(/\s*,\s*/);
}
else { // Element or CSS selector
list = $(list);
if (list && list.children) {
var items = [];
slice.apply(list.children).forEach(function (el) {
if (!el.disabled) {
var text = el.textContent.trim();
var value = el.value || text;
var label = el.label || text;
if (value !== "") {
items.push({ label: label, value: value });
}
}
});
this._list = items;
}
}
if (document.activeElement === this.input) {
this.evaluate();
}
},
get selected() {
return this.index > -1;
},
get opened() {
return this.isOpened;
},
close: function (o) {
if (!this.opened) {
return;
}
this.ul.setAttribute("hidden", "");
this.isOpened = false;
this.index = -1;
$.fire(this.input, "awesomplete-close", o || {});
},
open: function () {
this.ul.removeAttribute("hidden");
this.isOpened = true;
if (this.autoFirst && this.index === -1) {
this.goto(0);
}
$.fire(this.input, "awesomplete-open");
},
destroy: function() {
//remove events from the input and its form
$.unbind(this.input, this._events.input);
$.unbind(this.input.form, this._events.form);
//move the input out of the awesomplete container and remove the container and its children
var parentNode = this.container.parentNode;
parentNode.insertBefore(this.input, this.container);
parentNode.removeChild(this.container);
//remove autocomplete and aria-autocomplete attributes
this.input.removeAttribute("autocomplete");
this.input.removeAttribute("aria-autocomplete");
//remove this awesomeplete instance from the global array of instances
var indexOfAwesomplete = _.all.indexOf(this);
if (indexOfAwesomplete !== -1) {
_.all.splice(indexOfAwesomplete, 1);
}
},
next: function () {
var count = this.ul.children.length;
this.goto(this.index < count - 1 ? this.index + 1 : (count ? 0 : -1) );
},
previous: function () {
var count = this.ul.children.length;
var pos = this.index - 1;
this.goto(this.selected && pos !== -1 ? pos : count - 1);
},
// Should not be used, highlights specific item without any checks!
goto: function (i) {
var lis = this.ul.children;
if (this.selected) {
lis[this.index].setAttribute("aria-selected", "false");
}
this.index = i;
if (i > -1 && lis.length > 0) {
lis[i].setAttribute("aria-selected", "true");
this.status.textContent = lis[i].textContent;
// scroll to highlighted element in case parent's height is fixed
this.ul.scrollTop = lis[i].offsetTop - this.ul.clientHeight + lis[i].clientHeight;
$.fire(this.input, "awesomplete-highlight", {
text: this.suggestions[this.index]
});
}
},
select: function (selected, origin) {
if (selected) {
this.index = $.siblingIndex(selected);
} else {
selected = this.ul.children[this.index];
}
if (selected) {
var suggestion = this.suggestions[this.index];
var allowed = $.fire(this.input, "awesomplete-select", {
text: suggestion,
origin: origin || selected
});
if (allowed) {
this.replace(suggestion);
this.close({ reason: "select" });
$.fire(this.input, "awesomplete-selectcomplete", {
text: suggestion
});
}
}
},
evaluate: function() {
var me = this;
var value = this.input.value;
if (value.length >= this.minChars && this._list.length > 0) {
this.index = -1;
// Populate list with options that match
this.ul.innerHTML = "";
this.suggestions = this._list
.map(function(item) {
return new Suggestion(me.data(item, value));
})
.filter(function(item) {
return me.filter(item, value);
});
if (this.sort !== false) {
this.suggestions = this.suggestions.sort(this.sort);
}
this.suggestions = this.suggestions.slice(0, this.maxItems);
this.suggestions.forEach(function(text) {
me.ul.appendChild(me.item(text, value));
});
if (this.ul.children.length === 0) {
this.close({ reason: "nomatches" });
} else {
this.open();
}
}
else {
this.close({ reason: "nomatches" });
}
}
};
// Static methods/properties
_.all = [];
_.FILTER_CONTAINS = function (text, input) {
return RegExp($.regExpEscape(input.trim()), "i").test(text);
};
_.FILTER_STARTSWITH = function (text, input) {
return RegExp("^" + $.regExpEscape(input.trim()), "i").test(text);
};
_.SORT_BYLENGTH = function (a, b) {
if (a.length !== b.length) {
return a.length - b.length;
}
return a < b? -1 : 1;
};
_.ITEM = function (text, input) {
var html = input.trim() === "" ? text : text.replace(RegExp($.regExpEscape(input.trim()), "gi"), "<mark>$&</mark>");
return $.create("li", {
innerHTML: html,
"aria-selected": "false"
});
};
_.REPLACE = function (text) {
this.input.value = text.value;
};
_.DATA = function (item/*, input*/) { return item; };
// Private functions
function Suggestion(data) {
var o = Array.isArray(data)
? { label: data[0], value: data[1] }
: typeof data === "object" && "label" in data && "value" in data ? data : { label: data, value: data };
this.label = o.label || o.value;
this.value = o.value;
}
Object.defineProperty(Suggestion.prototype = Object.create(String.prototype), "length", {
get: function() { return this.label.length; }
});
Suggestion.prototype.toString = Suggestion.prototype.valueOf = function () {
return "" + this.label;
};
function configure(instance, properties, o) {
for (var i in properties) {
var initial = properties[i],
attrValue = instance.input.getAttribute("data-" + i.toLowerCase());
if (typeof initial === "number") {
instance[i] = parseInt(attrValue);
}
else if (initial === false) { // Boolean options must be false by default anyway
instance[i] = attrValue !== null;
}
else if (initial instanceof Function) {
instance[i] = null;
}
else {
instance[i] = attrValue;
}
if (!instance[i] && instance[i] !== 0) {
instance[i] = (i in o)? o[i] : initial;
}
}
}
// Helpers
var slice = Array.prototype.slice;
function $(expr, con) {
return typeof expr === "string"? (con || document).querySelector(expr) : expr || null;
}
function $$(expr, con) {
return slice.call((con || document).querySelectorAll(expr));
}
$.create = function(tag, o) {
var element = document.createElement(tag);
for (var i in o) {
var val = o[i];
if (i === "inside") {
$(val).appendChild(element);
}
else if (i === "around") {
var ref = $(val);
ref.parentNode.insertBefore(element, ref);
element.appendChild(ref);
}
else if (i in element) {
element[i] = val;
}
else {
element.setAttribute(i, val);
}
}
return element;
};
$.bind = function(element, o) {
if (element) {
for (var event in o) {
var callback = o[event];
event.split(/\s+/).forEach(function (event) {
element.addEventListener(event, callback);
});
}
}
};
$.unbind = function(element, o) {
if (element) {
for (var event in o) {
var callback = o[event];
event.split(/\s+/).forEach(function(event) {
element.removeEventListener(event, callback);
});
}
}
};
$.fire = function(target, type, properties) {
var evt = document.createEvent("HTMLEvents");
evt.initEvent(type, true, true );
for (var j in properties) {
evt[j] = properties[j];
}
return target.dispatchEvent(evt);
};
$.regExpEscape = function (s) {
return s.replace(/[-\\^$*+?.()|[\]{}]/g, "\\$&");
};
$.siblingIndex = function (el) {
/* eslint-disable no-cond-assign */
for (var i = 0; el = el.previousElementSibling; i++);
return i;
};
// Initialization
function init() {
$$("input.awesomplete").forEach(function (input) {
new _(input);
});
}
// Are we in a browser? Check for Document constructor
if (typeof Document !== "undefined") {
// DOM already loaded?
if (document.readyState !== "loading") {
init();
}
else {
// Wait for it
document.addEventListener("DOMContentLoaded", init);
}
}
_.$ = $;
_.$$ = $$;
// Make sure to export Awesomplete on self when in a browser
if (typeof self !== "undefined") {
self.Awesomplete = _;
}
// Expose Awesomplete as a CJS module
if (typeof module === "object" && module.exports) {
module.exports = _;
}
return _;
}());
/***/ }),
2018-01-25 10:05:24 +00:00
/* 35 */
/***/ (function(module, exports, __webpack_require__) {
const FloatControl = __webpack_require__(6);
const frappe = __webpack_require__(0);
class CurrencyControl extends FloatControl {
parse(value) {
return frappe.parse_number(value);
}
format(value) {
return frappe.format_number(value);
}
};
module.exports = CurrencyControl;
/***/ }),
/* 36 */
2018-01-10 10:50:57 +00:00
/***/ (function(module, exports, __webpack_require__) {
2018-01-09 13:40:33 +00:00
2018-01-10 10:50:57 +00:00
const frappe = __webpack_require__(0);
2018-01-09 13:40:33 +00:00
2018-01-23 08:00:08 +00:00
module.exports = class Navbar {
constructor({brand_label = 'Home'} = {}) {
Object.assign(this, arguments[0]);
this.items = {};
this.navbar = frappe.ui.add('div', 'navbar navbar-expand-md border-bottom', document.querySelector('body'));
this.brand = frappe.ui.add('a', 'navbar-brand', this.navbar);
this.brand.href = '#';
this.brand.textContent = brand_label;
this.toggler = frappe.ui.add('button', 'navbar-toggler', this.navbar);
this.toggler.setAttribute('type', 'button');
this.toggler.setAttribute('data-toggle', 'collapse');
this.toggler.setAttribute('data-target', 'desk-navbar');
this.toggler.innerHTML = `<span class="navbar-toggler-icon"></span>`;
this.navbar_collapse = frappe.ui.add('div', 'collapse navbar-collapse', this.navbar);
this.navbar_collapse.setAttribute('id', 'desk-navbar');
this.nav = frappe.ui.add('ul', 'navbar-nav mr-auto', this.navbar_collapse);
}
add_item(label, route) {
let item = frappe.ui.add('li', 'nav-item', this.nav);
item.link = frappe.ui.add('a', 'nav-link', item);
item.link.textContent = label;
item.link.href = route;
this.items[label] = item;
return item;
}
add_dropdown(label) {
}
add_search() {
let form = frappe.ui.add('form', 'form-inline my-2 my-md-0', this.nav);
}
}
/***/ }),
2018-01-25 10:05:24 +00:00
/* 37 */
2018-01-23 08:00:08 +00:00
/***/ (function(module, exports, __webpack_require__) {
2018-01-24 11:52:34 +00:00
const BaseMeta = __webpack_require__(3);
const BaseDocument = __webpack_require__(1);
2018-01-23 08:00:08 +00:00
2018-01-24 11:52:34 +00:00
class ToDoMeta extends BaseMeta {
setup_meta() {
2018-01-25 10:05:24 +00:00
Object.assign(this, __webpack_require__(38));
}
2018-01-10 10:50:57 +00:00
}
2018-01-09 13:40:33 +00:00
2018-01-24 11:52:34 +00:00
class ToDo extends BaseDocument {
setup() {
this.add_handler('validate');
}
validate() {
if (!this.status) {
this.status = 'Open';
}
}
2018-01-09 13:40:33 +00:00
}
2018-01-24 11:52:34 +00:00
module.exports = {
Document: ToDo,
Meta: ToDoMeta
};
2018-01-10 10:50:57 +00:00
2018-01-09 13:40:33 +00:00
/***/ }),
2018-01-25 10:05:24 +00:00
/* 38 */
2018-01-09 13:40:33 +00:00
/***/ (function(module, exports) {
module.exports = {"autoname":"hash","name":"ToDo","doctype":"DocType","issingle":0,"keyword_fields":["subject","description"],"fields":[{"fieldname":"subject","label":"Subject","fieldtype":"Data","reqd":1},{"fieldname":"description","label":"Description","fieldtype":"Text"},{"fieldname":"status","label":"Status","fieldtype":"Select","options":["Open","Closed"],"default":"Open","reqd":1}]}
2018-01-08 12:29:49 +00:00
2018-01-11 10:00:13 +00:00
/***/ }),
2018-01-25 10:05:24 +00:00
/* 39 */
2018-01-23 08:00:08 +00:00
/***/ (function(module, exports, __webpack_require__) {
2018-01-16 07:16:50 +00:00
2018-01-23 08:00:08 +00:00
const frappe = __webpack_require__(0);
2018-01-24 11:52:34 +00:00
const BaseMeta = __webpack_require__(3);
const BaseDocument = __webpack_require__(1);
2018-01-16 07:16:50 +00:00
2018-01-24 11:52:34 +00:00
class AccountMeta extends BaseMeta {
2018-01-23 08:00:08 +00:00
setup_meta() {
2018-01-25 10:05:24 +00:00
Object.assign(this, __webpack_require__(40));
2018-01-23 08:00:08 +00:00
}
}
2018-01-16 07:16:50 +00:00
2018-01-24 11:52:34 +00:00
class Account extends BaseDocument {
2018-01-23 08:00:08 +00:00
setup() {
this.add_handler('validate');
}
2018-01-23 13:18:02 +00:00
async validate() {
2018-01-23 08:00:08 +00:00
if (!this.account_type) {
2018-01-23 13:18:02 +00:00
if (this.parent_account) {
this.account_type = await frappe.db.get_value('Account', this.parent_account, 'account_type');
} else {
this.account_type = 'Asset';
}
2018-01-23 08:00:08 +00:00
}
}
}
2018-01-11 10:00:13 +00:00
2018-01-24 11:52:34 +00:00
module.exports = {
Document: Account,
Meta: AccountMeta
};
2018-01-16 07:16:50 +00:00
2018-01-11 10:00:13 +00:00
2018-01-23 08:00:08 +00:00
/***/ }),
2018-01-25 10:05:24 +00:00
/* 40 */
2018-01-23 08:00:08 +00:00
/***/ (function(module, exports) {
2018-01-23 12:26:11 +00:00
module.exports = {"name":"Account","doctype":"DocType","issingle":0,"keyword_fields":["name","account_type"],"fields":[{"fieldname":"name","label":"Account Name","fieldtype":"Data","reqd":1},{"fieldname":"parent_account","label":"Parent Account","fieldtype":"Link","options":"Account"},{"fieldname":"account_type","label":"Account Type","fieldtype":"Select","options":["Asset","Liability","Equity","Income","Expense"]}]}
2018-01-11 10:00:13 +00:00
2018-01-24 11:52:34 +00:00
/***/ }),
2018-01-25 10:05:24 +00:00
/* 41 */
/***/ (function(module, exports, __webpack_require__) {
const BaseMeta = __webpack_require__(3);
const BaseDocument = __webpack_require__(1);
class ItemMeta extends BaseMeta {
setup_meta() {
Object.assign(this, __webpack_require__(42));
}
}
class Item extends BaseDocument {
}
module.exports = {
Document: Item,
Meta: ItemMeta
};
/***/ }),
/* 42 */
/***/ (function(module, exports) {
module.exports = {"name":"Item","doctype":"DocType","issingle":0,"keyword_fields":["name","description"],"fields":[{"fieldname":"name","label":"Item Name","fieldtype":"Data","reqd":1},{"fieldname":"description","label":"Description","fieldtype":"Text"},{"fieldname":"unit","label":"Unit","fieldtype":"Select","options":["No","Kg","Gram","Hour","Day"]},{"fieldname":"rate","label":"Rate","fieldtype":"Currency"}]}
/***/ }),
/* 43 */
2018-01-24 11:52:34 +00:00
/***/ (function(module, exports, __webpack_require__) {
const BaseList = __webpack_require__(4);
const BaseForm = __webpack_require__(5);
class ToDoList extends BaseList {
2018-01-25 10:05:24 +00:00
get_fields() {
return ['name', 'subject', 'status'];
}
get_row_html(data) {
let symbol = data.status=="Closed" ? "✔" : "";
return `<a href="#edit/todo/${data.name}">${symbol} ${data.subject}</a>`;
}
2018-01-24 11:52:34 +00:00
}
module.exports = {
2018-01-25 10:05:24 +00:00
Form: BaseForm,
List: ToDoList
2018-01-24 11:52:34 +00:00
}
/***/ }),
2018-01-25 10:05:24 +00:00
/* 44 */
2018-01-24 11:52:34 +00:00
/***/ (function(module, exports, __webpack_require__) {
const BaseList = __webpack_require__(4);
const BaseForm = __webpack_require__(5);
class AccountList extends BaseList {
2018-01-25 10:05:24 +00:00
get_fields() {
return ['name', 'account_type'];
}
get_row_html(data) {
2018-01-24 11:52:34 +00:00
return `<a href="#edit/account/${data.name}">${data.name} (${data.account_type})</a>`;
2018-01-25 10:05:24 +00:00
}
2018-01-24 11:52:34 +00:00
}
class AccountForm extends BaseForm {
make() {
2018-01-25 10:05:24 +00:00
super.make();
2018-01-24 11:52:34 +00:00
2018-01-25 10:05:24 +00:00
// override controller event
2018-01-24 11:52:34 +00:00
this.controls['parent_account'].get_filters = (query) => {
return {
keywords: ["like", query],
name: ["!=", this.doc.name]
}
}
}
}
module.exports = {
2018-01-25 10:05:24 +00:00
Form: AccountForm,
List: AccountList
2018-01-24 11:52:34 +00:00
}
2018-01-08 12:29:49 +00:00
/***/ })
/******/ ]);
2018-01-25 10:05:24 +00:00
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIndlYnBhY2s6Ly8vd2VicGFjay9ib290c3RyYXAgMzU0MTliZWFmMmRhYTgwMjEyYzEiLCJ3ZWJwYWNrOi8vLy4uL2ZyYXBwZWpzL2luZGV4LmpzIiwid2VicGFjazovLy8uLi9mcmFwcGVqcy9tb2RlbC9kb2N1bWVudC5qcyIsIndlYnBhY2s6Ly8vLi4vZnJhcHBlanMvY2xpZW50L3ZpZXcvY29udHJvbHMvYmFzZS5qcyIsIndlYnBhY2s6Ly8vLi4vZnJhcHBlanMvbW9kZWwvbWV0YS5qcyIsIndlYnBhY2s6Ly8vLi4vZnJhcHBlanMvY2xpZW50L3ZpZXcvbGlzdC5qcyIsIndlYnBhY2s6Ly8vLi4vZnJhcHBlanMvY2xpZW50L3ZpZXcvZm9ybS5qcyIsIndlYnBhY2s6Ly8vLi4vZnJhcHBlanMvY2xpZW50L3ZpZXcvY29udHJvbHMvZmxvYXQuanMiLCJ3ZWJwYWNrOi8vLy4vaW5kZXguanMiLCJ3ZWJwYWNrOi8vLy4vc2Nzcy9tYWluLnNjc3M/NGJhYiIsIndlYnBhY2s6Ly8vLi9zY3NzL21haW4uc2NzcyIsIndlYnBhY2s6Ly8vLi9ub2RlX21vZHVsZXMvY3NzLWxvYWRlci9saWIvY3NzLWJhc2UuanMiLCJ3ZWJwYWNrOi8vLy4vbm9kZV9tb2R1bGVzL3N0eWxlLWxvYWRlci9saWIvYWRkU3R5bGVzLmpzIiwid2VicGFjazovLy8uL25vZGVfbW9kdWxlcy9zdHlsZS1sb2FkZXIvbGliL3VybHMuanMiLCJ3ZWJwYWNrOi8vLy4uL2ZyYXBwZWpzL2NsaWVudC9pbmRleC5qcyIsIndlYnBhY2s6Ly8vLi4vZnJhcHBlanMvY29tbW9uL2luZGV4LmpzIiwid2VicGFjazovLy8uLi9mcmFwcGVqcy91dGlscy9pbmRleC5qcyIsIndlYnBhY2s6Ly8vLi4vZnJhcHBlanMvdXRpbHMvbnVtYmVyX2Zvcm1hdC5qcyIsIndlYnBhY2s6Ly8vLi4vZnJhcHBlanMvbW9kZWwvaW5kZXguanMiLCJ3ZWJwYWNrOi8vLy4uL2ZyYXBwZWpzL3Nlc3Npb24uanMiLCJ3ZWJwYWNrOi8vLy4uL2ZyYXBwZWpzL2NvbW1vbi9lcnJvcnMuanMiLCJ3ZWJwYWNrOi8vLy4uL2ZyYXBwZWpzL2JhY2tlbmRzL3Jlc3RfY2xpZW50LmpzIiwid2VicGFjazovLy8uL25vZGVfbW9kdWxlcy9wYXRoLWJyb3dzZXJpZnkvaW5kZXguanMiLCJ3ZWJwYWNrOi8vLy4vbm9kZV9tb2R1bGVzL3Byb2Nlc3MvYnJvd3Nlci5qcyIsIndlYnBhY2s6Ly8vLi4vZnJhcHBlanMvY2xpZW50L3VpL2luZGV4LmpzIiwid2VicGFjazovLy8uLi9mcmFwcGVqcy9jbGllbnQvdWkvZHJvcGRvd24uanMiLCJ3ZWJwYWNrOi8vLy4uL2ZyYXBwZWpzL2NsaWVudC9kZXNrL2luZGV4LmpzIiwid2VicGFjazovLy8uLi9mcmFwcGVqcy9jbGllbnQvZGVzay9zZWFyY2guanMiLCJ3ZWJwYWNrOi8vLy4uL2ZyYXBwZWpzL2NvbW1vbi9yb3V0ZXIuanMiLCJ3ZWJwYWNrOi8vLy4uL2ZyYXBwZWpzL2NsaWVudC92aWV3L3BhZ2UuanMiLCJ3ZWJwYWNrOi8vLy4uL2ZyYXBwZWpzL2NsaWVudC92aWV3L2NvbnRyb2xzL2luZGV4LmpzIiwid2VicGFjazovLy8uLi9mcmFwcGVqcy9jbGllbnQvdmlldy9jb250cm9scy9kYXRhLmpzIiwid2VicGFjazovLy8uLi9mcmFwcGVqcy9jbGllbnQvdmlldy9jb250cm9scy90ZXh0LmpzIiwid2VicGFjazovLy8uLi9mcmFwcGVqcy9jbGllbnQvdmlldy9jb250cm9scy9zZWxlY3QuanMiLCJ3ZWJwYWNrOi8vLy4uL2ZyYXBwZWpzL2NsaWVudC92aWV3L2NvbnRyb2xzL2xpbmsuanMiLCJ3ZWJwYWNrOi8vLy4uL2ZyYXBwZWpzL25vZGVfbW9kdWxlcy9hd2Vzb21wbGV0ZS9hd2Vzb21wbGV0ZS5qcyIsIndlYnBhY2s6Ly8vLi4vZnJhcHBlanMvY2xpZW50L3ZpZXcvY29udHJvbHMvY3VycmVuY3kuanMiLCJ3ZWJwYWNrOi8vLy4uL2ZyYXBwZWpzL2NsaWVudC9kZXNrL25hdmJhci5qcyIsIndlYnBhY2s6Ly8vLi4vZnJhcHBlanMvbW9kZWxzL2RvY3R5cGUvdG9kby90b2RvLmpzIiwid2VicGFjazovLy8uLi9mcmFwcGVqcy9tb2RlbHMvZG9jdHlwZS90b2RvL3RvZG8uanNvbiIsIndlYnBhY2s6Ly8vLi9tb2RlbHMvZG9jdHlwZS9hY2NvdW50L2FjY291bnQuanMiLCJ3ZWJwYWNrOi8vLy4vbW9kZWxzL2RvY3R5cGUvYWNjb3VudC9hY2NvdW50Lmpzb24iLCJ3ZWJwYWNrOi8vLy4vbW9kZWxzL2RvY3R5cGUvaXRlbS9pdGVtLmpzIiwid2VicGFjazovLy8uL21vZGVscy9kb2N0eXBlL2l0ZW0vaXRlbS5qc29uIiwid2VicGFjazovLy8uLi9mcmFwcGVqcy9tb2RlbHMvZG9jdHlwZS90b2RvL3RvZG9fY2xpZW50LmpzIiwid2VicGFjazovLy8uL21vZGVscy9kb2N0eXBlL2FjY291bnQvYWNjb3VudF9jbGllbnQuanMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IjtBQUFBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOzs7QUFHQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxhQUFLO0FBQ0w7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxtQ0FBMkIsMEJBQTBCLEVBQUU7QUFDdkQseUNBQWlDLGVBQWU7QUFDaEQ7QUFDQTtBQUNBOztBQUVBO0FBQ0EsOERBQXNELCtEQUErRDs7QUFFckg7QUFDQTs7QUFFQTtBQUNBOzs7Ozs7O0FDN0RBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7O0FBRUw7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7O0FBRUw7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLOztBQUVMO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLOztBQUVMO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSzs7QUFFTDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSzs7QUFFTDtBQUNBO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0EsS0FBSzs7QUFFTDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsNENBQTRDLHlCQUF5QjtBQUNyRTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7O0FBRUw7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBLEtBQUs7O0FBRUw7QUFDQSx3Q0FBd0M