activeadmin_dynamic_table 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: ec7d176dc20e3cb34be2eae984bf87e6c790a3fa79bc61fde512e27b67ce15c9
4
+ data.tar.gz: bcc2afb91378be40321f206d2ac9d8d284ed22ad213864d1540f542f090e25f1
5
+ SHA512:
6
+ metadata.gz: ab184ef277fda19e363634353292983632793e88009ebdd08a071b9f92c226d1bce53461dc43f9c1f42fa19c4a8f1ef954befcd0370b2723b8c6d73b4667f1cf
7
+ data.tar.gz: e550f74ca22cd8099454e7790c0119803f8a07bb823282c42b9b7aa6d1249a24e4e4f87e6acc0315e39c7acd06a5e0c08f40920e76337750fd2f44c80ef36436
data/Gemfile ADDED
@@ -0,0 +1,8 @@
1
+ # frozen_string_literal: true
2
+
3
+ source "https://rubygems.org"
4
+
5
+ # Specify your gem's dependencies in activeadmin_dynamic_table.gemspec
6
+ gemspec
7
+
8
+ gem "rake", "~> 13.0"
data/Gemfile.lock ADDED
@@ -0,0 +1,123 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ activeadmin_dynamic_table (0.1.0)
5
+ activeadmin (~> 2.9)
6
+
7
+ GEM
8
+ remote: https://rubygems.org/
9
+ specs:
10
+ actionpack (7.0.3)
11
+ actionview (= 7.0.3)
12
+ activesupport (= 7.0.3)
13
+ rack (~> 2.0, >= 2.2.0)
14
+ rack-test (>= 0.6.3)
15
+ rails-dom-testing (~> 2.0)
16
+ rails-html-sanitizer (~> 1.0, >= 1.2.0)
17
+ actionview (7.0.3)
18
+ activesupport (= 7.0.3)
19
+ builder (~> 3.1)
20
+ erubi (~> 1.4)
21
+ rails-dom-testing (~> 2.0)
22
+ rails-html-sanitizer (~> 1.1, >= 1.2.0)
23
+ activeadmin (2.13.1)
24
+ arbre (~> 1.2, >= 1.2.1)
25
+ formtastic (>= 3.1, < 5.0)
26
+ formtastic_i18n (~> 0.4)
27
+ inherited_resources (~> 1.7)
28
+ jquery-rails (~> 4.2)
29
+ kaminari (~> 1.0, >= 1.2.1)
30
+ railties (>= 6.1, < 7.1)
31
+ ransack (>= 2.1.1, < 4)
32
+ activemodel (7.0.3)
33
+ activesupport (= 7.0.3)
34
+ activerecord (7.0.3)
35
+ activemodel (= 7.0.3)
36
+ activesupport (= 7.0.3)
37
+ activesupport (7.0.3)
38
+ concurrent-ruby (~> 1.0, >= 1.0.2)
39
+ i18n (>= 1.6, < 2)
40
+ minitest (>= 5.1)
41
+ tzinfo (~> 2.0)
42
+ arbre (1.5.0)
43
+ activesupport (>= 3.0.0, < 7.1)
44
+ ruby2_keywords (>= 0.0.2, < 1.0)
45
+ builder (3.2.4)
46
+ concurrent-ruby (1.1.10)
47
+ crass (1.0.6)
48
+ erubi (1.10.0)
49
+ formtastic (4.0.0)
50
+ actionpack (>= 5.2.0)
51
+ formtastic_i18n (0.7.0)
52
+ has_scope (0.8.0)
53
+ actionpack (>= 5.2)
54
+ activesupport (>= 5.2)
55
+ i18n (1.8.11)
56
+ concurrent-ruby (~> 1.0)
57
+ inherited_resources (1.13.1)
58
+ actionpack (>= 5.2, < 7.1)
59
+ has_scope (~> 0.6)
60
+ railties (>= 5.2, < 7.1)
61
+ responders (>= 2, < 4)
62
+ jquery-rails (4.5.0)
63
+ rails-dom-testing (>= 1, < 3)
64
+ railties (>= 4.2.0)
65
+ thor (>= 0.14, < 2.0)
66
+ kaminari (1.2.2)
67
+ activesupport (>= 4.1.0)
68
+ kaminari-actionview (= 1.2.2)
69
+ kaminari-activerecord (= 1.2.2)
70
+ kaminari-core (= 1.2.2)
71
+ kaminari-actionview (1.2.2)
72
+ actionview
73
+ kaminari-core (= 1.2.2)
74
+ kaminari-activerecord (1.2.2)
75
+ activerecord
76
+ kaminari-core (= 1.2.2)
77
+ kaminari-core (1.2.2)
78
+ loofah (2.18.0)
79
+ crass (~> 1.0.2)
80
+ nokogiri (>= 1.5.9)
81
+ method_source (1.0.0)
82
+ minitest (5.15.0)
83
+ nokogiri (1.11.5-arm64-darwin)
84
+ racc (~> 1.4)
85
+ racc (1.6.0)
86
+ rack (2.2.3.1)
87
+ rack-test (1.1.0)
88
+ rack (>= 1.0, < 3)
89
+ rails-dom-testing (2.0.3)
90
+ activesupport (>= 4.2.0)
91
+ nokogiri (>= 1.6)
92
+ rails-html-sanitizer (1.4.2)
93
+ loofah (~> 2.3)
94
+ railties (7.0.3)
95
+ actionpack (= 7.0.3)
96
+ activesupport (= 7.0.3)
97
+ method_source
98
+ rake (>= 12.2)
99
+ thor (~> 1.0)
100
+ zeitwerk (~> 2.5)
101
+ rake (13.0.6)
102
+ ransack (2.5.0)
103
+ activerecord (>= 5.2.4)
104
+ activesupport (>= 5.2.4)
105
+ i18n
106
+ responders (3.0.1)
107
+ actionpack (>= 5.0)
108
+ railties (>= 5.0)
109
+ ruby2_keywords (0.0.5)
110
+ thor (1.2.1)
111
+ tzinfo (2.0.4)
112
+ concurrent-ruby (~> 1.0)
113
+ zeitwerk (2.5.4)
114
+
115
+ PLATFORMS
116
+ arm64-darwin-21
117
+
118
+ DEPENDENCIES
119
+ activeadmin_dynamic_table!
120
+ rake (~> 13.0)
121
+
122
+ BUNDLED WITH
123
+ 2.3.4
data/LICENSE.txt ADDED
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2024 Anton Biliaiev
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in
13
+ all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,39 @@
1
+ # ActiveadminDynamicTable
2
+
3
+ Welcome to your new gem! In this directory, you'll find the files you need to be able to package up your Ruby library into a gem. Put your Ruby code in the file `lib/activeadmin_dynamic_table`. To experiment with that code, run `bin/console` for an interactive prompt.
4
+
5
+ TODO: Delete this and the text above, and describe your gem
6
+
7
+ ## Installation
8
+
9
+ Add this line to your application's Gemfile:
10
+
11
+ ```ruby
12
+ gem 'activeadmin_dynamic_table'
13
+ ```
14
+
15
+ And then execute:
16
+
17
+ $ bundle install
18
+
19
+ Or install it yourself as:
20
+
21
+ $ gem install activeadmin_dynamic_table
22
+
23
+ ## Usage
24
+
25
+ TODO: Write usage instructions here
26
+
27
+ ## Development
28
+
29
+ After checking out the repo, run `bin/setup` to install dependencies. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
30
+
31
+ To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and the created tag, and push the `.gem` file to [rubygems.org](https://rubygems.org).
32
+
33
+ ## Contributing
34
+
35
+ Bug reports and pull requests are welcome on GitHub at https://github.com/[USERNAME]/activeadmin_dynamic_table.
36
+
37
+ ## License
38
+
39
+ The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
data/Rakefile ADDED
@@ -0,0 +1,4 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "bundler/gem_tasks"
4
+ task default: %i[]
@@ -0,0 +1,38 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "lib/activeadmin_dynamic_table/version"
4
+
5
+ Gem::Specification.new do |spec|
6
+ spec.name = "activeadmin_dynamic_table"
7
+ spec.version = ActiveadminDynamicTable::VERSION
8
+ spec.authors = ["Anton Biliaiev"]
9
+ spec.email = ["amdj15@gmail.com"]
10
+
11
+ spec.summary = ""
12
+ spec.description = ""
13
+ spec.homepage = ""
14
+ spec.license = "MIT"
15
+ spec.required_ruby_version = ">= 2.6.0"
16
+
17
+ # spec.metadata["allowed_push_host"] = "TODO: Set to your gem server 'https://example.com'"
18
+ # spec.metadata["homepage_uri"] = spec.homepage
19
+ # spec.metadata["source_code_uri"] = "TODO: Put your gem's public repo URL here."
20
+ # spec.metadata["changelog_uri"] = "TODO: Put your gem's CHANGELOG.md URL here."
21
+
22
+ # Specify which files should be added to the gem when it is released.
23
+ # The `git ls-files -z` loads the files in the RubyGem that have been added into git.
24
+ spec.files = Dir.chdir(File.expand_path(__dir__)) do
25
+ `git ls-files -z`.split("\x0").reject do |f|
26
+ (f == __FILE__) || f.match(%r{\A(?:(?:test|spec|features)/|\.(?:git|travis|circleci)|appveyor)})
27
+ end
28
+ end
29
+ spec.bindir = "exe"
30
+ spec.executables = spec.files.grep(%r{\Aexe/}) { |f| File.basename(f) }
31
+ spec.require_paths = ["lib"]
32
+
33
+ # Uncomment to register a new dependency of your gem
34
+ spec.add_dependency "activeadmin", "~> 2.9"
35
+
36
+ # For more information and examples about making a new gem, check out our
37
+ # guide at: https://bundler.io/guides/creating_gem.html
38
+ end
@@ -0,0 +1 @@
1
+ //= require ./dynamic_table
@@ -0,0 +1,144 @@
1
+ $(function() {
2
+ const preferencesBtn = $('th.col-table-preferences');
3
+ const tableConfig = $('ul.dynamic_table_configuration');
4
+
5
+ const columnsPattern = 'th[data-column-key]';
6
+ const columns = $(columnsPattern);
7
+
8
+ if (tableConfig.length) {
9
+ $('#wrapper').css('display', 'block')
10
+ }
11
+
12
+ function parseSearchString(searchString) {
13
+ return searchString.split('&').reduce((acc, keyval) => {
14
+ const [key, value] = keyval.split('=');
15
+
16
+ if (!key || !value) {
17
+ return acc;
18
+ }
19
+
20
+ acc[key] = value;
21
+
22
+ return acc;
23
+ }, {});
24
+ }
25
+
26
+ function stringifyParams(params) {
27
+ const data = filterEmptyKeys(params);
28
+ const prefix = '?';
29
+ const searchString = Object.keys(data).map((key) => [key, data[key]].join('=')).join('&');
30
+
31
+ return searchString ? prefix + searchString : '';
32
+ }
33
+
34
+ function columnsConfigString(keys, sizes = {}) {
35
+ const str = keys.map(key => {
36
+ if (sizes[key]) {
37
+ return [key, 'w' + sizes[key]].join(':');
38
+ }
39
+
40
+ return key;
41
+ }).join(';');
42
+
43
+ return encodeURIComponent(str);
44
+ }
45
+
46
+ function getSearchParams() {
47
+ const searchString = decodeURIComponent(window.location.search).slice(1);
48
+
49
+ return parseSearchString(searchString);
50
+ }
51
+
52
+ function getColumnsWidths() {
53
+ return columns.map(function() {
54
+ const elem = $(this)
55
+
56
+ return {
57
+ width: elem.width(),
58
+ key: elem.data('column-key'),
59
+ };
60
+ })
61
+ .toArray()
62
+ .reduce((acc, item) => Object.assign(acc, { [item.key]: item.width }), {});
63
+ }
64
+
65
+ function filterEmptyKeys(params) {
66
+ return Object.keys(params).reduce((acc, key) => {
67
+ if (!params[key]) {
68
+ return acc;
69
+ }
70
+
71
+ acc[key] = params[key];
72
+ return acc;
73
+ }, {});
74
+ }
75
+
76
+ preferencesBtn.on('click', function() {
77
+ const offset = preferencesBtn.offset();
78
+ offset.top += preferencesBtn.outerHeight();
79
+
80
+ tableConfig.removeClass('hidden').offset(offset);
81
+
82
+ return false;
83
+ });
84
+
85
+ document.addEventListener('click', () => {
86
+ if (!tableConfig.length || tableConfig.hasClass('hidden')) {
87
+ return;
88
+ }
89
+
90
+ const selected = tableConfig.find('input').filter(function() {
91
+ return $(this).is(':checked');
92
+ }).map(function() {
93
+ return $(this).attr('name');
94
+ }).toArray();
95
+
96
+ const current = $(columnsPattern).map(function() {
97
+ return $(this).data('column-key');
98
+ }).toArray().filter(key => selected.includes(key));
99
+
100
+ const diff = selected.filter(key => !current.includes(key));
101
+
102
+ const columnSizes = getColumnsWidths();
103
+ const params = Object.assign(getSearchParams(), {
104
+ columns: columnsConfigString(current.concat(diff), columnSizes),
105
+ });
106
+ const searchString = stringifyParams(params);
107
+
108
+ tableConfig.addClass('hidden');
109
+ window.location.search = searchString;
110
+ });
111
+
112
+ tableConfig.on('click', function(event) {
113
+ event.stopPropagation();
114
+ });
115
+
116
+ columns.resizable({
117
+ stop: function() {
118
+ const columnSizes = getColumnsWidths();
119
+ const params = Object.assign(getSearchParams(), {
120
+ columns: columnsConfigString(Object.keys(columnSizes), columnSizes),
121
+ });
122
+
123
+ const searchString = stringifyParams(params);
124
+ window.location.search = searchString;
125
+ },
126
+ });
127
+
128
+ $('.index_as_dynamic_table thead tr').sortable({
129
+ axis: 'x',
130
+ update: function() {
131
+ const columnSizes = getColumnsWidths();
132
+ const keys = $(columnsPattern).map(function() {
133
+ return $(this).data('column-key');
134
+ }).toArray();
135
+
136
+ const params = Object.assign(getSearchParams(), {
137
+ columns: columnsConfigString(keys, columnSizes),
138
+ });
139
+
140
+ const searchString = stringifyParams(params);
141
+ window.location.search = searchString;
142
+ },
143
+ });
144
+ });
@@ -0,0 +1,42 @@
1
+ .index_as_dynamic_table {
2
+ position: relative;
3
+ overflow: auto;
4
+
5
+ .hidden {
6
+ display: none;
7
+ }
8
+
9
+ .col-table-preferences {
10
+ cursor: pointer;
11
+ }
12
+
13
+ .dynamic_table_configuration {
14
+ position: absolute;
15
+ background: #fff;
16
+ padding: 8px;
17
+ border: 1px solid #c9d0d6;
18
+ width: max-content;
19
+ }
20
+
21
+ .dynamic_table {
22
+ table-layout: fixed;
23
+ width: min-content;
24
+ }
25
+
26
+ .reorder {
27
+ cursor: move;
28
+ }
29
+
30
+ th {
31
+ position: relative;
32
+
33
+ .ui-resizable-e {
34
+ cursor: e-resize;
35
+ width: 7px;
36
+ right: -5px;
37
+ top: 0;
38
+ height: 100%;
39
+ position: absolute;
40
+ }
41
+ }
42
+ }
data/bin/console ADDED
@@ -0,0 +1,15 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ require "bundler/setup"
5
+ require "activeadmin_dynamic_table"
6
+
7
+ # You can add fixtures and/or initialization code here to make experimenting
8
+ # with your gem easier. You can also use a different console, if you like.
9
+
10
+ # (If you use this, don't forget to add pry to your Gemfile!)
11
+ # require "pry"
12
+ # Pry.start
13
+
14
+ require "irb"
15
+ IRB.start(__FILE__)
data/bin/setup ADDED
@@ -0,0 +1,8 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+ IFS=$'\n\t'
4
+ set -vx
5
+
6
+ bundle install
7
+
8
+ # Do any other automated setup that you need to do here
@@ -0,0 +1,49 @@
1
+ # frozen_string_literal: true
2
+ module ActiveadminDynamicTable
3
+ class RegisteredColumn
4
+ attr_reader :key, :args, :block, :config, :method
5
+
6
+ def initialize(options)
7
+ @is_default = options[:is_default]
8
+ @key = options[:key]
9
+ @args = options[:args]
10
+ @block = options[:block]
11
+ @config = options[:config]
12
+ @method = options[:method]
13
+ end
14
+
15
+ def default?
16
+ @is_default
17
+ end
18
+ end
19
+
20
+ class ColumnSettings
21
+ def initialize(column, options = [])
22
+ @column = column
23
+ @options = options
24
+ end
25
+
26
+ def column
27
+ @column.to_sym
28
+ end
29
+
30
+ def width
31
+ raw_width = @options.detect { |o| o[0] == 'w' }
32
+
33
+ return default_width if raw_width.nil?
34
+
35
+ width = raw_width[1..-1]
36
+ width.to_i if Float(width)
37
+ rescue
38
+ default_width
39
+ end
40
+
41
+ def default_width
42
+ @default_width || 50
43
+ end
44
+
45
+ def default_width=(value)
46
+ @default_width = value
47
+ end
48
+ end
49
+ end
@@ -0,0 +1,92 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ActiveadminDynamicTable
4
+ class Configurator
5
+ def initialize(context, settings)
6
+ @context = context
7
+ @settings = settings
8
+ @api_calls = []
9
+ end
10
+
11
+ def register_column(method, *args, &block)
12
+ options = args[1] || args[0]
13
+
14
+ config = settings_hash[options[:key]] || ColumnSettings.new(options[:key])
15
+ config.default_width = options[:width]
16
+
17
+ api_call = RegisteredColumn.new method: method,
18
+ key: options[:key],
19
+ is_default: options[:default],
20
+ args: args,
21
+ block: block,
22
+ config: config
23
+
24
+ @api_calls << api_call
25
+ end
26
+
27
+ def columns
28
+ applicable_columns.each do |applicable_column|
29
+ next @context.id_column *applicable_column.args if applicable_column.method == :id_column
30
+ next @context.actions(applicable_column.args[1] || applicable_column.args[0]) if applicable_column.method == :actions
31
+ next @context.index_column *applicable_column.args if applicable_column.method == :index_column
32
+
33
+ # next @context.selectable_column *applicable_column.args if applicable_column.method == :selectable_column
34
+
35
+ @context.public_send(applicable_column.method, *applicable_column.args, &applicable_column.block)
36
+ end
37
+ end
38
+
39
+ def applicable_columns
40
+ applicable_columns = []
41
+
42
+ settings.each do |config|
43
+ applicable_column = @api_calls.detect do |register_call|
44
+ register_call.key == config.column
45
+ end
46
+
47
+ applicable_columns << applicable_column if applicable_column.present?
48
+ end
49
+
50
+ applicable_columns
51
+ end
52
+
53
+ def registered_columns
54
+ @api_calls.map do |api_call|
55
+ args = api_call.args
56
+
57
+ {
58
+ key: api_call.key,
59
+ selected: selected?(api_call.key),
60
+ args: args,
61
+ }
62
+ end
63
+ end
64
+
65
+ def width_for(key)
66
+ col = settings_hash[key]
67
+
68
+ return ColumnSettings.new(nil).width if col.nil?
69
+
70
+ col.width
71
+ end
72
+
73
+ private
74
+
75
+ def selected?(key)
76
+ settings_hash[key].present?
77
+ end
78
+
79
+ def settings_hash
80
+ settings.inject({}) do |acc, item|
81
+ acc[item.column] = item
82
+ acc
83
+ end
84
+ end
85
+
86
+ def settings
87
+ return @settings if @settings.size > 0
88
+
89
+ @api_calls.select { |rc| rc.default? }.map { |rc| rc.config }
90
+ end
91
+ end
92
+ end
@@ -0,0 +1,19 @@
1
+ module ActiveadminDynamicTable
2
+ class SettingStringParser
3
+ def initialize(settings_string)
4
+ @settings_string = settings_string
5
+ end
6
+
7
+ def parse
8
+ return [] if @settings_string.nil?
9
+
10
+ columns = @settings_string.split(';')
11
+
12
+ columns.map do |col|
13
+ name, *options = col.split(':')
14
+
15
+ ColumnSettings.new(name, options)
16
+ end
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ActiveadminDynamicTable
4
+ VERSION = "0.1.0"
5
+ end
@@ -0,0 +1,175 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ActiveAdmin::Views
4
+ class IndexAsDynamicTable < IndexAsTable
5
+ class IndexDynamicTableFor < IndexTableFor
6
+ def build(configurator, *args, &block)
7
+ @configurator = configurator
8
+ super(*args, &block)
9
+ end
10
+
11
+ def build_table_header(col)
12
+ sort_key = sortable? && col.sortable? && col.sort_key
13
+ params = request.query_parameters.except :page, :order, :commit, :format
14
+ options = options_for_col(col, sort_key)
15
+
16
+ if sort_key
17
+ th options do
18
+ span do
19
+ link_to col.pretty_title, params: params, order: "#{sort_key}_#{order_for_sort_key(sort_key)}"
20
+ end
21
+ end
22
+ else
23
+ th options do
24
+ span col.pretty_title
25
+ end
26
+ end
27
+ end
28
+
29
+ def options_for_col(col, sort_key)
30
+ classes = Arbre::HTML::ClassList.new
31
+ classes << "sortable" if sort_key
32
+ classes << "sorted-#{current_sort[1]}" if sort_key && current_sort[0] == sort_key
33
+ classes << "reorder"
34
+ classes << col.html_class
35
+
36
+ options = col.instance_variable_get(:@options)
37
+ style = options[:style] || ''
38
+ style = "width: #{@configurator.width_for(options[:key])}px" if options[:key].present?
39
+
40
+ {
41
+ class: classes,
42
+ style: style,
43
+ 'data-column-key': options[:key],
44
+ }
45
+ end
46
+
47
+ # Display a column for checkbox
48
+ def selectable_column
49
+ return unless active_admin_config.batch_actions.any?
50
+
51
+ options = {
52
+ style: "width: 30px",
53
+ class: "col-selectable",
54
+ sortable: false,
55
+ }
56
+
57
+ column resource_selection_toggle_cell, options do |resource|
58
+ resource_selection_cell resource
59
+ end
60
+ end
61
+
62
+ # Display a column for the id
63
+ def id_column(*args)
64
+ raise "#{resource_class.name} has no primary_key!" unless resource_class.primary_key
65
+ data = args[1] || args[0]
66
+
67
+ options = {
68
+ sortable: resource_class.primary_key,
69
+ 'data-column-key': data[:key],
70
+ **data,
71
+ }
72
+
73
+ column(resource_class.human_attribute_name(resource_class.primary_key), options) do |resource|
74
+ if controller.action_methods.include?("show")
75
+ link_to resource.id, resource_path(resource), class: "resource_id_link"
76
+ elsif controller.action_methods.include?("edit")
77
+ link_to resource.id, edit_resource_path(resource), class: "resource_id_link"
78
+ else
79
+ resource.id
80
+ end
81
+ end
82
+ end
83
+
84
+ def index_column(*args)
85
+ data = args[1] || args[0]
86
+ start_value = data.delete(:start_value) || 1
87
+
88
+ options = {
89
+ class: "col-index",
90
+ sortable: false,
91
+ **data,
92
+ }
93
+
94
+ column "#", options do |resource|
95
+ @collection.offset_value + @collection.index(resource) + start_value
96
+ end
97
+ end
98
+ end
99
+
100
+ def build(page_presenter, collection)
101
+ settings = ActiveadminDynamicTable::SettingStringParser.new(params[:columns])
102
+ @configurator = ActiveadminDynamicTable::Configurator.new(self, settings.parse)
103
+
104
+ table_options = {
105
+ id: "index_table_#{active_admin_config.resource_name.plural}",
106
+ sortable: true,
107
+ class: "index_table index dynamic_table",
108
+ i18n: active_admin_config.resource_class,
109
+ paginator: page_presenter[:paginator] != false,
110
+ row_class: page_presenter[:row_class]
111
+ }
112
+
113
+ table_for collection, table_options do |t|
114
+ table_config_block = page_presenter.block || default_table
115
+ instance_exec(t, &table_config_block)
116
+
117
+ apply_configuration
118
+ end
119
+
120
+ columns_list
121
+ end
122
+
123
+ def table_for(*args, &block)
124
+ insert_tag IndexDynamicTableFor, @configurator, *args, &block
125
+ end
126
+
127
+ def register_column(*args, &block)
128
+ @configurator.register_column(:column, *args, &block)
129
+ end
130
+
131
+ def register_id_column(*args, &block)
132
+ @configurator.register_column(:id_column, *args, &block)
133
+ end
134
+
135
+ def register_index_column(*args, &block)
136
+ @configurator.register_column(:index_column, *args, &block)
137
+ end
138
+
139
+ def register_actions(*args, &block)
140
+ @configurator.register_column(:actions, *args, &block)
141
+ end
142
+
143
+ private
144
+
145
+ def apply_columns
146
+ @configurator.columns
147
+ end
148
+
149
+ def apply_configuration
150
+ apply_columns
151
+ column "⚙️", style: "width: 30px", class: 'col-table-preferences', & proc { '' }
152
+ end
153
+
154
+ def columns_list
155
+ ul class: 'dynamic_table_configuration hidden' do
156
+ @configurator.registered_columns.each do |col|
157
+ args = col[:args]
158
+
159
+ options = args.extract_options!
160
+ title = args[0]
161
+ data = args[1] || args[0]
162
+
163
+ column = ::ActiveAdmin::Views::TableFor::Column.new(title, data, @resource_class, options)
164
+
165
+ li do
166
+ label do
167
+ input type: :checkbox, name: col[:key], checked: col[:selected]
168
+ span column.pretty_title
169
+ end
170
+ end
171
+ end
172
+ end
173
+ end
174
+ end
175
+ end
@@ -0,0 +1,13 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "active_admin"
4
+ require_relative "activeadmin_dynamic_table/version"
5
+ require_relative "activeadmin_dynamic_table/configurator"
6
+ require_relative "activeadmin_dynamic_table/setting_string_parser"
7
+ require_relative "activeadmin_dynamic_table/column_settings"
8
+ require_relative "activeadmin_dynamic_table/views/index_as_dynamic_table"
9
+
10
+ module ActiveadminDynamicTable
11
+ class Error < StandardError; end
12
+ class Engine < ::Rails::Engine; end
13
+ end
@@ -0,0 +1,4 @@
1
+ module ActiveadminDynamicTable
2
+ VERSION: String
3
+ # See the writing guide of rbs: https://github.com/ruby/rbs#guides
4
+ end
metadata ADDED
@@ -0,0 +1,75 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: activeadmin_dynamic_table
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Anton Biliaiev
8
+ autorequire:
9
+ bindir: exe
10
+ cert_chain: []
11
+ date: 2024-01-28 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: activeadmin
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '2.9'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '2.9'
27
+ description: ''
28
+ email:
29
+ - amdj15@gmail.com
30
+ executables: []
31
+ extensions: []
32
+ extra_rdoc_files: []
33
+ files:
34
+ - Gemfile
35
+ - Gemfile.lock
36
+ - LICENSE.txt
37
+ - README.md
38
+ - Rakefile
39
+ - activeadmin_dynamic_table.gemspec
40
+ - app/assets/javascripts/activeadmin_dynamic_table/config.js
41
+ - app/assets/javascripts/activeadmin_dynamic_table/dynamic_table.js
42
+ - app/assets/stylesheets/activeadmin_dynamic_table/all.scss
43
+ - bin/console
44
+ - bin/setup
45
+ - lib/activeadmin_dynamic_table.rb
46
+ - lib/activeadmin_dynamic_table/column_settings.rb
47
+ - lib/activeadmin_dynamic_table/configurator.rb
48
+ - lib/activeadmin_dynamic_table/setting_string_parser.rb
49
+ - lib/activeadmin_dynamic_table/version.rb
50
+ - lib/activeadmin_dynamic_table/views/index_as_dynamic_table.rb
51
+ - sig/activeadmin_dynamic_table.rbs
52
+ homepage: ''
53
+ licenses:
54
+ - MIT
55
+ metadata: {}
56
+ post_install_message:
57
+ rdoc_options: []
58
+ require_paths:
59
+ - lib
60
+ required_ruby_version: !ruby/object:Gem::Requirement
61
+ requirements:
62
+ - - ">="
63
+ - !ruby/object:Gem::Version
64
+ version: 2.6.0
65
+ required_rubygems_version: !ruby/object:Gem::Requirement
66
+ requirements:
67
+ - - ">="
68
+ - !ruby/object:Gem::Version
69
+ version: '0'
70
+ requirements: []
71
+ rubygems_version: 3.1.4
72
+ signing_key:
73
+ specification_version: 4
74
+ summary: ''
75
+ test_files: []