diff --git a/handlers/lotOccupancies-get/new.ts b/handlers/lotOccupancies-get/new.ts index 2554ae1a..add3756e 100644 --- a/handlers/lotOccupancies-get/new.ts +++ b/handlers/lotOccupancies-get/new.ts @@ -3,7 +3,6 @@ import type { } from "express"; import { - getLotOccupantTypes, getOccupancyTypes } from "../../helpers/functions.cache.js"; diff --git a/handlers/lotOccupancies-post/doAddLotOccupancyComment.d.ts b/handlers/lotOccupancies-post/doAddLotOccupancyComment.d.ts new file mode 100644 index 00000000..9621c611 --- /dev/null +++ b/handlers/lotOccupancies-post/doAddLotOccupancyComment.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/doAddLotOccupancyComment.js b/handlers/lotOccupancies-post/doAddLotOccupancyComment.js new file mode 100644 index 00000000..cd5cbc73 --- /dev/null +++ b/handlers/lotOccupancies-post/doAddLotOccupancyComment.js @@ -0,0 +1,11 @@ +import { addLotOccupancyComment } from "../../helpers/lotOccupancyDB/addLotOccupancyComment.js"; +import { getLotOccupancyComments } from "../../helpers/lotOccupancyDB/getLotOccupancyComments.js"; +export const handler = async (request, response) => { + addLotOccupancyComment(request.body, request.session); + const lotOccupancyComments = getLotOccupancyComments(request.body.lotOccupancyId); + response.json({ + success: true, + lotOccupancyComments + }); +}; +export default handler; diff --git a/handlers/lotOccupancies-post/doAddLotOccupancyComment.ts b/handlers/lotOccupancies-post/doAddLotOccupancyComment.ts new file mode 100644 index 00000000..20f1d669 --- /dev/null +++ b/handlers/lotOccupancies-post/doAddLotOccupancyComment.ts @@ -0,0 +1,27 @@ +import type { + RequestHandler +} from "express"; + +import { + addLotOccupancyComment +} from "../../helpers/lotOccupancyDB/addLotOccupancyComment.js"; + +import { + getLotOccupancyComments +} from "../../helpers/lotOccupancyDB/getLotOccupancyComments.js"; + + +export const handler: RequestHandler = async (request, response) => { + + addLotOccupancyComment(request.body, request.session); + + const lotOccupancyComments = getLotOccupancyComments(request.body.lotOccupancyId); + + response.json({ + success: true, + lotOccupancyComments + }); +}; + + +export default handler; \ No newline at end of file diff --git a/handlers/lotOccupancies-post/doDeleteLotOccupancyComment.d.ts b/handlers/lotOccupancies-post/doDeleteLotOccupancyComment.d.ts new file mode 100644 index 00000000..9621c611 --- /dev/null +++ b/handlers/lotOccupancies-post/doDeleteLotOccupancyComment.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/doDeleteLotOccupancyComment.js b/handlers/lotOccupancies-post/doDeleteLotOccupancyComment.js new file mode 100644 index 00000000..c2f2d2ca --- /dev/null +++ b/handlers/lotOccupancies-post/doDeleteLotOccupancyComment.js @@ -0,0 +1,11 @@ +import { deleteLotOccupancyComment } from "../../helpers/lotOccupancyDB/deleteLotOccupancyComment.js"; +import { getLotOccupancyComments } from "../../helpers/lotOccupancyDB/getLotOccupancyComments.js"; +export const handler = async (request, response) => { + const success = deleteLotOccupancyComment(request.body.lotOccupancyCommentId, request.session); + const lotOccupancyComments = getLotOccupancyComments(request.body.lotOccupancyId); + response.json({ + success, + lotOccupancyComments + }); +}; +export default handler; diff --git a/handlers/lotOccupancies-post/doDeleteLotOccupancyComment.ts b/handlers/lotOccupancies-post/doDeleteLotOccupancyComment.ts new file mode 100644 index 00000000..ed4e1c69 --- /dev/null +++ b/handlers/lotOccupancies-post/doDeleteLotOccupancyComment.ts @@ -0,0 +1,25 @@ +import type { + RequestHandler +} from "express"; + +import { + deleteLotOccupancyComment +} from "../../helpers/lotOccupancyDB/deleteLotOccupancyComment.js"; + +import {getLotOccupancyComments} from "../../helpers/lotOccupancyDB/getLotOccupancyComments.js"; + + +export const handler: RequestHandler = async (request, response) => { + + const success = deleteLotOccupancyComment(request.body.lotOccupancyCommentId, request.session); + + const lotOccupancyComments = getLotOccupancyComments(request.body.lotOccupancyId); + + response.json({ + success, + lotOccupancyComments + }); +}; + + +export default handler; \ No newline at end of file diff --git a/handlers/lotOccupancies-post/doUpdateLotOccupancyComment.d.ts b/handlers/lotOccupancies-post/doUpdateLotOccupancyComment.d.ts new file mode 100644 index 00000000..9621c611 --- /dev/null +++ b/handlers/lotOccupancies-post/doUpdateLotOccupancyComment.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/doUpdateLotOccupancyComment.js b/handlers/lotOccupancies-post/doUpdateLotOccupancyComment.js new file mode 100644 index 00000000..0d19ad56 --- /dev/null +++ b/handlers/lotOccupancies-post/doUpdateLotOccupancyComment.js @@ -0,0 +1,11 @@ +import { updateLotOccupancyComment } from "../../helpers/lotOccupancyDB/updateLotOccupancyComment.js"; +import { getLotOccupancyComments } from "../../helpers/lotOccupancyDB/getLotOccupancyComments.js"; +export const handler = async (request, response) => { + const success = updateLotOccupancyComment(request.body, request.session); + const lotOccupancyComments = getLotOccupancyComments(request.body.lotOccupancyId); + response.json({ + success, + lotOccupancyComments + }); +}; +export default handler; diff --git a/handlers/lotOccupancies-post/doUpdateLotOccupancyComment.ts b/handlers/lotOccupancies-post/doUpdateLotOccupancyComment.ts new file mode 100644 index 00000000..0efd81c0 --- /dev/null +++ b/handlers/lotOccupancies-post/doUpdateLotOccupancyComment.ts @@ -0,0 +1,25 @@ +import type { + RequestHandler +} from "express"; + +import { + updateLotOccupancyComment +} from "../../helpers/lotOccupancyDB/updateLotOccupancyComment.js"; + +import {getLotOccupancyComments} from "../../helpers/lotOccupancyDB/getLotOccupancyComments.js"; + + +export const handler: RequestHandler = async (request, response) => { + + const success = updateLotOccupancyComment(request.body, request.session); + + const lotOccupancyComments = getLotOccupancyComments(request.body.lotOccupancyId); + + response.json({ + success, + lotOccupancyComments + }); +}; + + +export default handler; \ No newline at end of file diff --git a/helpers/lotOccupancyDB/addLotOccupancyComment.d.ts b/helpers/lotOccupancyDB/addLotOccupancyComment.d.ts index e1b7a3d9..da115ef5 100644 --- a/helpers/lotOccupancyDB/addLotOccupancyComment.d.ts +++ b/helpers/lotOccupancyDB/addLotOccupancyComment.d.ts @@ -1,8 +1,8 @@ import type * as recordTypes from "../../types/recordTypes"; interface AddLotOccupancyCommentForm { lotOccupancyId: string | number; - lotOccupancyCommentDateString: string; - lotOccupancyCommentTimeString: string; + lotOccupancyCommentDateString?: string; + lotOccupancyCommentTimeString?: string; lotOccupancyComment: string; } export declare const addLotOccupancyComment: (commentForm: AddLotOccupancyCommentForm, requestSession: recordTypes.PartialSession) => number; diff --git a/helpers/lotOccupancyDB/addLotOccupancyComment.js b/helpers/lotOccupancyDB/addLotOccupancyComment.js index 9477e3f5..ceb4a950 100644 --- a/helpers/lotOccupancyDB/addLotOccupancyComment.js +++ b/helpers/lotOccupancyDB/addLotOccupancyComment.js @@ -1,16 +1,26 @@ -import { dateStringToInteger, timeStringToInteger } from "@cityssm/expressjs-server-js/dateTimeFns.js"; import sqlite from "better-sqlite3"; import { lotOccupancyDB as databasePath } from "../../data/databasePaths.js"; +import { dateStringToInteger, dateToInteger, dateToTimeInteger, timeStringToInteger } from "@cityssm/expressjs-server-js/dateTimeFns.js"; export const addLotOccupancyComment = (commentForm, requestSession) => { + const rightNow = new Date(); + let lotOccupancyCommentDate; + let lotOccupancyCommentTime; + if (commentForm.lotOccupancyCommentDateString) { + lotOccupancyCommentDate = dateStringToInteger(commentForm.lotOccupancyCommentDateString); + lotOccupancyCommentTime = timeStringToInteger(commentForm.lotOccupancyCommentTimeString); + } + else { + lotOccupancyCommentDate = dateToInteger(rightNow); + lotOccupancyCommentTime = dateToTimeInteger(rightNow); + } const database = sqlite(databasePath); - const rightNowMillis = Date.now(); const result = database .prepare("insert into LotOccupancyComments (" + "lotOccupancyId, lotOccupancyCommentDate, lotOccupancyCommentTime, lotOccupancyComment," + " recordCreate_userName, recordCreate_timeMillis," + " recordUpdate_userName, recordUpdate_timeMillis)" + " values (?, ?, ?, ?, ?, ?, ?, ?)") - .run(commentForm.lotOccupancyId, dateStringToInteger(commentForm.lotOccupancyCommentDateString), timeStringToInteger(commentForm.lotOccupancyCommentTimeString), commentForm.lotOccupancyComment, requestSession.user.userName, rightNowMillis, requestSession.user.userName, rightNowMillis); + .run(commentForm.lotOccupancyId, lotOccupancyCommentDate, lotOccupancyCommentTime, commentForm.lotOccupancyComment, requestSession.user.userName, rightNow.getTime(), requestSession.user.userName, rightNow.getTime()); database.close(); return result.lastInsertRowid; }; diff --git a/helpers/lotOccupancyDB/addLotOccupancyComment.ts b/helpers/lotOccupancyDB/addLotOccupancyComment.ts index 799db476..2b6cee5f 100644 --- a/helpers/lotOccupancyDB/addLotOccupancyComment.ts +++ b/helpers/lotOccupancyDB/addLotOccupancyComment.ts @@ -1,44 +1,64 @@ -import { dateStringToInteger, timeStringToInteger } from "@cityssm/expressjs-server-js/dateTimeFns.js"; import sqlite from "better-sqlite3"; -import { lotOccupancyDB as databasePath } from "../../data/databasePaths.js"; + +import { + lotOccupancyDB as databasePath +} from "../../data/databasePaths.js"; + +import { + dateStringToInteger, + dateToInteger, + dateToTimeInteger, + timeStringToInteger +} from "@cityssm/expressjs-server-js/dateTimeFns.js"; import type * as recordTypes from "../../types/recordTypes"; interface AddLotOccupancyCommentForm { lotOccupancyId: string | number; - lotOccupancyCommentDateString: string; - lotOccupancyCommentTimeString: string; + lotOccupancyCommentDateString ? : string; + lotOccupancyCommentTimeString ? : string; lotOccupancyComment: string; } export const addLotOccupancyComment = - (commentForm: AddLotOccupancyCommentForm, requestSession: recordTypes.PartialSession): number => { + (commentForm: AddLotOccupancyCommentForm, requestSession: recordTypes.PartialSession): number => { - const database = sqlite(databasePath); + const rightNow = new Date(); - const rightNowMillis = Date.now(); + let lotOccupancyCommentDate: number; + let lotOccupancyCommentTime: number; - const result = database - .prepare("insert into LotOccupancyComments (" + - "lotOccupancyId, lotOccupancyCommentDate, lotOccupancyCommentTime, lotOccupancyComment," + - " recordCreate_userName, recordCreate_timeMillis," + - " recordUpdate_userName, recordUpdate_timeMillis)" + - " values (?, ?, ?, ?, ?, ?, ?, ?)") - .run(commentForm.lotOccupancyId, - dateStringToInteger(commentForm.lotOccupancyCommentDateString), - timeStringToInteger(commentForm.lotOccupancyCommentTimeString), - commentForm.lotOccupancyComment, - requestSession.user.userName, - rightNowMillis, - requestSession.user.userName, - rightNowMillis); + if (commentForm.lotOccupancyCommentDateString) { + lotOccupancyCommentDate = dateStringToInteger(commentForm.lotOccupancyCommentDateString); + lotOccupancyCommentTime = timeStringToInteger(commentForm.lotOccupancyCommentTimeString); + } else { + lotOccupancyCommentDate = dateToInteger(rightNow); + lotOccupancyCommentTime = dateToTimeInteger(rightNow); + } - database.close(); + const database = sqlite(databasePath); - return result.lastInsertRowid as number; - }; + const result = database + .prepare("insert into LotOccupancyComments (" + + "lotOccupancyId, lotOccupancyCommentDate, lotOccupancyCommentTime, lotOccupancyComment," + + " recordCreate_userName, recordCreate_timeMillis," + + " recordUpdate_userName, recordUpdate_timeMillis)" + + " values (?, ?, ?, ?, ?, ?, ?, ?)") + .run(commentForm.lotOccupancyId, + lotOccupancyCommentDate, + lotOccupancyCommentTime, + commentForm.lotOccupancyComment, + requestSession.user.userName, + rightNow.getTime(), + requestSession.user.userName, + rightNow.getTime()); + + database.close(); + + return result.lastInsertRowid as number; + }; export default addLotOccupancyComment; \ No newline at end of file diff --git a/helpers/lotOccupancyDB/deleteLotOccupancyComment.d.ts b/helpers/lotOccupancyDB/deleteLotOccupancyComment.d.ts new file mode 100644 index 00000000..5092cd12 --- /dev/null +++ b/helpers/lotOccupancyDB/deleteLotOccupancyComment.d.ts @@ -0,0 +1,3 @@ +import type * as recordTypes from "../../types/recordTypes"; +export declare const deleteLotOccupancyComment: (lotOccupancyCommentId: number | string, requestSession: recordTypes.PartialSession) => boolean; +export default deleteLotOccupancyComment; diff --git a/helpers/lotOccupancyDB/deleteLotOccupancyComment.js b/helpers/lotOccupancyDB/deleteLotOccupancyComment.js new file mode 100644 index 00000000..b9e70c74 --- /dev/null +++ b/helpers/lotOccupancyDB/deleteLotOccupancyComment.js @@ -0,0 +1,15 @@ +import sqlite from "better-sqlite3"; +import { lotOccupancyDB as databasePath } from "../../data/databasePaths.js"; +export const deleteLotOccupancyComment = (lotOccupancyCommentId, requestSession) => { + const database = sqlite(databasePath); + const rightNowMillis = Date.now(); + const result = database + .prepare("update LotOccupancyComments" + + " set recordDelete_userName = ?," + + " recordDelete_timeMillis = ?" + + " where lotOccupancyCommentId = ?") + .run(requestSession.user.userName, rightNowMillis, lotOccupancyCommentId); + database.close(); + return (result.changes > 0); +}; +export default deleteLotOccupancyComment; diff --git a/helpers/lotOccupancyDB/deleteLotOccupancyComment.ts b/helpers/lotOccupancyDB/deleteLotOccupancyComment.ts new file mode 100644 index 00000000..f6f6dfec --- /dev/null +++ b/helpers/lotOccupancyDB/deleteLotOccupancyComment.ts @@ -0,0 +1,33 @@ +import sqlite from "better-sqlite3"; + +import { + lotOccupancyDB as databasePath +} from "../../data/databasePaths.js"; + +import type * as recordTypes from "../../types/recordTypes"; + + +export const deleteLotOccupancyComment = + (lotOccupancyCommentId: number | string, + requestSession: recordTypes.PartialSession): boolean => { + + const database = sqlite(databasePath); + + const rightNowMillis = Date.now(); + + const result = database + .prepare("update LotOccupancyComments" + + " set recordDelete_userName = ?," + + " recordDelete_timeMillis = ?" + + " where lotOccupancyCommentId = ?") + .run(requestSession.user.userName, + rightNowMillis, + lotOccupancyCommentId); + + database.close(); + + return (result.changes > 0); + }; + + +export default deleteLotOccupancyComment; \ No newline at end of file diff --git a/helpers/lotOccupancyDB/getLotOccupancyComments.js b/helpers/lotOccupancyDB/getLotOccupancyComments.js index dae5b708..34c3a9a8 100644 --- a/helpers/lotOccupancyDB/getLotOccupancyComments.js +++ b/helpers/lotOccupancyDB/getLotOccupancyComments.js @@ -11,7 +11,8 @@ export const getLotOccupancyComments = (lotOccupancyId, connectedDatabase) => { .prepare("select lotOccupancyCommentId," + " lotOccupancyCommentDate, userFn_dateIntegerToString(lotOccupancyCommentDate) as lotOccupancyCommentDateString," + " lotOccupancyCommentTime, userFn_timeIntegerToString(lotOccupancyCommentTime) as lotOccupancyCommentTimeString," + - " lotOccupancyComment" + + " lotOccupancyComment," + + " recordCreate_userName, recordUpdate_userName" + " from LotOccupancyComments" + " where recordDelete_timeMillis is null" + " and lotOccupancyId = ?" + diff --git a/helpers/lotOccupancyDB/getLotOccupancyComments.ts b/helpers/lotOccupancyDB/getLotOccupancyComments.ts index 0d983ba1..01438617 100644 --- a/helpers/lotOccupancyDB/getLotOccupancyComments.ts +++ b/helpers/lotOccupancyDB/getLotOccupancyComments.ts @@ -20,7 +20,8 @@ export const getLotOccupancyComments = (lotOccupancyId: number | string, connect .prepare("select lotOccupancyCommentId," + " lotOccupancyCommentDate, userFn_dateIntegerToString(lotOccupancyCommentDate) as lotOccupancyCommentDateString," + " lotOccupancyCommentTime, userFn_timeIntegerToString(lotOccupancyCommentTime) as lotOccupancyCommentTimeString," + - " lotOccupancyComment" + + " lotOccupancyComment," + + " recordCreate_userName, recordUpdate_userName" + " from LotOccupancyComments" + " where recordDelete_timeMillis is null" + " and lotOccupancyId = ?" + diff --git a/helpers/lotOccupancyDB/updateLotOccupancyComment.d.ts b/helpers/lotOccupancyDB/updateLotOccupancyComment.d.ts new file mode 100644 index 00000000..04e21378 --- /dev/null +++ b/helpers/lotOccupancyDB/updateLotOccupancyComment.d.ts @@ -0,0 +1,9 @@ +import type * as recordTypes from "../../types/recordTypes"; +interface UpdateLotOccupancyCommentForm { + lotOccupancyCommentId: string | number; + lotOccupancyCommentDateString: string; + lotOccupancyCommentTimeString: string; + lotOccupancyComment: string; +} +export declare const updateLotOccupancyComment: (commentForm: UpdateLotOccupancyCommentForm, requestSession: recordTypes.PartialSession) => boolean; +export default updateLotOccupancyComment; diff --git a/helpers/lotOccupancyDB/updateLotOccupancyComment.js b/helpers/lotOccupancyDB/updateLotOccupancyComment.js new file mode 100644 index 00000000..83e4663d --- /dev/null +++ b/helpers/lotOccupancyDB/updateLotOccupancyComment.js @@ -0,0 +1,20 @@ +import sqlite from "better-sqlite3"; +import { lotOccupancyDB as databasePath } from "../../data/databasePaths.js"; +import { dateStringToInteger } from "@cityssm/expressjs-server-js/dateTimeFns.js"; +export const updateLotOccupancyComment = (commentForm, requestSession) => { + const rightNowMillis = Date.now(); + const database = sqlite(databasePath); + const result = database + .prepare("update LotOccupancyComments" + + " set lotOccupancyCommentDate = ?," + + " lotOccupancyCommentTime = ?," + + " lotOccupancyComment = ?," + + " recordUpdate_userName = ?," + + " recordUpdate_timeMillis = ?" + + " where recordDelete_timeMillis is null" + + " and lotOccupancyCommentId = ?") + .run(dateStringToInteger(commentForm.lotOccupancyCommentDateString), dateStringToInteger(commentForm.lotOccupancyCommentTimeString), commentForm.lotOccupancyComment, requestSession.user.userName, rightNowMillis, commentForm.lotOccupancyCommentId); + database.close(); + return result.changes > 0; +}; +export default updateLotOccupancyComment; diff --git a/helpers/lotOccupancyDB/updateLotOccupancyComment.ts b/helpers/lotOccupancyDB/updateLotOccupancyComment.ts new file mode 100644 index 00000000..b59f5247 --- /dev/null +++ b/helpers/lotOccupancyDB/updateLotOccupancyComment.ts @@ -0,0 +1,54 @@ +import sqlite from "better-sqlite3"; + +import { + lotOccupancyDB as databasePath +} from "../../data/databasePaths.js"; + +import { + dateStringToInteger, + dateToInteger, + dateToTimeInteger, + timeStringToInteger +} from "@cityssm/expressjs-server-js/dateTimeFns.js"; + +import type * as recordTypes from "../../types/recordTypes"; + + +interface UpdateLotOccupancyCommentForm { + lotOccupancyCommentId: string | number; + lotOccupancyCommentDateString: string; + lotOccupancyCommentTimeString: string; + lotOccupancyComment: string; +} + + +export const updateLotOccupancyComment = + (commentForm: UpdateLotOccupancyCommentForm, requestSession: recordTypes.PartialSession): boolean => { + + const rightNowMillis = Date.now(); + + const database = sqlite(databasePath); + + const result = database + .prepare("update LotOccupancyComments" + + " set lotOccupancyCommentDate = ?," + + " lotOccupancyCommentTime = ?," + + " lotOccupancyComment = ?," + + " recordUpdate_userName = ?," + + " recordUpdate_timeMillis = ?" + + " where recordDelete_timeMillis is null" + + " and lotOccupancyCommentId = ?") + .run(dateStringToInteger(commentForm.lotOccupancyCommentDateString), + dateStringToInteger(commentForm.lotOccupancyCommentTimeString), + commentForm.lotOccupancyComment, + requestSession.user.userName, + rightNowMillis, + commentForm.lotOccupancyCommentId); + + database.close(); + + return result.changes > 0; + }; + + +export default updateLotOccupancyComment; \ No newline at end of file diff --git a/public-typescript/lotOccupancyEdit.js b/public-typescript/lotOccupancyEdit.js index 59fb5df6..1b2f8136 100644 --- a/public-typescript/lotOccupancyEdit.js +++ b/public-typescript/lotOccupancyEdit.js @@ -395,4 +395,162 @@ Object.defineProperty(exports, "__esModule", { value: true }); }); renderLotOccupancyOccupants(); } + if (!isCreate) { + let lotOccupancyComments = exports.lotOccupancyComments; + const openEditLotOccupancyComment = (clickEvent) => { + const lotOccupancyCommentId = Number.parseInt(clickEvent.currentTarget.closest("tr").dataset.lotOccupancyCommentId, 10); + const lotOccupancyComment = lotOccupancyComments.find((currentLotOccupancyComment) => { + return currentLotOccupancyComment.lotOccupancyCommentId === lotOccupancyCommentId; + }); + let editFormElement; + let editCloseModalFunction; + const editComment = (submitEvent) => { + submitEvent.preventDefault(); + cityssm.postJSON(urlPrefix + "/lotOccupancies/doUpdateLotOccupancyComment", editFormElement, (responseJSON) => { + if (responseJSON.success) { + lotOccupancyComments = responseJSON.lotOccupancyComments; + editCloseModalFunction(); + renderLotOccupancyComments(); + } + else { + bulmaJS.alert({ + title: "Error Updating Comment", + message: responseJSON.errorMessage, + contextualColorName: "danger" + }); + } + }); + }; + cityssm.openHtmlModal("lotOccupancy-editComment", { + onshow: (modalElement) => { + los.populateAliases(modalElement); + modalElement.querySelector("#lotOccupancyCommentEdit--lotOccupancyId").value = lotOccupancyId; + modalElement.querySelector("#lotOccupancyCommentEdit--lotOccupancyCommentId").value = lotOccupancyCommentId.toString(); + modalElement.querySelector("#lotOccupancyCommentEdit--lotOccupancyComment").value = lotOccupancyComment.lotOccupancyComment; + modalElement.querySelector("#lotOccupancyCommentEdit--lotOccupancyCommentDateString").value = lotOccupancyComment.lotOccupancyCommentDateString; + modalElement.querySelector("#lotOccupancyCommentEdit--lotOccupancyCommentTimeString").value = lotOccupancyComment.lotOccupancyCommentTimeString; + }, + onshown: (modalElement, closeModalFunction) => { + bulmaJS.toggleHtmlClipped(); + editFormElement = modalElement.querySelector("form"); + editFormElement.addEventListener("submit", editComment); + editCloseModalFunction = closeModalFunction; + }, + onremoved: () => { + bulmaJS.toggleHtmlClipped(); + } + }); + }; + const deleteLotOccupancyComment = (clickEvent) => { + const lotOccupancyCommentId = Number.parseInt(clickEvent.currentTarget.closest("tr").dataset.lotOccupancyCommentId, 10); + const doDelete = () => { + cityssm.postJSON(urlPrefix + "/lotOccupancies/doDeleteLotOccupancyComment", { + lotOccupancyId, + lotOccupancyCommentId + }, (responseJSON) => { + if (responseJSON.success) { + lotOccupancyComments = responseJSON.lotOccupancyComments; + renderLotOccupancyComments(); + } + else { + bulmaJS.alert({ + title: "Error Removing Comment", + message: responseJSON.errorMessage, + contextualColorName: "danger" + }); + } + }); + }; + bulmaJS.confirm({ + title: "Remove Comment?", + message: "Are you sure you want to remove this comment?", + okButton: { + text: "Yes, Remove Comment", + callbackFunction: doDelete + }, + contextualColorName: "warning" + }); + }; + const renderLotOccupancyComments = () => { + const containerElement = document.querySelector("#container--lotOccupancyComments"); + if (lotOccupancyComments.length === 0) { + containerElement.innerHTML = "
" + + "

There are no comments associated with this record.

" + + "
"; + return; + } + const tableElement = document.createElement("table"); + tableElement.className = "table is-fullwidth is-striped is-hoverable"; + tableElement.innerHTML = "" + + "Commentor" + + "Comment Date" + + "Comment" + + "Options" + + "" + + ""; + for (const lotOccupancyComment of lotOccupancyComments) { + const tableRowElement = document.createElement("tr"); + tableRowElement.dataset.lotOccupancyCommentId = lotOccupancyComment.lotOccupancyCommentId.toString(); + tableRowElement.innerHTML = "" + cityssm.escapeHTML(lotOccupancyComment.recordCreate_userName) + "" + + "" + + lotOccupancyComment.lotOccupancyCommentDateString + + (lotOccupancyComment.lotOccupancyCommentTime === 0 ? "" : " " + lotOccupancyComment.lotOccupancyCommentTimeString) + + "" + + "" + cityssm.escapeHTML(lotOccupancyComment.lotOccupancyComment) + "" + + ("" + + "
" + + ("") + + ("") + + "
" + + ""); + tableRowElement.querySelector(".button--edit").addEventListener("click", openEditLotOccupancyComment); + tableRowElement.querySelector(".button--delete").addEventListener("click", deleteLotOccupancyComment); + tableElement.querySelector("tbody").append(tableRowElement); + } + containerElement.innerHTML = ""; + containerElement.append(tableElement); + }; + document.querySelector("#button--addComment").addEventListener("click", () => { + let addFormElement; + let addCloseModalFunction; + const addComment = (submitEvent) => { + submitEvent.preventDefault(); + cityssm.postJSON(urlPrefix + "/lotOccupancies/doAddLotOccupancyComment", addFormElement, (responseJSON) => { + if (responseJSON.success) { + lotOccupancyComments = responseJSON.lotOccupancyComments; + addCloseModalFunction(); + renderLotOccupancyComments(); + } + else { + bulmaJS.alert({ + title: "Error Adding Comment", + message: responseJSON.errorMessage, + contextualColorName: "danger" + }); + } + }); + }; + cityssm.openHtmlModal("lotOccupancy-addComment", { + onshow: (modalElement) => { + los.populateAliases(modalElement); + modalElement.querySelector("#lotOccupancyCommentAdd--lotOccupancyId").value = lotOccupancyId; + }, + onshown: (modalElement, closeModalFunction) => { + bulmaJS.toggleHtmlClipped(); + addFormElement = modalElement.querySelector("form"); + addFormElement.addEventListener("submit", addComment); + addCloseModalFunction = closeModalFunction; + }, + onremoved: () => { + bulmaJS.toggleHtmlClipped(); + } + }); + }); + renderLotOccupancyComments(); + } })(); diff --git a/public-typescript/lotOccupancyEdit.ts b/public-typescript/lotOccupancyEdit.ts index ac14237b..a4c080a1 100644 --- a/public-typescript/lotOccupancyEdit.ts +++ b/public-typescript/lotOccupancyEdit.ts @@ -8,8 +8,7 @@ import type { } from "@cityssm/bulma-webapp-js/src/types"; import type { - BulmaJS, - StringConfigProperties + BulmaJS } from "@cityssm/bulma-js/types"; declare const cityssm: cityssmGlobal; @@ -575,6 +574,221 @@ declare const bulmaJS: BulmaJS; * Comments */ + if (!isCreate) { + let lotOccupancyComments: recordTypes.LotOccupancyComment[] = exports.lotOccupancyComments; + + const openEditLotOccupancyComment = (clickEvent: Event) => { + + const lotOccupancyCommentId = Number.parseInt((clickEvent.currentTarget as HTMLElement).closest("tr").dataset.lotOccupancyCommentId, 10); + + const lotOccupancyComment = lotOccupancyComments.find((currentLotOccupancyComment) => { + return currentLotOccupancyComment.lotOccupancyCommentId === lotOccupancyCommentId; + }); + + let editFormElement: HTMLFormElement; + let editCloseModalFunction: () => void; + + const editComment = (submitEvent: SubmitEvent) => { + + submitEvent.preventDefault(); + + cityssm.postJSON(urlPrefix + "/lotOccupancies/doUpdateLotOccupancyComment", + editFormElement, + (responseJSON: { + success: boolean; + errorMessage ? : string; + lotOccupancyComments ? : recordTypes.LotOccupancyComment[]; + }) => { + + if (responseJSON.success) { + lotOccupancyComments = responseJSON.lotOccupancyComments; + editCloseModalFunction(); + renderLotOccupancyComments(); + } else { + bulmaJS.alert({ + title: "Error Updating Comment", + message: responseJSON.errorMessage, + contextualColorName: "danger" + }); + } + }); + }; + + cityssm.openHtmlModal("lotOccupancy-editComment", { + onshow: (modalElement) => { + los.populateAliases(modalElement); + + (modalElement.querySelector("#lotOccupancyCommentEdit--lotOccupancyId") as HTMLInputElement).value = lotOccupancyId; + (modalElement.querySelector("#lotOccupancyCommentEdit--lotOccupancyCommentId") as HTMLInputElement).value = lotOccupancyCommentId.toString(); + + (modalElement.querySelector("#lotOccupancyCommentEdit--lotOccupancyComment") as HTMLInputElement).value = lotOccupancyComment.lotOccupancyComment; + (modalElement.querySelector("#lotOccupancyCommentEdit--lotOccupancyCommentDateString") as HTMLInputElement).value = lotOccupancyComment.lotOccupancyCommentDateString; + (modalElement.querySelector("#lotOccupancyCommentEdit--lotOccupancyCommentTimeString") as HTMLInputElement).value = lotOccupancyComment.lotOccupancyCommentTimeString; + }, + onshown: (modalElement, closeModalFunction) => { + + bulmaJS.toggleHtmlClipped(); + + editFormElement = modalElement.querySelector("form"); + editFormElement.addEventListener("submit", editComment); + + editCloseModalFunction = closeModalFunction; + }, + onremoved: () => { + bulmaJS.toggleHtmlClipped(); + } + }); + }; + + const deleteLotOccupancyComment = (clickEvent: Event) => { + + const lotOccupancyCommentId = Number.parseInt((clickEvent.currentTarget as HTMLElement).closest("tr").dataset.lotOccupancyCommentId, 10); + + const doDelete = () => { + cityssm.postJSON(urlPrefix + "/lotOccupancies/doDeleteLotOccupancyComment", { + lotOccupancyId, + lotOccupancyCommentId + }, + (responseJSON: { + success: boolean; + errorMessage ? : string; + lotOccupancyComments: recordTypes.LotOccupancyComment[]; + }) => { + if (responseJSON.success) { + lotOccupancyComments = responseJSON.lotOccupancyComments; + renderLotOccupancyComments(); + } else { + bulmaJS.alert({ + title: "Error Removing Comment", + message: responseJSON.errorMessage, + contextualColorName: "danger" + }); + } + }); + }; + + bulmaJS.confirm({ + title: "Remove Comment?", + message: "Are you sure you want to remove this comment?", + okButton: { + text: "Yes, Remove Comment", + callbackFunction: doDelete + }, + contextualColorName: "warning" + }); + }; + + const renderLotOccupancyComments = () => { + + const containerElement = document.querySelector("#container--lotOccupancyComments") as HTMLElement; + + if (lotOccupancyComments.length === 0) { + containerElement.innerHTML = "
" + + "

There are no comments associated with this record.

" + + "
"; + return; + } + + const tableElement = document.createElement("table"); + tableElement.className = "table is-fullwidth is-striped is-hoverable"; + tableElement.innerHTML = "" + + "Commentor" + + "Comment Date" + + "Comment" + + "Options" + + "" + + ""; + + for (const lotOccupancyComment of lotOccupancyComments) { + + const tableRowElement = document.createElement("tr"); + tableRowElement.dataset.lotOccupancyCommentId = lotOccupancyComment.lotOccupancyCommentId.toString(); + + tableRowElement.innerHTML = "" + cityssm.escapeHTML(lotOccupancyComment.recordCreate_userName) + "" + + "" + + lotOccupancyComment.lotOccupancyCommentDateString + + (lotOccupancyComment.lotOccupancyCommentTime === 0 ? "" : " " + lotOccupancyComment.lotOccupancyCommentTimeString) + + "" + + "" + cityssm.escapeHTML(lotOccupancyComment.lotOccupancyComment) + "" + + ("" + + "
" + + ("") + + ("") + + "
" + + ""); + + tableRowElement.querySelector(".button--edit").addEventListener("click", openEditLotOccupancyComment); + tableRowElement.querySelector(".button--delete").addEventListener("click", deleteLotOccupancyComment); + + tableElement.querySelector("tbody").append(tableRowElement); + } + + containerElement.innerHTML = ""; + containerElement.append(tableElement); + }; + + + document.querySelector("#button--addComment").addEventListener("click", () => { + + let addFormElement: HTMLFormElement; + let addCloseModalFunction: () => void; + + const addComment = (submitEvent: SubmitEvent) => { + + submitEvent.preventDefault(); + + cityssm.postJSON(urlPrefix + "/lotOccupancies/doAddLotOccupancyComment", + addFormElement, + (responseJSON: { + success: boolean; + errorMessage ? : string; + lotOccupancyComments ? : recordTypes.LotOccupancyComment[]; + }) => { + + if (responseJSON.success) { + lotOccupancyComments = responseJSON.lotOccupancyComments; + addCloseModalFunction(); + renderLotOccupancyComments(); + } else { + bulmaJS.alert({ + title: "Error Adding Comment", + message: responseJSON.errorMessage, + contextualColorName: "danger" + }); + } + }); + }; + + cityssm.openHtmlModal("lotOccupancy-addComment", { + onshow: (modalElement) => { + los.populateAliases(modalElement); + + (modalElement.querySelector("#lotOccupancyCommentAdd--lotOccupancyId") as HTMLInputElement).value = lotOccupancyId; + }, + onshown: (modalElement, closeModalFunction) => { + + bulmaJS.toggleHtmlClipped(); + + addFormElement = modalElement.querySelector("form"); + addFormElement.addEventListener("submit", addComment); + + addCloseModalFunction = closeModalFunction; + }, + onremoved: () => { + bulmaJS.toggleHtmlClipped(); + } + }); + }); + + + renderLotOccupancyComments(); + } + /* * Fees */ diff --git a/public/html/lotOccupancy-addComment.html b/public/html/lotOccupancy-addComment.html new file mode 100644 index 00000000..d6a0671b --- /dev/null +++ b/public/html/lotOccupancy-addComment.html @@ -0,0 +1,29 @@ + \ No newline at end of file diff --git a/public/html/lotOccupancy-editComment.html b/public/html/lotOccupancy-editComment.html new file mode 100644 index 00000000..82d0e0e9 --- /dev/null +++ b/public/html/lotOccupancy-editComment.html @@ -0,0 +1,48 @@ + \ No newline at end of file diff --git a/public/javascripts/lotOccupancyEdit.min.js b/public/javascripts/lotOccupancyEdit.min.js index eaa45e35..d842422b 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("main").dataset.urlPrefix,c=document.querySelector("#lotOccupancy--lotOccupancyId").value,a=""===c;let o=!1,n=a;const s=()=>{o||(o=!0,cityssm.enableNavBlocker())},l=document.querySelector("#form--lotOccupancy");l.addEventListener("submit",e=>{e.preventDefault(),cityssm.postJSON(t+"/lotOccupancies/"+(a?"doCreateLotOccupancy":"doUpdateLotOccupancy"),l,e=>{e.success?(o=!1,cityssm.disableNavBlocker(),a||n?window.location.href=t+"/lotOccupancies/"+e.lotOccupancyId+"/edit?t="+Date.now():bulmaJS.alert({message:exports.aliases.occupancy+" Updated Successfully",contextualColorName:"success"})):bulmaJS.alert({title:"Error Saving "+exports.aliases.occupancy,message:e.errorMessage,contextualColorName:"danger"})})});const u=l.querySelectorAll("input, select");for(const e of u)e.addEventListener("change",s);const r=document.querySelector("#lotOccupancy--occupancyTypeId");if(a){const e=document.querySelector("#container--lotOccupancyFields");r.addEventListener("change",()=>{""!==r.value?cityssm.postJSON(t+"/lotOccupancies/doGetOccupancyTypeFields",{occupancyTypeId:r.value},t=>{if(0===t.occupancyTypeFields.length)return void(e.innerHTML='

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

");e.innerHTML="";let c="";for(const a of t.occupancyTypeFields){c+=","+a.occupancyTypeFieldId;const t=document.createElement("div");t.className="field",t.innerHTML='
',t.querySelector("label").textContent=a.occupancyTypeField;const o=document.createElement("input");o.className="input",o.id="lotOccupancy--lotOccupancyFieldValue_"+a.occupancyTypeFieldId,o.name="lotOccupancyFieldValue_"+a.occupancyTypeFieldId,o.type="text",o.required=a.isRequired,o.minLength=a.minimumLength,o.maxLength=a.maximumLength,a.pattern&&""!==a.pattern&&(o.pattern=a.pattern),t.querySelector(".control").append(o),e.append(t)}e.insertAdjacentHTML("beforeend",'')}):e.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:()=>{n=!0}},cancelButton:{text:"Revert the Change",callbackFunction:()=>{r.value=e}}})})}if(document.querySelector("#lotOccupancy--lotName").addEventListener("click",c=>{const a=c.currentTarget.value;let o,n,l;const u=e=>{e.preventDefault();const t=e.currentTarget;document.querySelector("#lotOccupancy--lotId").value=t.dataset.lotId,document.querySelector("#lotOccupancy--lotName").value=t.dataset.lotName,s(),o()},r=()=>{l.innerHTML='


Searching...

',cityssm.postJSON(t+"/lots/doSearchLots",n,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",u),t.append(e)}l.innerHTML="",l.append(t)})};cityssm.openHtmlModal("lotOccupancy-selectLot",{onshow:t=>{e.populateAliases(t)},onshown:(e,t)=>{bulmaJS.toggleHtmlClipped(),o=t;const c=e.querySelector("#lotSelect--lotName");c.value=a,c.focus(),c.addEventListener("change",r),e.querySelector("#lotSelect--occupancyStatus").addEventListener("change",r),n=e.querySelector("#form--lotSelect"),l=e.querySelector("#resultsContainer--lotSelect"),n.addEventListener("submit",e=>{e.preventDefault()}),r()},onremoved:()=>{bulmaJS.toggleHtmlClipped()}})}),document.querySelector("#lotOccupancy--occupancyStartDateString").addEventListener("change",()=>{document.querySelector("#lotOccupancy--occupancyEndDateString").min=document.querySelector("#lotOccupancy--occupancyStartDateString").value}),e.initializeUnlockFieldButtons(l),!a){let a=exports.lotOccupancyOccupants;const o=o=>{const n=Number.parseInt(o.currentTarget.closest("tr").dataset.lotOccupantIndex,10),l=a.find(e=>e.lotOccupantIndex===n);let u,r;const p=e=>{e.preventDefault(),cityssm.postJSON(t+"/lotOccupancies/doUpdateLotOccupancyOccupant",u,e=>{e.success?(a=e.lotOccupancyOccupants,r(),s()):bulmaJS.alert({title:"Error Updating "+exports.aliases.occupant,message:e.errorMessage,contextualColorName:"danger"})})};cityssm.openHtmlModal("lotOccupancy-editOccupant",{onshow:t=>{e.populateAliases(t),t.querySelector("#lotOccupancyOccupantEdit--lotOccupancyId").value=c,t.querySelector("#lotOccupancyOccupantEdit--lotOccupantIndex").value=n.toString();const a=t.querySelector("#lotOccupancyOccupantEdit--lotOccupantTypeId");let o=!1;for(const e of exports.lotOccupantTypes){const t=document.createElement("option");t.value=e.lotOccupantTypeId.toString(),t.textContent=e.lotOccupantType,e.lotOccupantTypeId===l.lotOccupantTypeId&&(t.selected=!0,o=!0),a.append(t)}if(!o){const e=document.createElement("option");e.value=l.lotOccupantTypeId.toString(),e.textContent=l.lotOccupantType,e.selected=!0,a.append(e)}t.querySelector("#lotOccupancyOccupantEdit--occupantName").value=l.occupantName,t.querySelector("#lotOccupancyOccupantEdit--occupantAddress1").value=l.occupantAddress1,t.querySelector("#lotOccupancyOccupantEdit--occupantAddress2").value=l.occupantAddress2,t.querySelector("#lotOccupancyOccupantEdit--occupantCity").value=l.occupantCity,t.querySelector("#lotOccupancyOccupantEdit--occupantProvince").value=l.occupantProvince,t.querySelector("#lotOccupancyOccupantEdit--occupantPostalCode").value=l.occupantPostalCode,t.querySelector("#lotOccupancyOccupantEdit--occupantPhoneNumber").value=l.occupantPhoneNumber},onshown:(e,t)=>{bulmaJS.toggleHtmlClipped(),(u=e.querySelector("form")).addEventListener("submit",p),r=t},onremoved:()=>{bulmaJS.toggleHtmlClipped()}})},n=e=>{const o=e.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(t+"/lotOccupancies/doDeleteLotOccupancyOccupant",{lotOccupancyId:c,lotOccupantIndex:o},e=>{e.success?(a=e.lotOccupancyOccupants,s()):bulmaJS.alert({title:"Error Removing "+exports.aliases.occupant,message:e.errorMessage,contextualColorName:"danger"})})}},contextualColorName:"warning"})},s=()=>{const e=document.querySelector("#container--lotOccupancyOccupants");if(cityssm.clearElement(e),0===a.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+"AddressPhone Number";for(const e of a){const c=document.createElement("tr");c.dataset.lotOccupantIndex=e.lotOccupantIndex.toString(),c.innerHTML=""+cityssm.escapeHTML(e.lotOccupantType)+""+cityssm.escapeHTML(e.occupantName)+""+cityssm.escapeHTML(e.occupantAddress1)+"
"+(e.occupantAddress2?cityssm.escapeHTML(e.occupantAddress2)+"
":"")+cityssm.escapeHTML(e.occupantCity)+", "+cityssm.escapeHTML(e.occupantProvince)+"
"+cityssm.escapeHTML(e.occupantPostalCode)+""+cityssm.escapeHTML(e.occupantPhoneNumber)+'
',c.querySelector(".button--edit").addEventListener("click",o),c.querySelector(".button--delete").addEventListener("click",n),t.querySelector("tbody").append(c)}e.append(t)};document.querySelector("#button--addOccupant").addEventListener("click",()=>{let o,n;const l=e=>{e.preventDefault(),cityssm.postJSON(t+"/lotOccupancies/doAddLotOccupancyOccupant",o,e=>{e.success?(a=e.lotOccupancyOccupants,n(),s()):bulmaJS.alert({title:"Error Adding "+exports.aliases.occupant,message:e.errorMessage,contextualColorName:"danger"})})};cityssm.openHtmlModal("lotOccupancy-addOccupant",{onshow:t=>{e.populateAliases(t),t.querySelector("#lotOccupancyOccupantAdd--lotOccupancyId").value=c;const a=t.querySelector("#lotOccupancyOccupantAdd--lotOccupantTypeId");for(const e of exports.lotOccupantTypes){const t=document.createElement("option");t.value=e.lotOccupantTypeId.toString(),t.textContent=e.lotOccupantType,a.append(t)}t.querySelector("#lotOccupancyOccupantAdd--occupantCity").value=exports.occupantCityDefault,t.querySelector("#lotOccupancyOccupantAdd--occupantProvince").value=exports.occupantProvinceDefault},onshown:(e,t)=>{bulmaJS.toggleHtmlClipped(),(o=e.querySelector("form")).addEventListener("submit",l),n=t},onremoved:()=>{bulmaJS.toggleHtmlClipped()}})}),s()}})(); \ No newline at end of file +"use strict";Object.defineProperty(exports,"__esModule",{value:!0}),(()=>{const e=exports.los,t=document.querySelector("main").dataset.urlPrefix,c=document.querySelector("#lotOccupancy--lotOccupancyId").value,o=""===c;let a=!1,n=o;const s=()=>{a||(a=!0,cityssm.enableNavBlocker())},l=document.querySelector("#form--lotOccupancy");l.addEventListener("submit",e=>{e.preventDefault(),cityssm.postJSON(t+"/lotOccupancies/"+(o?"doCreateLotOccupancy":"doUpdateLotOccupancy"),l,e=>{e.success?(a=!1,cityssm.disableNavBlocker(),o||n?window.location.href=t+"/lotOccupancies/"+e.lotOccupancyId+"/edit?t="+Date.now():bulmaJS.alert({message:exports.aliases.occupancy+" Updated Successfully",contextualColorName:"success"})):bulmaJS.alert({title:"Error Saving "+exports.aliases.occupancy,message:e.errorMessage,contextualColorName:"danger"})})});const u=l.querySelectorAll("input, select");for(const e of u)e.addEventListener("change",s);const r=document.querySelector("#lotOccupancy--occupancyTypeId");if(o){const e=document.querySelector("#container--lotOccupancyFields");r.addEventListener("change",()=>{""!==r.value?cityssm.postJSON(t+"/lotOccupancies/doGetOccupancyTypeFields",{occupancyTypeId:r.value},t=>{if(0===t.occupancyTypeFields.length)return void(e.innerHTML='

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

");e.innerHTML="";let c="";for(const o of t.occupancyTypeFields){c+=","+o.occupancyTypeFieldId;const t=document.createElement("div");t.className="field",t.innerHTML='
',t.querySelector("label").textContent=o.occupancyTypeField;const a=document.createElement("input");a.className="input",a.id="lotOccupancy--lotOccupancyFieldValue_"+o.occupancyTypeFieldId,a.name="lotOccupancyFieldValue_"+o.occupancyTypeFieldId,a.type="text",a.required=o.isRequired,a.minLength=o.minimumLength,a.maxLength=o.maximumLength,o.pattern&&""!==o.pattern&&(a.pattern=o.pattern),t.querySelector(".control").append(a),e.append(t)}e.insertAdjacentHTML("beforeend",'')}):e.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:()=>{n=!0}},cancelButton:{text:"Revert the Change",callbackFunction:()=>{r.value=e}}})})}if(document.querySelector("#lotOccupancy--lotName").addEventListener("click",c=>{const o=c.currentTarget.value;let a,n,l;const u=e=>{e.preventDefault();const t=e.currentTarget;document.querySelector("#lotOccupancy--lotId").value=t.dataset.lotId,document.querySelector("#lotOccupancy--lotName").value=t.dataset.lotName,s(),a()},r=()=>{l.innerHTML='


Searching...

',cityssm.postJSON(t+"/lots/doSearchLots",n,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",u),t.append(e)}l.innerHTML="",l.append(t)})};cityssm.openHtmlModal("lotOccupancy-selectLot",{onshow:t=>{e.populateAliases(t)},onshown:(e,t)=>{bulmaJS.toggleHtmlClipped(),a=t;const c=e.querySelector("#lotSelect--lotName");c.value=o,c.focus(),c.addEventListener("change",r),e.querySelector("#lotSelect--occupancyStatus").addEventListener("change",r),n=e.querySelector("#form--lotSelect"),l=e.querySelector("#resultsContainer--lotSelect"),n.addEventListener("submit",e=>{e.preventDefault()}),r()},onremoved:()=>{bulmaJS.toggleHtmlClipped()}})}),document.querySelector("#lotOccupancy--occupancyStartDateString").addEventListener("change",()=>{document.querySelector("#lotOccupancy--occupancyEndDateString").min=document.querySelector("#lotOccupancy--occupancyStartDateString").value}),e.initializeUnlockFieldButtons(l),!o){let o=exports.lotOccupancyOccupants;const a=a=>{const n=Number.parseInt(a.currentTarget.closest("tr").dataset.lotOccupantIndex,10),l=o.find(e=>e.lotOccupantIndex===n);let u,r;const p=e=>{e.preventDefault(),cityssm.postJSON(t+"/lotOccupancies/doUpdateLotOccupancyOccupant",u,e=>{e.success?(o=e.lotOccupancyOccupants,r(),s()):bulmaJS.alert({title:"Error Updating "+exports.aliases.occupant,message:e.errorMessage,contextualColorName:"danger"})})};cityssm.openHtmlModal("lotOccupancy-editOccupant",{onshow:t=>{e.populateAliases(t),t.querySelector("#lotOccupancyOccupantEdit--lotOccupancyId").value=c,t.querySelector("#lotOccupancyOccupantEdit--lotOccupantIndex").value=n.toString();const o=t.querySelector("#lotOccupancyOccupantEdit--lotOccupantTypeId");let a=!1;for(const e of exports.lotOccupantTypes){const t=document.createElement("option");t.value=e.lotOccupantTypeId.toString(),t.textContent=e.lotOccupantType,e.lotOccupantTypeId===l.lotOccupantTypeId&&(t.selected=!0,a=!0),o.append(t)}if(!a){const e=document.createElement("option");e.value=l.lotOccupantTypeId.toString(),e.textContent=l.lotOccupantType,e.selected=!0,o.append(e)}t.querySelector("#lotOccupancyOccupantEdit--occupantName").value=l.occupantName,t.querySelector("#lotOccupancyOccupantEdit--occupantAddress1").value=l.occupantAddress1,t.querySelector("#lotOccupancyOccupantEdit--occupantAddress2").value=l.occupantAddress2,t.querySelector("#lotOccupancyOccupantEdit--occupantCity").value=l.occupantCity,t.querySelector("#lotOccupancyOccupantEdit--occupantProvince").value=l.occupantProvince,t.querySelector("#lotOccupancyOccupantEdit--occupantPostalCode").value=l.occupantPostalCode,t.querySelector("#lotOccupancyOccupantEdit--occupantPhoneNumber").value=l.occupantPhoneNumber},onshown:(e,t)=>{bulmaJS.toggleHtmlClipped(),(u=e.querySelector("form")).addEventListener("submit",p),r=t},onremoved:()=>{bulmaJS.toggleHtmlClipped()}})},n=e=>{const a=e.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(t+"/lotOccupancies/doDeleteLotOccupancyOccupant",{lotOccupancyId:c,lotOccupantIndex:a},e=>{e.success?(o=e.lotOccupancyOccupants,s()):bulmaJS.alert({title:"Error Removing "+exports.aliases.occupant,message:e.errorMessage,contextualColorName:"danger"})})}},contextualColorName:"warning"})},s=()=>{const e=document.querySelector("#container--lotOccupancyOccupants");if(cityssm.clearElement(e),0===o.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+"AddressPhone Number";for(const e of o){const c=document.createElement("tr");c.dataset.lotOccupantIndex=e.lotOccupantIndex.toString(),c.innerHTML=""+cityssm.escapeHTML(e.lotOccupantType)+""+cityssm.escapeHTML(e.occupantName)+""+cityssm.escapeHTML(e.occupantAddress1)+"
"+(e.occupantAddress2?cityssm.escapeHTML(e.occupantAddress2)+"
":"")+cityssm.escapeHTML(e.occupantCity)+", "+cityssm.escapeHTML(e.occupantProvince)+"
"+cityssm.escapeHTML(e.occupantPostalCode)+""+cityssm.escapeHTML(e.occupantPhoneNumber)+'
',c.querySelector(".button--edit").addEventListener("click",a),c.querySelector(".button--delete").addEventListener("click",n),t.querySelector("tbody").append(c)}e.append(t)};document.querySelector("#button--addOccupant").addEventListener("click",()=>{let a,n;const l=e=>{e.preventDefault(),cityssm.postJSON(t+"/lotOccupancies/doAddLotOccupancyOccupant",a,e=>{e.success?(o=e.lotOccupancyOccupants,n(),s()):bulmaJS.alert({title:"Error Adding "+exports.aliases.occupant,message:e.errorMessage,contextualColorName:"danger"})})};cityssm.openHtmlModal("lotOccupancy-addOccupant",{onshow:t=>{e.populateAliases(t),t.querySelector("#lotOccupancyOccupantAdd--lotOccupancyId").value=c;const o=t.querySelector("#lotOccupancyOccupantAdd--lotOccupantTypeId");for(const e of exports.lotOccupantTypes){const t=document.createElement("option");t.value=e.lotOccupantTypeId.toString(),t.textContent=e.lotOccupantType,o.append(t)}t.querySelector("#lotOccupancyOccupantAdd--occupantCity").value=exports.occupantCityDefault,t.querySelector("#lotOccupancyOccupantAdd--occupantProvince").value=exports.occupantProvinceDefault},onshown:(e,t)=>{bulmaJS.toggleHtmlClipped(),(a=e.querySelector("form")).addEventListener("submit",l),n=t},onremoved:()=>{bulmaJS.toggleHtmlClipped()}})}),s()}if(!o){let o=exports.lotOccupancyComments;const a=a=>{const n=Number.parseInt(a.currentTarget.closest("tr").dataset.lotOccupancyCommentId,10),l=o.find(e=>e.lotOccupancyCommentId===n);let u,r;const p=e=>{e.preventDefault(),cityssm.postJSON(t+"/lotOccupancies/doUpdateLotOccupancyComment",u,e=>{e.success?(o=e.lotOccupancyComments,r(),s()):bulmaJS.alert({title:"Error Updating Comment",message:e.errorMessage,contextualColorName:"danger"})})};cityssm.openHtmlModal("lotOccupancy-editComment",{onshow:t=>{e.populateAliases(t),t.querySelector("#lotOccupancyCommentEdit--lotOccupancyId").value=c,t.querySelector("#lotOccupancyCommentEdit--lotOccupancyCommentId").value=n.toString(),t.querySelector("#lotOccupancyCommentEdit--lotOccupancyComment").value=l.lotOccupancyComment,t.querySelector("#lotOccupancyCommentEdit--lotOccupancyCommentDateString").value=l.lotOccupancyCommentDateString,t.querySelector("#lotOccupancyCommentEdit--lotOccupancyCommentTimeString").value=l.lotOccupancyCommentTimeString},onshown:(e,t)=>{bulmaJS.toggleHtmlClipped(),(u=e.querySelector("form")).addEventListener("submit",p),r=t},onremoved:()=>{bulmaJS.toggleHtmlClipped()}})},n=e=>{const a=Number.parseInt(e.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(t+"/lotOccupancies/doDeleteLotOccupancyComment",{lotOccupancyId:c,lotOccupancyCommentId:a},e=>{e.success?(o=e.lotOccupancyComments,s()):bulmaJS.alert({title:"Error Removing Comment",message:e.errorMessage,contextualColorName:"danger"})})}},contextualColorName:"warning"})},s=()=>{const e=document.querySelector("#container--lotOccupancyComments");if(0===o.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 o){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",n),t.querySelector("tbody").append(c)}e.innerHTML="",e.append(t)};document.querySelector("#button--addComment").addEventListener("click",()=>{let a,n;const l=e=>{e.preventDefault(),cityssm.postJSON(t+"/lotOccupancies/doAddLotOccupancyComment",a,e=>{e.success?(o=e.lotOccupancyComments,n(),s()):bulmaJS.alert({title:"Error Adding Comment",message:e.errorMessage,contextualColorName:"danger"})})};cityssm.openHtmlModal("lotOccupancy-addComment",{onshow:t=>{e.populateAliases(t),t.querySelector("#lotOccupancyCommentAdd--lotOccupancyId").value=c},onshown:(e,t)=>{bulmaJS.toggleHtmlClipped(),(a=e.querySelector("form")).addEventListener("submit",l),n=t},onremoved:()=>{bulmaJS.toggleHtmlClipped()}})}),s()}})(); \ No newline at end of file diff --git a/routes/lotOccupancies.js b/routes/lotOccupancies.js index 7dfaa929..1ef4f3e9 100644 --- a/routes/lotOccupancies.js +++ b/routes/lotOccupancies.js @@ -10,6 +10,9 @@ import handler_doUpdateLotOccupancy from "../handlers/lotOccupancies-post/doUpda import handler_doAddLotOccupancyOccupant from "../handlers/lotOccupancies-post/doAddLotOccupancyOccupant.js"; import handler_doUpdateLotOccupancyOccupant from "../handlers/lotOccupancies-post/doUpdateLotOccupancyOccupant.js"; import handler_doDeleteLotOccupancyOccupant from "../handlers/lotOccupancies-post/doDeleteLotOccupancyOccupant.js"; +import handler_doAddLotOccupancyComment from "../handlers/lotOccupancies-post/doAddLotOccupancyComment.js"; +import handler_doUpdateLotOccupancyComment from "../handlers/lotOccupancies-post/doUpdateLotOccupancyComment.js"; +import handler_doDeleteLotOccupancyComment from "../handlers/lotOccupancies-post/doDeleteLotOccupancyComment.js"; import * as permissionHandlers from "../handlers/permissions.js"; export const router = Router(); router.get("/", handler_search); @@ -23,4 +26,7 @@ router.post("/doUpdateLotOccupancy", permissionHandlers.updatePostHandler, handl router.post("/doAddLotOccupancyOccupant", permissionHandlers.updatePostHandler, handler_doAddLotOccupancyOccupant); router.post("/doUpdateLotOccupancyOccupant", permissionHandlers.updatePostHandler, handler_doUpdateLotOccupancyOccupant); router.post("/doDeleteLotOccupancyOccupant", permissionHandlers.updatePostHandler, handler_doDeleteLotOccupancyOccupant); +router.post("/doAddLotOccupancyComment", permissionHandlers.updatePostHandler, handler_doAddLotOccupancyComment); +router.post("/doUpdateLotOccupancyComment", permissionHandlers.updatePostHandler, handler_doUpdateLotOccupancyComment); +router.post("/doDeleteLotOccupancyComment", permissionHandlers.updatePostHandler, handler_doDeleteLotOccupancyComment); export default router; diff --git a/routes/lotOccupancies.ts b/routes/lotOccupancies.ts index 0afd766d..0cdd37c7 100644 --- a/routes/lotOccupancies.ts +++ b/routes/lotOccupancies.ts @@ -18,6 +18,10 @@ import handler_doAddLotOccupancyOccupant from "../handlers/lotOccupancies-post/d import handler_doUpdateLotOccupancyOccupant from "../handlers/lotOccupancies-post/doUpdateLotOccupancyOccupant.js"; import handler_doDeleteLotOccupancyOccupant from "../handlers/lotOccupancies-post/doDeleteLotOccupancyOccupant.js"; +import handler_doAddLotOccupancyComment from "../handlers/lotOccupancies-post/doAddLotOccupancyComment.js"; +import handler_doUpdateLotOccupancyComment from "../handlers/lotOccupancies-post/doUpdateLotOccupancyComment.js"; +import handler_doDeleteLotOccupancyComment from "../handlers/lotOccupancies-post/doDeleteLotOccupancyComment.js"; + import * as permissionHandlers from "../handlers/permissions.js"; @@ -69,5 +73,17 @@ router.post("/doDeleteLotOccupancyOccupant", permissionHandlers.updatePostHandler, handler_doDeleteLotOccupancyOccupant); +router.post("/doAddLotOccupancyComment", + permissionHandlers.updatePostHandler, + handler_doAddLotOccupancyComment); + +router.post("/doUpdateLotOccupancyComment", + permissionHandlers.updatePostHandler, + handler_doUpdateLotOccupancyComment); + +router.post("/doDeleteLotOccupancyComment", + permissionHandlers.updatePostHandler, + handler_doDeleteLotOccupancyComment); + export default router; \ No newline at end of file diff --git a/temp/legacy.importFromCSV.js b/temp/legacy.importFromCSV.js index a4730d13..5c7f4e19 100644 --- a/temp/legacy.importFromCSV.js +++ b/temp/legacy.importFromCSV.js @@ -181,7 +181,8 @@ function importFromCSV() { occupancyTypeId: preneedOccupancyType.occupancyTypeId, lotId, occupancyStartDateString, - occupancyEndDateString + occupancyEndDateString, + occupancyTypeFieldIds: "" }, user); const occupantPostalCode = ((masterRow.CM_POST1 || "") + " " + (masterRow.CM_POST2 || "")).trim(); addLotOccupancyOccupant({ @@ -228,7 +229,8 @@ function importFromCSV() { occupancyTypeId: deceasedOccupancyType.occupancyTypeId, lotId, occupancyStartDateString, - occupancyEndDateString + occupancyEndDateString, + occupancyTypeFieldIds: "" }, user); const deceasedPostalCode = ((masterRow.CM_POST1 || "") + " " + (masterRow.CM_POST2 || "")).trim(); addLotOccupancyOccupant({ diff --git a/temp/legacy.importFromCSV.ts b/temp/legacy.importFromCSV.ts index d3405b8a..456c69d6 100644 --- a/temp/legacy.importFromCSV.ts +++ b/temp/legacy.importFromCSV.ts @@ -329,7 +329,8 @@ function importFromCSV() { occupancyTypeId: preneedOccupancyType.occupancyTypeId, lotId, occupancyStartDateString, - occupancyEndDateString + occupancyEndDateString, + occupancyTypeFieldIds: "" }, user); const occupantPostalCode = ((masterRow.CM_POST1 || "") + " " + (masterRow.CM_POST2 || "")).trim(); @@ -392,7 +393,8 @@ function importFromCSV() { occupancyTypeId: deceasedOccupancyType.occupancyTypeId, lotId, occupancyStartDateString, - occupancyEndDateString + occupancyEndDateString, + occupancyTypeFieldIds: "" }, user); const deceasedPostalCode = ((masterRow.CM_POST1 || "") + " " + (masterRow.CM_POST2 || "")).trim(); diff --git a/views/lotOccupancy-edit.ejs b/views/lotOccupancy-edit.ejs index 6443b644..3e7d836b 100644 --- a/views/lotOccupancy-edit.ejs +++ b/views/lotOccupancy-edit.ejs @@ -202,9 +202,25 @@
-

Comments

+
+
+
+

Comments

+
+
+
+
+ +
+
+
+ +
diff --git a/views/lotOccupancy-view.ejs b/views/lotOccupancy-view.ejs index b6126f59..9abd85f6 100644 --- a/views/lotOccupancy-view.ejs +++ b/views/lotOccupancy-view.ejs @@ -81,8 +81,10 @@ <% if (lotOccupancy.lotOccupancyOccupants.length === 0) { %>
-

There are no <%= configFunctions.getProperty("aliases.occupants").toLowerCase() %> - associated with this record.

+

+ There are no <%= configFunctions.getProperty("aliases.occupants").toLowerCase() %> + associated with this record. +

<% } else { %> @@ -118,6 +120,27 @@ <% if (lotOccupancy.lotOccupancyComments.length > 0) { %>

Comments

+
+ + + + + + + + + <% for (const lotOccupancyComment of lotOccupancy.lotOccupancyComments) { %> + + + + + + <% } %> + +
CommentorComment DateComment
<%= lotOccupancyComment.recordCreate_userName %> + <%= lotOccupancyComment.lotOccupancyCommentDateString %> + <%= (lotOccupancyComment.lotOccupancyCommentTime === 0 ? "" : lotOccupancyComment.lotOccupancyCommentTimeString) %> + <%= lotOccupancyComment.lotOccupancyComment %>
<% } %>