4974-datasources-and-improvements #4

Merged
guillermo merged 24 commits from 4974-datasources-and-improvements into master 2023-02-03 12:26:09 +00:00
49 changed files with 600 additions and 375 deletions

View File

@ -1,4 +1,4 @@
Copyright (C) 2020 - Verdnatura Levante S.L.
Copyright (C) 2023 - Verdnatura Levante S.L.
This package is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by

BIN
datasources/datasource.bmp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

BIN
datasources/development.bmp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

BIN
datasources/production.bmp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

BIN
datasources/test.bmp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Before

Width:  |  Height:  |  Size: 264 KiB

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 264 KiB

After

Width:  |  Height:  |  Size: 2.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 264 KiB

After

Width:  |  Height:  |  Size: 3.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 264 KiB

After

Width:  |  Height:  |  Size: 4.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 264 KiB

After

Width:  |  Height:  |  Size: 3.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 264 KiB

After

Width:  |  Height:  |  Size: 4.2 KiB

BIN
icons/vn.ico Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 959 KiB

After

Width:  |  Height:  |  Size: 959 KiB

View File

@ -1,6 +1,6 @@
#define MyAppName "Verdnatura"
#define MyAppVersion "4"
#define MyAppVersion "5"
#define MyAppPublisher "Verdnatura"
#define MyAppURL "https://www.verdnatura.es/"
@ -50,28 +50,64 @@ Source: "src\*"; \
DestDir: "{app}"; Flags: ignoreversion
Source: "branches\*"; \
DestDir: "{app}\branches"; Flags: ignoreversion
Source: "datasources\*"; \
DestDir: "{app}\datasources"; Flags: ignoreversion
Source: "icons\*"; \
DestDir: "{app}\icons"; Flags: ignoreversion
Source: "ocx\*"; \
DestDir: {sys}; Flags: onlyifdoesntexist regserver 32bit
Source: "fonts\Roboto*"; \
DestDir: "{fonts}"; FontInstall: "Roboto"; Flags: onlyifdoesntexist uninsneveruninstall
Source: "fonts\Lucida Sans - *"; \
DestDir: "{fonts}"; FontInstall: "Lucida Sans"; Flags: onlyifdoesntexist uninsneveruninstall
Source: "fonts\Code128B.ttf"; \
DestDir: "{fonts}"; FontInstall: "Code128B"; Flags: onlyifdoesntexist uninsneveruninstall
Source: "fonts\Code128L.ttf"; \
DestDir: "{fonts}"; FontInstall: "Code128L"; Flags: onlyifdoesntexist uninsneveruninstall
Source: "fonts\CCode39.ttf"; \
DestDir: "{fonts}"; FontInstall: "CCode39"; Flags: onlyifdoesntexist uninsneveruninstall
Source: "fonts\Free 3 of 9.ttf"; \
DestDir: "{fonts}"; FontInstall: "Free 3 of 9"; Flags: onlyifdoesntexist uninsneveruninstall
Source: "fonts\Free 3 of 9 Extended.ttf"; \
DestDir: "{fonts}"; FontInstall: "Free 3 of 9 Extended"; Flags: onlyifdoesntexist uninsneveruninstall
Source: "fonts\IDAutomationHC39M.ttf"; \
DestDir: "{fonts}"; FontInstall: "IDAutomationHC39M"; Flags: onlyifdoesntexist uninsneveruninstall
Source: "fonts\MRV Code39extMA.ttf"; \
DestDir: "{fonts}"; FontInstall: "MRV Code39extMA"; Flags: onlyifdoesntexist uninsneveruninstall
; Roboto ToDo: Loop in code to install all fonts into folder
Source: "fonts\Roboto\Roboto-Black.ttf"; DestDir: "{commonfonts}"; \
FontInstall: "Roboto-Black"; Flags: onlyifdoesntexist uninsneveruninstall
Source: "fonts\Roboto\Roboto-BlackItalic.ttf"; DestDir: "{commonfonts}"; \
FontInstall: "Roboto-BlackItalic"; Flags: onlyifdoesntexist uninsneveruninstall
Source: "fonts\Roboto\Roboto-Bold.ttf"; DestDir: "{commonfonts}"; \
FontInstall: "Roboto-Bold"; Flags: onlyifdoesntexist uninsneveruninstall
Source: "fonts\Roboto\Roboto-BoldItalic.ttf"; DestDir: "{commonfonts}"; \
FontInstall: "Roboto-BoldItalic"; Flags: onlyifdoesntexist uninsneveruninstall
Source: "fonts\Roboto\Roboto-Italic.ttf"; DestDir: "{commonfonts}"; \
FontInstall: "Roboto-Italic"; Flags: onlyifdoesntexist uninsneveruninstall
Source: "fonts\Roboto\Roboto-Light.ttf"; DestDir: "{commonfonts}"; \
FontInstall: "Roboto-Light"; Flags: onlyifdoesntexist uninsneveruninstall
Source: "fonts\Roboto\Roboto-LightItalic.ttf"; DestDir: "{commonfonts}"; \
FontInstall: "Roboto-LightItalic"; Flags: onlyifdoesntexist uninsneveruninstall
Source: "fonts\Roboto\Roboto-Medium.ttf"; DestDir: "{commonfonts}"; \
FontInstall: "Roboto-Medium"; Flags: onlyifdoesntexist uninsneveruninstall
Source: "fonts\Roboto\Roboto-MediumItalic.ttf"; DestDir: "{commonfonts}"; \
FontInstall: "Roboto-MediumItalic"; Flags: onlyifdoesntexist uninsneveruninstall
Source: "fonts\Roboto\Roboto-Regular.ttf"; DestDir: "{commonfonts}"; \
FontInstall: "Roboto-Regular"; Flags: onlyifdoesntexist uninsneveruninstall
Source: "fonts\Roboto\Roboto-Thin.ttf"; DestDir: "{commonfonts}"; \
FontInstall: "Roboto-Thin"; Flags: onlyifdoesntexist uninsneveruninstall
Source: "fonts\Roboto\Roboto-ThinItalic.ttf"; DestDir: "{commonfonts}"; \
FontInstall: "Roboto-ThinItalic"; Flags: onlyifdoesntexist uninsneveruninstall
; Poppins
Source: "fonts\Poppins\Poppins-Regular.ttf"; DestDir: "{commonfonts}"; \
FontInstall: "Poppins-Regular.ttf"; Flags: onlyifdoesntexist uninsneveruninstall
Source: "fonts\Poppins\Poppins-Thin.ttf"; DestDir: "{commonfonts}"; \
FontInstall: "Poppins-Thin"; Flags: onlyifdoesntexist uninsneveruninstall
Source: "fonts\Poppins\Poppins-Bold.ttf"; DestDir: "{commonfonts}"; \
FontInstall: "Poppins-Bold"; Flags: onlyifdoesntexist uninsneveruninstall
Source: "fonts\Poppins\Poppins-Italic.ttf"; DestDir: "{commonfonts}"; \
FontInstall: "Poppins-Italic"; Flags: onlyifdoesntexist uninsneveruninstall
; Codes
Source: "fonts\Code128B.ttf"; DestDir: "{commonfonts}"; \
FontInstall: "Code128B"; Flags: onlyifdoesntexist uninsneveruninstall
Source: "fonts\Code128L.ttf"; DestDir: "{commonfonts}"; \
FontInstall: "Code128L"; Flags: onlyifdoesntexist uninsneveruninstall
Source: "fonts\CCode39.ttf"; DestDir: "{commonfonts}"; \
FontInstall: "CCode39"; Flags: onlyifdoesntexist uninsneveruninstall
Source: "fonts\Free 3 of 9.ttf"; DestDir: "{commonfonts}"; \
FontInstall: "Free 3 of 9"; Flags: onlyifdoesntexist uninsneveruninstall
Source: "fonts\Free 3 of 9 Extended.ttf"; DestDir: "{commonfonts}"; \
FontInstall: "Free 3 of 9 Extended"; Flags: onlyifdoesntexist uninsneveruninstall
Source: "fonts\IDAutomationHC39M.ttf"; DestDir: "{commonfonts}"; \
FontInstall: "IDAutomationHC39M"; Flags: onlyifdoesntexist uninsneveruninstall
Source: "fonts\MRV Code39extMA.ttf"; DestDir: "{commonfonts}"; \
FontInstall: "MRV Code39extMA"; Flags: onlyifdoesntexist uninsneveruninstall
[Tasks]
Name: "desktopicon"; \
@ -97,9 +133,6 @@ Name: "eti"; \
Name: "lab"; \
Description: "Laboral"; \
Types: full
Name: "srv"; \
Description: "Server"; \
Types: full
Name: "vn"; \
Description: "Library"; \
Types: full
@ -141,21 +174,14 @@ Name: "{group}\Laboral"; \
IconFileName: "{app}\icons\lab.ico"; \
FileName: "{app}\vn-access.hta"; \
WorkingDir: "{app}"
Name: "{group}\Server"; \
Parameters: "srv"; \
Components: srv; \
IconFileName: "{app}\icons\enc.ico"; \
FileName: "{app}\vn-access.hta"; \
WorkingDir: "{app}"
Name: "{group}\Library"; \
Parameters: "vn"; \
Components: vn; \
IconFileName: "{app}\icons\enc.ico"; \
IconFileName: "{app}\icons\vn.ico"; \
FileName: "{app}\vn-access.hta"; \
WorkingDir: "{app}"
; Desktop icons
Name: "{commondesktop}\Terminal Punto Venta"; \
Parameters: "tpv"; \
Components: tpv; \
@ -198,23 +224,15 @@ Name: "{commondesktop}\Laboral"; \
FileName: "{app}\vn-access.hta"; \
WorkingDir: "{app}"; \
Tasks: desktopicon
Name: "{commondesktop}\Server"; \
Parameters: "srv"; \
Components: srv; \
IconFileName: "{app}\icons\enc.ico"; \
FileName: "{app}\vn-access.hta"; \
WorkingDir: "{app}"; \
Tasks: desktopicon
Name: "{commondesktop}\Library"; \
Parameters: "vn"; \
Components: vn; \
IconFileName: "{app}\icons\enc.ico"; \
IconFileName: "{app}\icons\vn.ico"; \
FileName: "{app}\vn-access.hta"; \
WorkingDir: "{app}"; \
Tasks: desktopicon
[Code]
procedure InstallExe;
var
StatusText: String;

BIN
src/datasource.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 893 B

View File

@ -1,45 +1,50 @@
// Check when version 6 is uploaded
// Only in case all host have version 5
// Delete code with comment REMOVE!
var Conf = {
appName: 'Verdnatura'
,dsName: 'verdnatura'
,dsPath: 'HKCU\\Software\\ODBC\\ODBC.INI\\verdnatura'
,regPath: 'HKCU\\Software\\Verdnatura\\vn-access'
,remoteUrl: 'https://cdn.verdnatura.es/vn-access'
,dbHost: 'db.verdnatura.es'
,defaultModule: 'tpv'
,defaultLocale: 'es'
,defaultBranch: 'master'
,dbName: 'vn2008'
,maxCorruptSize: 600
,odbcDriver: 'MySQL ODBC 8.0 Unicode Driver'
,driverPath: '\\MySQL\\Connector ODBC 8.0\\myodbc8w.dll'
,version: 3
appName: 'Verdnatura',
odbcPath: 'HKCU\\SOFTWARE\\ODBC\\ODBC.INI\\',
regPath: 'HKCU\\SOFTWARE\\Verdnatura\\vn-access',
defaultModule: 'vn',
defaultLocale: 'es',
defaultBranch: 'master',
defaultDatasource: 'production',
defaultRemoteURL: 'https://salix.verdnatura.es',
defaultServer: 'db.verdnatura.es',
dbName: 'vn2008',
maxCorruptSize: 600,
odbcDriver: 'MySQL ODBC 8.0 Unicode Driver',
driverPath: '\\MySQL\\Connector ODBC 8.0\\myodbc8w.dll',
version: 5,
cdnURL: 'https://cdn.verdnatura.es/vn-access',
identifier: '.vn'
};
var Locale = {
es: {
"Enter a username":
"Introduce un nombre de usuario"
,"Enter a password":
"Introduce una contraseña"
,"Server can't be reached":
"No se ha podido conectar con el servidor"
,"Updating":
"Actualizando"
,"Bad login":
"Usuario o contraseña incorrectos"
,"Application it's already open":
"La aplicación ya está abierta"
,"Loading":
"Cargando"
,"Error while updating":
"Error al actualizar"
,"Microsoft Access 2003 is not installed":
"Microsoft Access 2003 no está instalado en el sistema"
,"MDB file not found":
"No se encontró el fichero MDB"
,"Cache files have been deleted":
"Se han borrado todos los ficheros de la caché"
"Introduce un nombre de usuario",
"Enter a password":
"Introduce una contraseña",
"Server can't be reached":
"No se ha podido conectar con el servidor",
"Updating":
"Actualizando",
"Bad login":
"Usuario o contraseña incorrectos, recuerda que se hace distinción entre mayúsculas y minúsculas",
"Application it's already open":
"La aplicación ya está abierta",
"Loading":
"Cargando",
"Error while updating":
"Error al actualizar",
"Microsoft Access 2003 is not installed":
"Microsoft Access 2003 no está instalado en el sistema",
"MDB file not found":
"No se encontró el fichero MDB",
"Cache files have been deleted":
"Se han borrado todos los ficheros almacenados en la caché"
}
};
@ -48,101 +53,132 @@ var App = {
fso: new ActiveXObject('scripting.filesystemobject'),
init: function() {
// Specify the size of window
var width = 420;
var height = 525;
var height = 570;
window.resizeTo(width, height);
window.moveTo((screen.width - width) / 2, (screen.height - height) / 2);
},
onUnload: function() {
this.disableUi(false);
},
onLoad: function() {
// Initializes the global variables
var split = Verdnatura.commandLine.match(/(?:[^\s"]+|"[^"]*")+/g);
if (split.length > 1)
this.module = split[1].replace(/^"+|"+$/g, '');
if (!this.module)
this.module = Conf.defaultModule;
this.appDir = this.getEnv('ProgramFiles') +'\\'+ Conf.appName;
this.moduleDir = this.shell.SpecialFolders('AppData') +'\\'+ Conf.appName;
this.compressFile = this.getEnv('TEMP') +'\\'+ this.module +'.7z';
this.mdbFile = this.moduleDir +'\\'+ this.module +'.mdb';
this.lockFile = this.moduleDir +'\\'+ this.module +'.ldb';
this.certFile = this.appDir +'\\cacert.pem';
this.lockFile = this.moduleDir +'\\' + this.module +'.ldb';
this.mdbFile = this.moduleDir +'\\' + this.module +'.mdb';
var defaultDsName = this.formatDatasource(Conf.defaultDatasource);
var mdbDsName = this.mdbGetValue(
'SELECT dsName FROM TblConfig',
'dsName', String
);
this.dsName = mdbDsName || defaultDsName;
// Creates the necessary registry entries
var lastVersion = this.regRead(Conf.regPath, 'lastExecutedVersion');
var configured = this.regRead(Conf.regPath, 'configured');
if (!configured || configured < Conf.version) {
var path;
if (!lastVersion || lastVersion != Conf.version) {
var path = 'HKCU\\Software\\Microsoft\\Office\\11.0\\Access\\';
// Creates the Access configuration entries
path = 'HKCU\\Software\\Microsoft\\Office\\11.0\\Access\\Settings';
this.regWrites(path, {
this.regWrites(path +'Settings', {
'Confirm Document Deletions': false,
'Confirm Action Queries': false,
'Confirm Record Changes': false
});
path = 'HKCU\\Software\\Microsoft\\Office\\11.0\\Access\\Security';
this.regWrite(path, 'Level', 1);
this.regWrite(path + 'Security', 'Level', 1);
// Creates the MySQL ODBC connection
var driverPath = this.getEnv('ProgramFiles') + Conf.driverPath;
var params = {
Driver : driverPath,
DESCRIPTION : Conf.appName,
SERVER : Conf.dbHost,
DATABASE : Conf.dbName,
SSLCA : this.certFile,
SSLMODE : 'VERIFY_IDENTITY',
SSLCIPHER : 'AES256-SHA',
AUTO_RECONNECT : '1',
NO_PROMPT : '1',
ENABLE_CLEARTEXT_PLUGIN : '1'
};
this.createOdbc(
Conf.dsName,
this.createODBC(Conf.odbcPath,
defaultDsName,
Conf.odbcDriver,
params
Conf.defaultDatasource
);
// Marks the application as configured
this.regWrite(Conf.regPath, 'remoteURL', Conf.defaultRemoteURL);
this.regWrite(Conf.regPath, 'lastExecutedVersion', Conf.version);
this.regWrite(Conf.regPath, 'configured', Conf.version);
// REMOVE!
this.createODBC(Conf.odbcPath,
'verdnatura',
Conf.odbcDriver,
'keep for backward compatibility'
);
// -----
this.regDelete(Conf.regPath +'\\configured');
this.regDelete(Conf.regPath + '\\remember');
}
// Loads the form data
var notSignOut = this.regRead(Conf.regPath, 'notSignOut');
var user = this.regRead(Conf.dsPath, 'UID');
var password = this.regRead(Conf.dsPath, 'PWD');
var remember = this.regRead(Conf.regPath, 'remember');
// Branch options
this.request('GET', 'mdbBranches', null, function(err, res) {
if (err)
throw new Error ('Version could not be retrieved: '+ err.message +': ');
var selectBranch = document.querySelector('#branch');
var option = [];
for (var x in res) {
option[x] = document.createElement('option');
option[x].text = res[x].name
option[x].value = res[x].name
selectBranch.options.add(option[x])
}
});
var branch = this.mdbGetValue(
'SELECT branch FROM tblVariables',
'branch', String
);
if (!branch)
branch = Conf.defaultBranch;
this.$('branch').value = branch;
this.onChangeBranch();
this.$('branch').value = this.getBranch();
this.onChangeBranchChange();
// Datasource options
var selectDatarouce = document.querySelector('#datasource');
var option = [];
var allOdbc = this.enumValues(Conf.odbcPath +'ODBC Data Sources\\');
var idLen = Conf.identifier.length;
for (var y in allOdbc) {
if (allOdbc[y].slice(-idLen) == Conf.identifier) {
var odbcName = allOdbc[y];
option[y] = document.createElement('option');
option[y].text = this.getDatasource(odbcName);
option[y].value = odbcName;
selectDatarouce.options.add(option[y])
}
}
// REMOVE!
if (this.dsName == 'verdnatura') {
this.dsName = Conf.defaultDatasource;
this.$('datasource').value = this.dsName + Conf.identifier;
this.$('datasource').text = this.dsName;
} else // -----
this.$('datasource').value = this.dsName;
if (user)
this.$('user').value = user;
if (remember && password) {
this.$('password').value = password;
this.$('remember').checked = true;
if (notSignOut && password) {
this.$('notSignOut').checked = true;
this.onChangeDatasource(true);
this.onEnterClick();
} else
} else {
this.resetForm(true);
this.onChangeDatasource(true);
}
},
formatDatasource: function(datasource) {
return datasource + Conf.identifier;
},
getDatasource: function(dsName) {
return dsName.substr(0, dsName.length - Conf.identifier.length);
},
resetForm: function(clearPassword) {
if (clearPassword)
this.$('password').value = '';
@ -150,13 +186,38 @@ var App = {
this.$('user').focus();
this.$('user').select();
},
createODBC: function(path, dsName, driverName, description) {
var driverPath = this.getEnv('ProgramFiles') + Conf.driverPath;
var params = {
Driver: driverPath,
DESCRIPTION: description,
SERVER: Conf.defaultServer,
DATABASE: Conf.dbName,
SSLCA: this.certFile,
SSLMODE: 'VERIFY_IDENTITY',
SSLCIPHER: 'AES256-SHA',
AUTO_RECONNECT: 1,
NO_PROMPT: 1,
};
createOdbc: function(dsName, driverName, params) {
var odbcPath = 'HKCU\\Software\\ODBC\\ODBC.INI\\';
this.regWrites(odbcPath + dsName, params);
this.regWrite(odbcPath + 'ODBC Data Sources', dsName, driverName);
this.regWrite(path + 'ODBC Data Sources', dsName, driverName);
this.regWrites(path + dsName, params);
},
updateODBC: function() {
var odbcPath = this.getOdbcPath();
var myUID = this.regRead(odbcPath, 'remoteUser');
var myPWD = this.regRead(odbcPath, 'remotePass');
var params = [];
if (myUID && myPWD) {
params['UID'] = myUID;
params['PWD'] = myPWD;
} else {
params['UID'] = this.regRead(odbcPath, 'UID');
params['PWD'] = this.regRead(odbcPath, 'PWD');
}
this.regWrites(odbcPath, params);
},
disableUi: function(disabled, loadMessage) {
if (disabled)
this.hideMessage();
@ -167,26 +228,35 @@ var App = {
this.$('user').disabled = disabled;
this.$('password').disabled = disabled;
this.$('remember').disabled = disabled;
this.$('notSignOut').disabled = disabled;
this.$('enter').disabled = disabled;
var display = disabled ? 'block' : 'none';
this.$('background').style.display = display;
this.$('spinner').style.display = display;
},
onCleanCacheClick: function() {
setTimeout(function() { App.cleanCache(); });
},
onShowOptionsClick: function() {
onShowBranchOptionsClick: function() {
var style = this.$("branchSelector").style;
style.display = style.display == 'none' || !style.display
? 'inline'
: 'none';
},
onShowDatasourceOptionsClick: function() {
var style = this.$("datasourceSelector").style;
style.display = style.display == 'none' || !style.display
? 'inline'
: 'none';
onChangeBranchChange: function() {
if (!this.$("datasourceLogo").className)
this.$("datasourceLogo").className = "on";
else
this.$("datasourceLogo").className = "";
},
onChangeBranch: function() {
if (this.$("branch").value == "master"||"test"||"dev") {
this.$("branchButton").className = this.$("branch").value;
this.$("branch").className = this.$("branch").value;
@ -196,7 +266,44 @@ var App = {
}
this.$('user').focus();
},
/**
* Changes the datasource, and optionally do the following
*
* @param {Boolean} hasUpdate
*/
onChangeDatasource: function(hasUpdate) {
this.dsName = this.$("datasource").value;
var myDatasource = this.getDatasource(this.dsName);
if (myDatasource == "production"||"test"||"dev") {
this.$("datasourceButton").className = myDatasource;
this.$("datasource").className = myDatasource;
} else {
this.$("datasourceButton").className = null;
this.$("datasource").className = null;
};
if (!hasUpdate) {
this.updateODBC();
};
var odbcPath = this.getOdbcPath();
var myUID = this.regRead(odbcPath, 'remoteUser');
var myPWD = this.regRead(odbcPath, 'remotePass');
var notSignOut = this.regRead(Conf.regPath, 'notSignOut');
if (myUID && myPWD && !notSignOut) {
this.$('user').value = myUID;
this.$('password').value = myPWD;
} else {
var user = this.regRead(odbcPath, 'UID')
if (user)
this.$('user').value = user
if (!notSignOut)
this.resetForm(true)
else
this.$('password').value = this.regRead(odbcPath, 'PWD')
}
this.$('user').focus();
},
cleanCache: function() {
if (this.fso.folderExists(this.moduleDir)) {
var folder = this.fso.getFolder(this.moduleDir);
@ -212,7 +319,6 @@ var App = {
}
this.showMessage(_('Cache files have been deleted'), 'notice');
},
onKeyPress: function(event) {
switch (event.keyCode) {
case 13: // Enter
@ -223,7 +329,6 @@ var App = {
break;
}
},
onEnterPress: function(event) {
var target = event.target || event.srcElement;
@ -231,80 +336,34 @@ var App = {
this.$('password').focus();
return;
}
this.onEnterClick();
},
onEnterClick: function() {
this.disableUi(true, _('Loading'));
setTimeout(function() { App.login(); });
},
login: function() {
try {
var user = this.$('user').value;
var password = this.$('password').value;
var branch = this.$('branch').value;
if (!user || user === '')
if (!user)
throw new Error(_('Enter a username'));
if (!password || password === '')
var password = this.$('password').value;
if (!password)
throw new Error(_('Enter a password'));
if (!branch || branch === '')
throw new Error(_('Select a branch'));
this.regWrite(Conf.dsPath, 'UID', user);
this.regWrite(Conf.dsPath, 'PWD', password);
var version = this.fetchVersion();
if (version !== null) {
this.disableUi(true, _('Updating'));
var remoteFile = version
? '.archive/'+ this.module +'/'+ version +'.7z'
: this.module +'.7z?'+ new Date().getTime();
remoteFile = Conf.remoteUrl +'/'+ remoteFile;
var request = new ActiveXObject("MSXML2.XMLHTTP");
request.open('GET', remoteFile, true);
request.onreadystatechange = function() {
App.onRequestReady(request);
};
request.send();
} else
this.openMdb();
} catch (err) {
this.catchError(err);
}
},
/**
* Gets information about the version to download.
* cmdle
* @return {Number|Boolean} Version number, %false if cannot
* fetch or %null if local is up-to-date
*/
fetchVersion: function() {
// Gets the last version number using the MySQL ODBC connection
var mysqlConn = new ActiveXObject('ADODB.Connection');;
this.regWrite(this.getOdbcPath(), 'UID', user);
this.regWrite(this.getOdbcPath(), 'PWD', password);
var mysqlConn = new ActiveXObject('ADODB.Connection');
// Check credentials
try {
mysqlConn.open(this.getOdbcString({
Driver : '{'+ Conf.odbcDriver +'}',
Server : Conf.dbHost,
Database : Conf.dbName,
Uid : this.$('user').value,
Pwd : this.$('password').value,
Sslca : this.certFile,
SslMode : 'VERIFY_IDENTITY',
SslCipher : 'AES256-SHA',
ENABLE_CLEARTEXT_PLUGIN : 1
}));
mysqlConn.open(this.dsName)
} catch (err) {
var dbErrors = mysqlConn && mysqlConn.errors;
if (dbErrors && dbErrors.count > 0) {
var dbError = dbErrors.item(0);
switch (dbError.NativeError) {
case 1045: // Access denied
clearPassword = true;
@ -317,65 +376,100 @@ var App = {
default:
err = new Error(dbError.description);
}
dbErrors.clear();
}
throw err;
}
var sql = "SELECT version " +
" FROM vn.mdbVersion " +
" WHERE app = '"+ this.module +"' " +
" AND branchFk = '" + this.$('branch').value + "'";
var rs = mysqlConn.execute(sql);
var version = rs.EOF ? false : parseInt(rs.fields(0).value);
rs.close();
mysqlConn.close();
if (this.$('previous-version').checked && version > 1)
version -= 1;
// Check the cretentials and return the last version number
this.fetchVersion();
} catch (err) {
this.catchError(err);
}
},
/**
* Gets information about the version to download.
* cmdle
* @return {Number|Boolean} Version number, %false if cannot
* fetch or %null if local is up-to-date
*/
fetchVersion: function() {
// To obtain the lastest version of this module
var params = {
filter: {
fields: ['version'],
where: {
app: this.module,
branchFk: this.$('branch').value
},
}
};
this.request('GET', 'MdbVersions/findOne', params,
function(err, res) { App.onVersionRequest(err, res); }
);
},
onVersionRequest: function(err, res) {
if (err)
throw new Error ('Version could not be retrieved: '+ err.message +': ');
var lastVersion;
// Checks if it's already open
if (this.fso.fileExists(this.lockFile))
try {
this.fso.deleteFile(this.lockFile);
return version;
lastVersion = res.version;
} catch (e) {
throw new Error(_('Application it\'s already open'));
}
// Checks if MDB exists
if (!this.fso.fileExists(this.mdbFile))
return version;
lastVersion = res.version;
// If it's abnormaly bigger, maybe is corrupted, so force download
if (!lastVersion) {
var file = this.fso.getFile(this.mdbFile);
if (file.size > Conf.maxCorruptSize * 1024 * 1024)
return version;
lastVersion = res.version;
// Obtains the local version number from the MDB file
var localVersion = this.mdbGetValue(
'SELECT Version FROM tblVariables',
'Version', parseInt
);
if (!localVersion) localVersion = false;
if (!localVersion)
localVersion = false;
// Determines if should download
return !localVersion || version === false || localVersion != version
? version
: null;
},
!localVersion || res.version === false || localVersion != res.version
? lastVersion = res.version
: lastVersion = null;
}
// Check if there is a new version, and if there is, download it
if (lastVersion) {
this.disableUi(true, _('Updating'));
var remoteFile = lastVersion
? '.archive/'+ this.module +'/'+ lastVersion +'.7z'
: this.module +'.7z?'+ new Date().getTime();
remoteFile = Conf.cdnURL +'/'+ remoteFile;
var request = new ActiveXObject('MSXML2.XMLHTTP.6.0');
request.open('GET', remoteFile, true);
request.onreadystatechange = function() {
App.onRequestReady(request);
};
request.send();
} else
App.openMdb();
},
mdbGetValue: function(query, field, parseFn) {
var value;
try {
if (this.fso.fileExists(this.mdbFile)) {
var mdbConn = new ActiveXObject('ADODB.Connection');
mdbConn.open(this.getOdbcString({
mdbConn.open(this.getODBCString({
'Provider': 'Microsoft.Jet.OLEDB.4.0',
'Data Source': this.mdbFile
}));
@ -393,21 +487,19 @@ var App = {
return value;
},
getOdbcString: function(options) {
getODBCString: function(options) {
var optionsArray = [];
for (var option in options)
optionsArray.push(option +'='+ options[option]);
return optionsArray.join(';');
},
onRequestReady: function(request) {
if (request.readyState !== 4)
return;
try {
if (request.status !== 200)
throw new Error('HTTP: '+ request.statusText);
throw new Error('HTTP: '+ request.statusText + ' ' + request.status);
if (this.fso.fileExists(this.compressFile))
this.fso.deleteFile(this.compressFile);
@ -438,10 +530,9 @@ var App = {
this.catchError(e);
}
},
openMdb: function() {
var remember = !!this.$('remember').checked;
this.regWrite(Conf.regPath, 'remember', remember);
var notSignOut = !!this.$('notSignOut').checked;
this.regWrite(Conf.regPath, 'notSignOut', notSignOut);
var programFiles = this.getEnv('ProgramFiles');
var accessBin = programFiles +'\\Microsoft Office\\OFFICE11\\MSACCESS.EXE';
@ -449,21 +540,23 @@ var App = {
if (!this.fso.fileExists(accessBin))
throw new Error(_('Microsoft Access 2003 is not installed'));
this.shell.exec('"'+ accessBin +'" "'+ this.mdbFile +'"');
// Open the mdb and pass it the argument
this.shell.exec('"'+ accessBin +'" "'+ this.mdbFile +'" /cmd "'+ this.dsName +'"');
window.close();
},
catchError: function(err) {
var clearPassword = err.name == 'BadLogin';
if (!this.$('remember').checked || clearPassword)
this.regWrite(Conf.dsPath, 'PWD', '');
if (this.$('notSignOut').checked) {
this.regWrite(this.getOdbcPath(), 'PWD', '');
this.regWrite(Conf.regPath, 'notSignOut', 0)
this.$('notSignOut').checked = false
}
this.disableUi(false);
this.showMessage(err.message, 'error');
this.resetForm(clearPassword);
},
/**
* Displays a non-intrusive message.
*
@ -475,7 +568,6 @@ var App = {
App.showMessageAsync(message, className);
});
},
showMessageAsync: function(message, className) {
if (this.messageTimeout)
clearTimeout(this.messageTimeout);
@ -488,11 +580,13 @@ var App = {
App.hideMessage();
}, 10000);
},
onBodyClick: function() {
this.hideMessage();
},
openOptions: function() {
this.onShowBranchOptionsClick();
this.onShowDatasourceOptionsClick();
},
/**
* Hides the last displayed non-intrusive message.
*/
@ -503,7 +597,6 @@ var App = {
this.messageTimeout = null;
}
},
/**
* Obtains a DOM element by it's identifier.
*
@ -512,18 +605,15 @@ var App = {
$: function(id) {
return document.getElementById(id);
},
run: function(command, wait) {
if (!wait)
wait = false;
this.shell.run(command, 0, wait);
},
getEnv: function(varName) {
return this.shell.expandEnvironmentStrings('%'+ varName +'%');
},
regRead: function(path, key) {
try {
var value = this.shell.regRead(path +'\\'+ key);
@ -533,7 +623,6 @@ var App = {
return value;
},
regWrite: function(path, key, value, type) {
if (!type)
switch (typeof (value))
@ -547,33 +636,98 @@ var App = {
break;
default:
type = 'REG_SZ';
if (!value)
value = '';
}
this.shell.regWrite(path + '\\' + key, value.toString(), type);
},
regWrites: function(path, values, type) {
for(var key in values)
this.regWrite(path, key, values[key], type);
},
regDelete: function(path) {
try {
this.shell.regDelete(path);
} catch (e) {}
},
/**
* Gets information about the branch config in access
*
* @return {string} Branch name, master if cannot
*/
getBranch: function() {
var branch = this.mdbGetValue(
'SELECT branch FROM tblVariables',
'branch', String
);
return branch || Conf.defaultBranch;
request: function (method, url, data, cb) {
var remoteURL = this.regRead(Conf.regPath,'remoteURL');
if (!remoteURL)
remoteURL = Conf.defaultRemoteURL;
var fullUrl = remoteURL +'/api/'+ url;
var isGet = method == 'GET';
if (isGet) {
var isFirst = true;
for (var param in data) {
fullUrl += isFirst ? '?' : '&';
isFirst = false;
var value = data[param];
if (typeof value == 'object')
value = JSON.stringify(value);
fullUrl += param +'='+ encodeURIComponent(value);
}
}
var req = new ActiveXObject('MSXML2.XMLHTTP.6.0');
req.open(method, fullUrl, false);
req.onreadystatechange = function() {
App.onRequestStateChange(req, cb)
};
if (isGet) {
req.setRequestHeader('Content-Type', 'application/json');
req.send(JSON.stringify(data));
} else
req.send();
},
onRequestStateChange: function(req, cb) {
if (req.readyState !== 4)
return;
var status = req.status;
if (status >= 100 && status < 400) {
var res = JSON.parse(req.responseText);
cb(null, res);
} else {
err = new Error(req.statusText);
err.name = 'HttpError';
err.status = status;
err.req = req;
if (status >= 400 && status < 600)
err.error = JSON.parse(req.responseText);
cb(err);
}
},
/**
* Get the odbc path
*
* @return {string} Remote server
*/
getOdbcPath: function() {
return Conf.odbcPath + this.dsName;
},
enumValues: function(RegKey) {
var RootKey = new Object()
RootKey["HKCR"] = RootKey["HKEY_CLASSES_ROOT"] = 0x80000000;
RootKey["HKCU"] = RootKey["HKEY_CURRENT_USER"] = 0x80000001;
RootKey["HKLM"] = RootKey["HKEY_LOCAL_MACHINE"] = 0x80000002;
RootKey["HKUS"] = RootKey["HKEY_USERS"] = 0x80000003;
RootKey["HKCC"] = RootKey["HKEY_CURRENT_CONFIG"] = 0x80000005;
var RootVal = RootKey[RegKey.substr(0, RegKey.indexOf("\\"))]
if (RootVal != undefined) {
Locator = new ActiveXObject("WbemScripting.SWbemLocator");
ServerConn = Locator.ConnectServer(null, "root\\default");
Registry = ServerConn.Get("StdRegProv");
Method = Registry.Methods_.Item("enumValues");
p_In = Method.InParameters.SpawnInstance_();
p_In.hDefKey = RootVal;
p_In.sSubKeyName = RegKey.substr(RegKey.indexOf("\\") + 1)
p_Out = Registry.ExecMethod_(Method.Name, p_In);
return p_Out.sNames.toArray();
}
},
};
App.init();

View File

@ -1,13 +1,13 @@
body {
font-family: 'Poppins', 'Verdana', 'Sans';
font-size: 18px;
padding: .8em;
overflow: hidden;
color: #222;
font-family: Roboto;
}
a {
text-decoration: none;
color: #44f;
color: black;
}
/* Login form */
@ -15,8 +15,8 @@ a {
#logo {
display: block;
margin: 0 auto;
margin-bottom: 2.5em;
width: 80%;
margin-bottom: 4em;
width: 62%;
}
button,
input {
@ -28,21 +28,12 @@ select {
font-size: 1em;
background-color: #8d8d8d;
}
select.master {
background-color: #c20000;
}
select.test {
background-color: #31a527;
}
select.dev {
background-color: #a59827;
}
option {
color: white;
}
#fields {
max-width: 11em;
margin: 0 auto;
max-width: 13em;
margin-left: 3.32em;
}
#inputs > div {
margin-top: 1em;
@ -50,12 +41,8 @@ option {
#inputs > div > * {
display: block;
}
label {
font-weight: normal;
font-size: .9em;
}
#inputs label {
color: #666;
color: rgb(155, 155, 155);
font-size: .8em;
}
input[type='text'],
@ -67,24 +54,17 @@ input[type='password'] {
color: #333;
padding-top: .5em;
padding-bottom: .5em;
padding-left: .2em;
padding-left: .3em;
max-width: auto;
}
input[type='text']:focus,
input[type='password']:focus {
border-bottom: 1px solid black;
}
input[type='text']::selection,
input[type='password']::selection {
background-color: #97d700;
}
#rememberMe {
#notSignOutSection {
margin-top: 1em;
font-size: .9em;
}
#oldVersion {
margin-top: .5em;
font-size: .9em;
font-size: .8em;
margin-bottom: 2.5em;
}
#submit {
margin-top: 1em;
@ -95,57 +75,64 @@ input[type='password']::selection {
text-align: center;
}
#submit,
#clean {
#cleanDiv {
text-align: center;
}
#cleanDiv {
margin-top: 10px;
}
#clean:hover {
text-decoration: underline;
text-decoration-color: #44f;
}
button {
color: #FFF;
background-color: #f7931e;
padding: .7em;
padding-right: 2.5em;
padding-left: 2.5em;
background-color: black;
padding: 1em;
padding-right: 4.5em;
padding-left: 4.5em;
border: none;
border-radius: 25px;
font-size: .9em;
}
button:hover {
background-color: #eb8b1d;
background-color: #3d3f42;
cursor: pointer;
}
select {
color: white;
}
/* Branch */
#branchOptions {
margin-top: 1em;
margin-top: 2em;
}
#branchLogo {
cursor: pointer;
padding-top: .4em;
padding-bottom: .2em;
padding-left: .4em;
padding-right: .4em;
}
#branch {
border: none;
cursor: pointer;
margin-left: .4em;
float: right;
}
#branchSelector {
float: right;
margin-top: .7em;
width: 107px;
display: none;
padding-left: .3em;
padding-right: .8em;
max-width: 133px;
}
#branchButton {
float: left;
border-radius: 25px;
color: black;
box-shadow: 0px 0px 5px 0px #000000;
box-shadow: 0 0 .25em rgba(1,1,1,.6);
background-color: #8d8d8d;
}
#branchButton:hover {
@ -160,36 +147,106 @@ button:hover {
#branchButton.dev {
background-color: #a59827;
}
select.master {
background-color: #c20000;
}
select.test {
background-color: #31a527;
}
select.dev {
background-color: #a59827;
}
/* Datasource */
#datasourceOptions {
margin-top: 2em;
margin-left: 17.3em;
}
#datasourceLogo {
cursor: pointer;
padding-top: .4em;
padding-left: .4em;
padding-right: .4em;
}
#datasourceLogo.on {
cursor: pointer;
padding-top: .4em;
padding-left: .4em;
padding-right: .4em;
margin-left: 7em;
}
#datasource {
border: none;
cursor: pointer;
margin-right: 1.5em;
float: left;
}
#datasourceSelector {
float: right;
display: none;
padding-right: .8em;
margin-right: .5em;
margin-top: -1.91em;
max-width: 133px;
}
#datasourceButton {
float: right;
border-radius: 25px;
color: black;
box-shadow: 0 0 .25em rgba(1,1,1,.6);
background-color: #8d8d8d;
}
#datasourceButton:hover {
box-shadow: none;
}
#datasourceButton.production {
background-color: #c20000;
}
#datasourceButton.test {
background-color: #31a527;
}
#datasourceButton.dev {
background-color: #a59827;
}
select.production {
background-color: #c20000;
}
select.test {
background-color: #31a527;
}
select.dev {
background-color: #a59827;
}
/* Message */
#message {
z-index: 2;
position: absolute;
top: 2em;
left: 49.2%;
width: 16em;
top: 1.8em;
left: 11.8em;
width: 20em;
padding: .5em;
margin-left: -8.25em;
margin-top: 2em;
border: 1px solid #644;
background-color: #EBB;
color: #644;
text-align: center;
font-size: .9em;
font-size: .8em;
display: none;
border-radius: 25px;
box-shadow: 0px 0px 5px 0px #000000
border-radius: 5px;
box-shadow: 0 0 .4em rgba(1,1,1,.6);
}
#message.error {
border-color: black;
background-color: #a52727;
color: white;
background-color: #ffcdd2;
color: #bf0000;
}
#message.notice {
border-color: black;
background-color: #2773a5;
color: white;
background-color: #d0cdff;
color: #0d00bf;
;
}
@ -201,8 +258,8 @@ button:hover {
width: 100%;
height: 100%;
background-color: black;
opacity: 0.7;
filter: alpha(opacity=70);
opacity: .7;
filter: alpha(opacity=50);
top: 0;
left: 0;
display: none;
@ -214,7 +271,7 @@ button:hover {
width: 10em;
height: 5em;
margin-top: -4em;
margin-left: -5.9em;
margin-left: -6.1em;
top: 50%;
left: 50%;
background-color: white;

View File

@ -41,47 +41,43 @@
<input id="password" type="password"/>
</div>
</div>
<div id="rememberMe">
<input id="remember" type="checkbox"/>
<label for="remember">Recu&eacute;rdame</label>
</div>
<div id="oldVersion">
<input id="previous-version" type="checkbox"/>
<label for="previous-version">Usar versi&oacute;n anterior</label>
<div id="notSignOutSection">
<input id="notSignOut" type="checkbox"/>
<label for="notSignOut">No cerrar sesión</label>
</div>
</div>
<div id="submit">
<button
id="enter"
onclick="App.onEnterClick()">
Entrar
</button>
<button id="enter" onclick="App.onEnterClick()">Iniciar sesión</button>
</div>
<div id="clean">
<a
href="#"
onclick="App.onCleanCacheClick()">
Limpiar cach&eacute;
</a>
<div id="cleanDiv">
<a id="clean" href="#" onclick="App.onCleanCacheClick()">Limpiar caché</a>
</div>
<div id="branchOptions">
<div id="branchButton">
<img
id="branchLogo"
src="branch.png"
onclick="App.onShowOptionsClick()"
onclick="App.openOptions()"
alt="Change branch"/>
<div id="branchSelector">
<select id="branch" onchange="App.onChangeBranchChange()">
<option value="master">master</option>
<option value="test">test</option>
<option value="dev">dev</option>
<select id="branch" onchange="App.onChangeBranch()"></select>
</div>
</div>
</div>
<div id="datasourceOptions">
<div id="datasourceButton">
<img
id="datasourceLogo"
src="datasource.png"
onclick="App.openOptions()"
alt="Change datasource"/>
<div id="datasourceSelector">
<select id="datasource" onchange="App.onChangeDatasource(false)">
</select>
</div>
</div>
</div>
<div id="background">
</div>
<div id="background"></div>
<div id="spinner">
<img
alt="Cargando..."