From 4888bd2294d8f2da5b3be9ae234ae8aee006ba92 Mon Sep 17 00:00:00 2001 From: Dan Gowans Date: Tue, 8 Nov 2022 12:12:02 -0500 Subject: [PATCH] copy lot occupancy as new --- .../doCopyLotOccupancy.d.ts | 3 + .../lotOccupancies-post/doCopyLotOccupancy.js | 9 +++ .../lotOccupancies-post/doCopyLotOccupancy.ts | 14 ++++ helpers/lotOccupancyDB/addLotOccupancy.d.ts | 3 +- helpers/lotOccupancyDB/addLotOccupancy.js | 8 +- helpers/lotOccupancyDB/addLotOccupancy.ts | 17 ++-- .../addLotOccupancyOccupant.d.ts | 3 +- .../lotOccupancyDB/addLotOccupancyOccupant.js | 8 +- .../lotOccupancyDB/addLotOccupancyOccupant.ts | 9 ++- helpers/lotOccupancyDB/copyLotOccupancy.d.ts | 3 + helpers/lotOccupancyDB/copyLotOccupancy.js | 42 ++++++++++ helpers/lotOccupancyDB/copyLotOccupancy.ts | 81 +++++++++++++++++++ helpers/lotOccupancyDB/getLotOccupancy.d.ts | 3 +- helpers/lotOccupancyDB/getLotOccupancy.js | 13 +-- helpers/lotOccupancyDB/getLotOccupancy.ts | 35 ++++---- public-typescript/lotOccupancyEdit.js | 47 ++++++++++- public-typescript/lotOccupancyEdit.ts | 62 +++++++++++++- public/javascripts/lotOccupancyEdit.min.js | 2 +- routes/lotOccupancies.js | 2 + routes/lotOccupancies.ts | 7 ++ views/lotOccupancy-edit.ejs | 4 + 21 files changed, 324 insertions(+), 51 deletions(-) create mode 100644 handlers/lotOccupancies-post/doCopyLotOccupancy.d.ts create mode 100644 handlers/lotOccupancies-post/doCopyLotOccupancy.js create mode 100644 handlers/lotOccupancies-post/doCopyLotOccupancy.ts create mode 100644 helpers/lotOccupancyDB/copyLotOccupancy.d.ts create mode 100644 helpers/lotOccupancyDB/copyLotOccupancy.js create mode 100644 helpers/lotOccupancyDB/copyLotOccupancy.ts diff --git a/handlers/lotOccupancies-post/doCopyLotOccupancy.d.ts b/handlers/lotOccupancies-post/doCopyLotOccupancy.d.ts new file mode 100644 index 00000000..9621c611 --- /dev/null +++ b/handlers/lotOccupancies-post/doCopyLotOccupancy.d.ts @@ -0,0 +1,3 @@ +import type { RequestHandler } from "express"; +export declare const handler: RequestHandler; +export default handler; diff --git a/handlers/lotOccupancies-post/doCopyLotOccupancy.js b/handlers/lotOccupancies-post/doCopyLotOccupancy.js new file mode 100644 index 00000000..1e8bb02d --- /dev/null +++ b/handlers/lotOccupancies-post/doCopyLotOccupancy.js @@ -0,0 +1,9 @@ +import { copyLotOccupancy } from "../../helpers/lotOccupancyDB/copyLotOccupancy.js"; +export const handler = async (request, response) => { + const lotOccupancyId = copyLotOccupancy(request.body.lotOccupancyId, request.session); + response.json({ + success: true, + lotOccupancyId + }); +}; +export default handler; diff --git a/handlers/lotOccupancies-post/doCopyLotOccupancy.ts b/handlers/lotOccupancies-post/doCopyLotOccupancy.ts new file mode 100644 index 00000000..35eadacb --- /dev/null +++ b/handlers/lotOccupancies-post/doCopyLotOccupancy.ts @@ -0,0 +1,14 @@ +import type { RequestHandler } from "express"; + +import { copyLotOccupancy } from "../../helpers/lotOccupancyDB/copyLotOccupancy.js"; + +export const handler: RequestHandler = async (request, response) => { + const lotOccupancyId = copyLotOccupancy(request.body.lotOccupancyId, request.session); + + response.json({ + success: true, + lotOccupancyId + }); +}; + +export default handler; diff --git a/helpers/lotOccupancyDB/addLotOccupancy.d.ts b/helpers/lotOccupancyDB/addLotOccupancy.d.ts index de1e04cb..71c50548 100644 --- a/helpers/lotOccupancyDB/addLotOccupancy.d.ts +++ b/helpers/lotOccupancyDB/addLotOccupancy.d.ts @@ -1,3 +1,4 @@ +import sqlite from "better-sqlite3"; import type * as recordTypes from "../../types/recordTypes"; interface AddLotOccupancyForm { occupancyTypeId: string | number; @@ -7,5 +8,5 @@ interface AddLotOccupancyForm { occupancyTypeFieldIds?: string; [lotOccupancyFieldValue_occupancyTypeFieldId: string]: unknown; } -export declare const addLotOccupancy: (lotOccupancyForm: AddLotOccupancyForm, requestSession: recordTypes.PartialSession) => number; +export declare const addLotOccupancy: (lotOccupancyForm: AddLotOccupancyForm, requestSession: recordTypes.PartialSession, connectedDatabase?: sqlite.Database) => number; export default addLotOccupancy; diff --git a/helpers/lotOccupancyDB/addLotOccupancy.js b/helpers/lotOccupancyDB/addLotOccupancy.js index af4c2f07..412c88b1 100644 --- a/helpers/lotOccupancyDB/addLotOccupancy.js +++ b/helpers/lotOccupancyDB/addLotOccupancy.js @@ -2,8 +2,8 @@ import sqlite from "better-sqlite3"; import { lotOccupancyDB as databasePath } from "../../data/databasePaths.js"; import * as dateTimeFunctions from "@cityssm/expressjs-server-js/dateTimeFns.js"; import { addOrUpdateLotOccupancyField } from "./addOrUpdateLotOccupancyField.js"; -export const addLotOccupancy = (lotOccupancyForm, requestSession) => { - const database = sqlite(databasePath); +export const addLotOccupancy = (lotOccupancyForm, requestSession, connectedDatabase) => { + const database = connectedDatabase || sqlite(databasePath); const rightNowMillis = Date.now(); const occupancyStartDate = dateTimeFunctions.dateStringToInteger(lotOccupancyForm.occupancyStartDateString); if (occupancyStartDate <= 0) { @@ -31,7 +31,9 @@ export const addLotOccupancy = (lotOccupancyForm, requestSession) => { }, requestSession, database); } } - database.close(); + if (!connectedDatabase) { + database.close(); + } return lotOccupancyId; }; export default addLotOccupancy; diff --git a/helpers/lotOccupancyDB/addLotOccupancy.ts b/helpers/lotOccupancyDB/addLotOccupancy.ts index 5cc7604b..0a414271 100644 --- a/helpers/lotOccupancyDB/addLotOccupancy.ts +++ b/helpers/lotOccupancyDB/addLotOccupancy.ts @@ -21,9 +21,10 @@ interface AddLotOccupancyForm { export const addLotOccupancy = ( lotOccupancyForm: AddLotOccupancyForm, - requestSession: recordTypes.PartialSession + requestSession: recordTypes.PartialSession, + connectedDatabase?: sqlite.Database ): number => { - const database = sqlite(databasePath); + const database = connectedDatabase || sqlite(databasePath); const rightNowMillis = Date.now(); @@ -50,9 +51,7 @@ export const addLotOccupancy = ( occupancyStartDate, lotOccupancyForm.occupancyEndDateString === "" ? undefined - : dateTimeFunctions.dateStringToInteger( - lotOccupancyForm.occupancyEndDateString - ), + : dateTimeFunctions.dateStringToInteger(lotOccupancyForm.occupancyEndDateString), requestSession.user.userName, rightNowMillis, requestSession.user.userName, @@ -61,9 +60,7 @@ export const addLotOccupancy = ( const lotOccupancyId = result.lastInsertRowid as number; - const occupancyTypeFieldIds = ( - lotOccupancyForm.occupancyTypeFieldIds || "" - ).split(","); + const occupancyTypeFieldIds = (lotOccupancyForm.occupancyTypeFieldIds || "").split(","); for (const occupancyTypeFieldId of occupancyTypeFieldIds) { const lotOccupancyFieldValue = lotOccupancyForm[ @@ -83,7 +80,9 @@ export const addLotOccupancy = ( } } - database.close(); + if (!connectedDatabase) { + database.close(); + } return lotOccupancyId; }; diff --git a/helpers/lotOccupancyDB/addLotOccupancyOccupant.d.ts b/helpers/lotOccupancyDB/addLotOccupancyOccupant.d.ts index 1c2f1449..5a574e6d 100644 --- a/helpers/lotOccupancyDB/addLotOccupancyOccupant.d.ts +++ b/helpers/lotOccupancyDB/addLotOccupancyOccupant.d.ts @@ -1,3 +1,4 @@ +import sqlite from "better-sqlite3"; import type * as recordTypes from "../../types/recordTypes"; interface AddLotOccupancyOccupantForm { lotOccupancyId: string | number; @@ -11,5 +12,5 @@ interface AddLotOccupancyOccupantForm { occupantPhoneNumber: string; occupantEmailAddress: string; } -export declare const addLotOccupancyOccupant: (lotOccupancyOccupantForm: AddLotOccupancyOccupantForm, requestSession: recordTypes.PartialSession) => number; +export declare const addLotOccupancyOccupant: (lotOccupancyOccupantForm: AddLotOccupancyOccupantForm, requestSession: recordTypes.PartialSession, connectedDatabase?: sqlite.Database) => number; export default addLotOccupancyOccupant; diff --git a/helpers/lotOccupancyDB/addLotOccupancyOccupant.js b/helpers/lotOccupancyDB/addLotOccupancyOccupant.js index 8fe9bb92..e17f7dec 100644 --- a/helpers/lotOccupancyDB/addLotOccupancyOccupant.js +++ b/helpers/lotOccupancyDB/addLotOccupancyOccupant.js @@ -1,7 +1,7 @@ import sqlite from "better-sqlite3"; import { lotOccupancyDB as databasePath } from "../../data/databasePaths.js"; -export const addLotOccupancyOccupant = (lotOccupancyOccupantForm, requestSession) => { - const database = sqlite(databasePath); +export const addLotOccupancyOccupant = (lotOccupancyOccupantForm, requestSession, connectedDatabase) => { + const database = connectedDatabase || sqlite(databasePath); let lotOccupantIndex = 0; const maxIndexResult = database .prepare("select lotOccupantIndex" + @@ -26,7 +26,9 @@ export const addLotOccupancyOccupant = (lotOccupancyOccupantForm, requestSession " recordUpdate_userName, recordUpdate_timeMillis)" + " values (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)") .run(lotOccupancyOccupantForm.lotOccupancyId, lotOccupantIndex, lotOccupancyOccupantForm.occupantName, lotOccupancyOccupantForm.occupantAddress1, lotOccupancyOccupantForm.occupantAddress2, lotOccupancyOccupantForm.occupantCity, lotOccupancyOccupantForm.occupantProvince, lotOccupancyOccupantForm.occupantPostalCode, lotOccupancyOccupantForm.occupantPhoneNumber, lotOccupancyOccupantForm.occupantEmailAddress, lotOccupancyOccupantForm.lotOccupantTypeId, requestSession.user.userName, rightNowMillis, requestSession.user.userName, rightNowMillis); - database.close(); + if (!connectedDatabase) { + database.close(); + } return lotOccupantIndex; }; export default addLotOccupancyOccupant; diff --git a/helpers/lotOccupancyDB/addLotOccupancyOccupant.ts b/helpers/lotOccupancyDB/addLotOccupancyOccupant.ts index 184b1306..7ccf2d5e 100644 --- a/helpers/lotOccupancyDB/addLotOccupancyOccupant.ts +++ b/helpers/lotOccupancyDB/addLotOccupancyOccupant.ts @@ -19,9 +19,10 @@ interface AddLotOccupancyOccupantForm { export const addLotOccupancyOccupant = ( lotOccupancyOccupantForm: AddLotOccupancyOccupantForm, - requestSession: recordTypes.PartialSession + requestSession: recordTypes.PartialSession, + connectedDatabase?: sqlite.Database ): number => { - const database = sqlite(databasePath); + const database = connectedDatabase || sqlite(databasePath); let lotOccupantIndex = 0; @@ -72,7 +73,9 @@ export const addLotOccupancyOccupant = ( rightNowMillis ); - database.close(); + if (!connectedDatabase) { + database.close(); + } return lotOccupantIndex; }; diff --git a/helpers/lotOccupancyDB/copyLotOccupancy.d.ts b/helpers/lotOccupancyDB/copyLotOccupancy.d.ts new file mode 100644 index 00000000..704794be --- /dev/null +++ b/helpers/lotOccupancyDB/copyLotOccupancy.d.ts @@ -0,0 +1,3 @@ +import type * as recordTypes from "../../types/recordTypes"; +export declare const copyLotOccupancy: (oldLotOccupancyId: number | string, requestSession: recordTypes.PartialSession) => number; +export default copyLotOccupancy; diff --git a/helpers/lotOccupancyDB/copyLotOccupancy.js b/helpers/lotOccupancyDB/copyLotOccupancy.js new file mode 100644 index 00000000..ca07c036 --- /dev/null +++ b/helpers/lotOccupancyDB/copyLotOccupancy.js @@ -0,0 +1,42 @@ +import sqlite from "better-sqlite3"; +import { lotOccupancyDB as databasePath } from "../../data/databasePaths.js"; +import { getLotOccupancy } from "./getLotOccupancy.js"; +import { addLotOccupancy } from "./addLotOccupancy.js"; +import { addLotOccupancyOccupant } from "./addLotOccupancyOccupant.js"; +import { dateToString } from "@cityssm/expressjs-server-js/dateTimeFns.js"; +export const copyLotOccupancy = (oldLotOccupancyId, requestSession) => { + const database = sqlite(databasePath); + const oldLotOccupancy = getLotOccupancy(oldLotOccupancyId, database); + const newLotOccupancyId = addLotOccupancy({ + lotId: oldLotOccupancy.lotId || "", + occupancyTypeId: oldLotOccupancy.occupancyTypeId, + occupancyStartDateString: dateToString(new Date()), + occupancyEndDateString: "" + }, requestSession, database); + const rightNowMillis = Date.now(); + for (const occupancyField of oldLotOccupancy.lotOccupancyFields) { + database + .prepare("insert into LotOccupancyFields" + + " (lotOccupancyId, occupancyTypeFieldId, lotOccupancyFieldValue," + + " recordCreate_userName, recordCreate_timeMillis, recordUpdate_userName, recordUpdate_timeMillis)" + + " values (?, ?, ?, ?, ?, ?, ?)") + .run(newLotOccupancyId, occupancyField.occupancyTypeFieldId, occupancyField.lotOccupancyFieldValue, requestSession.user.userName, rightNowMillis, requestSession.user.userName, rightNowMillis); + } + for (const occupant of oldLotOccupancy.lotOccupancyOccupants) { + addLotOccupancyOccupant({ + lotOccupancyId: newLotOccupancyId, + lotOccupantTypeId: occupant.lotOccupantTypeId, + occupantName: occupant.occupantName, + occupantAddress1: occupant.occupantAddress1, + occupantAddress2: occupant.occupantAddress2, + occupantCity: occupant.occupantCity, + occupantProvince: occupant.occupantProvince, + occupantPostalCode: occupant.occupantPostalCode, + occupantPhoneNumber: occupant.occupantPhoneNumber, + occupantEmailAddress: occupant.occupantEmailAddress + }, requestSession, database); + } + database.close(); + return newLotOccupancyId; +}; +export default copyLotOccupancy; diff --git a/helpers/lotOccupancyDB/copyLotOccupancy.ts b/helpers/lotOccupancyDB/copyLotOccupancy.ts new file mode 100644 index 00000000..065de521 --- /dev/null +++ b/helpers/lotOccupancyDB/copyLotOccupancy.ts @@ -0,0 +1,81 @@ +import sqlite from "better-sqlite3"; + +import { lotOccupancyDB as databasePath } from "../../data/databasePaths.js"; + +import { getLotOccupancy } from "./getLotOccupancy.js"; +import { addLotOccupancy } from "./addLotOccupancy.js"; +import { addLotOccupancyOccupant } from "./addLotOccupancyOccupant.js"; + +import { dateToString } from "@cityssm/expressjs-server-js/dateTimeFns.js"; + +import type * as recordTypes from "../../types/recordTypes"; + +export const copyLotOccupancy = ( + oldLotOccupancyId: number | string, + requestSession: recordTypes.PartialSession +): number => { + const database = sqlite(databasePath); + + const oldLotOccupancy = getLotOccupancy(oldLotOccupancyId, database); + + const newLotOccupancyId = addLotOccupancy( + { + lotId: oldLotOccupancy.lotId || "", + occupancyTypeId: oldLotOccupancy.occupancyTypeId, + occupancyStartDateString: dateToString(new Date()), + occupancyEndDateString: "" + }, + requestSession, + database + ); + + // Copy Fields + + const rightNowMillis = Date.now(); + + for (const occupancyField of oldLotOccupancy.lotOccupancyFields) { + database + .prepare( + "insert into LotOccupancyFields" + + " (lotOccupancyId, occupancyTypeFieldId, lotOccupancyFieldValue," + + " recordCreate_userName, recordCreate_timeMillis, recordUpdate_userName, recordUpdate_timeMillis)" + + " values (?, ?, ?, ?, ?, ?, ?)" + ) + .run( + newLotOccupancyId, + occupancyField.occupancyTypeFieldId, + occupancyField.lotOccupancyFieldValue, + requestSession.user.userName, + rightNowMillis, + requestSession.user.userName, + rightNowMillis + ); + } + + // Copy Occupants + + for (const occupant of oldLotOccupancy.lotOccupancyOccupants) { + addLotOccupancyOccupant( + { + lotOccupancyId: newLotOccupancyId, + lotOccupantTypeId: occupant.lotOccupantTypeId, + occupantName: occupant.occupantName, + occupantAddress1: occupant.occupantAddress1, + occupantAddress2: occupant.occupantAddress2, + occupantCity: occupant.occupantCity, + occupantProvince: occupant.occupantProvince, + occupantPostalCode: occupant.occupantPostalCode, + occupantPhoneNumber: occupant.occupantPhoneNumber, + occupantEmailAddress: occupant.occupantEmailAddress + }, + requestSession, + database + ); + } + + database.close(); + + return newLotOccupancyId; +}; + +export default copyLotOccupancy; diff --git a/helpers/lotOccupancyDB/getLotOccupancy.d.ts b/helpers/lotOccupancyDB/getLotOccupancy.d.ts index 502b6a7a..68292b02 100644 --- a/helpers/lotOccupancyDB/getLotOccupancy.d.ts +++ b/helpers/lotOccupancyDB/getLotOccupancy.d.ts @@ -1,3 +1,4 @@ +import sqlite from "better-sqlite3"; import type * as recordTypes from "../../types/recordTypes"; -export declare const getLotOccupancy: (lotOccupancyId: number | string) => recordTypes.LotOccupancy; +export declare const getLotOccupancy: (lotOccupancyId: number | string, connectedDatabase?: sqlite.Database) => recordTypes.LotOccupancy; export default getLotOccupancy; diff --git a/helpers/lotOccupancyDB/getLotOccupancy.js b/helpers/lotOccupancyDB/getLotOccupancy.js index 5336358f..12a24609 100644 --- a/helpers/lotOccupancyDB/getLotOccupancy.js +++ b/helpers/lotOccupancyDB/getLotOccupancy.js @@ -6,10 +6,11 @@ import { getLotOccupancyComments } from "./getLotOccupancyComments.js"; import { getLotOccupancyFields } from "./getLotOccupancyFields.js"; import { getLotOccupancyFees } from "./getLotOccupancyFees.js"; import { getLotOccupancyTransactions } from "./getLotOccupancyTransactions.js"; -export const getLotOccupancy = (lotOccupancyId) => { - const database = sqlite(databasePath, { - readonly: true - }); +export const getLotOccupancy = (lotOccupancyId, connectedDatabase) => { + const database = connectedDatabase || + sqlite(databasePath, { + readonly: true + }); database.function("userFn_dateIntegerToString", dateIntegerToString); const lotOccupancy = database .prepare("select o.lotOccupancyId," + @@ -33,7 +34,9 @@ export const getLotOccupancy = (lotOccupancyId) => { lotOccupancy.lotOccupancyFees = getLotOccupancyFees(lotOccupancyId, database); lotOccupancy.lotOccupancyTransactions = getLotOccupancyTransactions(lotOccupancyId, database); } - database.close(); + if (!connectedDatabase) { + database.close(); + } return lotOccupancy; }; export default getLotOccupancy; diff --git a/helpers/lotOccupancyDB/getLotOccupancy.ts b/helpers/lotOccupancyDB/getLotOccupancy.ts index df10dd0c..50b45c4f 100644 --- a/helpers/lotOccupancyDB/getLotOccupancy.ts +++ b/helpers/lotOccupancyDB/getLotOccupancy.ts @@ -17,11 +17,14 @@ import { getLotOccupancyTransactions } from "./getLotOccupancyTransactions.js"; import type * as recordTypes from "../../types/recordTypes"; export const getLotOccupancy = ( - lotOccupancyId: number | string + lotOccupancyId: number | string, + connectedDatabase?: sqlite.Database ): recordTypes.LotOccupancy => { - const database = sqlite(databasePath, { - readonly: true - }); + const database = + connectedDatabase || + sqlite(databasePath, { + readonly: true + }); database.function("userFn_dateIntegerToString", dateIntegerToString); @@ -44,29 +47,19 @@ export const getLotOccupancy = ( .get(lotOccupancyId); if (lotOccupancy) { - lotOccupancy.lotOccupancyFields = getLotOccupancyFields( - lotOccupancyId, - database - ); - lotOccupancy.lotOccupancyOccupants = getLotOccupancyOccupants( - lotOccupancyId, - database - ); - lotOccupancy.lotOccupancyComments = getLotOccupancyComments( - lotOccupancyId, - database - ); - lotOccupancy.lotOccupancyFees = getLotOccupancyFees( - lotOccupancyId, - database - ); + lotOccupancy.lotOccupancyFields = getLotOccupancyFields(lotOccupancyId, database); + lotOccupancy.lotOccupancyOccupants = getLotOccupancyOccupants(lotOccupancyId, database); + lotOccupancy.lotOccupancyComments = getLotOccupancyComments(lotOccupancyId, database); + lotOccupancy.lotOccupancyFees = getLotOccupancyFees(lotOccupancyId, database); lotOccupancy.lotOccupancyTransactions = getLotOccupancyTransactions( lotOccupancyId, database ); } - database.close(); + if (!connectedDatabase) { + database.close(); + } return lotOccupancy; }; diff --git a/public-typescript/lotOccupancyEdit.js b/public-typescript/lotOccupancyEdit.js index bdba5b5b..e025e7c7 100644 --- a/public-typescript/lotOccupancyEdit.js +++ b/public-typescript/lotOccupancyEdit.js @@ -53,6 +53,49 @@ Object.defineProperty(exports, "__esModule", { value: true }); formInputElement.addEventListener("change", setUnsavedChanges); } if (!isCreate) { + const doCopy = () => { + cityssm.postJSON(los.urlPrefix + "/lotOccupancies/doCopyLotOccupancy", { + lotOccupancyId + }, (responseJSON) => { + var _a; + if (responseJSON.success) { + cityssm.disableNavBlocker(); + window.location.href = + los.urlPrefix + + "/lotOccupancies/" + + ((_a = responseJSON.lotOccupancyId) === null || _a === void 0 ? void 0 : _a.toString()) + + "/edit"; + } + else { + bulmaJS.alert({ + title: "Error Copying Record", + message: responseJSON.errorMessage || "", + contextualColorName: "danger" + }); + } + }); + }; + document.querySelector("#button--copyLotOccupancy").addEventListener("click", (clickEvent) => { + clickEvent.preventDefault(); + if (hasUnsavedChanges) { + bulmaJS.alert({ + title: "Unsaved Changes", + message: "Please save all unsaved changes before continuing.", + contextualColorName: "warning" + }); + } + else { + bulmaJS.confirm({ + title: "Copy " + exports.aliases.occupancy + " Record as New", + message: "Are you sure you want to copy this record to a new record?", + contextualColorName: "info", + okButton: { + text: "Yes, Copy", + callbackFunction: doCopy + } + }); + } + }); document.querySelector("#button--deleteLotOccupancy").addEventListener("click", (clickEvent) => { clickEvent.preventDefault(); const doDelete = () => { @@ -1104,7 +1147,9 @@ Object.defineProperty(exports, "__esModule", { value: true }); cityssm.escapeHTML(fee.feeName || "") + "
" + "" + - cityssm.escapeHTML(fee.feeDescription || "").replace(/\n/g, "
") + + cityssm + .escapeHTML(fee.feeDescription || "") + .replace(/\n/g, "
") + "
"; panelBlockElement.addEventListener("click", tryAddFee); categoryContainerElement.querySelector(".panel").append(panelBlockElement); diff --git a/public-typescript/lotOccupancyEdit.ts b/public-typescript/lotOccupancyEdit.ts index b0c9dd3f..4b42c5c9 100644 --- a/public-typescript/lotOccupancyEdit.ts +++ b/public-typescript/lotOccupancyEdit.ts @@ -86,8 +86,64 @@ declare const bulmaJS: BulmaJS; } if (!isCreate) { + + const doCopy = () => { + cityssm.postJSON( + los.urlPrefix + "/lotOccupancies/doCopyLotOccupancy", + { + lotOccupancyId + }, + (responseJSON: { + success: boolean; + errorMessage?: string; + lotOccupancyId?: number; + }) => { + if (responseJSON.success) { + cityssm.disableNavBlocker(); + window.location.href = + los.urlPrefix + + "/lotOccupancies/" + + responseJSON.lotOccupancyId?.toString() + + "/edit"; + } else { + bulmaJS.alert({ + title: "Error Copying Record", + message: responseJSON.errorMessage || "", + contextualColorName: "danger" + }); + } + } + ); + }; + + (document.querySelector("#button--copyLotOccupancy") as HTMLAnchorElement).addEventListener( + "click", + (clickEvent) => { + clickEvent.preventDefault(); + + + if (hasUnsavedChanges) { + bulmaJS.alert({ + title: "Unsaved Changes", + message: "Please save all unsaved changes before continuing.", + contextualColorName: "warning" + }); + } else { + bulmaJS.confirm({ + title: "Copy " + exports.aliases.occupancy + " Record as New", + message: "Are you sure you want to copy this record to a new record?", + contextualColorName: "info", + okButton: { + text: "Yes, Copy", + callbackFunction: doCopy + } + }); + } + } + ); + ( - document.querySelector("#button--deleteLotOccupancy") as HTMLButtonElement + document.querySelector("#button--deleteLotOccupancy") as HTMLAnchorElement ).addEventListener("click", (clickEvent) => { clickEvent.preventDefault(); @@ -1717,7 +1773,9 @@ declare const bulmaJS: BulmaJS; cityssm.escapeHTML(fee.feeName || "") + "
" + "" + - cityssm.escapeHTML(fee.feeDescription || "").replace(/\n/g, "
") + + cityssm + .escapeHTML(fee.feeDescription || "") + .replace(/\n/g, "
") + "
"; panelBlockElement.addEventListener("click", tryAddFee); diff --git a/public/javascripts/lotOccupancyEdit.min.js b/public/javascripts/lotOccupancyEdit.min.js index 4cb510d6..2b638b47 100644 --- a/public/javascripts/lotOccupancyEdit.min.js +++ b/public/javascripts/lotOccupancyEdit.min.js @@ -1 +1 @@ -"use strict";Object.defineProperty(exports,"__esModule",{value:!0}),(()=>{const e=exports.los,t=document.querySelector("#lotOccupancy--lotOccupancyId").value,c=""===t;let a=!1,o=c;const n=()=>{a||(a=!0,cityssm.enableNavBlocker())},s=document.querySelector("#form--lotOccupancy");s.addEventListener("submit",t=>{t.preventDefault(),cityssm.postJSON(e.urlPrefix+"/lotOccupancies/"+(c?"doCreateLotOccupancy":"doUpdateLotOccupancy"),s,t=>{t.success?(a=!1,cityssm.disableNavBlocker(),c||o?window.location.href=e.urlPrefix+"/lotOccupancies/"+t.lotOccupancyId+"/edit?t="+Date.now():bulmaJS.alert({message:exports.aliases.occupancy+" Updated Successfully",contextualColorName:"success"})):bulmaJS.alert({title:"Error Saving "+exports.aliases.occupancy,message:t.errorMessage||"",contextualColorName:"danger"})})});const l=s.querySelectorAll("input, select");for(const e of l)e.addEventListener("change",n);c||document.querySelector("#button--deleteLotOccupancy").addEventListener("click",c=>{c.preventDefault();bulmaJS.confirm({title:"Delete "+exports.aliases.occupancy+" Record",message:"Are you sure you want to delete this record?",contextualColorName:"warning",okButton:{text:"Yes, Delete",callbackFunction:()=>{cityssm.postJSON(e.urlPrefix+"/lotOccupancies/doDeleteLotOccupancy",{lotOccupancyId:t},t=>{t.success?(cityssm.disableNavBlocker(),window.location.href=e.urlPrefix+"/lotOccupancies?t="+Date.now()):bulmaJS.alert({title:"Error Deleting Record",message:t.errorMessage||"",contextualColorName:"danger"})})}}})});const r=document.querySelector("#lotOccupancy--occupancyTypeId");if(c){const t=document.querySelector("#container--lotOccupancyFields");r.addEventListener("change",()=>{""!==r.value?cityssm.postJSON(e.urlPrefix+"/lotOccupancies/doGetOccupancyTypeFields",{occupancyTypeId:r.value},e=>{if(0===e.occupancyTypeFields.length)return void(t.innerHTML='

There are no additional fields for this '+exports.aliases.occupancy.toLowerCase()+" type.

");t.innerHTML="";let c="";for(const a of e.occupancyTypeFields){c+=","+a.occupancyTypeFieldId;const e="lotOccupancyFieldValue_"+a.occupancyTypeFieldId,o="lotOccupancy--"+e,n=document.createElement("div");if(n.className="field",n.innerHTML='
',n.querySelector("label").textContent=a.occupancyTypeField,""===a.occupancyTypeFieldValues){const t=document.createElement("input");t.className="input",t.id=o,t.name=e,t.type="text",t.required=a.isRequired,t.minLength=a.minimumLength,t.maxLength=a.maximumLength,a.pattern&&""!==a.pattern&&(t.pattern=a.pattern),n.querySelector(".control").append(t)}else{n.querySelector(".control").innerHTML='
';const t=n.querySelector("select");t.required=a.isRequired;const c=a.occupancyTypeFieldValues.split("\n");for(const e of c){const c=document.createElement("option");c.value=e,c.textContent=e,t.append(c)}}t.append(n)}t.insertAdjacentHTML("beforeend",'')}):t.innerHTML='

Select the '+exports.aliases.occupancy.toLowerCase()+" type to load the available fields.

"})}else{const e=r.value;r.addEventListener("change",()=>{r.value!==e&&bulmaJS.confirm({title:"Confirm Change",message:"Are you sure you want to change the "+exports.aliases.occupancy.toLowerCase()+" type?\nThis change affects the additional fields associated with this record, and may also affect the available fees.",contextualColorName:"warning",okButton:{text:"Yes, Keep the Change",callbackFunction:()=>{o=!0}},cancelButton:{text:"Revert the Change",callbackFunction:()=>{r.value=e}}})})}const i=document.querySelector("#lotOccupancy--lotName");if(i.addEventListener("click",t=>{const c=t.currentTarget.value;let a,o,s,l;const r=(e,t)=>{document.querySelector("#lotOccupancy--lotId").value=e.toString(),document.querySelector("#lotOccupancy--lotName").value=t,n(),a()},i=e=>{e.preventDefault();const t=e.currentTarget;r(t.dataset.lotId,t.dataset.lotName)},u=()=>{l.innerHTML='


Searching...

',cityssm.postJSON(e.urlPrefix+"/lots/doSearchLots",s,e=>{if(0===e.count)return void(l.innerHTML='

No results.

');const t=document.createElement("div");t.className="panel";for(const c of e.lots){const e=document.createElement("a");e.className="panel-block is-block",e.href="#",e.dataset.lotId=c.lotId.toString(),e.dataset.lotName=c.lotName,e.innerHTML='
'+cityssm.escapeHTML(c.lotName||"")+'
'+cityssm.escapeHTML(c.mapName||"")+'
'+cityssm.escapeHTML(c.lotStatus)+'
'+(c.lotOccupancyCount>0?"Currently Occupied":"")+"
",e.addEventListener("click",i),t.append(e)}l.innerHTML="",l.append(t)})},d=t=>{t.preventDefault();const c=o.querySelector("#lotCreate--lotName").value;cityssm.postJSON(e.urlPrefix+"/lots/doCreateLot",t.currentTarget,e=>{e.success?r(e.lotId,c):bulmaJS.alert({title:"Error Creating "+exports.aliases.lot,message:e.errorMessage||"",contextualColorName:"danger"})})};cityssm.openHtmlModal("lotOccupancy-selectLot",{onshow:t=>{e.populateAliases(t)},onshown:(e,t)=>{bulmaJS.toggleHtmlClipped(),o=e,a=t,bulmaJS.init(e);const n=e.querySelector("#lotSelect--lotName");""!==document.querySelector("#lotOccupancy--lotId").value&&(n.value=c),n.focus(),n.addEventListener("change",u);const r=e.querySelector("#lotSelect--occupancyStatus");if(r.addEventListener("change",u),""!==c&&(r.value=""),s=e.querySelector("#form--lotSelect"),l=e.querySelector("#resultsContainer--lotSelect"),s.addEventListener("submit",e=>{e.preventDefault()}),u(),exports.lotNamePattern){const t=exports.lotNamePattern;e.querySelector("#lotCreate--lotName").pattern=t.source}const i=e.querySelector("#lotCreate--lotTypeId");for(const e of exports.lotTypes){const t=document.createElement("option");t.value=e.lotTypeId.toString(),t.textContent=e.lotType,i.append(t)}const p=e.querySelector("#lotCreate--lotStatusId");for(const e of exports.lotStatuses){const t=document.createElement("option");t.value=e.lotStatusId.toString(),t.textContent=e.lotStatus,p.append(t)}const m=e.querySelector("#lotCreate--mapId");for(const e of exports.maps){const t=document.createElement("option");t.value=e.mapId.toString(),t.textContent=e.mapName||"(No Name)",m.append(t)}e.querySelector("#form--lotCreate").addEventListener("submit",d)},onremoved:()=>{bulmaJS.toggleHtmlClipped()}})}),document.querySelector(".is-lot-view-button").addEventListener("click",()=>{const t=document.querySelector("#lotOccupancy--lotId").value;t?window.open(e.urlPrefix+"/lots/"+t):bulmaJS.alert({message:"No "+exports.aliases.lot.toLowerCase()+" selected.",contextualColorName:"info"})}),document.querySelector(".is-clear-lot-button").addEventListener("click",()=>{i.disabled?bulmaJS.alert({message:"You need to unlock the field before clearing it.",contextualColorName:"info"}):(i.value="(No "+exports.aliases.lot+")",document.querySelector("#lotOccupancy--lotId").value="",n())}),e.initializeDatePickers(s),document.querySelector("#lotOccupancy--occupancyStartDateString").addEventListener("change",()=>{const e=document.querySelector("#lotOccupancy--occupancyEndDateString").bulmaCalendar.datePicker;e.min=document.querySelector("#lotOccupancy--occupancyStartDateString").value,e.refresh()}),e.initializeUnlockFieldButtons(s),!c){let c=exports.lotOccupancyOccupants;delete exports.lotOccupancyOccupants;const a=a=>{const o=Number.parseInt(a.currentTarget.closest("tr").dataset.lotOccupantIndex,10),s=c.find(e=>e.lotOccupantIndex===o);let l,r;const i=t=>{t.preventDefault(),cityssm.postJSON(e.urlPrefix+"/lotOccupancies/doUpdateLotOccupancyOccupant",l,e=>{e.success?(c=e.lotOccupancyOccupants,r(),n()):bulmaJS.alert({title:"Error Updating "+exports.aliases.occupant,message:e.errorMessage||"",contextualColorName:"danger"})})};cityssm.openHtmlModal("lotOccupancy-editOccupant",{onshow:c=>{e.populateAliases(c),c.querySelector("#lotOccupancyOccupantEdit--lotOccupancyId").value=t,c.querySelector("#lotOccupancyOccupantEdit--lotOccupantIndex").value=o.toString();const a=c.querySelector("#lotOccupancyOccupantEdit--lotOccupantTypeId");let n=!1;for(const e of exports.lotOccupantTypes){const t=document.createElement("option");t.value=e.lotOccupantTypeId.toString(),t.textContent=e.lotOccupantType,e.lotOccupantTypeId===s.lotOccupantTypeId&&(t.selected=!0,n=!0),a.append(t)}if(!n){const e=document.createElement("option");e.value=s.lotOccupantTypeId.toString(),e.textContent=s.lotOccupantType,e.selected=!0,a.append(e)}c.querySelector("#lotOccupancyOccupantEdit--occupantName").value=s.occupantName,c.querySelector("#lotOccupancyOccupantEdit--occupantAddress1").value=s.occupantAddress1,c.querySelector("#lotOccupancyOccupantEdit--occupantAddress2").value=s.occupantAddress2,c.querySelector("#lotOccupancyOccupantEdit--occupantCity").value=s.occupantCity,c.querySelector("#lotOccupancyOccupantEdit--occupantProvince").value=s.occupantProvince,c.querySelector("#lotOccupancyOccupantEdit--occupantPostalCode").value=s.occupantPostalCode,c.querySelector("#lotOccupancyOccupantEdit--occupantPhoneNumber").value=s.occupantPhoneNumber,c.querySelector("#lotOccupancyOccupantEdit--occupantEmailAddress").value=s.occupantEmailAddress},onshown:(e,t)=>{bulmaJS.toggleHtmlClipped(),e.querySelector("#lotOccupancyOccupantEdit--lotOccupantTypeId").focus(),(l=e.querySelector("form")).addEventListener("submit",i),r=t},onremoved:()=>{bulmaJS.toggleHtmlClipped()}})},o=a=>{const o=a.currentTarget.closest("tr").dataset.lotOccupantIndex;bulmaJS.confirm({title:"Remove "+exports.aliases.occupant+"?",message:"Are you sure you want to remove this "+exports.aliases.occupant.toLowerCase()+"?",okButton:{text:"Yes, Remove "+exports.aliases.occupant,callbackFunction:()=>{cityssm.postJSON(e.urlPrefix+"/lotOccupancies/doDeleteLotOccupancyOccupant",{lotOccupancyId:t,lotOccupantIndex:o},e=>{e.success?(c=e.lotOccupancyOccupants,n()):bulmaJS.alert({title:"Error Removing "+exports.aliases.occupant,message:e.errorMessage||"",contextualColorName:"danger"})})}},contextualColorName:"warning"})},n=()=>{const e=document.querySelector("#container--lotOccupancyOccupants");if(cityssm.clearElement(e),0===c.length)return void(e.innerHTML='

There are no '+exports.aliases.occupants.toLowerCase()+" associated with this record.

");const t=document.createElement("table");t.className="table is-fullwidth is-striped is-hoverable",t.innerHTML=""+exports.aliases.occupant+" Type"+exports.aliases.occupant+'AddressOther ContactOptions';for(const e of c){const c=document.createElement("tr");c.dataset.lotOccupantIndex=e.lotOccupantIndex.toString(),c.innerHTML=""+cityssm.escapeHTML(e.lotOccupantType)+""+cityssm.escapeHTML(e.occupantName||"")+""+(e.occupantAddress1?cityssm.escapeHTML(e.occupantAddress1)+"
":"")+(e.occupantAddress2?cityssm.escapeHTML(e.occupantAddress2)+"
":"")+(e.occupantCity?cityssm.escapeHTML(e.occupantCity)+", ":"")+cityssm.escapeHTML(e.occupantProvince||"")+"
"+cityssm.escapeHTML(e.occupantPostalCode||"")+""+(e.occupantPhoneNumber?cityssm.escapeHTML(e.occupantPhoneNumber)+"
":"")+(e.occupantEmailAddress?cityssm.escapeHTML(e.occupantEmailAddress):"")+'
',c.querySelector(".button--edit").addEventListener("click",a),c.querySelector(".button--delete").addEventListener("click",o),t.querySelector("tbody").append(c)}e.append(t)};document.querySelector("#button--addOccupant").addEventListener("click",()=>{let a,o,s,l;const r=t=>{cityssm.postJSON(e.urlPrefix+"/lotOccupancies/doAddLotOccupancyOccupant",t,e=>{e.success?(c=e.lotOccupancyOccupants,a(),n()):bulmaJS.alert({title:"Error Adding "+exports.aliases.occupant,message:e.errorMessage||"",contextualColorName:"danger"})})},i=e=>{e.preventDefault(),r(o)};let u=[];const d=e=>{e.preventDefault();const c=e.currentTarget,a=u[Number.parseInt(c.dataset.index,10)],o=c.closest(".modal").querySelector("#lotOccupancyOccupantCopy--lotOccupantTypeId").value;""===o?bulmaJS.alert({title:"No "+exports.aliases.occupant+" Type Selected",message:"Select a type to apply to the newly added "+exports.aliases.occupant.toLowerCase()+".",contextualColorName:"warning"}):(a.lotOccupantTypeId=Number.parseInt(o,10),a.lotOccupancyId=Number.parseInt(t,10),r(a))},p=t=>{t.preventDefault(),""!==s.querySelector("#lotOccupancyOccupantCopy--searchFilter").value?(l.innerHTML='

Searching...
',cityssm.postJSON(e.urlPrefix+"/lotOccupancies/doSearchPastOccupants",s,e=>{u=e.occupants;const t=document.createElement("div");t.className="panel";for(const[e,c]of u.entries()){const a=document.createElement("a");a.className="panel-block is-block",a.dataset.index=e.toString(),a.innerHTML=""+cityssm.escapeHTML(c.occupantName||"")+'
'+cityssm.escapeHTML(c.occupantAddress1||"")+"
"+(c.occupantAddress2?cityssm.escapeHTML(c.occupantAddress2)+"
":"")+cityssm.escapeHTML(c.occupantCity||"")+", "+cityssm.escapeHTML(c.occupantProvince||"")+"
"+cityssm.escapeHTML(c.occupantPostalCode||"")+'
'+(c.occupantPhoneNumber?cityssm.escapeHTML(c.occupantPhoneNumber)+"
":"")+cityssm.escapeHTML(c.occupantEmailAddress||"")+"
",a.addEventListener("click",d),t.append(a)}l.innerHTML="",l.append(t)})):l.innerHTML='

Enter a partial name or address in the search field above.

'};cityssm.openHtmlModal("lotOccupancy-addOccupant",{onshow:c=>{e.populateAliases(c),c.querySelector("#lotOccupancyOccupantAdd--lotOccupancyId").value=t;const a=c.querySelector("#lotOccupancyOccupantAdd--lotOccupantTypeId"),o=c.querySelector("#lotOccupancyOccupantCopy--lotOccupantTypeId");for(const e of exports.lotOccupantTypes){const t=document.createElement("option");t.value=e.lotOccupantTypeId.toString(),t.textContent=e.lotOccupantType,a.append(t),o.append(t.cloneNode(!0))}c.querySelector("#lotOccupancyOccupantAdd--occupantCity").value=exports.occupantCityDefault,c.querySelector("#lotOccupancyOccupantAdd--occupantProvince").value=exports.occupantProvinceDefault},onshown:(e,t)=>{bulmaJS.toggleHtmlClipped(),bulmaJS.init(e),e.querySelector("#lotOccupancyOccupantAdd--lotOccupantTypeId").focus(),(o=e.querySelector("#form--lotOccupancyOccupantAdd")).addEventListener("submit",i),l=e.querySelector("#lotOccupancyOccupantCopy--searchResults"),(s=e.querySelector("#form--lotOccupancyOccupantCopy")).addEventListener("submit",e=>{e.preventDefault()}),e.querySelector("#lotOccupancyOccupantCopy--searchFilter").addEventListener("change",p),a=t},onremoved:()=>{bulmaJS.toggleHtmlClipped()}})}),n()}if(!c){let c=exports.lotOccupancyComments;delete exports.lotOccupancyComments;const a=a=>{const o=Number.parseInt(a.currentTarget.closest("tr").dataset.lotOccupancyCommentId,10),s=c.find(e=>e.lotOccupancyCommentId===o);let l,r;const i=t=>{t.preventDefault(),cityssm.postJSON(e.urlPrefix+"/lotOccupancies/doUpdateLotOccupancyComment",l,e=>{e.success?(c=e.lotOccupancyComments,r(),n()):bulmaJS.alert({title:"Error Updating Comment",message:e.errorMessage||"",contextualColorName:"danger"})})};cityssm.openHtmlModal("lotOccupancy-editComment",{onshow:c=>{e.populateAliases(c),c.querySelector("#lotOccupancyCommentEdit--lotOccupancyId").value=t,c.querySelector("#lotOccupancyCommentEdit--lotOccupancyCommentId").value=o.toString(),c.querySelector("#lotOccupancyCommentEdit--lotOccupancyComment").value=s.lotOccupancyComment;const a=c.querySelector("#lotOccupancyCommentEdit--lotOccupancyCommentDateString");a.value=s.lotOccupancyCommentDateString;const n=cityssm.dateToString(new Date);a.max=s.lotOccupancyCommentDateString<=n?n:s.lotOccupancyCommentDateString,c.querySelector("#lotOccupancyCommentEdit--lotOccupancyCommentTimeString").value=s.lotOccupancyCommentTimeString},onshown:(t,c)=>{bulmaJS.toggleHtmlClipped(),e.initializeDatePickers(t),e.initializeTimePickers(t),t.querySelector("#lotOccupancyCommentEdit--lotOccupancyComment").focus(),(l=t.querySelector("form")).addEventListener("submit",i),r=c},onremoved:()=>{bulmaJS.toggleHtmlClipped()}})},o=a=>{const o=Number.parseInt(a.currentTarget.closest("tr").dataset.lotOccupancyCommentId,10);bulmaJS.confirm({title:"Remove Comment?",message:"Are you sure you want to remove this comment?",okButton:{text:"Yes, Remove Comment",callbackFunction:()=>{cityssm.postJSON(e.urlPrefix+"/lotOccupancies/doDeleteLotOccupancyComment",{lotOccupancyId:t,lotOccupancyCommentId:o},e=>{e.success?(c=e.lotOccupancyComments,n()):bulmaJS.alert({title:"Error Removing Comment",message:e.errorMessage||"",contextualColorName:"danger"})})}},contextualColorName:"warning"})},n=()=>{const e=document.querySelector("#container--lotOccupancyComments");if(0===c.length)return void(e.innerHTML='

There are no comments associated with this record.

');const t=document.createElement("table");t.className="table is-fullwidth is-striped is-hoverable",t.innerHTML='CommentorComment DateCommentOptions';for(const e of c){const c=document.createElement("tr");c.dataset.lotOccupancyCommentId=e.lotOccupancyCommentId.toString(),c.innerHTML=""+cityssm.escapeHTML(e.recordCreate_userName||"")+""+e.lotOccupancyCommentDateString+(0===e.lotOccupancyCommentTime?"":" "+e.lotOccupancyCommentTimeString)+""+cityssm.escapeHTML(e.lotOccupancyComment||"")+'
',c.querySelector(".button--edit").addEventListener("click",a),c.querySelector(".button--delete").addEventListener("click",o),t.querySelector("tbody").append(c)}e.innerHTML="",e.append(t)};document.querySelector("#button--addComment").addEventListener("click",()=>{let a,o;const s=t=>{t.preventDefault(),cityssm.postJSON(e.urlPrefix+"/lotOccupancies/doAddLotOccupancyComment",a,e=>{e.success?(c=e.lotOccupancyComments,o(),n()):bulmaJS.alert({title:"Error Adding Comment",message:e.errorMessage||"",contextualColorName:"danger"})})};cityssm.openHtmlModal("lotOccupancy-addComment",{onshow:c=>{e.populateAliases(c),c.querySelector("#lotOccupancyCommentAdd--lotOccupancyId").value=t},onshown:(e,t)=>{bulmaJS.toggleHtmlClipped(),e.querySelector("#lotOccupancyCommentAdd--lotOccupancyComment").focus(),(a=e.querySelector("form")).addEventListener("submit",s),o=t},onremoved:()=>{bulmaJS.toggleHtmlClipped()}})}),n()}if(!c){let c=exports.lotOccupancyFees;delete exports.lotOccupancyFees;const o=document.querySelector("#container--lotOccupancyFees"),n=()=>{let e=0;for(const t of c)e+=(t.feeAmount+t.taxAmount)*t.quantity;return e},s=a=>{const o=a.currentTarget.closest(".container--lotOccupancyFee").dataset.feeId;bulmaJS.confirm({title:"Delete Fee",message:"Are you sure you want to delete this fee?",contextualColorName:"warning",okButton:{text:"Yes, Delete Fee",callbackFunction:()=>{cityssm.postJSON(e.urlPrefix+"/lotOccupancies/doDeleteLotOccupancyFee",{lotOccupancyId:t,feeId:o},e=>{e.success?(c=e.lotOccupancyFees,l()):bulmaJS.alert({title:"Error Deleting Fee",message:e.errorMessage||"",contextualColorName:"danger"})})}}})},l=()=>{if(0===c.length)return o.innerHTML='

There are no fees associated with this record.

',void p();o.innerHTML='
FeeUnit Cost×QuantityequalsTotalOptions
Subtotal
Tax
Grand Total
';let e=0,t=0;for(const a of c){const c=document.createElement("tr");c.className="container--lotOccupancyFee",c.dataset.feeId=a.feeId.toString(),c.dataset.includeQuantity=a.includeQuantity?"1":"0",c.innerHTML=''+cityssm.escapeHTML(a.feeName||"")+""+(1===a.quantity?"":'$'+a.feeAmount.toFixed(2)+'×'+a.quantity+"=")+'$'+(a.feeAmount*a.quantity).toFixed(2)+'',c.querySelector("button").addEventListener("click",s),o.querySelector("tbody").append(c),e+=a.feeAmount*a.quantity,t+=a.taxAmount*a.quantity}o.querySelector("#lotOccupancyFees--feeAmountTotal").textContent="$"+e.toFixed(2),o.querySelector("#lotOccupancyFees--taxAmountTotal").textContent="$"+t.toFixed(2),o.querySelector("#lotOccupancyFees--grandTotal").textContent="$"+(e+t).toFixed(2),p()};document.querySelector("#button--addFee").addEventListener("click",()=>{if(a)return void bulmaJS.alert({message:"Please save all unsaved changes before adding fees.",contextualColorName:"warning"});let n,s,r;const i=(a,o=1)=>{cityssm.postJSON(e.urlPrefix+"/lotOccupancies/doAddLotOccupancyFee",{lotOccupancyId:t,feeId:a,quantity:o},e=>{e.success?(c=e.lotOccupancyFees,l(),d()):bulmaJS.alert({title:"Error Adding Fee",message:e.errorMessage||"",contextualColorName:"danger"})})},u=e=>{e.preventDefault();const t=Number.parseInt(e.currentTarget.dataset.feeId,10),c=Number.parseInt(e.currentTarget.closest(".container--feeCategory").dataset.feeCategoryId,10),a=n.find(e=>e.feeCategoryId===c).fees.find(e=>e.feeId===t);a.includeQuantity?(e=>{let t,c;const a=a=>{a.preventDefault(),i(e.feeId,t.value),c()};cityssm.openHtmlModal("lotOccupancy-setFeeQuantity",{onshow:t=>{t.querySelector("#lotOccupancyFeeQuantity--quantityUnit").textContent=e.quantityUnit},onshown:(e,o)=>{c=o,t=e.querySelector("#lotOccupancyFeeQuantity--quantity"),e.querySelector("form").addEventListener("submit",a)}})})(a):i(t)},d=()=>{const e=s.value.trim().toLowerCase().split(" ");r.innerHTML="";for(const t of n){const c=document.createElement("div");c.className="container--feeCategory",c.dataset.feeCategoryId=t.feeCategoryId.toString(),c.innerHTML='

'+cityssm.escapeHTML(t.feeCategory||"")+'

';let a=!1;for(const n of t.fees){if(o.querySelector(".container--lotOccupancyFee[data-fee-id='"+n.feeId+"'][data-include-quantity='0']"))continue;let t=!0;for(const c of e)if(!n.feeName.toLowerCase().includes(c)){t=!1;break}if(!t)continue;a=!0;const s=document.createElement("a");s.className="panel-block is-block container--fee",s.dataset.feeId=n.feeId.toString(),s.href="#",s.innerHTML=""+cityssm.escapeHTML(n.feeName||"")+"
"+cityssm.escapeHTML(n.feeDescription||"").replace(/\n/g,"
")+"
",s.addEventListener("click",u),c.querySelector(".panel").append(s)}a&&r.append(c)}};cityssm.openHtmlModal("lotOccupancy-addFee",{onshow:c=>{s=c.querySelector("#feeSelect--feeName"),r=c.querySelector("#resultsContainer--feeSelect"),cityssm.postJSON(e.urlPrefix+"/lotOccupancies/doGetFees",{lotOccupancyId:t},e=>{n=e.feeCategories,s.disabled=!1,s.addEventListener("keyup",d),s.focus(),d()})},onshown:()=>{bulmaJS.toggleHtmlClipped()},onhidden:()=>{l()},onremoved:()=>{bulmaJS.toggleHtmlClipped()}})});let r=exports.lotOccupancyTransactions;delete exports.lotOccupancyTransactions;const i=document.querySelector("#container--lotOccupancyTransactions"),u=()=>{let e=0;for(const t of r)e+=t.transactionAmount;return e},d=c=>{const a=c.currentTarget.closest(".container--lotOccupancyTransaction").dataset.transactionIndex;bulmaJS.confirm({title:"Delete Trasnaction",message:"Are you sure you want to delete this transaction?",contextualColorName:"warning",okButton:{text:"Yes, Delete Transaction",callbackFunction:()=>{cityssm.postJSON(e.urlPrefix+"/lotOccupancies/doDeleteLotOccupancyTransaction",{lotOccupancyId:t,transactionIndex:a},e=>{e.success?(r=e.lotOccupancyTransactions,p()):bulmaJS.alert({title:"Error Deleting Transaction",message:e.errorMessage||"",contextualColorName:"danger"})})}}})},p=()=>{if(0===r.length)return void(i.innerHTML='

There are no transactions associated with this record.

');i.innerHTML='
Date'+cityssm.escapeHTML(exports.aliases.externalReceiptNumber)+'AmountOptions
Transaction Total
';let e=0;for(const t of r){e+=t.transactionAmount;const c=document.createElement("tr");c.className="container--lotOccupancyTransaction",c.dataset.transactionIndex=t.transactionIndex.toString(),c.innerHTML=""+t.transactionDateString+""+cityssm.escapeHTML(t.externalReceiptNumber||"")+"
"+cityssm.escapeHTML(t.transactionNote||"")+'$'+t.transactionAmount.toFixed(2)+'',c.querySelector("button").addEventListener("click",d),i.querySelector("tbody").append(c)}i.querySelector("#lotOccupancyTransactions--grandTotal").textContent="$"+e.toFixed(2);const t=n();t>e&&i.insertAdjacentHTML("afterbegin",'
Outstanding Balance
$'+(t-e).toFixed(2)+"
")};document.querySelector("#button--addTransaction").addEventListener("click",()=>{let c;const a=t=>{t.preventDefault(),cityssm.postJSON(e.urlPrefix+"/lotOccupancies/doAddLotOccupancyTransaction",t.currentTarget,e=>{e.success?(r=e.lotOccupancyTransactions,c(),p()):bulmaJS.confirm({title:"Error Adding Transaction",message:e.errorMessage||"",contextualColorName:"danger"})})};cityssm.openHtmlModal("lotOccupancy-addTransaction",{onshow:c=>{e.populateAliases(c),c.querySelector("#lotOccupancyTransactionAdd--lotOccupancyId").value=t.toString();const a=n(),o=u(),s=c.querySelector("#lotOccupancyTransactionAdd--transactionAmount");s.min=(-1*o).toFixed(2),s.max=Math.max(a-o,0).toFixed(2),s.value=Math.max(a-o,0).toFixed(2)},onshown:(e,t)=>{bulmaJS.toggleHtmlClipped(),c=t,e.querySelector("form").addEventListener("submit",a)},onremoved:()=>{bulmaJS.toggleHtmlClipped()}})}),l()}})(); \ No newline at end of file +"use strict";Object.defineProperty(exports,"__esModule",{value:!0}),(()=>{const e=exports.los,t=document.querySelector("#lotOccupancy--lotOccupancyId").value,c=""===t;let a=!1,o=c;const n=()=>{a||(a=!0,cityssm.enableNavBlocker())},s=document.querySelector("#form--lotOccupancy");s.addEventListener("submit",t=>{t.preventDefault(),cityssm.postJSON(e.urlPrefix+"/lotOccupancies/"+(c?"doCreateLotOccupancy":"doUpdateLotOccupancy"),s,t=>{t.success?(a=!1,cityssm.disableNavBlocker(),c||o?window.location.href=e.urlPrefix+"/lotOccupancies/"+t.lotOccupancyId+"/edit?t="+Date.now():bulmaJS.alert({message:exports.aliases.occupancy+" Updated Successfully",contextualColorName:"success"})):bulmaJS.alert({title:"Error Saving "+exports.aliases.occupancy,message:t.errorMessage||"",contextualColorName:"danger"})})});const l=s.querySelectorAll("input, select");for(const e of l)e.addEventListener("change",n);if(!c){const c=()=>{cityssm.postJSON(e.urlPrefix+"/lotOccupancies/doCopyLotOccupancy",{lotOccupancyId:t},t=>{var c;t.success?(cityssm.disableNavBlocker(),window.location.href=e.urlPrefix+"/lotOccupancies/"+(null===(c=t.lotOccupancyId)||void 0===c?void 0:c.toString())+"/edit"):bulmaJS.alert({title:"Error Copying Record",message:t.errorMessage||"",contextualColorName:"danger"})})};document.querySelector("#button--copyLotOccupancy").addEventListener("click",e=>{e.preventDefault(),a?bulmaJS.alert({title:"Unsaved Changes",message:"Please save all unsaved changes before continuing.",contextualColorName:"warning"}):bulmaJS.confirm({title:"Copy "+exports.aliases.occupancy+" Record as New",message:"Are you sure you want to copy this record to a new record?",contextualColorName:"info",okButton:{text:"Yes, Copy",callbackFunction:c}})}),document.querySelector("#button--deleteLotOccupancy").addEventListener("click",c=>{c.preventDefault();bulmaJS.confirm({title:"Delete "+exports.aliases.occupancy+" Record",message:"Are you sure you want to delete this record?",contextualColorName:"warning",okButton:{text:"Yes, Delete",callbackFunction:()=>{cityssm.postJSON(e.urlPrefix+"/lotOccupancies/doDeleteLotOccupancy",{lotOccupancyId:t},t=>{t.success?(cityssm.disableNavBlocker(),window.location.href=e.urlPrefix+"/lotOccupancies?t="+Date.now()):bulmaJS.alert({title:"Error Deleting Record",message:t.errorMessage||"",contextualColorName:"danger"})})}}})})}const r=document.querySelector("#lotOccupancy--occupancyTypeId");if(c){const t=document.querySelector("#container--lotOccupancyFields");r.addEventListener("change",()=>{""!==r.value?cityssm.postJSON(e.urlPrefix+"/lotOccupancies/doGetOccupancyTypeFields",{occupancyTypeId:r.value},e=>{if(0===e.occupancyTypeFields.length)return void(t.innerHTML='

There are no additional fields for this '+exports.aliases.occupancy.toLowerCase()+" type.

");t.innerHTML="";let c="";for(const a of e.occupancyTypeFields){c+=","+a.occupancyTypeFieldId;const e="lotOccupancyFieldValue_"+a.occupancyTypeFieldId,o="lotOccupancy--"+e,n=document.createElement("div");if(n.className="field",n.innerHTML='
',n.querySelector("label").textContent=a.occupancyTypeField,""===a.occupancyTypeFieldValues){const t=document.createElement("input");t.className="input",t.id=o,t.name=e,t.type="text",t.required=a.isRequired,t.minLength=a.minimumLength,t.maxLength=a.maximumLength,a.pattern&&""!==a.pattern&&(t.pattern=a.pattern),n.querySelector(".control").append(t)}else{n.querySelector(".control").innerHTML='
';const t=n.querySelector("select");t.required=a.isRequired;const c=a.occupancyTypeFieldValues.split("\n");for(const e of c){const c=document.createElement("option");c.value=e,c.textContent=e,t.append(c)}}t.append(n)}t.insertAdjacentHTML("beforeend",'')}):t.innerHTML='

Select the '+exports.aliases.occupancy.toLowerCase()+" type to load the available fields.

"})}else{const e=r.value;r.addEventListener("change",()=>{r.value!==e&&bulmaJS.confirm({title:"Confirm Change",message:"Are you sure you want to change the "+exports.aliases.occupancy.toLowerCase()+" type?\nThis change affects the additional fields associated with this record, and may also affect the available fees.",contextualColorName:"warning",okButton:{text:"Yes, Keep the Change",callbackFunction:()=>{o=!0}},cancelButton:{text:"Revert the Change",callbackFunction:()=>{r.value=e}}})})}const i=document.querySelector("#lotOccupancy--lotName");if(i.addEventListener("click",t=>{const c=t.currentTarget.value;let a,o,s,l;const r=(e,t)=>{document.querySelector("#lotOccupancy--lotId").value=e.toString(),document.querySelector("#lotOccupancy--lotName").value=t,n(),a()},i=e=>{e.preventDefault();const t=e.currentTarget;r(t.dataset.lotId,t.dataset.lotName)},u=()=>{l.innerHTML='


Searching...

',cityssm.postJSON(e.urlPrefix+"/lots/doSearchLots",s,e=>{if(0===e.count)return void(l.innerHTML='

No results.

');const t=document.createElement("div");t.className="panel";for(const c of e.lots){const e=document.createElement("a");e.className="panel-block is-block",e.href="#",e.dataset.lotId=c.lotId.toString(),e.dataset.lotName=c.lotName,e.innerHTML='
'+cityssm.escapeHTML(c.lotName||"")+'
'+cityssm.escapeHTML(c.mapName||"")+'
'+cityssm.escapeHTML(c.lotStatus)+'
'+(c.lotOccupancyCount>0?"Currently Occupied":"")+"
",e.addEventListener("click",i),t.append(e)}l.innerHTML="",l.append(t)})},d=t=>{t.preventDefault();const c=o.querySelector("#lotCreate--lotName").value;cityssm.postJSON(e.urlPrefix+"/lots/doCreateLot",t.currentTarget,e=>{e.success?r(e.lotId,c):bulmaJS.alert({title:"Error Creating "+exports.aliases.lot,message:e.errorMessage||"",contextualColorName:"danger"})})};cityssm.openHtmlModal("lotOccupancy-selectLot",{onshow:t=>{e.populateAliases(t)},onshown:(e,t)=>{bulmaJS.toggleHtmlClipped(),o=e,a=t,bulmaJS.init(e);const n=e.querySelector("#lotSelect--lotName");""!==document.querySelector("#lotOccupancy--lotId").value&&(n.value=c),n.focus(),n.addEventListener("change",u);const r=e.querySelector("#lotSelect--occupancyStatus");if(r.addEventListener("change",u),""!==c&&(r.value=""),s=e.querySelector("#form--lotSelect"),l=e.querySelector("#resultsContainer--lotSelect"),s.addEventListener("submit",e=>{e.preventDefault()}),u(),exports.lotNamePattern){const t=exports.lotNamePattern;e.querySelector("#lotCreate--lotName").pattern=t.source}const i=e.querySelector("#lotCreate--lotTypeId");for(const e of exports.lotTypes){const t=document.createElement("option");t.value=e.lotTypeId.toString(),t.textContent=e.lotType,i.append(t)}const p=e.querySelector("#lotCreate--lotStatusId");for(const e of exports.lotStatuses){const t=document.createElement("option");t.value=e.lotStatusId.toString(),t.textContent=e.lotStatus,p.append(t)}const m=e.querySelector("#lotCreate--mapId");for(const e of exports.maps){const t=document.createElement("option");t.value=e.mapId.toString(),t.textContent=e.mapName||"(No Name)",m.append(t)}e.querySelector("#form--lotCreate").addEventListener("submit",d)},onremoved:()=>{bulmaJS.toggleHtmlClipped()}})}),document.querySelector(".is-lot-view-button").addEventListener("click",()=>{const t=document.querySelector("#lotOccupancy--lotId").value;t?window.open(e.urlPrefix+"/lots/"+t):bulmaJS.alert({message:"No "+exports.aliases.lot.toLowerCase()+" selected.",contextualColorName:"info"})}),document.querySelector(".is-clear-lot-button").addEventListener("click",()=>{i.disabled?bulmaJS.alert({message:"You need to unlock the field before clearing it.",contextualColorName:"info"}):(i.value="(No "+exports.aliases.lot+")",document.querySelector("#lotOccupancy--lotId").value="",n())}),e.initializeDatePickers(s),document.querySelector("#lotOccupancy--occupancyStartDateString").addEventListener("change",()=>{const e=document.querySelector("#lotOccupancy--occupancyEndDateString").bulmaCalendar.datePicker;e.min=document.querySelector("#lotOccupancy--occupancyStartDateString").value,e.refresh()}),e.initializeUnlockFieldButtons(s),!c){let c=exports.lotOccupancyOccupants;delete exports.lotOccupancyOccupants;const a=a=>{const o=Number.parseInt(a.currentTarget.closest("tr").dataset.lotOccupantIndex,10),s=c.find(e=>e.lotOccupantIndex===o);let l,r;const i=t=>{t.preventDefault(),cityssm.postJSON(e.urlPrefix+"/lotOccupancies/doUpdateLotOccupancyOccupant",l,e=>{e.success?(c=e.lotOccupancyOccupants,r(),n()):bulmaJS.alert({title:"Error Updating "+exports.aliases.occupant,message:e.errorMessage||"",contextualColorName:"danger"})})};cityssm.openHtmlModal("lotOccupancy-editOccupant",{onshow:c=>{e.populateAliases(c),c.querySelector("#lotOccupancyOccupantEdit--lotOccupancyId").value=t,c.querySelector("#lotOccupancyOccupantEdit--lotOccupantIndex").value=o.toString();const a=c.querySelector("#lotOccupancyOccupantEdit--lotOccupantTypeId");let n=!1;for(const e of exports.lotOccupantTypes){const t=document.createElement("option");t.value=e.lotOccupantTypeId.toString(),t.textContent=e.lotOccupantType,e.lotOccupantTypeId===s.lotOccupantTypeId&&(t.selected=!0,n=!0),a.append(t)}if(!n){const e=document.createElement("option");e.value=s.lotOccupantTypeId.toString(),e.textContent=s.lotOccupantType,e.selected=!0,a.append(e)}c.querySelector("#lotOccupancyOccupantEdit--occupantName").value=s.occupantName,c.querySelector("#lotOccupancyOccupantEdit--occupantAddress1").value=s.occupantAddress1,c.querySelector("#lotOccupancyOccupantEdit--occupantAddress2").value=s.occupantAddress2,c.querySelector("#lotOccupancyOccupantEdit--occupantCity").value=s.occupantCity,c.querySelector("#lotOccupancyOccupantEdit--occupantProvince").value=s.occupantProvince,c.querySelector("#lotOccupancyOccupantEdit--occupantPostalCode").value=s.occupantPostalCode,c.querySelector("#lotOccupancyOccupantEdit--occupantPhoneNumber").value=s.occupantPhoneNumber,c.querySelector("#lotOccupancyOccupantEdit--occupantEmailAddress").value=s.occupantEmailAddress},onshown:(e,t)=>{bulmaJS.toggleHtmlClipped(),e.querySelector("#lotOccupancyOccupantEdit--lotOccupantTypeId").focus(),(l=e.querySelector("form")).addEventListener("submit",i),r=t},onremoved:()=>{bulmaJS.toggleHtmlClipped()}})},o=a=>{const o=a.currentTarget.closest("tr").dataset.lotOccupantIndex;bulmaJS.confirm({title:"Remove "+exports.aliases.occupant+"?",message:"Are you sure you want to remove this "+exports.aliases.occupant.toLowerCase()+"?",okButton:{text:"Yes, Remove "+exports.aliases.occupant,callbackFunction:()=>{cityssm.postJSON(e.urlPrefix+"/lotOccupancies/doDeleteLotOccupancyOccupant",{lotOccupancyId:t,lotOccupantIndex:o},e=>{e.success?(c=e.lotOccupancyOccupants,n()):bulmaJS.alert({title:"Error Removing "+exports.aliases.occupant,message:e.errorMessage||"",contextualColorName:"danger"})})}},contextualColorName:"warning"})},n=()=>{const e=document.querySelector("#container--lotOccupancyOccupants");if(cityssm.clearElement(e),0===c.length)return void(e.innerHTML='

There are no '+exports.aliases.occupants.toLowerCase()+" associated with this record.

");const t=document.createElement("table");t.className="table is-fullwidth is-striped is-hoverable",t.innerHTML=""+exports.aliases.occupant+" Type"+exports.aliases.occupant+'AddressOther ContactOptions';for(const e of c){const c=document.createElement("tr");c.dataset.lotOccupantIndex=e.lotOccupantIndex.toString(),c.innerHTML=""+cityssm.escapeHTML(e.lotOccupantType)+""+cityssm.escapeHTML(e.occupantName||"")+""+(e.occupantAddress1?cityssm.escapeHTML(e.occupantAddress1)+"
":"")+(e.occupantAddress2?cityssm.escapeHTML(e.occupantAddress2)+"
":"")+(e.occupantCity?cityssm.escapeHTML(e.occupantCity)+", ":"")+cityssm.escapeHTML(e.occupantProvince||"")+"
"+cityssm.escapeHTML(e.occupantPostalCode||"")+""+(e.occupantPhoneNumber?cityssm.escapeHTML(e.occupantPhoneNumber)+"
":"")+(e.occupantEmailAddress?cityssm.escapeHTML(e.occupantEmailAddress):"")+'
',c.querySelector(".button--edit").addEventListener("click",a),c.querySelector(".button--delete").addEventListener("click",o),t.querySelector("tbody").append(c)}e.append(t)};document.querySelector("#button--addOccupant").addEventListener("click",()=>{let a,o,s,l;const r=t=>{cityssm.postJSON(e.urlPrefix+"/lotOccupancies/doAddLotOccupancyOccupant",t,e=>{e.success?(c=e.lotOccupancyOccupants,a(),n()):bulmaJS.alert({title:"Error Adding "+exports.aliases.occupant,message:e.errorMessage||"",contextualColorName:"danger"})})},i=e=>{e.preventDefault(),r(o)};let u=[];const d=e=>{e.preventDefault();const c=e.currentTarget,a=u[Number.parseInt(c.dataset.index,10)],o=c.closest(".modal").querySelector("#lotOccupancyOccupantCopy--lotOccupantTypeId").value;""===o?bulmaJS.alert({title:"No "+exports.aliases.occupant+" Type Selected",message:"Select a type to apply to the newly added "+exports.aliases.occupant.toLowerCase()+".",contextualColorName:"warning"}):(a.lotOccupantTypeId=Number.parseInt(o,10),a.lotOccupancyId=Number.parseInt(t,10),r(a))},p=t=>{t.preventDefault(),""!==s.querySelector("#lotOccupancyOccupantCopy--searchFilter").value?(l.innerHTML='

Searching...
',cityssm.postJSON(e.urlPrefix+"/lotOccupancies/doSearchPastOccupants",s,e=>{u=e.occupants;const t=document.createElement("div");t.className="panel";for(const[e,c]of u.entries()){const a=document.createElement("a");a.className="panel-block is-block",a.dataset.index=e.toString(),a.innerHTML=""+cityssm.escapeHTML(c.occupantName||"")+'
'+cityssm.escapeHTML(c.occupantAddress1||"")+"
"+(c.occupantAddress2?cityssm.escapeHTML(c.occupantAddress2)+"
":"")+cityssm.escapeHTML(c.occupantCity||"")+", "+cityssm.escapeHTML(c.occupantProvince||"")+"
"+cityssm.escapeHTML(c.occupantPostalCode||"")+'
'+(c.occupantPhoneNumber?cityssm.escapeHTML(c.occupantPhoneNumber)+"
":"")+cityssm.escapeHTML(c.occupantEmailAddress||"")+"
",a.addEventListener("click",d),t.append(a)}l.innerHTML="",l.append(t)})):l.innerHTML='

Enter a partial name or address in the search field above.

'};cityssm.openHtmlModal("lotOccupancy-addOccupant",{onshow:c=>{e.populateAliases(c),c.querySelector("#lotOccupancyOccupantAdd--lotOccupancyId").value=t;const a=c.querySelector("#lotOccupancyOccupantAdd--lotOccupantTypeId"),o=c.querySelector("#lotOccupancyOccupantCopy--lotOccupantTypeId");for(const e of exports.lotOccupantTypes){const t=document.createElement("option");t.value=e.lotOccupantTypeId.toString(),t.textContent=e.lotOccupantType,a.append(t),o.append(t.cloneNode(!0))}c.querySelector("#lotOccupancyOccupantAdd--occupantCity").value=exports.occupantCityDefault,c.querySelector("#lotOccupancyOccupantAdd--occupantProvince").value=exports.occupantProvinceDefault},onshown:(e,t)=>{bulmaJS.toggleHtmlClipped(),bulmaJS.init(e),e.querySelector("#lotOccupancyOccupantAdd--lotOccupantTypeId").focus(),(o=e.querySelector("#form--lotOccupancyOccupantAdd")).addEventListener("submit",i),l=e.querySelector("#lotOccupancyOccupantCopy--searchResults"),(s=e.querySelector("#form--lotOccupancyOccupantCopy")).addEventListener("submit",e=>{e.preventDefault()}),e.querySelector("#lotOccupancyOccupantCopy--searchFilter").addEventListener("change",p),a=t},onremoved:()=>{bulmaJS.toggleHtmlClipped()}})}),n()}if(!c){let c=exports.lotOccupancyComments;delete exports.lotOccupancyComments;const a=a=>{const o=Number.parseInt(a.currentTarget.closest("tr").dataset.lotOccupancyCommentId,10),s=c.find(e=>e.lotOccupancyCommentId===o);let l,r;const i=t=>{t.preventDefault(),cityssm.postJSON(e.urlPrefix+"/lotOccupancies/doUpdateLotOccupancyComment",l,e=>{e.success?(c=e.lotOccupancyComments,r(),n()):bulmaJS.alert({title:"Error Updating Comment",message:e.errorMessage||"",contextualColorName:"danger"})})};cityssm.openHtmlModal("lotOccupancy-editComment",{onshow:c=>{e.populateAliases(c),c.querySelector("#lotOccupancyCommentEdit--lotOccupancyId").value=t,c.querySelector("#lotOccupancyCommentEdit--lotOccupancyCommentId").value=o.toString(),c.querySelector("#lotOccupancyCommentEdit--lotOccupancyComment").value=s.lotOccupancyComment;const a=c.querySelector("#lotOccupancyCommentEdit--lotOccupancyCommentDateString");a.value=s.lotOccupancyCommentDateString;const n=cityssm.dateToString(new Date);a.max=s.lotOccupancyCommentDateString<=n?n:s.lotOccupancyCommentDateString,c.querySelector("#lotOccupancyCommentEdit--lotOccupancyCommentTimeString").value=s.lotOccupancyCommentTimeString},onshown:(t,c)=>{bulmaJS.toggleHtmlClipped(),e.initializeDatePickers(t),e.initializeTimePickers(t),t.querySelector("#lotOccupancyCommentEdit--lotOccupancyComment").focus(),(l=t.querySelector("form")).addEventListener("submit",i),r=c},onremoved:()=>{bulmaJS.toggleHtmlClipped()}})},o=a=>{const o=Number.parseInt(a.currentTarget.closest("tr").dataset.lotOccupancyCommentId,10);bulmaJS.confirm({title:"Remove Comment?",message:"Are you sure you want to remove this comment?",okButton:{text:"Yes, Remove Comment",callbackFunction:()=>{cityssm.postJSON(e.urlPrefix+"/lotOccupancies/doDeleteLotOccupancyComment",{lotOccupancyId:t,lotOccupancyCommentId:o},e=>{e.success?(c=e.lotOccupancyComments,n()):bulmaJS.alert({title:"Error Removing Comment",message:e.errorMessage||"",contextualColorName:"danger"})})}},contextualColorName:"warning"})},n=()=>{const e=document.querySelector("#container--lotOccupancyComments");if(0===c.length)return void(e.innerHTML='

There are no comments associated with this record.

');const t=document.createElement("table");t.className="table is-fullwidth is-striped is-hoverable",t.innerHTML='CommentorComment DateCommentOptions';for(const e of c){const c=document.createElement("tr");c.dataset.lotOccupancyCommentId=e.lotOccupancyCommentId.toString(),c.innerHTML=""+cityssm.escapeHTML(e.recordCreate_userName||"")+""+e.lotOccupancyCommentDateString+(0===e.lotOccupancyCommentTime?"":" "+e.lotOccupancyCommentTimeString)+""+cityssm.escapeHTML(e.lotOccupancyComment||"")+'
',c.querySelector(".button--edit").addEventListener("click",a),c.querySelector(".button--delete").addEventListener("click",o),t.querySelector("tbody").append(c)}e.innerHTML="",e.append(t)};document.querySelector("#button--addComment").addEventListener("click",()=>{let a,o;const s=t=>{t.preventDefault(),cityssm.postJSON(e.urlPrefix+"/lotOccupancies/doAddLotOccupancyComment",a,e=>{e.success?(c=e.lotOccupancyComments,o(),n()):bulmaJS.alert({title:"Error Adding Comment",message:e.errorMessage||"",contextualColorName:"danger"})})};cityssm.openHtmlModal("lotOccupancy-addComment",{onshow:c=>{e.populateAliases(c),c.querySelector("#lotOccupancyCommentAdd--lotOccupancyId").value=t},onshown:(e,t)=>{bulmaJS.toggleHtmlClipped(),e.querySelector("#lotOccupancyCommentAdd--lotOccupancyComment").focus(),(a=e.querySelector("form")).addEventListener("submit",s),o=t},onremoved:()=>{bulmaJS.toggleHtmlClipped()}})}),n()}if(!c){let c=exports.lotOccupancyFees;delete exports.lotOccupancyFees;const o=document.querySelector("#container--lotOccupancyFees"),n=()=>{let e=0;for(const t of c)e+=(t.feeAmount+t.taxAmount)*t.quantity;return e},s=a=>{const o=a.currentTarget.closest(".container--lotOccupancyFee").dataset.feeId;bulmaJS.confirm({title:"Delete Fee",message:"Are you sure you want to delete this fee?",contextualColorName:"warning",okButton:{text:"Yes, Delete Fee",callbackFunction:()=>{cityssm.postJSON(e.urlPrefix+"/lotOccupancies/doDeleteLotOccupancyFee",{lotOccupancyId:t,feeId:o},e=>{e.success?(c=e.lotOccupancyFees,l()):bulmaJS.alert({title:"Error Deleting Fee",message:e.errorMessage||"",contextualColorName:"danger"})})}}})},l=()=>{if(0===c.length)return o.innerHTML='

There are no fees associated with this record.

',void p();o.innerHTML='
FeeUnit Cost×QuantityequalsTotalOptions
Subtotal
Tax
Grand Total
';let e=0,t=0;for(const a of c){const c=document.createElement("tr");c.className="container--lotOccupancyFee",c.dataset.feeId=a.feeId.toString(),c.dataset.includeQuantity=a.includeQuantity?"1":"0",c.innerHTML=''+cityssm.escapeHTML(a.feeName||"")+""+(1===a.quantity?"":'$'+a.feeAmount.toFixed(2)+'×'+a.quantity+"=")+'$'+(a.feeAmount*a.quantity).toFixed(2)+'',c.querySelector("button").addEventListener("click",s),o.querySelector("tbody").append(c),e+=a.feeAmount*a.quantity,t+=a.taxAmount*a.quantity}o.querySelector("#lotOccupancyFees--feeAmountTotal").textContent="$"+e.toFixed(2),o.querySelector("#lotOccupancyFees--taxAmountTotal").textContent="$"+t.toFixed(2),o.querySelector("#lotOccupancyFees--grandTotal").textContent="$"+(e+t).toFixed(2),p()};document.querySelector("#button--addFee").addEventListener("click",()=>{if(a)return void bulmaJS.alert({message:"Please save all unsaved changes before adding fees.",contextualColorName:"warning"});let n,s,r;const i=(a,o=1)=>{cityssm.postJSON(e.urlPrefix+"/lotOccupancies/doAddLotOccupancyFee",{lotOccupancyId:t,feeId:a,quantity:o},e=>{e.success?(c=e.lotOccupancyFees,l(),d()):bulmaJS.alert({title:"Error Adding Fee",message:e.errorMessage||"",contextualColorName:"danger"})})},u=e=>{e.preventDefault();const t=Number.parseInt(e.currentTarget.dataset.feeId,10),c=Number.parseInt(e.currentTarget.closest(".container--feeCategory").dataset.feeCategoryId,10),a=n.find(e=>e.feeCategoryId===c).fees.find(e=>e.feeId===t);a.includeQuantity?(e=>{let t,c;const a=a=>{a.preventDefault(),i(e.feeId,t.value),c()};cityssm.openHtmlModal("lotOccupancy-setFeeQuantity",{onshow:t=>{t.querySelector("#lotOccupancyFeeQuantity--quantityUnit").textContent=e.quantityUnit},onshown:(e,o)=>{c=o,t=e.querySelector("#lotOccupancyFeeQuantity--quantity"),e.querySelector("form").addEventListener("submit",a)}})})(a):i(t)},d=()=>{const e=s.value.trim().toLowerCase().split(" ");r.innerHTML="";for(const t of n){const c=document.createElement("div");c.className="container--feeCategory",c.dataset.feeCategoryId=t.feeCategoryId.toString(),c.innerHTML='

'+cityssm.escapeHTML(t.feeCategory||"")+'

';let a=!1;for(const n of t.fees){if(o.querySelector(".container--lotOccupancyFee[data-fee-id='"+n.feeId+"'][data-include-quantity='0']"))continue;let t=!0;for(const c of e)if(!n.feeName.toLowerCase().includes(c)){t=!1;break}if(!t)continue;a=!0;const s=document.createElement("a");s.className="panel-block is-block container--fee",s.dataset.feeId=n.feeId.toString(),s.href="#",s.innerHTML=""+cityssm.escapeHTML(n.feeName||"")+"
"+cityssm.escapeHTML(n.feeDescription||"").replace(/\n/g,"
")+"
",s.addEventListener("click",u),c.querySelector(".panel").append(s)}a&&r.append(c)}};cityssm.openHtmlModal("lotOccupancy-addFee",{onshow:c=>{s=c.querySelector("#feeSelect--feeName"),r=c.querySelector("#resultsContainer--feeSelect"),cityssm.postJSON(e.urlPrefix+"/lotOccupancies/doGetFees",{lotOccupancyId:t},e=>{n=e.feeCategories,s.disabled=!1,s.addEventListener("keyup",d),s.focus(),d()})},onshown:()=>{bulmaJS.toggleHtmlClipped()},onhidden:()=>{l()},onremoved:()=>{bulmaJS.toggleHtmlClipped()}})});let r=exports.lotOccupancyTransactions;delete exports.lotOccupancyTransactions;const i=document.querySelector("#container--lotOccupancyTransactions"),u=()=>{let e=0;for(const t of r)e+=t.transactionAmount;return e},d=c=>{const a=c.currentTarget.closest(".container--lotOccupancyTransaction").dataset.transactionIndex;bulmaJS.confirm({title:"Delete Trasnaction",message:"Are you sure you want to delete this transaction?",contextualColorName:"warning",okButton:{text:"Yes, Delete Transaction",callbackFunction:()=>{cityssm.postJSON(e.urlPrefix+"/lotOccupancies/doDeleteLotOccupancyTransaction",{lotOccupancyId:t,transactionIndex:a},e=>{e.success?(r=e.lotOccupancyTransactions,p()):bulmaJS.alert({title:"Error Deleting Transaction",message:e.errorMessage||"",contextualColorName:"danger"})})}}})},p=()=>{if(0===r.length)return void(i.innerHTML='

There are no transactions associated with this record.

');i.innerHTML='
Date'+cityssm.escapeHTML(exports.aliases.externalReceiptNumber)+'AmountOptions
Transaction Total
';let e=0;for(const t of r){e+=t.transactionAmount;const c=document.createElement("tr");c.className="container--lotOccupancyTransaction",c.dataset.transactionIndex=t.transactionIndex.toString(),c.innerHTML=""+t.transactionDateString+""+cityssm.escapeHTML(t.externalReceiptNumber||"")+"
"+cityssm.escapeHTML(t.transactionNote||"")+'$'+t.transactionAmount.toFixed(2)+'',c.querySelector("button").addEventListener("click",d),i.querySelector("tbody").append(c)}i.querySelector("#lotOccupancyTransactions--grandTotal").textContent="$"+e.toFixed(2);const t=n();t>e&&i.insertAdjacentHTML("afterbegin",'
Outstanding Balance
$'+(t-e).toFixed(2)+"
")};document.querySelector("#button--addTransaction").addEventListener("click",()=>{let c;const a=t=>{t.preventDefault(),cityssm.postJSON(e.urlPrefix+"/lotOccupancies/doAddLotOccupancyTransaction",t.currentTarget,e=>{e.success?(r=e.lotOccupancyTransactions,c(),p()):bulmaJS.confirm({title:"Error Adding Transaction",message:e.errorMessage||"",contextualColorName:"danger"})})};cityssm.openHtmlModal("lotOccupancy-addTransaction",{onshow:c=>{e.populateAliases(c),c.querySelector("#lotOccupancyTransactionAdd--lotOccupancyId").value=t.toString();const a=n(),o=u(),s=c.querySelector("#lotOccupancyTransactionAdd--transactionAmount");s.min=(-1*o).toFixed(2),s.max=Math.max(a-o,0).toFixed(2),s.value=Math.max(a-o,0).toFixed(2)},onshown:(e,t)=>{bulmaJS.toggleHtmlClipped(),c=t,e.querySelector("form").addEventListener("submit",a)},onremoved:()=>{bulmaJS.toggleHtmlClipped()}})}),l()}})(); \ No newline at end of file diff --git a/routes/lotOccupancies.js b/routes/lotOccupancies.js index 469533b4..edc5e405 100644 --- a/routes/lotOccupancies.js +++ b/routes/lotOccupancies.js @@ -7,6 +7,7 @@ import handler_doGetOccupancyTypeFields from "../handlers/lotOccupancies-post/do import handler_doCreateLotOccupancy from "../handlers/lotOccupancies-post/doCreateLotOccupancy.js"; import handler_edit from "../handlers/lotOccupancies-get/edit.js"; import handler_doUpdateLotOccupancy from "../handlers/lotOccupancies-post/doUpdateLotOccupancy.js"; +import handler_doCopyLotOccupancy from "../handlers/lotOccupancies-post/doCopyLotOccupancy.js"; import handler_doDeleteLotOccupancy from "../handlers/lotOccupancies-post/doDeleteLotOccupancy.js"; import handler_doSearchPastOccupants from "../handlers/lotOccupancies-post/doSearchPastOccupants.js"; import handler_doAddLotOccupancyOccupant from "../handlers/lotOccupancies-post/doAddLotOccupancyOccupant.js"; @@ -30,6 +31,7 @@ router.post("/doCreateLotOccupancy", permissionHandlers.updatePostHandler, handl router.get("/:lotOccupancyId", handler_view); router.get("/:lotOccupancyId/edit", permissionHandlers.updateGetHandler, handler_edit); router.post("/doUpdateLotOccupancy", permissionHandlers.updatePostHandler, handler_doUpdateLotOccupancy); +router.post("/doCopyLotOccupancy", permissionHandlers.updatePostHandler, handler_doCopyLotOccupancy); router.post("/doDeleteLotOccupancy", permissionHandlers.updatePostHandler, handler_doDeleteLotOccupancy); router.post("/doSearchPastOccupants", permissionHandlers.updatePostHandler, handler_doSearchPastOccupants); router.post("/doAddLotOccupancyOccupant", permissionHandlers.updatePostHandler, handler_doAddLotOccupancyOccupant); diff --git a/routes/lotOccupancies.ts b/routes/lotOccupancies.ts index 6c1598f7..7df90688 100644 --- a/routes/lotOccupancies.ts +++ b/routes/lotOccupancies.ts @@ -11,6 +11,7 @@ import handler_doCreateLotOccupancy from "../handlers/lotOccupancies-post/doCrea import handler_edit from "../handlers/lotOccupancies-get/edit.js"; import handler_doUpdateLotOccupancy from "../handlers/lotOccupancies-post/doUpdateLotOccupancy.js"; +import handler_doCopyLotOccupancy from "../handlers/lotOccupancies-post/doCopyLotOccupancy.js"; import handler_doDeleteLotOccupancy from "../handlers/lotOccupancies-post/doDeleteLotOccupancy.js"; import handler_doSearchPastOccupants from "../handlers/lotOccupancies-post/doSearchPastOccupants.js"; @@ -73,6 +74,12 @@ router.post( handler_doUpdateLotOccupancy ); +router.post( + "/doCopyLotOccupancy", + permissionHandlers.updatePostHandler, + handler_doCopyLotOccupancy +); + router.post( "/doDeleteLotOccupancy", permissionHandlers.updatePostHandler, diff --git a/views/lotOccupancy-edit.ejs b/views/lotOccupancy-edit.ejs index 43fa1049..b5c7a7d7 100644 --- a/views/lotOccupancy-edit.ejs +++ b/views/lotOccupancy-edit.ejs @@ -282,6 +282,10 @@