From ab87f933c775857c8515c795d3414fcc7114d5e8 Mon Sep 17 00:00:00 2001 From: Dan Gowans Date: Fri, 9 Sep 2022 16:11:53 -0400 Subject: [PATCH] work order development --- handlers/workOrders-get/edit.js | 10 +- handlers/workOrders-get/edit.ts | 14 +- .../workOrders-post/doDeleteWorkOrderLot.d.ts | 3 + .../workOrders-post/doDeleteWorkOrderLot.js | 16 + .../workOrders-post/doDeleteWorkOrderLot.ts | 29 ++ .../doDeleteWorkOrderLotOccupancy.d.ts | 3 + .../doDeleteWorkOrderLotOccupancy.js | 17 + .../doDeleteWorkOrderLotOccupancy.ts | 30 ++ .../workOrders-post/doReopenWorkOrder.d.ts | 3 + handlers/workOrders-post/doReopenWorkOrder.js | 9 + handlers/workOrders-post/doReopenWorkOrder.ts | 14 + .../workOrders-post/doUpdateWorkOrder.d.ts | 3 + handlers/workOrders-post/doUpdateWorkOrder.js | 9 + handlers/workOrders-post/doUpdateWorkOrder.ts | 14 + .../lotOccupancyDB/deleteWorkOrderLot.d.ts | 3 + helpers/lotOccupancyDB/deleteWorkOrderLot.js | 16 + helpers/lotOccupancyDB/deleteWorkOrderLot.ts | 31 ++ .../deleteWorkOrderLotOccupancy.d.ts | 3 + .../deleteWorkOrderLotOccupancy.js | 16 + .../deleteWorkOrderLotOccupancy.ts | 31 ++ public-typescript/workOrderEdit.d.ts | 1 + public-typescript/workOrderEdit.js | 273 +++++++++++++ public-typescript/workOrderEdit.ts | 376 ++++++++++++++++++ public-typescript/workOrderView.d.ts | 1 + public-typescript/workOrderView.js | 41 ++ public-typescript/workOrderView.ts | 61 +++ public/javascripts/workOrderEdit.min.js | 1 + public/javascripts/workOrderView.min.js | 1 + routes/workOrders.js | 8 + routes/workOrders.ts | 34 +- types/recordTypes.d.ts | 4 +- types/recordTypes.ts | 4 +- views/workOrder-edit.ejs | 182 ++++++++- views/workOrder-view.ejs | 40 +- 34 files changed, 1282 insertions(+), 19 deletions(-) create mode 100644 handlers/workOrders-post/doDeleteWorkOrderLot.d.ts create mode 100644 handlers/workOrders-post/doDeleteWorkOrderLot.js create mode 100644 handlers/workOrders-post/doDeleteWorkOrderLot.ts create mode 100644 handlers/workOrders-post/doDeleteWorkOrderLotOccupancy.d.ts create mode 100644 handlers/workOrders-post/doDeleteWorkOrderLotOccupancy.js create mode 100644 handlers/workOrders-post/doDeleteWorkOrderLotOccupancy.ts create mode 100644 handlers/workOrders-post/doReopenWorkOrder.d.ts create mode 100644 handlers/workOrders-post/doReopenWorkOrder.js create mode 100644 handlers/workOrders-post/doReopenWorkOrder.ts create mode 100644 handlers/workOrders-post/doUpdateWorkOrder.d.ts create mode 100644 handlers/workOrders-post/doUpdateWorkOrder.js create mode 100644 handlers/workOrders-post/doUpdateWorkOrder.ts create mode 100644 helpers/lotOccupancyDB/deleteWorkOrderLot.d.ts create mode 100644 helpers/lotOccupancyDB/deleteWorkOrderLot.js create mode 100644 helpers/lotOccupancyDB/deleteWorkOrderLot.ts create mode 100644 helpers/lotOccupancyDB/deleteWorkOrderLotOccupancy.d.ts create mode 100644 helpers/lotOccupancyDB/deleteWorkOrderLotOccupancy.js create mode 100644 helpers/lotOccupancyDB/deleteWorkOrderLotOccupancy.ts create mode 100644 public-typescript/workOrderEdit.d.ts create mode 100644 public-typescript/workOrderEdit.js create mode 100644 public-typescript/workOrderEdit.ts create mode 100644 public-typescript/workOrderView.d.ts create mode 100644 public-typescript/workOrderView.js create mode 100644 public-typescript/workOrderView.ts create mode 100644 public/javascripts/workOrderEdit.min.js create mode 100644 public/javascripts/workOrderView.min.js diff --git a/handlers/workOrders-get/edit.js b/handlers/workOrders-get/edit.js index 92ecd479..2d53fdca 100644 --- a/handlers/workOrders-get/edit.js +++ b/handlers/workOrders-get/edit.js @@ -1,3 +1,4 @@ +import { getWorkOrderTypes } from "../../helpers/functions.cache.js"; import * as configFunctions from "../../helpers/functions.config.js"; import { getWorkOrder } from "../../helpers/lotOccupancyDB/getWorkOrder.js"; export const handler = (request, response) => { @@ -6,9 +7,16 @@ export const handler = (request, response) => { return response.redirect(configFunctions.getProperty("reverseProxy.urlPrefix") + "/workOrders/?error=workOrderIdNotFound"); } + if (workOrder.workOrderCloseDate) { + return response.redirect(configFunctions.getProperty("reverseProxy.urlPrefix") + + "/workOrders/" + workOrder.workOrderId.toString() + "/?error=workOrderIsClosed"); + } + const workOrderTypes = getWorkOrderTypes(); response.render("workOrder-edit", { headTitle: "Work Order #" + workOrder.workOrderNumber, - workOrder + workOrder, + isCreate: false, + workOrderTypes }); }; export default handler; diff --git a/handlers/workOrders-get/edit.ts b/handlers/workOrders-get/edit.ts index aa5b952c..f4cb7953 100644 --- a/handlers/workOrders-get/edit.ts +++ b/handlers/workOrders-get/edit.ts @@ -1,4 +1,5 @@ import type { RequestHandler } from "express"; +import { getWorkOrderTypes } from "../../helpers/functions.cache.js"; import * as configFunctions from "../../helpers/functions.config.js"; @@ -14,9 +15,20 @@ export const handler: RequestHandler = (request, response) => { ); } + if (workOrder.workOrderCloseDate) { + return response.redirect( + configFunctions.getProperty("reverseProxy.urlPrefix") + + "/workOrders/" + workOrder.workOrderId.toString() + "/?error=workOrderIsClosed" + ); + } + + const workOrderTypes = getWorkOrderTypes(); + response.render("workOrder-edit", { headTitle: "Work Order #" + workOrder.workOrderNumber, - workOrder + workOrder, + isCreate: false, + workOrderTypes }); }; diff --git a/handlers/workOrders-post/doDeleteWorkOrderLot.d.ts b/handlers/workOrders-post/doDeleteWorkOrderLot.d.ts new file mode 100644 index 00000000..9621c611 --- /dev/null +++ b/handlers/workOrders-post/doDeleteWorkOrderLot.d.ts @@ -0,0 +1,3 @@ +import type { RequestHandler } from "express"; +export declare const handler: RequestHandler; +export default handler; diff --git a/handlers/workOrders-post/doDeleteWorkOrderLot.js b/handlers/workOrders-post/doDeleteWorkOrderLot.js new file mode 100644 index 00000000..0fa5719c --- /dev/null +++ b/handlers/workOrders-post/doDeleteWorkOrderLot.js @@ -0,0 +1,16 @@ +import { deleteWorkOrderLot } from "../../helpers/lotOccupancyDB/deleteWorkOrderLot.js"; +import { getLots } from "../../helpers/lotOccupancyDB/getLots.js"; +export const handler = async (request, response) => { + const success = deleteWorkOrderLot(request.body.workOrderId, request.body.lotId, request.session); + const workOrderLots = getLots({ + workOrderId: request.body.workOrderId + }, { + limit: -1, + offset: 0 + }).lots; + response.json({ + success, + workOrderLots + }); +}; +export default handler; diff --git a/handlers/workOrders-post/doDeleteWorkOrderLot.ts b/handlers/workOrders-post/doDeleteWorkOrderLot.ts new file mode 100644 index 00000000..806c9cbf --- /dev/null +++ b/handlers/workOrders-post/doDeleteWorkOrderLot.ts @@ -0,0 +1,29 @@ +import type { RequestHandler } from "express"; + +import { deleteWorkOrderLot } from "../../helpers/lotOccupancyDB/deleteWorkOrderLot.js"; +import { getLots } from "../../helpers/lotOccupancyDB/getLots.js"; + +export const handler: RequestHandler = async (request, response) => { + const success = deleteWorkOrderLot( + request.body.workOrderId, + request.body.lotId, + request.session + ); + + const workOrderLots = getLots( + { + workOrderId: request.body.workOrderId + }, + { + limit: -1, + offset: 0 + } + ).lots; + + response.json({ + success, + workOrderLots + }); +}; + +export default handler; diff --git a/handlers/workOrders-post/doDeleteWorkOrderLotOccupancy.d.ts b/handlers/workOrders-post/doDeleteWorkOrderLotOccupancy.d.ts new file mode 100644 index 00000000..9621c611 --- /dev/null +++ b/handlers/workOrders-post/doDeleteWorkOrderLotOccupancy.d.ts @@ -0,0 +1,3 @@ +import type { RequestHandler } from "express"; +export declare const handler: RequestHandler; +export default handler; diff --git a/handlers/workOrders-post/doDeleteWorkOrderLotOccupancy.js b/handlers/workOrders-post/doDeleteWorkOrderLotOccupancy.js new file mode 100644 index 00000000..c2f0c675 --- /dev/null +++ b/handlers/workOrders-post/doDeleteWorkOrderLotOccupancy.js @@ -0,0 +1,17 @@ +import { deleteWorkOrderLotOccupancy } from "../../helpers/lotOccupancyDB/deleteWorkOrderLotOccupancy.js"; +import { getLotOccupancies } from "../../helpers/lotOccupancyDB/getLotOccupancies.js"; +export const handler = async (request, response) => { + const success = deleteWorkOrderLotOccupancy(request.body.workOrderId, request.body.lotOccupancyId, request.session); + const workOrderLotOccupancies = getLotOccupancies({ + workOrderId: request.body.workOrderId + }, { + limit: -1, + offset: 0, + includeOccupants: true + }).lotOccupancies; + response.json({ + success, + workOrderLotOccupancies + }); +}; +export default handler; diff --git a/handlers/workOrders-post/doDeleteWorkOrderLotOccupancy.ts b/handlers/workOrders-post/doDeleteWorkOrderLotOccupancy.ts new file mode 100644 index 00000000..a96c74ac --- /dev/null +++ b/handlers/workOrders-post/doDeleteWorkOrderLotOccupancy.ts @@ -0,0 +1,30 @@ +import type { RequestHandler } from "express"; + +import { deleteWorkOrderLotOccupancy } from "../../helpers/lotOccupancyDB/deleteWorkOrderLotOccupancy.js"; +import { getLotOccupancies } from "../../helpers/lotOccupancyDB/getLotOccupancies.js"; + +export const handler: RequestHandler = async (request, response) => { + const success = deleteWorkOrderLotOccupancy( + request.body.workOrderId, + request.body.lotOccupancyId, + request.session + ); + + const workOrderLotOccupancies = getLotOccupancies( + { + workOrderId: request.body.workOrderId + }, + { + limit: -1, + offset: 0, + includeOccupants: true + } + ).lotOccupancies; + + response.json({ + success, + workOrderLotOccupancies + }); +}; + +export default handler; diff --git a/handlers/workOrders-post/doReopenWorkOrder.d.ts b/handlers/workOrders-post/doReopenWorkOrder.d.ts new file mode 100644 index 00000000..9621c611 --- /dev/null +++ b/handlers/workOrders-post/doReopenWorkOrder.d.ts @@ -0,0 +1,3 @@ +import type { RequestHandler } from "express"; +export declare const handler: RequestHandler; +export default handler; diff --git a/handlers/workOrders-post/doReopenWorkOrder.js b/handlers/workOrders-post/doReopenWorkOrder.js new file mode 100644 index 00000000..56c0f7a0 --- /dev/null +++ b/handlers/workOrders-post/doReopenWorkOrder.js @@ -0,0 +1,9 @@ +import { reopenWorkOrder } from "../../helpers/lotOccupancyDB/reopenWorkOrder.js"; +export const handler = async (request, response) => { + const success = reopenWorkOrder(request.body.workOrderId, request.session); + response.json({ + success, + workOrderId: request.body.workOrderId + }); +}; +export default handler; diff --git a/handlers/workOrders-post/doReopenWorkOrder.ts b/handlers/workOrders-post/doReopenWorkOrder.ts new file mode 100644 index 00000000..d0644749 --- /dev/null +++ b/handlers/workOrders-post/doReopenWorkOrder.ts @@ -0,0 +1,14 @@ +import type { RequestHandler } from "express"; + +import { reopenWorkOrder } from "../../helpers/lotOccupancyDB/reopenWorkOrder.js"; + +export const handler: RequestHandler = async (request, response) => { + const success = reopenWorkOrder(request.body.workOrderId, request.session); + + response.json({ + success, + workOrderId: request.body.workOrderId + }); +}; + +export default handler; diff --git a/handlers/workOrders-post/doUpdateWorkOrder.d.ts b/handlers/workOrders-post/doUpdateWorkOrder.d.ts new file mode 100644 index 00000000..9621c611 --- /dev/null +++ b/handlers/workOrders-post/doUpdateWorkOrder.d.ts @@ -0,0 +1,3 @@ +import type { RequestHandler } from "express"; +export declare const handler: RequestHandler; +export default handler; diff --git a/handlers/workOrders-post/doUpdateWorkOrder.js b/handlers/workOrders-post/doUpdateWorkOrder.js new file mode 100644 index 00000000..e25716d4 --- /dev/null +++ b/handlers/workOrders-post/doUpdateWorkOrder.js @@ -0,0 +1,9 @@ +import { updateWorkOrder } from "../../helpers/lotOccupancyDB/updateWorkOrder.js"; +export const handler = async (request, response) => { + const success = updateWorkOrder(request.body, request.session); + response.json({ + success, + workOrderId: request.body.workOrderId + }); +}; +export default handler; diff --git a/handlers/workOrders-post/doUpdateWorkOrder.ts b/handlers/workOrders-post/doUpdateWorkOrder.ts new file mode 100644 index 00000000..7765c282 --- /dev/null +++ b/handlers/workOrders-post/doUpdateWorkOrder.ts @@ -0,0 +1,14 @@ +import type { RequestHandler } from "express"; + +import { updateWorkOrder } from "../../helpers/lotOccupancyDB/updateWorkOrder.js"; + +export const handler: RequestHandler = async (request, response) => { + const success = updateWorkOrder(request.body, request.session); + + response.json({ + success, + workOrderId: request.body.workOrderId + }); +}; + +export default handler; diff --git a/helpers/lotOccupancyDB/deleteWorkOrderLot.d.ts b/helpers/lotOccupancyDB/deleteWorkOrderLot.d.ts new file mode 100644 index 00000000..e37b6ba0 --- /dev/null +++ b/helpers/lotOccupancyDB/deleteWorkOrderLot.d.ts @@ -0,0 +1,3 @@ +import type * as recordTypes from "../../types/recordTypes"; +export declare const deleteWorkOrderLot: (workOrderId: number | string, lotId: number | string, requestSession: recordTypes.PartialSession) => boolean; +export default deleteWorkOrderLot; diff --git a/helpers/lotOccupancyDB/deleteWorkOrderLot.js b/helpers/lotOccupancyDB/deleteWorkOrderLot.js new file mode 100644 index 00000000..5f9e6fd4 --- /dev/null +++ b/helpers/lotOccupancyDB/deleteWorkOrderLot.js @@ -0,0 +1,16 @@ +import sqlite from "better-sqlite3"; +import { lotOccupancyDB as databasePath } from "../../data/databasePaths.js"; +export const deleteWorkOrderLot = (workOrderId, lotId, requestSession) => { + const database = sqlite(databasePath); + const rightNowMillis = Date.now(); + const result = database + .prepare("update WorkOrderLots" + + " set recordDelete_userName = ?," + + " recordDelete_timeMillis = ?" + + " where workOrderId = ?" + + " and lotId = ?") + .run(requestSession.user.userName, rightNowMillis, workOrderId, lotId); + database.close(); + return result.changes > 0; +}; +export default deleteWorkOrderLot; diff --git a/helpers/lotOccupancyDB/deleteWorkOrderLot.ts b/helpers/lotOccupancyDB/deleteWorkOrderLot.ts new file mode 100644 index 00000000..367ae656 --- /dev/null +++ b/helpers/lotOccupancyDB/deleteWorkOrderLot.ts @@ -0,0 +1,31 @@ +import sqlite from "better-sqlite3"; + +import { lotOccupancyDB as databasePath } from "../../data/databasePaths.js"; + +import type * as recordTypes from "../../types/recordTypes"; + +export const deleteWorkOrderLot = ( + workOrderId: number | string, + lotId: number | string, + requestSession: recordTypes.PartialSession +): boolean => { + const database = sqlite(databasePath); + + const rightNowMillis = Date.now(); + + const result = database + .prepare( + "update WorkOrderLots" + + " set recordDelete_userName = ?," + + " recordDelete_timeMillis = ?" + + " where workOrderId = ?" + + " and lotId = ?" + ) + .run(requestSession.user.userName, rightNowMillis, workOrderId, lotId); + + database.close(); + + return result.changes > 0; +}; + +export default deleteWorkOrderLot; diff --git a/helpers/lotOccupancyDB/deleteWorkOrderLotOccupancy.d.ts b/helpers/lotOccupancyDB/deleteWorkOrderLotOccupancy.d.ts new file mode 100644 index 00000000..c9b9430d --- /dev/null +++ b/helpers/lotOccupancyDB/deleteWorkOrderLotOccupancy.d.ts @@ -0,0 +1,3 @@ +import type * as recordTypes from "../../types/recordTypes"; +export declare const deleteWorkOrderLotOccupancy: (workOrderId: number | string, lotOccupancyId: number | string, requestSession: recordTypes.PartialSession) => boolean; +export default deleteWorkOrderLotOccupancy; diff --git a/helpers/lotOccupancyDB/deleteWorkOrderLotOccupancy.js b/helpers/lotOccupancyDB/deleteWorkOrderLotOccupancy.js new file mode 100644 index 00000000..35d43374 --- /dev/null +++ b/helpers/lotOccupancyDB/deleteWorkOrderLotOccupancy.js @@ -0,0 +1,16 @@ +import sqlite from "better-sqlite3"; +import { lotOccupancyDB as databasePath } from "../../data/databasePaths.js"; +export const deleteWorkOrderLotOccupancy = (workOrderId, lotOccupancyId, requestSession) => { + const database = sqlite(databasePath); + const rightNowMillis = Date.now(); + const result = database + .prepare("update WorkOrderLotOccupancies" + + " set recordDelete_userName = ?," + + " recordDelete_timeMillis = ?" + + " where workOrderId = ?" + + " and lotOccupancyId = ?") + .run(requestSession.user.userName, rightNowMillis, workOrderId, lotOccupancyId); + database.close(); + return result.changes > 0; +}; +export default deleteWorkOrderLotOccupancy; diff --git a/helpers/lotOccupancyDB/deleteWorkOrderLotOccupancy.ts b/helpers/lotOccupancyDB/deleteWorkOrderLotOccupancy.ts new file mode 100644 index 00000000..bcb9685a --- /dev/null +++ b/helpers/lotOccupancyDB/deleteWorkOrderLotOccupancy.ts @@ -0,0 +1,31 @@ +import sqlite from "better-sqlite3"; + +import { lotOccupancyDB as databasePath } from "../../data/databasePaths.js"; + +import type * as recordTypes from "../../types/recordTypes"; + +export const deleteWorkOrderLotOccupancy = ( + workOrderId: number | string, + lotOccupancyId: number | string, + requestSession: recordTypes.PartialSession +): boolean => { + const database = sqlite(databasePath); + + const rightNowMillis = Date.now(); + + const result = database + .prepare( + "update WorkOrderLotOccupancies" + + " set recordDelete_userName = ?," + + " recordDelete_timeMillis = ?" + + " where workOrderId = ?" + + " and lotOccupancyId = ?" + ) + .run(requestSession.user.userName, rightNowMillis, workOrderId, lotOccupancyId); + + database.close(); + + return result.changes > 0; +}; + +export default deleteWorkOrderLotOccupancy; diff --git a/public-typescript/workOrderEdit.d.ts b/public-typescript/workOrderEdit.d.ts new file mode 100644 index 00000000..cb0ff5c3 --- /dev/null +++ b/public-typescript/workOrderEdit.d.ts @@ -0,0 +1 @@ +export {}; diff --git a/public-typescript/workOrderEdit.js b/public-typescript/workOrderEdit.js new file mode 100644 index 00000000..5ceb190f --- /dev/null +++ b/public-typescript/workOrderEdit.js @@ -0,0 +1,273 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +(() => { + const urlPrefix = document.querySelector("main").dataset.urlPrefix; + const workOrderId = document.querySelector("#workOrderEdit--workOrderId").value; + const isCreate = workOrderId === ""; + document + .querySelector("#form--workOrderEdit") + .addEventListener("submit", (submitEvent) => { + submitEvent.preventDefault(); + cityssm.postJSON(urlPrefix + + "/workOrders/" + + (isCreate ? "doCreateWorkOrder" : "doUpdateWorkOrder"), submitEvent.currentTarget, (responseJSON) => { + if (responseJSON.success) { + if (isCreate) { + window.location.href = + urlPrefix + + "/workOrders/" + + responseJSON.workOrderId + + "/edit"; + } + else { + bulmaJS.alert({ + message: "Work Order Updated Successfully", + contextualColorName: "success" + }); + } + } + else { + bulmaJS.alert({ + title: "Error Updating Work Order", + message: responseJSON.errorMessage, + contextualColorName: "danger" + }); + } + }); + }); + if (!isCreate) { + let workOrderLots = exports.workOrderLots; + delete exports.workOrderLots; + let workOrderLotOccupancies = exports.workOrderLotOccupancies; + delete exports.workOrderLotOccupancies; + const deleteLotOccupancy = (clickEvent) => { + const lotOccupancyId = clickEvent.currentTarget.closest(".container--lotOccupancy").dataset.lotOccupancyId; + const doDelete = () => { + cityssm.postJSON(urlPrefix + "/workOrders/doDeleteWorkOrderLotOccupancy", { + workOrderId, + lotOccupancyId + }, (responseJSON) => { + if (responseJSON.success) { + workOrderLotOccupancies = + responseJSON.workOrderLotOccupancies; + renderRelatedLotsAndOccupancies(); + } + else { + bulmaJS.alert({ + title: "Error Deleting Relationship", + message: responseJSON.errorMessage, + contextualColorName: "danger" + }); + } + }); + }; + bulmaJS.confirm({ + title: "Delete " + + exports.aliases.lot + + " " + + exports.aliases.occupancy + + " Relationship", + message: "Are you sure you want to remove the relationship to this " + + exports.aliases.lot.toLowerCase() + + " " + + exports.aliases.occupancy.toLowerCase() + + " record from this work order? Note that the record will remain.", + contextualColorName: "warning", + okButton: { + text: "Yes, Delete Relationship", + callbackFunction: doDelete + } + }); + }; + const renderRelatedOccupancies = () => { + const occupanciesContainerElement = document.querySelector("#relatedTab--lotOccupancies"); + document.querySelector(".tabs a[href='#relatedTab--lotOccupancies'] .tag").textContent = workOrderLotOccupancies.length.toString(); + if (workOrderLotOccupancies.length === 0) { + occupanciesContainerElement.innerHTML = + '
' + + '

There are no ' + + exports.aliases.occupancies.toLowerCase() + + " associated with this work order.

" + + "
"; + return; + } + occupanciesContainerElement.innerHTML = + '' + + "" + + "" + + '' + + ("") + + ("") + + "" + + "" + + ("") + + '' + + "" + + "" + + "" + + "
" + exports.aliases.occupancy + " Type" + exports.aliases.lot + "Start DateEnd Date" + exports.aliases.occupants + "
"; + const currentDateString = cityssm.dateToString(new Date()); + for (const lotOccupancy of workOrderLotOccupancies) { + const rowElement = document.createElement("tr"); + rowElement.className = "container--lotOccupancy"; + rowElement.dataset.lotOccupancyId = + lotOccupancy.lotOccupancyId.toString(); + const isActive = !(lotOccupancy.occupancyEndDate && + lotOccupancy.occupancyEndDateString < currentDateString); + rowElement.innerHTML = + '' + + (isActive + ? '' + : '') + + "" + + ("" + + '' + + cityssm.escapeHTML(lotOccupancy.occupancyType) + + "" + + "") + + ("" + + (lotOccupancy.lotId + ? cityssm.escapeHTML(lotOccupancy.lotName) + : '(No ' + + exports.aliases.lot + + ")") + + "") + + ("" + lotOccupancy.occupancyStartDateString + "") + + ("" + + (lotOccupancy.occupancyEndDate + ? lotOccupancy.occupancyEndDateString + : '(No End Date)') + + "") + + ("" + + (lotOccupancy.lotOccupancyOccupants.length === 0 + ? '(No ' + + cityssm.escapeHTML(exports.aliases.occupants) + + ")" + : cityssm.escapeHTML(lotOccupancy.lotOccupancyOccupants[0] + .occupantName) + + (lotOccupancy.lotOccupancyOccupants.length > 1 + ? " plus " + + (lotOccupancy.lotOccupancyOccupants.length - + 1) + : "")) + + "") + + ("" + + '" + + ""); + rowElement + .querySelector(".button--deleteLotOccupancy") + .addEventListener("click", deleteLotOccupancy); + occupanciesContainerElement + .querySelector("tbody") + .append(rowElement); + } + }; + const deleteLot = (clickEvent) => { + const lotId = clickEvent.currentTarget.closest(".container--lot").dataset.lotId; + const doDelete = () => { + cityssm.postJSON(urlPrefix + "/workOrders/doDeleteWorkOrderLot", { + workOrderId, + lotId + }, (responseJSON) => { + if (responseJSON.success) { + workOrderLots = + responseJSON.workOrderLots; + renderRelatedLotsAndOccupancies(); + } + else { + bulmaJS.alert({ + title: "Error Deleting Relationship", + message: responseJSON.errorMessage, + contextualColorName: "danger" + }); + } + }); + }; + bulmaJS.confirm({ + title: "Delete " + + exports.aliases.lot + + " " + + exports.aliases.occupancy + + " Relationship", + message: "Are you sure you want to remove the relationship to this " + + exports.aliases.lot.toLowerCase() + + " " + + exports.aliases.occupancy.toLowerCase() + + " record from this work order? Note that the record will remain.", + contextualColorName: "warning", + okButton: { + text: "Yes, Delete Relationship", + callbackFunction: doDelete + } + }); + }; + const renderRelatedLots = () => { + const lotsContainerElement = document.querySelector("#relatedTab--lots"); + document.querySelector(".tabs a[href='#relatedTab--lots'] .tag").textContent = workOrderLots.length.toString(); + if (workOrderLots.length === 0) { + lotsContainerElement.innerHTML = + '
' + + '

There are no ' + + exports.aliases.lots.toLowerCase() + + " associated with this work order.

" + + "
"; + return; + } + lotsContainerElement.innerHTML = + '' + + "" + + "" + + ("") + + ("") + + ("") + + "" + + '' + + "" + + "" + + "" + + "
" + exports.aliases.lot + "" + exports.aliases.map + "" + exports.aliases.lot + " TypeStatus
"; + for (const lot of workOrderLots) { + const rowElement = document.createElement("tr"); + rowElement.className = "container--lot"; + rowElement.dataset.lotId = lot.lotId.toString(); + rowElement.innerHTML = + "" + + '' + + cityssm.escapeHTML(lot.lotName) + + "" + + "" + + ("" + cityssm.escapeHTML(lot.mapName) + "") + + ("" + cityssm.escapeHTML(lot.lotType) + "") + + ("" + cityssm.escapeHTML(lot.lotStatus) + "") + + ("" + + '" + + ""); + rowElement + .querySelector(".button--deleteLot") + .addEventListener("click", deleteLot); + lotsContainerElement.querySelector("tbody").append(rowElement); + } + }; + const renderRelatedLotsAndOccupancies = () => { + renderRelatedOccupancies(); + renderRelatedLots(); + }; + renderRelatedLotsAndOccupancies(); + } +})(); diff --git a/public-typescript/workOrderEdit.ts b/public-typescript/workOrderEdit.ts new file mode 100644 index 00000000..a5d2a739 --- /dev/null +++ b/public-typescript/workOrderEdit.ts @@ -0,0 +1,376 @@ +/* eslint-disable unicorn/prefer-module */ + +import type { cityssmGlobal } from "@cityssm/bulma-webapp-js/src/types"; +import type { BulmaJS } from "@cityssm/bulma-js/types"; +import type * as recordTypes from "../types/recordTypes"; + +declare const cityssm: cityssmGlobal; +declare const bulmaJS: BulmaJS; + +(() => { + const urlPrefix = document.querySelector("main").dataset.urlPrefix; + + const workOrderId = ( + document.querySelector( + "#workOrderEdit--workOrderId" + ) as HTMLInputElement + ).value; + + const isCreate = workOrderId === ""; + + document + .querySelector("#form--workOrderEdit") + .addEventListener("submit", (submitEvent) => { + submitEvent.preventDefault(); + + cityssm.postJSON( + urlPrefix + + "/workOrders/" + + (isCreate ? "doCreateWorkOrder" : "doUpdateWorkOrder"), + submitEvent.currentTarget, + (responseJSON: { + success: boolean; + workOrderId?: number; + errorMessage?: string; + }) => { + if (responseJSON.success) { + if (isCreate) { + window.location.href = + urlPrefix + + "/workOrders/" + + responseJSON.workOrderId + + "/edit"; + } else { + bulmaJS.alert({ + message: "Work Order Updated Successfully", + contextualColorName: "success" + }); + } + } else { + bulmaJS.alert({ + title: "Error Updating Work Order", + message: responseJSON.errorMessage, + contextualColorName: "danger" + }); + } + } + ); + }); + + /* + * Related Lots + */ + + if (!isCreate) { + let workOrderLots: recordTypes.Lot[] = exports.workOrderLots; + delete exports.workOrderLots; + + let workOrderLotOccupancies: recordTypes.LotOccupancy[] = + exports.workOrderLotOccupancies; + delete exports.workOrderLotOccupancies; + + const deleteLotOccupancy = (clickEvent: Event) => { + const lotOccupancyId = ( + (clickEvent.currentTarget as HTMLElement).closest( + ".container--lotOccupancy" + ) as HTMLElement + ).dataset.lotOccupancyId; + + const doDelete = () => { + cityssm.postJSON( + urlPrefix + "/workOrders/doDeleteWorkOrderLotOccupancy", + { + workOrderId, + lotOccupancyId + }, + (responseJSON: { + success: boolean; + errorMessage?: string; + workOrderLotOccupancies?: recordTypes.LotOccupancy[]; + }) => { + if (responseJSON.success) { + workOrderLotOccupancies = + responseJSON.workOrderLotOccupancies; + renderRelatedLotsAndOccupancies(); + } else { + bulmaJS.alert({ + title: "Error Deleting Relationship", + message: responseJSON.errorMessage, + contextualColorName: "danger" + }); + } + } + ); + }; + + bulmaJS.confirm({ + title: + "Delete " + + exports.aliases.lot + + " " + + exports.aliases.occupancy + + " Relationship", + message: + "Are you sure you want to remove the relationship to this " + + exports.aliases.lot.toLowerCase() + + " " + + exports.aliases.occupancy.toLowerCase() + + " record from this work order? Note that the record will remain.", + contextualColorName: "warning", + okButton: { + text: "Yes, Delete Relationship", + callbackFunction: doDelete + } + }); + }; + + const renderRelatedOccupancies = () => { + const occupanciesContainerElement = document.querySelector( + "#relatedTab--lotOccupancies" + ) as HTMLElement; + + document.querySelector( + ".tabs a[href='#relatedTab--lotOccupancies'] .tag" + ).textContent = workOrderLotOccupancies.length.toString(); + + if (workOrderLotOccupancies.length === 0) { + occupanciesContainerElement.innerHTML = + '
' + + '

There are no ' + + exports.aliases.occupancies.toLowerCase() + + " associated with this work order.

" + + "
"; + + return; + } + + occupanciesContainerElement.innerHTML = + '' + + "" + + "" + + '' + + ("") + + ("") + + "" + + "" + + ("") + + '' + + "" + + "" + + "" + + "
" + exports.aliases.occupancy + " Type" + exports.aliases.lot + "Start DateEnd Date" + exports.aliases.occupants + "
"; + + const currentDateString = cityssm.dateToString(new Date()); + + for (const lotOccupancy of workOrderLotOccupancies) { + const rowElement = document.createElement("tr"); + rowElement.className = "container--lotOccupancy"; + rowElement.dataset.lotOccupancyId = + lotOccupancy.lotOccupancyId.toString(); + + const isActive = !( + lotOccupancy.occupancyEndDate && + lotOccupancy.occupancyEndDateString < currentDateString + ); + + rowElement.innerHTML = + '' + + (isActive + ? '' + : '') + + "" + + ("" + + '' + + cityssm.escapeHTML(lotOccupancy.occupancyType) + + "" + + "") + + ("" + + (lotOccupancy.lotId + ? cityssm.escapeHTML(lotOccupancy.lotName) + : '(No ' + + exports.aliases.lot + + ")") + + "") + + ("" + lotOccupancy.occupancyStartDateString + "") + + ("" + + (lotOccupancy.occupancyEndDate + ? lotOccupancy.occupancyEndDateString + : '(No End Date)') + + "") + + ("" + + (lotOccupancy.lotOccupancyOccupants.length === 0 + ? '(No ' + + cityssm.escapeHTML(exports.aliases.occupants) + + ")" + : cityssm.escapeHTML( + lotOccupancy.lotOccupancyOccupants[0] + .occupantName + ) + + (lotOccupancy.lotOccupancyOccupants.length > 1 + ? " plus " + + (lotOccupancy.lotOccupancyOccupants.length - + 1) + : "")) + + "") + + ("" + + '" + + ""); + + rowElement + .querySelector(".button--deleteLotOccupancy") + .addEventListener("click", deleteLotOccupancy); + + occupanciesContainerElement + .querySelector("tbody") + .append(rowElement); + } + }; + + const deleteLot = (clickEvent: Event) => { + const lotId = ( + (clickEvent.currentTarget as HTMLElement).closest( + ".container--lot" + ) as HTMLElement + ).dataset.lotId; + + const doDelete = () => { + cityssm.postJSON( + urlPrefix + "/workOrders/doDeleteWorkOrderLot", + { + workOrderId, + lotId + }, + (responseJSON: { + success: boolean; + errorMessage?: string; + workOrderLots?: recordTypes.Lot[]; + }) => { + if (responseJSON.success) { + workOrderLots = + responseJSON.workOrderLots; + renderRelatedLotsAndOccupancies(); + } else { + bulmaJS.alert({ + title: "Error Deleting Relationship", + message: responseJSON.errorMessage, + contextualColorName: "danger" + }); + } + } + ); + }; + + bulmaJS.confirm({ + title: + "Delete " + + exports.aliases.lot + + " " + + exports.aliases.occupancy + + " Relationship", + message: + "Are you sure you want to remove the relationship to this " + + exports.aliases.lot.toLowerCase() + + " " + + exports.aliases.occupancy.toLowerCase() + + " record from this work order? Note that the record will remain.", + contextualColorName: "warning", + okButton: { + text: "Yes, Delete Relationship", + callbackFunction: doDelete + } + }); + }; + + const renderRelatedLots = () => { + const lotsContainerElement = document.querySelector( + "#relatedTab--lots" + ) as HTMLElement; + + document.querySelector( + ".tabs a[href='#relatedTab--lots'] .tag" + ).textContent = workOrderLots.length.toString(); + + if (workOrderLots.length === 0) { + lotsContainerElement.innerHTML = + '
' + + '

There are no ' + + exports.aliases.lots.toLowerCase() + + " associated with this work order.

" + + "
"; + + return; + } + + lotsContainerElement.innerHTML = + '' + + "" + + "" + + ("") + + ("") + + ("") + + "" + + '' + + "" + + "" + + "" + + "
" + exports.aliases.lot + "" + exports.aliases.map + "" + exports.aliases.lot + " TypeStatus
"; + + for (const lot of workOrderLots) { + const rowElement = document.createElement("tr"); + rowElement.className = "container--lot"; + + rowElement.dataset.lotId = lot.lotId.toString(); + + rowElement.innerHTML = + "" + + '' + + cityssm.escapeHTML(lot.lotName) + + "" + + "" + + ("" + cityssm.escapeHTML(lot.mapName) + "") + + ("" + cityssm.escapeHTML(lot.lotType) + "") + + ("" + cityssm.escapeHTML(lot.lotStatus) + "") + + ("" + + '" + + ""); + + rowElement + .querySelector(".button--deleteLot") + .addEventListener("click", deleteLot); + + lotsContainerElement.querySelector("tbody").append(rowElement); + } + }; + + const renderRelatedLotsAndOccupancies = () => { + renderRelatedOccupancies(); + renderRelatedLots(); + }; + + renderRelatedLotsAndOccupancies(); + } + + /* + * Comments + */ + + /* + * Milestones + */ +})(); diff --git a/public-typescript/workOrderView.d.ts b/public-typescript/workOrderView.d.ts new file mode 100644 index 00000000..cb0ff5c3 --- /dev/null +++ b/public-typescript/workOrderView.d.ts @@ -0,0 +1 @@ +export {}; diff --git a/public-typescript/workOrderView.js b/public-typescript/workOrderView.js new file mode 100644 index 00000000..a01c0d16 --- /dev/null +++ b/public-typescript/workOrderView.js @@ -0,0 +1,41 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +(() => { + const urlPrefix = document.querySelector("main").dataset.urlPrefix; + const reopenWorkOrderButtonElement = document.querySelector("#button--reopenWorkOrder"); + if (reopenWorkOrderButtonElement) { + reopenWorkOrderButtonElement.addEventListener("click", () => { + const workOrderId = reopenWorkOrderButtonElement.dataset.workOrderId; + const doReopen = () => { + cityssm.postJSON(urlPrefix + "/workOrders/doReopenWorkOrder", { + workOrderId + }, (responseJSON) => { + if (responseJSON.success) { + window.location.href = + urlPrefix + + "/workOrders/" + + workOrderId + + "/edit/?t=" + + Date.now(); + } + else { + bulmaJS.alert({ + title: "Error Reopening Work Order", + message: responseJSON.errorMessage, + contextualColorName: "danger" + }); + } + }); + }; + bulmaJS.confirm({ + title: "Reopen Work Order", + message: "Are you sure you want to remove the close date from this work order and reopen it?", + contextualColorName: "warning", + okButton: { + text: "Yes, Reopen Work Order", + callbackFunction: doReopen + } + }); + }); + } +})(); diff --git a/public-typescript/workOrderView.ts b/public-typescript/workOrderView.ts new file mode 100644 index 00000000..6e0de277 --- /dev/null +++ b/public-typescript/workOrderView.ts @@ -0,0 +1,61 @@ +/* eslint-disable unicorn/prefer-module */ + +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 urlPrefix = document.querySelector("main").dataset.urlPrefix; + + const reopenWorkOrderButtonElement = document.querySelector( + "#button--reopenWorkOrder" + ) as HTMLButtonElement; + + if (reopenWorkOrderButtonElement) { + reopenWorkOrderButtonElement.addEventListener("click", () => { + const workOrderId = + reopenWorkOrderButtonElement.dataset.workOrderId; + + const doReopen = () => { + cityssm.postJSON( + urlPrefix + "/workOrders/doReopenWorkOrder", + { + workOrderId + }, + (responseJSON: { + success: boolean; + errorMessage?: string; + }) => { + if (responseJSON.success) { + window.location.href = + urlPrefix + + "/workOrders/" + + workOrderId + + "/edit/?t=" + + Date.now(); + } else { + bulmaJS.alert({ + title: "Error Reopening Work Order", + message: responseJSON.errorMessage, + contextualColorName: "danger" + }); + } + } + ); + }; + + bulmaJS.confirm({ + title: "Reopen Work Order", + message: + "Are you sure you want to remove the close date from this work order and reopen it?", + contextualColorName: "warning", + okButton: { + text: "Yes, Reopen Work Order", + callbackFunction: doReopen + } + }); + }); + } +})(); diff --git a/public/javascripts/workOrderEdit.min.js b/public/javascripts/workOrderEdit.min.js new file mode 100644 index 00000000..0e04ec49 --- /dev/null +++ b/public/javascripts/workOrderEdit.min.js @@ -0,0 +1 @@ +"use strict";Object.defineProperty(exports,"__esModule",{value:!0}),(()=>{const t=document.querySelector("main").dataset.urlPrefix,e=document.querySelector("#workOrderEdit--workOrderId").value,s=""===e;if(document.querySelector("#form--workOrderEdit").addEventListener("submit",e=>{e.preventDefault(),cityssm.postJSON(t+"/workOrders/"+(s?"doCreateWorkOrder":"doUpdateWorkOrder"),e.currentTarget,e=>{e.success?s?window.location.href=t+"/workOrders/"+e.workOrderId+"/edit":bulmaJS.alert({message:"Work Order Updated Successfully",contextualColorName:"success"}):bulmaJS.alert({title:"Error Updating Work Order",message:e.errorMessage,contextualColorName:"danger"})})}),!s){let s=exports.workOrderLots;delete exports.workOrderLots;let a=exports.workOrderLotOccupancies;delete exports.workOrderLotOccupancies;const o=s=>{const o=s.currentTarget.closest(".container--lotOccupancy").dataset.lotOccupancyId;bulmaJS.confirm({title:"Delete "+exports.aliases.lot+" "+exports.aliases.occupancy+" Relationship",message:"Are you sure you want to remove the relationship to this "+exports.aliases.lot.toLowerCase()+" "+exports.aliases.occupancy.toLowerCase()+" record from this work order? Note that the record will remain.",contextualColorName:"warning",okButton:{text:"Yes, Delete Relationship",callbackFunction:()=>{cityssm.postJSON(t+"/workOrders/doDeleteWorkOrderLotOccupancy",{workOrderId:e,lotOccupancyId:o},t=>{t.success?(a=t.workOrderLotOccupancies,n()):bulmaJS.alert({title:"Error Deleting Relationship",message:t.errorMessage,contextualColorName:"danger"})})}}})},r=()=>{const e=document.querySelector("#relatedTab--lotOccupancies");if(document.querySelector(".tabs a[href='#relatedTab--lotOccupancies'] .tag").textContent=a.length.toString(),0===a.length)return void(e.innerHTML='

There are no '+exports.aliases.occupancies.toLowerCase()+" associated with this work order.

");e.innerHTML='
'+exports.aliases.occupancy+" Type"+exports.aliases.lot+"Start DateEnd Date"+exports.aliases.occupants+'
';const s=cityssm.dateToString(new Date);for(const r of a){const a=document.createElement("tr");a.className="container--lotOccupancy",a.dataset.lotOccupancyId=r.lotOccupancyId.toString();const c=!(r.occupancyEndDate&&r.occupancyEndDateString'+(c?'':'')+''+cityssm.escapeHTML(r.occupancyType)+""+(r.lotId?cityssm.escapeHTML(r.lotName):'(No '+exports.aliases.lot+")")+""+r.occupancyStartDateString+""+(r.occupancyEndDate?r.occupancyEndDateString:'(No End Date)')+""+(0===r.lotOccupancyOccupants.length?'(No '+cityssm.escapeHTML(exports.aliases.occupants)+")":cityssm.escapeHTML(r.lotOccupancyOccupants[0].occupantName)+(r.lotOccupancyOccupants.length>1?" plus "+(r.lotOccupancyOccupants.length-1):""))+'',a.querySelector(".button--deleteLotOccupancy").addEventListener("click",o),e.querySelector("tbody").append(a)}},c=a=>{const o=a.currentTarget.closest(".container--lot").dataset.lotId;bulmaJS.confirm({title:"Delete "+exports.aliases.lot+" "+exports.aliases.occupancy+" Relationship",message:"Are you sure you want to remove the relationship to this "+exports.aliases.lot.toLowerCase()+" "+exports.aliases.occupancy.toLowerCase()+" record from this work order? Note that the record will remain.",contextualColorName:"warning",okButton:{text:"Yes, Delete Relationship",callbackFunction:()=>{cityssm.postJSON(t+"/workOrders/doDeleteWorkOrderLot",{workOrderId:e,lotId:o},t=>{t.success?(s=t.workOrderLots,n()):bulmaJS.alert({title:"Error Deleting Relationship",message:t.errorMessage,contextualColorName:"danger"})})}}})},l=()=>{const e=document.querySelector("#relatedTab--lots");if(document.querySelector(".tabs a[href='#relatedTab--lots'] .tag").textContent=s.length.toString(),0!==s.length){e.innerHTML='
'+exports.aliases.lot+""+exports.aliases.map+""+exports.aliases.lot+' TypeStatus
';for(const a of s){const s=document.createElement("tr");s.className="container--lot",s.dataset.lotId=a.lotId.toString(),s.innerHTML=''+cityssm.escapeHTML(a.lotName)+""+cityssm.escapeHTML(a.mapName)+""+cityssm.escapeHTML(a.lotType)+""+cityssm.escapeHTML(a.lotStatus)+'',s.querySelector(".button--deleteLot").addEventListener("click",c),e.querySelector("tbody").append(s)}}else e.innerHTML='

There are no '+exports.aliases.lots.toLowerCase()+" associated with this work order.

"},n=()=>{r(),l()};n()}})(); \ No newline at end of file diff --git a/public/javascripts/workOrderView.min.js b/public/javascripts/workOrderView.min.js new file mode 100644 index 00000000..c7ff6f05 --- /dev/null +++ b/public/javascripts/workOrderView.min.js @@ -0,0 +1 @@ +"use strict";Object.defineProperty(exports,"__esModule",{value:!0}),(()=>{const e=document.querySelector("main").dataset.urlPrefix,r=document.querySelector("#button--reopenWorkOrder");r&&r.addEventListener("click",()=>{const o=r.dataset.workOrderId;bulmaJS.confirm({title:"Reopen Work Order",message:"Are you sure you want to remove the close date from this work order and reopen it?",contextualColorName:"warning",okButton:{text:"Yes, Reopen Work Order",callbackFunction:()=>{cityssm.postJSON(e+"/workOrders/doReopenWorkOrder",{workOrderId:o},r=>{r.success?window.location.href=e+"/workOrders/"+o+"/edit/?t="+Date.now():bulmaJS.alert({title:"Error Reopening Work Order",message:r.errorMessage,contextualColorName:"danger"})})}}})})})(); \ No newline at end of file diff --git a/routes/workOrders.js b/routes/workOrders.js index b32f16b5..43ce6e7c 100644 --- a/routes/workOrders.js +++ b/routes/workOrders.js @@ -3,10 +3,18 @@ import * as permissionHandlers from "../handlers/permissions.js"; import handler_search from "../handlers/workOrders-get/search.js"; import handler_doSearchWorkOrders from "../handlers/workOrders-post/doSearchWorkOrders.js"; import handler_view from "../handlers/workOrders-get/view.js"; +import handler_doReopenWorkOrder from "../handlers/workOrders-post/doReopenWorkOrder.js"; import handler_edit from "../handlers/workOrders-get/edit.js"; +import handler_doUpdateWorkOrder from "../handlers/workOrders-post/doUpdateWorkOrder.js"; +import handler_doDeleteWorkOrderLotOccupancy from "../handlers/workOrders-post/doDeleteWorkOrderLotOccupancy.js"; +import handler_doDeleteWorkOrderLot from "../handlers/workOrders-post/doDeleteWorkOrderLot.js"; export const router = Router(); router.get("/", handler_search); router.post("/doSearchWorkOrders", handler_doSearchWorkOrders); router.get("/:workOrderId", handler_view); +router.post("/doReopenWorkOrder", permissionHandlers.updatePostHandler, handler_doReopenWorkOrder); router.get("/:workOrderId/edit", permissionHandlers.updateGetHandler, handler_edit); +router.post("/doUpdateWorkOrder", permissionHandlers.updatePostHandler, handler_doUpdateWorkOrder); +router.post("/doDeleteWorkOrderLotOccupancy", permissionHandlers.updatePostHandler, handler_doDeleteWorkOrderLotOccupancy); +router.post("/doDeleteWorkOrderLot", permissionHandlers.updatePostHandler, handler_doDeleteWorkOrderLot); export default router; diff --git a/routes/workOrders.ts b/routes/workOrders.ts index 50928d5c..d4f44cde 100644 --- a/routes/workOrders.ts +++ b/routes/workOrders.ts @@ -6,8 +6,12 @@ import handler_search from "../handlers/workOrders-get/search.js"; import handler_doSearchWorkOrders from "../handlers/workOrders-post/doSearchWorkOrders.js"; import handler_view from "../handlers/workOrders-get/view.js"; +import handler_doReopenWorkOrder from "../handlers/workOrders-post/doReopenWorkOrder.js"; import handler_edit from "../handlers/workOrders-get/edit.js"; +import handler_doUpdateWorkOrder from "../handlers/workOrders-post/doUpdateWorkOrder.js"; +import handler_doDeleteWorkOrderLotOccupancy from "../handlers/workOrders-post/doDeleteWorkOrderLotOccupancy.js"; +import handler_doDeleteWorkOrderLot from "../handlers/workOrders-post/doDeleteWorkOrderLot.js"; export const router = Router(); @@ -17,8 +21,34 @@ router.post("/doSearchWorkOrders", handler_doSearchWorkOrders); router.get("/:workOrderId", handler_view); -router.get("/:workOrderId/edit", +router.post( + "/doReopenWorkOrder", + permissionHandlers.updatePostHandler, + handler_doReopenWorkOrder +); + +router.get( + "/:workOrderId/edit", permissionHandlers.updateGetHandler, - handler_edit); + handler_edit +); + +router.post( + "/doUpdateWorkOrder", + permissionHandlers.updatePostHandler, + handler_doUpdateWorkOrder +); + +router.post( + "/doDeleteWorkOrderLotOccupancy", + permissionHandlers.updatePostHandler, + handler_doDeleteWorkOrderLotOccupancy +); + +router.post( + "/doDeleteWorkOrderLot", + permissionHandlers.updatePostHandler, + handler_doDeleteWorkOrderLot +); export default router; diff --git a/types/recordTypes.d.ts b/types/recordTypes.d.ts index a4ba4523..fa140217 100644 --- a/types/recordTypes.d.ts +++ b/types/recordTypes.d.ts @@ -52,7 +52,7 @@ export interface Lot extends Record { lotId?: number; lotName?: string; lotTypeId?: number; - lotType?: LotType | string; + lotType?: string; mapId?: number; mapName?: string; map?: Map; @@ -61,7 +61,7 @@ export interface Lot extends Record { lotLatitude?: number; lotLongitude?: number; lotStatusId?: number; - lotStatus?: LotStatus | string; + lotStatus?: string; lotOccupancyCount?: number; lotOccupancies?: LotOccupancy[]; lotComments?: LotComment[]; diff --git a/types/recordTypes.ts b/types/recordTypes.ts index 32ea1b94..ede323ff 100644 --- a/types/recordTypes.ts +++ b/types/recordTypes.ts @@ -70,7 +70,7 @@ export interface Lot extends Record { lotName?: string; lotTypeId?: number; - lotType?: LotType | string; + lotType?: string; mapId?: number; mapName?: string; @@ -82,7 +82,7 @@ export interface Lot extends Record { lotLongitude?: number; lotStatusId?: number; - lotStatus?: LotStatus | string; + lotStatus?: string; lotOccupancyCount?: number; lotOccupancies?: LotOccupancy[]; diff --git a/views/workOrder-edit.ejs b/views/workOrder-edit.ejs index 8f01a76a..082888de 100644 --- a/views/workOrder-edit.ejs +++ b/views/workOrder-edit.ejs @@ -9,19 +9,181 @@ Work Orders -
  • - - Work Order #<%= workOrder.workOrderNumber || "(No Number)" %> - -
  • -
  • - - Update Work Order - -
  • + <% if (isCreate) { %> +
  • + + Create a New Work Order + +
  • + <% } else { %> +
  • + + Work Order #<%= workOrder.workOrderNumber || "(No Number)" %> + +
  • +
  • + + Update Work Order + +
  • + <% } %> +

    + <% if (isCreate) { %> + Create a New Work Order + <% } else { %> + Work Order #<%= workOrder.workOrderNumber || "(No Number)" %> + <% } %> +

    + +
    + +
    +
    +
    +
    +
    + +
    + +
    +
    +
    +
    +
    + +
    +
    + +
    +
    +
    +
    +
    +
    + +
    + +
    +
    +
    +
    +
    + +
    + +
    +
    +
    +
    +
    + +
    + +
    +
    +
    +
    +
    +
    + + <% if (!isCreate) { %> + + <% } %> +
    +
    + <% if (!isCreate) { %> +
    +
    +
    +
    +
    +

    Related <%= configFunctions.getProperty("aliases.lots") %>

    +
    +
    +
    +
    + +
    +
    +
    +
    +
    + <% + const tabToSelect = (workOrder.workOrderLotOccupancies.length > 0 || workOrder.workOrderLots.length === 0 ? "lotOccupancies" : "lots"); + %> + +
    +
    " id="relatedTab--lotOccupancies"> +
    +
    " id="relatedTab--lots"> +
    +
    +
    +
    + <% } %> +
    + <%- include('_footerA'); -%> + + + <%- include('_footerB'); -%> \ No newline at end of file diff --git a/views/workOrder-view.ejs b/views/workOrder-view.ejs index 21d4010d..fbf5fada 100644 --- a/views/workOrder-view.ejs +++ b/views/workOrder-view.ejs @@ -21,7 +21,7 @@ Work Order #<%= workOrder.workOrderNumber || "(No Number)" %> -<% if (user.userProperties.canUpdate) { %> +<% if (user.userProperties.canUpdate && !workOrder.workOrderCloseDate) { %> + <% if (user.userProperties.canUpdate && workOrder.workOrderCloseDate) { %> +
    + +
    + <% } %>
    @@ -101,6 +108,7 @@

    <% } else { %> + <% const currentDate = dateTimeFunctions.dateToInteger(new Date()); %> @@ -207,6 +215,34 @@

    Milestones

    + <% for (const milestone of workOrder.workOrderMilestones) { %> +
    +
    +
    + <% if (milestone.workOrderMilestoneCompletionDate) { %> + + + + <% } else { %> + + + + <% } %> +
    +
    + <% if (milestone.workOrderMilestoneTypeId) { %> + <%= milestone.workOrderMilestoneType %>
    + <% } %> + <%= milestone.workOrderMilestoneDateString %> + <% if (milestone.workOrderMilestoneTime !== 0) { %> + <%= milestone.workOrderMilestoneTimeString %> + <% } %> +
    + <%= milestone.workOrderMilestoneDescription %> +
    +
    +
    + <% } %>
    <% } %> @@ -214,4 +250,6 @@ <%- include('_footerA'); -%> + + <%- include('_footerB'); -%> \ No newline at end of file