development

deepsource-autofix-76c6eb20
Dan Gowans 2022-08-05 16:07:43 -04:00
parent e5b2d5da4f
commit 4a35da4b13
61 changed files with 1761 additions and 482 deletions

View File

@ -1,2 +1,12 @@
# lot-occupancy-system # Lot Occupancy System
A system for managing the occupancy of lots. (i.e. Cemetery management)
A system for managing the occupancy of lots.
Built with **cemetery management** in mind, but flexible enough to handle marinas and campgrounds as well.
## Key Features
**Maps are optional!**<br />
Many systems of this type start with a map, and drill down into the data from it.
This can result in a huge amount of effort to get started.
This system can run "out-of-the-box" without maps, with the option to add them when it makes sense.

View File

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

View File

@ -0,0 +1,13 @@
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-edit", {
headTitle: configFunctions.getProperty("aliases.lot") + " " + configFunctions.getProperty("aliases.occupancy") + " View",
lotOccupancy
});
};
export default handler;

View File

@ -0,0 +1,23 @@
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-edit", {
headTitle: configFunctions.getProperty("aliases.lot") + " " + configFunctions.getProperty("aliases.occupancy") + " View",
lotOccupancy
});
};
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,16 @@
import * as configFunctions from "../../helpers/functions.config.js";
import { getMaps } from "../../helpers/lotOccupancyDB/getMaps.js";
import { getLotTypes, getOccupancyTypes } from "../../helpers/functions.cache.js";
export const handler = (request, response) => {
const maps = getMaps();
const lotTypes = getLotTypes();
const occupancyTypes = getOccupancyTypes();
response.render("lotOccupancy-search", {
headTitle: configFunctions.getProperty("aliases.lot") + " Occupancy Search",
maps,
lotTypes,
occupancyTypes,
mapId: request.query.mapId
});
};
export default handler;

View File

@ -0,0 +1,30 @@
import type {
RequestHandler
} from "express";
import * as configFunctions from "../../helpers/functions.config.js";
import {
getMaps
} from "../../helpers/lotOccupancyDB/getMaps.js";
import { getLotTypes, getOccupancyTypes } from "../../helpers/functions.cache.js";
export const handler: RequestHandler = (request, response) => {
const maps = getMaps();
const lotTypes = getLotTypes();
const occupancyTypes = getOccupancyTypes();
response.render("lotOccupancy-search", {
headTitle: configFunctions.getProperty("aliases.lot") + " Occupancy Search",
maps,
lotTypes,
occupancyTypes,
mapId: request.query.mapId
});
};
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,13 @@
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-view", {
headTitle: configFunctions.getProperty("aliases.lot") + " " + configFunctions.getProperty("aliases.occupancy") + " View",
lotOccupancy
});
};
export default handler;

View File

@ -0,0 +1,23 @@
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-view", {
headTitle: configFunctions.getProperty("aliases.lot") + " " + configFunctions.getProperty("aliases.occupancy") + " View",
lotOccupancy
});
};
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,13 @@
import { getLotOccupancies } from "../../helpers/lotOccupancyDB/getLotOccupancies.js";
export const handler = async (request, response) => {
const result = getLotOccupancies(request.body, {
limit: request.body.limit,
offset: request.body.offset,
includeOccupants: true
});
response.json({
count: result.count,
lotOccupancies: result.lotOccupancies
});
};
export default handler;

View File

@ -0,0 +1,21 @@
import type { RequestHandler } from "express";
import { getLotOccupancies } from "../../helpers/lotOccupancyDB/getLotOccupancies.js";
export const handler: RequestHandler = async (request, response) => {
const result = getLotOccupancies(request.body, {
limit: request.body.limit,
offset: request.body.offset,
includeOccupants: true
});
response.json({
count: result.count,
lotOccupancies: result.lotOccupancies
});
};
export default handler;

View File

@ -11,7 +11,7 @@ const recordColumns = " recordCreate_userName varchar(30) not null," +
export const initLotOccupancyDB = () => { export const initLotOccupancyDB = () => {
const lotOccupancyDB = sqlite(databasePath); const lotOccupancyDB = sqlite(databasePath);
const row = lotOccupancyDB const row = lotOccupancyDB
.prepare("select name from sqlite_master where type = 'table' and name = 'LotOccupancies'") .prepare("select name from sqlite_master where type = 'table' and name = 'Fees'")
.get(); .get();
if (!row) { if (!row) {
debugSQL("Creating " + databasePath); debugSQL("Creating " + databasePath);
@ -181,16 +181,14 @@ export const initLotOccupancyDB = () => {
lotOccupancyDB.prepare("create table if not exists Fees (" + lotOccupancyDB.prepare("create table if not exists Fees (" +
"feeId integer not null primary key autoincrement," + "feeId integer not null primary key autoincrement," +
" feeName varchar(100) not null," + " feeName varchar(100) not null," +
" contactTypeId integer," + " occupancyTypeId integer," +
" contactId integer," +
" lotTypeId integer," + " lotTypeId integer," +
" feeAmount decimal(6, 2)," + " feeAmount decimal(6, 2)," +
" feeFunction varchar(100)," + " feeFunction varchar(100)," +
" isRequired bit not null default 0," + " isRequired bit not null default 0," +
" orderNumber smallint not null default 0," + " orderNumber smallint not null default 0," +
recordColumns + "," + recordColumns + "," +
" foreign key (contactTypeId) references ContactTypes (contactTypeId)," + " foreign key (occupancyTypeId) references OccupancyTypes (occupancyTypeId)," +
" foreign key (contactId) references Contacts (contactId)," +
" foreign key (lotTypeId) references LotTypes (lotTypeId)" + " foreign key (lotTypeId) references LotTypes (lotTypeId)" +
")").run(); ")").run();
lotOccupancyDB.prepare("create index if not exists idx_fees_ordernumber" + lotOccupancyDB.prepare("create index if not exists idx_fees_ordernumber" +

View File

@ -20,7 +20,7 @@ export const initLotOccupancyDB = (): boolean => {
const lotOccupancyDB = sqlite(databasePath); const lotOccupancyDB = sqlite(databasePath);
const row = lotOccupancyDB const row = lotOccupancyDB
.prepare("select name from sqlite_master where type = 'table' and name = 'LotOccupancies'") .prepare("select name from sqlite_master where type = 'table' and name = 'Fees'")
.get(); .get();
if (!row) { if (!row) {
@ -231,16 +231,14 @@ export const initLotOccupancyDB = (): boolean => {
lotOccupancyDB.prepare("create table if not exists Fees (" + lotOccupancyDB.prepare("create table if not exists Fees (" +
"feeId integer not null primary key autoincrement," + "feeId integer not null primary key autoincrement," +
" feeName varchar(100) not null," + " feeName varchar(100) not null," +
" contactTypeId integer," + " occupancyTypeId integer," +
" contactId integer," +
" lotTypeId integer," + " lotTypeId integer," +
" feeAmount decimal(6, 2)," + " feeAmount decimal(6, 2)," +
" feeFunction varchar(100)," + " feeFunction varchar(100)," +
" isRequired bit not null default 0," + " isRequired bit not null default 0," +
" orderNumber smallint not null default 0," + " orderNumber smallint not null default 0," +
recordColumns + "," + recordColumns + "," +
" foreign key (contactTypeId) references ContactTypes (contactTypeId)," + " foreign key (occupancyTypeId) references OccupancyTypes (occupancyTypeId)," +
" foreign key (contactId) references Contacts (contactId)," +
" foreign key (lotTypeId) references LotTypes (lotTypeId)" + " foreign key (lotTypeId) references LotTypes (lotTypeId)" +
")").run(); ")").run();

View File

@ -19,4 +19,8 @@ export declare function getProperty(propertyName: "aliases.lot"): string;
export declare function getProperty(propertyName: "aliases.lots"): string; export declare function getProperty(propertyName: "aliases.lots"): string;
export declare function getProperty(propertyName: "aliases.map"): string; export declare function getProperty(propertyName: "aliases.map"): string;
export declare function getProperty(propertyName: "aliases.maps"): string; export declare function getProperty(propertyName: "aliases.maps"): string;
export declare function getProperty(propertyName: "aliases.occupancy"): string;
export declare function getProperty(propertyName: "aliases.occupancies"): string;
export declare function getProperty(propertyName: "aliases.occupant"): string;
export declare function getProperty(propertyName: "aliases.occupants"): string;
export declare const keepAliveMillis: number; export declare const keepAliveMillis: number;

View File

@ -19,6 +19,10 @@ configFallbackValues.set("aliases.lot", "Lot");
configFallbackValues.set("aliases.lots", "Lots"); configFallbackValues.set("aliases.lots", "Lots");
configFallbackValues.set("aliases.map", "Map"); configFallbackValues.set("aliases.map", "Map");
configFallbackValues.set("aliases.maps", "Maps"); configFallbackValues.set("aliases.maps", "Maps");
configFallbackValues.set("aliases.occupancy", "Occupancy");
configFallbackValues.set("aliases.occupancies", "Occupancies");
configFallbackValues.set("aliases.occupant", "Occupant");
configFallbackValues.set("aliases.occupants", "Occupants");
export function getProperty(propertyName) { export function getProperty(propertyName) {
const propertyNameSplit = propertyName.split("."); const propertyNameSplit = propertyName.split(".");
let currentObject = config; let currentObject = config;

View File

@ -33,6 +33,10 @@ configFallbackValues.set("aliases.lot", "Lot");
configFallbackValues.set("aliases.lots", "Lots"); configFallbackValues.set("aliases.lots", "Lots");
configFallbackValues.set("aliases.map", "Map"); configFallbackValues.set("aliases.map", "Map");
configFallbackValues.set("aliases.maps", "Maps"); configFallbackValues.set("aliases.maps", "Maps");
configFallbackValues.set("aliases.occupancy", "Occupancy");
configFallbackValues.set("aliases.occupancies", "Occupancies");
configFallbackValues.set("aliases.occupant", "Occupant");
configFallbackValues.set("aliases.occupants", "Occupants");
/* /*
@ -64,6 +68,10 @@ export function getProperty(propertyName: "aliases.lot"): string;
export function getProperty(propertyName: "aliases.lots"): string; export function getProperty(propertyName: "aliases.lots"): string;
export function getProperty(propertyName: "aliases.map"): string; export function getProperty(propertyName: "aliases.map"): string;
export function getProperty(propertyName: "aliases.maps"): string; export function getProperty(propertyName: "aliases.maps"): string;
export function getProperty(propertyName: "aliases.occupancy"): string;
export function getProperty(propertyName: "aliases.occupancies"): string;
export function getProperty(propertyName: "aliases.occupant"): string;
export function getProperty(propertyName: "aliases.occupants"): string;
export function getProperty(propertyName: string): unknown { export function getProperty(propertyName: string): unknown {

View File

@ -2,6 +2,12 @@ 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;
occupancyTime?: "" | "past" | "current" | "future";
occupantName?: string;
occupancyTypeId?: number | string;
mapId?: number | string;
lotName?: string;
lotTypeId?: number | string;
} }
interface GetLotOccupanciesOptions { interface GetLotOccupanciesOptions {
limit: -1 | number; limit: -1 | number;

View File

@ -1,4 +1,4 @@
import { dateIntegerToString } from "@cityssm/expressjs-server-js/dateTimeFns.js"; import { dateIntegerToString, dateToInteger } 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";
import { getLotOccupancyOccupants } from "./getLotOccupancyOccupants.js"; import { getLotOccupancyOccupants } from "./getLotOccupancyOccupants.js";
@ -13,8 +13,52 @@ export const getLotOccupancies = (filters, options, connectedDatabase) => {
sqlWhereClause += " and o.lotId = ?"; sqlWhereClause += " and o.lotId = ?";
sqlParameters.push(filters.lotId); sqlParameters.push(filters.lotId);
} }
if (filters.lotName) {
const lotNamePieces = filters.lotName.toLowerCase().split(" ");
for (const lotNamePiece of lotNamePieces) {
sqlWhereClause += " and instr(lower(l.lotName), ?)";
sqlParameters.push(lotNamePiece);
}
}
if (filters.occupantName) {
const occupantNamePieces = filters.occupantName.toLowerCase().split(" ");
for (const occupantNamePiece of occupantNamePieces) {
sqlWhereClause += " and o.lotOccupancyId in (select oo.lotOccupancyId from LotOccupancyOccupants oo left join Occupants o on oo.occupantId = o.occupantId where oo.recordDelete_timeMillis is null and instr(lower(o.occupantName), ?))";
sqlParameters.push(occupantNamePiece);
}
}
if (filters.occupancyTypeId) {
sqlWhereClause += " and o.occupancyTypeId = ?";
sqlParameters.push(filters.occupancyTypeId);
}
if (filters.occupancyTime) {
const currentDateString = dateToInteger(new Date());
switch (filters.occupancyTime) {
case "current":
sqlWhereClause += " and o.occupancyStartDate <= ? and (o.occupancyEndDate is null or o.occupancyEndDate >= ?)";
sqlParameters.push(currentDateString, currentDateString);
break;
case "past":
sqlWhereClause += " and o.occupancyEndDate < ?";
sqlParameters.push(currentDateString);
break;
case "future":
sqlWhereClause += " and o.occupancyStartDate > ?";
sqlParameters.push(currentDateString);
break;
}
}
if (filters.mapId) {
sqlWhereClause += " and l.mapId = ?";
sqlParameters.push(filters.mapId);
}
if (filters.lotTypeId) {
sqlWhereClause += " and l.lotTypeId = ?";
sqlParameters.push(filters.lotTypeId);
}
const count = database.prepare("select count(*) as recordCount" + const count = database.prepare("select count(*) as recordCount" +
" from LotOccupancies o" + " from LotOccupancies o" +
" left join Lots l on o.lotId = l.lotId" +
sqlWhereClause) sqlWhereClause)
.get(sqlParameters) .get(sqlParameters)
.recordCount; .recordCount;
@ -24,11 +68,13 @@ export const getLotOccupancies = (filters, options, connectedDatabase) => {
.prepare("select o.lotOccupancyId," + .prepare("select o.lotOccupancyId," +
" o.occupancyTypeId, t.occupancyType," + " o.occupancyTypeId, t.occupancyType," +
" o.lotId, l.lotName," + " o.lotId, l.lotName," +
" l.mapId, m.mapName," +
" o.occupancyStartDate, userFn_dateIntegerToString(o.occupancyStartDate) as occupancyStartDateString," + " o.occupancyStartDate, userFn_dateIntegerToString(o.occupancyStartDate) as occupancyStartDateString," +
" o.occupancyEndDate, userFn_dateIntegerToString(o.occupancyEndDate) as occupancyEndDateString" + " o.occupancyEndDate, userFn_dateIntegerToString(o.occupancyEndDate) as occupancyEndDateString" +
" 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 Maps m on l.mapId = m.mapId" +
sqlWhereClause + sqlWhereClause +
" order by o.occupancyStartDate desc, ifnull(o.occupancyEndDate, 99999999) desc, l.lotName, o.lotId" + " order by o.occupancyStartDate desc, ifnull(o.occupancyEndDate, 99999999) desc, l.lotName, o.lotId" +
(options.limit !== -1 ? (options.limit !== -1 ?

View File

@ -1,15 +1,29 @@
import { dateIntegerToString } from "@cityssm/expressjs-server-js/dateTimeFns.js"; import {
dateIntegerToString,
dateToInteger
} 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 {
getLotOccupancyOccupants
} from "./getLotOccupancyOccupants.js";
import type * as recordTypes from "../../types/recordTypes"; import type * as recordTypes from "../../types/recordTypes";
import { getLotOccupancyOccupants } from "./getLotOccupancyOccupants.js";
interface GetLotOccupanciesFilters { interface GetLotOccupanciesFilters {
lotId ? : number | string; lotId ? : number | string;
occupancyTime ? : "" | "past" | "current" | "future";
occupantName ? : string;
occupancyTypeId ? : number | string;
mapId ? : number | string;
lotName ? : string;
lotTypeId ? : number | string;
} }
@ -41,8 +55,64 @@ export const getLotOccupancies = (filters: GetLotOccupanciesFilters,
sqlParameters.push(filters.lotId); sqlParameters.push(filters.lotId);
} }
if (filters.lotName) {
const lotNamePieces = filters.lotName.toLowerCase().split(" ");
for (const lotNamePiece of lotNamePieces) {
sqlWhereClause += " and instr(lower(l.lotName), ?)";
sqlParameters.push(lotNamePiece);
}
}
if (filters.occupantName) {
const occupantNamePieces = filters.occupantName.toLowerCase().split(" ");
for (const occupantNamePiece of occupantNamePieces) {
sqlWhereClause += " and o.lotOccupancyId in (select oo.lotOccupancyId from LotOccupancyOccupants oo left join Occupants o on oo.occupantId = o.occupantId where oo.recordDelete_timeMillis is null and instr(lower(o.occupantName), ?))";
sqlParameters.push(occupantNamePiece);
}
}
if (filters.occupancyTypeId) {
sqlWhereClause += " and o.occupancyTypeId = ?";
sqlParameters.push(filters.occupancyTypeId);
}
if (filters.occupancyTime) {
const currentDateString = dateToInteger(new Date());
switch (filters.occupancyTime) {
case "current":
sqlWhereClause += " and o.occupancyStartDate <= ? and (o.occupancyEndDate is null or o.occupancyEndDate >= ?)";
sqlParameters.push(currentDateString, currentDateString);
break;
case "past":
sqlWhereClause += " and o.occupancyEndDate < ?";
sqlParameters.push(currentDateString);
break;
case "future":
sqlWhereClause += " and o.occupancyStartDate > ?";
sqlParameters.push(currentDateString);
break;
}
}
if (filters.mapId) {
sqlWhereClause += " and l.mapId = ?";
sqlParameters.push(filters.mapId);
}
if (filters.lotTypeId) {
sqlWhereClause += " and l.lotTypeId = ?";
sqlParameters.push(filters.lotTypeId);
}
const count: number = database.prepare("select count(*) as recordCount" + const count: number = database.prepare("select count(*) as recordCount" +
" from LotOccupancies o" + " from LotOccupancies o" +
" left join Lots l on o.lotId = l.lotId" +
sqlWhereClause) sqlWhereClause)
.get(sqlParameters) .get(sqlParameters)
.recordCount; .recordCount;
@ -55,11 +125,13 @@ export const getLotOccupancies = (filters: GetLotOccupanciesFilters,
.prepare("select o.lotOccupancyId," + .prepare("select o.lotOccupancyId," +
" o.occupancyTypeId, t.occupancyType," + " o.occupancyTypeId, t.occupancyType," +
" o.lotId, l.lotName," + " o.lotId, l.lotName," +
" l.mapId, m.mapName," +
" o.occupancyStartDate, userFn_dateIntegerToString(o.occupancyStartDate) as occupancyStartDateString," + " o.occupancyStartDate, userFn_dateIntegerToString(o.occupancyStartDate) as occupancyStartDateString," +
" o.occupancyEndDate, userFn_dateIntegerToString(o.occupancyEndDate) as occupancyEndDateString" + " o.occupancyEndDate, userFn_dateIntegerToString(o.occupancyEndDate) as occupancyEndDateString" +
" 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 Maps m on l.mapId = m.mapId" +
sqlWhereClause + sqlWhereClause +
" order by o.occupancyStartDate desc, ifnull(o.occupancyEndDate, 99999999) desc, l.lotName, o.lotId" + " order by o.occupancyStartDate desc, ifnull(o.occupancyEndDate, 99999999) desc, l.lotName, o.lotId" +
(options.limit !== -1 ? (options.limit !== -1 ?

View File

@ -0,0 +1,3 @@
import type * as recordTypes from "../../types/recordTypes";
export declare const getLotOccupancy: (lotOccupancyId: number | string) => recordTypes.LotOccupancy;
export default getLotOccupancy;

View File

@ -0,0 +1,30 @@
import { dateIntegerToString } from "@cityssm/expressjs-server-js/dateTimeFns.js";
import sqlite from "better-sqlite3";
import { lotOccupancyDB as databasePath } from "../../data/databasePaths.js";
import { getLotOccupancyOccupants } from "./getLotOccupancyOccupants.js";
export const getLotOccupancy = (lotOccupancyId) => {
const database = sqlite(databasePath, {
readonly: true
});
database.function("userFn_dateIntegerToString", dateIntegerToString);
const lotOccupancy = database
.prepare("select o.lotOccupancyId," +
" o.occupancyTypeId, t.occupancyType," +
" o.lotId, l.lotName," +
" l.mapId, m.mapName," +
" o.occupancyStartDate, userFn_dateIntegerToString(o.occupancyStartDate) as occupancyStartDateString," +
" o.occupancyEndDate, userFn_dateIntegerToString(o.occupancyEndDate) as occupancyEndDateString" +
" from LotOccupancies o" +
" left join OccupancyTypes t on o.occupancyTypeId = t.occupancyTypeId" +
" left join Lots l on o.lotId = l.lotId" +
" left join Maps m on l.mapId = m.mapId" +
" where o.recordDelete_timeMillis is null" +
" and o.lotOccupancyId = ?")
.get(lotOccupancyId);
if (lotOccupancy) {
lotOccupancy.lotOccupancyOccupants = getLotOccupancyOccupants(lotOccupancyId, database);
}
database.close();
return lotOccupancy;
};
export default getLotOccupancy;

View File

@ -0,0 +1,53 @@
import {
dateIntegerToString
} from "@cityssm/expressjs-server-js/dateTimeFns.js";
import sqlite from "better-sqlite3";
import {
lotOccupancyDB as databasePath
} from "../../data/databasePaths.js";
import {
getLotOccupancyOccupants
} from "./getLotOccupancyOccupants.js";
import type * as recordTypes from "../../types/recordTypes";
export const getLotOccupancy = (lotOccupancyId: number | string): recordTypes.LotOccupancy => {
const database = sqlite(databasePath, {
readonly: true
});
database.function("userFn_dateIntegerToString", dateIntegerToString);
const lotOccupancy: recordTypes.LotOccupancy = database
.prepare("select o.lotOccupancyId," +
" o.occupancyTypeId, t.occupancyType," +
" o.lotId, l.lotName," +
" l.mapId, m.mapName," +
" o.occupancyStartDate, userFn_dateIntegerToString(o.occupancyStartDate) as occupancyStartDateString," +
" o.occupancyEndDate, userFn_dateIntegerToString(o.occupancyEndDate) as occupancyEndDateString" +
" from LotOccupancies o" +
" left join OccupancyTypes t on o.occupancyTypeId = t.occupancyTypeId" +
" left join Lots l on o.lotId = l.lotId" +
" left join Maps m on l.mapId = m.mapId" +
" where o.recordDelete_timeMillis is null" +
" and o.lotOccupancyId = ?"
)
.get(lotOccupancyId);
if (lotOccupancy) {
lotOccupancy.lotOccupancyOccupants = getLotOccupancyOccupants(lotOccupancyId, database);
}
database.close();
return lotOccupancy;
};
export default getLotOccupancy;

View File

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

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 getLotOccupancyComments = (lotOccupancyId, connectedDatabase) => {
const database = connectedDatabase || sqlite(databasePath, {
readonly: true
});
database.function("userFn_dateIntegerToString", dateIntegerToString);
database.function("userFn_timeIntegerToString", timeIntegerToString);
const lotComments = database
.prepare("select lotOccupancyCommentId," +
" lotOccupancyCommentDate, userFn_dateIntegerToString(lotOccupancyCommentDate) as lotOccupancyCommentDateString," +
" lotOccupancyCommentTime, userFn_timeIntegerToString(lotOccupancyCommentTime) as lotOccupancyCommentTimeString," +
" lotOccupancyComment" +
" from LotOccupancyComments" +
" where recordDelete_timeMillis is null" +
" and lotOccupancyId = ?" +
" order by lotOccupancyCommentDate desc, lotOccupancyCommentTime desc, lotOccupancyCommentId desc")
.all(lotOccupancyId);
if (!connectedDatabase) {
database.close();
}
return lotComments;
};
export default getLotOccupancyComments;

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 getLotOccupancyComments = (lotOccupancyId: number | string, connectedDatabase ? : sqlite.Database): recordTypes.LotOccupancyComment[] => {
const database = connectedDatabase || sqlite(databasePath, {
readonly: true
});
database.function("userFn_dateIntegerToString", dateIntegerToString);
database.function("userFn_timeIntegerToString", timeIntegerToString);
const lotComments = database
.prepare("select lotOccupancyCommentId," +
" lotOccupancyCommentDate, userFn_dateIntegerToString(lotOccupancyCommentDate) as lotOccupancyCommentDateString," +
" lotOccupancyCommentTime, userFn_timeIntegerToString(lotOccupancyCommentTime) as lotOccupancyCommentTimeString," +
" lotOccupancyComment" +
" from LotOccupancyComments" +
" where recordDelete_timeMillis is null" +
" and lotOccupancyId = ?" +
" order by lotOccupancyCommentDate desc, lotOccupancyCommentTime desc, lotOccupancyCommentId desc")
.all(lotOccupancyId);
if (!connectedDatabase) {
database.close();
}
return lotComments;
};
export default getLotOccupancyComments;

View File

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

View File

@ -6,7 +6,7 @@ import {
import type * as recordTypes from "../../types/recordTypes"; import type * as recordTypes from "../../types/recordTypes";
export const getLotOccupancyOccupants = (lotOccupancyId: number, export const getLotOccupancyOccupants = (lotOccupancyId: number | string,
connectedDatabase ? : sqlite.Database): recordTypes.LotOccupancyOccupant[] => { connectedDatabase ? : sqlite.Database): recordTypes.LotOccupancyOccupant[] => {
const database = connectedDatabase || sqlite(databasePath, { const database = connectedDatabase || sqlite(databasePath, {

436
package-lock.json generated
View File

@ -34,7 +34,7 @@
"@cityssm/bulma-webapp-css": "^0.11.0", "@cityssm/bulma-webapp-css": "^0.11.0",
"@cityssm/mssql-multi-pool": "^2.1.6", "@cityssm/mssql-multi-pool": "^2.1.6",
"@types/activedirectory2": "^1.2.3", "@types/activedirectory2": "^1.2.3",
"@types/better-sqlite3": "^7.5.0", "@types/better-sqlite3": "^7.6.0",
"@types/compression": "^1.7.2", "@types/compression": "^1.7.2",
"@types/cookie-parser": "^1.4.3", "@types/cookie-parser": "^1.4.3",
"@types/csurf": "^1.11.2", "@types/csurf": "^1.11.2",
@ -51,12 +51,12 @@
"@types/mocha": "^9.1.1", "@types/mocha": "^9.1.1",
"@types/mssql": "^8.0.3", "@types/mssql": "^8.0.3",
"@types/node-windows": "^0.1.2", "@types/node-windows": "^0.1.2",
"@types/papaparse": "^5.3.2", "@types/papaparse": "^5.3.3",
"@types/session-file-store": "^1.2.2", "@types/session-file-store": "^1.2.2",
"@typescript-eslint/eslint-plugin": "^5.31.0", "@typescript-eslint/eslint-plugin": "^5.32.0",
"@typescript-eslint/parser": "^5.31.0", "@typescript-eslint/parser": "^5.32.0",
"bulma": "^0.9.4", "bulma": "^0.9.4",
"eslint": "^8.20.0", "eslint": "^8.21.0",
"eslint-plugin-import": "^2.26.0", "eslint-plugin-import": "^2.26.0",
"eslint-plugin-node": "^11.1.0", "eslint-plugin-node": "^11.1.0",
"eslint-plugin-promise": "^6.0.0", "eslint-plugin-promise": "^6.0.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.54.0" "sass": "^1.54.3"
}, },
"engines": { "engines": {
"node": "^12.20.0 || ^14.13.1 || >=16.0.0" "node": "^12.20.0 || ^14.13.1 || >=16.0.0"
@ -638,9 +638,9 @@
} }
}, },
"node_modules/@humanwhocodes/config-array": { "node_modules/@humanwhocodes/config-array": {
"version": "0.9.5", "version": "0.10.4",
"resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.9.5.tgz", "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.10.4.tgz",
"integrity": "sha512-ObyMyWxZiCu/yTisA7uzx81s40xR2fD5Cg/2Kq7G02ajkNubJf6BopgDTmDyc3U7sXpNKM8cYOw7s7Tyr+DnCw==", "integrity": "sha512-mXAIHxZT3Vcpg83opl1wGlVZ9xydbfZO3r5YfRSH6Gpp2J/PfdBP0wbDa2sO6/qRbcalpoevVyW6A/fI6LfeMw==",
"dev": true, "dev": true,
"dependencies": { "dependencies": {
"@humanwhocodes/object-schema": "^1.2.1", "@humanwhocodes/object-schema": "^1.2.1",
@ -651,6 +651,16 @@
"node": ">=10.10.0" "node": ">=10.10.0"
} }
}, },
"node_modules/@humanwhocodes/gitignore-to-minimatch": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/@humanwhocodes/gitignore-to-minimatch/-/gitignore-to-minimatch-1.0.2.tgz",
"integrity": "sha512-rSqmMJDdLFUsyxR6FMtD00nfQKKLFb1kv+qBbOVKqErvloEIJLo5bDTJTQNTYgeyp78JsA7u/NPi5jT1GR/MuA==",
"dev": true,
"funding": {
"type": "github",
"url": "https://github.com/sponsors/nzakas"
}
},
"node_modules/@humanwhocodes/object-schema": { "node_modules/@humanwhocodes/object-schema": {
"version": "1.2.1", "version": "1.2.1",
"resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-1.2.1.tgz", "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-1.2.1.tgz",
@ -732,9 +742,9 @@
} }
}, },
"node_modules/@types/better-sqlite3": { "node_modules/@types/better-sqlite3": {
"version": "7.5.0", "version": "7.6.0",
"resolved": "https://registry.npmjs.org/@types/better-sqlite3/-/better-sqlite3-7.5.0.tgz", "resolved": "https://registry.npmjs.org/@types/better-sqlite3/-/better-sqlite3-7.6.0.tgz",
"integrity": "sha512-G9ZbMjydW2yj1AgiPlUtdgF3a1qNpLJLudc9ynJCeJByS3XFWpmT9LT+VSHrKHFbxb31CvtYwetLTOvG9zdxdg==", "integrity": "sha512-rnSP9vY+fVsF3iJja5yRGBJV63PNBiezJlYrCkqUmQWFoB16cxAHwOkjsAYEu317miOfKaJpa65cbp0P4XJ/jw==",
"dev": true, "dev": true,
"dependencies": { "dependencies": {
"@types/node": "*" "@types/node": "*"
@ -1040,9 +1050,9 @@
"dev": true "dev": true
}, },
"node_modules/@types/papaparse": { "node_modules/@types/papaparse": {
"version": "5.3.2", "version": "5.3.3",
"resolved": "https://registry.npmjs.org/@types/papaparse/-/papaparse-5.3.2.tgz", "resolved": "https://registry.npmjs.org/@types/papaparse/-/papaparse-5.3.3.tgz",
"integrity": "sha512-BNbCHJkTE4RwmAFkCxEalET4mDvGr/1ld7ZtQ4i/laWI/iiVt+GL07stdvufle4KfywyvloqqpIiJscXNCrKxA==", "integrity": "sha512-i7fV8u843vb7nIGpcwdCsG3WjfBONeytRHK1mQL9d5KQAvFeAK2rRisDHicreYpoQ0MXocUDEqunKHTeXdvibg==",
"dev": true, "dev": true,
"dependencies": { "dependencies": {
"@types/node": "*" "@types/node": "*"
@ -1137,14 +1147,14 @@
} }
}, },
"node_modules/@typescript-eslint/eslint-plugin": { "node_modules/@typescript-eslint/eslint-plugin": {
"version": "5.31.0", "version": "5.32.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.31.0.tgz", "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.32.0.tgz",
"integrity": "sha512-VKW4JPHzG5yhYQrQ1AzXgVgX8ZAJEvCz0QI6mLRX4tf7rnFfh5D8SKm0Pq6w5PyNfAWJk6sv313+nEt3ohWMBQ==", "integrity": "sha512-CHLuz5Uz7bHP2WgVlvoZGhf0BvFakBJKAD/43Ty0emn4wXWv5k01ND0C0fHcl/Im8Td2y/7h44E9pca9qAu2ew==",
"dev": true, "dev": true,
"dependencies": { "dependencies": {
"@typescript-eslint/scope-manager": "5.31.0", "@typescript-eslint/scope-manager": "5.32.0",
"@typescript-eslint/type-utils": "5.31.0", "@typescript-eslint/type-utils": "5.32.0",
"@typescript-eslint/utils": "5.31.0", "@typescript-eslint/utils": "5.32.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 +1180,14 @@
} }
}, },
"node_modules/@typescript-eslint/parser": { "node_modules/@typescript-eslint/parser": {
"version": "5.31.0", "version": "5.32.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.31.0.tgz", "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.32.0.tgz",
"integrity": "sha512-UStjQiZ9OFTFReTrN+iGrC6O/ko9LVDhreEK5S3edmXgR396JGq7CoX2TWIptqt/ESzU2iRKXAHfSF2WJFcWHw==", "integrity": "sha512-IxRtsehdGV9GFQ35IGm5oKKR2OGcazUoiNBxhRV160iF9FoyuXxjY+rIqs1gfnd+4eL98OjeGnMpE7RF/NBb3A==",
"dev": true, "dev": true,
"dependencies": { "dependencies": {
"@typescript-eslint/scope-manager": "5.31.0", "@typescript-eslint/scope-manager": "5.32.0",
"@typescript-eslint/types": "5.31.0", "@typescript-eslint/types": "5.32.0",
"@typescript-eslint/typescript-estree": "5.31.0", "@typescript-eslint/typescript-estree": "5.32.0",
"debug": "^4.3.4" "debug": "^4.3.4"
}, },
"engines": { "engines": {
@ -1197,13 +1207,13 @@
} }
}, },
"node_modules/@typescript-eslint/scope-manager": { "node_modules/@typescript-eslint/scope-manager": {
"version": "5.31.0", "version": "5.32.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.31.0.tgz", "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.32.0.tgz",
"integrity": "sha512-8jfEzBYDBG88rcXFxajdVavGxb5/XKXyvWgvD8Qix3EEJLCFIdVloJw+r9ww0wbyNLOTYyBsR+4ALNGdlalLLg==", "integrity": "sha512-KyAE+tUON0D7tNz92p1uetRqVJiiAkeluvwvZOqBmW9z2XApmk5WSMV9FrzOroAcVxJZB3GfUwVKr98Dr/OjOg==",
"dev": true, "dev": true,
"dependencies": { "dependencies": {
"@typescript-eslint/types": "5.31.0", "@typescript-eslint/types": "5.32.0",
"@typescript-eslint/visitor-keys": "5.31.0" "@typescript-eslint/visitor-keys": "5.32.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 +1224,12 @@
} }
}, },
"node_modules/@typescript-eslint/type-utils": { "node_modules/@typescript-eslint/type-utils": {
"version": "5.31.0", "version": "5.32.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-5.31.0.tgz", "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-5.32.0.tgz",
"integrity": "sha512-7ZYqFbvEvYXFn9ax02GsPcEOmuWNg+14HIf4q+oUuLnMbpJ6eHAivCg7tZMVwzrIuzX3QCeAOqKoyMZCv5xe+w==", "integrity": "sha512-0gSsIhFDduBz3QcHJIp3qRCvVYbqzHg8D6bHFsDMrm0rURYDj+skBK2zmYebdCp+4nrd9VWd13egvhYFJj/wZg==",
"dev": true, "dev": true,
"dependencies": { "dependencies": {
"@typescript-eslint/utils": "5.31.0", "@typescript-eslint/utils": "5.32.0",
"debug": "^4.3.4", "debug": "^4.3.4",
"tsutils": "^3.21.0" "tsutils": "^3.21.0"
}, },
@ -1240,9 +1250,9 @@
} }
}, },
"node_modules/@typescript-eslint/types": { "node_modules/@typescript-eslint/types": {
"version": "5.31.0", "version": "5.32.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.31.0.tgz", "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.32.0.tgz",
"integrity": "sha512-/f/rMaEseux+I4wmR6mfpM2wvtNZb1p9hAV77hWfuKc3pmaANp5dLAZSiE3/8oXTYTt3uV9KW5yZKJsMievp6g==", "integrity": "sha512-EBUKs68DOcT/EjGfzywp+f8wG9Zw6gj6BjWu7KV/IYllqKJFPlZlLSYw/PTvVyiRw50t6wVbgv4p9uE2h6sZrQ==",
"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 +1263,13 @@
} }
}, },
"node_modules/@typescript-eslint/typescript-estree": { "node_modules/@typescript-eslint/typescript-estree": {
"version": "5.31.0", "version": "5.32.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.31.0.tgz", "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.32.0.tgz",
"integrity": "sha512-3S625TMcARX71wBc2qubHaoUwMEn+l9TCsaIzYI/ET31Xm2c9YQ+zhGgpydjorwQO9pLfR/6peTzS/0G3J/hDw==", "integrity": "sha512-ZVAUkvPk3ITGtCLU5J4atCw9RTxK+SRc6hXqLtllC2sGSeMFWN+YwbiJR9CFrSFJ3w4SJfcWtDwNb/DmUIHdhg==",
"dev": true, "dev": true,
"dependencies": { "dependencies": {
"@typescript-eslint/types": "5.31.0", "@typescript-eslint/types": "5.32.0",
"@typescript-eslint/visitor-keys": "5.31.0", "@typescript-eslint/visitor-keys": "5.32.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 +1290,15 @@
} }
}, },
"node_modules/@typescript-eslint/utils": { "node_modules/@typescript-eslint/utils": {
"version": "5.31.0", "version": "5.32.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.31.0.tgz", "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.32.0.tgz",
"integrity": "sha512-kcVPdQS6VIpVTQ7QnGNKMFtdJdvnStkqS5LeALr4rcwx11G6OWb2HB17NMPnlRHvaZP38hL9iK8DdE9Fne7NYg==", "integrity": "sha512-W7lYIAI5Zlc5K082dGR27Fczjb3Q57ECcXefKU/f0ajM5ToM0P+N9NmJWip8GmGu/g6QISNT+K6KYB+iSHjXCQ==",
"dev": true, "dev": true,
"dependencies": { "dependencies": {
"@types/json-schema": "^7.0.9", "@types/json-schema": "^7.0.9",
"@typescript-eslint/scope-manager": "5.31.0", "@typescript-eslint/scope-manager": "5.32.0",
"@typescript-eslint/types": "5.31.0", "@typescript-eslint/types": "5.32.0",
"@typescript-eslint/typescript-estree": "5.31.0", "@typescript-eslint/typescript-estree": "5.32.0",
"eslint-scope": "^5.1.1", "eslint-scope": "^5.1.1",
"eslint-utils": "^3.0.0" "eslint-utils": "^3.0.0"
}, },
@ -1304,12 +1314,12 @@
} }
}, },
"node_modules/@typescript-eslint/visitor-keys": { "node_modules/@typescript-eslint/visitor-keys": {
"version": "5.31.0", "version": "5.32.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.31.0.tgz", "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.32.0.tgz",
"integrity": "sha512-ZK0jVxSjS4gnPirpVjXHz7mgdOsZUHzNYSfTw2yPa3agfbt9YfqaBiBZFSSxeBWnpWkzCxTfUpnzA3Vily/CSg==", "integrity": "sha512-S54xOHZgfThiZ38/ZGTgB2rqx51CMJ5MCfVT2IplK4Q7hgzGfe0nLzLCcenDnc/cSjP568hdeKfeDcBgqNHD/g==",
"dev": true, "dev": true,
"dependencies": { "dependencies": {
"@typescript-eslint/types": "5.31.0", "@typescript-eslint/types": "5.32.0",
"eslint-visitor-keys": "^3.3.0" "eslint-visitor-keys": "^3.3.0"
}, },
"engines": { "engines": {
@ -1344,9 +1354,9 @@
} }
}, },
"node_modules/acorn": { "node_modules/acorn": {
"version": "8.7.1", "version": "8.8.0",
"resolved": "https://registry.npmjs.org/acorn/-/acorn-8.7.1.tgz", "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.8.0.tgz",
"integrity": "sha512-Xx54uLJQZ19lKygFXOWsscKUbsBZW0CPykPhVQdhIeIwrbPmJzqeASDInc8nKBnp/JT6igTs82qPXz069H8I/A==", "integrity": "sha512-QOxyigPVrpZ2GXT+PFyZTl6TtOFc5egxHIP9IlQ+RbupQuX4RkT/Bee4/kQuC02Xkzg84JcT7oLYtDIQxp+v7w==",
"dev": true, "dev": true,
"bin": { "bin": {
"acorn": "bin/acorn" "acorn": "bin/acorn"
@ -3172,13 +3182,14 @@
} }
}, },
"node_modules/eslint": { "node_modules/eslint": {
"version": "8.20.0", "version": "8.21.0",
"resolved": "https://registry.npmjs.org/eslint/-/eslint-8.20.0.tgz", "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.21.0.tgz",
"integrity": "sha512-d4ixhz5SKCa1D6SCPrivP7yYVi7nyD6A4vs6HIAul9ujBzcEmZVM3/0NN/yu5nKhmO1wjp5xQ46iRfmDGlOviA==", "integrity": "sha512-/XJ1+Qurf1T9G2M5IHrsjp+xrGT73RZf23xA1z5wB1ZzzEAWSZKvRwhWxTFp1rvkvCfwcvAUNAP31bhKTTGfDA==",
"dev": true, "dev": true,
"dependencies": { "dependencies": {
"@eslint/eslintrc": "^1.3.0", "@eslint/eslintrc": "^1.3.0",
"@humanwhocodes/config-array": "^0.9.2", "@humanwhocodes/config-array": "^0.10.4",
"@humanwhocodes/gitignore-to-minimatch": "^1.0.2",
"ajv": "^6.10.0", "ajv": "^6.10.0",
"chalk": "^4.0.0", "chalk": "^4.0.0",
"cross-spawn": "^7.0.2", "cross-spawn": "^7.0.2",
@ -3188,14 +3199,17 @@
"eslint-scope": "^7.1.1", "eslint-scope": "^7.1.1",
"eslint-utils": "^3.0.0", "eslint-utils": "^3.0.0",
"eslint-visitor-keys": "^3.3.0", "eslint-visitor-keys": "^3.3.0",
"espree": "^9.3.2", "espree": "^9.3.3",
"esquery": "^1.4.0", "esquery": "^1.4.0",
"esutils": "^2.0.2", "esutils": "^2.0.2",
"fast-deep-equal": "^3.1.3", "fast-deep-equal": "^3.1.3",
"file-entry-cache": "^6.0.1", "file-entry-cache": "^6.0.1",
"find-up": "^5.0.0",
"functional-red-black-tree": "^1.0.1", "functional-red-black-tree": "^1.0.1",
"glob-parent": "^6.0.1", "glob-parent": "^6.0.1",
"globals": "^13.15.0", "globals": "^13.15.0",
"globby": "^11.1.0",
"grapheme-splitter": "^1.0.4",
"ignore": "^5.2.0", "ignore": "^5.2.0",
"import-fresh": "^3.0.0", "import-fresh": "^3.0.0",
"imurmurhash": "^0.1.4", "imurmurhash": "^0.1.4",
@ -3528,6 +3542,22 @@
"node": ">=4.0" "node": ">=4.0"
} }
}, },
"node_modules/eslint/node_modules/find-up": {
"version": "5.0.0",
"resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz",
"integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==",
"dev": true,
"dependencies": {
"locate-path": "^6.0.0",
"path-exists": "^4.0.0"
},
"engines": {
"node": ">=10"
},
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/eslint/node_modules/glob-parent": { "node_modules/eslint/node_modules/glob-parent": {
"version": "6.0.2", "version": "6.0.2",
"resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz",
@ -3540,18 +3570,75 @@
"node": ">=10.13.0" "node": ">=10.13.0"
} }
}, },
"node_modules/espree": { "node_modules/eslint/node_modules/locate-path": {
"version": "9.3.2", "version": "6.0.0",
"resolved": "https://registry.npmjs.org/espree/-/espree-9.3.2.tgz", "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz",
"integrity": "sha512-D211tC7ZwouTIuY5x9XnS0E9sWNChB7IYKX/Xp5eQj3nFXhqmiUDB9q27y76oFl8jTg3pXcQx/bpxMfs3CIZbA==", "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==",
"dev": true, "dev": true,
"dependencies": { "dependencies": {
"acorn": "^8.7.1", "p-locate": "^5.0.0"
},
"engines": {
"node": ">=10"
},
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/eslint/node_modules/p-limit": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz",
"integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==",
"dev": true,
"dependencies": {
"yocto-queue": "^0.1.0"
},
"engines": {
"node": ">=10"
},
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/eslint/node_modules/p-locate": {
"version": "5.0.0",
"resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz",
"integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==",
"dev": true,
"dependencies": {
"p-limit": "^3.0.2"
},
"engines": {
"node": ">=10"
},
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/eslint/node_modules/path-exists": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz",
"integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==",
"dev": true,
"engines": {
"node": ">=8"
}
},
"node_modules/espree": {
"version": "9.3.3",
"resolved": "https://registry.npmjs.org/espree/-/espree-9.3.3.tgz",
"integrity": "sha512-ORs1Rt/uQTqUKjDdGCyrtYxbazf5umATSf/K4qxjmZHORR6HJk+2s/2Pqe+Kk49HHINC/xNIrGfgh8sZcll0ng==",
"dev": true,
"dependencies": {
"acorn": "^8.8.0",
"acorn-jsx": "^5.3.2", "acorn-jsx": "^5.3.2",
"eslint-visitor-keys": "^3.3.0" "eslint-visitor-keys": "^3.3.0"
}, },
"engines": { "engines": {
"node": "^12.22.0 || ^14.17.0 || >=16.0.0" "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
},
"funding": {
"url": "https://opencollective.com/eslint"
} }
}, },
"node_modules/esquery": { "node_modules/esquery": {
@ -5083,6 +5170,12 @@
"resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.10.tgz", "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.10.tgz",
"integrity": "sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==" "integrity": "sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA=="
}, },
"node_modules/grapheme-splitter": {
"version": "1.0.4",
"resolved": "https://registry.npmjs.org/grapheme-splitter/-/grapheme-splitter-1.0.4.tgz",
"integrity": "sha512-bzh50DW9kTPM00T8y4o8vQg89Di9oLJVLW/KaOGIXJWP/iqCN6WKYkbNOF04vFLJhwcpYUh9ydh/+5vpOqV4YQ==",
"dev": true
},
"node_modules/gulp": { "node_modules/gulp": {
"version": "4.0.2", "version": "4.0.2",
"resolved": "https://registry.npmjs.org/gulp/-/gulp-4.0.2.tgz", "resolved": "https://registry.npmjs.org/gulp/-/gulp-4.0.2.tgz",
@ -8508,9 +8601,9 @@
"integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg=="
}, },
"node_modules/sass": { "node_modules/sass": {
"version": "1.54.0", "version": "1.54.3",
"resolved": "https://registry.npmjs.org/sass/-/sass-1.54.0.tgz", "resolved": "https://registry.npmjs.org/sass/-/sass-1.54.3.tgz",
"integrity": "sha512-C4zp79GCXZfK0yoHZg+GxF818/aclhp9F48XBu/+bm9vXEVAYov9iU3FBVRMq3Hx3OA4jfKL+p2K9180mEh0xQ==", "integrity": "sha512-fLodey5Qd41Pxp/Tk7Al97sViYwF/TazRc5t6E65O7JOk4XF8pzwIW7CvCxYVOfJFFI/1x5+elDyBIixrp+zrw==",
"dev": true, "dev": true,
"dependencies": { "dependencies": {
"chokidar": ">=3.0.0 <4.0.0", "chokidar": ">=3.0.0 <4.0.0",
@ -10543,6 +10636,18 @@
"node": ">=0.10.0" "node": ">=0.10.0"
} }
}, },
"node_modules/yocto-queue": {
"version": "0.1.0",
"resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz",
"integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==",
"dev": true,
"engines": {
"node": ">=10"
},
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/zxcvbn-typescript": { "node_modules/zxcvbn-typescript": {
"version": "5.0.1", "version": "5.0.1",
"resolved": "https://registry.npmjs.org/zxcvbn-typescript/-/zxcvbn-typescript-5.0.1.tgz", "resolved": "https://registry.npmjs.org/zxcvbn-typescript/-/zxcvbn-typescript-5.0.1.tgz",
@ -11041,9 +11146,9 @@
"integrity": "sha512-eYm8vijH/hpzr/6/1CJ/V/Eb1xQFW2nnUKArb3z+yUWv7HTwj6M7SP957oMjfZjAHU6qpoNc2wQvIxBLWYa/Jg==" "integrity": "sha512-eYm8vijH/hpzr/6/1CJ/V/Eb1xQFW2nnUKArb3z+yUWv7HTwj6M7SP957oMjfZjAHU6qpoNc2wQvIxBLWYa/Jg=="
}, },
"@humanwhocodes/config-array": { "@humanwhocodes/config-array": {
"version": "0.9.5", "version": "0.10.4",
"resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.9.5.tgz", "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.10.4.tgz",
"integrity": "sha512-ObyMyWxZiCu/yTisA7uzx81s40xR2fD5Cg/2Kq7G02ajkNubJf6BopgDTmDyc3U7sXpNKM8cYOw7s7Tyr+DnCw==", "integrity": "sha512-mXAIHxZT3Vcpg83opl1wGlVZ9xydbfZO3r5YfRSH6Gpp2J/PfdBP0wbDa2sO6/qRbcalpoevVyW6A/fI6LfeMw==",
"dev": true, "dev": true,
"requires": { "requires": {
"@humanwhocodes/object-schema": "^1.2.1", "@humanwhocodes/object-schema": "^1.2.1",
@ -11051,6 +11156,12 @@
"minimatch": "^3.0.4" "minimatch": "^3.0.4"
} }
}, },
"@humanwhocodes/gitignore-to-minimatch": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/@humanwhocodes/gitignore-to-minimatch/-/gitignore-to-minimatch-1.0.2.tgz",
"integrity": "sha512-rSqmMJDdLFUsyxR6FMtD00nfQKKLFb1kv+qBbOVKqErvloEIJLo5bDTJTQNTYgeyp78JsA7u/NPi5jT1GR/MuA==",
"dev": true
},
"@humanwhocodes/object-schema": { "@humanwhocodes/object-schema": {
"version": "1.2.1", "version": "1.2.1",
"resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-1.2.1.tgz", "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-1.2.1.tgz",
@ -11117,9 +11228,9 @@
} }
}, },
"@types/better-sqlite3": { "@types/better-sqlite3": {
"version": "7.5.0", "version": "7.6.0",
"resolved": "https://registry.npmjs.org/@types/better-sqlite3/-/better-sqlite3-7.5.0.tgz", "resolved": "https://registry.npmjs.org/@types/better-sqlite3/-/better-sqlite3-7.6.0.tgz",
"integrity": "sha512-G9ZbMjydW2yj1AgiPlUtdgF3a1qNpLJLudc9ynJCeJByS3XFWpmT9LT+VSHrKHFbxb31CvtYwetLTOvG9zdxdg==", "integrity": "sha512-rnSP9vY+fVsF3iJja5yRGBJV63PNBiezJlYrCkqUmQWFoB16cxAHwOkjsAYEu317miOfKaJpa65cbp0P4XJ/jw==",
"dev": true, "dev": true,
"requires": { "requires": {
"@types/node": "*" "@types/node": "*"
@ -11424,9 +11535,9 @@
"dev": true "dev": true
}, },
"@types/papaparse": { "@types/papaparse": {
"version": "5.3.2", "version": "5.3.3",
"resolved": "https://registry.npmjs.org/@types/papaparse/-/papaparse-5.3.2.tgz", "resolved": "https://registry.npmjs.org/@types/papaparse/-/papaparse-5.3.3.tgz",
"integrity": "sha512-BNbCHJkTE4RwmAFkCxEalET4mDvGr/1ld7ZtQ4i/laWI/iiVt+GL07stdvufle4KfywyvloqqpIiJscXNCrKxA==", "integrity": "sha512-i7fV8u843vb7nIGpcwdCsG3WjfBONeytRHK1mQL9d5KQAvFeAK2rRisDHicreYpoQ0MXocUDEqunKHTeXdvibg==",
"dev": true, "dev": true,
"requires": { "requires": {
"@types/node": "*" "@types/node": "*"
@ -11521,14 +11632,14 @@
} }
}, },
"@typescript-eslint/eslint-plugin": { "@typescript-eslint/eslint-plugin": {
"version": "5.31.0", "version": "5.32.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.31.0.tgz", "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.32.0.tgz",
"integrity": "sha512-VKW4JPHzG5yhYQrQ1AzXgVgX8ZAJEvCz0QI6mLRX4tf7rnFfh5D8SKm0Pq6w5PyNfAWJk6sv313+nEt3ohWMBQ==", "integrity": "sha512-CHLuz5Uz7bHP2WgVlvoZGhf0BvFakBJKAD/43Ty0emn4wXWv5k01ND0C0fHcl/Im8Td2y/7h44E9pca9qAu2ew==",
"dev": true, "dev": true,
"requires": { "requires": {
"@typescript-eslint/scope-manager": "5.31.0", "@typescript-eslint/scope-manager": "5.32.0",
"@typescript-eslint/type-utils": "5.31.0", "@typescript-eslint/type-utils": "5.32.0",
"@typescript-eslint/utils": "5.31.0", "@typescript-eslint/utils": "5.32.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 +11649,52 @@
} }
}, },
"@typescript-eslint/parser": { "@typescript-eslint/parser": {
"version": "5.31.0", "version": "5.32.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.31.0.tgz", "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.32.0.tgz",
"integrity": "sha512-UStjQiZ9OFTFReTrN+iGrC6O/ko9LVDhreEK5S3edmXgR396JGq7CoX2TWIptqt/ESzU2iRKXAHfSF2WJFcWHw==", "integrity": "sha512-IxRtsehdGV9GFQ35IGm5oKKR2OGcazUoiNBxhRV160iF9FoyuXxjY+rIqs1gfnd+4eL98OjeGnMpE7RF/NBb3A==",
"dev": true, "dev": true,
"requires": { "requires": {
"@typescript-eslint/scope-manager": "5.31.0", "@typescript-eslint/scope-manager": "5.32.0",
"@typescript-eslint/types": "5.31.0", "@typescript-eslint/types": "5.32.0",
"@typescript-eslint/typescript-estree": "5.31.0", "@typescript-eslint/typescript-estree": "5.32.0",
"debug": "^4.3.4" "debug": "^4.3.4"
} }
}, },
"@typescript-eslint/scope-manager": { "@typescript-eslint/scope-manager": {
"version": "5.31.0", "version": "5.32.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.31.0.tgz", "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.32.0.tgz",
"integrity": "sha512-8jfEzBYDBG88rcXFxajdVavGxb5/XKXyvWgvD8Qix3EEJLCFIdVloJw+r9ww0wbyNLOTYyBsR+4ALNGdlalLLg==", "integrity": "sha512-KyAE+tUON0D7tNz92p1uetRqVJiiAkeluvwvZOqBmW9z2XApmk5WSMV9FrzOroAcVxJZB3GfUwVKr98Dr/OjOg==",
"dev": true, "dev": true,
"requires": { "requires": {
"@typescript-eslint/types": "5.31.0", "@typescript-eslint/types": "5.32.0",
"@typescript-eslint/visitor-keys": "5.31.0" "@typescript-eslint/visitor-keys": "5.32.0"
} }
}, },
"@typescript-eslint/type-utils": { "@typescript-eslint/type-utils": {
"version": "5.31.0", "version": "5.32.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-5.31.0.tgz", "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-5.32.0.tgz",
"integrity": "sha512-7ZYqFbvEvYXFn9ax02GsPcEOmuWNg+14HIf4q+oUuLnMbpJ6eHAivCg7tZMVwzrIuzX3QCeAOqKoyMZCv5xe+w==", "integrity": "sha512-0gSsIhFDduBz3QcHJIp3qRCvVYbqzHg8D6bHFsDMrm0rURYDj+skBK2zmYebdCp+4nrd9VWd13egvhYFJj/wZg==",
"dev": true, "dev": true,
"requires": { "requires": {
"@typescript-eslint/utils": "5.31.0", "@typescript-eslint/utils": "5.32.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.31.0", "version": "5.32.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.31.0.tgz", "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.32.0.tgz",
"integrity": "sha512-/f/rMaEseux+I4wmR6mfpM2wvtNZb1p9hAV77hWfuKc3pmaANp5dLAZSiE3/8oXTYTt3uV9KW5yZKJsMievp6g==", "integrity": "sha512-EBUKs68DOcT/EjGfzywp+f8wG9Zw6gj6BjWu7KV/IYllqKJFPlZlLSYw/PTvVyiRw50t6wVbgv4p9uE2h6sZrQ==",
"dev": true "dev": true
}, },
"@typescript-eslint/typescript-estree": { "@typescript-eslint/typescript-estree": {
"version": "5.31.0", "version": "5.32.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.31.0.tgz", "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.32.0.tgz",
"integrity": "sha512-3S625TMcARX71wBc2qubHaoUwMEn+l9TCsaIzYI/ET31Xm2c9YQ+zhGgpydjorwQO9pLfR/6peTzS/0G3J/hDw==", "integrity": "sha512-ZVAUkvPk3ITGtCLU5J4atCw9RTxK+SRc6hXqLtllC2sGSeMFWN+YwbiJR9CFrSFJ3w4SJfcWtDwNb/DmUIHdhg==",
"dev": true, "dev": true,
"requires": { "requires": {
"@typescript-eslint/types": "5.31.0", "@typescript-eslint/types": "5.32.0",
"@typescript-eslint/visitor-keys": "5.31.0", "@typescript-eslint/visitor-keys": "5.32.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 +11703,26 @@
} }
}, },
"@typescript-eslint/utils": { "@typescript-eslint/utils": {
"version": "5.31.0", "version": "5.32.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.31.0.tgz", "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.32.0.tgz",
"integrity": "sha512-kcVPdQS6VIpVTQ7QnGNKMFtdJdvnStkqS5LeALr4rcwx11G6OWb2HB17NMPnlRHvaZP38hL9iK8DdE9Fne7NYg==", "integrity": "sha512-W7lYIAI5Zlc5K082dGR27Fczjb3Q57ECcXefKU/f0ajM5ToM0P+N9NmJWip8GmGu/g6QISNT+K6KYB+iSHjXCQ==",
"dev": true, "dev": true,
"requires": { "requires": {
"@types/json-schema": "^7.0.9", "@types/json-schema": "^7.0.9",
"@typescript-eslint/scope-manager": "5.31.0", "@typescript-eslint/scope-manager": "5.32.0",
"@typescript-eslint/types": "5.31.0", "@typescript-eslint/types": "5.32.0",
"@typescript-eslint/typescript-estree": "5.31.0", "@typescript-eslint/typescript-estree": "5.32.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.31.0", "version": "5.32.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.31.0.tgz", "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.32.0.tgz",
"integrity": "sha512-ZK0jVxSjS4gnPirpVjXHz7mgdOsZUHzNYSfTw2yPa3agfbt9YfqaBiBZFSSxeBWnpWkzCxTfUpnzA3Vily/CSg==", "integrity": "sha512-S54xOHZgfThiZ38/ZGTgB2rqx51CMJ5MCfVT2IplK4Q7hgzGfe0nLzLCcenDnc/cSjP568hdeKfeDcBgqNHD/g==",
"dev": true, "dev": true,
"requires": { "requires": {
"@typescript-eslint/types": "5.31.0", "@typescript-eslint/types": "5.32.0",
"eslint-visitor-keys": "^3.3.0" "eslint-visitor-keys": "^3.3.0"
} }
}, },
@ -11636,9 +11747,9 @@
} }
}, },
"acorn": { "acorn": {
"version": "8.7.1", "version": "8.8.0",
"resolved": "https://registry.npmjs.org/acorn/-/acorn-8.7.1.tgz", "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.8.0.tgz",
"integrity": "sha512-Xx54uLJQZ19lKygFXOWsscKUbsBZW0CPykPhVQdhIeIwrbPmJzqeASDInc8nKBnp/JT6igTs82qPXz069H8I/A==", "integrity": "sha512-QOxyigPVrpZ2GXT+PFyZTl6TtOFc5egxHIP9IlQ+RbupQuX4RkT/Bee4/kQuC02Xkzg84JcT7oLYtDIQxp+v7w==",
"dev": true "dev": true
}, },
"acorn-jsx": { "acorn-jsx": {
@ -13040,13 +13151,14 @@
"dev": true "dev": true
}, },
"eslint": { "eslint": {
"version": "8.20.0", "version": "8.21.0",
"resolved": "https://registry.npmjs.org/eslint/-/eslint-8.20.0.tgz", "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.21.0.tgz",
"integrity": "sha512-d4ixhz5SKCa1D6SCPrivP7yYVi7nyD6A4vs6HIAul9ujBzcEmZVM3/0NN/yu5nKhmO1wjp5xQ46iRfmDGlOviA==", "integrity": "sha512-/XJ1+Qurf1T9G2M5IHrsjp+xrGT73RZf23xA1z5wB1ZzzEAWSZKvRwhWxTFp1rvkvCfwcvAUNAP31bhKTTGfDA==",
"dev": true, "dev": true,
"requires": { "requires": {
"@eslint/eslintrc": "^1.3.0", "@eslint/eslintrc": "^1.3.0",
"@humanwhocodes/config-array": "^0.9.2", "@humanwhocodes/config-array": "^0.10.4",
"@humanwhocodes/gitignore-to-minimatch": "^1.0.2",
"ajv": "^6.10.0", "ajv": "^6.10.0",
"chalk": "^4.0.0", "chalk": "^4.0.0",
"cross-spawn": "^7.0.2", "cross-spawn": "^7.0.2",
@ -13056,14 +13168,17 @@
"eslint-scope": "^7.1.1", "eslint-scope": "^7.1.1",
"eslint-utils": "^3.0.0", "eslint-utils": "^3.0.0",
"eslint-visitor-keys": "^3.3.0", "eslint-visitor-keys": "^3.3.0",
"espree": "^9.3.2", "espree": "^9.3.3",
"esquery": "^1.4.0", "esquery": "^1.4.0",
"esutils": "^2.0.2", "esutils": "^2.0.2",
"fast-deep-equal": "^3.1.3", "fast-deep-equal": "^3.1.3",
"file-entry-cache": "^6.0.1", "file-entry-cache": "^6.0.1",
"find-up": "^5.0.0",
"functional-red-black-tree": "^1.0.1", "functional-red-black-tree": "^1.0.1",
"glob-parent": "^6.0.1", "glob-parent": "^6.0.1",
"globals": "^13.15.0", "globals": "^13.15.0",
"globby": "^11.1.0",
"grapheme-splitter": "^1.0.4",
"ignore": "^5.2.0", "ignore": "^5.2.0",
"import-fresh": "^3.0.0", "import-fresh": "^3.0.0",
"imurmurhash": "^0.1.4", "imurmurhash": "^0.1.4",
@ -13098,6 +13213,16 @@
"integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==",
"dev": true "dev": true
}, },
"find-up": {
"version": "5.0.0",
"resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz",
"integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==",
"dev": true,
"requires": {
"locate-path": "^6.0.0",
"path-exists": "^4.0.0"
}
},
"glob-parent": { "glob-parent": {
"version": "6.0.2", "version": "6.0.2",
"resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz",
@ -13106,6 +13231,39 @@
"requires": { "requires": {
"is-glob": "^4.0.3" "is-glob": "^4.0.3"
} }
},
"locate-path": {
"version": "6.0.0",
"resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz",
"integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==",
"dev": true,
"requires": {
"p-locate": "^5.0.0"
}
},
"p-limit": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz",
"integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==",
"dev": true,
"requires": {
"yocto-queue": "^0.1.0"
}
},
"p-locate": {
"version": "5.0.0",
"resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz",
"integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==",
"dev": true,
"requires": {
"p-limit": "^3.0.2"
}
},
"path-exists": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz",
"integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==",
"dev": true
} }
} }
}, },
@ -13325,12 +13483,12 @@
"dev": true "dev": true
}, },
"espree": { "espree": {
"version": "9.3.2", "version": "9.3.3",
"resolved": "https://registry.npmjs.org/espree/-/espree-9.3.2.tgz", "resolved": "https://registry.npmjs.org/espree/-/espree-9.3.3.tgz",
"integrity": "sha512-D211tC7ZwouTIuY5x9XnS0E9sWNChB7IYKX/Xp5eQj3nFXhqmiUDB9q27y76oFl8jTg3pXcQx/bpxMfs3CIZbA==", "integrity": "sha512-ORs1Rt/uQTqUKjDdGCyrtYxbazf5umATSf/K4qxjmZHORR6HJk+2s/2Pqe+Kk49HHINC/xNIrGfgh8sZcll0ng==",
"dev": true, "dev": true,
"requires": { "requires": {
"acorn": "^8.7.1", "acorn": "^8.8.0",
"acorn-jsx": "^5.3.2", "acorn-jsx": "^5.3.2",
"eslint-visitor-keys": "^3.3.0" "eslint-visitor-keys": "^3.3.0"
} }
@ -14566,6 +14724,12 @@
"resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.10.tgz", "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.10.tgz",
"integrity": "sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==" "integrity": "sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA=="
}, },
"grapheme-splitter": {
"version": "1.0.4",
"resolved": "https://registry.npmjs.org/grapheme-splitter/-/grapheme-splitter-1.0.4.tgz",
"integrity": "sha512-bzh50DW9kTPM00T8y4o8vQg89Di9oLJVLW/KaOGIXJWP/iqCN6WKYkbNOF04vFLJhwcpYUh9ydh/+5vpOqV4YQ==",
"dev": true
},
"gulp": { "gulp": {
"version": "4.0.2", "version": "4.0.2",
"resolved": "https://registry.npmjs.org/gulp/-/gulp-4.0.2.tgz", "resolved": "https://registry.npmjs.org/gulp/-/gulp-4.0.2.tgz",
@ -17176,9 +17340,9 @@
"integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg=="
}, },
"sass": { "sass": {
"version": "1.54.0", "version": "1.54.3",
"resolved": "https://registry.npmjs.org/sass/-/sass-1.54.0.tgz", "resolved": "https://registry.npmjs.org/sass/-/sass-1.54.3.tgz",
"integrity": "sha512-C4zp79GCXZfK0yoHZg+GxF818/aclhp9F48XBu/+bm9vXEVAYov9iU3FBVRMq3Hx3OA4jfKL+p2K9180mEh0xQ==", "integrity": "sha512-fLodey5Qd41Pxp/Tk7Al97sViYwF/TazRc5t6E65O7JOk4XF8pzwIW7CvCxYVOfJFFI/1x5+elDyBIixrp+zrw==",
"dev": true, "dev": true,
"requires": { "requires": {
"chokidar": ">=3.0.0 <4.0.0", "chokidar": ">=3.0.0 <4.0.0",
@ -18819,6 +18983,12 @@
"object.assign": "^4.1.0" "object.assign": "^4.1.0"
} }
}, },
"yocto-queue": {
"version": "0.1.0",
"resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz",
"integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==",
"dev": true
},
"zxcvbn-typescript": { "zxcvbn-typescript": {
"version": "5.0.1", "version": "5.0.1",
"resolved": "https://registry.npmjs.org/zxcvbn-typescript/-/zxcvbn-typescript-5.0.1.tgz", "resolved": "https://registry.npmjs.org/zxcvbn-typescript/-/zxcvbn-typescript-5.0.1.tgz",

View File

@ -53,7 +53,7 @@
"@cityssm/bulma-webapp-css": "^0.11.0", "@cityssm/bulma-webapp-css": "^0.11.0",
"@cityssm/mssql-multi-pool": "^2.1.6", "@cityssm/mssql-multi-pool": "^2.1.6",
"@types/activedirectory2": "^1.2.3", "@types/activedirectory2": "^1.2.3",
"@types/better-sqlite3": "^7.5.0", "@types/better-sqlite3": "^7.6.0",
"@types/compression": "^1.7.2", "@types/compression": "^1.7.2",
"@types/cookie-parser": "^1.4.3", "@types/cookie-parser": "^1.4.3",
"@types/csurf": "^1.11.2", "@types/csurf": "^1.11.2",
@ -70,12 +70,12 @@
"@types/mocha": "^9.1.1", "@types/mocha": "^9.1.1",
"@types/mssql": "^8.0.3", "@types/mssql": "^8.0.3",
"@types/node-windows": "^0.1.2", "@types/node-windows": "^0.1.2",
"@types/papaparse": "^5.3.2", "@types/papaparse": "^5.3.3",
"@types/session-file-store": "^1.2.2", "@types/session-file-store": "^1.2.2",
"@typescript-eslint/eslint-plugin": "^5.31.0", "@typescript-eslint/eslint-plugin": "^5.32.0",
"@typescript-eslint/parser": "^5.31.0", "@typescript-eslint/parser": "^5.32.0",
"bulma": "^0.9.4", "bulma": "^0.9.4",
"eslint": "^8.20.0", "eslint": "^8.21.0",
"eslint-plugin-import": "^2.26.0", "eslint-plugin-import": "^2.26.0",
"eslint-plugin-node": "^11.1.0", "eslint-plugin-node": "^11.1.0",
"eslint-plugin-promise": "^6.0.0", "eslint-plugin-promise": "^6.0.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.54.0" "sass": "^1.54.3"
} }
} }

View File

@ -12,6 +12,10 @@ $black: #000;
width: 10px; width: 10px;
} }
.has-min-page-height {
min-height: 100vh;
}
/* /*
* Status containers * Status containers
*/ */

View File

@ -34,6 +34,11 @@ Object.defineProperty(exports, "__esModule", { value: true });
let lotComments = exports.lotComments; let lotComments = exports.lotComments;
const renderLotComments = () => { const renderLotComments = () => {
const lotCommentsContainerElement = document.querySelector("#container--lotComments"); const lotCommentsContainerElement = document.querySelector("#container--lotComments");
if (lotComments.length === 0) {
lotCommentsContainerElement.innerHTML = "<div class=\"message is-info\">" +
"<p class=\"message-body\">There are no comments to display.</p>" +
"</div>";
}
}; };
const openAddCommentModal = () => { const openAddCommentModal = () => {
let addCommentCloseModalFunction; let addCommentCloseModalFunction;

View File

@ -65,6 +65,12 @@ declare const bulmaJS: BulmaJS;
const renderLotComments = () => { const renderLotComments = () => {
const lotCommentsContainerElement = document.querySelector("#container--lotComments") as HTMLElement; const lotCommentsContainerElement = document.querySelector("#container--lotComments") as HTMLElement;
if (lotComments.length === 0) {
lotCommentsContainerElement.innerHTML = "<div class=\"message is-info\">" +
"<p class=\"message-body\">There are no comments to display.</p>" +
"</div>";
}
}; };
const openAddCommentModal = () => { const openAddCommentModal = () => {

View File

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

View File

@ -0,0 +1,127 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
(() => {
const urlPrefix = document.querySelector("main").dataset.urlPrefix;
const searchFilterFormElement = document.querySelector("#form--searchFilters");
const searchResultsContainerElement = document.querySelector("#container--searchResults");
const limit = Number.parseInt(document.querySelector("#searchFilter--limit").value, 10);
const offsetElement = document.querySelector("#searchFilter--offset");
const getLotOccupancies = () => {
const offset = Number.parseInt(offsetElement.value, 10);
searchResultsContainerElement.innerHTML = "<div class=\"has-text-grey has-text-centered\">" +
"<i class=\"fas fa-5x fa-circle-notch fa-spin\" aria-hidden=\"true\"></i><br />" +
"Loading " + exports.aliases.occupancies + "..." +
"</div>";
cityssm.postJSON(urlPrefix + "/lotOccupancies/doSearchLotOccupancies", searchFilterFormElement, (responseJSON) => {
if (responseJSON.lotOccupancies.length === 0) {
searchResultsContainerElement.innerHTML = "<div class=\"message is-info\">" +
"<p class=\"message-body\">There are no " + exports.aliases.occupancy.toLowerCase() + " records that meet the search criteria.</p>" +
"</div>";
return;
}
const resultsTbodyElement = document.createElement("tbody");
const nowDateString = cityssm.dateToString(new Date());
for (const lotOccupancy of responseJSON.lotOccupancies) {
let occupancyTimeHTML = "";
if (lotOccupancy.occupancyStartDateString <= nowDateString && (lotOccupancy.occupancyEndDateString === "" || lotOccupancy.occupancyEndDateString >= nowDateString)) {
occupancyTimeHTML = "<i class=\"fas fa-play\" title=\"Current " + exports.aliases.occupancy + "\"></i>";
}
else if (lotOccupancy.occupancyStartDateString > nowDateString) {
occupancyTimeHTML = "<i class=\"fas fa-fast-forward\" title=\"Future " + exports.aliases.occupancy + "\"></i>";
}
else {
occupancyTimeHTML = "<i class=\"fas fa-stop\" title=\"Previous " + exports.aliases.occupancy + "\"></i>";
}
let occupantsHTML = "";
for (const occupant of lotOccupancy.lotOccupancyOccupants) {
occupantsHTML += cityssm.escapeHTML(occupant.occupantName) + "<br />";
}
resultsTbodyElement.insertAdjacentHTML("beforeend", "<tr>" +
"<td>" + occupancyTimeHTML + "</td>" +
("<td>" +
"<a class=\"has-text-weight-bold\" href=\"" + urlPrefix + "/lotOccupancies/" + lotOccupancy.lotOccupancyId + "\">" +
cityssm.escapeHTML(lotOccupancy.occupancyType) +
"</a>" +
"</td>") +
("<td>" +
cityssm.escapeHTML(lotOccupancy.lotName) + "<br />" +
"<span class=\"is-size-7\">" + cityssm.escapeHTML(lotOccupancy.mapName) + "</span>" +
"</td>") +
("<td>" +
lotOccupancy.occupancyStartDateString +
"</td>") +
("<td>" +
(lotOccupancy.occupancyEndDate ?
lotOccupancy.occupancyEndDateString :
"(No End Date)") +
"</td>") +
"<td>" + occupantsHTML + "</td>" +
"</tr>");
}
searchResultsContainerElement.innerHTML = "<table class=\"table is-fullwidth is-striped is-hoverable\">" +
"<thead><tr>" +
"<th></th>" +
"<th>" + exports.aliases.occupancy + " Type</th>" +
"<th>" + exports.aliases.lot + "</th>" +
"<th>Start Date</th>" +
"<th>End Date</th>" +
"<th>" + exports.aliases.occupants + "</th>" +
"</tr></thead>" +
"<table>" +
"<div class=\"level\">" +
("<div class=\"level-left\">" +
"<div class=\"level-item has-text-weight-bold\">" +
"Displaying " + (offset + 1).toString() +
" to " + Math.min(responseJSON.count, limit + offset) +
" of " + responseJSON.count +
"</div>" +
"</div>") +
("<div class=\"level-right\">" +
(offset > 0 ?
"<div class=\"level-item\">" +
"<button class=\"button is-rounded is-link is-outlined\" data-page=\"previous\" type=\"button\" title=\"Previous\">" +
"<i class=\"fas fa-arrow-left\" aria-hidden=\"true\"></i>" +
"</button>" +
"</div>" :
"") +
(limit + offset < responseJSON.count ?
"<div class=\"level-item\">" +
"<button class=\"button is-rounded is-link\" data-page=\"next\" type=\"button\" title=\"Next\">" +
"<span>Next</span>" +
"<span class=\"icon\"><i class=\"fas fa-arrow-right\" aria-hidden=\"true\"></i></span>" +
"</button>" +
"</div>" :
"") +
"</div>") +
"</div>";
searchResultsContainerElement.querySelector("table").append(resultsTbodyElement);
if (offset > 0) {
searchResultsContainerElement.querySelector("button[data-page='previous']").addEventListener("click", previousAndGetLotOccupancies);
}
if (limit + offset < responseJSON.count) {
searchResultsContainerElement.querySelector("button[data-page='next']").addEventListener("click", nextAndGetLotOccupancies);
}
});
};
const resetOffsetAndGetLotOccupancies = () => {
offsetElement.value = "0";
getLotOccupancies();
};
const previousAndGetLotOccupancies = () => {
offsetElement.value = Math.max(Number.parseInt(offsetElement.value, 10) - limit, 0).toString();
getLotOccupancies();
};
const nextAndGetLotOccupancies = () => {
offsetElement.value = (Number.parseInt(offsetElement.value, 10) + limit).toString();
getLotOccupancies();
};
const filterElements = searchFilterFormElement.querySelectorAll("input, select");
for (const filterElement of filterElements) {
filterElement.addEventListener("change", resetOffsetAndGetLotOccupancies);
}
searchFilterFormElement.addEventListener("submit", (formEvent) => {
formEvent.preventDefault();
resetOffsetAndGetLotOccupancies();
});
getLotOccupancies();
})();

View File

@ -0,0 +1,170 @@
/* eslint-disable unicorn/prefer-module */
import type * as recordTypes from "../types/recordTypes";
import type {
cityssmGlobal
} from "@cityssm/bulma-webapp-js/src/types";
declare const cityssm: cityssmGlobal;
(() => {
const urlPrefix = document.querySelector("main").dataset.urlPrefix;
const searchFilterFormElement = document.querySelector("#form--searchFilters") as HTMLFormElement;
const searchResultsContainerElement = document.querySelector("#container--searchResults") as HTMLElement;
const limit = Number.parseInt((document.querySelector("#searchFilter--limit") as HTMLInputElement).value, 10);
const offsetElement = document.querySelector("#searchFilter--offset") as HTMLInputElement;
const getLotOccupancies = () => {
const offset = Number.parseInt(offsetElement.value, 10);
searchResultsContainerElement.innerHTML = "<div class=\"has-text-grey has-text-centered\">" +
"<i class=\"fas fa-5x fa-circle-notch fa-spin\" aria-hidden=\"true\"></i><br />" +
"Loading " + exports.aliases.occupancies + "..." +
"</div>";
cityssm.postJSON(urlPrefix + "/lotOccupancies/doSearchLotOccupancies", searchFilterFormElement,
(responseJSON: {
count: number;
lotOccupancies: recordTypes.LotOccupancy[];
}) => {
if (responseJSON.lotOccupancies.length === 0) {
searchResultsContainerElement.innerHTML = "<div class=\"message is-info\">" +
"<p class=\"message-body\">There are no " + exports.aliases.occupancy.toLowerCase() + " records that meet the search criteria.</p>" +
"</div>";
return;
}
const resultsTbodyElement = document.createElement("tbody");
const nowDateString = cityssm.dateToString(new Date());
for (const lotOccupancy of responseJSON.lotOccupancies) {
let occupancyTimeHTML = "";
if (lotOccupancy.occupancyStartDateString <= nowDateString && (lotOccupancy.occupancyEndDateString === "" || lotOccupancy.occupancyEndDateString >= nowDateString)) {
occupancyTimeHTML = "<i class=\"fas fa-play\" title=\"Current " + exports.aliases.occupancy + "\"></i>";
} else if (lotOccupancy.occupancyStartDateString > nowDateString) {
occupancyTimeHTML = "<i class=\"fas fa-fast-forward\" title=\"Future " + exports.aliases.occupancy + "\"></i>";
} else {
occupancyTimeHTML = "<i class=\"fas fa-stop\" title=\"Previous " + exports.aliases.occupancy + "\"></i>";
}
let occupantsHTML = "";
for (const occupant of lotOccupancy.lotOccupancyOccupants) {
occupantsHTML += cityssm.escapeHTML(occupant.occupantName) + "<br />";
}
resultsTbodyElement.insertAdjacentHTML("beforeend", "<tr>" +
"<td>" + occupancyTimeHTML + "</td>" +
("<td>" +
"<a class=\"has-text-weight-bold\" href=\"" + urlPrefix + "/lotOccupancies/" + lotOccupancy.lotOccupancyId + "\">" +
cityssm.escapeHTML(lotOccupancy.occupancyType as string) +
"</a>" +
"</td>") +
("<td>" +
cityssm.escapeHTML(lotOccupancy.lotName) + "<br />" +
"<span class=\"is-size-7\">" + cityssm.escapeHTML(lotOccupancy.mapName) + "</span>" +
"</td>") +
("<td>" +
lotOccupancy.occupancyStartDateString +
"</td>") +
("<td>" +
(lotOccupancy.occupancyEndDate ?
lotOccupancy.occupancyEndDateString :
"(No End Date)") +
"</td>") +
"<td>" + occupantsHTML + "</td>" +
"</tr>");
}
searchResultsContainerElement.innerHTML = "<table class=\"table is-fullwidth is-striped is-hoverable\">" +
"<thead><tr>" +
"<th></th>" +
"<th>" + exports.aliases.occupancy + " Type</th>" +
"<th>" + exports.aliases.lot + "</th>" +
"<th>Start Date</th>" +
"<th>End Date</th>" +
"<th>" + exports.aliases.occupants + "</th>" +
"</tr></thead>" +
"<table>" +
"<div class=\"level\">" +
("<div class=\"level-left\">" +
"<div class=\"level-item has-text-weight-bold\">" +
"Displaying " + (offset + 1).toString() +
" to " + Math.min(responseJSON.count, limit + offset) +
" of " + responseJSON.count +
"</div>" +
"</div>") +
("<div class=\"level-right\">" +
(offset > 0 ?
"<div class=\"level-item\">" +
"<button class=\"button is-rounded is-link is-outlined\" data-page=\"previous\" type=\"button\" title=\"Previous\">" +
"<i class=\"fas fa-arrow-left\" aria-hidden=\"true\"></i>" +
"</button>" +
"</div>" :
"") +
(limit + offset < responseJSON.count ?
"<div class=\"level-item\">" +
"<button class=\"button is-rounded is-link\" data-page=\"next\" type=\"button\" title=\"Next\">" +
"<span>Next</span>" +
"<span class=\"icon\"><i class=\"fas fa-arrow-right\" aria-hidden=\"true\"></i></span>" +
"</button>" +
"</div>" :
"") +
"</div>") +
"</div>";
searchResultsContainerElement.querySelector("table").append(resultsTbodyElement);
if (offset > 0) {
searchResultsContainerElement.querySelector("button[data-page='previous']").addEventListener("click", previousAndGetLotOccupancies);
}
if (limit + offset < responseJSON.count) {
searchResultsContainerElement.querySelector("button[data-page='next']").addEventListener("click", nextAndGetLotOccupancies);
}
});
};
const resetOffsetAndGetLotOccupancies = () => {
offsetElement.value = "0";
getLotOccupancies();
}
const previousAndGetLotOccupancies = () => {
offsetElement.value = Math.max(Number.parseInt(offsetElement.value, 10) - limit, 0).toString();
getLotOccupancies();
};
const nextAndGetLotOccupancies = () => {
offsetElement.value = (Number.parseInt(offsetElement.value, 10) + limit).toString();
getLotOccupancies();
};
const filterElements = searchFilterFormElement.querySelectorAll("input, select") as NodeListOf < HTMLInputElement | HTMLSelectElement > ;
for (const filterElement of filterElements) {
filterElement.addEventListener("change", resetOffsetAndGetLotOccupancies);
}
searchFilterFormElement.addEventListener("submit", (formEvent) => {
formEvent.preventDefault();
resetOffsetAndGetLotOccupancies();
});
getLotOccupancies();
})();

View File

@ -31,7 +31,7 @@
inkscape:window-x="-8" inkscape:window-x="-8"
inkscape:window-y="-8" inkscape:window-y="-8"
inkscape:window-maximized="1" inkscape:window-maximized="1"
inkscape:current-layer="surface1" /> inkscape:current-layer="HS-H-9N" />
<defs <defs
id="defs334"> id="defs334">
<g <g
@ -2244,36 +2244,36 @@
style=" stroke:none;fill-rule:nonzero;fill:rgb(0%,0%,0%);fill-opacity:1;" style=" stroke:none;fill-rule:nonzero;fill:rgb(0%,0%,0%);fill-opacity:1;"
d="M 43.511719 472.980469 L 43.511719 360.289063 L 46.039063 360.289063 L 46.039063 472.980469 L 43.511719 472.980469 M 43.511719 360.289063 L 43.511719 359.050781 L 44.832031 359.050781 L 44.832031 360.289063 L 43.511719 360.289063 M 44.832031 359.050781 L 261.71875 359.050781 L 261.71875 361.441406 L 44.832031 361.441406 L 44.832031 359.050781 M 261.71875 359.050781 L 263.039063 359.050781 L 263.039063 360.289063 L 261.71875 360.289063 L 261.71875 359.050781 M 263.039063 360.289063 L 263.039063 472.980469 L 260.398438 472.980469 L 260.398438 360.289063 L 263.039063 360.289063 M 263.039063 472.980469 L 263.039063 474.21875 L 261.71875 474.21875 L 261.71875 472.980469 L 263.039063 472.980469 M 261.71875 474.21875 L 44.832031 474.21875 L 44.832031 471.730469 L 261.71875 471.730469 L 261.71875 474.21875 M 44.832031 474.21875 L 43.511719 474.21875 L 43.511719 472.980469 L 44.832031 472.980469 L 44.832031 474.21875 " d="M 43.511719 472.980469 L 43.511719 360.289063 L 46.039063 360.289063 L 46.039063 472.980469 L 43.511719 472.980469 M 43.511719 360.289063 L 43.511719 359.050781 L 44.832031 359.050781 L 44.832031 360.289063 L 43.511719 360.289063 M 44.832031 359.050781 L 261.71875 359.050781 L 261.71875 361.441406 L 44.832031 361.441406 L 44.832031 359.050781 M 261.71875 359.050781 L 263.039063 359.050781 L 263.039063 360.289063 L 261.71875 360.289063 L 261.71875 359.050781 M 263.039063 360.289063 L 263.039063 472.980469 L 260.398438 472.980469 L 260.398438 360.289063 L 263.039063 360.289063 M 263.039063 472.980469 L 263.039063 474.21875 L 261.71875 474.21875 L 261.71875 472.980469 L 263.039063 472.980469 M 261.71875 474.21875 L 44.832031 474.21875 L 44.832031 471.730469 L 261.71875 471.730469 L 261.71875 474.21875 M 44.832031 474.21875 L 43.511719 474.21875 L 43.511719 472.980469 L 44.832031 472.980469 L 44.832031 474.21875 "
id="path386" /> id="path386" />
<path
style="fill:none;stroke-width:3.2086;stroke-linecap:round;stroke-linejoin:round;stroke:rgb(0%,0%,0%);stroke-opacity:1;stroke-miterlimit:10;"
d="M 1183.398438 4893.007813 L 1543.710938 4893.007813 L 1543.710938 6027.109375 L 1183.398438 6027.109375 Z M 1183.398438 4893.007813 "
transform="matrix(0.1,0,0,-0.1,0,963)"
id="path1392" />
<path
style="fill:none;stroke-width:3.2086;stroke-linecap:round;stroke-linejoin:round;stroke:rgb(0%,0%,0%);stroke-opacity:1;stroke-miterlimit:10;"
d="M 1543.710938 4893.007813 L 1904.101563 4893.007813 L 1904.101563 6027.109375 L 1543.710938 6027.109375 Z M 1543.710938 4893.007813 "
transform="matrix(0.1,0,0,-0.1,0,963)"
id="path1394" />
<path
style="fill:none;stroke-width:3.2086;stroke-linecap:round;stroke-linejoin:round;stroke:rgb(0%,0%,0%);stroke-opacity:1;stroke-miterlimit:10;"
d="M 1905.195313 4893.007813 L 2265.585938 4893.007813 L 2265.585938 6027.109375 L 1905.195313 6027.109375 Z M 1905.195313 4893.007813 "
transform="matrix(0.1,0,0,-0.1,0,963)"
id="path1400" />
<path
style="fill:none;stroke-width:3.2086;stroke-linecap:round;stroke-linejoin:round;stroke:rgb(0%,0%,0%);stroke-opacity:1;stroke-miterlimit:10;"
d="M 2265.585938 4893.007813 L 2626.015625 4893.007813 L 2626.015625 6027.109375 L 2265.585938 6027.109375 Z M 2265.585938 4893.007813 "
transform="matrix(0.1,0,0,-0.1,0,963)"
id="path1402" />
<path <path
style="fill:none;stroke-width:3.2086;stroke-linecap:round;stroke-linejoin:round;stroke:rgb(0%,0%,0%);stroke-opacity:1;stroke-miterlimit:10;" style="fill:none;stroke-width:3.2086;stroke-linecap:round;stroke-linejoin:round;stroke:rgb(0%,0%,0%);stroke-opacity:1;stroke-miterlimit:10;"
d="M 457.109375 4893.007813 L 817.5 4893.007813 L 817.5 6027.109375 L 457.109375 6027.109375 Z M 457.109375 4893.007813 " d="M 457.109375 4893.007813 L 817.5 4893.007813 L 817.5 6027.109375 L 457.109375 6027.109375 Z M 457.109375 4893.007813 "
transform="matrix(0.1,0,0,-0.1,0,963)" transform="matrix(0.1,0,0,-0.1,0,963)"
id="path1420" /> id="HS-H-9N-1" />
<path <path
style="fill:none;stroke-width:3.2086;stroke-linecap:round;stroke-linejoin:round;stroke:rgb(0%,0%,0%);stroke-opacity:1;stroke-miterlimit:10;" style="fill:none;stroke-width:3.2086;stroke-linecap:round;stroke-linejoin:round;stroke:rgb(0%,0%,0%);stroke-opacity:1;stroke-miterlimit:10;"
d="M 817.5 4893.007813 L 1177.890625 4893.007813 L 1177.890625 6027.109375 L 817.5 6027.109375 Z M 817.5 4893.007813 " d="M 817.5 4893.007813 L 1177.890625 4893.007813 L 1177.890625 6027.109375 L 817.5 6027.109375 Z M 817.5 4893.007813 "
transform="matrix(0.1,0,0,-0.1,0,963)" transform="matrix(0.1,0,0,-0.1,0,963)"
id="path1422" /> id="HS-H-9N-2" />
<path
style="fill:none;stroke-width:3.2086;stroke-linecap:round;stroke-linejoin:round;stroke:rgb(0%,0%,0%);stroke-opacity:1;stroke-miterlimit:10;"
d="M 1183.398438 4893.007813 L 1543.710938 4893.007813 L 1543.710938 6027.109375 L 1183.398438 6027.109375 Z M 1183.398438 4893.007813 "
transform="matrix(0.1,0,0,-0.1,0,963)"
id="HS-H-9N-3" />
<path
style="fill:none;stroke-width:3.2086;stroke-linecap:round;stroke-linejoin:round;stroke:rgb(0%,0%,0%);stroke-opacity:1;stroke-miterlimit:10;"
d="M 1543.710938 4893.007813 L 1904.101563 4893.007813 L 1904.101563 6027.109375 L 1543.710938 6027.109375 Z M 1543.710938 4893.007813 "
transform="matrix(0.1,0,0,-0.1,0,963)"
id="HS-H-9N-3A" />
<path
style="fill:none;stroke-width:3.2086;stroke-linecap:round;stroke-linejoin:round;stroke:rgb(0%,0%,0%);stroke-opacity:1;stroke-miterlimit:10;"
d="M 1905.195313 4893.007813 L 2265.585938 4893.007813 L 2265.585938 6027.109375 L 1905.195313 6027.109375 Z M 1905.195313 4893.007813 "
transform="matrix(0.1,0,0,-0.1,0,963)"
id="HS-H-9N-4" />
<path
style="fill:none;stroke-width:3.2086;stroke-linecap:round;stroke-linejoin:round;stroke:rgb(0%,0%,0%);stroke-opacity:1;stroke-miterlimit:10;"
d="M 2265.585938 4893.007813 L 2626.015625 4893.007813 L 2626.015625 6027.109375 L 2265.585938 6027.109375 Z M 2265.585938 4893.007813 "
transform="matrix(0.1,0,0,-0.1,0,963)"
id="HS-H-9N-4A" />
<path <path
style=" stroke:none;fill-rule:evenodd;fill:rgb(100%,100%,100%);fill-opacity:1;" style=" stroke:none;fill-rule:evenodd;fill:rgb(100%,100%,100%);fill-opacity:1;"
d="M 155.46875 391.371094 L 158.550781 391.480469 L 161.519531 391.691406 L 164.480469 392.210938 L 167.230469 392.828125 L 169.871094 393.660156 L 172.390625 394.601563 L 174.699219 395.738281 L 176.789063 396.878906 L 177.78125 397.609375 L 178.769531 398.238281 L 179.648438 398.960938 L 180.519531 399.789063 L 181.289063 400.519531 L 182.058594 401.351563 L 182.71875 402.191406 L 183.269531 403.019531 L 183.820313 403.851563 L 184.371094 404.78125 L 184.699219 405.621094 L 185.03125 406.550781 L 185.359375 407.488281 L 185.578125 408.421875 L 185.691406 409.460938 L 185.691406 411.441406 L 185.578125 412.371094 L 185.359375 413.308594 L 185.03125 414.238281 L 184.699219 415.179688 L 184.371094 416.109375 L 183.820313 416.949219 L 183.269531 417.878906 L 182.71875 418.710938 L 182.058594 419.550781 L 181.289063 420.269531 L 180.519531 421.101563 L 179.648438 421.828125 L 178.769531 422.558594 L 177.78125 423.179688 L 176.789063 423.910156 L 174.699219 425.160156 L 172.390625 426.199219 L 169.871094 427.128906 L 167.230469 427.96875 L 164.480469 428.589844 L 161.519531 429.109375 L 158.550781 429.421875 L 155.46875 429.519531 L 152.398438 429.421875 L 149.320313 429.109375 L 146.460938 428.589844 L 143.71875 427.96875 L 141.078125 427.128906 L 138.550781 426.199219 L 136.25 425.160156 L 134.050781 423.910156 L 133.058594 423.179688 L 132.070313 422.558594 L 131.191406 421.828125 L 130.421875 421.101563 L 129.539063 420.269531 L 128.878906 419.550781 L 128.21875 418.710938 L 127.558594 417.878906 L 127.019531 416.949219 L 126.578125 416.109375 L 126.140625 415.179688 L 125.808594 414.238281 L 125.589844 413.308594 L 125.371094 412.371094 L 125.261719 411.441406 L 125.261719 409.460938 L 125.371094 408.421875 L 125.589844 407.488281 L 125.808594 406.550781 L 126.140625 405.621094 L 126.578125 404.78125 L 127.019531 403.851563 L 127.558594 403.019531 L 128.21875 402.191406 L 128.878906 401.351563 L 129.539063 400.519531 L 130.421875 399.789063 L 131.191406 398.960938 L 132.070313 398.238281 L 133.058594 397.609375 L 134.050781 396.878906 L 136.25 395.738281 L 138.550781 394.601563 L 141.078125 393.660156 L 143.71875 392.828125 L 146.460938 392.210938 L 149.320313 391.691406 L 152.398438 391.480469 L 155.46875 391.371094 " d="M 155.46875 391.371094 L 158.550781 391.480469 L 161.519531 391.691406 L 164.480469 392.210938 L 167.230469 392.828125 L 169.871094 393.660156 L 172.390625 394.601563 L 174.699219 395.738281 L 176.789063 396.878906 L 177.78125 397.609375 L 178.769531 398.238281 L 179.648438 398.960938 L 180.519531 399.789063 L 181.289063 400.519531 L 182.058594 401.351563 L 182.71875 402.191406 L 183.269531 403.019531 L 183.820313 403.851563 L 184.371094 404.78125 L 184.699219 405.621094 L 185.03125 406.550781 L 185.359375 407.488281 L 185.578125 408.421875 L 185.691406 409.460938 L 185.691406 411.441406 L 185.578125 412.371094 L 185.359375 413.308594 L 185.03125 414.238281 L 184.699219 415.179688 L 184.371094 416.109375 L 183.820313 416.949219 L 183.269531 417.878906 L 182.71875 418.710938 L 182.058594 419.550781 L 181.289063 420.269531 L 180.519531 421.101563 L 179.648438 421.828125 L 178.769531 422.558594 L 177.78125 423.179688 L 176.789063 423.910156 L 174.699219 425.160156 L 172.390625 426.199219 L 169.871094 427.128906 L 167.230469 427.96875 L 164.480469 428.589844 L 161.519531 429.109375 L 158.550781 429.421875 L 155.46875 429.519531 L 152.398438 429.421875 L 149.320313 429.109375 L 146.460938 428.589844 L 143.71875 427.96875 L 141.078125 427.128906 L 138.550781 426.199219 L 136.25 425.160156 L 134.050781 423.910156 L 133.058594 423.179688 L 132.070313 422.558594 L 131.191406 421.828125 L 130.421875 421.101563 L 129.539063 420.269531 L 128.878906 419.550781 L 128.21875 418.710938 L 127.558594 417.878906 L 127.019531 416.949219 L 126.578125 416.109375 L 126.140625 415.179688 L 125.808594 414.238281 L 125.589844 413.308594 L 125.371094 412.371094 L 125.261719 411.441406 L 125.261719 409.460938 L 125.371094 408.421875 L 125.589844 407.488281 L 125.808594 406.550781 L 126.140625 405.621094 L 126.578125 404.78125 L 127.019531 403.851563 L 127.558594 403.019531 L 128.21875 402.191406 L 128.878906 401.351563 L 129.539063 400.519531 L 130.421875 399.789063 L 131.191406 398.960938 L 132.070313 398.238281 L 133.058594 397.609375 L 134.050781 396.878906 L 136.25 395.738281 L 138.550781 394.601563 L 141.078125 393.660156 L 143.71875 392.828125 L 146.460938 392.210938 L 149.320313 391.691406 L 152.398438 391.480469 L 155.46875 391.371094 "

Before

Width:  |  Height:  |  Size: 503 KiB

After

Width:  |  Height:  |  Size: 503 KiB

View File

@ -1 +1 @@
"use strict";Object.defineProperty(exports,"__esModule",{value:!0}),(()=>{const e=exports.los,t=document.querySelector("main").dataset.urlPrefix,o=document.querySelector("#lot--lotId").value,l=""===o,s=document.querySelector("#form--lot");s.addEventListener("submit",e=>{e.preventDefault(),cityssm.postJSON(t+"/lots/"+(l?"doCreateLot":"doUpdateLot"),s,e=>{e.success?l?window.location.href=t+"/lots/"+e.lotId+"/edit":bulmaJS.alert({message:exports.aliases.lot+" Updated Successfully",contextualColorName:"success"}):bulmaJS.alert({title:"Error Updating "+exports.aliases.lot,message:e.errorMessage,contextualColorName:"danger"})})}),e.initializeUnlockFieldButtons(s);let r=exports.lotComments;const m=()=>{document.querySelector("#container--lotComments")},n=()=>{let l;const s=e=>{e.preventDefault(),cityssm.postJSON(t+"/lots/doAddLotComment",e.currentTarget,e=>{e.success&&(r=e.lotComments,m(),l())})};cityssm.openHtmlModal("lotComment-add",{onshow(t){e.populateAliases(t),t.querySelector("#lotCommentAdd--lotId").value=o,t.querySelector("form").addEventListener("submit",s)},onshown(e,t){bulmaJS.toggleHtmlClipped(),l=t,e.querySelector("#lotCommentAdd--lotComment").focus()},onremoved(){bulmaJS.toggleHtmlClipped(),document.querySelector("#lotComments--add").focus()}})};l||(document.querySelector("#lotComments--add").addEventListener("click",n),m())})(); "use strict";Object.defineProperty(exports,"__esModule",{value:!0}),(()=>{const e=exports.los,t=document.querySelector("main").dataset.urlPrefix,o=document.querySelector("#lot--lotId").value,s=""===o,l=document.querySelector("#form--lot");l.addEventListener("submit",e=>{e.preventDefault(),cityssm.postJSON(t+"/lots/"+(s?"doCreateLot":"doUpdateLot"),l,e=>{e.success?s?window.location.href=t+"/lots/"+e.lotId+"/edit":bulmaJS.alert({message:exports.aliases.lot+" Updated Successfully",contextualColorName:"success"}):bulmaJS.alert({title:"Error Updating "+exports.aliases.lot,message:e.errorMessage,contextualColorName:"danger"})})}),e.initializeUnlockFieldButtons(l);let r=exports.lotComments;const n=()=>{const e=document.querySelector("#container--lotComments");0===r.length&&(e.innerHTML='<div class="message is-info"><p class="message-body">There are no comments to display.</p></div>')},m=()=>{let s;const l=e=>{e.preventDefault(),cityssm.postJSON(t+"/lots/doAddLotComment",e.currentTarget,e=>{e.success&&(r=e.lotComments,n(),s())})};cityssm.openHtmlModal("lotComment-add",{onshow(t){e.populateAliases(t),t.querySelector("#lotCommentAdd--lotId").value=o,t.querySelector("form").addEventListener("submit",l)},onshown(e,t){bulmaJS.toggleHtmlClipped(),s=t,e.querySelector("#lotCommentAdd--lotComment").focus()},onremoved(){bulmaJS.toggleHtmlClipped(),document.querySelector("#lotComments--add").focus()}})};s||(document.querySelector("#lotComments--add").addEventListener("click",m),n())})();

View File

@ -0,0 +1 @@
"use strict";Object.defineProperty(exports,"__esModule",{value:!0}),(()=>{const e=document.querySelector("main").dataset.urlPrefix,t=document.querySelector("#form--searchFilters"),a=document.querySelector("#container--searchResults"),s=Number.parseInt(document.querySelector("#searchFilter--limit").value,10),c=document.querySelector("#searchFilter--offset"),i=()=>{const i=Number.parseInt(c.value,10);a.innerHTML='<div class="has-text-grey has-text-centered"><i class="fas fa-5x fa-circle-notch fa-spin" aria-hidden="true"></i><br />Loading '+exports.aliases.occupancies+"...</div>",cityssm.postJSON(e+"/lotOccupancies/doSearchLotOccupancies",t,t=>{if(0===t.lotOccupancies.length)return void(a.innerHTML='<div class="message is-info"><p class="message-body">There are no '+exports.aliases.occupancy.toLowerCase()+" records that meet the search criteria.</p></div>");const c=document.createElement("tbody"),n=cityssm.dateToString(new Date);for(const a of t.lotOccupancies){let t="";t=a.occupancyStartDateString<=n&&(""===a.occupancyEndDateString||a.occupancyEndDateString>=n)?'<i class="fas fa-play" title="Current '+exports.aliases.occupancy+'"></i>':a.occupancyStartDateString>n?'<i class="fas fa-fast-forward" title="Future '+exports.aliases.occupancy+'"></i>':'<i class="fas fa-stop" title="Previous '+exports.aliases.occupancy+'"></i>';let s="";for(const e of a.lotOccupancyOccupants)s+=cityssm.escapeHTML(e.occupantName)+"<br />";c.insertAdjacentHTML("beforeend","<tr><td>"+t+'</td><td><a class="has-text-weight-bold" href="'+e+"/lotOccupancies/"+a.lotOccupancyId+'">'+cityssm.escapeHTML(a.occupancyType)+"</a></td><td>"+cityssm.escapeHTML(a.lotName)+'<br /><span class="is-size-7">'+cityssm.escapeHTML(a.mapName)+"</span></td><td>"+a.occupancyStartDateString+"</td><td>"+(a.occupancyEndDate?a.occupancyEndDateString:"(No End Date)")+"</td><td>"+s+"</td></tr>")}a.innerHTML='<table class="table is-fullwidth is-striped is-hoverable"><thead><tr><th></th><th>'+exports.aliases.occupancy+" Type</th><th>"+exports.aliases.lot+"</th><th>Start Date</th><th>End Date</th><th>"+exports.aliases.occupants+'</th></tr></thead><table><div class="level"><div class="level-left"><div class="level-item has-text-weight-bold">Displaying '+(i+1).toString()+" to "+Math.min(t.count,s+i)+" of "+t.count+'</div></div><div class="level-right">'+(i>0?'<div class="level-item"><button class="button is-rounded is-link is-outlined" data-page="previous" type="button" title="Previous"><i class="fas fa-arrow-left" aria-hidden="true"></i></button></div>':"")+(s+i<t.count?'<div class="level-item"><button class="button is-rounded is-link" data-page="next" type="button" title="Next"><span>Next</span><span class="icon"><i class="fas fa-arrow-right" aria-hidden="true"></i></span></button></div>':"")+"</div></div>",a.querySelector("table").append(c),i>0&&a.querySelector("button[data-page='previous']").addEventListener("click",r),s+i<t.count&&a.querySelector("button[data-page='next']").addEventListener("click",o)})},n=()=>{c.value="0",i()},r=()=>{c.value=Math.max(Number.parseInt(c.value,10)-s,0).toString(),i()},o=()=>{c.value=(Number.parseInt(c.value,10)+s).toString(),i()},l=t.querySelectorAll("input, select");for(const e of l)e.addEventListener("change",n);t.addEventListener("submit",e=>{e.preventDefault(),n()}),i()})();

File diff suppressed because one or more lines are too long

View File

@ -8,7 +8,10 @@ const getSafeRedirectURL = (possibleRedirectURL = "") => {
? possibleRedirectURL.slice(urlPrefix.length) ? possibleRedirectURL.slice(urlPrefix.length)
: possibleRedirectURL).toLowerCase(); : possibleRedirectURL).toLowerCase();
switch (urlToCheck) { switch (urlToCheck) {
case "/licences": case "/lotOccupancies":
case "/lots":
case "/maps":
case "/workOrders":
case "/reports": case "/reports":
return urlPrefix + urlToCheck; return urlPrefix + urlToCheck;
} }

View File

@ -18,7 +18,10 @@ const getSafeRedirectURL = (possibleRedirectURL = "") => {
: possibleRedirectURL).toLowerCase(); : possibleRedirectURL).toLowerCase();
switch (urlToCheck) { switch (urlToCheck) {
case "/licences": case "/lotOccupancies":
case "/lots":
case "/maps":
case "/workOrders":
case "/reports": case "/reports":
return urlPrefix + urlToCheck; return urlPrefix + urlToCheck;

View File

@ -1,3 +1,12 @@
import { Router } from "express"; 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_edit from "../handlers/lotOccupancies-get/edit.js";
import * as permissionHandlers from "../handlers/permissions.js";
export const router = Router(); export const router = Router();
router.get("/", handler_search);
router.post("/doSearchLotOccupancies", handler_doSearchLotOccupancies);
router.get("/:lotOccupancyId", handler_view);
router.get("/:lotOccupancyId/edit", permissionHandlers.updateGetHandler, handler_edit);
export default router; export default router;

View File

@ -1,10 +1,34 @@
import { Router } from "express"; 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_edit from "../handlers/lotOccupancies-get/edit.js";
import * as permissionHandlers from "../handlers/permissions.js"; import * as permissionHandlers from "../handlers/permissions.js";
import * as configFunctions from "../helpers/functions.config.js";
export const router = Router(); export const router = Router();
router.get("/",
handler_search);
router.post("/doSearchLotOccupancies",
handler_doSearchLotOccupancies);
router.get("/:lotOccupancyId",
handler_view);
router.get("/:lotOccupancyId/edit",
permissionHandlers.updateGetHandler,
handler_edit);
export default router; export default router;

View File

@ -38,6 +38,7 @@ import {
} from "../helpers/lotOccupancyDB/addLotOccupancyOccupant.js"; } from "../helpers/lotOccupancyDB/addLotOccupancyOccupant.js";
import type * as recordTypes from "../types/recordTypes"; import type * as recordTypes from "../types/recordTypes";
import addLotOccupancyComment from "../helpers/lotOccupancyDB/addLotOccupancyComment.js"; import addLotOccupancyComment from "../helpers/lotOccupancyDB/addLotOccupancyComment.js";

View File

@ -14,10 +14,14 @@ export interface Config {
isAdmin?: string[]; isAdmin?: string[];
}; };
aliases?: { aliases?: {
lot: string; lot?: string;
lots: string; lots?: string;
map: string; map?: string;
maps: string; maps?: string;
occupancy?: string;
occupancies?: string;
occupant?: string;
occupants?: string;
}; };
} }
interface ConfigApplication { interface ConfigApplication {

View File

@ -14,10 +14,14 @@ export interface Config {
isAdmin?: string[]; isAdmin?: string[];
}, },
aliases?: { aliases?: {
lot: string; lot?: string;
lots: string; lots?: string;
map: string; map?: string;
maps: string; maps?: string;
occupancy?: string;
occupancies?: string;
occupant?: string;
occupants?: string;
} }
} }

View File

@ -1,2 +1 @@
"use strict"; export {};
Object.defineProperty(exports, "__esModule", { value: true });

View File

@ -113,16 +113,29 @@ export interface LotOccupancyOccupant extends Occupant, Record {
lotOccupantTypeId?: number; lotOccupantTypeId?: number;
lotOccupantType?: string | LotOccupantType; lotOccupantType?: string | LotOccupantType;
} }
export interface LotOccupancyComment extends Record {
lotOccupancyCommentId?: number;
lotOccupancyId?: number;
lotOccupancyCommentDate?: number;
lotOccupancyCommentDateString?: string;
lotOccupancyCommentTime?: number;
lotOccupancyCommentTimeString?: string;
lotOccupancyComment?: string;
}
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;
lotOccupancyOccupants?: LotOccupancyOccupant[]; lotName?: string;
mapId?: number;
mapName?: string;
occupancyStartDate?: number; occupancyStartDate?: number;
occupancyStartDateString?: string; occupancyStartDateString?: string;
occupancyEndDate?: number; occupancyEndDate?: number;
occupancyEndDateString?: string; occupancyEndDateString?: string;
lotOccupancyComments?: LotOccupancyComment[];
lotOccupancyOccupants?: LotOccupancyOccupant[];
} }
export interface User { export interface User {
userName: string; userName: string;

View File

@ -1,2 +1 @@
"use strict"; export {};
Object.defineProperty(exports, "__esModule", { value: true });

View File

@ -1,16 +1,16 @@
export interface Record { export interface Record {
recordCreate_userName?: string; recordCreate_userName ? : string;
recordCreate_timeMillis?: number; recordCreate_timeMillis ? : number;
recordCreate_dateString?: string; recordCreate_dateString ? : string;
recordUpdate_userName?: string; recordUpdate_userName ? : string;
recordUpdate_timeMillis?: number; recordUpdate_timeMillis ? : number;
recordUpdate_dateString?: string; recordUpdate_dateString ? : string;
recordUpdate_timeString?: string; recordUpdate_timeString ? : string;
recordDelete_userName?: string; recordDelete_userName ? : string;
recordDelete_timeMillis?: number; recordDelete_timeMillis ? : number;
recordDelete_dateString?: string; recordDelete_dateString ? : string;
} }
@ -20,161 +20,180 @@ export interface Record {
export interface Map extends Record { export interface Map extends Record {
mapId?: number; mapId ? : number;
mapName?: string; mapName ? : string;
mapDescription?: string; mapDescription ? : string;
mapLatitude?: number; mapLatitude ? : number;
mapLongitude?: number; mapLongitude ? : number;
mapSVG?: string; mapSVG ? : string;
mapAddress1?: string; mapAddress1 ? : string;
mapAddress2?: string; mapAddress2 ? : string;
mapCity?: string; mapCity ? : string;
mapProvince?: string; mapProvince ? : string;
mapPostalCode?: string; mapPostalCode ? : string;
mapPhoneNumber?: string; mapPhoneNumber ? : string;
lotCount?: number; lotCount ? : number;
} }
export interface LotType extends Record { export interface LotType extends Record {
lotTypeId?: number; lotTypeId ? : number;
lotType?: string; lotType ? : string;
orderNumber?: number; orderNumber ? : number;
lotTypeFields?: LotTypeField[]; lotTypeFields ? : LotTypeField[];
} }
export interface LotTypeField extends Record { export interface LotTypeField extends Record {
lotTypeFieldId?: number; lotTypeFieldId ? : number;
lotTypeField?: string; lotTypeField ? : string;
lotTypeId?: number; lotTypeId ? : number;
lotType: LotType; lotType: LotType;
lotTypeFieldValues?: string; lotTypeFieldValues ? : string;
isRequired?: boolean; isRequired ? : boolean;
pattern?: string; pattern ? : string;
minimumLength?: number; minimumLength ? : number;
maximumLength?: number; maximumLength ? : number;
orderNumber?: number; orderNumber ? : number;
} }
export interface LotStatus extends Record { export interface LotStatus extends Record {
lotStatusId?: number; lotStatusId ? : number;
lotStatus?: string; lotStatus ? : string;
orderNumber?: number; orderNumber ? : number;
} }
export interface Lot extends Record { export interface Lot extends Record {
lotId?: number; lotId ? : number;
lotName?: string; lotName ? : string;
lotTypeId?: number; lotTypeId ? : number;
lotType?: LotType | string; lotType ? : LotType | string;
mapId?: number; mapId ? : number;
mapName?: string; mapName ? : string;
map?: Map; map ? : Map;
mapSVG?: string; mapSVG ? : string;
mapKey?: string; mapKey ? : string;
lotLatitude?: number; lotLatitude ? : number;
lotLongitude?: number; lotLongitude ? : number;
lotStatusId?: number; lotStatusId ? : number;
lotStatus?: LotStatus | string; lotStatus ? : LotStatus | string;
lotOccupancyCount?: number; lotOccupancyCount ? : number;
lotOccupancies?: LotOccupancy[]; lotOccupancies ? : LotOccupancy[];
lotComments?: LotComment[]; lotComments ? : LotComment[];
} }
export interface LotComment extends Record { export interface LotComment extends Record {
lotCommentId?: number; lotCommentId ? : number;
lotId?: number; lotId ? : number;
lotCommentDate?: number; lotCommentDate ? : number;
lotCommentDateString?: string; lotCommentDateString ? : string;
lotCommentTime?: number; lotCommentTime ? : number;
lotCommentTimeString?: string; lotCommentTimeString ? : string;
lotComment?: string; lotComment ? : string;
} }
export interface OccupancyType extends Record { export interface OccupancyType extends Record {
occupancyTypeId?: number; occupancyTypeId ? : number;
occupancyType?: string; occupancyType ? : string;
orderNumber?: number; orderNumber ? : number;
occupancyTypeFields?: OccupancyTypeField[]; occupancyTypeFields ? : OccupancyTypeField[];
} }
export interface OccupancyTypeField { export interface OccupancyTypeField {
occupancyTypeFieldId?: number; occupancyTypeFieldId ? : number;
occupancyTypeId?: number; occupancyTypeId ? : number;
occupancyTypeField?: string; occupancyTypeField ? : string;
occupancyTypeFieldValues?: string; occupancyTypeFieldValues ? : string;
isRequired?: boolean; isRequired ? : boolean;
pattern?: string; pattern ? : string;
minimumLength?: number; minimumLength ? : number;
maximumLength?: number; maximumLength ? : number;
orderNumber?: number; orderNumber ? : number;
} }
export interface LotOccupantType extends Record { export interface LotOccupantType extends Record {
lotOccupantTypeId?: number; lotOccupantTypeId ? : number;
lotOccupantType?: string; lotOccupantType ? : string;
orderNumber?: number; orderNumber ? : number;
} }
export interface Occupant extends Record { export interface Occupant extends Record {
occupantId?: number; occupantId ? : number;
occupantName?: string; occupantName ? : string;
occupantAddress1?: string; occupantAddress1 ? : string;
occupantAddress2?: string; occupantAddress2 ? : string;
occupantCity?: string; occupantCity ? : string;
occupantProvince?: string; occupantProvince ? : string;
occupantPostalCode?: string; occupantPostalCode ? : string;
occupantPhoneNumber?: string; occupantPhoneNumber ? : string;
} }
export interface LotOccupancyOccupant extends Occupant, Record { export interface LotOccupancyOccupant extends Occupant, Record {
lotOccupancyId?: number; lotOccupancyId ? : number;
lotOccupantIndex?: number; lotOccupantIndex ? : number;
lotOccupantTypeId?: number; lotOccupantTypeId ? : number;
lotOccupantType?: string | LotOccupantType; lotOccupantType ? : string | LotOccupantType;
}
export interface LotOccupancyComment extends Record {
lotOccupancyCommentId ? : number;
lotOccupancyId ? : number;
lotOccupancyCommentDate ? : number;
lotOccupancyCommentDateString ? : string;
lotOccupancyCommentTime ? : number;
lotOccupancyCommentTimeString ? : string;
lotOccupancyComment ? : string;
} }
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;
lotName ? : string;
lotOccupancyOccupants?: LotOccupancyOccupant[]; mapId ? : number;
mapName ? : string;
occupancyStartDate?: number; occupancyStartDate ? : number;
occupancyStartDateString?: string; occupancyStartDateString ? : string;
occupancyEndDate?: number; occupancyEndDate ? : number;
occupancyEndDateString?: string; occupancyEndDateString ? : string;
lotOccupancyComments ? : LotOccupancyComment[];
lotOccupancyOccupants ? : LotOccupancyOccupant[];
} }
@ -184,22 +203,22 @@ export interface LotOccupancy extends Record {
export interface User { export interface User {
userName: string; userName: string;
userProperties?: UserProperties; userProperties ? : UserProperties;
} }
export interface UserProperties { export interface UserProperties {
canUpdate: boolean; canUpdate: boolean;
isAdmin: boolean; isAdmin: boolean;
} }
declare module "express-session" { declare module "express-session" {
interface Session { interface Session {
user: User; user: User;
} }
} }
export interface PartialSession { export interface PartialSession {
user: User; user: User;
} }

View File

@ -1,31 +1,35 @@
</main> </main>
<footer class="footer has-background-grey-lighter has-text-dark is-hidden-print mt-4"> <footer class="footer has-background-grey-lighter has-text-dark is-hidden-print mt-4">
<div class="container"> <div class="container">
<div class="content has-text-right"> <div class="content has-text-right">
<p class="has-text-grey-dark"> <p class="has-text-grey-dark">
<strong> <strong>
<%= configFunctions.getProperty("application.applicationName") %> <%= configFunctions.getProperty("application.applicationName") %>
</strong><br /> </strong><br />
Build <%= buildNumber %> Build <%= buildNumber %>
</p> </p>
</div>
</div> </div>
</div>
</footer> </footer>
<script> <script>
window.exports = window.exports || {}; window.exports = window.exports || {};
exports.aliases = { exports.aliases = {
map: "<%= configFunctions.getProperty("aliases.map") %>", map: "<%= configFunctions.getProperty("aliases.map") %>",
maps: "<%= configFunctions.getProperty("aliases.maps") %>", maps: "<%= configFunctions.getProperty("aliases.maps") %>",
lot: "<%= configFunctions.getProperty("aliases.lot") %>", lot: "<%= configFunctions.getProperty("aliases.lot") %>",
lots: "<%= configFunctions.getProperty("aliases.lots") %>" lots: "<%= configFunctions.getProperty("aliases.lots") %>",
}; occupancy: "<%= configFunctions.getProperty("aliases.occupancy") %>",
occupancies: "<%= configFunctions.getProperty("aliases.occupancies") %>",
occupant: "<%= configFunctions.getProperty("aliases.occupant") %>",
occupants: "<%= configFunctions.getProperty("aliases.occupants") %>"
};
</script> </script>
<script src="<%= urlPrefix %>/lib/cityssm-bulma-js/bulma-js.js"></script> <script src="<%= urlPrefix %>/lib/cityssm-bulma-js/bulma-js.js"></script>
<script src="<%= urlPrefix %>/lib/cityssm-bulma-webapp-js/dist/cityssm.min.js"></script> <script src="<%= urlPrefix %>/lib/cityssm-bulma-webapp-js/dist/cityssm.min.js"></script>
<script src="<%= urlPrefix %>/lib/leaflet/leaflet.js"></script> <script src="<%= urlPrefix %>/lib/leaflet/leaflet.js"></script>
<script> <script>
cityssm.htmlModalFolder ="<%= urlPrefix %>/html/"; cityssm.htmlModalFolder ="<%= urlPrefix %>/html/";
bulmaJS.init(); bulmaJS.init();
</script> </script>
<script src="<%= urlPrefix %>/lib/cityssm-bulma-webapp-js/dist/cityssm-theme.min.js" defer></script> <script src="<%= urlPrefix %>/lib/cityssm-bulma-webapp-js/dist/cityssm-theme.min.js" defer></script>
<script src="<%= urlPrefix %>/lib/fa/js/all.min.js" defer></script> <script src="<%= urlPrefix %>/lib/fa/js/all.min.js" defer></script>

View File

@ -2,92 +2,110 @@
<html class="has-navbar-fixed-top is-fullwidth" lang="en"> <html class="has-navbar-fixed-top is-fullwidth" lang="en">
<head> <head>
<meta charset="utf-8" /> <meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" /> <meta name="viewport" content="width=device-width, initial-scale=1" />
<meta name="csrf-token" content="<%= csrfToken %>"> <meta name="csrf-token" content="<%= csrfToken %>">
<title> <title>
<%= headTitle %>: <%= configFunctions.getProperty("application.applicationName") %> <%= headTitle %>: <%= configFunctions.getProperty("application.applicationName") %>
</title> </title>
<link rel="icon" href="<%= urlPrefix %>/images/favicon.png" /> <link rel="icon" href="<%= urlPrefix %>/images/favicon.png" />
<link rel="stylesheet" href="<%= urlPrefix %>/stylesheets/style.css" /> <link rel="stylesheet" href="<%= urlPrefix %>/stylesheets/style.css" />
<link rel="stylesheet" href="<%= urlPrefix %>/lib/leaflet/leaflet.css" /> <link rel="stylesheet" href="<%= urlPrefix %>/lib/leaflet/leaflet.css" />
</head> </head>
<body> <body>
<nav class="navbar is-light is-fixed-top is-static-print" id="cityssm-theme--navbar" role="navigation" aria-label="main navigation"> <nav class="navbar is-light is-fixed-top is-static-print" id="cityssm-theme--navbar" role="navigation"
<div class="container"> aria-label="main navigation">
<div class="navbar-brand"> <div class="container">
<a class="navbar-item" href="<%= urlPrefix %>/dashboard"> <div class="navbar-brand">
<img class="mr-3" src="<%= urlPrefix + configFunctions.getProperty("application.logoURL") %>" alt="" height="28" /> <a class="navbar-item" href="<%= urlPrefix %>/dashboard">
<strong><%= configFunctions.getProperty("application.applicationName") %></strong> <img class="mr-3" src="<%= urlPrefix + configFunctions.getProperty("application.logoURL") %>" alt=""
</a> height="28" />
<strong><%= configFunctions.getProperty("application.applicationName") %></strong>
</a>
<a class="navbar-burger burger is-hidden-print" role="button" aria-label="menu" aria-expanded="false"> <a class="navbar-burger burger is-hidden-print" role="button" aria-label="menu" aria-expanded="false">
<span aria-hidden="true"></span> <span aria-hidden="true"></span>
<span aria-hidden="true"></span> <span aria-hidden="true"></span>
<span aria-hidden="true"></span> <span aria-hidden="true"></span>
</a> </a>
</div>
<div class="navbar-menu">
<div class="navbar-start">
<a class="navbar-item" href="<%= urlPrefix %>/lots">
<span class="icon mr-1">
<i class="fas fa-fw fa-vector-square" aria-hidden="true"></i>
</span>
<span><%= configFunctions.getProperty("aliases.lots") %></span>
</a>
<a class="navbar-item" href="<%= urlPrefix %>/maps">
<span class="icon mr-1">
<i class="far fa-fw fa-map" aria-hidden="true"></i>
</span>
<span><%= configFunctions.getProperty("aliases.maps") %></span>
</a>
<div class="navbar-item has-dropdown">
<a class="navbar-link is-arrowless" href="#">
<span>More</span>
<span class="icon ml-1">
<i class="fas fa-angle-down" aria-hidden="true"></i>
</span>
</a>
<div class="navbar-dropdown">
<a class="navbar-item" href="<%= urlPrefix %>/reports">
<span class="icon mr-1">
<i class="fas fa-fw fa-file" aria-hidden="true"></i>
</span>
<span>Reports</span>
</a>
<hr class="navbar-divider" />
<a class="navbar-item" href="https://cityssm.github.io/lot-occupancy-system/" target="_blank" rel="noopener noreferrer">
<span class="icon mr-1">
<i class="fas fa-fw fa-question-circle" aria-hidden="true"></i>
</span>
<span>Help</span>
</a>
</div> </div>
</div>
</div>
<div class="navbar-end"> <div class="navbar-menu">
<a class="navbar-item" id="cityssm-theme--logout-button" role="button" href="#"> <div class="navbar-start">
<span class="icon mr-1">
<i class="fas fa-fw fa-sign-out-alt" aria-hidden="true"></i>
</span>
<span>Log Out <%=user.userName %></span>
</a>
</div>
</div>
</div>
</nav>
<main class="container pt-2 px-3 mr-auto has-min-page-height" <a class="navbar-item" href="<%= urlPrefix %>/lotOccupancies">
data-session-keep-alive-millis="<%= configFunctions.keepAliveMillis %>" <span class="icon mr-1">
data-url-prefix="<%= urlPrefix %>" <span class="fa-layers fa-fw" aria-hidden="true">
data-can-update="<%= user.userProperties.canUpdate ? "true" : "false" %>" <i class="fas fa-vector-square"></i>
data-is-admin="<%= user.userProperties.isAdmin ? "true" : "false" %>"> <i class="fas fa-user" data-fa-transform="shrink-10"></i>
</span>
</span>
<span><%= configFunctions.getProperty("aliases.occupancies") %></span>
</a>
<a class="navbar-item" href="<%= urlPrefix %>/workOrders">
<span class="icon mr-1">
<i class="fas fa-hard-hat" aria-hidden="true"></i>
</span>
<span>Work Orders</span>
</a>
<div class="navbar-item has-dropdown">
<a class="navbar-link is-arrowless" href="#">
<span>More</span>
<span class="icon ml-1">
<i class="fas fa-angle-down" aria-hidden="true"></i>
</span>
</a>
<div class="navbar-dropdown">
<a class="navbar-item" href="<%= urlPrefix %>/lots">
<span class="icon mr-1">
<i class="fas fa-fw fa-vector-square" aria-hidden="true"></i>
</span>
<span><%= configFunctions.getProperty("aliases.lots") %></span>
</a><a class="navbar-item" href="<%= urlPrefix %>/maps">
<span class="icon mr-1">
<i class="far fa-fw fa-map" aria-hidden="true"></i>
</span>
<span><%= configFunctions.getProperty("aliases.maps") %></span>
</a>
<hr class="navbar-divider" />
<a class="navbar-item" href="<%= urlPrefix %>/reports">
<span class="icon mr-1">
<i class="fas fa-fw fa-file" aria-hidden="true"></i>
</span>
<span>Reports</span>
</a>
<hr class="navbar-divider" />
<a class="navbar-item" href="https://cityssm.github.io/lot-occupancy-system/"
target="_blank" rel="noopener noreferrer">
<span class="icon mr-1">
<i class="fas fa-fw fa-question-circle" aria-hidden="true"></i>
</span>
<span>Help</span>
</a>
</div>
</div>
</div>
<div class="navbar-end">
<a class="navbar-item" id="cityssm-theme--logout-button" role="button" href="#">
<span class="icon mr-1">
<i class="fas fa-fw fa-sign-out-alt" aria-hidden="true"></i>
</span>
<span>Log Out <%=user.userName %></span>
</a>
</div>
</div>
</div>
</nav>
<main class="container pt-2 px-3 mr-auto has-min-page-height"
data-session-keep-alive-millis="<%= configFunctions.keepAliveMillis %>" data-url-prefix="<%= urlPrefix %>"
data-can-update="<%= user.userProperties.canUpdate ? "true" : "false" %>"
data-is-admin="<%= user.userProperties.isAdmin ? "true" : "false" %>">

View File

@ -9,6 +9,39 @@
</div> </div>
<div class="columns"> <div class="columns">
<div class="column">
<div class="card">
<div class="card-content">
<div class="media">
<div class="media-left">
<span class="fa-layers fa-3x fa-fw" aria-hidden="true">
<i class="fas fa-vector-square"></i>
<i class="fas fa-user" data-fa-transform="shrink-10"></i>
</span>
</div>
<div class="media-content has-text-black">
<h2 class="title is-4 is-marginless">
<a href="<%= urlPrefix %>/lotOccupancies"><%= configFunctions.getProperty("aliases.lot") %> <%= configFunctions.getProperty("aliases.occupancies") %></a>
</h2>
<p>View and maintain current and past <%= configFunctions.getProperty("aliases.lot").toLowerCase() %> <%= configFunctions.getProperty("aliases.occupancies").toLowerCase() %>.</p>
</div>
</div>
</div>
<div class="card-content">
<div class="media">
<div class="media-left">
<i class="fas fa-3x fa-fw fa-hard-hat" aria-hidden="true"></i>
</div>
<div class="media-content has-text-black">
<h2 class="title is-4 is-marginless">
<a href="<%= urlPrefix %>/workOrders">Work Orders</a>
</h2>
<p>View and maintain work orders.</p>
</div>
</div>
</div>
</div>
</div>
<div class="column"> <div class="column">
<div class="card"> <div class="card">
<div class="card-content"> <div class="card-content">
@ -20,12 +53,10 @@
<h2 class="title is-4 is-marginless"> <h2 class="title is-4 is-marginless">
<a href="<%= urlPrefix %>/lots"><%= configFunctions.getProperty("aliases.lots") %></a> <a href="<%= urlPrefix %>/lots"><%= configFunctions.getProperty("aliases.lots") %></a>
</h2> </h2>
<p>View and maintain <%= configFunctions.getProperty("aliases.lots").toLowerCase() %>.</p> <p>View and maintain <%= configFunctions.getProperty("aliases.lots").toLowerCase() %> within a <%= configFunctions.getProperty("aliases.map").toLowerCase() %>.</p>
</div> </div>
</div> </div>
</div> </div>
</div>
<div class="card">
<div class="card-content"> <div class="card-content">
<div class="media"> <div class="media">
<div class="media-left"> <div class="media-left">
@ -41,41 +72,6 @@
</div> </div>
</div> </div>
</div> </div>
<div class="column">
<div class="card">
<div class="card-content">
<div class="media">
<div class="media-left">
<span class="fa-layers fa-3x fa-fw" aria-hidden="true">
<i class="fas fa-vector-square"></i>
<i class="fas fa-user" data-fa-transform="shrink-10"></i>
</span>
</div>
<div class="media-content has-text-black">
<h2 class="title is-4 is-marginless">
<a href="<%= urlPrefix %>/lotOccupancies"><%= configFunctions.getProperty("aliases.lot") %> Occupancies</a>
</h2>
<p>View and maintain <%= configFunctions.getProperty("aliases.lot").toLowerCase() %> occupancies.</p>
</div>
</div>
</div>
</div>
<div class="card">
<div class="card-content">
<div class="media">
<div class="media-left">
<i class="fas fa-3x fa-fw fa-hard-hat" aria-hidden="true"></i>
</div>
<div class="media-content has-text-black">
<h2 class="title is-4 is-marginless">
<a href="<%= urlPrefix %>/workOrders">Work Orders</a>
</h2>
<p>View and maintain work orders.</p>
</div>
</div>
</div>
</div>
</div>
</div> </div>
<div class="columns"> <div class="columns">
<div class="column"> <div class="column">
@ -122,7 +118,7 @@
</div> </div>
</div> </div>
<% if (user.userProperties.isAdmin) { %> <% if (false && user.userProperties.isAdmin) { %>
<h2 class="title is-3">Administrator Tools</h2> <h2 class="title is-3">Administrator Tools</h2>
<div class="columns"> <div class="columns">

View File

@ -211,7 +211,7 @@
</p> </p>
</div> </div>
<% } else { %> <% } else { %>
<div class="columns is-mobile"> <div class="columns is-mobile mt-2">
<div class="column"> <div class="column">
<h2 class="title is-4"> <h2 class="title is-4">
Comments Comments
@ -226,24 +226,24 @@
</div> </div>
<div id="container--lotComments"></div> <div id="container--lotComments"></div>
<h2 class="title is-4"> <h2 class="title is-4 mt-2">
Occupancies <%= configFunctions.getProperty("aliases.occupancies") %>
<span class="tag"><%= lot.lotOccupancies.length %></span> <span class="tag"><%= lot.lotOccupancies.length %></span>
</h2> </h2>
<% if (lot.lotOccupancies.length === 0) { %> <% if (lot.lotOccupancies.length === 0) { %>
<div class="message is-info"> <div class="message is-info">
<p class="message-body">There are no occupancy records asscociated with this <%= configFunctions.getProperty("aliases.lot") %>.</p> <p class="message-body">There are no <%= configFunctions.getProperty("aliases.occupancy").toLowerCase() %> records asscociated with this <%= configFunctions.getProperty("aliases.lot") %>.</p>
</div> </div>
<% } else { %> <% } else { %>
<table class="table is-fullwidth is-striped is-hoverable"> <table class="table is-fullwidth is-striped is-hoverable">
<thead> <thead>
<tr> <tr>
<th class="has-width-10">&nbsp;</th> <th class="has-width-10">&nbsp;</th>
<th>Occupancy Type</th> <th><%= configFunctions.getProperty("aliases.occupancy") %> Type</th>
<th>Start Date</th> <th>Start Date</th>
<th>End Date</th> <th>End Date</th>
<th>Occupants</th> <th><%= configFunctions.getProperty("aliases.occupants") %></th>
</tr> </tr>
</thead> </thead>
<tbody> <tbody>
@ -253,12 +253,16 @@
<tr> <tr>
<td class="has-text-centered"> <td class="has-text-centered">
<% if (isActive) { %> <% if (isActive) { %>
<i class="fas fa-play" title="Currently Occupied"></i> <i class="fas fa-play" title="Current <%= configFunctions.getProperty("aliases.occupancy") %>"></i>
<% } else { %> <% } else { %>
<i class="fas fa-stop" title="Previously Occupied"></i> <i class="fas fa-stop" title="Previous <%= configFunctions.getProperty("aliases.occupancy") %>"></i>
<% } %> <% } %>
</td> </td>
<td><%= lotOccupancy.occupancyType %></td> <td>
<a class="has-text-weight-bold" href="<%= urlPrefix %>/lotOccupancies/<%= lotOccupancy.lotOccupancyId %>">
<%= lotOccupancy.occupancyType %>
</a>
</td>
<td><%= lotOccupancy.occupancyStartDateString %></td> <td><%= lotOccupancy.occupancyStartDateString %></td>
<td> <td>
<% if (lotOccupancy.occupancyEndDate) { %> <% if (lotOccupancy.occupancyEndDate) { %>
@ -269,7 +273,7 @@
</td> </td>
<td> <td>
<% if (lotOccupancy.lotOccupancyOccupants.length === 0) { %> <% if (lotOccupancy.lotOccupancyOccupants.length === 0) { %>
(No Occupants) (No <%= configFunctions.getProperty("aliases.occupants") %>)
<% } else { %> <% } else { %>
<% const occupant = lotOccupancy.lotOccupancyOccupants[0]; %> <% const occupant = lotOccupancy.lotOccupancyOccupants[0]; %>
<%= occupant.occupantName %> <%= occupant.occupantName %>

View File

@ -61,7 +61,7 @@
</div> </div>
<h2 class="title is-4"> <h2 class="title is-4">
Occupancies <%= configFunctions.getProperty("aliases.occupancies") %>
<span class="tag"><%= lot.lotOccupancies.length %></span> <span class="tag"><%= lot.lotOccupancies.length %></span>
</h2> </h2>
@ -74,10 +74,10 @@
<thead> <thead>
<tr> <tr>
<th class="has-width-10">&nbsp;</th> <th class="has-width-10">&nbsp;</th>
<th>Occupancy Type</th> <th><%= configFunctions.getProperty("aliases.occupancy") %> Type</th>
<th>Start Date</th> <th>Start Date</th>
<th>End Date</th> <th>End Date</th>
<th>Occupants</th> <th><%= configFunctions.getProperty("aliases.occupants") %></th>
</tr> </tr>
</thead> </thead>
<tbody> <tbody>
@ -85,31 +85,35 @@
<% for (const lotOccupancy of lot.lotOccupancies) { %> <% for (const lotOccupancy of lot.lotOccupancies) { %>
<% const isActive = !(lotOccupancy.occupancyEndDate && lotOccupancy.occupancyEndDate < currentDate); %> <% const isActive = !(lotOccupancy.occupancyEndDate && lotOccupancy.occupancyEndDate < currentDate); %>
<tr> <tr>
<td class="has-text-centered"> <td class="has-text-centered">
<% if (isActive) { %> <% if (isActive) { %>
<i class="fas fa-play" title="Currently Occupied"></i> <i class="fas fa-play" title="Current <%= configFunctions.getProperty("aliases.occupancy") %>"></i>
<% } else { %> <% } else { %>
<i class="fas fa-stop" title="Previously Occupied"></i> <i class="fas fa-stop" title="Previous <%= configFunctions.getProperty("aliases.occupancy") %>"></i>
<% } %> <% } %>
</td> </td>
<td><%= lotOccupancy.occupancyType %></td> <td>
<td><%= lotOccupancy.occupancyStartDateString %></td> <a class="has-text-weight-bold" href="<%= urlPrefix %>/lotOccupancies/<%= lotOccupancy.lotOccupancyId %>">
<td> <%= lotOccupancy.occupancyType %>
<% if (lotOccupancy.occupancyEndDate) { %> </a>
<%= lotOccupancy.occupancyEndDateString %> </td>
<% } else { %> <td><%= lotOccupancy.occupancyStartDateString %></td>
(No End Date) <td>
<% } %> <% if (lotOccupancy.occupancyEndDate) { %>
</td> <%= lotOccupancy.occupancyEndDateString %>
<td> <% } else { %>
<% if (lotOccupancy.lotOccupancyOccupants.length === 0) { %> (No End Date)
(No Occupants) <% } %>
<% } else { %> </td>
<% const occupant = lotOccupancy.lotOccupancyOccupants[0]; %> <td>
<%= occupant.occupantName %> <% if (lotOccupancy.lotOccupancyOccupants.length === 0) { %>
<%= (lotOccupancy.lotOccupancyOccupants.length > 1 ? " plus " + (lotOccupancy.lotOccupancyOccupants.length - 1) : "") %> (No <%= configFunctions.getProperty("aliases.occupants") %>)
<% } %> <% } else { %>
</td> <% const occupant = lotOccupancy.lotOccupancyOccupants[0]; %>
<%= occupant.occupantName %>
<%= (lotOccupancy.lotOccupancyOccupants.length > 1 ? " plus " + (lotOccupancy.lotOccupancyOccupants.length - 1) : "") %>
<% } %>
</td>
</tr> </tr>
<% } %> <% } %>
</tbody> </tbody>

View File

@ -0,0 +1,43 @@
<%- include('_header'); -%>
<nav class="breadcrumb">
<ul>
<li><a href="<%= urlPrefix %>/dashboard">Home</a></li>
<li>
<a href="<%= urlPrefix %>/lotOccupancies">
<span class="icon is-small">
<span class="fa-layers fa-fw" aria-hidden="true">
<i class="fas fa-vector-square"></i>
<i class="fas fa-user" data-fa-transform="shrink-10"></i>
</span>
</span>
<span><%= configFunctions.getProperty("aliases.lots") %> <%= configFunctions.getProperty("aliases.occupancies") %></span>
</a>
</li>
<li>
<a href="<%= urlPrefix %>/lotOccupancies/<%= lotOccupancy.lotOccupancyId %>">
<%= configFunctions.getProperty("aliases.occupancy") %> View
</a>
</li>
<li class="is-active">
<a href="#" aria-current="page">
<%= configFunctions.getProperty("aliases.occupancy") %> Edit
</a>
</li>
</ul>
</nav>
<h1 class="title is-1">
<%= configFunctions.getProperty("aliases.occupancy") %> Edit
</h1>
<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.occupancy") %>" type="submit">
<i class="fas fa-save" aria-hidden="true"></i>
<span class="sr-only">Update <%= configFunctions.getProperty("aliases.occupancy") %></span>
</button>
</div>
<%- include('_footerA'); -%>
<%- include('_footerB'); -%>

View File

@ -0,0 +1,146 @@
<%- include('_header'); -%>
<nav class="breadcrumb">
<ul>
<li><a href="<%= urlPrefix %>/dashboard">Home</a></li>
<li class="is-active">
<a href="#" aria-current="page">
<span class="icon is-small">
<span class="fa-layers fa-fw" aria-hidden="true">
<i class="fas fa-vector-square"></i>
<i class="fas fa-user" data-fa-transform="shrink-10"></i>
</span>
</span>
<span><%= configFunctions.getProperty("aliases.lot") %> <%= configFunctions.getProperty("aliases.occupancies") %></span>
</a>
</li>
</ul>
</nav>
<h1 class="title is-1">
Find an <%= configFunctions.getProperty("aliases.occupancy") %> Record
</h1>
<% if (user.userProperties.canUpdate) { %>
<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="Create a New <%= configFunctions.getProperty("aliases.occupancy") %>" href="<%= urlPrefix %>/lotOccupancies/new">
<i class="fas fa-plus" aria-hidden="true"></i>
<span class="sr-only">Create a New <%= configFunctions.getProperty("aliases.occupancy") %></span>
</a>
</div>
<% } %>
<div class="box">
<form id="form--searchFilters">
<input id="searchFilter--limit" name="limit" type="hidden" value="100" />
<input id="searchFilter--offset" name="offset" type="hidden" value="0" />
<div class="columns">
<div class="column">
<div class="field">
<label class="label" for="searchFilter--occupantName"><%= configFunctions.getProperty("aliases.occupant") %> Name</label>
<div class="control has-icons-left">
<input class="input" id="searchFilter--occupantName" name="occupantName" />
<span class="icon is-small is-left">
<i class="fas fa-search" aria-hidden="true"></i>
</span>
</div>
</div>
</div>
<div class="column">
<div class="field">
<label class="label" for="searchFilter--occupancyTypeId"><%= configFunctions.getProperty("aliases.occupancy") %> Type</label>
<div class="control has-icons-left">
<div class="select is-fullwidth">
<select id="searchFilter--occupancyTypeId" name="occupancyTypeId">
<option value="">(All <%= configFunctions.getProperty("aliases.occupancy") %> Types)</option>
<% for (const occupancyType of occupancyTypes) { %>
<option value="<%= occupancyType.occupancyTypeId %>"><%= occupancyType.occupancyType %></option>
<% } %>
</select>
</div>
<span class="icon is-small is-left">
<i class="fas fa-search" aria-hidden="true"></i>
</span>
</div>
</div>
</div>
<div class="column">
<div class="field">
<label class="label" for="searchFilter--occupancyTime"><%= configFunctions.getProperty("aliases.occupancy") %> Time</label>
<div class="control has-icons-left">
<div class="select is-fullwidth">
<select id="searchFilter--occupancyTime" name="occupancyTime">
<option value="">(All Times)</option>
<option value="current" selected>Current</option>
<option value="past">Past</option>
<option value="future">Future</option>
</select>
</div>
<span class="icon is-small is-left">
<i class="fas fa-search" aria-hidden="true"></i>
</span>
</div>
</div>
</div>
</div>
<div class="columns">
<div class="column">
<div class="field">
<label class="label" for="searchFilter--mapId"><%= configFunctions.getProperty("aliases.map") %></label>
<div class="control has-icons-left">
<div class="select is-fullwidth">
<select id="searchFilter--mapId" name="mapId">
<option value="">(All <%= configFunctions.getProperty("aliases.maps") %>)</option>
<% for (const map of maps) { %>
<option value="<%= map.mapId %>" <%= (map.mapId.toString() === mapId) ? " selected" : "" %>>
<%= map.mapName %>
</option>
<% } %>
</select>
</div>
<span class="icon is-small is-left">
<i class="fas fa-search" aria-hidden="true"></i>
</span>
</div>
</div>
</div>
<div class="column">
<div class="field">
<label class="label" for="searchFilter--lotName"><%= configFunctions.getProperty("aliases.lot") %></label>
<div class="control has-icons-left">
<input class="input" id="searchFilter--lotName" name="lotName" />
<span class="icon is-small is-left">
<i class="fas fa-search" aria-hidden="true"></i>
</span>
</div>
</div>
</div>
<div class="column">
<div class="field">
<label class="label" for="searchFilter--lotTypeId"><%= configFunctions.getProperty("aliases.lot") %> Type</label>
<div class="control has-icons-left">
<div class="select is-fullwidth">
<select id="searchFilter--lotTypeId" name="lotTypeId">
<option value="">(All <%= configFunctions.getProperty("aliases.lot") %> Types)</option>
<% for (const lotType of lotTypes) { %>
<option value="<%= lotType.lotTypeId %>"><%= lotType.lotType %></option>
<% } %>
</select>
</div>
<span class="icon is-small is-left">
<i class="fas fa-search" aria-hidden="true"></i>
</span>
</div>
</div>
</div>
</div>
</form>
</div>
<div id="container--searchResults"></div>
<%- include('_footerA'); -%>
<script src="<%= urlPrefix %>/javascripts/lotOccupancySearch.min.js"></script>
<%- include('_footerB'); -%>

View File

@ -0,0 +1,39 @@
<%- include('_header'); -%>
<nav class="breadcrumb">
<ul>
<li><a href="<%= urlPrefix %>/dashboard">Home</a></li>
<li>
<a href="<%= urlPrefix %>/lotOccupancies">
<span class="icon is-small">
<span class="fa-layers fa-fw" aria-hidden="true">
<i class="fas fa-vector-square"></i>
<i class="fas fa-user" data-fa-transform="shrink-10"></i>
</span>
</span>
<span><%= configFunctions.getProperty("aliases.lots") %> <%= configFunctions.getProperty("aliases.occupancies") %></span>
</a>
</li>
<li class="is-active"><a href="#" aria-current="page">
<%= configFunctions.getProperty("aliases.occupancy") %> View
</a></li>
</ul>
</nav>
<h1 class="title is-1">
<%= configFunctions.getProperty("aliases.occupancy") %> View
</h1>
<% if (user.userProperties.canUpdate) { %>
<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.occupancy") %>" href="<%= urlPrefix %>/lotOccupancies/<%= lotOccupancy.lotOccupancyId %>/edit">
<i class="fas fa-pencil-alt" aria-hidden="true"></i>
<span class="sr-only">Update <%= configFunctions.getProperty("aliases.occupancy") %></span>
</a>
</div>
<% } %>
<%- include('_footerA'); -%>
<%- include('_footerB'); -%>