From eda8483e62c0141da9fbd56e231253ceb72f9b37 Mon Sep 17 00:00:00 2001 From: Dan Gowans Date: Mon, 31 Oct 2022 09:21:53 -0400 Subject: [PATCH] refactor to reduce complexity --- handlers/api-get/milestoneICS.js | 277 +++++++++++++------------ handlers/api-get/milestoneICS.ts | 333 +++++++++++++++++-------------- 2 files changed, 323 insertions(+), 287 deletions(-) diff --git a/handlers/api-get/milestoneICS.js b/handlers/api-get/milestoneICS.js index 08ac4356..293405d1 100644 --- a/handlers/api-get/milestoneICS.js +++ b/handlers/api-get/milestoneICS.js @@ -2,17 +2,151 @@ import ical, { ICalEventStatus } from "ical-generator"; import { getWorkOrderMilestones } from "../../helpers/lotOccupancyDB/getWorkOrderMilestones.js"; import * as configFunctions from "../../helpers/functions.config.js"; import { getPrintConfig } from "../../helpers/functions.print.js"; +const calendarCompany = "cityssm.github.io"; +const calendarProduct = configFunctions.getProperty("application.applicationName"); const timeStringSplitRegex = /[ :-]/; function escapeHTML(stringToEscape) { return stringToEscape.replace(/[^\d A-Za-z]/g, (c) => "&#" + c.codePointAt(0) + ";"); } -export const handler = (request, response) => { - const urlRoot = "http://" + +function getUrlRoot(request) { + return ("http://" + request.hostname + (configFunctions.getProperty("application.httpPort") === 80 ? "" : ":" + configFunctions.getProperty("application.httpPort")) + - configFunctions.getProperty("reverseProxy.urlPrefix"); + configFunctions.getProperty("reverseProxy.urlPrefix")); +} +function getWorkOrderUrl(request, milestone) { + return getUrlRoot(request) + "/workOrders/" + milestone.workOrderId; +} +function buildEventSummary(milestone) { + let summary = (milestone.workOrderMilestoneCompletionDate ? "✔ " : "") + + (milestone.workOrderMilestoneTypeId + ? milestone.workOrderMilestoneType + : milestone.workOrderMilestoneDescription).trim(); + if (milestone.workOrderLotOccupancies.length > 0) { + let occupantCount = 0; + for (const lotOccupancy of milestone.workOrderLotOccupancies) { + for (const occupant of lotOccupancy.lotOccupancyOccupants) { + occupantCount += 1; + if (occupantCount === 1) { + if (summary !== "") { + summary += ": "; + } + summary += occupant.occupantName; + } + } + } + if (occupantCount > 1) { + summary += " plus " + (occupantCount - 1); + } + } + return summary; +} +function buildEventDescriptionHTML(request, milestone) { + const urlRoot = getUrlRoot(request); + const workOrderUrl = getWorkOrderUrl(request, milestone); + let descriptionHTML = "

Milestone Description

" + + "

" + + escapeHTML(milestone.workOrderMilestoneDescription) + + "

" + + "

Work Order #" + + milestone.workOrderNumber + + "

" + + ("

" + escapeHTML(milestone.workOrderDescription) + "

") + + ("

" + workOrderUrl + "

"); + if (milestone.workOrderLotOccupancies.length > 0) { + descriptionHTML += + "

Related " + + escapeHTML(configFunctions.getProperty("aliases.occupancies")) + + "

" + + '' + + ("") + + ("") + + "" + + "" + + ("") + + "" + + ""; + for (const occupancy of milestone.workOrderLotOccupancies) { + descriptionHTML += + "" + + ("") + + ("") + + ("") + + "" + + "" + ""; + } + descriptionHTML += "
" + escapeHTML(configFunctions.getProperty("aliases.occupancy")) + " Type" + escapeHTML(configFunctions.getProperty("aliases.lot")) + "Start DateEnd Date" + escapeHTML(configFunctions.getProperty("aliases.occupants")) + "
" + + '' + + escapeHTML(occupancy.occupancyType) + + "" + + (occupancy.lotName ? escapeHTML(occupancy.lotName) : "(Not Set)") + + "" + occupancy.occupancyStartDateString + "" + + (occupancy.occupancyEndDate ? occupancy.occupancyEndDateString : "(No End Date)") + + ""; + for (const occupant of occupancy.lotOccupancyOccupants) { + descriptionHTML += + escapeHTML(occupant.lotOccupantType) + + ": " + + escapeHTML(occupant.occupantName) + + "
"; + } + descriptionHTML += "
"; + } + if (milestone.workOrderLots.length > 0) { + descriptionHTML += + "

Related " + + escapeHTML(configFunctions.getProperty("aliases.lots")) + + "

" + + '' + + ("") + + ("") + + ("") + + "" + + "" + + ""; + for (const lot of milestone.workOrderLots) { + descriptionHTML += + "" + + ("") + + ("") + + ("") + + ("") + + ""; + } + descriptionHTML += "
" + escapeHTML(configFunctions.getProperty("aliases.lot")) + " Type" + escapeHTML(configFunctions.getProperty("aliases.map")) + "" + escapeHTML(configFunctions.getProperty("aliases.lot")) + " Type" + "Status
" + + '' + + escapeHTML(lot.lotName) + + "" + escapeHTML(lot.mapName) + "" + escapeHTML(lot.lotType) + "" + escapeHTML(lot.lotStatus) + "
"; + } + const prints = configFunctions.getProperty("settings.workOrders.prints"); + if (prints.length > 0) { + descriptionHTML += "

Prints

"; + for (const printName of prints) { + const printConfig = getPrintConfig(printName); + if (printConfig) { + descriptionHTML += + "

" + + escapeHTML(printConfig.title) + + "
" + + (urlRoot + "/print/" + printName + "/?workOrderId=" + milestone.workOrderId) + + "

"; + } + } + } + return descriptionHTML; +} +export const handler = (request, response) => { + const urlRoot = getUrlRoot(request); const workOrderMilestoneFilters = { workOrderTypeIds: request.query.workOrderTypeIds, workOrderMilestoneTypeIds: request.query.workOrderMilestoneTypeIds @@ -36,8 +170,8 @@ export const handler = (request, response) => { calendar.url(urlRoot + "/workOrders/" + workOrderMilestones[0].workOrderId); } calendar.prodId({ - company: "cityssm.github.io", - product: configFunctions.getProperty("application.applicationName") + company: calendarCompany, + product: calendarProduct }); for (const milestone of workOrderMilestones) { const milestoneTimePieces = (milestone.workOrderMilestoneDateString + @@ -46,28 +180,8 @@ export const handler = (request, response) => { const milestoneDate = new Date(Number.parseInt(milestoneTimePieces[0], 10), Number.parseInt(milestoneTimePieces[1], 10) - 1, Number.parseInt(milestoneTimePieces[2], 10), Number.parseInt(milestoneTimePieces[3], 10), Number.parseInt(milestoneTimePieces[4], 10)); const milestoneEndDate = new Date(milestoneDate.getTime()); milestoneEndDate.setHours(milestoneEndDate.getHours() + 1); - let summary = (milestone.workOrderMilestoneCompletionDate ? "✔ " : "") + - (milestone.workOrderMilestoneTypeId - ? milestone.workOrderMilestoneType - : milestone.workOrderMilestoneDescription).trim(); - if (milestone.workOrderLotOccupancies.length > 0) { - let occupantCount = 0; - for (const lotOccupancy of milestone.workOrderLotOccupancies) { - for (const occupant of lotOccupancy.lotOccupancyOccupants) { - occupantCount += 1; - if (occupantCount === 1) { - if (summary !== "") { - summary += ": "; - } - summary += occupant.occupantName; - } - } - } - if (occupantCount > 1) { - summary += " plus " + (occupantCount - 1); - } - } - const workOrderURL = urlRoot + "/workOrders/" + milestone.workOrderId; + const summary = buildEventSummary(milestone); + const workOrderUrl = getWorkOrderUrl(request, milestone); const eventData = { start: milestoneDate, created: new Date(milestone.recordCreate_timeMillis), @@ -75,118 +189,15 @@ export const handler = (request, response) => { lastModified: new Date(Math.max(milestone.recordUpdate_timeMillis, milestone.workOrderRecordUpdate_timeMillis)), allDay: !milestone.workOrderMilestoneTime, summary, - url: workOrderURL + url: workOrderUrl }; if (!eventData.allDay) { eventData.end = milestoneEndDate; } const calendarEvent = calendar.createEvent(eventData); - let descriptionHTML = "

Milestone Description

" + - "

" + - escapeHTML(milestone.workOrderMilestoneDescription) + - "

" + - "

Work Order #" + - milestone.workOrderNumber + - "

" + - ("

" + escapeHTML(milestone.workOrderDescription) + "

") + - ("

" + workOrderURL + "

"); - if (milestone.workOrderLotOccupancies.length > 0) { - descriptionHTML += - "

Related " + - escapeHTML(configFunctions.getProperty("aliases.occupancies")) + - "

" + - '' + - ("") + - ("") + - "" + - "" + - ("") + - "" + - ""; - for (const occupancy of milestone.workOrderLotOccupancies) { - descriptionHTML += - "" + - ("") + - ("") + - ("") + - "" + - "" + ""; - } - descriptionHTML += "
" + - escapeHTML(configFunctions.getProperty("aliases.occupancy")) + - " Type" + escapeHTML(configFunctions.getProperty("aliases.lot")) + "Start DateEnd Date" + escapeHTML(configFunctions.getProperty("aliases.occupants")) + "
" + - '' + - escapeHTML(occupancy.occupancyType) + - "" + - (occupancy.lotName ? escapeHTML(occupancy.lotName) : "(Not Set)") + - "" + occupancy.occupancyStartDateString + "" + - (occupancy.occupancyEndDate - ? occupancy.occupancyEndDateString - : "(No End Date)") + - ""; - for (const occupant of occupancy.lotOccupancyOccupants) { - descriptionHTML += escapeHTML(occupant.lotOccupantType) + ": " + escapeHTML(occupant.occupantName) + "
"; - } - descriptionHTML += "
"; - } - if (milestone.workOrderLots.length > 0) { - descriptionHTML += - "

Related " + - escapeHTML(configFunctions.getProperty("aliases.lots")) + - "

" + - '' + - ("") + - ("") + - ("") + - "" + - "" + - ""; - for (const lot of milestone.workOrderLots) { - descriptionHTML += - "" + - ("") + - ("") + - ("") + - ("") + - ""; - } - descriptionHTML += "
" + escapeHTML(configFunctions.getProperty("aliases.lot")) + " Type" + escapeHTML(configFunctions.getProperty("aliases.map")) + "" + - escapeHTML(configFunctions.getProperty("aliases.lot")) + - " Type" + - "Status
" + - '' + - escapeHTML(lot.lotName) + - "" + escapeHTML(lot.mapName) + "" + escapeHTML(lot.lotType) + "" + escapeHTML(lot.lotStatus) + "
"; - } - const prints = configFunctions.getProperty("settings.workOrders.prints"); - if (prints.length > 0) { - descriptionHTML += "

Prints

"; - for (const printName of prints) { - const printConfig = getPrintConfig(printName); - if (printConfig) { - descriptionHTML += - "

" + - escapeHTML(printConfig.title) + - "
" + - (urlRoot + - "/print/" + - printName + - "/?workOrderId=" + - milestone.workOrderId) + - "

"; - } - } - } + const descriptionHTML = buildEventDescriptionHTML(request, milestone); calendarEvent.description({ - plain: workOrderURL, + plain: workOrderUrl, html: descriptionHTML }); if (milestone.workOrderMilestoneCompletionDate) { diff --git a/handlers/api-get/milestoneICS.ts b/handlers/api-get/milestoneICS.ts index 539deb05..b4026167 100644 --- a/handlers/api-get/milestoneICS.ts +++ b/handlers/api-get/milestoneICS.ts @@ -7,25 +7,193 @@ import { WorkOrderMilestoneFilters } from "../../helpers/lotOccupancyDB/getWorkOrderMilestones.js"; -import type { RequestHandler } from "express"; +import type { RequestHandler, Request } from "express"; import * as configFunctions from "../../helpers/functions.config.js"; import { getPrintConfig } from "../../helpers/functions.print.js"; +import type * as recordTypes from "../../types/recordTypes"; + +const calendarCompany = "cityssm.github.io"; +const calendarProduct = configFunctions.getProperty("application.applicationName"); + const timeStringSplitRegex = /[ :-]/; function escapeHTML(stringToEscape: string) { return stringToEscape.replace(/[^\d A-Za-z]/g, (c) => "&#" + c.codePointAt(0) + ";"); } -export const handler: RequestHandler = (request, response) => { - const urlRoot = +function getUrlRoot(request: Request): string { + return ( "http://" + request.hostname + (configFunctions.getProperty("application.httpPort") === 80 ? "" : ":" + configFunctions.getProperty("application.httpPort")) + - configFunctions.getProperty("reverseProxy.urlPrefix"); + configFunctions.getProperty("reverseProxy.urlPrefix") + ); +} + +function getWorkOrderUrl(request: Request, milestone: recordTypes.WorkOrderMilestone) { + return getUrlRoot(request) + "/workOrders/" + milestone.workOrderId; +} + +function buildEventSummary(milestone: recordTypes.WorkOrderMilestone): string { + let summary = + (milestone.workOrderMilestoneCompletionDate ? "✔ " : "") + + (milestone.workOrderMilestoneTypeId + ? milestone.workOrderMilestoneType + : milestone.workOrderMilestoneDescription + ).trim(); + + if (milestone.workOrderLotOccupancies.length > 0) { + let occupantCount = 0; + + for (const lotOccupancy of milestone.workOrderLotOccupancies) { + for (const occupant of lotOccupancy.lotOccupancyOccupants) { + occupantCount += 1; + + if (occupantCount === 1) { + if (summary !== "") { + summary += ": "; + } + + summary += occupant.occupantName; + } + } + } + + if (occupantCount > 1) { + summary += " plus " + (occupantCount - 1); + } + } + + return summary; +} + +function buildEventDescriptionHTML( + request: Request, + milestone: recordTypes.WorkOrderMilestone +): string { + const urlRoot = getUrlRoot(request); + const workOrderUrl = getWorkOrderUrl(request, milestone); + + let descriptionHTML = + "

Milestone Description

" + + "

" + + escapeHTML(milestone.workOrderMilestoneDescription) + + "

" + + "

Work Order #" + + milestone.workOrderNumber + + "

" + + ("

" + escapeHTML(milestone.workOrderDescription) + "

") + + ("

" + workOrderUrl + "

"); + + if (milestone.workOrderLotOccupancies.length > 0) { + descriptionHTML += + "

Related " + + escapeHTML(configFunctions.getProperty("aliases.occupancies")) + + "

" + + '' + + ("") + + ("") + + "" + + "" + + ("") + + "" + + ""; + + for (const occupancy of milestone.workOrderLotOccupancies) { + descriptionHTML += + "" + + ("") + + ("") + + ("") + + "" + + "" + ""; + } + + descriptionHTML += "
" + escapeHTML(configFunctions.getProperty("aliases.occupancy")) + " Type" + escapeHTML(configFunctions.getProperty("aliases.lot")) + "Start DateEnd Date" + escapeHTML(configFunctions.getProperty("aliases.occupants")) + "
" + + '' + + escapeHTML(occupancy.occupancyType) + + "" + + (occupancy.lotName ? escapeHTML(occupancy.lotName) : "(Not Set)") + + "" + occupancy.occupancyStartDateString + "" + + (occupancy.occupancyEndDate ? occupancy.occupancyEndDateString : "(No End Date)") + + ""; + + for (const occupant of occupancy.lotOccupancyOccupants) { + descriptionHTML += + escapeHTML(occupant.lotOccupantType) + + ": " + + escapeHTML(occupant.occupantName) + + "
"; + } + + descriptionHTML += "
"; + } + + if (milestone.workOrderLots.length > 0) { + descriptionHTML += + "

Related " + + escapeHTML(configFunctions.getProperty("aliases.lots")) + + "

" + + '' + + ("") + + ("") + + ("") + + "" + + "" + + ""; + + for (const lot of milestone.workOrderLots) { + descriptionHTML += + "" + + ("") + + ("") + + ("") + + ("") + + ""; + } + + descriptionHTML += "
" + escapeHTML(configFunctions.getProperty("aliases.lot")) + " Type" + escapeHTML(configFunctions.getProperty("aliases.map")) + "" + escapeHTML(configFunctions.getProperty("aliases.lot")) + " Type" + "Status
" + + '' + + escapeHTML(lot.lotName) + + "" + escapeHTML(lot.mapName) + "" + escapeHTML(lot.lotType) + "" + escapeHTML(lot.lotStatus) + "
"; + } + + const prints = configFunctions.getProperty("settings.workOrders.prints"); + + if (prints.length > 0) { + descriptionHTML += "

Prints

"; + + for (const printName of prints) { + const printConfig = getPrintConfig(printName); + + if (printConfig) { + descriptionHTML += + "

" + + escapeHTML(printConfig.title) + + "
" + + (urlRoot + "/print/" + printName + "/?workOrderId=" + milestone.workOrderId) + + "

"; + } + } + } + + return descriptionHTML; +} + +export const handler: RequestHandler = (request, response) => { + const urlRoot = getUrlRoot(request); /* * Get work order milestones @@ -62,8 +230,8 @@ export const handler: RequestHandler = (request, response) => { } calendar.prodId({ - company: "cityssm.github.io", - product: configFunctions.getProperty("application.applicationName") + company: calendarCompany, + product: calendarProduct }); /* @@ -90,38 +258,11 @@ export const handler: RequestHandler = (request, response) => { // Build summary (title in Outlook) - let summary = - (milestone.workOrderMilestoneCompletionDate ? "✔ " : "") + - (milestone.workOrderMilestoneTypeId - ? milestone.workOrderMilestoneType - : milestone.workOrderMilestoneDescription - ).trim(); - - if (milestone.workOrderLotOccupancies.length > 0) { - let occupantCount = 0; - - for (const lotOccupancy of milestone.workOrderLotOccupancies) { - for (const occupant of lotOccupancy.lotOccupancyOccupants) { - occupantCount += 1; - - if (occupantCount === 1) { - if (summary !== "") { - summary += ": "; - } - - summary += occupant.occupantName; - } - } - } - - if (occupantCount > 1) { - summary += " plus " + (occupantCount - 1); - } - } + const summary = buildEventSummary(milestone); // Build URL - const workOrderURL = urlRoot + "/workOrders/" + milestone.workOrderId; + const workOrderUrl = getWorkOrderUrl(request, milestone); // Create event @@ -137,7 +278,7 @@ export const handler: RequestHandler = (request, response) => { ), allDay: !milestone.workOrderMilestoneTime, summary, - url: workOrderURL + url: workOrderUrl }; if (!eventData.allDay) { @@ -148,126 +289,10 @@ export const handler: RequestHandler = (request, response) => { // Build description - let descriptionHTML = - "

Milestone Description

" + - "

" + - escapeHTML(milestone.workOrderMilestoneDescription) + - "

" + - "

Work Order #" + - milestone.workOrderNumber + - "

" + - ("

" + escapeHTML(milestone.workOrderDescription) + "

") + - ("

" + workOrderURL + "

"); - - if (milestone.workOrderLotOccupancies.length > 0) { - descriptionHTML += - "

Related " + - escapeHTML(configFunctions.getProperty("aliases.occupancies")) + - "

" + - '' + - ("") + - ("") + - "" + - "" + - ("") + - "" + - ""; - - for (const occupancy of milestone.workOrderLotOccupancies) { - descriptionHTML += - "" + - ("") + - ("") + - ("") + - "" + - "" + ""; - } - - descriptionHTML += "
" + - escapeHTML(configFunctions.getProperty("aliases.occupancy")) + - " Type" + escapeHTML(configFunctions.getProperty("aliases.lot")) + "Start DateEnd Date" + escapeHTML(configFunctions.getProperty("aliases.occupants")) + "
" + - '' + - escapeHTML(occupancy.occupancyType) + - "" + - (occupancy.lotName ? escapeHTML(occupancy.lotName) : "(Not Set)") + - "" + occupancy.occupancyStartDateString + "" + - (occupancy.occupancyEndDate - ? occupancy.occupancyEndDateString - : "(No End Date)") + - ""; - - for (const occupant of occupancy.lotOccupancyOccupants) { - descriptionHTML += escapeHTML(occupant.lotOccupantType) + ": " + escapeHTML(occupant.occupantName) + "
"; - } - - descriptionHTML += "
"; - } - - if (milestone.workOrderLots.length > 0) { - descriptionHTML += - "

Related " + - escapeHTML(configFunctions.getProperty("aliases.lots")) + - "

" + - '' + - ("") + - ("") + - ("") + - "" + - "" + - ""; - - for (const lot of milestone.workOrderLots) { - descriptionHTML += - "" + - ("") + - ("") + - ("") + - ("") + - ""; - } - - descriptionHTML += "
" + escapeHTML(configFunctions.getProperty("aliases.lot")) + " Type" + escapeHTML(configFunctions.getProperty("aliases.map")) + "" + - escapeHTML(configFunctions.getProperty("aliases.lot")) + - " Type" + - "Status
" + - '' + - escapeHTML(lot.lotName) + - "" + escapeHTML(lot.mapName) + "" + escapeHTML(lot.lotType) + "" + escapeHTML(lot.lotStatus) + "
"; - } - - const prints = configFunctions.getProperty("settings.workOrders.prints"); - - if (prints.length > 0) { - descriptionHTML += "

Prints

"; - - for (const printName of prints) { - const printConfig = getPrintConfig(printName); - - if (printConfig) { - descriptionHTML += - "

" + - escapeHTML(printConfig.title) + - "
" + - (urlRoot + - "/print/" + - printName + - "/?workOrderId=" + - milestone.workOrderId) + - "

"; - } - } - } + const descriptionHTML = buildEventDescriptionHTML(request, milestone); calendarEvent.description({ - plain: workOrderURL, + plain: workOrderUrl, html: descriptionHTML });