Skip to content

Commit c188b82

Browse files
committed
Add initial search feature
Can search pages through their titles and block attributes
1 parent c6becc5 commit c188b82

File tree

9 files changed

+142
-1
lines changed

9 files changed

+142
-1
lines changed

app/assets/stylesheets/better_together/navigation.scss

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,3 +2,8 @@
22
#main-nav {
33
z-index: 500;
44
}
5+
6+
#navbarSearch {
7+
transition: height 0.3s ease;
8+
}
9+
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
# app/models/concerns/searchable.rb
2+
3+
module BetterTogether
4+
# Enables ElasticSearch
5+
module Searchable
6+
extend ActiveSupport::Concern
7+
8+
included do
9+
include Elasticsearch::Model
10+
include Elasticsearch::Model::Callbacks
11+
12+
after_commit :index_document, if: :persisted?
13+
after_commit on: [:destroy] do
14+
__elasticsearch__.delete_document
15+
end
16+
17+
# Need to create another way to access elasticsearch import.
18+
# class.import is using by activerecord-import, I think
19+
def self.elastic_import
20+
__elasticsearch__.import
21+
end
22+
end
23+
24+
private
25+
26+
def index_document
27+
__elasticsearch__.index_document
28+
end
29+
end
30+
end
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
module BetterTogether
2+
class SearchController < ApplicationController
3+
def search
4+
@query = params[:q]
5+
if @query.present?
6+
@results = BetterTogether::Page.search(@query).records
7+
else
8+
@results = []
9+
end
10+
end
11+
end
12+
end

app/models/better_together/content/block.rb

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ module BetterTogether
66
module Content
77
# Base class from which all other content blocks types inherit
88
class Block < ApplicationRecord
9+
include Searchable
910
include ::Storext.model
1011

1112
has_many :page_blocks, dependent: :destroy

app/models/better_together/page.rb

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ class Page < ApplicationRecord
66
include Identifier
77
include Protected
88
include Privacy
9+
include Searchable
910

1011
PAGE_LAYOUTS = [
1112
'layouts/better_together/page',
@@ -14,12 +15,33 @@ class Page < ApplicationRecord
1415

1516
has_many :page_blocks, -> { positioned }, dependent: :destroy, class_name: 'BetterTogether::Content::PageBlock'
1617
has_many :blocks, through: :page_blocks
18+
has_many :image_blocks, -> { where(type: 'BetterTogether::Content::Image') }, through: :page_blocks, source: :block
19+
has_many :rich_text_blocks, -> { where(type: 'BetterTogether::Content::RichText') }, through: :page_blocks, source: :block
1720

1821
accepts_nested_attributes_for :page_blocks, allow_destroy: true
1922

2023
translates :title, type: :string
2124
translates :content, backend: :action_text
2225

26+
settings index: { number_of_shards: 1 } do
27+
mappings dynamic: 'false' do
28+
indexes :title, as: 'title'
29+
indexes :content, as: 'content'
30+
indexes :rich_text_content, type: 'nested' do
31+
indexes :body, type: 'text'
32+
end
33+
34+
indexes :blocks, type: 'nested' do
35+
indexes :rich_text_content, type: 'nested' do
36+
indexes :body, type: 'text'
37+
end
38+
indexes :rich_text_translations, type: 'nested' do
39+
indexes :body, type: 'text'
40+
end
41+
end
42+
end
43+
end
44+
2345
slugged :title, min_length: 1
2446

2547
# Validations
@@ -30,6 +52,25 @@ class Page < ApplicationRecord
3052
scope :published, -> { where.not(published_at: nil) }
3153
scope :by_publication_date, -> { order(published_at: :desc) }
3254

55+
# Customize the data sent to Elasticsearch for indexing
56+
def as_indexed_json(options = {})
57+
self.as_json(
58+
methods: [:title, :content, *self.class.localized_attribute_list],
59+
60+
include: {
61+
rich_text_content: { only: :body },
62+
image_blocks: {
63+
64+
},
65+
rich_text_blocks: {
66+
include: {
67+
rich_text_content: { only: :body }
68+
}
69+
}
70+
}
71+
)
72+
end
73+
3374
def published?
3475
published_at.present? && published_at < Time.zone.now
3576
end
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
<!-- app/views/pages/search.html.erb -->
2+
3+
<div class="container mt-4">
4+
<!-- Search Results -->
5+
<% if @query.present? %>
6+
<h2>Search Results for "<%= @query %>"</h2>
7+
8+
<% if @results.any? %>
9+
<table class="table table-striped mt-3">
10+
<thead>
11+
<tr>
12+
<th>Title</th>
13+
<th>Content</th>
14+
</tr>
15+
</thead>
16+
<tbody>
17+
<% @results.each do |result| %>
18+
<tr>
19+
<td><%= link_to result.title, render_page_path(result.slug) %></td>
20+
<td><%= truncate(strip_tags(result.content.to_s), length: 100) %></td>
21+
</tr>
22+
<% end %>
23+
</tbody>
24+
</table>
25+
<% else %>
26+
<p>No results found for "<%= @query %>". Please try another search term.</p>
27+
<% end %>
28+
<% end %>
29+
</div>
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
<!-- app/views/better_together/shared/_search_bar.html.erb -->
2+
<!-- Search Form -->
3+
<%= form_with url: search_path, method: :get do %>
4+
<div class="input-group">
5+
<%= text_field_tag :q, params[:q], class: 'form-control', placeholder: 'Search for pages...' %>
6+
<button type="submit" class="btn btn-primary"><i class="fas fa-search"></i> Search</button>
7+
</div>
8+
<% end %>

app/views/layouts/better_together/_header.html.erb

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,13 @@
2323
<%= render 'better_together/navigation_items/navigation_items', navigation_items: platform_host_nav_items %>
2424
<% end %>
2525

26+
<!-- Search Icon -->
27+
<li class="nav-item">
28+
<a class="nav-link" href="#" data-bs-toggle="collapse" data-bs-target="#navbarSearch" aria-expanded="false" aria-controls="navbarSearch">
29+
<i class="fas fa-search"></i>
30+
</a>
31+
</li>
32+
2633
<!-- User Auth Nav Item -->
2734
<% if user_signed_in? %>
2835
<li class="nav-item">
@@ -55,3 +62,10 @@
5562
</div>
5663
</div>
5764
</nav>
65+
66+
<!-- Hidden Search Form below navbar -->
67+
<div class="collapse <%= 'show' if current_page?(search_path) %>" id="navbarSearch">
68+
<div class="container mt-3">
69+
<%= render 'better_together/shared/search_bar' %>
70+
</div>
71+
</div>

config/routes.rb

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,8 @@
3030
sign_up: 'sign-up'
3131
},
3232
defaults: { format: :html, locale: I18n.locale }
33-
33+
34+
get 'search', to: 'search#search'
3435
authenticated :user do # rubocop:todo Metrics/BlockLength
3536
resources :communities, only: %i[index show]
3637
resources :conversations, only: %i[index new create show] do

0 commit comments

Comments
 (0)