Merge pull request 'refs #6200 test into master' (!46) from test into master
gitea/hedera-web/pipeline/head Something is wrong with the build of this commit Details

Reviewed-on: #46
This commit is contained in:
Juan Ferrer 2023-10-10 08:21:49 +00:00
commit c7159a1e13
30 changed files with 383 additions and 205 deletions

2
debian/changelog vendored
View File

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

View File

@ -7,79 +7,7 @@ export default new Class({
activate() { activate() {
this.$.userModel.setInfo('c', 'myClient', 'hedera'); this.$.userModel.setInfo('c', 'myClient', 'hedera');
this.$.userModel.setInfo('u', 'myUser', 'account'); this.$.userModel.setInfo('u', 'myUser', 'account');
this.$.changePassword.conn = this.conn
if (this.hash.$.verificationToken) this.$.changePassword.user = this.gui.user
this.onPassChangeClick();
} }
});
,onPassChangeClick() {
this.$.oldPassword.value = '';
this.$.newPassword.value = '';
this.$.repeatPassword.value = '';
var verificationToken = this.hash.$.verificationToken;
this.$.oldPassword.style.display = verificationToken ? 'none' : 'block';
this.$.changePassword.show();
if (verificationToken)
this.$.newPassword.focus();
else
this.$.oldPassword.focus();
}
,async onPassModifyClick() {
const form = this.$.changePassword.node;
Vn.Node.disableInputs(form);
try {
const oldPassword = this.$.oldPassword.value;
const newPassword = this.$.newPassword.value;
const repeatedPassword = this.$.repeatPassword.value;
try {
if (newPassword == '' && repeatedPassword == '')
throw new Error(_('Passwords empty'));
if (newPassword !== repeatedPassword)
throw new Error(_('Passwords doesn\'t match'));
} catch (err) {
return Htk.Toast.showError(err.message);
}
const verificationToken = this.hash.$.verificationToken;
const params = {newPassword};
try {
if (verificationToken) {
params.verificationToken = verificationToken;
await this.conn.send('user/restore-password', params);
} else {
let userId = this.gui.user.id;
params.oldPassword = oldPassword;
await this.conn.patch(
`Accounts/${userId}/changePassword`, params);
}
} catch(err) {
Htk.Toast.showError(err.message);
if (verificationToken)
this.$.newPassword.select();
else
this.$.oldPassword.select();
return;
}
this.hash.unset('verificationToken');
await this.conn.open(this.gui.user.name, newPassword);
this.$.changePassword.hide();
} finally {
Vn.Node.disableInputs(form, false);
}
Htk.Toast.showMessage(_('Password changed!'));
}
,onPassInfoClick() {
this.$.passwordInfo.show();
}
});

View File

@ -1,11 +1,5 @@
<vn> <vn>
<vn-group> <vn-group>
<db-form v-model="passwordForm">
<db-model property="model">
SELECT length, nAlpha, nUpper, nDigits, nPunct
FROM account.userPassword
</db-model>
</db-form>
<db-form id="user-form"> <db-form id="user-form">
<db-model property="model" id="user-model" updatable="true"> <db-model property="model" id="user-model" updatable="true">
SELECT u.id, u.name, u.email, u.nickname, SELECT u.id, u.name, u.email, u.nickname,
@ -27,7 +21,7 @@
<htk-bar-button <htk-bar-button
icon="lock_reset" icon="lock_reset"
tip="_Change password" tip="_Change password"
on-click="this.onPassChangeClick()"/> on-click="this.$.changePassword.open()"/>
</div> </div>
<div id="form" class="conf"> <div id="form" class="conf">
<div class="form box vn-w-sm vn-pa-lg"> <div class="form box vn-w-sm vn-pa-lg">
@ -74,64 +68,5 @@
</div> </div>
</div> </div>
</div> </div>
<htk-popup <htk-change-password id="change-password"/>
id="change-password"
modal="true">
<div property="child-node" class="htk-dialog vn-w-xs vn-pa-lg">
<div class="form">
<h5 class="vn-mb-md">
<t>Change password</t>
</h5>
<input
id="old-password"
type="password"
placeholder="_Old password"/>
<input
id="new-password"
type="password"
placeholder="_New password"
autocomplete="new-password"/>
<input
id="repeat-password"
type="password"
placeholder="_Repeat password"
autocomplete="new-password"/>
</div>
<div class="button-bar">
<button class="thin" on-click="this.onPassModifyClick()">
<t>Modify</t>
</button>
<button class="thin" on-click="this.onPassInfoClick()">
<t>Requirements</t>
</button>
<div class="clear"/>
</div>
</div>
</htk-popup>
<htk-popup
id="password-info"
modal="true">
<div property="child-node" class="htk-dialog pass-info vn-w-xs vn-pa-lg">
<h5 class="vn-mb-md">
<t>Password requirements</t>
</h5>
<ul>
<li>
{{passwordForm.length}} <t>characters long</t>
</li>
<li>
{{passwordForm.nAlpha}} <t>alphabetic characters</t>
</li>
<li>
{{passwordForm.nUpper}} <t>capital letters</t>
</li>
<li>
{{passwordForm.nDigits}} <t>digits</t>
</li>
<li>
{{passwordForm.nPunct}} <t>symbols</t>
</li>
</ul>
</div>
</htk-popup>
</vn> </vn>

View File

@ -7,8 +7,8 @@ export default new Class({
,activate() { ,activate() {
if (!this.hash.$.to) if (!this.hash.$.to)
this.hash.assign({ this.hash.assign({
from: new Date(), from: Date.vnNew(),
to: new Date() to: Date.vnNew()
}); });
} }
}); });

View File

@ -14,7 +14,7 @@ export default new Class({
,refreshCaptcha() { ,refreshCaptcha() {
params = { params = {
srv: 'rest:misc/captcha', srv: 'rest:misc/captcha',
stamp: new Date().getTime() stamp: Date.vnNew().getTime()
}; };
this.$.captchaImg.src = '?'+ Vn.Url.makeUri(params); this.$.captchaImg.src = '?'+ Vn.Url.makeUri(params);
} }

View File

@ -202,6 +202,12 @@ const Catalog = new Class({
this.hideMenu(); this.hideMenu();
} }
,itemRenderer(builder, form) {
var minQuantity = builder.$.minQuantity;
minQuantity.style.display = form.$.minQuantity
? 'block' : 'hidden';
}
,realmRenderer(builder, form) { ,realmRenderer(builder, form) {
var link = builder.$.link; var link = builder.$.link;
@ -273,6 +279,8 @@ const Catalog = new Class({
orderId: this.orderId orderId: this.orderId
}); });
this.$.cardPopup.show(event.currentTarget); this.$.cardPopup.show(event.currentTarget);
this.$.cardMinQuantity.style.display = form.$.minQuantity
? 'block' : 'none';
} }
,onAddLotClick(column, value, row) { ,onAddLotClick(column, value, row) {
@ -317,7 +325,7 @@ const Catalog = new Class({
} }
if (amountSum > 0) { if (amountSum > 0) {
this.conn.execQuery(sql); await this.conn.execQuery(sql);
var itemName = this.$.$card.get('item'); var itemName = this.$.$card.get('item');
Htk.Toast.showMessage( Htk.Toast.showMessage(

View File

@ -46,3 +46,4 @@ NoMoreAmountAvailable: No hi ha més quantitat disponible
MinimalGrouping: Empaquetat mínim MinimalGrouping: Empaquetat mínim
Available: Disponible Available: Disponible
GroupingPrice: Preu per grup GroupingPrice: Preu per grup
MinimalQuantity: Quantitat mínima

View File

@ -46,3 +46,4 @@ NoMoreAmountAvailable: No more amount available
MinimalGrouping: Minimal packing MinimalGrouping: Minimal packing
Available: Available Available: Available
GroupingPrice: Price per group GroupingPrice: Price per group
MinimalQuantity: Minimal quantity

View File

@ -46,3 +46,4 @@ NoMoreAmountAvailable: No hay más cantidad disponible
MinimalGrouping: Empaquetado mínimo MinimalGrouping: Empaquetado mínimo
Available: Disponible Available: Disponible
GroupingPrice: Precio per grupo GroupingPrice: Precio per grupo
MinimalQuantity: Cantidad mínima

View File

@ -46,3 +46,4 @@ NoMoreAmountAvailable: Pas plus disponible
MinimalGrouping: Emballage minimal MinimalGrouping: Emballage minimal
Available: Disponible Available: Disponible
GroupingPrice: Prix par groupe GroupingPrice: Prix par groupe
MinimalQuantity: Quantité minimum

View File

@ -46,3 +46,4 @@ NoMoreAmountAvailable: Não há mais quantidade disponível
MinimalGrouping: Embalagem mínima MinimalGrouping: Embalagem mínima
Available: Disponível Available: Disponível
GroupingPrice: Preço por grupo GroupingPrice: Preço por grupo
MinimalQuantity: Quantidade mínima

View File

@ -192,6 +192,25 @@
margin: 0; margin: 0;
margin-bottom: 1px; margin-bottom: 1px;
} }
& > .min-quantity {
bottom: 32px;
right: 0;
}
}
.min-quantity {
position: absolute;
display: none;
bottom: 30px;
right: 0;
font-size: .8rem;
color: #a44;
cursor: pointer;
& > span {
font-size: 16px;
vertical-align: middle;
}
} }
/* Tags */ /* Tags */
@ -351,6 +370,7 @@
& > .top { & > .top {
padding: 14px; padding: 14px;
position: relative;
& > .item-info { & > .item-info {
margin-left: 126px; margin-left: 126px;
@ -371,6 +391,11 @@
margin-top: 15px 0; margin-top: 15px 0;
font-size: .9rem; font-size: .9rem;
} }
& > .min-quantity {
bottom: 0;
right: 0;
padding: 14px;
}
} }
& > .lots-grid { & > .lots-grid {
border-top: 1px solid #DDD; border-top: 1px solid #DDD;

View File

@ -117,7 +117,7 @@
SELECT i.id, i.longName item, i.subName, SELECT i.id, i.longName item, i.subName,
i.tag5, i.value5, i.tag6, i.value6, i.tag5, i.value5, i.tag6, i.value6,
i.tag7, i.value7, i.tag8, i.value8, i.tag7, i.value7, i.tag8, i.value8,
i.relevancy, i.size, i.category, i.relevancy, i.size, i.category, i.minQuantity,
k.name ink, p.name producer, o.name origin, k.name ink, p.name producer, o.name origin,
b.available, b.price, b.`grouping`, b.available, b.price, b.`grouping`,
i.image, im.updated i.image, im.updated
@ -149,7 +149,8 @@
id="grid-view" id="grid-view"
empty-message="_Choose filter from right menu" empty-message="_Choose filter from right menu"
form-id="item" form-id="item"
model="items"> model="items"
renderer="itemRenderer">
<custom> <custom>
<div <div
id="item-box" id="item-box"
@ -203,6 +204,12 @@
{{Vn.Value.format(item.price, '%.02d€')}} {{Vn.Value.format(item.price, '%.02d€')}}
</span> </span>
</div> </div>
<div id="min-quantity" class="min-quantity" title="_MinimalQuantity">
<span class="htk-icon material-symbols-rounded">
production_quantity_limits
</span>
{{item.minQuantity}}
</div>
</div> </div>
</div> </div>
</custom> </custom>
@ -461,6 +468,12 @@
</tr> </tr>
</custom> </custom>
</htk-repeater> </htk-repeater>
<div id="card-min-quantity" class="min-quantity" title="_MinimalQuantity">
<span class="htk-icon material-symbols-rounded">
production_quantity_limits
</span>
{{card.minQuantity}}
</div>
</div> </div>
<htk-grid class="lots-grid" show-header="false"> <htk-grid class="lots-grid" show-header="false">
<db-model <db-model

View File

@ -8,7 +8,7 @@ export default new Class({
this.autoStepLocked = true; this.autoStepLocked = true;
this.$.assistant.stepsIndex = this.agencySteps; this.$.assistant.stepsIndex = this.agencySteps;
this.today = new Date(); this.today = Date.vnNew();
this.today.setHours(0, 0, 0, 0); this.today.setHours(0, 0, 0, 0);
}, },
@ -22,8 +22,8 @@ export default new Class({
let date; let date;
const row = orderForm.$ || defaultsForm.$ || {}; const row = orderForm.$ || defaultsForm.$ || {};
if (!date || date.getTime() < (new Date()).getTime()) { if (!date || date.getTime() < (Date.vnNew()).getTime()) {
date = new Date(); date = Date.vnNew();
date.setHours(0, 0, 0, 0); date.setHours(0, 0, 0, 0);
let addDays = 0; let addDays = 0;

View File

@ -6,7 +6,7 @@ export default new Class({
activate() { activate() {
this.$.lot.assign({ this.$.lot.assign({
date: new Date(), date: Date.vnNew(),
useIds: false useIds: false
}); });
}, },

View File

@ -65,3 +65,20 @@ Account: Compte
Addresses: Adreces Addresses: Adreces
Load an order: Si us plau carrega una comanda pendent a la cistella o en comença una de nova Load an order: Si us plau carrega una comanda pendent a la cistella o en comença una de nova
Old password: Contrasenya antiga
New password: Nova contrasenya
Repeat password: Repetir contrasenya
Requirements: Requisits
Modify: Modificar
Password requirements: Requisits de contrasenya
characters long: caràcters de longitud
alphabetic characters: caràcters alfabètics
capital letters: majúscules
digits: dígits
symbols: símbols
Password changed!: Contrasenya modificada!
Password doesn't meet the requirements: ''
Passwords doesn't match: Les contrasenyes no coincideixen!
Passwords empty: Les contrasenyes en blanc
Change password: Canvia la contrasenya

View File

@ -65,3 +65,22 @@ Account: Cuenta
Addresses: Direcciones Addresses: Direcciones
Load an order: Por favor carga un pedido pendiente en la cesta o empieza uno nuevo Load an order: Por favor carga un pedido pendiente en la cesta o empieza uno nuevo
Old password: Contaseña antigua
New password: Nueva contraseña
Repeat password: Repetir contraseña
Requirements: Requisitos
Modify: Modificar
Password requirements: Requisitos de constraseña
characters long: carácteres de longitud
alphabetic characters: carácteres alfabéticos
capital letters: letras mayúsculas
digits: dígitos
symbols: 'símbolos. Ej: $%&.'
Password changed!: ¡Contraseña modificada!
Password doesn't meet the requirements: >-
La nueva contraseña no reune los requisitos de seguridad necesarios, pulsa en
info para más detalle
Passwords doesn't match: ¡Las contraseñas no coinciden!
Passwords empty: Contraseña vacía
Change password: Cambiar contraseña

View File

@ -65,3 +65,20 @@ Account: Compte
Addresses: Adresses Addresses: Adresses
Load an order: Veuillez télécharger une commande en attente dans le panier ou en démarrer une nouvelle Load an order: Veuillez télécharger une commande en attente dans le panier ou en démarrer une nouvelle
Old password: Ancien mot de passe
New password: Nouveau mot de passe
Repeat password: Répéter le mot de passe
Requirements: Exigences
Modify: Modifier
Password requirements: Mot de passe exigences
characters long: Longs caractères
alphabetic characters: les caractères alphabétiques
capital letters: lettres majuscules
digits: chiffres
symbols: 'symboles. Ej: $%&.'
Password changed!: Mot de passe modifié!
Password doesn't meet the requirements: ''
Passwords doesn't match: Les mots de passe ne correspondent pas!
Passwords empty: ''
Change password: Changer le mot de passe

View File

@ -63,3 +63,20 @@ Account: Conta
Addresses: Moradas Addresses: Moradas
Load an order: Carregue um pedido pendente no carrinho ou inicie um novo Load an order: Carregue um pedido pendente no carrinho ou inicie um novo
Old password: Palavra-passe antiga
New password: Nova Palavra-passe
Repeat password: Repetir Palavra-passe
Requirements: Requisitos
Modify: Modificar
Password requirements: Requisitos de Palavra-passe
characters long: caracteres
alphabetic characters: caracteres alfabéticos
capital letters: letras maiúsculas
digits: dígitos
symbols: 'símbolos. Ej: $%&.'
Password changed!: Palavra-passe Modificada!
Password doesn't meet the requirements: Palavra-passe não atende aos requisitos
Passwords doesn't match: As Palavras-Passe não coincidem!
Passwords empty: Palavra-passe vazia
Change password: Mudar Palavra-passe

View File

@ -26,6 +26,12 @@ module.exports = new Class({
self._onSubmit(); self._onSubmit();
return false; return false;
}; };
if(this.hash.$.verificationToken){
this.$.changePassword.conn = this.conn;
this.$.changePassword.token = this.hash.$.verificationToken;
this.$.changePassword.open();
}
} }
,_onConnLoadChange(conn, isLoading) { ,_onConnLoadChange(conn, isLoading) {
@ -94,7 +100,11 @@ module.exports = new Class({
return; return;
} }
await this._conn.send('user/recover-password', {recoverUser}); await this.conn.post('VnUsers/recoverPassword', {
user: recoverUser,
app: 'hedera'
});
Htk.Toast.showMessage(_('A mail has been sent wich you can recover your password')); Htk.Toast.showMessage(_('A mail has been sent wich you can recover your password'));
} }
}); });

View File

@ -54,4 +54,5 @@
</div> </div>
</div> </div>
</div> </div>
<htk-change-password id="change-password"/>
</vn> </vn>

View File

@ -141,7 +141,7 @@ module.exports = new Class({
} }
,goToCurrentMonth() { ,goToCurrentMonth() {
var date = new Date(); var date = Date.vnNew();
this.goToMonth(date.getFullYear(), date.getMonth()); this.goToMonth(date.getFullYear(), date.getMonth());
} }
@ -179,7 +179,7 @@ module.exports = new Class({
// Marks the current day // Marks the current day
var today = new Date(); var today = Date.vnNew();
if (this.year == today.getFullYear() if (this.year == today.getFullYear()
&& this.month == today.getMonth()) { && this.month == today.getMonth()) {

View File

@ -0,0 +1,111 @@
var Component = require('vn/component');
var Toast = require('../toast');
var Tpl = require('./ui.xml').default;
/**
* A change password popup.
*/
module.exports = new Class({
Extends: Component,
Tag: 'htk-change-password',
Properties: {
/**
* The token url.
*/
token: {
type: String
,set(value) {
this._token = value;
}
,get() {
return this._token;
}
},
conn: {
type: Db.Connection
,set(x) {
this._conn = x
}
,get() {
return this._conn;
}
},
user: {
type: Object
}
},
initialize(props) {
Component.prototype.initialize.call(this, props);
},
async open() {
this.passwordForm = await this.conn.get('UserPasswords/findOne')
this.loadTemplateFromString(Tpl);
this.$.oldPassword.value = '';
this.$.newPassword.value = '';
this.$.repeatPassword.value = '';
this.$.oldPassword.style.display = this.token ? 'none' : 'block';
this.$.changePassword.open();
if (this.token)
this.$.newPassword.focus();
else
this.$.oldPassword.focus();
},
async onPassModifyClick() {
const form = this.$.changePassword.node;
Vn.Node.disableInputs(form);
try {
const oldPassword = this.$.oldPassword.value;
const newPassword = this.$.newPassword.value;
const repeatedPassword = this.$.repeatPassword.value;
try {
if (newPassword == '' && repeatedPassword == '')
throw new Error(_('Passwords empty'));
if (newPassword !== repeatedPassword)
throw new Error(_('Passwords doesn\'t match'));
} catch (err) {
return Toast.showError(err.message);
}
const params = {newPassword};
try {
if (this.token) {
const headers = {
Authorization: this.token
};
await this.conn.post('VnUsers/reset-password', params, {headers});
} else {
params.userId = this.user.id;
params.oldPassword = oldPassword;
await this.conn.patch(`Accounts/change-password`, params);
}
} catch(err) {
Toast.showError(err.message);
if (this.token)
this.$.newPassword.select();
else
this.$.oldPassword.select();
return;
}
if(this.user)
await this.conn.open(this.user.name, newPassword);
this.$.changePassword.hide();
} finally {
Vn.Node.disableInputs(form, false);
}
Toast.showMessage(_('Password changed!'));
}
});

View File

@ -0,0 +1,62 @@
<vn>
<htk-popup
id="change-password"
modal="true">
<div property="child-node" class="htk-dialog vn-w-xs vn-pa-lg">
<div class="form">
<h5 class="vn-mb-md">
<t>Change password</t>
</h5>
<input
id="old-password"
type="password"
placeholder="_Old password"/>
<input
id="new-password"
type="password"
placeholder="_New password"
autocomplete="new-password"/>
<input
id="repeat-password"
type="password"
placeholder="_Repeat password"
autocomplete="new-password"/>
</div>
<div class="button-bar">
<button class="thin" on-click="this.onPassModifyClick()">
<t>Modify</t>
</button>
<button class="thin" on-click="this.$.passwordInfo.show()">
<t>Requirements</t>
</button>
<div class="clear"/>
</div>
</div>
</htk-popup>
<htk-popup
id="password-info"
modal="true">
<div property="child-node" class="htk-dialog pass-info vn-w-xs vn-pa-lg">
<h5 class="vn-mb-md">
<t>Password requirements</t>
</h5>
<ul>
<li>
{{this.passwordForm.length}} <t>characters long</t>
</li>
<li>
{{this.passwordForm.nAlpha}} <t>alphabetic characters</t>
</li>
<li>
{{this.passwordForm.nUpper}} <t>capital letters</t>
</li>
<li>
{{this.passwordForm.nDigits}} <t>digits</t>
</li>
<li>
{{this.passwordForm.nPunct}} <t>symbols</t>
</li>
</ul>
</div>
</htk-popup>
</vn>

View File

@ -3,22 +3,23 @@ require('db/db');
require('./style/index.scss'); require('./style/index.scss');
Htk = module.exports = { Htk = module.exports = {
Popup : require('./popup') Popup : require('./popup')
,Dialog : require('./dialog') ,Dialog : require('./dialog')
,Toast : require('./toast') ,Toast : require('./toast')
,Repeater : require('./repeater') ,Repeater : require('./repeater')
,Grid : require('./grid') ,Grid : require('./grid')
,Spinner : require('./spinner') ,Spinner : require('./spinner')
,Icon : require('./icon') ,Icon : require('./icon')
,FullImage : require('./full-image') ,FullImage : require('./full-image')
,ImageEditor : require('./image-editor') ,ImageEditor : require('./image-editor')
,Assistant : require('./assistant') ,Assistant : require('./assistant')
,AssistantBar : require('./assistant-bar') ,AssistantBar : require('./assistant-bar')
,Step : require('./step') ,Step : require('./step')
,Loader : require('./loader') ,Loader : require('./loader')
,List : require('./list') ,List : require('./list')
,Field : require('./field') ,Field : require('./field')
,Column : require('./column') ,Column : require('./column')
,ChangePassword : require('./change-password')
}; };
var Fields = { var Fields = {

View File

@ -192,7 +192,7 @@ module.exports = new Class({
} }
,_onFileUpload(cell) { ,_onFileUpload(cell) {
this._stamp = new Date().getTime(); this._stamp = Date.vnNew().getTime();
this._refreshSrc(cell); this._refreshSrc(cell);
this.popup.hide(); this.popup.hide();
} }

View File

@ -3,69 +3,61 @@
*/ */
module.exports = module.exports =
{ {
set: function (key, value, days) set: function(key, value, days) {
{
var strCookie = key + '=' + value + ';'; var strCookie = key + '=' + value + ';';
if (days != undefined) if (days != undefined) {
{ var date = Date.vnNew();
var date = new Date (); date.setTime(date.getTime() + days * 86400000);
date.setTime (date.getTime () + days * 86400000); strCookie += 'expires=' + date.toGMTString();
strCookie += 'expires=' + date.toGMTString ();
} }
document.cookie = strCookie; document.cookie = strCookie;
} }
,unset: function (key) ,unset: function(key) {
{ this.set(key, '', -1);
this.set (key, '', -1);
} }
,get: function (key) ,get: function(key) {
{ var cookie = new String(document.cookie);
var cookie = new String (document.cookie); var start = cookie.indexOf(key + '=');
var start = cookie.indexOf (key + '=');
if (start != -1) if (start != -1) {
{
var end; var end;
start += key.length + 1; start += key.length + 1;
end = cookie.indexOf (';', start); end = cookie.indexOf(';', start);
if (end > 0) if (end > 0)
return cookie.substring (start, end); return cookie.substring(start, end);
else else
return cookie.substring (start); return cookie.substring(start);
} }
return null; return null;
} }
,getInt: function (key) ,getInt: function(key) {
{ var value = this.get(key);
var value = this.get (key);
if (value != null) if (value != null)
return parseInt (value); return parseInt(value);
return null; return null;
} }
,getFloat: function (key) ,getFloat: function(key) {
{ var value = this.get(key);
var value = this.get (key);
if (value != null) if (value != null)
return parseFloat (value); return parseFloat(value);
return null; return null;
} }
,check: function (key) ,check: function(key) {
{ return this.get(key) != null;
return this.get (key) != null;
} }
}; };

View File

@ -6,6 +6,22 @@ Date.prototype.clone = function() {
return new Date(this.getTime()); return new Date(this.getTime());
} }
Date.vnUTC = () => {
const env = process.env.NODE_ENV;
if (!env || env === 'development')
return new Date(Date.UTC(2001, 0, 1, 11));
return new Date();
};
Date.vnNew = () => {
return new Date(Date.vnUTC());
};
Date.vnNow = () => {
return new Date(Date.vnUTC()).getTime();
};
module.exports = module.exports =
{ {
WDays: [ WDays: [

View File

@ -1,6 +1,6 @@
{ {
"name": "hedera-web", "name": "hedera-web",
"version": "23.30.5", "version": "23.40.6",
"description": "Verdnatura web page", "description": "Verdnatura web page",
"license": "GPL-3.0", "license": "GPL-3.0",
"repository": { "repository": {
@ -42,6 +42,7 @@
"scripts": { "scripts": {
"front": "webpack serve --open", "front": "webpack serve --open",
"back": "cd ../salix && gulp backOnly", "back": "cd ../salix && gulp backOnly",
"php": "php -S 127.0.0.1:3001 -t . index.php",
"db": "cd ../vn-database && myt run", "db": "cd ../vn-database && myt run",
"build": "rm -rf build/ ; webpack", "build": "rm -rf build/ ; webpack",
"clean": "rm -rf build/" "clean": "rm -rf build/"

View File

@ -18,7 +18,7 @@ class Segment {
switch ($type) { switch ($type) {
case Type::DATE: case Type::DATE:
$tmp = new Date(); $tmp = Date.vnNew();
$tmp->setDate(substr($v, 0, 4), substr($v, 4, 2), substr($v, 6, 2)); $tmp->setDate(substr($v, 0, 4), substr($v, 4, 2), substr($v, 6, 2));
return $tmp; return $tmp;
case Type::TIME: case Type::TIME: