Both searches done

This commit is contained in:
Daniel J. Summers 2021-08-08 21:25:00 -04:00
parent 33c0e5ff5b
commit 4a10f5413d
5 changed files with 52 additions and 41 deletions

View File

@ -188,6 +188,11 @@ let withReconn (conn : IConnection) =
(conn :?> Connection).Reconnect()
| false -> ()))
/// Sanitize user input, and create a "contains" pattern for use with RethinkDB queries
let regexContains (it : string) =
System.Text.RegularExpressions.Regex.Escape it
|> sprintf "(?i).*%s.*"
open JobsJobsJobs.Domain.SharedTypes
open RethinkDb.Driver.Ast
@ -251,14 +256,14 @@ module Profile =
match srch.skill with
| Some skl ->
yield (fun q -> q.Filter(ReqlFunction1(fun it ->
upcast it.G("skills.description").Downcase().Match(skl.ToLowerInvariant ()))) :> ReqlExpr)
upcast it.G("skills").Contains(ReqlFunction1(fun s ->
upcast s.G("description").Match(regexContains skl))))) :> ReqlExpr)
| None -> ()
match srch.bioExperience with
| Some text ->
let txt = text.ToLowerInvariant ()
let txt = regexContains text
yield (fun q -> q.Filter(ReqlFunction1(fun it ->
upcast it.G("biography" ).Downcase().Match(txt)
.Or(it.G("experience").Downcase().Match(txt)))) :> ReqlExpr)
upcast it.G("biography").Match(txt).Or(it.G("experience").Match(txt)))) :> ReqlExpr)
| None -> ()
}
|> Seq.toList
@ -290,8 +295,7 @@ module Profile =
match srch.region with
| Some reg ->
yield (fun q ->
q.Filter(ReqlFunction1(fun it ->
upcast it.G("region").Downcase().Match(reg.ToLowerInvariant ()))) :> ReqlExpr)
q.Filter(ReqlFunction1(fun it -> upcast it.G("region").Match(regexContains reg))) :> ReqlExpr)
| None -> ()
match srch.remoteWork with
| "" -> ()
@ -299,7 +303,8 @@ module Profile =
match srch.skill with
| Some skl ->
yield (fun q -> q.Filter(ReqlFunction1(fun it ->
upcast it.G("skills.description").Downcase().Match(skl.ToLowerInvariant ()))) :> ReqlExpr)
upcast it.G("skills").Contains(ReqlFunction1(fun s ->
upcast s.G("description").Match(regexContains skl))))) :> ReqlExpr)
| None -> ()
}
|> Seq.toList
@ -315,7 +320,7 @@ module Profile =
.HashMap("skills",
it.G("skills").Map(ReqlFunction1(fun skill ->
upcast r.Branch(skill.G("notes").Default_("").Eq(""), skill.G("description"),
sprintf "%O (%O)" (skill.G("description")) (skill.G("notes"))))))
skill.G("description").Add(" (").Add(skill.G("notes")).Add(")")))))
.With("continent", it.G("name"))))
.Pluck("continent", "region", "skills", "remoteWork")
.RunResultAsync<PublicSearchResult list> conn)

View File

@ -146,7 +146,7 @@ export default {
publicSearch: async (query : PublicSearch) : Promise<PublicSearchResult[] | string | undefined> => {
const params = new URLSearchParams()
if (query.continentId) params.append('continentId', query.continentId)
if (query.region) params.append('bioExperience', query.region)
if (query.region) params.append('region', query.region)
if (query.skill) params.append('skill', query.skill)
params.append('remoteWork', query.remoteWork)
return apiResult<PublicSearchResult[]>(

View File

@ -2,17 +2,19 @@
<div class="card">
<div class="card-body">
<h6 class="card-title">
<a href="#" :class="{ 'cp-c': isCollapsed, 'cp-o': !isCollapsed }" @click.prevent="toggle">{{headerText}}</a>
<a href="#" :class="{ 'cp-c': collapsed, 'cp-o': !collapsed }" @click.prevent="toggle">{{headerText}}</a>
</h6>
<slot v-if="!isCollapsed"></slot>
<slot v-if="!collapsed"></slot>
</div>
</div>
</template>
<script lang="ts">
import { defineComponent, ref } from 'vue'
import { defineComponent } from 'vue'
export default defineComponent({
name: 'CollapsePanel',
emits: ['toggle'],
props: {
headerText: {
type: String,
@ -23,13 +25,9 @@ export default defineComponent({
default: false
}
},
setup (props) {
/** Whether the panel is collapsed or not */
const isCollapsed = ref(props.collapsed)
setup (props, { emit }) {
return {
isCollapsed,
toggle: () => { isCollapsed.value = !isCollapsed.value }
toggle: () => emit('toggle', !props.collapsed)
}
}
})

View File

@ -1,19 +1,18 @@
<template>
<article>
<page-title title="Search Profiles" />
<h3>Search Profiles</h3>
<h3 class="pb-3">Search Profiles</h3>
<error-list :errors="errors">
<p v-if="searching">Searching profiles...</p>
<template v-else>
<p v-if="!searched">
Enter one or more criteria to filter results, or just click &ldquo;Search&rdquo; to list all profiles.
</p>
<collapse-panel headerText="Search Criteria" :collapsed="searched && results.length > 0">
<collapse-panel headerText="Search Criteria" :collapsed="isCollapsed" @toggle="toggleCollapse">
<profile-search-form v-model="criteria" @search="doSearch" />
</collapse-panel>
<br>
<table v-if="results.length > 0" class="table table-sm table-hover">
<error-list :errors="errors">
<p v-if="searching" class="pt-3">Searching profiles...</p>
<template v-else>
<table v-if="results.length > 0" class="table table-sm table-hover pt-3">
<thead>
<tr>
<th scope="col">Profile</th>
@ -35,7 +34,7 @@
</tr>
</tbody>
</table>
<p v-else-if="searched">No results found for the specified criteria</p>
<p v-else-if="searched" class="pt-3">No results found for the specified criteria</p>
</template>
</error-list>
</article>
@ -90,6 +89,9 @@ export default defineComponent({
/** The current search results */
const results : Ref<ProfileSearchResult[]> = ref([])
/** Whether the search criteria should be collapsed */
const isCollapsed = ref(searched.value && results.value.length > 0)
/** Set up the page to match its requested state */
const setUpPage = async () => {
if (queryValue(route, 'searched') === 'true') {
@ -114,6 +116,7 @@ export default defineComponent({
} finally {
searching.value = false
}
isCollapsed.value = searched.value && results.value.length > 0
} else {
searched.value = false
criteria.value = emptyCriteria
@ -127,6 +130,8 @@ export default defineComponent({
return {
errors,
criteria,
isCollapsed,
toggleCollapse: (it : boolean) => { isCollapsed.value = it },
doSearch: () => router.push({ query: { searched: 'true', ...criteria.value } }),
searching,
searched,

View File

@ -1,20 +1,19 @@
<template>
<article>
<page-title title="People Seeking Work" />
<h3>People Seeking Work</h3>
<h3 class="pb-3">People Seeking Work</h3>
<error-list :errors="errors">
<p v-if="searching">Searching profiles...</p>
<template v-else>
<p v-if="!searched">
Enter one or more criteria to filter results, or just click &ldquo;Search&rdquo; to list all profiles.
</p>
<collapse-panel headerText="Search Criteria" :collapsed="searched && results.length > 0">
<collapse-panel headerText="Search Criteria" :collapsed="isCollapsed" @toggle="toggleCollapse">
<profile-public-search-form v-model="criteria" @search="doSearch" />
</collapse-panel>
<br>
<error-list :errors="errors">
<p v-if="searching">Searching profiles...</p>
<template v-else>
<template v-if="results.length > 0">
<p>
<p class="pb-3 pt-3">
These profiles match your search criteria. To learn more about these people, join the merry band of human
resources in the <a href="https://noagendashow.net" target="_blank">No Agenda</a> tribe!
</p>
@ -39,9 +38,7 @@
</tbody>
</table>
</template>
<template v-else>
<p v-if="searched">No results found for the specified criteria</p>
</template>
<p v-else-if="searched" class="pt-3">No results found for the specified criteria</p>
</template>
</error-list>
</article>
@ -91,6 +88,9 @@ export default defineComponent({
/** The search results */
const results : Ref<PublicSearchResult[]> = ref([])
/** Whether the search results are collapsed */
const isCollapsed = ref(searched.value && results.value.length > 0)
/** Set up the page to match its requested state */
const setUpPage = async () => {
if (queryValue(route, 'searched') === 'true') {
@ -115,6 +115,7 @@ export default defineComponent({
} finally {
searching.value = false
}
isCollapsed.value = searched.value && results.value.length > 0
} else {
searched.value = false
criteria.value = emptyCriteria
@ -128,6 +129,8 @@ export default defineComponent({
return {
errors,
criteria,
isCollapsed,
toggleCollapse: (it : boolean) => { isCollapsed.value = it },
doSearch: () => router.push({ query: { searched: 'true', ...criteria.value } }),
searching,
searched,