kanaui 0.6.0 → 2.1.1

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 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