0
1
Fork 0

Merge branch 'test'

This commit is contained in:
Juan Ferrer 2022-11-10 21:57:43 +01:00
commit d4a7f41600
408 changed files with 13178 additions and 27673 deletions

2
debian/changelog vendored
View File

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

1
debian/source.lintian-overrides vendored Normal file
View File

@ -0,0 +1 @@
hedera-web: package-contains-npm-ignore-file

View File

@ -1,41 +1,40 @@
Hedera.AddressList = new Class Hedera.AddressList = new Class({
({
Extends: Hedera.Form Extends: Hedera.Form
,activate: function () ,activate: function() {
{ this.$.userModel.setInfo('c', 'myClient', 'hedera');
this.$('user-model').setInfo ('c', 'myClient', 'hedera'); this.$.addresses.setInfo('a', 'myAddress', 'hedera');
this.$('addresses').setInfo ('a', 'myAddress', 'hedera');
} }
,onAddAddressClick: function () ,onAddAddressClick: function() {
{ this.hash.setAll({
this.hash.set ({
form: 'account/address', form: 'account/address',
address: 0 address: 0
}); });
} }
,onReturnClick: function () ,onReturnClick: function() {
{
window.history.back(); window.history.back();
} }
,onSetDefaultClick: function(event, addressId) {
if (event.defaultPrevented) return;
this.$.defaultAddress.value = addressId;
Htk.Toast.showMessage(_('DefaultAddressModified'));
}
,onRemoveAddressClick: function (button, form) ,onRemoveAddressClick: function(form) {
{ if (confirm(_('AreYouSureDeleteAddress'))) {
if (confirm (_('AreYouSureDeleteAddress'))) form.set('isActive', false);
{ form.refresh();
form.set ('isActive', false);
form.refresh ();
} }
} }
,onEditAddressClick: function (button, form) ,onEditAddressClick: function(id) {
{ this.hash.setAll({
this.hash.set ({
form: 'account/address', form: 'account/address',
address: form.get ('id') address: id
}); });
} }
}); });

View File

@ -1,7 +1,8 @@
Addresses: Direccions Addresses: Adreces
Return: Tornar Return: Tornar
AddAddress: Afegir adreça AddAddress: Afegir adreça
SetAsDefault: Establir com per defecte SetAsDefault: Establir com per defecte
RemoveAddress: Esborrar direcció RemoveAddress: Esborrar direcció
EditAddress: Modificar direcció EditAddress: Modificar direcció
AreYouSureDeleteAddress: Estàs segur de que vols eliminar la direcció? AreYouSureDeleteAddress: Estàs segur de que vols eliminar la direcció?
DefaultAddressModified: Adreça per defecte modificada

View File

@ -5,3 +5,4 @@ SetAsDefault: Set as default
RemoveAddress: Remove address RemoveAddress: Remove address
EditAddress: Edit address EditAddress: Edit address
AreYouSureDeleteAddress: Are you sure you want to delete the address? AreYouSureDeleteAddress: Are you sure you want to delete the address?
DefaultAddressModified: Default address modified

View File

@ -5,3 +5,4 @@ SetAsDefault: Establecer como predeterminada
RemoveAddress: Borrar dirección RemoveAddress: Borrar dirección
EditAddress: Modificar dirección EditAddress: Modificar dirección
AreYouSureDeleteAddress: ¿Estás seguro de que quieres borrar la dirección? AreYouSureDeleteAddress: ¿Estás seguro de que quieres borrar la dirección?
DefaultAddressModified: Dirección por defecto modificada

View File

@ -5,3 +5,4 @@ SetAsDefault: Définir par défaut
RemoveAddress: Supprimer l'adresse RemoveAddress: Supprimer l'adresse
EditAddress: Changement d'adresse EditAddress: Changement d'adresse
AreYouSureDeleteAddress: Souhaitez-vous vraiment supprier l'adresse? AreYouSureDeleteAddress: Souhaitez-vous vraiment supprier l'adresse?
DefaultAddressModified: Adresse par défaut modifiée

View File

@ -5,3 +5,4 @@ SetAsDefault: Selecionar como pre-determinado
RemoveAddress: Eliminar Morada RemoveAddress: Eliminar Morada
EditAddress: Modificar Morada EditAddress: Modificar Morada
AreYouSureDeleteAddress: Tens certeza que queres eliminar esta morada? AreYouSureDeleteAddress: Tens certeza que queres eliminar esta morada?
DefaultAddressModified: Endereço padrão modificado

View File

@ -1,48 +1,4 @@
.address-list .address-list .htk-list .side {
{ padding-right: 16px;
padding: 1em;
}
.address-list .box
{
max-width: 30em;
}
.address-list .form
{
margin: 0 auto;
max-width: 25em;
padding: 2em;
}
.address
{
padding: 1em;
border-bottom: 1px solid #DDD;
}
.address p
{
margin: 0.2em 0;
text-overflow: ellipsis;
white-space: nowrap;
overflow: hidden;
}
.address p.important
{
font-size: 1.2em;
}
.address .actions
{
float: right;
}
.address .actions > .htk-button
{
margin: 0;
}
.address .actions > *
{
display: inline-block;
vertical-align: middle;
}
.address .actions > input
{
margin: .6em;
} }

View File

@ -2,20 +2,16 @@
<vn-group> <vn-group>
<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">
<custom> SELECT id, defaultAddressFk
SELECT id, defaultAddressFk FROM myClient c
FROM myClient c
</custom>
</db-model> </db-model>
</db-form> </db-form>
<db-model id="addresses" updatable="true"> <db-model id="addresses" updatable="true">
<custom> SELECT a.id, a.nickname, p.name province, a.postalCode,
SELECT a.id, a.nickname, p.name province, a.postalCode, a.city, a.street, a.isActive
a.city, a.street, a.isActive FROM myAddress a
FROM myAddress a LEFT JOIN vn.province p ON p.id = a.provinceFk
LEFT JOIN vn.province p ON p.id = a.provinceFk WHERE a.isActive
WHERE a.isActive
</custom>
</db-model> </db-model>
</vn-group> </vn-group>
<div id="title"> <div id="title">
@ -25,46 +21,47 @@
<htk-bar-button <htk-bar-button
icon="add" icon="add"
tip="_AddAddress" tip="_AddAddress"
on-click="onAddAddressClick"/> on-click="this.onAddAddressClick()"/>
</div> </div>
<div id="form" class="address-list"> <div id="form" class="address-list">
<div class="box"> <div class="box vn-w-sm">
<htk-radio-group <htk-radio-group
id="default-address" id="default-address"
column="defaultAddressFk" column="defaultAddressFk"
form="user-form"/> form="user-form"/>
<htk-repeater model="addresses" form-id="iter"> <htk-repeater model="addresses" form-id="address" class="htk-list">
<custom> <custom>
<div class="address"> <div class="item clickable" on-click="this.onSetDefaultClick($event, address.id)">
<div class="actions"> <div class="side">
<htk-radio <htk-radio
form="iter"
column="id"
radio-group="default-address" radio-group="default-address"
tip="_SetAsDefault"/> val="{{address.id}}"
<htk-button tip="_SetAsDefault"
form="iter" name="test"/>
column="id" </div>
tip="_RemoveAddress" <div class="content">
icon="delete" <p class="important">
on-click="onRemoveAddressClick"/> {{address.nickname}}
<htk-button </p>
form="iter" <p>
column="id" {{address.street}}
tip="_EditAddress" </p>
icon="edit" <p>
on-click="onEditAddressClick"/> {{address.postalCode}}, {{address.city}}
</p>
</div>
<div
class="actions"
on-click="$event.preventDefault()">
<htk-button
icon="delete"
tip="_RemoveAddress"
on-click="this.onRemoveAddressClick($iter)"/>
<htk-button
icon="edit"
tip="_EditAddress"
on-click="this.onEditAddressClick(address.id)"/>
</div> </div>
<p class="important">
<htk-text form="iter" column="nickname"/>
</p>
<p>
<htk-text form="iter" column="street"/>
</p>
<p>
<htk-text form="iter" column="postalCode"/>,
<htk-text form="iter" column="city"/>
</p>
</div> </div>
</custom> </custom>
</htk-repeater> </htk-repeater>

View File

@ -3,26 +3,18 @@ Hedera.Address = new Class({
Extends: Hedera.Form, Extends: Hedera.Form,
activate: function() { activate: function() {
this.$('model').setInfo('a', 'myAddress', 'hedera', ['id'], 'id'); this.$.model.setInfo('a', 'myAddress', 'hedera', ['id'], 'id');
this.$('model').setDefault('clientFk', 'a', this.$.model.setDefault('clientFk', 'a',
new Sql.Function({schema: 'account', name: 'myUser_getId'})); new Sql.Function({schema: 'account', name: 'myUser_getId'}));
}, },
onStatusChange: function(form) { onStatusChange: function() {
if (form.ready && this.$('address').value == 0) if (this.$.iter.ready && this.hash.$.address == 0)
form.insertRow(); this.$.iter.insertRow();
}, },
onOperationsDone: function() { onOperationsDone: function() {
Htk.Toast.showMessage(_('AddressChangedSuccessfully')); Htk.Toast.showMessage(_('AddressChangedSuccessfully'));
this.onReturnClick(); window.history.back()
},
onAcceptClick: function() {
this.$('iter').performOperations();
},
onReturnClick: function() {
window.history.back();
} }
}); });

View File

@ -1,16 +0,0 @@
.address
{
padding: 1em;
}
.address .box
{
max-width: 30em;
padding: 2em;
}
.address .form
{
margin: 0 auto;
max-width: 25em;
}

View File

@ -1,89 +1,86 @@
<vn> <vn>
<vn-group> <vn-group>
<vn-param id="address"/> <vn-lot-query id="params">
<vn-hash-param key="address" param="address"/> <vn-spec name="address" type="Number"/>
<db-form id="iter" on-status-changed="onStatusChange"> </vn-lot-query>
<db-form id="iter" on-status-changed="this.onStatusChange()">
<db-model <db-model
id="model" id="model"
property="model" property="model"
updatable="true" updatable="true"
mode="ON_DEMAND" mode="ON_DEMAND"
on-operations-done="onOperationsDone"> lot="params"
on-operations-done="this.onOperationsDone()">
SELECT a.id, a.street, a.nickname, a.city, SELECT a.id, a.street, a.nickname, a.city,
a.postalCode, a.provinceFk, p.countryFk a.postalCode, a.provinceFk, p.countryFk
FROM myAddress a FROM myAddress a
LEFT JOIN vn.province p ON p.id = a.provinceFk LEFT JOIN vn.province p ON p.id = a.provinceFk
WHERE a.id = #address WHERE a.id = #address
<sql-batch property="batch">
<custom>
<item name="address" param="address"/>
</custom>
</sql-batch>
</db-model> </db-model>
</db-form> </db-form>
</vn-group> </vn-group>
<div id="title"> <div id="title">
<h1><t>AddEditAddress</t></h1> <h1><t>Configuration</t></h1>
</div> </div>
<div id="actions"> <div id="actions">
<htk-bar-button
icon="ok"
tip="_Accept"
on-click="onAcceptClick"/>
<htk-bar-button <htk-bar-button
icon="close" icon="close"
tip="_Return" tip="_Return"
on-click="onReturnClick"/> on-click="window.history.back()"/>
<htk-bar-button
icon="check"
tip="_Accept"
on-click="iter.performOperations()"/>
</div> </div>
<div id="form" class="address"> <div id="form" class="address">
<div class="box"> <div class="form box vn-w-sm vn-pa-lg">
<div class="form"> <h5 class="vn-mb-md">
<div class="form-group"> <t>AddEditAddress</t>
<label><t>Name</t></label> </h5>
<htk-entry column="nickname" form="iter"/> <div class="form-group">
</div> <htk-entry
<div class="form-group"> placeholder="_Name"
<label><t>Address</t></label> form="iter" column="nickname"/>
<htk-entry column="street" form="iter"/> </div>
</div> <div class="form-group">
<div class="form-group"> <htk-entry
<label><t>City</t></label> placeholder="_Address"
<htk-entry column="city" form="iter"/> form="iter" column="street"/>
</div> </div>
<div class="form-group"> <div class="form-group">
<label><t>ZipCode</t></label> <htk-entry
<htk-entry column="postalCode" form="iter"/> placeholder="_City"
</div> form="iter" column="city"/>
<div class="form-group"> </div>
<label><t>Country</t></label> <div class="form-group">
<htk-combo> <htk-entry
<db-param placeholder="_ZipCode"
id="country" form="iter" column="postalCode"/>
property="param" </div>
form="iter" <div class="form-group">
column="countryFk" <htk-combo
one-way="true"/> placeholder="_Country"
<db-model property="model"> form="iter" column="countryFk"
SELECT id, country FROM vn.country id="country"
ORDER BY country one-way="true"
</db-model> one-time="true">
</htk-combo> <db-model property="model">
</div> SELECT id, country FROM vn.country
<div class="form-group"> ORDER BY country
<label><t>Province</t></label> </db-model>
<htk-combo column="provinceFk" form="iter"> </htk-combo>
<db-model property="model"> </div>
SELECT id, name FROM vn.province <div class="form-group">
WHERE countryFk = #country <htk-combo
ORDER BY name placeholder="_Province"
<sql-batch property="batch"> column="provinceFk"
<custom> form="iter">
<item name="country" param="country"/> <db-model property="model" lot="country">
</custom> SELECT id, name FROM vn.province
</sql-batch> WHERE countryFk = #id
</db-model> ORDER BY name
</htk-combo> </db-model>
</div> </htk-combo>
</div> </div>
</div> </div>
</div> </div>

View File

@ -3,45 +3,45 @@ Hedera.Conf = new Class({
Extends: Hedera.Form Extends: Hedera.Form
,activate: function() { ,activate: function() {
this.$('user-model').setInfo('c', 'myClient', 'hedera'); this.$.userModel.setInfo('c', 'myClient', 'hedera');
this.$('user-model').setInfo('u', 'myUser', 'account'); this.$.userModel.setInfo('u', 'myUser', 'account');
if (this.hash.get('verificationToken')) if (this.hash.$.verificationToken)
this.onPassChangeClick(); this.onPassChangeClick();
} }
,onPassChangeClick: function() {
this.$('old-password').value = '';
this.$('new-password').value = '';
this.$('repeat-password').value = '';
var verificationToken = this.hash.get('verificationToken'); ,onPassChangeClick: function() {
this.$('old-password').style.display = verificationToken ? 'none' : 'block'; this.$.oldPassword.value = '';
this.$('change-password').show(); this.$.newPassword.value = '';
this.$.repeatPassword.value = '';
var verificationToken = this.hash.$.verificationToken;
this.$.oldPassword.style.display = verificationToken ? 'none' : 'block';
this.$.changePassword.show();
if (verificationToken) if (verificationToken)
this.$('new-password').focus(); this.$.newPassword.focus();
else else
this.$('old-password').focus(); this.$.oldPassword.focus();
} }
,onPassModifyClick: function() { ,onPassModifyClick: function() {
try { try {
var oldPassword = this.$('old-password').value; var oldPassword = this.$.oldPassword.value;
var newPassword = this.$('new-password').value; var newPassword = this.$.newPassword.value;
var repeatedPassword = this.$('repeat-password').value; var repeatedPassword = this.$.repeatPassword.value;
if (newPassword == '' && repeatedPassword == '') if (newPassword == '' && repeatedPassword == '')
throw new Error(_('Passwords empty')); throw new Error(_('Passwords empty'));
if (newPassword !== repeatedPassword) if (newPassword !== repeatedPassword)
throw new Error(_('Passwords doesn\'t match')); throw new Error(_('Passwords doesn\'t match'));
var verificationToken = this.hash.get('verificationToken'); var verificationToken = this.hash.$.verificationToken;
var params = {newPassword: newPassword}; var params = {newPassword: newPassword};
if (verificationToken) { if (verificationToken) {
params.verificationToken = verificationToken; params.verificationToken = verificationToken;
this.conn.send('core/restore-password', params, this.conn.send('user/restore-password', params,
this._onPassChange.bind(this)); this._onPassChange.bind(this));
} else { } else {
let userId = this.gui.user.id; let userId = this.gui.user.id;
@ -58,26 +58,22 @@ Hedera.Conf = new Class({
,_onPassChange: function(json, error) { ,_onPassChange: function(json, error) {
if (!error) { if (!error) {
this.$('change-password').hide(); this.$.changePassword.hide();
this.hash.unset('verificationToken'); this.hash.unset('verificationToken');
Htk.Toast.showMessage(_('Password changed!')); Htk.Toast.showMessage(_('Password changed!'));
this.$('user-form').refresh(); this.$.userForm.refresh();
} else { } else {
Htk.Toast.showError(error.message); Htk.Toast.showError(error.message);
if (this.hash.get('verificationToken')) if (this.hash.$.verificationToken)
this.$('new-password').select(); this.$.newPassword.select();
else else
this.$('old-password').select(); this.$.oldPassword.select();
} }
} }
,onPassInfoClick: function() { ,onPassInfoClick: function() {
this.$('password-info').show(); this.$.passwordInfo.show();
}
,onAddressesClick: function() {
this.hash.set({form: 'account/address-list'});
} }
}); });

View File

@ -1,4 +1,5 @@
Configuration: Configuració Configuration: Configuració
Personal information: Dades personals
Username: Nom d'usuari Username: Nom d'usuari
Password: Contrasenya Password: Contrasenya
Email: Correu electrònic Email: Correu electrònic
@ -9,7 +10,7 @@ Receive invoices by email: Rebre factures per correu electrònic
Old password: Contrasenya antiga Old password: Contrasenya antiga
New password: Nova contrasenya New password: Nova contrasenya
Repeat password: Repetir contrasenya Repeat password: Repetir contrasenya
Info: Info Requirements: Requisits
Modify: Modificar Modify: Modificar
Password requirements: Requisits de contrasenya Password requirements: Requisits de contrasenya
characters long: caràcters de longitud characters long: caràcters de longitud

View File

@ -1,4 +1,5 @@
Configuration: Configuration Configuration: Configuration
Personal information: Personal information
Username: Username Username: Username
Password: Password Password: Password
Email: Email Email: Email
@ -9,7 +10,7 @@ Receive invoices by email: Receive invoices by email
Old password: Old password Old password: Old password
New password: New password New password: New password
Repeat password: Repeat password Repeat password: Repeat password
Info: Info Requirements: Requirements
Modify: Modify Modify: Modify
Password requirements: Password requirements Password requirements: Password requirements
characters long: characters long characters long: characters long

View File

@ -1,4 +1,5 @@
Configuration: Configuración Configuration: Configuración
Personal information: Datos personales
Username: Nombre de usuario Username: Nombre de usuario
Password: Contraseña Password: Contraseña
Email: Correo electrónico Email: Correo electrónico
@ -9,7 +10,7 @@ Receive invoices by email: Recibir facturas por correo electrónico
Old password: Contaseña antigua Old password: Contaseña antigua
New password: Nueva contraseña New password: Nueva contraseña
Repeat password: Repetir contraseña Repeat password: Repetir contraseña
Info: Info Requirements: Requisitos
Modify: Modificar Modify: Modificar
Password requirements: Requisitos de constraseña Password requirements: Requisitos de constraseña
characters long: carácteres de longitud characters long: carácteres de longitud

View File

@ -1,4 +1,5 @@
Configuration: Configuration Configuration: Configuration
Personal information: Informations personnelles
Username: Utilisateur Username: Utilisateur
Password: Mot de passe Password: Mot de passe
Email: Courriel Email: Courriel
@ -9,7 +10,7 @@ Receive invoices by email: Recevoir des factures par e-mail
Old password: Ancien mot de passe Old password: Ancien mot de passe
New password: Nouveau mot de passe New password: Nouveau mot de passe
Repeat password: Répéter le mot de passe Repeat password: Répéter le mot de passe
Info: Info Requirements: Exigences
Modify: Modifier Modify: Modifier
Password requirements: Mot de passe exigences Password requirements: Mot de passe exigences
characters long: Longs caractères characters long: Longs caractères

View File

@ -1,4 +1,5 @@
Configuration: Configuração Configuration: Configuração
Personal information: Dados pessoais
Username: Nome de usuario Username: Nome de usuario
Password: Palavra-Passe Password: Palavra-Passe
Email: E-Mail Email: E-Mail
@ -9,7 +10,7 @@ Receive invoices by email: Receber facturas por e-mail
Old password: Palavra-Passe antiga Old password: Palavra-Passe antiga
New password: Nova Palavra-Passe New password: Nova Palavra-Passe
Repeat password: Repetir Palavra-Passe Repeat password: Repetir Palavra-Passe
Info: Info Requirements: Requisitos
Modify: Modificar Modify: Modificar
Password requirements: Requisitos de Palavra-Passe Password requirements: Requisitos de Palavra-Passe
characters long: caracteres characters long: caracteres

View File

@ -1,33 +1,4 @@
.conf .pass-info ul {
{
padding: 1em;
}
.conf .box
{
max-width: 30em;
padding: 2em;
}
.conf .form
{
margin: 0 auto;
max-width: 25em;
}
.conf .form-group input[type=password]
{
margin-bottom: 0.5em;
}
.pass-change
{
max-width: 15em;
}
.pass-info
{
width: 15em;
}
.pass-info ul
{
list-style-type: none; list-style-type: none;
} }

View File

@ -1,22 +1,18 @@
<vn> <vn>
<vn-group> <vn-group>
<db-form id="password-form"> <db-form v-model="passwordForm">
<db-model property="model"> <db-model property="model">
<custom> SELECT length, nAlpha, nUpper, nDigits, nPunct
SELECT length, nAlpha, nUpper, nDigits, nPunct FROM account.userPassword
FROM account.userPassword
</custom>
</db-model> </db-model>
</db-form> </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">
<custom> SELECT u.id, u.name, u.email, u.nickname,
SELECT u.id, u.name, u.email, u.nickname, u.lang, c.isToBeMailed, c.id clientFk
u.lang, c.isToBeMailed, c.id clientFk FROM account.myUser u
FROM account.myUser u LEFT JOIN myClient c
LEFT JOIN myClient c ON u.id = c.id
ON u.id = c.id
</custom>
</db-model> </db-model>
</db-form> </db-form>
</vn-group> </vn-group>
@ -27,49 +23,65 @@
<htk-bar-button <htk-bar-button
icon="place" icon="place"
tip="_Addresses" tip="_Addresses"
on-click="onAddressesClick"/> on-click="hash.setAll({form: 'account/address-list'})"/>
<htk-bar-button <htk-bar-button
icon="preferences" icon="lock_reset"
tip="_Change password" tip="_Change password"
on-click="onPassChangeClick"/> on-click="this.onPassChangeClick()"/>
</div> </div>
<div id="form" class="conf"> <div id="form" class="conf">
<div class="box"> <div class="form box vn-w-sm vn-pa-lg">
<div class="form"> <h5 class="vn-mb-md">
<div class="form-group"> <t>Personal information</t>
<label for="user-name"><t>Username</t></label> </h5>
<htk-text form="user-form" column="name"/> <div class="form-group">
</div> <htk-entry
<div class="form-group"> placeholder="_Username"
<label for="email"><t>Email</t></label> disabled="true"
<htk-entry form="user-form" column="email"></htk-entry> form="user-form"
</div> column="name"/>
<div class="form-group"> </div>
<label for="nickname"><t>Display name</t></label> <div class="form-group">
<htk-entry form="user-form" column="nickname"/> <htk-entry
</div> placeholder="_Email"
<div class="form-group"> form="user-form"
<label for="lang"><t>Language</t></label> column="email">
<htk-combo form="user-form" column="lang"> </htk-entry>
<db-model property="model"> </div>
<custom> <div class="form-group">
SELECT code, name FROM language WHERE isActive <htk-entry
</custom> placeholder="_Display name"
</db-model> form="user-form"
</htk-combo> column="nickname"/>
</div> </div>
<div class="form-group"> <div class="form-group">
<label for="mail"><t>Receive invoices by email</t></label> <htk-combo
placeholder="_Language"
form="user-form"
column="lang">
<db-model property="model">
<custom>
SELECT code, name FROM language WHERE isActive
</custom>
</db-model>
</htk-combo>
</div>
<div class="form-group">
<label>
<htk-check form="user-form" column="isToBeMailed"/> <htk-check form="user-form" column="isToBeMailed"/>
</div> <t>Receive invoices by email</t>
</label>
</div> </div>
</div> </div>
</div> </div>
<htk-popup <htk-popup
id="change-password" id="change-password"
modal="true"> modal="true">
<div property="child-node" class="htk-dialog pass-change"> <div property="child-node" class="htk-dialog vn-w-xs vn-pa-lg">
<div> <div class="form">
<h5 class="vn-mb-md">
<t>Change password</t>
</h5>
<input <input
id="old-password" id="old-password"
type="password" type="password"
@ -84,11 +96,11 @@
placeholder="_Repeat password"/> placeholder="_Repeat password"/>
</div> </div>
<div class="button-bar"> <div class="button-bar">
<button class="thin" on-click="onPassModifyClick"> <button class="thin" on-click="this.onPassModifyClick()">
<t>Modify</t> <t>Modify</t>
</button> </button>
<button class="thin" on-click="onPassInfoClick"> <button class="thin" on-click="this.onPassInfoClick()">
<t>Info</t> <t>Requirements</t>
</button> </button>
<div class="clear"/> <div class="clear"/>
</div> </div>
@ -97,30 +109,25 @@
<htk-popup <htk-popup
id="password-info" id="password-info"
modal="true"> modal="true">
<div property="child-node" class="htk-dialog pass-info"> <div property="child-node" class="htk-dialog pass-info vn-w-xs vn-pa-lg">
<h3> <h5 class="vn-mb-md">
<t>Password requirements</t> <t>Password requirements</t>
</h3> </h5>
<ul> <ul>
<li> <li>
<htk-text form="password-form" column="length"/> {{passwordForm.length}} <t>characters long</t>
<t>characters long</t>
</li> </li>
<li> <li>
<htk-text form="password-form" column="nAlpha"/> {{passwordForm.nAlpha}} <t>alphabetic characters</t>
<t>alphabetic characters</t>
</li> </li>
<li> <li>
<htk-text form="password-form" column="nUpper"/> {{passwordForm.nUpper}} <t>capital letters</t>
<t>capital letters</t>
</li> </li>
<li> <li>
<htk-text form="password-form" column="nDigits"/> {{passwordForm.nDigits}} <t>digits</t>
<t>digits</t>
</li> </li>
<li> <li>
<htk-text form="password-form" column="nPunct"/> {{passwordForm.nPunct}} <t>symbols</t>
<t>symbols</t>
</li> </li>
</ul> </ul>
</div> </div>

View File

@ -1,6 +1,5 @@
Hedera.AccessLog = new Class Hedera.AccessLog = new Class({
({
Extends: Hedera.Form Extends: Hedera.Form
}); });

View File

@ -1,36 +1,12 @@
.access-log
{ .access-log .form > p {
padding: 1em;
}
.access-log .box
{
max-width: 25em;
margin: 0 auto;
}
.access-log .form
{
padding: 2em;
}
.access-log .form > p
{
font-size: 1.2em; font-size: 1.2em;
margin: .1em 0; margin: .1em 0;
} }
/* List */ /* List */
.access-log .list .access-log .htk-list {
{ margin-top: 16px;
margin-top: 1em;
}
.access-log .item
{
display: block;
padding: 1em;
border-bottom: 1px solid #DDD;
}
.access-log .item > p
{
margin: .1em 0;
} }

View File

@ -1,18 +1,12 @@
<vn> <vn>
<vn-group> <vn-group>
<vn-param id="user"/> <db-form v-model="user">
<vn-hash-param key="user" param="user"/> <db-model property="model" lot="hash">
<db-form id="user-form"> SELECT u.id, u.name user, u.nickname, u.email, c.phone, r.name role
<db-model property="model"> FROM account.user u
<custom> JOIN account.role r ON r.id = u.role
SELECT Id_Cliente, Cliente, Telefono, movil LEFT JOIN vn.client c ON c.id = u.id
FROM vn2008.Clientes WHERE Id_Cliente = #user WHERE u.id = #user
</custom>
<sql-batch property="batch">
<custom>
<item name="user" param="user"/>
</custom>
</sql-batch>
</db-model> </db-model>
</db-form> </db-form>
</vn-group> </vn-group>
@ -20,55 +14,37 @@
<h1><t>AccessLog</t></h1> <h1><t>AccessLog</t></h1>
</div> </div>
<div id="form" class="access-log"> <div id="form" class="access-log">
<div class="box"> <div class="box vn-w-xs vn-pa-lg">
<div class="form"> <div class="form">
<p> <h4>{{user.nickname}}</h4>
<htk-text form="user-form" column="Id_Cliente"/> <p>#{{user.id}} - {{user.user}}</p>
</p> <p>{{user.role}}</p>
<p> <p>{{user.email}}</p>
<htk-text form="user-form" column="Cliente"/> <p>{{user.phone}}</p>
</p>
<p>
<htk-text form="user-form" column="Telefono"/>
</p>
<p>
<htk-text form="user-form" column="movil"/>
</p>
</div>
</div>
<div class="list box">
<div>
<htk-repeater form-id="iter">
<db-model property="model">
<custom>
SELECT u.stamp, a.platform, a.browser, a.version, a.javascript, a.cookies
FROM visitUser u
JOIN visitAccess c ON c.id = u.accessFk
JOIN visitAgent a ON a.id = c.agentFk
WHERE u.userFk = #user
ORDER BY u.stamp DESC
LIMIT 8
</custom>
<sql-batch property="batch">
<custom>
<item name="user" param="user"/>
</custom>
</sql-batch>
</db-model>
<custom>
<div class="item">
<p>
<htk-text form="iter" column="stamp" format="_%a, %e %b %Y at %T"/>
</p>
<p>
<htk-text form="iter" column="platform"/> -
<htk-text form="iter" column="browser"/>
<htk-text form="iter" column="version"/>
</p>
</div>
</custom>
</htk-repeater>
</div> </div>
</div> </div>
<htk-repeater form-id="iter" class="box vn-w-xs htk-list vn-mt-md">
<db-model property="model" lot="hash">
SELECT u.stamp, a.platform, a.browser, a.version, a.javascript, a.cookies
FROM visitUser u
JOIN visitAccess c ON c.id = u.accessFk
JOIN visitAgent a ON a.id = c.agentFk
WHERE u.userFk = #user
ORDER BY u.stamp DESC
LIMIT 8
</db-model>
<custom>
<div class="item">
<div class="content">
<p>
{{Vn.Value.format(iter.stamp, _('%a, %e %b %Y at %T'))}}
</p>
<p>
{{iter.platform}} - {{iter.browser}} {{iter.version}}
</p>
</div>
</div>
</custom>
</htk-repeater>
</div> </div>
</vn> </vn>

View File

@ -4,38 +4,28 @@ Hedera.Connections = new Class({
,_timeoutId: null ,_timeoutId: null
,onModelStatusChange: function(model) { ,onModelStatusChange: function() {
if (!model.ready) if (!this.$.sessions.ready)
return; return;
if (this._timeoutId) if (this._timeoutId)
clearTimeout(this._timeoutId); clearTimeout(this._timeoutId);
this._timeoutId = setTimeout(this.onRefreshClick.bind(this), 60000); this._timeoutId = setTimeout(
() => this.$.sessions.refresh(), 60000);
} }
,deactivate: function() { ,deactivate: function() {
clearTimeout(this._timeoutId); clearTimeout(this._timeoutId);
} }
,onRefreshClick: function() {
this.$('sessions').refresh();
}
,onAccessLogClick: function(button, form) { ,onChangeUserClick: function(userName) {
this.hash.set({ this.gui.supplantUser(userName,
form: 'admin/access-log'
,user: form.get('userId')
});
}
,onChangeUserClick: function(button, form) {
this.gui.supplantUser(form.get('user'),
this._onUserSupplant.bind(this)); this._onUserSupplant.bind(this));
} }
,_onUserSupplant: function() { ,_onUserSupplant: function() {
this.hash.set({form: 'ecomerce/orders'}); this.hash.setAll({form: 'ecomerce/orders'});
} }
,sessionsFunc: function() { ,sessionsFunc: function() {

View File

@ -1,44 +1,6 @@
.connections
{ .action-bar .connections-sum {
padding: 1em;
}
.connections .box
{
max-width: 25em;
margin: 0 auto;
}
.action-bar .connections-sum
{
padding: .4em; padding: .4em;
margin-top: .9em;
margin-right: .5em;
background-color: #1e88e5; background-color: #1e88e5;
border-radius: 0.1em; border-radius: .1em;
box-shadow: 0 0 0.4em #666;
} }
/* List */
.connections .item
{
display: block;
padding: 1em;
border-bottom: 1px solid #DDD;
}
.connections .item > button
{
float: right;
margin: 0;
}
.connections .item > p
{
margin: .1em 0;
}
.connections .item > p.important
{
font-size: 1.2em;
text-overflow: ellipsis;
white-space: nowrap;
overflow: hidden;
}

View File

@ -6,7 +6,7 @@
<htk-bar-button <htk-bar-button
icon="refresh" icon="refresh"
tip="_Refresh" tip="_Refresh"
on-click="onRefreshClick"/> on-click="sessions.refresh()"/>
<div class="connections-sum"> <div class="connections-sum">
<htk-text> <htk-text>
<db-calc-sum <db-calc-sum
@ -18,50 +18,46 @@
</div> </div>
</div> </div>
<div id="form" class="connections"> <div id="form" class="connections">
<div class="box"> <htk-repeater form-id="iter" class="box htk-list vn-w-xs">
<htk-repeater form-id="iter"> <db-model
<db-model property="model" id="sessions" on-status-changed="onModelStatusChange"> property="model"
<custom> id="sessions"
SELECT vu.userFk userId, vu.stamp, u.nickname, s.lastUpdate, on-status-changed="this.onModelStatusChange()">
a.platform, a.browser, a.version, u.name user SELECT vu.userFk userId, vu.stamp, u.nickname, s.lastUpdate,
FROM userSession s a.platform, a.browser, a.version, u.name user
JOIN visitUser vu ON vu.id = s.userVisitFk FROM userSession s
JOIN visitAccess ac ON ac.id = vu.accessFk JOIN visitUser vu ON vu.id = s.userVisitFk
JOIN visitAgent a ON a.id = ac.agentFk JOIN visitAccess ac ON ac.id = vu.accessFk
JOIN visit v ON v.id = a.visitFk JOIN visitAgent a ON a.id = ac.agentFk
JOIN account.user u ON u.id = vu.userFk JOIN visit v ON v.id = a.visitFk
ORDER BY lastUpdate DESC JOIN account.user u ON u.id = vu.userFk
</custom> ORDER BY lastUpdate DESC
</db-model> </db-model>
<custom> <custom>
<div class="item"> <a class="item"
<htk-button href="{{`#!form=admin/access-log&amp;user=${iter.userId}`}}"
form="iter" title="_Access log">
column="id" <div class="content">
tip="_Supplant user"
icon="incognito"
on-click="onChangeUserClick"/>
<htk-button
form="iter"
column="id"
tip="_Access log"
icon="gnome"
on-click="onAccessLogClick"/>
<p class="important"> <p class="important">
<htk-text form="iter" column="nickname"/> {{iter.nickname}}
</p> </p>
<p> <p>
<htk-text form="iter" column="stamp" format="%a, %T"/> - {{Vn.Value.format(iter.stamp, '%a, %T')}} -
<htk-text form="iter" column="lastUpdate" format="%T"/> {{Vn.Value.format(iter.lastUpdate, '%T')}}
</p> </p>
<p> <p>
<htk-text form="iter" column="platform"/> - {{iter.platform}} - {{iter.browser}} {{iter.version}}
<htk-text form="iter" column="browser"/>
<htk-text form="iter" column="version"/>
</p> </p>
</div> </div>
</custom> <div class="actions"
</htk-repeater> on-click="$event.preventDefault()">
</div> <htk-button
tip="_Supplant user"
icon="supervisor_account"
on-click="this.onChangeUserClick(iter.user)"/>
</div>
</a>
</custom>
</htk-repeater>
</div> </div>
</vn> </vn>

View File

@ -3,6 +3,6 @@ Hedera.Items = new Class({
Extends: Hedera.Form, Extends: Hedera.Form,
activate: function() { activate: function() {
this.$('items').setInfo('i', 'item', 'vn', ['id']); this.$.items.setInfo('i', 'item', 'vn', ['id']);
} }
}); });

View File

@ -1,41 +1,6 @@
.items
{
padding: 1em;
}
.items .box
{
max-width: 25em;
margin: 0 auto;
}
/* Row */ .items .item .photo {
border-radius: 10px;
.items .row height: 80px;
{ width: 80px;
padding: 1em;
border-bottom: 1px solid #DDD;
} }
.items .row > .photo
{
margin-right: 1em;
float: left;
border-radius: 3%;
height: 5.5em;
width: 5.5em;
}
.items .row > p
{
margin: .1em 0;
margin-left: 5em;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
/* Topbar */
.action-bar .htk-search-entry
{
margin: .8em .6em;
}

View File

@ -1,38 +1,32 @@
<vn> <vn>
<vn-group>
<vn-param id="filter"/>
<vn-hash-param key="filter" param="filter"/>
</vn-group>
<div id="title"> <div id="title">
<h1><t>Items</t></h1> <h1><t>Items</t></h1>
</div> </div>
<div id="actions"> <div id="actions">
<htk-search-entry param="filter"/> <htk-search-entry form="hash" column="search"/>
</div> </div>
<div id="form" class="items"> <div id="form" class="items">
<div class="rows box"> <htk-repeater
<htk-repeater form-id="iter" empty-message="_Enter a search term"> class="htk-list rows box vn-w-xs"
<db-model property="model" id="items"> form-id="iter"
SELECT i.id, i.longName, i.size, i.category, empty-message="_Enter a search term">
i.value5, i.value6, i.value7, <db-model property="model" id="items" lot="hash">
i.image, im.updated SELECT i.id, i.longName, i.size, i.category,
FROM vn.item i i.value5, i.value6, i.value7,
LEFT JOIN image im i.image, im.updated
ON im.collectionFk = 'catalog' FROM vn.item i
AND im.name = i.image LEFT JOIN image im
WHERE i.longName LIKE CONCAT('%', #filter, '%') ON im.collectionFk = 'catalog'
OR i.id = #filter AND im.name = i.image
ORDER BY i.longName LIMIT 50 WHERE i.longName LIKE CONCAT('%', #search, '%')
<sql-batch property="batch"> OR i.id = #search
<custom> ORDER BY i.longName LIMIT 50
<item name="filter" param="filter"/> </db-model>
</custom> <custom>
</sql-batch> <div class="item">
</db-model> <div class="side vn-mr-md">
<custom>
<div class="row">
<htk-image <htk-image
form="iter" form="$iter"
column="image" column="image"
stamp-column="updated" stamp-column="updated"
class="photo" class="photo"
@ -41,24 +35,23 @@
full-dir="1600x900" full-dir="1600x900"
editable="true" editable="true"
conn="conn"/> conn="conn"/>
<p class="concept"> </div>
<htk-text form="iter" column="longName"/> <div class="content">
<p class="important">
{{iter.longName}}
</p> </p>
<p class="tags"> <p class="tags">
<htk-text form="iter" column="value5"/> {{iter.value5}} {{iter.value6}} {{iter.value7}}
<htk-text form="iter" column="value6"/>
<htk-text form="iter" column="value7"/>
</p> </p>
<p> <p>
#<htk-text form="iter" column="id"/> {{iter.id}}
</p> </p>
<p> <p>
<htk-text form="iter" column="image"/> {{iter.image}}
</p> </p>
<div class="clear"/>
</div> </div>
</custom> </div>
</htk-repeater> </custom>
</div> </htk-repeater>
</div> </div>
</vn> </vn>

View File

@ -1,11 +1,5 @@
Hedera.Links = new Class Hedera.Links = new Class({
({
Extends: Hedera.Form Extends: Hedera.Form
,repeaterFunc: function (res, form)
{
res.$('link').href = form.get ('link');
}
}); });

View File

@ -1,38 +1,50 @@
.cpanel .cpanel .items > div {
{ max-width: 900px;
padding: 1em; display: flex;
flex-wrap: wrap;
justify-content: center;
gap: 16px;
margin: 0 auto;
} }
.cpanel .box .cpanel .item {
{ display: flex;
max-width: 30em; flex-direction: column;
align-items: center;
margin: 0;
width: 140px;
padding: 15px;
text-align: center;
transition: background-color 250ms ease-out;
} }
.cpanel .item:hover {
/* Items */
.cpanel .item
{
display: block;
padding: 1em;
border-bottom: 1px solid #DDD;
}
.cpanel .item:hover
{
background-color: rgba(1, 1, 1, 0.05); background-color: rgba(1, 1, 1, 0.05);
} }
.cpanel .item > .htk-image .cpanel .item > .htk-image {
{ display: flex;
justify-content: center;
align-items: center;
margin: 0; margin: 0;
margin-right: 1em;
float: left; float: left;
max-height: 2.8em; height: 80px;
max-width: 2.8em;
} }
.cpanel .item > p .cpanel .item > .htk-image > img {
{ max-height: 60px;
max-width: 60px;
padding: 0;
}
.cpanel .item > h6 {
flex: none;
margin: .1em 0; margin: .1em 0;
font-size: .9rem;
text-overflow: ellipsis;
white-space: nowrap;
overflow: hidden;
} }
.cpanel .item > p.important .cpanel .item > .text-secondary {
{ flex: none;
font-size: 1.2em; margin: 0;
font-size: .8rem;
height: 40px;
overflow: hidden;
} }

View File

@ -3,30 +3,29 @@
<h1><t>ControlPanel</t></h1> <h1><t>ControlPanel</t></h1>
</div> </div>
<div id="form" class="cpanel"> <div id="form" class="cpanel">
<div class="box"> <htk-repeater form-id="iter" class="items">
<htk-repeater form-id="iter" renderer="repeaterFunc"> <db-model property="model">
<db-model property="model">
<custom>
SELECT image, name, description, link FROM link
ORDER BY name
</custom>
</db-model>
<custom> <custom>
<a id="link" class="item" target="_blank"> SELECT image, name, description, link FROM link
<htk-image ORDER BY name
form="iter"
column="image"
directory="link"
subdir="full"/>
<p class="important">
<htk-text form="iter" column="name"/>
</p>
<p>
<htk-text form="iter" column="description"/>
</p>
</a>
</custom> </custom>
</htk-repeater> </db-model>
</div> <custom>
<a class="item box"
href="{{iter.link}}"
target="_blank">
<htk-image
value="{{iter.image}}"
directory="link"
subdir="full"/>
<h6>
{{iter.name}}
</h6>
<p class="text-secondary">
{{iter.description}}
</p>
</a>
</custom>
</htk-repeater>
</div> </div>
</vn> </vn>

View File

@ -6,8 +6,7 @@ var Status = {
,UPLOADED : 3 ,UPLOADED : 3
}; };
Hedera.Photos = new Class Hedera.Photos = new Class({
({
Extends: Hedera.Form Extends: Hedera.Form
,filesData: [] ,filesData: []
,uploadCount: 0 ,uploadCount: 0
@ -16,7 +15,7 @@ Hedera.Photos = new Class
,isUploading: false ,isUploading: false
,activate: function() { ,activate: function() {
this.$('schema').value = 'catalog'; this.$.schema.value = 'catalog';
} }
,addFiles: function(files) { ,addFiles: function(files) {
@ -54,23 +53,24 @@ Hedera.Photos = new Class
statusNode.className = 'status'; statusNode.className = 'status';
li.appendChild(statusNode); li.appendChild(statusNode);
var button = new Htk.Button({
tip: 'Remove',
icon: 'delete'
});
button.on('click', this.onFileRemove, this);
li.appendChild(button.node);
var fileData = { var fileData = {
li: li, li: li,
file: file, file: file,
name: name, name: name,
statusNode: statusNode statusNode: statusNode
}; };
this.filesData.push(fileData);
button.value = fileData;
this.$('file-list').appendChild(li); var button = new Htk.Button({
tip: 'Remove',
icon: 'delete'
});
button.node.addEventListener('click',
() => this.onFileRemove(fileData));
li.appendChild(button.node);
this.filesData.push(fileData);
this.$.fileList.appendChild(li);
this.setImageStatus(fileData, Status.NONE, 'add', _('Pending upload')); this.setImageStatus(fileData, Status.NONE, 'add', _('Pending upload'));
} }
@ -83,7 +83,7 @@ Hedera.Photos = new Class
if (fileData.status === Status.NONE) { if (fileData.status === Status.NONE) {
this.setImageStatus( this.setImageStatus(
fileData, Status.WAITING, 'cloud-upload', _('Waiting for upload')); fileData, Status.WAITING, 'cloud_upload', _('Waiting for upload'));
fileData.name.disabled = true; fileData.name.disabled = true;
this.uploadQueue.push(fileData); this.uploadQueue.push(fileData);
count++; count++;
@ -107,10 +107,10 @@ Hedera.Photos = new Class
fileData, Status.UPLOADING, 'upload', _('Uploading file')); fileData, Status.UPLOADING, 'upload', _('Uploading file'));
var formData = new FormData(); var formData = new FormData();
formData.append('updateMatching', this.$('update-matching').value); formData.append('updateMatching', this.$.updateMatching.value);
formData.append('image', fileData.file); formData.append('image', fileData.file);
formData.append('name', fileData.name.value); formData.append('name', fileData.name.value);
formData.append('schema', this.$('schema').value); formData.append('schema', this.$.schema.value);
formData.append('srv', 'json:image/upload'); formData.append('srv', 'json:image/upload');
this.conn.sendFormData(formData, this.conn.sendFormData(formData,
this.onFileUpload.bind(this, fileData)); this.onFileUpload.bind(this, fileData));
@ -121,7 +121,7 @@ Hedera.Photos = new Class
if (data) { if (data) {
this.setImageStatus( this.setImageStatus(
fileData, Status.UPLOADED, 'ok', _('Image uploaded')); fileData, Status.UPLOADED, 'cloud_done', _('Image uploaded'));
} else { } else {
this.setImageStatus( this.setImageStatus(
fileData, Status.NONE, 'error', error.message); fileData, Status.NONE, 'error', error.message);
@ -146,14 +146,13 @@ Hedera.Photos = new Class
var statusNode = fileData.statusNode; var statusNode = fileData.statusNode;
Vn.Node.removeChilds(statusNode); Vn.Node.removeChilds(statusNode);
var iconNode = new Htk.Icon({icon: icon}); var iconNode = new Htk.Icon({name: icon});
statusNode.appendChild(iconNode.node); statusNode.appendChild(iconNode.node);
statusNode.title = title ? title : ''; statusNode.title = title ? title : '';
} }
,onFileRemove: function(button) { ,onFileRemove: function(fileData) {
var fileData = button.value; this.$.fileList.removeChild(fileData.li);
this.$('file-list').removeChild(fileData.li);
for (var i = 0; i < this.filesData.length; i++) for (var i = 0; i < this.filesData.length; i++)
if (this.filesData[i] === fileData) { if (this.filesData[i] === fileData) {
@ -164,23 +163,23 @@ Hedera.Photos = new Class
,onClearClick: function() { ,onClearClick: function() {
this.filesData = []; this.filesData = [];
Vn.Node.removeChilds(this.$('file-list')); Vn.Node.removeChilds(this.$.fileList);
} }
,onDropzoneClick: function() { ,onDropzoneClick: function() {
this.$('file').click(); this.$.file.click();
} }
,onFileChange: function() { ,onFileChange: function() {
this.addFiles(this.$('file').files); this.addFiles(this.$.file.files);
} }
,onDragEnter: function() { ,onDragEnter: function() {
this.$('dropzone').classList.add('dragover'); this.$.dropzone.classList.add('dragover');
} }
,onDragLeave: function() { ,onDragLeave: function() {
this.$('dropzone').classList.remove('dragover'); this.$.dropzone.classList.remove('dragover');
} }
,onDragOver: function(event) { ,onDragOver: function(event) {
@ -188,7 +187,7 @@ Hedera.Photos = new Class
} }
,onDragEnd: function(event) { ,onDragEnd: function(event) {
this.$('dropzone').classList.remove('dragover'); this.$.dropzone.classList.remove('dragover');
event.dataTransfer.clearData(); event.dataTransfer.clearData();
} }

View File

@ -1,12 +1,4 @@
.photos {
padding: 1em;
}
.photos .box {
max-width: 25em;
padding: 2em;
}
/* Dropzone */ /* Dropzone */
.photos .dropzone { .photos .dropzone {
@ -56,11 +48,11 @@
} }
.photos .file-list .status { .photos .file-list .status {
cursor: pointer; cursor: pointer;
width: 1em; width: 1.2em;
padding-left: .5em; padding-left: .5em;
padding-right: .5em; padding-right: .5em;
} }
.photos .file-list .status > img { .photos .file-list .status > .htk-icon {
display: block; display: block;
} }
.photos .file-list .htk-button { .photos .file-list .htk-button {

View File

@ -3,7 +3,7 @@
<h1><t>Images</t></h1> <h1><t>Images</t></h1>
</div> </div>
<div id="form" class="photos"> <div id="form" class="photos">
<div class="box"> <div class="box form vn-w-sm vn-pa-lg">
<div class="form-group"> <div class="form-group">
<label><t>Collection</t></label> <label><t>Collection</t></label>
<htk-combo id="schema"> <htk-combo id="schema">

View File

@ -1,102 +1,91 @@
Hedera.Queries = new Class Hedera.Queries = new Class({
({
Extends: Hedera.Form Extends: Hedera.Form
,activate: function () ,activate: function() {
{ this.$.resultIndex.value = 0;
this.$('result-index').value = 0;
} }
,clean: function () ,clean: function() {
{ if (this._grid) {
if (this._grid) this.$.gridHolder.removeChild(this._grid.node);
{ this._grid.unref();
this.$('grid-holder').removeChild (this._grid.node);
this._grid.unref ();
this._grid = null; this._grid = null;
} }
} }
,_onExecuteClick: function () ,onExecuteClick: function() {
{ this.clean();
this.clean ();
var model = new Db.Model ({ var model = new Db.Model({
conn: this.conn, conn: this.conn,
query: this.$('sql').value, query: this.$.sql.value,
resultIndex: this.$('result-index').value, resultIndex: this.$.resultIndex.value,
updatable: this.$('updatable').value updatable: this.$.updatable.value
}); });
model.on ('status-changed', this._onModelChange, this); model.on('status-changed', this.onModelChange, this);
} }
,_onCleanClick: function () ,onCleanClick: function() {
{ this.clean();
this.clean ();
} }
,_onModelChange: function (model, status) ,onModelChange: function(model, status) {
{ if (status !== Db.Model.Status.LOADING) {
if (status !== Db.Model.Status.LOADING) model.disconnect('status-changed', this.onModelChange, this);
{ model.unref();
model.disconnect ('status-changed', this._onModelChange, this);
model.unref ();
} }
if (status !== Db.Model.Status.READY) if (status !== Db.Model.Status.READY)
return; return;
Htk.Toast.showMessage (_('Query executed!')); Htk.Toast.showMessage(_('Query executed!'));
var gridHolder = this.$('grid-holder'); var gridHolder = this.$.gridHolder;
if (gridHolder.firstChild) if (gridHolder.firstChild)
gridHolder.removeChilds (gridHolder.firstChild); gridHolder.removeChilds(gridHolder.firstChild);
var grid = new Htk.Grid (); var grid = new Htk.Grid();
var columns = model.columns; var columns = model.columns;
for (var i = 0; i < columns.length; i++) for (var i = 0; i < columns.length; i++) {
{
var c = columns[i]; var c = columns[i];
switch (c.type) switch (c.type) {
{
case Db.Conn.Type.BOOLEAN: case Db.Conn.Type.BOOLEAN:
var column = new Htk.ColumnCheck (); var column = new Htk.ColumnCheck();
break; break;
case Db.Conn.Type.INTEGER: case Db.Conn.Type.INTEGER:
var column = new Htk.ColumnSpin (); var column = new Htk.ColumnSpin();
break; break;
case Db.Conn.Type.DOUBLE: case Db.Conn.Type.DOUBLE:
var column = new Htk.ColumnSpin ({digits: 2}); var column = new Htk.ColumnSpin({digits: 2});
break; break;
case Db.Conn.Type.DATE: case Db.Conn.Type.DATE:
var column = new Htk.ColumnDate ({format: '%a, %e %b %Y'}); var column = new Htk.ColumnDate({format: '%a, %e %b %Y'});
break; break;
case Db.Conn.Type.DATE_TIME: case Db.Conn.Type.DATE_TIME:
var column = new Htk.ColumnDate ({format: '%a, %e %b %Y, %T'}); var column = new Htk.ColumnDate({format: '%a, %e %b %Y, %T'});
break; break;
case Db.Conn.Type.STRING: case Db.Conn.Type.STRING:
default: default:
var column = new Htk.ColumnText (); var column = new Htk.ColumnText();
} }
column.setProperties ({ column.setProperties({
title: c.name, title: c.name,
editable: this.$('updatable').value, editable: this.$.updatable.value,
columnIndex: i columnIndex: i
}); });
grid.appendColumn (column); grid.appendColumn(column);
} }
grid.model = model; grid.model = model;
gridHolder.appendChild (grid.node); gridHolder.appendChild(grid.node);
this._grid = grid; this._grid = grid;
} }
}); });

View File

@ -1,25 +1,10 @@
.queries
{ .queries textarea {
padding: 1em;
}
.queries .box
{
max-width: 40em;
margin: 0 auto;
}
.queries .form
{
box-sizing: border-box;
padding: 2em;
}
.queries textarea
{
display: block; display: block;
width: 100%; width: 100%;
height: 8em; height: 8em;
} }
.queries .result .queries .result {
{
margin-top: 1em; margin-top: 1em;
overflow: auto; overflow: auto;
} }

View File

@ -6,14 +6,14 @@
<htk-bar-button <htk-bar-button
icon="ok" icon="ok"
tip="_Execute" tip="_Execute"
on-click="_onExecuteClick"/> on-click="this.onExecuteClick()"/>
<htk-bar-button <htk-bar-button
icon="delete" icon="delete"
tip="_Clean" tip="_Clean"
on-click="_onCleanClick"/> on-click="this.onCleanClick()"/>
</div> </div>
<div id="form" class="queries"> <div id="form" class="queries">
<div class="box form"> <div class="box form vn-w-sm vn-pa-lg">
<div class="form-group"> <div class="form-group">
<label><t>SQL query</t></label> <label><t>SQL query</t></label>
<textarea <textarea

View File

@ -1,45 +1,11 @@
.users
{ .users-box.item > .actions {
padding: 1em; display: flex;
} }
.users .box .users-box .disabled {
{
max-width: 30em;
margin: 0 auto;
}
.users-box
{
padding: 1em;
border-bottom: 1px solid #DDD;
}
.users-box > button
{
float: right;
margin: 0;
}
.users-box > p
{
margin: .2em 0;
}
.users-box > p.important
{
font-size: 1.2em;
}
.users-box > .disabled
{
float: right;
color: white; color: white;
background-color: #F66; background-color: #F66;
border-radius: .2em; border-radius: .2em;
padding: .2em; padding: .3em;
margin: .3em;
font-size: .8em; font-size: .8em;
} }
/* Topbar */
.action-bar .htk-search-entry
{
margin: .8em .6em;
}

View File

@ -1,62 +1,48 @@
<vn> <vn>
<vn-group>
<vn-param id="user-name"/>
<vn-hash-param key="user" param="user-name"/>
</vn-group>
<div id="title"> <div id="title">
<h1><t>User management</t></h1> <h1><t>User management</t></h1>
</div> </div>
<div id="actions"> <div id="actions">
<htk-search-entry <htk-search-entry form="hash" column="user"/>
param="user-name"/>
</div> </div>
<div id="form" class="users"> <div id="form" class="users">
<div class="box"> <htk-repeater
<htk-repeater form-id="iter" renderer="rendererFunc"> form-id="iter"
<db-model property="model"> renderer="rendererFunc"
<custom> class="htk-list box vn-w-xs">
SELECT u.id, u.name, u.nickname, u.active <db-model property="model" lot="hash">
FROM account.user u SELECT u.id, u.name, u.nickname, u.active
WHERE u.name LIKE CONCAT('%', #user, '%') FROM account.user u
OR u.nickname LIKE CONCAT('%', #user, '%') WHERE u.name LIKE CONCAT('%', #user, '%')
OR u.id = #user OR u.nickname LIKE CONCAT('%', #user, '%')
ORDER BY u.name LIMIT 200 OR u.id = #user
</custom> ORDER BY u.name LIMIT 200
<sql-batch property="batch"> </db-model>
<custom> <custom>
<item name="user" param="user-name"/> <a class="users-box item"
</custom> href="{{`#!form=admin/access-log&amp;user=${iter.id}`}}"
</sql-batch> title="_Access log">
</db-model> <div class="content">
<custom> <p class="important">
<div class="users-box"> {{iter.nickname}}
<htk-button </p>
form="iter" <p>
column="id" #{{iter.id}} - {{iter.name}}
tip="_Access log" </p>
icon="gnome" </div>
on-click="onAccessLogClick"/> <div class="actions"
<htk-button on-click="$event.preventDefault()">
id="impersonate"
form="iter"
column="id"
tip="_Impersonate user"
icon="incognito"
on-click="onChangeUserClick"/>
<span id="disabled" class="disabled"> <span id="disabled" class="disabled">
<t>Disabled</t> <t>Disabled</t>
</span> </span>
<p class="important"> <htk-button
<htk-text form="iter" column="nickname"/> id="impersonate"
</p> icon="supervisor_account"
<p> tip="_Impersonate user"
#<htk-text form="iter" column="id"/> - on-click="this.onChangeUserClick(iter.name)"/>
<htk-text form="iter" column="name"/>
</p>
<div class="clear"/>
</div> </div>
</custom> </a>
</htk-repeater> </custom>
</div> </htk-repeater>
</div> </div>
</vn> </vn>

View File

@ -2,28 +2,21 @@
Hedera.Users = new Class({ Hedera.Users = new Class({
Extends: Hedera.Form Extends: Hedera.Form
,onAccessLogClick: function(button, form) {
this.hash.set({
'form': 'admin/access-log'
,'user': form.get('id')
});
}
,rendererFunc: function(scope, form) { ,rendererFunc: function(scope, form) {
var isEnabled = form.get('active') var isEnabled = form.$.active
scope.$('disabled').style.display = isEnabled ? scope.$.disabled.style.display = isEnabled ?
'none' : 'block'; 'none' : 'block';
scope.$('impersonate').node.style.display = isEnabled ? scope.$.impersonate.node.style.display = isEnabled ?
'block' : 'none'; 'block' : 'none';
} }
,onChangeUserClick: function(button, form) { ,onChangeUserClick: function(userName) {
this.gui.supplantUser(form.get('name'), this.gui.supplantUser(userName,
this.onUserSupplant.bind(this)); this.onUserSupplant.bind(this));
} }
,onUserSupplant: function() { ,onUserSupplant: function() {
this.hash.set({form: 'ecomerce/orders'}); this.hash.setAll({form: 'ecomerce/orders'});
} }
}); });

View File

@ -1,46 +1,12 @@
.visits
{ .visits .box {
padding: 1em; margin-bottom: 16px;
} }
.visits .box .visits .box:last-child {
{ margin-bottom: 0;
max-width: 25em;
margin: 0 auto;
} }
.visits .form .visits .summary p {
{
padding: 1.5em;
max-width: 20em;
}
.visits .summary
{
margin-top: 1em;
}
.visits .summary p
{
padding: 1.5em;
font-size: 1.4em; font-size: 1.4em;
margin: 0;
text-align: right; text-align: right;
} }
/* List */
.visits .list
{
margin-top: 1em;
}
.visits .item
{
display: block;
padding: 1em;
border-bottom: 1px solid #DDD;
}
.visits .item > p
{
margin: .1em 0;
}
.visits .item > p.important
{
font-size: 1.2em;
}

View File

@ -1,4 +1,8 @@
<vn> <vn>
<vn-lot-query id="params">
<vn-spec name="from" type="Date"/>
<vn-spec name="to" type="Date"/>
</vn-lot-query>
<div id="title"> <div id="title">
<h1><t>Visits</t></h1> <h1><t>Visits</t></h1>
</div> </div>
@ -6,87 +10,78 @@
<htk-bar-button <htk-bar-button
icon="refresh" icon="refresh"
tip="_Refresh" tip="_Refresh"
on-click="onRefreshClick"/> on-click="visits.refresh()"/>
<htk-bar-button <htk-bar-button
icon="user-info" icon="visibility"
tip="_Connections" tip="_Connections"
on-click="onSessionsClick"/> on-click="this.hash.setAll({form: 'admin/connections'})"/>
</div> </div>
<div id="form" class="visits"> <div id="form" class="visits">
<div class="box"> <div class="vn-w-xs">
<div class="form"> <div class="form vn-pa-lg box">
<div class="form-group"> <div class="form-group">
<label><t>From</t></label> <label><t>From</t></label>
<htk-date-chooser> <htk-date-chooser
<vn-param property="param" id="from"/> form="params"
</htk-date-chooser> column="from"/>
</div> </div>
<div class="form-group"> <div class="form-group">
<label><t>To</t></label> <label><t>To</t></label>
<htk-date-chooser> <htk-date-chooser
<vn-param property="param" id="to"/> form="params"
</htk-date-chooser> column="to"/>
</div> </div>
</div> </div>
</div> <div class="summary vn-pa-lg box">
<div class="summary box"> <p>
<p> <htk-text>
<htk-text> <db-calc-sum
<db-calc-sum property="param"
property="param" model="visits"
model="visits" column-name="visits"/>
column-name="visits"/> </htk-text>
</htk-text> <t>visits</t>,
<t>visits</t>, <htk-text>
<htk-text> <db-calc-sum
<db-calc-sum property="param"
property="param" model="visits"
model="visits" column-name="newVisits"/>
column-name="newVisits"/> </htk-text>
</htk-text> <t>news</t>
<t>news</t> </p>
</p> </div>
</div> <htk-repeater
<div class="list box"> class="box htk-list"
<htk-repeater form-id="iter" empty-message="_Select date interval"> form-id="iter"
<db-model property="model" id="visits"> empty-message="_Select date interval">
<custom> <db-model property="model" id="visits" lot="params">
SELECT browser, SELECT browser,
MIN(CAST(version AS DECIMAL(4,1))) minVersion, MIN(CAST(version AS DECIMAL(4,1))) minVersion,
MAX(CAST(version AS DECIMAL(4,1))) maxVersion, MAX(CAST(version AS DECIMAL(4,1))) maxVersion,
MAX(c.stamp) lastVisit, MAX(c.stamp) lastVisit,
COUNT(DISTINCT c.id) visits, COUNT(DISTINCT c.id) visits,
SUM(a.firstAccessFk = c.id AND v.firstAgentFk = a.id) newVisits SUM(a.firstAccessFk = c.id AND v.firstAgentFk = a.id) newVisits
FROM visitUser e FROM visitUser e
JOIN visitAccess c ON c.id = e.accessFk JOIN visitAccess c ON c.id = e.accessFk
JOIN visitAgent a ON a.id = c.agentFk JOIN visitAgent a ON a.id = c.agentFk
JOIN visit v ON v.id = a.visitFk JOIN visit v ON v.id = a.visitFk
WHERE c.stamp BETWEEN TIMESTAMP(#from,'00:00:00') AND TIMESTAMP(#to,'23:59:59') WHERE c.stamp BETWEEN TIMESTAMP(#from,'00:00:00') AND TIMESTAMP(#to,'23:59:59')
GROUP BY browser ORDER BY visits DESC GROUP BY browser ORDER BY visits DESC
</custom>
<sql-batch property="batch">
<custom>
<item name="from" param="from"/>
<item name="to" param="to"/>
</custom>
</sql-batch>
</db-model> </db-model>
<custom> <custom>
<div class="item"> <div class="item">
<p class="important"> <div class="content">
<htk-text form="iter" column="browser"/> <p class="important">
<htk-text form="iter" column="minVersion"/> - {{iter.browser}} {{iter.minVersion}} - {{iter.maxVersion}}
<htk-text form="iter" column="maxVersion"/> </p>
</p> <p>
<p> {{iter.visits}} <t>visits</t>,
<htk-text form="iter" column="visits"/> {{iter.newVisits}} <t>news</t>
<t>visits</t>, </p>
<htk-text form="iter" column="newVisits"/> <p>
<t>news</t> {{Vn.Value.format(iter.lastVisit, _('%a, %e %b %Y at %T'))}}
</p> </p>
<p> </div>
<htk-text form="iter" column="lastVisit" format="_%a, %e %b %Y at %T"/>
</p>
</div> </div>
</custom> </custom>
</htk-repeater> </htk-repeater>

View File

@ -1,22 +1,13 @@
Hedera.Visits = new Class Hedera.Visits = new Class({
({
Extends: Hedera.Form Extends: Hedera.Form
,activate: function () ,activate: function() {
{ if (!this.hash.$.to)
this.$('from').value = new Date (); this.hash.assign({
this.$('to').value = new Date (); from: new Date(),
} to: new Date()
});
,onRefreshClick: function ()
{
this.$('visits').refresh ();
}
,onSessionsClick: function ()
{
this.hash.set ({'form': 'admin/connections'});
} }
}); });

View File

@ -1,13 +1,11 @@
Hedera.Packages = new Class Hedera.Packages = new Class({
({
Extends: Hedera.Form Extends: Hedera.Form
,onShowClick: function (column, agencyId) ,onShowClick: function(column, agencyId) {
{ this.hash.setAll({
this.hash.set ({ form: 'agencies/provinces',
'form': 'agencies/provinces', agency: agencyId
'agency': agencyId
}); });
} }
}); });

View File

@ -1,9 +0,0 @@
.packages
{
padding: 1em;
}
.packages .box
{
max-width: 40em;
margin: 0 auto;
}

View File

@ -3,7 +3,7 @@
<h1><t>ListByAgency</t></h1> <h1><t>ListByAgency</t></h1>
</div> </div>
<div id="form" class="packages"> <div id="form" class="packages">
<div class="box"> <div class="box vn-w-sm">
<htk-grid> <htk-grid>
<db-model property="model"> <db-model property="model">
<custom> <custom>
@ -12,7 +12,7 @@
</db-model> </db-model>
<htk-column-button <htk-column-button
column="agency_id" column="agency_id"
icon="show" icon="search"
tip="_ShowByProvince" tip="_ShowByProvince"
on-clicked="onShowClick"/> on-clicked="onShowClick"/>
<htk-column-text title="_Agency" column="Agencia"/> <htk-column-text title="_Agency" column="Agencia"/>

View File

@ -1,6 +1,5 @@
Hedera.Provinces = new Class Hedera.Provinces = new Class({
({
Extends: Hedera.Form Extends: Hedera.Form
}); });

View File

@ -1,9 +0,0 @@
.provinces
{
padding: 1em;
}
.provinces .box
{
max-width: 40em;
margin: 0 auto;
}

View File

@ -1,23 +1,12 @@
<vn> <vn>
<vn-group>
<vn-param id="agency"/>
<vn-hash-param key="agency" param="agency"/>
</vn-group>
<div id="title"> <div id="title">
<h1><t>ByProvince</t></h1> <h1><t>ByProvince</t></h1>
</div> </div>
<div id="form" class="provinces"> <div id="form" class="provinces vn-w-sm">
<div class="box"> <div class="box">
<htk-grid> <htk-grid>
<db-model property="model"> <db-model property="model" lot="hash">
<custom> CALL vn2008.desglose_volume(#agency)
CALL vn2008.desglose_volume (#agency)
</custom>
<sql-batch property="batch">
<custom>
<item name="agency" param="agency"/>
</custom>
</sql-batch>
</db-model> </db-model>
<htk-column-text title="_Province" column="Provincia"/> <htk-column-text title="_Province" column="Provincia"/>
<htk-column-spin title="_Expeditions" column="expediciones"/> <htk-column-spin title="_Expeditions" column="expediciones"/>

View File

@ -1,15 +1,5 @@
.about @media screen and (min-width: 1000px) /* and (max-width: 1399px) */ {
{
padding: 1em;
}
.about .cols
{
max-width: 85em;
margin: 0 auto;
}
@media screen and (min-width: 1000px) /* and (max-width: 1399px) */
{
.about .cols .about .cols
{ {
column-count: 2; column-count: 2;
@ -17,8 +7,7 @@
-webkit-column-count: 2; -webkit-column-count: 2;
} }
}/* }/*
@media screen and (min-width: 1400px) @media screen and (min-width: 1400px) {
{
.about .cols .about .cols
{ {
column-count: 3; column-count: 3;
@ -26,8 +15,7 @@
-webkit-column-count: 3; -webkit-column-count: 3;
} }
} }
@media screen and (min-width: 2000px) @media screen and (min-width: 2000px) {
{
.about .cols .about .cols
{ {
column-count: 4; column-count: 4;
@ -35,39 +23,33 @@
-webkit-column-count: 4; -webkit-column-count: 4;
} }
}*/ }*/
.about .box .about .box {
{ margin-bottom: 16px;
margin-bottom: 1em; padding: 32px;
padding: 2em;
} }
.about h1 .about h1 {
{
padding: 0; padding: 0;
margin: 0; margin: 0;
font-weight: normal; font-weight: normal;
font-size: 1.6em; font-size: 1.6em;
} }
.about h2 .about h2 {
{
text-align: center; text-align: center;
font-size: 1.2em; font-size: 1.2em;
font-weight: normal; font-weight: normal;
margin: 1em; margin: 1em;
} }
.about h3 .about h3 {
{
text-align: center; text-align: center;
font-size: 1.2em; font-size: 1.2em;
font-weight: normal; font-weight: normal;
padding: 1em; padding: 1em;
color: #00796B; color: #00796B;
} }
.about p .about p {
{
margin: 1em 0; margin: 1em 0;
} }
.about p.summary .about p.summary {
{
max-width: 26em; max-width: 26em;
text-align: center; text-align: center;
background-color: #FF8; background-color: #FF8;
@ -79,8 +61,7 @@
/* Images */ /* Images */
.about img .about img {
{
max-width: 90%; max-width: 90%;
text-align: center; text-align: center;
padding: 1em; padding: 1em;
@ -90,16 +71,13 @@
.about img[alt="producers"], .about img[alt="producers"],
.about img[alt="4_control"], .about img[alt="4_control"],
.about img[alt="dealer"], .about img[alt="dealer"],
.about img[alt="goods_transport"] .about img[alt="goods_transport"] {
{
float: right; float: right;
} }
.about img[alt="2_control"] .about img[alt="2_control"] {
{
float: left; float: left;
} }
.about img[alt="glass"] .about img[alt="glass"] {
{
display: inline; display: inline;
padding: 0; padding: 0;
padding-left: 0.9em; padding-left: 0.9em;

View File

@ -3,7 +3,7 @@
<h1><t>About</t></h1> <h1><t>About</t></h1>
</div> </div>
<div id="form" class="about"> <div id="form" class="about">
<div class="cols"> <div class="cols vn-w-lg">
<div class="box"> <div class="box">
<h1> <h1>
<t>QualityAndVariety</t> <t>QualityAndVariety</t>

View File

@ -1,46 +1,40 @@
Hedera.Contact = new Class Hedera.Contact = new Class({
({
Extends: Hedera.Form Extends: Hedera.Form
,activate: function () ,activate: function() {
{
var self = this; var self = this;
this.$('contact-form').onsubmit = function () this.$.contactForm.onsubmit = function() {
{ self._onSubmit (); return false; }; self._onSubmit(); return false;
this.refreshCaptcha ();
}
,refreshCaptcha: function ()
{
params = {
'srv': 'rest:core/captcha',
'stamp': new Date ().getTime ()
}; };
this.$('captcha-img').src = '?'+ Vn.Url.makeUri (params);
}
,_onSubmit: function ()
{
this.conn.sendForm (this.$('contact-form'),
this._onResponse.bind (this));
}
,_onResponse: function (json, error)
{
var form = this.$('contact-form');
if (json) this.refreshCaptcha();
{ }
form.reset ();
Htk.Toast.showMessage (_('DataSentSuccess')); ,refreshCaptcha: function() {
} params = {
else srv: 'rest:misc/captcha',
Htk.Toast.showError (_('ErrorSendingData')); stamp: new Date().getTime()
};
this.$.captchaImg.src = '?'+ Vn.Url.makeUri(params);
}
,_onSubmit: function() {
this.conn.sendForm(this.$.contactForm,
this._onResponse.bind(this));
}
,_onResponse: function(json) {
var form = this.$.contactForm;
if (json) {
form.reset();
Htk.Toast.showMessage(_('DataSentSuccess'));
} else
Htk.Toast.showError(_('ErrorSendingData'));
form['captcha'].value = ''; form['captcha'].value = '';
this.refreshCaptcha (); this.refreshCaptcha();
} }
}); });

View File

@ -1,55 +1,38 @@
.contact .contact .form {
{
padding: 1em;
}
.contact .box
{
max-width: 30em;
padding: 2em;
}
.contact .form
{
position: relative; position: relative;
text-align: left; text-align: left;
max-width: 25em; max-width: 25em;
margin: 0 auto; margin: 0 auto;
} }
.contact form .contact form {
{
margin: 0 auto; margin: 0 auto;
} }
.contact form p .contact form p {
{
margin: 1em auto; margin: 1em auto;
display: block; display: block;
margin-top: 2em; margin-top: 2em;
} }
.contact textarea .contact textarea {
{
height: 5em; height: 5em;
} }
.contact button .contact button {
{
display: block; display: block;
margin: 0 auto; margin: 0 auto;
margin-top: 1em; margin-top: 1em;
padding: 0.6em; padding: 0.6em;
} }
.contact .mandatory-message .contact .mandatory-message {
{
font-size: .9em; font-size: .9em;
} }
/* Captcha */ /* Captcha */
.captcha img .captcha img {
{
vertical-align: middle; vertical-align: middle;
margin-left: 1em; margin-left: 1em;
} }
.captcha input .captcha input {
{
max-width: 8em; max-width: 8em;
} }

View File

@ -3,54 +3,47 @@
<h1><t>IWantCustomer</t></h1> <h1><t>IWantCustomer</t></h1>
</div> </div>
<div id="form" class="contact"> <div id="form" class="contact">
<div class="box"> <div class="box form vn-w-xs vn-pa-lg">
<div class="form"> <p><t>FillFormData</t></p>
<p> <p><t>OrCallUs</t></p>
<t>FillFormData</t> <form id="contact-form">
<input type="hidden" name="srv" value="json:misc/contact"/>
<div class="form-group">
<label><t>Name</t></label>
<input type="text" name="name"/>
</div>
<div class="form-group">
<label><t>City</t></label>
<input type="text" name="city"/>
</div>
<div class="form-group">
<label><t>PC</t></label>
<input type="text" name="pc"/>
</div>
<div class="form-group">
<label><t>Phone</t></label>
<input type="text" name="phone"/>
</div>
<div class="form-group">
<label><t>EMail</t></label>
<input type="text" name="email"/>
</div>
<div class="form-group">
<label><t>Message</t></label>
<textarea name="message"/>
</div>
<div class="form-group captcha">
<label><t>Anti-Spam</t></label>
<input type="text" name="captcha"/>
<img alt="Captcha" id="captcha-img"/>
</div>
<p class="mandatory-message">
<t>AllFieldsMandatory</t>
</p> </p>
<p> <button>
<t>OrCallUs</t> <t>Send</t>
</p> </button>
<form </form>
id="contact-form">
<input type="hidden" name="srv" value="json:misc/contact"/>
<div class="form-group">
<label><t>Name</t></label>
<input type="text" name="name"/>
</div>
<div class="form-group">
<label><t>City</t></label>
<input type="text" name="city"/>
</div>
<div class="form-group">
<label><t>PC</t></label>
<input type="text" name="pc"/>
</div>
<div class="form-group">
<label><t>Phone</t></label>
<input type="text" name="phone"/>
</div>
<div class="form-group">
<label><t>EMail</t></label>
<input type="text" name="email"/>
</div>
<div class="form-group">
<label><t>Message</t></label>
<textarea name="message"/>
</div>
<div class="form-group captcha">
<label><t>Anti-Spam</t></label>
<input type="text" name="captcha"/>
<img alt="Captcha" id="captcha-img"/>
</div>
<p class="mandatory-message">
<t>AllFieldsMandatory</t>
</p>
<button class="thin">
<t>Send</t>
</button>
</form>
</div>
</div> </div>
</div> </div>
</vn> </vn>

View File

@ -1,9 +1,5 @@
Hedera.Home = new Class({ Hedera.Home = new Class({
Extends: Hedera.Form Extends: Hedera.Form
,onStartOrderClick: function() {
this.hash.set({form: 'ecomerce/catalog'});
}
}); });

View File

@ -1,70 +1,60 @@
.home {
padding: 0 !important;
}
/* News panel */ /* News panel */
.column .column {
{
margin: .5em; margin: .5em;
max-width: 120em; max-width: 120em;
} }
.action-bar button.start-order .action-bar button.start-order {
{ border: 1px solid white;
background-color: #EF5350;
margin: .7em;
padding: .5em;
box-shadow: 0 0 0.4em rgba(1, 1, 1, 0.4);
} }
.action-bar button.start-order:hover .action-bar button.start-order:hover {
{ background-color: white !important;
background-color: #F44336; color: black;
} }
/* New */ /* New */
.new .new {
{
text-align: left; text-align: left;
background-color: white;
color: #222;
border: none;
border-radius: 0.1em;
box-shadow: 0 0.2em 0.2em rgba(1, 1, 1, 0.2);
margin: .5em; margin: .5em;
} }
.new img .new img {
{
display: block; display: block;
margin: auto; margin: auto;
width: 100%; width: 100%;
} }
.new .top .new .top {
{
padding: 1.5em; padding: 1.5em;
padding-bottom: 1px; padding-bottom: 1px;
} }
.new h2 .new h2 {
{
font-size: 1.6em; font-size: 1.6em;
color: black; color: black;
font-weight: normal; font-weight: normal;
padding: 0; padding: 0;
} }
.new-info
{ .new-info {
font-size: 0.9em; font-size: 0.9em;
color: #444; color: #444;
text-align: right; text-align: right;
margin: 0.8em 0; margin: .8em 0;
} }
.new-text .new-text {
{
margin: 1.5em 0; margin: 1.5em 0;
font-family: 'Open Sans';
} }
.new-text a .new-text a {
{ color: #6a1;
color: blue; }
.new-text a:hover {
text-decoration: underline; text-decoration: underline;
} }
.new-text li .new-text li {
{
margin: 0.4em 0; margin: 0.4em 0;
} }

View File

@ -5,34 +5,33 @@
<div id="actions" class="catalog-actions"> <div id="actions" class="catalog-actions">
<htk-bar-button <htk-bar-button
class="start-order" class="start-order"
icon="new-order" icon="add_shopping_cart"
tip="_Start order" tip="_Start order"
on-click="onStartOrderClick"/> on-click="hash.setAll({form: 'ecomerce/catalog'})"/>
</div> </div>
<div id="form" class="home"> <div id="form" class="home">
<div class="column mansonry" id="news-column"> <div class="column mansonry" id="news-column">
<htk-repeater form-id="new"> <htk-repeater form-id="iter">
<db-model property="model"> <db-model property="model">
<custom> <custom>
SELECT title, text, image, id FROM news SELECT title, text, image, id
WHERE tag != 'course' FROM news
ORDER BY priority, created DESC ORDER BY priority, created DESC
</custom> </custom>
</db-model> </db-model>
<custom> <custom>
<div class="masonry-box"> <div class="masonry-box">
<div class="new"> <div class="new box">
<htk-image <htk-image
directory="news" directory="news"
subdir="full" subdir="full"
form="new" value="{{iter.image}}"
column="image"
editable="false" editable="false"
full-dir="full"/> full-dir="full"/>
<div class="top"> <div class="top">
<h2><htk-text form="new" column="title"/></h2> <h2>{{iter.title}}</h2>
<div class="new-text"> <div class="new-text">
<htk-html form="new" column="text"/> <htk-html value="{{iter.text}}"/>
</div> </div>
</div> </div>
</div> </div>

View File

@ -24,7 +24,7 @@ Hedera.Location = new Class({
} }
,onLocationsDone: function(resultSet) { ,onLocationsDone: function(resultSet) {
this.locations = resultSet.fetchResult(); this.locations = resultSet.fetchData();
this.allLoaded(); this.allLoaded();
} }
@ -44,12 +44,11 @@ Hedera.Location = new Class({
,center: new google.maps.LatLng(46.0, 4.0) ,center: new google.maps.LatLng(46.0, 4.0)
}; };
var div = this.$('form'); var div = this.$.form;
var gmap = new google.maps.Map(div, options); var gmap = new google.maps.Map(div, options);
if (this.locations) for (const location of this.locations)
while (this.locations.next()) this.createMarker(location, gmap);
this.createMarker(this.locations, gmap);
} }
,createMarker: function(location, gmap) { ,createMarker: function(location, gmap) {
@ -57,28 +56,28 @@ Hedera.Location = new Class({
div.className = 'marker'; div.className = 'marker';
var h = document.createElement('h3'); var h = document.createElement('h3');
h.appendChild(document.createTextNode(location.get('title'))); h.appendChild(document.createTextNode(location.title));
div.appendChild(h); div.appendChild(h);
var p = document.createElement('p'); var p = document.createElement('p');
p.appendChild(document.createTextNode(location.get('address'))); p.appendChild(document.createTextNode(location.address));
div.appendChild(p); div.appendChild(p);
var p = document.createElement('p'); var p = document.createElement('p');
p.appendChild(document.createTextNode(location.get('postcode') +' '+ location.get('city'))); p.appendChild(document.createTextNode(location.postcode +' '+ location.city));
div.appendChild(p); div.appendChild(p);
var p = document.createElement('p'); var p = document.createElement('p');
p.appendChild(document.createTextNode(location.get('province'))); p.appendChild(document.createTextNode(location.province));
div.appendChild(p); div.appendChild(p);
var p = document.createElement('p'); var p = document.createElement('p');
p.appendChild(document.createTextNode(location.get('phone'))); p.appendChild(document.createTextNode(location.phone));
div.appendChild(p); div.appendChild(p);
var lat = new google.maps.LatLng( var lat = new google.maps.LatLng(
location.get('lat'), location.lat,
location.get('lng') location.lng
); );
var marker = new google.maps.Marker({ var marker = new google.maps.Marker({
@ -95,7 +94,7 @@ Hedera.Location = new Class({
this.openInfoWindow.bind(this, infoWindow, gmap, marker)); this.openInfoWindow.bind(this, infoWindow, gmap, marker));
if (Vn.Locale.language if (Vn.Locale.language
&& Vn.Locale.language == location.get('language')) && Vn.Locale.language == location.language)
this.openInfoWindow(infoWindow, gmap, marker); this.openInfoWindow(infoWindow, gmap, marker);
} }

View File

@ -1 +0,0 @@
{}

View File

@ -1 +0,0 @@
{}

View File

@ -1 +0,0 @@
{}

View File

@ -1 +0,0 @@
{}

View File

@ -1 +0,0 @@
{}

View File

@ -1,59 +0,0 @@
/* News panel */
.column
{
margin: .5em;
max-width: 120em;
}
/* New */
.new
{
text-align: left;
background-color: white;
color: #222;
border: none;
border-radius: 0.1em;
box-shadow: 0 0.2em 0.2em rgba(1, 1, 1, 0.2);
margin: .5em;
}
.new img
{
display: block;
margin: auto;
width: 100%;
}
.new .top
{
padding: 1.5em;
padding-bottom: 1px;
}
.new h2
{
font-size: 1.6em;
color: black;
font-weight: normal;
padding: 0;
}
.new-info
{
font-size: 0.9em;
color: #444;
text-align: right;
margin: 0.8em 0;
}
.new-text
{
margin: 1.5em 0;
}
.new-text a
{
color: blue;
text-decoration: underline;
}
.new-text li
{
margin: 0.4em 0;
}

View File

@ -1,5 +0,0 @@
Hedera.Training = new Class
({
Extends: Hedera.Form
});

View File

@ -1,41 +0,0 @@
<vn>
<div id="title">
<h1><t>Training</t></h1>
</div>
<div id="form" class="training">
<div class="column mansonry" id="news-column">
<htk-repeater form-id="new">
<db-model property="model">
<custom>
SELECT title, created, text, image, id FROM news
WHERE tag = 'course'
ORDER BY priority, created DESC
</custom>
</db-model>
<custom>
<div class="masonry-box">
<div class="new">
<htk-image
directory="news"
subdir="full"
form="new"
column="image"
editable="false"
full-dir="full"/>
<div class="top">
<h2><htk-text form="new" column="title"/></h2>
<p class="new-info">
<htk-text format="_%a, %e %b %Y" form="new" column="created"/>
</p>
<div class="new-text">
<htk-html form="new" column="text"/>
</div>
</div>
</div>
</div>
</custom>
</htk-repeater>
<div class="clear"/>
</div>
</div>
</vn>

View File

@ -1,27 +1,13 @@
.why .why ul {
{
padding: 1em;
}
.why .box
{
max-width: 40em;
margin: 0 auto;
}
.why ul
{
list-style-type: none; list-style-type: none;
padding: 0 1em; padding: 0;
padding-bottom: 1em; margin-top: 0;
max-width: 36em;
margin: 0 auto;
} }
.why li .why li {
{ padding-bottom: 16px;
padding: 0.5em 0;
} }
.why img .why img {
{
display: block; display: block;
margin: 0 auto; margin: 0 auto;
max-width: 95%; max-width: 95%;

View File

@ -3,20 +3,18 @@
<h1><t>AboutCompany</t></h1> <h1><t>AboutCompany</t></h1>
</div> </div>
<div id="form" class="why"> <div id="form" class="why">
<div class="box"> <div class="box vn-w-sm vn-pa-lg">
<div class="body"> <ul class="vn-mb-lg">
<ul> <li><t>BecauseOurBigCatalog</t></li>
<li><t>BecauseOurBigCatalog</t></li> <li><t>BecauseThisWeb</t></li>
<li><t>BecauseThisWeb</t></li> <li><t>BecauseOurShoppingDep</t></li>
<li><t>BecauseOurShoppingDep</t></li> <li><t>BecauseOrderIsEasy</t></li>
<li><t>BecauseOrderIsEasy</t></li> <li><t>BecauseOurPlant</t></li>
<li><t>BecauseOurPlant</t></li> <li><t>BecauseOurSalesDep</t></li>
<li><t>BecauseOurSalesDep</t></li> <li><t>BecauseOurWorkShop</t></li>
<li><t>BecauseOurWorkShop</t></li> <li><t>BecauseWeHaveWhatYouNeed</t></li>
<li><t>BecauseWeHaveWhatYouNeed</t></li> </ul>
</ul> <img src="forms/cms/why/store.png" alt="Store photo"/>
<img src="forms/cms/why/store.png" alt="Store photo"/>
</div>
</div> </div>
</div> </div>
</vn> </vn>

View File

@ -1,58 +1,36 @@
Hedera.Basket = new Class Hedera.Basket = new Class({
({
Extends: Hedera.Form Extends: Hedera.Form
,open: function () ,open: function() {
{ this.close();
this.close ();
this.isOpen = true; this.isOpen = true;
Hedera.BasketChecker.check (this.conn, Hedera.BasketChecker.check(this.conn, this.hash,
this.onBasketCheck.bind (this)); this.onBasketCheck.bind(this));
} }
,onBasketCheck: function (isOk) ,onBasketCheck: function(isOk) {
{
if (isOk) if (isOk)
this.loadUi (); this.loadUi();
} }
,activate: function () ,activate: function() {
{ this.$.items.setInfo('bi', 'myBasketItem', 'hedera');
this.$('items').setInfo ('bi', 'myBasketItem', 'hedera');
} }
,onConfigureClick: function () ,onConfigureClick: function() {
{ Htk.Toast.showWarning(_('RememberReconfiguringImpact'));
Htk.Toast.showWarning (_('RememberReconfiguringImpact')); this.hash.setAll({form: 'ecomerce/checkout'});
this.hash.set ({form: 'ecomerce/checkout'});
} }
,onCatalogClick: function () ,onDeleteClick: function(form) {
{ if (confirm(_('ReallyDelete')))
this.hash.set ({form: 'ecomerce/catalog'}); form.deleteRow();
} }
,onCheckoutClick: function () ,subtotal: function(form) {
{ return form.$.amount * form.$.price;
this.hash.set ({form: 'ecomerce/confirm'});
}
,repeaterFunc: function (res, form)
{
res.$('subtotal').value = this.subtotal (form);
}
,onDeleteClick: function (button, form)
{
if (confirm (_('ReallyDelete')))
form.deleteRow ();
}
,subtotal: function (form)
{
return form.get ('amount') * form.get ('price');
} }
}); });

View File

@ -1,91 +1,65 @@
.basket
{ .basket .head {
padding: 1em; border-bottom: 1px solid #DDD;
} }
.basket .box .basket .head p {
{ font-weight: bold;
max-width: 30em; margin: 0;
margin: 0 auto; padding: 0;
padding: 0 2em; font-size: 1.4em;
text-align: right;
} }
.basket .form > p .basket .form > p {
{
margin: 0; margin: 0;
font-size: 1.4em; font-size: 1.4em;
color: white; color: white;
text-align: right; text-align: right;
} }
.basket .head
{
padding: 1.8em 0;
margin: 0;
border-bottom: 1px solid #DDD;
}
.basket .head p
{
margin: 0;
padding: 0;
font-size: 1.4em;
text-align: right;
}
/* Lines */ /* Lines */
.basket .lines .basket .line {
{ display: flex;
padding: .8em 0; gap: 20px;
margin: 24px 0;
height: 65px;
} }
.basket .line .basket .line:last-child {
{ margin-bottom: 0;
padding: 1em 0;
} }
.basket .line > .delete .basket .line > .delete {
{ align-self: center;
margin: -0.5em;
margin-top: 1em;
margin-right: .5em;
float: left;
} }
.basket .line > .photo .basket .line > .photo {
{ flex: none;
margin-right: 1em;
float: left;
border-radius: 50%; border-radius: 50%;
height: 4.25em; width: 65px;
width: 4.25em;
} }
.basket .line > .info .basket .line > .info {
{ flex: 1;
margin-left: 7.5em;
} }
.basket .line > .info > h2 .basket .line > .info > h2 {
{
font-size: 1em; font-size: 1em;
font-weight: normal; font-weight: normal;
padding: 0; padding: 0;
padding-bottom: .1em; padding-bottom: .1em;
} }
.basket .line > .info > p .basket .line > .info > p {
{
margin: 0; margin: 0;
} }
.basket .line > .info > .tags .basket .line > .info > .tags {
{
color: #777; color: #777;
} }
.basket .line .subtotal .basket .line .subtotal {
{
float: right; float: right;
} }
/* Fields */ /* Fields */
.basket td.available-exceeded input .basket td.available-exceeded input {
{
background-color: #FCC; background-color: #FCC;
} }
.basket .icon > img .basket .icon > img {
{
border-radius: 50%; border-radius: 50%;
} }

View File

@ -4,21 +4,21 @@
</div> </div>
<div id="actions"> <div id="actions">
<htk-bar-button <htk-bar-button
icon="ok" icon="settings"
tip="_Checkout"
on-click="onCheckoutClick"/>
<htk-bar-button
icon="view-dual"
tip="_Catalog"
on-click="onCatalogClick"/>
<htk-bar-button
icon="preferences"
tip="_ConfigureOrder" tip="_ConfigureOrder"
on-click="onConfigureClick"/> on-click="this.onConfigureClick()"/>
<htk-bar-button
icon="local_florist"
tip="_Catalog"
on-click="this.hash.setAll({form: 'ecomerce/catalog'})"/>
<htk-bar-button
icon="shopping_cart_checkout"
tip="_Checkout"
on-click="this.hash.setAll({form: 'ecomerce/confirm'})"/>
</div> </div>
<div id="form" class="basket"> <div id="form" class="basket">
<div class="box"> <div class="box vn-w-sm vn-pa-lg">
<div class="head"> <div class="head vn-pb-lg">
<p> <p>
<t>Total</t> <t>Total</t>
<htk-text format="%.2d€"> <htk-text format="%.2d€">
@ -27,7 +27,7 @@
</p> </p>
</div> </div>
<div class="lines"> <div class="lines">
<htk-repeater form-id="iter" renderer="repeaterFunc"> <htk-repeater form-id="iter">
<db-model id="items" property="model" updatable="true"> <db-model id="items" property="model" updatable="true">
SELECT bi.id, bi.amount, bi.price, i.longName item, SELECT bi.id, bi.amount, bi.price, i.longName item,
i.tag5, i.value5, i.tag6, i.value6, i.tag7, i.value7, i.tag5, i.value5, i.tag6, i.value6, i.tag7, i.value7,
@ -41,38 +41,29 @@
<custom> <custom>
<div class="line"> <div class="line">
<htk-button <htk-button
form="iter"
column="id"
class="delete" class="delete"
tip="_Remove" tip="_Remove"
icon="delete" icon="delete"
on-click="onDeleteClick"/> on-click="this.onDeleteClick($iter)"/>
<htk-image <htk-image
form="iter" value="{{iter.image}}"
column="image"
stamp-column="updated" stamp-column="updated"
class="photo" class="photo"
directory="catalog" directory="catalog"
subdir="200x200" subdir="200x200"
full-dir="1600x900"/> full-dir="1600x900"/>
<div class="info"> <div class="info">
<h2> <h2>{{iter.item}}</h2>
<htk-text form="iter" column="item"/>
</h2>
<p class="tags"> <p class="tags">
<htk-text form="iter" column="value5"/> {{iter.value5}} {{iter.value6}} {{iter.value7}}
<htk-text form="iter" column="value6"/>
<htk-text form="iter" column="value7"/>
</p> </p>
<p class="amount"> <p class="amount">
<htk-text form="iter" column="amount"/> x {{iter.amount}} x {{Vn.Value.format(iter.price, '%.2d€')}}
<htk-text form="iter" column="price" format="%.2d€"/>
<span class="subtotal"> <span class="subtotal">
<htk-text id="subtotal" format="%.2d€"/> {{Vn.Value.format(iter.price * iter.amount, '%.2d€')}}
</span> </span>
</p> </p>
</div> </div>
<div class="clear"/>
</div> </div>
</custom> </custom>
</htk-repeater> </htk-repeater>

View File

@ -8,8 +8,8 @@ Hedera.Catalog = new Class({
this.close(); this.close();
this.isOpen = true; this.isOpen = true;
if (!localStorage.getItem('hederaGuest')) { if (!localStorage.getItem('hederaGuest')) {
Hedera.BasketChecker.check(this.conn, Hedera.BasketChecker.check(this.conn, this.hash,
this.onBasketCheck.bind(this)); this.onBasketCheck.bind(this));
} else { } else {
var query = 'CALL mybasket_configureForGuest'; var query = 'CALL mybasket_configureForGuest';
@ -23,40 +23,143 @@ Hedera.Catalog = new Class({
} }
,activate: function() { ,activate: function() {
document.body.appendChild(this.$('right-panel')); document.body.appendChild(this.$.rightPanel);
this.$.items.setInfo('i', 'item', 'vn', ['id']);
this.$('items-model').setInfo('i', 'item', 'vn', ['id']);
if (localStorage.getItem('hederaView')) if (localStorage.getItem('hederaView'))
this.setView(parseInt(localStorage.getItem('hederaView'))); this.setView(parseInt(localStorage.getItem('hederaView')));
else else
this.setView(Hedera.Catalog.View.GRID); this.setView(Hedera.Catalog.View.GRID);
this.onFilterChange();
} }
,deactivate: function() { ,deactivate: function() {
this.hideMenu(); this.hideMenu();
this.gui.$('top-bar').style.backgroundColor = ''; this.gui.$.topBar.style.backgroundColor = '';
Vn.Node.remove(this.$('right-panel')); Vn.Node.remove(this.$.rightPanel);
}
,getFilter(params, tags, currentTag) {
if (params.search == null && params.type == null)
return null;
const $ = this.$;
params = Object.assign({}, params);
const filter = new Sql.Operation({
type: Sql.Operation.Type.AND
});
let idSearch = false;
if (params.search != null) {
idSearch = /^\d+$/.test(params.search);
if (!idSearch) {
filter.push($.searchOp);
params.search = `%${params.search}%`;
} else
filter.push($.idOp);
}
if (!idSearch) {
if (params.realm != null)
filter.push($.realmOp);
if (params.type != null)
filter.push($.typeOp);
for (const tag of tags)
if (tag != currentTag && params[tag] != null)
filter.push($[`${tag}Op`]);
}
params.filter = filter;
const lot = new Vn.Lot();
lot.setAll(params);
return lot;
}
,onFilterChange: function() {
const $ = this.$;
const params = $.params.$;
this.refreshTitle();
const hasRealm = params.realm != null;
$.filters.style.display = hasRealm ? 'block' : 'none';
$.realmMsg.style.display = hasRealm ? 'none' : 'block';
const tags = [
'color',
'origin',
'category',
'producer'
];
const lot = this.getFilter(params, tags);
if (lot) {
$.items.lot = lot;
$.items.refresh();
} else
$.items.clean();
for (const tag of tags)
$[`${tag}s`].lot = this.getFilter(params, tags, tag);
if (lot) this.hideMenu();
}
,refreshTitle: function() {
const hash = this.hash.$;
const types = this.$.types;
const realms = this.$.realms;
const type = hash.type;
const realm = hash.realm;
let typeName;
let realmName;
if (type && types.ready) {
var row = types.search('id', type);
if (row != -1) typeName = types.get(row, 'name');
}
if (realm && realms.ready) {
var row = realms.search('id', realm);
if (row != -1) realmName = realms.get(row, 'name');
}
let title = _('Catalog');
let subtitle = '';
if (typeName) {
title = typeName;
subtitle = realmName;
} else if (realmName) {
title = realmName;
}
Vn.Node.setText(this.$.titleText, title);
Vn.Node.setText(this.$.subtitle, subtitle);
} }
,setView: function(view) { ,setView: function(view) {
if (view === Hedera.Catalog.View.GRID) { if (view === Hedera.Catalog.View.GRID) {
this.$('view-button').setProperties({ this.$.viewButton.setProperties({
icon: 'view-list', icon: 'view_list',
tip: _('List view') tip: _('List view')
}); });
this.view = Hedera.Catalog.View.GRID; this.view = Hedera.Catalog.View.GRID;
var className = 'grid-view'; var className = 'grid-view';
} else { } else {
this.$('view-button').setProperties({ this.$.viewButton.setProperties({
icon: 'view-grid', icon: 'grid_on',
tip: _('Grid view') tip: _('Grid view')
}); });
this.view = Hedera.Catalog.View.LIST; this.view = Hedera.Catalog.View.LIST;
var className = 'list-view'; var className = 'list-view';
} }
var node = this.$('grid-view').node; var node = this.$.gridView.node;
node.className = className; node.className = className;
localStorage.setItem('hederaView', this.view); localStorage.setItem('hederaView', this.view);
} }
@ -66,18 +169,11 @@ Hedera.Catalog = new Class({
Hedera.Catalog.View.GRID : Hedera.Catalog.View.LIST); Hedera.Catalog.View.GRID : Hedera.Catalog.View.LIST);
} }
,onBasketReady: function(form) {
if (form.get('method') != 'PICKUP')
Vn.Node.setText(this.$('method'), _('Agency'));
else
Vn.Node.setText(this.$('method'), _('Warehouse'));
}
,onItemsChange: function(model, status) { ,onItemsChange: function(model, status) {
if (status !== Db.Model.Status.CLEAN) if (status !== Db.Model.Status.CLEAN)
this.$('order').style.display = 'block'; this.$.order.style.display = 'block';
else else
this.$('order').style.display = 'none'; this.$.order.style.display = 'none';
} }
,onOrderChange: function(e) { ,onOrderChange: function(e) {
@ -87,98 +183,17 @@ Hedera.Catalog = new Class({
Db.Model.SortWay.ASC : Db.Model.SortWay.DESC; Db.Model.SortWay.ASC : Db.Model.SortWay.DESC;
if (sortField) if (sortField)
this.$('items-model').sortByName(sortField, sortWay); this.$.items.sortByName(sortField, sortWay);
this.hideMenu(); this.hideMenu();
} }
,onFilterChange: function(param, newValue) {
if (newValue)
this.hideMenu();
}
,realmRenderer: function(builder, form) { ,realmRenderer: function(builder, form) {
var link = builder.$('link'); var link = builder.$.link;
link.href = this.hash.make({ link.href = this.hash.make({
'form': this.hash.get('form'), form: this.hash.$.form,
'realm': form.get('id') realm: form.$.id
}); });
var img = builder.$('image');
img.src = 'image/family/light/'+ form.get('code') +'.svg';
img.title = form.get('name');
img.alt = img.title;
}
,onRealmChange: function(param, newValue) {
if (newValue) {
this.$('filters').style.display = 'block';
this.$('realm-msg').style.display = 'none';
} else {
this.$('filters').style.display = 'none';
this.$('realm-msg').style.display = 'block';
}
this.refreshTitleColor();
this.refreshFilter(newValue, undefined);
}
,onTypeChange: function(param, newValue) {
this.onFilterChange(param, newValue);
this.refreshTitle();
this.refreshFilter(undefined, newValue);
}
,refreshFilter: function(realm, type) {
var batch = this.$('filter-batch');
batch.block();
this.$('realm-value').value = realm;
this.$('type-value').value = type;
this.$('search').value = undefined;
this.$('color').value = undefined;
this.$('origin').value = undefined;
this.$('category').value = undefined;
this.$('producer').value = undefined;
batch.unblock();
batch.changed();
}
,refreshTitleColor: function() {
var realms = this.$('realms-model');
if (!realms.ready)
return;
var color = null;
var realm = this.$('realm').value;
if (realm) {
var row = realms.search('id', realm);
if (row != -1)
color = '#'+ realms.get(row, 'color');
}
this.gui.$('top-bar').style.backgroundColor = color;
}
,refreshTitle: function() {
var types = this.$('types-model');
if (!types.ready)
return;
var title = _('Catalog');
var type = this.$('type').value;
if (type) {
var row = types.search('id', type);
if (row != -1)
title = types.get(row, 'name');
}
Vn.Node.setText(this.$('title-text'), title);
} }
,onRightPanelClick: function(event) { ,onRightPanelClick: function(event) {
@ -189,7 +204,7 @@ Hedera.Catalog = new Class({
this._menuShown = true; this._menuShown = true;
event.stopPropagation(); event.stopPropagation();
this.gui.showBackground(); this.gui.showBackground();
Vn.Node.addClass(this.$('right-panel'), 'show'); Vn.Node.addClass(this.$.rightPanel, 'show');
this.hideMenuCallback = this.hideMenu.bind(this); this.hideMenuCallback = this.hideMenu.bind(this);
document.addEventListener('click', this.hideMenuCallback); document.addEventListener('click', this.hideMenuCallback);
} }
@ -199,7 +214,7 @@ Hedera.Catalog = new Class({
return; return;
this.gui.hideBackground(); this.gui.hideBackground();
Vn.Node.removeClass(this.$('right-panel'), 'show'); Vn.Node.removeClass(this.$.rightPanel, 'show');
document.removeEventListener('click', this.hideMenuCallback); document.removeEventListener('click', this.hideMenuCallback);
this.hideMenuCallback = null; this.hideMenuCallback = null;
} }
@ -217,34 +232,29 @@ Hedera.Catalog = new Class({
if (this.isGuest()) if (this.isGuest())
return; return;
this.hash.set({'form': 'ecomerce/basket'}); this.hash.setAll({form: 'ecomerce/basket'});
} }
,onConfigureClick: function() { ,onConfigureClick: function() {
if (this.isGuest()) if (this.isGuest())
return; return;
this.hash.set({'form': 'ecomerce/checkout'}); this.hash.setAll({form: 'ecomerce/checkout'});
} }
,repeaterFunc: function(res, form) { ,onAddItemClick: function(event, form) {
res.$('item-box').addEventListener('click',
this.onAddItemClick.bind(this, form));
}
,onAddItemClick: function(form, event) {
if (event.defaultPrevented) return; if (event.defaultPrevented) return;
event.preventDefault(); event.preventDefault();
if (this.isGuest()) return; if (this.isGuest()) return;
this.onEraseClick(); this.onEraseClick();
this.$('card').row = form.row; this.$.$card.row = form.row;
this.$('card-item').value = form.get('id'); this.$.cardLot.assign({item: form.$.id});
this.$('card-popup').show(event.currentTarget); this.$.cardPopup.show(event.currentTarget);
} }
,onAddLotClick: function(column, value, row) { ,onAddLotClick: function(column, value, row) {
var model = this.$('item-lots'); var model = this.$.itemLots;
var grouping = model.get(row, 'grouping'); var grouping = model.get(row, 'grouping');
var warehouse = model.get(row, 'warehouseFk'); var warehouse = model.get(row, 'warehouseFk');
var available = model.get(row, 'available'); var available = model.get(row, 'available');
@ -261,14 +271,13 @@ Hedera.Catalog = new Class({
newAmount = available; newAmount = available;
this.items[warehouse] = newAmount; this.items[warehouse] = newAmount;
this.$('amount').value += newAmount - lotAmount; this.$.amount.value += newAmount - lotAmount;
} else } else
Htk.Toast.showError(_('NoMoreAmountAvailable')); Htk.Toast.showError(_('NoMoreAmountAvailable'));
} }
,onConfirmClick: function() { ,onConfirmClick: function() {
var sql = ''; var sql = '';
var batch = new Sql.Batch();
var query = new Sql.String({query: 'CALL myBasket_addItem(#warehouse, #item, #amount);'}); var query = new Sql.String({query: 'CALL myBasket_addItem(#warehouse, #item, #amount);'});
var amountSum = 0; var amountSum = 0;
@ -276,36 +285,38 @@ Hedera.Catalog = new Class({
var amount = this.items[warehouse]; var amount = this.items[warehouse];
amountSum += amount; amountSum += amount;
batch.addValue('warehouse', warehouse); const params = {
batch.addValue('item', this.$('card-item').value); warehouse: warehouse,
batch.addValue('amount', amount); item: this.$.cardLot.$.item,
sql += query.render(batch); amount: amount
}
sql += query.render(params);
} }
if (amountSum > 0) { if (amountSum > 0) {
this.conn.execQuery(sql); this.conn.execQuery(sql);
var itemName = this.$('card').get('item'); var itemName = this.$.$card.get('item');
Htk.Toast.showMessage( Htk.Toast.showMessage(
sprintf(_('Added%dOf%s'), amountSum, itemName)); Vn.Value.sprintf(_('Added%dOf%s'), amountSum, itemName));
} }
this.$('card-popup').hide(); this.$.cardPopup.hide();
} }
,onEraseClick: function() { ,onEraseClick: function() {
this.$('amount').value = 0; this.$.amount.value = 0;
this.items = {}; this.items = {};
} }
,onPopupClose: function() { ,onPopupClose: function() {
this.onEraseClick(); this.onEraseClick();
this.$('card').row = -1; this.$.$card.row = -1;
this.$('card-item').value = undefined; this.$.cardLot.value = undefined;
} }
,onCardLoad: function() { ,onCardLoad: function() {
this.$('card-popup').reset(); this.$.cardPopup.reset();
} }
}); });
@ -315,161 +326,3 @@ Hedera.Catalog.extend({
GRID: 1 GRID: 1
} }
}); });
Vn.Filter = new Class({
Extends: Htk.Field
,Tag: 'vn-filter'
,Child: 'model'
,Properties:
{
model:
{
type: Db.Model
,set: function(x) {
x.batch = this._batch;
this._model = x;
this._select.model = x;
}
,get: function() {
return this._model;
}
},
placeholder:
{
type: String
,set: function(x) {
this._select.placeholder = x;
this._placeholder = x;
}
,get: function() {
return this._placeholder;
}
},
filter:
{
type: Sql.Filter
,set: function(x) {
this._filter = x;
this._batch.addObject('filter', x);
}
,get: function() {
return this._filter;
}
},
}
,_valueColumnIndex: 0
,_showColumnIndex: 1
,initialize: function(props) {
var node = this.createRoot('div');
node.className = 'vn-filter';
this._select = new Htk.Select();
this._select.on('mousedown', this._onMouseDown, this);
this._select.on('changed', this._onChange, this);
this._select.on('ready', this._onReady, this);
this.node.appendChild(this._select.node);
this._ul = this.createElement('ul');
this.node.appendChild(this._ul);
this._batch = new Sql.Batch();
this.parent(props);
}
,_onMouseDown: function() {
if (this._model && this._model.status === Db.Model.Status.CLEAN)
this._model.refresh();
}
,_onCloseClick: function() {
this._removeSelectionNode();
this._changeValue(undefined);
}
,_removeSelectionNode: function() {
if (this._lastLi) {
Vn.Node.remove(this._lastLi);
this._lastLi = null;
this._label = null;
}
}
,_onChange: function() {
if (this._select.value === null
|| this._select.value === undefined)
return;
this._realSetValue(this._select.value);
}
,_onReady: function() {
if (this._emptyLabel)
this._refreshLabel();
}
,_changeValue: function(newValue) {
this._batch.block();
this.value = newValue;
this._batch.unblock();
}
,_onTimeout: function() {
this._select.value = null;
}
,putValue: function(value) {
this._onMouseDown();
this._realSetValue(value);
}
,_realSetValue: function(value) {
this._removeSelectionNode();
if (value === null || value === undefined)
return;
var li = this._lastLi = this.createElement('li');
this._ul.appendChild(li);
var button = this.createElement('button');
button.addEventListener('click',
this._onCloseClick.bind(this, li));
li.appendChild(button);
var icon = new Htk.Icon({
icon: 'close',
alt: _('Close')
});
button.appendChild(icon.node);
var text = this._label = this.createTextNode('');
li.appendChild(text);
setTimeout(this._onTimeout.bind(this));
this._changeValue(value);
this._refreshLabel();
}
,_refreshLabel: function() {
if (!this._label)
return;
var row = -1;
if (this._model.ready)
row = this._model.searchByIndex(this._valueColumnIndex, this._value);
if (row != -1) {
var label = this._model.getByIndex(row, this._showColumnIndex);
this._label.nodeValue = label;
this._emptyLabel = false;
} else {
this._emptyLabel = true;
this._label.nodeValue = _('Loading...');
}
}
});

View File

@ -2,7 +2,7 @@ Catalog: Catàleg
SearchResults: Resultats de cerca SearchResults: Resultats de cerca
SelectFamily: Selecciona una família SelectFamily: Selecciona una família
Choose filter from right menu: Tria un filtre en el menú de la dreta Choose filter from right menu: Tria un filtre en el menú de la dreta
Choose a realm: Tria un regne Choose a realm: Tria un categoria
ArticleNotFound: Artcle no trobat ArticleNotFound: Artcle no trobat
ArticleNotAvailable: Article no disponible ArticleNotAvailable: Article no disponible
List view: Vista de lista List view: Vista de lista
@ -15,7 +15,7 @@ Warehouse: Magatzem
Filter by: Filtrar per Filter by: Filtrar per
Order by: Ordenar per Order by: Ordenar per
Search: Cercar Search: Cercar
Change: Cambiar Modify: Modificar
Size: Mida Size: Mida
Realm: Regne Realm: Regne
Family: Família Family: Família
@ -35,6 +35,7 @@ Lower size: Mida més petita
Higher size: Mida més gran Higher size: Mida més gran
'%.0d Units': '%.0d Unitats' '%.0d Units': '%.0d Unitats'
for: per for: per
Zoom image: Ampliar imatge
AddToBasket: Afegir article AddToBasket: Afegir article
Add: Afegir Add: Afegir
Erase: Esborrar Erase: Esborrar

View File

@ -2,7 +2,7 @@ Catalog: Catalog
SearchResults: Search results SearchResults: Search results
SelectFamily: Select family SelectFamily: Select family
Choose filter from right menu: Choose a filter from the right menu Choose filter from right menu: Choose a filter from the right menu
Choose a realm: Choose a realm Choose a realm: Choose a category
ArticleNotFound: Item not found ArticleNotFound: Item not found
ArticleNotAvailable: Item not available ArticleNotAvailable: Item not available
List view: List view List view: List view
@ -15,7 +15,7 @@ Warehouse: Warehouse
Filter by: Filter by Filter by: Filter by
Order by: Order by Order by: Order by
Search: Search Search: Search
Change: Change Modify: Modify
Size: Size Size: Size
Realm: Realm Realm: Realm
Family: Family Family: Family
@ -35,6 +35,7 @@ Lower size: Lower size
Higher size: Higher size Higher size: Higher size
'%.0d Units': '%.0d Units' '%.0d Units': '%.0d Units'
for: for for: for
Zoom image: Zoom image
AddToBasket: Add to basket AddToBasket: Add to basket
Add: Add Add: Add
Erase: Remove Erase: Remove

View File

@ -2,7 +2,7 @@ Catalog: Catálogo
SearchResults: Resultados de búsqueda SearchResults: Resultados de búsqueda
SelectFamily: Selecciona una familia SelectFamily: Selecciona una familia
Choose filter from right menu: Elige un filtro en el menú de la derecha Choose filter from right menu: Elige un filtro en el menú de la derecha
Choose a realm: Elige un reino Choose a realm: Elige una categoría
ArticleNotFound: Artículo no encontrado ArticleNotFound: Artículo no encontrado
ArticleNotAvailable: Artículo no disponible ArticleNotAvailable: Artículo no disponible
List view: Vista de lista List view: Vista de lista
@ -15,7 +15,7 @@ Warehouse: Almacén
Filter by: Filtrar por Filter by: Filtrar por
Order by: Ordenar por Order by: Ordenar por
Search: Buscar Search: Buscar
Change: Cambiar Modify: Modificar
Size: Medida Size: Medida
Realm: Reino Realm: Reino
Family: Familia Family: Familia
@ -35,6 +35,7 @@ Higher size: Medida más grande
Relevancy: Relevancia Relevancy: Relevancia
'%.0d Units': '%.0d Unidades' '%.0d Units': '%.0d Unidades'
for: por for: por
Zoom image: Ampliar imagen
AddToBasket: Añadir artículo AddToBasket: Añadir artículo
Add: Añadir Add: Añadir
Erase: Borrar Erase: Borrar

View File

@ -2,7 +2,7 @@ Catalog: Catalogue
SearchResults: Résultats de la recherche SearchResults: Résultats de la recherche
SelectFamily: Choisissez une famille SelectFamily: Choisissez une famille
Choose filter from right menu: Choisissez un filtre dans le menu de droite Choose filter from right menu: Choisissez un filtre dans le menu de droite
Choose a realm: Choisissez un royaume Choose a realm: Choisissez une catégorie
ArticleNotFound: Article non trouvé ArticleNotFound: Article non trouvé
ArticleNotAvailable: Article non disponible ArticleNotAvailable: Article non disponible
List view: Liste voir List view: Liste voir
@ -15,7 +15,7 @@ Warehouse: Entrepôt
Filter by: Filtrer par Filter by: Filtrer par
Order by: Trier par Order by: Trier par
Search: Recherche Search: Recherche
Change: Modifier Modify: Modifier
Size: Mesure Size: Mesure
Realm: Famille Realm: Famille
Family: Sous-genre Family: Sous-genre
@ -35,6 +35,7 @@ Lower size: Taille le plus bas
Higher size: Taille le plus élevé Higher size: Taille le plus élevé
'%.0d Units': '%.0d Unités' '%.0d Units': '%.0d Unités'
for: pour for: pour
Zoom image: Agrandir l'image
AddToBasket: Ajouter article AddToBasket: Ajouter article
Add: Ajouter Add: Ajouter
Erase: Effacer Erase: Effacer

View File

@ -2,7 +2,7 @@ Catalog: Catálogo
SearchResults: Resultados de busca SearchResults: Resultados de busca
SelectFamily: Seleccione uma família SelectFamily: Seleccione uma família
Choose filter from right menu: Escolha um filtro no menú da direita Choose filter from right menu: Escolha um filtro no menú da direita
Choose a realm: Escolha um reino Choose a realm: Escolha uma categoria
ArticleNotFound: Ítem não encontrado ArticleNotFound: Ítem não encontrado
ArticleNotAvailable: Ítem não disponível ArticleNotAvailable: Ítem não disponível
List view: Ver como lista List view: Ver como lista
@ -15,7 +15,7 @@ Warehouse: Armazém
Filter by: Filtrar por Filter by: Filtrar por
Order by: Ordenar por Order by: Ordenar por
Search: Buscar Search: Buscar
Change: Modificar Modify: Modificar
Size: Medida Size: Medida
Realm: Reino Realm: Reino
Family: Família Family: Família
@ -35,6 +35,7 @@ Lower size: Tamanho menor
Higher size: Tamanho maior Higher size: Tamanho maior
'%.0d Units': '%.0d Unidades' '%.0d Units': '%.0d Unidades'
por: para por: para
Zoom image: Mais zoom
AddToBasket: Adicionar à Cesta AddToBasket: Adicionar à Cesta
Add: Adicionar Add: Adicionar
Erase: Eliminar Erase: Eliminar

View File

@ -1,180 +1,131 @@
.catalog .catalog {
{ margin-right: 18em;
margin-right: 17em;
} }
.title ._subtitle {
/* Topbar */ font-size: .7rem;
color: #bbb;
.catalog-actions > .htk-search-entry
{
margin-top: .8em;
margin-right: .4em;
}
/* Right panel */
.right-panel
{
position: fixed;
top: 3.9em;
bottom: 0;
right: 0;
width: 17em;
background-color: white;
box-shadow: 0 0 .2em rgba(1, 1, 1, .2);
overflow: auto;
}
.right-panel .basket-info
{
background-color: #00ACC1;
color: white;
box-shadow: 0 .1em .1em rgba(1, 1, 1, .3);
padding: 1.2em 2em;
}
.right-panel .basket-info > button
{
color: #E0F2F1;
margin: 0 auto;
display: block;
margin-top: .4em;
}
.right-panel .basket-info > p
{
margin: 0;
padding: .4em 0;
font-size: 1.1em;
text-align: left;
text-overflow: ellipsis; text-overflow: ellipsis;
white-space: nowrap; white-space: nowrap;
overflow: hidden; overflow: hidden;
} }
.right-panel .filter
{ /* Right panel */
padding: 1em;
.right-panel {
position: fixed;
top: 4.4em;
bottom: 0;
right: 0;
width: 18em;
overflow: auto;
background-color: #fafafa;
}
.right-panel .basket-info {
background-color: #8cc63f;
color: white;
padding: 1.2em 2em;
border-radius: .5em;
margin: 1em;
text-align: center;
}
.right-panel .basket-info > button {
color: white;
background-color: rgba(0, 0, 0, .1);
margin: 0 auto;
display: block;
margin-top: 10px;
padding: 10px 15px;
}
.right-panel .basket-info > button:hover {
background-color: white;
color: #60872c;
}
.right-panel .basket-info > p {
margin: 0;
padding: .4em 0;
text-overflow: ellipsis;
white-space: nowrap;
overflow: hidden;
}
.right-panel .filter {
margin: 1em;
}
.right-panel .categories,
.right-panel .filters,
.right-panel .order {
margin: 1.5em 0;
} }
.right-panel .filters, .right-panel .filters,
.right-panel .order .right-panel .order {
{
display: none; display: none;
} }
.right-panel .realm-msg .right-panel .realm-msg {
{
margin-top: 1em; margin-top: 1em;
} }
.right-panel .realm-msg > h1 .right-panel .realm-msg > h5 {
{
font-weight: normal; font-weight: normal;
text-align: center; text-align: center;
padding: 2.5em 0; padding: 2.5em 0;
color: #777; color: #777;
} }
.right-panel h2 .right-panel h2 {
{
font-weight: normal; font-weight: normal;
padding: .4em 0;
color: #777; color: #777;
font-size: 1.1em; font-size: 1.1em;
} }
.right-panel .realms > div > div .right-panel .realms > div > div {
{
text-align: center; text-align: center;
} }
.right-panel .realms a .right-panel .realms a {
{
display: inline-block; display: inline-block;
width: 30%; width: 25%;
padding: .6em; padding: .6em;
box-sizing: border-box; box-sizing: border-box;
border-radius: 50%;
} }
.right-panel .realms a:hover .right-panel .realms a:hover {
{
background-color: rgba(1, 1, 1, .05); background-color: rgba(1, 1, 1, .05);
border-radius: .15em;
} }
.right-panel .realms a > img .right-panel .realms a > img {
{
display: block; display: block;
padding: 0; padding: 0;
width: 100%; width: 100%;
} }
.right-panel .vn-filter, .right-panel .filters > button {
.right-panel select
{
margin: 0 auto;
margin-bottom: .7em;
width: 90%;
display: block;
}
.vn-filter > ul
{
margin: 0;
list-style-type: none;
text-align: left;
color: #666;
padding-left: .8em;
}
.vn-filter li
{
margin: 0;
margin-top: .3em;
line-height: 2em;
max-width: 90%;
text-overflow: ellipsis;
white-space: nowrap;
overflow: hidden;
}
.vn-filter li > button
{
vertical-align: middle;
text-align: center;
padding: .2em;
margin: 0;
margin-right: .2em;
}
.right-panel .filters > button
{
display: block;
margin: 0 auto;
margin-top: 1em; margin-top: 1em;
} }
/* Items */ /* Items */
.item-box .item-box {
{ display: flex;
transition: background-color 200ms ease-in; box-sizing: border-box;
} }
.item-box:hover .item-box > .htk-image {
{ flex: none;
cursor: pointer;
background-color: #eee;
} }
.item-info .item-box > .item-info {
{ flex: auto;
position: relative; position: relative;
} }
.item-info .second-category .item-info .second-category {
{
font-weight: bold; font-weight: bold;
color: orange; color: orange;
} }
.item-info .third-category .item-info .third-category {
{
font-weight: bold; font-weight: bold;
color: red; color: red;
} }
.item-info > h2 .item-info > h2 {
{
padding: 0; padding: 0;
margin-bottom: .15em; margin-bottom: .15em;
font-weight: normal; font-weight: normal;
font-size: 1em; font-size: 1em;
text-overflow: ellipsis; text-overflow: ellipsis;
overflow: hidden; overflow: hidden;
max-height: 3.8em; max-height: 3em;
} }
.item-info > p .item-info > p {
{
margin: 0; margin: 0;
padding: 0; padding: 0;
color: #777; color: #777;
@ -183,24 +134,29 @@
white-space: nowrap; white-space: nowrap;
overflow: hidden; overflow: hidden;
} }
.item-info .sub-name .item-info .sub-name {
{
text-transform: uppercase; text-transform: uppercase;
padding: 0; padding: 0;
margin-bottom: .2em; margin-bottom: .2em;
font-size: .9em; font-size: .9em;
} }
.item-info > .htk-button .item-info > .htk-button {
{
margin: -0.3em; margin: -0.3em;
padding: .3em; padding: .3em;
} }
.item-info > .htk-button > img .item-info > .htk-button > img {
{
vertical-align: middle; vertical-align: middle;
} }
.item-info .available-price .item-info .item-id {
{ float: right;
font-size: .8rem;
line-height: 1.8em;
color: #777;
}
.item-info .available-price {
position: absolute;
bottom: 0;
right: 0;
white-space: nowrap; white-space: nowrap;
font-size: .95em; font-size: .95em;
text-align: right; text-align: right;
@ -208,32 +164,27 @@
column-gap: .2em; column-gap: .2em;
display: flex; display: flex;
} }
.item-info .available-price > * .item-info .available-price > * {
{
border-radius: .2em; border-radius: .2em;
padding: .3em; padding: .1em .3em;
border: .1em transparent solid; border: .1em transparent solid;
background-color: white; box-sizing: border-box;
} }
.item-info .grouping .item-info .grouping {
{ width: 38px;
width: 2em;
background-color: #ddd; background-color: #ddd;
} }
.item-info .available .item-info .available {
{ width: 65px;
width: 3.3em;
border-color: #bbb; border-color: #bbb;
color: #777; color: #777;
} }
.item-info .price .item-info .price {
{ width: 75px;
width: 4em;
border-color: #9cbc28; border-color: #9cbc28;
color: #748c1e; color: #748c1e;
} }
.tags .tags {
{
font-size: .8em; font-size: .8em;
display: table; display: table;
color: #333; color: #333;
@ -246,129 +197,38 @@
padding-right: .5em; padding-right: .5em;
} }
/* List view */
.list-view
{
max-width: 30em;
margin: 0 auto;
padding: 1em;
}
.list-view .item-box
{
display: block;
position: relative;
width: 100%;
margin: 0;
height: 5.5em;
overflow: visible;
border-bottom: 1px solid #DDD;
}
.list-view .item-box > .htk-image
{
margin: 1em;
width: 3.5em;
height: 3.5em;
float: left;
overflow: hidden;
}
.list-view .item-box > .htk-image > img
{
border-radius: 50%;
}
.list-view .item-info
{
position: absolute;
left: 5.5em;
right: 0;
top: 0;
bottom: 0;
margin: .8em;
margin-left: 0;
}
.list-view .item-info > h2
{
font-size: 1em;
white-space: nowrap;
}
.list-view .item-info > .color
{
display: none;
}
.list-view .item-info > .htk-button
{
float: right;
}
.list-view .item-info .available-price
{
clear: both;
float: right;
position:absolute;
bottom: 0;
right: 0;
}
.list-view .item-info .tags
{
display: block;
text-overflow: ellipsis;
white-space: nowrap;
overflow: hidden;
}
.list-view .item-info .tags > tr
{
display: inline-block;
}
.list-view .item-info .tags td
{
display: inline-block;
padding-right: .5em;
}
.list-view .item-info .tags td:first-child
{
display: none;
}
/* Grid view */ /* Grid view */
.grid-view .grid-view > * {
{ display: flex;
padding: 1em; gap: 16px;
padding-right: .2em; flex-wrap: wrap;
padding-bottom: .4em; justify-content: center;
text-align: center;
} }
.grid-view .item-box .grid-view .item-box {
{ border-radius: .6em;
text-align: left; box-shadow: .05em .05em .2em rgba(0, 0, 0, .1);
position: relative; overflow: hidden;
display: inline-block; background-color: white;
width: 24em;
margin: 0; flex-direction: column;
margin-right: .8em; width: 260px;
margin-bottom: .6em; height: 425px;
height: 11em;
overflow: hidden; overflow: hidden;
} }
.grid-view .item-box > .htk-image .grid-view .item-box:hover {
{ background-color: #efefef;
width: 11em;
height: 100%;
float: left;
} }
.grid-view .item-info .grid-view .item-info {
{ margin: 10px;
position: absolute;
left: 11.4em;
right: 0;
top: 0;
bottom: 0;
margin: .6em;
} }
.grid-view .item-info .available-price .grid-view .item-box > .htk-image {
{ width: 260px;
position: absolute; height: 260px;
bottom: 0; }
right: 0; .grid-view .item-box > .item-info {
flex: auto;
overflow: hidden;
} }
.grid-view .item-info .tags td { .grid-view .item-info .tags td {
overflow: hidden; overflow: hidden;
@ -379,109 +239,138 @@
line-height: 1.1em; line-height: 1.1em;
} }
/* List view */
.list-view {
border-radius: .6em;
box-shadow: .05em .05em .2em rgba(0, 0, 0, .1);
overflow: hidden;
background-color: white;
max-width: 544px;
margin: 0 auto;
}
.list-view .item-box {
gap: 10px;
margin: 0;
padding: 10px;
height: 130px;
overflow: visible;
border-bottom: 1px solid #DDD;
}
.list-view .item-box:last-child {
border-bottom: none;
}
.list-view .item-box > .htk-image {
width: 110px;
height: 110px;
border-radius: 50%;
}
.list-view .item-info {
overflow: hidden;
}
.list-view .item-info > h2 {
font-size: 1rem;
white-space: nowrap;
}
.list-view .item-info > .color {
display: none;
}
.list-view .item-info > .htk-button {
float: right;
}
.list-view .item-info .tags {
display: block;
text-overflow: ellipsis;
white-space: nowrap;
overflow: hidden;
}
.list-view .item-info .tags > tr {
display: inline-block;
}
.list-view .item-info .tags td {
display: inline-block;
padding-right: .5em;
}
.list-view .item-info .tags td:first-child {
display: none;
}
/* Card */ /* Card */
.card-popup .card-popup {
{
overflow: auto; overflow: auto;
} }
.item-card .item-card {
{
font-size: .9em; font-size: .9em;
width: 20em; width: 20em;
} }
.item-card .top .item-card .top {
{
padding: 1em; padding: 1em;
} }
.item-card .item-info .item-card .item-info {
{
margin-left: 9em; margin-left: 9em;
height: 8em; height: 8em;
} }
.item-card .htk-image .item-card .htk-image {
{
height: 8em; height: 8em;
width: 8em; width: 8em;
float: left; float: left;
border-radius: .3em; border-radius: .3em;
} }
.item-card .desc .item-card .desc {
{
clear: both; clear: both;
margin-top: 1em 0; margin-top: 1em 0;
font-size: .9em; font-size: .9em;
} }
.item-card .lots-grid .item-card .lots-grid {
{
border-top: 1px solid #DDD; border-top: 1px solid #DDD;
} }
.item-card .lots-grid tr .item-card .lots-grid tr {
{
height: 3em; height: 3em;
} }
.item-card .lots-grid .cell-spin .item-card .lots-grid .cell-spin {
{
max-width: initial; max-width: initial;
width: 3em; width: 3em;
} }
.item-card .lots-grid .price-kg .item-card .lots-grid .price-kg {
{
font-size: .8em; font-size: .8em;
color: #999; color: #999;
width: 1px; width: 1px;
} }
.item-card .lots-grid .cell-text .item-card .lots-grid .cell-text {
{
max-width: initial; max-width: initial;
width: auto; width: auto;
} }
.item-card .lots-grid .cell-button .item-card .lots-grid .cell-button {
{
max-width: initial; max-width: initial;
width: 1em; width: 1em;
} }
.item-card .footer .item-card .footer {
{ display: flex;
text-align: center; align-items: center;
background-color: #009688; justify-content: space-between;
background-color: #1a1a1a;
color: white; color: white;
line-height: 2em; padding: 10px;
padding: .4em;
} }
.item-card .footer > button .item-card .footer > button:hover {
{ background-color: rgba(255, 255, 255, .1);
margin: 0;
} }
.item-card .erase .item-card .footer > button > .htk-icon {
{
float: left;
}
.item-card .confirm
{
float: right;
}
.item-card .erase > img,
.item-card .confirm > img
{
display: block; display: block;
height: 1em;
} }
/* Mobile */ /* Mobile */
.catalog-actions > button.menu .catalog-actions > button.menu {
{
display: none; display: none;
padding: 1.1em .5em;
} }
.catalog-actions > button.menu > img .catalog-actions > button.menu > .htk-icon {
{ display: block;
height: 1.8em;
} }
@media (max-width: 960px) @media (max-width: 960px) {
{
.catalog-actions > button.menu .catalog-actions > button.menu
{ {
display: block; display: block;
@ -489,15 +378,15 @@
.right-panel .right-panel
{ {
top: 0; top: 0;
right: -17em; right: -18em;
z-index: 20; z-index: 20;
transition: transform 200ms ease-out; transition: transform 200ms ease-out;
-webkit-transition: transform 200ms ease-out; -webkit-transition: transform 200ms ease-out;
} }
.right-panel.show .right-panel.show
{ {
transform: translateZ(0) translateX(-17em); transform: translateZ(0) translateX(-18em);
-webkit-transform: translateZ(0) translateX(-17em); -webkit-transform: translateZ(0) translateX(-18em);
} }
.catalog .catalog
{ {

View File

@ -1,46 +1,93 @@
<vn> <vn>
<div id="title">
<h1 id="title-text"><t>Catalog</t></h1>
<div id="subtitle"></div>
</div>
<div id="actions" class="catalog-actions">
<htk-search-entry form="params" column="search"/>
<htk-bar-button
id="view-button"
tip="_Switch view"
icon="view_list"
on-click="this.onSwitchViewClick()"/>
<htk-bar-button
icon="shopping_cart_checkout"
tip="_ShoppingBasket"
on-click="this.onBasketClick()"/>
<button
class="menu"
on-click="onShowMenuClick">
<htk-icon name="menu" alt="_Menu"/>
</button>
</div>
<vn-group> <vn-group>
<vn-param id="card-item"/> <vn-lot-query id="params" on-change="this.onFilterChange()">
<vn-param id="realm" on-changed="onRealmChange"/> <vn-spec name="search" type="String"/>
<vn-param id="type" on-changed="onTypeChange"/> <vn-spec name="realm" type="Number"/>
<vn-param id="search" on-changed="onFilterChange"/> <vn-spec name="type" type="Number"/>
<vn-param id="color" on-changed="onFilterChange"/> </vn-lot-query>
<vn-param id="origin" on-changed="onFilterChange"/> <vn-lot id="filter-lot"/>
<vn-param id="category" on-changed="onFilterChange"/> </vn-group>
<vn-param id="producer" on-changed="onFilterChange"/> <vn-group>
<vn-hash-param key="realm" param="realm"/> <sql-filter-item
<vn-hash-param key="type" param="type"/> id="id-op"
<sql-filter type="AND" id="filter"> type="EQUAL"
<sql-filter-item type="EQUAL" primary="false" id="op-realm"> target="i"
<sql-field target="t" name="categoryFk"/> field="id"
<sql-value id="realm-value"/> param="search"/>
</sql-filter-item> <sql-operation
<sql-filter-item type="EQUAL" id="op-type"> id="search-op"
<sql-field target="i" name="typeFk"/> type="OR">
<sql-value id="type-value"/> <sql-filter-item
</sql-filter-item> type="LIKE"
<sql-filter-item type="LIKE" id="op-name"> target="i"
<sql-field target="i" name="longName"/> field="longName"
<sql-search-tags param="search"/> param="search"/>
</sql-filter-item> <sql-filter-item
<sql-filter-item type="EQUAL" id="op-color"> type="LIKE"
<sql-field target="i" name="inkFk"/> target="i"
<sql-value param="color"/> field="subname"
</sql-filter-item> param="search"/>
<sql-filter-item type="EQUAL" id="op-origin"> </sql-operation>
<sql-field target="i" name="originFk"/> <sql-filter-item
<sql-value param="origin"/> id="realm-op"
</sql-filter-item> type="EQUAL"
<sql-filter-item type="EQUAL" id="op-category"> target="t"
<sql-field target="i" name="category"/> field="categoryFk"
<sql-value param="category"/> param="realm"/>
</sql-filter-item> <sql-filter-item
<sql-filter-item type="EQUAL" id="op-producer"> id="type-op"
<sql-field target="i" name="producerFk"/> type="EQUAL"
<sql-value param="producer"/> target="i"
</sql-filter-item> field="typeFk"
</sql-filter> param="type"/>
<db-form id="basket" on-ready="onBasketReady"> <sql-filter-item
id="color-op"
type="EQUAL"
target="i"
field="inkFk"
param="color"/>
<sql-filter-item
type="EQUAL"
id="origin-op"
target="i"
field="originFk"
param="origin"/>
<sql-filter-item
type="EQUAL"
id="category-op"
target="i"
field="category"
param="category"/>
<sql-filter-item
id="producer-op"
type="EQUAL"
target="i"
field="producerFk"
param="producer"/>
</vn-group>
<vn-group>
<db-form v-model="basket">
<db-model property="model"> <db-model property="model">
SELECT b.id, b.sent, a.description agency, m.code method SELECT b.id, b.sent, a.description agency, m.code method
FROM myBasket b FROM myBasket b
@ -49,7 +96,8 @@
</db-model> </db-model>
</db-form> </db-form>
<db-model <db-model
id="items-model" id="items"
auto-load="false"
result-index="3" result-index="3"
on-status-changed="onItemsChange"> on-status-changed="onItemsChange">
DROP TEMPORARY TABLE IF EXISTS tmp.item; DROP TEMPORARY TABLE IF EXISTS tmp.item;
@ -61,7 +109,7 @@
JOIN vn.itemType t ON t.id = i.typeFk JOIN vn.itemType t ON t.id = i.typeFk
WHERE #filter; WHERE #filter;
CALL myBasket_calcCatalogFull; CALL myBasket_calcCatalogFull;
SELECT i.id, i.description, i.longName item, i.subName, SELECT i.id, i.longName item, i.subName,
i.tag5, i.value5, i.tag6, i.value6, i.tag7, i.value7, i.tag5, i.value5, i.tag6, i.value6, i.tag7, i.value7,
i.relevancy, i.size, i.category, i.relevancy, i.size, i.category,
k.name ink, p.name producer, o.name origin, k.name ink, p.name producer, o.name origin,
@ -85,87 +133,64 @@
tmp.ticketComponent, tmp.ticketComponent,
tmp.ticketLot, tmp.ticketLot,
tmp.zoneGetShipped; tmp.zoneGetShipped;
<sql-batch property="batch" id="filter-batch">
<custom>
<item name="filter" object="filter"/>
</custom>
</sql-batch>
</db-model> </db-model>
<db-form id="card" model="items-model"/> <db-form id="$card" v-model="card" model="items"/>
<sql-batch id="card-batch"> <vn-lot id="card-lot"/>
<custom>
<item name="item" param="card-item"/>
</custom>
</sql-batch>
</vn-group> </vn-group>
<div id="title">
<h1 id="title-text"><t>Catalog</t></h1>
</div>
<div id="actions" class="catalog-actions">
<button class="menu" on-click="onShowMenuClick">
<img src="image/icon/dark/menu.svg" alt="_Menu"/>
</button>
<htk-bar-button
icon="basket"
tip="_ShoppingBasket"
on-click="onBasketClick"/>
<htk-bar-button
id="view-button"
tip="_Switch view"
on-click="onSwitchViewClick"/>
<htk-search-entry
param="search"/>
</div>
<div id="form" class="catalog"> <div id="form" class="catalog">
<div id="main" class="main"> <div id="main" class="main">
<htk-repeater <htk-repeater
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" model="items">
renderer="repeaterFunc">
<custom> <custom>
<div <div
id="item-box" id="item-box"
class="box item-box" class="item-box clickable"
title="_AddToBasket"> title="{{_('AddToBasket')}}"
on-click="this.onAddItemClick($event, $iter)">
<htk-image <htk-image
directory="catalog" directory="catalog"
subdir="200x200" subdir="200x200"
form="item" form="$iter"
column="image" column="image"
stamp-column="updated" stamp-column="updated"
full-dir="1600x900"/> full-dir="1600x900"
title="_Zoom image"/>
<div class="item-info"> <div class="item-info">
<h2> <h2>
<htk-text form="item" column="item"/> <span class="item-id">
#{{item.id}}
</span>
{{item.item}}
</h2> </h2>
<p class="sub-name"> <p class="sub-name">
<htk-text form="item" column="subName"/> {{item.subName}}
</p> </p>
<table class="tags"> <table class="tags">
<tr> <tr>
<td><htk-text form="item" column="tag5"/></td> <td>{{item.tag5}}</td>
<td><htk-text form="item" column="value5"/></td> <td>{{item.value5}}</td>
</tr> </tr>
<tr> <tr>
<td><htk-text form="item" column="tag6"/></td> <td>{{item.tag6}}</td>
<td><htk-text form="item" column="value6"/></td> <td>{{item.value6}}</td>
</tr> </tr>
<tr> <tr>
<td><htk-text form="item" column="tag7"/></td> <td>{{item.tag7}}</td>
<td><htk-text form="item" column="value7"/></td> <td>{{item.value7}}</td>
</tr> </tr>
</table> </table>
<div class="available-price"> <div class="available-price">
<span class="grouping" title="_MinimalGrouping"> <span class="grouping" title="_MinimalGrouping">
<htk-text form="item" column="grouping" format="x%.0d"/> {{Vn.Value.format(item.grouping, 'x%.0d')}}
</span> </span>
<span class="available" title="_Available"> <span class="available" title="_Available">
<htk-text form="item" column="available"/> {{item.available}}
</span> </span>
<span class="price" title="_GroupingPrice"> <span class="price" title="_GroupingPrice">
<htk-text form="item" column="price" format="%.2d€"/> {{Vn.Value.format(item.price, '%.02d€')}}
</span> </span>
</div> </div>
</div> </div>
@ -176,29 +201,26 @@
</div> </div>
<div id="right-panel" class="right-panel" on-click="onRightPanelClick"> <div id="right-panel" class="right-panel" on-click="onRightPanelClick">
<div class="basket-info"> <div class="basket-info">
<p>{{Vn.Value.format(basket.sent, '%D')}}</p>
<p> <p>
<htk-text form="basket" column="sent" format="%D"/> {{_(basket.method != 'PICKUP' ? 'Agency' : 'Warehouse')}}
{{basket.agency}}
</p> </p>
<p> <button class="thin" on-click="this.onConfigureClick()">
<span id="method"/> <t>Modify</t>
<htk-text form="basket" column="agency"/>
</p>
<button class="thin" on-click="onConfigureClick">
<t>Change</t>
</button> </button>
</div> </div>
<div class="filter"> <div class="filter">
<div class="categories"> <div class="categories">
<div class="realms"> <div class="realms">
<htk-repeater <htk-repeater
model="realms-model" form-id="form"
form-id="realm-form"
renderer="realmRenderer" renderer="realmRenderer"
class="realms-box"> class="realms-box">
<db-model <db-model
id="realms-model" id="realms"
property="model" property="model"
on-status-changed="refreshTitleColor"> on-status-changed="refreshTitle">
SELECT c.id, l.name, c.color, c.code SELECT c.id, l.name, c.color, c.code
FROM vn.itemCategory c FROM vn.itemCategory c
JOIN vn.itemCategoryL10n l ON l.id = c.id JOIN vn.itemCategoryL10n l ON l.id = c.id
@ -207,7 +229,11 @@
</db-model> </db-model>
<custom> <custom>
<a id="link"> <a id="link">
<img id="image"/> <img
id="image"
src="{{`image/family/black/${form.code}.svg`}}"
title="{{form.name}}"
alt="{{form.name}}"/>
</a> </a>
</custom> </custom>
</htk-repeater> </htk-repeater>
@ -215,17 +241,20 @@
</div> </div>
</div> </div>
<div id="realm-msg" class="realm-msg"> <div id="realm-msg" class="realm-msg">
<h1><t>Choose a realm</t></h1> <h5><t>Choose a realm</t></h5>
</div> </div>
<div id="filters" class="filters"> <div id="filters" class="filters">
<h2><t>Filter by</t></h2> <h2><t>Filter by</t></h2>
<vn-filter <htk-combo
placeholder="_Family" placeholder="_Family"
param="type"> form="params"
column="type"
id="type-filter">
<db-model <db-model
id="types-model" id="types"
property="model" property="model"
conn="conn" conn="conn"
lot="params"
result-index="1" result-index="1"
on-status-changed="refreshTitle"> on-status-changed="refreshTitle">
CALL myBasket_getAvailable; CALL myBasket_getAvailable;
@ -234,21 +263,22 @@
JOIN vn.itemType t ON t.id = i.typeFk JOIN vn.itemType t ON t.id = i.typeFk
JOIN tmp.itemAvailable a ON a.id = i.id JOIN tmp.itemAvailable a ON a.id = i.id
JOIN vn.itemTypeL10n l ON l.id = t.id JOIN vn.itemTypeL10n l ON l.id = t.id
WHERE t.`order` >= 0 AND #filter WHERE t.`order` >= 0
AND t.categoryFk = #realm
ORDER BY t.`order`, l.name; ORDER BY t.`order`, l.name;
DROP TEMPORARY TABLE tmp.itemAvailable; DROP TEMPORARY TABLE tmp.itemAvailable;
</db-model> </db-model>
<sql-filter property="filter" type="AND"> </htk-combo>
<sql-filter-item type="EQUAL"> <htk-combo
<sql-field name="categoryFk" target="t"/>
<sql-value param="realm"/>
</sql-filter-item>
</sql-filter>
</vn-filter>
<vn-filter
placeholder="_Color" placeholder="_Color"
param="color"> form="params"
<db-model property="model" auto-load="false" result-index="1"> column="color"
on-mousedown="colors.lazyRefresh()">
<db-model
id="colors"
property="model"
auto-load="false"
result-index="1">
CALL myBasket_getAvailable; CALL myBasket_getAvailable;
SELECT DISTINCT l.id, l.name SELECT DISTINCT l.id, l.name
FROM vn.item i FROM vn.item i
@ -259,19 +289,17 @@
ORDER BY name; ORDER BY name;
DROP TEMPORARY TABLE tmp.itemAvailable; DROP TEMPORARY TABLE tmp.itemAvailable;
</db-model> </db-model>
<sql-filter property="filter" always-ready="true" type="AND"> </htk-combo>
<pointer object="op-realm"/> <htk-combo
<pointer object="op-type"/>
<pointer object="op-name"/>
<pointer object="op-origin"/>
<pointer object="op-category"/>
<pointer object="op-producer"/>
</sql-filter>
</vn-filter>
<vn-filter
placeholder="_Producer" placeholder="_Producer"
param="producer"> form="params"
<db-model property="model" auto-load="false" result-index="1"> column="producer"
on-mousedown="producers.lazyRefresh()">
<db-model
id="producers"
property="model"
auto-load="false"
result-index="1">
CALL myBasket_getAvailable; CALL myBasket_getAvailable;
SELECT DISTINCT p.id, p.name SELECT DISTINCT p.id, p.name
FROM vn.item i FROM vn.item i
@ -282,19 +310,17 @@
ORDER BY name; ORDER BY name;
DROP TEMPORARY TABLE tmp.itemAvailable; DROP TEMPORARY TABLE tmp.itemAvailable;
</db-model> </db-model>
<sql-filter property="filter" always-ready="true" type="AND"> </htk-combo>
<pointer object="op-realm"/> <htk-combo
<pointer object="op-type"/>
<pointer object="op-name"/>
<pointer object="op-origin"/>
<pointer object="op-color"/>
<pointer object="op-category"/>
</sql-filter>
</vn-filter>
<vn-filter
placeholder="_Origin" placeholder="_Origin"
param="origin"> form="params"
<db-model property="model" auto-load="false" result-index="1"> column="origin"
on-mousedown="origins.lazyRefresh()">
<db-model
id="origins"
property="model"
auto-load="false"
result-index="1">
CALL myBasket_getAvailable; CALL myBasket_getAvailable;
SELECT DISTINCT o.id, l.name, o.code SELECT DISTINCT o.id, l.name, o.code
FROM vn.item i FROM vn.item i
@ -306,19 +332,17 @@
ORDER BY name; ORDER BY name;
DROP TEMPORARY TABLE tmp.itemAvailable; DROP TEMPORARY TABLE tmp.itemAvailable;
</db-model> </db-model>
<sql-filter property="filter" always-ready="true" type="AND"> </htk-combo>
<pointer object="op-realm"/> <htk-combo
<pointer object="op-type"/>
<pointer object="op-name"/>
<pointer object="op-color"/>
<pointer object="op-category"/>
<pointer object="op-producer"/>
</sql-filter>
</vn-filter>
<vn-filter
placeholder="_Category" placeholder="_Category"
param="category"> form="params"
<db-model property="model" auto-load="false" result-index="1"> column="category"
on-mousedown="categorys.lazyRefresh()">
<db-model
id="categorys"
property="model"
auto-load="false"
result-index="1">
CALL myBasket_getAvailable; CALL myBasket_getAvailable;
SELECT DISTINCT i.category, i.category SELECT DISTINCT i.category, i.category
FROM vn.item i FROM vn.item i
@ -328,15 +352,7 @@
ORDER BY category; ORDER BY category;
DROP TEMPORARY TABLE tmp.itemAvailable; DROP TEMPORARY TABLE tmp.itemAvailable;
</db-model> </db-model>
<sql-filter property="filter" always-ready="true" type="AND"> </htk-combo>
<pointer object="op-realm"/>
<pointer object="op-type"/>
<pointer object="op-name"/>
<pointer object="op-color"/>
<pointer object="op-origin"/>
<pointer object="op-producer"/>
</sql-filter>
</vn-filter>
</div> </div>
<div id="order" class="order"> <div id="order" class="order">
<h2><t>Order by</t></h2> <h2><t>Order by</t></h2>
@ -390,10 +406,10 @@
modal="true" modal="true"
on-closed="onPopupClose"> on-closed="onPopupClose">
<div property="child-node" class="item-card"> <div property="child-node" class="item-card">
<db-form id="card-extend"> <db-form vModel="extendedCard">
<db-model <db-model
property="model" property="model"
batch="card-batch" lot="card-lot"
on-status-changed-after="onCardLoad"> on-status-changed-after="onCardLoad">
SELECT i.description, o.name origin SELECT i.description, o.name origin
FROM vn.item i FROM vn.item i
@ -405,33 +421,23 @@
<htk-image <htk-image
directory="catalog" directory="catalog"
subdir="200x200" subdir="200x200"
form="card" form="$card"
column="image" column="image"
stamp-column="updated" stamp-column="updated"
full-dir="1600x900" full-dir="1600x900"
conn="conn" conn="conn"
editable="true"/> editable="true"/>
<div class="item-info"> <div class="item-info">
<h2> <h2>{{card.item}}</h2>
<htk-text form="card" column="item"/> <p class="sub-name">{{card.subname}}</p>
</h2> <p>#{{card.id}}</p>
<p class="sub-name"> <p>{{Vn.Value.format(card.stems, _('%.0d Units'))}}</p>
<htk-text form="card" column="subName"/>
</p>
<p>
#<htk-text form="card" column="id"/>
</p>
<p>
<htk-text form="card" column="stems" format="_%.0d Units"/>
</p>
</div> </div>
<p class="desc"> <p class="desc">{{extendedCard.description}}</p>
<htk-text form="card-extend" column="description" id="desc"/>
</p>
<htk-repeater show-status="false" form-id="tag" class="tags"> <htk-repeater show-status="false" form-id="tag" class="tags">
<db-model <db-model
property="model" property="model"
batch="card-batch" lot="card-lot"
on-status-changed-after="onCardLoad"> on-status-changed-after="onCardLoad">
SELECT l.name, it.value SELECT l.name, it.value
FROM vn.itemTag it FROM vn.itemTag it
@ -443,8 +449,8 @@
</db-model> </db-model>
<custom> <custom>
<tr> <tr>
<td><htk-text form="tag" column="name"/></td> <td>{{tag.name}}</td>
<td><htk-text form="tag" column="value"/></td> <td>{{tag.value}}</td>
</tr> </tr>
</custom> </custom>
</htk-repeater> </htk-repeater>
@ -455,7 +461,7 @@
property="model" property="model"
result-index="1" result-index="1"
on-status-changed-after="onCardLoad" on-status-changed-after="onCardLoad"
batch="card-batch"> lot="card-lot">
CALL myBasket_calcCatalogFromItem(#item); CALL myBasket_calcCatalogFromItem(#item);
SELECT l.warehouseFk, w.name warehouse, p.`grouping`, SELECT l.warehouseFk, w.name warehouse, p.`grouping`,
p.price, p.priceKg, p.rate, l.available p.price, p.priceKg, p.rate, l.available
@ -480,20 +486,25 @@
on-clicked="onAddLotClick"/> on-clicked="onAddLotClick"/>
</htk-grid> </htk-grid>
<div class="footer"> <div class="footer">
<button on-click="onEraseClick" title="_Erase" class="erase"> <button
title="_Erase"
on-click="this.onEraseClick()"
class="erase">
<htk-icon <htk-icon
icon="delete" name="delete"
theme="dark" theme="dark"
alt="_Erase"/> alt="_Erase"/>
</button> </button>
<htk-text id="amount"/> <htk-text id="amount"/>
<button on-click="onConfirmClick" title="_Confirm" class="confirm"> <button
title="_Confirm"
on-click="this.onConfirmClick()"
class="confirm">
<htk-icon <htk-icon
icon="ok" name="done"
theme="dark" theme="dark"
alt="_Confirm"/> alt="_Confirm"/>
</button> </button>
<div class="clear"/>
</div> </div>
</div> </div>
</htk-popup> </htk-popup>

View File

@ -4,32 +4,27 @@ Hedera.Checkout = new Class({
activate: function() { activate: function() {
this.autoStepLocked = true; this.autoStepLocked = true;
this.$('assistant').stepsIndex = this.agencySteps; this.$.assistant.stepsIndex = this.agencySteps;
this.today = new Date(); this.today = new Date();
this.today.setHours(0, 0, 0, 0); this.today.setHours(0, 0, 0, 0);
}, },
onValuesReady: function() { onValuesReady: function() {
var orderForm = this.$('order-form'); const orderForm = this.$.orderForm;
var defaultsForm = this.$('defaults'); const defaultsForm = this.$.defaults;
if (!(orderForm.ready && defaultsForm.ready)) if (!(orderForm.ready && defaultsForm.ready))
return; return;
var date; let date;
const row = orderForm.$ || defaultsForm.$ || {};
if (orderForm.numRows > 0) {
var i = orderForm;
date = i.get('sent');
} else
var i = defaultsForm;
if (!date || date.getTime() < (new Date()).getTime()) { if (!date || date.getTime() < (new Date()).getTime()) {
date = new Date(); date = new Date();
date.setHours(0, 0, 0, 0); date.setHours(0, 0, 0, 0);
var addDays = 0; let addDays = 0;
switch(date.getDay()) { switch(date.getDay()) {
case 6: // Saturday case 6: // Saturday
@ -40,37 +35,31 @@ Hedera.Checkout = new Class({
break; break;
} }
if (i.get('deliveryMethod') != 'PICKUP') if (row.deliveryMethod != 'PICKUP')
addDays++; addDays++;
date.setDate(date.getDate() + addDays); date.setDate(date.getDate() + addDays);
} }
this.$('date').value = date;
this.$('method').value = i.get('deliveryMethod');
this.$('agency').value = i.get('agencyModeFk');
this.$('address').value = i.get('addressFk');
this.$.lot.assign({
date: date,
method: row.deliveryMethod,
agency: row.agencyModeFk,
address: row.addressFk
});
this.autoStepLocked = false; this.autoStepLocked = false;
}, },
disableButtons: function(disable) { disableButtons: function(disable) {
this.$('assistant-bar').disabled = disable; this.$.assistantBar.disabled = disable;
}, },
onConfirmClick: function() { onConfirmClick: function() {
this.disableButtons(true); this.disableButtons(true);
var query = 'CALL myBasket_configure(#date, #method, #agency, #address)'; const query = 'CALL myBasket_configure(#date, #method, #agency, #address)';
var batch = new Sql.Batch();
batch.addParam('method', this.$('method'));
batch.addParam('date', this.$('date'));
batch.addParam('agency', this.$('agency'));
batch.addParam('address', this.$('address'));
this.conn.execQuery(query, this.conn.execQuery(query,
this.onBasketConfigured.bind(this), batch); this.onBasketConfigured.bind(this), this.$.lot.$);
}, },
onBasketConfigured: function(resultSet) { onBasketConfigured: function(resultSet) {
@ -79,96 +68,91 @@ Hedera.Checkout = new Class({
if (!resultSet.fetchResult()) if (!resultSet.fetchResult())
return; return;
if (this.$('order-form').numRows > 0) if (this.$.orderForm.numRows > 0)
Htk.Toast.showMessage(_('OrderUpdated')); Htk.Toast.showMessage(_('OrderUpdated'));
else else
Htk.Toast.showMessage(_('OrderStarted')); Htk.Toast.showMessage(_('OrderStarted'));
this.hash.set({form: 'ecomerce/catalog'}); this.hash.setAll({form: 'ecomerce/catalog'});
}, },
onCancelClick: function() { onCancelClick: function() {
if (this.$('order-form').numRows > 0) if (this.$.orderForm.numRows > 0)
window.history.back(); window.history.back();
else else
this.hash.set({form: 'ecomerce/orders'}); this.hash.setAll({form: 'ecomerce/orders'});
}, },
agencySteps: ['method', 'date', 'address', 'agency', 'confirm-delivery'], agencySteps: ['method', 'date', 'address', 'agency', 'confirm-delivery'],
pickupSteps: ['method', 'date', 'address', 'pickup', 'confirm-pickup'], pickupSteps: ['method', 'date', 'address', 'pickup', 'confirm-pickup'],
isDelivery: function() { isDelivery: function() {
return this.$('rg-method').value != 'PICKUP'; return this.$.rgMethod.value != 'PICKUP';
}, },
onMethodChange: function() { onMethodChange: function() {
this.$('assistant').stepsIndex = this.isDelivery() ? this.$.assistant.stepsIndex = this.isDelivery() ?
this.agencySteps : this.pickupSteps; this.agencySteps : this.pickupSteps;
this.onFieldChange(); this.onFieldChange();
}, },
methodValidate: function() { methodValidate: function() {
if (!this.$('rg-method').isSelected()) if (!this.$.rgMethod.isSelected())
throw new Error(_('Please select an option')); throw new Error(_('Please select an option'));
}, },
dateShow: function() { dateShow: function() {
Vn.Node.setText(this.$('date-question'), this.isDelivery() ? Vn.Node.setText(this.$.dateQuestion, this.isDelivery() ?
_('OrderDateDeliveryQuestion'): _('OrderDateDeliveryQuestion'):
_('OrderDatePickupQuestion')); _('OrderDatePickupQuestion'));
this.$('calendar').goToSelectedMonth(); this.$.calendar.goToSelectedMonth();
}, },
dateValidate: function() { dateValidate: function() {
if (!this.$('calendar').value) if (!this.$.calendar.value)
throw new Error(_('Please select a date')); throw new Error(_('Please select a date'));
}, },
addressShow: function() { addressShow: function() {
Vn.Node.setText(this.$('address-question'), this.isDelivery() ? Vn.Node.setText(this.$.addressQuestion, this.isDelivery() ?
_('AddressQuestion'): _('AddressQuestion'):
_('AddressQuestionPickup')); _('AddressQuestionPickup'));
}, },
addressValidate: function() { addressValidate: function() {
if (this.$('address-form').row == -1) if (this.$.addressForm.row == -1)
throw new Error(_('Please select an address')); throw new Error(_('Please select an address'));
}, },
agencyShow: function() { agencyShow: function() {
this.$('agencies').refresh(); this.$.agencies.refresh();
}, },
agencyValidate: function() { agencyValidate: function() {
if (this.$('agency-combo').row == -1 && this.isDelivery()) if (this.$.agencyCombo.row == -1 && this.isDelivery())
throw new Error(_('Please select an agency')); throw new Error(_('Please select an agency'));
}, },
pickupShow: function() { pickupShow: function() {
this.$('warehouses').refresh(); this.$.warehouses.refresh();
}, },
pickupValidate: function() { pickupValidate: function() {
if (this.$('warehouse-combo').row == -1) if (this.$.warehouseCombo.row == -1)
throw new Error(_('Please select a store')); throw new Error(_('Please select a store'));
}, },
onFieldChange: function() { onFieldChange: function() {
if (!this.autoStepLocked) if (!this.autoStepLocked)
this.$('assistant').moveNext(); this.$.assistant.moveNext();
}, },
goNextStep: function() { goNextStep: function() {
this.$('assistant').moveNext(); this.$.assistant.moveNext();
},
addressRenderer: function(builder, form) {
builder.$('address').addEventListener('click',
this.onAddressClick.bind(this, form.get('id')));
}, },
onAddressClick: function(addressId) { onAddressClick: function(addressId) {
this.$('address').value = addressId; this.$.lot.set('address', addressId);
this.goNextStep(); this.goNextStep();
}, },
@ -176,37 +160,43 @@ Hedera.Checkout = new Class({
if (this.selectedNode) if (this.selectedNode)
Vn.Node.removeClass(this.selectedNode, 'selected'); Vn.Node.removeClass(this.selectedNode, 'selected');
var row = this.$('addresses').search('id', this.$('address').value); const row = this.$.addresses.search('id', this.$.lot.$.address);
if (row != -1) { if (row != -1) {
var builder = this.$('repeater').getBuilder(row); const builder = this.$.repeater.getBuilder(row);
this.selectedNode = builder.$('address'); this.selectedNode = builder.$.address;
Vn.Node.addClass(this.selectedNode, 'selected'); Vn.Node.addClass(this.selectedNode, 'selected');
} }
this.$('address-form').row = row; this.$.addressForm.row = row;
}, },
onAgenciesReady: function(model) { onAgenciesReady: function(model) {
if (!model.ready) return; if (!model.ready) return;
if (model.numRows > 0) { if (model.numRows > 0) {
var agency; let agency;
var defaults = [ const agencies = [];
this.$('order-form').get('agencyModeFk'),
this.$('defaults').get('agencyModeFk'),
this.$('defaults').get('defaultAgencyFk')
];
for (var i = 0; i < defaults.length; i++) { if (this.$.orderForm.$)
agency = defaults[i]; agencies.push(this.$.orderForm.$);
const defaults = this.$.defaults.$;
if (defaults)
agencies.push(
defaults.agencyModeFk,
defaults.defaultAgencyFk
);
for (let i = 0; i < agencies.length; i++) {
agency = agencies[i];
if (model.search('id', agency) !== -1) if (model.search('id', agency) !== -1)
break; break;
} }
this.autoStepLocked = true; this.autoStepLocked = true;
this.$('agency').value = agency; this.$.lot.assign({agency});
this.autoStepLocked = false; this.autoStepLocked = false;
} else } else
Htk.Toast.showError(_('NoAgeciesAvailableForDate')); Htk.Toast.showError(_('NoAgeciesAvailableForDate'));

View File

@ -11,7 +11,7 @@ AddressQuestion: On vols rebre la comanda?
AddressQuestionPickup: A què direcció vols associar la comanda? (Opcional) AddressQuestionPickup: A què direcció vols associar la comanda? (Opcional)
AgencyQuestion: Com vols rebre la comanda? AgencyQuestion: Com vols rebre la comanda?
PickupWarehouseQuestion: En quin magatzem vols recollir la comanda? PickupWarehouseQuestion: En quin magatzem vols recollir la comanda?
ConfirmToAccessCatalog: Confirma les dades per accedir al catàleg ConfirmData: Confirma les dades
Arrival: Arribada Arrival: Arribada
Pickup: Recollida Pickup: Recollida
Agency: Agència Agency: Agència

View File

@ -11,7 +11,7 @@ AddressQuestion: Where do you want to receive the order?
AddressQuestionPickup: To which address do you want to associate the order? (Optional) AddressQuestionPickup: To which address do you want to associate the order? (Optional)
AgencyQuestion: How you want to receive the order? AgencyQuestion: How you want to receive the order?
PickupWarehouseQuestion: What store you want to pickup your order? PickupWarehouseQuestion: What store you want to pickup your order?
ConfirmToAccessCatalog: Confirm the data to access the catalog ConfirmData: Confirm the data
Arrival: Arrival Arrival: Arrival
Pickup: Pickup Pickup: Pickup
Agency: Agency Agency: Agency

View File

@ -11,7 +11,7 @@ AddressQuestion: ¿Dónde quieres recibir el pedido?
AddressQuestionPickup: ¿A qué dirección quieres asociar el pedido? (Opcional) AddressQuestionPickup: ¿A qué dirección quieres asociar el pedido? (Opcional)
AgencyQuestion: ¿Cómo quieres recibir el pedido? AgencyQuestion: ¿Cómo quieres recibir el pedido?
PickupWarehouseQuestion: ¿En qué almacén quieres recoger el pedido? PickupWarehouseQuestion: ¿En qué almacén quieres recoger el pedido?
ConfirmToAccessCatalog: Confirma los datos para acceder al catálogo ConfirmData: Confirma los datos
Arrival: Llegada Arrival: Llegada
Pickup: Recogida Pickup: Recogida
Agency: Agencia Agency: Agencia

View File

@ -11,7 +11,7 @@ AddressQuestion: Adresse livraison?
AddressQuestionPickup: À quelle adresse voulez-vous associer la commande? (Optionnel) AddressQuestionPickup: À quelle adresse voulez-vous associer la commande? (Optionnel)
AgencyQuestion: Agence de livraison AgencyQuestion: Agence de livraison
PickupWarehouseQuestion: Dans quel magasin vuoulez-vous retirer votre commande? PickupWarehouseQuestion: Dans quel magasin vuoulez-vous retirer votre commande?
ConfirmToAccessCatalog: Confirmez les coordonnées pour accéder au catalogue ConfirmData: Confirmez les coordonnées
Arrival: Arrivée Arrival: Arrivée
Pickup: Retrait Pickup: Retrait
Agency: Agence Agency: Agence

View File

@ -11,7 +11,7 @@ AddressQuestion: Onde queres receber a encomenda?
AddressQuestionPickup: Para qual endereço deseja associar o pedido? (Opcional) AddressQuestionPickup: Para qual endereço deseja associar o pedido? (Opcional)
AgencyQuestion: Como queres receber a encomenda? AgencyQuestion: Como queres receber a encomenda?
PickupWarehouseQuestion: Em qual armazém queres levantar a encomenda? PickupWarehouseQuestion: Em qual armazém queres levantar a encomenda?
ConfirmToAccessCatalog: Confirme os dados para entrar no catálogo ConfirmData: Confirme os dados
Arrival: Chegada Arrival: Chegada
Pickup: Recolhida Pickup: Recolhida
Agency: Agência Agency: Agência

View File

@ -1,89 +1,54 @@
.checkout
{ .checkout .bar {
padding: 1em; margin-bottom: 16px;
max-width: 40em;
margin: 0 auto;
}
.checkout .bar
{
margin-bottom: 1em;
}
.checkout .form
{
max-width: 40em;
padding: 4em 2em;
} }
/* Step */ /* Step */
.answers button, .answers button,
.answers p, .answers p,
.radio > div .radio > div {
{ font-size: 1.2em;
}
.answers .htk-select {
max-width: 15em;
margin: 0 auto;
font-size: 1.4em; font-size: 1.4em;
} }
.answers .htk-select .answers p {
{
max-width: 10em;
display: block;
margin: 0 auto;
font-size: 1.6em;
height: 1.8em;
}
.answers p
{
margin: 0.3em 0; margin: 0.3em 0;
} }
.target .target {
{
max-width: 28em; max-width: 28em;
margin: 0 auto; margin: 0 auto;
} }
.address .address {
{
border-radius: 0.1em; border-radius: 0.1em;
padding: 0.6em 1.4em; padding: 0.6em 1.4em;
} }
.address.selected .address.selected {
{
background-color: rgba(1, 1, 1, .1); background-color: rgba(1, 1, 1, .1);
} }
.address:hover .address:hover {
{
cursor: pointer; cursor: pointer;
background-color: rgba(1, 1, 1, .05); background-color: rgba(1, 1, 1, .05);
} }
.address p.consignee .address p.consignee {
{
font-weight: bold; font-weight: bold;
} }
.radio .radio {
{
max-width: 20em; max-width: 20em;
margin: 0 auto; margin: 0 auto;
} }
.radio > div .radio > div {
{
padding: 0.5em; padding: 0.5em;
border-top: 1px solid #AAA;
} }
.radio > div:first-child .thin-calendar {
{
border-top: none;
}
.thin-calendar
{
width: inherit;
max-width: 24em; max-width: 24em;
margin: 0 auto; margin: 0 auto;
box-shadow: 0 0.1em 0.3em #ccc; box-shadow: none;
} }
.thin-calendar tr > th .htk-assistant .thin {
{
color: white;
}
.htk-assistant .thin
{
float: right; float: right;
} }

View File

@ -1,9 +1,6 @@
<vn> <vn>
<vn-group> <vn-group>
<vn-param id="method"/> <vn-lot id="lot" on-change="this.onAddressChange()"/>
<vn-param id="date"/>
<vn-param id="agency"/>
<vn-param id="address" on-changed="onAddressChange"/>
<db-form id="defaults" on-ready="onValuesReady"> <db-form id="defaults" on-ready="onValuesReady">
<db-model property="model"> <db-model property="model">
SELECT deliveryMethod, agencyModeFk, addressFk, defaultAgencyFk SELECT deliveryMethod, agencyModeFk, addressFk, defaultAgencyFk
@ -19,6 +16,7 @@
</db-form> </db-form>
<db-model id="agencies" <db-model id="agencies"
auto-load="false" auto-load="false"
lot="lot"
result-index="1" result-index="1"
on-status-changed="onAgenciesReady"> on-status-changed="onAgenciesReady">
CALL vn.zone_getAgency(#address, #date); CALL vn.zone_getAgency(#address, #date);
@ -30,15 +28,10 @@
AND a.isVisible AND a.isVisible
ORDER BY a.description; ORDER BY a.description;
DROP TEMPORARY TABLE tmp.zoneGetAgency; DROP TEMPORARY TABLE tmp.zoneGetAgency;
<sql-batch property="batch">
<custom>
<item name="address" param="address"/>
<item name="date" param="date"/>
</custom>
</sql-batch>
</db-model> </db-model>
<db-model id="warehouses" <db-model id="warehouses"
auto-load="false" auto-load="false"
lot="lot"
result-index="1" result-index="1"
on-status-changed="onWarehousesReady"> on-status-changed="onWarehousesReady">
CALL vn.zone_getAgency(#address, #date); CALL vn.zone_getAgency(#address, #date);
@ -50,12 +43,6 @@
AND a.isVisible AND a.isVisible
ORDER BY a.description; ORDER BY a.description;
DROP TEMPORARY TABLE tmp.zoneGetAgency; DROP TEMPORARY TABLE tmp.zoneGetAgency;
<sql-batch property="batch">
<custom>
<item name="address" param="address"/>
<item name="date" param="date"/>
</custom>
</sql-batch>
</db-model> </db-model>
</vn-group> </vn-group>
<div id="title"> <div id="title">
@ -68,144 +55,148 @@
on-click="onCancelClick"/> on-click="onCancelClick"/>
</div> </div>
<div id="form" class="checkout"> <div id="form" class="checkout">
<div class="box bar"> <div class="vn-w-sm">
<htk-assistant-bar <div class="box bar">
id="assistant-bar" <htk-assistant-bar
assistant="assistant"/> id="assistant-bar"
</div> assistant="assistant"/>
<div class="box"> </div>
<div class="form"> <div class="box vn-px-lg vn-py-xl">
<htk-assistant id="assistant" <div class="form">
endFunc="onConfirmClick"> <htk-assistant id="assistant"
<htk-step endFunc="onConfirmClick">
name="method" <htk-step
validate-func="methodValidate"> name="method"
<h2><t>DeliveryOrPickupQuestion</t></h2> validate-func="methodValidate">
<div class="answers radio"> <h2><t>DeliveryOrPickupQuestion</t></h2>
<htk-radio-group <div class="answers radio">
id="rg-method" <htk-radio-group
param="method" id="rg-method"
on-changed="onMethodChange"/> form="lot"
<div> column="method"
<label> on-changed="onMethodChange"/>
<htk-radio radio-group="rg-method" value="AGENCY"/> <div>
<t>Receive the order</t> <label>
</label> <htk-radio radio-group="rg-method" value="AGENCY"/>
<t>Receive the order</t>
</label>
</div>
<div>
<label>
<htk-radio radio-group="rg-method" value="PICKUP"/>
<t>PickupInStore</t>
</label>
</div>
</div> </div>
<div> </htk-step>
<label> <htk-step
<htk-radio radio-group="rg-method" value="PICKUP"/> name="date"
<t>PickupInStore</t> show-func="dateShow"
</label> validate-func="dateValidate">
<h2 id="date-question"/>
<div class="answers">
<htk-calendar
id="calendar"
class="thin-calendar"
form="lot"
column="date"
restrict-func="calendarRestrict"
on-changed="onFieldChange"/>
</div> </div>
</div> </htk-step>
</htk-step> <htk-step
<htk-step name="address"
name="date" show-func="addressShow"
show-func="dateShow" validate-func="addressValidate">
validate-func="dateValidate"> <h2 id="address-question"/>
<h2 id="date-question"/> <div class="answers target">
<div class="answers"> <db-form id="address-form" model="addresses"/>
<htk-calendar <htk-repeater
id="calendar" id="repeater"
class="thin-calendar" form-id="iter"
param="date" on-change="onAddressChange">
restrict-func="calendarRestrict" <db-model property="model" id="addresses">
on-changed="onFieldChange"/> SELECT a.id, a.nickname, p.name province, a.city, a.street, a.isActive, c.country
</div> FROM myAddress a
</htk-step> LEFT JOIN vn.province p ON p.id = a.provinceFk
<htk-step JOIN vn.country c ON c.id = p.countryFk
name="address"
show-func="addressShow"
validate-func="addressValidate">
<h2 id="address-question"/>
<div class="answers target">
<db-form id="address-form" model="addresses"/>
<htk-repeater
id="repeater"
form-id="iter"
on-change="onAddressChange"
renderer="addressRenderer">
<db-model property="model" id="addresses">
SELECT a.id, a.nickname, p.name province, a.city, a.street, a.isActive, c.country
FROM myAddress a
LEFT JOIN vn.province p ON p.id = a.provinceFk
JOIN vn.country c ON c.id = p.countryFk
WHERE a.isActive WHERE a.isActive
</db-model> </db-model>
<custom> <custom>
<div class="address" id="address"> <div
<p class="consignee"> class="address"
<htk-text form="iter" column="nickname"/> on-click="this.onAddressClick(iter.id)"
</p> id="address">
<p> <p class="consignee">{{iter.nickname}}</p>
<htk-text form="iter" column="street"/> <p>{{iter.street}}</p>
</p> </div>
</div> </custom>
</custom> </htk-repeater>
</htk-repeater> </div>
</div> </htk-step>
</htk-step> <htk-step
<htk-step name="agency"
name="agency" show-func="agencyShow"
show-func="agencyShow" validate-func="agencyValidate">
validate-func="agencyValidate"> <h2><t>AgencyQuestion</t></h2>
<h2><t>AgencyQuestion</t></h2> <div class="answers target">
<div class="answers target"> <htk-combo
<htk-combo id="agency-combo"
id="agency-combo" form="lot"
param="agency" column="agency"
on-changed="onFieldChange" on-changed="onFieldChange"
model="agencies"/> model="agencies"/>
</div> </div>
</htk-step> </htk-step>
<htk-step <htk-step
name="pickup" name="pickup"
show-func="pickupShow" show-func="pickupShow"
validate-func="pickupValidate"> validate-func="pickupValidate">
<h2><t>PickupWarehouseQuestion</t></h2> <h2><t>PickupWarehouseQuestion</t></h2>
<div class="answers target"> <div class="answers target">
<htk-combo <htk-combo
id="warehouse-combo" id="warehouse-combo"
param="agency" form="lot"
on-changed="onFieldChange" column="agency"
model="warehouses"/> on-changed="onFieldChange"
</div> model="warehouses"/>
</htk-step> </div>
<htk-step </htk-step>
name="confirm-delivery"> <htk-step
<h2><t>ConfirmToAccessCatalog</t></h2> name="confirm-delivery">
<div class="answers target"> <h2><t>ConfirmData</t></h2>
<p> <div class="answers target">
<t>Arrival</t> <p>
<htk-text format="%D" param="date"/> <t>Arrival</t>
</p> <htk-text format="%D" form="lot" column="date"/>
<p> </p>
<htk-text form="address-form" column="street"/> <p>
</p> <htk-text form="address-form" column="street"/>
<p> </p>
<t>Agency</t> <p>
<htk-text form="agency-combo" column="description"/> <t>Agency</t>
</p> <htk-text form="agency-combo" column="description"/>
<div class="clear"/> </p>
</div> <div class="clear"/>
</htk-step> </div>
<htk-step </htk-step>
name="confirm-pickup"> <htk-step
<h2><t>ConfirmToAccessCatalog</t></h2> name="confirm-pickup">
<div class="answers target"> <h2><t>ConfirmData</t></h2>
<p> <div class="answers target">
<t>Pickup</t> <p>
<htk-text format="%D" param="date"/> <t>Pickup</t>
</p> <htk-text format="%D" form="lot" column="date"/>
<p> </p>
<t>Warehouse</t> <p>
<htk-text form="warehouse-combo" column="description"/> <t>Warehouse</t>
</p> <htk-text form="warehouse-combo" column="description"/>
<div class="clear"/> </p>
</div> <div class="clear"/>
</htk-step> </div>
</htk-assistant> </htk-step>
</htk-assistant>
</div>
</div> </div>
</div> </div>
</div> </div>

View File

@ -6,7 +6,7 @@ Hedera.Confirm = new Class({
this.close(); this.close();
this.isOpen = true; this.isOpen = true;
Hedera.BasketChecker.check(this.conn, Hedera.BasketChecker.check(this.conn, this.hash,
this.onBasketCheck.bind(this)); this.onBasketCheck.bind(this));
}, },
@ -19,21 +19,21 @@ Hedera.Confirm = new Class({
if (form.row < 0) if (form.row < 0)
return; return;
if (form.get('method') != 'PICKUP') { if (form.$.method != 'PICKUP') {
Vn.Node.show(this.$('address')); Vn.Node.show(this.$.address);
Vn.Node.setText(this.$('method'), _('Agency')); Vn.Node.setText(this.$.method, _('Agency'));
} else { } else {
Vn.Node.hide(this.$('address')); Vn.Node.hide(this.$.address);
Vn.Node.setText(this.$('method'), _('Warehouse')); Vn.Node.setText(this.$.method, _('Warehouse'));
} }
var total = form.get('taxableBase') + form.get('tax'); var total = form.$.taxableBase + form.$.tax;
if (total === null) if (total === null)
total = 0; total = 0;
var credit = form.get('credit'); var credit = form.$.credit;
var debt = form.get('debt'); var debt = form.$.debt;
var totalDebt = debt + total; var totalDebt = debt + total;
var exceededCredit = totalDebt - credit; var exceededCredit = totalDebt - credit;
@ -43,21 +43,21 @@ Hedera.Confirm = new Class({
Htk.Toast.showWarning( Htk.Toast.showWarning(
_('You have exceeded your credit.')); _('You have exceeded your credit.'));
this.$('debt').value = debt; this.$.debt.value = debt;
this.$('total-debt').value = totalDebt; this.$.totalDebt.value = totalDebt;
this.$('total-amount').value = totalDebt; this.$.totalAmount.value = totalDebt;
this.$('credit-excess').value = exceededCredit; this.$.creditExcess.value = exceededCredit;
this.$('excess-amount').value = exceededCredit; this.$.excessAmount.value = exceededCredit;
this.$('pay-amount').value = 'ALL'; this.$.payAmount.value = 'ALL';
if (credit > 0) { if (credit > 0) {
this.$('credit-info').style.display = 'table-row'; this.$.creditInfo.style.display = 'table-row';
if (creditExceededCond) { if (creditExceededCond) {
this.$('amount-selector').style.display = 'block'; this.$.amountSelector.style.display = 'block';
this.$('exceeded-info').style.display = 'table-row'; this.$.exceededInfo.style.display = 'table-row';
this.$('pay-amount').value = 'EXCEEDED'; this.$.payAmount.value = 'EXCEEDED';
} }
} }
@ -77,43 +77,43 @@ Hedera.Confirm = new Class({
} }
for (var i = 0; i < methods.length; i++) for (var i = 0; i < methods.length; i++)
this.$(methods[i] +'-method').style.display = 'block'; this.$[`${methods[i]}Method`].style.display = 'block';
this.$('pay-method').value = selectedMethod; this.$.payMethod.value = selectedMethod;
}, },
onPayMethodChange: function(payMethod) { onPayMethodChange: function(payMethod) {
var id = this.displayedInfo; var id = this.displayedInfo;
if (id) if (id)
Vn.Node.removeClass(this.$(id), 'selected'); Vn.Node.removeClass(this.$[id], 'selected');
switch (payMethod.value) { switch (payMethod.value) {
case 'BALANCE': case 'BALANCE':
id = 'balance-method'; id = 'balanceMethod';
break; break;
case 'CREDIT': case 'CREDIT':
id = 'credit-method'; id = 'creditMethod';
break; break;
case 'CARD': case 'CARD':
id = 'card-method'; id = 'cardMethod';
break; break;
case 'TRANSFER': case 'TRANSFER':
id = 'transfer-method'; id = 'transferMethod';
break; break;
default: default:
id = null; id = null;
} }
this.displayedInfo = id; this.displayedInfo = id;
if (id) if (id)
Vn.Node.addClass(this.$(id), 'selected'); Vn.Node.addClass(this.$[id], 'selected');
}, },
disableButtons: function(disable) { disableButtons: function(disable) {
this.$('modify').disabled = disable; this.$.modify.disabled = disable;
this.$('confirm').disabled = disable; this.$.confirm.disabled = disable;
}, },
onModifyClick: function() { onModifyClick: function() {
@ -122,27 +122,30 @@ Hedera.Confirm = new Class({
onConfirmClick: function() { onConfirmClick: function() {
this.disableButtons(true); this.disableButtons(true);
this.$('confirm-query').execute(); this.$.confirmQuery.execute();
}, },
onConfirm: function(query, resultSet) { onConfirm: function(query, resultSet) {
this.disableButtons(false); this.disableButtons(false);
if (resultSet.fetchResult()) if (resultSet.fetchResult())
this.$('success-dialog').show(); this.$.successDialog.show();
}, },
onDialogResponse: function() { onDialogResponse: function() {
if (this.$('pay-method').value === 'CARD') { if (this.$.payMethod.value === 'CARD') {
if (this.$('pay-amount').value === 'EXCEEDED') if (this.$.payAmount.value === 'EXCEEDED')
var payAmount = this.$('excess-amount').value; var payAmount = this.$.excessAmount.value;
else else
var payAmount = this.$('total-amount').value; var payAmount = this.$.totalAmount.value;
var tpv = new Hedera.Tpv({conn: this.conn}); var tpv = new Hedera.Tpv({
tpv.pay(payAmount, this.$('order-form').get('companyFk')); conn: this.conn,
hash: this.hash
});
tpv.pay(payAmount, this.$.order.companyFk);
} else } else
this.hash.set({'form': 'ecomerce/orders'}); this.hash.setAll({form: 'ecomerce/orders'});
} }
}); });

View File

@ -1,5 +1,7 @@
Checkout: Finalitzar comanda Checkout: Finalitzar comanda
Order summary: Resum de la comanda Order summary: Resum de la comanda
ShippingInformation: Dades d'enviament
DeliveryAddress: Adreça de lliurament
Delivery at: Lliurament el Delivery at: Lliurament el
Agency: Agència Agency: Agència
Warehouse: Magatzem Warehouse: Magatzem

View File

@ -1,5 +1,7 @@
Checkout: Checkout Checkout: Checkout
Order summary: Order summary Order summary: Order summary
ShippingInformation: Shipping information
DeliveryAddress: Delivery address
Delivery at: Delivery at Delivery at: Delivery at
Agency: Agency Agency: Agency
Warehouse: Store Warehouse: Store

View File

@ -1,5 +1,7 @@
Checkout: Finalizar pedido Checkout: Finalizar pedido
Order summary: Resumen del pedido Order summary: Resumen del pedido
ShippingInformation: Datos de envío
DeliveryAddress: Dirección de entrega
Delivery at: Entrega el Delivery at: Entrega el
Agency: Agencia Agency: Agencia
Warehouse: Almacén Warehouse: Almacén

View File

@ -1,5 +1,7 @@
Checkout: Finir la commande Checkout: Finir la commande
Order summary: Résumé de la commande Order summary: Résumé de la commande
ShippingInformation: Informations sur la livraison
DeliveryAddress: Addresse de livraison
Delivery at: Livraison à Delivery at: Livraison à
Agency: Agence Agency: Agence
Warehouse: Entrepôt Warehouse: Entrepôt

View File

@ -1,5 +1,7 @@
Checkout: Finalizar encomenda Checkout: Finalizar encomenda
Order summary: Resumo da encomenda Order summary: Resumo da encomenda
ShippingInformation: Dados de envio
DeliveryAddress: Endereço de entrega
Delivery at: Entrega na Delivery at: Entrega na
Agency: Agência Agency: Agência
Warehouse: Armazém Warehouse: Armazém

View File

@ -1,86 +1,33 @@
.confirm
{ .confirm .summary {
padding: 1em; margin-bottom: 16px;
max-width: 30em;
margin: 0 auto;
color: #555;
} }
.confirm .box .confirm p {
{
padding: 2.2em 2.5em;
}
.confirm .summary
{
margin-bottom: 1em;
}
.confirm .address
{
margin-top: .8em;
}
.confirm h2
{
font-size: 1.1em;
font-weight: normal;
padding: 0;
margin: 0;
margin-bottom: .5em;
color: #333;
}
.confirm button
{
font-size: 1.4em;
}
.confirm p
{
margin: .2em 0; margin: .2em 0;
} }
.confirm .modify-order
{
float: left;
}
.confirm .confirm-order
{
float: right;
}
.confirm .payment > div
{
margin-bottom: 1.4em;
}
.confirm .payment > .button-bar
{
margin: 0;
margin-top: 1.8em;
}
/* Table */ /* Table */
.confirm .debt-info .confirm .debt-info {
{
padding: 0; padding: 0;
} }
.confirm .debt-info > table .confirm .debt-info > table {
{
border-collapse: collapse; border-collapse: collapse;
} }
.confirm td .confirm td {
{
padding: .15em 0; padding: .15em 0;
} }
.confirm .sum-total > td .confirm .sum-total > td {
{
border-top: solid 1px #DDD; border-top: solid 1px #DDD;
font-weight: bold; font-weight: bold;
} }
.confirm .currency .confirm .currency {
{
text-align: right; text-align: right;
} }
.confirm .credit-info .confirm .credit-info {
{
display: none; display: none;
} }
.confirm .exceeded-info .confirm .exceeded-info {
{
display: none; display: none;
color: #E53935; color: #E53935;
} }
@ -88,34 +35,59 @@
/* Pay */ /* Pay */
.confirm .amount-selector, .confirm .amount-selector,
.confirm .pay-methods > div .confirm .pay-methods > div {
{
display: none; display: none;
} }
.confirm .pay-methods > div .confirm .pay-methods > div {
{
margin: .3em 0; margin: .3em 0;
} }
.confirm .pay-methods > div > label > input[type=radio] .confirm .pay-methods > div > label > input[type=radio] {
{
margin: 0; margin: 0;
margin-right: .5em; margin-right: .5em;
vertical-align: middle; vertical-align: middle;
} }
.confirm .pay-methods > div > div .confirm .pay-methods > div > div {
{
padding: .5em 1.5em; padding: .5em 1.5em;
display: none; display: none;
} }
.confirm .pay-methods > div.selected > div .confirm .pay-methods > div.selected > div {
{
display: block; display: block;
} }
.confirm .transfer-account .confirm .transfer-account {
{
margin-top: .5em; margin-top: .5em;
} }
.confirm .transfer-account > p .confirm .transfer-account > p {
{
margin: .1em 0; margin: .1em 0;
} }
.confirm .payment > div {
margin-bottom: 1.4em;
}
.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,6 +1,6 @@
<vn> <vn>
<vn-group> <vn-group>
<db-form id="order-form" on-ready="onOrderReady"> <db-form v-model="order" on-ready="onOrderReady">
<db-model property="model" result-index="1"> <db-model property="model" result-index="1">
CALL myBasket_getTax; CALL myBasket_getTax;
SELECT o.id, o.sent, o.notes, o.companyFk, SELECT o.id, o.sent, o.notes, o.companyFk,
@ -31,181 +31,177 @@
<h1><t>Order summary</t></h1> <h1><t>Order summary</t></h1>
</div> </div>
<div id="form" class="confirm"> <div id="form" class="confirm">
<div class="box summary"> <div class="vn-w-sm">
<div> <div class="box vn-pa-lg summary">
<div class="delivery"> <div>
<p> <div class="delivery">
<t>Delivery at</t> <h6><t>ShippingInformation</t></h6>
<htk-text format="%D" form="order-form" column="sent"/> <p>
</p> <t>Delivery at</t> {{Vn.Value.format(order.sent, _('%D'))}}
<p> </p>
<span id="method"><t>Agency</t></span> <p>
<htk-text form="order-form" column="agency"/> <span id="method"><t>Agency</t></span> {{order.agency}}
</p> </p>
</div>
<div id="address" class="address">
<p>
<htk-text form="order-form" column="nickname"/>
</p>
<p>
<htk-text form="order-form" column="street"/>
</p>
<p>
<htk-text form="order-form" column="postalCode"/>,
<htk-text form="order-form" column="city"/>
</p>
</div>
</div>
</div>
<div class="box payment">
<div>
<table class="debt-info">
<tbody>
<tr>
<td>
<t>Previous balance</t>
</td>
<td class="currency">
<htk-text format="%.2d€" id="debt"/>
</td>
</tr>
<tr>
<td>
<t>Order total</t>
</td>
<td class="currency">
<htk-text format="%.2d€" form="order-form" column="taxableBase"/>
</td>
</tr>
<tr>
<td>
<t>Order VAT</t>
</td>
<td class="currency">
<htk-text format="%.2d€" form="order-form" column="tax"/>
</td>
</tr>
<tr class="total-debt sum-total">
<td>
<t>Total debt</t>
</td>
<td class="currency">
<htk-text format="%.2d€" id="total-debt"/>
</td>
</tr>
<tr id="credit-info" class="credit-info">
<td>
<t>Credit</t>
</td>
<td class="currency">
<htk-text format="%.2d€" form="order-form" column="credit"/>
</td>
</tr>
<tr id="exceeded-info" class="exceeded-info sum-total">
<td>
<t>Exceeded credit</t>
</td>
<td class="currency">
<htk-text format="%.2d€" id="credit-excess"/>
</td>
</tr>
</tbody>
</table>
</div>
<div id="amount-selector" class="amount-selector">
<h2>
<t>Amount to pay</t>
</h2>
<div class="radio">
<htk-radio-group
id="pay-amount"/>
<div>
<htk-radio radio-group="pay-amount" value="ALL"/>
<label>
<t>Total debt</t>,
<htk-text format="%.2d€" id="total-amount"/>
</label>
</div> </div>
<div> <div id="address" class="address vn-mt-md">
<htk-radio radio-group="pay-amount" value="EXCEEDED"/> <h6><t>DeliveryAddress</t></h6>
<label> <p>{{order.nickname}}</p>
<t>Exceeded credit</t>, <p>{{order.street}}</p>
<htk-text format="%.2d€" id="excess-amount"/> <p>{{order.postalCode}}, {{order.city}}</p>
</label>
</div> </div>
</div> </div>
</div> </div>
<div> <div class="box vn-pa-lg payment">
<h2> <div>
<t>Pay method</t> <table class="debt-info">
</h2> <tbody>
<div class="pay-methods"> <tr>
<htk-radio-group <td><t>Previous balance</t></td>
id="pay-method" <td class="currency">
on-changed="onPayMethodChange"/> <htk-text format="%.2d€" id="debt"/>
<div id="balance-method"> </td>
<label> </tr>
<htk-radio radio-group="pay-method" value="BALANCE"/> <tr>
<t>Use my balance</t> <td>
</label> <t>Order total</t>
</td>
<td class="currency">
{{Vn.Value.format(order.taxableBase, _('%.2d€'))}}
</td>
</tr>
<tr>
<td>
<t>Order VAT</t>
</td>
<td class="currency">
{{Vn.Value.format(order.tax, _('%.2d€'))}}
</td>
</tr>
<tr class="total-debt sum-total">
<td>
<t>Total debt</t>
</td>
<td class="currency">
<htk-text format="%.2d€" id="total-debt"/>
</td>
</tr>
<tr id="credit-info" class="credit-info">
<td>
<t>Credit</t>
</td>
<td class="currency">
{{Vn.Value.format(order.credit, _('%.2d€'))}}
</td>
</tr>
<tr id="exceeded-info" class="exceeded-info sum-total">
<td>
<t>Exceeded credit</t>
</td>
<td class="currency">
<htk-text format="%.2d€" id="credit-excess"/>
</td>
</tr>
</tbody>
</table>
</div>
<div id="amount-selector" class="amount-selector">
<h2>
<t>Amount to pay</t>
</h2>
<div class="radio">
<htk-radio-group
id="pay-amount"/>
<div> <div>
<t>You have a favorable balance.</t> <htk-radio radio-group="pay-amount" value="ALL"/>
<label>
<t>Total debt</t>,
<htk-text format="%.2d€" id="total-amount"/>
</label>
</div> </div>
</div>
<div id="credit-method">
<label>
<htk-radio radio-group="pay-method" value="CREDIT"/>
<t>Use my credit</t>
</label>
<div> <div>
<t>You have a favorable credit.</t> <htk-radio radio-group="pay-amount" value="EXCEEDED"/>
<label>
<t>Exceeded credit</t>,
<htk-text format="%.2d€" id="excess-amount"/>
</label>
</div> </div>
</div> </div>
<div id="card-method">
<label>
<htk-radio radio-group="pay-method" value="CARD"/>
<t>Credit card</t>
</label>
<div>
<t>You will be redirected to the payment.</t>
</div>
</div>
<div id="transfer-method">
<label>
<htk-radio radio-group="pay-method" value="TRANSFER"/>
<t>Bank Transfer</t>
</label>
<div>
<t>Make a transfer to one account.</t>
<htk-repeater form-id="iter">
<db-model property="model">
SELECT name, iban FROM mainAccountBank
</db-model>
<custom>
<div class="transfer-account">
<p><htk-text form="iter" column="name"/></p>
<p><htk-text form="iter" column="iban"/></p>
</div>
</custom>
</htk-repeater>
</div>
</div>
<div id="later-method">
<label>
<htk-radio radio-group="pay-method" value="LATER"/>
<t>Pay later</t>
</label>
</div>
</div> </div>
</div> <div>
<div class="button-bar"> <h6><t>Pay method</t></h6>
<button on-click="onModifyClick" id="modify" class="thin modify-order"> <div class="pay-methods">
<t>Modify</t> <htk-radio-group
</button> id="pay-method"
<button on-click="onConfirmClick" id="confirm" class="thin confirm-order"> on-changed="onPayMethodChange"/>
<t>Confirm</t> <div id="balance-method">
</button> <label>
<div class="clear"/> <htk-radio radio-group="pay-method" value="BALANCE"/>
<t>Use my balance</t>
</label>
<div>
<t>You have a favorable balance.</t>
</div>
</div>
<div id="credit-method">
<label>
<htk-radio radio-group="pay-method" value="CREDIT"/>
<t>Use my credit</t>
</label>
<div>
<t>You have a favorable credit.</t>
</div>
</div>
<div id="card-method">
<label>
<htk-radio radio-group="pay-method" value="CARD"/>
<t>Credit card</t>
</label>
<div>
<t>You will be redirected to the payment.</t>
</div>
</div>
<div id="transfer-method">
<label>
<htk-radio radio-group="pay-method" value="TRANSFER"/>
<t>Bank Transfer</t>
</label>
<div>
<t>Make a transfer to one account.</t>
<htk-repeater form-id="iter">
<db-model property="model">
SELECT name, iban FROM mainAccountBank
</db-model>
<custom>
<div class="transfer-account">
<p>{{iter.name}}</p>
<p>{{iter.iban}}</p>
</div>
</custom>
</htk-repeater>
</div>
</div>
<div id="later-method">
<label>
<htk-radio radio-group="pay-method" value="LATER"/>
<t>Pay later</t>
</label>
</div>
</div>
</div>
<div class="button-bar vn-mt-md">
<button
id="modify"
on-click="this.onModifyClick()"
class="modify-order">
<t>Modify</t>
</button>
<button
id="confirm"
on-click="this.onConfirmClick()"
class="confirm-order">
<t>Confirm</t>
</button>
</div>
</div> </div>
</div> </div>
</div> </div>

View File

@ -3,9 +3,9 @@ Hedera.Invoices = new Class({
Extends: Hedera.Form, Extends: Hedera.Form,
donwloadRenderer: function(column, invoice) { donwloadRenderer: function(column, invoice) {
var invoiceId = invoice.get('id'); var invoiceId = invoice.$.id;
if (invoice.get('hasPdf') && invoiceId) { if (invoice.$.hasPdf && invoiceId) {
var params = { var params = {
srv: 'rest:dms/invoice', srv: 'rest:dms/invoice',
invoice: invoiceId, invoice: invoiceId,

View File

@ -1,14 +0,0 @@
.invoices
{
padding: 1em;
}
.invoices .box
{
max-width: 40em;
}
.invoices .box > .header,
.invoices .htk-grid > thead > tr
{
background-color: #3F51B6;
}

View File

@ -3,9 +3,9 @@
<h1><t>Invoices</t></h1> <h1><t>Invoices</t></h1>
</div> </div>
<div id="form" class="invoices"> <div id="form" class="invoices">
<div class="box"> <htk-grid
<div> class="box vn-w-sm"
<htk-grid show-header="false"> show-header="false">
<db-model property="model" id="tickets"> <db-model property="model" id="tickets">
SELECT id, ref, issued, amount, hasPdf SELECT id, ref, issued, amount, hasPdf
FROM myInvoice FROM myInvoice
@ -19,7 +19,5 @@
renderer="donwloadRenderer" renderer="donwloadRenderer"
target="_blank"/> target="_blank"/>
</htk-grid> </htk-grid>
</div>
</div>
</div> </div>
</vn> </vn>

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