Full text profile search for the member directory
This commit is contained in:
parent
6ac121b345
commit
616f6ae76b
|
@ -68,6 +68,11 @@ var (
|
||||||
"music_movies",
|
"music_movies",
|
||||||
"hide_age",
|
"hide_age",
|
||||||
}
|
}
|
||||||
|
EssayProfileFields = []string{
|
||||||
|
"about_me",
|
||||||
|
"interests",
|
||||||
|
"music_movies",
|
||||||
|
}
|
||||||
|
|
||||||
// Site preference names (stored in ProfileField table)
|
// Site preference names (stored in ProfileField table)
|
||||||
SitePreferenceFields = []string{
|
SitePreferenceFields = []string{
|
||||||
|
|
|
@ -32,7 +32,8 @@ func Search() http.HandlerFunc {
|
||||||
// Search filters.
|
// Search filters.
|
||||||
var (
|
var (
|
||||||
isCertified = r.FormValue("certified")
|
isCertified = r.FormValue("certified")
|
||||||
username = r.FormValue("name") // username search
|
username = r.FormValue("name") // username search
|
||||||
|
searchTerm = r.FormValue("search") // profile text search
|
||||||
gender = r.FormValue("gender")
|
gender = r.FormValue("gender")
|
||||||
orientation = r.FormValue("orientation")
|
orientation = r.FormValue("orientation")
|
||||||
maritalStatus = r.FormValue("marital_status")
|
maritalStatus = r.FormValue("marital_status")
|
||||||
|
@ -48,6 +49,8 @@ func Search() http.HandlerFunc {
|
||||||
ageMin, ageMax = ageMax, ageMin
|
ageMin, ageMax = ageMax, ageMin
|
||||||
}
|
}
|
||||||
|
|
||||||
|
search := models.ParseSearchString(searchTerm)
|
||||||
|
|
||||||
// Get current user.
|
// Get current user.
|
||||||
currentUser, err := session.CurrentUser(r)
|
currentUser, err := session.CurrentUser(r)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -91,6 +94,7 @@ func Search() http.HandlerFunc {
|
||||||
Orientation: orientation,
|
Orientation: orientation,
|
||||||
MaritalStatus: maritalStatus,
|
MaritalStatus: maritalStatus,
|
||||||
HereFor: hereFor,
|
HereFor: hereFor,
|
||||||
|
ProfileText: search,
|
||||||
Certified: isCertified == "true",
|
Certified: isCertified == "true",
|
||||||
NotCertified: isCertified == "false",
|
NotCertified: isCertified == "false",
|
||||||
InnerCircle: isCertified == "circle",
|
InnerCircle: isCertified == "circle",
|
||||||
|
@ -127,6 +131,7 @@ func Search() http.HandlerFunc {
|
||||||
"MaritalStatus": maritalStatus,
|
"MaritalStatus": maritalStatus,
|
||||||
"HereFor": hereFor,
|
"HereFor": hereFor,
|
||||||
"EmailOrUsername": username,
|
"EmailOrUsername": username,
|
||||||
|
"Search": searchTerm,
|
||||||
"AgeMin": ageMin,
|
"AgeMin": ageMin,
|
||||||
"AgeMax": ageMax,
|
"AgeMax": ageMax,
|
||||||
"FriendSearch": friendSearch,
|
"FriendSearch": friendSearch,
|
||||||
|
|
|
@ -258,6 +258,7 @@ type UserSearch struct {
|
||||||
Orientation string
|
Orientation string
|
||||||
MaritalStatus string
|
MaritalStatus string
|
||||||
HereFor string
|
HereFor string
|
||||||
|
ProfileText *Search
|
||||||
Certified bool
|
Certified bool
|
||||||
NotCertified bool
|
NotCertified bool
|
||||||
InnerCircle bool
|
InnerCircle bool
|
||||||
|
@ -364,6 +365,30 @@ func SearchUsers(user *User, search *UserSearch, pager *Pagination) ([]*User, er
|
||||||
placeholders = append(placeholders, "here_for", "%"+search.HereFor+"%")
|
placeholders = append(placeholders, "here_for", "%"+search.HereFor+"%")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Profile text search.
|
||||||
|
if terms := search.ProfileText; terms != nil {
|
||||||
|
for _, term := range terms.Includes {
|
||||||
|
var ilike = "%" + strings.ToLower(term) + "%"
|
||||||
|
wheres = append(wheres, `
|
||||||
|
EXISTS (
|
||||||
|
SELECT 1 FROM profile_fields
|
||||||
|
WHERE user_id = users.id AND name IN ? AND value ILIKE ?
|
||||||
|
)
|
||||||
|
`)
|
||||||
|
placeholders = append(placeholders, config.EssayProfileFields, ilike)
|
||||||
|
}
|
||||||
|
for _, term := range terms.Excludes {
|
||||||
|
var ilike = "%" + strings.ToLower(term) + "%"
|
||||||
|
wheres = append(wheres, `
|
||||||
|
NOT EXISTS (
|
||||||
|
SELECT 1 FROM profile_fields
|
||||||
|
WHERE user_id = users.id AND name IN ? AND value ILIKE ?
|
||||||
|
)
|
||||||
|
`)
|
||||||
|
placeholders = append(placeholders, config.EssayProfileFields, ilike)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Only admin user can show disabled/banned users.
|
// Only admin user can show disabled/banned users.
|
||||||
var statuses = []string{}
|
var statuses = []string{}
|
||||||
if user.HasAdminScope(config.ScopeUserBan) {
|
if user.HasAdminScope(config.ScopeUserBan) {
|
||||||
|
|
|
@ -6,6 +6,7 @@ import (
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"code.nonshy.com/nonshy/website/pkg/config"
|
||||||
"code.nonshy.com/nonshy/website/pkg/log"
|
"code.nonshy.com/nonshy/website/pkg/log"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -55,7 +56,7 @@ func CountNotesAboutUser(currentUser *User, user *User) int64 {
|
||||||
count int64
|
count int64
|
||||||
)
|
)
|
||||||
|
|
||||||
if currentUser.IsAdmin {
|
if currentUser.HasAdminScope(config.ScopeUserNotes) {
|
||||||
wheres = append(wheres, "about_user_id = ?")
|
wheres = append(wheres, "about_user_id = ?")
|
||||||
placeholders = append(placeholders, user.ID)
|
placeholders = append(placeholders, user.ID)
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -87,9 +87,9 @@
|
||||||
|
|
||||||
<div class="column pr-1">
|
<div class="column pr-1">
|
||||||
<div class="field">
|
<div class="field">
|
||||||
<label class="label">Status:</label>
|
<label class="label" for="certified">Status:</label>
|
||||||
<div class="select is-fullwidth">
|
<div class="select is-fullwidth">
|
||||||
<select id="certified" name="certified">
|
<select id="certified" name="certified" id="certified">
|
||||||
<optgroup label="Certification Status">
|
<optgroup label="Certification Status">
|
||||||
<option value="true">Only certified users</option>
|
<option value="true">Only certified users</option>
|
||||||
<option value="false"{{if eq $Root.Certified "false"}} selected{{end}}>Non-certified only</option>
|
<option value="false"{{if eq $Root.Certified "false"}} selected{{end}}>Non-certified only</option>
|
||||||
|
@ -115,15 +115,33 @@
|
||||||
|
|
||||||
<div class="column px-1">
|
<div class="column px-1">
|
||||||
<div class="field">
|
<div class="field">
|
||||||
<label class="label">Name or username:</label>
|
<label class="label" for="name">Name or username:</label>
|
||||||
<input type="text" class="input"
|
<input type="text" class="input"
|
||||||
name="name"
|
name="name" id="name"
|
||||||
autocomplete="off"
|
autocomplete="off"
|
||||||
value="{{$Root.EmailOrUsername}}">
|
value="{{$Root.EmailOrUsername}}">
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="column px-1">
|
<div class="column is-half pl-1">
|
||||||
|
<div class="field">
|
||||||
|
<label class="label" for="search">Profile text:</label>
|
||||||
|
<input type="text" class="input"
|
||||||
|
name="search" id="search"
|
||||||
|
autocomplete="off"
|
||||||
|
value="{{$Root.Search}}">
|
||||||
|
<p class="help">
|
||||||
|
Tip: you can <span class="has-text-success">"quote exact phrases"</span> and
|
||||||
|
<span class="has-text-success">-exclude</span> words (or
|
||||||
|
<span class="has-text-success">-"exclude phrases"</span>) from your search.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
<div class="columns is-centered">
|
||||||
|
|
||||||
|
<div class="column pr-1">
|
||||||
<div class="field">
|
<div class="field">
|
||||||
<label class="label">Age:</label>
|
<label class="label">Age:</label>
|
||||||
<div class="columns is-mobile is-gapless">
|
<div class="columns is-mobile is-gapless">
|
||||||
|
@ -151,7 +169,7 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="column pl-1">
|
<div class="column px-1">
|
||||||
<div class="field">
|
<div class="field">
|
||||||
<label class="label" for="gender">Gender:</label>
|
<label class="label" for="gender">Gender:</label>
|
||||||
<div class="select is-fullwidth">
|
<div class="select is-fullwidth">
|
||||||
|
@ -165,10 +183,7 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
</div>
|
<div class="column px-1">
|
||||||
<div class="columns is-centered">
|
|
||||||
|
|
||||||
<div class="column pr-1">
|
|
||||||
<div class="field">
|
<div class="field">
|
||||||
<label class="label" for="orientation">Orientation:</label>
|
<label class="label" for="orientation">Orientation:</label>
|
||||||
<div class="select is-fullwidth">
|
<div class="select is-fullwidth">
|
||||||
|
@ -182,7 +197,7 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="column px-1">
|
<div class="column pl-1">
|
||||||
<div class="field">
|
<div class="field">
|
||||||
<label class="label" for="marital_status">Relationship:</label>
|
<label class="label" for="marital_status">Relationship:</label>
|
||||||
<div class="select is-fullwidth">
|
<div class="select is-fullwidth">
|
||||||
|
@ -196,7 +211,10 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="column px-1">
|
</div>
|
||||||
|
<div class="columns is-centered">
|
||||||
|
|
||||||
|
<div class="column pr-1">
|
||||||
<div class="field">
|
<div class="field">
|
||||||
<label class="label" for="here_for">Here for:</label>
|
<label class="label" for="here_for">Here for:</label>
|
||||||
<div class="select is-fullwidth">
|
<div class="select is-fullwidth">
|
||||||
|
|
Loading…
Reference in New Issue
Block a user