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.

View File

@ -7,79 +7,7 @@ export default new Class({
activate() {
this.$.userModel.setInfo('c', 'myClient', 'hedera');
this.$.userModel.setInfo('u', 'myUser', 'account');
if (this.hash.$.verificationToken)
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();
this.$.changePassword.conn = this.conn
this.$.changePassword.user = this.gui.user
}
});

View File

@ -1,11 +1,5 @@
<vn>
<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-model property="model" id="user-model" updatable="true">
SELECT u.id, u.name, u.email, u.nickname,
@ -27,7 +21,7 @@
<htk-bar-button
icon="lock_reset"
tip="_Change password"
on-click="this.onPassChangeClick()"/>
on-click="this.$.changePassword.open()"/>
</div>
<div id="form" class="conf">
<div class="form box vn-w-sm vn-pa-lg">
@ -74,64 +68,5 @@
</div>
</div>
</div>
<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.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>
<htk-change-password id="change-password"/>
</vn>

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -46,3 +46,4 @@ NoMoreAmountAvailable: Pas plus disponible
MinimalGrouping: Emballage minimal
Available: Disponible
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
Available: Disponível
GroupingPrice: Preço por grupo
MinimalQuantity: Quantidade mínima

View File

@ -192,6 +192,25 @@
margin: 0;
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 */
@ -351,6 +370,7 @@
& > .top {
padding: 14px;
position: relative;
& > .item-info {
margin-left: 126px;
@ -371,6 +391,11 @@
margin-top: 15px 0;
font-size: .9rem;
}
& > .min-quantity {
bottom: 0;
right: 0;
padding: 14px;
}
}
& > .lots-grid {
border-top: 1px solid #DDD;

View File

@ -117,7 +117,7 @@
SELECT i.id, i.longName item, i.subName,
i.tag5, i.value5, i.tag6, i.value6,
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,
b.available, b.price, b.`grouping`,
i.image, im.updated
@ -149,7 +149,8 @@
id="grid-view"
empty-message="_Choose filter from right menu"
form-id="item"
model="items">
model="items"
renderer="itemRenderer">
<custom>
<div
id="item-box"
@ -203,6 +204,12 @@
{{Vn.Value.format(item.price, '%.02d€')}}
</span>
</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>
</custom>
@ -461,6 +468,12 @@
</tr>
</custom>
</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>
<htk-grid class="lots-grid" show-header="false">
<db-model

View File

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

View File

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

View File

@ -65,3 +65,20 @@ Account: Compte
Addresses: Adreces
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
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
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
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();
return false;
};
if(this.hash.$.verificationToken){
this.$.changePassword.conn = this.conn;
this.$.changePassword.token = this.hash.$.verificationToken;
this.$.changePassword.open();
}
}
,_onConnLoadChange(conn, isLoading) {
@ -94,7 +100,11 @@ module.exports = new Class({
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'));
}
});

View File

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

View File

@ -141,7 +141,7 @@ module.exports = new Class({
}
,goToCurrentMonth() {
var date = new Date();
var date = Date.vnNew();
this.goToMonth(date.getFullYear(), date.getMonth());
}
@ -179,7 +179,7 @@ module.exports = new Class({
// Marks the current day
var today = new Date();
var today = Date.vnNew();
if (this.year == today.getFullYear()
&& 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');
Htk = module.exports = {
Popup : require('./popup')
,Dialog : require('./dialog')
,Toast : require('./toast')
,Repeater : require('./repeater')
,Grid : require('./grid')
,Spinner : require('./spinner')
,Icon : require('./icon')
,FullImage : require('./full-image')
,ImageEditor : require('./image-editor')
,Assistant : require('./assistant')
,AssistantBar : require('./assistant-bar')
,Step : require('./step')
,Loader : require('./loader')
,List : require('./list')
,Field : require('./field')
,Column : require('./column')
Popup : require('./popup')
,Dialog : require('./dialog')
,Toast : require('./toast')
,Repeater : require('./repeater')
,Grid : require('./grid')
,Spinner : require('./spinner')
,Icon : require('./icon')
,FullImage : require('./full-image')
,ImageEditor : require('./image-editor')
,Assistant : require('./assistant')
,AssistantBar : require('./assistant-bar')
,Step : require('./step')
,Loader : require('./loader')
,List : require('./list')
,Field : require('./field')
,Column : require('./column')
,ChangePassword : require('./change-password')
};
var Fields = {

View File

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

View File

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

View File

@ -6,6 +6,22 @@ Date.prototype.clone = function() {
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 =
{
WDays: [

View File

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

View File

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