diff --git a/client/gulpfile.js b/client/gulpfile.js index 0937af7ee90..23fbd0ac9f3 100644 --- a/client/gulpfile.js +++ b/client/gulpfile.js @@ -13,16 +13,22 @@ const glob = require("glob"); const STATIC_PLUGIN_BUILD_IDS = [ "annotate_image", "chiraviz", + "cytoscape", + "drawrna", "editor", + "example", "heatmap/heatmap_default", "hyphyvision", + "jqplot/jqplot_bar", "media_player", "mvpapp", "ngl", + "nvd3/nvd3_bar", "openlayers", "openseadragon", "pv", "nora", + "venn", ]; const DIST_PLUGIN_BUILD_IDS = ["new_user"]; diff --git a/client/src/bundleEntries.js b/client/src/bundleEntries.js index 139d859a3d4..42ba563d815 100644 --- a/client/src/bundleEntries.js +++ b/client/src/bundleEntries.js @@ -76,20 +76,10 @@ export { default as async_save_text } from "utils/async-save-text"; // Previously "chart" import Client from "mvc/visualization/chart/chart-client"; -import Datasets from "mvc/visualization/chart/utilities/datasets"; -import Series from "mvc/visualization/chart/utilities/series"; -import Jobs from "mvc/visualization/chart/utilities/jobs"; - export function chart(options) { return new Client(options); } -export const chartUtilities = { - Datasets: Datasets, - Jobs: Jobs, - Series: Series, -}; - export { initMasthead } from "components/Masthead/initMasthead"; export { panelManagement } from "onload/globalInits/panelManagement"; export { mountMakoTags } from "components/Tags"; diff --git a/client/src/mvc/visualization/chart/utilities/datasets.js b/client/src/mvc/visualization/chart/utilities/datasets.js deleted file mode 100644 index 08a96b24710..00000000000 --- a/client/src/mvc/visualization/chart/utilities/datasets.js +++ /dev/null @@ -1,176 +0,0 @@ -/** This class handles, formats and caches datasets. */ -import _ from "underscore"; -import { getAppRoot } from "onload/loadConfig"; -import Utils from "utils/utils"; - -/** Assists in assigning the viewport panels */ -var requestPanels = function (options) { - var process = options.process; - var chart = options.chart; - var render = options.render; - var targets = options.targets; - var dataset_id = options.dataset_id || options.chart.get("dataset_id"); - var dataset_groups = options.dataset_groups || options.chart.groups; - request({ - chart: chart, - dataset_id: dataset_id, - dataset_groups: dataset_groups, - success: function (result) { - try { - if (targets.length == result.length) { - var valid = true; - for (var group_index in result) { - var group = result[group_index]; - if (!render(targets[group_index], [group])) { - valid = false; - break; - } - } - if (valid) { - chart.state("ok", "Multi-panel chart drawn."); - } - } else if (targets.length == 1) { - if (render(targets[0], result)) { - chart.state("ok", "Chart drawn."); - } - } else { - chart.state("failed", "Invalid panel count."); - } - process.resolve(); - } catch (err) { - console.debug("FAILED: tabular-utilities::panelHelper() - " + err); - chart.state("failed", err); - process.reject(); - } - }, - }); -}; - -/** Fills request dictionary with data from cache/response */ -var _cache = {}; -var request = function (options) { - var groups = options.dataset_groups; - var dataset_id = options.dataset_id; - // identify columns needed to fulfill request - var column_list = []; - groups.each(function (group) { - _.each(group.get("__data_columns"), function (column_def, column_name) { - var column = group.get(column_name); - var block_id = _block_id(dataset_id, column); - if ( - column_list.indexOf(column) === -1 && - !_cache[block_id] && - column != "auto" && - column != "zero" && - column !== undefined - ) { - column_list.push(column); - } - }); - }); - if (column_list.length === 0) { - _fillFromCache(options); - return; - } - // Fetch data columns into dataset object - Utils.get({ - url: getAppRoot() + "api/datasets/" + dataset_id, - data: { - data_type: "raw_data", - provider: "dataset-column", - indeces: column_list.toString(), - }, - success: function (response) { - var column_length = column_list.length; - var results = new Array(column_length); - for (let i = 0; i < results.length; i++) { - results[i] = []; - } - for (const i in response.data) { - var row = response.data[i]; - for (const j in row) { - var v = row[j]; - if (v !== undefined && v != 2147483647 && j < column_length) { - results[j].push(v); - } - } - } - console.debug("tabular-datasets::_fetch() - Fetching complete."); - for (const i in results) { - var column = column_list[i]; - var block_id = _block_id(dataset_id, column); - _cache[block_id] = results[i]; - } - _fillFromCache(options); - }, - }); -}; - -/** Fill data from cache */ -var _fillFromCache = function (options) { - var groups = options.dataset_groups; - var dataset_id = options.dataset_id; - console.debug("tabular-datasets::_fillFromCache() - Filling request from cache."); - var limit = 0; - groups.each(function (group) { - _.each(group.get("__data_columns"), function (column_def, column_name) { - var column = group.get(column_name); - var block_id = _block_id(dataset_id, column); - var column_data = _cache[block_id]; - if (column_data) { - limit = Math.max(limit, column_data.length); - } - }); - }); - if (limit === 0) { - console.debug("tabular-datasets::_fillFromCache() - No data available."); - if (options.chart) { - options.chart.state("failed", "No data available."); - } - } - var results = []; - groups.each(function (group, group_index) { - var dict = Utils.merge({ key: group_index + ":" + group.get("key"), values: [] }, group.attributes); - for (let j = 0; j < limit; j++) { - dict.values[j] = { x: parseInt(j) }; - } - results.push(dict); - }); - groups.each(function (group, group_index) { - var values = results[group_index].values; - _.each(group.get("__data_columns"), function (column_def, column_name) { - var column = group.get(column_name); - switch (column) { - case "auto": - for (let j = 0; j < limit; j++) { - values[j][column_name] = parseInt(j); - } - break; - case "zero": - for (let j = 0; j < limit; j++) { - values[j][column_name] = 0; - } - break; - default: - var block_id = _block_id(dataset_id, column); - var column_data = _cache[block_id]; - for (let j = 0; j < limit; j++) { - var value = values[j]; - var v = column_data[j]; - if (isNaN(v) && !column_def.is_label) { - v = 0; - } - value[column_name] = v; - } - } - }); - }); - options.success(results); -}; - -/** Get block id */ -var _block_id = function (dataset_id, column) { - return dataset_id + "_" + "_" + column; -}; - -export default { request: request, requestPanels: requestPanels }; diff --git a/client/src/mvc/visualization/chart/utilities/jobs.js b/client/src/mvc/visualization/chart/utilities/jobs.js deleted file mode 100644 index 3b9dce7aaf3..00000000000 --- a/client/src/mvc/visualization/chart/utilities/jobs.js +++ /dev/null @@ -1,158 +0,0 @@ -/** This class handles job submissions to the Galaxy API. */ -import _ from "underscore"; -import { getAppRoot } from "onload/loadConfig"; -import Utils from "utils/utils"; -import { getGalaxyInstance } from "app"; - -/** Time to wait before refreshing to check if job has completed */ -const WAITTIME = 1000; - -/** build job dictionary */ -var requestCharts = function (chart, module) { - var settings_string = ""; - var columns_string = ""; - var group_index = 0; - for (var key in chart.settings.attributes) { - var settings_value = chart.settings.get(key); - _.each( - [ - [" ", " "], - [",", ","], - [":", ":"], - ], - function (pair) { - settings_value = settings_value.replace(new RegExp(pair[0], "g"), pair[1]); - } - ); - settings_string += key + ":" + settings_value + ", "; - } - settings_string = settings_string.substring(0, settings_string.length - 2); - chart.groups.each(function (group) { - group_index++; - _.each(group.get("__data_columns"), function (data_columns, name) { - columns_string += name + "_" + group_index + ":" + (parseInt(group.get(name)) + 1) + ", "; - }); - }); - columns_string = columns_string.substring(0, columns_string.length - 2); - return { - tool_id: "toolshed.g2.bx.psu.edu/repos/iuc/charts/charts/1.0.1", - inputs: { - input: { - id: chart.get("dataset_id"), - src: "hda", - }, - module: module, - columns: columns_string, - settings: settings_string, - }, - }; -}; - -/** Submit job request to charts tool */ -var request = function (chart, parameters, success, error) { - chart.state("wait", "Requesting job results..."); - if (chart.get("modified") && chart.get("dataset_id_job")) { - Utils.request({ - type: "PUT", - url: getAppRoot() + "api/histories/none/contents/" + chart.get("dataset_id_job"), - data: { deleted: true }, - success: () => { - refreshHdas(); - }, - }); - chart.set("dataset_id_job", null); - chart.set("modified", false); - } - if (chart.get("dataset_id_job")) { - wait(chart, success, error); - } else { - chart.state("wait", "Sending job request..."); - Utils.request({ - type: "POST", - url: getAppRoot() + "api/tools", - data: parameters, - success: function (response) { - if (!response.outputs || response.outputs.length === 0) { - chart.state("failed", "Job submission failed. No response."); - if (error) { - error(); - } - } else { - refreshHdas(); - var job = response.outputs[0]; - chart.state( - "wait", - "Your job has been queued. You may close the browser window. The job will run in the background." - ); - chart.set("dataset_id_job", job.id); - chart.save(); - wait(chart, success, error); - } - }, - error: function (response) { - var message = ""; - if (response && response.message && response.message.data && response.message.data.input) { - message = response.message.data.input + "."; - } - chart.state( - "failed", - "This visualization requires the '" + - parameters.tool_id + - "' tool. Please make sure it is installed. " + - message - ); - if (error) { - error(); - } - }, - }); - } -}; - -/** Request job details */ -var wait = function (chart, success, error) { - Utils.request({ - type: "GET", - url: getAppRoot() + "api/datasets/" + chart.get("dataset_id_job"), - data: {}, - success: function (dataset) { - var ready = false; - switch (dataset.state) { - case "ok": - chart.state("wait", "Job completed successfully..."); - if (success) { - success(dataset); - } - ready = true; - break; - case "error": - chart.state("failed", "Job has failed. Please check the history for details."); - if (error) { - error(dataset); - } - ready = true; - break; - case "running": - chart.state( - "wait", - "Your job is running in the background and you may close the browser tab. Results will be available in your saved visualizations list." - ); - } - if (!ready) { - window.setTimeout(function () { - wait(chart, success, error); - }, WAITTIME); - } - }, - }); -}; - -/** Refresh history panel */ -var refreshHdas = function () { - const Galaxy = getGalaxyInstance(); - if (Galaxy && Galaxy.currHistoryPanel) { - Galaxy.currHistoryPanel.refreshContents(); - } -}; - -export default { request: request, requestCharts: requestCharts }; diff --git a/client/src/mvc/visualization/chart/utilities/series.js b/client/src/mvc/visualization/chart/utilities/series.js deleted file mode 100644 index 2a48bf5faf0..00000000000 --- a/client/src/mvc/visualization/chart/utilities/series.js +++ /dev/null @@ -1,227 +0,0 @@ -import _ from "underscore"; -import * as d3 from "d3"; - -/** Get domain boundaries value */ -function getDomains(groups, keys) { - function _apply(operator, key) { - let value; - for (const group_index in groups) { - const value_sub = d3[operator](groups[group_index].values, function (d) { - return d[key]; - }); - value = value === undefined ? value_sub : Math[operator](value, value_sub); - } - return value; - } - var result = {}; - for (var index in keys) { - var key = keys[index]; - result[key] = { - min: _apply("min", key), - max: _apply("max", key), - }; - } - return result; -} - -/** Default series maker */ -function makeSeries(groups, keys) { - var plot_data = []; - for (var group_index in groups) { - var group = groups[group_index]; - var data = []; - for (var value_index in group.values) { - var point = []; - if (keys) { - for (var key_index in keys) { - const column_index = keys[key_index]; - point.push(group.values[value_index][column_index]); - } - } else { - for (const column_index in group.values[value_index]) { - point.push(group.values[value_index][column_index]); - } - } - data.push(point); - } - plot_data.push(data); - } - return plot_data; -} - -/** Default category maker */ -function makeCategories(groups, column_keys) { - var array = {}; - var data_columns = groups[0].__data_columns; - _.each(column_keys, function (key) { - const data_entry = data_columns && data_columns[key]; - if (data_entry && data_entry.is_label) { - array[key] = []; - } - }); - if (groups && groups[0]) { - _.each(groups[0].values, function (value_dict) { - for (var key in array) { - array[key].push(String(value_dict[key])); - } - }); - } - mapCategories(array, groups); - return { array: array }; -} - -/** Apply default mapping index all values contained in label columns (for all groups) */ -function mapCategories(array, groups) { - _.each(groups, function (group) { - _.each(group.values, function (value_dict, i) { - for (var key in array) { - value_dict[key] = parseInt(i); - } - }); - }); -} - -/** Category make for unique category labels */ -function makeUniqueCategories(groups, with_index) { - var categories = {}; - var array = {}; - var counter = {}; - var data_columns = groups[0].__data_columns; - _.each(data_columns, function (column_def, key) { - if (column_def.is_label) { - categories[key] = {}; - array[key] = []; - counter[key] = 0; - } - }); - // index all values contained in label columns (for all groups) - for (var i in groups) { - var group = groups[i]; - for (var j in group.values) { - var value_dict = group.values[j]; - for (var key in categories) { - var value = String(value_dict[key]); - if (categories[key][value] === undefined) { - categories[key][value] = counter[key]; - array[key].push(with_index ? [counter[key], value] : value); - counter[key]++; - } - } - } - } - // convert group values into category indeces - for (const i in groups) { - const group = groups[i]; - for (const j in group.values) { - const value_dict = group.values[j]; - for (const key in categories) { - const value = String(value_dict[key]); - value_dict[key] = categories[key][value]; - } - } - } - return { - categories: categories, - array: array, - counter: counter, - }; -} - -/** Make axis */ -function makeTickFormat(options) { - var type = options.type; - var precision = options.precision; - var categories = options.categories; - var formatter = options.formatter; - if (type == "hide") { - formatter(function () { - return ""; - }); - } else if (type == "auto") { - if (categories) { - formatter(function (value) { - return categories[value] || ""; - }); - } - } else { - var d3format = function (d) { - switch (type) { - case "s": - var prefix = d3.formatPrefix(d); - return prefix.scale(d).toFixed() + prefix.symbol; - default: - return d3.format("." + precision + type)(d); - } - }; - if (categories) { - formatter(function (value) { - var label = categories[value]; - if (label) { - if (isNaN(label)) { - return label; - } else { - try { - return d3format(label); - } catch (err) { - return label; - } - } - } else { - return ""; - } - }); - } else { - formatter(function (value) { - return d3format(value); - }); - } - } -} - -/** Add zoom handler */ -function addZoom(options) { - var scaleExtent = 100; - var yAxis = options.yAxis; - var xAxis = options.xAxis; - var xDomain = options.xDomain || xAxis.scale().domain; - var yDomain = options.yDomain || yAxis.scale().domain; - var redraw = options.redraw; - var svg = options.svg; - var xScale = xAxis.scale(); - var yScale = yAxis.scale(); - var x_boundary = xScale.domain().slice(); - var y_boundary = yScale.domain().slice(); - var d3zoom = d3.behavior.zoom(); - xScale.nice(); - yScale.nice(); - function fixDomain(domain, boundary) { - domain[0] = Math.min(Math.max(domain[0], boundary[0]), boundary[1] - boundary[1] / scaleExtent); - domain[1] = Math.max(boundary[0] + boundary[1] / scaleExtent, Math.min(domain[1], boundary[1])); - return domain; - } - function zoomed() { - yDomain(fixDomain(yScale.domain(), y_boundary)); - xDomain(fixDomain(xScale.domain(), x_boundary)); - redraw(); - } - function unzoomed() { - xDomain(x_boundary); - yDomain(y_boundary); - redraw(); - d3zoom.scale(1); - d3zoom.translate([0, 0]); - } - d3zoom.x(xScale).y(yScale).scaleExtent([1, scaleExtent]).on("zoom", zoomed); - svg.call(d3zoom).on("dblclick.zoom", unzoomed); - return d3zoom; -} - -export default { - makeCategories: makeCategories, - makeUniqueCategories: makeUniqueCategories, - makeSeries: makeSeries, - getDomains: getDomains, - mapCategories: mapCategories, - makeTickFormat: makeTickFormat, - addZoom: addZoom, -}; diff --git a/client/src/mvc/visualization/chart/views/settings.js b/client/src/mvc/visualization/chart/views/settings.js index be5a11818cd..3889893269f 100644 --- a/client/src/mvc/visualization/chart/views/settings.js +++ b/client/src/mvc/visualization/chart/views/settings.js @@ -17,18 +17,6 @@ export default Backbone.View.extend({ render: function () { var self = this; var inputs = Utils.clone(this.chart.plugin.settings) || []; - var panel_option = this.chart.plugin.specs.use_panels; - if (panel_option == "optional") { - inputs.push({ - name: "__use_panels", - type: "boolean", - label: "Use multi-panels", - help: "Would you like to separate your data into individual panels?", - value: false, - }); - } else { - this.chart.settings.set("__use_panels", panel_option == "yes" ? "true" : "false"); - } this.$el.empty(); if (inputs.length > 0) { visitInputs(inputs, function (input, name) { diff --git a/client/src/mvc/visualization/chart/views/viewer.js b/client/src/mvc/visualization/chart/views/viewer.js index e8ac3d29446..1e2e72eee14 100644 --- a/client/src/mvc/visualization/chart/views/viewer.js +++ b/client/src/mvc/visualization/chart/views/viewer.js @@ -5,6 +5,7 @@ import $ from "jquery"; import Backbone from "backbone"; import Utils from "utils/utils"; +import { getAppRoot } from "onload/loadConfig"; export default Backbone.View.extend({ initialize: function (app, options) { @@ -12,6 +13,7 @@ export default Backbone.View.extend({ this.app = app; this.chart = this.app.chart; this.options = options; + this.$container = $("
").css("height", "100%").attr("id", "charts-container"); this.setElement( $("") .addClass("charts-viewer") @@ -21,12 +23,12 @@ export default Backbone.View.extend({ .append($("").addClass("icon")) .append($("").addClass("text")) ) + .append(this.$container) ); this.$info = this.$(".info"); this.$icon = this.$(".icon"); this.$text = this.$(".text"); this._fullscreen(this.$el, 20); - this._createContainer("div"); this.chart.on("redraw", function (confirmed) { if (!self.chart.get("modified") || !self._asBoolean(self.chart.plugin.specs.confirm) || confirmed) { self.app.deferred.execute(function (process) { @@ -79,29 +81,17 @@ export default Backbone.View.extend({ }); }, - /** A chart may contain multiple sub charts/containers which are created here */ - _createContainer: function (tag, n) { - tag = tag || "div"; - n = n || 1; - this.$(".charts-viewer-container").remove(); - this.targets = []; - for (var i = 0; i < n; i++) { - var container_id = Utils.uid(); - var container_el = $("") - .addClass("charts-viewer-container") - .width(parseInt(100 / n) + "%") - .append($("<" + tag + " class='charts-viewer-canvas' />").attr("id", container_id)); - this.$el.append(container_el); - this.targets.push(container_id); - } - }, - /** Draws a new chart by loading and executing the corresponding chart wrapper */ _draw: function (process, chart) { - var n_panels = this._asBoolean(chart.settings.get("__use_panels")) ? chart.groups.length : 1; - this._createContainer(chart.plugin.specs.tag, n_panels); chart.set("date", Utils.time()); chart.state("wait", "Please wait..."); - this.app.chart_load({ process: process, chart: chart, dataset: this.app.dataset, targets: this.targets }); + this.$container.empty(); + this.app.chart_load({ + process: process, + chart: chart, + target: "charts-container", + dataset: this.app.dataset, + root: getAppRoot(), + }); }, }); diff --git a/config/plugins/visualizations/annotate_image/package.json b/config/plugins/visualizations/annotate_image/package.json index 83c6fe6d2f7..10db5307044 100644 --- a/config/plugins/visualizations/annotate_image/package.json +++ b/config/plugins/visualizations/annotate_image/package.json @@ -18,6 +18,8 @@ "underscore": "^1.8.3" }, "scripts": { - "build": "parcel build src/script.js -d static --no-source-maps" + "build": "yarn build-css && yarn build-js", + "build-css": "cp 'node_modules/jquery-contextmenu/dist/jquery.contextMenu.css' 'static/'", + "build-js": "parcel build src/script.js -d static --no-source-maps" } } diff --git a/config/plugins/visualizations/annotate_image/src/script.js b/config/plugins/visualizations/annotate_image/src/script.js index a2f1492e5a4..2b031ad8295 100644 --- a/config/plugins/visualizations/annotate_image/src/script.js +++ b/config/plugins/visualizations/annotate_image/src/script.js @@ -54,417 +54,416 @@ const generateUUID = function() { return uuid; }; -_.extend(window.bundleEntries || {}, { - load: function(opt) { - const chart = opt.chart; - const dataset = opt.dataset; - const defaults = { color: "red", width: 4, opacity: 0.5 }; - $.fn.createCanvas = function(options) { - let settings = $.extend({}, defaults, options || {}); - const self = this; +window.bundleEntries = window.bundleEntries || {}; +window.bundleEntries.load = function (opt) { + const chart = opt.chart; + const dataset = opt.dataset; + const defaults = { color: "red", width: 4, opacity: 0.5 }; + $.fn.createCanvas = function(options) { + let settings = $.extend({}, defaults, options || {}); + const self = this; - this.setOptions = function(options) { - settings = $.extend(settings, options); - }; + this.setOptions = function(options) { + settings = $.extend(settings, options); + }; - $(document).ready(function() { - $(self).each(function(eachIndex, eachItem) { - self.paths = []; - const img = eachItem; - // Get a reference to the canvas object - const canvas = $("