diff --git a/handlers/workOrders-post/doUpdateWorkOrderMilestone.d.ts b/handlers/workOrders-post/doUpdateWorkOrderMilestone.d.ts new file mode 100644 index 00000000..9621c611 --- /dev/null +++ b/handlers/workOrders-post/doUpdateWorkOrderMilestone.d.ts @@ -0,0 +1,3 @@ +import type { RequestHandler } from "express"; +export declare const handler: RequestHandler; +export default handler; diff --git a/handlers/workOrders-post/doUpdateWorkOrderMilestone.js b/handlers/workOrders-post/doUpdateWorkOrderMilestone.js new file mode 100644 index 00000000..54783961 --- /dev/null +++ b/handlers/workOrders-post/doUpdateWorkOrderMilestone.js @@ -0,0 +1,11 @@ +import { updateWorkOrderMilestone } from "../../helpers/lotOccupancyDB/updateWorkOrderMilestone.js"; +import { getWorkOrderMilestones } from "../../helpers/lotOccupancyDB/getWorkOrderMilestones.js"; +export const handler = async (request, response) => { + const success = updateWorkOrderMilestone(request.body, request.session); + const workOrderMilestones = getWorkOrderMilestones(request.body.workOrderId); + response.json({ + success, + workOrderMilestones + }); +}; +export default handler; diff --git a/handlers/workOrders-post/doUpdateWorkOrderMilestone.ts b/handlers/workOrders-post/doUpdateWorkOrderMilestone.ts new file mode 100644 index 00000000..d9a97503 --- /dev/null +++ b/handlers/workOrders-post/doUpdateWorkOrderMilestone.ts @@ -0,0 +1,19 @@ +import type { RequestHandler } from "express"; + +import { updateWorkOrderMilestone } from "../../helpers/lotOccupancyDB/updateWorkOrderMilestone.js"; +import { getWorkOrderMilestones } from "../../helpers/lotOccupancyDB/getWorkOrderMilestones.js"; + +export const handler: RequestHandler = async (request, response) => { + const success = updateWorkOrderMilestone(request.body, request.session); + + const workOrderMilestones = getWorkOrderMilestones( + request.body.workOrderId + ); + + response.json({ + success, + workOrderMilestones + }); +}; + +export default handler; diff --git a/helpers/lotOccupancyDB/updateWorkOrderMilestone.d.ts b/helpers/lotOccupancyDB/updateWorkOrderMilestone.d.ts new file mode 100644 index 00000000..fbe65e96 --- /dev/null +++ b/helpers/lotOccupancyDB/updateWorkOrderMilestone.d.ts @@ -0,0 +1,10 @@ +import type * as recordTypes from "../../types/recordTypes"; +interface UpdateWorkOrderMilestoneForm { + workOrderMilestoneId: string | number; + workOrderMilestoneTypeId?: number | string; + workOrderMilestoneDateString: string; + workOrderMilestoneTimeString?: string; + workOrderMilestoneDescription: string; +} +export declare const updateWorkOrderMilestone: (milestoneForm: UpdateWorkOrderMilestoneForm, requestSession: recordTypes.PartialSession) => boolean; +export default updateWorkOrderMilestone; diff --git a/helpers/lotOccupancyDB/updateWorkOrderMilestone.js b/helpers/lotOccupancyDB/updateWorkOrderMilestone.js new file mode 100644 index 00000000..2fe026ef --- /dev/null +++ b/helpers/lotOccupancyDB/updateWorkOrderMilestone.js @@ -0,0 +1,22 @@ +import sqlite from "better-sqlite3"; +import { lotOccupancyDB as databasePath } from "../../data/databasePaths.js"; +import { dateStringToInteger, timeStringToInteger } from "@cityssm/expressjs-server-js/dateTimeFns.js"; +export const updateWorkOrderMilestone = (milestoneForm, requestSession) => { + const rightNow = new Date(); + const database = sqlite(databasePath); + const result = database + .prepare("update WorkOrderMilestones" + + " set workOrderMilestoneTypeId = ?," + + " workOrderMilestoneDate = ?," + + " workOrderMilestoneTime = ?," + + " workOrderMilestoneDescription = ?," + + " recordUpdate_userName = ?," + + " recordUpdate_timeMillis = ?" + + " where workOrderMilestoneId = ?") + .run(milestoneForm.workOrderMilestoneTypeId || undefined, dateStringToInteger(milestoneForm.workOrderMilestoneDateString), milestoneForm.workOrderMilestoneTimeString + ? timeStringToInteger(milestoneForm.workOrderMilestoneTimeString) + : 0, milestoneForm.workOrderMilestoneDescription, requestSession.user.userName, rightNow.getTime(), milestoneForm.workOrderMilestoneId); + database.close(); + return result.changes > 0; +}; +export default updateWorkOrderMilestone; diff --git a/helpers/lotOccupancyDB/updateWorkOrderMilestone.ts b/helpers/lotOccupancyDB/updateWorkOrderMilestone.ts new file mode 100644 index 00000000..18f333a8 --- /dev/null +++ b/helpers/lotOccupancyDB/updateWorkOrderMilestone.ts @@ -0,0 +1,59 @@ +import sqlite from "better-sqlite3"; + +import { lotOccupancyDB as databasePath } from "../../data/databasePaths.js"; + +import { + dateStringToInteger, + timeStringToInteger +} from "@cityssm/expressjs-server-js/dateTimeFns.js"; + +import type * as recordTypes from "../../types/recordTypes"; + +interface UpdateWorkOrderMilestoneForm { + workOrderMilestoneId: string | number; + workOrderMilestoneTypeId?: number | string; + workOrderMilestoneDateString: string; + workOrderMilestoneTimeString?: string; + workOrderMilestoneDescription: string; +} + +export const updateWorkOrderMilestone = ( + milestoneForm: UpdateWorkOrderMilestoneForm, + requestSession: recordTypes.PartialSession +): boolean => { + const rightNow = new Date(); + + const database = sqlite(databasePath); + + const result = database + .prepare( + "update WorkOrderMilestones" + + " set workOrderMilestoneTypeId = ?," + + " workOrderMilestoneDate = ?," + + " workOrderMilestoneTime = ?," + + " workOrderMilestoneDescription = ?," + + " recordUpdate_userName = ?," + + " recordUpdate_timeMillis = ?" + + " where workOrderMilestoneId = ?" + ) + .run( + milestoneForm.workOrderMilestoneTypeId || undefined, + dateStringToInteger(milestoneForm.workOrderMilestoneDateString), + milestoneForm.workOrderMilestoneTimeString + ? timeStringToInteger( + milestoneForm.workOrderMilestoneTimeString + ) + : 0, + milestoneForm.workOrderMilestoneDescription, + + requestSession.user.userName, + rightNow.getTime(), + milestoneForm.workOrderMilestoneId + ); + + database.close(); + + return result.changes > 0; +}; + +export default updateWorkOrderMilestone; diff --git a/public-typescript/workOrderEdit.js b/public-typescript/workOrderEdit.js index 507dc5e2..581683f8 100644 --- a/public-typescript/workOrderEdit.js +++ b/public-typescript/workOrderEdit.js @@ -676,6 +676,66 @@ Object.defineProperty(exports, "__esModule", { value: true }); }; const editMilestone = (clickEvent) => { clickEvent.preventDefault(); + const workOrderMilestoneId = Number.parseInt(clickEvent.currentTarget.closest(".container--milestone").dataset.workOrderMilestoneId, 10); + const workOrderMilestone = workOrderMilestones.find((currentMilestone) => { + return (currentMilestone.workOrderMilestoneId === + workOrderMilestoneId); + }); + let editCloseModalFunction; + const doEdit = (submitEvent) => { + submitEvent.preventDefault(); + cityssm.postJSON(urlPrefix + "/workOrders/doUpdateWorkOrderMilestone", submitEvent.currentTarget, (responseJSON) => { + processMilestoneResponse(responseJSON); + if (responseJSON.success) { + editCloseModalFunction(); + } + }); + }; + cityssm.openHtmlModal("workOrder-editMilestone", { + onshow: (modalElement) => { + modalElement.querySelector("#milestoneEdit--workOrderId").value = workOrderId; + modalElement.querySelector("#milestoneEdit--workOrderMilestoneId").value = + workOrderMilestone.workOrderMilestoneId.toString(); + const milestoneTypeElement = modalElement.querySelector("#milestoneEdit--workOrderMilestoneTypeId"); + let milestoneTypeFound = false; + for (const milestoneType of exports.workOrderMilestoneTypes) { + const optionElement = document.createElement("option"); + optionElement.value = + milestoneType.workOrderMilestoneTypeId.toString(); + optionElement.textContent = + milestoneType.workOrderMilestoneType; + if (milestoneType.workOrderMilestoneTypeId === + workOrderMilestone.workOrderMilestoneTypeId) { + optionElement.selected = true; + milestoneTypeFound = true; + } + milestoneTypeElement.append(optionElement); + } + if (!milestoneTypeFound && + workOrderMilestone.workOrderMilestoneTypeId) { + const optionElement = document.createElement("option"); + optionElement.value = + workOrderMilestone.workOrderMilestoneTypeId.toString(); + optionElement.textContent = + workOrderMilestone.workOrderMilestoneType; + optionElement.selected = true; + milestoneTypeElement.append(optionElement); + } + modalElement.querySelector("#milestoneEdit--workOrderMilestoneDateString").value = workOrderMilestone.workOrderMilestoneDateString; + modalElement.querySelector("#milestoneEdit--workOrderMilestoneTimeString").value = workOrderMilestone.workOrderMilestoneTimeString; + modalElement.querySelector("#milestoneEdit--workOrderMilestoneDescription").value = workOrderMilestone.workOrderMilestoneDescription; + }, + onshown: (modalElement, closeModalFunction) => { + editCloseModalFunction = closeModalFunction; + bulmaJS.toggleHtmlClipped(); + modalElement + .querySelector("form") + .addEventListener("submit", doEdit); + }, + onremoved: () => { + bulmaJS.toggleHtmlClipped(); + } + }); }; const renderMilestones = () => { const milestonesPanelElement = document.querySelector("#panel--milestones"); @@ -798,7 +858,9 @@ Object.defineProperty(exports, "__esModule", { value: true }); onshown: (modalElement, closeModalFunction) => { addCloseModalFunction = closeModalFunction; bulmaJS.toggleHtmlClipped(); - modalElement.querySelector("form").addEventListener("submit", doAdd); + modalElement + .querySelector("form") + .addEventListener("submit", doAdd); }, onremoved: () => { bulmaJS.toggleHtmlClipped(); diff --git a/public-typescript/workOrderEdit.ts b/public-typescript/workOrderEdit.ts index 4a24d639..070d2720 100644 --- a/public-typescript/workOrderEdit.ts +++ b/public-typescript/workOrderEdit.ts @@ -978,6 +978,129 @@ declare const bulmaJS: BulmaJS; const editMilestone = (clickEvent: Event) => { clickEvent.preventDefault(); + + const workOrderMilestoneId = Number.parseInt( + ( + (clickEvent.currentTarget as HTMLElement).closest( + ".container--milestone" + ) as HTMLElement + ).dataset.workOrderMilestoneId, + 10 + ); + + const workOrderMilestone = workOrderMilestones.find( + (currentMilestone) => { + return ( + currentMilestone.workOrderMilestoneId === + workOrderMilestoneId + ); + } + ); + + let editCloseModalFunction: () => void; + + const doEdit = (submitEvent: SubmitEvent) => { + submitEvent.preventDefault(); + + cityssm.postJSON( + urlPrefix + "/workOrders/doUpdateWorkOrderMilestone", + submitEvent.currentTarget, + (responseJSON: { + success: boolean; + errorMessage?: string; + workOrderMilestones?: recordTypes.WorkOrderMilestone[]; + }) => { + processMilestoneResponse(responseJSON); + if (responseJSON.success) { + editCloseModalFunction(); + } + } + ); + }; + + cityssm.openHtmlModal("workOrder-editMilestone", { + onshow: (modalElement) => { + ( + modalElement.querySelector( + "#milestoneEdit--workOrderId" + ) as HTMLInputElement + ).value = workOrderId; + + ( + modalElement.querySelector( + "#milestoneEdit--workOrderMilestoneId" + ) as HTMLInputElement + ).value = + workOrderMilestone.workOrderMilestoneId.toString(); + + const milestoneTypeElement = modalElement.querySelector( + "#milestoneEdit--workOrderMilestoneTypeId" + ) as HTMLSelectElement; + + let milestoneTypeFound = false; + + for (const milestoneType of exports.workOrderMilestoneTypes as recordTypes.WorkOrderMilestoneType[]) { + const optionElement = document.createElement("option"); + + optionElement.value = + milestoneType.workOrderMilestoneTypeId.toString(); + optionElement.textContent = + milestoneType.workOrderMilestoneType; + + if ( + milestoneType.workOrderMilestoneTypeId === + workOrderMilestone.workOrderMilestoneTypeId + ) { + optionElement.selected = true; + milestoneTypeFound = true; + } + + milestoneTypeElement.append(optionElement); + } + + if ( + !milestoneTypeFound && + workOrderMilestone.workOrderMilestoneTypeId + ) { + const optionElement = document.createElement("option"); + optionElement.value = + workOrderMilestone.workOrderMilestoneTypeId.toString(); + optionElement.textContent = + workOrderMilestone.workOrderMilestoneType; + optionElement.selected = true; + milestoneTypeElement.append(optionElement); + } + + ( + modalElement.querySelector( + "#milestoneEdit--workOrderMilestoneDateString" + ) as HTMLInputElement + ).value = workOrderMilestone.workOrderMilestoneDateString; + + ( + modalElement.querySelector( + "#milestoneEdit--workOrderMilestoneTimeString" + ) as HTMLInputElement + ).value = workOrderMilestone.workOrderMilestoneTimeString; + ( + modalElement.querySelector( + "#milestoneEdit--workOrderMilestoneDescription" + ) as HTMLTextAreaElement + ).value = workOrderMilestone.workOrderMilestoneDescription; + }, + onshown: (modalElement, closeModalFunction) => { + editCloseModalFunction = closeModalFunction; + + bulmaJS.toggleHtmlClipped(); + + modalElement + .querySelector("form") + .addEventListener("submit", doEdit); + }, + onremoved: () => { + bulmaJS.toggleHtmlClipped(); + } + }); }; const renderMilestones = () => { @@ -1149,7 +1272,9 @@ declare const bulmaJS: BulmaJS; onshown: (modalElement, closeModalFunction) => { addCloseModalFunction = closeModalFunction; bulmaJS.toggleHtmlClipped(); - modalElement.querySelector("form").addEventListener("submit", doAdd); + modalElement + .querySelector("form") + .addEventListener("submit", doAdd); }, onremoved: () => { bulmaJS.toggleHtmlClipped(); diff --git a/public/html/workOrder-editMilestone.html b/public/html/workOrder-editMilestone.html new file mode 100644 index 00000000..8669ed35 --- /dev/null +++ b/public/html/workOrder-editMilestone.html @@ -0,0 +1,59 @@ + \ No newline at end of file diff --git a/public/javascripts/workOrderEdit.min.js b/public/javascripts/workOrderEdit.min.js index c4479885..9001ac89 100644 --- a/public/javascripts/workOrderEdit.min.js +++ b/public/javascripts/workOrderEdit.min.js @@ -1 +1 @@ -"use strict";Object.defineProperty(exports,"__esModule",{value:!0}),(()=>{const e=exports.los,t=document.querySelector("main").dataset.urlPrefix,s=document.querySelector("#workOrderEdit--workOrderId").value,o=""===s;if(document.querySelector("#form--workOrderEdit").addEventListener("submit",e=>{e.preventDefault(),cityssm.postJSON(t+"/workOrders/"+(o?"doCreateWorkOrder":"doUpdateWorkOrder"),e.currentTarget,e=>{e.success?o?window.location.href=t+"/workOrders/"+e.workOrderId+"/edit":bulmaJS.alert({message:"Work Order Updated Successfully",contextualColorName:"success"}):bulmaJS.alert({title:"Error Updating Work Order",message:e.errorMessage,contextualColorName:"danger"})})}),!o){let o=exports.workOrderLots;delete exports.workOrderLots;let a=exports.workOrderLotOccupancies;delete exports.workOrderLotOccupancies;const r=e=>{const o=e.currentTarget.closest(".container--lotOccupancy").dataset.lotOccupancyId;bulmaJS.confirm({title:"Delete "+exports.aliases.lot+" "+exports.aliases.occupancy+" Relationship",message:"Are you sure you want to remove the relationship to this "+exports.aliases.lot.toLowerCase()+" "+exports.aliases.occupancy.toLowerCase()+" record from this work order? Note that the record will remain.",contextualColorName:"warning",okButton:{text:"Yes, Delete Relationship",callbackFunction:()=>{cityssm.postJSON(t+"/workOrders/doDeleteWorkOrderLotOccupancy",{workOrderId:s,lotOccupancyId:o},e=>{e.success?(a=e.workOrderLotOccupancies,u()):bulmaJS.alert({title:"Error Deleting Relationship",message:e.errorMessage,contextualColorName:"danger"})})}}})},n=(e,a)=>{cityssm.postJSON(t+"/workOrders/doAddWorkOrderLot",{workOrderId:s,lotId:e},e=>{e.success?(o=e.workOrderLots,u()):bulmaJS.alert({title:"Error Adding "+exports.aliases.lot,message:e.errorMessage,contextualColorName:"danger"}),a&&a(e.success)})},c=(e,o)=>{cityssm.postJSON(t+"/workOrders/doAddWorkOrderLotOccupancy",{workOrderId:s,lotOccupancyId:e},e=>{e.success?(a=e.workOrderLotOccupancies,u()):bulmaJS.alert({title:"Error Adding "+exports.aliases.occupancy,message:e.errorMessage,contextualColorName:"danger"}),o&&o(e.success)})},l=e=>{const t=e.currentTarget.dataset.lotId;n(t)},i=()=>{const e=document.querySelector("#container--lotOccupancies");if(document.querySelector(".tabs a[href='#relatedTab--lotOccupancies'] .tag").textContent=a.length.toString(),0===a.length)return void(e.innerHTML='

There are no '+exports.aliases.occupancies.toLowerCase()+" associated with this work order.

");e.innerHTML='
'+exports.aliases.occupancy+" Type"+exports.aliases.lot+"Start DateEnd Date"+exports.aliases.occupants+'
';const s=cityssm.dateToString(new Date);for(const n of a){const a=document.createElement("tr");a.className="container--lotOccupancy",a.dataset.lotOccupancyId=n.lotOccupancyId.toString();const c=!(n.occupancyEndDate&&n.occupancyEndDateStringn.lotId===e.lotId);a.innerHTML=''+(c?'':'')+''+cityssm.escapeHTML(n.occupancyType)+"",n.lotId?a.insertAdjacentHTML("beforeend",""+cityssm.escapeHTML(n.lotName)+(i?"":' ')+""):a.insertAdjacentHTML("beforeend",'(No '+exports.aliases.lot+")"),a.insertAdjacentHTML("beforeend",""+n.occupancyStartDateString+""+(n.occupancyEndDate?n.occupancyEndDateString:'(No End Date)')+""+(0===n.lotOccupancyOccupants.length?'(No '+cityssm.escapeHTML(exports.aliases.occupants)+")":cityssm.escapeHTML(n.lotOccupancyOccupants[0].occupantName)+(n.lotOccupancyOccupants.length>1?" plus "+(n.lotOccupancyOccupants.length-1):""))+''),n.lotId&&!i&&a.querySelector(".button--addLot").addEventListener("click",l),a.querySelector(".button--deleteLotOccupancy").addEventListener("click",r),e.querySelector("tbody").append(a)}},d=e=>{const a=e.currentTarget.closest(".container--lot").dataset.lotId;bulmaJS.confirm({title:"Delete "+exports.aliases.lot+" "+exports.aliases.occupancy+" Relationship",message:"Are you sure you want to remove the relationship to this "+exports.aliases.lot.toLowerCase()+" "+exports.aliases.occupancy.toLowerCase()+" record from this work order? Note that the record will remain.",contextualColorName:"warning",okButton:{text:"Yes, Delete Relationship",callbackFunction:()=>{cityssm.postJSON(t+"/workOrders/doDeleteWorkOrderLot",{workOrderId:s,lotId:a},e=>{e.success?(o=e.workOrderLots,u()):bulmaJS.alert({title:"Error Deleting Relationship",message:e.errorMessage,contextualColorName:"danger"})})}}})},p=()=>{const e=document.querySelector("#container--lots");if(document.querySelector(".tabs a[href='#relatedTab--lots'] .tag").textContent=o.length.toString(),0!==o.length){e.innerHTML='
'+exports.aliases.lot+""+exports.aliases.map+""+exports.aliases.lot+' TypeStatus
';for(const s of o){const o=document.createElement("tr");o.className="container--lot",o.dataset.lotId=s.lotId.toString(),o.innerHTML=''+cityssm.escapeHTML(s.lotName)+""+cityssm.escapeHTML(s.mapName)+""+cityssm.escapeHTML(s.lotType)+""+cityssm.escapeHTML(s.lotStatus)+'',o.querySelector(".button--deleteLot").addEventListener("click",d),e.querySelector("tbody").append(o)}}else e.innerHTML='

There are no '+exports.aliases.lots.toLowerCase()+" associated with this work order.

"},u=()=>{i(),p()};u(),document.querySelector("#button--addLotOccupancy").addEventListener("click",()=>{let o,a;const r=e=>{const t=e.currentTarget.closest("tr"),s=t.dataset.lotOccupancyId;c(s,e=>{e&&t.remove()})},n=e=>{e&&e.preventDefault(),a.innerHTML='


Searching...

',cityssm.postJSON(t+"/lotOccupancies/doSearchLotOccupancies",o,e=>{if(0!==e.lotOccupancies.length){a.innerHTML='
'+exports.aliases.occupancy+" Type"+exports.aliases.lot+"Start DateEnd Date"+exports.aliases.occupants+"
";for(const t of e.lotOccupancies){const e=document.createElement("tr");e.className="container--lotOccupancy",e.dataset.lotOccupancyId=t.lotOccupancyId.toString(),e.innerHTML=''+cityssm.escapeHTML(t.occupancyType)+"",t.lotId?e.insertAdjacentHTML("beforeend",""+cityssm.escapeHTML(t.lotName)+""):e.insertAdjacentHTML("beforeend",'(No '+exports.aliases.lot+")"),e.insertAdjacentHTML("beforeend",""+t.occupancyStartDateString+""+(t.occupancyEndDate?t.occupancyEndDateString:'(No End Date)')+""+(0===t.lotOccupancyOccupants.length?'(No '+cityssm.escapeHTML(exports.aliases.occupants)+")":cityssm.escapeHTML(t.lotOccupancyOccupants[0].occupantName)+(t.lotOccupancyOccupants.length>1?" plus "+(t.lotOccupancyOccupants.length-1):""))+""),e.querySelector(".button--addLotOccupancy").addEventListener("click",r),a.querySelector("tbody").append(e)}}else a.innerHTML='

There are no records that meet the search criteria.

'})};cityssm.openHtmlModal("workOrder-addLotOccupancy",{onshow:t=>{e.populateAliases(t),o=t.querySelector("form"),a=t.querySelector("#resultsContainer--lotOccupancyAdd"),t.querySelector("#lotOccupancySearch--notWorkOrderId").value=s,t.querySelector("#lotOccupancySearch--occupancyEffectiveDateString").value=document.querySelector("#workOrderEdit--workOrderOpenDateString").value,n()},onshown:e=>{bulmaJS.toggleHtmlClipped(),e.querySelector("#lotOccupancySearch--occupantName").addEventListener("change",n),e.querySelector("#lotOccupancySearch--lotName").addEventListener("change",n),o.addEventListener("submit",n)},onremoved:()=>{bulmaJS.toggleHtmlClipped()}})}),document.querySelector("#button--addLot").addEventListener("click",()=>{let o,a;const r=e=>{const t=e.currentTarget.closest("tr"),s=t.dataset.lotId;n(s,e=>{e&&t.remove()})},c=e=>{e&&e.preventDefault(),a.innerHTML='


Searching...

',cityssm.postJSON(t+"/lots/doSearchLots",o,e=>{if(0!==e.lots.length){a.innerHTML='
'+exports.aliases.lot+""+exports.aliases.map+""+exports.aliases.lot+" TypeStatus
";for(const t of e.lots){const e=document.createElement("tr");e.className="container--lot",e.dataset.lotId=t.lotId.toString(),e.innerHTML=''+cityssm.escapeHTML(t.lotName)+""+cityssm.escapeHTML(t.mapName)+""+cityssm.escapeHTML(t.lotType)+""+cityssm.escapeHTML(t.lotStatus)+"",e.querySelector(".button--addLot").addEventListener("click",r),a.querySelector("tbody").append(e)}}else a.innerHTML='

There are no records that meet the search criteria.

'})};cityssm.openHtmlModal("workOrder-addLot",{onshow:t=>{e.populateAliases(t),o=t.querySelector("form"),a=t.querySelector("#resultsContainer--lotAdd"),t.querySelector("#lotSearch--notWorkOrderId").value=s;const r=t.querySelector("#lotSearch--lotStatusId");for(const e of exports.lotStatuses){const t=document.createElement("option");t.value=e.lotStatusId.toString(),t.textContent=e.lotStatus,r.append(t)}c()},onshown:e=>{bulmaJS.toggleHtmlClipped(),e.querySelector("#lotSearch--lotName").addEventListener("change",c),e.querySelector("#lotSearch--lotStatusId").addEventListener("change",c),o.addEventListener("submit",c)},onremoved:()=>{bulmaJS.toggleHtmlClipped()}})})}if(!o){let e=exports.workOrderMilestones;delete exports.workOrderMilestones;const o=t=>{t.success?(e=t.workOrderMilestones,l()):bulmaJS.alert({title:"Error Reopening Milestone",message:t.errorMessage,contextualColorName:"danger"})},a=a=>{a.preventDefault();const r=cityssm.dateToString(new Date),n=Number.parseInt(a.currentTarget.closest(".container--milestone").dataset.workOrderMilestoneId,10),c=e.find(e=>e.workOrderMilestoneId===n);bulmaJS.confirm({title:"Complete Milestone",message:"Are you sure you want to complete this milestone?"+(c.workOrderMilestoneDateString>r?"
Note that this milestone is expected to be completed in the future.":""),messageIsHtml:!0,contextualColorName:"warning",okButton:{text:"Yes, Complete Milestone",callbackFunction:()=>{cityssm.postJSON(t+"/workOrders/doCompleteWorkOrderMilestone",{workOrderId:s,workOrderMilestoneId:n},o)}}})},r=e=>{e.preventDefault();const a=e.currentTarget.closest(".container--milestone").dataset.workOrderMilestoneId;bulmaJS.confirm({title:"Reopen Milestone",message:"Are you sure you want to remove the completion status from this milestone, and reopen it?",contextualColorName:"warning",okButton:{text:"Yes, Reopen Milestone",callbackFunction:()=>{cityssm.postJSON(t+"/workOrders/doReopenWorkOrderMilestone",{workOrderId:s,workOrderMilestoneId:a},o)}}})},n=e=>{e.preventDefault();const a=e.currentTarget.closest(".container--milestone").dataset.workOrderMilestoneId;bulmaJS.confirm({title:"Delete Milestone",message:"Are you sure you want to delete this milestone?",contextualColorName:"warning",okButton:{text:"Yes, Delete Milestone",callbackFunction:()=>{cityssm.postJSON(t+"/workOrders/doDeleteWorkOrderMilestone",{workOrderMilestoneId:a,workOrderId:s},o)}}})},c=e=>{e.preventDefault()},l=()=>{const t=document.querySelector("#panel--milestones"),s=t.querySelectorAll(".panel-block");for(const e of s)e.remove();for(const s of e){const e=document.createElement("div");e.className="panel-block is-block container--milestone",e.dataset.workOrderMilestoneId=s.workOrderMilestoneId.toString(),e.innerHTML='
'+(s.workOrderMilestoneCompletionDate?'':'')+'
'+(s.workOrderMilestoneTypeId?""+cityssm.escapeHTML(s.workOrderMilestoneType)+"
":"")+s.workOrderMilestoneDateString+(s.workOrderMilestoneTime?" "+s.workOrderMilestoneTimeString:"")+'
'+cityssm.escapeHTML(s.workOrderMilestoneDescription)+'
',s.workOrderMilestoneCompletionDate?e.querySelector(".button--reopenMilestone").addEventListener("click",r):(e.querySelector(".button--editMilestone").addEventListener("click",c),e.querySelector(".button--completeMilestone").addEventListener("click",a)),e.querySelector(".button--deleteMilestone").addEventListener("click",n),t.append(e)}bulmaJS.init(t)};l(),document.querySelector("#button--addMilestone").addEventListener("click",()=>{let e;const a=s=>{s.preventDefault(),cityssm.postJSON(t+"/workOrders/doAddWorkOrderMilestone",s.currentTarget,t=>{o(t),t.success&&e()})};cityssm.openHtmlModal("workOrder-addMilestone",{onshow:e=>{e.querySelector("#milestoneAdd--workOrderId").value=s;const t=e.querySelector("#milestoneAdd--workOrderMilestoneTypeId");for(const e of exports.workOrderMilestoneTypes){const s=document.createElement("option");s.value=e.workOrderMilestoneTypeId.toString(),s.textContent=e.workOrderMilestoneType,t.append(s)}e.querySelector("#milestoneAdd--workOrderMilestoneDateString").valueAsDate=new Date},onshown:(t,s)=>{e=s,bulmaJS.toggleHtmlClipped(),t.querySelector("form").addEventListener("submit",a)},onremoved:()=>{bulmaJS.toggleHtmlClipped()}})})}})(); \ No newline at end of file +"use strict";Object.defineProperty(exports,"__esModule",{value:!0}),(()=>{const e=exports.los,t=document.querySelector("main").dataset.urlPrefix,s=document.querySelector("#workOrderEdit--workOrderId").value,o=""===s;if(document.querySelector("#form--workOrderEdit").addEventListener("submit",e=>{e.preventDefault(),cityssm.postJSON(t+"/workOrders/"+(o?"doCreateWorkOrder":"doUpdateWorkOrder"),e.currentTarget,e=>{e.success?o?window.location.href=t+"/workOrders/"+e.workOrderId+"/edit":bulmaJS.alert({message:"Work Order Updated Successfully",contextualColorName:"success"}):bulmaJS.alert({title:"Error Updating Work Order",message:e.errorMessage,contextualColorName:"danger"})})}),!o){let o=exports.workOrderLots;delete exports.workOrderLots;let r=exports.workOrderLotOccupancies;delete exports.workOrderLotOccupancies;const a=e=>{const o=e.currentTarget.closest(".container--lotOccupancy").dataset.lotOccupancyId;bulmaJS.confirm({title:"Delete "+exports.aliases.lot+" "+exports.aliases.occupancy+" Relationship",message:"Are you sure you want to remove the relationship to this "+exports.aliases.lot.toLowerCase()+" "+exports.aliases.occupancy.toLowerCase()+" record from this work order? Note that the record will remain.",contextualColorName:"warning",okButton:{text:"Yes, Delete Relationship",callbackFunction:()=>{cityssm.postJSON(t+"/workOrders/doDeleteWorkOrderLotOccupancy",{workOrderId:s,lotOccupancyId:o},e=>{e.success?(r=e.workOrderLotOccupancies,u()):bulmaJS.alert({title:"Error Deleting Relationship",message:e.errorMessage,contextualColorName:"danger"})})}}})},n=(e,r)=>{cityssm.postJSON(t+"/workOrders/doAddWorkOrderLot",{workOrderId:s,lotId:e},e=>{e.success?(o=e.workOrderLots,u()):bulmaJS.alert({title:"Error Adding "+exports.aliases.lot,message:e.errorMessage,contextualColorName:"danger"}),r&&r(e.success)})},l=(e,o)=>{cityssm.postJSON(t+"/workOrders/doAddWorkOrderLotOccupancy",{workOrderId:s,lotOccupancyId:e},e=>{e.success?(r=e.workOrderLotOccupancies,u()):bulmaJS.alert({title:"Error Adding "+exports.aliases.occupancy,message:e.errorMessage,contextualColorName:"danger"}),o&&o(e.success)})},c=e=>{const t=e.currentTarget.dataset.lotId;n(t)},i=()=>{const e=document.querySelector("#container--lotOccupancies");if(document.querySelector(".tabs a[href='#relatedTab--lotOccupancies'] .tag").textContent=r.length.toString(),0===r.length)return void(e.innerHTML='

There are no '+exports.aliases.occupancies.toLowerCase()+" associated with this work order.

");e.innerHTML='
'+exports.aliases.occupancy+" Type"+exports.aliases.lot+"Start DateEnd Date"+exports.aliases.occupants+'
';const s=cityssm.dateToString(new Date);for(const n of r){const r=document.createElement("tr");r.className="container--lotOccupancy",r.dataset.lotOccupancyId=n.lotOccupancyId.toString();const l=!(n.occupancyEndDate&&n.occupancyEndDateStringn.lotId===e.lotId);r.innerHTML=''+(l?'':'')+''+cityssm.escapeHTML(n.occupancyType)+"",n.lotId?r.insertAdjacentHTML("beforeend",""+cityssm.escapeHTML(n.lotName)+(i?"":' ')+""):r.insertAdjacentHTML("beforeend",'(No '+exports.aliases.lot+")"),r.insertAdjacentHTML("beforeend",""+n.occupancyStartDateString+""+(n.occupancyEndDate?n.occupancyEndDateString:'(No End Date)')+""+(0===n.lotOccupancyOccupants.length?'(No '+cityssm.escapeHTML(exports.aliases.occupants)+")":cityssm.escapeHTML(n.lotOccupancyOccupants[0].occupantName)+(n.lotOccupancyOccupants.length>1?" plus "+(n.lotOccupancyOccupants.length-1):""))+''),n.lotId&&!i&&r.querySelector(".button--addLot").addEventListener("click",c),r.querySelector(".button--deleteLotOccupancy").addEventListener("click",a),e.querySelector("tbody").append(r)}},d=e=>{const r=e.currentTarget.closest(".container--lot").dataset.lotId;bulmaJS.confirm({title:"Delete "+exports.aliases.lot+" "+exports.aliases.occupancy+" Relationship",message:"Are you sure you want to remove the relationship to this "+exports.aliases.lot.toLowerCase()+" "+exports.aliases.occupancy.toLowerCase()+" record from this work order? Note that the record will remain.",contextualColorName:"warning",okButton:{text:"Yes, Delete Relationship",callbackFunction:()=>{cityssm.postJSON(t+"/workOrders/doDeleteWorkOrderLot",{workOrderId:s,lotId:r},e=>{e.success?(o=e.workOrderLots,u()):bulmaJS.alert({title:"Error Deleting Relationship",message:e.errorMessage,contextualColorName:"danger"})})}}})},p=()=>{const e=document.querySelector("#container--lots");if(document.querySelector(".tabs a[href='#relatedTab--lots'] .tag").textContent=o.length.toString(),0!==o.length){e.innerHTML='
'+exports.aliases.lot+""+exports.aliases.map+""+exports.aliases.lot+' TypeStatus
';for(const s of o){const o=document.createElement("tr");o.className="container--lot",o.dataset.lotId=s.lotId.toString(),o.innerHTML=''+cityssm.escapeHTML(s.lotName)+""+cityssm.escapeHTML(s.mapName)+""+cityssm.escapeHTML(s.lotType)+""+cityssm.escapeHTML(s.lotStatus)+'',o.querySelector(".button--deleteLot").addEventListener("click",d),e.querySelector("tbody").append(o)}}else e.innerHTML='

There are no '+exports.aliases.lots.toLowerCase()+" associated with this work order.

"},u=()=>{i(),p()};u(),document.querySelector("#button--addLotOccupancy").addEventListener("click",()=>{let o,r;const a=e=>{const t=e.currentTarget.closest("tr"),s=t.dataset.lotOccupancyId;l(s,e=>{e&&t.remove()})},n=e=>{e&&e.preventDefault(),r.innerHTML='


Searching...

',cityssm.postJSON(t+"/lotOccupancies/doSearchLotOccupancies",o,e=>{if(0!==e.lotOccupancies.length){r.innerHTML='
'+exports.aliases.occupancy+" Type"+exports.aliases.lot+"Start DateEnd Date"+exports.aliases.occupants+"
";for(const t of e.lotOccupancies){const e=document.createElement("tr");e.className="container--lotOccupancy",e.dataset.lotOccupancyId=t.lotOccupancyId.toString(),e.innerHTML=''+cityssm.escapeHTML(t.occupancyType)+"",t.lotId?e.insertAdjacentHTML("beforeend",""+cityssm.escapeHTML(t.lotName)+""):e.insertAdjacentHTML("beforeend",'(No '+exports.aliases.lot+")"),e.insertAdjacentHTML("beforeend",""+t.occupancyStartDateString+""+(t.occupancyEndDate?t.occupancyEndDateString:'(No End Date)')+""+(0===t.lotOccupancyOccupants.length?'(No '+cityssm.escapeHTML(exports.aliases.occupants)+")":cityssm.escapeHTML(t.lotOccupancyOccupants[0].occupantName)+(t.lotOccupancyOccupants.length>1?" plus "+(t.lotOccupancyOccupants.length-1):""))+""),e.querySelector(".button--addLotOccupancy").addEventListener("click",a),r.querySelector("tbody").append(e)}}else r.innerHTML='

There are no records that meet the search criteria.

'})};cityssm.openHtmlModal("workOrder-addLotOccupancy",{onshow:t=>{e.populateAliases(t),o=t.querySelector("form"),r=t.querySelector("#resultsContainer--lotOccupancyAdd"),t.querySelector("#lotOccupancySearch--notWorkOrderId").value=s,t.querySelector("#lotOccupancySearch--occupancyEffectiveDateString").value=document.querySelector("#workOrderEdit--workOrderOpenDateString").value,n()},onshown:e=>{bulmaJS.toggleHtmlClipped(),e.querySelector("#lotOccupancySearch--occupantName").addEventListener("change",n),e.querySelector("#lotOccupancySearch--lotName").addEventListener("change",n),o.addEventListener("submit",n)},onremoved:()=>{bulmaJS.toggleHtmlClipped()}})}),document.querySelector("#button--addLot").addEventListener("click",()=>{let o,r;const a=e=>{const t=e.currentTarget.closest("tr"),s=t.dataset.lotId;n(s,e=>{e&&t.remove()})},l=e=>{e&&e.preventDefault(),r.innerHTML='


Searching...

',cityssm.postJSON(t+"/lots/doSearchLots",o,e=>{if(0!==e.lots.length){r.innerHTML='
'+exports.aliases.lot+""+exports.aliases.map+""+exports.aliases.lot+" TypeStatus
";for(const t of e.lots){const e=document.createElement("tr");e.className="container--lot",e.dataset.lotId=t.lotId.toString(),e.innerHTML=''+cityssm.escapeHTML(t.lotName)+""+cityssm.escapeHTML(t.mapName)+""+cityssm.escapeHTML(t.lotType)+""+cityssm.escapeHTML(t.lotStatus)+"",e.querySelector(".button--addLot").addEventListener("click",a),r.querySelector("tbody").append(e)}}else r.innerHTML='

There are no records that meet the search criteria.

'})};cityssm.openHtmlModal("workOrder-addLot",{onshow:t=>{e.populateAliases(t),o=t.querySelector("form"),r=t.querySelector("#resultsContainer--lotAdd"),t.querySelector("#lotSearch--notWorkOrderId").value=s;const a=t.querySelector("#lotSearch--lotStatusId");for(const e of exports.lotStatuses){const t=document.createElement("option");t.value=e.lotStatusId.toString(),t.textContent=e.lotStatus,a.append(t)}l()},onshown:e=>{bulmaJS.toggleHtmlClipped(),e.querySelector("#lotSearch--lotName").addEventListener("change",l),e.querySelector("#lotSearch--lotStatusId").addEventListener("change",l),o.addEventListener("submit",l)},onremoved:()=>{bulmaJS.toggleHtmlClipped()}})})}if(!o){let e=exports.workOrderMilestones;delete exports.workOrderMilestones;const o=t=>{t.success?(e=t.workOrderMilestones,c()):bulmaJS.alert({title:"Error Reopening Milestone",message:t.errorMessage,contextualColorName:"danger"})},r=r=>{r.preventDefault();const a=cityssm.dateToString(new Date),n=Number.parseInt(r.currentTarget.closest(".container--milestone").dataset.workOrderMilestoneId,10),l=e.find(e=>e.workOrderMilestoneId===n);bulmaJS.confirm({title:"Complete Milestone",message:"Are you sure you want to complete this milestone?"+(l.workOrderMilestoneDateString>a?"
Note that this milestone is expected to be completed in the future.":""),messageIsHtml:!0,contextualColorName:"warning",okButton:{text:"Yes, Complete Milestone",callbackFunction:()=>{cityssm.postJSON(t+"/workOrders/doCompleteWorkOrderMilestone",{workOrderId:s,workOrderMilestoneId:n},o)}}})},a=e=>{e.preventDefault();const r=e.currentTarget.closest(".container--milestone").dataset.workOrderMilestoneId;bulmaJS.confirm({title:"Reopen Milestone",message:"Are you sure you want to remove the completion status from this milestone, and reopen it?",contextualColorName:"warning",okButton:{text:"Yes, Reopen Milestone",callbackFunction:()=>{cityssm.postJSON(t+"/workOrders/doReopenWorkOrderMilestone",{workOrderId:s,workOrderMilestoneId:r},o)}}})},n=e=>{e.preventDefault();const r=e.currentTarget.closest(".container--milestone").dataset.workOrderMilestoneId;bulmaJS.confirm({title:"Delete Milestone",message:"Are you sure you want to delete this milestone?",contextualColorName:"warning",okButton:{text:"Yes, Delete Milestone",callbackFunction:()=>{cityssm.postJSON(t+"/workOrders/doDeleteWorkOrderMilestone",{workOrderMilestoneId:r,workOrderId:s},o)}}})},l=r=>{r.preventDefault();const a=Number.parseInt(r.currentTarget.closest(".container--milestone").dataset.workOrderMilestoneId,10),n=e.find(e=>e.workOrderMilestoneId===a);let l;const c=e=>{e.preventDefault(),cityssm.postJSON(t+"/workOrders/doUpdateWorkOrderMilestone",e.currentTarget,e=>{o(e),e.success&&l()})};cityssm.openHtmlModal("workOrder-editMilestone",{onshow:e=>{e.querySelector("#milestoneEdit--workOrderId").value=s,e.querySelector("#milestoneEdit--workOrderMilestoneId").value=n.workOrderMilestoneId.toString();const t=e.querySelector("#milestoneEdit--workOrderMilestoneTypeId");let o=!1;for(const e of exports.workOrderMilestoneTypes){const s=document.createElement("option");s.value=e.workOrderMilestoneTypeId.toString(),s.textContent=e.workOrderMilestoneType,e.workOrderMilestoneTypeId===n.workOrderMilestoneTypeId&&(s.selected=!0,o=!0),t.append(s)}if(!o&&n.workOrderMilestoneTypeId){const e=document.createElement("option");e.value=n.workOrderMilestoneTypeId.toString(),e.textContent=n.workOrderMilestoneType,e.selected=!0,t.append(e)}e.querySelector("#milestoneEdit--workOrderMilestoneDateString").value=n.workOrderMilestoneDateString,e.querySelector("#milestoneEdit--workOrderMilestoneTimeString").value=n.workOrderMilestoneTimeString,e.querySelector("#milestoneEdit--workOrderMilestoneDescription").value=n.workOrderMilestoneDescription},onshown:(e,t)=>{l=t,bulmaJS.toggleHtmlClipped(),e.querySelector("form").addEventListener("submit",c)},onremoved:()=>{bulmaJS.toggleHtmlClipped()}})},c=()=>{const t=document.querySelector("#panel--milestones"),s=t.querySelectorAll(".panel-block");for(const e of s)e.remove();for(const s of e){const e=document.createElement("div");e.className="panel-block is-block container--milestone",e.dataset.workOrderMilestoneId=s.workOrderMilestoneId.toString(),e.innerHTML='
'+(s.workOrderMilestoneCompletionDate?'':'')+'
'+(s.workOrderMilestoneTypeId?""+cityssm.escapeHTML(s.workOrderMilestoneType)+"
":"")+s.workOrderMilestoneDateString+(s.workOrderMilestoneTime?" "+s.workOrderMilestoneTimeString:"")+'
'+cityssm.escapeHTML(s.workOrderMilestoneDescription)+'
',s.workOrderMilestoneCompletionDate?e.querySelector(".button--reopenMilestone").addEventListener("click",a):(e.querySelector(".button--editMilestone").addEventListener("click",l),e.querySelector(".button--completeMilestone").addEventListener("click",r)),e.querySelector(".button--deleteMilestone").addEventListener("click",n),t.append(e)}bulmaJS.init(t)};c(),document.querySelector("#button--addMilestone").addEventListener("click",()=>{let e;const r=s=>{s.preventDefault(),cityssm.postJSON(t+"/workOrders/doAddWorkOrderMilestone",s.currentTarget,t=>{o(t),t.success&&e()})};cityssm.openHtmlModal("workOrder-addMilestone",{onshow:e=>{e.querySelector("#milestoneAdd--workOrderId").value=s;const t=e.querySelector("#milestoneAdd--workOrderMilestoneTypeId");for(const e of exports.workOrderMilestoneTypes){const s=document.createElement("option");s.value=e.workOrderMilestoneTypeId.toString(),s.textContent=e.workOrderMilestoneType,t.append(s)}e.querySelector("#milestoneAdd--workOrderMilestoneDateString").valueAsDate=new Date},onshown:(t,s)=>{e=s,bulmaJS.toggleHtmlClipped(),t.querySelector("form").addEventListener("submit",r)},onremoved:()=>{bulmaJS.toggleHtmlClipped()}})})}})(); \ No newline at end of file diff --git a/routes/workOrders.js b/routes/workOrders.js index c2b20c76..69a3029f 100644 --- a/routes/workOrders.js +++ b/routes/workOrders.js @@ -11,6 +11,7 @@ import handler_doDeleteWorkOrderLotOccupancy from "../handlers/workOrders-post/d import handler_doAddWorkOrderLot from "../handlers/workOrders-post/doAddWorkOrderLot.js"; import handler_doDeleteWorkOrderLot from "../handlers/workOrders-post/doDeleteWorkOrderLot.js"; import handler_doAddWorkOrderMilestone from "../handlers/workOrders-post/doAddWorkOrderMilestone.js"; +import handler_doUpdateWorkOrderMilestone from "../handlers/workOrders-post/doUpdateWorkOrderMilestone.js"; import handler_doCompleteWorkOrderMilestone from "../handlers/workOrders-post/doCompleteWorkOrderMilestone.js"; import handler_doReopenWorkOrderMilestone from "../handlers/workOrders-post/doReopenWorkOrderMilestone.js"; import handler_doDeleteWorkOrderMilestone from "../handlers/workOrders-post/doDeleteWorkOrderMilestone.js"; @@ -26,6 +27,7 @@ router.post("/doDeleteWorkOrderLotOccupancy", permissionHandlers.updatePostHandl router.post("/doAddWorkOrderLot", permissionHandlers.updatePostHandler, handler_doAddWorkOrderLot); router.post("/doDeleteWorkOrderLot", permissionHandlers.updatePostHandler, handler_doDeleteWorkOrderLot); router.post("/doAddWorkOrderMilestone", permissionHandlers.updatePostHandler, handler_doAddWorkOrderMilestone); +router.post("/doUpdateWorkOrderMilestone", permissionHandlers.updatePostHandler, handler_doUpdateWorkOrderMilestone); router.post("/doCompleteWorkOrderMilestone", permissionHandlers.updatePostHandler, handler_doCompleteWorkOrderMilestone); router.post("/doReopenWorkOrderMilestone", permissionHandlers.updatePostHandler, handler_doReopenWorkOrderMilestone); router.post("/doDeleteWorkOrderMilestone", permissionHandlers.updatePostHandler, handler_doDeleteWorkOrderMilestone); diff --git a/routes/workOrders.ts b/routes/workOrders.ts index 0c171aba..d7755814 100644 --- a/routes/workOrders.ts +++ b/routes/workOrders.ts @@ -18,6 +18,7 @@ import handler_doAddWorkOrderLot from "../handlers/workOrders-post/doAddWorkOrde import handler_doDeleteWorkOrderLot from "../handlers/workOrders-post/doDeleteWorkOrderLot.js"; import handler_doAddWorkOrderMilestone from "../handlers/workOrders-post/doAddWorkOrderMilestone.js"; +import handler_doUpdateWorkOrderMilestone from "../handlers/workOrders-post/doUpdateWorkOrderMilestone.js"; import handler_doCompleteWorkOrderMilestone from "../handlers/workOrders-post/doCompleteWorkOrderMilestone.js"; import handler_doReopenWorkOrderMilestone from "../handlers/workOrders-post/doReopenWorkOrderMilestone.js"; import handler_doDeleteWorkOrderMilestone from "../handlers/workOrders-post/doDeleteWorkOrderMilestone.js"; @@ -80,6 +81,12 @@ router.post( handler_doAddWorkOrderMilestone ); +router.post( + "/doUpdateWorkOrderMilestone", + permissionHandlers.updatePostHandler, + handler_doUpdateWorkOrderMilestone +); + router.post( "/doCompleteWorkOrderMilestone", permissionHandlers.updatePostHandler,