Commit 6787022e authored by Boris Kocherov's avatar Boris Kocherov Committed by Romain Courteaud

[erp5_only_office] initial add olap_wizard

parent dd532779
......@@ -187,6 +187,9 @@ DocsAPI.DocEditor.version = function () {
});
}
})
.allowPublicAcquisition("getRemoteSettings", function () {
return this.jio_getAttachment('/', 'remote_settings.json', {format: 'json'});
})
// methods emulating Gateway used for connection with ooffice begin.
.declareMethod('appReady', function () {
......
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>OLAP Query editor</title>
<link rel="stylesheet" href="../gadget_erp5_nojqm.css">
<script src="../rsvp.js"></script>
<script src="../renderjs.js"></script>
<script src="../jio.js"></script>
<script src="web-apps/vendor/xmla4js/Xmla-compiled.js"></script>
<script src="olap_wizard.js"></script>
</head>
<body>
<div data-role="page">
<div role="main" class="ui-content gadget-content">
<div data-gadget-url="../jsonform.gadget.html"
data-gadget-scope="olap_wizard"
data-gadget-sandbox="public"></div>
</div>
</div>
</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>olap_wizard.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 getCurrentConnectionSettings(g, gadget) {
var connections;
return RSVP.Queue()
.push(function () {
return g.getRemoteSettings();
})
.push(function (c) {
connections = c;
return gadget.getContent("/connection_name");
})
.push(function (connection_name) {
return connections[connection_name];
})
.push(undefined, function (err) {
console.error(err);
});
}
function get_used_dimensions(g) {
var q;
if (g.props.init_value) {
q = RSVP.Queue()
.push(function () {
return g.props.init_value;
});
} else {
q = g.getDeclaredGadget("olap_wizard")
.push(function (gadget) {
return gadget.getContent();
});
}
return q
.push(function (v) {
var dimensions = [],
key,
dimension;
if (v) {
if (v.columns) {
for (key in v.columns) {
if (v.columns.hasOwnProperty(key)) {
dimension = v.columns[key].dimension;
if (dimension) {
dimensions.push(dimension);
}
}
}
}
if (v.rows) {
for (key in v.rows) {
if (v.rows.hasOwnProperty(key)) {
dimension = v.rows[key].dimension;
if (dimension) {
dimensions.push(dimension);
}
}
}
}
}
return dimensions;
});
}
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 < settings.urls.length; i += 1) {
queue.push(undefined, make_request(urls[i]));
}
return queue;
}
function print_content(gadget) {
return gadget.getDeclaredGadget("olap_wizard")
.push(function (g) {
return g.getContent();
})
.push(function (v) {
console.log(JSON.stringify(v));
});
}
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
};
}
});
}
function generateChoiceSchema(connection_settings, used_dimensions, choice_settings) {
var schema = {
"type": "object",
"additionalProperties": false,
"properties": {}
},
current_dimension;
if (!connection_settings) {
return new RSVP.Queue()
.push(function () {
return schema;
});
}
if (!connection_settings.hasOwnProperty('properties')) {
connection_settings.properties = {};
}
if (!choice_settings) {
choice_settings = {};
}
current_dimension = choice_settings.dimension;
if (current_dimension) {
used_dimensions = used_dimensions
.filter(function (d) {
return d !== current_dimension;
});
}
return new RSVP.Queue()
.push(function () {
var tasks = [discoverDimensions(schema, used_dimensions, {
urls: connection_settings.urls,
prop: {
restrictions: {
CATALOG_NAME: connection_settings.properties.Catalog,
CUBE_NAME: connection_settings.properties.Cube
}
}
})];
if (choice_settings.dimension) {
tasks.push(
discoverHierarchies(schema, {
urls: connection_settings.urls,
prop: {
restrictions: {
CATALOG_NAME: connection_settings.properties.Catalog,
CUBE_NAME: connection_settings.properties.Cube,
DIMENSION_UNIQUE_NAME: choice_settings.dimension
}
}
})
);
}
if (choice_settings.hierarchy) {
tasks.push(discoverLevels(schema, {
urls: connection_settings.urls,
prop: {
restrictions: {
CATALOG_NAME: connection_settings.properties.Catalog,
CUBE_NAME: connection_settings.properties.Cube,
DIMENSION_UNIQUE_NAME: choice_settings.dimension,
HIERARCHY_UNIQUE_NAME: choice_settings.hierarchy
}
}
}));
}
return RSVP.all(tasks);
})
.push(function () {
return schema;
});
}
function decodeJsonPointer(_str) {
// https://tools.ietf.org/html/rfc6901#section-5
return _str.replace(/~1/g, '/').replace(/~0/g, '~');
}
function convertOnMultiLevel(d, key, value) {
var ii,
kk,
prev_value,
key_list = key.split("/");
for (ii = 1; ii < key_list.length; ii += 1) {
kk = decodeJsonPointer(key_list[ii]);
if (ii === key_list.length - 1) {
if (value !== undefined) {
prev_value = d[kk];
d[kk] = value[0];
return prev_value;
}
return d[kk];
}
if (!d.hasOwnProperty(kk)) {
if (value !== undefined) {
d[kk] = {};
} else {
return;
}
}
d = d[kk];
}
}
rJS(window)
.ready(function (g) {
g.props = {};
g.props.choices = [];
return g.render({
schema_url: new URL("olap_wizard.json", window.location).toString(),
value: {}
});
})
.declareAcquiredMethod("getRemoteSettings", "getRemoteSettings")
.allowPublicAcquisition("notifyValid", function (arr, scope) {
})
.allowPublicAcquisition("notifyInvalid", function (arr, scope) {
})
.declareMethod("render", function (opt) {
var g = this;
if (!opt) {
opt = {};
}
g.props.init_value = opt.value;
return get_used_dimensions(g)
.push(function (v) {
g.props.used_dimensions = v;
return g.getDeclaredGadget("olap_wizard");
})
.push(function (gadget) {
return gadget.render(opt);
})
.push(function () {
delete g.props.init_value;
delete g.props.used_dimensions;
});
})
.declareMethod("getContent", function (path) {
return this.getDeclaredGadget("olap_wizard")
.push(function (g) {
return g.getContent(path);
});
})
.declareAcquiredMethod("notifyChange", "notifyChange")
.allowPublicAcquisition("notifyChange", function (arr, s) {
var g = this,
scope = arr[0].scope,
relPath = arr[0].rel_path,
action = arr[0].action,
used_diemensions,
url = arr[0].ref,
allRerender,
y;
function rerender(sub_scope) {
var queue,
gadget_settings;
if (!used_diemensions) {
queue = get_used_dimensions(g)
.push(function (v) {
used_diemensions = v;
});
} else {
queue = RSVP.Queue();
}
function rerender_once(connection_settings, sub_gadget) {
return sub_gadget.getContent()
.push(function (content) {
console.log(content);
return generateChoiceSchema(connection_settings, used_diemensions, content);
})
.push(function (schema) {
return gadget_settings.rerender({
scope: sub_scope,
schema: schema,
ignore_incorrect: true
});
});
}
queue
.push(function () {
return g.getDeclaredGadget("olap_wizard");
})
.push(function (gadget) {
gadget_settings = gadget;
return RSVP.all([
getCurrentConnectionSettings(g, gadget),
gadget.getSubGadget(sub_scope)
]);
})
.push(function (arr) {
var connection_settings = arr[0],
sub_gadget = arr[1];
return rerender_once(connection_settings, sub_gadget)
.push(function (changed) {
if (changed.length > 0) {
if (changed.indexOf('/dimension') >= 0) {
return allRerender();
}
return rerender_once(connection_settings, sub_gadget);
}
})
.push(function (changed) {
if (changed.length > 0) {
return rerender_once(connection_settings, sub_gadget);
}
});
})
.push(function () {
// return g.notifyChange();
return print_content(g);
});
}
allRerender = function () {
return get_used_dimensions(g)
.push(function (v) {
used_diemensions = v;
return RSVP.all(g.props.choices.map(function (q) {
return rerender(q);
}));
})
.push(function () {
return [];
});
};
if ("urn:jio:remote_connections.json" === url) {
return allRerender();
}
if (action === "render") {
if ("urn:jio:choice.json" === url) {
g.props.choices.push(scope);
}
// action `render` fake change so do nothing
return;
}
for (y = 0; y < g.props.choices.length; y += 1) {
s = g.props.choices[y];
if (scope.startsWith(s)) {
if (action === "delete") {
g.props.choices.splice(y, 1);
return allRerender();
}
if (relPath === "/dimension") {
return allRerender();
}
return rerender(s);
}
}
// return g.notifyChange();
return print_content(g);
})
.allowPublicAcquisition("resolveExternalReference", function (arr) {
var g = this,
url = arr[0],
schema_path = arr[1],
path = arr[2];
if ("urn:jio:remote_connections.json" === url) {
return new RSVP.Queue()
.push(function () {
return g.getRemoteSettings();
})
.push(function (connections) {
var key,
schema = {
enum: []
};
for (key in connections) {
if (connections.hasOwnProperty(key)) {
schema.enum.push(key);
}
}
return schema;
});
}
if ("urn:jio:choice.json" === url) {
return new RSVP.Queue()
.push(function () {
return g.getRemoteSettings();
})
.push(function (connections) {
var connection_settings,
choice_settings;
if (g.props.init_value) {
connection_settings =
connections[convertOnMultiLevel(g.props.init_value, "/connection_name")];
if (path !== "/columns/" && path !== "/rows/") {
choice_settings = convertOnMultiLevel(g.props.init_value, path);
}
return generateChoiceSchema(connection_settings, g.props.used_dimensions, choice_settings);
}
return {};
});
}
throw new Error("urn: '" + url + "' not supported");
});
}(window, rJS));
\ 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>olap_wizard.js</string> </value>
</item>
<item>
<key> <string>content_type</string> </key>
<value> <string>text/javascript</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>
{
"$schema": "http://json-schema.org/draft-07/schema",
"title": "OLAP Query parameters",
"type": "object",
"definitions": {
"choice": {
"type": "array",
"uniqueItems": true,
"items": {
"$ref": "urn:jio:choice.json"
}
}
},
"properties": {
"connection_name": {
"$ref": "urn:jio:remote_connections.json"
},
"columns": {
"title": "columns",
"$ref": "#/definitions/choice"
},
"rows": {
"title": "rows",
"$ref": "#/definitions/choice"
}
},
"additionalProperties": false
}
\ 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>olap_wizard.json</string> </value>
</item>
<item>
<key> <string>content_type</string> </key>
<value> <string>application/json</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>
/**
* User: Julia.Radzhabova
* Date: 17.05.16
* Time: 15:38
*/
if (Common === undefined)
var Common = {};
Common.Views = Common.Views || {};
define([
'common/main/lib/util/utils',
'common/main/lib/component/BaseView',
'common/main/lib/component/Layout',
'common/main/lib/component/Window'
], function (template) {
'use strict';
Common.Views.RenderJSPanel = Common.UI.BaseView.extend(_.extend({
initialize: function (options) {
_.extend(this, options);
Common.UI.BaseView.prototype.initialize.call(this, arguments);
},
render: function () {
var me = this,
element = me.$el[0],
q = RSVP.Queue();
if (!me.gadget) {
q = Common.Gateway.declareGadget(this.gadget_url, {
scope: this.scope,
element: element,
sandbox: "iframe"
})
.push(function (sub_gadget) {
me.gadget = sub_gadget;
var iframe = sub_gadget.element.querySelector("iframe");
iframe.width = '100%';
iframe.height = (Common.Utils.innerHeight() - 80) + 'px';
iframe.setAttribute("frameBorder", "0");
});
} else {
q = RSVP.Queue();
}
return q.push(function () {
return me.gadget.render(me.gadget_render_opt);
})
.push(function () {
return me;
})
.push(undefined, function (e) {
console.error(e);
});
},
show: function () {
Common.UI.BaseView.prototype.show.call(this,arguments);
this.fireEvent('show', this );
},
hide: function () {
Common.UI.BaseView.prototype.hide.call(this,arguments);
this.fireEvent('hide', this );
}
}, Common.Views.RenderJSPanel || {}));
});
\ 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>RenderJSPanel.js</string> </value>
</item>
<item>
<key> <string>content_type</string> </key>
<value> <string>text/javascript</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>
<div id="view-left-menu" class="tool-menu left">
<div class="tool-menu-btns">
<button id="left-btn-file" class="btn btn-category" content-target="left-panel-file"><span class="btn-icon img-toolbarmenu btn-menu-file">&nbsp;</span></button>
<button id="left-btn-search" class="btn btn-category" content-target=""><span class="btn-icon img-toolbarmenu btn-menu-search">&nbsp;</span></button>
<!-- /** coauthoring begin **/ -->
<button id="left-btn-comments" class="btn btn-category" content-target="left-panel-comments"><span class="btn-icon img-toolbarmenu btn-menu-comments">&nbsp;</span></button>
<button id="left-btn-chat" class="btn btn-category" content-target="left-panel-chat"><span class="btn-icon img-toolbarmenu btn-menu-chat">&nbsp;</span></button>
<!-- /** coauthoring end **/ -->
<button id="left-btn-plugins" class="btn btn-category" content-target=""><span class="btn-icon img-toolbarmenu btn-menu-plugin">&nbsp;</span></button>
<button id="left-btn-remote" class="btn btn-category" content-target=""><span class="btn-icon img-toolbarmenu btn-settings">&nbsp;</span></button>
<button id="left-btn-support" class="btn btn-category" content-target=""><span class="btn-icon img-toolbarmenu btn-menu-support">&nbsp;</span></button>
<button id="left-btn-about" class="btn btn-category" content-target=""><span class="btn-icon img-toolbarmenu btn-menu-about">&nbsp;</span></button>
</div>
<div class="left-panel" style="">
<!-- /** coauthoring begin **/ -->
<div id="left-panel-comments" class="" style="display: none;" />
<div id="left-panel-chat" class="" style="display: none;" />
<!-- /** coauthoring end **/ -->
<div id="left-panel-plugins" class="" style="display: none; height: 100%;" />
</div>
</div>
<div id="view-left-menu" class="tool-menu left">
<div class="tool-menu-btns">
<button id="left-btn-file" class="btn btn-category" content-target="left-panel-file"><span class="btn-icon img-toolbarmenu btn-menu-file">&nbsp;</span></button>
<button id="left-btn-search" class="btn btn-category" content-target=""><span class="btn-icon img-toolbarmenu btn-menu-search">&nbsp;</span></button>
<!-- /** coauthoring begin **/ -->
<button id="left-btn-comments" class="btn btn-category" content-target="left-panel-comments"><span class="btn-icon img-toolbarmenu btn-menu-comments">&nbsp;</span></button>
<button id="left-btn-chat" class="btn btn-category" content-target="left-panel-chat"><span class="btn-icon img-toolbarmenu btn-menu-chat">&nbsp;</span></button>
<!-- /** coauthoring end **/ -->
<button id="left-btn-plugins" class="btn btn-category" content-target=""><span class="btn-icon img-toolbarmenu btn-menu-plugin">&nbsp;</span></button>
<button id="left-btn-remote" class="btn btn-category" content-target=""><span class="btn-icon img-toolbarmenu btn-settings">&nbsp;</span></button>
<button id="left-btn-xmlawizard" class="btn btn-category" content-target="left-panel-xmlawizard"><span class="btn-icon img-toolbarmenu btn-menu-table">&nbsp;</span></button>
<button id="left-btn-support" class="btn btn-category" content-target=""><span class="btn-icon img-toolbarmenu btn-menu-support">&nbsp;</span></button>
<button id="left-btn-about" class="btn btn-category" content-target=""><span class="btn-icon img-toolbarmenu btn-menu-about">&nbsp;</span></button>
</div>
<div class="left-panel" style="">
<!-- /** coauthoring begin **/ -->
<div id="left-panel-comments" class="" style="display: none;" />
<div id="left-panel-chat" class="" style="display: none;" />
<!-- /** coauthoring end **/ -->
<div id="left-panel-xmlawizard" class="" style="display: none; height: 100%;" />
<div id="left-panel-plugins" class="" style="display: none; height: 100%;" />
</div>
</div>
......@@ -42,6 +42,7 @@ define([
'common/main/lib/view/Chat',
/** coauthoring end **/
'common/main/lib/view/SearchDialog',
'common/main/lib/view/RenderJSPanel',
'common/main/lib/view/Plugins',
'spreadsheeteditor/main/app/view/FileMenu'
], function (menuTemplate, $, _, Backbone) {
......@@ -63,6 +64,7 @@ define([
'click #left-btn-chat': _.bind(this.onCoauthOptions, this),
/** coauthoring end **/
'click #left-btn-plugins': _.bind(this.onCoauthOptions, this),
'click #left-btn-xmlawizard': _.bind(this.onCoauthOptions, this),
'click #left-btn-support': function() {
var config = this.mode.customization;
config && !!config.feedback && !!config.feedback.url ?
......@@ -77,7 +79,8 @@ define([
},
render: function () {
var el = $(this.el);
var el = $(this.el),
me = this;
el.html(this.template({
}));
......@@ -157,6 +160,26 @@ define([
this.btnPlugins.hide();
this.btnPlugins.on('click', _.bind(this.onBtnMenuClick, this));
this.btnXmlaWizard = new Common.UI.Button({
el: $('#left-btn-xmlawizard', this.el),
enableToggle: true,
disabled: true,
toggleGroup: 'leftMenuGroup'
});
this.btnXmlaWizard.on('click', _.bind(this.onBtnMenuClick, this));
this.btnXmlaWizard.on('toggle', _.bind(this.onBtnMenuToggle, this));
(new Common.Views.RenderJSPanel({
el: $('#left-panel-xmlawizard'),
scope: "xmlawizard",
gadget_url: "onlyoffice/olap_wizard.html"
})).render()
.push(function (z) {
me.btnXmlaWizard.panel = z;
})
.push(undefined, function (e) {
console.error(e);
});
this.btnSearch.on('click', _.bind(this.onBtnMenuClick, this));
this.btnRemote.on('toggle', _.bind(this.onBtnMenuClick, this));
this.btnAbout.on('toggle', _.bind(this.onBtnMenuToggle, this));
......@@ -267,6 +290,7 @@ define([
close: function(menu) {
this.btnFile.toggle(false);
this.btnAbout.toggle(false);
this.btnXmlaWizard.toggle(false);
this.$el.width(SCALE_MIN);
/** coauthoring begin **/
if (this.mode.canCoAuthoring) {
......@@ -300,6 +324,7 @@ define([
this.btnFile.setDisabled(false);
this.btnAbout.setDisabled(false);
this.btnRemote.setDisabled(false);
this.btnXmlaWizard.setDisabled(false);
this.btnSupport.setDisabled(false);
this.btnSearch.setDisabled(false);
/** coauthoring begin **/
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment