From e5b2d5da4f0f236a0b4e240004ef73f19d146570 Mon Sep 17 00:00:00 2001 From: Dan Gowans Date: Tue, 26 Jul 2022 16:13:37 -0400 Subject: [PATCH] development --- helpers/lotOccupancyDB/addLotComment.d.ts | 7 +++ helpers/lotOccupancyDB/addLotComment.js | 17 +++++++ helpers/lotOccupancyDB/addLotComment.ts | 43 ++++++++++++++++ public-typescript/lotEdit.js | 40 ++++++++++++++- public-typescript/lotEdit.ts | 62 ++++++++++++++++++++++- public-typescript/main.js | 16 +++++- public-typescript/main.ts | 22 +++++++- public/html/lotComment-add.html | 29 +++++++++++ public/javascripts/lotEdit.min.js | 2 +- public/javascripts/main.min.js | 2 +- types/globalTypes.d.ts | 1 + types/globalTypes.ts | 1 + types/recordTypes.js | 3 +- views/lot-edit.ejs | 23 ++++++--- 14 files changed, 254 insertions(+), 14 deletions(-) create mode 100644 helpers/lotOccupancyDB/addLotComment.d.ts create mode 100644 helpers/lotOccupancyDB/addLotComment.js create mode 100644 helpers/lotOccupancyDB/addLotComment.ts create mode 100644 public/html/lotComment-add.html diff --git a/helpers/lotOccupancyDB/addLotComment.d.ts b/helpers/lotOccupancyDB/addLotComment.d.ts new file mode 100644 index 00000000..4b6b2634 --- /dev/null +++ b/helpers/lotOccupancyDB/addLotComment.d.ts @@ -0,0 +1,7 @@ +import type * as recordTypes from "../../types/recordTypes"; +interface AddLotCommentForm { + lotId: string; + lotComment: string; +} +export declare const addLotComment: (lotCommentForm: AddLotCommentForm, requestSession: recordTypes.PartialSession) => number; +export default addLotComment; diff --git a/helpers/lotOccupancyDB/addLotComment.js b/helpers/lotOccupancyDB/addLotComment.js new file mode 100644 index 00000000..49cb4ad5 --- /dev/null +++ b/helpers/lotOccupancyDB/addLotComment.js @@ -0,0 +1,17 @@ +import sqlite from "better-sqlite3"; +import { lotOccupancyDB as databasePath } from "../../data/databasePaths.js"; +import * as dateTimeFunctions from "@cityssm/expressjs-server-js/dateTimeFns.js"; +export const addLotComment = (lotCommentForm, requestSession) => { + const database = sqlite(databasePath); + const rightNow = new Date(); + const result = database + .prepare("insert into LotComments (" + + "lotId, lotCommentDate, lotCommentTime, lotComment," + + " recordCreate_userName, recordCreate_timeMillis," + + " recordUpdate_userName, recordUpdate_timeMillis)" + + " values (?, ?, ?, ?, ?, ?, ?, ?)") + .run(lotCommentForm.lotId, dateTimeFunctions.dateToInteger(rightNow), dateTimeFunctions.dateToTimeInteger(rightNow), lotCommentForm.lotComment, requestSession.user.userName, rightNow.getTime(), requestSession.user.userName, rightNow.getTime()); + database.close(); + return result.lastInsertRowid; +}; +export default addLotComment; diff --git a/helpers/lotOccupancyDB/addLotComment.ts b/helpers/lotOccupancyDB/addLotComment.ts new file mode 100644 index 00000000..5633eed9 --- /dev/null +++ b/helpers/lotOccupancyDB/addLotComment.ts @@ -0,0 +1,43 @@ +import sqlite from "better-sqlite3"; +import { lotOccupancyDB as databasePath } from "../../data/databasePaths.js"; + +import * as dateTimeFunctions from "@cityssm/expressjs-server-js/dateTimeFns.js"; + +import type * as recordTypes from "../../types/recordTypes"; + + +interface AddLotCommentForm { + lotId: string; + lotComment: string; +} + + +export const addLotComment = + (lotCommentForm: AddLotCommentForm, requestSession: recordTypes.PartialSession): number => { + + const database = sqlite(databasePath); + + const rightNow = new Date(); + + const result = database + .prepare("insert into LotComments (" + + "lotId, lotCommentDate, lotCommentTime, lotComment," + + " recordCreate_userName, recordCreate_timeMillis," + + " recordUpdate_userName, recordUpdate_timeMillis)" + + " values (?, ?, ?, ?, ?, ?, ?, ?)") + .run(lotCommentForm.lotId, + dateTimeFunctions.dateToInteger(rightNow), + dateTimeFunctions.dateToTimeInteger(rightNow), + lotCommentForm.lotComment, + requestSession.user.userName, + rightNow.getTime(), + requestSession.user.userName, + rightNow.getTime()); + + database.close(); + + return result.lastInsertRowid as number; + }; + + +export default addLotComment; \ No newline at end of file diff --git a/public-typescript/lotEdit.js b/public-typescript/lotEdit.js index 34c89839..909a7883 100644 --- a/public-typescript/lotEdit.js +++ b/public-typescript/lotEdit.js @@ -1,6 +1,7 @@ "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); (() => { + const los = exports.los; const urlPrefix = document.querySelector("main").dataset.urlPrefix; const lotId = document.querySelector("#lot--lotId").value; const isCreate = (lotId === ""); @@ -29,5 +30,42 @@ Object.defineProperty(exports, "__esModule", { value: true }); }); }; formElement.addEventListener("submit", updateLot); - exports.los.initializeUnlockFieldButtons(formElement); + los.initializeUnlockFieldButtons(formElement); + let lotComments = exports.lotComments; + const renderLotComments = () => { + const lotCommentsContainerElement = document.querySelector("#container--lotComments"); + }; + const openAddCommentModal = () => { + let addCommentCloseModalFunction; + const doAddComment = (formEvent) => { + formEvent.preventDefault(); + cityssm.postJSON(urlPrefix + "/lots/doAddLotComment", formEvent.currentTarget, (responseJSON) => { + if (responseJSON.success) { + lotComments = responseJSON.lotComments; + renderLotComments(); + addCommentCloseModalFunction(); + } + }); + }; + cityssm.openHtmlModal("lotComment-add", { + onshow(modalElement) { + los.populateAliases(modalElement); + modalElement.querySelector("#lotCommentAdd--lotId").value = lotId; + modalElement.querySelector("form").addEventListener("submit", doAddComment); + }, + onshown(modalElement, closeModalFunction) { + bulmaJS.toggleHtmlClipped(); + addCommentCloseModalFunction = closeModalFunction; + modalElement.querySelector("#lotCommentAdd--lotComment").focus(); + }, + onremoved() { + bulmaJS.toggleHtmlClipped(); + document.querySelector("#lotComments--add").focus(); + } + }); + }; + if (!isCreate) { + document.querySelector("#lotComments--add").addEventListener("click", openAddCommentModal); + renderLotComments(); + } })(); diff --git a/public-typescript/lotEdit.ts b/public-typescript/lotEdit.ts index 83354cdb..4c4e4842 100644 --- a/public-typescript/lotEdit.ts +++ b/public-typescript/lotEdit.ts @@ -1,22 +1,29 @@ /* eslint-disable unicorn/prefer-module */ import type * as globalTypes from "../types/globalTypes"; +import type * as recordTypes from "../types/recordTypes"; import type { cityssmGlobal } from "@cityssm/bulma-webapp-js/src/types"; -import type { BulmaJS } from "@cityssm/bulma-js/types"; +import type { + BulmaJS +} from "@cityssm/bulma-js/types"; declare const cityssm: cityssmGlobal; declare const bulmaJS: BulmaJS; (() => { + const los = (exports.los as globalTypes.LOS); + const urlPrefix = document.querySelector("main").dataset.urlPrefix; const lotId = (document.querySelector("#lot--lotId") as HTMLInputElement).value; const isCreate = (lotId === ""); + // Main form + const formElement = document.querySelector("#form--lot") as HTMLFormElement; const updateLot = (formEvent: SubmitEvent) => { @@ -49,5 +56,56 @@ declare const bulmaJS: BulmaJS; formElement.addEventListener("submit", updateLot); - (exports.los as globalTypes.LOS).initializeUnlockFieldButtons(formElement); + los.initializeUnlockFieldButtons(formElement); + + // Comments + + let lotComments: recordTypes.LotComment[] = exports.lotComments; + + const renderLotComments = () => { + + const lotCommentsContainerElement = document.querySelector("#container--lotComments") as HTMLElement; + }; + + const openAddCommentModal = () => { + + let addCommentCloseModalFunction: () => void; + + const doAddComment = (formEvent: SubmitEvent) => { + formEvent.preventDefault(); + + cityssm.postJSON(urlPrefix + "/lots/doAddLotComment", + formEvent.currentTarget, + (responseJSON: {success: boolean; lotComments?: recordTypes.LotComment[]}) => { + + if (responseJSON.success) { + lotComments = responseJSON.lotComments; + renderLotComments(); + addCommentCloseModalFunction(); + } + }); + }; + + cityssm.openHtmlModal("lotComment-add", { + onshow(modalElement) { + los.populateAliases(modalElement); + (modalElement.querySelector("#lotCommentAdd--lotId") as HTMLInputElement).value = lotId; + modalElement.querySelector("form").addEventListener("submit", doAddComment); + }, + onshown(modalElement, closeModalFunction) { + bulmaJS.toggleHtmlClipped(); + addCommentCloseModalFunction = closeModalFunction; + (modalElement.querySelector("#lotCommentAdd--lotComment") as HTMLTextAreaElement).focus(); + }, + onremoved() { + bulmaJS.toggleHtmlClipped(); + (document.querySelector("#lotComments--add") as HTMLButtonElement).focus(); + } + }); + }; + + if (!isCreate) { + document.querySelector("#lotComments--add").addEventListener("click", openAddCommentModal); + renderLotComments(); + } })(); \ No newline at end of file diff --git a/public-typescript/main.js b/public-typescript/main.js index d027eef0..d7904376 100644 --- a/public-typescript/main.js +++ b/public-typescript/main.js @@ -41,9 +41,23 @@ Object.defineProperty(exports, "__esModule", { value: true }); unlockFieldButtonElement.addEventListener("click", unlockField); } }; + const populateAliases = (containerElement) => { + const aliasElements = containerElement.querySelectorAll(".alias"); + for (const aliasElement of aliasElements) { + switch (aliasElement.dataset.alias) { + case "Lot": + aliasElement.textContent = exports.aliases.lot; + break; + case "lot": + aliasElement.textContent = exports.aliases.lot.toLowerCase(); + break; + } + } + }; const los = { highlightMap, - initializeUnlockFieldButtons + initializeUnlockFieldButtons, + populateAliases }; exports.los = los; })(); diff --git a/public-typescript/main.ts b/public-typescript/main.ts index f1c31601..6f2f6977 100644 --- a/public-typescript/main.ts +++ b/public-typescript/main.ts @@ -68,9 +68,29 @@ import type * as globalTypes from "../types/globalTypes"; } }; + const populateAliases = (containerElement: HTMLElement) => { + + const aliasElements = containerElement.querySelectorAll(".alias") as NodeListOf; + + for (const aliasElement of aliasElements) { + + switch (aliasElement.dataset.alias) { + + case "Lot": + aliasElement.textContent = exports.aliases.lot; + break; + + case "lot": + aliasElement.textContent = exports.aliases.lot.toLowerCase(); + break; + } + } + }; + const los: globalTypes.LOS = { highlightMap, - initializeUnlockFieldButtons + initializeUnlockFieldButtons, + populateAliases }; exports.los = los; diff --git a/public/html/lotComment-add.html b/public/html/lotComment-add.html new file mode 100644 index 00000000..acbb9ebb --- /dev/null +++ b/public/html/lotComment-add.html @@ -0,0 +1,29 @@ + \ No newline at end of file diff --git a/public/javascripts/lotEdit.min.js b/public/javascripts/lotEdit.min.js index 911f495c..cc0e4b47 100644 --- a/public/javascripts/lotEdit.min.js +++ b/public/javascripts/lotEdit.min.js @@ -1 +1 @@ -"use strict";Object.defineProperty(exports,"__esModule",{value:!0}),(()=>{const e=document.querySelector("main").dataset.urlPrefix,t=""===document.querySelector("#lot--lotId").value,o=document.querySelector("#form--lot");o.addEventListener("submit",s=>{s.preventDefault(),cityssm.postJSON(e+"/lots/"+(t?"doCreateLot":"doUpdateLot"),o,o=>{o.success?t?window.location.href=e+"/lots/"+o.lotId+"/edit":bulmaJS.alert({message:exports.aliases.lot+" Updated Successfully",contextualColorName:"success"}):bulmaJS.alert({title:"Error Updating "+exports.aliases.lot,message:o.errorMessage,contextualColorName:"danger"})})}),exports.los.initializeUnlockFieldButtons(o)})(); \ No newline at end of file +"use strict";Object.defineProperty(exports,"__esModule",{value:!0}),(()=>{const e=exports.los,t=document.querySelector("main").dataset.urlPrefix,o=document.querySelector("#lot--lotId").value,l=""===o,s=document.querySelector("#form--lot");s.addEventListener("submit",e=>{e.preventDefault(),cityssm.postJSON(t+"/lots/"+(l?"doCreateLot":"doUpdateLot"),s,e=>{e.success?l?window.location.href=t+"/lots/"+e.lotId+"/edit":bulmaJS.alert({message:exports.aliases.lot+" Updated Successfully",contextualColorName:"success"}):bulmaJS.alert({title:"Error Updating "+exports.aliases.lot,message:e.errorMessage,contextualColorName:"danger"})})}),e.initializeUnlockFieldButtons(s);let r=exports.lotComments;const m=()=>{document.querySelector("#container--lotComments")},n=()=>{let l;const s=e=>{e.preventDefault(),cityssm.postJSON(t+"/lots/doAddLotComment",e.currentTarget,e=>{e.success&&(r=e.lotComments,m(),l())})};cityssm.openHtmlModal("lotComment-add",{onshow(t){e.populateAliases(t),t.querySelector("#lotCommentAdd--lotId").value=o,t.querySelector("form").addEventListener("submit",s)},onshown(e,t){bulmaJS.toggleHtmlClipped(),l=t,e.querySelector("#lotCommentAdd--lotComment").focus()},onremoved(){bulmaJS.toggleHtmlClipped(),document.querySelector("#lotComments--add").focus()}})};l||(document.querySelector("#lotComments--add").addEventListener("click",n),m())})(); \ No newline at end of file diff --git a/public/javascripts/main.min.js b/public/javascripts/main.min.js index aa21e6d1..d8bf923b 100644 --- a/public/javascripts/main.min.js +++ b/public/javascripts/main.min.js @@ -1 +1 @@ -"use strict";Object.defineProperty(exports,"__esModule",{value:!0}),(()=>{const e=e=>{const l=e.currentTarget.closest(".field").querySelector("input, select");if("INPUT"===l.tagName)l.disabled=!1;else{const e=l.querySelectorAll("option");for(const l of e)l.disabled=!1}l.focus()},l={highlightMap:(e,l,t)=>{let o,s=l;for(;!(o=e.querySelector("#"+s))&&s.includes("-");)s=s.slice(0,Math.max(0,s.lastIndexOf("-"))),console.log(s);if(o){o.style.fill=null,o.classList.add("highlight","is-"+t);const e=o.querySelectorAll("path");for(const l of e)l.style.fill=null}},initializeUnlockFieldButtons:l=>{const t=l.querySelectorAll(".is-unlock-field-button");for(const l of t)l.addEventListener("click",e)}};exports.los=l})(); \ No newline at end of file +"use strict";Object.defineProperty(exports,"__esModule",{value:!0}),(()=>{const e=e=>{const t=e.currentTarget.closest(".field").querySelector("input, select");if("INPUT"===t.tagName)t.disabled=!1;else{const e=t.querySelectorAll("option");for(const t of e)t.disabled=!1}t.focus()},t={highlightMap:(e,t,l)=>{let o,s=t;for(;!(o=e.querySelector("#"+s))&&s.includes("-");)s=s.slice(0,Math.max(0,s.lastIndexOf("-"))),console.log(s);if(o){o.style.fill=null,o.classList.add("highlight","is-"+l);const e=o.querySelectorAll("path");for(const t of e)t.style.fill=null}},initializeUnlockFieldButtons:t=>{const l=t.querySelectorAll(".is-unlock-field-button");for(const t of l)t.addEventListener("click",e)},populateAliases:e=>{const t=e.querySelectorAll(".alias");for(const e of t)switch(e.dataset.alias){case"Lot":e.textContent=exports.aliases.lot;break;case"lot":e.textContent=exports.aliases.lot.toLowerCase()}}};exports.los=t})(); \ No newline at end of file diff --git a/types/globalTypes.d.ts b/types/globalTypes.d.ts index 806f661b..6b2becc9 100644 --- a/types/globalTypes.d.ts +++ b/types/globalTypes.d.ts @@ -1,4 +1,5 @@ export interface LOS { highlightMap: (mapContainerElement: HTMLElement, mapKey: string, contextualClass: "success" | "danger") => void; initializeUnlockFieldButtons: (containerElement: HTMLElement) => void; + populateAliases: (containerElement: HTMLElement) => void; } diff --git a/types/globalTypes.ts b/types/globalTypes.ts index 806f661b..6b2becc9 100644 --- a/types/globalTypes.ts +++ b/types/globalTypes.ts @@ -1,4 +1,5 @@ export interface LOS { highlightMap: (mapContainerElement: HTMLElement, mapKey: string, contextualClass: "success" | "danger") => void; initializeUnlockFieldButtons: (containerElement: HTMLElement) => void; + populateAliases: (containerElement: HTMLElement) => void; } diff --git a/types/recordTypes.js b/types/recordTypes.js index cb0ff5c3..c8ad2e54 100644 --- a/types/recordTypes.js +++ b/types/recordTypes.js @@ -1 +1,2 @@ -export {}; +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); diff --git a/views/lot-edit.ejs b/views/lot-edit.ejs index 9b81aa7a..b657f4b8 100644 --- a/views/lot-edit.ejs +++ b/views/lot-edit.ejs @@ -93,7 +93,7 @@
-