Commit 235c02a2 by Boris Kocherov

[erp5_only_office] add xmla_client, partial use xmla_client for cubefunctions

1 parent e84b1df2
/*global window, rJS, RSVP, DocsAPI, console, document,
Common, require, jIO, URL, FileReader, atob, ArrayBuffer,
Uint8Array, XMLHttpRequest, Blob, Rusha, define,
Uint8ClampedArray,
Uint8ClampedArray, Asc, History,
TextDecoder, DesktopOfflineAppDocumentEndSave*/
/*jslint nomen: true, maxlen:80, indent:2*/
"use strict";
......@@ -52,6 +52,154 @@ DocsAPI.DocEditor.version = function () {
return new Blob([ab], {type: mimeString});
}
function printOlapTable(xmla_client, data) {
var Api = Asc.editor,
s = Api.GetActiveSheet(),
connection_name,
start_row,
start_column;
function endTransaction() {
s.worksheet.workbook.dependencyFormulas.unlockRecal();
History.EndTransaction();
Api._onUpdateAfterApplyChanges();
Api._onUpdateDocumentCanSave();
}
function setCell(row, col, value) {
// setValue on range
s.GetRangeByNumber(row, col).range._foreach(function (cell) {
cell.setValue(value);
});
}
function print_titles(levels, begin_row, begin_column, columns) {
var members = [],
member,
i,
m,
x,
z,
row,
col,
span,
repeats;
function amp_arr_length(amp, arr) {
if (arr.length === 0) {
return amp;
}
return amp * arr.length;
}
for (i = 0; i < levels.length; i += 1) {
members = levels[i];
span = levels.slice(i + 1).reduce(amp_arr_length, 1);
repeats = levels.slice(0, i).reduce(amp_arr_length, 1);
for (z = 0; z < repeats * members.length * span; z += (members.length * span)) {
for (m = 0; m < members.length; m += 1) {
member = members[m];
for (x = 0; x < span; x += 1) {
if (columns) {
row = begin_row + i;
col = begin_column + z + (m * span) + x;
} else {
row = begin_row + z + (m * span) + x;
col = begin_column + i;
}
setCell(row, col,
"=CUBEMEMBER(" + connection_name + ',"' + member.uname + '")');
}
}
}
}
return repeats * members.length * span;
}
return RSVP.Queue()
.push(function () {
// var active = s.GetActiveCell();
// var row = active.GetRow();
// var col = active.GetCol();
start_row = 0;
start_column = 0;
History.Create_NewPoint();
s.worksheet.workbook.dependencyFormulas.lockRecal();
// XXX use named ranges for cleaning space
s.worksheet.getRange3(0, 0, 100, 100).cleanAll();
// (new Asc.asc_CDefName(
// "name111",
// "Sheet1!$A$3:$D$13",
// null, // or number of sheet
// this.props.asc_getIsTable(),
// false, // Hidden
// false // locked
// ));
// rows titles
setCell(start_row, start_column, "Connection:");
setCell(start_row, start_column + 1, data.connection_name);
connection_name = "$B$1";
start_row += 2;
// XXX default absent in json schema
data.rows = data.rows || [];
data.columns = data.columns || [];
return RSVP.all([
RSVP.all(data.rows
.filter(function (i) {
return i.hasOwnProperty("level");
})
.map(function (i) {
return xmla_client
.getMembersOnLevel(data.connection_name, i.level);
})),
RSVP.all(data.columns
.filter(function (i) {
return i.hasOwnProperty("level");
})
.map(function (i) {
return xmla_client
.getMembersOnLevel(data.connection_name, i.level);
}))
]);
})
.push(function (arr) {
var rows = arr[0],
columns = arr[1],
c,
c_len,
r,
r_len;
r_len = print_titles(rows, start_row + columns.length, start_column, false);
c_len = print_titles(columns, start_row, start_column + rows.length, true);
r_len = r_len + start_row + columns.length;
c_len = c_len + start_column + rows.length;
for (r = start_row + columns.length; r < r_len; r += 1) {
for (c = start_column + rows.length; c < c_len; c += 1) {
setCell(r, c,
"=CUBEVALUE(" + connection_name + ',' +
s.worksheet.getRange3(r, start_column, r, start_column + rows.length -1).getName() +
',' +
s.worksheet.getRange3(start_row, c, start_row + columns.length - 1, c).getName() +
')');
}
}
endTransaction();
})
.push(undefined, function (error) {
endTransaction();
throw error;
});
}
rJS(window)
.ready(function (g) {
g.props = {
......@@ -167,13 +315,15 @@ DocsAPI.DocEditor.version = function () {
return queue;
})
.allowPublicAcquisition("notifyChange", function (arr, scope) {
var gadget = this;
var gadget = this,
content;
if (scope === "remote_settings") {
return this.getDeclaredGadget(scope)
.push(function (g) {
return g.getContent();
})
.push(function (data) {
content = data;
return gadget
.jio_putAttachment('/', 'remote_settings.json', data);
})
......@@ -183,6 +333,12 @@ DocsAPI.DocEditor.version = function () {
return gadget.changeState({changed: true});
})
.push(function () {
return gadget.getDeclaredGadget("xmla_client");
})
.push(function (g) {
return g.setConnectionsSettings(content);
})
.push(function () {
return gadget.getDeclaredGadget("xmlawizard");
})
.push(function (g) {
......@@ -195,10 +351,16 @@ DocsAPI.DocEditor.version = function () {
if (scope === "xmlawizard") {
return this.getDeclaredGadget(scope)
.push(function (g) {
return g.getContent();
return RSVP.all([
gadget.getDeclaredGadget("xmla_client"),
g.getContent()
]);
})
.push(function (data) {
console.log(JSON.stringify(data));
.push(function (arr) {
return printOlapTable(arr[0], arr[1]);
})
.push(function () {
return gadget.changeState({changed: true});
})
.push(undefined, function (e) {
console.error(e);
......@@ -431,7 +593,7 @@ DocsAPI.DocEditor.version = function () {
config[old_url] = [
new_url,
old_url
];
];
}
}
}
......@@ -494,6 +656,12 @@ DocsAPI.DocEditor.version = function () {
return loadScript(app_url);
})
.push(function () {
// declare public gadgets only after configure requirejs
// public because xmla_client return not serialized data
return g.declareGadget('onlyoffice/xmla_client.html',
{scope: 'xmla_client', sandbox: "public"});
})
.push(undefined, function (error) {
display_error(g, error);
});
......@@ -562,9 +730,8 @@ DocsAPI.DocEditor.version = function () {
.push(function (Editor_bin) {
if (Editor_bin) {
return zip.getAttachment('/', '/');
} else {
return new Blob();
}
return new Blob();
})
.push(function (zip_blob) {
return jIO.util.readBlobAsDataURL(zip_blob);
......
......@@ -68,6 +68,7 @@ function (window, RSVP, Xmla, console) {
function xmla_request(func, prop) {
var xmla = new Xmla({async: true});
prop = JSON.parse(JSON.stringify(prop));
// return function () {
return new RSVP.Queue()
.push(function () {
......@@ -85,30 +86,30 @@ function (window, RSVP, Xmla, console) {
function xmla_request_retry(func, settings) {
var queue,
urls = settings.urls,
urls = settings.urls || [""],
i;
function make_request(url) {
return function (error) {
settings.prop.url = url;
return xmla_request(func, settings.prop)
.push(undefined, function (response) {
// fix mondrian Internal and Sql errors
if (response) {
switch (response["code"]) {
case "SOAP-ENV:Server.00HSBE02":
case "SOAP-ENV:00UE001.Internal Error":
// rarely server error, so try again
return xmla_request(func, settings.prop);
}
}
throw response;
});
};
return xmla_request(func, settings.prop)
.push(undefined, function (response) {
// fix mondrian Internal and Sql errors
if (response) {
switch (response["code"]) {
case "SOAP-ENV:Server.00HSBE02":
case "SOAP-ENV:00UE001.Internal Error":
// rarely server error, so try again
return xmla_request(func, settings.prop);
}
}
throw response;
});
};
}
queue = make_request(urls[0])();
for (i = 1; i < settings.urls.length; i += 1) {
for (i = 1; i < urls.length; i += 1) {
queue.push(undefined, make_request(urls[i]));
}
return queue;
......@@ -415,85 +416,8 @@ function (window, RSVP, Xmla, console) {
return execution_scheme.execute.promise;
}
function discover_members(connection, opt) {
return getProperties(connection)
.push(function (settings) {
var prop = settings.prop,
cached_member,
scheme = getExecutionScheme(connection);
prop.restrictions = {
// 'CATALOG_NAME': 'FoodMart',
'CUBE_NAME': settings["cube"]
};
if (!opt) {
opt = {};
}
if (opt.member_uname) {
prop.restrictions["MEMBER_UNIQUE_NAME"] = opt.member_uname;
}
if (opt.level_uname) {
prop.restrictions["LEVEL_UNIQUE_NAME"] = opt.level_uname;
}
if (opt.tree_op) {
prop.restrictions["TREE_OP"] = opt.tree_op;
}
return xmla_request_retry("discoverMDMembers", settings)
.push(function (r) {
var ret = [],
uname,
level,
cached_member;
while (r.hasMoreRows()) {
uname = r["getMemberUniqueName"]();
level = r["getLevelUniqueName"]();
// we can check cache twice because fist check
// only if discover by member_uname
if (!scheme.members.hasOwnProperty(uname)) {
cached_member = {
uname: uname,
h: r["getHierarchyUniqueName"](),
level: r["getLevelUniqueName"](),
caption: r["getMemberCaption"](),
type: r["getMemberType"]()
};
scheme.members[uname] = cached_member;
} else {
cached_member = scheme.members[uname];
}
ret.push(cached_member);
r.nextRow();
if (!scheme.levels.hasOwnProperty(level)) {
scheme.levels[level] = discover_level(connection, scheme, level);
}
}
return ret;
});
});
}
function discover_level(connection, scheme, level) {
return discover_members(connection, {
level_uname: level
})
.push(function (members) {
var i;
function compare(a, b) {
if (a.uname < b.uname) {
return -1;
}
if (a.uname > b.uname) {
return 1;
}
return 0;
}
members.sort(compare);
for (i = 0; i < members.length; i += 1) {
members[i].level_index = i;
}
scheme.levels[level] = members;
});
function getXmlaClient() {
return Common.Gateway.getDeclaredGadget("xmla_client");
}
function discover_members_for_arguments(connection, members) {
......@@ -511,16 +435,14 @@ function (window, RSVP, Xmla, console) {
if (member) {
promises
.push(
discover_members(connection, {
member_uname: member,
tree_op: 8
})
.push(function (members) {
var m;
if (members.length > 0) {
m = members[0];
check_interseption(m.h);
return m;
getXmlaClient()
.push(function (xmla_client) {
return xmla_client.getMember(connection, member);
})
.push(function (member) {
if (member) {
check_interseption(member.h);
return member;
} else {
throw "member not found";
}
......@@ -577,7 +499,7 @@ function (window, RSVP, Xmla, console) {
caption;
return queue
.push(function (arg) {
connection = getCell(arg[0]);
connection = getCell(arg[0]).toString();
caption = getCell(arg[2]);
if (caption) {
caption = caption.getValue();
......@@ -603,26 +525,21 @@ function (window, RSVP, Xmla, console) {
.push(undefined, error_handler(current_cell_id));
};
cCUBEMEMBER.prototype.changeOffsetElem = function (arg, offset) {
var connection = getCell(arg[0]),
scheme = getExecutionScheme(connection),
i,
elem,
member,
new_member,
level;
for (i = 0; i < arg.length; i += 1) {
elem = arg[i];
var connection_name = getCell(arg[0]).toString();
return RSVP.all(arg.slice(1).map(function (elem) {
if (cElementType.string === elem.type) {
member = scheme.members[elem.value];
if (member && (member.level_index >= 0)) {
level = scheme.levels[member.level];
new_member = level[member.level_index + offset.offsetCol + offset.offsetRow];
if (new_member) {
elem.value = new_member.uname;
}
}
return getXmlaClient()
.push(function (xmla_client) {
return xmla_client
.getMemberWithOffset(connection_name, elem.value, offset.offsetCol + offset.offsetRow);
})
.push(function (member) {
if (member) {
elem.value = member.uname;
}
});
}
}
}));
};
cCUBEMEMBER.prototype.getInfo = function () {
return {
......@@ -695,7 +612,7 @@ function (window, RSVP, Xmla, console) {
waiter = AddCubeValueCalculate(current_cell_id);
return queue
.push(function (arg) {
connection = getCell(arg[0]);
connection = getCell(arg[0]).toString();
scheme = getExecutionScheme(connection);
return parseArgs(arg.slice(1))();
})
......
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>XMLA Client</title>
<script type="text/javascript" src="../rsvp.js" ></script>
<script type="text/javascript" src="../renderjs.js"></script>
<script type="text/javascript" src="web-apps/vendor/xmla4js/Xmla-compiled.js"></script>
<script type="text/javascript" src="xmla_client.js"></script>
</head>
<body>
</body>
</html>
\ No newline at end of file
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="File" module="OFS.Image"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>_Cacheable__manager_id</string> </key>
<value> <string>http_cache</string> </value>
</item>
<item>
<key> <string>__name__</string> </key>
<value> <string>xmla_client.html</string> </value>
</item>
<item>
<key> <string>content_type</string> </key>
<value> <string>text/html</string> </value>
</item>
<item>
<key> <string>precondition</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>title</string> </key>
<value> <string></string> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
/*jslint nomen: true, maxlen: 200, indent: 2*/
/*global rJS, console, window, document, RSVP, Xmla*/
(function (window, rJS) {
"use strict";
function xmla_request(func, prop) {
var xmla = new Xmla({async: true});
prop = JSON.parse(JSON.stringify(prop));
// return function () {
return new RSVP.Queue()
.push(function () {
return new RSVP.Promise(function (resolve, reject) {
prop.success = function (xmla, options, response) {
resolve(response);
};
prop.error = function (xmla, options, response) {
reject(response);
};
xmla[func](prop);
});
});
}
function xmla_request_retry(func, settings) {
var queue,
urls = settings.urls || [""],
i;
function make_request(url) {
return function (error) {
settings.prop.url = url;
return xmla_request(func, settings.prop)
.push(undefined, function (response) {
// fix mondrian Internal and Sql errors
if (response) {
switch (response["code"]) {
case "SOAP-ENV:Server.00HSBE02":
case "SOAP-ENV:00UE001.Internal Error":
// rarely server error, so try again
return xmla_request(func, settings.prop);
}
}
throw response;
});
};
}
queue = make_request(urls[0])();
for (i = 1; i < urls.length; i += 1) {
queue.push(undefined, make_request(urls[i]));
}
return queue;
}
function discoverDimensions(schema, used_dimensions, opt) {
return xmla_request_retry("discoverMDDimensions", opt)
.push(undefined, function (error) {
console.log(error);
})
.push(function (response) {
var arr = [],
row;
if (response && response.numRows > 0) {
while (response.hasMoreRows()) {
row = response.readAsObject();
if (row["DIMENSION_TYPE"] !== 2) {
if (used_dimensions.indexOf(row["DIMENSION_UNIQUE_NAME"]) < 0) {
arr.push({
const: row["DIMENSION_UNIQUE_NAME"] || undefined,
title: row["DIMENSION_NAME"] || undefined
});
}
}
response.nextRow();
}
}
if (arr.length !== 0) {
schema.properties.dimension = {
title: " ",
oneOf: arr
};
}
});
}
function discoverHierarchies(schema, opt) {
return xmla_request_retry("discoverMDHierarchies", opt)
.push(undefined, function (error) {
console.log(error);
})
.push(function (response) {
var arr = [],
row;
if (response && response.numRows > 0) {
while (response.hasMoreRows()) {
row = response.readAsObject();
arr.push({
const: row["HIERARCHY_UNIQUE_NAME"] || undefined,
title: row["HIERARCHY_NAME"] || undefined
});
response.nextRow();
}
}
if (arr.length !== 0) {
schema.properties.hierarchy = {
title: " ",
oneOf: arr
};
}
});
}
function discoverLevels(schema, opt) {
return xmla_request_retry("discoverMDLevels", opt)
.push(undefined, function (error) {
console.log(error);
})
.push(function (response) {
var arr = [],
row;
if (response && response.numRows > 0) {
while (response.hasMoreRows()) {
row = response.readAsObject();
arr.push({
const: row["LEVEL_UNIQUE_NAME"] || undefined,
title: row["LEVEL_NAME"] || undefined
});
response.nextRow();
}
}
if (arr.length !== 0) {
schema.properties.level = {
title: " ",
oneOf: arr
};
}
});
}
rJS(window)
.ready(function () {
var g = this;
console.log("xmla_client");
g.props = {
cache: {},
connections: {}
};
return g.getRemoteSettings()
.push(function (settings) {
return g.setConnectionsSettings(settings);
})
})
.declareAcquiredMethod("getRemoteSettings", "getRemoteSettings")
.declareMethod("getConnectionSettings", function (name) {
return this.props.connections[name];
})
.declareMethod("setConnectionsSettings", function (connections) {
var key,
new_state = {};
for (key in connections) {
if (connections.hasOwnProperty(key) && connections[key]) {
new_state[key] = JSON.stringify(connections[key]);
}
}
for (key in this.state) {
if (this.state.hasOwnProperty(key) && !connections[key]) {
new_state[key] = null;
}
}
return this.changeState(new_state);
})
.onStateChange(function (m_dict) {
var g = this,
key;
for (key in m_dict) {
if (m_dict.hasOwnProperty(key)) {
delete g.props.cache[key];
delete g.props.connections[key];
if (m_dict[key] !== null) {
g.props.cache[key] = {
members: {},
levels: {}
};
g.props.connections[key] = JSON.parse(m_dict[key]);
}
}
}
})
.declareMethod("request", function (function_name, settings, connection_name) {
var queue;
if (connection_name) {
queue = this.getConnectionSettings(connection_name);
} else {
queue = RSVP.Queue();
}
return queue
.push(function (connection_settings) {
if (!settings) {
settings = {};
}
if (connection_settings) {
settings.urls = connection_settings.urls;
settings.prop.restrictions.CATALOG_NAME = connection_settings.properties.Catalog;
settings.prop.restrictions.CUBE_NAME = connection_settings.properties.Cube;
}
return xmla_request_retry(function_name, settings);
})
.push(undefined, function (error) {
console.error(error);
});
})
.declareMethod("getMembersOnLevel", function (connection_name, level_uname) {
var g = this,
cache = g.props.cache[connection_name];
if (cache.levels.hasOwnProperty(level_uname)) {
return cache.levels[level_uname];
}
return g.request("discoverMDMembers", {
prop: {
restrictions: {
LEVEL_UNIQUE_NAME: level_uname
}
}
}, connection_name)
.push(function (r) {
var uname,
member,
i,
level = [];
while (r.hasMoreRows()) {
uname = r["getMemberUniqueName"]();
if (level_uname !== r["getLevelUniqueName"]()) {
throw "xmla server fail";
}
member = {
uname: uname,