diff --git a/.ci/flake8_lint_include_list.txt b/.ci/flake8_lint_include_list.txt index 3f9464d8e44..82143f3804c 100644 --- a/.ci/flake8_lint_include_list.txt +++ b/.ci/flake8_lint_include_list.txt @@ -69,6 +69,7 @@ lib/galaxy/jobs/actions/ lib/galaxy/jobs/datasets.py lib/galaxy/jobs/deferred/ lib/galaxy/jobs/error_level.py +lib/galaxy/jobs/__init__.py lib/galaxy/jobs/manager.py lib/galaxy/jobs/metrics/collectl/__init__.py lib/galaxy/jobs/metrics/collectl/stats.py diff --git a/Makefile b/Makefile index b7f7598ca84..789680cfcbd 100644 --- a/Makefile +++ b/Makefile @@ -157,10 +157,10 @@ release-create: release-ensure-upstream ## Create a release branch git commit -m "Merge branch 'release_$(RELEASE_CURR)' into dev" git checkout master git merge release_$(RELEASE_CURR) - #git push $(RELEASE_UPSTREAM) release_$(RELEASE_CURR):release_$(RELEASE_CURR) - #git push $(RELEASE_UPSTREAM) dev:dev - #git push $(RELEASE_UPSTREAM) master:master - #git push $(RELEASE_UPSTREAM) --tags + git push $(RELEASE_UPSTREAM) release_$(RELEASE_CURR):release_$(RELEASE_CURR) + git push $(RELEASE_UPSTREAM) dev:dev + git push $(RELEASE_UPSTREAM) master:master + git push $(RELEASE_UPSTREAM) --tags release-create-point: ## Create a point release git pull --ff-only $(RELEASE_UPSTREAM) master diff --git a/client/galaxy/scripts/mvc/dataset/data.js b/client/galaxy/scripts/mvc/dataset/data.js index 309dd20f92a..22b7b6ed37a 100644 --- a/client/galaxy/scripts/mvc/dataset/data.js +++ b/client/galaxy/scripts/mvc/dataset/data.js @@ -251,16 +251,20 @@ var TabularDatasetChunkedView = Backbone.View.extend({ }, this); row.append(this._renderCell(cells.slice(num_columns - 1).join('\t'), num_columns - 1)); } - else if (num_columns > 5 && cells.length === num_columns - 1 ) { - // SAM file or like format with optional metadata missing. + else if (cells.length === 1){ + // Comment line, just return the one cell. + row.append(this._renderCell(line, 0, num_columns)); + } + else { + // cells.length is greater than one, but less than num_columns. Render cells and pad tds. + // Possibly a SAM file or like format with optional metadata missing. + // Could also be a tabular file with a line with missing columns. _.each(cells, function(cell_contents, index) { row.append(this._renderCell(cell_contents, index)); }, this); - row.append($('')); - } - else { - // Comment line, just return the one cell. - row.append(this._renderCell(line, 0, num_columns)); + _.each(_.range(num_columns - cells.length), function(){ + row.append($('')); + }); } this.row_count++; diff --git a/client/galaxy/scripts/mvc/form/form-data.js b/client/galaxy/scripts/mvc/form/form-data.js index 9a0981e47c3..826636c08ce 100644 --- a/client/galaxy/scripts/mvc/form/form-data.js +++ b/client/galaxy/scripts/mvc/form/form-data.js @@ -1,6 +1,4 @@ -/* - This class maps the form dom to an api compatible javascript dictionary. -*/ +/* This class maps the form dom to an api compatible javascript dictionary. */ define([ 'utils/utils' ], function( Utils ) { var Manager = Backbone.Model.extend({ initialize: function( app ) { @@ -21,14 +19,6 @@ define([ 'utils/utils' ], function( Utils ) { return sum; }, - /** Set parameter values from model */ - set: function( model ) { - for ( var attr in model.attributes ) { - var index = this.match( attr ); - index && this.app.field_list[ index ].value( model.get( attr ) ); - } - }, - /** Convert dom into a dictionary of flat id/value pairs used e.g. on job submission. */ create: function() { var self = this; @@ -211,8 +201,9 @@ define([ 'utils/utils' ], function( Utils ) { context[ input.name ] = input; } }); - for ( var i in inputs ) { - var node = inputs[ i ]; + for ( var key in inputs ) { + var node = inputs[ key ]; + node.name = node.name || key; var name = prefix ? prefix + '|' + node.name : node.name; switch ( node.type ) { case 'repeat': diff --git a/client/galaxy/scripts/mvc/form/form-view.js b/client/galaxy/scripts/mvc/form/form-view.js index 6d40b1ed469..3684e15c459 100644 --- a/client/galaxy/scripts/mvc/form/form-view.js +++ b/client/galaxy/scripts/mvc/form/form-view.js @@ -86,11 +86,6 @@ function( Utils, Portlet, Ui, FormSection, FormData ) { } }, - /** Modify onchange event handler */ - setOnChange: function( callback ) { - this.options.onchange = callback; - }, - /** Render tool form */ render: function() { var self = this; diff --git a/client/galaxy/scripts/mvc/ui/ui-color-picker.js b/client/galaxy/scripts/mvc/ui/ui-color-picker.js index 02be894e001..d5a341e9ed7 100644 --- a/client/galaxy/scripts/mvc/ui/ui-color-picker.js +++ b/client/galaxy/scripts/mvc/ui/ui-color-picker.js @@ -10,29 +10,18 @@ define(['utils/utils'], function( Utils ) { ['a5a5a5','262626','494429','17365d','366092','953734','76923c','5f497a','31859b','e36c09'], ['7f7f7e','0c0c0c','1d1b10','0f243e','244061','632423','4f6128','3f3151','205867','974806']] }, + initialize : function( options ) { this.options = Utils.merge( options, {} ); this.setElement( this._template() ); - - // link components this.$panel = this.$( '.ui-color-picker-panel' ); this.$view = this.$( '.ui-color-picker-view' ); this.$value = this.$( '.ui-color-picker-value' ); this.$header = this.$( '.ui-color-picker-header' ); - - // build panel this._build(); - - // hide panel on start up this.visible = false; - - // set initial value this.value( this.options.value ); - - // link boxes this.$boxes = this.$( '.ui-color-picker-box' ); - - // add event handler var self = this; this.$boxes.on( 'click', function() { self.value( $( this ).css( 'background-color' ) ); @@ -48,25 +37,18 @@ define(['utils/utils'], function( Utils ) { } ); }, - // value + /** Get/set value */ value : function ( new_val ) { if ( new_val !== undefined && new_val !== null ) { - // update color value this.$value.css( 'background-color', new_val ); - - // check selected color in panel this.$( '.ui-color-picker-box' ).empty(); this.$( this._getValue() ).html( this._templateCheck() ); - - // trigger custom event this.options.onchange && this.options.onchange( new_val ); } - - // return current value return this._getValue(); }, - // get value from dom + /** Get value from dom */ _getValue: function() { var rgb = this.$value.css( 'background-color' ); rgb = rgb.match(/^rgb\((\d+),\s*(\d+),\s*(\d+)\)$/); @@ -80,7 +62,7 @@ define(['utils/utils'], function( Utils ) { } }, - // build panel + /** Build color panel */ _build: function() { var $content = this._content({ label : 'Theme Colors', @@ -110,27 +92,20 @@ define(['utils/utils'], function( Utils ) { }); }, - // create content + /** Create content */ _content: function( options ) { - // get parameters var label = options.label; var colors = options.colors; var padding = options.padding; var top = options.top; var bottom = options.bottom; - - // create lines var $content = $( this._templateContent() ); - - // set label var $label = $content.find( '.label' ); if ( options.label ) { $label.html( options.label ); } else { $label.hide(); } - - // build line var $line = $content.find( '.line' ); this.$panel.append( $content ); for ( var i in colors ) { @@ -153,12 +128,12 @@ define(['utils/utils'], function( Utils ) { return $content; }, - // check icon + /** Check icon */ _templateCheck: function() { return '
'; }, - // content template + /** Content template */ _templateContent: function() { return '
' + '
' + @@ -166,12 +141,12 @@ define(['utils/utils'], function( Utils ) { '
'; }, - // box template + /** Box template */ _templateBox: function( color ) { return '
'; }, - // template + /** Main template */ _template: function() { return '
' + '
' + diff --git a/client/galaxy/scripts/mvc/ui/ui-tabs.js b/client/galaxy/scripts/mvc/ui/ui-tabs.js index 1b5f82f1bda..9cdf1287019 100644 --- a/client/galaxy/scripts/mvc/ui/ui-tabs.js +++ b/client/galaxy/scripts/mvc/ui/ui-tabs.js @@ -109,7 +109,7 @@ var View = Backbone.View.extend({ }, /** Delete all tabs */ - delRemovable: function() { + delAll: function() { for ( var id in this.list ) { this.del( id ); } @@ -135,6 +135,16 @@ var View = Backbone.View.extend({ this.visible = false; }, + /** Show tab */ + showTab: function( id ) { + this.$( '#tab-' + id ).show(); + }, + + /** hide tab */ + hideTab: function( id ) { + this.$( '#tab-' + id ).hide(); + }, + /** Hide operation by id */ hideOperation: function( id ) { this.$nav.find( '#' + id ).hide(); diff --git a/client/galaxy/scripts/utils/utils.js b/client/galaxy/scripts/utils/utils.js index 32eae1ccd2b..1cac029c26a 100644 --- a/client/galaxy/scripts/utils/utils.js +++ b/client/galaxy/scripts/utils/utils.js @@ -25,6 +25,11 @@ function deepeach( dict, callback ) { } } +/** Clone */ +function clone( obj ) { + return JSON.parse( JSON.stringify( obj ) || null ); +} + /** * Check if a string is a json string * @param{String} text - Content to be validated @@ -275,7 +280,8 @@ return { textify: textify, isEmpty: isEmpty, deepeach: deepeach, - isJSON: isJSON + isJSON: isJSON, + clone: clone }; }); \ No newline at end of file diff --git a/config/galaxy.ini.sample b/config/galaxy.ini.sample index 52f661ee9d2..0659b6597fa 100644 --- a/config/galaxy.ini.sample +++ b/config/galaxy.ini.sample @@ -175,7 +175,7 @@ paste.app_factory = galaxy.web.buildapp:app_factory # the Tool Shed to install dependencies and can also be used by administrators # to manually install or link to dependencies. For details, see: # https://wiki.galaxyproject.org/Admin/Config/ToolDependencies -# Set to the string none to explicitly disable tool dependency handling. +# Set the string to None to explicitly disable tool dependency handling. # If this option is set to none or an invalid path, installing tools with dependencies # from the Tool Shed will fail. #tool_dependency_dir = database/dependencies @@ -320,7 +320,6 @@ paste.app_factory = galaxy.web.buildapp:app_factory # Time to sleep between checks if check_job_script_integrity is enabled (in seconds). #check_job_script_integrity_sleep = .25 - # Set the default shell used by non-containerized jobs Galaxy-wide. This # defaults to bash for all jobs and can be overidden at the destination # level for heterogenous clusters. conda job resolution requires bash or zsh @@ -632,7 +631,7 @@ nglims_config_file = tool-data/nglims.yaml # implementation, alongside a new Golang single-binary-no-dependencies # version. Valid values are (node, golang) #dynamic_proxy=node -# + # The NodeJS dynamic proxy can use an SQLite database or a JSON file for IPC, # set that here. #dynamic_proxy_session_map=database/session_map.sqlite @@ -702,7 +701,6 @@ nglims_config_file = tool-data/nglims.yaml # log_events and log_actions functionality will eventually be merged. #log_actions = True - # Fluentd configuration. Various events can be logged to the fluentd instance # configured below by enabling fluent_log. #fluent_log = False @@ -956,23 +954,17 @@ use_interactive = True #expose_user_email = False # -- Beta features + # Enable new run workflow form #run_workflow_toolform_upgrade = False # Enable Galaxy to communicate directly with a sequencer #enable_sequencer_communication = False -# Separate tool command from rest of job script so tool dependencies -# don't interfer with metadata generation. -# Despite the name, this feature is enabled by default -# in 16.01 and the option will go away in the future. -#enable_beta_tool_command_isolation = True - # Enable the new interface for installing tools from Tool Shed # via the API. Admin menu will list both if enabled. #enable_beta_ts_api_install = False - # Set the following to a number of threads greater than 1 to spawn # a Python task queue for dealing with large tool submissions (either # through the tool form or as part of an individual workflow step across @@ -1184,14 +1176,14 @@ use_interactive = True # if running many handlers. #cache_user_job_count = False -# ToolBox filtering +# -- ToolBox filtering # Modules from lib/galaxy/tools/toolbox/filters/ can be specified in # the following lines. tool_* filters will be applied for all users # and can not be changed by them. user_tool_* filters will be shown -# under user preferences and can be toogled on and off by +# under user preferences and can be toggled on and off at # runtime. Example shown below are not real defaults (no custom -# filters applied by defualt) but can be enabled with by renaming the +# filters are applied by default), but can be enabled by renaming the # example.py.sample in the filters directory to example.py. #tool_filters = @@ -1206,7 +1198,7 @@ use_interactive = True # modifying the following option. #toolbox_filter_base_modules = galaxy.tools.toolbox.filters,galaxy.tools.filters -# Galaxy Application Internal Message Queue +# -- Galaxy Application Internal Message Queue # Galaxy uses AMQP internally TODO more documentation on what for. # For examples, see http://ask.github.io/kombu/userguide/connections.html diff --git a/config/plugins/visualizations/charts/static/app.css b/config/plugins/visualizations/charts/static/app.css index b2a1c0096fd..483fd737a30 100644 --- a/config/plugins/visualizations/charts/static/app.css +++ b/config/plugins/visualizations/charts/static/app.css @@ -1,38 +1,69 @@ -.charts-tooltip { - position: absolute; - text-align: center; - padding: 3px 5px 3px 5px; - font: 12px sans-serif; - background: white; - border: 1px solid gray; - border-radius: 4px; - pointer-events: none; +.charts-viewer .ui-message { + position: absolute; + width: calc(100% - 20px); + z-index: 100; +} + +.charts-description { + margin-bottom: 20px; +} +.charts-description-image-td { + vertical-align: top; +} + +.charts-types .nav-tabs { + margin-bottom: 10px; +} + +.charts-description-image { + width: 50px; + height: 43px; + margin-right: 10px; +} + +.charts-description-title { + font-weight: bold; +} + +.charts-description-text { + word-wrap: break-word; +} + +.charts-tooltip { + position: absolute; + text-align: center; + padding: 3px 5px 3px 5px; + font: 12px sans-serif; + background: white; + border: 1px solid gray; + border-radius: 4px; + pointer-events: none; } .charts-tooltip-first { - font-weight: bold; - text-align: left; - padding-right: 5px; + font-weight: bold; + text-align: left; + padding-right: 5px; } .charts-grid .item { - padding: 5px; - margin: 5px; - float: left; - cursor: pointer; - border-radius:5px + padding: 5px; + margin: 5px; + float: left; + cursor: pointer; + border-radius:5px } .charts-grid .current { - border-color:#66afe9; - background-color:#EEEEFF; - outline:0; - -webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075), 0 0 8px rgba(102, 175, 233, 0.6); - box-shadow:inset 0 1px 1px rgba(0,0,0,.075), 0 0 8px rgba(102, 175, 233, 0.6); + border-color:#66afe9; + background-color:#EEEEFF; + outline:0; + -webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075), 0 0 8px rgba(102, 175, 233, 0.6); + box-shadow:inset 0 1px 1px rgba(0,0,0,.075), 0 0 8px rgba(102, 175, 233, 0.6); } .charts-grid .image { - padding: 10px; + padding: 10px; width: 100px; height: 86px; } @@ -49,6 +80,7 @@ font-size: 0.9em; font-weight: bold; padding-bottom: 10px; + clear: both; } .charts-viewport { @@ -62,27 +94,27 @@ } .charts-viewport .text { - position: relative; - margin-left: 5px; - top: -1px; - font-size: 1.0em; - display: inline; + position: relative; + margin-left: 5px; + top: -1px; + font-size: 1.0em; + display: inline; } .charts-viewport .icon { - font-size: 1.2em; - display: inline-block; + font-size: 1.2em; + display: inline-block; } .charts-viewport .charts-viewport-container { - float: left; - display: block; - height: 100%; + float: left; + display: block; + height: 100%; } .charts-viewport .charts-viewport-canvas { - display: block; - width:100%; - min-height: 100px; - height: inherit; + display: block; + width: 100%; + min-height: 100px; + height: inherit; } \ No newline at end of file diff --git a/config/plugins/visualizations/charts/static/app.js b/config/plugins/visualizations/charts/static/app.js index 1f686860b57..be38bf36b1c 100644 --- a/config/plugins/visualizations/charts/static/app.js +++ b/config/plugins/visualizations/charts/static/app.js @@ -1,35 +1,22 @@ /** * Main application class. */ -define( [ 'mvc/ui/ui-modal', 'mvc/ui/ui-portlet', 'mvc/ui/ui-misc', 'utils/utils', - 'plugin/library/jobs', 'plugin/library/datasets', 'plugin/library/storage', 'utils/deferred', - 'plugin/views/viewer', 'plugin/views/editor', - 'plugin/models/config', 'plugin/models/chart', 'plugin/charts/types' ], - function( Modal, Portlet, Ui, Utils, Jobs, Datasets, Storage, Deferred, - ViewerView, EditorView, Config, Chart, Types ) { +define( [ 'mvc/ui/ui-modal', 'mvc/ui/ui-portlet', 'mvc/ui/ui-misc', 'utils/utils', 'plugin/components/storage', 'plugin/components/model', 'utils/deferred', 'plugin/views/viewer', 'plugin/views/editor', 'plugin/charts/types' ], + function( Modal, Portlet, Ui, Utils, Storage, Chart, Deferred, Viewer, Editor, Types ) { return Backbone.View.extend({ initialize: function(options){ this.options = options; this.modal = parent.Galaxy && parent.Galaxy.modal || new Modal.View(); - - // models - this.config = new Config(); - this.types = new Types(); + this.types = Types; this.chart = new Chart(); - - // libraries - this.jobs = new Jobs(this); - this.datasets = new Datasets( this ); this.storage = new Storage( this ); this.deferred = new Deferred(); // views - this.viewer_view = new ViewerView( this ); - this.editor_view = new EditorView( this ); - - // append views - this.$el.append( this.viewer_view.$el ); - this.$el.append( this.editor_view.$el ); + this.viewer = new Viewer( this ); + this.editor = new Editor( this ); + this.$el.append( this.viewer.$el ); + this.$el.append( this.editor.$el ); // pick start screen if ( !this.storage.load() ) { @@ -43,31 +30,25 @@ define( [ 'mvc/ui/ui-modal', 'mvc/ui/ui-portlet', 'mvc/ui/ui-misc', 'utils/utils /** Loads a view and makes sure that all others are hidden */ go: function( view_id ) { $( '.tooltip' ).hide(); - switch ( view_id ) { - case 'editor' : - this.editor_view.show(); - this.viewer_view.hide(); - break; - case 'viewer' : - this.editor_view.hide(); - this.viewer_view.show(); - break; - } - }, - - /** Returns root path */ - chartPath: function( chart_type ) { - var path = chart_type.split( /_(.+)/ ); - if ( path.length >= 2 ) { - return path[ 0 ] + '/' + path[ 1 ]; - } - console.debug( 'FAILED app:chartPath() - Invalid format: ' + chart_type ); + this.viewer.hide(); + this.editor.hide(); + this[ view_id ].show(); }, /** Message */ showModal: function( title, body ) { var self = this; this.modal.show( { title: title, body: body, buttons: { 'Close': function() { self.modal.hide() } } } ); + }, + + /** Split chart type into path components */ + split: function( chart_type ) { + var path = chart_type.split( /_(.+)/ ); + if ( path.length >= 2 ) { + return path[ 0 ] + '/' + path[ 1 ]; + } else { + return chart_type; + } } }); }); \ No newline at end of file diff --git a/config/plugins/visualizations/charts/static/charts/forms/default.js b/config/plugins/visualizations/charts/static/charts/forms/default.js deleted file mode 100644 index 7b3b4eac577..00000000000 --- a/config/plugins/visualizations/charts/static/charts/forms/default.js +++ /dev/null @@ -1,259 +0,0 @@ -define([], function() { - -return { - title : '', - category : '', - library : '', - tag : '', - keywords : '', - settings : { - separator_x : { - title : 'X axis', - type : 'separator' - }, - x_axis_label : { - title : 'Axis label', - info : 'Provide a label for the axis.', - type : 'text', - init : 'X-axis', - placeholder : 'Axis label' - }, - x_axis_type : { - title : 'Axis value type', - info : 'Select the value type of the axis.', - type : 'select', - init : 'auto', - data : [ - { - label : '-- Do not show values --', - value : 'hide', - operations : { - hide : ['x_axis_precision'] - } - }, - { - label : 'Auto', - value : 'auto', - operations : { - hide : ['x_axis_precision'] - } - }, - { - label : 'Float', - value : 'f', - operations : { - show : ['x_axis_precision'] - } - }, - { - label : 'Exponent', - value : 'e', - operations : { - show : ['x_axis_precision'] - } - }, - { - label : 'Integer', - value : 'd', - operations : { - hide : ['x_axis_precision'] - } - }, - { - label : 'Percentage', - value : 'p', - operations : { - show : ['x_axis_precision'] - } - }, - { - label : 'SI-prefix', - value : 's', - operations : { - hide : ['x_axis_precision'] - } - } - ] - }, - x_axis_precision : { - title : 'Axis tick format', - info : 'Select the tick format for the axis.', - type : 'select', - init : '1', - data : [ - { - label : '0.00001', - value : '5' - }, - { - label : '0.0001', - value : '4' - }, - { - label : '0.001', - value : '3' - }, - { - label : '0.01', - value : '2' - }, - { - label : '0.1', - value : '1' - }, - { - label : '1', - value : '0' - } - ] - - }, - separator_y : { - title : 'Y axis', - type : 'separator' - }, - y_axis_label : { - title : 'Axis label', - info : 'Provide a label for the axis.', - type : 'text', - init : 'Y-axis', - placeholder : 'Axis label' - }, - y_axis_type : { - title : 'Axis value type', - info : 'Select the value type of the axis.', - type : 'select', - init : 'auto', - data : [ - { - label : '-- Do not show values --', - value : 'hide', - operations : { - hide : ['y_axis_precision'] - } - }, - { - label : 'Auto', - value : 'auto', - operations : { - hide : ['y_axis_precision'] - } - }, - { - label : 'Float', - value : 'f', - operations : { - show : ['y_axis_precision'] - } - }, - { - label : 'Exponent', - value : 'e', - operations : { - show : ['y_axis_precision'] - } - }, - { - label : 'Integer', - value : 'd', - operations : { - hide : ['y_axis_precision'] - } - }, - { - label : 'Percentage', - value : 'p', - operations : { - show : ['y_axis_precision'] - } - }, - { - label : 'SI-prefix', - value : 's', - operations : { - hide : ['y_axis_precision'] - } - } - ] - }, - y_axis_precision : { - title : 'Axis tick format', - info : 'Select the tick format for the axis.', - type : 'select', - init : '1', - data : [ - { - label : '0.00001', - value : '5' - }, - { - label : '0.0001', - value : '4' - }, - { - label : '0.001', - value : '3' - }, - { - label : '0.01', - value : '2' - }, - { - label : '0.1', - value : '1' - }, - { - label : '1', - value : '0' - } - ] - - }, - separator_legend : { - title : 'Others', - type : 'separator' - }, - show_legend : { - title : 'Show legend', - info : 'Would you like to add a legend?', - type : 'select', - display : 'radiobutton', - init : 'true', - data : [ - { - label : 'Yes', - value : 'true' - }, - { - label : 'No', - value : 'false' - } - ] - }, - use_panels : { - title : 'Use multi-panels', - info : 'Would you like to separate your data into individual panels?', - type : 'select', - display : 'radiobutton', - init : 'false', - data : [ - { - label : 'Yes', - value : 'true' - }, - { - label : 'No', - value : 'false' - } - ] - } - }, - series : [{ - name : 'key', - label : 'Provide a label', - type : 'text', - placeholder : 'Data label' - }] -}; - -}); \ No newline at end of file diff --git a/config/plugins/visualizations/charts/static/charts/jqplot/bar/config.js b/config/plugins/visualizations/charts/static/charts/jqplot/bar/config.js index cdeb37129ba..322c87a4445 100644 --- a/config/plugins/visualizations/charts/static/charts/jqplot/bar/config.js +++ b/config/plugins/visualizations/charts/static/charts/jqplot/bar/config.js @@ -1,20 +1,20 @@ -define(['plugin/charts/jqplot/common/config'], function(plot_config) { - -return $.extend(true, {}, plot_config, { - title : 'Regular', - category : 'Bar diagrams', - columns : { - x : { - title : 'Values for x-axis', - is_label : true, - is_auto : true, - is_unique : true - }, - y : { - title : 'Values for y-axis', - is_numeric : true +define( [ 'plugin/charts/jqplot/common/config' ], function( plot_config ) { + return $.extend( true, {}, plot_config, { + title : 'Regular', + category : 'Bar diagrams', + groups : { + x : { + label : 'Values for x-axis', + type : 'data_column', + is_label : true, + is_auto : true, + is_unique : true + }, + y : { + label : 'Values for y-axis', + type : 'data_column', + is_numeric : true + } } - } -}); - + }); }); \ No newline at end of file diff --git a/config/plugins/visualizations/charts/static/charts/jqplot/bar/wrapper.js b/config/plugins/visualizations/charts/static/charts/jqplot/bar/wrapper.js index c37d08dc4b9..55c8dc3f8da 100644 --- a/config/plugins/visualizations/charts/static/charts/jqplot/bar/wrapper.js +++ b/config/plugins/visualizations/charts/static/charts/jqplot/bar/wrapper.js @@ -1,26 +1,22 @@ -// dependencies -define(['plugin/charts/jqplot/common/wrapper'], function(Plot) { - -// widget -return Backbone.Model.extend({ - initialize: function(app, options) { - options.makeConfig = function(groups, plot_config){ - $.extend(true, plot_config, { - seriesDefaults: { - renderer : $.jqplot.BarRenderer - }, - axes: { - xaxis: { - min : -1 +define( [ 'plugin/charts/jqplot/common/wrapper' ], function( Plot ) { + return Backbone.Model.extend({ + initialize: function( app, options ) { + options.makeConfig = function( groups, plot_config ){ + $.extend( true, plot_config, { + seriesDefaults: { + renderer : $.jqplot.BarRenderer }, - yaxis: { - pad : 1.2 + axes: { + xaxis: { + min : -1 + }, + yaxis: { + pad : 1.2 + } } - } - }); - }; - new Plot(app, options); - } -}); - + }); + }; + new Plot( app, options ); + } + }); }); \ No newline at end of file diff --git a/config/plugins/visualizations/charts/static/charts/jqplot/boxplot/config.js b/config/plugins/visualizations/charts/static/charts/jqplot/boxplot/config.js index 72b6c994d64..2892ce1e854 100644 --- a/config/plugins/visualizations/charts/static/charts/jqplot/boxplot/config.js +++ b/config/plugins/visualizations/charts/static/charts/jqplot/boxplot/config.js @@ -1,23 +1,16 @@ -define(['plugin/charts/jqplot/common/config'], function(plot_config) { - -return $.extend(true, {}, plot_config, { - title : 'Box plot', - category : 'Data processing (requires \'charts\' tool from Toolshed)', - library : 'jqPlot', - tag : 'div', - execute : 'boxplot', - keywords : 'small medium large', - columns : { - y : { - title : 'Observations', - is_numeric : true +define( [ 'plugin/charts/jqplot/common/config' ], function( plot_config ) { + return $.extend( true, {}, plot_config, { + title : 'Box plot', + category : 'Data processing (requires \'charts\' tool from Toolshed)', + library : 'jqPlot', + tag : 'div', + keywords : 'jqplot default', + groups : { + y : { + label : 'Observations', + type : 'data_column', + is_numeric : true + } } - }, - settings : { - show_legend : { - init : 'false' - } - } -}); - + }); }); \ No newline at end of file diff --git a/config/plugins/visualizations/charts/static/charts/jqplot/boxplot/wrapper.js b/config/plugins/visualizations/charts/static/charts/jqplot/boxplot/wrapper.js index 122353f3ca2..df096f88dc0 100644 --- a/config/plugins/visualizations/charts/static/charts/jqplot/boxplot/wrapper.js +++ b/config/plugins/visualizations/charts/static/charts/jqplot/boxplot/wrapper.js @@ -1,127 +1,98 @@ -// dependencies -define(['plugin/charts/jqplot/common/wrapper', 'plugin/charts/tools'], function(Plot, Tools) { - -// widget -return Backbone.View.extend( -{ - // initialize - initialize: function(app, options) { - // get request dictionary - var request_dictionary = options.request_dictionary; - var chart = options.chart; - - // modify request - var index = 0; - for (var i in request_dictionary.groups) { - var group = request_dictionary.groups[i]; - group.columns = null; - group.columns = { - x: { - index: index++ - } - } - } - - // create plot - var plot = new Plot(app, { - process : options.process, - chart : options.chart, - request_dictionary : options.request_dictionary, - canvas_list : options.canvas_list, - makeConfig : function(groups, plot_config){ - var boundary = Tools.getDomains(groups, 'x'); - $.extend(true, plot_config, { - seriesDefaults: { - renderer: $.jqplot.OHLCRenderer, - rendererOptions : { - candleStick : true, - fillUpBody : true, - fillDownBody : true +define( [ 'plugin/charts/jqplot/common/wrapper', 'plugin/components/jobs', 'plugin/charts/utilities/tabular-utilities' ], function( Plot, Jobs, Utilities ) { + return Backbone.View.extend({ + initialize: function( app, options ) { + Jobs.request( app, Utilities.buildJobDictionary( 'boxplot', app.chart ), function( dataset ) { + var request_dictionary = Utilities.buildRequestDictionary( app.chart, dataset.id ); + var chart = options.chart; + var index = 0; + _.each( request_dictionary.groups, function( group ) { + group.columns = { x: { index : index++ } }; + }); + var plot = new Plot( app, { + process : options.process, + chart : options.chart, + request_dictionary : request_dictionary, + canvas_list : options.canvas_list, + makeConfig : function( groups, plot_config ){ + var boundary = Utilities.getDomains( groups, 'x' ); + $.extend( true, plot_config, { + seriesDefaults: { + renderer: $.jqplot.OHLCRenderer, + rendererOptions : { + candleStick : true, + fillUpBody : true, + fillDownBody : true + } + }, + axes : { + xaxis: { + min: -1, + max: groups.length + 0.01 + }, + yaxis: { + min: boundary.x.min, + max: boundary.x.max + } + } + }); + }, + makeCategories: function( groups ) { + var x_labels = []; + for ( var group_index in groups ) { + x_labels.push( groups[ group_index ].key ); + } + Utilities.mapCategories ( groups, x_labels ); + return { + array: { + x : x_labels + } } }, - axes : { - xaxis: { - min: -1, - max: groups.length + 0.01 - }, - yaxis: { - min: boundary.x.min, - max: boundary.x.max + makeSeriesLabels : function ( groups, plot_config ) { + return [ { label : 'Boxplot values' } ]; + }, + makeSeries: function ( groups ) { + /*/ example data + var catOHLC = [ + [0, 138.7, 139.68, 135.18, 135.4], + [1, 143.46, 144.66, 139.79, 140.02], + [2, 140.67, 143.56, 132.88, 142.44], + [3, 136.01, 139.5, 134.53, 139.48] + ]; + return [catOHLC];*/ + + // plot data + var plot_data = []; + + // check group length + if ( groups.length == 0 || groups[0].values.length < 5 ) { + chart.state( 'failed', 'Boxplot data could not be found.' ); + return [ plot_data ]; } + + // loop through data groups + var indeces = [ 2, 4, 0, 1 ]; + for ( var group_index in groups ) { + var group = groups[ group_index ]; + var point = []; + point.push( parseInt( group_index ) ); + for ( var key in indeces ) { + point.push( group.values[ indeces[ key ] ].x ); + } + plot_data.push( point ); + } + + // HACK: the boxplot renderer has an issue with single elements + var point = []; + point[ 0 ] = plot_data.length; + for ( var key in indeces ) { + point.push( 0 ); + } + plot_data.push ( point ); + return [ plot_data ]; } }); - }, - makeCategories: function(groups) { - // define custom category labels - var x_labels = []; - for (var group_index in groups) { - x_labels.push(groups[group_index].key); - } - - // use default mapping - Tools.mapCategories (groups, x_labels); - - // return labels array for x axis - return { - array: { - x : x_labels - } - } - }, - makeSeriesLabels : function (groups, plot_config) { - return [{ - label: 'Boxplot values' - }]; - }, - makeSeries: function (groups) { - /*/ example data - var catOHLC = [ - [0, 138.7, 139.68, 135.18, 135.4], - [1, 143.46, 144.66, 139.79, 140.02], - [2, 140.67, 143.56, 132.88, 142.44], - [3, 136.01, 139.5, 134.53, 139.48] - ]; - return [catOHLC];*/ - - // plot data - var plot_data = []; - - // check group length - if (groups.length == 0 || groups[0].values.length < 5) { - chart.state('failed', 'Boxplot data could not be found.'); - return [plot_data]; - } - - // loop through data groups - var indeces = [2, 4, 0, 1]; - for (var group_index in groups) { - // get group - var group = groups[group_index]; - - // format chart data - var point = []; - point.push(parseInt(group_index)); - for (var key in indeces) { - point.push(group.values[indeces[key]].x); - } - - // add to data - plot_data.push (point); - } - - // HACK: the boxplot renderer has an issue with single elements - var point = []; - point[0] = plot_data.length; - for (var key in indeces) { - point.push(0); - } - plot_data.push (point); - - // return - return [plot_data]; - } - }); - } -}); - + }, function() { options.process.reject() } ); + } + }); }); diff --git a/config/plugins/visualizations/charts/static/charts/jqplot/common/config.js b/config/plugins/visualizations/charts/static/charts/jqplot/common/config.js index 3d6c9f7b4b6..5c20a977cc6 100644 --- a/config/plugins/visualizations/charts/static/charts/jqplot/common/config.js +++ b/config/plugins/visualizations/charts/static/charts/jqplot/common/config.js @@ -1,52 +1,22 @@ -define(['plugin/charts/forms/default'], function(config_default) { - -return $.extend(true, {}, config_default, { - title : '', - category : '', - library : 'jqPlot', - tag : 'div', - zoomable : true, - keywords : 'medium', - settings : { - separator_grid : { - title : 'Grids', - type : 'separator' - }, - x_axis_grid : { - title : 'Axis grid', - info : 'Would you like to show grid lines for the X axis?', - type : 'select', - display : 'radiobutton', - init : 'false', - data : [ - { - label : 'On', - value : 'true' - }, - { - label : 'Off', - value : 'false' - } - ] - }, - y_axis_grid : { - title : 'Axis grid', - info : 'Would you like to show grid lines for the Y axis?', - type : 'select', - display : 'radiobutton', - init : 'true', - data : [ - { - label : 'On', - value : 'true' - }, - { - label : 'Off', - value : 'false' - } - ] +define( [ 'plugin/charts/utilities/tabular-form' ], function( default_config ) { + return $.extend(true, {}, default_config, { + title : '', + category : '', + library : 'jqPlot', + tag : 'div', + zoomable : true, + keywords : 'jqplot', + settings : { + x_axis_grid : { + label : 'Axis grid', + help : 'Would you like to show grid lines for the X axis?', + type : 'boolean' + }, + y_axis_grid : { + label : 'Axis grid', + help : 'Would you like to show grid lines for the Y axis?', + type : 'boolean' + } } - } -}); - + }); }); \ No newline at end of file diff --git a/config/plugins/visualizations/charts/static/charts/jqplot/common/plot-config.js b/config/plugins/visualizations/charts/static/charts/jqplot/common/plot-config.js index 27f589b475b..a0c8635c7dc 100644 --- a/config/plugins/visualizations/charts/static/charts/jqplot/common/plot-config.js +++ b/config/plugins/visualizations/charts/static/charts/jqplot/common/plot-config.js @@ -1,115 +1,110 @@ -// dependencies -define([], function() { +define( [], function() { + return function( chart ) { -// highcharts configuration -return function(chart) { - - // get chart settings - var settings = chart.settings; - var plot_config = { - enablePlugins: true, - seriesColors: d3.scale.category20().range(), - seriesDefaults: { - renderer : $.jqplot.LineRenderer, - //lineWidth : 1, // width of the line in pixels. - shadow : false, // show shadow or not. - showLine : true, // whether to render the line segments or not. - rendererOptions: { - shadowDepth : 0, - barWidth : 3, - barPadding : 3 + // get chart settings + var settings = chart.settings; + var plot_config = { + enablePlugins: true, + seriesColors: d3.scale.category20().range(), + seriesDefaults: { + renderer : $.jqplot.LineRenderer, + //lineWidth : 1, // width of the line in pixels. + shadow : false, // show shadow or not. + showLine : true, // whether to render the line segments or not. + rendererOptions: { + shadowDepth : 0, + barWidth : 3, + barPadding : 3 + }, + markerRenderer : $.jqplot.MarkerRenderer, + markerOptions: { + show : false, // wether to show data point markers. + style : 'filledCircle', // circle, diamond, square, filledCircle. + // filledDiamond or filledSquare. + lineWidth : 0, // width of the stroke drawing the marker. + size : 10, // size (diameter, edge length, etc.) of the marker. + shadow : false, // wether to draw shadow on marker or not. + shadowAngle : 45, // angle of the shadow. Clockwise from x axis. + shadowOffset : 1, // offset from the line of the shadow, + shadowDepth : 3, // number of strokes to make when drawing shadow. Each stroke + // offset by shadowOffset from the last. + shadowAlpha : 0.07 // opacity of the shadow + } }, - markerRenderer : $.jqplot.MarkerRenderer, - markerOptions: { - show : false, // wether to show data point markers. - style : 'filledCircle', // circle, diamond, square, filledCircle. - // filledDiamond or filledSquare. - lineWidth : 0, // width of the stroke drawing the marker. - size : 10, // size (diameter, edge length, etc.) of the marker. - shadow : false, // wether to draw shadow on marker or not. - shadowAngle : 45, // angle of the shadow. Clockwise from x axis. - shadowOffset : 1, // offset from the line of the shadow, - shadowDepth : 3, // number of strokes to make when drawing shadow. Each stroke - // offset by shadowOffset from the last. - shadowAlpha : 0.07 // opacity of the shadow - } - }, - - axesDefaults: { - labelRenderer : $.jqplot.CanvasAxisLabelRenderer, - labelOptions: { - fontSize : '12pt', - textColor : '#000000' - }, - tickRenderer : $.jqplot.CanvasAxisTickRenderer , - tickOptions: { - fontSize : '12pt', - textColor : '#000000' - } - }, - - axes: { - xaxis: { - label : chart.settings.get('x_axis_label'), - tickRenderer : $.jqplot.CanvasAxisTickRenderer, + + axesDefaults: { + labelRenderer : $.jqplot.CanvasAxisLabelRenderer, + labelOptions: { + fontSize : '12pt', + textColor : '#000000' + }, + tickRenderer : $.jqplot.CanvasAxisTickRenderer , tickOptions: { - angle : chart.settings.get('use_panels') === 'true' ? 0 : -30, - showGridline : chart.settings.get('x_axis_grid') === 'true' - }, - pad : 0 + fontSize : '12pt', + textColor : '#000000' + } }, - yaxis: { - label : chart.settings.get('y_axis_label'), - tickOptions : { - showGridline : chart.settings.get('y_axis_grid') === 'true' + + axes: { + xaxis: { + label : chart.settings.get( 'x_axis_label' ), + tickRenderer : $.jqplot.CanvasAxisTickRenderer, + tickOptions: { + angle : chart.settings.get( 'use_panels' ) === 'true' ? 0 : -30, + showGridline : chart.settings.get( 'x_axis_grid' ) === 'true' + }, + pad : 0 }, - pad : 0 - } - }, - - grid: { - background : '#FFFFFF', - borderWidth : 0, - shadow : false - }, - - cursor: { - show : true, - zoom : true, - showTooltip : false, - style : 'pointer' - }, - - highlighter: { - show : true, - showMarker : false, - tooltipAxes : 'xy' - }, - - series: [] - }; - - // show the legend and put it outside the grid - if (chart.settings.get('show_legend') == 'true') { - plot_config.legend = { - renderer : $.jqplot.EnhancedLegendRenderer, - show : true, - placement : 'outsideGrid', - location : 'n', - rendererOptions: { - textColor : '#000000', - fontSize : '12pt', - border : 'none', - shadowAlpha : 1, - background : 'rgba(255, 255, 255, 0.9)', - fontFamily : 'Arial', - numberRows : 1 - } + yaxis: { + label : chart.settings.get( 'y_axis_label' ), + tickOptions : { + showGridline : chart.settings.get( 'y_axis_grid' ) === 'true' + }, + pad : 0 + } + }, + + grid: { + background : '#FFFFFF', + borderWidth : 0, + shadow : false + }, + + cursor: { + show : true, + zoom : true, + showTooltip : false, + style : 'pointer' + }, + + highlighter: { + show : true, + showMarker : false, + tooltipAxes : 'xy' + }, + + series: [] }; - } - - // callback - return plot_config; -}; + + // show the legend and put it outside the grid + if ( chart.settings.get( 'show_legend' ) == 'true' ) { + plot_config.legend = { + renderer : $.jqplot.EnhancedLegendRenderer, + show : true, + placement : 'outsideGrid', + location : 'n', + rendererOptions: { + textColor : '#000000', + fontSize : '12pt', + border : 'none', + shadowAlpha : 1, + background : 'rgba(255, 255, 255, 0.9)', + fontFamily : 'Arial', + numberRows : 1 + } + }; + } + return plot_config; + }; }); \ No newline at end of file diff --git a/config/plugins/visualizations/charts/static/charts/jqplot/common/wrapper.js b/config/plugins/visualizations/charts/static/charts/jqplot/common/wrapper.js index 061e25803d9..7e0bf6b71b4 100644 --- a/config/plugins/visualizations/charts/static/charts/jqplot/common/wrapper.js +++ b/config/plugins/visualizations/charts/static/charts/jqplot/common/wrapper.js @@ -1,138 +1,105 @@ -// dependencies -define(['plugin/charts/jqplot/common/plot-config', 'plugin/charts/tools'], function(configmaker, Tools) { +/** This is the common wrapper for jqplot based visualizations. */ +define( [ 'plugin/charts/jqplot/common/plot-config', 'plugin/charts/utilities/tabular-utilities' ], function( configmaker, Utilities ) { + return Backbone.View.extend({ + initialize: function( app, options ) { + this.options = options; + var self = this; + options.render = function( canvas_id, groups ) { + return self.render( canvas_id, groups ) + }; + Utilities.panelHelper( options ); + }, -/** - * This is the common wrapper for jqplot based visualizations. - */ -return Backbone.View.extend({ - // initialize - initialize: function(app, options) { - // get parameters - this.options = options; - - // define render function - var self = this; - options.render = function(canvas_id, groups) { - return self.render(canvas_id, groups) - }; - - // call panel helper - Tools.panelHelper(app, options); - }, - - // draw all data into a single canvas - render: function(canvas_id, groups) { - // get parameters - var chart = this.options.chart; - var makeCategories = this.options.makeCategories; - var makeSeries = this.options.makeSeries; - var makeSeriesLabels = this.options.makeSeriesLabels; - var makeConfig = this.options.makeConfig; - - // create configuration - var plot_config = configmaker(chart); - var plot_data = []; - - // draw plot - try { - // make custom categories call - this._makeAxes(groups, plot_config, chart.settings); - - // make custom series call - if (makeSeriesLabels) { - plot_config.series = makeSeriesLabels(groups, plot_config); - } else { - plot_config.series = this._makeSeriesLabels(groups); - } - - // make custom series call - if (makeSeries) { - plot_data = makeSeries(groups, plot_config); - } else { - plot_data = Tools.makeSeries(groups); - } - - // make custom config call - if (makeConfig) { - makeConfig(groups, plot_config); - } - - // check chart state - if (chart.get('state') == 'failed') { + /** Draw all data into a single canvas */ + render: function( canvas_id, groups ) { + var chart = this.options.chart; + var makeCategories = this.options.makeCategories; + var makeSeries = this.options.makeSeries; + var makeSeriesLabels = this.options.makeSeriesLabels; + var makeConfig = this.options.makeConfig; + var plot_config = configmaker( chart ); + var plot_data = []; + try { + this._makeAxes( groups, plot_config, chart.settings ); + if ( makeSeriesLabels ) { + plot_config.series = makeSeriesLabels( groups, plot_config ); + } else { + plot_config.series = this._makeSeriesLabels( groups ); + } + if ( makeSeries ) { + plot_data = makeSeries( groups, plot_config ); + } else { + plot_data = Utilities.makeSeries( groups ); + } + if ( makeConfig ) { + makeConfig( groups, plot_config ); + } + if ( chart.get( 'state' ) == 'failed' ) { + return false; + } + + // draw graph with default options, overwriting with passed options + function drawGraph ( opts ) { + var canvas = $( '#' + canvas_id ); + if ( canvas.length == 0 ) { + return; + } + canvas.empty(); + var plot_cnf = _.extend( _.clone( plot_config ), opts || {} ); + return plot = $.jqplot( canvas_id, plot_data, plot_cnf ); + } + + // draw plot + var plot = drawGraph(); + $( window ).on( 'resize', function () { drawGraph() } ); + return true; + } catch ( err ) { + this._handleError( chart, err ); return false; } - - // draw graph with default options, overwriting with passed options - function drawGraph (opts) { - var canvas = $('#' + canvas_id); - if(canvas.length == 0) { - return; - } - canvas.empty(); - var plot_cnf = _.extend(_.clone(plot_config), opts || {}); - return plot = $.jqplot(canvas_id, plot_data, plot_cnf); - } - - // draw plot - var plot = drawGraph(); - - // catch window resize event - $(window).on('resize', function () { - drawGraph(); - }); - - return true; - } catch (err) { - this._handleError(chart, err); - return false; - } - }, - - // make series labels - _makeSeriesLabels: function(groups, plot_config) { - var series = []; - for (var group_index in groups) { - series.push({ - label: groups[group_index].key - }); - } - return series; - }, - - // create axes formatting - _makeAxes: function(groups, plot_config, settings) { - // result - var makeCategories = this.options.makeCategories; - var categories; - if (makeCategories) { - categories = makeCategories(groups, plot_config); - } else { - categories = Tools.makeCategories(groups); - } - - // make axes - function makeAxis (id) { - Tools.makeTickFormat({ - categories : categories.array[id], - type : settings.get(id + '_axis_type'), - precision : settings.get(id + '_axis_precision'), - formatter : function(formatter) { - if (formatter) { - plot_config.axes[id + 'axis'].tickOptions.formatter = function(format, value) { - return formatter(value); - }; - } - } - }); - }; - makeAxis('x'); - makeAxis('y'); - }, - - // handle error - _handleError: function(chart, err) { - chart.state('failed', err); - } -}); + }, + /** Make series labels */ + _makeSeriesLabels: function( groups, plot_config ) { + var series = []; + for ( var group_index in groups ) { + series.push( { label: groups[ group_index ].key } ); + } + return series; + }, + + /** Create axes formatting */ + _makeAxes: function( groups, plot_config, settings ) { + var makeCategories = this.options.makeCategories; + var categories; + if ( makeCategories ) { + categories = makeCategories( groups, plot_config ); + } else { + categories = Utilities.makeCategories( groups ); + } + + // make axes + function makeAxis (id) { + Utilities.makeTickFormat({ + categories : categories.array[ id ], + type : settings.get( id + '_axis_type|type' ), + precision : settings.get( id + '_axis_type|precision' ), + formatter : function( formatter ) { + if ( formatter ) { + plot_config.axes[ id + 'axis' ].tickOptions.formatter = function( format, value ) { + return formatter( value ); + }; + } + } + }); + }; + makeAxis( 'x' ); + makeAxis( 'y' ); + }, + + /** Handle error */ + _handleError: function( chart, err ) { + chart.state( 'failed', err ); + } + }); }); \ No newline at end of file diff --git a/config/plugins/visualizations/charts/static/charts/jqplot/histogram_discrete/config.js b/config/plugins/visualizations/charts/static/charts/jqplot/histogram_discrete/config.js index 33c92da1432..a2a7b038db7 100644 --- a/config/plugins/visualizations/charts/static/charts/jqplot/histogram_discrete/config.js +++ b/config/plugins/visualizations/charts/static/charts/jqplot/histogram_discrete/config.js @@ -1,24 +1,14 @@ -define(['plugin/charts/jqplot/common/config'], function(default_config) { - -return $.extend(true, {}, default_config, { - title : 'Discrete Histogram', - category : 'Data processing (requires \'charts\' tool from Toolshed)', - execute : 'histogramdiscrete', - keywords : 'small medium large', - columns : { - x : { - title : 'Observations', - is_label : true +define( [ 'plugin/charts/jqplot/common/config' ], function( default_config ) { + return $.extend( true, {}, default_config, { + title : 'Discrete Histogram', + category : 'Data processing (requires \'charts\' tool from Toolshed)', + keywords : 'jqplot default', + groups : { + x : { + label : 'Observations', + type : 'data_column', + is_label : true + } } - }, - settings : { - x_axis_label : { - init : 'Breaks' - }, - y_axis_label : { - init : 'Density' - } - } -}); - + }); }); \ No newline at end of file diff --git a/config/plugins/visualizations/charts/static/charts/jqplot/histogram_discrete/wrapper.js b/config/plugins/visualizations/charts/static/charts/jqplot/histogram_discrete/wrapper.js index b030c237f78..2e6c6c7a6fa 100644 --- a/config/plugins/visualizations/charts/static/charts/jqplot/histogram_discrete/wrapper.js +++ b/config/plugins/visualizations/charts/static/charts/jqplot/histogram_discrete/wrapper.js @@ -1,57 +1,25 @@ -// dependencies -define(['plugin/charts/jqplot/common/wrapper'], function(Plot) { - -// widget -return Backbone.Model.extend({ - initialize: function(app, options) { - // link request - var request_dictionary = options.request_dictionary; - - // configure request - var index = 1; - var tmp_dict = { - id : request_dictionary.id, - groups : [] - }; - - // configure groups - for (var group_index in request_dictionary.groups) { - var group = request_dictionary.groups[group_index]; - tmp_dict.groups.push({ - key : group.key, - columns : { - x: { - index : 0, - is_label : true - }, - y: { - index : index++ - } - } +define( [ 'plugin/charts/utilities/tabular-utilities', 'plugin/components/jobs', 'plugin/charts/jqplot/common/wrapper' ], function( Utilities, Jobs, Plot ) { + return Backbone.Model.extend({ + initialize: function( app, options ) { + Jobs.request( app, Utilities.buildJobDictionary( 'histogramdiscrete', app.chart ), function( dataset ) { + var request_dictionary = Utilities.buildRequestDictionary( app.chart, dataset.id ); + var index = 1; + var tmp_dict = { id : request_dictionary.id, groups : [] }; + _.each( request_dictionary.groups, function( group ) { + tmp_dict.groups.push({ + key : group.key, + columns : { x: { index : 0, is_label : true }, y: { index : index++ } } + }); + }); + options.request_dictionary = tmp_dict; + options.makeConfig = function( groups, plot_config ){ + $.extend( true, plot_config, { + seriesDefaults: { renderer: $.jqplot.BarRenderer }, + axes: { xaxis: { min : -1 }, yaxis: { pad : 1.2 } } + }); + }; + new Plot( app, options ); }); } - - // add new request dictionary - options.request_dictionary = tmp_dict; - - // add config maker - options.makeConfig = function(groups, plot_config){ - $.extend(true, plot_config, { - seriesDefaults: { - renderer : $.jqplot.BarRenderer - }, - axes: { - xaxis: { - min : -1 - }, - yaxis: { - pad : 1.2 - } - } - }); - }; - new Plot(app, options); - } -}); - + }); }); \ No newline at end of file diff --git a/config/plugins/visualizations/charts/static/charts/jqplot/line/config.js b/config/plugins/visualizations/charts/static/charts/jqplot/line/config.js index 928f6918a57..6de953aeb4c 100644 --- a/config/plugins/visualizations/charts/static/charts/jqplot/line/config.js +++ b/config/plugins/visualizations/charts/static/charts/jqplot/line/config.js @@ -1,20 +1,20 @@ -define(['plugin/charts/jqplot/common/config'], function(plot_config) { - -return $.extend(true, {}, plot_config, { - title : 'Line chart', - category : 'Others', - columns : { - x : { - title : 'Values for x-axis', - is_label : true, - is_auto : true, - is_unique : true - }, - y : { - title : 'Values for y-axis', - is_numeric : true +define( [ 'plugin/charts/jqplot/common/config' ], function( plot_config ) { + return $.extend( true, {}, plot_config, { + title : 'Line chart', + category : 'Others', + groups : { + x : { + label : 'Values for x-axis', + type : 'data_column', + is_label : true, + is_auto : true, + is_unique : true + }, + y : { + label : 'Values for y-axis', + type : 'data_column', + is_numeric : true + } } - } -}); - + }); }); \ No newline at end of file diff --git a/config/plugins/visualizations/charts/static/charts/jqplot/line/wrapper.js b/config/plugins/visualizations/charts/static/charts/jqplot/line/wrapper.js index 312012695b8..669b6529898 100644 --- a/config/plugins/visualizations/charts/static/charts/jqplot/line/wrapper.js +++ b/config/plugins/visualizations/charts/static/charts/jqplot/line/wrapper.js @@ -1,11 +1,7 @@ -// dependencies -define(['plugin/charts/jqplot/common/wrapper'], function(Plot) { - -// widget -return Backbone.Model.extend({ - initialize: function(app, options) { - new Plot(app, options); - } -}); - +define( [ 'plugin/charts/jqplot/common/wrapper' ], function( Plot ) { + return Backbone.Model.extend({ + initialize: function( app, options ) { + new Plot( app, options ); + } + }); }); \ No newline at end of file diff --git a/config/plugins/visualizations/charts/static/charts/jqplot/scatter/config.js b/config/plugins/visualizations/charts/static/charts/jqplot/scatter/config.js index 94bf5e5e0ff..a815071ff41 100644 --- a/config/plugins/visualizations/charts/static/charts/jqplot/scatter/config.js +++ b/config/plugins/visualizations/charts/static/charts/jqplot/scatter/config.js @@ -1,23 +1,18 @@ -define(['plugin/charts/jqplot/common/config'], function(plot_config) { - -return $.extend(true, {}, plot_config, { - title : 'Scatter plot', - category : 'Others', - columns : { - x : { - title : 'Values for x-axis', - is_numeric : true - }, - y : { - title : 'Values for y-axis', - is_numeric : true +define( [ 'plugin/charts/jqplot/common/config' ], function( plot_config ) { + return $.extend( true, {}, plot_config, { + title : 'Scatter plot', + category : 'Others', + groups : { + x : { + label : 'Values for x-axis', + type : 'data_column', + is_numeric : true + }, + y : { + label : 'Values for y-axis', + type : 'data_column', + is_numeric : true + } } - }, - settings : { - x_axis_grid : { - init : 'true' - } - } -}); - + }); }); \ No newline at end of file diff --git a/config/plugins/visualizations/charts/static/charts/jqplot/scatter/wrapper.js b/config/plugins/visualizations/charts/static/charts/jqplot/scatter/wrapper.js index 4c57252ce62..effb9ead43e 100644 --- a/config/plugins/visualizations/charts/static/charts/jqplot/scatter/wrapper.js +++ b/config/plugins/visualizations/charts/static/charts/jqplot/scatter/wrapper.js @@ -1,22 +1,18 @@ -// dependencies -define(['plugin/charts/jqplot/common/wrapper'], function(Plot) { - -// widget -return Backbone.Model.extend({ - initialize: function(app, options) { - options.makeConfig = function(groups, plot_config){ - $.extend(true, plot_config, { - seriesDefaults: { - renderer: $.jqplot.LineRenderer, - showLine: false, - markerOptions : { - show : true +define( [ 'plugin/charts/jqplot/common/wrapper' ], function( Plot ) { + return Backbone.Model.extend({ + initialize: function( app, options ) { + options.makeConfig = function( groups, plot_config ) { + $.extend( true, plot_config, { + seriesDefaults: { + renderer: $.jqplot.LineRenderer, + showLine: false, + markerOptions : { + show : true + } } - } - }); - }; - new Plot(app, options); - } -}); - + }); + }; + new Plot( app, options ); + } + }); }); \ No newline at end of file diff --git a/config/plugins/visualizations/charts/static/charts/nvd3/bar/config.js b/config/plugins/visualizations/charts/static/charts/nvd3/bar/config.js index bd3efdcb588..6edd849d72f 100644 --- a/config/plugins/visualizations/charts/static/charts/nvd3/bar/config.js +++ b/config/plugins/visualizations/charts/static/charts/nvd3/bar/config.js @@ -1,20 +1,20 @@ -define(['plugin/charts/nvd3/common/config'], function(nvd3_config) { - -return $.extend(true, {}, nvd3_config, { - title : 'Regular', - category : 'Bar diagrams', - columns : { - x : { - title : 'Values for x-axis', - is_label : true, - is_auto : true, - is_unique : true - }, - y : { - title : 'Values for y-axis', - is_numeric : true +define( [ 'plugin/charts/nvd3/common/config' ], function( nvd3_config ) { + return $.extend(true, {}, nvd3_config, { + title : 'Regular', + category : 'Bar diagrams', + groups : { + x : { + label : 'Values for x-axis', + type : 'data_column', + is_label : true, + is_auto : true, + is_unique : true + }, + y : { + label : 'Values for y-axis', + type : 'data_column', + is_numeric : true + } } - } -}); - + }); }); \ No newline at end of file diff --git a/config/plugins/visualizations/charts/static/charts/nvd3/bar/wrapper.js b/config/plugins/visualizations/charts/static/charts/nvd3/bar/wrapper.js index 14332f5a292..9b6a1f17222 100644 --- a/config/plugins/visualizations/charts/static/charts/nvd3/bar/wrapper.js +++ b/config/plugins/visualizations/charts/static/charts/nvd3/bar/wrapper.js @@ -1,12 +1,8 @@ -// dependencies -define(['plugin/charts/nvd3/common/wrapper'], function(NVD3) { - -// widget -return Backbone.Model.extend({ - initialize: function(app, options) { - options.type = 'multiBarChart'; - new NVD3(app, options); - } -}); - +define( [ 'plugin/charts/nvd3/common/wrapper' ], function( NVD3 ) { + return Backbone.Model.extend({ + initialize: function( app, options ) { + options.type = 'multiBarChart'; + new NVD3( app, options ); + } + }); }); \ No newline at end of file diff --git a/config/plugins/visualizations/charts/static/charts/nvd3/bar_horizontal/config.js b/config/plugins/visualizations/charts/static/charts/nvd3/bar_horizontal/config.js index 3510ee3ed9d..fd61adee2fb 100644 --- a/config/plugins/visualizations/charts/static/charts/nvd3/bar_horizontal/config.js +++ b/config/plugins/visualizations/charts/static/charts/nvd3/bar_horizontal/config.js @@ -1,25 +1,20 @@ -define(['plugin/charts/nvd3/common/config'], function(nvd3_config) { - -return $.extend(true, {}, nvd3_config, { - title : 'Horizontal', - category : 'Bar diagrams', - settings : { - x_axis_type : { - init : 'hide' +define( [ 'plugin/charts/nvd3/common/config' ], function( nvd3_config ) { + return $.extend( true, {}, nvd3_config, { + title : 'Horizontal', + category : 'Bar diagrams', + groups : { + x : { + label : 'Values for x-axis', + type : 'data_column', + is_label : true, + is_auto : true, + is_unique : true + }, + y : { + label : 'Values for y-axis', + type : 'data_column', + is_numeric : true + } } - }, - columns : { - x : { - title : 'Values for x-axis', - is_label : true, - is_auto : true, - is_unique : true - }, - y : { - title : 'Values for y-axis', - is_numeric : true - } - } -}); - + }); }); \ No newline at end of file diff --git a/config/plugins/visualizations/charts/static/charts/nvd3/bar_horizontal/wrapper.js b/config/plugins/visualizations/charts/static/charts/nvd3/bar_horizontal/wrapper.js index f2fd4ef1353..5e6f4e15461 100644 --- a/config/plugins/visualizations/charts/static/charts/nvd3/bar_horizontal/wrapper.js +++ b/config/plugins/visualizations/charts/static/charts/nvd3/bar_horizontal/wrapper.js @@ -1,12 +1,8 @@ -// dependencies -define(['plugin/charts/nvd3/common/wrapper'], function(NVD3) { - -// widget -return Backbone.Model.extend({ - initialize: function(app, options) { - options.type = 'multiBarHorizontalChart'; - new NVD3(app, options); - } -}); - +define( [ 'plugin/charts/nvd3/common/wrapper' ], function( NVD3 ) { + return Backbone.Model.extend({ + initialize: function( app, options ) { + options.type = 'multiBarHorizontalChart'; + new NVD3( app, options ); + } + }); }); \ No newline at end of file diff --git a/config/plugins/visualizations/charts/static/charts/nvd3/bar_horizontal_stacked/config.js b/config/plugins/visualizations/charts/static/charts/nvd3/bar_horizontal_stacked/config.js index fac90095c8a..8bfe75014e7 100644 --- a/config/plugins/visualizations/charts/static/charts/nvd3/bar_horizontal_stacked/config.js +++ b/config/plugins/visualizations/charts/static/charts/nvd3/bar_horizontal_stacked/config.js @@ -1,25 +1,20 @@ -define(['plugin/charts/nvd3/common/config'], function(nvd3_config) { - -return $.extend(true, {}, nvd3_config, { - title : 'Stacked horizontal', - category : 'Bar diagrams', - settings : { - x_axis_type : { - init : 'hide' +define( [ 'plugin/charts/nvd3/common/config' ], function( nvd3_config ) { + return $.extend( true, {}, nvd3_config, { + title : 'Stacked horizontal', + category : 'Bar diagrams', + groups : { + x : { + label : 'Values for x-axis', + type : 'data_column', + is_label : true, + is_auto : true, + is_unique : true + }, + y : { + label : 'Values for y-axis', + type : 'data_column', + is_numeric : true + } } - }, - columns : { - x : { - title : 'Values for x-axis', - is_label : true, - is_auto : true, - is_unique : true - }, - y : { - title : 'Values for y-axis', - is_numeric : true - } - } -}); - + }); }); \ No newline at end of file diff --git a/config/plugins/visualizations/charts/static/charts/nvd3/bar_horizontal_stacked/wrapper.js b/config/plugins/visualizations/charts/static/charts/nvd3/bar_horizontal_stacked/wrapper.js index 7271d5594db..47218c8a27c 100644 --- a/config/plugins/visualizations/charts/static/charts/nvd3/bar_horizontal_stacked/wrapper.js +++ b/config/plugins/visualizations/charts/static/charts/nvd3/bar_horizontal_stacked/wrapper.js @@ -1,15 +1,11 @@ -// dependencies -define(['plugin/charts/nvd3/common/wrapper'], function(NVD3) { - -// widget -return Backbone.Model.extend({ - initialize: function(app, options) { - options.type = 'multiBarHorizontalChart'; - options.makeConfig = function(nvd3_model) { - nvd3_model.stacked(true); - }; - new NVD3(app, options); - } -}); - +define( [ 'plugin/charts/nvd3/common/wrapper' ], function( NVD3 ) { + return Backbone.Model.extend({ + initialize: function( app, options ) { + options.type = 'multiBarHorizontalChart'; + options.makeConfig = function( nvd3_model ) { + nvd3_model.stacked( true ); + }; + new NVD3( app, options ); + } + }); }); \ No newline at end of file diff --git a/config/plugins/visualizations/charts/static/charts/nvd3/bar_stacked/config.js b/config/plugins/visualizations/charts/static/charts/nvd3/bar_stacked/config.js index a816b105d6e..2fa355845cd 100644 --- a/config/plugins/visualizations/charts/static/charts/nvd3/bar_stacked/config.js +++ b/config/plugins/visualizations/charts/static/charts/nvd3/bar_stacked/config.js @@ -1,20 +1,20 @@ -define(['plugin/charts/nvd3/common/config'], function(nvd3_config) { - -return $.extend(true, {}, nvd3_config, { - title : 'Stacked', - category : 'Bar diagrams', - columns : { - x : { - title : 'Values for x-axis', - is_label : true, - is_auto : true, - is_unique : true - }, - y : { - title : 'Values for y-axis', - is_numeric : true +define( [ 'plugin/charts/nvd3/common/config' ], function( nvd3_config ) { + return $.extend( true, {}, nvd3_config, { + title : 'Stacked', + category : 'Bar diagrams', + groups : { + x : { + label : 'Values for x-axis', + type : 'data_column', + is_label : true, + is_auto : true, + is_unique : true + }, + y : { + label : 'Values for y-axis', + type : 'data_column', + is_numeric : true + } } - } -}); - + }); }); \ No newline at end of file diff --git a/config/plugins/visualizations/charts/static/charts/nvd3/bar_stacked/wrapper.js b/config/plugins/visualizations/charts/static/charts/nvd3/bar_stacked/wrapper.js index c45ca332fb3..876ce8fe3a4 100644 --- a/config/plugins/visualizations/charts/static/charts/nvd3/bar_stacked/wrapper.js +++ b/config/plugins/visualizations/charts/static/charts/nvd3/bar_stacked/wrapper.js @@ -1,15 +1,11 @@ -// dependencies -define(['plugin/charts/nvd3/common/wrapper'], function(NVD3) { - -// widget -return Backbone.Model.extend({ - initialize: function(app, options) { - options.type = 'multiBarChart'; - options.makeConfig = function(nvd3_model) { - nvd3_model.stacked(true); - }; - new NVD3(app, options); - } -}); - +define( [ 'plugin/charts/nvd3/common/wrapper' ], function( NVD3 ) { + return Backbone.Model.extend({ + initialize: function( app, options ) { + options.type = 'multiBarChart'; + options.makeConfig = function( nvd3_model ) { + nvd3_model.stacked( true ); + }; + new NVD3( app, options ); + } + }); }); \ No newline at end of file diff --git a/config/plugins/visualizations/charts/static/charts/nvd3/common/config.js b/config/plugins/visualizations/charts/static/charts/nvd3/common/config.js index 70126ec228b..3ba8e0701d9 100644 --- a/config/plugins/visualizations/charts/static/charts/nvd3/common/config.js +++ b/config/plugins/visualizations/charts/static/charts/nvd3/common/config.js @@ -1,27 +1,22 @@ -define( [ 'plugin/charts/forms/default', 'plugin/plugins/nvd3/nv.d3' ], function( config_default ) { - return $.extend( true, {}, config_default, { +define( [ 'plugin/charts/utilities/tabular-form', 'plugin/plugins/nvd3/nv.d3' ], function( default_config ) { + return $.extend( true, {}, default_config, { title : '', category : '', library : 'NVD3', tag : 'svg', - keywords : 'small', - columns : { + keywords : 'nvd3 default', + groups : { + color: { + label : 'Pick a series color', + type : 'color' + }, tooltip : { - title : 'Data point labels', - is_text : true, - is_numeric : true, - is_auto : true + label : 'Data point labels', + type : 'data_column', + is_label : true, + is_auto : true, + is_unique : true } - }, - series : [{ - name : 'key', - label : 'Provide a label', - type : 'text', - placeholder : 'Data label' - },{ - name : 'color', - label : 'Pick a series color', - type : 'color' - }] + } }); }); \ No newline at end of file diff --git a/config/plugins/visualizations/charts/static/charts/nvd3/common/wrapper.js b/config/plugins/visualizations/charts/static/charts/nvd3/common/wrapper.js index 2a2fe2c1316..28e47f8c86c 100644 --- a/config/plugins/visualizations/charts/static/charts/nvd3/common/wrapper.js +++ b/config/plugins/visualizations/charts/static/charts/nvd3/common/wrapper.js @@ -1,7 +1,5 @@ -/** - * This is the common wrapper for nvd3 based visualizations. - */ -define( [ 'plugin/charts/tools' ], function( Tools ) { +/** This is the common wrapper for nvd3 based visualizations. */ +define( [ 'plugin/charts/utilities/tabular-utilities' ], function( Utilities ) { return Backbone.View.extend({ initialize: function( app, options ) { var self = this; @@ -9,7 +7,7 @@ define( [ 'plugin/charts/tools' ], function( Tools ) { options.render = function( canvas_id, groups ) { return self.render( canvas_id, groups ) }; - Tools.panelHelper( app, options ); + Utilities.panelHelper( options ); }, render: function( canvas_id, groups ) { @@ -37,7 +35,7 @@ define( [ 'plugin/charts/tools' ], function( Tools ) { canvas.datum( groups ).call( d3chart ); if ( chart.definition.zoomable && chart.definition.zoomable != 'native' ) { d3chart.clipEdge && d3chart.clipEdge( true ); - Tools.addZoom({ + Utilities.addZoom({ xAxis : d3chart.xAxis, yAxis : d3chart.yAxis, yDomain: d3chart.yDomain, @@ -57,12 +55,12 @@ define( [ 'plugin/charts/tools' ], function( Tools ) { /** Format axes ticks */ _makeAxes: function( d3chart, groups, settings ) { - var categories = Tools.makeCategories( groups ); + var categories = Utilities.makeCategories( groups ); function makeTickFormat( id ) { - Tools.makeTickFormat({ + Utilities.makeTickFormat({ categories : categories.array[ id ], - type : settings.get( id + '_axis_type' ), - precision : settings.get( id + '_axis_precision' ), + type : settings.get( id + '_axis_type|type' ), + precision : settings.get( id + '_axis_type|precision' ), formatter : function( formatter ) { formatter && d3chart[ id + 'Axis' ].tickFormat( function( value ) { return formatter( value ); diff --git a/config/plugins/visualizations/charts/static/charts/nvd3/histogram/config.js b/config/plugins/visualizations/charts/static/charts/nvd3/histogram/config.js index 7e445747166..ba01e5f4ba9 100644 --- a/config/plugins/visualizations/charts/static/charts/nvd3/histogram/config.js +++ b/config/plugins/visualizations/charts/static/charts/nvd3/histogram/config.js @@ -1,31 +1,27 @@ -define(['plugin/charts/forms/default'], function(config_default) { -return $.extend(true, {}, config_default, { - library : 'NVD3', - tag : 'svg', - title : 'Histogram', - category : 'Data processing (requires \'charts\' tool from Toolshed)', - execute : 'histogram', - keywords : 'small medium large', - columns : { - y : { - title : 'Observations', - is_numeric : true +define( [ 'plugin/charts/utilities/tabular-form' ], function( default_config ) { + return $.extend( true, {}, default_config, { + library : 'NVD3', + tag : 'svg', + title : 'Histogram', + category : 'Data processing (requires \'charts\' tool from Toolshed)', + keywords : 'nvd3 default', + datatype : 'tabular', + groups : { + key : { + label : 'Provide a label', + type : 'text', + placeholder : 'Data label', + value : 'Data label' + }, + color : { + label : 'Pick a series color', + type : 'color' + }, + y : { + label : 'Observations', + type : 'data_column', + is_numeric : true + } } - }, - settings : { - x_axis_label : { - init : 'Values' - }, - y_axis_label : { - init : 'Density' - }, - y_axis_type : { - init : 'f' - }, - y_axis_precision : { - init : '.2' - } - } -}); - + }); }); \ No newline at end of file diff --git a/config/plugins/visualizations/charts/static/charts/nvd3/histogram/wrapper.js b/config/plugins/visualizations/charts/static/charts/nvd3/histogram/wrapper.js index 55254a25eff..7faf9a07adc 100644 --- a/config/plugins/visualizations/charts/static/charts/nvd3/histogram/wrapper.js +++ b/config/plugins/visualizations/charts/static/charts/nvd3/histogram/wrapper.js @@ -1,34 +1,18 @@ -// dependencies -define(['plugin/charts/nvd3/common/wrapper'], function(NVD3) { - -// widget -return Backbone.Model.extend({ - initialize: function(app, options) { - // link request - var request_dictionary = options.request_dictionary; - - // configure request - var index = 1; - for (var i in request_dictionary.groups) { - var group = request_dictionary.groups[i]; - group.columns = { - x: { - index : 0, - is_numeric : true - }, - y: { - index : index++ - } - } +define( [ 'plugin/charts/utilities/tabular-utilities', 'plugin/components/jobs', 'plugin/charts/nvd3/common/wrapper' ], function( Utilities, Jobs, NVD3 ) { + return Backbone.Model.extend({ + initialize: function( app, options ) { + Jobs.request( app, Utilities.buildJobDictionary( 'histogram', app.chart ), function( dataset ) { + options.request_dictionary = Utilities.buildRequestDictionary( app.chart, dataset.id ); + var index = 1; + _.each( options.request_dictionary.groups, function( group ) { + group.columns = { x : { index : 0, is_numeric : true }, y : { index : index++ } } + }); + options.type = 'multiBarChart'; + options.makeConfig = function( nvd3_model ) { + nvd3_model.options( { showControls: true } ); + }; + new NVD3( app, options ); + }, function() { options.process.reject() } ); } - - // setup chart wrapper - options.type = 'multiBarChart'; - options.makeConfig = function(nvd3_model) { - nvd3_model.options({showControls: true}); - }; - new NVD3(app, options); - } -}); - + }); }); \ No newline at end of file diff --git a/config/plugins/visualizations/charts/static/charts/nvd3/histogram_discrete/config.js b/config/plugins/visualizations/charts/static/charts/nvd3/histogram_discrete/config.js index cd01edff775..c6834649cb5 100644 --- a/config/plugins/visualizations/charts/static/charts/nvd3/histogram_discrete/config.js +++ b/config/plugins/visualizations/charts/static/charts/nvd3/histogram_discrete/config.js @@ -1,31 +1,17 @@ -define(['plugin/charts/forms/default'], function(config_default) { -return $.extend(true, {}, config_default, { - library : 'NVD3', - tag : 'svg', - title : 'Discrete Histogram', - category : 'Data processing (requires \'charts\' tool from Toolshed)', - execute : 'histogramdiscrete', - keywords : 'small medium large', - columns : { - x : { - title : 'Observations', - is_label : true +define( [ 'plugin/charts/utilities/tabular-form' ], function( default_config ) { + return $.extend(true, {}, default_config, { + library : 'NVD3', + tag : 'svg', + title : 'Discrete Histogram', + category : 'Data processing (requires \'charts\' tool from Toolshed)', + keywords : 'nvd3', + datatype : 'tabular', + groups : { + x : { + label : 'Observations', + type : 'data_column', + is_label : true + } } - }, - settings : { - x_axis_label : { - init : 'Breaks' - }, - y_axis_label : { - init : 'Density' - }, - y_axis_type : { - init : 'f' - }, - y_axis_precision : { - init : '2' - } - } -}); - + }); }); \ No newline at end of file diff --git a/config/plugins/visualizations/charts/static/charts/nvd3/histogram_discrete/wrapper.js b/config/plugins/visualizations/charts/static/charts/nvd3/histogram_discrete/wrapper.js index 5e7a84d9c3d..6230c97c3e3 100644 --- a/config/plugins/visualizations/charts/static/charts/nvd3/histogram_discrete/wrapper.js +++ b/config/plugins/visualizations/charts/static/charts/nvd3/histogram_discrete/wrapper.js @@ -1,44 +1,23 @@ -// dependencies -define(['plugin/charts/nvd3/common/wrapper'], function(NVD3) { - -// widget -return Backbone.Model.extend({ - initialize: function(app, options) { - // link request - var request_dictionary = options.request_dictionary; - - // configure request - var index = 1; - var tmp_dict = { - id : request_dictionary.id, - groups : [] - }; - - // configure groups - for (var group_index in request_dictionary.groups) { - var group = request_dictionary.groups[group_index]; - tmp_dict.groups.push({ - key : group.key, - columns : { - x: { - index : 0, - is_label : true - }, - y: { - index : index++ - } - } - }); +define( [ 'plugin/charts/utilities/tabular-utilities', 'plugin/components/jobs', 'plugin/charts/nvd3/common/wrapper' ], function( Utilities, Jobs, NVD3 ) { + return Backbone.Model.extend({ + initialize: function( app, options ) { + Jobs.request( app, Utilities.buildJobDictionary( 'histogramdiscrete', app.chart ), function( dataset ) { + var request_dictionary = Utilities.buildRequestDictionary( app.chart, dataset.id ); + var index = 1; + var tmp_dict = { id : request_dictionary.id, groups : [] }; + _.each( request_dictionary.groups, function( group ) { + tmp_dict.groups.push({ + key : group.key, + columns : { x: { index : 0, is_label : true }, y: { index : index++ } } + }); + }); + options.request_dictionary = tmp_dict; + options.type = 'multiBarChart'; + options.makeConfig = function( nvd3_model ) { + nvd3_model.options( { showControls: true } ); + }; + new NVD3( app, options ); + }, function() { options.process.reject() } ); } - - // setup chart wrapper - options.type = 'multiBarChart'; - options.request_dictionary = tmp_dict; - options.makeConfig = function(nvd3_model) { - nvd3_model.options({showControls: true}); - }; - new NVD3(app, options); - } -}); - + }); }); \ No newline at end of file diff --git a/config/plugins/visualizations/charts/static/charts/nvd3/line/config.js b/config/plugins/visualizations/charts/static/charts/nvd3/line/config.js index 865bca50e23..e16876511a1 100644 --- a/config/plugins/visualizations/charts/static/charts/nvd3/line/config.js +++ b/config/plugins/visualizations/charts/static/charts/nvd3/line/config.js @@ -1,21 +1,21 @@ -define(['plugin/charts/nvd3/common/config'], function(nvd3_config) { - -return $.extend(true, {}, nvd3_config, { - title : 'Line chart', - category : 'Others', - zoomable : true, - columns : { - x : { - title : 'Values for x-axis', - is_label : true, - is_auto : true, - is_unique : true - }, - y : { - title : 'Values for y-axis', - is_numeric : true +define( [ 'plugin/charts/nvd3/common/config' ], function( nvd3_config ) { + return $.extend( true, {}, nvd3_config, { + title : 'Line chart', + category : 'Others', + zoomable : true, + groups : { + x : { + label : 'Values for x-axis', + type : 'data_column', + is_label : true, + is_auto : true, + is_unique : true + }, + y : { + label : 'Values for y-axis', + type : 'data_column', + is_numeric : true + } } - } -}); - + }); }); \ No newline at end of file diff --git a/config/plugins/visualizations/charts/static/charts/nvd3/line/wrapper.js b/config/plugins/visualizations/charts/static/charts/nvd3/line/wrapper.js index 8623dcafbbc..060a01b9ba8 100644 --- a/config/plugins/visualizations/charts/static/charts/nvd3/line/wrapper.js +++ b/config/plugins/visualizations/charts/static/charts/nvd3/line/wrapper.js @@ -1,12 +1,8 @@ -// dependencies -define(['plugin/charts/nvd3/common/wrapper'], function(NVD3) { - -// widget -return Backbone.Model.extend({ - initialize: function(app, options) { - options.type = 'lineChart'; - new NVD3(app, options); - } -}); - +define( [ 'plugin/charts/nvd3/common/wrapper' ], function( NVD3 ) { + return Backbone.Model.extend({ + initialize: function( app, options ) { + options.type = 'lineChart'; + new NVD3( app, options ); + } + }); }); \ No newline at end of file diff --git a/config/plugins/visualizations/charts/static/charts/nvd3/line_focus/config.js b/config/plugins/visualizations/charts/static/charts/nvd3/line_focus/config.js index d84ac835b88..59215c913a7 100644 --- a/config/plugins/visualizations/charts/static/charts/nvd3/line_focus/config.js +++ b/config/plugins/visualizations/charts/static/charts/nvd3/line_focus/config.js @@ -1,21 +1,21 @@ -define(['plugin/charts/nvd3/common/config'], function(nvd3_config) { - -return $.extend(true, {}, nvd3_config, { - title : 'Line with focus', - category : 'Others', - zoomable : 'native', - columns : { - x : { - title : 'Values for x-axis', - is_label : true, - is_auto : true, - is_unique : true - }, - y : { - title : 'Values for y-axis', - is_numeric : true +define( [ 'plugin/charts/nvd3/common/config' ], function( nvd3_config ) { + return $.extend( true, {}, nvd3_config, { + title : 'Line with focus', + category : 'Others', + zoomable : 'native', + groups : { + x : { + label : 'Values for x-axis', + type : 'data_column', + is_label : true, + is_auto : true, + is_unique : true + }, + y : { + label : 'Values for y-axis', + type : 'data_column', + is_numeric : true + } } - } -}); - + }); }); \ No newline at end of file diff --git a/config/plugins/visualizations/charts/static/charts/nvd3/line_focus/wrapper.js b/config/plugins/visualizations/charts/static/charts/nvd3/line_focus/wrapper.js index e6ef5a177c2..66d89e5de81 100644 --- a/config/plugins/visualizations/charts/static/charts/nvd3/line_focus/wrapper.js +++ b/config/plugins/visualizations/charts/static/charts/nvd3/line_focus/wrapper.js @@ -1,12 +1,8 @@ -// dependencies -define(['plugin/charts/nvd3/common/wrapper'], function(NVD3) { - -// widget -return Backbone.Model.extend({ - initialize: function(app, options) { - options.type = 'lineWithFocusChart'; - new NVD3(app, options); - } -}); - +define( [ 'plugin/charts/nvd3/common/wrapper' ], function( NVD3 ) { + return Backbone.Model.extend({ + initialize: function( app, options ) { + options.type = 'lineWithFocusChart'; + new NVD3( app, options ); + } + }); }); \ No newline at end of file diff --git a/config/plugins/visualizations/charts/static/charts/nvd3/pie/config.js b/config/plugins/visualizations/charts/static/charts/nvd3/pie/config.js index d4dbf78f053..542a58790df 100644 --- a/config/plugins/visualizations/charts/static/charts/nvd3/pie/config.js +++ b/config/plugins/visualizations/charts/static/charts/nvd3/pie/config.js @@ -1,128 +1,75 @@ -define(['plugin/plugins/nvd3/nv.d3'], function() { - -return $.extend(true, {}, { - title : 'Pie chart', - category : 'Area charts', - library : 'NVD3', - tag : 'svg', - keywords : 'small', - columns : { - label : { - title : 'Labels', - is_label : true, - is_auto : true +define( [ 'plugin/charts/utilities/tabular-form' ], function( default_config ) { + return $.extend( true, {}, default_config, { + title : 'Pie chart', + category : 'Area charts', + library : 'NVD3', + tag : 'svg', + keywords : 'nvd3 default', + datatype : 'tabular', + groups : { + label : { + label : 'Labels', + type : 'data_column', + is_label : true, + is_auto : true + }, + y : { + label : 'Values', + type : 'data_column', + is_numeric : true + } }, - y : { - title : 'Values', - is_numeric : true + settings : { + donut_ratio : { + label : 'Donut ratio', + help : 'Determine how large the donut hole will be.', + type : 'float', + value : 0.5, + max : 1, + min : 0.0 + }, + show_legend : { + label : 'Show legend', + help : 'Would you like to add a legend?', + type : 'select', + display : 'radiobutton', + value : 'false', + data : [ { label : 'Yes', value : 'true' }, { label : 'No', value : 'false' } ] + }, + label_type : { + type : 'conditional', + test_param : { + name : 'type', + label : 'Donut label', + type : 'select', + value : 'percent', + help : 'What would you like to show for each slice?', + data : [ { value : 'hide', label : '-- Nothing --' }, + { value : 'key', label : 'Label column' }, + { value : 'percent', label : 'Percentage' } ] + }, + cases : [ { value : 'hide' }, + { value : 'key', inputs: [ { name : 'label_outside', + label : 'Show outside', + help : 'Would you like to show labels outside the donut?', + type : 'select', + display : 'radiobutton', + value : 'true', + data : [ { label : 'Yes', value : 'true' }, + { label : 'No', value : 'false' } ] } ] }, + { value : 'percent', inputs: [ { name : 'label_outside', + label : 'Show outside', + help : 'Would you like to show labels outside the donut?', + type : 'select', + display : 'radiobutton', + value : 'true', + data : [ { label : 'Yes', value : 'true' }, + { label : 'No', value : 'false' } ] } ] } ] + }, + use_panels : { + value : 'true', + hidden : true + } } - }, - - settings : { - main_separator : { - type : 'separator', - title : 'Pie chart settings' - }, - - donut_ratio : { - title : 'Donut ratio', - info : 'Determine how large the donut hole will be.', - type : 'select', - init : '0.5', - data : [ - { - label : '50%', - value : '0.5' - }, - { - label : '25%', - value : '0.25' - }, - { - label : '10%', - value : '0.10' - }, - { - label : '0%', - value : '0' - } - ] - }, - - show_legend : { - title : 'Show legend', - info : 'Would you like to add a legend?', - type : 'select', - display : 'radiobutton', - init : 'false', - data : [ - { - label : 'Yes', - value : 'true' - }, - { - label : 'No', - value : 'false' - } - ] - }, - - label_separator : { - type : 'separator', - title : 'Label settings' - }, - - label_type : { - title : 'Donut label', - info : 'What would you like to show for each slice?', - type : 'select', - init : 'percent', - data : [ - { - label : '-- Nothing --', - value : 'hide', - hide : 'label_outside' - }, - { - label : 'Label column', - value : 'key', - show : 'label_outside' - }, - { - label : 'Value column', - value : 'value', - show : 'label_outside' - }, - { - label : 'Percentage', - value : 'percent', - show : 'label_outside' - } - ], - }, - - label_outside : { - title : 'Show outside', - info : 'Would you like to show labels outside the donut?', - type : 'select', - display : 'radiobutton', - init : 'false', - data : [ - { - label : 'Yes', - value : 'true' - }, - { - label : 'No', - value : 'false' - } - ] - }, - - use_panels : { - init : 'true', - hide : true - } - } -}); + }); }); \ No newline at end of file diff --git a/config/plugins/visualizations/charts/static/charts/nvd3/pie/wrapper.js b/config/plugins/visualizations/charts/static/charts/nvd3/pie/wrapper.js index 0dda3d6c013..7a93a525213 100644 --- a/config/plugins/visualizations/charts/static/charts/nvd3/pie/wrapper.js +++ b/config/plugins/visualizations/charts/static/charts/nvd3/pie/wrapper.js @@ -1,122 +1,67 @@ -// dependencies -define(['utils/utils'], function(Utils) { - -// widget -return Backbone.View.extend( -{ - // initialize - initialize: function(app, options) { - // get parameters - var request_dictionary = options.request_dictionary; - var chart = options.chart; - var canvas_list = options.canvas_list; - var process = options.process; - - // setup handler - var self = this; - request_dictionary.success = function() { - // loop through data groups - for (var group_index in request_dictionary.groups) { - // get group - var group = request_dictionary.groups[group_index]; - - // draw group - self._drawGroup(chart, group, canvas_list[group_index]); - } - - // set chart state - chart.state('ok', 'Pie chart has been drawn.'); - - // unregister process - process.resolve(); - } - - // request data - app.datasets.request(request_dictionary); - }, - - // draw group - _drawGroup: function(chart, group, canvas_id) { - try { - // get canvas - var canvas = d3.select('#' + canvas_id); - - // add title - var title = canvas.append('text'); - - // configure title attributes - this._fixTitle(chart, canvas, title, group.key); - - // format chart data - var pie_data = []; - for (var key in group.values) { - var value = group.values[key]; - pie_data.push ({ - y : value.y, - x : value.label - }); - } - - // add graph to screen +/** Pie chart wrapper */ +define( [ 'utils/utils', 'plugin/charts/utilities/tabular-utilities', 'plugin/charts/utilities/tabular-datasets' ], function( Utils, Utilities, Datasets ) { + return Backbone.View.extend({ + initialize: function( app, options ) { var self = this; - nv.addGraph(function() { - // legend - var legend_visible = true; - if (chart.settings.get('show_legend') == 'false') { - legend_visible = false; + var chart = app.chart; + var request_dictionary = Utilities.buildRequestDictionary( app.chart ); + var canvas_list = options.canvas_list; + var process = options.process; + request_dictionary.success = function( result ) { + for ( var group_index in result.groups ) { + var group = result.groups[ group_index ]; + self._drawGroup( chart, group, canvas_list[ group_index ] ); } - - // legend - var label_outside = true; - if (chart.settings.get('label_outside') == 'false') { - label_outside = false; - } - - // label type - var label_type = chart.settings.get('label_type'); - - // ratio - var donut_ratio = parseFloat(chart.settings.get('donut_ratio')) - - // create chart model - var chart_3d = nv.models.pieChart() - .donut(true) - .labelThreshold(.05) - .showLegend(legend_visible) - .labelType(label_type) - .donutRatio(donut_ratio) - .donutLabelsOutside(label_outside); - - // add data to canvas - canvas.datum(pie_data) - .call(chart_3d); - - // add resize trigger - nv.utils.windowResize(function() { - // update chart - chart_3d.update(); - - // fix title - self._fixTitle(chart, canvas, title, group.key); - }); - }); - } catch (err) { - console.log(err); - } - }, - - // fix title - _fixTitle: function(chart, canvas, title_element, title_text) { - // update title - var width = parseInt(canvas.style('width')); - var height = parseInt(canvas.style('height')); - - // add title - title_element.attr('x', width / 2) - .attr('y', height - 10) - .attr('text-anchor', 'middle') - .text(title_text); - } -}); + chart.state('ok', 'Pie chart has been drawn.'); + process.resolve(); + } + Datasets.request( request_dictionary ); + }, + /** Draw group */ + _drawGroup: function( chart, group, canvas_id ) { + try { + var self = this; + var canvas = d3.select( '#' + canvas_id ); + var title = canvas.append( 'text' ); + this._fixTitle( chart, canvas, title, group.key ); + var pie_data = []; + _.each( group.values, function( value ) { + pie_data.push( { y : value.y, x : value.label } ); + }); + + // add graph to screen + nv.addGraph(function() { + var legend_visible = chart.settings.get( 'show_legend' ) == 'true'; + var label_outside = chart.settings.get( 'label_outside' ) == 'true'; + var label_type = chart.settings.get( 'label_type' ); + var donut_ratio = parseFloat( chart.settings.get( 'donut_ratio' ) ); + var chart_3d = nv.models.pieChart() + .donut( true ) + .labelThreshold( .05 ) + .showLegend( legend_visible ) + .labelType( label_type ) + .donutRatio( donut_ratio ) + .donutLabelsOutside( label_outside ); + canvas.datum( pie_data ).call( chart_3d ); + nv.utils.windowResize( function() { + chart_3d.update(); + self._fixTitle( chart, canvas, title, group.key ); + }); + }); + } catch ( err ) { + console.log( err ); + } + }, + + /** Fix title */ + _fixTitle: function( chart, canvas, title_element, title_text ) { + var width = parseInt( canvas.style( 'width' ) ); + var height = parseInt( canvas.style( 'height' ) ); + title_element.attr( 'x', width / 2 ) + .attr( 'y', height - 10 ) + .attr( 'text-anchor', 'middle' ) + .text( title_text ); + } + }); }); diff --git a/config/plugins/visualizations/charts/static/charts/nvd3/scatter/config.js b/config/plugins/visualizations/charts/static/charts/nvd3/scatter/config.js index 5d319dac390..cd44200e0cd 100644 --- a/config/plugins/visualizations/charts/static/charts/nvd3/scatter/config.js +++ b/config/plugins/visualizations/charts/static/charts/nvd3/scatter/config.js @@ -1,19 +1,19 @@ -define(['plugin/charts/nvd3/common/config'], function(nvd3_config) { - -return $.extend(true, {}, nvd3_config, { - title : 'Scatter plot', - category : 'Others', - zoomable : true, - columns : { - x : { - title : 'Values for x-axis', - is_numeric : true - }, - y : { - title : 'Values for y-axis', - is_numeric : true +define( [ 'plugin/charts/nvd3/common/config' ], function( nvd3_config ) { + return $.extend( true, {}, nvd3_config, { + title : 'Scatter plot', + category : 'Others', + zoomable : true, + groups : { + x : { + label : 'Values for x-axis', + type : 'data_column', + is_numeric : true + }, + y : { + label : 'Values for y-axis', + type : 'data_column', + is_numeric : true + } } - } -}); - + }); }); \ No newline at end of file diff --git a/config/plugins/visualizations/charts/static/charts/nvd3/scatter/wrapper.js b/config/plugins/visualizations/charts/static/charts/nvd3/scatter/wrapper.js index edeb3e901ed..73a7e1ccc73 100644 --- a/config/plugins/visualizations/charts/static/charts/nvd3/scatter/wrapper.js +++ b/config/plugins/visualizations/charts/static/charts/nvd3/scatter/wrapper.js @@ -1,17 +1,13 @@ -// dependencies -define(['plugin/charts/nvd3/common/wrapper'], function(NVD3) { - -// widget -return Backbone.Model.extend({ - initialize: function(app, options) { - options.type = 'scatterChart'; - options.makeConfig = function(nvd3_model) { - nvd3_model.showDistX(true) - .showDistY(true) - .color(d3.scale.category10().range()); - }; - new NVD3(app, options); - } -}); - +define( [ 'plugin/charts/nvd3/common/wrapper' ], function( NVD3 ) { + return Backbone.Model.extend({ + initialize: function( app, options ) { + options.type = 'scatterChart'; + options.makeConfig = function( nvd3_model ) { + nvd3_model.showDistX( true ) + .showDistY( true ) + .color( d3.scale.category10().range() ); + }; + new NVD3( app, options ); + } + }); }); \ No newline at end of file diff --git a/config/plugins/visualizations/charts/static/charts/nvd3/stackedarea/config.js b/config/plugins/visualizations/charts/static/charts/nvd3/stackedarea/config.js index 1dc95b3a970..8e2a4991c12 100644 --- a/config/plugins/visualizations/charts/static/charts/nvd3/stackedarea/config.js +++ b/config/plugins/visualizations/charts/static/charts/nvd3/stackedarea/config.js @@ -1,22 +1,22 @@ -define(['plugin/charts/nvd3/common/config'], function(nvd3_config) { - -return $.extend(true, {}, nvd3_config, { - title : 'Regular', - zoomable : true, - category : 'Area charts', - keywords : 'default small', - columns : { - x : { - title : 'Values for x-axis', - is_label : true, - is_auto : true, - is_unique : true - }, - y : { - title : 'Values for y-axis', - is_numeric : true +define( [ 'plugin/charts/nvd3/common/config' ], function( nvd3_config ) { + return $.extend( true, {}, nvd3_config, { + title : 'Regular', + zoomable : true, + category : 'Area charts', + keywords : 'nvd3 default', + groups : { + x : { + label : 'Values for x-axis', + type : 'data_column', + is_label : true, + is_auto : true, + is_unique : true + }, + y : { + label : 'Values for y-axis', + type : 'data_column', + is_numeric : true + } } - } -}); - + }); }); \ No newline at end of file diff --git a/config/plugins/visualizations/charts/static/charts/nvd3/stackedarea/wrapper.js b/config/plugins/visualizations/charts/static/charts/nvd3/stackedarea/wrapper.js index 3ef2ecb8040..3a609b919bf 100644 --- a/config/plugins/visualizations/charts/static/charts/nvd3/stackedarea/wrapper.js +++ b/config/plugins/visualizations/charts/static/charts/nvd3/stackedarea/wrapper.js @@ -1,12 +1,8 @@ -// dependencies -define(['plugin/charts/nvd3/common/wrapper'], function(NVD3) { - -// widget -return Backbone.Model.extend({ - initialize: function(app, options) { - options.type = 'stackedAreaChart'; - new NVD3(app, options); - } -}); - +define( [ 'plugin/charts/nvd3/common/wrapper' ], function( NVD3 ) { + return Backbone.Model.extend({ + initialize: function( app, options ) { + options.type = 'stackedAreaChart'; + new NVD3( app, options ); + } + }); }); \ No newline at end of file diff --git a/config/plugins/visualizations/charts/static/charts/nvd3/stackedarea_full/config.js b/config/plugins/visualizations/charts/static/charts/nvd3/stackedarea_full/config.js index 1a16065c654..6940adbdd83 100644 --- a/config/plugins/visualizations/charts/static/charts/nvd3/stackedarea_full/config.js +++ b/config/plugins/visualizations/charts/static/charts/nvd3/stackedarea_full/config.js @@ -1,22 +1,22 @@ -define(['plugin/charts/nvd3/common/config'], function(nvd3_config) { - -return $.extend(true, {}, nvd3_config, { - title : 'Expanded', - zoomable : true, - category : 'Area charts', - keywords : 'default small', - columns : { - x : { - title : 'Values for x-axis', - is_label : true, - is_auto : true, - is_unique : true - }, - y : { - title : 'Values for y-axis', - is_numeric : true +define( [ 'plugin/charts/nvd3/common/config' ], function( nvd3_config ) { + return $.extend( true, {}, nvd3_config, { + title : 'Expanded', + zoomable : true, + category : 'Area charts', + keywords : 'nvd3 default', + groups : { + x : { + label : 'Values for x-axis', + type : 'data_column', + is_label : true, + is_auto : true, + is_unique : true + }, + y : { + label : 'Values for y-axis', + type : 'data_column', + is_numeric : true + } } - } -}); - + }); }); \ No newline at end of file diff --git a/config/plugins/visualizations/charts/static/charts/nvd3/stackedarea_full/wrapper.js b/config/plugins/visualizations/charts/static/charts/nvd3/stackedarea_full/wrapper.js index 1b0f23c7d92..b7c8147cc89 100644 --- a/config/plugins/visualizations/charts/static/charts/nvd3/stackedarea_full/wrapper.js +++ b/config/plugins/visualizations/charts/static/charts/nvd3/stackedarea_full/wrapper.js @@ -1,15 +1,11 @@ -// dependencies -define(['plugin/charts/nvd3/common/wrapper'], function(NVD3) { - -// widget -return Backbone.Model.extend({ - initialize: function(app, options) { - options.type = 'stackedAreaChart'; - options.makeConfig = function(nvd3_model) { - nvd3_model.style('expand'); - }; - new NVD3(app, options); - } -}); - +define( [ 'plugin/charts/nvd3/common/wrapper' ], function( NVD3 ) { + return Backbone.Model.extend({ + initialize: function( app, options ) { + options.type = 'stackedAreaChart'; + options.makeConfig = function( nvd3_model ) { + nvd3_model.style( 'expand' ); + }; + new NVD3( app, options ); + } + }); }); \ No newline at end of file diff --git a/config/plugins/visualizations/charts/static/charts/nvd3/stackedarea_stream/config.js b/config/plugins/visualizations/charts/static/charts/nvd3/stackedarea_stream/config.js index fd37cae5afb..aa80cfa8b0c 100644 --- a/config/plugins/visualizations/charts/static/charts/nvd3/stackedarea_stream/config.js +++ b/config/plugins/visualizations/charts/static/charts/nvd3/stackedarea_stream/config.js @@ -1,23 +1,23 @@ -define(['plugin/charts/nvd3/common/config'], function(nvd3_config) { - -return $.extend(true, {}, nvd3_config, { - title : 'Stream', - category : 'Area charts', - zoomable : true, - keywords : 'default small', - showmaxmin : true, - columns : { - x : { - title : 'Values for x-axis', - is_label : true, - is_auto : true, - is_unique : true - }, - y : { - title : 'Values for y-axis', - is_numeric : true +define( [ 'plugin/charts/nvd3/common/config' ], function( nvd3_config ) { + return $.extend(true, {}, nvd3_config, { + title : 'Stream', + category : 'Area charts', + zoomable : true, + keywords : 'nvd3 default', + showmaxmin : true, + groups : { + x : { + label : 'Values for x-axis', + type : 'data_column', + is_label : true, + is_auto : true, + is_unique : true + }, + y : { + label : 'Values for y-axis', + type : 'data_column', + is_numeric : true + } } - } -}); - + }); }); \ No newline at end of file diff --git a/config/plugins/visualizations/charts/static/charts/nvd3/stackedarea_stream/wrapper.js b/config/plugins/visualizations/charts/static/charts/nvd3/stackedarea_stream/wrapper.js index 942cdf58da5..29a1e70ea2e 100644 --- a/config/plugins/visualizations/charts/static/charts/nvd3/stackedarea_stream/wrapper.js +++ b/config/plugins/visualizations/charts/static/charts/nvd3/stackedarea_stream/wrapper.js @@ -1,15 +1,11 @@ -// dependencies -define(['plugin/charts/nvd3/common/wrapper'], function(NVD3) { - -// widget -return Backbone.Model.extend({ - initialize: function(app, options) { - options.type = 'stackedAreaChart'; - options.makeConfig = function(nvd3_model) { - nvd3_model.style('stream') - }; - new NVD3(app, options); - } -}); - +define( [ 'plugin/charts/nvd3/common/wrapper' ], function( NVD3 ) { + return Backbone.Model.extend({ + initialize: function( app, options ) { + options.type = 'stackedAreaChart'; + options.makeConfig = function( nvd3_model ) { + nvd3_model.style( 'stream' ) + }; + new NVD3( app, options ); + } + }); }); \ No newline at end of file diff --git a/config/plugins/visualizations/charts/static/charts/others/example/config.js b/config/plugins/visualizations/charts/static/charts/others/example/config.js new file mode 100755 index 00000000000..419804720d2 --- /dev/null +++ b/config/plugins/visualizations/charts/static/charts/others/example/config.js @@ -0,0 +1,18 @@ +define([], function() { + return { + title : 'Example', + category : 'Developer Examples', + library : 'Custom', + tag : 'svg', + keywords : 'others', + description : 'This is a developer example which demonstrates how to implement and configure a basic d3-based plugin for charts.', + groups : { + x : { type : 'data_column', is_numeric : true, label : 'Bubble x-position' }, + y : { type : 'data_column', is_numeric : true, label : 'Bubble y-position' }, + z : { type : 'data_column', is_numeric : true, label : 'Bubble size' } + }, + settings : { + use_panels : { label : 'Use multiple panels', help : 'Do you want to draw all data series into a individual panels?', type : 'boolean' } + } + } +}); \ No newline at end of file diff --git a/config/plugins/visualizations/charts/static/charts/others/example/logo.png b/config/plugins/visualizations/charts/static/charts/others/example/logo.png new file mode 100644 index 00000000000..0c13459935b Binary files /dev/null and b/config/plugins/visualizations/charts/static/charts/others/example/logo.png differ diff --git a/config/plugins/visualizations/charts/static/charts/others/example/wrapper.js b/config/plugins/visualizations/charts/static/charts/others/example/wrapper.js new file mode 100755 index 00000000000..7f86ebc872a --- /dev/null +++ b/config/plugins/visualizations/charts/static/charts/others/example/wrapper.js @@ -0,0 +1,37 @@ +define( [ 'plugin/charts/utilities/tabular-utilities', 'plugin/charts/utilities/tabular-datasets' ], function( Utilities, Datasets ) { + return Backbone.View.extend({ + initialize: function( app, options ) { + var chart = app.chart; + var request_dictionary = Utilities.buildRequestDictionary( chart ); + var error = null; + request_dictionary.success = function( result ) { + var colors = d3.scale.category20(); + _.each( result.groups, function( group, group_index ) { + try { + var svg = d3.select( '#' + ( options.canvas_list[ group_index ] || options.canvas_list[ 0 ] ) ); + var height = parseInt( svg.style( 'height' ) ); + var width = parseInt( svg.style( 'width' ) ); + var maxValue = d3.max( group.values, function( d ) { return Math.max( d.x, d.y ) } ); + svg.selectAll( 'bubbles' ) + .data( group.values ) + .enter().append( 'circle' ) + .attr( 'r', function( d ) { return ( Math.abs( d.z ) * 20 ) / maxValue } ) + .attr( 'cy', function( d, i ) { return height * d.y / maxValue } ) + .attr( 'cx', function( d ) { return width * d.x / maxValue } ) + .style( 'stroke', colors( group_index ) ) + .style( 'fill', 'white' ); + } catch ( err ) { + error = err; + } + }); + if ( error ) { + chart.state( 'failed', error ); + } else { + chart.state( 'ok', 'Workshop chart has been drawn.' ); + } + options.process.resolve(); + } + Datasets.request( request_dictionary ); + } + }); +}); \ No newline at end of file diff --git a/config/plugins/visualizations/charts/static/charts/others/heatmap/config.js b/config/plugins/visualizations/charts/static/charts/others/heatmap/config.js index a83b5e77141..50da087af72 100644 --- a/config/plugins/visualizations/charts/static/charts/others/heatmap/config.js +++ b/config/plugins/visualizations/charts/static/charts/others/heatmap/config.js @@ -1,111 +1,65 @@ -define(['plugin/charts/forms/default'], function(config_default) { - -return $.extend(true, {}, config_default, { - title : 'Heatmap', - category : 'Others', - library : 'Custom', - tag : 'svg', - keywords : 'small', - zoomable : true, - columns : { - x : { - title : 'Column labels', - is_label : true, - is_numeric : true, - is_unique : true +define( [ 'plugin/charts/utilities/tabular-form' ], function( default_config ) { + return $.extend( true, {}, default_config, { + title : 'Heatmap', + category : 'Others', + library : 'Custom', + tag : 'svg', + keywords : 'others default', + zoomable : true, + groups : { + x : { + label : 'Column labels', + type : 'data_column', + is_label : true, + is_unique : true, + is_numeric : true + }, + y : { + label : 'Row labels', + type : 'data_column', + is_label : true, + is_unique : true, + is_numeric : true + }, + z : { + label : 'Observation', + type : 'data_column', + is_numeric : true + } }, - y : { - title : 'Row labels', - is_label : true, - is_numeric : true, - is_unique : true - }, - z : { - title : 'Observation', - is_numeric : true + settings : { + use_panels : { + value : 'true', + hidden : true + }, + color_set : { + label : 'Color scheme', + help : 'Select a color scheme for your heatmap', + type : 'select', + value : 'jet', + data : [ { label : 'Cold-to-Hot', value : 'hot' }, + { label : 'Cool', value : 'cool' }, + { label : 'Copper', value : 'copper' }, + { label : 'Gray scale', value : 'gray' }, + { label : 'Jet', value : 'jet' }, + { label : 'No-Green', value : 'no_green' }, + { label : 'Ocean', value : 'ocean' }, + { label : 'Polar', value : 'polar' }, + { label : 'Red-to-Green', value : 'redgreen' }, + { label : 'Red-to-green (saturated)', value : 'red2green' }, + { label : 'Relief', value : 'relief' }, + { label : 'Seismograph', value : 'seis' }, + { label : 'Sealand', value : 'sealand' }, + { label : 'Split', value : 'split' }, + { label : 'Wysiwyg', value : 'wysiwyg' } ] + }, + url_template: { + label : 'Url template', + help : 'Enter a url to link the labels with external sources. Use __LABEL__ as placeholder.', + type : 'text', + value : '', + placeholder : 'http://someurl.com?id=__LABEL__' + } } - }, - settings : { - use_panels : { - init : 'true', - hide : true - }, - color_set : { - title : 'Color scheme', - info : 'Select a color scheme for your heatmap', - type : 'select', - init : 'jet', - data : [ - { - label : 'Cold-to-Hot', - value : 'hot' - }, - { - label : 'Cool', - value : 'cool' - }, - { - label : 'Copper', - value : 'copper' - }, - { - label : 'Gray scale', - value : 'gray' - }, - { - label : 'Jet', - value : 'jet' - }, - { - label : 'No-Green', - value : 'no_green' - }, - { - label : 'Ocean', - value : 'ocean' - }, - { - label : 'Polar', - value : 'polar' - }, - { - label : 'Red-to-Green', - value : 'redgreen' - }, - { - label : 'Red-to-green (saturated)', - value : 'red2green' - }, - { - label : 'Relief', - value : 'relief' - }, - { - label : 'Seismograph', - value : 'seis' - }, - { - label : 'Sealand', - value : 'sealand' - }, - { - label : 'Split', - value : 'split' - }, - { - label : 'Wysiwyg', - value : 'wysiwyg' - } - ] - }, - url_template: { - title : 'Url template', - info : 'Enter a url to link the labels with external sources. Use __LABEL__ as placeholder.', - type : 'text', - init : '', - placeholder : 'http://someurl.com?id=__LABEL__' - } - } -}); - + }); }); \ No newline at end of file diff --git a/config/plugins/visualizations/charts/static/charts/others/heatmap/heatmap-parameters.js b/config/plugins/visualizations/charts/static/charts/others/heatmap/heatmap-parameters.js index 95235c4538d..603353012a3 100644 --- a/config/plugins/visualizations/charts/static/charts/others/heatmap/heatmap-parameters.js +++ b/config/plugins/visualizations/charts/static/charts/others/heatmap/heatmap-parameters.js @@ -1,42 +1,35 @@ -// dependencies define([], function() { + return { + colorSets: { + seis: ['#AA0000', '#D00000', '#F70000', '#FF1D00', '#FF4400', '#FF6A00', '#FF9000', '#FFB700', '#FFDD00', '#FFFF00', '#FFFF00', '#FFFF00', '#BDFF0C', '#73FF1A', '#3FFA36', '#16F45A', '#00D08B', '#0087CD', '#0048FA', '#0024E3'].reverse(), + + sealand: ['#8C66FF', '#6A66FF', '#6684FF', '#66A7FF', '#66CAFF', '#66ECFF', '#66FFF0', '#66FFCE', '#66FFAB', '#66FF88', '#66FF66', '#88FF66', '#ABFF66', '#CEFF66', '#FFEEA6', '#FFD3A6', '#FFB8A6', '#FFAAB0', '#FFB5CB', '#FFC0E1'].reverse(), + + redgreen: ['#005824', '#1A693B', '#347B53', '#4F8D6B', '#699F83', '#83B09B', '#9EC2B3', '#B8D4CB', '#D2E6E3', '#EDF8FB', '#FFFFFF', '#F1EEF6', '#E6D3E1','#DBB9CD', '#D19EB9', '#C684A4', '#BB6990', '#B14F7C', '#A63467', '#9B1A53', '#91003F'], + + ocean: ['#000000', '#000209', '#000413', '#00061E', '#000728', '#000932', '#002650', '#00426E', '#005E8C', '#007AAA', '#0096C8', '#22A9C2', '#45BCBB', '#67CFB5', '#8AE2AE', '#ACF6A8', '#BCF8B9', '#CBF9CA', '#DBFBDC', '#EBFDED'].reverse(), + + cool: ['#00FFFF', '#0DF2FF', '#19E6FF', '#26D9FF', '#33CCFF', '#3FBFFF', '#4CB3FF', '#59A6FF', '#6699FF', '#738CFF', '#7F7FFF', '#8C73FF', '#9966FF', '#A659FF', '#B24DFF', '#BF3FFF', '#CC33FF', '#D926FF', '#E619FF', '#F20DFF'], + + copper: ['#000000', '#100906', '#1F130D', '#301E13', '#40281A', '#50321F', '#603C26', '#70462D', '#805033', '#905A3A', '#A06440', '#B06E46', '#C0784D', '#D08253', '#E08C5A', '#F09660', '#FFA066', '#FFAA6D', '#FFB473', '#FFBE7A'].reverse(), + + gray: ['#000000', '#0D0D0D', '#191919', '#262626', '#333333', '#3F3F3F', '#4C4C4C', '#595959', '#666666', '#737373', '#7F7F7F', '#8C8C8C', '#999999', '#A6A6A6', '#B2B2B2', '#BFBFBF', '#CCCCCC', '#D9D9D9', '#E6E6E6', '#F2F2F2'].reverse(), + + hot: ['#000000', '#220000', '#440000', '#660000', '#880000', '#AA0000', '#CC0000', '#EE0000', '#FF1100', '#FF3300', '#FF5500', '#FF7700', '#FF9900', '#FFBB00', '#FFDD00', '#FFFF00', '#FFFF33', '#FFFF66', '#FFFF99', '#FFFFCC'].reverse(), + + jet: ['#00007F', '#0000B2', '#0000E5', '#0019FF', '#004DFF', '#007FFF', '#00B2FF', '#00E5FF', '#FFFFF2', '#FFFFD9', '#FFFFBF', '#FFFFA5', '#FFFF8C', '#FFE500', '#FFB300', '#FF7F00', '#FF4C00', '#FF1900', '#E50000', '#B20000'], + + no_green: ['#1F60FF', '#1F60FF', '#1F9FFF', '#1FBFFF', '#00CFFF', '#2AFFFF', '#2AFFFF', '#55FFFF', '#7FFFFF', '#AAFFFF', '#FFFF54', '#FFFF54', '#FFF000', '#FFBF00', '#FFA800', '#FF8A00', '#FF8A00', '#FF7000', '#FF4D00', '#FF0000'], -// color palettes -var colorSets = { - seis: ['#AA0000', '#D00000', '#F70000', '#FF1D00', '#FF4400', '#FF6A00', '#FF9000', '#FFB700', '#FFDD00', '#FFFF00', '#FFFF00', '#FFFF00', '#BDFF0C', '#73FF1A', '#3FFA36', '#16F45A', '#00D08B', '#0087CD', '#0048FA', '#0024E3'].reverse(), - - sealand: ['#8C66FF', '#6A66FF', '#6684FF', '#66A7FF', '#66CAFF', '#66ECFF', '#66FFF0', '#66FFCE', '#66FFAB', '#66FF88', '#66FF66', '#88FF66', '#ABFF66', '#CEFF66', '#FFEEA6', '#FFD3A6', '#FFB8A6', '#FFAAB0', '#FFB5CB', '#FFC0E1'].reverse(), - - redgreen: ['#005824', '#1A693B', '#347B53', '#4F8D6B', '#699F83', '#83B09B', '#9EC2B3', '#B8D4CB', '#D2E6E3', '#EDF8FB', '#FFFFFF', '#F1EEF6', '#E6D3E1','#DBB9CD', '#D19EB9', '#C684A4', '#BB6990', '#B14F7C', '#A63467', '#9B1A53', '#91003F'], - - ocean: ['#000000', '#000209', '#000413', '#00061E', '#000728', '#000932', '#002650', '#00426E', '#005E8C', '#007AAA', '#0096C8', '#22A9C2', '#45BCBB', '#67CFB5', '#8AE2AE', '#ACF6A8', '#BCF8B9', '#CBF9CA', '#DBFBDC', '#EBFDED'].reverse(), - - cool: ['#00FFFF', '#0DF2FF', '#19E6FF', '#26D9FF', '#33CCFF', '#3FBFFF', '#4CB3FF', '#59A6FF', '#6699FF', '#738CFF', '#7F7FFF', '#8C73FF', '#9966FF', '#A659FF', '#B24DFF', '#BF3FFF', '#CC33FF', '#D926FF', '#E619FF', '#F20DFF'], - - copper: ['#000000', '#100906', '#1F130D', '#301E13', '#40281A', '#50321F', '#603C26', '#70462D', '#805033', '#905A3A', '#A06440', '#B06E46', '#C0784D', '#D08253', '#E08C5A', '#F09660', '#FFA066', '#FFAA6D', '#FFB473', '#FFBE7A'].reverse(), - - gray: ['#000000', '#0D0D0D', '#191919', '#262626', '#333333', '#3F3F3F', '#4C4C4C', '#595959', '#666666', '#737373', '#7F7F7F', '#8C8C8C', '#999999', '#A6A6A6', '#B2B2B2', '#BFBFBF', '#CCCCCC', '#D9D9D9', '#E6E6E6', '#F2F2F2'].reverse(), - - hot: ['#000000', '#220000', '#440000', '#660000', '#880000', '#AA0000', '#CC0000', '#EE0000', '#FF1100', '#FF3300', '#FF5500', '#FF7700', '#FF9900', '#FFBB00', '#FFDD00', '#FFFF00', '#FFFF33', '#FFFF66', '#FFFF99', '#FFFFCC'].reverse(), - - jet: ['#00007F', '#0000B2', '#0000E5', '#0019FF', '#004DFF', '#007FFF', '#00B2FF', '#00E5FF', '#FFFFF2', '#FFFFD9', '#FFFFBF', '#FFFFA5', '#FFFF8C', '#FFE500', '#FFB300', '#FF7F00', '#FF4C00', '#FF1900', '#E50000', '#B20000'], - - no_green: ['#1F60FF', '#1F60FF', '#1F9FFF', '#1FBFFF', '#00CFFF', '#2AFFFF', '#2AFFFF', '#55FFFF', '#7FFFFF', '#AAFFFF', '#FFFF54', '#FFFF54', '#FFF000', '#FFBF00', '#FFA800', '#FF8A00', '#FF8A00', '#FF7000', '#FF4D00', '#FF0000'], + polar: ['#0000FF', '#1919FF', '#3333FF', '#4C4CFF', '#6666FF', '#7F7FFF', '#9999FF', '#B2B2FF', '#CCCCFF', '#E6E6FF', '#FFFFFF', '#FFE5E5', '#FFCCCC', '#FFB2B2', '#FF9999', '#FF7F7F', '#FF6666', '#FF4C4C', '#FF3333', '#FF1A1A'], - polar: ['#0000FF', '#1919FF', '#3333FF', '#4C4CFF', '#6666FF', '#7F7FFF', '#9999FF', '#B2B2FF', '#CCCCFF', '#E6E6FF', '#FFFFFF', '#FFE5E5', '#FFCCCC', '#FFB2B2', '#FF9999', '#FF7F7F', '#FF6666', '#FF4C4C', '#FF3333', '#FF1A1A'], - - red2green: ['#FF0000', '#FF1919', '#FF3333', '#FF4C4C', '#FF6666', '#FF7F7F', '#FF9999', '#FFB2B2', '#FFCCCC', '#FFE6E6', '#FFFFFF', '#E5FFE5', '#CCFFCC', '#B2FFB2', '#99FF99', '#7FFF7F', '#66FF66', '#4CFF4C', '#33FF33', '#1AFF1A'].reverse(), - - relief: ['#000000', '#000413', '#000728', '#002650', '#005E8C', '#0096C8', '#45BCBB', '#8AE2AE', '#BCF8B9', '#DBFBDC', '#467832', '#887438', '#B19D48', '#DBC758', '#FAE769', '#FAEB7E', '#FCED93', '#FCF1A7', '#FCF6C1', '#FDFAE0'].reverse(), - - split: ['#7F7FFF', '#6666E6', '#4D4DCC', '#3333B3', '#1A1A99', '#00007F', '#000066', '#00004D', '#000033', '#00001A', '#000000', '#1A0000', '#330000', '#4D0000', '#660000', '#7F0000', '#991A1A', '#B33333', '#CC4D4D', '#E66666'], - - wysiwyg: ['#3F003F', '#3F003F', '#3F00BF', '#003FFF', '#00A0FF', '#3FBFFF', '#3FBFFF', '#40E0FF', '#3FFFBF', '#3FFF3F', '#7FFF3F', '#BFFF3F', '#BFFF3F', '#FFE040', '#FFE040', '#FF6040', '#FF1F40', '#FF60C0', '#FFA0FF', '#FFA0FF'].reverse() -} - -// return -return { - colorSets: colorSets -} + red2green: ['#FF0000', '#FF1919', '#FF3333', '#FF4C4C', '#FF6666', '#FF7F7F', '#FF9999', '#FFB2B2', '#FFCCCC', '#FFE6E6', '#FFFFFF', '#E5FFE5', '#CCFFCC', '#B2FFB2', '#99FF99', '#7FFF7F', '#66FF66', '#4CFF4C', '#33FF33', '#1AFF1A'].reverse(), + relief: ['#000000', '#000413', '#000728', '#002650', '#005E8C', '#0096C8', '#45BCBB', '#8AE2AE', '#BCF8B9', '#DBFBDC', '#467832', '#887438', '#B19D48', '#DBC758', '#FAE769', '#FAEB7E', '#FCED93', '#FCF1A7', '#FCF6C1', '#FDFAE0'].reverse(), + + split: ['#7F7FFF', '#6666E6', '#4D4DCC', '#3333B3', '#1A1A99', '#00007F', '#000066', '#00004D', '#000033', '#00001A', '#000000', '#1A0000', '#330000', '#4D0000', '#660000', '#7F0000', '#991A1A', '#B33333', '#CC4D4D', '#E66666'], + + wysiwyg: ['#3F003F', '#3F003F', '#3F00BF', '#003FFF', '#00A0FF', '#3FBFFF', '#3FBFFF', '#40E0FF', '#3FFFBF', '#3FFF3F', '#7FFF3F', '#BFFF3F', '#BFFF3F', '#FFE040', '#FFE040', '#FF6040', '#FF1F40', '#FF60C0', '#FFA0FF', '#FFA0FF'].reverse() + } + } }); \ No newline at end of file diff --git a/config/plugins/visualizations/charts/static/charts/others/heatmap/heatmap-plugin.js b/config/plugins/visualizations/charts/static/charts/others/heatmap/heatmap-plugin.js index 2919325422e..b039e5ed145 100644 --- a/config/plugins/visualizations/charts/static/charts/others/heatmap/heatmap-plugin.js +++ b/config/plugins/visualizations/charts/static/charts/others/heatmap/heatmap-plugin.js @@ -1,448 +1,391 @@ -// dependencies -define(['plugin/charts/tools', 'utils/utils', 'plugin/charts/others/heatmap/heatmap-parameters'], function(Tools, Utils, HeatmapParameters) { - -// widget -return Backbone.View.extend({ - - // options - optionsDefault: { - margin: { - top : 40, - right : 70, - bottom : 70, - left : 70 - }, - style: { - 'font-weight' : 'normal', - 'font-family' : 'Verdana', - 'font-size' : 12 - }, - legend: { - width : 15, - size : 0.9, - style : { - 'font-weight' : 'normal', - 'font-family' : 'Verdana', - 'font-size' : 11 +define( [ 'plugin/charts/utilities/tabular-utilities', 'utils/utils', 'plugin/charts/others/heatmap/heatmap-parameters' ], function( Utilities, Utils, HeatmapParameters ) { + return Backbone.View.extend({ + optionsDefault: { + margin: { + top : 40, + right : 70, + bottom : 70, + left : 70 }, - limit : 7 + style: { + 'font-weight' : 'normal', + 'font-family' : 'Verdana', + 'font-size' : 12 + }, + legend: { + width : 15, + size : 0.9, + style : { + 'font-weight' : 'normal', + 'font-family' : 'Verdana', + 'font-size' : 11 + }, + limit : 7 + }, + background_color : '#FFFFFF', + debug_color : '#FFFFFF' }, - background_color : '#FFFFFF', - debug_color : '#FFFFFF' - }, - - // initialize - initialize: function(app, options) { - // collect parameters - this.app = app; - this.chart = options.chart; - this.canvas_id = options.canvas_id; - this.group = options.groups[0]; - this.data = options.groups[0].values; - this.options = Utils.merge (this.optionsDefault, options); - // get color set - this.color_set = HeatmapParameters.colorSets[this.chart.settings.get('color_set')]; - - // categories - this.categories = Tools.makeUniqueCategories([this.group]); - - // domains/scales - this.xScale = d3.scale.linear().domain([0, this.categories.array.x.length]); - this.yScale = d3.scale.linear().domain([0, this.categories.array.y.length]); - - // color scale - this.zMin = d3.min(this.data, function(d) { return d.z; }); - this.zMax = d3.max(this.data, function(d) { return d.z; }); - this.zScale = d3.scale.quantize().domain([this.zMin, this.zMax]).range(this.color_set); - - // create axis - this.xAxis = d3.svg.axis().scale(this.xScale).orient('bottom'); - this.yAxis = d3.svg.axis().scale(this.yScale).orient('left'); - - // make categories - this._makeTickFormat('x'); - this._makeTickFormat('y'); - - // add tooltip - this.tooltip = d3.select('.charts-viewport-container').append('div') - .attr('class', 'charts-tooltip') - .style(this.options.style) - .style('opacity', 0); - - // refresh on window resize - var self = this; - $(window).on('resize', function () { - self.redraw(); - }); - - // draw - this.redraw(); - - // add zoom - Tools.addZoom({ - xAxis : this.xAxis, - yAxis : this.yAxis, - redraw : function() { self.redraw(); }, - svg : d3.select('#' + this.canvas_id) - }); - }, - - // redraw - redraw: function() { - // get parameters - var chart = this.chart; - var data = this.data; - var self = this; - this.data = data; - - // get/reset container - var container = $('#' + this.canvas_id); - container.empty(); - - // get domain - var xDomain = this.xScale.domain(); - var yDomain = this.yScale.domain(); - - // set ticks - var xTickStart = Math.ceil(xDomain[0]); - var xTickEnd = Math.floor(xDomain[1]); - var yTickStart = Math.ceil(yDomain[0]); - var yTickEnd = Math.floor(yDomain[1]); - this.xAxis.tickValues(d3.range(xTickStart, xTickEnd, 1)); - this.yAxis.tickValues(d3.range(yTickStart, yTickEnd, 1)); - - // get margins - var margin = this.options.margin; - - // configure dimensions - this.height = parseInt(container.height()) - margin.top - margin.bottom; - this.width = parseInt(container.width()) - margin.left - margin.right; - - // set range - this.xScale.range([0, this.width]); - this.yScale.range([this.height, 0]); - - // get box properties - this.rowCount = yDomain[1] - yDomain[0]; - this.colCount = xDomain[1] - xDomain[0]; - this.boxWidth = Math.max(1, Math.floor(this.width / this.colCount)); - this.boxHeight = Math.max(1, Math.floor(this.height / this.rowCount)); - - // create group - var svg = this.svg = d3.select('#' + this.canvas_id) - .append('g') - .attr('class', 'heatmap') - .attr('transform', 'translate(' + margin.left + ',' + margin.top + ')'); - - // build elements - this._buildBoxes(); - this._buildX(); - this._buildY(); - - // show legend only if requested - if (this.chart.settings.get('show_legend') == 'true') { - this._buildLegend(); - } - }, - - // y axis - _buildBoxes: function() { - // link this - var self = this; - - // collect parameters - var height = this.height; - var width = this.width; - var margin = this.options.margin; - var svg = this.svg; - var boxWidth = this.boxWidth; - var boxHeight = this.boxHeight; - - // box location - function _locator(d) { - return 'translate(' + self.xScale(d.x) + ',' + self.yScale(d.y+1) + ')'; - }; - - // box color - function _color (d) { - return self.zScale(d.z); - }; - - // set background color - var gBackground = svg.append('rect') - .attr('width', width) - .attr('height', height) - .attr('fill', this.options.background_color); - - // clip path - var clip = svg.append('clipPath') - .attr('id', 'clip') - .append('rect') - .attr('x', 0) - .attr('y', 0) - .attr('width', width) - .attr('height', height); - - // create chart area - var chartBody = svg.append('g') - .attr('clip-path', 'url(#clip)'); + initialize: function( app, options ) { + var self = this; + this.app = app; + this.chart = options.chart; + this.canvas_id = options.canvas_id; + this.group = options.groups[ 0 ]; + this.data = options.groups[ 0 ].values; + this.options = Utils.merge ( this.optionsDefault, options ); - // add boxes to chart area - var boxes = chartBody.selectAll('box-group').data(this.data, function(d, i) { - return d.x + '\0' + d.y; - }); - var gEnter = boxes.enter().append('g') - .attr('class', 'box-group'); - gEnter.append('rect') - .attr('class','heat-box'); - boxes.selectAll('rect') - .attr('rx', 1) - .attr('ry', 1) - .attr('fill', _color) - .attr('width', boxWidth) - .attr('height', boxHeight) - .attr('transform', _locator); - - // add tooltip events - boxes.selectAll('rect') - .on('dblclick', function(d) { - var url = self.chart.settings.get('url_template').trim(); - if (url) { - d3.event.stopPropagation(); - var xLabel = self.categories.array.x[d.x]; - var yLabel = self.categories.array.y[d.y]; - window.open(url.replace('__LABEL__', xLabel)); - window.open(url.replace('__LABEL__', yLabel)); + // get color set + this.color_set = HeatmapParameters.colorSets[ this.chart.settings.get( 'color_set' ) ]; + + // categories + this.categories = Utilities.makeUniqueCategories( [ this.group ] ); + + // domains/scales + this.xScale = d3.scale.linear().domain( [ 0, this.categories.array.x.length ] ); + this.yScale = d3.scale.linear().domain( [ 0, this.categories.array.y.length ] ); + + // color scale + this.zMin = d3.min( this.data, function( d ) { return d.z; } ); + this.zMax = d3.max( this.data, function( d ) { return d.z; } ); + this.zScale = d3.scale.quantize().domain( [ this.zMin, this.zMax ] ).range( this.color_set ); + + // create axis + this.xAxis = d3.svg.axis().scale( this.xScale ).orient( 'bottom' ); + this.yAxis = d3.svg.axis().scale( this.yScale ).orient( 'left' ); + + // make categories + this._makeTickFormat( 'x' ); + this._makeTickFormat( 'y' ); + + // add tooltip + this.tooltip = d3.select( '.charts-viewport-container' ).append( 'div' ) + .attr( 'class', 'charts-tooltip' ) + .style( this.options.style ) + .style( 'opacity', 0 ); + + // refresh on window resize + $( window ).on( 'resize', function () { self.redraw() } ); + this.redraw(); + Utilities.addZoom({ + xAxis : this.xAxis, + yAxis : this.yAxis, + redraw : function() { self.redraw() }, + svg : d3.select( '#' + this.canvas_id ) + }); + }, + + /** Redraw */ + redraw: function() { + // get parameters + var chart = this.chart; + var data = this.data; + var self = this; + this.data = data; + + // get/reset container + var container = $( '#' + this.canvas_id ); + container.empty(); + + // get domain + var xDomain = this.xScale.domain(); + var yDomain = this.yScale.domain(); + + // set ticks + var xTickStart = Math.ceil( xDomain[ 0 ] ); + var xTickEnd = Math.floor( xDomain[ 1 ] ); + var yTickStart = Math.ceil( yDomain[ 0 ] ); + var yTickEnd = Math.floor( yDomain[ 1 ] ); + this.xAxis.tickValues( d3.range( xTickStart, xTickEnd, 1 ) ); + this.yAxis.tickValues( d3.range( yTickStart, yTickEnd, 1 ) ); + + // get margins + var margin = this.options.margin; + + // configure dimensions + this.height = parseInt( container.height() ) - margin.top - margin.bottom; + this.width = parseInt( container.width() ) - margin.left - margin.right; + + // set range + this.xScale.range( [ 0, this.width ] ); + this.yScale.range( [ this.height, 0 ] ); + + // get box properties + this.rowCount = yDomain[ 1 ] - yDomain[ 0 ]; + this.colCount = xDomain[ 1 ] - xDomain[ 0 ]; + this.boxWidth = Math.max( 1, Math.floor( this.width / this.colCount ) ); + this.boxHeight = Math.max( 1, Math.floor( this.height / this.rowCount ) ); + + // create group + var svg = this.svg = d3.select( '#' + this.canvas_id ) + .append( 'g' ) + .attr( 'class', 'heatmap' ) + .attr( 'transform', 'translate(' + margin.left + ',' + margin.top + ')' ); + + // build elements + this._buildBoxes(); + this._buildX(); + this._buildY(); + + // show legend only if requested + if ( this.chart.settings.get('show_legend') == 'true' ) { + this._buildLegend(); } - }) - .on('mouseover', function(d) { - self.tooltip.style('opacity', 0.9); - self.tooltip .html(self._templateTooltip(d)) - .style('left', (d3.event.pageX) + 'px') - .style('top', (d3.event.pageY - 20) + 'px'); - }) - .on('mouseout', function(d) { - self.tooltip.style('opacity', 0); - }); + }, + + /** Build boxes */ + _buildBoxes: function() { + var self = this; + var height = this.height; + var width = this.width; + var margin = this.options.margin; + var svg = this.svg; + var boxWidth = this.boxWidth; + var boxHeight = this.boxHeight; + function _locator( d ) { return 'translate(' + self.xScale( d.x ) + ',' + self.yScale( d.y + 1 ) + ')' }; + function _color ( d ) { return self.zScale( d.z ) }; - // initially hide tooltips - this.tooltip.style('opacity', 0); - - // exit - boxes.exit().remove(); - }, - - // x axis - _buildX : function() { - // link this - var self = this; - - // collect parameters - var height = this.height; - var width = this.width; - var margin = this.options.margin; - var svg = this.svg; - var font_size = this.options.style['font-size']; - var boxWidth = this.boxWidth; - - // draw x axis - this.gxAxis = svg.append('g') - .attr('class', 'x axis') - .style('stroke-width', 1) - .attr('transform', 'translate(0,' + height + ')') - .call(this.xAxis); - - // fix text - var xFontSize = Math.min(boxWidth, font_size); - this.gxAxis.selectAll('text') - .style(this.options.style) - .style({'font-size': xFontSize + 'px'}) - .attr('transform', function(d) { - var y = -this.getBBox().height - 15; - var x = -xFontSize + boxWidth/2; - return 'rotate(-90)translate(' + y + ',' + x + ')'; - }); - - // set background color - var gxAxisLabelBackground = svg.append('rect') - .attr('width', width) - .attr('height', font_size + 3) - .attr('y', height + margin.bottom - font_size - 3) - .attr('fill', this.options.debug_color) - .attr('opacity', 0.7); - - // axis label - this.gxAxisLabel = svg.append('text') - .attr('class', 'x label') - .style(this.options.style) - .text(this.chart.settings.get('x_axis_label')) - .attr('transform', function(d) { - var y = height + margin.bottom - font_size/3; - var x = (width - this.getBBox().width)/2; - return 'translate(' + x + ',' + y + ')'; - }); - - // chart title - this.gxTickLabel = svg.append('text') - .attr('class', 'title') - .style(this.options.style) - .style({'font-size' : 1.5*font_size}) - .text(this.group.key) - .attr('transform', function(d) { - var y = -margin.top/2; - var x = (width - this.getBBox().width)/2; - return 'translate(' + x + ',' + y + ')'; - }); - }, - - // y axis - _buildY : function() { - // link this - var self = this; - - // collect parameters - var height = this.height; - var width = this.width; - var margin = this.options.margin; - var svg = this.svg; - var font_size = this.options.style['font-size']; - var boxHeight = this.boxHeight; - - // draw y axis - this.gyAxis = svg.append('g') - .attr('class', 'y axis') - .style('stroke-width', 1) - .call(this.yAxis); + // set background color + var gBackground = svg.append( 'rect' ) + .attr( 'width', width ) + .attr( 'height', height ) + .attr( 'fill', this.options.background_color ); - // fix text - var yFontSize = Math.min(boxHeight, font_size); - this.gyAxis.selectAll('text') - .style(this.options.style) - .style({'font-size': yFontSize + 'px'}) - .attr('y', -boxHeight/2); - - // set background color - var gyAxisLabelBackground = svg.append('rect') - .attr('width', font_size) - .attr('height', height) - .attr('x', -margin.left) - .attr('fill', this.options.debug_color) - .attr('opacity', 0.7); - - // axis label - this.gyAxisLabel = svg.append('text') - .attr('class', 'y label') - .style(this.options.style) - .text(this.chart.settings.get('y_axis_label')) - .attr('transform', function(d) { - var x = -margin.left + font_size-2; - var y = -(height + this.getBBox().width)/2; - return 'rotate(-90)translate(' + y + ',' + x + ')'; - }); - }, + // clip path + var clip = svg.append( 'clipPath' ) + .attr( 'id', 'clip' ) + .append( 'rect' ) + .attr( 'x', 0 ) + .attr( 'y', 0 ) + .attr( 'width', width ) + .attr( 'height', height ); - // legend - _buildLegend : function() { - // link this - var self = this; - - // collect parameters - var height = this.height; - var width = this.width; - var margin = this.options.margin; - var font_size = this.options.legend.style['font-size']; - var limit = this.options.legend.limit; + // create chart area + var chartBody = svg.append( 'g' ).attr( 'clip-path', 'url(#clip)' ); - // identify legend dimensions - var legendSize = this.options.legend.size; - var legendWidth = this.options.legend.width; - var legendElements = this.zScale.range().length; - var legendElementHeight = Math.max(legendSize * height / legendElements, font_size); - var legendHeight = legendElements * legendElementHeight / 2; + // add boxes to chart area + var boxes = chartBody.selectAll( 'box-group' ).data( this.data, function( d, i ) { + return d.x + '\0' + d.y; + }); + var gEnter = boxes.enter().append( 'g' ) + .attr( 'class', 'box-group' ); + gEnter.append( 'rect' ) + .attr( 'class','heat-box' ); + boxes.selectAll( 'rect' ) + .attr( 'rx', 1 ) + .attr( 'ry', 1 ) + .attr( 'fill', _color ) + .attr( 'width', boxWidth ) + .attr( 'height', boxHeight ) + .attr( 'transform', _locator ); + + // add tooltip events + boxes.selectAll( 'rect' ) + .on( 'dblclick', function( d ) { + var url = self.chart.settings.get( 'url_template' ).trim(); + if ( url ) { + d3.event.stopPropagation(); + var xLabel = self.categories.array.x[ d.x ]; + var yLabel = self.categories.array.y[ d.y ]; + window.open( url.replace( '__LABEL__', xLabel ) ); + window.open( url.replace( '__LABEL__', yLabel ) ); + } + }) + .on('mouseover', function( d ) { + self.tooltip.style( 'opacity', 0.9 ); + self.tooltip .html( self._templateTooltip( d ) ) + .style( 'left', ( d3.event.pageX ) + 'px' ) + .style( 'top', ( d3.event.pageY - 20 ) + 'px' ); + }) + .on('mouseout', function( d ) { + self.tooltip.style( 'opacity', 0 ); + }); + + // initially hide tooltips + this.tooltip.style( 'opacity', 0 ); + + // exit + boxes.exit().remove(); + }, - // check number of legend elements - var data = d3.range(this.zMin, this.zMax, 2 * (this.zMax-this.zMin) / legendElements).reverse(); - if (data.length < 2) { - return; - } - - // create legend elements - var legend = this.svg.selectAll('.legend') - .data(data) - .enter().append('g') - .attr('class', 'legend') - .attr('transform', function(d, i) { - var x = width + 10; - var y = ((height - legendHeight) / 2) + (i * legendElementHeight); + /** Build x axis */ + _buildX : function() { + var self = this; + var height = this.height; + var width = this.width; + var margin = this.options.margin; + var svg = this.svg; + var font_size = this.options.style[ 'font-size' ]; + var boxWidth = this.boxWidth; + + // draw x axis + this.gxAxis = svg.append( 'g' ) + .attr( 'class', 'x axis' ) + .style( 'stroke-width', 1 ) + .attr( 'transform', 'translate(0,' + height + ')' ) + .call( this.xAxis ); + + // fix text + var xFontSize = Math.min( boxWidth, font_size ); + this.gxAxis.selectAll( 'text' ) + .style( this.options.style ) + .style( { 'font-size': xFontSize + 'px' } ) + .attr( 'transform', function( d ) { + var y = -this.getBBox().height - 15; + var x = -xFontSize + boxWidth / 2; + return 'rotate(-90)translate(' + y + ',' + x + ')'; + }); + + // set background color + var gxAxisLabelBackground = svg.append( 'rect' ) + .attr( 'width', width ) + .attr( 'height', font_size + 3 ) + .attr( 'y', height + margin.bottom - font_size - 3 ) + .attr( 'fill', this.options.debug_color ) + .attr( 'opacity', 0.7 ); + + // axis label + this.gxAxisLabel = svg.append( 'text' ) + .attr( 'class', 'x label' ) + .style( this.options.style ) + .text( this.chart.settings.get( 'x_axis_label' ) ) + .attr( 'transform', function( d ) { + var y = height + margin.bottom - font_size / 3; + var x = ( width - this.getBBox().width ) / 2; return 'translate(' + x + ',' + y + ')'; }); - - legend.append('rect') - .attr('width', legendWidth) - .attr('height', legendElementHeight) - .style('fill', function(z) { - return self.zScale(z); - }); - - legend.append('text') - .attr('x', legendWidth + 4) - .attr('y', function() { - return (legendElementHeight+this.getBBox().height)/2; - }) - .style(this.options.legend.style) - .text(function(d) { - var str = String(d); - if (str.length > limit) { - return str.substr(0, limit-2) + '..'; - } else { - return str; - } - }); - - this.svg.append('text') - .style(this.options.legend.style) - .style({'font-size' : 9, 'font-weight': 'bold'}) - .text('Legend') - .attr('transform', function(d, i) { - var x = width + (margin.right - this.getBBox().width) / 2; - var y = ((height - legendHeight) / 2) - 10; - return 'translate(' + x + ',' + y + ')'; - }); - }, - - // create axes formatting - _makeTickFormat: function(id) { - var settings = this.chart.settings; - var self = this; - Tools.makeTickFormat({ - categories : self.categories.array[id], - type : settings.get(id + '_axis_type'), - precision : settings.get(id + '_axis_precision'), - formatter : function(formatter) { - if (formatter) { - self[id + 'Axis'].tickFormat(function(value) { - return formatter(value); - }); - } - } - }); - }, - - // handle error - _handleError: function(err) { - this.chart.state('failed', err); - }, - - // templates - _templateTooltip: function(d) { - // collect data values - var x = this.categories.array.x[d.x]; - var y = this.categories.array.y[d.y]; - var z = d.z; + + // chart title + this.gxTickLabel = svg.append( 'text' ) + .attr( 'class', 'title' ) + .style( this.options.style ) + .style({'font-size' : 1.1 * font_size } ) + .text( this.group.key ) + .attr( 'transform', function( d ) { + var y = -margin.top / 2; + var x = ( width - this.getBBox().width ) / 2; + return 'translate(' + x + ',' + y + ')'; + }); + }, - // create tooltip - var tmpl = '' + + /** Build y axis */ + _buildY : function() { + var self = this; + var height = this.height; + var width = this.width; + var margin = this.options.margin; + var svg = this.svg; + var font_size = this.options.style[ 'font-size' ]; + var boxHeight = this.boxHeight; + + // draw y axis + this.gyAxis = svg.append( 'g' ) + .attr( 'class', 'y axis' ) + .style( 'stroke-width', 1 ) + .call( this.yAxis ); + + // fix text + var yFontSize = Math.min( boxHeight, font_size ); + this.gyAxis.selectAll( 'text' ) + .style( this.options.style ) + .style( { 'font-size': yFontSize + 'px' } ) + .attr( 'y', -boxHeight / 2 ); + + // set background color + var gyAxisLabelBackground = svg.append( 'rect' ) + .attr( 'width', font_size ) + .attr( 'height', height ) + .attr( 'x', -margin.left ) + .attr( 'fill', this.options.debug_color ) + .attr( 'opacity', 0.7 ); + + // axis label + this.gyAxisLabel = svg.append( 'text' ) + .attr( 'class', 'y label' ) + .style( this.options.style ) + .text( this.chart.settings.get( 'y_axis_label' ) ) + .attr( 'transform', function( d ) { + var x = -margin.left + font_size - 2; + var y = -( height + this.getBBox().width ) / 2; + return 'rotate(-90)translate(' + y + ',' + x + ')'; + }); + }, + + /** Build legend */ + _buildLegend : function() { + var self = this; + var height = this.height; + var width = this.width; + var margin = this.options.margin; + var font_size = this.options.legend.style[ 'font-size' ]; + var limit = this.options.legend.limit; + var legendSize = this.options.legend.size; + var legendWidth = this.options.legend.width; + var legendElements = this.zScale.range().length; + var legendElementHeight = Math.max( legendSize * height / legendElements, font_size ); + var legendHeight = legendElements * legendElementHeight / 2; + var data = d3.range( this.zMin, this.zMax, 2 * ( this.zMax - this.zMin ) / legendElements ).reverse(); + if ( data.length < 2 ) { + return; + } + var legend = this.svg.selectAll( '.legend' ) + .data( data ) + .enter().append( 'g' ) + .attr( 'class', 'legend' ) + .attr( 'transform', function( d, i ) { + var x = width + 10; + var y = ( ( height - legendHeight ) / 2 ) + ( i * legendElementHeight ); + return 'translate(' + x + ',' + y + ')'; + }); + legend.append( 'rect' ) + .attr( 'width', legendWidth ) + .attr( 'height', legendElementHeight ) + .style( 'fill', function( z ) { return self.zScale( z ) } ); + legend.append('text') + .attr( 'x', legendWidth + 4 ) + .attr( 'y', function() { return ( legendElementHeight + this.getBBox().height ) / 2 } ) + .style( this.options.legend.style ) + .text( function( d ) { return String( d ).length > limit ? String( d ).substr( 0, limit - 2 ) + '..' : String( d ) } ); + this.svg.append( 'text' ) + .style( this.options.legend.style ) + .style( { 'font-size' : 9, 'font-weight': 'bold' } ) + .text( 'Legend' ) + .attr( 'transform', function( d, i ) { + var x = width + ( margin.right - this.getBBox().width ) / 2; + var y = ( ( height - legendHeight ) / 2 ) - 10; + return 'translate(' + x + ',' + y + ')'; + }); + }, + + /** Create axes formatting */ + _makeTickFormat: function( id ) { + var settings = this.chart.settings; + var self = this; + Utilities.makeTickFormat({ + categories : self.categories.array[ id ], + type : settings.get( id + '_axis_type|type' ), + precision : settings.get( id + '_axis_type|precision' ), + formatter : function( formatter ) { + if ( formatter ) { + self[ id + 'Axis' ].tickFormat( function( value ) { + return formatter( value ); + }); + } + } + }); + }, + + /** Handle error */ + _handleError: function( err ) { + this.chart.state( 'failed', err ); + }, + + /** Main template */ + _templateTooltip: function(d) { + var x = this.categories.array.x[ d.x ]; + var y = this.categories.array.y[ d.y ]; + var z = d.z; + return '
' + '' + '' + '' + @@ -456,8 +399,6 @@ return Backbone.View.extend({ '' + '' + '
Row:' + y + '' + z + '
'; - return tmpl; - } -}); - + } + }); }); \ No newline at end of file diff --git a/config/plugins/visualizations/charts/static/charts/others/heatmap/wrapper.js b/config/plugins/visualizations/charts/static/charts/others/heatmap/wrapper.js index b4232e69490..5179271ccc8 100644 --- a/config/plugins/visualizations/charts/static/charts/others/heatmap/wrapper.js +++ b/config/plugins/visualizations/charts/static/charts/others/heatmap/wrapper.js @@ -1,23 +1,15 @@ -// dependencies -define(['plugin/charts/tools', 'plugin/charts/others/heatmap/heatmap-plugin'], function(Tools, HeatMap) { - -// widget -return Backbone.View.extend({ - // initialize - initialize: function(app, options) { - // define render function - options.render = function(canvas_id, groups) { - new HeatMap(app, { - chart : options.chart, - canvas_id : canvas_id, - groups : groups - }); - return true; - }; - - // call panel helper - Tools.panelHelper(app, options); - } -}); - +define( [ 'plugin/charts/utilities/tabular-utilities', 'plugin/charts/others/heatmap/heatmap-plugin' ], function( Utilities, HeatMap ) { + return Backbone.View.extend({ + initialize: function( app, options ) { + options.render = function( canvas_id, groups ) { + new HeatMap( app, { + chart : options.chart, + canvas_id : canvas_id, + groups : groups + }); + return true; + }; + Utilities.panelHelper( options ); + } + }); }); \ No newline at end of file diff --git a/config/plugins/visualizations/charts/static/charts/others/heatmap_cluster/config.js b/config/plugins/visualizations/charts/static/charts/others/heatmap_cluster/config.js index fd8cbc98108..a1304daa2c2 100644 --- a/config/plugins/visualizations/charts/static/charts/others/heatmap_cluster/config.js +++ b/config/plugins/visualizations/charts/static/charts/others/heatmap_cluster/config.js @@ -1,10 +1,7 @@ -define(['plugin/charts/others/heatmap/config'], function(config_default) { - -return $.extend(true, {}, config_default, { - title : 'Clustered Heatmap', - category : 'Data processing (requires \'charts\' tool from Toolshed)', - execute : 'heatmap', - keywords : 'small medium large' -}); - +define( [ 'plugin/charts/others/heatmap/config' ], function( default_config ) { + return $.extend( true, {}, default_config, { + title : 'Clustered Heatmap', + category : 'Data processing (requires \'charts\' tool from Toolshed)', + keywords : 'others default' + }); }); \ No newline at end of file diff --git a/config/plugins/visualizations/charts/static/charts/others/heatmap_cluster/wrapper.js b/config/plugins/visualizations/charts/static/charts/others/heatmap_cluster/wrapper.js index 9ced4ec1fed..79d6c97fe3a 100644 --- a/config/plugins/visualizations/charts/static/charts/others/heatmap_cluster/wrapper.js +++ b/config/plugins/visualizations/charts/static/charts/others/heatmap_cluster/wrapper.js @@ -1,55 +1,40 @@ -// dependencies -define(['plugin/charts/tools', 'plugin/charts/others/heatmap/heatmap-plugin'], function(Tools, HeatMap) { - -// widget -return Backbone.View.extend({ - // initialize - initialize: function(app, options) { - // get request dictionary - var request_dictionary = options.request_dictionary; - - // configure request - var index = 0; - var tmp_dict = { - id : request_dictionary.id, - groups : [] - }; - - // configure groups - for (var group_index in request_dictionary.groups) { - var group = request_dictionary.groups[group_index]; - tmp_dict.groups.push({ - key : group.key, - columns : { - x: { - index : index++, - is_label : true - }, - y: { - index : index++, - is_label : true - }, - z: { - index : index++ - } +define( [ 'plugin/charts/utilities/tabular-utilities', 'plugin/components/jobs', 'plugin/charts/others/heatmap/heatmap-plugin' ], function( Utilities, Jobs, HeatMap ) { + return Backbone.View.extend({ + initialize: function(app, options) { + Jobs.request( app, Utilities.buildJobDictionary( 'heatmap', app.chart ), function( dataset ) { + var request_dictionary = Utilities.buildRequestDictionary( app.chart, dataset.id ); + var index = 0; + var tmp_dict = { id : request_dictionary.id, groups : [] }; + for ( var group_index in request_dictionary.groups ) { + var group = request_dictionary.groups[ group_index ]; + tmp_dict.groups.push({ + key : group.key, + columns : { + x: { + index : index++, + is_label : true + }, + y: { + index : index++, + is_label : true + }, + z: { + index : index++ + } + } + }); } - }); + options.request_dictionary = tmp_dict; + options.render = function( canvas_id, groups ) { + new HeatMap( app, { + chart : options.chart, + canvas_id : canvas_id, + groups : groups + }); + return true; + }; + Utilities.panelHelper( options ); + }, function() { options.process.reject() } ); } - - // define render function - options.request_dictionary = tmp_dict; - options.render = function(canvas_id, groups) { - new HeatMap(app, { - chart : options.chart, - canvas_id : canvas_id, - groups : groups - }); - return true; - }; - - // call panel helper - Tools.panelHelper(app, options); - } -}); - + }); }); \ No newline at end of file diff --git a/config/plugins/visualizations/charts/static/charts/overview.js b/config/plugins/visualizations/charts/static/charts/overview.js new file mode 100644 index 00000000000..df07c21ca70 --- /dev/null +++ b/config/plugins/visualizations/charts/static/charts/overview.js @@ -0,0 +1,13 @@ +define( [], function() { + return [ + { label : 'Default', value: 'default', + help : 'The visualizations below were curated from different libraries. Its a representative set covering most use cases. Use this selection by default.' }, + { label : 'NVD3', value: 'nvd3', + help : 'NVD3 is a popular d3-based library hosted at www.nvd3.org. Most visualization types support intuitive drag-and-drop zooming and scaling. NVD3 generates high quality vector graphics. As with all vector based plugins, you may experience a slow down in browser responsiveness if visualizing thousands of data points.' }, + { label : 'jqPlot', value: 'jqplot', + help : 'jqPlot is a canvas-based library hosted at www.jqplot.com. It is a plotting and charting plugin for the jQuery Javascript framework. Since based on canvas it is capable of rendering many thousand data points without adverse effects.' }, + { label : 'Others', value: 'others', + help : 'These visualizations were developed by the Galaxy team.' + } + ]; +}); \ No newline at end of file diff --git a/config/plugins/visualizations/charts/static/charts/tools.js b/config/plugins/visualizations/charts/static/charts/tools.js deleted file mode 100644 index 6597ad191c1..00000000000 --- a/config/plugins/visualizations/charts/static/charts/tools.js +++ /dev/null @@ -1,379 +0,0 @@ -// dependencies -define(['utils/utils'], function(Utils) { - -// render -function panelHelper (app, options) { - // link this - var self = this; - - // require parameters - var process = options.process; - var chart = options.chart; - var request_dictionary = options.request_dictionary; - var render = options.render; - var canvas_list = options.canvas_list; - - // get request size from chart - request_dictionary.query_limit = chart.definition.query_limit; - - // define success function - request_dictionary.success = function() { - try { - // check if this chart has multiple panels - if (chart.settings.get('use_panels') === 'true') { - // draw groups in separate panels - var valid = true; - for (var group_index in request_dictionary.groups) { - var group = request_dictionary.groups[group_index]; - if (!render(canvas_list[group_index], [group])) { - valid = false; - break; - } - } - if (valid) { - chart.state('ok', 'Multi-panel chart drawn.'); - } - } else { - // draw all groups into a single panel - if (render(canvas_list[0], request_dictionary.groups)) { - chart.state('ok', 'Chart drawn.'); - } - } - - // unregister process - process.resolve(); - } catch (err) { - // log - console.debug('FAILED: Tools::panelHelper() - ' + err); - - // set chart state - chart.state('failed', err); - - // unregister process - process.reject(); - } - }; - - // add progress - request_dictionary.progress = function(percentage) { - if (chart.get('state') == 'wait') { - chart.state('wait', 'Loading data...' + percentage + '%'); - } - }; - - // request data - app.datasets.request(request_dictionary); -}; - -// get domain boundaries value -function getDomains(groups, keys) { - - // get value - function _apply(operator, key) { - var value = undefined; - for (var group_index in groups) { - var value_sub = d3[operator](groups[group_index].values, function(d) { return d[key]; }); - if (value === undefined) { - value = value_sub; - } else { - value = 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) { - // plot data - var plot_data = []; - - // loop through data groups - for (var group_index in groups) { - // get group - var group = groups[group_index]; - - // reset data - var data = []; - - // format chart data - for (var value_index in group.values) { - // parse data - var point = []; - if (keys) { - for (var key_index in keys) { - var column_index = keys[key_index]; - point.push(group.values[value_index][column_index]); - } - } else { - for (var column_index in group.values[value_index]) { - point.push(group.values[value_index][column_index]); - } - } - - // add to data - data.push (point); - } - - // append series - plot_data.push(data); - } - - // return - return plot_data; -}; - -// default category maker -function makeCategories(groups, with_index) { - // hashkeys, arrays and counter for labeled columns - var array = {}; - - // identify label columns - var chart_definition = groups[0]; - for (var key in chart_definition.columns) { - var column_def = chart_definition.columns[key]; - if (column_def.is_label) { - array[key] = []; - } - } - - // collect string labels in array - if (groups && groups[0]) { - var group = groups[0]; - for (var j in group.values) { - var value_dict = group.values[j]; - for (var key in array) { - array[key].push (String(value_dict[key])); - } - } - } - - // index all values contained in label columns (for all groups) - mapCategories(array, groups); - - // return dictionary - return { - array : array - } -}; - -// apply default mapping -// index all values contained in label columns (for all groups) -function mapCategories(array, 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 array) { - value_dict[key] = parseInt(j) - } - } - } -}; - -// category make for unique category labels -function makeUniqueCategories(groups, with_index) { - // hashkeys, arrays and counter for labeled columns - var categories = {}; - var array = {}; - var counter = {}; - - // identify label columns - var chart_definition = groups[0]; - for (var key in chart_definition.columns) { - var column_def = chart_definition.columns[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) { - // add index - categories[key][value] = counter[key]; - - // array formatter - if (with_index) { - array[key].push([counter[key], value]); - } else { - array[key].push(value); - } - - // increase counter - counter[key]++; - } - } - } - } - - // convert group values into category indeces - 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]); - value_dict[key] = categories[key][value] - } - } - } - - // return dictionary - 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; - - // hide axis - if (type == 'hide') { - formatter(function() { return '' }); - return; - } - - // format values/labels - 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) { - // scaleExtent - var scaleExtent = 100; - - // parameters - 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; - - // scales - var xScale = xAxis.scale(); - var yScale = yAxis.scale(); - - // min/max boundaries - var x_boundary = xScale.domain().slice(); - var y_boundary = yScale.domain().slice(); - - // create d3 zoom handler - var d3zoom = d3.behavior.zoom(); - - // ensure nice axis - xScale.nice(); - yScale.nice(); - - // fix domain - 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; - }; - - // zoom event handler - function zoomed() { - yDomain(fixDomain(yScale.domain(), y_boundary)); - xDomain(fixDomain(xScale.domain(), x_boundary)); - redraw(); - }; - - // zoom event handler - function unzoomed() { - xDomain(x_boundary); - yDomain(y_boundary); - redraw(); - d3zoom.scale(1); - d3zoom.translate([0,0]); - }; - - // initialize wrapper - d3zoom.x(xScale) - .y(yScale) - .scaleExtent([1, scaleExtent]) - .on('zoom', zoomed); - - // add handler - svg.call(d3zoom).on('dblclick.zoom', unzoomed); - - // return - return d3zoom; -}; - -// return -return { - panelHelper : panelHelper, - makeCategories : makeCategories, - makeUniqueCategories : makeUniqueCategories, - makeSeries : makeSeries, - getDomains : getDomains, - mapCategories : mapCategories, - makeTickFormat : makeTickFormat, - addZoom : addZoom -} - -}); diff --git a/config/plugins/visualizations/charts/static/charts/types.js b/config/plugins/visualizations/charts/static/charts/types.js index b294db8323e..07b17cc443a 100644 --- a/config/plugins/visualizations/charts/static/charts/types.js +++ b/config/plugins/visualizations/charts/static/charts/types.js @@ -1,4 +1,3 @@ -// dependencies define(['plugin/charts/nvd3/bar/config', 'plugin/charts/nvd3/bar_stacked/config', 'plugin/charts/nvd3/bar_horizontal/config', @@ -8,6 +7,7 @@ define(['plugin/charts/nvd3/bar/config', 'plugin/charts/nvd3/stackedarea_full/config', 'plugin/charts/nvd3/stackedarea_stream/config', 'plugin/charts/nvd3/histogram/config', + 'plugin/charts/nvd3/histogram_discrete/config', 'plugin/charts/nvd3/line/config', 'plugin/charts/nvd3/scatter/config', 'plugin/charts/nvd3/stackedarea/config', @@ -17,33 +17,30 @@ define(['plugin/charts/nvd3/bar/config', 'plugin/charts/jqplot/boxplot/config', 'plugin/charts/jqplot/histogram_discrete/config', 'plugin/charts/others/heatmap/config', - 'plugin/charts/others/heatmap_cluster/config' - ], function(nvd3_bar, - nvd3_bar_stacked, - nvd3_bar_horizontal, - nvd3_bar_horizontal_stacked, - nvd3_line_focus, - nvd3_pie, - nvd3_stackedarea_full, - nvd3_stackedarea_stream, - nvd3_histogram, - nvd3_line, - nvd3_scatter, - nvd3_stackedarea, - jqplot_bar, - jqplot_line, - jqplot_scatter, - jqplot_boxplot, - jqplot_histogram_discrete, - others_heatmap, - others_heatmap_cluster - ) { - -// widget -return Backbone.Model.extend( -{ - // types - defaults: { + 'plugin/charts/others/heatmap_cluster/config', + 'plugin/charts/others/example/config' ], + function(nvd3_bar, + nvd3_bar_stacked, + nvd3_bar_horizontal, + nvd3_bar_horizontal_stacked, + nvd3_line_focus, + nvd3_pie, + nvd3_stackedarea_full, + nvd3_stackedarea_stream, + nvd3_histogram, + nvd3_histogram_discrete, + nvd3_line, + nvd3_scatter, + nvd3_stackedarea, + jqplot_bar, + jqplot_line, + jqplot_scatter, + jqplot_boxplot, + jqplot_histogram_discrete, + others_heatmap, + others_heatmap_cluster, + others_example) { + return { 'nvd3_bar' : nvd3_bar, 'nvd3_bar_stacked' : nvd3_bar_stacked, 'nvd3_bar_horizontal' : nvd3_bar_horizontal, @@ -56,14 +53,14 @@ return Backbone.Model.extend( 'nvd3_line' : nvd3_line, 'nvd3_scatter' : nvd3_scatter, 'nvd3_histogram' : nvd3_histogram, + 'nvd3_histogram_discrete' : nvd3_histogram_discrete, 'jqplot_bar' : jqplot_bar, 'jqplot_histogram_discrete' : jqplot_histogram_discrete, 'jqplot_line' : jqplot_line, 'jqplot_scatter' : jqplot_scatter, 'jqplot_boxplot' : jqplot_boxplot, 'others_heatmap' : others_heatmap, - 'others_heatmap_cluster' : others_heatmap_cluster + 'others_heatmap_cluster' : others_heatmap_cluster, + 'others_example' : others_example } -}); - }); \ No newline at end of file diff --git a/config/plugins/visualizations/charts/static/charts/utilities/tabular-datasets.js b/config/plugins/visualizations/charts/static/charts/utilities/tabular-datasets.js new file mode 100644 index 00000000000..33edc97622e --- /dev/null +++ b/config/plugins/visualizations/charts/static/charts/utilities/tabular-datasets.js @@ -0,0 +1,122 @@ +/** This class handles, formats and caches datasets. */ +define( [ 'utils/utils' ], function( Utils ) { + /** Fills request dictionary with data from cache/response */ + var _cache = {}; + var request = function( options ) { + // identify columns needed to fulfill request + var column_list = []; + _.each( options.groups, function( group ) { + _.each( group.columns, function( column ) { + var column = column.index; + var block_id = _block_id( options, 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 : Galaxy.root + 'api/datasets/' + options.id, + data : { + data_type : 'raw_data', + provider : 'dataset-column', + indeces : column_list.toString() + }, + success : function( response ) { + var results = new Array( column_list.length ); + for ( var i = 0; i < results.length; i++ ) { + results[ i ] = []; + } + for ( var i in response.data ) { + var row = response.data[ i ]; + for ( var j in row ) { + var v = row[ j ]; + if ( v !== undefined && v != 2147483647 ) { + results[ j ].push( v ); + } + } + } + console.debug( 'tabular-datasets::_fetch() - Fetching complete.' ); + for ( var i in results ) { + var column = column_list[ i ]; + var block_id = _block_id( options, column ); + _cache[ block_id ] = results[ i ]; + } + _fillFromCache( options ); + } + }); + + }; + + /** Fill data from cache */ + var _fillFromCache = function( options ) { + var result = Utils.clone( options ); + console.debug( 'tabular-datasets::_fillFromCache() - Filling request from cache.' ); + var limit = 0; + for ( var i in result.groups ) { + var group = result.groups[ i ]; + for ( var key in group.columns ) { + var column = group.columns[ key ]; + var block_id = _block_id( result, column.index ); + var column_data = _cache[ block_id ]; + if ( column_data ) { + limit = Math.max( limit, column_data.length ); + } + } + } + if ( limit == 0 ) { + console.debug( 'tabular-datasets::_fillFromCache() - Reached data range limit.' ); + } + for ( var i in result.groups ) { + var group = result.groups[ i ]; + group.values = []; + for ( var j = 0; j < limit; j++ ) { + group.values[ j ] = { x : parseInt( j ) }; + } + } + for ( var i in result.groups ) { + var group = result.groups[ i ]; + for ( var key in group.columns ) { + var column = group.columns[ key ]; + switch ( column.index ) { + case 'auto': + for ( var j = 0; j < limit; j++ ) { + var value = group.values[ j ]; + value[ key ] = parseInt( j ); + } + break; + case 'zero': + for ( var j = 0; j < limit; j++ ) { + var value = group.values[ j ]; + value[ key ] = 0; + } + break; + default: + var block_id = _block_id( result, column.index ); + var column_data = _cache[ block_id ]; + for ( var j = 0; j < limit; j++ ) { + var value = group.values[ j ]; + var v = column_data[ j ]; + if ( isNaN( v ) && !column.is_label && !column.is_text ) { + v = 0; + } + value[ key ] = v; + } + } + } + } + options.success( result ); + }; + + /** Get block id */ + var _block_id = function ( options, column ) { + return options.id + '_' + '_' + column; + }; + + return { request: request }; +}); \ No newline at end of file diff --git a/config/plugins/visualizations/charts/static/charts/utilities/tabular-form.js b/config/plugins/visualizations/charts/static/charts/utilities/tabular-form.js new file mode 100644 index 00000000000..b7c22827d57 --- /dev/null +++ b/config/plugins/visualizations/charts/static/charts/utilities/tabular-form.js @@ -0,0 +1,26 @@ +define( [ 'plugin/charts/utilities/tabular-inputs' ], function( Inputs ) { + return { + title : '', + category : '', + library : '', + tag : '', + keywords : '', + datatype : 'tabular', + settings : { + x_axis_label : Inputs.axisLabel( 'x_axis_label' ), + x_axis_type : Inputs.axisType( 'x_axis_type' ), + y_axis_label : Inputs.axisLabel( 'y_axis_label' ), + y_axis_type : Inputs.axisType( 'y_axis_type' ), + show_legend : Inputs.boolean( 'show_legend', { label: 'Show legend', help: 'Would you like to add a legend?' } ), + use_panels : Inputs.boolean( 'use_panels', { label: 'Use multi-panels', help: 'Would you like to separate your data into individual panels?' } ) + }, + groups : { + key: { + label : 'Provide a label', + type : 'text', + placeholder : 'Data label', + value : 'Data label' + } + } + } +}); \ No newline at end of file diff --git a/config/plugins/visualizations/charts/static/charts/utilities/tabular-inputs.js b/config/plugins/visualizations/charts/static/charts/utilities/tabular-inputs.js new file mode 100644 index 00000000000..742c1517b46 --- /dev/null +++ b/config/plugins/visualizations/charts/static/charts/utilities/tabular-inputs.js @@ -0,0 +1,65 @@ +define( [], function() { + return { + axisLabel : function( name, options ) { + options = options || {}; + prefix = name.substr( 0, 1 ); + return { + name : name, + label : prefix.toUpperCase() + '-Axis label', + help : 'Provide a label for the axis.', + type : 'text', + value : options.value || prefix.toUpperCase() + '-axis', + placeholder : 'Axis label' + } + }, + axisType : function( name, options ) { + options = options || {}; + prefix = name.substr( 0, 1 ); + var axisPrecision = function() { + return { name : 'precision', + label : 'Axis tick format', + help : 'Select the tick format for the axis.', + type : 'select', + value : options.precision || 1, + data : [ { label : '0.00001', value : '5' }, + { label : '0.0001', value : '4' }, + { label : '0.001', value : '3' }, + { label : '0.01', value : '2' }, + { label : '0.1', value : '1' }, + { label : '1', value : '0' } ] } + } + return { + name : prefix + '_axis_type', + type : 'conditional', + test_param : { + name : 'type', + label : prefix.toUpperCase() + '-Axis value type', + type : 'select', + value : options.value || 'auto', + help : 'Select the value type of the axis.', + data : [ { value : 'hide', label : '-- Do not show values --' }, + { value : 'auto', label : 'Auto' }, + { value : 'f', label : 'Float' }, + { value : 'd', label : 'Integer' }, + { value : 'e', label : 'Exponent' }, + { value : 'p', label : 'Percent' }, + { value : 's', label : 'SI-prefix' } ] + }, + cases : [ { value : 'hide' }, + { value : 'auto' }, + { value : 'f', inputs: [ axisPrecision() ] }, + { value : 'd' }, + { value : 'e', inputs: [ axisPrecision() ] }, + { value : 'p', inputs: [ axisPrecision() ] }, + { value : 's' } ] + } + }, + boolean : function( name, options ) { + options = options || {}; + return { name : name, + label : options.label, + help : options.help, + type : 'boolean' } + } + } +}); \ No newline at end of file diff --git a/config/plugins/visualizations/charts/static/charts/utilities/tabular-utilities.js b/config/plugins/visualizations/charts/static/charts/utilities/tabular-utilities.js new file mode 100644 index 00000000000..dec6f2a79c5 --- /dev/null +++ b/config/plugins/visualizations/charts/static/charts/utilities/tabular-utilities.js @@ -0,0 +1,320 @@ +define( [ 'utils/utils', 'plugin/charts/utilities/tabular-datasets' ], function( Utils, Datasets ) { + + /** Create default data request dictionary */ + function buildRequestDictionary( chart, dataset_id ) { + var result = { groups : [] }; + result.id = dataset_id ? dataset_id : chart.get( 'dataset_id' ); + var group_index = 0; + chart.groups.each( function( group ) { + var columns = {}; + _.each( group.get( '__data_columns' ), function( data_columns, name ) { + columns[ name ] = Utils.merge( { index : group.get( name ) }, data_columns ); + }); + result.groups.push( Utils.merge({ + key : ( ++group_index ) + ':' + group.get( 'key' ), + columns : columns + }, group.attributes )); + }); + return result; + }; + + /** build job dictionary */ + function buildJobDictionary( module, chart ) { + var settings_string = ''; + var columns_string = ''; + var group_index = 0; + for ( key in chart.settings.attributes ) { + settings_string += key + ':' + chart.settings.get( key ) + ', '; + }; + 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' : 'charts', + 'inputs' : { + 'input' : { + 'id' : chart.get( 'dataset_id' ), + 'src' : 'hda' + }, + 'module' : module, + 'columns' : columns_string, + 'settings' : settings_string + } + } + }; + + /** Assists in assigning the viewport panels */ + function panelHelper( options ) { + var self = this; + var process = options.process; + var chart = options.chart; + var request_dictionary = options.request_dictionary || buildRequestDictionary( chart ); + var render = options.render; + var canvas_list = options.canvas_list; + request_dictionary.success = function( result ) { + try { + if ( chart.settings.get( 'use_panels' ) === 'true' ) { + var valid = true; + for ( var group_index in result.groups ) { + var group = result.groups[ group_index ]; + if (!render( canvas_list[ group_index ], [ group ] ) ) { + valid = false; + break; + } + } + if ( valid ) { + chart.state( 'ok', 'Multi-panel chart drawn.' ); + } + } else { + if ( render( canvas_list[ 0 ], result.groups ) ) { + chart.state( 'ok', 'Chart drawn.' ); + } + } + process.resolve(); + } catch ( err ) { + console.debug( 'FAILED: tabular-utilities::panelHelper() - ' + err ); + chart.state( 'failed', err ); + process.reject(); + } + }; + Datasets.request( request_dictionary ); + }; + + /** Get domain boundaries value */ + function getDomains( groups, keys ) { + function _apply( operator, key ) { + var value = undefined; + for ( var group_index in groups ) { + var 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 ) { + var column_index = keys[ key_index ]; + point.push( group.values[ value_index ][ column_index ] ); + } + } else { + for ( var 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, with_index ) { + var array = {}; + // identify label columns + var chart_definition = groups[ 0 ]; + for ( var key in chart_definition.columns ) { + var column_def = chart_definition.columns[ key ]; + if ( column_def.is_label ) { + array[ key ] = []; + } + } + // collect string labels in array + if ( groups && groups[ 0 ] ) { + var group = groups[ 0 ]; + for ( var j in group.values ) { + var value_dict = group.values[ j ]; + for ( var key in array ) { + array[ key ].push ( String( value_dict[ key ] ) ); + } + } + } + // index all values contained in label columns (for all groups) + mapCategories( array, groups ); + return { array : array } + }; + + /** Apply default mapping index all values contained in label columns (for all groups) */ + function mapCategories( array, 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 array ) { + value_dict[ key ] = parseInt( j ) + } + } + } + }; + + /** Category make for unique category labels */ + function makeUniqueCategories( groups, with_index ) { + var categories = {}; + var array = {}; + var counter = {}; + var chart_definition = groups[ 0 ]; + for( var key in chart_definition.columns ) { + var column_def = chart_definition.columns[ 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 ( 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 ] ); + 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; + }; + + return { + buildRequestDictionary : buildRequestDictionary, + buildJobDictionary : buildJobDictionary, + panelHelper : panelHelper, + makeCategories : makeCategories, + makeUniqueCategories : makeUniqueCategories, + makeSeries : makeSeries, + getDomains : getDomains, + mapCategories : mapCategories, + makeTickFormat : makeTickFormat, + addZoom : addZoom + } + +}); diff --git a/config/plugins/visualizations/charts/static/components/jobs.js b/config/plugins/visualizations/charts/static/components/jobs.js new file mode 100644 index 00000000000..4a316004900 --- /dev/null +++ b/config/plugins/visualizations/charts/static/components/jobs.js @@ -0,0 +1,102 @@ +/** This class handles job submissions to the charts tool. */ +define( [ 'utils/utils' ], function( Utils ) { + + /** Time to wait before refreshing to check if job has completed */ + var WAITTIME = 1000; + + /** Submit job request to charts tool */ + var request = function( app, parameters, success, error ) { + var chart = app.chart; + chart.state( 'wait', 'Requesting job results...' ); + if ( chart.get( 'modified' ) ) { + cleanup( chart ); + chart.set( 'modified', false ); + } + var dataset_id_job = chart.get( 'dataset_id_job' ); + if ( dataset_id_job != '' ) { + wait( chart, success, error ); + } else { + var chart_id = chart.id; + var chart_type = chart.get( 'type' ); + var chart_definition = chart.definition; + chart.state( 'wait', 'Sending job request...' ); + Utils.request({ + type : 'POST', + url : Galaxy.root + 'api/tools', + data : parameters, + success : function( response ) { + if ( !response.outputs || response.outputs.length == 0 ) { + chart.state( 'failed', 'Job submission failed. No response.' ); + 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 ); + self.app.storage.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 ); + error && error(); + + } + }); + } + }; + + /* Remove previous data when re-running jobs */ + var cleanup = function( chart ) { + var self = this; + var previous = chart.get( 'dataset_id_job' ); + if (previous != '') { + Utils.request({ + type : 'PUT', + url : Galaxy.root + 'api/histories/none/contents/' + previous, + data : { deleted: true }, + success : function() { refreshHdas() } + }); + chart.set( 'dataset_id_job', '' ); + } + }; + + /** Request job details */ + var wait = function( chart, success, error ) { + var self = this; + Utils.request({ + type : 'GET', + url : Galaxy.root + '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...' ); + success && success( dataset ); + ready = true; + break; + case 'error': + chart.state( 'failed', 'Job has failed. Please check the history for details.' ); + error && error( dataset ); + ready = true; + break; + case 'running': + chart.state( 'wait', 'Your job is running. You may close the browser window. The job will continue in the background.' ); + } + !ready && setTimeout( function() { wait( chart, success, error ) }, WAITTIME ); + } + }); + }; + + /** Refresh history panel */ + var refreshHdas = function() { + Galaxy && Galaxy.currHistoryPanel && Galaxy.currHistoryPanel.refreshContents(); + }; + + return { request: request } +}); \ No newline at end of file diff --git a/config/plugins/visualizations/charts/static/components/model.js b/config/plugins/visualizations/charts/static/components/model.js new file mode 100644 index 00000000000..b0b782aa283 --- /dev/null +++ b/config/plugins/visualizations/charts/static/components/model.js @@ -0,0 +1,39 @@ +define( [ 'utils/utils' ], function( Utils ) { + return Backbone.Model.extend({ + defaults : { + id : null, + title : '', + type : '', + date : null, + state : '', + state_info : '', + modified : false, + dataset_id : '', + dataset_id_job : '' + }, + + initialize: function( options ) { + this.groups = new Backbone.Collection(); + this.settings = new Backbone.Model(); + this.definition = {}; + }, + + reset: function( options ) { + this.set({ + 'id' : Utils.uid(), + 'type' : 'nvd3_bar', + 'dataset_id' : options.config.dataset_id, + 'title' : 'New Chart' + }); + 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( 'Chart:state() - ' + info + ' (' + value + ')' ); + } + }); +}); \ No newline at end of file diff --git a/config/plugins/visualizations/charts/static/library/screenshot.js b/config/plugins/visualizations/charts/static/components/screenshot.js similarity index 100% rename from config/plugins/visualizations/charts/static/library/screenshot.js rename to config/plugins/visualizations/charts/static/components/screenshot.js diff --git a/config/plugins/visualizations/charts/static/library/storage.js b/config/plugins/visualizations/charts/static/components/storage.js similarity index 61% rename from config/plugins/visualizations/charts/static/library/storage.js rename to config/plugins/visualizations/charts/static/components/storage.js index 9d3e6eca807..5ef3abdc58e 100644 --- a/config/plugins/visualizations/charts/static/library/storage.js +++ b/config/plugins/visualizations/charts/static/components/storage.js @@ -1,10 +1,6 @@ -/** - * This class saves and loads a chart through the api. - */ - define( [ 'utils/utils', 'plugin/models/chart', 'mvc/visualization/visualization-model' ], - function( Utils, Chart ) { +/** This class saves and loads a chart through the api. */ +define( [ 'utils/utils', 'plugin/components/model', 'mvc/visualization/visualization-model' ], function( Utils, Chart ) { return Backbone.Model.extend({ - vis: null, initialize: function( app ) { this.app = app; @@ -39,33 +35,34 @@ }); this.vis.set( 'title', chart.get( 'title' ) || '' ); this.vis.get( 'config' ).chart_dict = chart_dict; - this.vis.save().fail(function( xhr, status, message ) { - self.app.showModal( 'Saving failed.', 'An attempt to save this chart to the server failed. Please try again and contact the administrator.' ); - }) - .then( function( response ) { - if ( response && response.id ) { - self.id = response.id; - } else { - console.debug('Storage::save() - Unrecognized response. Saving may have failed.'); - } - }); + this.vis.save() + .fail(function( xhr, status, message ) { + self.app.showModal( 'Saving failed.', 'An attempt to save this chart to the server failed. Please try again and contact the administrator.' ); + }) + .then( function( response ) { + if ( response && response.id ) { + self.id = response.id; + } else { + console.debug( 'Storage::save() - Unrecognized response. Saving may have failed.' ); + } + }); }, /** Load nested models/collections from packed dictionary */ load: function() { var chart_dict = this.vis.get( 'config' ).chart_dict; if ( !chart_dict.attributes ) { - console.debug('Storage::load() - Chart attributes not found. Invalid format.'); + console.debug( 'Storage::load() - Chart attributes not found. Invalid format.' ); return false; } var chart_type = chart_dict.attributes[ 'type' ]; if ( !chart_type ) { - console.debug('Storage::load() - Chart type not provided. Invalid format.'); + console.debug( 'Storage::load() - Chart type not provided. Invalid format.' ); return false; } - var chart_definition = this.app.types.get( chart_type ); + var chart_definition = this.app.types[ chart_type ]; if ( !chart_definition ) { - console.debug('Storage::load() - Chart type not supported. Please re-configure the chart. Resetting chart.'); + console.debug( 'Storage::load() - Chart type not supported. Please re-configure the chart.' ); return false; } this.chart.definition = chart_definition; @@ -75,7 +72,7 @@ this.chart.groups.reset(); this.chart.groups.add( chart_dict.groups ); this.chart.set( 'modified', false ); - console.debug('Storage::load() - Loading chart type ' + chart_type + '.'); + console.debug( 'Storage::load() - Loading chart type ' + chart_type + '.' ); return true; } }); diff --git a/config/plugins/visualizations/charts/static/library/datasets.js b/config/plugins/visualizations/charts/static/library/datasets.js deleted file mode 100644 index 9afc78e92f8..00000000000 --- a/config/plugins/visualizations/charts/static/library/datasets.js +++ /dev/null @@ -1,378 +0,0 @@ -/** - * This class handles, formats and caches datasets. - */ -define( [ 'utils/utils' ], function( Utils ) { -return Backbone.Collection.extend({ - // list of datasets - list: {}, - - // cache for datablocks - cache: {}, - - // initialize - initialize: function(app, options){ - this.app = app; - this.options = Utils.merge(options, this.optionsDefault); - }, - - // request handler - request: function(request_dictionary) { - if (request_dictionary.groups) { - this._get_blocks(request_dictionary); - } else { - this._get_dataset(request_dictionary.id, request_dictionary.success, request_dictionary.error) - } - }, - - // multiple request handler - _get_blocks: function(request_dictionary) { - // get callbacks - var success = request_dictionary.success; - var progress = request_dictionary.progress; - - // query block size - var query_size = this.app.config.get('query_limit'); - - // set range - var query_start = request_dictionary.start || 0; - var query_end = query_start + request_dictionary.query_limit || query_start + this.app.config.get('query_limit'); - - // get query limit - var query_range = Math.abs(query_end - query_start); - if (query_range <= 0) { - console.debug('FAILED - Datasets::request() - Invalid query range.'); - return; - } - - // get number of required queries - var query_number = Math.ceil(query_range / query_size) || 1; - - // get query dictionary template - var query_dictionary_template = $.extend(true, {}, request_dictionary); - - // reset query counter - var query_counter = 0; - - // fetch blocks - var self = this; - function fetch_blocks (query) { - self._get(query, function() { - // copy values from query into request_dictionary - var done = false; - for (var group_index in request_dictionary.groups) { - // get source/destination - destination_group = request_dictionary.groups[group_index]; - source_group = query.groups[group_index]; - - // check if value fields already exist - if (!destination_group.values) { - destination_group.values = []; - } - - // concat values - destination_group.values = destination_group.values.concat(source_group.values); - - // validate - if (source_group.values.length == 0) { - done = true; - break; - } - } - - // check if for remaining queries - if (++query_counter < query_number && !done) { - // report progress - if (progress) { - progress(parseInt((query_counter / query_number) * 100)); - } - - // next query - var start = query.start + query_size; - query = $.extend(true, query_dictionary_template, {start: start}); - fetch_blocks(query); - } else { - success(); - } - }); - - }; - - // prepare query - var query = $.extend(true, query_dictionary_template, {start: query_start}); - - // get dataset meta data - this._get_dataset(request_dictionary.id, function() { - fetch_blocks(query); - }); - }, - - // get dataset - _get_dataset: function(id, success, error) { - // check if dataset is available from cache - var dataset = this.list[id]; - if (dataset) { - success(dataset); - return; - } - - // request dataset - var self = this; - Utils.request({ - type : 'GET', - url : config.root + 'api/datasets/' + id, - success : function(dataset) { - switch (dataset.state) { - case 'error': - if (error) { - error(dataset); - } - break; - default: - self.list[id] = dataset; - success(dataset); - } - } - }); - }, - - // get block id - _block_id: function (options, column) { - return options.id + '_' + options.start + '_' + options.start + this.app.config.get('query_limit') + '_' + column; - }, - - // fills request dictionary with data from cache/response - _get: function(request_dictionary, callback) { - // set start - request_dictionary.start = request_dictionary.start || 0; - - // get column indices - var column_list = []; - var column_map = {}; - var column_count = 0; - for (var i in request_dictionary.groups) { - var group = request_dictionary.groups[i]; - for (var key in group.columns) { - // identify column - var column = group.columns[key].index; - - // check if column is in cache - var block_id = this._block_id(request_dictionary, column); - if (this.cache[block_id] || column === 'auto' || column === 'zero') { - continue; - } - - // add to dictionary - if (!column_map[column] && column !== undefined) { - column_map[column] = column_count; - column_list.push(column); - column_count++; - } - } - } - - // check length of blocks not available in cache - if (column_list.length == 0) { - // fill dictionary from cache - this._fill_from_cache(request_dictionary); - - // parse requested data - callback(request_dictionary); - - // return - return; - } - - // configure dataset request dictionary - var dataset_request = { - dataset_id : request_dictionary.id, - start : request_dictionary.start, - columns : column_list - } - - // fetch data - var self = this; - this._fetch(dataset_request, function(results) { - // add results to cache - for (var i in results) { - var column = column_list[i]; - var block_id = self._block_id(request_dictionary, column); - self.cache[block_id] = results[i]; - } - - // fill dictionary from cache - self._fill_from_cache(request_dictionary); - - // trigger callback - callback(request_dictionary); - }); - }, - - // convert - _fill_from_cache: function(request_dictionary) { - // identify start of request - var start = request_dictionary.start; - - // log - console.debug('Datasets::_fill_from_cache() - Filling request from cache at ' + start + '.'); - - // identify end of request - var limit = 0; - for (var i in request_dictionary.groups) { - var group = request_dictionary.groups[i]; - for (var key in group.columns) { - var column = group.columns[key]; - var block_id = this._block_id(request_dictionary, column.index); - var column_data = this.cache[block_id]; - if (column_data) { - limit = Math.max(limit, column_data.length); - } - } - } - - // check length - if (limit == 0) { - console.debug('Datasets::_fill_from_cache() - Reached data range limit.'); - } - - // initialize group values - for (var i in request_dictionary.groups) { - // get group - var group = request_dictionary.groups[i]; - - // reset group - group.values = []; - - // add values - for (var j = 0; j < limit; j++) { - // add default x values - group.values[j] = { - x : parseInt(j) + start - }; - } - } - - // collect all data into the defined groups - for (var i in request_dictionary.groups) { - // get group - var group = request_dictionary.groups[i]; - - // fill value - for (var key in group.columns) { - // get column - var column = group.columns[key]; - - // check if auto block is requested - switch (column.index) { - case 'auto': - for (var j = 0; j < limit; j++) { - // get value dictionary - var value = group.values[j]; - - // add auto value - value[key] = parseInt(j) + start; - } - break; - case 'zero': - for (var j = 0; j < limit; j++) { - // get value dictionary - var value = group.values[j]; - - // add zero value - value[key] = 0; - } - break; - default: - // get block - var block_id = this._block_id(request_dictionary, column.index); - var column_data = this.cache[block_id]; - - // go through column - for (var j = 0; j < limit; j++) { - // get value dictionary - var value = group.values[j]; - - // get/fix value - var v = column_data[j]; - if (isNaN(v) && !column.is_label && !column.is_text) { - v = 0; - } - - // add to dict - value[key] = v; - } - } - } - } - }, - - // fetch data columns into dataset object - _fetch: function(dataset_request, callback) { - // set offset - var offset = dataset_request.start ? dataset_request.start : 0; - - // set limit - var limit = this.app.config.get('query_limit'); - - // check length - var n_columns = 0; - if (dataset_request.columns) { - n_columns = dataset_request.columns.length; - console.debug('Datasets::_fetch() - Fetching ' + n_columns + ' column(s) at ' + offset + '.'); - } - if (n_columns == 0) { - console.debug('Datasets::_fetch() - No columns requested'); - } - - // get column indices - var column_string = ''; - for (var i in dataset_request.columns) { - column_string += dataset_request.columns[i] + ','; - } - column_string = column_string.substring(0, column_string.length - 1); - - // make request - var self = this; - Utils.request({ - type : 'GET', - url : config.root + 'api/datasets/' + dataset_request.dataset_id, - data : { - data_type : 'raw_data', - provider : 'dataset-column', - limit : limit, - offset : offset, - indeces : column_string - }, - success : function(response) { - // initialize result dictionary - var result = new Array(n_columns); - for (var i = 0; i < n_columns; i++) { - result[i] = []; - } - - // loop through rows - for (var i in response.data) { - // get row - var row = response.data[i]; - - // collect all data into the defined groups - for (var j in row) { - // get group - var v = row[j]; - if (v !== undefined && v != 2147483647) { - // add to result - result[j].push(v); - } - } - } - - // log - console.debug('Datasets::_fetch() - Fetching complete.'); - - // callback - callback(result); - } - }); - } -}); - -}); \ No newline at end of file diff --git a/config/plugins/visualizations/charts/static/library/jobs.js b/config/plugins/visualizations/charts/static/library/jobs.js deleted file mode 100644 index 89310639f0b..00000000000 --- a/config/plugins/visualizations/charts/static/library/jobs.js +++ /dev/null @@ -1,153 +0,0 @@ -/** - * This class handles job submissions to the charts tool. - */ -define( [ 'utils/utils' ], function( Utils ) { - return Backbone.Model.extend({ - initialize: function( app, options ) { - this.app = app; - this.options = Utils.merge( options, this.optionsDefault ); - }, - - /* Request job results */ - request: function( chart, settings_string, columns_string, success, error ) { - var self = this; - chart.state( 'wait', 'Requesting job results...' ); - var dataset_id_job = chart.get( 'dataset_id_job' ); - if (dataset_id_job != '') { - self._wait( chart, success, error ); - } else { - self._submit( chart, settings_string, columns_string, success, error ); - } - }, - - /* Remove previous data when re-running jobs */ - cleanup: function( chart ) { - var self = this; - var previous = chart.get( 'dataset_id_job' ); - if (previous != '') { - Utils.request({ - type : 'PUT', - url : config.root + 'api/histories/none/contents/' + previous, - data : { deleted: true }, - success : function() { - self._refreshHdas(); - } - }); - chart.set( 'dataset_id_job', '' ); - } - }, - - // create job - _submit: function(chart, settings_string, columns_string, success, error) { - // link this - var self = this; - - // backup chart details - var chart_id = chart.id; - var chart_type = chart.get('type'); - - // get chart settings - var chart_definition = chart.definition; - - // configure tool - data = { - 'tool_id' : 'charts', - 'inputs' : { - 'input' : { - 'id' : chart.get('dataset_id'), - 'src' : 'hda' - }, - 'module' : chart_definition.execute, - 'columns' : columns_string, - 'settings' : settings_string - } - } - - // set chart state - chart.state('wait', 'Sending job request...'); - - // post job - Utils.request({ - type : 'POST', - url : config.root + 'api/tools', - data : data, - success : function(response) { - if (!response.outputs || response.outputs.length == 0) { - chart.state('failed', 'Job submission failed. No response.'); - - // call error - error && error(); - } else { - // update galaxy history - self._refreshHdas(); - - // get dataset - var job = response.outputs[0]; - - // check dataset - chart.state('wait', 'Your job has been queued. You may close the browser window. The job will run in the background.'); - - // backup resulting dataset id - chart.set('dataset_id_job', job.id); - - // save - self.app.storage.save(); - - // wait for job completion - self._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 + '.'; - } - - // update state - chart.state('failed', 'This visualization requires the \'charts\' tool. Please make sure it is installed. ' + message); - - // call error - error && error(); - - } - }); - }, - - /** Request job details */ - _wait: function( chart, success, error ) { - var self = this; - Utils.request({ - type : 'GET', - url : config.root + '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...' ); - success && success( dataset ); - ready = true; - break; - case 'error': - chart.state( 'failed', 'Job has failed. Please check the history for details.' ); - error && error( dataset ); - ready = true; - break; - case 'running': - chart.state( 'wait', 'Your job is running. You may close the browser window. The job will continue in the background.' ); - } - if ( !ready ) { - setTimeout( function() { - self._wait( chart, success, error ); - }, self.app.config.get( 'query_timeout' ) ); - } - } - }); - }, - - /** Refresh history panel */ - _refreshHdas: function() { - Galaxy && Galaxy.currHistoryPanel && Galaxy.currHistoryPanel.refreshContents(); - } - }); -}); \ No newline at end of file diff --git a/config/plugins/visualizations/charts/static/models/chart.js b/config/plugins/visualizations/charts/static/models/chart.js deleted file mode 100644 index d5969cc5b3f..00000000000 --- a/config/plugins/visualizations/charts/static/models/chart.js +++ /dev/null @@ -1,58 +0,0 @@ -define( [], function() { - var Groups = Backbone.Collection.extend({ - model: Backbone.Model.extend({ - defaults : { - key : 'Data label', - date : '' - }, - - reset: function(){ - this.clear( { silent: true } ).set( this.defaults ); - this.trigger( 'reset', this ); - } - }) - }); - return Backbone.Model.extend({ - defaults : { - id : null, - title : '', - type : '', - date : null, - state : '', - state_info : '', - modified : false, - dataset_id : '', - dataset_id_job : '' - }, - - initialize: function( options ) { - this.groups = new Groups(); - this.settings = new Backbone.Model(); - }, - - reset: function() { - this.clear( { silent: true } ).set( this.defaults ); - this.groups.reset(); - this.settings.clear(); - this.trigger( 'reset', this ); - }, - - copy: function( new_chart ) { - var current = this; - current.clear( { silent: true } ).set( this.defaults ); - current.set( new_chart.attributes ); - current.settings = new_chart.settings.clone(); - current.groups.reset(); - new_chart.groups.each( function( group ) { - current.groups.add( group.clone() ); - }); - current.trigger( 'change', current ); - }, - - state: function( value, info ) { - this.set( { 'state': value, 'state_info': info } ); - this.trigger( 'set:state' ); - console.debug( 'Chart:state() - ' + info + ' (' + value + ')' ); - } - }); -}); \ No newline at end of file diff --git a/config/plugins/visualizations/charts/static/models/config.js b/config/plugins/visualizations/charts/static/models/config.js deleted file mode 100644 index f44c82e4bd1..00000000000 --- a/config/plugins/visualizations/charts/static/models/config.js +++ /dev/null @@ -1,8 +0,0 @@ -define( [], function() { - return Backbone.Model.extend({ - defaults : { - query_limit : 1000, - query_timeout : 100 - } - }); -}); \ No newline at end of file diff --git a/config/plugins/visualizations/charts/static/views/description.js b/config/plugins/visualizations/charts/static/views/description.js new file mode 100644 index 00000000000..c98e5f050f3 --- /dev/null +++ b/config/plugins/visualizations/charts/static/views/description.js @@ -0,0 +1,36 @@ +/** This class renders the chart configuration form. */ +define( [], function() { + return 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() { + this.$image.attr( 'src', app_root + 'charts/' + this.app.split( this.chart.get( 'type' ) ) + '/logo.png' ); + this.$title.html( this.chart.definition.title + ' (' + this.chart.definition.library + ')' ); + this.$text.html( this.chart.definition.description || this.chart.definition.category ); + }, + _template: function() { + return '
' + + '' + + '' + + '' + + '' + + '' + + '
' + + '' + + '' + + '
' + + '
' + + '
' + + '
'; + } + }); +}); \ No newline at end of file diff --git a/config/plugins/visualizations/charts/static/views/editor.js b/config/plugins/visualizations/charts/static/views/editor.js index f4c7f04603e..26d829466f6 100644 --- a/config/plugins/visualizations/charts/static/views/editor.js +++ b/config/plugins/visualizations/charts/static/views/editor.js @@ -2,9 +2,8 @@ * The charts editor holds the tabs for selecting chart types, chart configuration * and data group selections. */ -define( [ 'mvc/ui/ui-tabs', 'mvc/ui/ui-misc', 'mvc/ui/ui-portlet', 'utils/utils', - 'plugin/models/chart', 'plugin/views/settings', 'plugin/views/groups', 'plugin/views/types' ], - function( Tabs, Ui, Portlet, Utils, Chart, SettingsView, GroupsView, TypesView ) { +define( [ 'mvc/ui/ui-tabs', 'mvc/ui/ui-misc', 'mvc/ui/ui-portlet', 'utils/utils', 'plugin/views/settings', 'plugin/views/groups', 'plugin/views/types' ], + function( Tabs, Ui, Portlet, Utils, SettingsView, GroupsView, TypesView ) { return Backbone.View.extend({ initialize: function( app, options ){ var self = this; @@ -36,14 +35,11 @@ define( [ 'mvc/ui/ui-tabs', 'mvc/ui/ui-misc', 'mvc/ui/ui-portlet', 'utils/utils' }); // grid with chart types - this.types = new TypesView(app, { - onchange : function(chart_type) { - var chart_definition = self.app.types.get( chart_type ); - if ( !chart_definition ) { - console.debug('FAILED - Editor::onchange() - Chart type not supported.'); - } + this.types = new TypesView( app, { + onchange : function( chart_type ) { + var chart_definition = self.app.types[ chart_type ]; + !chart_definition && console.debug( 'FAILED - Editor::onchange() - Chart type not supported.' ); self.chart.definition = chart_definition; - self.chart.settings.clear(); self.chart.set( { type : chart_type, modified : true } ); console.debug( 'Editor::onchange() - Switched chart type.' ); }, @@ -69,8 +65,9 @@ define( [ 'mvc/ui/ui-tabs', 'mvc/ui/ui-misc', 'mvc/ui/ui-portlet', 'utils/utils' tooltip : 'Start by selecting a chart type.', $el : $( '
' ).append( ( new Ui.Label( { title : 'Provide a chart title:' } ).$el ) ) .append( this.title.$el ) - .append( $( '
' ).addClass( 'ui-form-info' ).html( 'This title will appear in the list of \'Saved Visualizations\'. Charts are saved upon creation.' ) ) - .append( this.types.$el.addClass( 'ui-margin-top' ) ) + .append( $( '
' ).addClass( 'ui-form-info ui-margin-bottom' ).html( 'This title will appear in the list of \'Saved Visualizations\'. Charts are saved upon creation.' ) ) + .append( ( new Ui.Label( { title : 'Select a chart type:' } ).$el.addClass( 'ui-margin-top' ) ) ) + .append( this.types.$el ) }); this.tabs.add({ id : 'settings', @@ -83,22 +80,22 @@ define( [ 'mvc/ui/ui-tabs', 'mvc/ui/ui-misc', 'mvc/ui/ui-portlet', 'utils/utils' id : 'groups', title : 'Select data', icon : 'fa-database', - tooltip : 'Specify your data columns.', + tooltip : 'Specify your data options.', $el : ( new GroupsView( this.app ) ).$el }); // set elements this.portlet.append( this.message.$el ); this.portlet.append( this.tabs.$el.addClass( 'ui-margin-top-large' ) ); + this.portlet.hideOperation( 'back' ); this.setElement( this.portlet.$el ); this.tabs.hideOperation( 'back' ); // chart events this.chart.on( 'change:title', function( chart ) { self._refreshTitle() } ); this.chart.on( 'change:type', function( chart ) { self.types.value( chart.get( 'type' ) ) } ); - this.chart.on( 'reset', function( chart ) { self._resetChart() } ); - this.app.chart.on( 'redraw', function( chart ) { self.portlet.showOperation( 'back' ) } ); - this._resetChart(); + this.chart.on( 'redraw', function( chart ) { self.portlet.showOperation( 'back' ) } ); + this.chart.reset( this.app.options ); }, /** Show editor */ @@ -118,19 +115,6 @@ define( [ 'mvc/ui/ui-tabs', 'mvc/ui/ui-misc', 'mvc/ui/ui-portlet', 'utils/utils' this.title.value( title ); }, - /** Reset entire chart */ - _resetChart: function() { - this.chart.set({ - 'id' : Utils.uid(), - 'type' : 'nvd3_bar', - 'dataset_id' : this.app.options.config.dataset_id, - 'title' : 'New Chart' - }); - this.chart.groups.reset(); - this.chart.groups.add( { id : Utils.uid() } ); - this.portlet.hideOperation( 'back' ); - }, - /** Save chart data */ _saveChart: function() { var self = this; @@ -140,7 +124,7 @@ define( [ 'mvc/ui/ui-tabs', 'mvc/ui/ui-misc', 'mvc/ui/ui-portlet', 'utils/utils' date : Utils.time() }); if ( this.chart.groups.length == 0 ) { - this.message.update( { message: 'Please specify data columns before drawing the chart.' } ); + this.message.update( { message: 'Please specify data options before drawing the chart.' } ); this.tabs.show( 'groups' ); return; } @@ -148,13 +132,13 @@ define( [ 'mvc/ui/ui-tabs', 'mvc/ui/ui-misc', 'mvc/ui/ui-portlet', 'utils/utils' var chart_def = this.chart.definition; this.chart.groups.each( function( group ) { if ( valid ) { - for ( var key in chart_def.columns ) { - if ( group.attributes[ key ] === null ) { + _.each( group.get( '__data_columns' ), function( data_columns, name ) { + if ( group.attributes[ name ] === null ) { self.message.update( { status: 'danger', message: 'This chart type requires column types not found in your tabular file.' } ); self.tabs.show( 'groups' ); valid = false; } - } + }); } }); if ( valid ) { diff --git a/config/plugins/visualizations/charts/static/views/groups.js b/config/plugins/visualizations/charts/static/views/groups.js index e65b244a3a5..b67ce5ac793 100644 --- a/config/plugins/visualizations/charts/static/views/groups.js +++ b/config/plugins/visualizations/charts/static/views/groups.js @@ -1,62 +1,59 @@ -/** - * This class renders the chart configuration form. - */ -define( [ 'mvc/ui/ui-table', 'mvc/ui/ui-misc', 'mvc/form/form-view', 'mvc/form/form-repeat', 'utils/utils' ], function( Table, Ui, Form, Repeat, Utils ) { +/** This class renders the chart configuration form. */ +define( [ 'utils/utils', 'mvc/ui/ui-misc', 'mvc/form/form-view', 'mvc/form/form-repeat', 'mvc/form/form-data', 'plugin/views/description' ], + function( Utils, Ui, Form, Repeat, FormData, Description ) { var GroupView = Backbone.View.extend({ initialize: function( app, options ) { var self = this; - this.app = app; - this.chart = app.chart; - this.group = options.group; + this.app = app; + this.chart = app.chart; + this.group = options.group; this.setElement( $( '
' ) ); - this.chart.on( 'change:dataset_id change:type', function() { self.render() } ); - this.group.on( 'change', function() { self.form && self.form.data.set( self.group ) } ); + this.listenTo( this.chart, 'change:dataset_id change:type', function() { self.render() } ); this.render(); }, render: function() { var self = this; - var inputs = this.chart.definition.series && this.chart.definition.series.slice() || []; - _.each( this.chart.definition.columns, function( column, name ) { - inputs.push( { name: name, label: column.title, type: 'select' } ); - }); - this.form = new Form( { - inputs : inputs, - cls : 'ui-portlet-plain' - } ); - this.$el.empty().append( this.form.$el ); + var inputs = this.chart.definition.groups ? Utils.clone( this.chart.definition.groups ) : []; var dataset_id = this.chart.get( 'dataset_id' ); var chart_type = this.chart.get( 'type' ); var chart_definition = this.chart.definition; if ( dataset_id && chart_type ) { this.chart.state( 'wait', 'Loading metadata...' ); this.app.deferred.execute( function( process ) { - self.app.datasets.request({ - id : dataset_id, + Utils.get({ + url : Galaxy.root + 'api/datasets/' + dataset_id, + cache : true, success : function( dataset ) { - for ( var id in chart_definition.columns ) { - var index = self.form.data.match( id ); - if ( index ) { + var data_columns = {}; + FormData.visitInputs( inputs, function( input, prefixed ) { + if ( input.type == 'data_column' ) { + data_columns[ prefixed ] = Utils.clone( input ); var columns = []; - var select = self.form.field_list[ index ]; - var input_def = chart_definition.columns[ id ]; - input_def.is_auto && columns.push( { 'label': 'Column: Row Number', 'value': 'auto' } ); - input_def.is_zero && columns.push( { 'label' : 'Column: None', 'value' : 'zero' } ); + input.is_auto && columns.push( { 'label': 'Column: Row Number', 'value': 'auto' } ); + input.is_zero && columns.push( { 'label' : 'Column: None', 'value' : 'zero' } ); var meta = dataset.metadata_column_types; for ( var key in meta ) { - var valid = ( [ 'int', 'float' ].indexOf( meta[ key ] ) != -1 && input_def.is_numeric ) || input_def.is_text || input_def.is_label; + var valid = ( [ 'int', 'float' ].indexOf( meta[ key ] ) != -1 && input.is_numeric ) || input.is_text || input.is_label; valid && columns.push( { 'label' : 'Column: ' + ( parseInt( key ) + 1 ), 'value' : key } ); } - select.update( columns ); - self.group.set( id, select.value( self.group.get( id ) ) ); + input.data = columns; } - } - self.chart.state( 'ok', 'Metadata initialized...' ); - self.form.data.set( self.group ); - self.form.setOnChange( function() { - self.group.set( self.form.data.create() ); - self.chart.set( 'modified', true ); + var model_value = self.group.get( prefixed ); + model_value !== undefined && !input.hidden && ( input.value = model_value ); }); + inputs[ '__data_columns' ] = { name: '__data_columns', type: 'hidden', hidden: true, value: data_columns }; + self.chart.state( 'ok', 'Metadata initialized...' ); + self.form = new Form( { + inputs : inputs, + cls : 'ui-portlet-plain', + onchange: function() { + self.group.set( self.form.data.create() ); + self.chart.set( 'modified', true ); + } + } ); + self.group.set( self.form.data.create() ); + self.$el.empty().append( self.form.$el ); process.resolve(); } }); @@ -67,24 +64,42 @@ define( [ 'mvc/ui/ui-table', 'mvc/ui/ui-misc', 'mvc/form/form-view', 'mvc/form/f return Backbone.View.extend({ initialize: function( app ) { - var repeat = new Repeat.View({ + var self = this; + this.app = app; + this.chart = app.chart; + this.repeat = new Repeat.View({ title : 'Data series', title_new : 'Data series', min : 1, - onnew : function() { app.chart.groups.add( { id : Utils.uid() } ) } + onnew : function() { self.chart.groups.add( { id : Utils.uid() } ) } }); - this.setElement( repeat.$el ); - app.chart.groups.on( 'add remove reset', function() { app.chart.set( 'modified', true ) } ) - .on( 'remove', function( group ) { repeat.del( group.id ) } ) - .on( 'reset', function() { repeat.delAll() } ) - .on( 'add', function( group ) { - repeat.add({ - id : group.id, - cls : 'ui-portlet-panel', - $el : ( new GroupView( app, { group: group } ) ).$el, - ondel : function() { app.chart.groups.remove( group ) } - }); - }); + this.description = new Description( this.app ); + this.message = new Ui.Message( { message : 'There are no options for this chart type.', persistent : true, status : 'info' } ); + this.setElement( $( '
' ).append( this.description.$el ) + .append( this.repeat.$el.addClass( 'ui-margin-bottom' ) ) + .append( this.message.$el.addClass( 'ui-margin-bottom' ) ) ); + this.listenTo( this.chart, 'change', function() { self.render() } ); + this.listenTo( this.chart.groups, 'add remove reset', function() { self.chart.set( 'modified', true ) } ); + this.listenTo( this.chart.groups, 'remove', function( group ) { self.repeat.del( group.id ) } ); + this.listenTo( this.chart.groups, 'reset', function() { self.repeat.delAll() } ); + this.listenTo( this.chart.groups, 'add', function( group ) { + self.repeat.add({ + id : group.id, + cls : 'ui-portlet-panel', + $el : ( new GroupView( self.app, { group: group } ) ).$el, + ondel : function() { self.chart.groups.remove( group ) } + }); + }); + }, + + render: function() { + if ( _.size( this.chart.definition.groups ) > 0 ) { + this.repeat.$el.show(); + this.message.$el.hide(); + } else { + this.repeat.$el.hide(); + this.message.$el.show(); + } } }); }); \ No newline at end of file diff --git a/config/plugins/visualizations/charts/static/views/settings.js b/config/plugins/visualizations/charts/static/views/settings.js index f0d118c7a2d..993ecebe773 100644 --- a/config/plugins/visualizations/charts/static/views/settings.js +++ b/config/plugins/visualizations/charts/static/views/settings.js @@ -1,76 +1,35 @@ -/** - * This class renders the chart configuration form. - */ -define( [ 'mvc/ui/ui-table', 'mvc/ui/ui-misc', 'mvc/form/form-parameters', 'utils/utils' ], function( Table, Ui, Parameters, Utils ) { +/** This class renders the chart configuration form. */ +define( [ 'utils/utils', 'mvc/ui/ui-misc', 'mvc/form/form-view', 'mvc/form/form-data', 'plugin/views/description' ], function( Utils, Ui, Form, FormData, Description ) { return Backbone.View.extend({ initialize: function( app, options ) { var self = this; this.app = app; - this.chart = this.app.chart; - this.list = []; - this.parameters = new Parameters(); - this.table_title = new Ui.Label({}); - this.table = new Table.View( { content: 'This chart type does not provide any options.' } ); - this.setElement( $( '
' ).addClass( 'ui-form' ) - .append( this.table_title.$el ) - .append( this.table.$el ) ); - this.chart.on( 'change', function() { self.render() } ); + this.chart = app.chart; + this.description = new Description( this.app ); + this.message = new Ui.Message( { message: 'There are no options for this chart type.', persistent: true, status: 'info' } ); + this.setElement( $( '
' ).append( this.description.$el ).append( this.message.$el ).append( this.$form = $( '
' ) ) ); + this.listenTo( this.chart, 'change', function() { self.render() } ); }, - render: function() { - var chart_definition = this.chart.definition; - if ( chart_definition ) { - this.table_title.title( chart_definition.category + ' - ' + chart_definition.title + ':' ); - this.table.delAll(); - this.list = []; - var settings = chart_definition.settings; - for ( var id in settings ) { - this._add( settings[ id ].id || id, settings[ id ], this.chart.settings ); - } - for ( var id in this.list ) { - this.list[ id ].trigger('change'); - } - } - }, - - /** Add table row */ - _add: function( name, settings_def, model ) { var self = this; - if ( settings_def.type !== 'separator' ) { - switch( settings_def.type ) { - case 'select': - settings_def.onchange = function( new_value ) { - model.set( name, new_value ); - var dict = _.findWhere( settings_def.data, { value: new_value } ); - if ( dict && dict.operations ) { - var operations = dict.operations; - for ( var i in operations.show ) { - self.table.get( operations.show[ i ] ).fadeIn( 'fast' ); - } - for ( var i in operations.hide ) { - self.table.get( operations.hide[ i ] ).hide(); - } - } - }; - break; - default: - settings_def.onchange = function( new_value ) { model.set( name, new_value ) }; - } - settings_def.id = name; - settings_def.value = model.get( name ) || settings_def.init; - model.set( name, settings_def.value ); - var field = this.parameters.create( settings_def ); - var $input = $( '
' ).append( field.$el ); - settings_def.info && $input.append( $( '
' ).addClass( 'ui-form-info' ).append( settings_def.info ) ); - this.table.add( $( '' ).addClass( 'ui-form-title' ).append( settings_def.title ), '20%' ); - this.table.add( $input ); - this.list[ name ] = field; + var inputs = Utils.clone( this.chart.definition.settings ); + if ( _.size( inputs ) > 0 ) { + FormData.visitInputs( inputs, function( input, name ) { + var model_value = self.chart.settings.get( name ); + model_value !== undefined && !input.hidden && ( input.value = model_value ); + }); + this.form = new Form({ + inputs : inputs, + cls : 'ui-portlet-plain', + onchange : function() { self.chart.settings.set( self.form.data.create() ); } + }); + this.chart.settings.set( this.form.data.create() ); + this.$form.empty().append( this.form.$el ); + this.message.$el.hide(); } else { - this.table.add( $( '
' ).addClass( 'ui-form-separator' ).append( settings_def.title + ':' ) ); - this.table.add( $( '
' ) ); + this.$form.empty(); + this.message.$el.show(); } - this.table.append( name ); - settings_def.hide && this.table.get( name ).hide(); } }); }); \ No newline at end of file diff --git a/config/plugins/visualizations/charts/static/views/types.js b/config/plugins/visualizations/charts/static/views/types.js index 9ecba0c7a84..26500bd0ed9 100644 --- a/config/plugins/visualizations/charts/static/views/types.js +++ b/config/plugins/visualizations/charts/static/views/types.js @@ -1,44 +1,63 @@ -/** - * This class renders the chart type selection grid. - */ -define( [ 'utils/utils', 'mvc/ui/ui-misc' ], function( Utils, Ui ) { +/** This class renders the chart type selection grid. */ +define( [ 'utils/utils', 'mvc/ui/ui-misc', 'mvc/ui/ui-tabs', 'plugin/charts/overview' ], function( Utils, Ui, Tabs, Overview ) { return Backbone.View.extend({ - optionsDefault: { - onchange : null, - ondblclick : null - }, - events : { - 'click' : '_onclick', - 'dblclick' : '_ondblclick' + 'click .item' : '_onclick', + 'dblclick .item' : '_ondblclick' }, initialize : function( app, options ) { var self = this; this.app = app; this.options = Utils.merge( options, this.optionsDefault ); - this.library = new Ui.RadioButton.View({ - data : [ { label: 'Few (<500)', value: 'small' }, - { label: 'Some (<10k)', value: 'medium' }, - { label: 'Many (>10k)', value: 'large' }], - onchange: function( value ) { self._filter( value ) } + this.tabs = new Tabs.View( {} ); + this.setElement( this.tabs.$el.addClass( 'charts-types' ) ); + this.render(); + }, + + render: function() { + var self = this; + this.index = {}; + _.each( this.app.types, function( type, type_id ) { + _.each( type.keywords.split( ' ' ), function( keyword ) { + self.index[ keyword ] = self.index[ keyword ] || {}; + self.index[ keyword ][ type.category ] = self.index[ keyword ][ type.category ] || {}; + self.index[ keyword ][ type.category ][ type_id ] = type; + }); + }); + this.tabs.delAll(); + _.each( Overview, function( d, i ) { + var keyword = d.value; + var categories = self.index[ keyword ]; + var $help = $( '

' ).addClass( 'ui-form-info' ).html( d.help ) ; + var $el = $( '

' ).addClass( 'charts-grid' ).append( $help ); + _.each( categories, function( category, category_header ) { + var $category = self._templateHeader( { title: category_header } ); + $el.append( $category ); + _.each( category, function( type, type_id ) { + $el.append( self._templateType({ + id : type_id, + title : ( type.zoomable ? '' : '' ) + type.title + ' (' + type.library + ')', + url : app_root + 'charts/' + self.app.split( type_id ) + '/logo.png' + })); + }); + }); + self.tabs.add({ + id : Utils.uid(), + title : d.label, + $el : $el + }); }); - this.setElement( $( '
' ).addClass( 'charts-grid' ) - .append( ( new Ui.Label( { title : 'How many data points would you like to analyze?' } ) ).$el ) - .append( this.library.$el.addClass( 'ui-margin-bottom' ) ) ); - this._render(); - this.library.value( 'small' ); - this.library.trigger( 'change' ); }, /** Set/Get selected chart type */ value: function( new_value ) { - var before = this.$el.find( '.current' ).attr( 'id' ); + var before = this.$( '.current' ).attr( 'chart_id' ); if ( new_value !== undefined ) { - this.$el.find( '.current' ).removeClass( 'current' ); - this.$el.find( '#' + new_value ).addClass( 'current' ); + this.$( '.current' ).removeClass( 'current' ); + this.$( '[chart_id="' + new_value + '"]' ).addClass( 'current' ); } - var after = this.$el.find( '.current' ).attr( 'id' ); + var after = this.$( '.current' ).attr( 'chart_id' ); if( after !== undefined ) { if ( after != before && this.options.onchange ) { this.options.onchange( new_value ); @@ -47,91 +66,26 @@ define( [ 'utils/utils', 'mvc/ui/ui-misc' ], function( Utils, Ui ) { } }, - /** Filter chart types */ - _filter: function( value ) { - this.$el.find( '.header' ).hide(); - var types = this.app.types.attributes; - for ( var id in types ) { - var type = types[ id ]; - var $el = this.$el.find( '#' + id ); - var $header = this.$el.find( '#types-header-' + this.categories_index[ type.category ] ); - var keywords = type.keywords || ''; - if ( keywords.indexOf( value ) >= 0 ) { - $el.show(); - $header.show(); - } else { - $el.hide(); - } - } - }, - - /** Render chart type view */ - _render: function() { - var category_index = 0; - this.categories = {}; - this.categories_index = {}; - var types = this.app.types.attributes; - for ( var id in types ) { - var type = types[ id ]; - var category = type.category; - if ( !this.categories[ category ] ) { - this.categories[ category ] = {}; - this.categories_index[ category ] = category_index++; - } - this.categories[ category ][ id ] = type; - } - - // add categories and charts to screen - for (var category in this.categories) { - var $el = $( '
' ).append( this._template_header({ - id : 'types-header-' + this.categories_index[ category ], - title : category - })); - for ( var id in this.categories[ category ] ) { - var type = this.categories[ category ][ id ]; - var title = type.title + ' (' + type.library + ')'; - if ( type.zoomable ) { - title = '' + title; - } - $el.append( this._template_item({ - id : id, - title : title, - url : config.app_root + 'charts/' + this.app.chartPath( id ) + '/logo.png' - })); - } - this.$el.append( $el ); - } - }, - /** Add click handler */ _onclick: function( e ) { - var old_value = this.value(); - var new_value = $( e.target ).closest( '.item' ).attr( 'id' ); - if ( new_value != '' ) { - if ( new_value && old_value != new_value ) { - this.value( new_value ); - } - } + this.value( $( e.target ).closest( '.item' ).attr( 'chart_id' ) ); }, /** Add double click handler */ _ondblclick: function( e ) { - var value = this.value(); - if ( value && this.options.ondblclick ) { - this.options.ondblclick( value ); - } + this.options.ondblclick && this.options.ondblclick( this.value() ); }, - // header template - _template_header: function( options ) { - return '
' + + /** Header template */ + _templateHeader: function( options ) { + return '
' + '• ' + options.title + '
'; }, - // item template - _template_item: function( options ) { - return '
' + + /* Chart type template with image */ + _templateType: function( options ) { + return '
' + '' + '
' + options.title + '
' + '
'; diff --git a/config/plugins/visualizations/charts/static/views/viewer.js b/config/plugins/visualizations/charts/static/views/viewer.js index 17cba91fbcb..bbe9c757296 100644 --- a/config/plugins/visualizations/charts/static/views/viewer.js +++ b/config/plugins/visualizations/charts/static/views/viewer.js @@ -1,15 +1,12 @@ -/** - * This class renders the chart viewer which encapsulates the chart viewport. - */ -define( [ 'utils/utils', 'mvc/ui/ui-misc', 'mvc/ui/ui-portlet', - 'plugin/views/viewport', 'plugin/library/screenshot' ], - function( Utils, Ui, Portlet, ViewportView, Screenshot ) { +/** This class renders the chart viewer which encapsulates the chart viewport. */ +define( [ 'utils/utils', 'mvc/ui/ui-misc', 'mvc/ui/ui-portlet', 'plugin/views/viewport', 'plugin/components/screenshot' ], + function( Utils, Ui, Portlet, Viewport, Screenshot ) { return Backbone.View.extend({ initialize: function(app, options){ var self = this; this.app = app; this.chart = this.app.chart; - this.viewport_view = new ViewportView( app ); + this.viewport = new Viewport( app ); this.message = new Ui.Message(); // button menu @@ -27,7 +24,7 @@ define( [ 'utils/utils', 'mvc/ui/ui-misc', 'mvc/ui/ui-portlet', onclick : function() { self._wait( self.chart, function() { Screenshot.createPNG({ - $el : self.viewport_view.$el, + $el : self.viewport.$el, title : self.chart.get( 'title' ), error : function( err ) { self.message.update( { message: err, status: 'danger' } ); @@ -45,7 +42,7 @@ define( [ 'utils/utils', 'mvc/ui/ui-misc', 'mvc/ui/ui-portlet', onclick : function() { self._wait( self.chart, function() { Screenshot.createSVG({ - $el : self.viewport_view.$el, + $el : self.viewport.$el, title : self.chart.get( 'title' ), error : function( err ) { self.message.update( { message: err, status: 'danger' } ); @@ -70,7 +67,7 @@ define( [ 'utils/utils', 'mvc/ui/ui-misc', 'mvc/ui/ui-portlet', self.app.modal.hide(); self._wait( self.chart, function() { Screenshot.createPDF({ - $el : self.viewport_view.$el, + $el : self.viewport.$el, title : self.chart.get( 'title' ), error : function( err ) { self.message.update( { message: err, status: 'danger' } ); @@ -87,6 +84,7 @@ define( [ 'utils/utils', 'mvc/ui/ui-misc', 'mvc/ui/ui-portlet', this.portlet = new Portlet.View({ icon : 'fa-bar-chart-o', title: 'Viewport', + cls : 'ui-portlet charts-viewer', operations: { edit_button: new Ui.ButtonIcon({ icon : 'fa-edit', @@ -103,8 +101,8 @@ define( [ 'utils/utils', 'mvc/ui/ui-misc', 'mvc/ui/ui-portlet', }); // append elements - this.portlet.append( this.message.$el.addClass( 'ui-margin-top' ) ); - this.portlet.append( this.viewport_view.$el ); + this.portlet.append( this.message.$el ); + this.portlet.append( this.viewport.$el.addClass( 'ui-margin-top' ) ); this.setElement( this.portlet.$el ); // events @@ -129,7 +127,7 @@ define( [ 'utils/utils', 'mvc/ui/ui-misc', 'mvc/ui/ui-portlet', }, /** Check if chart is ready for export */ - _wait: function(chart, callback) { + _wait: function( chart, callback ) { if ( this.app.deferred.ready() ) { callback(); } else { diff --git a/config/plugins/visualizations/charts/static/views/viewport.js b/config/plugins/visualizations/charts/static/views/viewport.js index 10716e84ff4..9bf1245899a 100644 --- a/config/plugins/visualizations/charts/static/views/viewport.js +++ b/config/plugins/visualizations/charts/static/views/viewport.js @@ -5,9 +5,6 @@ */ define( [ 'mvc/ui/ui-portlet', 'mvc/ui/ui-misc', 'utils/utils' ], function( Portlet, Ui, Utils ) { return Backbone.View.extend({ - // list of container/canvas elements - container_list: [], - canvas_list: [], initialize: function( app, options ) { var self = this; this.app = app; @@ -22,7 +19,7 @@ define( [ 'mvc/ui/ui-portlet', 'mvc/ui/ui-misc', 'utils/utils' ], function( Port this.$text = this.$( '.text' ); // use full screen for viewer - this._fullscreen( this.$el, 50 ); + this._fullscreen( this.$el, 55 ); // prevent window scrolling var initial_overflow = $( 'body' ).css( 'overflow' ); @@ -110,85 +107,12 @@ define( [ 'mvc/ui/ui-portlet', 'mvc/ui/ui-misc', 'utils/utils' ], function( Port /** Draws a new chart by loading and executing the corresponding chart wrapper */ _draw: function( process, chart ) { var self = this; - var chart_type = chart.get( 'type' ); - this.chart_definition = chart.definition; - var n_panels = 1; - if ( chart.settings.get( 'use_panels' ) === 'true' ) { - n_panels = chart.groups.length; - } - this._createContainer( this.chart_definition.tag, n_panels ); + var n_panels = chart.settings.get( 'use_panels' ) === 'true' ? chart.groups.length : 1; + this._createContainer( chart.definition.tag, n_panels ); chart.state( 'wait', 'Please wait...' ); - if ( !this.chart_definition.execute || ( this.chart_definition.execute && chart.get( 'modified' ) ) ) { - this.app.jobs.cleanup( chart ); - chart.set( 'modified', false ); - } - require( [ 'plugin/charts/' + this.app.chartPath( chart_type ) + '/wrapper' ], function( ChartView ) { - if ( self.chart_definition.execute ) { - self.app.jobs.request( chart, self._defaultSettingsString( chart ), self._defaultRequestString( chart ), - function() { - var view = new ChartView( self.app, { - process : process, - chart : chart, - request_dictionary : self._defaultRequestDictionary( chart ), - canvas_list : self.canvas_list - }); - }, - function() { - process.reject(); - } - ); - } else { - var view = new ChartView( self.app, { - process : process, - chart : chart, - request_dictionary : self._defaultRequestDictionary( chart ), - canvas_list : self.canvas_list - }); - } + require( [ 'plugin/charts/' + this.app.split( chart.get( 'type' ) ) + '/wrapper' ], function( ChartView ) { + new ChartView( self.app, { process : process, chart : chart, canvas_list : self.canvas_list } ); }); - }, - - /** Creates default chart request */ - _defaultRequestString: function( chart ) { - var request_string = ''; - var group_index = 0; - var self = this; - chart.groups.each( function( group ) { - group_index++; - for ( var key in self.chart_definition.columns ) { - request_string += key + '_' + group_index + ':' + ( parseInt( group.get( key ) ) + 1 ) + ', '; - } - }); - return request_string.substring( 0, request_string.length - 2 ); - }, - - /** Creates default settings string for charts which require a job execution */ - _defaultSettingsString: function( chart ) { - var settings_string = ''; - for ( key in chart.settings.attributes ) { - settings_string += key + ':' + chart.settings.get( key ) + ', '; - }; - return settings_string.substring( 0, settings_string.length - 2 ); - }, - - /** Create default data request dictionary */ - _defaultRequestDictionary: function( chart ) { - var request_dictionary = { groups : [] }; - request_dictionary.id = this.chart_definition.execute ? chart.get( 'dataset_id_job' ) : chart.get( 'dataset_id' ); - var group_index = 0; - var self = this; - chart.groups.each( function( group ) { - var columns = {}; - for ( var column_key in self.chart_definition.columns ) { - var column_settings = self.chart_definition.columns[ column_key ]; - columns[ column_key ] = Utils.merge( { index : group.get( column_key ) }, column_settings ); - } - request_dictionary.groups.push( Utils.merge({ - key : ( ++group_index ) + ':' + group.get( 'key' ), - columns : columns - }, group.attributes )); - }); - return request_dictionary; } }); }); diff --git a/config/plugins/visualizations/charts/templates/charts.mako b/config/plugins/visualizations/charts/templates/charts.mako index 949cdc42b35..9d310899098 100644 --- a/config/plugins/visualizations/charts/templates/charts.mako +++ b/config/plugins/visualizations/charts/templates/charts.mako @@ -12,6 +12,7 @@ ## install shared libraries ${h.js( 'libs/jquery/jquery', + 'libs/jquery/jquery-ui', 'libs/jquery/select2', 'libs/bootstrap', 'libs/underscore', @@ -20,7 +21,7 @@ 'libs/require')} ## shared css - ${h.css( 'base' )} + ${h.css( 'base', 'jquery-ui/smoothness/jquery-ui' )} ## crossfilter ${h.javascript_link( app_root + "plugins/crossfilter/crossfilter.js" )} @@ -46,21 +47,13 @@ - - - -
-

Repositories by Category

- - - - - - - - - %for category in categories: - - - - - - %endfor -
NameDescriptionRepositories
- ${category['name']} - ${category['description']}${category['repositories']}
-
diff --git a/templates/admin/tool_shed_repository/browse_toolsheds.mako b/templates/admin/tool_shed_repository/browse_toolsheds.mako new file mode 100644 index 00000000000..036c1a9d71a --- /dev/null +++ b/templates/admin/tool_shed_repository/browse_toolsheds.mako @@ -0,0 +1,918 @@ +<%inherit file="/base.mako"/> +<%namespace file="/message.mako" import="render_msg" /> +<%namespace file="/admin/tool_shed_repository/common.mako" import="*" /> +<%namespace file="/admin/tool_shed_repository/repository_actions_menu.mako" import="*" /> + +<%def name="stylesheets()"> + ${parent.stylesheets()} + ${h.css( "dynatree_skin/ui.dynatree" )} + + +<%def name="javascripts()"> + ${parent.javascripts()} + + +
diff --git a/templates/admin/tool_shed_repository/preview_repository.mako b/templates/admin/tool_shed_repository/preview_repository.mako deleted file mode 100644 index 099a37684a2..00000000000 --- a/templates/admin/tool_shed_repository/preview_repository.mako +++ /dev/null @@ -1,487 +0,0 @@ -<%inherit file="/base.mako"/> -<%namespace file="/message.mako" import="render_msg" /> -<%namespace file="/admin/tool_shed_repository/common.mako" import="*" /> -<%namespace file="/admin/tool_shed_repository/repository_actions_menu.mako" import="*" /> - -<%def name="stylesheets()"> - ${parent.stylesheets()} - ${h.css( "dynatree_skin/ui.dynatree" )} - - - -<%def name="javascripts()"> - ${parent.javascripts()} - - - -%if message: - ${render_msg( message, status )} -%endif -

Installing repository ${toolshed_data['name']} from ${toolshed_data['owner']}

-
- - -
-
Changeset
-
- - -
- Please select a revision and review the settings below before installing. -
-
- %if shed_tool_conf_select_field: -
Shed tool configuration file:
-
- <% - if len( shed_tool_conf_select_field.options ) == 1: - select_help = "Your Galaxy instance is configured with 1 shed-related tool configuration file, so repositories will be " - select_help += "installed using its tool_path setting." - else: - select_help = "Your Galaxy instance is configured with %d shed-related tool configuration files, " % len( shed_tool_conf_select_field.options ) - select_help += "so select the file whose tool_path setting you want used for installing repositories." - %> -
- ${shed_tool_conf_select_field.get_html()} -
- ${select_help} -
-
-
-
- %endif -
Tool panel section:
-
-
-
Contents of this repository at revision
-
-

- - -

-

- - -

-

- - -

-
- -
-
    -
  • Repository installation requires the following:

  • -
-
-
- - -
-
-
diff --git a/templates/webapps/galaxy/workflow/display.mako b/templates/webapps/galaxy/workflow/display.mako index 386875ef24c..7d3726e1ddd 100644 --- a/templates/webapps/galaxy/workflow/display.mako +++ b/templates/webapps/galaxy/workflow/display.mako @@ -90,7 +90,7 @@ <% # HACK: Rendering workflow steps requires that trans have a history; however, if its user's first visit to Galaxy is here, he won't have a history # and an error will occur. To prevent this error, make sure user has a history. - trans.get_history( create=True ) + trans.get_history( most_recent=True, create=True ) %> diff --git a/templates/webapps/tool_shed/index.mako b/templates/webapps/tool_shed/index.mako index 87facc14582..0689e780fa3 100644 --- a/templates/webapps/tool_shed/index.mako +++ b/templates/webapps/tool_shed/index.mako @@ -44,7 +44,7 @@ <%def name="left_panel()"> <% can_review_repositories = trans.app.security_agent.user_can_review_repositories( trans.user ) %>
-
${trans.app.shed_counter.unique_valid_tools | h} valid tools on ${trans.app.shed_counter.generation_time | h}
+
${trans.app.shed_counter.unique_valid_tools | h} valid tools on ${util.unicodify( trans.app.shed_counter.generation_time ) | h}
diff --git a/test/api/test_api_batch.py b/test/api/test_api_batch.py new file mode 100644 index 00000000000..186e0964d6a --- /dev/null +++ b/test/api/test_api_batch.py @@ -0,0 +1,87 @@ +import json +import pprint +import logging +from requests import post +from base import api + +log = logging.getLogger( "functional_tests.py" ) + + +class ApiBatchTestCase( api.ApiTestCase ): + + def _get_api_key( self, admin=False ): + return self.galaxy_interactor.api_key if not admin else self.galaxy_interactor.master_api_key + + def _with_key( self, url, admin=False ): + sep = '&' if '?' in url else '?' + return url + sep + 'key=' + self._get_api_key( admin=admin ) + + def _post_batch( self, batch ): + data = json.dumps({ "batch" : batch }) + return post( "%s/batch" % ( self.galaxy_interactor.api_url ), data=data ) + + def _log_reponse( self, response ): + log.debug( 'RESPONSE %s\n%s', ( '-' * 40 ), pprint.pformat( response ) ) + + # ---- tests + def test_simple_array( self ): + batch = [ + dict( url=self._with_key( '/api/histories' ) ), + dict( url=self._with_key( '/api/histories' ), + method='POST', body=json.dumps( dict( name='Wat' ) ) ), + dict( url=self._with_key( '/api/histories' ) ), + ] + response = self._post_batch( batch ) + response = response.json() + # self._log_reponse( response ) + self.assertIsInstance( response, list ) + self.assertEquals( len( response ), 3 ) + + def test_unallowed_route( self ): + batch = [ + dict( url=self._with_key( '/api/workflow' ) ) + ] + response = self._post_batch( batch ) + response = response.json() + self.assertIsInstance( response, list ) + self.assertEquals( response[0][ 'status' ], 403 ) + + def test_404_route( self ): + # needs to be within the allowed routes + batch = [ + dict( url=self._with_key( '/api/histories_bler' ) ) + ] + response = self._post_batch( batch ) + response = response.json() + self.assertIsInstance( response, list ) + self.assertEquals( response[0][ 'status' ], 404 ) + + def test_errors( self ): + batch = [ + dict( url=self._with_key( '/api/histories/abc123' ) ), + dict( url=self._with_key( '/api/jobs' ), method='POST', body=json.dumps( dict( name='Wat' ) ) ), + ] + response = self._post_batch( batch ) + response = response.json() + # self._log_reponse( response ) + self.assertIsInstance( response, list ) + self.assertEquals( response[0][ 'status' ], 400 ) + self.assertEquals( response[1][ 'status' ], 501 ) + + def test_querystring_params( self ): + post_data = dict( name='test' ) + create_response = self._post( 'histories', data=post_data ).json() + + history_url = '/api/histories/' + create_response[ 'id' ] + history_url_with_keys = history_url + '?v=dev&keys=size,non_ready_jobs' + contents_url_with_filters = history_url + '/contents?v=dev&q=deleted&qv=True' + batch = [ + dict( url=self._with_key( history_url_with_keys ) ), + dict( url=self._with_key( contents_url_with_filters ) ), + ] + response = self._post_batch( batch ) + response = response.json() + self._log_reponse( response ) + self.assertEquals( len( response ), 2 ) + self.assertEquals( len( response[0][ 'body' ].keys() ), 2 ) + self.assertEquals( response[1][ 'body' ], [] ) diff --git a/test/casperjs/api-batch-tests.js b/test/casperjs/api-batch-tests.js new file mode 100644 index 00000000000..30d861108de --- /dev/null +++ b/test/casperjs/api-batch-tests.js @@ -0,0 +1,83 @@ +var require = patchRequire( require ), + spaceghost = require( 'spaceghost' ).fromCasper( casper ), + xpath = require( 'casper' ).selectXPath, + utils = require( 'utils' ), + format = utils.format; + +function apiBatch( batch ){ + return spaceghost.api._ajax( 'api/batch', { + type : 'POST', + contentType : 'application/json', + data : { batch : batch } + }); +} + +spaceghost.test.begin( 'Test the API batch system', 0, function suite( test ){ + spaceghost.start(); + + // ======================================================================== SET UP + var email = spaceghost.user.getRandomEmail(), + password = '123456'; + if( spaceghost.fixtureData.testUser ){ + email = spaceghost.fixtureData.testUser.email; + password = spaceghost.fixtureData.testUser.password; + } + spaceghost.user.registerUser( email, password ); + + var responseKeys = [ 'body', 'headers', 'status' ]; + + // ======================================================================== TESTS + spaceghost.then( function(){ + // -------------------------------------------------------------------- + this.test.comment( 'API batching should allow multiple requests and responses, executed in order' ); + var responses = apiBatch([ + { url : '/api/histories' }, + { url : '/api/histories', type: 'POST', body: JSON.stringify({ name: 'wert' }) }, + { url : '/api/histories' }, + ]); + // this.debug( 'responses:' + this.jsonStr( responses ) ); + this.test.assert( utils.isArray( responses ), "returned an array: length " + responses.length ); + this.test.assert( responses.length === 3, 'Has three responses' ); + + var historiesBeforeCreate = responses[0], + createdHistory = responses[1], + historiesAfterCreate = responses[2]; + this.test.assert( utils.isArray( historiesBeforeCreate.body ), + "first histories call returned an array" + historiesBeforeCreate.body.length ); + this.test.assert( utils.isObject( createdHistory.body ), 'history create returned an object' ); + this.test.assert( historiesAfterCreate.body[0].id === createdHistory.body.id, + "second histories call includes the newly created history:" + historiesAfterCreate.body[0].id ); + + + this.test.comment( 'API batching should handle bad routes well' ); + responses = apiBatch([ + { url : '/api/bler' }, + ]); + // this.debug( 'responses:' + this.jsonStr( responses ) ); + this.test.assert( responses.length === 1 ); + var badRouteResponse = responses[0]; + this.test.assert( badRouteResponse.status === 404 ); + this.test.assert( utils.isObject( badRouteResponse.body ) + && this.countKeys( badRouteResponse.body ) === 0 ); + + this.test.comment( 'API batching should handle errors well' ); + responses = apiBatch([ + { url : '/api/histories/abc123' }, + { url : '/api/users/123', method: 'PUT' } + ]); + // this.debug( 'responses:' + this.jsonStr( responses ) ); + this.test.assert( responses.length === 2 ); + var badIdResponse = responses[0], + notImplemented = responses[1]; + this.test.assert( badIdResponse.status === 400 ); + this.test.assert( notImplemented.status === 501 ); + + /* + */ + }); + //spaceghost.user.logout(); + + // =================================================================== + spaceghost.run( function(){ test.done(); }); +}); +
StepAnnotation