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 = {
2018-01-15 11:54:54 +00:00
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 = { } ;
2018-01-15 11:54:54 +00:00
this . docs = { } ;
this . flags = {
cache _docs : false
}
} ,
2018-01-08 12:29:49 +00:00
2018-01-15 11:54:54 +00:00
add _to _cache ( doc ) {
if ( ! this . flags . cache _docs ) return ;
2018-01-08 12:29:49 +00:00
2018-01-15 11:54:54 +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
2018-01-15 11:54:54 +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
2018-01-15 11:54:54 +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 ) ) ( ) ;
2018-01-15 11:54:54 +00:00
}
return this . meta _cache [ doctype ] ;
} ,
2018-01-24 11:52:34 +00:00
get _meta _class ( doctype ) {
2018-01-15 11:54:54 +00:00
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 ;
}
2018-01-15 11:54:54 +00:00
} ,
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 ) ;
2018-01-15 11:54:54 +00:00
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 ) ;
2018-01-15 11:54:54 +00:00
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 ;
}
} ,
2018-01-15 11:54:54 +00:00
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
2018-01-15 11:54:54 +00:00
close ( ) {
this . db . close ( ) ;
2018-01-08 12:29:49 +00:00
2018-01-15 11:54:54 +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 ) {
2018-01-15 11:54:54 +00:00
Object . assign ( this , docfield ) ;
2018-01-23 12:47:56 +00:00
this . form = form ;
2018-01-15 11:54:54 +00:00
if ( ! this . fieldname ) {
this . fieldname = frappe . slug ( this . label ) ;
}
2018-01-23 12:47:56 +00:00
this . parent = form . form ;
2018-01-15 11:54:54 +00:00
if ( this . setup ) {
this . setup ( ) ;
}
}
2018-01-10 10:50:57 +00:00
2018-01-15 11:54:54 +00:00
bind ( doc ) {
this . doc = doc ;
this . set _doc _value ( ) ;
}
2018-01-10 10:50:57 +00:00
2018-01-15 11:54:54 +00:00
refresh ( ) {
this . make ( ) ;
this . set _doc _value ( ) ;
}
2018-01-10 10:50:57 +00:00
2018-01-15 11:54:54 +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
2018-01-15 11:54:54 +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
2018-01-15 11:54:54 +00:00
make _form _group ( ) {
this . form _group = frappe . ui . add ( 'div' , 'form-group' , this . parent ) ;
}
2018-01-10 10:50:57 +00:00
2018-01-15 11:54:54 +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
2018-01-15 11:54:54 +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-15 11:54:54 +00:00
}
2018-01-10 10:50:57 +00:00
2018-01-15 11:54:54 +00:00
set _input _name ( ) {
this . input . setAttribute ( 'name' , this . fieldname ) ;
}
2018-01-10 10:50:57 +00:00
2018-01-15 11:54:54 +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
2018-01-15 11:54:54 +00:00
set _input _value ( value ) {
2018-01-25 10:05:24 +00:00
this . input . value = this . format ( value ) ;
}
format ( value ) {
2018-01-15 11:54:54 +00:00
if ( value === undefined || value === null ) {
value = '' ;
}
2018-01-25 10:05:24 +00:00
return value ;
2018-01-15 11:54:54 +00:00
}
2018-01-10 10:50:57 +00:00
2018-01-25 10:05:24 +00:00
async get _parsed _value ( ) {
2018-01-15 11:54:54 +00:00
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 ;
}
2018-01-15 11:54:54 +00:00
async parse ( value ) {
return value ;
}
2018-01-10 10:50:57 +00:00
2018-01-15 11:54:54 +00:00
async validate ( value ) {
return value ;
}
2018-01-10 10:50:57 +00:00
2018-01-15 11:54:54 +00:00
bind _change _event ( ) {
this . input . addEventListener ( 'change' , ( e ) => this . handle _change ( e ) ) ;
}
2018-01-10 10:50:57 +00:00
2018-01-15 11:54:54 +00:00
async handle _change ( e ) {
2018-01-25 10:05:24 +00:00
let value = await this . parse ( this . get _input _value ( ) ) ;
2018-01-15 11:54:54 +00:00
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-15 11:54:54 +00:00
}
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-15 11:54:54 +00:00
}
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-15 11:54:54 +00:00
}
2018-01-10 10:50:57 +00:00
2018-01-24 11:52:34 +00:00
get _fields ( ) {
return [ 'name' ] ;
2018-01-15 11:54:54 +00:00
}
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-15 11:54:54 +00:00
}
2018-01-24 11:52:34 +00:00
return filters ;
2018-01-15 11:54:54 +00:00
}
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-15 11:54:54 +00:00
}
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 < / b u t t o n >
< / d i v >
< / d i v >
< / d i v >
< div class = "col-md-3 col-3" >
< a href = "#new/${frappe.slug(this.doctype)}" class = "btn btn-outline-primary" >
New
< / a >
< / d i v >
< / d i v >
` ;
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-15 11:54:54 +00:00
}
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-15 11:54:54 +00:00
}
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-15 11:54:54 +00:00
}
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-15 11:54:54 +00:00
}
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-15 11:54:54 +00:00
}
2018-01-24 11:52:34 +00:00
return this . rows [ i ] ;
2018-01-15 11:54:54 +00:00
}
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-15 11:54:54 +00:00
}
}
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-15 11:54:54 +00:00
}
}
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-15 11:54:54 +00:00
}
2018-01-24 11:52:34 +00:00
this . make ( ) ;
2018-01-15 11:54:54 +00:00
}
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-15 11:54:54 +00:00
}
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-15 11:54:54 +00:00
}
}
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 < / b u t t o n >
< button class = "btn btn-primary btn-submit" > Save < / b u t t o n >
`
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-15 11:54:54 +00:00
}
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-15 11:54:54 +00:00
}
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-15 11:54:54 +00:00
}
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-15 11:54:54 +00:00
}
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-15 11:54:54 +00:00
}
}
2018-01-24 11:52:34 +00:00
refresh ( ) {
for ( let control of this . controls _list ) {
control . refresh ( ) ;
}
2018-01-15 11:54:54 +00:00
}
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 ( {
2018-01-15 11:54:54 +00:00
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
2018-01-15 11:54:54 +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 .
/ u r l \ s * \ ( = M a t c h o n t h e w o r d " u r l " w i t h a n y w h i t e s p a c e a f t e r i t a n d t h e n a p a r e n s
( = 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
/ g i = G e t a l l m a t c h e s , n o t t h e f i r s t . B e c a s e i n s e n s i t i v e .
* /
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 } ) {
2018-01-15 11:54:54 +00:00
window . frappe = frappe ;
frappe . init ( ) ;
common . init _libs ( frappe ) ;
2018-01-09 13:40:33 +00:00
2018-01-15 11:54:54 +00:00
frappe . fetch = window . fetch . bind ( ) ;
frappe . db = await new RESTClient ( { server : server } ) ;
2018-01-08 12:29:49 +00:00
2018-01-15 11:54:54 +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 = {
2018-01-15 11:54:54 +00:00
init _libs ( frappe ) {
Object . assign ( frappe , utils ) ;
frappe . model = model ;
2018-01-24 11:52:34 +00:00
frappe . BaseDocument = BaseDocument ;
frappe . BaseMeta = BaseMeta ;
2018-01-15 11:54:54 +00:00
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 , {
2018-01-15 11:54:54 +00:00
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-15 11:54:54 +00:00
} ) ;
}
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-15 11:54:54 +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 {
2018-01-15 11:54:54 +00:00
constructor ( user , user _key ) {
this . user = user || 'guest' ;
if ( this . user !== 'guest' ) {
this . login ( user _key ) ;
}
}
2018-01-08 12:29:49 +00:00
2018-01-15 11:54:54 +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
2018-01-15 11:54:54 +00:00
module . exports = class RESTClient {
constructor ( { server , protocol = 'http' } ) {
this . server = server ;
this . protocol = protocol ;
2018-01-10 10:50:57 +00:00
2018-01-15 11:54:54 +00:00
this . init _type _map ( ) ;
2018-01-10 10:50:57 +00:00
2018-01-15 11:54:54 +00:00
this . json _headers = {
'Accept' : 'application/json' ,
'Content-Type' : 'application/json'
}
}
2018-01-08 12:29:49 +00:00
2018-01-15 11:54:54 +00:00
connect ( ) {
2018-01-08 12:29:49 +00:00
2018-01-15 11:54:54 +00:00
}
2018-01-08 12:29:49 +00:00
2018-01-15 11:54:54 +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
2018-01-15 11:54:54 +00:00
return await response . json ( ) ;
}
2018-01-08 12:29:49 +00:00
2018-01-15 11:54:54 +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
2018-01-15 11:54:54 +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
2018-01-15 11:54:54 +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
2018-01-15 11:54:54 +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-15 11:54:54 +00:00
}
2018-01-08 12:29:49 +00:00
2018-01-15 11:54:54 +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
2018-01-15 11:54:54 +00:00
return await response . json ( ) ;
}
2018-01-08 12:29:49 +00:00
2018-01-15 11:54:54 +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
2018-01-15 11:54:54 +00:00
let response = await frappe . fetch ( url , {
method : 'DELETE' ,
headers : this . json _headers
} ) ;
2018-01-08 12:29:49 +00:00
2018-01-15 11:54:54 +00:00
return await response . json ( ) ;
}
2018-01-08 12:29:49 +00:00
2018-01-15 11:54:54 +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 ;
}
2018-01-15 11:54:54 +00:00
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
2018-01-15 11:54:54 +00:00
close ( ) {
2018-01-08 12:29:49 +00:00
2018-01-15 11:54:54 +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 = {
2018-01-15 11:54:54 +00:00
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
2018-01-15 11:54:54 +00:00
remove ( element ) {
element . parentNode . removeChild ( element ) ;
} ,
2018-01-10 10:50:57 +00:00
2018-01-15 11:54:54 +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
2018-01-15 11:54:54 +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
2018-01-15 11:54:54 +00:00
toggle ( element , default _display = '' ) {
element . style . display = element . style . display === 'none' ? default _display : 'none' ;
} ,
2018-01-11 10:00:13 +00:00
2018-01-15 11:54:54 +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 ) ;
2018-01-15 11:54:54 +00:00
class Dropdown {
constructor ( { parent , label , btn _class = 'btn-secondary' , items = [ ] } ) {
Object . assign ( this , arguments [ 0 ] ) ;
2018-01-09 13:40:33 +00:00
2018-01-15 11:54:54 +00:00
this . dropdown _items = [ ] ;
this . setup _background _click ( ) ;
this . make ( ) ;
2018-01-09 13:40:33 +00:00
2018-01-15 11:54:54 +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 ) ;
2018-01-15 11:54:54 +00:00
item . textContent = label ;
2018-01-16 07:16:50 +00:00
item . setAttribute ( 'type' , 'button' ) ;
2018-01-15 11:54:54 +00:00
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 ) ;
2018-01-15 11:54:54 +00:00
this . toggle ( ) ;
} ) ;
} else {
item . addEventListener ( 'click' , async ( ) => {
await action ( ) ;
this . toggle ( ) ;
} ) ;
}
this . dropdown _items . push ( item ) ;
}
2018-01-09 13:40:33 +00:00
2018-01-15 11:54:54 +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
}
2018-01-15 11:54:54 +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
2018-01-15 11:54:54 +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
2018-01-15 11:54:54 +00:00
this . sidebar _items = [ ] ;
this . pages = {
lists : { } ,
forms : { }
} ;
2018-01-09 13:40:33 +00:00
2018-01-15 11:54:54 +00:00
this . init _routes ( ) ;
2018-01-09 13:40:33 +00:00
2018-01-15 11:54:54 +00:00
// this.search = new Search(this.nav);
}
2018-01-09 13:40:33 +00:00
2018-01-15 11:54:54 +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 : '' ) ;
} )
2018-01-15 11:54:54 +00:00
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
2018-01-15 11:54:54 +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
2018-01-15 11:54:54 +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-15 11:54:54 +00:00
} ) ;
2018-01-09 13:40:33 +00:00
2018-01-15 11:54:54 +00:00
}
2018-01-09 13:40:33 +00:00
2018-01-15 11:54:54 +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 ) ) ( {
2018-01-15 11:54:54 +00:00
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
2018-01-15 11:54:54 +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 ) ) ( {
2018-01-15 11:54:54 +00:00
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 ` ] ;
}
2018-01-15 11:54:54 +00:00
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 ) ;
2018-01-15 11:54:54 +00:00
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-15 11:54:54 +00:00
/***/ } ) ,
2018-01-25 10:05:24 +00:00
/* 27 */
2018-01-15 11:54:54 +00:00
/***/ ( function ( module , exports , _ _webpack _require _ _ ) {
2018-01-08 12:29:49 +00:00
2018-01-15 11:54:54 +00:00
const frappe = _ _webpack _require _ _ ( 0 ) ;
2018-01-08 12:29:49 +00:00
2018-01-15 11:54:54 +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
2018-01-15 11:54:54 +00:00
add ( route , handler ) {
let page = { handler : handler , route : route } ;
2018-01-08 12:29:49 +00:00
2018-01-15 11:54:54 +00:00
// '/todo/:name/:place'.match(/:([^/]+)/g);
page . param _keys = route . match ( /:([^/]+)/g ) ;
2018-01-11 10:00:13 +00:00
2018-01-15 11:54:54 +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 , "\/([^/]+)" ) ;
2018-01-15 11:54:54 +00:00
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
2018-01-15 11:54:54 +00:00
sort _dynamic _routes ( ) {
2018-01-16 07:16:50 +00:00
// routes with more parts first
2018-01-15 11:54:54 +00:00
this . dynamic _routes = this . dynamic _routes . sort ( ( a , b ) => {
2018-01-16 07:16:50 +00:00
if ( a . depth < b . depth ) {
2018-01-15 11:54:54 +00:00
return 1 ;
2018-01-16 07:16:50 +00:00
} else if ( a . depth > b . depth ) {
2018-01-15 11:54:54 +00:00
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-15 11:54:54 +00:00
}
} )
}
2018-01-08 12:29:49 +00:00
2018-01-15 11:54:54 +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-15 11:54:54 +00:00
} ) ;
}
2018-01-24 11:52:34 +00:00
set _route ( ... parts ) {
const route = parts . join ( '/' ) ;
window . location . hash = route ;
2018-01-15 11:54:54 +00:00
}
2018-01-24 11:52:34 +00:00
async show ( route ) {
if ( route && route [ 0 ] === '#' ) {
route = route . substr ( 1 ) ;
}
2018-01-15 11:54:54 +00:00
2018-01-24 11:52:34 +00:00
if ( ! route ) {
route = this . default ;
2018-01-15 11:54:54 +00:00
}
2018-01-24 11:52:34 +00:00
let page = this . match ( route ) ;
2018-01-15 11:54:54 +00:00
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-15 11:54:54 +00:00
}
2018-01-24 11:52:34 +00:00
} else {
await this . match ( 'not-found' ) . handler ( { route : route } ) ;
2018-01-15 11:54:54 +00:00
}
}
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-15 11:54:54 +00:00
}
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 ;
2018-01-15 11:54:54 +00:00
this . make ( ) ;
}
2018-01-08 12:29:49 +00:00
2018-01-15 11:54:54 +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-15 11:54:54 +00:00
}
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-15 11:54:54 +00:00
}
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-15 11:54:54 +00:00
}
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-15 11:54:54 +00:00
}
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-15 11:54:54 +00:00
}
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-15 11:54:54 +00:00
}
}
}
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 = {
2018-01-15 11:54:54 +00:00
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 {
2018-01-15 11:54:54 +00:00
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 {
2018-01-15 11:54:54 +00:00
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 {
2018-01-15 11:54:54 +00:00
make _input ( ) {
this . input = frappe . ui . add ( 'select' , 'form-control' , this . form _group ) ;
2018-01-09 13:40:33 +00:00
2018-01-15 11:54:54 +00:00
let options = this . options ;
if ( typeof options === 'string' ) {
options = options . split ( '\n' ) ;
}
2018-01-09 13:40:33 +00:00
2018-01-15 11:54:54 +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 weren ’ t enough autocomplete scripts in the world ? Because I ’ m 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 {
2018-01-15 11:54:54 +00:00
setup _meta ( ) {
2018-01-25 10:05:24 +00:00
Object . assign ( this , _ _webpack _require _ _ ( 38 ) ) ;
2018-01-15 11:54:54 +00:00
}
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 {
2018-01-15 11:54:54 +00:00
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 ) {
2018-01-15 11:54:54 +00:00
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-15 11:54:54 +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