diff --git a/handlers/admin-post/doUpdateOccupancyTypeField.d.ts b/handlers/admin-post/doUpdateOccupancyTypeField.d.ts new file mode 100644 index 00000000..9621c611 --- /dev/null +++ b/handlers/admin-post/doUpdateOccupancyTypeField.d.ts @@ -0,0 +1,3 @@ +import type { RequestHandler } from "express"; +export declare const handler: RequestHandler; +export default handler; diff --git a/handlers/admin-post/doUpdateOccupancyTypeField.js b/handlers/admin-post/doUpdateOccupancyTypeField.js new file mode 100644 index 00000000..2cd41510 --- /dev/null +++ b/handlers/admin-post/doUpdateOccupancyTypeField.js @@ -0,0 +1,11 @@ +import { updateOccupancyTypeField } from "../../helpers/lotOccupancyDB/updateOccupancyTypeField.js"; +import { getOccupancyTypes } from "../../helpers/functions.cache.js"; +export const handler = async (request, response) => { + const success = updateOccupancyTypeField(request.body, request.session); + const occupancyTypes = getOccupancyTypes(); + response.json({ + success, + occupancyTypes + }); +}; +export default handler; diff --git a/handlers/admin-post/doUpdateOccupancyTypeField.ts b/handlers/admin-post/doUpdateOccupancyTypeField.ts new file mode 100644 index 00000000..c378f0f4 --- /dev/null +++ b/handlers/admin-post/doUpdateOccupancyTypeField.ts @@ -0,0 +1,18 @@ +import type { RequestHandler } from "express"; + +import { updateOccupancyTypeField } from "../../helpers/lotOccupancyDB/updateOccupancyTypeField.js"; + +import { getOccupancyTypes } from "../../helpers/functions.cache.js"; + +export const handler: RequestHandler = async (request, response) => { + const success = updateOccupancyTypeField(request.body, request.session); + + const occupancyTypes = getOccupancyTypes(); + + response.json({ + success, + occupancyTypes + }); +}; + +export default handler; diff --git a/helpers/lotOccupancyDB/updateOccupancyTypeField.d.ts b/helpers/lotOccupancyDB/updateOccupancyTypeField.d.ts new file mode 100644 index 00000000..eaba42c5 --- /dev/null +++ b/helpers/lotOccupancyDB/updateOccupancyTypeField.d.ts @@ -0,0 +1,12 @@ +import type * as recordTypes from "../../types/recordTypes"; +interface UpdateOccupancyTypeFieldForm { + occupancyTypeFieldId: number | string; + occupancyTypeField: string; + isRequired: "0" | "1"; + minimumLength?: string; + maximumLength?: string; + pattern?: string; + occupancyTypeFieldValues: string; +} +export declare const updateOccupancyTypeField: (occupancyTypeFieldForm: UpdateOccupancyTypeFieldForm, requestSession: recordTypes.PartialSession) => boolean; +export default updateOccupancyTypeField; diff --git a/helpers/lotOccupancyDB/updateOccupancyTypeField.js b/helpers/lotOccupancyDB/updateOccupancyTypeField.js new file mode 100644 index 00000000..bfb7dee2 --- /dev/null +++ b/helpers/lotOccupancyDB/updateOccupancyTypeField.js @@ -0,0 +1,24 @@ +import sqlite from "better-sqlite3"; +import { lotOccupancyDB as databasePath } from "../../data/databasePaths.js"; +import { clearOccupancyTypesCache } from "../functions.cache.js"; +export const updateOccupancyTypeField = (occupancyTypeFieldForm, requestSession) => { + const database = sqlite(databasePath); + const rightNowMillis = Date.now(); + const result = database + .prepare("update OccupancyTypeFields" + + " set occupancyTypeField = ?," + + " isRequired = ?," + + " minimumLength = ?," + + " maximumLength = ?," + + " pattern = ?," + + " occupancyTypeFieldValues = ?," + + " recordUpdate_userName = ?," + + " recordUpdate_timeMillis = ?" + + " where occupancyTypeFieldId = ?" + + " and recordDelete_timeMillis is null") + .run(occupancyTypeFieldForm.occupancyTypeField, Number.parseInt(occupancyTypeFieldForm.isRequired, 10), occupancyTypeFieldForm.minimumLength || 0, occupancyTypeFieldForm.maximumLength || 100, occupancyTypeFieldForm.pattern || "", occupancyTypeFieldForm.occupancyTypeFieldValues, requestSession.user.userName, rightNowMillis, occupancyTypeFieldForm.occupancyTypeFieldId); + database.close(); + clearOccupancyTypesCache(); + return result.changes > 0; +}; +export default updateOccupancyTypeField; diff --git a/helpers/lotOccupancyDB/updateOccupancyTypeField.ts b/helpers/lotOccupancyDB/updateOccupancyTypeField.ts new file mode 100644 index 00000000..8669f2d0 --- /dev/null +++ b/helpers/lotOccupancyDB/updateOccupancyTypeField.ts @@ -0,0 +1,60 @@ +import sqlite from "better-sqlite3"; + +import { lotOccupancyDB as databasePath } from "../../data/databasePaths.js"; + +import { clearOccupancyTypesCache } from "../functions.cache.js"; + +import type * as recordTypes from "../../types/recordTypes"; + +interface UpdateOccupancyTypeFieldForm { + occupancyTypeFieldId: number | string; + occupancyTypeField: string; + isRequired: "0" | "1"; + minimumLength?: string; + maximumLength?: string; + pattern?: string; + occupancyTypeFieldValues: string; +} + +export const updateOccupancyTypeField = ( + occupancyTypeFieldForm: UpdateOccupancyTypeFieldForm, + requestSession: recordTypes.PartialSession +): boolean => { + const database = sqlite(databasePath); + + const rightNowMillis = Date.now(); + + const result = database + .prepare( + "update OccupancyTypeFields" + + " set occupancyTypeField = ?," + + " isRequired = ?," + + " minimumLength = ?," + + " maximumLength = ?," + + " pattern = ?," + + " occupancyTypeFieldValues = ?," + + " recordUpdate_userName = ?," + + " recordUpdate_timeMillis = ?" + + " where occupancyTypeFieldId = ?" + + " and recordDelete_timeMillis is null" + ) + .run( + occupancyTypeFieldForm.occupancyTypeField, + Number.parseInt(occupancyTypeFieldForm.isRequired, 10), + occupancyTypeFieldForm.minimumLength || 0, + occupancyTypeFieldForm.maximumLength || 100, + occupancyTypeFieldForm.pattern || "", + occupancyTypeFieldForm.occupancyTypeFieldValues, + requestSession.user.userName, + rightNowMillis, + occupancyTypeFieldForm.occupancyTypeFieldId + ); + + database.close(); + + clearOccupancyTypesCache(); + + return result.changes > 0; +}; + +export default updateOccupancyTypeField; diff --git a/public-typescript/adminOccupancyTypes.js b/public-typescript/adminOccupancyTypes.js index 505d3c15..b495b6da 100644 --- a/public-typescript/adminOccupancyTypes.js +++ b/public-typescript/adminOccupancyTypes.js @@ -104,9 +104,6 @@ Object.defineProperty(exports, "__esModule", { value: true }); }; const openAddOccupancyTypeField = (clickEvent) => { const occupancyTypeId = Number.parseInt(clickEvent.currentTarget.closest(".container--occupancyType").dataset.occupancyTypeId, 10); - const occupancyType = occupancyTypes.find((currentOccupancyType) => { - return occupancyTypeId === currentOccupancyType.occupancyTypeId; - }); let addCloseModalFunction; const doAdd = (submitEvent) => { submitEvent.preventDefault(); @@ -116,6 +113,7 @@ Object.defineProperty(exports, "__esModule", { value: true }); addCloseModalFunction(); occupancyTypes = responseJSON.occupancyTypes; renderOccupancyTypes(); + openEditOccupancyTypeField(occupancyTypeId, responseJSON.occupancyTypeFieldId); } else { bulmaJS.alert({ @@ -186,6 +184,93 @@ Object.defineProperty(exports, "__esModule", { value: true }); } }); }; + const openEditOccupancyTypeField = (occupancyTypeId, occupancyTypeFieldId) => { + const occupancyType = occupancyTypes.find((currentOccupancyType) => { + return currentOccupancyType.occupancyTypeId === occupancyTypeId; + }); + const occupancyTypeField = occupancyType.occupancyTypeFields.find((currentOccupancyTypeField) => { + return (currentOccupancyTypeField.occupancyTypeFieldId === + occupancyTypeFieldId); + }); + let minimumLengthElement; + let maximumLengthElement; + let patternElement; + let occupancyTypeFieldValuesElement; + let editCloseModalFunction; + const updateMaximumLengthMin = () => { + maximumLengthElement.min = minimumLengthElement.value; + }; + const toggleInputFields = () => { + if (occupancyTypeFieldValuesElement.value === "") { + minimumLengthElement.disabled = false; + maximumLengthElement.disabled = false; + patternElement.disabled = false; + } + else { + minimumLengthElement.disabled = true; + maximumLengthElement.disabled = true; + patternElement.disabled = true; + } + }; + const doUpdate = (submitEvent) => { + submitEvent.preventDefault(); + cityssm.postJSON(urlPrefix + "/admin/doUpdateOccupancyTypeField", submitEvent.currentTarget, (responseJSON) => { + if (responseJSON.success) { + occupancyTypes = responseJSON.occupancyTypes; + editCloseModalFunction(); + renderOccupancyTypes(); + } + else { + bulmaJS.alert({ + title: "Error Updating Field", + message: responseJSON.errorMessage, + contextualColorName: "danger" + }); + } + }); + }; + cityssm.openHtmlModal("adminOccupancyTypes-editOccupancyTypeField", { + onshow: (modalElement) => { + los.populateAliases(modalElement); + modalElement.querySelector("#occupancyTypeFieldEdit--occupancyTypeFieldId").value = occupancyTypeField.occupancyTypeFieldId.toString(); + modalElement.querySelector("#occupancyTypeFieldEdit--occupancyTypeField").value = occupancyTypeField.occupancyTypeField; + modalElement.querySelector("#occupancyTypeFieldEdit--isRequired").value = occupancyTypeField.isRequired ? "1" : "0"; + minimumLengthElement = modalElement.querySelector("#occupancyTypeFieldEdit--minimumLength"); + minimumLengthElement.value = + occupancyTypeField.minimumLength.toString(); + maximumLengthElement = modalElement.querySelector("#occupancyTypeFieldEdit--maximumLength"); + maximumLengthElement.value = + occupancyTypeField.maximumLength.toString(); + patternElement = modalElement.querySelector("#occupancyTypeFieldEdit--pattern"); + patternElement.value = occupancyTypeField.pattern; + occupancyTypeFieldValuesElement = modalElement.querySelector("#occupancyTypeFieldEdit--occupancyTypeFieldValues"); + occupancyTypeFieldValuesElement.value = + occupancyTypeField.occupancyTypeFieldValues; + toggleInputFields(); + }, + onshown: (modalElement, closeModalFunction) => { + editCloseModalFunction = closeModalFunction; + bulmaJS.toggleHtmlClipped(); + cityssm.enableNavBlocker(); + modalElement + .querySelector("form") + .addEventListener("submit", doUpdate); + minimumLengthElement.addEventListener("keyup", updateMaximumLengthMin); + updateMaximumLengthMin(); + occupancyTypeFieldValuesElement.addEventListener("keyup", toggleInputFields); + }, + onremoved: () => { + bulmaJS.toggleHtmlClipped(); + cityssm.disableNavBlocker(); + } + }); + }; + const openEditOccupancyTypeFieldByClick = (clickEvent) => { + clickEvent.preventDefault(); + const occupancyTypeFieldId = Number.parseInt(clickEvent.currentTarget.closest(".container--occupancyTypeField").dataset.occupancyTypeFieldId, 10); + const occupancyTypeId = Number.parseInt(clickEvent.currentTarget.closest(".container--occupancyType").dataset.occupancyTypeId, 10); + openEditOccupancyTypeField(occupancyTypeId, occupancyTypeFieldId); + }; const renderOccupancyTypes = () => { if (occupancyTypes.length === 0) { containerElement.innerHTML = @@ -304,6 +389,9 @@ Object.defineProperty(exports, "__esModule", { value: true }); "") + "" + ""; + panelBlockElement + .querySelector(".button--editOccupancyTypeField") + .addEventListener("click", openEditOccupancyTypeFieldByClick); occupancyTypeContainer.append(panelBlockElement); } } diff --git a/public-typescript/adminOccupancyTypes.ts b/public-typescript/adminOccupancyTypes.ts index 0e7b85a1..a9696c3e 100644 --- a/public-typescript/adminOccupancyTypes.ts +++ b/public-typescript/adminOccupancyTypes.ts @@ -201,10 +201,6 @@ declare const bulmaJS: BulmaJS; 10 ); - const occupancyType = occupancyTypes.find((currentOccupancyType) => { - return occupancyTypeId === currentOccupancyType.occupancyTypeId; - }); - let addCloseModalFunction: () => void; const doAdd = (submitEvent: SubmitEvent) => { @@ -217,6 +213,7 @@ declare const bulmaJS: BulmaJS; success: boolean; errorMessage?: string; occupancyTypes?: recordTypes.OccupancyType[]; + occupancyTypeFieldId?: number; }) => { if (responseJSON.success) { expandedOccupancyTypes.add(occupancyTypeId); @@ -224,6 +221,11 @@ declare const bulmaJS: BulmaJS; addCloseModalFunction(); occupancyTypes = responseJSON.occupancyTypes; renderOccupancyTypes(); + + openEditOccupancyTypeField( + occupancyTypeId, + responseJSON.occupancyTypeFieldId + ); } else { bulmaJS.alert({ title: "Error Adding Field", @@ -338,6 +340,175 @@ declare const bulmaJS: BulmaJS; ); }; + const openEditOccupancyTypeField = ( + occupancyTypeId: number, + occupancyTypeFieldId: number + ) => { + const occupancyType = occupancyTypes.find((currentOccupancyType) => { + return currentOccupancyType.occupancyTypeId === occupancyTypeId; + }); + + const occupancyTypeField = occupancyType.occupancyTypeFields.find( + (currentOccupancyTypeField) => { + return ( + currentOccupancyTypeField.occupancyTypeFieldId === + occupancyTypeFieldId + ); + } + ); + + let minimumLengthElement: HTMLInputElement; + let maximumLengthElement: HTMLInputElement; + let patternElement: HTMLInputElement; + let occupancyTypeFieldValuesElement: HTMLTextAreaElement; + + let editCloseModalFunction: () => void; + + const updateMaximumLengthMin = () => { + maximumLengthElement.min = minimumLengthElement.value; + }; + + const toggleInputFields = () => { + if (occupancyTypeFieldValuesElement.value === "") { + minimumLengthElement.disabled = false; + maximumLengthElement.disabled = false; + patternElement.disabled = false; + } else { + minimumLengthElement.disabled = true; + maximumLengthElement.disabled = true; + patternElement.disabled = true; + } + }; + + const doUpdate = (submitEvent: SubmitEvent) => { + submitEvent.preventDefault(); + + cityssm.postJSON( + urlPrefix + "/admin/doUpdateOccupancyTypeField", + submitEvent.currentTarget, + (responseJSON: { + success: boolean; + errorMessage?: string; + occupancyTypes?: recordTypes.OccupancyType[]; + }) => { + if (responseJSON.success) { + occupancyTypes = responseJSON.occupancyTypes; + editCloseModalFunction(); + renderOccupancyTypes(); + } else { + bulmaJS.alert({ + title: "Error Updating Field", + message: responseJSON.errorMessage, + contextualColorName: "danger" + }); + } + } + ); + }; + + cityssm.openHtmlModal("adminOccupancyTypes-editOccupancyTypeField", { + onshow: (modalElement) => { + los.populateAliases(modalElement); + + ( + modalElement.querySelector( + "#occupancyTypeFieldEdit--occupancyTypeFieldId" + ) as HTMLInputElement + ).value = occupancyTypeField.occupancyTypeFieldId.toString(); + + ( + modalElement.querySelector( + "#occupancyTypeFieldEdit--occupancyTypeField" + ) as HTMLInputElement + ).value = occupancyTypeField.occupancyTypeField; + + ( + modalElement.querySelector( + "#occupancyTypeFieldEdit--isRequired" + ) as HTMLSelectElement + ).value = occupancyTypeField.isRequired ? "1" : "0"; + + minimumLengthElement = modalElement.querySelector( + "#occupancyTypeFieldEdit--minimumLength" + ); + + minimumLengthElement.value = + occupancyTypeField.minimumLength.toString(); + + maximumLengthElement = modalElement.querySelector( + "#occupancyTypeFieldEdit--maximumLength" + ); + + maximumLengthElement.value = + occupancyTypeField.maximumLength.toString(); + + patternElement = modalElement.querySelector( + "#occupancyTypeFieldEdit--pattern" + ); + + patternElement.value = occupancyTypeField.pattern; + + occupancyTypeFieldValuesElement = modalElement.querySelector( + "#occupancyTypeFieldEdit--occupancyTypeFieldValues" + ); + + occupancyTypeFieldValuesElement.value = + occupancyTypeField.occupancyTypeFieldValues; + + toggleInputFields(); + }, + onshown: (modalElement, closeModalFunction) => { + editCloseModalFunction = closeModalFunction; + + bulmaJS.toggleHtmlClipped(); + cityssm.enableNavBlocker(); + + modalElement + .querySelector("form") + .addEventListener("submit", doUpdate); + + minimumLengthElement.addEventListener( + "keyup", + updateMaximumLengthMin + ); + updateMaximumLengthMin(); + + occupancyTypeFieldValuesElement.addEventListener( + "keyup", + toggleInputFields + ); + }, + onremoved: () => { + bulmaJS.toggleHtmlClipped(); + cityssm.disableNavBlocker(); + } + }); + }; + + const openEditOccupancyTypeFieldByClick = (clickEvent: Event) => { + clickEvent.preventDefault(); + + const occupancyTypeFieldId = Number.parseInt( + ( + (clickEvent.currentTarget as HTMLElement).closest( + ".container--occupancyTypeField" + ) as HTMLElement + ).dataset.occupancyTypeFieldId, + 10 + ); + + const occupancyTypeId = Number.parseInt( + ( + (clickEvent.currentTarget as HTMLElement).closest( + ".container--occupancyType" + ) as HTMLElement + ).dataset.occupancyTypeId, + 10 + ); + + openEditOccupancyTypeField(occupancyTypeId, occupancyTypeFieldId); + }; + const renderOccupancyTypes = () => { if (occupancyTypes.length === 0) { containerElement.innerHTML = @@ -477,6 +648,13 @@ declare const bulmaJS: BulmaJS; "" + ""; + panelBlockElement + .querySelector(".button--editOccupancyTypeField") + .addEventListener( + "click", + openEditOccupancyTypeFieldByClick + ); + occupancyTypeContainer.append(panelBlockElement); } } diff --git a/public/html/adminOccupancyTypes-addOccupancyTypeField.html b/public/html/adminOccupancyTypes-addOccupancyTypeField.html index 43c899ac..33794c3f 100644 --- a/public/html/adminOccupancyTypes-addOccupancyTypeField.html +++ b/public/html/adminOccupancyTypes-addOccupancyTypeField.html @@ -11,7 +11,7 @@