Skip to content

Commit

Permalink
Move charts client to core
Browse files Browse the repository at this point in the history
  • Loading branch information
guerler committed Feb 11, 2018
1 parent 65e2e0b commit ca66882
Show file tree
Hide file tree
Showing 10 changed files with 1,078 additions and 0 deletions.
101 changes: 101 additions & 0 deletions client/galaxy/scripts/mvc/visualization/client/components/model.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
define(["utils/utils", "mvc/visualization/visualization-model"], function(Utils) {
return Backbone.Model.extend({
defaults: {
title: "",
type: "",
date: null,
state: "",
state_info: "",
modified: false,
dataset_id: "",
dataset_id_job: ""
},

initialize: function(options, viz_options) {
this.groups = new Backbone.Collection();
this.settings = new Backbone.Model();
this.definition = {};
this.viz_options = viz_options;
console.debug("model::initialize() - Initialized with configuration:");
console.debug(viz_options);
},

reset: function() {
this.clear().set({
title: "New Chart",
type: "__first",
dataset_id: this.viz_options.dataset_id
});
this.settings.clear();
this.groups.reset();
this.groups.add({ id: Utils.uid() });
},

state: function(value, info) {
this.set({ state: value, state_info: info });
this.trigger("set:state");
console.debug("model::state() - " + info + " (" + value + ")");
},

/** Pack and save nested chart model */
save: function(options) {
var self = this;
options = options || {};
var chart_dict = {
attributes: this.attributes,
settings: this.settings.attributes,
groups: []
};
this.groups.each(function(group) {
chart_dict.groups.push(group.attributes);
});
var viz = new Visualization({
id: this.viz_options.visualization_id || undefined,
type: "charts",
title: this.get("title") || "",
config: {
dataset_id: this.viz_options.dataset_id,
chart_dict: (this.viz_options.chart_dict = chart_dict)
}
});
viz
.save()
.then(function(response) {
if (response && response.id) {
self.viz_options.visualization_id = response.id;
options.success && options.success();
console.debug("model::save() - Received visualization id: " + response.id);
} else {
options.error && options.error();
console.debug("model::save() - Unrecognized response. Saving may have failed.");
}
})
.fail(function(response) {
options.error && options.error();
console.debug("model::save() - Saving failed.");
});
console.debug("model::save() - Saved with configuration:");
console.debug(this.viz_options);
},

/** Load nested models/collections from packed dictionary */
load: function() {
console.debug("model::load() - Attempting to load with configuration:");
console.debug(this.viz_options);
var chart_dict = this.viz_options.chart_dict;
if (chart_dict && chart_dict.attributes) {
this.set(chart_dict.attributes);
this.state("ok", "Loading saved visualization...");
this.settings.set(chart_dict.settings);
this.groups.reset();
this.groups.add(chart_dict.groups);
this.set("modified", false);
console.debug("model::load() - Loading chart model " + chart_dict.attributes.type + ".");
this.trigger("redraw");
return true;
}
console.debug("model::load() - Visualization attributes unavailable.");
return false;
}
});
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,188 @@
/** This class enables users to export/download a chart as PNG, SVG or PDF. */
define(["libs/underscore"], function(_) {
/** PNG export */
function createPNG(options) {
if (options.$el.find("svg").length > 0) {
_svg2png(options);
} else {
_canvas2png(options.$el.find(".charts-viewport-canvas"));
}
}

/** Convert canvas to png */
function _canvas2png($canvas) {
try {
if ($canvas.width() !== 0 && $canvas.height() !== 0) {
var newCanvas = document.createElement("canvas");
newCanvas.width = $canvas.outerWidth(true);
newCanvas.height = $canvas.outerHeight(true);
var newContext = newCanvas.getContext("2d");
newContext.save();
newContext.fillStyle = "rgb(255,255,255)";
newContext.fillRect(0, 0, newCanvas.width, newCanvas.height);
newContext.restore();
newContext.translate(0, 0);
newContext.textAlign = "left";
newContext.textBaseline = "top";
function _toImage($el, x_offset, y_offset) {
var tagname = $el.prop("tagName").toLowerCase();
var p = $el.position();
var left =
x_offset +
p.left +
parseInt($el.css("marginLeft"), 10) +
parseInt($el.css("borderLeftWidth"), 10) +
parseInt($el.css("paddingLeft"), 10);
var top =
y_offset +
p.top +
parseInt($el.css("marginTop"), 10) +
parseInt($el.css("borderTopWidth"), 10) +
parseInt($el.css("paddingTop"), 10);
var w = newCanvas.width;
if (tagname == "div" || tagname == "span") {
$el.children().each(function() {
_toImage($(this), left, top);
});
} else if (tagname == "canvas") {
newContext.drawImage($el[0], left, top);
}
}
$canvas.children().each(function() {
_toImage($(this), 0, 0);
});
var imgData = newCanvas.toDataURL("image/png");
if (imgData) {
window.location.href = imgData.replace("image/png", "image/octet-stream");
}
}
} catch (err) {
console.debug("FAILED - screenshot::_canvas2png() - " + err);
if (options.error) {
options.error("Please reduce your visualization to a single panel and try again.");
}
}
}

/** Convert svg to png */
function _svg2png(options) {
var scale = 5;
var xml = toXML(options);
var canvas = document.createElement("canvas");
var context = canvas.getContext("2d");
var source = new Image();
var $container = $('<div style="display:none;"/>').append($(canvas));
$("body").append($container);
canvas.width = xml.width * scale;
canvas.height = xml.height * scale;
source.src = "data:image/svg+xml;base64," + btoa(xml.string);
source.onload = function() {
context.drawImage(source, 0, 0, canvas.width, canvas.height);
window.location.href = canvas.toDataURL("image/png").replace("image/png", "image/octet-stream");
$container.remove();
};
}

/** SVG export */
function createSVG(options) {
window.location.href = "data:none/none;base64," + btoa(toXML(options).string);
}

/** PDF export */
function createPDF(options) {
var xml = toXML(options);
var data = {
filename: "visualization",
type: "application/pdf",
height: xml.height,
width: xml.width,
scale: 2,
svg: xml.string
};
var $el = $("body");
var form = $el.find("#viewport-form");
if (form.length === 0) {
form = $("<form>", {
id: "viewport-form",
method: "post",
action: "http://export.highcharts.com/",
display: "none"
});
$el.append(form);
}
form.empty();
for (var name in data) {
var input = $("<input/>", {
type: "hidden",
name: name,
value: data[name]
});
form.append(input);
}
try {
form.submit();
} catch (err) {
console.log(err);
}
}

/** XML export */
function toXML(options) {
var $svg = options.$el.find("svg");
if ($svg.length == 0) {
if (options.error) {
options.error("No SVG found. This visualization type does not support SVG/PDF export.");
return;
}
}
var $el = options.$el;
var nsvgs = $svg.length;
var height = parseInt($svg.first().css("height"));
var width = parseInt($svg.first().css("width"));
var serializer = new XMLSerializer();
var $composite = $("<svg/>").attr({
version: "1.1",
xmlns: "http://www.w3.org/2000/svg",
width: width * nsvgs,
height: height
});
var xmlString = "";
var offsetX = 0;
$svg.each(function() {
var $svg = $(this).clone();
_inline($svg);
var $g = $('<g transform="translate(' + offsetX + ', 0)">').attr("xmlns", "http://www.w3.org/2000/svg");
$g.append($svg.find("g").first());
$composite.append($g);
offsetX += width;
});
return {
string: serializer.serializeToString($composite[0]),
height: height,
width: width
};
}

/** inlines CSS code */
function _inline($target) {
for (var sheet_id in document.styleSheets) {
var sheet = document.styleSheets[sheet_id];
var rules = sheet.cssRules;
if (rules) {
for (var idx = 0, len = rules.length; idx < len; idx++) {
try {
$target.find(rules[idx].selectorText).each(function(i, elem) {
elem.style.cssText += rules[idx].style.cssText;
});
} catch (err) {}
}
}
}
}

return {
createPNG: createPNG,
createSVG: createSVG,
createPDF: createPDF
};
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
/** This class renders the chart configuration form. */
import Utils from "utils/utils";
export default Backbone.View.extend({
initialize: function(app, options) {
var self = this;
this.chart = app.chart;
this.app = app;
this.setElement(this._template());
this.$title = this.$(".charts-description-title");
this.$image = this.$(".charts-description-image");
this.$text = this.$(".charts-description-text");
this.listenTo(this.chart, "change", function() {
self.render();
});
this.render();
},
render: function() {
if (this.chart.get("type")) {
/*this.$image.attr(
"src",
repository_root + "/visualizations/" + this.app.split(this.chart.get("type")) + "/logo.png"
);*/
this.$title.html(this.chart.definition.title + " (" + this.chart.definition.library + ")");
this.$text.html(Utils.linkify(this.chart.definition.description || ""));
this.$el.show();
} else {
this.$el.hide();
}
},
_template: function() {
return (
'<div class="charts-description">' +
"<table>" +
"<tr>" +
'<td class="charts-description-image-td">' +
'<img class="charts-description-image"/>' +
"</td>" +
"<td>" +
'<div class="charts-description-title ui-form-info"/>' +
'<div class="charts-description-text ui-form-info"/>' +
"</td>" +
"</tr>" +
"</table>" +
"</div>"
);
}
});

0 comments on commit ca66882

Please sign in to comment.