Added Searching Features
* Added Thread Search Feature * Added User Search Feature * Re-organized searching, added @mention support to author search
This commit is contained in:
@@ -75,4 +75,4 @@ class ApplicationController < ActionController::Base
|
||||
!!(current_user && current_user.confirmed?)
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
|
||||
@@ -75,4 +75,4 @@ class BlogpostsController < ApplicationController
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
class ForumsController < ApplicationController
|
||||
|
||||
before_filter :check_permission, only: [:show, :edit, :update, :destroy]
|
||||
|
||||
def index
|
||||
@@ -77,7 +78,6 @@ class ForumsController < ApplicationController
|
||||
redirect_to forums_path
|
||||
end
|
||||
|
||||
|
||||
private
|
||||
|
||||
def check_permission
|
||||
|
||||
@@ -3,9 +3,14 @@ class ForumthreadsController < ApplicationController
|
||||
before_filter :check_permission, only: [:show, :edit, :update, :destroy]
|
||||
|
||||
def index
|
||||
redirect_to forum_path(@thread.forum.forumgroup, f)
|
||||
if params[:label] && !Label.where("lower(name) = ?", params[:label].downcase).try(:first) && params[:label].downcase != "no label"
|
||||
flash[:alert] = "'#{params[:label]}' is not a valid label."
|
||||
redirect_to forumthreads_path(params.except(:label, :controller, :action))
|
||||
return
|
||||
end
|
||||
@threads = Forumthread.filter(current_user, params[:title], params[:content], params[:reply], params[:label], User.where("lower(ign) = ?", params[:author].to_s.downcase).try(:first), params[:query], Forum.where(id: params[:id]).try(:first))
|
||||
.page(params[:page]).per(30)
|
||||
end
|
||||
|
||||
def show
|
||||
if params[:reverse]
|
||||
@replies = @thread.replies.reverse_order.page(params[:page])
|
||||
@@ -80,6 +85,20 @@ class ForumthreadsController < ApplicationController
|
||||
redirect_to @thread.forum
|
||||
end
|
||||
|
||||
def search
|
||||
end
|
||||
|
||||
def search_redirect
|
||||
params.each do |key, value|
|
||||
params[key] = nil if params[key] == ""
|
||||
end
|
||||
params[:id] = nil if params[:id] == "Search All Threads"
|
||||
params[:label] = nil if params[:label] && params[:label].downcase == "label"
|
||||
params[:author] = params[:author].tr("@ ", "") if params[:author]
|
||||
params_list = Hash[params.except(:commit, :utf8, :authenticity_token)]
|
||||
redirect_to forumthreads_path(params_list)
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def check_permission
|
||||
|
||||
@@ -4,7 +4,7 @@ class UsersController < ApplicationController
|
||||
include MailerHelper
|
||||
include ERB::Util
|
||||
|
||||
before_filter :set_user, except: [:index, :new, :create, :lost_password, :reset_password, :suggestions]
|
||||
before_filter :set_user, except: [:index, :new, :create, :lost_password, :reset_password, :suggestions, :search_redirect]
|
||||
|
||||
def index
|
||||
if params[:role]
|
||||
@@ -13,7 +13,7 @@ class UsersController < ApplicationController
|
||||
else
|
||||
if role = Role.get(params[:role])
|
||||
@users = User.joins(:role).where(role: role)
|
||||
else
|
||||
elsif params[:search] == nil
|
||||
flash[:alert] = "role '#{params[:role]}' does not exist!"
|
||||
redirect_to users_path
|
||||
return
|
||||
@@ -30,6 +30,7 @@ class UsersController < ApplicationController
|
||||
else
|
||||
@users = User.joins(:role).where.not(id: User.first.id) #Remove first user
|
||||
end
|
||||
@users = User.search(@users, params[:search]) if params[:search]
|
||||
@users = @users.order("roles.value desc", "confirmed desc", :name) unless params[:badge]
|
||||
@count = @users.size
|
||||
@users = @users.page(params[:page]).per(100)
|
||||
@@ -339,6 +340,14 @@ class UsersController < ApplicationController
|
||||
end
|
||||
end
|
||||
|
||||
def search_redirect
|
||||
params.each do |key, value|
|
||||
params[key] = nil if params[key] == ""
|
||||
end
|
||||
params_list = Hash[params.except(:commit, :utf8, :authenticity_token)]
|
||||
redirect_to users_path(params_list)
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def validate_token(uuid, email, token)
|
||||
|
||||
@@ -24,4 +24,4 @@ module MailerHelper
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -52,4 +52,4 @@ module UsersHelper
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
|
||||
@@ -32,4 +32,4 @@ class Forum < ActiveRecord::Base
|
||||
def to_param
|
||||
[id, to_s.parameterize].join("-")
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -65,4 +65,47 @@ class Forumthread < ActiveRecord::Base
|
||||
def to_param
|
||||
[id, to_s.parameterize].join("-")
|
||||
end
|
||||
|
||||
def self.filter (user, title, content, reply, label, author, query, forum)
|
||||
userid = user.try(:id).to_i
|
||||
role = user.try(:role).to_i
|
||||
|
||||
can_read = "COALESCE(forum_role_read.value, 0) <= ? AND COALESCE(forumgroup_role_read.value, 0) <= ?"
|
||||
sticky_can_write = "sticky = true AND (COALESCE(forum_role_write.value, 0) <= ? OR COALESCE(forumgroup_role_write.value, 0) <= ?)"
|
||||
|
||||
threads = forum.try(:forumthreads) || Forumthread
|
||||
threads = threads.where("forumthreads.user_author_id = ? OR (#{can_read}) OR (#{sticky_can_write})", userid, role, role, role, role)
|
||||
.joins("LEFT JOIN threadreplies ON forumthreads.id = threadreplies.forumthread_id")
|
||||
.joins(forum: :forumgroup)
|
||||
.joins("LEFT JOIN roles as forum_role_read ON forums.role_read_id = forum_role_read.id")
|
||||
.joins("LEFT JOIN roles as forum_role_write ON forums.role_write_id = forum_role_write.id")
|
||||
.joins("LEFT JOIN roles as forumgroup_role_read ON forumgroups.role_read_id = forumgroup_role_read.id")
|
||||
.joins("LEFT JOIN roles as forumgroup_role_write ON forumgroups.role_write_id = forumgroup_role_write.id")
|
||||
|
||||
if [content, title, reply, label, author, query].any?
|
||||
label_o = Label.find_by(name: label)
|
||||
if label_o
|
||||
threads = threads.where(label: label_o)
|
||||
elsif label.try(:downcase) == "no label"
|
||||
threads = threads.where(label: nil)
|
||||
end
|
||||
|
||||
threads = threads.where(user_author: author) if author
|
||||
|
||||
if query
|
||||
threads = threads.where("MATCH (title, forumthreads.content) AGAINST (?) OR MATCH (threadreplies.content) AGAINST (?)", query, query)
|
||||
elsif [title, content, reply].any?
|
||||
query = [title, content, reply].select(&:present?).join(" ")
|
||||
threads = threads.where("MATCH (title) AGAINST (?)", title) if title
|
||||
threads = threads.where("MATCH (forumthreads.content) AGAINST (?)", content) if content
|
||||
threads = threads.where("MATCH (threadreplies.content) AGAINST (?)", reply) if reply
|
||||
threads = threads.group("threadreplies.id", "forumthreads.id")
|
||||
threads = threads.order("(MATCH (title, forumthreads.content) AGAINST ('#{query}')) DESC")
|
||||
end
|
||||
end
|
||||
|
||||
threads = threads.order("sticky desc", "threadreplies.created_at desc", "forumthreads.created_at desc") if threads.order_values.empty?
|
||||
|
||||
threads
|
||||
end
|
||||
end
|
||||
|
||||
@@ -53,4 +53,4 @@ class Role < ActiveRecord::Base
|
||||
Role.order(:value).select {|r| r >= from}.select {|r| r <= to}
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
|
||||
@@ -174,4 +174,8 @@ class User < ActiveRecord::Base
|
||||
def set_email_token
|
||||
self.email_token ||= SecureRandom.hex(16)
|
||||
end
|
||||
|
||||
def self.search (users, search)
|
||||
return users.where("users.name like ? OR ign like ?", "%#{User.send(:sanitize_sql_like, search)}%", "%#{User.send(:sanitize_sql_like, search)}%")
|
||||
end
|
||||
end
|
||||
|
||||
8
app/views/application/_md_editor_user.html.erb
Normal file
8
app/views/application/_md_editor_user.html.erb
Normal file
@@ -0,0 +1,8 @@
|
||||
<div class="md_editor">
|
||||
<div class="field_container_user">
|
||||
<% options = (defined?(options) && options || {}) %>
|
||||
<% options[:class] = "#{options[:class]} editor_field" %>
|
||||
<% options[:placeholder] ||= "Enter user's name. Prefix with \"@\" to get suggestions." %>
|
||||
<%= text_field_tag name, content, options %>
|
||||
</div>
|
||||
</div>
|
||||
@@ -1,5 +1,7 @@
|
||||
<% title "Forums" %>
|
||||
|
||||
<%= link_to "All threads", forumthreads_path(params.except("controller", "action")), class: "btn blue right" %>
|
||||
|
||||
<div id="forum_groups">
|
||||
<% @groups.each do |group| %>
|
||||
<div class="item-group" id="group-<%= group.id %>">
|
||||
@@ -56,4 +58,4 @@
|
||||
<%= link_to "New group", new_forumgroup_path, class: "btn blue" %>
|
||||
<% elsif mod? %>
|
||||
<%= link_to "New group", "#", class: "btn blue", disabled: true %>
|
||||
<% end %>
|
||||
<% end %>
|
||||
|
||||
@@ -1,8 +1,15 @@
|
||||
<%= link_to @forum.group, forumgroup_path(@forum.group) %> → <%= @forum %>
|
||||
|
||||
<h1><%= title @forum %></h1>
|
||||
<h1>
|
||||
<%= title @forum %>
|
||||
<% params[:id] = params[:id].split("-")[0] %>
|
||||
<%= link_to "Search Threads", forumthreads_path(params.except("action", "controller")), class: "btn blue right" %>
|
||||
</h1>
|
||||
<% if @forum.can_write?(current_user) %>
|
||||
<p><%= link_to "New thread", new_forumthread_path(forum: @forum), class: "btn blue" %></p>
|
||||
<p>
|
||||
<%= link_to "New thread", new_forumthread_path(forum: @forum), class: "btn blue" %>
|
||||
<% params[:id] = params[:id].split("-")[0] %>
|
||||
</p>
|
||||
<% end %>
|
||||
|
||||
<% if @forum.role_read && @forum.role_write && @forum.role_write < @forum.role_read %>
|
||||
@@ -51,4 +58,4 @@
|
||||
</div>
|
||||
<% end %>
|
||||
<%= paginate @threads %>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
84
app/views/forumthreads/index.html.erb
Normal file
84
app/views/forumthreads/index.html.erb
Normal file
@@ -0,0 +1,84 @@
|
||||
<%= link_to "Forums", forums_path %> →
|
||||
<% if params.to_hash.slice("label", "title", "content", "author", "reply").size > 0 %>
|
||||
<%= link_to "All Threads", forumthreads_path %> → Search Results
|
||||
<% else %>
|
||||
<%= "All Threads" %>
|
||||
<% end %>
|
||||
<% params_list = params.to_hash.slice("id", "query", "label", "title", "content", "author", "reply") %>
|
||||
<h1>
|
||||
<% if params[:id] %>
|
||||
<% text = "forum '#{Forum.find(params[:id]).name}'" %>
|
||||
<% else %>
|
||||
<% text = "all threads" %>
|
||||
<% end %>
|
||||
<% if params_list.size > 0 %>
|
||||
<%= title "Search results in #{text} (#{@threads.length})" %>
|
||||
<% else %>
|
||||
<% if params[:id] %>
|
||||
<%= title "All threads in #{text}" %>
|
||||
<% else %>
|
||||
<%= title "All Threads" %>
|
||||
<% end %>
|
||||
<% end %>
|
||||
<br>
|
||||
<%= link_to "Advanced Search", search_forumthreads_path(params_list), class: "btn right blue" %>
|
||||
<% if params_list.size > 0 && params[:id] %>
|
||||
<%= link_to "Show All Threads", forumthreads_path(params_list.except("id")), class: "btn right blue" %>
|
||||
<% elsif params_list.size > 0 && !params[:id] %>
|
||||
<%= link_to "Show All Threads", forumthreads_path, class: "btn right blue" %>
|
||||
<% end %>
|
||||
<% if params[:id] %>
|
||||
<%= link_to "Go to Forum", forum_path(params[:id]), class: "btn right blue" %>
|
||||
<% end %>
|
||||
</h1>
|
||||
<br>
|
||||
<%= form_tag({controller: "forumthreads", action: "search_redirect"}, method: :post, style: "margin:0px;height:40px") do %>
|
||||
<%= text_field_tag "query", nil, placeholder: "Search...", style: "margin:0px;height:40px;width:300px" %>
|
||||
<% params.each do |key, value| %>
|
||||
<%= hidden_field_tag key, params[key] if params[key] && params[key] != params[:query] %>
|
||||
<% end %>
|
||||
<%= submit_tag "Go", class: "btn blue", style: "margin:0px;height:40px;width:40px" %>
|
||||
<% end %>
|
||||
</h1>
|
||||
<div id="forum_groups">
|
||||
<% counter = 0 %>
|
||||
<% @threads.each do |thread| %>
|
||||
<% counter += 1 %>
|
||||
<div class="item-group with-avatar" id="thread-<%= thread.id %>">
|
||||
<div class="header">
|
||||
<%= link_to(thread.author.avatar(64), thread.author, title: thread.author.ign) %>
|
||||
<%= render partial: "users/username", locals: { user: thread.author } %>
|
||||
<%= link_to thread do %>
|
||||
<%= ago thread.created_at %>
|
||||
<% end %>
|
||||
<span class="comment-counter">
|
||||
<%= link_to pluralize(thread.replies.count, "Reply"), thread %>
|
||||
</span>
|
||||
<div class="clear-right"></div>
|
||||
</div>
|
||||
<div class="items bold">
|
||||
<div class="item <%= "#{"locked" if thread.locked}#{"sticky" if thread.sticky}" %>">
|
||||
<%= render partial: "labels/label", locals: {label: thread.label} %><%= link_to truncate(thread.title, length: 60, omission: " …"), forumthread_path(thread), title: thread.title %>
|
||||
<div class="item-info">
|
||||
<% if rpl = thread.replies.last %>
|
||||
<%= rpl.author.name %>
|
||||
<%
|
||||
position = thread.replies.count - 1
|
||||
page = position / Kaminari.config.default_per_page + 1
|
||||
%>
|
||||
<%= link_to "replied", forumthread_path(thread, page: page) + "#reply-#{rpl.id}" %>
|
||||
<%= ago rpl.created_at %>.
|
||||
<% else %>
|
||||
No replies yet.
|
||||
<% end %>
|
||||
</div>
|
||||
<div class="clear"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<% end %>
|
||||
<% if counter == 0 %>
|
||||
<h3>No results found</h3>
|
||||
<% end %>
|
||||
<%= paginate @threads %>
|
||||
</div>
|
||||
56
app/views/forumthreads/search.html.erb
Normal file
56
app/views/forumthreads/search.html.erb
Normal file
@@ -0,0 +1,56 @@
|
||||
<% title "Thread Search" %>
|
||||
<h1>Thread Search</h1>
|
||||
<h3>Leave a field blank to ignore that search aspect.</h3>
|
||||
<% label = Label.where(name: params[:label]).first %>
|
||||
<table>
|
||||
<tbody>
|
||||
<%= form_tag({controller: "forumthreads", action: "search_redirect"}, method: :post) do %>
|
||||
<%
|
||||
forums = []
|
||||
Forum.all.sort_by{ |f| f.forumgroup && f.forumgroup.position || 0 }.each do |f|
|
||||
if current_user != nil && current_user.role_id > f.role_read_id.to_i || current_user == nil && f.role_read_id == nil
|
||||
forums << ["#{f.forumgroup.name} → #{f.name}", f.id] if f.forumgroup
|
||||
end
|
||||
end
|
||||
%>
|
||||
<% label_list = Label.pluck(:name).insert(0, "Label").insert(1, "No Label") %>
|
||||
<tr>
|
||||
<td>Forum</td>
|
||||
<td><%= select_tag "id", options_for_select(["Search All Threads"] + forums, params[:id]) %></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Label</td>
|
||||
<td>
|
||||
<%= select_tag "label", options_for_select(label_list, params[:label]), class: "auto-width" %>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Title</td>
|
||||
<td>
|
||||
<%= text_field_tag "title", params[:title], placeholder: "Search Titles" %>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Content</td>
|
||||
<td>
|
||||
<%= text_field_tag "content", params[:content], placeholder: "Search Contents" %>
|
||||
</td>
|
||||
<tr>
|
||||
<td>Author</td>
|
||||
<td>
|
||||
<%= render partial: "md_editor_user", locals: {name: "author", content: params[:author]} %>
|
||||
</td>
|
||||
</tr>
|
||||
<td>Replies</td>
|
||||
<td>
|
||||
<%= text_field_tag "reply", params[:reply], placeholder: "Search Replies" %>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<%= submit_tag "Go", class: "btn blue", style: "width:50px" %>
|
||||
</td>
|
||||
</tr>
|
||||
<% end %>
|
||||
</tbody>
|
||||
</table>
|
||||
@@ -1,14 +1,29 @@
|
||||
<%= form_tag({controller: "users", action: "search_redirect"}, method: :post, style: "margin:0px;height:40px") do %>
|
||||
<%= text_field_tag "search", nil, placeholder: "Search for a user", style: "margin:0px;height:40px;width:300px" %>
|
||||
<%= submit_tag "Go", class: "btn blue", style: "margin:0px;height:40px;width:40px" %>
|
||||
<%= hidden_field_tag "role", params[:role] %>
|
||||
<% end %>
|
||||
|
||||
<h1>
|
||||
<% if params[:role] && !params[:badge]%>
|
||||
<%= title "All '#{params[:role]}' users" %>
|
||||
<% elsif params[:badge] && !params[:role] %>
|
||||
<%= title "All '#{params[:badge]}' users" %>
|
||||
<% elsif params[:role] && params[:badge] %>
|
||||
<%= title "All '#{params[:role]}' and '#{params[:badge]}' users" %>
|
||||
<%
|
||||
if params[:role] && !params[:badge]
|
||||
text = "All '#{params[:role]}' users"
|
||||
elsif params[:badge] && !params[:role]
|
||||
text = "All '#{params[:badge]}' users"
|
||||
elsif params[:role] && params[:badge]
|
||||
text = "All '#{params[:role]}' and '#{params[:badge]}' users"
|
||||
else
|
||||
text = "All users"
|
||||
end
|
||||
text += " that contain '#{params[:search]}'" if params[:search]
|
||||
%>
|
||||
<%= title text %>
|
||||
<% if params[:search] %>
|
||||
(<%= @users.select {|u| u.name.downcase.include?(params[:search].downcase) || u.ign.downcase.include?(params[:search].downcase) }.size %>)
|
||||
<% else %>
|
||||
<%= title "All Users" %>
|
||||
(<%= @count %>)
|
||||
<% end %>
|
||||
(<%= @count %>)
|
||||
|
||||
</h1>
|
||||
<%= link_to "show all", users_path if params[:role] || params[:badge] %>
|
||||
|
||||
|
||||
@@ -27,14 +27,19 @@ Redstoner::Application.routes.draw do
|
||||
get 'lost_password'
|
||||
post 'reset_password'
|
||||
post 'suggestions'
|
||||
post 'search_redirect'
|
||||
end
|
||||
end
|
||||
|
||||
resources :forumgroups, path: '/forums/groups'
|
||||
resources :forums, path: '/forums'
|
||||
resources :forumthreads, path: '/forums/threads' do
|
||||
resources :threadreplies, path: 'replies'
|
||||
collection do
|
||||
get 'search'
|
||||
post 'search_redirect'
|
||||
end
|
||||
end
|
||||
resources :forums, path: '/forums'
|
||||
|
||||
resources :tools do
|
||||
collection do
|
||||
|
||||
8
db/migrate/20170522210610_add_search_indexes.rb
Normal file
8
db/migrate/20170522210610_add_search_indexes.rb
Normal file
@@ -0,0 +1,8 @@
|
||||
class AddSearchIndexes < ActiveRecord::Migration
|
||||
def change
|
||||
add_index :forumthreads, [:title, :content], type: :fulltext
|
||||
add_index :forumthreads, :title, type: :fulltext
|
||||
add_index :forumthreads, :content, type: :fulltext
|
||||
add_index :threadreplies, :content, type: :fulltext
|
||||
end
|
||||
end
|
||||
12
db/schema.rb
12
db/schema.rb
@@ -11,7 +11,7 @@
|
||||
#
|
||||
# It's strongly recommended that you check this file into your version control system.
|
||||
|
||||
ActiveRecord::Schema.define(version: 20170515200733) do
|
||||
ActiveRecord::Schema.define(version: 20170522210610) do
|
||||
|
||||
create_table "blogposts", force: :cascade do |t|
|
||||
t.string "title", limit: 191
|
||||
@@ -65,6 +65,10 @@ ActiveRecord::Schema.define(version: 20170515200733) do
|
||||
t.integer "label_id", limit: 4
|
||||
end
|
||||
|
||||
add_index "forumthreads", ["content"], name: "index_forumthreads_on_content", type: :fulltext
|
||||
add_index "forumthreads", ["title", "content"], name: "index_forumthreads_on_title_and_content", type: :fulltext
|
||||
add_index "forumthreads", ["title"], name: "index_forumthreads_on_title", type: :fulltext
|
||||
|
||||
create_table "info", force: :cascade do |t|
|
||||
t.string "title", limit: 191
|
||||
t.text "content", limit: 65535
|
||||
@@ -78,8 +82,8 @@ ActiveRecord::Schema.define(version: 20170515200733) do
|
||||
end
|
||||
|
||||
create_table "register_tokens", force: :cascade do |t|
|
||||
t.string "uuid", limit: 191, null: false
|
||||
t.string "token", limit: 191, null: false
|
||||
t.string "uuid", limit: 32, null: false
|
||||
t.string "token", limit: 6, null: false
|
||||
t.string "email", limit: 191, null: false
|
||||
end
|
||||
|
||||
@@ -116,6 +120,8 @@ ActiveRecord::Schema.define(version: 20170515200733) do
|
||||
t.datetime "updated_at"
|
||||
end
|
||||
|
||||
add_index "threadreplies", ["content"], name: "index_threadreplies_on_content", type: :fulltext
|
||||
|
||||
create_table "users", force: :cascade do |t|
|
||||
t.string "uuid", limit: 191, null: false
|
||||
t.string "name", limit: 191, null: false
|
||||
|
||||
Reference in New Issue
Block a user