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

102
setup.iss
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
; 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;
@ -255,10 +273,10 @@ begin
begin
MsgBox(CurrentFilename +' installation failed with code: ' + IntToStr(ResultCode) + '.',
mbError, MB_OK);
WizardForm.Close;
WizardForm.Close;
end;
finally
WizardForm.StatusLabel.Caption := StatusText;
WizardForm.ProgressGauge.Style := npbstNormal;
end;
end;
end;

BIN
src/datasource.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 893 B

View File

@ -1,148 +1,184 @@
// 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 user name":
"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é"
"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, 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é"
}
};
var App = {
shell: new ActiveXObject('WScript.Shell'),
fso: new ActiveXObject('scripting.filesystemobject'),
init: function() {
var width = 420;
var height = 525;
init: function() {
// Specify the size of window
var width = 420;
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);
// 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, {
'Confirm Document Deletions' : false,
'Confirm Action Queries' : false,
'Confirm Record Changes' : false
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, 'configured', Conf.version);
this.regWrite(Conf.regPath, 'remoteURL', Conf.defaultRemoteURL);
this.regWrite(Conf.regPath, 'lastExecutedVersion', 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 user = this.regRead(Conf.dsPath, 'UID');
var password = this.regRead(Conf.dsPath, 'PWD');
var remember = this.regRead(Conf.regPath, 'remember');
this.$('branch').value = this.getBranch();
this.onChangeBranchChange();
var notSignOut = this.regRead(Conf.regPath, 'notSignOut');
if (user)
this.$('user').value = user;
// 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();
if (remember && password) {
this.$('password').value = password;
this.$('remember').checked = true;
// 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 (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,51 +336,58 @@ 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 === '')
throw new Error(_('Enter a user name'));
if (!password || 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);
if (!user)
throw new Error(_('Enter a username'));
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();
var password = this.$('password').value;
if (!password)
throw new Error(_('Enter a password'));
this.regWrite(this.getOdbcPath(), 'UID', user);
this.regWrite(this.getOdbcPath(), 'PWD', password);
var mysqlConn = new ActiveXObject('ADODB.Connection');
// Check credentials
try {
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;
err = new Error(_('Bad login'));
err.name = 'BadLogin';
break;
case 2003: // Can't connect
err = new Error(_('Server can\'t be reached'));
break;
default:
err = new Error(dbError.description);
}
dbErrors.clear();
}
throw err;
}
mysqlConn.close();
// Check the cretentials and return the last version number
this.fetchVersion();
} catch (err) {
this.catchError(err);
}
},
/**
* Gets information about the version to download.
* cmdle
@ -283,99 +395,81 @@ var App = {
* 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');;
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
}));
} 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;
err = new Error(_('Bad login'));
err.name = 'BadLogin';
break;
case 2003: // Can't connect
err = new Error(_('Server can\'t be reached'));
break;
default:
err = new Error(dbError.description);
}
dbErrors.clear();
// 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 +': ');
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;
var lastVersion;
// Checks if it's already open
if (this.fso.fileExists(this.lockFile))
try {
this.fso.deleteFile(this.lockFile);
return version;
} catch (e) {
throw new Error(_('Application it\'s already open'));
try {
this.fso.deleteFile(this.lockFile);
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
var file = this.fso.getFile(this.mdbFile);
if (file.size > Conf.maxCorruptSize * 1024 * 1024)
return version;
if (!lastVersion) {
var file = this.fso.getFile(this.mdbFile);
if (file.size > Conf.maxCorruptSize * 1024 * 1024)
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;
// Obtains the local version number from the MDB file
var localVersion = this.mdbGetValue(
'SELECT Version FROM tblVariables',
'Version', parseInt
);
if (!localVersion)
localVersion = false;
// Determines if should download
return !localVersion || version === false || localVersion != version
? version
: null;
// Determines if should download
!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,28 +487,26 @@ 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);
var stream = new ActiveXObject('ADODB.Stream');
stream.open();
stream.Type = 1; //adTypeBinary
stream.Type = 1; // adTypeBinary
stream.write(request.responseBody);
stream.Position = 0;
stream.saveToFile(this.compressFile, 2);
@ -438,32 +530,33 @@ 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';
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);
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) {}
},
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);
}
},
/**
* Gets information about the branch config in access
* Get the odbc path
*
* @return {string} Branch name, master if cannot
* @return {string} Remote server
*/
getBranch: function() {
var branch = this.mdbGetValue(
'SELECT branch FROM tblVariables',
'branch', String
);
return branch || Conf.defaultBranch;
}
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();
@ -581,4 +735,4 @@ App.init();
function _(string) {
var translation = Locale[Conf.defaultLocale][string];
return translation ? translation : string;
}
}

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;
@ -233,4 +290,4 @@ button:hover {
}
#loading-message {
font-size: .9em;
}
}

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..."