/**
* Интерфейс к localstorage, alasql и pouchdb
*
* © Evgeniy Malyarov http://www.oknosoft.ru 2014-2016
*
* @module common
* @submodule wsql
*/
/**
* ### Интерфейс к localstorage, alasql и pouchdb
* - Обеспечивает взаимодействие с локальными и серверными данными
* - Обслуживает локальные параметры пользователя
*
* @class WSQL
* @static
* @menuorder 33
* @tooltip Данные localstorage
*/
function WSQL(){
var wsql = this,
ls,
user_params = {};
this.__define({
/**
* ### Поправка времени javascript
* @property js_time_diff
* @type Number
*/
js_time_diff: {
value: -(new Date("0001-01-01")).valueOf()
},
/**
* ### Поправка времени javascript с учетом пользовательского сдвига из константы _time_diff_
* @property time_diff
* @type Number
*/
time_diff: {
get: function () {
var diff = this.get_user_param("time_diff", "number");
return (!diff || isNaN(diff) || diff < 62135571600000 || diff > 62135622000000) ? this.js_time_diff : diff;
}
},
/**
* ### Устанавливает параметр в user_params и localStorage
*
* @method set_user_param
* @param prm_name {string} - имя параметра
* @param prm_value {string|number|object|boolean} - значение
* @async
*/
set_user_param: {
value: function(prm_name, prm_value){
var str_prm = prm_value;
if(typeof prm_value == "object")
str_prm = JSON.stringify(prm_value);
else if(prm_value === false)
str_prm = "";
ls.setItem($p.job_prm.local_storage_prefix+prm_name, str_prm);
user_params[prm_name] = prm_value;
}
},
/**
* ### Возвращает значение сохраненного параметра из localStorage
* Параметр извлекается с приведением типа
*
* @method get_user_param
* @param prm_name {String} - имя параметра
* @param [type] {String} - имя типа параметра. Если указано, выполняем приведение типов
* @return {*} - значение параметра
*/
get_user_param: {
value: function(prm_name, type){
if(!user_params.hasOwnProperty(prm_name) && ls)
user_params[prm_name] = this.fetch_type(ls.getItem($p.job_prm.local_storage_prefix+prm_name), type);
return user_params[prm_name];
}
},
/**
* ### Выполняет sql запрос к локальной базе данных
*
* @method promise
* @param sql
* @param params
* @return {Promise}
* @async
*/
promise: {
value: function(sql, params) {
return new Promise(function(resolve, reject){
wsql.alasql(sql, params || [], function(data, err) {
if(err) {
reject(err);
} else {
resolve(data);
}
});
});
}
},
/**
* ### Сохраняет настройки формы или иные параметры объекта _options_
* @method save_options
* @param prefix {String} - имя области
* @param options {Object} - сохраняемые параметры
* @return {Promise}
* @async
*/
save_options: {
value: function(prefix, options){
return wsql.set_user_param(prefix + "_" + options.name, options);
}
},
/**
* ### Восстанавливает сохраненные параметры в объект _options_
* @method restore_options
* @param prefix {String} - имя области
* @param options {Object} - объект, в который будут записаны параметры
*/
restore_options: {
value: function(prefix, options){
var options_saved = wsql.get_user_param(prefix + "_" + options.name, "object");
for(var i in options_saved){
if(typeof options_saved[i] != "object")
options[i] = options_saved[i];
else{
if(!options[i])
options[i] = {};
for(var j in options_saved[i])
options[i][j] = options_saved[i][j];
}
}
return options;
}
},
/**
* ### Приведение типов при операциях с `localStorage`
* @method fetch_type
* @param prm
* @param type
* @returns {*}
*/
fetch_type: {
value: function(prm, type){
if(type == "object"){
try{
prm = JSON.parse(prm);
}catch(e){
prm = {};
}
return prm;
}else if(type == "number")
return $p.utils.fix_number(prm, true);
else if(type == "date")
return $p.utils.fix_date(prm, true);
else if(type == "boolean")
return $p.utils.fix_boolean(prm);
else
return prm;
}
},
/**
* ### Указатель на alasql
* @property alasql
* @type Function
*/
alasql: {
value: typeof alasql != "undefined" ? alasql : require("alasql")
},
/**
* ### Создаёт и заполняет умолчаниями таблицу параметров
*
* @method init_params
* @return {Promise}
* @async
*/
init_params: {
value: function(){
// префикс параметров LocalStorage
// TODO: отразить в документации, что если префикс пустой, то параметры не инициализируются
if(!$p.job_prm.local_storage_prefix && !$p.job_prm.create_tables)
return Promise.resolve();
if(typeof localStorage === "undefined"){
// локальное хранилище внутри node.js
if(typeof WorkerGlobalScope === "undefined"){
ls = new require('node-localstorage').LocalStorage('./localstorage');
}else{
ls = {
setItem: function (name, value) {
},
getItem: function (name) {
}
};
}
} else
ls = localStorage;
// значения базовых параметров по умолчанию
var nesessery_params = [
{p: "user_name", v: "", t:"string"},
{p: "user_pwd", v: "", t:"string"},
{p: "browser_uid", v: $p.utils.generate_guid(), t:"string"},
{p: "zone", v: $p.job_prm.hasOwnProperty("zone") ? $p.job_prm.zone : 1, t: $p.job_prm.zone_is_string ? "string" : "number"},
{p: "enable_save_pwd", v: $p.job_prm.enable_save_pwd, t:"boolean"},
{p: "autologin", v: "", t:"boolean"},
{p: "skin", v: "dhx_web", t:"string"},
{p: "rest_path", v: "", t:"string"}
], zone;
// подмешиваем к базовым параметрам настройки приложения
if($p.job_prm.additional_params)
nesessery_params = nesessery_params.concat($p.job_prm.additional_params);
// если зона не указана, устанавливаем "1"
if(!ls.getItem($p.job_prm.local_storage_prefix+"zone"))
zone = $p.job_prm.hasOwnProperty("zone") ? $p.job_prm.zone : 1;
// если зона указана в url, используем её
if($p.job_prm.url_prm.hasOwnProperty("zone"))
zone = $p.job_prm.zone_is_string ? $p.job_prm.url_prm.zone : $p.utils.fix_number($p.job_prm.url_prm.zone, true);
if(zone !== undefined)
wsql.set_user_param("zone", zone);
// дополняем хранилище недостающими параметрами
nesessery_params.forEach(function(o){
if(wsql.get_user_param(o.p, o.t) == undefined ||
(!wsql.get_user_param(o.p, o.t) && (o.p.indexOf("url") != -1)))
wsql.set_user_param(o.p, $p.job_prm.hasOwnProperty(o.p) ? $p.job_prm[o.p] : o.v);
});
// сообщяем движку pouch пути и префиксы
var pouch_prm = {
path: wsql.get_user_param("couch_path", "string") || $p.job_prm.couch_path || "",
zone: wsql.get_user_param("zone", "number"),
prefix: $p.job_prm.local_storage_prefix,
suffix: wsql.get_user_param("couch_suffix", "string") || ""
};
if(pouch_prm.path){
/**
* ### Указатель на локальные и сетевые базы PouchDB
* @property pouch
* @for WSQL
* @type Pouch
*/
wsql.__define("pouch", { value: new Pouch() });
wsql.pouch.init(pouch_prm);
}
// создаём таблицы alasql
if(this.create_tables){
this.alasq(this.create_tables, []);
this.create_tables = "";
}
}
},
/**
* ### Удаляет таблицы WSQL
* Например, для последующего пересоздания при изменении структуры данных
* @method drop_tables
* @param callback {Function}
* @async
*/
drop_tables: {
value: function(callback){
var cstep = 0, tmames = [];
function ccallback(){
cstep--;
if(cstep<=0)
setTimeout(callback, 10);
else
iteration();
}
function iteration(){
var tname = tmames[cstep-1]["tableid"];
if(tname.substr(0, 1) == "_")
ccallback();
else
wsql.alasql("drop table IF EXISTS " + tname, [], ccallback);
}
function tmames_finded(data){
tmames = data;
if(cstep = data.length)
iteration();
else
ccallback();
}
wsql.alasql("SHOW TABLES", [], tmames_finded);
}
}
});
/**
* ### Указатель на aladb
* @property aladb
* @type alasql.Database
*/
this.__define({
aladb: {
value: new this.alasql.Database('md')
}
});
}