diff --git a/doc/Htk.odg b/doc/Htk.odg
deleted file mode 100755
index 52719292..00000000
Binary files a/doc/Htk.odg and /dev/null differ
diff --git a/forms/account/address-list/index.js b/forms/account/address-list/index.js
deleted file mode 100644
index a68d195a..00000000
--- a/forms/account/address-list/index.js
+++ /dev/null
@@ -1,43 +0,0 @@
-import './style.scss';
-
-export default new Class({
-	Extends: Hedera.Form,
-	Template: require('./ui.xml')
-
-	,activate() {
-		this.$.userModel.setInfo('c', 'myClient', 'hedera');
-		this.$.addresses.setInfo('a', 'myAddress', 'hedera');
-	}
-	
-	,onAddAddressClick() {
-		this.hash.setAll({
-			form: 'account/address',
-			address: 0
-		});
-	}
-	
-	,onReturnClick() {
-		window.history.back();
-	}
-
-	,onSetDefaultClick(event, addressId) {
-		if (event.defaultPrevented) return;
-		this.$.defaultAddress.value = addressId;
-		Htk.Toast.showMessage(_('DefaultAddressModified'));
-	}
-	
-	,async onRemoveAddressClick(form) {
-		if (confirm(_('AreYouSureDeleteAddress'))) {
-			await form.set('isActive', false);
-			await form.refresh();
-		}
-	}
-	
-	,onEditAddressClick(address) {
-		this.hash.setAll({
-			form: 'account/address',
-			address
-		});
-	}
-});
-
diff --git a/forms/account/address-list/locale/ca.yml b/forms/account/address-list/locale/ca.yml
deleted file mode 100644
index 26601428..00000000
--- a/forms/account/address-list/locale/ca.yml
+++ /dev/null
@@ -1,8 +0,0 @@
-Addresses: Adreces
-Return: Tornar
-AddAddress: Afegir adreça
-SetAsDefault: Establir com per defecte
-RemoveAddress: Esborrar direcció
-EditAddress: Modificar direcció
-AreYouSureDeleteAddress: Estàs segur de que vols eliminar la direcció?
-DefaultAddressModified: Adreça per defecte modificada
diff --git a/forms/account/address-list/locale/en.yml b/forms/account/address-list/locale/en.yml
deleted file mode 100644
index 75bdb2ac..00000000
--- a/forms/account/address-list/locale/en.yml
+++ /dev/null
@@ -1,8 +0,0 @@
-Addresses: Addresses
-Return: Return
-AddAddress: Add address
-SetAsDefault: Set as default
-RemoveAddress: Remove address
-EditAddress: Edit address
-AreYouSureDeleteAddress: Are you sure you want to delete the address?
-DefaultAddressModified: Default address modified
diff --git a/forms/account/address-list/locale/es.yml b/forms/account/address-list/locale/es.yml
deleted file mode 100644
index 50a29c77..00000000
--- a/forms/account/address-list/locale/es.yml
+++ /dev/null
@@ -1,8 +0,0 @@
-Addresses: Direcciones
-Return: Volver
-AddAddress: Añadir dirección
-SetAsDefault: Establecer como predeterminada
-RemoveAddress: Borrar dirección
-EditAddress: Modificar dirección
-AreYouSureDeleteAddress: ¿Estás seguro de que quieres borrar la dirección?
-DefaultAddressModified: Dirección por defecto modificada
diff --git a/forms/account/address-list/locale/fr.yml b/forms/account/address-list/locale/fr.yml
deleted file mode 100644
index 8530ec22..00000000
--- a/forms/account/address-list/locale/fr.yml
+++ /dev/null
@@ -1,8 +0,0 @@
-Addresses: Adresses
-Return: Retour
-AddAddress: Ajouter une adresse
-SetAsDefault: Définir par défaut
-RemoveAddress: Supprimer l'adresse
-EditAddress: Changement d'adresse
-AreYouSureDeleteAddress: Souhaitez-vous vraiment supprier l'adresse?
-DefaultAddressModified: Adresse par défaut modifiée
diff --git a/forms/account/address-list/locale/pt.yml b/forms/account/address-list/locale/pt.yml
deleted file mode 100644
index 7657ab26..00000000
--- a/forms/account/address-list/locale/pt.yml
+++ /dev/null
@@ -1,8 +0,0 @@
-Addresses: Moradas
-Return: Voltar
-AddAddress: Adicionar Morada
-SetAsDefault: Selecionar como pre-determinado
-RemoveAddress: Eliminar Morada
-EditAddress: Modificar Morada
-AreYouSureDeleteAddress: Tens certeza que queres eliminar esta morada?
-DefaultAddressModified: Endereço padrão modificado
diff --git a/forms/account/address-list/style.scss b/forms/account/address-list/style.scss
deleted file mode 100644
index 71f0f721..00000000
--- a/forms/account/address-list/style.scss
+++ /dev/null
@@ -1,6 +0,0 @@
-
-hedera-address-list {
-	.htk-list .side {
-		padding-right: 16px;
-	}
-}
diff --git a/forms/account/address-list/ui.xml b/forms/account/address-list/ui.xml
deleted file mode 100644
index 3afbf143..00000000
--- a/forms/account/address-list/ui.xml
+++ /dev/null
@@ -1,70 +0,0 @@
-<vn>
-<vn-group>
-	<db-form id="user-form">
-		<db-model property="model" id="user-model" updatable="true">
-			SELECT id, defaultAddressFk
-				FROM myClient c
-		</db-model>
-	</db-form>
-	<db-model id="addresses" updatable="true">
-		SELECT a.id, a.nickname, p.name province, a.postalCode,
-		a.city, a.street, a.isActive
-			FROM myAddress a
-			LEFT JOIN vn.province p ON p.id = a.provinceFk
-				WHERE a.isActive
-	</db-model>
-</vn-group>
-<div id="title">
-	<h1><t>Addresses</t></h1>
-</div>
-<div id="actions">
-	<htk-bar-button
-		icon="add"
-		tip="_AddAddress"
-		on-click="this.onAddAddressClick()"/>
-</div>
-<div id="form" class="hedera-address-list">
-	<div class="box vn-w-sm">
-		<htk-radio-group
-			id="default-address"
-			column="defaultAddressFk"
-			form="user-form"/>
-		<htk-repeater model="addresses" form-id="address" class="htk-list">
-			<custom>
-			<div class="item clickable" on-click="this.onSetDefaultClick($event, address.id)">
-				<div class="side">
-					<htk-radio
-						radio-group="default-address"
-						val="{{address.id}}"
-						tip="_SetAsDefault"
-						name="test"/>
-				</div>
-				<div class="content">
-					<p class="important">
-						{{address.nickname}}
-					</p>
-					<p>
-						{{address.street}}
-					</p>
-					<p>
-						{{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>
-			</custom>
-		</htk-repeater>
-	</div>
-</div>
-</vn>
diff --git a/forms/account/address/index.js b/forms/account/address/index.js
deleted file mode 100644
index 374d9bda..00000000
--- a/forms/account/address/index.js
+++ /dev/null
@@ -1,20 +0,0 @@
-export default new Class({
-	Extends: Hedera.Form,
-	Template: require('./ui.xml'),
-
-	activate() {
-		this.$.model.setInfo('a', 'myAddress', 'hedera', ['id'], 'id');
-		this.$.model.setDefault('clientFk', 'a',
-			new Sql.Function({schema: 'account', name: 'myUser_getId'}));
-	},
-	
-	onStatusChange() {
-		if (this.$.iter.ready && this.hash.$.address == 0)
-			this.$.iter.insertRow();
-	},
-	
-	onOperationsDone() {
-		Htk.Toast.showMessage(_('AddressChangedSuccessfully'));
-		window.history.back()
-	}
-});
diff --git a/forms/account/address/locale/ca.yml b/forms/account/address/locale/ca.yml
deleted file mode 100644
index 16c63cf3..00000000
--- a/forms/account/address/locale/ca.yml
+++ /dev/null
@@ -1,10 +0,0 @@
-AddEditAddress: Afegir o modificar adreça
-Name: Consignatari
-Address: Direcció
-City: Ciutat
-ZipCode: Codi postal
-Country: País
-Province: Província
-Return: Tornar
-Accept: Acceptar
-AddressChangedSuccessfully: Adreça modificada correctament
diff --git a/forms/account/address/locale/en.yml b/forms/account/address/locale/en.yml
deleted file mode 100644
index 38fe889e..00000000
--- a/forms/account/address/locale/en.yml
+++ /dev/null
@@ -1,10 +0,0 @@
-AddEditAddress: Add or edit address
-Name: Consignee
-Address: Address
-City: City
-ZipCode: Zip code
-Country: Country
-Province: Province
-Return: Return
-Accept: Accept
-AddressChangedSuccessfully: Address changed successfully
diff --git a/forms/account/address/locale/es.yml b/forms/account/address/locale/es.yml
deleted file mode 100644
index 19674310..00000000
--- a/forms/account/address/locale/es.yml
+++ /dev/null
@@ -1,10 +0,0 @@
-AddEditAddress: Añadir o modificar dirección
-Name: Consignatario
-Address: Dirección
-City: Ciudad
-ZipCode: Código postal
-Country: País
-Province: Provincia
-Return: Volver
-Accept: Aceptar
-AddressChangedSuccessfully: Dirección modificada correctamente
diff --git a/forms/account/address/locale/fr.yml b/forms/account/address/locale/fr.yml
deleted file mode 100644
index ed739095..00000000
--- a/forms/account/address/locale/fr.yml
+++ /dev/null
@@ -1,10 +0,0 @@
-AddEditAddress: Ajouter ou modifier l'adresse
-Name: Destinataire
-Address: Numéro Rue
-City: Ville
-ZipCode: Code postal
-Country: Pays
-Province: Province
-Return: Reviens
-Accept: Accepter
-AddressChangedSuccessfully: Adresse modifié avec succès
diff --git a/forms/account/address/locale/pt.yml b/forms/account/address/locale/pt.yml
deleted file mode 100644
index 4aaa30d3..00000000
--- a/forms/account/address/locale/pt.yml
+++ /dev/null
@@ -1,10 +0,0 @@
-AddEditAddress: Adicionar ou modificar morada
-Name: Consignatario
-Address: Morada
-City: Concelho
-ZipCode: Código postal
-Country: País
-Province: Distrito
-Return: Voltar
-Accept: Aceitar
-AddressChangedSuccessfully: Morada modificada corretamente
diff --git a/forms/account/address/ui.xml b/forms/account/address/ui.xml
deleted file mode 100644
index 66c71144..00000000
--- a/forms/account/address/ui.xml
+++ /dev/null
@@ -1,87 +0,0 @@
-<vn>
-<vn-group>
-	<vn-lot-query id="params">
-		<vn-spec name="address" type="Number"/>
-	</vn-lot-query>
-	<db-form id="iter" on-status-changed="this.onStatusChange()">
-		<db-model
-		 	id="model"
-			property="model"
-			updatable="true"
-			mode="ON_DEMAND"
-			lot="params"
-			on-operations-done="this.onOperationsDone()">
-			SELECT a.id, a.street, a.nickname, a.city,
-					a.postalCode, a.provinceFk, p.countryFk
-				FROM myAddress a
-					LEFT JOIN vn.province p ON p.id = a.provinceFk
-				WHERE a.id = #address
-		</db-model>
-	</db-form>
-</vn-group>
-<div id="title">
-	<h1><t>Configuration</t></h1>
-</div>
-<div id="actions">
-	<htk-bar-button
-		icon="close"
-		tip="_Return"
-		on-click="window.history.back()"/>
-	<htk-bar-button
-		icon="check"
-		tip="_Accept"
-		on-click="iter.performOperations()"/>
-</div>
-<div id="form" class="hedera-address">
-	<div class="form box vn-w-sm vn-pa-lg">
-		<h5 class="vn-mb-md">
-			<t>AddEditAddress</t>
-		</h5>
-		<div class="form-group">
-			<htk-entry
-				placeholder="_Name"
-				form="iter" column="nickname"/>
-		</div>
-		<div class="form-group">
-			<htk-entry
-				placeholder="_Address"
-				form="iter" column="street"/>
-		</div>
-		<div class="form-group">
-			<htk-entry
-				placeholder="_City"
-				form="iter" column="city"/>
-		</div>
-		<div class="form-group">
-			<htk-entry
-				placeholder="_ZipCode"
-				form="iter" column="postalCode"/>
-		</div>
-		<div class="form-group">
-			<htk-combo
-				placeholder="_Country"
-				form="iter" column="countryFk"
-				id="country"
-				one-way="true"
-				one-time="true">
-				<db-model property="model">
-					SELECT id, country FROM vn.country
-						ORDER BY country
-				</db-model>
-			</htk-combo>
-		</div>
-		<div class="form-group">
-			<htk-combo
-				placeholder="_Province"
-				column="provinceFk"
-				form="iter">
-				<db-model property="model" lot="country">
-					SELECT id, name FROM vn.province
-						WHERE countryFk = #id
-						ORDER BY name
-				</db-model>
-			</htk-combo>
-		</div>
-	</div>
-</div>
-</vn>
diff --git a/forms/account/conf/index.js b/forms/account/conf/index.js
deleted file mode 100644
index 1cd8855a..00000000
--- a/forms/account/conf/index.js
+++ /dev/null
@@ -1,76 +0,0 @@
-import './style.scss';
-
-export default new Class({
-	Extends: Hedera.Form,
-	Template: require('./ui.xml'),
-	
-	activate() {
-		this.$.userModel.setInfo('c', 'myClient', 'hedera');
-		this.$.userModel.setInfo('u', 'myUser', 'account');
-
-		if (this.hash.$.verificationToken)
-			this.onPassChangeClick();
-	}
-
-	,onPassChangeClick() {
-		this.$.oldPassword.value = '';
-		this.$.newPassword.value = '';
-		this.$.repeatPassword.value = '';
-
-		var verificationToken = this.hash.$.verificationToken;
-		this.$.oldPassword.style.display = verificationToken ? 'none' : 'block';
-		this.$.changePassword.show();
-
-		if (verificationToken)
-			this.$.newPassword.focus();
-		else
-			this.$.oldPassword.focus();
-	}
-
-	,async onPassModifyClick() {
-		var oldPassword = this.$.oldPassword.value;
-		var newPassword = this.$.newPassword.value;
-		var repeatedPassword = this.$.repeatPassword.value;
-
-		if (newPassword == '' && repeatedPassword == '')
-			throw new Error(_('Passwords empty'));
-		if (newPassword !== repeatedPassword)
-			throw new Error(_('Passwords doesn\'t match'));
-	
-		var verificationToken = this.hash.$.verificationToken;
-		var params = {newPassword};
-
-		let err;
-		try {
-			if (verificationToken) {
-				params.verificationToken = verificationToken;
-				await this.conn.send('user/restore-password', params);
-			} else {
-				let userId = this.gui.user.id;
-				params.oldPassword = oldPassword;
-				await this.conn.patch(
-					`Accounts/${userId}/changePassword`, params);
-			}
-		} catch(e) {
-			err = e;
-			Htk.Toast.showError(err.message);
-
-			if (this.hash.$.verificationToken)
-				this.$.newPassword.select();
-			else
-				this.$.oldPassword.select();
-
-			return;
-		}
-
-		this.$.changePassword.hide();
-		this.hash.unset('verificationToken');
-		Htk.Toast.showMessage(_('Password changed!'));
-		this.$.userForm.refresh();
-	}
-	
-	,onPassInfoClick() {
-		this.$.passwordInfo.show();
-	}
-});
-
diff --git a/forms/account/conf/locale/ca.yml b/forms/account/conf/locale/ca.yml
deleted file mode 100644
index 7fb9a5fa..00000000
--- a/forms/account/conf/locale/ca.yml
+++ /dev/null
@@ -1,26 +0,0 @@
-Configuration: Configuració
-Personal information: Dades personals
-Username: Nom d'usuari
-Password: Contrasenya
-Email: Correu electrònic
-Display name: Nom a mostrar
-Language: Idioma
-Billing: Facturació
-Receive invoices by email: Rebre factures per correu electrònic
-Old password: Contrasenya antiga
-New password: Nova contrasenya
-Repeat password: Repetir contrasenya
-Requirements: Requisits
-Modify: Modificar
-Password requirements: Requisits de contrasenya
-characters long: caràcters de longitud
-alphabetic characters: caràcters alfabètics
-capital letters: majúscules
-digits: dígits
-symbols: símbols
-Password changed!: Contrasenya modificada!
-Password doesn't meet the requirements: ''
-Passwords doesn't match: Les contrasenyes no coincideixen!
-Passwords empty: Les contrasenyes en blanc
-Addresses: Adreces
-Change password: Canvia la contrasenya
diff --git a/forms/account/conf/locale/en.yml b/forms/account/conf/locale/en.yml
deleted file mode 100644
index c88631be..00000000
--- a/forms/account/conf/locale/en.yml
+++ /dev/null
@@ -1,26 +0,0 @@
-Configuration: Configuration
-Personal information: Personal information
-Username: Username
-Password: Password
-Email: Email
-Display name: Display name
-Language: Language
-Billing: Billing
-Receive invoices by email: Receive invoices by email
-Old password: Old password
-New password: New password
-Repeat password: Repeat password
-Requirements: Requirements
-Modify: Modify
-Password requirements: Password requirements
-characters long: characters long
-alphabetic characters: alphabetic characters
-capital letters: capital letters
-digits: digits
-symbols: 'symbols. Ej: $%&.'
-Password changed!: Password changed!
-Password doesn't meet the requirements: 'Password doesn''t meet the requirements, press info button for more details'
-Passwords doesn't match: Passwords doesn't match
-Passwords empty: Passwords empty
-Addresses: Addresses
-Change password: Change password
diff --git a/forms/account/conf/locale/es.yml b/forms/account/conf/locale/es.yml
deleted file mode 100644
index 3012d755..00000000
--- a/forms/account/conf/locale/es.yml
+++ /dev/null
@@ -1,28 +0,0 @@
-Configuration: Configuración
-Personal information: Datos personales
-Username: Nombre de usuario
-Password: Contraseña
-Email: Correo electrónico
-Display name: Nombre a mostrar
-Language: Idioma
-Billing: Facturación
-Receive invoices by email: Recibir facturas por correo electrónico
-Old password: Contaseña antigua
-New password: Nueva contraseña
-Repeat password: Repetir contraseña
-Requirements: Requisitos
-Modify: Modificar
-Password requirements: Requisitos de constraseña
-characters long: carácteres de longitud
-alphabetic characters: carácteres alfabéticos
-capital letters: letras mayúsculas
-digits: dígitos
-symbols: 'símbolos. Ej: $%&.'
-Password changed!: ¡Contraseña modificada!
-Password doesn't meet the requirements: >-
-  La nueva contraseña no reune los requisitos de seguridad necesarios, pulsa en
-  info para más detalle
-Passwords doesn't match: ¡Las contraseñas no coinciden!
-Passwords empty: Contraseña vacía
-Addresses: Direcciones
-Change password: Cambiar contraseña
diff --git a/forms/account/conf/locale/fr.yml b/forms/account/conf/locale/fr.yml
deleted file mode 100644
index 6ae14ca8..00000000
--- a/forms/account/conf/locale/fr.yml
+++ /dev/null
@@ -1,26 +0,0 @@
-Configuration: Configuration
-Personal information: Informations personnelles
-Username: Utilisateur
-Password: Mot de passe
-Email: Courriel
-Display name: Nom à afficher
-Language: Langage
-Billing: Facturation
-Receive invoices by email: Recevoir des factures par e-mail
-Old password: Ancien mot de passe
-New password: Nouveau mot de passe
-Repeat password: Répéter le mot de passe
-Requirements: Exigences
-Modify: Modifier
-Password requirements: Mot de passe exigences
-characters long: Longs caractères
-alphabetic characters: les caractères alphabétiques
-capital letters: lettres majuscules
-digits: chiffres
-symbols: 'symboles. Ej: $%&.'
-Password changed!: Mot de passe modifié!
-Password doesn't meet the requirements: ''
-Passwords doesn't match: Les mots de passe ne correspondent pas!
-Passwords empty: ''
-Addresses: Adresses
-Change password: Changer le mot de passe
diff --git a/forms/account/conf/locale/pt.yml b/forms/account/conf/locale/pt.yml
deleted file mode 100644
index 05e6ae40..00000000
--- a/forms/account/conf/locale/pt.yml
+++ /dev/null
@@ -1,26 +0,0 @@
-Configuration: Configuração
-Personal information: Dados pessoais
-Username: Nome de usuario
-Password: Palavra-passe
-Email: E-Mail
-Display name: Nome para mostrar
-Language: Idioma
-Billing: Facturação
-Receive invoices by email: Receber facturas por e-mail
-Old password: Palavra-passe antiga
-New password: Nova Palavra-passe
-Repeat password: Repetir Palavra-passe
-Requirements: Requisitos
-Modify: Modificar
-Password requirements: Requisitos de Palavra-passe
-characters long: caracteres
-alphabetic characters: caracteres alfabéticos
-capital letters: letras maiúsculas
-digits: dígitos
-symbols: 'símbolos. Ej: $%&.'
-Password changed!: Palavra-passe Modificada!
-Password doesn't meet the requirements: Palavra-passe não atende aos requisitos
-Passwords doesn't match: As Palavras-Passe não coincidem!
-Passwords empty: Palavra-passe vazia
-Addresses: Moradas
-Change password: Mudar Palavra-passe
diff --git a/forms/account/conf/style.scss b/forms/account/conf/style.scss
deleted file mode 100644
index 13dbdcf8..00000000
--- a/forms/account/conf/style.scss
+++ /dev/null
@@ -1,4 +0,0 @@
-
-.pass-info ul {
-	list-style-type: none;
-}
diff --git a/forms/account/conf/ui.xml b/forms/account/conf/ui.xml
deleted file mode 100644
index cc60d89a..00000000
--- a/forms/account/conf/ui.xml
+++ /dev/null
@@ -1,135 +0,0 @@
-<vn>
-<vn-group>
-	<db-form v-model="passwordForm">
-		<db-model property="model">
-			SELECT length, nAlpha, nUpper, nDigits, nPunct
-				FROM account.userPassword
-		</db-model>
-	</db-form>
-	<db-form id="user-form">
-		<db-model property="model" id="user-model" updatable="true">
-			SELECT u.id, u.name, u.email, u.nickname,
-					u.lang, c.isToBeMailed, c.id clientFk
-				FROM account.myUser u
-					LEFT JOIN myClient c
-						ON u.id = c.id
-		</db-model>
-	</db-form>
-</vn-group>
-<div id="title">
-	<h1><t>Configuration</t></h1>
-</div>
-<div id="actions">
-	<htk-bar-button
-		icon="place"
-		tip="_Addresses"
-		on-click="hash.setAll({form: 'account/address-list'})"/>
-	<htk-bar-button
-		icon="lock_reset"
-		tip="_Change password"
-		on-click="this.onPassChangeClick()"/>
-</div>
-<div id="form" class="conf">
-	<div class="form box vn-w-sm vn-pa-lg">
-		<h5 class="vn-mb-md">
-			<t>Personal information</t>
-		</h5>
-		<div class="form-group">
-			<htk-entry
-				placeholder="_Username"
-				disabled="true"
-				form="user-form"
-				column="name"/>
-		</div>
-		<div class="form-group">
-			<htk-entry
-				placeholder="_Email"
-				form="user-form"
-				column="email">
-			</htk-entry>
-		</div>
-		<div class="form-group">
-			<htk-entry
-				placeholder="_Display name"
-				form="user-form"
-				column="nickname"/>
-		</div>
-		<div class="form-group">
-			<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"/>
-				<t>Receive invoices by email</t>
-			</label>
-		</div>
-	</div>
-</div>
-<htk-popup
-	id="change-password"
-	modal="true">
-	<div property="child-node" class="htk-dialog vn-w-xs vn-pa-lg">
-		<div class="form">
-			<h5 class="vn-mb-md">
-				<t>Change password</t>
-			</h5>
-			<input
-				id="old-password"
-				type="password"
-				placeholder="_Old password"/>
-			<input
-				id="new-password"
-				type="password"
-				placeholder="_New password"/>
-			<input
-				id="repeat-password"
-				type="password"
-				placeholder="_Repeat password"/>
-		</div>
-		<div class="button-bar">
-			<button class="thin" on-click="this.onPassModifyClick()">
-				<t>Modify</t>
-			</button>
-			<button class="thin" on-click="this.onPassInfoClick()">
-				<t>Requirements</t>
-			</button>
-			<div class="clear"/>
-		</div>
-	</div>
-</htk-popup>
-<htk-popup
-	id="password-info"
-	modal="true">
-	<div property="child-node" class="htk-dialog pass-info vn-w-xs vn-pa-lg">
-		<h5 class="vn-mb-md">
-			<t>Password requirements</t>
-		</h5>
-		<ul>
-			<li>
-				{{passwordForm.length}} <t>characters long</t>
-			</li>
-			<li>
-				{{passwordForm.nAlpha}} <t>alphabetic characters</t>
-			</li>
-			<li>
-				{{passwordForm.nUpper}} <t>capital letters</t>
-			</li>
-			<li>
-				{{passwordForm.nDigits}} <t>digits</t>
-			</li>
-			<li>
-				{{passwordForm.nPunct}} <t>symbols</t>
-			</li>
-		</ul>
-	</div>
-</htk-popup>
-</vn>
diff --git a/forms/admin/access-log/index.js b/forms/admin/access-log/index.js
deleted file mode 100644
index 36552d4f..00000000
--- a/forms/admin/access-log/index.js
+++ /dev/null
@@ -1,7 +0,0 @@
-import './style.scss';
-
-export default new Class({
-	Extends: Hedera.Form,
-	Template: require('./ui.xml')
-});
-
diff --git a/forms/admin/access-log/locale/ca.yml b/forms/admin/access-log/locale/ca.yml
deleted file mode 100644
index 94f2c89f..00000000
--- a/forms/admin/access-log/locale/ca.yml
+++ /dev/null
@@ -1,11 +0,0 @@
-AccessLog: Registre d'accessos
-'UserNumber:': 'N d''usuari:'
-'User:': 'Usuari:'
-'Phone:': 'Telèfon:'
-'Mobile:': 'Mòbil:'
-Access: Accés
-OS: SO
-Browser: Navegador
-Version: Versió
-Javascript: Javascript
-Cookies: Cookies
diff --git a/forms/admin/access-log/locale/en.yml b/forms/admin/access-log/locale/en.yml
deleted file mode 100644
index 7a975465..00000000
--- a/forms/admin/access-log/locale/en.yml
+++ /dev/null
@@ -1,11 +0,0 @@
-AccessLog: Access log
-'UserNumber:': 'User Number:'
-'User:': 'User:'
-'Phone:': 'Phone:'
-'Mobile:': 'Mobile:'
-Access: Access
-OS: OS
-Browser: Browser
-Version: Version
-Javascript: Javascript
-Cookies: Cookies
diff --git a/forms/admin/access-log/locale/es.yml b/forms/admin/access-log/locale/es.yml
deleted file mode 100644
index dad42443..00000000
--- a/forms/admin/access-log/locale/es.yml
+++ /dev/null
@@ -1,11 +0,0 @@
-AccessLog: Registro de accesos
-'UserNumber:': 'Nº usuario:'
-'User:': 'Usuario:'
-'Phone:': 'Teléfono:'
-'Mobile:': 'Móvil:'
-Access: Acceso
-OS: SO
-Browser: Navegador
-Version: Versión
-Javascript: Javascript
-Cookies: Cookies
diff --git a/forms/admin/access-log/locale/fr.yml b/forms/admin/access-log/locale/fr.yml
deleted file mode 100644
index ff1f58b6..00000000
--- a/forms/admin/access-log/locale/fr.yml
+++ /dev/null
@@ -1,11 +0,0 @@
-AccessLog: Fiche d'accès
-'UserNumber:': 'Numéro utilisateur:'
-'User:': 'Utilisateur:'
-'Phone:': 'Téléphone:'
-'Mobile:': 'Portable:'
-Access: Accès
-OS: OS
-Browser: Navigateur
-Version: Version
-Javascript: Javascript
-Cookies: Cookies
diff --git a/forms/admin/access-log/locale/pt.yml b/forms/admin/access-log/locale/pt.yml
deleted file mode 100644
index eb457dc8..00000000
--- a/forms/admin/access-log/locale/pt.yml
+++ /dev/null
@@ -1,11 +0,0 @@
-AccessLog: Registro de acessos
-'UserNumber:': 'Nº utilizador:'
-'User:': 'Utilizador:'
-'Phone:': 'Telefone:'
-'Mobile:': 'Telemóvel:'
-Access: Acceso
-OS: OS
-Browser: Navegador
-Version: Versão
-Javascript: Javascript
-Cookies: Cookies
diff --git a/forms/admin/access-log/style.scss b/forms/admin/access-log/style.scss
deleted file mode 100644
index 17e52e14..00000000
--- a/forms/admin/access-log/style.scss
+++ /dev/null
@@ -1,12 +0,0 @@
-
-.access-log .form > p {
-	font-size: 1.2rem;
-	margin: .1em 0;
-}
-
-/* List */
-
-.access-log .htk-list {
-	margin-top: 16px;
-}
-
diff --git a/forms/admin/access-log/ui.xml b/forms/admin/access-log/ui.xml
deleted file mode 100644
index ebe24628..00000000
--- a/forms/admin/access-log/ui.xml
+++ /dev/null
@@ -1,50 +0,0 @@
-<vn>
-<vn-group>
-	<db-form v-model="user">
-		<db-model property="model" lot="hash">
-			SELECT u.id, u.name user, u.nickname, u.email, c.phone, r.name role
-				FROM account.user u
-					JOIN account.role r ON r.id = u.role
-					LEFT JOIN vn.client c ON c.id = u.id 
-				WHERE u.id = #user
-		</db-model>
-	</db-form>
-</vn-group>
-<div id="title">
-	<h1><t>AccessLog</t></h1>
-</div>
-<div id="form" class="access-log">
-	<div class="box vn-w-xs vn-pa-lg">
-		<div class="form">
-			<h4>{{user.nickname}}</h4>
-			<p>#{{user.id}} - {{user.user}}</p>
-			<p>{{user.role}}</p>
-			<p>{{user.email}}</p>
-			<p>{{user.phone}}</p>
-		</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>
-</vn>
diff --git a/forms/admin/connections/index.js b/forms/admin/connections/index.js
deleted file mode 100644
index dd2c5c59..00000000
--- a/forms/admin/connections/index.js
+++ /dev/null
@@ -1,33 +0,0 @@
-import './style.scss';
-
-export default new Class({
-	Extends: Hedera.Form,
-	Template: require('./ui.xml')
-	
-	,_timeoutId: null
-
-	,onModelStatusChange() {
-		if (!this.$.sessions.ready)
-			return;
-
-		if (this._timeoutId)
-			clearTimeout(this._timeoutId);
-			
-		this._timeoutId = setTimeout(
-			() => this.$.sessions.refresh(), 60000);
-	}
-	
-	,deactivate() {
-		clearTimeout(this._timeoutId);
-	}
-
-	,async onChangeUserClick(userName) {
-		await this.gui.supplantUser(userName);
-		this.hash.setAll({form: 'ecomerce/orders'});
-	}
-	
-	,sessionsFunc() {
-		return 1;
-	}
-});
-
diff --git a/forms/admin/connections/locale/ca.yml b/forms/admin/connections/locale/ca.yml
deleted file mode 100644
index 25b19fd7..00000000
--- a/forms/admin/connections/locale/ca.yml
+++ /dev/null
@@ -1,4 +0,0 @@
-Connections: Connexions
-Refresh: Actualitzar
-Visits: Visites
-connections: connexions
diff --git a/forms/admin/connections/locale/en.yml b/forms/admin/connections/locale/en.yml
deleted file mode 100644
index 8547d70a..00000000
--- a/forms/admin/connections/locale/en.yml
+++ /dev/null
@@ -1,4 +0,0 @@
-Connections: Connections
-Refresh: Refresh
-Visits: Visits
-connections: connections
diff --git a/forms/admin/connections/locale/es.yml b/forms/admin/connections/locale/es.yml
deleted file mode 100644
index 6c514d0d..00000000
--- a/forms/admin/connections/locale/es.yml
+++ /dev/null
@@ -1,4 +0,0 @@
-Connections: Conexiones
-Refresh: Actualizar
-Visits: Visitas
-connections: conexiones
diff --git a/forms/admin/connections/locale/fr.yml b/forms/admin/connections/locale/fr.yml
deleted file mode 100644
index 8fdf9e00..00000000
--- a/forms/admin/connections/locale/fr.yml
+++ /dev/null
@@ -1,4 +0,0 @@
-Connections: Connexions
-Refresh: Actualiser
-Visits: Visites
-connections: connexions
diff --git a/forms/admin/connections/locale/mn.yml b/forms/admin/connections/locale/mn.yml
deleted file mode 100644
index 9746c720..00000000
--- a/forms/admin/connections/locale/mn.yml
+++ /dev/null
@@ -1,4 +0,0 @@
-Connections: холболт
-Refresh: Сэргээх
-Visits: уулзалт
-connections: холболт
diff --git a/forms/admin/connections/locale/pt.yml b/forms/admin/connections/locale/pt.yml
deleted file mode 100644
index 33a1e5c1..00000000
--- a/forms/admin/connections/locale/pt.yml
+++ /dev/null
@@ -1,4 +0,0 @@
-Connections: Conexões
-Refresh: actualização
-Visits: Visualizações
-connections: conexões
diff --git a/forms/admin/connections/style.scss b/forms/admin/connections/style.scss
deleted file mode 100644
index de549ebd..00000000
--- a/forms/admin/connections/style.scss
+++ /dev/null
@@ -1,9 +0,0 @@
-
-.action-bar .connections-sum {
-	padding: .4em;
-	background-color: #1e88e5;
-	border-radius: .1em;
-	text-overflow: ellipsis;
-	white-space: nowrap;
-	overflow: hidden;
-}
diff --git a/forms/admin/connections/ui.xml b/forms/admin/connections/ui.xml
deleted file mode 100644
index 487938fa..00000000
--- a/forms/admin/connections/ui.xml
+++ /dev/null
@@ -1,63 +0,0 @@
-<vn>
-<div id="title">
-	<h1><t>Connections</t></h1>
-</div>
-<div id="actions">
-	<htk-bar-button
-		icon="refresh"
-		tip="_Refresh"
-		on-click="sessions.refresh()"/>
-	<div class="connections-sum">
-		<htk-text>
-			<db-calc-sum
-				property="param"
-				model="sessions"
-				func="sessionsFunc"/>
-		</htk-text> 
-		<t>connections</t>
-	</div>
-</div>
-<div id="form" class="connections">
-	<htk-repeater form-id="iter" class="box htk-list vn-w-xs">
-		<db-model
-			property="model"
-			id="sessions"
-			on-status-changed="this.onModelStatusChange()">
-			SELECT vu.userFk userId, vu.stamp, u.nickname, s.lastUpdate, 
-					a.platform, a.browser, a.version, u.name user
-				FROM userSession s
-					JOIN visitUser vu ON vu.id = s.userVisitFk
-					JOIN visitAccess ac ON ac.id = vu.accessFk
-					JOIN visitAgent a ON a.id = ac.agentFk
-					JOIN visit v ON v.id = a.visitFk
-					JOIN account.user u ON u.id = vu.userFk
-				ORDER BY lastUpdate DESC
-		</db-model>
-		<custom>
-			<a class="item"
-				href="{{`#!form=admin/access-log&amp;user=${iter.userId}`}}"
-				title="_Access log">
-				<div class="content">
-					<p class="important">
-						{{iter.nickname}}
-					</p>
-					<p>
-						{{Vn.Value.format(iter.stamp, '%a, %T')}} - 
-						{{Vn.Value.format(iter.lastUpdate, '%T')}}
-					</p>
-					<p>
-						{{iter.platform}} - {{iter.browser}} {{iter.version}}
-					</p>
-				</div>
-				<div class="actions"
-					on-click="$event.preventDefault()">
-					<htk-button
-						tip="_Supplant user"
-						icon="supervisor_account"
-						on-click="this.onChangeUserClick(iter.user)"/>
-				</div>
-			</a>
-		</custom>
-	</htk-repeater>
-</div>
-</vn>
diff --git a/forms/admin/items/index.js b/forms/admin/items/index.js
deleted file mode 100644
index 39a6049c..00000000
--- a/forms/admin/items/index.js
+++ /dev/null
@@ -1,10 +0,0 @@
-import './style.scss';
-
-export default new Class({
-	Extends: Hedera.Form,
-	Template: require('./ui.xml'),
-	
-	activate() {	
-		this.$.items.setInfo('i', 'item', 'vn', ['id']);
-	}
-});
diff --git a/forms/admin/items/locale/ca.yml b/forms/admin/items/locale/ca.yml
deleted file mode 100644
index 28be78e9..00000000
--- a/forms/admin/items/locale/ca.yml
+++ /dev/null
@@ -1,2 +0,0 @@
-Items: Artícles
-Enter a search term: Introdueix un terme de cerca
diff --git a/forms/admin/items/locale/en.yml b/forms/admin/items/locale/en.yml
deleted file mode 100644
index c7e9edd8..00000000
--- a/forms/admin/items/locale/en.yml
+++ /dev/null
@@ -1,2 +0,0 @@
-Items: Items
-Enter a search term: Enter a search term
diff --git a/forms/admin/items/locale/es.yml b/forms/admin/items/locale/es.yml
deleted file mode 100644
index 23757015..00000000
--- a/forms/admin/items/locale/es.yml
+++ /dev/null
@@ -1,2 +0,0 @@
-Items: Artículos
-Enter a search term: Introduce un término de búsqueda
diff --git a/forms/admin/items/locale/fr.yml b/forms/admin/items/locale/fr.yml
deleted file mode 100644
index 47d12ed7..00000000
--- a/forms/admin/items/locale/fr.yml
+++ /dev/null
@@ -1,2 +0,0 @@
-Items: Articles
-Enter a search term: Entrez un terme de recherche
diff --git a/forms/admin/items/locale/pt.yml b/forms/admin/items/locale/pt.yml
deleted file mode 100644
index d44892ac..00000000
--- a/forms/admin/items/locale/pt.yml
+++ /dev/null
@@ -1,2 +0,0 @@
-Items: Ítens
-Enter a search term: Digite um termo de pesquisa
diff --git a/forms/admin/items/style.scss b/forms/admin/items/style.scss
deleted file mode 100644
index e9914e1a..00000000
--- a/forms/admin/items/style.scss
+++ /dev/null
@@ -1,6 +0,0 @@
-
-.items .item .photo {
-	border-radius: 10px;
-	height: 80px;
-	width: 80px;
-}
diff --git a/forms/admin/items/ui.xml b/forms/admin/items/ui.xml
deleted file mode 100644
index 9dd869ba..00000000
--- a/forms/admin/items/ui.xml
+++ /dev/null
@@ -1,57 +0,0 @@
-<vn>
-<div id="title">
-	<h1><t>Items</t></h1>
-</div>
-<div id="actions">
-	<htk-search-entry form="hash" column="search"/>
-</div>
-<div id="form" class="items">
-	<htk-repeater 
-		class="htk-list rows box vn-w-xs"
-		form-id="iter"
-		empty-message="_Enter a search term">
-		<db-model property="model" id="items" lot="hash">
-			SELECT i.id, i.longName, i.size, i.category,
-					i.value5, i.value6, i.value7,
-					i.image, im.updated
-				FROM vn.item i
-					LEFT JOIN image im
-						ON im.collectionFk = 'catalog'
-						AND im.name = i.image
-				WHERE i.longName LIKE CONCAT('%', #search, '%')
-					OR i.id = #search
-				ORDER BY i.longName LIMIT 50
-		</db-model>
-		<custom>
-			<div class="item">
-				<div class="side vn-mr-md">
-					<htk-image
-						form="$iter"
-						column="image"
-						stamp-column="updated"
-						class="photo"
-						directory="catalog"
-						subdir="200x200"
-						full-dir="1600x900"
-						editable="true"
-						conn="conn"/>
-				</div>
-				<div class="content">
-					<p class="important">
-						{{iter.longName}}
-					</p>
-					<p class="tags">
-						{{iter.value5}} {{iter.value6}} {{iter.value7}}
-					</p>
-					<p>
-						{{iter.id}}
-					</p>
-					<p>
-						{{iter.image}}
-					</p>
-				</div>
-			</div>
-		</custom>
-	</htk-repeater>
-</div>
-</vn>
diff --git a/forms/admin/links/index.js b/forms/admin/links/index.js
deleted file mode 100644
index 36552d4f..00000000
--- a/forms/admin/links/index.js
+++ /dev/null
@@ -1,7 +0,0 @@
-import './style.scss';
-
-export default new Class({
-	Extends: Hedera.Form,
-	Template: require('./ui.xml')
-});
-
diff --git a/forms/admin/links/locale/ca.yml b/forms/admin/links/locale/ca.yml
deleted file mode 100644
index efd56c6e..00000000
--- a/forms/admin/links/locale/ca.yml
+++ /dev/null
@@ -1,3 +0,0 @@
-ControlPanel: Panell de control
-Module: Mòdul
-Description: Descripció
diff --git a/forms/admin/links/locale/en.yml b/forms/admin/links/locale/en.yml
deleted file mode 100644
index c4763aae..00000000
--- a/forms/admin/links/locale/en.yml
+++ /dev/null
@@ -1,3 +0,0 @@
-ControlPanel: Control panel
-Module: Module
-Description: Description
diff --git a/forms/admin/links/locale/es.yml b/forms/admin/links/locale/es.yml
deleted file mode 100644
index 91314eab..00000000
--- a/forms/admin/links/locale/es.yml
+++ /dev/null
@@ -1,3 +0,0 @@
-ControlPanel: Panel de control
-Module: Módulo
-Description: Descripción
diff --git a/forms/admin/links/locale/fr.yml b/forms/admin/links/locale/fr.yml
deleted file mode 100644
index 53fd0f17..00000000
--- a/forms/admin/links/locale/fr.yml
+++ /dev/null
@@ -1,3 +0,0 @@
-ControlPanel: Panneau de configuration
-Module: Module
-Description: Description
diff --git a/forms/admin/links/locale/pt.yml b/forms/admin/links/locale/pt.yml
deleted file mode 100644
index f53680aa..00000000
--- a/forms/admin/links/locale/pt.yml
+++ /dev/null
@@ -1,3 +0,0 @@
-ControlPanel: Painel de controle
-Module: Módulo
-Description: Descrição
diff --git a/forms/admin/links/style.scss b/forms/admin/links/style.scss
deleted file mode 100644
index 4ec8fa2c..00000000
--- a/forms/admin/links/style.scss
+++ /dev/null
@@ -1,50 +0,0 @@
-
-.cpanel .items > div {
-	max-width: 900px;
-	display: flex;
-	flex-wrap: wrap;
-	justify-content: center;
-	gap: 16px;
-	margin: 0 auto;
-}
-.cpanel .item {
-	display: flex;
-	flex-direction: column;
-	align-items: center;
-	margin: 0;
-	width: 140px;
-	padding: 15px;
-	text-align: center;
-	transition: background-color 250ms ease-out;
-}
-.cpanel .item:hover {
-	background-color: rgba(1, 1, 1, 0.05);
-}
-.cpanel .item > .htk-image {
-	display: flex;
-	justify-content: center;
-	align-items: center;
-	margin: 0;
-	float: left;
-	height: 80px;
-}
-.cpanel .item > .htk-image > img {
-	max-height: 60px;
-	max-width: 60px;
-	padding: 0;
-}
-.cpanel .item > h6 {
-	flex: none;
-	margin: .1em 0;
-	font-size: .9rem;
-	text-overflow: ellipsis;
-	white-space: nowrap;
-	overflow: hidden;
-}
-.cpanel .item > .text-secondary {
-	flex: none;
-	margin: 0;
-	font-size: .8rem;
-	height: 40px;
-	overflow: hidden;
-}
diff --git a/forms/admin/links/ui.xml b/forms/admin/links/ui.xml
deleted file mode 100644
index c5e166c9..00000000
--- a/forms/admin/links/ui.xml
+++ /dev/null
@@ -1,31 +0,0 @@
-<vn>
-<div id="title">
-	<h1><t>ControlPanel</t></h1>
-</div>
-<div id="form" class="cpanel">
-	<htk-repeater form-id="iter" class="items">
-		<db-model property="model">
-			<custom>
-				SELECT image, name, description, link FROM link
-					ORDER BY name
-			</custom>
-		</db-model>
-		<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>
-</vn>
diff --git a/forms/admin/photos/index.js b/forms/admin/photos/index.js
deleted file mode 100644
index 97ff838e..00000000
--- a/forms/admin/photos/index.js
+++ /dev/null
@@ -1,201 +0,0 @@
-import './style.scss';
-
-var Status = {
-	 NONE      : 0
-	,WAITING   : 1
-	,UPLOADING : 2
-	,UPLOADED  : 3
-};
-
-export default new Class({
-	Extends: Hedera.Form,
-	Template: require('./ui.xml')
-
-	,filesData: []
-	,uploadCount: 0
-	,isUploading: false
-
-	,activate() {
-		this.$.schema.value = 'catalog';
-	}
-
-	,addFiles(files) {
-		if (!files)
-			return;
-
-		for (var i = 0; i < files.length; i++)
-			this.addFile(files[i]);
-	}
-
-	,addFile(file) {
-		var doc = document;
-		var li = doc.createElement('div');
-
-		var div = doc.createElement('div');
-		div.className = 'thumb';
-		li.appendChild(div);
-
-		var thumb = doc.createElement('img');
-		thumb.file = file;
-		div.appendChild(thumb);
-
-		var reader = new FileReader();
-		reader.onload = function(e) {
-			thumb.src = e.target.result; 
-		};
-		reader.readAsDataURL(file);
-
-		var name = doc.createElement('input');
-		name.type = 'text';
-		name.value = getFileName(file.name);
-		li.appendChild(name);
-
-		var statusNode = doc.createElement('div');
-		statusNode.className = 'status';
-		li.appendChild(statusNode);
-
-		var fileData = {
-			li: li,
-			file: file,
-			name: name,
-			statusNode: statusNode
-		};
-
-		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'));
-	}
-
-	,async onUploadClick() {
-		if (this.isUploading) return;
-	
-		const uploadQueue = [];
-		let hasFiles = false;
-
-		for (const fileData of this.filesData) {
-			if (fileData.status !== Status.NONE) continue;
-			this.setImageStatus(
-				fileData, Status.WAITING, 'cloud_upload', _('Waiting for upload'));
-			fileData.name.disabled = true;
-			uploadQueue.push(fileData);
-			hasFiles = true;
-		}
-
-		if (!hasFiles) {
-			Htk.Toast.showWarning(_('There are no files to upload'));
-			return;
-		}
-
-		this.isUploading = true;
-		let hasErrors = false;
-		
-		for (const fileData of uploadQueue) {
-			this.setImageStatus(
-				fileData, Status.UPLOADING, 'upload', _('Uploading file'));
-
-			const formData = new FormData();
-			formData.append('updateMatching', this.$.updateMatching.value);
-			formData.append('image', fileData.file);
-			formData.append('name', fileData.name.value);
-			formData.append('schema', this.$.schema.value);
-			formData.append('srv', 'json:image/upload');
-
-			try {
-				await this.conn.sendFormData(formData);
-				this.setImageStatus(
-					fileData, Status.UPLOADED, 'cloud_done', _('Image uploaded'));
-			} catch(err) {
-				this.setImageStatus(
-					fileData, Status.NONE, 'error', err.message);
-				fileData.name.disabled = false;
-				hasErrors = true;
-			}
-		}
-
-		this.isUploading = false;
-
-		if (hasErrors)
-			Htk.Toast.showError(_('Some errors happened on upload'));
-		else
-			Htk.Toast.showMessage(_('Upload finished successfully'));
-	}
-
-	,setImageStatus(fileData, status, icon, title) {
-		fileData.status = status;
-
-		var statusNode = fileData.statusNode;
-		Vn.Node.removeChilds(statusNode);
-	
-		var iconNode = new Htk.Icon({name: icon});
-		statusNode.appendChild(iconNode.node);
-		statusNode.title = title ? title : '';
-	}
-
-	,onFileRemove(fileData) {
-		this.$.fileList.removeChild(fileData.li);
-
-		for (var i = 0; i < this.filesData.length; i++)
-		if (this.filesData[i] === fileData) {
-			this.filesData.splice(i, 1);
-			break;
-		}
-	}
-
-	,onClearClick() {
-		this.filesData = [];
-		Vn.Node.removeChilds(this.$.fileList);
-	}
-
-	,onDropzoneClick() {
-		this.$.file.click();
-	}
-
-	,onFileChange() {
-		this.addFiles(this.$.file.files);
-	}
-
-	,onDragEnter() {
-		this.$.dropzone.classList.add('dragover');
-	}
-
-	,onDragLeave() {
-		this.$.dropzone.classList.remove('dragover');
-	}
-
-	,onDragOver(event) {
-		event.preventDefault();
-	}
-
-	,onDragEnd(event) {
-		this.$.dropzone.classList.remove('dragover');
-		event.dataTransfer.clearData();
-	}
-
-	,onDrop(event) {
-		event.preventDefault();
-		this.addFiles(event.dataTransfer.files);
-	}
-});
-
-function getFileName(path) {
-	var barIndex = path.lastIndexOf('/');
-	if (barIndex === -1)
-		barIndex = path.lastIndexOf('\\');
-	if (barIndex === -1)
-		barIndex = 0;
-
-	var dotIndex = path.lastIndexOf('.');
-	if (dotIndex === -1)
-		dotIndex = 0;
-
-	return path.substr(barIndex, dotIndex);
-}
diff --git a/forms/admin/photos/locale/ca.yml b/forms/admin/photos/locale/ca.yml
deleted file mode 100644
index d29fdcb5..00000000
--- a/forms/admin/photos/locale/ca.yml
+++ /dev/null
@@ -1,13 +0,0 @@
-Images: Imatges
-Collection: Col·lecció
-Click or drop files here: Prem o deixa anar els arxius aquí
-Pending upload: Pujada pendent
-Update items with matching id: Actualitzar els elements amb id coincident
-Clear all: Netejar tot
-Upload files: Pujar arxius
-Waiting for upload: Esperant per pujar
-Uploading file: Pujant fitxer
-Image uploaded: Imatge pujada
-Upload finished successfully: Imatges pujades correctament
-Some errors happened on upload: Van ocórrer errors en pujar alguna de les imatges
-There are no files to upload: No s'ha seleccionat arxius per pujar
diff --git a/forms/admin/photos/locale/en.yml b/forms/admin/photos/locale/en.yml
deleted file mode 100644
index dcf9c6e1..00000000
--- a/forms/admin/photos/locale/en.yml
+++ /dev/null
@@ -1,13 +0,0 @@
-Images: Images
-Collection: Collection
-Click or drop files here: Click or drop files here
-Pending upload: Pending upload
-Update items with matching id: Update items with matching id
-Clear all: Clear all
-Upload files: Upload files
-Waiting for upload: Waiting for upload
-Uploading file: Uploading file
-Image uploaded: Image uploaded
-Upload finished successfully: Upload finished successfully
-Some errors happened on upload: Some errors happened on upload
-There are no files to upload: There are no files to upload
diff --git a/forms/admin/photos/locale/es.yml b/forms/admin/photos/locale/es.yml
deleted file mode 100644
index 16ae5ae0..00000000
--- a/forms/admin/photos/locale/es.yml
+++ /dev/null
@@ -1,13 +0,0 @@
-Images: Imágenes
-Collection: Colección
-Click or drop files here: Pulsa o suelta los archivos aquí
-Pending upload: Subida pendiente
-Update items with matching id: Actualizar ítems con id coincidente
-Clear all: Limpiar todo
-Upload files: Subir archivos
-Waiting for upload: Esperando para subir
-Uploading file: Subiendo fichero
-Image uploaded: Imagen subida
-Upload finished successfully: Imágenes subidas correctamente
-Some errors happened on upload: Ocurrieron errores al subir alguna de las imágenes
-There are no files to upload: No se han seleccionado archivos para subir
diff --git a/forms/admin/photos/locale/fr.yml b/forms/admin/photos/locale/fr.yml
deleted file mode 100644
index d86e8e35..00000000
--- a/forms/admin/photos/locale/fr.yml
+++ /dev/null
@@ -1,13 +0,0 @@
-Images: Images
-Collection: Collection
-Click or drop files here: Cliquez ici ou déposer des fichiers
-Pending upload: Hausse en attente
-Update items with matching id: Mettre à jour les éléments avec l'identifiant correspondant
-Clear all: Tout effacer
-Upload files: Upload Files
-Waiting for upload: En attente de télécharger
-Uploading file: Uploader des fichiers
-Image uploaded: Fichier uploadé
-Upload finished successfully: Les images téléchargées correctement
-Some errors happened on upload: Des erreurs sont survenues lors du téléchargement des images
-There are no files to upload: Aucun fichier sélectionné pour télécharger
diff --git a/forms/admin/photos/locale/pt.yml b/forms/admin/photos/locale/pt.yml
deleted file mode 100644
index 57d862a4..00000000
--- a/forms/admin/photos/locale/pt.yml
+++ /dev/null
@@ -1,13 +0,0 @@
-Images: Imagens
-Collection: Coleção
-Click or drop files here: Clique ou solte arquivos aqui
-Pending upload: Ascensão pendente
-Update items with matching id: Atualizar itens com id correspondente
-Clear all: Limpar tudo
-Upload files: Fazer upload de arquivos
-Waiting for upload: Esperando para enviar
-Uploading file: Enviando arquivo
-Image uploaded: Imagem Enviada
-Upload finished successfully: Upload concluído com sucesso
-Some errors happened on upload: Ocorreram erros ao subir alguma das imagens
-There are no files to upload: Não há arquivos selecionados para upload
diff --git a/forms/admin/photos/style.scss b/forms/admin/photos/style.scss
deleted file mode 100644
index 3dbdafad..00000000
--- a/forms/admin/photos/style.scss
+++ /dev/null
@@ -1,81 +0,0 @@
-
-/* Dropzone */
-
-.photos .dropzone {
-	background-color:  white;
-	border-style: dashed;
-	border-radius: .4em;
-	border-color: #2196F3;
-	padding: 2em 1em;
-	text-align: center;
-	color: #666;
-	cursor: pointer;
-}
-.photos .dropzone.dragover {
-	color: #CCC;
-	border-style: solid;
-}
-.photos input[type=file] {
-	display: none;
-}
-
-/* File list */
-
-.photos .file-list {
-	margin-top: 1em;
-}
-.photos .file-list > div {
-	height: 2.5em;
-	display: flex;
-	align-items: center;
-}
-.photos .file-list > div > * {
-	overflow: hidden;
-}
-.photos .file-list .thumb {
-	width: 2em;
-	padding-right: .5em;
-	text-align: center;
-}
-.photos .file-list .thumb > img {
-	max-height: 2em;
-	max-width: 2em;
-	vertical-align: middle;
-}
-.photos .file-list input {
-	flex: 1;
-	min-width: 0;
-}
-.photos .file-list .status {
-	cursor: pointer;
-	width: 1.2em;
-	padding-left: .5em;
-	padding-right: .5em;
-}
-.photos .file-list .status > .htk-icon {
-	display: block;
-}
-.photos .file-list .htk-button {
-	opacity: .2;
-}
-.photos .file-list .htk-button:hover {
-	background-color: transparent;
-	opacity: 1;
-}
-.photos .file-list .htk-button > img {
-	display: block;
-}
-
-/* Footer */
-
-.photos .update-matching {
-	margin-top: 1.5em;
-}
-.photos .footer {
-	margin-top: 1.5em;
-	text-align: center;
-}
-.photos .footer > button {
-	font-size: 1.2rem;
-	margin-left: 1em;
-}
diff --git a/forms/admin/photos/ui.xml b/forms/admin/photos/ui.xml
deleted file mode 100644
index 4a4bb83c..00000000
--- a/forms/admin/photos/ui.xml
+++ /dev/null
@@ -1,50 +0,0 @@
-<vn>
-<div id="title">
-	<h1><t>Images</t></h1>
-</div>
-<div id="form" class="photos">
-	<div class="box form vn-w-sm vn-pa-lg">
-		<div class="form-group">
-			<label><t>Collection</t></label>
-			<htk-combo id="schema">
-				<db-model property="model">
-					<custom>
-						SELECT name, `desc` FROM imageCollection ORDER BY `desc`
-					</custom>
-				</db-model>
-			</htk-combo>
-		</div>
-		<div id="dropzone" class="dropzone"
-			on-dragenter="onDragEnter"
-			on-dragleave="onDragLeave"
-			on-mouseout="onDragLeave"
-			on-dragover="onDragOver"
-			on-drop="onDrop"
-			on-dragend="onDragEnd"
-			on-click="onDropzoneClick">
-			<t>Click or drop files here</t>
-		</div>
-		<input
-			 id="file"
-			 type="file"
-			 multiple="true"
-			 name="image"
-			 on-change="onFileChange"/>
-		<div id="file-list" class="file-list"/>
-		<div class="update-matching">
-			<label>
-				<htk-check id="update-matching" value="true"/>
-				<t>Update items with matching id</t>
-			</label>
-		</div>
-		<div class="footer">
-			<button class="thin" on-click="onClearClick">
-				<t>Clear all</t>
-			</button>
-			<button class="thin" on-click="onUploadClick">
-				<t>Upload files</t>
-			</button>
-		</div>
-	</div>
-</div>
-</vn>
diff --git a/forms/admin/queries/index.js b/forms/admin/queries/index.js
deleted file mode 100644
index 2b87e0ac..00000000
--- a/forms/admin/queries/index.js
+++ /dev/null
@@ -1,93 +0,0 @@
-import './style.scss';
-
-export default new Class({
-	Extends: Hedera.Form,
-	Template: require('./ui.xml')
-	
-	,activate() {
-		this.$.resultIndex.value = 0;
-	}
-	
-	,clean() {
-		if (this._grid) {
-			this.$.gridHolder.removeChild(this._grid.node);
-			this._grid.unref();
-			this._grid = null;
-		}
-	}
-	
-	,onExecuteClick() {
-		this.clean();
-		
-		var model = new Db.Model({
-			conn: this.conn,
-			query: this.$.sql.value,
-			resultIndex: this.$.resultIndex.value,
-			updatable: this.$.updatable.value
-		});
-		model.on('status-changed', this.onModelChange, this);
-	}
-	
-	,onCleanClick() {
-		this.clean();
-	}
-	
-	,onModelChange(model, status) {
-		if (status !== Db.Model.Status.LOADING) {
-			model.disconnect('status-changed', this.onModelChange, this);
-			model.unref();
-		}
-
-		if (status !== Db.Model.Status.READY)
-			return;
-
-		Htk.Toast.showMessage(_('Query executed!'));
-
-		var gridHolder = this.$.gridHolder;
-		
-		if (gridHolder.firstChild)
-			gridHolder.removeChilds(gridHolder.firstChild);
-
-		var grid = new Htk.Grid();
-		
-		var columns = model.columns;
-		
-		for (var i = 0; i < columns.length; i++) {
-			var c = columns[i];
-		
-			switch (c.type) {
-				case Db.Conn.Type.BOOLEAN:
-					var column = new Htk.ColumnCheck();
-					break;
-				case Db.Conn.Type.INTEGER:
-					var column = new Htk.ColumnSpin();
-					break;
-				case Db.Conn.Type.DOUBLE:
-					var column = new Htk.ColumnSpin({digits: 2});
-					break;
-				case Db.Conn.Type.DATE:
-					var column = new Htk.ColumnDate({format: '%a, %e %b %Y'});
-					break;
-				case Db.Conn.Type.DATE_TIME:
-					var column = new Htk.ColumnDate({format: '%a, %e %b %Y, %T'});
-					break;
-				case Db.Conn.Type.STRING:
-				default:
-					var column = new Htk.ColumnText();
-			}
-		
-			column.setProperties({
-				title: c.name,
-				editable: this.$.updatable.value,
-				columnIndex: i
-			});
-			
-			grid.appendColumn(column);
-		}
-		
-		grid.model = model;
-		gridHolder.appendChild(grid.node);
-		this._grid = grid;
-	}
-});
-
diff --git a/forms/admin/queries/locale/ca.yml b/forms/admin/queries/locale/ca.yml
deleted file mode 100644
index ecc96548..00000000
--- a/forms/admin/queries/locale/ca.yml
+++ /dev/null
@@ -1,6 +0,0 @@
-Queries: Consultes
-Execute: Executar
-Clean: Netejar
-SQL query: Consulta SQL
-Updatable: Actualitzable
-Query executed!: Consulta executada!
diff --git a/forms/admin/queries/locale/en.yml b/forms/admin/queries/locale/en.yml
deleted file mode 100644
index b8a3bcdb..00000000
--- a/forms/admin/queries/locale/en.yml
+++ /dev/null
@@ -1,6 +0,0 @@
-Queries: Queries
-Execute: Execute
-Clean: Clean
-SQL query: SQL query
-Updatable: Updatable
-Query executed!: Query executed!
diff --git a/forms/admin/queries/locale/es.yml b/forms/admin/queries/locale/es.yml
deleted file mode 100644
index 3a67c14b..00000000
--- a/forms/admin/queries/locale/es.yml
+++ /dev/null
@@ -1,6 +0,0 @@
-Queries: Consultas
-Execute: Ejecutar
-Clean: Limpiar
-SQL query: Consulta SQL
-Updatable: Actualizable
-Query executed!: ¡Consulta ejecutada!
diff --git a/forms/admin/queries/locale/fr.yml b/forms/admin/queries/locale/fr.yml
deleted file mode 100644
index b8a3bcdb..00000000
--- a/forms/admin/queries/locale/fr.yml
+++ /dev/null
@@ -1,6 +0,0 @@
-Queries: Queries
-Execute: Execute
-Clean: Clean
-SQL query: SQL query
-Updatable: Updatable
-Query executed!: Query executed!
diff --git a/forms/admin/queries/locale/pt.yml b/forms/admin/queries/locale/pt.yml
deleted file mode 100644
index 6556a81f..00000000
--- a/forms/admin/queries/locale/pt.yml
+++ /dev/null
@@ -1,6 +0,0 @@
-Queries: Consultas
-Execute: Executar
-Clean: Limpar
-SQL query: Consulta SQL
-Updatable: Actualizável
-Query executed!: Consulta executada!
diff --git a/forms/admin/queries/style.scss b/forms/admin/queries/style.scss
deleted file mode 100644
index 9b9420ce..00000000
--- a/forms/admin/queries/style.scss
+++ /dev/null
@@ -1,10 +0,0 @@
-
-.queries textarea {
-	display: block;
-	width: 100%;
-	height: 8em;
-}
-.queries .result {
-	margin-top: 1em;
-	overflow: auto;
-}
diff --git a/forms/admin/queries/ui.xml b/forms/admin/queries/ui.xml
deleted file mode 100644
index ab3932bf..00000000
--- a/forms/admin/queries/ui.xml
+++ /dev/null
@@ -1,38 +0,0 @@
-<vn>
-<div id="title">
-	<h1><t>Queries</t></h1>
-</div>
-<div id="actions">
-	<htk-bar-button
-		icon="ok"
-		tip="_Execute"
-		on-click="this.onExecuteClick()"/>
-	<htk-bar-button
-		icon="delete"
-		tip="_Clean"
-		on-click="this.onCleanClick()"/>
-</div>
-<div id="form" class="queries">
-	<div class="box form vn-w-sm vn-pa-lg">
-		<div class="form-group">
-			<label><t>SQL query</t></label>
-			<textarea
-				id="sql"
-				autocorrect="off"
-				autocapitalize="off"
-				spellcheck="false"/>
-		</div>
-		<div class="form-group">
-			<label><t>Result index</t></label>
-			<htk-spin id="result-index"/>
-		</div>
-		<div class="form-group">
-			<label><t>Updatable</t></label>
-			<htk-check id="updatable"/>
-		</div>
-	</div>
-	<div class="box result">
-		<div id="grid-holder"/>
-	</div>
-</div>
-</vn>
diff --git a/forms/admin/users/index.js b/forms/admin/users/index.js
deleted file mode 100644
index 37168668..00000000
--- a/forms/admin/users/index.js
+++ /dev/null
@@ -1,20 +0,0 @@
-import './style.scss';
-
-export default new Class({
-	Extends: Hedera.Form,
-	Template: require('./ui.xml')
-
-	,rendererFunc(scope, form) {
-		var isEnabled = form.$.active
-		scope.$.disabled.style.display = isEnabled ?
-			'none' : 'block';
-		scope.$.impersonate.node.style.display = isEnabled ?
-			'block' : 'none';
-	}
-
-	,async onChangeUserClick(userName) {
-		await this.gui.supplantUser(userName);
-		this.hash.setAll({form: 'ecomerce/orders'});
-	}
-});
-
diff --git a/forms/admin/users/locale/ca.yml b/forms/admin/users/locale/ca.yml
deleted file mode 100644
index 243425a2..00000000
--- a/forms/admin/users/locale/ca.yml
+++ /dev/null
@@ -1,4 +0,0 @@
-User management: Gestió d'usuaris
-Disabled: Deshabilitat
-Impersonate user: Suplantar usuari
-Access log: Registre d'accessos
diff --git a/forms/admin/users/locale/en.yml b/forms/admin/users/locale/en.yml
deleted file mode 100644
index 3786cc93..00000000
--- a/forms/admin/users/locale/en.yml
+++ /dev/null
@@ -1,4 +0,0 @@
-User management: User management
-Disabled: Disabled
-Impersonate user: Impersonate user
-Access log: Access log
diff --git a/forms/admin/users/locale/es.yml b/forms/admin/users/locale/es.yml
deleted file mode 100644
index c3679194..00000000
--- a/forms/admin/users/locale/es.yml
+++ /dev/null
@@ -1,4 +0,0 @@
-User management: Gestión de usuarios
-Disabled: Desactivado
-Impersonate user: Suplantar usuario
-Access log: Registro de accesos
diff --git a/forms/admin/users/locale/fr.yml b/forms/admin/users/locale/fr.yml
deleted file mode 100644
index a59f6320..00000000
--- a/forms/admin/users/locale/fr.yml
+++ /dev/null
@@ -1,4 +0,0 @@
-User management: Gestion des utilisateurs
-Disabled: Désactivé
-Impersonate user: Accès utilisateur
-Access log: Journal des accès
diff --git a/forms/admin/users/locale/pt.yml b/forms/admin/users/locale/pt.yml
deleted file mode 100644
index 84423836..00000000
--- a/forms/admin/users/locale/pt.yml
+++ /dev/null
@@ -1,4 +0,0 @@
-User management: Gestão de usuarios
-Disabled: Desativado
-Impersonate user: Suplantar usuario
-Access log: Registro de acessos
diff --git a/forms/admin/users/style.scss b/forms/admin/users/style.scss
deleted file mode 100644
index 586a0d0e..00000000
--- a/forms/admin/users/style.scss
+++ /dev/null
@@ -1,11 +0,0 @@
-
-.users-box.item > .actions {
-	display: flex;
-}
-.users-box .disabled {
-	color: white;
-	background-color: #F66;
-	border-radius: .2em;
-	padding: .3em;
-	font-size: .8em;
-}
diff --git a/forms/admin/users/ui.xml b/forms/admin/users/ui.xml
deleted file mode 100644
index 922e88ff..00000000
--- a/forms/admin/users/ui.xml
+++ /dev/null
@@ -1,48 +0,0 @@
-<vn>
-<div id="title">
-	<h1><t>User management</t></h1>
-</div>
-<div id="actions">
-	<htk-search-entry form="hash" column="user"/>
-</div>
-<div id="form" class="users">
-	<htk-repeater
-		form-id="iter"
-		renderer="rendererFunc"
-		class="htk-list box vn-w-xs">
-		<db-model property="model" lot="hash">
-			SELECT u.id, u.name, u.nickname, u.active
-				FROM account.user u
-				WHERE u.name LIKE CONCAT('%', #user, '%')
-					OR u.nickname LIKE CONCAT('%', #user, '%')
-					OR u.id = #user
-				ORDER BY u.name LIMIT 200
-		</db-model>
-		<custom>
-			<a class="users-box item"
-				href="{{`#!form=admin/access-log&amp;user=${iter.id}`}}"
-				title="_Access log">
-				<div class="content">
-					<p class="important">
-						{{iter.nickname}}
-					</p>
-					<p>
-						#{{iter.id}} - {{iter.name}}
-					</p>
-				</div>
-				<div class="actions"
-					on-click="$event.preventDefault()">
-					<span id="disabled" class="disabled">
-						<t>Disabled</t>
-					</span>
-					<htk-button
-						id="impersonate"
-						icon="supervisor_account"
-						tip="_Impersonate user"
-						on-click="this.onChangeUserClick(iter.name)"/>
-				</div>
-			</a>
-		</custom>
-	</htk-repeater>
-</div>
-</vn>
diff --git a/forms/admin/visits/index.js b/forms/admin/visits/index.js
deleted file mode 100644
index 78f093d8..00000000
--- a/forms/admin/visits/index.js
+++ /dev/null
@@ -1,15 +0,0 @@
-import './style.scss';
-
-export default new Class({
-	Extends: Hedera.Form,
-	Template: require('./ui.xml')
-
-	,activate() {
-		if (!this.hash.$.to)
-			this.hash.assign({
-				from: new Date(),
-				to: new Date()
-			});
-	}
-});
-
diff --git a/forms/admin/visits/locale/ca.yml b/forms/admin/visits/locale/ca.yml
deleted file mode 100644
index b34fdf41..00000000
--- a/forms/admin/visits/locale/ca.yml
+++ /dev/null
@@ -1,9 +0,0 @@
-Visits: Visites
-Refresh: Actualitzar
-Connections: Connexions
-From: Desde
-To: Fins
-Select date interval: Selecciona un interval de dates
-visits: visites
-news: noves
-'%a, %e %b %Y at %T': '%a, %e %b %Y a les %T'
diff --git a/forms/admin/visits/locale/en.yml b/forms/admin/visits/locale/en.yml
deleted file mode 100644
index 379e2005..00000000
--- a/forms/admin/visits/locale/en.yml
+++ /dev/null
@@ -1,9 +0,0 @@
-Visits: Visits
-Refresh: Refresh
-Connections: Connections
-From: From
-To: To
-Select date interval: Select date interval
-visits: visits
-news: news
-'%a, %e %b %Y at %T': '%a, %e %b %Y at %T'
diff --git a/forms/admin/visits/locale/es.yml b/forms/admin/visits/locale/es.yml
deleted file mode 100644
index 9b96d380..00000000
--- a/forms/admin/visits/locale/es.yml
+++ /dev/null
@@ -1,9 +0,0 @@
-Visits: Visitas
-Refresh: Actualizar
-Connections: Conexiones
-From: Desde
-To: Hasta
-Select date interval: Selecciona un intérvalo de fechas
-visits: visitas
-news: nuevas
-'%a, %e %b %Y at %T': '%a, %e %b %Y a las %T'
diff --git a/forms/admin/visits/locale/fr.yml b/forms/admin/visits/locale/fr.yml
deleted file mode 100644
index 7b40a3b4..00000000
--- a/forms/admin/visits/locale/fr.yml
+++ /dev/null
@@ -1,9 +0,0 @@
-Visits: Visites
-Refresh: Actualiser
-Connections: Connexions
-From: À partir de
-To: À
-Select date interval: Sélectionnez une plage de dates
-visits: visites
-news: nouvelles
-'%a, %e %b %Y at %T': '%a, %e %b %Y à %T'
diff --git a/forms/admin/visits/locale/mn.yml b/forms/admin/visits/locale/mn.yml
deleted file mode 100644
index c5c98ac4..00000000
--- a/forms/admin/visits/locale/mn.yml
+++ /dev/null
@@ -1,9 +0,0 @@
-Visits: уулзалт
-Refresh: Сэргээх
-Connections: холболт
-From: эхлэн
-To: нь
-Select date interval: Сонгох огноо интервал
-visits: уулзалт
-news: мэдээ
-'%a, %e %b %Y at %T': '%a, %e %b %Y нь %T'
diff --git a/forms/admin/visits/locale/pt.yml b/forms/admin/visits/locale/pt.yml
deleted file mode 100644
index c5fcc6a7..00000000
--- a/forms/admin/visits/locale/pt.yml
+++ /dev/null
@@ -1,9 +0,0 @@
-Visits: Visualizações
-Refresh: Actualização
-Connections: Conexões
-From: Desde
-To: Até
-Select date interval: Selecciona un intérvalo de datas
-visits: Visualizações
-news: novas
-'%a, %e %b %Y at %T': '%a, %e %b %Y em %T'
diff --git a/forms/admin/visits/style.scss b/forms/admin/visits/style.scss
deleted file mode 100644
index 2808d3a1..00000000
--- a/forms/admin/visits/style.scss
+++ /dev/null
@@ -1,12 +0,0 @@
-
-.visits .box {
-	margin-bottom: 16px;
-}
-.visits .box:last-child {
-	margin-bottom: 0;
-}
-.visits .summary p {
-	font-size: 1.4rem;
-	margin: 0;
-	text-align: right;
-}
diff --git a/forms/admin/visits/ui.xml b/forms/admin/visits/ui.xml
deleted file mode 100644
index 8baf101b..00000000
--- a/forms/admin/visits/ui.xml
+++ /dev/null
@@ -1,90 +0,0 @@
-<vn>
-<vn-lot-query id="params">
-	<vn-spec name="from" type="Date"/>
-	<vn-spec name="to" type="Date"/>
-</vn-lot-query>
-<div id="title">
-	<h1><t>Visits</t></h1>
-</div>
-<div id="actions">
-	<htk-bar-button
-		icon="refresh"
-		tip="_Refresh"
-		on-click="visits.refresh()"/>
-	<htk-bar-button
-		icon="visibility"
-		tip="_Connections"
-		on-click="this.hash.setAll({form: 'admin/connections'})"/>
-</div>
-<div id="form" class="visits">
-	<div class="vn-w-xs">
-		<div class="form vn-pa-lg box">
-			<div class="form-group">
-				<label><t>From</t></label>
-				<htk-date-chooser
-					form="params"
-					column="from"/>
-			</div>
-			<div class="form-group">
-				<label><t>To</t></label>
-				<htk-date-chooser
-					form="params"
-					column="to"/>
-			</div>
-		</div>
-		<div class="summary vn-pa-lg box">
-			<p>
-				<htk-text>
-					<db-calc-sum
-						property="param"
-						model="visits"
-						column-name="visits"/>
-				</htk-text> 
-				<t>visits</t>,
-				<htk-text>
-					<db-calc-sum
-						property="param"
-						model="visits"
-						column-name="newVisits"/>
-				</htk-text> 
-				<t>news</t>
-			</p>
-		</div>
-		<htk-repeater
-			class="box htk-list"
-			form-id="iter"
-			empty-message="_Select date interval">
-			<db-model property="model" id="visits" lot="params">
-				SELECT browser,
-						MIN(CAST(version AS DECIMAL(4,1))) minVersion,
-						MAX(CAST(version AS DECIMAL(4,1))) maxVersion,
-						MAX(c.stamp) lastVisit,
-						COUNT(DISTINCT c.id) visits,
-						SUM(a.firstAccessFk = c.id AND v.firstAgentFk = a.id) newVisits
-					FROM visitUser e
-						JOIN visitAccess c ON c.id = e.accessFk
-						JOIN visitAgent a ON a.id = c.agentFk
-						JOIN visit v ON v.id = a.visitFk
-					WHERE c.stamp BETWEEN TIMESTAMP(#from,'00:00:00') AND TIMESTAMP(#to,'23:59:59')
-					GROUP BY browser ORDER BY visits DESC
-			</db-model>
-			<custom>
-				<div class="item">
-					<div class="content">
-						<p class="important">
-							{{iter.browser}} {{iter.minVersion}} - {{iter.maxVersion}}
-						</p>
-						<p>
-							{{iter.visits}} <t>visits</t>, 
-							{{iter.newVisits}} <t>news</t>
-						</p>
-						<p>
-							{{Vn.Value.format(iter.lastVisit, _('%a, %e %b %Y at %T'))}}
-						</p>
-					</div>
-				</div>
-			</custom>
-		</htk-repeater>
-	</div>
-</div>
-</vn>
diff --git a/forms/agencies/packages/index.js b/forms/agencies/packages/index.js
deleted file mode 100644
index 8c8d3238..00000000
--- a/forms/agencies/packages/index.js
+++ /dev/null
@@ -1,14 +0,0 @@
-import './style.scss';
-
-export default new Class({
-	Extends: Hedera.Form,
-	Template: require('./ui.xml'),
-	
-	onShowClick(column, agencyId) {
-		this.hash.setAll({
-			form: 'agencies/provinces',
-			agency: agencyId
-		});
-	}
-});
-
diff --git a/forms/agencies/packages/locale/ca.yml b/forms/agencies/packages/locale/ca.yml
deleted file mode 100644
index 12cbbe67..00000000
--- a/forms/agencies/packages/locale/ca.yml
+++ /dev/null
@@ -1,6 +0,0 @@
-ListByAgency: Paquets per agència
-ShowByProvince: Mostrar desglose per província
-Agency: Agència
-Exps: Exps.
-Bundles: Paquets
-Prevision: Prev.
diff --git a/forms/agencies/packages/locale/en.yml b/forms/agencies/packages/locale/en.yml
deleted file mode 100644
index 651dcfae..00000000
--- a/forms/agencies/packages/locale/en.yml
+++ /dev/null
@@ -1,6 +0,0 @@
-ListByAgency: Bundles by agency
-ShowByProvince: Show breakdown by province
-Agency: Agency
-Exps: Exps.
-Bundles: Bundles
-Prevision: Prev.
diff --git a/forms/agencies/packages/locale/es.yml b/forms/agencies/packages/locale/es.yml
deleted file mode 100644
index 4532c554..00000000
--- a/forms/agencies/packages/locale/es.yml
+++ /dev/null
@@ -1,6 +0,0 @@
-ListByAgency: Bultos por agencia
-ShowByProvince: Mostrar desglose por provincia
-Agency: Agencia
-Exps: Exps.
-Bundles: Bultos
-Prevision: Prev.
diff --git a/forms/agencies/packages/locale/fr.yml b/forms/agencies/packages/locale/fr.yml
deleted file mode 100644
index a1999077..00000000
--- a/forms/agencies/packages/locale/fr.yml
+++ /dev/null
@@ -1,6 +0,0 @@
-ListByAgency: Liste par agence
-ShowByProvince: Montrer par province
-Agency: Agence
-Exps: Expéditeur
-Bundles: Cartons
-Prevision: Prévision
diff --git a/forms/agencies/packages/locale/pt.yml b/forms/agencies/packages/locale/pt.yml
deleted file mode 100644
index ae5bef89..00000000
--- a/forms/agencies/packages/locale/pt.yml
+++ /dev/null
@@ -1,6 +0,0 @@
-ListByAgency: Bultos por agencia
-ShowByProvince: Mostrar desglosse por Distrito
-Agency: Agencia
-Exps: Exps.
-Bundles: Bultos
-Prevision: Prev.
diff --git a/forms/agencies/packages/style.scss b/forms/agencies/packages/style.scss
deleted file mode 100644
index e69de29b..00000000
diff --git a/forms/agencies/packages/ui.xml b/forms/agencies/packages/ui.xml
deleted file mode 100644
index 866bab74..00000000
--- a/forms/agencies/packages/ui.xml
+++ /dev/null
@@ -1,25 +0,0 @@
-<vn>
-<div id="title">
-	<h1><t>ListByAgency</t></h1>
-</div>
-<div id="form" class="packages">
-	<div class="box vn-w-sm">
-		<htk-grid>
-			<db-model property="model">
-				<custom>
-					CALL vn2008.agencia_volume ()
-				</custom>
-			</db-model>
-			<htk-column-button
-				column="agency_id"
-				icon="search"
-				tip="_ShowByProvince"
-				on-clicked="onShowClick"/>
-			<htk-column-text title="_Agency" column="Agencia"/>
-			<htk-column-spin title="_Exps" column="expediciones"/>
-			<htk-column-spin title="_Bundles" column="Bultos"/>
-			<htk-column-spin title="_Prevision" column="Faltan"/>
-		</htk-grid>
-	</div>
-</div>
-</vn>
diff --git a/forms/agencies/provinces/index.js b/forms/agencies/provinces/index.js
deleted file mode 100644
index 36552d4f..00000000
--- a/forms/agencies/provinces/index.js
+++ /dev/null
@@ -1,7 +0,0 @@
-import './style.scss';
-
-export default new Class({
-	Extends: Hedera.Form,
-	Template: require('./ui.xml')
-});
-
diff --git a/forms/agencies/provinces/locale/ca.yml b/forms/agencies/provinces/locale/ca.yml
deleted file mode 100644
index c46b70c3..00000000
--- a/forms/agencies/provinces/locale/ca.yml
+++ /dev/null
@@ -1,6 +0,0 @@
-ByProvince: Desglose per província
-Return: Tornar
-SelectAgency: Selecciona una agència al llistat de l'esquerra
-Province: Província
-Expeditions: Exps.
-Left: Falten
diff --git a/forms/agencies/provinces/locale/en.yml b/forms/agencies/provinces/locale/en.yml
deleted file mode 100644
index f72295d0..00000000
--- a/forms/agencies/provinces/locale/en.yml
+++ /dev/null
@@ -1,6 +0,0 @@
-ByProvince: Breakdown by province
-Return: Return
-SelectAgency: Select an agency
-Province: Province
-Expeditions: Exps.
-Left: Left
diff --git a/forms/agencies/provinces/locale/es.yml b/forms/agencies/provinces/locale/es.yml
deleted file mode 100644
index f04d3d2e..00000000
--- a/forms/agencies/provinces/locale/es.yml
+++ /dev/null
@@ -1,6 +0,0 @@
-ByProvince: Desglose por provincia
-Return: Volver
-SelectAgency: Selecciona una agencia
-Province: Provincia
-Expeditions: Exps.
-Left: Faltan
diff --git a/forms/agencies/provinces/locale/fr.yml b/forms/agencies/provinces/locale/fr.yml
deleted file mode 100644
index e289766b..00000000
--- a/forms/agencies/provinces/locale/fr.yml
+++ /dev/null
@@ -1,6 +0,0 @@
-ByProvince: Par province
-Return: Retour
-SelectAgency: Sélectionnez une agence
-Province: Province
-Expeditions: Expéditions
-Left: Restant
diff --git a/forms/agencies/provinces/locale/pt.yml b/forms/agencies/provinces/locale/pt.yml
deleted file mode 100644
index 815c8d5c..00000000
--- a/forms/agencies/provinces/locale/pt.yml
+++ /dev/null
@@ -1,6 +0,0 @@
-ByProvince: Desglosse por Distritos
-Return: Voltar
-SelectAgency: Seleccione uma agência
-Province: Distrito
-Expeditions: Exps.
-Left: Faltam
diff --git a/forms/agencies/provinces/style.scss b/forms/agencies/provinces/style.scss
deleted file mode 100644
index e69de29b..00000000
diff --git a/forms/agencies/provinces/ui.xml b/forms/agencies/provinces/ui.xml
deleted file mode 100644
index 46fd7c04..00000000
--- a/forms/agencies/provinces/ui.xml
+++ /dev/null
@@ -1,18 +0,0 @@
-<vn>
-<div id="title">
-	<h1><t>ByProvince</t></h1>
-</div>
-<div id="form" class="provinces vn-w-sm">
-	<div class="box">
-		<htk-grid>
-			<db-model property="model" lot="hash">
-				CALL vn2008.desglose_volume(#agency)
-			</db-model>
-			<htk-column-text title="_Province" column="Provincia"/>
-			<htk-column-spin title="_Expeditions" column="expediciones"/>
-			<htk-column-spin title="_Bundles" column="Bultos"/>
-			<htk-column-spin title="_Left" column="Prevision"/>
-		</htk-grid>
-	</div>
-</div>
-</vn>
diff --git a/forms/cms/about/image/2_control.png b/forms/cms/about/image/2_control.png
deleted file mode 100644
index a184fc47..00000000
Binary files a/forms/cms/about/image/2_control.png and /dev/null differ
diff --git a/forms/cms/about/image/4_control.png b/forms/cms/about/image/4_control.png
deleted file mode 100644
index c5690c75..00000000
Binary files a/forms/cms/about/image/4_control.png and /dev/null differ
diff --git a/forms/cms/about/image/agencies.png b/forms/cms/about/image/agencies.png
deleted file mode 100644
index 7e4f8b9b..00000000
Binary files a/forms/cms/about/image/agencies.png and /dev/null differ
diff --git a/forms/cms/about/image/auction.png b/forms/cms/about/image/auction.png
deleted file mode 100644
index ae8099c3..00000000
Binary files a/forms/cms/about/image/auction.png and /dev/null differ
diff --git a/forms/cms/about/image/commercial.png b/forms/cms/about/image/commercial.png
deleted file mode 100644
index 3046e843..00000000
Binary files a/forms/cms/about/image/commercial.png and /dev/null differ
diff --git a/forms/cms/about/image/courses.png b/forms/cms/about/image/courses.png
deleted file mode 100644
index c951b85e..00000000
Binary files a/forms/cms/about/image/courses.png and /dev/null differ
diff --git a/forms/cms/about/image/dealer.png b/forms/cms/about/image/dealer.png
deleted file mode 100644
index 4ac64400..00000000
Binary files a/forms/cms/about/image/dealer.png and /dev/null differ
diff --git a/forms/cms/about/image/differentiates_us.png b/forms/cms/about/image/differentiates_us.png
deleted file mode 100644
index bd9727f1..00000000
Binary files a/forms/cms/about/image/differentiates_us.png and /dev/null differ
diff --git a/forms/cms/about/image/fit.png b/forms/cms/about/image/fit.png
deleted file mode 100644
index 93e36a53..00000000
Binary files a/forms/cms/about/image/fit.png and /dev/null differ
diff --git a/forms/cms/about/image/glass.png b/forms/cms/about/image/glass.png
deleted file mode 100644
index 170e1d08..00000000
Binary files a/forms/cms/about/image/glass.png and /dev/null differ
diff --git a/forms/cms/about/image/goods_receive.png b/forms/cms/about/image/goods_receive.png
deleted file mode 100644
index bb16c098..00000000
Binary files a/forms/cms/about/image/goods_receive.png and /dev/null differ
diff --git a/forms/cms/about/image/goods_transport.png b/forms/cms/about/image/goods_transport.png
deleted file mode 100644
index 72f906b9..00000000
Binary files a/forms/cms/about/image/goods_transport.png and /dev/null differ
diff --git a/forms/cms/about/image/palletizing.png b/forms/cms/about/image/palletizing.png
deleted file mode 100644
index 12be2c70..00000000
Binary files a/forms/cms/about/image/palletizing.png and /dev/null differ
diff --git a/forms/cms/about/image/producers.png b/forms/cms/about/image/producers.png
deleted file mode 100644
index c6d05c7d..00000000
Binary files a/forms/cms/about/image/producers.png and /dev/null differ
diff --git a/forms/cms/about/image/store.png b/forms/cms/about/image/store.png
deleted file mode 100644
index a280989e..00000000
Binary files a/forms/cms/about/image/store.png and /dev/null differ
diff --git a/forms/cms/about/image/summary.png b/forms/cms/about/image/summary.png
deleted file mode 100644
index 5532302f..00000000
Binary files a/forms/cms/about/image/summary.png and /dev/null differ
diff --git a/forms/cms/about/image/trailer.png b/forms/cms/about/image/trailer.png
deleted file mode 100644
index f5f15eb8..00000000
Binary files a/forms/cms/about/image/trailer.png and /dev/null differ
diff --git a/forms/cms/about/image/training.png b/forms/cms/about/image/training.png
deleted file mode 100644
index 334b4c1c..00000000
Binary files a/forms/cms/about/image/training.png and /dev/null differ
diff --git a/forms/cms/about/image/web.png b/forms/cms/about/image/web.png
deleted file mode 100644
index 261625ea..00000000
Binary files a/forms/cms/about/image/web.png and /dev/null differ
diff --git a/forms/cms/about/image/youtube.png b/forms/cms/about/image/youtube.png
deleted file mode 100644
index 6147c272..00000000
Binary files a/forms/cms/about/image/youtube.png and /dev/null differ
diff --git a/forms/cms/about/index.js b/forms/cms/about/index.js
deleted file mode 100644
index 36552d4f..00000000
--- a/forms/cms/about/index.js
+++ /dev/null
@@ -1,7 +0,0 @@
-import './style.scss';
-
-export default new Class({
-	Extends: Hedera.Form,
-	Template: require('./ui.xml')
-});
-
diff --git a/forms/cms/about/locale/ca.yml b/forms/cms/about/locale/ca.yml
deleted file mode 100644
index b5e58a70..00000000
--- a/forms/cms/about/locale/ca.yml
+++ /dev/null
@@ -1,103 +0,0 @@
-QualityAndVariety: 'Qualitat, varietat i servei'
-MaximumFreshness: >-
-  Verdnatura t'ofereix un producte amb la màxima frescor garantida, gràcies als
-  seus recepcions diàries de flor i planta procedents d'Holanda, Sud-amèrica, o
-  des del mateix productor.
-SquareMeters: Més de 13.000m d'instal·lacions
-AboutRealms: 'Amb flor tallada, verds, artificial i complements'
-AboutLocation: >-
-  Assentats a València, Madrid, Barcelona, Holanda i França, oferim venda
-  directa a les nostres instal·lacions i repartiment a tot Espanya mitjançant
-  servei propi o agència.
-PurchaseThroughWeb: >-
-  Compra a través de la nostra web i rep la teva comanda còmodament a la teua
-  floristeria. ¡En menys de 24 hores!
-WhatMakeUsDifferent: Que ens fa diferents?
-DesignVariety: >-
-  La varietat en el disseny, la qualitat dels materials utilitzats i el nostre
-  servei de repartiment, et garanteixen un mostrari de gènere dinàmic, sempre
-  fresc i atractiu.
-AdaptToYourNeeds: >-
-  Verdnatura s'adapta a les necessitats de cada client oferint un ampli ventall
-  de productes, garantit sempre.
-TheBestQuality: La millor qualitat al millor preu. Sense oblidar mai el disseny.
-AtYourService: Estem al teu servei
-BuyersAndTraders: >-
-  9 compradors especialitzats i els nostres 20 comercials t'assessoraran en tot
-  el que necessitis.
-Verdnatura training: Verdnatura formació
-GoodTraining: >-
-  En Verdnatura sabem que una bona formació és imprescindible per al
-  desenvolupament òptim de qualsevol activitat, i com no, també la de florista.
-SpecialTrainingPrices: >-
-  Perquè el pressupost d'una escola no repercuteixi en la qualitat de la teva
-  formació, col·laborem amb una política de preus especials per a totes aquelles
-  escoles que ho sol·licitin realitzar cursos a les nostres instal·lacions de
-  Verdnatura Silla.
-YoutubeChannel: >-
-  I no et perdis els vídeos de Canal Verdnatura a Youtube. On trobaràs un munt
-  de consells molt interessants sobre el maneig de la flor.
-HowWeWork: Com treballem?
-FirstQualityControl: 1º control de qualitat
-SecondQualityControl: 2º control de qualitat
-ThirdQualityControl: 3º control de qualitat
-FourthQualityControl: 4º control de qualitat
-AalsmeerAuction: >-
-  A les 5: 00h, els nostres responsables de compres adquireixen, en la subhasta
-  d'Aalsmeer i Noaldwijk, el gènere que el productor ha collit el dia anterior.
-BeforeAuction: >-
-  Després de la seva compra, aquest gènere entra ràpidament en Verdnatura
-  Holland BV, la nostra empresa de Flora Holland, en Aalsmeer.
-DirectlyFromProviders: >-
-  A més de comprar a través de la subhasta Holandesa, també comprem directament
-  a productors de Colòmbia, Equador, Tailàndia, Malàisia, Àfrica i Austràlia.
-  Aquests productes són supervisats directament pels nostres delegats de compra
-  situats a cada zona. Aquesta mercaderia viatjarà a Amsterdam, sotmesa a un
-  procés de Vaacum i en menys de dues hores des del seu aterratge, estarà a les
-  nostres instal·lacions d'Aalsmeer.
-GoodsDischarge: >-
-  A les 7: 00h els nostres companys de Aalsmeer comencen a rebre la mercaderia
-  comprada, passant un primer control de qualitat, i donant-la d'alta al nostre
-  estoc. Ja està disponible per als nostres clients a la web.
-GoodsTravel: >-
-  La mercaderia viatja durant dia i mig a camions amb compartiments estancs a
-  temperatures diferents, de manera que no es trenqui la cadena de fred i viatge
-  en les millors condicions.
-GoodsReception: >-
-  A la recepció de la mercaderia el responsable de la seva compra revisa l'estat
-  en què arriba, acceptant-la o rebutjant-la segons el cas, es descarrega en
-  fred i ràpidament entra a la nostra càmera.
-CustomerOrders: >-
-  Els nostres clients poden fer les seves comandes a través del web, per telèfon
-  o venint directament a les nostres instal·lacions. Tenim un equip de
-  comercials especialitzats que t'assessorarà en la teva compra i que
-  t'informarà de les novetats i articles que puguin ser del teu interès, de
-  manera que la teva compra s'ajusti a les teves necessitats i quedis totalment
-  satisfet.
-AfterOrder: >-
-  Un cop realitzada la comanda, passa al departament de producció. Durant la
-  preparació d'aquest es realitza un nou control de qualitat (el tercer) en què
-  es rebutjarà la mercaderia deficient.
-BuyerControl: >-
-  Quant es finalitza la preparació, es realitza un nou control (el quart) on un
-  especialista conta i revisa l'estat dels productes. En cas que aquests no
-  compleixin amb els estàndards de qualitat exigits els rebutja i els
-  substitueix per els adequats.
-EmbeddedSection: >-
-  Seguidament es porta a la secció de encaixat, on la comanda és condicionada
-  per la seva correcta entrega. Cada tipus de lliurament requereix un mètode de
-  encaixat adequat perquè el gènere viatge protegit i arribi al client en
-  perfectes condicions.
-AfterEmbedAgency: >-
-  Quant el producte ha estat encaixat s'emmagatzema de nou a la cambra fins a la
-  seva sortida per agència o per repartiment propi, rebent el client, en 24h en
-  el cas de l'agència o el mateix dia en el cas del repartiment, còmodament al
-  seu domicili .
-FreshnessGuaranteed: >-
-  Aquesta forma de treball garanteix la major frescor per la rapidesa dels
-  processos i pel manteniment de la cadena de fred desde la compra fins a la
-  seva recepció pel nostre client.
-AboutSummary: >-
-  75 persones repartides per tothom perquè el nostre client tingui el més ampli
-  catàleg del sector, la flor més fresca, la planta més innovadora, els
-  complements més actuals, i el servei més ràpid possible.
diff --git a/forms/cms/about/locale/en.yml b/forms/cms/about/locale/en.yml
deleted file mode 100644
index bef2b510..00000000
--- a/forms/cms/about/locale/en.yml
+++ /dev/null
@@ -1,92 +0,0 @@
-QualityAndVariety: 'Quality, variety and service'
-MaximumFreshness: >-
-  Verdnatura offers a product guarantee maximum freshness thanks to their daily
-  flowers and plants from Holland, South America, or from the same producer
-  receptions.
-SquareMeters: 'Over facilities 13,000m'
-AboutRealms: 'With cut flowers, green, artificial and accessories'
-AboutLocation: >-
-  Settled in Valencia, Madrid, Barcelona, Holland and France, we offer direct
-  sales in our facilities and distribution throughout Spain by own service or
-  agency.
-PurchaseThroughWeb: >-
-  Purchase through our website and receive your order comfortably in your
-  florist.In less than 24 hours!
-WhatMakeUsDifferent: What makes us different?
-DesignVariety: >-
-  The variety in design, quality of materials used and our service delivery,
-  will provide a showcase of dynamic genre, always fresh and appealing.
-AdaptToYourNeeds: >-
-  Verdnatura adapts to the needs of each customer by offering a wide range of
-  products, always guaranteed.
-TheBestQuality: The best quality at the best price. Without forgetting the design.
-AtYourService: We are at your service
-BuyersAndTraders: 9 specialized trade buyers and our 20 advise you on everything you need.
-Verdnatura training: Verdnatura training
-GoodTraining: >-
-  In Verdnatura we know that a good education is essential for the optimal
-  development of any activity, and of course, also the florist.
-SpecialTrainingPrices: >-
-  For the school budget does not affect the quality of your training, we work
-  with special pricing policy for all schools that request it take courses in
-  our facilities Verdnatura chair.
-YoutubeChannel: >-
-  And do not miss Verdnatura videos on Youtube Channel. Where you'll find plenty
-  of interesting tips on handling of the flower.
-HowWeWork: How we work?
-FirstQualityControl: First quality control
-SecondQualityControl: Second quality control
-ThirdQualityControl: Third quality control
-FourthQualityControl: Fourth quality control
-AalsmeerAuction: >-
-  At 5: 00h, our purchasing managers acquire, in the auction of Aalsmeer and
-  Noaldwijk, gender, the producer has reaped the previous day.
-BeforeAuction: >-
-  After purchase, the genre quickly enters Verdnatura Holland BV, our company
-  Flora Holland in Aalsmeer.
-DirectlyFromProviders: >-
-  Besides buying through the Dutch auction, we buy directly from producers
-  Colombia, Ecuador, Thailand, Malaysia, Africa and Australia. These products
-  are directly supervised by our delegates Purchase located in each area. This
-  merchandise will travel to Amsterdam, subjected to a process Vaacum and in
-  less than two hours after landing, you will be at our facility in Aalsmeer.
-GoodsDischarge: >-
-  At 7: 00h our fellow Aalsmeer start receiving the purchased goods, having a
-  first quality control, and creating it in stock. Now available for our
-  customers on the web.
-GoodsTravel: >-
-  The goods travel for a day and a half trucks watertight compartments at
-  different temperatures, so that the cold chain is not broken trip in the best
-  conditions.
-GoodsReception: >-
-  Upon receipt of the merchandise responsible for the purchase reviewed state
-  that arrives, accepting or rejecting it as appropriate, it discharged cold and
-  quickly enters our camera.
-CustomerOrders: >-
-  Our customers can place their orders via the web, by phone or coming directly
-  to our facilities. We have a team of specialized commercial advise you on your
-  purchase and inform you the latest news and articles that may be of interest,
-  so that your purchase meets your needs and stay totally satisfied.
-AfterOrder: >-
-  Once placed the order, turn to the production department. During the
-  preparation of this new quality control (third) in which the poor will be
-  discarded merchandise it is made.
-BuyerControl: >-
-  As the preparation is completed, a new control (fourth) where a specialist
-  account is made and check the status of products. If they do not meet the
-  quality standards required rejects and replaces the right.
-EmbeddedSection: >-
-  Then takes embedded section, where the order is suitable for proper delivery.
-  Each type of delivery requires a method suitable for embedded gender protected
-  books and reaches the customer in perfect condition.
-AfterEmbedAgency: >-
-  Once the product has been fitted it is stored again in the chamber until they
-  leave by agency or own deal, receiving the customer within 24 hours in the
-  case of the agency or the same day for the cast, comfortably at home .
-FreshnessGuaranteed: >-
-  This way of working ensures freshness by rapid processes and maintaining the
-  cold chain from purchase to receipt by our customer.
-AboutSummary: >-
-  75 people spread over almost everybody so that our client has the broadest
-  portfolio in the industry, coolest flower, plant newest, latest accessories,
-  and fastest service possible.
diff --git a/forms/cms/about/locale/es.yml b/forms/cms/about/locale/es.yml
deleted file mode 100644
index 3b56cec5..00000000
--- a/forms/cms/about/locale/es.yml
+++ /dev/null
@@ -1,102 +0,0 @@
-QualityAndVariety: 'Calidad, variedad y servicio'
-MaximumFreshness: >-
-  Verdnatura te ofrece un producto con la máxima frescura garantizada, gracias a
-  sus recepciones diarias de flor y planta procedentes de Holanda, Sudamérica, o
-  desde el mismo productor.
-SquareMeters: Más de 13.000m de instalaciones
-AboutRealms: 'Con flor cortada, verdes, artificial y complementos'
-AboutLocation: >-
-  Asentados en Valencia, Madrid, Barcelona, Holanda y Francia, ofrecemos venta
-  directa en nuestras instalaciones y reparto a toda España mediante servicio
-  propio o agencia.
-PurchaseThroughWeb: >-
-  Compra a través de nuestra web y recibe tu pedido cómodamente en tu
-  floristería. ¡En menos de 24 horas!
-WhatMakeUsDifferent: ¿Que nos hace diferentes?
-DesignVariety: >-
-  La variedad en el diseño, la calidad de los materiales utilizados y nuestro
-  servicio de reparto, te garantizan un muestrario de género dinámico, siempre
-  fresco y atractivo.
-AdaptToYourNeeds: >-
-  Verdnatura se adapta a las necesidades de cada cliente ofreciéndote un amplio
-  abanico de productos, garantizado siempre.
-TheBestQuality: La mejor calidad al mejor precio. Sin olvidar nunca el diseño.
-AtYourService: Estamos a tu servicio
-BuyersAndTraders: >-
-  9 compradores especializados y nuestros 20 comerciales te asesorarán en todo
-  lo que necesites.
-Verdnatura training: Verdnatura formación
-GoodTraining: >-
-  En Verdnatura sabemos que una buena formación es imprescindible para el
-  desarrollo óptimo de cualquier actividad, y cómo no, también la de florista.
-SpecialTrainingPrices: >-
-  Para que el presupuesto de una escuela no repercuta en la calidad de tu
-  formación, colaboramos con una política de precios especiales para todas
-  aquellas escuelas que lo soliciten realizar cursos en nuestras instalaciones
-  de Verdnatura Silla.
-YoutubeChannel: >-
-  Y no te pierdas los vídeos de Canal Verdnatura en Youtube. Donde encontrarás
-  un montón de consejos muy interesantes sobre el manejo de la flor.
-HowWeWork: ¿Cómo trabajamos?
-FirstQualityControl: 1º control de calidad
-SecondQualityControl: 2º control de calidad
-ThirdQualityControl: 3º control de calidad
-FourthQualityControl: 4º control de calidad
-AalsmeerAuction: >-
-  A las 5:00h, nuestros responsables de compras adquieren, en la subasta de
-  Aalsmeer y Noaldwijk, el género que el productor ha cosechado el día anterior.
-BeforeAuction: >-
-  Tras su compra, este género entra rápidamente en Verdnatura Holland BV,
-  nuestra empresa de Flora Holland, en Aalsmeer.
-DirectlyFromProviders: >-
-  Además de comprar a través de la subasta Holandesa, también compramos
-  directamente a productores de Colombia, Ecuador, Thailandia, Malasia, África y
-  Australia. Estos productos son supervisados directamente por nuestros
-  delegados de compra ubicados en cada zona. Esta mercancía viajará a Amsterdam,
-  sometida a un proceso de Vaacum y en menos de dos horas desde su aterrizaje,
-  estará en nuestras instalaciones de Aalsmeer.
-GoodsDischarge: >-
-  A las 7:00h nuestros compañeros de Aalsmeer empiezan a recibir la mercancía
-  comprada, pasando un primer control de calidad, y dándola de alta en nuestro
-  stock. Ya está disponible para nuestros clientes en la web.
-GoodsTravel: >-
-  La mercancía viaja durante día y medio en camiones con compartimentos estancos
-  a temperaturas diferentes, de manera que no se rompa la cadena de frío y viaje
-  en las mejores condiciones.
-GoodsReception: >-
-  A la recepción de la mercancía el responsable de su compra revisa el estado en
-  el que llega, aceptándola o rechazándola según el caso, se descarga en frío y
-  rápidamente entra en nuestra cámara.
-CustomerOrders: >-
-  Nuestros clientes pueden hacer sus pedidos a través de la web, por teléfono o
-  viniendo directamente a nuestras instalaciones. Tenemos un equipo de
-  comerciales especializados que te asesorará en tu compra y que te informará de
-  las novedades y artículos que puedan ser de tu interés, de forma que tu compra
-  se ajuste a tus necesidades y quedes totalmente satisfecho.
-AfterOrder: >-
-  Una vez realizado el pedido, pasa al departamento de producción. Durante la
-  preparación de este se realiza un nuevo control de calidad (el tercero) en el
-  que se desechará la mercancía deficiente.
-BuyerControl: >-
-  En cuanto se finaliza la preparación, se realiza un nuevo control (el cuarto)
-  donde un especialista cuenta y revisa el estado de los productos. En caso de
-  que estos no cumplan con los estándares de calidad exigidos los rechaza y los
-  sustituye por los adecuados.
-EmbeddedSection: >-
-  Seguidamente se lleva a la sección de encajado, donde el pedido es
-  acondicionado para su correcta entrega. Cada tipo de entrega requiere un
-  método de encajado adecuado para que el género viaje protegido y llegue al
-  cliente en perfectas condiciones.
-AfterEmbedAgency: >-
-  En cuanto el producto ha sido encajado se almacena de nuevo en la cámara hasta
-  su salida por agencia o por reparto propio, recibiéndolo el cliente, en 24h en
-  el caso de la agencia o el mismo día en el caso del reparto, cómodamente en su
-  domicilio.
-FreshnessGuaranteed: >-
-  Esta forma de trabajo garantiza la mayor frescura por la rapidez los procesos
-  y por el mantenimiento de la cadena de frío desde compra hasta su recepción
-  por nuestro cliente.
-AboutSummary: >-
-  75 personas repartidas por casi todo el mundo para que nuestro cliente tenga
-  el más amplio catálogo del sector, la flor más fresca, la planta más novedosa,
-  los complementos más actuales, y el servicio más rápido posible.
diff --git a/forms/cms/about/locale/fr.yml b/forms/cms/about/locale/fr.yml
deleted file mode 100644
index 83268ec4..00000000
--- a/forms/cms/about/locale/fr.yml
+++ /dev/null
@@ -1,99 +0,0 @@
-QualityAndVariety: 'Qualité, variété et le service'
-MaximumFreshness: >-
-  Verdnatura offre une garantie de produit maximales de fraîcheur grâce à leurs
-  fleurs quotidiens et plantes de Hollande, Amérique du Sud, ou à partir des
-  mêmes réceptions de producteurs.
-SquareMeters: 'Sur des installations 13,000m'
-AboutRealms: 'Avec les fleurs coupées, vert, artificielle et accessoires'
-AboutLocation: >-
-  Installé à Valence, Madrid, Barcelone, la Hollande et la France, offrir des
-  ventes directes dans nos installations et la distribution dans toute l'Espagne
-  par propre service ou organisme.
-PurchaseThroughWeb: >-
-  Achetez sur notre site et recevoir votre commande confortablement dans votre
-  fleuriste. En moins de 24 heures!
-WhatMakeUsDifferent: Qu'est-ce qui nous rend différents?
-DesignVariety: >-
-  La variété dans la conception, la qualité des matériaux utilisés et de notre
-  prestation de service, fournira une vitrine de genre dynamique, toujours frais
-  et attrayant.
-AdaptToYourNeeds: >-
-  Verdnatura adapte aux besoins de chaque client en offrant une large gamme de
-  produits, toujours garanti.
-TheBestQuality: La meilleure qualité au meilleur prix. Sans oublier la conception.
-AtYourService: Nous sommes à votre service
-BuyersAndTraders: >-
-  9 acheteurs commerciaux spécialisés et notre 20 conseillera dans tout ce que
-  vous avez besoin.
-Verdnatura training: Formation Verdnatura
-GoodTraining: >-
-  Dans Verdnatura sait qu'une bonne éducation est essentielle pour le
-  développement optimal de toute activité, et bien sûr, aussi le fleuriste.
-SpecialTrainingPrices: >-
-  Pour le budget d'une école n'a aucun effet sur la qualité de votre formation,
-  travailler avec la politique de tarification spéciale pour toutes les écoles
-  qui le demandent de suivre des cours dans nos installations chaise Verdnatura.
-YoutubeChannel: >-
-  Et ne manquez pas les vidéos Verdnatura sur Youtube Channel. Où vous trouverez
-  beaucoup de conseils intéressants sur la manipulation de la fleur.
-HowWeWork: Comment travaillons-nous?
-FirstQualityControl: QC 1
-SecondQualityControl: QC 2
-ThirdQualityControl: QC 3
-FourthQualityControl: QC 4
-AalsmeerAuction: >-
-  À 5: 00h, nos directeurs d'achat acquièrent, dans la vente aux enchères
-  d'Aalsmeer et Noaldwijk, le sexe, le producteur a récolté la journée
-  précédente.
-BeforeAuction: >-
-  Après l'achat, le genre pénètre rapidement Verdnatura Holland BV, notre
-  société Flora Holland à Aalsmeer.
-DirectlyFromProviders: >-
-  Outre l'achat par l'adjudication à la hollandaise, achète directement auprès
-  des producteurs de la Colombie, l'Equateur, Thaïlande, Malaisie, Afrique et
-  Australie. Ces produits sont directement supervisés par nos délégués achat
-  situés dans chaque zone. Cette marchandise se rendra à Amsterdam, soumis à un
-  processus Vaacum et en moins de deux heures après l'atterrissage, sera dans
-  notre usine de Aalsmeer.
-GoodsDischarge: >-
-  À 7: 00h notre compagnon Aalsmeer commencer à recevoir les marchandises
-  achetées, ayant un premier contrôle de la qualité, et la création en stock.
-  Maintenant disponible pour nos clients sur le web.
-GoodsTravel: >-
-  Les marchandises voyagent pendant un jour et un camion demi compartiments
-  étanches à des températures différentes, de sorte que la chaîne du froid est
-  pas cassé voyage dans les meilleures conditions.
-GoodsReception: >-
-  Dès réception de la marchandise responsable de l'achat Etat examiné qui
-  arrive, d'accepter ou de rejeter le cas échéant, déchargé froid et pénètre
-  rapidement notre caméra.
-CustomerOrders: >-
-  Nos clients peuvent passer leurs commandes via le Web, par téléphone ou venir
-  directement à nos installations. Nous avons une équipe spécialisée de conseil
-  commercial, vous sur votre achat et vous informons les dernières nouvelles et
-  des articles qui peuvent être d'intérêt, pour que votre achat répond à vos
-  besoins et de rester totalement satisfait.
-AfterOrder: >-
-  Une fois placé l'ordre, se tourner vers le département de production. Lors de
-  la préparation de ce nouveau contrôle de la qualité (troisième) dans laquelle
-  les pauvres seront rejetés marchandise est faite.
-BuyerControl: >-
-  Comme la préparation est terminée, un nouveau contrôle (quatrième), où un
-  compte de spécialiste est faite et vérifier l'état des produits. Si elles ne
-  répondent pas aux normes de qualité requises rejets et remplace le droit.
-EmbeddedSection: >-
-  Prend alors la section embarqué, où l'ordre est approprié pour la livraison
-  appropriée. Chaque type de prestation requiert une méthode appropriée pour les
-  livres de genre protégée embarqués et atteint le client en parfait état.
-AfterEmbedAgency: >-
-  Une fois que le produit a été installé il est stocké à nouveau dans la chambre
-  jusqu'à ce qu'ils quittent par agence ou propre affaire, recevoir le client
-  dans les 24 heures dans le cas de l'agence ou le même jour pour le casting,
-  confortablement à la maison.
-FreshnessGuaranteed: >-
-  Cette méthode de travail garantit la fraîcheur par des processus rapides et le
-  maintien de la chaîne du froid, de l'achat à la réception par notre client.
-AboutSummary: >-
-  75 personnes réparties sur presque tout le monde pour que notre client a le
-  plus vaste portefeuille de l'industrie, plus cool fleur, plante récentes, les
-  derniers accessoires, et le service le plus rapide possible.
diff --git a/forms/cms/about/locale/pt.yml b/forms/cms/about/locale/pt.yml
deleted file mode 100644
index 2ab5be0a..00000000
--- a/forms/cms/about/locale/pt.yml
+++ /dev/null
@@ -1,99 +0,0 @@
-QualityAndVariety: 'Qualidade, variedade e serviço'
-MaximumFreshness: >-
-  Verdnatura lhe ofrece um produto com a máxima frescura garantida, graças a
-  suas recepções diárias de flor e planta procedentes de Holanda, América do
-  Sul, ou desde o mesmo produtor.
-SquareMeters: Mais de 13.000m de instalações
-AboutRealms: 'Com flor cortada, verdes, artificial e complementos'
-AboutLocation: >-
-  Asentados em Valencia, Madrid, Barcelona, Holanda e França, oferecemos venta
-  direta em nossas instalações e Entregamos a toda Espanha mediante serviço
-  proprio ou agência.
-PurchaseThroughWeb: Compra a través de nossa web e receba o pedido cômodamente em sua florista.
-WhatMakeUsDifferent: O Que nos faz diferentes?
-DesignVariety: >-
-  A variedade no desenho, a qualidade dos materiais utilizados e nosso serviço
-  de entrega, te garantizam uma amostra de produto dinámico, sempre fresco e
-  atrativo.
-AdaptToYourNeeds: >-
-  Verdnatura se adapta às necessidades de cada cliente oferecendo-te um amplo
-  leque de produtos, garantido sempre.
-TheBestQuality: A melhor qualidade ao melhor preço. Sen esquecer nunca do desenho.
-AtYourService: Estamos a seu serviço
-BuyersAndTraders: >-
-  9 compradores especializados e nossos 20 comerciais te asessorarão em tudo o
-  que necessites.
-Verdnatura training: Verdnatura formação
-GoodTraining: >-
-  Em Verdnatura sabemos que uma boa formação é imprescindível para o
-  desenvolvimento ótimo de qualqer atividade, e como não, também a de florista.
-SpecialTrainingPrices: >-
-  Para que o orçamento de uma escola não repercuta na qualidade da sua formação,
-  colaboramos com uma política de preços especiais para todas aquelas escolas
-  que solicitem realizar cursos em nossas instalações de Verdnatura Silla.
-YoutubeChannel: >-
-  E não perdas os vídeos do Canal Verdnatura em Youtube. Onde vas a encontrar um
-  montão de conselhos muito interessantes sobre o manuseio da flor.
-HowWeWork: Como Trabalhamos?
-FirstQualityControl: 1º controle de qualidade
-SecondQualityControl: 2º controle de qualidade
-ThirdQualityControl: 3º controle de qualidade
-FourthQualityControl: 4º controle de qualidade
-AalsmeerAuction: >-
-  Às 5:00h, nossos responsáveis de compras adquirem, no leilão de Aalsmeer e
-  Noaldwijk, o material que o produtor colheu no dia día anterior.
-BeforeAuction: >-
-  Após sua compra, este material entra rápidamente em Verdnatura Holland BV,
-  nossa empresa de Flora Holland, em Aalsmeer.
-DirectlyFromProviders: >-
-  Além de comprar a través do leilão Holandes, também compramos diretamente a
-  produtores de Colombia, Equador, Thailandia, Malasia, África e Australia.
-  Estes productos são supervisados diretamente por nossos delegados de compra
-  ubicados em cada zona. Esta mercadoria viajará a Amsterdam, submetida a um
-  proceso de Vaacum e em menos de duas horas desde sua aterrizagem, estará em
-  nossas instalações de Aalsmeer.
-GoodsDischarge: >-
-  Às 7:00h nossos companheiros de Aalsmeer começam a receber a mercadoria
-  comprada, passando um primeiro controle de qualidade, e registrando-a em nosso
-  estoque. Já está disponivel para nossos clientes em nossa pagina online.
-GoodsTravel: >-
-  A mercadoria viaja durante um día e meio em camiões com compartimentos
-  herméticos com temperaturas diferentes, de maneira que não se interrompa a
-  cadeia de frío e viaje nas melhores condições.
-GoodsReception: >-
-  Na recepção da mercadoria o responsável da compra revisa o estado em que
-  chega, aceitándo-la ou recuzando-a segundo o caso, se descarrega em frío e
-  rápidamente entra em nossa câmara.
-CustomerOrders: >-
-  Nossos clientes podem fazer seus pedidos a través da pagina web, por telefone
-  ou vindo diretamente a nossas instalações. Temos uma equipa de comerciais
-  especializados que lhe vai a asesorar em sua compra e lhe informará das
-  novidades e ítens que possam ser de seu interesse, de forma que sua compra se
-  ajuste às suas necessidades, e fique totalmente satisfeito.
-AfterOrder: >-
-  Uma vez realizado o pedido, passa ao departamento de produção. Durante a
-  preparação deste, se realiza um novo controle de qualidade (o terceiro), no
-  qual se eliminará a mercadoria deficiente.
-BuyerControl: >-
-  Quando se finaliza a preparação, se realiza um novo controle (o quarto) onde
-  um especialista conta e revisa o estado dos produtos. Em caso de que estes não
-  cumpram com o estandard de qualidade exigidos os recusa e os substitue pelos
-  adequados.
-EmbeddedSection: >-
-  Seguidamente se leva à sessão de encaixado, onde o pedido é acondicionado para
-  sua correta entrega. Cada tipo de entrega requer un método de encaixado
-  adequado para que o produto viaje protegido e chegue ao cliente em perfeitas
-  condições.
-AfterEmbedAgency: >-
-  Quando producto já foi encaixado se armazena de novo na câmara até sua saída
-  por agência ou pelo nosso transporte proprio, recibiéndolo el cliente, em 24h
-  no caso de agência ou no mesmo dia no caso de nosso transporte, cômodamente em
-  sua morada.
-FreshnessGuaranteed: >-
-  Esta forma de trabalho garante a maior frescura pela rapidez dos processos e
-  pela manutenção da cadeia de frio desde a compra até sua recepção por nosso
-  cliente.
-AboutSummary: >-
-  75 pessoas divididas por quase todo o mundo para que nosso cliente tenha o
-  mais amplo catálogo do sector, a flor mais fresca, a planta mais novedosa, os
-  complementos mais actuais e o serviço mais rápido possível.
diff --git a/forms/cms/about/style.scss b/forms/cms/about/style.scss
deleted file mode 100644
index 246230a2..00000000
--- a/forms/cms/about/style.scss
+++ /dev/null
@@ -1,86 +0,0 @@
-
-@media screen and (min-width: 1000px) /* and (max-width: 1399px) */ {
-	.about .cols
-	{
-		column-count: 2;
-		-moz-column-count: 2;
-		-webkit-column-count: 2;
-	}
-}/*
-@media screen and (min-width: 1400px) {
-	.about .cols
-	{
-		column-count: 3;
-		-moz-column-count: 3;
-		-webkit-column-count: 3;
-	}
-}
-@media screen and (min-width: 2000px) {
-	.about .cols
-	{
-		column-count: 4;
-		-moz-column-count: 4;
-		-webkit-column-count: 4;
-	}
-}*/
-.about .box {
-	margin-bottom: 16px;
-	padding: 32px;
-}
-.about h1 {
-	padding: 0;
-	margin: 0;
-	font-weight: normal;
-	font-size: 1.6rem;
-}
-.about h2 {
-	text-align: center;
-	font-size: 1.2rem;
-	font-weight: normal;
-	margin: 1em;
-}
-.about h3 {
-	text-align: center;
-	font-size: 1.2rem;
-	font-weight: normal;
-	padding: 1em;
-	color: #00796B;
-}
-.about p {
-    margin: 1em 0;
-}
-.about p.summary {
-	max-width: 26em;
-	text-align: center;
-	background-color: #FF8;
-	padding: 1em;
-	border-radius: 0.1em;
-	box-shadow: 0 0.2em 0.2em #AAA;
-    margin: 1.5em auto;
-}
-
-/* Images */
-
-.about img {
-	max-width: 90%;
-	text-align: center;
-	padding: 1em;
-    display: block;
-    margin: 0 auto;
-}
-.about img[alt="producers"],
-.about img[alt="4_control"],
-.about img[alt="dealer"],
-.about img[alt="goods_transport"] {
-	float: right;
-}
-.about img[alt="2_control"] {
-	float: left;
-}
-.about img[alt="glass"] {
-	display: inline;
-	padding: 0;
-	padding-left: 0.9em;
-	vertical-align: middle;
-}
-
diff --git a/forms/cms/about/ui.xml b/forms/cms/about/ui.xml
deleted file mode 100644
index 3dff0745..00000000
--- a/forms/cms/about/ui.xml
+++ /dev/null
@@ -1,98 +0,0 @@
-<vn>
-<div id="title">
-	<h1><t>About</t></h1>
-</div>
-<div id="form" class="about">
-<div class="cols  vn-w-lg">
-	<div class="box">
-		<h1>
-			<t>QualityAndVariety</t>
-		</h1>
-		<p><t>MaximumFreshness</t></p>
-		<h3><t>SquareMeters</t></h3>
-		<img src="forms/cms/about/image/store.png" alt="store"/>
-		<h3><t>AboutRealms</t></h3>
-		<p><t>AboutLocation</t></p>
-		<img src="forms/cms/about/image/trailer.png" alt="trailer"/>
-		<p>
-			<img src="forms/cms/about/image/dealer.png" alt="dealer"/>
-			<t>PurchaseThroughWeb</t>
-		</p>
-		<img src="forms/cms/about/image/palletizing.png" alt="palletizing"/>
-	</div>
-	<div class="box">
-		<h1>
-			<t>WhatMakeUsDifferent</t>
-		</h1>
-		<p><t>DesignVariety</t></p>
-		<img src="forms/cms/about/image/differentiates_us.png" alt="differentiates_us"/>
-		<p><t>AdaptToYourNeeds</t></p>
-		<h3><t>TheBestQuality</t></h3>
-	</div>
-	<div class="box">
-		<h1>
-			<t>AtYourService</t>
-		</h1>
-		<h2><t>BuyersAndTraders</t></h2>
-		<img src="forms/cms/about/image/commercial.png" alt="commercial"/>
-	</div>
-	<div class="box">
-		<h1>
-			<t>Verdnatura training</t>
-		</h1>
-		<p><t>GoodTraining</t></p>
-		<img src="forms/cms/about/image/training.png" alt="training"/>
-		<p><t>SpecialTrainingPrices</t></p>
-		<img src="forms/cms/about/image/courses.png" alt="courses"/>
-		<h2><t>YoutubeChannel</t></h2>
-		<img src="forms/cms/about/image/youtube.png" alt="youtube"/>
-	</div>
-	<div class="box">
-		<h1>
-			<t>HowWeWork</t>
-		</h1>
-		<p><t>AalsmeerAuction</t></p>
-		<img src="forms/cms/about/image/auction.png" alt="auction"/>
-		<p><t>BeforeAuction</t></p>
-		<img src="forms/cms/about/image/producers.png" alt="producers"/>
-		<p><t>DirectlyFromProviders</t></p>
-		<p><t>GoodsDischarge</t></p>
-		<img src="forms/cms/about/image/goods_transport.png" alt="goods_transport"/>
-		<h2>
-			<t>FirstQualityControl</t>		
-			<img src="forms/cms/about/image/glass.png" alt="glass"/>
-		</h2>
-		<img src="forms/cms/about/image/goods_receive.png" alt="goods_receive"/>
-		<p><t>GoodsTravel</t></p>
-		<img src="forms/cms/about/image/2_control.png" alt="2_control"/>
-		<p><t>GoodsReception</t></p>
-		<h2>
-			<t>SecondQualityControl</t>
-			<img src="forms/cms/about/image/glass.png" alt="glass"/>
-		</h2>
-		<p><t>CustomerOrders</t></p>
-		<img src="forms/cms/about/image/web.png" alt="web"/>
-		<p><t>AfterOrder</t></p>
-		<img src="forms/cms/about/image/4_control.png" alt="4_control"/>
-		<h2>
-			<t>ThirdQualityControl</t>		
-			<img src="forms/cms/about/image/glass.png" alt="glass"/>
-		</h2>
-		<p><t>BuyerControl</t></p>
-		<h2>
-			<t>FourthQualityControl</t>
-			<img src="forms/cms/about/image/glass.png" alt="glass"/>
-		</h2>
-		<p><t>EmbeddedSection</t></p>
-		<img src="forms/cms/about/image/fit.png" alt="fit"/>
-		<p><t>AfterEmbedAgency</t></p>
-		<img src="forms/cms/about/image/agencies.png" alt="agencies"/>
-		<p><t>FreshnessGuaranteed</t></p>
-		<p class="summary">
-			<t>AboutSummary</t>
-			<img src="image/logo.svg" alt="Verdnatura"/>
-		</p>
-	</div>
-</div>
-</div>
-</vn>
diff --git a/forms/cms/contact/index.js b/forms/cms/contact/index.js
deleted file mode 100644
index 7bff0faf..00000000
--- a/forms/cms/contact/index.js
+++ /dev/null
@@ -1,39 +0,0 @@
-import './style.scss';
-
-export default new Class({
-	Extends: Hedera.Form,
-	Template: require('./ui.xml')
-
-	,activate() {
-		this.$.contactForm.onsubmit = () => {
-			this._onSubmit(); return false; 
-		};
-		this.refreshCaptcha();
-	}
-	
-	,refreshCaptcha() {
-		params = {
-			srv: 'rest:misc/captcha',
-			stamp: new Date().getTime()
-		};
-		this.$.captchaImg.src = '?'+ Vn.Url.makeUri(params);
-	}
-	
-	,async _onSubmit() {
-		const form = this.$.contactForm;
-		
-		try {
-			await this.conn.sendForm(this.$.contactForm);
-		} catch (err) {
-			Htk.Toast.showError(_('ErrorSendingData'));
-			return;
-		} finally {
-			form['captcha'].value = '';
-			this.refreshCaptcha();
-		}
-
-		form.reset();
-		Htk.Toast.showMessage(_('DataSentSuccess'));
-	}
-});
-
diff --git a/forms/cms/contact/locale/ca.yml b/forms/cms/contact/locale/ca.yml
deleted file mode 100644
index a6bcf847..00000000
--- a/forms/cms/contact/locale/ca.yml
+++ /dev/null
@@ -1,21 +0,0 @@
-IWantCustomer: Vull ser client!
-FillFormData: >-
-  Ompli el formulari amb les teves dades i en breu ens posarem en contacte amb
-  tu.
-OrCallUs: O si ho prefereixes truca'ns al 963 242 100.
-AllFieldsMandatory: '* Tots els camps són obligatoris.'
-Name: Nom
-Surname: Cognoms
-EMail: Correu electrònic
-Message: Missatge
-Address: Adreça
-PC: Codi postal
-City: Ciutat
-Phone: Telèfon
-Send: Enviar dades
-DataSentSuccess: >-
-  Les teves dades han estat enviades correctament. En breu ens posarem en
-  contacte amb tu.
-ErrorSendingData: >-
-  Error en enviar les dades. Si us plau, comprova que has omplert tots els camps
-  i que has introduït el codi antispam correctament.
diff --git a/forms/cms/contact/locale/en.yml b/forms/cms/contact/locale/en.yml
deleted file mode 100644
index b011f7f8..00000000
--- a/forms/cms/contact/locale/en.yml
+++ /dev/null
@@ -1,17 +0,0 @@
-IWantCustomer: I want to be a customer!
-FillFormData: Fill the form with your details and we will contact you soon.
-OrCallUs: 'Or if you prefer, call us at 963 242 100.'
-AllFieldsMandatory: '* All fields are mandatory.'
-Name: Name
-Surname: Surname
-EMail: Email
-Message: Message
-Address: Address
-PC: Zip code
-City: City
-Phone: Phone
-Send: Send
-DataSentSuccess: Your details have been sent successfully. Shortly we will contact you.
-ErrorSendingData: >-
-  Failed to send the data. Please check that you have filled in all the fields
-  and you entered the anti-spam code correctly.
diff --git a/forms/cms/contact/locale/es.yml b/forms/cms/contact/locale/es.yml
deleted file mode 100644
index d8a6aeb6..00000000
--- a/forms/cms/contact/locale/es.yml
+++ /dev/null
@@ -1,21 +0,0 @@
-IWantCustomer: ¡Quiero ser cliente!
-FillFormData: >-
-  Rellena el formulario con tus datos y en breve nos pondremos en contacto
-  contigo.
-OrCallUs: O si lo prefieres llámanos al 963 242 100.
-AllFieldsMandatory: '* Todos los campos son obligatorios.'
-Name: Nombre
-Surname: Apellidos
-EMail: Correo electrónico
-Message: Mensaje
-Address: Dirección
-PC: Código postal
-City: Ciudad
-Phone: Teléfono
-Send: Enviar datos
-DataSentSuccess: >-
-  Tus datos han sido enviados correctamente. En breve nos pondremos en contacto
-  contigo.
-ErrorSendingData: >-
-  Error al enviar los datos. Por favor, comprueba que has rellenado todos los
-  campos y que has introducido el código anti-spam correctamente.
diff --git a/forms/cms/contact/locale/fr.yml b/forms/cms/contact/locale/fr.yml
deleted file mode 100644
index dfcc16b3..00000000
--- a/forms/cms/contact/locale/fr.yml
+++ /dev/null
@@ -1,19 +0,0 @@
-IWantCustomer: Je veux devenir client!
-FillFormData: >-
-  Remplissez le formulaire avec vos coordonnées et nous prendrons contact avec
-  vous.
-OrCallUs: Ou si vous préférez nous appeler au 0033 781 533 900.
-AllFieldsMandatory: '* Tous les champs sont obligatoires.'
-Name: Prénom
-Surname: Nom
-EMail: Email
-Message: Message
-Address: Adresse
-PC: Code postal
-City: Ville
-Phone: Téléphone
-Send: Envoyer des données
-DataSentSuccess: Vos détails ont été envoyés avec succès. Rapidement nous vous contacterons.
-ErrorSendingData: >-
-  Échec de l'envoi de vos données. S'il vous plaît vérifiez que vous avez rempli
-  tous les champs et mis en place le code anti-spam correctement.
diff --git a/forms/cms/contact/locale/pt.yml b/forms/cms/contact/locale/pt.yml
deleted file mode 100644
index 7e2fb7ef..00000000
--- a/forms/cms/contact/locale/pt.yml
+++ /dev/null
@@ -1,19 +0,0 @@
-IWantCustomer: Quero ser cliente!
-FillFormData: Preencha o formulário com seus dados e em breve contactaremos consigo.
-OrCallUs: Ou se preferes ligue-nos ao +34 963 242 100.
-AllFieldsMandatory: '* Todos os campos são obrigatorios.'
-Name: Nome
-Surname: Apelidos
-EMail: E-Mail
-Message: Menssagem
-Address: Morada
-PC: Código postal
-City: Concelho
-Phone: Telefone
-Send: Enviar dados
-DataSentSuccess: >-
-  Seus dados foram enviados corretamente.Em breve nos colocaremos em contacto
-  consigo.
-ErrorSendingData: >-
-  Erro ao enviar os dados. Por favor, comprove que preenchestes todos os campos
-  e que há introduzido o código anti-spam corretamente.
diff --git a/forms/cms/contact/style.scss b/forms/cms/contact/style.scss
deleted file mode 100644
index a330fa93..00000000
--- a/forms/cms/contact/style.scss
+++ /dev/null
@@ -1,38 +0,0 @@
-
-.contact .form {
-	position: relative;
-	text-align: left;
-	max-width: 25em;
-	margin: 0 auto;
-}
-.contact form {
-	margin: 0 auto;
-}
-.contact form p {
-	margin: 1em auto;
-	display: block;
-	margin-top: 2em;
-}
-.contact textarea {
-	height: 5em;
-}
-.contact button {
-	display: block;
-	margin: 0 auto;
-	margin-top: 1em;
-	padding: 0.6em;
-}
-.contact .mandatory-message {
-	font-size: .9em;
-}
-
-/* Captcha */
-
-.captcha img {
-	vertical-align: middle;
-	margin-left: 1em;
-}
-.captcha input {
-	max-width: 8em;
-}
-
diff --git a/forms/cms/contact/ui.xml b/forms/cms/contact/ui.xml
deleted file mode 100644
index 44a203b0..00000000
--- a/forms/cms/contact/ui.xml
+++ /dev/null
@@ -1,49 +0,0 @@
-<vn>
-<div id="title">
-	<h1><t>IWantCustomer</t></h1>
-</div>
-<div id="form" class="contact">
-	<div class="box form  vn-w-xs vn-pa-lg">
-		<p><t>FillFormData</t></p>
-		<p><t>OrCallUs</t></p>
-		<form id="contact-form">
-			<input type="hidden" name="srv" value="json:client/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>
-				<t>Send</t>
-			</button>
-		</form>
-	</div>
-</div>
-</vn>
diff --git a/forms/cms/home/index.js b/forms/cms/home/index.js
deleted file mode 100644
index 3e49e755..00000000
--- a/forms/cms/home/index.js
+++ /dev/null
@@ -1,6 +0,0 @@
-import './style.scss';
-
-export default new Class({
-	Extends: Hedera.Form,
-	Template: require('./ui.xml')
-});
diff --git a/forms/cms/home/locale/ca.yml b/forms/cms/home/locale/ca.yml
deleted file mode 100644
index 2b7a8db8..00000000
--- a/forms/cms/home/locale/ca.yml
+++ /dev/null
@@ -1,12 +0,0 @@
-Start order: Començar comanda
-Sent: Enviat
-Author: Autor
-votes: vots
-NoAnswerSelected: No has seleccionat cap resposta
-ThanksForVote: Gràcies pel teu vot!
-Vote: Votar
-Total: Total
-BrownserRecommend: >-
-  Verdnatura recomana utilitzar el navegador web Mozilla Firefox per a obtindre
-  tota la funcionalitat del nostre lloc web.
-PressHere: Clica aquí per descarregar Firefox
diff --git a/forms/cms/home/locale/en.yml b/forms/cms/home/locale/en.yml
deleted file mode 100644
index 445ff36a..00000000
--- a/forms/cms/home/locale/en.yml
+++ /dev/null
@@ -1,12 +0,0 @@
-Start order: Start order
-Sent: Sent
-Author: Author
-votes: votes
-NoAnswerSelected: No answer selected
-ThanksForVote: Thanks for your vote!
-Vote: Vote
-Total: Total
-BrownserRecommend: >-
-  Verdnatura recommend using the Mozilla Firefox web browser for full
-  functionality of our website.
-PressHere: Click here to download Firefox
diff --git a/forms/cms/home/locale/es.yml b/forms/cms/home/locale/es.yml
deleted file mode 100644
index ab9ea5cc..00000000
--- a/forms/cms/home/locale/es.yml
+++ /dev/null
@@ -1,12 +0,0 @@
-Start order: Empezar pedido
-Sent: Enviado
-Author: Autor
-votes: votos
-NoAnswerSelected: No has seleccionado ninguna respuesta
-ThanksForVote: ¡Gracias por tu voto!
-Vote: Votar
-Total: Total
-BrownserRecommend: >-
-  Verdnatura recomienda utilizar el navegador web Mozilla Firefox para obtener
-  toda la funcionalidad de nuestra página web.
-PressHere: Pulsa aquí para descargar Firefox
diff --git a/forms/cms/home/locale/fr.yml b/forms/cms/home/locale/fr.yml
deleted file mode 100644
index a90007ea..00000000
--- a/forms/cms/home/locale/fr.yml
+++ /dev/null
@@ -1,12 +0,0 @@
-Start order: Lancer commande
-Sent: Envoyé
-Author: Auteur
-votes: votes
-NoAnswerSelected: Vous avez pas sélectionné de réponse
-ThanksForVote: Merci pour votre vote!
-Vote: Voter
-Total: Total
-BrownserRecommend: >-
-  Verdnatura recommande d'utiliser le navigateur Web Mozilla Firefox pour
-  obtenir toutes les fonctionnalités de notre site web.
-PressHere: Cliquez ici pour télécharger Firefox
diff --git a/forms/cms/home/locale/mn.yml b/forms/cms/home/locale/mn.yml
deleted file mode 100644
index d59a1ad1..00000000
--- a/forms/cms/home/locale/mn.yml
+++ /dev/null
@@ -1,12 +0,0 @@
-Start order: Захиалга эхлэх
-Sent: Sent
-Author: Author
-votes: votes
-NoAnswerSelected: No answer selected
-ThanksForVote: Thanks for your vote!
-Vote: Vote
-Total: Total
-BrownserRecommend: >-
-  Verdnatura recommend using the Mozilla Firefox web browser for full
-  functionality of our website.
-PressHere: Click here to download Firefox
diff --git a/forms/cms/home/locale/pt.yml b/forms/cms/home/locale/pt.yml
deleted file mode 100644
index 4dcdd229..00000000
--- a/forms/cms/home/locale/pt.yml
+++ /dev/null
@@ -1,12 +0,0 @@
-Start order: Comece uma encomenda
-Sent: Enviado
-Author: Autor
-votes: votos
-NoAnswerSelected: Não seleccionou nenhuma resposta
-ThanksForVote: Obrigado por seu voto!
-Vote: Votar
-Total: Total
-BrownserRecommend: >-
-  Verdnatura recomenda utilizar o navegador web Mozilla Firefox para obter toda
-  a funcionalidade de nossa página web.
-PressHere: Pulse aquí para baixar Firefox
diff --git a/forms/cms/home/style.scss b/forms/cms/home/style.scss
deleted file mode 100644
index b6d83b5f..00000000
--- a/forms/cms/home/style.scss
+++ /dev/null
@@ -1,54 +0,0 @@
-
-.home {
-	padding: 6px !important;
-}
-
-/* News panel */
-
-.column {
-	margin: 0 auto;
-	max-width: 1680px;
-}
-.action-bar button.start-order {
-	border: 1px solid white;
-}
-.action-bar button.start-order:hover {
-	background-color: white !important;
-	color: black;
-}
-
-/* New */
-
-.new {
-	text-align: left;
-	margin: 6px;
-}
-.new img {
-	display: block;
-	margin: auto;
-	width: 100%;
-}
-.new .top {
-	padding: 18px;
-	padding-bottom: 1px;
-}
-.new h2 {
-	font-size: 1.6rem;
-	color: black;
-	font-weight: normal;
-	padding: 0;
-}
-
-.new-text {
-	margin: 18px 0;
-	font-family: 'Open Sans';
-}
-.new-text a {
-	color: #6a1;
-}
-.new-text a:hover {
-	text-decoration: underline;
-}
-.new-text li {
-	margin: 4px 0;
-}
diff --git a/forms/cms/home/ui.xml b/forms/cms/home/ui.xml
deleted file mode 100644
index ba1600e8..00000000
--- a/forms/cms/home/ui.xml
+++ /dev/null
@@ -1,44 +0,0 @@
-<vn>
-<div id="title">
-	<h1><t>Home</t></h1>
-</div>
-<div id="actions" class="catalog-actions">
-	<htk-bar-button
-		class="start-order"
-		icon="add_shopping_cart"
-		tip="_Start order"
-		on-click="hash.setAll({form: 'ecomerce/catalog'})"/>
-</div>
-<div id="form" class="home">
-	<div class="column mansonry" id="news-column">
-		<htk-repeater form-id="iter">
-			<db-model property="model">
-				<custom>
-					SELECT title, text, image, id
-						FROM news
-						ORDER BY priority, created DESC
-				</custom>
-			</db-model>
-			<custom>
-				<div class="masonry-box">
-				<div class="new box">
-					<htk-image
-						directory="news"
-						subdir="full"
-						value="{{iter.image}}"
-						editable="false"
-						full-dir="full"/>
-					<div class="top">
-						<h2>{{iter.title}}</h2>
-						<div class="new-text">
-							<htk-html value="{{iter.text}}"/>
-						</div>
-					</div>
-				</div>
-				</div>
-			</custom>
-		</htk-repeater>
-		<div class="clear"/>
-	</div>
-</div>
-</vn>
diff --git a/forms/cms/location/index.js b/forms/cms/location/index.js
deleted file mode 100644
index 8aa1ffa4..00000000
--- a/forms/cms/location/index.js
+++ /dev/null
@@ -1,103 +0,0 @@
-import './style.scss';
-
-var gmapsIsLoaded = false;
-
-export default new Class({
-	Extends: Hedera.Form,
-	Template: require('./ui.xml')
-
-	,locations: null
-
-	,async activate() {
-		this.gui.loaderPush();
-
-		var sql = 'SELECT lat, lng, title, address, postcode, city, province, phone, language FROM location';
-		const resultSet = await this.conn.execQuery(sql);
-		this.locations = resultSet.fetchData();
-	
-		if (!gmapsIsLoaded) {
-			window.gmapsLoadedCallback = () => this.gmapsLoaded();
-			Vn.includeJs('https://maps.google.com/maps/api/js'
-				+'?sensor=false&callback=gmapsLoadedCallback'
-				+'&key=AIzaSyBbunFsAFEkjtw-c7BUHNgkThSlKEKFxiE',
-				null, true
-			);
-		} else
-			this.gmapsLoaded();
-	}
-
-	,gmapsLoaded() {
-		this.gui.loaderPop();
-		gmapsIsLoaded = true;
-
-		if (!this.locations || !gmapsIsLoaded)
-			return;
-
-		var options = {
-			 zoom: 4
-			,mapTypeId: google.maps.MapTypeId.ROADMAP
-			,center: new google.maps.LatLng(46.0, 4.0)
-		};
-
-		var div = this.$.form;
-		var gmap = new google.maps.Map(div, options);
-
-		for (const location of this.locations)
-			this.createMarker(location, gmap);
-	}
-	
-	,createMarker(location, gmap) {
-		var div = document.createElement('div');
-		div.className = 'marker';
-
-		var h = document.createElement('h3');
-		h.appendChild(document.createTextNode(location.title));
-		div.appendChild(h);
-
-		var p = document.createElement('p');
-		p.appendChild(document.createTextNode(location.address));
-		div.appendChild(p);
-
-		var p = document.createElement('p');
-		p.appendChild(document.createTextNode(location.postcode +' '+ location.city));
-		div.appendChild(p);
-
-		var p = document.createElement('p');
-		p.appendChild(document.createTextNode(location.province));
-		div.appendChild(p);
-
-		var p = document.createElement('p');
-		p.appendChild(document.createTextNode(location.phone));
-		div.appendChild(p);
-		
-		var lat = new google.maps.LatLng(
-			location.lat,
-			location.lng
-		);
-
-		var marker = new google.maps.Marker({
-			 position: lat
-			,tilte: location.title
-			,map: gmap
-		});
-
-		var infoWindow = new google.maps.InfoWindow({
-			 content: div
-		});
-
-		google.maps.event.addListener(marker, 'click',
-			this.openInfoWindow.bind(this, infoWindow, gmap, marker));
- 		
- 		if (Vn.Locale.language
-		&& Vn.Locale.language == location.language)
- 			this.openInfoWindow(infoWindow, gmap, marker);
-	}
-	
-	,openInfoWindow(infoWindow, gmap, marker) {
-		if (this.openedWindow)
-			this.openedWindow.close();
-
-		infoWindow.open(gmap, marker);
-		this.openedWindow = infoWindow;
-	}
-});
diff --git a/forms/cms/location/locale/ca.yml b/forms/cms/location/locale/ca.yml
deleted file mode 100644
index 6e6d99e8..00000000
--- a/forms/cms/location/locale/ca.yml
+++ /dev/null
@@ -1 +0,0 @@
-ShowMap: Mostrar mapa
diff --git a/forms/cms/location/locale/en.yml b/forms/cms/location/locale/en.yml
deleted file mode 100644
index 81bf9390..00000000
--- a/forms/cms/location/locale/en.yml
+++ /dev/null
@@ -1 +0,0 @@
-ShowMap: Show map
diff --git a/forms/cms/location/locale/es.yml b/forms/cms/location/locale/es.yml
deleted file mode 100644
index 6e6d99e8..00000000
--- a/forms/cms/location/locale/es.yml
+++ /dev/null
@@ -1 +0,0 @@
-ShowMap: Mostrar mapa
diff --git a/forms/cms/location/locale/fr.yml b/forms/cms/location/locale/fr.yml
deleted file mode 100644
index fbc94b57..00000000
--- a/forms/cms/location/locale/fr.yml
+++ /dev/null
@@ -1 +0,0 @@
-ShowMap: Montrer la carte
diff --git a/forms/cms/location/locale/pt.yml b/forms/cms/location/locale/pt.yml
deleted file mode 100644
index 6e6d99e8..00000000
--- a/forms/cms/location/locale/pt.yml
+++ /dev/null
@@ -1 +0,0 @@
-ShowMap: Mostrar mapa
diff --git a/forms/cms/location/style.scss b/forms/cms/location/style.scss
deleted file mode 100644
index a5dcdab6..00000000
--- a/forms/cms/location/style.scss
+++ /dev/null
@@ -1,16 +0,0 @@
-.location
-{
-	position: relative;
-	height: 100%;
-	width: 100%;
-}
-
-div.marker h3
-{
-	font-size: 1.3rem;
-}
-div.marker p
-{
-	padding: 0;
-	margin: 0;
-}
diff --git a/forms/cms/location/ui.xml b/forms/cms/location/ui.xml
deleted file mode 100644
index 58388869..00000000
--- a/forms/cms/location/ui.xml
+++ /dev/null
@@ -1,6 +0,0 @@
-<vn>
-	<div id="title">
-		<h1><t>Location</t></h1>
-	</div>
-	<div id="form" class="location"/>
-</vn>
diff --git a/forms/cms/why/index.js b/forms/cms/why/index.js
deleted file mode 100644
index 36552d4f..00000000
--- a/forms/cms/why/index.js
+++ /dev/null
@@ -1,7 +0,0 @@
-import './style.scss';
-
-export default new Class({
-	Extends: Hedera.Form,
-	Template: require('./ui.xml')
-});
-
diff --git a/forms/cms/why/locale/ca.yml b/forms/cms/why/locale/ca.yml
deleted file mode 100644
index 4f8a89f3..00000000
--- a/forms/cms/why/locale/ca.yml
+++ /dev/null
@@ -1,32 +0,0 @@
-AboutCompany: Per què Verdnatura?
-StorePhoto: Foto magatzem
-BecauseOurBigCatalog: 'Perquè tenim el catàleg més gran del sector, renovat diariament.'
-BecauseThisWeb: 'Per aquest lloc web, amb stock en temps real sempre a la teua disposició.'
-BecauseOurShoppingDep: 'Per el nostre departament de compres, amb 9 compradors especialitzats.'
-BecauseOrderIsEasy: >-
-  Perquè és molt fàcil realitzar el teu encàrrec mitjançant la web, per telèfon
-  o venint.
-BecauseOurPlant: 'Per les nostres instal·lacions, vine i visita''ns. T''encantaran.'
-BecauseOurSalesDep: >-
-  Pel nostre departament comercial, amb professionals que sempre ofereixen amb
-  una solució adaptada a les teues necessitats.
-BecauseOurWorkShop: Perquè tenim un taller de confecció per ajudar-te.
-BecauseWeHaveWhatYouNeed: Perquè tenim el que necessites quan ho necessites...
-AboutDesc: >-
-  Som una empresa dedicada a la venta a l'engrós i distribució d'una amplia gama
-  de complements, verds i flors naturals a frloristeries o altres majoristes.
-AboutService: >-
-  Disposem de servei de repartiment a domicili amb els nostres vehícles per tota
-  la provincia de València i arees limitades de Castelló, Alacant, Murcia,
-  Albacete i Madrid. A la resta de la península enviem mitjançan agències de
-  transport amb servei 24/48 hores (Zeleris, Viaexpress). També realitzaem venda
-  directa a floristes en qualsevol de les nostres instal·lacions.
-AboutDisp: >-
-  La nostra empresa disposa de més de 50 treballadors i diferents sucursals. La
-  principal es troba a València i disposa de més de 8000 m2. També disposem d'un
-  magatzem situat a Mercaflor - Mercavalencia (València) en el qual solament
-  realitzem venda directa.
-AboutOrder: >-
-  Pots realitzar els teus encarrecs i reserves telefonant al +34 607 562 391,
-  per Internet mitjançant el nostre lloc web o bé directament a les nostres
-  instal·lacions.
diff --git a/forms/cms/why/locale/en.yml b/forms/cms/why/locale/en.yml
deleted file mode 100644
index 455d2c25..00000000
--- a/forms/cms/why/locale/en.yml
+++ /dev/null
@@ -1,28 +0,0 @@
-AboutCompany: Why Verdnatura?
-StorePhoto: Store photo
-BecauseOurBigCatalog: 'Because we have the largest catalog in the sector, renewed daily.'
-BecauseThisWeb: 'Because this website, with real time stock always at your disposal.'
-BecauseOurShoppingDep: For our purchasing department with 9 specialized buyers.
-BecauseOrderIsEasy: 'Because it is very easy to place your order by web, phone or coming.'
-BecauseOurPlant: 'Because our premises, come and visit us. You''ll love.'
-BecauseOurSalesDep: >-
-  For our commercial department, with professionals who will always find a
-  solution to your needs.
-BecauseOurWorkShop: Because we have a sewing shop to help you.
-BecauseWeHaveWhatYouNeed: Because we have what you need when you need it ...
-AboutDesc: >-
-  We are a company engaged in the wholesale and distribution of a wide range of
-  accessories, greens and flowers to florists or other wholesalers.
-AboutService: >-
-  We have home delivery service with our vehicles throughout the province of
-  Valencia and limited areas of Castellón, Alicante, Murcia, Albacete and Madrid
-  send the rest of the peninsula by transportation agencies with 24/48 hours
-  service (Zeleris, via express) . We also do direct sales to florists in any of
-  our facilities.
-AboutDisp: >-
-  Our company has over 50 employees and several branches. The main is located in
-  Valencia and has more than 8000 m2. We also have a warehouse located in
-  Mercaflor - Mercavalencia (Valencia) that perform direct sales only.
-AboutOrder: >-
-  You can make your orders and reservations by telephone at 96 324 21 00, online
-  through our website or directly in our facilities.
diff --git a/forms/cms/why/locale/es.yml b/forms/cms/why/locale/es.yml
deleted file mode 100644
index c5c79d10..00000000
--- a/forms/cms/why/locale/es.yml
+++ /dev/null
@@ -1,31 +0,0 @@
-AboutCompany: ¿Por qué Verdnatura?
-StorePhoto: Foto almacén
-BecauseOurBigCatalog: 'Porque tenemos el catálogo más grande del sector, renovado diariamente.'
-BecauseThisWeb: 'Por esta página web, con stock en tiempo real siempre a tu disposición.'
-BecauseOurShoppingDep: Por nuestro departamento de compras con 9 compradores especializados.
-BecauseOrderIsEasy: 'Porque es muy fácil hacer tu pedido por web, por teléfono o viniendo.'
-BecauseOurPlant: 'Por nuestras instalaciones, ven y visítanos. Te encantarán.'
-BecauseOurSalesDep: >-
-  Por nuestro departamento comercial, con profesionales que siempre encontrarán
-  una solución a tus necesidades.
-BecauseOurWorkShop: Porque tenemos un taller de confección para ayudarte.
-BecauseWeHaveWhatYouNeed: Porque tenemos lo que necesitas cuando lo necesitas...
-AboutDesc: >-
-  Somos una empresa dedicada a la venta mayorista y distribución de una amplia
-  gama de complementos, verdes y flores naturales a floristerías u otros
-  mayoristas.
-AboutService: >-
-  Disponemos de servicio de reparto a domicilio con nuestros vehículos por toda
-  la provincia de Valencia y áreas limitadas de Castellón, Alicante, Murcia,
-  Albacete y Madrid enviamos al resto de la península mediante agencias de
-  transporte con servicio 24/48 horas (Zeleris, Viaexpress). También realizamos
-  venta directa a floristas en cualquiera de nuestras instalaciones.
-AboutDisp: >-
-  Nuestra empresa dispone de más de 50 trabajadores y varias sucursales. La
-  principal se encuentra situada en Valencia y cuenta con más de 8000 m2.
-  También disponemos de un almacén situado en Mercaflor - Mercavalencia
-  (Valencia) en el que únicamente realizamos venta directa.
-AboutOrder: >-
-  Puedes realizar tus pedidos y reservas por teléfono llamando al 96 324 21 00,
-  por Internet a través de nuestra página web o bien directamente en nuestras
-  instalaciones.
diff --git a/forms/cms/why/locale/fr.yml b/forms/cms/why/locale/fr.yml
deleted file mode 100644
index 5052a7b7..00000000
--- a/forms/cms/why/locale/fr.yml
+++ /dev/null
@@ -1,36 +0,0 @@
-AboutCompany: Pourquoi Verdnatura?
-StorePhoto: Magasin de photo
-BecauseOurBigCatalog: >-
-  Parce que nous avons le plus grand catalogue dans le secteur, chaque jour
-  renouvelé.
-BecauseThisWeb: 'Sur ce site, avec un stock en temps réel toujours à votre disposition.'
-BecauseOurShoppingDep: Pour notre département achats 9 acheteurs spécialisés.
-BecauseOrderIsEasy: >-
-  Parce qu'il est très facile de passer votre commande par Internet, par
-  téléphone ou à venir.
-BecauseOurPlant: 'Chez nous, venez nous rendre visite. Vous allez adorer.'
-BecauseOurSalesDep: >-
-  Pour nos professionnels de service commercial qui sera toujours de trouver une
-  solution à vos besoins.
-BecauseOurWorkShop: Parce que nous avons un atelier de couture pour aider.
-BecauseWeHaveWhatYouNeed: Parce que nous avons ce que vous avez besoin quand vous en avez besoin ...
-AboutDesc: >-
-  Nous sommes une société spécialisée dans le commerce de gros et de la
-  distribution d'une large gamme d'accessoires, des verts et des fleurs à des
-  fleuristes ou des autres grossistes.
-AboutService: >-
-  Nous avons un service de livraison à domicile avec nos véhicules dans la
-  province de Valence et des zones limitées de Castellón, Alicante, Murcie,
-  Albacete et Madrid envoyer le reste de la péninsule par les agences de
-  transport avec le service 24/48 heures (Zeleris, Viaexpress). Nous faisons
-  également des ventes directes aux fleuristes dans la totalité de nos
-  installations.
-AboutDisp: >-
-  Notre société a plus de 100 employés et plusieurs branches. Le principal est
-  situé à Valence et a plus de 8000 m2. Nous avons aussi un entrepôt situé à
-  Mercaflor - Mercavalencia (Valencia) qui effectuent des ventes directes
-  seulement.
-AboutOrder: >-
-  Vous pouvez faire vos commandes et réservations par téléphone au +33 781 533
-  900, en ligne grâce à notre site Internet ou directement dans nos
-  installations.
diff --git a/forms/cms/why/locale/pt.yml b/forms/cms/why/locale/pt.yml
deleted file mode 100644
index 613fe14a..00000000
--- a/forms/cms/why/locale/pt.yml
+++ /dev/null
@@ -1,28 +0,0 @@
-AboutCompany: Por quê Verdnatura?
-StorePhoto: Foto armazém
-BecauseOurBigCatalog: 'Porque temos o maior catálogo do sector, renovado diariamente.'
-BecauseThisWeb: 'Por este site, com estoque em tempo real sempre à sua disposição.'
-BecauseOurShoppingDep: Por nosso departamento de compras com 9 compradores especializados.
-BecauseOrderIsEasy: 'Porque é muito fácil fazer pedidos por internet, aplicativo ou telefone.'
-BecauseOurPlant: 'Por nossas instalações, venha e visite-nos. Vas a adorar.'
-BecauseOurSalesDep: >-
-  Por nosso departamento comercial, com profissionais que sempre encontrarão uma
-  solução para suas necessidades.
-BecauseOurWorkShop: Porque temos uma oficina de confecção para ajudar-te.
-BecauseWeHaveWhatYouNeed: Porque temos o que necessitas quando necessitas.
-AboutDesc: >-
-  Somos uma empresa dedicada à venta grossista e distribuição de uma ampla gama
-  de complementos, verdes e flores naturaise a floristas ou outros grossistas.
-AboutService: >-
-  Contamos com serviço de entrega a domicilio com nossos veículos por toda a
-  provincia de Valencia e áreas limitadas de Castellón, Alicante, Murcia,
-  Albacete e Madrid enviamos ao resto da península mediante agencias de
-  transporte com serviço 24/48 horas (MRW, Zeleris, Viaexpress). Também
-  realizamos venta directa a floristas em qualquer de nossas instalações.
-AboutDisp: >-
-  Nossa empresa tem mais de 50 trabalhadores e varias sucursais. A principal se
-  encontra situada em Valencia e conta com mais de 8.000m2.
-AboutOrder: >-
-  Podes realizar seus pedidos e reservas por telefone ligando ao +34 96 324 21
-  00, por Internet a través de nossa página web, por nosso aplicativo para
-  Android, ou diretamente em nossas instalações.
diff --git a/forms/cms/why/store.png b/forms/cms/why/store.png
deleted file mode 100644
index 82494548..00000000
Binary files a/forms/cms/why/store.png and /dev/null differ
diff --git a/forms/cms/why/style.scss b/forms/cms/why/style.scss
deleted file mode 100644
index edc70906..00000000
--- a/forms/cms/why/style.scss
+++ /dev/null
@@ -1,14 +0,0 @@
-
-.why ul {
-	list-style-type: none;
-	padding: 0;
-	margin-top: 0;
-}
-.why li {
-	padding-bottom: 16px;
-}
-.why img {
-	display: block;
-	margin: 0 auto;
-	max-width: 95%;
-}
diff --git a/forms/cms/why/ui.xml b/forms/cms/why/ui.xml
deleted file mode 100644
index 822cda36..00000000
--- a/forms/cms/why/ui.xml
+++ /dev/null
@@ -1,20 +0,0 @@
-<vn>
-<div id="title">
-	<h1><t>AboutCompany</t></h1>
-</div>
-<div id="form" class="why">
-	<div class="box vn-w-sm vn-pa-lg">
-		<ul class="vn-mb-lg">
-			<li><t>BecauseOurBigCatalog</t></li>
-			<li><t>BecauseThisWeb</t></li>
-			<li><t>BecauseOurShoppingDep</t></li>
-			<li><t>BecauseOrderIsEasy</t></li>
-			<li><t>BecauseOurPlant</t></li>
-			<li><t>BecauseOurSalesDep</t></li>
-			<li><t>BecauseOurWorkShop</t></li>
-			<li><t>BecauseWeHaveWhatYouNeed</t></li>
-		</ul>
-		<img src="forms/cms/why/store.png" alt="Store photo"/>
-	</div>
-</div>
-</vn>
diff --git a/forms/ecomerce/basket/index.js b/forms/ecomerce/basket/index.js
deleted file mode 100644
index 2e2ec1f2..00000000
--- a/forms/ecomerce/basket/index.js
+++ /dev/null
@@ -1,29 +0,0 @@
-import './style.scss';
-
-export default new Class({
-	Extends: Hedera.Form,
-	Template: require('./ui.xml'),
-
-	async open() {
-		const isOk = await Hedera.BasketChecker.check(this.conn, this.hash);
-		if (isOk) await Hedera.Form.prototype.open.call(this);
-	},
-	
-	activate() {	
-		this.$.items.setInfo('bi', 'myBasketItem', 'hedera');
-	},
-
-	onConfigureClick() {
-		Htk.Toast.showWarning(_('RememberReconfiguringImpact'));
-		this.hash.setAll({form: 'ecomerce/checkout'});
-	},
-
-	onDeleteClick(form) {
-		if (confirm(_('ReallyDelete')))
-			form.deleteRow();
-	},
-
-	subtotal(form) {
-		return form.$.amount * form.$.price;
-	}
-});
diff --git a/forms/ecomerce/basket/locale/ca.yml b/forms/ecomerce/basket/locale/ca.yml
deleted file mode 100644
index d4a09b57..00000000
--- a/forms/ecomerce/basket/locale/ca.yml
+++ /dev/null
@@ -1,27 +0,0 @@
-ShoppingBasket: Cistella de la compra
-Delete: Borrar encàrrec
-GoToCatalog: Anar al catàleg
-ConfigureOrder: Configurar encàrrec
-Checkout: Tramitar encàrrec
-OrderNumber: N encàrec
-DateExit: Data d'eixida
-Warehouse: Magatzem
-OrderTotal: Total encàrrec
-Amount: Quant
-Pack: Pack
-Stems: Tijes
-Avail: Disp
-Item: Artícle
-Cat: Cat
-S1: Mes
-Color: Color
-Origin: Orige
-Price: Preu
-Disc: Desc
-Subtotal: Subtotal
-Order items updated: >-
-  La teva comanda porta massa temps obert i ha estat actualitzat, els preus o
-  quantitats dels teus articles poden haver canviat
-RememberReconfiguringImpact: >-
-  Recorda que si tornes a configurar la comanda els preus o quantitats dels teus
-  articles podrien canviar
diff --git a/forms/ecomerce/basket/locale/en.yml b/forms/ecomerce/basket/locale/en.yml
deleted file mode 100644
index d1b3271a..00000000
--- a/forms/ecomerce/basket/locale/en.yml
+++ /dev/null
@@ -1,27 +0,0 @@
-ShoppingBasket: Shopping basket
-Delete: Delete order
-GoToCatalog: Go to catalog
-ConfigureOrder: Configure order
-Checkout: Checkout
-OrderNumber: Order number
-DateExit: Shipping date
-Warehouse: Store
-OrderTotal: Total
-Amount: Amount
-Pack: Pack
-Stems: Stems
-Avail: Avail
-Item: Item
-Cat: Cat
-S1: Siz
-Color: Color
-Origin: Origin
-Price: Price
-Disc: Desc
-Subtotal: Subtotal
-Order items updated: >-
-  Your order takes too long and has been updated, prices or quantities of your
-  items may have changed
-RememberReconfiguringImpact: >-
-  Remember that if you reconfigure your order prices or quantities of your items
-  may change
diff --git a/forms/ecomerce/basket/locale/es.yml b/forms/ecomerce/basket/locale/es.yml
deleted file mode 100644
index 4069ca0d..00000000
--- a/forms/ecomerce/basket/locale/es.yml
+++ /dev/null
@@ -1,27 +0,0 @@
-ShoppingBasket: Cesta de la compra
-Delete: Borrar pedido
-GoToCatalog: Ir al catálogo
-ConfigureOrder: Configurar pedido
-Checkout: Finalizar pedido
-OrderNumber: Nº pedido
-DateExit: Fecha de salida
-Warehouse: Almacén
-OrderTotal: Total
-Amount: Cantidad
-Pack: Pack
-Stems: Tallos
-Avail: Disp
-Item: Artículo
-Cat: Cat
-S1: Med
-Color: Color
-Origin: Origen
-Price: Precio
-Disc: Desc
-Subtotal: Subtotal
-Order items updated: >-
-  Tu pedido lleva demasiado tiempo abierto y ha sido actualizado, los precios o
-  cantidades de tus artículos pueden haber cambiado
-RememberReconfiguringImpact: >-
-  Recuerda que si vuelves a configurar el pedido los precios o cantidades de tus
-  artículos podrían cambiar
diff --git a/forms/ecomerce/basket/locale/fr.yml b/forms/ecomerce/basket/locale/fr.yml
deleted file mode 100644
index dba6194b..00000000
--- a/forms/ecomerce/basket/locale/fr.yml
+++ /dev/null
@@ -1,27 +0,0 @@
-ShoppingBasket: Panier
-Delete: Effacer
-GoToCatalog: Aller au catalogue
-ConfigureOrder: Définissez l'ordre
-Checkout: Caisse
-OrderNumber: Numéro de commande
-DateExit: Date de sortie
-Warehouse: Magasin
-OrderTotal: Total commande
-Amount: Quant
-Pack: Pack
-Stems: Tige
-Avail: Disp
-Item: Nom
-Cat: Cat
-S1: Mes
-Color: Couleur
-Origin: Origine
-Price: '* Prix'
-Disc: Remise
-Subtotal: Sous-total
-Order items updated: >-
-  Ouvrir votre commande prend trop de temps et a été mis à jour, les prix ou les
-  quantités de vos articles peuvent avoir changé
-RememberReconfiguringImpact: >-
-  Rappelez-vous que si jamais vous commandez des prix fixés ou les quantités de
-  vos articles pourraient changer
diff --git a/forms/ecomerce/basket/locale/pt.yml b/forms/ecomerce/basket/locale/pt.yml
deleted file mode 100644
index 0e3227b7..00000000
--- a/forms/ecomerce/basket/locale/pt.yml
+++ /dev/null
@@ -1,27 +0,0 @@
-ShoppingBasket: Cesta da compra
-Delete: Eliminar encomenda
-GoToCatalog: Ir ao catálogo
-ConfigureOrder: Configurar encomenda
-Checkout: Finalizar encomenda
-OrderNumber: Nº encomenda
-DateExit: Data de saída
-Warehouse: Armazém
-OrderTotal: Total
-Amount: Quantidade
-Pack: Pack
-Stems: Pés
-Avail: Disp
-Item: Item
-Cat: Cat
-S1: Med
-Color: Cor
-Origin: Origem
-Price: Preço
-Disc: Desc
-Subtotal: Sub-total
-Order items updated: >-
-  Seu pedido leva muito tiempo aberto foi atualizado, os preços ou quantidades
-  de seus ítens podem haver variado
-RememberReconfiguringImpact: >-
-  Lembre-se que si voltas a configurar a encomenda os preços ou quantidades de
-  ítens poderíam variar
diff --git a/forms/ecomerce/basket/style.scss b/forms/ecomerce/basket/style.scss
deleted file mode 100644
index f46a077c..00000000
--- a/forms/ecomerce/basket/style.scss
+++ /dev/null
@@ -1,76 +0,0 @@
-
-.basket .head {
-	border-bottom: 1px solid #DDD;
-}
-.basket .head p {
-	font-weight: bold;
-	margin: 0;
-	padding: 0;
-	font-size: 1.4rem;
-	text-align: right;
-}
-.basket .form > p {
-	margin: 0;
-	font-size: 1.4rem;
-	color: white;
-	text-align: right;
-}
-
-/* Lines */
-
-.basket .line {
-	display: flex;
-	align-items: center;
-	gap: 12px;
-	margin: 10px 0;
-	height: 80px;
-}
-.basket .line:first-child {
-	margin-top: 0;
-}
-.basket .line:last-child {
-	margin-bottom: 0;
-}
-.basket .line > .delete {
-	margin: 0 -8px;
-}
-.basket .line > .photo {
-	flex: none;
-	border-radius: 50%;
-	width: 68px;
-	height: 68px;
-	gap: 0;
-}
-.basket .line > .info {
-	flex: 1;
-	overflow: hidden;
-}
-.basket .line > .info > * {
-	text-overflow: ellipsis;
-	white-space: nowrap;
-	overflow: hidden;
-}
-.basket .line > .info > h2 {
-	font-size: 1rem;
-	font-weight: normal;
-	margin: 0;
-}
-.basket .line > .info > p {
-	margin: 0;
-}
-.basket .line > .info > .tags {
-	color: #777;
-}
-.basket .line .subtotal {
-	float: right;
-}
-
-/* Fields */
-
-.basket td.available-exceeded input {
-	background-color: #FCC;
-}
-.basket .icon > img {
-	border-radius: 50%;
-}
-
diff --git a/forms/ecomerce/basket/ui.xml b/forms/ecomerce/basket/ui.xml
deleted file mode 100644
index fd23a819..00000000
--- a/forms/ecomerce/basket/ui.xml
+++ /dev/null
@@ -1,73 +0,0 @@
-<vn>
-<div id="title">
-	<h1><t>ShoppingBasket</t></h1>
-</div>
-<div id="actions">
-	<htk-bar-button
-		icon="settings"
-		tip="_ConfigureOrder"
-		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 id="form" class="basket">
-	<div class="box vn-w-sm vn-pa-lg">
-		<div class="head vn-pb-lg">
-			<p>
-				<t>Total</t> 
-				<htk-text format="%.2d€">
-					<db-calc-sum property="param" func="subtotal" model="items"/>
-				</htk-text>
-			</p>
-		</div>
-		<div class="lines vn-pt-lg">
-			<htk-repeater form-id="iter">
-				<db-model id="items" property="model" updatable="true">
-					SELECT bi.id, bi.amount, bi.price, i.longName item,
-							i.tag5, i.value5, i.tag6, i.value6, i.tag7, i.value7,
-							i.image, im.updated
-						FROM myBasketItem bi
-							JOIN vn.item i ON i.id = bi.itemFk
-							LEFT JOIN image im
-								ON im.collectionFk = 'catalog'
-								AND im.name = i.image
-				</db-model>
-				<custom>
-					<div class="line">
-						<htk-button
-							class="delete"
-							tip="_Remove"
-							icon="delete"
-							on-click="this.onDeleteClick($iter)"/>
-						<htk-image
-							value="{{iter.image}}"
-							stamp-column="updated"
-							class="photo"
-							directory="catalog"
-							subdir="200x200"
-							full-dir="1600x900"/>
-						<div class="info">
-							<h2>{{iter.item}}</h2>
-							<p class="tags">
-								{{iter.value5}} {{iter.value6}} {{iter.value7}}
-							</p>
-							<span class="subtotal">
-								{{Vn.Value.format(iter.price * iter.amount, '%.2d€')}}
-							</span>
-							<p class="amount">
-								{{iter.amount}} x {{Vn.Value.format(iter.price, '%.2d€')}}
-							</p>
-						</div>
-					</div>
-				</custom>
-			</htk-repeater>
-		</div>
-	</div>
-</div>
-</vn>
diff --git a/forms/ecomerce/catalog/index.js b/forms/ecomerce/catalog/index.js
deleted file mode 100644
index 8b6eddd9..00000000
--- a/forms/ecomerce/catalog/index.js
+++ /dev/null
@@ -1,336 +0,0 @@
-import './style.scss';
-
-const Catalog = new Class({
-	Extends: Hedera.Form,
-	Template: require('./ui.xml')
-	
-	,_menuShown: false
-
-	,async open() {
-		let isOk = true;
-
-		if (!localStorage.getItem('hederaGuest'))
-			isOk = await Hedera.BasketChecker.check(this.conn, this.hash);
-		else
-			await this.conn.execQuery('CALL mybasket_configureForGuest');
-
-		if (isOk) await Hedera.Form.prototype.open.call(this);
-	}
-	
-	,activate() {
-		document.body.appendChild(this.$.rightPanel);
-		this.$.items.setInfo('i', 'item', 'vn', ['id']);
-		
-		if (localStorage.getItem('hederaView'))
-			this.setView(parseInt(localStorage.getItem('hederaView')));
-		else
-			this.setView(Catalog.View.GRID);
-
-		this.onFilterChange();
-	}
-	
-	,deactivate() {
-		this.hideMenu();
-		this.gui.$.topBar.style.backgroundColor = '';
-		Vn.Node.remove(this.$.rightPanel);
-	}
-
-	,getFilter(params, tags, currentTag) {
-		if (params.search == null && params.realm == null)
-			return;
-
-		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() {
-		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'
-		];
-
-		let hasTagFilter = false;
-		for (const tag of tags)
-		if (params[tag] != null) {
-			hasTagFilter = true;
-			break;
-		}
-
-		const refreshItems = hasTagFilter
-			|| params.search != null
-			|| params.type != null;
-
-		const lot = refreshItems && 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() {
-		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(view) {
-		if (view === Catalog.View.GRID) {
-			this.$.viewButton.setProperties({
-				icon: 'view_list',
-				tip: _('List view')
-			});
-			this.view = Catalog.View.GRID;
-			var className = 'grid-view';
-		} else {
-			this.$.viewButton.setProperties({
-				icon: 'grid_on',
-				tip: _('Grid view')
-			});
-			this.view = Catalog.View.LIST;
-			var className = 'list-view';
-		}
-		
-		var node = this.$.gridView.node;
-		node.className = className;
-		localStorage.setItem('hederaView', this.view);
-	}
-	
-	,onSwitchViewClick() {
-		this.setView(this.view === Catalog.View.LIST ?
-			Catalog.View.GRID : Catalog.View.LIST);
-	}
-	
-	,onItemsChange(model, status) {
-		if (status !== Db.Model.Status.CLEAN)
-			this.$.order.style.display = 'block';
-		else
-			this.$.order.style.display = 'none';
-	}
-	
-	,onOrderChange(e) {
-		var value = e.target.value;	
-		var sortField = value.substr(2);
-		var sortWay = value.charAt(0) === 'A' ?
-			Db.Model.SortWay.ASC : Db.Model.SortWay.DESC;
-		
-		if (sortField)
-			this.$.items.sortByName(sortField, sortWay);
-		
-		this.hideMenu();
-	}
-	
-	,realmRenderer(builder, form) {
-		var link = builder.$.link;
-		link.href = this.hash.make({
-			form: this.hash.$.form,
-			realm: form.$.id
-		});
-	}
-
-	,onRightPanelClick(event) {
-		event.stopPropagation();
-	}
-
-	,onShowMenuClick(event) {
-		this._menuShown = true;
-		event.stopPropagation();
-		this.gui.showBackground();
-		Vn.Node.addClass(this.$.rightPanel, 'show');
-		this.hideMenuCallback = this.hideMenu.bind(this);
-		document.addEventListener('click', this.hideMenuCallback);
-	}
-
-	,hideMenu() {
-		if (!this._menuShown)
-			return;
-
-		this.gui.hideBackground();
-		Vn.Node.removeClass(this.$.rightPanel, 'show');
-		document.removeEventListener('click', this.hideMenuCallback);
-		this.hideMenuCallback = null;
-	}
-	
-	,isGuest() {
-		if (localStorage.getItem('hederaGuest')) {
-			Htk.Toast.showError(_('YouMustBeLoggedIn'));
-			return true;
-		}
-		
-		return false;
-	}
-	
-	,onBasketClick() {
-		if (this.isGuest())
-			return;
-
-		this.hash.setAll({form: 'ecomerce/basket'});
-	}
-	
-	,onConfigureClick() {
-		if (this.isGuest())
-			return;
-
-		this.hash.setAll({form: 'ecomerce/checkout'});
-	}
-
-	,onAddItemClick(event, form) {
-		if (event.defaultPrevented) return;
-		event.preventDefault();
-		if (this.isGuest()) return;
-
-		this.onEraseClick();
-		this.$.$card.row = form.row;
-		this.$.cardLot.assign({item: form.$.id});
-		this.$.cardPopup.show(event.currentTarget);
-	}
-	
-	,onAddLotClick(column, value, row) {
-		var model = this.$.itemLots;
-		var grouping = model.get(row, 'grouping');
-		var warehouse = model.get(row, 'warehouseFk');
-		var available = model.get(row, 'available');
-
-		var lotAmount = this.items[warehouse];
-
-		if (lotAmount === undefined)
-			lotAmount = 0;
-		
-		if (lotAmount < available) {
-			var newAmount = lotAmount + grouping;
-		
-			if (newAmount > available)
-				newAmount = available;
-		
-			this.items[warehouse] = newAmount;
-			this.$.amount.value += newAmount - lotAmount;
-		} else
-			Htk.Toast.showError(_('NoMoreAmountAvailable'));
-	}
-	
-	,async onConfirmClick() {
-		var sql = '';
-		var query = new Sql.String({query: 'CALL myBasket_addItem(#warehouse, #item, #amount);'});
-		var amountSum = 0;
-
-		for (var warehouse in this.items) {
-			var amount = this.items[warehouse];
-			amountSum += amount;
-		
-			const params = {
-				warehouse: warehouse,
-				item: this.$.cardLot.$.item,
-				amount: amount
-			}
-			sql += query.render(params);
-		}
-	
-		if (amountSum > 0) {
-			this.conn.execQuery(sql);
-
-			var itemName = this.$.$card.get('item');
-			Htk.Toast.showMessage(
-				Vn.Value.sprintf(_('Added%dOf%s'), amountSum, itemName));
-		}
-
-		this.$.cardPopup.hide();
-	}
-	
-	,onEraseClick() {
-		this.$.amount.value = 0;
-		this.items = {};
-	}
-	
-	,onPopupClose() {
-		this.onEraseClick();
-		this.$.$card.row = -1;
-		this.$.cardLot.value = undefined;
-	}
-	
-	,onCardLoad() {
-		this.$.cardPopup.reset();
-	}
-});
-
-Catalog.extend({
-	View: {
-		LIST: 0,
-		GRID: 1
-	}
-});
-
-export default Catalog;
diff --git a/forms/ecomerce/catalog/locale/ca.yml b/forms/ecomerce/catalog/locale/ca.yml
deleted file mode 100644
index 31ee9147..00000000
--- a/forms/ecomerce/catalog/locale/ca.yml
+++ /dev/null
@@ -1,48 +0,0 @@
-Catalog: Catàleg
-SearchResults: Resultats de cerca
-SelectFamily: Selecciona una família
-Choose filter from right menu: Tria un filtre en el menú de la dreta
-Choose a realm: Tria un categoria
-ArticleNotFound: Artcle no trobat
-ArticleNotAvailable: Article no disponible
-List view: Vista de lista
-Grid view: Vista de reixeta
-Switch view: Canviar vista
-StartOrder: Començar comanda
-ShoppingBasket: Cistella de la compra
-Agency: Agència
-Warehouse: Magatzem
-Filter by: Filtrar per
-Order by: Ordenar per
-Search: Cercar
-Modify: Modificar
-Size: Mida
-Realm: Regne
-Family: Família
-Color: Color
-Producer: Productor
-Origin: Origen
-Category: Categoria
-Remove filters: Esborrar filtres
-Relevancy: Rellevància
-Price: Precio
-Amount: Quantitat
-Name: Nom
-Pack: Pack
-Lower price: Preu més baix
-Higher price: Preu més alt
-Lower size: Mida més petita
-Higher size: Mida més gran
-'%.0d Units': '%.0d Unitats'
-for: per
-Zoom image: Ampliar imatge
-AddToBasket: Afegir article
-Add: Afegir
-Erase: Esborrar
-Confirm: Confirmar
-IndicativePhotos: '* Les fotos són orientatives'
-Added%dOf%s: Afegits %d de %s
-NoMoreAmountAvailable: No hi ha més quantitat disponible
-MinimalGrouping: Empaquetat mínim
-Available: Disponible
-GroupingPrice: Preu per grup
diff --git a/forms/ecomerce/catalog/locale/en.yml b/forms/ecomerce/catalog/locale/en.yml
deleted file mode 100644
index 6940d979..00000000
--- a/forms/ecomerce/catalog/locale/en.yml
+++ /dev/null
@@ -1,48 +0,0 @@
-Catalog: Catalog
-SearchResults: Search results
-SelectFamily: Select family
-Choose filter from right menu: Choose a filter from the right menu
-Choose a realm: Choose a category
-ArticleNotFound: Item not found
-ArticleNotAvailable: Item not available
-List view: List view
-Grid view: Grid view
-Switch view: Switch view
-StartOrder: Start order
-ShoppingBasket: Shopping basket
-Agency: Agency
-Warehouse: Warehouse
-Filter by: Filter by
-Order by: Order by
-Search: Search
-Modify: Modify
-Size: Size
-Realm: Realm
-Family: Family
-Color: Color
-Producer: Producer
-Origin: Origin
-Category: Category
-Remove filters: Remove filters
-Relevancy: Relevance
-Price: Price
-Amount: Amount
-Name: Name
-Pack: Pack
-Lower price: Lower price
-Higher price: Higher price
-Lower size: Lower size
-Higher size: Higher size
-'%.0d Units': '%.0d Units'
-for: for
-Zoom image: Zoom image
-AddToBasket: Add to basket
-Add: Add
-Erase: Remove
-Confirm: Confirm
-IndicativePhotos: '* Photos are indicative'
-Added%dOf%s: Added %d of %s
-NoMoreAmountAvailable: No more amount available
-MinimalGrouping: Minimal packing
-Available: Available
-GroupingPrice: Price per group
diff --git a/forms/ecomerce/catalog/locale/es.yml b/forms/ecomerce/catalog/locale/es.yml
deleted file mode 100644
index 776ef9ba..00000000
--- a/forms/ecomerce/catalog/locale/es.yml
+++ /dev/null
@@ -1,48 +0,0 @@
-Catalog: Catálogo
-SearchResults: Resultados de búsqueda
-SelectFamily: Selecciona una familia
-Choose filter from right menu: Elige un filtro en el menú de la derecha
-Choose a realm: Elige una categoría
-ArticleNotFound: Artículo no encontrado
-ArticleNotAvailable: Artículo no disponible
-List view: Vista de lista
-Grid view: Vista de rejilla
-Switch view: Cambiar vista
-StartOrder: Empezar pedido
-ShoppingBasket: Cesta de la compra
-Agency: Agencia
-Warehouse: Almacén
-Filter by: Filtrar por
-Order by: Ordenar por
-Search: Buscar
-Modify: Modificar
-Size: Medida
-Realm: Reino
-Family: Familia
-Color: Color
-Producer: Productor
-Origin: Origen
-Category: Categoría
-Remove filters: Quitar filtros
-Price: Precio
-Amount: Cantidad
-Name: Nombre
-Pack: Pack
-Lower price: Precio más bajo
-Higher price: Precio más alto
-Lower size: Medida más pequeña
-Higher size: Medida más grande
-Relevancy: Relevancia
-'%.0d Units': '%.0d Unidades'
-for: por
-Zoom image: Ampliar imagen
-AddToBasket: Añadir artículo
-Add: Añadir
-Erase: Borrar
-Confirm: Confirmar
-IndicativePhotos: '* Las fotos son orientativas'
-Added%dOf%s: Añadidos %d de %s
-NoMoreAmountAvailable: No hay más cantidad disponible
-MinimalGrouping: Empaquetado mínimo
-Available: Disponible
-GroupingPrice: Precio per grupo
diff --git a/forms/ecomerce/catalog/locale/fr.yml b/forms/ecomerce/catalog/locale/fr.yml
deleted file mode 100644
index bd6266b7..00000000
--- a/forms/ecomerce/catalog/locale/fr.yml
+++ /dev/null
@@ -1,48 +0,0 @@
-Catalog: Catalogue
-SearchResults: Résultats de la recherche
-SelectFamily: Choisissez une famille
-Choose filter from right menu: Choisissez un filtre dans le menu de droite
-Choose a realm: Choisissez une catégorie
-ArticleNotFound: Article non trouvé
-ArticleNotAvailable: Article non disponible
-List view: Liste voir
-Grid view: Grille voir
-Switch view: Changer vue
-StartOrder: Acheter
-ShoppingBasket: Mon panier
-Agency: Agence
-Warehouse: Entrepôt
-Filter by: Filtrer par
-Order by: Trier par
-Search: Recherche
-Modify: Modifier
-Size: Mesure
-Realm: Famille
-Family: Sous-genre
-Color: Couleur
-Producer: Producteur
-Origin: Origine
-Category: Catégorie
-Remove filters: Retirer les filtres
-Relevancy: Pertinence
-Price: Prix
-Amount: Quantité
-Name: Nom
-Pack: Pack
-Lower price: Prix le plus bas
-Higher price: Prix le plus élevé
-Lower size: Taille le plus bas
-Higher size: Taille le plus élevé
-'%.0d Units': '%.0d Unités'
-for: pour
-Zoom image: Agrandir l'image
-AddToBasket: Ajouter article
-Add: Ajouter
-Erase: Effacer
-Confirm: Confirmer
-IndicativePhotos: '* Photos sont indicatifs'
-Added%dOf%s: Ajouté %d %s
-NoMoreAmountAvailable: Pas plus disponible
-MinimalGrouping: Emballage minimal
-Available: Disponible
-GroupingPrice: Prix par groupe
diff --git a/forms/ecomerce/catalog/locale/pt.yml b/forms/ecomerce/catalog/locale/pt.yml
deleted file mode 100644
index 9ade502e..00000000
--- a/forms/ecomerce/catalog/locale/pt.yml
+++ /dev/null
@@ -1,48 +0,0 @@
-Catalog: Catálogo
-SearchResults: Resultados de busca
-SelectFamily: Seleccione uma família
-Choose filter from right menu: Escolha um filtro no menú da direita
-Choose a realm: Escolha uma categoria
-ArticleNotFound: Ítem não encontrado
-ArticleNotAvailable: Ítem não disponível
-List view: Ver como lista
-Grid view: Vista em modo de grade
-Switch view: Modificar vista
-StartOrder: Iniciar encomenda
-ShoppingBasket: Cesta da compra
-Agency: Agência
-Warehouse: Armazém
-Filter by: Filtrar por
-Order by: Ordenar por
-Search: Buscar
-Modify: Modificar
-Size: Medida
-Realm: Reino
-Family: Família
-Color: Cor
-Producer: Produtor
-Origin: Orígem
-Category: Categoria
-Remove filters: Eliminar filtros
-Relevancy: Relevância
-Price: Preço
-Amount: Quantidade
-Name: Nome
-Pack: Pack
-Lower price: Menor preço
-Higher price: Maior preço
-Lower size: Tamanho menor
-Higher size: Tamanho maior
-'%.0d Units': '%.0d Unidades'
-por: para
-Zoom image: Mais zoom
-AddToBasket: Adicionar à Cesta
-Add: Adicionar
-Erase: Eliminar
-Confirm: Confirmar
-IndicativePhotos: '* As Fotos São Orientativas'
-Added%dOf%s: Adicionados %d de %s
-NoMoreAmountAvailable: Não há mais quantidade disponível
-MinimalGrouping: Embalagem mínima
-Available: Disponível
-GroupingPrice: Preço por grupo
diff --git a/forms/ecomerce/catalog/style.scss b/forms/ecomerce/catalog/style.scss
deleted file mode 100644
index a1cef51c..00000000
--- a/forms/ecomerce/catalog/style.scss
+++ /dev/null
@@ -1,438 +0,0 @@
-
-@import "htk/style/classes";
-
-.catalog {
-	margin-right: $side-panel-width;
-}
-.catalog-actions {
-	.htk-search-entry {
-		margin-right: 4px;
-	}
-	& > button.menu {
-		display: none;
-	
-		& > .htk-icon {
-			display: block;
-		}
-	}
-}
-.title ._subtitle {
-	font-size: .85rem;
-	color: #bbb;
-	text-overflow: ellipsis;
-	white-space: nowrap;
-	overflow: hidden;
-}
-
-/* Right panel */
-
-.catalog-panel {
-	background-color: #fafafa;
-
-	.basket-info {
-		background-color: #8cc63f;
-		color: white;
-		padding: 17px 28px;
-		border-radius: 7px;
-		margin: 14px;
-		text-align: center;
-
-		& > button {
-			color: white;
-			background-color: rgba(0, 0, 0, .1);
-			margin: 0 auto;
-			display: block;
-			margin-top: 10px;
-			padding: 10px 15px;
-		}
-		& > button:hover {
-			background-color: white;
-			color: #60872c;
-		}
-		& > p {
-			margin: 0;
-			padding: .4em 0;
-			text-overflow: ellipsis;
-			white-space: nowrap;
-			overflow: hidden;
-		}
-	}
-	.filter {
-		margin: 14px;
-	}
-	.categories,
-	.filters,
-	.order {
-		margin: 20px 0;
-	}
-	.filters,
-	.order {
-		display: none;
-	}
-	.realm-msg {
-		margin-top: 14px;
-	}
-	.realm-msg > h5 {
-		font-weight: normal;
-		text-align: center;
-		padding: 34px 0;
-		color: #777;
-	}
-	h2 {
-		font-weight: normal;
-		color: #777;
-		font-size: 1.1rem;
-	}
-	.realms > div > div {
-		text-align: center;
-	}
-	.realms a {
-		display: inline-block;
-		width: 25%;
-		padding: 8px;
-		box-sizing: border-box;
-		border-radius: 50%;
-	}
-	.realms a:hover {
-		background-color: rgba(1, 1, 1, .05);
-	}
-	.realms a > img {
-		display: block;
-		padding: 0;
-		width: 100%;
-	}
-	.filters > button {
-		margin-top: 14px;
-	}
-}
-
-/* Items */
-
-.item-box {
-	display: flex;
-	box-sizing: border-box;
-
-	& > .htk-image {
-		flex: none;
-	}
-	& > .item-info {
-		flex: auto;
-		position: relative;
-
-		.second-category {
-			font-weight: bold;
-			color: orange;
-		}
-		.third-category {
-			font-weight: bold;
-			color: red;
-		}
-		.item-id {
-			float: right;
-		}
-		& > .available-price {
-			position: absolute;
-			bottom: 0;
-			right: 0;
-			white-space: nowrap;
-			font-size: .95rem;
-			text-align: right;
-			align-items: middle;
-			column-gap: 3px;
-			display: flex;
-
-			& > * {
-				border-radius: 3px;
-				padding: 1px 5px;
-				border: 1px transparent solid;
-				box-sizing: border-box;
-			}
-		}
-		.grouping {
-			width: 44px;
-			background-color: #ddd;
-		}
-		.available {
-			width: 65px;
-			border-color: #bbb;
-			color: #777;
-		}
-		.price {
-			width: 75px;
-			border-color: #9cbc28;
-			color: #748c1e;
-		}
-	}
-}
-
-.item-info {
-	& > h2 {
-		font-weight: normal;
-		font-size: 1rem;
-		margin-bottom: 1px;
-		text-overflow: ellipsis;
-		overflow: hidden;
-	}
-	& > .sub-name {
-		margin: 0;
-		padding: 0;
-		color: #777;
-		font-size: .9rem;
-		text-overflow: ellipsis;
-		white-space: nowrap;
-		overflow: hidden;
-		text-transform: uppercase;
-		margin-bottom: 1px;
-	}
-	.item-id {
-		font-size: .9rem;
-		color: #777;
-	}
-	& > p {
-		margin: 0;
-		margin-bottom: 1px;
-	}
-}
-
-/* Tags */
-
-.grid-view,
-.list-view,
-.item-card {
-	.item-tags {
-		font-size: .8rem;
-		display: table;
-		color: #333;
-		margin: 0;
-		width: auto;
-		border-collapse: collapse;
-
-		td:first-child {
-			color: #999;
-			padding-right: 7px;
-		}
-	}
-}
-.grid-view,
-.item-card {
-	.item-tags {
-		td {
-			overflow: hidden;
-			white-space: nowrap;
-			text-overflow: ellipsis;
-			line-height: 14px;
-		}
-		td:first-child {
-			max-width: 90px;
-			width: 90px;
-		}
-		td:last-child {
-			max-width: 120px;
-			width: 120px;
-		}
-	}
-}
-
-/* Grid view */
-
-.grid-view {
-	& > * {
-		display: flex;
-		gap: 16px;
-		flex-wrap: wrap;
-		justify-content: center;
-	}
-	.item-box {
-		border-radius: 8px;
-		box-shadow: 1px 1px 3px rgba(0, 0, 0, .1);
-		overflow: hidden;
-		background-color: white;
-		flex-direction: column;
-		width: 210px;
-		overflow: hidden;
-
-		&:hover {
-			background-color: #efefef;
-		}
-		& > .htk-image {
-			width: 100%;
-			height: 180px;
-
-			& > img {
-				height: initial;
-			}
-		}
-		& > .item-info {
-			flex: auto;
-			overflow: hidden;
-			margin: 10px;
-			height: 170px;
-
-			& > h2 {
-				max-height: 3rem;
-			}
-			& > .item-tags {
-				position: absolute;
-				top: 75px;
-			}
-		}
-	}
-}
-
-/* List view */
-
-.list-view {
-	border-radius: 8px;
-	box-shadow: .05em .05em .2em rgba(0, 0, 0, .1);
-	overflow: hidden;
-	background-color: white;
-	max-width: 544px;
-	margin: 0 auto;
-
-	.item-box {
-		gap: 10px;
-		margin: 0;
-		padding: 10px;
-		height: 126px;
-		overflow: visible;
-		border-bottom: 1px solid #DDD;
-
-		&:last-child {
-			border-bottom: none;
-		}
-		& > .htk-image {
-			width: 105px;
-			height: 105px;
-			border-radius: 50%;
-		}
-		& > .item-info {
-			overflow: hidden;
-
-			& > h2 {
-				white-space: nowrap;
-			}
-			& > .color {
-				display: none;
-			}
-			& > .htk-button {
-				float: right;
-			}
-			& > .item-tags {
-				display: block;
-				text-overflow: ellipsis;
-				white-space: nowrap;
-				overflow: hidden;
-		
-				& > tr {
-					display: inline-block;
-				}
-				td {
-					display: inline-block;
-					padding-right: 7px;
-		
-					&:first-child {
-						display: none;
-					}
-				}
-			}
-		}
-	}
-}
-
-/* Card */
-
-.card-popup {
-	overflow: auto;
-}
-.item-card {
-	font-size: .9rem;
-	max-width: 320px;
-	overflow: hidden;
-
-	& > .top {
-		padding: 14px;
-
-		& > .item-info {
-			margin-left: 126px;
-			height: 112px;
-
-			& > h2 {
-				max-height: 4.5rem;
-			}
-		}
-		& > .htk-image {
-			height: 112px;
-			width: 112px;
-			float: left;
-			border-radius: 4px;
-		}
-		& > .desc {
-			clear: both;
-			margin-top: 15px 0;
-			font-size: .9rem;
-		}
-	}
-	& > .lots-grid {
-		border-top: 1px solid #DDD;
-
-		tr {
-			height: 45px;
-		}
-		.cell-spin {
-			max-width: initial;
-			width: 42px;
-		}
-		.price-kg {
-			font-size: .8rem;
-			color: #999;
-			width: 1px;
-		}
-		.cell-text {
-			max-width: initial;
-			width: auto;
-		}
-		.cell-button {
-			max-width: initial;
-			width: 14px;
-		}
-	}
-	& > .footer {
-		display: flex;
-		align-items: center;
-		justify-content: space-between;
-		background-color: #1a1a1a;
-		color: white;
-		padding: 10px;
-
-		& > button {
-			&:hover {
-				background-color: rgba(255, 255, 255, .1);
-			}
-			& > .htk-icon {
-				display: block;
-			}
-		}
-	}
-}
-
-/* Mobile */
-
-@include mobile {
-	.catalog-actions > button.menu {
-		display: block;
-	}
-	.catalog {
-		margin-right: 0;
-	}
-}
-@media (max-width: 650px) {
-	.grid-view .item-box {
-		width: 100%;
-		max-width: 450px;
-
-		& > .htk-image {
-			height: initial;
-			max-height: 260px;
-		}
-	}
-}
diff --git a/forms/ecomerce/catalog/ui.xml b/forms/ecomerce/catalog/ui.xml
deleted file mode 100644
index 5c2e3b6e..00000000
--- a/forms/ecomerce/catalog/ui.xml
+++ /dev/null
@@ -1,515 +0,0 @@
-<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-lot-query id="params" on-change="this.onFilterChange()">
-		<vn-spec name="search" type="String"/>
-		<vn-spec name="realm" type="Number"/>
-		<vn-spec name="type" type="Number"/>
-		<vn-spec name="color" type="String"/>
-		<vn-spec name="origin" type="Number"/>
-		<vn-spec name="category" type="String"/>
-		<vn-spec name="producer" type="Number"/>
-	</vn-lot-query>
-	<vn-lot id="filter-lot"/>
-</vn-group>
-<vn-group>
-	<sql-filter-item
-		id="id-op"
-		type="EQUAL"
-		target="i"
-		field="id"
-		param="search"/>
-	<sql-operation
-		id="search-op"
-		type="OR">
-		<sql-filter-item
-			type="LIKE"
-			target="i"
-			field="longName"
-			param="search"/>
-		<sql-filter-item
-			type="LIKE"
-			target="i"
-			field="subname"
-			param="search"/>
-	</sql-operation>
-	<sql-filter-item
-		id="realm-op"
-		type="EQUAL"
-		target="t"
-		field="categoryFk"
-		param="realm"/>
-	<sql-filter-item
-		id="type-op"
-		type="EQUAL"
-		target="i"
-		field="typeFk"
-		param="type"/>
-	<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">
-			SELECT b.id, b.sent, a.description agency, m.code method
-				FROM myBasket b
-					JOIN vn.agencyMode a ON a.id = b.agencyModeFk
-					JOIN vn.deliveryMethod m ON m.id = b.deliveryMethodFk
-		</db-model>
-	</db-form>
-	<db-model
-		id="items"
-		auto-load="false"
-		result-index="3"
-		on-status-changed="onItemsChange">
-		DROP TEMPORARY TABLE IF EXISTS tmp.item;
-		CREATE TEMPORARY TABLE tmp.item
-			(INDEX (itemFk))
-			ENGINE = MEMORY
-			SELECT i.id itemFk
-				FROM vn.item i
-					JOIN vn.itemType t ON t.id = i.typeFk
-				WHERE #filter;
-		CALL myBasket_calcCatalogFull;
-		SELECT i.id, i.longName item, i.subName,
-				i.tag5, i.value5, i.tag6, i.value6, i.tag7, i.value7,
-				i.relevancy, i.size, i.category,
-				k.name ink, p.name producer, o.name origin,
-				b.available, b.price, b.`grouping`,
-				i.image, im.updated
-			FROM tmp.ticketCalculateItem b
-				JOIN vn.item i ON i.id = b.itemFk
-				LEFT JOIN vn.ink k ON k.id = i.inkFk
-				LEFT JOIN vn.producer p ON p.id = i.producerFk
-				LEFT JOIN vn.origin o ON o.id = i.originFk
-				LEFT JOIN image im
-					ON im.collectionFk = 'catalog'
-					AND im.name = i.image
-			WHERE b.available > 0
-			ORDER BY i.relevancy DESC, i.name, i.size
-			LIMIT 5000;
-		DROP TEMPORARY TABLE
-			tmp.item,
-			tmp.ticketCalculateItem,
-			tmp.ticketComponentPrice,
-			tmp.ticketComponent,
-			tmp.ticketLot,
-			tmp.zoneGetShipped;
-	</db-model>
-	<db-form id="$card" v-model="card" model="items"/>
-	<vn-lot id="card-lot"/>
-</vn-group>
-<div id="form" class="catalog">
-	<div id="main" class="main">
-	<htk-repeater
-		id="grid-view"
-		empty-message="_Choose filter from right menu"
-		form-id="item"
-		model="items">
-		<custom>
-		<div
-			id="item-box"
-			class="item-box clickable"
-			title="{{_('AddToBasket')}}"
-			on-click="this.onAddItemClick($event, $iter)">
-			<htk-image
-				directory="catalog"
-				subdir="200x200"
-				form="$iter"
-				column="image"
-				stamp-column="updated"
-				full-dir="1600x900"
-				title="_Zoom image"/>
-			<div class="item-info">
-				<h2>
-					{{item.item}}
-				</h2>
-				<p class="sub-name">
-					<span class="item-id">
-						#{{item.id}}
-					</span>
-					{{item.subName}}
-				</p>
-				<table class="item-tags">
-					<tr>
-						<td>{{item.tag5}}</td>
-						<td>{{item.value5}}</td>
-					</tr>
-					<tr>
-						<td>{{item.tag6}}</td>
-						<td>{{item.value6}}</td>
-					</tr>
-					<tr>
-						<td>{{item.tag7}}</td>
-						<td>{{item.value7}}</td>
-					</tr>
-				</table>
-				<div class="available-price">
-					<span class="grouping" title="_MinimalGrouping">
-						{{Vn.Value.format(item.grouping, 'x%.0d')}}
-					</span> 
-					<span class="available" title="_Available">
-						{{item.available}}
-					</span> 
-					<span class="price" title="_GroupingPrice">
-						{{Vn.Value.format(item.price, '%.02d€')}}
-					</span>
-				</div>
-			</div>
-		</div>
-		</custom>
-	</htk-repeater>
-	</div>
-</div>
-<div id="right-panel" class="catalog-panel right-panel side-panel" on-click="onRightPanelClick">
-	<div class="basket-info">
-		<p>{{Vn.Value.format(basket.sent, '%D')}}</p>
-		<p>
-			{{_(basket.method != 'PICKUP' ? 'Agency' : 'Warehouse')}} 
-			{{basket.agency}}
-		</p>
-		<button class="thin" on-click="this.onConfigureClick()">
-			<t>Modify</t>
-		</button>
-	</div>
-	<div class="filter">
-		<div class="categories">
-			<div class="realms">
-				<htk-repeater
-					form-id="form"
-					renderer="realmRenderer"
-					class="realms-box">
-					<db-model
-						id="realms"
-						property="model"
-						on-status-changed="refreshTitle">
-						SELECT c.id, l.name, c.color, c.code
-							FROM vn.itemCategory c
-								JOIN vn.itemCategoryL10n l ON l.id = c.id
-							WHERE c.display
-							ORDER BY display
-					</db-model>
-					<custom>
-						<a id="link">
-							<img
-								id="image"
-								src="{{`image/family/black/${form.code}.svg`}}"
-								title="{{form.name}}"
-								alt="{{form.name}}"/>
-						</a>
-					</custom>
-				</htk-repeater>
-				<div class="clear"/>
-			</div>
-		</div>
-		<div id="realm-msg" class="realm-msg">
-			<h5><t>Choose a realm</t></h5>
-		</div>
-		<div id="filters" class="filters">
-			<h2><t>Filter by</t></h2>
-			<htk-combo
-				placeholder="_Family"
-				form="params"
-				column="type"
-				id="type-filter">
-				<db-model
-					id="types"
-					property="model"
-					conn="conn"
-					lot="params"
-					result-index="1"
-					on-status-changed="refreshTitle">
-					CALL myBasket_getAvailable;
-					SELECT DISTINCT t.id, l.name
-						FROM vn.item i
-							JOIN vn.itemType t ON t.id = i.typeFk
-							JOIN tmp.itemAvailable a ON a.id = i.id
-							JOIN vn.itemTypeL10n l ON l.id = t.id
-						WHERE t.`order` >= 0
-							AND t.categoryFk = #realm
-						ORDER BY t.`order`, l.name;
-					DROP TEMPORARY TABLE tmp.itemAvailable;
-				</db-model>
-			</htk-combo>
-			<htk-combo
-				placeholder="_Color"
-				form="params"
-				column="color"
-				on-mousedown="colors.lazyRefresh()">
-				<db-model
-					id="colors"
-					property="model"
-					auto-load="false"
-					result-index="1">
-					CALL myBasket_getAvailable;
-					SELECT DISTINCT l.id, l.name
-						FROM vn.item i
-							JOIN vn.itemType t ON t.id = i.typeFk
-							JOIN tmp.itemAvailable a ON a.id = i.id
-							JOIN vn.inkL10n l ON l.id = i.inkFk
-						WHERE #filter
-						ORDER BY name;
-					DROP TEMPORARY TABLE tmp.itemAvailable;
-				</db-model>
-			</htk-combo>
-			<htk-combo
-				placeholder="_Producer"
-				form="params"
-				column="producer"
-				on-mousedown="producers.lazyRefresh()">
-				<db-model
-					id="producers"
-					property="model"
-					auto-load="false"
-					result-index="1">
-					CALL myBasket_getAvailable;
-					SELECT DISTINCT p.id, p.name
-						FROM vn.item i 
-							JOIN vn.itemType t ON t.id = i.typeFk
-							JOIN tmp.itemAvailable a ON a.id = i.id
-							JOIN vn.producer p ON p.id = i.producerFk
-						WHERE #filter
-						ORDER BY name;
-					DROP TEMPORARY TABLE tmp.itemAvailable;
-				</db-model>
-			</htk-combo>
-			<htk-combo
-				placeholder="_Origin"
-				form="params"
-				column="origin"
-				on-mousedown="origins.lazyRefresh()">
-				<db-model
-					id="origins"
-					property="model"
-					auto-load="false"
-					result-index="1">
-					CALL myBasket_getAvailable;
-					SELECT DISTINCT o.id, l.name, o.code
-						FROM vn.item i 
-							JOIN vn.itemType t ON t.id = i.typeFk
-							JOIN tmp.itemAvailable a ON a.id = i.id
-							JOIN vn.origin o ON o.id = i.originFk
-							JOIN vn.originL10n l ON l.id = o.id
-						WHERE #filter
-						ORDER BY name;
-					DROP TEMPORARY TABLE tmp.itemAvailable;
-				</db-model>
-			</htk-combo>
-			<htk-combo
-				placeholder="_Category"
-				form="params"
-				column="category"
-				on-mousedown="categorys.lazyRefresh()">
-				<db-model
-					id="categorys"
-					property="model"
-					auto-load="false"
-					result-index="1">
-					CALL myBasket_getAvailable;
-					SELECT DISTINCT i.category, i.category
-						FROM vn.item i 
-							JOIN vn.itemType t ON t.id = i.typeFk
-							JOIN tmp.itemAvailable a ON a.id = i.id
-						WHERE #filter
-						ORDER BY category;
-					DROP TEMPORARY TABLE tmp.itemAvailable;
-				</db-model>
-			</htk-combo>
-		</div>
-		<div id="order" class="order">
-			<h2><t>Order by</t></h2>
-			<select on-change="onOrderChange">
-				<option value="D|relevancy" selected="true">
-					<t>Relevancy</t>
-				</option>
-				<option value="A|item">
-					<t>Name</t>
-				</option>
-				<option value="A|price">
-					<t>Lower price</t>
-				</option>
-				<option value="D|price">
-					<t>Higher price</t>
-				</option>
-				<option value="A|available">
-					<t>Available</t>
-				</option>
-				<option value="A|size">
-					<t>Lower size</t>
-				</option>
-				<option value="D|size">
-					<t>Higher size</t>
-				</option>
-				<option value="A|ink">
-					<t>Color</t>
-				</option>
-				<option value="A|producer">
-					<t>Producer</t>
-				</option>
-				<option value="A|origin">
-					<t>Origin</t>
-				</option>
-				<option value="A|category">
-					<t>Category</t>
-				</option>
-			</select>
-		</div>
-	</div>
-</div>
-<htk-popup id="desc-popup">
-	<div
-		property="child-node"
-		class="desc-popup"
-		id="description"/>
-</htk-popup>
-<htk-popup
-	id="card-popup"
-	class="card-popup"
-	modal="true"
-	on-closed="onPopupClose">
-	<div property="child-node" class="item-card">
-		<db-form vModel="extendedCard">
-			<db-model
-				property="model"
-				lot="card-lot"
-				on-status-changed-after="onCardLoad">
-				SELECT i.description, o.name origin
-					FROM vn.item i
-						LEFT JOIN vn.originL10n o ON o.id = i.originFk
-					WHERE i.id = #item
-			</db-model>
-		</db-form>
-		<div class="top">
-			<htk-image
-				directory="catalog"
-				subdir="200x200"
-				form="$card"
-				column="image"
-				stamp-column="updated"
-				full-dir="1600x900"
-				conn="conn"
-				editable="true"/>
-			<div class="item-info">
-				<h2>{{card.item}}</h2>
-				<p class="sub-name">{{card.subName}}</p>
-				<p class="item-id">#{{card.id}}</p>
-				<p>{{Vn.Value.format(card.stems, _('%.0d Units'))}}</p>
-			</div>
-			<p class="desc">{{extendedCard.description}}</p>
-			<htk-repeater show-status="false" form-id="tag" class="item-tags">
-				<db-model
-					property="model"
-					lot="card-lot"
-					on-status-changed-after="onCardLoad">
-					SELECT l.name, it.value
-						FROM vn.itemTag it
-							JOIN vn.tag t ON t.id = it.tagFk
-							JOIN vn.tagL10n l ON l.id = t.id
-						WHERE it.itemFk = #item
-							AND priority >= 0
-						ORDER BY it.priority
-				</db-model>
-				<custom>
-					<tr>
-						<td>{{tag.name}}</td>
-						<td>{{tag.value}}</td>
-					</tr>
-				</custom>
-			</htk-repeater>
-		</div>
-		<htk-grid class="lots-grid" show-header="false">
-			<db-model
-				id="item-lots"
-				property="model"
-				result-index="1"
-				on-status-changed-after="onCardLoad"
-				lot="card-lot">
-				CALL myBasket_calcCatalogFromItem(#item);
-				SELECT l.warehouseFk, w.name warehouse, p.`grouping`,
-						p.price, p.priceKg, p.rate, l.available
-					FROM tmp.ticketLot l
-						JOIN tmp.ticketComponentPrice p ON p.warehouseFk = l.warehouseFk
-						JOIN vn.warehouse w ON w.id = p.warehouseFk
-					ORDER BY warehouseFk, `grouping`;
-				DROP TEMPORARY TABLE
-					tmp.ticketCalculateItem,
-					tmp.ticketComponentPrice,
-					tmp.ticketComponent,
-					tmp.ticketLot,
-					tmp.zoneGetShipped;
-			</db-model>
-			<htk-column-spin column="price" unit="€" digits="2"/>
-			<htk-column-spin column="priceKg" unit="€/kg" digits="3" class="price-kg"/>
-			<htk-column-text column="grouping" format="x%.0d"/>
-			<htk-column-button
-				column="id"
-				icon="add"
-				tip="_Add"
-				on-clicked="onAddLotClick"/>
-		</htk-grid>
-		<div class="footer">
-			<button
-				title="_Erase"
-				on-click="this.onEraseClick()"
-				class="erase">
-				<htk-icon
-					name="delete"
-					theme="dark"
-					alt="_Erase"/>
-			</button>
-			<htk-text id="amount"/>
-			<button
-				title="_Confirm"
-				on-click="this.onConfirmClick()"
-				class="confirm">
-				<htk-icon
-					name="done"
-					theme="dark"
-					alt="_Confirm"/>
-			</button>
-		</div>
-	</div>
-</htk-popup>
-</vn>
diff --git a/forms/ecomerce/checkout/index.js b/forms/ecomerce/checkout/index.js
deleted file mode 100644
index 90cda232..00000000
--- a/forms/ecomerce/checkout/index.js
+++ /dev/null
@@ -1,215 +0,0 @@
-import './style.scss';
-
-export default new Class({
-	Extends: Hedera.Form,
-	Template: require('./ui.xml'),
-
-	activate() {
-		this.autoStepLocked = true;
-		this.$.assistant.stepsIndex = this.agencySteps;
-
-		this.today = new Date();
-		this.today.setHours(0, 0, 0, 0);
-	},
-
-	onValuesReady() {
-		const orderForm = this.$.orderForm;
-		const defaultsForm = this.$.defaults;
-
-		if (!(orderForm.ready && defaultsForm.ready))
-			return;
-
-		let date;
-		const row = orderForm.$ || defaultsForm.$ || {};
-		
-		if (!date || date.getTime() < (new Date()).getTime()) {
-			date = new Date();
-			date.setHours(0, 0, 0, 0);
-
-			let addDays = 0;
-
-			switch(date.getDay()) {
-				case 6: // Saturday
-					addDays += 2;
-					break;
-				case 0: // Sunday
-					addDays++;
-					break;
-			}
-
-			if (row.deliveryMethod != 'PICKUP')
-				addDays++;
-
-			date.setDate(date.getDate() + addDays);
-		}
-
-		this.$.lot.assign({
-			date: date,
-			method: row.deliveryMethod,
-			agency: row.agencyModeFk,
-			address: row.addressFk
-		});
-		this.autoStepLocked = false;
-	},
-	
-	disableButtons(disable) {
-		this.$.assistantBar.disabled = disable;
-	},
-
-	async onConfirmClick() {
-		this.disableButtons(true);
-	
-		const query = 'CALL myBasket_configure(#date, #method, #agency, #address)';
-		let resultSet;
-		
-		try {
-			resultSet = await this.conn.execQuery(query, this.$.lot.$);
-		} finally {
-			this.disableButtons(false);
-		}
-
-		if (!resultSet.fetchResult())
-			return;
-	
-		if (this.$.orderForm.numRows > 0)
-			Htk.Toast.showMessage(_('OrderUpdated'));
-		else
-			Htk.Toast.showMessage(_('OrderStarted'));
-
-		this.hash.setAll({form: 'ecomerce/catalog'});
-	},
-
-	onCancelClick() {
-		if (this.$.orderForm.numRows > 0)
-			window.history.back();
-		else
-			this.hash.setAll({form: 'ecomerce/orders'});
-	},
-	
-	agencySteps: ['method', 'date', 'address', 'agency', 'confirm-delivery'],
-	pickupSteps: ['method', 'date', 'address', 'pickup', 'confirm-pickup'],
-
-	isDelivery() {
-		return this.$.rgMethod.value != 'PICKUP';
-	},
-
-	onMethodChange() {
-		this.$.assistant.stepsIndex = this.isDelivery() ?
-			this.agencySteps : this.pickupSteps;
-		this.onFieldChange();
-	},
-
-	methodValidate() {
-		if (!this.$.rgMethod.isSelected())
-			throw new Error(_('Please select an option'));
-	},
-
-	dateShow() {
-		Vn.Node.setText(this.$.dateQuestion, this.isDelivery() ?
-			_('OrderDateDeliveryQuestion'):
-			_('OrderDatePickupQuestion'));
-		this.$.calendar.goToSelectedMonth();
-	},
-
-	dateValidate() {
-		if (!this.$.calendar.value)
-			throw new Error(_('Please select a date'));
-	},
-
-	addressShow() {
-		Vn.Node.setText(this.$.addressQuestion, this.isDelivery() ?
-			_('AddressQuestion'):
-			_('AddressQuestionPickup'));
-	},
-
-	addressValidate() {
-		if (this.$.addressForm.row == -1)
-			throw new Error(_('Please select an address'));
-	},
-
-	agencyShow() {
-		this.$.agencies.refresh();
-	},
-
-	agencyValidate() {
-		if (this.$.agencyCombo.row == -1 && this.isDelivery())
-			throw new Error(_('Please select an agency'));
-	},
-
-	pickupShow() {
-		this.$.warehouses.refresh();
-	},
-
-	pickupValidate() {
-		if (this.$.warehouseCombo.row == -1)
-			throw new Error(_('Please select a store'));
-	},
-	
-	onFieldChange() {
-		if (!this.autoStepLocked)
-			this.$.assistant.moveNext();
-	},
-	
-	goNextStep() {
-		this.$.assistant.moveNext();
-	},
-	
-	onAddressClick(addressId) {
-		this.$.lot.set('address', addressId);
-		this.goNextStep();
-	},
-	
-	onAddressChange() {
-		if (this.selectedNode)
-			Vn.Node.removeClass(this.selectedNode, 'selected');
-
-		const row = this.$.addresses.search('id', this.$.lot.$.address);
-
-		if (row != -1) {
-			const builder = this.$.repeater.getBuilder(row);
-		
-			this.selectedNode = builder.$.address;
-			Vn.Node.addClass(this.selectedNode, 'selected');
-		}
-
-		this.$.addressForm.row = row;
-	},
-	
-	onAgenciesReady(model) {
-		this.selectAgency(model, 'NoAgeciesAvailableForDate');
-	},
-	
-	onWarehousesReady(model) {
-		this.selectAgency(model, 'NoWarehousesAvailableForDate');
-	},
-
-	selectAgency(model, emptyMessage) {
-		if (!model.ready) return;
-		let agencyId = null;
-
-		if (model.numRows > 0) {
-			const agencies = [this.$.lot.$.agency];
-
-			const defaults = this.$.defaults.$ || {};
-			if (defaults.agencyModeFk)
-				defaults.push(defaults.agencyModeFk);
-			if (defaults.defaultAgencyFk)
-				defaults.push(defaults.defaultAgencyFk);
-
-			for (const agency of agencies)
-			if (model.search('id', agency) !== -1) {
-				agencyId = agency;
-				break;
-			}
-		} else
-			Htk.Toast.showError(_(emptyMessage));
-
-		this.autoStepLocked = true;
-		this.$.lot.assign({agency: agencyId});
-		this.autoStepLocked = false;
-	},
-	
-	calendarRestrict(date) {
-		return date.getTime() >= this.today.getTime();
-	}
-});
diff --git a/forms/ecomerce/checkout/locale/ca.yml b/forms/ecomerce/checkout/locale/ca.yml
deleted file mode 100644
index 41a84a8f..00000000
--- a/forms/ecomerce/checkout/locale/ca.yml
+++ /dev/null
@@ -1,34 +0,0 @@
-ConfigureOrder: Configurar comanda
-Cancel: Cancelar
-Next: Següent
-DeliveryOrPickupQuestion: Vols rebre o recollir la comanda?
-Receive the order: Rebre en mi tenda
-ReceiveThroughtRoute: Repartiment Verdnatura
-PickupInStore: Recollir en magatzem
-OrderDateDeliveryQuestion: Quin dia vols rebre la comanda?
-OrderDatePickupQuestion: Quin dia vols recollir la comanda?
-AddressQuestion: On vols rebre la comanda?
-AddressQuestionPickup: A què direcció vols associar la comanda? (Opcional)
-AgencyQuestion: Com vols rebre la comanda?
-PickupWarehouseQuestion: En quin magatzem vols recollir la comanda?
-ConfirmData: Confirma les dades
-Arrival: Arribada
-Pickup: Recollida
-Agency: Agència
-Warehouse: Magatzem
-Confirm: Confirmar
-OrderStarted: Comanda començada
-OrderUpdated: Comanda actualitzada
-Please select an option: Si us plau tria una opció
-Please select a date: Si us plau tria una data
-Please select an address: Si us plau tria una direcció
-Please select an agency: Si us plau tria una agència
-Please select a store: Si us plau tria un magatzem
-NoAgeciesAvailableForDate: >-
-  No hi ha agències disponibles per a la data i el consignatari seleccionats,
-  comprova la data de la comanda i que consignatari seleccionat conté una 
-  província i codi postal correctes
-NoWarehousesAvailableForDate: >-
-  No hi ha magatzems disponibles per a la data seleccionada, comprova la data
-  de recollida de la comanda i que consignatari seleccionat conté una província 
-  i codi postal correctes
diff --git a/forms/ecomerce/checkout/locale/en.yml b/forms/ecomerce/checkout/locale/en.yml
deleted file mode 100644
index c9c94c90..00000000
--- a/forms/ecomerce/checkout/locale/en.yml
+++ /dev/null
@@ -1,33 +0,0 @@
-ConfigureOrder: Configure order
-Cancel: Cancel
-Next: Next
-DeliveryOrPickupQuestion: Do you want to receive or pickup the order?
-Receive the order: Receive in my store
-ReceiveThroughtRoute: Verdnatura delivery
-PickupInStore: Store pickup
-OrderDateDeliveryQuestion: What day you want to receive the order?
-OrderDatePickupQuestion: What day you want to pickup your order?
-AddressQuestion: Where do you want to receive the order?
-AddressQuestionPickup: To which address do you want to associate the order? (Optional)
-AgencyQuestion: How you want to receive the order?
-PickupWarehouseQuestion: What store you want to pickup your order?
-ConfirmData: Confirm the data
-Arrival: Arrival
-Pickup: Pickup
-Agency: Agency
-Warehouse: Store
-Confirm: Confirm
-OrderStarted: Order started
-OrderUpdated: Order updated
-Please select an option: Please select an option
-Please select a date: Please select a date
-Please select an address: Please select an address
-Please select an agency: Please select an agency
-Please select a store: Please select a store
-NoAgeciesAvailableForDate: >-
-  There are no agencies available for the selected date and consignee, check 
-  the date of the order and that selected address contains a correct province 
-  and zip code
-NoWarehousesAvailableForDate: >-
-  There are no stores available for the selected date, check the date of order 
-  pickup and that selected address contains a correct province and zip code
diff --git a/forms/ecomerce/checkout/locale/es.yml b/forms/ecomerce/checkout/locale/es.yml
deleted file mode 100644
index b2276376..00000000
--- a/forms/ecomerce/checkout/locale/es.yml
+++ /dev/null
@@ -1,34 +0,0 @@
-ConfigureOrder: Configurar pedido
-Cancel: Cancelar
-Next: Siguiente
-DeliveryOrPickupQuestion: ¿Quieres recibir o recoger el pedido?
-Receive the order: Recibir en mi tienda
-ReceiveThroughtRoute: Reparto Verdnatura
-PickupInStore: Recoger en almacén
-OrderDateDeliveryQuestion: ¿Qué día quieres recibir el pedido?
-OrderDatePickupQuestion: ¿Qué día quieres recoger el pedido?
-AddressQuestion: ¿Dónde quieres recibir el pedido?
-AddressQuestionPickup: ¿A qué dirección quieres asociar el pedido? (Opcional)
-AgencyQuestion: ¿Cómo quieres recibir el pedido?
-PickupWarehouseQuestion: ¿En qué almacén quieres recoger el pedido?
-ConfirmData: Confirma los datos
-Arrival: Llegada
-Pickup: Recogida
-Agency: Agencia
-Warehouse: Almacén
-Confirm: Confirmar
-OrderStarted: Pedido empezado
-OrderUpdated: Pedido actualizado
-Please select an option: Por favor elige una opción
-Please select a date: Por favor elige una fecha
-Please select an address: Por favor elige una dirección
-Please select an agency: Por favor elige una agencia
-Please select a store: Por favor elige un almacén
-NoAgeciesAvailableForDate: >-
-  No hay agencias disponibles para la fecha y el consignatario seleccionados, 
-  comprueba la fecha del pedido y que consignatario seleccionado
-  contiene una provincia y código postal correctos
-NoWarehousesAvailableForDate: >-
-  No hay almacenes disponibles para la fecha seleccionada, comprueba la fecha
-  de recogida del pedido y que consignatario seleccionado contiene una 
-  provincia y código postal correctos
diff --git a/forms/ecomerce/checkout/locale/fr.yml b/forms/ecomerce/checkout/locale/fr.yml
deleted file mode 100644
index 53166061..00000000
--- a/forms/ecomerce/checkout/locale/fr.yml
+++ /dev/null
@@ -1,34 +0,0 @@
-ConfigureOrder: Configurez votre commande
-Cancel: Annuler
-Next: Suivant
-DeliveryOrPickupQuestion: Voulez-vous recevoir ou récuperer l'ordre?
-Receive the order: Livraison à la boutique
-ReceiveThroughtRoute: Livraison par Verdnatura
-PickupInStore: Récupérer en entrepôt
-OrderDateDeliveryQuestion: Date de livraison?
-OrderDatePickupQuestion: Date retrait commande?
-AddressQuestion: Adresse livraison?
-AddressQuestionPickup: À quelle adresse voulez-vous associer la commande? (Optionnel)
-AgencyQuestion: Agence de livraison
-PickupWarehouseQuestion: Dans quel magasin vuoulez-vous retirer votre commande?
-ConfirmData: Confirmez les coordonnées
-Arrival: Arrivée
-Pickup: Retrait
-Agency: Agence
-Warehouse: MAgasin
-Confirm: Confirmer
-OrderStarted: Commande a commencé
-OrderUpdated: Mise à jour commande
-Please select an option: Veuillez choisir une option
-Please select a date: Veuillez choisir une date
-Please select an address: Veuillez choisir une adresse
-Please select an agency: Veuillez choisir une agence
-Please select a store: Veuillez choisir un entrepôt
-NoAgeciesAvailableForDate: >-
-  Aucune agence disponibles pour la date et le destinataire sélectionné, changer
-  la date d'envoi de la commande et vérifier quel destinataire a été sélectionné
-   contient une province et un code postal correct
-NoWarehousesAvailableForDate: >-
-  Pas de magasins disponibles à la date sélectionnée, changer la date de 
-  retrait et vérifier quel destinataire a été sélectionné contient une province 
-  et un code postal correct
diff --git a/forms/ecomerce/checkout/locale/pt.yml b/forms/ecomerce/checkout/locale/pt.yml
deleted file mode 100644
index c6f76484..00000000
--- a/forms/ecomerce/checkout/locale/pt.yml
+++ /dev/null
@@ -1,34 +0,0 @@
-ConfigureOrder: Configurar encomenda
-Cancel: Cancelar
-Next: Seguir
-DeliveryOrPickupQuestion: Queres receber ou levantar a encomenda?
-Receive the order: Receber na minha loja
-ReceiveThroughtRoute: Transporte Verdnatura
-PickupInStore: Levantar no armazém
-OrderDateDeliveryQuestion: Que dia queres receber a encomenda?
-OrderDatePickupQuestion: Que dia queres levantar a encomenda?
-AddressQuestion: Onde queres receber a encomenda?
-AddressQuestionPickup: Para qual endereço deseja associar o pedido? (Opcional)
-AgencyQuestion: Como queres receber a encomenda?
-PickupWarehouseQuestion: Em qual armazém queres levantar a encomenda?
-ConfirmData: Confirme os dados
-Arrival: Chegada
-Pickup: Recolhida
-Agency: Agência
-Warehouse: Armazém
-Confirm: Confirmar
-OrderStarted: Encomenda iniciada
-OrderUpdated: Encomenda actualizada
-Please select an option: Por favor escolha uma opção
-Please select a date: Por favor, escolha uma data
-Please select an address: Por favor, escolha um endereço
-Please select an agency: Por favor, escolha uma agência
-Please select a store: Por favor, escolha um armazém
-NoAgeciesAvailableForDate: >-
-  Não há agências disponíveis para a data e o consignatario escolhido, modifique
-  a data de envío do pedido e verifique qual destinatário selecionou contém uma 
-  província e código postal corretos
-NoWarehousesAvailableForDate: >-
-  Não há armazéns disponíveis para a data seleccionada, modifique a data para
-  levantar a encomenda e verifique qual destinatário selecionou contém uma 
-  província e código postal corretos
diff --git a/forms/ecomerce/checkout/style.scss b/forms/ecomerce/checkout/style.scss
deleted file mode 100644
index cb95cfab..00000000
--- a/forms/ecomerce/checkout/style.scss
+++ /dev/null
@@ -1,54 +0,0 @@
-
-.checkout .bar {
-	margin-bottom: 16px;
-}
-
-/* Step */
-
-.answers button,
-.answers p,
-.radio > div {
-	font-size: 1.2rem;
-}
-.answers .htk-select {
-	max-width: 15em;
-	margin: 0 auto;
-	font-size: 1.4rem;
-}
-.answers p {
-	margin: 0.3em 0;
-}
-.target {
-	max-width: 28em;
-	margin: 0 auto;
-}
-.address {
-	border-radius: 0.1em;
-	padding: 0.6em 1.4em;
-}
-.address.selected {
-	background-color: rgba(1, 1, 1, .1);
-}
-.address:hover {
-	cursor: pointer;
-	background-color: rgba(1, 1, 1, .05);
-}
-.address p.consignee {
-	font-weight: bold;
-}
-.radio {
-	max-width: 20em;
-	margin: 0 auto;
-}
-.radio > div {
-	padding: 0.5em;
-}
-.thin-calendar {
-	max-width: 24em;
-	margin: 0 auto;
-	box-shadow: none;
-}
-.htk-assistant .thin {
-	float: right;
-}
-
diff --git a/forms/ecomerce/checkout/ui.xml b/forms/ecomerce/checkout/ui.xml
deleted file mode 100644
index f9a32719..00000000
--- a/forms/ecomerce/checkout/ui.xml
+++ /dev/null
@@ -1,203 +0,0 @@
-<vn>
-<vn-group>
-	<vn-lot id="lot" on-change="this.onAddressChange()"/>
-	<db-form id="defaults" on-ready="onValuesReady">
-		<db-model property="model">
-			SELECT deliveryMethod, agencyModeFk, addressFk, defaultAgencyFk
-				FROM myBasketDefaults
-		</db-model>
-	</db-form>
-	<db-form id="order-form" on-ready="onValuesReady">
-		<db-model property="model">
-			SELECT m.code deliveryMethod, o.sent, o.agencyModeFk, o.addressFk
-				FROM myBasket o
-					JOIN vn.deliveryMethod m ON m.id = o.deliveryMethodFk
-		</db-model>
-	</db-form>
-	<db-model id="agencies"
-		auto-load="false"
-		lot="lot"
-		result-index="1"
-		on-status-changed="onAgenciesReady">
-		CALL vn.zone_getAgency(#address, #date);
-		SELECT DISTINCT a.agencyModeFk id, a.description	
-			FROM tmp.zoneGetAgency a
-				JOIN vn.deliveryMethod d
-					ON d.id = a.deliveryMethodFk
-			WHERE d.code IN ('AGENCY', 'DELIVERY')
-				AND a.isVisible
-			ORDER BY a.description;
-		DROP TEMPORARY TABLE tmp.zoneGetAgency;
-	</db-model>
-	<db-model id="warehouses"
-		auto-load="false"
-		lot="lot"
-		result-index="1"
-		on-status-changed="onWarehousesReady">
-		CALL vn.zone_getAgency(#address, #date);
-		SELECT DISTINCT a.agencyModeFk id, a.description	
-			FROM tmp.zoneGetAgency a
-				JOIN vn.deliveryMethod d
-					ON d.id = a.deliveryMethodFk
-			WHERE d.code IN ('PICKUP')
-				AND a.isVisible
-			ORDER BY a.description;
-		DROP TEMPORARY TABLE tmp.zoneGetAgency;
-	</db-model>
-</vn-group>
-<div id="title">
-	<h1><t>ConfigureOrder</t></h1>
-</div>
-<div id="actions">
-	<htk-bar-button
-		icon="close"
-		tip="_Cancel"
-		on-click="onCancelClick"/>
-</div>
-<div id="form" class="checkout">
-	<div class="vn-w-sm">
-		<div class="box bar">
-			<htk-assistant-bar
-				id="assistant-bar"
-				assistant="assistant"/>
-		</div>
-		<div class="box vn-px-md vn-py-xl">
-			<div class="form">
-			<htk-assistant id="assistant"
-				endFunc="onConfirmClick">
-				<htk-step
-					name="method"
-					validate-func="methodValidate">
-					<h2><t>DeliveryOrPickupQuestion</t></h2>
-					<div class="answers radio">
-						<htk-radio-group
-							id="rg-method"
-							form="lot"
-							column="method"
-							on-changed="onMethodChange"/>
-						<div>
-							<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>
-				</htk-step>
-				<htk-step
-					name="date"
-					show-func="dateShow"
-					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>
-				</htk-step>
-				<htk-step
-					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">
-							<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
-							</db-model>
-							<custom>
-								<div
-									class="address"
-									on-click="this.onAddressClick(iter.id)"
-									id="address">
-									<p class="consignee">{{iter.nickname}}</p>
-									<p>{{iter.street}}</p>
-								</div>
-							</custom>
-						</htk-repeater>
-					</div>
-				</htk-step>
-				<htk-step
-					name="agency"
-					show-func="agencyShow"
-					validate-func="agencyValidate">
-					<h2><t>AgencyQuestion</t></h2>
-					<div class="answers target">
-						<htk-combo
-							id="agency-combo"
-							form="lot"
-							column="agency"
-							on-changed="onFieldChange"
-							model="agencies"/>
-					</div>
-				</htk-step>
-				<htk-step
-					name="pickup"
-					show-func="pickupShow"
-					validate-func="pickupValidate">
-					<h2><t>PickupWarehouseQuestion</t></h2>
-					<div class="answers target">
-						<htk-combo
-							id="warehouse-combo"
-							form="lot"
-							column="agency"
-							on-changed="onFieldChange"
-							model="warehouses"/>
-					</div>
-				</htk-step>
-				<htk-step
-					name="confirm-delivery">
-					<h2><t>ConfirmData</t></h2>
-					<div class="answers target">
-						<p>
-							<t>Arrival</t> 
-							<htk-text format="%D" form="lot" column="date"/>
-						</p>
-						<p>
-							<htk-text form="address-form" column="street"/>
-						</p>
-						<p>
-							<t>Agency</t> 
-							<htk-text form="agency-combo" column="description"/>
-						</p>
-						<div class="clear"/>
-					</div>
-				</htk-step>
-				<htk-step
-					name="confirm-pickup">
-					<h2><t>ConfirmData</t></h2>
-					<div class="answers target">
-						<p>
-							<t>Pickup</t> 
-							<htk-text format="%D" form="lot" column="date"/>
-						</p>
-						<p>
-							<t>Warehouse</t> 
-							<htk-text form="warehouse-combo" column="description"/>
-						</p>
-						<div class="clear"/>
-					</div>
-				</htk-step>
-			</htk-assistant>
-			</div>
-		</div>
-	</div>
-</div>
-</vn>
diff --git a/forms/ecomerce/confirm/index.js b/forms/ecomerce/confirm/index.js
deleted file mode 100644
index db1e9f78..00000000
--- a/forms/ecomerce/confirm/index.js
+++ /dev/null
@@ -1,145 +0,0 @@
-import './style.scss';
-
-export default new Class({
-	Extends: Hedera.Form,
-	Template: require('./ui.xml'),
-
-	async open() {
-		const isOk = await Hedera.BasketChecker.check(this.conn, this.hash);
-		if (isOk) await Hedera.Form.prototype.open.call(this);
-	},
-	
-	onOrderReady(form) {
-		if (form.row < 0)
-			return;
-		
-		if (form.$.method != 'PICKUP') {
-			Vn.Node.show(this.$.address);
-			Vn.Node.setText(this.$.method, _('Agency'));
-		} else {
-			Vn.Node.hide(this.$.address);
-			Vn.Node.setText(this.$.method, _('Warehouse'));
-		}
-
-		var total = form.$.taxableBase + form.$.tax;
-		
-		if (total === null)
-			total = 0;
-
-		var credit = form.$.credit;
-		var debt = form.$.debt;
-
-		var totalDebt = debt + total;
-		var exceededCredit = totalDebt - credit;
-		var creditExceededCond = exceededCredit > 0;
-			
-		if (creditExceededCond)
-			Htk.Toast.showWarning(
-				_('You have exceeded your credit.'));
-
-		this.$.debt.value = debt;
-		this.$.totalDebt.value = totalDebt;
-		this.$.totalAmount.value = totalDebt;
-		this.$.creditExcess.value = exceededCredit;
-		this.$.excessAmount.value = exceededCredit;
-		
-		this.$.payAmount.value = 'ALL';
-		
-		if (credit > 0) {
-			this.$.creditInfo.style.display = 'table-row';
-
-			if (creditExceededCond) {
-				this.$.amountSelector.style.display = 'block';
-				this.$.exceededInfo.style.display = 'table-row';
-				this.$.payAmount.value = 'EXCEEDED';
-			}
-		}
-		
-		var methods = [];
-		let selectedMethod;
-		
-		if (totalDebt <= 0) {
-			methods = ['balance'];
-			selectedMethod = 'BALANCE';
-		} else {
-			methods = ['card', 'transfer', 'later'];
-
-			if (!creditExceededCond) {
-				methods.push('credit');
-				selectedMethod = 'CREDIT';
-			} else
-				selectedMethod = 'CARD';
-		}
-		
-		for (var i = 0; i < methods.length; i++)
-			this.$[`${methods[i]}Method`].style.display = 'block';
-		
-		this.$.payMethod.value = selectedMethod;
-	},
-	
-	onPayMethodChange(payMethod) {
-		var id = this.displayedInfo;
-
-		if (id)
-			Vn.Node.removeClass(this.$[id], 'selected');
-
-		switch (payMethod.value) {
-			case 'BALANCE':
-				id = 'balanceMethod';
-				break;
-			case 'CREDIT':
-				id = 'creditMethod';
-				break;
-			case 'CARD':
-				id = 'cardMethod';
-				break;
-			case 'TRANSFER':
-				id = 'transferMethod';
-				break;
-			default:
-				id = null;
-		}
-
-		this.displayedInfo = id;
-		
-		if (id)
-			Vn.Node.addClass(this.$[id], 'selected');
-	},
-	
-	disableButtons(disable) {
-		this.$.modify.disabled = disable;
-		this.$.confirm.disabled = disable;
-	},
-	
-	onModifyClick() {
-		window.history.back();
-	},
-	
-	async onConfirmClick() {
-		this.disableButtons(true);
-		await this.$.confirmQuery.execute();
-	},
-
-	onConfirm(query, resultSet) {
-		this.disableButtons(false);
-
-		if (resultSet.fetchResult())
-			this.$.successDialog.show();
-	},
-
-	async onDialogResponse() {
-		if (this.$.payMethod.value === 'CARD') {
-			if (this.$.payAmount.value === 'EXCEEDED')
-				var payAmount = this.$.excessAmount.value;
-			else
-				var payAmount = this.$.totalAmount.value;
-		
-			var tpv = new Hedera.Tpv({
-				conn: this.conn,
-				hash: this.hash
-			});
-			await tpv.pay(payAmount, this.$.order.companyFk);
-		} else
-			this.hash.setAll({form: 'ecomerce/orders'});
-	}
-});
diff --git a/forms/ecomerce/confirm/locale/ca.yml b/forms/ecomerce/confirm/locale/ca.yml
deleted file mode 100644
index 5f84813a..00000000
--- a/forms/ecomerce/confirm/locale/ca.yml
+++ /dev/null
@@ -1,33 +0,0 @@
-Checkout: Finalitzar comanda
-Order summary: Resum de la comanda
-ShippingInformation: Dades d'enviament
-DeliveryAddress: Adreça de lliurament
-Delivery at: Lliurament el
-Agency: Agència
-Warehouse: Magatzem
-Previous balance: Saldo anterior
-Order total: Total comanda
-Order VAT: IVA comanda
-Total debt: Total deute
-Credit: Crèdit
-Exceeded credit: Crèdit excedit
-Amount to pay: Quantitat a pagar
-Pay method: Mètode de pagament
-Use my balance: Utilitzar el meu saldo
-You have a favorable balance.: 'No necessites pagar res, tens un saldo favorable.'
-Use my credit: Utilitzar el meu crèdit
-You have a favorable credit.: 'No necessites pagar res, tens crèdit favorable.'
-Credit card: Targeta de crèdit
-You will be redirected to the payment.: En confirmar la comanda seràs redirigit a la plataforma de pagament.
-Bank Transfer: Transferència bancària
-Make a transfer to one account.: >-
-  Fer una transferecia a una de les següents comptes i envia el justificant al
-  teu comercial.
-Pay later: Pagar més tard
-Modify: Modificar
-Confirm: Confirmar
-Order confirmed successfully: La teva comanda ha estat realitzat amb èxit
-Accept: D'acord
-You have exceeded your credit.: >-
-  Has excedit el teu crèdit, si us plau realitza el pagament perquè puguem
-  preparar la teva comanda.
diff --git a/forms/ecomerce/confirm/locale/en.yml b/forms/ecomerce/confirm/locale/en.yml
deleted file mode 100644
index c480fa72..00000000
--- a/forms/ecomerce/confirm/locale/en.yml
+++ /dev/null
@@ -1,33 +0,0 @@
-Checkout: Checkout
-Order summary: Order summary
-ShippingInformation: Shipping information
-DeliveryAddress: Delivery address
-Delivery at: Delivery at
-Agency: Agency
-Warehouse: Store
-Previous balance: Previous balance
-Order total: Order total
-Order VAT: Order VAT
-Total debt: Total debt
-Credit: Credit
-Exceeded credit: Exceeded credit
-Amount to pay: Amount to pay
-Pay method: Pay method
-Use my balance: Use my balance
-You have a favorable balance.: 'You do not need to perform any payment, you have a favorable balance.'
-Use my credit: Use my credit
-You have a favorable credit.: 'You do not need to pay now, you have a favorable credit.'
-Credit card: Credit card
-You will be redirected to the payment.: By confirming the order you will be redirected to the payment platform.
-Bank Transfer: Bank Transfer
-Make a transfer to one account.: >-
-  Make a transfer to one of the following accounts and send the receipt to your
-  salesperson.
-Pay later: Pay later
-Modify: Modify
-Confirm: Confirm
-Order confirmed successfully: Your order has been confirmed successfully
-Accept: Accept
-You have exceeded your credit.: >-
-  You have exceeded your credit, in order to prepare your order please pay your
-  debt.
diff --git a/forms/ecomerce/confirm/locale/es.yml b/forms/ecomerce/confirm/locale/es.yml
deleted file mode 100644
index 08c65dac..00000000
--- a/forms/ecomerce/confirm/locale/es.yml
+++ /dev/null
@@ -1,33 +0,0 @@
-Checkout: Finalizar pedido
-Order summary: Resumen del pedido
-ShippingInformation: Datos de envío
-DeliveryAddress: Dirección de entrega
-Delivery at: Entrega el
-Agency: Agencia
-Warehouse: Almacén
-Previous balance: Saldo anterior
-Order total: Total pedido
-Order VAT: IVA pedido
-Total debt: Total deuda
-Credit: Crédito
-Exceeded credit: Crédito excedido
-Amount to pay: Cantidad a pagar
-Pay method: Método de pago
-Use my balance: Usar mi saldo
-You have a favorable balance.: 'No necesitas pagar nada, tienes un saldo favorable.'
-Use my credit: Usar mi crédito
-You have a favorable credit.: 'No necesitas pagar nada, tienes crédito favorable.'
-Credit card: Tarjeta de crédito
-You will be redirected to the payment.: Al confirmar el pedido serás redirigido a la plataforma de pago.
-Bank Transfer: Transferencia bancaria
-Make a transfer to one account.: >-
-  Haz una transferecia a una de las siguientes cuentas y envía el justificante a
-  tu comercial.
-Pay later: Pagar más tarde
-Modify: Modificar
-Confirm: Confirmar
-Order confirmed successfully: Tu pedido ha sido realizado con éxito
-Accept: Aceptar
-You have exceeded your credit.: >-
-  Has excedido tu crédito, por favor realiza el pago para que podamos preparar
-  tu pedido.
diff --git a/forms/ecomerce/confirm/locale/fr.yml b/forms/ecomerce/confirm/locale/fr.yml
deleted file mode 100644
index 2bcdda8c..00000000
--- a/forms/ecomerce/confirm/locale/fr.yml
+++ /dev/null
@@ -1,33 +0,0 @@
-Checkout: Finir la commande
-Order summary: Résumé de la commande
-ShippingInformation: Informations sur la livraison
-DeliveryAddress: Addresse de livraison
-Delivery at: Livraison à
-Agency: Agence
-Warehouse: Entrepôt
-Previous balance: Solde précédent
-Order total: Total de la commande
-Order VAT: TVA de la commande
-Total debt: Total de la dette
-Credit: Crédit
-Exceeded credit: Crédit dépassée
-Amount to pay: Montant à payer
-Pay method: Mode de paiement
-Use my balance: Utiliser mon équilibre
-You have a favorable balance.: 'Pas besoin de payer quoi que ce soit, vous avez un solde favorable.'
-Use my credit: Utiliser mon crédit
-You have a favorable credit.: 'Pas besoin de payer quoi que ce soit, vous favorable crédit.'
-Credit card: Carte de crédit
-You will be redirected to the payment.: 'En confirmant la commande, vous serez redirigé vers la plateforme de paiement.'
-Bank Transfer: Virement bancaire
-Make a transfer to one account.: >-
-  Faire Transféré à l'un des comptes suivants et envoyer le coupon à votre
-  entreprise.
-Pay later: Payer plus tard
-Modify: Modifier
-Confirm: Confirmer
-Order confirmed successfully: Votre commande a été complété avec succès
-Accept: OK
-You have exceeded your credit.: >-
-  Vous avez dépassé votre crédit, s'il vous plaît effectuer le paiement afin que
-  nous puissions préparer votre commande.
diff --git a/forms/ecomerce/confirm/locale/pt.yml b/forms/ecomerce/confirm/locale/pt.yml
deleted file mode 100644
index 6f44570a..00000000
--- a/forms/ecomerce/confirm/locale/pt.yml
+++ /dev/null
@@ -1,33 +0,0 @@
-Checkout: Finalizar encomenda
-Order summary: Resumo da encomenda
-ShippingInformation: Dados de envio
-DeliveryAddress: Endereço de entrega
-Delivery at: Entrega na
-Agency: Agência
-Warehouse: Armazém
-Previous balance: Saldo anterior
-Order total: Total pedido
-Order VAT: IVA
-Total debt: Total dívida
-Credit: Crédito
-Exceeded credit: Crédito excedido
-Amount to pay: Valor a pagar
-Pay method: Método de pagamento
-Use my balance: Usar meu saldo
-You have a favorable balance.: 'Não há necessidade de pagar, tens um crédito a seu favor.'
-Use my credit: Usar meu crédito
-You have a favorable credit.: 'Não há necessidade de pagar, tens um crédito à favor.'
-Credit card: Cartão de crédito/debito
-You will be redirected to the payment.: 'Ao confirmar a encomenda, serás re-direcionado à plataforma de pagamento.'
-Bank Transfer: Transferência bancária
-Make a transfer to one account.: >-
-  Faça a transferencia para uma das seguintes contas e envie o comprovativo para
-  seu comercial.
-Pay later: Pagar mais tarde
-Modify: Modificar
-Confirm: Confirmar
-Order confirmed successfully: Seu pedido foi realizado com êxito
-Accept: Aceitar
-You have exceeded your credit.: >-
-  Ultrapassastes seu crédito, por favor, faça o pagamento para que possamos
-  preparar sua encomenda.
diff --git a/forms/ecomerce/confirm/style.scss b/forms/ecomerce/confirm/style.scss
deleted file mode 100644
index f5da4a6b..00000000
--- a/forms/ecomerce/confirm/style.scss
+++ /dev/null
@@ -1,93 +0,0 @@
-
-.confirm .summary {
-	margin-bottom: 16px;
-}
-.confirm p {
-	margin: .2em 0;
-}
-
-/* Table */
-
-.confirm .debt-info {
-	padding: 0;
-}
-.confirm .debt-info > table {
-	border-collapse: collapse;
-}
-.confirm td {
-	padding: .15em 0;
-}
-.confirm .sum-total > td {
-	border-top: solid 1px #DDD;
-	font-weight: bold;
-}
-.confirm .currency {
-	text-align: right;
-}
-.confirm .credit-info {
-	display: none;
-}
-.confirm .exceeded-info {
-	display: none;
-	color: #E53935;
-}
-
-/* Pay */
-
-.confirm .amount-selector,
-.confirm .pay-methods > div {
-	display: none;
-}
-.confirm .pay-methods > div {
-	margin: .3em 0;
-}
-.confirm .pay-methods > div > label > input[type=radio] {
-	margin: 0;
-	margin-right: .5em;
-	vertical-align: middle;
-}
-.confirm .pay-methods > div > div {
-	padding: .5em 1.5em;
-	display: none;
-}
-.confirm .pay-methods > div.selected > div {
-	display: block;
-}
-.confirm .transfer-account {
-	margin-top: .5em;
-}
-.confirm .transfer-account > p {
-	margin: .1em 0;
-}
-
-.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;
-}
\ No newline at end of file
diff --git a/forms/ecomerce/confirm/ui.xml b/forms/ecomerce/confirm/ui.xml
deleted file mode 100644
index c9deba20..00000000
--- a/forms/ecomerce/confirm/ui.xml
+++ /dev/null
@@ -1,214 +0,0 @@
-<vn>
-<vn-group>
-	<db-form v-model="order" on-ready="onOrderReady">
-		<db-model property="model" result-index="1">
-			CALL myBasket_getTax;
-			SELECT o.id, o.sent, o.notes, o.companyFk, 
-					ag.description agency, v.code method, 
-					ad.nickname, ad.postalCode, ad.city, ad.street, 
-					t.*, c.credit, myClient_getDebt(NULL) debt
-				FROM myBasket o
-					JOIN vn.agencyMode ag ON ag.id = o.agencyModeFk 
-					LEFT JOIN myAddress ad ON ad.id = o.addressFk 
-					JOIN vn.deliveryMethod v ON v.id = o.deliveryMethodFk
-					JOIN myClient c
-					JOIN (
-						SELECT
-							IFNULL(SUM(taxableBase), 0) taxableBase,
-							IFNULL(SUM(tax), 0) tax
-							FROM tmp.orderAmount
-					) t;
-			DROP TEMPORARY TABLE
-				tmp.orderAmount,
-				tmp.orderTax;
-		</db-model>
-	</db-form>
-	<db-query id="confirm-query" on-ready="onConfirm">
-		CALL myBasket_confirm
-	</db-query>
-</vn-group>
-<div id="title">
-	<h1><t>Order summary</t></h1>
-</div>
-<div id="form" class="confirm">
-	<div class="vn-w-sm">
-		<div class="box vn-pa-lg summary">
-			<div>
-				<div class="delivery">
-					<h6><t>ShippingInformation</t></h6>
-					<p>
-						<t>Delivery at</t>  {{Vn.Value.format(order.sent, _('%D'))}}
-					</p>
-					<p>
-						<span id="method"><t>Agency</t></span> {{order.agency}}
-					</p>
-				</div>
-				<div id="address" class="address vn-mt-md">
-					<h6><t>DeliveryAddress</t></h6>
-					<p>{{order.nickname}}</p>
-					<p>{{order.street}}</p>
-					<p>{{order.postalCode}}, {{order.city}}</p>
-				</div>
-			</div>
-		</div>
-		<div class="box vn-pa-lg 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">
-								{{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>
-						<htk-radio radio-group="pay-amount" value="ALL"/>
-						<label>
-							<t>Total debt</t>, 
-							<htk-text format="%.2d€" id="total-amount"/>
-						</label>
-					</div>
-					<div>
-						<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>
-				<h6><t>Pay method</t></h6>
-				<div class="pay-methods">
-					<htk-radio-group
-						id="pay-method"
-						on-changed="onPayMethodChange"/>
-					<div id="balance-method">
-						<label>
-							<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>
-<htk-dialog
-	id="success-dialog"
-	icon="ok"
-	message="_Order confirmed successfully"
-	buttons="ACCEPT"
-	on-response="onDialogResponse"/>
-</vn>
diff --git a/forms/ecomerce/invoices/index.js b/forms/ecomerce/invoices/index.js
deleted file mode 100644
index 5c0960b9..00000000
--- a/forms/ecomerce/invoices/index.js
+++ /dev/null
@@ -1,32 +0,0 @@
-import './style.scss';
-
-export default new Class({
-	Extends: Hedera.Form,
-	Template: require('./ui.xml'),
-	
-	donwloadRenderer(column, invoice) {
-		var invoiceId = invoice.$.id;
-
-		if (invoice.$.hasPdf && invoiceId) {
-			var params = {
-				srv: 'rest:dms/invoice',
-				invoice: invoiceId,
-				access_token: this.conn.token
-			};
-
-			Object.assign(column, {
-				tip: _('Download PDF'),
-				disabled: false,
-				icon: 'download',
-				href: '?'+ Vn.Url.makeUri(params)
-			});
-		} else
-			Object.assign(column, {
-				tip: _('Request the invoice to your salesperson'),
-				disabled: true,
-				icon: 'warning',
-				href: null
-			});
-	}
-});
-
diff --git a/forms/ecomerce/invoices/locale/ca.yml b/forms/ecomerce/invoices/locale/ca.yml
deleted file mode 100644
index 7e7fa462..00000000
--- a/forms/ecomerce/invoices/locale/ca.yml
+++ /dev/null
@@ -1,6 +0,0 @@
-Invoices: Factures
-Serial: Sèrie
-Date: Data
-Import: Import
-Donwload PDF: Descarregar PDF
-Request the invoice to your salesperson: Sol·licita la factura al teu comercial
diff --git a/forms/ecomerce/invoices/locale/en.yml b/forms/ecomerce/invoices/locale/en.yml
deleted file mode 100644
index 7b673d0e..00000000
--- a/forms/ecomerce/invoices/locale/en.yml
+++ /dev/null
@@ -1,6 +0,0 @@
-Invoices: Invoices
-Serial: Serial
-Date: Date
-Import: Import
-Download PDF: Download PDF
-Request the invoice to your salesperson: Request the invoice to your salesperson
diff --git a/forms/ecomerce/invoices/locale/es.yml b/forms/ecomerce/invoices/locale/es.yml
deleted file mode 100644
index 39a956ca..00000000
--- a/forms/ecomerce/invoices/locale/es.yml
+++ /dev/null
@@ -1,6 +0,0 @@
-Invoices: Facturas
-Serial: Serie
-Date: Fecha
-Import: Importe
-Download PDF: Descargar PDF
-Request the invoice to your salesperson: Solicita la factura a tu comercial
diff --git a/forms/ecomerce/invoices/locale/fr.yml b/forms/ecomerce/invoices/locale/fr.yml
deleted file mode 100644
index 2197fa75..00000000
--- a/forms/ecomerce/invoices/locale/fr.yml
+++ /dev/null
@@ -1,6 +0,0 @@
-Invoices: Factures
-Serial: Série
-Date: Date
-Import: Montant
-Donwload PDF: Télécharger le PDF
-Request the invoice to your salesperson: Demander la facture à votre commercial
diff --git a/forms/ecomerce/invoices/locale/pt.yml b/forms/ecomerce/invoices/locale/pt.yml
deleted file mode 100644
index adf3270b..00000000
--- a/forms/ecomerce/invoices/locale/pt.yml
+++ /dev/null
@@ -1,6 +0,0 @@
-Invoices: Factura
-Serial: Serie
-Date: Data
-Import: Importe
-Download PDF: Baixar PDF
-Request the invoice to your salesperson: Solicite a fatura ao seu comercial
diff --git a/forms/ecomerce/invoices/style.scss b/forms/ecomerce/invoices/style.scss
deleted file mode 100644
index e69de29b..00000000
diff --git a/forms/ecomerce/invoices/ui.xml b/forms/ecomerce/invoices/ui.xml
deleted file mode 100644
index e69a3ce7..00000000
--- a/forms/ecomerce/invoices/ui.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<vn>
-<div id="title">
-	<h1><t>Invoices</t></h1>
-</div>
-<div id="form" class="invoices">
-	<htk-grid
-		class="box vn-w-sm"
-		show-header="false">
-		<db-model property="model" id="tickets">
-			SELECT id, ref, issued, amount, hasPdf
-				FROM myInvoice
-				ORDER BY issued DESC
-				LIMIT 100
-		</db-model>
-		<htk-column-text title="_Serial" column="ref"/>
-		<htk-column-date title="_Date" column="issued" format="_%e %b %Y"/>
-		<htk-column-spin title="_Import" column="amount" unit="€" digits="2"/>
-		<htk-column-button
-			renderer="donwloadRenderer"
-			target="_blank"/>
-	</htk-grid>
-</div>
-</vn>
diff --git a/forms/ecomerce/orders/index.js b/forms/ecomerce/orders/index.js
deleted file mode 100644
index bcaa6057..00000000
--- a/forms/ecomerce/orders/index.js
+++ /dev/null
@@ -1,57 +0,0 @@
-import './style.scss';
-
-export default new Class({
-	Extends: Hedera.Form,
-	Template: require('./ui.xml'),
-
-	activate() {
-		this.tpv = new Hedera.Tpv({
-			conn: this.conn,
-			hash: this.hash
-		});
-		const tpvStatus = this.tpv.check();
-		if (tpvStatus === 'ko') this.$.errorDialog.show();
-	},
-
-	onBasketClick() {
-		this.hash.setAll({form: 'ecomerce/basket'});
-	},
-	
-	repeaterFunc(res, form) {
-		res.$.link.href = this.hash.make({
-			form: 'ecomerce/ticket',
-			ticket: form.$.id
-		});
-	},
-
-	// TPV
-	
-	balanceConditionalFunc(_, value) {
-		if (value >= 0)
-			Vn.Node.removeClass(this.$.balance, 'negative');
-		else
-			Vn.Node.addClass(this.$.balance, 'negative');
-	},
-	
-	async onPayButtonClick() {
-		var amount = -this.$.debt.value;
-		amount = amount <= 0 ? null : amount;
-
-		var defaultAmountStr = '';
-		
-		if (amount !== null)
-			defaultAmountStr = Vn.Value.format(amount, '%.2d');
-			
-		amount = prompt(_('AmountToPay:'), defaultAmountStr);
-
-		if (amount != null) {
-			amount = parseFloat(amount.replace(',', '.'));
-			await this.tpv.pay(amount, null);
-		}
-	},
-	
-	async onDialogResponse(_, response) {
-		if (response == Htk.Dialog.Button.RETRY)
-			await this.tpv.retryPay();
-	}
-});
diff --git a/forms/ecomerce/orders/locale/ca.yml b/forms/ecomerce/orders/locale/ca.yml
deleted file mode 100644
index c93f4817..00000000
--- a/forms/ecomerce/orders/locale/ca.yml
+++ /dev/null
@@ -1,36 +0,0 @@
-OpenOrders: Comandes obertes
-StartOrder: Començar encàrrec
-ContinueOrder: Continuar encàrrec
-OrderNumber: N encàrrec
-DateMake: Data de creació
-DateExit: Data d'eixida
-SendMethod: Forma d'enviament
-LastOrders: Últimes comandes
-'Balance:': 'Saldo:'
-PaymentInfo: >-
-  La quantitat mostrada és el teu saldo pendent (negatiu) o favorable a dia
-  d'avui, no té en compte comandes del futur. Perquè la teva comanda sigui
-  enviat, aquesta quantitat ha de ser igual o més gran que 0. Si vols fer un
-  lliurament a compte, prem el botó de pagament, esborra la quantitat suggerida
-  e introdueix la quantitat que vulguis.
-MakePayment: Realitzar pagament
-Company: Empresa
-Pending: Pendent
-Pay: Pagar
-Basket: Cistella
-ShoppingBasket: Cistella de la compra
-SeeOrder: Mostrar detall de l'encàrrec
-Delivery: Lliurament
-TicketNumber: N ticket
-SentAddress: Adreça d'enviament
-Consignee: Consignatari
-Boxes: Caixes
-TotalWithVAT: Total amb IVA
-PayOrder: Pagar encàrrec
-'AmountToPay:': 'Quantitat a pagar (€):'
-AmountError: >-
-  La quantitat ha de ser un nombre positiu i inferior o igual a l'import pendent
-PayError: Error al realitzar el pagament
-An error has been in the payment: Sembla que hi ha hagut un error en el pagament
-Retry: Reintenta
-Accept: Acceptar
diff --git a/forms/ecomerce/orders/locale/en.yml b/forms/ecomerce/orders/locale/en.yml
deleted file mode 100644
index 4bb08ce7..00000000
--- a/forms/ecomerce/orders/locale/en.yml
+++ /dev/null
@@ -1,37 +0,0 @@
-OpenOrders: Open orders
-StartOrder: Start order
-ContinueOrder: Continue order
-OrderNumber: Order number
-DateMake: Creation date
-DateExit: Shipping date
-SendMethod: Delivery method
-LastOrders: Last orders
-'Balance:': 'Balance:'
-PaymentInfo: >-
-  The amount shown is your slope (negative) or favorable balance today, it
-  disregards future orders. For get your order shipped, this amount must be
-  equal to or greater than 0. If you want to make a down payment, click the
-  payment button, delete the suggested amount and enter the amount you want.
-MakePayment: Make payment
-Company: Company
-Pending: Pending
-Pay: Pay
-Basket: Basket
-ShoppingBasket: Shopping basket
-SeeOrder: Show details of the order
-Delivery: Delivery
-TicketNumber: Ticket number
-SentAddress: Delivery address
-Consignee: Consignee
-Boxes: Bundles
-TotalWithVAT: Total with VAT
-PayOrder: Pay order
-'AmountToPay:': 'Amount to pay (€):'
-AmountError: >-
-  The amount must be a positive number less than or equal to the outstanding
-  amount
-PayError: Failed to make the payment
-An error has been in the payment: >-
-  It seems that there has been an error in the payment
-Retry: Retry
-Accept: Accept
diff --git a/forms/ecomerce/orders/locale/es.yml b/forms/ecomerce/orders/locale/es.yml
deleted file mode 100644
index b649cddf..00000000
--- a/forms/ecomerce/orders/locale/es.yml
+++ /dev/null
@@ -1,37 +0,0 @@
-OpenOrders: Pedidos abiertos
-StartOrder: Empezar pedido
-ContinueOrder: Continuar pedido
-OrderNumber: Nº pedido
-DateMake: Fecha de creación
-DateExit: Fecha de salida
-SendMethod: Forma de envío
-LastOrders: Últimos pedidos
-'Balance:': 'Saldo:'
-PaymentInfo: >-
-  La cantidad mostrada es tu saldo pendiente (negativa) o favorable a día de
-  hoy, no tiene en cuenta pedidos del futuro. Para que tu pedido sea enviado,
-  esta cantidad debe ser igual o mayor que 0. Si quieres realizar una entrega a
-  cuenta, pulsa el botón de pago, borra la cantidad sugerida e introduce la
-  cantidad que desees.
-MakePayment: Realizar pago
-Company: Empresa
-Pending: Pendiente
-Pay: Pagar
-Basket: Cesta
-ShoppingBasket: Cesta de la compra
-SeeOrder: Mostrar detalle del pedido
-Delivery: Entrega
-TicketNumber: Nº ticket
-SentAddress: Dirección de envío
-Consignee: Consignatario
-Boxes: Bultos
-TotalWithVAT: Total con IVA
-PayOrder: Pagar pedido
-'AmountToPay:': 'Cantidad a pagar (€):'
-AmountError: >-
-  La cantidad debe ser un número positivo e inferior o igual al importe
-  pendiente
-PayError: Error al realizar el pago
-An error has been in the payment: Parece que ha habido un error en el pago
-Retry: Reintentar
-Accept: Aceptar
diff --git a/forms/ecomerce/orders/locale/fr.yml b/forms/ecomerce/orders/locale/fr.yml
deleted file mode 100644
index e10b5d7c..00000000
--- a/forms/ecomerce/orders/locale/fr.yml
+++ /dev/null
@@ -1,38 +0,0 @@
-OpenOrders: Les commandes ouvertes
-StartOrder: Acheter
-ContinueOrder: Continuer la commande
-OrderNumber: Numéro de commande
-DateMake: Date de creation
-DateExit: Date de sortie
-SendMethod: Typo
-LastOrders: Les dernières commandes
-'Balance:': 'Balance:'
-PaymentInfo: >-
-  Le montant indiqué est votre pente (négative) ou balance favorable
-  aujourd'hui, ne tient pas compte pour les commandes futures. Obtenir votre
-  commande est expédiée, ce montant doit être égal ou supérieur à 0. Si vous
-  voulez faire un versement, le montant suggéré effacé et entrez le montant que
-  vous souhaitez.
-MakePayment: Effectuer un paiement
-Company: Entreprise
-Pending: Pente
-Pay: Payer
-Basket: Panier
-ShoppingBasket: Panier
-SeeOrder: Votre panier
-Delivery: Livraison
-TicketNumber: Numéro ticket
-SentAddress: Adresse de livraison
-Consignee: Destinataire
-Boxes: Colis
-TotalWithVAT: Total avec TVA
-PayOrder: Payer la commande
-'AmountToPay:': 'Montant à payer (€):'
-AmountError: >-
-  La quantité doit être un neméro positif et inférieur ou égal  à la somme
-  restant à payer
-PayError: Impossible d'effectuer le paiement
-An error has been in the payment: >-
-  Il semble qu'il ya eu une erreur dans le paiement
-Retry: Réessayez
-Accept: Accepter
diff --git a/forms/ecomerce/orders/locale/mn.yml b/forms/ecomerce/orders/locale/mn.yml
deleted file mode 100644
index 207a0dac..00000000
--- a/forms/ecomerce/orders/locale/mn.yml
+++ /dev/null
@@ -1,37 +0,0 @@
-OpenOrders: Open orders
-StartOrder: Start order
-ContinueOrder: Continue order
-OrderNumber: Order number
-DateMake: Creation date
-DateExit: Shipping date
-SendMethod: Delivery method
-LastOrders: Last orders
-'Balance:': 'Balance:'
-PaymentInfo: >-
-  Үзүүлсэн хэмжээ цаашид захиалга эзэлж биш, таны налуу (сөрөг), эсвэл
-  тааламжтай тэнцвэр нь өнөөдөр юм. Хэрэв та дүн арилгаж гэж хэлж байсан нь доош
-  нь төлбөр хийж, өөрийн хүссэн хэмжээгээр орж хүсэж байгаа бол таны захиалга
-  ирдэг бол авах, энэ хэмжээ тэнцүү буюу 0-ээс их байх ёстой.
-MakePayment: Make payment
-Company: Company
-Pending: Pending
-Pay: Pay
-Basket: Basket
-ShoppingBasket: Shopping basket
-SeeOrder: Show details of the order
-Delivery: Delivery
-TicketNumber: Ticket number
-SentAddress: Delivery address
-Consignee: Consignee
-Boxes: Bundles
-TotalWithVAT: Total with VAT
-PayOrder: Pay order
-'AmountToPay:': 'Amount to pay (€):'
-AmountError: >-
-  The amount must be a positive number less than or equal to the outstanding
-  amount
-PayError: Failed to make the payment
-An error has been in the payment: >-
-  It seems that there has been an error in the payment
-Retry: Retry
-Accept: Accept
diff --git a/forms/ecomerce/orders/locale/pt.yml b/forms/ecomerce/orders/locale/pt.yml
deleted file mode 100644
index ff127648..00000000
--- a/forms/ecomerce/orders/locale/pt.yml
+++ /dev/null
@@ -1,37 +0,0 @@
-OpenOrders: Abrir encomendas
-StartOrder: Iniciar encomenda
-ContinueOrder: Continuar encomenda
-OrderNumber: Nº pedido
-DateMake: Data de criação
-DateExit: Data de saída
-SendMethod: Forma de envío
-LastOrders: Últimas encomendas
-'Balance:': 'Saldo:'
-PaymentInfo: >-
-  A quantidade mostrada é seu saldo pendente (negativo) ou favorável a dia de
-  hoje, não se vincula a pedidos futuros. Para que seu pedido seja enviado, esta
-  quantidade deve ser igual ou superior a 0. Se queres realizar um depósito à
-  conta, clique no botão de pagamento, apague a quantidade sugerida e introduza
-  a quantidade que deseje.
-MakePayment: Realizar pagamento
-Company: Empresa
-Pending: Pendente
-Pay: Pagar
-Basket: Cesta
-ShoppingBasket: Cesta da compra
-SeeOrder: Ver encomenda
-Delivery: Entrega
-TicketNumber: Nº encomenda
-SentAddress: Endereço de envío
-Consignee: Consignatario
-Boxes: Bultos
-TotalWithVAT: Total com IVA
-PayOrder: Pagar encomenda
-'AmountToPay:': 'Quantidade a pagar (€):'
-AmountError: >-
-  A quantidade deve ser um número positivo e inferior ou igual ao importe
-  pendiente
-PayError: Erro ao realizar o pagamento
-An error has been in the payment: Parece que houve um erro no pagamento
-Retry: Tentar novamente
-Accept: Aceitar
diff --git a/forms/ecomerce/orders/style.scss b/forms/ecomerce/orders/style.scss
deleted file mode 100644
index 80318bed..00000000
--- a/forms/ecomerce/orders/style.scss
+++ /dev/null
@@ -1,39 +0,0 @@
-
-.balance {
-	margin-right: 8px;
-	white-space: nowrap;
-
-	& > * {
-		vertical-align: middle;
-	}
-	& > .amount {
-		color: white;
-		padding: 4px;
-	}
-	& > .info {
-		display: inline;
-		cursor: pointer;
-		height: 17px;
-		cursor: pointer;
-	}
-	& > .negative {
-		background-color: #EF5350;
-		border-radius: 2px;
-		box-shadow: 0 0 .4em #666;
-	}
-}
-
-.balance-popup {
-	width: 25em;
-}
-.balance-grid {
-	width: 100%;
-	margin: auto;
-}
-
-/* List */
-
-.orders .htk-list .total {
-	float: right;
-}
-
diff --git a/forms/ecomerce/orders/ui.xml b/forms/ecomerce/orders/ui.xml
deleted file mode 100644
index 9d83e3c5..00000000
--- a/forms/ecomerce/orders/ui.xml
+++ /dev/null
@@ -1,68 +0,0 @@
-<vn>
-<div id="title">
-	<h1><t>LastOrders</t></h1>
-</div>
-<div id="actions">
-	<div class="balance">
-		<span class="label">
-			<t>Balance:</t>
-		</span> 
-		<span class="amount" id="balance">
-			<htk-text id="debt"
-				format="%.2d€"
-				conditional-func="balanceConditionalFunc"
-				column="debt">
-				<db-form property="form">
-					<db-model property="model">
-						SELECT -myClient_getDebt(NULL) debt
-					</db-model>
-				</db-form>
-			</htk-text>
-		</span> 
-		<htk-icon
-			name="info"
-			title="_PaymentInfo"
-			class="info"/>
-	</div>
-	<htk-bar-button
-		id="pay-button"
-		icon="payments"
-		tip="_MakePayment"
-		on-click="onPayButtonClick"/>
-	<htk-bar-button
-		icon="shopping_cart"
-		tip="_ShoppingBasket"
-		on-click="onBasketClick"/>
-</div>
-<div id="form" class="orders">
-	<htk-repeater
-		class="htk-list box confirmed vn-w-sm"
-		form-id="iter"
-		renderer="repeaterFunc">
-		<db-model property="model" id="tickets">
-			CALL myTicket_list(NULL, NULL);
-		</db-model>
-		<custom>
-			<a id="link" class="item" title="{{_('SeeOrder')}}">
-				<div class="content">
-					<p class="important total">
-						{{Vn.Value.format(iter.total, '%.2d€')}}
-					</p>
-					<p class="important">
-						{{Vn.Value.format(iter.landed, '%D')}}
-					</p>
-					<p>#{{iter.id}}</p>
-					<p>{{iter.nickname}}</p>
-					<p>{{iter.agency}}</p>
-				</div>
-			</a>
-		</custom>
-	</htk-repeater>
-</div>
-<htk-dialog
-	id="error-dialog"
-	icon="error"
-	message="_An error has been in the payment"
-	buttons="RETRY_CANCEL"
-	on-response="onDialogResponse"/>
-</vn>
diff --git a/forms/ecomerce/ticket/index.js b/forms/ecomerce/ticket/index.js
deleted file mode 100644
index f171c199..00000000
--- a/forms/ecomerce/ticket/index.js
+++ /dev/null
@@ -1,45 +0,0 @@
-import './style.scss';
-
-export default new Class({
-	Extends: Hedera.Form,
-	Template: require('./ui.xml'),
-
-	async onTicketChange(ticket) {
-		if (!ticket.value) return;
-		await this.conn.execQuery('CALL myTicket_logAccess(#ticket)',
-			{ticket: ticket.value});
-	},
-
-	onPrintClick() {
-		let params = Vn.Url.makeUri({
-			access_token: this.conn.token,
-			recipientId: this.gui.user.id,
-			type: 'deliveryNote'
-		});
-		window.open(`/api/Tickets/${this.hash.$.ticket}/delivery-note-pdf?${params}`);
-	},
-
-	repeaterFunc(scope, form) {
-		scope.$.discount.style.display = form.$.discount ? 'inline' : 'none';
-	},
-
-	discountSubtotal(line) {
-		return line.quantity * line.price;
-	},
-
-	subtotal(line) {
-		var discount = line.discount;
-		return this.discountSubtotal(line) * ((100 - discount) / 100);
-	},
-
-	onServicesChanged(model) {
-		this.$.services.node.style.display =
-			model.numRows > 0 ? 'block' : 'none';
-	},
-
-	onPackagesChanged(model) {
-		this.$.packages.node.style.display =
-			model.numRows > 0 ? 'block' : 'none';
-	},
-});
-
diff --git a/forms/ecomerce/ticket/locale/ca.yml b/forms/ecomerce/ticket/locale/ca.yml
deleted file mode 100644
index 680bc6d6..00000000
--- a/forms/ecomerce/ticket/locale/ca.yml
+++ /dev/null
@@ -1,25 +0,0 @@
-OrderDetail: Detall de l'encarrec
-ShippingInformation: Dades d'enviament
-DeliveryAddress: Adreça de lliurament
-Print delivery note: Imprimir albarà
-Agency: Agència
-Warehouse: Magatzem
-Total: Total
-Total + tax: Total + IVA
-Tax base: Base imposable
-VAT: IVA
-ItemNumber: N article
-Amount: Quant
-Item: Article
-Category: Categoria
-S1: Mes
-Stems: Tijes
-Color: Color
-Origin: Orige
-Price: Preu
-Disc: Desc
-Subtotal: Subtotal
-Preparation: Preparació
-Delivery: Entrega
-Service: Servei
-Packaging: Embalatge
diff --git a/forms/ecomerce/ticket/locale/en.yml b/forms/ecomerce/ticket/locale/en.yml
deleted file mode 100644
index ae229f20..00000000
--- a/forms/ecomerce/ticket/locale/en.yml
+++ /dev/null
@@ -1,25 +0,0 @@
-OrderDetail: Order detail
-ShippingInformation: Shipping information
-DeliveryAddress: Delivery address
-Print delivery note: Print delivery note
-Agency: Agency
-Warehouse: Store
-Total: Total
-Total + tax: Total + tax
-Tax base: Tax base
-VAT: VAT
-ItemNumber: Item number
-Amount: Amount
-Item: Item
-Category: Category
-S1: Siz
-Stems: Stems
-Color: Color
-Origin: Origin
-Price: Price
-Disc: Disc
-Subtotal: Subtotal
-Preparation: Preparation
-Delivery: Delivery
-Service: Service
-Packaging: Packaging
diff --git a/forms/ecomerce/ticket/locale/es.yml b/forms/ecomerce/ticket/locale/es.yml
deleted file mode 100644
index f798dc7e..00000000
--- a/forms/ecomerce/ticket/locale/es.yml
+++ /dev/null
@@ -1,25 +0,0 @@
-OrderDetail: Detalle del pedido
-ShippingInformation: Datos de envío
-DeliveryAddress: Dirección de entrega
-Print delivery note: Imprimir albarán
-Agency: Agencia
-Warehouse: Almacén
-Total: Total
-Total + tax: Total + IVA
-Tax base: Base imponible
-VAT: IVA
-ItemNumber: Nº artículo
-Amount: Cant
-Item: Artículo
-Category: Categoría
-S1: Med
-Stems: Tallos
-Color: Color
-Origin: Origen
-Price: Precio
-Disc: Desc
-Subtotal: Subtotal
-Preparation: Preparación
-Delivery: Entrega
-Service: Servicio
-Packaging: Embalaje
diff --git a/forms/ecomerce/ticket/locale/fr.yml b/forms/ecomerce/ticket/locale/fr.yml
deleted file mode 100644
index 74cc068a..00000000
--- a/forms/ecomerce/ticket/locale/fr.yml
+++ /dev/null
@@ -1,25 +0,0 @@
-OrderDetail: Détails de la commande
-ShippingInformation: Informations sur la livraison
-DeliveryAddress: Addresse de livraison
-Print delivery note: Imprimer bulletin de livraison
-Agency: Agence
-Warehouse: Entrepôt
-Total: Total
-Total + tax: Total + impôt
-Tax base: Imposable
-VAT: TVA
-ItemNumber: Num article
-Amount: Quant
-Item: Article
-Category: catégorie
-S1: Mes
-Stems: Tiges
-Color: Couleur
-Origin: Origine
-Price: Prix
-Disc: Remise
-Subtotal: Sous-total
-Preparation: Préparation
-Delivery: Livraison
-Service: Service
-Packaging: Emballage
diff --git a/forms/ecomerce/ticket/locale/pt.yml b/forms/ecomerce/ticket/locale/pt.yml
deleted file mode 100644
index 64bca977..00000000
--- a/forms/ecomerce/ticket/locale/pt.yml
+++ /dev/null
@@ -1,25 +0,0 @@
-OrderDetail: Detalhes da encomenda
-ShippingInformation: Dados de envio
-DeliveryAddress: Endereço de entrega
-Print delivery note: Imprimir nota de entrega
-Agency: Agência
-Warehouse: Armazém
-Total: Total
-Total + tax: Total + IVA
-Tax base: Base tributável
-VAT: IVA
-ItemNumber: Nº Ítem
-Amount: Qtde
-Item: Ítem
-Category: Categoría
-S1: Med
-Stems: Pés
-Color: Cor
-Origin: Orígem
-Price: Preço
-Disc: Desc
-Subtotal: Sub-total
-Preparation: Preparação
-Delivery: Entrega
-Service: Serviço
-Packaging: Embalagem
diff --git a/forms/ecomerce/ticket/style.scss b/forms/ecomerce/ticket/style.scss
deleted file mode 100644
index e3814122..00000000
--- a/forms/ecomerce/ticket/style.scss
+++ /dev/null
@@ -1,78 +0,0 @@
-
-/* Header */
-
-.ticket .head {
-	padding: 0;
-	padding-bottom: 3px;
-	border-bottom: 1px solid #DDD;
-	margin-bottom: 1px;
-}
-.ticket .head > div > div {
-	margin: 15px 0;
-}
-.ticket .head > div > div:first-child {
-	margin: 0;
-}
-.ticket .head p {
-	margin: 3px 0;
-}
-.ticket .head p.important {
-	font-size: 1.2rem;
-	font-weight: bold;
-}
-.ticket .total {
-	text-align: right;
-}
-.ticket .packages {
-	margin-top: 14px;
-	padding-top: 14px;
-	border-top: 1px solid #DDD;
-	display: block;
-}
-
-/* Lines */
-
-.ticket .line {
-	display: flex;
-	align-items: center;
-	gap: 12px;
-	margin: 10px 0;
-	height: 80px;
-}
-.ticket .line:last-child {
-	margin-bottom: 0;
-}
-.ticket .line > .photo {
-	flex: none;
-	border-radius: 50%;
-	width: 68px;
-	height: 68px;
-	gap: 0;
-}
-.ticket .line > .info {
-	flex: 1;
-	overflow: hidden;
-}
-.ticket .line > .info > * {
-	text-overflow: ellipsis;
-	white-space: nowrap;
-	overflow: hidden;
-}
-.ticket .line > .info > h2 {
-	font-size: 1rem;
-	font-weight: normal;
-	margin-bottom: 2px;
-}
-.ticket .line > .info > p {
-	margin: 0;
-}
-.ticket .line > .info > .tags {
-	color: #777;
-}
-.ticket .line > .info .discount {
-	color: green;
-}
-.ticket .line > .info > .subtotal {
-	float: right;
-}
-
diff --git a/forms/ecomerce/ticket/ui.xml b/forms/ecomerce/ticket/ui.xml
deleted file mode 100644
index c31e5f4e..00000000
--- a/forms/ecomerce/ticket/ui.xml
+++ /dev/null
@@ -1,131 +0,0 @@
-<vn>
-<vn-lot-query id="params">
-	<vn-spec name="ticket" type="Number"/>
-</vn-lot-query>
-<db-lot id="ticket-form" lot="params" v-model="ticket">
-	CALL myTicket_get(#ticket)
-</db-lot>
-<div id="title">
-	<h1><t>OrderDetail</t></h1>
-</div>
-<div id="actions" class="action-bar">
-	<htk-bar-button
-		icon="print"
-		tip="_Print delivery note"
-		on-click="this.onPrintClick()"/>
-</div>
-<div id="form" class="ticket">
-	<div class="box vn-w-sm vn-pa-lg">
-		<htk-loader class="head" form="ticket-form">
-			<h5>#{{ticket.id}}</h5>
-			<div>
-				<h6><t>ShippingInformation</t></h6>
-				<p>
-					<t>Preparation</t> {{Vn.Value.format(ticket.shipped, '%D')}}
-				</p>
-				<p>
-					<t>Delivery</t> {{Vn.Value.format(ticket.landed, '%D')}}
-				</p>
-				<p>
-					{{_(ticket.method != 'PICKUP' ? 'Agency' : 'Warehouse')}} {{ticket.agency}}
-				</p>
-			</div>
-			<div class="address">
-				<h6><t>DeliveryAddress</t></h6>
-				<p>{{ticket.nickname}}</p>
-				<p>{{ticket.street}}</p>
-				<p>{{ticket.postalCode}} {{ticket.city}} ({{ticket.province}})</p>
-			</div>
-			<div class="total">
-				<p class="important total">
-					<t>Total</t> {{Vn.Value.format(ticket.taxBase, '%.2d€')}}
-				</p>
-				<p class="important total">
-					<t>Total + tax</t> {{Vn.Value.format(ticket.total, '%.2d€')}}
-				</p>
-			</div>
-		</htk-loader>
-		<htk-repeater form-id="iter" renderer="repeaterFunc">
-			<db-model
-				property="model"
-				id="movements"
-				lot="params">
-				CALL myTicket_getRows(#ticket)
-			</db-model>
-			<custom>
-				<div class="line">
-					<htk-image
-						value="{{iter.image}}"
-						stamp-column="updated"
-						class="photo"
-						directory="catalog"
-						subdir="200x200"
-						full-dir="1600x900"/>
-					<div class="info">
-						<h2>{{iter.concept}}</h2>
-						<p class="tags">
-							{{iter.value5}} {{iter.value6}} {{iter.value7}}
-						</p>
-						<p class="subtotal">
-							<span class="discount" id="discount">
-								{{Vn.Value.format(this.discountSubtotal(iter), '%.2d€')}} - 
-								{{Vn.Value.format(iter.discount, '%.0d%')}} = 
-							</span>
-							{{Vn.Value.format(this.subtotal(iter), '%.2d€')}}
-						</p>
-						<p class="amount">
-							{{iter.quantity}} x {{Vn.Value.format(iter.price, '%.2d€')}}
-						</p>
-					</div>
-				</div>
-			</custom>
-		</htk-repeater>
-		<htk-repeater form-id="iter" id="services" class="packages">
-			<db-model
-				property="model"
-				on-status-changed="onServicesChanged"
-				lot="params">
-				CALL myTicket_getServices(#ticket)
-			</db-model>
-			<custom>
-				<div class="line">
-					<div class="info">
-						<h2>{{iter.description}}</h2>
-						<p class="amount">
-							{{iter.quantity}} x {{Vn.Value.format(iter.price, '%.2d€')}}
-						</p>
-						<p class="subtotal">
-							{{Vn.Value.format(iter.quantity * iter.price, '%.2d€')}}
-						</p>
-					</div>
-					<div class="clear"/>
-				</div>
-			</custom>
-		</htk-repeater>
-		<htk-repeater form-id="iter" id="packages" class="packages">
-			<db-model
-				property="model"
-				on-status-changed="onPackagesChanged"
-				lot="params">
-				CALL myTicket_getPackages(#ticket)
-			</db-model>
-			<custom>
-				<div class="line">
-					<htk-image
-						value="{{iter.image}}"
-						class="photo"
-						directory="catalog"
-						subdir="200x200"
-						full-dir="1600x900"/>
-					<div class="info">
-						<h2>{{iter.name}}</h2>
-						<p>#{{iter.id}}</p>
-						<p class="amount">{{iter.quantity}}</p>
-					</div>
-					<div class="clear"/>
-				</div>
-			</custom>
-		</htk-repeater>
-	</div>
-</div>
-</vn>
diff --git a/forms/news/new/index.js b/forms/news/new/index.js
deleted file mode 100644
index 1b6e1d4c..00000000
--- a/forms/news/new/index.js
+++ /dev/null
@@ -1,108 +0,0 @@
-import './style.scss';
-
-// TinyMCE
-const tinymce = require('tinymce/tinymce');
-require('tinymce/icons/default');
-require('tinymce/themes/silver');
-require('tinymce/skins/ui/oxide/skin.css');
-require('tinymce/models/dom');
-require('tinymce/plugins/advlist');
-require('tinymce/plugins/code');
-require('tinymce/plugins/emoticons');
-require('tinymce/plugins/emoticons/js/emojis');
-require('tinymce/plugins/link');
-require('tinymce/plugins/lists');
-require('tinymce/plugins/table');
-require('tinymce/plugins/autolink');
-require('tinymce/plugins/image');
-require('tinymce/plugins/charmap');
-require('tinymce/plugins/preview');
-require('tinymce/plugins/anchor');
-require('tinymce/plugins/pagebreak');
-require('tinymce/plugins/searchreplace');
-require('tinymce/plugins/wordcount');
-require('tinymce/plugins/visualblocks');
-require('tinymce/plugins/visualchars');
-require('tinymce/plugins/code');
-require('tinymce/plugins/fullscreen');
-require('tinymce/plugins/insertdatetime');
-require('tinymce/plugins/media');
-require('tinymce/plugins/nonbreaking');
-require('tinymce/plugins/save');
-require('tinymce/plugins/table');
-require('tinymce/plugins/directionality');
-require('tinymce/plugins/emoticons');
-require('tinymce/plugins/template');
-const contentUiCss = require('tinymce/skins/ui/oxide/content.css');
-const contentCss = require('tinymce/skins/content/default/content.css');
-
-export default new Class({
-	Extends: Hedera.Form,
-	Template: require('./ui.xml'),
-	
-	editor: null,
-
-	activate() {
-		this.$.model.mode = Db.Model.Mode.ON_DEMAND;
-		this.$.model.setDefault('userFk', 'news',
-			new Sql.Function({schema: 'account', name: 'myUser_getId'}));
-
-		tinymce.init({
-			 target: this.$.htmlEditor
-			,plugins:
-				 ' advlist autolink lists link image charmap preview'
-				+' anchor pagebreak searchreplace wordcount visualblocks'
-				+' visualchars code fullscreen insertdatetime media nonbreaking'
-				+' save table directionality emoticons template'
-			,toolbar1:
-				 ' print preview paste'
-				+'|link image media emoticons blockquote hr'
-				+'|insertfile undo redo'
-				+'|bold italic'
-				+'|alignleft aligncenter alignright alignjustify'
-				+'|bullist numlist outdent indent'
-				+'|styleselect'
-				+'|fontselect fontsizeselect'
-				+'|forecolor backcolor '
-			,image_advtab: true
-			,init_instance_callback: editor => this._onEditorInit(editor)
-			,skin: false
-			,content_css: false
-			,content_style: contentUiCss.toString() + '\n' + contentCss.toString()
-		});
-	},
-	
-	deactivate() {
-		this.editor.destroy();
-	},
-	
-	_onEditorInit(editor) {
-		this.editor = editor;
-		editor.getDoc().body.style.fontSize = '1rem';
-		this.setEditorText();
-	},
-	
-	setEditorText() {
-		if (!this.editor) return;
-		const row = this.$.iter.$;
-		this.editor.setContent(row ? row.text : '');
-	},
-
-	onReady() {
-		if (this.hash.$.new)
-			this.setEditorText();
-		else
-			this.$.iter.insertRow();
-	},
-
-	async onAcceptClick() {
-		this.$.iter.set('text', this.editor.getContent());
-		await this.$.iter.performOperations();
-		Htk.Toast.showMessage(_('NewChangedSuccessfully'));
-		this.onReturnClick();
-	},
-
-	onReturnClick() {
-		this.hash.setAll({form: 'news/news'});
-	}
-});
diff --git a/forms/news/new/locale/ca.yml b/forms/news/new/locale/ca.yml
deleted file mode 100644
index 405c0281..00000000
--- a/forms/news/new/locale/ca.yml
+++ /dev/null
@@ -1,8 +0,0 @@
-AddEditNew: Afegir o editar notícia
-Title: Títol
-NewBody: Cos
-Tag: Etiqueta
-Priority: Prioritat
-Return: Tornar
-Accept: Acceptar
-NewChangedSuccessfully: Notícia modificada correctament
diff --git a/forms/news/new/locale/en.yml b/forms/news/new/locale/en.yml
deleted file mode 100644
index 329071c1..00000000
--- a/forms/news/new/locale/en.yml
+++ /dev/null
@@ -1,8 +0,0 @@
-AddEditNew: Add or edit new
-Title: Title
-NewBody: New body
-Tag: Tag
-Priority: Priority
-Return: Return
-Accept: Accept
-NewChangedSuccessfully: New changed successfully
diff --git a/forms/news/new/locale/es.yml b/forms/news/new/locale/es.yml
deleted file mode 100644
index 6e53ffa3..00000000
--- a/forms/news/new/locale/es.yml
+++ /dev/null
@@ -1,8 +0,0 @@
-AddEditNew: Añadir o editar noticia
-Title: Título
-NewBody: Cuerpo
-Tag: Etiqueta
-Priority: Prioridad
-Return: Volver
-Accept: Aceptar
-NewChangedSuccessfully: Noticia modificada correctamente
diff --git a/forms/news/new/locale/fr.yml b/forms/news/new/locale/fr.yml
deleted file mode 100644
index 06e6291d..00000000
--- a/forms/news/new/locale/fr.yml
+++ /dev/null
@@ -1,8 +0,0 @@
-AddEditNew: Ajouter ou editer nouvelles
-Title: Titre
-NewBody: Corps
-Tag: Tag
-Priority: Priorité
-Return: Reviens
-Accept: Accepter
-NewChangedSuccessfully: Nouvelles modifié avec succès
diff --git a/forms/news/new/locale/pt.yml b/forms/news/new/locale/pt.yml
deleted file mode 100644
index c789b2e7..00000000
--- a/forms/news/new/locale/pt.yml
+++ /dev/null
@@ -1,8 +0,0 @@
-AddEditNew: Adicionar ou editar notícia
-Title: Título
-NewBody: Corpo
-Tag: Etiqueta
-Priority: Prioridade
-Return: Voltar
-Accept: Aceitar
-NewChangedSuccessfully: Noticia modificada corretamente
diff --git a/forms/news/new/style.scss b/forms/news/new/style.scss
deleted file mode 100644
index 6a5aaac2..00000000
--- a/forms/news/new/style.scss
+++ /dev/null
@@ -1,32 +0,0 @@
-.hedera-new {
-	.box {
-		position: relative;
-	}
-	.htk-image {
-		height: 100px;
-		overflow: hidden;
-		border-bottom: 1px solid #ddd;
-	}
-	.htk-image > button {
-		display: block;
-	}
-	.htk-image > img {
-		margin-top: -40%;
-		width: 100%;
-		height: initial;
-	}
-	.tag-priority {
-		display: flex;
-		gap: 16px;
-	}
-	.tag-priority > *{
-		flex: 1;
-	}
-	textarea {
-		min-height: 500px;
-	}
-	.tox-tinymce {
-		border: 1px solid #ddd;
-		border-radius: 0;
-	}
-}
diff --git a/forms/news/new/ui.xml b/forms/news/new/ui.xml
deleted file mode 100644
index 305f9478..00000000
--- a/forms/news/new/ui.xml
+++ /dev/null
@@ -1,66 +0,0 @@
-<vn>
-<vn-group>
-	<db-form id="iter"
-		on-ready="this.onReady()">
-		<db-model
-			id="model"
-			property="model"
-			updatable="true"
-			lot="hash">
-			SELECT id, title, text, tag, priority, image
-				FROM news WHERE id = #new
-		</db-model>
-	</db-form>
-</vn-group>
-<div id="title">
-	<h1><t>AddEditNew</t></h1>
-</div>
-<div id="actions">
-	<htk-bar-button
-		icon="close"
-		tip="_Return"
-		on-click="this.onReturnClick()"/>
-	<htk-bar-button
-		icon="check"
-		tip="_Accept"
-		on-click="this.onAcceptClick()"/>
-</div>
-<div id="form" class="hedera-new">
-	<div class="box form vn-w-sm">
-		<htk-image
-			form="iter"
-			column="image"
-			class="photo"
-			directory="news"
-			subdir="full"
-			full-dir="full"
-			editable="true"
-			conn="conn"/>
-		<div class="vn-pa-lg">
-			<div class="form-group">
-				<label><t>Title</t></label>
-				<htk-entry form="iter" column="title"/>
-			</div>
-			<div class="form-group tag-priority">
-				<div>
-					<label><t>Tag</t></label>
-					<htk-combo form="iter" column="tag">
-						<db-model property="model">
-							SELECT name, description FROM newsTag
-								ORDER BY description
-						</db-model>
-					</htk-combo>
-				</div>
-				<div>
-					<label><t>Priority</t></label>
-					<htk-entry form="iter" column="priority"/>
-				</div>
-			</div>
-			<div class="form-group">
-				<label><t>NewBody</t></label>
-				<textarea id="html-editor"/>
-			</div>
-		</div>
-	</div>
-</div>
-</vn>
diff --git a/forms/news/news/index.js b/forms/news/news/index.js
deleted file mode 100644
index 770472e2..00000000
--- a/forms/news/news/index.js
+++ /dev/null
@@ -1,30 +0,0 @@
-import './style.scss';
-
-export default new Class({
-	Extends: Hedera.Form,
-	Template: require('./ui.xml'),
-
-	activate() {
-		this.$.newsModel.setInfo('n', 'news', 'hedera', ['id'], 'id');
-	},
-	
-	onAddClick() {
-		this.hash.setAll({
-			form: 'news/new',
-			new: null
-		});
-	},
-
-	onEditClick(newId) {
-		this.hash.setAll({
-			form: 'news/new',
-			new: newId
-		});
-	},
-
-	async onDeleteClick(form) {
-		if (confirm(_('ReallyDelete')))
-			await form.deleteRow();
-	}
-});
-
diff --git a/forms/news/news/locale/ca.yml b/forms/news/news/locale/ca.yml
deleted file mode 100644
index 53773038..00000000
--- a/forms/news/news/locale/ca.yml
+++ /dev/null
@@ -1,8 +0,0 @@
-NewsManagement: Gestió de noticies
-AddNew: Afegir noticia
-EditNew: Edita notícia
-NewNum: N notícia
-Date: Data
-Author: Autor
-Title: Títol
-Priority: Prioritat
diff --git a/forms/news/news/locale/en.yml b/forms/news/news/locale/en.yml
deleted file mode 100644
index 3b49fc93..00000000
--- a/forms/news/news/locale/en.yml
+++ /dev/null
@@ -1,8 +0,0 @@
-NewsManagement: News management
-AddNew: Add new
-EditNew: Edit new
-NewNum: New number
-Date: Date
-Author: Author
-Title: Title
-Priority: Priority
diff --git a/forms/news/news/locale/es.yml b/forms/news/news/locale/es.yml
deleted file mode 100644
index 17d42a6e..00000000
--- a/forms/news/news/locale/es.yml
+++ /dev/null
@@ -1,8 +0,0 @@
-NewsManagement: Gestión de noticias
-AddNew: Añadir noticia
-EditNew: Editar noticia
-NewNum: Nº noticia
-Date: Fecha
-Author: Autor
-Title: Título
-Priority: Prioridad
diff --git a/forms/news/news/locale/fr.yml b/forms/news/news/locale/fr.yml
deleted file mode 100644
index 7df649c1..00000000
--- a/forms/news/news/locale/fr.yml
+++ /dev/null
@@ -1,8 +0,0 @@
-NewsManagement: Gestion des nouvelles
-AddNew: Ajouter nouvelles
-EditNew: Modifier nouvelles
-NewNum: Nº nouvelles
-Date: Date
-Author: Auteur
-Title: Titre
-Priority: Priorité
diff --git a/forms/news/news/locale/pt.yml b/forms/news/news/locale/pt.yml
deleted file mode 100644
index 9503aac0..00000000
--- a/forms/news/news/locale/pt.yml
+++ /dev/null
@@ -1,8 +0,0 @@
-NewsManagement: Gestão de noticias
-AddNew: Adicionar noticia
-EditNew: Editar noticia
-NewNum: Nº noticia
-Date: Data
-Author: Autor
-Title: Título
-Priority: Prioridade
diff --git a/forms/news/news/style.scss b/forms/news/news/style.scss
deleted file mode 100644
index e36850ce..00000000
--- a/forms/news/news/style.scss
+++ /dev/null
@@ -1,8 +0,0 @@
-
-.hedera-news {
-	.item .photo {
-		height: 80px;
-		width: 80px;
-		border-radius: 10px;
-	}
-}
diff --git a/forms/news/news/ui.xml b/forms/news/news/ui.xml
deleted file mode 100644
index 9e6074c7..00000000
--- a/forms/news/news/ui.xml
+++ /dev/null
@@ -1,55 +0,0 @@
-<vn>
-<div id="title">
-	<h1><t>NewsManagement</t></h1>
-</div>
-<div id="actions">
-	<htk-bar-button
-		icon="add"
-		tip="_AddNew"
-		on-click="hash.setAll({form: 'news/new', new: null})"/>
-</div>
-<div id="form" class="hedera-news">
-	<htk-repeater form-id="iter" class="box htk-list vn-w-sm">
-		<db-model property="model" id="news-model" updatable="true">
-			<custom>
-				SELECT n.id, u.nickname, n.priority, n.image, n.title
-					FROM news n
-						JOIN account.user u ON u.id = n.userFk
-					ORDER BY priority, n.created DESC
-			</custom>
-		</db-model>
-		<custom>
-			<a class="item"
-				href="{{`#!form=news/new&amp;new=${iter.id}`}}"
-				title="_EditNew">
-				<div class="side vn-mr-md">
-					<htk-image
-						form="$iter"
-						column="image"
-						class="photo"
-						directory="news"
-						subdir="200x200"
-						full-dir="full"
-						editable="true"
-						conn="conn"/>
-				</div>
-				<div class="content">
-					<p class="important">
-						{{iter.title}}
-					</p>
-					<p>{{iter.nickname}}</p>
-					<p>{{iter.priority}}</p>
-				</div>
-				<div
-					class="actions"
-					on-click="$event.preventDefault()">
-					<htk-button
-						tip="_Remove"
-						icon="delete"
-						on-click="this.onDeleteClick($iter)"/>
-				</div>
-			</a>
-		</custom>
-	</htk-repeater>
-</div>
-</vn>
diff --git a/forms/reports/items-form/index.js b/forms/reports/items-form/index.js
deleted file mode 100644
index 559e0f35..00000000
--- a/forms/reports/items-form/index.js
+++ /dev/null
@@ -1,19 +0,0 @@
-import './style.scss';
-
-export default new Class({
-	Extends: Hedera.Form,
-	Template: require('./ui.xml')
-	
-	,activate() {
-		this.$.lot.assign({
-			warehouse: 7,
-			realm: null
-		});
-	}
-	
-	,onPreviewClick() {
-		this.$.lot.set('rate', this.$.rate.value);
-		this.gui.openReport('items-report', this.$.lot);
-	}
-});
-
diff --git a/forms/reports/items-form/locale/en.yml b/forms/reports/items-form/locale/en.yml
deleted file mode 100644
index 3ef8e761..00000000
--- a/forms/reports/items-form/locale/en.yml
+++ /dev/null
@@ -1,5 +0,0 @@
-Item list: Item list
-Store: Store
-Realm: Realm
-Rate: Rate
-Preview: Preview
diff --git a/forms/reports/items-form/locale/es.yml b/forms/reports/items-form/locale/es.yml
deleted file mode 100644
index 816be9c0..00000000
--- a/forms/reports/items-form/locale/es.yml
+++ /dev/null
@@ -1,5 +0,0 @@
-Item list: Listado de artículos
-Store: Almacén
-Realm: Reino
-Rate: Tarifa
-Preview: Mostrar
diff --git a/forms/reports/items-form/locale/pt.yml b/forms/reports/items-form/locale/pt.yml
deleted file mode 100644
index f38a6b34..00000000
--- a/forms/reports/items-form/locale/pt.yml
+++ /dev/null
@@ -1,5 +0,0 @@
-Item list: Lista de Ítens
-Store: Armazém
-Realm: Reino
-Rate: Tarifa
-Preview: Mostrar
diff --git a/forms/reports/items-form/style.scss b/forms/reports/items-form/style.scss
deleted file mode 100644
index e69de29b..00000000
diff --git a/forms/reports/items-form/ui.xml b/forms/reports/items-form/ui.xml
deleted file mode 100644
index 8b6462db..00000000
--- a/forms/reports/items-form/ui.xml
+++ /dev/null
@@ -1,42 +0,0 @@
-<vn>
-<vn-lot id="lot"/>
-<div id="title">
-	<h1><t>Item list</t></h1>
-</div>
-<div id="actions" class="action-bar">
-	<htk-bar-button
-		icon="print"
-		tip="_Preview"
-		on-click="this.onPreviewClick()"/>
-</div>
-<div id="form" class="items">
-	<div class="form box vn-w-sm vn-pa-lg">
-		<div class="form-group">
-			<label><t>Store</t></label>
-			<htk-combo form="lot" column="warehouse">
-				<db-model property="model">
-					SELECT id, name FROM vn2008.warehouse
-						WHERE reserve ORDER BY name
-				</db-model>
-			</htk-combo>
-		</div>
-		<div class="form-group">
-			<label><t>Realm</t></label>
-			<htk-combo form="lot" column="realm" not-null="false">
-				<db-model property="model">
-					SELECT id, reino FROM vn2008.reinos
-						WHERE display != FALSE ORDER BY reino
-				</db-model>
-			</htk-combo>
-		</div>
-		<div class="form-group">
-			<label><t>Rate</t></label>
-			<select id="rate">
-				<option>3</option>
-				<option>2</option>
-				<option>1</option>
-			</select>
-		</div>
-	</div>
-</div>
-</vn>
diff --git a/forms/reports/shelves/index.js b/forms/reports/shelves/index.js
deleted file mode 100644
index 0cbb379c..00000000
--- a/forms/reports/shelves/index.js
+++ /dev/null
@@ -1,22 +0,0 @@
-import './style.scss';
-
-export default new Class({
-	Extends: Hedera.Form,
-	Template: require('./ui.xml'),
-
-	activate() {
-		this.$.lot.assign({
-			date: new Date(),
-			useIds: false
-		});
-	},
-
-	onConfigChange() {
-		this.$.lot.assignLot(this.$.config);
-	},
-	
-	onPreviewClick() {
-		this.gui.openReport('shelves-report', this.$.lot);
-	}
-});
-
diff --git a/forms/reports/shelves/locale/ca.yml b/forms/reports/shelves/locale/ca.yml
deleted file mode 100644
index 0967ef42..00000000
--- a/forms/reports/shelves/locale/ca.yml
+++ /dev/null
@@ -1 +0,0 @@
-{}
diff --git a/forms/reports/shelves/locale/en.yml b/forms/reports/shelves/locale/en.yml
deleted file mode 100644
index 67838b82..00000000
--- a/forms/reports/shelves/locale/en.yml
+++ /dev/null
@@ -1,15 +0,0 @@
-Configuration: Configuration
-Select config: Select config
-Reign: Reign
-Family: Family
-Store: Store
-Date: Date
-Shelf: Shelf
-Name prefix: Name prefix
-Limit amount per item: Limit amount per item
-Title: Title
-Show packing: Show packing
-Stack different items: Stack different items
-Preview: Preview
-Pallets: Pallets
-'No items found, check that all fields are correct': 'No items found, check that all fields are correct'
diff --git a/forms/reports/shelves/locale/es.yml b/forms/reports/shelves/locale/es.yml
deleted file mode 100644
index 955788d2..00000000
--- a/forms/reports/shelves/locale/es.yml
+++ /dev/null
@@ -1,15 +0,0 @@
-Configuration: Configuración
-Select config: Selecciona configuración
-Reign: Reino
-Family: Familia
-Store: Almacén
-Date: Fecha
-Shelf: Estantería
-Name prefix: Prefijo del nombre
-Limit amount per item: Límite de cantidad por artículo
-Title: Título
-Show packing: Mostrar unidades por caja
-Stack different items: Apilar artículos distintos
-Preview: Mostrar
-Pallets: Palets
-'No items found, check that all fields are correct': 'No se han encontrado artículos, comprueba que todos los campos son correctos'
diff --git a/forms/reports/shelves/locale/fr.yml b/forms/reports/shelves/locale/fr.yml
deleted file mode 100644
index 0967ef42..00000000
--- a/forms/reports/shelves/locale/fr.yml
+++ /dev/null
@@ -1 +0,0 @@
-{}
diff --git a/forms/reports/shelves/locale/pt.yml b/forms/reports/shelves/locale/pt.yml
deleted file mode 100644
index 3a02ba9d..00000000
--- a/forms/reports/shelves/locale/pt.yml
+++ /dev/null
@@ -1,15 +0,0 @@
-Configuration: Configuração
-Select config: Selecione a configuração
-Reign: Reino
-Family: Familia
-Store: Armazém
-Date: Data
-Shelf: Pratilheira
-Name prefix: Prefixo do nome
-Limit amount per item: Limíte de quantidade por ítem
-Title: Título
-Show packing: Mostrar unidades por caixa
-Stack different items: Empilhar ítens diferentes
-Preview: Mostrar
-Pallets: Palets
-'No items found, check that all fields are correct': 'Nenhum ítem encontrado, comprove que todos os campos estão corretos'
diff --git a/forms/reports/shelves/style.scss b/forms/reports/shelves/style.scss
deleted file mode 100644
index e69de29b..00000000
diff --git a/forms/reports/shelves/ui.xml b/forms/reports/shelves/ui.xml
deleted file mode 100644
index 376a1bff..00000000
--- a/forms/reports/shelves/ui.xml
+++ /dev/null
@@ -1,105 +0,0 @@
-<vn>
-<vn-lot-query id="params">
-	<vn-spec name="config" type="Number"/>
-</vn-lot-query>
-<vn-lot id="lot"/>
-<div id="title">
-	<h1><t>Shelves</t></h1>
-</div>
-<div id="actions" class="action-bar">
-	<htk-bar-button
-		icon="print"
-		tip="_Preview"
-		on-click="this.onPreviewClick()"/>
-</div>
-<div id="form" class="shelves">
-	<div class="form box vn-w-sm vn-pa-lg">
-		<div class="form-group">
-			<label><t>Configuration</t></label>
-			<htk-combo
-				id="config"
-				placeholder="_Select config"
-				form="params"
-				column="config"
-				on-changed="this.onConfigChange()"
-				on-ready="this.onConfigChange()">
-				<db-model property="model">
-					SELECT c.id, c.name reportTitle, c.namePrefix, c.warehouse, c.family,
-					c.shelf, c.maxAmount, c.showPacking, c.stack, t.reino_id realm
-						FROM shelfConfig c
-						JOIN vn2008.Tipos t ON t.tipo_id = c.family
-				</db-model>
-			</htk-combo>
-		</div>
-		<div class="form-group">
-			<label><t>Date</t></label>
-			<htk-date-chooser form="lot" name="date"/>
-		</div>
-		<div class="form-group">
-			<label><t>Reign</t></label>
-			<htk-combo form="lot" name="realm">
-				<db-model property="model">
-					SELECT id, reino FROM vn2008.reinos
-						WHERE display != FALSE ORDER BY reino
-				</db-model>
-			</htk-combo>
-		</div>
-		<div class="form-group">
-			<label><t>Family</t></label>
-			<htk-combo form="lot" name="family">
-				<db-model property="model" lot="lot">
-					SELECT tipo_id, Tipo FROM vn2008.Tipos 
-						WHERE reino_id = #realm ORDER BY Tipo
-				</db-model>
-			</htk-combo>
-		</div>
-		<div class="form-group">
-			<label><t>Store</t></label>
-			<htk-combo form="lot">
-				<db-model property="model">
-					SELECT id, name FROM vn2008.warehouse
-						WHERE reserve ORDER BY name
-				</db-model>
-			</htk-combo>
-		</div>
-		<div class="form-group">
-			<label><t>Shelf</t></label>
-			<htk-combo form="lot" name="shelf">
-				<db-model property="model">
-					SELECT id, name FROM shelf
-				</db-model>
-			</htk-combo>
-		</div>
-		<div class="form-group">
-			<label><t>Name prefix</t></label>
-			<htk-entry form="lot" name="namePrefix"/>
-		</div>
-		<div class="form-group">
-			<label><t>Limit amount per item</t></label>
-			<htk-entry form="lot" name="maxAmount"/>
-		</div>
-		<div class="form-group">
-			<label><t>Title</t></label>
-			<htk-entry form="lot" name="reportTitle"/>
-		</div>
-		<div class="form-group">
-			<label>
-				<htk-check form="lot" name="showPacking"/>
-				<t>Show packing</t>
-			</label>
-		</div>
-		<div class="form-group">
-			<label>
-				<htk-check form="lot" name="stack"/>
-				<t>Stack different items</t>
-			</label>
-		</div>
-		<div class="form-group">
-			<label>
-				<htk-check form="lot" name="useIds"/>
-				<t>Use ids instead of names</t>
-			</label>
-		</div>
-	</div>
-</div>
-</vn>
diff --git a/js/db/calc-sum.js b/js/db/calc-sum.js
deleted file mode 100644
index 9314a236..00000000
--- a/js/db/calc-sum.js
+++ /dev/null
@@ -1,52 +0,0 @@
-
-var Calc = require ('./calc');
-
-/**
- * Computes a sum of data in the model.
- */
-module.exports = new Class
-({
-	Extends: Calc
-	,Tag: 'db-calc-sum'
-
-	,getRowValue: function (row)
-	{
-		var value;
-	
-		if (this._func)
-		{
-			this._set.row = row;
-			value = this._func (this._set);
-		}
-		else
-			value = this._model.getByIndex (row, this.columnIndex);
-
-		return value;
-	}
-
-	,before: function (row)
-	{
-		var value = this.getRowValue (row)
-	
-		if (value !== null)
-			this._sum -= value;
-	}
-
-	,after: function (row)
-	{
-		var value = this.getRowValue (row);
-
-		if (value !== null)
-			this._sum += value;
-	}
-
-	,init: function ()
-	{
-		this._sum = 0;
-	}
-
-	,done: function ()
-	{
-		this.value = this._sum;
-	}
-});
diff --git a/js/db/calc.js b/js/db/calc.js
deleted file mode 100644
index 17851a6b..00000000
--- a/js/db/calc.js
+++ /dev/null
@@ -1,154 +0,0 @@
-
-var Model = require ('./model');
-var SimpleIterator = require ('./simple-iterator');
-
-/**
- * Interface for handle foreach operations on the model.
- */
-module.exports = new Class
-({
-	Extends: Vn.Param
-	,Tag: 'db-calc'
-	,Properties:
-	{
-		 model:
-		 {
-			type: Model
-			,set: function (x)
-			{
-				this.link ({_model: x},
-				{
-					 'status-changed': this.onModelChange
-					,'row-deleted-before': this.onRowDeleteBefore
-					,'row-updated': this.onRowUpdate
-					,'row-updated-before': this.onRowUpdateBefore
-					,'row-inserted': this.onRowInsert
-				});
-
-				var set = new SimpleIterator ({model: x});
-				this.link ({_set: set});
-			}
-			,get: function ()
-			{
-				return this._model;
-			}
-		},
-		columnIndex:
-		{
-			type: Number
-			,set: function (x)
-			{
-				this.reset ();
-				this._columnIndex = x;
-				this.onModelChange ();
-			}
-			,get: function ()
-			{
-				return this._columnIndex;
-			}
-		},
-		columnName:
-		{
-			type: String
-			,set: function (x)
-			{
-				this.reset ();
-				this._columnName = x;
-				this.onModelChange ();
-			}
-			,get: function ()
-			{
-				return this._columnName;
-			}
-		},
-		func:
-		{
-			type: Function
-			,set: function (x)
-			{
-				this.reset ();
-				this._func = x;
-				this.onModelChange ();
-			}
-			,get: function ()
-			{
-				return this._func;
-			}
-		}
-	}
-	
-	,_model: null
-	
-	,reset: function ()
-	{
-		delete this._columnIndex;
-		delete this._columnName;
-		delete this._func;
-	}
-
-	,onModelChange: function ()
-	{
-		this.init ();
-
-		if (this._model)
-		{
-			if (this._model.ready && this._columnName)
-				this._columnIndex = this._model.getColumnIndex (this._columnName);
-
-			var rows = this._model.numRows;
-
-			for (var i = 0; i < rows; i++)
-				this.after (i);
-		}
-
-		this.done ();
-	}
-	
-	,onRowInsert: function (model, row)
-	{
-		this.after (row);
-		this.done ();
-	}
-	
-	,onRowUpdateBefore: function (model, row)
-	{
-		this.before (row);
-	}
-	
-	,onRowUpdate: function (model, row)
-	{
-		this.after (row);
-		this.done ();
-	}
-	
-	,onRowDeleteBefore: function (model, row)
-	{
-		this.before (row);
-		this.done ();
-	}
-
-	/**
-	 * Called before each update or delete row operation.
-	 * You don't need to define it if model isn't updatable.
-	 *
-	 * @param {integer} row The row number
-	 */
-	,before: function (row) {}
-
-	/**
-	 * Called after each update or insert row operation.
-	 *
-	 * @param {integer} row The row number
-	 */
-	,after: function (row) {}
-
-	/**
-	 * Called before each model refresh.
-	 */
-	,init: function () {}
-
-	/**
-	 * Called when an operation in the model is complete.
-	 */
-	,done: function () {}
-});
diff --git a/js/db/connection.js b/js/db/connection.js
deleted file mode 100644
index badbdd49..00000000
--- a/js/db/connection.js
+++ /dev/null
@@ -1,152 +0,0 @@
-
-/**
- * Simulates a connection to a database by making asynchronous requests to a
- * remote REST service that returns the results in JSON format.
- * Using this class can perform any operation that can be done with a database,
- * like open/close a connection or selecion/updating queries.
- *
- * Warning! You should set a well defined dababase level privileges to use this
- * class or you could have a serious security hole in you application becasuse
- * the user can send any statement to the server. For example: DROP DATABASE
- */
-var Connection = new Class();
-module.exports = Connection;
-
-var Flag = {
-	 NOT_NULL : 1
-	,PRI_KEY  : 2
-	,AI       : 512 | 2 | 1
-};
-
-var Type = {
-	 BOOLEAN   : 1
-	,INTEGER   : 3
-	,DOUBLE    : 4
-	,STRING    : 5
-	,DATE      : 8
-	,DATE_TIME : 9
-};
-
-Connection.extend({
-	 Flag: Flag
-	,Type: Type
-});
-
-Connection.implement({
-	Extends: Vn.JsonConnection
-
-	/**
-	 * Runs a SQL query on the database.
-	 *
-	 * @param {String} sql The SQL statement
-	 * @return {ResultSet} The result
-	 */
-	,async execSql(sql) {
-		const json = await this.send('core/query', {sql});
-		const results = [];
-		let err;
-
-		if (json)
-		try {
-			if (json && json instanceof Array)
-			for (let i = 0; i < json.length; i++)
-			if (json[i] !== true) {
-				const rows = json[i].data;
-				const columns = json[i].columns;
-
-				const data = new Array(rows.length);
-				results.push({
-					data,
-					columns,
-					tables: json[i].tables
-				});
-
-				for (let j = 0; j < rows.length; j++) {
-					const row = data[j] = {};
-					for (let k = 0; k < columns.length; k++)
-						row[columns[k].name] = rows[j][k];
-				}
-
-				for (let j = 0; j < columns.length; j++) {
-					let castFunc = null;
-					const col = columns[j];
-			
-					switch (col.type) {
-						case Type.DATE:
-						case Type.DATE_TIME:
-						case Type.TIMESTAMP:
-							castFunc = this.valueToDate;
-							break;
-					}
-			
-					if (castFunc !== null) {
-						if (col.def != null)
-							col.def = castFunc(col.def);
-
-						for (let k = 0; k < data.length; k++)
-							if (data[k][col.name] != null)
-								data[k][col.name] = castFunc(data[k][col.name]);
-					}
-				}
-			} else
-				results.push(json[i]);
-		} catch (e) {
-			err = e;
-		}
-
-		return new Db.ResultSet(results, err);
-	}
-	
-	/**
-	 * Runs a stmt on the database.
-	 *
-	 * @param {Sql.Stmt} stmt The statement
-	 * @param {Object} params The query params
-	 * @return {ResultSet} The result
-	 */
-	,async execStmt(stmt, params) {
-		return await this.execSql(stmt.render(params));
-	}
-
-	/**
-	 * Runs a query on the database.
-	 *
-	 * @param {String} query The SQL statement
-	 * @param {Object} params The query params
-	 * @return {ResultSet} The result
-	 */
-	,async execQuery(query, params) {
-		return await this.execStmt(new Sql.String({query}), params);
-	}
-
-	/*
-	 * Parses a value to date.
-	 */
-	,valueToDate(value) {
-		return fixTz(new Date(value));
-	}
-});
-
-// TODO: Read time zone from db configuration
-var tz = {timeZone: 'Europe/Madrid'};
-var isLocal = Intl
-	.DateTimeFormat()
-	.resolvedOptions()
-	.timeZone == tz.timeZone;
-
-function fixTz(date) {
-	if (isLocal) return date;
-
-	var localDate = new Date(date.toLocaleString('en-US', tz));
-	var hasTime = localDate.getHours()
-		|| localDate.getMinutes()
-		|| localDate.getSeconds()
-		|| localDate.getMilliseconds(); 
-
-	if (!hasTime) {
-		date.setHours(date.getHours() + 12);
-		date.setHours(0, 0, 0, 0);
-	}
-
-	return date;
-}
diff --git a/js/db/db-lot.js b/js/db/db-lot.js
deleted file mode 100644
index 4b79dcc5..00000000
--- a/js/db/db-lot.js
+++ /dev/null
@@ -1,109 +0,0 @@
-
-var Connection = require('./connection');
-var Model = require('./model');
-
-module.exports = new Class({
-	Extends: Vn.Form
-	,Tag: 'db-lot'
-	,Properties: {
-		/**
-		 * The connection used to execute the statement.
-		 */
-		conn: {
-			type: Connection
-			,set(x) {
-				this.model.conn = x;
-			}
-			,get() {
-				return this.model.conn;
-			}
-		},
-		/**
-		 * The model query.
-		 */
-		query: {
-			type: String
-			,set(x) {
-				this.model.query = x;
-			}
-			,get() {
-				return this.model.query;
-			}
-		},
-		/**
-		 * The model select statement.
-		 */
-		stmt: {
-			type: Sql.Stmt
-			,set(x) {
-				this.model.stmt = x;
-			}
-			,get() {
-				return this.model.stmt;
-			}
-		},
-		/**
-		 * The lot used to execute the statement.
-		 */
-		lot: {
-			type: Vn.Lot
-			,set(x) {
-				this.model.lot = x;
-			}
-			,get() {
-				return this.model.lot;
-			}
-		}
-	}
-
-	,initialize(props) {
-		this.model = new Model();
-		Vn.Form.prototype.initialize.call(this, props);
-	}
-
-	,appendChild(child) {
-		if (child.nodeType === Node.TEXT_NODE)
-			this.query = child.textContent;
-	}
-	
-	,refresh() {
-		if (this._model)
-			this._model.refresh();
-	}
-	
-	,performOperations() {
-		if (this._model)
-			this._model.performOperations();
-	}
-	
-	/**
-	 * Get the index of the column from its name.
-	 *
-	 * @param {string} columnName The column name
-	 * @return {integer} The column index or -1 if column not exists
-	 */
-	,getColumnIndex(columnName) {
-		return this._model ?
-			this._model.getColumnIndex(columnName) : -1;
-	}
-
-	/**
-	 * Gets a value from the form using the column index.
-	 *
-	 * @param {string} columnName The column index
-	 * @return {Object} The value
-	 */
-	,getByIndex(column) {
-		return this._model.getByIndex(this._row, column);
-	}
-
-	/**
-	 * Sets a value on the form using the column index.
-	 *
-	 * @param {string} columnName The column index
-	 * @param {Object} value The new value
-	 */
-	,setByIndex(column, value) {
-		return this._model.setByIndex(this._row, column, value);
-	}
-});
diff --git a/js/db/db.js b/js/db/db.js
deleted file mode 100644
index 073799ae..00000000
--- a/js/db/db.js
+++ /dev/null
@@ -1,17 +0,0 @@
-
-require('sql/sql');
-
-Db = module.exports = {
-	 Connection     : require('./connection')
-	,Result         : require('./result')
-	,ResultSet      : require('./result-set')
-	,Model          : require('./model')
-	,Iterator       : require('./iterator')
-	,SimpleIterator : require('./simple-iterator')
-	,Form           : require('./form')
-	,Query          : require('./query')
-	,Calc           : require('./calc')
-	,CalcSum        : require('./calc-sum')
-	,Lot            : require('./db-lot')
-};
-
diff --git a/js/db/form.js b/js/db/form.js
deleted file mode 100644
index 379a8648..00000000
--- a/js/db/form.js
+++ /dev/null
@@ -1,105 +0,0 @@
-
-var Iterator = require('./iterator');
-var Model = require('./model');
-
-module.exports = new Class({
-	Extends: Vn.Object
-	,Implements: Iterator
-	,Tag: 'db-form'
-	,Properties: {
-		/**
-		 * The model associated to this form.
-		 */
-		model: { 
-			type: Model
-			,set(x) {
-				this.link({_model: x}, {
-					 'status-changed': this.onModelChange
-					,'row-updated': this.onRowUpdate
-				});
-			}
-			,get() {
-				return this._model;
-			}
-		},
-		/**
-		 * The row where the form positioned, has -1 if the row is unselected.
-		 */
-		row: { 
-			type: Number
-			,set(x) {
-				if (!this._model || this._model.numRows <= x || x < -1)
-					x = -1;
-				if (x == this._row)
-					return;
-
-				this._row = x;
-				this.iterChanged();
-			}
-			,get() {
-				return this._row;
-			}
-		},
-		/**
-		 * The number of rows in the form.
-		 */
-		numRows: {
-			type: Number
-			,get() {
-				if (this._model)
-					return this._model.numRows;
-
-				return 0;
-			}
-		},
-		/**
-		 * Checks if the form data is ready.
-		 */
-		ready: {
-			type: Boolean
-			,get() {
-				return this._ready;
-			}
-		},
-		/**
-		 * The row object.
-		 */
-		$: {
-			type: Object
-			,get() {
-				return this._model && this._model.getObject(this._row);
-			}
-		}
-	}
-	
-	,lastRow: 0
-	,_model: null
-	,_row: -1
-	,_ready: false
-
-	,onModelChange() {
-		var ready = this._model && this._model.ready;
-		
-		if (ready != this._ready) {
-			if (this._row != -1)
-				this.lastRow = this._row;
-	
-			this._ready = ready;
-			this.emit('status-changed');
-			
-			if (this._row == -1)
-				this.row = this.lastRow;
-				
-			if (ready)
-				this.emit('ready');
-
-			this.iterChanged();
-		}
-	}
-
-	,onRowUpdate(model, row) {
-		if (row == this._row)
-			this.iterChanged();
-	}
-});
-
diff --git a/js/db/iterator.js b/js/db/iterator.js
deleted file mode 100644
index 85d8eb1c..00000000
--- a/js/db/iterator.js
+++ /dev/null
@@ -1,133 +0,0 @@
-
-var Model = require('./model');
-
-module.exports = new Class({
-	Properties: {
-		/**
-		 * The model associated to this form.
-		 */
-		model: { 
-			type: Model
-		},
-		/**
-		 * The row where the form positioned, has -1 if the row is unselected.
-		 */
-		row: { 
-			type: Number
-		},
-		/**
-		 * The number of rows in the form.
-		 */
-		numRows: {
-			type: Number
-		},
-		/**
-		 * Checks if the form data is ready.
-		 */
-		ready: {
-			type: Boolean
-		},
-		/**
-		 * The row object.
-		 */
-		$: {
-			type: Object
-		}
-	}
-
-	,_model: null
-	,_row: -1
-	
-	,async refresh() {
-		if (this._model)
-			await this._model.refresh();
-	}
-
-	/**
-	 * Emits the 'change' signal on the form.
-	 */
-	,iterChanged() {
-		this.emit('change');
-	}
-	
-	/**
-	 * Get the index of the column from its name.
-	 *
-	 * @param {String} columnName The column name
-	 * @return {integer} The column index or -1 if column not exists
-	 */
-	,getColumnIndex(columnName) {
-		if (this._model)
-			return this._model.getColumnIndex(columnName);
-			
-		return -1;
-	}
-	
-	,insertRow() {
-		if (this._model)
-			this.row = this._model.insertRow();
-	}
-	
-	,async performOperations() {
-		if (this._model)
-			await this._model.performOperations();
-	}
-
-	/**
-	 * Removes the current row.
-	 */
-	,async deleteRow() {
-		if (this._row >= 0)
-			await this._model.deleteRow(this._row);
-	}
-
-	/**
-	 * Gets the row as object.
-	 *
-	 * @return {Object} The row
-	 */
-	,getObject() {
-		return this._model.getObject(this._row);
-	}
-
-	/**
-	 * Sets a value on the form.
-	 *
-	 * @param {String} columnName The column name
-	 */
-	,get(columnName) {
-		if (!this._model) return undefined;
-		return this._model.get(this._row, columnName);
-	}
-
-	/**
-	 * Sets a value on the form.
-	 *
-	 * @param {String} columnName The column name
-	 * @param {Object} value The new value
-	 */
-	,async set(columnName, value) {
-		return await this._model.set(this._row, columnName, value);
-	}
-
-	/**
-	 * Gets a value from the form using the column index.
-	 *
-	 * @param {String} columnName The column index
-	 * @return {Object} The value
-	 */
-	,getByIndex(column) {
-		return this._model.getByIndex(this._row, column);
-	}
-
-	/**
-	 * Sets a value on the form using the column index.
-	 *
-	 * @param {String} columnName The column index
-	 * @param {Object} value The new value
-	 */
-	,setByIndex(column, value) {
-		return this._model.setByIndex(this._row, column, value);
-	}
-});
-
diff --git a/js/db/locale/ca.yml b/js/db/locale/ca.yml
deleted file mode 100644
index 8ab1a7b3..00000000
--- a/js/db/locale/ca.yml
+++ /dev/null
@@ -1,5 +0,0 @@
-ConnError: Error en la conexió
-BadServerReply: Resposta del servidor incorrecta
-ModelNotUpdatable: Aquest model no és actualitzable
-RowNotExists: El registre no existeix o ha sigut esborrat
-ColNotExists: La columna no existeix
diff --git a/js/db/locale/en.yml b/js/db/locale/en.yml
deleted file mode 100644
index 576730a6..00000000
--- a/js/db/locale/en.yml
+++ /dev/null
@@ -1,5 +0,0 @@
-ConnError: Connection failed
-BadServerReply: Bad server reply
-ModelNotUpdatable: Model not updatable
-RowNotExists: The record does not exist or has been deleted
-ColNotExists: The column does not exist
diff --git a/js/db/locale/es.yml b/js/db/locale/es.yml
deleted file mode 100644
index 24919c17..00000000
--- a/js/db/locale/es.yml
+++ /dev/null
@@ -1,5 +0,0 @@
-ConnError: Error en la conexión
-BadServerReply: Respuesta del servidor incorrecta
-ModelNotUpdatable: Este modelo no es actualizable
-RowNotExists: El registro no existe o a sido borrado
-ColNotExists: La columna no existe
diff --git a/js/db/locale/fr.yml b/js/db/locale/fr.yml
deleted file mode 100644
index 61a6b792..00000000
--- a/js/db/locale/fr.yml
+++ /dev/null
@@ -1,5 +0,0 @@
-ConnError: Échec de la connexion
-BadServerReply: Réponse du serveur incorrecte
-ModelNotUpdatable: Ce modèle n'est pas modifiable
-RowNotExists: Le dossier n'existe pas ou a été supprimée
-ColNotExists: N'existe pas la colonne
diff --git a/js/db/locale/pt.yml b/js/db/locale/pt.yml
deleted file mode 100644
index 1fff629c..00000000
--- a/js/db/locale/pt.yml
+++ /dev/null
@@ -1,5 +0,0 @@
-ConnError: Erro de conexão
-BadServerReply: Má Resposta do servidor
-ModelNotUpdatable: Este modelo não está actualizado
-RowNotExists: O Registro não existe ou foi apagado
-ColNotExists: A Coluna não existe
diff --git a/js/db/model.js b/js/db/model.js
deleted file mode 100644
index 6f15bd46..00000000
--- a/js/db/model.js
+++ /dev/null
@@ -1,1251 +0,0 @@
-
-var Connection = require('./connection');
-
-/**
- * Class to handle the Database select results. Also allows
- * updates, insertions and deletions on tables where the primary key is 
- * selected.
- *
- * Note that table and column names must be unique in the selection query,
- * otherwise updates are not allowed on that table/column. If two tables or
- * columns have the same name, an alias should be used to make it updatable.
- */
-var Model = new Class();
-module.exports = Model;
-
-var Status = {
-	 CLEAN    : 1
-	,LOADING  : 2
-	,READY    : 3
-	,ERROR    : 4
-};
-
-var Mode = {
-	 ON_CHANGE : 1
-	,ON_DEMAND : 2
-};
-
-var Operation = {
-	 INSERT : 1 << 1
-	,UPDATE : 1 << 2
-	,DELETE : 1 << 3
-};
-
-var SortWay = {
-	 ASC   : 1
-	,DESC  : 2 
-};
-
-Model.extend({
-	 Status: Status
-	,Mode: Mode
-	,Operation: Operation
-	,SortWay: SortWay
-});
-
-Model.implement({
-	Extends: Vn.Object
-	,Tag: 'db-model'
-	,Properties: {
-		/**
-		 * The connection used to execute the statement.
-		 */
-		conn: {
-			type: Connection
-			,set(x) {
-				this._conn = x;
-				this._autoLoad();
-			}
-			,get() {
-				return this._conn;
-			}
-		},
-		/**
-		 * The result index.
-		 */
-		resultIndex: {
-			type: Number
-			,set(x) {
-				this._resultIndex = x;
-			}
-			,get() {
-				return this._resultIndex;
-			}
-		},
-		/**
-		 * The lot used to execute the statement.
-		 */
-		lot: {
-			type: Vn.LotIface
-			,set(x) {
-				this.link({_lot: x}, {'change': this._onLotChange});
-				this._onLotChange();
-			}
-			,get() {
-				return this._lot;
-			}
-		},
-		/**
-		 * The model select statement.
-		 */
-		stmt: {
-			type: Sql.Stmt
-			,set(x) {
-				this._stmt = x;
-				this._autoLoad();
-			}
-			,get() {
-				return this._stmt;
-			}
-		},
-		/**
-		 * The model query.
-		 */
-		query: {
-			type: String
-			,set(x) {
-				this.stmt = new Sql.String({query: x});
-			}
-			,get() {
-				if (this._stmt)
-					return this._stmt.render(null);
-				else
-					return null;
-			}
-		},
-		/**
-		 * The main table.
-		 */
-		mainTable: {
-			type: String
-			,set(x) {
-				this._mainTable = null;
-				this._requestedMainTable = x;
-				this._refreshMainTable();
-			}
-			,get() {
-				return this._mainTable;
-			}
-		},
-		/**
-		 * Determines if the model is updatable.
-		 */
-		updatable: {
-			type: Boolean
-			,set(x) {
-				this._updatable = false;
-				this._requestedUpdatable = x;
-				this._refreshUpdatable();
-			}
-			,get() {
-				return this._updatable;
-			}
-		},
-		/**
-		 * The number of rows in the model.
-		 */
-		numRows: {
-			type: Number
-			,get() {
-				if (this.data)
-					return this.data.length;
-	
-				return 0;
-			}
-		},
-		/**
-		 * The current status of the model.
-		 */
-		status: {
-			type: Number
-			,get() {
-				return this._status;
-			}
-		},
-		/**
-		 * Checks if the model data is ready.
-		 */
-		ready: {
-			type: Boolean
-			,get() {
-				return this._status == Status.READY;
-			}
-		},
-		/**
-		 * Update mode.
-		 */
-		mode: {
-			enumType: Mode
-			,value: Mode.ON_CHANGE
-		},
-		/**
-		 * Wether to execute the model query automatically.
-		 */
-		autoLoad: {
-			type: Boolean
-			,value: true
-		}
-	}
-
-	,_conn: null
-	,_resultIndex: 0
-	,_lot: null
-	,_stmt: null
-	,_status: Status.CLEAN
-	,data: null
-	,tables: null
-	,columns: null
-	,columnMap: null
-	,_updatable: false
-	,_paramsChanged: true
-
-	,_requestedSortIndex: -1
-	,_requestedSortName: null
-	,_sortColumn: null
-	,_sortWay: null
-
-	,_requestedIndexes: {}
-	,_indexes: []	
-
-	,_requestedUpdatable: false
-	,_operations: null
-	,_operationsMap: null
-	,_defaults: []
-	,_requestedMainTable: null
-
-	,initialize(props) {
-		Vn.Object.prototype.initialize.call(this, props);
-		this._cleanData();
-		this._setStatus(Status.CLEAN);
-	}
-
-	,appendChild(child) {
-		if (child.nodeType === Node.TEXT_NODE)
-			this.query = child.textContent;
-	}
-
-	,loadXml(builder, node) {
-		Vn.Object.prototype.loadXml.call(this, builder, node);
-
-		var query = node.firstChild.nodeValue;
-		
-		if (query)
-			this.query = query;
-	}
-
-	,_getHolders(stmt) {
-		if (!stmt) return null;
-		let holders = this._stmt.findHolders();
-		if (!holders) return null;
-
-		if (this._lot) {
-			const params = this._lot.params;
-			for (const holder of holders)
-			if (params[holder] instanceof Sql.Object) {
-				const paramHolders = params[holder].findHolders();
-				if (paramHolders)
-					holders = holders.concat(paramHolders);
-			}
-		}
-
-		return holders;
-	}
-
-	,_getHolderValues() {
-		let holders = this._getHolders(this._stmt);
-		if (!holders) return null;
-
-		const lotParams = this._lot ? this._lot.params : {};
-		const params = {};
-		for (const holder of holders)
-		if (!(lotParams[holder] instanceof Sql.Object))
-			params[holder] = lotParams[holder];
-
-		return params;
-	}
-
-	,_getHolderParams() {
-		let holders = this._getHolders(this._stmt);
-		if (!holders) return null;
-
-		const lotParams = this._lot ? this._lot.params : {};
-		const params = {};
-		for (const holder of holders)
-			params[holder] = lotParams[holder];
-
-		return params;
-	}
-
-	,_onLotChange() {
-		const params = this._getHolderValues();
-		this._paramsChanged = !Vn.Value.equals(params, this._lastParams);
-
-		if (this.autoLoad)
-			this.lazyRefresh();
-	}
-
-	,_autoLoad() {
-		if (this.autoLoad)
-			this.refresh();
-		else
-			this.clean();
-	}
-
-	,_isReady(params) {
-		if (!this._stmt || !this._conn)
-			return false;
-
-		for (const param in params)
-			if (params[param] === undefined)
-				return false;
-
-		return true;
-	}
-
-	,async lazyRefresh() {
-		if (this._paramsChanged)
-			await this.refresh();
-	}
-
-	,clean() {
-		this._cleanData();
-		this._setStatus(Status.CLEAN);
-	}
-
-	/**
-	 * Refresh the model data reexecuting the query on the database.
-	 */
-	,async refresh() {
-		const params = this._getHolderParams();
-
-		if (!this._isReady(params)) {
-			this.clean();
-			return;
-		}
-		this._setStatus(Status.LOADING);
-		this._lastParams = this._getHolderValues();
-		this._paramsChanged = false;
-
-		let result;
-		let dataResult;
-		
-		this._cleanData();
-
-		try {
-			const resultSet = await this._conn.execStmt(this._stmt, params);
-
-			for (let i = 0; result = resultSet.fetchResult(); i++)
-			if (i == this._resultIndex)
-				dataResult = result;
-
-			if (!dataResult || typeof dataResult !== 'object')
-				throw new Error('The provided statement doesn\'t return a result set');
-		} catch (e) {
-			this._setStatus(Status.ERROR);
-			throw e;
-		}
-
-		this.data = dataResult.data;
-		this.tables = dataResult.tables;
-		this.columns = dataResult.columns;
-		this.columnMap = dataResult.columnMap;
-		this._repairColumns();
-		this._refreshRowIndexes(0);
-		this._refreshMainTable();
-
-		for (column in this._requestedIndexes)
-			this._buildIndex(column);
-
-		let sortColumn = null;
-
-		if (this._requestedSortName)
-			sortColumn = this._requestedSortName;
-		else if (this._requestedSortIndex !== -1
-		&& this.checkColExists(this._requestedSortIndex))
-			sortColumn = this.getColumnName(this._requestedSortIndex);
-
-		if (sortColumn !== null)
-			this._realSort(sortColumn, this._sortWay);
-	
-		this._setStatus(Status.READY);
-	}
-	
-	,_refreshRowIndexes(start) {
-		for (var i = start; i < this.data.length; i++)
-			this.data[i].index = i;
-		
-		if (this._operationsMap) {
-			this._operationsMap = {};
-			
-			for (var i = 0; i < this._operations.length; i++)
-				this._operationsMap[i] = this._operations[i];
-		}
-	}
-
-	,_cleanData() {
-		this.data = null;
-		this.tables = null;
-		this.columns = null;
-		this.columnMap = null;
-		this._sortColumn = null;
-		this._indexes = [];
-		this._resetOperations();
-	}
-	
-	,_refreshUpdatable() {
-		var oldValue = this._updatable;
-		this._updatable = this._mainTable !== null && this._requestedUpdatable;
-		
-		if (oldValue != this._updatable)
-			this.emit('updatable-changed');
-	}
-	
-	,_refreshMainTable() {
-		var newMainTable = null;
-		var tables = this.tables;
-
-		if (tables)
-		for (var i = 0; i < tables.length; i++)
-		if (tables[i].pks.length > 0)
-		if (!this._requestedMainTable
-		|| tables[i].name === this._requestedMainTable) {
-			newMainTable = i;
-			break;
-		}
-
-		this._mainTable = newMainTable;
-		this._refreshUpdatable();
-	}
-
-	/**
-	 * Sets the default value for inserted fields.
-	 *
-	 * @param {String} field The destination field name
-	 * @param {String} table The destination table name
-	 * @param {Sql.Expr} srcColumn The default value expression
-	 */
-	,setDefault(field, table, expr) {
-		this._defaults.push({field, table, expr});
-	}
-
-	/**
-	 * Sets the default value for inserted fields.
-	 *
-	 * @param {String} field The destination field name
-	 * @param {String} table The destination table name
-	 * @param {Object} value The default value
-	 */
-	,setDefaultFromValue(field, table, value) {
-		this._defaults.push({field, table, value});
-	}
-
-	/**
-	 * Sets the default value for inserted fields from another column in the
-	 * model.
-	 *
-	 * @param {String} field The destination field name
-	 * @param {String} table The destination table name
-	 * @param {String} srcColumn The source column
-	 */
-	,setDefaultFromColumn(field, table, srcColumn) {
-		this._defaults.push({field, table, srcColumn});
-	}
-
-	/**
-	 * Checks if column index exists.
-	 *
-	 * @param {integer} column The column index
-	 * @return {Boolean} %true if column exists, %false otherwise
-	 */
-	,checkColExists(column) {
-		return this.columns
-			&& column >= 0
-			&& column < this.columns.length;
-	}
-
-	/**
-	 * Checks if column name exists.
-	 *
-	 * @param {string} columnName The column name
-	 * @return {Boolean} %true if column exists, %false otherwise
-	 */
-	,checkColName(columnName) {
-		return this.columnMap
-			&& this.columnMap[columnName] != null;
-	}
-
-	/**
-	 * Checks if the row exists.
-	 *
-	 * @param {integer} rowIndex The row index
-	 * @return {Boolean} %true if row exists, %false otherwise
-	 */
-	,checkRowExists(rowIndex) {
-		return this.data
-			&& rowIndex >= 0
-			&& rowIndex < this.data.length;
-	}
-	
-	,_checkTableUpdatable(tableIndex) {
-		var tableUpdatable = tableIndex !== null
-			&& this.tables[tableIndex].pks.length > 0;
-
-		if (!tableUpdatable && !tableIndex) {
-			if (tableIndex)
-				console.warn("Db.Model: Table %s is not updatable",
-					this.tables[tableIndex].name);
-			else
-				console.warn("Db.Model: Model not updatable");
-		}
-				
-		return tableUpdatable;
-	}
-
-	/**
-	 * Get the index of the column from its name.
-	 *
-	 * @param {string} columnName The column name
-	 * @return {number} The column index or -1 if column not exists
-	 */
-	,getColumnIndex(columnName) {
-		if (this.checkColName(columnName))
-			return this.columnMap[columnName].index;
-
-		return -1;
-	}
-
-	/**
-	 * Get the index of the column from its name.
-	 *
-	 * @param {number} columnIndex The column name
-	 * @return {string} The column index or -1 if column not exists
-	 */
-	,getColumnName(columnIndex) {
-		if (this.checkColExists(columnIndex))
-			return this.columns[columnIndex].name;
-
-		return null;
-	}
-
-	/**
-	 * Gets the row as object.
-	 *
-	 * @param {number} rowIndex The row index
-	 * @return {Object} The row
-	 */
-	,getObject(rowIndex) {
-		if (!this.checkRowExists(rowIndex))
-			return undefined;
-
-		return this.data[rowIndex];
-	}
-	
-	/**
-	 * Gets a value from the model.
-	 *
-	 * @param {number} rowIndex The row index
-	 * @param {string} columnName The column name
-	 * @return {mixed} The value
-	 */
-	,get(rowIndex, columnName) {
-		if (this.checkRowExists(rowIndex))
-			return this.data[rowIndex][columnName];
-	}
-
-	/**
-	 * Updates a value on the model.
-	 *
-	 * @param {number} rowIndex The row index
-	 * @param {string} columnName The column name
-	 * @param {mixed} value The new value
-	 */
-	,async set(rowIndex, columnName, value) {
-		if (!this.checkRowExists(rowIndex)
-		&& !this.checkColName(columnName))
-			return;
-
-		var tableIndex = this.columnMap[columnName].table;
-			
-		if (!this._checkTableUpdatable(tableIndex))
-			return;
-
-		var row = this.data[rowIndex];
-
-		var op = this._createOperation(rowIndex);
-		op.type |= Operation.UPDATE;
-
-		if (!op.oldValues)
-			op.oldValues = [];
-		if (!op.tables)
-			op.tables = {};
-			
-		var tableOp = op.tables[tableIndex];
-		
-		if (!tableOp) {
-			tableOp = Operation.UPDATE;
-			var pks = this.tables[tableIndex].pks;
-			
-			for (const pk of pks)
-			if (!row[pk] && !op.oldValues[pk]) {
-				tableOp = Operation.INSERT;
-				break;
-			}
-
-			op.tables[tableIndex] = tableOp;
-		}
-		
-		if (tableOp & Operation.UPDATE
-		&& op.oldValues[columnName] === undefined)
-			op.oldValues[columnName] = row[columnName];
-
-		this.emit('row-updated-before', rowIndex);
-		row[columnName] = value;
-		this.emit('row-updated', rowIndex, [columnName]);
-
-		if (this.mode == Mode.ON_CHANGE
-		&& !(op.type & Operation.INSERT))
-			await this.performOperations();
-	}
-
-	/**
-	 * Gets a value from the model using the column index.
-	 *
-	 * @param {number} rowIndex The row index
-	 * @param {number} columnIndex The column index
-	 * @return {mixed} The value
-	 */
-	,getByIndex(rowIndex, columnIndex) {
-		var columnName = this.getColumnName(columnIndex);
-	
-		if (columnName)
-			return this.get(rowIndex, columnName);
-
-		return undefined;
-	}
-
-	/**
-	 * Updates a value on the model using the column index.
-	 *
-	 * @param {number} rowIndex The row index
-	 * @param {number} columnIndex The column index
-	 * @param {mixed} value The new value
-	 */
-	,async setByIndex(rowIndex, columnIndex, value) {
-		var columnName = this.getColumnName(columnIndex);
-		
-		if (columnName)
-			await this.set(rowIndex, columnName, value);
-		else
-			console.warn('Db.Model: Column %d doesn\'t exist', columnIndex);
-	}
-
-	/**
-	 * Deletes a row from the model. 
-	 *
-	 * @param {number} rowIndex The row index
-	 */
-	,async deleteRow(rowIndex) {
-		if (!this.checkRowExists(rowIndex)
-		|| !this._checkTableUpdatable(this._mainTable))
-			return;
-	
-		var op = this._createOperation(rowIndex);
-		op.type |= Operation.DELETE;
-
-		if (!this._requestedMainTable) {
-			this.emit('row-deleted-before', rowIndex);
-			this.data.splice(rowIndex, 1);
-			this.emit('row-deleted', rowIndex);
-			this._refreshRowIndexes(rowIndex);
-		} else {
-			this.emit('row-updated-before', rowIndex);
-
-			if (!op.oldValues)
-				op.oldValues = [];
-
-			var updatedCols = [];
-
-			for (var i = 0; i < this.columns.length; i++)
-			if (this.columns[i].table == this._mainTable) {
-				const colName = this.columns[i].name;
-
-				if (op.oldValues[colName] === undefined)
-					op.oldValues[colName] = op.row[colName];
-
-				op.row[colName] = null;
-				updatedCols.push(i);
-			}
-
-			this.emit('row-updated', rowIndex, updatedCols);
-		}
-		
-		if (this.mode === Mode.ON_CHANGE)
-			await this.performOperations();
-	}
-
-	/**
-	 * Inserts a new row on the model.
-	 *
-	 * @return The index of the inserted row
-	 */
-	,insertRow() {
-		if (!this._checkTableUpdatable(this._mainTable))
-			return -1;
-
-		var cols = this.columns;
-		var newRow = {};
-		
-		for (var i = 0; i < cols.length; i++)
-		if (cols[i].table === this._mainTable)
-			newRow[cols[i].name] = cols[i].def;
-		else
-			newRow[cols[i].name] = null;
-			
-		var rowIndex = this.data.push(newRow) - 1;
-		newRow.index = rowIndex;
-			
-		var op = this._createOperation(rowIndex);
-		op.type |= Operation.INSERT;
-
-		this.emit('row-inserted', rowIndex);
-	
-		return rowIndex;
-	}
-	
-	/**
-	 * Performs all model changes on the database.
-	 */
-	,async performOperations() {
-		const ops = this._operations;
-	
-		if (ops.length === 0) {
-			this.emit('operations-done');
-			return;
-		}
-		
-		const stmts = new Sql.MultiStmt();
-		
-		let query = new Sql.String({query: 'START TRANSACTION'});
-		stmts.push(query);
-
-		for (let i = 0; i < ops.length; i++) {
-			query = null;
-			let op = ops[i];
-
-			if (op.type & Operation.DELETE) {
-				if (op.type & Operation.INSERT)
-					continue;
-		
-				const where = this._createWhere(this._mainTable, op, true);
-
-				if (where) {
-					query = new Sql.Delete({where});
-					query.addTarget(this._createTarget(this._mainTable));
-				}
-			} else if (op.type & (Operation.INSERT | Operation.UPDATE)) {
-				query = new Sql.MultiStmt();
-
-				for (const tableIndex in op.tables) {
-					const stmt = this._createDmlQuery(op, parseInt(tableIndex));
-					query.push(stmt);
-				}
-			}
-
-			if (query) {
-				stmts.push(query);
-			} else {
-				console.warn('Db.Model: %s', _('ErrorSavingChanges'));
-				return;
-			}
-		}
-
-		query = new Sql.String({query: 'COMMIT'});
-		stmts.push(query);
-	
-		const resultSet = await this._conn.execStmt(stmts);	
-		const error = resultSet.getError();
-	
-		if (error) {
-			this._operations = this._operations.concat(ops);
-			
-			for (let i = 0; i < ops.length; i++)
-				this._operationsMap[ops[i].row.index] = ops[i];
-		
-			throw error;
-		}
-
-		resultSet.fetchResult();
-		let isOperation = false;
-	
-		for (let i = 0; i < ops.length; i++) {
-			const op = ops[i];
-			const row = op.row;
-			
-			if (!(op.type & Operation.DELETE
-			&& op.type & Operation.INSERT))
-				// eslint-disable-next-line no-unused-vars
-				isOperation = true;
-		
-			if (op.type & Operation.DELETE) {
-				resultSet.fetchResult();
-			} else if (op.type & (Operation.INSERT | Operation.UPDATE)) {
-				this.emit('row-updated-before', row.index);
-
-				const updatedCols = [];
-				const cols = this.columns;
-		
-				for (let tableIndex in op.tables) {	
-					let j = 0;
-					tableIndex = parseInt(tableIndex);
-
-					resultSet.fetchResult();
-					const newValues = resultSet.fetchRow();		
-
-					if (op.tables[tableIndex] & Operation.INSERT) {
-						for (let i = 0; i < cols.length; i++)
-						if (cols[i].table === tableIndex) {
-							row[cols[i].name] = newValues[j++];
-							updatedCols.push(i);
-						}
-					} else {
-						for (let i = 0; i < cols.length; i++)
-						if (cols[i].table === tableIndex
-						&& op.oldValues[i] !== undefined) {
-							row[cols[i].name] = newValues[j++];
-							updatedCols.push(i);
-						}
-					}
-				}
-
-				this.emit('row-updated', row.index, updatedCols);
-			}
-		}
-		
-		resultSet.fetchResult();
-			
-//		if (isOperation)
-			this.emit('operations-done');
-
-		this._resetOperations();
-	}
-
-	,_createDmlQuery(op, tableIndex) {
-		var where = this._createWhere(tableIndex, op, false);
-
-		if (!where)
-			return null;
-
-		var multiStmt = new Sql.MultiStmt();
-		var target = this._createTarget(tableIndex);
-		
-		var select = new Sql.Select({where});
-		select.addTarget(target);
-
-		var row = op.row;
-		var cols = this.columns;
-
-		if (op.tables[tableIndex] & Operation.INSERT) {
-			var dmlQuery = new Sql.Insert();
-			var table = this.tables[tableIndex];
-
-			for (const def of this._defaults)
-			if (def.table === table.name) {
-				if (def.value)
-					dmlQuery.addSet(def.field, def.value);
-				else if (def.expr)
-					dmlQuery.addExpr(def.field, def.expr);
-				else if (def.srcColumn)
-					dmlQuery.addSet(def.field, row[def.srcColumn]);
-			}
-
-			for (const col of cols)
-			if (col.table === tableIndex) {
-				if (row[col.name] !== null)
-					dmlQuery.addSet(col.orgname, row[col.name]);
-				select.addField(col.orgname);
-			}
-		} else {
-			var updateWhere = this._createWhere(tableIndex, op, true);
-			
-			if (!updateWhere)
-				return null;
-		
-			var dmlQuery = new Sql.Update({where: updateWhere});
-		
-			for (const col of cols)
-			if (col.table === tableIndex && op.oldValues[col.name] !== undefined) {
-				var fieldName = col.orgname;
-				dmlQuery.addSet(fieldName, row[col.name]);
-				select.addField(fieldName);
-			}
-		}
-
-		dmlQuery.addTarget(target);
-
-		multiStmt.push(dmlQuery);
-		multiStmt.push(select);
-		return multiStmt;
-	}
-	
-	/**
-	 * Undoes all unsaved changes made to the model.
-	 */
-	,reverseOperations() {
-		for (var i = 0; i < this._operations.length; i++) {
-			var op = this._operations[i];
-			var row = op.row;
-
-			if (op.type & Operation.DELETE
-			&& !(op.type & Operation.INSERT)) {
-				this.data.splice(row.index, 0, row);
-				this.emit('row-inserted', row.index);
-			} else if (op.type & Operation.UPDATE) {
-				this.emit('row-updated-before', row.index);
-
-				var updatedCols = [];
-				var cols = this.columns;
-
-				for (var i = 0; i < cols.length; i++)
-				if (op.oldValues[i] !== undefined) {
-					const colName = cols[i].name;
-					row[colName] = op.oldValues[colName];
-					updatedCols.push(i);
-				}
-
-				this.emit('row-updated', row.index, updatedCols);
-			}
-		}
-
-		this._resetOperations();
-		this._refreshRowIndexes(0);
-	}
-	
-	,_resetOperations() {
-		this._operations = [];
-		this._operationsMap = {};
-	}
-	
-	/*
-	 * Function used to sort the model ascending.
-	 */
-	,sortFunctionAsc(column, a, b) {
-		if (a[column] < b[column])
-			return -1;
-		else if (a[column] > b[column])
-			return 1;
-			
-		return 0;
-	}
-	
-	/*
-	 * Function used to sort the model descending.
-	 */
-	,sortFunctionDesc(column, a, b) {
-		if (a[column] > b[column])
-			return -1;
-		else if (a[column] < b[column])
-			return 1;
-			
-		return 0;
-	}
-	
-	/**
-	 * Orders the model by the specified column name.
-	 *
-	 * @param {integer} columnName The column name
-	 * @param {SortWay} way The sort way
-	 */
-	,sortByName(columnName, way) {
-		this._requestedSortIndex = -1;
-		this._requestedSortName = columnName;
-
-		if (this.checkColName(columnName))
-			this._sort(columnName, way);
-	}
-
-	/**
-	 * Orders the model by the specified column.
-	 *
-	 * @param {integer} column The column index
-	 * @param {SortWay} way The sort way
-	 */
-	,sort(column, way) {
-		this._requestedSortIndex = column;
-		this._requestedSortName = null;
-
-		const columnName = this.getColumnName(column);
-		if (columnName) return;
-
-		this._sort(columnName, way);
-	}
-	 
-	,_sort(column, way) {
-		this._setStatus(Status.LOADING);
-		this._realSort(column, way);
-		this._setStatus(Status.READY);
-	}
-	
-	,_realSort(column, way) {
-		if (column !== this._sortColumn) {
-			if (way === SortWay.DESC)
-				var sortFunction = this.sortFunctionDesc;
-			else
-				var sortFunction = this.sortFunctionAsc;
-	
-			this.data.sort(sortFunction.bind(this, column));
-		} else if (way !== this._sortWay)
-			this.data.reverse();
-
-		this._sortColumn = column;
-		this._sortWay = way;
-
-		this._refreshRowIndexes(0);
-	}
-
-	/**
-	 * Builds an internal hash index for the specified column, this speeds
-	 * significantly searches on that column, specially when model has a lot of
-	 * rows.
-	 *
-	 * FIXME: Not fully implemented.
-	 *
-	 * @param {String} column The column name
-	 */
-	,indexColumn(column) {
-		this._requestedIndexes[column] = true;
-
-		if (this._status === Status.READY)
-			this._buildIndex(column);
-	}
-
-	,_buildIndex(columnName) {
-		if (this.checkColName(columnName)) {
-			var index = {};
-			var data = this.data;
-
-			switch (this.columns[columnName].type) {
-				case Connection.Type.TIMESTAMP:
-				case Connection.Type.DATE_TIME:
-				case Connection.Type.DATE:
-					for (var i = 0; i < data.length; i++)
-						index[data[i][columnName].toString()] = i;
-					break;
-				default:
-					for (var i = 0; i < data.length; i++)
-						index[data[i][columnName]] = i;
-			}
-
-			this._indexes[columnName] = index;
-		}
-	}
-
-	/**
-	 * Searchs a value on the model and returns the row index of the first
-	 * ocurrence.
-	 * If an index have been built on that column, it will be used, for more
-	 * information see the indexColumn() method.
-	 *
-	 * @param {String} columnName The column name
-	 * @param {Object} value The value to search
-	 * @return {integer} The column index
-	 */
-	,search(columnName, value) {
-		if (!this.checkColName(columnName))
-			return -1;
-		
-		if (value)
-		switch (this.columnMap[columnName].type) {
-			case Connection.Type.BOOLEAN:
-				value = !!value;
-				break;
-			case Connection.Type.INTEGER:
-				value = parseInt(value);
-				break;
-			case Connection.Type.DOUBLE:
-				value = parseFloat(value);
-				break;
-			default:
-				value = value.toString();
-		}
-
-		let rowIndex = -1;
-		const index = this._indexes[columnName];
-		
-		if (index) {
-			// Searchs the value using an internal index
-
-			if (index[value] !== undefined)
-				rowIndex = index[value];
-		} else {
-			// Searchs the value using a loop
-
-			var data = this.data;
-		
-			switch (this.columnMap[columnName].type) {
-			case Connection.Type.TIMESTAMP:
-			case Connection.Type.DATE_TIME:
-			case Connection.Type.DATE:
-				for (var i = 0; i < data.length; i++)
-				if (value === data[i][columnName].toString()) {
-					rowIndex = i;
-					break;
-				}
-				break;
-			default:
-				for (var i = 0; i < data.length; i++)
-				if (value === data[i][columnName]) {
-					rowIndex = i;
-					break;
-				}
-			}
-		}
-
-		return rowIndex;
-	}
-
-	/**
-	 * Searchs a value on the model and returns the row index of the first
-	 * ocurrence.
-	 *
-	 * @param {integer} columnIndex The column index
-	 * @param {Object} value The value to search
-	 * @return {integer} The column index
-	 */
-	,searchByIndex(columnIndex, value) {
-		var columnName = this.getColumnName(columnIndex);
-		return this.search(columnName, value);
-	}
-
-	,_setStatus(status) {
-		this._status = status;
-		this.emit('status-changed', status);
-		this.emit('status-changed-after', status);
-	}
-	
-	,_createTarget(tableIndex) {
-		var table = this.tables[tableIndex];
-
-		return new Sql.Table({
-			 name: table.orgname
-			,schema: table.schema
-		});
-	}
-
-	,_createWhere(tableIndex, op, useOldValues) {
-		const where = new Sql.Operation({type: Sql.Operation.Type.AND});
-		const pks = this.tables[tableIndex].pks;
-		
-		if (pks.length === 0)
-			return null;
-
-		for (const pk of pks) {
-			const column = this.columnMap[pk];
-		
-			const equalOp = new Sql.Operation({type: Sql.Operation.Type.EQUAL});
-			equalOp.push(new Sql.Field({name: column.orgname}));
-			where.push(equalOp);
-
-			let pkValue = null;
-			
-			if (useOldValues && op.oldValues
-			&& op.oldValues[pk] !== undefined)
-				pkValue = op.oldValues[pk];
-			else
-				pkValue = op.row[pk];
-
-			if (pkValue)
-				equalOp.push(new Sql.Value({value: pkValue}));
-			else if (column.flags & Connection.Flag.AI && !useOldValues)
-				equalOp.push(new Sql.Function({name: 'LAST_INSERT_ID'}));
-			else
-				return null;
-		}
-		
-		return where;
-	}
-
-	,_createOperation(rowIndex) {
-		var op = this._operationsMap[rowIndex];
-
-		if (!op) {		
-			op = {
-				type: 0,
-				row: this.data[rowIndex]
-			};
-			this._operations.push(op);
-			this._operationsMap[rowIndex] = op;
-		}
-			
-		return op;
-	}
-
-	/**
-	 * Overrides information about a table and its columns. If a parameter is
-	 * not provided, the original will be preserved. This method should be used
-	 * primarily to avoid the mysql bug that causes this information will not
-	 * be set correctly.
-	 * For more information see the following links:
-	 *  - https://bugs.mysql.com/bug.php?id=44660
-	 *  - https://bugs.mysql.com/bug.php?id=26894
-	 *
-	 * @param {String} table The table alias
-	 * @param {String} orgtable The original table name
-	 * @param {String} schema The original table schema
-	 * @param {Array} pks Array with the names of primary keys
-	 * @param {String} ai The autoincrement column name
-	 */
-	,setInfo(table, orgname, schema, pks, ai) {
-		if (!this.tableInfo)
-			this.tableInfo = {};
-	
-		this.tableInfo[table] = {
-			orgname,
-			schema,
-			pks,
-			ai
-		};
-		
-		this._repairColumns();
-	}
-
-	,_repairColumns() {
-		// Repairs wrong table info
-
-		if (this.tableInfo && this.tables)
-		for (var i = 0; i < this.tables.length; i++) {
-			var table = this.tables[i];
-			var tableInfo = this.tableInfo[table.name];
-		
-			if (!tableInfo)
-				continue;
-
-			table.orgname = tableInfo.orgname;
-			table.schema = tableInfo.schema;
-
-			if (tableInfo.pks) {
-				table.pks = [];
-			
-				for (const pk of tableInfo.pks) {
-					if (this.checkColName(pk))
-						table.pks.push(pk);
-					else
-						console.warn('Db.Model: Can\'t repair primary key: `%s`.`%s`'
-							,tableInfo.orgname
-							,pk
-						);
-				}
-			}
-
-			if (tableInfo.ai) {
-				if (this.checkColName(tableInfo.ai))
-					this.columnMap[tableInfo.ai].flags |= Connection.Flag.AI;
-				else
-					console.warn('Db.Model: Can\'t repair autoincrement column: `%s`.`%s`'
-						,tableInfo.orgname
-						,tableInfo.ai
-					);
-			}
-		}
-	}
-});
-
diff --git a/js/db/query.js b/js/db/query.js
deleted file mode 100644
index 664688cc..00000000
--- a/js/db/query.js
+++ /dev/null
@@ -1,94 +0,0 @@
-
-var Connection = require('./connection');
-
-module.exports = new Class({
-	Extends: Vn.Object
-	,Tag: 'db-query'
-	,Properties: {
-		/**
-		 * The connection used to execute the statement.
-		 */
-		conn: {
-			type: Connection
-			,set(x) {
-				this._conn = x;
-				this.onChange();
-			}
-			,get() {
-				return this._conn;
-			}
-		},
-		/**
-		 * The model query.
-		 */
-		query: {
-			type: String
-			,set(x) {
-				this._stmt = new Sql.String({query: x});
-				this.onChange();
-			}
-			,get() {
-				return this._stmt.render(null);
-			}
-		},
-		/**
-		 * The model select statement.
-		 */
-		stmt: {
-			type: Sql.Stmt
-			,set(x) {
-				this._stmt = x;
-				this.onChange();
-			}
-			,get() {
-				return this._stmt;
-			}
-		},
-		/**
-		 * The lot used to execute the statement.
-		 */
-		lot: {
-			type: Vn.LotIface
-			,set(x) {
-				this.link({_lot: x}, {'change': this.onChange});
-				this.onChange();
-			}
-			,get() {
-				return this._lot;
-			}
-		},
-		/**
-		 * Wether to execute automatically de query que it's ready.
-		 */
-		autoLoad: {
-			type: Boolean,
-			value: false
-		}
-	}
-
-	,appendChild(child) {
-		if (child.nodeType === Node.TEXT_NODE)
-			this.query = child.textContent;
-	}
-
-	,loadXml(builder, node) {
-		Vn.Object.prototype.loadXml.call(this, builder, node);
-
-		var query = node.firstChild.nodeValue;
-		
-		if (query)
-			this.query = query;
-	}
-	
-	,async execute() {
-		const resultSet = await this._conn.execStmt(this._stmt, this._lot);
-		this.emit('ready', resultSet);
-		return resultSet;
-	}
-	
-	,onChange() {
-		if (this.autoLoad && this._conn && this._stmt && this._lot)
-			this.execute();
-	}
-});
-
diff --git a/js/db/result-set.js b/js/db/result-set.js
deleted file mode 100644
index 4144ca2c..00000000
--- a/js/db/result-set.js
+++ /dev/null
@@ -1,130 +0,0 @@
-const Result = require('./result');
-
-/**
- * This class stores the database results.
- */
-module.exports = new Class({
-    results: null,
-    error: null,
-
-    /**
-     * Initilizes the resultset object.
-     */
-    initialize(results, error) {
-        this.results = results;
-        this.error = error;
-    },
-
-    /**
-     * Gets the query error.
-     *
-     * @return {Db.Err} the error or null if no errors hapened
-     */
-    getError() {
-        return this.error;
-    },
-
-    fetch() {
-        if (this.error) {
-            throw this.error;
-        }
-        console.log('this.results', this.results);
-        if (this.results !== null && this.results.length > 0) {
-            return this.results.shift();
-        }
-
-        return null;
-    },
-
-    /**
-     * Fetchs the next result from the resultset.
-     *
-     * @return {Db.Result} the result or %null if error or there are no more results
-     */
-    fetchResult() {
-        const result = this.fetch();
-        console.log('test result', result);
-        if (result !== null) {
-            if (result.data instanceof Array) {
-                return new Result(result);
-            } else {
-                return true;
-            }
-        }
-
-        return null;
-    },
-
-    /**
-     * Fetchs the first row object from the next resultset.
-     *
-     * @return {Array} the row if success, %null otherwise
-     */
-    fetchObject() {
-        const result = this.fetch();
-
-        if (
-            result !== null &&
-            result.data instanceof Array &&
-            result.data.length > 0
-        ) {
-            return result.data[0];
-        }
-
-        return null;
-    },
-
-    /**
-     * Fetchs data from the next resultset.
-     *
-     * @return {Array} the data
-     */
-    fetchData() {
-        const result = this.fetch();
-
-        if (result !== null && result.data instanceof Array) {
-            return result.data;
-        }
-
-        return null;
-    },
-
-    /**
-     * Fetchs the first row and column value from the next resultset.
-     *
-     * @return {Object} the value if success, %null otherwise
-     */
-    fetchValue() {
-        const row = this.fetchRow();
-
-        if (row instanceof Array && row.length > 0) {
-            return row[0];
-        }
-
-        return null;
-    },
-
-    /**
-     * Fetchs the first row from the next resultset.
-     *
-     * @return {Array} the row if success, %null otherwise
-     */
-    fetchRow() {
-        const result = this.fetch();
-
-        if (
-            result !== null &&
-            result.data instanceof Array &&
-            result.data.length > 0
-        ) {
-            const object = result.data[0];
-            const row = new Array(result.columns.length);
-            for (let i = 0; i < row.length; i++) {
-                row[i] = object[result.columns[i].name];
-            }
-            return row;
-        }
-
-        return null;
-    }
-});
diff --git a/js/db/result.js b/js/db/result.js
deleted file mode 100644
index fc4bfb8a..00000000
--- a/js/db/result.js
+++ /dev/null
@@ -1,64 +0,0 @@
-/**
- * This class stores a database result.
- */
-module.exports = new Class({
-	/**
-	 * Initilizes the result object.
-	 */
-	initialize(result) {
-		this.data = result.data;
-		this.tables = result.tables;
-		this.columns = result.columns;
-		this.row = -1;
-		
-		if (this.columns) {
-			this.columnMap = {};
-
-			for (var i = 0; i < this.columns.length; i++) {
-				const col = this.columns[i];
-				col.index = i;
-				this.columnMap[col.name] = col;
-			}
-		} else
-			this.columnMap = null;
-	}
-	
-	/**
-	 * Gets a value from de result.
-	 *
-	 * @param {String} columnName The column name
-	 * @return {Object} The cell value
-	 */
-	,get(columnName) {
-		return this.data[this.row][columnName];
-	}
-
-	/**
-	 * Gets a row.
-	 *
-	 * @return {Object} The cell value
-	 */
-	,getObject() {
-		return this.data[this.row];
-	}
-	
-	/**
-	 * Resets the result iterator.
-	 */
-	,reset() {
-		this.row = -1;
-	}
-	
-	/**
-	 * Moves the internal iterator to the next row.
-	 */
-	,next() {
-		this.row++;
-		
-		if (this.row >= this.data.length)
-			return false;
-			
-		return true;
-	}
-});
-
diff --git a/js/db/simple-iterator.js b/js/db/simple-iterator.js
deleted file mode 100644
index 52bde2bc..00000000
--- a/js/db/simple-iterator.js
+++ /dev/null
@@ -1,71 +0,0 @@
-
-var Iterator = require('./iterator');
-var Model = require('./model');
-
-/**
- * A light iterator for models.
- */
-module.exports = new Class({
-	Extends: Vn.Object
-	,Implements: Iterator
-	,Properties: {
-		/**
-		 * The model associated to this form.
-		 */
-		model: {
-			type: Model
-			,set(x) {
-				this._model = x;
-			}
-			,get() {
-				return this._model;
-			}
-		},
-		/**
-		 * The row where the form positioned, has -1 if the row is unselected.
-		 */
-		row: {
-			type: Number
-			,set(x) {
-				this._row = x;
-			}
-			,get() {
-				return this._row;
-			}
-		},
-		/**
-		 * The number of rows in the form.
-		 */
-		numRows: {
-			type: Number
-			,get() {
-				if (this._model)
-					return this._model.numRows;
-
-				return 0;
-			}
-		},
-		/**
-		 * Checks if the form data is ready.
-		 */
-		ready: {
-			type: Boolean
-			,get() {
-				if (this._model)
-					return this._model.ready;
-					
-				return false;
-			}
-		},
-		/**
-		 * The row object.
-		 */
-		$: {
-			type: Object
-			,get() {
-				return this._model.getObject(this._row);
-			}
-		}
-	}
-});
-
diff --git a/js/hedera/app.js b/js/hedera/app.js
deleted file mode 100644
index 6e7ba1c2..00000000
--- a/js/hedera/app.js
+++ /dev/null
@@ -1,252 +0,0 @@
-const Login = require('./login');
-const Gui = require('./gui');
-
-module.exports = new Class({
-	Extends: Vn.Object,
-	Properties: {
-		conn: {
-			type: Db.Connection
-			,get() {
-				return this._conn;
-			}
-		}
-	}
-
-	,initialize() {
-		window.addEventListener('error',
-			e => this._onWindowError(e));
-		window.addEventListener('unhandledrejection',
-			e => this._onWindowRejection(e));
-		window.addEventListener('unload',
-			() => this._onWindowUnload());
-
-		this._hash = new Vn.Hash({window: window});
-
-		const conn = new Db.Connection();
-		this.link({_conn: conn}, {'error': this._onConnError});
-
-		this.initAutoLogin();
-	}
-	
-	,run() {
-		if (this.tryAutoLogin()) return;
-		this.showLogin();
-	}
-
-	,showLogin() {
-		const login = this._login = new Login({
-			conn: this._conn,
-			hash: this._hash
-		});
-		login.on('login', this._onLogin, this);
-		login.show();
-	}
-	
-	,async _onLogin() {
-		this._freeLogin();
-		if (this._gui) return;
-		
-		const gui = this._gui = new Gui({
-			conn: this._conn,
-			hash: this._hash
-		});
-		gui.on('logout', this._onLogout, this);
-		await gui.show();
-	}
-	
-	,async _onLogout() {
-		this.clearAutoLogin();
-		await this._freeGui();
-		this.loggingOut = false;
-		this.showLogin();
-	}
-	
-	,_onWindowUnload() {
-		this.unref();
-	}
-	
-	,async _logout() {
-		if (this._gui && !this.loggingOut) {
-			this.loggingOut = true;
-			await this._gui.logout();
-		}
-	}
-	
-	,_newVersion() {
-		if (this.ignoreVersion) return;
-		this.ignoreVersion = true;
-
-		const dialog = new Htk.Dialog({
-			 message: _('New version available')
-			,buttons: Htk.Dialog.Button.ACCEPT
-			,icon: 'warning'
-		});
-		dialog.on('response', this._onNewVersionResponse, this);
-		dialog.open();
-	}
-	
-	,_onNewVersionResponse() {
-		location.reload();
-	}
-	
-	,_freeLogin() {
-		if (!this._login) return;
-		this._login.disconnectByInstance(this);
-		this._login.hide();
-		this._login.unref();
-		this._login = null;
-	}
-	
-	,async _freeGui() {
-		if (!this._gui) return;
-		this._gui.disconnectByInstance(this);
-		await this._gui.hide();
-		this._gui.unref();
-		this._gui = null;
-	}
-	
-	,_destroy() {
-		this._freeLogin();
-		this._freeGui();
-		this.deinitAutoLogin();
-		if (this._conn) this._conn.unref();
-		if (this._hash) this._hash.unref();
-	}
-	
-	// Auto login
-	
-	,_firstLogin: true
-
-	,initAutoLogin() {
-		const isGuest = new Vn.Param({
-			lot: this._hash,
-			type: Boolean,
-			name: 'guest'
-		});
-		this.link({_isGuest: isGuest}, {'changed': this._onGuestChange});
-
-		const token = new Vn.Param({
-			lot: this._hash,
-			type: String,
-			name: 'token'
-		});
-		this.link({_token: token}, {'changed': this._onTokenChange});
-	}
-	
-	,_onGuestChange() {
-		if (this._isGuest.value)
-			setTimeout(this.tryAutoLogin.bind(this));
-	}
-	
-	,_onTokenChange() {
-		if (this._token.value)
-			setTimeout(this.tryAutoLogin.bind(this));
-	}
-	
-	,deinitAutoLogin() {
-		if (this._isGuest) this._isGuest.unref();
-		if (this._token) this._token.unref();
-	}
-
-	,autoLogin() {
-		const guest = localStorage.getItem('hederaGuest');
-
-		if (this._isGuest.value || guest) {
-			localStorage.setItem('hederaGuest', true);
-			return true;
-		}
-
-		if (this._token.value)
-			this._conn.token = this._token.value;
-		else
-			this._conn.fetchToken();
-		
-		if (this._conn.token)
-			return true;
-
-		return false;
-	}
-	
-	,tryAutoLogin() {
-		const ok = this.autoLogin();
-
-		this._firstLogin = false;
-		this._isGuest.value = undefined;
-		this._token.value = undefined;
-
-		if (!ok)
-			return false;
-
-		this._onLogin();
-		return true;
-	}
-	
-	,clearAutoLogin() {
-		localStorage.removeItem('hederaGuest');
-	}
-
-	// Error management
-
-	,_onWindowError(event) {
-		this.globalHandler(event.error);
-	}
-	
-	,_onWindowRejection(event) {
-		this.globalHandler(event.reason);
-	}
-
-	,async _onConnError(conn, err) {
-		if (!(err instanceof Vn.JsonException)) return;
-		switch (err.exception) {
-			case 'UserDisabled':
-				Htk.Toast.showError(_('User disabled'));
-				await this._logout();
-				return;
-			case 'OutdatedVersion':
-				this._newVersion();
-				return;
-		}
-		if (err.statusCode == 401 && !this._login) {
-			Htk.Toast.showError(_('Session expired'));
-			this._logout();
-		}
-	}
-
-	,async globalHandler(err) {
-		try {
-			if (!err) return;
-			if (err instanceof Vn.JsonException) {
-				const statusCode = err.statusCode;
-				if (statusCode >= 400 && statusCode < 500) {
-					if (err.statusCode == 403)
-						Htk.Toast.showError(_('You don\'t have enough privileges'));
-					else {
-						switch (err.exception) {
-							case 'UserDisabled':
-							case 'OutdatedVersion':
-								return;
-						}
-						if (err.statusCode == 401)
-							return;
-						Htk.Toast.showError(err.message);
-					}
-				} else
-					Htk.Toast.showError(err.message);
-			} else {
-				Htk.Toast.showError(_('Something went wrong'));
-				if (this._conn)
-						await this._conn.send('core/log', {
-						file: err.fileName
-						,line: err.lineNumber
-						,message: err.message
-						,stack: err.stack
-						,agent: navigator.userAgent
-						,location: location.href
-					});
-			}
-		} catch(e) {
-			console.error(e);
-		}
-	}
-});
-
diff --git a/js/hedera/basket-checker.js b/js/hedera/basket-checker.js
deleted file mode 100644
index 29a6c841..00000000
--- a/js/hedera/basket-checker.js
+++ /dev/null
@@ -1,21 +0,0 @@
-
-module.exports = {
-	async check(conn, hash) {
-		this.hash = hash;
-		const resultSet = await conn.execQuery('CALL myBasket_check');
-
-		const status = resultSet.fetchValue();
-		if (!status) return;
-
-		const isOk = status == 'UPDATED' || status == 'OK';
-
-		if (status == 'UPDATED')
-			Htk.Toast.showWarning(_('Order items updated'));
-
-		if (!isOk)
-			this.hash.setAll({form: 'ecomerce/checkout'});
-
-		return isOk;
-	}
-};
-
diff --git a/js/hedera/form.js b/js/hedera/form.js
deleted file mode 100644
index 518cb3f9..00000000
--- a/js/hedera/form.js
+++ /dev/null
@@ -1,108 +0,0 @@
-
-module.exports = new Class({
-	Extends: Vn.Object
-	
-	,isOpen: false
-	,uiLoaded: false
-
-	,initialize(gui) {
-		this.gui = gui;
-		this.conn = gui.conn;
-		this.hash = gui.hash;
-	}
-	
-	,async loadUi() {
-		if (!this.isOpen)
-			return;
-
-		const conn = this.conn;
-		const hash = this.hash;
-	
-		const builder = new Vn.Builder();
-		builder.compileString(this.$constructor.Template.default);
-
-		const scope = this.scope = this.builder = builder.load(null, this);
-		this.$ = scope.$;
-		scope.link({conn, hash});
-		this.node = scope.$.form;
-		this.node.$ctrl = this;
-
-		const paramsLot = this.$.params;
-		if (paramsLot) {
-			paramsLot.source = hash;
-			this.params = paramsLot;
-		}
-
-		function setConnection(tagName) {
-			const objects = scope.getByTagName(tagName);
-			for (let i = 0; i < objects.length; i++)
-				objects[i].conn = conn;
-		}
-
-		const tags = ['db-model', 'db-query', 'db-lot'];
-		for (let i = 0; i < tags.length; i++)
-			setConnection(tags[i]);
-			
-		if (this.node) {
-			this.gui.setForm(this.node);
-			this.gui.setTitle(scope.$.title);
-			this.gui.setActions(scope.$.actions);
-			await this.activate();
-		}
-		
-		this.uiLoaded = true;
-	}
-	
-	,async unloadUi() {
-		if (!this.uiLoaded)
-			return;
-
-		if (this.node) {
-			await this.deactivate();
-			this.gui.setTitle(null);
-			this.gui.setActions(null);
-			Vn.Node.remove(this.node);
-			await this.deactivate();
-			this.node = null;
-		}
-		if (this.builder) {
-			this.builder.unref();
-			this.builder = null;
-		}
-	}
-
-	/**
-	 * Called when the form is opened.
-	 */
-	,async open() {
-		await this.close();
-		this.isOpen = true;
-		await this.loadUi();
-	}
-
-	/**
-	 * Called when the form is closed.
-	 */
-	,async close() {
-		if (!this.isOpen) return;
-		this.isOpen = false;
-		await this.unloadUi();
-	}
-	
-	/**
-	 * Called when the form is activated.
-	 */
-	,async activate() {}
-	
-	/**
-	 * Called when the form is deactivated.
-	 */
-	,async deactivate() {}
-
-	,_destroy() {
-		this.close();
-		if (this.scope) this.scope._destroy();
-		Vn.Object.prototype._destroy.call(this);
-	}
-});
-
diff --git a/js/hedera/gui.js b/js/hedera/gui.js
deleted file mode 100644
index 9b724cf4..00000000
--- a/js/hedera/gui.js
+++ /dev/null
@@ -1,497 +0,0 @@
-
-const Module = require('./module');
-const Tpl = require('./gui.xml').default;
-const kebabToCamel = require('vn/string-util').kebabToCamel;
-const routes = require('../../import').routes;
-require('./gui.scss');
-
-module.exports = new Class({
-	Extends: Vn.Component,
-	Properties: {
-		conn: {
-			type: Db.Connection
-			,set(x) {
-				this.link({_conn: x}, {'loading-changed': this._onConnLoadChange });
-			}
-			,get() {
-				return this._conn;
-			}
-		}
-	}
-
-	,forms: {}
-	,activeForm: null
-	,activeCss: null
-	,requestedForm: null
-	,menuShown: false
-	,menuOptions: {}
-	,choosedOption: null
-	,_shown: false
-	,_scrollTimeout: null
-	,_navbarVisible: true
-
-	,initialize(props) {
-		this.loadTemplateFromString(Tpl);
-		this.loadingCount = 0;
-
-		this.$.background.onclick = function() {};
-
-		this.$.leftPanel.addEventListener('click', function(event) {
-			event.stopPropagation();
-		});
-
-		Vn.Component.prototype.initialize.call(this, props);
-	}
-	
-	,async show() {
-		if (this._shown) return;
-		this._shown = true;
-
-		this.doc.body.appendChild(this.node);
-		Htk.Toast.pushTop(this.$.formHolder);
-
-		const resultSet = await this._conn.execQuery(
-			'SELECT id, name, nickname FROM account.myUser;'
-			+'SELECT defaultForm FROM config;'
-			+'SELECT url FROM imageConfig;'
-			+'SELECT dbproduccion FROM vn.config;'
-			+'SELECT productionDomain, testDomain FROM config;'
-		);
-
-		// Retrieving the user name
-
-		this.user = resultSet.fetchObject();
-		Vn.Node.setText(this.$.userName, this.user.nickname);
-
-		// Retrieving configuration parameters
-
-		Vn.Config.defaultForm = resultSet.fetchValue();
-		Vn.Config.imageUrl = resultSet.fetchValue();
-
-		// Retrieving configuration parameters
-
-		const isTesting = !resultSet.fetchValue();
-
-		if (isTesting) {
-			this.$.devInfo.style.display = 'block';
-			this.$.version.textContent = Vn.Cookie.get('vnVersion');
-		}
-
-		// Retrieving configuration parameters
-
-		const res = resultSet.fetchObject();
-
-		if (res && res.testDomain) {
-			let linkText, linkField;
-
-			if (location.host != res.productionDomain) {
-				linkText = 'Old website';
-				linkField = 'productionDomain';
-			} else {
-				linkText = 'Test the new website';
-				linkField = 'testDomain';
-			}
-			
-			Vn.Node.setText(this.$.testLink, _(linkText));
-			this.$.testLink.href = '//'+ res.get(linkField);
-			this.$.testLink.style.display = 'block';
-		} else
-			this.$.testLink.style.display = 'none';
-
-		await this.loadMenu();
-		
-		if (Vn.isMobile()) {
-			this._onScrollHandler = this._onScroll.bind(this);
-			window.addEventListener('scroll', this._onScrollHandler );
-		}
-
-		await this.supplantInit();
-
-		this.formParam = new Vn.Param({
-			lot: this.hash,
-			name: 'form',
-		});
-		this.formParam.on('changed', this._onFormChange, this);
-		await this._onFormChange();
-
-		if (!localStorage.getItem('hederaCookies')) {
-			localStorage.setItem('hederaCookies', true);
-			Htk.Toast.showWarning(_('By using this site you accept cookies'));
-		}
-	}
-	
-	,async hide() {
-		if (!this._shown)
-			return;
-	
-		this._shown = false;
-
-		if (Vn.isMobile())
-			window.removeEventListener('scroll', this._onScrollHandler);
-
-		Htk.Toast.popTop();
-		if (this.formParam) {
-			this.formParam.unref();
-			this.formParam = null;
-		}
-		await this.closeForm();
-		this.hideMenu();
-		Vn.Node.remove(this.node);
-	}
-	
-	,async logout() {
-		await this.onLogoutClick();
-	}
-	
-	,async onLogoutClick() {
-		try {
-			if (!localStorage.getItem('hederaGuest'))
-				this._conn.close();
-		} finally {
-			this.emit('logout');
-		}
-	}
-
-	,_onConnLoadChange(conn, isLoading) {
-		if (isLoading)
-			this.loaderPush();
-		else
-			this.loaderPop();
-	}
-	
-	,async loadMenu() {
-		const resultSet = await this._conn.execQuery('SELECT * FROM myMenu');
-
-		// Retrieving menu sections		
-
-		var res = resultSet.fetchData();	
-		var sectionMap = {};
-		let i = 0;
-
-		for (const row of res) {
-			var parent = row.parentFk;
-			
-			if (!sectionMap[parent])
-				sectionMap[parent] = [];
-				
-			sectionMap[parent].push(i++);
-		}
-
-		Vn.Node.removeChilds(this.$.mainMenu);
-		this.createMenu(res, sectionMap, null, this.$.mainMenu);
-	}
-
-	//++++++++++++++++++++++++++++++++++++++++++++++++++++++ Menu
-
-	,createMenu(res, sectionMap, parent, ul) {
-		var sections = sectionMap[parent];
-		if (!sections) return;
-
-		for (var i = 0; i < sections.length; i++) {
-			res.row = sections[i];
-			const row = res[sections[i]];
-		
-			var li = this.createElement('li');
-			ul.appendChild(li);
-	
-			var text = this.createTextNode(_(row.description));
-
-			var a = this.createElement('a');
-			
-			if (row.path) {
-				a.href = this.hash.make({form: row.path});
-				this.menuOptions[row.path] = a;
-			}
-
-			a.appendChild(text);
-			li.appendChild(a);
-			
-			var formId = row.id;
-			
-			if (sectionMap[formId]) {
-				var submenu = this.createElement('ul');
-				submenu.className = 'submenu';
-				li.appendChild(submenu);
-
-				li.addEventListener('mouseover',
-					this._onLiMouseHover.bind(this, submenu, a));
-				li.addEventListener('mouseout',
-					this._onLiMouseOut.bind(this));
-
-				this.createMenu(res, sectionMap, formId, submenu);
-			}
-		}
-	}
-
-	,_onLiMouseHover(submenu, parent) {
-		if (this.menuShown)
-			return;
-
-		this.hideSubmenu();
-		this.activeSubmenu = submenu;
-
-		var rect = parent.getBoundingClientRect();
-		Vn.Node.addClass(submenu, 'popup');
-		submenu.style.left = rect.right +'px';
-		submenu.style.top = rect.top +'px';
-	}
-	
-	,_onLiMouseOut() {
-		this.timeout = setTimeout(this.hideSubmenu.bind(this), 160);
-	}
-	
-	,hideSubmenu() {
-		var submenu = this.activeSubmenu;
-	
-		if (submenu) {
-			Vn.Node.removeClass(submenu, 'popup');
-			submenu.style.left = '';
-			submenu.style.top = '';
-			clearTimeout(this.timeout);
-			this.activeSubmenu = null;
-			this.timeout = 0;
-		}
-	}
-
-	,onMenuClick(event) {
-		event.stopPropagation();
-		this.showMenu();
-	}
-
-	,showMenu() {
-		this.showBackground();
-		Vn.Node.addClass(this.$.leftPanel, 'show');
-		this.menuShown = true;
-
-		this.hideMenuCallback = this.hideMenu.bind(this);
-		this.doc.addEventListener('click', this.hideMenuCallback);
-	}
-
-	,hideMenu() {
-		if (!this.menuShown)
-			return;
-	
-		this.hideBackground();
-		Vn.Node.removeClass(this.$.leftPanel, 'show');
-		this.menuShown = false;
-		
-		this.doc.removeEventListener('click', this.hideMenuCallback);
-		this.hideMenuCallback = null;
-	}
-
-	//++++++++++++++++++++++++++++++++++++++++++++++++++++++ Navigation bar
-	
-	,_onScroll() {
-		if (this._scrollTimeout === null)
-			this._scrollTimeout = setTimeout(
-				this._scrollTimeoutFunc.bind(this), 150);
-	}
-	
-	,_scrollTimeoutFunc() {
-		if (!this._shown)
-			return;
-		
-		var navbar = this.$.topBar;
-		var yOffset = Vn.Browser.getPageYOffset();
-		var showNavbar = this._lastYOffset > yOffset || yOffset < navbar.offsetHeight;
-		
-		if (showNavbar !== this._navbarVisible) {
-			if (showNavbar)
-				var translateY = 0;
-			else
-				var translateY = -navbar.offsetHeight;
-
-			navbar.style.transform =
-				'translateZ(0) translateY('+ translateY +'px)';
-		}
-		
-		this._navbarVisible = showNavbar;
-		this._lastYOffset = yOffset;
-		this._scrollTimeout = null;
-	}
-
-	//++++++++++++++++++++++++++++++++++++++++++++++++++++++ Background
-
-	,showBackground() {
-		Vn.Node.addClass(this.$.background, 'show');
-	}
-
-	,hideBackground() {
-		Vn.Node.removeClass(this.$.background, 'show');
-	}
-
-	//++++++++++++++++++++++++++++++++++++++++++++++++++++++ Spinner
-	
-	,loaderPush() {
-		this.loadingCount++;
-
-		if (this.loadingCount == 1)
-			this.$.loader.start();
-	}
-	
-	,loaderPop() {
-		if (this.loadingCount == 0)
-			return;
-		
-		this.loadingCount--;
-		
-		if (this.loadingCount == 0)
-			this.$.loader.stop();
-	}
-	
-	//++++++++++++++++++++++++++++++++++++++++++++++++++++++ Forms
-	
-	,async _onFormChange() {
-		var formPath = this.formParam.value;
-		
-		if (!formPath)
-			formPath = Vn.Config.defaultForm;
-		
-		this.hideMenu();
-		await this.closeForm();
-		this.requestedForm = formPath;
-
-		if (!formPath) return;
-		this.loaderPush();
-		const newChoosedOption = this.menuOptions[formPath];
-		
-		if (newChoosedOption) {
-			Vn.Node.addClass(newChoosedOption, 'selected');
-			this.choosedOption = newChoosedOption;
-		}
-
-		await Vn.Locale.load(`forms/${formPath}`);
-
-		let FormKlass;
-		
-		try {
-			FormKlass = (await this.importForm(formPath)).default;
-		} catch (err) {
-			this.loaderPop();
-			console.log(err);
-			return Htk.Toast.showError(_('Error loading form') +`: ${err.message}`);
-		}
-
-		this.loaderPop();
-
-		if (!this._shown)
-			return;
-
-		this.activeForm = new FormKlass(this);
-		await this.activeForm.open();
-	}
-
-	,async importForm(path) {
-		const states = path.split('/');
-		let importFn = routes;
-		for (let i = 0; i < states.length && importFn; i++)
-			importFn = importFn[kebabToCamel(states[i])];
-		if (!importFn)
-			throw new Error(`Route '${path}' does not exist`);
-		return importFn();
-	}
-	
-	,setForm(form) {
-		const holder = this.$.formHolder;
-		Vn.Node.removeChilds(holder);
-
-		if (form) {
-			holder.appendChild(form);
-			holder.classList.add('move-start');
-			setTimeout(() => this._onSetFormTimeout(), 10);
-		}
-	}
-	
-	,_onSetFormTimeout() {
-		const holder = this.$.formHolder;
-		holder.classList.remove('move-start');
-		holder.classList.add('move-end');
-		holder.addEventListener('transitionend',
-			() => holder.classList.remove('move-end'),
-			{once: true}
-		);
-	}
-	
-	,setTitle(title) {
-		Vn.Node.removeChilds(this.$.title);
-	
-		if (title)
-			this.$.title.appendChild(title);
-	}
-	
-	,setActions(actions) {
-		Vn.Node.removeChilds(this.$.actionBar);
-				
-		if (actions)
-			this.$.actionBar.appendChild(actions);
-	}
-	
-	,async closeForm() {
-		if (this.activeForm) {
-			Vn.Node.removeClass(this.$.formHolder, 'show');
-			await this.activeForm.close();
-			this.activeForm._destroy();
-			this.activeForm = null;
-		}
-
-		if (this.activeCss) {
-			Vn.excludeCss(this.activeCss);
-			this.activeCss = null;
-		}
-
-		if (this.choosedOption) {
-			Vn.Node.removeClass(this.choosedOption, 'selected');
-			this.choosedOption = null;
-		}
-	}
-	
-	//++++++++++++++++++++++++++++++++++++++++++++++++++++++ Reports
-	
-	,async openReport(reportName, lot) {
-		try {
-			this.loaderPush();
-			const module = new Module('reports', reportName);
-			await module.load();
-		
-			const report = new module.klass(module, this);
-			report.open(lot);
-		} catch(err) {
-			Htk.Toast.showError(_('Error loading report'));
-		} finally {
-			this.loaderPop();
-		}
-	}
-	
-	//++++++++++++++++++++++++++++++++++++++++++++++++++++++ Supplant
-	
-	,async supplantInit() {
-		var user = sessionStorage.getItem('supplantUser');
-		if (user == null) return;
-
-		await this._conn.supplantUser(user);
-		sessionStorage.setItem('supplantUser', user);
-		await this.loadMenu();
-	
-		const res = await this._conn.execQuery(
-			'SELECT nickname FROM account.myUser');
-
-		const userName = res.fetchValue();
-		Vn.Node.setText(this.$.supplanted, userName);
-		this.$.supplant.classList.toggle('show', true);
-	}
-
-	,async onSupplantExitClick() {
-		this.$.supplant.classList.toggle('show', false);
-		await this._conn.supplantEnd();
-		sessionStorage.removeItem('supplantUser');
-		await this.loadMenu();
-		this._onFormChange();
-	}
-	
-	//++++++++++++++++++++++++++++++++++++++++++++++++++++++ Destroy
-
-	,_destroy() {
-		this.hide();
-		Vn.Component.prototype.initialize.call(this);
-	}
-});
diff --git a/js/hedera/gui.scss b/js/hedera/gui.scss
deleted file mode 100644
index a65c6956..00000000
--- a/js/hedera/gui.scss
+++ /dev/null
@@ -1,375 +0,0 @@
-
-@import "../htk/style/classes";
-
-
-.vn-gui {
-	height: inherit;
-
-	/* Font */
-
-	.user-name,
-	.menu-title {
-		font-size: 1.1rem;
-	}
-
-	/* Navigation bar */
-
-	.navbar {
-		position: fixed;
-		background-color: #1A1A1A;
-		left: $side-panel-width;
-		top: 0;
-		right: 0;
-		z-index: 1;
-		overflow: hidden;
-		height: $navbar-height;
-		color: white;
-		display: flex;
-		align-items: center;
-
-		transition-property: left, background-color, transform;
-		transition-duration: 200ms;
-		transition-timing-function: ease-in-out;
-
-		& > .menu-button {
-			flex: none;
-			display: none;
-			border: none;
-
-			&:hover {
-				background-color: rgba(255, 255, 255, .1);
-			}
-			& > .htk-icon {
-				display: block;
-			}
-		}
-		& > .title-wraper {
-			display: flex;
-			align-items: center;
-			gap: 12px;
-			overflow: hidden;
-			padding-left: 12px;
-			flex-shrink: 3;
-
-			& > .title {
-				overflow: hidden;
-
-				h1 {
-					font-weight: normal;
-					font-size: 1.4rem;
-					margin: 0;
-					white-space: nowrap;
-					text-overflow: ellipsis;
-					overflow: hidden;
-				}
-			}
-		}
-		& > .action-bar {
-			flex: auto;
-			height: 100%;
-
-			& > div {
-				display: flex;
-				justify-content: flex-end;
-				height: 100%;
-				align-items: center;
-				padding-right: 12px;
-				padding-left: 4px;
-				gap: 2px;
-			}
-			button {
-				margin: 0;
-				padding: 8px 13px;
-
-				&:hover {
-					background-color: rgba(2550, 255, 255, .2);
-				}
-			}
-		}
-	}
-
-	/* Background */
-
-	& > .background {
-		z-index: 10;
-		position: fixed;
-		top: 0;
-		left: 0;
-		right: 0;
-		bottom: 0;
-		visibility: hidden;
-		background-color: rgba(1, 1, 1, .7);
-		opacity: 0;
-
-		&.show {
-			visibility: visible;
-			transition: opacity 200ms ease-out;
-			opacity: 1;
-		}
-	}
-
-	/* Left panel */
-
-	.menu-overflow {
-		position: absolute;
-		top: 0;
-		left: 0;
-		right: 0;
-		bottom: 4em;
-		overflow: auto;
-	}
-	.menu-header {
-		background-color: #1A1A1A;
-		color: white;
-		height: $navbar-height;
-		display: flex;
-	}
-	.logo {
-		display: block;
-		width: 160px;
-		margin-left: 37px;
-	}
-	.user-info {
-		margin: 25px;
-
-		& > div {
-			display: flex;
-			justify-content: space-between;
-			align-items: center;
-			overflow: hidden;
-			font-weight: bold;
-			border: 1px solid #eaeaea;
-
-			& > span {
-				padding: 10px;
-				overflow: hidden;
-				text-overflow: ellipsis;
-				white-space: nowrap;
-			}
-			.logout {
-				display: block;
-				margin: 0;
-				text-align: left;
-				border-radius: 0;
-
-				&:hover {
-					background-color: #1a1a1a;
-					color: white;
-				}
-				& > .htk-icon {
-					display: block;
-				}
-			}
-			&.supplant {
-				display: none;
-				border-top: none;
-
-				&.show {
-					display: flex;
-				}
-			}
-		}
-	}
-
-	/* Test link */
-
-	.test-link {
-		display: none;
-		margin: .5em;
-		background-color: #3f51b5;
-		color: white;
-		padding: 0 1em;
-		line-height: 2em;
-		border-radius: .1em;
-		text-align: center;
-
-		&:hover {
-			background-color: #4f61c5;
-		}
-	}
-	.dev-info {
-		display: none;
-		padding: .3em .5em;
-		color: white;
-		background-color: #3f51b5;
-		font-size: .9em;
-		margin: .5em;
-		border-radius: .1em;
-
-		& > p {
-			margin: .2em 0;
-		}
-		& > .mode {
-			color: #BBF;
-		}
-	}
-
-	/* Menu */
-
-	.main-menu,
-	ul.submenu {
-		list-style-type: none;
-		padding: 0;
-		margin: 0;
-	}
-	.main-menu > li {
-		display: block;
-		padding: 0;
-		margin: 0;
-		width: 100%;
-	}
-	.main-menu a {
-		width: 70%;
-		padding: 0 15%;
-		display: block;
-		line-height: 2.8em;
-	}
-	.main-menu a:hover,
-	.main-menu a.selected {
-		background-color: rgba(1, 1, 1, .1);
-	}
-	ul.submenu {
-		display: none;
-	}
-	ul.submenu.popup {
-		display: inline;
-		position: fixed;
-		border: none;
-		border-radius: 1px;
-		background-color: white;
-		box-shadow: 0 0 .3em rgba(1, 1, 1, .3);
-		z-index: 50;
-		width: 13em;
-		max-height: 30em;
-	}
-
-	/* Social */
-
-	.menu-footer {
-		position: absolute;
-		bottom: 0;
-		right: 0;
-		left: 0;
-	}
-
-	/* Body */
-
-	& > .body {
-		margin-left: $side-panel-width;
-		padding-top: $navbar-height;
-		height: inherit;
-		box-sizing: border-box;
-		height: inherit;
-
-		transition-property: margin-left, margin-right;
-		transition-duration: 200ms;
-	}
-	.form-holder {
-		position: relative;
-		height: inherit;
-
-		&.move-start {
-			opacity: 0;
-			transform: translate3d(-2em, 0, 0);
-			-webkit-transform: translate3d(-2em, 0, 0);		
-		}
-		&.move-end {
-			opacity: 1;
-			transform: translate3d(0, 0, 0);
-			-webkit-transform: translate3d(0, 0, 0);
-
-			transition-property: opacity, transform;
-			transition-duration: 200ms;
-			transition-timing-function: ease-out;
-		}
-		& > * {
-			padding: $spacing-md;
-		}
-	}
-
-	/* Mobile */
-
-	@include mobile {
-		& > .navbar {
-			padding-left: 12px;
-			left: 0;
-
-			& > .menu-button {
-				display: block;
-			}
-			& > .action-bar {
-				button {
-					padding: 8px;
-				}
-				span.label,
-				button > .text {
-					display: none;
-				}
-			}
-		}
-		& > .body {
-			margin-left: 0;
-		}
-		.form-holder {
-			left: 0;
-		}
-		ul.submenu {
-			display: block;
-			background-color: #888;
-			color: white;
-			box-shadow: inset 0 0 .2em rgba(1, 1, 1, .2);
-			overflow: hidden;
-		
-			max-height: 0;
-			transition: max-height 300ms ease-out;
-			webkit-transition: max-height 300ms ease-out;
-		}
-		.main-menu li:hover > ul.submenu {
-			max-height: 20em;
-		}
-	}
-}
-
-/* Side panel */
-
-.side-panel {
-	z-index: 20;
-	position: fixed;
-	bottom: 0;
-	background-color: white;
-	width: $side-panel-width;
-
-	&.left-panel {
-		left: 0;
-		top: 0;
-	
-		@include mobile {
-			left: -$side-panel-width;
-	
-			&.show {
-				transform: translateZ(0) translateX($side-panel-width);
-				-webkit-transform: translateZ(0) translateX($side-panel-width);
-			}
-		}
-	}
-	&.right-panel {
-		right: 0;
-		top: $navbar-height;
-		overflow: auto;
-	
-		@include mobile {
-			top: 0;
-			right: -$side-panel-width;
-	
-			&.show {
-				transform: translateZ(0) translateX(-$side-panel-width);
-				-webkit-transform: translateZ(0) translateX(-$side-panel-width);
-			}
-		}
-	}
-	@include mobile {
-		transition: transform 200ms ease-out;
-		-webkit-transition: transform 200ms ease-out;
-		box-shadow: 0 0 .2em rgba(1, 1, 1, .3);
-	}
-}
diff --git a/js/hedera/gui.xml b/js/hedera/gui.xml
deleted file mode 100644
index 1381d7a2..00000000
--- a/js/hedera/gui.xml
+++ /dev/null
@@ -1,50 +0,0 @@
-<vn>
-<div id="main" class="vn-gui">
-	<div id="top-bar" class="navbar">
-		<button
-			id="menu-button"
-			class="menu-button"
-			on-click="onMenuClick">
-			<htk-icon name="menu" alt="_Menu"/>
-		</button>
-		<div class="title-wraper">
-			<div id="title" class="title"/>
-			<htk-spinner id="loader" class="loader dark"/>
-		</div>
-		<div id="action-bar" class="action-bar"/>
-	</div>
-	<div id="left-panel" class="left-panel side-panel">
-		<div class="menu-overflow">
-			<div class="menu-header" id="menu-header">
-				<img class="logo" src="image/logo-dark.svg" alt="Verdnatura"/>
-			</div>
-			<div class="user-info">
-				<div>
-					<span id="user-name"/>
-					<button class="logout" on-click="this.onLogoutClick()">
-						<htk-icon name="logout" alt="_Exit"/>
-					</button>
-				</div>
-				<div id="supplant" class="supplant">
-					<span id="supplanted"/>
-					<button class="logout" on-click="this.onSupplantExitClick()">
-						<htk-icon name="logout" alt="_Exit"/>
-					</button>
-				</div>
-			</div>
-			<ul id="main-menu" class="main-menu"/>
-		</div>
-		<div class="menu-footer">
-			<div id="dev-info" class="dev-info">
-				<p class="mode">Testing</p>
-				<p><t>Version</t> <span id="version"/></p>
-			</div>
-			<a id="test-link" class="test-link" href="#">Old website</a>
-		</div>
-	</div>
-	<div class="body">
-		<div id="form-holder" class="form-holder"/>
-	</div>
-	<div id="background" class="background"/>
-</div>
-</vn>
diff --git a/js/hedera/hedera.js b/js/hedera/hedera.js
deleted file mode 100644
index 5389daea..00000000
--- a/js/hedera/hedera.js
+++ /dev/null
@@ -1,15 +0,0 @@
-
-require('htk/htk');
-
-Hedera = module.exports = {
-	 Login         : require('./login')
-	,SocialBar     : require('./social-bar')
-	,Gui           : require('./gui')
-	,Module        : require('./module')
-	,Form          : require('./form')
-	,Report        : require('./report')
-	,App           : require('./app')
-	,Tpv           : require('./tpv')
-	,BasketChecker : require('./basket-checker')
-};
-
diff --git a/js/hedera/locale/ca.yml b/js/hedera/locale/ca.yml
deleted file mode 100644
index fe0589df..00000000
--- a/js/hedera/locale/ca.yml
+++ /dev/null
@@ -1,64 +0,0 @@
-User: Usuari
-Password: Contrasenya
-Beta: Beta
-Remind me: Recorda'm
-Log in as guest: Accedir com a convidat
-Login: Iniciar sessió
-Login mail: info@verdnatura.es
-Login phone: +34 607 562 391
-Password forgotten? Push here: ¿Has oblidat la teva contrasenya?
-Yet you are not a customer?: Encara no ets client?
-Sign up: Registrar-me
-You don't have enough privileges: No tens prou privilegis
-Session expired: La sessió ha expirat
-Invalid login: >-
-  Usuari o contrasenya incorrectes, recorda que s'hi distingeix entre majúscula
-  i minúscula
-User disabled: >-
-  L'autenticació és correcta però el compte d'usuari ha estat desactivada, si 
-  us plau posa't en contacte amb el teu comercial o persona assignada
-Please write your user name: Si us plau introdueix el teu nom d'usuari
-A mail has been sent wich you can recover your password: T'hem enviat un correu on podràs recuperar la teva contrasenya
-Menu: Menú
-Exit: Sortir
-Test the new website: Prova la nova web!
-Old website: Web antiga
-Recent changes: Canvis recents
-Print: Imprimir
-Please unlock popups and try again: 'Si us plau, desbloqueja els popups i torna-ho a intentar'
-Error loading form: Error al carregar formulari
-Error loading report: Error en carregar l'informe
-By using this site you accept cookies: >-
-  En utilitzar aquest lloc web acceptes l'ús de cookies per a la personalització
-  de continguts i anàlisi.
-New version available: >-
-  Hi ha una nova actualització, la pàgina recarregarà automàticament per
-  descarregar-la
-AppName: Verdnatura
-Home: Inici
-Orders: Encàrrecs
-Basket: Cistella
-Last orders: Últims comandes
-Invoices: Factures
-Catalog: Catàleg
-About: Coneix-nos
-About us: Quant a
-Why: Per què?
-Location: Localització
-Administration: Administració
-Control panel: Panell de control
-Users: Usuaris
-Connections: Conexions
-Visits: Visites
-News: Noticies
-Photos: Fotos
-Items: Artícles
-Reports: Informes
-Shelves: Estanterías
-Items list: Llistat articles
-Contact: Vull ser client
-Training: Formació
-Agencies: Agències
-Configuration: Configuració
-Account: Compte
-Addresses: Adreces
diff --git a/js/hedera/locale/en.yml b/js/hedera/locale/en.yml
deleted file mode 100644
index 88d354eb..00000000
--- a/js/hedera/locale/en.yml
+++ /dev/null
@@ -1,60 +0,0 @@
-User: User
-Password: Password
-Beta: Beta
-Remind me: Remind me
-Log in as guest: Log in as guest
-Login: Log in
-Login mail: info@verdnatura.es
-Login phone: +34 607 562 391
-Password forgotten? Push here: Have you forgotten your password?
-Yet you are not a customer?: Not a customer yet?
-Sign up: Register
-You don't have enough privileges: You don't have enough privileges
-Session expired: Your session has expired
-Invalid login: 'Username or password incorrect, remember that it is case-sensitive'
-User disabled: >-
-  Authentication is correct but the user account has been disabled, please 
-  contact your commercial or assigned person
-Please write your user name: Please write your user name
-A mail has been sent wich you can recover your password: A mail has been sent wich you can recover your password
-Menu: Menu
-Exit: Exit
-Test the new website: Test the new website!
-Old website: Old website
-Recent changes: Recent changes
-Print: Print
-Please unlock popups and try again: Please unlock popups and try again
-Error loading form: Error while loading form
-Error loading report: Error loading report
-By using this site you accept cookies: >-
-  By using this website you accept the use of cookies for customization of
-  content and analysis.
-New version available: 'There is a new update, the page will automatically recharge to download it'
-AppName: Verdnatura
-Home: Home
-Orders: Orders
-Basket: Basket
-Last orders: Last orders
-Invoices: Invoices
-Catalog: Catalog
-About: About
-About us: About us
-Why: Why
-Location: Location
-Administration: Administration
-Control panel: Control panel
-Users: Users
-Connections: Connections
-Visits: Visits
-News: News
-Photos: Photos
-Items: Items
-Reports: Reports
-Shelves: Shelves
-Items list: Items list
-Contact: Contact
-Training: Training
-Agencies: Agencies
-Configuration: Configuration
-Account: Account
-Addresses: Addresses
diff --git a/js/hedera/locale/es.yml b/js/hedera/locale/es.yml
deleted file mode 100644
index de2766ed..00000000
--- a/js/hedera/locale/es.yml
+++ /dev/null
@@ -1,64 +0,0 @@
-User: Usuario
-Password: Contraseña
-Beta: Beta
-Remind me: Recuérdame
-Log in as guest: Entrar como invitado
-Login: Iniciar sesión
-Login mail: info@verdnatura.es
-Login phone: +34 963 242 100
-Password forgotten? Push here: ¿Has olvidado tu contraseña?
-Yet you are not a customer?: ¿Todavía no eres cliente?
-Sign up: Registrarme
-You don't have enough privileges: No tienes suficientes privilegios
-Session expired: La sesión ha expirado
-Invalid login: >-
-  Usuario o contraseña incorrectos, recuerda que se hace distinción entre
-  mayúsculas y minúsculas
-User disabled: >-
-  La autenticación es correcta pero la cuenta de usuario ha sido deshabilitada,
-  por favor ponte en contacto con tu comercial o persona asignada
-Please write your user name: Por favor escribe tu nombre de usuario
-A mail has been sent wich you can recover your password: Te hemos enviado un correo donde podrás recuperar tu contraseña
-Menu: Menú
-Exit: Salir
-Test the new website: ¡Prueba la nueva web!
-Old website: Web antigua
-Recent changes: Cambios recientes
-Print: Imprimir
-Please unlock popups and try again: 'Por favor, desbloquea los popups y vuélvelo a intentar'
-Error loading form: Error al cargar formulario
-Error loading report: Error al cargar el informe
-By using this site you accept cookies: >-
-  Al utilizar este sitio web aceptas el uso de cookies para la personalización
-  de contenidos y análisis.
-New version available: >-
-  Hay una nueva actualización, la página se recargará automaticamente para
-  descargarla
-AppName: Verdnatura
-Home: Inicio
-Orders: Pedidos
-Basket: Cesta
-Last orders: Últimos pedidos
-Invoices: Facturas
-Catalog: Catálogo
-About: Conócenos
-About us: Sobre nosotros
-Why: ¿Por qué?
-Location: Localización
-Administration: Administración
-Control panel: Panel de control
-Users: Usuarios
-Connections: Conexiones
-Visits: Visitas
-News: Noticias
-Photos: Fotos
-Items: Artículos
-Reports: Informes
-Shelves: Estanterías
-Items list: Listado artículos
-Contact: Quiero ser cliente
-Training: Formación
-Agencies: Agencias
-Configuration: Configuración
-Account: Cuenta
-Addresses: Direcciones
diff --git a/js/hedera/locale/fr.yml b/js/hedera/locale/fr.yml
deleted file mode 100644
index 4622bfeb..00000000
--- a/js/hedera/locale/fr.yml
+++ /dev/null
@@ -1,64 +0,0 @@
-User: Utilisateur
-Password: Mot de passe
-Beta: Beta
-Remind me: Retenir mon mot de passe
-Log in as guest: Entrez en tant qu'invité
-Login: Se connecter
-Login mail: info@verdnatura.es
-Login phone: +33 781 533 900
-Password forgotten? Push here: Vous avez oublié votre mot de passe?
-Yet you are not a customer?: Vous n'êtes pas encore client?
-Sign up: S'inscrire
-You don't have enough privileges: Vous n'avez pas assez de privilèges
-Session expired: Et votre session a expiré
-Invalid login: >-
-  Utilisateur ou mot de passe incorrect, n'oubliez pas de distinction entre
-  majuscules et minuscules
-User disabled: >-
-  L’authentification est correcte mais le compte utilisateur a été désactivé. 
-  Veuillez contacter votre représentant commercial ou votre correspondant.
-Please write your user name: S'il vous plaît entrer votre nom d'utilisateur
-A mail has been sent wich you can recover your password: Nous avons envoyé un e-mail où vous pouvez récupérer votre mot de passe
-Menu: Menu
-Exit: Laisser
-Test the new website: Testez le nouveau site!
-Old website: Ancien site web
-Recent changes: Modifications récentes
-Print: Imprimir
-Please unlock popups and try again: S'il vous plaît déverrouiller pop ups et essayez à nouveau
-Error loading form: Forme erreur de chargement
-Error loading report: Rapport erreur de chargement
-By using this site you accept cookies: >-
-  En utilisant ce site, vous acceptez l'utilisation de cookies pour
-  personnaliser le contenu et l'analyse.
-New version available: >-
-  Il ya une nouvelle mise à jour, la page sera automatiquement recargargará pour
-  télécharger
-AppName: Verdnatura
-Home: Accueil
-Orders: Commandes
-Basket: Panier
-Last orders: Dernières commandes
-Invoices: Facturas
-Catalog: Catalogue
-About: Nous
-About us: A propos de nous
-Why: Pourquoi?
-Location: Emplacement
-Administration: Administration
-Control panel: Panneau de contrôle
-Users: Utilisateurs
-Connections: Connexions
-Visits: Visites
-News: Nouvelles
-Photos: Photos
-Items: Articles
-Reports: Rapport
-Shelves: Etagères
-Items list: Liste des articles
-Contact: Je veux être client
-Training: Formation
-Agencies: Agences
-Configuration: Configuration
-Account: Compte
-Addresses: Adresses
diff --git a/js/hedera/locale/mn.yml b/js/hedera/locale/mn.yml
deleted file mode 100644
index 80edf0e5..00000000
--- a/js/hedera/locale/mn.yml
+++ /dev/null
@@ -1,55 +0,0 @@
-User: Хэрэглэгчийн
-Password: нууц үг
-Beta: Бета
-Remind me: Гаргаж гарын үсэг зураагүй байна
-Log in as guest: Зочин байдлаар оруулна уу
-Login: энд бичнэ үү
-Login mail: info@verdnatura.es
-Login phone: +34 607 562 391
-Password forgotten? Push here: Нууц үг мартсан? энд түлхэх
-Yet you are not a customer?: Гэсэн хэдий ч та хэрэглэгчийн биш гэж үү?
-Sign up: бүртгүүлэх
-Invalid login: 'Хэрэглэгчийн нэр эсвэл нууц үг буруу, Тэр хэргийг мэдрэмтгий гэдгийг санаарай'
-Please write your user name: Хэрэглэгчийн нэрээ бичнэ үү
-A mail has been sent wich you can recover your password: Мэйл та нууц үгээ сэргээх боломжтой А байна илгээсэн
-Menu: Цэс
-Exit: гарах
-Test the new website: Шинэ вэб шалгана!
-Old website: Хуучин вэб сайт
-Recent changes: Сүүлийн өөрчлөлтүүд
-Print: Хэвлэх
-Please unlock popups and try again: Поп өгсөх түгжээ дахин оролдоно уу
-Error loading form: Алдаа бол ачих хэлбэр
-Error loading report: Алдаа ачих тайлан
-By using this site you accept cookies: >-
-  Энэ вэб сайтыг ашиглан та агуулга, дүн шинжилгээ хийх тохиргоонууд жигнэмэг
-  хэрэглэхийг хүлээн зөвшөөрдөг.
-New version available: 'Шинэ шинэчлэх байна, хуудас автоматаар татаж авах цэнэглэж болно'
-AppName: Verdnatura
-Home: Нүүр хуудас
-Orders: захиалга
-Basket: сагс
-Last orders: Өнгөрсөн захиалга
-Invoices: Нэхэмжлэх
-Catalog: Каталог
-About: тухай
-About us: бидний тухай
-Why: яагаад
-Location: Байрлал
-Administration: захиргаа
-Control panel: хяналтын самбар
-Users: Хэрэглэгчид нь
-Connections: холболт
-Visits: уулзалт
-News: мэдээ
-Photos: Фото зураг
-Items: зүйл
-Reports: мэдээ
-Shelves: тавиур
-Items list: зүйлс жагсаалт
-Contact: Холбоо барих
-Training: сургалт
-Agencies: байгууллагууд
-Configuration: Тохиргоо
-Account: Дансны
-Addresses: хаягууд
diff --git a/js/hedera/locale/pt.yml b/js/hedera/locale/pt.yml
deleted file mode 100644
index d1254b4b..00000000
--- a/js/hedera/locale/pt.yml
+++ /dev/null
@@ -1,62 +0,0 @@
-User: Utilizador
-Password: Palavra-passe
-Beta: Beta
-Remind me: Lembre-me
-Log in as guest: Entrar como convidado
-Login: Iniciar sessão
-Login mail: info@verdnatura.es
-Login phone: +34 963 242 100
-Password forgotten? Push here: Não lembro minha Palavra-passe
-Yet you are not a customer?: Ainda não és cliente?
-Sign up: Registar-me
-You don't have enough privileges: Você não tem privilégios suficientes
-Session expired: 'A sessão foi finalizada'
-Invalid login: >-
-  Usuário ou Palavra-passe incorreto, lembre-se de diferenciar maiusculas e
-  minusculas
-User disabled: >-
-  A autenticação está correta, mas a conta do usuário foi desativada. Entre em 
-  contato com a pessoa comercial ou a quem foi designada.
-Please write your user name: 'Por favor, escreva seu nome de usuário'
-A mail has been sent wich you can recover your password: Um e-mail foi enviado para recuperar sua Palavra-passe
-Menu: Menú
-Exit: Sair
-Test the new website: Prove a nova pagina web
-Old website: Web antiga
-Recent changes: Modificações recentes
-Print: Imprimir
-Please unlock popups and try again: 'Por favor, desbloqueie os pop-ups e volte a tentar'
-Error loading form: Erro ao carregar formulario
-Error loading report: Erro ao carregar o informe
-By using this site you accept cookies: >-
-  Ao utilizar esta pagina web, aceitas o uso de cookies para a personalização de
-  conteúdos e análise.
-New version available: 'Existe uma nova atualização, a página se atualizará automaticamente'
-AppName: VerdNatura
-Home: Principio
-Orders: Encomendas
-Basket: Cesta
-Last orders: Últimas encomendas
-Invoices: Facturas
-Catalog: Catálogo
-About: Conheça-nos
-About us: Sobre nós
-Why: Por quê?
-Location: Localização
-Administration: Administração
-Control panel: Painel de controle
-Users: Usuarios
-Connections: Conexões
-Visits: Visitas
-News: Noticias
-Photos: Fotos
-Items: Artigos
-Reports: Relatórios
-Shelves: Estantes
-Items list: Lista de Itens
-Contact: Quero ser cliente
-Training: Formação
-Agencies: Agências
-Configuration: Configuração
-Account: Conta
-Addresses: Moradas
diff --git a/js/hedera/login.js b/js/hedera/login.js
deleted file mode 100644
index 870518f6..00000000
--- a/js/hedera/login.js
+++ /dev/null
@@ -1,101 +0,0 @@
-var Tpl = require('./login.xml').default;
-require('./login.scss');
-
-module.exports = new Class({
-	Extends: Vn.Component,
-	Properties: {
-		conn: {
-			type: Db.Connection
-			,set(x) {
-				this.link({_conn: x}, {'loading-changed': this._onConnLoadChange});
-			}
-			,get() {
-				return this._conn;
-			}
-		}
-	}
-
-	,initialize(props) {
-		Vn.Component.prototype.initialize.call(this, props);
-		this.loadTemplateFromString(Tpl);
-	
-		//this.$.socialBar.conn = this._conn;
-		
-		var self = this;
-		this.$.form.onsubmit = function() {
-			self._onSubmit();
-			return false;
-		};
-	}
-	
-	,_onConnLoadChange(conn, isLoading) {
-		if (isLoading)
-			this.$.spinner.start();
-		else
-			this.$.spinner.stop();
-	}
-
-	,show() {
-		document.body.appendChild(this.node);
-
-		var lastUser = localStorage.getItem('hederaLastUser');
-
-		if (lastUser)
-			this.$.user.value = lastUser;
-	
-		this._focusUserInput();
-	}
-	
-	,async _onSubmit() {
-		this._disableUi(true);
-		try {
-			await this._conn.open(
-				this.$.user.value,
-				this.$.pass.value,
-				this.$.remember.checked
-			);
-
-			const user = this.$.user.value;
-			if (user) localStorage.setItem('hederaLastUser', user);
-			this.emit('login');
-		} catch (err) {
-			this._focusUserInput();
-			if (err.statusCode == 401)
-				Htk.Toast.showError(_('Invalid login'));
-			else
-				throw err;
-		} finally {
-			this.$.pass.value = '';
-			this._disableUi(false);
-		}
-	}
-	
-	,hide() {
-		Vn.Node.remove(this.node);
-	}
-	
-	,_focusUserInput() {
-		var userEntry = this.$.user;
-		userEntry.focus();
-		userEntry.select();
-	}
-	
-	,_disableUi(disabled) {
-		this.$.user.disabled = disabled;
-		this.$.pass.disabled = disabled;
-		this.$.submit.disabled = disabled;
-	}
-	
-	,async onPasswordLost() {
-		var recoverUser = this.$.user.value;
-	
-		if (!recoverUser) {
-			Htk.Toast.showError(_('Please write your user name'));
-			return;
-		}
-		
-		await this._conn.send('user/recover-password', {recoverUser});
-		Htk.Toast.showMessage(_('A mail has been sent wich you can recover your password'));
-	}
-});
-
diff --git a/js/hedera/login.scss b/js/hedera/login.scss
deleted file mode 100644
index 6281783a..00000000
--- a/js/hedera/login.scss
+++ /dev/null
@@ -1,150 +0,0 @@
-
-.vn-login {
-	display: flex;
-	align-items: center;
-	justify-content: center;
-	color: #333;
-	font-weight: normal;
-	height: inherit;
-	background-color: white;
-
-	a:hover {
-		text-decoration: underline;
-	}
-	input {
-		margin: 4px;
-	}
-	input[type=text],
-	input[type=password] {
-		margin: 0;
-		padding: 0 5px;
-		width: 100%;
-		height: 36px;
-		border-radius: 0;
-		border-top: none;
-		border-left: none;
-		border-right: none;
-		background-color: none;
-	}
-	input[type=checkbox] {
-		padding: 0;
-		margin: 0;
-		width: initial;
-		height: initial;
-		margin-right: 7px;
-	}
-	input[type=submit],
-	input[type=button],
-	input[type=reset],
-	button,
-	.button {
-		margin: 0 auto;
-		background-color: #0d1115;
-		border-radius: 25px;
-		height: 50px;
-		width: 100%;
-		color: white;
-		transition: transform 200ms ease-out;
-		transition-property: background-color;
-
-		&:hover {
-			background-color: #3d3f42;
-		}
-	}
-	@media (max-height: 680px) {
-		height: initial;
-	}
-}
-
-$login-margin-top: 50px;
-$login-margin-between: 55px;
-
-.vn-login > .column {
-	max-width: 250px;
-	overflow: hidden;
-
-	& > .header {
-		margin-top: $login-margin-top;
-		margin-bottom: $login-margin-between;
-		
-		img {
-			display: block;
-			margin: 0 auto;
-			width: 90%;
-		}
-		.version-code {
-			color: red;
-			text-align: right;
-			margin: 3px auto;
-			font-weight: bold;
-			height: 20px;
-			display: none;
-		}
-	}
-	& > .footer {
-		margin-bottom: $login-margin-top;
-		margin-top: $login-margin-between;
-		text-align: center;
-		font-size: .85rem;
-		
-		.contact {
-			margin-top: 15px;
-			color: grey;
-		}
-		a {
-			font-weight: bold;
-		}
-	}
-	& > form {
-		& > div {
-			margin: 20px 0;
-		}
-		p {
-			margin: 5px 0;
-		}
-		& > .remind-block {
-			margin-top: 20px;
-			margin-bottom: 40px;
-		}
-		.button.guest {
-			display: flex;
-			align-items: center;
-			justify-content: center;
-			border: 1px solid #0d1115;
-			background-color: white;
-			color: #0d1115;
-			text-decoration: none;
-	
-			&:hover {
-				background-color: rgba(0, 0, 0, .1);
-			}
-		}
-		.password-forgotten {
-			text-align: center;
-			font-size: .85rem;
-			margin-top: 30px;
-		}
-		.enter {
-			position: relative;
-		}
-		.wrapper {
-		}
-		._submit {
-			position: relative;
-		}
-		.htk-spinner {
-			width: 24px;
-			height: 24px;
-			position: absolute;
-			top: 50%;
-			margin-top: -12px;
-			right: 24px;
-
-			& > .spinner {
-				border-top-color: white;
-				border-left-color: white;
-			}
-		}
-	}
-}
-
diff --git a/js/hedera/login.xml b/js/hedera/login.xml
deleted file mode 100644
index 33051c28..00000000
--- a/js/hedera/login.xml
+++ /dev/null
@@ -1,57 +0,0 @@
-<vn>
-<div id="main" class="vn-login">
-	<div class="column">
-		<div class="header">
-			<img src="image/logo.svg" alt="VerdNatura"/>
-			<div class="version-code"/>
-		</div>
-		<form id="form">
-			<div class="form-group">
-				<input
-					placeholder="_User"
-					type="text"
-					id="user"
-					name="user"/>
-			</div>
-			<div class="form-group">
-				<input
-					placeholder="_Password"
-					type="password"
-					id="pass"
-					name="password"/>
-			</div>
-			<div class="remind-block">
-				<label>
-					<input type="checkbox" id="remember" name="remember"/>
-					<t>Remind me</t>
-				</label>
-			</div>
-			<div class="enter">
-				<button id="submit" type="submit">
-					<t>Login</t>
-					<htk-spinner id="spinner"/>
-				</button>
-			</div>
-			<div>
-				<a class="button guest" href="#!form=cms/home&amp;guest=true">
-					<t>Log in as guest</t>
-				</a>
-			</div>
-			<p class="password-forgotten">
-				<a href="#" on-click="onPasswordLost">
-					<t>Password forgotten? Push here</t>
-				</a>
-			</p>
-		</form>
-		<div class="footer">
-			<p>
-				<t>Yet you are not a customer?</t>
-				<a href="//verdnatura.es/register/" target="_blank"><t>Sign up</t></a>
-			</p>
-			<p class="contact">
-				<t>Login phone</t> · <t>Login mail</t>
-			</p>
-		</div>
-	</div>
-</div>
-</vn>
diff --git a/js/hedera/module.js b/js/hedera/module.js
deleted file mode 100644
index dc522dda..00000000
--- a/js/hedera/module.js
+++ /dev/null
@@ -1,70 +0,0 @@
-
-module.exports = new Class({
-	basePath: null,
-	path: null,
-	moduleName: null,
-	resolvers: null,
-	status: null,
-
-	initialize(basePath, path) {
-		const aux = path.split('/');
-		const moduleName = aux[aux.length - 1];
-
-		this.basePath = basePath;
-		this.path = path;
-		this.moduleName = moduleName;
-	},
-
-	async load() {
-		switch(this.status) {
-			case 'ready':
-				return;
-			case 'loading':
-				return new Promise((resolve, reject) => {
-					this.resolvers.push(status => {
-						if (status == 'error')
-							return reject(new Error(`Module could not be loaded`));
-						resolve();
-					});
-				});
-		}
-
-		this.status = 'loading';
-		this.resolvers = [];
-		const absPath = `${this.basePath}/${this.path}`;
-		const requests = [
-			Vn.includeJs(`${absPath}/${this.moduleName}.js`),
-			Vn.loadXml(`${absPath}/ui.xml`)
-		];
-
-		try {
-			await Vn.Locale.load(absPath);
-		} catch(err) {
-			console.err(err);
-		}
-
-		try {
-			await Promise.all(requests);
-			const klassName = this.toCamelCase(this.moduleName);
-			this.klass = Hedera[klassName];
-			this.status = 'ready';
-		} catch (err) {
-			this.status = 'error';
-			console.error(err);
-		}
-
-		for (const resolver of this.resolvers)
-			resolver(this.status);
-
-		this.resolvers = null;
-	}
-	
-	,toCamelCase(dashedName) {
-		var camelCase = dashedName.charAt(0).toUpperCase();
-		camelCase += dashedName.substr(1).replace(/\w-\w/g, function(token) {
-			return token.charAt(0) + token.charAt(2).toUpperCase();
-		});
-		return camelCase;
-	}
-});
-
diff --git a/js/hedera/report.css b/js/hedera/report.css
deleted file mode 100644
index 0bb41036..00000000
--- a/js/hedera/report.css
+++ /dev/null
@@ -1,98 +0,0 @@
-
-@font-face {
-	font-family: 'Roboto';
-	src: url('roboto.ttf') format('truetype');
-}
-@media print {
-	body {
-		-webkit-print-color-adjust: exact;
-	}
-	.sheet {
-		width: 100%;
-		page-break-after: always;
-	}
-	#topbar {
-		display: none;
-	}
-}
-@media screen {
-	body {
-		background-color: #EEE;
-		padding-top: 3.9em;
-	}
-	.sheet {
-		width: 210mm;
-		height: 297mm;
-		background-color: white;
-		margin: 10mm auto;
-		box-shadow: 0 1mm 1mm #CCC;
-		padding: 20mm;
-	}
-	#topbar {
-		position: fixed;
-		top: 0;
-		left: 0;
-		right: 0;
-		height: 4em;
-		background-color: #009688;
-		z-index: 100;
-		box-shadow: 0 .1em .1em #AAA;
-	}
-	#topbar > button {
-		float: right;
-		background-color: transparent;
-		color: white;
-		padding: .4em;
-		z-index: 100;
-		border: none;
-		cursor: pointer;
-		font-size: 1.15rem;
-		height: 100%;
-		padding: 0 1em;
-	}
-	#topbar > button:hover {
-		background-color: rgba(1, 1, 1, 0.2);
-	}
-}
-* {
-	font-family: 'Roboto';
-}
-body {
-	position: relative;
-	margin: 0;
-	width: 100%;
-	z-index: -2;
-}
-.sheet {
-	position: relative;
-	overflow: hidden;
-	box-sizing: padding-box;
-/*	page-break-after: always;*/
-}
-
-/* Widgets */
-
-.htk-grid {
-	border-collapse: collapse;
-	width: 100%;
-	margin: 0 auto;
-	padding: 0;
-}
-.htk-grid > thead > tr {
-	border-bottom: 1px solid #333;
-	height: 10mm;
-}
-.htk-grid > thead th {
-	text-align: left;
-	font-weight: normal;
-}
-.htk-grid tr {
-	height: 2em;
-}
-.htk-grid > thead th,
-.htk-grid td {
-	padding-left: 3mm;
-}
-.htk-grid .cell-spin {
-	text-align: right;
-}
diff --git a/js/hedera/report.html b/js/hedera/report.html
deleted file mode 100644
index 908c81fd..00000000
--- a/js/hedera/report.html
+++ /dev/null
@@ -1,18 +0,0 @@
-<!DOCTYPE html>
-
-<html xmlns="http://www.w3.org/1999/xhtml">
-	<head>
-		<meta charset="UTF-8">
-		<meta name="viewport" content="user-scalable=no"/>
-		<meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes"/>
-		<meta name="mobile-web-app-capable" content="yes">
-		<link rel="shortcut icon" type="image/x-icon" href="image/favicon.ico"/>
-		<link rel="stylesheet" type="text/css" href="report.css"/>
-		<title>Report</title>
-	</head>
-	<body>
-		<div id="topbar">
-			<button id="print">Print</button>
-		</div>
-	</body>
-</html>
diff --git a/js/hedera/report.js b/js/hedera/report.js
deleted file mode 100644
index 5d905e2f..00000000
--- a/js/hedera/report.js
+++ /dev/null
@@ -1,86 +0,0 @@
-
-module.exports = new Class({
-	Extends: Vn.Object
-
-	,initialize(moduleInfo, gui) {
-		this.info = moduleInfo;
-		this.gui = gui;
-		this.conn = gui.conn;
-		Vn.Object.prototype.initialize.call(this);
-	}
-
-	,open(lot) {
-		this.lot = lot;
-		this.createWindow();
-	}
-	
-	,print() {
-		this.window.print();
-	}
-
-	,includeCss(path) {
-		var basePath = location.protocol +'//'+ location.host;
-		basePath += location.port ? ':'+ location.port : '';
-		basePath += location.pathname.substring(0,
-			location.pathname.lastIndexOf('/'));
-	
-		var link = this.doc.createElement('link');
-		link.rel = 'stylesheet';
-		link.type = 'text/css';
-		link.href = basePath +'/'+ path + Vn.getVersion();
-		
-		var head = this.doc.getElementsByTagName('head')[0];
-		head.appendChild(link);
-	}
-
-	,createWindow() {
-		var reportWindow = window.open(
-			'js/hedera/report.html', '_blank',
-			'height=650, width=950, resizable=yes, fullscreen=no,'+
-			'titlebar=no, menubar=no, toolbar=no, location=no, scrollbars=yes'
-		);
-		
-		if (!reportWindow) {
-			Htk.Toast.showError(
-				_('Please unlock popups and try again'));
-			return false;
-		}
-		
-		reportWindow.addEventListener('load', 
-			this._onWindowLoad.bind(this));		
-		this.window = reportWindow;
-		return true;
-	}
-	
-	,_onWindowLoad() {
-		this.doc = this.window.document
-
-		this.includeCss('reports/'+ this.info.path +'/style.css');
-		
-		var printButton = this.doc.getElementById('print');
-		printButton.addEventListener('click', this.print.bind(this));
-		Vn.Node.setText(printButton, _('Print'));
-		
-		this.onWindowCreate();
-	}
-	
-	,onWindowCreate() {
-		var builder = new Vn.Builder();
-		builder.compileFile('reports/'+ this.info.path +'/ui.xml');
-
-		var scope = this.scope = builder.load(this.doc, this);
-		scope.link({
-			lot: this.lot,
-			conn: this.conn
-		});
-		this.$ = scope.$;
-
-		this.doc.body.appendChild(scope.$.report);
-	}
-
-	,_destroy() {
-		if (this.scope) this.scope._destroy();
-		Vn.Object.prototype._destroy.call(this);
-	}
-});
-
diff --git a/js/hedera/social-bar.js b/js/hedera/social-bar.js
deleted file mode 100644
index 3cbc4306..00000000
--- a/js/hedera/social-bar.js
+++ /dev/null
@@ -1,63 +0,0 @@
-require('./social-bar.scss');
-
-module.exports = new Class({
-	Extends: Vn.Component
-	,Tag: 'htk-social-bar'
-	,Properties: {
-		conn: {
-			type: Db.Connection
-			,set(x) {	
-				this._conn = x;
-				this._refresh();
-			}
-			,get() {
-				return this._conn;
-			}
-		},
-		priority: {
-			type: Number
-			,set(x) {	
-				this._priority = x;
-				this._refresh();
-			}
-			,get() {
-				return this._priority;
-			}
-		}	
-	}
-	
-	,_priority: 0
-	
-	,initialize() {
-		var node = this.createRoot('div');
-		node.className = 'htk-social-bar';
-	}
-
-	,async _refresh() {
-		if (!this._conn || this._priority === null)
-			return;
-		
-		const params = {priority: this._priority};
-		
-		const query = 'SELECT title, link, icon FROM social '
-			+'WHERE priority >= #priority ORDER BY priority';
-		const resultSet = await this._conn.execQuery(query, params);
-
-		Vn.Node.removeChilds(this._node);	
-		const res = resultSet.fetchResult();
-		
-		while (res.next()) {
-			const a = this.createElement('a');
-			a.href = res.get('link');
-			a.target = '_blank';
-			this._node.appendChild(a);
-			
-			const img = this.createElement('img');
-			img.src = 'image/social/'+ res.get('icon');
-			img.alt = res.get('title');
-			img.title = res.get('title');
-			a.appendChild(img);
-		}
-	}
-});
-
diff --git a/js/hedera/social-bar.scss b/js/hedera/social-bar.scss
deleted file mode 100644
index e540930a..00000000
--- a/js/hedera/social-bar.scss
+++ /dev/null
@@ -1,13 +0,0 @@
-
-.htk-social-bar {
-	text-align: center;
-
-	a {
-		display: inline-block;
-		margin: 0 .1em;
-	}
-	img {
-		height: 1.8em;
-		width: 1.8em;
-	}
-}
diff --git a/js/hedera/tpv.js b/js/hedera/tpv.js
deleted file mode 100644
index 6ee274bd..00000000
--- a/js/hedera/tpv.js
+++ /dev/null
@@ -1,91 +0,0 @@
-module.exports = new Class({
-	Extends: Vn.Object
-
-	,tpvOrder: null
-	,tpvStatus: null
-
-	,check() {
-		this.tpvOrder = this.hash.$.tpvOrder;
-		this.tpvStatus = this.hash.$.tpvStatus;
-
-		if (this.tpvStatus) {
-			const query = 'CALL myTpvTransaction_end(#transaction, #status)';
-			this.conn.execQuery(query, {
-				transaction: this.tpvOrder,
-				status: this.tpvStatus
-			});
-		}
-
-		return this.tpvStatus;
-	}
-
-	,async pay(amount, company) {
-		await this._realPay(amount * 100, company);
-	}
-
-	,async _realPay(amount, company) {
-		if (!isNumeric(amount) || amount <= 0)
-			throw new UserError(_('AmountError'));
-
-		let json;
-		
-		try {
-			json = await this.conn.send('tpv/transaction', {
-				amount: parseInt(amount)
-				,urlOk: this._makeUrl('ok')
-				,urlKo: this._makeUrl('ko')
-				,company: company
-			});
-		} catch(err) {
-			throw new UserError(_('PayError'));
-		}
-
-		const postValues = json.postValues;
-
-		const form = document.createElement('form');
-		form.method = 'POST';
-		form.action = json.url;
-		document.body.appendChild(form);
-		
-		for (var field in postValues) {
-			const input = document.createElement('input');
-			input.type = 'hidden';
-			input.name = field;
-			form.appendChild(input);
-			
-			if (postValues[field])
-				input.value = postValues[field];
-		}
-		
-		form.submit();
-	}
-	
-	,async retryPay() {
-		const query = 'SELECT t.amount, m.companyFk '
-			+'FROM myTpvTransaction t '
-			+'JOIN tpvMerchant m ON m.id = t.merchantFk '
-				+'WHERE t.id = #transaction';
-
-		const res = await this.conn.execQuery(query,
-			{transaction: parseInt(this.tpvOrder)});
-		const payment = res.fetchObject();
-		await this._realPay(payment.amount, payment.companyFk);
-	}
-
-	,_makeUrl(status) {
-		let path = location.protocol +'//'+ location.hostname;
-		path += location.port ? ':'+ location.port : '';
-		path += location.pathname;
-		path += location.search ? location.search : '';
-		path += this.hash.make({
-			form: 'ecomerce/orders',
-			tpvStatus: status,
-			tpvOrder: '_transactionId_'
-		}, true);
-		return path;
-	}
-});
-
-function isNumeric(n) {
-	return !isNaN(parseFloat(n)) && isFinite(n);
-}
diff --git a/js/htk/assistant-bar/index.js b/js/htk/assistant-bar/index.js
deleted file mode 100644
index fd96eaa8..00000000
--- a/js/htk/assistant-bar/index.js
+++ /dev/null
@@ -1,140 +0,0 @@
-require('./style.scss');
-var Component = require('vn/component');
-var Assistant = require('../assistant');
-
-module.exports = new Class({
-	Extends: Component,
-	Tag: 'htk-assistant-bar',
-	Properties: {
-		assistant: {
-			type: Assistant,
-			set(x) {
-				this.link({_assistant: x}, {
-					'step-change': this.onStepChange,
-					'steps-change': this.onStepsChange
-				});
-				this.onStepsChange();
-			},
-			get() {
-				return this._assistant;
-			}
-		},
-		disabled: {
-			type: Boolean,
-			set(x) {
-				this._disabled = x;
-				this._previousButton.disabled = x;
-				this._nextButton.disabled = x;
-				this._endButton.disabled = x;
-			},
-			get() {
-				return this._disabled;
-			}
-		}
-	},
-
-	_assistant: null,
-	_stepIndex: -1,
-	_disabled: false,
-	
-	render() {
-		var node = this.createRoot('div');
-
-		var previousButton = new Htk.Button({
-			icon: 'arrow_back',
-			tip: 'Previous'
-		}).node;
-		previousButton.classList.add('previous');
-		previousButton.addEventListener('click', this.movePrevious.bind(this));
-		node.appendChild(previousButton);
-		
-		var steps = this.createElement('div');
-		steps.className = 'steps';
-		node.appendChild(steps);
-		
-		var nextButton = new Htk.Button({
-			icon: 'arrow_forward',
-			tip: 'Next'
-		}).node;
-		nextButton.classList.add('next');
-		nextButton.addEventListener('click', this.moveNext.bind(this));
-		node.appendChild(nextButton);
-		
-		var endButton = new Htk.Button({
-			icon: 'done',
-			tip: 'Confirm'
-		}).node;
-		endButton.classList.add('end');
-		endButton.addEventListener('click', this.end.bind(this));
-		node.appendChild(endButton);
-		
-		this._steps = steps;
-		this._previousButton = previousButton;
-		this._nextButton = nextButton;
-		this._endButton = endButton;
-	},
-
-	movePrevious() {
-		if (this._assistant)
-			this._assistant.movePrevious();
-	},
-	
-	moveNext() {
-		if (this._assistant)
-			this._assistant.moveNext();
-	},
-	
-	end() {
-		if (this._assistant)
-			this._assistant.end();
-	},
-	
-	setStep(stepIndex) {
-		if (this._assistant)
-			this._assistant.setStep(stepIndex);
-	},
-
-	onStepsChange() {
-		var stepCount = this._assistant.stepCount;
-		var steps = this._steps;
-
-		Vn.Node.removeChilds(steps);
-
-		for (var i = 0; i < stepCount; i++) {
-			var img = this.createElement('div');
-			img.src = 'image/step.svg';
-			img.addEventListener('click', this.setStep.bind(this, i));
-			steps.appendChild(img);
-		}
-
-		this.onStepChange();
-	},
-
-	onStepChange() {
-		var childs = this._steps.childNodes;
-		var stepCount = childs ? childs.length : 0;
-		var stepIndex = this._assistant ? this._assistant.step : -1;
-
-		if (this._stepIndex != -1) {
-			childs[this._stepIndex].src = 'image/step.svg';
-			childs[this._stepIndex].className = '';
-		}
-
-		if (stepIndex >= stepCount)
-			return;
-
-		this._stepIndex = stepIndex;
-		
-		if (stepIndex != -1) {
-			childs[stepIndex].src = 'image/step-cur.svg';
-			childs[this._stepIndex].className = 'selected';
-		}
-
-		var visibility = stepIndex > 0 ? 'visible' : 'hidden';
-		this._previousButton.style.visibility = visibility;
-
-		var isEnd = stepIndex >= stepCount - 1;
-		this._nextButton.style.display = isEnd ? 'none' : 'block';
-		this._endButton.style.display = isEnd ? 'block' : 'none';
-	}
-});
diff --git a/js/htk/assistant-bar/style.scss b/js/htk/assistant-bar/style.scss
deleted file mode 100644
index 4b6877d3..00000000
--- a/js/htk/assistant-bar/style.scss
+++ /dev/null
@@ -1,66 +0,0 @@
-
-.htk-assistant-bar {
-	position: relative;
-	padding: .8em;
-	display: flex;
-	align-items: center;
-	justify-content: space-between;
-	box-sizing: border-box;
-	width: 100%;
-
-	& > button {
-		border-radius: 50%;
-		padding: .5em;
-		margin: 0;
-		text-align: center;
-
-		& > img {
-			display: block;
-			width: 1.8em;
-			padding: .5em;
-		}
-	}
-	& > .end {
-		display: none;
-		color: #8cc63f;
-
-		& > .icon {
-			font-size: 1.6rem;
-		}
-	}
-	& > .steps {
-		display: flex;
-		align-items: center;
-
-		& > div {
-			background-color: #AAA;
-			width: .5em;
-			height: .5em;
-			cursor: pointer;
-			border-radius: 50%;
-			margin: .5em;
-		
-			transition-property: width, height;
-			transition-duration: 100ms;
-			transition-timing-function: ease-in-out;
-
-			&.selected {
-				background-color: #666;
-				width: 1em;
-				height: 1em;
-			}
-			&:hover {
-				opacity: .7;
-			}
-		}
-		& > img {
-			width: 1.3em;
-			margin: 0 .2em;
-			cursor: pointer;
-
-			&:hover {
-				opacity: .7;
-			}
-		}
-	}
-}
diff --git a/js/htk/assistant/index.js b/js/htk/assistant/index.js
deleted file mode 100644
index 79e4dc50..00000000
--- a/js/htk/assistant/index.js
+++ /dev/null
@@ -1,161 +0,0 @@
-require('./style.scss');
-var Component = require('vn/component');
-var Step = require('../step');
-var Toast = require('../toast');
-
-/**
- * A simple assistant with steps.
- */
-module.exports = new Class({
-	Extends: Component,
-	Tag: 'htk-assistant',
-	Properties: {
-		/**
-		 * The current step index.
-		 */
-		step: {
-			type: Number,
-			set(x) {
-				this.setStep(x);
-			},
-			get() {
-				return this._stepIndex;
-			}
-		},
-		/**
-		 * The current step name.
-		 */
-		stepName: {
-			type: String,
-			set(x) {
-				this.setStepByName(x);
-			},
-			get() {
-				return this._stepName;
-			}
-		},
-		/**
-		 * The steps index.
-		 */
-		stepsIndex: {
-			type: Array,
-			set(x) {
-				this._stepsIndex = x;
-				this.setStep(this._stepIndex);
-				this.emit('steps-change');
-			},
-			get() {
-				return this._stepsIndex;
-			}
-		},
-		/**
-		 * The total number of steps in the assistant.
-		 */
-		stepCount: {
-			type: Number,
-			get() {
-				if (this._stepsIndex)
-					return this._stepsIndex.length;
-				return 0;
-			}
-		},
-		/**
-		 * Function to call on every step change.
-		 */
-		stepFunc: {
-			type: Function,
-			value: null
-		},
-		/**
-		 * Function to call on every step change.
-		 */
-		endFunc: {
-			type: Function,
-			value: null
-		},
-	},
-
-	_stepNode: null,
-	_stepIndex: 0,
-	_stepName: null,
-	steps: {},
-
-	initialize(props) {
-		Component.prototype.initialize.call(this, props);
-		this.createRoot('div');
-	},
-
-	appendChild(step) {
-		if (!(step instanceof Step))
-			throw new Error('Invalid child for assistant');
-
-		this.node.appendChild(step.node);
-		this.steps[step.name] = step;
-	},
-
-	setStepByName(stepName) {
-		if (this._stepsIndex)
-			this.setStep(this._stepsIndex.indexOf(stepName));
-	},
-
-	setStep(stepIndex) {
-		if ((this.currentStep && stepIndex == this._stepIndex)
-		|| !this._stepsIndex
-		|| !(stepIndex >= -1 && stepIndex < this._stepsIndex.length))
-			return;
-
-		if (stepIndex > this._stepIndex) {
-			var validateIni = Math.max(this._stepIndex, 0);
-
-			try {
-				for (var i = validateIni; i < stepIndex; i++) {
-					var validateName = this._stepsIndex[i];
-					var validateStep = this.steps[validateName];
-					validateStep.validate();
-				}
-			} catch(e) {
-				Toast.showError(e.message);
-				if (i == this._stepIndex) return;
-				stepIndex = i;
-			}
-		}
-
-		var stepName = this._stepsIndex[stepIndex];
-		var step = this.steps[stepName];
-		var currentStep = this.currentStep;
-
-		if (currentStep)
-			currentStep.hide();
-
-		this._stepIndex = stepIndex;
-		this._stepName = stepName;
-		this.currentStep = step;
-		step.show();
-		this.emit('step-change', stepIndex);
-		
-		if (this.stepFunc)
-			this.stepFunc(step);
-	},
-
-	/**
-	 * Moves the assistant to the previous step.
-	 */
-	movePrevious() {
-		this.setStep(this._stepIndex - 1);
-	},
-	
-	/**
-	 * Moves the assistant to the next step.
-	 */
-	moveNext() {
-		this.setStep(this._stepIndex + 1);
-	},
-
-	/**
-	 * Ends the assistant. If defined, the stepFunc will be called.
-	 */
-	end() {
-		if (this.endFunc)
-			this.endFunc();
-	}
-});
diff --git a/js/htk/assistant/style.scss b/js/htk/assistant/style.scss
deleted file mode 100644
index b5261194..00000000
--- a/js/htk/assistant/style.scss
+++ /dev/null
@@ -1,14 +0,0 @@
-
-.htk-assistant > div {
-	display: none;
-	
-	& > h2 {
-		text-align: center;
-		font-weight: normal;
-		font-size: 1.5rem;
-		margin: 0;
-		padding: 0;
-		margin-bottom: 1em;
-		font-weight: bold;
-	}
-}
\ No newline at end of file
diff --git a/js/htk/bar-button/index.js b/js/htk/bar-button/index.js
deleted file mode 100644
index aad3e764..00000000
--- a/js/htk/bar-button/index.js
+++ /dev/null
@@ -1,9 +0,0 @@
-
-var Button = require('../button');
-
-module.exports = new Class({
-	Extends: Button
-	,Tag: 'htk-bar-button'
-	
-	,_showText: true
-});
diff --git a/js/htk/button/index.js b/js/htk/button/index.js
deleted file mode 100644
index 783a6577..00000000
--- a/js/htk/button/index.js
+++ /dev/null
@@ -1,61 +0,0 @@
-require('./style.scss');
-
-module.exports = new Class({
-	Extends: Htk.Field
-	,Tag: 'htk-button'
-	,Properties: {
-		image: {
-			type: String
-			,set(x) {
-				this.iconNode.name = x;
-			}
-		},
-		icon: {
-			type: String
-			,set(x) {
-				this.iconNode.name = x;
-			}
-		},
-		tip: {
-			type: String
-			,set(x) {
-				this.node.title = x ? _(x) : '';
-				this.renderContent();
-			}
-			,get() {
-				return this.node.title;
-			}
-		},
-		showText: {
-			type: Boolean
-			,set(x) {
-				this._showText = x;
-				this.renderContent();
-			}
-			,get() {
-				return this._showText;
-			}
-		}
-	}
-	
-	,_showText: false
-	
-	,render() {
-		var node = this.createRoot('button');
-	
-		this.iconNode = new Htk.Icon();
-		node.appendChild(this.iconNode.node);
-	}
-	
-	,renderContent() {
-		if (this._textNode)
-			Vn.Node.remove(this._textNode);
-
-		if (this._showText && this.node.title) {
-			this._textNode = this.createElement('span');
-			this._textNode.className = 'text';
-			this._textNode.appendChild(this.createTextNode(this.node.title));
-			this.node.appendChild(this._textNode);
-		}
-	}
-});
diff --git a/js/htk/button/style.scss b/js/htk/button/style.scss
deleted file mode 100644
index d0863010..00000000
--- a/js/htk/button/style.scss
+++ /dev/null
@@ -1,15 +0,0 @@
-
-.htk-button {
-	display: flex;
-	align-items: center;
-	gap: 8px;
-
-	& > .htk-icon {
-		display: block;
-	}
-	& > .text {
-		white-space: nowrap;
-		text-overflow: ellipsis;
-		overflow: hidden;
-	}
-}
\ No newline at end of file
diff --git a/js/htk/calendar/index.js b/js/htk/calendar/index.js
deleted file mode 100644
index 24f757ef..00000000
--- a/js/htk/calendar/index.js
+++ /dev/null
@@ -1,265 +0,0 @@
-require('./style.scss');
-
-module.exports = new Class({
-	Extends: Htk.Field
-	,Tag: 'htk-calendar'
-	,Properties: {
-		restrictFunc: {
-			type: Function
-			,set(x) {
-				this._restrictFunc = x;
-			}
-			,get() {
-				return this._restrictFunc;
-			}
-		}
-	}
-	
-	,cells: []
-	,selectedCell: -1
-	,year: null
-	,month: null
-
-	,render() {
-		this.createRoot('div');
-		
-		var table = this.createElement('table');
-		this.node.appendChild(table);
-
-		var colgroup = this.createElement('colgroup');
-		table.appendChild(colgroup);
-		
-		var len = Vn.Date.WDays.length;
-		for (var i = 0; i < len; i++)
-			colgroup.appendChild(this.createElement('col'));
-		
-		var thead = this.createElement('thead');
-		table.appendChild(thead);
-
-		var tr = this.createElement('tr');
-		thead.appendChild(tr);
-
-		var th = this.createElement('th');
-		th.className = 'previous';
-		tr.appendChild(th);
-
-		var previousButton = new Htk.Button({
-			icon: 'arrow_back_ios'
-		}).node;
-		previousButton.addEventListener('click', this.prevMonthClicked.bind(this));
-		th.appendChild(previousButton);
-
-		var th = this.createElement('th');
-		th.className = 'month-year';
-		th.colSpan = 5;
-		tr.appendChild(th);
-
-		var monthNode = this.createElement('span');
-		th.appendChild(monthNode);
-
-		var space = this.createTextNode(' ');
-		th.appendChild(space);
-		
-		var yearNode = this.createElement('span');
-		th.appendChild(yearNode);
-
-		var th = this.createElement('th');
-		th.className = 'next';
-		tr.appendChild(th);
-
-		var nextButton = new Htk.Button({
-			icon: 'arrow_forward_ios'
-		}).node;
-		nextButton.addEventListener('click', this.nextMonthClicked.bind(this));
-		th.appendChild(nextButton);
-		
-		var tr = this.createElement('tr');
-		tr.className = 'weekdays';
-		thead.appendChild(tr);
-		
-		for (var i = 1; i <= len; i++) {
-			var th = this.createElement('th');
-			tr.appendChild(th);
-			
-			var weekday = _(Vn.Date.AbrWDays [i%len]);
-			th.appendChild(this.createTextNode(weekday));
-		}
-
-		var tbody = this.createElement('tbody');
-		table.appendChild(tbody);
-		
-		for (var i = 0; i < 6; i++) {
-			var tr = this.createElement('tr');
-			tbody.appendChild(tr);
-
-			for (var j = 0; j < len; j++) {
-				var td = this.createElement('td');
-				td.addEventListener('click', this.dayClicked.bind(this, td, i*len+j));
-				tr.appendChild(td);
-				
-				var div = this.createElement('div');
-				td.appendChild(div);
-
-				this.cells.push({
-					node: div,
-					enabled: false,
-					day: -1
-				});
-			}
-		}
-
-		this.monthNode = monthNode;
-		this.yearNode = yearNode;
-		this.goToCurrentMonth();
-	}
-
-	,getMonthDays() {
-		if (this.month > 6)
-			return (this.month % 2 != 0) ? 31 : 30;
-		else if (this.month != 1)
-			return (this.month % 2 != 1) ? 31 : 30;
-		else
-			return (this.year % 4 != 0) ? 28 : 29;
-	}
-	
-	,goToMonth(year, month) {
-		if (year)
-			this.year = year;
-		if (!isNaN(month))
-			this.month = month;
-
-		this.refresh();
-	}
-	
-	,goToSelectedMonth() {
-		var date = this._value;
-		
-		if (date instanceof Date)
-			this.goToMonth(date.getFullYear(), date.getMonth());
-		else
-			this.goToCurrentMonth();			
-	}
-
-	,goToCurrentMonth() {
-		var date = new Date();
-		this.goToMonth(date.getFullYear(), date.getMonth());
-	}
-
-	,refresh() {
-		Vn.Node.setText(this.yearNode, this.year);
-		Vn.Node.setText(this.monthNode, _(Vn.Date.Months[this.month]));
-
-		var day = 1;
-		var cellDate = new Date(this.year, this.month, 1);
-
-		var weekDay = cellDate.getDay();
-		var firstWeekDay = (weekDay != 0) ? weekDay - 1 : 6;
-		var monthDays = this.getMonthDays();
-
-		for (var i = 0; i < this.cells.length; i++) {
-			var cell = this.cells[i];
-
-			if (firstWeekDay <= i && day <= monthDays) {
-				Vn.Node.setText(cell.node, day);
-				cell.enabled = true;
-				cell.day = day++;
-				
-				if (this._restrictFunc) {
-					cell.enabled = this._restrictFunc(cellDate);
-					cellDate.setDate(cellDate.getDate() + 1);
-				}
-			} else {
-				Vn.Node.removeChilds(cell.node);
-				cell.enabled = false;
-				cell.day = -1;
-			}
-			
-			cell.node.className = cell.enabled ? 'enabled' : 'disabled';
-		}
-
-		// Marks the current day
-
-		var today = new Date();
-		
-		if (this.year == today.getFullYear()
-		&& this.month == today.getMonth()) {
-			var cellIndex = (firstWeekDay + today.getDate()) - 1;
-			Vn.Node.addClass(this.cells[cellIndex].node, 'today');
-		}
-		
-		// Marks the selected day
-		
-		var date = this._value;
-
-		if (date instanceof Date
-		&& this.year == date.getFullYear()
-		&& this.month == date.getMonth())
-			this.selectCell((firstWeekDay + date.getDate()) - 1);
-		else
-			this.selectCell(-1);
-	}
-
-	,selectCell(cellIndex) {
-		if (this.selectedCell != -1) {
-			var node = this.cells[this.selectedCell].node;
-			Vn.Node.removeClass(node, 'selected');
-		}
-		if (cellIndex != -1) {
-			var node = this.cells[cellIndex].node;
-			Vn.Node.addClass(node, 'selected');
-		}
-
-		this.selectedCell = cellIndex;
-	}
-
-	,putValue() {
-		this.goToSelectedMonth();
-	}
-
-	,dayClicked(td, cellIndex) {
-		var cell = this.cells[cellIndex];
-	
-		if (cell.enabled) {
-			this.selectCell(cellIndex);
-			var newDate = new Date(this.year, this.month, cell.day);
-
-			if (this.value) {
-				var orgDate = this.value instanceof Date
-					? this.value
-					: new Date(this.value);
-
-				if (!isNaN(orgDate.getTime()))
-					newDate.setHours(
-						orgDate.getHours(),
-						orgDate.getMinutes(),
-						orgDate.getSeconds(),
-						orgDate.getMilliseconds()
-					);
-			}
-
-			this.valueChanged(newDate);
-		}
-	}
-
-	,prevMonthClicked() {
-		if (this.month > 0)
-			this.month--;
-		else {
-			this.month = 11;
-			this.year--;
-		}
-		
-		this.refresh();
-	}
-
-	,nextMonthClicked() {
-		if (this.month < 11)
-			this.month++;
-		else {
-			this.month = 0;
-			this.year++;
-		}
-		
-		this.refresh();
-	}
-});
diff --git a/js/htk/calendar/style.scss b/js/htk/calendar/style.scss
deleted file mode 100644
index 56761078..00000000
--- a/js/htk/calendar/style.scss
+++ /dev/null
@@ -1,94 +0,0 @@
-@import "../style/variables";
-@import "../style/classes";
-
-.htk-calendar {
-	@extend %box;
-	width: 20em;
-
-	table {
-		border-collapse: collapse;
-	}
-	thead tr,
-	tfoot tr {
-		font-weight: normal;
-		vertical-align: middle;
-		text-align: center;
-		height: 3em;
-	}
-	thead > tr {
-		&.weekdays > th {
-			font-weight: normal;
-			color: #999;
-			text-transform: lowercase;
-		}
-		& > th {
-			&.previous, &.next {
-				font-size: .8rem;
-
-				button {
-					border-radius: 50%;
-					padding: 10px;
-					display: block;
-					margin: 0 auto;
-
-					& > .htk-icon {
-						font-size: 1rem;
-					}
-				}
-			}
-			&.month-year {
-				font-size: 1.2rem;
-				text-transform: lowercase;
-			}
-		}
-	}
-	tfoot tr {
-		border-top: none;
-	}
-	th.button {
-		display: table-cell;
-	}
-	th.button:hover {
-		cursor: pointer;
-		background-color: rgba(1, 1, 1, 0.2);
-	}
-	col {
-		width: 14.2%;
-	}
-	tr {
-		height: 2em;
-	}
-	tbody td {
-		text-align: right;
-	}
-	tbody td > div {
-		height: 2em;
-		width: 2em;
-		line-height: 2em;
-		text-align: center;
-		border-radius: 2em;
-		padding: 0.3em;
-		margin: 0 auto;
-		color: #555;
-	}
-	div {
-		&.disabled {
-			color: #bbb;
-		}
-		&.today {
-			font-weight: bold;
-			color: black;
-		}
-		&.selected {
-			color: white;
-			background-color: $color-primary;
-		}
-		&.enabled {
-			@extend %clickable;
-
-			&:hover {
-				background-color: rgba(140, 198, 63, 0.8);
-			}
-		}
-	}
-}
diff --git a/js/htk/check/index.js b/js/htk/check/index.js
deleted file mode 100644
index 404f3504..00000000
--- a/js/htk/check/index.js
+++ /dev/null
@@ -1,26 +0,0 @@
-
-module.exports = new Class({
-	Extends: Htk.Field
-	,Tag: 'htk-check'
-
-	,render() {
-		var node = this.createRoot('input');
-		node.type = 'checkbox';
-		node.addEventListener('change', this.changed.bind(this));
-	}
-
-	,changed() {
-		this.valueChanged(this.node.checked);
-	}
-
-	,putValue(value) {
-		if (value)
-			this.node.checked = true;
-		else
-			this.node.checked = false;
-	}
-
-	,setEditable(editable) {
-		this.node.disabled = !editable;
-	}
-});
diff --git a/js/htk/column/index.js b/js/htk/column/index.js
deleted file mode 100644
index a53066e4..00000000
--- a/js/htk/column/index.js
+++ /dev/null
@@ -1,95 +0,0 @@
-
-var NodeBuilder = require('../../vn/node-builder');
-
-/**
- * Represents a grid column. This is an abstract class and should not be
- * instantiated directly.
- */
-module.exports = new Class({
-	Extends: NodeBuilder
-	,Tag: 'htk-column'
-	,Properties: {
-		value: {
-			type: String
-			,value: null
-		},
-		column: {
-			type: String
-			,value: null
-		},
-		columnIndex: {
-			type: Number
-			,value: -1
-		},
-		title: {
-			 type: String
-			 ,value: null
-		},
-		editable: {
-			type: Boolean
-			,value: false
-		},
-		renderer: {
-			type: Function
-			,value: false
-		},
-		class: {
-			type: String
-			,set(x) {
-				this._userCssClass = x;
-				
-				if (this._cssClass)
-					this._cssClass = x +' '+ this._cssClass;
-				else
-					this._cssClass = x;
-			}
-			,get() {
-				return this._userCssClass;
-			}
-		}
-	}
-	
-	,_cssClass: null
-	,_userCssClass: null
-
-	/**
-	 * Initializes the column.
-	 */
-	,initialize(props) {
-		NodeBuilder.prototype.initialize.call(this, props);
-		this.td = this.createElement('td');
-	}
-	
-	,renderHeader() {
-		var th = this.createElement('th');
-		
-		if (this.title)
-			th.appendChild(this.createTextNode(this.title));
-			
-		return th;
-	}
-
-	/**
-	 * Draws the cell and returns its associated td.
-	 *
-	 * @return {HTMLTableData} the rendered cell
-	 */
-	,render() {
-		var td = this.td.cloneNode(true);
-
-		if (this._cssClass)
-			td.className = this._cssClass;
-			
-		return td;
-	}
-
-	,updateColumnName(model) {
-		if (this.columnIndex !== -1)
-			this.column = model.getColumnName(this.columnIndex);
-	}
-
-	,changed(tr, newValue) {
-		this.emit('changed', tr.rowIndex - 1, newValue);
-	}
-});
-
diff --git a/js/htk/columns/button/index.js b/js/htk/columns/button/index.js
deleted file mode 100644
index e2cbca4f..00000000
--- a/js/htk/columns/button/index.js
+++ /dev/null
@@ -1,75 +0,0 @@
-require('./style.scss');
-
-module.exports = new Class({
-	Extends: Htk.Column,
-	Tag: 'htk-column-button',
-	Properties: {
-		image: {
-			type: String
-			,value: null
-		},
-		icon: {
-			type: String
-			,set(x) {
-				this._icon = x;
-			}
-			,get() {
-				return this._icon;
-			}
-		},
-		tip: {
-			type: String,
-			value: null
-		},
-		disabled: {
-			type: Boolean,
-			value: false
-		},
-		href: {
-			type: String,
-			value: null
-		},
-		target: {
-			type: String,
-			value: ''
-		}
-	},
-	
-	initialize(props) {
-		this._cssClass = 'cell-button';
-		Htk.Column.prototype.initialize.call(this, props);
-	},
-
-	render(tr) {
-		const td = Htk.Column.prototype.render.call(this, tr);
-
-		let button;
-		
-		if (this.href == null) {
-			button = this.createElement('button');
-			button.addEventListener('click', 
-				this.buttonClicked.bind(this, this.value, tr, button));
-		} else {
-			button = this.createElement('a');
-			button.href = this.href;
-			button.target = this.target;
-		}
-	
-		if (this.tip)
-			button.title = _(this.tip);
-
-		button.disabled = this.disabled;
-		td.appendChild(button);
-	
-		const icon = new Htk.Icon({
-			name: this._icon
-		});
-		button.appendChild(icon.node);
-
-		return td;
-	},
-
-	buttonClicked(value, tr, button) {
-		this.emit('clicked', value, tr.rowIndex - 1, button);
-	}
-});
diff --git a/js/htk/columns/button/style.scss b/js/htk/columns/button/style.scss
deleted file mode 100644
index 2cec77cb..00000000
--- a/js/htk/columns/button/style.scss
+++ /dev/null
@@ -1,34 +0,0 @@
-@import "../../style/classes";
-
-td.cell-button {
-	max-width: 20px;
-	text-align: center;
-
-	& > button,
-	& > a {
-		@extend %clickable;
-		display: block;
-		height: 40px;
-		width: 40px;
-		margin: 0 auto;
-		border: none;
-		border-radius: 50%;
-		padding: 8px;
-		background-color: transparent;
-		box-sizing: border-box;
-
-		& > .htk-icon {
-			display: block;
-		}
-		&:hover {
-			background-color: rgba(1, 1, 1, 0.1);
-		}
-	}
-	img {
-		height: 1.5em;
-		width: 1.5em;
-		display: block;
-		margin: auto;
-		padding: 0;
-	}
-}
diff --git a/js/htk/columns/check/index.js b/js/htk/columns/check/index.js
deleted file mode 100644
index b090ea50..00000000
--- a/js/htk/columns/check/index.js
+++ /dev/null
@@ -1,31 +0,0 @@
-require('./style.scss');
-
-module.exports = new Class({
-	Extends: Htk.Column
-	,Tag: 'htk-column-check'
-
-	,initialize(props) {
-		this._cssClass = 'cell-check';
-		Htk.Column.prototype.initialize.call(this, props);
-	}
-
-	,render(tr) {
-		var checkButton = this.createElement('input');
-		checkButton.type = 'checkbox';
-		checkButton.checked = this.value;
-	
-		if (this.editable)
-			checkButton.addEventListener('changed',
-				this.inputChanged.bind(this, tr, node));
-		else
-			checkButton.disabled = true;
-
-		var td = Htk.Column.prototype.render.call(this, tr);
-		td.appendChild(checkButton);
-		return td;
-	}
-	
-	,inputChanged(tr, node) {
-		this.changed(tr, node.value);
-	}
-});
diff --git a/js/htk/columns/check/style.scss b/js/htk/columns/check/style.scss
deleted file mode 100644
index bdee6773..00000000
--- a/js/htk/columns/check/style.scss
+++ /dev/null
@@ -1,5 +0,0 @@
-
-th.cell-check,
-th.cell-radio {
-	text-align: center;
-}
diff --git a/js/htk/columns/date/index.js b/js/htk/columns/date/index.js
deleted file mode 100644
index 1ef93bc5..00000000
--- a/js/htk/columns/date/index.js
+++ /dev/null
@@ -1,38 +0,0 @@
-
-module.exports = new Class
-({
-	Extends: Htk.Column
-	,Tag: 'htk-column-date'
-	,Properties:
-	{
-		/**
-		 * Format that applies to the value.
-		 */
-		format:
-		{
-			type: String
-			,set(x) {
-				this._format = _(x);
-			}
-			,get() {
-				return this._format;
-			}
-		}
-	}
-
-	,_format: _('%a, %e %b %Y')
-	
-	,initialize(props) {
-		this._cssClass = 'cell-date';
-		Htk.Column.prototype.initialize.call(this, props);
-	}
-
-	,render(tr) {
-		var text = Vn.Date.strftime(this.value, this._format);
-
-		var td = Htk.Column.prototype.render.call(this, tr);
-		td.appendChild(this.createTextNode(text));
-
-		return td;
-	}
-});
diff --git a/js/htk/columns/image/index.js b/js/htk/columns/image/index.js
deleted file mode 100644
index dd116ee9..00000000
--- a/js/htk/columns/image/index.js
+++ /dev/null
@@ -1,55 +0,0 @@
-require('./style.scss');
-
-module.exports = new Class({
-	Extends: Htk.Column
-	,Tag: 'htk-column-image'
-	,Properties: {
-		/**
-		 * The directory where the images are allocated.
-		 */
-		directory:{
-			type: String
-			,value: null
-		},
-		/**
-		 * The subdirectory where the images are allocated.
-		 */
-		subdir:{
-			type: String
-			,value: null
-		},
-		/**
-		 * Subdirectory where full images are allocated.
-		 */
-		fullDir:{
-			type: String
-			,value: null
-		},
-		/**
-		 * The REST connection used to upload the image.
-		 */
-		conn:{
-			type: Vn.JsonConnection
-		}
-	}
-	
-	,initialize(props) {
-		this._cssClass = 'cell-image';
-		Htk.Column.prototype.initialize.call(this, props);
-	}
-
-	,render(tr) {
-		var image = new Htk.Image({
-			 directory: this.directory
-			,subdir: this.subdir
-			,fullDir: this.fullDir
-			,value: this.value
-			,conn: this.conn
-			,doc: this.doc
-		});
-
-		var td = Htk.Column.prototype.render.call(this, tr);
-		td.appendChild(image.node);
-		return td;
-	}
-});
diff --git a/js/htk/columns/image/style.scss b/js/htk/columns/image/style.scss
deleted file mode 100644
index 9be8f215..00000000
--- a/js/htk/columns/image/style.scss
+++ /dev/null
@@ -1,11 +0,0 @@
-
-td.cell-image {
-	text-align: center;
-	
-	.htk-image {
-		max-width: 2.5em;
-		max-height: 2.5em;
-		display: block;
-		margin: auto;
-	}
-}
diff --git a/js/htk/columns/link/index.js b/js/htk/columns/link/index.js
deleted file mode 100644
index 0d5fab23..00000000
--- a/js/htk/columns/link/index.js
+++ /dev/null
@@ -1,35 +0,0 @@
-
-module.exports = new Class({
-	Extends: Htk.Column
-	,Tag: 'htk-column-link'
-	,Properties: {
-		/**
-		 * The link url.
-		 */
-		href:{
-			type: String
-			,value: null
-		},
-		/**
-		 * the target where the link is opened.
-		 */
-		target:{
-			type: String
-			,value: null
-		}
-	}
-
-	,render(tr) {
-		var link = this.createElement('a');
-		link.href = this.href;
-		link.appendChild(this.createTextNode(this.value));
-		
-		if (this.target)
-			link.target = this.target;
-		
-		var td = Htk.Column.prototype.render.call(this, tr);
-		td.appendChild(link);
-		return td;
-	}
-});
-
diff --git a/js/htk/columns/radio/index.js b/js/htk/columns/radio/index.js
deleted file mode 100644
index f2cff5aa..00000000
--- a/js/htk/columns/radio/index.js
+++ /dev/null
@@ -1,32 +0,0 @@
-
-module.exports = new Class({
-	Extends: Htk.Column
-	,Tag: 'htk-column-radio'
-	,Properties: {
-		param:{
-			type: Vn.Param
-			,set(x) {
-				this.radioGroup.master = x;
-			}
-		}
-	}
-
-	,initialize(props) {
-		this._cssClass = 'cell-radio';
-		this.radioGroup = new Htk.RadioGroup(this.doc);
-		Htk.Column.prototype.initialize.call(this, props);
-	}
-
-	,render(tr) {
-		var td = Htk.Column.prototype.render.call(this, tr);
-
-		var radio = this.radioGroup.createButton(this.value);
-		td.appendChild(radio);
-
-		return td;
-	}
-	
-	,clear() {
-		this.radioGroup.clear();
-	}
-});
diff --git a/js/htk/columns/spin/index.js b/js/htk/columns/spin/index.js
deleted file mode 100644
index 09223409..00000000
--- a/js/htk/columns/spin/index.js
+++ /dev/null
@@ -1,64 +0,0 @@
-require('./style.scss');
-
-module.exports = new Class({
-	Extends: Htk.Column
-	,Tag: 'htk-column-spin'
-	,Properties: {
-		/**
-		 * The text to append to the number.
-		 */
-		unit:{
-			type: String
-			,value: null
-		},
-		/**
-		 * The number of decimal places to display.
-		 */
-		digits: {
-			type: Number
-			,value: 0
-		}
-	}
-	
-	,initialize(props) {
-		this._cssClass = 'cell-spin';
-		Htk.Column.prototype.initialize.call(this, props);
-	}
-	
-	,renderHeader() {
-		var th = Htk.Column.prototype.renderHeader.call(this, );
-		th.className = 'cell-spin';
-		return th;
-	}
-
-	,render(tr) {
-		var td = Htk.Column.prototype.render.call(this, tr);
-		
-		var valueString = null;
-		
-		if (this.value !== null && this.value !== undefined)
-			valueString = new Number(this.value).toFixed(this.digits);
-
-		if (this.editable) {
-			var entry = this.createElement('input');
-			entry.type = 'text';
-			entry.addEventListener('change', this.inputChanged.bind(this, tr, entry));
-			td.appendChild(entry);
-			
-			if (valueString)
-				entry.value = valueString;
-		} else if (valueString) {
-			if (this.unit)
-				valueString = valueString + this.unit;
-		
-			var text = this.createTextNode(valueString);
-			td.appendChild(text);
-		}
-
-		return td;
-	}
-	
-	,inputChanged(tr, entry) {
-		this.changed(tr, parseInt(entry.value));
-	}
-});
diff --git a/js/htk/columns/spin/style.scss b/js/htk/columns/spin/style.scss
deleted file mode 100644
index 33603fb3..00000000
--- a/js/htk/columns/spin/style.scss
+++ /dev/null
@@ -1,8 +0,0 @@
-
-th.cell-spin {
-	text-align: right;
-}
-td.cell-spin {
-	width: 2.5em;
-	text-align: right;
-}
diff --git a/js/htk/columns/text/index.js b/js/htk/columns/text/index.js
deleted file mode 100644
index b8efa69a..00000000
--- a/js/htk/columns/text/index.js
+++ /dev/null
@@ -1,50 +0,0 @@
-
-module.exports = new Class({
-	Extends: Htk.Column
-	,Tag: 'htk-column-text'
-	,Properties: {
-		/**
-		 * Format that applies to the value.
-		 */
-		format:{
-			type: String
-			,set(x) {
-				this._format = _(x);
-			}
-			,get() {
-				return this._format;
-			}
-		}
-	}
-	
-	,_format: null
-
-	,initialize(props) {
-		this._cssClass = 'cell-text';
-		Htk.Column.prototype.initialize.call(this, props);
-	}
-
-	,render(tr) {
-		var node;
-	
-		if (this.editable) {
-			var value = this.value ? this.value : '';
-
-			node = this.createElement('input');
-			node.type = 'text';
-			node.value = value;
-			node.addEventListener('changed',
-				this.inputChanged.bind(this, tr, node));
-		} else
-			node = this.createTextNode(
-				Vn.Value.format(this.value, this._format));
-
-		var td = Htk.Column.prototype.render.call(this, tr);
-		td.appendChild(node);
-		return td;
-	}
-	
-	,inputChanged(tr, node) {
-		this.changed(tr, node.value);
-	}
-});
diff --git a/js/htk/date-chooser/index.js b/js/htk/date-chooser/index.js
deleted file mode 100644
index 868aaa1c..00000000
--- a/js/htk/date-chooser/index.js
+++ /dev/null
@@ -1,73 +0,0 @@
-require('./style.scss');
-var Calendar = require('../calendar');
-
-module.exports = new Class({
-	Extends: Htk.Field
-	,Tag: 'htk-date-chooser'
-
-	,format: _('%a, %e %b %Y')
-	,calendar: null
-	,ignoreCalendarChange: false
-	
-	,render() {
-		const node = this.createRoot('button');
-		node.classList.add('input');
-		node.addEventListener('click', this._onClick.bind(this));
-
-		this.label = this.createElement('span');
-		node.appendChild(this.label);
-
-		const dropDown = new Htk.Icon({
-			name: 'expand_more'
-		});
-		node.appendChild(dropDown.node);
-
-		this.setEditable(this._editable);
-	}
-
-	,putValue(value) {
-		var dateString;
-
-		if (value instanceof Date)
-			dateString = Vn.Date.strftime(value, this.format);
-		else
-			dateString = '';
-
-		Vn.Node.setText(this.label, dateString);
-	}
-
-	,setEditable(editable) {
-		if (this.calendar) {		
-			this.calendar.disconnectByInstance(this);
-			this.calendar = null;
-		}
-		if (editable) {
-			this.calendar = new Calendar();
-			this.calendar.on('changed', this._onCalendarChange.bind(this));
-			
-			this.popup = new Htk.Popup();
-			this.popup.child = this.calendar;
-		}
-	}
-
-	,_onCalendarChange(calendar) {
-		if (this.ignoreCalendarChange)
-			return;
-	
-		this.popup.hide();
-		
-		var newDate = calendar.value;
-		this.putValue(newDate);
-		this.valueChanged(newDate);
-	}
-
-	,_onClick() {
-		this.ignoreCalendarChange = true;
-		this.calendar.value = this._value;
-		this.calendar.goToSelectedMonth();
-		this.ignoreCalendarChange = false;
-
-		this.popup.show(this.node);
-	}
-});
-
diff --git a/js/htk/date-chooser/style.scss b/js/htk/date-chooser/style.scss
deleted file mode 100644
index 5a464056..00000000
--- a/js/htk/date-chooser/style.scss
+++ /dev/null
@@ -1,17 +0,0 @@
-
-.htk-date-chooser {
-	display: flex;
-	align-items: center;
-	font-weight: normal;
-
-	& > span {
-		flex: 1;
-		text-overflow: ellipsis;
-		white-space: nowrap;
-		overflow: hidden;
-	}
-	& > .htk-icon {
-		flex: none;
-		color: #666;
-	}
-}
\ No newline at end of file
diff --git a/js/htk/dialog/index.js b/js/htk/dialog/index.js
deleted file mode 100644
index bc697810..00000000
--- a/js/htk/dialog/index.js
+++ /dev/null
@@ -1,161 +0,0 @@
-require('./style.scss');
-var Popup = require('../popup');
-
-/**
- * Class to show message dialogs with buttons.
- */
-var Dialog = new Class();
-module.exports = Dialog;
-
-var Button =
-{
-	 OK     : 1 << 1
-	,ACCEPT : 1 << 2
-	,CANCEL : 1 << 3
-	,RETRY  : 1 << 4
-	,YES    : 1 << 5
-	,NO     : 1 << 6
-};
-
-var labels =
-[{
-	response: Button.NO
-	,label: 'No'
-},{
-	response: Button.CANCEL
-	,label: 'Cancel'
-},{
-	response: Button.RETRY
-	,label: 'Retry'
-},{
-	response: Button.ACCEPT
-	,label: 'Accept'
-},{
-	response: Button.OK
-	,label: 'Ok'
-},{
-	response: Button.YES
-	,label: 'Yes'
-}];
-
-Button.CANCEL_ACCEPT = Button.CANCEL | Button.ACCEPT;
-Button.RETRY_CANCEL = Button.RETRY | Button.CANCEL;
-Button.YES_NO = Button.YES | Button.NO;
-
-Dialog.extend({
-	 Button: Button
-});
-
-Dialog.implement({
-	Extends: Popup
-	,Tag: 'htk-dialog'
-	,Properties:
-	{
-		/**
-		 * The message displayed to the user.
-		 */
-		message:
-		{ 
-			type: String
-			,set(x) {
-				this._message = x;
-			}
-			,get() {
-				return this._message;
-			}
-		}
-		/**
-		 * The dialog icon.
-		 */
-		,icon:
-		{ 
-			type: String
-			,set(x) {
-				this._icon = x;
-			}
-			,get() {
-				return this._icon;
-			}
-		}
-		/**
-		 * The dialog buttons.
-		 */
-		,buttons:
-		{
-			enumType: Button
-			,set(x) {
-				this._buttons = x;
-			}
-			,get() {
-				return this._buttons;
-			}
-		}
-	}
-	
-	,_modal: true
-	,_icon: 'info'
-	,_buttons: Button.ACCEPT
-	
-	,open() {
-		Popup.prototype.open.call(this);
-	
-		// Dialog body
-
-		var root = this.createElement('div');
-		root.className = 'htk-dialog';
-		
-		var body = this.createElement('div');
-		root.appendChild(body);
-		
-		if (this._icon) {
-			var icon = new Htk.Icon({
-				doc: this.doc,
-				icon: this._icon
-			});
-			body.appendChild(icon.node);
-		}
-		
-		var p = this.createElement('p');
-		body.appendChild(p);
-		
-		if (this._message)
-			p.appendChild(this.createTextNode(this._message));
-		
-		var clear = this.createElement('div');
-		clear.style.clear = 'both';
-		body.appendChild(clear);
-
-		// Button bar
-		
-		var buttonBar = this._buttonBar = this.createElement('div');
-		buttonBar.className = 'button-bar';
-		root.appendChild(buttonBar);
-		
-		var i = labels.length;
-
-		while (i--)
-		if (this._buttons & labels[i].response)
-			this.createButton(_(labels[i].label), labels[i].response);
-		
-		var clear = this.createElement('div');
-		clear.style.clear = 'both';
-		root.appendChild(clear);
-
-		this.childNode = root;
-	}
-
-	,hide(response) {
-		if (!this._isOpen) return;
-		Popup.prototype.hide.call(this);
-		this.emit('response', response);
-	}
-	
-	,createButton(label, response) {
-		var button = this.createElement('button');
-		button.className = 'thin';
-		button.appendChild(this.createTextNode(label));
-		button.addEventListener('click',
-			this.hide.bind(this, response));
-		this._buttonBar.appendChild(button);
-	}
-});
diff --git a/js/htk/dialog/style.scss b/js/htk/dialog/style.scss
deleted file mode 100644
index e2073089..00000000
--- a/js/htk/dialog/style.scss
+++ /dev/null
@@ -1,25 +0,0 @@
-
-.htk-dialog {
-	padding: 1.5em;
-	max-width: 20em;
-	font-weight: normal;
-	color: #555;
-
-	p {
-		margin: 0;
-	}
-	img {
-		float: left;
-		height: 3em;
-		margin-top: 0;
-		margin-right: 1em;
-	}
-	p {
-		padding: 0;
-	}
-	.button-bar > button {
-		float: right;
-		margin-left: 1em;
-		margin-top: .5em;
-	}
-}
\ No newline at end of file
diff --git a/js/htk/entry/index.js b/js/htk/entry/index.js
deleted file mode 100644
index e2e0da51..00000000
--- a/js/htk/entry/index.js
+++ /dev/null
@@ -1,74 +0,0 @@
-
-module.exports = new Class({
-	Extends: Htk.Field
-	,Tag: 'htk-entry'
-	,Properties: {
-		/**
-		 * Displayed text when there is no content.
-		 */
-		placeholder:
-		{ 
-			type: String
-			,set(x) {
-				this.node.placeholder = x;
-			}
-			,get() {
-				return this.node.placeholder;
-			}
-		},
-		/**
-		 * Whether is disabled.
-		 */
-		disabled:
-		{ 
-			type: Boolean
-			,set(x) {
-				this.node.disabled = x;
-			}
-			,get() {
-				return this.node.disabled;
-			}
-		},
-		/**
-		 * Whether is readonly data.
-		 */
-		 readonly:
-		{ 
-			type: Boolean
-			,set(x) {
-				this.node.readonly = x;
-			}
-			,get() {
-				return this.node.readonly;
-			}
-		}
-	}
-	
-	,render() {
-		var node = this.createRoot('input');
-		node.type = 'text';
-		node.addEventListener('change', this._onChange.bind(this));
-	}
-
-	,_onChange() {
-		var newValue;
-	
-		if (this.node.value == '')
-			newValue = null;
-		else
-			newValue = this.node.value;
-
-		this.valueChanged(newValue);
-	}
-
-	,putValue(value) {
-		if (!value)
-			this.node.value = '';
-		else
-			this.node.value = value;
-	}
-
-	,setEditable(editable) {
-		this.node.readOnly = !editable;
-	}
-});
diff --git a/js/htk/field/index.js b/js/htk/field/index.js
deleted file mode 100644
index d8b7102d..00000000
--- a/js/htk/field/index.js
+++ /dev/null
@@ -1,156 +0,0 @@
-
-var Component = require('vn/component');
-
-module.exports = new Class({
-	Extends: Component
-	,Implements: Vn.ParamIface
-	,Tag: 'htk-field'
-	,Child: 'param'
-	,Properties: {
-		value: {
-			type: String
-			,set(x) {
-				if (Vn.Value.compare(x, this._value))
-					return;
-
-				if (x instanceof Date)
-					x = x.clone();
-
-				this.valueChanged(x);
-				this.putValue(x);
-				this._notifyChanges();
-			}
-			,get() {
-				return this._value;
-			}
-		},
-		param: {
-			type: Vn.ParamIface
-			,set(x) {
-				this._setParam(x);
-			}
-			,get() {
-				return this._param;
-			}
-		},
-		lot: {
-			type: Vn.LotIface
-			,set(x) {
-				this._setLot(x);
-			}
-			,get() {
-				return this._lot;
-			}
-		},
-		name: {
-			type: String
-			,set(x) {
-				this._setName(x);
-			}
-			,get() {
-				return this._name;
-			}
-		},
-		oneWay: {
-			type: Boolean
-			,set(x) {
-				this._oneWay = x;
-			}
-			,get() {
-				return this._oneWay;
-			}
-		},
-		oneTime: {
-			type: Boolean
-			,set(x) {
-				this._oneTime = x;
-			}
-			,get() {
-				return this._oneTime;
-			}
-		},
-		editable: {
-			type: Boolean
-			,set(x) {
-				if (x != this._editable) {
-					this._editable = x;
-					this.setEditable(x);
-				}
-			}
-			,get() {
-				return this._editable;
-			}
-		},
-		form: {
-			type: Db.Iterator
-			,set(x) {
-				this.lot = x;
-			}
-			,get() {
-				return this._lot;
-			}
-		},
-		column: {
-			type: String
-			,set(x) {
-				this.name = x;
-			}
-			,get() {
-				return this._name;
-			}
-		},
-		conditionalFunc: {
-			type: Function
-			,value: null
-		}
-	}
-
-	,_editable: true
-	,_lockField: false
-
-	,_setValue(newValue) {
-		if (!this._putValue(newValue))
-			return;
-
-		if (!this._lockField)
-			this.putValue(newValue);
-
-		if (this.conditionalFunc)
-			this.conditionalFunc(this, newValue);
-
-		const node = this.node;
-		if (node && node.nodeType === Node.ELEMENT_NODE)
-			node.classList.toggle('filled', newValue !== undefined);
-
-		this._notifyChanges();
-	}
-
-	/**
-	 * Virtual method that must be implemented by class childs to set the entry
-	 * editable.
-	 *
-	 * @param {Boolean} editable Whether the user is allowed to edit the entry
-	 */
-	,setEditable() {}
-
-	/**
-	 * Virtual method that must be implemented by class childs to put the value
-	 * on the associated entry.
-	 *
-	 * @param {Object} value The new value for the entry
-	 */
-	,putValue() {}
-
-	/**
-	 * Protected method that should be called from class childs when the value
-	 * on the associated entry changes.
-	 *
-	 * @param {Object} value The new entry value
-	 */
-	,valueChanged(value) {
-		this._lockField = true;
-		this._setValue(value);
-		this._lockField = false;
-	}
-});
-
diff --git a/js/htk/full-image/index.js b/js/htk/full-image/index.js
deleted file mode 100644
index e643fba8..00000000
--- a/js/htk/full-image/index.js
+++ /dev/null
@@ -1,79 +0,0 @@
-require('./style.scss');
-var Popup = require('../popup');
-var Spinner = require('../spinner');
-
-module.exports = new Class
-({
-	Extends: Vn.Object
-	,Properties:
-	{
-		/**
-		 * Subdirectory where full images are allocated.
-		 */
-		fullDir:
-		{
-			type: String
-			,set(x) {
-				this._fullDir = x;
-			}
-			,get() {
-				return this._fullDir;
-			}
-		}
-	}
-
-	,show(src) {
-		var popup = new Popup({class: 'htk-full-image', modal: true});
-
-		var img = document.createElement('img');
-		img.className = 'htk-full-image';
-		img.addEventListener('click', this._onImageClick.bind(this, popup));
-		//img.addEventListener ('error', this._onImageError.bind (this, popup));
-		img.src = src;
-		
-		if (!img.complete) {
-			img.addEventListener('load', this._onImageLoad.bind(this, popup, img));
-
-			var spinner = new Spinner();
-			spinner.start();
-			popup.child = spinner;
-		} else
-			this._onImageLoad(popup, img);
-		
-		popup.open();
-	}
-	
-	,_onImageLoad(popup, img) {
-		var scale = null;
-		var width = img.width;
-		var height = img.height;
-		var innerWidth = Vn.Browser.getInnerWidth() - 50;
-		var innerHeight = Vn.Browser.getInnerHeight() - 50;
-	
-		if (width > innerWidth) {
-			scale = width / innerWidth;
-			height = parseInt(height / scale);
-			width = innerWidth;
-		}
-		if (height > innerHeight) {
-			scale = height / innerHeight;
-			width = parseInt(width / scale);
-			height = innerHeight;
-		}
-
-		if (scale !== null) {
-			img.style.width = width +'px';
-			img.style.height = height +'px';
-		}
-		
-		popup.childNode = img;
-		popup.reset();
-	}
-	
-	,_onImageClick(popup) {
-		popup.hide();
-	}
-
-	,_onImageError(popup) {}
-});
-
diff --git a/js/htk/full-image/style.scss b/js/htk/full-image/style.scss
deleted file mode 100644
index 8795818b..00000000
--- a/js/htk/full-image/style.scss
+++ /dev/null
@@ -1,12 +0,0 @@
-
-.htk-full-image {
-    img {
-       display: block;
-       cursor: pointer;
-   }
-   .htk-spinner {
-       background-color: #FFF;
-       margin: .6em;
-       display: block;
-   }
-}
diff --git a/js/htk/grid/index.js b/js/htk/grid/index.js
deleted file mode 100644
index fc11b7e0..00000000
--- a/js/htk/grid/index.js
+++ /dev/null
@@ -1,349 +0,0 @@
-require('./style.scss');
-var Component = require('vn/component');
-
-module.exports = new Class({
-	Extends: Component
-	,Tag: 'htk-grid'
-	,Child: 'model'
-	,Properties:
-	{
-		/**
-		 * The source data model.
-		 */
-		model: {
-			type: Db.Model
-			,set(x) {
-				this.link({_model: x},
-				{
-					 'status-changed': this.onModelChange
-					,'row-deleted': this.onRowDelete
-					,'row-updated': this.onRowUpdate
-					,'row-inserted': this.onRowInsert
-					,'updatable-changed': this.onUpdatableChange
-				});
-
-				var set = new Db.SimpleIterator({model: x});
-				this.link({_set: set});
-				
-				this.onUpdatableChange();
-				this.onModelChange();
-			}
-			,get() {
-				return this._model;
-			}
-		},
-		/**
-		 * Message that should be displayed when source model is not ready.
-		 */
-		emptyMessage: {
-			type: String
-			,value: null
-		},
-		/**
-		 * Wether to display the header with column titles.
-		 */
-		showHeader: {
-			type: Boolean
-			,set(x) {
-				this._showHeader = x;
-				this.thead.style.display = x ? 'table-header-group' : 'none';
-			}
-			,get() {
-				return this._showHeader;
-			}
-		}
-	}
-
-	,_model: null
-	,_set: null
-	,columns: new Array()
-	,internalColumn: null
-	,internalColumns: 0
-	,sortColumn: -1
-	,sortWay: null
-	,_showHeader: true
-	
-	,render() {
-		var table = this.createRoot('table');
-
-		var thead = this.createElement('thead');
-		table.appendChild(thead);
-		
-		this.thead = this.createElement('tr')
-		thead.appendChild(this.thead);
-		
-		this.tbody = this.createElement('tbody');
-		table.appendChild(this.tbody);
-	}
-	
-	,appendChild(child) {
-		this.appendColumn(child);
-	}
-
-	,removeClicked(column, value, row) {
-		if (confirm(_('ReallyDelete')))
-			this._model.deleteRow(row);
-	}
-
-	,onRowDelete(model, row) {
-		var tableRows = this.tbody.childNodes;
-		this.tbody.removeChild(tableRows[row]);
-		
-		for (var i = row; i < tableRows.length; i++)
-			tableRows[i].className = (i % 2) ? 'pair-row' : '';
-	
-		this.showNoRecordsFound();
-	}
-
-	,onRowInsert() {
-		this.buildRow(1);
-	}
-
-	,renderCell(row, column, tr) {
-		if (column.column)
-			column.value = this._model.data[row][column.column];
-
-		if (column.renderer) {
-			this._set.row = row;
-			column.renderer(column, this._set);
-		}
-
-		return column.render(tr);
-	}
-	
-	,refreshRow(row, columns) {
-		var x = this.columns;
-		var tr = this.tbody.childNodes[row];
-		
-		for (var i = 0; i < x.length; i++)
-		if (x[i].renderer || columns.indexOf(x[i].columnIndex) != -1) {
-			var cell = this.renderCell(row, x[i], tr);
-			tr.replaceChild(cell, tr.childNodes[i]);
-		}
-	}
-
-	,onRowUpdate(model, row, columns) {
-		this.refreshRow(row, columns);
-	}
-
-	,buildRow(count) {
-		for (var i = 0; i < count; i++) {
-			var tr = this.createElement('tr');
-		
-			if (i % 2)
-				tr.className = 'pair-row';
-
-			for (var j = 0; j < this.columns.length; j++) {
-				var cell = this.renderCell(i, this.columns[j], tr);
-				tr.appendChild(cell);
-			}
-
-			this.tbody.appendChild(tr);
-		}
-	}
-
-	,onUpdatableChange() {
-		if (this._model && this._model.updatable) {
-			if (!this.internalColumn) {
-				this.internalColumn = new Htk.ColumnButton({
-					 icon: 'delete'
-					,tip: _('Remove')
-				});
-				this.internalColumn.on('clicked', this.removeClicked, this);
-				this.insertInternalColumn(0, this.internalColumn);
-			}
-		} else if (this.internalColumn) {
-			this.internalColumn = null;
-			this.removeInternalColumn(0);
-		}
-	}
-
-	,onModelChange() {
-		var emptyMessage = this.emptyMessage ?
-			this.emptyMessage : _('NoData');
-	
-		if (!this._model) {
-			this.showMessage(emptyMessage, 'refresh');
-			return;
-		}
-
-		this._node.removeChild(this.tbody);
-		this.tbody = this.createElement('tbody');
-
-		switch (this._model.status) {
-			case Db.Model.Status.READY:
-			{
-				for (var i = 0; i < this.columns.length; i++)
-					this.columns[i].updateColumnName(this._model);
-			
-				this.buildRow(this._model.numRows);
-				this.showNoRecordsFound();
-				break;
-			}
-			case Db.Model.Status.LOADING:
-				this.showMessage(_('Loading'), null);
-				break;
-			case Db.Model.Status.CLEAN:
-				this.showMessage(emptyMessage, 'refresh');
-				break;
-			case Db.Model.Status.ERROR:
-				this.showMessage(_('ErrorLoadingData'), 'error');
-				break;
-		}
-
-		this._node.appendChild(this.tbody);
-	}
-
-	,showNoRecordsFound() {
-		if (this._model.numRows == 0)
-			this.showMessage(_('EmptyList'), 'block');
-	}
-
-	,showMessage(message, src) {
-		if (this.columns.length == 0)
-			return;
-	
-		var tr =  this.createElement('tr');
-		this.tbody.appendChild(tr);
-
-		var td = this.createElement('td');
-		td.className = 'message';
-		td.colSpan = this.columns.length;
-		tr.appendChild(td);
-		
-		if (src) {
-			const icon = new Htk.Icon({
-				name: src
-			});
-			td.appendChild(icon.node);
-		} else {
-			var spinner = new Htk.Spinner();
-			spinner.start();
-			td.appendChild(spinner.node);
-		}
-		
-		var message = this.createTextNode(message);
-		td.appendChild(message);
-	}
-	
-	,scrollToRow(row) {
-		if (row >= 0) {
-			var height = parseInt(this.tr.style.height);
-			this.node.scrollTop = (row - 2) * height;
-		
-			if (this.selectedRow)
-				this.selectedRow.style.backgroundColor = null;
-		
-			this.selectedRow = this.tbody.childNodes[row]
-			this.selectedRow.style.backgroundColor = '#AAD';
-		}
-	}
-
-	,sortModel(column) {
-		var columnName = column.column;
-
-		if (this._model && columnName != -1) {
-			if (this.sortColumn === columnName
-			&& this.sortWay === Db.Model.SortWay.ASC)
-				this.sortWay = Db.Model.SortWay.DESC;
-			else
-				this.sortWay = Db.Model.SortWay.ASC;
-
-			this.sortColumn = columnName;
-		
-			this._model.sortByName(columnName, this.sortWay);
-		}
-	}
-	
-	,columnChanged(column, row, newValue) {
-		var columnName = column.column;
-
-		if (columnName != -1)
-			this._model.set(row, columnName, newValue);
-	}
-	
-	,addColumn(pos, column) {
-		var header = column.renderHeader();
-
-		if (pos == -1 || pos >= this.columns.length) {
-			pos = this.columns.push(column) - 1;
-			this.thead.appendChild(header);
-		} else {
-			this.columns.splice(pos, 0, column);
-			this.thead.insertBefore(header, this.thead.childNodes[pos]);
-		}
-
-		header.addEventListener('click', 
-			this.sortModel.bind(this, column));
-		header.title = _('Sort');
-
-		column.on('changed', this.columnChanged, this);
-		
-		var rows = this.tbody.childNodes;
-		
-		if (this._model && this._model.numRows > 0)
-		for (var i = 0; i < rows.length; i++) {
-			var cell = this.renderCell(i, column, rows[i]);
-			rows[i].insertBefore(cell, rows[i].childNodes[pos+1]);
-		}
-
-		return pos;
-	}
-
-	,insertInternalColumn(pos, column) {
-		if (pos < 0 || pos > this.internalColumns)
-			pos = this.internalColumns;
-
-		this.internalColumns++;
-		return this.addColumn(pos, column);
-	}
-
-	,insertColumn(pos, column) {
-		if (pos > 0)
-			pos += this.internalColumns;
-
-		return this.addColumn(pos, column) - this.internalColumns;
-	}
-
-	,appendColumn(column) {
-		return this.insertColumn(-1, column);
-	}
-
-	,deleteColumn(pos) {
-		if (pos < 0 || pos >= this.columns.length)
-			return;
-
-		this.columns.splice(pos, 1);
-		this.thead.removeChild(this.thead.childNodes[pos]);
-		
-		var rows = this.tbody.childNodes;
-		
-		if (this._model && this._model.numRows > 0)
-		for (var i = 0; i < rows.length; i++)
-			rows[i].removeChild(rows[i].childNodes[pos]);
-	}
-
-	,removeInternalColumn(pos) {
-		if (this.internalColumns == 0)
-			return;
-	
-		if (pos < 0 || pos > this.internalColumns)
-			pos = this.internalColumns;
-	
-		this.deleteColumn(pos);
-		this.internalColumns--;
-	}
-
-	,removeColumn(pos) {
-		if (pos > 0)
-			pos += this.internalColumns;
-		
-		this.deleteColumn(pos);
-	}
-
-	,reloadModel() {
-		if (this._model != null)
-			this.onModelChange();
-	}
-});
-
diff --git a/js/htk/grid/style.scss b/js/htk/grid/style.scss
deleted file mode 100644
index a2a608db..00000000
--- a/js/htk/grid/style.scss
+++ /dev/null
@@ -1,63 +0,0 @@
-@import "../style/variables";
-
-.htk-grid {
-	margin: auto;
-	border-collapse: collapse;
-
-	& > thead > tr,
-	& > tfoot > tr {
-		background-color:  $color-primary;
-		vertical-align: middle;
-		height: 3em;
-	}
-	th {
-		color: white;
-		cursor: pointer;
-		font-weight: normal;
-		padding: 0 0.4em;
-	}
-	th:hover {
-		background-color: rgba(1, 1, 1, 0.2);
-	}
-	tr {
-		height: 3.5em;
-	}
-	& > tfoot a,
-	& > thead a {
-		color: black;
-	}
-	tr.pair-row {
-		background-color: transparent;
-	}
-	& > tbody tr {
-		border-top: 1px solid #DDD;
-	}
-	& > tbody tr:first-child {
-		border-top: none;
-	}
-	& > tbody td {
-		margin: 0;
-		padding: 0 0.5em;
-	}
-	th,
-	td {
-		text-align: left;
-	}
-	td:first-child,
-	th:first-child {
-		padding-left: 1em;
-	}
-	td:last-child,
-	th:last-child {
-		padding-right: 1em;
-	}
-	.message {
-		padding: 1.5em;
-		text-align: center;
-	}
-	.message > * {
-		display: inline-block;
-		vertical-align: middle;
-		padding-right: .8em;
-	}
-}
diff --git a/js/htk/htk.js b/js/htk/htk.js
deleted file mode 100644
index 5cc21c26..00000000
--- a/js/htk/htk.js
+++ /dev/null
@@ -1,54 +0,0 @@
-
-require('db/db');
-require('./style/index.scss');
-
-Htk = module.exports = {
-	 Popup        : require('./popup')
-	,Dialog       : require('./dialog')
-	,Toast        : require('./toast')
-	,Repeater     : require('./repeater')
-	,Grid         : require('./grid')
-	,Spinner      : require('./spinner')
-	,Icon         : require('./icon')
-	,FullImage    : require('./full-image')
-	,ImageEditor  : require('./image-editor')
-	,Assistant    : require('./assistant')
-	,AssistantBar : require('./assistant-bar')
-	,Step         : require('./step')
-	,Loader       : require('./loader')
-	,List         : require('./list')
-	,Field        : require('./field')
-	,Column       : require('./column')
-};
-
-var Fields = {
-	 Text         : require('./text')
-	,Html         : require('./html')
-	,Entry        : require('./entry')
-	,RadioGroup   : require('./radio/radio-group')
-	,Radio        : require('./radio')
-	,Label        : require('./label')
-	,TextArea     : require('./text-area')
-	,Spin         : require('./spin')
-	,Check        : require('./check')
-	,Select       : require('./select')
-	,Calendar     : require('./calendar')
-	,DateChooser  : require('./date-chooser')
-	,Image        : require('./image')
-	,Button       : require('./button')
-	,BarButton    : require('./bar-button')
-	,Table        : require('./table')
-	,SearchEntry  : require('./search-entry')
-	,ColumnButton : require('./columns/button')
-	,ColumnLink   : require('./columns/link')
-	,ColumnDate   : require('./columns/date')
-	,ColumnImage  : require('./columns/image')
-	,ColumnRadio  : require('./columns/radio')
-	,ColumnSpin   : require('./columns/spin')
-	,ColumnText   : require('./columns/text')
-	,ColumnCheck  : require('./columns/check')
-};
-
-for (var field in Fields)
-	Htk[field] = Fields[field];
-
diff --git a/js/htk/html/index.js b/js/htk/html/index.js
deleted file mode 100644
index a08c3efe..00000000
--- a/js/htk/html/index.js
+++ /dev/null
@@ -1,14 +0,0 @@
-
-module.exports = new Class
-({
-	Extends: Htk.Field
-	,Tag: 'htk-html'
-
-	,render() {
-		this.createRoot('div');
-	}
-
-	,putValue(value) {
-		this.node.innerHTML = value;
-	}
-});
diff --git a/js/htk/icon/index.js b/js/htk/icon/index.js
deleted file mode 100644
index 72dc2029..00000000
--- a/js/htk/icon/index.js
+++ /dev/null
@@ -1,51 +0,0 @@
-
-var Component = require('vn/component');
-
-module.exports = new Class({
-	Extends: Component
-	,Tag: 'htk-icon'
-	,Properties:
-	{
-		name: {
-			type: String
-			,set(x) {
-				this._icon = x;
-				this._setIcon();
-			}
-			,get() {
-				return this._icon;
-			}
-			
-		},
-		theme: {
-			type: String
-			,set(x) {
-				this._theme = x;
-				this._setIcon();
-			}
-			,get() {
-				return this._theme;
-			}
-		},
-		alt: {
-			type: String
-			,set(x) {
-				this.node.alt = x;
-			}
-			,get() {
-				return this.node.alt;
-			}
-		}
-	}
-
-	,_icon: null
-
-	,render() {
-		const node = this.createRoot('span');
-		node.classList.add('material-symbols-rounded');
-	}
-	
-	,_setIcon() {
-		this.node.innerText = this._icon;
-	}
-});
diff --git a/js/htk/image-editor/index.js b/js/htk/image-editor/index.js
deleted file mode 100644
index b83ac8ef..00000000
--- a/js/htk/image-editor/index.js
+++ /dev/null
@@ -1,60 +0,0 @@
-require('./style.scss');
-var Component = require('vn/component');
-var Toast = require('../toast');
-var Tpl = require('./ui.xml').default;
-
-/**
- * A form to handle the image database, it allows to add new images or
- * replace it.
- */
-module.exports = new Class({
-	Extends: Component,
-	Properties: {
-		/**
-		 * The REST connection used to upload the image.
-		 */
-		conn: {
-			type: Vn.JsonConnection
-		}
-	},
-	
-	initialize(props) {
-		this.loadTemplateFromString(Tpl);
-
-		this.$.form.onsubmit = () => {
-			this._onSubmit(); return false; 
-		};
-
-		Component.prototype.initialize.call(this, props);
-	},
-	
-	onNameChange() {
-		var newValue = this.$.name.value;
-		
-		if (!newValue)
-			newValue = null
-	
-		this.emit('name-changed', newValue);
-	},
-	
-	async _onSubmit() {
-		this.$.hiddenName.value = this.$.name.value;
-		this.$.submit.disabled = true;
-		this.$.spinner.start();
-
-		try {
-			await this.conn.sendFormMultipart(this.$.form);
-			Toast.showMessage(_('ImageAdded'));
-			this.emit('file-uploaded', this.$.name.value);
-		} finally {
-			this.$.submit.disabled = false;
-			this.$.spinner.stop();
-		}
-	},
-	
-	setData(image, directory) {
-		this.$.name.value = image;
-		this.$.schema.value = directory;
-	}
-});
-
diff --git a/js/htk/image-editor/style.scss b/js/htk/image-editor/style.scss
deleted file mode 100644
index e2d6f285..00000000
--- a/js/htk/image-editor/style.scss
+++ /dev/null
@@ -1,33 +0,0 @@
-
-.htk-image-editor {
-	width: 18em;
-	margin: 0 auto;
-	padding: 1.5em;
-
-	h2 {
-		color: white;
-		background-color: #009688;
-		text-align: left;
-		font-size: 1.3rem;
-		line-height: 1.7em;
-		font-weight: normal;
-		padding: 0.6em 0.8em;
-		margin: 0;
-	}
-	iframe {
-		display: none;
-	}
-	.footer {
-		margin-top: 2em;
-
-		& > .htk-spinner {
-			padding-right: 1.2em;
-			height: 1.3em;
-			width: 1.3em;
-		}
-		& > .htk-spinner,
-		& > input {
-			float: right;
-		}
-	}
-}
diff --git a/js/htk/image-editor/ui.xml b/js/htk/image-editor/ui.xml
deleted file mode 100644
index 4b36e302..00000000
--- a/js/htk/image-editor/ui.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<vn>
-<div id="main" class="htk-image-editor">
-	<div class="form-group">
-		<label for="name"><t>FileName</t></label>
-		<input id="name" type="text" on-change="onNameChange"/>
-	</div>
-	<form
-		id="form"
-		enctype="multipart/form-data">
-		<input type="hidden" name="srv" value="json:image/upload"/>
-		<input type="hidden" name="schema" id="schema"/>
-		<input type="hidden" name="name" id="hidden-name"/>
-		<div class="form-group">
-			<label for="file"><t>File</t></label>
-			<input id="file" type="file" name="image"/>
-		</div>
-		<div class="footer">
-			<input id="submit" type="submit" class="thin"/>
-			<htk-spinner id="spinner"/>
-			<div class="clear"/>
-		</div>
-	</form>
-</div>
-</vn>
diff --git a/js/htk/image/index.js b/js/htk/image/index.js
deleted file mode 100644
index efe3a752..00000000
--- a/js/htk/image/index.js
+++ /dev/null
@@ -1,203 +0,0 @@
-require('./style.scss');
-
-/**
- * Class to display or edit an image. Also it allows to show it's full version.
- */
-module.exports = new Class({
-	Extends: Htk.Field
-	,Tag: 'htk-image'
-	,Properties:
-	{
-		/**
-		 * The directory where the images are allocated.
-		 */
-		directory: {
-			type: String
-			,set(x) {
-				this._directory = x;
-				this._refreshSrc();
-			}
-			,get() {
-				return this._directory;
-			}
-		},
-		/**
-		 * The subdirectory where the images are allocated.
-		 */
-		subdir: {
-			type: String
-			,set(x) {
-				this._subdir = x;
-				this._refreshSrc();
-			}
-			,get() {
-				return this._subdir;
-			}
-		},
-		/**
-		 * The timestamp field of the last update, used for caching purposes.
-		 */
-		stampColumn: {
-			type: String
-			,set(x) {
-				this._stampColumn = x;
-				this._refreshSrc();
-			}
-			,get() {
-				return this._stampColumn;
-			}
-		},
-		/**
-		 * Whether to show the full image when mouse hover.
-		 */
-		fullDir: {
-			type: String
-			,set(x) {			
-				this._fullDir = x;
-				this._refreshClick();
-			}
-			,get() {
-				return this._fullDir;
-			}
-		},
-		/**
-		 * The REST connection used to upload the image.
-		 */
-		conn: {
-			type: Vn.JsonConnection
-		}
-	}
-
-	,_directory: null
-	,_subdir: null
-	,_fullDir: null
-	,_error: false
-	,_editable: false
-
-	,render() {
-		var node = this.createRoot('div');
-		
-		var img = this.img = this.createElement('img');
-		img.addEventListener('error', this._onImageError.bind(this));
-		node.appendChild(img);
-		
-		this.setEditable();
-		this._refreshClick();
-		this._refreshSrc();
-	}
-	
-	,_refreshClick() {
-		if (!this.node)
-			return;
-	
-		if (this.clickHandler) {
-			Vn.Node.removeClass(this.node, 'clickable');
-			this.node.removeEventListener('click', this.clickHandler);
-			this.clickHander = null;
-		}
-			
-		if (this._fullDir) {
-			this.clickHandler = this._onClick.bind(this);
-			this.node.addEventListener('click', this.clickHandler);
-			Vn.Node.addClass(this.node, 'clickable');
-		}
-	}
-	
-	,setEditable() {
-		if (!this.node)
-			return;
-
-		if (this.editButton) {
-			this.node.removeChild(this.editButton);
-			this.editButton = null;
-		}
-		if (this._editable) {
-			var button = this.createElement('button');
-			button.addEventListener('click', this._onEditClick.bind(this));
-			button.title = _('UpdateImage');
-			this.node.appendChild(button);
-			
-			var icon = new Htk.Icon({name: 'add_a_photo'});
-			button.appendChild(icon.node);
-
-			this.editButton = button;
-		}
-	}
-	
-	,_makeSrc(subdir) {
-		var src = Vn.Config.imageUrl +'/';
-	
-		if (this._directory)
-			src += this._directory +'/';
-		if (subdir)
-			src += subdir +'/';
-
-		src += this._value;
-		
-		if (this._stamp)
-			src += '?'+ this._stamp;
-		else if (this._stampColumn && this.form)
-			src += '?'+ this.form.$[this._stampColumn];
-	
-		return  src;
-	}
-
-	,_refreshSrc() {
-		if (!this.node)
-			return;
-
-		if (this._value) {
-			this._error = false;
-			this.img.src = this._makeSrc(this._subdir);
-		} else
-			delete this.img.src;
-	}
-
-	,putValue() {
-		this._refreshSrc();
-	}
-
-	,_onImageError() {
-		this._error = true;
-	}
-
-	,_onClick(event) {
-		if (!this._fullDir || !this._value || this._error
-		|| event.defaultPrevented)
-			return;
-
-		event.preventDefault();
-		(new Htk.FullImage()).show(this._makeSrc(this._fullDir));		
-	}
-	
-	,_onEditClick(event) {
-		if (event.defaultPrevented) return
-		event.preventDefault();
-
-		var editor = new Htk.ImageEditor({conn: this.conn});
-		editor.setData(this.value, this._directory);	
-		editor.on('name-changed', this._onNameChange, this);
-		editor.on('file-uploaded', this._onFileUpload, this);
-		editor.on('closed', this._onEditorClose, this);
-		
-		this.popup = new Htk.Popup({
-			modal: true,
-			child: editor
-		});
-		this.popup.show(this.node);
-	}
-
-	,_onNameChange(editor, value) {
-		this.value = value;
-	}
-	
-	,_onFileUpload(cell) {
-		this._stamp = new Date().getTime();
-		this._refreshSrc(cell);
-		this.popup.hide();
-	}
-
-	,_onEditorClose(editor) {
-		editor.disconnectByInstance(this);
-	}
-});
diff --git a/js/htk/image/style.scss b/js/htk/image/style.scss
deleted file mode 100644
index fdfceb41..00000000
--- a/js/htk/image/style.scss
+++ /dev/null
@@ -1,35 +0,0 @@
-
-.htk-image {
-	position: relative;
-	overflow: hidden;
-	transition: opacity 250ms ease-out;
-
-	&.clickable:hover {
-		cursor: pointer;
-		opacity: 0.85;
-	}
-	& > img {
-		display: block;
-		height: 100%;
-		width: 100%;
-	}
-	& > button {
-		position: absolute;
-		top: 0;
-		left: 0;
-		padding: 8px;
-		margin: 4px;
-		display: none;
-		background-color: rgba(255, 255, 255, .6);
-
-		&:hover {
-			background-color: rgba(255, 255, 255, .8);
-		}
-	}
-	&:hover > button {
-		display: block;
-	}
-	& > button > .htk-icon {
-		display: block;
-	}
-}
diff --git a/js/htk/label/index.js b/js/htk/label/index.js
deleted file mode 100644
index 5f9cbad4..00000000
--- a/js/htk/label/index.js
+++ /dev/null
@@ -1,34 +0,0 @@
-
-module.exports = new Class
-({
-	Extends: Htk.Field
-	,Tag: 'htk-label'
-	,Properties:
-	{
-		/**
-		 * Format that applies to the value.
-		 */
-		format:
-		{
-			type: String
-			,set(x) {
-				this._format = _(x);
-				this.putValue(this._value);
-			}
-			,get() {
-				return this._format;
-			}
-		}
-	}
-	
-	,_format: null
-
-	,render() {
-		this.createRoot('label');
-	}
-
-	,putValue(value) {
-		Vn.Node.setText(this.node,
-			Vn.Value.format(value, this._format));
-	}
-});
diff --git a/js/htk/list/index.js b/js/htk/list/index.js
deleted file mode 100644
index 1fe6bd72..00000000
--- a/js/htk/list/index.js
+++ /dev/null
@@ -1 +0,0 @@
-require('./style.scss');
diff --git a/js/htk/list/style.scss b/js/htk/list/style.scss
deleted file mode 100644
index adc60d14..00000000
--- a/js/htk/list/style.scss
+++ /dev/null
@@ -1,64 +0,0 @@
-@import "../style/classes";
-
-.htk-list {
-	a.item,
-	.item.clickable {
-		@extend %clickable;
-	}
-	.item {
-		padding: 20px;
-		border-bottom: 1px solid #DDD;
-		display: flex;
-		align-items: center;
-
-		& > .side {
-			flex: none;
-		}
-		& > .content {
-			flex: 1;
-			overflow: hidden;
-
-			& > .important {
-				font-weight: bold;
-				font-size: 1rem;
-				margin-bottom: .5em;
-			}
-			& > p {
-				margin: .1em 0;
-				text-overflow: ellipsis;
-				white-space: nowrap;
-				overflow: hidden;
-			}
-		}
-		& > .actions {
-			flex: none;
-			display: none;
-			align-items: center;
-
-			& > .htk-button {
-				margin: 0;
-			}
-			& > * {
-				display: inline-block;
-				vertical-align: middle;
-			}
-			& > input {
-				margin: .6em;
-			}
-		}
-		&:hover > .actions {
-			display: flex;
-		}
-		&:last-child {
-			border-bottom: none;
-		}
-	}
-
-	/* Mobile */
-
-	@include mobile {
-		.item > .actions {
-			display: initial;
-		}
-	}
-}
diff --git a/js/htk/loader/index.js b/js/htk/loader/index.js
deleted file mode 100644
index ee59627f..00000000
--- a/js/htk/loader/index.js
+++ /dev/null
@@ -1,70 +0,0 @@
-require('./style.scss');
-var Component = require('vn/component');
-
-module.exports = new Class({
-	Extends: Component
-	,Tag: 'htk-loader'
-	,Properties: {
-		form: {
-			type: Db.Form
-			,set(x) {
-				this.link({_form: x}, {'status-changed': this.onFormChange});
-				this.onFormChange();
-			}
-			,get() {
-				return this._form;
-			}
-		}
-	}
-
-	,initialize(props) {
-		Component.prototype.initialize.call(this, props);
-		this.createRoot('div');
-
-		var div = this.createElement('div');
-		div.className = 'spinner';
-
-		var spinner = new Htk.Spinner();
-		div.appendChild(spinner.node);
-
-		var childs = this.createElement('div');
-
-		this.spinner = spinner;
-		this.div = div;
-		this.childs = childs;
-		this.isLoading = true;
-		this.stop();
-	}
-
-	,appendChild(child) {
-		this.childs.appendChild(child);
-	}
-
-	,stop() {
-		if (!this.isLoading)
-			return;
-
-		this.isLoading = false;
-		this.spinner.stop();
-		Vn.Node.removeChilds(this.node);
-		this.node.appendChild(this.childs);
-	}
-
-	,start() {
-		if (this.isLoading)
-			return;
-
-		this.isLoading = true;
-		this.spinner.start();
-		Vn.Node.removeChilds(this.node);
-		this.node.appendChild(this.div);
-	}
-
-	,onFormChange() {
-		if (this._form.ready)
-			this.stop();
-		else
-			this.start();
-	}
-});
-
diff --git a/js/htk/loader/style.scss b/js/htk/loader/style.scss
deleted file mode 100644
index 5c42e10b..00000000
--- a/js/htk/loader/style.scss
+++ /dev/null
@@ -1,4 +0,0 @@
-
-.htk-loader > .spinner {
-	text-align: center;
-}
diff --git a/js/htk/locale/ca.yml b/js/htk/locale/ca.yml
deleted file mode 100644
index 3bb55c1d..00000000
--- a/js/htk/locale/ca.yml
+++ /dev/null
@@ -1,30 +0,0 @@
-'True': Sí
-'False': 'No'
-'Null': Nul
-ChangeDate: Cambiar Data
-Sort: Ordenar
-At: a les
-Of: de
-OfThe: del
-Remove: Esborrar
-Loading: Carregant
-Loading...: Carregant...
-ReallyDelete: Estàs segur que vols esborrar la línia?
-YouMustBeLoggedIn: Has d'estar registrat com a usuari
-EmptyList: Llistat buit
-NoData: Sense dades
-ErrorLoadingData: Error
-Error: Error
-Image: Imatge
-File: Arxiu
-FileName: Nom
-UpdateImage: Afegir o actualitzar Imatge
-UploadFile: Putjar arxiu
-ImageAdded: Imatge afegida correctament
-Close: Tancar
-Previous: Anterior
-Next: Següent
-Confirm: Confirmar
-Search: Cercar
-Search...: Cercar...
-Erase: Esborrar
diff --git a/js/htk/locale/en.yml b/js/htk/locale/en.yml
deleted file mode 100644
index 58547015..00000000
--- a/js/htk/locale/en.yml
+++ /dev/null
@@ -1,30 +0,0 @@
-'True': 'True'
-'False': 'False'
-'Null': 'Null'
-ChangeDate: Change date
-Sort: Sort
-At: at
-Of: of
-OfThe: of the
-Remove: Remove
-Loading: Loading
-Loading...: Loading...
-ReallyDelete: Are you sure you want to delete the line?
-YouMustBeLoggedIn: You must be a registered user
-EmptyList: Empty list
-NoData: No data
-ErrorLoadingData: Error
-Error: Error
-Image: Image
-File: File
-FileName: File name
-UpdateImage: Add or update an image
-UploadFile: Upload file
-ImageAdded: Image added successfully
-Close: Close
-Previous: Previous
-Next: Next
-Confirm: Confirm
-Search: Search
-Search...: Search...
-Erase: Erase
diff --git a/js/htk/locale/es.yml b/js/htk/locale/es.yml
deleted file mode 100644
index 4210301e..00000000
--- a/js/htk/locale/es.yml
+++ /dev/null
@@ -1,30 +0,0 @@
-'True': Si
-'False': 'No'
-'Null': Nulo
-ChangeDate: Cambiar Fecha
-Sort: Ordenar
-At: a las
-Of: de
-OfThe: del
-Remove: Borrar
-Loading: Cargando
-Loading...: Cargando...
-ReallyDelete: ¿Estás seguro de que quieres borrar la línea?
-YouMustBeLoggedIn: Debes estar registrado como usuario
-EmptyList: Lista vacía
-NoData: Sin datos
-ErrorLoadingData: Error
-Error: Error
-Image: Imagen
-File: Archivo
-FileName: Nombre
-UpdateImage: Añadir o actualizar imagen
-UploadFile: Subir archivo
-ImageAdded: Imagen añadida correctamente
-Close: Cerrar
-Previous: Anterior
-Next: Siguiente
-Confirm: Confirmar
-Search: Buscar
-Search...: Buscar...
-Erase: Borrar
diff --git a/js/htk/locale/fr.yml b/js/htk/locale/fr.yml
deleted file mode 100644
index 4bd0b2ca..00000000
--- a/js/htk/locale/fr.yml
+++ /dev/null
@@ -1,30 +0,0 @@
-'True': Si
-'False': Aucun
-'Null': Nul
-ChangeDate: Modification de la date
-Sort: Ordre
-At: à
-Of: de
-OfThe: de
-Remove: Effacer
-Loading: Chargement
-Loading...: Chargement...
-ReallyDelete: Voulez-vous vraiment supprimer la ligne?
-YouMustBeLoggedIn: Vous devez être un utilisateur enregistré
-EmptyList: Vider la liste
-NoData: Aucune donnée
-ErrorLoadingData: Erreur
-Error: Erreur
-Image: Image
-File: Archives
-FileName: Nom
-UpdateImage: Ajouter our mettre à jour l'image
-UploadFile: Télécharger le fichier
-ImageAdded: Image ajoutée correctement
-Close: Croche
-Previous: Précédent
-Next: Suivant
-Confirm: Confirmer
-Search: Recherche
-Search...: Recherche...
-Erase: Effacer
diff --git a/js/htk/locale/pt.yml b/js/htk/locale/pt.yml
deleted file mode 100644
index 17167706..00000000
--- a/js/htk/locale/pt.yml
+++ /dev/null
@@ -1,30 +0,0 @@
-'True': Sim
-'False': Não
-'Null': Nulo
-ChangeDate: Modificar Data
-Sort: Organizar
-At: às
-Of: de
-OfThe: de
-Remove: Eliminar
-Loading: Carregando
-Loading...: Carregando...
-ReallyDelete: Tens certeza que queres eliminar esta linha?
-YouMustBeLoggedIn: Deves estar registrado como usuario
-EmptyList: Lista vazia
-NoData: Sem dados
-ErrorLoadingData: Erro
-Error: Erro
-Image: Imagem
-File: Arquivo
-FileName: Nome
-UpdateImage: Adicionar ou atualizar imagem
-UploadFile: Subir arquivo
-ImageAdded: Imagen adicionada corretamente
-Close: Fechar
-Previous: Anterior
-Next: Seguinte
-Confirm: Confirmar
-Search: Procurar
-Search...: Procurar...
-Erase: Apagar
diff --git a/js/htk/popup/index.js b/js/htk/popup/index.js
deleted file mode 100644
index 1cd46375..00000000
--- a/js/htk/popup/index.js
+++ /dev/null
@@ -1,194 +0,0 @@
-require('./style.scss');
-var Component = require('vn/component');
-
-/**
- * Class to handle popups.
- */
-module.exports = new Class({
-	Extends: Component
-	,Tag: 'htk-popup'
-	,Properties: {
-		/**
-		 * The popup child.
-		 */
-		child: { 
-			type: Component
-			,set(x) {
-				this._child = x;
-				this._setChildNode(x.node);
-			}
-			,get() {
-				return this._child;
-			}
-		}
-		/**
-		 * The popup child Node.
-		 */
-		,childNode: { 
-			type: Object
-			,set(x) {
-				this._child = null;
-				this._setChildNode(x);
-			}
-			,get() {
-				return this.node.firstChild;
-			}
-		}
-		/**
-		 * Indicates how the dialog must be displayed.
-		 */
-		,modal: { 
-			type: Boolean
-			,set(x) {
-				this._modal = x;
-			}
-			,get() {
-				return this._modal;
-			}
-		}
-	}
-
-	,_parent: null
-	,_modal: false
-	,_isOpen: false
-	,_child: null
-
-	,initialize(props) {
-		this._bgMouseDownHandler = this._bgMouseDown.bind(this);
-		Component.prototype.initialize.call(this, props);
-	}
-	
-	,render() {
-		this.createRoot('div');
-	}
-
-	,_setChildNode(childNode) {
-		Vn.Node.removeChilds(this.node);
-		this.node.appendChild(childNode);
-	}
-
-	,show(parent, event) {
-		this._parent = parent;
-		this._lastEvent = event;
-		this.open();
-	}
-
-	,isModal() {
-		return this._modal || Vn.isMobile();
-	}
-	
-	,open() {
-		if (this._isOpen) {
-			this.reset();
-			return;
-		}
-	
-		this.node.addEventListener('mousedown', this._onMouseDown.bind(this));
-
-		if (this.isModal()) {
-			var bg = this._bg = this.createElement('div');
-			bg.className = 'htk-background';
-			bg.addEventListener('mousedown', this._bgMouseDownHandler);
-			Htk.Toast.pushTop(bg);
-
-			this.node.classList.add('modal');
-			bg.appendChild(this.node);
-
-			this.doc.body.appendChild(bg);
-			setTimeout(this._onOpacityTimeout.bind(this), 0);
-		} else {
-			this.doc.addEventListener('mousedown', this._bgMouseDownHandler);
-			this.doc.body.appendChild(this.node);
-		}
-		
-		this._isOpen = true;
-		this.reset();
-		setTimeout(this._onResetTimeout.bind(this), 0);
-	}
-	
-	,_onOpacityTimeout() {
-		if (this._bg)
-			this._bg.style.opacity = 1;
-	}
-
-	,_onResetTimeout() {
-		this.reset();
-	}
-	
-	,reset() {
-		if (!this._isOpen)
-			return;
-			
-		var node = this._node;
-
-		var style = node.style;
-		style.height = '';
-		style.width = '';
-
-		if (!this.isModal()) {
-			var margin = 20;
-			var dblMargin = margin * 2;
-			var width = node.offsetWidth;
-			var height = node.offsetHeight;
-			var innerWidth = window.innerWidth;
-			var innerHeight = window.innerHeight;
-	
-			if (width + dblMargin > innerWidth) {
-				width = innerWidth - dblMargin;
-				style.width = width +'px';
-			}
-			if (height + dblMargin > innerHeight) {
-				height = innerHeight - dblMargin;
-				style.height = height +'px';
-			}
-
-			var spacing = 4;
-			var rect = this._parent.getBoundingClientRect();
-			var left = rect.left;
-			var top = rect.top + spacing + this._parent.offsetHeight;
-
-			if (left + width > innerWidth)
-				left -= (left + width) - window.innerWidth + margin;
-			if (top + height > innerHeight)
-				top -= height + this._parent.offsetHeight + spacing * 2;
-
-			if (left < 0)
-				left = margin;
-			if (top < 0)
-				top = margin;
-
-			style.top = (top) +'px';
-			style.left = (left) +'px';
-		}
-	}
-
-	,hide() {
-		if (!this._isOpen)
-			return;
-
-		if (this._bg) {
-			Htk.Toast.popTop();
-			Vn.Node.remove(this._bg);
-			Vn.Node.removeClass(this._node, 'modal');
-			this._bg = null;
-		} else
-			this.doc.removeEventListener('mousedown', this._bgMouseDownHandler);
-
-		Vn.Node.remove(this._node);
-		this._parent = null;
-		this._isOpen = false;
-		this.emit('closed');
-	}
-	
-	,_bgMouseDown(e) {
-		if (e !== this._lastEvent)
-			this.hide();
-			
-		this._lastEvent = null;
-	}
-	
-	,_onMouseDown(e) {
-		this._lastEvent = e;
-	}
-});
-
diff --git a/js/htk/popup/style.scss b/js/htk/popup/style.scss
deleted file mode 100644
index 5f43d1ea..00000000
--- a/js/htk/popup/style.scss
+++ /dev/null
@@ -1,35 +0,0 @@
-
-.htk-popup {
-	z-index: 200;
-	display: block;
-	position: fixed;
-	overflow: auto;
-	background-color: white;
-	border-radius: 10px;
-	box-shadow: 0 0 0.4em rgba(1, 1, 1, 0.6);
-	box-sizing: content-box;
-
-	&.modal {
-		position: relative;
-		max-width: 100%;
-		max-height: 100%;
-	}
-	& > * {
-		border-radius: 0.1em;
-	}
-}
-.htk-background {
-	position: fixed;
-	display: flex;
-	align-items: center;
-	justify-content: center;
-	left: 0;
-	right: 0;
-	top: 0;
-	bottom: 0;
-	z-index: 190;
-	padding: 20px;
-	background-color: rgba(1, 1, 1, 0.7);
-	opacity: 0;
-	transition: opacity 200ms ease-in-out;
-}
diff --git a/js/htk/radio/index.js b/js/htk/radio/index.js
deleted file mode 100644
index 270a1f3f..00000000
--- a/js/htk/radio/index.js
+++ /dev/null
@@ -1,82 +0,0 @@
-
-var RadioGroup = require('./radio-group');
-
-module.exports = new Class({
-	Extends: Htk.Field
-	,Tag: 'htk-radio'
-	,Properties: {
-		tip: {
-			type: String
-			,set(x) {
-				if (x)
-					this.node.title = _(x);
-			}
-		},
-		val: {
-			type: String
-			,get() {
-				return this._val;
-			}
-			,set(x) {
-				this._val = x;
-				this.node.value = !x ? '' : x;
-				this._onRadioGroupChange();
-			}
-		},
-		name: {
-			type: String
-			,get() {
-				return this.node.name;
-			}
-			,set(x) {
-				this.node.name = x;
-			}
-		},
-		radioGroup: {
-			type: RadioGroup
-			,get() {
-				return this._radioGroup;
-			}
-			,set(x) {
-				if (this._radioGroup)
-					this._radioGroup.removeButton(this);
-
-				this.link({_radioGroup: x}, {'changed': this._onRadioGroupChange});
-				this.node.name = x.name;
-				x.buttons.push(this);
-				this._onRadioGroupChange();
-			}
-		}
-	}
-	
-	,_radioGroup: null
-
-	,render() {
-		var radio = Vn.Browser.createRadio('', this.doc);
-		radio.checked = false;
-		radio.addEventListener('change', this._onChange.bind(this));
-		this._node = radio;
-	}
-
-	,_onChange() {
-		if (this.node.checked && this._radioGroup)
-			this._radioGroup.value = this._val || this.value;
-	}
-	
-	,_onRadioGroupChange() {
-		const value = this._radioGroup.value;
-		this.node.checked =
-			value && (value == this._val || value == this.value);
-	}
-
-	,putValue(value) {
-		if (!value)
-			this.node.value = '';
-		else
-			this.node.value = value;
-	}
-
-	,setEditable(editable) {
-		this.node.disabled = !editable;
-	}
-});
diff --git a/js/htk/radio/radio-group.js b/js/htk/radio/radio-group.js
deleted file mode 100644
index ebeaaba2..00000000
--- a/js/htk/radio/radio-group.js
+++ /dev/null
@@ -1,45 +0,0 @@
-
-var htkRadioGroupUid = 0;
-
-module.exports = new Class({
-	Extends: Htk.Field
-	,Tag: 'htk-radio-group'
-	
-	,radioLock: false
-
-	,initialize(props) {
-		this.clear();
-		Htk.Field.prototype.initialize.call(this, props);
-	}
-	
-	,clear() {
-		this.name = htkRadioGroupUid++;
-		this.buttons = [];
-	}
-	
-	,createButton(value) {
-		var button = Vn.Browser.createRadio(this.name, this.doc);
-		button.value = value;
-		button.radioGroup = this;
-		return button;
-	}
-
-	,removeButton(button) {
-		for (var i = 0; i < this.buttons.length; i++)
-			if (this.buttons === button) {
-				this.buttons.splice(i, 1);
-				break;
-			}
-	}
-
-	/**
-	 * @return %true if there is an option selected, otherwise it returns %false
-	 */
-	,isSelected() {
-		for (var i = 0; i < this.buttons.length; i++)
-			if (this.buttons[i].value == this.value)
-				return true;
-
-		return false;
-	}
-});
diff --git a/js/htk/repeater/index.js b/js/htk/repeater/index.js
deleted file mode 100644
index 402894ca..00000000
--- a/js/htk/repeater/index.js
+++ /dev/null
@@ -1,231 +0,0 @@
-require('./style.scss');
-var Component = require('vn/component');
-
-module.exports = new Class({
-	Extends: Component
-	,Tag: 'htk-repeater'
-	,Child: 'model'
-	,Properties: {
-		/**
-		 * The source data model.
-		 */
-		model: {
-			type: Db.Model
-			,set(x) {
-				this.link({_model: x}, {
-					 'status-changed': this._onModelChange
-					,'row-deleted': this._onRowDelete
-					,'row-updated': this._onRowUpdate
-					,'row-inserted': this._onRowInsert
-				});
-				
-				this._onModelChange();
-			}
-			,get() {
-				this._model;
-			}
-		}
-		/**
-		 * The identifier for internal iterator.
-		 */
-		,formId: {
-			type: String
-			,set(x) {
-				this._formId = x;
-			}
-			,get() {
-				this._formId;
-			}
-		}
-		/**
-		 * {Function (Vn.BuilderResult, Db.Form)} Function to call after every
-		 * box rendering.
-		 */
-		,renderer: {
-			type: Function
-			,set(x) {
-				this._renderer = x;
-			}
-			,get() {
-				this._renderer;
-			}
-		}
-		/**
-		 * Wether to show the model status.
-		 */
-		,showStatus: {
-			type: Boolean
-			,set(x) {
-				this._showStatus = x;
-				this._onModelChange();
-			}
-			,get() {
-				this._showStatus;
-			}
-		}
-		/**
-		 * Message that should be displayed when source model is not ready.
-		 */
-		,emptyMessage: {
-			type: String
-			,value: null
-		}
-	}
-	
-	,_builder: null
-	,_formId: 'form'
-	,_showStatus: true
-	
-	,render() {
-		var div = this.createRoot('div');
-		
-		this._container = this.createElement('div');
-		this._container.className = 'htk-repeater';
-		div.appendChild(this._container);
-	}
-	
-	,loadXml(scope, node) {
-		Component.prototype.loadXml.call(this, scope, node);
-		this._parentScope = scope;
-
-		var builder = this._builder = new Vn.Builder();
-		builder.compileNode(node.firstElementChild, [this._formId]);
-
-		this._onModelChange();
-	}
-	
-	,getChild(index) {
-		return this._container.childNodes[index];
-	}
-	
-	,getBuilder(index) {
-		return this._childsData[index].scope;
-	}
-	
-	,getForm(index) {
-		return this._childsData[index].set;
-	}
-	
-	,_buildBox(index) {
-		var set = new Db.SimpleIterator({
-			model: this._model,
-			row: index
-		});
-
-		var scope = this._builder.load(this.doc, null, this._parentScope);
-		scope.link({
-			$iter: set,
-			[this._formId]: set.getObject()
-		});
-
-		this._childsData.push({scope, set});
-		
-		if (this._renderer)
-			this._renderer(scope, set);
-			
-		return scope.getMain();
-	}
-
-	,_onModelChange() {
-		if (!this._model || !this._builder)
-			return;
-
-		this.node.removeChild(this._container);
-		Vn.Node.removeChilds(this._container);
-
-		this._freeChildsData();
-		this._childsData = [];
-
-		switch (this._model.status) {
-			case Db.Model.Status.READY:
-			{
-				for (var i = 0; i < this._model.numRows; i++)
-					this._container.appendChild(this._buildBox(i));
-
-				this._showNoRecordsFound();
-				break;
-			}
-			case Db.Model.Status.LOADING:
-				this._showMessage(_('Loading'), null);
-				break;
-			case Db.Model.Status.CLEAN:
-			{	
-				var emptyMessage = this.emptyMessage ?
-					this.emptyMessage : _('NoData');
-				this._showMessage(emptyMessage, 'refresh');
-				break;
-			}
-			case Db.Model.Status.ERROR:
-				this._showMessage(_('ErrorLoadingData'), 'error');
-				break;
-		}
-	
-		this.node.appendChild(this._container);
-		this.emit('change');
-	}
-
-	,_showNoRecordsFound() {
-		if (this._model.numRows === 0)
-			this._showMessage(_('EmptyList'), 'block');
-	}
-
-	,_showMessage(message, src) {
-		if (!this._showStatus)
-			return;
-
-		var div =  this.createElement('div');
-		div.className = 'message';
-		this._container.appendChild(div);
-		
-		if (src) {
-			const icon = new Htk.Icon({
-				name: src
-			});
-			div.appendChild(icon.node);
-		} else {
-			var spinner = new Htk.Spinner();
-			spinner.start();
-			div.appendChild(spinner.node);
-		}
-		
-		div.appendChild(this.createTextNode(message));
-	}
-
-	,_onRowDelete(model, row) {
-		Vn.Node.remove(this._container.childNodes[row]);
-		this._unrefChildData(row);
-		this._childsData.splice(row, 1);		
-		
-		for (var i = row; i < this._model.numRows; i++)
-			this._childsData[i].set.row = i;
-		
-		this._showNoRecordsFound();
-	}
-
-	,_onRowUpdate(model, row) {
-		this._childsData[row].set.iterChanged();
-	}
-
-	,_onRowInsert(model, row) {
-		var box = this._buildBox(row);
-		this._container.appendChild(box);
-	}
-	
-	,_freeChildsData() {
-		if (this._childsData)
-		for (var i = 0; i < this._childsData.length; i++)
-			this._unrefChildData(i);
-	}
-	
-	,_unrefChildData(index) {
-		var childData = this._childsData[index];
-		childData.set._destroy();
-		childData.scope._destroy();
-	}
-	
-	,_destroy() {
-		this._freeChildsData();
-		Component.prototype._destroy.call(this);
-	}
-});
-
diff --git a/js/htk/repeater/style.scss b/js/htk/repeater/style.scss
deleted file mode 100644
index fc353a74..00000000
--- a/js/htk/repeater/style.scss
+++ /dev/null
@@ -1,16 +0,0 @@
-
-.htk-repeater {
-	& > .message {
-		padding: 1.5em;
-		text-align: center;
-
-		& > * {
-			vertical-align: middle;
-		}
-		& > span,
-		& > .htk-spinner {
-			display: inline-block;
-			padding-right: 10px;
-		}
-	}
-}
diff --git a/js/htk/search-entry/index.js b/js/htk/search-entry/index.js
deleted file mode 100644
index 379585c3..00000000
--- a/js/htk/search-entry/index.js
+++ /dev/null
@@ -1,48 +0,0 @@
-require('./style.scss');
-
-module.exports = new Class({
-	Extends: Htk.Field
-	,Tag: 'htk-search-entry'
-	
-	,render() {
-		var div = this.createRoot('div');
-		div.className = 'htk-search-entry';
-		
-		var icon = new Htk.Icon({
-			name: 'search',
-			alt: _('Search')
-		});
-		div.appendChild(icon.node);
-		
-		var input = this.createElement('input');
-		input.className = 'entry';
-		input.type = 'text';
-		input.placeholder = _('Search');
-		input.addEventListener('change', this._onChange.bind(this));
-		div.appendChild(input);
-
-		this._input = input;
-	}
-
-	,_onChange() {
-		var newValue;
-	
-		if (this._input.value === '')
-			newValue = undefined;
-		else
-			newValue = this._input.value;
-
-		this.valueChanged(newValue);
-	}
-
-	,putValue(value) {
-		if (!value)
-			this._input.value = '';
-		else
-			this._input.value = value;
-	}
-
-	,setEditable(editable) {
-		this.node.readOnly = !editable;
-	}
-});
diff --git a/js/htk/search-entry/style.scss b/js/htk/search-entry/style.scss
deleted file mode 100644
index 10c9601c..00000000
--- a/js/htk/search-entry/style.scss
+++ /dev/null
@@ -1,35 +0,0 @@
-
-.htk-search-entry {
-	display: flex;
-	align-items: center;
-	gap: 6px;
-	background-color: white;
-	height: 40px;
-	border-radius: 20px;
-	padding: 0 12px;
-	overflow: hidden;
-	flex: auto;
-	max-width: 300px;
-
-	& > * {
-		display: inline-block;
-		vertical-align: middle;
-	}
-	& > .htk-icon {
-		display: block;
-		margin: 0;
-		color: gray;
-	}
-	& > .entry {
-		flex: auto;
-		margin: 0;
-		border: none;
-		box-shadow: none;
-		padding-right: 0;
-		padding-left: 0;
-		height: inherit;
-	}
-	& > .entry:focus {
-		background-color: initial;
-	}
-}
\ No newline at end of file
diff --git a/js/htk/select/index.js b/js/htk/select/index.js
deleted file mode 100644
index c45066df..00000000
--- a/js/htk/select/index.js
+++ /dev/null
@@ -1,265 +0,0 @@
-require('./style.scss');
-var ColumnText = require('../columns/text');
-
-module.exports = new Class({
-	Extends: Htk.Field
-	,Implements: Db.Iterator
-	,Tag: 'htk-combo'
-	,Properties: {
-		/**
-		 * The model associated to this form.
-		 */
-		model: {
-			type: Db.Model
-			,set(x) {
-				this.link({_model: x}, {'status-changed-after': this._onModelChange});
-				this._onModelChange();
-			}
-			,get() {
-				return this._model;
-			}
-		},
-		/**
-		 * The row where the form positioned, has -1 if the row is unselected.
-		 */
-		row: {
-			type: Number
-			,set(x) {
-				if (!this._model || this._model.numRows <= x || x < -1)
-					x = -1;
-				if (x == this._row)
-					return;
-
-				this._row = x;
-				this.iterChanged();
-			}
-			,get() {
-				return this._row;
-			}
-		},
-		/**
-		 * The number of rows in the form.
-		 */
-		numRows:{
-			type: Number
-			,get() {
-				if (this._model)
-					return this._model.numRows;
-
-				return 0;
-			}
-		},
-		/**
-		 * Checks if the form data is ready.
-		 */
-		ready:{
-			type: Boolean
-			,get() {
-				return this._model && this._model.ready;
-			}
-		},
-		/**
-		 * Checks if the form data is ready.
-		 */
-		placeholder:{
-			type: String
-			,set(x) {
-				this._placeholder = x;
-				this._refreshShowText(x);
-			}
-			,get() {
-				return this._placeholder;
-			}
-		},
-		/**
-		 * Wether to allow null values.
-		 */
-		notNull:{
-			type: Boolean
-			,set(x) {
-				this._notNull = x;
-			}
-			,get() {
-				return this._notNull;
-			}
-		},
-		/**
-		 * The row object.
-		 */
-		$: {
-			type: Object
-			,get() {
-				return this._model.getObject(this._row) || {};
-			}
-		},
-		params: {
-			type: Object
-			,get() {
-				return this.$;
-			}
-		}
-	}
-	
-	,_row: -1
-	,_model: null
-	,valueColumnIndex: 0
-	,valueColumnName: null
-	,showColumnIndex: 1
-	,showColumnName: null
-	,_notNull: true
-	,_webkitRefresh: false
-
-	,render() {
-		const button = this.createRoot('button');
-		button.type = 'button';
-		button.classList.add('input');
-		button.addEventListener('mousedown',
-			e => this._onButtonMouseDown(e));
-
-		this.label = this.createElement('span');
-		button.appendChild(this.label);
-
-		const erase = new Htk.Icon({
-			name: 'close',
-			title: _('Erase')
-		});
-		erase.classList.add('erase');
-		erase.addEventListener('mousedown',
-			e => this._onEraseMouseDown(e));
-		button.appendChild(erase.node);
-
-		const dropDown = new Htk.Icon({
-			name: 'expand_more'
-		});
-		button.appendChild(dropDown.node);
-	}
-	
-	,_setRow(row) {
-		this._row = row;
-		this._refreshShowText();
-		this.iterChanged();
-	}
-	
-	,_onButtonMouseDown(event) {
-		if (this._popup) {
-			this._popup.hide();
-			return;
-		}
-
-		if (event.defaultPrevented) return;
-		event.preventDefault();
-	
-		var model = this._model;
-
-		var menu = this.createElement('div');
-		menu.className = 'htk-select-menu';
-		
-		var grid = new Htk.Grid({showHeader: false});
-		menu.appendChild(grid.node);
-		
-		var gridNode = grid.node;
-		gridNode.addEventListener('click', this._onGridClicked.bind(this, grid));
-		
-		var column = new ColumnText({columnIndex: this.showColumnIndex});
-		grid.appendColumn(column);
-		grid.model = model;
-		
-		var popup = this._popup = new Htk.Popup({childNode: menu});
-		popup.on('closed', this._onPopupClose.bind(this));
-		popup.show(this.node, event);
-
-		this.emit('menu-show');
-	}
-	
-	,_onGridClicked(grid, e) {
-		let cell;
-		let target = e.target;
-		
-		while (target !== grid.tbody) {
-			cell = target;
-			target = target.parentNode;
-		}
-
-		if (!cell) return;
-
-		let value;
-		const row = cell.rowIndex - 1;
-
-		if (row >= 0)
-			value = this._model.getByIndex(row, this.valueColumnIndex);
-		else
-			value = null;
-
-		this._setMyValue(row, value);
-		this._popup.hide();
-		
-		e.stopPropagation();
-	}
-
-	,_onEraseMouseDown(event) {
-		if (event.defaultPrevented) return;
-		event.preventDefault();
-		this._setMyValue(-1, undefined);
-	}
-
-	,_setMyValue(row, value) {
-		this._myValue = value;
-		this._setRow(row);
-		this.valueChanged(value);
-	}
-	
-	,_onPopupClose() {
-		this._popup = null;
-		this.emit('menu-hide');
-	}
-	
-	,_refreshShowText() {
-		const model = this._model;
-		let showText = '';
-
-		if (this._row !== -1)
-			showText = model.getByIndex(this._row, this.showColumnIndex);
-		else if (model && model.status === Db.Model.Status.LOADING)
-			showText = _('Loading...');
-		else if (this._myValue != null)
-			showText = this._myValue;
-		else if (this._placeholder)
-			showText = this._placeholder;
-
-		Vn.Node.setText(this.label, showText);
-	}
-	
-	,_onModelChange() {
-		var model = this._model;
-		this.emit('status-changed');
-		
-		if (this._popup)
-			this._popup.reset();
-
-		if (model && model.ready) {
-			this._selectOption();
-			this.emit('ready');
-		} else
-			this._setRow(-1);
-	}
-	
-	,setEditable(editable) {
-		this.node.disabled = !editable;
-	}
-
-	,_selectOption() {
-		var row;
-	
-		if (this._model && this._model.ready)
-			row = this._model.searchByIndex(this.valueColumnIndex, this._myValue);
-		else
-			row = -1;
-
-		this._setRow(row);
-	}
-
-	,putValue() {
-		this._myValue = this._value;
-		this._selectOption();
-	}
-});
diff --git a/js/htk/select/style.scss b/js/htk/select/style.scss
deleted file mode 100644
index ec3afe59..00000000
--- a/js/htk/select/style.scss
+++ /dev/null
@@ -1,58 +0,0 @@
-@import "../style/variables";
-@import "../style/classes";
-
-.htk-combo {
-	display: flex;
-	align-items: center;
-	font-weight: normal;
-	width: 100%;
-
-	& > span {
-		flex: 1;
-		text-overflow: ellipsis;
-		white-space: nowrap;
-		overflow: hidden;
-	}
-	& > .htk-icon {
-		flex: none;
-		color: #666;
-
-		&.erase {
-			display: none;
-		}
-	}
-	&:not(.filled) > span {
-		color: #666;
-	}
-	&.filled {
-		&:hover > .erase {
-			display: block;
-		}
-		@include mobile {
-			& > .erase {
-				display: initial;
-			}
-		}
-	}
-}
-.htk-select-menu {
-	min-width: 14em;
-
-	tbody > tr {
-		border-top: none;
-		height: 2.5em;
-	}
-	td.message {
-		padding: 1em;
-	}
-	tr:hover {
-		background-color: rgba(1, 1, 1, 0.1);
-		cursor: pointer;
-	}
-	td {
-		max-width: 11em;
-		overflow: hidden;
-		text-overflow: ellipsis;
-		white-space: nowrap;
-	}
-}
\ No newline at end of file
diff --git a/js/htk/spin/index.js b/js/htk/spin/index.js
deleted file mode 100644
index 8ef919f5..00000000
--- a/js/htk/spin/index.js
+++ /dev/null
@@ -1,38 +0,0 @@
-
-module.exports = new Class({
-	Extends: Htk.Field
-	,Tag: 'htk-spin'
-
-	,render() {
-		var input = this.createRoot('input');
-		this.node.type = 'number';
-		input.addEventListener('change', this._onChange.bind(this));
-
-		this.unit = null;
-		this.digits = 0;
-	}
-
-	,_onChange() {
-		var newValue = (this.node.value == '') ? null : parseFloat(this.node.value);
-		this.node.value = newValue;
-		this.valueChanged(newValue);
-	}
-
-	,putValue(value) {
-		var text;
-		
-		if (value != null) {
-			text = (new Number(value)).toFixed(this.digits);
-		
-			if (this.unit != null)
-				text += ' ' + this.unit;
-		} else
-			text = '';
-	
-		this.node.value = text;
-	}
-
-	,setEditable(editable) {
-		this.node.readOnly = !editable;
-	}
-});
diff --git a/js/htk/spinner/index.js b/js/htk/spinner/index.js
deleted file mode 100644
index fcc0b425..00000000
--- a/js/htk/spinner/index.js
+++ /dev/null
@@ -1,33 +0,0 @@
-require('./style.scss');
-var Component = require('vn/component');
-
-module.exports = new Class({
-	Extends: Component
-	,Tag: 'htk-spinner'
-	
-	,_started: false
-
-	,render() {
-		var loader = this.createRoot('div');
-		
-		var spin = this.spin = this.createElement('div');
-		loader.appendChild(spin);
-	}
-	
-	,start() {
-		if (this._started)
-			return;
-	
-		Vn.Node.addClass(this.spin, 'spinner');
-		this._started = true;
-	}
-	
-	,stop() {
-		if (!this._started)
-			return;
-
-		Vn.Node.removeClass(this.spin, 'spinner');
-		this._started = false;
-	}
-});
-
diff --git a/js/htk/spinner/style.scss b/js/htk/spinner/style.scss
deleted file mode 100644
index 3003ecf5..00000000
--- a/js/htk/spinner/style.scss
+++ /dev/null
@@ -1,31 +0,0 @@
-
-.htk-spinner {
-	width: 25px;
-	height: 25px;
-	position: relative;
-	display: inline-block;
-
-	& > .spinner {
-		left: 0;
-		position: absolute;
-		width: inherit;
-		height: inherit;
-		box-sizing: border-box;
-		border-radius: 50%;
-		border: 2px solid transparent;
-		border-top-color: #666;
-		border-left-color: #666;
-		animation: spinner 1s linear infinite;
-		-webkit-animation: spinner 1s linear infinite;
-	}
-	&.dark > .spinner {
-		border-top-color: white;
-		border-left-color: white;
-	}
-}
-@keyframes spinner {
-	to {transform: rotate(360deg);}
-}
-@-webkit-keyframes spinner {
-	to {-webkit-transform: rotate(360deg);}
-}
diff --git a/js/htk/step/index.js b/js/htk/step/index.js
deleted file mode 100644
index 1085ff0a..00000000
--- a/js/htk/step/index.js
+++ /dev/null
@@ -1,48 +0,0 @@
-
-var Component = require('vn/component');
-
-module.exports = new Class({
-	Extends: Component,
-	Tag: 'htk-step',
-	Properties: {
-		name: {
-			type: String,
-			value: null
-		},
-		validateFunc: {
-			type: Function,
-			value: null
-		},
-		showFunc: {
-			type: Function,
-			value: null
-		}
-	},
-
-	initialize(props) {
-		Component.prototype.initialize.call(this, props);
-		this.createRoot('div');
-	},
-
-	show() {
-		if (this.showFunc)
-			this.showFunc();
-		this.node.style.display = 'block';
-	},
-
-	hide() {
-		this.node.style.display = 'none';
-	},
-
-	validate() {
-		if (this.validateFunc)
-			return this.validateFunc();
-		return true;
-	},
-
-	appendChild(child) {
-		if (child instanceof Component)
-			child = child.node;
-		this.node.appendChild(child);
-	}
-});
diff --git a/js/htk/style/classes.scss b/js/htk/style/classes.scss
deleted file mode 100644
index 2dc505bf..00000000
--- a/js/htk/style/classes.scss
+++ /dev/null
@@ -1,26 +0,0 @@
-
-@import "variables";
-
-%box {
-	border-radius: .6em;
-	box-shadow: .05em .05em .2em rgba(0, 0, 0, .1);
-	overflow: hidden;
-	border: none;
-	background-color: white;
-}
-%clickable {
-	cursor: pointer;
-	transition: background-color 250ms ease-out;
-
-	&:hover,
-	&:focus {
-		background-color: $color-hover-cd;
-		outline: none;
-	}
-}
-
-@mixin mobile {
-	@media screen and (max-width: 960px) {
-		@content;
-	}
-}
diff --git a/js/htk/style/index.scss b/js/htk/style/index.scss
deleted file mode 100644
index 6bd86f10..00000000
--- a/js/htk/style/index.scss
+++ /dev/null
@@ -1,9 +0,0 @@
-
-@import "./variables";
-@import "./classes";
-@import "./spacing";
-@import "./text";
-@import "./width";
-@import "./responsive";
-@import "./material-symbols";
-@import "./style";
diff --git a/js/htk/style/material-symbols.scss b/js/htk/style/material-symbols.scss
deleted file mode 100644
index 6c59713d..00000000
--- a/js/htk/style/material-symbols.scss
+++ /dev/null
@@ -1,22 +0,0 @@
-/* fallback */
-@font-face {
-	font-family: 'Material Symbols Rounded';
-	font-style: normal;
-	font-weight: 400;
-	src: url(./material-symbols.woff2) format('woff2');
-}
-.material-symbols-rounded {
-	font-family: 'Material Symbols Rounded';
-	font-weight: normal;
-	font-style: normal;
-	font-size: 24px;
-	line-height: 1;
-	letter-spacing: normal;
-	text-transform: none;
-	display: inline-block;
-	white-space: nowrap;
-	word-wrap: normal;
-	direction: ltr;
-	-moz-font-feature-settings: 'liga';
-	-moz-osx-font-smoothing: grayscale;
-}
diff --git a/js/htk/style/material-symbols.woff2 b/js/htk/style/material-symbols.woff2
deleted file mode 100644
index e4c3b75c..00000000
Binary files a/js/htk/style/material-symbols.woff2 and /dev/null differ
diff --git a/js/htk/style/opensans.ttf b/js/htk/style/opensans.ttf
deleted file mode 100644
index e21ff5f1..00000000
Binary files a/js/htk/style/opensans.ttf and /dev/null differ
diff --git a/js/htk/style/poppins.ttf b/js/htk/style/poppins.ttf
deleted file mode 100644
index 9f0c71b7..00000000
Binary files a/js/htk/style/poppins.ttf and /dev/null differ
diff --git a/js/htk/style/responsive.scss b/js/htk/style/responsive.scss
deleted file mode 100644
index 24682ccd..00000000
--- a/js/htk/style/responsive.scss
+++ /dev/null
@@ -1,16 +0,0 @@
-
-// Standard
-html { font-size: 13px; }
-
-// Smartphone, portrait
-@media screen and (min-width:320px)  { html { font-size: 13px; } }
-// Smartphone, html
-@media screen and (min-width:480px)  { html { font-size: 13px; } }
-// Tablet, portrait
-@media screen and (min-width:600px)  { html { font-size: 13px; } }
-// Tablet, landscape
-@media screen and (min-width:801px)  { html { font-size: 13px; } }
-// Big screen and landscape tablets, laptop and desktop
-@media screen and (min-width:1025px) { html { font-size: 14px; } }
-// Hi-res laptop and desktop
-@media screen and (min-width:1281px) { html { font-size: 14px; } }
diff --git a/js/htk/style/roboto.ttf b/js/htk/style/roboto.ttf
deleted file mode 100644
index 8c082c8d..00000000
Binary files a/js/htk/style/roboto.ttf and /dev/null differ
diff --git a/js/htk/style/spacing.scss b/js/htk/style/spacing.scss
deleted file mode 100644
index 21ad73d3..00000000
--- a/js/htk/style/spacing.scss
+++ /dev/null
@@ -1,355 +0,0 @@
-/**
- * CSS spacing classes
- *
- * vn-[p|m][t|r|b|l|a|x|y]-[none|auto|xs|sm|md|lg|xl]
- *      T         D                     S
- * 
- * T - type
- *     - values: p (padding), m (margin)
- * 
- * D - direction
- *     - values:
- *             t (top), r (right), b (bottom), l (left),
- *             a (all), x (both left & right), y (both top & bottom)
- * 
- * S - size
- *     - values:
- *             none,
- *             auto (ONLY for specific margins: vn-ml-*, vn-mr-*, vn-mx-*),
- *             xs (extra small),
- *             sm (small),
- *             md (medium),
- *             lg (large),
- *             xl (extra large)
- */
- 
-@import "./variables";
-
-//++++++++++++++++++++++++++++++++++++++++++++++++ Padding
-
-// None
-
-.vn-pa-none {
-    padding: 0;
-}
-.vn-pl-none {
-    padding-left: 0;
-}
-.vn-pr-none {
-    padding-right: 0;
-}
-.vn-pt-none {
-    padding-top: 0;
-}
-.vn-pb-none {
-    padding-bottom: 0;
-}
-.vn-py-none {
-    padding-top: 0;
-    padding-bottom: 0;
-}
-.vn-px-none {
-    padding-left: 0;
-    padding-right: 0;
-}
-
-// Extra small
-
-.vn-pa-xs {
-    padding: $spacing-xs;
-}
-.vn-pl-xs {
-    padding-left: $spacing-xs;
-}
-.vn-pr-xs {
-    padding-right: $spacing-xs;
-}
-.vn-pt-xs {
-    padding-top: $spacing-xs;
-}
-.vn-pb-xs {
-    padding-bottom: $spacing-xs;
-}
-.vn-py-xs {
-    padding-top: $spacing-xs;
-    padding-bottom: $spacing-xs;
-}
-.vn-px-xs {
-    padding-left: $spacing-xs;
-    padding-right: $spacing-xs;
-}
-
-// Small
-
-.vn-pa-sm {
-        padding: $spacing-sm;
-}
-.vn-pl-sm {
-    padding-left: $spacing-sm;
-}
-.vn-pr-sm {
-    padding-right: $spacing-sm;
-}
-.vn-pt-sm {
-    padding-top: $spacing-sm;
-}
-.vn-pb-sm {
-    padding-bottom: $spacing-sm;
-}
-.vn-py-sm {
-    padding-top: $spacing-sm;
-    padding-bottom: $spacing-sm;
-}
-.vn-px-sm {
-    padding-left: $spacing-sm;
-    padding-right: $spacing-sm;
-}
-
-// Medium
-
-.vn-pa-md {
-    padding: $spacing-md;
-}
-.vn-pl-md {
-    padding-left: $spacing-md;
-}
-.vn-pr-md {
-    padding-right: $spacing-md;
-}
-.vn-pt-md {
-    padding-top: $spacing-md;
-}
-.vn-pb-md {
-    padding-bottom: $spacing-md;
-}
-.vn-py-md {
-    padding-top: $spacing-md;
-    padding-bottom: $spacing-md;
-}
-.vn-px-md {
-    padding-left: $spacing-md;
-    padding-right: $spacing-md;
-}
-
-// Large
-
-.vn-pa-lg {
-    padding: $spacing-lg;
-}
-.vn-pl-lg {
-    padding-left: $spacing-lg;
-}
-.vn-pr-lg {
-    padding-right: $spacing-lg;
-}
-.vn-pt-lg {
-    padding-top: $spacing-lg;
-}
-.vn-pb-lg {
-    padding-bottom: $spacing-lg;
-}
-.vn-py-lg {
-    padding-top: $spacing-lg;
-    padding-bottom: $spacing-lg;
-}
-.vn-px-lg {
-    padding-left: $spacing-lg;
-    padding-right: $spacing-lg;
-}
-
-// Extra large
-
-.vn-pa-xl {
-    padding: $spacing-xl;
-}
-.vn-pl-xl {
-    padding-left: $spacing-xl;
-}
-.vn-pr-xl {
-    padding-right: $spacing-xl;
-}
-.vn-pt-xl {
-    padding-top: $spacing-xl;
-}
-.vn-pb-xl {
-    padding-bottom: $spacing-xl;
-}
-.vn-py-xl {
-    padding-top: $spacing-xl;
-    padding-bottom: $spacing-xl;
-}
-.vn-px-xl {
-    padding-left: $spacing-xl;
-    padding-right: $spacing-xl;
-}
-
-//++++++++++++++++++++++++++++++++++++++++++++++++ Margin
-
-// None
-
-.vn-ma-none {
-    padding: 0;
-}
-.vn-ml-none {
-    padding-left: 0;
-}
-.vn-mr-none {
-    padding-right: 0;
-}
-.vn-mt-none {
-    padding-top: 0;
-}
-.vn-mb-none {
-    padding-bottom: 0;
-}
-.vn-my-none {
-    padding-top: 0;
-    padding-bottom: 0;
-}
-.vn-mx-none {
-    padding-left: 0;
-    padding-right: 0;
-}
-
-// Auto
-
-.vn-ml-none {
-    padding-left: auto;
-}
-.vn-mr-none {
-    padding-right: auto;
-}
-.vn-mx-none {
-    padding-left: auto;
-    padding-right: auto;
-}
-
-// Extra small
-
-.vn-ma-xs {
-    margin: $spacing-xs;
-}
-.vn-mt-xs {
-    margin-top: $spacing-xs;
-}
-.vn-ml-xs {
-    margin-left: $spacing-xs;
-}
-.vn-mr-xs {
-    margin-right: $spacing-xs;
-}
-.vn-mb-xs {
-    margin-bottom: $spacing-xs;
-}
-.vn-my-xs {
-    margin-top: $spacing-xs;
-    margin-bottom: $spacing-xs;
-}
-.vn-mx-xs {
-    margin-left: $spacing-xs;
-    margin-right: $spacing-xs;
-}
-
-// Small
-
-.vn-ma-sm {
-    margin: $spacing-sm;
-}
-.vn-mt-sm {
-    margin-top: $spacing-sm;
-}
-.vn-ml-sm {
-    margin-left: $spacing-sm;
-}
-.vn-mr-sm {
-    margin-right: $spacing-sm;
-}
-.vn-mb-sm {
-    margin-bottom: $spacing-sm;
-}
-.vn-my-sm {
-    margin-top: $spacing-sm;
-    margin-bottom: $spacing-sm;
-}
-.vn-mx-sm {
-    margin-left: $spacing-sm;
-    margin-right: $spacing-sm;
-}
-
-// Medium
-
-.vn-ma-md {
-    margin: $spacing-md;
-}
-.vn-mt-md {
-    margin-top: $spacing-md;
-}
-.vn-ml-md {
-    margin-left: $spacing-md;
-}
-.vn-mr-md {
-    margin-right: $spacing-md;
-}
-.vn-mb-md {
-    margin-bottom: $spacing-md;
-}
-.vn-my-md {
-    margin-top: $spacing-md;
-    margin-bottom: $spacing-md;
-}
-.vn-mx-md {
-    margin-left: $spacing-md;
-    margin-right: $spacing-md;
-}
-
-// Large
-
-.vn-ma-lg {
-    margin: $spacing-lg;
-}
-.vn-mt-lg {
-    margin-top: $spacing-lg;
-}
-.vn-ml-lg {
-    margin-left: $spacing-lg;
-}
-.vn-mr-lg {
-    margin-right: $spacing-lg;
-}
-.vn-mb-lg {
-    margin-bottom: $spacing-lg;
-}
-.vn-my-lg {
-    margin-top: $spacing-lg;
-    margin-bottom: $spacing-lg;
-}
-.vn-mx-lg {
-    margin-left: $spacing-lg;
-    margin-right: $spacing-lg;
-}
-
-/* Extra large */
-
-.vn-ma-xl {
-    margin: $spacing-xl;
-}
-.vn-mt-xl {
-    margin-top: $spacing-xl;
-}
-.vn-ml-xl {
-    margin-left: $spacing-xl;
-}
-.vn-mr-xl {
-    margin-right: $spacing-xl;
-}
-.vn-mb-xl {
-    margin-bottom: $spacing-xl;
-}
-.vn-my-xl {
-    margin-top: $spacing-xl;
-    margin-bottom: $spacing-xl;
-}
-.vn-mx-xl {
-    margin-left: $spacing-xl;
-    margin-right: $spacing-xl;
-}
diff --git a/js/htk/style/style.scss b/js/htk/style/style.scss
deleted file mode 100644
index e0b52c80..00000000
--- a/js/htk/style/style.scss
+++ /dev/null
@@ -1,314 +0,0 @@
-
-@import "./classes";
-
-@font-face {
-	font-family: 'Poppins';
-	src: url('poppins.ttf') format('truetype');
-}
-@font-face {
-	font-family: 'Open Sans';
-	src: url('opensans.ttf') format('truetype');
-}
-
-/* Global */
-
-body {
-	font-family: 'Poppins', 'Verdana', 'Sans';
-	background-color: #FAFAFA;
-	color: #333;
-	position: absolute;
-	height: 100%;
-	width: 100%;
-	margin: 0;
-	overflow: auto;
-	z-index: -2;
-}
-label,
-button,
-input,
-select,
-textarea,
-option {
-	font-size: inherit;
-	font-family: inherit;
-	color: inherit;
-}
-iframe {
-	border: none;
-}
-fieldset {
-	margin: 0;
-}
-form {
-	padding: 0;
-	margin: 0;
-}
-table {
-	width: 100%;
-}
-a:link,
-a:visited,
-a:active {
-	color: inherit;
-	text-decoration: none;
-}
-a:hover {
-	text-decoration: none;
-	cursor: pointer;
-}
-a img {
-	padding: 1px;
-}
-a img:hover {
-	opacity: 0.9;
-}
-p {
-	margin: 0.8em 0;
-}
-
-/* Focus outline */
-
-a:focus {
-	outline: 1px solid rgba(1, 1, 1, 0.15);
-	-moz-outline-radius: .1em;
-}
-input:focus,
-button:focus {
-	outline: 0;
-}
-button::-moz-focus-inner,
-input[type=submit]::-moz-focus-inner,
-input[type=button]::-moz-focus-inner,
-input[type=reset]::-moz-focus-inner {
-	border: none;
-}
-select:-moz-focusring {
-/*	color: transparent;
-    text-shadow: 0 0 0 #333;*/
-}
-input:-webkit-autofill {
-	-webkit-box-shadow: inset 0 0 0px 9999px white;
-}
-
-/* Inputs */
-
-input[type=text],
-input[type=password],
-input[type=file],
-input[type=number],
-textarea,
-select,
-.input {
-	border: 1px solid #ddd;
-	transition: border-color 100ms ease-in;
-	margin: .2em 0;
-	box-sizing: border-box;
-	color: #333;
-	border-radius: 0;
-	text-align: left;
-	width: 100%;
-
-	&:focus {
-		border-color: #333;
-	}
-}
-input[type=text],
-input[type=password],
-input[type=file],
-input[type=number],
-textarea,
-.input,
-select {
-	padding: .8em;
-}
-input[type=text],
-input[type=password],
-input[type=file],
-input[type=number],
-select,
-.input {
-	height: 2.8em;
-}
-textarea {
-	height: 3.5em;
-	width: 20em;
-}
-input[type=text]:disabled {
-	background-color: #f3f3f3;
-}
-input[type=checkbox],
-input[type=radio] {
-	cursor: pointer;
-	margin: 0;
-	margin-right: 10px;
-}
-select {
-	@extend %clickable;
-	background-color: transparent;
-	-moz-appearance: none;
-	appearance: none;
-	line-height: 1em;
-}
-option {
-	padding: .4em;
-	border-width: 0;
-	font-weight: normal;
-	font-size: 1rem;
-}
-select,
-option {
-	cursor: pointer;
-}
-
-/* Buttons */
-
-input[type=submit],
-input[type=button],
-input[type=reset],
-button,
-.button {
-	@extend %clickable;
-	border: none;
-	background-color: transparent;
-	padding: 8px;
-	border-radius: 22px;
-	font-weight: normal;
-
-	&:disabled {
-		background-color: rgba(0, 0, 0, .1);
-	}
-}
-.button {
-	display: inline-block;
-	text-align: center;
-	box-sizing: border-box;
-}
-
-/* Image */
-
-img.editable {
-	cursor: pointer;
-}
-
-/* Float */
-
-.clear {
-	clear: both !important;
-}
-
-/* Clickable */
-
-.clickable {
-	@extend %clickable;
-}
-
-/* Box */
-
-.box {
-	@extend %box;
-	margin: 0 auto;
-	box-sizing: border-box;
-
-	.header {
-		padding: 0.6em 0.8em;
-		margin: 0;
-		background-color: #009688;
-		color: white;
-
-		& > h1 {
-			color: white;
-			text-align: left;
-			font-size: 1.6rem;
-			line-height: 2em;
-			font-weight: normal;
-			display: inline;
-		}
-	}
-	.body {
-		padding: 2em;
-	}
-}
-
-/* Form */
-
-.form {
-	margin: 0 auto;
-}
-.form > h2 {
-	margin-bottom: .8em;
-}
-.form-group {
-	margin-bottom: 1.2em;
-
-	&:last-child {
-		margin-bottom: 0;
-	}
-	& > label {
-		display: block;
-		margin: 0;
-		margin-bottom: .2em;
-		color: #222;
-	}
-	& > input[type=text],
-	& > input[type=password],
-	& > input[type=file],
-	& > input[type=number],
-	& > select,
-	& > textarea {
-		margin: 0;
-		width: 100%;
-	}
-}
-
-/* Form */
-
-table.form {
-	padding: 1em;
-	border-collapse: separate;
-	border-spacing: 0.3em;
-}
-table.form td.label {
-	width: 45%;
-	text-align: right;
-}
-table.form tr {
-	height: 2.8em;
-}
-
-/* Icon */
-
-img.icon {
-	height: 1.5em;
-}
-
-/* Masonry */
-
-.masonry {
-	margin: 0 auto;
-	text-align: left;
-}
-.masonry-box {
-	width: 100%;
-	display: inline-block;
-	vertical-align: top;
-}
-@media screen and (min-width: 1000px) and (max-width: 1399px) {
-	.masonry-box
-	{
-		width: 50%;
-		display: block;
-		float: left;
-		clear: left;
-	}
-	.masonry-box:nth-child(2n+0)
-	{
-		float: right;
-		clear: right;
-	}
-}
-@media screen and (min-width: 1400px) {
-	.masonry-box { width: 33.3%; }
-}
-@media screen and (min-width: 2000px) {
-	.masonry-box { width: 25%; }
-}
diff --git a/js/htk/style/text.scss b/js/htk/style/text.scss
deleted file mode 100644
index 701a84d0..00000000
--- a/js/htk/style/text.scss
+++ /dev/null
@@ -1,70 +0,0 @@
-@import "./variables";
-
-/* Headings */
-
-.text-h1, h1 {
-    font-size: 2.3rem;
-}
-.text-h2, h2 {
-    font-size: 2.25rem;
-}
-.text-h3, h3 {
-    font-size: 2rem;
-}
-.text-h4, h4 {
-    font-size: 1.6rem;
-}
-.text-h5, h5 {
-    font-size: 1.3rem;
-}
-.text-h6, h6 {
-    font-size: 1.125rem;
-}
-.text-subtitle1 {
-    font-size: 1.06rem;
-}
-.text-subtitle2 {
-    font-size: 1rem;
-}
-.text-body1 {
-    font-size: .875rem;
-}
-.text-body2 {
-    font-size: .875rem;
-}
-.text-caption {
-    font-size: .875rem;
-}
-.text-overline {
-    font-size: .8rem;
-}
-
-h1, h2, h3, h4, h5, h6 {
-    padding: 0;
-    margin-top: 0;
-    margin-bottom: 4px;
-}
-
-/* Colors */
-
-.text-primary {
-    color: $color-main;
-}
-.text-secondary {
-    color: $color-font-light;
-}
-
-/* Helpers */
-
-.text-uppercase {
-    text-transform: uppercase;
-}
-.text-center {
-    text-align: center;
-}
-.text-right {
-    text-align: right;
-}
-.text-left {
-    text-align: left;
-}
diff --git a/js/htk/style/variables.scss b/js/htk/style/variables.scss
deleted file mode 100644
index 7d6ec396..00000000
--- a/js/htk/style/variables.scss
+++ /dev/null
@@ -1,28 +0,0 @@
-
-// Width
-
-$width-xs: 400px;
-$width-sm: 544px;
-$width-md: 800px;
-$width-lg: 1280px;
-$width-xl: 1600px;
-
-// Spacing
-
-$spacing-xs: 4px;
-$spacing-sm: 8px;
-$spacing-md: 16px;
-$spacing-lg: 32px;
-$spacing-xl: 70px;
-
-// Light theme
-
-$color-primary: #8cc63f;
-$color-hover-cd: rgba(0, 0, 0, .05);
-$color-main: #333;
-$color-font-light: #666;
-
-// Layout
-
-$side-panel-width: 250px;
-$navbar-height: 64px;
diff --git a/js/htk/style/width.scss b/js/htk/style/width.scss
deleted file mode 100644
index e017de3e..00000000
--- a/js/htk/style/width.scss
+++ /dev/null
@@ -1,26 +0,0 @@
-@import "./variables";
-
-%margin-auto {
-    margin-left: auto;
-    margin-right: auto;
-}
-.vn-w-xs {
-    @extend %margin-auto;
-    max-width: $width-xs;
-}
-.vn-w-sm {
-    @extend %margin-auto;
-    max-width: $width-sm;
-}
-.vn-w-md {
-    @extend %margin-auto;
-    max-width: $width-md;
-}
-.vn-w-lg {
-    @extend %margin-auto;
-    max-width: $width-lg;
-}
-.vn-w-xl {
-    @extend %margin-auto;
-    max-width: $width-xl;
-}
diff --git a/js/htk/table/index.js b/js/htk/table/index.js
deleted file mode 100644
index 6a232aa5..00000000
--- a/js/htk/table/index.js
+++ /dev/null
@@ -1,50 +0,0 @@
-
-var Entry = require('../entry');
-var ColumnRadio = require('../columns/radio');
-
-module.exports = new Class({
-	Extends: Entry
-	,Tag: 'htk-table'
-
-	,render() {
-		var tv = new Htk.TreeView();
-		this.node.appendChild(tv.node);
-		
-		var renderer = new ColumnRadio();
-		tv.appendColumn(0, renderer, '');
-		
-		var rbGroup = renderer.rbGroup;
-		rbGroup.addSignal('changed', this.changed, this);
-
-		this.treeview = tv;
-		this.rbGroup = rbGroup;
-	}
-
-	,setModel(model) {
-		this.treeview.setModel(model);
-		model.addSignal('status-changed', this.modelRefresh, this);
-		this.selectValue();
-	}
-
-	,changed() {
-		this.realValue = this.rbGroup.getValue();
-		this.emit('changed');
-	}
-
-	,selectValue() {
-		this.rbGroup.setValue(this.realValue);
-	}
-
-	,setRealValue() {
-		this.selectValue();
-	}
-
-	,modelRefresh(model, status) {
-		if (status == Db.Model.Status.READY)
-			this.selectValue();
-	}
-
-	,setEditable(editable) {
-		this.rbGroup.setEditable(editable);
-	}
-});
diff --git a/js/htk/text-area/index.js b/js/htk/text-area/index.js
deleted file mode 100644
index 8030d3f0..00000000
--- a/js/htk/text-area/index.js
+++ /dev/null
@@ -1,32 +0,0 @@
-
-module.exports = new Class({
-	Extends: Htk.Field
-	,Tag: 'htk-textarea'
-	
-	,render() {
-		var node = this.createRoot('textarea');
-		node.addEventListener('change', this.changed.bind(this));
-	}
-
-	,changed() {
-		var value;
-	
-		if (this.node.value == '')
-			value = null;
-		else
-			value = this.node.value;
-
-		this.valueChanged(value);
-	}
-
-	,setEditable(editable) {
-		this.node.readOnly = !editable;
-	}
-
-	,putValue(value) {
-		if (!value)
-			this.node.value = '';
-		else
-			this.node.value = value;
-	}
-});
diff --git a/js/htk/text/index.js b/js/htk/text/index.js
deleted file mode 100644
index 721d2e30..00000000
--- a/js/htk/text/index.js
+++ /dev/null
@@ -1,33 +0,0 @@
-
-module.exports = new Class
-({
-	Extends: Htk.Field
-	,Tag: 'htk-text'
-	,Properties:
-	{
-		/**
-		 * Format that applies to the value.
-		 */
-		format:
-		{
-			type: String
-			,set(x) {
-				this._format = _(x);
-				this.putValue(this._value);
-			}
-			,get() {
-				return this._format;
-			}
-		}
-	}
-	
-	,_format: null
-
-	,render() {
-		this._node = this.createTextNode('');
-	}
-
-	,putValue(value) {
-		this._node.nodeValue = Vn.Value.format(value, this._format);
-	}
-});
diff --git a/js/htk/toast/index.js b/js/htk/toast/index.js
deleted file mode 100644
index 94e3f9d6..00000000
--- a/js/htk/toast/index.js
+++ /dev/null
@@ -1,156 +0,0 @@
-require('./style.scss');
-
-/**
- * Class to show toast messages.
- */
-module.exports =
-{
-	 maxMessages: 6
-	,timeout: 10 /* Seconds */
-	,_container: null
-	,_timeouts: null
-	,_topHeap: []
-
-	/**
-	 * Shows a normal toast message.
-	 *
-	 * @param {String} message The message text
-	 */
-	,showMessage(message) {
-		this._showText(message, 'message');
-	}
-	
-	/**
-	 * Shows a warning toast message.
-	 *
-	 * @param {String} message The message text
-	 */
-	,showWarning(message) {
-		this._showText(message, 'warning');
-	}
-	
-	/**
-	 * Shows an error toast message.
-	 *
-	 * @param {String} message The message text
-	 */
-	,showError(message) {
-		this._showText(message, 'error');
-	}
-	
-	,pushTop(top) {
-		this._topHeap.push(top);
-		this._refreshPosition();
-	}
-	
-	,popTop() {
-		var top = this._topHeap.pop();
-		this._refreshPosition();
-		return top;
-	}
-
-	,_refreshPosition() {
-		if (!this._container)
-			return;
-		
-		var left;
-		var heapLen = this._topHeap.length;
-		
-		if (heapLen > 0) {
-			var top = this._topHeap[heapLen - 1];
-			var rect = top.getBoundingClientRect();
-			left = (rect.left + parseInt(rect.width / 2) - window.pageXOffset) +'px';
-		} else
-			left = '';
-
-		this._container.style.left = left;
-	}
-	
-	/**
-	 * Hides all currently displayed toast messages.
-	 */
-	,hide() {
-		if (!this._container)
-			return;
-
-		if (this._timeouts)
-		for (var i = 0; i < this._timeouts.length; i++)
-			clearTimeout(this._timeouts[i]);
-
-		this._timeouts = null;			
-
-		document.removeEventListener('mousedown', this.hideHandler);
-		Vn.Node.remove(this._container);
-		this._container = null;
-		this.nodes = [];
-		this.lastMessage = null;
-	}
-
-	,_createContainer() {
-		if (!this._container) {
-			var container = document.createElement('div');
-			container.className = 'htk-toast';
-			document.body.appendChild(container);
-
-			this.hideHandler = this.hide.bind(this);
-			document.addEventListener('mousedown', this.hideHandler);
-
-			this._timeouts = [];
-			this._container = container;
-		}
-
-		this._refreshPosition();
-	}
-
-	,_showText(message, className) {
-		if (!message) return;
-
-		const last = this.lastMessage;
-		if (last
-		&& last.message == message
-		&& last.className == className)
-			return;
-		this.lastMessage = {message, className};
-
-		this._createContainer();
-
-		if (this._timeouts.length >= this.maxMessages)
-			this._onMessageTimeout();
-		
-		var toast = document.createElement('div');
-		toast.className = className;
-		toast.addEventListener('mousedown', this._onMessageMouseDown);
-
-		var textNode = document.createTextNode(message);
-		toast.appendChild(textNode);
-
-		this._container.appendChild(toast);
-
-		var timeoutId = setTimeout(this._onMessageTimeout.bind(this), this.timeout * 1000);
-		this._timeouts.push(timeoutId);
-		
-		setTimeout(this._onShowToastTimeout.bind(this, toast), 50);
-	}
-	
-	,_onShowToastTimeout(toast) {
-		Vn.Node.addClass(toast, 'show');
-	}
-
-	,_onMessageTimeout() {
-		if (!this._container)
-			return;
-	
-		var nodes = this._container.childNodes;
-	
-		if (nodes.length > 0) {
-			clearTimeout(this._timeouts.shift());
-			Vn.Node.remove(nodes[0]);
-		}
-		if (nodes.length == 0)
-			this.hide();
-	}
-	
-	,_onMessageMouseDown(event) {
-		event.stopPropagation();
-	}
-};
diff --git a/js/htk/toast/style.scss b/js/htk/toast/style.scss
deleted file mode 100644
index 4334fa08..00000000
--- a/js/htk/toast/style.scss
+++ /dev/null
@@ -1,47 +0,0 @@
-.htk-toast {
-	z-index: 210;
-	display: block;
-	position: fixed;
-	left: 50%;
-	top: 4em;
-	width: 21em;
-	margin-left: -10.5em;
-	text-align: center;
-	overflow: auto;
-	max-height: 40em;
-	overflow: visible;
-
-	& > div {
-		margin: .5em 0;
-		padding: .5em 2%;
-		border-radius: 0.1em;
-		box-shadow: 0 0 0.4em rgba(1, 1, 1, 0.6);
-		width: 96%;
-	
-		opacity: 0;
-		transform: translateZ(0) translateY(-1em);
-		-webkit-transform: translateZ(0) translateY(-1em);
-	
-		transition-property: opacity, transform;
-		transition-duration: 200ms;
-		transition-timing-function: ease-out;
-
-		&.show {
-			opacity: 1;
-			transform: translateZ(0) translateY(0em);
-			-webkit-transform: translateZ(0) translateY(0em);
-		}
-	}
-	& > .message {
-		background-color: #BBFFBB;
-		color: #363;
-	}
-	& > .warning {
-		background-color: #FFE0B2;
-		color: #C30;
-	}
-	& > .error {
-		background-color: #FFCDD2;
-		color: #A00;
-	}
-}
\ No newline at end of file
diff --git a/js/sql/delete.js b/js/sql/delete.js
deleted file mode 100644
index e8e862fc..00000000
--- a/js/sql/delete.js
+++ /dev/null
@@ -1,17 +0,0 @@
-
-var Stmt = require('./stmt');
-
-/**
- * The equivalent of a SQL delete.
- */
-module.exports = new Class({
-	Extends: Stmt
-	,Tag: 'sql-delete'
-
-	,render(params) {
-		return 'DELETE FROM'
-			+ this.renderTarget(params)
-			+ this.renderIfSet(this.where, 'WHERE', params)
-			+ this.renderLimit(params);
-	}
-});
diff --git a/js/sql/dml.js b/js/sql/dml.js
deleted file mode 100644
index 4de0610a..00000000
--- a/js/sql/dml.js
+++ /dev/null
@@ -1,29 +0,0 @@
-
-var Stmt = require('./stmt');
-var Value = require('./value');
-var Field = require('./field');
-
-/**
- * The equivalent of a SQL DML.
- */
-module.exports = new Class({
-	Extends: Stmt
-	
-	,field: []
-	,expr: []
-
-	,addSet(fieldName, value) {
-		this.field.push(new Field({name: fieldName}));
-		this.expr.push(new Value({value: value}));
-	}
-
-	,addExpr(fieldName, expr) {
-		this.field.push(new Field({name: fieldName}));
-		this.expr.push(expr);
-	}
-
-	,delSet() {
-		this.field.splice(0, this.field.length);
-		this.expr.splice(0, this.expr.length);
-	}
-});
diff --git a/js/sql/expr.js b/js/sql/expr.js
deleted file mode 100644
index 35ac50cf..00000000
--- a/js/sql/expr.js
+++ /dev/null
@@ -1,11 +0,0 @@
-
-var Object = require('./object');
-
-/**
- * The equivalent of a SQL expression.
- */
-module.exports = new Class({
-	Extends: Object
-	,Tag: 'sql-expr'
-});
-
diff --git a/js/sql/field.js b/js/sql/field.js
deleted file mode 100644
index 2e7310f0..00000000
--- a/js/sql/field.js
+++ /dev/null
@@ -1,33 +0,0 @@
-
-var Expr = require('./expr');
-
-/**
- * The equivalent of a SQL field.
- *
- * @param {string} taget The name of the owner table
- */
-module.exports = new Class({
-	Extends: Expr
-	,Tag: 'sql-field'
-	,Properties: {
-		/**
-		 * The column name.
-		 */
-		name: {
-			type: String
-			,value: null
-		},
-		/**
-		 * The source table name or its alias if it has been specified.
-		 */
-		target: {
-			type: String
-			,value: null
-		}
-	}
-
-	,render() {
-		return this.renderPreIdent(this.target)
-			+ this.renderIdent(this.name);
-	}
-});
diff --git a/js/sql/filter-item.js b/js/sql/filter-item.js
deleted file mode 100644
index 345253a3..00000000
--- a/js/sql/filter-item.js
+++ /dev/null
@@ -1,62 +0,0 @@
-
-var Operation = require('./operation');
-var Value = require('./value');
-var Field = require('./field');
-
-/**
- * Objects to be used as an operands of @Sql.Filter. It represents a two
- * expressions basic operation composed by a table column, the operator and the
- * value extracted from the rendering paramerers.
- */
-module.exports = new Class({
-	Extends: Operation
-	,Tag: 'sql-filter-item'
-	,Properties: {
-		/**
-		 * The column name.
-		 */
-		field: {
-			type: String,
-			value: null
-		},
-		/**
-		 * The source table name or its alias if it has been specified.
-		 */
-		target: {
-			type: String,
-			value: null
-		},
-		/**
-		 * The parameter name.
-		 */
-		param: {
-			type: String,
-			value: null
-		}
-	}
-
-	/**
-	 * Checks if parameter name has been defined and if it has a value.
-	 */
-	,isReady(params) {
-		return this.param != null && params != null && params[this.param] != null;
-	}
-
-	,render(params) {
-		var newOp = new Operation({type: this.type});
-
-		newOp.push(new Field({
-			name: this.field,
-			target: this.target
-		}));
-
-		var value = params[this.param];
-		newOp.push(new Value({value: value}));
-			
-		return newOp.render(params);
-	}
-
-	,findHolders() {
-		return this.param ? [this.param] : null;
-	}
-});
diff --git a/js/sql/filter.js b/js/sql/filter.js
deleted file mode 100644
index ed904412..00000000
--- a/js/sql/filter.js
+++ /dev/null
@@ -1,49 +0,0 @@
-
-var Operation = require('./operation');
-var Value = require('./value');
-
-/**
- * The equivalent of a SQL filter expression. It allows to automatically build
- * SQL filters based on lot parameters.
- */
-module.exports = new Class({
-	Extends: Operation
-	,Tag: 'sql-filter'
-
-	/**
-	 * Checks if any of filters childs are ready.
-	 */
-	,isReady(params) {
-		var exprs = this.exprs;
-		for (var i = exprs.length; i--;)
-		if (exprs[i].isReady(params))
-			return true;
-
-		return false;
-	}
-
-	/**
-	 * Renders the filter as an SQL expression. If any of its childs isn't
-	 * ready is ommitted from the expression. If all of its childs aren't ready
-	 * renders the TRUE expression.
-	 */
-	,render(params) {
-		var newOp;
-		var newExprs = [];
-
-		this.exprs.forEach(function(expr) {
-			if (expr.isReady(params))
-				newExprs.push(expr);
-		})
-	
-		if (newExprs.length > 0)
-			newOp = new Operation({
-				type: this.type,
-				exprs: newExprs
-			});
-		else
-			newOp = new Value({value: true});
-			
-		return newOp.render(params);
-	}
-});
diff --git a/js/sql/function.js b/js/sql/function.js
deleted file mode 100644
index 0f8452d5..00000000
--- a/js/sql/function.js
+++ /dev/null
@@ -1,48 +0,0 @@
-
-var Expr = require('./expr');
-var ListHolder = require('./list-holder');
-
-/**
- * The equivalent of a SQL function.
- */
-module.exports = new Class({
-	Extends: Expr
-	,Tag: 'sql-function'
-	,Implements: ListHolder
-	,Properties: {
-		/**
-		 * The function name.
-		 */
-		name: {
-			type: String
-			,value: null
-		},
-		/**
-		 * The function schema.
-		 */
-		schema: {
-			type: String
-			,value: null
-		},
-		/**
-		 * The function parameters.
-		 */
-		params: {
-			type: Array
-			,set(x) {
-				this.list = x;
-			}
-			,get() {
-				return this.list;
-			}
-		}
-	}
-
-	,render(params) {
-		return this.renderPreIdent(this.schema)
-			+ this.renderIdent(this.name)
-			+ '('
-			+ this.renderListWs(this.list, params, ', ')
-			+ ')';
-	}
-});
diff --git a/js/sql/holder.js b/js/sql/holder.js
deleted file mode 100644
index 01345c48..00000000
--- a/js/sql/holder.js
+++ /dev/null
@@ -1,33 +0,0 @@
-
-var SqlObject = require('./object');
-var Value = require('./value');
-
-/**
- * A holder for another object.
- */
-module.exports = new Class({
-	Extends: SqlObject
-	,Properties: {
-		id: {
-			type: String
-			,value: null
-		}
-	}
-
-	,render(params) {
-		if (params) {
-			var object = params[this.id];
-
-			if (object !== undefined) {
-				if (!(object instanceof SqlObject)) {
-					var sqlValue = new Value();
-					sqlValue.value = object;
-					return sqlValue.render();
-				} else
-					return object.render(params);
-			}
-		}
-			
-		return '#'+ this.id;
-	}
-});
diff --git a/js/sql/insert.js b/js/sql/insert.js
deleted file mode 100644
index 1dad50cf..00000000
--- a/js/sql/insert.js
+++ /dev/null
@@ -1,19 +0,0 @@
-
-var Dml = require('./dml');
-
-/**
- * The equivalent of a SQL insert.
- */
-module.exports = new Class({
-	Extends: Dml
-
-	,render(params) {
-		return 'INSERT INTO'
-			+ this.renderTarget(params)
-			+ ' ('
-			+ this.renderListWs(this.field, params, ', ')
-			+ ') VALUES ('
-			+ this.renderListWs(this.expr, params, ', ')
-			+ ')';
-	}
-})
diff --git a/js/sql/join-item.js b/js/sql/join-item.js
deleted file mode 100644
index 0902df7e..00000000
--- a/js/sql/join-item.js
+++ /dev/null
@@ -1,48 +0,0 @@
-
-var Target = require('./target');
-var Expr = require('./expr');
-var SqlObject = require('./object');
-var Type = require('./join').Type;
-
-var TypeSql = [
-	'INNER',
-	'LEFT',
-	'RIGHT'
-];
-
-/**
- * The equivalent of a SQL join.
- */
-module.exports = new Class({
-	Extends: SqlObject
-	,Tag: 'sql-join-table'
-	,Properties: {
-		/**
-		 * The join type.
-		 */
-		type: {
-			enumType: Type
-			,value: 0
-		},
-		/**
-		 * The right target.
-		 */
-		target: {
-			type: Target
-			,value: null
-		},
-		/**
-		 * The join on condition.
-		 */
-		condition: {
-			type: Expr
-			,value: null
-		}
-	}
-
-	,render(params) {
-		return TypeSql[this.type] +' JOIN '
-			+ this.target.render(params)
-			+ this.renderIfSet(this.condition, 'ON', params);
-	}
-});
diff --git a/js/sql/join.js b/js/sql/join.js
deleted file mode 100644
index c23c520c..00000000
--- a/js/sql/join.js
+++ /dev/null
@@ -1,47 +0,0 @@
-
-var Target = require('./target');
-var ListHolder = require('./list-holder');
-
-/**
- * The equivalent of a SQL join.
- */
-var Klass = new Class();
-module.exports = Klass;
-
-var Type = {
-	INNER : 0,
-	LEFT  : 1,
-	RIGHT : 2
-};
-
-Klass.extend({
-	Type: Type
-});
-
-Klass.implement({
-	Extends: Target
-	,Implements: ListHolder
-	,Tag: 'sql-join'
-	,Properties: {
-		/**
-		 * The right targets.
-		 */
-		targets: {
-			type: Array
-			,set(x) {
-				this.list = x;
-			}
-			,get() {
-				return this.list;
-			}
-		}
-	}
-
-	,render(params) {
-		return '('
-			+ this.target.render(params)
-			+ ' '
-			+ this.renderList(this.list, params)
-			+ ')';
-	}
-});
diff --git a/js/sql/list-holder.js b/js/sql/list-holder.js
deleted file mode 100644
index ef05ad11..00000000
--- a/js/sql/list-holder.js
+++ /dev/null
@@ -1,61 +0,0 @@
-/**
- * Interface for array holders.
- */
-module.exports = new Class({
-	Properties: {
-/*	list: {
-			type: Array
-			,set: function (x) {
-				this._list = x;
-			}
-			,get: function () {
-				return this._list;
-			}
-		}
-*/
-	}
-
-	,list: []
-
-	,appendChild(child) {
-		this.list.push(child);
-	}
-
-	/**
-	 * Adds an element to the list.
-	 * 
-	 * @param {SqlObject} element The element to add
-	 */
-	,push(element) {
-		this.list.push(element);
-	}
-	
-	/**
-	 * Removes an element from the list.
-	 *
-	 * @param {Number} i The element index
-	 */
-	,splice(i) {
-		this.list.splice(i);
-	}
-	
-	/**
-	 * Adds an element to the list.
-	 *
-	 * @param {Number} i The element index
-	 */
-	,get(i) {
-		return this.list[i];
-	}
-
-	,findHolders() {
-		let ids = [];
-
-		for (const object of this.list){
-			holders = object.findHolders();
-			if (holders) ids = ids.concat(holders);
-		}
-
-		return ids;
-	}
-});
diff --git a/js/sql/list.js b/js/sql/list.js
deleted file mode 100644
index 32cf2492..00000000
--- a/js/sql/list.js
+++ /dev/null
@@ -1,71 +0,0 @@
-
-var SqlObject = require('./object');
-
-/**
- * List of Sql.Object
- */
-module.exports = new Class({
-	Extends: SqlObject
-
-	,objects: []
-
-	,add(object) {
-		this.objects.push(object.ref());
-		object.on('changed', this._onObjectChange, this);
-		this._onObjectChange();
-	}
-	
-	,get(i) {
-		return objects[i];
-	}
-	
-	,getArray() {
-		return this.objects;
-	}
-	
-	,remove(i) {
-		this._unrefObject(this.objects.splice(i, 1));
-		this._onObjectChange();
-	}
-
-	,_onObjectChange() {
-		this.emit('changed');
-	}
-
-	,isReady() {
-		var o = this.objects;
-		
-		if (o.length == 0)
-			return false;
-	
-		for (var i = 0; i < o.length; i++)
-		if (!o[i].isReady())
-			return false;
-
-		return true;
-	}
-
-	,findHolders() {
-		let ids = [];
-
-		for (const object of this.objects){
-			holders = object.findHolders();
-			if (holders) ids = ids.concat(holders);
-		}
-
-		return ids;
-	}
-	
-	,_unrefObject(object) {
-		object.disconnect('changed', this._onObjectChange, this);
-		object.unref();
-	}
-	
-	,_destroy() {
-		for (var i = 0; i < this.objects.length; i++)
-			this._unrefObject(this.objects[i]);
-			
-		SqlObject.prototype._destroy.call(this);
-	}
-});
-
diff --git a/js/sql/multi-stmt.js b/js/sql/multi-stmt.js
deleted file mode 100644
index d71a6546..00000000
--- a/js/sql/multi-stmt.js
+++ /dev/null
@@ -1,30 +0,0 @@
-
-var Stmt = require('./stmt');
-var ListHolder = require('./list-holder');
-
-/**
- * The equivalent of a SQL multi statement.
- */
-module.exports = new Class({
-	Extends: Stmt
-	,Implements: ListHolder
-	,Tag: 'sql-multi-stmt'
-	,Properties: {
-		/**
-		 * The statements list.
-		 */
-		stmts: {
-			type: Array
-			,set(x) {
-				this.list = x;
-			}
-			,get() {
-				return this.list;
-			}
-		}
-	}
-
-	,render(params) {
-		return this.renderListWs(this.list, params, ";\n");
-	}
-});
diff --git a/js/sql/object.js b/js/sql/object.js
deleted file mode 100644
index 582eb2d2..00000000
--- a/js/sql/object.js
+++ /dev/null
@@ -1,104 +0,0 @@
-/**
- * Base class for all objects on this library.
- */
-module.exports = new Class({
-	Extends: Vn.Object
-
-	/**
-	 * Gets if the object is ready to be rendered.
-	 *
-	 * @param {Object} params The query parameters
-	 * @return {boolean} %true if the object is ready, %false otherwise
-	 */
-	,isReady() {
-		return true;
-	}
-
-	/**
-	 * Through the query looking for containers.
-	 *
-	 * @return {Array} An array with the names of the found parameters
-	 */
-	,findHolders() {}
-	
-	/**
-	 * Renders the object as an SQL string.
-	 *
-	 * @param {Object} params The params used to render the object
-	 * @return {string} The SQL string
-	 */
-	,render() {}
-	
-	/**
-	 * Renders an objects array.
-	 *
-	 * @param {Array} list The objects array
-	 * @param {Object} params The parameters
-	 * @return {string} The rendered SQL string
-	 */
-	,renderList(list, params) {
-		var sql = '';
-
-		list.forEach(function(item) {
-			sql += item.render(params);
-		})
-
-		return sql;
-	}
-
-	/**
-	 * Renders an objects array using a separator.
-	 *
-	 * @param {Array} list The objects array
-	 * @param {Object} params The parameters
-	 * @param {String} separator The separator between items
-	 * @return {string} The rendered SQL string
-	 */
-	,renderListWs(list, params, separator) {
-		var sql = '';
-
-		list.forEach(function(item, i) {
-			if (i > 0)
-				sql += separator;
-			sql += item.render(params);
-		})
-
-		return sql;
-	}
-
-	/**
-	 * Renders a quoted SQL identifier.
-	 *
-	 * @param {String} identifier The identifier
-	 * @return {string} The quoted identifier
-	 */
-	,renderIdent(identifier) {
-		return '`'+ identifier +'`';
-	}
-	
-	/**
-	 * Renders a quoted SQL identifier.
-	 *
-	 * @param {String} identifier The identifier
-	 * @return {string} The quoted identifier
-	 */
-	,renderPreIdent(identifier) {
-		if (identifier)
-			return this.renderIdent(identifier) +'.';
-		else
-			return '';
-	}
-
-	/**
-	 * Renders the object if it's defined.
-	 *
-	 * @param {String} prefix The rendered string prefix
-	 * @return {string} The rendered object with its prefix
-	 */
-	,renderIfSet(object, prefix, params) {
-		if (object)
-			return ' '+ prefix +' '+ object.render(params);
-		else
-			return '';
-	}
-});
diff --git a/js/sql/operation.js b/js/sql/operation.js
deleted file mode 100644
index 6d37bb92..00000000
--- a/js/sql/operation.js
+++ /dev/null
@@ -1,85 +0,0 @@
-
-var Expr = require('./expr');
-var ListHolder = require('./list-holder');
-
-/**
- * The equivalent of a SQL operation between exprs.
- *
- * @param {Array#Expr} exprs Array with the exprs
- * @param {Type} type The type of the operation
- */
-var Klass = new Class();
-module.exports = Klass;
-
-var Type = {
-	 EQUAL  : 0
-	,LIKE   : 1
-	,AND    : 2
-	,OR     : 3
-	,REGEXP : 4
-	,LOWER  : 5
-	,UPPER  : 6
-	,LE     : 7
-	,UE     : 8
-	,PLUS   : 9
-	,MINUS  : 10
-	,MULT   : 11
-	,DIV    : 12
-	,NE     : 13
-	,MOD    : 14
-};
-
-var Operators = [
-	 '='
-	,'LIKE'
-	,'AND'
-	,'OR'
-	,'REGEXP'
-	,'<'
-	,'>'
-	,'<='
-	,'>='
-	,'+'
-	,'-'
-	,'*'
-	,'/'
-	,'<>'
-	,'MOD'
-];
-
-Klass.extend({
-	Type: Type
-	,Operators: Operators
-});
-
-Klass.implement({
-	Extends: Expr
-	,Implements: ListHolder
-	,Tag: 'sql-operation'
-	,Properties: {
-		type: {
-			enumType: Type
-			,value: -1
-		},
-		target: {
-			type: String
-			,value: null
-		},
-		exprs: {
-			type: Array
-			,set(x) {
-				this.list = x;
-			}
-			,get() {
-				return this.list;
-			}
-		}
-	}
-
-	,render(params) {
-		var operator = ' '+ Operators[this.type] +' ';
-		return '('
-			+ this.renderListWs(this.list, params, operator)
-			+ ')';
-	}
-});
diff --git a/js/sql/select.js b/js/sql/select.js
deleted file mode 100644
index 8d5c2ff0..00000000
--- a/js/sql/select.js
+++ /dev/null
@@ -1,25 +0,0 @@
-
-var Stmt = require('./stmt');
-var Field = require('./field');
-
-/**
- * The equivalent of a SQL select.
- */
-module.exports = new Class({
-	Extends: Stmt
-
-	,expr: []
-
-	,addField(fieldName) {
-		this.expr.push(new Field({name: fieldName}));
-	}
-
-	,render(params) {
-		return 'SELECT '
-			+ this.renderListWs(this.expr, params, ', ')
-			+ ' FROM'
-			+ this.renderTarget(params)
-			+ this.renderIfSet(this.where, 'WHERE', params)
-			+ this.renderLimit(params);
-	}
-});
diff --git a/js/sql/sql.js b/js/sql/sql.js
deleted file mode 100644
index 068b8231..00000000
--- a/js/sql/sql.js
+++ /dev/null
@@ -1,29 +0,0 @@
-
-require('vn/vn');
-
-Sql = module.exports = {
-	 Object     : require('./object')
-	,Holder     : require('./holder')
-	,List       : require('./list')
-	,ListHolder : require('./list-holder')
-	,Expr       : require('./expr')
-	,Value      : require('./value')
-	,Field      : require('./field')
-	,Function   : require('./function')
-	,Operation  : require('./operation')
-	,Target     : require('./target')
-	,Table      : require('./table')
-	,Join       : require('./join')
-	,JoinItem   : require('./join-item')
-	,Stmt       : require('./stmt')
-	,Dml        : require('./dml')
-	,String     : require('./string')
-	,Delete     : require('./delete')
-	,Insert     : require('./insert')
-	,Select     : require('./select')
-	,Update     : require('./update')
-	,MultiStmt  : require('./multi-stmt')
-	,Filter     : require('./filter')
-	,FilterItem : require('./filter-item')
-};
-
diff --git a/js/sql/stmt.js b/js/sql/stmt.js
deleted file mode 100644
index da147eb6..00000000
--- a/js/sql/stmt.js
+++ /dev/null
@@ -1,40 +0,0 @@
-
-var Object = require('./object');
-var Expr = require('./expr');
-
-/**
- * The equivalent of a SQL statement.
- */
-module.exports = new Class({
-	Extends: Object
-	,Properties: {
-		where: {
-			type: Expr
-			,value: null
-		},
-		limit: {
-			type: Number
-			,value: null
-		}
-	}
-
-	,target: []
-
-	,addTarget(target) {
-		this.target.push(target);
-	}
-
-	,renderTarget(params) {
-		if (this.target.length > 0)
-			return ' '+ this.renderListWs(this.target, params, ', ');
-		else
-			return ' DUAL';
-	}
-	
-	,renderLimit() {
-		if (this.limit != null)
-			return ' LIMIT '+ parseInt(this.limit);
-		else
-			return '';
-	}
-});
diff --git a/js/sql/string.js b/js/sql/string.js
deleted file mode 100644
index dee0bb20..00000000
--- a/js/sql/string.js
+++ /dev/null
@@ -1,46 +0,0 @@
-
-var Stmt = require('./stmt');
-var Holder = require('./holder');
-
-/**
- * Literal SQL string.
- */
-module.exports = new Class({
-	Extends: Stmt
-	,Tag: 'sql-string'
-	,Properties: {
-		query: {
-			type: String
-			,value: null
-		}
-	}
-
-	,regexp: /#\w+/g
-
-	,appendChild(child) {
-		if (child.nodeType === Node.TEXT_NODE)
-			this.query = child.textContent;
-	}
-
-	,render(params) {
-		if (!this.query)
-			return null;
-			
-		function replaceFunc(token) {
-			var holder = new Holder({id: token.substr(1)});
-			return holder.render(params);
-		}
-
-		return this.query.replace(this.regexp, replaceFunc);
-	}
-
-	,findHolders() {
-		var ids = this.query.match(this.regexp);
-		
-		if (ids)
-		for (var i = 0; i < ids.length; i++)
-			ids[i] = ids[i].substr(1);
-			
-		return ids;
-	}
-});
diff --git a/js/sql/table.js b/js/sql/table.js
deleted file mode 100644
index 61975ece..00000000
--- a/js/sql/table.js
+++ /dev/null
@@ -1,33 +0,0 @@
-
-var Target = require('./target');
-
-/**
- * Represents a database table.
- */
-module.exports = new Class({
-	Extends: Target
-	,Properties: {
-		name: {
-			type: String
-			,value: null
-		},
-		alias: {
-			type: String
-			,value: null
-		},
-		schema: {
-			type: String
-			,value: null
-		}
-	}
-
-	,render() {
-		var sql = this.renderPreIdent(this.schema)
-			+ this.renderIdent(this.name);
-
-		if (this.alias)
-			sql += ' AS '+ this.renderIdent(this.alias);
-
-		return sql;
-	}
-});
diff --git a/js/sql/target.js b/js/sql/target.js
deleted file mode 100644
index bb19092c..00000000
--- a/js/sql/target.js
+++ /dev/null
@@ -1,9 +0,0 @@
-
-var Object = require('./object');
-
-/**
- * The equivalent of a SQL target.
- */
-module.exports = new Class({
-	Extends: Object
-});
diff --git a/js/sql/update.js b/js/sql/update.js
deleted file mode 100644
index 5b9e42cf..00000000
--- a/js/sql/update.js
+++ /dev/null
@@ -1,28 +0,0 @@
-
-var Dml = require('./dml');
-
-/**
- * The equivalent of a SQL update.
- */
-module.exports = new Class({
-	Extends: Dml
-
-	,render(params) {
-		var sql = 'UPDATE'
-			+ this.renderTarget(params)
-			+ ' SET ';
-		
-		this.field.forEach(function(field, i) {
-			if (i > 0)
-				sql += ', ';
-
-			sql += field.render(params) 
-				+ ' = '
-				+ this.expr[i].render(params);
-		}, this);
-		
-		sql += this.renderIfSet(this.where, 'WHERE', params)
-			+ this.renderLimit(params);
-		return sql;
-	}
-});
diff --git a/js/sql/value.js b/js/sql/value.js
deleted file mode 100644
index 3006d55f..00000000
--- a/js/sql/value.js
+++ /dev/null
@@ -1,138 +0,0 @@
-
-var Expr = require('./expr');
-
-/**
- * The equivalent of a SQL value.
- */
-module.exports = new Class({
-
-	Extends: Expr
-	,Implements: Vn.ParamIface
-	,Tag: 'sql-value'
-	,Properties: {
-		value: {
-			type: null
-			,set(x) {
-				this._setValue(x);
-			}
-			,get() {
-				return this._value;
-			}
-		},
-		type: {
-			type: Type
-			,set(x) {
-				this._setType(x);
-			}
-			,get() {
-				return this._type;
-			}
-		},
-		param: {
-			type: Vn.ParamIface
-			,set(x) {
-				this._setParam(x);
-			}
-			,get() {
-				return this._param;
-			}
-		},
-		lot: {
-			type: Vn.LotIface
-			,set(x) {
-				this._setLot(x);
-			}
-			,get() {
-				return this._lot;
-			}
-		},
-		name: {
-			type: String
-			,set(x) {
-				this._name = x;
-				this._onLotChange();
-			}
-			,get() {
-				return this._name;
-			}
-		},
-		oneWay: {
-			type: Boolean
-			,set(x) {
-				this._oneWay = x;
-			}
-			,get() {
-				return this._oneWay;
-			}
-		},
-		oneTime: {
-			type: Boolean
-			,set(x) {
-				this._oneTime = x;
-			}
-			,get() {
-				return this._oneTime;
-			}
-		}
-	}
-
-	,regexp: new RegExp('(\\\\)|\'', 'g')
-	
-	,isReady() {
-		return this._value !== undefined;
-	}
-	
-	,replaceFunc(token) {
-		switch (token) {
-			case '\\': return '\\\\';
-			case '\'': return '\\\'';
-		}
-		
-		return token;
-	}
-
-	,render() {
-		var v = this._value;
-	
-		switch (typeof v) {
-		case 'number':
-			return v;
-		case 'boolean':
-			return (v) ? 'TRUE' : 'FALSE';
-		case 'string':
-			return "'" + v.replace(this.regexp, this.replaceFunc) + "'";
-		default:
-			if (v instanceof Date) {
-				if (!isNaN(v.getTime())) {
-					var unixTime = parseInt(fixTz(v).getTime() / 1000);
-					return 'DATE(FROM_UNIXTIME('+ unixTime +'))';
-				} else
-					return '0000-00-00'
-			} else
-				return 'NULL';
-		}
-	}
-});
-
-// TODO: Read time zone from db configuration
-var tz = {timeZone: 'Europe/Madrid'};
-var isLocal = Intl
-	.DateTimeFormat()
-	.resolvedOptions()
-	.timeZone == tz.timeZone;
-
-function fixTz(date) {
-	if (isLocal) return date;
-
-	var hasTime = date.getHours()
-		|| date.getMinutes()
-		|| date.getSeconds()
-		|| date.getMilliseconds(); 
-
-	if (!hasTime) {
-		date = new Date(date.getTime());
-		date.setHours(12, 0, 0, 0);
-	}
-
-	return date;
-}
diff --git a/js/vn/browser.js b/js/vn/browser.js
deleted file mode 100644
index 86aa8a8a..00000000
--- a/js/vn/browser.js
+++ /dev/null
@@ -1,29 +0,0 @@
-
-module.exports = {
-	getPageYOffset() {
-		return window.pageYOffset;
-	},
-
-	getPageXOffset() {
-		return window.pageXOffset;
-	},
-
-	getInnerHeight() {
-		return window.innerHeight;
-	},
-
-	getInnerWidth() {
-		return window.innerWidth;
-	},
-	
-	createRadio(uid, doc) {
-		var radio = doc.createElement('input');
-		radio.type = 'radio';
-		radio.name = uid;
-		return radio;
-	},
-
-	setInputTypeNumber(input) {
-		input.type = 'number';
-	}
-};
diff --git a/js/vn/builder.js b/js/vn/builder.js
deleted file mode 100644
index ffe22d00..00000000
--- a/js/vn/builder.js
+++ /dev/null
@@ -1,168 +0,0 @@
-const VnObject = require('./object');
-const Scope = require('./scope');
-const kebabToCamel = require('./string-util').kebabToCamel;
-
-const CompilerObject = require('./compiler-object');
-const CompilerElement = require('./compiler-element');
-const CompilerText = require('./compiler-text');
-
-const regCompilers = [
-	CompilerText,
-	CompilerObject,
-	CompilerElement
-];
-
-/**
- * Creates a object from a XML specification.
- */
-module.exports = new Class({
-	 Extends: VnObject
-
-	/**
-	 * Compiles an XML file.
-	 *
-	 * @param {String} path The XML path
-	 * @return {Boolean} %true on success, %false othersise
-	 */
-	,compileFile(path) {
-		this._path = path;
-		return this.compileDocument(Vn.getXml(path));
-	 }
-
-	/**
-	 * Compiles an XML string.
-	 *
-	 * @param {String} xmlString The XML string
-	 * @return {Boolean} %true on success, %false othersise
-	 */
-	,compileString(xmlString) {
-		const parser = new DOMParser();
-		const doc = parser.parseFromString(xmlString, 'text/xml');
-		return this.compileDocument(doc);
-	 }
-
-	/**
-	 * Compiles a XML document.
-	 *
-	 * @param {Document} doc The DOM document
-	 * @return {Boolean} %true on success, %false othersise
-	 */
-	,compileDocument(doc) {
-		if (!doc)
-		return false;
-
-		this._preCompile();
-		const docElement = doc.documentElement;
-		
-		if (docElement.tagName !== 'vn') {
-			this.showError('The toplevel tag should be named \'vn\'');
-			this._contexts = null;
-			return false;
-		}
-
-		const childs = docElement.childNodes;
-		if (childs)
-		for (let i = 0; i < childs.length; i++)
-			this._compile(childs[i]);
-
-		this._postCompile();
-		return true;
-	}
-	
-	/**
-	 * Compiles a single DOM node.
-	 *
-	 * @path Node The DOM node
-	 * @return %true on success, %false othersise
-	 */
-	,compileNode(node) {
-		this._preCompile();
-		this._mainContext = this._compile(node).id;
-		this._postCompile();
-		return true;
-	}
-
-	/**
-	 * Called before starting to compile nodes.
-	 */
-	,_preCompile() {
-		this._path = null;
-		this._tags = {};
-		this._contexts = [];
-		this._exprContexts = [];
-		this._contextMap = {};
-		this._links = [];
-		this._mainContext = null;
-
-		this._compilers = [];
-		for (regCompiler of regCompilers)
-			this._compilers.push(new regCompiler(this));
-	}
-	
-	/**
-	 * Called after all nodes have been compiled.
-	 */
-	,_postCompile() {
-		for (const compiler of this._compilers)
-			compiler.postCompile(this._contextMap);
-	}
-
-	/**
-	 * Compiles a node.
-	 */
-	,_compile(node) {
-		let context = null;
-		let tagName = null;
-		const isElement = node.nodeType === Node.ELEMENT_NODE;
-
-		if (isElement)
-			tagName = node.tagName.toLowerCase();
-		else if (node.nodeType !== Node.TEXT_NODE
-		|| /^[\n\r\t]*$/.test(node.textContent))
-			return null;
-
-		let i;
-		const compilers = this._compilers;
-		for (i = 0; i < compilers.length && context === null; i++)
-			context = compilers[i].compile(this, node, tagName);
-
-		context.id = this._contexts.length;
-		context.compiler = compilers[i - 1];
-
-		if (isElement) {
-			const nodeId = node.getAttribute('id');
-	
-			if (nodeId) {
-				this._contextMap[kebabToCamel(nodeId)] = context.id;
-				context.nodeId = nodeId;
-			}
-
-			let tags = this._tags[tagName];
-			if (!tags)
-				this._tags[tagName] = tags = [];
-			
-			tags.push(context.id);
-		}
-
-		this._contexts.push(context);
-		return context;
-	}
-	
-	,load(dstDocument, thisArg, parentScope) {
-		if (!this._contexts) return null;
-		const doc = dstDocument ? dstDocument : document;
-		const objects = new Array(this._contexts.length);
-		const exprValues = new Array(this._exprContexts.length);
-		return new Scope(this, doc, objects, exprValues, thisArg, parentScope);
-	}
-
-	,showError(error) {
-		const path = this._path ? this._path : 'Node';		
-		const logArgs = ['Vn.Builder: %s: '+ error, path];
-
-		for (let i = 1; i < arguments.length; i++)
-			logArgs.push(arguments[i]);
-	
-		console.warn.apply(null, logArgs);
-	}
-});
diff --git a/js/vn/compiler-element.js b/js/vn/compiler-element.js
deleted file mode 100644
index b35c9d31..00000000
--- a/js/vn/compiler-element.js
+++ /dev/null
@@ -1,85 +0,0 @@
-const Compiler = require('./compiler');
-const Component = require('./component');
-const VnNode = require('./node');
-
-/**
- * Compiles a @HTMLElement from element tag.
- */
- module.exports = new Class({
-	Extends: Compiler
-
-	,compile(builder, node, tagName) {
-		const context = {
-			tagName,
-			attributes: {},
-			childs: [],
-			events: {}
-		};
-		const {attributes} = context;
-
-		const a = node.attributes;
-		for (let i = 0; i < a.length; i++) {
-			const attribute = a[i].nodeName;
-			const value = a[i].nodeValue;
-	
-			if (this.isEvent(attribute)) {
-				const handler = this._getMethod(value);
-				if (handler) context.events[attribute.substr(3)] = handler;
-			} else if (!/^(id|property)$/.test(attribute)) {
-				if (this.isExpr(value))
-					this.compileExpr(context, attribute, value);
-				else
-					attributes[attribute] = this._translateValue(value);
-			}
-		}
-
-		let childContext;
-		const childNodes = node.childNodes;
-
-		if (childNodes)
-		for (let i = 0; i < childNodes.length; i++)
-		if (childContext = builder._compile(childNodes[i]))
-			context.childs.push(childContext.id);
-
-		return context;
-	}
-	
-	,instantiate(doc, context, scope) {
-		const object = doc.createElement(context.tagName);
-
-		const attributes = context.attributes;
-		for (const attribute in attributes)
-			object.setAttribute(attribute, attributes[attribute]);
-
-		if (context.nodeId) {
-			const id = context.nodeId;
-			object.setAttribute('id', scope.getHtmlId(id));
-			VnNode.addClass(object, '_'+ id);
-		}
-
-		return object;
-	}
-
-	,setProperty(object, property, value) {
-		object.setAttribute(property, value);
-	}
-	
-	,link(context, object, objects, scope) {
-			const childs = context.childs;
-		for (let i = 0; i < childs.length; i++) {
-			let child = objects[childs[i]];
-		
-			if (child instanceof Component)
-				child = child.node;
-			if (child instanceof Node)
-				object.appendChild(child);
-		}
-		
-		const events = context.events;
-		for (const event in events) {
-			const listener = this.bindMethod(events[event], scope, true);
-			if (listener)
-				object.addEventListener(event, listener);
-		}
-	}
-});
diff --git a/js/vn/compiler-object.js b/js/vn/compiler-object.js
deleted file mode 100644
index a5ddd221..00000000
--- a/js/vn/compiler-object.js
+++ /dev/null
@@ -1,216 +0,0 @@
-const Compiler = require('./compiler');
-const Component = require('./component');
-const Type = require('./type');
-const kebabToCamel = require('./string-util').kebabToCamel;
-
-/**
- * Compiles a @Vn.Object from element tag.
- */
-module.exports = new Class({
-	Extends: Compiler
-	
-	,_links: []
-
-	/**
-	 * Creates a object context.
-	 */
-	 ,compile(builder, node, tagName) {
-		const klass = vnCustomTags[tagName];
-		if (!klass) return null;
-			
-		const context = {
-			klass,
-			props: {},
-			funcProps: {},
-			objectProps: {},
-			childs: [],
-			events: {},
-			custom: null
-		};
-
-		const a = node.attributes;
-		for (let i = 0; i < a.length; i++) {
-			const attribute = a[i].nodeName;
-			const value = a[i].nodeValue;
-
-			if (this.isEvent(attribute)) {
-				const handler = this._getMethod(value)
-				if (handler) context.events[attribute.substr(3)] = handler;
-			} else if (!/^(id|property)$/.test(attribute)) {
-				this.propCompile(context, node, attribute, value);
-			}
-		}
-		
-		const childNodes = node.childNodes;
-
-		if (childNodes)
-		for (let i = 0; i < childNodes.length; i++) {
-			const child = childNodes[i];
-			const isElement = child.nodeType === Node.ELEMENT_NODE;
-			const childTagName = isElement ? child.tagName.toLowerCase() : null;
-			let childContext;
-			
-			if (childTagName === 'pointer') {
-				this._addLink(context, null, child.getAttribute('object'));
-			} else if (childTagName === 'custom') {
-				context.custom = child;
-			} else if (childContext = builder._compile(child)) {
-				let prop = isElement ? child.getAttribute('property') : null;
-	
-				if (prop) {
-					prop = kebabToCamel(prop); 
-					context.objectProps[prop] = childContext.id;
-				} else
-					context.childs.push(childContext.id);
-			}
-		}
-
-		return context;
-	}
-
-	,propCompile(context, node, attribute, value) {
-		const tagName = node.tagName;
-		const propName = kebabToCamel(attribute);
-		const propInfo = context.klass.Properties[propName];
-
-		if (!value) {
-			this.showError('Attribute \'%s\' empty on tag \'%s\'',
-				attribute, tagName);
-			return;
-		}
-
-		if (propName == 'vModel') {
-			context.vModel = this.modelExpr(value);
-			return;
-		}
-
-		if (!propInfo) {
-			this.showError('Attribute \'%s\' not valid for tag \'%s\'',
-				attribute, tagName);
-			return;
-		}
-
-		if (this.isExpr(value)) {
-			this.compileExpr(context, propName, value);
-		} else {
-			let isLink = false;
-			let propError = false;
-			let newValue = null;
-
-			switch (propInfo.type) {
-			case Boolean:
-				newValue = (/^(true|1)$/i).test(value);
-				break;
-			case Number:
-				newValue = 0 + new Number(value);
-				break;
-			case String:
-				newValue = this._translateValue(value);
-				break;
-			case Function:
-				context.funcProps[propName] = this._getMethod(value);
-				break;
-			case Type:
-				newValue = window[value];
-				break;
-			default:
-			if (propInfo.enumType)
-				newValue = propInfo.enumType[value];
-			else if (propInfo.type instanceof Function)
-				isLink = true;
-			else
-				propError = true;
-			}
-			
-			if (isLink)
-				this._addLink(context, propName, value);
-			else if (newValue !== null && newValue !== undefined)
-				context.props[propName] = newValue;
-			else if (propError)
-				this.showError('Attribute \'%s\' invalid for tag \'%s\'',
-					attribute, tagName);
-		}
-	}
-	
-	,instantiate(doc, context, scope) {
-		const object = new context.klass();
-		object.setProperties(context.props);
-
-		if (context.nodeId && object instanceof Component) {
-			const id = context.nodeId;
-			object.htmlId = scope.getHtmlId(id);
-			object.className = '_'+ id +' '+ (object.className || '');
-		}
-
-		return object;
-	}
-
-	,setProperty(object, property, value) {
-		object[property] = value;
-	}
-
-	,preLink(scope) {
-		const objects = scope.objects;
-		const links = this._links;
-
-		for (let i = links.length - 1; i >= 0; i--) {
-			const link = links[i];
-			const object = objects[link.context.id];
-			const objectRef = scope.$[link.objectId];
-
-			if (objectRef === undefined) {
-				this.showError('Referenced unexistent object with id \'%s\'',
-					link.objectId);
-				continue;
-			}
-			
-			if (link.prop)
-				object[link.prop] = objectRef;
-			else
-				object.appendChild(objectRef);
-		}
-	}
-	
-	,link(context, object, objects, scope) {
-		const objectProps = context.objectProps;
-		for (const prop in objectProps)
-			object[prop] = objects[objectProps[prop]];
-
-		const childs = context.childs;
-		for (let i = 0; i < childs.length; i++)
-			object.appendChild(objects[childs[i]]);
-
-		const funcProps = context.funcProps;
-		for (const prop in funcProps)
-			object[prop] = this.bindMethod(funcProps[prop], scope);
-
-		const events = context.events;
-		for (const event in events) {
-			const listener = this.bindMethod(events[event], scope);
-			if (listener)
-				object.on(event, listener, scope.thisArg);
-		}
-
-		if (context.vModel) {
-			object.on('change', function(lot) {
-				context.vModel.call(scope.thisArg, scope.$, lot.$);
-				scope.digest();
-			}, scope);
-		}
-
-		if (context.custom)
-			object.loadXml(scope, context.custom);
-	}
-
-	,_addLink(context, prop, objectId) {
-		this._links.push({
-			 context
-			,prop
-			,objectId: kebabToCamel(objectId)
-		});
-	}
-	
-	,_replaceFunc(token) {
-		return token.charAt(1).toUpperCase();
-	}
-});
\ No newline at end of file
diff --git a/js/vn/compiler-text.js b/js/vn/compiler-text.js
deleted file mode 100644
index 7951c735..00000000
--- a/js/vn/compiler-text.js
+++ /dev/null
@@ -1,33 +0,0 @@
-const Compiler = require('./compiler');
-
-/**
- * Compiles a @Text from text node.
- */
-module.exports = new Class({
-	Extends: Compiler
-
-	,compile(builder, node, tagName) {
-		if (tagName && tagName != 't')
-			return null;
-
-		const text = node.textContent;
-		const context = {text};
-
-		if (tagName === 't') {
-			context.text = _(node.firstChild.textContent); 
-		} else if (this.isExpr(text, true)) {
-			context.text = '';
-			this.compileExpr(context, null, text, true);
-		}
-
-		return context;
-	}
-	
-	,instantiate(doc, context) {
-		return doc.createTextNode(context.text);
-	}
-
-	,setProperty(object, property, value) {
-		object.textContent = value;
-	}
-});
diff --git a/js/vn/compiler.js b/js/vn/compiler.js
deleted file mode 100644
index 9f00c05e..00000000
--- a/js/vn/compiler.js
+++ /dev/null
@@ -1,150 +0,0 @@
-
-var VnObject = require('./object');
-
-/**
- * Base class for compilers.
- */
-module.exports = new Class({
-	Extends: VnObject
-
-	,compile() {}
-	,postCompile() {}
-	,instantiate() {}
-	,preLink() {}
-	,link() {}
-	,connect() {}
-	,postLink() {}
-	,setProperty() {}
-	,free() {}
-
-	,initialize(builder) {
-		this._builder = builder;
-		this._interpoler = builder._interpoler;
-		this.parent();
-	}
-
-	/**
-	 * Checks if the passed attribute name it's an event.
-	 * 
-	 * @param {String} attribute The attribute name
-	 * @return {Boolean} %true if it's an event, otherwise %false
-	 */
-	,isEvent(attribute) {
-		return /^on-\w+/.test(attribute);
-	}
-
-	,isIdentifier(value) {
-		return /^[a-zA-Z_$][\w$]*$/.test(value);
-	}
-
-	/**
-	 * Logs an error parsing the node.
-	 * 
-	 * @param {String} error The error message template
-	 * @param {...} varArgs The message template arguments
-	 */
-	,showError() {
-		this._builder.showError.apply(this._builder, arguments);
-	}
-
-	,_getMethod(value) {
-		// XXX: Compatibility with old methods
-		return this.isIdentifier(value)
-			? value
-			: this.fnExpr(value);
-	}
-
-	,bindMethod(handler, scope, isEvent) {
-		// XXX: Compatibility with old methods
-		if (typeof handler === 'string') {
-			const method = scope.thisArg[handler];
-			if (!method) {
-				this.showError(`Function '${handler}' not found`);
-				return undefined;
-			}
-
-			return method.bind(scope.thisArg);
-		}
-
-		return function($event) {
-			let handlerScope;
-			if (isEvent) {
-				handlerScope = Object.create(scope.$);
-				Object.assign(handlerScope, {$event});
-			} else
-				handlerScope = scope.$;
-
-			handler.call(this, handlerScope);
-		}.bind(scope.thisArg);
-	}
-
-	,matchExpr(value) {
-		const match = /^{{(.*)}}$/.exec(value);
-		if (!match) return null;
-		return this.fnExpr(match[1]);
-	}
-
-	,modelExpr(expr) {
-		try {
-			return new Function('$scope', '$value',
-				`"use strict"; $scope.${expr} = $value;`
-			);
-		} catch (err) {
-			this.showError(`${err.message}:`, expr);
-		}
-	}
-
-	,exprRegex: /^{{((?:(?!}}).)*)}}$/
-	,exprRegexMulti: /{{((?:(?!}}).)*)}}/g
-
-	,isExpr(expr, isMulti) {
-		return isMulti
-			? this.exprRegexMulti.test(expr)
-			: this.exprRegex.test(expr);
-	}
-
-	,compileExpr(context, property, value, isMulti) {
-		const exprContext = {
-			context,
-			property,
-			value
-		};
-
-		if (isMulti) {
-			let i = 0;
-			const self = this;
-			exprContext.exprs = [];
-			exprContext.template = value.replace(this.exprRegexMulti,
-				function(match, capture) {
-					exprContext.exprs.push(self.fnExpr(capture));
-					return `{{${i++}}}`;
-				});
-		} else {
-			const match = this.exprRegex.exec(value);
-			exprContext.expr = this.fnExpr(match[1]);
-		}
-
-		this._builder._exprContexts.push(exprContext);
-	}
-
-	,fnExpr(expr) {
-		try {
-			return new Function('$scope',
-				`with($scope) { return ${expr}; }`
-			);
-		} catch (err) {
-			this.showError(`${err.message}:`, expr);
-		}
-	}
-
-	,_translateValue(value) {
-		var chr = value.charAt(0);
-
-		if (chr === '_')
-			return _(value.substr(1));
-		else if (chr === '\\' && value.charAt(1) === '_')
-			return value.substr(1);
-			
-		return value;
-	}
-});
diff --git a/js/vn/component.js b/js/vn/component.js
deleted file mode 100644
index 706b04c0..00000000
--- a/js/vn/component.js
+++ /dev/null
@@ -1,205 +0,0 @@
-
-const NodeBuilder = require('./node-builder');
-
-const Klass = new Class();
-module.exports = Klass;
-
-Klass.extend({Classes: ''});
-
-const ComponentClass = {
-	Extends: NodeBuilder,
-	Tag: 'vn-component',
-	Properties: {
-		/**
-		 * Main HTML node that represents the component
-		 */
-		node: {
-			type: Object
-			,get() {
-				this.renderBase();
-				return this._node;
-			}
-		},
-		/**
-		 * CSS syle.
-		 */
-		style: {
-			type: String
-			,set(x) {
-				this.node.style = x;
-			}
-			,get() {
-				return this._node.style;
-			}
-		},
-		/**
-		 * CSS classes to be appendend to the node classes.
-		 */
-		class: {
-			type: String
-			,set(x) {
-				this._className = x;
-				this._refreshClass();
-			}
-			,get() {
-				return this._className;
-			}
-		},
-		/**
-		 * CSS classes to be appendend to the node classes.
-		 */
-		className: {
-			type: String
-			,set(x) {
-				this._className = x;
-				this._refreshClass();
-			}
-			,get() {
-				return this._className;
-			}
-		},
-		/**
-		 * CSS class list.
-		 */
-		classList: {
-			type: Object
-			,get() {
-				return this._node.classList;
-			}
-		},
-		/**
-		 * Title of the element.
-		 */
-		title: {
-			type: String
-			,set(x) {
-				this._node.title = x;
-			}
-			,get() {
-				return this._node.title;
-			}
-		},
-		/**
-		 * The HTML id of the element.
-		 */
-		htmlId:
-		{
-			type: String
-			,set(x) {
-				this._htmlId = x;
-				if (this._node)
-					this._node.id = x;
-			}
-			,get() {
-				return this._htmlId;
-			}
-		},
-	}
-
-	,_node: null
-	,scope: null
-	
-	,initialize(props) {
-		this.doc = document;
-		this.renderBase();
-		NodeBuilder.prototype.initialize.call(this, props);
-	}
-	
-	,createRoot(tagName) {
-		const node = this._node = this.createElement(tagName);
-		node.$ctrl = this;
-		if (this._htmlId)
-			node.id = this._htmlId;
-		if (this.$constructor.Classes)
-			node.className = this.$constructor.Classes;
-		return node;
-	}
-	
-	,appendChild(child) {
-		if (child instanceof Klass)
-			this._node.appendChild(child.node);
-		else if (child instanceof Element)
-			this._node.appendChild(child);
-	}
-	
-	,renderBase() {
-		if (this._node)
-			return;
-
-		this.render();
-		this._refreshClass();
-	}
-
-	,_refreshClass() {
-		if (this._node && this._className)
-			this._node.className = this._className +' '+ (this._node.className || '');
-	}
-	
-	,remove() {
-		Vn.Node.remove(this._node);
-	}
-
-	,on(id, callback, instance) {
-		if (htmlEventMap[id]) {
-			this.addEventListener(id,
-				callback.bind(instance, this));
-		} else
-			NodeBuilder.prototype.on.call(this, id, callback, instance);
-	}
-
-	,loadTemplateFromFile(path) {
-		const builder = new Vn.Builder();
-		builder.compileFile(path);
-		this.loadScope(builder);
-	}
-	
-	,loadTemplateFromString(xmlString) {
-		const builder = new Vn.Builder();
-		builder.compileString(xmlString);
-		this.loadScope(builder);
-	}
-	
-	,loadScope(builder) {
-		const scope = this.scope = builder.load(this.doc, this);
-		scope.link();
-
-		this.$ = scope.$;
-		this._node = scope.$.main;
-	}
-
-	,_destroy() {
-		if (this.scope) this.scope._destroy();
-		NodeBuilder.prototype._destroy.call(this, );
-	}
-};
-
-htmlEventMap = {};
-htmlEvents = [
-	'click',
-	'dblclick',
-	'keydown',
-	'keypress',
-	'keyup',
-	'mousedown',
-	'mousemove',
-	'mouseout',
-	'mouseover',
-	'mouseup',
-	'mousewheel',
-	'wheel',
-	'focus',
-	'focusout',
-	'focusin'
-];
-htmlEvents.forEach(x => htmlEventMap[x] = true);
-
-htmlMethods = [
-	'addEventListener'
-];
-htmlMethods.forEach(method => {
-	ComponentClass[method] = function() {
-		this.node[method].apply(this.node, arguments);
-	};
-});
-
-Klass.implement(ComponentClass);
diff --git a/js/vn/cookie.js b/js/vn/cookie.js
deleted file mode 100644
index 7ab233e1..00000000
--- a/js/vn/cookie.js
+++ /dev/null
@@ -1,71 +0,0 @@
-/**
- * Brownser cookie handler.
- */
-module.exports =
-{
-	set: function (key, value, days)
-	{
-		var strCookie = key + '=' + value + ';';
-	
-		if (days != undefined)
-		{
-			var date = new Date ();
-			date.setTime (date.getTime () + days * 86400000);
-			strCookie += 'expires=' + date.toGMTString ();
-		}
-	
-		document.cookie = strCookie;
-	}
-
-	,unset: function (key)
-	{
-		this.set (key, '', -1);
-	}
-
-	,get: function (key)
-	{
-		var cookie = new String (document.cookie);
-		var start = cookie.indexOf (key + '=');
-	
-		if (start != -1)
-		{
-			var end;
-
-			start += key.length + 1;
-			end = cookie.indexOf (';', start);
-
-			if (end > 0)
-				return cookie.substring (start, end);
-			else
-				return cookie.substring (start);
-		}
-		
-		return null;
-	}
-	
-	,getInt: function (key)
-	{
-		var value = this.get (key);
-		
-		if (value != null)
-			return parseInt (value);
-		
-		return null;
-	}
-	
-	,getFloat: function (key)
-	{
-		var value = this.get (key);
-		
-		if (value != null)
-			return parseFloat (value);
-		
-		return null;
-	}
-
-	,check: function (key)
-	{
-		return this.get (key) != null;
-	}
-};
-
diff --git a/js/vn/date.js b/js/vn/date.js
deleted file mode 100644
index 1a0c26b6..00000000
--- a/js/vn/date.js
+++ /dev/null
@@ -1,121 +0,0 @@
-/**
- * Date handling utilities.
- */
-
-Date.prototype.clone = function() {
-	return new Date(this.getTime());
-}
-
-module.exports =
-{
-	WDays: [
-		 'Sunday'
-		,'Monday'
-		,'Tuesday'
-		,'Wednesday'
-		,'Thursday'
-		,'Friday'
-		,'Saturday'
-	]
-	,AbrWDays: [
-		 'Su'
-		,'Mo'
-		,'Tu'
-		,'We'
-		,'Th'
-		,'Fr'
-		,'Sa'
-	]
-	,Months: [
-		 'January'
-		,'February'
-		,'March'
-		,'April'
-		,'May'
-		,'June'
-		,'July'
-		,'August'
-		,'September'
-		,'October'
-		,'November'
-		,'December'
-	]
-	,AbrMonths: [
-		 'Jan'
-		,'Feb'
-		,'Mar'
-		,'Apr'
-		,'AbrMay'
-		,'Jun'
-		,'Jul'
-		,'Ago'
-		,'Sep'
-		,'Oct'
-		,'Nov'
-		,'Dec'
-	]
-	
-	,tokenD: '%A, %B %e'
-	
-	,regexp: new RegExp('%[a-zA-Z]', 'g')
-
-	,pad(number) {
-		if (number < 10)
-			return '0'+ number.toString();
-
-		return number.toString();
-	}
-	
-	,regexpFunc(d, token) {
-		switch (token.charAt(1)) {
-			// Minutes with 2 digits
-			case 'M': return this.pad(d.getMinutes());
-
-			// Hour with 2 digits in 24 hour format
-			case 'H': return this.pad(d.getHours());
-
-			// Complete time
-			case 'T': return d.toLocaleTimeString();
-
-			// Complete week day name
-			case 'A': return _(this.WDays[d.getDay()]);
-
-			// Abreviated week day name
-			case 'a': return _(this.AbrWDays[d.getDay()]);
-
-			// Day of month with 2 digits
-			case 'd': return this.pad(d.getDate());
-
-			// Day of month
-			case 'e': return d.getDate();
-
-			// Complete month name
-			case 'B': return _(this.Months[d.getMonth()]);
-
-			// Abreviated month name
-			case 'b': return _(this.AbrMonths[d.getMonth()]);
-
-			// Month number with 2 digits
-			case 'm': return this.pad(d.getMonth() + 1);
-
-			// Year with 4 digits
-			case 'Y': return d.getFullYear();
-
-			// Complete date without year
-			case 'D': return _(this.tokenD).replace(this.regexp, this.regexpFunc.bind(this, d));
-		}
-		
-		return token;
-	}
-
-	,strftime(date, format) {
-		if (!date)
-			return '';
-		if (!(date instanceof Date))
-			date = new Date(date);
-		if (isNaN(date.getTime()))
-			return date.toString();
-
-		return format.replace(this.regexp, this.regexpFunc.bind(this, date));
-	}
-};
diff --git a/js/vn/enum.js b/js/vn/enum.js
deleted file mode 100644
index 3c48b4aa..00000000
--- a/js/vn/enum.js
+++ /dev/null
@@ -1,4 +0,0 @@
-/**
- * Base type for ennumerations.
- */
- module.exports = function() {};
diff --git a/js/vn/form.js b/js/vn/form.js
deleted file mode 100644
index 0f2d5d8f..00000000
--- a/js/vn/form.js
+++ /dev/null
@@ -1,72 +0,0 @@
-
-var Iterator = require('./iterator');
-var ModelIface = require('./model-iface');
-
-module.exports = new Class({
-	Extends: Iterator
-	,Tag: 'db-form'
-	,Properties: {
-		model: { 
-			type: ModelIface
-			,set(x) {
-				this.link({_model: x},
-				{
-					 'status-changed': this.onModelChange
-					,'row-updated': this.onModelRowUpdate
-				});
-			}
-			,get() {
-				return this._model;
-			}
-		},
-		/**
-		 * The row where the form positioned, has -1 if the row is unselected.
-		 */
-		row: { 
-			type: Number
-			,set(x) {
-				if (!this._model || this._model.numRows <= x || x < -1)
-					x = -1;
-				if (x == this._row)
-					return;
-
-				this._row = x;
-				this.rowChanged();
-			}
-			,get() {
-				return this._row;
-			}
-		}
-	}
-
-	,initialize(props) {
-		Object.assign(this, {
-			 _lastRow: 0
-			,_lastReady: false
-		});
-		Iterator.prototype.initialize.call(this, props);
-	}
-
-	,onModelChange() {
-		var ready = this._model && this._model.ready;
-		
-		if (ready != this._lastReady) {
-			if (this._row != -1)
-				this._lastRow = this._row;
-	
-			this._lastReady = ready;
-			this.emit('status-changed');
-			
-			if (this._row == -1)
-				this.row = this._lastRow;
-				
-			if (ready)
-				this.emit('ready');
-		}
-	}
-
-	,onModelRowUpdate(model, row) {
-		if (row == this._row)
-			this.rowChanged();
-	}
-});
diff --git a/js/vn/hash.js b/js/vn/hash.js
deleted file mode 100644
index 0e373c43..00000000
--- a/js/vn/hash.js
+++ /dev/null
@@ -1,164 +0,0 @@
-
-var VnDate = require('./date');
-var Lot = require('./lot');
-
-/**
- * Class to handle the hash part of the URL as a key-value javascript object.
- * It also handles dates and objects as a value.
- */
-module.exports = new Class({
-	Extends: Lot
-	,Properties: {
-		/**
-		 * The main window object.
-		 */
-		window:
-		{
-			type: Window
-			,set(x) {
-				this._window = x;
-				x.addEventListener('hashchange', this._hashChangedHandler);
-				this._hashChanged();
-			}
-			,get() {
-				return this._window;
-			}
-		}
-	}
-
-	,initialize(props) {
-		Object.assign(this, {
-			 _hash: null
-			,_hashLock: false
-			,_window: null
-			,_hashChangedHandler: this._hashChanged.bind(this)
-		});
-		Lot.prototype.initialize.call(this, props);
-	}
-
-	,_paramsChanged() {
-		this.updateHash();
-	}
-
-	/**
-	 * Creates a URL with the given hash data.
-	 *
-	 * @param {Object} params A key-value object
-	 * @param {boolean} add %true to combine with the current params, %false otherwise
-	 * @return {string} The URL
-	 */
-	,make(params, add) {
-		if (add) {
-			params = Object.assign({}, params);
-
-			for (var key in this._params)
-			if (!params[key])
-				params[key] = this._params[key];
-		}
-
-		return this.renderHash(params);
-	}
-
-	/**
-	 * Updates the window hash with current params.
-	 */
-	,updateHash() {
-		if (this._hashLock)
-			return;
-
-		this._hash = this.renderHash(this._params);
-
-		this._hashLock = true;
-		location.hash = this._hash;
-		this._hashLock = false;
-	}
-
-	/*
-	 * Called when window hash changes.
-	 */
-	,_hashChanged() {
-		var newHash = location.hash;
-	
-		if (this._hashLock || this._hash === newHash)
-			return;
-
-		this._hash = newHash;
-
-		this._hashLock = true;
-		this.params = this.parseHash(newHash);
-		this._hashLock = false;
-	}
-
-	/**
-	 * Creates a URL with the given hash data.
-	 *
-	 * @param {Object} params The key-value object
-	 * @return {string} The URL
-	 */
-	,renderHash(params) {
-		var hash = '#!';
-
-		for (var key in params)
-		if (params[key] !== undefined) {
-			if (hash.length > 2)
-				hash += '&';
-
-			hash += encodeURIComponent(key) +'='+ this.renderValue(params[key]);
-		}
-	
-		return hash;
-	}
-
-	/**
-	 * Parses a hash string to a key-value object.
-	 *
-	 * @param {string} hashString The hash string
-	 * @return {Object} The key-value object
-	 */
-	,parseHash(hashString) {
-		var newMap = hashMap = {};
-		var kvPairs = hashString.substr(2).split('&');
-
-		for (var i = 0; i < kvPairs.length; i++) {
-			var kvPair = kvPairs[i].split('=', 2);
-			
-			if (kvPair[0])
-				newMap[decodeURIComponent(kvPair[0])] = this.parseValue(kvPair[1]);
-		}
-
-		return newMap;
-	}
-
-	,renderValue(v) {
-		if (v == null)
-			return '';
-
-		switch (typeof v) {
-			case 'object':
-			if (v instanceof Date)
-				return VnDate.strftime(v, '%Y-%m-%d');
-			else
-				return JSON.stringify(v)
-		}
-
-		return v;
-	}
-
-	,parseValue(v) {
-		if (v == null)
-			return v;
-
-		v = decodeURIComponent(v);
-
-		if (v === '')
-			return null;
-
-		return v;
-	}
-
-	,_destroy() {
-		this._window.removeEventListener('hashchange', this._hashChangedHandler);
-		this._window = null;
-		Lot.prototype._destroy.call(this);
-	}
-});
diff --git a/js/vn/ie.js b/js/vn/ie.js
deleted file mode 100644
index 34270e68..00000000
--- a/js/vn/ie.js
+++ /dev/null
@@ -1,119 +0,0 @@
-
-module.exports = {
-	getPageYOffset() {	
-		if (document.documentElement.scrollTop)
-			return document.documentElement.scrollTop;
-		else
-			return document.body.scrollTop;
-	},
-
-	getPageXOffset() {	
-		if (document.documentElement.scrollLeft)
-			return document.documentElement.scrollLeft;
-		else
-			return document.body.scrollLeft;
-	},
-
-	getInnerHeight() {
-		if (document.documentElement.clientHeight)
-			return document.documentElement.clientHeight;
-		else
-			return document.body.clientHeight;
-	},
-
-	getInnerWidth() {
-		if (document.documentElement.clientWidth)
-			return document.documentElement.clientWidth;
-		else
-			return document.body.clientWidth;
-	},
-
-	createRadio(radioName) {
-		var radio;
-
-		try {
-			radio = document.createElement('<input type="radio" name="' + radioName + '">');
-		} catch (e) {
-			radio = document.createElement('input');
-			radio.type = 'radio';
-			radio.name = radioName;
-		}
-	
-		return radio;
-	},
-
-	setInputTypeNumber(input) {
-		input.type = 'text';
-	}
-};
-
-if (!Function.bind) {
-	Function.prototype.bind = function() {
-		var bindFunc = this;
-		var bindThis = arguments[0];
-		var bindArgs = arguments;
-
-		var IE_bind = function() {
-			var args = new Array();
-	
-			for (var i = 1; i < bindArgs.length; i++)
-				args.push(bindArgs[i]);
-			for (var i = 0; i < arguments.length; i++)
-				args.push(arguments[i]);
-		
-			bindFunc.apply(bindThis, args);
-		}
-
-		return IE_bind;
-	}
-}
-
-//	attachEvent -> addEventListener
-
-if (window.attachEvent && !window.addEventListener) {
-	function IE_addEventListener(signal, func, capture) {
-		var obj = this;
-		
-		func.IE_eventHandler = function(event) {
-			event.target = event.srcElement;
-			event.layerY = event.clientY;
-			event.layerX = event.clientX;
-			event.pageX = event.offsetX;
-			event.pageY = event.offsetY;
-			event.stopPropagation = function() {
-				this.cancelBubble = true;
-			}
-			
-			func.call(obj, event);
-		}
-
-		this.attachEvent('on' + signal, func.IE_eventHandler);
-	}
-	
-	function IE_removeEventListener(signal, func, capture) {
-		this.detachEvent('on' + signal, func.IE_eventHandler);
-	}
-
-	window.addEventListener = IE_addEventListener;
-	window.removeEventListener = IE_removeEventListener;
-	document.addEventListener = IE_addEventListener;
-	document.removeEventListener = IE_removeEventListener;
-
-	var IE_createElement = document.createElement;
-
-	document.createElement = function(tagName) {
-		var node = IE_createElement(tagName);
-		node.addEventListener = IE_addEventListener;
-		node.removeEventListener = IE_removeEventListener;
-		return node;
-	}
-}
-
-//	ActiveXObject ('Microsoft.XMLHTTP') -> XMLHttpRequest
-
-if (!window.XMLHttpRequest && window.ActiveXObject) {
-	function XMLHttpRequest() {
-		return new ActiveXObject('Microsoft.XMLHTTP');
-	}
-}
-
diff --git a/js/vn/iterator-iface.js b/js/vn/iterator-iface.js
deleted file mode 100644
index e7f91724..00000000
--- a/js/vn/iterator-iface.js
+++ /dev/null
@@ -1,67 +0,0 @@
-
-var LotIface = require('./lot-iface');
-var ModelIface = require('./model-iface');
-
-module.exports = new Class({
-	Implements: LotIface
-	,Properties: {
-		/**
-		 * The model associated to this form.
-		 */
-		model: {
-			type: ModelIface
-		},
-		/**
-		 * The row where the form positioned, has -1 if the row is unselected.
-		 */
-		row: { 
-			type: Number
-		},
-		/**
-		 * The number of rows in the form.
-		 */
-		numRows: {
-			type: Number
-		},
-		/**
-		 * Checks if the form data is ready.
-		 */
-		ready: {
-			type: Boolean
-		}
-	}
-	
-	,insertRow() {
-		if (this._model)
-			this.row = this._model.insertRow();
-	}
-
-	/**
-	 * Removes the current row.
-	 */
-	,deleteRow() {
-		if (this._row >= 0)
-			this._model.deleteRow(this._row);
-	}
-	
-	/**
-	 * Gets a value from the form.
-	 *
-	 * @param {string} columnName The column name
-	 * @return {Object} The value
-	 */
-	,get(columnName) {
-		return this._model ?
-			this._model.get(this._row, columnName) : undefined;
-	}
-
-	/**
-	 * Sets a value on the form.
-	 *
-	 * @param {string} columnName The column name
-	 * @param {Object} value The new value
-	 */
-	,set(columnName, value) {
-		this._model.set(this._row, columnName, value);
-	}
-});
diff --git a/js/vn/iterator.js b/js/vn/iterator.js
deleted file mode 100644
index db609daa..00000000
--- a/js/vn/iterator.js
+++ /dev/null
@@ -1,75 +0,0 @@
-
-var Lot = require('./lot');
-var IteratorIface = require('./iterator-iface');
-var ModelIface = require('./model-iface');
-
-/**
- * A light iterator for models. It assumes that its row and model properties
- * are always valid.
- */
-module.exports = new Class({
-	Extends: Lot
-	,Implements: IteratorIface
-	,Properties: {
-		model: {
-			type: ModelIface
-			,set(x) {
-				this._model = x;
-			}
-			,get() {
-				return this._model;
-			}
-		},
-		row: {
-			type: Number
-			,set(x) {
-				this._row = x;
-				this.rowChanged();
-			}
-			,get() {
-				return this._row;
-			}
-		},
-		numRows: {
-			type: Number
-			,get() {
-				return this._model ?
-					this._model.numRows : 0;
-			}
-		},
-		ready: {
-			type: Boolean
-			,get() {
-				return this._model ?
-					this._model.ready : false;
-			}
-		}
-	}
-
-	,_model: null
-
-	,initialize(props) {
-		Object.assign(this, {
-			 _row: -1
-			,_rowLock: false
-		});
-		Lot.prototype.initialize.call(this, props);
-	}
-
-	,_paramsChanged(diff) {
-		if (!this._rowLock)
-		for (var key in diff)
-			this._model.set(this._row, key, diff[key]);
-	}
-
-	,rowChanged() {
-		var row;
-		
-		if (this._model)
-			row = this._model.getObject(this._row);
-
-		this._rowLock = true;
-		this.params = row != null ? row : {};
-		this._rowLock = false;
-	}
-});
diff --git a/js/vn/json-connection.js b/js/vn/json-connection.js
deleted file mode 100644
index 578582e3..00000000
--- a/js/vn/json-connection.js
+++ /dev/null
@@ -1,317 +0,0 @@
-
-const VnObject = require('./object');
-const JsonException = require('./json-exception');
-
-/**
- * Handler for JSON rest connections.
- */
-module.exports = new Class({
-	Extends: VnObject,
-
-	_connected: false,
-	_requestsCount: 0,
-	token: null,
-
-	/**
-	 * Initilizes the connection object.
-	 */
-	initialize() {
-		VnObject.prototype.initialize.call(this);
-		this.fetchToken();
-	},
-
-	fetchToken() {
-		let token = null;
-	
-		if (sessionStorage.getItem('vnToken'))
-			token = sessionStorage.getItem('vnToken');
-		if (localStorage.getItem('vnToken'))
-			token = localStorage.getItem('vnToken');
-			
-		this.token = token;
-	},
-	
-	clearToken() {
-		this.token = null;
-		localStorage.removeItem('vnToken');
-		sessionStorage.removeItem('vnToken');
-	},
-
-	/**
-	 * Opens the connection to the REST service.
-	 *
-	 * @param {String} user The user name
-	 * @param {String} password The user password
-	 * @param {Boolean} remember Specifies if the user should be remembered
-	 * @return {Promise} Resolved when operation is done
-	 */
-	async open(user, pass, remember) {
-		let params;
-
-		if (user !== null && user !== undefined) {
-			params = {
-				user: user,
-				password: pass,
-				remember: remember
-			};
-		} else
-			params = null;
-
-		try {
-			const json = await this.post('Accounts/login', params);
-
-			const storage = remember ? localStorage : sessionStorage;
-			storage.setItem('vnToken', json.token);
-
-			this.token = json.token;
-			this._connected = true;
-			this.emit('openned');
-		} catch(err) {
-			this._closeClient();
-			throw err;
-		}
-	},
-
-	/**
-	 * Closes the connection to the REST service.
-	 *
-	 * @return {Promise} Resolved when operation is done
-	 */
-	async close() {
-		const token = this.token;
-		this._closeClient();
-		this.emit('closed');
-
-		if (token) {
-			const config = {
-				headers: {'Authorization': token}
-			};
-			await this.post('Accounts/logout', null, config);
-		}
-	},
-
-	
-	_closeClient() {
-		this._connected = false;
-		this.clearToken();
-	},
-
-	/**
-	 * Supplants another user.
-	 *
-	 * @param {String} supplantUser The user name
-	 */
-	async supplantUser(supplantUser) {
-		const json = await this.send('client/supplant', {supplantUser});
-		this.token = json;
-	},
-
-	/**
-	 * Ends the user supplanting and restores the last login.
-	 */
-	async supplantEnd() {
-		await this.post('Accounts/logout');
-		this.fetchToken();
-	},
-
-	/**
-	 * Executes the specified REST service with the given params and calls
-	 * the callback when response is received.
-	 *
-	 * @param {String} url The service path
-	 * @param {Object} params The params to pass to the service
-	 * @return {Object} The parsed JSON response
-	 */
-	async send(url, params) {
-		if (!params) params = {};
-		params.srv = `json:${url}`;
-		return this.sendWithUrl('POST', '.', params);
-	},
-	
-	async sendForm(form) {
-		const params = {};
-		const elements = form.elements;
-
-		for (var i = 0; i < elements.length; i++)
-		if (elements[i].name)
-			params[elements[i].name] = elements[i].value;
-
-		return this.sendWithUrl('POST', form.action, params);
-	},
-	
-	async sendFormMultipart(form) {
-		return this.request({
-			method: 'POST',
-			url: form.action,
-			data: new FormData(form)
-		});
-	},
-
-	async sendFormData(formData) {
-		return this.request({
-			method: 'POST',
-			url: '',
-			data: formData
-		});
-	},
-
-	/*
-	 * Called when REST response is received.
-	 */
-	async sendWithUrl(method, url, params) {
-		return this.request({
-			method,
-			url,
-			data: Vn.Url.makeUri(params),
-			headers: {
-				'Content-Type': 'application/x-www-form-urlencoded'
-			}
-		});
-	},
-
-	async get(url, config) {
-		config = Object.assign({}, config, {
-			method: 'GET',
-			url: `api/${url}`
-		});
-		return this.request(config);
-	},
-
-	async post(url, data, config) {
-		return this.requestData('POST', url, data, config);
-	},
-
-	async patch(url, data, config) {
-		return this.requestData('PATCH', url, data, config);
-	},
-
-	async requestData(method, url, data, config) {
-		config = Object.assign({}, config, {
-			method,
-			url: `api/${url}`,
-			data: data && JSON.stringify(data),
-		});
-		
-		config.headers = Object.assign({}, config.headers, {
-			'Content-Type': 'application/json;charset=utf-8'
-		});
-		return this.request(config);
-	},
-
-	async request(config) {
-		const request = new XMLHttpRequest();
-		request.open(config.method, config.url, true);
-		if (this.token)
-			request.setRequestHeader('Authorization', this.token);
-
-		const headers = config.headers;
-		if (headers)
-		for (const header in headers)
-			request.setRequestHeader(header, headers[header]);
-
-		const promise = new Promise((resolve, reject) => {
-			request.onreadystatechange =
-				() => this._onStateChange(request, resolve, reject);
-		});
-
-		request.send(config.data);
-
-		this._requestsCount++;
-		
-		if (this._requestsCount === 1)
-			this.emit('loading-changed', true);
-
-		return promise;
-	},
-	
-	_onStateChange(request, resolve, reject) {
-		if (request.readyState !== 4)
-			return;
-
-		this._requestsCount--;
-		
-		if (this._requestsCount === 0)
-			this.emit('loading-changed', false);
-
-		let data = null;
-		let error = null;
-		try {
-			if (request.status == 0) {
-				const err = new JsonException();
-				err.message = _('The server does not respond, please check your Internet connection');
-				err.statusCode = request.status;
-				throw err;
-			}
-		
-			let contentType = null;
-			
-			try {
-				contentType = request
-					.getResponseHeader('Content-Type')
-					.split(';')[0]
-					.trim();
-			} catch (err) {
-				console.warn(err);
-			}
-				
-			if (contentType != 'application/json') {
-				const err = new JsonException();
-				err.message = request.statusText;
-				err.statusCode = request.status;
-				throw err;
-			}
-
-			let json;
-			let jsData;
-
-			if (request.responseText)
-				json = JSON.parse(request.responseText);
-			if (json)
-				jsData = json.data || json;
-
-			if (request.status >= 200 && request.status < 300) {
-				data = jsData;
-			} else {
-				let exception = jsData.exception;
-				let error = jsData.error;
-				let err = new JsonException();
-			
-				if (exception) {
-					exception = exception
-						.replace(/\\/g, '.')
-						.replace(/Exception$/, '')
-						.replace(/^Vn\.Web\./, '');
-
-					err.exception = exception;
-					err.message = jsData.message;
-					err.code = jsData.code;
-					err.file = jsData.file;
-					err.line = jsData.line;
-					err.trace = jsData.trace;
-					err.statusCode = request.status;
-				} else if (error) {
-					err.message = error.message;
-					err.code = error.code;
-					err.statusCode = request.status;
-				} else {
-					err.message = request.statusText;
-					err.statusCode = request.status;
-				}
-
-				throw err;
-			}
-		} catch (e) {
-			data = null;
-			error = e;
-		}
-
-		if (error) {
-			if (error.exception == 'SessionExpired')
-				this.clearToken();
-
-			this.emit('error', error);
-			reject(error);
-		} else
-			resolve(data);
-	}
-});
diff --git a/js/vn/json-exception.js b/js/vn/json-exception.js
deleted file mode 100644
index 318cfbc8..00000000
--- a/js/vn/json-exception.js
+++ /dev/null
@@ -1,15 +0,0 @@
-/**
- * This class stores the database errors.
- */
-module.exports = class JsonException {
-	constructor(exception, message, code, file, line, trace, statucCode) {
-		this.name = 'JsonException';
-		this.exception = exception;
-		this.message = message;
-		this.code = code;
-		this.file = file;
-		this.line = line;
-		this.trace = trace;
-		this.statusCode = statucCode;
-	}
-}
diff --git a/js/vn/locale.js b/js/vn/locale.js
deleted file mode 100644
index 61cd3aea..00000000
--- a/js/vn/locale.js
+++ /dev/null
@@ -1,98 +0,0 @@
-const yaml = require('js-yaml');
-
-const locales = {};
-let fallbackLang = 'en';
-let lang = null;
-
-/**
- * Class to manage the internationalization.
- */
-module.exports =
-{
-	init() {
-		if (lang) return;
-		this.loads = {};
-		this.locales = locales;
-		this.fallbackLang = fallbackLang;
-
-		const languages = navigator.languages;
-
-		if (languages && languages.length > 0)
-			lang = languages[0];
-		else if (navigator.language)
-			lang = navigator.language;
-
-		lang = lang ? lang.substr(0, 2) : fallbackLang;
-		this.language = lang;
-	},
-
-	async load(path) {
-		this.init();
-		await Promise.all([
-			this.loadLang(path, fallbackLang),
-			this.loadLang(path, lang)
-		]);
-	},
-
-	/**
-	 * @returns {Promise}
-	 */
-	async loadLang(path, lang) {
-		let langLoad = this.loads[lang];
-		if (!langLoad)
-			langLoad = this.loads[lang] = {};
-
-		if (langLoad[path])
-			return Promise.resolve();
-		langLoad[path] = true;
-
-		const langFile = `${path}/locale/${lang}.yml${Vn.getVersion()}`;
-		const request = new XMLHttpRequest();
-		request.open('get', langFile, true);
-
-		const promise = new Promise((resolve, reject) => {
-			request.onreadystatechange =
-				() => this.onRequestReady(request, resolve, reject);
-		});
-
-		request.send();
-
-		try {
-			const translations = await promise;
-			this.add(translations, lang);
-		} catch(err) {
-			langLoad[path] = false;
-			//console.warn(err);
-		}
-	},
-
-	onRequestReady(request, resolve, reject) {
-		if (request.readyState != 4)
-			return;
-		if (request.status < 200 || request.status >= 400)
-			return reject(new Error(`HTTP ${request.status}: ${request.statusText}`));
-
-		resolve(yaml.safeLoad(request.responseText));
-	},
-	
-	add(translations, myLang) {
-		if (!translations) return;
-		myLang = myLang || lang;
-		let langLocales = locales[myLang];
-		if (!langLocales)
-			langLocales = locales[myLang] = {};
-		for (const str in translations)
-			langLocales[str] = translations[str];
-	}
-}
-
-function getString(stringId, lang) {
-	return locales[lang] ? locales[lang][stringId] : null;
-}
-
-window._ = function(stringId) {
-	let string = getString(stringId, lang);
-	if (!string)
-		string = getString(stringId, fallbackLang);
-	return string || stringId;
-}
diff --git a/js/vn/locale/ca.yml b/js/vn/locale/ca.yml
deleted file mode 100644
index 8af6588c..00000000
--- a/js/vn/locale/ca.yml
+++ /dev/null
@@ -1,44 +0,0 @@
-Sunday: Diumenge
-Monday: Dilluns
-Tuesday: Dimarts
-Wednesday: Dimecres
-Thursday: Dijous
-Friday: Divendres
-Saturday: Dissabte
-Su: Dg
-Mo: Dl
-Tu: Dt
-We: Dc
-Th: Dj
-Fr: Dv
-Sa: Ds
-January: Gener
-February: Febrer
-March: Març
-April: Abril
-May: Maig
-June: Juny
-July: Juliol
-August: Agost
-September: Setembre
-October: Octubre
-November: Novembre
-December: Decembre
-Jan: Gen
-Feb: Febr
-Mar: Març
-AbrMay: Mai
-Apr: Abr
-Jun: Juny
-Jul: Jul
-Ago: Ag
-Sep: Set
-Oct: Oct
-Nov: Nov
-Dec: Des
-'%A, %B %e': '%A, %e de %B'
-Something went wrong: Alguna cosa ha anat malament
-'The server does not respond, please check your Internet connection': 'El servidor no respon, si us plau comprova la teva connexió a Internet'
-Accept: Acceptar
-Cancel: Cancel·lar
-Retry: Reintenta
diff --git a/js/vn/locale/en.yml b/js/vn/locale/en.yml
deleted file mode 100644
index 4ca5bcfa..00000000
--- a/js/vn/locale/en.yml
+++ /dev/null
@@ -1,41 +0,0 @@
-Sunday: Sunday
-Monday: Monday
-Tuesday: Tuesday
-Wednesday: Wednesday
-Thursday: Thursday
-Friday: Friday
-Saturday: Saturday
-Su: Su
-Mo: Mo
-Tu: Tu
-We: We
-Th: Th
-Fr: Fr
-Sa: Sa
-January: January
-February: February
-March: March
-April: April
-May: May
-June: June
-July: July
-August: August
-September: September
-October: October
-November: November
-December: December
-Jan: Jan
-Feb: Feb
-Mar: Mar
-Apr: Apr
-AbrMay: May
-Jun: Jun
-Jul: Jul
-Ago: Ago
-Sep: Sep
-Oct: Oct
-Nov: Nov
-Dec: Dic
-'%A, %B %e': '%A, %B %e'
-Something went wrong: Something went wrong
-'The server does not respond, please check your Internet connection': 'The server does not respond, please check you Internet connection'
diff --git a/js/vn/locale/es.yml b/js/vn/locale/es.yml
deleted file mode 100644
index d9663c12..00000000
--- a/js/vn/locale/es.yml
+++ /dev/null
@@ -1,44 +0,0 @@
-Sunday: Domingo
-Monday: Lunes
-Tuesday: Martes
-Wednesday: Miércoles
-Thursday: Jueves
-Friday: Viernes
-Saturday: Sábado
-Su: Do
-Mo: Lu
-Tu: Ma
-We: Mi
-Th: Ju
-Fr: Vi
-Sa: Sa
-January: Enero
-February: Febrero
-March: Marzo
-April: Abril
-May: Mayo
-June: Junio
-July: Julio
-August: Agosto
-September: Septiembre
-October: Octubre
-November: Noviembre
-December: Diciembre
-Jan: Ene
-Feb: Feb
-Mar: Mar
-Apr: Abr
-AbrMay: May
-Jun: Jun
-Jul: Jul
-Ago: Ago
-Sep: Sep
-Oct: Oct
-Nov: Nov
-Dec: Dic
-'%A, %B %e': '%A, %e de %B'
-Something went wrong: Algo salió mal
-'The server does not respond, please check your Internet connection': 'El servidor no responde, por favor comprueba tu conexión a Internet'
-Accept: Aceptar
-Cancel: Cancelar
-Retry: Reintentar
diff --git a/js/vn/locale/fr.yml b/js/vn/locale/fr.yml
deleted file mode 100644
index a2789597..00000000
--- a/js/vn/locale/fr.yml
+++ /dev/null
@@ -1,44 +0,0 @@
-Sunday: Dimanche
-Monday: Lundi
-Tuesday: Mardi
-Wednesday: Mercredi
-Thursday: Jeudi
-Friday: Vendredi
-Saturday: Samedi
-Su: Do
-Mo: Lu
-Tu: Ma
-We: Me
-Th: Je
-Fr: Ve
-Sa: Sa
-January: Janvier
-February: Février
-March: Mars
-April: Avril
-May: Mai
-June: Juin
-July: Juillet
-August: Août
-September: Septembre
-October: Octobre
-November: Novembre
-December: Décembre
-Jan: Jan
-Feb: Fév
-Mar: Mars
-Apr: Avr
-AbrMay: Mai
-Jun: Juin
-Jul: Juil
-Ago: Août
-Sep: Sep
-Oct: Oct
-Nov: Nov
-Dec: Déc
-'%A, %B %e': '%A, %B %e'
-Something went wrong: Quelque-chose s'est mal passé
-'The server does not respond, please check your Internet connection': 'Le serveur ne répond pas, s''il vous plaît vérifier votre connexion Internet'
-Accept: Accepter
-Cancel: Annuler
-Retry: Réessayer
diff --git a/js/vn/locale/mn.yml b/js/vn/locale/mn.yml
deleted file mode 100644
index 97eb4d32..00000000
--- a/js/vn/locale/mn.yml
+++ /dev/null
@@ -1,41 +0,0 @@
-Sunday: Ням гараг
-Monday: Даваа гариг
-Tuesday: Мягмар
-Wednesday: Лхагва
-Thursday: Пүрэв
-Friday: Баасан гариг
-Saturday: Бямба
-Su: Ня
-Mo: Да
-Tu: Мя
-We: Лх
-Th: Пү
-Fr: Ба
-Sa: Бя
-January: оны нэгдүгээр сарын
-February: хоёрдугаар сар
-March: Гуравдугаар сарын
-April: Дөрөвдүгээр сар
-May: May
-June: June
-July: July
-August: Наймдугаар сар
-September: Есдүгээр
-October: Аравдугаар сар
-November: Арваннэгдүгээр
-December: Арванхоёрдугаар сар
-Jan: оны
-Feb: хоё
-Mar: Гур
-Apr: Дөр
-AbrMay: May
-Jun: Jun
-Jul: Jul
-Ago: Най
-Sep: Есд
-Oct: Ара
-Nov: Арв
-Dec: Арв
-'%A, %B %e': '%A, %B %e'
-Something went wrong: Something went wrong
-'The server does not respond, please check your Internet connection': 'The server does not respond, please check you Internet connection'
diff --git a/js/vn/locale/pt.yml b/js/vn/locale/pt.yml
deleted file mode 100644
index db6c2892..00000000
--- a/js/vn/locale/pt.yml
+++ /dev/null
@@ -1,44 +0,0 @@
-Sunday: Domingo
-Monday: Segunda-Feira
-Tuesday: Terça-Feira
-Wednesday: Quarta-Feira
-Thursday: Quinta-Feira
-Friday: Sexta-Feira
-Saturday: Sábado
-Su: Do
-Mo: Seg
-Tu: Ter
-We: Qua
-Th: Qui
-Fr: Sex
-Sa: Sab
-January: Janeiro
-February: Fevereiro
-March: Março
-April: Abril
-May: Mai
-June: Junho
-July: Julho
-August: Agosto
-September: Septembro
-October: Outubro
-November: Novembro
-December: Dezembro
-Jan: Jan
-Feb: Fev
-Mar: Mar
-Apr: Abr
-AbrMay: Mai
-Jun: Jun
-Jul: Jul
-Ago: Ago
-Sep: Set
-Oct: Out
-Nov: Nov
-Dec: Dez
-'%A, %B %e': '%A, %B %e'
-Something went wrong: Algo deu errado
-'The server does not respond, please check your Internet connection': 'O servidor não responde, por favor, verifique sua conexão com a Internet'
-Accept: Aceitar
-Cancel: Cancelar
-Retry: Tentar novamente
diff --git a/js/vn/lot-iface.js b/js/vn/lot-iface.js
deleted file mode 100644
index 2678e9af..00000000
--- a/js/vn/lot-iface.js
+++ /dev/null
@@ -1,83 +0,0 @@
-
-/**
- * Holds a plain key-value javascript object and monitorizes changes over it.
- */
-module.exports = new Class({
-	Properties: {
-		/**
-		 * The internal object with the params, this is the lot internal object
-		 * and should be used for read-only purposes.
-		 */
-		params: { 
-			type: Object
-		}
-		/**
-		 * Shortcut for params property.
-		 */
-		,$: { 
-			type: Object
-		 }
-	 }
- 
-	 /**
-	  * Gets a value from the lot.
-	  *
-	  * @param {string} field The field name
-	  * @return {*} The field value
-	  */
-	 ,get(field) {
-		 return this.params[field];
-	 }
- 
-	 /**
-	  * Sets a value on the lot.
-	  *
-	  * @param {string} field The field name
-	  * @param {*} value The new field value
-	  */
-	 ,set(field, value) {
-		 var params = {};
-		 params[field] = value;
-		 this.assign(params);
-	 }
- 
-	 /**
-	  * Returns an array with the lot keys.
-	  * 
-	  * @return {Array} The lot keys
-	  */
-	 ,keys() {}
- 
-	 /**
-	  * Emits the 'change' signal on the lot.
-	  * 
-	  * @param {Object} changes The changed params and its values
-	  */
-	 ,changed(changes) {
-		 this.emit('change', changes);
-	 }
- 
-	 /**
-	  * Copies all values from another lot.
-	  *
-	  * @param {Object} object The source object
-	  */
-	 ,assign() {}
- 
-	 /**
-	  * Copies all values from another lot.
-	  *
-	  * @param {LotIface} lot The source lot
-	  */
-	 ,assignLot(lot) {
-		 this.assign(lot.$);
-	 }
- 
-	 /**
-	  * Resets all values.
-	  */
-	 ,reset() {
-		 this.params = {};
-	 }
- });
- 
\ No newline at end of file
diff --git a/js/vn/lot-query.js b/js/vn/lot-query.js
deleted file mode 100644
index 8b4748b0..00000000
--- a/js/vn/lot-query.js
+++ /dev/null
@@ -1,122 +0,0 @@
-
-var Lot = require('./lot');
-var LotIface = require('./lot-iface');
-var Spec = require('./spec');
-var Value = require('./value');
-
-module.exports = new Class({
-	Extends: Lot
-	,Tag: 'vn-lot-query'
-	,Properties: {
-		fields: { 
-			type: Array
-			,set(x) {
-				this._fields = x;
-				this._onSourceChange();
-			}
-			,get() {
-				return this._fields;
-			}
-		},
-		source: { 
-			type: LotIface
-			,set(x) {
-				this.link({_source: x}, {change: this._onSourceChange});
-				this._onSourceChange();
-			}
-			,get() {
-				return this._source;
-			}
-		}
-	}
-
-	,initialize(props) {
-		Object.assign(this, {
-			_fields: null,
-			_source: null,
-			_lockSource: false,
-			_specs: {}
-		});
-		Lot.prototype.initialize.call(this, props);
-	}
-
-	,appendChild(child) {
-		if (!(child instanceof Spec))
-			throw new Error('VnLotQuery: Child must be a Vn.Spec instance');
-
-		this._specs[child.name] = child;
-		this._onSourceChange();
-	}
-
-	,_onSourceChange() {
-		if (this._lockSource)
-			return;
-
-		var params = this._source ? this._source.params : {};
-		var myParams = {};
-
-		for (var key in this._specs)
-			myParams[key] = Value.simpleClone(params[key]);
-
-		this.assign(myParams);
-	}
-
-	,assign(params) {
-		params = this.transformParams(params);
-		var diff = Value.partialDiff(this._params, params);
-		this._assign(diff);
-	}
-
-	,setAll(params) {
-		params = this.transformParams(params);
-		var diff = Value.diff(this._params, params);
-		this._assign(diff);
-	}
-
-	,_assign(diff) {
-		if (diff) {
-			Object.assign(this._params, diff);
-
-			if (this.source) {
-				this._lockSource = true;
-				this.source.assign(diff);
-				this._lockSource = false;
-			}
-
-			this._paramsChanged(diff);
-			this.changed(diff);
-		}
-	}
-
-	,transformParams(params) {
-		var newParams = {};
-
-		for (var key in this._specs) {
-			var spec = this._specs[key];
-			if (params[key])
-				newParams[key] = cast(params[key], spec.type);
-		}
-
-		return Object.assign(params, newParams);
-	}
-});
-
-function cast(value, type) {
-	switch (type) {
-		case Boolean:
-			return (/^(true|1)$/i).test(value);
-		case Number:
-			return 0 + new Number(value);
-		case Date:
-			var date = new Date(value);
-			date.setHours(0, 0, 0, 0);
-			return date;
-		case String:
-			return value;
-		default:
-		if (type instanceof Object)
-			return JSON.parse(value);
-		else
-			return value;
-	}
-}
diff --git a/js/vn/lot.js b/js/vn/lot.js
deleted file mode 100644
index 7d84aba4..00000000
--- a/js/vn/lot.js
+++ /dev/null
@@ -1,69 +0,0 @@
-
-var VnObject = require('./object');
-var LotIface = require('./lot-iface');
-var Value = require('./value');
-
-module.exports = new Class({
-	Extends: VnObject
-	,Implements: LotIface
-	,Tag: 'vn-lot'
-	,Properties: {
-		$: {
-			type: Object
-			,set(x) {
-				this.setAll(x);
-			}
-			,get() {
-				return this._params;
-			}
-		}
-		,params: {
-			type: Object
-			,set(x) {
-				this.$ = x;
-			}
-			,get() {
-				return this.$;
-			}
-		}
-	}
-
-	,initialize(props) {
-		this._params = new Proxy({}, {
-			set(obj, prop, value) {
-				return Reflect.set(obj, prop, value);
-			}
-		});
-		VnObject.prototype.initialize.call(this, props);
-	}
-	
-	,keys() {
-		return Object.keys(this._params);
-	}
-
-	,assign(params) {
-		var diff = Value.partialDiff(this._params, params);
-		this._assign(diff);
-	}
-
-	,setAll(params) {
-		var diff = Value.diff(this._params, params);
-		this._assign(diff);
-	}
-
-	,_assign(diff) {
-		if (diff) {
-			Object.assign(this._params, diff);
-			this._paramsChanged(diff);
-			this.changed(diff);
-		}
-	}
-
-	/**
-	 * Called when lot params changes, can be implemented by child classes to be
-	 * notified about changes.
-	 * 
-	 * @param {Object} diff Changed parameters and its new values
-	 */
-	,_paramsChanged() {}
-});
diff --git a/js/vn/model-iface.js b/js/vn/model-iface.js
deleted file mode 100644
index d5218a14..00000000
--- a/js/vn/model-iface.js
+++ /dev/null
@@ -1,127 +0,0 @@
-
-/**
- * Readable data model.
- */
- module.exports = new Class({
-	 Properties: {
-		 /**
-		  * The number of rows in the model.
-		  */
-		 numRows: {
-			 type: Number
-		 },
-		 /**
-		  * The current status of the model.
-		  */
-		 status: {
-			 type: Number
-		 },
-		 /**
-		  * Checks if the model data is ready.
-		  */
-		 ready: {
-			 type: Boolean
-		 }
-	 }
- 
-	 /**
-	  * Checks if the column exists.
-	  *
-	  * @param {integer} column The column index
-	  * @return {boolean} %true if column exists, %false otherwise
-	  */
-	 ,checkColExists() {}
- 
-	 /**
-	  * Checks if the row exists.
-	  *
-	  * @param {integer} rowIndex The row index
-	  * @return {boolean} %true if row exists, %false otherwise
-	  */
-	 ,checkRowExists() {}
-	 
-	 /**
-	  * Get the index of the column from its name.
-	  *
-	  * @param {string} columnName The column name
-	  * @return {number} The column index or -1 if column not exists
-	  */
-	 ,getColumnIndex() {}
-	 
-	 /**
-	  * Gets a value from the model.
-	  *
-	  * @param {number} rowIndex The row index
-	  * @param {string} columnName The column name
-	  * @return {*} The value, or %undefined
-	  */
-	 ,get() {}
- 
-	 /**
-	  * Gets a value using the column index.
-	  *
-	  * @param {number} rowIndex The row index
-	  * @param {number} column The column index
-	  * @return {*} The value
-	  */
-	 ,getByIndex() {}
- 
-	 /**
-	  * Gets a row as an object  using the column index.
-	  *
-	  * @param {number} rowIndex The row index
-	  * @return {Object} The row as an object
-	  */
-	 ,getObject() {}
- 
-	 /**
-	  * Orders the model by the specified column name.
-	  *
-	  * @param {number} column The column name
-	  * @param {SortWay} way The sort way
-	  */
-	 ,sortByName() {}
- 
-	 /**
-	  * Orders the model by the specified column.
-	  *
-	  * @param {number} column The column index
-	  * @param {SortWay} way The sort way
-	  */
-	 ,sort() {}
- 
-	 /**
-	  * Searchs a value on the model and returns the row index of the first
-	  * ocurrence.
-	  * If an index have been built on that column, it will be used, for more
-	  * information see the indexColumn() method.
-	  *
-	  * @param {string} column The column name
-	  * @param {Object} value The value to search
-	  * @return {number} The column index
-	  */
-	 ,search() {}
- 
-	 /**
-	  * Searchs a value on the model and returns the row index of the first
-	  * ocurrence.
-	  *
-	  * @param {number} col The column index
-	  * @param {Object} value The value to search
-	  * @return {number} The column index
-	  */
-	 ,searchByIndex() {}
- 
-	 /**
-	  * Builds an internal hash index for the specified column, this speeds
-	  * significantly searches on that column, specially when model has a lot of
-	  * rows.
-	  *
-	  * FIXME: Not fully implemented.
-	  *
-	  * @param {string} column The column name
-	  */
-	 ,indexColumn() {}
- });
- 
- 
\ No newline at end of file
diff --git a/js/vn/model-proxy.js b/js/vn/model-proxy.js
deleted file mode 100644
index 71ff34f1..00000000
--- a/js/vn/model-proxy.js
+++ /dev/null
@@ -1,80 +0,0 @@
-
-var ModelIface = require('./object');
-
-/**
- * Monitorizes all changes made to a model.
- */
-var Klass = new Class();
-module.exports = Klass;
-
-var Mode = {
-	 ON_CHANGE : 1
-	,ON_DEMAND : 2
-};
-
-var Operation = {
-	 INSERT : 1 << 1
-	,UPDATE : 1 << 2
-	,DELETE : 1 << 3
-};
-
-Klass.extend({
-	 Mode: Mode
-	,Operation: Operation
-});
-
-Klass.implement({
-	Implements: ModelIface
-	,Properties: {
-		/**
-		 * Update mode.
-		 */
-		mode: {
-			enumType: Mode
-			,value: Mode.ON_CHANGE
-		}
-	}
-
-	/**
-	 * Updates a value on the model.
-	 *
-	 * @param {number} rowIndex The row index
-	 * @param {string} columnName The column name
-	 * @param {*} value The new value
-	 */
-	,set() {}
-
-	/**
-	 * Updates a value on the model using the column index.
-	 *
-	 * @param {number} rowIndex The row index
-	 * @param {number} col The column index
-	 * @param {*} value The new value
-	 */
-	,setByIndex() {}
-
-	/**
-	 * Deletes a row from the model. 
-	 *
-	 * @param {number} rowIndex The row index
-	 */
-	,deleteRow() {}
-
-	/**
-	 * Inserts a new row on the model.
-	 *
-	 * @return The index of the inserted row
-	 */
-	,insertRow() {}
-
-	/**
-	 * Cleans the model data.
-	 */
-	,clean() {}
-	
-	/**
-	 * Performs all model changes on the database.
-	 */
-	,performOperations() {}
-});
-
diff --git a/js/vn/model.js b/js/vn/model.js
deleted file mode 100644
index 9feeec24..00000000
--- a/js/vn/model.js
+++ /dev/null
@@ -1,350 +0,0 @@
-
-var VnObject = require('./object');
-var simpleEquals = require('./value').simpleEquals;
-
-var Klass = new Class();
-module.exports = Klass;
-
-var Status = {
-	 CLEAN    : 1
-	,LOADING  : 2
-	,READY    : 3
-	,ERROR    : 4
-};
-
-var SortWay = {
-	 ASC   : 1
-	,DESC  : 2 
-};
-
-Klass.extend({
-	 Status
-	,SortWay
-});
-
-Klass.implement({
-	Extends: VnObject
-	,Tag: 'vn-model'
-	,Properties: {
-		/**
-		 * The model internal data.
-		 */
-		data: {
-			type: Array
-			,get() {
-				return this._data;
-			}
-			,set(x) {
-				this._setData(x);
-			}
-		},
-		/**
-		 * The number of rows in the model.
-		 */
-		numRows: {
-			type: Number
-			,get() {
-				if (this._data)
-					return this._data.length;
-
-				return 0;
-			}
-		},
-		/**
-		 * The current status of the model.
-		 */
-		status: {
-			type: Number
-			,get() {
-				return this._status;
-			}
-		},
-		/**
-		 * Checks if the model data is ready.
-		 */
-		ready: {
-			type: Boolean
-			,get() {
-				return this._status === Status.READY;
-			}
-		}
-	}
-
-	,_data: null
-	,_status: Status.CLEAN
-
-	,_requestedSortName: null
-	,_sortColumn: null
-	,_sortWay: null
-
-	,_requestedIndexes: {}
-	,_indexes: []
-
-	//+++++++++++++++++++++++++++++ Data hadling
-	
-	,_setData(data) {
-		this._data = data;
-		this._refreshRowIndexes(0);
-
-		if (this._requestedSortName != null)
-			this._realSort(this._requestedSortName, this._sortWay);
-		for (column in this._requestedIndexes)
-			this._buildIndex(column);
-
-		this._setStatus(Status.READY);
-	}
-
-	/**
-	 * Checks if the row exists.
-	 *
-	 * @param {Integer} rowIndex The row index
-	 * @return {Boolean} %true if row exists, %false otherwise
-	 */
-	,checkRowExists(rowIndex) {
-		return this._data != null
-			&& rowIndex >= 0
-			&& rowIndex < this._data.length;
-	}
-
-	/**
-	 * Gets a value from the model.
-	 *
-	 * @param {Number} rowIndex The row index
-	 * @param {Number} columnName The column name
-	 * @return {*} The value
-	 */
-	,get(rowIndex, columnName) {
-		if (!this.checkRowExists(rowIndex))
-			return undefined;
-		
-		return this._data[rowIndex][columnName];
-	}
-
-	/**
-	 * Updates a value on the model.
-	 *
-	 * @param {Number} rowIndex The row index
-	 * @param {Number} columnName The column name
-	 * @param {*} value The new value
-	 */
-	,set(rowIndex, columnName, value) {
-		if (!this.checkRowExists(rowIndex))
-			return;
-
-		this.emit('row-updated-before', rowIndex);
-		this._data[rowIndex][columnName] = value;
-		this.emit('row-updated', rowIndex, [columnName]);
-	}
-
-	/**
-	 * Gets a row as an object using the column index.
-	 *
-	 * @param {Number} rowIndex The row index
-	 * @return {Object} The row as an object
-	 */
-	,getObject(rowIndex) {
-		return this.checkRowExists(rowIndex) ?
-			this._data[rowIndex] : null;
-	}
-	
-	,_setStatus(status) {
-		this._status = status;
-		this.emit('status-changed', status);
-		this.emit('status-changed-after', status);
-	}
-	
-	/**
-	* Inserts a new row on the model.
-	*
-	* @return The index of the inserted row
-	*/
-   ,insertRow(newRow) {
-		var rowIndex = this._data.push(newRow) - 1;
-		newRow.index = rowIndex;
-		this.emit('row-inserted', rowIndex);
-		return rowIndex;
-   }
-
-	/**
-	 * Deletes a row from the model. 
-	 *
-	 * @param {Number} rowIndex The row index
-	 */
-	,deleteRow(rowIndex) {
-		if (!this.checkRowExists(rowIndex))
-			return;
-
-		this.emit('row-deleted-before', rowIndex);
-		this._data.splice(rowIndex, 1);
-		this.emit('row-deleted', rowIndex);
-		this._refreshRowIndexes(rowIndex);
-	}
-
-	//+++++++++++++++++++++++++++++ Sorting
-
-	/**
-	 * Orders the model by the specified column name.
-	 *
-	 * @param {String} columnName The column name
-	 * @param {SortWay} way The sort way
-	 */
-	,sort(columnName, way) {
-		this._requestedSortName = columnName;
-		this._sort(columnName, way);
-	}
-	 
-	,_sort(columnName, way) {
-		var status = this._status;
-		this._setStatus(Status.LOADING);
-		this._realSort(columnName, way);
-		this._setStatus(status);
-	}
-	
-	,_realSort(columnName, way) {
-		if (!this._data)
-			return;
-
-		if (columnName !== this._sortColumn) {
-			if (way === SortWay.DESC)
-				var sortFunction = this.sortFunctionDesc;
-			else
-				var sortFunction = this.sortFunctionAsc;
-	
-			this._data.sort(sortFunction.bind(this, columnName));
-		} else if (way !== this._sortWay)
-			this._data.reverse();
-
-		this._sortColumn = columnName;
-		this._sortWay = way;
-
-		this._refreshRowIndexes(0);
-	}
-
-	,_refreshRowIndexes(start) {
-		var data = this._data;
-
-		for (var i = start; i < data.length; i++)
-			data[i].index = i;
-	}
-	
-	/*
-	 * Function used to sort the model ascending.
-	 */
-	,sortFunctionAsc(column, a, b) {
-		if (a[column] < b[column])
-			return -1;
-		else if (a[column] > b[column])
-			return 1;
-			
-		return 0;
-	}
-	
-	/*
-	 * Function used to sort the model descending.
-	 */
-	,sortFunctionDesc(column, a, b) {
-		if (a[column] > b[column])
-			return -1;
-		else if (a[column] < b[column])
-			return 1;
-			
-		return 0;
-	}
-	
-	//+++++++++++++++++++++++++++++ Searching
-
-	/**
-	 * Builds an internal hash index for the specified column, this speeds
-	 * significantly searches on that column, specially when model has a lot of
-	 * rows.
-	 *
-	 * FIXME: Not fully implemented.
-	 *
-	 * @param {String} column The column name
-	 */
-	,indexColumn(column) {
-		this._requestedIndexes[column] = true;
-
-		if (this._status === Status.READY)
-			this._buildIndex(column);
-	}
-
-	,getHashValue(value) {
-		if (value instanceof Date)
-			return value.getTime();
-		else
-			return value;
-	}
-
-	,_buildIndex(columnName) {
-		if (this.columnMap[columnName] === undefined)
-			return;
-
-		var data = this._data;
-		var values = {};
-		var nulls = [];
-
-		for (var i = 0; i < data.length; i++) {
-			var value = data[i][columnName];
-
-			if (value == null) {
-				nulls.push(data[i]);
-				continue;
-			}
-
-			index[this.getHashValue(value)] = data[i];
-		}
-
-		this._indexes[columnName] = {
-			values: values,
-			index: index
-		};
-	}
-
-	/**
-	 * Searchs a value on the model and returns the row index of the first
-	 * ocurrence.
-	 *
-	 * @param {Number} columnName The column name
-	 * @param {Object} value The value to search
-	 * @return {Number} The column index
-	 */
-	,search(columnName, value) {
-		var data = this._data;
-
-		if (data == null)
-			return -1;
-
-		// Searchs the value using an internal index.
-
-		var index = this._indexes[columnName];
-		
-		if (index) {
-			if (value == null) {
-				if (index.nulls[0] !== undefined)
-					return index.nulls[0].index;
-			} else {
-				var row = index.values[this.getHashValue(value)];
-
-				if (rowIndex !== undefined)
-					return row.index;
-			}
-
-			return -1;
-		}
-
-		// Searchs the value using a loop.
-
-		for (var i = 0; i < data.length; i++)
-		if (simpleEquals(data[i][columnName], value))
-			return i;
-
-		return -1;
-	}
-	
-	//+++++++++++++++++++++++++++++ Virtual
-
-	,refresh() {
-		this._setStatus(Status.READY);
-	}
-});
diff --git a/js/vn/mutators.js b/js/vn/mutators.js
deleted file mode 100644
index 0df4f97a..00000000
--- a/js/vn/mutators.js
+++ /dev/null
@@ -1,48 +0,0 @@
-
-vnCustomTags = {};
-
-const Mutators = Class.Mutators;
-const _Extends = Mutators.Extends;
-
-Mutators.Extends = function() {
-	_Extends.apply(this, arguments);
-	this.implement({Properties: {}});
-}
-
-Mutators.Template = function(template) {
-	this.extend({Template: template});
-};
-
-Mutators.Tag = function(tagName) {
-	vnCustomTags[tagName] = this;
-	this.extend({Tag: tagName});
-
-	const parent = this.parent;
-	if (parent && parent.Classes !== undefined) {
-		let Classes = tagName
-		
-		if (parent.Classes !== '')
-			Classes += ' '+ parent.Classes;
-		this.extend({Classes});
-	}
-};
-
-Mutators.Properties = function(props) {
-	let parentProps;
-	
-	for (const propName in props) {
-		const prop = props[propName];
-		prop.configurable = true;
-	
-		if (!prop.get && !prop.set && prop.writable === undefined)
-			prop.writable = true;
-	}
-
-	if (this.parent && (parentProps = this.parent.Properties))
-	for (const propName in parentProps)
-	if (!props[propName])
-		props[propName] = parentProps[propName];
-		
-	this.extend({Properties: props});
-	Object.defineProperties(this.prototype, props);
-};
diff --git a/js/vn/node-builder.js b/js/vn/node-builder.js
deleted file mode 100644
index c576f6c5..00000000
--- a/js/vn/node-builder.js
+++ /dev/null
@@ -1,23 +0,0 @@
-const VnObject = require('./object');
-
-module.exports = new Class({
-	Extends: VnObject
-
-	,doc: null
-	
-	,initialize(props) {
-		this.doc = document;
-		this.parent(props);
-	}
-	
-	,createElement(tagName) {
-		return this.doc.createElement(tagName);
-	}
-	
-	,createTextNode(text) {
-		return this.doc.createTextNode(text);
-	}
-	
-	,render() {}
-});
-
diff --git a/js/vn/node.js b/js/vn/node.js
deleted file mode 100644
index c75bac86..00000000
--- a/js/vn/node.js
+++ /dev/null
@@ -1,66 +0,0 @@
-
-module.exports =
-{
-	removeChilds: function (node)
-	{
-		var childs = node.childNodes;
-
-		if (childs)
-		while (childs.length > 0)
-			node.removeChild (childs[0]);
-	}
-
-	,remove: function (node)
-	{	
-		if (node.parentNode)
-			node.parentNode.removeChild (node);
-	}
-
-	,setText: function (node, text)
-	{
-		Vn.Node.removeChilds (node);
-
-		if (text)
-			node.appendChild (
-				node.ownerDocument.createTextNode (text));
-	}
-	
-	,addClass: function (node, className)
-	{
-/*		var classes = node.className.split (' ');
-		
-		if (classes.split (' ').indexOf (className) == -1)
-*/			node.className = className +' '+ node.className;
-	}
-	
-	,removeClass: function (node, className)
-	{
-		var index = 0;
-		var found = false;
-		var classes = node.className.split (' ');
-		
-		while ((index = classes.indexOf (className, index)) != -1)
-		{
-			classes.splice (index, 1);
-			found = true;
-		}
-		
-		if (found)
-			node.className = classes.join (' ');
-	}
-	
-	,hide: function (node)
-	{
-		node.style.display = 'none';
-	}
-	
-	,show: function (node)
-	{
-		node.style.display = 'block';
-	}
-};
-
-$ = function (id)
-{
-	return document.getElementById (id);
-}
diff --git a/js/vn/object.js b/js/vn/object.js
deleted file mode 100644
index 9ae2306b..00000000
--- a/js/vn/object.js
+++ /dev/null
@@ -1,260 +0,0 @@
-
-/**
- * The main base class. Manages the signal system. Objects based on this class
- * can be instantiated declaratively using XML.
- */
-module.exports = class VnObject {
-	/**
-	 * Tag to be used when the class instance is defined via XML. All classes 
-	 * must define this attribute, even if it is not used.
-	 */
-	static Tag = 'vn-object';
-
-	/**
-	 * Class public properties.
-	 */
-	static Properties = {};
-
-	/*
-	 * Reference count.
-	 */
-	_refCount = 1;
-
-	/*
-	 * Signal handlers data.
-	 */
-	_thisArg = null;
-
-	/**
-	 * Initializes the object and sets all properties passed to the class
-	 * constructor.
-	 * 
-	 * @param {Object} props The properties passed to the contructor
-	 */
-	constructor(props) {
-		this.setProperties(props);
-	}
-
-	initialize(props) {
-		this.setProperties(props);
-	}
-	
-	/**
-	 * Sets a group of object properties.
-	 * 
-	 * @param {Object} props Properties
-	 */
-	setProperties(props) {
-		for (var prop in props)
-			this[prop] = props[prop];
-	}
-	
-	/**
-	 * Increases the object reference count.
-	 */
-	ref() {
-		this._refCount++;
-		return this;
-	}
-	
-	/**
-	 * Decreases the object reference count.
-	 */
-	unref() {
-		this._refCount--;
-		
-		if (this._refCount === 0)
-			this._destroy();
-	}
-
-	/**
-	 * Called from @Vn.Builder when it finds a custom tag as a child of the
-	 * element.
-	 * 
-	 * @param {Vn.Scope} scope The scope instance
-	 * @param {Node} node The custom tag child nodes
-	 */
-	loadXml() {}
-
-	/**
-	 * Called from @Vn.Builder when it finds a a child tag that isn't
-	 * associated to any property.
-	 * 
-	 * @param {Object} child The child object instance
-	 */
-	appendChild() {}
-
-	/**
-	 * Conects a signal with a function.
-	 *
-	 * @param {string} id The signal identifier
-	 * @param {function} callback The callback
-	 * @param {Object} instance The instance
-	 */
-	on(id, callback, instance) {
-		if (!(callback instanceof Function)) {
-			console.warn('Vn.Object: Invalid callback for signal \'%s\'', id);
-			return;
-		}
-		
-		this._signalInit();
-		var callbacks = this._thisArg.signals[id];
-
-		if (!callbacks)
-			callbacks = this._thisArg.signals[id] = [];
-			
-		callbacks.push({
-			blocked: false
-			,callback: callback
-			,instance: instance
-		});
-	}
-
-	/**
-	 * Locks/Unlocks a signal emission to the specified object.
-	 *
-	 * @param {string} id The signal identifier
-	 * @param {function} callback The callback
-	 * @param {boolean} block %true for lock the signal, %false for unlock
-	 */
-	blockSignal(id, callback, block, instance) {
-		if (!this._thisArg)
-			return;
-
-		var callbacks = this._thisArg.signals[id];
-		
-		if (!callbacks)
-			return;
-			
-		for (var i = 0; i < callbacks.length; i++)
-		if (callbacks[i].callback == callback
-		&& callbacks[i].instance == instance)
-			callbacks[i].blocked = block;
-	}
-	
-	/**
-	 * Emits a signal in the object.
-	 *
-	 * @param {string} id The signal identifier
-	 */
-	emit(id) {
-		if (!this._thisArg)
-			return;
-
-		var callbacks = this._thisArg.signals[id];
-		
-		if (!callbacks)
-			return;
-
-		var callbackArgs = [];
-		callbackArgs.push(this);
-	
-		for (var i = 1; i < arguments.length; i++)
-			callbackArgs.push(arguments[i]);
-
-		for (var i = 0; i < callbacks.length; i++)
-		if (!callbacks[i].blocked)
-			callbacks[i].callback.apply(callbacks[i].instance, callbackArgs);
-	}
-	
-	/**
-	 * Disconnects a signal from current object.
-	 *
-	 * @param {string} id The signal identifier
-	 * @param {function} callback The connected callback
-	 * @param {Object} instance The instance
-	 */
-	disconnect(id, callback, instance) {
-		if (!this._thisArg)
-			return;
-
-		var callbacks = this._thisArg.signals[id];
-		
-		if (callbacks)
-		for (var i = callbacks.length; i--;)
-		if (callbacks[i].callback === callback
-		&& callbacks[i].instance === instance)
-			callbacks.splice(i, 1);
-	}
-	
-	/**
-	 * Disconnects all signals for the given instance.
-	 *
-	 * @param {Object} instance The instance
-	 */
-	disconnectByInstance(instance) {
-		if (!this._thisArg)
-			return;
-	
-		var signals = this._thisArg.signals;
-
-		for (var signalId in signals) {
-			var callbacks = signals[signalId];
-
-			if (callbacks)
-			for (var i = callbacks.length; i--;)
-			if (callbacks[i].instance === instance)
-				callbacks.splice(i, 1);
-		}
-	}
-
-	/**
-	 * Destroys the object, this method should only be called before losing
-	 * the last reference to the object. It can be overwritten by child classes
-	 * but should always call the parent method.
-	 */
-	_destroy() {
-		if (!this._thisArg)
-			return;
-	
-		var links = this._thisArg.links;
-	
-		for (var key in links)
-			this._unlink(links[key]);
-		
-		this._thisArg = null;
-	}
-	
-	/**
-	 * Links the object with another object.
-	 * 
-	 * @param {Object} prop The linked property
-	 * @param {Object} handlers The object events to listen with
-	 */
-	link(prop, handlers) {
-		this._signalInit();
-		var links = this._thisArg.links;
-	
-		for (var key in prop) {
-			var newObject = prop[key];
-			var oldObject = this[key];
-		
-			if (oldObject)
-				this._unlink(oldObject);
-
-			this[key] = newObject;
-
-			if (newObject) {
-				links[key] = newObject.ref();
-
-				for (var signal in handlers)
-					newObject.on(signal, handlers[signal], this);
-			} else if (oldObject)
-				links[key] = undefined;
-		}
-	}
-
-	_unlink(object) {
-		if (!object) return;
-		object.disconnectByInstance(this);
-		object.unref();
-	}
-	
-	_signalInit() {
-		if (!this._thisArg)
-			this._thisArg = {
-				signals: {},
-				links: {}
-			};
-	}
-}
diff --git a/js/vn/param-iface.js b/js/vn/param-iface.js
deleted file mode 100644
index 98134303..00000000
--- a/js/vn/param-iface.js
+++ /dev/null
@@ -1,139 +0,0 @@
-
-var LotIface = require('./lot-iface');
-var Type = require('./type');
-var Value = require('./value');
-
-/**
- * A value holder, it emits the changed signal when value is changed.
- * Also it can be linked with a lot value or another parameter.
- */
-module.exports = new Class({
-	Properties: {
-		/**
-		 * The parameter value.
-		 */
-		value: {
-			type: null
-		},
-		/**
-		 * The parameter type.
-		 */
-		type: {
-			type: Type
-		},
-		/**
-		 * Another parameter to bind with.
-		 */
-		param: {
-			type: Object
-		},
-		/**
-		 * A lot to bind with.
-		 */
-		lot: {
-			type: LotIface
-		},
-		/**
-		 * The field name in the lot.
-		 */
-		name: {
-			type: String
-		},
-		/**
-		 * Determines whether the link to the lot is unidirectional, ie, a
-		 * change in the lot updates the parameter but not viceversa.
-		 */
-		oneWay: {
-			type: Boolean
-		}
-	}
-	
-	,_value: undefined
-	,_type: null
-	,_param: null
-	,_lot: null
-	,_sourceLock: false
-	,_name: null
-	,_oneWay: false
-	
-	,_setValue(newValue) {
-		if (this._putValue(newValue))
-			this._notifyChanges();
-	}
-
-	,_putValue(newValue) {
-		if (Value.simpleEquals(newValue, this._value))
-			return false;
-
-		this._value = Value.simpleClone(newValue);
-		return true;
-	}
-
-	,_notifyChanges() {
-		this._refreshLot();
-		this._refreshParam();
-		this.emit('changed', this._value);
-	}
-
-	,_setType(type) {
-		this._type = type;
-		this._onLotChange();
-	}
-
-	,_onSourceChange(newValue) {
-		if (this._oneTime && this._value !== undefined)
-			return;
-
-		this._sourceLock = true;
-		this._setValue(newValue);
-		this._sourceLock = false;
-	}
-	
-	,_setParam(param) {
-		this.link({_lot: null});
-		this.link({_param: param}, {changed: this._onParamChange});
-		this._refreshParam();
-	}
-
-	,_onParamChange() {
-		if (this._sourceLock || !this._param) return;
-		this._onSourceChange(this._param.value);
-	}
-
-	,_refreshParam() {
-		if (this._sourceLock || !this._param || this._oneWay)
-			return;
-
-		this._sourceLock = true;
-		this._param.value = this._value;
-		this._sourceLock = false;
-	}
-
-	,_setLot(lot) {
-		this.link({_param: null});
-		this.link({_lot: lot}, {change: this._onLotChange});
-		this._onLotChange();
-	}
-
-	,_onLotChange() {
-		if (this._sourceLock || !this._lot || !this._name)
-			return;
-
-		var newValue = this._lot.get(this._name, this._type);
-		this._onSourceChange(newValue);
-	}
-
-	,_refreshLot() {
-		if (this._sourceLock || !this._name || !this._lot || this._oneWay)
-			return;
-
-		this._sourceLock = true;
-		this._lot.set(this._name, this._value);
-		this._sourceLock = false;
-	}
-
-	,_setName(name) {
-		this._name = name;
-		this._onLotChange();
-	}
-});
diff --git a/js/vn/param.js b/js/vn/param.js
deleted file mode 100644
index cc9d5b25..00000000
--- a/js/vn/param.js
+++ /dev/null
@@ -1,88 +0,0 @@
-
-var VnObject = require('./object');
-var Type = require('./type');
-var ParamIface = require('./param-iface');
-var LotIface = require('./lot-iface');
-
-/**
- * A simple implementation of @ParamIface.
- */
-module.exports = new Class({
-	Extends: VnObject
-	,Implements: ParamIface
-	,Tag: 'vn-param'
-	,Properties: {
-		value: {
-			type: null
-			,set(x) {
-				this._setValue(x);
-			}
-			,get() {
-				return this._value;
-			}
-		},
-		type: {
-			type: Type
-			,set(x) {
-				this._setType(x);
-			}
-			,get() {
-				return this._type;
-			}
-		},
-		param: {
-			type: ParamIface
-			,set(x) {
-				this._setParam(x);
-			}
-			,get() {
-				return this._param;
-			}
-		},
-		master: {
-			type: ParamIface
-			,set(x) {
-				this._setParam(x);
-			}
-			,get() {
-				return this._param;
-			}
-		},
-		lot: {
-			type: LotIface
-			,set(x) {
-				this._setLot(x);
-			}
-			,get() {
-				return this._lot;
-			}
-		},
-		name: {
-			type: String
-			,set(x) {
-				this._setName(x);
-			}
-			,get() {
-				return this._name;
-			}
-		},
-		oneWay: {
-			type: Boolean
-			,set(x) {
-				this._oneWay = x;
-			}
-			,get() {
-				return this._oneWay;
-			}
-		},
-		oneTime: {
-			type: Boolean
-			,set(x) {
-				this._oneTime = x;
-			}
-			,get() {
-				return this._oneTime;
-			}
-		}
-	}
-});
diff --git a/js/vn/scope.js b/js/vn/scope.js
deleted file mode 100644
index d0e78c08..00000000
--- a/js/vn/scope.js
+++ /dev/null
@@ -1,163 +0,0 @@
-const VnObject = require('./object');
-const kebabToCamel = require('./string-util').kebabToCamel;
-
-let scopeUid = 0;
-Vn.nWatchers = 0;
-
-module.exports = new Class({
-	Extends: VnObject
-
-	,initialize(builder, doc, objects, exprValues, thisArg, parent) {
-		this.builder = builder;
-		this.objects = objects;
-		this.exprValues = exprValues;
-		this.thisArg = thisArg;
-		this.parent = parent;
-		this.uid = ++scopeUid;
-		this.$ = parent ? Object.create(parent.$) : {};
-		Vn.nWatchers += exprValues.length;
-
-		if (parent) {
-			parent.ref();
-			// XXX: Keep commented until optimized
-			//parent.on('change', this.onChange, this);
-			if (!thisArg) this.thisArg = parent.thisArg;
-		}
-
-		const contexts = builder._contexts;
-		for (let i = 0; i < contexts.length; i++) {
-			const context = contexts[i];
-			objects[i] = context.compiler.instantiate(doc, context, this);
-		}
-	}
-	
-	,link(extraObjects) {
-		var contextMap = this.builder._contextMap;
-
-		for (var id in extraObjects)
-			this.$[id] = extraObjects[id];
-		for (var id in contextMap)
-			this.$[id] = this.objects[contextMap[id]];
-
-		const builder = this.builder;
-		const contexts = builder._contexts;
-		const objects = this.objects;
-
-		for (const compiler of builder._compilers)
-			compiler.preLink(this);
-
-		for (let i = 0; i < contexts.length; i++) {
-			const context = contexts[i];
-			context.compiler.link(context, objects[i], objects, this);
-		}
-
-		for (let i = 0; i < contexts.length; i++) {
-			const context = contexts[i];
-			context.compiler.connect(context, objects[i], objects, this);
-		}
-
-		for (const compiler of builder._compilers)
-			compiler.postLink(this);
-
-		this.digest();
-
-		for (const object of this.objects)
-		if (object.assignLot)
-			object.on('change', this.onChange, this);
-	}
-
-	,digest() {
-		const exprContexts = this.builder._exprContexts;
-		const exprValues = this.exprValues;
-		const objects = this.objects;
-
-		for (let i = 0; i < exprContexts.length; i++) {
-			const exprContext = exprContexts[i];
-			let newValue;
-
-			if (exprContext.template) {
-				const values = [];
-				let isEmpty = false;
-
-				for (expr of exprContext.exprs) {
-					const value = this.execExpr(expr);
-					if (value == null) {
-						isEmpty = true;
-						break;
-					}
-					values.push(value);
-				}
-
-				if (!isEmpty) {
-					let k = 0;
-					newValue = exprContext.template.replace(/{{\d+}}/g, function() {
-						return values[k++];
-					});
-				} else
-					newValue = '';
-			} else 
-				newValue = this.execExpr(exprContext.expr);
-
-			if (newValue !== exprValues[i]) {
-				const context = exprContext.context;
-				context.compiler.setProperty(objects[context.id],
-					exprContext.property, newValue);
-				exprValues[i] = newValue;
-			}
-		}
-	}
-
-	,execExpr(expr) {
-		try {
-			return expr.call(this.thisArg, this.$);
-		// eslint-disable-next-line no-empty
-		} catch (e) {}
-	}
-
-	,onChange() {
-		this.emit('change');
-		this.digest();
-	}
-
-	,getMain() {
-		return this.objects[this.builder._mainContext];
-	}
-	
-	,getById(objectId) {
-		if (!objectId) return null;
-		return this.$[kebabToCamel(objectId)];
-	}
-	
-	,getByTagName(tagName) {
-		const tags = this.builder._tags[tagName];
-	
-		if (tags) {
-			const arr = new Array(tags.length);
-			
-			for (let i = 0; i < tags.length; i++)
-				arr[i] = this.objects[tags[i]];
-
-			return arr;
-		}
-		
-		return [];
-	}
-
-	,getHtmlId(nodeId) {
-		return 'vn-'+ this.uid +'-'+ nodeId;
-	}
-	
-	,_destroy() {
-		Vn.nWatchers -= this.exprValues.length;
-
-		for (const object of this.objects)
-		if (object instanceof VnObject) {
-			object.disconnectByInstance(this);
-			object._destroy();
-		}
-		if (this.parent)
-			this.parent.disconnectByInstance(this);
-
-		VnObject.prototype._destroy.call(this);
-	}
-});
diff --git a/js/vn/spec.js b/js/vn/spec.js
deleted file mode 100644
index b64eb4dc..00000000
--- a/js/vn/spec.js
+++ /dev/null
@@ -1,37 +0,0 @@
-
-var VnObject = require('./object');
-var Type = require('./type');
-
-/**
- * Paramter specification.
- */
-module.exports = new Class({
-	Extends: VnObject
-	,Tag: 'vn-spec'
-	,Properties: {
-		/**
-		 * The parameter name.
-		 */
-		name: {
-			type: String
-			,set(x) {
-				this._name = x;
-			}
-			,get() {
-				return this._name;
-			}
-		},
-		/**
-		 * The parameter type.
-		 */
-		type: {
-			type: Type
-			,set(x) {
-				this._type = x;
-			}
-			,get() {
-				return this._type;
-			}
-		}
-	}
-});
diff --git a/js/vn/string-util.js b/js/vn/string-util.js
deleted file mode 100644
index ccd01c7b..00000000
--- a/js/vn/string-util.js
+++ /dev/null
@@ -1,27 +0,0 @@
-module.exports = {
-	kebabToCamel: kebabToCamel,
-	kebabToPascal: kebabToPascal
-};
-
-/**
- * Converts a kebab-case (hyphenized) string to camelCase (lowerCamelCase).
- * 
- * @param {String} string The kebab-case string
- * @return {String} The string parsed to camelCase
- */
-function kebabToCamel(string) {
-	function replaceFunc(token) {
-		return token.charAt(1).toUpperCase();
-	}
-	return string.replace(/-./g, replaceFunc);
-}
-/**
- * Converts a kebab-case (hyphenized) string to PascalCase (UpperCamelCase).
- * 
- * @param {String} string The kebab-case string
- * @return {String} The string parsed to PascalCase
- */
-function kebabToPascal(string) {
-	string = string.charAt(0).toUpperCase() + string.substr(1);
-	return kebabToCamel(string);
-}
diff --git a/js/vn/type.js b/js/vn/type.js
deleted file mode 100644
index b380e90a..00000000
--- a/js/vn/type.js
+++ /dev/null
@@ -1,4 +0,0 @@
-/**
- * Type that references another type.
- */
- module.exports = function() {};
\ No newline at end of file
diff --git a/js/vn/url.js b/js/vn/url.js
deleted file mode 100644
index 2ee29c48..00000000
--- a/js/vn/url.js
+++ /dev/null
@@ -1,70 +0,0 @@
-/**
- * Class to handle the URL.
- */
-module.exports =
-{
-	/**
-	 * Gets the value of a URL variable.
-	 *
-	 * @param {string} key The variable name
-	 */
-	getQuery(key) {
-		var regExp = new RegExp('[\?\&]'+ key +'=([^\&]*)(\&?)', 'i');
-		var value = location.search.match(regExp);
-
-		return value ? value[1] : value;
-	}
-	
-	/**
-	 * Sets the value of a URL variable.
-	 *
-	 * @param {string} key The variable name
-	 * @param {string} value The new value
-	 */
-	,setQuery(key, value) {
-		var changed = true;
-		var found = false;
-		var newPair = key +'='+ value;
-		var kvPairs = location.search.substr(1).split('?');
-
-		for (var i = 0; i < kvPairs.length; i++) {
-			var kvPair = kvPairs[i].split('=', 1);
-			
-			if (kvPair[0] == key) {
-				if (kvPair[1] != value)
-					kvPairs.splice(i, 1, newPair);
-				else
-					changed = false;
-
-				found = true;
-				break;
-			}
-		}
-
-		if (!found)
-			kvPairs.push(newPair);
-		
-		if (changed)
-			document.location.hash = '?'+ kvPairs.join('&');
-	}
-	
-	,makeUri(map) {
-		var post = '';
-	
-		for (var key in map) {
-			var value = map[key];
-				
-			if (value === null || value === undefined)
-				continue;
-			if (typeof value == 'boolean')
-				value = value ? '1' : '0';
-			if (post.length > 2)
-				post += '&';
-
-			post += encodeURIComponent(key) +'='+ encodeURIComponent(value);
-		}
-	
-		return post;
-	}
-};
-
diff --git a/js/vn/value.js b/js/vn/value.js
deleted file mode 100644
index dc7584ed..00000000
--- a/js/vn/value.js
+++ /dev/null
@@ -1,191 +0,0 @@
-
-var VnDate = require('./date');
-
-/**
- * Clones a simple value. A simple value is any value that is not an array,
- * object or function. If non-simple value is passed, the same object reference
- * is returned.
- *
- * @param {*} value The value to be copied
- * @return {*} The value copy
- */
-function simpleClone(value) {
-	if (value instanceof Date)
-		return value.clone();
-
-	return value;
-}
-
-/**
- * Checks if two simple values are equal using the strict equality operator. For
- * information about simple values see simpleClone() function.
- *
- * @param {*} a Value to compare to
- * @param {*} b Value to compare with
- * @return {boolean} %true if they are equal, %false otherwise
- */
-function simpleEquals(a, b) {
-	if (a === b)
-		return true;
-	if (a instanceof Date && b instanceof Date)
-		return a.getTime() === b.getTime();
-
-	return false;
-}
-
-/**
- * Calculates differences between two simple key-value objects.
- *
- * @param {Object} orgObject Value to compare to
- * @param {Object} newObject Value to compare with
- * @return {Object} The differences or %null if there are no differences
- */
-function diff(orgObject, newObject) {
-	var diff = {};
-
-	for (var key in orgObject)
-	if (!simpleEquals(orgObject[key], newObject[key]))
-		diff[key] = simpleClone(newObject[key]);
-
-	for (var key in newObject)
-	if (orgObject[key] === undefined && newObject[key] !== undefined)
-		diff[key] = simpleClone(newObject[key]);
-
-	if (Object.keys(diff).length > 0)
-		return diff;
-
-	return null;
-}
-
-/**
- * Calculates new differences between two simple key-value objects.
- *
- * @param {Object} orgObject Value to compare to
- * @param {Object} newObject Value to compare with
- * @return {Object} The differences or %null if there are no differences
- */
-function partialDiff(orgObject, newObject) {
-	var diff = {};
-
-	for (var key in newObject)
-	if (!simpleEquals(orgObject[key], newObject[key]))
-		diff[key] = simpleClone(newObject[key]);
-
-	if (Object.keys(diff).length > 0)
-		return diff;
-
-	return null;
-}
-
-/**
- * Clones a simple key-value object in wich properties are simple values. For
- * information about simple values see simpleClone() function.
- * 
- * @param {*} object The object to be cloned
- * @return The cloned object
- */
-function kvClone(object) {
-	var copy = {};
-
-	for (var key in object)
-		copy[key] = simpleClone(object[key]);
-
-	return copy;
-}
-
-/**
- * Checks if two values are equal, it also checks objects. Basic values are
- * compared using the strict equality operator.
- *
- * @param {*} a Value to compare to
- * @param {*} b Value to compare with
- * @return {boolean} %true if they are equal, %false otherwise
- */
-function equals(a, b) {
-	if (a === b)
-		return true;
-	if (a instanceof Date && b instanceof Date)
-		return a.getTime() === b.getTime();
-	if (a && b && (typeof a === 'object') && (typeof b === 'object')) {
-		for (var key in a)
-		if (!equals(a[key], b[key]))
-			return false;
-
-		for (var key in b)
-		if (a[key] === undefined && b[key] !== undefined)
-			return false;
-
-		return true;
-	}
-
-	return false;
-}
-
-/**
- * Returns a formated string.
- *
- * @param {Object} formatString The base string template
- * @param {...} arguments Format parameters
- * @return {string} The formated string
- */
-function sprintf(formatString) {
-	var args = arguments;
-
-	if (args.length <= 1)
-		return formatString;
-	
-	var i = 1;
-	return formatString.replace(/%[s|d]/g, function() {
-		return args[i++];
-	});
-}
-
-module.exports = {
-	 regexpNumber: /%\.([0-9]+)d/g
-	,regexpString: /%s/g
-
-	,equals
-	,diff
-	,partialDiff
-	,kvClone
-	,simpleClone
-	,simpleEquals
-	,sprintf
-
-	,compare(a, b) {
-		if (a === b)
-			return true;
-		if (a instanceof Date && b instanceof Date)
-			return a.getTime() === b.getTime();
-			
-		return false;		
-	}
-
-	,format(value, format) {
-		if (value === null || value === undefined)
-			return '';
-	
-		if (format)
-		switch (typeof value) {
-			case 'number':
-				return format.replace(this.regexpNumber,
-					this.replaceNumber.bind(null, value));
-			case 'string':
-				return format.replace(this.regexpString,
-					this.replaceString.bind(null, value));
-			case 'object':
-			if (value instanceof Date)
-				return VnDate.strftime(value, format);
-		}
-		
-		return value;
-	}
-
-	,replaceNumber(value, token, digits) {
-		return new Number(value).toFixed(parseInt(digits));
-	}
-
-	,replaceString(value) {
-		return value;
-	}
-};
diff --git a/js/vn/vn.js b/js/vn/vn.js
deleted file mode 100644
index 6546f0b9..00000000
--- a/js/vn/vn.js
+++ /dev/null
@@ -1,382 +0,0 @@
-
-require('mootools');
-
-Vn = module.exports = {};
-
-Object.assign(Vn, {
-	 Locale         : require('./locale')
-	,Enum           : require('./enum')
-	,Type           : require('./type')
-	,Object         : require('./object')
-	,Mutators       : require('./mutators')
-	,Browser        : require('./browser')
-	,Cookie         : require('./cookie')
-	,Date           : require('./date')
-	,Value          : require('./value')
-	,Url            : require('./url')
-	,LotIface       : require('./lot-iface')
-	,Lot            : require('./lot')
-	,LotQuery       : require('./lot-query')
-	,Hash           : require('./hash')
-	,ParamIface     : require('./param-iface')
-	,Param          : require('./param')
-	,Spec           : require('./spec')
-	,Model          : require('./model')
-	,ModelIface     : require('./model-iface')
-	,ModelProxy     : require('./model-proxy')
-	,IteratorIface  : require('./iterator-iface')
-	,Iterator       : require('./iterator')
-	,Form           : require('./form')
-	,Node           : require('./node')
-	,NodeBuilder    : require('./node-builder')
-	,Component      : require('./component')
-	,Builder        : require('./builder')
-	,JsonException  : require('./json-exception')
-	,JsonConnection : require('./json-connection')
-
-	,Config: {}
-	,includes: {}
-	,cssIncludes: {}
-	,currentDeps: []
-	,currentCallback: null
-	,head: document.getElementsByTagName('head')[0]
-	,isMobileCached: null
-	
-	,getVersion() {
-		if (this._version === undefined) {
-			var re = /[; ]vnVersion=([^\\s;]*)/;
-			var sMatch = (' '+ document.cookie).match(re);
-			this._version = (sMatch) ? '?'+ unescape(sMatch[1]) : '';
-		}
-		
-		return this._version;
-	}
-
-	,setVersion(version) {
-		document.cookie = `vnVersion=${version}; SameSite=Lax;`;
-	}
-
-	/**
-	 * Includes a new CSS stylesheet in the current document, if the stylesheet
-	 * is already included, does nothing.
-	 *
-	 * @param {string} fileName The stylesheet file name
-	 */
-	,includeCss(fileName) {	
-		var cssData = this.cssIncludes[fileName];
-
-		if (!cssData) {
-			var link = document.createElement('link');
-			link.rel = 'stylesheet';
-			link.type = 'text/css';
-			link.href = fileName + this.getVersion();
-			this.head.appendChild(link);
-			
-			this.cssIncludes[fileName] = 
-			{
-				 included: true
-				,link: link
-			};
-		} else if (!cssData.included) {
-			cssData.link.disabled = false;
-			cssData.included = true;
-		}
-	}
-	
-	/**
-	 * Excludes a CSS stylesheet from the current document.
-	 *
-	 * @param {string} fileName The stylesheet file name
-	 */
-	,excludeCss(fileName) {
-		var cssData = this.cssIncludes[fileName];
-	
-		if (cssData && cssData.included) {
-			cssData.link.disabled = true;
-			cssData.included = false;
-		}		
-	}
-	
-	,_createIncludeData(path) {
-		var includeData = {
-			path,
-			 depCount: 0,
-			success: false,
-			loaded: false,
-			callbacks: [],
-			dependants: [],
-		};
-
-		this.includes[path] = includeData;
-		return includeData;
-	}
-	
-	,_resolveDeps(includeData) {
-		includeData.success = true;
-
-		var callbacks = includeData.callbacks;
-	
-		if (callbacks)		
-		for (var i = 0; i < callbacks.length; i++)
-			callbacks[i](includeData.loaded);
-
-		var dependants = includeData.dependants;
-
-		if (dependants)
-		for (var i = 0; i < dependants.length; i++) {
-			var dependant = dependants[i];
-			dependant.depCount--;
-			
-			if (dependant.depCount == 0)
-				this._resolveDeps(dependant);
-		}
-
-		delete includeData.callbacks;
-		delete includeData.dependants;
-		delete includeData.depCount;
-	}
-
-	/**
-	 * Initializes the library and calls the passed function when all
-	 * includes and its dependencies are resolved.
-	 * Should be called on the last statically incuded script.
-	 *
-	 * @param {Function} callback The main function
-	 */
-	,main(callback) {
-		if (this.mainCalled) {
-			Vn.warning("Vn: main method should be called only once");
-			return;
-		}
-	
-		this.mainCalled = true;
-		this.mainCallback = callback;
-
-		var basePath = location.protocol +'//'+ location.host;
-		basePath += location.port ? ':'+ location.port : '';
-		basePath += location.pathname;
-
-		var scripts = this.head.getElementsByTagName('script');
-		var includes = this.currentDeps;
-
-		for (var i = 0; i < scripts.length; i++) {
-			var path = scripts[i].src.substr(basePath.length);
-			path = path.substr(0, path.indexOf('.js')) +'.js';
-
-			var includeData = this.includes[path];
-			
-			if (includeData === undefined) {
-				this.currentDeps = includes;
-				var includeData = this._createIncludeData(path);
-				this._onScriptLoad(includeData, true);
-			}
-		}
-
-		includeData.callbacks.push(this._onMainDepsLoad.bind(this));
-		window.addEventListener('load', this._onWindowLoad.bind(this));
-	}
-	
-	,_onMainDepsLoad() {
-		this.mainDepsLoaded = true;
-		this._callMain();
-	}
-	
-	,_onWindowLoad() {
-		this.windowReady = true;
-		this._callMain();
-	}
-	
-	,_callMain() {
-		if (this.mainCallback && this.windowReady && this.mainDepsLoaded)
-			this.mainCallback();
-	}
-	
-	/**
-	 * Includes a set of javascript files and sets it as dependecies of the
-	 * current script.
-	 *
-	 * @param {...} The list of files as function arguments
-	 */
-	,include() {
-		for (var i = 0; i < arguments.length; i++) {
-			var includeData = this._realIncludeJs(arguments[i] +'.js');
-			
-			if (!includeData.success)
-				this.currentDeps.push(includeData);
-		}
-	}
-
-	/**
-	 * Downloads a set of resources and sets it as dependecies of the
-	 * current script.
-	 *
-	 * @param {...} The list of files as function arguments
-	 */
-	,resource() {
-		for (var i = 0; i < arguments.length; i++) {
-			var includeData = this._realLoadXml(arguments[i]);
-			
-			if (!includeData.success)
-				this.currentDeps.push(includeData);
-		}
-	}
-	
-	/**
-	 * Sets the function that will be called when current script dependencies
-	 * are resolved.
-	 *
-	 * @param {Function} callback The callback function
-	 */
-	,define(callback) {
-		this.currentCallback = callback;
-	}
-
-	,async _handleCallback(includeData) {
-		if (includeData.success) return;
-
-		return new Promise((resolve, reject) => {
-			function callback(loaded) {
-				if (!loaded)
-					return reject(new Error(`Could not load resource: ${includeData.path}`));
-				resolve();
-			}
-
-			includeData.callbacks.push(callback);
-		});
-	}
-
-	/**
-	 * Includes a new Javascript in the current document, if the script
-	 * is already included, does nothing and calls the callback.
-	 *
-	 * @param {string} fileName The script file name
-	 */
-	,async includeJs(fileName, skipVersion) {
-		var includeData = this._realIncludeJs(fileName, skipVersion);
-		return this._handleCallback(includeData);
-	}
-	 
-	,_realIncludeJs(fileName, skipVersion) {
-		var includeData = this.includes[fileName];
-	
-		if (includeData === undefined) {
-			includeData = this._createIncludeData(fileName);
-
-			var src = fileName;
-
-			if (!skipVersion)
-				src = src + this.getVersion();
-
-			var script = document.createElement('script');
-			script.type = 'text/javascript';
-			script.async = false;
-			script.src = src;
-
-			script.onload =
-				() => this._onScriptLoad(includeData, true);
-			script.onerror =
-				() => this._onScriptLoad(includeData, false);
-			script.onreadystatechange =
-				() => this._onScriptStateChange(includeData, script);
-
-			this.head.appendChild(script);
-		}
-
-		return includeData;
-	}
-
-	,_onScriptStateChange(includeData, script) {
-		if (script.readyState == 'complete')
-			this._onScriptLoad(includeData, true);
-	}
-
-	,_onScriptLoad(includeData, loaded) {
-		includeData.loaded = loaded;
-
-		if (loaded) {			
-			if (this.currentCallback)
-				includeData.callbacks.unshift(this.currentCallback);
-
-			var includes = this.currentDeps;
-			
-			if (includes && includes.length > 0) {
-				includeData.depCount = includes.length;
-
-				for (var i = 0; i < includes.length; i++)
-					includes[i].dependants.push(includeData);
-			} else
-				this._resolveDeps(includeData);
-		} else
-			this._resolveDeps(includeData);
-		
-		this.currentDeps = [];
-		this.currentCallback = null;
-	}
-
-	/**
-	 * Request an XML file.
-	 *
-	 * @param {string} path The file path
-	 */
-	,async loadXml(path) {
-		var includeData = this._realLoadXml(path);
-		return this._handleCallback(includeData);
-	}
-
-	,_realLoadXml(path) {
-		var includeData = this.includes[path];
-	
-		if (includeData === undefined) {
-			includeData = this._createIncludeData(path);
-
-			var request = new XMLHttpRequest();
-			request.onreadystatechange =
-				() => this._onXmlReady(includeData, request);
-			request.open('get', path + this.getVersion(), true);
-			request.send();
-		}
-
-		return includeData;
-	}
-	
-	,_onXmlReady(includeData, request) {
-		if (request.readyState != 4)
-			return;
-			
-		includeData.loaded = request.status == 200;
-
-		if (includeData.loaded)
-			includeData.xml = request.responseXML;
-			
-		this._resolveDeps(includeData);
-	}
-	
-	/**
-	 * Gets the DOM object from an included XML file.
-	 *
-	 * @param {string} path The file path
-	 * @return {Object} The DOM object
-	 */
-	,getXml(path) {
-		var includeData = this.includes[path];
-		
-		if (!(includeData && includeData.success))
-			return null;
-			
-		return includeData.xml;
-	}
-
-	/**
-	 * Checks if user is using a mobile browser.
-	 *
-	 * return {boolean} %true if is mobile, %false otherwise.
-	 */
-	,isMobile() {
-		if (this.isMobileCached === null) {
-			var regExp = /(Android|webOS|iPhone|iPad|iPod|BlackBerry|Windows Phone)/i;
-			this.isMobileCached =  navigator.userAgent.match(regExp);
-		}
-
-		return this.isMobileCached;
-	}
-});
diff --git a/pages/main/manifest.json b/pages/main/manifest.json
deleted file mode 100644
index 84f134d0..00000000
--- a/pages/main/manifest.json
+++ /dev/null
@@ -1,13 +0,0 @@
-{
-	"name": "Verdnatura",
-	"icons": [
-		{
-			"src": "\/image\/icon.png",
-			"sizes": "512x512"
-		}
-	],
-	"start_url": "/index.php",
-	"display": "standalone",
-	"theme_color": "#333333",
-	"background_color": "#FFFFFF"
-}
diff --git a/pages/main/ui.php b/pages/main/ui.php
deleted file mode 100644
index 52806c58..00000000
--- a/pages/main/ui.php
+++ /dev/null
@@ -1,32 +0,0 @@
-<?php
-
-$lang = Vn\Lib\Locale::get();
-$result = $db->query('SELECT name, content FROM metatag');
-
-?>
-<!DOCTYPE html>
-<html xmlns="http://www.w3.org/1999/xhtml">
-	<head>
-		<meta charset="UTF-8">
-		<meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=no"/>
-		<meta name="mobile-web-app-capable" content="yes"/>
-		<link rel="shortcut icon" href="image/favicon/favicon.ico"/>
-		<link rel="apple-touch-icon" href="image/favicon/apple-touch-icon.png"/>
-		<link rel="icon" type="image/png" href="image/favicon/favicon.png"/>
-		<link rel="icon" type="image/svg+xml" href="image/icon.svg" sizes="any"/>
-		<link rel="manifest" href="<?=$dir?>/manifest.json"/>
-		<meta name="theme-color" content="#333333"/>
-		<meta name="content-language" content="<?=$lang?>"/>
-		
-		<?php while ($row = $result->fetch_object()): ?>
-		<meta name="<?=$row->name?>" content="<?=$row->content?>"/>
-		<?php endwhile ?>
-
-		<?php foreach (getWebpackAssets() as $js): ?>
-		<script type="text/javascript" src="<?=$js?>"></script>
-		<?php endforeach ?>
-
-		<title>Verdnatura</title>
-	</head>
-	<body></body>
-</html>
diff --git a/pages/production/main.js b/pages/production/main.js
deleted file mode 100644
index d3a076e2..00000000
--- a/pages/production/main.js
+++ /dev/null
@@ -1,161 +0,0 @@
-
-/**
- * Time in seconds between every request.
- */
-var INTERVAL = 15;
-
-var requestInterval = INTERVAL;
-var failedRequests = 0;
-var timeoutId = null;
-var request = null;
-var myText;
-var myStatus;
-var myError;
-
-function onBodyLoad ()
-{
-	setTimeout (setText, 1000);
-}
-
-function onSettingsClick ()
-{
-	var deviceId = localStorage.getItem ('hederaDeviceId');
-
-	if (deviceId == null)
-		deviceId = '';
-
-	deviceId = prompt ('Enter the device identifier', deviceId);
-
-	if (deviceId == null)
-		return;
-
-	if (deviceId)
-		localStorage.setItem ('hederaDeviceId', deviceId);
-	else if (deviceId === '')
-		localStorage.removeItem ('hederaDeviceId');
-
-	if (timeoutId != null)
-	{
-		clearTimeout (timeoutId);
-		timeoutId = null;
-	}
-	if (request)
-	{
-		request.abort ();
-		request = null;
-	}
-
-	setText ();
-}
-
-function setText ()
-{
-	display (null, null, null);
-	updateText ();
-}
-
-function updateText ()
-{
-	var deviceId = localStorage.getItem ('hederaDeviceId');
-
-	if (!deviceId)
-	{
-		display (null, null, 'Device id not set');
-		return;
-	}
-
-	var formData = new FormData ();
-	formData.append ('srv', 'json:misc/production');
-	formData.append ('deviceId', deviceId);
-
-	request = new XMLHttpRequest();
-	request.open ('POST', '', true);
-	request.onreadystatechange =
-		onRequestChange.bind (null, request);
-	request.send (formData);
-}
-
-function onRequestChange (request)
-{
-	if (request.readyState !== 4)
-		return;
-
-	try {
-		switch (request.status)
-		{
-			case 200:
-				var data = JSON.parse (request.responseText).data;
-				display (data.displayText, data.status, null);
-				requestInterval = INTERVAL;
-				failedRequests = 0;
-				break;
-			case 400:
-				var json = JSON.parse (request.responseText);
-				throw new Error (json.data.message);
-			case 0:
-				throw new Error ('Connection lost');
-			default:
-				throw new Error ('HTTP '+ request.status +': '+ request.statusText);
-		}
-	}
-	catch (e)
-	{
-		display (myText, myStatus, e.message);
-		console.error (e.message);
-		failedRequests++;
-		
-		if (failedRequests > 10 && requestInterval < 60)
-		{
-			requestInterval += parseInt (Math.random() * INTERVAL) + 1;
-			console.warn ('Request interval increased to %d seconds.', requestInterval);
-		}
-	}
-
-	timeoutId = setTimeout (updateText, requestInterval * 1000);
-	request = null;
-}
-
-function display (text, status, error)
-{
-	if (text === myText && status === myStatus && error === myError)
-		return;
-
-	var bgColor;
-	var body = document.body;
-
-	if (error)
-	{
-		text = text ? text : 'Er';
-		$.error.textContent = error;
-		$.error.style.display = 'block';
-		bgColor = 'red';
-	}
-	else
-	{
-		$.error.textContent = '';
-		$.error.style.display = 'none';
-		bgColor = 'green';
-	}
-
-	$.text.textContent = text;
-	body.className = status ? status : '';
-
-	body.addEventListener ('transitionend', onTransitionEnd);
-	body.style.backgroundColor = bgColor;
-
-	myText = text;
-	myStatus = status;
-	myError = error;
-}
-
-function onTransitionEnd ()
-{
-	var body = document.body;
-	body.removeEventListener ('transitionend', onTransitionEnd);
-	body.style.backgroundColor = '';
-}
-
-function $ (elementId)
-{
-	return document.getElementById (elementId);
-}
diff --git a/pages/production/manifest.json b/pages/production/manifest.json
deleted file mode 100644
index 95c5a691..00000000
--- a/pages/production/manifest.json
+++ /dev/null
@@ -1,11 +0,0 @@
-{
-	"name": "Production",
-	"icons": [
-		{
-			"src": "\/image\/favicon\/favicon.png",
-			"sizes": "512x512"
-		}
-	],
-	"start_url": "/index.php?method=production",
-	"display": "standalone"
-}
diff --git a/pages/production/style.css b/pages/production/style.css
deleted file mode 100644
index 4ea43f15..00000000
--- a/pages/production/style.css
+++ /dev/null
@@ -1,74 +0,0 @@
-body
-{
-    background-color: #333;
-    position: absolute;
-    height: 100%;
-    width: 100%;
-    margin: 0;
-    font-family: Sans;
-    transition: background-color 500ms ease-in;
-}
-body.idle
-{
-    background-color: #08D;
-}
-body.doing
-{
-    background-color: #333;
-}
-body.done
-{
-    background-color: #4A0;
-}
-#container
-{
-    width: 100%;
-    height: 100%;
-    display: flex;
-    justify-content: center;
-    align-items: center;
-}
-#child
-{
-    max-width: 90%;
-    text-align: center;
-}
-#text
-{
-    color: white;
-    font-size: 24rem;
-    font-weight: bold;
-    text-align: center;
-    white-space: nowrap;
-    overflow: hidden;
-    line-height: 1em;
-}
-#error
-{
-    color: red;
-    font-size: 3rem;
-    text-overflow: ellipsis;
-    white-space: nowrap;
-    overflow: hidden;
-}
-button
-{
-    position: fixed;
-    margin: 1em;
-    padding: 1em;
-    top: 0;
-    right: 0;
-    background-color: transparent;
-    border: none;
-    cursor: pointer;
-}
-button:hover
-{
-    background-color: rgba(0, 0, 0, 0.4);
-    border-radius: .2em;
-}
-button > img
-{
-    height: 3em;
-    display: block;
-}
\ No newline at end of file
diff --git a/pages/production/ui.php b/pages/production/ui.php
deleted file mode 100644
index d274f02b..00000000
--- a/pages/production/ui.php
+++ /dev/null
@@ -1,28 +0,0 @@
-<!DOCTYPE html>
-<html xmlns="http://www.w3.org/1999/xhtml">
-	<head>
-		<meta charset="UTF-8">
-		<meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=no"/>
-		<meta name="mobile-web-app-capable" content="yes"/>
-		<meta name="content-language" content="<?=$lang?>"/>
-		<meta name="theme-color" content="#009688"/>
-		<link rel="shortcut icon" href="image/favicon/favicon.ico"/>
-		<link rel="icon" type="image/png" href="image/favicon/favicon.png"/>
-		<link rel="icon" type="image/svg+xml" href="image/icon.svg" sizes="any"/>
-		<link rel="manifest" href="<?=$dir?>/manifest.json"/>
-		<?=js("$dir/main")?>
-		<?=css("$dir/style")?>
-		<title>Production</title>
-	</head>
-	<body onload="onBodyLoad()">
-		<button onclick="onSettingsClick()">
-			<img src="image/icon/dark/preferences.svg" alt="Config"/>
-		</button>
-		<div id="container">
-			<div id="child">
-				<div id="text">Hi!</div>
-				<div id="error"></div>
-			</div>
-		</div>
-	</body>
-</html>
\ No newline at end of file
diff --git a/pages/update-browser/locale/ca.yml b/pages/update-browser/locale/ca.yml
deleted file mode 100644
index 6dc920c4..00000000
--- a/pages/update-browser/locale/ca.yml
+++ /dev/null
@@ -1,2 +0,0 @@
-UpdateYourBrowser: Actualitza el teu navegador
-ContinueAnyway: Continuar igualment
diff --git a/pages/update-browser/locale/en.yml b/pages/update-browser/locale/en.yml
deleted file mode 100644
index 3660ead7..00000000
--- a/pages/update-browser/locale/en.yml
+++ /dev/null
@@ -1,2 +0,0 @@
-UpdateYourBrowser: Upgrade your browser
-ContinueAnyway: Continue anyway
diff --git a/pages/update-browser/locale/es.yml b/pages/update-browser/locale/es.yml
deleted file mode 100644
index 39adff07..00000000
--- a/pages/update-browser/locale/es.yml
+++ /dev/null
@@ -1,2 +0,0 @@
-UpdateYourBrowser: Actualiza tu navegador
-ContinueAnyway: Continuar de todos modos
diff --git a/pages/update-browser/locale/fr.yml b/pages/update-browser/locale/fr.yml
deleted file mode 100644
index 8500ff28..00000000
--- a/pages/update-browser/locale/fr.yml
+++ /dev/null
@@ -1,2 +0,0 @@
-UpdateYourBrowser: Mettez à jour votre navigateur
-ContinueAnyway: Continuer
diff --git a/pages/update-browser/locale/mn.yml b/pages/update-browser/locale/mn.yml
deleted file mode 100644
index 3660ead7..00000000
--- a/pages/update-browser/locale/mn.yml
+++ /dev/null
@@ -1,2 +0,0 @@
-UpdateYourBrowser: Upgrade your browser
-ContinueAnyway: Continue anyway
diff --git a/pages/update-browser/locale/pt.yml b/pages/update-browser/locale/pt.yml
deleted file mode 100644
index 37048a27..00000000
--- a/pages/update-browser/locale/pt.yml
+++ /dev/null
@@ -1,2 +0,0 @@
-UpdateYourBrowser: Atualize seu navegador
-ContinueAnyway: Continuar de todas maneiras
diff --git a/pages/update-browser/style.css b/pages/update-browser/style.css
deleted file mode 100644
index 8fff05e8..00000000
--- a/pages/update-browser/style.css
+++ /dev/null
@@ -1,26 +0,0 @@
-*
-{
-	font-family: 'Roboto';
-}
-img
-{
-	position: absolute;
-	margin-top: -200px;
-	margin-left: -200px;
-	top: 50%;
-	left: 50%;
-}
-#continue
-{
-	position: absolute;
-	bottom: 0;
-	left: 0;
-	right: 0;
-	margin: 1em;
-	text-align: center;
-}
-a
-{
-	color: #444;
-	border-width: 0;
-}
diff --git a/pages/update-browser/ui.php b/pages/update-browser/ui.php
deleted file mode 100644
index b5faeb43..00000000
--- a/pages/update-browser/ui.php
+++ /dev/null
@@ -1,23 +0,0 @@
-<!DOCTYPE html>
-<html xmlns="http://www.w3.org/1999/xhtml">
-<head>
-	<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
-	<meta name="viewport" content="user-scalable=no"/>
-	<meta name="content-language" content="<?=$lang?>"/>
-	<link href="//fonts.googleapis.com/css?family=Roboto" rel="stylesheet" type="text/css"/>
-	<?=css("$dir/style")?>
-	<title>Verdnatura</title>
-</head>
-<body>
-	<div>
-		<a href="http://www.mozilla.org/es-ES/firefox/new/" target="_blank">
-			<img src="<?=$dir?>/update-browser.png" alt="<?=s('UpdateYourBrowser')?>"></img>
-		</a>
-	</div>
-	<div id="continue">
-		<a href="?skipBrowser=true">
-			<?=s('ContinueAnyway')?>
-		</a>
-	</div>
-</body>
-</html>
diff --git a/pages/update-browser/update-browser.png b/pages/update-browser/update-browser.png
deleted file mode 100644
index 7be69691..00000000
Binary files a/pages/update-browser/update-browser.png and /dev/null differ
diff --git a/pages/version-menu/locale/ca.yml b/pages/version-menu/locale/ca.yml
deleted file mode 100644
index 62ddfddb..00000000
--- a/pages/version-menu/locale/ca.yml
+++ /dev/null
@@ -1,5 +0,0 @@
-'Welcome to Verdnatura, where are you going?': 'Benvingut a Verdnatura, On vols anar?'
-New website: Nova web
-(Fantastic): (Fantàstica)
-Old website: Antiga web
-(Best choose new): (Millor triï la nova)
diff --git a/pages/version-menu/locale/en.yml b/pages/version-menu/locale/en.yml
deleted file mode 100644
index 4691428e..00000000
--- a/pages/version-menu/locale/en.yml
+++ /dev/null
@@ -1,5 +0,0 @@
-'Welcome to Verdnatura, where are you going?': 'Welcome to Verdnatura, where are you going?'
-New website: New website
-(Fantastic): (Fantastic)
-Old website: Old website
-(Best choose new): (Best choose new)
diff --git a/pages/version-menu/locale/es.yml b/pages/version-menu/locale/es.yml
deleted file mode 100644
index 0b22d9b5..00000000
--- a/pages/version-menu/locale/es.yml
+++ /dev/null
@@ -1,5 +0,0 @@
-'Welcome to Verdnatura, where are you going?': 'Bienvenido a Verdnatura, ¿Dónde quieres ir?'
-New website: Nueva web
-(Fantastic): (Fantástica)
-Old website: Antigua web
-(Best choose new): (Mejor elige la nueva)
diff --git a/pages/version-menu/locale/fr.yml b/pages/version-menu/locale/fr.yml
deleted file mode 100644
index e9b002f2..00000000
--- a/pages/version-menu/locale/fr.yml
+++ /dev/null
@@ -1,5 +0,0 @@
-'Welcome to Verdnatura, where are you going?': 'Bienvenue à Verdnatura, où allez-vous?'
-New website: Nouveau site web
-(Fantastic): (Fantastique)
-Old website: Vieux web
-(Best choose new): (Mieux choisir le nouveau)
diff --git a/pages/version-menu/locale/mn.yml b/pages/version-menu/locale/mn.yml
deleted file mode 100644
index 4691428e..00000000
--- a/pages/version-menu/locale/mn.yml
+++ /dev/null
@@ -1,5 +0,0 @@
-'Welcome to Verdnatura, where are you going?': 'Welcome to Verdnatura, where are you going?'
-New website: New website
-(Fantastic): (Fantastic)
-Old website: Old website
-(Best choose new): (Best choose new)
diff --git a/pages/version-menu/locale/pt.yml b/pages/version-menu/locale/pt.yml
deleted file mode 100644
index 8c02c51e..00000000
--- a/pages/version-menu/locale/pt.yml
+++ /dev/null
@@ -1,5 +0,0 @@
-'Welcome to Verdnatura, where are you going?': 'Bem-Vindo a VerdNatura, onde queres ir?'
-New website: Nova Web
-(Fantastic): (Fantástica)
-Old website: Antiga web
-(Best choose new): (Melhor escolher a nova)
diff --git a/pages/version-menu/new-web.svg b/pages/version-menu/new-web.svg
deleted file mode 100644
index 0b055e28..00000000
--- a/pages/version-menu/new-web.svg
+++ /dev/null
@@ -1,233 +0,0 @@
-<?xml version="1.0" encoding="UTF-8" standalone="no"?>
-<!-- Generator: Adobe Illustrator 16.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0)  -->
-
-<svg
-   xmlns:ns="&amp;#38;ns_sfw;"
-   xmlns:dc="http://purl.org/dc/elements/1.1/"
-   xmlns:cc="http://creativecommons.org/ns#"
-   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
-   xmlns:svg="http://www.w3.org/2000/svg"
-   xmlns="http://www.w3.org/2000/svg"
-   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
-   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
-   version="1.1"
-   id="Capa_1"
-   x="0px"
-   y="0px"
-   width="200"
-   height="200"
-   viewBox="0 0 200 199.99999"
-   enable-background="new 0 0 434.057 306.911"
-   xml:space="preserve"
-   inkscape:version="0.91 r13725"
-   sodipodi:docname="new-web.svg"><defs
-     id="defs137" /><sodipodi:namedview
-     pagecolor="#ffffff"
-     bordercolor="#666666"
-     borderopacity="1"
-     objecttolerance="10"
-     gridtolerance="10"
-     guidetolerance="10"
-     inkscape:pageopacity="0"
-     inkscape:pageshadow="2"
-     inkscape:window-width="1920"
-     inkscape:window-height="1043"
-     id="namedview135"
-     showgrid="false"
-     fit-margin-top="0"
-     fit-margin-left="0"
-     fit-margin-right="0"
-     fit-margin-bottom="0"
-     inkscape:zoom="2.6848173"
-     inkscape:cx="1.4297595"
-     inkscape:cy="127.55081"
-     inkscape:window-x="0"
-     inkscape:window-y="0"
-     inkscape:window-maximized="1"
-     inkscape:current-layer="Capa_1" /><metadata
-     id="metadata3"><ns:sfw><ns:slices /><ns:sliceSourceBounds
-         width="250.32"
-         height="250.32"
-         y="-567.01"
-         x="89.06"
-         bottomLeftOrigin="true" /></ns:sfw><rdf:RDF><cc:Work
-         rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type
-           rdf:resource="http://purl.org/dc/dcmitype/StillImage" /><dc:title></dc:title></cc:Work></rdf:RDF></metadata><g
-     id="g9"
-     transform="matrix(0.92484694,0,0,0.92484694,-100.71768,-41.922394)"><radialGradient
-       gradientUnits="userSpaceOnUse"
-       r="108.126"
-       cy="153.45509"
-       cx="217.02831"
-       id="SVGID_1_"><stop
-         id="stop12"
-         style="stop-color:#93C01E"
-         offset="0" /><stop
-         id="stop14"
-         style="stop-color:#8FBD1F"
-         offset="0.304" /><stop
-         id="stop16"
-         style="stop-color:#84B520"
-         offset="0.5783" /><stop
-         id="stop18"
-         style="stop-color:#72A823"
-         offset="0.8403" /><stop
-         id="stop20"
-         style="stop-color:#639D25"
-         offset="1" /><stop
-         id="stop22"
-         style="stop-color:#609A25"
-         offset="1" /></radialGradient><path
-       inkscape:connector-curvature="0"
-       style="fill:url(#SVGID_1_)"
-       id="path24"
-       d="m 325.154,241.738 c 0,10.914 -8.929,19.843 -19.843,19.843 l -176.566,0 c -10.914,0 -19.843,-8.929 -19.843,-19.843 l 0,-176.566 c 0,-10.914 8.929,-19.843 19.843,-19.843 l 176.566,0 c 10.914,0 19.843,8.929 19.843,19.843 l 0,176.566 z" /></g><g
-     id="g4261"
-     transform="translate(2.8816553,-6.0234074)"><g
-       transform="matrix(0.92484694,0,0,0.92484694,-103.81794,-38.133192)"
-       id="XMLID_12_"><g
-         id="g27"><path
-           id="path29"
-           d="m 307.028,144.175 c 0.15,12.569 -2.19,25.439 -5.5,35.72 -9,29.62 -36,55.53 -67,54.47 -27,-1.05 -57.5,-3.17 -80,-21.68 -21.34,-17.03 -23.55,-49.851 -16.03,-76.62 13.84,0.34 27.96,0.5 41.03,-2.77 11,-3 35.5,-9 41.5,-19.5 l 1.23,-0.421 c 20.511,27.351 55.971,38.78 84.77,30.801 z m -59.39,10.059 c 0.22,-9.05 -12.95,-10.43 -12.67,-1.42 -2.01,-5.85 -8.74,-8.28 -10.63,-1.09 -1.48,6.149 5.68,13.56 9.51,17.25 l 2.04,1.56 c 1.341,-6.51 11.35,-9.239 11.75,-16.3 z m -52.639,0 c 0.22,-9.05 -12.94,-10.43 -12.67,-1.42 -2.01,-5.85 -8.74,-8.28 -10.63,-1.09 -1.48,6.149 5.68,13.56 9.51,17.25 l 2.04,1.56 c 1.339,-6.51 11.349,-9.239 11.75,-16.3 z"
-           inkscape:connector-curvature="0"
-           style="fill:#ebc7b9" /><path
-           id="path31"
-           d="m 305.828,130.864 c 0.78,4.311 1.15,8.79 1.2,13.311 -28.8,7.979 -64.26,-3.45 -84.77,-30.801 -1.95,-2.6 -3.77,-5.359 -5.43,-8.25 -2.64,-4.569 -4.88,-9.5 -6.66,-14.77 -0.96,-2.81 -1.78,-5.71 -2.45,-8.72 -0.07,-0.28 -0.13,-0.561 -0.19,-0.84 l -1.65,-1.891 c 3,-0.49 6,-0.859 8.98,-1.12 l 0.17,2.011 c 1,20.5 23.5,41.5 41.5,47.5 14.82,4.631 33.51,7.551 49.3,3.57 z"
-           inkscape:connector-curvature="0"
-           style="fill:#842d1e" /><path
-           id="path33"
-           d="m 301.548,116.925 c 2.02,4.29 3.41,9 4.28,13.939 -15.79,3.98 -34.48,1.061 -49.3,-3.569 -18,-6 -40.5,-27 -41.5,-47.5 l -0.17,-2.011 c 3.77,-0.33 7.51,-0.489 11.17,-0.489 l -5.22,2.64 c 1.69,0 3.43,0.06 5.23,0.17 l -0.01,0.19 c 3.28,23.88 51.73,40.75 75.52,36.63 z"
-           inkscape:connector-curvature="0"
-           style="fill:#a44b39" /><path
-           id="path35"
-           d="m 301.548,116.925 c -23.79,4.12 -72.24,-12.75 -75.52,-36.63 l 0.01,-0.19 c 3.89,0.229 8.01,0.72 12.25,1.45 13.91,14.21 34.57,21.62 53.75,22.609 4.09,3.49 7.211,7.841 9.51,12.761 z"
-           inkscape:connector-curvature="0"
-           style="fill:#842d1e" /><path
-           id="path37"
-           d="m 291.528,103.734 c 0.17,0.14 0.34,0.28 0.51,0.43 -19.18,-0.989 -39.84,-8.399 -53.75,-22.609 18.72,3.21 39.711,11.059 53.24,22.179 z"
-           inkscape:connector-curvature="0"
-           style="fill:#a44b39" /><path
-           id="path39"
-           d="m 234.968,152.814 c -0.28,-9.01 12.89,-7.63 12.67,1.42 -0.4,7.061 -10.41,9.79 -11.75,16.3 l -2.04,-1.56 c -3.83,-3.69 -10.99,-11.101 -9.51,-17.25 1.891,-7.19 8.62,-4.759 10.63,1.09 z"
-           inkscape:connector-curvature="0"
-           style="fill:#a61916" /><path
-           id="path41"
-           d="m 222.258,113.374 -1.23,0.421 c -6,10.5 -30.5,16.5 -41.5,19.5 -13.07,3.27 -27.19,3.109 -41.03,2.77 1.23,-4.36 2.71,-8.56 4.41,-12.51 10.16,0.729 21.86,-0.53 30.62,-1.26 7.5,-1 15.5,-2.5 22.5,-5.5 7,-3 13,-9 20.5,-11.5 l 0.3,-0.171 c 1.66,2.891 3.48,5.65 5.43,8.25 z"
-           inkscape:connector-curvature="0"
-           style="fill:#a44b39" /><path
-           id="path43"
-           d="m 216.828,105.124 -0.3,0.171 c -7.5,2.5 -13.5,8.5 -20.5,11.5 -7,3 -15,4.5 -22.5,5.5 -8.76,0.729 -20.46,1.989 -30.62,1.26 0.83,-1.91 1.7,-3.76 2.62,-5.54 1.8,-3.5 3.87,-6.74 6.16,-9.73 19.39,-0.21 50.11,-2.12 56.34,-17.489 l 2.14,-0.44 c 1.78,5.268 4.02,10.199 6.66,14.768 z"
-           inkscape:connector-curvature="0"
-           style="fill:#842d1e" /><path
-           id="path45"
-           d="m 210.168,90.354 -2.14,0.44 c -6.23,15.369 -36.95,17.279 -56.34,17.489 4.28,-5.59 9.35,-10.3 14.95,-14.229 4.8,-0.24 9.59,-0.66 14.39,-1.26 9.5,-2 17,-8.5 26,-11 l 0.69,-0.16 c 0.67,3.011 1.49,5.911 2.45,8.72 z"
-           inkscape:connector-curvature="0"
-           style="fill:#a44b39" /><path
-           id="path47"
-           d="m 207.528,80.795 c 0.06,0.279 0.12,0.56 0.19,0.84 l -0.69,0.16 c -9,2.5 -16.5,9 -26,11 -4.8,0.6 -9.59,1.02 -14.39,1.26 11.54,-8.101 25.36,-12.88 39.24,-15.15 l 1.65,1.89 z"
-           inkscape:connector-curvature="0"
-           style="fill:#842d1e" /><path
-           id="path49"
-           d="m 182.328,152.814 c -0.27,-9.01 12.89,-7.63 12.67,1.42 -0.4,7.061 -10.41,9.79 -11.75,16.3 l -2.04,-1.56 c -3.83,-3.69 -10.99,-11.101 -9.51,-17.25 1.89,-7.19 8.62,-4.759 10.63,1.09 z"
-           inkscape:connector-curvature="0"
-           style="fill:#a61916" /></g><g
-         id="g51" /></g><path
-       id="path53"
-       d="m 178.35656,94.836677 c -6.2011,1.546344 -12.73514,0.335719 -19.0463,0.312598 -6.81427,-0.02497 -12.85352,-0.710282 -19.40699,-2.671883 -6.66722,-1.99397 -12.86832,-4.851747 -18.60607,-8.780497 -5.26053,-3.603203 -11.89908,-7.524554 -15.60956,-12.815604 -0.64092,-0.913748 -1.52045,-1.330854 -2.41108,-1.403917 -1.36322,-1.45386 -3.869558,-1.797903 -4.990473,0.47907 -4.922035,9.993896 -19.96652,11.888908 -29.648743,14.524722 -7.306291,1.988421 -14.662523,3.497771 -22.228696,3.993489 -3.549563,0.232136 -7.148142,0.378262 -10.694005,0.06381 -3.322051,-0.294101 -6.516472,-1.020106 -9.872741,-0.907275 -4.135916,0.138727 -4.148864,6.570113 0,6.430461 3.326674,-0.111906 6.582135,0.502192 9.872741,0.907275 4.029558,0.495718 8.24501,0.09618 12.280117,-0.168322 8.719457,-0.571556 17.232673,-2.689455 25.622885,-5.019145 9.613784,-2.668183 21.913323,-5.054288 28.263325,-13.455598 3.41083,3.923201 7.84362,6.955774 12.04243,9.960602 6.70421,4.798106 13.34184,8.57703 21.12073,11.35897 7.46166,2.668187 14.7883,3.954647 22.69297,3.938927 7.43484,-0.0166 15.02321,1.27351 22.33043,-0.54751 4.02123,-1.00161 2.31396,-7.202711 -1.71097,-6.200177 z"
-       inkscape:connector-curvature="0"
-       style="fill:#bd988b" /><path
-       id="path55"
-       d="m 178.98361,111.29988 c 0,0 -13.87641,67.34643 -89.02022,65.78621 0,0 28.63789,10.24453 56.63023,-9.05795 27.99326,-19.30063 32.38999,-56.72826 32.38999,-56.72826 z"
-       inkscape:connector-curvature="0"
-       style="fill:#bd988b" /><g
-       transform="matrix(0.92484694,0,0,0.92484694,-103.81794,-38.133192)"
-       id="g57"><g
-         id="g59"><path
-           id="path61"
-           d="m 226.028,75.366 c -21.731,0.109 -44.027,5.164 -61.841,18.083 -17.754,12.875 -26.837,33.436 -30.259,54.586 -3.263,20.171 -0.875,42.404 12.075,58.881 15.159,19.288 42.388,25.518 65.462,27.926 11.851,1.236 24.397,2.557 36.186,0.336 10.942,-2.062 20.935,-7.712 29.447,-14.719 17.711,-14.578 27.118,-36.233 30.561,-58.472 3.022,-19.521 2.034,-43.279 -12.929,-57.992 -8.021,-7.886 -19.127,-12.96 -29.455,-17.002 -11.297,-4.421 -23.262,-7.224 -35.315,-8.501 -3.041,-0.323 -6.099,-0.457 -9.155,-0.481 -2.488,-0.021 -2.486,3.837 0,3.856 24.073,0.191 51.749,8.252 70.297,24.029 17.477,14.867 15.615,43.957 11.147,64.05 -5.305,23.861 -19.41,45.563 -41.621,56.75 -11.775,5.931 -23.918,5.957 -36.75,5.245 -13.384,-0.742 -26.733,-2.296 -39.633,-6.057 -19.035,-5.551 -36.346,-17.073 -43.521,-36.145 -6.388,-16.979 -5.026,-36.466 -0.228,-53.643 5.169,-18.504 15.792,-33.85 32.398,-43.773 15.838,-9.463 34.887,-13.01 53.135,-13.102 2.486,-0.01 2.487,-3.867 -0.001,-3.855 l 0,0 z"
-           inkscape:connector-curvature="0"
-           style="fill:#1c1c1b" /></g></g><g
-       transform="matrix(0.92484694,0,0,0.92484694,-103.81794,-38.133192)"
-       id="g63"><g
-         id="g65"><path
-           id="path67"
-           d="m 205.645,81.313 c 5.402,24.115 20.444,44.519 42.009,56.622 19.31,10.837 43.325,14.034 64.394,6.708 2.363,-0.821 1.347,-4.597 -1.039,-3.767 -19.931,6.93 -41.85,3.957 -60.335,-5.746 -21.321,-11.191 -36.033,-31.512 -41.262,-54.855 -0.551,-2.458 -4.317,-1.416 -3.767,1.038 l 0,0 z"
-           inkscape:connector-curvature="0"
-           style="fill:#1c1c1b" /></g></g><g
-       transform="matrix(0.92484694,0,0,0.92484694,-103.81794,-38.133192)"
-       id="g69"><g
-         id="g71"><path
-           id="path73"
-           d="m 213.075,79.795 c 1.374,19.379 16.987,35.576 33.013,44.895 8.896,5.173 19.299,7.415 29.371,8.927 11.51,1.728 23.426,1.578 34.589,-1.938 2.394,-0.754 1.371,-4.525 -1.039,-3.767 -18.56,5.847 -42.543,3.112 -59.751,-5.931 -15.306,-8.045 -30.997,-24.132 -32.276,-42.186 -0.177,-2.498 -4.085,-2.516 -3.907,0 l 0,0 z"
-           inkscape:connector-curvature="0"
-           style="fill:#1c1c1b" /></g></g><g
-       transform="matrix(0.92484694,0,0,0.92484694,-103.81794,-38.133192)"
-       id="g75"><g
-         id="g77"><path
-           id="path79"
-           d="m 224.145,80.813 c 2.526,15.8 19.634,25.236 32.953,30.821 14.466,6.064 33.964,11.161 49.45,6.043 2.38,-0.787 1.36,-4.56 -1.039,-3.767 -13.93,4.604 -30.788,0.128 -44.035,-4.733 -13.138,-4.822 -31.1,-13.998 -33.562,-29.402 -0.397,-2.482 -4.161,-1.425 -3.767,1.038 l 0,0 z"
-           inkscape:connector-curvature="0"
-           style="fill:#1c1c1b" /></g></g><g
-       transform="matrix(0.92484694,0,0,0.92484694,-103.81794,-38.133192)"
-       id="g81"><g
-         id="g83"><path
-           id="path85"
-           d="m 236.647,82.676 c 15.646,15.771 37.927,23.381 59.881,23.572 2.521,0.021 2.518,-3.885 0,-3.906 -20.941,-0.183 -42.188,-7.377 -57.119,-22.429 -1.775,-1.79 -4.537,0.974 -2.762,2.763 l 0,0 z"
-           inkscape:connector-curvature="0"
-           style="fill:#1c1c1b" /></g></g><g
-       transform="matrix(0.92484694,0,0,0.92484694,-103.81794,-38.133192)"
-       id="g87"><g
-         id="g89"><path
-           id="path91"
-           d="m 206.342,89.809 c -4.713,10.742 -19.143,13.318 -29.474,14.875 -11.677,1.76 -23.562,1.667 -35.339,1.658 -2.519,-0.002 -2.519,3.904 0,3.906 12.557,0.01 25.088,-0.096 37.535,-1.971 11.004,-1.658 25.692,-5.192 30.652,-16.497 1.001,-2.284 -2.364,-4.274 -3.374,-1.971 l 0,0 z"
-           inkscape:connector-curvature="0"
-           style="fill:#1c1c1b" /></g></g><g
-       transform="matrix(0.92484694,0,0,0.92484694,-103.81794,-38.133192)"
-       id="g93"><g
-         id="g95"><path
-           id="path97"
-           d="m 206.509,79.911 c -7.555,2.298 -14.073,6.829 -21.401,9.664 -8.415,3.257 -19.169,2.724 -28.08,2.767 -2.519,0.012 -2.52,3.918 0,3.906 8.994,-0.043 18.924,0.15 27.617,-2.392 8.061,-2.358 14.857,-7.731 22.902,-10.179 2.404,-0.73 1.379,-4.501 -1.038,-3.766 l 0,0 z"
-           inkscape:connector-curvature="0"
-           style="fill:#1c1c1b" /></g></g><g
-       transform="matrix(0.92484694,0,0,0.92484694,-103.81794,-38.133192)"
-       id="g99"><g
-         id="g101"><path
-           id="path103"
-           d="m 216.009,103.411 c -6.168,2.269 -11.294,6.211 -16.867,9.589 -6.767,4.102 -14.934,5.669 -22.642,6.91 -13.64,2.197 -30.022,3.783 -43.453,0.001 -2.43,-0.685 -3.459,3.085 -1.038,3.767 13.395,3.771 27.89,1.725 41.519,0.57 7.793,-0.661 15.792,-2.621 23.019,-5.57 7.311,-2.982 13.052,-8.76 20.5,-11.5 2.345,-0.862 1.332,-4.639 -1.038,-3.767 l 0,0 z"
-           inkscape:connector-curvature="0"
-           style="fill:#1c1c1b" /></g></g><g
-       transform="matrix(0.92484694,0,0,0.92484694,-103.81794,-38.133192)"
-       id="g105"><g
-         id="g107"><path
-           id="path109"
-           d="m 219.342,112.809 c -3.538,5.693 -10.51,8.738 -16.476,11.18 -6.536,2.676 -13.378,4.586 -20.184,6.432 -19.599,5.311 -39.601,3.488 -59.654,3.422 -2.52,-0.009 -2.519,3.897 0,3.906 20.855,0.068 41.351,1.68 61.714,-3.839 12.468,-3.379 30.615,-7.29 37.972,-19.129 1.335,-2.146 -2.046,-4.107 -3.372,-1.972 l 0,0 z"
-           inkscape:connector-curvature="0"
-           style="fill:#1c1c1b" /></g></g><g
-       transform="matrix(0.92484694,0,0,0.92484694,-103.81794,-38.133192)"
-       id="g111"><g
-         id="g113"><path
-           id="path115"
-           d="m 182.575,167.607 c -2.819,-2.738 -5.435,-5.59 -7.48,-8.966 -1.574,-2.598 -2.21,-5.403 -0.817,-8.2 1.883,-3.781 5.528,1.26 6.191,2.887 0.791,1.941 3.726,1.796 3.788,-0.512 0.202,-7.594 11.952,-3.244 7.83,4.225 -2.816,5.105 -9.019,6.945 -10.697,12.978 -0.668,2.4 3.053,3.418 3.719,1.025 1.39,-4.995 6.941,-7.152 9.74,-11.228 2.455,-3.576 2.833,-7.977 0.159,-11.563 -4.818,-6.462 -14.398,-3.272 -14.607,4.563 1.263,-0.172 2.525,-0.342 3.788,-0.514 -2.301,-5.65 -8.776,-9.922 -13.24,-3.809 -5.392,7.384 4.091,17.17 8.9,21.84 1.783,1.734 4.513,-0.99 2.726,-2.726 l 0,0 z"
-           inkscape:connector-curvature="0"
-           style="fill:#1c1c1b" /></g></g><g
-       transform="matrix(0.92484694,0,0,0.92484694,-103.81794,-38.133192)"
-       id="g117"><g
-         id="g119"><path
-           id="path121"
-           d="m 235.214,167.607 c -2.819,-2.738 -5.435,-5.59 -7.48,-8.966 -1.574,-2.598 -2.21,-5.403 -0.816,-8.2 1.883,-3.781 5.528,1.26 6.191,2.887 0.791,1.941 3.727,1.796 3.788,-0.512 0.201,-7.594 11.951,-3.245 7.829,4.225 -2.816,5.105 -9.019,6.945 -10.697,12.978 -0.668,2.4 3.053,3.418 3.719,1.025 1.39,-4.995 6.941,-7.152 9.74,-11.228 2.455,-3.576 2.833,-7.977 0.159,-11.563 -4.818,-6.461 -14.399,-3.272 -14.607,4.563 1.263,-0.172 2.525,-0.342 3.788,-0.514 -2.302,-5.648 -8.776,-9.922 -13.24,-3.809 -5.392,7.384 4.091,17.17 8.9,21.84 1.783,1.734 4.513,-0.991 2.726,-2.726 l 0,0 z"
-           inkscape:connector-curvature="0"
-           style="fill:#1c1c1b" /></g></g><g
-       transform="matrix(0.92484694,0,0,0.92484694,-103.81794,-38.133192)"
-       id="g123"><g
-         id="g125"><path
-           id="path127"
-           d="m 206.165,174.932 c -2.758,2.425 -5.56,5.749 -5.157,9.677 0.423,4.122 4.437,6.116 8.008,7.046 2.409,0.627 3.431,-3.093 1.025,-3.719 -1.972,-0.514 -4.977,-1.383 -5.229,-3.832 -0.265,-2.584 2.357,-4.931 4.08,-6.445 1.872,-1.645 -0.867,-4.362 -2.727,-2.727 l 0,0 z"
-           inkscape:connector-curvature="0"
-           style="fill:#1c1c1b" /></g></g><g
-       transform="matrix(0.92484694,0,0,0.92484694,-103.81794,-38.133192)"
-       id="g129"><g
-         id="g131"><path
-           id="path133"
-           d="m 185.52,215.833 c 5.588,2.601 11.259,3.283 17.379,3.195 6.112,-0.088 12.653,-0.151 18.684,-1.168 12.009,-2.025 23.418,-7.933 33.644,-14.366 18.476,-11.625 29.383,-29.234 36.1,-49.646 0.842,-2.559 -3.182,-3.646 -4.018,-1.107 -6.116,18.588 -15.698,34.553 -32.049,45.755 -8.647,5.924 -18.53,10.986 -28.568,13.99 -6.145,1.839 -12.465,1.758 -18.8,2.142 -6.924,0.419 -13.833,0.604 -20.269,-2.392 -2.42,-1.127 -4.538,2.464 -2.103,3.597 l 0,0 z"
-           inkscape:connector-curvature="0"
-           style="fill:#1c1c1b" /></g></g></g></svg>
\ No newline at end of file
diff --git a/pages/version-menu/old-web.svg b/pages/version-menu/old-web.svg
deleted file mode 100644
index f0e5f656..00000000
--- a/pages/version-menu/old-web.svg
+++ /dev/null
@@ -1,198 +0,0 @@
-<?xml version="1.0" encoding="UTF-8" standalone="no"?>
-<!-- Generator: Adobe Illustrator 16.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0)  -->
-
-<svg
-   xmlns:ns="&amp;ns_sfw;"
-   xmlns:dc="http://purl.org/dc/elements/1.1/"
-   xmlns:cc="http://creativecommons.org/ns#"
-   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
-   xmlns:svg="http://www.w3.org/2000/svg"
-   xmlns="http://www.w3.org/2000/svg"
-   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
-   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
-   version="1.1"
-   id="Capa_1"
-   x="0px"
-   y="0px"
-   width="200"
-   height="200"
-   viewBox="0 0 200 199.99999"
-   enable-background="new 0 0 434.057 306.911"
-   xml:space="preserve"
-   inkscape:version="0.91 r13725"
-   sodipodi:docname="old-web.svg"><defs
-     id="defs123" /><sodipodi:namedview
-     pagecolor="#ffffff"
-     bordercolor="#666666"
-     borderopacity="1"
-     objecttolerance="10"
-     gridtolerance="10"
-     guidetolerance="10"
-     inkscape:pageopacity="0"
-     inkscape:pageshadow="2"
-     inkscape:window-width="1920"
-     inkscape:window-height="1016"
-     id="namedview121"
-     showgrid="false"
-     fit-margin-top="0"
-     fit-margin-left="0"
-     fit-margin-right="0"
-     fit-margin-bottom="0"
-     inkscape:zoom="4.12"
-     inkscape:cx="100"
-     inkscape:cy="100"
-     inkscape:window-x="1920"
-     inkscape:window-y="27"
-     inkscape:window-maximized="1"
-     inkscape:current-layer="Capa_1" /><metadata
-     id="metadata3"><ns:sfw><ns:slices /><ns:sliceSourceBounds
-         width="16383"
-         height="16383"
-         y="-8490"
-         x="-7770"
-         bottomLeftOrigin="true" /></ns:sfw><rdf:RDF><cc:Work
-         rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type
-           rdf:resource="http://purl.org/dc/dcmitype/StillImage" /><dc:title></dc:title></cc:Work></rdf:RDF></metadata><g
-     id="g9"
-     transform="matrix(0.83995145,0,0,0.83994439,-87.096246,-32.92078)"><radialGradient
-       gradientUnits="userSpaceOnUse"
-       r="119.0547"
-       cy="158.25"
-       cx="222.74609"
-       id="SVGID_1_"><stop
-         id="stop12"
-         style="stop-color:#C6C1B9"
-         offset="0" /><stop
-         id="stop14"
-         style="stop-color:#C3BEB5"
-         offset="0.2905" /><stop
-         id="stop16"
-         style="stop-color:#BAB5AA"
-         offset="0.5527" /><stop
-         id="stop18"
-         style="stop-color:#AAA698"
-         offset="0.803" /><stop
-         id="stop20"
-         style="stop-color:#999684"
-         offset="1" /></radialGradient><path
-       inkscape:connector-curvature="0"
-       style="fill:url(#SVGID_1_)"
-       id="path22"
-       d="m 341.801,255.456 c 0,12.017 -9.832,21.849 -21.848,21.849 l -194.413,0 c -12.017,0 -21.848,-9.832 -21.848,-21.849 l 0,-194.414 c 0,-12.016 9.832,-21.848 21.848,-21.848 l 194.413,0 c 12.017,0 21.848,9.832 21.848,21.848 l 0,194.414 z" /></g><g
-     id="g4260"
-     transform="matrix(0.90696416,0,0,0.92415977,-101.04756,-68.67621)"><g
-       id="XMLID_10_"><g
-         id="g25"><path
-           id="path27"
-           d="m 305.885,149.498 c 1.69,6 2.65,12.391 3.04,18.78 -5.8,2.24 -12.33,2.87 -17.94,0.73 -7.75,-2.711 -13.56,-8.91 -21.31,-11.62 -5.81,-1.94 -11.23,-0.771 -17.04,-1.94 -5.81,-1.55 -7.75,-6.189 -12.4,-9.29 -7.36,-5.04 -16.66,-7.36 -24.79,-10.85 -4.36,-2.33 -9.37,-4 -14.06,-6.16 -1.56,-0.72 -3.09,-1.49 -4.54,-2.36 -1.73,-1.2 -3.28,-2.81 -4.83,-4.41 -2.82,-2.899 -5.67,-5.76 -9.66,-6.029 l -0.45,-0.9 c 4.8,-2.4 9.8,-4.4 14.88,-6.05 l 1.61,1.5 c 9.69,3.88 17.82,8.91 26.73,13.56 10.07,5.04 18.6,6.98 27.51,13.95 4.65,3.87 7.36,4.26 13.56,4.65 5.81,0.38 8.52,1.93 13.94,4.26 8.46,3.869 17.23,5.179 25.75,2.179 z"
-           inkscape:connector-curvature="0"
-           style="fill:#caba9f" /><path
-           id="path29"
-           d="m 298.445,132.929 c 3.32,4.84 5.75,10.5 7.44,16.569 -8.52,3 -17.29,1.69 -25.75,-2.18 -5.42,-2.33 -8.13,-3.88 -13.94,-4.26 -6.2,-0.391 -8.91,-0.78 -13.56,-4.65 -8.91,-6.97 -17.44,-8.91 -27.51,-13.95 -8.91,-4.649 -17.04,-9.68 -26.73,-13.56 l -1.61,-1.5 c 5.73,-1.851 11.57,-3.25 17.32,-4.22 l 0.43,2.5 c 4.1,-0.521 8.6,-0.761 13.33,-0.71 l -0.03,2.77 c 12.79,7.36 26.35,8.14 38.74,15.11 5.86,3.1 23.63,12.31 31.87,8.081 z"
-           inkscape:connector-curvature="0"
-           style="fill:#a3897a" /><path
-           id="path31"
-           d="m 298.445,132.929 c -8.24,4.229 -26.01,-4.98 -31.87,-8.08 -12.39,-6.971 -25.95,-7.75 -38.74,-15.11 l 0.03,-2.77 c 19.89,0.189 43.9,5.38 59.83,15.42 4.32,2.71 7.88,6.319 10.75,10.54 z"
-           inkscape:connector-curvature="0"
-           style="fill:#caba9f" /><path
-           id="path33"
-           d="m 215.445,135.309 c 8.13,3.489 17.43,5.81 24.79,10.85 4.65,3.101 6.59,7.74 12.4,9.29 5.81,1.17 11.23,0 17.04,1.94 7.75,2.71 13.56,8.909 21.31,11.62 5.61,2.14 12.14,1.51 17.94,-0.73 0.62,9.99 -0.15,19.96 -1.73,28.4 -5.2,30.51 -28.72,59.619 -59.61,62.47 -26.92,2.35 -57.44,4.09 -82.09,-11.44 -21.79,-13.279 -28.74,-42.34 -26.2,-68.529 13.14,-1.801 25.9,-5.721 37.8,-10.94 15.1,-6.979 32.54,-12.79 37.19,-30.99 l 1.16,-1.941 z"
-           inkscape:connector-curvature="0"
-           style="fill:#dcd2d2" /><path
-           id="path35"
-           d="m 215.445,135.309 -1.16,1.939 c -4.65,18.2 -22.09,24.011 -37.19,30.99 -11.9,5.22 -24.66,9.14 -37.8,10.94 0.49,-5.221 1.37,-10.33 2.59,-15.17 8.46,-1.7 17.78,-5.95 23.2,-8.171 7.36,-3.1 15.11,-5.81 20.92,-10.85 4.65,-3.479 13.17,-8.52 14.72,-14.33 l 0.66,-1.51 c 4.69,2.162 9.7,3.832 14.06,6.162 z"
-           inkscape:connector-curvature="0"
-           style="fill:#a3897a" /><path
-           id="path37"
-           d="m 201.385,129.148 -0.66,1.51 c -1.55,5.811 -10.07,10.851 -14.72,14.33 -5.81,5.04 -13.56,7.75 -20.92,10.85 -5.42,2.221 -14.74,6.471 -23.2,8.171 0.78,-3.15 1.71,-6.19 2.77,-9.08 1.14,-3.15 2.5,-6.131 4.05,-8.95 15.82,-2.87 32.17,-10.351 41.95,-21.9 l 1.36,-1.7 c 1.55,1.601 3.1,3.21 4.83,4.41 1.45,0.869 2.98,1.64 4.54,2.359 z"
-           inkscape:connector-curvature="0"
-           style="fill:#caba9f" /><path
-           id="path39"
-           d="m 182.355,116.349 c 3.99,0.27 6.84,3.13 9.66,6.029 l -1.36,1.7 c -9.78,11.55 -26.13,19.03 -41.95,21.9 7.53,-13.771 19.55,-23.72 33.2,-30.53 l 0.45,0.901 z"
-           inkscape:connector-curvature="0"
-           style="fill:#a3897a" /></g><g
-         id="g41" /></g><path
-       id="path43"
-       d="m 305.678,169.868 c -4.972,4.817 -15.361,-1.4 -20.364,-3.697 -4.736,-2.173 -9.09,-5.093 -13.842,-7.251 -4.028,-1.829 -8.236,-2.121 -12.592,-2.375 -15.828,-0.925 -24.354,-17.54 -40.206,-19.063 -0.042,-0.004 -0.078,0.003 -0.119,0 -1.515,-0.895 -3.919,-0.229 -3.81,2.024 0.572,11.752 -16.881,19.599 -25.592,23.926 -10.228,5.082 -20.496,10.325 -31.334,13.764 -2.456,0.234 -4.999,0.009 -7.45,0.27 -3.66,0.389 -7.048,2.07 -10.423,3.421 -1.725,0.691 -2.189,3.06 -1.191,4.24 -0.209,1.647 1.021,3.448 2.999,2.723 8.015,-2.943 16.51,-4.259 24.691,-6.652 1.764,-0.517 3.449,-1.158 5.093,-1.869 0.122,1.14 0.914,2.19 2.394,2.185 11.373,-0.046 32.948,-0.366 38.333,-12.899 1.259,-2.929 -3.047,-5.479 -4.316,-2.523 -2.462,5.728 -9.682,7.428 -15.203,8.643 -5.028,1.106 -10.223,1.571 -15.385,1.72 3.488,-1.921 6.876,-4.051 10.419,-6.027 7.204,-4.02 16.453,-4.392 22.879,-9.9 5.01,-4.296 6.59,-10.622 10.175,-15.948 0.392,-0.582 0.482,-1.151 0.385,-1.666 7.511,1.688 13.437,7.293 19.519,11.781 2.901,2.142 5.963,3.877 9.295,5.244 4.724,1.938 9.953,1.424 14.907,2.13 5.285,0.753 10.229,4.342 14.822,6.864 3.445,1.892 7.073,3.537 10.714,5.016 5.83,2.367 13.677,4.362 18.738,-0.542 2.318,-2.251 -1.221,-5.783 -3.536,-3.539 z"
-       inkscape:connector-curvature="0"
-       style="fill:#beb9b9" /><path
-       id="path45"
-       d="m 254.85,169.373 c -10.718,-0.074 -28.397,-1.865 -30.908,-14.824 -0.613,-3.163 -5.432,-1.82 -4.822,1.33 2.996,15.459 22.724,18.404 35.73,18.494 3.225,0.023 3.222,-4.977 0,-5 z"
-       inkscape:connector-curvature="0"
-       style="fill:#beb9b9" /><path
-       id="path47"
-       d="m 138.792,199.716 c 0,0 3.247,66.474 87.734,60.963 84.487,-5.511 -62.422,20.193 -87.734,-60.963 z"
-       inkscape:connector-curvature="0"
-       style="fill:#beb9b9" /><g
-       id="g49"><g
-         id="g51"><path
-           id="path53"
-           d="m 219.385,102.465 c -21.343,2.818 -42.368,10.369 -58.521,24.98 -16.112,14.574 -22.737,35.698 -23.881,56.861 -1.088,20.117 3.587,41.916 17.6,57.035 17.012,18.354 45.473,21.638 69.038,21.216 12.089,-0.217 25.075,-0.412 36.677,-4.118 10.44,-3.336 19.61,-9.918 27.138,-17.761 15.512,-16.16 22.377,-37.929 23.51,-59.897 1.015,-19.673 -2.37,-43.253 -18.011,-56.927 -8.236,-7.2 -19.822,-11.088 -30.178,-13.96 -11.764,-3.264 -24.104,-4.814 -36.299,-4.863 -3.986,-0.016 -7.967,0.245 -11.923,0.715 -2.438,0.29 -2.467,4.15 0,3.857 23.955,-2.846 51.491,1.708 72.185,14.444 19.373,11.923 21.613,40.257 20.13,60.582 -1.762,24.151 -12.267,47.683 -32.208,62.169 -10.564,7.675 -22.151,10.083 -34.91,11.067 -13.845,1.067 -27.831,1.469 -41.609,-0.556 -19.992,-2.938 -39.096,-11.984 -49.006,-30.246 -8.526,-15.713 -9.782,-35.141 -7.35,-52.547 2.584,-18.489 10.472,-34.886 24.876,-47.007 14.635,-12.315 34.018,-18.717 52.743,-21.188 2.427,-0.32 2.459,-4.18 -0.001,-3.856 l 0,0 z"
-           inkscape:connector-curvature="0"
-           style="fill:#1c1c1b" /></g></g><g
-       id="g55"><g
-         id="g57"><path
-           id="path59"
-           d="m 181.74,118.254 c 5.862,0.412 8.855,6.237 13.147,9.455 5.715,4.286 13.27,6.046 19.582,9.264 6.025,3.071 12.814,4.658 18.958,7.518 5.829,2.713 9.434,7.314 14.497,10.955 4.622,3.323 11.275,2.405 16.607,2.818 7.956,0.616 14.358,6.679 21.032,10.422 5.046,2.829 10.858,4.176 16.616,3.3 6.296,-0.958 10.7,-3.723 16.12,-6.733 2.174,-1.208 0.229,-4.539 -1.946,-3.33 -5.928,3.293 -10.759,6.24 -17.816,6.475 -7.275,0.242 -13.477,-4.424 -19.27,-8.192 -5.178,-3.367 -10.247,-5.449 -16.425,-5.928 -3.98,-0.309 -8.112,0.196 -11.848,-1.502 -2.496,-1.135 -4.404,-3.547 -6.313,-5.441 -3.998,-3.97 -9.313,-6.299 -14.445,-8.415 -6.265,-2.584 -12.574,-4.984 -18.819,-7.619 -6.592,-2.781 -12.818,-4.942 -17.895,-10.139 -3.414,-3.495 -6.725,-6.407 -11.78,-6.764 -2.485,-0.176 -2.468,3.682 -0.002,3.856 l 0,0 z"
-           inkscape:connector-curvature="0"
-           style="fill:#1c1c1b" /></g></g><g
-       id="g61"><g
-         id="g63"><path
-           id="path65"
-           d="m 197.885,112.762 c 11.872,4.874 22.572,12.067 34.395,17.038 5.731,2.409 11.359,4.812 16.576,8.228 4.391,2.876 7.506,5.938 12.932,6.568 6.443,0.749 11.404,1.793 17.376,4.386 5.459,2.37 10.922,3.902 16.892,4.099 6.979,0.229 21.132,-2.974 21.262,-11.962 0.036,-2.488 -3.821,-2.484 -3.856,0 -0.073,5.007 -8.935,6.94 -12.591,7.716 -7.326,1.554 -14.693,-0.982 -21.311,-3.856 -3.68,-1.598 -7.198,-3.052 -11.2,-3.632 -5.54,-0.803 -9.764,-0.647 -14.363,-4.303 -7.852,-6.241 -17.348,-9.285 -26.317,-13.478 -9.755,-4.561 -18.771,-10.418 -28.769,-14.522 -2.302,-0.946 -3.294,2.787 -1.026,3.718 l 0,0 z"
-           inkscape:connector-curvature="0"
-           style="fill:#1c1c1b" /></g></g><g
-       id="g67"><g
-         id="g69"><path
-           id="path71"
-           d="m 226.866,111.405 c 7.846,4.342 16.355,6.735 24.866,9.398 7.393,2.313 13.958,5.97 20.92,9.227 7.705,3.605 22.941,10.639 29.768,1.991 1.523,-1.929 -1.187,-4.678 -2.728,-2.727 -6.222,7.882 -22.854,-1.379 -29.514,-4.745 -5.722,-2.893 -11.3,-5.489 -17.422,-7.466 -8.183,-2.641 -16.366,-4.814 -23.944,-9.009 -2.177,-1.204 -4.123,2.127 -1.946,3.331 l 0,0 z"
-           inkscape:connector-curvature="0"
-           style="fill:#1c1c1b" /></g></g><g
-       id="g73"><g
-         id="g75"><path
-           id="path77"
-           d="m 189.287,122.71 c -13.33,15.273 -34.945,22.485 -54.807,22.678 -2.486,0.024 -2.488,3.881 0,3.857 20.814,-0.202 43.56,-7.795 57.535,-23.809 1.627,-1.864 -1.09,-4.604 -2.728,-2.726 l 0,0 z"
-           inkscape:connector-curvature="0"
-           style="fill:#1c1c1b" /></g></g><g
-       id="g79"><g
-         id="g81"><path
-           id="path83"
-           d="m 198.862,130.146 c -2.072,6.059 -8.959,9.602 -13.834,13.182 -6.635,4.873 -13.722,7.874 -21.312,11.005 -9.693,3.999 -23.55,11.66 -34.147,7.396 -2.309,-0.93 -3.302,2.803 -1.025,3.719 11.686,4.703 26.426,-3.363 37.053,-7.748 8.425,-3.476 15.863,-7.119 23.282,-12.42 5.309,-3.792 11.489,-7.633 13.703,-14.107 0.806,-2.362 -2.92,-3.366 -3.72,-1.027 l 0,0 z"
-           inkscape:connector-curvature="0"
-           style="fill:#1c1c1b" /></g></g><g
-       id="g85"><g
-         id="g87"><path
-           id="path89"
-           d="m 212.421,136.731 c -4.241,15.227 -18.143,21.714 -31.472,27.659 -17.583,7.843 -35.612,13.344 -54.993,13.925 -2.481,0.074 -2.488,3.932 0,3.857 20.574,-0.617 39.515,-6.68 58.159,-14.996 13.99,-6.239 27.632,-13.647 32.025,-29.42 0.669,-2.4 -3.053,-3.417 -3.719,-1.025 l 0,0 z"
-           inkscape:connector-curvature="0"
-           style="fill:#1c1c1b" /></g></g><g
-       id="g91"><g
-         id="g93"><path
-           id="path95"
-           d="m 193.317,180.647 c 0.366,6.094 -1.158,12.01 0.569,18.013 0.686,2.386 4.408,1.37 3.719,-1.025 -1.62,-5.634 -0.087,-11.261 -0.431,-16.987 -0.149,-2.471 -4.007,-2.486 -3.857,-0.001 l 0,0 z"
-           inkscape:connector-curvature="0"
-           style="fill:#1c1c1b" /></g></g><g
-       id="g97"><g
-         id="g99"><path
-           id="path101"
-           d="m 241.886,178.66 c 1.345,5.927 0.96,11.958 0.931,17.987 -0.012,2.487 3.844,2.486 3.856,0 0.031,-6.39 0.355,-12.734 -1.069,-19.013 -0.55,-2.424 -4.268,-1.396 -3.718,1.026 l 0,0 z"
-           inkscape:connector-curvature="0"
-           style="fill:#1c1c1b" /></g></g><g
-       id="g103"><g
-         id="g105"><path
-           id="path107"
-           d="m 174.745,179.076 c 12.873,-1.547 26.768,-1.989 35.864,-12.565 1.612,-1.875 -1.103,-4.615 -2.728,-2.727 -8.393,9.759 -21.276,10.011 -33.136,11.435 -2.437,0.293 -2.466,4.153 0,3.857 l 0,0 z"
-           inkscape:connector-curvature="0"
-           style="fill:#1c1c1b" /></g></g><g
-       id="g109"><g
-         id="g111"><path
-           id="path113"
-           d="m 221.08,154.121 c 6.875,11.79 20.959,17.268 34.165,16.955 2.483,-0.06 2.489,-3.916 0,-3.857 -11.854,0.281 -24.632,-4.406 -30.835,-15.045 -1.251,-2.147 -4.585,-0.206 -3.33,1.947 l 0,0 z"
-           inkscape:connector-curvature="0"
-           style="fill:#1c1c1b" /></g></g><g
-       id="g115"><g
-         id="g117"><path
-           id="path119"
-           d="m 189.108,242.511 c 10.387,-8.83 26.196,-9.952 39.147,-11.699 18.439,-2.488 36.867,-6.533 55.489,-7.236 2.479,-0.093 2.488,-3.95 0,-3.855 -19.209,0.724 -38.216,4.918 -57.235,7.469 -13.594,1.824 -29.258,3.354 -40.128,12.596 -1.897,1.611 0.845,4.325 2.727,2.725 l 0,0 z"
-           inkscape:connector-curvature="0"
-           style="fill:#1c1c1b" /></g></g></g></svg>
\ No newline at end of file
diff --git a/pages/version-menu/style.css b/pages/version-menu/style.css
deleted file mode 100644
index 38b69776..00000000
--- a/pages/version-menu/style.css
+++ /dev/null
@@ -1,81 +0,0 @@
-
-@media (min-resolution: 120dpi) and (orientation: portrait)
-{
-	* { font-size: 18pt; }
-}
-@media (min-resolution: 120dpi) and (orientation: landscape)
-{
-	* { font-size: 10pt; }
-}
-@media (orientation: portrait)
-{
-	#main
-	{
-		padding: 0;
-	}
-	#main > div
-	{
-		display: block;
-		width: 80%;
-		padding: 0 10%;
-	}
-	#main > div
-	{
-		padding-bottom: 2em;
-	}
-}
-@media (orientation: landscape)
-{
-	#main
-	{
-		padding: 0;
-	}
-	#main > div
-	{
-		display: inline-block;
-		vertical-align: top;
-		width: 24%;
-		padding: 0 5%;
-	}
-}
-
-*
-{
-	font-family: 'Roboto';
-}
-body
-{
-	position: absolute;
-	margin: 0;
-	padding: 0;
-	width: 100%;
-	height: 100%;
-}
-#main
-{
-	position: relative;
-	text-align: center;
-}
-h1
-{
-	font-size: 2.5rem;
-	font-weight: normal;
-	margin: 1.2em 1em;
-	padding: 0;
-}
-img
-{
-	width: 100%;
-	margin-bottom: .8em;
-}
-p
-{
-	text-align: center;
-	font-size: 1.6rem;
-	margin: 0;
-}
-a
-{
-	color: black;
-	text-decoration: none;
-}
diff --git a/pages/version-menu/ui.php b/pages/version-menu/ui.php
deleted file mode 100644
index cd94eb69..00000000
--- a/pages/version-menu/ui.php
+++ /dev/null
@@ -1,42 +0,0 @@
-<!DOCTYPE html>
-<html xmlns="http://www.w3.org/1999/xhtml">
-<head>
-	<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
-	<meta name="viewport" content="user-scalable=no"/>
-	<meta name="content-language" content="<?=$lang?>"/>
-	<link href="//fonts.googleapis.com/css?family=Roboto" rel="stylesheet" type="text/css"/>
-	<?=css("$dir/style")?>
-	<title>Verdnatura</title>
-</head>
-<body>
-	<div id="main">
-		<h1><?=s('Welcome to Verdnatura, where are you going?')?></h1>
-		<div>
-			<a href="https://test-www.verdnatura.es/">
-				<div>
-					<img src="<?=$dir?>/new-web.svg" alt=""></img>
-					<p>
-						<?=s('New website')?>
-					</p>
-					<p>
-						<?=s('(Fantastic)')?>
-					</p>
-				</div>
-			</a>
-		</div>
-		<div>
-			<a href="?skipVersion=true">
-				<div>
-					<img src="<?=$dir?>/old-web.svg" alt=""></img>
-					<p>
-						<?=s('Old website')?>
-					</p>
-					<p>
-						<?=s('(Best choose new)')?>
-					</p>
-				</div>
-			</a>
-		</div>
-	</div>
-</body>
-</html>