From c117cc84e43641a3ea26679968c0c16edbbe0354 Mon Sep 17 00:00:00 2001 From: Dan Gowans Date: Wed, 5 Oct 2022 15:09:53 -0400 Subject: [PATCH] create lot from lot occupancy --- handlers/lotOccupancies-get/edit.js | 9 +- handlers/lotOccupancies-get/edit.ts | 10 ++ handlers/lotOccupancies-get/new.js | 9 +- handlers/lotOccupancies-get/new.ts | 15 ++- public-typescript/lotOccupancyEdit.js | 63 ++++++++-- public-typescript/lotOccupancyEdit.ts | 102 ++++++++++++++-- public-typescript/lotSearch.js | 4 +- public-typescript/lotSearch.ts | 4 +- public-typescript/main.js | 4 + public-typescript/main.ts | 10 +- public/html/lotOccupancy-selectLot.html | 130 ++++++++++++++++----- public/javascripts/lotOccupancyEdit.min.js | 2 +- public/javascripts/lotSearch.min.js | 2 +- public/javascripts/main.min.js | 2 +- views/lotOccupancy-edit.ejs | 18 ++- 15 files changed, 316 insertions(+), 68 deletions(-) diff --git a/handlers/lotOccupancies-get/edit.js b/handlers/lotOccupancies-get/edit.js index f9cf3391..076c1618 100644 --- a/handlers/lotOccupancies-get/edit.js +++ b/handlers/lotOccupancies-get/edit.js @@ -1,6 +1,7 @@ -import { getLotOccupantTypes, getOccupancyTypes } from "../../helpers/functions.cache.js"; +import { getLotOccupantTypes, getLotStatuses, getLotTypes, getOccupancyTypes } from "../../helpers/functions.cache.js"; import * as configFunctions from "../../helpers/functions.config.js"; import { getLotOccupancy } from "../../helpers/lotOccupancyDB/getLotOccupancy.js"; +import { getMaps } from "../../helpers/lotOccupancyDB/getMaps.js"; export const handler = (request, response) => { const lotOccupancy = getLotOccupancy(request.params.lotOccupancyId); if (!lotOccupancy) { @@ -9,6 +10,9 @@ export const handler = (request, response) => { } const occupancyTypes = getOccupancyTypes(); const lotOccupantTypes = getLotOccupantTypes(); + const lotTypes = getLotTypes(); + const lotStatuses = getLotStatuses(); + const maps = getMaps(); return response.render("lotOccupancy-edit", { headTitle: configFunctions.getProperty("aliases.lot") + " " + @@ -17,6 +21,9 @@ export const handler = (request, response) => { lotOccupancy, occupancyTypes, lotOccupantTypes, + lotTypes, + lotStatuses, + maps, isCreate: false }); }; diff --git a/handlers/lotOccupancies-get/edit.ts b/handlers/lotOccupancies-get/edit.ts index 9e47d7d1..9e8edbb5 100644 --- a/handlers/lotOccupancies-get/edit.ts +++ b/handlers/lotOccupancies-get/edit.ts @@ -2,12 +2,15 @@ import type { RequestHandler } from "express"; import { getLotOccupantTypes, + getLotStatuses, + getLotTypes, getOccupancyTypes } from "../../helpers/functions.cache.js"; import * as configFunctions from "../../helpers/functions.config.js"; import { getLotOccupancy } from "../../helpers/lotOccupancyDB/getLotOccupancy.js"; +import { getMaps } from "../../helpers/lotOccupancyDB/getMaps.js"; export const handler: RequestHandler = (request, response) => { const lotOccupancy = getLotOccupancy(request.params.lotOccupancyId); @@ -21,6 +24,9 @@ export const handler: RequestHandler = (request, response) => { const occupancyTypes = getOccupancyTypes(); const lotOccupantTypes = getLotOccupantTypes(); + const lotTypes = getLotTypes(); + const lotStatuses = getLotStatuses(); + const maps = getMaps(); return response.render("lotOccupancy-edit", { headTitle: @@ -32,6 +38,10 @@ export const handler: RequestHandler = (request, response) => { occupancyTypes, lotOccupantTypes, + lotTypes, + lotStatuses, + maps, + isCreate: false }); }; diff --git a/handlers/lotOccupancies-get/new.js b/handlers/lotOccupancies-get/new.js index 541fcb63..d81f389c 100644 --- a/handlers/lotOccupancies-get/new.js +++ b/handlers/lotOccupancies-get/new.js @@ -1,6 +1,7 @@ import { dateToInteger, dateToString } from "@cityssm/expressjs-server-js/dateTimeFns.js"; -import { getOccupancyTypes } from "../../helpers/functions.cache.js"; +import { getLotStatuses, getLotTypes, getOccupancyTypes } from "../../helpers/functions.cache.js"; import { getLot } from "../../helpers/lotOccupancyDB/getLot.js"; +import { getMaps } from "../../helpers/lotOccupancyDB/getMaps.js"; import * as configFunctions from "../../helpers/functions.config.js"; export const handler = (request, response) => { const startDate = new Date(); @@ -16,6 +17,9 @@ export const handler = (request, response) => { lotOccupancy.mapName = lot.mapName; } const occupancyTypes = getOccupancyTypes(); + const lotTypes = getLotTypes(); + const lotStatuses = getLotStatuses(); + const maps = getMaps(); return response.render("lotOccupancy-edit", { headTitle: "Create a New " + configFunctions.getProperty("aliases.lot") + @@ -24,6 +28,9 @@ export const handler = (request, response) => { " Record", lotOccupancy, occupancyTypes, + lotTypes, + lotStatuses, + maps, isCreate: true }); }; diff --git a/handlers/lotOccupancies-get/new.ts b/handlers/lotOccupancies-get/new.ts index 2f423aa0..ada15902 100644 --- a/handlers/lotOccupancies-get/new.ts +++ b/handlers/lotOccupancies-get/new.ts @@ -1,13 +1,11 @@ import type { RequestHandler } from "express"; -import { - dateToInteger, - dateToString -} from "@cityssm/expressjs-server-js/dateTimeFns.js"; +import { dateToInteger, dateToString } from "@cityssm/expressjs-server-js/dateTimeFns.js"; -import { getOccupancyTypes } from "../../helpers/functions.cache.js"; +import { getLotStatuses, getLotTypes, getOccupancyTypes } from "../../helpers/functions.cache.js"; import { getLot } from "../../helpers/lotOccupancyDB/getLot.js"; +import { getMaps } from "../../helpers/lotOccupancyDB/getMaps.js"; import * as configFunctions from "../../helpers/functions.config.js"; @@ -30,6 +28,9 @@ export const handler: RequestHandler = (request, response) => { } const occupancyTypes = getOccupancyTypes(); + const lotTypes = getLotTypes(); + const lotStatuses = getLotStatuses(); + const maps = getMaps(); return response.render("lotOccupancy-edit", { headTitle: @@ -41,6 +42,10 @@ export const handler: RequestHandler = (request, response) => { lotOccupancy, occupancyTypes, + lotTypes, + lotStatuses, + maps, + isCreate: true }); }; diff --git a/public-typescript/lotOccupancyEdit.js b/public-typescript/lotOccupancyEdit.js index 769c6565..fe7aa726 100644 --- a/public-typescript/lotOccupancyEdit.js +++ b/public-typescript/lotOccupancyEdit.js @@ -199,18 +199,21 @@ Object.defineProperty(exports, "__esModule", { value: true }); lotNameElement.addEventListener("click", (clickEvent) => { const currentLotName = clickEvent.currentTarget.value; let lotSelectCloseModalFunction; + let lotSelectModalElement; let lotSelectFormElement; let lotSelectResultsElement; - const selectLot = (clickEvent) => { - clickEvent.preventDefault(); - const selectedLotElement = clickEvent.currentTarget; + const renderSelectedLotAndClose = (lotId, lotName) => { document.querySelector("#lotOccupancy--lotId").value = - selectedLotElement.dataset.lotId; - document.querySelector("#lotOccupancy--lotName").value = - selectedLotElement.dataset.lotName; + lotId.toString(); + document.querySelector("#lotOccupancy--lotName").value = lotName; setUnsavedChanges(); lotSelectCloseModalFunction(); }; + const selectExistingLot = (clickEvent) => { + clickEvent.preventDefault(); + const selectedLotElement = clickEvent.currentTarget; + renderSelectedLotAndClose(selectedLotElement.dataset.lotId, selectedLotElement.dataset.lotName); + }; const searchLots = () => { lotSelectResultsElement.innerHTML = '

' + @@ -252,20 +255,38 @@ Object.defineProperty(exports, "__esModule", { value: true }); "" + "") + ""; - panelBlockElement.addEventListener("click", selectLot); + panelBlockElement.addEventListener("click", selectExistingLot); panelElement.append(panelBlockElement); } lotSelectResultsElement.innerHTML = ""; lotSelectResultsElement.append(panelElement); }); }; + const createLotAndSelect = (submitEvent) => { + submitEvent.preventDefault(); + const lotName = lotSelectModalElement.querySelector("#lotCreate--lotName").value; + cityssm.postJSON(urlPrefix + "/lots/doCreateLot", submitEvent.currentTarget, (responseJSON) => { + if (responseJSON.success) { + renderSelectedLotAndClose(responseJSON.lotId, lotName); + } + else { + bulmaJS.alert({ + title: "Error Creating " + exports.aliases.lot, + message: responseJSON.errorMessage, + contextualColorName: "danger" + }); + } + }); + }; cityssm.openHtmlModal("lotOccupancy-selectLot", { onshow: (modalElement) => { los.populateAliases(modalElement); }, onshown: (modalElement, closeModalFunction) => { bulmaJS.toggleHtmlClipped(); + lotSelectModalElement = modalElement; lotSelectCloseModalFunction = closeModalFunction; + bulmaJS.init(modalElement); const lotNameFilterElement = modalElement.querySelector("#lotSelect--lotName"); if (document.querySelector("#lotOccupancy--lotId").value !== "") { @@ -284,6 +305,34 @@ Object.defineProperty(exports, "__esModule", { value: true }); submitEvent.preventDefault(); }); searchLots(); + if (exports.lotNamePattern) { + const regex = exports.lotNamePattern; + modalElement.querySelector("#lotCreate--lotName").pattern = regex.source; + } + const lotTypeElement = modalElement.querySelector("#lotCreate--lotTypeId"); + for (const lotType of exports.lotTypes) { + const optionElement = document.createElement("option"); + optionElement.value = lotType.lotTypeId.toString(); + optionElement.textContent = lotType.lotType; + lotTypeElement.append(optionElement); + } + const lotStatusElement = modalElement.querySelector("#lotCreate--lotStatusId"); + for (const lotStatus of exports.lotStatuses) { + const optionElement = document.createElement("option"); + optionElement.value = lotStatus.lotStatusId.toString(); + optionElement.textContent = lotStatus.lotStatus; + lotStatusElement.append(optionElement); + } + const mapElement = modalElement.querySelector("#lotCreate--mapId"); + for (const map of exports.maps) { + const optionElement = document.createElement("option"); + optionElement.value = map.mapId.toString(); + optionElement.textContent = map.mapName || "(No Name)"; + mapElement.append(optionElement); + } + modalElement + .querySelector("#form--lotCreate") + .addEventListener("submit", createLotAndSelect); }, onremoved: () => { bulmaJS.toggleHtmlClipped(); diff --git a/public-typescript/lotOccupancyEdit.ts b/public-typescript/lotOccupancyEdit.ts index 5c7f8749..fac55c24 100644 --- a/public-typescript/lotOccupancyEdit.ts +++ b/public-typescript/lotOccupancyEdit.ts @@ -284,23 +284,29 @@ declare const bulmaJS: BulmaJS; const currentLotName = (clickEvent.currentTarget as HTMLInputElement).value; let lotSelectCloseModalFunction: () => void; + let lotSelectModalElement: HTMLElement; let lotSelectFormElement: HTMLFormElement; let lotSelectResultsElement: HTMLElement; - const selectLot = (clickEvent: Event) => { + const renderSelectedLotAndClose = (lotId: number | string, lotName: string) => { + (document.querySelector("#lotOccupancy--lotId") as HTMLInputElement).value = + lotId.toString(); + (document.querySelector("#lotOccupancy--lotName") as HTMLInputElement).value = lotName; + + setUnsavedChanges(); + lotSelectCloseModalFunction(); + }; + + const selectExistingLot = (clickEvent: Event) => { clickEvent.preventDefault(); const selectedLotElement = clickEvent.currentTarget as HTMLElement; - (document.querySelector("#lotOccupancy--lotId") as HTMLInputElement).value = - selectedLotElement.dataset.lotId; - (document.querySelector("#lotOccupancy--lotName") as HTMLInputElement).value = - selectedLotElement.dataset.lotName; - - setUnsavedChanges(); - - lotSelectCloseModalFunction(); + renderSelectedLotAndClose( + selectedLotElement.dataset.lotId, + selectedLotElement.dataset.lotName + ); }; const searchLots = () => { @@ -354,7 +360,7 @@ declare const bulmaJS: BulmaJS; "") + ""; - panelBlockElement.addEventListener("click", selectLot); + panelBlockElement.addEventListener("click", selectExistingLot); panelElement.append(panelBlockElement); } @@ -365,6 +371,30 @@ declare const bulmaJS: BulmaJS; ); }; + const createLotAndSelect = (submitEvent: SubmitEvent) => { + submitEvent.preventDefault(); + + const lotName = ( + lotSelectModalElement.querySelector("#lotCreate--lotName") as HTMLInputElement + ).value; + + cityssm.postJSON( + urlPrefix + "/lots/doCreateLot", + submitEvent.currentTarget, + (responseJSON: { success: boolean; errorMessage?: string; lotId?: number }) => { + if (responseJSON.success) { + renderSelectedLotAndClose(responseJSON.lotId, lotName); + } else { + bulmaJS.alert({ + title: "Error Creating " + exports.aliases.lot, + message: responseJSON.errorMessage, + contextualColorName: "danger" + }); + } + } + ); + }; + cityssm.openHtmlModal("lotOccupancy-selectLot", { onshow: (modalElement) => { los.populateAliases(modalElement); @@ -372,8 +402,13 @@ declare const bulmaJS: BulmaJS; onshown: (modalElement, closeModalFunction) => { bulmaJS.toggleHtmlClipped(); + lotSelectModalElement = modalElement; lotSelectCloseModalFunction = closeModalFunction; + bulmaJS.init(modalElement); + + // search Tab + const lotNameFilterElement = modalElement.querySelector( "#lotSelect--lotName" ) as HTMLInputElement; @@ -407,6 +442,53 @@ declare const bulmaJS: BulmaJS; }); searchLots(); + + // Create Tab + + if (exports.lotNamePattern) { + const regex = exports.lotNamePattern as RegExp; + + ( + modalElement.querySelector("#lotCreate--lotName") as HTMLInputElement + ).pattern = regex.source; + } + + const lotTypeElement = modalElement.querySelector( + "#lotCreate--lotTypeId" + ) as HTMLSelectElement; + + for (const lotType of exports.lotTypes as recordTypes.LotType[]) { + const optionElement = document.createElement("option"); + optionElement.value = lotType.lotTypeId.toString(); + optionElement.textContent = lotType.lotType; + lotTypeElement.append(optionElement); + } + + const lotStatusElement = modalElement.querySelector( + "#lotCreate--lotStatusId" + ) as HTMLSelectElement; + + for (const lotStatus of exports.lotStatuses as recordTypes.LotStatus[]) { + const optionElement = document.createElement("option"); + optionElement.value = lotStatus.lotStatusId.toString(); + optionElement.textContent = lotStatus.lotStatus; + lotStatusElement.append(optionElement); + } + + const mapElement = modalElement.querySelector( + "#lotCreate--mapId" + ) as HTMLSelectElement; + + for (const map of exports.maps as recordTypes.Map[]) { + const optionElement = document.createElement("option"); + optionElement.value = map.mapId.toString(); + optionElement.textContent = map.mapName || "(No Name)"; + mapElement.append(optionElement); + } + + modalElement + .querySelector("#form--lotCreate") + .addEventListener("submit", createLotAndSelect); }, onremoved: () => { bulmaJS.toggleHtmlClipped(); diff --git a/public-typescript/lotSearch.js b/public-typescript/lotSearch.js index 2ba7c568..978750f4 100644 --- a/public-typescript/lotSearch.js +++ b/public-typescript/lotSearch.js @@ -50,7 +50,9 @@ Object.defineProperty(exports, "__esModule", { value: true }); "") + ("" + cityssm.escapeHTML(lot.lotType) + "") + ("" + - cityssm.escapeHTML(lot.lotStatus) + + (lot.lotStatusId + ? cityssm.escapeHTML(lot.lotStatus) + : '(No Status)') + "
" + (lot.lotOccupancyCount > 0 ? 'Currently Occupied' diff --git a/public-typescript/lotSearch.ts b/public-typescript/lotSearch.ts index 7272c817..dc5f2502 100644 --- a/public-typescript/lotSearch.ts +++ b/public-typescript/lotSearch.ts @@ -76,7 +76,9 @@ declare const cityssm: cityssmGlobal; "") + ("" + cityssm.escapeHTML(lot.lotType) + "") + ("" + - cityssm.escapeHTML(lot.lotStatus) + + (lot.lotStatusId + ? cityssm.escapeHTML(lot.lotStatus) + : '(No Status)') + "
" + (lot.lotOccupancyCount > 0 ? 'Currently Occupied' diff --git a/public-typescript/main.js b/public-typescript/main.js index 9e83635f..7665b5f1 100644 --- a/public-typescript/main.js +++ b/public-typescript/main.js @@ -128,6 +128,10 @@ Object.defineProperty(exports, "__esModule", { value: true }); const aliasElements = containerElement.querySelectorAll(".alias"); for (const aliasElement of aliasElements) { switch (aliasElement.dataset.alias) { + case "Map": { + aliasElement.textContent = exports.aliases.map; + break; + } case "Lot": { aliasElement.textContent = exports.aliases.lot; break; diff --git a/public-typescript/main.ts b/public-typescript/main.ts index 5d139560..120d40fc 100644 --- a/public-typescript/main.ts +++ b/public-typescript/main.ts @@ -211,36 +211,34 @@ declare const cityssm: cityssmGlobal; for (const aliasElement of aliasElements) { switch (aliasElement.dataset.alias) { + case "Map": { + aliasElement.textContent = exports.aliases.map; + break; + } case "Lot": { aliasElement.textContent = exports.aliases.lot; break; } - case "lot": { aliasElement.textContent = exports.aliases.lot.toLowerCase(); break; } - case "Occupancy": { aliasElement.textContent = exports.aliases.occupancy; break; } - case "occupancy": { aliasElement.textContent = exports.aliases.occupancy.toLowerCase(); break; } - case "Occupant": { aliasElement.textContent = exports.aliases.occupant; break; } - case "occupant": { aliasElement.textContent = exports.aliases.occupant.toLowerCase(); break; } - case "ExternalReceiptNumber": { aliasElement.textContent = exports.aliases.externalReceiptNumber; break; diff --git a/public/html/lotOccupancy-selectLot.html b/public/html/lotOccupancy-selectLot.html index be4db062..788bd31c 100644 --- a/public/html/lotOccupancy-selectLot.html +++ b/public/html/lotOccupancy-selectLot.html @@ -8,35 +8,109 @@