Version 3 #40

Merged
danieljsummers merged 67 commits from version-2-3 into main 2023-02-02 23:47:28 +00:00
5 changed files with 68 additions and 54 deletions
Showing only changes of commit de0883b898 - Show all commits

View File

@ -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;

View File

@ -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"
] ]

View File

@ -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 "

View File

@ -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

View File

@ -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