diff --git a/app.js b/app.js index fa3e5e1b..6d65358a 100644 --- a/app.js +++ b/app.js @@ -10,13 +10,15 @@ import FileStore from "session-file-store"; import routerLogin from "./routes/login.js"; import routerDashboard from "./routes/dashboard.js"; import routerApi from "./routes/api.js"; -import routerLots from "./routes/lots.js"; +import routerPrint from "./routes/print.js"; import routerMaps from "./routes/maps.js"; +import routerLots from "./routes/lots.js"; import routerLotOccupancies from "./routes/lotOccupancies.js"; import routerWorkOrders from "./routes/workOrders.js"; import routerReports from "./routes/reports.js"; import routerAdmin from "./routes/admin.js"; import * as configFunctions from "./helpers/functions.config.js"; +import * as printFunctions from "./helpers/functions.print.js"; import * as dateTimeFns from "@cityssm/expressjs-server-js/dateTimeFns.js"; import * as stringFns from "@cityssm/expressjs-server-js/stringFns.js"; import * as htmlFns from "@cityssm/expressjs-server-js/htmlFns.js"; @@ -102,6 +104,7 @@ app.use((request, response, next) => { response.locals.user = request.session.user; response.locals.csrfToken = request.csrfToken(); response.locals.configFunctions = configFunctions; + response.locals.printFunctions = printFunctions; response.locals.dateTimeFunctions = dateTimeFns; response.locals.stringFunctions = stringFns; response.locals.htmlFunctions = htmlFns; @@ -113,8 +116,9 @@ app.get(urlPrefix + "/", sessionChecker, (_request, response) => { }); app.use(urlPrefix + "/dashboard", sessionChecker, routerDashboard); app.use(urlPrefix + "/api/:apiKey", apiGetHandler, routerApi); -app.use(urlPrefix + "/lots", sessionChecker, routerLots); +app.use(urlPrefix + "/print", sessionChecker, routerPrint); app.use(urlPrefix + "/maps", sessionChecker, routerMaps); +app.use(urlPrefix + "/lots", sessionChecker, routerLots); app.use(urlPrefix + "/lotOccupancies", sessionChecker, routerLotOccupancies); app.use(urlPrefix + "/workOrders", sessionChecker, routerWorkOrders); app.use(urlPrefix + "/reports", sessionChecker, routerReports); @@ -135,13 +139,6 @@ app.get(urlPrefix + "/logout", (request, response) => { } }); app.use((_request, _response, next) => { - next(createError(404)); -}); -app.use((error, request, response) => { - response.locals.message = error.message; - response.locals.error = - request.app.get("env") === "development" ? error : {}; - response.status(error.status || 500); - response.render("error"); + next(createError(404, "File not found.")); }); export default app; diff --git a/app.ts b/app.ts index c527e209..c98c83c1 100644 --- a/app.ts +++ b/app.ts @@ -13,14 +13,16 @@ import FileStore from "session-file-store"; import routerLogin from "./routes/login.js"; import routerDashboard from "./routes/dashboard.js"; import routerApi from "./routes/api.js"; -import routerLots from "./routes/lots.js"; +import routerPrint from "./routes/print.js"; import routerMaps from "./routes/maps.js"; +import routerLots from "./routes/lots.js"; import routerLotOccupancies from "./routes/lotOccupancies.js"; import routerWorkOrders from "./routes/workOrders.js"; import routerReports from "./routes/reports.js"; import routerAdmin from "./routes/admin.js"; import * as configFunctions from "./helpers/functions.config.js"; +import * as printFunctions from "./helpers/functions.print.js"; import * as dateTimeFns from "@cityssm/expressjs-server-js/dateTimeFns.js"; import * as stringFns from "@cityssm/expressjs-server-js/stringFns.js"; import * as htmlFns from "@cityssm/expressjs-server-js/htmlFns.js"; @@ -54,7 +56,6 @@ if (!configFunctions.getProperty("reverseProxy.disableEtag")) { app.set("etag", false); } - // View engine setup app.set("views", path.join(__dirname, "views")); app.set("view engine", "ejs"); @@ -123,27 +124,18 @@ app.use( app.use( urlPrefix + "/lib/fa", - express.static( - path.join("node_modules", "@fortawesome", "fontawesome-free") - ) + express.static(path.join("node_modules", "@fortawesome", "fontawesome-free")) ); -app.use( - urlPrefix + "/lib/leaflet", - express.static(path.join("node_modules", "leaflet", "dist")) -); +app.use(urlPrefix + "/lib/leaflet", express.static(path.join("node_modules", "leaflet", "dist"))); -app.use( - urlPrefix + "/lib/randomcolor", - express.static(path.join("node_modules", "randomcolor")) -); +app.use(urlPrefix + "/lib/randomcolor", express.static(path.join("node_modules", "randomcolor"))); /* * SESSION MANAGEMENT */ -const sessionCookieName: string = - configFunctions.getProperty("session.cookieName"); +const sessionCookieName: string = configFunctions.getProperty("session.cookieName"); const FileStoreSession = FileStore(session); @@ -188,9 +180,7 @@ const sessionChecker = ( const redirectUrl = getSafeRedirectURL(request.originalUrl); - return response.redirect( - `${urlPrefix}/login?redirect=${redirectUrl}` - ); + return response.redirect(`${urlPrefix}/login?redirect=${redirectUrl}`); }; /* @@ -206,13 +196,12 @@ app.use((request, response, next) => { response.locals.csrfToken = request.csrfToken(); response.locals.configFunctions = configFunctions; + response.locals.printFunctions = printFunctions; response.locals.dateTimeFunctions = dateTimeFns; response.locals.stringFunctions = stringFns; response.locals.htmlFunctions = htmlFns; - response.locals.urlPrefix = configFunctions.getProperty( - "reverseProxy.urlPrefix" - ); + response.locals.urlPrefix = configFunctions.getProperty("reverseProxy.urlPrefix"); next(); }); @@ -225,8 +214,9 @@ app.use(urlPrefix + "/dashboard", sessionChecker, routerDashboard); app.use(urlPrefix + "/api/:apiKey", apiGetHandler, routerApi); -app.use(urlPrefix + "/lots", sessionChecker, routerLots); +app.use(urlPrefix + "/print", sessionChecker, routerPrint); app.use(urlPrefix + "/maps", sessionChecker, routerMaps); +app.use(urlPrefix + "/lots", sessionChecker, routerLots); app.use(urlPrefix + "/lotOccupancies", sessionChecker, routerLotOccupancies); app.use(urlPrefix + "/workOrders", sessionChecker, routerWorkOrders); @@ -253,28 +243,7 @@ app.get(urlPrefix + "/logout", (request, response) => { // Catch 404 and forward to error handler app.use((_request, _response, next) => { - next(createError(404)); + next(createError(404, "File not found.")); }); -// Error handler -app.use( - ( - error: { - status: number; - message: string; - }, - request: express.Request, - response: express.Response - ) => { - // Set locals, only providing error in development - response.locals.message = error.message; - response.locals.error = - request.app.get("env") === "development" ? error : {}; - - // Render the error page - response.status(error.status || 500); - response.render("error"); - } -); - export default app; diff --git a/handlers/lotOccupancies-get/print.js b/handlers/lotOccupancies-get/print.js deleted file mode 100644 index c84d9a5f..00000000 --- a/handlers/lotOccupancies-get/print.js +++ /dev/null @@ -1,17 +0,0 @@ -import * as configFunctions from "../../helpers/functions.config.js"; -import { getLotOccupancy } from "../../helpers/lotOccupancyDB/getLotOccupancy.js"; -export const handler = (request, response) => { - const lotOccupancy = getLotOccupancy(request.params.lotOccupancyId); - if (!lotOccupancy) { - return response.redirect(configFunctions.getProperty("reverseProxy.urlPrefix") + - "/lotOccupancies/?error=lotOccupancyIdNotFound"); - } - return response.render("lotOccupancy-print", { - headTitle: configFunctions.getProperty("aliases.lot") + - " " + - configFunctions.getProperty("aliases.occupancy") + - " Print", - lotOccupancy - }); -}; -export default handler; diff --git a/handlers/lotOccupancies-get/print.ts b/handlers/lotOccupancies-get/print.ts deleted file mode 100644 index 311a7a19..00000000 --- a/handlers/lotOccupancies-get/print.ts +++ /dev/null @@ -1,27 +0,0 @@ -import type { RequestHandler } from "express"; - -import * as configFunctions from "../../helpers/functions.config.js"; - -import { getLotOccupancy } from "../../helpers/lotOccupancyDB/getLotOccupancy.js"; - -export const handler: RequestHandler = (request, response) => { - const lotOccupancy = getLotOccupancy(request.params.lotOccupancyId); - - if (!lotOccupancy) { - return response.redirect( - configFunctions.getProperty("reverseProxy.urlPrefix") + - "/lotOccupancies/?error=lotOccupancyIdNotFound" - ); - } - - return response.render("lotOccupancy-print", { - headTitle: - configFunctions.getProperty("aliases.lot") + - " " + - configFunctions.getProperty("aliases.occupancy") + - " Print", - lotOccupancy - }); -}; - -export default handler; diff --git a/handlers/lotOccupancies-get/print.d.ts b/handlers/print-get/screen.d.ts similarity index 100% rename from handlers/lotOccupancies-get/print.d.ts rename to handlers/print-get/screen.d.ts diff --git a/handlers/print-get/screen.js b/handlers/print-get/screen.js new file mode 100644 index 00000000..331b457b --- /dev/null +++ b/handlers/print-get/screen.js @@ -0,0 +1,20 @@ +import * as configFunctions from "../../helpers/functions.config.js"; +import { getScreenPrintConfig } from "../../helpers/functions.print.js"; +import { getLotOccupancy } from "../../helpers/lotOccupancyDB/getLotOccupancy.js"; +export const handler = (request, response) => { + const printName = request.params.printName; + const printConfig = getScreenPrintConfig(printName); + if (!printConfig) { + return response.redirect(configFunctions.getProperty("reverseProxy.urlPrefix") + + "/dashboard/?error=printConfigNotFound"); + } + const reportData = { + headTitle: printConfig.title + }; + if (printConfig.params.includes("lotOccupancyId") && + typeof request.query.lotOccupancyId === "string") { + reportData.lotOccupancy = getLotOccupancy(request.query.lotOccupancyId); + } + return response.render("print/screen/" + printName, reportData); +}; +export default handler; diff --git a/handlers/print-get/screen.ts b/handlers/print-get/screen.ts new file mode 100644 index 00000000..221324c3 --- /dev/null +++ b/handlers/print-get/screen.ts @@ -0,0 +1,34 @@ +import type { RequestHandler } from "express"; + +import * as configFunctions from "../../helpers/functions.config.js"; +import { getScreenPrintConfig } from "../../helpers/functions.print.js"; + +import { getLotOccupancy } from "../../helpers/lotOccupancyDB/getLotOccupancy.js"; + +export const handler: RequestHandler = (request, response) => { + const printName = request.params.printName; + + const printConfig = getScreenPrintConfig(printName); + + if (!printConfig) { + return response.redirect( + configFunctions.getProperty("reverseProxy.urlPrefix") + + "/dashboard/?error=printConfigNotFound" + ); + } + + const reportData: { [dataName: string]: unknown } = { + headTitle: printConfig.title + }; + + if ( + printConfig.params.includes("lotOccupancyId") && + typeof request.query.lotOccupancyId === "string" + ) { + reportData.lotOccupancy = getLotOccupancy(request.query.lotOccupancyId); + } + + return response.render("print/screen/" + printName, reportData); +}; + +export default handler; diff --git a/helpers/functions.config.d.ts b/helpers/functions.config.d.ts index 5f18185e..be7d2f0c 100644 --- a/helpers/functions.config.d.ts +++ b/helpers/functions.config.d.ts @@ -32,6 +32,7 @@ export declare function getProperty(propertyName: "settings.lot.lotNameSortNameF export declare function getProperty(propertyName: "settings.lotOccupancy.occupancyEndDateIsRequired"): boolean; export declare function getProperty(propertyName: "settings.lotOccupancy.occupantCityDefault"): string; export declare function getProperty(propertyName: "settings.lotOccupancy.occupantProvinceDefault"): string; +export declare function getProperty(propertyName: "settings.lotOccupancy.prints"): string[]; export declare function getProperty(propertyName: "settings.fees.taxPercentageDefault"): number; export declare function getProperty(propertyName: "settings.workOrders.workOrderNumberLength"): number; export declare function getProperty(propertyName: "settings.workOrders.workOrderMilestoneDateRecentBeforeDays"): number; diff --git a/helpers/functions.config.js b/helpers/functions.config.js index c73c1c58..c3a8169d 100644 --- a/helpers/functions.config.js +++ b/helpers/functions.config.js @@ -31,6 +31,7 @@ configFallbackValues.set("settings.lot.lotNameSortNameFunction", (lotName) => lo configFallbackValues.set("settings.lotOccupancy.occupancyEndDateIsRequired", true); configFallbackValues.set("settings.lotOccupancy.occupantCityDefault", ""); configFallbackValues.set("settings.lotOccupancy.occupantProvinceDefault", ""); +configFallbackValues.set("settings.lotOccupancy.prints", ["screen/lotOccupancy"]); configFallbackValues.set("settings.fees.taxPercentageDefault", 0); configFallbackValues.set("settings.workOrders.workOrderNumberLength", 6); configFallbackValues.set("settings.workOrders.workOrderMilestoneDateRecentBeforeDays", 5); diff --git a/helpers/functions.config.ts b/helpers/functions.config.ts index 83fa1599..a39200b6 100644 --- a/helpers/functions.config.ts +++ b/helpers/functions.config.ts @@ -48,6 +48,7 @@ configFallbackValues.set("settings.lot.lotNameSortNameFunction", (lotName: strin configFallbackValues.set("settings.lotOccupancy.occupancyEndDateIsRequired", true); configFallbackValues.set("settings.lotOccupancy.occupantCityDefault", ""); configFallbackValues.set("settings.lotOccupancy.occupantProvinceDefault", ""); +configFallbackValues.set("settings.lotOccupancy.prints", ["screen/lotOccupancy"]); configFallbackValues.set("settings.fees.taxPercentageDefault", 0); @@ -112,8 +113,8 @@ export function getProperty( ): boolean; export function getProperty(propertyName: "settings.lotOccupancy.occupantCityDefault"): string; - export function getProperty(propertyName: "settings.lotOccupancy.occupantProvinceDefault"): string; +export function getProperty(propertyName: "settings.lotOccupancy.prints"): string[]; export function getProperty(propertyName: "settings.fees.taxPercentageDefault"): number; diff --git a/helpers/functions.print.d.ts b/helpers/functions.print.d.ts new file mode 100644 index 00000000..aa758d7e --- /dev/null +++ b/helpers/functions.print.d.ts @@ -0,0 +1,7 @@ +interface PrintConfig { + title: string; + params: string[]; +} +export declare const getScreenPrintConfig: (printName: string) => PrintConfig; +export declare const getPrintConfig: (screenOrPdf_printName: string) => PrintConfig; +export {}; diff --git a/helpers/functions.print.js b/helpers/functions.print.js new file mode 100644 index 00000000..57ec254a --- /dev/null +++ b/helpers/functions.print.js @@ -0,0 +1,20 @@ +import * as configFunctions from "./functions.config.js"; +const screenPrintConfigs = { + lotOccupancy: { + title: configFunctions.getProperty("aliases.lot") + + " " + + configFunctions.getProperty("aliases.occupancy") + + " Print", + params: ["lotOccupancyId"] + } +}; +export const getScreenPrintConfig = (printName) => { + return screenPrintConfigs[printName]; +}; +export const getPrintConfig = (screenOrPdf_printName) => { + const printNameSplit = screenOrPdf_printName.split("/"); + switch (printNameSplit[0]) { + case "screen": + return getScreenPrintConfig(printNameSplit[1]); + } +}; diff --git a/helpers/functions.print.ts b/helpers/functions.print.ts new file mode 100644 index 00000000..e3eb85bc --- /dev/null +++ b/helpers/functions.print.ts @@ -0,0 +1,30 @@ +import * as configFunctions from "./functions.config.js"; + +interface PrintConfig { + title: string; + params: string[]; +} + +const screenPrintConfigs = { + lotOccupancy: { + title: + configFunctions.getProperty("aliases.lot") + + " " + + configFunctions.getProperty("aliases.occupancy") + + " Print", + params: ["lotOccupancyId"] + } +}; + +export const getScreenPrintConfig = (printName: string): PrintConfig => { + return screenPrintConfigs[printName]; +}; + +export const getPrintConfig = (screenOrPdf_printName: string): PrintConfig => { + const printNameSplit = screenOrPdf_printName.split("/"); + + switch (printNameSplit[0]) { + case "screen": + return getScreenPrintConfig(printNameSplit[1]); + } +}; diff --git a/routes/lotOccupancies.js b/routes/lotOccupancies.js index ea373333..3704d4aa 100644 --- a/routes/lotOccupancies.js +++ b/routes/lotOccupancies.js @@ -2,7 +2,6 @@ import { Router } from "express"; import handler_search from "../handlers/lotOccupancies-get/search.js"; import handler_doSearchLotOccupancies from "../handlers/lotOccupancies-post/doSearchLotOccupancies.js"; import handler_view from "../handlers/lotOccupancies-get/view.js"; -import handler_print from "../handlers/lotOccupancies-get/print.js"; import handler_new from "../handlers/lotOccupancies-get/new.js"; import handler_doGetOccupancyTypeFields from "../handlers/lotOccupancies-post/doGetOccupancyTypeFields.js"; import handler_doCreateLotOccupancy from "../handlers/lotOccupancies-post/doCreateLotOccupancy.js"; @@ -28,7 +27,6 @@ router.get("/new", permissionHandlers.updateGetHandler, handler_new); router.post("/doGetOccupancyTypeFields", permissionHandlers.updatePostHandler, handler_doGetOccupancyTypeFields); router.post("/doCreateLotOccupancy", permissionHandlers.updatePostHandler, handler_doCreateLotOccupancy); router.get("/:lotOccupancyId", handler_view); -router.get("/:lotOccupancyId/print", handler_print); router.get("/:lotOccupancyId/edit", permissionHandlers.updateGetHandler, handler_edit); router.post("/doUpdateLotOccupancy", permissionHandlers.updatePostHandler, handler_doUpdateLotOccupancy); router.post("/doDeleteLotOccupancy", permissionHandlers.updatePostHandler, handler_doDeleteLotOccupancy); diff --git a/routes/lotOccupancies.ts b/routes/lotOccupancies.ts index 74063446..7d251a4d 100644 --- a/routes/lotOccupancies.ts +++ b/routes/lotOccupancies.ts @@ -4,7 +4,6 @@ import handler_search from "../handlers/lotOccupancies-get/search.js"; import handler_doSearchLotOccupancies from "../handlers/lotOccupancies-post/doSearchLotOccupancies.js"; import handler_view from "../handlers/lotOccupancies-get/view.js"; -import handler_print from "../handlers/lotOccupancies-get/print.js"; import handler_new from "../handlers/lotOccupancies-get/new.js"; import handler_doGetOccupancyTypeFields from "../handlers/lotOccupancies-post/doGetOccupancyTypeFields.js"; @@ -59,8 +58,6 @@ router.post( router.get("/:lotOccupancyId", handler_view); -router.get("/:lotOccupancyId/print", handler_print); - // Edit router.get( diff --git a/routes/print.d.ts b/routes/print.d.ts new file mode 100644 index 00000000..433ab333 --- /dev/null +++ b/routes/print.d.ts @@ -0,0 +1,2 @@ +export declare const router: import("express-serve-static-core").Router; +export default router; diff --git a/routes/print.js b/routes/print.js new file mode 100644 index 00000000..2a270b04 --- /dev/null +++ b/routes/print.js @@ -0,0 +1,5 @@ +import { Router } from "express"; +import handler_screen from "../handlers/print-get/screen.js"; +export const router = Router(); +router.get("/screen/:printName", handler_screen); +export default router; diff --git a/routes/print.ts b/routes/print.ts new file mode 100644 index 00000000..c28902bf --- /dev/null +++ b/routes/print.ts @@ -0,0 +1,9 @@ +import { Router } from "express"; + +import handler_screen from "../handlers/print-get/screen.js"; + +export const router = Router(); + +router.get("/screen/:printName", handler_screen); + +export default router; diff --git a/types/configTypes.d.ts b/types/configTypes.d.ts index 6f445aa3..a153b2d6 100644 --- a/types/configTypes.d.ts +++ b/types/configTypes.d.ts @@ -41,6 +41,7 @@ export interface Config { occupancyEndDateIsRequired?: boolean; occupantCityDefault?: string; occupantProvinceDefault?: string; + prints?: string[]; }; workOrders?: { workOrderNumberLength?: number; diff --git a/types/configTypes.ts b/types/configTypes.ts index 5e0a5a58..8316bcc4 100644 --- a/types/configTypes.ts +++ b/types/configTypes.ts @@ -41,6 +41,7 @@ export interface Config { occupancyEndDateIsRequired?: boolean; occupantCityDefault?: string; occupantProvinceDefault?: string; + prints?: string[]; }; workOrders?: { workOrderNumberLength?: number; diff --git a/types/globalTypes.js b/types/globalTypes.js index c8ad2e54..cb0ff5c3 100644 --- a/types/globalTypes.js +++ b/types/globalTypes.js @@ -1,2 +1 @@ -"use strict"; -Object.defineProperty(exports, "__esModule", { value: true }); +export {}; diff --git a/views/lotOccupancy-edit.ejs b/views/lotOccupancy-edit.ejs index 562badfe..7b55a729 100644 --- a/views/lotOccupancy-edit.ejs +++ b/views/lotOccupancy-edit.ejs @@ -46,14 +46,39 @@ -