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,4 @@
1
+ module DashCreator
2
+ module DashboardHelper
3
+ end
4
+ end
@@ -0,0 +1,4 @@
1
+ module DashCreator
2
+ module DashboardObjectHelper
3
+ end
4
+ end
@@ -0,0 +1,237 @@
1
+ module DashCreator
2
+ module FilterHelper
3
+ def filter_data(data)
4
+ mods = {}
5
+ data.keys.each do |k|
6
+ filter_hash = data[k]
7
+
8
+ mods[k] = filter_model(k.safe_constantize, filter_hash)
9
+ end
10
+
11
+ mods
12
+ end
13
+
14
+ def prepare_data(params)
15
+ mods = filter_data(params['filters'])
16
+
17
+ data = params
18
+
19
+ data['y_data'] = data['y_data'].map { |d| mods[d] }
20
+
21
+ x_model_data = mods[data['x_data']['attribute']]
22
+ data['x_data'] = x_model_data unless x_model_data.nil?
23
+
24
+ data
25
+ end
26
+
27
+ # Query on model with data from filter_hash
28
+ def filter_model(model, filter_hash)
29
+ mods = model.all
30
+ # For each key of the model, recursively query (attributes, submodels)
31
+ filter_hash.keys.each do |k|
32
+ next if k == 'num_records'
33
+ attribute = k.split('_').last == 'id' ? k[0..-4] : k
34
+ mods = recursive_filter_attribute(mods, attribute, filter_hash[k])
35
+ end
36
+ return nil if mods.nil?
37
+
38
+ # Limit results if num_records is given
39
+ limit = filter_hash['num_records']
40
+ return mods.limit(limit.to_i) unless limit.empty?
41
+ mods
42
+ end
43
+
44
+ # Recursively query attributes depending on type associated to hash
45
+ def recursive_filter_attribute(models, attribute, filter_hash)
46
+ return nil if models.nil? || models.empty?
47
+
48
+ case filter_hash['type']
49
+ when 'datetime'
50
+ mods = filter_datetime(models, attribute, filter_hash)
51
+
52
+ when 'text'
53
+ mods = filter_text(models, attribute, filter_hash)
54
+
55
+ when 'numeric'
56
+ mods = filter_numeric(models, attribute, filter_hash)
57
+
58
+ when 'boolean'
59
+ mods = filter_boolean(models, attribute, filter_hash)
60
+
61
+ when 'has'
62
+ mods = filter_has(models, attribute, filter_hash)
63
+
64
+ when 'ref'
65
+ mods = filter_ref(models, attribute, filter_hash)
66
+
67
+ else
68
+ raise ArgumentError, 'type_' + filter_hash['type'] + '_is_unknown'
69
+ end
70
+ mods
71
+ end
72
+
73
+ # Helper functions for each type
74
+ # Query on models for attribute according to data in filter_hash
75
+
76
+ def filter_datetime(models, attribute, filter_hash)
77
+ mods = models
78
+ model_string = models.first.class.name.underscore
79
+ query_attribute = model_string.pluralize + '.' + attribute
80
+ start_date = DateTime.strptime(filter_hash['start'], '%b %d, %Y').beginning_of_day
81
+ end_date = DateTime.strptime(filter_hash['end'], '%b %d, %Y').beginning_of_day + 1.days
82
+ mods = mods.where("#{query_attribute}": start_date..end_date) if filter_hash.key?('start')
83
+ mods
84
+ end
85
+
86
+ def filter_text(models, attribute, filter_hash)
87
+ return models unless filter_hash.key?('present')
88
+ mods = models
89
+
90
+ model_string = models.first.class.name.underscore
91
+ query_attribute = model_string.pluralize + '.' + attribute
92
+
93
+ if !true_string?(filter_hash['present'])
94
+ mods = mods.where("#{attribute}": [nil, ''])
95
+ else
96
+ if filter_hash.key?('contains')
97
+ mods = mods.where(query_attribute + ' ~* ?', filter_hash['contains'])
98
+ else
99
+ mods = mods.where.not("#{attribute}": [nil, ''])
100
+ end
101
+ end
102
+ mods
103
+ end
104
+
105
+ def filter_numeric(models, attribute, filter_hash)
106
+ return models unless filter_hash.key?('value')
107
+
108
+ mods = models.where("#{attribute}": filter_hash['value'].to_i)
109
+ mods
110
+ end
111
+
112
+ def filter_boolean(models, attribute, filter_hash)
113
+ return models unless filter_hash.key?('value')
114
+
115
+ mods = models.where("#{attribute}": true_string?(filter_hash['value']))
116
+ mods
117
+ end
118
+
119
+ def filter_has(models, attribute, filter_hash)
120
+ return models unless filter_hash.key?('has')
121
+ mods = models
122
+
123
+ has_models = attribute.pluralize
124
+ model_string = models.first.class.name.underscore
125
+
126
+ if true_string?(filter_hash['has'])
127
+ mods = mods.includes("#{has_models}")
128
+ .where.not("#{has_models}": {"#{model_string}_id": nil})
129
+
130
+ mods = mods.joins("LEFT JOIN #{has_models} ON #{has_models}.#{model_string}_id = #{model_string.pluralize}.id")
131
+ .group("#{model_string.pluralize}.id")
132
+ .having("count(#{has_models}.id) >= ?", filter_hash['has-inf'].to_i) if filter_hash.key?('has-inf')
133
+ mods = mods.joins("LEFT JOIN #{has_models} ON #{has_models}.#{model_string}_id = #{model_string.pluralize}.id")
134
+ .group("#{model_string.pluralize}.id")
135
+ .having("count(#{has_models}.id) <= ?", filter_hash['has-sup'].to_i) if filter_hash.key?('has-sup')
136
+ return nil if mods.nil?
137
+
138
+ # Go recursively through has model params
139
+ attribute_models = attribute.classify.safe_constantize.where("#{model_string}": mods)
140
+ main_keys = %w[has-sup has-inf has type]
141
+ filter_hash.keys.each do |k|
142
+ attribute_models = recursive_filter_attribute(attribute_models, k.underscore, filter_hash[k]) unless main_keys.include?(k)
143
+ end
144
+ return nil if attribute_models.nil?
145
+ mods_ids = []
146
+ attribute_models.each { |m| mods_ids.push(m[model_string + '_id']) }
147
+ mods = mods.where(id: mods_ids)
148
+ else
149
+ mods = mods.includes(:"#{has_models}")
150
+ .where("#{has_models}": {"#{model_string}_id": nil})
151
+ end
152
+ mods
153
+ end
154
+
155
+ def filter_ref(models, attribute, filter_hash)
156
+ return models unless filter_hash.key?('ref')
157
+ mods = models
158
+
159
+ if true_string?(filter_hash['ref'])
160
+ mods = mods.where.not("#{attribute}": nil)
161
+ return nil if mods.nil?
162
+
163
+ # Go recursively through ref model params
164
+ attributes_ids = []
165
+ mods.each { |m| attributes_ids.push(m[attribute + '_id']) }
166
+ attribute_models = attribute.classify.safe_constantize
167
+ .where(id: attributes_ids)
168
+ main_keys = %w[ref type]
169
+ filter_hash.keys.each do |k|
170
+ attribute_models = recursive_filter_attribute(attribute_models, k.underscore, filter_hash[k]) unless main_keys.include?(k)
171
+ end
172
+ mods = mods.where("#{attribute}": attribute_models)
173
+ else
174
+ mods = mods.where("#{attribute}": nil)
175
+ end
176
+ mods
177
+ end
178
+
179
+ def filter_data_count_from_redis(data)
180
+ redis_data = nil
181
+ refresh = data.delete('refresh')
182
+ redis_filter_data = encode_filter_data(data)
183
+
184
+ unless refresh == true || DashCreator.redis_store_variable.nil?
185
+ redis_data = DashCreator.redis_store_variable.get(redis_filter_data)
186
+ end
187
+
188
+ unless redis_data.nil?
189
+ processed_data = JSON.parse(redis_data)
190
+ else
191
+ processed_data = filter_data(data).deep_stringify_keys
192
+ processed_data.keys.each { |k| processed_data[k] = processed_data[k].count }
193
+ processed_data['last_updated'] = DateTime.now.strftime('%d/%m/%Y - %T')
194
+
195
+ # Add chart data to redis
196
+ DashCreator.redis_store_variable.set(redis_filter_data, processed_data.to_json) unless DashCreator.redis_store_variable.nil?
197
+ end
198
+
199
+ processed_data
200
+ end
201
+
202
+ def encode_filter_data(data)
203
+ # Prepare data to encode
204
+ encoded_data = data.clone
205
+ encoded_data = encoded_data.to_unsafe_h unless encoded_data.is_a?(Hash)
206
+
207
+ # Encode
208
+ hash_hash(encoded_data)
209
+ end
210
+
211
+ # This helper function is used in create_chart.js.erb to hash param hash to store it in Redis
212
+ def hash_hash(h)
213
+ require 'digest/sha1'
214
+ str = recursive_flatten(h).sort.join
215
+ Digest::SHA1.hexdigest(str)
216
+ end
217
+
218
+ def recursive_flatten(h)
219
+ h.flatten(-1).map{|el| el.is_a?(Hash) ? recursive_flatten(el) : el}.flatten
220
+ end
221
+
222
+ # Check if string is 'true'
223
+ def true_string?(string)
224
+ string == 'true'
225
+ end
226
+
227
+ def get_csv(models)
228
+ CSV.generate do |csv|
229
+ columns = models.first.keys.map { |k| k.to_s }
230
+ csv << columns
231
+ models.each do |m|
232
+ csv << m.attributes.values_at(*columns)
233
+ end
234
+ end
235
+ end
236
+ end
237
+ end
@@ -0,0 +1,4 @@
1
+ module DashCreator
2
+ module UserHelper
3
+ end
4
+ end
@@ -0,0 +1,4 @@
1
+ module DashCreator
2
+ class ApplicationJob < ActiveJob::Base
3
+ end
4
+ end
@@ -0,0 +1,6 @@
1
+ module DashCreator
2
+ class ApplicationMailer < ActionMailer::Base
3
+ default from: 'from@example.com'
4
+ layout 'mailer'
5
+ end
6
+ end
@@ -0,0 +1,5 @@
1
+ module DashCreator
2
+ class ApplicationRecord < ActiveRecord::Base
3
+ self.abstract_class = true
4
+ end
5
+ end
@@ -0,0 +1,21 @@
1
+ module DashCreator
2
+ class Chart < ApplicationRecord
3
+ attr_accessor :user_id
4
+ belongs_to :user, class_name: DashCreator.user_class.to_s
5
+
6
+ before_validation :set_user
7
+
8
+ def as_json(options = {})
9
+ json = {
10
+ name: name,
11
+ data: data
12
+ }
13
+ json
14
+ end
15
+
16
+ private
17
+ def set_user
18
+ self.user = DashCreator.user_class.find(user_id)
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,13 @@
1
+ module DashCreator
2
+ class Dashboard < ApplicationRecord
3
+ attr_accessor :user_id
4
+ belongs_to :user, class_name: DashCreator.user_class.to_s
5
+
6
+ before_validation :set_user
7
+
8
+ private
9
+ def set_user
10
+ self.user = DashCreator.user_class.find(user_id)
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,7 @@
1
+ module DashCreator
2
+ class DashboardObject < ApplicationRecord
3
+ validates_presence_of :code, unique: true
4
+
5
+ # Acts as dashboard object for objects you want to display in your dashboard
6
+ end
7
+ end
@@ -0,0 +1,22 @@
1
+ module DashCreator
2
+ class Filter < ApplicationRecord
3
+ attr_accessor :user_id
4
+ belongs_to :user, class_name: DashCreator.user_class.to_s
5
+
6
+ before_validation :set_user
7
+
8
+ def as_json (opts={})
9
+ json = {
10
+ 'id': id,
11
+ 'name': name,
12
+ 'options': options
13
+ }
14
+ json
15
+ end
16
+
17
+ private
18
+ def set_user
19
+ self.user = DashCreator.user_class.find(user_id)
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,230 @@
1
+ <div class="row">
2
+ <div class="col-md-12">
3
+ <div class="card">
4
+ <div class="card-header">
5
+ Super Amazing Chart Creator
6
+ </div>
7
+ <div class="card-block" id="chart-creator" style="margin:20px 50px;">
8
+
9
+ </div>
10
+ <div class="card-footer">
11
+ <button type="submit" class="pull-left btn btn-success" id="chart-submit-btn">Draw Chart</button>
12
+ <a href="#" data-toggle="modal" data-target="#delete_charts_modal" class="pull-right btn btn-sm btn-danger" id="chart-unsave-btn"><%=t :delete_charts%></a>
13
+ <a href="#" data-toggle="modal" data-target="#edit_chart_modal" class="pull-right btn btn-sm btn-primary" id="chart-edit-btn"><%=t :modify_chart%></a>
14
+ <a href="#" data-toggle="modal" data-target="#save_chart_modal" class="pull-right btn btn-sm btn-success"><%=t :save_new_chart%></a>
15
+ <%= select_tag 'chart-select', options_for_select([]), prompt: 'Choose a chart', id: '', class: 'form-control pull-right', style: 'width: 20%; margin-right: 10%;' %>
16
+ </div>
17
+ </div>
18
+ <!--/.card-->
19
+ </div>
20
+ </div>
21
+
22
+ <script>
23
+ var charts = <%= raw @charts %>;
24
+
25
+ // TODO: JSON handling ??
26
+ // TODO: for date charts, always calculate day values and then gather ? so that changing day/week/month display doesn't need a reload
27
+ // TODO: if only bar/line change don't refresh
28
+ // TODO: Stats creator: take a filter, simply return the count of objects
29
+ // TODO: minicolors issue ?? Too much JS to handle for the browser when many color fields in chart creator
30
+
31
+ // Style presets
32
+ var minicolors_swatches = [
33
+ 'rgb(255, 99, 132)',
34
+ 'rgb(54, 162, 235)',
35
+ 'rgb(255, 206, 86)',
36
+ 'rgb(75, 192, 192)',
37
+ 'rgb(153, 102, 255)',
38
+ 'rgb(255, 159, 64)',
39
+ 'rgb(216, 247, 147)',
40
+ 'rgb(52, 85, 17)',
41
+ 'rgb(220, 255, 253)',
42
+ 'rgb(1, 17, 10)',
43
+ 'rgb(219, 153, 90)',
44
+ 'rgb(153, 134, 80)'
45
+ ];
46
+ var minicolors_options = {theme: 'bootstrap', format: 'rgb', swatches: minicolors_swatches};
47
+
48
+ $('#chart-creator').chartCreator({
49
+ models_data: <%= raw @models_data.to_json %>,
50
+ attributes_aliases: <%= raw DashCreator.attributes_aliases.to_json %>,
51
+ displayed_model_names: <%= raw DashCreator.displayed_model_names.to_json %>,
52
+ displayed_attribute_names: <%= raw DashCreator.displayed_attribute_names.to_json %>,
53
+ filter_creator: $('#filter-creator'),
54
+ minicolors_options: minicolors_options
55
+ });
56
+ var chart_creator = $('#chart-creator').data('chartCreator');
57
+
58
+
59
+ // --------------- Send chart data to controller ---------------
60
+ chart_creator.labelOptionsContainer.on('click', '#pluck-labels-btn', labelsFromPluck);
61
+ function labelsFromPluck() {
62
+ var limit = chart_creator.labelOptionsContainer.find('[name="pluck-num"]').val();
63
+
64
+ var x = chart_creator.xContainer.find('[name="x-axis"]').val().split('-');
65
+ var model, attribute;
66
+ if (x[1] === 'has' || x[1] === 'ref') {
67
+ model = x[0].classify();
68
+ attribute = chart_creator.labelOptionsContainer.find('[name="x-sub"]').val().split('-')[0];
69
+ }
70
+ else {
71
+ model = chart_creator.yContainer.find('[name="y-axis"]:first').val();
72
+ attribute = x[0];
73
+ }
74
+
75
+ var params = {
76
+ model: model,
77
+ attribute: attribute,
78
+ limit: limit
79
+ };
80
+
81
+ $.post('<%= pluck_labels_path %>', params, function(data) {
82
+ var labels = data['labels'];
83
+
84
+ chart_creator.labelOptionsContainer.find('[name="labels-num"]').val(labels.length).change();
85
+ chart_creator.labelOptionsContainer.find('.limit-label').each(function() {
86
+ $(this).val(labels.shift());
87
+ });
88
+ });
89
+ }
90
+
91
+
92
+ // --------------- Send chart data to controller ---------------
93
+ // Send data for controller chart actions
94
+ function sendChartDataCreate(chart_data) {
95
+ $.post("<%= create_chart_path %>", chart_data);
96
+ }
97
+
98
+ function sendChartDataSave(chart_data) {
99
+ $.post("<%= save_chart_path %>", chart_data, function(data) {
100
+ var chart_id = data['chart_id'], chart_name = chart_data['chart_name'];
101
+ charts.push([chart_name, chart_id]);
102
+
103
+ var dashboard_creator_objects_data = $('#dashboard-creator').data('dashboardCreator').objects_data;
104
+ dashboard_creator_objects_data['chart']['objects'].push({id: chart_id, name: chart_name});
105
+ });
106
+ }
107
+
108
+ function sendChartDataEdit(chart_data) {
109
+ $.post("<%= edit_chart_path %>", chart_data);
110
+ }
111
+
112
+ // Handle submit
113
+ $('#chart-submit-btn').click(function() {
114
+ var chart_data = chart_creator.getChartData();
115
+ chart_data['refresh'] = false;
116
+ sendChartDataCreate(chart_data);
117
+ });
118
+
119
+
120
+ // --------------- Save, unsave, show saved charts ---------------
121
+ var chart_id = '';
122
+
123
+ // Save a chart config
124
+ $(document).on('click', '#save-chart-btn', function() {
125
+ var chart_data = chart_creator.getChartData();
126
+
127
+ // Get the chart name
128
+ chart_data['chart_name'] = $('.modal#save_chart_modal').find('[name="chart-name"]').val();
129
+
130
+ // Post data with chart-save request
131
+ sendChartDataSave(chart_data);
132
+ });
133
+
134
+ // Prepare modal display for edit
135
+ $('#chart-edit-btn').click(function() {
136
+ var confirm_edit_chart_btn = $('#confirm-edit-chart-btn');
137
+
138
+ var h3_div = $('.modal#edit_chart_modal .modal-body #edit-message');
139
+ h3_div.empty();
140
+ confirm_edit_chart_btn.prop('disabled', false);
141
+
142
+ var h3_div_text;
143
+ if (chart_id !== '') {
144
+ h3_div_text = 'Are you sure you want to edit chart ';
145
+ for (var i = 0; i < charts.length; i++) {
146
+ var chart_name = charts[i][0], id = charts[i][1];
147
+ if (chart_id === id) {
148
+ h3_div_text += chart_name;
149
+ break;
150
+ }
151
+ }
152
+ h3_div_text += ' ?'
153
+ }
154
+ else {
155
+ h3_div_text = 'No chart to edit.';
156
+ confirm_edit_chart_btn.prop('disabled', true);
157
+ }
158
+ h3_div.text(h3_div_text);
159
+ });
160
+
161
+ // Prepare and send new chart data on chart edit confirm
162
+ $(document).on('click', '#confirm-edit-chart-btn', function() {
163
+ var chart_data = chart_creator.getChartData();
164
+ chart_data['chart_id'] = chart_id;
165
+
166
+ sendChartDataEdit(chart_data);
167
+ });
168
+
169
+ // Prepare list of charts for delete charts modal
170
+ $('#chart-unsave-btn').click(function() {
171
+ var checkbox_list = $('#charts-checkbox-list');
172
+ // First empty the checkbox list
173
+ checkbox_list.children().remove();
174
+
175
+ // Append charts list to div in modal
176
+ var checkbox_string_start = '<div class="col-sm-12"><div class="form-group">'
177
+ + '<input type="checkbox" class="form-control" name="chart" value="';
178
+ for (var i = 0; i < charts.length; i++) {
179
+ var chart_name = charts[i][0], id = charts[i][1];
180
+ var chart_string = checkbox_string_start + id + '"><label>' + chart_name + '</label><br>';
181
+ $(chart_string).appendTo(checkbox_list);
182
+ }
183
+ $('</div></div>').appendTo(checkbox_list);
184
+ });
185
+
186
+ // Delete charts
187
+ $(document).on('click', '#delete-charts-btn', function() {
188
+ // Get the charts ids
189
+ var charts_ids = [];
190
+ $(this).closest('.modal').find('[type="checkbox"]:checked').each(function() {
191
+ charts_ids.push($(this).attr("value"));
192
+ });
193
+
194
+ var params = {charts_ids: charts_ids};
195
+
196
+ $.post("<%= delete_charts_path %>", params, function() {
197
+ // Remove from charts list
198
+ for (var i = 0; i < charts.length; i++) {
199
+ var id = charts[i][1];
200
+ if ($.inArray(id, charts_ids) !== -1) {
201
+ charts.splice(i, 1);
202
+ i--;
203
+ }
204
+ }
205
+ });
206
+ });
207
+
208
+ $('[name="chart-select"]')
209
+ .focusin(displayChartList)
210
+ .change(displayChart);
211
+
212
+ // Display chart select list
213
+ function displayChartList() {
214
+ $(this).children().not('[value=""]').remove();
215
+ for (var i = 0; i < charts.length; i++) {
216
+ var chart_name = charts[i][0], id = charts[i][1];
217
+ $('<option value="' + id + '">' + chart_name + '</option>').appendTo($('[name="chart-select"]'));
218
+ }
219
+ }
220
+
221
+ // Display chosen chart
222
+ function displayChart() {
223
+ if ($(this).val() === '') { return false; }
224
+
225
+ chart_id = $(this).val();
226
+ var params = {chart_id: chart_id};
227
+
228
+ $.post("<%= get_chart_path %>", params);
229
+ }
230
+ </script>