development

deepsource-autofix-76c6eb20
Dan Gowans 2022-07-25 15:51:57 -04:00
parent b4127304d1
commit 8a80a1a57a
51 changed files with 2366 additions and 1580 deletions

6
app.js
View File

@ -93,9 +93,9 @@ app.use((request, response, next) => {
response.locals.user = request.session.user; response.locals.user = request.session.user;
response.locals.csrfToken = request.csrfToken(); response.locals.csrfToken = request.csrfToken();
response.locals.configFunctions = configFunctions; response.locals.configFunctions = configFunctions;
response.locals.dateTimeFns = dateTimeFns; response.locals.dateTimeFunctions = dateTimeFns;
response.locals.stringFns = stringFns; response.locals.stringFunctions = stringFns;
response.locals.htmlFns = htmlFns; response.locals.htmlFunctions = htmlFns;
response.locals.urlPrefix = configFunctions.getProperty("reverseProxy.urlPrefix"); response.locals.urlPrefix = configFunctions.getProperty("reverseProxy.urlPrefix");
next(); next();
}); });

6
app.ts
View File

@ -175,9 +175,9 @@ app.use((request, response, next) => {
response.locals.csrfToken = request.csrfToken(); response.locals.csrfToken = request.csrfToken();
response.locals.configFunctions = configFunctions; response.locals.configFunctions = configFunctions;
response.locals.dateTimeFns = dateTimeFns; response.locals.dateTimeFunctions = dateTimeFns;
response.locals.stringFns = stringFns; response.locals.stringFunctions = stringFns;
response.locals.htmlFns = htmlFns; response.locals.htmlFunctions = htmlFns;
response.locals.urlPrefix = configFunctions.getProperty("reverseProxy.urlPrefix"); response.locals.urlPrefix = configFunctions.getProperty("reverseProxy.urlPrefix");

View File

@ -1,7 +1,22 @@
export const handler = (_request, response) => { import * as configFunctions from "../../helpers/functions.config.js";
import { getLot } from "../../helpers/lotOccupancyDB/getLot.js";
import { getMaps } from "../../helpers/lotOccupancyDB/getMaps.js";
import * as cacheFunctions from "../../helpers/functions.cache.js";
export const handler = (request, response) => {
const lot = getLot(request.params.lotId);
if (!lot) {
return response.redirect(configFunctions.getProperty("reverseProxy.urlPrefix") + "/lots/?error=lotIdNotFound");
}
const maps = getMaps();
const lotTypes = cacheFunctions.getLotTypes();
const lotStatuses = cacheFunctions.getLotStatuses();
return response.render("lot-edit", { return response.render("lot-edit", {
headTitle: "Licence Update", headTitle: lot.lotName,
isCreate: false lot,
isCreate: false,
maps,
lotTypes,
lotStatuses
}); });
}; };
export default handler; export default handler;

View File

@ -1,11 +1,30 @@
import type { RequestHandler } from "express"; import type { RequestHandler } from "express";
import * as configFunctions from "../../helpers/functions.config.js";
export const handler: RequestHandler = (_request, response) => { import { getLot } from "../../helpers/lotOccupancyDB/getLot.js";
import { getMaps } from "../../helpers/lotOccupancyDB/getMaps.js";
import * as cacheFunctions from "../../helpers/functions.cache.js";
export const handler: RequestHandler = (request, response) => {
const lot = getLot(request.params.lotId);
if (!lot) {
return response.redirect(configFunctions.getProperty("reverseProxy.urlPrefix") + "/lots/?error=lotIdNotFound");
}
const maps = getMaps();
const lotTypes = cacheFunctions.getLotTypes();
const lotStatuses = cacheFunctions.getLotStatuses();
return response.render("lot-edit", { return response.render("lot-edit", {
headTitle: "Licence Update", headTitle: lot.lotName,
isCreate: false lot,
isCreate: false,
maps,
lotTypes,
lotStatuses
}); });
}; };

View File

@ -1,7 +1,20 @@
import * as configFunctions from "../../helpers/functions.config.js";
import { getMaps } from "../../helpers/lotOccupancyDB/getMaps.js";
import * as cacheFunctions from "../../helpers/functions.cache.js";
export const handler = (_request, response) => { export const handler = (_request, response) => {
const lot = {
lotOccupancies: []
};
const maps = getMaps();
const lotTypes = cacheFunctions.getLotTypes();
const lotStatuses = cacheFunctions.getLotStatuses();
response.render("lot-edit", { response.render("lot-edit", {
headTitle: "Licence Create", headTitle: "Create a New " + configFunctions.getProperty("aliases.lot"),
isCreate: true lot,
isCreate: true,
maps,
lotTypes,
lotStatuses
}); });
}; };
export default handler; export default handler;

View File

@ -1,11 +1,30 @@
import type { RequestHandler } from "express"; import type { RequestHandler } from "express";
import * as configFunctions from "../../helpers/functions.config.js";
import { getMaps } from "../../helpers/lotOccupancyDB/getMaps.js";
import * as cacheFunctions from "../../helpers/functions.cache.js";
import * as recordTypes from "../../types/recordTypes";
export const handler: RequestHandler = (_request, response) => { export const handler: RequestHandler = (_request, response) => {
const lot: recordTypes.Lot = {
lotOccupancies: []
};
const maps = getMaps();
const lotTypes = cacheFunctions.getLotTypes();
const lotStatuses = cacheFunctions.getLotStatuses();
response.render("lot-edit", { response.render("lot-edit", {
headTitle: "Licence Create", headTitle: "Create a New " + configFunctions.getProperty("aliases.lot"),
isCreate: true lot,
isCreate: true,
maps,
lotTypes,
lotStatuses
}); });
}; };

View File

@ -1,6 +1,5 @@
import * as configFunctions from "../../helpers/functions.config.js"; import * as configFunctions from "../../helpers/functions.config.js";
import { getLot } from "../../helpers/lotOccupancyDB/getLot.js"; import { getLot } from "../../helpers/lotOccupancyDB/getLot.js";
const urlPrefix = configFunctions.getProperty("reverseProxy.urlPrefix");
export const handler = (request, response) => { export const handler = (request, response) => {
const lot = getLot(request.params.lotId); const lot = getLot(request.params.lotId);
if (!lot) { if (!lot) {

View File

@ -5,9 +5,6 @@ import * as configFunctions from "../../helpers/functions.config.js";
import { getLot } from "../../helpers/lotOccupancyDB/getLot.js"; import { getLot } from "../../helpers/lotOccupancyDB/getLot.js";
const urlPrefix = configFunctions.getProperty("reverseProxy.urlPrefix");
export const handler: RequestHandler = (request, response) => { export const handler: RequestHandler = (request, response) => {
const lot = getLot(request.params.lotId); const lot = getLot(request.params.lotId);
@ -16,7 +13,6 @@ export const handler: RequestHandler = (request, response) => {
return response.redirect(configFunctions.getProperty("reverseProxy.urlPrefix") + "/lots/?error=lotIdNotFound"); return response.redirect(configFunctions.getProperty("reverseProxy.urlPrefix") + "/lots/?error=lotIdNotFound");
} }
return response.render("lot-view", { return response.render("lot-view", {
headTitle: lot.lotName, headTitle: lot.lotName,
lot lot

View File

@ -0,0 +1,3 @@
import type { RequestHandler } from "express";
export declare const handler: RequestHandler;
export default handler;

View File

@ -0,0 +1,9 @@
import { addLot } from "../../helpers/lotOccupancyDB/addLot.js";
export const handler = async (request, response) => {
const lotId = addLot(request.body, request.session);
response.json({
success: true,
lotId
});
};
export default handler;

View File

@ -0,0 +1,17 @@
import type { RequestHandler } from "express";
import { addLot } from "../../helpers/lotOccupancyDB/addLot.js";
export const handler: RequestHandler = async (request, response) => {
const lotId = addLot(request.body, request.session);
response.json({
success: true,
lotId
});
};
export default handler;

View File

@ -0,0 +1,3 @@
import type { RequestHandler } from "express";
export declare const handler: RequestHandler;
export default handler;

View File

@ -0,0 +1,9 @@
import { updateLot } from "../../helpers/lotOccupancyDB/updateLot.js";
export const handler = async (request, response) => {
const success = updateLot(request.body, request.session);
response.json({
success,
lotId: request.body.lotId
});
};
export default handler;

View File

@ -0,0 +1,17 @@
import type { RequestHandler } from "express";
import { updateLot } from "../../helpers/lotOccupancyDB/updateLot.js";
export const handler: RequestHandler = async (request, response) => {
const success = updateLot(request.body, request.session);
response.json({
success,
lotId: request.body.lotId
});
};
export default handler;

View File

@ -2,7 +2,7 @@ import { getLotOccupantTypes as getLotOccupantTypesFromDatabase } from "./lotOcc
import { getLotStatuses as getLotStatusesFromDatabase } from "./lotOccupancyDB/getLotStatuses.js"; import { getLotStatuses as getLotStatusesFromDatabase } from "./lotOccupancyDB/getLotStatuses.js";
import { getLotTypes as getLotTypesFromDatabase } from "./lotOccupancyDB/getLotTypes.js"; import { getLotTypes as getLotTypesFromDatabase } from "./lotOccupancyDB/getLotTypes.js";
import { getOccupancyTypes as getOccupancyTypesFromDatabase } from "./lotOccupancyDB/getOccupancyTypes.js"; import { getOccupancyTypes as getOccupancyTypesFromDatabase } from "./lotOccupancyDB/getOccupancyTypes.js";
import getOccupancyType from "./lotOccupancyDB/getOccupancyType.js"; import { getOccupancyType } from "./lotOccupancyDB/getOccupancyType.js";
let lotOccupantTypes; let lotOccupantTypes;
export function getLotOccupantTypes() { export function getLotOccupantTypes() {
if (!lotOccupantTypes) { if (!lotOccupantTypes) {

View File

@ -4,7 +4,7 @@ import { getLotTypes as getLotTypesFromDatabase } from "./lotOccupancyDB/getLotT
import { getOccupancyTypes as getOccupancyTypesFromDatabase } from "./lotOccupancyDB/getOccupancyTypes.js"; import { getOccupancyTypes as getOccupancyTypesFromDatabase } from "./lotOccupancyDB/getOccupancyTypes.js";
import type * as recordTypes from "../types/recordTypes"; import type * as recordTypes from "../types/recordTypes";
import getOccupancyType from "./lotOccupancyDB/getOccupancyType.js"; import { getOccupancyType } from "./lotOccupancyDB/getOccupancyType.js";
/* /*
* Lot Occupant Types * Lot Occupant Types

View File

@ -1,5 +1,7 @@
import sqlite from "better-sqlite3"; import sqlite from "better-sqlite3";
import { lotOccupancyDB as databasePath } from "../../data/databasePaths.js"; import { lotOccupancyDB as databasePath } from "../../data/databasePaths.js";
import { getLotComments } from "./getLotComments.js";
import { getLotOccupancies } from "./getLotOccupancies.js";
export const getLot = (lotId) => { export const getLot = (lotId) => {
const database = sqlite(databasePath, { const database = sqlite(databasePath, {
readonly: true readonly: true
@ -18,6 +20,16 @@ export const getLot = (lotId) => {
" where l.recordDelete_timeMillis is null" + " where l.recordDelete_timeMillis is null" +
" and l.lotId = ?") " and l.lotId = ?")
.get(lotId); .get(lotId);
if (lot) {
lot.lotOccupancies = getLotOccupancies({
lotId
}, {
includeOccupants: true,
limit: -1,
offset: 0
}, database).lotOccupancies;
lot.lotComments = getLotComments(lotId);
}
database.close(); database.close();
return lot; return lot;
}; };

View File

@ -4,6 +4,8 @@ import {
} from "../../data/databasePaths.js"; } from "../../data/databasePaths.js";
import type * as recordTypes from "../../types/recordTypes"; import type * as recordTypes from "../../types/recordTypes";
import { getLotComments } from "./getLotComments.js";
import { getLotOccupancies } from "./getLotOccupancies.js";
export const getLot = (lotId: number | string): recordTypes.Lot => { export const getLot = (lotId: number | string): recordTypes.Lot => {
@ -27,6 +29,18 @@ export const getLot = (lotId: number | string): recordTypes.Lot => {
" and l.lotId = ?") " and l.lotId = ?")
.get(lotId); .get(lotId);
if (lot) {
lot.lotOccupancies = getLotOccupancies({
lotId
}, {
includeOccupants: true,
limit: -1,
offset: 0
}, database).lotOccupancies;
lot.lotComments = getLotComments(lotId);
}
database.close(); database.close();
return lot; return lot;

View File

@ -0,0 +1,4 @@
import sqlite from "better-sqlite3";
import type * as recordTypes from "../../types/recordTypes";
export declare const getLotComments: (lotId: number | string, connectedDatabase?: sqlite.Database) => recordTypes.LotComment[];
export default getLotComments;

View File

@ -0,0 +1,25 @@
import { dateIntegerToString, timeIntegerToString } from "@cityssm/expressjs-server-js/dateTimeFns.js";
import sqlite from "better-sqlite3";
import { lotOccupancyDB as databasePath } from "../../data/databasePaths.js";
export const getLotComments = (lotId, connectedDatabase) => {
const database = connectedDatabase || sqlite(databasePath, {
readonly: true
});
database.function("userFn_dateIntegerToString", dateIntegerToString);
database.function("userFn_timeIntegerToString", timeIntegerToString);
const lotComments = database
.prepare("select lotCommentId," +
" lotCommentDate, userFn_dateIntegerToString(lotCommentDate) as lotCommentDateString," +
" lotCommentTime, userFn_timeIntegerToString(lotCommentTime) as lotCommentTimeString," +
" lotComment" +
" from LotComments" +
" where recordDelete_timeMillis is null" +
" and lotId = ?" +
" order by lotCommentDate desc, lotCommentTime desc, lotCommentId desc")
.all(lotId);
if (!connectedDatabase) {
database.close();
}
return lotComments;
};
export default getLotComments;

View File

@ -0,0 +1,38 @@
import { dateIntegerToString, timeIntegerToString } from "@cityssm/expressjs-server-js/dateTimeFns.js";
import sqlite from "better-sqlite3";
import {
lotOccupancyDB as databasePath
} from "../../data/databasePaths.js";
import type * as recordTypes from "../../types/recordTypes";
export const getLotComments = (lotId: number | string, connectedDatabase ? : sqlite.Database): recordTypes.LotComment[] => {
const database = connectedDatabase || sqlite(databasePath, {
readonly: true
});
database.function("userFn_dateIntegerToString", dateIntegerToString);
database.function("userFn_timeIntegerToString", timeIntegerToString);
const lotComments = database
.prepare("select lotCommentId," +
" lotCommentDate, userFn_dateIntegerToString(lotCommentDate) as lotCommentDateString," +
" lotCommentTime, userFn_timeIntegerToString(lotCommentTime) as lotCommentTimeString," +
" lotComment" +
" from LotComments" +
" where recordDelete_timeMillis is null" +
" and lotId = ?" +
" order by lotCommentDate desc, lotCommentTime desc, lotCommentId desc")
.all(lotId);
if (!connectedDatabase) {
database.close();
}
return lotComments;
};
export default getLotComments;

View File

@ -1,12 +1,14 @@
import sqlite from "better-sqlite3";
import type * as recordTypes from "../../types/recordTypes"; import type * as recordTypes from "../../types/recordTypes";
interface GetLotOccupanciesFilters { interface GetLotOccupanciesFilters {
lotId?: number | string; lotId?: number | string;
} }
interface GetLotOccupanciesOptions { interface GetLotOccupanciesOptions {
limit: number; limit: -1 | number;
offset: number; offset: number;
includeOccupants: boolean;
} }
export declare const getLotOccupancies: (filters: GetLotOccupanciesFilters, options?: GetLotOccupanciesOptions) => { export declare const getLotOccupancies: (filters: GetLotOccupanciesFilters, options: GetLotOccupanciesOptions, connectedDatabase?: sqlite.Database) => {
count: number; count: number;
lotOccupancies: recordTypes.LotOccupancy[]; lotOccupancies: recordTypes.LotOccupancy[];
}; };

View File

@ -1,9 +1,12 @@
import { dateIntegerToString } from "@cityssm/expressjs-server-js/dateTimeFns.js";
import sqlite from "better-sqlite3"; import sqlite from "better-sqlite3";
import { lotOccupancyDB as databasePath } from "../../data/databasePaths.js"; import { lotOccupancyDB as databasePath } from "../../data/databasePaths.js";
export const getLotOccupancies = (filters, options) => { import { getLotOccupancyOccupants } from "./getLotOccupancyOccupants.js";
const database = sqlite(databasePath, { export const getLotOccupancies = (filters, options, connectedDatabase) => {
const database = connectedDatabase || sqlite(databasePath, {
readonly: true readonly: true
}); });
database.function("userFn_dateIntegerToString", dateIntegerToString);
let sqlWhereClause = " where o.recordDelete_timeMillis is null"; let sqlWhereClause = " where o.recordDelete_timeMillis is null";
const sqlParameters = []; const sqlParameters = [];
if (filters.lotId) { if (filters.lotId) {
@ -21,21 +24,26 @@ export const getLotOccupancies = (filters, options) => {
.prepare("select o.lotOccupancyId," + .prepare("select o.lotOccupancyId," +
" o.occupancyTypeId, t.occupancyType," + " o.occupancyTypeId, t.occupancyType," +
" o.lotId, l.lotName," + " o.lotId, l.lotName," +
" o.occupantId, n.occupantName," + " o.occupancyStartDate, userFn_dateIntegerToString(o.occupancyStartDate) as occupancyStartDateString," +
" o.occupancyStartDate," + " o.occupancyEndDate, userFn_dateIntegerToString(o.occupancyEndDate) as occupancyEndDateString" +
" o.occupancyEndDate" +
" from LotOccupancies o" + " from LotOccupancies o" +
" left join OccupancyTypes t on o.occupancyTypeId = t.occupancyTypeId" + " left join OccupancyTypes t on o.occupancyTypeId = t.occupancyTypeId" +
" left join Lots l on o.lotId = l.lotId" + " left join Lots l on o.lotId = l.lotId" +
" left join Occupants n on o.occupantId = n.occupantId" +
sqlWhereClause + sqlWhereClause +
" order by o.occupancyStartDate, o.occupancyEndDate, l.lotName, o.lotId" + " order by o.occupancyStartDate desc, ifnull(o.occupancyEndDate, 99999999) desc, l.lotName, o.lotId" +
(options ? (options.limit !== -1 ?
" limit " + options.limit + " offset " + options.offset : " limit " + options.limit + " offset " + options.offset :
"")) ""))
.all(sqlParameters); .all(sqlParameters);
if (options.includeOccupants) {
for (const lotOccupancy of lotOccupancies) {
lotOccupancy.lotOccupancyOccupants = getLotOccupancyOccupants(lotOccupancy.lotOccupancyId, database);
} }
}
}
if (!connectedDatabase) {
database.close(); database.close();
}
return { return {
count, count,
lotOccupancies lotOccupancies

View File

@ -1,9 +1,11 @@
import { dateIntegerToString } from "@cityssm/expressjs-server-js/dateTimeFns.js";
import sqlite from "better-sqlite3"; import sqlite from "better-sqlite3";
import { import {
lotOccupancyDB as databasePath lotOccupancyDB as databasePath
} from "../../data/databasePaths.js"; } from "../../data/databasePaths.js";
import type * as recordTypes from "../../types/recordTypes"; import type * as recordTypes from "../../types/recordTypes";
import { getLotOccupancyOccupants } from "./getLotOccupancyOccupants.js";
interface GetLotOccupanciesFilters { interface GetLotOccupanciesFilters {
@ -12,20 +14,25 @@ interface GetLotOccupanciesFilters {
interface GetLotOccupanciesOptions { interface GetLotOccupanciesOptions {
limit: number; limit: -1 | number;
offset: number; offset: number;
includeOccupants: boolean;
} }
export const getLotOccupancies = (filters: GetLotOccupanciesFilters, options ? : GetLotOccupanciesOptions): { export const getLotOccupancies = (filters: GetLotOccupanciesFilters,
options: GetLotOccupanciesOptions,
connectedDatabase ? : sqlite.Database): {
count: number; count: number;
lotOccupancies: recordTypes.LotOccupancy[]; lotOccupancies: recordTypes.LotOccupancy[];
} => { } => {
const database = sqlite(databasePath, { const database = connectedDatabase || sqlite(databasePath, {
readonly: true readonly: true
}); });
database.function("userFn_dateIntegerToString", dateIntegerToString);
let sqlWhereClause = " where o.recordDelete_timeMillis is null"; let sqlWhereClause = " where o.recordDelete_timeMillis is null";
const sqlParameters = []; const sqlParameters = [];
@ -48,22 +55,28 @@ export const getLotOccupancies = (filters: GetLotOccupanciesFilters, options ? :
.prepare("select o.lotOccupancyId," + .prepare("select o.lotOccupancyId," +
" o.occupancyTypeId, t.occupancyType," + " o.occupancyTypeId, t.occupancyType," +
" o.lotId, l.lotName," + " o.lotId, l.lotName," +
" o.occupantId, n.occupantName," + " o.occupancyStartDate, userFn_dateIntegerToString(o.occupancyStartDate) as occupancyStartDateString," +
" o.occupancyStartDate," + " o.occupancyEndDate, userFn_dateIntegerToString(o.occupancyEndDate) as occupancyEndDateString" +
" o.occupancyEndDate" +
" from LotOccupancies o" + " from LotOccupancies o" +
" left join OccupancyTypes t on o.occupancyTypeId = t.occupancyTypeId" + " left join OccupancyTypes t on o.occupancyTypeId = t.occupancyTypeId" +
" left join Lots l on o.lotId = l.lotId" + " left join Lots l on o.lotId = l.lotId" +
" left join Occupants n on o.occupantId = n.occupantId" +
sqlWhereClause + sqlWhereClause +
" order by o.occupancyStartDate, o.occupancyEndDate, l.lotName, o.lotId" + " order by o.occupancyStartDate desc, ifnull(o.occupancyEndDate, 99999999) desc, l.lotName, o.lotId" +
(options ? (options.limit !== -1 ?
" limit " + options.limit + " offset " + options.offset : " limit " + options.limit + " offset " + options.offset :
"")) ""))
.all(sqlParameters); .all(sqlParameters);
if (options.includeOccupants) {
for (const lotOccupancy of lotOccupancies) {
lotOccupancy.lotOccupancyOccupants = getLotOccupancyOccupants(lotOccupancy.lotOccupancyId, database);
}
}
} }
if (!connectedDatabase) {
database.close(); database.close();
}
return { return {
count, count,

View File

@ -0,0 +1,4 @@
import sqlite from "better-sqlite3";
import type * as recordTypes from "../../types/recordTypes";
export declare const getLotOccupancyOccupants: (lotOccupancyId: number, connectedDatabase?: sqlite.Database) => recordTypes.LotOccupancyOccupant[];
export default getLotOccupancyOccupants;

View File

@ -0,0 +1,25 @@
import sqlite from "better-sqlite3";
import { lotOccupancyDB as databasePath } from "../../data/databasePaths.js";
export const getLotOccupancyOccupants = (lotOccupancyId, connectedDatabase) => {
const database = connectedDatabase || sqlite(databasePath, {
readonly: true
});
const lotOccupancyOccupants = database
.prepare("select o.lotOccupancyId, o.lotOccupantIndex," +
" o.occupantId," +
" n.occupantName, n.occupantAddress1, n.occupantAddress2," +
" n.occupantCity, n.occupantProvince, n.occupantPostalCode, n.occupantPhoneNumber," +
" o.lotOccupantTypeId, t.lotOccupantType" +
" from LotOccupancyOccupants o" +
" left join Occupants n on o.occupantId = n.occupantId" +
" left join LotOccupantTypes t on o.lotOccupantTypeId = t.lotOccupantTypeId" +
" where o.recordDelete_timeMillis is null" +
" and o.lotOccupancyId = ?" +
" order by t.orderNumber, t.lotOccupantType, n.occupantName, o.lotOccupantIndex")
.all(lotOccupancyId);
if (!connectedDatabase) {
database.close();
}
return lotOccupancyOccupants;
};
export default getLotOccupancyOccupants;

View File

@ -0,0 +1,38 @@
import sqlite from "better-sqlite3";
import {
lotOccupancyDB as databasePath
} from "../../data/databasePaths.js";
import type * as recordTypes from "../../types/recordTypes";
export const getLotOccupancyOccupants = (lotOccupancyId: number,
connectedDatabase ? : sqlite.Database): recordTypes.LotOccupancyOccupant[] => {
const database = connectedDatabase || sqlite(databasePath, {
readonly: true
});
const lotOccupancyOccupants: recordTypes.LotOccupancyOccupant[] = database
.prepare("select o.lotOccupancyId, o.lotOccupantIndex," +
" o.occupantId," +
" n.occupantName, n.occupantAddress1, n.occupantAddress2," +
" n.occupantCity, n.occupantProvince, n.occupantPostalCode, n.occupantPhoneNumber," +
" o.lotOccupantTypeId, t.lotOccupantType" +
" from LotOccupancyOccupants o" +
" left join Occupants n on o.occupantId = n.occupantId" +
" left join LotOccupantTypes t on o.lotOccupantTypeId = t.lotOccupantTypeId" +
" where o.recordDelete_timeMillis is null" +
" and o.lotOccupancyId = ?" +
" order by t.orderNumber, t.lotOccupantType, n.occupantName, o.lotOccupantIndex")
.all(lotOccupancyId);
if (!connectedDatabase) {
database.close();
}
return lotOccupancyOccupants;
};
export default getLotOccupancyOccupants;

View File

@ -53,7 +53,7 @@ export const getLots = (filters, options) => {
" group by lotId" + " group by lotId" +
") o on l.lotId = o.lotId") + ") o on l.lotId = o.lotId") +
sqlWhereClause + sqlWhereClause +
" order by l.lotName" + " order by l.lotName, l.lotId" +
(options ? (options ?
" limit " + options.limit + " offset " + options.offset : " limit " + options.limit + " offset " + options.offset :
"")) ""))

View File

@ -88,7 +88,7 @@ export const getLots = (filters ? : GetLotsFilters, options ? : GetLotsOptions):
" group by lotId" + " group by lotId" +
") o on l.lotId = o.lotId") + ") o on l.lotId = o.lotId") +
sqlWhereClause + sqlWhereClause +
" order by l.lotName" + " order by l.lotName, l.lotId" +
(options ? (options ?
" limit " + options.limit + " offset " + options.offset : " limit " + options.limit + " offset " + options.offset :
"")) ""))

188
package-lock.json generated
View File

@ -24,7 +24,7 @@
"ejs": "^3.1.8", "ejs": "^3.1.8",
"exit-hook": "^3.0.0", "exit-hook": "^3.0.0",
"express": "^4.18.1", "express": "^4.18.1",
"express-rate-limit": "^6.4.0", "express-rate-limit": "^6.5.1",
"express-session": "^1.17.3", "express-session": "^1.17.3",
"http-errors": "^2.0.0", "http-errors": "^2.0.0",
"leaflet": "^1.8.0", "leaflet": "^1.8.0",
@ -53,8 +53,8 @@
"@types/node-windows": "^0.1.2", "@types/node-windows": "^0.1.2",
"@types/papaparse": "^5.3.2", "@types/papaparse": "^5.3.2",
"@types/session-file-store": "^1.2.2", "@types/session-file-store": "^1.2.2",
"@typescript-eslint/eslint-plugin": "^5.30.7", "@typescript-eslint/eslint-plugin": "^5.31.0",
"@typescript-eslint/parser": "^5.30.7", "@typescript-eslint/parser": "^5.31.0",
"bulma": "^0.9.4", "bulma": "^0.9.4",
"eslint": "^8.20.0", "eslint": "^8.20.0",
"eslint-plugin-import": "^2.26.0", "eslint-plugin-import": "^2.26.0",
@ -67,7 +67,7 @@
"gulp-sass": "^5.1.0", "gulp-sass": "^5.1.0",
"nodemon": "^2.0.19", "nodemon": "^2.0.19",
"papaparse": "^5.3.2", "papaparse": "^5.3.2",
"sass": "^1.53.0" "sass": "^1.54.0"
}, },
"engines": { "engines": {
"node": "^12.20.0 || ^14.13.1 || >=16.0.0" "node": "^12.20.0 || ^14.13.1 || >=16.0.0"
@ -1137,14 +1137,14 @@
} }
}, },
"node_modules/@typescript-eslint/eslint-plugin": { "node_modules/@typescript-eslint/eslint-plugin": {
"version": "5.30.7", "version": "5.31.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.30.7.tgz", "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.31.0.tgz",
"integrity": "sha512-l4L6Do+tfeM2OK0GJsU7TUcM/1oN/N25xHm3Jb4z3OiDU4Lj8dIuxX9LpVMS9riSXQs42D1ieX7b85/r16H9Fw==", "integrity": "sha512-VKW4JPHzG5yhYQrQ1AzXgVgX8ZAJEvCz0QI6mLRX4tf7rnFfh5D8SKm0Pq6w5PyNfAWJk6sv313+nEt3ohWMBQ==",
"dev": true, "dev": true,
"dependencies": { "dependencies": {
"@typescript-eslint/scope-manager": "5.30.7", "@typescript-eslint/scope-manager": "5.31.0",
"@typescript-eslint/type-utils": "5.30.7", "@typescript-eslint/type-utils": "5.31.0",
"@typescript-eslint/utils": "5.30.7", "@typescript-eslint/utils": "5.31.0",
"debug": "^4.3.4", "debug": "^4.3.4",
"functional-red-black-tree": "^1.0.1", "functional-red-black-tree": "^1.0.1",
"ignore": "^5.2.0", "ignore": "^5.2.0",
@ -1170,14 +1170,14 @@
} }
}, },
"node_modules/@typescript-eslint/parser": { "node_modules/@typescript-eslint/parser": {
"version": "5.30.7", "version": "5.31.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.30.7.tgz", "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.31.0.tgz",
"integrity": "sha512-Rg5xwznHWWSy7v2o0cdho6n+xLhK2gntImp0rJroVVFkcYFYQ8C8UJTSuTw/3CnExBmPjycjmUJkxVmjXsld6A==", "integrity": "sha512-UStjQiZ9OFTFReTrN+iGrC6O/ko9LVDhreEK5S3edmXgR396JGq7CoX2TWIptqt/ESzU2iRKXAHfSF2WJFcWHw==",
"dev": true, "dev": true,
"dependencies": { "dependencies": {
"@typescript-eslint/scope-manager": "5.30.7", "@typescript-eslint/scope-manager": "5.31.0",
"@typescript-eslint/types": "5.30.7", "@typescript-eslint/types": "5.31.0",
"@typescript-eslint/typescript-estree": "5.30.7", "@typescript-eslint/typescript-estree": "5.31.0",
"debug": "^4.3.4" "debug": "^4.3.4"
}, },
"engines": { "engines": {
@ -1197,13 +1197,13 @@
} }
}, },
"node_modules/@typescript-eslint/scope-manager": { "node_modules/@typescript-eslint/scope-manager": {
"version": "5.30.7", "version": "5.31.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.30.7.tgz", "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.31.0.tgz",
"integrity": "sha512-7BM1bwvdF1UUvt+b9smhqdc/eniOnCKxQT/kj3oXtj3LqnTWCAM0qHRHfyzCzhEfWX0zrW7KqXXeE4DlchZBKw==", "integrity": "sha512-8jfEzBYDBG88rcXFxajdVavGxb5/XKXyvWgvD8Qix3EEJLCFIdVloJw+r9ww0wbyNLOTYyBsR+4ALNGdlalLLg==",
"dev": true, "dev": true,
"dependencies": { "dependencies": {
"@typescript-eslint/types": "5.30.7", "@typescript-eslint/types": "5.31.0",
"@typescript-eslint/visitor-keys": "5.30.7" "@typescript-eslint/visitor-keys": "5.31.0"
}, },
"engines": { "engines": {
"node": "^12.22.0 || ^14.17.0 || >=16.0.0" "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
@ -1214,12 +1214,12 @@
} }
}, },
"node_modules/@typescript-eslint/type-utils": { "node_modules/@typescript-eslint/type-utils": {
"version": "5.30.7", "version": "5.31.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-5.30.7.tgz", "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-5.31.0.tgz",
"integrity": "sha512-nD5qAE2aJX/YLyKMvOU5jvJyku4QN5XBVsoTynFrjQZaDgDV6i7QHFiYCx10wvn7hFvfuqIRNBtsgaLe0DbWhw==", "integrity": "sha512-7ZYqFbvEvYXFn9ax02GsPcEOmuWNg+14HIf4q+oUuLnMbpJ6eHAivCg7tZMVwzrIuzX3QCeAOqKoyMZCv5xe+w==",
"dev": true, "dev": true,
"dependencies": { "dependencies": {
"@typescript-eslint/utils": "5.30.7", "@typescript-eslint/utils": "5.31.0",
"debug": "^4.3.4", "debug": "^4.3.4",
"tsutils": "^3.21.0" "tsutils": "^3.21.0"
}, },
@ -1240,9 +1240,9 @@
} }
}, },
"node_modules/@typescript-eslint/types": { "node_modules/@typescript-eslint/types": {
"version": "5.30.7", "version": "5.31.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.30.7.tgz", "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.31.0.tgz",
"integrity": "sha512-ocVkETUs82+U+HowkovV6uxf1AnVRKCmDRNUBUUo46/5SQv1owC/EBFkiu4MOHeZqhKz2ktZ3kvJJ1uFqQ8QPg==", "integrity": "sha512-/f/rMaEseux+I4wmR6mfpM2wvtNZb1p9hAV77hWfuKc3pmaANp5dLAZSiE3/8oXTYTt3uV9KW5yZKJsMievp6g==",
"dev": true, "dev": true,
"engines": { "engines": {
"node": "^12.22.0 || ^14.17.0 || >=16.0.0" "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
@ -1253,13 +1253,13 @@
} }
}, },
"node_modules/@typescript-eslint/typescript-estree": { "node_modules/@typescript-eslint/typescript-estree": {
"version": "5.30.7", "version": "5.31.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.30.7.tgz", "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.31.0.tgz",
"integrity": "sha512-tNslqXI1ZdmXXrHER83TJ8OTYl4epUzJC0aj2i4DMDT4iU+UqLT3EJeGQvJ17BMbm31x5scSwo3hPM0nqQ1AEA==", "integrity": "sha512-3S625TMcARX71wBc2qubHaoUwMEn+l9TCsaIzYI/ET31Xm2c9YQ+zhGgpydjorwQO9pLfR/6peTzS/0G3J/hDw==",
"dev": true, "dev": true,
"dependencies": { "dependencies": {
"@typescript-eslint/types": "5.30.7", "@typescript-eslint/types": "5.31.0",
"@typescript-eslint/visitor-keys": "5.30.7", "@typescript-eslint/visitor-keys": "5.31.0",
"debug": "^4.3.4", "debug": "^4.3.4",
"globby": "^11.1.0", "globby": "^11.1.0",
"is-glob": "^4.0.3", "is-glob": "^4.0.3",
@ -1280,15 +1280,15 @@
} }
}, },
"node_modules/@typescript-eslint/utils": { "node_modules/@typescript-eslint/utils": {
"version": "5.30.7", "version": "5.31.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.30.7.tgz", "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.31.0.tgz",
"integrity": "sha512-Z3pHdbFw+ftZiGUnm1GZhkJgVqsDL5CYW2yj+TB2mfXDFOMqtbzQi2dNJIyPqPbx9mv2kUxS1gU+r2gKlKi1rQ==", "integrity": "sha512-kcVPdQS6VIpVTQ7QnGNKMFtdJdvnStkqS5LeALr4rcwx11G6OWb2HB17NMPnlRHvaZP38hL9iK8DdE9Fne7NYg==",
"dev": true, "dev": true,
"dependencies": { "dependencies": {
"@types/json-schema": "^7.0.9", "@types/json-schema": "^7.0.9",
"@typescript-eslint/scope-manager": "5.30.7", "@typescript-eslint/scope-manager": "5.31.0",
"@typescript-eslint/types": "5.30.7", "@typescript-eslint/types": "5.31.0",
"@typescript-eslint/typescript-estree": "5.30.7", "@typescript-eslint/typescript-estree": "5.31.0",
"eslint-scope": "^5.1.1", "eslint-scope": "^5.1.1",
"eslint-utils": "^3.0.0" "eslint-utils": "^3.0.0"
}, },
@ -1304,12 +1304,12 @@
} }
}, },
"node_modules/@typescript-eslint/visitor-keys": { "node_modules/@typescript-eslint/visitor-keys": {
"version": "5.30.7", "version": "5.31.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.30.7.tgz", "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.31.0.tgz",
"integrity": "sha512-KrRXf8nnjvcpxDFOKej4xkD7657+PClJs5cJVSG7NNoCNnjEdc46juNAQt7AyuWctuCgs6mVRc1xGctEqrjxWw==", "integrity": "sha512-ZK0jVxSjS4gnPirpVjXHz7mgdOsZUHzNYSfTw2yPa3agfbt9YfqaBiBZFSSxeBWnpWkzCxTfUpnzA3Vily/CSg==",
"dev": true, "dev": true,
"dependencies": { "dependencies": {
"@typescript-eslint/types": "5.30.7", "@typescript-eslint/types": "5.31.0",
"eslint-visitor-keys": "^3.3.0" "eslint-visitor-keys": "^3.3.0"
}, },
"engines": { "engines": {
@ -3832,9 +3832,9 @@
} }
}, },
"node_modules/express-rate-limit": { "node_modules/express-rate-limit": {
"version": "6.4.0", "version": "6.5.1",
"resolved": "https://registry.npmjs.org/express-rate-limit/-/express-rate-limit-6.4.0.tgz", "resolved": "https://registry.npmjs.org/express-rate-limit/-/express-rate-limit-6.5.1.tgz",
"integrity": "sha512-lxQRZI4gi3qAWTf0/Uqsyugsz57h8bd7QyllXBgJvd6DJKokzW7C5DTaNvwzvAQzwHGFaItybfYGhC8gpu0V2A==", "integrity": "sha512-pxO6ioBLd3i8IHL+RmJtL4noYzte5fugoMdaDabtU4hcg53+x0QkTwfPtM7vWD0YUaXQgNj9NRdzmps+CHEHlA==",
"engines": { "engines": {
"node": ">= 12.9.0" "node": ">= 12.9.0"
}, },
@ -8508,9 +8508,9 @@
"integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg=="
}, },
"node_modules/sass": { "node_modules/sass": {
"version": "1.53.0", "version": "1.54.0",
"resolved": "https://registry.npmjs.org/sass/-/sass-1.53.0.tgz", "resolved": "https://registry.npmjs.org/sass/-/sass-1.54.0.tgz",
"integrity": "sha512-zb/oMirbKhUgRQ0/GFz8TSAwRq2IlR29vOUJZOx0l8sV+CkHUfHa4u5nqrG+1VceZp7Jfj59SVW9ogdhTvJDcQ==", "integrity": "sha512-C4zp79GCXZfK0yoHZg+GxF818/aclhp9F48XBu/+bm9vXEVAYov9iU3FBVRMq3Hx3OA4jfKL+p2K9180mEh0xQ==",
"dev": true, "dev": true,
"dependencies": { "dependencies": {
"chokidar": ">=3.0.0 <4.0.0", "chokidar": ">=3.0.0 <4.0.0",
@ -11521,14 +11521,14 @@
} }
}, },
"@typescript-eslint/eslint-plugin": { "@typescript-eslint/eslint-plugin": {
"version": "5.30.7", "version": "5.31.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.30.7.tgz", "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.31.0.tgz",
"integrity": "sha512-l4L6Do+tfeM2OK0GJsU7TUcM/1oN/N25xHm3Jb4z3OiDU4Lj8dIuxX9LpVMS9riSXQs42D1ieX7b85/r16H9Fw==", "integrity": "sha512-VKW4JPHzG5yhYQrQ1AzXgVgX8ZAJEvCz0QI6mLRX4tf7rnFfh5D8SKm0Pq6w5PyNfAWJk6sv313+nEt3ohWMBQ==",
"dev": true, "dev": true,
"requires": { "requires": {
"@typescript-eslint/scope-manager": "5.30.7", "@typescript-eslint/scope-manager": "5.31.0",
"@typescript-eslint/type-utils": "5.30.7", "@typescript-eslint/type-utils": "5.31.0",
"@typescript-eslint/utils": "5.30.7", "@typescript-eslint/utils": "5.31.0",
"debug": "^4.3.4", "debug": "^4.3.4",
"functional-red-black-tree": "^1.0.1", "functional-red-black-tree": "^1.0.1",
"ignore": "^5.2.0", "ignore": "^5.2.0",
@ -11538,52 +11538,52 @@
} }
}, },
"@typescript-eslint/parser": { "@typescript-eslint/parser": {
"version": "5.30.7", "version": "5.31.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.30.7.tgz", "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.31.0.tgz",
"integrity": "sha512-Rg5xwznHWWSy7v2o0cdho6n+xLhK2gntImp0rJroVVFkcYFYQ8C8UJTSuTw/3CnExBmPjycjmUJkxVmjXsld6A==", "integrity": "sha512-UStjQiZ9OFTFReTrN+iGrC6O/ko9LVDhreEK5S3edmXgR396JGq7CoX2TWIptqt/ESzU2iRKXAHfSF2WJFcWHw==",
"dev": true, "dev": true,
"requires": { "requires": {
"@typescript-eslint/scope-manager": "5.30.7", "@typescript-eslint/scope-manager": "5.31.0",
"@typescript-eslint/types": "5.30.7", "@typescript-eslint/types": "5.31.0",
"@typescript-eslint/typescript-estree": "5.30.7", "@typescript-eslint/typescript-estree": "5.31.0",
"debug": "^4.3.4" "debug": "^4.3.4"
} }
}, },
"@typescript-eslint/scope-manager": { "@typescript-eslint/scope-manager": {
"version": "5.30.7", "version": "5.31.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.30.7.tgz", "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.31.0.tgz",
"integrity": "sha512-7BM1bwvdF1UUvt+b9smhqdc/eniOnCKxQT/kj3oXtj3LqnTWCAM0qHRHfyzCzhEfWX0zrW7KqXXeE4DlchZBKw==", "integrity": "sha512-8jfEzBYDBG88rcXFxajdVavGxb5/XKXyvWgvD8Qix3EEJLCFIdVloJw+r9ww0wbyNLOTYyBsR+4ALNGdlalLLg==",
"dev": true, "dev": true,
"requires": { "requires": {
"@typescript-eslint/types": "5.30.7", "@typescript-eslint/types": "5.31.0",
"@typescript-eslint/visitor-keys": "5.30.7" "@typescript-eslint/visitor-keys": "5.31.0"
} }
}, },
"@typescript-eslint/type-utils": { "@typescript-eslint/type-utils": {
"version": "5.30.7", "version": "5.31.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-5.30.7.tgz", "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-5.31.0.tgz",
"integrity": "sha512-nD5qAE2aJX/YLyKMvOU5jvJyku4QN5XBVsoTynFrjQZaDgDV6i7QHFiYCx10wvn7hFvfuqIRNBtsgaLe0DbWhw==", "integrity": "sha512-7ZYqFbvEvYXFn9ax02GsPcEOmuWNg+14HIf4q+oUuLnMbpJ6eHAivCg7tZMVwzrIuzX3QCeAOqKoyMZCv5xe+w==",
"dev": true, "dev": true,
"requires": { "requires": {
"@typescript-eslint/utils": "5.30.7", "@typescript-eslint/utils": "5.31.0",
"debug": "^4.3.4", "debug": "^4.3.4",
"tsutils": "^3.21.0" "tsutils": "^3.21.0"
} }
}, },
"@typescript-eslint/types": { "@typescript-eslint/types": {
"version": "5.30.7", "version": "5.31.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.30.7.tgz", "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.31.0.tgz",
"integrity": "sha512-ocVkETUs82+U+HowkovV6uxf1AnVRKCmDRNUBUUo46/5SQv1owC/EBFkiu4MOHeZqhKz2ktZ3kvJJ1uFqQ8QPg==", "integrity": "sha512-/f/rMaEseux+I4wmR6mfpM2wvtNZb1p9hAV77hWfuKc3pmaANp5dLAZSiE3/8oXTYTt3uV9KW5yZKJsMievp6g==",
"dev": true "dev": true
}, },
"@typescript-eslint/typescript-estree": { "@typescript-eslint/typescript-estree": {
"version": "5.30.7", "version": "5.31.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.30.7.tgz", "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.31.0.tgz",
"integrity": "sha512-tNslqXI1ZdmXXrHER83TJ8OTYl4epUzJC0aj2i4DMDT4iU+UqLT3EJeGQvJ17BMbm31x5scSwo3hPM0nqQ1AEA==", "integrity": "sha512-3S625TMcARX71wBc2qubHaoUwMEn+l9TCsaIzYI/ET31Xm2c9YQ+zhGgpydjorwQO9pLfR/6peTzS/0G3J/hDw==",
"dev": true, "dev": true,
"requires": { "requires": {
"@typescript-eslint/types": "5.30.7", "@typescript-eslint/types": "5.31.0",
"@typescript-eslint/visitor-keys": "5.30.7", "@typescript-eslint/visitor-keys": "5.31.0",
"debug": "^4.3.4", "debug": "^4.3.4",
"globby": "^11.1.0", "globby": "^11.1.0",
"is-glob": "^4.0.3", "is-glob": "^4.0.3",
@ -11592,26 +11592,26 @@
} }
}, },
"@typescript-eslint/utils": { "@typescript-eslint/utils": {
"version": "5.30.7", "version": "5.31.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.30.7.tgz", "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.31.0.tgz",
"integrity": "sha512-Z3pHdbFw+ftZiGUnm1GZhkJgVqsDL5CYW2yj+TB2mfXDFOMqtbzQi2dNJIyPqPbx9mv2kUxS1gU+r2gKlKi1rQ==", "integrity": "sha512-kcVPdQS6VIpVTQ7QnGNKMFtdJdvnStkqS5LeALr4rcwx11G6OWb2HB17NMPnlRHvaZP38hL9iK8DdE9Fne7NYg==",
"dev": true, "dev": true,
"requires": { "requires": {
"@types/json-schema": "^7.0.9", "@types/json-schema": "^7.0.9",
"@typescript-eslint/scope-manager": "5.30.7", "@typescript-eslint/scope-manager": "5.31.0",
"@typescript-eslint/types": "5.30.7", "@typescript-eslint/types": "5.31.0",
"@typescript-eslint/typescript-estree": "5.30.7", "@typescript-eslint/typescript-estree": "5.31.0",
"eslint-scope": "^5.1.1", "eslint-scope": "^5.1.1",
"eslint-utils": "^3.0.0" "eslint-utils": "^3.0.0"
} }
}, },
"@typescript-eslint/visitor-keys": { "@typescript-eslint/visitor-keys": {
"version": "5.30.7", "version": "5.31.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.30.7.tgz", "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.31.0.tgz",
"integrity": "sha512-KrRXf8nnjvcpxDFOKej4xkD7657+PClJs5cJVSG7NNoCNnjEdc46juNAQt7AyuWctuCgs6mVRc1xGctEqrjxWw==", "integrity": "sha512-ZK0jVxSjS4gnPirpVjXHz7mgdOsZUHzNYSfTw2yPa3agfbt9YfqaBiBZFSSxeBWnpWkzCxTfUpnzA3Vily/CSg==",
"dev": true, "dev": true,
"requires": { "requires": {
"@typescript-eslint/types": "5.30.7", "@typescript-eslint/types": "5.31.0",
"eslint-visitor-keys": "^3.3.0" "eslint-visitor-keys": "^3.3.0"
} }
}, },
@ -13582,9 +13582,9 @@
} }
}, },
"express-rate-limit": { "express-rate-limit": {
"version": "6.4.0", "version": "6.5.1",
"resolved": "https://registry.npmjs.org/express-rate-limit/-/express-rate-limit-6.4.0.tgz", "resolved": "https://registry.npmjs.org/express-rate-limit/-/express-rate-limit-6.5.1.tgz",
"integrity": "sha512-lxQRZI4gi3qAWTf0/Uqsyugsz57h8bd7QyllXBgJvd6DJKokzW7C5DTaNvwzvAQzwHGFaItybfYGhC8gpu0V2A==", "integrity": "sha512-pxO6ioBLd3i8IHL+RmJtL4noYzte5fugoMdaDabtU4hcg53+x0QkTwfPtM7vWD0YUaXQgNj9NRdzmps+CHEHlA==",
"requires": {} "requires": {}
}, },
"express-session": { "express-session": {
@ -17176,9 +17176,9 @@
"integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg=="
}, },
"sass": { "sass": {
"version": "1.53.0", "version": "1.54.0",
"resolved": "https://registry.npmjs.org/sass/-/sass-1.53.0.tgz", "resolved": "https://registry.npmjs.org/sass/-/sass-1.54.0.tgz",
"integrity": "sha512-zb/oMirbKhUgRQ0/GFz8TSAwRq2IlR29vOUJZOx0l8sV+CkHUfHa4u5nqrG+1VceZp7Jfj59SVW9ogdhTvJDcQ==", "integrity": "sha512-C4zp79GCXZfK0yoHZg+GxF818/aclhp9F48XBu/+bm9vXEVAYov9iU3FBVRMq3Hx3OA4jfKL+p2K9180mEh0xQ==",
"dev": true, "dev": true,
"requires": { "requires": {
"chokidar": ">=3.0.0 <4.0.0", "chokidar": ">=3.0.0 <4.0.0",

View File

@ -43,7 +43,7 @@
"ejs": "^3.1.8", "ejs": "^3.1.8",
"exit-hook": "^3.0.0", "exit-hook": "^3.0.0",
"express": "^4.18.1", "express": "^4.18.1",
"express-rate-limit": "^6.4.0", "express-rate-limit": "^6.5.1",
"express-session": "^1.17.3", "express-session": "^1.17.3",
"http-errors": "^2.0.0", "http-errors": "^2.0.0",
"leaflet": "^1.8.0", "leaflet": "^1.8.0",
@ -72,8 +72,8 @@
"@types/node-windows": "^0.1.2", "@types/node-windows": "^0.1.2",
"@types/papaparse": "^5.3.2", "@types/papaparse": "^5.3.2",
"@types/session-file-store": "^1.2.2", "@types/session-file-store": "^1.2.2",
"@typescript-eslint/eslint-plugin": "^5.30.7", "@typescript-eslint/eslint-plugin": "^5.31.0",
"@typescript-eslint/parser": "^5.30.7", "@typescript-eslint/parser": "^5.31.0",
"bulma": "^0.9.4", "bulma": "^0.9.4",
"eslint": "^8.20.0", "eslint": "^8.20.0",
"eslint-plugin-import": "^2.26.0", "eslint-plugin-import": "^2.26.0",
@ -86,6 +86,6 @@
"gulp-sass": "^5.1.0", "gulp-sass": "^5.1.0",
"nodemon": "^2.0.19", "nodemon": "^2.0.19",
"papaparse": "^5.3.2", "papaparse": "^5.3.2",
"sass": "^1.53.0" "sass": "^1.54.0"
} }
} }

View File

@ -90,6 +90,7 @@ fieldset:enabled .is-hidden-enabled {
* SVG * SVG
*/ */
.image svg { .image svg {
display: block; display: block;
height: auto; height: auto;
@ -111,3 +112,13 @@ fieldset:enabled .is-hidden-enabled {
user-select: none; user-select: none;
} }
} }
/*
* "Readonly" selects
*/
.select option:disabled {
display: none;
}

1
public-typescript/lotEdit.d.ts vendored 100644
View File

@ -0,0 +1 @@
export {};

View File

@ -0,0 +1,33 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
(() => {
const urlPrefix = document.querySelector("main").dataset.urlPrefix;
const lotId = document.querySelector("#lot--lotId").value;
const isCreate = (lotId === "");
const formElement = document.querySelector("#form--lot");
const updateLot = (formEvent) => {
formEvent.preventDefault();
cityssm.postJSON(urlPrefix + "/lots/" + (isCreate ? "doCreateLot" : "doUpdateLot"), formElement, (responseJSON) => {
if (responseJSON.success) {
if (isCreate) {
window.location.href = urlPrefix + "/lots/" + responseJSON.lotId + "/edit";
}
else {
bulmaJS.alert({
message: exports.aliases.lot + " Updated Successfully",
contextualColorName: "success"
});
}
}
else {
bulmaJS.alert({
title: "Error Updating " + exports.aliases.lot,
message: responseJSON.errorMessage,
contextualColorName: "danger"
});
}
});
};
formElement.addEventListener("submit", updateLot);
exports.los.initializeUnlockFieldButtons(formElement);
})();

View File

@ -0,0 +1,53 @@
/* eslint-disable unicorn/prefer-module */
import type * as globalTypes from "../types/globalTypes";
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 lotId = (document.querySelector("#lot--lotId") as HTMLInputElement).value;
const isCreate = (lotId === "");
const formElement = document.querySelector("#form--lot") as HTMLFormElement;
const updateLot = (formEvent: SubmitEvent) => {
formEvent.preventDefault();
cityssm.postJSON(urlPrefix + "/lots/" + (isCreate ? "doCreateLot" : "doUpdateLot"),
formElement,
(responseJSON: {
success: boolean;lotId ? : number;errorMessage ? : string
}) => {
if (responseJSON.success) {
if (isCreate) {
window.location.href = urlPrefix + "/lots/" + responseJSON.lotId + "/edit";
} else {
bulmaJS.alert({
message: exports.aliases.lot + " Updated Successfully",
contextualColorName: "success"
});
}
} else {
bulmaJS.alert({
title: "Error Updating " + exports.aliases.lot,
message: responseJSON.errorMessage,
contextualColorName: "danger"
});
}
});
};
formElement.addEventListener("submit", updateLot);
(exports.los as globalTypes.LOS).initializeUnlockFieldButtons(formElement);
})();

View File

@ -21,8 +21,29 @@ Object.defineProperty(exports, "__esModule", { value: true });
} }
} }
}; };
const unlockField = (clickEvent) => {
const fieldElement = clickEvent.currentTarget.closest(".field");
const inputOrSelectElement = fieldElement.querySelector("input, select");
if (inputOrSelectElement.tagName === "INPUT") {
inputOrSelectElement.disabled = false;
}
else {
const optionElements = inputOrSelectElement.querySelectorAll("option");
for (const optionElement of optionElements) {
optionElement.disabled = false;
}
}
inputOrSelectElement.focus();
};
const initializeUnlockFieldButtons = (containerElement) => {
const unlockFieldButtonElements = containerElement.querySelectorAll(".is-unlock-field-button");
for (const unlockFieldButtonElement of unlockFieldButtonElements) {
unlockFieldButtonElement.addEventListener("click", unlockField);
}
};
const los = { const los = {
highlightMap highlightMap,
initializeUnlockFieldButtons
}; };
exports.los = los; exports.los = los;
})(); })();

View File

@ -41,8 +41,36 @@ import type * as globalTypes from "../types/globalTypes";
} }
}; };
const unlockField = (clickEvent: Event) => {
const fieldElement = (clickEvent.currentTarget as HTMLElement).closest(".field");
const inputOrSelectElement = fieldElement.querySelector("input, select") as HTMLInputElement | HTMLSelectElement;
if (inputOrSelectElement.tagName === "INPUT") {
inputOrSelectElement.disabled = false;
} else {
const optionElements = inputOrSelectElement.querySelectorAll("option");
for (const optionElement of optionElements) {
optionElement.disabled = false;
}
}
inputOrSelectElement.focus();
};
const initializeUnlockFieldButtons = (containerElement: HTMLElement) => {
const unlockFieldButtonElements = containerElement.querySelectorAll(".is-unlock-field-button");
for (const unlockFieldButtonElement of unlockFieldButtonElements) {
unlockFieldButtonElement.addEventListener("click", unlockField);
}
};
const los: globalTypes.LOS = { const los: globalTypes.LOS = {
highlightMap highlightMap,
initializeUnlockFieldButtons
}; };
exports.los = los; exports.los = los;

File diff suppressed because it is too large Load Diff

Before

Width:  |  Height:  |  Size: 472 KiB

After

Width:  |  Height:  |  Size: 425 KiB

View File

@ -0,0 +1 @@
"use strict";Object.defineProperty(exports,"__esModule",{value:!0}),(()=>{const e=document.querySelector("main").dataset.urlPrefix,t=""===document.querySelector("#lot--lotId").value,o=document.querySelector("#form--lot");o.addEventListener("submit",s=>{s.preventDefault(),cityssm.postJSON(e+"/lots/"+(t?"doCreateLot":"doUpdateLot"),o,o=>{o.success?t?window.location.href=e+"/lots/"+o.lotId+"/edit":bulmaJS.alert({message:exports.aliases.lot+" Updated Successfully",contextualColorName:"success"}):bulmaJS.alert({title:"Error Updating "+exports.aliases.lot,message:o.errorMessage,contextualColorName:"danger"})})}),exports.los.initializeUnlockFieldButtons(o)})();

View File

@ -1 +1 @@
"use strict";Object.defineProperty(exports,"__esModule",{value:!0}),(()=>{const l={highlightMap:(l,e,t)=>{let s,o=e;for(;!(s=l.querySelector("#"+o))&&o.includes("-");)o=o.slice(0,Math.max(0,o.lastIndexOf("-"))),console.log(o);if(s){s.style.fill=null,s.classList.add("highlight","is-"+t);const l=s.querySelectorAll("path");for(const e of l)e.style.fill=null}}};exports.los=l})(); "use strict";Object.defineProperty(exports,"__esModule",{value:!0}),(()=>{const e=e=>{const l=e.currentTarget.closest(".field").querySelector("input, select");if("INPUT"===l.tagName)l.disabled=!1;else{const e=l.querySelectorAll("option");for(const l of e)l.disabled=!1}l.focus()},l={highlightMap:(e,l,t)=>{let o,s=l;for(;!(o=e.querySelector("#"+s))&&s.includes("-");)s=s.slice(0,Math.max(0,s.lastIndexOf("-"))),console.log(s);if(o){o.style.fill=null,o.classList.add("highlight","is-"+t);const e=o.querySelectorAll("path");for(const l of e)l.style.fill=null}},initializeUnlockFieldButtons:l=>{const t=l.querySelectorAll(".is-unlock-field-button");for(const l of t)l.addEventListener("click",e)}};exports.los=l})();

File diff suppressed because one or more lines are too long

View File

@ -6,11 +6,15 @@ import handler_view from "../handlers/lots-get/view.js";
import handler_new from "../handlers/lots-get/new.js"; import handler_new from "../handlers/lots-get/new.js";
import handler_edit from "../handlers/lots-get/edit.js"; import handler_edit from "../handlers/lots-get/edit.js";
import handler_print from "../handlers/lots-get/print.js"; import handler_print from "../handlers/lots-get/print.js";
import handler_doCreateLot from "../handlers/lots-post/doCreateLot.js";
import handler_doUpdateLot from "../handlers/lots-post/doUpdateLot.js";
export const router = Router(); export const router = Router();
router.get("/", handler_search); router.get("/", handler_search);
router.post("/doSearchLots", handler_doSearchLots); router.post("/doSearchLots", handler_doSearchLots);
router.get("/new", permissionHandlers.updateGetHandler, handler_new); router.get("/new", permissionHandlers.updateGetHandler, handler_new);
router.get("/:lotId", handler_view); router.get("/:lotId", handler_view);
router.get("/:lotId/edit", permissionHandlers.updateGetHandler, handler_edit); router.get("/:lotId/edit", permissionHandlers.updateGetHandler, handler_edit);
router.post("/doCreateLot", permissionHandlers.updatePostHandler, handler_doCreateLot);
router.post("/doUpdateLot", permissionHandlers.updatePostHandler, handler_doUpdateLot);
router.get("/:lotId/print", handler_print); router.get("/:lotId/print", handler_print);
export default router; export default router;

View File

@ -10,6 +10,9 @@ import handler_new from "../handlers/lots-get/new.js";
import handler_edit from "../handlers/lots-get/edit.js"; import handler_edit from "../handlers/lots-get/edit.js";
import handler_print from "../handlers/lots-get/print.js"; import handler_print from "../handlers/lots-get/print.js";
import handler_doCreateLot from "../handlers/lots-post/doCreateLot.js";
import handler_doUpdateLot from "../handlers/lots-post/doUpdateLot.js";
export const router = Router(); export const router = Router();
@ -46,6 +49,17 @@ router.get("/:lotId/edit",
handler_edit); handler_edit);
router.post("/doCreateLot",
permissionHandlers.updatePostHandler,
handler_doCreateLot);
router.post("/doUpdateLot",
permissionHandlers.updatePostHandler,
handler_doUpdateLot);
router.get("/:lotId/print", router.get("/:lotId/print",
handler_print); handler_print);

View File

@ -165,7 +165,7 @@ function importFromCSV() {
const occupantId = possibleOccupants.length > 0 ? const occupantId = possibleOccupants.length > 0 ?
possibleOccupants[0].occupantId : possibleOccupants[0].occupantId :
addOccupant({ addOccupant({
occupantName: masterRow.CM_PRENEED_ORDER, occupantName: masterRow.CM_PRENEED_OWNER,
occupantAddress1: masterRow.CM_ADDRESS, occupantAddress1: masterRow.CM_ADDRESS,
occupantAddress2: "", occupantAddress2: "",
occupantCity: masterRow.CM_CITY, occupantCity: masterRow.CM_CITY,

View File

@ -292,7 +292,7 @@ function importFromCSV() {
const occupantId = possibleOccupants.length > 0 ? const occupantId = possibleOccupants.length > 0 ?
possibleOccupants[0].occupantId : possibleOccupants[0].occupantId :
addOccupant({ addOccupant({
occupantName: masterRow.CM_PRENEED_ORDER, occupantName: masterRow.CM_PRENEED_OWNER,
occupantAddress1: masterRow.CM_ADDRESS, occupantAddress1: masterRow.CM_ADDRESS,
occupantAddress2: "", occupantAddress2: "",
occupantCity: masterRow.CM_CITY, occupantCity: masterRow.CM_CITY,

View File

@ -1,3 +1,4 @@
export interface LOS { export interface LOS {
highlightMap: (mapContainerElement: HTMLElement, mapKey: string, contextualClass: "success" | "danger") => void; highlightMap: (mapContainerElement: HTMLElement, mapKey: string, contextualClass: "success" | "danger") => void;
initializeUnlockFieldButtons: (containerElement: HTMLElement) => void;
} }

View File

@ -1,3 +1,4 @@
export interface LOS { export interface LOS {
highlightMap: (mapContainerElement: HTMLElement, mapKey: string, contextualClass: "success" | "danger") => void; highlightMap: (mapContainerElement: HTMLElement, mapKey: string, contextualClass: "success" | "danger") => void;
initializeUnlockFieldButtons: (containerElement: HTMLElement) => void;
} }

View File

@ -64,6 +64,16 @@ export interface Lot extends Record {
lotStatus?: LotStatus | string; lotStatus?: LotStatus | string;
lotOccupancyCount?: number; lotOccupancyCount?: number;
lotOccupancies?: LotOccupancy[]; lotOccupancies?: LotOccupancy[];
lotComments?: LotComment[];
}
export interface LotComment extends Record {
lotCommentId?: number;
lotId?: number;
lotCommentDate?: number;
lotCommentDateString?: string;
lotCommentTime?: number;
lotCommentTimeString?: string;
lotComment?: string;
} }
export interface OccupancyType extends Record { export interface OccupancyType extends Record {
occupancyTypeId?: number; occupancyTypeId?: number;
@ -97,13 +107,18 @@ export interface Occupant extends Record {
occupantPostalCode?: string; occupantPostalCode?: string;
occupantPhoneNumber?: string; occupantPhoneNumber?: string;
} }
export interface LotOccupancyOccupant extends Occupant, Record {
lotOccupancyId?: number;
lotOccupantIndex?: number;
lotOccupantTypeId?: number;
lotOccupantType?: string | LotOccupantType;
}
export interface LotOccupancy extends Record { export interface LotOccupancy extends Record {
lotOccupancyId?: number; lotOccupancyId?: number;
occupancyTypeId?: number; occupancyTypeId?: number;
occupancyType?: OccupancyType | string; occupancyType?: OccupancyType | string;
lotId?: number; lotId?: number;
occupantId?: number; lotOccupancyOccupants?: LotOccupancyOccupant[];
occupant?: Occupant;
occupancyStartDate?: number; occupancyStartDate?: number;
occupancyStartDateString?: string; occupancyStartDateString?: string;
occupancyEndDate?: number; occupancyEndDate?: number;

View File

@ -92,6 +92,22 @@ export interface Lot extends Record {
lotOccupancyCount?: number; lotOccupancyCount?: number;
lotOccupancies?: LotOccupancy[]; lotOccupancies?: LotOccupancy[];
lotComments?: LotComment[];
}
export interface LotComment extends Record {
lotCommentId?: number;
lotId?: number;
lotCommentDate?: number;
lotCommentDateString?: string;
lotCommentTime?: number;
lotCommentTimeString?: string;
lotComment?: string;
} }
@ -135,6 +151,15 @@ export interface Occupant extends Record {
} }
export interface LotOccupancyOccupant extends Occupant, Record {
lotOccupancyId?: number;
lotOccupantIndex?: number;
lotOccupantTypeId?: number;
lotOccupantType?: string | LotOccupantType;
}
export interface LotOccupancy extends Record { export interface LotOccupancy extends Record {
lotOccupancyId?: number; lotOccupancyId?: number;
@ -143,8 +168,7 @@ export interface LotOccupancy extends Record {
lotId?: number; lotId?: number;
occupantId?: number; lotOccupancyOccupants?: LotOccupancyOccupant[];
occupant?: Occupant;
occupancyStartDate?: number; occupancyStartDate?: number;
occupancyStartDateString?: string; occupancyStartDateString?: string;

View File

@ -0,0 +1,282 @@
<%- include('_header'); -%>
<nav class="breadcrumb">
<ul>
<li><a href="<%= urlPrefix %>/dashboard">Home</a></li>
<li>
<a href="<%= urlPrefix %>/lots">
<span class="icon is-small"><i class="fas fa-vector-square" aria-hidden="true"></i></span>
<span><%= configFunctions.getProperty("aliases.lots") %></span>
</a>
</li>
<% if (!isCreate) { %>
<li>
<a href="<%= urlPrefix %>/lots/<%= lot.lotId %>">
<%= lot.lotName %>
</a>
</li>
<% } %>
<li class="is-active">
<a href="#" aria-current="page">
<% if (isCreate) { %>
Create a New <%= configFunctions.getProperty("aliases.lot") %>
<% } else { %>
Update <%= configFunctions.getProperty("aliases.lot") %>
<% } %>
</a>
</li>
</ul>
</nav>
<h1 class="title is-1">
<%= lot.lotName %>
</h1>
<form id="form--lot">
<input id="lot--lotId" name="lotId" type="hidden" value="<%= lot.lotId %>" />
<div class="fixed-container is-fixed-bottom-right mx-4 my-4 has-text-right is-hidden-print">
<button class="button is-circle is-primary has-tooltip-left" data-tooltip="Update <%= configFunctions.getProperty("aliases.lot") %>" type="submit">
<i class="fas fa-save" aria-hidden="true"></i>
<span class="sr-only">Update <%= configFunctions.getProperty("aliases.lot") %></span>
</button>
</div>
<div class="columns">
<div class="column">
<div class="field">
<label class="label" for="lot--lotName">
<%= configFunctions.getProperty("aliases.lot") %> Name
</label>
<div class="control">
<input class="input" id="lot--lotName" name="lotName" value="<%= lot.lotName %>" maxlength="100" required />
</div>
</div>
</div>
<div class="column">
<label class="label" for="lot--lotTypeId">
<%= configFunctions.getProperty("aliases.lot") %> Type
</label>
<div class="field has-addons">
<div class="control is-expanded">
<div class="select is-fullwidth">
<select id="lot--lotTypeId" name="lotTypeId" required>
<% if (isCreate) { %>
<option value="">(No Type)</option>
<% } %>
<% let typeIsFound = false; %>
<% for (const lotType of lotTypes) { %>
<%
if (lot.lotTypeId === lotType.lotTypeId) {
typeIsFound = true;
}
%>
<option value="<%= lotType.lotTypeId %>"
<%= (lot.lotTypeId === lotType.lotTypeId ? " selected" : "") %>
<%= (!isCreate && lot.lotTypeId !== lotType.lotTypeId ? " disabled" : "") %>>
<%= lotType.lotType %>
</option>
<% } %>
<% if (lot.lotTypeId && !typeIsFound) { %>
<option value="<%= lot.lotTypeId %>" selected>
<%= lot.lotType %>
</option>
<% } %>
</select>
</div>
</div>
<div class="control">
<button class="button is-unlock-field-button" type="button" title="Unlock Field">
<i class="fas fa-unlock" aria-hidden="true"></i>
</button>
</div>
</div>
</div>
<div class="column">
<label class="label" for="lot--lotTypeId">
<%= configFunctions.getProperty("aliases.lot") %> Status
</label>
<div class="field">
<div class="control">
<div class="select is-fullwidth">
<select id="lot--lotStatusId" name="lotStatusId">
<option value="">(No Status)</option>
<% let statusIsFound = false; %>
<% for (const lotStatus of lotStatuses) { %>
<%
if (lot.lotStatusId === lotStatus.lotStatusId) {
statusIsFound = true;
}
%>
<option value="<%= lotStatus.lotStatusId %>"
<%= (lot.lotStatusId === lotStatus.lotStatusId ? " selected" : "") %>>
<%= lotStatus.lotStatus %>
</option>
<% } %>
<% if (lot.lotStatusId && !statusIsFound) { %>
<option value="<%= lot.lotStatusId %>" selected>
<%= lot.lotStatus %>
</option>
<% } %>
</select>
</div>
</div>
</div>
</div>
</div>
<div class="columns">
<div class="column">
<h2 class="title is-4">Geographic Location</h2>
<div class="field">
<label class="label" for="lot--lotLatitude">Latitude</label>
<div class="control">
<input class="input" id="lot--lotLatitude" name="lotLatitude" type="number" min="-90" max="90" step="0.00000001" value="<%= lot.lotLatitude %>" />
</div>
</div>
<div class="field">
<label class="label" for="lot--lotLongitude">Longitude</label>
<div class="control">
<input class="input" id="lot--lotLongitude" name="lotLongitude" type="number" min="-180" max="180" step="0.00000001" value="<%= lot.lotLongitude %>" />
</div>
</div>
</div>
<div class="column">
<h2 class="title is-4">Image</h2>
<label class="label" for="lot--mapId"><%= configFunctions.getProperty("aliases.map") %></label>
<div class="field has-addons">
<div class="control is-expanded">
<div class="select is-fullwidth">
<select id="lot--mapId" name="mapId">
<option value="" <%= (!isCreate && lot.mapId ? " disabled" : "") %>>
(No <%= configFunctions.getProperty("aliases.map") %> Selected)
</option>
<% let mapIsFound = false; %>
<% for (const map of maps) { %>
<%
if (lot.mapId === map.mapId) {
mapIsFound = true;
}
%>
<option value="<%= map.mapId %>"
<%= (lot.mapId === map.mapId ? " selected" : "") %>
<%= (!isCreate && lot.mapId !== map.mapId ? " disabled" : "") %>>
<%= map.mapName %>
</option>
<% } %>
<% if (lot.mapId && !mapIsFound) { %>
<option value="<%= lot.mapId %>" selected>
<%= lot.mapName %>
</option>
<% } %>
</select>
</div>
</div>
<div class="control">
<button class="button is-unlock-field-button" type="button" title="Unlock Field">
<i class="fas fa-unlock" aria-hidden="true"></i>
</button>
</div>
</div>
<div class="field">
<label class="label" for="lot--mapKey">
<%= configFunctions.getProperty("aliases.map") %> SVG Key
</label>
<div class="control">
<input class="input" id="lot--mapKey" name="mapKey" value="<%= lot.mapKey %>" maxlength="100" />
</div>
<p class="help">
<a href="https://cityssm.github.io/lot-occupancy-system/docs/" target="_blank" rel="noreferrer">
<i class="fa fa-question-circle" aria-hidden="true"></i>
What is the SVG key?
</a>
</p>
</div>
</div>
</div>
<div class="columns">
</div>
<h2 class="title is-4">
Additional Details
</h2>
</form>
<% if (isCreate) { %>
<div class="message is-info">
<p class="message-body">
Additional options will be available after the record has been created.
</p>
</div>
<% } else { %>
<h2 class="title is-4">
Comments
</h2>
<h2 class="title is-4">
Occupancies
<span class="tag"><%= lot.lotOccupancies.length %></span>
</h2>
<% if (lot.lotOccupancies.length === 0) { %>
<div class="message is-info">
<p class="message-body">There are no occupancy records asscociated with this <%= configFunctions.getProperty("aliases.lot") %>.</p>
</div>
<% } else { %>
<table class="table is-fullwidth is-striped is-hoverable">
<thead>
<tr>
<th class="has-width-10">&nbsp;</th>
<th>Occupancy Type</th>
<th>Start Date</th>
<th>End Date</th>
<th>Occupants</th>
</tr>
</thead>
<tbody>
<% const currentDate = dateTimeFunctions.dateToInteger(new Date()); %>
<% for (const lotOccupancy of lot.lotOccupancies) { %>
<% const isActive = !(lotOccupancy.occupancyEndDate && lotOccupancy.occupancyEndDate < currentDate); %>
<tr>
<td class="has-text-centered">
<% if (isActive) { %>
<i class="fas fa-play" title="Currently Occupied"></i>
<% } else { %>
<i class="fas fa-stop" title="Previously Occupied"></i>
<% } %>
</td>
<td><%= lotOccupancy.occupancyType %></td>
<td><%= lotOccupancy.occupancyStartDateString %></td>
<td>
<% if (lotOccupancy.occupancyEndDate) { %>
<%= lotOccupancy.occupancyEndDateString %>
<% } else { %>
(No End Date)
<% } %>
</td>
<td>
<% if (lotOccupancy.lotOccupancyOccupants.length === 0) { %>
(No Occupants)
<% } else { %>
<% const occupant = lotOccupancy.lotOccupancyOccupants[0]; %>
<%= occupant.occupantName %>
<%= (lotOccupancy.lotOccupancyOccupants.length > 1 ? " plus " + (lotOccupancy.lotOccupancyOccupants.length - 1) : "") %>
<% } %>
</td>
</tr>
<% } %>
</tbody>
</table>
<% } %>
<% } %>
<%- include('_footerA'); -%>
<script>
exports.lotComments = <%- JSON.stringify(lot.lotComments) %>;
</script>
<script src="<%= urlPrefix %>/javascripts/lotEdit.min.js"></script>
<%- include('_footerB'); -%>

View File

@ -10,8 +10,7 @@
</a> </a>
</li> </li>
<li class="is-active"><a href="#" aria-current="page"> <li class="is-active"><a href="#" aria-current="page">
<span class="icon is-small"><i class="fas fa-vector-square" aria-hidden="true"></i></span> <%= lot.lotName %>
<span><%= lot.lotName %></span>
</a></li> </a></li>
</ul> </ul>
</nav> </nav>
@ -20,29 +19,101 @@
<%= lot.lotName %> <%= lot.lotName %>
</h1> </h1>
<div>
<strong><%= configFunctions.getProperty("aliases.lot") %> Type</strong><br />
<%= lot.lotType %>
</div>
<% if (user.userProperties.canUpdate) { %> <% if (user.userProperties.canUpdate) { %>
<div class="fixed-container is-fixed-bottom-right mx-4 my-4 has-text-right is-hidden-print"> <div class="fixed-container is-fixed-bottom-right mx-4 my-4 has-text-right is-hidden-print">
<a class="button is-circle is-primary has-tooltip-left" data-tooltip="Update <%= configFunctions.getProperty("aliases.lot") %>" href="<%= urlPrefix %>/lots/<%= lot.lotId %>/edit>"> <a class="button is-circle is-primary has-tooltip-left" data-tooltip="Update <%= configFunctions.getProperty("aliases.lot") %>" href="<%= urlPrefix %>/lots/<%= lot.lotId %>/edit">
<i class="fas fa-pencil-alt" aria-hidden="true"></i> <i class="fas fa-pencil-alt" aria-hidden="true"></i>
<span class="sr-only">Update <%= configFunctions.getProperty("aliases.lot") %></span> <span class="sr-only">Update <%= configFunctions.getProperty("aliases.lot") %></span>
</a> </a>
</div> </div>
<% } %> <% } %>
<% if (lot.mapSVG) { %> <div class="columns">
<div class="column">
<div>
<strong><%= configFunctions.getProperty("aliases.map") %></strong><br />
<a href="<%= urlPrefix %>/maps/<%= lot.mapId %>">
<%= lot.mapName %>
</a>
</div>
<div class="mt-2">
<strong><%= configFunctions.getProperty("aliases.lot") %> Type</strong><br />
<%= lot.lotType %>
</div>
<div class="mt-2">
<strong>Status</strong><br />
<%= lot.lotStatus %>
</div>
</div>
<div class="column">
<h2 class="title is-4">Image</h2>
<% if (lot.mapSVG) { %>
<% const imageURL = urlPrefix + "/images/maps/" + lot.mapSVG %> <% const imageURL = urlPrefix + "/images/maps/" + lot.mapSVG %>
<div class="image" id="lot--map" data-map-key="<%= lot.mapKey %>"> <div class="image" id="lot--map" data-map-key="<%= lot.mapKey %>">
<%- include('../public/images/maps/' + lot.mapSVG); -%> <%- include('../public/images/maps/' + lot.mapSVG); -%>
</div> </div>
<% } else { %> <% } else { %>
<div class="message is-info"> <div class="message is-info">
<p class="message-body">There are no image associated with this <%= configFunctions.getProperty("aliases.lot").toLowerCase() %>.</p> <p class="message-body">There are no image associated with this <%= configFunctions.getProperty("aliases.lot").toLowerCase() %>.</p>
</div> </div>
<% } %>
</div>
</div>
<h2 class="title is-4">
Occupancies
<span class="tag"><%= lot.lotOccupancies.length %></span>
</h2>
<% if (lot.lotOccupancies.length === 0) { %>
<div class="message is-info">
<p class="message-body">There are no occupancy records asscociated with this <%= configFunctions.getProperty("aliases.lot") %>.</p>
</div>
<% } else { %>
<table class="table is-fullwidth is-striped is-hoverable">
<thead>
<tr>
<th class="has-width-10">&nbsp;</th>
<th>Occupancy Type</th>
<th>Start Date</th>
<th>End Date</th>
<th>Occupants</th>
</tr>
</thead>
<tbody>
<% const currentDate = dateTimeFunctions.dateToInteger(new Date()); %>
<% for (const lotOccupancy of lot.lotOccupancies) { %>
<% const isActive = !(lotOccupancy.occupancyEndDate && lotOccupancy.occupancyEndDate < currentDate); %>
<tr>
<td class="has-text-centered">
<% if (isActive) { %>
<i class="fas fa-play" title="Currently Occupied"></i>
<% } else { %>
<i class="fas fa-stop" title="Previously Occupied"></i>
<% } %>
</td>
<td><%= lotOccupancy.occupancyType %></td>
<td><%= lotOccupancy.occupancyStartDateString %></td>
<td>
<% if (lotOccupancy.occupancyEndDate) { %>
<%= lotOccupancy.occupancyEndDateString %>
<% } else { %>
(No End Date)
<% } %>
</td>
<td>
<% if (lotOccupancy.lotOccupancyOccupants.length === 0) { %>
(No Occupants)
<% } else { %>
<% const occupant = lotOccupancy.lotOccupancyOccupants[0]; %>
<%= occupant.occupantName %>
<%= (lotOccupancy.lotOccupancyOccupants.length > 1 ? " plus " + (lotOccupancy.lotOccupancyOccupants.length - 1) : "") %>
<% } %>
</td>
</tr>
<% } %>
</tbody>
</table>
<% } %> <% } %>
<%- include('_footerA'); -%> <%- include('_footerA'); -%>