WIP on skill add/remove

This commit is contained in:
Daniel J. Summers 2023-01-13 09:17:35 -05:00
parent 7096368b6e
commit 13f688496a
3 changed files with 81 additions and 13 deletions

View File

@ -60,7 +60,11 @@ module EditProfileViewModel =
FullTime = false FullTime = false
Biography = "" Biography = ""
Experience = None Experience = None
Skills = [||] Skills = [|
{ Id = "1"; Description = "test 1"; Notes = None }
{ Id = "3"; Description = "test 2"; Notes = Some "noted" }
{ Id = "4"; Description = "asfasdfa"; Notes = None }
|]
} }
/// Create an instance of this form from the given profile /// Create an instance of this form from the given profile

View File

@ -7,12 +7,13 @@ open Giraffe.ViewEngine
open Giraffe.ViewEngine.Htmx open Giraffe.ViewEngine.Htmx
open JobsJobsJobs.ViewModels open JobsJobsJobs.ViewModels
/// Render the skill edit template and existing skills
let skillEdit (skills : SkillForm array) = let skillEdit (skills : SkillForm array) =
let mapToInputs (idx : int) (skill : SkillForm) = let mapToInputs (idx : int) (skill : SkillForm) =
div [ _class "row pb-3" ] [ div [ _id $"skillRow{skill.Id}"; _class "row pb-3" ] [
div [ _class "col-2 col-md-1 align-self-center" ] [ div [ _class "col-2 col-md-1 align-self-center" ] [
button [ _class "btn btn-sm btn-outline-danger rounded-pill"; _title "Delete" button [ _class "btn btn-sm btn-outline-danger rounded-pill"; _title "Delete"
_onclick $"jjj.removeSkill('{skill.Id}')" ] [ _onclick $"jjj.profile.removeSkill('{skill.Id}')" ] [
rawText " − " rawText " − "
] ]
] ]
@ -23,7 +24,8 @@ let skillEdit (skills : SkillForm array) =
_maxlength "200"; _value skill.Description; _required ] _maxlength "200"; _value skill.Description; _required ]
label [ _class "jjj-label"; _for $"skillDesc{skill.Id}" ] [ rawText "Skill" ] label [ _class "jjj-label"; _for $"skillDesc{skill.Id}" ] [ rawText "Skill" ]
] ]
div [ _class "form-text" ] [ rawText "A skill (language, design technique, process, etc.)" ] if idx < 1 then
div [ _class "form-text" ] [ rawText "A skill (language, design technique, process, etc.)" ]
] ]
div [ _class "col-12 col-md-5" ] [ div [ _class "col-12 col-md-5" ] [
div [ _class "form-floating" ] [ div [ _class "form-floating" ] [
@ -33,7 +35,8 @@ let skillEdit (skills : SkillForm array) =
_value (defaultArg skill.Notes "") ] _value (defaultArg skill.Notes "") ]
label [ _class "jjj-label"; _for $"skillNotes{skill.Id}" ] [ rawText "Notes" ] label [ _class "jjj-label"; _for $"skillNotes{skill.Id}" ] [ rawText "Notes" ]
] ]
div [ _class "form-text" ] [ rawText "A further description of the skill" ] if idx < 1 then
div [ _class "form-text" ] [ rawText "A further description of the skill" ]
] ]
] ]
template [ _id "newSkill" ] [ mapToInputs -1 { Id = ""; Description = ""; Notes = None } ] template [ _id "newSkill" ] [ mapToInputs -1 { Id = ""; Description = ""; Notes = None } ]
@ -97,7 +100,7 @@ let edit (m : EditProfileViewModel) continents isNew csrf =
hr [] hr []
h4 [ _class "pb-2" ] [ h4 [ _class "pb-2" ] [
rawText "Skills &nbsp; " rawText "Skills &nbsp; "
button [ _class "btn btn-sm btn-outline-primary rounded-pill"; _onclick "jjj.addSkill" ] [ button [ _class "btn btn-sm btn-outline-primary rounded-pill"; _onclick "jjj.profile.addSkill()" ] [
rawText "Add a Skill" rawText "Add a Skill"
] ]
] ]
@ -140,4 +143,9 @@ let edit (m : EditProfileViewModel) continents isNew csrf =
rawText "(If you want to delete your profile, or your entire account, " rawText "(If you want to delete your profile, or your entire account, "
a [ _href "/so-long/options" ] [ rawText "see your deletion options here" ]; rawText ".)" a [ _href "/so-long/options" ] [ rawText "see your deletion options here" ]; rawText ".)"
] ]
script [] [
rawText """addEventListener("DOMContentLoaded", function () {"""
rawText $" jjj.profile.nextIndex = {m.Skills.Length} "
rawText "})"
]
] ]

View File

@ -41,17 +41,73 @@ this.jjj = {
/** /**
* The time zone of the current browser * The time zone of the current browser
* @type {string} * @type {string}
**/ */
timeZone: undefined, timeZone: undefined,
/** /**
* Derive the time zone from the current browser * Derive the time zone from the current browser
*/ */
deriveTimeZone () { deriveTimeZone () {
try { try {
this.timeZone = (new Intl.DateTimeFormat()).resolvedOptions().timeZone this.timeZone = (new Intl.DateTimeFormat()).resolvedOptions().timeZone
} catch (_) { } } catch (_) { }
} },
/**
* Script for profile pages
*/
profile: {
/**
* The next index for a newly-added skill
* @type {number}
*/
nextIndex: 0,
/**
* Add a skill to the profile form
*/
addSkill() {
const newId = `new${this.nextIndex}`
/** @type {HTMLTemplateElement} */
const newSkillTemplate = document.getElementById("newSkill")
/** @type {HTMLDivElement} */
const newSkill = newSkillTemplate.content.firstElementChild.cloneNode(true)
newSkill.setAttribute("id", `skillRow${newId}`)
const cols = newSkill.children
// Button column
cols[0].querySelector("button").setAttribute("onclick", `jjj.profile.removeSkill('${newId}')`)
// Skill column
const skillField = cols[1].querySelector("input")
skillField.setAttribute("id", `skillDesc${newId}`)
skillField.setAttribute("name", `Skills[${this.nextIndex}].Description`)
cols[1].querySelector("label").setAttribute("for", `skillDesc${newId}`)
if (this.nextIndex > 0) cols[1].querySelector("div.form-text").remove()
// Notes column
const notesField = cols[2].querySelector("input")
notesField.setAttribute("id", `skillNotes${newId}`)
notesField.setAttribute("name", `Skills[${this.nextIndex}].Notes`)
cols[2].querySelector("label").setAttribute("for", `skillNotes${newId}`)
if (this.nextIndex > 0) cols[2].querySelector("div.form-text").remove()
// Add the row
const skills = document.querySelectorAll("div[id^=skillRow]")
const sibling = skills.length > 0 ? skills[skills.length - 1] : newSkillTemplate
sibling.insertAdjacentElement('afterend', newSkill)
this.nextIndex++
},
/**
* Remove a skill row from the profile form
* @param {string} id The ID of the skill row to remove
*/
removeSkill(id) {
document.getElementById(`skillRow${id}`).remove()
}
}
} }
htmx.on("htmx:configRequest", function (evt) { htmx.on("htmx:configRequest", function (evt) {