Version 3 #40
|
@ -228,6 +228,13 @@ span.jjj-audio-clip:hover {
|
||||||
border: solid 1px lightgray;
|
border: solid 1px lightgray;
|
||||||
border-radius: .5rem;
|
border-radius: .5rem;
|
||||||
}
|
}
|
||||||
|
/* Collapse Panel styling */
|
||||||
|
a[data-bs-toggle] {
|
||||||
|
color: var(--bs-body-color);
|
||||||
|
}
|
||||||
|
a[data-bs-toggle]:hover {
|
||||||
|
text-decoration: none;
|
||||||
|
}
|
||||||
/* Footer styling */
|
/* Footer styling */
|
||||||
footer {
|
footer {
|
||||||
display: flex;
|
display: flex;
|
||||||
|
|
|
@ -100,16 +100,16 @@ let markdownEditor attrs name value editorLabel isHtmx =
|
||||||
]
|
]
|
||||||
|
|
||||||
/// Wrap content in a collapsing panel
|
/// Wrap content in a collapsing panel
|
||||||
let collapsePanel header content =
|
let collapsePanel header isShown content =
|
||||||
|
let showClass = if isShown then " show" else ""
|
||||||
div [ _class "card" ] [
|
div [ _class "card" ] [
|
||||||
div [ _class "card-body" ] [
|
div [ _class "card-header" ] [
|
||||||
h6 [ _class "card-title" ] [
|
h6 [ _class "mb-0 card-title" ] [
|
||||||
// TODO: toggle collapse
|
a [ _href "#jjjCollapse"; _data "bs-toggle" "collapse"; _roleButton; _ariaControls "#jjjCollapse"
|
||||||
//a [ _href "#"; _class "{ 'cp-c': collapsed, 'cp-o': !collapsed }"; @click.prevent="toggle">{{headerText}} ]
|
_ariaExpanded (isShown.ToString().ToLowerInvariant ()) ] [ txt header ]
|
||||||
txt header
|
|
||||||
]
|
]
|
||||||
yield! content
|
|
||||||
]
|
]
|
||||||
|
div [ _id "jjjCollapse"; _class $"card-body collapse{showClass}" ] content
|
||||||
]
|
]
|
||||||
|
|
||||||
/// "Yes" or "No" based on a boolean value
|
/// "Yes" or "No" based on a boolean value
|
||||||
|
@ -242,7 +242,7 @@ module Layout =
|
||||||
if ctx.IsLoggedOn then
|
if ctx.IsLoggedOn then
|
||||||
navLink "/citizen/dashboard" "view-dashboard-variant" "Dashboard"
|
navLink "/citizen/dashboard" "view-dashboard-variant" "Dashboard"
|
||||||
navLink "/help-wanted" "newspaper-variant-multiple-outline" "Help Wanted!"
|
navLink "/help-wanted" "newspaper-variant-multiple-outline" "Help Wanted!"
|
||||||
navLink "/profile/search" "view-list-outline" "Employment Profiles"
|
navLink "/profile/search" "view-list-outline" "Job Seekers"
|
||||||
navLink "/success-stories" "thumb-up" "Success Stories"
|
navLink "/success-stories" "thumb-up" "Success Stories"
|
||||||
div [ _class "separator" ] []
|
div [ _class "separator" ] []
|
||||||
navLink "/citizen/account" "account-edit" "My Account"
|
navLink "/citizen/account" "account-edit" "My Account"
|
||||||
|
@ -252,7 +252,7 @@ module Layout =
|
||||||
navLink "/citizen/log-off" "logout-variant" "Log Off"
|
navLink "/citizen/log-off" "logout-variant" "Log Off"
|
||||||
else
|
else
|
||||||
navLink "/" "home" "Home"
|
navLink "/" "home" "Home"
|
||||||
navLink "/profile/search" "view-list-outline" "Employment Profiles"
|
navLink "/profile/search" "view-list-outline" "Job Seekers"
|
||||||
navLink "/citizen/log-on" "login-variant" "Log On"
|
navLink "/citizen/log-on" "login-variant" "Log On"
|
||||||
navLink "/how-it-works" "help-circle-outline" "How It Works"
|
navLink "/how-it-works" "help-circle-outline" "How It Works"
|
||||||
]
|
]
|
||||||
|
|
|
@ -854,14 +854,15 @@ module Help =
|
||||||
|
|
||||||
h5 [] [ txt "Search Criteria" ]
|
h5 [] [ txt "Search Criteria" ]
|
||||||
p [] [
|
p [] [
|
||||||
txt "The employment profile search form is the same whether there is a user logged on or not; however, "
|
txt "The "; span [ linkedPage ] [ txt "Job Seekers" ]; txt " page and its search form is the same "
|
||||||
txt "the results are different. There are three sections to the search form. "
|
txt "whether there is a user logged on or not; however, the results are different. There are three "
|
||||||
strong [] [ txt "Continent" ]; txt " will select profiles from the selected continent, while "
|
txt "sections to the search form. "; strong [] [ txt "Continent" ]; txt " will select profiles from "
|
||||||
strong [] [ txt "Seeking Remote Work?" ]; txt " will select profiles based whether the citizen has "
|
txt "the selected continent, while "; strong [] [ txt "Seeking Remote Work?" ]; txt " will select "
|
||||||
txt "selected remote work in their profile. "; strong [] [ txt "Text Search" ]; txt " will search "
|
txt "profiles based whether the citizen has selected remote work in their profile. "
|
||||||
txt "several aspects of the employment profile for matches; it is case-insensitive and will match "
|
strong [] [ txt "Text Search" ]; txt " will search several aspects of the employment profile for "
|
||||||
txt "using English stemming rules (ex. searching for “force” will match words like "
|
txt "matches; it is case-insensitive and will match using English stemming rules (ex. searching for "
|
||||||
txt "“force”, “forced”, or “forcing”)."
|
txt "“force” will match words like “force”, “forced”, or "
|
||||||
|
txt "“forcing”)."
|
||||||
]
|
]
|
||||||
p [] [
|
p [] [
|
||||||
txt "If more than one field has a value selected, profiles must match all of those selections to be "
|
txt "If more than one field has a value selected, profiles must match all of those selections to be "
|
||||||
|
|
|
@ -9,41 +9,40 @@ open JobsJobsJobs.Listings.Domain
|
||||||
|
|
||||||
/// Job listing edit page
|
/// Job listing edit page
|
||||||
let edit (m : EditListingForm) continents isNew isHtmx csrf =
|
let edit (m : EditListingForm) continents isNew isHtmx csrf =
|
||||||
pageWithTitle $"""{if isNew then "Add a" else "Edit"} Job Listing""" [
|
form [ _class "row g-3"; _method "POST"; _action "/listing/save" ] [
|
||||||
form [ _class "row g-3"; _method "POST"; _action "/listing/save" ] [
|
antiForgery csrf
|
||||||
antiForgery csrf
|
input [ _type "hidden"; _name (nameof m.Id); _value m.Id ]
|
||||||
input [ _type "hidden"; _name (nameof m.Id); _value m.Id ]
|
div [ _class "col-12 col-sm-10 col-md-8 col-lg-6" ] [
|
||||||
div [ _class "col-12 col-sm-10 col-md-8 col-lg-6" ] [
|
textBox [ _type "text"; _maxlength "255"; _autofocus ] (nameof m.Title) m.Title "Title" true
|
||||||
textBox [ _type "text"; _maxlength "255"; _autofocus ] (nameof m.Title) m.Title "Title" true
|
div [ _class "form-text" ] [
|
||||||
div [ _class "form-text" ] [
|
txt "No need to put location here; it will always be show to seekers with continent and region"
|
||||||
txt "No need to put location here; it will always be show to seekers with continent and region"
|
|
||||||
]
|
|
||||||
]
|
]
|
||||||
div [ _class "col-12 col-sm-6 col-md-4" ] [
|
|
||||||
continentList [] (nameof m.ContinentId) continents None m.ContinentId true
|
|
||||||
]
|
|
||||||
div [ _class "col-12 col-sm-6 col-md-8" ] [
|
|
||||||
textBox [ _type "text"; _maxlength "255" ] (nameof m.Region) m.Region "Region" true
|
|
||||||
div [ _class "form-text" ] [ txt "Country, state, geographic area, etc." ]
|
|
||||||
]
|
|
||||||
div [ _class "col-12" ] [
|
|
||||||
checkBox [] (nameof m.RemoteWork) m.RemoteWork "This opportunity is for remote work"
|
|
||||||
]
|
|
||||||
markdownEditor [ _required ] (nameof m.Text) m.Text "Job Description" isHtmx
|
|
||||||
div [ _class "col-12 col-md-4" ] [
|
|
||||||
textBox [ _type "date" ] (nameof m.NeededBy) m.NeededBy "Needed By" false
|
|
||||||
]
|
|
||||||
div [ _class "col-12" ] [ submitButton "content-save-outline" "Save" ]
|
|
||||||
]
|
]
|
||||||
|
div [ _class "col-12 col-sm-6 col-md-4" ] [
|
||||||
|
continentList [] (nameof m.ContinentId) continents None m.ContinentId true
|
||||||
|
]
|
||||||
|
div [ _class "col-12 col-sm-6 col-md-8" ] [
|
||||||
|
textBox [ _type "text"; _maxlength "255" ] (nameof m.Region) m.Region "Region" true
|
||||||
|
div [ _class "form-text" ] [ txt "Country, state, geographic area, etc." ]
|
||||||
|
]
|
||||||
|
div [ _class "col-12" ] [
|
||||||
|
checkBox [] (nameof m.RemoteWork) m.RemoteWork "This opportunity is for remote work"
|
||||||
|
]
|
||||||
|
markdownEditor [ _required ] (nameof m.Text) m.Text "Job Description" isHtmx
|
||||||
|
div [ _class "col-12 col-md-4" ] [
|
||||||
|
textBox [ _type "date" ] (nameof m.NeededBy) m.NeededBy "Needed By" false
|
||||||
|
]
|
||||||
|
div [ _class "col-12" ] [ submitButton "content-save-outline" "Save" ]
|
||||||
]
|
]
|
||||||
|
|> List.singleton
|
||||||
|
|> pageWithTitle $"""{if isNew then "Add a" else "Edit"} Job Listing"""
|
||||||
|
|
||||||
|
|
||||||
open System.Net
|
open System.Net
|
||||||
|
|
||||||
/// Page to expire a job listing
|
/// Page to expire a job listing
|
||||||
let expire (m : ExpireListingForm) (listing : Listing) isHtmx csrf =
|
let expire (m : ExpireListingForm) (listing : Listing) isHtmx csrf =
|
||||||
pageWithTitle $"Expire Job Listing ({WebUtility.HtmlEncode listing.Title})" [
|
[ p [ _class "fst-italic" ] [
|
||||||
p [ _class "fst-italic" ] [
|
|
||||||
txt "Expiring this listing will remove it from search results. You will be able to see it via your "
|
txt "Expiring this listing will remove it from search results. You will be able to see it via your "
|
||||||
txt "“My Job Listings” page, but you will not be able to “un-expire” it."
|
txt "“My Job Listings” page, but you will not be able to “un-expire” it."
|
||||||
]
|
]
|
||||||
|
@ -65,14 +64,14 @@ let expire (m : ExpireListingForm) (listing : Listing) isHtmx csrf =
|
||||||
]
|
]
|
||||||
jsOnLoad "jjj.listing.toggleFromHere()" isHtmx
|
jsOnLoad "jjj.listing.toggleFromHere()" isHtmx
|
||||||
]
|
]
|
||||||
|
|> pageWithTitle $"Expire Job Listing ({WebUtility.HtmlEncode listing.Title})"
|
||||||
|
|
||||||
|
|
||||||
/// "My Listings" page
|
/// "My Listings" page
|
||||||
let mine (listings : ListingForView list) tz =
|
let mine (listings : ListingForView list) tz =
|
||||||
let active = listings |> List.filter (fun it -> not it.Listing.IsExpired)
|
let active = listings |> List.filter (fun it -> not it.Listing.IsExpired)
|
||||||
let expired = listings |> List.filter (fun it -> it.Listing.IsExpired)
|
let expired = listings |> List.filter (fun it -> it.Listing.IsExpired)
|
||||||
pageWithTitle "My Job Listings" [
|
[ p [] [ a [ _href "/listing/new/edit"; _class "btn btn-outline-primary" ] [ txt "Add a New Job Listing" ] ]
|
||||||
p [] [ a [ _href "/listing/new/edit"; _class "btn btn-outline-primary" ] [ txt "Add a New Job Listing" ] ]
|
|
||||||
if not (List.isEmpty expired) then h4 [ _class "pb-2" ] [ txt "Active Job Listings" ]
|
if not (List.isEmpty expired) then h4 [ _class "pb-2" ] [ txt "Active Job Listings" ]
|
||||||
if List.isEmpty active then p [ _class "pb-3 fst-italic" ] [ txt "You have no active job listings" ]
|
if List.isEmpty active then p [ _class "pb-3 fst-italic" ] [ txt "You have no active job listings" ]
|
||||||
else
|
else
|
||||||
|
@ -117,6 +116,7 @@ let mine (listings : ListingForView list) tz =
|
||||||
|> tbody []
|
|> tbody []
|
||||||
]
|
]
|
||||||
]
|
]
|
||||||
|
|> pageWithTitle "My Job Listings"
|
||||||
|
|
||||||
open NodaTime.Text
|
open NodaTime.Text
|
||||||
|
|
||||||
|
@ -125,13 +125,12 @@ let private neededBy dt =
|
||||||
(LocalDatePattern.CreateWithCurrentCulture "MMMM d, yyyy").Format dt
|
(LocalDatePattern.CreateWithCurrentCulture "MMMM d, yyyy").Format dt
|
||||||
|
|
||||||
let search (m : ListingSearchForm) continents (listings : ListingForView list option) =
|
let search (m : ListingSearchForm) continents (listings : ListingForView list option) =
|
||||||
pageWithTitle "Help Wanted" [
|
[ if Option.isNone listings then
|
||||||
if Option.isNone listings then
|
|
||||||
p [] [
|
p [] [
|
||||||
txt "Enter relevant criteria to find results, or just click “Search” to see all active job "
|
txt "Enter relevant criteria to find results, or just click “Search” to see all active job "
|
||||||
txt "listings."
|
txt "listings."
|
||||||
]
|
]
|
||||||
collapsePanel "Search Criteria" [
|
collapsePanel "Search Criteria" (List.isEmpty (defaultArg listings [])) [
|
||||||
form [ _class "container"; _method "GET"; _action "/help-wanted" ] [
|
form [ _class "container"; _method "GET"; _action "/help-wanted" ] [
|
||||||
input [ _type "hidden"; _name "searched"; _value "true" ]
|
input [ _type "hidden"; _name "searched"; _value "true" ]
|
||||||
div [ _class "row" ] [
|
div [ _class "row" ] [
|
||||||
|
@ -201,11 +200,12 @@ let search (m : ListingSearchForm) continents (listings : ListingForView list op
|
||||||
]
|
]
|
||||||
| None -> ()
|
| None -> ()
|
||||||
]
|
]
|
||||||
|
|> pageWithTitle "Help Wanted"
|
||||||
|
|
||||||
/// The job listing view page
|
/// The job listing view page
|
||||||
let view (it : ListingForView) =
|
let view (it : ListingForView) =
|
||||||
article [] [
|
article [] [
|
||||||
h3 [] [
|
h3 [ _class "mb-1" ] [
|
||||||
str it.Listing.Title
|
str it.Listing.Title
|
||||||
if it.Listing.IsExpired then
|
if it.Listing.IsExpired then
|
||||||
span [ _class "jjj-heading-label" ] [
|
span [ _class "jjj-heading-label" ] [
|
||||||
|
@ -214,11 +214,17 @@ let view (it : ListingForView) =
|
||||||
txt " "; span [ _class "badge bg-success" ] [ txt "Filled via Jobs, Jobs, Jobs" ]
|
txt " "; span [ _class "badge bg-success" ] [ txt "Filled via Jobs, Jobs, Jobs" ]
|
||||||
]
|
]
|
||||||
]
|
]
|
||||||
h4 [ _class "pb-3 text-muted" ] [ str it.ContinentName; rawText " / "; str it.Listing.Region ]
|
h4 [ _class "mb-3 text-muted" ] [
|
||||||
|
str $"{it.ContinentName} / {it.Listing.Region}"
|
||||||
|
if it.Listing.IsRemote then
|
||||||
|
span [ _class "jjj-heading-label" ] [
|
||||||
|
txt " "; span [ _class "badge text-bg-info" ] [ txt "Remote" ]
|
||||||
|
]
|
||||||
|
]
|
||||||
p [] [
|
p [] [
|
||||||
match it.Listing.NeededBy with
|
match it.Listing.NeededBy with
|
||||||
| Some needed ->
|
| Some needed ->
|
||||||
strong [] [ em [] [ txt "NEEDED BY "; str ((neededBy needed).ToUpperInvariant ()) ] ]; txt " • "
|
strong [] [ em [] [ txt "NEEDED BY "; str ((neededBy needed).ToUpperInvariant ()) ] ]; br [] // txt " • "
|
||||||
| None -> ()
|
| None -> ()
|
||||||
txt "Listed by "; strong [ _class "me-4" ] [ str (Citizen.name it.Citizen) ]; br []
|
txt "Listed by "; strong [ _class "me-4" ] [ str (Citizen.name it.Citizen) ]; br []
|
||||||
span [ _class "ms-3" ] []; yield! contactInfo it.Citizen false
|
span [ _class "ms-3" ] []; yield! contactInfo it.Citizen false
|
||||||
|
|
|
@ -354,8 +354,8 @@ let editHistory (history : EmploymentHistory list) idx csrf =
|
||||||
// ~~~ PROFILE SEARCH ~~~ //
|
// ~~~ PROFILE SEARCH ~~~ //
|
||||||
|
|
||||||
/// The search form
|
/// The search form
|
||||||
let private searchForm (m : ProfileSearchForm) continents =
|
let private searchForm (m : ProfileSearchForm) continents isShown =
|
||||||
collapsePanel "Search Criteria" [
|
collapsePanel "Search Criteria" isShown [
|
||||||
form [ _class "container"; _method "GET"; _action "/profile/search" ] [
|
form [ _class "container"; _method "GET"; _action "/profile/search" ] [
|
||||||
input [ _type "hidden"; _name "searched"; _value "true" ]
|
input [ _type "hidden"; _name "searched"; _value "true" ]
|
||||||
div [ _class "row" ] [
|
div [ _class "row" ] [
|
||||||
|
@ -474,7 +474,7 @@ let search m continents tz (results : ProfileForView list option) isPublic =
|
||||||
if isPublic then txt "publicly searchable or viewable "
|
if isPublic then txt "publicly searchable or viewable "
|
||||||
txt "profiles."
|
txt "profiles."
|
||||||
]
|
]
|
||||||
searchForm m continents
|
searchForm m continents (List.isEmpty (defaultArg results []))
|
||||||
match results with
|
match results with
|
||||||
| Some r when List.isEmpty r -> p [ _class "pt-3" ] [ txt "No results found for the specified criteria" ]
|
| Some r when List.isEmpty r -> p [ _class "pt-3" ] [ txt "No results found for the specified criteria" ]
|
||||||
| Some r -> if isPublic then yield! publicResults r else privateResults r tz
|
| Some r -> if isPublic then yield! publicResults r else privateResults r tz
|
||||||
|
|
Loading…
Reference in New Issue
Block a user