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.
Files changed (96) hide show
  1. checksums.yaml +7 -0
  2. data/MIT-LICENSE +20 -0
  3. data/README.md +170 -0
  4. data/Rakefile +36 -0
  5. data/app/assets/config/dash_creator_manifest.js +2 -0
  6. data/app/assets/javascripts/dash_creator/application.js +24 -0
  7. data/app/assets/javascripts/dash_creator/chart.js +2 -0
  8. data/app/assets/javascripts/dash_creator/dashboard.js +2 -0
  9. data/app/assets/javascripts/dash_creator/dashboard_object.js +2 -0
  10. data/app/assets/javascripts/dash_creator/filter.js +2 -0
  11. data/app/assets/javascripts/dash_creator/libs/Chart.js +12269 -0
  12. data/app/assets/javascripts/dash_creator/libs/bootstrap.js +3535 -0
  13. data/app/assets/javascripts/dash_creator/libs/chartCreator.js +1582 -0
  14. data/app/assets/javascripts/dash_creator/libs/dashboardCreator.js +531 -0
  15. data/app/assets/javascripts/dash_creator/libs/daterangepicker.js +1626 -0
  16. data/app/assets/javascripts/dash_creator/libs/filterCreator.js +733 -0
  17. data/app/assets/javascripts/dash_creator/libs/jquery-ui.js +18706 -0
  18. data/app/assets/javascripts/dash_creator/libs/jquery.minicolors.js +1108 -0
  19. data/app/assets/javascripts/dash_creator/libs/moment.js +4301 -0
  20. data/app/assets/javascripts/dash_creator/libs/tether.js +1811 -0
  21. data/app/assets/javascripts/dash_creator/user.js +2 -0
  22. data/app/assets/stylesheets/dash_creator/application.css +16 -0
  23. data/app/assets/stylesheets/dash_creator/chart.css +4 -0
  24. data/app/assets/stylesheets/dash_creator/dashboard.css +4 -0
  25. data/app/assets/stylesheets/dash_creator/dashboard_object.css +4 -0
  26. data/app/assets/stylesheets/dash_creator/filter.css +4 -0
  27. data/app/assets/stylesheets/dash_creator/fonts/FontAwesome.otf +0 -0
  28. data/app/assets/stylesheets/dash_creator/fonts/fontawesome-webfont.eot +0 -0
  29. data/app/assets/stylesheets/dash_creator/fonts/fontawesome-webfont.svg +2671 -0
  30. data/app/assets/stylesheets/dash_creator/fonts/fontawesome-webfont.ttf +0 -0
  31. data/app/assets/stylesheets/dash_creator/fonts/fontawesome-webfont.woff +0 -0
  32. data/app/assets/stylesheets/dash_creator/fonts/fontawesome-webfont.woff2 +0 -0
  33. data/app/assets/stylesheets/dash_creator/libs/font-awesome.css +2199 -0
  34. data/app/assets/stylesheets/dash_creator/libs/jquery.minicolors.css +319 -0
  35. data/app/assets/stylesheets/dash_creator/libs/jquery.minicolors.png +0 -0
  36. data/app/assets/stylesheets/dash_creator/libs/style.css +13714 -0
  37. data/app/assets/stylesheets/dash_creator/user.css +4 -0
  38. data/app/controllers/dash_creator/application_controller.rb +3 -0
  39. data/app/controllers/dash_creator/chart_controller.rb +81 -0
  40. data/app/controllers/dash_creator/dashboard_controller.rb +37 -0
  41. data/app/controllers/dash_creator/dashboard_object_controller.rb +34 -0
  42. data/app/controllers/dash_creator/filter_controller.rb +60 -0
  43. data/app/controllers/dash_creator/user_controller.rb +82 -0
  44. data/app/helpers/dash_creator/application_helper.rb +4 -0
  45. data/app/helpers/dash_creator/chart_helper.rb +829 -0
  46. data/app/helpers/dash_creator/dashboard_helper.rb +4 -0
  47. data/app/helpers/dash_creator/dashboard_object_helper.rb +4 -0
  48. data/app/helpers/dash_creator/filter_helper.rb +237 -0
  49. data/app/helpers/dash_creator/user_helper.rb +4 -0
  50. data/app/jobs/dash_creator/application_job.rb +4 -0
  51. data/app/mailers/dash_creator/application_mailer.rb +6 -0
  52. data/app/models/dash_creator/application_record.rb +5 -0
  53. data/app/models/dash_creator/chart.rb +21 -0
  54. data/app/models/dash_creator/dashboard.rb +13 -0
  55. data/app/models/dash_creator/dashboard_object.rb +7 -0
  56. data/app/models/dash_creator/filter.rb +22 -0
  57. data/app/views/dash_creator/chart/_chart_creator.html.erb +230 -0
  58. data/app/views/dash_creator/chart/_modals.html.erb +74 -0
  59. data/app/views/dash_creator/chart/_plot_chart.html.erb +45 -0
  60. data/app/views/dash_creator/chart/create_chart.js.erb +53 -0
  61. data/app/views/dash_creator/dashboard/_dashboard_creator.html.erb +182 -0
  62. data/app/views/dash_creator/dashboard/_modals.html.erb +74 -0
  63. data/app/views/dash_creator/dashboard_object/_chart.html.erb +9 -0
  64. data/app/views/dash_creator/dashboard_object/_stat.html.erb +24 -0
  65. data/app/views/dash_creator/dashboard_object/_table.html.erb +16 -0
  66. data/app/views/dash_creator/filter/_filtering_card.html.erb +132 -0
  67. data/app/views/dash_creator/filter/_modals.html.erb +51 -0
  68. data/app/views/dash_creator/filter/_result_tables.html.erb +55 -0
  69. data/app/views/dash_creator/filter/apply_filtering.js.erb +46 -0
  70. data/app/views/dash_creator/filter/create_stat.js.erb +20 -0
  71. data/app/views/dash_creator/layouts/application.html.erb +64 -0
  72. data/app/views/dash_creator/layouts/menu/_left_menu.html.erb +12 -0
  73. data/app/views/dash_creator/user/_section_card.html.erb +17 -0
  74. data/app/views/dash_creator/user/creator.html.erb +11 -0
  75. data/app/views/dash_creator/user/dashboard.html.erb +10 -0
  76. data/config/initializers/dash_creator.rb +0 -0
  77. data/config/routes.rb +30 -0
  78. data/lib/dash_creator.rb +87 -0
  79. data/lib/dash_creator/acts_as_dash_creator.rb +16 -0
  80. data/lib/dash_creator/acts_as_dashboard_object.rb +19 -0
  81. data/lib/dash_creator/engine.rb +11 -0
  82. data/lib/dash_creator/version.rb +3 -0
  83. data/lib/generators/dash_creator/install/install_generator.rb +70 -0
  84. data/lib/generators/dash_creator/install/templates/_chart.html.erb +9 -0
  85. data/lib/generators/dash_creator/install/templates/_section_card.html.erb +17 -0
  86. data/lib/generators/dash_creator/install/templates/_stat.html.erb +24 -0
  87. data/lib/generators/dash_creator/install/templates/_table.html.erb +16 -0
  88. data/lib/generators/dash_creator/install/templates/add_indexes_to_dash_creator_tables.rb +15 -0
  89. data/lib/generators/dash_creator/install/templates/create_dash_creator_charts.rb +25 -0
  90. data/lib/generators/dash_creator/install/templates/create_dash_creator_dashboard_objects.rb +36 -0
  91. data/lib/generators/dash_creator/install/templates/create_dash_creator_dashboards.rb +28 -0
  92. data/lib/generators/dash_creator/install/templates/create_dash_creator_filters.rb +22 -0
  93. data/lib/generators/dash_creator/install/templates/dashboard.html.erb +10 -0
  94. data/lib/generators/dash_creator/install/templates/initializer.rb +48 -0
  95. data/lib/tasks/dash_creator_tasks.rake +4 -0
  96. metadata +196 -0
@@ -0,0 +1,531 @@
1
+ /*!
2
+ * Dashboard Creator v1.0
3
+ * 2017 Elie Oriol
4
+ */
5
+
6
+ (function(factory) {
7
+ if (typeof define === 'function' && define.amd) {
8
+ define([ 'jquery' ], factory);
9
+ }
10
+ else if (typeof exports === 'object') { // Node/CommonJS
11
+ module.exports = factory(require('jquery'));
12
+ }
13
+ else {
14
+ factory(jQuery);
15
+ }
16
+ })(function($) {
17
+ var DashboardCreator = function(element, options, callback) {
18
+ this.parentEl = $(element);
19
+
20
+ // Objects data format:
21
+ // 'object.code': {
22
+ // 'related_model': object.related_model,
23
+ // 'name': object.name,
24
+ // 'objects': [model_objects]
25
+ // }
26
+
27
+ // Model object format:
28
+ // {
29
+ // 'id': object.id,
30
+ // 'name': object.name
31
+ // }
32
+
33
+ if (typeof options !== 'object' || options === null)
34
+ options = {};
35
+
36
+ this.objects_data = typeof options.objects_data === 'object' ? options.objects_data : {};
37
+
38
+ this.callback = (typeof callback === 'function') ? callback : function() { };
39
+
40
+ if (typeof options.template !== 'string' && !(options.template instanceof $)) {
41
+ options.template = '<div class="row">' +
42
+ '<div class="col-md-12 px-2" style="background-color: #eee; border-radius: 10px; padding: 20px 10px;">' +
43
+ '<h3>Dashboard Preview</h3>' +
44
+ '<div class="row" id="dashboard-preview" style="margin: 30px; padding: 20px; border: 1px dashed black; border-radius: 10px;">' +
45
+ '</div>' +
46
+ '</div>' +
47
+ '<div class="col-md-12 px-2">' +
48
+ '<div class="row" id="sections-container">' +
49
+ '<div class="col-sm-12" style="margin-top:50px;" id="add-section-btn-container">' +
50
+ '<button id="add-section-btn" class="btn btn-primary">+</button>' +
51
+ '</div>' +
52
+ '</div>' +
53
+ '</div>' +
54
+ '</div>';
55
+ }
56
+
57
+ this.container = $(options.template).appendTo(this.parentEl);
58
+ this.sections_container = this.container.find('div#sections-container');
59
+ this.dashboard_preview = this.container.find('div#dashboard-preview');
60
+
61
+ this.sections_container
62
+ .on('click', '#add-section-btn', $.proxy(this.addSection, this))
63
+ .on('click', '.remove-section-btn', $.proxy(this.removeSection, this))
64
+ .on('change', 'input[name="section-name"]', $.proxy(this.changeSectionName, this))
65
+ .on('click', '.add-object-btn', $.proxy(this.addObject, this))
66
+ .on('click', '.remove-object-btn', $.proxy(this.removeObject, this))
67
+ .on('change', 'select[name="object_type"]', $.proxy(this.displayObjectSelect, this))
68
+ .on('blur', 'select[name="object_select"]', $.proxy(this.selectObjectResponse, this))
69
+ .on('change', 'select[name="object_select"]', $.proxy(this.selectObjectResponse, this));
70
+
71
+ this.dashboard_preview
72
+ .on('change', 'input[name="section-size"]', $.proxy(this.changeSectionSize, this))
73
+ .on('change', 'input[name="section-offset"]', $.proxy(this.changeSectionOffset, this))
74
+ .on('change', 'input[name="object-size"]', $.proxy(this.changeObjectSize, this))
75
+ .on('change', 'input[name="object-offset"]', $.proxy(this.changeObjectOffset, this))
76
+ // Event 'build' to avoid wrong dashboard display
77
+ .on('build', 'input[name="section-size"]', $.proxy(this.changeSectionSize, this))
78
+ .on('build', 'input[name="section-offset"]', $.proxy(this.changeSectionOffset, this))
79
+ .on('build', 'input[name="object-size"]', $.proxy(this.changeObjectSize, this))
80
+ .on('build', 'input[name="object-offset"]', $.proxy(this.changeObjectOffset, this));
81
+ };
82
+
83
+ DashboardCreator.prototype = {
84
+
85
+ constructor: DashboardCreator,
86
+
87
+ // --------------- Sections handling ---------------
88
+ // Add section
89
+ addSection: function() {
90
+ var last_section = this.sections_container.find('.section:last');
91
+ var section_id = last_section.length === 0 ? 1 : parseInt(last_section.attr('data-section-id')) + 1;
92
+
93
+ this.addCreatorSection(section_id);
94
+ this.addPreviewSection(section_id);
95
+ },
96
+
97
+ // Add section to creator
98
+ addCreatorSection: function(section_id) {
99
+ var section_string = '<div class="col-sm-12 section" data-section-id="' + section_id + '" style="margin-top: 50px;">'
100
+ + '<div class="row">'
101
+ + '<div class="col-sm-1">'
102
+ + '<button type="button" class="close remove-section-btn" aria-label="Close">'
103
+ + '<span aria-hidden="true">×</span>'
104
+ + '</button>'
105
+ + '</div>'
106
+ + '<div class="col-sm-2">'
107
+ + '<h5 class="section-name">Section ' + section_id + '</h5>'
108
+ + '</div>'
109
+ + '<div class="form-group col-sm-9">'
110
+ + '<input type="text" name="section-name" value="Section ' + section_id + '" class="form-control">'
111
+ + '</div>'
112
+ + '<div class="col-sm-11 offset-sm-1">'
113
+ + '<ul class="section-objects-list"></ul>'
114
+ + '<button class="btn-sm btn-primary add-object-btn">+</button>'
115
+ + '</div></div></div>';
116
+
117
+ $(section_string).appendTo(this.sections_container);
118
+ },
119
+
120
+ // Add section to preview
121
+ addPreviewSection: function(section_id) {
122
+ var preview_section_string = '<div class="col-sm-12 preview-section" data-section-id="' + section_id + '" style="padding: 20px; overflow: auto;">'
123
+ + '<div style="padding: 15px 30px; background-color: #2d8ac7; border: 1px solid #0e6498; border-radius: 5px;">'
124
+ + '<div class="row" style="margin-bottom: 20px;">'
125
+ + '<div class="col-sm-6">'
126
+ + '<h5 class="section-name">Section ' + section_id + '</h5>'
127
+ + '</div>'
128
+ + '<div class="col-sm-3">'
129
+ + '<input type="number" name="section-size" min="1" max="12" step="1" value="12" class="form-control">'
130
+ + '</div>'
131
+ + '<div class="col-sm-3">'
132
+ + '<input type="number" name="section-offset" min="0" max="11" step="1" value="0" class="form-control">'
133
+ + '</div></div>'
134
+ + '<div class="row preview-objects-container"></div>'
135
+ + '</div></div>';
136
+
137
+ $(preview_section_string).appendTo(this.dashboard_preview);
138
+ },
139
+
140
+ removeSection: function(e) {
141
+ var target = $(e.target);
142
+
143
+ var section_id = target.closest('.section').attr("data-section-id");
144
+ this.removeCreatorSection(section_id);
145
+ this.removePreviewSection(section_id);
146
+ },
147
+
148
+ // Remove section from creator
149
+ removeCreatorSection: function(section_id) {
150
+ this.sections_container.find('.section[data-section-id="' + section_id + '"]').remove();
151
+ },
152
+
153
+ // Remove section from preview
154
+ removePreviewSection: function(section_id) {
155
+ this.dashboard_preview.find('.preview-section[data-section-id="' + section_id + '"]').remove();
156
+ },
157
+
158
+ changeSectionName: function(e) {
159
+ var target = $(e.target);
160
+
161
+ var section_id = target.closest('.section').attr('data-section-id');
162
+ var preview_section = this.dashboard_preview.find('.preview-section[data-section-id="' + section_id + '"]');
163
+ var section_name = target.val();
164
+ preview_section.find('.section-name').text(section_name);
165
+ },
166
+
167
+
168
+ // --------------- Objects handling ---------------
169
+ // Add an object to section
170
+ addObject: function(e) {
171
+ var target = $(e.target);
172
+
173
+ var objects_list = target.siblings('.section-objects-list');
174
+ var section_id = target.closest('.section').attr("data-section-id");
175
+
176
+ var last_object = objects_list.find('.object:last');
177
+ var new_object_id = last_object.length === 0 ? 1 : parseInt(last_object.attr("data-id")) + 1;
178
+
179
+ var object_string = '<li class="object" data-section-id="' + section_id + '" data-id="' + new_object_id + '">'
180
+ + '<div class="row">'
181
+ + '<div class="col-sm-1">'
182
+ + '<button type="button" class="close remove-object-btn" aria-label="Close">'
183
+ + '<span aria-hidden="true">×</span>'
184
+ + '</button>'
185
+ + '</div>'
186
+ + '<div class="form-group col-sm-5">'
187
+ + '<select name="object_type" class="form-control"></select>'
188
+ + '</div>'
189
+ + '<div class="form-group col-sm-5 offset-sm-1 select-object">'
190
+ + '</div>'
191
+ + '</div></li>';
192
+
193
+ var li_object = $(object_string).appendTo(objects_list);
194
+
195
+ var options_string = '<option value="">Choose object type</option>';
196
+ $.each(this.objects_data, function(type, data) {
197
+ var name = data['name'];
198
+ options_string += '<option value="' + type + '">' + name + '</option>';
199
+ });
200
+
201
+ $(options_string).appendTo(li_object.find('[name="object_type"]'));
202
+ },
203
+
204
+ // Remove an object from section
205
+ removeObject: function(e) {
206
+ var target = $(e.target);
207
+
208
+ // Remove from creator and preview
209
+ var object_div = target.closest('.object');
210
+ var section_id = object_div.attr("data-section-id"), object_id = object_div.attr("data-id");
211
+ var preview_object = this.dashboard_preview.find('.preview-object[data-section-id="' + section_id + '"][data-id="' + object_id + '"]');
212
+ object_div.remove();
213
+ preview_object.remove();
214
+ },
215
+
216
+ // Display select according to object type selected
217
+ displayObjectSelect: function(e) {
218
+ var target = $(e.target);
219
+
220
+ // Remove select if already one
221
+ var select_object_div = target.closest('.object').find('.select-object');
222
+ select_object_div.children().remove();
223
+
224
+ // Return if type is empty (value of select prompt)
225
+ var object_type = target.val();
226
+ if (object_type === '') return;
227
+
228
+ // Retrieve object type info
229
+ var object_model_name = this.objects_data[object_type]['related_model'];
230
+
231
+ // Add select if associated to model
232
+ if (object_model_name !== '') {
233
+ var select_string = '<select name="object_select" class="form-control">'
234
+ + '<option value="">Choose a ' + object_type + '</option>'
235
+ + '</select>';
236
+
237
+ var select = $(select_string).appendTo(select_object_div);
238
+
239
+ // Add options to select
240
+ var objects = this.objects_data[object_type]['objects'];
241
+ var options_string = '';
242
+ for (var i = 0; i < objects.length; i++) {
243
+ var name = objects[i]['name'], id = objects[i]['id'];
244
+ options_string += '<option value="' + id + '">' + name + '</option>';
245
+ }
246
+
247
+ $(options_string).appendTo(select);
248
+ }
249
+ },
250
+
251
+ // Respond to object select change
252
+ selectObjectResponse: function(e) {
253
+ var target = $(e.target);
254
+
255
+ var option_value = target.val();
256
+
257
+ var object_div = target.closest('.object');
258
+ var id = object_div.attr("data-id"), section_id = object_div.attr("data-section-id");
259
+
260
+ if (option_value === '') return this.removeObjectPreview(id, section_id);
261
+
262
+ this.addObjectPreview(id, section_id);
263
+ },
264
+
265
+ // Add object to preview
266
+ addObjectPreview: function(id, section_id) {
267
+ var object_div = this.sections_container.find('[data-id="' + id + '"][data-section-id="' + section_id + '"]');
268
+ var object_type = object_div.find('[name="object_type"] option:selected').text();
269
+ var object_name = object_div.find('[name="object_select"] option:selected').text();
270
+
271
+ var object_preview_string = '<div class="col-sm-6 preview-object" data-section-id="' + section_id + '" data-id="' + id + '" style="padding: 20px;">'
272
+ + '<div class="row" style="height: 100px; padding: 10px; background-color: #00bf8f; border: 1px solid #00a67c; border-radius: 5px;">'
273
+ + '<div class="col-sm-12" style="margin-bottom: 10px;">'
274
+ + '<strong>' + object_type + ' ' + object_name + '</strong>'
275
+ + '</div>'
276
+ + '<div class="col-sm-6">'
277
+ + '<input type="number" name="object-size" min="1" max="12" step="1" value="6" class="form-control">'
278
+ + '</div>'
279
+ + '<div class="col-sm-6">'
280
+ + '<input type="number" name="object-offset" min="0" max="11" step="1" value="0" class="form-control">'
281
+ + '</div></div></div>';
282
+
283
+ var preview_objects_container = this.dashboard_preview.find('.preview-section[data-section-id="' + section_id + '"] .preview-objects-container');
284
+ var preview_section_objects = preview_objects_container.find('.preview-object');
285
+
286
+ if (preview_section_objects.length === 0) return $(object_preview_string).appendTo(preview_objects_container);
287
+ if (preview_objects_container.find('.preview-object[data-id="' + id +'"]').length !== 0) return;
288
+
289
+ var to_append = true;
290
+ preview_section_objects.each(function() {
291
+ if (parseInt($(this).attr("data-id")) > id) {
292
+ to_append = false;
293
+ return $(object_preview_string).insertBefore($(this));
294
+ }
295
+ });
296
+ if (to_append) $(object_preview_string).appendTo(preview_objects_container);
297
+ },
298
+
299
+ // Remove object from preview
300
+ removeObjectPreview: function(id, section_id) {
301
+ this.dashboard_preview.find('[data-id="' + id + '"][data-section-id="' + section_id + '"]').remove();
302
+ },
303
+
304
+ // Change section preview on size change
305
+ changeSectionSize: function(e) {
306
+ var target = $(e.target);
307
+
308
+ var size = target.val();
309
+ var preview_section = target.closest('.preview-section');
310
+
311
+ var new_class = 'col-sm-' + size, old_class = 'col-sm-12';
312
+
313
+ $.each(preview_section.attr("class").split(' '), function(index, c) {
314
+ if (c.indexOf('col-sm-') !== -1)
315
+ return old_class = c;
316
+ });
317
+
318
+ if (new_class !== old_class) {
319
+ var duration = e.type === 'change' ? 400 : 0;
320
+ preview_section.switchClass(old_class, new_class, duration);
321
+ }
322
+ },
323
+
324
+ // Change section preview on offset change
325
+ changeSectionOffset: function(e) {
326
+ var target = $(e.target);
327
+
328
+ var offset = target.val();
329
+ var preview_section = target.closest('.preview-section');
330
+
331
+ var new_class = 'offset-sm-' + offset, old_class = '';
332
+
333
+ $.each(preview_section.attr("class").split(' '), function(index, c) {
334
+ if (c.indexOf('offset-sm-') !== -1)
335
+ return old_class = c;
336
+ });
337
+
338
+ if (new_class !== old_class) {
339
+ var duration = e.type === 'change' ? 400 : 0;
340
+ preview_section.switchClass(old_class, new_class, duration);
341
+ }
342
+ },
343
+
344
+ // Change object preview on size change
345
+ changeObjectSize: function(e) {
346
+ var target = $(e.target);
347
+
348
+ var size = target.val();
349
+ var preview_object = target.closest('.preview-object');
350
+
351
+ var new_class = 'col-sm-' + size, old_class = 'col-sm-6';
352
+
353
+ $.each(preview_object.attr("class").split(' '), function(index, c) {
354
+ if (c.indexOf('col-sm-') !== -1)
355
+ return old_class = c;
356
+ });
357
+
358
+ if (new_class !== old_class) {
359
+ var duration = e.type === 'change' ? 400 : 0;
360
+ preview_object.switchClass(old_class, new_class, duration);
361
+ }
362
+ },
363
+
364
+ // Change object preview on offset change
365
+ changeObjectOffset: function(e) {
366
+ var target = $(e.target);
367
+
368
+ var offset = target.val();
369
+ var preview_object = target.closest('.preview-object');
370
+
371
+ var new_class = 'offset-sm-' + offset, old_class = '';
372
+
373
+ $.each(preview_object.attr("class").split(' '), function(index, c) {
374
+ if (c.indexOf('offset-sm-') !== -1)
375
+ return old_class = c;
376
+ });
377
+
378
+ if (new_class !== old_class) {
379
+ var duration = e.type === 'change' ? 400 : 0;
380
+ preview_object.switchClass(old_class, new_class, duration);
381
+ }
382
+ },
383
+
384
+
385
+ // --------------- Prepare data ---------------
386
+ // Get the dashboard data
387
+ getDashboardData: function() {
388
+ var dashboard_data = [];
389
+ this.getSectionsData(dashboard_data);
390
+
391
+ return JSON.parse(JSON.stringify(dashboard_data));
392
+ },
393
+
394
+ // Get sections data
395
+ getSectionsData: function(dashboard_data) {
396
+ var creator = this;
397
+ creator.sections_container.find('.section').each(function() {
398
+ var section_data = dashboard_data[dashboard_data.push({}) - 1];
399
+ creator.getSectionData(section_data, $(this));
400
+ });
401
+ },
402
+
403
+ // Get a section data
404
+ getSectionData: function(section_data, section_div) {
405
+ // Get size & offset in preview
406
+ var section_id = section_div.attr("data-section-id");
407
+ var preview_section = this.dashboard_preview.find('.preview-section[data-section-id="' + section_id + '"]');
408
+ var section_size = preview_section.find('[name="section-size"]').val();
409
+ var section_offset = preview_section.find('[name="section-offset"]').val();
410
+
411
+ // Get name
412
+ var section_name = section_div.find('[name="section-name"]').val();
413
+
414
+ // Fill section data in hash
415
+
416
+ section_data['name'] = section_name;
417
+ section_data['size'] = section_size;
418
+ section_data['offset'] = section_offset;
419
+ section_data['objects'] = [];
420
+
421
+ // Add objects
422
+ var objects_list = section_div.find('.section-objects-list');
423
+ this.getObjectsData(section_data['objects'], objects_list);
424
+ },
425
+
426
+ // Get objects data of a section
427
+ getObjectsData: function(objects_data, objects_list) {
428
+ var creator = this;
429
+ objects_list.find('.object').each(function() {
430
+ var object_data = objects_data[objects_data.push({}) - 1];
431
+ creator.getObjectData(object_data, $(this));
432
+ });
433
+ },
434
+
435
+ // Get an object data
436
+ getObjectData: function(object_data, object_div) {
437
+ // Get object type and return if empty (don't add to hash)
438
+ var type = object_div.find('[name="object_type"]').val();
439
+ if (type === '') return true;
440
+
441
+ // Get size & offset in preview
442
+ var object_id = object_div.attr("data-id"), section_id = object_div.attr("data-section-id");
443
+ var preview_object = this.dashboard_preview.find('.preview-object[data-section-id="' + section_id + '"][data-id="' + object_id + '"]');
444
+ var object_size = preview_object.find('[name="object-size"]').val();
445
+ var object_offset = preview_object.find('[name="object-offset"]').val();
446
+
447
+ // Fill object data in hash
448
+
449
+ object_data['type'] = type;
450
+ object_data['size'] = object_size;
451
+ object_data['offset'] = object_offset;
452
+
453
+ var object_select = object_div.find('[name="object_select"]');
454
+ if (object_select.length !== 0) object_data['id'] = object_select.val();
455
+ },
456
+
457
+
458
+ // --------------- Build dashboard from data ---------------
459
+ // Build dashboard from data
460
+ buildDashboard: function(dashboard_data) {
461
+ this.sections_container.children().not('#add-section-btn-container').remove();
462
+ this.dashboard_preview.children().remove();
463
+
464
+ this.buildSections(dashboard_data);
465
+ },
466
+
467
+ // Build sections from data
468
+ buildSections: function(dashboard_data) {
469
+ var creator = this;
470
+ // For each section data in dashboard data
471
+ $.each(dashboard_data, function(index, section_data) {
472
+ creator.buildSection(section_data);
473
+ });
474
+ },
475
+
476
+ // Build a section from data
477
+ buildSection: function(section_data) {
478
+ // Add new section
479
+ this.sections_container.find('#add-section-btn').click();
480
+
481
+ // Fill section name, size & offset
482
+ this.sections_container.find('[name="section-name"]:last').val(section_data['name']);
483
+ this.dashboard_preview.find('[name="section-size"]:last').val(section_data['size']).trigger('build');
484
+ this.dashboard_preview.find('[name="section-offset"]:last').val(section_data['offset']).trigger('build');
485
+
486
+ // Rebuild objects of section
487
+ this.buildObjects(section_data['objects']);
488
+ },
489
+
490
+ // Build objects of a section from data
491
+ buildObjects: function(objects_data) {
492
+ var creator = this;
493
+ // For each object data in objects array
494
+ $.each(objects_data, function(index, object_data) {
495
+ creator.buildObject(object_data);
496
+ });
497
+ },
498
+
499
+ // Build an object from data
500
+ buildObject: function(object_data) {
501
+ // Add new object to section
502
+ this.sections_container.find('.add-object-btn:last').click();
503
+
504
+ // Fill object type
505
+ var type = object_data['type'];
506
+ this.sections_container.find('[name="object_type"]:last').val(type).change();
507
+
508
+ // Select object
509
+ var object_select = this.sections_container.find('[name="object_select"]:last');
510
+ if (object_select.length !== 0) object_select.val(object_data['id']).change();
511
+
512
+ // Fill object size & offset
513
+ this.dashboard_preview.find('[name="object-size"]:last').val(object_data['size']).trigger('build');
514
+ this.dashboard_preview.find('[name="object-offset"]:last').val(object_data['offset']).trigger('build');
515
+ }
516
+
517
+ };
518
+
519
+ $.fn.dashboardCreator = function(options, callback) {
520
+ this.each(function(i, _element) {
521
+ var el = $(_element);
522
+ if (el.data('dashboardCreator'))
523
+ el.data('dashboardCreator').remove();
524
+ el.data('dashboardCreator', new DashboardCreator(el, options, callback));
525
+ });
526
+ return this;
527
+ };
528
+
529
+ return DashboardCreator;
530
+ });
531
+