0
1
Fork 0

Compare commits

...

25 Commits

Author SHA1 Message Date
Juan Ferrer 18cdb4cc1b Merge branch 'dev' into 5122-multipleBasket 2023-02-15 19:54:25 +00:00
Juan Ferrer ca5f80f6c3 refs #5122 2023-02-15 17:18:54 +01:00
Juan Ferrer d1ff6889af Merge pull request '5122-multipleBasket' (!19) from 5122-multipleBasket into dev
Reviewed-on: verdnatura/hedera-web#19
2023-02-15 16:15:03 +00:00
Juan Ferrer a632a15242 refs #5122 2023-02-15 17:13:25 +01:00
Juan Ferrer 67b6f77b12 refs #5122 2023-02-15 14:07:09 +01:00
Juan Ferrer e8eab29887 Merge branch 'dev' into 5122-multipleBasket 2023-02-14 17:10:34 +01:00
Juan Ferrer 326aeee127 Merge pull request 'test' (!18) from test into dev
Reviewed-on: verdnatura/hedera-web#18
2023-01-31 13:15:47 +00:00
Juan Ferrer bbb0089b59 Merge pull request 'master' (!17) from master into test
Reviewed-on: verdnatura/hedera-web#17
2023-01-31 13:15:19 +00:00
Juan Ferrer 406b2f8300 #4253 Hotfix: OutdatedVersionError not handled 2023-01-31 14:09:01 +01:00
Juan Ferrer efc7342359 fixes #5174 Redsys TPV api migrated to salix 2023-01-31 13:38:59 +01:00
Juan Ferrer 806c4cc3ad refs #5122 Checkpoint 2023-01-30 11:08:26 +01:00
Juan Ferrer c463e967ca refs #3971 Form input locking when loading 2023-01-16 16:57:48 +01:00
Juan Ferrer be43a38b38 refs #3971 Order confirm style fixes 2023-01-16 14:18:07 +01:00
Juan Ferrer 59ed61ae9b refs #4253 Translation & UI fixes 2023-01-16 13:59:11 +01:00
Juan Ferrer 17e54cfc60 Merge pull request 'test' (!16) from test into dev
Reviewed-on: verdnatura/hedera-web#16
2022-12-09 11:55:42 +00:00
Juan Ferrer baa9bb7cdf Merge pull request 'refs #3971 Fixes: Checkout, pay' (!15) from master into test
Reviewed-on: verdnatura/hedera-web#15
2022-12-09 11:55:18 +00:00
Juan Ferrer 87d75be910 refs #3971 Fixes: Checkout, pay 2022-12-09 12:51:51 +01:00
Juan Ferrer ac629dc97b Merge pull request 'test' (!14) from test into dev
Reviewed-on: verdnatura/hedera-web#14
2022-12-05 09:21:44 +00:00
Juan Ferrer ff3320d590 Merge branch 'test' of https://gitea.verdnatura.es/verdnatura/hedera-web into test 2022-12-02 19:24:38 +01:00
Juan Ferrer e8b727ab6c refs #4922 .quasar dir added to gitignore 2022-12-02 09:18:09 +01:00
Juan Ferrer 5934ee3832 refs #3971 User supplant fixes 2022-12-02 09:15:43 +01:00
Juan Ferrer 4f09574697 Merge pull request 'test' (!13) from test into dev
Reviewed-on: verdnatura/hedera-web#13
2022-12-01 08:07:57 +00:00
Juan Ferrer 6d95dfb999 Merge pull request 'master' (!12) from master into test
Reviewed-on: verdnatura/hedera-web#12
2022-12-01 08:07:08 +00:00
Juan Ferrer 1fa9b1e8b0 refs #3971 Order checkout hotfix 2022-12-01 09:04:33 +01:00
Juan Ferrer 327508c3ee Merge pull request 'test' (!11) from test into master
Reviewed-on: verdnatura/hedera-web#11
2022-12-01 07:54:27 +00:00
116 changed files with 1079 additions and 1349 deletions

1
.gitignore vendored
View File

@ -2,3 +2,4 @@ node_modules
build/
config.my.php
.vscode/
.quasar

View File

@ -33,9 +33,9 @@ RUN curl -sL https://apt.verdnatura.es/conf/verdnatura.gpg | apt-key add - \
> /etc/apt/sources.list.d/vn.list \
&& apt-get update \
&& apt-get install -y --no-install-recommends \
php-apcu \
php-image-text \
php-text-captcha \
php-apcu \
php-zip \
hedera-web \
cron

2
debian/changelog vendored
View File

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

2
debian/control vendored
View File

@ -10,7 +10,7 @@ Vcs-Git: https://gitea.verdnatura.es/verdnatura/hedera-web
Package: hedera-web
Architecture: all
Depends: apache2 | httpd, nodejs, php-cli, php-vn-lib, php-apcu, php-imap, php-soap, libphp-phpmailer, php-gd, php-pear
Suggests: php-text-captcha, php-zip, cron
Suggests: php-image-text, php-text-captcha, php-zip, cron
Section: misc
Priority: optional
Description: Verdnatura's web page

1
debian/cron.d vendored
View File

@ -1,6 +1,5 @@
MAILTO=webmaster
*/1 * * * * root hedera-web.php -m misc/mail
*/4 * * * * root hedera-web.php -m tpv/confirm-mail
*/2 * * * * root hedera-web.php -m edi/load
0 23 * * * root hedera-web.php -m edi/clean
0 5 * * * root hedera-web.php -m edi/update

View File

@ -28,45 +28,54 @@ export default new Class({
}
,async onPassModifyClick() {
var oldPassword = this.$.oldPassword.value;
var newPassword = this.$.newPassword.value;
var repeatedPassword = this.$.repeatPassword.value;
if (newPassword == '' && repeatedPassword == '')
throw new Error(_('Passwords empty'));
if (newPassword !== repeatedPassword)
throw new Error(_('Passwords doesn\'t match'));
var verificationToken = this.hash.$.verificationToken;
var params = {newPassword};
let err;
const form = this.$.changePassword.node;
Vn.Node.disableInputs(form);
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);
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);
}
} catch(e) {
err = e;
Htk.Toast.showError(err.message);
const verificationToken = this.hash.$.verificationToken;
const params = {newPassword};
if (this.hash.$.verificationToken)
this.$.newPassword.select();
else
this.$.oldPassword.select();
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);
return;
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);
}
this.$.changePassword.hide();
this.hash.unset('verificationToken');
Htk.Toast.showMessage(_('Password changed!'));
this.$.userForm.refresh();
}
,onPassInfoClick() {

View File

@ -89,11 +89,13 @@
<input
id="new-password"
type="password"
placeholder="_New password"/>
placeholder="_New password"
autocomplete="new-password"/>
<input
id="repeat-password"
type="password"
placeholder="_Repeat password"/>
placeholder="_Repeat password"
autocomplete="new-password"/>
</div>
<div class="button-bar">
<button class="thin" on-click="this.onPassModifyClick()">

View File

@ -5,17 +5,38 @@ export default new Class({
Template: require('./ui.xml'),
async open() {
const isOk = await Hedera.BasketChecker.check(this.conn, this.hash);
if (isOk) await Hedera.Form.prototype.open.call(this);
await Hedera.Form.prototype.open.call(this);
this.basket = new Hedera.Basket(this.app);
this.orderId = this.$.params.$.id || this.basket.orderId;
if (!this.orderId)
return this.hash.setAll({form: 'ecomerce/checkout'});
this.$.lot.assign({id: this.orderId});
},
activate() {
this.$.items.setInfo('bi', 'myBasketItem', 'hedera');
activate() {
this.$.items.setInfo('bi', 'myOrderRow', 'hedera');
},
onConfigureClick() {
Htk.Toast.showWarning(_('RememberReconfiguringImpact'));
this.hash.setAll({form: 'ecomerce/checkout'});
this.hash.setAll({
form: 'ecomerce/checkout',
id: this.orderId
});
},
async onCatalogClick() {
const basket = new Hedera.Basket(this.app);
await basket.load(this.orderId);
},
onConfirmClick() {
this.hash.setAll({
form: 'ecomerce/confirm',
id: this.orderId
});
},
onDeleteClick(form) {

View File

@ -1,4 +1,6 @@
ShoppingBasket: Cistella de la compra
Order: Encàrrec
ShippingInformation: Dades d'enviament
Delete: Borrar encàrrec
GoToCatalog: Anar al catàleg
ConfigureOrder: Configurar encàrrec

View File

@ -1,4 +1,6 @@
ShoppingBasket: Shopping basket
Order: Order
ShippingInformation: Shipping information
Delete: Delete order
GoToCatalog: Go to catalog
ConfigureOrder: Configure order

View File

@ -1,4 +1,6 @@
ShoppingBasket: Cesta de la compra
Order: Pedido
ShippingInformation: Datos de envío
Delete: Borrar pedido
GoToCatalog: Ir al catálogo
ConfigureOrder: Configurar pedido

View File

@ -1,4 +1,6 @@
ShoppingBasket: Panier
Order: Commande
ShippingInformation: Informations sur la livraison
Delete: Effacer
GoToCatalog: Aller au catalogue
ConfigureOrder: Définissez l'ordre

View File

@ -1,4 +1,6 @@
ShoppingBasket: Cesta da compra
Order: Encomenda
ShippingInformation: Dados de envio
Delete: Eliminar encomenda
GoToCatalog: Ir ao catálogo
ConfigureOrder: Configurar encomenda

View File

@ -1,76 +1,93 @@
.basket .head {
border-bottom: 1px solid #DDD;
}
.basket .head p {
font-weight: bold;
margin: 0;
padding: 0;
font-size: 1.4rem;
text-align: right;
}
.basket .form > p {
margin: 0;
font-size: 1.4rem;
color: white;
text-align: right;
}
.hedera-basket {
.head {
border-bottom: 1px solid #DDD;
/* Lines */
& > div > div {
margin: 15px 0;
}
& > div > div:first-child {
margin: 0;
}
p {
margin: 3px 0;
.basket .line {
display: flex;
align-items: center;
gap: 12px;
margin: 10px 0;
height: 80px;
}
.basket .line:first-child {
margin-top: 0;
}
.basket .line:last-child {
margin-bottom: 0;
}
.basket .line > .delete {
margin: 0 -8px;
}
.basket .line > .photo {
flex: none;
border-radius: 50%;
width: 68px;
height: 68px;
gap: 0;
}
.basket .line > .info {
flex: 1;
overflow: hidden;
}
.basket .line > .info > * {
text-overflow: ellipsis;
white-space: nowrap;
overflow: hidden;
}
.basket .line > .info > h2 {
font-size: 1rem;
font-weight: normal;
margin: 0;
}
.basket .line > .info > p {
margin: 0;
}
.basket .line > .info > .tags {
color: #777;
}
.basket .line .subtotal {
float: right;
}
&.important {
font-size: 1.2rem;
font-weight: bold;
}
}
.total {
/* Fields */
font-weight: bold;
margin: 0;
padding: 0;
font-size: 1.4rem;
text-align: right;
}
}
.form > p {
margin: 0;
font-size: 1.4rem;
color: white;
text-align: right;
}
.basket td.available-exceeded input {
background-color: #FCC;
}
.basket .icon > img {
border-radius: 50%;
}
/* Lines */
.line {
display: flex;
align-items: center;
gap: 12px;
margin: 10px 0;
height: 80px;
}
.line:first-child {
margin-top: 0;
}
.line:last-child {
margin-bottom: 0;
}
.line > .delete {
margin: 0 -8px;
}
.line > .photo {
flex: none;
border-radius: 50%;
width: 68px;
height: 68px;
gap: 0;
}
.line > .info {
flex: 1;
overflow: hidden;
}
.line > .info > * {
text-overflow: ellipsis;
white-space: nowrap;
overflow: hidden;
}
.line > .info > h2 {
font-size: 1rem;
font-weight: normal;
margin: 0;
}
.line > .info > p {
margin: 0;
}
.line > .info > .tags {
color: #777;
}
.line .subtotal {
float: right;
}
/* Fields */
td.available-exceeded input {
background-color: #FCC;
}
.icon > img {
border-radius: 50%;
}
}

View File

@ -1,6 +1,9 @@
<vn>
<vn-lot-query id="params">
<vn-spec name="id" type="Number"/>
</vn-lot-query>
<div id="title">
<h1><t>ShoppingBasket</t></h1>
<h1>{{_(params.$.id ? 'Order' : 'ShoppingBasket')}}</h1>
</div>
<div id="actions">
<htk-bar-button
@ -10,16 +13,38 @@
<htk-bar-button
icon="local_florist"
tip="_Catalog"
on-click="this.hash.setAll({form: 'ecomerce/catalog'})"/>
on-click="this.onCatalogClick()"/>
<htk-bar-button
icon="shopping_cart_checkout"
tip="_Checkout"
on-click="this.hash.setAll({form: 'ecomerce/confirm'})"/>
on-click="this.onConfirmClick()"/>
</div>
<div id="form" class="basket">
<vn-group>
<vn-lot id="lot"/>
<db-form v-model="order">
<db-model property="model" lot="lot">
SELECT o.id, o.sent,
ag.description agency, v.code method, ad.nickname
FROM myOrder o
JOIN vn.agencyMode ag ON ag.id = o.agencyModeFk
LEFT JOIN myAddress ad ON ad.id = o.addressFk
JOIN vn.deliveryMethod v ON v.id = o.deliveryMethodFk
WHERE o.id = #id;
</db-model>
</db-form>
</vn-group>
<div id="form" class="hedera-basket">
<div class="box vn-w-sm vn-pa-lg">
<div class="head vn-pb-lg">
<p>
<h5>#{{order.id}}</h5>
<div class="vn-mt-md">
<h6><t>ShippingInformation</t></h6>
<p></p>
<p><t>Delivery at</t> {{Vn.Value.format(order.sent, _('%D'))}}</p>
<p><span id="method"><t>Agency</t></span> {{order.agency}}</p>
<p>{{order.nickname}}</p>
</div>
<p class="total">
<t>Total</t>
<htk-text format="%.2d€">
<db-calc-sum property="param" func="subtotal" model="items"/>
@ -28,15 +53,16 @@
</div>
<div class="lines vn-pt-lg">
<htk-repeater form-id="iter">
<db-model id="items" property="model" updatable="true">
<db-model id="items" property="model" lot="lot" updatable="true">
SELECT bi.id, bi.amount, bi.price, i.longName item,
i.tag5, i.value5, i.tag6, i.value6, i.tag7, i.value7,
i.image, im.updated
FROM myBasketItem bi
FROM myOrderRow bi
JOIN vn.item i ON i.id = bi.itemFk
LEFT JOIN image im
ON im.collectionFk = 'catalog'
AND im.name = i.image
WHERE orderFk = #id
</db-model>
<custom>
<div class="line">

View File

@ -8,18 +8,29 @@ const Catalog = new Class({
,async open() {
let isOk = true;
const basket = new Hedera.Basket(this.app);
this.orderId = basket.orderId;
if (!localStorage.getItem('hederaGuest'))
isOk = await Hedera.BasketChecker.check(this.conn, this.hash);
else
await this.conn.execQuery('CALL mybasket_configureForGuest');
if (!localStorage.getItem('hederaGuest')) {
if (!this.orderId)
return this.hash.setAll({form: 'ecomerce/checkout'});
else
isOk = await basket.checkRedirect(this.orderId);
} else {
const resultSet = await this.conn.execQuery(
'CALL myOrder_configureForGuest(@orderId); SELECT @orderId;');
resultSet.fetchResult();
this.orderId = resultSet.fetchValue();
}
if (isOk) await Hedera.Form.prototype.open.call(this);
}
,activate() {
document.body.appendChild(this.$.rightPanel);
this.$.items.setInfo('i', 'item', 'vn', ['id']);
this.$.orderLot.assign({orderId: this.orderId});
if (localStorage.getItem('hederaView'))
this.setView(parseInt(localStorage.getItem('hederaView')));
@ -98,6 +109,7 @@ const Catalog = new Class({
break;
}
params.orderId = this.orderId;
const refreshItems = hasTagFilter
|| params.search != null
|| params.type != null;
@ -245,7 +257,11 @@ const Catalog = new Class({
if (this.isGuest())
return;
this.hash.setAll({form: 'ecomerce/checkout'});
this.hash.setAll({
form: 'ecomerce/checkout',
id: this.orderId,
continue: 'catalog'
});
}
,onAddItemClick(event, form) {
@ -255,7 +271,10 @@ const Catalog = new Class({
this.onEraseClick();
this.$.$card.row = form.row;
this.$.cardLot.assign({item: form.$.id});
this.$.cardLot.assign({
item: form.$.id,
orderId: this.orderId
});
this.$.cardPopup.show(event.currentTarget);
}
@ -284,7 +303,7 @@ const Catalog = new Class({
,async onConfirmClick() {
var sql = '';
var query = new Sql.String({query: 'CALL myBasket_addItem(#warehouse, #item, #amount);'});
var query = new Sql.String({query: 'CALL myOrder_addItem(#orderId, #warehouse, #item, #amount);'});
var amountSum = 0;
for (var warehouse in this.items) {
@ -292,6 +311,7 @@ const Catalog = new Class({
amountSum += amount;
const params = {
orderId: this.orderId,
warehouse: warehouse,
item: this.$.cardLot.$.item,
amount: amount

View File

@ -91,12 +91,14 @@
param="producer"/>
</vn-group>
<vn-group>
<vn-lot id="order-lot"/>
<db-form v-model="basket">
<db-model property="model">
SELECT b.id, b.sent, a.description agency, m.code method
FROM myBasket b
JOIN vn.agencyMode a ON a.id = b.agencyModeFk
JOIN vn.deliveryMethod m ON m.id = b.deliveryMethodFk
<db-model property="model" lot="order-lot">
SELECT o.id, o.sent, a.description agency, m.code method
FROM myOrder o
JOIN vn.agencyMode a ON a.id = o.agencyModeFk
JOIN vn.deliveryMethod m ON m.id = o.deliveryMethodFk
WHERE o.id = #orderId
</db-model>
</db-form>
<db-model
@ -112,7 +114,7 @@
FROM vn.item i
JOIN vn.itemType t ON t.id = i.typeFk
WHERE #filter;
CALL myBasket_calcCatalogFull;
CALL myOrder_calcCatalogFull(#orderId);
SELECT i.id, i.longName item, i.subName,
i.tag5, i.value5, i.tag6, i.value6, i.tag7, i.value7,
i.relevancy, i.size, i.category,
@ -261,7 +263,7 @@
lot="params"
result-index="1"
on-status-changed="refreshTitle">
CALL myBasket_getAvailable;
CALL myOrder_getAvailable(#orderId);
SELECT DISTINCT t.id, l.name
FROM vn.item i
JOIN vn.itemType t ON t.id = i.typeFk
@ -283,7 +285,7 @@
property="model"
auto-load="false"
result-index="1">
CALL myBasket_getAvailable;
CALL myOrder_getAvailable(#orderId);
SELECT DISTINCT l.id, l.name
FROM vn.item i
JOIN vn.itemType t ON t.id = i.typeFk
@ -304,7 +306,7 @@
property="model"
auto-load="false"
result-index="1">
CALL myBasket_getAvailable;
CALL myOrder_getAvailable(#orderId);
SELECT DISTINCT p.id, p.name
FROM vn.item i
JOIN vn.itemType t ON t.id = i.typeFk
@ -325,7 +327,7 @@
property="model"
auto-load="false"
result-index="1">
CALL myBasket_getAvailable;
CALL myOrder_getAvailable(#orderId);
SELECT DISTINCT o.id, l.name, o.code
FROM vn.item i
JOIN vn.itemType t ON t.id = i.typeFk
@ -347,7 +349,7 @@
property="model"
auto-load="false"
result-index="1">
CALL myBasket_getAvailable;
CALL myOrder_getAvailable(#orderId);
SELECT DISTINCT i.category, i.category
FROM vn.item i
JOIN vn.itemType t ON t.id = i.typeFk
@ -466,7 +468,7 @@
result-index="1"
on-status-changed-after="onCardLoad"
lot="card-lot">
CALL myBasket_calcCatalogFromItem(#item);
CALL myOrder_calcCatalogFromItem(#orderId, #item);
SELECT l.warehouseFk, w.name warehouse, p.`grouping`,
p.price, p.priceKg, p.rate, l.available
FROM tmp.ticketLot l

View File

@ -44,7 +44,7 @@ export default new Class({
}
this.$.lot.assign({
date: date,
date,
method: row.deliveryMethod,
agency: row.agencyModeFk,
address: row.addressFk
@ -59,11 +59,21 @@ export default new Class({
async onConfirmClick() {
this.disableButtons(true);
const query = 'CALL myBasket_configure(#date, #method, #agency, #address)';
let id = this.$.params.$.id;
const params = Object.assign({}, this.$.lot.$);
let query;
if (id) {
params.id = id;
query = 'CALL myOrder_configure(#id, #date, #method, #agency, #address)';
} else {
query = 'CALL myOrder_create(@orderId, #date, #method, #agency, #address); SELECT @orderId;';
}
let resultSet;
try {
resultSet = await this.conn.execQuery(query, this.$.lot.$);
resultSet = await this.conn.execQuery(query, params);
} finally {
this.disableButtons(false);
}
@ -71,16 +81,25 @@ export default new Class({
if (!resultSet.fetchResult())
return;
if (this.$.orderForm.numRows > 0)
if (id) {
Htk.Toast.showMessage(_('OrderUpdated'));
else
Htk.Toast.showMessage(_('OrderStarted'));
this.hash.setAll({form: 'ecomerce/catalog'});
switch(this.hash.$.continue) {
case 'catalog':
this.hash.setAll({form: 'ecomerce/catalog'});
break;
default:
this.hash.setAll({form: 'ecomerce/basket', id});
}
} else {
const basket = new Hedera.Basket(this.app);
basket.loadIntoBasket(resultSet.fetchValue());
this.hash.setAll({form: 'ecomerce/catalog'});
}
},
onCancelClick() {
if (this.$.orderForm.numRows > 0)
if (this.$.params.$.id)
window.history.back();
else
this.hash.setAll({form: 'ecomerce/orders'});
@ -150,13 +169,9 @@ export default new Class({
this.$.assistant.moveNext();
},
goNextStep() {
this.$.assistant.moveNext();
},
onAddressClick(addressId) {
this.$.lot.set('address', addressId);
this.goNextStep();
this.$.assistant.moveNext();
},
onAddressChange() {
@ -192,9 +207,9 @@ export default new Class({
const defaults = this.$.defaults.$ || {};
if (defaults.agencyModeFk)
defaults.push(defaults.agencyModeFk);
agencies.push(defaults.agencyModeFk);
if (defaults.defaultAgencyFk)
defaults.push(defaults.defaultAgencyFk);
agencies.push(defaults.defaultAgencyFk);
for (const agency of agencies)
if (model.search('id', agency) !== -1) {

View File

@ -1,54 +1,55 @@
.checkout .bar {
margin-bottom: 16px;
}
.hedera-checkout {
.bar {
margin-bottom: 16px;
}
/* Step */
/* Step */
.answers button,
.answers p,
.radio > div {
font-size: 1.2rem;
.answers button,
.answers p,
.radio > div {
font-size: 1.2rem;
}
.answers .htk-select {
max-width: 15em;
margin: 0 auto;
font-size: 1.4rem;
}
.answers p {
margin: 0.3em 0;
}
.target {
max-width: 28em;
margin: 0 auto;
}
.address {
border-radius: 0.1em;
padding: 0.6em 1.4em;
}
.address.selected {
background-color: rgba(1, 1, 1, .1);
}
.address:hover {
cursor: pointer;
background-color: rgba(1, 1, 1, .05);
}
.address p.consignee {
font-weight: bold;
}
.radio {
max-width: 20em;
margin: 0 auto;
}
.radio > div {
padding: 0.5em;
}
.thin-calendar {
max-width: 24em;
margin: 0 auto;
box-shadow: none;
}
.htk-assistant .thin {
float: right;
}
}
.answers .htk-select {
max-width: 15em;
margin: 0 auto;
font-size: 1.4rem;
}
.answers p {
margin: 0.3em 0;
}
.target {
max-width: 28em;
margin: 0 auto;
}
.address {
border-radius: 0.1em;
padding: 0.6em 1.4em;
}
.address.selected {
background-color: rgba(1, 1, 1, .1);
}
.address:hover {
cursor: pointer;
background-color: rgba(1, 1, 1, .05);
}
.address p.consignee {
font-weight: bold;
}
.radio {
max-width: 20em;
margin: 0 auto;
}
.radio > div {
padding: 0.5em;
}
.thin-calendar {
max-width: 24em;
margin: 0 auto;
box-shadow: none;
}
.htk-assistant .thin {
float: right;
}

View File

@ -1,4 +1,7 @@
<vn>
<vn-lot-query id="params">
<vn-spec name="id" type="Number"/>
</vn-lot-query>
<vn-group>
<vn-lot id="lot" on-change="this.onAddressChange()"/>
<db-form id="defaults" on-ready="onValuesReady">
@ -8,10 +11,11 @@
</db-model>
</db-form>
<db-form id="order-form" on-ready="onValuesReady">
<db-model property="model">
<db-model property="model" lot="params">
SELECT m.code deliveryMethod, o.sent, o.agencyModeFk, o.addressFk
FROM myBasket o
FROM myOrder o
JOIN vn.deliveryMethod m ON m.id = o.deliveryMethodFk
WHERE o.id = #id
</db-model>
</db-form>
<db-model id="agencies"
@ -54,7 +58,7 @@
tip="_Cancel"
on-click="onCancelClick"/>
</div>
<div id="form" class="checkout">
<div id="form" class="hedera-checkout">
<div class="vn-w-sm">
<div class="box bar">
<htk-assistant-bar

View File

@ -5,8 +5,13 @@ export default new Class({
Template: require('./ui.xml'),
async open() {
const isOk = await Hedera.BasketChecker.check(this.conn, this.hash);
if (isOk) await Hedera.Form.prototype.open.call(this);
const basket = new Hedera.Basket(this.app);
try {
await basket.check(this.hash.$.id);
} catch (err) {
Htk.Toast.showError(err.message);
}
await Hedera.Form.prototype.open.call(this);
},
onOrderReady(form) {
@ -106,25 +111,22 @@ export default new Class({
Vn.Node.addClass(this.$[id], 'selected');
},
disableButtons(disable) {
this.$.modify.disabled = disable;
this.$.confirm.disabled = disable;
},
onModifyClick() {
window.history.back();
},
async onConfirmClick() {
this.disableButtons(true);
await this.$.confirmQuery.execute();
},
onConfirm(query, resultSet) {
this.disableButtons(false);
if (resultSet.fetchResult())
Vn.Node.disableInputs(this.node);
try {
await this.conn.execQuery(
'CALL myOrder_confirm(#id)',
this.$.params.$
);
Hedera.Basket.unload();
this.$.successDialog.show();
} finally {
Vn.Node.disableInputs(this.node, false);
}
},
async onDialogResponse() {

View File

@ -1,93 +1,95 @@
.confirm .summary {
margin-bottom: 16px;
}
.confirm p {
margin: .2em 0;
}
.hedera-confirm {
.summary {
margin-bottom: 16px;
}
p {
margin: .2em 0;
}
/* Table */
/* Table */
.confirm .debt-info {
padding: 0;
}
.confirm .debt-info > table {
border-collapse: collapse;
}
.confirm td {
padding: .15em 0;
}
.confirm .sum-total > td {
border-top: solid 1px #DDD;
font-weight: bold;
}
.confirm .currency {
text-align: right;
}
.confirm .credit-info {
display: none;
}
.confirm .exceeded-info {
display: none;
color: #E53935;
}
.debt-info {
padding: 0;
}
.debt-info > table {
border-collapse: collapse;
}
td {
padding: .15em 0;
}
.sum-total > td {
border-top: solid 1px #DDD;
font-weight: bold;
}
.currency {
text-align: right;
}
.credit-info {
display: none;
}
.exceeded-info {
display: none;
color: #E53935;
}
/* Pay */
/* Pay */
.confirm .amount-selector,
.confirm .pay-methods > div {
display: none;
}
.confirm .pay-methods > div {
margin: .3em 0;
}
.confirm .pay-methods > div > label > input[type=radio] {
margin: 0;
margin-right: .5em;
vertical-align: middle;
}
.confirm .pay-methods > div > div {
padding: .5em 1.5em;
display: none;
}
.confirm .pay-methods > div.selected > div {
display: block;
}
.confirm .transfer-account {
margin-top: .5em;
}
.confirm .transfer-account > p {
margin: .1em 0;
}
.amount-selector,
.pay-methods > div {
display: none;
}
.pay-methods > div {
margin: .3em 0;
}
.pay-methods > div > label > input[type=radio] {
margin: 0;
margin-right: .5em;
vertical-align: middle;
}
.pay-methods > div > div {
padding: .5em 1.5em;
display: none;
}
.pay-methods > div.selected > div {
display: block;
}
.transfer-account {
margin-top: .5em;
}
.transfer-account > p {
margin: .1em 0;
}
.confirm .payment > div {
margin-bottom: 1.4em;
.payment > div {
margin-bottom: 1.4em;
}
.payment > .button-bar {
display: flex;
justify-content: space-between;
margin-bottom: 0;
margin-top: 32px;
}
.payment > .button-bar button{
font-size: 1.2rem;
border-radius: 2rem;
padding: .5rem 1rem;
margin: 0;
}
.modify-order {
border: 1px solid #1a1a1a;
}
.modify-order:hover {
color: white;
background-color: #1a1a1a;
}
.confirm-order {
border: 1px solid #8cc63f;
background-color: #8cc63f;
color: white;
}
.confirm-order:hover {
background-color: transparent;
color: #6b5;
}
}
.confirm .payment > .button-bar {
display: flex;
justify-content: space-between;
margin-bottom: 0;
margin-top: 32px;
}
.confirm .payment > .button-bar button{
font-size: 1.2rem;
border-radius: 2rem;
padding: .5rem 1rem;
margin: 0;
}
.confirm .modify-order {
border: 1px solid #1a1a1a;
}
.confirm .modify-order:hover {
color: white;
background-color: #1a1a1a;
}
.confirm .confirm-order {
border: 1px solid #8cc63f;
background-color: #8cc63f;
color: white;
}
.confirm .confirm-order:hover {
background-color: transparent;
color: #6b5;
}

View File

@ -1,13 +1,16 @@
<vn>
<vn-lot-query id="params">
<vn-spec name="id" type="Number"/>
</vn-lot-query>
<vn-group>
<db-form v-model="order" on-ready="onOrderReady">
<db-model property="model" result-index="1">
CALL myBasket_getTax;
<db-model property="model" result-index="1" lot="params">
CALL myOrder_getTax(#id);
SELECT o.id, o.sent, o.notes, o.companyFk,
ag.description agency, v.code method,
ad.nickname, ad.postalCode, ad.city, ad.street,
t.*, c.credit, myClient_getDebt(NULL) debt
FROM myBasket o
FROM myOrder o
JOIN vn.agencyMode ag ON ag.id = o.agencyModeFk
LEFT JOIN myAddress ad ON ad.id = o.addressFk
JOIN vn.deliveryMethod v ON v.id = o.deliveryMethodFk
@ -17,27 +20,25 @@
IFNULL(SUM(taxableBase), 0) taxableBase,
IFNULL(SUM(tax), 0) tax
FROM tmp.orderAmount
) t;
) t
WHERE o.id = #id;
DROP TEMPORARY TABLE
tmp.orderAmount,
tmp.orderTax;
</db-model>
</db-form>
<db-query id="confirm-query" on-ready="onConfirm">
CALL myBasket_confirm
</db-query>
</vn-group>
<div id="title">
<h1><t>Order summary</t></h1>
</div>
<div id="form" class="confirm">
<div id="form" class="hedera-confirm">
<div class="vn-w-sm">
<div class="box vn-pa-lg summary">
<div>
<div class="delivery">
<h6><t>ShippingInformation</t></h6>
<p>
<t>Delivery at</t> {{Vn.Value.format(order.sent, _('%D'))}}
<t>Delivery at</t> {{Vn.Value.format(order.sent, _('%D'))}}
</p>
<p>
<span id="method"><t>Agency</t></span> {{order.agency}}

View File

@ -2,7 +2,7 @@
<div id="title">
<h1><t>Invoices</t></h1>
</div>
<div id="form" class="invoices">
<div id="form" class="hedera-invoices">
<htk-grid
class="box vn-w-sm"
show-header="false">

View File

@ -5,7 +5,7 @@ OrderNumber: N encàrrec
DateMake: Data de creació
DateExit: Data d'eixida
SendMethod: Forma d'enviament
LastOrders: Últimes comandes
LastOrders: Comandes confirmades
'Balance:': 'Saldo:'
PaymentInfo: >-
La quantitat mostrada és el teu saldo pendent (negatiu) o favorable a dia

View File

@ -5,7 +5,7 @@ OrderNumber: Order number
DateMake: Creation date
DateExit: Shipping date
SendMethod: Delivery method
LastOrders: Last orders
LastOrders: Confirmed orders
'Balance:': 'Balance:'
PaymentInfo: >-
The amount shown is your slope (negative) or favorable balance today, it

View File

@ -5,7 +5,7 @@ OrderNumber: Nº pedido
DateMake: Fecha de creación
DateExit: Fecha de salida
SendMethod: Forma de envío
LastOrders: Últimos pedidos
LastOrders: Pedidos confirmados
'Balance:': 'Saldo:'
PaymentInfo: >-
La cantidad mostrada es tu saldo pendiente (negativa) o favorable a día de

View File

@ -5,7 +5,7 @@ OrderNumber: Numéro de commande
DateMake: Date de creation
DateExit: Date de sortie
SendMethod: Typo
LastOrders: Les dernières commandes
LastOrders: Commandes confirmées
'Balance:': 'Balance:'
PaymentInfo: >-
Le montant indiqué est votre pente (négative) ou balance favorable

View File

@ -1,37 +0,0 @@
OpenOrders: Open orders
StartOrder: Start order
ContinueOrder: Continue order
OrderNumber: Order number
DateMake: Creation date
DateExit: Shipping date
SendMethod: Delivery method
LastOrders: Last orders
'Balance:': 'Balance:'
PaymentInfo: >-
Үзүүлсэн хэмжээ цаашид захиалга эзэлж биш, таны налуу (сөрөг), эсвэл
тааламжтай тэнцвэр нь өнөөдөр юм. Хэрэв та дүн арилгаж гэж хэлж байсан нь доош
нь төлбөр хийж, өөрийн хүссэн хэмжээгээр орж хүсэж байгаа бол таны захиалга
ирдэг бол авах, энэ хэмжээ тэнцүү буюу 0-ээс их байх ёстой.
MakePayment: Make payment
Company: Company
Pending: Pending
Pay: Pay
Basket: Basket
ShoppingBasket: Shopping basket
SeeOrder: Show details of the order
Delivery: Delivery
TicketNumber: Ticket number
SentAddress: Delivery address
Consignee: Consignee
Boxes: Bundles
TotalWithVAT: Total with VAT
PayOrder: Pay order
'AmountToPay:': 'Amount to pay (€):'
AmountError: >-
The amount must be a positive number less than or equal to the outstanding
amount
PayError: Failed to make the payment
An error has been in the payment: >-
It seems that there has been an error in the payment
Retry: Retry
Accept: Accept

View File

@ -5,7 +5,7 @@ OrderNumber: Nº pedido
DateMake: Data de criação
DateExit: Data de saída
SendMethod: Forma de envío
LastOrders: Últimas encomendas
LastOrders: Encomendas confirmadas
'Balance:': 'Saldo:'
PaymentInfo: >-
A quantidade mostrada é seu saldo pendente (negativo) ou favorável a dia de

View File

@ -33,7 +33,6 @@
/* List */
.orders .htk-list .total {
.hedera-orders .htk-list .total {
float: right;
}

View File

@ -34,7 +34,7 @@
tip="_ShoppingBasket"
on-click="onBasketClick"/>
</div>
<div id="form" class="orders">
<div id="form" class="hedera-orders">
<htk-repeater
class="htk-list box confirmed vn-w-sm"
form-id="iter"

View File

@ -0,0 +1,21 @@
import './style.scss';
export default new Class({
Extends: Hedera.Form,
Template: require('./ui.xml'),
activate() {
this.basket = new Hedera.Basket(this.app);
this.$.orders.setInfo('o', 'myOrder', 'hedera', ['id'], 'id');
},
async onRemoveOrderClick(form) {
if (confirm(_('AreYouSureDeleteOrder')))
await form.deleteRow();
},
async loadOrder(id) {
const basket = new Hedera.Basket(this.app);
await basket.load(id);
}
});

View File

@ -0,0 +1 @@
Pending: Pendents

View File

@ -0,0 +1 @@
Pending: Pending

View File

@ -0,0 +1,8 @@
Pending: Pendientes
PendingOrders: Pedidos pendientes
NewOrder: Nuevo pedido
ViewOrder: Ver pedido
RemoveOrder: Eliminar pedido
LoadOrderIntoCart: Cargar pedido en la cesta
AreYouSureDeleteOrder: ¿Seguro que quieres borrar el pedido?
OrderLoadedIntoBasket: ¡Pedido cargado en la cesta!

View File

@ -0,0 +1 @@
Pending: Pendents

View File

@ -0,0 +1 @@
Pending: Pendientes

View File

View File

@ -0,0 +1,54 @@
<vn>
<div id="title">
<h1><t>PendingOrders</t></h1>
</div>
<div id="actions">
<htk-bar-button
class="start-order"
icon="add_shopping_cart"
tip="_NewOrder"
on-click="hash.setAll({form: 'ecomerce/checkout'})"/>
</div>
<div id="form" class="hedera-pending">
<htk-repeater
class="htk-list box confirmed vn-w-sm"
form-id="iter">
<db-model property="model" id="orders">
SELECT o.id, o.sent, o.deliveryMethodFk, o.total,
a.nickname, am.description agency
FROM myOrder o
JOIN myAddress a ON a.id = o.addressFk
JOIN vn.agencyMode am ON am.id = o.agencyModeFk
WHERE NOT o.isConfirmed
ORDER BY o.sent DESC
</db-model>
<custom>
<a class="item"
title="{{_('ViewOrder')}}"
href="{{'#!form=ecomerce/basket&amp;id='+iter.id}}">
<div class="content">
<p class="important">
{{Vn.Value.format(iter.sent, '%D')}}
</p>
<p>#{{iter.id}}</p>
<p>{{iter.nickname}}</p>
<p>{{iter.agency}}</p>
<p>{{Vn.Value.format(iter.total, '%.2d€')}}</p>
</div>
<div
class="actions"
on-click="$event.preventDefault()">
<htk-button
icon="delete"
tip="_RemoveOrder"
on-click="this.onRemoveOrderClick($iter)"/>
<htk-button
icon="shopping_bag"
tip="_LoadOrderIntoCart"
on-click="this.loadOrder(iter.id)"/>
</div>
</a>
</custom>
</htk-repeater>
</div>
</vn>

View File

@ -1,78 +1,79 @@
/* Header */
.hedera-ticket {
/* Header */
.ticket .head {
padding: 0;
padding-bottom: 3px;
border-bottom: 1px solid #DDD;
margin-bottom: 1px;
}
.ticket .head > div > div {
margin: 15px 0;
}
.ticket .head > div > div:first-child {
margin: 0;
}
.ticket .head p {
margin: 3px 0;
}
.ticket .head p.important {
font-size: 1.2rem;
font-weight: bold;
}
.ticket .total {
text-align: right;
}
.ticket .packages {
margin-top: 14px;
padding-top: 14px;
border-top: 1px solid #DDD;
display: block;
}
.head {
padding: 0;
padding-bottom: 3px;
border-bottom: 1px solid #DDD;
margin-bottom: 1px;
}
.head > div > div {
margin: 15px 0;
}
.head > div > div:first-child {
margin: 0;
}
.head p {
margin: 3px 0;
}
.head p.important {
font-size: 1.2rem;
font-weight: bold;
}
.total {
text-align: right;
}
.packages {
margin-top: 14px;
padding-top: 14px;
border-top: 1px solid #DDD;
display: block;
}
/* Lines */
/* Lines */
.ticket .line {
display: flex;
align-items: center;
gap: 12px;
margin: 10px 0;
height: 80px;
.line {
display: flex;
align-items: center;
gap: 12px;
margin: 10px 0;
height: 80px;
}
.line:last-child {
margin-bottom: 0;
}
.line > .photo {
flex: none;
border-radius: 50%;
width: 68px;
height: 68px;
gap: 0;
}
.line > .info {
flex: 1;
overflow: hidden;
}
.line > .info > * {
text-overflow: ellipsis;
white-space: nowrap;
overflow: hidden;
}
.line > .info > h2 {
font-size: 1rem;
font-weight: normal;
margin-bottom: 2px;
}
.line > .info > p {
margin: 0;
}
.line > .info > .tags {
color: #777;
}
.line > .info .discount {
color: green;
}
.line > .info > .subtotal {
float: right;
}
}
.ticket .line:last-child {
margin-bottom: 0;
}
.ticket .line > .photo {
flex: none;
border-radius: 50%;
width: 68px;
height: 68px;
gap: 0;
}
.ticket .line > .info {
flex: 1;
overflow: hidden;
}
.ticket .line > .info > * {
text-overflow: ellipsis;
white-space: nowrap;
overflow: hidden;
}
.ticket .line > .info > h2 {
font-size: 1rem;
font-weight: normal;
margin-bottom: 2px;
}
.ticket .line > .info > p {
margin: 0;
}
.ticket .line > .info > .tags {
color: #777;
}
.ticket .line > .info .discount {
color: green;
}
.ticket .line > .info > .subtotal {
float: right;
}

View File

@ -14,7 +14,7 @@
tip="_Print delivery note"
on-click="this.onPrintClick()"/>
</div>
<div id="form" class="ticket">
<div id="form" class="hedera-ticket">
<div class="box vn-w-sm vn-pa-lg">
<htk-loader class="head" form="ticket-form">
<h5>#{{ticket.id}}</h5>

View File

@ -70,7 +70,9 @@ export const routes = {
orders:
() => import('ecomerce/orders'),
ticket:
() => import('ecomerce/ticket')
() => import('ecomerce/ticket'),
pending:
() => import('ecomerce/pending')
},
news: {
new:

View File

@ -9,6 +9,24 @@ module.exports = new Class({
,get() {
return this._conn;
}
},
hash: {
type: Vn.Hash
,get() {
return this._hash;
}
},
gui: {
type: Gui
,get() {
return this._gui;
}
},
login: {
type: Login
,get() {
return this._login;
}
}
}
@ -35,6 +53,7 @@ module.exports = new Class({
,showLogin() {
const login = this._login = new Login({
app: this,
conn: this._conn,
hash: this._hash
});
@ -47,6 +66,7 @@ module.exports = new Class({
if (this._gui) return;
const gui = this._gui = new Gui({
app: this,
conn: this._conn,
hash: this._hash
});
@ -198,11 +218,11 @@ module.exports = new Class({
,async _onConnError(conn, err) {
if (!(err instanceof Vn.JsonException)) return;
switch (err.exception) {
case 'UserDisabled':
case 'UserDisabledError':
Htk.Toast.showError(_('User disabled'));
await this._logout();
return;
case 'OutdatedVersion':
case 'OutdatedVersionError':
this._newVersion();
return;
}
@ -222,8 +242,8 @@ module.exports = new Class({
Htk.Toast.showError(_('You don\'t have enough privileges'));
else {
switch (err.exception) {
case 'UserDisabled':
case 'OutdatedVersion':
case 'UserDisabledError':
case 'OutdatedVersionError':
return;
}
if (err.statusCode == 401)

View File

@ -1,21 +0,0 @@
module.exports = {
async check(conn, hash) {
this.hash = hash;
const resultSet = await conn.execQuery('CALL myBasket_check');
const status = resultSet.fetchValue();
if (!status) return;
const isOk = status == 'UPDATED' || status == 'OK';
if (status == 'UPDATED')
Htk.Toast.showWarning(_('Order items updated'));
if (!isOk)
this.hash.setAll({form: 'ecomerce/checkout'});
return isOk;
}
};

48
js/hedera/basket.js Normal file
View File

@ -0,0 +1,48 @@
module.exports = class {
constructor(app) {
this.app = app;
let orderId = localStorage.getItem('hederaBasket');
if (orderId) orderId = parseInt(orderId);
this.orderId = orderId;
}
async check(orderId) {
const resultSet = await this.app.conn.execQuery(
'CALL myOrder_checkConfig(#id)',
{id: orderId}
);
resultSet.fetchValue();
}
async checkRedirect(orderId) {
try {
await this.check(orderId);
return true;
} catch(err) {
Htk.Toast.showError(err.message);
this.app.hash.setAll({
form: 'ecomerce/checkout',
id: orderId,
continue: 'catalog'
});
return false;
}
}
async load(orderId) {
this.loadIntoBasket(orderId);
if (!await this.checkRedirect(orderId)) return;
this.app.hash.setAll({
form: 'ecomerce/catalog'
});
}
loadIntoBasket(orderId) {
if (this.orderId != orderId) {
localStorage.setItem('hederaBasket', orderId);
this.orderId = orderId;
Htk.Toast.showMessage(_('OrderLoadedIntoBasket'));
}
}
static unload() {
localStorage.removeItem('hederaBasket');
}
};

View File

@ -7,6 +7,7 @@ module.exports = new Class({
,initialize(gui) {
this.gui = gui;
this.app = gui.app;
this.conn = gui.conn;
this.hash = gui.hash;
}

View File

@ -50,19 +50,16 @@ module.exports = new Class({
this.doc.body.appendChild(this.node);
Htk.Toast.pushTop(this.$.formHolder);
await this.refreshUserData();
Vn.Node.setText(this.$.userName, this.user.nickname);
const resultSet = await this._conn.execQuery(
'SELECT id, name, nickname FROM account.myUser;'
+'SELECT defaultForm FROM config;'
'SELECT defaultForm FROM config;'
+'SELECT url FROM imageConfig;'
+'SELECT dbproduccion FROM vn.config;'
+'SELECT productionDomain, testDomain FROM config;'
);
// Retrieving the user name
this.user = resultSet.fetchObject();
Vn.Node.setText(this.$.userName, this.user.nickname);
// Retrieving configuration parameters
Vn.Config.defaultForm = resultSet.fetchValue();
@ -119,6 +116,12 @@ module.exports = new Class({
Htk.Toast.showWarning(_('By using this site you accept cookies'));
}
}
,async refreshUserData() {
const resultSet = await this._conn.execQuery(
'SELECT id, name, nickname FROM account.myUser');
this.user = resultSet.fetchObject();
}
,async hide() {
if (!this._shown)
@ -463,29 +466,41 @@ module.exports = new Class({
}
//++++++++++++++++++++++++++++++++++++++++++++++++++++++ Supplant
/**
* Supplants another user.
*
* @param {String} supplantUser The user name
*/
,async supplantUser(supplantUser) {
const json = await this._conn.send('client/supplant', {supplantUser});
this._conn.token = json;
sessionStorage.setItem('supplantUser', supplantUser);
await this.refreshUserData();
Vn.Node.setText(this.$.supplanted, this.user.nickname);
this.$.supplant.classList.toggle('show', true);
await this.loadMenu();
}
/*
* Ends the user supplanting and restores the original login.
*/
,async onSupplantExitClick() {
this._conn.post('Accounts/logout');
this._conn.fetchToken();
sessionStorage.removeItem('supplantUser');
this.$.supplant.classList.toggle('show', false);
await this.refreshUserData();
await this.loadMenu();
this._onFormChange();
}
,async supplantInit() {
var user = sessionStorage.getItem('supplantUser');
if (user == null) return;
await this._conn.supplantUser(user);
sessionStorage.setItem('supplantUser', user);
await this.loadMenu();
const res = await this._conn.execQuery(
'SELECT nickname FROM account.myUser');
const userName = res.fetchValue();
Vn.Node.setText(this.$.supplanted, userName);
this.$.supplant.classList.toggle('show', true);
}
,async onSupplantExitClick() {
this.$.supplant.classList.toggle('show', false);
await this._conn.supplantEnd();
sessionStorage.removeItem('supplantUser');
await this.loadMenu();
this._onFormChange();
await this.supplantUser(user);
}
//++++++++++++++++++++++++++++++++++++++++++++++++++++++ Destroy

View File

@ -10,6 +10,6 @@ Hedera = module.exports = {
,Report : require('./report')
,App : require('./app')
,Tpv : require('./tpv')
,BasketChecker : require('./basket-checker')
,Basket : require('./basket')
};

View File

@ -38,7 +38,8 @@ AppName: Verdnatura
Home: Inici
Orders: Encàrrecs
Basket: Cistella
Last orders: Últims comandes
Pending orders: Pendents
Last orders: Confirmades
Invoices: Factures
Catalog: Catàleg
About: Coneix-nos

View File

@ -34,7 +34,8 @@ AppName: Verdnatura
Home: Home
Orders: Orders
Basket: Basket
Last orders: Last orders
Pending orders: Pending
Last orders: Confirmed
Invoices: Invoices
Catalog: Catalog
About: About

View File

@ -38,7 +38,8 @@ AppName: Verdnatura
Home: Inicio
Orders: Pedidos
Basket: Cesta
Last orders: Últimos pedidos
Pending orders: Pendientes
Last orders: Confirmados
Invoices: Facturas
Catalog: Catálogo
About: Conócenos

View File

@ -38,7 +38,8 @@ AppName: Verdnatura
Home: Accueil
Orders: Commandes
Basket: Panier
Last orders: Dernières commandes
Pending orders: En attente
Last orders: Confirmées
Invoices: Facturas
Catalog: Catalogue
About: Nous

View File

@ -36,7 +36,8 @@ AppName: VerdNatura
Home: Principio
Orders: Encomendas
Basket: Cesta
Last orders: Últimas encomendas
Pending orders: Pendentes
Last orders: Confirmados
Invoices: Facturas
Catalog: Catálogo
About: Conheça-nos

View File

@ -9,11 +9,10 @@ module.exports = new Class({
this.tpvStatus = this.hash.$.tpvStatus;
if (this.tpvStatus) {
const query = 'CALL myTpvTransaction_end(#transaction, #status)';
this.conn.execQuery(query, {
transaction: this.tpvOrder,
this.conn.post('TpvTransactions/end', {
orderId: this.tpvOrder,
status: this.tpvStatus
});
})
}
return this.tpvStatus;
@ -24,22 +23,18 @@ module.exports = new Class({
}
,async _realPay(amount, company) {
if (!isNumeric(amount) || amount <= 0)
throw new UserError(_('AmountError'));
let json;
try {
json = await this.conn.send('tpv/transaction', {
amount: parseInt(amount)
,urlOk: this._makeUrl('ok')
,urlKo: this._makeUrl('ko')
,company: company
});
} catch(err) {
throw new UserError(_('PayError'));
if (!isNumeric(amount) || amount <= 0) {
Htk.Toast.showError(_('AmountError'));
return;
}
const json = await this.conn.post('TpvTransactions/start', {
amount: parseInt(amount),
urlOk: this._makeUrl('ok'),
urlKo: this._makeUrl('ko'),
company
});
const postValues = json.postValues;
const form = document.createElement('form');

View File

@ -10,15 +10,7 @@ module.exports = new Class({
value: {
type: String
,set(x) {
if (Vn.Value.compare(x, this._value))
return;
if (x instanceof Date)
x = x.clone();
this.valueChanged(x);
this.putValue(x);
this._notifyChanges();
this._setValue(x);
}
,get() {
return this._value;
@ -109,11 +101,11 @@ module.exports = new Class({
,_lockField: false
,_setValue(newValue) {
if (!this._putValue(newValue))
return;
if (!this._putValue(newValue)) return;
newValue = this._value;
if (!this._lockField)
this.putValue(newValue);
this.putValue(this._value);
if (this.conditionalFunc)
this.conditionalFunc(this, newValue);

View File

@ -54,7 +54,7 @@ module.exports = new Class({
,render() {
var radio = Vn.Browser.createRadio('', this.doc);
radio.checked = false;
radio.addEventListener('change', this._onChange.bind(this));
radio.addEventListener('change', () => this._onChange());
this._node = radio;
}

View File

@ -4,8 +4,6 @@ var htkRadioGroupUid = 0;
module.exports = new Class({
Extends: Htk.Field
,Tag: 'htk-radio-group'
,radioLock: false
,initialize(props) {
this.clear();

View File

@ -50,9 +50,8 @@ module.exports = new Class({
if (user !== null && user !== undefined) {
params = {
user: user,
password: pass,
remember: remember
user,
password: pass
};
} else
params = null;
@ -96,24 +95,6 @@ module.exports = new Class({
this.clearToken();
},
/**
* Supplants another user.
*
* @param {String} supplantUser The user name
*/
async supplantUser(supplantUser) {
const json = await this.send('client/supplant', {supplantUser});
this.token = json;
},
/**
* Ends the user supplanting and restores the last login.
*/
async supplantEnd() {
await this.post('Accounts/logout');
this.fetchToken();
},
/**
* Executes the specified REST service with the given params and calls
* the callback when response is received.
@ -279,7 +260,7 @@ module.exports = new Class({
if (exception) {
exception = exception
.replace(/\\/g, '.')
.replace(/Exception$/, '')
.replace(/Exception$/, 'Error')
.replace(/^Vn\.Web\./, '');
err.exception = exception;

View File

@ -1,4 +1,3 @@
/**
* Holds a plain key-value javascript object and monitorizes changes over it.
*/
@ -10,14 +9,14 @@ module.exports = new Class({
*/
params: {
type: Object
}
},
/**
* Shortcut for params property.
*/
,$: {
$: {
type: Object
}
}
}
},
/**
* Gets a value from the lot.
@ -25,9 +24,9 @@ module.exports = new Class({
* @param {string} field The field name
* @return {*} The field value
*/
,get(field) {
return this.params[field];
}
get(field) {
return this.params[field];
},
/**
* Sets a value on the lot.
@ -35,49 +34,51 @@ module.exports = new Class({
* @param {string} field The field name
* @param {*} value The new field value
*/
,set(field, value) {
var params = {};
params[field] = value;
this.assign(params);
}
set(field, value) {
this.assign({[field]: value});
},
unset(field) {
this.assign({[field]: undefined});
},
/**
* Returns an array with the lot keys.
*
* @return {Array} The lot keys
*/
,keys() {}
keys() {},
/**
* Emits the 'change' signal on the lot.
*
* @param {Object} changes The changed params and its values
*/
,changed(changes) {
this.emit('change', changes);
}
changed(changes) {
this.emit('change', changes);
},
/**
* Copies all values from another lot.
*
* @param {Object} object The source object
*/
,assign() {}
assign() {},
/**
* Copies all values from another lot.
*
* @param {LotIface} lot The source lot
*/
,assignLot(lot) {
this.assign(lot.$);
}
assignLot(lot) {
this.assign(lot.$);
},
/**
* Resets all values.
*/
,reset() {
this.params = {};
}
reset() {
this.params = {};
}
});

View File

@ -1,66 +1,63 @@
module.exports =
{
removeChilds: function (node)
{
module.exports = {
removeChilds(node) {
var childs = node.childNodes;
if (childs)
while (childs.length > 0)
node.removeChild (childs[0]);
}
node.removeChild(childs[0]);
},
,remove: function (node)
{
remove(node) {
if (node.parentNode)
node.parentNode.removeChild (node);
}
node.parentNode.removeChild(node);
},
,setText: function (node, text)
{
Vn.Node.removeChilds (node);
setText(node, text) {
Vn.Node.removeChilds(node);
if (text)
node.appendChild (
node.ownerDocument.createTextNode (text));
}
node.appendChild(
node.ownerDocument.createTextNode(text));
},
,addClass: function (node, className)
{
/* var classes = node.className.split (' ');
addClass(node, className) {
/* var classes = node.className.split(' ');
if (classes.split (' ').indexOf (className) == -1)
if (classes.split(' ').indexOf(className) == -1)
*/ node.className = className +' '+ node.className;
}
},
,removeClass: function (node, className)
{
removeClass(node, className) {
var index = 0;
var found = false;
var classes = node.className.split (' ');
var classes = node.className.split(' ');
while ((index = classes.indexOf (className, index)) != -1)
{
classes.splice (index, 1);
while ((index = classes.indexOf(className, index)) != -1) {
classes.splice(index, 1);
found = true;
}
if (found)
node.className = classes.join (' ');
}
node.className = classes.join(' ');
},
,hide: function (node)
{
hide: function(node) {
node.style.display = 'none';
}
},
,show: function (node)
{
show: function(node) {
node.style.display = 'block';
},
disableInputs(formNode, disable = true) {
const inputs = formNode
.querySelectorAll('input, textarea, button, select');
for (const input of inputs)
input.disabled = disable;
}
};
$ = function (id)
{
return document.getElementById (id);
$ = function(id) {
return document.getElementById(id);
}

View File

@ -140,52 +140,33 @@ function sprintf(formatString) {
});
}
module.exports = {
regexpNumber: /%\.([0-9]+)d/g
,regexpString: /%s/g
function format(value, format) {
if (value === null || value === undefined)
return '';
,equals
,diff
,partialDiff
,kvClone
,simpleClone
,simpleEquals
,sprintf
,compare(a, b) {
if (a === b)
return true;
if (a instanceof Date && b instanceof Date)
return a.getTime() === b.getTime();
return false;
if (format)
switch (typeof value) {
case 'number':
return format.replace(/%\.([0-9]+)d/g,
(_, digits) => new Number(value).toFixed(parseInt(digits)));
case 'string':
return format.replace(/%s/g,
() => value);
case 'object':
if (value instanceof Date)
return VnDate.strftime(value, format);
}
,format(value, format) {
if (value === null || value === undefined)
return '';
if (format)
switch (typeof value) {
case 'number':
return format.replace(this.regexpNumber,
this.replaceNumber.bind(null, value));
case 'string':
return format.replace(this.regexpString,
this.replaceString.bind(null, value));
case 'object':
if (value instanceof Date)
return VnDate.strftime(value, format);
}
return value;
}
return value;
}
,replaceNumber(value, token, digits) {
return new Number(value).toFixed(parseInt(digits));
}
,replaceString(value) {
return value;
}
module.exports = {
equals,
diff,
partialDiff,
kvClone,
simpleClone,
simpleEquals,
sprintf,
format,
};

4
package-lock.json generated
View File

@ -1,12 +1,12 @@
{
"name": "hedera-web",
"version": "22.46.19",
"version": "22.48.4",
"lockfileVersion": 2,
"requires": true,
"packages": {
"": {
"name": "hedera-web",
"version": "22.46.19",
"version": "22.48.4",
"license": "GPL-3.0",
"dependencies": {
"js-yaml": "^3.12.1",

View File

@ -1,6 +1,6 @@
{
"name": "hedera-web",
"version": "22.48.2",
"version": "22.48.10",
"description": "Verdnatura web page",
"license": "GPL-3.0",
"repository": {

Binary file not shown.

After

Width:  |  Height:  |  Size: 80 KiB

View File

@ -1,2 +1,4 @@
UpdateYourBrowser: Actualitza el teu navegador
ContinueAnyway: Continuar igualment
BrowserVersionNotCompatible: El vostre navegador no és compatible amb aquesta versió de la pàgina web
PushHereToInstallFirefox: Clica aquí per instal·lar Firefox

View File

@ -1,2 +1,4 @@
UpdateYourBrowser: Upgrade your browser
ContinueAnyway: Continue anyway
BrowserVersionNotCompatible: Your browser is not compatible with this version of the website
PushHereToInstallFirefox: Click here to install Firefox

View File

@ -1,2 +1,4 @@
UpdateYourBrowser: Actualiza tu navegador
ContinueAnyway: Continuar de todos modos
BrowserVersionNotCompatible: Tu navegador no es compatible con esta versión de la página web
PushHereToInstallFirefox: Pulsa aquí para instalar Firefox

View File

@ -1,2 +1,4 @@
UpdateYourBrowser: Mettez à jour votre navigateur
ContinueAnyway: Continuer
BrowserVersionNotCompatible: Votre navigateur n'est pas compatible avec cette version du site
PushHereToInstallFirefox: Cliquez ici pour installer Firefox

View File

@ -1,2 +0,0 @@
UpdateYourBrowser: Upgrade your browser
ContinueAnyway: Continue anyway

View File

@ -1,2 +1,4 @@
UpdateYourBrowser: Atualize seu navegador
ContinueAnyway: Continuar de todas maneiras
BrowserVersionNotCompatible: Seu navegador não é compatível com esta versão do site
PushHereToInstallFirefox: Clique aqui para instalar o Firefox

View File

@ -1,26 +1,53 @@
*
{
* {
font-family: 'Roboto';
}
img
{
position: absolute;
margin-top: -200px;
margin-left: -200px;
top: 50%;
left: 50%;
.box {
text-align: center;
margin: 0 auto;
max-width: 380px;
padding: 40px;
padding-bottom: 60px;
}
#continue
{
position: absolute;
.logo {
padding: 5px;
max-width: 100%;
}
h2 {
font-weight: normal;
font-size: 22px;
}
.browser-logo {
display: block;
margin: 30px auto;
height: 120px;
}
.download {
display: block;
}
.bottom {
position: fixed;
bottom: 0;
left: 0;
right: 0;
margin: 1em;
text-align: center;
color: white;
}
a
{
color: #444;
.continue {
color: white;
background-color: #8cc63f;
padding: 5px;
border-radius: 3px;
}
.continue:hover {
text-decoration: none;
background-color: #7eb239;
}
a {
color: #6a1;
border-width: 0;
text-decoration: none;
}
a:hover {
text-decoration: underline;
}

View File

@ -2,20 +2,35 @@
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
<meta name="viewport" content="user-scalable=no"/>
<meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=no"/>
<meta name="content-language" content="<?=$lang?>"/>
<link href="//fonts.googleapis.com/css?family=Roboto" rel="stylesheet" type="text/css"/>
<?=css("$dir/style")?>
<title>Verdnatura</title>
</head>
<body>
<div>
<a href="http://www.mozilla.org/es-ES/firefox/new/" target="_blank">
<img src="<?=$dir?>/update-browser.png" alt="<?=s('UpdateYourBrowser')?>"></img>
<div class="box">
<img
class="logo"
src="image/logo.png"
alt="VerdNatura">
</img>
<h2><?=s('BrowserVersionNotCompatible')?></h2>
<a
class="download"
href="http://www.mozilla.org/firefox/new/"
target="_blank">
<img
class="browser-logo"
src="<?=$dir?>/firefox.png"
alt="Firefox">
</img>
<?=s('PushHereToInstallFirefox')?>
</a>
</div>
<div id="continue">
<a href="?skipBrowser=true">
<div class="bottom">
<a class="continue"
href="?skipBrowser=true">
<?=s('ContinueAnyway')?>
</a>
</div>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 62 KiB

View File

@ -1,4 +0,0 @@
{
"Recover password": "Recover password",
"Press on the following link to change your password.": "Press on the following link to change your password."
}

View File

@ -0,0 +1,2 @@
recoverPassword: Recover password
pressLinkToRecoverPassword: Press on the following link to change your password.

View File

@ -1,4 +0,0 @@
{
"Recover password": "Restaurar contraseña",
"Press on the following link to change your password.": "Pulsa en el siguiente link para cambiar tu contraseña."
}

View File

@ -0,0 +1,2 @@
recoverPassword: Restaurar contraseña
pressLinkToRecoverPassword: Pulsa en el siguiente link para cambiar tu contraseña.

View File

@ -1,4 +0,0 @@
{
"Recover password": "Réinitialisation du mot de passe",
"Press on the following link to change your password.": "Appuyez sur le lien suivant pour changer votre mot de passe."
}

View File

@ -0,0 +1,2 @@
recoverPassword: Réinitialisation du mot de passe
pressLinkToRecoverPassword: Appuyez sur le lien suivant pour changer votre mot de passe.

View File

@ -1,4 +0,0 @@
{
"Recover password": "Recuperar palavra-passe",
"Press on the following link to change your password.": "Pressione o botão para modificar sua palavra-passe."
}

View File

@ -0,0 +1,2 @@
recoverPassword: Recuperar palavra-passe
pressLinkToRecoverPassword: Pressione o botão para modificar sua palavra-passe.

View File

@ -1,7 +1,7 @@
<?php $title = s('Recover password') ?>
<?php $title = s('recoverPassword') ?>
<p>
<?=s('Press on the following link to change your password.')?>
<?=s('pressLinkToRecoverPassword')?>
</p>
<a href="<?=$url?>">
<?=s('Recover password')?>
<?=s('recoverPassword')?>
</a>

View File

@ -10,7 +10,7 @@ class Supplant extends Vn\Web\JsonRequest {
'SELECT id FROM account.user WHERE `name` = #',
[$_REQUEST['supplantUser']]
);
/*
$isClient = $db->getValue(
'SELECT COUNT(*) > 0 FROM vn.client WHERE id = #',
[$userId]
@ -24,7 +24,7 @@ class Supplant extends Vn\Web\JsonRequest {
);
if ($hasAccount)
throw new Web\ForbiddenException(s('The user is not impersonable'));
*/
return $this->service->createToken($_REQUEST['supplantUser']);
}
}

View File

@ -1,5 +0,0 @@
{
"InvalidAction": "Acció invàlida"
,"EmptyQuery": "Consulta buida"
}

2
rest/core/locale/ca.yml Normal file
View File

@ -0,0 +1,2 @@
InvalidAction: Acció invàlida
EmptyQuery: Consulta buida

View File

@ -1,5 +0,0 @@
{
"InvalidAction": "Invalid action"
,"EmptyQuery": "Empty query"
}

2
rest/core/locale/en.yml Normal file
View File

@ -0,0 +1,2 @@
InvalidAction: Invalid action
EmptyQuery: Empty query

View File

@ -1,7 +0,0 @@
{
"InvalidAction": "Acción inválida"
,"EmptyQuery": "Consulta vacía"
,"Invalid password": "Contraseña inválida"
,"Password does not meet requirements":
"La nueva contraseña no reune los requisitos de seguridad necesarios"
}

2
rest/core/locale/es.yml Normal file
View File

@ -0,0 +1,2 @@
InvalidAction: Acción inválida
EmptyQuery: Consulta vacía

View File

@ -1,5 +0,0 @@
{
"InvalidAction": "Action non valide"
,"EmptyQuery": "Requête vide"
}

2
rest/core/locale/fr.yml Normal file
View File

@ -0,0 +1,2 @@
InvalidAction: Action non valide
EmptyQuery: Requête vide

View File

@ -1,5 +0,0 @@
{
"InvalidAction": "Ação Inválida"
,"EmptyQuery": "Consulta vazía"
}

2
rest/core/locale/pt.yml Normal file
View File

@ -0,0 +1,2 @@
InvalidAction: Ação Inválida
EmptyQuery: Consulta vazía

View File

@ -22,53 +22,34 @@ class Query extends Vn\Web\JsonRequest {
function run($db) {
$results = [];
$db->multiQuery($_REQUEST['sql']);
try {
$db->multiQuery($_REQUEST['sql']);
do {
$result = $db->storeResult();
do {
$result = $db->storeResult();
if ($result !== FALSE) {
$results[] = $this->transformResult($result);
$result->free();
} else
$results[] = TRUE;
}
while ($db->moreResults() && $db->nextResult());
if ($result !== FALSE) {
$results[] = $this->transformResult($result);
$result->free();
} else
$results[] = TRUE;
if ($db->checkWarnings()
&&($result = $db->query('SHOW WARNINGS'))) {
$sql = 'SELECT `description`, @warn `code`
FROM `message` WHERE `code` = @warn';
while ($row = $result->fetch_object()) {
if ($row->Code == 1265
&&($warning = $db->getObject($sql)))
trigger_error("{$warning->code}: {$warning->description}", E_USER_WARNING);
else
trigger_error("{$row->Code}: {$row->Message}", E_USER_WARNING);
}
while ($db->moreResults() && $db->nextResult());
// Checks for warnings
if ($db->checkWarnings()
&&($result = $db->query('SHOW WARNINGS'))) {
$sql = 'SELECT `description`, @warn `code`
FROM `message` WHERE `code` = @warn';
while ($row = $result->fetch_object()) {
if ($row->Code == 1265
&&($warning = $db->getObject($sql)))
trigger_error("{$warning->code}: {$warning->description}", E_USER_WARNING);
else
trigger_error("{$row->Code}: {$row->Message}", E_USER_WARNING);
}
}
// Checks for errors
$db->checkError();
} catch (Vn\Db\Exception $e) {
if ($e->getCode() == 1644) {
$dbMessage = $e->getMessage();
$sql = 'SELECT `description` FROM `message` WHERE `code` = #';
$message = $db->getValue($sql, [$dbMessage]);
if ($message)
throw new Lib\UserException($message, $dbMessage);
}
throw $e;
}
$db->checkError();
return $results;
}

View File

@ -1,29 +0,0 @@
{
"Cant lock cache": "The cache could not be blocked"
,"Bad file format": "Unrecognized file format"
,"File not choosed": "You have not selected any file"
,"Permission denied": "You are not allowed to upload the file"
,"File upload error": "Failed to upload the file, check that size is not too large"
,"File save error": "Failed to save the file: %s"
,"File size error": "The file must be no longer than %.2f MB"
,"Bad file name": "The file name must contain only lowercase letters, digits or the '_' character"
,"Bad collection name": "Invalid collection name"
,"Collection not exists": "Collection does not exist"
,"Unreferenced file": "The file is not referenced by the database"
,"Cannot update matching id": "Cannot update matching id"
,"Com error": "Error communicating with the server"
,"Image open error": "Error opening the image file"
,"Operation disabled": "Operation disabled for security"
,"Image added": "Image added correctly"
,"ErrIniSize": "File exceeds the upload_max_filesize directive in php.ini"
,"ErrFormSize": "File exceeds the MAX_FILE_SIZE specified in the HTML form"
,"ErrPartial": "File was partially uploaded"
,"ErrNoFile": "No file was uploaded"
,"ErrNoTmpDir": "Missing a temporary folder"
,"ErrCantWrite": "Failed to write file to disk"
,"ErrExtension": "File upload stopped by extension"
,"ErrDefault": "Unknown upload error"
,"Sync complete": "Synchronization complete"
}

27
rest/image/locale/en.yml Normal file
View File

@ -0,0 +1,27 @@
Cant lock cache: The cache could not be blocked
Bad file format: Unrecognized file format
File not choosed: You have not selected any file
Permission denied: You are not allowed to upload the file
File upload error: Failed to upload the file, check that size is not too large
File save error: 'Failed to save the file: %s'
File size error: The file must be no longer than %.2f MB
Bad file name: 'The file name must contain only lowercase letters, digits or the ''_'' character'
Bad collection name: Invalid collection name
Collection not exists: Collection does not exist
Unreferenced file: The file is not referenced by the database
Cannot update matching id: Cannot update matching id
Com error: Error communicating with the server
Image open error: Error opening the image file
Operation disabled: Operation disabled for security
Image added: Image added correctly
ErrIniSize: File exceeds the upload_max_filesize directive in php.ini
ErrFormSize: File exceeds the MAX_FILE_SIZE specified in the HTML form
ErrPartial: File was partially uploaded
ErrNoFile: No file was uploaded
ErrNoTmpDir: Missing a temporary folder
ErrCantWrite: Failed to write file to disk
ErrExtension: File upload stopped by extension
ErrDefault: Unknown upload error
Sync complete: Synchronization complete

View File

@ -1,29 +0,0 @@
{
"Cant lock cache": "La caché no pudo ser bloqueada"
,"Bad file format": "Formato de archivo no reconocido"
,"File not choosed": "No has seleccionado ningún archivo"
,"Permission denied": "No tienes permiso para subir el fichero"
,"File upload error": "Error al subir el fichero, comprueba que su tamaño no sea demasiado grande"
,"File save error": "Error al guardar el fichero: %s"
,"File size error": "El fichero no debe ocupar más de %.2f MB"
,"Bad file name": "El nombre del archivo solo debe contener letras minúsculas, dígitos o el carácter '_'"
,"Bad collection name": "Nombre de colección no válido"
,"Collection not exists": "La colección no existe"
,"Unreferenced file": "El archivo no está referenciado por la base de datos"
,"Cannot update matching id": "No es posible actualizar los ítems con id coincidente"
,"Com error": "Error en la comunicación con el servidor"
,"Image open error": "Error al abrir el archivo de imagen"
,"Operation disabled": "Operación deshabilitada por seguridad"
,"Image added": "Imagen añadida correctamente"
,"ErrIniSize": "File exceeds the upload_max_filesize directive in php.ini"
,"ErrFormSize": "File exceeds the MAX_FILE_SIZE specified in the HTML form"
,"ErrPartial": "File was partially uploaded"
,"ErrNoFile": "No file was uploaded"
,"ErrNoTmpDir": "Missing a temporary folder"
,"ErrCantWrite": "Failed to write file to disk"
,"ErrExtension": "File upload stopped by extension"
,"ErrDefault": "Unknown upload error"
,"Sync complete": "Sincronización completada"
}

27
rest/image/locale/es.yml Normal file
View File

@ -0,0 +1,27 @@
Cant lock cache: La caché no pudo ser bloqueada
Bad file format: Formato de archivo no reconocido
File not choosed: No has seleccionado ningún archivo
Permission denied: No tienes permiso para subir el fichero
File upload error: Error al subir el fichero, comprueba que su tamaño no sea demasiado grande
File save error: 'Error al guardar el fichero: %s'
File size error: El fichero no debe ocupar más de %.2f MB
Bad file name: 'El nombre del archivo solo debe contener letras minúsculas, dígitos o el carácter ''_'''
Bad collection name: Nombre de colección no válido
Collection not exists: La colección no existe
Unreferenced file: El archivo no está referenciado por la base de datos
Cannot update matching id: No es posible actualizar los ítems con id coincidente
Com error: Error en la comunicación con el servidor
Image open error: Error al abrir el archivo de imagen
Operation disabled: Operación deshabilitada por seguridad
Image added: Imagen añadida correctamente
ErrIniSize: File exceeds the upload_max_filesize directive in php.ini
ErrFormSize: File exceeds the MAX_FILE_SIZE specified in the HTML form
ErrPartial: File was partially uploaded
ErrNoFile: No file was uploaded
ErrNoTmpDir: Missing a temporary folder
ErrCantWrite: Failed to write file to disk
ErrExtension: File upload stopped by extension
ErrDefault: Unknown upload error
Sync complete: Sincronización completada

View File

@ -1,29 +0,0 @@
{
"Cant lock cache": "O cache não pôde ser bloqueado"
,"Bad file format": "Formato de arquivo inválido"
,"File not choosed": "Não selecionastes nenhum arquivo"
,"Permission denied": "Não estas autorizado a subir o arquivo"
,"File upload error": "Erro ao subir o arquivo, verifique o tamanho"
,"File save error": "Erro ao salvar o arquivo: %s"
,"File size error": "O arquivo não deve ser maior que: %.2f MB"
,"Bad file name": "O nome do arquivo deve conter somente letras minusculas, numeros ou '_' "
,"Bad collection name": "Nome de coleção inválido"
,"Collection not exists": "Coleção não existe"
,"Unreferenced file": "O arquivo não é referenciado pelo banco de dados"
,"Cannot update matching id": "Não é possível atualizar os itens com id coincidente"
,"Com error": "Erro de comunicação com o servidor"
,"Image open error": "Erro ao abrir a imagem"
,"Operation disabled": "Operação desativada por segurança"
,"Image added": "Imagem adicionada corretamente"
,"ErrIniSize": "Arquivo supera o tamanho maximo de protocolo em php.ini"
,"ErrFormSize": "Arquivo supera o tamanho maximo de protocolo em HTML form"
,"ErrPartial": "Arquivo subido parcialmente"
,"ErrNoFile": "Nenhum arquivo subido"
,"ErrNoTmpDir": "Falta a pasta de arquivo temporal"
,"ErrCantWrite": "Erro ao gravar arquivo no disco"
,"ErrExtension": "Erro de extensão do arquivo"
,"ErrDefault": "Erro desconhecido ao subir arquivo"
,"Sync complete": "Sincronização completa"
}

Some files were not shown because too many files have changed in this diff Show More