diff --git a/app.js b/app.js index 0796bd49..3a647e0c 100644 --- a/app.js +++ b/app.js @@ -1,6 +1,5 @@ var Hedera = require ('hedera/hedera'); -Vn.includeCss ('pages/main/style.css'); window.onload = function () { @@ -25,7 +24,7 @@ function loadLocale (lang, cb) switch (lang) { case 'ca': - require ([], function (){ + require ([], function () { cb (require.context ('locale/ca/js')); }); break; case 'es': diff --git a/forms/account/address/address.js b/forms/account/address/address.js index d977a2c3..1dbabe5d 100644 --- a/forms/account/address/address.js +++ b/forms/account/address/address.js @@ -7,7 +7,7 @@ Hedera.Address = new Class { this.$('model').setInfo ('a', 'address_view', 'hedera', ['id'], 'id'); this.$('model').setDefault ('customer_id', 'a', - new Sql.Func ({schema: 'account', name: 'user_get_id'})); + new Sql.Function ({schema: 'account', name: 'user_get_id'})); } ,onStatusChange: function (form) diff --git a/forms/admin/connections/connections.js b/forms/admin/connections/connections.js index ff66f4d3..a7d4efc6 100644 --- a/forms/admin/connections/connections.js +++ b/forms/admin/connections/connections.js @@ -36,11 +36,11 @@ Hedera.Connections = new Class ,onChangeUserClick: function (button, form) { - this.gui.supplantUser (form.get ('user_id'), - this.onUserSupplant.bind (this)); + this.gui.supplantUser (form.get ('user'), + this._onUserSupplant.bind (this)); } - ,onUserSupplant: function (userName) + ,_onUserSupplant: function (userName) { this.hash.set ({'form': 'ecomerce/orders'}); } diff --git a/forms/admin/connections/ui.xml b/forms/admin/connections/ui.xml index 38a93ea6..ac673f32 100755 --- a/forms/admin/connections/ui.xml +++ b/forms/admin/connections/ui.xml @@ -23,9 +23,9 @@ SELECT s.id, e.user_id, c.Cliente, e.date_time login, is_new, - s.date_time last_activity, a.platform, a.browser, a.version - FROM user_session s - JOIN visit_user e ON s.visit_user_id = e.id + s.lastUpdate last_activity, a.platform, a.browser, a.version, u.name user + FROM userSession s + JOIN visit_user e ON s.userVisit = e.id JOIN visit_access c ON e.access_id = c.id JOIN visit_agent a ON c.agent_id = a.id JOIN visit v ON a.visit_id = v.id diff --git a/forms/admin/shelves/shelves.js b/forms/admin/shelves/shelves.js index d1753511..603cd32b 100644 --- a/forms/admin/shelves/shelves.js +++ b/forms/admin/shelves/shelves.js @@ -2,41 +2,50 @@ Hedera.Shelves = new Class ({ Extends: Hedera.Form - + ,activate: function () { this.$('date').value = new Date (); } - + ,onConfigChange: function () { - var c = this.$('config'); - this.$('warehouse').value = c.get ('warehouse_id'); - this.$('shelf').value = c.get ('shelf_id'); - this.$('reign').value = c.get ('reino_id'); - this.$('family').value = c.get ('family_id'); - this.$('filter').value = c.get ('name_prefix'); - this.$('max-amount').value = c.get ('max_amount'); - this.$('show-packing').value = c.get ('show_packing'); - this.$('stack').value = c.get ('stack'); - this.$('report-title').value = c.get ('name'); + var fields = [ + 'realm' + ,'family' + ,'warehouse' + ,'shelf' + ,'namePrefix' + ,'maxAmount' + ,'reportTitle' + ,'showPacking' + ,'stack' + ]; + + for (var i = 0; i < fields.length; i++) + this.$(fields[i]).value = this.$('config').get (fields[i]); } ,onPreviewClick: function () - { - var batch = new Sql.Batch (); - batch.addValues ({ - 'shelf': this.$('shelf').value, - 'wh': this.$('warehouse').value, - 'date': this.$('date').value, - 'family': this.$('family').value, - 'filter': this.$('filter').value, - 'title': this.$('report-title').value, - 'max-amount': this.$('max-amount').value, - 'show-packing': this.$('show-packing').value, - 'stack': this.$('stack').value, - 'use-ids': this.$('use-ids').value, - }); + { + var fields = [ + 'family' + ,'warehouse' + ,'shelf' + ,'namePrefix' + ,'maxAmount' + ,'reportTitle' + ,'showPacking' + ,'stack' + ,'useIds' + ,'date' + ]; + + var batch = new Sql.Batch (); + + for (var i = 0; i < fields.length; i++) + batch.addValue (fields[i], this.$(fields[i]).value); + this.gui.openReport ('shelves-report', batch); } }); diff --git a/forms/admin/shelves/ui.xml b/forms/admin/shelves/ui.xml index d67ea7d2..e1fa2a94 100755 --- a/forms/admin/shelves/ui.xml +++ b/forms/admin/shelves/ui.xml @@ -2,10 +2,10 @@ - SELECT c.id, c.name, c.name_prefix, c.warehouse_id, c.family_id, - c.shelf_id, c.max_amount, c.show_packing, c.stack, t.reino_id - FROM shelf_config c - JOIN vn2008.Tipos t ON t.tipo_id = c.family_id + SELECT c.id, c.name reportTitle, c.namePrefix, c.warehouse, c.family, + c.shelf, c.maxAmount, c.showPacking, c.stack, t.reino_id realm + FROM shelfConfig c + JOIN vn2008.Tipos t ON t.tipo_id = c.family @@ -36,8 +36,8 @@
- - + + SELECT id, reino FROM vn2008.reinos WHERE display != FALSE ORDER BY reino @@ -51,11 +51,11 @@ SELECT tipo_id, Tipo FROM vn2008.Tipos - WHERE reino_id = #reign ORDER BY Tipo + WHERE reino_id = #realm ORDER BY Tipo - + @@ -84,19 +84,19 @@
- +
- +
- +
- +
@@ -104,7 +104,7 @@
- +
diff --git a/forms/admin/users/ui.xml b/forms/admin/users/ui.xml index ac6e69f6..f894b5ff 100755 --- a/forms/admin/users/ui.xml +++ b/forms/admin/users/ui.xml @@ -35,13 +35,13 @@ form="iter" column="id" tip="_AccessAsUser" - image="image/incognito.svg" + icon="incognito" on-click="onChangeUserClick"/>

diff --git a/forms/admin/users/users.js b/forms/admin/users/users.js index 471b4d4b..08b383c3 100644 --- a/forms/admin/users/users.js +++ b/forms/admin/users/users.js @@ -13,7 +13,7 @@ Hedera.Users = new Class ,onChangeUserClick: function (button, form) { - this.gui.supplantUser (form.get ('id'), + this.gui.supplantUser (form.get ('name'), this.onUserSupplant.bind (this)); } diff --git a/forms/ecomerce/catalog/catalog.js b/forms/ecomerce/catalog/catalog.js index b8a720c2..1c944ae7 100644 --- a/forms/ecomerce/catalog/catalog.js +++ b/forms/ecomerce/catalog/catalog.js @@ -500,8 +500,8 @@ Vn.Filter = new Class icon: 'close', alt: _('Close') }); - button.appendChild (icon); - + button.appendChild (icon.node); + var text = this._label = document.createTextNode (''); li.appendChild (text); diff --git a/forms/ecomerce/confirm/ui.xml b/forms/ecomerce/confirm/ui.xml index c059b9ab..a706ef9b 100755 --- a/forms/ecomerce/confirm/ui.xml +++ b/forms/ecomerce/confirm/ui.xml @@ -215,7 +215,7 @@

- _Ok +

Order confirmed successfully

diff --git a/forms/news/new/new.js b/forms/news/new/new.js index af3b6220..f8f8a7c8 100644 --- a/forms/news/new/new.js +++ b/forms/news/new/new.js @@ -10,7 +10,7 @@ Hedera.New = new Class { this.$('model').mode = Db.Model.Mode.ON_DEMAND; this.$('model').setDefault ('user_id', 'news', - new Sql.Func ({schema: 'account', name: 'user_get_id'})); + new Sql.Function ({schema: 'account', name: 'userGetId'})); this.$('html-editor').id = 'html-editor'; tinymce.init ({ @@ -72,4 +72,3 @@ Hedera.New = new Class }); }); - diff --git a/js/db/model.js b/js/db/model.js index e8d7b3bb..c0c5d92b 100644 --- a/js/db/model.js +++ b/js/db/model.js @@ -1219,7 +1219,7 @@ Model.implement if (pkValue) equalOp.exprs.add (new Sql.Value ({value: pkValue})); else if (column.flags & Connection.Flag.AI && !useOldValues) - equalOp.exprs.add (new Sql.Func ({name: 'LAST_INSERT_ID'})); + equalOp.exprs.add (new Sql.Function ({name: 'LAST_INSERT_ID'})); else return null; } diff --git a/js/hedera/gui.js b/js/hedera/gui.js index 8a885617..db0ae232 100644 --- a/js/hedera/gui.js +++ b/js/hedera/gui.js @@ -15,14 +15,12 @@ module.exports = new Class this.link ({_conn: x}, {'loading-changed': this._onConnLoadChange }); - var sql = 'SELECT default_form, image_dir, image_host FROM config;' - +'SELECT production_domain, test_domain FROM config;' - +'SELECT name FROM customer_user;' - +'CALL form_list ();'; + var sql = 'SELECT name FROM customer_user;' + +'SELECT default_form, image_dir, image_host FROM config;' + +'SELECT production_domain, test_domain FROM config;'; x.execQuery (sql, this.onMainQueryDone.bind (this)); - if (Vn.Cookie.check ('hedera_supplant')) - this.supplantUser (Vn.Cookie.get ('hedera_supplant')); + this.loadMenu (); } ,get: function () { @@ -45,7 +43,6 @@ module.exports = new Class ,initialize: function (props) { this.builderInitString (Tpl); - this.loadingCount = 0; this.$('background').onclick = function () {}; @@ -133,6 +130,11 @@ module.exports = new Class ,onMainQueryDone: function (resultSet) { + // Retrieving the user name + + var userName = resultSet.fetchValue (); + Vn.Node.setText (this.$('user-name'), userName); + // Retrieving configuration parameters var res = resultSet.fetchResult (); @@ -165,16 +167,19 @@ module.exports = new Class else Vn.Node.hide (this.$('test-link')); - // Retrieving the user name + // Loading the default form - var userName = resultSet.fetchValue (); - - if (userName) - { - var span = this.$('user-name'); - span.appendChild (document.createTextNode (userName)); - } + this._onFormChange (); + } + + ,loadMenu: function () + { + var sql = 'CALL form_list ()'; + this._conn.execQuery (sql, this._onMenuLoad.bind (this)); + } + ,_onMenuLoad: function (resultSet) + { // Retrieving menu sections var res = resultSet.fetchResult (); @@ -191,105 +196,10 @@ module.exports = new Class sectionMap[parent].push (i); } + Vn.Node.removeChilds (this.$('main-menu')); this.createMenu (res, sectionMap, null, this.$('main-menu')); - - // Loading the default form - - this._onFormChange (); } - //++++++++++++++++++++++++++++++++++++++++++++++++++++++ Navigation bar - - ,_onScroll: function () - { - if (this._scrollTimeout === null) - this._scrollTimeout = setTimeout ( - this._scrollTimeoutFunc.bind (this), 150); - } - - ,_scrollTimeoutFunc: function () - { - if (!this._shown) - return; - - var navbar = this.$('top-bar'); - var yOffset = Vn.Browser.getPageYOffset (); - var showNavbar = this._lastYOffset > yOffset || yOffset < navbar.offsetHeight; - - if (showNavbar !== this._navbarVisible) - { - if (showNavbar) - var translateY = 0; - else - var translateY = -navbar.offsetHeight; - - navbar.style.transform = - 'translateZ(0) translateY('+ translateY +'px)'; - } - - this._navbarVisible = showNavbar; - this._lastYOffset = yOffset; - this._scrollTimeout = null; - } - - //++++++++++++++++++++++++++++++++++++++++++++++++++++++ Background - - ,showBackground: function () - { - Vn.Node.addClass (this.$('background'), 'show'); - } - - ,hideBackground: function () - { - Vn.Node.removeClass (this.$('background'), 'show'); - } - - //++++++++++++++++++++++++++++++++++++++++++++++++++++++ Menu - - ,showMenu: function () - { - this.showBackground (); - Vn.Node.addClass (this.$('left-panel'), 'show'); - this.menuShown = true; - - this.hideMenuCallback = this.hideMenu.bind (this); - document.addEventListener ('click', this.hideMenuCallback); - } - - ,hideMenu: function () - { - if (!this.menuShown) - return; - - this.hideBackground (); - Vn.Node.removeClass (this.$('left-panel'), 'show'); - this.menuShown = false; - - document.removeEventListener ('click', this.hideMenuCallback); - this.hideMenuCallback = null; - } - - //++++++++++++++++++++++++++++++++++++++++++++++++++++++ Spinner - - ,loaderPush: function () - { - this.loadingCount++; - - if (this.loadingCount == 1) - this.$('loader').start (); - } - - ,loaderPop: function () - { - if (this.loadingCount == 0) - return; - - this.loadingCount--; - - if (this.loadingCount == 0) - this.$('loader').stop (); - } - //++++++++++++++++++++++++++++++++++++++++++++++++++++++ Menu ,createMenu: function (res, sectionMap, parent, ul) @@ -362,6 +272,96 @@ module.exports = new Class this.timeout = 0; } } + + ,showMenu: function () + { + this.showBackground (); + Vn.Node.addClass (this.$('left-panel'), 'show'); + this.menuShown = true; + + this.hideMenuCallback = this.hideMenu.bind (this); + document.addEventListener ('click', this.hideMenuCallback); + } + + ,hideMenu: function () + { + if (!this.menuShown) + return; + + this.hideBackground (); + Vn.Node.removeClass (this.$('left-panel'), 'show'); + this.menuShown = false; + + document.removeEventListener ('click', this.hideMenuCallback); + this.hideMenuCallback = null; + } + + //++++++++++++++++++++++++++++++++++++++++++++++++++++++ Navigation bar + + ,_onScroll: function () + { + if (this._scrollTimeout === null) + this._scrollTimeout = setTimeout ( + this._scrollTimeoutFunc.bind (this), 150); + } + + ,_scrollTimeoutFunc: function () + { + if (!this._shown) + return; + + var navbar = this.$('top-bar'); + var yOffset = Vn.Browser.getPageYOffset (); + var showNavbar = this._lastYOffset > yOffset || yOffset < navbar.offsetHeight; + + if (showNavbar !== this._navbarVisible) + { + if (showNavbar) + var translateY = 0; + else + var translateY = -navbar.offsetHeight; + + navbar.style.transform = + 'translateZ(0) translateY('+ translateY +'px)'; + } + + this._navbarVisible = showNavbar; + this._lastYOffset = yOffset; + this._scrollTimeout = null; + } + + //++++++++++++++++++++++++++++++++++++++++++++++++++++++ Background + + ,showBackground: function () + { + Vn.Node.addClass (this.$('background'), 'show'); + } + + ,hideBackground: function () + { + Vn.Node.removeClass (this.$('background'), 'show'); + } + + //++++++++++++++++++++++++++++++++++++++++++++++++++++++ Spinner + + ,loaderPush: function () + { + this.loadingCount++; + + if (this.loadingCount == 1) + this.$('loader').start (); + } + + ,loaderPop: function () + { + if (this.loadingCount == 0) + return; + + this.loadingCount--; + + if (this.loadingCount == 0) + this.$('loader').stop (); + } //++++++++++++++++++++++++++++++++++++++++++++++++++++++ Forms @@ -501,50 +501,38 @@ module.exports = new Class //++++++++++++++++++++++++++++++++++++++++++++++++++++++ Supplant - ,supplantUser: function (userId, callback) + ,supplantUser: function (user, callback) { - var batch = new Sql.Batch (); - batch.addValue ('user', userId); - - var query = 'UPDATE user_session_view SET user_id = #user;'+ - 'SELECT Cliente FROM vn2008.Clientes WHERE Id_cliente = #user'; - this._conn.execQuery (query, - this._onUserSupplant.bind (this, userId, callback), batch); + this._conn.supplantUser (user, + this._onUserSupplant.bind (this, callback)); } - ,_onUserSupplant: function (userId, callback, resultSet) + ,_onUserSupplant: function (callback, supplantOk) { - this._supplantClear (); - Vn.Cookie.set ('hedera_supplant', userId); + if (!supplantOk) + return; - resultSet.fetchResult (); - var userName = resultSet.fetchValue (); - - Vn.Node.setText (this.$('supplanted'), userName); - Vn.Node.show (this.$('supplant')); + this.loadMenu (); + + var sql = 'SELECT name FROM customer_user'; + this._conn.execQuery (sql, this._onSupplantName.bind (this)); if (callback) callback (); } - - ,_supplantClear: function () + + ,_onSupplantName: function (resultSet) { - if (Vn.Cookie.check ('hedera_supplant')) - { - Vn.Node.hide (this.$('supplant')); - Vn.Cookie.unset ('hedera_supplant'); - } + var userName = resultSet.fetchValue (); + Vn.Node.setText (this.$('supplanted'), userName); + Vn.Node.show (this.$('supplant')); } ,onSupplantExitClick: function () { - var query = 'UPDATE user_session_view SET user_id = account.user_get_id ()' - this._conn.execQuery (query, this.supplantExit.bind (this)); - } - - ,supplantExit: function () - { - this._supplantClear (); + Vn.Node.hide (this.$('supplant')); + this._conn.supplantEnd (); + this.loadMenu (); this._onFormChange (); } diff --git a/js/hedera/login.css b/js/hedera/login.css index 5226bd4b..9ec43ac1 100644 --- a/js/hedera/login.css +++ b/js/hedera/login.css @@ -1,10 +1,4 @@ -body -{ - overflow: auto; - height: 100%; -} - .vn-login { color: #333; @@ -55,12 +49,11 @@ body { position: absolute; padding: 1em; - max-width: 15em; + max-width: 16em; top: 50%; left: 50%; margin-top: -20em; - margin-left: -8.5em; - + margin-left: -9em; } @media (max-height: 630px) { diff --git a/js/hedera/style.css b/js/hedera/style.css index a0560d08..af755988 100644 --- a/js/hedera/style.css +++ b/js/hedera/style.css @@ -71,9 +71,15 @@ body { - color: #333; font-family: 'Roboto', 'Verdana', 'Sans'; + background-color: #EEE; + color: #333; + position: absolute; + height: 100%; + width: 100%; margin: 0; + overflow: auto; + z-index: -2; } label, button, diff --git a/js/sql/sql.js b/js/sql/sql.js index 94377629..7de038f9 100644 --- a/js/sql/sql.js +++ b/js/sql/sql.js @@ -7,7 +7,7 @@ Sql = module.exports = { ,Batch : require ('./batch') ,List : require ('./list') ,Expr : require ('./expr') - ,Valuee : require ('./value') + ,Value : require ('./value') ,Field : require ('./field') ,Function : require ('./function') ,Operation : require ('./operation') diff --git a/js/vn/builder.js b/js/vn/builder.js index 50349ec7..d6d2531b 100644 --- a/js/vn/builder.js +++ b/js/vn/builder.js @@ -34,7 +34,13 @@ module.exports = new Class if (index !== undefined) return result.objects[index]; - else if (this._parentResult) + + var object = this._addedMap[objectId]; + + if (object !== undefined) + return object; + + if (this._parentResult) return this._parentResult.getById (objectId); return null; @@ -150,12 +156,14 @@ module.exports = new Class { var l = this._links[i]; var addedObject = this._addedMap[l.objectId]; - + if (addedObject) + { if (l.prop) objects[l.context.id][l.prop] = addedObject; else objects[l.context.id].appendChild (addedObject); + } else this._showError ('Referenced unexistent object with id \'%s\'', l.objectId); @@ -190,7 +198,7 @@ module.exports = new Class for (var i = this._links.length - 1; i >= 0; i--) { var l = this._links[i]; - var contextId = this._contextMap[l.objectId] + var contextId = this._contextMap[l.objectId]; if (contextId != undefined) { diff --git a/js/vn/json-connection.js b/js/vn/json-connection.js index 1441ec75..6782804f 100644 --- a/js/vn/json-connection.js +++ b/js/vn/json-connection.js @@ -19,17 +19,21 @@ module.exports = new Class ,initialize: function () { this.parent (); - - if (localStorage.getItem ('vnToken')) - this._token = localStorage.getItem ('vnToken'); + this._token = this.fetchToken (); + } + + ,fetchToken: function () + { if (sessionStorage.getItem ('vnToken')) - this._token = sessionStorage.getItem ('vnToken'); + return sessionStorage.getItem ('vnToken'); + if (localStorage.getItem ('vnToken')) + return localStorage.getItem ('vnToken'); } /** * Opens the connection to the REST service. * - * @param {string} user The user name + * @param {String} user The user name * @param {String} password The user password * @param {Boolean} remember Specifies if the user should be remembered * @param {Function} openCallback The function to call when operation is done @@ -105,6 +109,40 @@ module.exports = new Class sessionStorage.removeItem ('vnToken'); } + /** + * Suppants another user. + * + * @param {String} user The user name + * @param {Function} callback The callback function + **/ + ,supplantUser: function (user, callback) + { + var params = {'supplantUser': user}; + this.send ('core/supplant', params, + this._onUserSupplant.bind (this, callback)); + } + + ,_onUserSupplant: function (callback, json, error) + { + if (json) + { + this._token = json; + this._isSupplant = true; + } + + if (callback) + callback (json != null); + } + + /** + * Ends the user supplanting and restores the last login. + **/ + ,supplantEnd: function () + { + this._isSupplant = false; + this._token = this.fetchToken (); + } + /** * Executes the specified REST service with the given params and calls * the callback when response is received. diff --git a/js/vn/node.js b/js/vn/node.js index 7065f354..c75bac86 100644 --- a/js/vn/node.js +++ b/js/vn/node.js @@ -21,7 +21,8 @@ module.exports = Vn.Node.removeChilds (node); if (text) - node.appendChild (document.createTextNode (text)); + node.appendChild ( + node.ownerDocument.createTextNode (text)); } ,addClass: function (node, className) diff --git a/locale/en/reports/shelves-report.json b/locale/en/reports/shelves-report.json new file mode 100644 index 00000000..101d29fc --- /dev/null +++ b/locale/en/reports/shelves-report.json @@ -0,0 +1,5 @@ +{ + "Start": "Start" + ,"End": "End" + ,"Pallet": "Pallet" +} diff --git a/locale/es/reports/shelves-report.json b/locale/es/reports/shelves-report.json new file mode 100644 index 00000000..f3416e67 --- /dev/null +++ b/locale/es/reports/shelves-report.json @@ -0,0 +1,5 @@ +{ + "Start": "Inicio" + ,"End": "Fin" + ,"Pallet": "Palé" +} diff --git a/package.json b/package.json index 1d72c507..30d5e60d 100644 --- a/package.json +++ b/package.json @@ -10,13 +10,15 @@ "style-loader": "*", "file-loader": "*", "json-loader": "*", - "raw-loader": "*" + "raw-loader": "*", + "bundle-loader": "*" }, "dependencies": { "mootools": "^1.5.2", "tinymce": "^4.4.3" }, "scripts": { - "dev": "webpack-dev-server --devtool eval --inline --progress --colors" + "dev": "webpack-dev-server --progress --colors --inline --hot", + "build": "rm build/* ; webpack --progress --colors" } } diff --git a/pages/main/head.php b/pages/main/head.php index 1bae9239..67183340 100755 --- a/pages/main/head.php +++ b/pages/main/head.php @@ -12,7 +12,7 @@ if ($result = $db->query ('SELECT name, content FROM metatag')) $result->free (); } -if (DEBUG_MODE) +if (_DEBUG_MODE) { $this->includeJs ('http://localhost:8080/webpack-dev-server.js'); $this->includeJs ('http://localhost:8080/build/hedera-web.js'); diff --git a/pages/main/style.css b/pages/main/style.css deleted file mode 100755 index 75100497..00000000 --- a/pages/main/style.css +++ /dev/null @@ -1,11 +0,0 @@ - -body -{ - position: absolute; - height: 100%; - width: 100%; - z-index: -2; - background-color: #EEE; - overflow: hidden; -} - diff --git a/reports/shelves-report/shelves-report.js b/reports/shelves-report/shelves-report.js index 53332665..940c41f3 100644 --- a/reports/shelves-report/shelves-report.js +++ b/reports/shelves-report/shelves-report.js @@ -5,21 +5,22 @@ Hedera.ShelvesReport = new Class ,nItem: -1 ,nColors: 5 + ,trayThickness: 2 + ,trayMargin: 5 ,open: function (batch) { this.batch = batch; - this.title = batch.getValue ('title'); - this.maxAmount = batch.getValue ('max-amount'); - this.showPacking = batch.getValue ('show-packing'); + this.title = batch.getValue ('reportTitle'); + this.maxAmount = batch.getValue ('maxAmount'); + this.showPacking = batch.getValue ('showPacking'); this.stack = batch.getValue ('stack'); - this.useIds = batch.getValue ('use-ids'); + this.useIds = batch.getValue ('useIds'); var query = - 'SELECT id, name, width, height, depth, max_height, tray_height, '+ - 'first_tray_elevation, tray_density, vspacing, hspacing '+ + 'SELECT id, name, nTrays, topTrayHeight, trayHeight, width, depth '+ 'FROM shelf WHERE id = #shelf; '+ - 'CALL itemAllocator (#wh, #date, #family, #filter, #use-ids)'; + 'CALL itemAllocator (#warehouse, #date, #family, #namePrefix, #useIds)'; this.conn.execQuery (query, this.onQueryExec.bind (this), this.batch); } @@ -33,29 +34,28 @@ Hedera.ShelvesReport = new Class // Calculates the scale - var maxWidth = 170; - var maxHeight = 200; + var maxWidth = 160; + var maxHeight = 160; - var scale = maxWidth / res.get ('width'); + var shelfWidth = res.get ('width'); + var shelfHeight = res.get ('trayHeight') * (res.get ('nTrays') - 1) + res.get ('topTrayHeight'); - if (res.get ('max_height') * scale > maxHeight) - scale = maxHeight / res.get ('max_height'); + var scale = maxWidth / shelfWidth; + + if (shelfHeight * scale > maxHeight) + scale = maxHeight / shelfHeight; - // Gets the shelf dimensions + // Calculates the shelf dimensions var shelf = this.shelf = { - width: res.get ('width') * scale - ,height: res.get ('height') * scale + nTrays: res.get ('nTrays') + ,trayHeight: res.get ('trayHeight') * scale + ,topTrayHeight: res.get ('topTrayHeight') * scale + ,width: res.get ('width') * scale ,depth: res.get ('depth') * scale - ,maxHeight: res.get ('max_height') * scale - ,trayHeight: res.get ('tray_height') * scale - ,firstTrayElevation: res.get ('first_tray_elevation') * scale - ,trayDensity: res.get ('tray_density') * scale - ,vspacing: res.get ('vspacing') * scale - ,hspacing: res.get ('hspacing') * scale }; - + // Gets the items var items = this.items = []; @@ -100,15 +100,11 @@ Hedera.ShelvesReport = new Class alloc.shelfFunc = this.drawShelf.bind (this); alloc.boxFunc = this.drawBox.bind (this); alloc.stack = this.stack; - alloc.nTrays = Math.ceil ( - (shelf.height - shelf.firstTrayElevation) / - (shelf.trayHeight + shelf.trayDensity) - ); - alloc.width = shelf.width - shelf.hspacing * 2; + alloc.nTrays = shelf.nTrays; + alloc.width = shelf.width; alloc.depth = shelf.depth; - alloc.trayHeight = shelf.trayHeight - shelf.vspacing; - alloc.topTrayHeight = shelf.maxHeight - shelf.vspacing - - shelf.firstTrayElevation - (alloc.nTrays - 1) * shelf.trayHeight; + alloc.trayHeight = shelf.trayHeight; + alloc.topTrayHeight = shelf.topTrayHeight; // Opens the report @@ -168,7 +164,7 @@ Hedera.ShelvesReport = new Class // Draws the shelves this.alloc.run (); - this.drawShelfEnding (); + this.drawShelfRange (this.lastItem, false); } ,drawShelf: function (allocator, item) @@ -190,54 +186,65 @@ Hedera.ShelvesReport = new Class title.className = 'title'; title.appendChild (this.doc.createTextNode (this.title)); sheet.appendChild (title); + + if (this.subtitles) + this.drawShelfRange (this.lastItem, false); + + this.subtitles = this.doc.createElement ('div'); + sheet.appendChild (this.subtitles); - var subtitle = this.doc.createElement ('h2'); - subtitle.className = 'subtitle'; - subtitle.appendChild (this.doc.createTextNode (this.getName (item))); - sheet.appendChild (subtitle); - - this.drawShelfEnding (); - this.lastSubtitle = subtitle; + this.drawShelfRange (item, true); + this.lastSubtitles = this.subtitles; // Draws the shelf + var trayWidth = shelf.width + this.trayMargin * 2; + var shelfHeight = shelf.trayHeight * (shelf.nTrays - 1) + shelf.topTrayHeight + + (this.trayThickness + this.trayMargin) * shelf.nTrays; + var shelfDiv = this.shelfDiv = this.doc.createElement ('div'); shelfDiv.className = 'shelf'; - shelfDiv.style.width = this.mm (shelf.width); - shelfDiv.style.height = this.mm (shelf.maxHeight); + shelfDiv.style.width = this.mm (trayWidth); + shelfDiv.style.height = this.mm (shelfHeight); sheet.appendChild (shelfDiv); // Draws trays - var lastTrayY = shelf.firstTrayElevation; - - if (shelf.trayHeight > 0) - while (lastTrayY + shelf.trayDensity < shelf.height) + for (var i = 0; i < shelf.nTrays; i++) { var tray = this.doc.createElement ('div'); tray.className = 'tray'; - tray.style.width = this.mm (shelf.width); - tray.style.height = this.mm (shelf.trayDensity); - tray.style.bottom = this.mm (lastTrayY); + tray.style.bottom = this.mm ((shelf.trayHeight + this.trayThickness + this.trayMargin) * i); + tray.style.width = this.mm (trayWidth); + tray.style.height = this.mm (this.trayThickness); shelfDiv.appendChild (tray); - - lastTrayY += shelf.trayHeight + shelf.trayDensity; } } - ,drawShelfEnding: function () + ,drawShelfRange: function (item, isFirst) { - if (this.lastSubtitle) - this.lastSubtitle.appendChild (this.doc.createTextNode ( - ' - '+ this.getName (this.lastItem))); + var labelText = isFirst ? _('Start') : _('End'); + + var label = this.doc.createElement ('label'); + label.className = 'range-label'; + label.appendChild (this.doc.createTextNode (labelText)); + this.subtitles.appendChild (label); + + var subtitle = this.doc.createElement ('h2'); + subtitle.className = 'subtitle'; + subtitle.appendChild (this.doc.createTextNode (this.getItemLabel (item))); + this.subtitles.appendChild (subtitle); } - ,getName: function (item) + ,getItemLabel: function (item) { - if (this.useIds) - return item.id.toLocaleString (); + if (!this.useIds) + { + var packing = this.showPacking ? (' x'+ item.packing) : ''; + return item.name + packing; + } else - return item.name.charAt (0).toUpperCase (); + return item.id.toLocaleString (); } ,mm: function (size) @@ -252,10 +259,10 @@ Hedera.ShelvesReport = new Class var shelf = this.shelf; - var x = allocator.trayX + shelf.hspacing; - var y = allocator.trayY - + shelf.firstTrayElevation + shelf.trayDensity - + allocator.currentTray * (shelf.trayHeight + shelf.trayDensity); + var x = allocator.trayX + this.trayMargin; + var y = allocator.trayY + this.trayThickness + + this.trayMargin * allocator.currentTray + + allocator.currentTray * (shelf.trayHeight + this.trayThickness); var box = this.doc.createElement ('div'); box.className = 'box'; @@ -273,21 +280,28 @@ Hedera.ShelvesReport = new Class Vn.Node.addClass (box, 'color'+ nColor); if (amount == 0 || allocator.firstShelfBox) - { - var fontSize = item.boxWidth / 5.2; - - if (fontSize > item.boxHeight - 1) - fontSize = item.boxHeight - 1; - - if (this.useIds) - var labelText = item.id.toLocaleString (); - else - var labelText = item.name; - + { var boxLabel = this.doc.createElement ('div'); - boxLabel.className = 'box-label'; - boxLabel.style.fontSize = this.mm (fontSize); - boxLabel.appendChild (this.doc.createTextNode (labelText)); + + if (this.useIds) + { + var fontSize = item.boxWidth / 5.2; + + if (fontSize > item.boxHeight - 1) + fontSize = item.boxHeight - 1; + + boxLabel.style.fontSize = this.mm (fontSize); + + var cssClass = 'id'; + } + else + var cssClass = 'name'; + + boxLabel.className = 'box-label '+ cssClass; + + var labelText = this.doc.createTextNode (this.getItemLabel (item)); + boxLabel.appendChild (labelText); + box.appendChild (boxLabel); } diff --git a/reports/shelves-report/style.css b/reports/shelves-report/style.css index 9b140684..475471b6 100644 --- a/reports/shelves-report/style.css +++ b/reports/shelves-report/style.css @@ -9,11 +9,17 @@ h1 text-overflow: ellipsis; white-space: nowrap; overflow: hidden; + margin-bottom: 4mm; +} +label.range-label +{ + color: #777; } h2.subtitle { margin: 0; - font-size: 400%; + font-size: 200%; + margin-bottom: 2mm; font-weight: normal; color: #333; } @@ -47,13 +53,16 @@ h1.page-number border-bottom: 0; box-sizing: border-box; } -.box .box-label +.box-label { - text-align: right; - font-size: 55%; + font-size: 2.55mm; word-wrap: break-word; box-sizing: border-box; - padding: 0 4%; + padding: 1% 2%; +} +.box-label.id +{ + text-align: right; } .color0 { diff --git a/rest/core/login.php b/rest/core/login.php index c60a666e..dee21a0a 100755 --- a/rest/core/login.php +++ b/rest/core/login.php @@ -1,27 +1,22 @@ updateCredentials ($db); + try { + $this->updateCredentials ($db); + //$this->updateCredentialsLdap ($db); + } + catch (Exception $e) + { + error_log ($e->getMessage ()); + } - if (!empty ($_POST['remember'])) - $tokenLife = WEEK; - else - $tokenLife = 30 * MIN; - - $payload = [ - 'sub' => $_SESSION['user'], - 'exp' => time () + $tokenLife - ]; - $key = $db->getValue ('SELECT jwtKey FROM config'); - $token = Vn\Web\Jwt::encode ($payload, $key); + $token = $this->service->createToken ( + $_SESSION['user'], + !empty ($_POST['remember']) + ); return [ 'login' => TRUE, @@ -29,6 +24,27 @@ class Login extends Vn\Web\JsonRequest ]; } + /** + * Updates the user credentials in other user databases like Samba + * LDAP . + **/ + function updateCredentialsLdap ($db) + { + $host = $ldapConf['host']; + + if ($ldapConf->secure) + $ldapHost = "ldaps://$host"; + else + $ldapHost = "ldap://$host"; + + $ldap = ldap_connect ($ldapHost, $ldapConf['port']); + + if (!ldap_bind ($ldap, $ldapConf['user'], $ldapConf['password'])) + throw new Exception ('LDAP authentication failed'); + + error_log ('Connected to LDAP!'); + } + /** * Updates the user credentials in other user databases like Samba. **/ @@ -51,18 +67,19 @@ class Login extends Vn\Web\JsonRequest $sshConf = $db->getRow ('SELECT host, user, password FROM ssh_config'); $ssh = ssh2_connect ($sshConf['host']); - $sshOk = $ssh && ssh2_auth_password ($ssh, + + if (!$ssh) + throw new Exception ("Can't connect to SSH server {$sshConf['host']}"); + + $sshAuth = ssh2_auth_password ($ssh, $sshConf['user'], base64_decode ($sshConf['password'])); - if (!$sshOk) - { - error_log ("Can't connect to SSH server {$sshConf['host']}"); - return; - } + if (!$sshAuth) + throw new Exception ("SSH authentication failed"); $user = $this->escape ($_SESSION['user']); $pass = $this->escape ($_POST['password']); - ssh2_exec ($ssh, "samba-tool user create \"$user\" \"$pass\""); + $stream = ssh2_exec ($ssh, "samba-tool user create \"$user\" \"$pass\""); } /** diff --git a/rest/core/supplant.php b/rest/core/supplant.php new file mode 100755 index 00000000..cc0b4377 --- /dev/null +++ b/rest/core/supplant.php @@ -0,0 +1,13 @@ +service->createToken ($_REQUEST['supplantUser']); + } +} + +?> diff --git a/split-plugin.js b/split-plugin.js new file mode 100644 index 00000000..f0c46c16 --- /dev/null +++ b/split-plugin.js @@ -0,0 +1,30 @@ + +const util = require('util'); + +function SplitPlugin () {} + +module.exports = SplitPlugin; + +SplitPlugin.prototype.apply = function (compiler) +{ + compiler.plugin("this-compilation", function (compilation) + { + compilation.plugin(["optimize-chunks", "optimize-extracted-chunks"], function (chunks) + { +/* console.log ("\n"); + + chunks.forEach (function processChunk (chunk, idx) + { + chunk.modules.forEach (function (module) + { + console.log (module.userRequest); + console.log ("+"+module.resource); + console.log ("+"+module.index); + console.log (util.inspect (module, { showHidden: false, depth: 2 })); + }); + }); + + console.log ("\n"); +*/ }); + }); +}; diff --git a/web/html-service.php b/web/html-service.php index 747d54b6..e88a9ac6 100644 --- a/web/html-service.php +++ b/web/html-service.php @@ -14,7 +14,7 @@ class HtmlService extends Service $db = $this->db; if (!$this->isHttps () - && $db->getValue ('SELECT https FROM config') && !DEBUG_MODE) + && $db->getValue ('SELECT https FROM config') && !_DEBUG_MODE) { header ("Location: https://{$_SERVER['SERVER_NAME']}{$_SERVER['REQUEST_URI']}"); exit (0); diff --git a/web/service.php b/web/service.php index c7125f93..e37c8b1c 100755 --- a/web/service.php +++ b/web/service.php @@ -5,6 +5,11 @@ namespace Vn\Web; use Vn\Lib\Locale; use Vn\Lib\UserException; +const MIN = 60; +const HOUR = 60 * MIN; +const DAY = 24 * HOUR; +const WEEK = 7 * DAY; + /** * Thrown when user credentials could not be fetched. **/ @@ -129,9 +134,7 @@ abstract class Service function login () { $db = $this->db; - $user = NULL; - $wasLoged = isset ($_SESSION['user']); if (isset ($_POST['user']) && isset ($_POST['password'])) { @@ -175,7 +178,7 @@ abstract class Service // Registering the user access if (isset ($_SESSION['access']) - && (!isset ($_SESSION['visitUser']) || $wasLoged)) + && !isset ($_SESSION['visitUser'])) { $_SESSION['visitUser'] = TRUE; @@ -210,6 +213,28 @@ abstract class Service 'SELECT password FROM account.user WHERE name = #', [$user]); return $this->userDb = $this->app->createConnection ($user, $password); } + + /** + * Generates a JWT authentication token for the specified $user. + * + * @param {string} $user The user name + * @param {boolean} $remember Wether to create long live token + * @return {string} The JWT generated token + **/ + function createToken ($user, $remember = FALSE) + { + if ($remember) + $tokenLife = WEEK; + else + $tokenLife = 30 * MIN; + + $payload = [ + 'sub' => $user, + 'exp' => time () + $tokenLife + ]; + $key = $this->db->getValue ('SELECT jwtKey FROM config'); + return Jwt::encode ($payload, $key); + } /** * Runs a method. diff --git a/webpack.config.js b/webpack.config.js index d4e3c4f2..848d0494 100644 --- a/webpack.config.js +++ b/webpack.config.js @@ -1,34 +1,36 @@ var webpack = require ('webpack'); var path = require ('path'); +var SplitPlugin = require ('./split-plugin'); var devMode = true; module.exports = { - entry: ['./app.js'], - output: { + entry: ['./app.js'], + output: { path: path.join (__dirname, 'build'), filename: 'hedera-web.js', chunkFilename: 'chunk.[id].js', publicPath: devMode ? 'http://localhost:8080/build/' : 'build/', - }, - module: { + }, + module: { loaders: [ { test: /\.css$/, loader: 'style!css' }, { test: /\.json$/, loader: 'json' }, { test: /\.xml$/, loader: 'raw' } ] - }, - resolve: { + }, + resolve: { modulesDirectories: [__dirname +'/js', __dirname, 'node_modules'], fallback: process.env.NODE_PATH, - }, - resolveLoader: { + }, + resolveLoader: { fallback: process.env.NODE_PATH - }, + }, plugins: [ -/* new webpack.IgnorePlugin (new RegExp ('.{2}/(forms|pages|rest)')) + new SplitPlugin (), +/* new webpack.IgnorePlugin (new RegExp ('/.{2}/(forms|pages|rest)')) new webpack.optimize.UglifyJsPlugin ({minimize: true}) */ ] }; @@ -41,15 +43,15 @@ var langs = fs.readdirSync ('./locale'); for (var lang in languages) configs.push ( { - entry: './locale.js', - output: { + entry: './locale.js', + output: { path: __dirname +'/build', filename: 'lang.'+ lang +'.js' - }, - module: { + }, + module: { loaders: [ { test: /\.json$/, loader: 'json' } ] - } + } }); */