This commit is contained in:
Juan Ferrer Toribio 2016-10-04 17:27:49 +02:00
parent 6988bb9f84
commit 66bb2a57f2
32 changed files with 507 additions and 355 deletions

3
app.js
View File

@ -1,6 +1,5 @@
var Hedera = require ('hedera/hedera'); var Hedera = require ('hedera/hedera');
Vn.includeCss ('pages/main/style.css');
window.onload = function () window.onload = function ()
{ {
@ -25,7 +24,7 @@ function loadLocale (lang, cb)
switch (lang) switch (lang)
{ {
case 'ca': case 'ca':
require ([], function (){ require ([], function () {
cb (require.context ('locale/ca/js')); }); cb (require.context ('locale/ca/js')); });
break; break;
case 'es': case 'es':

View File

@ -7,7 +7,7 @@ Hedera.Address = new Class
{ {
this.$('model').setInfo ('a', 'address_view', 'hedera', ['id'], 'id'); this.$('model').setInfo ('a', 'address_view', 'hedera', ['id'], 'id');
this.$('model').setDefault ('customer_id', 'a', 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) ,onStatusChange: function (form)

View File

@ -36,11 +36,11 @@ Hedera.Connections = new Class
,onChangeUserClick: function (button, form) ,onChangeUserClick: function (button, form)
{ {
this.gui.supplantUser (form.get ('user_id'), this.gui.supplantUser (form.get ('user'),
this.onUserSupplant.bind (this)); this._onUserSupplant.bind (this));
} }
,onUserSupplant: function (userName) ,_onUserSupplant: function (userName)
{ {
this.hash.set ({'form': 'ecomerce/orders'}); this.hash.set ({'form': 'ecomerce/orders'});
} }

View File

@ -23,9 +23,9 @@
<db-model property="model" id="sessions" on-status-changed="onModelStatusChange"> <db-model property="model" id="sessions" on-status-changed="onModelStatusChange">
<custom> <custom>
SELECT s.id, e.user_id, c.Cliente, e.date_time login, is_new, 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 s.lastUpdate last_activity, a.platform, a.browser, a.version, u.name user
FROM user_session s FROM userSession s
JOIN visit_user e ON s.visit_user_id = e.id JOIN visit_user e ON s.userVisit = e.id
JOIN visit_access c ON e.access_id = c.id JOIN visit_access c ON e.access_id = c.id
JOIN visit_agent a ON c.agent_id = a.id JOIN visit_agent a ON c.agent_id = a.id
JOIN visit v ON a.visit_id = v.id JOIN visit v ON a.visit_id = v.id

View File

@ -10,33 +10,42 @@ Hedera.Shelves = new Class
,onConfigChange: function () ,onConfigChange: function ()
{ {
var c = this.$('config'); var fields = [
this.$('warehouse').value = c.get ('warehouse_id'); 'realm'
this.$('shelf').value = c.get ('shelf_id'); ,'family'
this.$('reign').value = c.get ('reino_id'); ,'warehouse'
this.$('family').value = c.get ('family_id'); ,'shelf'
this.$('filter').value = c.get ('name_prefix'); ,'namePrefix'
this.$('max-amount').value = c.get ('max_amount'); ,'maxAmount'
this.$('show-packing').value = c.get ('show_packing'); ,'reportTitle'
this.$('stack').value = c.get ('stack'); ,'showPacking'
this.$('report-title').value = c.get ('name'); ,'stack'
];
for (var i = 0; i < fields.length; i++)
this.$(fields[i]).value = this.$('config').get (fields[i]);
} }
,onPreviewClick: function () ,onPreviewClick: function ()
{ {
var fields = [
'family'
,'warehouse'
,'shelf'
,'namePrefix'
,'maxAmount'
,'reportTitle'
,'showPacking'
,'stack'
,'useIds'
,'date'
];
var batch = new Sql.Batch (); var batch = new Sql.Batch ();
batch.addValues ({
'shelf': this.$('shelf').value, for (var i = 0; i < fields.length; i++)
'wh': this.$('warehouse').value, batch.addValue (fields[i], this.$(fields[i]).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,
});
this.gui.openReport ('shelves-report', batch); this.gui.openReport ('shelves-report', batch);
} }
}); });

View File

@ -2,10 +2,10 @@
<vn-group> <vn-group>
<db-model property="model" id="configs-model"> <db-model property="model" id="configs-model">
<custom> <custom>
SELECT c.id, c.name, c.name_prefix, c.warehouse_id, c.family_id, SELECT c.id, c.name reportTitle, c.namePrefix, c.warehouse, c.family,
c.shelf_id, c.max_amount, c.show_packing, c.stack, t.reino_id c.shelf, c.maxAmount, c.showPacking, c.stack, t.reino_id realm
FROM shelf_config c FROM shelfConfig c
JOIN vn2008.Tipos t ON t.tipo_id = c.family_id JOIN vn2008.Tipos t ON t.tipo_id = c.family
</custom> </custom>
</db-model> </db-model>
</vn-group> </vn-group>
@ -36,8 +36,8 @@
</div> </div>
<div class="form-group"> <div class="form-group">
<label><t>Reign</t></label> <label><t>Reign</t></label>
<htk-combo id="reign"> <htk-combo id="realm">
<db-model property="model" id="reigns"> <db-model property="model" id="realms">
<custom> <custom>
SELECT id, reino FROM vn2008.reinos SELECT id, reino FROM vn2008.reinos
WHERE display != FALSE ORDER BY reino WHERE display != FALSE ORDER BY reino
@ -51,11 +51,11 @@
<db-model property="model"> <db-model property="model">
<custom> <custom>
SELECT tipo_id, Tipo FROM vn2008.Tipos SELECT tipo_id, Tipo FROM vn2008.Tipos
WHERE reino_id = #reign ORDER BY Tipo WHERE reino_id = #realm ORDER BY Tipo
</custom> </custom>
<sql-batch property="batch"> <sql-batch property="batch">
<custom> <custom>
<item name="reign" param="reign"/> <item name="realm" param="realm"/>
</custom> </custom>
</sql-batch> </sql-batch>
</db-model> </db-model>
@ -84,19 +84,19 @@
</div> </div>
<div class="form-group"> <div class="form-group">
<label><t>Name prefix</t></label> <label><t>Name prefix</t></label>
<htk-entry id="filter"/> <htk-entry id="namePrefix"/>
</div> </div>
<div class="form-group"> <div class="form-group">
<label><t>Limit amount per item</t></label> <label><t>Limit amount per item</t></label>
<htk-entry id="max-amount"/> <htk-entry id="maxAmount"/>
</div> </div>
<div class="form-group"> <div class="form-group">
<label><t>Title</t></label> <label><t>Title</t></label>
<htk-entry id="report-title"/> <htk-entry id="reportTitle"/>
</div> </div>
<div class="form-group"> <div class="form-group">
<label><t>Show packing</t></label> <label><t>Show packing</t></label>
<htk-check id="show-packing"/> <htk-check id="showPacking"/>
</div> </div>
<div class="form-group"> <div class="form-group">
<label><t>Stack different items</t></label> <label><t>Stack different items</t></label>
@ -104,7 +104,7 @@
</div> </div>
<div class="form-group"> <div class="form-group">
<label><t>Use ids instead of names</t></label> <label><t>Use ids instead of names</t></label>
<htk-check id="use-ids"/> <htk-check id="useIds"/>
</div> </div>
</div> </div>
</div> </div>

View File

@ -35,13 +35,13 @@
form="iter" form="iter"
column="id" column="id"
tip="_AccessAsUser" tip="_AccessAsUser"
image="image/incognito.svg" icon="incognito"
on-click="onChangeUserClick"/> on-click="onChangeUserClick"/>
<htk-button <htk-button
form="iter" form="iter"
column="id" column="id"
tip="_AccessLog" tip="_AccessLog"
image="image/gnome.svg" icon="gnome"
on-click="onAccessLogClick"/> on-click="onAccessLogClick"/>
<p class="important"> <p class="important">
<htk-text form="iter" column="Cliente"/> <htk-text form="iter" column="Cliente"/>

View File

@ -13,7 +13,7 @@ Hedera.Users = new Class
,onChangeUserClick: function (button, form) ,onChangeUserClick: function (button, form)
{ {
this.gui.supplantUser (form.get ('id'), this.gui.supplantUser (form.get ('name'),
this.onUserSupplant.bind (this)); this.onUserSupplant.bind (this));
} }

View File

@ -500,7 +500,7 @@ Vn.Filter = new Class
icon: 'close', icon: 'close',
alt: _('Close') alt: _('Close')
}); });
button.appendChild (icon); button.appendChild (icon.node);
var text = this._label = document.createTextNode (''); var text = this._label = document.createTextNode ('');
li.appendChild (text); li.appendChild (text);

View File

@ -215,7 +215,7 @@
<htk-popup id="success-dialog" modal="true" on-closed="onPopupClose"> <htk-popup id="success-dialog" modal="true" on-closed="onPopupClose">
<div property="child-node" class="dialog"> <div property="child-node" class="dialog">
<div> <div>
<img src="image/ok.svg" alt="_Ok"/> <htk-icon icon="ok" alt="_Ok"/>
<p><t>Order confirmed successfully</t></p> <p><t>Order confirmed successfully</t></p>
<div class="clear"/> <div class="clear"/>
</div> </div>

View File

@ -10,7 +10,7 @@ Hedera.New = new Class
{ {
this.$('model').mode = Db.Model.Mode.ON_DEMAND; this.$('model').mode = Db.Model.Mode.ON_DEMAND;
this.$('model').setDefault ('user_id', 'news', 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'; this.$('html-editor').id = 'html-editor';
tinymce.init ({ tinymce.init ({
@ -72,4 +72,3 @@ Hedera.New = new Class
}); });
}); });

View File

@ -1219,7 +1219,7 @@ Model.implement
if (pkValue) if (pkValue)
equalOp.exprs.add (new Sql.Value ({value: pkValue})); equalOp.exprs.add (new Sql.Value ({value: pkValue}));
else if (column.flags & Connection.Flag.AI && !useOldValues) 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 else
return null; return null;
} }

View File

@ -15,14 +15,12 @@ module.exports = new Class
this.link ({_conn: x}, this.link ({_conn: x},
{'loading-changed': this._onConnLoadChange }); {'loading-changed': this._onConnLoadChange });
var sql = 'SELECT default_form, image_dir, image_host FROM config;' var sql = 'SELECT name FROM customer_user;'
+'SELECT production_domain, test_domain FROM config;' +'SELECT default_form, image_dir, image_host FROM config;'
+'SELECT name FROM customer_user;' +'SELECT production_domain, test_domain FROM config;';
+'CALL form_list ();';
x.execQuery (sql, this.onMainQueryDone.bind (this)); x.execQuery (sql, this.onMainQueryDone.bind (this));
if (Vn.Cookie.check ('hedera_supplant')) this.loadMenu ();
this.supplantUser (Vn.Cookie.get ('hedera_supplant'));
} }
,get: function () ,get: function ()
{ {
@ -45,7 +43,6 @@ module.exports = new Class
,initialize: function (props) ,initialize: function (props)
{ {
this.builderInitString (Tpl); this.builderInitString (Tpl);
this.loadingCount = 0; this.loadingCount = 0;
this.$('background').onclick = function () {}; this.$('background').onclick = function () {};
@ -133,6 +130,11 @@ module.exports = new Class
,onMainQueryDone: function (resultSet) ,onMainQueryDone: function (resultSet)
{ {
// Retrieving the user name
var userName = resultSet.fetchValue ();
Vn.Node.setText (this.$('user-name'), userName);
// Retrieving configuration parameters // Retrieving configuration parameters
var res = resultSet.fetchResult (); var res = resultSet.fetchResult ();
@ -165,16 +167,19 @@ module.exports = new Class
else else
Vn.Node.hide (this.$('test-link')); Vn.Node.hide (this.$('test-link'));
// Retrieving the user name // Loading the default form
var userName = resultSet.fetchValue (); this._onFormChange ();
if (userName)
{
var span = this.$('user-name');
span.appendChild (document.createTextNode (userName));
} }
,loadMenu: function ()
{
var sql = 'CALL form_list ()';
this._conn.execQuery (sql, this._onMenuLoad.bind (this));
}
,_onMenuLoad: function (resultSet)
{
// Retrieving menu sections // Retrieving menu sections
var res = resultSet.fetchResult (); var res = resultSet.fetchResult ();
@ -191,103 +196,8 @@ module.exports = new Class
sectionMap[parent].push (i); sectionMap[parent].push (i);
} }
Vn.Node.removeChilds (this.$('main-menu'));
this.createMenu (res, sectionMap, null, 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 //++++++++++++++++++++++++++++++++++++++++++++++++++++++ Menu
@ -363,6 +273,96 @@ module.exports = new Class
} }
} }
,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 //++++++++++++++++++++++++++++++++++++++++++++++++++++++ Forms
,_onFormChange: function () ,_onFormChange: function ()
@ -501,50 +501,38 @@ module.exports = new Class
//++++++++++++++++++++++++++++++++++++++++++++++++++++++ Supplant //++++++++++++++++++++++++++++++++++++++++++++++++++++++ Supplant
,supplantUser: function (userId, callback) ,supplantUser: function (user, callback)
{ {
var batch = new Sql.Batch (); this._conn.supplantUser (user,
batch.addValue ('user', userId); this._onUserSupplant.bind (this, callback));
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);
} }
,_onUserSupplant: function (userId, callback, resultSet) ,_onUserSupplant: function (callback, supplantOk)
{ {
this._supplantClear (); if (!supplantOk)
Vn.Cookie.set ('hedera_supplant', userId); return;
resultSet.fetchResult (); this.loadMenu ();
var userName = resultSet.fetchValue ();
Vn.Node.setText (this.$('supplanted'), userName); var sql = 'SELECT name FROM customer_user';
Vn.Node.show (this.$('supplant')); this._conn.execQuery (sql, this._onSupplantName.bind (this));
if (callback) if (callback)
callback (); callback ();
} }
,_supplantClear: function () ,_onSupplantName: function (resultSet)
{ {
if (Vn.Cookie.check ('hedera_supplant')) var userName = resultSet.fetchValue ();
{ Vn.Node.setText (this.$('supplanted'), userName);
Vn.Node.hide (this.$('supplant')); Vn.Node.show (this.$('supplant'));
Vn.Cookie.unset ('hedera_supplant');
}
} }
,onSupplantExitClick: function () ,onSupplantExitClick: function ()
{ {
var query = 'UPDATE user_session_view SET user_id = account.user_get_id ()' Vn.Node.hide (this.$('supplant'));
this._conn.execQuery (query, this.supplantExit.bind (this)); this._conn.supplantEnd ();
} this.loadMenu ();
,supplantExit: function ()
{
this._supplantClear ();
this._onFormChange (); this._onFormChange ();
} }

View File

@ -1,10 +1,4 @@
body
{
overflow: auto;
height: 100%;
}
.vn-login .vn-login
{ {
color: #333; color: #333;
@ -55,12 +49,11 @@ body
{ {
position: absolute; position: absolute;
padding: 1em; padding: 1em;
max-width: 15em; max-width: 16em;
top: 50%; top: 50%;
left: 50%; left: 50%;
margin-top: -20em; margin-top: -20em;
margin-left: -8.5em; margin-left: -9em;
} }
@media (max-height: 630px) @media (max-height: 630px)
{ {

View File

@ -71,9 +71,15 @@
body body
{ {
color: #333;
font-family: 'Roboto', 'Verdana', 'Sans'; font-family: 'Roboto', 'Verdana', 'Sans';
background-color: #EEE;
color: #333;
position: absolute;
height: 100%;
width: 100%;
margin: 0; margin: 0;
overflow: auto;
z-index: -2;
} }
label, label,
button, button,

View File

@ -7,7 +7,7 @@ Sql = module.exports = {
,Batch : require ('./batch') ,Batch : require ('./batch')
,List : require ('./list') ,List : require ('./list')
,Expr : require ('./expr') ,Expr : require ('./expr')
,Valuee : require ('./value') ,Value : require ('./value')
,Field : require ('./field') ,Field : require ('./field')
,Function : require ('./function') ,Function : require ('./function')
,Operation : require ('./operation') ,Operation : require ('./operation')

View File

@ -34,7 +34,13 @@ module.exports = new Class
if (index !== undefined) if (index !== undefined)
return result.objects[index]; 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 this._parentResult.getById (objectId);
return null; return null;
@ -152,10 +158,12 @@ module.exports = new Class
var addedObject = this._addedMap[l.objectId]; var addedObject = this._addedMap[l.objectId];
if (addedObject) if (addedObject)
{
if (l.prop) if (l.prop)
objects[l.context.id][l.prop] = addedObject; objects[l.context.id][l.prop] = addedObject;
else else
objects[l.context.id].appendChild (addedObject); objects[l.context.id].appendChild (addedObject);
}
else else
this._showError ('Referenced unexistent object with id \'%s\'', this._showError ('Referenced unexistent object with id \'%s\'',
l.objectId); l.objectId);
@ -190,7 +198,7 @@ module.exports = new Class
for (var i = this._links.length - 1; i >= 0; i--) for (var i = this._links.length - 1; i >= 0; i--)
{ {
var l = this._links[i]; var l = this._links[i];
var contextId = this._contextMap[l.objectId] var contextId = this._contextMap[l.objectId];
if (contextId != undefined) if (contextId != undefined)
{ {

View File

@ -19,17 +19,21 @@ module.exports = new Class
,initialize: function () ,initialize: function ()
{ {
this.parent (); this.parent ();
this._token = this.fetchToken ();
}
if (localStorage.getItem ('vnToken')) ,fetchToken: function ()
this._token = localStorage.getItem ('vnToken'); {
if (sessionStorage.getItem ('vnToken')) 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. * 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 {String} password The user password
* @param {Boolean} remember Specifies if the user should be remembered * @param {Boolean} remember Specifies if the user should be remembered
* @param {Function} openCallback The function to call when operation is done * @param {Function} openCallback The function to call when operation is done
@ -105,6 +109,40 @@ module.exports = new Class
sessionStorage.removeItem ('vnToken'); 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 * Executes the specified REST service with the given params and calls
* the callback when response is received. * the callback when response is received.

View File

@ -21,7 +21,8 @@ module.exports =
Vn.Node.removeChilds (node); Vn.Node.removeChilds (node);
if (text) if (text)
node.appendChild (document.createTextNode (text)); node.appendChild (
node.ownerDocument.createTextNode (text));
} }
,addClass: function (node, className) ,addClass: function (node, className)

View File

@ -0,0 +1,5 @@
{
"Start": "Start"
,"End": "End"
,"Pallet": "Pallet"
}

View File

@ -0,0 +1,5 @@
{
"Start": "Inicio"
,"End": "Fin"
,"Pallet": "Palé"
}

View File

@ -10,13 +10,15 @@
"style-loader": "*", "style-loader": "*",
"file-loader": "*", "file-loader": "*",
"json-loader": "*", "json-loader": "*",
"raw-loader": "*" "raw-loader": "*",
"bundle-loader": "*"
}, },
"dependencies": { "dependencies": {
"mootools": "^1.5.2", "mootools": "^1.5.2",
"tinymce": "^4.4.3" "tinymce": "^4.4.3"
}, },
"scripts": { "scripts": {
"dev": "webpack-dev-server --devtool eval --inline --progress --colors" "dev": "webpack-dev-server --progress --colors --inline --hot",
"build": "rm build/* ; webpack --progress --colors"
} }
} }

View File

@ -12,7 +12,7 @@ if ($result = $db->query ('SELECT name, content FROM metatag'))
$result->free (); $result->free ();
} }
if (DEBUG_MODE) if (_DEBUG_MODE)
{ {
$this->includeJs ('http://localhost:8080/webpack-dev-server.js'); $this->includeJs ('http://localhost:8080/webpack-dev-server.js');
$this->includeJs ('http://localhost:8080/build/hedera-web.js'); $this->includeJs ('http://localhost:8080/build/hedera-web.js');

View File

@ -1,11 +0,0 @@
body
{
position: absolute;
height: 100%;
width: 100%;
z-index: -2;
background-color: #EEE;
overflow: hidden;
}

View File

@ -5,21 +5,22 @@ Hedera.ShelvesReport = new Class
,nItem: -1 ,nItem: -1
,nColors: 5 ,nColors: 5
,trayThickness: 2
,trayMargin: 5
,open: function (batch) ,open: function (batch)
{ {
this.batch = batch; this.batch = batch;
this.title = batch.getValue ('title'); this.title = batch.getValue ('reportTitle');
this.maxAmount = batch.getValue ('max-amount'); this.maxAmount = batch.getValue ('maxAmount');
this.showPacking = batch.getValue ('show-packing'); this.showPacking = batch.getValue ('showPacking');
this.stack = batch.getValue ('stack'); this.stack = batch.getValue ('stack');
this.useIds = batch.getValue ('use-ids'); this.useIds = batch.getValue ('useIds');
var query = var query =
'SELECT id, name, width, height, depth, max_height, tray_height, '+ 'SELECT id, name, nTrays, topTrayHeight, trayHeight, width, depth '+
'first_tray_elevation, tray_density, vspacing, hspacing '+
'FROM shelf WHERE id = #shelf; '+ '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); this.conn.execQuery (query, this.onQueryExec.bind (this), this.batch);
} }
@ -33,27 +34,26 @@ Hedera.ShelvesReport = new Class
// Calculates the scale // Calculates the scale
var maxWidth = 170; var maxWidth = 160;
var maxHeight = 200; 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) var scale = maxWidth / shelfWidth;
scale = maxHeight / res.get ('max_height');
// Gets the shelf dimensions if (shelfHeight * scale > maxHeight)
scale = maxHeight / shelfHeight;
// Calculates the shelf dimensions
var shelf = this.shelf = var shelf = this.shelf =
{ {
width: res.get ('width') * scale nTrays: res.get ('nTrays')
,height: res.get ('height') * scale ,trayHeight: res.get ('trayHeight') * scale
,topTrayHeight: res.get ('topTrayHeight') * scale
,width: res.get ('width') * scale
,depth: res.get ('depth') * 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 // Gets the items
@ -100,15 +100,11 @@ Hedera.ShelvesReport = new Class
alloc.shelfFunc = this.drawShelf.bind (this); alloc.shelfFunc = this.drawShelf.bind (this);
alloc.boxFunc = this.drawBox.bind (this); alloc.boxFunc = this.drawBox.bind (this);
alloc.stack = this.stack; alloc.stack = this.stack;
alloc.nTrays = Math.ceil ( alloc.nTrays = shelf.nTrays;
(shelf.height - shelf.firstTrayElevation) / alloc.width = shelf.width;
(shelf.trayHeight + shelf.trayDensity)
);
alloc.width = shelf.width - shelf.hspacing * 2;
alloc.depth = shelf.depth; alloc.depth = shelf.depth;
alloc.trayHeight = shelf.trayHeight - shelf.vspacing; alloc.trayHeight = shelf.trayHeight;
alloc.topTrayHeight = shelf.maxHeight - shelf.vspacing alloc.topTrayHeight = shelf.topTrayHeight;
- shelf.firstTrayElevation - (alloc.nTrays - 1) * shelf.trayHeight;
// Opens the report // Opens the report
@ -168,7 +164,7 @@ Hedera.ShelvesReport = new Class
// Draws the shelves // Draws the shelves
this.alloc.run (); this.alloc.run ();
this.drawShelfEnding (); this.drawShelfRange (this.lastItem, false);
} }
,drawShelf: function (allocator, item) ,drawShelf: function (allocator, item)
@ -191,53 +187,64 @@ Hedera.ShelvesReport = new Class
title.appendChild (this.doc.createTextNode (this.title)); title.appendChild (this.doc.createTextNode (this.title));
sheet.appendChild (title); sheet.appendChild (title);
var subtitle = this.doc.createElement ('h2'); if (this.subtitles)
subtitle.className = 'subtitle'; this.drawShelfRange (this.lastItem, false);
subtitle.appendChild (this.doc.createTextNode (this.getName (item)));
sheet.appendChild (subtitle);
this.drawShelfEnding (); this.subtitles = this.doc.createElement ('div');
this.lastSubtitle = subtitle; sheet.appendChild (this.subtitles);
this.drawShelfRange (item, true);
this.lastSubtitles = this.subtitles;
// Draws the shelf // 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'); var shelfDiv = this.shelfDiv = this.doc.createElement ('div');
shelfDiv.className = 'shelf'; shelfDiv.className = 'shelf';
shelfDiv.style.width = this.mm (shelf.width); shelfDiv.style.width = this.mm (trayWidth);
shelfDiv.style.height = this.mm (shelf.maxHeight); shelfDiv.style.height = this.mm (shelfHeight);
sheet.appendChild (shelfDiv); sheet.appendChild (shelfDiv);
// Draws trays // Draws trays
var lastTrayY = shelf.firstTrayElevation; for (var i = 0; i < shelf.nTrays; i++)
if (shelf.trayHeight > 0)
while (lastTrayY + shelf.trayDensity < shelf.height)
{ {
var tray = this.doc.createElement ('div'); var tray = this.doc.createElement ('div');
tray.className = 'tray'; tray.className = 'tray';
tray.style.width = this.mm (shelf.width); tray.style.bottom = this.mm ((shelf.trayHeight + this.trayThickness + this.trayMargin) * i);
tray.style.height = this.mm (shelf.trayDensity); tray.style.width = this.mm (trayWidth);
tray.style.bottom = this.mm (lastTrayY); tray.style.height = this.mm (this.trayThickness);
shelfDiv.appendChild (tray); shelfDiv.appendChild (tray);
lastTrayY += shelf.trayHeight + shelf.trayDensity;
} }
} }
,drawShelfEnding: function () ,drawShelfRange: function (item, isFirst)
{ {
if (this.lastSubtitle) var labelText = isFirst ? _('Start') : _('End');
this.lastSubtitle.appendChild (this.doc.createTextNode (
' - '+ this.getName (this.lastItem))); 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) if (!this.useIds)
return item.id.toLocaleString (); {
var packing = this.showPacking ? (' x'+ item.packing) : '';
return item.name + packing;
}
else else
return item.name.charAt (0).toUpperCase (); return item.id.toLocaleString ();
} }
,mm: function (size) ,mm: function (size)
@ -252,10 +259,10 @@ Hedera.ShelvesReport = new Class
var shelf = this.shelf; var shelf = this.shelf;
var x = allocator.trayX + shelf.hspacing; var x = allocator.trayX + this.trayMargin;
var y = allocator.trayY var y = allocator.trayY + this.trayThickness
+ shelf.firstTrayElevation + shelf.trayDensity + this.trayMargin * allocator.currentTray
+ allocator.currentTray * (shelf.trayHeight + shelf.trayDensity); + allocator.currentTray * (shelf.trayHeight + this.trayThickness);
var box = this.doc.createElement ('div'); var box = this.doc.createElement ('div');
box.className = 'box'; box.className = 'box';
@ -273,21 +280,28 @@ Hedera.ShelvesReport = new Class
Vn.Node.addClass (box, 'color'+ nColor); Vn.Node.addClass (box, 'color'+ nColor);
if (amount == 0 || allocator.firstShelfBox) if (amount == 0 || allocator.firstShelfBox)
{
var boxLabel = this.doc.createElement ('div');
if (this.useIds)
{ {
var fontSize = item.boxWidth / 5.2; var fontSize = item.boxWidth / 5.2;
if (fontSize > item.boxHeight - 1) if (fontSize > item.boxHeight - 1)
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.style.fontSize = this.mm (fontSize);
boxLabel.appendChild (this.doc.createTextNode (labelText));
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); box.appendChild (boxLabel);
} }

View File

@ -9,11 +9,17 @@ h1
text-overflow: ellipsis; text-overflow: ellipsis;
white-space: nowrap; white-space: nowrap;
overflow: hidden; overflow: hidden;
margin-bottom: 4mm;
}
label.range-label
{
color: #777;
} }
h2.subtitle h2.subtitle
{ {
margin: 0; margin: 0;
font-size: 400%; font-size: 200%;
margin-bottom: 2mm;
font-weight: normal; font-weight: normal;
color: #333; color: #333;
} }
@ -47,13 +53,16 @@ h1.page-number
border-bottom: 0; border-bottom: 0;
box-sizing: border-box; box-sizing: border-box;
} }
.box .box-label .box-label
{ {
text-align: right; font-size: 2.55mm;
font-size: 55%;
word-wrap: break-word; word-wrap: break-word;
box-sizing: border-box; box-sizing: border-box;
padding: 0 4%; padding: 1% 2%;
}
.box-label.id
{
text-align: right;
} }
.color0 .color0
{ {

View File

@ -1,27 +1,22 @@
<?php <?php
const MIN = 60;
const HOUR = 60 * MIN;
const DAY = 24 * HOUR;
const WEEK = 7 * DAY;
class Login extends Vn\Web\JsonRequest class Login extends Vn\Web\JsonRequest
{ {
function run ($db) function run ($db)
{ {
try {
$this->updateCredentials ($db); $this->updateCredentials ($db);
//$this->updateCredentialsLdap ($db);
}
catch (Exception $e)
{
error_log ($e->getMessage ());
}
if (!empty ($_POST['remember'])) $token = $this->service->createToken (
$tokenLife = WEEK; $_SESSION['user'],
else !empty ($_POST['remember'])
$tokenLife = 30 * MIN; );
$payload = [
'sub' => $_SESSION['user'],
'exp' => time () + $tokenLife
];
$key = $db->getValue ('SELECT jwtKey FROM config');
$token = Vn\Web\Jwt::encode ($payload, $key);
return [ return [
'login' => TRUE, '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. * 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'); $sshConf = $db->getRow ('SELECT host, user, password FROM ssh_config');
$ssh = ssh2_connect ($sshConf['host']); $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'])); $sshConf['user'], base64_decode ($sshConf['password']));
if (!$sshOk) if (!$sshAuth)
{ throw new Exception ("SSH authentication failed");
error_log ("Can't connect to SSH server {$sshConf['host']}");
return;
}
$user = $this->escape ($_SESSION['user']); $user = $this->escape ($_SESSION['user']);
$pass = $this->escape ($_POST['password']); $pass = $this->escape ($_POST['password']);
ssh2_exec ($ssh, "samba-tool user create \"$user\" \"$pass\""); $stream = ssh2_exec ($ssh, "samba-tool user create \"$user\" \"$pass\"");
} }
/** /**

13
rest/core/supplant.php Executable file
View File

@ -0,0 +1,13 @@
<?php
class Supplant extends Vn\Web\JsonRequest
{
const PARAMS = ['supplantUser'];
function run ($db)
{
return $this->service->createToken ($_REQUEST['supplantUser']);
}
}
?>

30
split-plugin.js Normal file
View File

@ -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");
*/ });
});
};

View File

@ -14,7 +14,7 @@ class HtmlService extends Service
$db = $this->db; $db = $this->db;
if (!$this->isHttps () 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']}"); header ("Location: https://{$_SERVER['SERVER_NAME']}{$_SERVER['REQUEST_URI']}");
exit (0); exit (0);

View File

@ -5,6 +5,11 @@ namespace Vn\Web;
use Vn\Lib\Locale; use Vn\Lib\Locale;
use Vn\Lib\UserException; 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. * Thrown when user credentials could not be fetched.
**/ **/
@ -129,9 +134,7 @@ abstract class Service
function login () function login ()
{ {
$db = $this->db; $db = $this->db;
$user = NULL; $user = NULL;
$wasLoged = isset ($_SESSION['user']);
if (isset ($_POST['user']) && isset ($_POST['password'])) if (isset ($_POST['user']) && isset ($_POST['password']))
{ {
@ -175,7 +178,7 @@ abstract class Service
// Registering the user access // Registering the user access
if (isset ($_SESSION['access']) if (isset ($_SESSION['access'])
&& (!isset ($_SESSION['visitUser']) || $wasLoged)) && !isset ($_SESSION['visitUser']))
{ {
$_SESSION['visitUser'] = TRUE; $_SESSION['visitUser'] = TRUE;
@ -211,6 +214,28 @@ abstract class Service
return $this->userDb = $this->app->createConnection ($user, $password); 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. * Runs a method.
**/ **/

View File

@ -1,6 +1,7 @@
var webpack = require ('webpack'); var webpack = require ('webpack');
var path = require ('path'); var path = require ('path');
var SplitPlugin = require ('./split-plugin');
var devMode = true; var devMode = true;
@ -28,7 +29,8 @@ module.exports =
fallback: process.env.NODE_PATH fallback: process.env.NODE_PATH
}, },
plugins: [ 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}) new webpack.optimize.UglifyJsPlugin ({minimize: true})
*/ ] */ ]
}; };