dash_creator 0.1.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/MIT-LICENSE +20 -0
- data/README.md +170 -0
- data/Rakefile +36 -0
- data/app/assets/config/dash_creator_manifest.js +2 -0
- data/app/assets/javascripts/dash_creator/application.js +24 -0
- data/app/assets/javascripts/dash_creator/chart.js +2 -0
- data/app/assets/javascripts/dash_creator/dashboard.js +2 -0
- data/app/assets/javascripts/dash_creator/dashboard_object.js +2 -0
- data/app/assets/javascripts/dash_creator/filter.js +2 -0
- data/app/assets/javascripts/dash_creator/libs/Chart.js +12269 -0
- data/app/assets/javascripts/dash_creator/libs/bootstrap.js +3535 -0
- data/app/assets/javascripts/dash_creator/libs/chartCreator.js +1582 -0
- data/app/assets/javascripts/dash_creator/libs/dashboardCreator.js +531 -0
- data/app/assets/javascripts/dash_creator/libs/daterangepicker.js +1626 -0
- data/app/assets/javascripts/dash_creator/libs/filterCreator.js +733 -0
- data/app/assets/javascripts/dash_creator/libs/jquery-ui.js +18706 -0
- data/app/assets/javascripts/dash_creator/libs/jquery.minicolors.js +1108 -0
- data/app/assets/javascripts/dash_creator/libs/moment.js +4301 -0
- data/app/assets/javascripts/dash_creator/libs/tether.js +1811 -0
- data/app/assets/javascripts/dash_creator/user.js +2 -0
- data/app/assets/stylesheets/dash_creator/application.css +16 -0
- data/app/assets/stylesheets/dash_creator/chart.css +4 -0
- data/app/assets/stylesheets/dash_creator/dashboard.css +4 -0
- data/app/assets/stylesheets/dash_creator/dashboard_object.css +4 -0
- data/app/assets/stylesheets/dash_creator/filter.css +4 -0
- data/app/assets/stylesheets/dash_creator/fonts/FontAwesome.otf +0 -0
- data/app/assets/stylesheets/dash_creator/fonts/fontawesome-webfont.eot +0 -0
- data/app/assets/stylesheets/dash_creator/fonts/fontawesome-webfont.svg +2671 -0
- data/app/assets/stylesheets/dash_creator/fonts/fontawesome-webfont.ttf +0 -0
- data/app/assets/stylesheets/dash_creator/fonts/fontawesome-webfont.woff +0 -0
- data/app/assets/stylesheets/dash_creator/fonts/fontawesome-webfont.woff2 +0 -0
- data/app/assets/stylesheets/dash_creator/libs/font-awesome.css +2199 -0
- data/app/assets/stylesheets/dash_creator/libs/jquery.minicolors.css +319 -0
- data/app/assets/stylesheets/dash_creator/libs/jquery.minicolors.png +0 -0
- data/app/assets/stylesheets/dash_creator/libs/style.css +13714 -0
- data/app/assets/stylesheets/dash_creator/user.css +4 -0
- data/app/controllers/dash_creator/application_controller.rb +3 -0
- data/app/controllers/dash_creator/chart_controller.rb +81 -0
- data/app/controllers/dash_creator/dashboard_controller.rb +37 -0
- data/app/controllers/dash_creator/dashboard_object_controller.rb +34 -0
- data/app/controllers/dash_creator/filter_controller.rb +60 -0
- data/app/controllers/dash_creator/user_controller.rb +82 -0
- data/app/helpers/dash_creator/application_helper.rb +4 -0
- data/app/helpers/dash_creator/chart_helper.rb +829 -0
- data/app/helpers/dash_creator/dashboard_helper.rb +4 -0
- data/app/helpers/dash_creator/dashboard_object_helper.rb +4 -0
- data/app/helpers/dash_creator/filter_helper.rb +237 -0
- data/app/helpers/dash_creator/user_helper.rb +4 -0
- data/app/jobs/dash_creator/application_job.rb +4 -0
- data/app/mailers/dash_creator/application_mailer.rb +6 -0
- data/app/models/dash_creator/application_record.rb +5 -0
- data/app/models/dash_creator/chart.rb +21 -0
- data/app/models/dash_creator/dashboard.rb +13 -0
- data/app/models/dash_creator/dashboard_object.rb +7 -0
- data/app/models/dash_creator/filter.rb +22 -0
- data/app/views/dash_creator/chart/_chart_creator.html.erb +230 -0
- data/app/views/dash_creator/chart/_modals.html.erb +74 -0
- data/app/views/dash_creator/chart/_plot_chart.html.erb +45 -0
- data/app/views/dash_creator/chart/create_chart.js.erb +53 -0
- data/app/views/dash_creator/dashboard/_dashboard_creator.html.erb +182 -0
- data/app/views/dash_creator/dashboard/_modals.html.erb +74 -0
- data/app/views/dash_creator/dashboard_object/_chart.html.erb +9 -0
- data/app/views/dash_creator/dashboard_object/_stat.html.erb +24 -0
- data/app/views/dash_creator/dashboard_object/_table.html.erb +16 -0
- data/app/views/dash_creator/filter/_filtering_card.html.erb +132 -0
- data/app/views/dash_creator/filter/_modals.html.erb +51 -0
- data/app/views/dash_creator/filter/_result_tables.html.erb +55 -0
- data/app/views/dash_creator/filter/apply_filtering.js.erb +46 -0
- data/app/views/dash_creator/filter/create_stat.js.erb +20 -0
- data/app/views/dash_creator/layouts/application.html.erb +64 -0
- data/app/views/dash_creator/layouts/menu/_left_menu.html.erb +12 -0
- data/app/views/dash_creator/user/_section_card.html.erb +17 -0
- data/app/views/dash_creator/user/creator.html.erb +11 -0
- data/app/views/dash_creator/user/dashboard.html.erb +10 -0
- data/config/initializers/dash_creator.rb +0 -0
- data/config/routes.rb +30 -0
- data/lib/dash_creator.rb +87 -0
- data/lib/dash_creator/acts_as_dash_creator.rb +16 -0
- data/lib/dash_creator/acts_as_dashboard_object.rb +19 -0
- data/lib/dash_creator/engine.rb +11 -0
- data/lib/dash_creator/version.rb +3 -0
- data/lib/generators/dash_creator/install/install_generator.rb +70 -0
- data/lib/generators/dash_creator/install/templates/_chart.html.erb +9 -0
- data/lib/generators/dash_creator/install/templates/_section_card.html.erb +17 -0
- data/lib/generators/dash_creator/install/templates/_stat.html.erb +24 -0
- data/lib/generators/dash_creator/install/templates/_table.html.erb +16 -0
- data/lib/generators/dash_creator/install/templates/add_indexes_to_dash_creator_tables.rb +15 -0
- data/lib/generators/dash_creator/install/templates/create_dash_creator_charts.rb +25 -0
- data/lib/generators/dash_creator/install/templates/create_dash_creator_dashboard_objects.rb +36 -0
- data/lib/generators/dash_creator/install/templates/create_dash_creator_dashboards.rb +28 -0
- data/lib/generators/dash_creator/install/templates/create_dash_creator_filters.rb +22 -0
- data/lib/generators/dash_creator/install/templates/dashboard.html.erb +10 -0
- data/lib/generators/dash_creator/install/templates/initializer.rb +48 -0
- data/lib/tasks/dash_creator_tasks.rake +4 -0
- metadata +196 -0
@@ -0,0 +1,1582 @@
|
|
1
|
+
/*!
|
2
|
+
* Chart Creator v1.0
|
3
|
+
* 2017 Elie Oriol
|
4
|
+
*/
|
5
|
+
|
6
|
+
(function(factory) {
|
7
|
+
if (typeof define === 'function' && define.amd) {
|
8
|
+
define([ 'jquery', 'moment' ], factory);
|
9
|
+
}
|
10
|
+
else if (typeof exports === 'object') { // Node/CommonJS
|
11
|
+
module.exports = factory(require('jquery'), require('moment'));
|
12
|
+
}
|
13
|
+
else {
|
14
|
+
factory(jQuery, moment);
|
15
|
+
}
|
16
|
+
})(function($, moment) {
|
17
|
+
var ChartCreator = function(element, options, callback) {
|
18
|
+
this.parentEl = $(element);
|
19
|
+
|
20
|
+
if (typeof options !== 'object' || options === null)
|
21
|
+
options = {};
|
22
|
+
|
23
|
+
this.models_data = (typeof options.models_data === 'object') ?
|
24
|
+
options.models_data : {};
|
25
|
+
|
26
|
+
this.attributes_aliases = (typeof options.attributes_aliases === 'object') ?
|
27
|
+
options.attributes_aliases : {};
|
28
|
+
|
29
|
+
this.displayed_model_names = (typeof options.displayed_model_names === 'object') ?
|
30
|
+
options.displayed_model_names : {};
|
31
|
+
|
32
|
+
this.displayed_attribute_names = (typeof options.displayed_attribute_names === 'object') ?
|
33
|
+
options.displayed_attribute_names : {};
|
34
|
+
|
35
|
+
this.filter_creator = (typeof options.filter_creator === 'object') ?
|
36
|
+
options.filter_creator : null;
|
37
|
+
|
38
|
+
this.minicolors_options = (typeof options.minicolors_options === 'object') ?
|
39
|
+
options.minicolors_options : {};
|
40
|
+
|
41
|
+
this.callback = (typeof callback === 'function') ? callback : function() {};
|
42
|
+
|
43
|
+
if (typeof options.template !== 'string' && !(options.template instanceof $)) {
|
44
|
+
options.template = '<div class="row"> ' +
|
45
|
+
'<div class="col-md-10 offset-md-1 px-2" id="chart-container" style="background-color: #eee; border-radius: 10px; padding: 20px 10px; margin-bottom: 50px;"> ' +
|
46
|
+
'<h3>Chart Zone</h3> ' +
|
47
|
+
'<div class="chart-wrapper" style="height:370px; margin-bottom:50px;"> ' +
|
48
|
+
'<iframe class="chartjs-hidden-iframe" tabindex="-1" style="display: flex; overflow: hidden; border: 0; margin: 0; top: 0; left: 0; bottom: 0; right: 0; height: 100%; width: 100%; position: absolute; pointer-events: none; z-index: -1;"></iframe> ' +
|
49
|
+
'</div> ' +
|
50
|
+
'</div> ' +
|
51
|
+
'<hr> ' +
|
52
|
+
'<div class="col-md-12 px-2" id="var-container"> ' +
|
53
|
+
'<div class="row" id="y-container"> ' +
|
54
|
+
'<button id="add-var-btn" class="btn btn-primary pull-right">+</button> ' +
|
55
|
+
'</div> ' +
|
56
|
+
'<div class="row" id="x-container"> ' +
|
57
|
+
'<div class="col-sm-12" id="x-axis-select-div" style="margin-top:40px;"> ' +
|
58
|
+
'<div class="col-sm-2"> ' +
|
59
|
+
'<h5>Function of</h5> ' +
|
60
|
+
'</div> ' +
|
61
|
+
'<div class="form-group col-sm-10"> ' +
|
62
|
+
'<select name="x-axis" class="axis-select form-control">' +
|
63
|
+
'<option value="">Choose data</option>' +
|
64
|
+
'</select>' +
|
65
|
+
'</div> ' +
|
66
|
+
'</div> ' +
|
67
|
+
'</div> ' +
|
68
|
+
'</div> ' +
|
69
|
+
'<hr> ' +
|
70
|
+
'<div class="col-md-12 px-2" id="options-container"> ' +
|
71
|
+
'<div class="row" style="margin-top:60px;"> ' +
|
72
|
+
'<div class="col-sm-12" style="margin-bottom: 40px;"> ' +
|
73
|
+
'<h3 style="margin-bottom: 20px;">Label Options</h3> ' +
|
74
|
+
'<div class="row"> ' +
|
75
|
+
'<div class="col-sm-10 offset-sm-1"> ' +
|
76
|
+
'<div class="row" id="label-options"> ' +
|
77
|
+
'</div> ' +
|
78
|
+
'</div> ' +
|
79
|
+
'</div> ' +
|
80
|
+
'</div> ' +
|
81
|
+
'<div class="col-sm-6"> ' +
|
82
|
+
'<h3 style="margin-bottom: 20px;">Style Options</h3> ' +
|
83
|
+
'<div class="row"> ' +
|
84
|
+
'<div class="col-sm-10 offset-sm-1"> ' +
|
85
|
+
'<div class="row" id="style-options"> ' +
|
86
|
+
'</div> ' +
|
87
|
+
'</div> ' +
|
88
|
+
'</div> ' +
|
89
|
+
'</div> ' +
|
90
|
+
'<div class="col-sm-6"> ' +
|
91
|
+
'<h3 style="margin-bottom: 20px;">Color Options</h3> ' +
|
92
|
+
'<div class="row"> ' +
|
93
|
+
'<div class="col-sm-10 offset-sm-1"> ' +
|
94
|
+
'<div class="row" id="color-options"> ' +
|
95
|
+
'</div> ' +
|
96
|
+
'</div> ' +
|
97
|
+
'</div> ' +
|
98
|
+
'</div> ' +
|
99
|
+
'</div> ' +
|
100
|
+
'</div> ' +
|
101
|
+
'</div>';
|
102
|
+
}
|
103
|
+
|
104
|
+
|
105
|
+
this.container = $(options.template).appendTo(this.parentEl);
|
106
|
+
this.varContainer = this.container.find('#var-container');
|
107
|
+
this.yContainer = this.varContainer.find('#y-container');
|
108
|
+
this.xContainer = this.varContainer.find('#x-container');
|
109
|
+
this.labelOptionsContainer = this.container.find('#label-options');
|
110
|
+
this.styleOptionsContainer = this.container.find('#style-options');
|
111
|
+
this.colorOptionsContainer = this.container.find('#color-options');
|
112
|
+
this.addMainVar();
|
113
|
+
|
114
|
+
this.varContainer
|
115
|
+
.on('click', '#add-var-btn', $.proxy(this.addVar, this))
|
116
|
+
.on('click', '.remove-var-btn', $.proxy(this.removeVar, this))
|
117
|
+
.on('change', '[name="main-type"]', $.proxy(this.checkMainType, this))
|
118
|
+
.on('focusin', '.axis-select', $.proxy(this.axisSelection, this))
|
119
|
+
.on('change', '.axis-select', $.proxy(this.axisSelectionCallback, this));
|
120
|
+
|
121
|
+
this.labelOptionsContainer
|
122
|
+
.on('focusin', '.axis-select', $.proxy(this.axisSelection, this))
|
123
|
+
.on('change', '.axis-select', $.proxy(this.axisSelectionCallback, this))
|
124
|
+
.on('change', '#date-range-select', $.proxy(this.daterangeSelection, this))
|
125
|
+
.on('blur', '#date-range-select', $.proxy(this.daterangeSelection, this))
|
126
|
+
.on('change', '[name="labels-type"]', $.proxy(this.changeLabelTypeCallback, this))
|
127
|
+
.on('change', '[name="sub-labels-type"]', $.proxy(this.changeLabelTypeCallback, this))
|
128
|
+
.on('change', '[name="labels-num"]', $.proxy(this.changeLabelsNumCallback, this));
|
129
|
+
|
130
|
+
// Adjust number of color inputs in style options
|
131
|
+
this.container
|
132
|
+
.on('change', 'select', $.proxy(this.colorCallback, this))
|
133
|
+
.on('blur', 'select', $.proxy(this.colorCallback, this))
|
134
|
+
.on('change', 'input', $.proxy(this.colorCallback, this))
|
135
|
+
.on('click', 'input[type="radio"]', $.proxy(this.colorCallback, this));
|
136
|
+
};
|
137
|
+
|
138
|
+
ChartCreator.prototype = {
|
139
|
+
|
140
|
+
constructor: ChartCreator,
|
141
|
+
|
142
|
+
// --------------- Initialize main components ---------------
|
143
|
+
addMainVar: function() {
|
144
|
+
this.addMainVarToCreator();
|
145
|
+
this.addMainStyleToCreator();
|
146
|
+
this.addMainColorToCreator();
|
147
|
+
this.xContainer.find('#x-axis-select-div').hide();
|
148
|
+
},
|
149
|
+
|
150
|
+
addMainVarToCreator: function() {
|
151
|
+
var main_var_string = '<div class="col-sm-12 var-div" data-id="0"> ' +
|
152
|
+
'<div class="row"> ' +
|
153
|
+
'<div class="col-sm-12"> ' +
|
154
|
+
'<h5>Main variable</h5> ' +
|
155
|
+
'</div> ' +
|
156
|
+
'<div class="form-group col-sm-3 offset-sm-1"> ' +
|
157
|
+
'<select name="y-axis" class="axis-select form-control">' +
|
158
|
+
'<option value="">Choose main data</option>' +
|
159
|
+
'</select>' +
|
160
|
+
'</div> ' +
|
161
|
+
'<div class="form-group col-sm-3 offset-sm-1"> ' +
|
162
|
+
'<input type="text" name="dataset-label" class="form-control"> ' +
|
163
|
+
'</div> ' +
|
164
|
+
'<div class="form-group col-sm-3 offset-sm-1"> ' +
|
165
|
+
'<select name="main-type" class="type-select form-control">' +
|
166
|
+
'<option value="line">Line</option>' +
|
167
|
+
'<option value="bar">Bar</option>' +
|
168
|
+
'<option value="pie">Pie</option>' +
|
169
|
+
'<option value="doughnut">Doughnut</option>' +
|
170
|
+
'<option value="polar">Polar</option>' +
|
171
|
+
'<option value="radar">Radar</option>' +
|
172
|
+
'</select>' +
|
173
|
+
'</div> ' +
|
174
|
+
'</div> ' +
|
175
|
+
'</div> ';
|
176
|
+
|
177
|
+
$(main_var_string).prependTo(this.yContainer);
|
178
|
+
},
|
179
|
+
|
180
|
+
addMainStyleToCreator: function() {
|
181
|
+
var main_style_string = '<div class="col-sm-12 var-style-div" data-id="0"> ' +
|
182
|
+
'<div class="row"> ' +
|
183
|
+
'<div class="col-sm-12" style="margin-bottom: 20px;"> ' +
|
184
|
+
'<div class="row" id="style-general"> ' +
|
185
|
+
'<div class="col-sm-12"> ' +
|
186
|
+
'<strong>General</strong> ' +
|
187
|
+
'</div> ' +
|
188
|
+
'<div class="col-sm-12" id="title-div"> ' +
|
189
|
+
'<div class="form-group"> ' +
|
190
|
+
'<label for="title">Title</label> ' +
|
191
|
+
'<input type="text" name="title" id="title" class="form-control"> ' +
|
192
|
+
'</div> ' +
|
193
|
+
'</div> ' +
|
194
|
+
'<div class="col-sm-12" id="legend-div"> ' +
|
195
|
+
'<div class="row"> ' +
|
196
|
+
'<div class="col-sm-3"> ' +
|
197
|
+
'<div class="form-group"> ' +
|
198
|
+
'<label for="legend">Display legend</label> ' +
|
199
|
+
'<input type="checkbox" name="legend" class="form-control" checked="checked"> ' +
|
200
|
+
'</div> ' +
|
201
|
+
'</div> ' +
|
202
|
+
'<div class="col-sm-9"> ' +
|
203
|
+
'<div class="form-group"> ' +
|
204
|
+
'<label for="legend-pos">Legend Position</label> ' +
|
205
|
+
'<select name="legend-pos" class="form-control"> ' +
|
206
|
+
'<option value="top">Top</option> ' +
|
207
|
+
'<option value="right">Right</option> ' +
|
208
|
+
'<option value="bottom">Bottom</option> ' +
|
209
|
+
'<option value="left">Left</option> ' +
|
210
|
+
'</select> ' +
|
211
|
+
'</div> ' +
|
212
|
+
'</div> ' +
|
213
|
+
'</div> ' +
|
214
|
+
'</div> ' +
|
215
|
+
'</div> ' +
|
216
|
+
'</div> ' +
|
217
|
+
'<div class="col-sm-12" style="margin-bottom: 20px;"> ' +
|
218
|
+
'<div class="row" id="style-barline"> ' +
|
219
|
+
'<div class="col-sm-12"> ' +
|
220
|
+
'<strong>Bar/Line</strong> ' +
|
221
|
+
'</div> ' +
|
222
|
+
'<div class="col-sm-12" id="grid-div"> ' +
|
223
|
+
'<div class="row"> ' +
|
224
|
+
'<div class="col-sm-6"> ' +
|
225
|
+
'<div class="form-group"> ' +
|
226
|
+
'<label for="x-grid-lines">Vertical grid lines</label> ' +
|
227
|
+
'<input type="checkbox" name="x-grid-lines" class="form-control" checked="checked"> ' +
|
228
|
+
'</div> ' +
|
229
|
+
'</div> ' +
|
230
|
+
'<div class="col-sm-6"> ' +
|
231
|
+
'<div class="form-group"> ' +
|
232
|
+
'<label for="y-grid-lines">Horizontal</label> ' +
|
233
|
+
'<input type="checkbox" name="y-grid-lines" class="form-control" checked="checked"> ' +
|
234
|
+
'</div> ' +
|
235
|
+
'</div> ' +
|
236
|
+
'</div> ' +
|
237
|
+
'</div> ' +
|
238
|
+
'<div class="col-sm-12" id="y-axis-div"> ' +
|
239
|
+
'<div class="row"> ' +
|
240
|
+
'<div class="col-sm-4"> ' +
|
241
|
+
'<div class="form-group"> ' +
|
242
|
+
'<label for="y-axis-min">Y Axis Min</label> ' +
|
243
|
+
'<input type="number" name="y-axis-min" class="form-control"> ' +
|
244
|
+
'</div> ' +
|
245
|
+
'</div> ' +
|
246
|
+
'<div class="col-sm-4"> ' +
|
247
|
+
'<div class="form-group"> ' +
|
248
|
+
'<label for="y-axis-min">Max</label> ' +
|
249
|
+
'<input type="number" name="y-axis-max" class="form-control"> ' +
|
250
|
+
'</div> ' +
|
251
|
+
'</div> ' +
|
252
|
+
'<div class="col-sm-4"> ' +
|
253
|
+
'<div class="form-group"> ' +
|
254
|
+
'<label for="y-axis-min">Step</label> ' +
|
255
|
+
'<input type="number" name="y-axis-step" class="form-control"> ' +
|
256
|
+
'</div> ' +
|
257
|
+
'</div> ' +
|
258
|
+
'</div> ' +
|
259
|
+
'</div> ' +
|
260
|
+
'<div class="col-sm-12" id="labeling-step-div"> ' +
|
261
|
+
'<div class="form-group"> ' +
|
262
|
+
'<label for="labeling-step">X Axis Labeling step</label> ' +
|
263
|
+
'<input type="number" name="labeling-step" class="form-control" min="1" value="1"> ' +
|
264
|
+
'</div> ' +
|
265
|
+
'</div> ' +
|
266
|
+
'<div class="col-sm-12" id="stacked-div"> ' +
|
267
|
+
'<div class="form-group"> ' +
|
268
|
+
'<label for="stacked">Stacked</label> ' +
|
269
|
+
'<input type="checkbox" name="stacked" class="form-control"> ' +
|
270
|
+
'</div> ' +
|
271
|
+
'</div> ' +
|
272
|
+
'</div> ' +
|
273
|
+
'</div> ' +
|
274
|
+
// '<div class="col-sm-12" style="margin-bottom: 20px;"> ' +
|
275
|
+
// '<div class="row" id="style-line"> ' +
|
276
|
+
// '<div class="col-sm-12"> ' +
|
277
|
+
// '<strong>Line</strong> ' +
|
278
|
+
// '</div> ' +
|
279
|
+
// '<div class="col-sm-12" id="point-div"> ' +
|
280
|
+
// '<div class="row"> ' +
|
281
|
+
// '<div class="col-sm-6"> ' +
|
282
|
+
// '<div class="form-group"> ' +
|
283
|
+
// '<label for="y-axis-min">Point Style</label> ' +
|
284
|
+
// '<input type="number" name="point-style" class="form-control"> ' +
|
285
|
+
// '</div> ' +
|
286
|
+
// '</div> ' +
|
287
|
+
// '<div class="col-sm-6"> ' +
|
288
|
+
// '<div class="form-group"> ' +
|
289
|
+
// '<label for="y-axis-min">Size</label> ' +
|
290
|
+
// '<input type="number" name="point-size" class="form-control" min="1"> ' +
|
291
|
+
// '</div> ' +
|
292
|
+
// '</div> ' +
|
293
|
+
// '</div> ' +
|
294
|
+
// '</div> ' +
|
295
|
+
// '<div class="col-sm-12" id="line-div"> ' +
|
296
|
+
// '<div class="form-group"> ' +
|
297
|
+
// '<label for="stacked">Stacked</label> ' +
|
298
|
+
// '<input type="checkbox" name="stacked" class="form-control"> ' +
|
299
|
+
// '</div> ' +
|
300
|
+
// '</div> ' +
|
301
|
+
// '</div> ' +
|
302
|
+
// '</div> ' +
|
303
|
+
'</div> ' +
|
304
|
+
'</div> ';
|
305
|
+
|
306
|
+
$(main_style_string).appendTo(this.styleOptionsContainer);
|
307
|
+
},
|
308
|
+
|
309
|
+
addMainColorToCreator: function() {
|
310
|
+
var main_color_string = '<div class="col-sm-12 color-div" data-id="0" id="main-color" style="margin-bottom: 20px;">' +
|
311
|
+
'<div class="row" id="main-color"> ' +
|
312
|
+
'<div class="col-sm-6"> ' +
|
313
|
+
'<div class="form-group color-group"> ' +
|
314
|
+
'<label for="dataset-color">Main variable color</label>' +
|
315
|
+
'<input type="text" name="dataset-color" class="form-control"> ' +
|
316
|
+
'</div> ' +
|
317
|
+
'</div> ' +
|
318
|
+
'<div class="col-sm-6"> ' +
|
319
|
+
'<div class="form-group transparency-group"> ' +
|
320
|
+
'<label for="transparency">Area transparency</label> ' +
|
321
|
+
'<input type="range" name="transparency" value="0" step="1" class="form-control"> ' +
|
322
|
+
'</div>' +
|
323
|
+
'</div>' +
|
324
|
+
'</div>' +
|
325
|
+
'</div>';
|
326
|
+
|
327
|
+
var main_color_div = $(main_color_string).appendTo(this.colorOptionsContainer);
|
328
|
+
// Set first swatches color
|
329
|
+
var default_color = this.minicolors_options.swatches[0];
|
330
|
+
main_color_div.find('[name="dataset-color"]').minicolors(this.minicolors_options).val(default_color).change();
|
331
|
+
main_color_div.find('.minicolors-input-swatch .minicolors-swatch-color').css("background-color", default_color);
|
332
|
+
},
|
333
|
+
|
334
|
+
|
335
|
+
// --------------- Variables handling ---------------
|
336
|
+
addVar: function() {
|
337
|
+
var last_var_div = this.yContainer.find('.var-div:last');
|
338
|
+
var var_id = parseInt(last_var_div.attr('data-id')) + 1;
|
339
|
+
|
340
|
+
this.addVarToCreator(var_id);
|
341
|
+
this.checkMainType();
|
342
|
+
this.addStyleToCreator(var_id);
|
343
|
+
},
|
344
|
+
|
345
|
+
addVarToCreator: function(var_id) {
|
346
|
+
var var_div_string = '<div class="col-sm-12 var-div" data-id="' + var_id + '" style="margin-top:20px;">'
|
347
|
+
+ '<div class="row">'
|
348
|
+
+ '<div class="col-sm-12">'
|
349
|
+
+ '<h5>Variable ' + var_id + '</h5>'
|
350
|
+
+ '</div>'
|
351
|
+
+ '<div class="col-sm-1">'
|
352
|
+
+ '<button type="button" class="close remove-var-btn" aria-label="Close">'
|
353
|
+
+ '<span aria-hidden="true">×</span>'
|
354
|
+
+ '</button>'
|
355
|
+
+ '</div>'
|
356
|
+
+ '<div class="form-group col-sm-3">' +
|
357
|
+
'<select name="y-axis" class="axis-select form-control">' +
|
358
|
+
'<option value="">Choose data</option>' +
|
359
|
+
'</select>'
|
360
|
+
+ '</div>'
|
361
|
+
+ '<div class="form-group col-sm-3 offset-sm-1">'
|
362
|
+
+ '<input type="text" name="dataset-label" class="form-control">'
|
363
|
+
+ '</div>'
|
364
|
+
+ '<div class="form-group col-sm-3 offset-sm-1">' +
|
365
|
+
'<select name="type" class="type-select form-control">' +
|
366
|
+
'<option value="line">Line</option>' +
|
367
|
+
'<option value="bar">Bar</option>' +
|
368
|
+
'</select>'
|
369
|
+
+ '</div></div></div>';
|
370
|
+
|
371
|
+
$(var_div_string).appendTo(this.yContainer);
|
372
|
+
},
|
373
|
+
|
374
|
+
addStyleToCreator: function(var_id) {
|
375
|
+
var var_style_div_string = '<div class="col-sm-12 var-style-div" data-id="' + var_id + '"></div>';
|
376
|
+
$(var_style_div_string).appendTo(this.styleOptionsContainer);
|
377
|
+
|
378
|
+
this.addColorToCreator(var_id, 0);
|
379
|
+
},
|
380
|
+
|
381
|
+
addColorToCreator: function(var_id, label_num) {
|
382
|
+
var label;
|
383
|
+
var is_not_var_color = var_id === 0;
|
384
|
+
if (is_not_var_color)
|
385
|
+
label = 'Label ' + label_num + ' color';
|
386
|
+
else
|
387
|
+
label = 'Variable ' + var_id + ' color';
|
388
|
+
|
389
|
+
var color_div_string = '<div class="col-sm-12 color-div" data-id="' + var_id + '" style="margin-bottom: 20px;">' +
|
390
|
+
'<div class="row"> ' +
|
391
|
+
'<div class="col-sm-6"> ' +
|
392
|
+
'<div class="form-group color-group"> ' +
|
393
|
+
'<label for="dataset-color">' + label + '</label>' +
|
394
|
+
'<input type="text" name="dataset-color" class="form-control"> ' +
|
395
|
+
'</div> ' +
|
396
|
+
'</div> ' +
|
397
|
+
'<div class="col-sm-6"> ' +
|
398
|
+
'<div class="form-group transparency-group"> ' +
|
399
|
+
'<label for="transparency">Area transparency</label> ' +
|
400
|
+
'<input type="range" name="transparency" value="0" step="1" class="form-control"> ' +
|
401
|
+
'</div>' +
|
402
|
+
'</div>' +
|
403
|
+
'</div>' +
|
404
|
+
'</div>';
|
405
|
+
|
406
|
+
var color_div = $(color_div_string).appendTo(this.colorOptionsContainer);
|
407
|
+
|
408
|
+
// Set a default color
|
409
|
+
var swatches = this.minicolors_options.swatches;
|
410
|
+
var num = label_num === 0 ? var_id : label_num;
|
411
|
+
var default_color = swatches[num % swatches.length];
|
412
|
+
color_div.find('[name="dataset-color"]').minicolors(this.minicolors_options).val(default_color).change();
|
413
|
+
color_div.find('.minicolors-input-swatch .minicolors-swatch-color').css("background-color", default_color);
|
414
|
+
},
|
415
|
+
|
416
|
+
removeVar: function(e) {
|
417
|
+
var target = $(e.target);
|
418
|
+
|
419
|
+
var var_div = target.closest('.var-div');
|
420
|
+
var id = var_div.attr("data-id");
|
421
|
+
this.container.find('[data-id="' + id + '"]').remove();
|
422
|
+
},
|
423
|
+
|
424
|
+
checkMainType: function() {
|
425
|
+
var main_type = this.yContainer.find('[name="main-type"]').val();
|
426
|
+
|
427
|
+
if (main_type === 'bar' || main_type === 'line') {
|
428
|
+
this.yContainer.find('[name="type"]').show();
|
429
|
+
this.styleOptionsContainer.find('#style-barline').show();
|
430
|
+
}
|
431
|
+
else {
|
432
|
+
this.yContainer.find('[name="type"]').hide();
|
433
|
+
this.styleOptionsContainer.find('#style-barline').hide();
|
434
|
+
this.styleOptionsContainer.find('#style-line').hide();
|
435
|
+
}
|
436
|
+
|
437
|
+
return main_type;
|
438
|
+
},
|
439
|
+
|
440
|
+
|
441
|
+
// --------------- Selection callbacks ---------------
|
442
|
+
axisSelection: function(e) {
|
443
|
+
var target = $(e.target);
|
444
|
+
|
445
|
+
var select_name = target.attr("name");
|
446
|
+
|
447
|
+
// Remove previous options
|
448
|
+
target.children('option').not('[value=""]').remove();
|
449
|
+
|
450
|
+
// Different handling for main or second variable
|
451
|
+
if (select_name === 'y-axis')
|
452
|
+
this.fillYAxisSelect(target);
|
453
|
+
else if (select_name === 'x-axis')
|
454
|
+
this.fillXAxisSelect(target);
|
455
|
+
else
|
456
|
+
this.fillXSubSelect(target);
|
457
|
+
},
|
458
|
+
|
459
|
+
fillYAxisSelect: function(select) {
|
460
|
+
var options_string = '';
|
461
|
+
|
462
|
+
// Take models from filters if associated with filter_creator
|
463
|
+
var displayed_model_names = this.displayed_model_names;
|
464
|
+
if (this.filter_creator !== null) {
|
465
|
+
this.filter_creator.find('.top-filter').each(function() {
|
466
|
+
var filter_id = $(this).attr("data-id");
|
467
|
+
var model = $(this).find('[name="model"]').val();
|
468
|
+
if (model !== '') {
|
469
|
+
var model_name_to_display = displayed_model_names[model];
|
470
|
+
if (typeof model_name_to_display === 'undefined')
|
471
|
+
model_name_to_display = model.humanize();
|
472
|
+
options_string += '<option value="' + model + '">Filter ' + filter_id + ': ' + model_name_to_display + '</option>';
|
473
|
+
}
|
474
|
+
});
|
475
|
+
}
|
476
|
+
else {
|
477
|
+
$.each(this.models_data, function(model, attributes) {
|
478
|
+
var model_name_to_display = displayed_model_names[model];
|
479
|
+
if (typeof model_name_to_display === 'undefined')
|
480
|
+
model_name_to_display = model.humanize();
|
481
|
+
options_string += '<option value="' + model + '">' + model_name_to_display + '</option>';
|
482
|
+
});
|
483
|
+
}
|
484
|
+
|
485
|
+
// Append options to select
|
486
|
+
$(options_string).appendTo(select);
|
487
|
+
},
|
488
|
+
|
489
|
+
fillXAxisSelect: function(select) {
|
490
|
+
var options_string = '';
|
491
|
+
var attributes_aliases = this.attributes_aliases;
|
492
|
+
|
493
|
+
// Get model data
|
494
|
+
var y_vals = [];
|
495
|
+
this.yContainer.find('[name="y-axis"]').each(function() {
|
496
|
+
var model = $(this).val().split('-')[0];
|
497
|
+
var alias = attributes_aliases[model];
|
498
|
+
model = (typeof alias === 'undefined') ? model : alias;
|
499
|
+
y_vals.push(model.classify());
|
500
|
+
});
|
501
|
+
var model_data = this.yAxesDataInCommon(y_vals);
|
502
|
+
|
503
|
+
// Get list of filtered models
|
504
|
+
var filtered_models = [];
|
505
|
+
if (this.filter_creator !== null) {
|
506
|
+
this.filter_creator.find('.top-filter').each(function() {
|
507
|
+
var model = $(this).find('[name="model"]').val();
|
508
|
+
if (model !== '')
|
509
|
+
filtered_models.push(model);
|
510
|
+
});
|
511
|
+
}
|
512
|
+
|
513
|
+
var filter_creator = this.filter_creator;
|
514
|
+
var displayed_attribute_names = this.displayed_attribute_names[y_vals[0]];
|
515
|
+
$.each(model_data, function(idx, str) {
|
516
|
+
var key = str.split('-')[0], value = str.split('-')[1];
|
517
|
+
|
518
|
+
// Create option string for each attribute
|
519
|
+
var key_name_to_display = (typeof displayed_attribute_names === 'undefined') ? undefined : displayed_attribute_names[key];
|
520
|
+
if (typeof key_name_to_display === 'undefined')
|
521
|
+
key_name_to_display = key.humanize();
|
522
|
+
|
523
|
+
var new_option_string = '<option value="' + key + '-' + value + '">' + key_name_to_display;
|
524
|
+
if (value === 'has')
|
525
|
+
new_option_string += ' (has relation)';
|
526
|
+
if (value === 'ref')
|
527
|
+
new_option_string += ' (belongs relation)';
|
528
|
+
|
529
|
+
// If attribute is a related model that is filtered, copy the option to have filtered or not version
|
530
|
+
var alias = attributes_aliases[key];
|
531
|
+
var key_model = (typeof alias === 'undefined') ? key : alias;
|
532
|
+
if ($.inArray(key_model.classify(), filtered_models) !== -1) {
|
533
|
+
new_option_string += '</option>' +
|
534
|
+
'<option value="' + key + '-' + value + '-filter">' + key_name_to_display;
|
535
|
+
|
536
|
+
var filters_model_selects = filter_creator.find('[name="model"]');
|
537
|
+
filters_model_selects.each(function() {
|
538
|
+
var model = $(this).val();
|
539
|
+
if (model === key_model.classify()) {
|
540
|
+
var filter_id = $(this).closest('.top-filter').attr("data-id");
|
541
|
+
new_option_string += ' (Filter ' + filter_id + ')';
|
542
|
+
}
|
543
|
+
});
|
544
|
+
}
|
545
|
+
options_string += new_option_string + '</option>';
|
546
|
+
});
|
547
|
+
|
548
|
+
// Append options to select
|
549
|
+
$(options_string).appendTo(select);
|
550
|
+
},
|
551
|
+
|
552
|
+
fillXSubSelect: function(select) {
|
553
|
+
var options_string = '';
|
554
|
+
|
555
|
+
// Get model data
|
556
|
+
var x_model = this.xContainer.find('[name="x-axis"]').val().split('-')[0];
|
557
|
+
var alias = this.attributes_aliases[x_model];
|
558
|
+
x_model = (typeof alias === 'undefined') ? x_model : alias;
|
559
|
+
var model_data = this.models_data[x_model.classify()];
|
560
|
+
|
561
|
+
var plotting_types = ['text', 'numeric', 'boolean', 'datetime'];
|
562
|
+
var displayed_attribute_names = this.displayed_attribute_names[x_model.classify()];
|
563
|
+
$.each(model_data, function(idx, str) {
|
564
|
+
var key = str.split('-')[0], value = str.split('-')[1];
|
565
|
+
// Get types that can be used for plotting
|
566
|
+
if ($.inArray(value, plotting_types) === -1) return true;
|
567
|
+
|
568
|
+
var key_name_to_display = (typeof displayed_attribute_names === 'undefined') ? undefined : displayed_attribute_names[key];
|
569
|
+
if (typeof key_name_to_display === 'undefined')
|
570
|
+
key_name_to_display = key.humanize();
|
571
|
+
|
572
|
+
// Create option string for each attribute
|
573
|
+
options_string += '<option value="' + key + '-' + value + '">' + key_name_to_display + '</option>';
|
574
|
+
});
|
575
|
+
|
576
|
+
// Append options to select
|
577
|
+
$(options_string).appendTo(select);
|
578
|
+
},
|
579
|
+
|
580
|
+
yAxesDataInCommon: function(models) {
|
581
|
+
var models_data = this.models_data;
|
582
|
+
|
583
|
+
var first_model_data = models_data[models[0]];
|
584
|
+
if (models.length === 1)
|
585
|
+
return first_model_data;
|
586
|
+
|
587
|
+
var final_data = [];
|
588
|
+
$.each(models, function(index, model) {
|
589
|
+
if (index === 0) return true;
|
590
|
+
|
591
|
+
$.each(first_model_data, function(idx, str) {
|
592
|
+
if ($.inArray(str, models_data[model]) !== -1) final_data.push(str);
|
593
|
+
});
|
594
|
+
});
|
595
|
+
|
596
|
+
return final_data;
|
597
|
+
},
|
598
|
+
|
599
|
+
axisSelectionCallback: function(e) {
|
600
|
+
var target = $(e.target);
|
601
|
+
|
602
|
+
var select_name = target.attr("name");
|
603
|
+
var attribute = target.val().split('-')[0], attribute_type = target.val().split('-')[1];
|
604
|
+
if (select_name === 'y-axis') {
|
605
|
+
target.closest('.var-div').find('[name="dataset-label"]').val(attribute);
|
606
|
+
this.showXAxisSelect();
|
607
|
+
}
|
608
|
+
else {
|
609
|
+
// Hide if empty value (prompt value)
|
610
|
+
if (attribute === '') {
|
611
|
+
if (select_name === 'x-axis')
|
612
|
+
this.labelOptionsContainer.children().not('#label').hide();
|
613
|
+
else
|
614
|
+
this.labelOptionsContainer.children().not('#label').not('#label-type-radio-div').remove();
|
615
|
+
return;
|
616
|
+
}
|
617
|
+
this.showLabelOptions(select_name, attribute_type);
|
618
|
+
}
|
619
|
+
},
|
620
|
+
|
621
|
+
showXAxisSelect: function() {
|
622
|
+
if (this.yContainer.find('[name="y-axis"]').first().val() === '') {
|
623
|
+
this.xContainer.find('#x-axis-select-div').hide();
|
624
|
+
this.labelOptionsContainer.children().not('#label').remove();
|
625
|
+
}
|
626
|
+
else this.xContainer.find('#x-axis-select-div').show();
|
627
|
+
},
|
628
|
+
|
629
|
+
showLabelOptions: function(select_name, attribute_type) {
|
630
|
+
// Otherwise show and remove previous options
|
631
|
+
this.labelOptionsContainer.children().show();
|
632
|
+
var is_sub = false;
|
633
|
+
if (select_name === 'x-sub' && this.labelOptionsContainer.find('[name="labels-type"]:checked').val() === 'attribute') {
|
634
|
+
this.labelOptionsContainer.children().not('#label-type-radio-div').not('#label').remove();
|
635
|
+
is_sub = true;
|
636
|
+
}
|
637
|
+
else
|
638
|
+
this.labelOptionsContainer.children().not('#label').remove();
|
639
|
+
|
640
|
+
// Display according to attribute type
|
641
|
+
switch(attribute_type) {
|
642
|
+
case 'datetime':
|
643
|
+
this.showDatetimeLabelOptions();
|
644
|
+
break;
|
645
|
+
|
646
|
+
case 'numeric':
|
647
|
+
this.showNumericLabelTypes(is_sub);
|
648
|
+
break;
|
649
|
+
|
650
|
+
case 'boolean':
|
651
|
+
this.showBooleanLabelOptions(is_sub);
|
652
|
+
break;
|
653
|
+
|
654
|
+
case 'text':
|
655
|
+
this.showTextLabelTypes(is_sub);
|
656
|
+
break;
|
657
|
+
|
658
|
+
case 'ref':
|
659
|
+
this.showRefLabelTypes(is_sub);
|
660
|
+
break;
|
661
|
+
|
662
|
+
case 'has':
|
663
|
+
this.showHasLabelTypes(is_sub);
|
664
|
+
break;
|
665
|
+
|
666
|
+
default:
|
667
|
+
this.showErrorMessage(is_sub, attribute_type);
|
668
|
+
break;
|
669
|
+
}
|
670
|
+
|
671
|
+
// Add options to page and change labels number to display further options
|
672
|
+
if (!is_sub)
|
673
|
+
this.labelOptionsContainer.find('#label-type-radio-div').find('[type="radio"]:first').click();
|
674
|
+
else
|
675
|
+
this.labelOptionsContainer.find('#sub-label-type-radio-div').find('[type="radio"]:first').click();
|
676
|
+
},
|
677
|
+
|
678
|
+
showDatetimeLabelOptions: function() {
|
679
|
+
this.labelOptionsContainer.find('#sub-label-type-radio-div').remove();
|
680
|
+
|
681
|
+
// Select input for date range
|
682
|
+
var date_range_options = [
|
683
|
+
'Today',
|
684
|
+
'Yesterday',
|
685
|
+
'Last 7 Days',
|
686
|
+
'This Week',
|
687
|
+
'Last Week',
|
688
|
+
'Last 30 Days',
|
689
|
+
'This Month',
|
690
|
+
'Last Month',
|
691
|
+
'Last 365 Days',
|
692
|
+
'This Year',
|
693
|
+
'Last Year',
|
694
|
+
'Fixed Date Range'
|
695
|
+
];
|
696
|
+
var date_range_select_string = '<select name="date_range" id="date-range-select" class="form-control">' +
|
697
|
+
'<option value="">Choose a date range</option>';
|
698
|
+
$.each(date_range_options, function(index, daterange) {
|
699
|
+
date_range_select_string += '<option value="' + daterange + '">' + daterange + '</option>';
|
700
|
+
});
|
701
|
+
date_range_select_string += '</select>';
|
702
|
+
|
703
|
+
var options_string = '<div class="col-sm-6">'
|
704
|
+
+ '<div class="form-group">'
|
705
|
+
+ '<label>Date range</label>'
|
706
|
+
+ date_range_select_string
|
707
|
+
+ '</div></div>';
|
708
|
+
|
709
|
+
// Choose period plot : day, week, month
|
710
|
+
options_string += '<div class="col-sm-2">'
|
711
|
+
+ '<div class="form-group">'
|
712
|
+
+ '<input type="radio" name="period" value="day" checked="checked" class="form-control">'
|
713
|
+
+ '<label>Day</label>'
|
714
|
+
+ '</div></div>';
|
715
|
+
options_string += '<div class="col-sm-2">'
|
716
|
+
+ '<div class="form-group">'
|
717
|
+
+ '<input type="radio" name="period" value="week" class="form-control">'
|
718
|
+
+ '<label>Week</label>'
|
719
|
+
+ '</div></div>';
|
720
|
+
options_string += '<div class="col-sm-2">'
|
721
|
+
+ '<div class="form-group">'
|
722
|
+
+ '<input type="radio" name="period" value="month" class="form-control">'
|
723
|
+
+ '<label>Month</label>'
|
724
|
+
+ '</div></div>';
|
725
|
+
|
726
|
+
// // Choose date formatting in the labels
|
727
|
+
// options_string += form_div_string_start
|
728
|
+
// + '<label>Date formatting</label>'
|
729
|
+
// + '<input type="text" name="format" value="%Y/%m/%d" class="form-control">'
|
730
|
+
// + '</div></div>';
|
731
|
+
|
732
|
+
$(options_string).appendTo(this.labelOptionsContainer);
|
733
|
+
|
734
|
+
var parent_div = $('<div class="col-sm-12"></div>').appendTo(this.labelOptionsContainer);
|
735
|
+
var parent_div = $('<div class="form-group"></div>').appendTo(parent_div);
|
736
|
+
|
737
|
+
// Add daterangepicker
|
738
|
+
daterangeField(parent_div);
|
739
|
+
},
|
740
|
+
|
741
|
+
showNumericLabelTypes: function(is_sub) {
|
742
|
+
var sub = is_sub ? 'sub-' : '';
|
743
|
+
var options_string = '<div class="col-sm-12 row" id="' + sub + 'label-type-radio-div">'
|
744
|
+
+ '<div class="col-sm-4">'
|
745
|
+
+ '<div class="form-group">'
|
746
|
+
+ '<input type="radio" name="' + sub + 'labels-type" value="numeric" class="form-control">'
|
747
|
+
+ '<label>Define labels</label>'
|
748
|
+
+ '</div></div>';
|
749
|
+
options_string += '<div class="col-sm-4">'
|
750
|
+
+ '<div class="form-group">'
|
751
|
+
+ '<input type="radio" name="' + sub + 'labels-type" value="number" class="form-control">'
|
752
|
+
+ '<label>Count</label>'
|
753
|
+
+ '</div></div>'
|
754
|
+
+ '</div>';
|
755
|
+
$(options_string).appendTo(this.labelOptionsContainer);
|
756
|
+
},
|
757
|
+
|
758
|
+
showBooleanLabelOptions: function() {
|
759
|
+
var labels_options_string = '<div class="col-sm-12 label-limit-div">'
|
760
|
+
+ '<div class="row">'
|
761
|
+
+ '<div class="col-sm-3">'
|
762
|
+
+ '<div class="form-group">'
|
763
|
+
+ '<label>Value</label>'
|
764
|
+
+ '<input type="text" class="limit-label form-control" name="boolean-true" value="true" disabled="disabled">'
|
765
|
+
+ '</div></div>'
|
766
|
+
+ '<div class="col-sm-9">'
|
767
|
+
+ '<div class="form-group">'
|
768
|
+
+ '<label>Correspondence</label>'
|
769
|
+
+ '<input type="text" class="limit-label-corres form-control" name="boolean-true-corres">'
|
770
|
+
+ '</div></div></div>'
|
771
|
+
+ '<div class="row">'
|
772
|
+
+ '<div class="col-sm-3">'
|
773
|
+
+ '<div class="form-group">'
|
774
|
+
+ '<label>Value</label>'
|
775
|
+
+ '<input type="text" class="limit-label form-control" name="boolean-false" value="false" disabled="disabled">'
|
776
|
+
+ '</div></div>'
|
777
|
+
+ '<div class="col-sm-9">'
|
778
|
+
+ '<div class="form-group">'
|
779
|
+
+ '<label>Correspondence</label>'
|
780
|
+
+ '<input type="text" class="limit-label-corres form-control" name="boolean-false-corres">'
|
781
|
+
+ '</div></div></div>'
|
782
|
+
+ '</div>';
|
783
|
+
$(labels_options_string).appendTo(this.labelOptionsContainer);
|
784
|
+
},
|
785
|
+
|
786
|
+
showTextLabelTypes: function(is_sub) {
|
787
|
+
var sub = is_sub ? 'sub-' : '';
|
788
|
+
var options_string = '<div class="col-sm-12 row" id="' + sub + 'label-type-radio-div">'
|
789
|
+
+ '<div class="col-sm-4">'
|
790
|
+
+ '<div class="form-group">'
|
791
|
+
+ '<input type="radio" name="' + sub + 'labels-type" value="text-auto" class="form-control">'
|
792
|
+
+ '<label>Auto text labels</label>'
|
793
|
+
+ '</div></div>';
|
794
|
+
options_string += '<div class="col-sm-4">'
|
795
|
+
+ '<div class="form-group">'
|
796
|
+
+ '<input type="radio" name="' + sub + 'labels-type" value="text" class="form-control">'
|
797
|
+
+ '<label>Define labels</label>'
|
798
|
+
+ '</div></div>'
|
799
|
+
+ '</div>';
|
800
|
+
$(options_string).appendTo(this.labelOptionsContainer);
|
801
|
+
},
|
802
|
+
|
803
|
+
showRefLabelTypes: function(is_sub) {
|
804
|
+
var sub = is_sub ? 'sub-' : '';
|
805
|
+
var options_string = '<div class="col-sm-12 row" id="' + sub + 'label-type-radio-div">'
|
806
|
+
+ '<div class="col-sm-4">'
|
807
|
+
+ '<div class="form-group">'
|
808
|
+
+ '<input type="radio" name="' + sub + 'labels-type" value="number" class="form-control">'
|
809
|
+
+ '<label>Count</label>'
|
810
|
+
+ '</div></div>';
|
811
|
+
options_string += '<div class="col-sm-4">'
|
812
|
+
+ '<div class="form-group">'
|
813
|
+
+ '<input type="radio" name="' + sub + 'labels-type" value="attribute" class="form-control">'
|
814
|
+
+ '<label>Sub-attribute</label>'
|
815
|
+
+ '</div></div>'
|
816
|
+
+ '</div>';
|
817
|
+
$(options_string).appendTo(this.labelOptionsContainer);
|
818
|
+
},
|
819
|
+
|
820
|
+
showHasLabelTypes: function(is_sub) {
|
821
|
+
var sub = is_sub ? 'sub-' : '';
|
822
|
+
var options_string = '<div class="col-sm-12 row" id="' + sub + 'label-type-radio-div">'
|
823
|
+
+ '<div class="col-sm-4">'
|
824
|
+
+ '<div class="form-group">'
|
825
|
+
+ '<input type="radio" name="' + sub + 'labels-type" value="number" class="form-control">'
|
826
|
+
+ '<label>Count</label>'
|
827
|
+
+ '</div></div>';
|
828
|
+
options_string += '<div class="col-sm-4">'
|
829
|
+
+ '<div class="form-group">'
|
830
|
+
+ '<input type="radio" name="' + sub + 'labels-type" value="attribute" class="form-control">'
|
831
|
+
+ '<label>Sub-attribute</label>'
|
832
|
+
+ '</div></div>'
|
833
|
+
+ '</div>';
|
834
|
+
$(options_string).appendTo(this.labelOptionsContainer);
|
835
|
+
},
|
836
|
+
|
837
|
+
showErrorMessage: function(is_sub, type) {
|
838
|
+
var sub = is_sub ? 'sub-' : '';
|
839
|
+
var options_string = '<div class="col-sm-12" id="' + sub + 'label-type-radio-div">'
|
840
|
+
+ '<strong>Type ' + type + ' is not handled</strong>'
|
841
|
+
+ '</div>';
|
842
|
+
$(options_string).appendTo(this.labelOptionsContainer);
|
843
|
+
},
|
844
|
+
|
845
|
+
daterangeSelection: function(e) {
|
846
|
+
var target = $(e.target);
|
847
|
+
|
848
|
+
// Change date format
|
849
|
+
var label_options_container = this.labelOptionsContainer;
|
850
|
+
function cb(start, end) {
|
851
|
+
label_options_container.find('#daterange-chart span').html(start.format('MMMM D, YYYY') + ' - ' + end.format('MMMM D, YYYY'));
|
852
|
+
}
|
853
|
+
|
854
|
+
switch(target.val()) {
|
855
|
+
case 'Today':
|
856
|
+
cb(moment(), moment());
|
857
|
+
break;
|
858
|
+
|
859
|
+
case 'Yesterday':
|
860
|
+
cb(moment().subtract(1, 'days'), moment().subtract(1, 'days'));
|
861
|
+
break;
|
862
|
+
|
863
|
+
case 'Last 7 Days':
|
864
|
+
cb(moment().subtract(6, 'days'), moment());
|
865
|
+
break;
|
866
|
+
|
867
|
+
case 'This Week':
|
868
|
+
cb(moment().startOf('week'), moment().endOf('week'));
|
869
|
+
break;
|
870
|
+
|
871
|
+
case 'Last Week':
|
872
|
+
cb(moment().subtract(1, 'week').startOf('week'), moment().subtract(1, 'week').endOf('week'));
|
873
|
+
break;
|
874
|
+
|
875
|
+
case 'Last 30 Days':
|
876
|
+
cb(moment().subtract(29, 'days'), moment());
|
877
|
+
break;
|
878
|
+
|
879
|
+
case 'This Month':
|
880
|
+
cb(moment().startOf('month'), moment().endOf('month'));
|
881
|
+
break;
|
882
|
+
|
883
|
+
case 'Last Month':
|
884
|
+
cb(moment().subtract(1, 'month').startOf('month'), moment().subtract(1, 'month').endOf('month'));
|
885
|
+
break;
|
886
|
+
|
887
|
+
case 'Last 365 Days':
|
888
|
+
cb(moment().subtract(364, 'days'), moment());
|
889
|
+
break;
|
890
|
+
|
891
|
+
case 'This Year':
|
892
|
+
cb(moment().startOf('year'), moment().endOf('year'));
|
893
|
+
break;
|
894
|
+
|
895
|
+
case 'Last Year':
|
896
|
+
cb(moment().subtract(1, 'year').startOf('year'), moment().subtract(1, 'year').endOf('year'));
|
897
|
+
break;
|
898
|
+
|
899
|
+
case 'Fixed Date Range':
|
900
|
+
default:
|
901
|
+
break;
|
902
|
+
|
903
|
+
}
|
904
|
+
},
|
905
|
+
|
906
|
+
changeLabelTypeCallback: function(e) {
|
907
|
+
var target = $(e.target);
|
908
|
+
|
909
|
+
var value = target.val();
|
910
|
+
this.labelOptionsContainer.find('.limit-label').prop("type", value);
|
911
|
+
|
912
|
+
if (target.attr("name") === 'labels-type') {
|
913
|
+
this.labelOptionsContainer.find('#sub-select-div').remove();
|
914
|
+
this.labelOptionsContainer.children().not('#label-type-radio-div').not('#label').remove();
|
915
|
+
}
|
916
|
+
else {
|
917
|
+
this.labelOptionsContainer.children().not('#label-type-radio-div').not('#sub-label-type-radio-div').not('#label').remove();
|
918
|
+
}
|
919
|
+
|
920
|
+
switch(value) {
|
921
|
+
case 'attribute':
|
922
|
+
this.showAttributeLabelOptions();
|
923
|
+
break;
|
924
|
+
|
925
|
+
case 'text-auto':
|
926
|
+
this.labelOptionsContainer.children().not('#label-type-radio-div').not('#sub-label-type-radio-div').not('#label').remove();
|
927
|
+
break;
|
928
|
+
|
929
|
+
case 'numeric':
|
930
|
+
this.showNumericLabelOptions();
|
931
|
+
break;
|
932
|
+
|
933
|
+
case 'number':
|
934
|
+
this.showNumberLabelOptions();
|
935
|
+
break;
|
936
|
+
|
937
|
+
case 'text':
|
938
|
+
this.showTextLabelOptions();
|
939
|
+
break;
|
940
|
+
|
941
|
+
default:
|
942
|
+
break;
|
943
|
+
}
|
944
|
+
},
|
945
|
+
|
946
|
+
showAttributeLabelOptions: function() {
|
947
|
+
this.labelOptionsContainer.children().not('#label-type-radio-div').not('#label').remove();
|
948
|
+
var select_string = '<div class="col-sm-4" id="sub-select-div">'
|
949
|
+
+ '<select class="axis-select form-control" name="x-sub">'
|
950
|
+
+ '<option value="">Choose sub-attribute</option>'
|
951
|
+
+ '</select></div>';
|
952
|
+
$(select_string).appendTo(this.labelOptionsContainer.find('#label-type-radio-div'));
|
953
|
+
},
|
954
|
+
|
955
|
+
showNumericLabelOptions: function() {
|
956
|
+
var labels_num_div_string = '<div class="col-sm-12" id="labels-num-div" style="margin-bottom:20px;">'
|
957
|
+
+ '<div class="form-group">'
|
958
|
+
+ '<label>Number of labels</label>'
|
959
|
+
+ '<input type="number" name="labels-num" min="1" value="3" class="form-control">'
|
960
|
+
+ '</div>'
|
961
|
+
+ '<div class="row">'
|
962
|
+
+ '<div class="col-sm-6">'
|
963
|
+
+ '<button class="pull-right btn btn-primary" id="pluck-labels-btn">Generate values with limit: </button>'
|
964
|
+
+ '</div>'
|
965
|
+
+ '<div class="col-sm-6">'
|
966
|
+
+ '<input type="number" name="pluck-num" min="1" value="3" class="form-control pull-right">'
|
967
|
+
+ '</div></div></div>';
|
968
|
+
$(labels_num_div_string).appendTo(this.labelOptionsContainer);
|
969
|
+
this.labelOptionsContainer.find('[name="labels-num"]').change();
|
970
|
+
},
|
971
|
+
|
972
|
+
showNumberLabelOptions: function() {
|
973
|
+
var labels_num_div_string = '<div class="col-sm-12" id="labels-num-div" style="margin-bottom:20px;">'
|
974
|
+
+ '<div class="form-group">'
|
975
|
+
+ '<label>Number of labels</label>'
|
976
|
+
+ '<input type="number" name="labels-num" min="1" value="3" class="form-control">'
|
977
|
+
+ '</div></div>'
|
978
|
+
+ '<div class="col-sm-12" id="plus-div">'
|
979
|
+
+ '<div class="form-group">'
|
980
|
+
+ '<input type="radio" name="plus" value="true" class="form-control" checked="checked">'
|
981
|
+
+ '<label>+</label>'
|
982
|
+
+ '</div>'
|
983
|
+
+ '<div class="form-group">'
|
984
|
+
+ '<input type="radio" name="plus" value="false" class="form-control">'
|
985
|
+
+ '<label>Not +</label>'
|
986
|
+
+ '</div></div>';
|
987
|
+
$(labels_num_div_string).appendTo(this.labelOptionsContainer);
|
988
|
+
this.labelOptionsContainer.find('[name="labels-num"]').change();
|
989
|
+
},
|
990
|
+
|
991
|
+
showTextLabelOptions: function() {
|
992
|
+
var labels_num_div_string = '<div class="col-sm-12" id="labels-num-div" style="margin-bottom:20px;">'
|
993
|
+
+ '<div class="form-group">'
|
994
|
+
+ '<label>Number of labels</label>'
|
995
|
+
+ '<input type="number" name="labels-num" min="1" value="3" class="form-control">'
|
996
|
+
+ '</div>'
|
997
|
+
+ '<div class="row">'
|
998
|
+
+ '<div class="col-sm-6">'
|
999
|
+
+ '<button class="pull-right btn btn-primary" id="pluck-labels-btn">Generate labels with limit: </button>'
|
1000
|
+
+ '</div>'
|
1001
|
+
+ '<div class="col-sm-6">'
|
1002
|
+
+ '<input type="number" name="pluck-num" min="1" value="30" class="form-control pull-right">'
|
1003
|
+
+ '</div></div></div>';
|
1004
|
+
$(labels_num_div_string).appendTo(this.labelOptionsContainer);
|
1005
|
+
this.labelOptionsContainer.find('[name="labels-num"]').change();
|
1006
|
+
},
|
1007
|
+
|
1008
|
+
changeLabelsNumCallback: function() {
|
1009
|
+
var low_limit_div = this.labelOptionsContainer.find('#low-limit-div'), labels_num_div = this.labelOptionsContainer.find('#labels-num-div');
|
1010
|
+
|
1011
|
+
var number = labels_num_div.find('[name="labels-num"]').val(), previous_number = this.labelOptionsContainer.find('.label-limit-div').length;
|
1012
|
+
var labels_options_string = '';
|
1013
|
+
|
1014
|
+
var label_type = this.labelOptionsContainer.find('[name="labels-type"]:checked').val();
|
1015
|
+
if (label_type === 'attribute') label_type = this.labelOptionsContainer.find('[name="sub-labels-type"]:checked').val();
|
1016
|
+
var label_base = (label_type === 'number') ? 'Limit ' : 'Label ';
|
1017
|
+
|
1018
|
+
this.labelOptionsContainer.find('.limit-label').each(function() {
|
1019
|
+
var id = $(this).attr("name").split('-')[1];
|
1020
|
+
if (id !== '0') $(this).siblings('label').text(label_base + id);
|
1021
|
+
});
|
1022
|
+
|
1023
|
+
// Display low limit for first display
|
1024
|
+
if (label_type === 'number' && low_limit_div.length === 0) {
|
1025
|
+
labels_options_string = '<div class="col-sm-6" id="low-limit-div">'
|
1026
|
+
+ '<div class="form-group">'
|
1027
|
+
+ '<label>Low limit</label>'
|
1028
|
+
+ '<input type="number" class="limit-label form-control" name="label-0" min="0" value="0">'
|
1029
|
+
+ '</div></div>';
|
1030
|
+
$(labels_options_string).insertAfter(labels_num_div);
|
1031
|
+
low_limit_div = this.labelOptionsContainer.find('#low-limit-div');
|
1032
|
+
}
|
1033
|
+
|
1034
|
+
// On change of labels number, either remove fields if too many, either add fields
|
1035
|
+
if (number >= previous_number) {
|
1036
|
+
labels_options_string = '';
|
1037
|
+
for (var i = previous_number + 1; i <= number; i++) {
|
1038
|
+
if (label_type === 'numeric') {
|
1039
|
+
labels_options_string += '<div class="col-sm-12 label-limit-div">'
|
1040
|
+
+ '<div class="row">'
|
1041
|
+
+ '<div class="col-sm-3">'
|
1042
|
+
+ '<div class="form-group">'
|
1043
|
+
+ '<label>Value ' + i +'</label>'
|
1044
|
+
+ '<input type="number" class="limit-label form-control" name="label-' + i + '">'
|
1045
|
+
+ '</div></div>'
|
1046
|
+
+ '<div class="col-sm-9">'
|
1047
|
+
+ '<div class="form-group">'
|
1048
|
+
+ '<label>Correspondence ' + i +'</label>'
|
1049
|
+
+ '<input type="text" class="limit-label-corres form-control" name="label-corres-' + i + '">'
|
1050
|
+
+ '</div></div></div></div>';
|
1051
|
+
}
|
1052
|
+
else {
|
1053
|
+
labels_options_string += '<div class="col-sm-6 label-limit-div">'
|
1054
|
+
+ '<div class="form-group">'
|
1055
|
+
+ '<label>' + label_base + i +'</label>'
|
1056
|
+
+ '<input type="' + label_type + '" class="limit-label form-control" name="label-' + i + '" min="0">'
|
1057
|
+
+ '</div></div>';
|
1058
|
+
}
|
1059
|
+
}
|
1060
|
+
|
1061
|
+
if (previous_number === 0) {
|
1062
|
+
if (label_type === 'number') $(labels_options_string).insertAfter(low_limit_div);
|
1063
|
+
else $(labels_options_string).insertAfter(labels_num_div);
|
1064
|
+
}
|
1065
|
+
else $(labels_options_string).insertAfter(this.labelOptionsContainer.find('.label-limit-div:last'));
|
1066
|
+
}
|
1067
|
+
else {
|
1068
|
+
for (var i = previous_number; i > number; i--) {
|
1069
|
+
this.labelOptionsContainer.find('.label-limit-div:last').remove();
|
1070
|
+
}
|
1071
|
+
}
|
1072
|
+
},
|
1073
|
+
|
1074
|
+
|
1075
|
+
// --------------- Prepare data ---------------
|
1076
|
+
getChartData: function() {
|
1077
|
+
var chart_data = {};
|
1078
|
+
|
1079
|
+
// Axes Data
|
1080
|
+
this.getAxesData(chart_data);
|
1081
|
+
|
1082
|
+
// Style Options
|
1083
|
+
var style_options = chart_data['style'] = {};
|
1084
|
+
this.getStyleData(style_options);
|
1085
|
+
this.getColorData(style_options);
|
1086
|
+
|
1087
|
+
if (this.filter_creator === null)
|
1088
|
+
this.addDefaultFilters(chart_data);
|
1089
|
+
else
|
1090
|
+
chart_data = $.extend(chart_data, {filters: this.filter_creator.data('filterCreator').getFiltersData()});
|
1091
|
+
|
1092
|
+
return JSON.parse(JSON.stringify(chart_data));
|
1093
|
+
},
|
1094
|
+
|
1095
|
+
getAxesData: function(chart_data) {
|
1096
|
+
// Get select fields values
|
1097
|
+
var split_x_axis = this.xContainer.find('[name="x-axis"]').val().split('-');
|
1098
|
+
var x_val = split_x_axis[0], x_type = split_x_axis[1];
|
1099
|
+
var y_vals = [];
|
1100
|
+
this.yContainer.find('[name="y-axis"]').each(function() {
|
1101
|
+
y_vals.push($(this).val());
|
1102
|
+
});
|
1103
|
+
|
1104
|
+
// Return if x or y missing
|
1105
|
+
if (x_val === '' || y_vals.length === 0)
|
1106
|
+
return alert('Variable missing.');
|
1107
|
+
|
1108
|
+
// If type is datetime, prepare date_info
|
1109
|
+
chart_data['x_data'] = {};
|
1110
|
+
chart_data['x_data']['type'] = x_type;
|
1111
|
+
var label_type = this.labelOptionsContainer.find('[name="labels-type"]:checked').val();
|
1112
|
+
if (label_type === 'attribute') {
|
1113
|
+
var sub_array = this.labelOptionsContainer.find('.axis-select[name="x-sub"]').val().split('-');
|
1114
|
+
chart_data['x_data']['sub_attribute'] = sub_array[0];
|
1115
|
+
chart_data['x_data']['sub_attribute_from'] = x_type;
|
1116
|
+
chart_data['x_data']['type'] = sub_array[1];
|
1117
|
+
label_type = this.labelOptionsContainer.find('[name="sub-labels-type"]:checked').val();
|
1118
|
+
}
|
1119
|
+
chart_data['x_data']['label_type'] = label_type;
|
1120
|
+
|
1121
|
+
switch(chart_data['x_data']['type']) {
|
1122
|
+
case 'datetime':
|
1123
|
+
var date_info = chart_data['x_data'];
|
1124
|
+
var daterange = this.labelOptionsContainer.find('.daterange-value').text().split(' - ');
|
1125
|
+
date_info['start'] = daterange[0];
|
1126
|
+
date_info['end'] = daterange[1];
|
1127
|
+
date_info['date_range_type'] = this.labelOptionsContainer.find('#date-range-select').val();
|
1128
|
+
date_info['period'] = this.labelOptionsContainer.find('[name="period"]:checked').val();
|
1129
|
+
// date_info['format'] = label_options_div.find('input[name="format"]').val();
|
1130
|
+
break;
|
1131
|
+
|
1132
|
+
case 'has':
|
1133
|
+
case 'ref':
|
1134
|
+
case 'text':
|
1135
|
+
case 'numeric':
|
1136
|
+
if (label_type === 'text-auto') break;
|
1137
|
+
|
1138
|
+
var labels_num = this.labelOptionsContainer.find('.label-limit-div').length;
|
1139
|
+
var labels = chart_data['x_data']['labels'] = [];
|
1140
|
+
var labels_corres = chart_data['x_data']['labels-corres'] = [];
|
1141
|
+
|
1142
|
+
for (var i = 1; i <= labels_num; i++) {
|
1143
|
+
if (label_type === 'number') {
|
1144
|
+
var low = parseInt(this.labelOptionsContainer.find('[name="label-' + (i-1) + '"]').val()), high = parseInt(this.labelOptionsContainer.find('[name="label-' + i + '"]').val()) - 1;
|
1145
|
+
if (low === high)
|
1146
|
+
labels.push(low);
|
1147
|
+
else
|
1148
|
+
labels.push(low + '-' + high);
|
1149
|
+
}
|
1150
|
+
else if (label_type === 'numeric') {
|
1151
|
+
labels.push(this.labelOptionsContainer.find('[name="label-' + i + '"]').val());
|
1152
|
+
labels_corres.push(this.labelOptionsContainer.find('[name="label-corres-' + i + '"]').val());
|
1153
|
+
}
|
1154
|
+
else
|
1155
|
+
labels.push(this.labelOptionsContainer.find('[name="label-' + i + '"]').val());
|
1156
|
+
}
|
1157
|
+
|
1158
|
+
if (label_type === 'number') {
|
1159
|
+
var plus = this.labelOptionsContainer.find('[name="plus"]:checked').val();
|
1160
|
+
if (plus === 'true')
|
1161
|
+
labels.push(this.labelOptionsContainer.find('[name="label-' + labels_num + '"]').val() + '+');
|
1162
|
+
}
|
1163
|
+
|
1164
|
+
break;
|
1165
|
+
|
1166
|
+
case 'boolean':
|
1167
|
+
chart_data['x_data']['labels'] = [true, false];
|
1168
|
+
|
1169
|
+
var true_corres = this.labelOptionsContainer.find('[name="boolean-true-corres"]').val(),
|
1170
|
+
false_corres = this.labelOptionsContainer.find('[name="boolean-false-corres"]').val();
|
1171
|
+
chart_data['x_data']['labels-corres'] = [true_corres, false_corres];
|
1172
|
+
break;
|
1173
|
+
|
1174
|
+
default:
|
1175
|
+
break;
|
1176
|
+
}
|
1177
|
+
chart_data['y_data'] = y_vals;
|
1178
|
+
chart_data['x_data']['attribute'] = x_val;
|
1179
|
+
chart_data['x_data']['from_filter'] = (split_x_axis.length === 3);
|
1180
|
+
|
1181
|
+
// Datasets Labels
|
1182
|
+
var datasets_labels = [];
|
1183
|
+
this.yContainer.find('[name="dataset-label"]').each(function() {
|
1184
|
+
datasets_labels.push($(this).val());
|
1185
|
+
});
|
1186
|
+
chart_data['datasets_labels'] = datasets_labels;
|
1187
|
+
|
1188
|
+
// Options
|
1189
|
+
chart_data['options'] = null;
|
1190
|
+
|
1191
|
+
// Types
|
1192
|
+
var main_type = this.yContainer.find('[name="main-type"]').val(), type = [];
|
1193
|
+
if (main_type === 'bar' || main_type === 'line') {
|
1194
|
+
this.yContainer.find('.type-select').each(function() {
|
1195
|
+
type.push($(this).val());
|
1196
|
+
});
|
1197
|
+
}
|
1198
|
+
else
|
1199
|
+
type.push(main_type);
|
1200
|
+
chart_data['types'] = type;
|
1201
|
+
},
|
1202
|
+
|
1203
|
+
getStyleData: function(style_options) {
|
1204
|
+
// Title
|
1205
|
+
style_options['title'] = this.styleOptionsContainer.find('[name="title"]').val();
|
1206
|
+
|
1207
|
+
// Legend
|
1208
|
+
var legend_options = style_options['legend'] = {};
|
1209
|
+
legend_options['display'] = this.styleOptionsContainer.find('[name="legend"]').is(':checked');
|
1210
|
+
legend_options['position'] = this.styleOptionsContainer.find('[name="legend-pos"]').val();
|
1211
|
+
|
1212
|
+
// Grid
|
1213
|
+
var grid_options = style_options['grid'] = {};
|
1214
|
+
grid_options['x'] = this.styleOptionsContainer.find('[name="x-grid-lines"]').is(':checked');
|
1215
|
+
grid_options['y'] = this.styleOptionsContainer.find('[name="y-grid-lines"]').is(':checked');
|
1216
|
+
|
1217
|
+
// Y Axis
|
1218
|
+
var y_axis_options = style_options['y-axis'] = {};
|
1219
|
+
y_axis_options['min'] = this.styleOptionsContainer.find('[name="y-axis-min"]').val();
|
1220
|
+
y_axis_options['max'] = this.styleOptionsContainer.find('[name="y-axis-max"]').val();
|
1221
|
+
y_axis_options['step'] = this.styleOptionsContainer.find('[name="y-axis-step"]').val();
|
1222
|
+
|
1223
|
+
// Labeling step
|
1224
|
+
style_options['labeling-step'] = this.styleOptionsContainer.find('[name="labeling-step"]').val();
|
1225
|
+
|
1226
|
+
// Stacked
|
1227
|
+
style_options['stacked'] = this.styleOptionsContainer.find('[name="stacked"]').is(':checked');
|
1228
|
+
},
|
1229
|
+
|
1230
|
+
getColorData: function(style_options) {
|
1231
|
+
// Colors
|
1232
|
+
style_options['colors'] = [];
|
1233
|
+
this.colorOptionsContainer.find('[name="dataset-color"]').each(function() {
|
1234
|
+
style_options['colors'].push($(this).val());
|
1235
|
+
});
|
1236
|
+
|
1237
|
+
// Area transparency
|
1238
|
+
style_options['transparencies'] = [];
|
1239
|
+
this.colorOptionsContainer.find('[name="transparency"]').each(function() {
|
1240
|
+
style_options['transparencies'].push($(this).val());
|
1241
|
+
});
|
1242
|
+
},
|
1243
|
+
|
1244
|
+
addDefaultFilters: function(chart_data) {
|
1245
|
+
var filters_data = chart_data['filters'] = {};
|
1246
|
+
$.each(chart_data['y_data'], function(index, model) {
|
1247
|
+
filters_data[model] = {num_records: ''};
|
1248
|
+
});
|
1249
|
+
},
|
1250
|
+
|
1251
|
+
|
1252
|
+
// --------------- Build chart from data ---------------
|
1253
|
+
buildChartFields: function(chart_data) {
|
1254
|
+
this.buildYAxes(chart_data);
|
1255
|
+
this.buildXAxis(chart_data['x_data']);
|
1256
|
+
this.buildLabelOptions(chart_data['x_data'], false);
|
1257
|
+
this.buildStyleOptions(chart_data['style']);
|
1258
|
+
this.buildColorOptions(chart_data['style']);
|
1259
|
+
},
|
1260
|
+
|
1261
|
+
buildYAxes: function(chart_data) {
|
1262
|
+
var yContainer = this.yContainer;
|
1263
|
+
yContainer.find('.remove-var-btn').click();
|
1264
|
+
|
1265
|
+
$.each(chart_data['y_data'], function(index, value) {
|
1266
|
+
if (index > 0)
|
1267
|
+
yContainer.find('#add-var-btn').click();
|
1268
|
+
|
1269
|
+
yContainer.find('.var-div:last [name="y-axis"]').focusin().val(value).change();
|
1270
|
+
yContainer.find('[name="dataset-label"]:last').val(chart_data['datasets_labels'][index]);
|
1271
|
+
|
1272
|
+
});
|
1273
|
+
|
1274
|
+
var main_type = chart_data['types'][0];
|
1275
|
+
yContainer.find('[name="main-type"]').val(main_type).change();
|
1276
|
+
if (main_type === 'bar' || main_type === 'line') {
|
1277
|
+
var idx = 1;
|
1278
|
+
yContainer.find('.type-select').not('[name="main-type"]').each(function() {
|
1279
|
+
$(this).val(chart_data['types'][idx++]);
|
1280
|
+
});
|
1281
|
+
}
|
1282
|
+
},
|
1283
|
+
|
1284
|
+
buildXAxis: function(x_data) {
|
1285
|
+
var value_string = x_data['attribute'] + '-';
|
1286
|
+
if ('sub_attribute' in x_data) {
|
1287
|
+
if (x_data['sub_attribute_from'] === 'has')
|
1288
|
+
value_string += 'has';
|
1289
|
+
else
|
1290
|
+
value_string += 'ref';
|
1291
|
+
}
|
1292
|
+
else
|
1293
|
+
value_string += x_data['type'];
|
1294
|
+
|
1295
|
+
if (x_data['from_filter'] === 'true')
|
1296
|
+
value_string += '-filter';
|
1297
|
+
|
1298
|
+
this.xContainer.find('[name="x-axis"]').focusin().val(value_string).change();
|
1299
|
+
},
|
1300
|
+
|
1301
|
+
buildLabelOptions: function(x_data, is_sub) {
|
1302
|
+
if ('sub_attribute' in x_data && !is_sub) {
|
1303
|
+
if (x_data['sub_attribute_from'] === 'has')
|
1304
|
+
this.buildHasLabelOptions(x_data);
|
1305
|
+
else
|
1306
|
+
this.buildRefLabelOptions(x_data);
|
1307
|
+
}
|
1308
|
+
|
1309
|
+
switch (x_data['type']) {
|
1310
|
+
case 'datetime':
|
1311
|
+
this.buildDatetimeLabelOptions(x_data);
|
1312
|
+
break;
|
1313
|
+
|
1314
|
+
case 'numeric':
|
1315
|
+
this.buildNumericLabelOptions(x_data);
|
1316
|
+
break;
|
1317
|
+
|
1318
|
+
case 'boolean':
|
1319
|
+
this.buildBooleanLabelOptions(x_data);
|
1320
|
+
break;
|
1321
|
+
|
1322
|
+
case 'text':
|
1323
|
+
this.buildTextLabelOptions(x_data);
|
1324
|
+
break;
|
1325
|
+
|
1326
|
+
case 'has':
|
1327
|
+
this.buildHasLabelOptions(x_data);
|
1328
|
+
break;
|
1329
|
+
|
1330
|
+
case 'ref':
|
1331
|
+
this.buildRefLabelOptions(x_data);
|
1332
|
+
break;
|
1333
|
+
|
1334
|
+
default:
|
1335
|
+
break;
|
1336
|
+
|
1337
|
+
}
|
1338
|
+
},
|
1339
|
+
|
1340
|
+
buildDatetimeLabelOptions: function(x_data) {
|
1341
|
+
var start = x_data['start'], end = x_data['end'];
|
1342
|
+
this.labelOptionsContainer.find('.daterange span').html(start + ' - ' + end);
|
1343
|
+
this.labelOptionsContainer.find('#date-range-select').val(x_data['date_range_type']).change();
|
1344
|
+
this.labelOptionsContainer.find('[name="period"][value="' + x_data['period'] + '"]').prop('checked', true);
|
1345
|
+
// $('input[name="format"]').val(x_data['format']);
|
1346
|
+
},
|
1347
|
+
|
1348
|
+
buildNumericLabelOptions: function(x_data) {
|
1349
|
+
var label_options_container = this.labelOptionsContainer;
|
1350
|
+
|
1351
|
+
var label_type = x_data['label_type'];
|
1352
|
+
|
1353
|
+
if (label_type === 'number') {
|
1354
|
+
label_options_container.find('[type="radio"][value="number"]:last').prop('checked', true).change();
|
1355
|
+
var last_idx = x_data['labels'].length - 1;
|
1356
|
+
var plus = x_data['labels'][last_idx].split('+');
|
1357
|
+
var num_labels = last_idx;
|
1358
|
+
if (plus.length === 1) num_labels++;
|
1359
|
+
|
1360
|
+
label_options_container.find('[name="labels-num"]').val(num_labels).change();
|
1361
|
+
$.each(x_data['labels'], function(index, value) {
|
1362
|
+
if (index === last_idx) return true;
|
1363
|
+
label_options_container.find('[name="label-' + index + '"]:last').val(value.split('-')[0]);
|
1364
|
+
});
|
1365
|
+
if (plus.length === 2) {
|
1366
|
+
label_options_container.find('[name="label-' + last_idx + '"]:last').val(plus[0]);
|
1367
|
+
plus = 'true';
|
1368
|
+
}
|
1369
|
+
else {
|
1370
|
+
label_options_container.find('[name="label-' + num_labels + '"]:last').val(x_data['labels'][last_idx].split('-')[1]);
|
1371
|
+
plus = 'false';
|
1372
|
+
}
|
1373
|
+
label_options_container.find('[name="plus"][value="' + plus + '"]').prop('checked', true);
|
1374
|
+
}
|
1375
|
+
else {
|
1376
|
+
$.each(x_data['labels'], function(index, value) {
|
1377
|
+
label_options_container.find('[name="label-' + (index+1) + '"]').val(value);
|
1378
|
+
label_options_container.find('[name="label-corres-' + (index+1) + '"]').val(x_data['labels-corres'][index]);
|
1379
|
+
});
|
1380
|
+
}
|
1381
|
+
},
|
1382
|
+
|
1383
|
+
buildBooleanLabelOptions: function(x_data) {
|
1384
|
+
this.labelOptionsContainer.find('[name="boolean-true-corres"]').val(x_data['labels-corres'][0]);
|
1385
|
+
this.labelOptionsContainer.find('[name="boolean-false-corres"]').val(x_data['labels-corres'][1]);
|
1386
|
+
},
|
1387
|
+
|
1388
|
+
buildTextLabelOptions: function(x_data) {
|
1389
|
+
var label_options_container = this.labelOptionsContainer;
|
1390
|
+
|
1391
|
+
var label_type = x_data['label_type'];
|
1392
|
+
if (label_type === 'text') label_options_container.find('[name="labels-type"][value="text"]').prop('checked', true).change();
|
1393
|
+
|
1394
|
+
if (label_type !== 'text-auto') {
|
1395
|
+
label_options_container.find('[name="labels-num"]').val(x_data['labels'].length).change();
|
1396
|
+
$.each(x_data['labels'], function(index, value) {
|
1397
|
+
label_options_container.find('.limit-label[name="label-' + (index+1) + '"]').val(value);
|
1398
|
+
});
|
1399
|
+
}
|
1400
|
+
},
|
1401
|
+
|
1402
|
+
buildHasLabelOptions: function(x_data) {
|
1403
|
+
var label_options_container = this.labelOptionsContainer;
|
1404
|
+
|
1405
|
+
var label_type = ('sub_attribute' in x_data) ? 'attribute' : x_data['label_type'];
|
1406
|
+
label_options_container.find('[name="labels-type"][value="' + label_type + '"]').prop('checked', true).change();
|
1407
|
+
|
1408
|
+
if (label_type === 'number') {
|
1409
|
+
var last_idx = x_data['labels'].length - 1;
|
1410
|
+
var plus = x_data['labels'][last_idx].split('+');
|
1411
|
+
var num_labels = last_idx;
|
1412
|
+
if (plus.length === 1) num_labels++;
|
1413
|
+
|
1414
|
+
label_options_container.find('[name="labels-num"]').val(num_labels).change();
|
1415
|
+
$.each(x_data['labels'], function(index, value) {
|
1416
|
+
label_options_container.find('.limit-label[name="label-' + index + '"]').val(value.split('-')[0]);
|
1417
|
+
if (index === last_idx) return true;
|
1418
|
+
});
|
1419
|
+
if (plus.length === 2) {
|
1420
|
+
label_options_container.find('.limit-label[name="label-' + last_idx + '"]').val(plus[0]);
|
1421
|
+
plus = 'true';
|
1422
|
+
}
|
1423
|
+
else {
|
1424
|
+
label_options_container.find('.limit-label[name="label-' + num_labels + '"]').val(x_data['labels'][last_idx].split('-')[1]);
|
1425
|
+
plus = 'false';
|
1426
|
+
}
|
1427
|
+
label_options_container.find('[name="plus"][value="' + plus + '"]').prop('checked', true);
|
1428
|
+
}
|
1429
|
+
else {
|
1430
|
+
var sub_attribute_string = x_data['sub_attribute'] + '-' + x_data['type'];
|
1431
|
+
label_options_container.find('[name="x-sub"]').focusin().val(sub_attribute_string).change();
|
1432
|
+
this.buildLabelOptions(x_data, true);
|
1433
|
+
}
|
1434
|
+
},
|
1435
|
+
|
1436
|
+
buildRefLabelOptions: function(x_data) {
|
1437
|
+
var label_type = ('sub_attribute' in x_data) ? 'attribute' : x_data['label_type'];
|
1438
|
+
this.labelOptionsContainer.find('[name="labels-type"][value="' + label_type + '"]').prop('checked', true).change();
|
1439
|
+
|
1440
|
+
if (label_type === 'attribute') {
|
1441
|
+
var sub_attribute_string = x_data['sub_attribute'] + '-' + x_data['type'];
|
1442
|
+
this.labelOptionsContainer.find('[name="x-sub"]').focusin().val(sub_attribute_string).change();
|
1443
|
+
this.buildLabelOptions(x_data, true);
|
1444
|
+
}
|
1445
|
+
},
|
1446
|
+
|
1447
|
+
buildStyleOptions: function(style_options) {
|
1448
|
+
// Title
|
1449
|
+
var title = style_options['title'];
|
1450
|
+
this.styleOptionsContainer.find('[name="title"]').val(title);
|
1451
|
+
|
1452
|
+
// Legend options
|
1453
|
+
var legend_options = style_options['legend'];
|
1454
|
+
this.styleOptionsContainer.find('[name="legend"]').prop('checked', legend_options['display'] === 'true');
|
1455
|
+
this.styleOptionsContainer.find('[name="legend-pos"]').val(legend_options['position']);
|
1456
|
+
|
1457
|
+
// Grid checkboxes
|
1458
|
+
var grid_options = style_options['grid'];
|
1459
|
+
this.styleOptionsContainer.find('[name="x-grid-lines"]').prop('checked', grid_options['x'] === 'true');
|
1460
|
+
this.styleOptionsContainer.find('[name="y-grid-lines"]').prop('checked', grid_options['y'] === 'true');
|
1461
|
+
|
1462
|
+
// Y Axis options
|
1463
|
+
var y_axis_options = style_options['y-axis'];
|
1464
|
+
this.styleOptionsContainer.find('[name="y-axis-min"]').val(y_axis_options['min']);
|
1465
|
+
this.styleOptionsContainer.find('[name="y-axis-max"]').val(y_axis_options['max']);
|
1466
|
+
this.styleOptionsContainer.find('[name="y-axis-step"]').val(y_axis_options['step']);
|
1467
|
+
|
1468
|
+
// Labeling step number
|
1469
|
+
this.styleOptionsContainer.find('[name="labeling-step"]').val(style_options['labeling-step']);
|
1470
|
+
|
1471
|
+
// Stacked checkbox
|
1472
|
+
var stacked = style_options['stacked'] === 'true';
|
1473
|
+
this.styleOptionsContainer.find('[name="stacked"]').prop('checked', stacked);
|
1474
|
+
},
|
1475
|
+
|
1476
|
+
buildColorOptions: function(style_options) {
|
1477
|
+
// Colors
|
1478
|
+
var colors = style_options['colors'], i = 0;
|
1479
|
+
this.colorOptionsContainer.find('[name="dataset-color"]').each(function() {
|
1480
|
+
$(this).val(colors[i]);
|
1481
|
+
$(this).parent().find('.minicolors-input-swatch .minicolors-swatch-color').css("background-color", colors[i++]);
|
1482
|
+
});
|
1483
|
+
|
1484
|
+
// Transparencies
|
1485
|
+
var transparencies = style_options['transparencies'];
|
1486
|
+
i = 0;
|
1487
|
+
this.colorOptionsContainer.find('[name="transparency"]').each(function() {
|
1488
|
+
$(this).val(transparencies[i++]);
|
1489
|
+
});
|
1490
|
+
},
|
1491
|
+
|
1492
|
+
|
1493
|
+
// --------------- Color callback ---------------
|
1494
|
+
colorCallback: function() {
|
1495
|
+
var labels_num_input = this.labelOptionsContainer.find('[name="labels-num"]'),
|
1496
|
+
main_var_color_divs = this.colorOptionsContainer.find('.color-div[data-id="0"]'),
|
1497
|
+
x_is_boolean = this.labelOptionsContainer.find('[name="boolean-true"]').length !== 0;
|
1498
|
+
|
1499
|
+
var main_type = this.yContainer.find('[name="main-type"]').val();
|
1500
|
+
|
1501
|
+
// No colors if no labels_num (in no boolean case) or if type 1 chart
|
1502
|
+
if ((labels_num_input.length === 0 && !x_is_boolean) || main_type === 'bar' || main_type === 'line') {
|
1503
|
+
main_var_color_divs.not('#main-color').remove();
|
1504
|
+
}
|
1505
|
+
// Right number of colors for type 2 chart
|
1506
|
+
else {
|
1507
|
+
var color_number = x_is_boolean ? 2 : parseInt(labels_num_input.val()), // 2 colors if x is boolean
|
1508
|
+
previous_color_number = parseInt(main_var_color_divs.length);
|
1509
|
+
var adapt_to_label_type = 0;
|
1510
|
+
if ((this.labelOptionsContainer.find('[name="labels-type"][value="number"]').is(':checked')
|
1511
|
+
|| this.labelOptionsContainer.find('[name="sub-labels-type"][value="number"]').is(':checked'))
|
1512
|
+
&& this.labelOptionsContainer.find('[name="plus"][value="true"]').is(':checked')) {
|
1513
|
+
adapt_to_label_type = 1;
|
1514
|
+
}
|
1515
|
+
|
1516
|
+
if (color_number >= previous_color_number) {
|
1517
|
+
for (var i = previous_color_number; i < color_number + adapt_to_label_type; i++) {
|
1518
|
+
this.addColorToCreator(0, i + 1);
|
1519
|
+
}
|
1520
|
+
}
|
1521
|
+
else {
|
1522
|
+
for (var i = previous_color_number - adapt_to_label_type; i > color_number; i--) {
|
1523
|
+
this.colorOptionsContainer.find('.color-div[data-id="0"]:last').remove();
|
1524
|
+
}
|
1525
|
+
}
|
1526
|
+
}
|
1527
|
+
}
|
1528
|
+
|
1529
|
+
};
|
1530
|
+
|
1531
|
+
$.fn.chartCreator = function(options, callback) {
|
1532
|
+
this.each(function(i, _element) {
|
1533
|
+
var el = $(_element);
|
1534
|
+
if (el.data('chartCreator'))
|
1535
|
+
el.data('chartCreator').remove();
|
1536
|
+
el.data('chartCreator', new ChartCreator(el, options, callback));
|
1537
|
+
});
|
1538
|
+
return this;
|
1539
|
+
};
|
1540
|
+
|
1541
|
+
// Creates a daterange field for datetime label options
|
1542
|
+
function daterangeField(parent_div) {
|
1543
|
+
// Append (empty) daterangepicker
|
1544
|
+
var daterange_input_string = '<label>In range</label>'
|
1545
|
+
+ '<div id="daterange-chart" class="daterange" style="background: #fff; cursor: pointer; padding: 5px 10px; border: 1px solid #ccc; width: 100%">'
|
1546
|
+
+ '<i class="glyphicon glyphicon-calendar fa fa-calendar"></i> '
|
1547
|
+
+ '<span class="daterange-value"></span>'
|
1548
|
+
+ '<b class="caret"></b>'
|
1549
|
+
+ '</div>';
|
1550
|
+
var daterange_input = $(daterange_input_string).appendTo(parent_div);
|
1551
|
+
|
1552
|
+
// Customize daterangepicker
|
1553
|
+
$(function() {
|
1554
|
+
// Default start, end
|
1555
|
+
var start = moment().subtract(29, 'days');
|
1556
|
+
var end = moment();
|
1557
|
+
|
1558
|
+
// Change date format
|
1559
|
+
function cb(start, end) {
|
1560
|
+
parent_div.find('#daterange-chart span').html(start.format('MMMM D, YYYY') + ' - ' + end.format('MMMM D, YYYY'));
|
1561
|
+
}
|
1562
|
+
|
1563
|
+
// Set as daterangepicker with different defaults
|
1564
|
+
daterange_input.daterangepicker({
|
1565
|
+
startDate: start,
|
1566
|
+
endDate: end,
|
1567
|
+
ranges: {
|
1568
|
+
'Today': [moment(), moment()],
|
1569
|
+
'Yesterday': [moment().subtract(1, 'days'), moment().subtract(1, 'days')],
|
1570
|
+
'Last 7 Days': [moment().subtract(6, 'days'), moment()],
|
1571
|
+
'Last 30 Days': [moment().subtract(29, 'days'), moment()],
|
1572
|
+
'This Month': [moment().startOf('month'), moment().endOf('month')],
|
1573
|
+
'Last Month': [moment().subtract(1, 'month').startOf('month'), moment().subtract(1, 'month').endOf('month')]
|
1574
|
+
}
|
1575
|
+
}, cb);
|
1576
|
+
|
1577
|
+
cb(start, end);
|
1578
|
+
});
|
1579
|
+
}
|
1580
|
+
|
1581
|
+
return ChartCreator;
|
1582
|
+
});
|