spotlight_search 0.2.1 → 0.2.2

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: a8928a9f036ae75254d0b39e31260ee6191c4c84a61a49e83a48db7b67947a5f
4
- data.tar.gz: 379cd6fbf3f8ab91c0f90655aa92ac6190cd93250d61a22861bb0099736e107d
3
+ metadata.gz: b8d70a1928ef9bfa68c81817f7ab8ba5bb70848ab5c68223ad52294f2cc0e41b
4
+ data.tar.gz: 0e87e9608d99ffb50b6b6239f7af51e01f1b916919062a97b086466b8403caa5
5
5
  SHA512:
6
- metadata.gz: 6d0c131c7f697024d7ed1b94c3f0777c880ac93316be16eda6c542f408d39d40a692eebd3dc581b69fe248e00d7e03c233e315aa8765cd0896fb2bc7fd4c4688
7
- data.tar.gz: 52a2fd7c087b4a27c3f3b3a6169a247e8bdb822ebc6e65380d722ba58fd99d3139dc23059f3de75ef7eb9c0a48da5012413fe3200a3c9f06db9e58ca820eff5f
6
+ metadata.gz: ddd8e03cad7ed5f110c5b9e158f2f40a4efe5551371da46caf92cf3b1c57b6b2b405aee83dabf0050f732e571c7ff891407c5a65906095bddce904771772e63e
7
+ data.tar.gz: 4b3b4880334b8b5a55fb0224e4878da2673bbaade2c221194c9e178e3cd2d633dd5275bfb60ce8c353de072003ac5d2999beb92613820112aa1909736e462a2d
data/README.md CHANGED
@@ -4,6 +4,13 @@
4
4
 
5
5
  It helps filtering, sorting and exporting tables easier.
6
6
 
7
+ First create a new rails project with the following command. If you are adding to existing project skip this
8
+
9
+ ```
10
+ rails new blog -m https://raw.githubusercontent.com/commutatus/cm-rails-template/devise_integration/template.rb
11
+ ```
12
+
13
+
7
14
  ## Installation
8
15
 
9
16
  Add this line to your application's Gemfile:
@@ -20,7 +27,30 @@ Or install it manually:
20
27
 
21
28
  $ gem install spotlight_search
22
29
 
23
- Include the spotlight_search javascript by adding the line `//= require spotlight_search` to your `app/assets/javascripts/application.js`
30
+ Generator that installs mandatory files and gems to application
31
+
32
+ $ rails g spotlight_search:install
33
+
34
+ The install generator does the following
35
+
36
+ * `require spotlight_search` added to application.js
37
+
38
+ * Copies required files for the spotlight_search to work, Such as gemassets.rb, webpacker.yml, environment.js
39
+
40
+ * Copies initializer file
41
+
42
+ * Adds a line in route for mounting.
43
+
44
+ Generator that installs filter and table files to application
45
+
46
+ $ rails g spotlight_search:filter orders --filters search:input order_status:multi_select status:select
47
+
48
+ The install generator does the following
49
+
50
+ * Copies the filter partial and the controller with necessary changes
51
+
52
+ Filter arguments can be passed as an array and the format is `filter_scope:type_of_filter_input`
53
+
24
54
 
25
55
  ## Usage
26
56
 
@@ -66,24 +96,20 @@ end
66
96
  #### View
67
97
  Please note that the below code is in haml.
68
98
 
69
- **STEP - 1 Search**
99
+ **STEP - 1 Filters**
70
100
 
71
- First step is to add the input box to search. Here there are few elements that should be placed mandatorily.
101
+ **Filter Wrapper, Select-tags and Inputs**
72
102
 
73
- ```
74
- .filters.w-100 data-filter-url="/admin/workshops" data-replacement-class="workshops_table"
75
- .col-md-4.input-group.search
76
- input#workshop-search-filter.form-control.filter-box name=("search_term_for_workshops ") placeholder=("Search Workshops") type="text" data-behaviour="filter" data-scope="search" data-type="input-filter"
77
- ```
78
-
79
- The elements that should be placed mandatorily are
103
+ | Generator | *Mandatory(Data Attributes, Select options) | *Optional(Classes, Placeholders) |
104
+ |----------------------------------------------------------------------------------|------------------------------------------------------------------------------------------------------------------------|----------------------------------------------------------------------------------------|
105
+ | `= filter_wrapper(data_behaviours, classes=nil)` | `{filter_url: '/users', replacement_class: 'users-table'}` | "filter-classes" |
106
+ | | | |
107
+ | `= cm_select_tag(select_options, data_behaviours, classes=nil, placeholder=nil)` | `{behaviour: "filter", scope: "status", type: "select-filter}` , User.all.map {\|user\| [user.name.titleize, user.id]} | `"user-select"`, placeholder = `"Users"` |
108
+ | | | |
109
+ | `= cm_textfield_tag(data_behaviours, classes=nil, placeholder=nil)` | `{behaviour: "filter", scope: "search", type: "input-filter}` | `"user-search"`, placeholder = `"Search"` |
110
+ | | | |
111
+ | `= clear_filters(clear_path, classes=nil, data_behaviours=nil, clear_text=nil)` | clear_path = `users_path` | `"clear-filter"`, data_behaviours = `{behaviour: 'clear'}`, clear_text = `"Clear all"` |
80
112
 
81
- * `.filters` All search input / select filter should be nested inside this class name.
82
- * `data-filter-url` Is mandatory, this is the search URL, Mostly this will hit the index action.
83
- * `data-replacement-class` After ajax this is the class name where the data will get appended.
84
- * `data-behaviour="filter"` If the input behaviour is set to filter then this will get added to ajax
85
- * `data-scope="search"` This is the model scope name, The helper method will call this when filter is applied.
86
- * `data-type="input-filter"` This is to tell if the element is input or select other value is `data-type="select-filter"`
87
113
 
88
114
  **STEP - 2 Pagination**
89
115
 
@@ -105,20 +131,6 @@ th = sortable "name", "Name", @filtered_result.sort[:sort_column], @filtered_res
105
131
 
106
132
  You will need to have a background job processor such as `sidekiq`, `resque`, `delayed_job` etc as the file will be generated in the background and will be sent to the email passed. If you need to use any other service for sending emails, you will need to override `ExportMailer` class.
107
133
 
108
- #### Initializer
109
- An initializer will have to be created to extend the functionality to ActiveRecord.
110
-
111
- ```ruby
112
- # config/initializers/spotlight_search.rb
113
- ActiveRecord::Base.include SpotlightSearch::ExportableColumns
114
- ```
115
-
116
- #### Routes
117
- A line has to be added to the routes.
118
-
119
- ```ruby
120
- mount SpotlightSearch::Engine => '/spotlight_search'
121
- ```
122
134
 
123
135
  #### <a name="export-view"></a>View
124
136
 
@@ -0,0 +1,18 @@
1
+ module SpotlightSearch
2
+ module Generators
3
+ class FilterGenerator < Rails::Generators::Base
4
+ source_root File.expand_path('templates', __dir__)
5
+
6
+ argument :model, type: :string, required: true, desc: "Pass a model name"
7
+ class_option :filters, aliases: "-f", type: :array, desc: "Pass filters and scopes as an array. E.x: date_filter:datetime search:input"
8
+
9
+ def copy_filter_contents_to_app
10
+ if @options.filters?
11
+ template 'filters.html.erb', "app/views/admin/#{model}/_filters.html.slim"
12
+ template 'controller.rb.erb', "app/controllers/admin/#{model}_controller.rb"
13
+ end
14
+ end
15
+
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,31 @@
1
+ require 'yaml'
2
+
3
+ module SpotlightSearch
4
+ module Generators
5
+ class InstallGenerator < Rails::Generators::Base
6
+ source_root File.expand_path('templates', __dir__)
7
+
8
+ def copy_webpacker_gem_assets
9
+ copy_file 'webpacker_gem_assets.rb', 'config/initializers/webpacker_gem_assets.rb'
10
+ copy_file 'webpacker.yml', 'config/webpacker.yml'
11
+ copy_file 'environment.js', 'config/webpack/environment.js'
12
+ copy_file 'coffee.js', 'config/webpack/loaders/coffee.js'
13
+ copy_file 'spotlight_search.rb', 'config/initializers/spotlight_search.rb'
14
+ route "mount SpotlightSearch::Engine => '/spotlight_search'"
15
+ end
16
+
17
+ def add_essentials
18
+ system("yarn add jquery")
19
+ system("yarn add coffeescript")
20
+ system("yarn add select2")
21
+ inject_into_file 'app/assets/stylesheets/application.css.scss', before: " */" do
22
+ " *= require select2\n"
23
+ end
24
+ template "application.js", "app/javascript/packs/application.js"
25
+ template 'scaffolds.coffee', "app/javascript/application/coffee_scripts/scaffolds.coffee"
26
+ gem 'kaminari', '~> 1.2.1' unless File.readlines("Gemfile").grep(/kaminari/).size > 0
27
+ end
28
+
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,15 @@
1
+ // This file is automatically compiled by Webpack, along with any other files
2
+ // present in this directory. You're encouraged to place your actual application logic in
3
+ // a relevant structure within app/javascript and only use these pack files to reference
4
+ // that code so it'll be compiled.
5
+
6
+
7
+ require("@rails/ujs").start()
8
+ require("turbolinks").start()
9
+ require("@rails/activestorage").start()
10
+ require('spotlight_search')
11
+
12
+ import jQuery from 'jquery';
13
+ window.$ = jQuery
14
+ window.jQuery = jQuery
15
+ import 'select2';
@@ -0,0 +1,6 @@
1
+ module.exports = {
2
+ test: /\.coffee(\.erb)?$/,
3
+ use: [{
4
+ loader: 'coffee-loader'
5
+ }]
6
+ }
@@ -0,0 +1,91 @@
1
+ class Admin::<%= model.titleize %>Controller < ApplicationController
2
+ before_action :set_<%= model.singularize %>, only: [:show, :edit, :update, :destroy]
3
+
4
+ # GET /<%= model %>
5
+ # GET /<%= model %>.json
6
+ def index
7
+ @filtered_result = <%= model.classify %>.all.filter_by(params[:page], filter_params.to_h, sort_params.to_h)
8
+ respond_to do |format|
9
+ if request.xhr?
10
+ format.html { render partial: 'table' }
11
+ format.json
12
+ else
13
+ format.html
14
+ end
15
+ end
16
+ end
17
+
18
+ # GET /<%= model %>/1
19
+ # GET /<%= model %>/1.json
20
+ def show
21
+ end
22
+
23
+ # GET /<%= model %>/new
24
+ def new
25
+ @<%= model.singularize %> = Profile.new
26
+ end
27
+
28
+ # GET /<%= model %>/1/edit
29
+ def edit
30
+ end
31
+
32
+ # POST /<%= model %>
33
+ # POST /<%= model %>.json
34
+ def create
35
+ @<%= model.singularize %> = Profile.new(<%= model.singularize %>_params)
36
+
37
+ respond_to do |format|
38
+ if @<%= model.singularize %>.save
39
+ format.html { redirect_to @<%= model.singularize %>, notice: 'Profile was successfully created.' }
40
+ format.json { render :show, status: :created, location: @<%= model.singularize %> }
41
+ else
42
+ format.html { render :new }
43
+ format.json { render json: @<%= model.singularize %>.errors, status: :unprocessable_entity }
44
+ end
45
+ end
46
+ end
47
+
48
+ # PATCH/PUT /<%= model %>/1
49
+ # PATCH/PUT /<%= model %>/1.json
50
+ def update
51
+ respond_to do |format|
52
+ if @<%= model.singularize %>.update(<%= model.singularize %>_params)
53
+ format.html { redirect_to @<%= model.singularize %>, notice: 'Profile was successfully updated.' }
54
+ format.json { render :show, status: :ok, location: @<%= model.singularize %> }
55
+ else
56
+ format.html { render :edit }
57
+ format.json { render json: @<%= model.singularize %>.errors, status: :unprocessable_entity }
58
+ end
59
+ end
60
+ end
61
+
62
+ # DELETE /<%= model %>/1
63
+ # DELETE /<%= model %>/1.json
64
+ def destroy
65
+ @<%= model.singularize %>.destroy
66
+ respond_to do |format|
67
+ format.html { redirect_to <%= model.singularize %>s_url, notice: 'Profile was successfully destroyed.' }
68
+ format.json { head :no_content }
69
+ end
70
+ end
71
+
72
+ private
73
+
74
+ # Use callbacks to share common setup or constraints between actions.
75
+ def set_<%= model.singularize %>
76
+ @<%= model.singularize %> = Profile.find(params[:id])
77
+ end
78
+
79
+ # Only allow a list of trusted parameters through.
80
+ def <%= model.singularize %>_params
81
+ params.require(:<%= model.singularize %>).permit()
82
+ end
83
+
84
+ def filter_params
85
+ params.require(:filters).permit(<%= @options.filters.map{ |f| ':' + f.split(':')[0] }.join(', ') %>) if params[:filters]
86
+ end
87
+
88
+ def sort_params
89
+ params.require(:sort).permit(:sort_column, :sort_direction) if params[:sort]
90
+ end
91
+ end
@@ -0,0 +1,19 @@
1
+ const { environment } = require('@rails/webpacker')
2
+ const coffee = require('./loaders/coffee')
3
+
4
+ const webpack = require('webpack')
5
+ environment.plugins.prepend('Provide',
6
+ new webpack.ProvidePlugin({
7
+ $: require.resolve('jquery'),
8
+ jQuery: require.resolve('jquery')
9
+ })
10
+ )
11
+
12
+ const { add_paths_to_environment } = require(
13
+ // `${environment.plugins.get('Environment').defaultValues["PWD"]}/config/environments/_add_gem_paths`
14
+ `/tmp/_add_gem_paths`
15
+ )
16
+ add_paths_to_environment(environment)
17
+
18
+ environment.loaders.prepend('coffee', coffee)
19
+ module.exports = environment
@@ -0,0 +1,12 @@
1
+ = filter_wrapper({filter_url: '/admin/<%= model %>', replacement_class: "<%= model %>-table"})
2
+ <%- @options.filters.each do |filter| -%>
3
+ <%- filter_arr = filter.split(':') -%>
4
+ <%- if filter_arr[1].eql?('input') -%>
5
+ = cm_textfield_tag({behaviour: "filter", scope: "<%= filter_arr[0] %>", type: "input-filter"}, nil, "<%= filter_arr[0].titleize %>")
6
+ <%- elsif filter_arr[1].eql?('select') -%>
7
+ = cm_select_tag([["<%= model.titleize %>", "<%= model %>"]], {behaviour: 'filter', scope: "<%= filter_arr[0] %>", type: 'select-filter', placeholder: ''}, "select2-single")
8
+ <%- elsif filter_arr[1].eql?('multi_select') -%>
9
+ = cm_multi_select_tag([["<%= model.titleize %>", "<%= model %>"]], {behaviour: 'filter', scope: "<%= filter_arr[0] %>", type: 'select-filter', placeholder: ''}, "select2-multiple")
10
+ <%- end -%>
11
+ <%- end -%>
12
+ = clear_filters(admin_<%= model %>_path, nil, nil, "Clear all")
@@ -0,0 +1,6 @@
1
+ $(document).on "turbolinks:load", () ->
2
+ $('.select2-multiple').select2()
3
+ $('.select2-single').select2(
4
+ allowClear: true
5
+ )
6
+
@@ -0,0 +1 @@
1
+ ActiveRecord::Base.include SpotlightSearch::ExportableColumns
@@ -0,0 +1,102 @@
1
+ # Note: You must restart bin/webpack-dev-server for changes to take effect
2
+
3
+ default: &default
4
+ source_path: app/javascript
5
+ source_entry_path: packs
6
+ public_root_path: public
7
+ public_output_path: packs
8
+ cache_path: tmp/cache/webpacker
9
+ check_yarn_integrity: false
10
+ webpack_compile_output: true
11
+
12
+ # Additional paths webpack should lookup modules
13
+ # ['app/assets', 'engine/foo/app/assets']
14
+ resolved_paths: []
15
+ resolved_gems_output_path: '/tmp/_add_gem_paths.js'
16
+ resolved_gems: [
17
+ 'spotlight_search'
18
+ ]
19
+
20
+ # Reload manifest.json on all requests so we reload latest compiled packs
21
+ cache_manifest: false
22
+
23
+ # Extract and emit a css file
24
+ extract_css: false
25
+
26
+ static_assets_extensions:
27
+ - .jpg
28
+ - .jpeg
29
+ - .png
30
+ - .gif
31
+ - .tiff
32
+ - .ico
33
+ - .svg
34
+ - .eot
35
+ - .otf
36
+ - .ttf
37
+ - .woff
38
+ - .woff2
39
+
40
+ extensions:
41
+ - .coffee
42
+ - .mjs
43
+ - .js
44
+ - .sass
45
+ - .scss
46
+ - .css
47
+ - .module.sass
48
+ - .module.scss
49
+ - .module.css
50
+ - .png
51
+ - .svg
52
+ - .gif
53
+ - .jpeg
54
+ - .jpg
55
+
56
+ development:
57
+ <<: *default
58
+ compile: true
59
+
60
+ # Verifies that correct packages and versions are installed by inspecting package.json, yarn.lock, and node_modules
61
+ check_yarn_integrity: true
62
+
63
+ # Reference: https://webpack.js.org/configuration/dev-server/
64
+ dev_server:
65
+ https: false
66
+ host: localhost
67
+ port: 3035
68
+ public: localhost:3035
69
+ hmr: false
70
+ # Inline should be set to true if using HMR
71
+ inline: true
72
+ overlay: true
73
+ compress: true
74
+ disable_host_check: true
75
+ use_local_ip: false
76
+ quiet: false
77
+ pretty: false
78
+ headers:
79
+ 'Access-Control-Allow-Origin': '*'
80
+ watch_options:
81
+ ignored: '**/node_modules/**'
82
+
83
+
84
+ test:
85
+ <<: *default
86
+ compile: true
87
+
88
+ # Compile test packs to a separate directory
89
+ public_output_path: packs-test
90
+
91
+ production:
92
+ <<: *default
93
+ webpack_compile_output: true
94
+
95
+ # Production depends on precompilation of packs prior to booting for performance.
96
+ compile: false
97
+
98
+ # Extract and emit a css file
99
+ extract_css: true
100
+
101
+ # Cache manifest.json for performance
102
+ cache_manifest: true
@@ -0,0 +1,55 @@
1
+ # config/initializers/webpacker_gem_assets.rb
2
+
3
+ def default_assets_path
4
+ 'app/assets/javascripts'
5
+ end
6
+
7
+ def output_path
8
+ Webpacker.config.send(:data)[:resolved_gems_output_path] || '/tmp/_add_gem_paths.js'
9
+ end
10
+
11
+ def resolve_gem_path(gem)
12
+ if gem.present?
13
+ gem_path = Gem.loaded_specs[gem]&.full_gem_path
14
+ if gem_path.present?
15
+ return "#{gem_path}/#{default_assets_path}"
16
+ end
17
+ end
18
+ abort("Gem '#{gem}' not found, please check webpacker config (#{Webpacker.config.config_path})")
19
+ end
20
+
21
+ buffer = []
22
+ buffer << "
23
+ /*
24
+ * THIS IS A GENERATED FILE.
25
+ * DO NOT CHECK IT INTO SOURCE CONTROL
26
+ */
27
+ function add_paths_to_environment(environment) {".strip
28
+
29
+ resolved_gems = Webpacker.config.send(:data)[:resolved_gems]
30
+ if resolved_gems.any?
31
+ buffer << "\n environment.resolvedModules.add(\n"
32
+ buffer << resolved_gems.map do |gem|
33
+ " { key: 'gem-#{gem}', value: '#{resolve_gem_path(gem)}' }"
34
+ end.join(",\n")
35
+ buffer << "\n )\n"
36
+ end
37
+
38
+ buffer << "}\nexports.add_paths_to_environment = add_paths_to_environment\n"
39
+
40
+ File.write(
41
+ output_path,
42
+ buffer.join
43
+ )
44
+
45
+ module WebpackerGemAssets
46
+ def resolved_paths
47
+ self.send(:data)[:resolved_gems].map do |gem|
48
+ resolve_gem_path gem
49
+ end.compact.concat(super)
50
+ end
51
+ end
52
+
53
+ class Webpacker::Configuration
54
+ prepend WebpackerGemAssets
55
+ end
@@ -83,6 +83,28 @@ module SpotlightSearch
83
83
  end
84
84
  end
85
85
 
86
+ def filter_wrapper(data_behaviours, classes=nil)
87
+ tag.div class: "filter-wrapper d-flex filters #{classes}", data: data_behaviours do
88
+ yield
89
+ end
90
+ end
91
+
92
+ def cm_single_select_tag(select_options, data_behaviours, classes=nil, placeholder=nil)
93
+ select_tag data_behaviours[:scope], options_for_select(select_options), class: "#{classes}", data: data_behaviours, include_blank: "#{placeholder}"
94
+ end
95
+
96
+ def cm_multi_select_tag(select_options, data_behaviours, classes=nil, placeholder=nil)
97
+ select_tag data_behaviours[:scope], options_for_select(select_options), class: "#{classes}", data: data_behaviours, include_blank: "#{placeholder}", multiple: true
98
+ end
99
+
100
+ def cm_textfield_tag(data_behaviours, classes=nil, placeholder=nil)
101
+ text_field_tag data_behaviours[:scope], '', class: "#{classes}", data: data_behaviours, placeholder: "#{placeholder}"
102
+ end
103
+
104
+ def clear_filters(clear_path, classes=nil, data_behaviours=nil, clear_text=nil)
105
+ link_to "#{clear_text}", clear_path, class: "#{classes}", data: data_behaviours
106
+ end
107
+
86
108
  def checkbox_row_v2(klass)
87
109
  tag.div class: "row" do
88
110
  SpotlightSearch::Utils.serialize_csv_columns(*klass.enabled_columns).each do |column_path|
@@ -1,3 +1,3 @@
1
1
  module SpotlightSearch
2
- VERSION = "0.2.1"
2
+ VERSION = "0.2.2"
3
3
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: spotlight_search
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.1
4
+ version: 0.2.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Anbazhagan Palani
@@ -106,6 +106,17 @@ files:
106
106
  - bin/console
107
107
  - bin/setup
108
108
  - config/routes.rb
109
+ - lib/generators/spotlight_search/filter_generator.rb
110
+ - lib/generators/spotlight_search/install_generator.rb
111
+ - lib/generators/spotlight_search/templates/application.js
112
+ - lib/generators/spotlight_search/templates/coffee.js
113
+ - lib/generators/spotlight_search/templates/controller.rb.erb
114
+ - lib/generators/spotlight_search/templates/environment.js
115
+ - lib/generators/spotlight_search/templates/filters.html.erb
116
+ - lib/generators/spotlight_search/templates/scaffolds.coffee
117
+ - lib/generators/spotlight_search/templates/spotlight_search.rb
118
+ - lib/generators/spotlight_search/templates/webpacker.yml
119
+ - lib/generators/spotlight_search/templates/webpacker_gem_assets.rb
109
120
  - lib/spotlight_search.rb
110
121
  - lib/spotlight_search/engine.rb
111
122
  - lib/spotlight_search/exceptions.rb