kanaui 0.5.1 → 2.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (56) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +15 -9
  3. data/Rakefile +4 -5
  4. data/app/assets/javascripts/application.js +1 -1
  5. data/app/assets/javascripts/kanaui/kiddo/kiddo_initialize.js +1 -1
  6. data/app/assets/javascripts/kanaui/reports.dataTables.js +74 -2
  7. data/app/assets/stylesheets/application.css +2 -0
  8. data/app/assets/stylesheets/bootstrap_and_overrides.css +0 -4
  9. data/app/assets/stylesheets/kanaui/reports.css +66 -2
  10. data/app/controllers/kanaui/dashboard_controller.rb +24 -12
  11. data/app/controllers/kanaui/engine_controller.rb +41 -6
  12. data/app/controllers/kanaui/reports_controller.rb +15 -12
  13. data/app/controllers/kanaui/settings_controller.rb +13 -0
  14. data/app/helpers/kanaui/application_helper.rb +2 -2
  15. data/app/helpers/kanaui/dashboard_helper.rb +7 -5
  16. data/app/views/kanaui/dashboard/index.html.erb +153 -125
  17. data/app/views/kanaui/reports/_form.html.erb +30 -16
  18. data/app/views/kanaui/reports/_reports_table.html.erb +22 -0
  19. data/app/views/kanaui/settings/index.html.erb +19 -0
  20. data/config/routes.rb +11 -8
  21. data/lib/kanaui.rb +11 -10
  22. data/lib/kanaui/engine.rb +5 -1
  23. data/lib/kanaui/version.rb +3 -1
  24. data/lib/tasks/kanaui_tasks.rake +1 -0
  25. data/test/dummy/app/assets/config/manifest.js +1 -0
  26. data/test/dummy/bin/bundle +3 -0
  27. data/test/dummy/bin/rails +4 -0
  28. data/test/dummy/bin/rake +4 -0
  29. data/test/dummy/bin/setup +38 -0
  30. data/test/dummy/bin/update +29 -0
  31. data/test/dummy/bin/yarn +11 -0
  32. data/test/dummy/config/application.rb +15 -47
  33. data/test/dummy/config/boot.rb +2 -9
  34. data/test/dummy/config/environment.rb +4 -4
  35. data/test/dummy/config/environments/development.rb +38 -18
  36. data/test/dummy/config/environments/production.rb +61 -39
  37. data/test/dummy/config/environments/test.rb +20 -14
  38. data/test/dummy/config/initializers/application_controller_renderer.rb +6 -0
  39. data/test/dummy/config/initializers/assets.rb +14 -0
  40. data/test/dummy/config/initializers/cookies_serializer.rb +5 -0
  41. data/test/dummy/config/initializers/filter_parameter_logging.rb +4 -0
  42. data/test/dummy/config/initializers/inflections.rb +6 -5
  43. data/test/dummy/config/initializers/killbill_client.rb +3 -3
  44. data/test/dummy/config/initializers/mime_types.rb +0 -1
  45. data/test/dummy/config/initializers/new_framework_defaults_5_1.rb +14 -0
  46. data/test/dummy/config/initializers/wrap_parameters.rb +5 -5
  47. data/test/dummy/config/locales/en.yml +30 -2
  48. data/test/dummy/config/secrets.yml +32 -0
  49. data/test/functional/kanaui/tests_controller_test.rb +2 -0
  50. data/test/integration/navigation_test.rb +7 -5
  51. data/test/kanaui_test.rb +3 -1
  52. data/test/test_helper.rb +7 -7
  53. data/test/unit/helpers/kanaui/tests_helper_test.rb +2 -0
  54. metadata +117 -176
  55. data/app/models/kanaui/dashboard.rb +0 -5
  56. data/test/dummy/config/database.yml +0 -25
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: b509920c148aef35ccf0bffbe38b935b669a35ff
4
- data.tar.gz: e5d121e521e55c1c3f882f7f0bbfd576c961a7e9
3
+ metadata.gz: c634cb242e7d9aef0a4bb937451a57c3f10f0c90
4
+ data.tar.gz: '08e4e1e1419a230305488420fa8f2f8b69de57a4'
5
5
  SHA512:
6
- metadata.gz: e8ebbb2db468390719e6c125880f483382f2cfd61ca4256128409c7dfa89aa11b367d3f6b5bdc039897c81de3fd627007348ff2c86e82096e94392c4c7f47b4d
7
- data.tar.gz: bc6c3397d0fa1f6192f81cf85c199934126c4a42283791ec8e6ec7b0b8e31dc7678804dc5c288474713f22a9ccad7dac089967a2a6fed42440b5edb83956bc81
6
+ metadata.gz: 4e4bd12458f02a2beeddd6b111e89460245bcc24c8d65be1debd3b261eb88dc55ce6a139e7e550e5110c59cc8d63b287805ec47d74ad803849560b97e55a2eb2
7
+ data.tar.gz: a3d7284429507ddc4b465613407b30ccd3ed118f31b834a7db4846ff1a7b9b416e89f9526e5c2f38a4ee4ed28651f3b3d9d6fe4aa8121a9d2534b18cfe1ae68e
data/README.md CHANGED
@@ -12,7 +12,10 @@ Kill Bill compatibility
12
12
  | Kanaui version | Kill Bill version |
13
13
  | -------------: | ----------------: |
14
14
  | 0.4.y | 0.16.z |
15
- | 0.5.y | 0.18.z |
15
+ | 0.5.y | 0.18.z (Rails 4) |
16
+ | 0.6.y | 0.18.z (Rails 5) |
17
+ | 1.x.y | 0.20.z |
18
+ | 2.x.y | 0.22.z |
16
19
 
17
20
  Getting Started
18
21
  ===============
@@ -34,15 +37,18 @@ KillBillClient.api_key = 'bob'
34
37
  KillBillClient.api_secret = 'lazar'
35
38
  ```
36
39
 
37
- Running Kanaui
38
- --------------
40
+ Testing
41
+ -------
39
42
 
40
- You can run Kanaui locally by using the test/dummy app provided:
43
+ To run the dummy app:
41
44
 
42
45
  ```
43
- bundle install
44
- cd test/dummy
45
- export RAILS_ENV=development
46
- bundle install
47
- rails server
46
+ rails s
47
+ ```
48
+
49
+
50
+ To run tests:
51
+
52
+ ```
53
+ rails t
48
54
  ```
data/Rakefile CHANGED
@@ -1,4 +1,6 @@
1
1
  #!/usr/bin/env rake
2
+ # frozen_string_literal: true
3
+
2
4
  begin
3
5
  require 'bundler/setup'
4
6
  rescue LoadError
@@ -20,11 +22,9 @@ RDoc::Task.new(:rdoc) do |rdoc|
20
22
  rdoc.rdoc_files.include('lib/**/*.rb')
21
23
  end
22
24
 
23
- APP_RAKEFILE = File.expand_path("../test/dummy/Rakefile", __FILE__)
25
+ APP_RAKEFILE = File.expand_path('test/dummy/Rakefile', __dir__)
24
26
  load 'rails/tasks/engine.rake'
25
27
 
26
-
27
-
28
28
  Bundler::GemHelper.install_tasks
29
29
 
30
30
  require 'rake/testtask'
@@ -36,5 +36,4 @@ Rake::TestTask.new(:test) do |t|
36
36
  t.verbose = false
37
37
  end
38
38
 
39
-
40
- task :default => :test
39
+ task default: :test
@@ -6,13 +6,13 @@
6
6
  //
7
7
  //= require js-routes
8
8
  //= require log4javascript
9
- //= require moment
10
9
  //= require spin
11
10
  //= require jquery
12
11
  //= require jquery_ujs
13
12
  //= require twitter/bootstrap
14
13
  //= require dataTables/jquery.dataTables
15
14
  //= require dataTables/bootstrap/3/jquery.dataTables.bootstrap
15
+ //= require dataTables/extras/dataTables.colVis
16
16
  //= require d3
17
17
  //= require bootstrap-datepicker
18
18
  //= require jquery.spin
@@ -8,7 +8,7 @@
8
8
  var renderer = new Kiddo.Renderer('#chartAnchor');
9
9
 
10
10
  if (error) {
11
- console.log(error);
11
+ ajaxErrorAlert(error);
12
12
  return renderer.noData();
13
13
  }
14
14
 
@@ -40,16 +40,88 @@ ReportsDataTables.prototype.buildTable = function(data, wrapper) {
40
40
  }
41
41
 
42
42
  var aoColumns = [];
43
+ var columnsVisible = [];
43
44
  for (var i in data['header']) {
44
- aoColumns.push({ "sTitle": data['header'][i] })
45
+ var isVisible = isColumnVisible(data['header'][i]);
46
+ aoColumns.push({ "sTitle": data['header'][i], "name": data['header'][i], "visible": isVisible })
47
+ if (isVisible) {
48
+ columnsVisible.push(data['header'][i]);
49
+ }
45
50
  }
46
51
 
47
52
  dataTable.dataTable({
48
53
  "aaData": aaData,
49
- "aoColumns": aoColumns
54
+ "aoColumns": aoColumns,
55
+ "scrollX": true,
56
+ "sDom": 'C<"clear">lfrtip'
50
57
  });
58
+
59
+ dataTable.on( 'column-visibility.dt', function ( e, settings, column, state ) {
60
+ setColumnVisible(settings.aoColumns[column].name, state);
61
+ });
62
+
63
+ $("#copy-url").click(function(e){
64
+ var pathPlusParams = $(this).data("reports-path");
65
+ var sPageURL = decodeURIComponent(pathPlusParams.substring(1)).split('?');
66
+ var params = sPageURL[1].split('&');
67
+
68
+ var columnsVisible = $("#visible-table-columns").val();
69
+ var placeholder = $("#url-placeholder");
70
+
71
+ var urlToShare = window.location.origin + "/" + sPageURL[0] + "?";
72
+ for (var i in params) {
73
+ var keyValue = params[i].split('=');
74
+ if (keyValue[0] == 'columns') {
75
+ continue;
76
+ }
77
+ urlToShare += "&" + params[i];
78
+ }
79
+
80
+ placeholder.val(urlToShare + "&columns=" + columnsVisible);
81
+ placeholder.removeClass("hidden");
82
+ placeholder.select();
83
+
84
+ document.execCommand("Copy");
85
+ placeholder.addClass("hidden");
86
+ alert("URL copied into the clipboard!")
87
+ });
88
+
89
+ $("#visible-table-columns").val(columnsVisible.join());
51
90
  }
52
91
 
53
92
  ReportsDataTables.prototype.buildCSVURL = function(position) {
54
93
  return this.reports.buildDataURL(position, 'csv');
55
94
  }
95
+ function setColumnVisible(column, isVisible) {
96
+ var columnsVisible = $("#visible-table-columns").val();
97
+ if (columnsVisible == undefined || columnsVisible == null || columnsVisible.length == 0) {
98
+ columnsVisible = [];
99
+ } else {
100
+ columnsVisible = (columnsVisible).split(",");
101
+ }
102
+
103
+ var columnIndex = columnsVisible.indexOf(column);
104
+ if (isVisible && columnIndex == -1) {
105
+ columnsVisible.push(column);
106
+ } else if (!isVisible && columnIndex != -1) {
107
+ columnsVisible.splice(columnIndex, 1);
108
+ }
109
+
110
+ $("#visible-table-columns").val(columnsVisible.join());
111
+ }
112
+
113
+ function isColumnVisible(column) {
114
+ var columnsVisible = $("#visible-table-columns").val();
115
+ if ((columnsVisible == undefined || columnsVisible == null || columnsVisible.length == 0) && column != 'tenant_record_id') {
116
+ return true;
117
+ }
118
+ columnsVisible = (columnsVisible).split(",");
119
+
120
+ for (var i in columnsVisible) {
121
+ if (columnsVisible[i] == column) {
122
+ return true;
123
+ }
124
+ }
125
+
126
+ return false;
127
+ }
@@ -6,6 +6,8 @@
6
6
  *= require bootstrap-datepicker3
7
7
  *= require dataTables/jquery.dataTables
8
8
  *= require dataTables/bootstrap/3/jquery.dataTables.bootstrap
9
+ *= require dataTables/extras/dataTables.colVis
10
+ *= require font-awesome
9
11
  *= require bootstrap_and_overrides
10
12
  *= require kanaui/kanaui
11
13
  */
@@ -1,9 +1,5 @@
1
1
  /*
2
2
  *= require twitter-bootstrap-static/bootstrap
3
- *
4
- * Use Font Awesome icons (default)
5
- * To use Glyphicons sprites instead of Font Awesome, replace with "require twitter-bootstrap-static/sprites"
6
- *= require twitter-bootstrap-static/fontawesome
7
3
  */
8
4
 
9
5
  /* Override Bootstrap 3 font locations */
@@ -1,5 +1,10 @@
1
- #date-picker {
2
- margin-bottom: 20px;
1
+ #reports-table th, #reports-table td,
2
+ #dataTable-api_wrapper th, #dataTable-api_wrapper td {
3
+ white-space: nowrap;
4
+ }
5
+
6
+ .sql-query {
7
+ word-break: break-word;
3
8
  }
4
9
 
5
10
  .axis path,
@@ -92,3 +97,62 @@
92
97
  .grid path{
93
98
  stroke-width: 0;
94
99
  }
100
+
101
+ button.ColVis_Button, button.ColVis_Button:hover {
102
+ background: inherit;
103
+ box-shadow: unset;
104
+ text-transform: none;
105
+ color: #333 !important;
106
+ border-color: #adadad;
107
+ }
108
+
109
+ ul.ColVis_collection {
110
+ background-color: #f3f3f3;
111
+ }
112
+
113
+ ul.ColVis_collection li, ul.ColVis_collection li:hover{
114
+ border: none;
115
+ box-shadow: unset;
116
+ background: transparent;
117
+ }
118
+
119
+ button.ColVis_Button:hover, ul.ColVis_collection li:hover {
120
+ background-color: #e6e6e6;
121
+ border-color: #adadad;
122
+ }
123
+
124
+ .dataTables_wrapper .dataTables_paginate .paginate_button {
125
+ padding: 0.25em 0.5em;
126
+ }
127
+
128
+ .flex-panel {
129
+ display: -webkit-flex;
130
+ display: flex;
131
+ -webkit-flex-direction: row;
132
+ flex-direction: row;
133
+ }
134
+
135
+ .flex-inner-left-panel {
136
+ -ms-flex: 1 .5 0%;
137
+ -webkit-flex: 1 .5 0%;
138
+ flex: 1 .5 0%;
139
+ }
140
+
141
+ .flex-inner-left-panel ul li {
142
+ white-space: nowrap;
143
+ }
144
+
145
+ .flex-inner-right-panel {
146
+ -ms-flex: .5 1 70%;
147
+ -webkit-flex: .5 1 70%;
148
+ flex: .5 1 70%;
149
+ overflow: scroll;
150
+ }
151
+
152
+ #date-picker .form-group {
153
+ height: 34px;
154
+ }
155
+
156
+ #table-tools {
157
+ padding-bottom: 10px;
158
+ }
@@ -1,6 +1,7 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Kanaui
2
4
  class DashboardController < Kanaui::EngineController
3
-
4
5
  #
5
6
  # Load the dashboard by rendering the view and executing the javascript that will call
6
7
  # the reports and available_reports endpoints below.
@@ -20,25 +21,34 @@ module Kanaui
20
21
 
21
22
  query = build_slice_and_dice_query
22
23
 
24
+ # get columns visibility from query parameters to be used by tables
25
+ @visible_columns = params[:columns]
26
+
23
27
  # Redirect also in case the dates have been updated to avoid any confusion in the view
24
28
  if query.present? || params[:start_date].blank? || params[:end_date].blank?
25
- # TODO Make metrics configurable
29
+ # TODO: Make metrics configurable
26
30
  name = query.present? ? "#{params[:name]}#{query}^metric:count" : params[:name]
27
- redirect_to dashboard_index_path(:start_date => @start_date,
28
- :end_date => @end_date,
29
- :name => name,
30
- :smooth => params[:smooth],
31
- :sql_only => params[:sql_only],
32
- :format => params[:format]) and return
31
+ query_params = { start_date: @start_date,
32
+ end_date: @end_date,
33
+ name: name,
34
+ smooth: params[:smooth],
35
+ sql_only: params[:sql_only],
36
+ format: params[:format] }
37
+
38
+ # Test only
39
+ query_params[:fake] = params[:fake] unless params[:fake].blank?
40
+ query_params[:type] = params[:type] unless params[:type].blank?
41
+
42
+ redirect_to dashboard_index_path(query_params) and return
33
43
  end
34
44
 
35
- render
45
+ params.permit!
36
46
  end
37
47
 
38
48
  # Not used anymore as reports are pulled from index
39
49
  def available_reports
40
50
  available_reports = Kanaui::DashboardHelper::DashboardApi.available_reports(options_for_klient)
41
- render :json => available_reports
51
+ render json: available_reports
42
52
  end
43
53
 
44
54
  def reports
@@ -57,7 +67,7 @@ module Kanaui
57
67
  else
58
68
  reports = raw_reports
59
69
  end
60
- render :json => reports
70
+ render json: reports
61
71
  end
62
72
 
63
73
  private
@@ -108,6 +118,7 @@ module Kanaui
108
118
  filter_query = ''
109
119
  filters.each do |k, v|
110
120
  next if v.blank?
121
+
111
122
  filter_query << '%26' unless filter_query.blank?
112
123
  filter_query << "(#{k}=#{v.join("|#{k}=")})"
113
124
  end
@@ -115,7 +126,8 @@ module Kanaui
115
126
 
116
127
  groups.each do |k, v|
117
128
  next if v.blank?
118
- # TODO Make "no other" configurable
129
+
130
+ # TODO: Make "no other" configurable
119
131
  query << "^dimension:#{k}(#{v.join('|')}|-)"
120
132
  end
121
133
 
@@ -1,6 +1,7 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Kanaui
2
4
  class EngineController < ApplicationController
3
-
4
5
  layout :get_layout
5
6
 
6
7
  def get_layout
@@ -17,12 +18,46 @@ module Kanaui
17
18
  def options_for_klient
18
19
  user = current_tenant_user
19
20
  {
20
- :username => user[:username],
21
- :password => user[:password],
22
- :session_id => user[:session_id],
23
- :api_key => user[:api_key],
24
- :api_secret => user[:api_secret]
21
+ username: user[:username],
22
+ password: user[:password],
23
+ session_id: user[:session_id],
24
+ api_key: user[:api_key],
25
+ api_secret: user[:api_secret]
25
26
  }
26
27
  end
28
+
29
+ rescue_from(KillBillClient::API::ResponseError) do |killbill_exception|
30
+ flash[:error] = "Error while communicating with the Kill Bill server: #{as_string(killbill_exception)}"
31
+ redirect_to dashboard_index_path
32
+ end
33
+
34
+ def as_string(e)
35
+ if e.is_a?(KillBillClient::API::ResponseError)
36
+ "Error #{e.response.code}: #{as_string_from_response(e.response.body)}"
37
+ else
38
+ log_rescue_error(e)
39
+ e.message
40
+ end
41
+ end
42
+
43
+ def log_rescue_error(error)
44
+ Rails.logger.warn "#{error.class} #{error}. #{error.backtrace.join("\n")}"
45
+ end
46
+
47
+ def as_string_from_response(response)
48
+ error_message = response
49
+ begin
50
+ # BillingExceptionJson?
51
+ error_message = JSON.parse response
52
+ rescue StandardError => _e
53
+ end
54
+
55
+ if error_message.respond_to?(:[]) && error_message['message'].present?
56
+ # Likely BillingExceptionJson
57
+ error_message = error_message['message']
58
+ end
59
+ # Limit the error size to avoid ActionDispatch::Cookies::CookieOverflow
60
+ error_message[0..1000]
61
+ end
27
62
  end
28
63
  end
@@ -1,6 +1,7 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Kanaui
2
4
  class ReportsController < Kanaui::EngineController
3
-
4
5
  def index
5
6
  @reports = JSON.parse(Kanaui::DashboardHelper::DashboardApi.available_reports(options_for_klient)).map(&:deep_symbolize_keys)
6
7
  end
@@ -13,7 +14,7 @@ module Kanaui
13
14
  Kanaui::DashboardHelper::DashboardApi.create_report(report_from_params.to_json, options_for_klient)
14
15
 
15
16
  flash[:notice] = 'Report successfully created'
16
- redirect_to :action => :index
17
+ redirect_to action: :index
17
18
  end
18
19
 
19
20
  def edit
@@ -26,34 +27,36 @@ module Kanaui
26
27
  Kanaui::DashboardHelper::DashboardApi.update_report(params.require(:id), report_from_params.to_json, options_for_klient)
27
28
 
28
29
  flash[:notice] = 'Report successfully updated'
29
- redirect_to :action => :index
30
+ redirect_to action: :index
30
31
  end
31
32
 
32
33
  def refresh
33
34
  Kanaui::DashboardHelper::DashboardApi.refresh_report(params.require(:id), options_for_klient)
34
35
 
35
36
  flash[:notice] = 'Report refresh successfully scheduled'
36
- redirect_to :action => :index
37
+ redirect_to action: :index
37
38
  end
38
39
 
39
40
  def destroy
40
41
  Kanaui::DashboardHelper::DashboardApi.delete_report(params.require(:id), options_for_klient)
41
42
 
42
43
  flash[:notice] = 'Report successfully deleted'
43
- redirect_to :action => :index
44
+ redirect_to action: :index
44
45
  end
45
46
 
46
47
  private
47
48
 
48
49
  def report_from_params
49
50
  {
50
- :reportName => params[:report_name],
51
- :reportPrettyName => params[:report_pretty_name],
52
- :reportType => params[:report_type],
53
- :sourceTableName => params[:source_table_name],
54
- :refreshProcedureName => params[:refresh_procedure_name],
55
- :refreshFrequency => params[:refresh_frequency],
56
- :refreshHourOfDayGmt => params[:refresh_hour_of_day_gmt]
51
+ reportName: params[:report_name],
52
+ reportPrettyName: params[:report_pretty_name],
53
+ reportType: params[:report_type],
54
+ sourceTableName: params[:source_table_name],
55
+ sourceName: params[:source_name],
56
+ sourceQuery: params[:source_query],
57
+ refreshProcedureName: params[:refresh_procedure_name],
58
+ refreshFrequency: params[:refresh_frequency].presence,
59
+ refreshHourOfDayGmt: params[:refresh_hour_of_day_gmt]
57
60
  }
58
61
  end
59
62
  end