kanaui 0.6.0 → 2.1.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 44408c840e86c3b09c99de32d8562b6f6cb11f8b
4
- data.tar.gz: b4c65299ff506937976f193d337701969e0cba65
3
+ metadata.gz: b97ea14f934efc662bd48c78371bb3bbaf57a347
4
+ data.tar.gz: e3b86efa67ff817e61cd181654d92fa1ba1fad3d
5
5
  SHA512:
6
- metadata.gz: a1fd5e4063dea83305ead4baa1e6b60d9c532d86a4518067c2a2995709fab84df428c266f0a2d5a96222f5729bc8d3f7336d9036046b8d222fc2e4bd0dcb6e7f
7
- data.tar.gz: b62394e70ab37f0d418930846d288e8da1fec047dc9ad37a35cdaa0b5be8c9d6801aa54a84073e7c3d9ed8c131379e76265dc72ea2a972eb1f41e566559931ee
6
+ metadata.gz: 9bf5d0c1847d69ca090ea670cd9731ecaeac658bac5b5a2fd2cf7dea1a463a9fa138a5c32ffd8db01f5a69a3d50efedf1a492b4c9705cfe6bf13ab1e2831654f
7
+ data.tar.gz: 62cd8b7055b53dce95b8abfe0f309a7d4cd84cb9ed18da9bb700341c38191b743b80ae852feb2821954e2aae26675fbefec4192a72d41371de01e90e4f982774
data/README.md CHANGED
@@ -14,6 +14,8 @@ Kill Bill compatibility
14
14
  | 0.4.y | 0.16.z |
15
15
  | 0.5.y | 0.18.z (Rails 4) |
16
16
  | 0.6.y | 0.18.z (Rails 5) |
17
+ | 1.x.y | 0.20.z |
18
+ | 2.x.y | 0.22.z |
17
19
 
18
20
  Getting Started
19
21
  ===============
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
@@ -12,6 +12,7 @@
12
12
  //= require twitter/bootstrap
13
13
  //= require dataTables/jquery.dataTables
14
14
  //= require dataTables/bootstrap/3/jquery.dataTables.bootstrap
15
+ //= require dataTables/extras/dataTables.colVis
15
16
  //= require d3
16
17
  //= require bootstrap-datepicker
17
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,7 @@
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
9
10
  *= require font-awesome
10
11
  *= require bootstrap_and_overrides
11
12
  *= require kanaui/kanaui
@@ -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,16 +21,19 @@ 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
- query_params = {: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]}
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] }
33
37
 
34
38
  # Test only
35
39
  query_params[:fake] = params[:fake] unless params[:fake].blank?
@@ -44,7 +48,7 @@ module Kanaui
44
48
  # Not used anymore as reports are pulled from index
45
49
  def available_reports
46
50
  available_reports = Kanaui::DashboardHelper::DashboardApi.available_reports(options_for_klient)
47
- render :json => available_reports
51
+ render json: available_reports
48
52
  end
49
53
 
50
54
  def reports
@@ -63,7 +67,18 @@ module Kanaui
63
67
  else
64
68
  reports = raw_reports
65
69
  end
66
- render :json => reports
70
+ respond_to do |fmt|
71
+ fmt.csv do
72
+ filename = params[:name]
73
+ unless params[:start_date].blank?
74
+ filename += "_#{params[:start_date]}"
75
+ filename += "-#{params[:end_date]}" unless params[:end_date].blank?
76
+ end
77
+ filename += '.csv'
78
+ send_data(raw_reports, filename: filename)
79
+ end
80
+ fmt.all { render json: reports }
81
+ end
67
82
  end
68
83
 
69
84
  private
@@ -114,6 +129,7 @@ module Kanaui
114
129
  filter_query = ''
115
130
  filters.each do |k, v|
116
131
  next if v.blank?
132
+
117
133
  filter_query << '%26' unless filter_query.blank?
118
134
  filter_query << "(#{k}=#{v.join("|#{k}=")})"
119
135
  end
@@ -121,7 +137,8 @@ module Kanaui
121
137
 
122
138
  groups.each do |k, v|
123
139
  next if v.blank?
124
- # TODO Make "no other" configurable
140
+
141
+ # TODO: Make "no other" configurable
125
142
  query << "^dimension:#{k}(#{v.join('|')}|-)"
126
143
  end
127
144
 
@@ -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