easy_data_tables 0.1.1 → 0.2.0

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