/* eslint-disable unicorn/filename-case */ import ical, { ICalEventData, ICalEventStatus } from "ical-generator"; import { getWorkOrderMilestones, WorkOrderMilestoneFilters } from "../../helpers/lotOccupancyDB/getWorkOrderMilestones.js"; import type { RequestHandler } from "express"; import * as configFunctions from "../../helpers/functions.config.js"; 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 = "http://" + request.hostname + (configFunctions.getProperty("application.httpPort") === 80 ? "" : ":" + configFunctions.getProperty("application.httpPort")) + configFunctions.getProperty("reverseProxy.urlPrefix"); const workOrderMilestoneFilters: WorkOrderMilestoneFilters = { workOrderTypeIds: request.query.workOrderTypeIds as string, workOrderMilestoneTypeIds: request.query .workOrderMilestoneTypeIds as string }; if (request.query.workOrderId) { workOrderMilestoneFilters.workOrderId = request.query .workOrderId as string; } else { workOrderMilestoneFilters.workOrderMilestoneDateFilter = "recent"; } const workOrderMilestones = getWorkOrderMilestones( workOrderMilestoneFilters, { includeWorkOrders: true, orderBy: "date" } ); const calendar = ical({ name: "Work Order Milestone Calendar", url: urlRoot + "/workOrders" }); if (request.query.workOrderId && workOrderMilestones.length > 0) { calendar.name("Work Order #" + workOrderMilestones[0].workOrder.workOrderNumber); calendar.url(urlRoot + "/workOrders/" + workOrderMilestones[0].workOrderId); } calendar.prodId({ company: "cityssm.github.io", product: configFunctions.getProperty("application.applicationName") }); for (const milestone of workOrderMilestones) { const milestoneTimePieces = ( milestone.workOrderMilestoneDateString + " " + milestone.workOrderMilestoneTimeString ).split(timeStringSplitRegex); 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) ); // Build summary (title in Outlook) let summary = ( milestone.workOrderMilestoneTypeId ? milestone.workOrderMilestoneType : milestone.workOrderMilestoneDescription ).trim(); if (milestone.workOrder.workOrderLotOccupancies.length > 0) { let occupantCount = 0; for (const lotOccupancy of milestone.workOrder .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); } } // Build URL const workOrderURL = urlRoot + "/workOrders/" + milestone.workOrderId; // Create event const eventData: ICalEventData = { start: milestoneDate, created: new Date(milestone.recordCreate_timeMillis), stamp: new Date(milestone.recordCreate_timeMillis), lastModified: new Date( Math.max( milestone.recordUpdate_timeMillis, milestone.workOrder.recordUpdate_timeMillis ) ), allDay: !milestone.workOrderMilestoneTime, summary, url: workOrderURL }; const calendarEvent = calendar.createEvent(eventData); // Build description let descriptionHTML = "
" + escapeHTML(milestone.workOrderMilestoneDescription) + "
" + "" + escapeHTML(milestone.workOrder.workOrderDescription) + "
") + ('"); if (milestone.workOrder.workOrderLotOccupancies.length > 0) { descriptionHTML += "| " + escapeHTML( configFunctions.getProperty("aliases.occupancy") ) + " Type | ") + ("" + escapeHTML(configFunctions.getProperty("aliases.lot")) + " | ") + "Start Date | " + "End 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.occupantName) + " "; } 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) + " | ") + "