diff --git a/handlers/admin-get/lotTypes.d.ts b/handlers/admin-get/lotTypes.d.ts new file mode 100644 index 00000000..9621c611 --- /dev/null +++ b/handlers/admin-get/lotTypes.d.ts @@ -0,0 +1,3 @@ +import type { RequestHandler } from "express"; +export declare const handler: RequestHandler; +export default handler; diff --git a/handlers/admin-get/lotTypes.js b/handlers/admin-get/lotTypes.js new file mode 100644 index 00000000..2ed26b2a --- /dev/null +++ b/handlers/admin-get/lotTypes.js @@ -0,0 +1,10 @@ +import { getLotTypes } from "../../helpers/functions.cache.js"; +import * as configFunctions from "../../helpers/functions.config.js"; +export const handler = (_request, response) => { + const lotTypes = getLotTypes(); + response.render("admin-lotTypes", { + headTitle: configFunctions.getProperty("aliases.lot") + " Type Management", + lotTypes + }); +}; +export default handler; diff --git a/handlers/admin-get/lotTypes.ts b/handlers/admin-get/lotTypes.ts new file mode 100644 index 00000000..eea73f9a --- /dev/null +++ b/handlers/admin-get/lotTypes.ts @@ -0,0 +1,16 @@ +import type { RequestHandler } from "express"; + +import { getLotTypes } from "../../helpers/functions.cache.js"; + +import * as configFunctions from "../../helpers/functions.config.js"; + +export const handler: RequestHandler = (_request, response) => { + const lotTypes = getLotTypes(); + + response.render("admin-lotTypes", { + headTitle: configFunctions.getProperty("aliases.lot") + " Type Management", + lotTypes + }); +}; + +export default handler; diff --git a/handlers/admin-get/occupancyTypes.js b/handlers/admin-get/occupancyTypes.js index 9dfc77de..31a8f1a3 100644 --- a/handlers/admin-get/occupancyTypes.js +++ b/handlers/admin-get/occupancyTypes.js @@ -4,8 +4,7 @@ export const handler = (_request, response) => { const occupancyTypes = getOccupancyTypes(); const allOccupancyTypeFields = getAllOccupancyTypeFields(); response.render("admin-occupancyTypes", { - headTitle: configFunctions.getProperty("aliases.occupancy") + - " Type Management", + headTitle: configFunctions.getProperty("aliases.occupancy") + " Type Management", occupancyTypes, allOccupancyTypeFields }); diff --git a/handlers/admin-get/occupancyTypes.ts b/handlers/admin-get/occupancyTypes.ts index f950aa44..260abe7b 100644 --- a/handlers/admin-get/occupancyTypes.ts +++ b/handlers/admin-get/occupancyTypes.ts @@ -9,9 +9,7 @@ export const handler: RequestHandler = (_request, response) => { const allOccupancyTypeFields = getAllOccupancyTypeFields(); response.render("admin-occupancyTypes", { - headTitle: - configFunctions.getProperty("aliases.occupancy") + - " Type Management", + headTitle: configFunctions.getProperty("aliases.occupancy") + " Type Management", occupancyTypes, allOccupancyTypeFields }); diff --git a/handlers/admin-post/doAddLotType.d.ts b/handlers/admin-post/doAddLotType.d.ts new file mode 100644 index 00000000..9621c611 --- /dev/null +++ b/handlers/admin-post/doAddLotType.d.ts @@ -0,0 +1,3 @@ +import type { RequestHandler } from "express"; +export declare const handler: RequestHandler; +export default handler; diff --git a/handlers/admin-post/doAddLotType.js b/handlers/admin-post/doAddLotType.js new file mode 100644 index 00000000..2831a4ea --- /dev/null +++ b/handlers/admin-post/doAddLotType.js @@ -0,0 +1,12 @@ +import { addLotType } from "../../helpers/lotOccupancyDB/addLotType.js"; +import { getLotTypes } from "../../helpers/functions.cache.js"; +export const handler = async (request, response) => { + const lotTypeId = addLotType(request.body, request.session); + const lotTypes = getLotTypes(); + response.json({ + success: true, + lotTypeId, + lotTypes + }); +}; +export default handler; diff --git a/handlers/admin-post/doAddLotType.ts b/handlers/admin-post/doAddLotType.ts new file mode 100644 index 00000000..63db8f25 --- /dev/null +++ b/handlers/admin-post/doAddLotType.ts @@ -0,0 +1,19 @@ +import type { RequestHandler } from "express"; + +import { addLotType } from "../../helpers/lotOccupancyDB/addLotType.js"; + +import { getLotTypes } from "../../helpers/functions.cache.js"; + +export const handler: RequestHandler = async (request, response) => { + const lotTypeId = addLotType(request.body, request.session); + + const lotTypes = getLotTypes(); + + response.json({ + success: true, + lotTypeId, + lotTypes + }); +}; + +export default handler; diff --git a/handlers/admin-post/doAddLotTypeField.d.ts b/handlers/admin-post/doAddLotTypeField.d.ts new file mode 100644 index 00000000..9621c611 --- /dev/null +++ b/handlers/admin-post/doAddLotTypeField.d.ts @@ -0,0 +1,3 @@ +import type { RequestHandler } from "express"; +export declare const handler: RequestHandler; +export default handler; diff --git a/handlers/admin-post/doAddLotTypeField.js b/handlers/admin-post/doAddLotTypeField.js new file mode 100644 index 00000000..4696384c --- /dev/null +++ b/handlers/admin-post/doAddLotTypeField.js @@ -0,0 +1,12 @@ +import { addLotTypeField } from "../../helpers/lotOccupancyDB/addLotTypeField.js"; +import { getLotTypes } from "../../helpers/functions.cache.js"; +export const handler = async (request, response) => { + const lotTypeFieldId = addLotTypeField(request.body, request.session); + const lotTypes = getLotTypes(); + response.json({ + success: true, + lotTypeFieldId, + lotTypes + }); +}; +export default handler; diff --git a/handlers/admin-post/doAddLotTypeField.ts b/handlers/admin-post/doAddLotTypeField.ts new file mode 100644 index 00000000..987d1599 --- /dev/null +++ b/handlers/admin-post/doAddLotTypeField.ts @@ -0,0 +1,19 @@ +import type { RequestHandler } from "express"; + +import { addLotTypeField } from "../../helpers/lotOccupancyDB/addLotTypeField.js"; + +import { getLotTypes } from "../../helpers/functions.cache.js"; + +export const handler: RequestHandler = async (request, response) => { + const lotTypeFieldId = addLotTypeField(request.body, request.session); + + const lotTypes = getLotTypes(); + + response.json({ + success: true, + lotTypeFieldId, + lotTypes + }); +}; + +export default handler; diff --git a/handlers/admin-post/doDeleteLotType.d.ts b/handlers/admin-post/doDeleteLotType.d.ts new file mode 100644 index 00000000..9621c611 --- /dev/null +++ b/handlers/admin-post/doDeleteLotType.d.ts @@ -0,0 +1,3 @@ +import type { RequestHandler } from "express"; +export declare const handler: RequestHandler; +export default handler; diff --git a/handlers/admin-post/doDeleteLotType.js b/handlers/admin-post/doDeleteLotType.js new file mode 100644 index 00000000..6b676cc3 --- /dev/null +++ b/handlers/admin-post/doDeleteLotType.js @@ -0,0 +1,11 @@ +import { deleteLotType } from "../../helpers/lotOccupancyDB/deleteLotType.js"; +import { getLotTypes } from "../../helpers/functions.cache.js"; +export const handler = async (request, response) => { + const success = deleteLotType(request.body.lotTypeId, request.session); + const lotTypes = getLotTypes(); + response.json({ + success, + lotTypes + }); +}; +export default handler; diff --git a/handlers/admin-post/doDeleteLotType.ts b/handlers/admin-post/doDeleteLotType.ts new file mode 100644 index 00000000..b7476eb1 --- /dev/null +++ b/handlers/admin-post/doDeleteLotType.ts @@ -0,0 +1,21 @@ +import type { RequestHandler } from "express"; + +import { deleteLotType } from "../../helpers/lotOccupancyDB/deleteLotType.js"; + +import { getLotTypes } from "../../helpers/functions.cache.js"; + +export const handler: RequestHandler = async (request, response) => { + const success = deleteLotType( + request.body.lotTypeId, + request.session + ); + + const lotTypes = getLotTypes(); + + response.json({ + success, + lotTypes + }); +}; + +export default handler; diff --git a/handlers/admin-post/doDeleteLotTypeField.d.ts b/handlers/admin-post/doDeleteLotTypeField.d.ts new file mode 100644 index 00000000..9621c611 --- /dev/null +++ b/handlers/admin-post/doDeleteLotTypeField.d.ts @@ -0,0 +1,3 @@ +import type { RequestHandler } from "express"; +export declare const handler: RequestHandler; +export default handler; diff --git a/handlers/admin-post/doDeleteLotTypeField.js b/handlers/admin-post/doDeleteLotTypeField.js new file mode 100644 index 00000000..c37821e8 --- /dev/null +++ b/handlers/admin-post/doDeleteLotTypeField.js @@ -0,0 +1,11 @@ +import { deleteLotTypeField } from "../../helpers/lotOccupancyDB/deleteLotTypeField.js"; +import { getLotTypes } from "../../helpers/functions.cache.js"; +export const handler = async (request, response) => { + const success = deleteLotTypeField(request.body.lotTypeFieldId, request.session); + const lotTypes = getLotTypes(); + response.json({ + success, + lotTypes + }); +}; +export default handler; diff --git a/handlers/admin-post/doDeleteLotTypeField.ts b/handlers/admin-post/doDeleteLotTypeField.ts new file mode 100644 index 00000000..329b9dd7 --- /dev/null +++ b/handlers/admin-post/doDeleteLotTypeField.ts @@ -0,0 +1,18 @@ +import type { RequestHandler } from "express"; + +import { deleteLotTypeField } from "../../helpers/lotOccupancyDB/deleteLotTypeField.js"; + +import { getLotTypes } from "../../helpers/functions.cache.js"; + +export const handler: RequestHandler = async (request, response) => { + const success = deleteLotTypeField(request.body.lotTypeFieldId, request.session); + + const lotTypes = getLotTypes(); + + response.json({ + success, + lotTypes + }); +}; + +export default handler; diff --git a/handlers/admin-post/doMoveLotTypeDown.d.ts b/handlers/admin-post/doMoveLotTypeDown.d.ts new file mode 100644 index 00000000..9621c611 --- /dev/null +++ b/handlers/admin-post/doMoveLotTypeDown.d.ts @@ -0,0 +1,3 @@ +import type { RequestHandler } from "express"; +export declare const handler: RequestHandler; +export default handler; diff --git a/handlers/admin-post/doMoveLotTypeDown.js b/handlers/admin-post/doMoveLotTypeDown.js new file mode 100644 index 00000000..41fdae5f --- /dev/null +++ b/handlers/admin-post/doMoveLotTypeDown.js @@ -0,0 +1,11 @@ +import { moveLotTypeDown } from "../../helpers/lotOccupancyDB/moveLotTypeDown.js"; +import { getLotTypes } from "../../helpers/functions.cache.js"; +export const handler = async (request, response) => { + const success = moveLotTypeDown(request.body.lotTypeId); + const lotTypes = getLotTypes(); + response.json({ + success, + lotTypes + }); +}; +export default handler; diff --git a/handlers/admin-post/doMoveLotTypeDown.ts b/handlers/admin-post/doMoveLotTypeDown.ts new file mode 100644 index 00000000..1d9980a6 --- /dev/null +++ b/handlers/admin-post/doMoveLotTypeDown.ts @@ -0,0 +1,18 @@ +import type { RequestHandler } from "express"; + +import { moveLotTypeDown } from "../../helpers/lotOccupancyDB/moveLotTypeDown.js"; + +import { getLotTypes } from "../../helpers/functions.cache.js"; + +export const handler: RequestHandler = async (request, response) => { + const success = moveLotTypeDown(request.body.lotTypeId); + + const lotTypes = getLotTypes(); + + response.json({ + success, + lotTypes + }); +}; + +export default handler; diff --git a/handlers/admin-post/doMoveLotTypeFieldDown.d.ts b/handlers/admin-post/doMoveLotTypeFieldDown.d.ts new file mode 100644 index 00000000..9621c611 --- /dev/null +++ b/handlers/admin-post/doMoveLotTypeFieldDown.d.ts @@ -0,0 +1,3 @@ +import type { RequestHandler } from "express"; +export declare const handler: RequestHandler; +export default handler; diff --git a/handlers/admin-post/doMoveLotTypeFieldDown.js b/handlers/admin-post/doMoveLotTypeFieldDown.js new file mode 100644 index 00000000..e0fe0008 --- /dev/null +++ b/handlers/admin-post/doMoveLotTypeFieldDown.js @@ -0,0 +1,11 @@ +import { moveLotTypeFieldDown } from "../../helpers/lotOccupancyDB/moveLotTypeFieldDown.js"; +import { getLotTypes } from "../../helpers/functions.cache.js"; +export const handler = async (request, response) => { + const success = moveLotTypeFieldDown(request.body.lotTypeFieldId); + const lotTypes = getLotTypes(); + response.json({ + success, + lotTypes + }); +}; +export default handler; diff --git a/handlers/admin-post/doMoveLotTypeFieldDown.ts b/handlers/admin-post/doMoveLotTypeFieldDown.ts new file mode 100644 index 00000000..979e09a1 --- /dev/null +++ b/handlers/admin-post/doMoveLotTypeFieldDown.ts @@ -0,0 +1,18 @@ +import type { RequestHandler } from "express"; + +import { moveLotTypeFieldDown } from "../../helpers/lotOccupancyDB/moveLotTypeFieldDown.js"; + +import { getLotTypes } from "../../helpers/functions.cache.js"; + +export const handler: RequestHandler = async (request, response) => { + const success = moveLotTypeFieldDown(request.body.lotTypeFieldId); + + const lotTypes = getLotTypes(); + + response.json({ + success, + lotTypes + }); +}; + +export default handler; diff --git a/handlers/admin-post/doMoveLotTypeFieldUp.d.ts b/handlers/admin-post/doMoveLotTypeFieldUp.d.ts new file mode 100644 index 00000000..9621c611 --- /dev/null +++ b/handlers/admin-post/doMoveLotTypeFieldUp.d.ts @@ -0,0 +1,3 @@ +import type { RequestHandler } from "express"; +export declare const handler: RequestHandler; +export default handler; diff --git a/handlers/admin-post/doMoveLotTypeFieldUp.js b/handlers/admin-post/doMoveLotTypeFieldUp.js new file mode 100644 index 00000000..acad2347 --- /dev/null +++ b/handlers/admin-post/doMoveLotTypeFieldUp.js @@ -0,0 +1,11 @@ +import { moveLotTypeFieldUp } from "../../helpers/lotOccupancyDB/moveLotTypeFieldUp.js"; +import { getLotTypes } from "../../helpers/functions.cache.js"; +export const handler = async (request, response) => { + const success = moveLotTypeFieldUp(request.body.lotTypeFieldId); + const lotTypes = getLotTypes(); + response.json({ + success, + lotTypes + }); +}; +export default handler; diff --git a/handlers/admin-post/doMoveLotTypeFieldUp.ts b/handlers/admin-post/doMoveLotTypeFieldUp.ts new file mode 100644 index 00000000..6758683e --- /dev/null +++ b/handlers/admin-post/doMoveLotTypeFieldUp.ts @@ -0,0 +1,18 @@ +import type { RequestHandler } from "express"; + +import { moveLotTypeFieldUp } from "../../helpers/lotOccupancyDB/moveLotTypeFieldUp.js"; + +import { getLotTypes } from "../../helpers/functions.cache.js"; + +export const handler: RequestHandler = async (request, response) => { + const success = moveLotTypeFieldUp(request.body.lotTypeFieldId); + + const lotTypes = getLotTypes(); + + response.json({ + success, + lotTypes + }); +}; + +export default handler; diff --git a/handlers/admin-post/doMoveLotTypeUp.d.ts b/handlers/admin-post/doMoveLotTypeUp.d.ts new file mode 100644 index 00000000..9621c611 --- /dev/null +++ b/handlers/admin-post/doMoveLotTypeUp.d.ts @@ -0,0 +1,3 @@ +import type { RequestHandler } from "express"; +export declare const handler: RequestHandler; +export default handler; diff --git a/handlers/admin-post/doMoveLotTypeUp.js b/handlers/admin-post/doMoveLotTypeUp.js new file mode 100644 index 00000000..1ad89c88 --- /dev/null +++ b/handlers/admin-post/doMoveLotTypeUp.js @@ -0,0 +1,11 @@ +import { moveLotTypeUp } from "../../helpers/lotOccupancyDB/moveLotTypeUp.js"; +import { getLotTypes } from "../../helpers/functions.cache.js"; +export const handler = async (request, response) => { + const success = moveLotTypeUp(request.body.lotTypeId); + const lotTypes = getLotTypes(); + response.json({ + success, + lotTypes + }); +}; +export default handler; diff --git a/handlers/admin-post/doMoveLotTypeUp.ts b/handlers/admin-post/doMoveLotTypeUp.ts new file mode 100644 index 00000000..57b35777 --- /dev/null +++ b/handlers/admin-post/doMoveLotTypeUp.ts @@ -0,0 +1,18 @@ +import type { RequestHandler } from "express"; + +import { moveLotTypeUp } from "../../helpers/lotOccupancyDB/moveLotTypeUp.js"; + +import { getLotTypes } from "../../helpers/functions.cache.js"; + +export const handler: RequestHandler = async (request, response) => { + const success = moveLotTypeUp(request.body.lotTypeId); + + const lotTypes = getLotTypes(); + + response.json({ + success, + lotTypes + }); +}; + +export default handler; diff --git a/handlers/admin-post/doUpdateLotType.d.ts b/handlers/admin-post/doUpdateLotType.d.ts new file mode 100644 index 00000000..9621c611 --- /dev/null +++ b/handlers/admin-post/doUpdateLotType.d.ts @@ -0,0 +1,3 @@ +import type { RequestHandler } from "express"; +export declare const handler: RequestHandler; +export default handler; diff --git a/handlers/admin-post/doUpdateLotType.js b/handlers/admin-post/doUpdateLotType.js new file mode 100644 index 00000000..731200cb --- /dev/null +++ b/handlers/admin-post/doUpdateLotType.js @@ -0,0 +1,11 @@ +import { updateLotType } from "../../helpers/lotOccupancyDB/updateLotType.js"; +import { getLotTypes } from "../../helpers/functions.cache.js"; +export const handler = async (request, response) => { + const success = updateLotType(request.body, request.session); + const lotTypes = getLotTypes(); + response.json({ + success, + lotTypes + }); +}; +export default handler; diff --git a/handlers/admin-post/doUpdateLotType.ts b/handlers/admin-post/doUpdateLotType.ts new file mode 100644 index 00000000..06828ab3 --- /dev/null +++ b/handlers/admin-post/doUpdateLotType.ts @@ -0,0 +1,18 @@ +import type { RequestHandler } from "express"; + +import { updateLotType } from "../../helpers/lotOccupancyDB/updateLotType.js"; + +import { getLotTypes } from "../../helpers/functions.cache.js"; + +export const handler: RequestHandler = async (request, response) => { + const success = updateLotType(request.body, request.session); + + const lotTypes = getLotTypes(); + + response.json({ + success, + lotTypes + }); +}; + +export default handler; diff --git a/handlers/admin-post/doUpdateLotTypeField.d.ts b/handlers/admin-post/doUpdateLotTypeField.d.ts new file mode 100644 index 00000000..9621c611 --- /dev/null +++ b/handlers/admin-post/doUpdateLotTypeField.d.ts @@ -0,0 +1,3 @@ +import type { RequestHandler } from "express"; +export declare const handler: RequestHandler; +export default handler; diff --git a/handlers/admin-post/doUpdateLotTypeField.js b/handlers/admin-post/doUpdateLotTypeField.js new file mode 100644 index 00000000..1ce4c4a4 --- /dev/null +++ b/handlers/admin-post/doUpdateLotTypeField.js @@ -0,0 +1,11 @@ +import { updateLotTypeField } from "../../helpers/lotOccupancyDB/updateLotTypeField.js"; +import { getLotTypes } from "../../helpers/functions.cache.js"; +export const handler = async (request, response) => { + const success = updateLotTypeField(request.body, request.session); + const lotTypes = getLotTypes(); + response.json({ + success, + lotTypes + }); +}; +export default handler; diff --git a/handlers/admin-post/doUpdateLotTypeField.ts b/handlers/admin-post/doUpdateLotTypeField.ts new file mode 100644 index 00000000..3538e101 --- /dev/null +++ b/handlers/admin-post/doUpdateLotTypeField.ts @@ -0,0 +1,18 @@ +import type { RequestHandler } from "express"; + +import { updateLotTypeField } from "../../helpers/lotOccupancyDB/updateLotTypeField.js"; + +import { getLotTypes } from "../../helpers/functions.cache.js"; + +export const handler: RequestHandler = async (request, response) => { + const success = updateLotTypeField(request.body, request.session); + + const lotTypes = getLotTypes(); + + response.json({ + success, + lotTypes + }); +}; + +export default handler; diff --git a/helpers/lotOccupancyDB/addLotType.js b/helpers/lotOccupancyDB/addLotType.js index 78ed9194..555caec9 100644 --- a/helpers/lotOccupancyDB/addLotType.js +++ b/helpers/lotOccupancyDB/addLotType.js @@ -10,7 +10,7 @@ export const addLotType = (lotTypeForm, requestSession) => { " recordCreate_userName, recordCreate_timeMillis," + " recordUpdate_userName, recordUpdate_timeMillis)" + " values (?, ?, ?, ?, ?, ?)") - .run(lotTypeForm.lotType, lotTypeForm.orderNumber || 0, requestSession.user.userName, rightNowMillis, requestSession.user.userName, rightNowMillis); + .run(lotTypeForm.lotType, lotTypeForm.orderNumber || -1, requestSession.user.userName, rightNowMillis, requestSession.user.userName, rightNowMillis); database.close(); clearLotTypesCache(); return result.lastInsertRowid; diff --git a/helpers/lotOccupancyDB/addLotType.ts b/helpers/lotOccupancyDB/addLotType.ts index 27358c32..32bc2428 100644 --- a/helpers/lotOccupancyDB/addLotType.ts +++ b/helpers/lotOccupancyDB/addLotType.ts @@ -29,7 +29,7 @@ export const addLotType = ( ) .run( lotTypeForm.lotType, - lotTypeForm.orderNumber || 0, + lotTypeForm.orderNumber || -1, requestSession.user.userName, rightNowMillis, requestSession.user.userName, diff --git a/helpers/lotOccupancyDB/addLotTypeField.d.ts b/helpers/lotOccupancyDB/addLotTypeField.d.ts new file mode 100644 index 00000000..12e69860 --- /dev/null +++ b/helpers/lotOccupancyDB/addLotTypeField.d.ts @@ -0,0 +1,13 @@ +import type * as recordTypes from "../../types/recordTypes"; +interface AddLotTypeFieldForm { + lotTypeId: string | number; + lotTypeField: string; + lotTypeFieldValues?: string; + isRequired?: string; + pattern?: string; + minimumLength: string | number; + maximumLength: string | number; + orderNumber?: number; +} +export declare const addLotTypeField: (lotTypeFieldForm: AddLotTypeFieldForm, requestSession: recordTypes.PartialSession) => number; +export default addLotTypeField; diff --git a/helpers/lotOccupancyDB/addLotTypeField.js b/helpers/lotOccupancyDB/addLotTypeField.js new file mode 100644 index 00000000..ee7e712e --- /dev/null +++ b/helpers/lotOccupancyDB/addLotTypeField.js @@ -0,0 +1,21 @@ +import sqlite from "better-sqlite3"; +import { lotOccupancyDB as databasePath } from "../../data/databasePaths.js"; +import { clearLotTypesCache } from "../functions.cache.js"; +export const addLotTypeField = (lotTypeFieldForm, requestSession) => { + const database = sqlite(databasePath); + const rightNowMillis = Date.now(); + const result = database + .prepare("insert into LotTypeFields (" + + "lotTypeId, lotTypeField," + + " lotTypeFieldValues, isRequired, pattern," + + " minimumLength, maximumLength," + + " orderNumber," + + " recordCreate_userName, recordCreate_timeMillis," + + " recordUpdate_userName, recordUpdate_timeMillis)" + + " values (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)") + .run(lotTypeFieldForm.lotTypeId, lotTypeFieldForm.lotTypeField, lotTypeFieldForm.lotTypeFieldValues || "", lotTypeFieldForm.isRequired ? 1 : 0, lotTypeFieldForm.pattern || "", lotTypeFieldForm.minimumLength || 0, lotTypeFieldForm.maximumLength || 100, lotTypeFieldForm.orderNumber || -1, requestSession.user.userName, rightNowMillis, requestSession.user.userName, rightNowMillis); + database.close(); + clearLotTypesCache(); + return result.lastInsertRowid; +}; +export default addLotTypeField; diff --git a/helpers/lotOccupancyDB/addLotTypeField.ts b/helpers/lotOccupancyDB/addLotTypeField.ts new file mode 100644 index 00000000..97f4202b --- /dev/null +++ b/helpers/lotOccupancyDB/addLotTypeField.ts @@ -0,0 +1,60 @@ +import sqlite from "better-sqlite3"; + +import { lotOccupancyDB as databasePath } from "../../data/databasePaths.js"; + +import type * as recordTypes from "../../types/recordTypes"; +import { clearLotTypesCache } from "../functions.cache.js"; + +interface AddLotTypeFieldForm { + lotTypeId: string | number; + lotTypeField: string; + lotTypeFieldValues?: string; + isRequired?: string; + pattern?: string; + minimumLength: string | number; + maximumLength: string | number; + orderNumber?: number; +} + +export const addLotTypeField = ( + lotTypeFieldForm: AddLotTypeFieldForm, + requestSession: recordTypes.PartialSession +): number => { + const database = sqlite(databasePath); + + const rightNowMillis = Date.now(); + + const result = database + .prepare( + "insert into LotTypeFields (" + + "lotTypeId, lotTypeField," + + " lotTypeFieldValues, isRequired, pattern," + + " minimumLength, maximumLength," + + " orderNumber," + + " recordCreate_userName, recordCreate_timeMillis," + + " recordUpdate_userName, recordUpdate_timeMillis)" + + " values (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)" + ) + .run( + lotTypeFieldForm.lotTypeId, + lotTypeFieldForm.lotTypeField, + lotTypeFieldForm.lotTypeFieldValues || "", + lotTypeFieldForm.isRequired ? 1 : 0, + lotTypeFieldForm.pattern || "", + lotTypeFieldForm.minimumLength || 0, + lotTypeFieldForm.maximumLength || 100, + lotTypeFieldForm.orderNumber || -1, + requestSession.user.userName, + rightNowMillis, + requestSession.user.userName, + rightNowMillis + ); + + database.close(); + + clearLotTypesCache(); + + return result.lastInsertRowid as number; +}; + +export default addLotTypeField; diff --git a/helpers/lotOccupancyDB/deleteLotType.d.ts b/helpers/lotOccupancyDB/deleteLotType.d.ts new file mode 100644 index 00000000..e95b64e3 --- /dev/null +++ b/helpers/lotOccupancyDB/deleteLotType.d.ts @@ -0,0 +1,3 @@ +import type * as recordTypes from "../../types/recordTypes"; +export declare const deleteLotType: (lotTypeId: number | string, requestSession: recordTypes.PartialSession) => boolean; +export default deleteLotType; diff --git a/helpers/lotOccupancyDB/deleteLotType.js b/helpers/lotOccupancyDB/deleteLotType.js new file mode 100644 index 00000000..70542803 --- /dev/null +++ b/helpers/lotOccupancyDB/deleteLotType.js @@ -0,0 +1,23 @@ +import sqlite from "better-sqlite3"; +import { lotOccupancyDB as databasePath } from "../../data/databasePaths.js"; +import { clearLotTypesCache } from "../functions.cache.js"; +export const deleteLotType = (lotTypeId, requestSession) => { + const database = sqlite(databasePath); + const rightNowMillis = Date.now(); + const result = database + .prepare("update LotTypes" + + " set recordDelete_userName = ?," + + " recordDelete_timeMillis = ?" + + " where lotTypeId = ?") + .run(requestSession.user.userName, rightNowMillis, lotTypeId); + database + .prepare("update LotTypeFields" + + " set recordDelete_userName = ?," + + " recordDelete_timeMillis = ?" + + " where lotTypeId = ?") + .run(requestSession.user.userName, rightNowMillis, lotTypeId); + database.close(); + clearLotTypesCache(); + return result.changes > 0; +}; +export default deleteLotType; diff --git a/helpers/lotOccupancyDB/deleteLotType.ts b/helpers/lotOccupancyDB/deleteLotType.ts new file mode 100644 index 00000000..a6545927 --- /dev/null +++ b/helpers/lotOccupancyDB/deleteLotType.ts @@ -0,0 +1,42 @@ +import sqlite from "better-sqlite3"; + +import { lotOccupancyDB as databasePath } from "../../data/databasePaths.js"; + +import { clearLotTypesCache } from "../functions.cache.js"; + +import type * as recordTypes from "../../types/recordTypes"; + +export const deleteLotType = ( + lotTypeId: number | string, + requestSession: recordTypes.PartialSession +): boolean => { + const database = sqlite(databasePath); + + const rightNowMillis = Date.now(); + + const result = database + .prepare( + "update LotTypes" + + " set recordDelete_userName = ?," + + " recordDelete_timeMillis = ?" + + " where lotTypeId = ?" + ) + .run(requestSession.user.userName, rightNowMillis, lotTypeId); + + database + .prepare( + "update LotTypeFields" + + " set recordDelete_userName = ?," + + " recordDelete_timeMillis = ?" + + " where lotTypeId = ?" + ) + .run(requestSession.user.userName, rightNowMillis, lotTypeId) + + database.close(); + + clearLotTypesCache(); + + return result.changes > 0; +}; + +export default deleteLotType; diff --git a/helpers/lotOccupancyDB/deleteLotTypeField.d.ts b/helpers/lotOccupancyDB/deleteLotTypeField.d.ts new file mode 100644 index 00000000..029a593b --- /dev/null +++ b/helpers/lotOccupancyDB/deleteLotTypeField.d.ts @@ -0,0 +1,3 @@ +import type * as recordTypes from "../../types/recordTypes"; +export declare const deleteLotTypeField: (lotTypeFieldId: number | string, requestSession: recordTypes.PartialSession) => boolean; +export default deleteLotTypeField; diff --git a/helpers/lotOccupancyDB/deleteLotTypeField.js b/helpers/lotOccupancyDB/deleteLotTypeField.js new file mode 100644 index 00000000..cce3f5a7 --- /dev/null +++ b/helpers/lotOccupancyDB/deleteLotTypeField.js @@ -0,0 +1,17 @@ +import sqlite from "better-sqlite3"; +import { lotOccupancyDB as databasePath } from "../../data/databasePaths.js"; +import { clearLotTypesCache } from "../functions.cache.js"; +export const deleteLotTypeField = (lotTypeFieldId, requestSession) => { + const database = sqlite(databasePath); + const rightNowMillis = Date.now(); + const result = database + .prepare("update LotTypeFields" + + " set recordDelete_userName = ?," + + " recordDelete_timeMillis = ?" + + " where lotTypeFieldId = ?") + .run(requestSession.user.userName, rightNowMillis, lotTypeFieldId); + database.close(); + clearLotTypesCache(); + return result.changes > 0; +}; +export default deleteLotTypeField; diff --git a/helpers/lotOccupancyDB/deleteLotTypeField.ts b/helpers/lotOccupancyDB/deleteLotTypeField.ts new file mode 100644 index 00000000..ca109a19 --- /dev/null +++ b/helpers/lotOccupancyDB/deleteLotTypeField.ts @@ -0,0 +1,33 @@ +import sqlite from "better-sqlite3"; + +import { lotOccupancyDB as databasePath } from "../../data/databasePaths.js"; + +import { clearLotTypesCache } from "../functions.cache.js"; + +import type * as recordTypes from "../../types/recordTypes"; + +export const deleteLotTypeField = ( + lotTypeFieldId: number | string, + requestSession: recordTypes.PartialSession +): boolean => { + const database = sqlite(databasePath); + + const rightNowMillis = Date.now(); + + const result = database + .prepare( + "update LotTypeFields" + + " set recordDelete_userName = ?," + + " recordDelete_timeMillis = ?" + + " where lotTypeFieldId = ?" + ) + .run(requestSession.user.userName, rightNowMillis, lotTypeFieldId); + + database.close(); + + clearLotTypesCache(); + + return result.changes > 0; +}; + +export default deleteLotTypeField; diff --git a/helpers/lotOccupancyDB/getLotTypeFields.d.ts b/helpers/lotOccupancyDB/getLotTypeFields.d.ts new file mode 100644 index 00000000..6947ca7f --- /dev/null +++ b/helpers/lotOccupancyDB/getLotTypeFields.d.ts @@ -0,0 +1,4 @@ +import sqlite from "better-sqlite3"; +import type * as recordTypes from "../../types/recordTypes"; +export declare const getLotTypeFields: (lotTypeId: number, connectedDatabase?: sqlite.Database) => recordTypes.LotTypeField[]; +export default getLotTypeFields; diff --git a/helpers/lotOccupancyDB/getLotTypeFields.js b/helpers/lotOccupancyDB/getLotTypeFields.js new file mode 100644 index 00000000..a3c4611e --- /dev/null +++ b/helpers/lotOccupancyDB/getLotTypeFields.js @@ -0,0 +1,30 @@ +import sqlite from "better-sqlite3"; +import { lotOccupancyDB as databasePath } from "../../data/databasePaths.js"; +export const getLotTypeFields = (lotTypeId, connectedDatabase) => { + const database = connectedDatabase || sqlite(databasePath); + const lotTypeFields = database + .prepare("select lotTypeFieldId," + + " lotTypeField, lotTypeFieldValues, isRequired, pattern," + + " minimumLength, maximumLength," + + " orderNumber" + + " from LotTypeFields" + + " where recordDelete_timeMillis is null" + + " and lotTypeId = ?" + + " order by orderNumber, lotTypeField") + .all(lotTypeId); + let expectedFieldOrderNumber = -1; + for (const lotTypeField of lotTypeFields) { + expectedFieldOrderNumber += 1; + if (lotTypeField.orderNumber !== expectedFieldOrderNumber) { + database + .prepare("update LotTypeFields set orderNumber = ? where lotTypeFieldId = ?") + .run(expectedFieldOrderNumber, lotTypeField.lotTypeFieldId); + lotTypeField.orderNumber = expectedFieldOrderNumber; + } + } + if (!connectedDatabase) { + database.close(); + } + return lotTypeFields; +}; +export default getLotTypeFields; diff --git a/helpers/lotOccupancyDB/getLotTypeFields.ts b/helpers/lotOccupancyDB/getLotTypeFields.ts new file mode 100644 index 00000000..75cbc08e --- /dev/null +++ b/helpers/lotOccupancyDB/getLotTypeFields.ts @@ -0,0 +1,49 @@ +import sqlite from "better-sqlite3"; + +import { lotOccupancyDB as databasePath } from "../../data/databasePaths.js"; + +import type * as recordTypes from "../../types/recordTypes"; + +export const getLotTypeFields = ( + lotTypeId: number, + connectedDatabase?: sqlite.Database +): recordTypes.LotTypeField[] => { + const database = connectedDatabase || sqlite(databasePath); + + const lotTypeFields: recordTypes.LotTypeField[] = database + .prepare( + "select lotTypeFieldId," + + " lotTypeField, lotTypeFieldValues, isRequired, pattern," + + " minimumLength, maximumLength," + + " orderNumber" + + " from LotTypeFields" + + " where recordDelete_timeMillis is null" + + " and lotTypeId = ?" + + " order by orderNumber, lotTypeField" + ) + .all(lotTypeId); + + let expectedFieldOrderNumber = -1; + + for (const lotTypeField of lotTypeFields) { + expectedFieldOrderNumber += 1; + + if (lotTypeField.orderNumber !== expectedFieldOrderNumber) { + database + .prepare( + "update LotTypeFields set orderNumber = ? where lotTypeFieldId = ?" + ) + .run(expectedFieldOrderNumber, lotTypeField.lotTypeFieldId); + + lotTypeField.orderNumber = expectedFieldOrderNumber; + } + } + + if (!connectedDatabase) { + database.close(); + } + + return lotTypeFields; +}; + +export default getLotTypeFields; diff --git a/helpers/lotOccupancyDB/getLotTypes.js b/helpers/lotOccupancyDB/getLotTypes.js index 8ae2152e..45c82ba8 100644 --- a/helpers/lotOccupancyDB/getLotTypes.js +++ b/helpers/lotOccupancyDB/getLotTypes.js @@ -1,15 +1,37 @@ import sqlite from "better-sqlite3"; import { lotOccupancyDB as databasePath } from "../../data/databasePaths.js"; +import { getLotTypeFields } from "./getLotTypeFields.js"; export const getLotTypes = () => { - const database = sqlite(databasePath, { - readonly: true - }); + const database = sqlite(databasePath); const lotTypes = database - .prepare("select lotTypeId, lotType" + + .prepare("select lotTypeId, lotType, orderNumber" + " from LotTypes" + " where recordDelete_timeMillis is null" + " order by orderNumber, lotType") .all(); + let expectedTypeOrderNumber = -1; + for (const lotType of lotTypes) { + expectedTypeOrderNumber += 1; + if (lotType.orderNumber !== expectedTypeOrderNumber) { + database + .prepare("update LotTypes set orderNumber = ? where lotTypeId = ?") + .run(expectedTypeOrderNumber, lotType.lotTypeId); + lotType.orderNumber = expectedTypeOrderNumber; + } + lotType.lotTypeFields = getLotTypeFields(lotType.lotTypeId, database); + let expectedFieldOrderNumber = -1; + for (const lotTypeField of lotType.lotTypeFields) { + expectedFieldOrderNumber += 1; + if (lotTypeField.orderNumber !== expectedFieldOrderNumber) { + database + .prepare("update LotTypeFields" + + " set orderNumber = ?" + + " where lotTypeFieldId = ?") + .run(expectedFieldOrderNumber, lotTypeField.lotTypeFieldId); + lotTypeField.orderNumber = expectedFieldOrderNumber; + } + } + } database.close(); return lotTypes; }; diff --git a/helpers/lotOccupancyDB/getLotTypes.ts b/helpers/lotOccupancyDB/getLotTypes.ts index 50a809a8..6bbc4984 100644 --- a/helpers/lotOccupancyDB/getLotTypes.ts +++ b/helpers/lotOccupancyDB/getLotTypes.ts @@ -2,22 +2,61 @@ import sqlite from "better-sqlite3"; import { lotOccupancyDB as databasePath } from "../../data/databasePaths.js"; +import { getLotTypeFields } from "./getLotTypeFields.js"; + import type * as recordTypes from "../../types/recordTypes"; export const getLotTypes = (): recordTypes.LotType[] => { - const database = sqlite(databasePath, { - readonly: true - }); + const database = sqlite(databasePath); const lotTypes: recordTypes.LotType[] = database .prepare( - "select lotTypeId, lotType" + + "select lotTypeId, lotType, orderNumber" + " from LotTypes" + " where recordDelete_timeMillis is null" + " order by orderNumber, lotType" ) .all(); + let expectedTypeOrderNumber = -1; + + for (const lotType of lotTypes) { + expectedTypeOrderNumber += 1; + + if (lotType.orderNumber !== expectedTypeOrderNumber) { + database + .prepare( + "update LotTypes set orderNumber = ? where lotTypeId = ?" + ) + .run(expectedTypeOrderNumber, lotType.lotTypeId); + + lotType.orderNumber = expectedTypeOrderNumber; + } + + lotType.lotTypeFields = getLotTypeFields( + lotType.lotTypeId, + database + ); + + let expectedFieldOrderNumber = -1; + + for (const lotTypeField of lotType.lotTypeFields) { + expectedFieldOrderNumber += 1; + + if (lotTypeField.orderNumber !== expectedFieldOrderNumber) { + database + .prepare( + "update LotTypeFields" + + " set orderNumber = ?" + + " where lotTypeFieldId = ?" + ) + .run(expectedFieldOrderNumber, lotTypeField.lotTypeFieldId); + + lotTypeField.orderNumber = expectedFieldOrderNumber; + } + } + } + database.close(); return lotTypes; diff --git a/helpers/lotOccupancyDB/moveLotTypeDown.d.ts b/helpers/lotOccupancyDB/moveLotTypeDown.d.ts new file mode 100644 index 00000000..2007cc71 --- /dev/null +++ b/helpers/lotOccupancyDB/moveLotTypeDown.d.ts @@ -0,0 +1,2 @@ +export declare const moveLotTypeDown: (lotTypeId: number | string) => boolean; +export default moveLotTypeDown; diff --git a/helpers/lotOccupancyDB/moveLotTypeDown.js b/helpers/lotOccupancyDB/moveLotTypeDown.js new file mode 100644 index 00000000..23633c53 --- /dev/null +++ b/helpers/lotOccupancyDB/moveLotTypeDown.js @@ -0,0 +1,22 @@ +import sqlite from "better-sqlite3"; +import { lotOccupancyDB as databasePath } from "../../data/databasePaths.js"; +import { clearLotTypesCache } from "../functions.cache.js"; +export const moveLotTypeDown = (lotTypeId) => { + const database = sqlite(databasePath); + const currentOrderNumber = database + .prepare("select orderNumber" + " from LotTypes" + " where lotTypeId = ?") + .get(lotTypeId).orderNumber; + database + .prepare("update LotTypes" + + " set orderNumber = orderNumber - 1" + + " where recordDelete_timeMillis is null" + + " and orderNumber = ? + 1") + .run(currentOrderNumber); + const result = database + .prepare("update LotTypes" + " set orderNumber = ? + 1" + " where lotTypeId = ?") + .run(currentOrderNumber, lotTypeId); + database.close(); + clearLotTypesCache(); + return result.changes > 0; +}; +export default moveLotTypeDown; diff --git a/helpers/lotOccupancyDB/moveLotTypeDown.ts b/helpers/lotOccupancyDB/moveLotTypeDown.ts new file mode 100644 index 00000000..bf5b0d83 --- /dev/null +++ b/helpers/lotOccupancyDB/moveLotTypeDown.ts @@ -0,0 +1,34 @@ +import sqlite from "better-sqlite3"; + +import { lotOccupancyDB as databasePath } from "../../data/databasePaths.js"; + +import { clearLotTypesCache } from "../functions.cache.js"; + +export const moveLotTypeDown = (lotTypeId: number | string): boolean => { + const database = sqlite(databasePath); + + const currentOrderNumber: number = database + .prepare("select orderNumber" + " from LotTypes" + " where lotTypeId = ?") + .get(lotTypeId).orderNumber; + + database + .prepare( + "update LotTypes" + + " set orderNumber = orderNumber - 1" + + " where recordDelete_timeMillis is null" + + " and orderNumber = ? + 1" + ) + .run(currentOrderNumber); + + const result = database + .prepare("update LotTypes" + " set orderNumber = ? + 1" + " where lotTypeId = ?") + .run(currentOrderNumber, lotTypeId); + + database.close(); + + clearLotTypesCache(); + + return result.changes > 0; +}; + +export default moveLotTypeDown; diff --git a/helpers/lotOccupancyDB/moveLotTypeFieldDown.d.ts b/helpers/lotOccupancyDB/moveLotTypeFieldDown.d.ts new file mode 100644 index 00000000..8f25f30e --- /dev/null +++ b/helpers/lotOccupancyDB/moveLotTypeFieldDown.d.ts @@ -0,0 +1,2 @@ +export declare const moveLotTypeFieldDown: (lotTypeFieldId: number | string) => boolean; +export default moveLotTypeFieldDown; diff --git a/helpers/lotOccupancyDB/moveLotTypeFieldDown.js b/helpers/lotOccupancyDB/moveLotTypeFieldDown.js new file mode 100644 index 00000000..e863696b --- /dev/null +++ b/helpers/lotOccupancyDB/moveLotTypeFieldDown.js @@ -0,0 +1,23 @@ +import sqlite from "better-sqlite3"; +import { lotOccupancyDB as databasePath } from "../../data/databasePaths.js"; +import { clearLotTypesCache } from "../functions.cache.js"; +export const moveLotTypeFieldDown = (lotTypeFieldId) => { + const database = sqlite(databasePath); + const currentField = database + .prepare("select lotTypeId, orderNumber from LotTypeFields where lotTypeFieldId = ?") + .get(lotTypeFieldId); + database + .prepare("update LotTypeFields" + + " set orderNumber = orderNumber - 1" + + " where recordDelete_timeMillis is null" + + " and lotTypeId = ?" + + " and orderNumber = ? + 1") + .run(currentField.lotTypeId, currentField.orderNumber); + const result = database + .prepare("update LotTypeFields set orderNumber = ? + 1 where lotTypeFieldId = ?") + .run(currentField.orderNumber, lotTypeFieldId); + database.close(); + clearLotTypesCache(); + return result.changes > 0; +}; +export default moveLotTypeFieldDown; diff --git a/helpers/lotOccupancyDB/moveLotTypeFieldDown.ts b/helpers/lotOccupancyDB/moveLotTypeFieldDown.ts new file mode 100644 index 00000000..346193de --- /dev/null +++ b/helpers/lotOccupancyDB/moveLotTypeFieldDown.ts @@ -0,0 +1,37 @@ +import sqlite from "better-sqlite3"; + +import { lotOccupancyDB as databasePath } from "../../data/databasePaths.js"; + +import { clearLotTypesCache } from "../functions.cache.js"; + +export const moveLotTypeFieldDown = (lotTypeFieldId: number | string): boolean => { + const database = sqlite(databasePath); + + const currentField: { lotTypeId?: number; orderNumber: number } = database + .prepare( + "select lotTypeId, orderNumber from LotTypeFields where lotTypeFieldId = ?" + ) + .get(lotTypeFieldId); + + database + .prepare( + "update LotTypeFields" + + " set orderNumber = orderNumber - 1" + + " where recordDelete_timeMillis is null" + + " and lotTypeId = ?" + + " and orderNumber = ? + 1" + ) + .run(currentField.lotTypeId, currentField.orderNumber); + + const result = database + .prepare("update LotTypeFields set orderNumber = ? + 1 where lotTypeFieldId = ?") + .run(currentField.orderNumber, lotTypeFieldId); + + database.close(); + + clearLotTypesCache(); + + return result.changes > 0; +}; + +export default moveLotTypeFieldDown; diff --git a/helpers/lotOccupancyDB/moveLotTypeFieldUp.d.ts b/helpers/lotOccupancyDB/moveLotTypeFieldUp.d.ts new file mode 100644 index 00000000..81612b3a --- /dev/null +++ b/helpers/lotOccupancyDB/moveLotTypeFieldUp.d.ts @@ -0,0 +1,2 @@ +export declare const moveLotTypeFieldUp: (lotTypeFieldId: number | string) => boolean; +export default moveLotTypeFieldUp; diff --git a/helpers/lotOccupancyDB/moveLotTypeFieldUp.js b/helpers/lotOccupancyDB/moveLotTypeFieldUp.js new file mode 100644 index 00000000..b9f61628 --- /dev/null +++ b/helpers/lotOccupancyDB/moveLotTypeFieldUp.js @@ -0,0 +1,27 @@ +import sqlite from "better-sqlite3"; +import { lotOccupancyDB as databasePath } from "../../data/databasePaths.js"; +import { clearLotTypesCache } from "../functions.cache.js"; +export const moveLotTypeFieldUp = (lotTypeFieldId) => { + const database = sqlite(databasePath); + const currentField = database + .prepare("select lotTypeId, orderNumber" + " from LotTypeFields" + " where lotTypeFieldId = ?") + .get(lotTypeFieldId); + if (currentField.orderNumber <= 0) { + database.close(); + return true; + } + database + .prepare("update LotTypeFields" + + " set orderNumber = orderNumber + 1" + + " where recordDelete_timeMillis is null" + + " and lotTypeId = ?" + + " and orderNumber = ? - 1") + .run(currentField.lotTypeId, currentField.orderNumber); + const result = database + .prepare("update LotTypeFields" + " set orderNumber = ? - 1" + " where lotTypeFieldId = ?") + .run(currentField.orderNumber, lotTypeFieldId); + database.close(); + clearLotTypesCache(); + return result.changes > 0; +}; +export default moveLotTypeFieldUp; diff --git a/helpers/lotOccupancyDB/moveLotTypeFieldUp.ts b/helpers/lotOccupancyDB/moveLotTypeFieldUp.ts new file mode 100644 index 00000000..402945d7 --- /dev/null +++ b/helpers/lotOccupancyDB/moveLotTypeFieldUp.ts @@ -0,0 +1,42 @@ +import sqlite from "better-sqlite3"; + +import { lotOccupancyDB as databasePath } from "../../data/databasePaths.js"; + +import { clearLotTypesCache } from "../functions.cache.js"; + +export const moveLotTypeFieldUp = (lotTypeFieldId: number | string): boolean => { + const database = sqlite(databasePath); + + const currentField: { lotTypeId: number; orderNumber: number } = database + .prepare( + "select lotTypeId, orderNumber" + " from LotTypeFields" + " where lotTypeFieldId = ?" + ) + .get(lotTypeFieldId); + + if (currentField.orderNumber <= 0) { + database.close(); + return true; + } + + database + .prepare( + "update LotTypeFields" + + " set orderNumber = orderNumber + 1" + + " where recordDelete_timeMillis is null" + + " and lotTypeId = ?" + + " and orderNumber = ? - 1" + ) + .run(currentField.lotTypeId, currentField.orderNumber); + + const result = database + .prepare("update LotTypeFields" + " set orderNumber = ? - 1" + " where lotTypeFieldId = ?") + .run(currentField.orderNumber, lotTypeFieldId); + + database.close(); + + clearLotTypesCache(); + + return result.changes > 0; +}; + +export default moveLotTypeFieldUp; diff --git a/helpers/lotOccupancyDB/moveLotTypeUp.d.ts b/helpers/lotOccupancyDB/moveLotTypeUp.d.ts new file mode 100644 index 00000000..2b647c6e --- /dev/null +++ b/helpers/lotOccupancyDB/moveLotTypeUp.d.ts @@ -0,0 +1,2 @@ +export declare const moveLotTypeUp: (lotTypeId: number | string) => boolean; +export default moveLotTypeUp; diff --git a/helpers/lotOccupancyDB/moveLotTypeUp.js b/helpers/lotOccupancyDB/moveLotTypeUp.js new file mode 100644 index 00000000..16bb0dfc --- /dev/null +++ b/helpers/lotOccupancyDB/moveLotTypeUp.js @@ -0,0 +1,30 @@ +import sqlite from "better-sqlite3"; +import { lotOccupancyDB as databasePath } from "../../data/databasePaths.js"; +import { clearLotTypesCache } from "../functions.cache.js"; +export const moveLotTypeUp = (lotTypeId) => { + const database = sqlite(databasePath); + const currentOrderNumber = database + .prepare("select orderNumber" + + " from LotTypes" + + " where lotTypeId = ?") + .get(lotTypeId).orderNumber; + if (currentOrderNumber <= 0) { + database.close(); + return true; + } + database + .prepare("update LotTypes" + + " set orderNumber = orderNumber + 1" + + " where recordDelete_timeMillis is null" + + " and orderNumber = ? - 1") + .run(currentOrderNumber); + const result = database + .prepare("update LotTypes" + + " set orderNumber = ? - 1" + + " where lotTypeId = ?") + .run(currentOrderNumber, lotTypeId); + database.close(); + clearLotTypesCache(); + return result.changes > 0; +}; +export default moveLotTypeUp; diff --git a/helpers/lotOccupancyDB/moveLotTypeUp.ts b/helpers/lotOccupancyDB/moveLotTypeUp.ts new file mode 100644 index 00000000..d4ae6c5d --- /dev/null +++ b/helpers/lotOccupancyDB/moveLotTypeUp.ts @@ -0,0 +1,49 @@ +import sqlite from "better-sqlite3"; + +import { lotOccupancyDB as databasePath } from "../../data/databasePaths.js"; + +import { clearLotTypesCache } from "../functions.cache.js"; + +export const moveLotTypeUp = ( + lotTypeId: number | string +): boolean => { + const database = sqlite(databasePath); + + const currentOrderNumber: number = database + .prepare( + "select orderNumber" + + " from LotTypes" + + " where lotTypeId = ?" + ) + .get(lotTypeId).orderNumber; + + if (currentOrderNumber <= 0) { + database.close(); + return true; + } + + database + .prepare( + "update LotTypes" + + " set orderNumber = orderNumber + 1" + + " where recordDelete_timeMillis is null" + + " and orderNumber = ? - 1" + ) + .run(currentOrderNumber); + + const result = database + .prepare( + "update LotTypes" + + " set orderNumber = ? - 1" + + " where lotTypeId = ?" + ) + .run(currentOrderNumber, lotTypeId); + + database.close(); + + clearLotTypesCache(); + + return result.changes > 0; +}; + +export default moveLotTypeUp; diff --git a/helpers/lotOccupancyDB/updateLotType.d.ts b/helpers/lotOccupancyDB/updateLotType.d.ts new file mode 100644 index 00000000..5ca18eb9 --- /dev/null +++ b/helpers/lotOccupancyDB/updateLotType.d.ts @@ -0,0 +1,7 @@ +import type * as recordTypes from "../../types/recordTypes"; +interface UpdateLotTypeForm { + lotTypeId: number | string; + lotType: string; +} +export declare const updateLotType: (lotTypeForm: UpdateLotTypeForm, requestSession: recordTypes.PartialSession) => boolean; +export default updateLotType; diff --git a/helpers/lotOccupancyDB/updateLotType.js b/helpers/lotOccupancyDB/updateLotType.js new file mode 100644 index 00000000..8b4c50ff --- /dev/null +++ b/helpers/lotOccupancyDB/updateLotType.js @@ -0,0 +1,19 @@ +import sqlite from "better-sqlite3"; +import { lotOccupancyDB as databasePath } from "../../data/databasePaths.js"; +import { clearLotTypesCache } from "../functions.cache.js"; +export const updateLotType = (lotTypeForm, requestSession) => { + const database = sqlite(databasePath); + const rightNowMillis = Date.now(); + const result = database + .prepare("update LotTypes" + + " set lotType = ?," + + " recordUpdate_userName = ?," + + " recordUpdate_timeMillis = ?" + + " where lotTypeId = ?" + + " and recordDelete_timeMillis is null") + .run(lotTypeForm.lotType, requestSession.user.userName, rightNowMillis, lotTypeForm.lotTypeId); + database.close(); + clearLotTypesCache(); + return result.changes > 0; +}; +export default updateLotType; diff --git a/helpers/lotOccupancyDB/updateLotType.ts b/helpers/lotOccupancyDB/updateLotType.ts new file mode 100644 index 00000000..7925f2d2 --- /dev/null +++ b/helpers/lotOccupancyDB/updateLotType.ts @@ -0,0 +1,45 @@ +import sqlite from "better-sqlite3"; + +import { lotOccupancyDB as databasePath } from "../../data/databasePaths.js"; + +import { clearLotTypesCache } from "../functions.cache.js"; + +import type * as recordTypes from "../../types/recordTypes"; + +interface UpdateLotTypeForm { + lotTypeId: number | string; + lotType: string; +} + +export const updateLotType = ( + lotTypeForm: UpdateLotTypeForm, + requestSession: recordTypes.PartialSession +): boolean => { + const database = sqlite(databasePath); + + const rightNowMillis = Date.now(); + + const result = database + .prepare( + "update LotTypes" + + " set lotType = ?," + + " recordUpdate_userName = ?," + + " recordUpdate_timeMillis = ?" + + " where lotTypeId = ?" + + " and recordDelete_timeMillis is null" + ) + .run( + lotTypeForm.lotType, + requestSession.user.userName, + rightNowMillis, + lotTypeForm.lotTypeId + ); + + database.close(); + + clearLotTypesCache(); + + return result.changes > 0; +}; + +export default updateLotType; diff --git a/helpers/lotOccupancyDB/updateLotTypeField.d.ts b/helpers/lotOccupancyDB/updateLotTypeField.d.ts new file mode 100644 index 00000000..ca207c65 --- /dev/null +++ b/helpers/lotOccupancyDB/updateLotTypeField.d.ts @@ -0,0 +1,12 @@ +import type * as recordTypes from "../../types/recordTypes"; +interface UpdateLotTypeFieldForm { + lotTypeFieldId: number | string; + lotTypeField: string; + isRequired: "0" | "1"; + minimumLength?: string; + maximumLength?: string; + pattern?: string; + lotTypeFieldValues: string; +} +export declare const updateLotTypeField: (lotTypeFieldForm: UpdateLotTypeFieldForm, requestSession: recordTypes.PartialSession) => boolean; +export default updateLotTypeField; diff --git a/helpers/lotOccupancyDB/updateLotTypeField.js b/helpers/lotOccupancyDB/updateLotTypeField.js new file mode 100644 index 00000000..847e79a9 --- /dev/null +++ b/helpers/lotOccupancyDB/updateLotTypeField.js @@ -0,0 +1,24 @@ +import sqlite from "better-sqlite3"; +import { lotOccupancyDB as databasePath } from "../../data/databasePaths.js"; +import { clearLotTypesCache } from "../functions.cache.js"; +export const updateLotTypeField = (lotTypeFieldForm, requestSession) => { + const database = sqlite(databasePath); + const rightNowMillis = Date.now(); + const result = database + .prepare("update LotTypeFields" + + " set lotTypeField = ?," + + " isRequired = ?," + + " minimumLength = ?," + + " maximumLength = ?," + + " pattern = ?," + + " lotTypeFieldValues = ?," + + " recordUpdate_userName = ?," + + " recordUpdate_timeMillis = ?" + + " where lotTypeFieldId = ?" + + " and recordDelete_timeMillis is null") + .run(lotTypeFieldForm.lotTypeField, Number.parseInt(lotTypeFieldForm.isRequired, 10), lotTypeFieldForm.minimumLength || 0, lotTypeFieldForm.maximumLength || 100, lotTypeFieldForm.pattern || "", lotTypeFieldForm.lotTypeFieldValues, requestSession.user.userName, rightNowMillis, lotTypeFieldForm.lotTypeFieldId); + database.close(); + clearLotTypesCache(); + return result.changes > 0; +}; +export default updateLotTypeField; diff --git a/helpers/lotOccupancyDB/updateLotTypeField.ts b/helpers/lotOccupancyDB/updateLotTypeField.ts new file mode 100644 index 00000000..d8e162d6 --- /dev/null +++ b/helpers/lotOccupancyDB/updateLotTypeField.ts @@ -0,0 +1,60 @@ +import sqlite from "better-sqlite3"; + +import { lotOccupancyDB as databasePath } from "../../data/databasePaths.js"; + +import { clearLotTypesCache } from "../functions.cache.js"; + +import type * as recordTypes from "../../types/recordTypes"; + +interface UpdateLotTypeFieldForm { + lotTypeFieldId: number | string; + lotTypeField: string; + isRequired: "0" | "1"; + minimumLength?: string; + maximumLength?: string; + pattern?: string; + lotTypeFieldValues: string; +} + +export const updateLotTypeField = ( + lotTypeFieldForm: UpdateLotTypeFieldForm, + requestSession: recordTypes.PartialSession +): boolean => { + const database = sqlite(databasePath); + + const rightNowMillis = Date.now(); + + const result = database + .prepare( + "update LotTypeFields" + + " set lotTypeField = ?," + + " isRequired = ?," + + " minimumLength = ?," + + " maximumLength = ?," + + " pattern = ?," + + " lotTypeFieldValues = ?," + + " recordUpdate_userName = ?," + + " recordUpdate_timeMillis = ?" + + " where lotTypeFieldId = ?" + + " and recordDelete_timeMillis is null" + ) + .run( + lotTypeFieldForm.lotTypeField, + Number.parseInt(lotTypeFieldForm.isRequired, 10), + lotTypeFieldForm.minimumLength || 0, + lotTypeFieldForm.maximumLength || 100, + lotTypeFieldForm.pattern || "", + lotTypeFieldForm.lotTypeFieldValues, + requestSession.user.userName, + rightNowMillis, + lotTypeFieldForm.lotTypeFieldId + ); + + database.close(); + + clearLotTypesCache(); + + return result.changes > 0; +}; + +export default updateLotTypeField; diff --git a/public-typescript/adminLotTypes.d.ts b/public-typescript/adminLotTypes.d.ts new file mode 100644 index 00000000..cb0ff5c3 --- /dev/null +++ b/public-typescript/adminLotTypes.d.ts @@ -0,0 +1 @@ +export {}; diff --git a/public-typescript/adminLotTypes.js b/public-typescript/adminLotTypes.js new file mode 100644 index 00000000..c7f91874 --- /dev/null +++ b/public-typescript/adminLotTypes.js @@ -0,0 +1,435 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +(() => { + const los = exports.los; + const urlPrefix = document.querySelector("main").dataset.urlPrefix; + const containerElement = document.querySelector("#container--lotTypes"); + let lotTypes = exports.lotTypes; + delete exports.lotTypes; + const expandedLotTypes = new Set(); + const toggleLotTypeFields = (clickEvent) => { + const toggleButtonElement = clickEvent.currentTarget; + const lotTypeElement = toggleButtonElement.closest(".container--lotType"); + const lotTypeId = Number.parseInt(lotTypeElement.dataset.lotTypeId, 10); + if (expandedLotTypes.has(lotTypeId)) { + expandedLotTypes.delete(lotTypeId); + } + else { + expandedLotTypes.add(lotTypeId); + } + toggleButtonElement.innerHTML = expandedLotTypes.has(lotTypeId) + ? '' + : ''; + const panelBlockElements = lotTypeElement.querySelectorAll(".panel-block"); + for (const panelBlockElement of panelBlockElements) { + panelBlockElement.classList.toggle("is-hidden"); + } + }; + const lotTypeResponseHandler = (responseJSON) => { + if (responseJSON.success) { + lotTypes = responseJSON.lotTypes; + renderLotTypes(); + } + else { + bulmaJS.alert({ + title: "Error Updating " + exports.aliases.lot + " Type", + message: responseJSON.errorMessage, + contextualColorName: "danger" + }); + } + }; + const deleteLotType = (clickEvent) => { + const lotTypeId = Number.parseInt(clickEvent.currentTarget.closest(".container--lotType").dataset.lotTypeId, 10); + const doDelete = () => { + cityssm.postJSON(urlPrefix + "/admin/doDeleteLotType", { + lotTypeId + }, lotTypeResponseHandler); + }; + bulmaJS.confirm({ + title: "Delete " + exports.aliases.lot + " Type", + message: "Are you sure you want to delete this " + + exports.aliases.lot.toLowerCase() + + " type?", + contextualColorName: "warning", + okButton: { + text: "Yes, Delete " + exports.aliases.lot + " Type", + callbackFunction: doDelete + } + }); + }; + const openEditLotType = (clickEvent) => { + const lotTypeId = Number.parseInt(clickEvent.currentTarget.closest(".container--lotType").dataset.lotTypeId, 10); + const lotType = lotTypes.find((currentLotType) => { + return lotTypeId === currentLotType.lotTypeId; + }); + let editCloseModalFunction; + const doEdit = (submitEvent) => { + submitEvent.preventDefault(); + cityssm.postJSON(urlPrefix + "/admin/doUpdateLotType", submitEvent.currentTarget, (responseJSON) => { + lotTypeResponseHandler(responseJSON); + if (responseJSON.success) { + editCloseModalFunction(); + } + }); + }; + cityssm.openHtmlModal("adminLotTypes-editLotType", { + onshow: (modalElement) => { + los.populateAliases(modalElement); + modalElement.querySelector("#lotTypeEdit--lotTypeId").value = + lotTypeId.toString(); + modalElement.querySelector("#lotTypeEdit--lotType").value = + lotType.lotType; + }, + onshown: (modalElement, closeModalFunction) => { + editCloseModalFunction = closeModalFunction; + modalElement.querySelector("#lotTypeEdit--lotType").focus(); + modalElement.querySelector("form").addEventListener("submit", doEdit); + bulmaJS.toggleHtmlClipped(); + }, + onremoved: () => { + bulmaJS.toggleHtmlClipped(); + } + }); + }; + const openAddLotTypeField = (clickEvent) => { + const lotTypeId = Number.parseInt(clickEvent.currentTarget.closest(".container--lotType").dataset.lotTypeId, 10); + let addCloseModalFunction; + const doAdd = (submitEvent) => { + submitEvent.preventDefault(); + cityssm.postJSON(urlPrefix + "/admin/doAddLotTypeField", submitEvent.currentTarget, (responseJSON) => { + expandedLotTypes.add(lotTypeId); + lotTypeResponseHandler(responseJSON); + if (responseJSON.success) { + addCloseModalFunction(); + openEditLotTypeField(lotTypeId, responseJSON.lotTypeFieldId); + } + }); + }; + cityssm.openHtmlModal("adminLotTypes-addLotTypeField", { + onshow: (modalElement) => { + los.populateAliases(modalElement); + if (lotTypeId) { + modalElement.querySelector("#lotTypeFieldAdd--lotTypeId").value = lotTypeId.toString(); + } + }, + onshown: (modalElement, closeModalFunction) => { + addCloseModalFunction = closeModalFunction; + modalElement.querySelector("#lotTypeFieldAdd--lotTypeField").focus(); + modalElement.querySelector("form").addEventListener("submit", doAdd); + bulmaJS.toggleHtmlClipped(); + }, + onremoved: () => { + bulmaJS.toggleHtmlClipped(); + } + }); + }; + const moveLotTypeUp = (clickEvent) => { + clickEvent.preventDefault(); + const lotTypeId = clickEvent.currentTarget.closest(".container--lotType").dataset.lotTypeId; + cityssm.postJSON(urlPrefix + "/admin/doMoveLotTypeUp", { + lotTypeId + }, lotTypeResponseHandler); + }; + const moveLotTypeDown = (clickEvent) => { + clickEvent.preventDefault(); + const lotTypeId = clickEvent.currentTarget.closest(".container--lotType").dataset.lotTypeId; + cityssm.postJSON(urlPrefix + "/admin/doMoveLotTypeDown", { + lotTypeId + }, lotTypeResponseHandler); + }; + const openEditLotTypeField = (lotTypeId, lotTypeFieldId) => { + const lotType = lotTypes.find((currentLotType) => { + return currentLotType.lotTypeId === lotTypeId; + }); + const lotTypeField = lotType.lotTypeFields.find((currentLotTypeField) => { + return currentLotTypeField.lotTypeFieldId === lotTypeFieldId; + }); + let minimumLengthElement; + let maximumLengthElement; + let patternElement; + let lotTypeFieldValuesElement; + let editCloseModalFunction; + const updateMaximumLengthMin = () => { + maximumLengthElement.min = minimumLengthElement.value; + }; + const toggleInputFields = () => { + if (lotTypeFieldValuesElement.value === "") { + minimumLengthElement.disabled = false; + maximumLengthElement.disabled = false; + patternElement.disabled = false; + } + else { + minimumLengthElement.disabled = true; + maximumLengthElement.disabled = true; + patternElement.disabled = true; + } + }; + const doUpdate = (submitEvent) => { + submitEvent.preventDefault(); + cityssm.postJSON(urlPrefix + "/admin/doUpdateLotTypeField", submitEvent.currentTarget, (responseJSON) => { + lotTypeResponseHandler(responseJSON); + if (responseJSON.success) { + editCloseModalFunction(); + } + }); + }; + const doDelete = () => { + const _doDelete = () => { + cityssm.postJSON(urlPrefix + "/admin/doDeleteLotTypeField", { + lotTypeFieldId + }, (responseJSON) => { + lotTypeResponseHandler(responseJSON); + if (responseJSON.success) { + editCloseModalFunction(); + } + }); + }; + bulmaJS.confirm({ + title: "Delete Field", + message: "Are you sure you want to delete this field? Note that historical records that make use of this field will not be affected.", + contextualColorName: "warning", + okButton: { + text: "Yes, Delete Field", + callbackFunction: _doDelete + } + }); + }; + cityssm.openHtmlModal("adminLotTypes-editLotTypeField", { + onshow: (modalElement) => { + los.populateAliases(modalElement); + modalElement.querySelector("#lotTypeFieldEdit--lotTypeFieldId").value = lotTypeField.lotTypeFieldId.toString(); + modalElement.querySelector("#lotTypeFieldEdit--lotTypeField").value = lotTypeField.lotTypeField; + modalElement.querySelector("#lotTypeFieldEdit--isRequired").value = lotTypeField.isRequired ? "1" : "0"; + minimumLengthElement = modalElement.querySelector("#lotTypeFieldEdit--minimumLength"); + minimumLengthElement.value = lotTypeField.minimumLength.toString(); + maximumLengthElement = modalElement.querySelector("#lotTypeFieldEdit--maximumLength"); + maximumLengthElement.value = lotTypeField.maximumLength.toString(); + patternElement = modalElement.querySelector("#lotTypeFieldEdit--pattern"); + patternElement.value = lotTypeField.pattern; + lotTypeFieldValuesElement = modalElement.querySelector("#lotTypeFieldEdit--lotTypeFieldValues"); + lotTypeFieldValuesElement.value = lotTypeField.lotTypeFieldValues; + toggleInputFields(); + }, + onshown: (modalElement, closeModalFunction) => { + editCloseModalFunction = closeModalFunction; + bulmaJS.init(modalElement); + bulmaJS.toggleHtmlClipped(); + cityssm.enableNavBlocker(); + modalElement.querySelector("form").addEventListener("submit", doUpdate); + minimumLengthElement.addEventListener("keyup", updateMaximumLengthMin); + updateMaximumLengthMin(); + lotTypeFieldValuesElement.addEventListener("keyup", toggleInputFields); + modalElement + .querySelector("#button--deleteLotTypeField") + .addEventListener("click", doDelete); + }, + onremoved: () => { + bulmaJS.toggleHtmlClipped(); + cityssm.disableNavBlocker(); + } + }); + }; + const openEditLotTypeFieldByClick = (clickEvent) => { + clickEvent.preventDefault(); + const lotTypeFieldId = Number.parseInt(clickEvent.currentTarget.closest(".container--lotTypeField").dataset.lotTypeFieldId, 10); + const lotTypeId = Number.parseInt(clickEvent.currentTarget.closest(".container--lotType").dataset.lotTypeId, 10); + openEditLotTypeField(lotTypeId, lotTypeFieldId); + }; + const moveLotTypeFieldUp = (clickEvent) => { + clickEvent.preventDefault(); + const lotTypeFieldId = clickEvent.currentTarget.closest(".container--lotTypeField").dataset.lotTypeFieldId; + cityssm.postJSON(urlPrefix + "/admin/doMoveLotTypeFieldUp", { + lotTypeFieldId + }, lotTypeResponseHandler); + }; + const moveLotTypeFieldDown = (clickEvent) => { + clickEvent.preventDefault(); + const lotTypeFieldId = clickEvent.currentTarget.closest(".container--lotTypeField").dataset.lotTypeFieldId; + cityssm.postJSON(urlPrefix + "/admin/doMoveLotTypeFieldDown", { + lotTypeFieldId + }, lotTypeResponseHandler); + }; + const renderLotTypeFields = (panelElement, lotTypeId, lotTypeFields) => { + if (lotTypeFields.length === 0) { + panelElement.insertAdjacentHTML("beforeend", '
' + + '
' + + '

There are no additional fields.

' + + "
" + + "
"); + } + else { + for (const lotTypeField of lotTypeFields) { + const panelBlockElement = document.createElement("div"); + panelBlockElement.className = "panel-block is-block container--lotTypeField"; + if (!expandedLotTypes.has(lotTypeId)) { + panelBlockElement.classList.add("is-hidden"); + } + panelBlockElement.dataset.lotTypeFieldId = lotTypeField.lotTypeFieldId.toString(); + panelBlockElement.innerHTML = + '
' + + '
' + + ('") + + "
" + + '
' + + ('
' + + '
' + + '
' + + '" + + "
" + + '
' + + '" + + "
" + + "
" + + "
") + + "
" + + "
"; + panelBlockElement + .querySelector(".button--editLotTypeField") + .addEventListener("click", openEditLotTypeFieldByClick); + panelBlockElement + .querySelector(".button--moveLotTypeFieldUp") + .addEventListener("click", moveLotTypeFieldUp); + panelBlockElement + .querySelector(".button--moveLotTypeFieldDown") + .addEventListener("click", moveLotTypeFieldDown); + panelElement.append(panelBlockElement); + } + } + }; + const renderLotTypes = () => { + containerElement.innerHTML = ""; + if (lotTypes.length === 0) { + containerElement.insertAdjacentHTML("afterbegin", '
There are no active ' + + exports.aliases.lot.toLowerCase() + + " types.

" + + "
"); + return; + } + for (const lotType of lotTypes) { + const lotTypeContainer = document.createElement("div"); + lotTypeContainer.className = "panel container--lotType"; + lotTypeContainer.dataset.lotTypeId = lotType.lotTypeId.toString(); + lotTypeContainer.innerHTML = + '
' + + '
' + + ('
' + + '
' + + '" + + "
" + + '
' + + '

' + + cityssm.escapeHTML(lotType.lotType) + + "

" + + "
" + + "
") + + ('
' + + ('
' + + '" + + "
") + + ('
' + + '" + + "
") + + ('
' + + '" + + "
") + + ('
' + + '
' + + '
' + + '" + + "
" + + '
' + + '" + + "
" + + "
" + + "
") + + "
") + + "
" + + "
"; + renderLotTypeFields(lotTypeContainer, lotType.lotTypeId, lotType.lotTypeFields); + lotTypeContainer + .querySelector(".button--toggleLotTypeFields") + .addEventListener("click", toggleLotTypeFields); + lotTypeContainer + .querySelector(".button--deleteLotType") + .addEventListener("click", deleteLotType); + lotTypeContainer + .querySelector(".button--editLotType") + .addEventListener("click", openEditLotType); + lotTypeContainer + .querySelector(".button--addLotTypeField") + .addEventListener("click", openAddLotTypeField); + lotTypeContainer + .querySelector(".button--moveLotTypeUp") + .addEventListener("click", moveLotTypeUp); + lotTypeContainer + .querySelector(".button--moveLotTypeDown") + .addEventListener("click", moveLotTypeDown); + containerElement.append(lotTypeContainer); + } + }; + document.querySelector("#button--addLotType").addEventListener("click", () => { + let addCloseModalFunction; + const doAdd = (submitEvent) => { + submitEvent.preventDefault(); + cityssm.postJSON(urlPrefix + "/admin/doAddLotType", submitEvent.currentTarget, (responseJSON) => { + if (responseJSON.success) { + addCloseModalFunction(); + lotTypes = responseJSON.lotTypes; + renderLotTypes(); + } + else { + bulmaJS.alert({ + title: "Error Adding " + exports.aliases.lot + " Type", + message: responseJSON.errorMessage, + contextualColorName: "danger" + }); + } + }); + }; + cityssm.openHtmlModal("adminLotTypes-addLotType", { + onshow: (modalElement) => { + los.populateAliases(modalElement); + }, + onshown: (modalElement, closeModalFunction) => { + addCloseModalFunction = closeModalFunction; + modalElement.querySelector("#lotTypeAdd--lotType").focus(); + modalElement.querySelector("form").addEventListener("submit", doAdd); + bulmaJS.toggleHtmlClipped(); + }, + onremoved: () => { + bulmaJS.toggleHtmlClipped(); + } + }); + }); + renderLotTypes(); +})(); diff --git a/public-typescript/adminLotTypes.ts b/public-typescript/adminLotTypes.ts new file mode 100644 index 00000000..530f7d02 --- /dev/null +++ b/public-typescript/adminLotTypes.ts @@ -0,0 +1,697 @@ +/* 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"; + +declare const cityssm: cityssmGlobal; +declare const bulmaJS: BulmaJS; + +(() => { + const los = exports.los as globalTypes.LOS; + + const urlPrefix = document.querySelector("main").dataset.urlPrefix; + + const containerElement = document.querySelector("#container--lotTypes") as HTMLElement; + + let lotTypes: recordTypes.LotType[] = exports.lotTypes; + delete exports.lotTypes; + + const expandedLotTypes = new Set(); + + const toggleLotTypeFields = (clickEvent: Event) => { + const toggleButtonElement = clickEvent.currentTarget as HTMLButtonElement; + + const lotTypeElement = toggleButtonElement.closest(".container--lotType") as HTMLElement; + + const lotTypeId = Number.parseInt(lotTypeElement.dataset.lotTypeId, 10); + + if (expandedLotTypes.has(lotTypeId)) { + expandedLotTypes.delete(lotTypeId); + } else { + expandedLotTypes.add(lotTypeId); + } + + toggleButtonElement.innerHTML = expandedLotTypes.has(lotTypeId) + ? '' + : ''; + + const panelBlockElements = lotTypeElement.querySelectorAll(".panel-block"); + + for (const panelBlockElement of panelBlockElements) { + panelBlockElement.classList.toggle("is-hidden"); + } + }; + + const lotTypeResponseHandler = (responseJSON: { + success: boolean; + errorMessage?: string; + lotTypes?: recordTypes.LotType[]; + }) => { + if (responseJSON.success) { + lotTypes = responseJSON.lotTypes; + renderLotTypes(); + } else { + bulmaJS.alert({ + title: "Error Updating " + exports.aliases.lot + " Type", + message: responseJSON.errorMessage, + contextualColorName: "danger" + }); + } + }; + + const deleteLotType = (clickEvent: Event) => { + const lotTypeId = Number.parseInt( + ( + (clickEvent.currentTarget as HTMLElement).closest( + ".container--lotType" + ) as HTMLElement + ).dataset.lotTypeId, + 10 + ); + + const doDelete = () => { + cityssm.postJSON( + urlPrefix + "/admin/doDeleteLotType", + { + lotTypeId + }, + lotTypeResponseHandler + ); + }; + + bulmaJS.confirm({ + title: "Delete " + exports.aliases.lot + " Type", + message: + "Are you sure you want to delete this " + + exports.aliases.lot.toLowerCase() + + " type?", + contextualColorName: "warning", + okButton: { + text: "Yes, Delete " + exports.aliases.lot + " Type", + callbackFunction: doDelete + } + }); + }; + + const openEditLotType = (clickEvent: Event) => { + const lotTypeId = Number.parseInt( + ( + (clickEvent.currentTarget as HTMLElement).closest( + ".container--lotType" + ) as HTMLElement + ).dataset.lotTypeId, + 10 + ); + + const lotType = lotTypes.find((currentLotType) => { + return lotTypeId === currentLotType.lotTypeId; + }); + + let editCloseModalFunction: () => void; + + const doEdit = (submitEvent: SubmitEvent) => { + submitEvent.preventDefault(); + + cityssm.postJSON( + urlPrefix + "/admin/doUpdateLotType", + submitEvent.currentTarget, + (responseJSON: { + success: boolean; + errorMessage?: string; + occupancyTypes?: recordTypes.OccupancyType[]; + }) => { + lotTypeResponseHandler(responseJSON); + if (responseJSON.success) { + editCloseModalFunction(); + } + } + ); + }; + + cityssm.openHtmlModal("adminLotTypes-editLotType", { + onshow: (modalElement) => { + los.populateAliases(modalElement); + + (modalElement.querySelector("#lotTypeEdit--lotTypeId") as HTMLInputElement).value = + lotTypeId.toString(); + + (modalElement.querySelector("#lotTypeEdit--lotType") as HTMLInputElement).value = + lotType.lotType; + }, + onshown: (modalElement, closeModalFunction) => { + editCloseModalFunction = closeModalFunction; + + (modalElement.querySelector("#lotTypeEdit--lotType") as HTMLInputElement).focus(); + + modalElement.querySelector("form").addEventListener("submit", doEdit); + + bulmaJS.toggleHtmlClipped(); + }, + onremoved: () => { + bulmaJS.toggleHtmlClipped(); + } + }); + }; + + const openAddLotTypeField = (clickEvent: Event) => { + const lotTypeId = Number.parseInt( + ( + (clickEvent.currentTarget as HTMLElement).closest( + ".container--lotType" + ) as HTMLElement + ).dataset.lotTypeId, + 10 + ); + + let addCloseModalFunction: () => void; + + const doAdd = (submitEvent: SubmitEvent) => { + submitEvent.preventDefault(); + + cityssm.postJSON( + urlPrefix + "/admin/doAddLotTypeField", + submitEvent.currentTarget, + (responseJSON: { + success: boolean; + errorMessage?: string; + lotTypes?: recordTypes.LotType[]; + lotTypeFieldId?: number; + }) => { + expandedLotTypes.add(lotTypeId); + lotTypeResponseHandler(responseJSON); + + if (responseJSON.success) { + addCloseModalFunction(); + openEditLotTypeField(lotTypeId, responseJSON.lotTypeFieldId); + } + } + ); + }; + + cityssm.openHtmlModal("adminLotTypes-addLotTypeField", { + onshow: (modalElement) => { + los.populateAliases(modalElement); + + if (lotTypeId) { + ( + modalElement.querySelector( + "#lotTypeFieldAdd--lotTypeId" + ) as HTMLInputElement + ).value = lotTypeId.toString(); + } + }, + onshown: (modalElement, closeModalFunction) => { + addCloseModalFunction = closeModalFunction; + + ( + modalElement.querySelector("#lotTypeFieldAdd--lotTypeField") as HTMLInputElement + ).focus(); + + modalElement.querySelector("form").addEventListener("submit", doAdd); + + bulmaJS.toggleHtmlClipped(); + }, + onremoved: () => { + bulmaJS.toggleHtmlClipped(); + } + }); + }; + + const moveLotTypeUp = (clickEvent: Event) => { + clickEvent.preventDefault(); + + const lotTypeId = ( + (clickEvent.currentTarget as HTMLElement).closest(".container--lotType") as HTMLElement + ).dataset.lotTypeId; + + cityssm.postJSON( + urlPrefix + "/admin/doMoveLotTypeUp", + { + lotTypeId + }, + lotTypeResponseHandler + ); + }; + + const moveLotTypeDown = (clickEvent: Event) => { + clickEvent.preventDefault(); + + const lotTypeId = ( + (clickEvent.currentTarget as HTMLElement).closest(".container--lotType") as HTMLElement + ).dataset.lotTypeId; + + cityssm.postJSON( + urlPrefix + "/admin/doMoveLotTypeDown", + { + lotTypeId + }, + lotTypeResponseHandler + ); + }; + + const openEditLotTypeField = (lotTypeId: number, lotTypeFieldId: number) => { + const lotType = lotTypes.find((currentLotType) => { + return currentLotType.lotTypeId === lotTypeId; + }); + + const lotTypeField = lotType.lotTypeFields.find((currentLotTypeField) => { + return currentLotTypeField.lotTypeFieldId === lotTypeFieldId; + }); + + let minimumLengthElement: HTMLInputElement; + let maximumLengthElement: HTMLInputElement; + let patternElement: HTMLInputElement; + let lotTypeFieldValuesElement: HTMLTextAreaElement; + + let editCloseModalFunction: () => void; + + const updateMaximumLengthMin = () => { + maximumLengthElement.min = minimumLengthElement.value; + }; + + const toggleInputFields = () => { + if (lotTypeFieldValuesElement.value === "") { + minimumLengthElement.disabled = false; + maximumLengthElement.disabled = false; + patternElement.disabled = false; + } else { + minimumLengthElement.disabled = true; + maximumLengthElement.disabled = true; + patternElement.disabled = true; + } + }; + + const doUpdate = (submitEvent: SubmitEvent) => { + submitEvent.preventDefault(); + + cityssm.postJSON( + urlPrefix + "/admin/doUpdateLotTypeField", + submitEvent.currentTarget, + (responseJSON: { + success: boolean; + errorMessage?: string; + occupancyTypes?: recordTypes.OccupancyType[]; + }) => { + lotTypeResponseHandler(responseJSON); + if (responseJSON.success) { + editCloseModalFunction(); + } + } + ); + }; + + const doDelete = () => { + const _doDelete = () => { + cityssm.postJSON( + urlPrefix + "/admin/doDeleteLotTypeField", + { + lotTypeFieldId + }, + (responseJSON: { + success: boolean; + errorMessage?: string; + lotTypes?: recordTypes.LotType[]; + }) => { + lotTypeResponseHandler(responseJSON); + if (responseJSON.success) { + editCloseModalFunction(); + } + } + ); + }; + + bulmaJS.confirm({ + title: "Delete Field", + message: + "Are you sure you want to delete this field? Note that historical records that make use of this field will not be affected.", + contextualColorName: "warning", + okButton: { + text: "Yes, Delete Field", + callbackFunction: _doDelete + } + }); + }; + + cityssm.openHtmlModal("adminLotTypes-editLotTypeField", { + onshow: (modalElement) => { + los.populateAliases(modalElement); + + ( + modalElement.querySelector( + "#lotTypeFieldEdit--lotTypeFieldId" + ) as HTMLInputElement + ).value = lotTypeField.lotTypeFieldId.toString(); + + ( + modalElement.querySelector( + "#lotTypeFieldEdit--lotTypeField" + ) as HTMLInputElement + ).value = lotTypeField.lotTypeField; + + ( + modalElement.querySelector("#lotTypeFieldEdit--isRequired") as HTMLSelectElement + ).value = lotTypeField.isRequired ? "1" : "0"; + + minimumLengthElement = modalElement.querySelector( + "#lotTypeFieldEdit--minimumLength" + ); + + minimumLengthElement.value = lotTypeField.minimumLength.toString(); + + maximumLengthElement = modalElement.querySelector( + "#lotTypeFieldEdit--maximumLength" + ); + + maximumLengthElement.value = lotTypeField.maximumLength.toString(); + + patternElement = modalElement.querySelector("#lotTypeFieldEdit--pattern"); + + patternElement.value = lotTypeField.pattern; + + lotTypeFieldValuesElement = modalElement.querySelector( + "#lotTypeFieldEdit--lotTypeFieldValues" + ); + + lotTypeFieldValuesElement.value = lotTypeField.lotTypeFieldValues; + + toggleInputFields(); + }, + onshown: (modalElement, closeModalFunction) => { + editCloseModalFunction = closeModalFunction; + + bulmaJS.init(modalElement); + bulmaJS.toggleHtmlClipped(); + cityssm.enableNavBlocker(); + + modalElement.querySelector("form").addEventListener("submit", doUpdate); + + minimumLengthElement.addEventListener("keyup", updateMaximumLengthMin); + updateMaximumLengthMin(); + + lotTypeFieldValuesElement.addEventListener("keyup", toggleInputFields); + + modalElement + .querySelector("#button--deleteLotTypeField") + .addEventListener("click", doDelete); + }, + onremoved: () => { + bulmaJS.toggleHtmlClipped(); + cityssm.disableNavBlocker(); + } + }); + }; + + const openEditLotTypeFieldByClick = (clickEvent: Event) => { + clickEvent.preventDefault(); + + const lotTypeFieldId = Number.parseInt( + ( + (clickEvent.currentTarget as HTMLElement).closest( + ".container--lotTypeField" + ) as HTMLElement + ).dataset.lotTypeFieldId, + 10 + ); + + const lotTypeId = Number.parseInt( + ( + (clickEvent.currentTarget as HTMLElement).closest( + ".container--lotType" + ) as HTMLElement + ).dataset.lotTypeId, + 10 + ); + + openEditLotTypeField(lotTypeId, lotTypeFieldId); + }; + + const moveLotTypeFieldUp = (clickEvent: Event) => { + clickEvent.preventDefault(); + + const lotTypeFieldId = ( + (clickEvent.currentTarget as HTMLElement).closest( + ".container--lotTypeField" + ) as HTMLElement + ).dataset.lotTypeFieldId; + + cityssm.postJSON( + urlPrefix + "/admin/doMoveLotTypeFieldUp", + { + lotTypeFieldId + }, + lotTypeResponseHandler + ); + }; + + const moveLotTypeFieldDown = (clickEvent: Event) => { + clickEvent.preventDefault(); + + const lotTypeFieldId = ( + (clickEvent.currentTarget as HTMLElement).closest( + ".container--lotTypeField" + ) as HTMLElement + ).dataset.lotTypeFieldId; + + cityssm.postJSON( + urlPrefix + "/admin/doMoveLotTypeFieldDown", + { + lotTypeFieldId + }, + lotTypeResponseHandler + ); + }; + + const renderLotTypeFields = ( + panelElement: HTMLElement, + lotTypeId: number, + lotTypeFields: recordTypes.LotTypeField[] + ) => { + if (lotTypeFields.length === 0) { + panelElement.insertAdjacentHTML( + "beforeend", + '
' + + '
' + + '

There are no additional fields.

' + + "
" + + "
" + ); + } else { + for (const lotTypeField of lotTypeFields) { + const panelBlockElement = document.createElement("div"); + panelBlockElement.className = "panel-block is-block container--lotTypeField"; + + if (!expandedLotTypes.has(lotTypeId)) { + panelBlockElement.classList.add("is-hidden"); + } + + panelBlockElement.dataset.lotTypeFieldId = lotTypeField.lotTypeFieldId.toString(); + + panelBlockElement.innerHTML = + '
' + + '" + + '
' + + ('
' + + '
' + + '
' + + '" + + "
" + + '
' + + '" + + "
" + + "
" + + "
") + + "
" + + "
"; + + panelBlockElement + .querySelector(".button--editLotTypeField") + .addEventListener("click", openEditLotTypeFieldByClick); + + panelBlockElement + .querySelector(".button--moveLotTypeFieldUp") + .addEventListener("click", moveLotTypeFieldUp); + + panelBlockElement + .querySelector(".button--moveLotTypeFieldDown") + .addEventListener("click", moveLotTypeFieldDown); + + panelElement.append(panelBlockElement); + } + } + }; + + const renderLotTypes = () => { + containerElement.innerHTML = ""; + + if (lotTypes.length === 0) { + containerElement.insertAdjacentHTML( + "afterbegin", + '
There are no active ' + + exports.aliases.lot.toLowerCase() + + " types.

" + + "
" + ); + + return; + } + + for (const lotType of lotTypes) { + const lotTypeContainer = document.createElement("div"); + + lotTypeContainer.className = "panel container--lotType"; + + lotTypeContainer.dataset.lotTypeId = lotType.lotTypeId.toString(); + + lotTypeContainer.innerHTML = + '
' + + '
' + + ('
' + + '
' + + '" + + "
" + + '
' + + '

' + + cityssm.escapeHTML(lotType.lotType) + + "

" + + "
" + + "
") + + ('
' + + ('
' + + '" + + "
") + + ('
' + + '" + + "
") + + ('
' + + '" + + "
") + + ('
' + + '
' + + '
' + + '" + + "
" + + '
' + + '" + + "
" + + "
" + + "
") + + "
") + + "
" + + "
"; + + renderLotTypeFields(lotTypeContainer, lotType.lotTypeId, lotType.lotTypeFields); + + lotTypeContainer + .querySelector(".button--toggleLotTypeFields") + .addEventListener("click", toggleLotTypeFields); + + lotTypeContainer + .querySelector(".button--deleteLotType") + .addEventListener("click", deleteLotType); + + lotTypeContainer + .querySelector(".button--editLotType") + .addEventListener("click", openEditLotType); + + lotTypeContainer + .querySelector(".button--addLotTypeField") + .addEventListener("click", openAddLotTypeField); + + lotTypeContainer + .querySelector(".button--moveLotTypeUp") + .addEventListener("click", moveLotTypeUp); + + lotTypeContainer + .querySelector(".button--moveLotTypeDown") + .addEventListener("click", moveLotTypeDown); + + containerElement.append(lotTypeContainer); + } + }; + + document.querySelector("#button--addLotType").addEventListener("click", () => { + let addCloseModalFunction: () => void; + + const doAdd = (submitEvent: SubmitEvent) => { + submitEvent.preventDefault(); + + cityssm.postJSON( + urlPrefix + "/admin/doAddLotType", + submitEvent.currentTarget, + (responseJSON: { + success: boolean; + errorMessage?: string; + lotTypes?: recordTypes.LotType[]; + }) => { + if (responseJSON.success) { + addCloseModalFunction(); + lotTypes = responseJSON.lotTypes; + renderLotTypes(); + } else { + bulmaJS.alert({ + title: "Error Adding " + exports.aliases.lot + " Type", + message: responseJSON.errorMessage, + contextualColorName: "danger" + }); + } + } + ); + }; + + cityssm.openHtmlModal("adminLotTypes-addLotType", { + onshow: (modalElement) => { + los.populateAliases(modalElement); + }, + onshown: (modalElement, closeModalFunction) => { + addCloseModalFunction = closeModalFunction; + + (modalElement.querySelector("#lotTypeAdd--lotType") as HTMLInputElement).focus(); + + modalElement.querySelector("form").addEventListener("submit", doAdd); + + bulmaJS.toggleHtmlClipped(); + }, + onremoved: () => { + bulmaJS.toggleHtmlClipped(); + } + }); + }); + + renderLotTypes(); +})(); diff --git a/public/html/adminLotTypes-addLotType.html b/public/html/adminLotTypes-addLotType.html new file mode 100644 index 00000000..2e59d270 --- /dev/null +++ b/public/html/adminLotTypes-addLotType.html @@ -0,0 +1,28 @@ + \ No newline at end of file diff --git a/public/html/adminLotTypes-addLotTypeField.html b/public/html/adminLotTypes-addLotTypeField.html new file mode 100644 index 00000000..dadf43e4 --- /dev/null +++ b/public/html/adminLotTypes-addLotTypeField.html @@ -0,0 +1,29 @@ + \ No newline at end of file diff --git a/public/html/adminLotTypes-editLotType.html b/public/html/adminLotTypes-editLotType.html new file mode 100644 index 00000000..5e01de0c --- /dev/null +++ b/public/html/adminLotTypes-editLotType.html @@ -0,0 +1,29 @@ + \ No newline at end of file diff --git a/public/html/adminLotTypes-editLotTypeField.html b/public/html/adminLotTypes-editLotTypeField.html new file mode 100644 index 00000000..8da446c2 --- /dev/null +++ b/public/html/adminLotTypes-editLotTypeField.html @@ -0,0 +1,105 @@ + \ No newline at end of file diff --git a/public/javascripts/adminLotTypes.min.js b/public/javascripts/adminLotTypes.min.js new file mode 100644 index 00000000..a0bcecf1 --- /dev/null +++ b/public/javascripts/adminLotTypes.min.js @@ -0,0 +1 @@ +"use strict";Object.defineProperty(exports,"__esModule",{value:!0}),(()=>{const e=exports.los,t=document.querySelector("main").dataset.urlPrefix,l=document.querySelector("#container--lotTypes");let o=exports.lotTypes;delete exports.lotTypes;const s=new Set,a=e=>{const t=e.currentTarget,l=t.closest(".container--lotType"),o=Number.parseInt(l.dataset.lotTypeId,10);s.has(o)?s.delete(o):s.add(o),t.innerHTML=s.has(o)?'':'';const a=l.querySelectorAll(".panel-block");for(const e of a)e.classList.toggle("is-hidden")},i=e=>{e.success?(o=e.lotTypes,b()):bulmaJS.alert({title:"Error Updating "+exports.aliases.lot+" Type",message:e.errorMessage,contextualColorName:"danger"})},d=e=>{const l=Number.parseInt(e.currentTarget.closest(".container--lotType").dataset.lotTypeId,10);bulmaJS.confirm({title:"Delete "+exports.aliases.lot+" Type",message:"Are you sure you want to delete this "+exports.aliases.lot.toLowerCase()+" type?",contextualColorName:"warning",okButton:{text:"Yes, Delete "+exports.aliases.lot+" Type",callbackFunction:()=>{cityssm.postJSON(t+"/admin/doDeleteLotType",{lotTypeId:l},i)}}})},n=l=>{const s=Number.parseInt(l.currentTarget.closest(".container--lotType").dataset.lotTypeId,10),a=o.find(e=>s===e.lotTypeId);let d;const n=e=>{e.preventDefault(),cityssm.postJSON(t+"/admin/doUpdateLotType",e.currentTarget,e=>{i(e),e.success&&d()})};cityssm.openHtmlModal("adminLotTypes-editLotType",{onshow:t=>{e.populateAliases(t),t.querySelector("#lotTypeEdit--lotTypeId").value=s.toString(),t.querySelector("#lotTypeEdit--lotType").value=a.lotType},onshown:(e,t)=>{d=t,e.querySelector("#lotTypeEdit--lotType").focus(),e.querySelector("form").addEventListener("submit",n),bulmaJS.toggleHtmlClipped()},onremoved:()=>{bulmaJS.toggleHtmlClipped()}})},r=l=>{const o=Number.parseInt(l.currentTarget.closest(".container--lotType").dataset.lotTypeId,10);let a;const d=e=>{e.preventDefault(),cityssm.postJSON(t+"/admin/doAddLotTypeField",e.currentTarget,e=>{s.add(o),i(e),e.success&&(a(),u(o,e.lotTypeFieldId))})};cityssm.openHtmlModal("adminLotTypes-addLotTypeField",{onshow:t=>{e.populateAliases(t),o&&(t.querySelector("#lotTypeFieldAdd--lotTypeId").value=o.toString())},onshown:(e,t)=>{a=t,e.querySelector("#lotTypeFieldAdd--lotTypeField").focus(),e.querySelector("form").addEventListener("submit",d),bulmaJS.toggleHtmlClipped()},onremoved:()=>{bulmaJS.toggleHtmlClipped()}})},p=e=>{e.preventDefault();const l=e.currentTarget.closest(".container--lotType").dataset.lotTypeId;cityssm.postJSON(t+"/admin/doMoveLotTypeUp",{lotTypeId:l},i)},c=e=>{e.preventDefault();const l=e.currentTarget.closest(".container--lotType").dataset.lotTypeId;cityssm.postJSON(t+"/admin/doMoveLotTypeDown",{lotTypeId:l},i)},u=(l,s)=>{const a=o.find(e=>e.lotTypeId===l).lotTypeFields.find(e=>e.lotTypeFieldId===s);let d,n,r,p,c;const u=()=>{n.min=d.value},y=()=>{""===p.value?(d.disabled=!1,n.disabled=!1,r.disabled=!1):(d.disabled=!0,n.disabled=!0,r.disabled=!0)},m=e=>{e.preventDefault(),cityssm.postJSON(t+"/admin/doUpdateLotTypeField",e.currentTarget,e=>{i(e),e.success&&c()})},T=()=>{bulmaJS.confirm({title:"Delete Field",message:"Are you sure you want to delete this field? Note that historical records that make use of this field will not be affected.",contextualColorName:"warning",okButton:{text:"Yes, Delete Field",callbackFunction:()=>{cityssm.postJSON(t+"/admin/doDeleteLotTypeField",{lotTypeFieldId:s},e=>{i(e),e.success&&c()})}}})};cityssm.openHtmlModal("adminLotTypes-editLotTypeField",{onshow:t=>{e.populateAliases(t),t.querySelector("#lotTypeFieldEdit--lotTypeFieldId").value=a.lotTypeFieldId.toString(),t.querySelector("#lotTypeFieldEdit--lotTypeField").value=a.lotTypeField,t.querySelector("#lotTypeFieldEdit--isRequired").value=a.isRequired?"1":"0",(d=t.querySelector("#lotTypeFieldEdit--minimumLength")).value=a.minimumLength.toString(),(n=t.querySelector("#lotTypeFieldEdit--maximumLength")).value=a.maximumLength.toString(),(r=t.querySelector("#lotTypeFieldEdit--pattern")).value=a.pattern,(p=t.querySelector("#lotTypeFieldEdit--lotTypeFieldValues")).value=a.lotTypeFieldValues,y()},onshown:(e,t)=>{c=t,bulmaJS.init(e),bulmaJS.toggleHtmlClipped(),cityssm.enableNavBlocker(),e.querySelector("form").addEventListener("submit",m),d.addEventListener("keyup",u),u(),p.addEventListener("keyup",y),e.querySelector("#button--deleteLotTypeField").addEventListener("click",T)},onremoved:()=>{bulmaJS.toggleHtmlClipped(),cityssm.disableNavBlocker()}})},y=e=>{e.preventDefault();const t=Number.parseInt(e.currentTarget.closest(".container--lotTypeField").dataset.lotTypeFieldId,10),l=Number.parseInt(e.currentTarget.closest(".container--lotType").dataset.lotTypeId,10);u(l,t)},m=e=>{e.preventDefault();const l=e.currentTarget.closest(".container--lotTypeField").dataset.lotTypeFieldId;cityssm.postJSON(t+"/admin/doMoveLotTypeFieldUp",{lotTypeFieldId:l},i)},T=e=>{e.preventDefault();const l=e.currentTarget.closest(".container--lotTypeField").dataset.lotTypeFieldId;cityssm.postJSON(t+"/admin/doMoveLotTypeFieldDown",{lotTypeFieldId:l},i)},v=(e,t,l)=>{if(0===l.length)e.insertAdjacentHTML("beforeend",'

There are no additional fields.

');else for(const o of l){const l=document.createElement("div");l.className="panel-block is-block container--lotTypeField",s.has(t)||l.classList.add("is-hidden"),l.dataset.lotTypeFieldId=o.lotTypeFieldId.toString(),l.innerHTML='
',l.querySelector(".button--editLotTypeField").addEventListener("click",y),l.querySelector(".button--moveLotTypeFieldUp").addEventListener("click",m),l.querySelector(".button--moveLotTypeFieldDown").addEventListener("click",T),e.append(l)}},b=()=>{if(l.innerHTML="",0!==o.length)for(const e of o){const t=document.createElement("div");t.className="panel container--lotType",t.dataset.lotTypeId=e.lotTypeId.toString(),t.innerHTML='

'+cityssm.escapeHTML(e.lotType)+'

',v(t,e.lotTypeId,e.lotTypeFields),t.querySelector(".button--toggleLotTypeFields").addEventListener("click",a),t.querySelector(".button--deleteLotType").addEventListener("click",d),t.querySelector(".button--editLotType").addEventListener("click",n),t.querySelector(".button--addLotTypeField").addEventListener("click",r),t.querySelector(".button--moveLotTypeUp").addEventListener("click",p),t.querySelector(".button--moveLotTypeDown").addEventListener("click",c),l.append(t)}else l.insertAdjacentHTML("afterbegin",'
There are no active '+exports.aliases.lot.toLowerCase()+" types.

")};document.querySelector("#button--addLotType").addEventListener("click",()=>{let l;const s=e=>{e.preventDefault(),cityssm.postJSON(t+"/admin/doAddLotType",e.currentTarget,e=>{e.success?(l(),o=e.lotTypes,b()):bulmaJS.alert({title:"Error Adding "+exports.aliases.lot+" Type",message:e.errorMessage,contextualColorName:"danger"})})};cityssm.openHtmlModal("adminLotTypes-addLotType",{onshow:t=>{e.populateAliases(t)},onshown:(e,t)=>{l=t,e.querySelector("#lotTypeAdd--lotType").focus(),e.querySelector("form").addEventListener("submit",s),bulmaJS.toggleHtmlClipped()},onremoved:()=>{bulmaJS.toggleHtmlClipped()}})}),b()})(); \ No newline at end of file diff --git a/routes/admin.js b/routes/admin.js index 39c5fdd3..3557d9ce 100644 --- a/routes/admin.js +++ b/routes/admin.js @@ -22,6 +22,17 @@ import handler_doUpdateOccupancyTypeField from "../handlers/admin-post/doUpdateO import handler_doMoveOccupancyTypeFieldUp from "../handlers/admin-post/doMoveOccupancyTypeFieldUp.js"; import handler_doMoveOccupancyTypeFieldDown from "../handlers/admin-post/doMoveOccupancyTypeFieldDown.js"; import handler_doDeleteOccupancyTypeField from "../handlers/admin-post/doDeleteOccupancyTypeField.js"; +import handler_lotTypes from "../handlers/admin-get/lotTypes.js"; +import handler_doAddLotType from "../handlers/admin-post/doAddLotType.js"; +import handler_doUpdateLotType from "../handlers/admin-post/doUpdateLotType.js"; +import handler_doMoveLotTypeUp from "../handlers/admin-post/doMoveLotTypeUp.js"; +import handler_doMoveLotTypeDown from "../handlers/admin-post/doMoveLotTypeDown.js"; +import handler_doDeleteLotType from "../handlers/admin-post/doDeleteLotType.js"; +import handler_doAddLotTypeField from "../handlers/admin-post/doAddLotTypeField.js"; +import handler_doUpdateLotTypeField from "../handlers/admin-post/doUpdateLotTypeField.js"; +import handler_doMoveLotTypeFieldUp from "../handlers/admin-post/doMoveLotTypeFieldUp.js"; +import handler_doMoveLotTypeFieldDown from "../handlers/admin-post/doMoveLotTypeFieldDown.js"; +import handler_doDeleteLotTypeField from "../handlers/admin-post/doDeleteLotTypeField.js"; import handler_tables from "../handlers/admin-get/tables.js"; import handler_doAddWorkOrderType from "../handlers/admin-post/doAddWorkOrderType.js"; import handler_doUpdateWorkOrderType from "../handlers/admin-post/doUpdateWorkOrderType.js"; @@ -68,6 +79,17 @@ router.post("/doUpdateOccupancyTypeField", permissionHandlers.adminPostHandler, router.post("/doMoveOccupancyTypeFieldUp", permissionHandlers.adminPostHandler, handler_doMoveOccupancyTypeFieldUp); router.post("/doMoveOccupancyTypeFieldDown", permissionHandlers.adminPostHandler, handler_doMoveOccupancyTypeFieldDown); router.post("/doDeleteOccupancyTypeField", permissionHandlers.adminPostHandler, handler_doDeleteOccupancyTypeField); +router.get("/lotTypes", permissionHandlers.adminGetHandler, handler_lotTypes); +router.post("/doAddLotType", permissionHandlers.adminPostHandler, handler_doAddLotType); +router.post("/doUpdateLotType", permissionHandlers.adminPostHandler, handler_doUpdateLotType); +router.post("/doMoveLotTypeUp", permissionHandlers.adminPostHandler, handler_doMoveLotTypeUp); +router.post("/doMoveLotTypeDown", permissionHandlers.adminPostHandler, handler_doMoveLotTypeDown); +router.post("/doDeleteLotType", permissionHandlers.adminPostHandler, handler_doDeleteLotType); +router.post("/doAddLotTypeField", permissionHandlers.adminPostHandler, handler_doAddLotTypeField); +router.post("/doUpdateLotTypeField", permissionHandlers.adminPostHandler, handler_doUpdateLotTypeField); +router.post("/doMoveLotTypeFieldUp", permissionHandlers.adminPostHandler, handler_doMoveLotTypeFieldUp); +router.post("/doMoveLotTypeFieldDown", permissionHandlers.adminPostHandler, handler_doMoveLotTypeFieldDown); +router.post("/doDeleteLotTypeField", permissionHandlers.adminPostHandler, handler_doDeleteLotTypeField); router.get("/tables", permissionHandlers.adminGetHandler, handler_tables); router.post("/doAddWorkOrderType", permissionHandlers.adminPostHandler, handler_doAddWorkOrderType); router.post("/doUpdateWorkOrderType", permissionHandlers.adminPostHandler, handler_doUpdateWorkOrderType); diff --git a/routes/admin.ts b/routes/admin.ts index f57adcb1..63f2cb48 100644 --- a/routes/admin.ts +++ b/routes/admin.ts @@ -34,6 +34,22 @@ import handler_doMoveOccupancyTypeFieldUp from "../handlers/admin-post/doMoveOcc import handler_doMoveOccupancyTypeFieldDown from "../handlers/admin-post/doMoveOccupancyTypeFieldDown.js"; import handler_doDeleteOccupancyTypeField from "../handlers/admin-post/doDeleteOccupancyTypeField.js"; +// Lot Type Management + +import handler_lotTypes from "../handlers/admin-get/lotTypes.js"; + +import handler_doAddLotType from "../handlers/admin-post/doAddLotType.js"; +import handler_doUpdateLotType from "../handlers/admin-post/doUpdateLotType.js"; +import handler_doMoveLotTypeUp from "../handlers/admin-post/doMoveLotTypeUp.js"; +import handler_doMoveLotTypeDown from "../handlers/admin-post/doMoveLotTypeDown.js"; +import handler_doDeleteLotType from "../handlers/admin-post/doDeleteLotType.js"; + +import handler_doAddLotTypeField from "../handlers/admin-post/doAddLotTypeField.js"; +import handler_doUpdateLotTypeField from "../handlers/admin-post/doUpdateLotTypeField.js"; +import handler_doMoveLotTypeFieldUp from "../handlers/admin-post/doMoveLotTypeFieldUp.js"; +import handler_doMoveLotTypeFieldDown from "../handlers/admin-post/doMoveLotTypeFieldDown.js"; +import handler_doDeleteLotTypeField from "../handlers/admin-post/doDeleteLotTypeField.js"; + // Config Table Management import handler_tables from "../handlers/admin-get/tables.js"; @@ -175,6 +191,50 @@ router.post( handler_doDeleteOccupancyTypeField ); +/* + * Lot Type Management + */ + +router.get("/lotTypes", permissionHandlers.adminGetHandler, handler_lotTypes); + +router.post("/doAddLotType", permissionHandlers.adminPostHandler, handler_doAddLotType); + +router.post("/doUpdateLotType", permissionHandlers.adminPostHandler, handler_doUpdateLotType); + +router.post("/doMoveLotTypeUp", permissionHandlers.adminPostHandler, handler_doMoveLotTypeUp); + +router.post("/doMoveLotTypeDown", permissionHandlers.adminPostHandler, handler_doMoveLotTypeDown); + +router.post("/doDeleteLotType", permissionHandlers.adminPostHandler, handler_doDeleteLotType); + +// Lot Type Fields + +router.post("/doAddLotTypeField", permissionHandlers.adminPostHandler, handler_doAddLotTypeField); + +router.post( + "/doUpdateLotTypeField", + permissionHandlers.adminPostHandler, + handler_doUpdateLotTypeField +); + +router.post( + "/doMoveLotTypeFieldUp", + permissionHandlers.adminPostHandler, + handler_doMoveLotTypeFieldUp +); + +router.post( + "/doMoveLotTypeFieldDown", + permissionHandlers.adminPostHandler, + handler_doMoveLotTypeFieldDown +); + +router.post( + "/doDeleteLotTypeField", + permissionHandlers.adminPostHandler, + handler_doDeleteLotTypeField +); + /* * Config Tables */ diff --git a/views/_menu-admin.ejs b/views/_menu-admin.ejs index 2ef77907..127afaec 100644 --- a/views/_menu-admin.ejs +++ b/views/_menu-admin.ejs @@ -10,11 +10,17 @@
  • - " href="<%= urlPrefix %>/admin/occupancyTypes"> + " href="<%= urlPrefix %>/admin/occupancyTypes"> <%= configFunctions.getProperty("aliases.occupancy") %> Type Management
  • +
  • + " href="<%= urlPrefix %>/admin/lotTypes"> + + <%= configFunctions.getProperty("aliases.lot") %> Type Management + +
  • " href="<%= urlPrefix %>/admin/tables"> diff --git a/views/admin-lotTypes.ejs b/views/admin-lotTypes.ejs new file mode 100644 index 00000000..447f9aff --- /dev/null +++ b/views/admin-lotTypes.ejs @@ -0,0 +1,56 @@ +<%- include('_header'); -%> + +
    +
    + <%- include('_menu-admin'); -%> +
    +
    + + +
    +
    +
    +

    + <%= configFunctions.getProperty("aliases.lot") %> Type Management +

    +
    +
    +
    +
    + +
    +
    +
    + +
    +
    +
    + +<%- include('_footerA'); -%> + + + + + +<%- include('_footerB'); -%> diff --git a/views/dashboard.ejs b/views/dashboard.ejs index 42a75079..828b323e 100644 --- a/views/dashboard.ejs +++ b/views/dashboard.ejs @@ -294,6 +294,23 @@ +
    +
    +
    + +
    +
    +

    + <%= configFunctions.getProperty("aliases.lot") %> Type Management +

    +

    + Manage + <%= configFunctions.getProperty("aliases.lot").toLowerCase() %> types + and fields associated with them. +

    +
    +
    +