From 234566b6af8e0d17408280d1662b300b64b75815 Mon Sep 17 00:00:00 2001 From: Juan Ferrer Toribio Date: Wed, 19 Apr 2017 08:16:37 +0200 Subject: [PATCH] Backup --- forms/cms/home/home.js | 2 + forms/ecomerce/catalog/catalog.js | 192 ++++++++++++++---------- forms/ecomerce/catalog/style.css | 5 - forms/ecomerce/catalog/ui.xml | 221 +++++++++++++--------------- forms/ecomerce/checkout/checkout.js | 10 +- forms/ecomerce/confirm/ui.xml | 2 +- js/db/connection.js | 7 + js/db/form.js | 4 +- js/db/model.js | 82 ++++++----- js/db/query.js | 2 +- js/hedera/app.js | 30 +++- js/hedera/form.js | 32 ++-- js/hedera/gui.js | 81 ++++++---- js/hedera/login.js | 39 +++-- js/hedera/report.html | 18 --- js/htk/assistant.js | 2 +- js/htk/column.js | 2 +- js/htk/column/button.js | 2 +- js/htk/dialog.js | 4 +- js/htk/field.js | 146 +++++++++--------- js/htk/field/button.js | 2 +- js/htk/field/combo.js | 8 +- js/htk/field/radio.js | 2 +- js/htk/field/table.js | 2 +- js/htk/image-editor.js | 4 +- js/htk/popup.js | 2 +- js/htk/repeater.js | 2 +- js/sql/field.js | 8 +- js/sql/filter-item.js | 69 ++++++++- js/sql/filter.js | 56 ++++--- js/sql/list.js | 2 +- js/sql/object.js | 1 + js/sql/operation.js | 10 +- js/sql/search-tags.js | 2 +- js/sql/string.js | 8 +- js/sql/value.js | 98 ++++++------ js/vn/builder.js | 5 +- js/vn/hash.js | 11 +- js/vn/json-connection.js | 10 +- js/vn/json-model.js | 90 +++++++++++ js/vn/lot-iface.js | 11 +- js/vn/lot-query.js | 125 ++++++++++++++++ js/vn/lot.js | 6 +- js/vn/model-iface.js | 157 ++++++++++++++++++++ js/vn/model-proxy.js | 86 +++++++++++ js/vn/object.js | 74 ++++++---- js/vn/param-iface.js | 140 ++++++++++++++++++ js/vn/param.js | 156 ++++++-------------- js/vn/value.js | 68 +++++++-- js/vn/vn.js | 5 + rest/edi/sql/supplier.sql | 1 + 51 files changed, 1435 insertions(+), 669 deletions(-) delete mode 100755 js/hedera/report.html create mode 100644 js/vn/json-model.js create mode 100644 js/vn/lot-query.js create mode 100644 js/vn/model-iface.js create mode 100644 js/vn/model-proxy.js create mode 100644 js/vn/param-iface.js diff --git a/forms/cms/home/home.js b/forms/cms/home/home.js index 4a672b3d..1337ae3a 100644 --- a/forms/cms/home/home.js +++ b/forms/cms/home/home.js @@ -1,3 +1,4 @@ +(function () { Hedera.Home = new Class ({ @@ -9,3 +10,4 @@ Hedera.Home = new Class } }); +})(); diff --git a/forms/ecomerce/catalog/catalog.js b/forms/ecomerce/catalog/catalog.js index 432a9203..d8894d72 100644 --- a/forms/ecomerce/catalog/catalog.js +++ b/forms/ecomerce/catalog/catalog.js @@ -1,3 +1,9 @@ +(function () { + +var View = { + LIST: 0, + GRID: 1 +}; Hedera.Catalog = new Class ({ @@ -32,12 +38,14 @@ Hedera.Catalog = new Class { document.body.appendChild (this.$('right-panel')); - this.$('items-model').setInfo ('a', 'Articles', 'vn2008', ['item_id']); + this.$('items').setInfo ('a', 'Articles', 'vn2008', ['item_id']); if (localStorage.getItem ('hederaView')) this.setView (parseInt (localStorage.getItem ('hederaView'))); else - this.setView (Hedera.Catalog.View.GRID); + this.setView (View.GRID); + + this.hash.on ('change', this.onHashChange, this); } ,deactivate: function () @@ -45,17 +53,18 @@ Hedera.Catalog = new Class this.hideMenu (); this.gui.$('top-bar').style.backgroundColor = ''; Vn.Node.remove (this.$('right-panel')); + this.hash.disconnect ('change', this.onHashChange, this); } ,setView: function (view) { - if (view === Hedera.Catalog.View.GRID) + if (view === View.GRID) { this.$('view-button').setProperties ({ icon: 'view-list', tip: _('List view') }); - this.view = Hedera.Catalog.View.GRID; + this.view = View.GRID; var className = 'grid-view'; } else @@ -64,7 +73,7 @@ Hedera.Catalog = new Class icon: 'view-grid', tip: _('Grid view') }); - this.view = Hedera.Catalog.View.LIST; + this.view = View.LIST; var className = 'list-view'; } @@ -75,8 +84,8 @@ Hedera.Catalog = new Class ,onSwitchViewClick: function () { - this.setView (this.view === Hedera.Catalog.View.LIST ? - Hedera.Catalog.View.GRID : Hedera.Catalog.View.LIST); + this.setView (this.view === View.LIST ? + View.GRID : View.LIST); } ,onBasketReady: function (form) @@ -103,23 +112,44 @@ Hedera.Catalog = new Class Db.Model.SortWay.ASC : Db.Model.SortWay.DESC; if (sortField) - this.$('items-model').sortByName (sortField, sortWay); + this.$('items').sortByName (sortField, sortWay); this.hideMenu (); } - ,onFilterChange: function (param, newValue) + ,shouldRefresh: function () { - if (newValue) - this.hideMenu (); + var params = this.hash.params; + + if (params.search) + return true; + + var refresh = params.realm && ( + params.type || + params.color || + params.origin || + params.category || + params.producer + ); + + return refresh; + } + + ,onHashChange: function () + { + if (!this.shouldRefresh ()) + return; + + this.$('items').refresh (); + this.hideMenu (); } ,realmRenderer: function (builder, form) { var link = builder.$('link'); link.href = this.hash.make ({ - 'form': this.hash.get ('form'), - 'realm': form.get ('id') + form: this.hash.get ('form'), + realm: form.get ('id') }); var img = builder.$('image'); @@ -147,36 +177,25 @@ Hedera.Catalog = new Class ,onTypeChange: function (param, newValue) { - this.onFilterChange (param, newValue); this.refreshTitle (); this.refreshFilter (undefined, newValue); } ,refreshFilter: function (realm, type) { - var batch = this.$('filter-batch'); - batch.block (); - this.$('realm-value').value = realm; - this.$('type-value').value = type; - this.$('search').value = undefined; - this.$('color').value = undefined; - this.$('origin').value = undefined; - this.$('category').value = undefined; - this.$('producer').value = undefined; - batch.unblock (); - batch.changed (); + this.hash.params = { + form: this.hash.get ('form'), + realm: realm, + type: type + }; } ,refreshTitleColor: function () { - var realms = this.$('realms-model'); - - if (!realms.ready) - return; - + var realms = this.$('realms'); + var realm = this.hash.get ('realm'); var color = null; - var realm = this.$('realm').value; - + if (realm) { var row = realms.search ('id', realm); @@ -190,14 +209,10 @@ Hedera.Catalog = new Class ,refreshTitle: function () { - var types = this.$('types-model'); - - if (!types.ready) - return; - + var types = this.$('types'); + var type = this.hash.get ('type'); var title = _('Catalog'); - var type = this.$('type').value; - + if (type) { var row = types.search ('tipo_id', type); @@ -251,7 +266,7 @@ Hedera.Catalog = new Class if (this.isGuest ()) return; - this.hash.setAll ({'form': 'ecomerce/basket'}); + this.hash.params = {form: 'ecomerce/basket'}; } ,onConfigureClick: function () @@ -259,7 +274,7 @@ Hedera.Catalog = new Class if (this.isGuest ()) return; - this.hash.setAll ({'form': 'ecomerce/checkout'}); + this.hash.params = {form: 'ecomerce/checkout'}; } ,onAddItemClick: function (button, form) @@ -273,26 +288,22 @@ Hedera.Catalog = new Class this.$('card-popup').show (button.node); } - ,onAddLotClick: function (column, value, row) + ,onAddLotClick: function (column, value, rowIndex) { - var model = this.$('item-lots'); - var grouping = model.get (row, 'grouping'); - var warehouse = model.get (row, 'warehouse_id'); - var available = model.get (row, 'available'); - - var lotAmount = this.items[warehouse]; + var row = this.$('item-lots').getObject (rowIndex); + var lotAmount = this.items[row.warehouse]; if (lotAmount === undefined) lotAmount = 0; - if (lotAmount < available) + if (lotAmount < row.available) { - var newAmount = lotAmount + grouping; + var newAmount = lotAmount + row.grouping; - if (newAmount > available) - newAmount = available; + if (newAmount > row.available) + newAmount = row.available; - this.items[warehouse] = newAmount; + this.items[row.warehouse] = newAmount; this.$('amount').value += newAmount - lotAmount; } else @@ -302,21 +313,22 @@ Hedera.Catalog = new Class ,onConfirmClick: function () { var sql = ''; - var batch = new Sql.Batch (); - var query = new Sql.String ({query: 'CALL basket_item_add (#warehouse, #item, #amount);'}); + var query = 'CALL basket_item_add (#warehouse, #item, #amount);'; var amountSum = 0; for (var warehouse in this.items) { var amount = this.items[warehouse]; amountSum += amount; - - batch.addValue ('warehouse', warehouse); - batch.addValue ('item', this.$('card-item').value); - batch.addValue ('amount', amount); - sql += query.render (batch); + + var params = { + item: this.$('card-item').value, + warehouse: warehouse, + amount: amount + }; + sql += this.conn.render (query, params); } - + if (amountSum > 0) { this.conn.execQuery (sql); @@ -348,19 +360,10 @@ Hedera.Catalog = new Class } }); -Hedera.Catalog.extend -({ - View: { - LIST: 0, - GRID: 1 - } -}); - Vn.Filter = new Class ({ Extends: Htk.Field ,Tag: 'vn-filter' - ,Child: 'model' ,Properties: { model: @@ -368,9 +371,9 @@ Vn.Filter = new Class type: Db.Model ,set: function (x) { - x.batch = this._batch; this._model = x; this._select.model = x; + this._refreshLot (); } ,get: function () { @@ -396,13 +399,40 @@ Vn.Filter = new Class ,set: function (x) { this._filter = x; - this._batch.addObject ('filter', x); + this._modelLot.assign ({filter: x}); + this._refreshLot (); } ,get: function () { return this._filter; } }, + lot: + { + type: Vn.LotIface + ,set: function (x) + { + this._modelLot.source = x; + this._setLot (x); + } + ,get: function () + { + return this._lot; + } + }, + name: + { + type: String + ,set: function (x) + { + this._modelLot.fields = [x]; + this._onLotChange (); + } + ,get: function () + { + return this._name; + } + } } ,_valueColumnIndex: 0 @@ -422,9 +452,22 @@ Vn.Filter = new Class this._ul = this.createElement ('ul'); this.node.appendChild (this._ul); - this._batch = new Sql.Batch (); + this._modelLot = new Vn.LotQuery ({ + type: Vn.LotQuery.Type.EXCLUDE + }); this.parent (props); } + + ,_refreshLot: function () + { + if (!this._model) + return; + + if (this._filter) + this._model.lot = this._modelLot; + else + this._model.lot = null; + } ,_onMouseDown: function () { @@ -465,9 +508,7 @@ Vn.Filter = new Class ,_changeValue: function (newValue) { - this._batch.block (); this.value = newValue; - this._batch.unblock (); } ,_onTimeout: function () @@ -535,3 +576,4 @@ Vn.Filter = new Class } }); +})(); diff --git a/forms/ecomerce/catalog/style.css b/forms/ecomerce/catalog/style.css index 4a0e7a65..b44fc3bf 100644 --- a/forms/ecomerce/catalog/style.css +++ b/forms/ecomerce/catalog/style.css @@ -60,9 +60,6 @@ .right-panel .realm-msg { margin-top: 1em; -/* box-shadow: 0 0 .3em rgba(1, 1, 1, .5); - border-radius: 50%; - overflow: hidden;*/ } .right-panel .realm-msg > h1 { @@ -70,8 +67,6 @@ text-align: center; padding: 2.5em 0; color: #777; -/* background-color: #009688; - color: white;*/ } .right-panel h2 { diff --git a/forms/ecomerce/catalog/ui.xml b/forms/ecomerce/catalog/ui.xml index 0b2a7cf0..b783c1ac 100755 --- a/forms/ecomerce/catalog/ui.xml +++ b/forms/ecomerce/catalog/ui.xml @@ -1,45 +1,62 @@ - - - - - - - - - + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + CREATE TEMPORARY TABLE tmp.bionic_calc + (INDEX (item_id)) + ENGINE = MEMORY + SELECT a.Id_Article item_id + FROM vn2008.Articles a + JOIN vn2008.Tipos t ON t.tipo_id = a.tipo_id + WHERE #filter; + CALL bionic_calc (); + SELECT a.Id_Article item_id, a.description, b.available, b.price, + b.producer, a.Foto, a.Article, a.Categoria, a.Medida, + IF(a.Tallos > 1, a.Tallos, NULL) Tallos, c.str color + FROM tmp.bionic_item b + JOIN vn2008.Articles a ON a.Id_Article = b.item_id + LEFT JOIN vn2008.producer p ON p.producer_id = a.producer_id + LEFT JOIN vn_locale.color_view c ON c.color_id = a.Color + LEFT JOIN vn_locale.origin_view o ON o.origin_id = a.id_origen + WHERE b.available > 0 + ORDER BY a.Article, a.Medida + LIMIT 40; + SELECT o.id, o.date_send, ag.description agency, v.code method @@ -53,35 +70,7 @@ FROM basket_item GROUP BY warehouse_id - - CREATE TEMPORARY TABLE tmp.bionic_calc - (INDEX (item_id)) - ENGINE=MEMORY - SELECT a.Id_Article item_id FROM vn2008.Articles a - JOIN vn2008.Tipos t ON t.tipo_id = a.tipo_id - WHERE #filter; - CALL bionic_calc (); - SELECT a.Id_Article item_id, a.description, b.available, b.price, - b.producer, a.Foto, a.Article, a.Categoria, a.Medida, - IF(a.Tallos > 1, a.Tallos, NULL) Tallos, c.str color - FROM tmp.bionic_item b - JOIN vn2008.Articles a ON a.Id_Article = b.item_id - LEFT JOIN vn2008.producer p ON p.producer_id = a.producer_id - LEFT JOIN vn_locale.color_view c ON c.color_id = a.Color - LEFT JOIN vn_locale.origin_view o ON o.origin_id = a.id_origen - WHERE b.available > 0 - ORDER BY a.Article, a.Medida - LIMIT 400; - - - - - - - + + lot="card-lot" + on-status-changed-after="onStatusChange"> CALL bionic_from_item (#item); SELECT p.warehouse_id, w.name warehouse, p.grouping, p.price, p.rate, l.available FROM tmp.bionic_lot l @@ -122,15 +111,15 @@ tip="_Switch view" on-click="onSwitchViewClick"/> + lot="hash" + name="search"/>
-
+ model="items">
-
@@ -193,12 +181,10 @@
SELECT r.id, l.str name, r.color @@ -222,12 +208,14 @@

Filter by

+ lot="hash" + name="type" + placeholder="_Family"> CALL item_available (); @@ -236,19 +224,16 @@ JOIN vn2008.Articles a ON a.tipo_id = t.tipo_id LEFT JOIN vn_locale.family_view l ON l.family_id = t.tipo_id JOIN tmp.item_available i ON i.item_id = a.Id_Article - WHERE #filter + WHERE t.reino_id = #realm ORDER BY name - - - - - - + filter="filter"> CALL item_available (); SELECT DISTINCT c.Id_Tinta, l.str name @@ -260,18 +245,12 @@ WHERE #filter ORDER BY name - - - - - - - - + filter="filter"> CALL item_available (); SELECT DISTINCT p.producer_id, p.name @@ -282,18 +261,12 @@ WHERE #filter ORDER BY name - - - - - - - - + filter="filter"> CALL item_available (); SELECT DISTINCT o.id, l.str name, o.Abreviatura @@ -305,18 +278,12 @@ WHERE #filter ORDER BY name - - - - - - - - + filter="filter"> CALL item_available (); SELECT DISTINCT a.Categoria, a.Categoria category @@ -326,14 +293,6 @@ WHERE #filter ORDER BY a.Categoria - - - - - - - -
@@ -444,4 +403,22 @@
- + + \ No newline at end of file diff --git a/forms/ecomerce/checkout/checkout.js b/forms/ecomerce/checkout/checkout.js index f87cea6b..ecd26f11 100644 --- a/forms/ecomerce/checkout/checkout.js +++ b/forms/ecomerce/checkout/checkout.js @@ -3,12 +3,16 @@ Hedera.Checkout = new Class ({ Extends: Hedera.Form + ,initialize: function (props) + { + this.today = new Date (); + this.today.setHours (0, 0, 0, 0); + this.parent (props); + } + ,activate: function () { this.autoStepLocked = true; - - this.today = new Date (); - this.today.setHours (0,0,0,0); } ,onValuesReady: function () diff --git a/forms/ecomerce/confirm/ui.xml b/forms/ecomerce/confirm/ui.xml index f1623a41..8229e343 100755 --- a/forms/ecomerce/confirm/ui.xml +++ b/forms/ecomerce/confirm/ui.xml @@ -184,7 +184,7 @@

- + diff --git a/js/db/connection.js b/js/db/connection.js index 0e61da41..141ed7ff 100644 --- a/js/db/connection.js +++ b/js/db/connection.js @@ -75,6 +75,13 @@ Connection.implement this.execSql (this.renderQuery (query, params), callback); } + /** + * Renders a query. + * + * @param {String} query The SQL statement + * @param {Object} params The statement parameters + * @return {String} The rendered statement + */ ,renderQuery: function (query, params) { return new Sql.String ({query: query}).render (params); diff --git a/js/db/form.js b/js/db/form.js index 6947bf96..b3b0968d 100644 --- a/js/db/form.js +++ b/js/db/form.js @@ -106,13 +106,13 @@ module.exports = new Class this.lastRow = this._row; this._ready = ready; - this.signalEmit ('status-changed'); + this.emit ('status-changed'); if (this._row == -1) this.row = this.lastRow; if (ready) - this.signalEmit ('ready'); + this.emit ('ready'); this.changed (); } diff --git a/js/db/model.js b/js/db/model.js index 4d4acdcd..779d0391 100644 --- a/js/db/model.js +++ b/js/db/model.js @@ -10,8 +10,8 @@ var Connection = require ('./connection'); * otherwise updates are not allowed on that table/column. If two tables or * columns have the same name, an alias should be used to make it updatable. */ -var Model = new Class (); -module.exports = Model; +var Klass = new Class (); +module.exports = Klass; var Status = { @@ -40,7 +40,7 @@ var SortWay = ,DESC : 2 }; -Model.extend +Klass.extend ({ Status: Status ,Mode: Mode @@ -48,7 +48,7 @@ Model.extend ,SortWay: SortWay }); -Model.implement +Klass.implement ({ Extends: Vn.Object ,Tag: 'db-model' @@ -85,22 +85,6 @@ Model.implement return this._resultIndex; } }, - /** - * The batch used to execute the statement. - */ - batch: - { - type: Sql.Batch - ,set: function (x) - { - this.link ({_batch: x}, {'changed': this._autoLoad}); - this._autoLoad (); - } - ,get: function () - { - return this._batch; - } - }, /** * The lot used to execute the statement. */ @@ -241,10 +225,10 @@ Model.implement ,_conn: null ,_resultIndex: 0 - ,_batch: null ,_lot: null ,_stmt: null ,_status: Status.CLEAN + ,result: null ,data: null ,tables: null ,columns: null @@ -289,6 +273,10 @@ Model.implement return null; var lotParams = this._lot ? this._lot.params : {}; + + if (lotParams == null) + lotParams = {}; + var params = {}; for (var i = 0; i < ids.length; i++) @@ -371,6 +359,7 @@ Model.implement throw e; } + this.result = dataResult; this.data = dataResult.data; this.tables = dataResult.tables; this.columns = dataResult.columns; @@ -412,6 +401,7 @@ Model.implement ,_cleanData: function () { + this.result = null; this.data = null; this.tables = null; this.columns = null; @@ -427,7 +417,7 @@ Model.implement this._updatable = this._mainTable !== null && this._requestedUpdatable; if (oldValue != this._updatable) - this.signalEmit ('updatable-changed'); + this.emit ('updatable-changed'); } ,_refreshMainTable: function () @@ -591,7 +581,7 @@ Model.implement } /** - * Gets a value from the model using the column index. + * Gets a value using the column index. * * @param {number} rowIndex The row index * @param {number} column The column index @@ -605,6 +595,20 @@ Model.implement return undefined; } + /** + * Gets a row as an object using the column index. + * + * @param {number} rowIndex The row index + * @return {Object} The row as an object + */ + ,getObject: function (rowIndex) + { + if (!this.checkRowExists (rowIndex)) + return null; + + return this.result.getObject (rowIndex); + } + /** * Updates a value on the model using the column index. * @@ -654,9 +658,9 @@ Model.implement && op.oldValues[col] === undefined) op.oldValues[col] = row[col]; - this.signalEmit ('row-updated-before', rowIndex); + this.emit ('row-updated-before', rowIndex); row[col] = value; - this.signalEmit ('row-updated', rowIndex, [col]); + this.emit ('row-updated', rowIndex, [col]); if (this.mode == Mode.ON_CHANGE && !(op.type & Operation.INSERT)) @@ -679,14 +683,14 @@ Model.implement if (!this._requestedMainTable) { - this.signalEmit ('row-deleted-before', rowIndex); + this.emit ('row-deleted-before', rowIndex); this.data.splice (rowIndex, 1); - this.signalEmit ('row-deleted', rowIndex); + this.emit ('row-deleted', rowIndex); this._refreshRowIndexes (rowIndex); } else { - this.signalEmit ('row-updated-before', rowIndex); + this.emit ('row-updated-before', rowIndex); if (!op.oldValues) op.oldValues = []; @@ -703,7 +707,7 @@ Model.implement updatedCols.push (i); } - this.signalEmit ('row-updated', rowIndex, updatedCols); + this.emit ('row-updated', rowIndex, updatedCols); } if (this.mode === Mode.ON_CHANGE) @@ -735,7 +739,7 @@ Model.implement var op = this._createOperation (rowIndex); op.type |= Operation.INSERT; - this.signalEmit ('row-inserted', rowIndex); + this.emit ('row-inserted', rowIndex); return rowIndex; } @@ -749,7 +753,7 @@ Model.implement if (ops.length === 0) { - this.signalEmit ('operations-done'); + this.emit ('operations-done'); return; } @@ -912,7 +916,7 @@ Model.implement } else if (op.type & (Operation.INSERT | Operation.UPDATE)) { - this.signalEmit ('row-updated-before', row.index); + this.emit ('row-updated-before', row.index); var updatedCols = []; var cols = this.columns; @@ -946,14 +950,14 @@ Model.implement } } - this.signalEmit ('row-updated', row.index, updatedCols); + this.emit ('row-updated', row.index, updatedCols); } } resultSet.fetchResult (); // if (isOperation) - this.signalEmit ('operations-done'); + this.emit ('operations-done'); } /** @@ -970,11 +974,11 @@ Model.implement && !(op.type & Operation.INSERT)) { this.data.splice (row.index, 0, row); - this.signalEmit ('row-inserted', row.index); + this.emit ('row-inserted', row.index); } else if (op.type & Operation.UPDATE) { - this.signalEmit ('row-updated-before', row.index); + this.emit ('row-updated-before', row.index); var updatedCols = []; var cols = this.columns; @@ -986,7 +990,7 @@ Model.implement updatedCols.push (i); } - this.signalEmit ('row-updated', row.index, updatedCols); + this.emit ('row-updated', row.index, updatedCols); } } @@ -1215,8 +1219,8 @@ Model.implement ,_setStatus: function (status) { this._status = status; - this.signalEmit ('status-changed', status); - this.signalEmit ('status-changed-after', status); + this.emit ('status-changed', status); + this.emit ('status-changed-after', status); } ,_createTarget: function (tableIndex) diff --git a/js/db/query.js b/js/db/query.js index c8468131..c9c7e7c3 100644 --- a/js/db/query.js +++ b/js/db/query.js @@ -95,7 +95,7 @@ module.exports = new Class ,onQueryDone: function (resultSet) { - this.signalEmit ('ready', resultSet); + this.emit ('ready', resultSet); } ,onChange: function () diff --git a/js/hedera/app.js b/js/hedera/app.js index 51cea148..92db4264 100644 --- a/js/hedera/app.js +++ b/js/hedera/app.js @@ -2,11 +2,17 @@ var Login = require ('./login'); var Gui = require ('./gui'); +/** + * The main application object. + */ module.exports = new Class ({ Extends: Vn.Object, Properties: { + /** + * The main connection object. + */ conn: { type: Db.Connection @@ -15,6 +21,28 @@ module.exports = new Class return this._conn; } } + /** + * The main screen component. + */ + ,gui: + { + type: Gui + ,get: function () + { + return this._gui; + } + } + /** + * The login component. + */ + ,login: + { + type: Login + ,get: function () + { + return this._login; + } + } } ,initialize: function () @@ -66,7 +94,7 @@ module.exports = new Class this.unref (); } - ,_onWindowError: function (message, file, line, col, err) + ,_onWindowError: function (message, file, line) { var error = new Error (message); error.fileName = file; diff --git a/js/hedera/form.js b/js/hedera/form.js index b09a423f..d4098f8b 100644 --- a/js/hedera/form.js +++ b/js/hedera/form.js @@ -1,19 +1,33 @@ +var Gui = require ('./gui'); + module.exports = new Class ({ Extends: Htk.Component + ,Properties: { + gui: + { + type: Gui + ,set: function (x) + { + this._gui = x; + this.conn = x.conn; + this.hash = x.hash; + } + ,get: function () + { + return this._gui; + } + }, + formInfo: + { + type: Object, + value: null + } + } ,isOpen: false ,uiLoaded: false - - ,initialize: function (gui, formInfo) - { - this.gui = gui; - this.conn = gui.conn; - this.hash = gui.hash; - this.formInfo = formInfo; - this.parent (); - } ,loadUi: function () { diff --git a/js/hedera/gui.js b/js/hedera/gui.js index b5f7ed3b..2e37b310 100644 --- a/js/hedera/gui.js +++ b/js/hedera/gui.js @@ -1,13 +1,22 @@ -var Module = require ('./module'); -var Css = require ('./gui.css'); var Tpl = require ('./gui.xml'); +var Module = require ('./module'); +var Form = require ('./form'); +require ('./gui.css'); + +/** + * The main screen component. It has a left menu, a navbar with configurable + * action buttons and the body where @Db.Form childs can be displayed. + */ module.exports = new Class ({ Extends: Htk.Component, Properties: { + /** + * The main connection object. + */ conn: { type: Db.Connection @@ -19,15 +28,26 @@ module.exports = new Class { return this._conn; } + }, + /** + * The current open form. + */ + activeForm: + { + type: Form + ,get: function () + { + return this._activeForm; + } } } - ,forms: {} - ,activeForm: null - ,requestedForm: null - ,menuShown: false - ,menuOptions: {} - ,choosedOption: null + ,_forms: {} + ,_activeForm: null + ,_requestedForm: null + ,_menuShown: false + ,_menuOptions: {} + ,_choosedOption: null ,_shown: false ,_scrollTimeout: null ,_navbarVisible: true @@ -119,7 +139,7 @@ module.exports = new Class ,_onConnClose: function () { - this.signalEmit ('logout'); + this.emit ('logout'); } ,_onConnLoadChange: function (conn, isLoading) @@ -220,7 +240,7 @@ module.exports = new Class if (row.path) { a.href = this.hash.make ({'form': row.path}); - this.menuOptions[row.path] = a; + this._menuOptions[row.path] = a; } a.appendChild (text); @@ -246,7 +266,7 @@ module.exports = new Class ,_onLiMouseHover: function (submenu, parent) { - if (this.menuShown) + if (this._menuShown) return; this.hideSubmenu (); @@ -282,7 +302,7 @@ module.exports = new Class { this.showBackground (); Vn.Node.addClass (this.$('left-panel'), 'show'); - this.menuShown = true; + this._menuShown = true; this.hideMenuCallback = this.hideMenu.bind (this); this.doc.addEventListener ('click', this.hideMenuCallback); @@ -290,12 +310,12 @@ module.exports = new Class ,hideMenu: function () { - if (!this.menuShown) + if (!this._menuShown) return; this.hideBackground (); Vn.Node.removeClass (this.$('left-panel'), 'show'); - this.menuShown = false; + this._menuShown = false; this.doc.removeEventListener ('click', this.hideMenuCallback); this.hideMenuCallback = null; @@ -387,22 +407,22 @@ module.exports = new Class this.loaderPush (); this.closeForm (); - this.requestedForm = formPath; + this._requestedForm = formPath; - var newChoosedOption = this.menuOptions[formPath]; + var newChoosedOption = this._menuOptions[formPath]; if (newChoosedOption) { Vn.Node.addClass (newChoosedOption, 'selected'); - this.choosedOption = newChoosedOption; + this._choosedOption = newChoosedOption; } - var formInfo = this.forms[formPath]; + var formInfo = this._forms[formPath]; if (!formInfo) { formInfo = new Module ('forms', formPath); - this.forms[formPath] = formInfo; + this._forms[formPath] = formInfo; } formInfo.load (callback); @@ -418,8 +438,11 @@ module.exports = new Class return; } - this.activeForm = new formInfo.klass (this, formInfo); - this.activeForm.open (); + this._activeForm = new formInfo.klass ({ + gui: this, + formInfo: formInfo + }); + this._activeForm.open (); } ,setForm: function (form) @@ -453,18 +476,18 @@ module.exports = new Class ,closeForm: function () { - if (this.activeForm) + if (this._activeForm) { - this.activeForm.formInfo.unload (); - this.activeForm.close (); - this.activeForm.unref (); - this.activeForm = null; + this._activeForm.formInfo.unload (); + this._activeForm.close (); + this._activeForm.unref (); + this._activeForm = null; } - if (this.choosedOption) + if (this._choosedOption) { - Vn.Node.removeClass (this.choosedOption, 'selected'); - this.choosedOption = null; + Vn.Node.removeClass (this._choosedOption, 'selected'); + this._choosedOption = null; } } diff --git a/js/hedera/login.js b/js/hedera/login.js index 78fa4d4d..1a09e699 100644 --- a/js/hedera/login.js +++ b/js/hedera/login.js @@ -1,12 +1,19 @@ -var Css = require ('./login.css'); var Tpl = require ('./login.xml'); +require ('./login.css'); + +/** + * The login component. + */ module.exports = new Class ({ Extends: Htk.Component, Properties: { + /** + * The main connection object. + */ conn: { type: Db.Connection @@ -35,14 +42,6 @@ module.exports = new Class return false; }; } - - ,_onConnLoadChange: function (conn, isLoading) - { - if (isLoading) - this.$('spinner').start (); - else - this.$('spinner').stop (); - } ,show: function () { @@ -56,6 +55,19 @@ module.exports = new Class this._focusUserInput (); } + ,hide: function () + { + Vn.Node.remove (this.node); + } + + ,_onConnLoadChange: function (conn, isLoading) + { + if (isLoading) + this.$('spinner').start (); + else + this.$('spinner').stop (); + } + ,_onSubmit: function () { this._conn.open ( @@ -79,7 +91,7 @@ module.exports = new Class if (user) localStorage.setItem ('hederaLastUser', user); - this.signalEmit ('login'); + this.emit ('login'); } else { @@ -88,11 +100,6 @@ module.exports = new Class } } - ,hide: function () - { - Vn.Node.remove (this.node); - } - ,_focusUserInput: function () { var userEntry = this.$('user'); @@ -114,7 +121,7 @@ module.exports = new Class if (!user) Htk.Toast.showError (_('Please write your user name')); else - this._conn.send ('core/recover-password', {'recoverUser': user}, + this._conn.send ('core/recover-password', {recoverUser: user}, this._onPasswordRecovered.bind (this)); } diff --git a/js/hedera/report.html b/js/hedera/report.html deleted file mode 100755 index 908c81fd..00000000 --- a/js/hedera/report.html +++ /dev/null @@ -1,18 +0,0 @@ - - - - - - - - - - - Report - - -

- -
- - diff --git a/js/htk/assistant.js b/js/htk/assistant.js index 971f7c7f..08580912 100644 --- a/js/htk/assistant.js +++ b/js/htk/assistant.js @@ -93,7 +93,7 @@ module.exports = new Class ,_setStepIndex: function (stepIndex) { this._stepIndex = stepIndex; - this.signalEmit ('step-change', stepIndex); + this.emit ('step-change', stepIndex); } ,movePrevious: function () diff --git a/js/htk/column.js b/js/htk/column.js index 62103b26..3c1e4ad5 100644 --- a/js/htk/column.js +++ b/js/htk/column.js @@ -106,7 +106,7 @@ module.exports = new Class ,changed: function (tr, newValue) { - this.signalEmit ('changed', tr.rowIndex - 1, newValue); + this.emit ('changed', tr.rowIndex - 1, newValue); } }); diff --git a/js/htk/column/button.js b/js/htk/column/button.js index daf794fd..95a870ab 100644 --- a/js/htk/column/button.js +++ b/js/htk/column/button.js @@ -61,6 +61,6 @@ module.exports = new Class ,_onClick: function (value, tr, button, event) { event.preventDefault (); - this.signalEmit ('clicked', value, tr.rowIndex - 1, button, event); + this.emit ('clicked', value, tr.rowIndex - 1, button, event); } }); diff --git a/js/htk/dialog.js b/js/htk/dialog.js index 38e1b827..4e282b11 100644 --- a/js/htk/dialog.js +++ b/js/htk/dialog.js @@ -173,12 +173,12 @@ Dialog.implement ,_onButtonClick: function (response) { this.hide (); - this.signalEmit ('response', response); + this.emit ('response', response); } ,_onClosed: function () { - this.signalEmit ('response', null); + this.emit ('response', null); } }); diff --git a/js/htk/field.js b/js/htk/field.js index 6a4f6bbb..8852f786 100644 --- a/js/htk/field.js +++ b/js/htk/field.js @@ -1,44 +1,89 @@ var Widget = require ('./widget'); +/** + * Base class for graphical fields. + */ module.exports = new Class ({ Extends: Widget + ,Implements: Vn.ParamIface ,Tag: 'htk-field' ,Properties: { value: { - type: String + type: null ,set: function (x) { - if (Vn.Value.compare (x, this._value)) - return; - - if (x instanceof Date) - x = x.clone (); - - this.valueChanged (x); - this.putValue (x); + this._setValue (x); } ,get: function () { return this._value; } }, - param: + type: { - type: Vn.Param + type: Type ,set: function (x) { - this.link ({_param: x}, {'changed': this.onParamChange}); - this.onParamChange (); + this._setType (x); + } + ,get: function () + { + return this._type; + } + }, + param: + { + type: Vn.ParamIface + ,set: function (x) + { + this._setParam (x); } ,get: function () { return this._param; } }, + lot: + { + type: Vn.LotIface + ,set: function (x) + { + this._setLot (x); + } + ,get: function () + { + return this._lot; + } + }, + name: + { + type: String + ,set: function (x) + { + this._name = x; + this._onLotChange (); + } + ,get: function () + { + return this._name; + } + }, + oneWay: + { + type: Boolean + ,set: function (x) + { + this._oneWay = x; + } + ,get: function () + { + return this._oneWay; + } + }, editable: { type: Boolean @@ -55,24 +100,6 @@ module.exports = new Class return this._editable; } }, - lot: - { - type: Db.Iterator - ,set: function (x) - { - this._lot = x; - this.bindToLot (); - } - }, - name: - { - type: String - ,set: function (x) - { - this._paramName = x; - this.bindToLot (); - } - }, conditionalFunc: { type: Function @@ -80,30 +107,26 @@ module.exports = new Class } } - ,_value: undefined - ,_param: null ,_editable: true - ,_blockParamChange: false - ,_blockValueChange: false - ,onParamChange: function () + ,_setValue: function (newValue) { - if (!this._blockValueChange) - { - this._blockParamChange = true; - this.value = this._param.value; - this._blockParamChange = false; - } + Vn.ParamIface.prototype._setValue.call (this, newValue); + this.putValue (newValue); + + if (this.conditionalFunc) + this.conditionalFunc (this, newValue); } - - ,bindToLot: function () + + /** + * Protected method that should be called from class childs when the value + * on the associated entry changes. + * + * @param {*} value The new entry value + */ + ,valueChanged: function (value) { - if (this._lot && this._paramName) - this.param = new Vn.Param - ({ - lot: this._lot - ,name: this._paramName - }); + this._setValue (value); } /** @@ -121,28 +144,5 @@ module.exports = new Class * @param {*} value The new value for the entry */ ,putValue: function () {} - - /** - * Protected method that should be called from class childs when the value - * on the associated entry changes. - * - * @param {*} value The new entry value - */ - ,valueChanged: function (value) - { - this._value = value; - - if (this.conditionalFunc) - this.conditionalFunc (this, value); - - if (this._param && !this._blockParamChange) - { - this._blockValueChange = true; - this._param.value = value; - this._blockValueChange = false; - } - - this.signalEmit ('changed'); - } }); diff --git a/js/htk/field/button.js b/js/htk/field/button.js index 84056f24..033952b3 100644 --- a/js/htk/field/button.js +++ b/js/htk/field/button.js @@ -82,6 +82,6 @@ module.exports = new Class ,_onClick: function (event) { event.preventDefault (); - this.signalEmit ('click', this._form, event); + this.emit ('click', this._form, event); } }); diff --git a/js/htk/field/combo.js b/js/htk/field/combo.js index 1f41a2c0..de578a14 100644 --- a/js/htk/field/combo.js +++ b/js/htk/field/combo.js @@ -184,7 +184,7 @@ module.exports = new Class popup.on ('closed', this._onPopupClose.bind (this)); popup.show (this.node, true, e); - this.signalEmit ('menu-show'); + this.emit ('menu-show'); } ,_onGridClicked: function (grid, e) @@ -216,7 +216,7 @@ module.exports = new Class ,_onPopupClose: function () { this._popup = null; - this.signalEmit ('menu-hide'); + this.emit ('menu-hide'); } ,_refreshShowText: function () @@ -238,7 +238,7 @@ module.exports = new Class ,_onModelChange: function () { var model = this._model; - this.signalEmit ('status-changed'); + this.emit ('status-changed'); if (this._popup) this._popup.reset (); @@ -246,7 +246,7 @@ module.exports = new Class if (model && model.ready) { this._selectOption (); - this.signalEmit ('ready'); + this.emit ('ready'); } else this._setRow (-1); diff --git a/js/htk/field/radio.js b/js/htk/field/radio.js index ea839618..3e5e4723 100644 --- a/js/htk/field/radio.js +++ b/js/htk/field/radio.js @@ -21,7 +21,7 @@ module.exports = new Class type: RadioGroup ,set: function (x) { - this.link ({_radioGroup: x}, {'changed': this._onRadioGroupChange}); + this.link ({_radioGroup: x}, {changed: this._onRadioGroupChange}); this.node.name = x.radioName this._onRadioGroupChange (); } diff --git a/js/htk/field/table.js b/js/htk/field/table.js index b1b39464..b0137de7 100644 --- a/js/htk/field/table.js +++ b/js/htk/field/table.js @@ -32,7 +32,7 @@ module.exports = new Class ,changed: function (rbGroup) { this.realValue = this.rbGroup.getValue (); - this.signalEmit ('changed'); + this.emit ('changed'); } ,selectValue: function () diff --git a/js/htk/image-editor.js b/js/htk/image-editor.js index 399d5c54..053258d4 100644 --- a/js/htk/image-editor.js +++ b/js/htk/image-editor.js @@ -39,7 +39,7 @@ module.exports = new Class if (!newValue) newValue = null - this.signalEmit ('name-changed', newValue); + this.emit ('name-changed', newValue); } ,_onSubmit: function () @@ -60,7 +60,7 @@ module.exports = new Class throw error; Toast.showMessage (_('ImageAdded')); - this.signalEmit ('file-uploaded', this.$('name').value); + this.emit ('file-uploaded', this.$('name').value); } ,setData: function (image, directory) diff --git a/js/htk/popup.js b/js/htk/popup.js index bf687516..20a33198 100644 --- a/js/htk/popup.js +++ b/js/htk/popup.js @@ -261,7 +261,7 @@ module.exports = new Class Vn.Node.remove (node); this._parent = null; this._isOpen = false; - this.signalEmit ('closed'); + this.emit ('closed'); } ,_bgMouseDown: function (e) diff --git a/js/htk/repeater.js b/js/htk/repeater.js index 5c00690b..055b928a 100644 --- a/js/htk/repeater.js +++ b/js/htk/repeater.js @@ -169,7 +169,7 @@ module.exports = new Class } this.node.appendChild (this._container); - this.signalEmit ('change'); + this.emit ('change'); } ,_showNoRecordsFound: function (count) diff --git a/js/sql/field.js b/js/sql/field.js index b936b125..e6967331 100644 --- a/js/sql/field.js +++ b/js/sql/field.js @@ -12,11 +12,17 @@ module.exports = new Class ,Tag: 'sql-field' ,Properties: { + /** + * The column name. + */ name: { type: String ,value: null }, + /** + * The source table name or its alias if it has been specified. + */ target: { type: String @@ -24,7 +30,7 @@ module.exports = new Class } } - ,render: function (batch) + ,render: function () { var sql = (this.target) ? '`' + this.target + '`.' : ''; return sql + '`' + this.name + '`'; diff --git a/js/sql/filter-item.js b/js/sql/filter-item.js index 175fb3a6..c730a980 100644 --- a/js/sql/filter-item.js +++ b/js/sql/filter-item.js @@ -1,8 +1,12 @@ var Operation = require ('./operation'); +var Value = require ('./value'); +var Field = require ('./field'); /** - * The equivalent of a SQL operation. + * Objects to be used as an operands of @Sql.Filter. It represents a two + * expressions basic operation composed by a table column, the operator and the + * value extracted from the rendering paramerers. */ module.exports = new Class ({ @@ -10,11 +14,66 @@ module.exports = new Class ,Tag: 'sql-filter-item' ,Properties: { - primary: + /** + * The column name. + */ + field: { - type: Boolean + type: String, + value: null + }, + /** + * The source table name or its alias if it has been specified. + */ + target: + { + type: String, + value: null + }, + /** + * The parameter name. + */ + param: + { + type: String, + value: null } } - - ,primary: true + + /** + * Checks if parameter name haa been defined and if it has a value. + */ + ,isReady: function (params) + { + return this.param != null && params != null && params[this.param] != null; + } + + ,render: function (params) + { + var op = new Operation ({type: this.type}); + + var field = new Field ({ + name: this.field, + target: this.target + }); + op.appendChild (field); + + var value = params[this.param]; + + if (this.type === Operation.Type.LIKE && typeof value == 'string') + { + value = value.replace (/[\%\?]/g, this._escapeChar); + value = value.replace (/^|\s+|$/g, '%'); + } + + var sqlValue = new Value ({value: value}); + op.appendChild (sqlValue); + + return op.render (params); + } + + ,_escapeChar: function (char) + { + return '\\'+ char; + } }); diff --git a/js/sql/filter.js b/js/sql/filter.js index a574ff3b..5b557fcf 100644 --- a/js/sql/filter.js +++ b/js/sql/filter.js @@ -1,50 +1,46 @@ var Operation = require ('./operation'); +var Value = require ('./value'); /** - * The equivalent of a SQL operation. + * The equivalent of a SQL filter expression. It allows to automatically build + * SQL filters based on lot parameters. */ module.exports = new Class ({ Extends: Operation ,Tag: 'sql-filter' - ,Properties: - { - alwaysReady: - { - type: Boolean - } - } - ,isReady: function () + /** + * Checks if any of filters childs are ready. + */ + ,isReady: function (params) { - if (this.alwaysReady) + var exprs = this.exprs.objects; + for (var i = exprs.length; i--;) + if (exprs[i].isReady (params)) return true; - - var e = this.exprs.getArray (); - for (var i = 0; i < e.length; i++) - if (e[i].isReady () && e[i].primary) - return true; - + return false; } - ,render: function (batch) + /** + * Renders the filter as an SQL expression. If any of its childs isn't + * ready is ommitted from the expression. If all of its childs aren't ready + * renders the TRUE expression. + */ + ,render: function (params) { - var isReady = false; - var newOp = new Operation ({type: this.type}); + var op = new Operation ({type: this.type}); + var exprs = this.exprs.objects; + + for (var i = 0; i < exprs.length; i++) + if (exprs[i].isReady (params)) + op.exprs.add (exprs[i]); - var e = this.exprs.getArray (); - for (var i = 0; i < e.length; i++) - if (e[i].isReady ()) - { - newOp.exprs.add (e[i]); - isReady = true; - } + if (op.exprs.objects.length == 0) + op = new Value ({value: true}); - if (!isReady) - return 'TRUE'; - - return newOp.render (batch); + return op.render (params); } }); diff --git a/js/sql/list.js b/js/sql/list.js index e9ff9275..00af5453 100644 --- a/js/sql/list.js +++ b/js/sql/list.js @@ -35,7 +35,7 @@ module.exports = new Class ,_onObjectChange: function () { - this.signalEmit ('changed'); + this.emit ('changed'); } ,isReady: function () diff --git a/js/sql/object.js b/js/sql/object.js index 316d111b..74f56b31 100644 --- a/js/sql/object.js +++ b/js/sql/object.js @@ -16,6 +16,7 @@ module.exports = new Class /** * Gets if the object is ready to be rendered. * + * @param {Object} params The query parameters * @return {boolean} %true if the object is ready, %false otherwise */ ,isReady: function () diff --git a/js/sql/operation.js b/js/sql/operation.js index be8a4145..76445641 100644 --- a/js/sql/operation.js +++ b/js/sql/operation.js @@ -7,8 +7,8 @@ var Expr = require ('./expr'); * @param {Array#Sql.Expr} expr Array with the exprs * @param {Sql..Operation.Type} type The type of the operation */ -var Operation = new Class (); -module.exports = Operation; +var Klass = new Class (); +module.exports = Klass; var Type = { @@ -28,13 +28,13 @@ var Operators = ,'REGEXP' ]; -Operation.extend +Klass.extend ({ Type: Type ,Operators: Operators }); -Operation.implement +Klass.implement ({ Extends: Expr ,Tag: 'sql-operation' @@ -60,7 +60,7 @@ Operation.implement ,onListChange: function () { - this.signalEmit ('changed'); + this.emit ('changed'); } ,isReady: function () diff --git a/js/sql/search-tags.js b/js/sql/search-tags.js index 7e0eab98..96f4ac77 100644 --- a/js/sql/search-tags.js +++ b/js/sql/search-tags.js @@ -9,7 +9,7 @@ module.exports = new Class Extends: Value ,Tag: 'sql-search-tags' - ,render: function (batch) + ,render: function () { if (typeof this._value == 'string') { diff --git a/js/sql/string.js b/js/sql/string.js index aa9fefb7..54015f29 100644 --- a/js/sql/string.js +++ b/js/sql/string.js @@ -19,18 +19,18 @@ module.exports = new Class ,regexp: /#\w+/g - ,replaceFunc: function (batch, token) + ,replaceFunc: function (params, token) { var holder = new Holder ({id: token.substr (1)}); - return holder.render (batch); + return holder.render (params); } - ,render: function (batch) + ,render: function (params) { if (!this.query) return null; - return this.query.replace (this.regexp, this.replaceFunc.bind (this, batch)); + return this.query.replace (this.regexp, this.replaceFunc.bind (this, params)); } ,findHolders: function () diff --git a/js/sql/value.js b/js/sql/value.js index c0a73d5b..21e88e92 100644 --- a/js/sql/value.js +++ b/js/sql/value.js @@ -7,72 +7,86 @@ var Expr = require ('./expr'); module.exports = new Class ({ Extends: Expr + ,Implements: Vn.ParamIface ,Tag: 'sql-value' - ,Properties: { - /** - * The master param. - */ - param: + value: { - type: Vn.Param + type: null ,set: function (x) { - this.link ({_param: x}, {'changed': this.onParamChange}); - this.onParamChange (); + this._setValue (x); + } + ,get: function () + { + return this._value; + } + }, + type: + { + type: Type + ,set: function (x) + { + this._setType (x); + } + ,get: function () + { + return this._type; + } + }, + param: + { + type: Vn.ParamIface + ,set: function (x) + { + this._setParam (x); } ,get: function () { return this._param; } }, - /** - * The value. - */ - value: + lot: + { + type: Vn.LotIface + ,set: function (x) + { + this._setLot (x); + } + ,get: function () + { + return this._lot; + } + }, + name: { type: String ,set: function (x) { - if (Vn.Value.compare (x, this._value)) - return; - - if (x instanceof Date) - x = x.clone (); - - this._value = x; - - if (this._param && !this.paramLock) - { - this.paramLock = true; - this._param.value = x; - this.paramLock = false; - } - - this.signalEmit ('changed'); + this._name = x; + this._onLotChange (); } ,get: function () { - return this._value; + return this._name; + } + }, + oneWay: + { + type: Boolean + ,set: function (x) + { + this._oneWay = x; + } + ,get: function () + { + return this._oneWay; } } } - ,_value: undefined - ,_param: null ,regexp: new RegExp ('(\\\\)|\'', 'g') - ,paramLock: false - - ,onParamChange: function () - { - if (this.paramLock || !this._param) - return; - - this.paramLock = true; - this.value = this._param.value; - this.paramLock = false; - } ,isReady: function () { diff --git a/js/vn/builder.js b/js/vn/builder.js index 09b07ef7..d3a9dfb4 100644 --- a/js/vn/builder.js +++ b/js/vn/builder.js @@ -390,6 +390,9 @@ module.exports = new Class switch (propInfo.type) { + case null: + newValue = value; + break; case Boolean: newValue = (/^(true|1)$/i).test (value); break; @@ -614,7 +617,7 @@ var BuilderResult = new Class { var objects = this.objects; - for (var i = 0; i < objects.length; i++) + for (var i = objects.length; i--;) if (objects[i] instanceof VnObject) objects[i].unref (); diff --git a/js/vn/hash.js b/js/vn/hash.js index 48236ce9..81d6537b 100644 --- a/js/vn/hash.js +++ b/js/vn/hash.js @@ -5,7 +5,9 @@ var LotIface = require ('./lot-iface'); var Value = require ('./value'); /** - * Class to handle the URL. + * Class to handle the hash part of the URL as a key-value + * javascript object. It also handles dates and objects as + * a value. */ module.exports = new Class ({ @@ -60,12 +62,7 @@ module.exports = new Class object[key] = value; this.assign (object); } - - /** - * Sets the hash part of the URL, respecting the current hash variables. - * - * @param {Object} object A key-value object - */ + ,assign: function (object) { var newObject = {}; diff --git a/js/vn/json-connection.js b/js/vn/json-connection.js index 2c893c81..ba334a10 100644 --- a/js/vn/json-connection.js +++ b/js/vn/json-connection.js @@ -79,7 +79,7 @@ module.exports = new Class var storage = remember ? localStorage : sessionStorage; storage.setItem ('vnToken', this.token); - this.signalEmit ('openned'); + this.emit ('openned'); } else this._closeClient (); @@ -105,7 +105,7 @@ module.exports = new Class */ ,_onClose: function (callback, json, error) { - this.signalEmit ('closed'); + this.emit ('closed'); if (callback) callback (this, json === true, error); @@ -217,7 +217,7 @@ module.exports = new Class this._requestsCount++; if (this._requestsCount === 1) - this.signalEmit ('loading-changed', true); + this.emit ('loading-changed', true); } ,_onStateChange: function (request, callback) @@ -228,7 +228,7 @@ module.exports = new Class this._requestsCount--; if (this._requestsCount === 0) - this.signalEmit ('loading-changed', false); + this.emit ('loading-changed', false); var data = null; var error = null; @@ -310,7 +310,7 @@ module.exports = new Class if (error.exception == 'SessionExpired') this.clearToken (); - this.signalEmit ('error', error); + this.emit ('error', error); } } }); diff --git a/js/vn/json-model.js b/js/vn/json-model.js new file mode 100644 index 00000000..ec6ae32f --- /dev/null +++ b/js/vn/json-model.js @@ -0,0 +1,90 @@ + +var VnObject = require ('./object'); +var ModelIface = require ('./model-iface'); +var ModelProxy = require ('./model-proxy'); + +var Mode = ModelProxy.Mode; + +/** + * Model that holds an array of Javascript objects with + * the same structure. + */ +module.exports = new Class +({ + Extends: VnObject + ,Implements: ModelIface + ,Tag: 'vn-json-model' + ,Properties: + { + numRows: + { + type: Number + }, + status: + { + type: Number + }, + mode: + { + enumType: Mode + ,value: Mode.ON_CHANGE + }, + data: + { + type: Array + ,set: function (x) + { + this.data = x; + } + ,get: function () + { + return this.data; + } + } + } + + ,checkColExists: function () {} + + ,checkRowExists: function () {} + + ,getColumnIndex: function () {} + + ,get: function (rowIndex, columnName) + { + return this.data[rowIndex][columnName]; + } + + ,getByIndex: function (rowIndex, column) + { + var columnName = this.columns[column]; + return this.data[rowIndex][columnName]; + } + + ,getObject: function (rowIndex) + { + return this.data[rowIndex]; + } + + ,sortByName: function () {} + + ,sort: function () {} + + ,search: function () {} + + ,searchByIndex: function () {} + + ,set: function () {} + + ,setByIndex: function () {} + + ,deleteRow: function () {} + + ,insertRow: function () {} + + ,clean: function () {} + + ,performOperations: function () {} + + ,indexColumn: function () {} +}); + diff --git a/js/vn/lot-iface.js b/js/vn/lot-iface.js index dfc12168..4f621ebf 100644 --- a/js/vn/lot-iface.js +++ b/js/vn/lot-iface.js @@ -1,4 +1,8 @@ +/** + * Holds a plain key-value javascript object and monitorizes + * changes over it. + */ module.exports = new Class ({ Properties: @@ -40,7 +44,7 @@ module.exports = new Class */ ,changed: function () { - this.signalEmit ('change'); + this.emit ('change'); } /** @@ -56,6 +60,11 @@ module.exports = new Class this.changed (); } + /** + * Copies all values from another lot. + * + * @param {LotIface} lot The source lot + */ ,assignLot: function (lot) { this.assign (lot.params); diff --git a/js/vn/lot-query.js b/js/vn/lot-query.js new file mode 100644 index 00000000..e77a45af --- /dev/null +++ b/js/vn/lot-query.js @@ -0,0 +1,125 @@ + +var Lot = require ('./lot'); +var LotIface = require ('./lot-iface'); + +var Klass = new Class (); +module.exports = Klass; + +var Type = +{ + INCLUDE: 1, + EXCLUDE: 2 +}; + +Klass.extend +({ + Type: Type +}); + +Klass.implement +({ + Extends: Lot + ,Tag: 'vn-lot-query' + ,Properties: + { + fields: + { + type: Array + ,set: function (x) + { + this._fields = x; + this._onSourceChange (); + } + ,get: function () + { + return this._fields; + } + }, + source: + { + type: LotIface + ,set: function (x) + { + this.link ({_source: x}, {change: this._onSourceChange}); + this._onSourceChange (); + } + ,get: function () + { + return this._source; + } + }, + type: + { + enumType: Type + ,set: function (x) + { + this._type = x; + this._onSourceChange (); + } + ,get: function () + { + return this._type; + } + } + } + + ,_fields: null + ,_source: null + ,_type: Type.INCLUDE + + ,_onSourceChange: function () + { + var changed = false; + var params = this._source ? this._source.params : {}; + + if (this._fields) + switch (this._type) + { + case Type.EXCLUDE: + changed = this.typeExclude (params); + break; + default: + changed = this.typeInclude (params); + } + else + changed = true; + + if (changed) + this.changed (); + } + + ,typeInclude: function (params) + { + var changed = false; + var fields = this._fields; + + for (var i = fields.length; i--;) + { + var field = fields[i]; + + if (this._params[field] !== params[field]) + { + this._params[field] = params[field]; + changed = true; + } + } + + return changed; + } + + ,typeExclude: function (params) + { + var changed = false; + + for (var field in params) + if (this._fields.indexOf (field) === -1 + && this._params[field] !== params[field]) + { + this._params[field] = params[field]; + changed = true; + } + + return changed; + } +}); + diff --git a/js/vn/lot.js b/js/vn/lot.js index 65594326..2f6fd981 100644 --- a/js/vn/lot.js +++ b/js/vn/lot.js @@ -1,10 +1,10 @@ -var Object = require ('./object'); +var VnObject = require ('./object'); var LotIface = require ('./lot-iface'); module.exports = new Class ({ - Extends: Object + Extends: VnObject ,Implements: LotIface ,Tag: 'vn-lot' ,Properties: @@ -24,6 +24,8 @@ module.exports = new Class } } + ,_attachments: null + ,initialize: function (props) { this._params = {}; diff --git a/js/vn/model-iface.js b/js/vn/model-iface.js new file mode 100644 index 00000000..59cc75f0 --- /dev/null +++ b/js/vn/model-iface.js @@ -0,0 +1,157 @@ + +var VnObject = require ('./object'); + +/** + * Readable data model. + */ +var Klass = new Class (); +module.exports = Klass; + +var Status = +{ + CLEAN : 1 + ,LOADING : 2 + ,READY : 3 + ,ERROR : 4 +}; + +var SortWay = +{ + ASC : 1 + ,DESC : 2 +}; + +Klass.extend +({ + Status: Status + ,SortWay: SortWay +}); + +Klass.implement +({ + Extends: VnObject + ,Properties: + { + /** + * The number of rows in the model. + */ + numRows: + { + type: Number + }, + /** + * The current status of the model. + */ + status: + { + type: Number + }, + /** + * Checks if the model data is ready. + */ + ready: + { + type: Boolean + } + } + + /** + * Checks if the column exists. + * + * @param {integer} column The column index + * @return {Boolean} %true if column exists, %false otherwise + */ + ,checkColExists: function () {} + + /** + * Checks if the row exists. + * + * @param {integer} rowIndex The row index + * @return {Boolean} %true if row exists, %false otherwise + */ + ,checkRowExists: function () {} + + /** + * Get the index of the column from its name. + * + * @param {string} columnName The column name + * @return {number} The column index or -1 if column not exists + */ + ,getColumnIndex: function () {} + + /** + * Gets a value from the model. + * + * @param {number} rowIndex The row index + * @param {String} columnName The column name + * @return {*} The value, or %undefined + */ + ,get: function () {} + + /** + * Gets a value using the column index. + * + * @param {number} rowIndex The row index + * @param {number} column The column index + * @return {*} The value + */ + ,getByIndex: function () {} + + /** + * Gets a row as an object using the column index. + * + * @param {number} rowIndex The row index + * @return {Object} The row as an object + */ + ,getObject: function () {} + + /** + * Orders the model by the specified column name. + * + * @param {Number} column The column name + * @param {SortWay} way The sort way + */ + ,sortByName: function () {} + + /** + * Orders the model by the specified column. + * + * @param {Number} column The column index + * @param {SortWay} way The sort way + */ + ,sort: function () {} + + /** + * Searchs a value on the model and returns the row index of the first + * ocurrence. + * If an index have been built on that column, it will be used, for more + * information see the indexColumn() method. + * + * @param {String} column The column name + * @param {Object} value The value to search + * @return {Number} The column index + */ + ,search: function () {} + + /** + * Searchs a value on the model and returns the row index of the first + * ocurrence. + * + * @param {Number} col The column index + * @param {Object} value The value to search + * @return {Number} The column index + */ + ,searchByIndex: function () {} + + /** + * Builds an internal hash index for the specified column, this speeds + * significantly searches on that column, specially when model has a lot of + * rows. + * + * FIXME: Not fully implemented. + * + * @param {String} column The column name + */ + ,indexColumn: function () {} +}); + diff --git a/js/vn/model-proxy.js b/js/vn/model-proxy.js new file mode 100644 index 00000000..fd9bdeff --- /dev/null +++ b/js/vn/model-proxy.js @@ -0,0 +1,86 @@ + +var ModelIface = require ('./object'); + +/** + * Monitorizes all changes made to a model. + */ +var Klass = new Class (); +module.exports = Klass; + +var Mode = +{ + ON_CHANGE : 1 + ,ON_DEMAND : 2 +}; + +var Operation = +{ + INSERT : 1 << 1 + ,UPDATE : 1 << 2 + ,DELETE : 1 << 3 +}; + +Klass.extend +({ + Mode: Mode + ,Operation: Operation +}); + +Klass.implement +({ + Implements: ModelIface + ,Properties: + { + /** + * Update mode. + */ + mode: + { + enumType: Mode + ,value: Mode.ON_CHANGE + } + } + + /** + * Updates a value on the model. + * + * @param {number} rowIndex The row index + * @param {String} columnName The column name + * @param {*} value The new value + */ + ,set: function () {} + + /** + * Updates a value on the model using the column index. + * + * @param {Number} rowIndex The row index + * @param {Number} col The column index + * @param {*} value The new value + */ + ,setByIndex: function () {} + + /** + * Deletes a row from the model. + * + * @param {number} rowIndex The row index + */ + ,deleteRow: function () {} + + /** + * Inserts a new row on the model. + * + * @return The index of the inserted row + */ + ,insertRow: function () {} + + /** + * Cleans the model data. + */ + ,clean: function () {} + + /** + * Performs all model changes on the database. + */ + ,performOperations: function () {} +}); + diff --git a/js/vn/object.js b/js/vn/object.js index 6a308c13..f0e644c4 100644 --- a/js/vn/object.js +++ b/js/vn/object.js @@ -12,6 +12,12 @@ module.exports = new Class ,_refCount: 1 ,_signalData: null + /** + * Initializes the object and sets all properties passed to the class + * constructor. + * + * @param {Object} props The properties passed to the contructor + */ ,initialize: function (props) { this.setProperties (props); @@ -47,18 +53,23 @@ module.exports = new Class if (this._refCount === 0) this._destroy (); } - - ,loadXml: function (builder, node) {} - ,appendChild: function (child) {} - - ,_signalInit: function () - { - if (!this._signalData) - this._signalData = { - signals: {}, - links: {} - }; - } + + /** + * Called from @Vn.Builder when it finds a custom tag as a child of the + * element. + * + * @param {Vn.Builder} builder The builder instance + * @param {Node} node The custom tag child nodes + */ + ,loadXml: function () {} + + /** + * Called from @Vn.Builder when it finds a a child tag that isn't + * associated to any object property. + * + * @param {Object} child The child object instance + */ + ,appendChild: function () {} /** * Conects a signal with a function. @@ -81,8 +92,7 @@ module.exports = new Class if (!callbacks) callbacks = this._signalData.signals[id] = []; - callbacks.push - ({ + callbacks.push ({ blocked: false ,callback: callback ,instance: instance @@ -117,7 +127,7 @@ module.exports = new Class * * @param {String} id The signal identifier */ - ,signalEmit: function (id) + ,emit: function (id) { if (!this._signalData) return; @@ -152,13 +162,11 @@ module.exports = new Class var callbacks = this._signalData.signals[id]; - if (!callbacks) - return; - - for (var i = 0; i < callbacks.length; i++) + if (callbacks) + for (var i = callbacks.length; i--;) if (callbacks[i].callback === callback && callbacks[i].instance === instance) - callbacks.splice (i--, 1); + callbacks.splice (i, 1); } /** @@ -177,9 +185,10 @@ module.exports = new Class { var callbacks = signals[signalId]; - for (var i = 0; i < callbacks.length; i++) + if (callbacks) + for (var i = callbacks.length; i--;) if (callbacks[i].instance === instance) - callbacks.splice (i--, 1); + callbacks.splice (i, 1); } } @@ -199,12 +208,6 @@ module.exports = new Class this._signalData = null; } - - ,_unlink: function (object) - { - object.disconnectByInstance (this); - object.unref (); - } /** * Links the object with another object. @@ -238,5 +241,20 @@ module.exports = new Class delete links[key]; } } + + ,_unlink: function (object) + { + object.disconnectByInstance (this); + object.unref (); + } + + ,_signalInit: function () + { + if (!this._signalData) + this._signalData = { + signals: {}, + links: {} + }; + } }); diff --git a/js/vn/param-iface.js b/js/vn/param-iface.js new file mode 100644 index 00000000..6f62e741 --- /dev/null +++ b/js/vn/param-iface.js @@ -0,0 +1,140 @@ + +var LotIface = require ('./lot-iface'); +var Type = require ('./type'); + +/** + * A value holder, it emits the changed signal when value is changed. + * Also it can be linked with a lot value or another parameter. + */ +module.exports = new Class +({ + Properties: + { + /** + * The parameter value. + */ + value: + { + type: null + }, + /** + * The parameter type. + */ + type: + { + type: Type + }, + /** + * Another parameter to bind with. + */ + param: + { + type: Object + }, + /** + * A lot to bind with. + */ + lot: + { + type: LotIface + }, + /** + * The field name in the lot. + */ + name: + { + type: String + }, + /** + * Determines whether the link to the lot is unidirectional, ie, a + * change in the lot updates the parameter but not viceversa. + */ + oneWay: + { + type: Boolean + } + } + + ,_value: undefined + ,_type: null + ,_param: null + ,_paramLock: false + ,_lot: null + ,_name: null + ,_lotLock: false + ,_oneWay: false + + ,_setValue: function (newValue) + { + if (newValue == this._value) + return; + + if (newValue instanceof Date) + newValue = newValue.clone (); + + this._value = newValue; + this._refreshLot (); + this._refreshParam (); + this.emit ('changed', newValue); + } + + ,_setType: function (type) + { + this._type = type; + this._onLotChange (); + } + + ,_setParam: function (param) + { + this.link ({_param: param}, {changed: this._onParamChange}); + this._refreshParam (); + } + + ,_onParamChange: function () + { + if (this._paramLock || !this._param) + return; + + this._paramLock = true; + this._setValue (this._param.value); + this._paramLock = false; + } + + ,_refreshParam: function () + { + if (this._paramLock || !this._param) + return; + + this._paramLock = true; + this._param.value = this._value; + this._paramLock = false; + } + + ,_setLot: function (lot) + { + this.link ({_lot: lot}, {change: this._onLotChange}); + this._onLotChange (); + } + + ,_onLotChange: function () + { + if (this._lotLock || !this._name || !this._lot) + return; + + var newValue = this._lot.get (this._name, this._type); + + this._lotLock = true; + this._setValue (newValue); + this._lotLock = false; + } + + ,_refreshLot: function () + { + if (this._lotLock || !this._name || !this._lot || this._oneWay) + return; + + this._lotLock = true; + this._lot.set (this._name, this._value); + this._lotLock = false; + } +}); diff --git a/js/vn/param.js b/js/vn/param.js index 6f23e799..620ef8a7 100644 --- a/js/vn/param.js +++ b/js/vn/param.js @@ -1,28 +1,67 @@ var VnObject = require ('./object'); -var Lot = require ('./lot'); var Type = require ('./type'); +var ParamIface = require ('./param-iface'); +var LotIface = require ('./lot-iface'); +/** + * A simple implementation of @ParamIface. + */ module.exports = new Class ({ Extends: VnObject + ,Implements: ParamIface ,Tag: 'vn-param' - ,Child: 'param' ,Properties: { - param: + value: { - type: Object + type: null ,set: function (x) { - this.link ({_param: x}, {'changed': this._onParamChange}); - this._refreshParam (); + this._setValue (x); + } + ,get: function () + { + return this._value; + } + }, + type: + { + type: Type + ,set: function (x) + { + this._setType (x); + } + ,get: function () + { + return this._type; + } + }, + param: + { + type: ParamIface + ,set: function (x) + { + this._setParam (x); } ,get: function () { return this._param; } }, + lot: + { + type: LotIface + ,set: function (x) + { + this._setLot (x); + } + ,get: function () + { + return this._lot; + } + }, name: { type: String @@ -36,48 +75,6 @@ module.exports = new Class return this._name; } }, - value: - { - type: Object - ,set: function (x) - { - this._setValue (x, true); - } - ,get: function () - { - return this._value; - } - }, - type: - { - type: Type - ,set: function (x) - { - this._type = x; - this._onLotChange (); - } - ,get: function () - { - return this._type; - } - }, - lot: - { - type: Lot - ,set: function (x) - { - this.link ({_lot: x}, {'change': this._onLotChange}); - this._onLotChange (); - } - ,get: function () - { - return this._lot; - } - }, - /** - * Determines whether the link to the form is unidirectional, ie, a - * change in the lot updates the parameter but not vice versa. - */ oneWay: { type: Boolean @@ -91,67 +88,4 @@ module.exports = new Class } } } - - ,_lotLock: false - ,_paramLock: false - ,_value: undefined - ,_lot: null - ,_name: null - ,_type: null - ,_oneWay: false - - ,_onLotChange: function () - { - if (this._lotLock || !this._name || !this._lot) - return; - - var newValue = this._lot.get (this._name, this._type); - - this._lotLock = true; - this._setValue (newValue, true); - this._lotLock = false; - } - - ,_setValue: function (newValue, signal) - { - if (newValue == this._value) - return; - - if (newValue instanceof Date) - newValue = newValue.clone (); - - this._value = newValue; - - if (this._lot && this._name && !this._lotLock && !this._oneWay) - { - this._lotLock = true; - this._lot.set (this._name, newValue); - this._lotLock = false; - } - - this._refreshParam (); - - if (signal) - this.signalEmit ('changed', newValue); - } - - ,_refreshParam: function () - { - if (this._param && !this._paramLock) - { - this._paramLock = true; - this._param.value = this._value; - this._paramLock = false; - } - } - - ,_onParamChange: function () - { - if (this._paramLock) - return; - - this._paramLock = true; - this._setValue (this._param.value); - this._paramLock = false; - } }); diff --git a/js/vn/value.js b/js/vn/value.js index c21603ed..ecc0cc53 100644 --- a/js/vn/value.js +++ b/js/vn/value.js @@ -31,12 +31,65 @@ function equals (a, b) return false; } +/** + * Calculates differences of to key-value objects. + * + * @param {Object} orgObject Value to compare to + * @param {Object} newObject Value to compare with + * @return {Object} The differences or %null if there are no differences + */ +function diff (orgObject, newObject) +{ + var key; + var diff = {}; + + var keys = Object.keys (orgObject); + + for (var i = keys.length; --i; key = keys[i]) + if (orgObject[key] !== newObject[key]) + diff[key] = newObject[key]; + + var keys = Object.keys (newObject); + + for (var i = keys.length; --i; key = keys[i]) + if (orgObject[key] === undefined) + diff[key] = newObject[key]; + + if (Object.keys (diff).length > 0) + return diff; + + return null; +} + +/** + * Returns a formated string. + * + * @param {Object} formatString The base string template + * @param {...} arguments Format parameters + * @return {String} The formated string + */ +function sprintf (formatString) +{ + var args = arguments; + + if (args.length <= 1) + return formatString; + + var i = 1; + return formatString.replace (/%[s|d]/g, function () + { + return args[i++]; + }); +} + module.exports = { regexpNumber: /%\.([0-9]+)d/g ,regexpString: /%s/g ,equals: equals + ,diff: diff + ,sprintf: sprintf ,compare: function (a, b) { @@ -80,18 +133,3 @@ module.exports = return value; } }; - -window.sprintf = function (formatString) -{ - var args = arguments; - - if (args.length <= 1) - return formatString; - - var i = 1; - return formatString.replace (/%[s|d]/g, function () - { - return args[i++]; - }); -} - diff --git a/js/vn/vn.js b/js/vn/vn.js index 1fd84735..275d2504 100644 --- a/js/vn/vn.js +++ b/js/vn/vn.js @@ -14,8 +14,13 @@ Vn = module.exports = { ,Url : require ('./url') ,LotIface : require ('./lot-iface') ,Lot : require ('./lot') + ,LotQuery : require ('./lot-query') ,Hash : require ('./hash') + ,ParamIface : require ('./param-iface') ,Param : require ('./param') + ,ModelIface : require ('./model-iface') + ,ModelProxy : require ('./model-proxy') + ,JsonModel : require ('./json-model') ,Node : require ('./node') ,Builder : require ('./builder') ,JsonException : require ('./json-exception') diff --git a/rest/edi/sql/supplier.sql b/rest/edi/sql/supplier.sql index 93c82929..6dd419be 100644 --- a/rest/edi/sql/supplier.sql +++ b/rest/edi/sql/supplier.sql @@ -3,6 +3,7 @@ LOAD DATA LOCAL INFILE #file FIELDS TERMINATED BY ';' LINES TERMINATED BY '\n' (@col1, @col2, @col3, @col4, @col5, @col6, @col7, @col8, @col9, @col10, @col11, @col12, @col13, @col14, @col15, @col16, @col17, @col18, @col19, @col20) SET + glnAddressCode = @col2, supplier_id = @col4, company_name = @col3, entry_date = STR_TO_DATE(@col9, '%Y%m%d'),