effective_search 0.2.0 → 0.2.1

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: 4eebd4b86b285679dd65b0e5240bbf4c6bee508e73a38506d192529749a7b17f
4
- data.tar.gz: 604f92513481a00bfc13fddc4b9e90a64e54d4068b5dd381b4e233a508d72601
3
+ metadata.gz: 11770692b109202d028619f343a7f20e32cf84ebb5d25862c1783af0b7247522
4
+ data.tar.gz: 9feec5773a0e9cb0c0f308f94d956dd68f7d92e063781d2e6a45a65359a4423a
5
5
  SHA512:
6
- metadata.gz: 4b8f79bbd7181bcf238a17719f34c3d92f7294d7fd33ae2812a394eec87adec23ac01a0e5fb10c5526d898353d7a197a07ae9dc51444d3600d456ee81ee6c4a4
7
- data.tar.gz: 1ebca0f4b46495d5eebd0175b7c4c8ad1a8ffea8a0f49276137a44e9add02a385d7089db906cf1214b08e05c46cacc4fac9c2d7aca52a5b2e74de3dff7617d0a
6
+ metadata.gz: 62b1a07b867c7ab4d071b637971d61066703053e7489487fc59dda87cb4a20f0a866085c7021e566ae7557f7e8769c871f769a4912c2d0c882ab973b5c3ddeaa
7
+ data.tar.gz: 2b683dcf2e40676564757a1b5ab93dd9b1a5618a8fccba94f7a24b0c88f11de4cf8a360d661c0a54a1c630dc4edee9ded771e5729154264b1a7f36970752fd52
@@ -29,3 +29,29 @@ div.effective-search {
29
29
  background-position: calc(100% - 0.75rem) center !important;
30
30
  }
31
31
  }
32
+
33
+ // Search contents
34
+ .search-content {
35
+ box-shadow: 0px 3px 16px #00000029 !important;
36
+ border-radius: 0.25rem !important;
37
+ margin-bottom: 3rem;
38
+ }
39
+
40
+ .search-content-title {
41
+ font-size: 1.75rem;
42
+ margin-bottom: 0.5rem;
43
+ }
44
+
45
+ .search-content-image {
46
+ min-width: 300px;
47
+ min-height: 300px;
48
+ }
49
+
50
+ .search-content-body {
51
+ padding: 30px;
52
+ }
53
+
54
+ .search-content-link {
55
+ font-weight: 700;
56
+ text-decoration: none;
57
+ }
@@ -0,0 +1,13 @@
1
+ module Admin
2
+ class SearchContentsController < ApplicationController
3
+ before_action(:authenticate_user!) if defined?(Devise)
4
+ before_action { EffectiveResources.authorize!(self, :admin, :effective_search) }
5
+
6
+ include Effective::CrudController
7
+
8
+ def permitted_params
9
+ params.require(:effective_search_content).permit!
10
+ end
11
+
12
+ end
13
+ end
@@ -0,0 +1,23 @@
1
+ module Admin
2
+ class EffectiveSearchContentsDatatable < Effective::Datatable
3
+ datatable do
4
+ order :updated_at, :desc
5
+
6
+ col :id, visible: false
7
+ col :created_at, visible: false
8
+ col :updated_at, visible: false
9
+
10
+ col :title
11
+ col :url
12
+ col :keywords
13
+ col :rich_text_body, label: 'Body', visible: false
14
+ col :file, visible: false
15
+
16
+ actions_col
17
+ end
18
+
19
+ collection do
20
+ Effective::SearchContent.deep.all
21
+ end
22
+ end
23
+ end
@@ -30,6 +30,11 @@ module EffectiveSearchSearch
30
30
  nil
31
31
  end
32
32
 
33
+ # These classes should not be searched
34
+ def unsearchable_types
35
+ ['Effective::Permalink', 'Effective::SearchContent']
36
+ end
37
+
33
38
  def per_page
34
39
  24
35
40
  end
@@ -47,6 +52,18 @@ module EffectiveSearchSearch
47
52
  @search_results
48
53
  end
49
54
 
55
+ # This is Set #1 of results we display on the search page
56
+ def search_contents
57
+ return [] unless present?
58
+ @search_contents ||= Effective::Resource.new(Effective::SearchContent.deep).search_any(term, columns: [:keywords])
59
+ end
60
+
61
+ # This is Set #2 of results we display on the search page
62
+ def permalinks
63
+ return [] unless present?
64
+ @permalinks ||= Effective::Resource.new(Effective::Permalink.deep).search_any(term, columns: [:title, :summary])
65
+ end
66
+
50
67
  # The unpaginated results of the search
51
68
  def search_results
52
69
  @search_results || []
@@ -62,9 +79,7 @@ module EffectiveSearchSearch
62
79
 
63
80
  # View helper
64
81
  def authorized?(result)
65
- raise('expected a PgSearch::Document') unless result.kind_of?(PgSearch::Document)
66
-
67
- searchable = result.searchable
82
+ searchable = result.try(:searchable) || result
68
83
 
69
84
  return false if searchable.blank?
70
85
  return false if searchable.try(:draft?)
@@ -79,7 +94,7 @@ module EffectiveSearchSearch
79
94
 
80
95
  # View helper
81
96
  def title(result)
82
- (result.try(:searchable).try(:title) || result.to_s).html_safe
97
+ (result.try(:searchable).try(:title) || result.try(:title) || result).to_s.html_safe
83
98
  end
84
99
 
85
100
  # View helper
@@ -89,7 +104,7 @@ module EffectiveSearchSearch
89
104
 
90
105
  # View helper
91
106
  def body(result)
92
- content = result.try(:pg_search_highlight) || result.to_s
107
+ content = (result.try(:pg_search_highlight) || result.try(:rich_text_body) || result).to_s
93
108
  scrubs.each { |pattern| content.gsub!(pattern, '') }
94
109
  content.html_safe
95
110
  end
@@ -120,6 +135,10 @@ module EffectiveSearchSearch
120
135
  collection = collection.where(searchable_type: searchable_types)
121
136
  end
122
137
 
138
+ if unsearchable_types.present?
139
+ collection = collection.where.not(searchable_type: unsearchable_types)
140
+ end
141
+
123
142
  # Preload what we need
124
143
  collection = collection.includes(searchable: [:rich_text_body])
125
144
 
@@ -129,7 +148,9 @@ module EffectiveSearchSearch
129
148
 
130
149
  # Sort of a view helper. The result is passed through here
131
150
  def effective_path(result)
132
- case result.searchable_type
151
+ class_name = result.try(:searchable_type) || result.class.name
152
+
153
+ case class_name
133
154
  when 'Effective::Page'
134
155
  EffectivePages::Engine.routes.url_helpers.page_path(result.searchable)
135
156
  when 'Effective::Permalink'
@@ -138,6 +159,8 @@ module EffectiveSearchSearch
138
159
  EffectivePosts::Engine.routes.url_helpers.post_path(result.searchable)
139
160
  when 'Effective::Event'
140
161
  EffectiveEvents::Engine.routes.url_helpers.event_path(result.searchable)
162
+ when 'Effective::SearchContent'
163
+ result.url
141
164
  end
142
165
  end
143
166
 
@@ -0,0 +1,42 @@
1
+ # Provides content areas that will be displayed for specific search terms
2
+
3
+ module Effective
4
+ class SearchContent < ActiveRecord::Base
5
+ self.table_name = (EffectiveSearch.search_contents_table_name || :search_contents).to_s
6
+
7
+ # For the body
8
+ has_many_rich_texts
9
+
10
+ has_one_attached :file
11
+ has_one_purgable :file
12
+
13
+ log_changes if respond_to?(:log_changes)
14
+
15
+ effective_resource do
16
+ title :string
17
+ url :string
18
+ keywords :string
19
+
20
+ timestamps
21
+ end
22
+
23
+ validates :title, presence: true
24
+ validates :url, presence: true, url: true
25
+ validates :keywords, presence: true
26
+
27
+ validates :file, content_type: :image
28
+ validates :file, size: { less_than: 2.megabytes }
29
+
30
+ scope :deep, -> { with_attached_file.includes(:rich_texts) }
31
+ scope :sorted, -> { order(:title) }
32
+
33
+ def to_s
34
+ title.presence || model_name.human
35
+ end
36
+
37
+ # As per has_many_rich_texts
38
+ def body
39
+ rich_text_body
40
+ end
41
+ end
42
+ end
@@ -0,0 +1,7 @@
1
+ = tabs do
2
+ = tab 'Search Content' do
3
+ = render '/admin/search_contents/form_search_content', search_content: search_content
4
+
5
+ - if search_content.persisted?
6
+ = tab 'Logs' do
7
+ = render_datatable(search_content.log_changes_datatable, inline: true, namespace: :admin)
@@ -0,0 +1,13 @@
1
+ = effective_form_with(model: [:admin, search_content], engine: true) do |f|
2
+ = f.text_field :title
3
+ = f.url_field :url, hint: 'The URL of the page to link to'
4
+ = f.text_field :keywords, hint: 'A comma separated list of keywords'
5
+
6
+ - if defined?(EffectiveArticleEditor)
7
+ = f.article_editor :rich_text_body, label: 'Body', hint: 'The main content'
8
+ - else
9
+ = f.rich_text_area :rich_text_body, label: 'Body', hint: 'The main content'
10
+
11
+ = f.file_field :file, label: 'Attachment', hint: 'Upload an image to display on this search content'
12
+
13
+ = effective_submit(f)
@@ -1,5 +1,7 @@
1
1
  = effective_form_with(scope: :q, model: search, method: :get, url: effective_search.search_path) do |f|
2
- = f.text_field :term, label: 'Search'
2
+ .row
3
+ .col-lg-4
4
+ = f.text_field :term, label: false, placeholder: 'Search', autofocus: true, class: "py-4 px-3 shadow-sm border-0"
3
5
 
4
- = f.save('Search', class: 'btn btn-primary btn-search mr-3', name: nil)
5
- = link_to 'Reset', request.path
6
+ -# = f.save('Search', class: 'btn btn-primary btn-search mr-3', name: nil)
7
+ -# = link_to 'Reset', request.path
@@ -5,13 +5,32 @@
5
5
  %hr
6
6
 
7
7
  - results = search.results(page: params[:page])
8
+ - search_contents = search.search_contents.select { |resource| search.authorized?(resource) }
9
+ - permalinks = search.permalinks.select { |resource| search.authorized?(resource) }
8
10
 
9
- - if results.length == 0
10
- .alert.alert-info There are no results for your search. Please try again.
11
+ - if search_contents.present?
12
+ = render(collection: search_contents, partial: 'effective/search_contents/search_content', locals: { search: search })
11
13
 
12
- - if results.length > 0
13
- - collection = results.with_pg_search_highlight.select { |result| search.authorized?(result) }
14
- = render(collection: collection, partial: 'effective/search/result', locals: { search: search })
14
+ .row
15
+ - if permalinks.present?
16
+ .col-xl-4.col-lg-5
17
+ %h3 Downloads
18
+ %hr.mt-0
19
+ %ul
20
+ - permalinks.each do |permalink|
21
+ %li= link_to(permalink.title, permalink.redirect_path, target: '_blank', title: permalink.title)
15
22
 
16
- %nav.d-flex.justify-content-center
17
- = bootstrap_paginate(results, per_page: search.per_page)
23
+ -# Search results
24
+ %div{class: (permalinks.present? ? 'col-xl-8 col-lg-7' : 'col')}
25
+ %h3 Pages
26
+ %hr.mt-0
27
+
28
+ - if results.length == 0
29
+ .alert.alert-info There are no results for your search. Please try again.
30
+
31
+ - if results.length > 0
32
+ - collection = results.with_pg_search_highlight.select { |result| search.authorized?(result) }
33
+ = render(collection: collection, partial: 'effective/search/result', locals: { search: search })
34
+
35
+ %nav.d-flex.justify-content-center
36
+ = bootstrap_paginate(results, per_page: search.per_page)
@@ -1 +1,8 @@
1
+ .row
2
+ .col
3
+ %ol.breadcrumb
4
+ %li.breadcrumb-item= link_to "Home", "/"
5
+ %li.breadcrumb-item.active{"aria-current": "page"}= @page_title
6
+
7
+ %h1= @page_title
1
8
  = render('effective/search/search', search: @search)
@@ -0,0 +1,16 @@
1
+ .search-content.d-flex
2
+ - title = search.title(search_content)
3
+ - url = search.path(search_content)
4
+
5
+ - if search_content.file.attached?
6
+ = link_to(url, title: title) do
7
+ = image_tag(url_for(search_content.file), alt: title, class: 'img-fluid search-content-image d-none d-md-block', height: search_content.file.metadata['height'], width: search_content.file.metadata['width'])
8
+
9
+ .search-content-body
10
+ %h4.search-content-title= link_to(title, url, title: title)
11
+ = search.body(search_content)
12
+
13
+ .search-content-link
14
+ = link_to(url, title: title) do
15
+ View more
16
+ %span.pl-1 &rarr;
data/config/routes.rb CHANGED
@@ -11,6 +11,7 @@ EffectiveSearch::Engine.routes.draw do
11
11
  end
12
12
 
13
13
  namespace :admin do
14
+ resources :search_contents, except: [:show]
14
15
  end
15
16
 
16
17
  end
@@ -11,6 +11,14 @@ class CreateEffectiveSearch < ActiveRecord::Migration[7.0]
11
11
  t.belongs_to :searchable, polymorphic: true, index: true
12
12
  t.timestamps null: false
13
13
  end
14
+
15
+ create_table :search_contents, if_not_exists: true do |t|
16
+ t.string :title
17
+ t.string :url
18
+ t.string :keywords
19
+
20
+ t.timestamps
21
+ end
14
22
  end
15
23
 
16
24
  def down
@@ -21,5 +29,6 @@ class CreateEffectiveSearch < ActiveRecord::Migration[7.0]
21
29
 
22
30
  # PgSearch multisearch table
23
31
  drop_table :pg_search_documents, if_exists: true
32
+ drop_table :search_contents, if_exists: true
24
33
  end
25
34
  end
@@ -1,3 +1,3 @@
1
1
  module EffectiveSearch
2
- VERSION = '0.2.0'.freeze
2
+ VERSION = '0.2.1'.freeze
3
3
  end
@@ -5,7 +5,7 @@ require 'effective_search/version'
5
5
  module EffectiveSearch
6
6
 
7
7
  def self.config_keys
8
- [:search_class_name, :authenticate_user, :layout]
8
+ [:search_class_name, :search_contents_table_name, :authenticate_user, :layout]
9
9
  end
10
10
 
11
11
  include EffectiveGem
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: effective_search
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.0
4
+ version: 0.2.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Code and Effect
@@ -165,16 +165,22 @@ files:
165
165
  - app/assets/javascripts/effective_search/base.js
166
166
  - app/assets/stylesheets/effective_search.scss
167
167
  - app/assets/stylesheets/effective_search/base.scss
168
+ - app/controllers/admin/search_contents_controller.rb
168
169
  - app/controllers/effective/search_controller.rb
170
+ - app/datatables/admin/effective_search_contents_datatable.rb
169
171
  - app/helpers/effective_search_helper.rb
170
172
  - app/models/concerns/effective_search_search.rb
171
173
  - app/models/effective/search.rb
174
+ - app/models/effective/search_content.rb
175
+ - app/views/admin/search_contents/_form.html.haml
176
+ - app/views/admin/search_contents/_form_search_content.html.haml
172
177
  - app/views/effective/search/_form.html.haml
173
178
  - app/views/effective/search/_form_nav_item.html.haml
174
179
  - app/views/effective/search/_layout.html.haml
175
180
  - app/views/effective/search/_result.html.haml
176
181
  - app/views/effective/search/_search.html.haml
177
182
  - app/views/effective/search/index.html.haml
183
+ - app/views/effective/search_contents/_search_content.html.haml
178
184
  - config/effective_search.rb
179
185
  - config/routes.rb
180
186
  - db/migrate/101_create_effective_search.rb