lot type maintenance

deepsource-autofix-76c6eb20
Dan Gowans 2022-09-30 11:53:51 -04:00
parent ca028fbacf
commit 12397aa4aa
82 changed files with 2653 additions and 16 deletions

View File

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

View File

@ -0,0 +1,10 @@
import { getLotTypes } from "../../helpers/functions.cache.js";
import * as configFunctions from "../../helpers/functions.config.js";
export const handler = (_request, response) => {
const lotTypes = getLotTypes();
response.render("admin-lotTypes", {
headTitle: configFunctions.getProperty("aliases.lot") + " Type Management",
lotTypes
});
};
export default handler;

View File

@ -0,0 +1,16 @@
import type { RequestHandler } from "express";
import { getLotTypes } from "../../helpers/functions.cache.js";
import * as configFunctions from "../../helpers/functions.config.js";
export const handler: RequestHandler = (_request, response) => {
const lotTypes = getLotTypes();
response.render("admin-lotTypes", {
headTitle: configFunctions.getProperty("aliases.lot") + " Type Management",
lotTypes
});
};
export default handler;

View File

@ -4,8 +4,7 @@ export const handler = (_request, response) => {
const occupancyTypes = getOccupancyTypes();
const allOccupancyTypeFields = getAllOccupancyTypeFields();
response.render("admin-occupancyTypes", {
headTitle: configFunctions.getProperty("aliases.occupancy") +
" Type Management",
headTitle: configFunctions.getProperty("aliases.occupancy") + " Type Management",
occupancyTypes,
allOccupancyTypeFields
});

View File

@ -9,9 +9,7 @@ export const handler: RequestHandler = (_request, response) => {
const allOccupancyTypeFields = getAllOccupancyTypeFields();
response.render("admin-occupancyTypes", {
headTitle:
configFunctions.getProperty("aliases.occupancy") +
" Type Management",
headTitle: configFunctions.getProperty("aliases.occupancy") + " Type Management",
occupancyTypes,
allOccupancyTypeFields
});

View File

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

View File

@ -0,0 +1,12 @@
import { addLotType } from "../../helpers/lotOccupancyDB/addLotType.js";
import { getLotTypes } from "../../helpers/functions.cache.js";
export const handler = async (request, response) => {
const lotTypeId = addLotType(request.body, request.session);
const lotTypes = getLotTypes();
response.json({
success: true,
lotTypeId,
lotTypes
});
};
export default handler;

View File

@ -0,0 +1,19 @@
import type { RequestHandler } from "express";
import { addLotType } from "../../helpers/lotOccupancyDB/addLotType.js";
import { getLotTypes } from "../../helpers/functions.cache.js";
export const handler: RequestHandler = async (request, response) => {
const lotTypeId = addLotType(request.body, request.session);
const lotTypes = getLotTypes();
response.json({
success: true,
lotTypeId,
lotTypes
});
};
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,12 @@
import { addLotTypeField } from "../../helpers/lotOccupancyDB/addLotTypeField.js";
import { getLotTypes } from "../../helpers/functions.cache.js";
export const handler = async (request, response) => {
const lotTypeFieldId = addLotTypeField(request.body, request.session);
const lotTypes = getLotTypes();
response.json({
success: true,
lotTypeFieldId,
lotTypes
});
};
export default handler;

View File

@ -0,0 +1,19 @@
import type { RequestHandler } from "express";
import { addLotTypeField } from "../../helpers/lotOccupancyDB/addLotTypeField.js";
import { getLotTypes } from "../../helpers/functions.cache.js";
export const handler: RequestHandler = async (request, response) => {
const lotTypeFieldId = addLotTypeField(request.body, request.session);
const lotTypes = getLotTypes();
response.json({
success: true,
lotTypeFieldId,
lotTypes
});
};
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,11 @@
import { deleteLotType } from "../../helpers/lotOccupancyDB/deleteLotType.js";
import { getLotTypes } from "../../helpers/functions.cache.js";
export const handler = async (request, response) => {
const success = deleteLotType(request.body.lotTypeId, request.session);
const lotTypes = getLotTypes();
response.json({
success,
lotTypes
});
};
export default handler;

View File

@ -0,0 +1,21 @@
import type { RequestHandler } from "express";
import { deleteLotType } from "../../helpers/lotOccupancyDB/deleteLotType.js";
import { getLotTypes } from "../../helpers/functions.cache.js";
export const handler: RequestHandler = async (request, response) => {
const success = deleteLotType(
request.body.lotTypeId,
request.session
);
const lotTypes = getLotTypes();
response.json({
success,
lotTypes
});
};
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,11 @@
import { deleteLotTypeField } from "../../helpers/lotOccupancyDB/deleteLotTypeField.js";
import { getLotTypes } from "../../helpers/functions.cache.js";
export const handler = async (request, response) => {
const success = deleteLotTypeField(request.body.lotTypeFieldId, request.session);
const lotTypes = getLotTypes();
response.json({
success,
lotTypes
});
};
export default handler;

View File

@ -0,0 +1,18 @@
import type { RequestHandler } from "express";
import { deleteLotTypeField } from "../../helpers/lotOccupancyDB/deleteLotTypeField.js";
import { getLotTypes } from "../../helpers/functions.cache.js";
export const handler: RequestHandler = async (request, response) => {
const success = deleteLotTypeField(request.body.lotTypeFieldId, request.session);
const lotTypes = getLotTypes();
response.json({
success,
lotTypes
});
};
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,11 @@
import { moveLotTypeDown } from "../../helpers/lotOccupancyDB/moveLotTypeDown.js";
import { getLotTypes } from "../../helpers/functions.cache.js";
export const handler = async (request, response) => {
const success = moveLotTypeDown(request.body.lotTypeId);
const lotTypes = getLotTypes();
response.json({
success,
lotTypes
});
};
export default handler;

View File

@ -0,0 +1,18 @@
import type { RequestHandler } from "express";
import { moveLotTypeDown } from "../../helpers/lotOccupancyDB/moveLotTypeDown.js";
import { getLotTypes } from "../../helpers/functions.cache.js";
export const handler: RequestHandler = async (request, response) => {
const success = moveLotTypeDown(request.body.lotTypeId);
const lotTypes = getLotTypes();
response.json({
success,
lotTypes
});
};
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,11 @@
import { moveLotTypeFieldDown } from "../../helpers/lotOccupancyDB/moveLotTypeFieldDown.js";
import { getLotTypes } from "../../helpers/functions.cache.js";
export const handler = async (request, response) => {
const success = moveLotTypeFieldDown(request.body.lotTypeFieldId);
const lotTypes = getLotTypes();
response.json({
success,
lotTypes
});
};
export default handler;

View File

@ -0,0 +1,18 @@
import type { RequestHandler } from "express";
import { moveLotTypeFieldDown } from "../../helpers/lotOccupancyDB/moveLotTypeFieldDown.js";
import { getLotTypes } from "../../helpers/functions.cache.js";
export const handler: RequestHandler = async (request, response) => {
const success = moveLotTypeFieldDown(request.body.lotTypeFieldId);
const lotTypes = getLotTypes();
response.json({
success,
lotTypes
});
};
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,11 @@
import { moveLotTypeFieldUp } from "../../helpers/lotOccupancyDB/moveLotTypeFieldUp.js";
import { getLotTypes } from "../../helpers/functions.cache.js";
export const handler = async (request, response) => {
const success = moveLotTypeFieldUp(request.body.lotTypeFieldId);
const lotTypes = getLotTypes();
response.json({
success,
lotTypes
});
};
export default handler;

View File

@ -0,0 +1,18 @@
import type { RequestHandler } from "express";
import { moveLotTypeFieldUp } from "../../helpers/lotOccupancyDB/moveLotTypeFieldUp.js";
import { getLotTypes } from "../../helpers/functions.cache.js";
export const handler: RequestHandler = async (request, response) => {
const success = moveLotTypeFieldUp(request.body.lotTypeFieldId);
const lotTypes = getLotTypes();
response.json({
success,
lotTypes
});
};
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,11 @@
import { moveLotTypeUp } from "../../helpers/lotOccupancyDB/moveLotTypeUp.js";
import { getLotTypes } from "../../helpers/functions.cache.js";
export const handler = async (request, response) => {
const success = moveLotTypeUp(request.body.lotTypeId);
const lotTypes = getLotTypes();
response.json({
success,
lotTypes
});
};
export default handler;

View File

@ -0,0 +1,18 @@
import type { RequestHandler } from "express";
import { moveLotTypeUp } from "../../helpers/lotOccupancyDB/moveLotTypeUp.js";
import { getLotTypes } from "../../helpers/functions.cache.js";
export const handler: RequestHandler = async (request, response) => {
const success = moveLotTypeUp(request.body.lotTypeId);
const lotTypes = getLotTypes();
response.json({
success,
lotTypes
});
};
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,11 @@
import { updateLotType } from "../../helpers/lotOccupancyDB/updateLotType.js";
import { getLotTypes } from "../../helpers/functions.cache.js";
export const handler = async (request, response) => {
const success = updateLotType(request.body, request.session);
const lotTypes = getLotTypes();
response.json({
success,
lotTypes
});
};
export default handler;

View File

@ -0,0 +1,18 @@
import type { RequestHandler } from "express";
import { updateLotType } from "../../helpers/lotOccupancyDB/updateLotType.js";
import { getLotTypes } from "../../helpers/functions.cache.js";
export const handler: RequestHandler = async (request, response) => {
const success = updateLotType(request.body, request.session);
const lotTypes = getLotTypes();
response.json({
success,
lotTypes
});
};
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,11 @@
import { updateLotTypeField } from "../../helpers/lotOccupancyDB/updateLotTypeField.js";
import { getLotTypes } from "../../helpers/functions.cache.js";
export const handler = async (request, response) => {
const success = updateLotTypeField(request.body, request.session);
const lotTypes = getLotTypes();
response.json({
success,
lotTypes
});
};
export default handler;

View File

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

View File

@ -10,7 +10,7 @@ export const addLotType = (lotTypeForm, requestSession) => {
" recordCreate_userName, recordCreate_timeMillis," +
" recordUpdate_userName, recordUpdate_timeMillis)" +
" values (?, ?, ?, ?, ?, ?)")
.run(lotTypeForm.lotType, lotTypeForm.orderNumber || 0, requestSession.user.userName, rightNowMillis, requestSession.user.userName, rightNowMillis);
.run(lotTypeForm.lotType, lotTypeForm.orderNumber || -1, requestSession.user.userName, rightNowMillis, requestSession.user.userName, rightNowMillis);
database.close();
clearLotTypesCache();
return result.lastInsertRowid;

View File

@ -29,7 +29,7 @@ export const addLotType = (
)
.run(
lotTypeForm.lotType,
lotTypeForm.orderNumber || 0,
lotTypeForm.orderNumber || -1,
requestSession.user.userName,
rightNowMillis,
requestSession.user.userName,

View File

@ -0,0 +1,13 @@
import type * as recordTypes from "../../types/recordTypes";
interface AddLotTypeFieldForm {
lotTypeId: string | number;
lotTypeField: string;
lotTypeFieldValues?: string;
isRequired?: string;
pattern?: string;
minimumLength: string | number;
maximumLength: string | number;
orderNumber?: number;
}
export declare const addLotTypeField: (lotTypeFieldForm: AddLotTypeFieldForm, requestSession: recordTypes.PartialSession) => number;
export default addLotTypeField;

View File

@ -0,0 +1,21 @@
import sqlite from "better-sqlite3";
import { lotOccupancyDB as databasePath } from "../../data/databasePaths.js";
import { clearLotTypesCache } from "../functions.cache.js";
export const addLotTypeField = (lotTypeFieldForm, requestSession) => {
const database = sqlite(databasePath);
const rightNowMillis = Date.now();
const result = database
.prepare("insert into LotTypeFields (" +
"lotTypeId, lotTypeField," +
" lotTypeFieldValues, isRequired, pattern," +
" minimumLength, maximumLength," +
" orderNumber," +
" recordCreate_userName, recordCreate_timeMillis," +
" recordUpdate_userName, recordUpdate_timeMillis)" +
" values (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)")
.run(lotTypeFieldForm.lotTypeId, lotTypeFieldForm.lotTypeField, lotTypeFieldForm.lotTypeFieldValues || "", lotTypeFieldForm.isRequired ? 1 : 0, lotTypeFieldForm.pattern || "", lotTypeFieldForm.minimumLength || 0, lotTypeFieldForm.maximumLength || 100, lotTypeFieldForm.orderNumber || -1, requestSession.user.userName, rightNowMillis, requestSession.user.userName, rightNowMillis);
database.close();
clearLotTypesCache();
return result.lastInsertRowid;
};
export default addLotTypeField;

View File

@ -0,0 +1,60 @@
import sqlite from "better-sqlite3";
import { lotOccupancyDB as databasePath } from "../../data/databasePaths.js";
import type * as recordTypes from "../../types/recordTypes";
import { clearLotTypesCache } from "../functions.cache.js";
interface AddLotTypeFieldForm {
lotTypeId: string | number;
lotTypeField: string;
lotTypeFieldValues?: string;
isRequired?: string;
pattern?: string;
minimumLength: string | number;
maximumLength: string | number;
orderNumber?: number;
}
export const addLotTypeField = (
lotTypeFieldForm: AddLotTypeFieldForm,
requestSession: recordTypes.PartialSession
): number => {
const database = sqlite(databasePath);
const rightNowMillis = Date.now();
const result = database
.prepare(
"insert into LotTypeFields (" +
"lotTypeId, lotTypeField," +
" lotTypeFieldValues, isRequired, pattern," +
" minimumLength, maximumLength," +
" orderNumber," +
" recordCreate_userName, recordCreate_timeMillis," +
" recordUpdate_userName, recordUpdate_timeMillis)" +
" values (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)"
)
.run(
lotTypeFieldForm.lotTypeId,
lotTypeFieldForm.lotTypeField,
lotTypeFieldForm.lotTypeFieldValues || "",
lotTypeFieldForm.isRequired ? 1 : 0,
lotTypeFieldForm.pattern || "",
lotTypeFieldForm.minimumLength || 0,
lotTypeFieldForm.maximumLength || 100,
lotTypeFieldForm.orderNumber || -1,
requestSession.user.userName,
rightNowMillis,
requestSession.user.userName,
rightNowMillis
);
database.close();
clearLotTypesCache();
return result.lastInsertRowid as number;
};
export default addLotTypeField;

View File

@ -0,0 +1,3 @@
import type * as recordTypes from "../../types/recordTypes";
export declare const deleteLotType: (lotTypeId: number | string, requestSession: recordTypes.PartialSession) => boolean;
export default deleteLotType;

View File

@ -0,0 +1,23 @@
import sqlite from "better-sqlite3";
import { lotOccupancyDB as databasePath } from "../../data/databasePaths.js";
import { clearLotTypesCache } from "../functions.cache.js";
export const deleteLotType = (lotTypeId, requestSession) => {
const database = sqlite(databasePath);
const rightNowMillis = Date.now();
const result = database
.prepare("update LotTypes" +
" set recordDelete_userName = ?," +
" recordDelete_timeMillis = ?" +
" where lotTypeId = ?")
.run(requestSession.user.userName, rightNowMillis, lotTypeId);
database
.prepare("update LotTypeFields" +
" set recordDelete_userName = ?," +
" recordDelete_timeMillis = ?" +
" where lotTypeId = ?")
.run(requestSession.user.userName, rightNowMillis, lotTypeId);
database.close();
clearLotTypesCache();
return result.changes > 0;
};
export default deleteLotType;

View File

@ -0,0 +1,42 @@
import sqlite from "better-sqlite3";
import { lotOccupancyDB as databasePath } from "../../data/databasePaths.js";
import { clearLotTypesCache } from "../functions.cache.js";
import type * as recordTypes from "../../types/recordTypes";
export const deleteLotType = (
lotTypeId: number | string,
requestSession: recordTypes.PartialSession
): boolean => {
const database = sqlite(databasePath);
const rightNowMillis = Date.now();
const result = database
.prepare(
"update LotTypes" +
" set recordDelete_userName = ?," +
" recordDelete_timeMillis = ?" +
" where lotTypeId = ?"
)
.run(requestSession.user.userName, rightNowMillis, lotTypeId);
database
.prepare(
"update LotTypeFields" +
" set recordDelete_userName = ?," +
" recordDelete_timeMillis = ?" +
" where lotTypeId = ?"
)
.run(requestSession.user.userName, rightNowMillis, lotTypeId)
database.close();
clearLotTypesCache();
return result.changes > 0;
};
export default deleteLotType;

View File

@ -0,0 +1,3 @@
import type * as recordTypes from "../../types/recordTypes";
export declare const deleteLotTypeField: (lotTypeFieldId: number | string, requestSession: recordTypes.PartialSession) => boolean;
export default deleteLotTypeField;

View File

@ -0,0 +1,17 @@
import sqlite from "better-sqlite3";
import { lotOccupancyDB as databasePath } from "../../data/databasePaths.js";
import { clearLotTypesCache } from "../functions.cache.js";
export const deleteLotTypeField = (lotTypeFieldId, requestSession) => {
const database = sqlite(databasePath);
const rightNowMillis = Date.now();
const result = database
.prepare("update LotTypeFields" +
" set recordDelete_userName = ?," +
" recordDelete_timeMillis = ?" +
" where lotTypeFieldId = ?")
.run(requestSession.user.userName, rightNowMillis, lotTypeFieldId);
database.close();
clearLotTypesCache();
return result.changes > 0;
};
export default deleteLotTypeField;

View File

@ -0,0 +1,33 @@
import sqlite from "better-sqlite3";
import { lotOccupancyDB as databasePath } from "../../data/databasePaths.js";
import { clearLotTypesCache } from "../functions.cache.js";
import type * as recordTypes from "../../types/recordTypes";
export const deleteLotTypeField = (
lotTypeFieldId: number | string,
requestSession: recordTypes.PartialSession
): boolean => {
const database = sqlite(databasePath);
const rightNowMillis = Date.now();
const result = database
.prepare(
"update LotTypeFields" +
" set recordDelete_userName = ?," +
" recordDelete_timeMillis = ?" +
" where lotTypeFieldId = ?"
)
.run(requestSession.user.userName, rightNowMillis, lotTypeFieldId);
database.close();
clearLotTypesCache();
return result.changes > 0;
};
export default deleteLotTypeField;

View File

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

View File

@ -0,0 +1,30 @@
import sqlite from "better-sqlite3";
import { lotOccupancyDB as databasePath } from "../../data/databasePaths.js";
export const getLotTypeFields = (lotTypeId, connectedDatabase) => {
const database = connectedDatabase || sqlite(databasePath);
const lotTypeFields = database
.prepare("select lotTypeFieldId," +
" lotTypeField, lotTypeFieldValues, isRequired, pattern," +
" minimumLength, maximumLength," +
" orderNumber" +
" from LotTypeFields" +
" where recordDelete_timeMillis is null" +
" and lotTypeId = ?" +
" order by orderNumber, lotTypeField")
.all(lotTypeId);
let expectedFieldOrderNumber = -1;
for (const lotTypeField of lotTypeFields) {
expectedFieldOrderNumber += 1;
if (lotTypeField.orderNumber !== expectedFieldOrderNumber) {
database
.prepare("update LotTypeFields set orderNumber = ? where lotTypeFieldId = ?")
.run(expectedFieldOrderNumber, lotTypeField.lotTypeFieldId);
lotTypeField.orderNumber = expectedFieldOrderNumber;
}
}
if (!connectedDatabase) {
database.close();
}
return lotTypeFields;
};
export default getLotTypeFields;

View File

@ -0,0 +1,49 @@
import sqlite from "better-sqlite3";
import { lotOccupancyDB as databasePath } from "../../data/databasePaths.js";
import type * as recordTypes from "../../types/recordTypes";
export const getLotTypeFields = (
lotTypeId: number,
connectedDatabase?: sqlite.Database
): recordTypes.LotTypeField[] => {
const database = connectedDatabase || sqlite(databasePath);
const lotTypeFields: recordTypes.LotTypeField[] = database
.prepare(
"select lotTypeFieldId," +
" lotTypeField, lotTypeFieldValues, isRequired, pattern," +
" minimumLength, maximumLength," +
" orderNumber" +
" from LotTypeFields" +
" where recordDelete_timeMillis is null" +
" and lotTypeId = ?" +
" order by orderNumber, lotTypeField"
)
.all(lotTypeId);
let expectedFieldOrderNumber = -1;
for (const lotTypeField of lotTypeFields) {
expectedFieldOrderNumber += 1;
if (lotTypeField.orderNumber !== expectedFieldOrderNumber) {
database
.prepare(
"update LotTypeFields set orderNumber = ? where lotTypeFieldId = ?"
)
.run(expectedFieldOrderNumber, lotTypeField.lotTypeFieldId);
lotTypeField.orderNumber = expectedFieldOrderNumber;
}
}
if (!connectedDatabase) {
database.close();
}
return lotTypeFields;
};
export default getLotTypeFields;

View File

@ -1,15 +1,37 @@
import sqlite from "better-sqlite3";
import { lotOccupancyDB as databasePath } from "../../data/databasePaths.js";
import { getLotTypeFields } from "./getLotTypeFields.js";
export const getLotTypes = () => {
const database = sqlite(databasePath, {
readonly: true
});
const database = sqlite(databasePath);
const lotTypes = database
.prepare("select lotTypeId, lotType" +
.prepare("select lotTypeId, lotType, orderNumber" +
" from LotTypes" +
" where recordDelete_timeMillis is null" +
" order by orderNumber, lotType")
.all();
let expectedTypeOrderNumber = -1;
for (const lotType of lotTypes) {
expectedTypeOrderNumber += 1;
if (lotType.orderNumber !== expectedTypeOrderNumber) {
database
.prepare("update LotTypes set orderNumber = ? where lotTypeId = ?")
.run(expectedTypeOrderNumber, lotType.lotTypeId);
lotType.orderNumber = expectedTypeOrderNumber;
}
lotType.lotTypeFields = getLotTypeFields(lotType.lotTypeId, database);
let expectedFieldOrderNumber = -1;
for (const lotTypeField of lotType.lotTypeFields) {
expectedFieldOrderNumber += 1;
if (lotTypeField.orderNumber !== expectedFieldOrderNumber) {
database
.prepare("update LotTypeFields" +
" set orderNumber = ?" +
" where lotTypeFieldId = ?")
.run(expectedFieldOrderNumber, lotTypeField.lotTypeFieldId);
lotTypeField.orderNumber = expectedFieldOrderNumber;
}
}
}
database.close();
return lotTypes;
};

View File

@ -2,22 +2,61 @@ import sqlite from "better-sqlite3";
import { lotOccupancyDB as databasePath } from "../../data/databasePaths.js";
import { getLotTypeFields } from "./getLotTypeFields.js";
import type * as recordTypes from "../../types/recordTypes";
export const getLotTypes = (): recordTypes.LotType[] => {
const database = sqlite(databasePath, {
readonly: true
});
const database = sqlite(databasePath);
const lotTypes: recordTypes.LotType[] = database
.prepare(
"select lotTypeId, lotType" +
"select lotTypeId, lotType, orderNumber" +
" from LotTypes" +
" where recordDelete_timeMillis is null" +
" order by orderNumber, lotType"
)
.all();
let expectedTypeOrderNumber = -1;
for (const lotType of lotTypes) {
expectedTypeOrderNumber += 1;
if (lotType.orderNumber !== expectedTypeOrderNumber) {
database
.prepare(
"update LotTypes set orderNumber = ? where lotTypeId = ?"
)
.run(expectedTypeOrderNumber, lotType.lotTypeId);
lotType.orderNumber = expectedTypeOrderNumber;
}
lotType.lotTypeFields = getLotTypeFields(
lotType.lotTypeId,
database
);
let expectedFieldOrderNumber = -1;
for (const lotTypeField of lotType.lotTypeFields) {
expectedFieldOrderNumber += 1;
if (lotTypeField.orderNumber !== expectedFieldOrderNumber) {
database
.prepare(
"update LotTypeFields" +
" set orderNumber = ?" +
" where lotTypeFieldId = ?"
)
.run(expectedFieldOrderNumber, lotTypeField.lotTypeFieldId);
lotTypeField.orderNumber = expectedFieldOrderNumber;
}
}
}
database.close();
return lotTypes;

View File

@ -0,0 +1,2 @@
export declare const moveLotTypeDown: (lotTypeId: number | string) => boolean;
export default moveLotTypeDown;

View File

@ -0,0 +1,22 @@
import sqlite from "better-sqlite3";
import { lotOccupancyDB as databasePath } from "../../data/databasePaths.js";
import { clearLotTypesCache } from "../functions.cache.js";
export const moveLotTypeDown = (lotTypeId) => {
const database = sqlite(databasePath);
const currentOrderNumber = database
.prepare("select orderNumber" + " from LotTypes" + " where lotTypeId = ?")
.get(lotTypeId).orderNumber;
database
.prepare("update LotTypes" +
" set orderNumber = orderNumber - 1" +
" where recordDelete_timeMillis is null" +
" and orderNumber = ? + 1")
.run(currentOrderNumber);
const result = database
.prepare("update LotTypes" + " set orderNumber = ? + 1" + " where lotTypeId = ?")
.run(currentOrderNumber, lotTypeId);
database.close();
clearLotTypesCache();
return result.changes > 0;
};
export default moveLotTypeDown;

View File

@ -0,0 +1,34 @@
import sqlite from "better-sqlite3";
import { lotOccupancyDB as databasePath } from "../../data/databasePaths.js";
import { clearLotTypesCache } from "../functions.cache.js";
export const moveLotTypeDown = (lotTypeId: number | string): boolean => {
const database = sqlite(databasePath);
const currentOrderNumber: number = database
.prepare("select orderNumber" + " from LotTypes" + " where lotTypeId = ?")
.get(lotTypeId).orderNumber;
database
.prepare(
"update LotTypes" +
" set orderNumber = orderNumber - 1" +
" where recordDelete_timeMillis is null" +
" and orderNumber = ? + 1"
)
.run(currentOrderNumber);
const result = database
.prepare("update LotTypes" + " set orderNumber = ? + 1" + " where lotTypeId = ?")
.run(currentOrderNumber, lotTypeId);
database.close();
clearLotTypesCache();
return result.changes > 0;
};
export default moveLotTypeDown;

View File

@ -0,0 +1,2 @@
export declare const moveLotTypeFieldDown: (lotTypeFieldId: number | string) => boolean;
export default moveLotTypeFieldDown;

View File

@ -0,0 +1,23 @@
import sqlite from "better-sqlite3";
import { lotOccupancyDB as databasePath } from "../../data/databasePaths.js";
import { clearLotTypesCache } from "../functions.cache.js";
export const moveLotTypeFieldDown = (lotTypeFieldId) => {
const database = sqlite(databasePath);
const currentField = database
.prepare("select lotTypeId, orderNumber from LotTypeFields where lotTypeFieldId = ?")
.get(lotTypeFieldId);
database
.prepare("update LotTypeFields" +
" set orderNumber = orderNumber - 1" +
" where recordDelete_timeMillis is null" +
" and lotTypeId = ?" +
" and orderNumber = ? + 1")
.run(currentField.lotTypeId, currentField.orderNumber);
const result = database
.prepare("update LotTypeFields set orderNumber = ? + 1 where lotTypeFieldId = ?")
.run(currentField.orderNumber, lotTypeFieldId);
database.close();
clearLotTypesCache();
return result.changes > 0;
};
export default moveLotTypeFieldDown;

View File

@ -0,0 +1,37 @@
import sqlite from "better-sqlite3";
import { lotOccupancyDB as databasePath } from "../../data/databasePaths.js";
import { clearLotTypesCache } from "../functions.cache.js";
export const moveLotTypeFieldDown = (lotTypeFieldId: number | string): boolean => {
const database = sqlite(databasePath);
const currentField: { lotTypeId?: number; orderNumber: number } = database
.prepare(
"select lotTypeId, orderNumber from LotTypeFields where lotTypeFieldId = ?"
)
.get(lotTypeFieldId);
database
.prepare(
"update LotTypeFields" +
" set orderNumber = orderNumber - 1" +
" where recordDelete_timeMillis is null" +
" and lotTypeId = ?" +
" and orderNumber = ? + 1"
)
.run(currentField.lotTypeId, currentField.orderNumber);
const result = database
.prepare("update LotTypeFields set orderNumber = ? + 1 where lotTypeFieldId = ?")
.run(currentField.orderNumber, lotTypeFieldId);
database.close();
clearLotTypesCache();
return result.changes > 0;
};
export default moveLotTypeFieldDown;

View File

@ -0,0 +1,2 @@
export declare const moveLotTypeFieldUp: (lotTypeFieldId: number | string) => boolean;
export default moveLotTypeFieldUp;

View File

@ -0,0 +1,27 @@
import sqlite from "better-sqlite3";
import { lotOccupancyDB as databasePath } from "../../data/databasePaths.js";
import { clearLotTypesCache } from "../functions.cache.js";
export const moveLotTypeFieldUp = (lotTypeFieldId) => {
const database = sqlite(databasePath);
const currentField = database
.prepare("select lotTypeId, orderNumber" + " from LotTypeFields" + " where lotTypeFieldId = ?")
.get(lotTypeFieldId);
if (currentField.orderNumber <= 0) {
database.close();
return true;
}
database
.prepare("update LotTypeFields" +
" set orderNumber = orderNumber + 1" +
" where recordDelete_timeMillis is null" +
" and lotTypeId = ?" +
" and orderNumber = ? - 1")
.run(currentField.lotTypeId, currentField.orderNumber);
const result = database
.prepare("update LotTypeFields" + " set orderNumber = ? - 1" + " where lotTypeFieldId = ?")
.run(currentField.orderNumber, lotTypeFieldId);
database.close();
clearLotTypesCache();
return result.changes > 0;
};
export default moveLotTypeFieldUp;

View File

@ -0,0 +1,42 @@
import sqlite from "better-sqlite3";
import { lotOccupancyDB as databasePath } from "../../data/databasePaths.js";
import { clearLotTypesCache } from "../functions.cache.js";
export const moveLotTypeFieldUp = (lotTypeFieldId: number | string): boolean => {
const database = sqlite(databasePath);
const currentField: { lotTypeId: number; orderNumber: number } = database
.prepare(
"select lotTypeId, orderNumber" + " from LotTypeFields" + " where lotTypeFieldId = ?"
)
.get(lotTypeFieldId);
if (currentField.orderNumber <= 0) {
database.close();
return true;
}
database
.prepare(
"update LotTypeFields" +
" set orderNumber = orderNumber + 1" +
" where recordDelete_timeMillis is null" +
" and lotTypeId = ?" +
" and orderNumber = ? - 1"
)
.run(currentField.lotTypeId, currentField.orderNumber);
const result = database
.prepare("update LotTypeFields" + " set orderNumber = ? - 1" + " where lotTypeFieldId = ?")
.run(currentField.orderNumber, lotTypeFieldId);
database.close();
clearLotTypesCache();
return result.changes > 0;
};
export default moveLotTypeFieldUp;

View File

@ -0,0 +1,2 @@
export declare const moveLotTypeUp: (lotTypeId: number | string) => boolean;
export default moveLotTypeUp;

View File

@ -0,0 +1,30 @@
import sqlite from "better-sqlite3";
import { lotOccupancyDB as databasePath } from "../../data/databasePaths.js";
import { clearLotTypesCache } from "../functions.cache.js";
export const moveLotTypeUp = (lotTypeId) => {
const database = sqlite(databasePath);
const currentOrderNumber = database
.prepare("select orderNumber" +
" from LotTypes" +
" where lotTypeId = ?")
.get(lotTypeId).orderNumber;
if (currentOrderNumber <= 0) {
database.close();
return true;
}
database
.prepare("update LotTypes" +
" set orderNumber = orderNumber + 1" +
" where recordDelete_timeMillis is null" +
" and orderNumber = ? - 1")
.run(currentOrderNumber);
const result = database
.prepare("update LotTypes" +
" set orderNumber = ? - 1" +
" where lotTypeId = ?")
.run(currentOrderNumber, lotTypeId);
database.close();
clearLotTypesCache();
return result.changes > 0;
};
export default moveLotTypeUp;

View File

@ -0,0 +1,49 @@
import sqlite from "better-sqlite3";
import { lotOccupancyDB as databasePath } from "../../data/databasePaths.js";
import { clearLotTypesCache } from "../functions.cache.js";
export const moveLotTypeUp = (
lotTypeId: number | string
): boolean => {
const database = sqlite(databasePath);
const currentOrderNumber: number = database
.prepare(
"select orderNumber" +
" from LotTypes" +
" where lotTypeId = ?"
)
.get(lotTypeId).orderNumber;
if (currentOrderNumber <= 0) {
database.close();
return true;
}
database
.prepare(
"update LotTypes" +
" set orderNumber = orderNumber + 1" +
" where recordDelete_timeMillis is null" +
" and orderNumber = ? - 1"
)
.run(currentOrderNumber);
const result = database
.prepare(
"update LotTypes" +
" set orderNumber = ? - 1" +
" where lotTypeId = ?"
)
.run(currentOrderNumber, lotTypeId);
database.close();
clearLotTypesCache();
return result.changes > 0;
};
export default moveLotTypeUp;

View File

@ -0,0 +1,7 @@
import type * as recordTypes from "../../types/recordTypes";
interface UpdateLotTypeForm {
lotTypeId: number | string;
lotType: string;
}
export declare const updateLotType: (lotTypeForm: UpdateLotTypeForm, requestSession: recordTypes.PartialSession) => boolean;
export default updateLotType;

View File

@ -0,0 +1,19 @@
import sqlite from "better-sqlite3";
import { lotOccupancyDB as databasePath } from "../../data/databasePaths.js";
import { clearLotTypesCache } from "../functions.cache.js";
export const updateLotType = (lotTypeForm, requestSession) => {
const database = sqlite(databasePath);
const rightNowMillis = Date.now();
const result = database
.prepare("update LotTypes" +
" set lotType = ?," +
" recordUpdate_userName = ?," +
" recordUpdate_timeMillis = ?" +
" where lotTypeId = ?" +
" and recordDelete_timeMillis is null")
.run(lotTypeForm.lotType, requestSession.user.userName, rightNowMillis, lotTypeForm.lotTypeId);
database.close();
clearLotTypesCache();
return result.changes > 0;
};
export default updateLotType;

View File

@ -0,0 +1,45 @@
import sqlite from "better-sqlite3";
import { lotOccupancyDB as databasePath } from "../../data/databasePaths.js";
import { clearLotTypesCache } from "../functions.cache.js";
import type * as recordTypes from "../../types/recordTypes";
interface UpdateLotTypeForm {
lotTypeId: number | string;
lotType: string;
}
export const updateLotType = (
lotTypeForm: UpdateLotTypeForm,
requestSession: recordTypes.PartialSession
): boolean => {
const database = sqlite(databasePath);
const rightNowMillis = Date.now();
const result = database
.prepare(
"update LotTypes" +
" set lotType = ?," +
" recordUpdate_userName = ?," +
" recordUpdate_timeMillis = ?" +
" where lotTypeId = ?" +
" and recordDelete_timeMillis is null"
)
.run(
lotTypeForm.lotType,
requestSession.user.userName,
rightNowMillis,
lotTypeForm.lotTypeId
);
database.close();
clearLotTypesCache();
return result.changes > 0;
};
export default updateLotType;

View File

@ -0,0 +1,12 @@
import type * as recordTypes from "../../types/recordTypes";
interface UpdateLotTypeFieldForm {
lotTypeFieldId: number | string;
lotTypeField: string;
isRequired: "0" | "1";
minimumLength?: string;
maximumLength?: string;
pattern?: string;
lotTypeFieldValues: string;
}
export declare const updateLotTypeField: (lotTypeFieldForm: UpdateLotTypeFieldForm, requestSession: recordTypes.PartialSession) => boolean;
export default updateLotTypeField;

View File

@ -0,0 +1,24 @@
import sqlite from "better-sqlite3";
import { lotOccupancyDB as databasePath } from "../../data/databasePaths.js";
import { clearLotTypesCache } from "../functions.cache.js";
export const updateLotTypeField = (lotTypeFieldForm, requestSession) => {
const database = sqlite(databasePath);
const rightNowMillis = Date.now();
const result = database
.prepare("update LotTypeFields" +
" set lotTypeField = ?," +
" isRequired = ?," +
" minimumLength = ?," +
" maximumLength = ?," +
" pattern = ?," +
" lotTypeFieldValues = ?," +
" recordUpdate_userName = ?," +
" recordUpdate_timeMillis = ?" +
" where lotTypeFieldId = ?" +
" and recordDelete_timeMillis is null")
.run(lotTypeFieldForm.lotTypeField, Number.parseInt(lotTypeFieldForm.isRequired, 10), lotTypeFieldForm.minimumLength || 0, lotTypeFieldForm.maximumLength || 100, lotTypeFieldForm.pattern || "", lotTypeFieldForm.lotTypeFieldValues, requestSession.user.userName, rightNowMillis, lotTypeFieldForm.lotTypeFieldId);
database.close();
clearLotTypesCache();
return result.changes > 0;
};
export default updateLotTypeField;

View File

@ -0,0 +1,60 @@
import sqlite from "better-sqlite3";
import { lotOccupancyDB as databasePath } from "../../data/databasePaths.js";
import { clearLotTypesCache } from "../functions.cache.js";
import type * as recordTypes from "../../types/recordTypes";
interface UpdateLotTypeFieldForm {
lotTypeFieldId: number | string;
lotTypeField: string;
isRequired: "0" | "1";
minimumLength?: string;
maximumLength?: string;
pattern?: string;
lotTypeFieldValues: string;
}
export const updateLotTypeField = (
lotTypeFieldForm: UpdateLotTypeFieldForm,
requestSession: recordTypes.PartialSession
): boolean => {
const database = sqlite(databasePath);
const rightNowMillis = Date.now();
const result = database
.prepare(
"update LotTypeFields" +
" set lotTypeField = ?," +
" isRequired = ?," +
" minimumLength = ?," +
" maximumLength = ?," +
" pattern = ?," +
" lotTypeFieldValues = ?," +
" recordUpdate_userName = ?," +
" recordUpdate_timeMillis = ?" +
" where lotTypeFieldId = ?" +
" and recordDelete_timeMillis is null"
)
.run(
lotTypeFieldForm.lotTypeField,
Number.parseInt(lotTypeFieldForm.isRequired, 10),
lotTypeFieldForm.minimumLength || 0,
lotTypeFieldForm.maximumLength || 100,
lotTypeFieldForm.pattern || "",
lotTypeFieldForm.lotTypeFieldValues,
requestSession.user.userName,
rightNowMillis,
lotTypeFieldForm.lotTypeFieldId
);
database.close();
clearLotTypesCache();
return result.changes > 0;
};
export default updateLotTypeField;

View File

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

View File

@ -0,0 +1,435 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
(() => {
const los = exports.los;
const urlPrefix = document.querySelector("main").dataset.urlPrefix;
const containerElement = document.querySelector("#container--lotTypes");
let lotTypes = exports.lotTypes;
delete exports.lotTypes;
const expandedLotTypes = new Set();
const toggleLotTypeFields = (clickEvent) => {
const toggleButtonElement = clickEvent.currentTarget;
const lotTypeElement = toggleButtonElement.closest(".container--lotType");
const lotTypeId = Number.parseInt(lotTypeElement.dataset.lotTypeId, 10);
if (expandedLotTypes.has(lotTypeId)) {
expandedLotTypes.delete(lotTypeId);
}
else {
expandedLotTypes.add(lotTypeId);
}
toggleButtonElement.innerHTML = expandedLotTypes.has(lotTypeId)
? '<i class="fas fa-fw fa-minus" aria-hidden="true"></i>'
: '<i class="fas fa-fw fa-plus" aria-hidden="true"></i>';
const panelBlockElements = lotTypeElement.querySelectorAll(".panel-block");
for (const panelBlockElement of panelBlockElements) {
panelBlockElement.classList.toggle("is-hidden");
}
};
const lotTypeResponseHandler = (responseJSON) => {
if (responseJSON.success) {
lotTypes = responseJSON.lotTypes;
renderLotTypes();
}
else {
bulmaJS.alert({
title: "Error Updating " + exports.aliases.lot + " Type",
message: responseJSON.errorMessage,
contextualColorName: "danger"
});
}
};
const deleteLotType = (clickEvent) => {
const lotTypeId = Number.parseInt(clickEvent.currentTarget.closest(".container--lotType").dataset.lotTypeId, 10);
const doDelete = () => {
cityssm.postJSON(urlPrefix + "/admin/doDeleteLotType", {
lotTypeId
}, lotTypeResponseHandler);
};
bulmaJS.confirm({
title: "Delete " + exports.aliases.lot + " Type",
message: "Are you sure you want to delete this " +
exports.aliases.lot.toLowerCase() +
" type?",
contextualColorName: "warning",
okButton: {
text: "Yes, Delete " + exports.aliases.lot + " Type",
callbackFunction: doDelete
}
});
};
const openEditLotType = (clickEvent) => {
const lotTypeId = Number.parseInt(clickEvent.currentTarget.closest(".container--lotType").dataset.lotTypeId, 10);
const lotType = lotTypes.find((currentLotType) => {
return lotTypeId === currentLotType.lotTypeId;
});
let editCloseModalFunction;
const doEdit = (submitEvent) => {
submitEvent.preventDefault();
cityssm.postJSON(urlPrefix + "/admin/doUpdateLotType", submitEvent.currentTarget, (responseJSON) => {
lotTypeResponseHandler(responseJSON);
if (responseJSON.success) {
editCloseModalFunction();
}
});
};
cityssm.openHtmlModal("adminLotTypes-editLotType", {
onshow: (modalElement) => {
los.populateAliases(modalElement);
modalElement.querySelector("#lotTypeEdit--lotTypeId").value =
lotTypeId.toString();
modalElement.querySelector("#lotTypeEdit--lotType").value =
lotType.lotType;
},
onshown: (modalElement, closeModalFunction) => {
editCloseModalFunction = closeModalFunction;
modalElement.querySelector("#lotTypeEdit--lotType").focus();
modalElement.querySelector("form").addEventListener("submit", doEdit);
bulmaJS.toggleHtmlClipped();
},
onremoved: () => {
bulmaJS.toggleHtmlClipped();
}
});
};
const openAddLotTypeField = (clickEvent) => {
const lotTypeId = Number.parseInt(clickEvent.currentTarget.closest(".container--lotType").dataset.lotTypeId, 10);
let addCloseModalFunction;
const doAdd = (submitEvent) => {
submitEvent.preventDefault();
cityssm.postJSON(urlPrefix + "/admin/doAddLotTypeField", submitEvent.currentTarget, (responseJSON) => {
expandedLotTypes.add(lotTypeId);
lotTypeResponseHandler(responseJSON);
if (responseJSON.success) {
addCloseModalFunction();
openEditLotTypeField(lotTypeId, responseJSON.lotTypeFieldId);
}
});
};
cityssm.openHtmlModal("adminLotTypes-addLotTypeField", {
onshow: (modalElement) => {
los.populateAliases(modalElement);
if (lotTypeId) {
modalElement.querySelector("#lotTypeFieldAdd--lotTypeId").value = lotTypeId.toString();
}
},
onshown: (modalElement, closeModalFunction) => {
addCloseModalFunction = closeModalFunction;
modalElement.querySelector("#lotTypeFieldAdd--lotTypeField").focus();
modalElement.querySelector("form").addEventListener("submit", doAdd);
bulmaJS.toggleHtmlClipped();
},
onremoved: () => {
bulmaJS.toggleHtmlClipped();
}
});
};
const moveLotTypeUp = (clickEvent) => {
clickEvent.preventDefault();
const lotTypeId = clickEvent.currentTarget.closest(".container--lotType").dataset.lotTypeId;
cityssm.postJSON(urlPrefix + "/admin/doMoveLotTypeUp", {
lotTypeId
}, lotTypeResponseHandler);
};
const moveLotTypeDown = (clickEvent) => {
clickEvent.preventDefault();
const lotTypeId = clickEvent.currentTarget.closest(".container--lotType").dataset.lotTypeId;
cityssm.postJSON(urlPrefix + "/admin/doMoveLotTypeDown", {
lotTypeId
}, lotTypeResponseHandler);
};
const openEditLotTypeField = (lotTypeId, lotTypeFieldId) => {
const lotType = lotTypes.find((currentLotType) => {
return currentLotType.lotTypeId === lotTypeId;
});
const lotTypeField = lotType.lotTypeFields.find((currentLotTypeField) => {
return currentLotTypeField.lotTypeFieldId === lotTypeFieldId;
});
let minimumLengthElement;
let maximumLengthElement;
let patternElement;
let lotTypeFieldValuesElement;
let editCloseModalFunction;
const updateMaximumLengthMin = () => {
maximumLengthElement.min = minimumLengthElement.value;
};
const toggleInputFields = () => {
if (lotTypeFieldValuesElement.value === "") {
minimumLengthElement.disabled = false;
maximumLengthElement.disabled = false;
patternElement.disabled = false;
}
else {
minimumLengthElement.disabled = true;
maximumLengthElement.disabled = true;
patternElement.disabled = true;
}
};
const doUpdate = (submitEvent) => {
submitEvent.preventDefault();
cityssm.postJSON(urlPrefix + "/admin/doUpdateLotTypeField", submitEvent.currentTarget, (responseJSON) => {
lotTypeResponseHandler(responseJSON);
if (responseJSON.success) {
editCloseModalFunction();
}
});
};
const doDelete = () => {
const _doDelete = () => {
cityssm.postJSON(urlPrefix + "/admin/doDeleteLotTypeField", {
lotTypeFieldId
}, (responseJSON) => {
lotTypeResponseHandler(responseJSON);
if (responseJSON.success) {
editCloseModalFunction();
}
});
};
bulmaJS.confirm({
title: "Delete Field",
message: "Are you sure you want to delete this field? Note that historical records that make use of this field will not be affected.",
contextualColorName: "warning",
okButton: {
text: "Yes, Delete Field",
callbackFunction: _doDelete
}
});
};
cityssm.openHtmlModal("adminLotTypes-editLotTypeField", {
onshow: (modalElement) => {
los.populateAliases(modalElement);
modalElement.querySelector("#lotTypeFieldEdit--lotTypeFieldId").value = lotTypeField.lotTypeFieldId.toString();
modalElement.querySelector("#lotTypeFieldEdit--lotTypeField").value = lotTypeField.lotTypeField;
modalElement.querySelector("#lotTypeFieldEdit--isRequired").value = lotTypeField.isRequired ? "1" : "0";
minimumLengthElement = modalElement.querySelector("#lotTypeFieldEdit--minimumLength");
minimumLengthElement.value = lotTypeField.minimumLength.toString();
maximumLengthElement = modalElement.querySelector("#lotTypeFieldEdit--maximumLength");
maximumLengthElement.value = lotTypeField.maximumLength.toString();
patternElement = modalElement.querySelector("#lotTypeFieldEdit--pattern");
patternElement.value = lotTypeField.pattern;
lotTypeFieldValuesElement = modalElement.querySelector("#lotTypeFieldEdit--lotTypeFieldValues");
lotTypeFieldValuesElement.value = lotTypeField.lotTypeFieldValues;
toggleInputFields();
},
onshown: (modalElement, closeModalFunction) => {
editCloseModalFunction = closeModalFunction;
bulmaJS.init(modalElement);
bulmaJS.toggleHtmlClipped();
cityssm.enableNavBlocker();
modalElement.querySelector("form").addEventListener("submit", doUpdate);
minimumLengthElement.addEventListener("keyup", updateMaximumLengthMin);
updateMaximumLengthMin();
lotTypeFieldValuesElement.addEventListener("keyup", toggleInputFields);
modalElement
.querySelector("#button--deleteLotTypeField")
.addEventListener("click", doDelete);
},
onremoved: () => {
bulmaJS.toggleHtmlClipped();
cityssm.disableNavBlocker();
}
});
};
const openEditLotTypeFieldByClick = (clickEvent) => {
clickEvent.preventDefault();
const lotTypeFieldId = Number.parseInt(clickEvent.currentTarget.closest(".container--lotTypeField").dataset.lotTypeFieldId, 10);
const lotTypeId = Number.parseInt(clickEvent.currentTarget.closest(".container--lotType").dataset.lotTypeId, 10);
openEditLotTypeField(lotTypeId, lotTypeFieldId);
};
const moveLotTypeFieldUp = (clickEvent) => {
clickEvent.preventDefault();
const lotTypeFieldId = clickEvent.currentTarget.closest(".container--lotTypeField").dataset.lotTypeFieldId;
cityssm.postJSON(urlPrefix + "/admin/doMoveLotTypeFieldUp", {
lotTypeFieldId
}, lotTypeResponseHandler);
};
const moveLotTypeFieldDown = (clickEvent) => {
clickEvent.preventDefault();
const lotTypeFieldId = clickEvent.currentTarget.closest(".container--lotTypeField").dataset.lotTypeFieldId;
cityssm.postJSON(urlPrefix + "/admin/doMoveLotTypeFieldDown", {
lotTypeFieldId
}, lotTypeResponseHandler);
};
const renderLotTypeFields = (panelElement, lotTypeId, lotTypeFields) => {
if (lotTypeFields.length === 0) {
panelElement.insertAdjacentHTML("beforeend", '<div class="panel-block is-block' +
(expandedLotTypes.has(lotTypeId) ? "" : " is-hidden") +
'">' +
'<div class="message is-info">' +
'<p class="message-body">There are no additional fields.</p>' +
"</div>" +
"</div>");
}
else {
for (const lotTypeField of lotTypeFields) {
const panelBlockElement = document.createElement("div");
panelBlockElement.className = "panel-block is-block container--lotTypeField";
if (!expandedLotTypes.has(lotTypeId)) {
panelBlockElement.classList.add("is-hidden");
}
panelBlockElement.dataset.lotTypeFieldId = lotTypeField.lotTypeFieldId.toString();
panelBlockElement.innerHTML =
'<div class="level is-mobile">' +
'<div class="level-left">' +
('<div class="level-item">' +
'<a class="has-text-weight-bold button--editLotTypeField" href="#">' +
cityssm.escapeHTML(lotTypeField.lotTypeField) +
"</a>" +
"</div>") +
"</div>" +
'<div class="level-right">' +
('<div class="level-item">' +
'<div class="field has-addons">' +
'<div class="control">' +
'<button class="button is-small button--moveLotTypeFieldUp" data-tooltip="Move Up" type="button" aria-label="Move Up">' +
'<i class="fas fa-arrow-up" aria-hidden="true"></i>' +
"</button>" +
"</div>" +
'<div class="control">' +
'<button class="button is-small button--moveLotTypeFieldDown" data-tooltip="Move Down" type="button" aria-label="Move Down">' +
'<i class="fas fa-arrow-down" aria-hidden="true"></i>' +
"</button>" +
"</div>" +
"</div>" +
"</div>") +
"</div>" +
"</div>";
panelBlockElement
.querySelector(".button--editLotTypeField")
.addEventListener("click", openEditLotTypeFieldByClick);
panelBlockElement
.querySelector(".button--moveLotTypeFieldUp")
.addEventListener("click", moveLotTypeFieldUp);
panelBlockElement
.querySelector(".button--moveLotTypeFieldDown")
.addEventListener("click", moveLotTypeFieldDown);
panelElement.append(panelBlockElement);
}
}
};
const renderLotTypes = () => {
containerElement.innerHTML = "";
if (lotTypes.length === 0) {
containerElement.insertAdjacentHTML("afterbegin", '<div class="message is-warning>' +
'<p class="message-body">There are no active ' +
exports.aliases.lot.toLowerCase() +
" types.</p>" +
"</div>");
return;
}
for (const lotType of lotTypes) {
const lotTypeContainer = document.createElement("div");
lotTypeContainer.className = "panel container--lotType";
lotTypeContainer.dataset.lotTypeId = lotType.lotTypeId.toString();
lotTypeContainer.innerHTML =
'<div class="panel-heading">' +
'<div class="level is-mobile">' +
('<div class="level-left">' +
'<div class="level-item">' +
'<button class="button is-small button--toggleLotTypeFields" data-tooltip="Toggle Fields" type="button" aria-label="Toggle Fields">' +
(expandedLotTypes.has(lotType.lotTypeId)
? '<i class="fas fa-fw fa-minus" aria-hidden="true"></i>'
: '<i class="fas fa-fw fa-plus" aria-hidden="true"></i>') +
"</button>" +
"</div>" +
'<div class="level-item">' +
'<h2 class="title is-4">' +
cityssm.escapeHTML(lotType.lotType) +
"</h2>" +
"</div>" +
"</div>") +
('<div class="level-right">' +
('<div class="level-item">' +
'<button class="button is-danger is-small button--deleteLotType" type="button">' +
'<span class="icon is-small"><i class="fas fa-trash" aria-hidden="true"></i></span>' +
"<span>Delete</span>" +
"</button>" +
"</div>") +
('<div class="level-item">' +
'<button class="button is-primary is-small button--editLotType" type="button">' +
'<span class="icon is-small"><i class="fas fa-pencil-alt" aria-hidden="true"></i></span>' +
"<span>Edit " +
exports.aliases.lot +
" Type</span>" +
"</button>" +
"</div>") +
('<div class="level-item">' +
'<button class="button is-success is-small button--addLotTypeField" type="button">' +
'<span class="icon is-small"><i class="fas fa-plus" aria-hidden="true"></i></span>' +
"<span>Add Field</span>" +
"</button>" +
"</div>") +
('<div class="level-item">' +
'<div class="field has-addons">' +
'<div class="control">' +
'<button class="button is-small button--moveLotTypeUp" data-tooltip="Move Up" type="button" aria-label="Move Up">' +
'<i class="fas fa-arrow-up" aria-hidden="true"></i>' +
"</button>" +
"</div>" +
'<div class="control">' +
'<button class="button is-small button--moveLotTypeDown" data-tooltip="Move Down" type="button" aria-label="Move Down">' +
'<i class="fas fa-arrow-down" aria-hidden="true"></i>' +
"</button>" +
"</div>" +
"</div>" +
"</div>") +
"</div>") +
"</div>" +
"</div>";
renderLotTypeFields(lotTypeContainer, lotType.lotTypeId, lotType.lotTypeFields);
lotTypeContainer
.querySelector(".button--toggleLotTypeFields")
.addEventListener("click", toggleLotTypeFields);
lotTypeContainer
.querySelector(".button--deleteLotType")
.addEventListener("click", deleteLotType);
lotTypeContainer
.querySelector(".button--editLotType")
.addEventListener("click", openEditLotType);
lotTypeContainer
.querySelector(".button--addLotTypeField")
.addEventListener("click", openAddLotTypeField);
lotTypeContainer
.querySelector(".button--moveLotTypeUp")
.addEventListener("click", moveLotTypeUp);
lotTypeContainer
.querySelector(".button--moveLotTypeDown")
.addEventListener("click", moveLotTypeDown);
containerElement.append(lotTypeContainer);
}
};
document.querySelector("#button--addLotType").addEventListener("click", () => {
let addCloseModalFunction;
const doAdd = (submitEvent) => {
submitEvent.preventDefault();
cityssm.postJSON(urlPrefix + "/admin/doAddLotType", submitEvent.currentTarget, (responseJSON) => {
if (responseJSON.success) {
addCloseModalFunction();
lotTypes = responseJSON.lotTypes;
renderLotTypes();
}
else {
bulmaJS.alert({
title: "Error Adding " + exports.aliases.lot + " Type",
message: responseJSON.errorMessage,
contextualColorName: "danger"
});
}
});
};
cityssm.openHtmlModal("adminLotTypes-addLotType", {
onshow: (modalElement) => {
los.populateAliases(modalElement);
},
onshown: (modalElement, closeModalFunction) => {
addCloseModalFunction = closeModalFunction;
modalElement.querySelector("#lotTypeAdd--lotType").focus();
modalElement.querySelector("form").addEventListener("submit", doAdd);
bulmaJS.toggleHtmlClipped();
},
onremoved: () => {
bulmaJS.toggleHtmlClipped();
}
});
});
renderLotTypes();
})();

View File

@ -0,0 +1,697 @@
/* eslint-disable unicorn/prefer-module */
import type * as globalTypes from "../types/globalTypes";
import type * as recordTypes from "../types/recordTypes";
import type { cityssmGlobal } from "@cityssm/bulma-webapp-js/src/types";
import type { BulmaJS } from "@cityssm/bulma-js/types";
declare const cityssm: cityssmGlobal;
declare const bulmaJS: BulmaJS;
(() => {
const los = exports.los as globalTypes.LOS;
const urlPrefix = document.querySelector("main").dataset.urlPrefix;
const containerElement = document.querySelector("#container--lotTypes") as HTMLElement;
let lotTypes: recordTypes.LotType[] = exports.lotTypes;
delete exports.lotTypes;
const expandedLotTypes = new Set<number>();
const toggleLotTypeFields = (clickEvent: Event) => {
const toggleButtonElement = clickEvent.currentTarget as HTMLButtonElement;
const lotTypeElement = toggleButtonElement.closest(".container--lotType") as HTMLElement;
const lotTypeId = Number.parseInt(lotTypeElement.dataset.lotTypeId, 10);
if (expandedLotTypes.has(lotTypeId)) {
expandedLotTypes.delete(lotTypeId);
} else {
expandedLotTypes.add(lotTypeId);
}
toggleButtonElement.innerHTML = expandedLotTypes.has(lotTypeId)
? '<i class="fas fa-fw fa-minus" aria-hidden="true"></i>'
: '<i class="fas fa-fw fa-plus" aria-hidden="true"></i>';
const panelBlockElements = lotTypeElement.querySelectorAll(".panel-block");
for (const panelBlockElement of panelBlockElements) {
panelBlockElement.classList.toggle("is-hidden");
}
};
const lotTypeResponseHandler = (responseJSON: {
success: boolean;
errorMessage?: string;
lotTypes?: recordTypes.LotType[];
}) => {
if (responseJSON.success) {
lotTypes = responseJSON.lotTypes;
renderLotTypes();
} else {
bulmaJS.alert({
title: "Error Updating " + exports.aliases.lot + " Type",
message: responseJSON.errorMessage,
contextualColorName: "danger"
});
}
};
const deleteLotType = (clickEvent: Event) => {
const lotTypeId = Number.parseInt(
(
(clickEvent.currentTarget as HTMLElement).closest(
".container--lotType"
) as HTMLElement
).dataset.lotTypeId,
10
);
const doDelete = () => {
cityssm.postJSON(
urlPrefix + "/admin/doDeleteLotType",
{
lotTypeId
},
lotTypeResponseHandler
);
};
bulmaJS.confirm({
title: "Delete " + exports.aliases.lot + " Type",
message:
"Are you sure you want to delete this " +
exports.aliases.lot.toLowerCase() +
" type?",
contextualColorName: "warning",
okButton: {
text: "Yes, Delete " + exports.aliases.lot + " Type",
callbackFunction: doDelete
}
});
};
const openEditLotType = (clickEvent: Event) => {
const lotTypeId = Number.parseInt(
(
(clickEvent.currentTarget as HTMLElement).closest(
".container--lotType"
) as HTMLElement
).dataset.lotTypeId,
10
);
const lotType = lotTypes.find((currentLotType) => {
return lotTypeId === currentLotType.lotTypeId;
});
let editCloseModalFunction: () => void;
const doEdit = (submitEvent: SubmitEvent) => {
submitEvent.preventDefault();
cityssm.postJSON(
urlPrefix + "/admin/doUpdateLotType",
submitEvent.currentTarget,
(responseJSON: {
success: boolean;
errorMessage?: string;
occupancyTypes?: recordTypes.OccupancyType[];
}) => {
lotTypeResponseHandler(responseJSON);
if (responseJSON.success) {
editCloseModalFunction();
}
}
);
};
cityssm.openHtmlModal("adminLotTypes-editLotType", {
onshow: (modalElement) => {
los.populateAliases(modalElement);
(modalElement.querySelector("#lotTypeEdit--lotTypeId") as HTMLInputElement).value =
lotTypeId.toString();
(modalElement.querySelector("#lotTypeEdit--lotType") as HTMLInputElement).value =
lotType.lotType;
},
onshown: (modalElement, closeModalFunction) => {
editCloseModalFunction = closeModalFunction;
(modalElement.querySelector("#lotTypeEdit--lotType") as HTMLInputElement).focus();
modalElement.querySelector("form").addEventListener("submit", doEdit);
bulmaJS.toggleHtmlClipped();
},
onremoved: () => {
bulmaJS.toggleHtmlClipped();
}
});
};
const openAddLotTypeField = (clickEvent: Event) => {
const lotTypeId = Number.parseInt(
(
(clickEvent.currentTarget as HTMLElement).closest(
".container--lotType"
) as HTMLElement
).dataset.lotTypeId,
10
);
let addCloseModalFunction: () => void;
const doAdd = (submitEvent: SubmitEvent) => {
submitEvent.preventDefault();
cityssm.postJSON(
urlPrefix + "/admin/doAddLotTypeField",
submitEvent.currentTarget,
(responseJSON: {
success: boolean;
errorMessage?: string;
lotTypes?: recordTypes.LotType[];
lotTypeFieldId?: number;
}) => {
expandedLotTypes.add(lotTypeId);
lotTypeResponseHandler(responseJSON);
if (responseJSON.success) {
addCloseModalFunction();
openEditLotTypeField(lotTypeId, responseJSON.lotTypeFieldId);
}
}
);
};
cityssm.openHtmlModal("adminLotTypes-addLotTypeField", {
onshow: (modalElement) => {
los.populateAliases(modalElement);
if (lotTypeId) {
(
modalElement.querySelector(
"#lotTypeFieldAdd--lotTypeId"
) as HTMLInputElement
).value = lotTypeId.toString();
}
},
onshown: (modalElement, closeModalFunction) => {
addCloseModalFunction = closeModalFunction;
(
modalElement.querySelector("#lotTypeFieldAdd--lotTypeField") as HTMLInputElement
).focus();
modalElement.querySelector("form").addEventListener("submit", doAdd);
bulmaJS.toggleHtmlClipped();
},
onremoved: () => {
bulmaJS.toggleHtmlClipped();
}
});
};
const moveLotTypeUp = (clickEvent: Event) => {
clickEvent.preventDefault();
const lotTypeId = (
(clickEvent.currentTarget as HTMLElement).closest(".container--lotType") as HTMLElement
).dataset.lotTypeId;
cityssm.postJSON(
urlPrefix + "/admin/doMoveLotTypeUp",
{
lotTypeId
},
lotTypeResponseHandler
);
};
const moveLotTypeDown = (clickEvent: Event) => {
clickEvent.preventDefault();
const lotTypeId = (
(clickEvent.currentTarget as HTMLElement).closest(".container--lotType") as HTMLElement
).dataset.lotTypeId;
cityssm.postJSON(
urlPrefix + "/admin/doMoveLotTypeDown",
{
lotTypeId
},
lotTypeResponseHandler
);
};
const openEditLotTypeField = (lotTypeId: number, lotTypeFieldId: number) => {
const lotType = lotTypes.find((currentLotType) => {
return currentLotType.lotTypeId === lotTypeId;
});
const lotTypeField = lotType.lotTypeFields.find((currentLotTypeField) => {
return currentLotTypeField.lotTypeFieldId === lotTypeFieldId;
});
let minimumLengthElement: HTMLInputElement;
let maximumLengthElement: HTMLInputElement;
let patternElement: HTMLInputElement;
let lotTypeFieldValuesElement: HTMLTextAreaElement;
let editCloseModalFunction: () => void;
const updateMaximumLengthMin = () => {
maximumLengthElement.min = minimumLengthElement.value;
};
const toggleInputFields = () => {
if (lotTypeFieldValuesElement.value === "") {
minimumLengthElement.disabled = false;
maximumLengthElement.disabled = false;
patternElement.disabled = false;
} else {
minimumLengthElement.disabled = true;
maximumLengthElement.disabled = true;
patternElement.disabled = true;
}
};
const doUpdate = (submitEvent: SubmitEvent) => {
submitEvent.preventDefault();
cityssm.postJSON(
urlPrefix + "/admin/doUpdateLotTypeField",
submitEvent.currentTarget,
(responseJSON: {
success: boolean;
errorMessage?: string;
occupancyTypes?: recordTypes.OccupancyType[];
}) => {
lotTypeResponseHandler(responseJSON);
if (responseJSON.success) {
editCloseModalFunction();
}
}
);
};
const doDelete = () => {
const _doDelete = () => {
cityssm.postJSON(
urlPrefix + "/admin/doDeleteLotTypeField",
{
lotTypeFieldId
},
(responseJSON: {
success: boolean;
errorMessage?: string;
lotTypes?: recordTypes.LotType[];
}) => {
lotTypeResponseHandler(responseJSON);
if (responseJSON.success) {
editCloseModalFunction();
}
}
);
};
bulmaJS.confirm({
title: "Delete Field",
message:
"Are you sure you want to delete this field? Note that historical records that make use of this field will not be affected.",
contextualColorName: "warning",
okButton: {
text: "Yes, Delete Field",
callbackFunction: _doDelete
}
});
};
cityssm.openHtmlModal("adminLotTypes-editLotTypeField", {
onshow: (modalElement) => {
los.populateAliases(modalElement);
(
modalElement.querySelector(
"#lotTypeFieldEdit--lotTypeFieldId"
) as HTMLInputElement
).value = lotTypeField.lotTypeFieldId.toString();
(
modalElement.querySelector(
"#lotTypeFieldEdit--lotTypeField"
) as HTMLInputElement
).value = lotTypeField.lotTypeField;
(
modalElement.querySelector("#lotTypeFieldEdit--isRequired") as HTMLSelectElement
).value = lotTypeField.isRequired ? "1" : "0";
minimumLengthElement = modalElement.querySelector(
"#lotTypeFieldEdit--minimumLength"
);
minimumLengthElement.value = lotTypeField.minimumLength.toString();
maximumLengthElement = modalElement.querySelector(
"#lotTypeFieldEdit--maximumLength"
);
maximumLengthElement.value = lotTypeField.maximumLength.toString();
patternElement = modalElement.querySelector("#lotTypeFieldEdit--pattern");
patternElement.value = lotTypeField.pattern;
lotTypeFieldValuesElement = modalElement.querySelector(
"#lotTypeFieldEdit--lotTypeFieldValues"
);
lotTypeFieldValuesElement.value = lotTypeField.lotTypeFieldValues;
toggleInputFields();
},
onshown: (modalElement, closeModalFunction) => {
editCloseModalFunction = closeModalFunction;
bulmaJS.init(modalElement);
bulmaJS.toggleHtmlClipped();
cityssm.enableNavBlocker();
modalElement.querySelector("form").addEventListener("submit", doUpdate);
minimumLengthElement.addEventListener("keyup", updateMaximumLengthMin);
updateMaximumLengthMin();
lotTypeFieldValuesElement.addEventListener("keyup", toggleInputFields);
modalElement
.querySelector("#button--deleteLotTypeField")
.addEventListener("click", doDelete);
},
onremoved: () => {
bulmaJS.toggleHtmlClipped();
cityssm.disableNavBlocker();
}
});
};
const openEditLotTypeFieldByClick = (clickEvent: Event) => {
clickEvent.preventDefault();
const lotTypeFieldId = Number.parseInt(
(
(clickEvent.currentTarget as HTMLElement).closest(
".container--lotTypeField"
) as HTMLElement
).dataset.lotTypeFieldId,
10
);
const lotTypeId = Number.parseInt(
(
(clickEvent.currentTarget as HTMLElement).closest(
".container--lotType"
) as HTMLElement
).dataset.lotTypeId,
10
);
openEditLotTypeField(lotTypeId, lotTypeFieldId);
};
const moveLotTypeFieldUp = (clickEvent: Event) => {
clickEvent.preventDefault();
const lotTypeFieldId = (
(clickEvent.currentTarget as HTMLElement).closest(
".container--lotTypeField"
) as HTMLElement
).dataset.lotTypeFieldId;
cityssm.postJSON(
urlPrefix + "/admin/doMoveLotTypeFieldUp",
{
lotTypeFieldId
},
lotTypeResponseHandler
);
};
const moveLotTypeFieldDown = (clickEvent: Event) => {
clickEvent.preventDefault();
const lotTypeFieldId = (
(clickEvent.currentTarget as HTMLElement).closest(
".container--lotTypeField"
) as HTMLElement
).dataset.lotTypeFieldId;
cityssm.postJSON(
urlPrefix + "/admin/doMoveLotTypeFieldDown",
{
lotTypeFieldId
},
lotTypeResponseHandler
);
};
const renderLotTypeFields = (
panelElement: HTMLElement,
lotTypeId: number,
lotTypeFields: recordTypes.LotTypeField[]
) => {
if (lotTypeFields.length === 0) {
panelElement.insertAdjacentHTML(
"beforeend",
'<div class="panel-block is-block' +
(expandedLotTypes.has(lotTypeId) ? "" : " is-hidden") +
'">' +
'<div class="message is-info">' +
'<p class="message-body">There are no additional fields.</p>' +
"</div>" +
"</div>"
);
} else {
for (const lotTypeField of lotTypeFields) {
const panelBlockElement = document.createElement("div");
panelBlockElement.className = "panel-block is-block container--lotTypeField";
if (!expandedLotTypes.has(lotTypeId)) {
panelBlockElement.classList.add("is-hidden");
}
panelBlockElement.dataset.lotTypeFieldId = lotTypeField.lotTypeFieldId.toString();
panelBlockElement.innerHTML =
'<div class="level is-mobile">' +
'<div class="level-left">' +
('<div class="level-item">' +
'<a class="has-text-weight-bold button--editLotTypeField" href="#">' +
cityssm.escapeHTML(lotTypeField.lotTypeField) +
"</a>" +
"</div>") +
"</div>" +
'<div class="level-right">' +
('<div class="level-item">' +
'<div class="field has-addons">' +
'<div class="control">' +
'<button class="button is-small button--moveLotTypeFieldUp" data-tooltip="Move Up" type="button" aria-label="Move Up">' +
'<i class="fas fa-arrow-up" aria-hidden="true"></i>' +
"</button>" +
"</div>" +
'<div class="control">' +
'<button class="button is-small button--moveLotTypeFieldDown" data-tooltip="Move Down" type="button" aria-label="Move Down">' +
'<i class="fas fa-arrow-down" aria-hidden="true"></i>' +
"</button>" +
"</div>" +
"</div>" +
"</div>") +
"</div>" +
"</div>";
panelBlockElement
.querySelector(".button--editLotTypeField")
.addEventListener("click", openEditLotTypeFieldByClick);
panelBlockElement
.querySelector(".button--moveLotTypeFieldUp")
.addEventListener("click", moveLotTypeFieldUp);
panelBlockElement
.querySelector(".button--moveLotTypeFieldDown")
.addEventListener("click", moveLotTypeFieldDown);
panelElement.append(panelBlockElement);
}
}
};
const renderLotTypes = () => {
containerElement.innerHTML = "";
if (lotTypes.length === 0) {
containerElement.insertAdjacentHTML(
"afterbegin",
'<div class="message is-warning>' +
'<p class="message-body">There are no active ' +
exports.aliases.lot.toLowerCase() +
" types.</p>" +
"</div>"
);
return;
}
for (const lotType of lotTypes) {
const lotTypeContainer = document.createElement("div");
lotTypeContainer.className = "panel container--lotType";
lotTypeContainer.dataset.lotTypeId = lotType.lotTypeId.toString();
lotTypeContainer.innerHTML =
'<div class="panel-heading">' +
'<div class="level is-mobile">' +
('<div class="level-left">' +
'<div class="level-item">' +
'<button class="button is-small button--toggleLotTypeFields" data-tooltip="Toggle Fields" type="button" aria-label="Toggle Fields">' +
(expandedLotTypes.has(lotType.lotTypeId)
? '<i class="fas fa-fw fa-minus" aria-hidden="true"></i>'
: '<i class="fas fa-fw fa-plus" aria-hidden="true"></i>') +
"</button>" +
"</div>" +
'<div class="level-item">' +
'<h2 class="title is-4">' +
cityssm.escapeHTML(lotType.lotType) +
"</h2>" +
"</div>" +
"</div>") +
('<div class="level-right">' +
('<div class="level-item">' +
'<button class="button is-danger is-small button--deleteLotType" type="button">' +
'<span class="icon is-small"><i class="fas fa-trash" aria-hidden="true"></i></span>' +
"<span>Delete</span>" +
"</button>" +
"</div>") +
('<div class="level-item">' +
'<button class="button is-primary is-small button--editLotType" type="button">' +
'<span class="icon is-small"><i class="fas fa-pencil-alt" aria-hidden="true"></i></span>' +
"<span>Edit " +
exports.aliases.lot +
" Type</span>" +
"</button>" +
"</div>") +
('<div class="level-item">' +
'<button class="button is-success is-small button--addLotTypeField" type="button">' +
'<span class="icon is-small"><i class="fas fa-plus" aria-hidden="true"></i></span>' +
"<span>Add Field</span>" +
"</button>" +
"</div>") +
('<div class="level-item">' +
'<div class="field has-addons">' +
'<div class="control">' +
'<button class="button is-small button--moveLotTypeUp" data-tooltip="Move Up" type="button" aria-label="Move Up">' +
'<i class="fas fa-arrow-up" aria-hidden="true"></i>' +
"</button>" +
"</div>" +
'<div class="control">' +
'<button class="button is-small button--moveLotTypeDown" data-tooltip="Move Down" type="button" aria-label="Move Down">' +
'<i class="fas fa-arrow-down" aria-hidden="true"></i>' +
"</button>" +
"</div>" +
"</div>" +
"</div>") +
"</div>") +
"</div>" +
"</div>";
renderLotTypeFields(lotTypeContainer, lotType.lotTypeId, lotType.lotTypeFields);
lotTypeContainer
.querySelector(".button--toggleLotTypeFields")
.addEventListener("click", toggleLotTypeFields);
lotTypeContainer
.querySelector(".button--deleteLotType")
.addEventListener("click", deleteLotType);
lotTypeContainer
.querySelector(".button--editLotType")
.addEventListener("click", openEditLotType);
lotTypeContainer
.querySelector(".button--addLotTypeField")
.addEventListener("click", openAddLotTypeField);
lotTypeContainer
.querySelector(".button--moveLotTypeUp")
.addEventListener("click", moveLotTypeUp);
lotTypeContainer
.querySelector(".button--moveLotTypeDown")
.addEventListener("click", moveLotTypeDown);
containerElement.append(lotTypeContainer);
}
};
document.querySelector("#button--addLotType").addEventListener("click", () => {
let addCloseModalFunction: () => void;
const doAdd = (submitEvent: SubmitEvent) => {
submitEvent.preventDefault();
cityssm.postJSON(
urlPrefix + "/admin/doAddLotType",
submitEvent.currentTarget,
(responseJSON: {
success: boolean;
errorMessage?: string;
lotTypes?: recordTypes.LotType[];
}) => {
if (responseJSON.success) {
addCloseModalFunction();
lotTypes = responseJSON.lotTypes;
renderLotTypes();
} else {
bulmaJS.alert({
title: "Error Adding " + exports.aliases.lot + " Type",
message: responseJSON.errorMessage,
contextualColorName: "danger"
});
}
}
);
};
cityssm.openHtmlModal("adminLotTypes-addLotType", {
onshow: (modalElement) => {
los.populateAliases(modalElement);
},
onshown: (modalElement, closeModalFunction) => {
addCloseModalFunction = closeModalFunction;
(modalElement.querySelector("#lotTypeAdd--lotType") as HTMLInputElement).focus();
modalElement.querySelector("form").addEventListener("submit", doAdd);
bulmaJS.toggleHtmlClipped();
},
onremoved: () => {
bulmaJS.toggleHtmlClipped();
}
});
});
renderLotTypes();
})();

View File

@ -0,0 +1,28 @@
<div class="modal">
<div class="modal-background"></div>
<div class="modal-card" style="width:900px">
<header class="modal-card-head">
<h3 class="modal-card-title">
Add <span class="alias" data-alias="Lot"></span> Type
</h3>
<button class="delete is-close-modal-button" aria-label="close" type="button"></button>
</header>
<section class="modal-card-body">
<form id="form--lotTypeAdd">
<div class="field">
<label class="label" for="lotTypeAdd--lotType"><span class="alias" data-alias="Lot"></span> Type</label>
<div class="control">
<input class="input" id="lotTypeAdd--lotType" name="lotType" type="text" maxlength="100" required />
</div>
</div>
</form>
</section>
<footer class="modal-card-foot justify-right">
<button class="button is-success" type="submit" form="form--lotTypeAdd">
<span class="icon"><i class="fas fa-plus" aria-hidden="true"></i></span>
<span>Add <span class="alias" data-alias="Lot"></span> Type</span>
</button>
<button class="button is-close-modal-button" type="button">Cancel</button>
</footer>
</div>
</div>

View File

@ -0,0 +1,29 @@
<div class="modal">
<div class="modal-background"></div>
<div class="modal-card" style="width:900px">
<header class="modal-card-head">
<h3 class="modal-card-title">
Add <span class="alias" data-alias="Lot"></span> Type Field
</h3>
<button class="delete is-close-modal-button" aria-label="close" type="button"></button>
</header>
<section class="modal-card-body">
<form id="form--lotTypeFieldAdd">
<input class="input" id="lotTypeFieldAdd--lotTypeId" name="lotTypeId" type="hidden" />
<div class="field">
<label class="label" for="lotTypeFieldAdd--lotTypeField">New Field Name</label>
<div class="control">
<input class="input" id="lotTypeFieldAdd--lotTypeField" name="lotTypeField" type="text" maxlength="100" required />
</div>
</div>
</form>
</section>
<footer class="modal-card-foot justify-right">
<button class="button is-success" type="submit" form="form--lotTypeFieldAdd">
<span class="icon"><i class="fas fa-plus" aria-hidden="true"></i></span>
<span>Add Field</span>
</button>
<button class="button is-close-modal-button" type="button">Cancel</button>
</footer>
</div>
</div>

View File

@ -0,0 +1,29 @@
<div class="modal">
<div class="modal-background"></div>
<div class="modal-card" style="width:900px">
<header class="modal-card-head">
<h3 class="modal-card-title">
Update <span class="alias" data-alias="Lot"></span> Type
</h3>
<button class="delete is-close-modal-button" aria-label="close" type="button"></button>
</header>
<section class="modal-card-body">
<form id="form--lotTypeEdit">
<input class="input" id="lotTypeEdit--lotTypeId" name="lotTypeId" type="hidden" />
<div class="field">
<label class="label" for="lotTypeEdit--lotType"><span class="alias" data-alias="Lot"></span> Type</label>
<div class="control">
<input class="input" id="lotTypeEdit--lotType" name="lotType" type="text" maxlength="100" required />
</div>
</div>
</form>
</section>
<footer class="modal-card-foot justify-right">
<button class="button is-success" type="submit" form="form--lotTypeEdit">
<span class="icon"><i class="fas fa-save" aria-hidden="true"></i></span>
<span>Update <span class="alias" data-alias="Lot"></span> Type</span>
</button>
<button class="button is-close-modal-button" type="button">Cancel</button>
</footer>
</div>
</div>

View File

@ -0,0 +1,105 @@
<div class="modal">
<div class="modal-background"></div>
<div class="modal-card" style="width:900px">
<header class="modal-card-head">
<h3 class="modal-card-title">
Update <span class="alias" data-alias="Lot"></span> Type Field
</h3>
<button class="delete is-close-modal-button" aria-label="close" type="button"></button>
</header>
<section class="modal-card-body">
<form id="form--lotTypeFieldEdit">
<input class="input" id="lotTypeFieldEdit--lotTypeFieldId" name="lotTypeFieldId" type="hidden" />
<div class="columns">
<div class="column is-8">
<div class="field">
<label class="label" for="lotTypeFieldEdit--lotTypeField">Field Name</label>
<div class="control">
<input class="input" id="lotTypeFieldEdit--lotTypeField" name="lotTypeField" type="text" maxlength="100" required />
</div>
</div>
</div>
<div class="column">
<div class="field">
<label class="label" for="lotTypeFieldEdit--isRequired">Required</label>
<div class="control">
<div class="select is-fullwidth">
<select id="lotTypeFieldEdit--isRequired" name="isRequired">
<option value="0">Not Required</option>
<option value="1">Required</option>
</select>
</div>
</div>
</div>
</div>
</div>
<div class="columns">
<div class="column is-5">
<div class="columns">
<div class="column">
<div class="field">
<label class="label" for="lotTypeFieldEdit--minimumLength">Minimum Length</label>
<div class="control">
<input class="input" id="lotTypeFieldEdit--minimumLength" name="minimumLength" type="number" min="0" max="32767" step="1" onwheel="return false" />
</div>
</div>
</div>
<div class="column">
<div class="field">
<label class="label" for="lotTypeFieldEdit--maximumLength">Maximum Length</label>
<div class="control">
<input class="input" id="lotTypeFieldEdit--maximumLength" name="maximumLength" type="number" min="0" max="32767" step="1" onwheel="return false" />
</div>
</div>
</div>
</div>
<div class="field">
<label class="label" for="lotTypeFieldEdit--pattern">Regular Expression</label>
<div class="control">
<input class="input" id="lotTypeFieldEdit--pattern" name="pattern" type="text" maxlength="100" />
</div>
</div>
</div>
<div class="column">
<div class="field">
<label class="label" for="lotTypeFieldEdit--lotTypeFieldValues">Field Values</label>
<div class="control">
<textarea class="textarea" id="lotTypeFieldEdit--lotTypeFieldValues" name="lotTypeFieldValues"></textarea>
</div>
<p class="help is-info">
Place each item on a separate line.
Note that when field values are set, only those values can be used to complete the field.
</p>
</div>
</div>
</div>
</form>
</section>
<footer class="modal-card-foot justify-right">
<button class="button is-success" type="submit" form="form--lotTypeFieldEdit">
<span class="icon"><i class="fas fa-save" aria-hidden="true"></i></span>
<span>Update Field</span>
</button>
<div class="dropdown is-up is-right mr-2">
<div class="dropdown-trigger">
<button class="button" type="button">
<span>More Options</span>
<span class="icon is-small">
<i class="fas fa-angle-down" aria-hidden="true"></i>
</span>
</button>
</div>
<div class="dropdown-menu">
<div class="dropdown-content">
<a class="dropdown-item" id="button--deleteLotTypeField" href="#">
<span class="icon is-small"><i class="fas fa-trash has-text-danger" aria-hidden="true"></i></span>
<span>Delete Field</span>
</a>
</div>
</div>
</div>
<button class="button is-close-modal-button" type="button">Cancel</button>
</footer>
</div>
</div>

File diff suppressed because one or more lines are too long

View File

@ -22,6 +22,17 @@ import handler_doUpdateOccupancyTypeField from "../handlers/admin-post/doUpdateO
import handler_doMoveOccupancyTypeFieldUp from "../handlers/admin-post/doMoveOccupancyTypeFieldUp.js";
import handler_doMoveOccupancyTypeFieldDown from "../handlers/admin-post/doMoveOccupancyTypeFieldDown.js";
import handler_doDeleteOccupancyTypeField from "../handlers/admin-post/doDeleteOccupancyTypeField.js";
import handler_lotTypes from "../handlers/admin-get/lotTypes.js";
import handler_doAddLotType from "../handlers/admin-post/doAddLotType.js";
import handler_doUpdateLotType from "../handlers/admin-post/doUpdateLotType.js";
import handler_doMoveLotTypeUp from "../handlers/admin-post/doMoveLotTypeUp.js";
import handler_doMoveLotTypeDown from "../handlers/admin-post/doMoveLotTypeDown.js";
import handler_doDeleteLotType from "../handlers/admin-post/doDeleteLotType.js";
import handler_doAddLotTypeField from "../handlers/admin-post/doAddLotTypeField.js";
import handler_doUpdateLotTypeField from "../handlers/admin-post/doUpdateLotTypeField.js";
import handler_doMoveLotTypeFieldUp from "../handlers/admin-post/doMoveLotTypeFieldUp.js";
import handler_doMoveLotTypeFieldDown from "../handlers/admin-post/doMoveLotTypeFieldDown.js";
import handler_doDeleteLotTypeField from "../handlers/admin-post/doDeleteLotTypeField.js";
import handler_tables from "../handlers/admin-get/tables.js";
import handler_doAddWorkOrderType from "../handlers/admin-post/doAddWorkOrderType.js";
import handler_doUpdateWorkOrderType from "../handlers/admin-post/doUpdateWorkOrderType.js";
@ -68,6 +79,17 @@ router.post("/doUpdateOccupancyTypeField", permissionHandlers.adminPostHandler,
router.post("/doMoveOccupancyTypeFieldUp", permissionHandlers.adminPostHandler, handler_doMoveOccupancyTypeFieldUp);
router.post("/doMoveOccupancyTypeFieldDown", permissionHandlers.adminPostHandler, handler_doMoveOccupancyTypeFieldDown);
router.post("/doDeleteOccupancyTypeField", permissionHandlers.adminPostHandler, handler_doDeleteOccupancyTypeField);
router.get("/lotTypes", permissionHandlers.adminGetHandler, handler_lotTypes);
router.post("/doAddLotType", permissionHandlers.adminPostHandler, handler_doAddLotType);
router.post("/doUpdateLotType", permissionHandlers.adminPostHandler, handler_doUpdateLotType);
router.post("/doMoveLotTypeUp", permissionHandlers.adminPostHandler, handler_doMoveLotTypeUp);
router.post("/doMoveLotTypeDown", permissionHandlers.adminPostHandler, handler_doMoveLotTypeDown);
router.post("/doDeleteLotType", permissionHandlers.adminPostHandler, handler_doDeleteLotType);
router.post("/doAddLotTypeField", permissionHandlers.adminPostHandler, handler_doAddLotTypeField);
router.post("/doUpdateLotTypeField", permissionHandlers.adminPostHandler, handler_doUpdateLotTypeField);
router.post("/doMoveLotTypeFieldUp", permissionHandlers.adminPostHandler, handler_doMoveLotTypeFieldUp);
router.post("/doMoveLotTypeFieldDown", permissionHandlers.adminPostHandler, handler_doMoveLotTypeFieldDown);
router.post("/doDeleteLotTypeField", permissionHandlers.adminPostHandler, handler_doDeleteLotTypeField);
router.get("/tables", permissionHandlers.adminGetHandler, handler_tables);
router.post("/doAddWorkOrderType", permissionHandlers.adminPostHandler, handler_doAddWorkOrderType);
router.post("/doUpdateWorkOrderType", permissionHandlers.adminPostHandler, handler_doUpdateWorkOrderType);

View File

@ -34,6 +34,22 @@ import handler_doMoveOccupancyTypeFieldUp from "../handlers/admin-post/doMoveOcc
import handler_doMoveOccupancyTypeFieldDown from "../handlers/admin-post/doMoveOccupancyTypeFieldDown.js";
import handler_doDeleteOccupancyTypeField from "../handlers/admin-post/doDeleteOccupancyTypeField.js";
// Lot Type Management
import handler_lotTypes from "../handlers/admin-get/lotTypes.js";
import handler_doAddLotType from "../handlers/admin-post/doAddLotType.js";
import handler_doUpdateLotType from "../handlers/admin-post/doUpdateLotType.js";
import handler_doMoveLotTypeUp from "../handlers/admin-post/doMoveLotTypeUp.js";
import handler_doMoveLotTypeDown from "../handlers/admin-post/doMoveLotTypeDown.js";
import handler_doDeleteLotType from "../handlers/admin-post/doDeleteLotType.js";
import handler_doAddLotTypeField from "../handlers/admin-post/doAddLotTypeField.js";
import handler_doUpdateLotTypeField from "../handlers/admin-post/doUpdateLotTypeField.js";
import handler_doMoveLotTypeFieldUp from "../handlers/admin-post/doMoveLotTypeFieldUp.js";
import handler_doMoveLotTypeFieldDown from "../handlers/admin-post/doMoveLotTypeFieldDown.js";
import handler_doDeleteLotTypeField from "../handlers/admin-post/doDeleteLotTypeField.js";
// Config Table Management
import handler_tables from "../handlers/admin-get/tables.js";
@ -175,6 +191,50 @@ router.post(
handler_doDeleteOccupancyTypeField
);
/*
* Lot Type Management
*/
router.get("/lotTypes", permissionHandlers.adminGetHandler, handler_lotTypes);
router.post("/doAddLotType", permissionHandlers.adminPostHandler, handler_doAddLotType);
router.post("/doUpdateLotType", permissionHandlers.adminPostHandler, handler_doUpdateLotType);
router.post("/doMoveLotTypeUp", permissionHandlers.adminPostHandler, handler_doMoveLotTypeUp);
router.post("/doMoveLotTypeDown", permissionHandlers.adminPostHandler, handler_doMoveLotTypeDown);
router.post("/doDeleteLotType", permissionHandlers.adminPostHandler, handler_doDeleteLotType);
// Lot Type Fields
router.post("/doAddLotTypeField", permissionHandlers.adminPostHandler, handler_doAddLotTypeField);
router.post(
"/doUpdateLotTypeField",
permissionHandlers.adminPostHandler,
handler_doUpdateLotTypeField
);
router.post(
"/doMoveLotTypeFieldUp",
permissionHandlers.adminPostHandler,
handler_doMoveLotTypeFieldUp
);
router.post(
"/doMoveLotTypeFieldDown",
permissionHandlers.adminPostHandler,
handler_doMoveLotTypeFieldDown
);
router.post(
"/doDeleteLotTypeField",
permissionHandlers.adminPostHandler,
handler_doDeleteLotTypeField
);
/*
* Config Tables
*/

View File

@ -10,11 +10,17 @@
</a>
</li>
<li>
<a class="<%= (headTitle.endsWith("Type Management") ? "is-active" : "") %>" href="<%= urlPrefix %>/admin/occupancyTypes">
<a class="<%= (headTitle === configFunctions.getProperty("aliases.occupancy") + " Type Management" ? "is-active" : "") %>" href="<%= urlPrefix %>/admin/occupancyTypes">
<span class="icon"><i class="fas fa-fw fa-user-friends" aria-hidden="true"></i></span>
<span><%= configFunctions.getProperty("aliases.occupancy") %> Type Management</span>
</a>
</li>
<li>
<a class="<%= (headTitle === configFunctions.getProperty("aliases.lot") + " Type Management" ? "is-active" : "") %>" href="<%= urlPrefix %>/admin/lotTypes">
<span class="icon"><i class="fas fa-fw fa-vector-square" aria-hidden="true"></i></span>
<span><%= configFunctions.getProperty("aliases.lot") %> Type Management</span>
</a>
</li>
<li>
<a class="<%= (headTitle === "Config Table Management" ? "is-active" : "") %>" href="<%= urlPrefix %>/admin/tables">
<span class="icon"><i class="fas fa-fw fa-table" aria-hidden="true"></i></span>

View File

@ -0,0 +1,56 @@
<%- include('_header'); -%>
<div class="columns">
<div class="column is-3 is-hidden-mobile">
<%- include('_menu-admin'); -%>
</div>
<div class="column">
<nav class="breadcrumb">
<ul>
<li><a href="<%= urlPrefix %>/dashboard">Home</a></li>
<li>
<a href="#">
<span class="icon is-small"><i class="fas fa-cog" aria-hidden="true"></i></span>
<span>Administrator Tools</span>
</a>
</li>
<li class="is-active">
<a href="#" aria-current="page">
<%= configFunctions.getProperty("aliases.lot") %> Type Management
</a>
</li>
</ul>
</nav>
<div class="level is-mobile">
<div class="level-left">
<div class="level-item">
<h1 class="title is-1">
<%= configFunctions.getProperty("aliases.lot") %> Type Management
</h1>
</div>
</div>
<div class="level-right">
<div class="level-item">
<button class="button is-success" id="button--addLotType" type="button" accesskey="n">
<span class="icon is-small"><i class="fas fa-plus" aria-hidden="true"></i></span>
<span>Add <%= configFunctions.getProperty("aliases.lot") %> Type</span>
</button>
</div>
</div>
</div>
<div id="container--lotTypes"></div>
</div>
</div>
<%- include('_footerA'); -%>
<script>
exports.lotTypes = <%- JSON.stringify(lotTypes) %>;
</script>
<script src="<%= urlPrefix %>/javascripts/adminLotTypes.min.js"></script>
<%- include('_footerB'); -%>

View File

@ -294,6 +294,23 @@
</div>
</div>
</div>
<div class="card-content">
<div class="media">
<div class="media-left">
<i class="fas fa-3x fa-fw fa-vector-square" aria-hidden="true"></i>
</div>
<div class="media-content has-text-black">
<h2 class="title is-4 is-marginless">
<a href="<%= urlPrefix %>/admin/lotTypes"><%= configFunctions.getProperty("aliases.lot") %> Type Management</a>
</h2>
<p>
Manage
<%= configFunctions.getProperty("aliases.lot").toLowerCase() %> types
and fields associated with them.
</p>
</div>
</div>
</div>
<div class="card-content">
<div class="media">
<div class="media-left">