easy_data_tables 0.1.1 → 0.2.0

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
  SHA256:
3
- metadata.gz: 3cb80cf6b75f6538198a91b5e47dda21b23d33f16ad59017e23601c19c1f7f4b
4
- data.tar.gz: f157300ea30e55dee0fbf082c8da2e9e3681a7e19b6ebf39d56e71b1e3279820
3
+ metadata.gz: f9f6075dc6b932de890fbe28050a1b6d3b417d5576e601ccb97b695cedffcc84
4
+ data.tar.gz: '09d60e1ba17eac10c7760bf908912d37b56cdda590543a9075938d55f8e1cc10'
5
5
  SHA512:
6
- metadata.gz: f9db24e2600639ee0f711be2e123e410af17922cbb793380f930c2c137681fd85e1237cfe00e5a262242578b217897296aceeac4ff2a0b28c8dfb4eec2bfa394
7
- data.tar.gz: 5b069d81d97bf2c07efbac3e05065dc5357d95111e74a5a56dc0dcfedd37f82d16746e64609fff0f8400f8318fc8470cc53058126ed1ccbe86a1461246e78ae8
6
+ metadata.gz: 67d03e29ff2f7725c8da4492f75ad4a6d3be78de093fe1e54fc1fc71775614e5075b2c731ffda8b835cfc515f6b0590a8e252952612fbd4cf97148bd3dce3d06
7
+ data.tar.gz: 3f59f1c2fd4302981e88af92ac01318b6634a046a93fc7703477ecafa58b82e3530fa8ac86328dcca937d3c20080786b58c58c5f53db470a0e1ebb18dd15dde1
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- easy_data_tables (0.1.1)
4
+ easy_data_tables (0.2.0)
5
5
 
6
6
  GEM
7
7
  remote: https://rubygems.org/
data/README.md CHANGED
@@ -2,6 +2,8 @@
2
2
 
3
3
  This gem provides a way to create fast tables based on the models of your db. It will expose a helper method `easy_data_table(columns, rows, grouping)`that will output a datatable with the rows and the columns you indicated.
4
4
 
5
+ Two links above and below the table will allow you to export it on csv format
6
+
5
7
  ## Installation
6
8
 
7
9
  Add this line to your application's Gemfile:
@@ -24,6 +26,11 @@ Or install it yourself as:
24
26
 
25
27
  You will have a method available once you install this gem: `easy_data_table(columns, rows, grouping)` in order to expose it, you need to add `helper EasyDataTables::Engine.helpers` to your app's ApplicationController. You can call this helper method in any view and it will output a table with the data you provide.
26
28
 
29
+ In order to access the style of the application add:
30
+ `@import "easy_data_tables/application";`
31
+
32
+ to your `application.scss`
33
+
27
34
  ### Parameters
28
35
 
29
36
  #### Columns
@@ -108,14 +115,18 @@ in order to have correct looking column labels you must have a I18n file that wi
108
115
  en:
109
116
  easy_data_tables:
110
117
  data_table:
111
- user_count: User count
112
- user_count_title: "Count of all the users that have the row's status"
113
- active_user_count: Active User Count
114
- active_user_count_title: Active users for each status
115
- active_user_expense: Active User Expense
116
- active_user_expense_title: Sum of the expenses for the active users of each status
117
- active_user_rate: Active User Rate
118
- active_user_rate_title: % of active users over total users per status
118
+ user_count: User count
119
+ user_count_title: "Count of all the users that have the row's status"
120
+ active_user_count: Active User Count
121
+ active_user_count_title: Active users for each status
122
+ active_user_expense: Active User Expense
123
+ active_user_expense_title: Sum of the expenses for the active users of each status
124
+ active_user_rate: Active User Rate
125
+ active_user_rate_title: % of active users over total users per status
126
+ download_links:
127
+ download_formated_csv: Download Formated CSV
128
+ download_unformated_csv: Download Unformated CSV
129
+
119
130
  ```
120
131
 
121
132
  On hover on a column label, you will have the title that appears as a tooltip.
@@ -141,3 +152,8 @@ Bug reports and pull requests are welcome on GitHub at https://github.com/pabloc
141
152
  ## License
142
153
 
143
154
  The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
155
+
156
+ ## Changelog
157
+
158
+ ### v 0.2.0
159
+ - added possibility of downloading the table as a csv (both formated and unformated)
data/Rakefile CHANGED
@@ -1,8 +1,20 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require 'bundler/setup'
4
+
5
+ APP_RAKEFILE = File.expand_path('test/dummy/Rakefile', __dir__)
6
+ load 'rails/tasks/engine.rake'
7
+
8
+ load 'rails/tasks/statistics.rake'
9
+
3
10
  require 'bundler/gem_tasks'
4
- require 'rspec/core/rake_task'
5
11
 
6
- RSpec::Core::RakeTask.new(:spec)
12
+ require 'rake/testtask'
13
+
14
+ Rake::TestTask.new(:test) do |t|
15
+ t.libs << 'test'
16
+ t.pattern = 'test/**/*_test.rb'
17
+ t.verbose = false
18
+ end
7
19
 
8
- task default: :spec
20
+ task default: :test
@@ -0,0 +1,5 @@
1
+ .easy-data-tables__links {
2
+ display: flex;
3
+ padding: 5px;
4
+ gap: 5px;
5
+ }
@@ -0,0 +1,15 @@
1
+ # frozen_string_literal: true
2
+
3
+ module EasyDataTables
4
+ # Creates and exposes the helper method
5
+ module TableHelper
6
+ def easy_data_table(columns, label, grouping)
7
+ data_table = DataTable.new(
8
+ columns,
9
+ label,
10
+ grouping
11
+ )
12
+ render 'easy_data_tables/data_table', data_table: data_table
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,48 @@
1
+ # frozen_string_literal: true
2
+
3
+ module EasyDataTables
4
+ # Column class, we can access the formated data and the data of a particular cell
5
+ class Column
6
+ attr_reader :label
7
+
8
+ # values = {}, label = '', type = 'Integer')
9
+ def initialize(args = {})
10
+ @label = args[:label] || ''
11
+ @type = args[:type] || 'Integer'
12
+ @default = args[:default] || 0
13
+ @collection = args[:collection]
14
+ @grouping = args[:grouping]
15
+ @agregate_function = args[:agregate_function]
16
+ @values = construct_values
17
+ end
18
+
19
+ def formated_data_at(row)
20
+ case @type
21
+ when 'Integer'
22
+ helpers.number_with_delimiter(data_at(row))
23
+ when 'Percentage'
24
+ helpers.number_to_percentage(data_at(row), precision: 2)
25
+ when 'Currency'
26
+ helpers.number_to_currency(data_at(row))
27
+ else
28
+ data_at(row)
29
+ end
30
+ end
31
+
32
+ def data_at(row)
33
+ @values[row]
34
+ end
35
+
36
+ private
37
+
38
+ def construct_values
39
+ Hash.new(@default)
40
+ .merge(@collection.send(*@grouping).send(*@agregate_function))
41
+ .merge({ 'TOTAL' => @collection.send(*@agregate_function) })
42
+ end
43
+
44
+ def helpers
45
+ ActionController::Base.helpers
46
+ end
47
+ end
48
+ end
@@ -0,0 +1,37 @@
1
+ # frozen_string_literal: true
2
+
3
+ module EasyDataTables
4
+ # combined columns. can substract and create rates
5
+ class CombinedColumn < EasyDataTables::Column
6
+ attr_accessor :columns
7
+
8
+ def initialize(args = {})
9
+ super(args)
10
+ @columns = args[:columns]
11
+ @method = args[:method]
12
+ @type = args[:type]
13
+ @label = args[:label]
14
+ end
15
+
16
+ def data_at(row)
17
+ combine(row)
18
+ end
19
+
20
+ private
21
+
22
+ def combine(row)
23
+ case @method
24
+ when 'rate'
25
+ columns[0].data_at(row).fdiv(columns[1].data_at(row)) * 100
26
+ when 'substract'
27
+ columns[0].data_at(row) - columns[1].data_at(row)
28
+ end
29
+ end
30
+
31
+ def construct_values; end
32
+
33
+ def helpers
34
+ ActionController::Base.helpers
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,39 @@
1
+ # frozen_string_literal: true
2
+
3
+ module EasyDataTables
4
+ # creates the datatable and it's columns
5
+ class DataTable
6
+ attr_reader :columns, :rows, :labels
7
+
8
+ def initialize(columns, rows, grouping)
9
+ @grouping = grouping
10
+ @rows = rows + ['TOTAL']
11
+ @columns = treat_columns(columns)
12
+ @labels = @columns.map(&:label)
13
+ end
14
+
15
+ private
16
+
17
+ def treat_columns(columns)
18
+ convert_columns(columns)
19
+ columns.map! do |col|
20
+ if col.is_a?(CombinedColumn)
21
+ col.columns = columns.find_all { |col2| col.columns.include?(col2.label) }.sort do |column|
22
+ col.columns.index(column.label)
23
+ end
24
+ end
25
+ col
26
+ end
27
+ end
28
+
29
+ def convert_columns(columns)
30
+ columns.map! do |col|
31
+ if col[:column_type] == 'combined'
32
+ CombinedColumn.new(col)
33
+ else
34
+ Column.new(col.merge(grouping: @grouping))
35
+ end
36
+ end
37
+ end
38
+ end
39
+ end
@@ -1,4 +1,5 @@
1
- <table class="table datatable" data-controller="datatable">
1
+ <%= render 'easy_data_tables/download_links' %>
2
+ <table class="table datatable" id="easy_data_table" data-controller="datatable">
2
3
  <thead>
3
4
  <tr>
4
5
  <th></th>
@@ -16,11 +17,68 @@
16
17
  <%= row %>
17
18
  </td>
18
19
  <% data_table.columns.each do |column| %>
19
- <td>
20
+ <td data-unformated-value="<%= column.data_at(row) %>">
20
21
  <%= column.formated_data_at(row) %>
21
22
  </td>
22
23
  <% end %>
23
24
  </tr>
24
25
  <% end %>
25
26
  </tbody>
26
- </table>
27
+ </table>
28
+
29
+ <%= render 'easy_data_tables/download_links' %>
30
+
31
+ <script>
32
+ // Quick and simple export target #table_id into a csv
33
+ function download_unformated_table_as_csv(table_id, separator = ',') {
34
+ const rows = document.querySelectorAll('table#' + table_id + ' tr');
35
+ const csv = [];
36
+ for (let i = 0; i < rows.length; i++) {
37
+ let row = []
38
+ let cols = rows[i].querySelectorAll('td, th');
39
+ for (let j = 0; j < cols.length; j++) {
40
+ let data;
41
+ if (cols[j].dataset.unformatedValue) {
42
+ data = cols[j].dataset.unformatedValue
43
+ }
44
+ else {
45
+ data = cols[j].innerText.replace(/(\r\n|\n|\r)/gm, '').replace(/(\s\s)/gm, ' ')
46
+ }
47
+ data = data.replace(/"/g, '""');
48
+ row.push('"' + data + '"');
49
+ }
50
+ csv.push(row.join(separator));
51
+ }
52
+ createLink(csv, table_id)
53
+ }
54
+
55
+ function download_formated_table_as_csv(table_id, separator = ',') {
56
+ const rows = document.querySelectorAll('table#' + table_id + ' tr');
57
+ const csv = [];
58
+ for (let i = 0; i < rows.length; i++) {
59
+ let row = []
60
+ let cols = rows[i].querySelectorAll('td, th');
61
+ for (let j = 0; j < cols.length; j++) {
62
+ let data = cols[j].innerText.replace(/(\r\n|\n|\r)/gm, '').replace(/(\s\s)/gm, ' ')
63
+ data = data.replace(/"/g, '""');
64
+ row.push('"' + data + '"');
65
+ }
66
+ csv.push(row.join(separator));
67
+ }
68
+ createLink(csv, table_id)
69
+ }
70
+
71
+ function createLink(csv, table_id) {
72
+ const csv_string = csv.join('\n');
73
+ // Download it
74
+ const filename = 'export_' + table_id + '_' + new Date().toLocaleDateString() + '.csv';
75
+ const link = document.createElement('a');
76
+ link.style.display = 'none';
77
+ link.setAttribute('target', '_blank');
78
+ link.setAttribute('href', 'data:text/csv;charset=utf-8,' + encodeURIComponent(csv_string));
79
+ link.setAttribute('download', filename);
80
+ document.body.appendChild(link);
81
+ link.click();
82
+ document.body.removeChild(link);
83
+ }
84
+ </script>
@@ -0,0 +1,5 @@
1
+ <div class="easy-data-tables__links">
2
+ <a href="#" onclick="download_unformated_table_as_csv('easy_data_table');"><%= t('.download_unformated_csv') %></a>
3
+ <span> | </span>
4
+ <a href="#" onclick="download_formated_table_as_csv('easy_data_table');"><%= t('.download_formated_csv') %></a>
5
+ </div>
@@ -14,7 +14,7 @@ Gem::Specification.new do |spec|
14
14
  spec.license = 'MIT'
15
15
  spec.required_ruby_version = Gem::Requirement.new('>= 2.4.0')
16
16
 
17
- spec.metadata['allowed_push_host'] = "https://rubygems.org/"
17
+ spec.metadata['allowed_push_host'] = 'https://rubygems.org/'
18
18
 
19
19
  spec.metadata['homepage_uri'] = spec.homepage
20
20
  spec.metadata['source_code_uri'] = 'https://github.com/pablocm90/easy_data_tables'
@@ -1,10 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require 'easy_data_tables/version'
4
- # require "app/helpers/helper"
5
4
  require 'easy_data_tables/engine'
6
- # require "easy_data_tables/models/column"
7
- # require "easy_data_tables/models/combined_column"
8
5
 
9
6
  module EasyDataTables
10
7
  class Error < StandardError; end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module EasyDataTables
4
- VERSION = '0.1.1'
4
+ VERSION = '0.2.0'
5
5
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: easy_data_tables
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.1
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Pablo Curell
@@ -26,11 +26,13 @@ files:
26
26
  - LICENSE.txt
27
27
  - README.md
28
28
  - Rakefile
29
- - app/helpers/table_helper.rb
30
- - app/models/column.rb
31
- - app/models/combined_column.rb
32
- - app/models/data_table.rb
29
+ - app/assets/stylesheets/easy_data_tables/application.css
30
+ - app/helpers/easy_data_tables/table_helper.rb
31
+ - app/models/easy_data_tables/column.rb
32
+ - app/models/easy_data_tables/combined_column.rb
33
+ - app/models/easy_data_tables/data_table.rb
33
34
  - app/views/easy_data_tables/_data_table.html.erb
35
+ - app/views/easy_data_tables/_download_links.html.erb
34
36
  - bin/rails
35
37
  - easy_data_tables.gemspec
36
38
  - lib/easy_data_tables.rb
@@ -1,13 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- # Creates and exposes the helper method
4
- module TableHelper
5
- def easy_data_table(columns, label, grouping)
6
- data_table = DataTable.new(
7
- columns,
8
- label,
9
- grouping
10
- )
11
- render 'easy_data_tables/data_table', data_table: data_table
12
- end
13
- end
data/app/models/column.rb DELETED
@@ -1,46 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- # Column class, we can access the formated data and the data of a particular cell
4
- class Column
5
- attr_reader :label
6
-
7
- # values = {}, label = '', type = 'Integer')
8
- def initialize(args = {})
9
- @label = args[:label] || ''
10
- @type = args[:type] || 'Integer'
11
- @default = args[:default] || 0
12
- @collection = args[:collection]
13
- @grouping = args[:grouping]
14
- @agregate_function = args[:agregate_function]
15
- @values = construct_values
16
- end
17
-
18
- def formated_data_at(row)
19
- case @type
20
- when 'Integer'
21
- helpers.number_with_delimiter(data_at(row))
22
- when 'Percentage'
23
- helpers.number_to_percentage(data_at(row), precision: 2)
24
- when 'Currency'
25
- helpers.number_to_currency(data_at(row))
26
- else
27
- data_at(row)
28
- end
29
- end
30
-
31
- def data_at(row)
32
- @values[row]
33
- end
34
-
35
- private
36
-
37
- def construct_values
38
- Hash.new(@default)
39
- .merge(@collection.send(*@grouping).send(*@agregate_function))
40
- .merge({ 'TOTAL' => @collection.send(*@agregate_function) })
41
- end
42
-
43
- def helpers
44
- ActionController::Base.helpers
45
- end
46
- end
@@ -1,35 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- # combined columns. can substract and create rates
4
- class CombinedColumn < Column
5
- attr_accessor :columns
6
-
7
- def initialize(args = {})
8
- super(args)
9
- @columns = args[:columns]
10
- @method = args[:method]
11
- @type = args[:type]
12
- @label = args[:label]
13
- end
14
-
15
- def data_at(row)
16
- combine(row)
17
- end
18
-
19
- private
20
-
21
- def combine(row)
22
- case @method
23
- when 'rate'
24
- columns[0].data_at(row).fdiv(columns[1].data_at(row)) * 100
25
- when 'substract'
26
- columns[0].data_at(row) - columns[1].data_at(row)
27
- end
28
- end
29
-
30
- def construct_values; end
31
-
32
- def helpers
33
- ActionController::Base.helpers
34
- end
35
- end
@@ -1,37 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- # creates the datatable and it's columns
4
- class DataTable
5
- attr_reader :columns, :rows, :labels
6
-
7
- def initialize(columns, rows, grouping)
8
- @grouping = grouping
9
- @rows = rows + ['TOTAL']
10
- @columns = treat_columns(columns)
11
- @labels = @columns.map(&:label)
12
- end
13
-
14
- private
15
-
16
- def treat_columns(columns)
17
- convert_columns(columns)
18
- columns.map! do |col|
19
- if col.is_a?(CombinedColumn)
20
- col.columns = columns.find_all { |col2| col.columns.include?(col2.label) }.sort do |column|
21
- col.columns.index(column.label)
22
- end
23
- end
24
- col
25
- end
26
- end
27
-
28
- def convert_columns(columns)
29
- columns.map! do |col|
30
- if col[:column_type] == 'combined'
31
- CombinedColumn.new(col)
32
- else
33
- Column.new(col.merge(grouping: @grouping))
34
- end
35
- end
36
- end
37
- end