sortofil 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
+ SHA1:
3
+ metadata.gz: 5e8184e9c2392eff97ce32bc7b6adebfc72c97b4
4
+ data.tar.gz: '01387c3d6ac9002adf88d132a9ad3602f9301ace'
5
+ SHA512:
6
+ metadata.gz: 5c9bdfdc10031c61269e964610860ab1ed923cea9b51cd4abc427e79008dfca4c82346beefd7ec634772f03f09d10e3cc64ae463625ffb1e0c327e21073612d8
7
+ data.tar.gz: 3e379f420ed934e77d8016a227c49effbd92b1429409ce394f2305abe26d92bb0f10ce3fea2854ed72e41dfb36f2b316e02dcee573ac5262088bc507df6175e8
data/MIT-LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright 2017 Rinat Garifullin
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,135 @@
1
+ # Sortofil
2
+ Sortofil - sort and filter helper for Rails app
3
+
4
+ Features:
5
+ * sortable table headers
6
+ * restore url query params during session
7
+
8
+ ## Usage
9
+
10
+ ### Sort/filter
11
+ Add this to controller:
12
+ ```ruby
13
+ include Sortofilterable
14
+
15
+ before_action :permit_params
16
+ before_action :set_default_sort_opts
17
+ ```
18
+ Customize options (override methods inside controller):
19
+ * Simple case:
20
+
21
+ ```ruby
22
+ def set_default_sort_field
23
+ @default_sort_field = { nil => :created_at }
24
+ end
25
+
26
+ def set_default_sort_direction
27
+ @default_sort_direction = { nil => :desc }
28
+ end
29
+
30
+ def permit_params
31
+ @permitted_params = params.permit(sort_params, filter_params,
32
+ pagination_params, :your_additional_param)
33
+ end
34
+ ```
35
+
36
+ * Multiple models per page case:
37
+
38
+ ```ruby
39
+ def set_default_sort_field
40
+ @default_sort_field = { artists: :first_name, authors: :last_name }
41
+ end
42
+
43
+ def set_default_sort_direction
44
+ @default_sort_direction = { artists: :asc, authors: :desc }
45
+ end
46
+
47
+ def permit_params
48
+ @permitted_params = params.permit({ artists: sort_params + filter_params,
49
+ authors: sort_params + filter_params },
50
+ pagination_params)
51
+ end
52
+ ```
53
+
54
+ View
55
+
56
+ * Simple case:
57
+
58
+ ```html
59
+ <table>
60
+ <thead>
61
+ <th>
62
+ <%= render 'layouts/sortable_theader', model: 'artists' %>
63
+ </th>
64
+ </thead>
65
+ <tbody>
66
+ ...
67
+ </tbody>
68
+ </table>
69
+ ```
70
+
71
+ * Multiple models per page case:
72
+
73
+ ```html
74
+ <table>
75
+ <thead>
76
+ <th>
77
+ <%= render 'layouts/sortable_theader', model: 'artists', scoped: true,
78
+ url: 'root' %>
79
+ </th>
80
+ </thead>
81
+ <tbody>
82
+ ...
83
+ </tbody>
84
+ </table>
85
+
86
+ <table>
87
+ <thead>
88
+ <th>
89
+ <%= render 'layouts/sortable_theader', model: 'authors', scoped: true,
90
+ url: 'root' %>
91
+ </th>
92
+ </thead>
93
+ <tbody>
94
+ ...
95
+ </tbody>
96
+ </table>
97
+ ```
98
+
99
+ ### Url restore
100
+
101
+ Add this to controller:
102
+ ```ruby
103
+ include UrlRestorable
104
+
105
+ before_action do
106
+ restore_url_params(:your_key)
107
+ end
108
+ ```
109
+
110
+ View
111
+
112
+ ```html
113
+ <%= render 'layouts/restorable_url_params', key: :your_key %>
114
+ ```
115
+
116
+ ## Installation
117
+ Add this line to your application's Gemfile:
118
+
119
+ ```ruby
120
+ gem 'sortofil'
121
+ ```
122
+
123
+ And then execute:
124
+ ```bash
125
+ $ bundle
126
+ ```
127
+
128
+ Or install it yourself as:
129
+ ```bash
130
+ $ gem install sortofil
131
+ ```
132
+
133
+
134
+ ## License
135
+ The gem is available as open source under the terms of the [MIT License](http://opensource.org/licenses/MIT).
data/Rakefile ADDED
@@ -0,0 +1,27 @@
1
+ begin
2
+ require 'bundler/setup'
3
+ rescue LoadError
4
+ puts 'You must `gem install bundler` and `bundle install` to run rake tasks'
5
+ end
6
+
7
+ require 'rdoc/task'
8
+
9
+ RDoc::Task.new(:rdoc) do |rdoc|
10
+ rdoc.rdoc_dir = 'rdoc'
11
+ rdoc.title = 'Sortofil'
12
+ rdoc.options << '--line-numbers'
13
+ rdoc.rdoc_files.include('README.md')
14
+ rdoc.rdoc_files.include('lib/**/*.rb')
15
+ end
16
+
17
+ require 'bundler/gem_tasks'
18
+
19
+ require 'rake/testtask'
20
+
21
+ Rake::TestTask.new(:test) do |t|
22
+ t.libs << 'test'
23
+ t.pattern = 'test/**/*_test.rb'
24
+ t.verbose = false
25
+ end
26
+
27
+ task default: :test
@@ -0,0 +1,17 @@
1
+ const filterRestore = function filterRestoreUrl() {
2
+ var str = document.getElementById('url_params').value;
3
+ if (str) {
4
+ var updated_url = location.pathname + '?' + encodeURI(str);
5
+ var page = location.search.match(/page=\d+/);
6
+ if (page) {
7
+ updated_url += '&' + page;
8
+ }
9
+ history.replaceState({}, document.title, updated_url);
10
+ }
11
+ };
12
+
13
+ document.onreadystatechange = function() {
14
+ if (document.readyState === 'interactive') {
15
+ filterRestore();
16
+ }
17
+ };
@@ -0,0 +1,48 @@
1
+ # Sort and filter
2
+ module Sortofilterable
3
+ extend ActiveSupport::Concern
4
+
5
+ included do
6
+ private
7
+
8
+ def filter_params
9
+ []
10
+ end
11
+
12
+ def sort_params
13
+ %i[sort_by direction]
14
+ end
15
+
16
+ def pagination_params
17
+ %i[page]
18
+ end
19
+
20
+ def set_default_sort_opts
21
+ set_default_sort_field
22
+ set_default_sort_direction
23
+ end
24
+
25
+ def set_default_sort_field
26
+ @default_sort_field = { nil => :id }
27
+ end
28
+
29
+ def set_default_sort_direction
30
+ @default_sort_direction = { nil => :asc }
31
+ end
32
+
33
+ def sort_field(scope = nil)
34
+ params.dig(scope, :sort_by) || params[:sort_by] ||
35
+ @default_sort_field[scope]
36
+ end
37
+
38
+ def sort_direction(scope = nil)
39
+ params.dig(scope, :direction) || params[:direction] ||
40
+ @default_sort_direction[scope]
41
+ end
42
+
43
+ def permit_params
44
+ @permitted_params = params.permit(sort_params, filter_params,
45
+ pagination_params)
46
+ end
47
+ end
48
+ end
@@ -0,0 +1,43 @@
1
+ # Restore url query params between requests
2
+ module UrlRestorable
3
+ extend ActiveSupport::Concern
4
+
5
+ included do
6
+ private
7
+
8
+ def restore_url_params(key_prefix)
9
+ key = "#{key_prefix}_url_params"
10
+ if @permitted_params
11
+ params_wo_paging = @permitted_params.reject do |k, _|
12
+ pagination_params.include?(k.to_sym)
13
+ end
14
+ end
15
+ all_params = params_wo_paging ||
16
+ params.permit(filter_params + sort_params)
17
+
18
+ if params[:reset_url]
19
+ if params[:reset_url] == 'all'
20
+ session[key] = nil
21
+ else
22
+ session[key] = Rack::Utils.parse_nested_query(session[key])
23
+ .except(params[:reset_url]).to_query
24
+ end
25
+ elsif session[key].blank?
26
+ session[key] = all_params.to_h.to_query
27
+ end
28
+
29
+ return if session[key].blank?
30
+
31
+ new_params = Rack::Utils.parse_nested_query(session[key])
32
+ .merge(deep_transform(all_params.to_h))
33
+ session[key] = new_params.to_query
34
+ params.merge!(new_params)
35
+ end
36
+
37
+ def deep_transform(hash)
38
+ hash.transform_values do |val|
39
+ val.is_a?(String) ? val : val.transform_values { |vv| vv }
40
+ end
41
+ end
42
+ end
43
+ end
@@ -0,0 +1,3 @@
1
+ <%= hidden_field_tag :url_params, session["#{key}_url_params".to_sym] %>
2
+
3
+ <%= javascript_include_tag 'filter_restore' %>
@@ -0,0 +1,56 @@
1
+ <% scope = model.to_sym if defined?(scoped) %>
2
+
3
+ <% if params.dig(scope, :direction).present? %>
4
+ <% if params.dig(scope, :direction) == 'asc' %>
5
+ <% direction = 'asc' %>
6
+ <% next_direction = 'desc' %>
7
+ <% else %>
8
+ <% direction = 'desc' %>
9
+ <% next_direction = 'asc' %>
10
+ <% end %>
11
+ <% elsif params[:direction] %>
12
+ <% direction = params[:direction] %>
13
+ <% next_direction = direction == 'asc' ? 'desc' : 'asc' %>
14
+ <% else %>
15
+ <% direction = @default_sort_direction[scope] %>
16
+ <% next_direction = @default_sort_direction[scope] == :asc ? :desc : :asc %>
17
+ <% end %>
18
+
19
+ <% if scope %>
20
+ <% if @permitted_params[scope] %>
21
+ <% sort_params = { "#{scope}".to_sym => @permitted_params[scope]
22
+ .merge(direction: next_direction, sort_by: column) } %>
23
+ <% else %>
24
+ <% sort_params = { "#{scope}".to_sym => { direction: next_direction,
25
+ sort_by: column } } %>
26
+ <% end %>
27
+ <% else %>
28
+ <% sort_params = @permitted_params.merge(direction: next_direction,
29
+ sort_by: column) %>
30
+ <% end %>
31
+
32
+ <% i18_scope ||= model %>
33
+ <% header = t("#{i18_scope}.#{scope || model}.#{column}", default: '') %>
34
+ <% if header.empty? %>
35
+ <% header = Object.const_get(model.singularize.capitalize)
36
+ .human_attribute_name(column) %>
37
+ <% end %>
38
+
39
+ <% url ||= model %>
40
+ <%= link_to url_for([url, params: sort_params.to_h]) do %>
41
+ <%= header %>
42
+ <% if params.dig(scope, :sort_by).present? %>
43
+ <% if params.dig(scope, :sort_by) == column.to_s %>
44
+ &nbsp;
45
+ <i class="fa fa-sort-<%= direction %>"></i>
46
+ <% end %>
47
+ <% elsif params[:sort_by].present? %>
48
+ <% if params[:sort_by] == column.to_s %>
49
+ &nbsp;
50
+ <i class="fa fa-sort-<%= direction %>"></i>
51
+ <% end %>
52
+ <% elsif @default_sort_field[scope] == column %>
53
+ &nbsp;
54
+ <i class="fa fa-sort-<%= direction %>"></i>
55
+ <% end %>
56
+ <% end %>
@@ -0,0 +1,8 @@
1
+ module Sortofil
2
+ # Use assets pipeline
3
+ class Engine < ::Rails::Engine
4
+ initializer 'Sortofil precompiled assets', group: :all do |app|
5
+ app.config.assets.precompile += %w[filter_restore.js]
6
+ end
7
+ end
8
+ end
@@ -0,0 +1,3 @@
1
+ module Sortofil
2
+ VERSION = '0.1.0'.freeze
3
+ end
data/lib/sortofil.rb ADDED
@@ -0,0 +1,2 @@
1
+ require 'sortofil/engine' if defined? Rails::Railtie
2
+ require 'font-awesome-rails'
@@ -0,0 +1,4 @@
1
+ # desc "Explaining what the task does"
2
+ # task :sortofil do
3
+ # # Task goes here
4
+ # end
metadata ADDED
@@ -0,0 +1,126 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: sortofil
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Rinat Garifullin
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2017-07-03 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: rails
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '5.1'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '5.1'
27
+ - !ruby/object:Gem::Dependency
28
+ name: font-awesome-rails
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '4.7'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '4.7'
41
+ - !ruby/object:Gem::Dependency
42
+ name: poltergeist
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: puma
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: sqlite3
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ">="
74
+ - !ruby/object:Gem::Version
75
+ version: '0'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ">="
81
+ - !ruby/object:Gem::Version
82
+ version: '0'
83
+ description: Set of sort and filter helpers
84
+ email:
85
+ - ringarifullin@gmail.com
86
+ executables: []
87
+ extensions: []
88
+ extra_rdoc_files: []
89
+ files:
90
+ - MIT-LICENSE
91
+ - README.md
92
+ - Rakefile
93
+ - app/assets/javascripts/filter_restore.js
94
+ - app/controllers/concerns/sortofilterable.rb
95
+ - app/controllers/concerns/url_restorable.rb
96
+ - app/views/layouts/_restorable_url_params.html.erb
97
+ - app/views/layouts/_sortable_theader.html.erb
98
+ - lib/sortofil.rb
99
+ - lib/sortofil/engine.rb
100
+ - lib/sortofil/version.rb
101
+ - lib/tasks/sortofil_tasks.rake
102
+ homepage: https://github.com/rgarifullin/sortofil
103
+ licenses:
104
+ - MIT
105
+ metadata: {}
106
+ post_install_message:
107
+ rdoc_options: []
108
+ require_paths:
109
+ - lib
110
+ required_ruby_version: !ruby/object:Gem::Requirement
111
+ requirements:
112
+ - - ">="
113
+ - !ruby/object:Gem::Version
114
+ version: '0'
115
+ required_rubygems_version: !ruby/object:Gem::Requirement
116
+ requirements:
117
+ - - ">="
118
+ - !ruby/object:Gem::Version
119
+ version: '0'
120
+ requirements: []
121
+ rubyforge_project:
122
+ rubygems_version: 2.6.12
123
+ signing_key:
124
+ specification_version: 4
125
+ summary: Sorting and filtering tool
126
+ test_files: []