0
1
Fork 0
This commit is contained in:
Juan Ferrer Toribio 2017-03-09 13:30:39 +01:00
parent b7ec06ffdc
commit 043c11a4ed
26 changed files with 227 additions and 206 deletions

1
app.js
View File

@ -61,4 +61,3 @@ function loadLocale (cb)
cb (require.context ('js', true, /locale\/en.json$/)); });
}
}

2
debian/changelog vendored
View File

@ -1,4 +1,4 @@
hedera-web (2.0.1) stable; urgency=low
hedera-web (2.0.3) stable; urgency=low
* Initial Release.

2
debian/control vendored
View File

@ -9,7 +9,7 @@ Vcs-Git: git://www.verdnatura.es/var/git/hedera-web
Package: hedera-web
Architecture: all
Depends: apache2, php5-mysql, php5-mcrypt, php5-ssh2, php-vn-lib, php-acpu, nodejs, npm
Depends: apache2, php5-mysql, php5-mcrypt, php5-ssh2, php5-apcu, php-vn-lib, nodejs, npm
Suggests: php-text-captcha, php5-imap
Section: misc
Priority: optional

3
debian/install vendored
View File

@ -10,5 +10,6 @@ reports usr/share/hedera-web
rest usr/share/hedera-web
index.php usr/share/hedera-web
package.json usr/share/hedera-web
build usr/share/hedera-web
manifest.json usr/share/hedera-web
webpack.config.json usr/share/hedera-web
build usr/share/hedera-web

View File

@ -8,9 +8,10 @@
}
.basket .head
{
padding: 0;
padding-bottom: 2em;
margin: 0;
border-bottom: 1px solid #DDD;
margin-bottom: 1em;
}
.basket .head p
{
@ -22,13 +23,9 @@
/* Lines */
.basket .lines
{
padding: .8em 0;
}
.basket .line
{
padding: 1em 0;
padding: .5em 0;
}
.basket .line > .delete
{
@ -48,7 +45,7 @@
.basket .line > p
{
margin: .1em 0;
margin-left: 7.5em;
margin-left: 6em;
}
.basket .line .subtotal
{

View File

@ -26,7 +26,6 @@
</htk-text>
</p>
</div>
<div class="lines">
<htk-repeater form-id="iter" renderer="repeaterFunc">
<db-model id="items" property="model" updatable="true">
<custom>
@ -70,6 +69,5 @@
</custom>
</htk-repeater>
</div>
</div>
</div>
</vn>

View File

@ -2,14 +2,6 @@
{
color: #555;
}
.confirm .card
{
padding: 2.2em 2.5em;
}
.confirm .summary
{
margin-bottom: 1em;
}
.confirm .address
{
margin-top: .8em;
@ -119,4 +111,3 @@
{
margin: .1em 0;
}

View File

@ -31,13 +31,18 @@
{
padding: .5em 0;
}
.ticket .line > .photo
{
margin-right: 1em;
float: left;
border-radius: 50%;
height: 3.2em;
width: 3.2em;
}
.ticket .line p
{
margin: .1em 0;
}
.ticket .amount
{
float: left;
margin-left: 4em;
}
.ticket .subtotal
{

View File

@ -69,8 +69,9 @@
<htk-repeater form-id="iter" renderer="repeaterFunc">
<db-model property="model" id="movements">
<custom>
SELECT m.item_id, amount, concept, Categoria, Medida, Tallos, Color,
Abreviatura, IF(fixed != FALSE, price, NULL) price, fixed, discount
SELECT m.item_id, m.amount, m.concept,
IF(m.fixed != FALSE, m.price, NULL) price, m.fixed, m.discount,
o.Abreviatura, a.Categoria, a.Medida, a.Tallos, a.Color, a.Foto
FROM ticket_row_view m
INNER JOIN vn2008.Articles a
ON m.item_id = a.Id_Article AND ticket_id = #ticket
@ -86,6 +87,13 @@
</db-model>
<custom>
<div class="line">
<htk-image
form="iter"
column="Foto"
class="photo"
directory="catalog"
subdir="200x200"
full-dir="900x900"/>
<p class="concept">
<htk-text form="iter" column="concept"/>
<htk-text form="iter" column="Medida"/>
@ -94,9 +102,9 @@
<p class="amount">
<htk-text form="iter" column="amount"/> x
<htk-text form="iter" column="price" format="%.2d€"/>
</p>
<p class="subtotal">
<span class="subtotal">
<htk-text id="subtotal" format="%.2d€"/>
</span>
</p>
<div class="clear"/>
</div>

BIN
image/logo.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.4 KiB

View File

@ -5,4 +5,3 @@ require_once 'vn-autoload.php';
$webApp = new Vn\Web\App ('hedera-web');
$webApp->run ();

View File

@ -48,7 +48,7 @@ module.exports = new Class
gui.show ();
}
,_onLogout: function (gui)
,_onLogout: function ()
{
this.clearAutoLogin ();
this._freeGui ();

View File

@ -44,7 +44,7 @@ module.exports = new Class
this.$('spinner').stop ();
}
,show: function (firstLogin)
,show: function ()
{
document.body.appendChild (this.node);
@ -114,7 +114,7 @@ module.exports = new Class
if (!user)
Htk.Toast.showError (_('Please write your user name'));
else
this._conn.send ('core/recover-password', {'user': user},
this._conn.send ('core/recover-password', {'recoverUser': user},
this._onPasswordRecovered.bind (this));
}

View File

@ -100,4 +100,3 @@ module.exports = new Class
this.doc.body.appendChild (res.$('report'));
}
});

View File

@ -99,7 +99,7 @@ th.cell-radio
}
td.cell-button
{
max-width: 1px;
width: 1em;
text-align: center;
}
td.cell-button > button
@ -633,4 +633,3 @@ td.cell-image .htk-image
{
to {-webkit-transform: rotate(360deg);}
}

View File

@ -1,6 +1,6 @@
{
"name": "hedera-web",
"version": "2.0.1",
"version": "2.0.3",
"description": "Verdnatura web page",
"devDependencies": {
"assets-webpack-plugin": "^3.5.1",

View File

@ -1,47 +1,7 @@
<?php
$lang = Vn\Lib\Locale::get ();
$result = $db->query('SELECT name, content FROM metatag');
$wpConfig = json_decode (file_get_contents ('webpack.config.json'));
$buildDir = $wpConfig->buildDir;
$devServerPort = $wpConfig->devServerPort;
$host = $_SERVER['SERVER_NAME'];
$assets = new stdClass();
if (!_DEV_MODE)
{
$wpAssets = json_decode (file_get_contents ("$buildDir/webpack-assets.json"));
$manifestJs = $wpAssets->manifest->js;
$mainJs = $wpAssets->main->js;
unset ($wpAssets->manifest);
unset ($wpAssets->main);
foreach ($wpAssets as $name => $asset)
if (property_exists ($asset, 'js'))
$assets->$name = $asset->js;
}
else
{
$devServerPath = "http://$host:$devServerPort/$buildDir";
$manifestJs = "$devServerPath/manifest.js";
$mainJs = "$devServerPath/main.js";
unset ($wpConfig->entry->main);
foreach ($wpConfig->entry as $asset => $files)
$assets->$asset = "$devServerPath/$asset.js";
}
$jsFiles = [];
$jsFiles[] = $manifestJs;
foreach ($assets as $jsFile)
$jsFiles[] = $jsFile;
$jsFiles[] = $mainJs;
$result = $db->query ('SELECT name, content FROM metatag');
?>
<!DOCTYPE html>
@ -58,11 +18,11 @@ $jsFiles[] = $mainJs;
<meta name="theme-color" content="#009688"/>
<meta name="content-language" content="<?=$lang?>"/>
<?php while ($row = $result->fetch_object()): ?>
<?php while ($row = $result->fetch_object ()): ?>
<meta name="<?=$row->name?>" content="<?=$row->content?>"/>
<?php endwhile ?>
<?php foreach ($jsFiles as $js): ?>
<?php foreach (getWebpackAssets () as $js): ?>
<script type="text/javascript" src="<?=$js?>"></script>
<?php endforeach ?>

View File

@ -0,0 +1,3 @@
{
"Import": "Importe"
}

View File

@ -56,7 +56,7 @@
<htk-column-text title="_S1" column="Medida"/>
<htk-column-text title="_Cat" column="Categoria"/>
<htk-column-spin title="_Price" column="price" unit="€" digits="2"/>
<htk-column-spin title="_Subtotal" unit="€" digits="2" renderer="subtotalRenderer"/>
<htk-column-spin title="_Import" unit="€" digits="2" renderer="subtotalRenderer"/>
</htk-grid>
<p class="footer">
<htk-text format="%.2d€">

View File

@ -4,7 +4,7 @@ use Vn\Web;
class RecoverPassword extends Vn\Web\JsonRequest
{
const PARAMS = ['user'];
const PARAMS = ['recoverUser'];
function run ($db)
{
@ -13,14 +13,14 @@ class RecoverPassword extends Vn\Web\JsonRequest
FROM vn2008.Clientes c
JOIN account.user u ON u.id = c.Id_Cliente
WHERE u.name = #',
[$_REQUEST['user']]
[$_REQUEST['recoverUser']]
);
if (!($user['active'] && $user['mail']))
return TRUE;
$service = $this->service;
$token = $service->createToken ($_REQUEST['user'], FALSE, TRUE);
$token = $service->createToken ($_REQUEST['recoverUser'], FALSE, TRUE);
$url = $service->getUrl () ."#!form=account/conf&token=$token";
$report = new Vn\Web\Report ($db, 'recover-password', ['url' => $url]);

View File

@ -13,12 +13,20 @@ class HtmlService extends Service
{
function run ()
{
$eFlag =
E_ERROR
| E_USER_ERROR;
set_error_handler ([$this, 'errorHandler'], $eFlag);
set_exception_handler ([$this, 'errorHandler']);
$this->init ();
$db = $this->db;
if (!$this->isHttps ()
&& $db->getValue ('SELECT https FROM config') && !_DEV_MODE)
{
header ("Location: https://{$_SERVER['SERVER_NAME']}{$_SERVER['REQUEST_URI']}");
header ("Location: https://{$this->getUri()}");
exit (0);
}
@ -96,11 +104,12 @@ class HtmlService extends Service
//header ("Content-Security-Policy: default-src *; img-src *;");
}
function globalErrorHandler ()
function errorHandler ()
{
$this->printHeader ();
include (__DIR__.'/unavailable.html');
exit (0);
return FALSE;
}
function isMobile ()

View File

@ -3,27 +3,9 @@
function getUrl ($fileName)
{
if (file_exists ($fileName))
{
$hashes = apc_fetch ("$appName.hashes", $success);
if (!$success)
{
apc_store ("$appName.version", $version);
$hashes = [];
}
if (!isset ($hashes[$fileName]))
{
$hash = md5_file($fileName);
$hashes[$fileName] = $hash;
}
$mTime = '?'. strftime ('%G%m%d%H%M%S', filemtime ($fileName));
else
$hash = $hashes[$fileName];
$mTime = "?$hash";
}
else
$mTime = '';
$mTime = '?'. $this->getVersion ();
return $fileName.$mTime;
}
@ -37,3 +19,48 @@ function css ($fileName)
{
return '<link rel="stylesheet" type="text/css" href="'. getUrl ($fileName) .'"/>'."\n";
}
function getWebpackAssets ()
{
$wpConfig = json_decode (file_get_contents ('webpack.config.json'));
$buildDir = $wpConfig->buildDir;
$devServerPort = $wpConfig->devServerPort;
$host = $_SERVER['SERVER_NAME'];
$assets = new stdClass();
if (!_DEV_MODE)
{
$wpAssets = json_decode (file_get_contents ("$buildDir/webpack-assets.json"));
$manifestJs = $wpAssets->manifest->js;
$mainJs = $wpAssets->main->js;
unset ($wpAssets->manifest);
unset ($wpAssets->main);
foreach ($wpAssets as $name => $asset)
if (property_exists ($asset, 'js'))
$assets->$name = $asset->js;
}
else
{
$devServerPath = "http://$host:$devServerPort/$buildDir";
$manifestJs = "$devServerPath/manifest.js";
$mainJs = "$devServerPath/main.js";
unset ($wpConfig->entry->main);
foreach ($wpConfig->entry as $asset => $files)
$assets->$asset = "$devServerPath/$asset.js";
}
$jsFiles = [];
$jsFiles[] = $manifestJs;
foreach ($assets as $jsFile)
$jsFiles[] = $jsFile;
$jsFiles[] = $mainJs;
return $jsFiles;
}

View File

@ -17,6 +17,7 @@ class JsonService extends RestService
set_error_handler ([$this, 'errorHandler'], E_ALL);
set_exception_handler ([$this, 'exceptionHandler']);
$this->init ();
$this->startSession ();
$this->checkVersion ();

View File

@ -3,6 +3,8 @@
namespace Vn\Web;
use Vn\Lib;
use Vn\Lib\Locale;
use Vn\Lib\UserException;
/**
* Base class for REST application.
@ -15,10 +17,47 @@ class RestService extends Service
set_error_handler ([$this, 'errorHandler'], E_ALL);
set_exception_handler ([$this, 'exceptionHandler']);
$this->init ();
$this->startSession ();
$this->loadMethod (__NAMESPACE__.'\RestRequest');
}
/**
* Runs a REST method.
*/
function loadMethod ($class)
{
$db = $this->db;
$this->login ();
$method = $this->app->loadMethod (
$_REQUEST['method'], $class, './rest');
$method->service = $this;
if ($method::SECURITY == Security::DEFINER)
{
$isAuthorized = $db->getValue ('SELECT userCheckRestPriv (#)',
[$_REQUEST['method']]);
if (!$isAuthorized)
throw new UserException (s('You don\'t have enough privileges'));
$methodDb = $db;
}
else
$methodDb = $this->getUserDb ($_SESSION['user']);
if ($method::PARAMS !== NULL && !$method->checkParams ($_REQUEST, $method::PARAMS))
throw new UserException (s('Missing parameters'));
Locale::addPath ("rest/{$_REQUEST['method']}");
$res = $method->run ($methodDb);
$db->query ('CALL account.userLogout ()');
return $res;
}
function statusFromException ($e)
{
try {

View File

@ -37,7 +37,11 @@ abstract class Service
function __construct ($app)
{
$this->app = $app;
$this->db = $app->getSysConn ();
}
function init ()
{
$this->db = $this->app->getSysConn ();
}
/**
@ -45,7 +49,7 @@ abstract class Service
*/
function startSession ()
{
$db = $this->db;
$db = $this->app->getSysConn ();
ini_set ('session.cookie_secure', $this->isHttps ());
ini_set ('session.hash_function', 'sha256');
@ -147,7 +151,10 @@ abstract class Service
catch (\Vn\Db\Exception $e)
{
if ($e->getMessage () == 'INVALID_CREDENTIALS')
{
sleep (3);
throw new BadLoginException ();
}
else
throw $e;
}
@ -259,42 +266,6 @@ abstract class Service
return Jwt::encode ($payload, $key);
}
/**
* Runs a method.
*/
function loadMethod ($class)
{
$db = $this->db;
$this->login ();
$method = $this->app->loadMethod (
$_REQUEST['method'], $class, './rest');
$method->service = $this;
if ($method::SECURITY == Security::DEFINER)
{
$isAuthorized = $db->getValue ('SELECT userCheckRestPriv (#)',
[$_REQUEST['method']]);
if (!$isAuthorized)
throw new UserException (s('You don\'t have enough privileges'));
$methodDb = $db;
}
else
$methodDb = $this->getUserDb ($_SESSION['user']);
if ($method::PARAMS !== NULL && !$method->checkParams ($_REQUEST, $method::PARAMS))
throw new UserException (s('Missing parameters'));
Locale::addPath ("rest/{$_REQUEST['method']}");
$res = $method->run ($methodDb);
$db->query ('CALL account.userLogout ()');
return $res;
}
/**
* Obtains the application version number. It is extracted and
* cached from package.json file.
@ -345,6 +316,16 @@ abstract class Service
return isset ($_SERVER['HTTPS']) && $_SERVER['HTTPS'] == 'on';
}
/**
* Returns the current URI without the GET part.
*
* @return string The current URI
*/
function getUri ()
{
return "{$_SERVER['SERVER_NAME']}{$_SERVER['REQUEST_URI']}";
}
/**
* Returns the current URL without the GET part.
*
@ -353,7 +334,7 @@ abstract class Service
function getUrl ()
{
$proto = $this->isHttps () ? 'https' : 'http';
return "$proto://{$_SERVER['SERVER_NAME']}{$_SERVER['REQUEST_URI']}";
return "$proto://{$this->getUri()}";
}
}

View File

@ -3,36 +3,41 @@
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
<title>No disponible - Verdnatura</title>
<title>Not available - Verdnatura</title>
<style type="text/css">
body
{
font-size: 16pt;
font-family: Sans;
}
div
{
position: absolute;
width: 36em;
width: 32em;
margin-top: -7em;
margin-left: -18em;
top: 50%;
left: 50%;
text-align: center;
}
div h2
{
font-weight: normal;
}
div a
{
color: #444;
color: #2962FF;
text-decoration: none;
}
</style>
</head>
<body>
<div>
<h2>
Estamos teniendo problemas; por favor,
espera unos minutos e int&eacute;ntalo de nuevo.
We are having problems; Please wait a few minutes and try again.
</h2>
<a href="javascript: location.reload (true)">
Intentarlo de nuevo
Try it again
</a>
</div>
</body>