lot fields in lot view and edit
parent
1212066071
commit
15afd72ed8
|
|
@ -0,0 +1,3 @@
|
||||||
|
import type { RequestHandler } from "express";
|
||||||
|
export declare const handler: RequestHandler;
|
||||||
|
export default handler;
|
||||||
|
|
@ -0,0 +1,8 @@
|
||||||
|
import { getLotTypeById } from "../../helpers/functions.cache.js";
|
||||||
|
export const handler = async (request, response) => {
|
||||||
|
const lotType = getLotTypeById(Number.parseInt(request.body.lotTypeId, 10));
|
||||||
|
response.json({
|
||||||
|
lotTypeFields: lotType.lotTypeFields
|
||||||
|
});
|
||||||
|
};
|
||||||
|
export default handler;
|
||||||
|
|
@ -0,0 +1,13 @@
|
||||||
|
import type { RequestHandler } from "express";
|
||||||
|
|
||||||
|
import { getLotTypeById } from "../../helpers/functions.cache.js";
|
||||||
|
|
||||||
|
export const handler: RequestHandler = async (request, response) => {
|
||||||
|
const lotType = getLotTypeById(Number.parseInt(request.body.lotTypeId, 10));
|
||||||
|
|
||||||
|
response.json({
|
||||||
|
lotTypeFields: lotType.lotTypeFields
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
export default handler;
|
||||||
|
|
@ -7,6 +7,8 @@ interface AddLotForm {
|
||||||
mapKey: string;
|
mapKey: string;
|
||||||
lotLatitude: string;
|
lotLatitude: string;
|
||||||
lotLongitude: string;
|
lotLongitude: string;
|
||||||
|
lotTypeFieldIds?: string;
|
||||||
|
[lotFieldValue_lotTypeFieldId: string]: unknown;
|
||||||
}
|
}
|
||||||
export declare const addLot: (lotForm: AddLotForm, requestSession: recordTypes.PartialSession) => number;
|
export declare const addLot: (lotForm: AddLotForm, requestSession: recordTypes.PartialSession) => number;
|
||||||
export default addLot;
|
export default addLot;
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
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 { addOrUpdateLotField } from "./addOrUpdateLotField.js";
|
||||||
export const addLot = (lotForm, requestSession) => {
|
export const addLot = (lotForm, requestSession) => {
|
||||||
const database = sqlite(databasePath);
|
const database = sqlite(databasePath);
|
||||||
const rightNowMillis = Date.now();
|
const rightNowMillis = Date.now();
|
||||||
|
|
@ -12,7 +13,19 @@ export const addLot = (lotForm, requestSession) => {
|
||||||
" recordUpdate_userName, recordUpdate_timeMillis)" +
|
" recordUpdate_userName, recordUpdate_timeMillis)" +
|
||||||
" values (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)")
|
" values (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)")
|
||||||
.run(lotForm.lotName, lotForm.lotTypeId, lotForm.lotStatusId === "" ? undefined : lotForm.lotStatusId, lotForm.mapId === "" ? undefined : lotForm.mapId, lotForm.mapKey, lotForm.lotLatitude === "" ? undefined : lotForm.lotLatitude, lotForm.lotLongitude === "" ? undefined : lotForm.lotLongitude, requestSession.user.userName, rightNowMillis, requestSession.user.userName, rightNowMillis);
|
.run(lotForm.lotName, lotForm.lotTypeId, lotForm.lotStatusId === "" ? undefined : lotForm.lotStatusId, lotForm.mapId === "" ? undefined : lotForm.mapId, lotForm.mapKey, lotForm.lotLatitude === "" ? undefined : lotForm.lotLatitude, lotForm.lotLongitude === "" ? undefined : lotForm.lotLongitude, requestSession.user.userName, rightNowMillis, requestSession.user.userName, rightNowMillis);
|
||||||
|
const lotId = result.lastInsertRowid;
|
||||||
|
const lotTypeFieldIds = (lotForm.lotTypeFieldIds || "").split(",");
|
||||||
|
for (const lotTypeFieldId of lotTypeFieldIds) {
|
||||||
|
const lotFieldValue = lotForm["lotFieldValue_" + lotTypeFieldId];
|
||||||
|
if (lotFieldValue && lotFieldValue !== "") {
|
||||||
|
addOrUpdateLotField({
|
||||||
|
lotId,
|
||||||
|
lotTypeFieldId,
|
||||||
|
lotFieldValue
|
||||||
|
}, requestSession, database);
|
||||||
|
}
|
||||||
|
}
|
||||||
database.close();
|
database.close();
|
||||||
return result.lastInsertRowid;
|
return lotId;
|
||||||
};
|
};
|
||||||
export default addLot;
|
export default addLot;
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,8 @@ import sqlite from "better-sqlite3";
|
||||||
|
|
||||||
import { lotOccupancyDB as databasePath } from "../../data/databasePaths.js";
|
import { lotOccupancyDB as databasePath } from "../../data/databasePaths.js";
|
||||||
|
|
||||||
|
import { addOrUpdateLotField } from "./addOrUpdateLotField.js";
|
||||||
|
|
||||||
import type * as recordTypes from "../../types/recordTypes";
|
import type * as recordTypes from "../../types/recordTypes";
|
||||||
|
|
||||||
interface AddLotForm {
|
interface AddLotForm {
|
||||||
|
|
@ -14,12 +16,12 @@ interface AddLotForm {
|
||||||
|
|
||||||
lotLatitude: string;
|
lotLatitude: string;
|
||||||
lotLongitude: string;
|
lotLongitude: string;
|
||||||
|
|
||||||
|
lotTypeFieldIds?: string;
|
||||||
|
[lotFieldValue_lotTypeFieldId: string]: unknown;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const addLot = (
|
export const addLot = (lotForm: AddLotForm, requestSession: recordTypes.PartialSession): number => {
|
||||||
lotForm: AddLotForm,
|
|
||||||
requestSession: recordTypes.PartialSession
|
|
||||||
): number => {
|
|
||||||
const database = sqlite(databasePath);
|
const database = sqlite(databasePath);
|
||||||
|
|
||||||
const rightNowMillis = Date.now();
|
const rightNowMillis = Date.now();
|
||||||
|
|
@ -48,9 +50,29 @@ export const addLot = (
|
||||||
rightNowMillis
|
rightNowMillis
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const lotId = result.lastInsertRowid as number;
|
||||||
|
|
||||||
|
const lotTypeFieldIds = (lotForm.lotTypeFieldIds || "").split(",");
|
||||||
|
|
||||||
|
for (const lotTypeFieldId of lotTypeFieldIds) {
|
||||||
|
const lotFieldValue = lotForm["lotFieldValue_" + lotTypeFieldId] as string;
|
||||||
|
|
||||||
|
if (lotFieldValue && lotFieldValue !== "") {
|
||||||
|
addOrUpdateLotField(
|
||||||
|
{
|
||||||
|
lotId,
|
||||||
|
lotTypeFieldId,
|
||||||
|
lotFieldValue
|
||||||
|
},
|
||||||
|
requestSession,
|
||||||
|
database
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
database.close();
|
database.close();
|
||||||
|
|
||||||
return result.lastInsertRowid as number;
|
return lotId;
|
||||||
};
|
};
|
||||||
|
|
||||||
export default addLot;
|
export default addLot;
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,9 @@
|
||||||
|
import sqlite from "better-sqlite3";
|
||||||
|
import type * as recordTypes from "../../types/recordTypes";
|
||||||
|
interface LotFieldForm {
|
||||||
|
lotId: string | number;
|
||||||
|
lotTypeFieldId: string | number;
|
||||||
|
lotFieldValue: string;
|
||||||
|
}
|
||||||
|
export declare const addOrUpdateLotField: (lotFieldForm: LotFieldForm, requestSession: recordTypes.PartialSession, connectedDatabase?: sqlite.Database) => boolean;
|
||||||
|
export default addOrUpdateLotField;
|
||||||
|
|
@ -0,0 +1,31 @@
|
||||||
|
import sqlite from "better-sqlite3";
|
||||||
|
import { lotOccupancyDB as databasePath } from "../../data/databasePaths.js";
|
||||||
|
export const addOrUpdateLotField = (lotFieldForm, requestSession, connectedDatabase) => {
|
||||||
|
const database = connectedDatabase || sqlite(databasePath);
|
||||||
|
const rightNowMillis = Date.now();
|
||||||
|
let result = database
|
||||||
|
.prepare("update LotFields" +
|
||||||
|
" set lotFieldValue = ?," +
|
||||||
|
" recordUpdate_userName = ?," +
|
||||||
|
" recordUpdate_timeMillis = ?," +
|
||||||
|
" recordDelete_userName = null," +
|
||||||
|
" recordDelete_timeMillis = null" +
|
||||||
|
" where lotId = ?" +
|
||||||
|
" and lotTypeFieldId = ?")
|
||||||
|
.run(lotFieldForm.lotFieldValue, requestSession.user.userName, rightNowMillis, lotFieldForm.lotId, lotFieldForm.lotTypeFieldId);
|
||||||
|
if (result.changes === 0) {
|
||||||
|
result = database
|
||||||
|
.prepare("insert into LotFields (" +
|
||||||
|
"lotId, lotTypeFieldId," +
|
||||||
|
" lotFieldValue," +
|
||||||
|
" recordCreate_userName, recordCreate_timeMillis," +
|
||||||
|
" recordUpdate_userName, recordUpdate_timeMillis)" +
|
||||||
|
" values (?, ?, ?, ?, ?, ?, ?)")
|
||||||
|
.run(lotFieldForm.lotId, lotFieldForm.lotTypeFieldId, lotFieldForm.lotFieldValue, requestSession.user.userName, rightNowMillis, requestSession.user.userName, rightNowMillis);
|
||||||
|
}
|
||||||
|
if (!connectedDatabase) {
|
||||||
|
database.close();
|
||||||
|
}
|
||||||
|
return result.changes > 0;
|
||||||
|
};
|
||||||
|
export default addOrUpdateLotField;
|
||||||
|
|
@ -0,0 +1,69 @@
|
||||||
|
import sqlite from "better-sqlite3";
|
||||||
|
|
||||||
|
import { lotOccupancyDB as databasePath } from "../../data/databasePaths.js";
|
||||||
|
|
||||||
|
import type * as recordTypes from "../../types/recordTypes";
|
||||||
|
|
||||||
|
interface LotFieldForm {
|
||||||
|
lotId: string | number;
|
||||||
|
lotTypeFieldId: string | number;
|
||||||
|
lotFieldValue: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const addOrUpdateLotField = (
|
||||||
|
lotFieldForm: LotFieldForm,
|
||||||
|
requestSession: recordTypes.PartialSession,
|
||||||
|
connectedDatabase?: sqlite.Database
|
||||||
|
): boolean => {
|
||||||
|
const database = connectedDatabase || sqlite(databasePath);
|
||||||
|
|
||||||
|
const rightNowMillis = Date.now();
|
||||||
|
|
||||||
|
let result = database
|
||||||
|
.prepare(
|
||||||
|
"update LotFields" +
|
||||||
|
" set lotFieldValue = ?," +
|
||||||
|
" recordUpdate_userName = ?," +
|
||||||
|
" recordUpdate_timeMillis = ?," +
|
||||||
|
" recordDelete_userName = null," +
|
||||||
|
" recordDelete_timeMillis = null" +
|
||||||
|
" where lotId = ?" +
|
||||||
|
" and lotTypeFieldId = ?"
|
||||||
|
)
|
||||||
|
.run(
|
||||||
|
lotFieldForm.lotFieldValue,
|
||||||
|
requestSession.user.userName,
|
||||||
|
rightNowMillis,
|
||||||
|
lotFieldForm.lotId,
|
||||||
|
lotFieldForm.lotTypeFieldId
|
||||||
|
);
|
||||||
|
|
||||||
|
if (result.changes === 0) {
|
||||||
|
result = database
|
||||||
|
.prepare(
|
||||||
|
"insert into LotFields (" +
|
||||||
|
"lotId, lotTypeFieldId," +
|
||||||
|
" lotFieldValue," +
|
||||||
|
" recordCreate_userName, recordCreate_timeMillis," +
|
||||||
|
" recordUpdate_userName, recordUpdate_timeMillis)" +
|
||||||
|
" values (?, ?, ?, ?, ?, ?, ?)"
|
||||||
|
)
|
||||||
|
.run(
|
||||||
|
lotFieldForm.lotId,
|
||||||
|
lotFieldForm.lotTypeFieldId,
|
||||||
|
lotFieldForm.lotFieldValue,
|
||||||
|
requestSession.user.userName,
|
||||||
|
rightNowMillis,
|
||||||
|
requestSession.user.userName,
|
||||||
|
rightNowMillis
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!connectedDatabase) {
|
||||||
|
database.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
return result.changes > 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
export default addOrUpdateLotField;
|
||||||
|
|
@ -0,0 +1,4 @@
|
||||||
|
import sqlite from "better-sqlite3";
|
||||||
|
import type * as recordTypes from "../../types/recordTypes";
|
||||||
|
export declare const deleteLotField: (lotId: number | string, lotTypeFieldId: number | string, requestSession: recordTypes.PartialSession, connectedDatabase?: sqlite.Database) => boolean;
|
||||||
|
export default deleteLotField;
|
||||||
|
|
@ -0,0 +1,18 @@
|
||||||
|
import sqlite from "better-sqlite3";
|
||||||
|
import { lotOccupancyDB as databasePath } from "../../data/databasePaths.js";
|
||||||
|
export const deleteLotField = (lotId, lotTypeFieldId, requestSession, connectedDatabase) => {
|
||||||
|
const database = connectedDatabase || sqlite(databasePath);
|
||||||
|
const rightNowMillis = Date.now();
|
||||||
|
const result = database
|
||||||
|
.prepare("update LotFields" +
|
||||||
|
" set recordDelete_userName = ?," +
|
||||||
|
" recordDelete_timeMillis = ?" +
|
||||||
|
" where lotId = ?" +
|
||||||
|
" and lotTypeFieldId = ?")
|
||||||
|
.run(requestSession.user.userName, rightNowMillis, lotId, lotTypeFieldId);
|
||||||
|
if (!connectedDatabase) {
|
||||||
|
database.close();
|
||||||
|
}
|
||||||
|
return result.changes > 0;
|
||||||
|
};
|
||||||
|
export default deleteLotField;
|
||||||
|
|
@ -0,0 +1,34 @@
|
||||||
|
import sqlite from "better-sqlite3";
|
||||||
|
|
||||||
|
import { lotOccupancyDB as databasePath } from "../../data/databasePaths.js";
|
||||||
|
|
||||||
|
import type * as recordTypes from "../../types/recordTypes";
|
||||||
|
|
||||||
|
export const deleteLotField = (
|
||||||
|
lotId: number | string,
|
||||||
|
lotTypeFieldId: number | string,
|
||||||
|
requestSession: recordTypes.PartialSession,
|
||||||
|
connectedDatabase?: sqlite.Database
|
||||||
|
): boolean => {
|
||||||
|
const database = connectedDatabase || sqlite(databasePath);
|
||||||
|
|
||||||
|
const rightNowMillis = Date.now();
|
||||||
|
|
||||||
|
const result = database
|
||||||
|
.prepare(
|
||||||
|
"update LotFields" +
|
||||||
|
" set recordDelete_userName = ?," +
|
||||||
|
" recordDelete_timeMillis = ?" +
|
||||||
|
" where lotId = ?" +
|
||||||
|
" and lotTypeFieldId = ?"
|
||||||
|
)
|
||||||
|
.run(requestSession.user.userName, rightNowMillis, lotId, lotTypeFieldId);
|
||||||
|
|
||||||
|
if (!connectedDatabase) {
|
||||||
|
database.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
return result.changes > 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
export default deleteLotField;
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
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 { getLotFields } from "./getLotFields.js";
|
||||||
import { getLotComments } from "./getLotComments.js";
|
import { getLotComments } from "./getLotComments.js";
|
||||||
import { getLotOccupancies } from "./getLotOccupancies.js";
|
import { getLotOccupancies } from "./getLotOccupancies.js";
|
||||||
const baseSQL = "select l.lotId," +
|
const baseSQL = "select l.lotId," +
|
||||||
|
|
@ -26,7 +27,8 @@ const _getLot = (sql, lotId_or_lotName) => {
|
||||||
limit: -1,
|
limit: -1,
|
||||||
offset: 0
|
offset: 0
|
||||||
}, database).lotOccupancies;
|
}, database).lotOccupancies;
|
||||||
lot.lotComments = getLotComments(lot.lotId);
|
lot.lotFields = getLotFields(lot.lotId, database);
|
||||||
|
lot.lotComments = getLotComments(lot.lotId, database);
|
||||||
}
|
}
|
||||||
database.close();
|
database.close();
|
||||||
return lot;
|
return lot;
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,8 @@ import sqlite from "better-sqlite3";
|
||||||
|
|
||||||
import { lotOccupancyDB as databasePath } from "../../data/databasePaths.js";
|
import { lotOccupancyDB as databasePath } from "../../data/databasePaths.js";
|
||||||
|
|
||||||
|
import { getLotFields } from "./getLotFields.js";
|
||||||
|
|
||||||
import { getLotComments } from "./getLotComments.js";
|
import { getLotComments } from "./getLotComments.js";
|
||||||
|
|
||||||
import { getLotOccupancies } from "./getLotOccupancies.js";
|
import { getLotOccupancies } from "./getLotOccupancies.js";
|
||||||
|
|
@ -41,7 +43,9 @@ const _getLot = (sql: string, lotId_or_lotName: number | string): recordTypes.Lo
|
||||||
database
|
database
|
||||||
).lotOccupancies;
|
).lotOccupancies;
|
||||||
|
|
||||||
lot.lotComments = getLotComments(lot.lotId);
|
lot.lotFields = getLotFields(lot.lotId, database);
|
||||||
|
|
||||||
|
lot.lotComments = getLotComments(lot.lotId, database);
|
||||||
}
|
}
|
||||||
|
|
||||||
database.close();
|
database.close();
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,4 @@
|
||||||
|
import sqlite from "better-sqlite3";
|
||||||
|
import type * as recordTypes from "../../types/recordTypes";
|
||||||
|
export declare const getLotFields: (lotId: number | string, connectedDatabase?: sqlite.Database) => recordTypes.LotField[];
|
||||||
|
export default getLotFields;
|
||||||
|
|
@ -0,0 +1,37 @@
|
||||||
|
import sqlite from "better-sqlite3";
|
||||||
|
import { lotOccupancyDB as databasePath } from "../../data/databasePaths.js";
|
||||||
|
export const getLotFields = (lotId, connectedDatabase) => {
|
||||||
|
const database = connectedDatabase ||
|
||||||
|
sqlite(databasePath, {
|
||||||
|
readonly: true
|
||||||
|
});
|
||||||
|
const lotFields = database
|
||||||
|
.prepare("select l.lotId," +
|
||||||
|
" l.lotTypeFieldId, l.lotFieldValue," +
|
||||||
|
" f.lotTypeField," +
|
||||||
|
" f.lotTypeFieldValues, f.isRequired, f.pattern, f.minimumLength, f.maximumLength," +
|
||||||
|
" f.orderNumber, t.orderNumber as lotTypeOrderNumber" +
|
||||||
|
" from LotFields l" +
|
||||||
|
" left join LotTypeFields f on l.lotTypeFieldId = f.lotTypeFieldId" +
|
||||||
|
" left join LotTypes t on f.lotTypeId = t.lotTypeId" +
|
||||||
|
" where l.recordDelete_timeMillis is null" +
|
||||||
|
" and l.lotId = ?" +
|
||||||
|
" union" +
|
||||||
|
" select ? as lotId," +
|
||||||
|
" f.lotTypeFieldId, '' as lotFieldValue," +
|
||||||
|
" f.lotTypeField," +
|
||||||
|
" f.lotTypeFieldValues, f.isRequired, f.pattern, f.minimumLength, f.maximumLength," +
|
||||||
|
" f.orderNumber, t.orderNumber as lotTypeOrderNumber" +
|
||||||
|
" from LotTypeFields f" +
|
||||||
|
" left join LotTypes t on f.lotTypeId = t.lotTypeId" +
|
||||||
|
" where f.recordDelete_timeMillis is null" +
|
||||||
|
" and (f.lotTypeId is null or f.lotTypeId in (select lotTypeId from Lots where lotId = ?))" +
|
||||||
|
" and f.lotTypeFieldId not in (select lotTypeFieldId from LotFields where lotId = ? and recordDelete_timeMillis is null)" +
|
||||||
|
" order by lotTypeOrderNumber, f.orderNumber, f.lotTypeField")
|
||||||
|
.all(lotId, lotId, lotId, lotId);
|
||||||
|
if (!connectedDatabase) {
|
||||||
|
database.close();
|
||||||
|
}
|
||||||
|
return lotFields;
|
||||||
|
};
|
||||||
|
export default getLotFields;
|
||||||
|
|
@ -0,0 +1,51 @@
|
||||||
|
import sqlite from "better-sqlite3";
|
||||||
|
|
||||||
|
import { lotOccupancyDB as databasePath } from "../../data/databasePaths.js";
|
||||||
|
|
||||||
|
import type * as recordTypes from "../../types/recordTypes";
|
||||||
|
|
||||||
|
export const getLotFields = (
|
||||||
|
lotId: number | string,
|
||||||
|
connectedDatabase?: sqlite.Database
|
||||||
|
): recordTypes.LotField[] => {
|
||||||
|
const database =
|
||||||
|
connectedDatabase ||
|
||||||
|
sqlite(databasePath, {
|
||||||
|
readonly: true
|
||||||
|
});
|
||||||
|
|
||||||
|
const lotFields: recordTypes.LotField[] = database
|
||||||
|
.prepare(
|
||||||
|
"select l.lotId," +
|
||||||
|
" l.lotTypeFieldId, l.lotFieldValue," +
|
||||||
|
" f.lotTypeField," +
|
||||||
|
" f.lotTypeFieldValues, f.isRequired, f.pattern, f.minimumLength, f.maximumLength," +
|
||||||
|
" f.orderNumber, t.orderNumber as lotTypeOrderNumber" +
|
||||||
|
" from LotFields l" +
|
||||||
|
" left join LotTypeFields f on l.lotTypeFieldId = f.lotTypeFieldId" +
|
||||||
|
" left join LotTypes t on f.lotTypeId = t.lotTypeId" +
|
||||||
|
" where l.recordDelete_timeMillis is null" +
|
||||||
|
" and l.lotId = ?" +
|
||||||
|
" union" +
|
||||||
|
" select ? as lotId," +
|
||||||
|
" f.lotTypeFieldId, '' as lotFieldValue," +
|
||||||
|
" f.lotTypeField," +
|
||||||
|
" f.lotTypeFieldValues, f.isRequired, f.pattern, f.minimumLength, f.maximumLength," +
|
||||||
|
" f.orderNumber, t.orderNumber as lotTypeOrderNumber" +
|
||||||
|
" from LotTypeFields f" +
|
||||||
|
" left join LotTypes t on f.lotTypeId = t.lotTypeId" +
|
||||||
|
" where f.recordDelete_timeMillis is null" +
|
||||||
|
" and (f.lotTypeId is null or f.lotTypeId in (select lotTypeId from Lots where lotId = ?))" +
|
||||||
|
" and f.lotTypeFieldId not in (select lotTypeFieldId from LotFields where lotId = ? and recordDelete_timeMillis is null)" +
|
||||||
|
" order by lotTypeOrderNumber, f.orderNumber, f.lotTypeField"
|
||||||
|
)
|
||||||
|
.all(lotId, lotId, lotId, lotId);
|
||||||
|
|
||||||
|
if (!connectedDatabase) {
|
||||||
|
database.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
return lotFields;
|
||||||
|
};
|
||||||
|
|
||||||
|
export default getLotFields;
|
||||||
|
|
@ -8,6 +8,8 @@ interface UpdateLotForm {
|
||||||
mapKey: string;
|
mapKey: string;
|
||||||
lotLatitude: string;
|
lotLatitude: string;
|
||||||
lotLongitude: string;
|
lotLongitude: string;
|
||||||
|
lotTypeFieldIds?: string;
|
||||||
|
[lotFieldValue_lotTypeFieldId: string]: unknown;
|
||||||
}
|
}
|
||||||
export declare function updateLot(lotForm: UpdateLotForm, requestSession: recordTypes.PartialSession): boolean;
|
export declare function updateLot(lotForm: UpdateLotForm, requestSession: recordTypes.PartialSession): boolean;
|
||||||
export declare function updateLotStatus(lotId: number | string, lotStatusId: number | string, requestSession: recordTypes.PartialSession): boolean;
|
export declare function updateLotStatus(lotId: number | string, lotStatusId: number | string, requestSession: recordTypes.PartialSession): boolean;
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,7 @@
|
||||||
import sqlite from "better-sqlite3";
|
import sqlite from "better-sqlite3";
|
||||||
import { lotOccupancyDB as databasePath } from "../../data/databasePaths.js";
|
import { lotOccupancyDB as databasePath } from "../../data/databasePaths.js";
|
||||||
|
import { addOrUpdateLotField } from "./addOrUpdateLotField.js";
|
||||||
|
import { deleteLotField } from "./deleteLotField.js";
|
||||||
export function updateLot(lotForm, requestSession) {
|
export function updateLot(lotForm, requestSession) {
|
||||||
const database = sqlite(databasePath);
|
const database = sqlite(databasePath);
|
||||||
const rightNowMillis = Date.now();
|
const rightNowMillis = Date.now();
|
||||||
|
|
@ -17,6 +19,22 @@ export function updateLot(lotForm, requestSession) {
|
||||||
" where lotId = ?" +
|
" where lotId = ?" +
|
||||||
" and recordDelete_timeMillis is null")
|
" and recordDelete_timeMillis is null")
|
||||||
.run(lotForm.lotName, lotForm.lotTypeId, lotForm.lotStatusId === "" ? undefined : lotForm.lotStatusId, lotForm.mapId === "" ? undefined : lotForm.mapId, lotForm.mapKey, lotForm.lotLatitude === "" ? undefined : lotForm.lotLatitude, lotForm.lotLongitude === "" ? undefined : lotForm.lotLongitude, requestSession.user.userName, rightNowMillis, lotForm.lotId);
|
.run(lotForm.lotName, lotForm.lotTypeId, lotForm.lotStatusId === "" ? undefined : lotForm.lotStatusId, lotForm.mapId === "" ? undefined : lotForm.mapId, lotForm.mapKey, lotForm.lotLatitude === "" ? undefined : lotForm.lotLatitude, lotForm.lotLongitude === "" ? undefined : lotForm.lotLongitude, requestSession.user.userName, rightNowMillis, lotForm.lotId);
|
||||||
|
if (result.changes > 0) {
|
||||||
|
const lotTypeFieldIds = (lotForm.lotTypeFieldIds || "").split(",");
|
||||||
|
for (const lotTypeFieldId of lotTypeFieldIds) {
|
||||||
|
const lotFieldValue = lotForm["lotFieldValue_" + lotTypeFieldId];
|
||||||
|
if (lotFieldValue && lotFieldValue !== "") {
|
||||||
|
addOrUpdateLotField({
|
||||||
|
lotId: lotForm.lotId,
|
||||||
|
lotTypeFieldId,
|
||||||
|
lotFieldValue
|
||||||
|
}, requestSession, database);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
deleteLotField(lotForm.lotId, lotTypeFieldId, requestSession, database);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
database.close();
|
database.close();
|
||||||
return result.changes > 0;
|
return result.changes > 0;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,9 @@ import sqlite from "better-sqlite3";
|
||||||
|
|
||||||
import { lotOccupancyDB as databasePath } from "../../data/databasePaths.js";
|
import { lotOccupancyDB as databasePath } from "../../data/databasePaths.js";
|
||||||
|
|
||||||
|
import { addOrUpdateLotField } from "./addOrUpdateLotField.js";
|
||||||
|
import { deleteLotField } from "./deleteLotField.js";
|
||||||
|
|
||||||
import type * as recordTypes from "../../types/recordTypes";
|
import type * as recordTypes from "../../types/recordTypes";
|
||||||
|
|
||||||
interface UpdateLotForm {
|
interface UpdateLotForm {
|
||||||
|
|
@ -15,6 +18,9 @@ interface UpdateLotForm {
|
||||||
|
|
||||||
lotLatitude: string;
|
lotLatitude: string;
|
||||||
lotLongitude: string;
|
lotLongitude: string;
|
||||||
|
|
||||||
|
lotTypeFieldIds?: string;
|
||||||
|
[lotFieldValue_lotTypeFieldId: string]: unknown;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function updateLot(
|
export function updateLot(
|
||||||
|
|
@ -53,6 +59,28 @@ export function updateLot(
|
||||||
lotForm.lotId
|
lotForm.lotId
|
||||||
);
|
);
|
||||||
|
|
||||||
|
if (result.changes > 0) {
|
||||||
|
const lotTypeFieldIds = (lotForm.lotTypeFieldIds || "").split(",");
|
||||||
|
|
||||||
|
for (const lotTypeFieldId of lotTypeFieldIds) {
|
||||||
|
const lotFieldValue = lotForm["lotFieldValue_" + lotTypeFieldId] as string;
|
||||||
|
|
||||||
|
if (lotFieldValue && lotFieldValue !== "") {
|
||||||
|
addOrUpdateLotField(
|
||||||
|
{
|
||||||
|
lotId: lotForm.lotId,
|
||||||
|
lotTypeFieldId,
|
||||||
|
lotFieldValue
|
||||||
|
},
|
||||||
|
requestSession,
|
||||||
|
database
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
deleteLotField(lotForm.lotId, lotTypeFieldId, requestSession, database);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
database.close();
|
database.close();
|
||||||
|
|
||||||
return result.changes > 0;
|
return result.changes > 0;
|
||||||
|
|
|
||||||
|
|
@ -4,14 +4,27 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
||||||
const los = exports.los;
|
const los = exports.los;
|
||||||
const lotId = document.querySelector("#lot--lotId").value;
|
const lotId = document.querySelector("#lot--lotId").value;
|
||||||
const isCreate = lotId === "";
|
const isCreate = lotId === "";
|
||||||
|
let hasUnsavedChanges = false;
|
||||||
|
let refreshAfterSave = isCreate;
|
||||||
|
const setUnsavedChanges = () => {
|
||||||
|
if (!hasUnsavedChanges) {
|
||||||
|
hasUnsavedChanges = true;
|
||||||
|
cityssm.enableNavBlocker();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
const clearUnsavedChanges = () => {
|
||||||
|
hasUnsavedChanges = false;
|
||||||
|
cityssm.disableNavBlocker();
|
||||||
|
};
|
||||||
const formElement = document.querySelector("#form--lot");
|
const formElement = document.querySelector("#form--lot");
|
||||||
const updateLot = (formEvent) => {
|
const updateLot = (formEvent) => {
|
||||||
formEvent.preventDefault();
|
formEvent.preventDefault();
|
||||||
cityssm.postJSON(los.urlPrefix + "/lots/" + (isCreate ? "doCreateLot" : "doUpdateLot"), formElement, (responseJSON) => {
|
cityssm.postJSON(los.urlPrefix + "/lots/" + (isCreate ? "doCreateLot" : "doUpdateLot"), formElement, (responseJSON) => {
|
||||||
if (responseJSON.success) {
|
if (responseJSON.success) {
|
||||||
if (isCreate) {
|
clearUnsavedChanges();
|
||||||
|
if (isCreate || refreshAfterSave) {
|
||||||
window.location.href =
|
window.location.href =
|
||||||
los.urlPrefix + "/lots/" + responseJSON.lotId + "/edit";
|
los.urlPrefix + "/lots/" + responseJSON.lotId + "/edit?t=" + Date.now();
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
bulmaJS.alert({
|
bulmaJS.alert({
|
||||||
|
|
@ -30,6 +43,10 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
formElement.addEventListener("submit", updateLot);
|
formElement.addEventListener("submit", updateLot);
|
||||||
|
const formInputElements = formElement.querySelectorAll("input, select");
|
||||||
|
for (const formInputElement of formInputElements) {
|
||||||
|
formInputElement.addEventListener("change", setUnsavedChanges);
|
||||||
|
}
|
||||||
los.initializeUnlockFieldButtons(formElement);
|
los.initializeUnlockFieldButtons(formElement);
|
||||||
if (!isCreate) {
|
if (!isCreate) {
|
||||||
document.querySelector("#button--deleteLot").addEventListener("click", (clickEvent) => {
|
document.querySelector("#button--deleteLot").addEventListener("click", (clickEvent) => {
|
||||||
|
|
@ -64,6 +81,114 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
const lotTypeIdElement = document.querySelector("#lot--lotTypeId");
|
||||||
|
if (isCreate) {
|
||||||
|
const lotFieldsContainerElement = document.querySelector("#container--lotFields");
|
||||||
|
lotTypeIdElement.addEventListener("change", () => {
|
||||||
|
if (lotTypeIdElement.value === "") {
|
||||||
|
lotFieldsContainerElement.innerHTML =
|
||||||
|
'<div class="message is-info">' +
|
||||||
|
'<p class="message-body">Select the ' +
|
||||||
|
exports.aliases.lot.toLowerCase() +
|
||||||
|
" type to load the available fields.</p>" +
|
||||||
|
"</div>";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
cityssm.postJSON(los.urlPrefix + "/lots/doGetLotTypeFields", {
|
||||||
|
lotTypeId: lotTypeIdElement.value
|
||||||
|
}, (responseJSON) => {
|
||||||
|
if (responseJSON.lotTypeFields.length === 0) {
|
||||||
|
lotFieldsContainerElement.innerHTML =
|
||||||
|
'<div class="message is-info">' +
|
||||||
|
'<p class="message-body">There are no additional fields for this ' +
|
||||||
|
exports.aliases.lot.toLowerCase() +
|
||||||
|
" type.</p>" +
|
||||||
|
"</div>";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
lotFieldsContainerElement.innerHTML = "";
|
||||||
|
let lotTypeFieldIds = "";
|
||||||
|
for (const lotTypeField of responseJSON.lotTypeFields) {
|
||||||
|
lotTypeFieldIds += "," + lotTypeField.lotTypeFieldId;
|
||||||
|
const fieldName = "lotFieldValue_" + lotTypeField.lotTypeFieldId;
|
||||||
|
const fieldId = "lot--" + fieldName;
|
||||||
|
const fieldElement = document.createElement("div");
|
||||||
|
fieldElement.className = "field";
|
||||||
|
fieldElement.innerHTML =
|
||||||
|
'<label class="label" for="' +
|
||||||
|
fieldId +
|
||||||
|
'"></label>' +
|
||||||
|
'<div class="control"></div>';
|
||||||
|
fieldElement.querySelector("label").textContent =
|
||||||
|
lotTypeField.lotTypeField;
|
||||||
|
if (lotTypeField.lotTypeFieldValues === "") {
|
||||||
|
const inputElement = document.createElement("input");
|
||||||
|
inputElement.className = "input";
|
||||||
|
inputElement.id = fieldId;
|
||||||
|
inputElement.name = fieldName;
|
||||||
|
inputElement.type = "text";
|
||||||
|
inputElement.required = lotTypeField.isRequired;
|
||||||
|
inputElement.minLength = lotTypeField.minimumLength;
|
||||||
|
inputElement.maxLength = lotTypeField.maximumLength;
|
||||||
|
if (lotTypeField.pattern && lotTypeField.pattern !== "") {
|
||||||
|
inputElement.pattern = lotTypeField.pattern;
|
||||||
|
}
|
||||||
|
fieldElement.querySelector(".control").append(inputElement);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
fieldElement.querySelector(".control").innerHTML =
|
||||||
|
'<div class="select is-fullwidth"><select id="' +
|
||||||
|
fieldId +
|
||||||
|
'" name="' +
|
||||||
|
fieldName +
|
||||||
|
'">' +
|
||||||
|
'<option value="">(Not Set)</option>' +
|
||||||
|
"</select></div>";
|
||||||
|
const selectElement = fieldElement.querySelector("select");
|
||||||
|
selectElement.required = lotTypeField.isRequired;
|
||||||
|
const optionValues = lotTypeField.lotTypeFieldValues.split("\n");
|
||||||
|
for (const optionValue of optionValues) {
|
||||||
|
const optionElement = document.createElement("option");
|
||||||
|
optionElement.value = optionValue;
|
||||||
|
optionElement.textContent = optionValue;
|
||||||
|
selectElement.append(optionElement);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
lotFieldsContainerElement.append(fieldElement);
|
||||||
|
}
|
||||||
|
lotFieldsContainerElement.insertAdjacentHTML("beforeend", '<input name="lotTypeFieldIds" type="hidden" value="' +
|
||||||
|
lotTypeFieldIds.slice(1) +
|
||||||
|
'" />');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
const originalLotTypeId = lotTypeIdElement.value;
|
||||||
|
lotTypeIdElement.addEventListener("change", () => {
|
||||||
|
if (lotTypeIdElement.value !== originalLotTypeId) {
|
||||||
|
bulmaJS.confirm({
|
||||||
|
title: "Confirm Change",
|
||||||
|
message: "Are you sure you want to change the " +
|
||||||
|
exports.aliases.lot.toLowerCase() +
|
||||||
|
" type?\n" +
|
||||||
|
"This change affects the additional fields associated with this record.",
|
||||||
|
contextualColorName: "warning",
|
||||||
|
okButton: {
|
||||||
|
text: "Yes, Keep the Change",
|
||||||
|
callbackFunction: () => {
|
||||||
|
refreshAfterSave = true;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
cancelButton: {
|
||||||
|
text: "Revert the Change",
|
||||||
|
callbackFunction: () => {
|
||||||
|
lotTypeIdElement.value = originalLotTypeId;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
let lotComments = exports.lotComments;
|
let lotComments = exports.lotComments;
|
||||||
delete exports.lotComments;
|
delete exports.lotComments;
|
||||||
const openEditLotComment = (clickEvent) => {
|
const openEditLotComment = (clickEvent) => {
|
||||||
|
|
|
||||||
|
|
@ -18,6 +18,21 @@ declare const bulmaJS: BulmaJS;
|
||||||
|
|
||||||
// Main form
|
// Main form
|
||||||
|
|
||||||
|
let hasUnsavedChanges = false;
|
||||||
|
let refreshAfterSave = isCreate;
|
||||||
|
|
||||||
|
const setUnsavedChanges = () => {
|
||||||
|
if (!hasUnsavedChanges) {
|
||||||
|
hasUnsavedChanges = true;
|
||||||
|
cityssm.enableNavBlocker();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const clearUnsavedChanges = () => {
|
||||||
|
hasUnsavedChanges = false;
|
||||||
|
cityssm.disableNavBlocker();
|
||||||
|
};
|
||||||
|
|
||||||
const formElement = document.querySelector("#form--lot") as HTMLFormElement;
|
const formElement = document.querySelector("#form--lot") as HTMLFormElement;
|
||||||
|
|
||||||
const updateLot = (formEvent: SubmitEvent) => {
|
const updateLot = (formEvent: SubmitEvent) => {
|
||||||
|
|
@ -28,9 +43,11 @@ declare const bulmaJS: BulmaJS;
|
||||||
formElement,
|
formElement,
|
||||||
(responseJSON: { success: boolean; lotId?: number; errorMessage?: string }) => {
|
(responseJSON: { success: boolean; lotId?: number; errorMessage?: string }) => {
|
||||||
if (responseJSON.success) {
|
if (responseJSON.success) {
|
||||||
if (isCreate) {
|
clearUnsavedChanges();
|
||||||
|
|
||||||
|
if (isCreate || refreshAfterSave) {
|
||||||
window.location.href =
|
window.location.href =
|
||||||
los.urlPrefix + "/lots/" + responseJSON.lotId + "/edit";
|
los.urlPrefix + "/lots/" + responseJSON.lotId + "/edit?t=" + Date.now();
|
||||||
} else {
|
} else {
|
||||||
bulmaJS.alert({
|
bulmaJS.alert({
|
||||||
message: exports.aliases.lot + " Updated Successfully",
|
message: exports.aliases.lot + " Updated Successfully",
|
||||||
|
|
@ -50,6 +67,12 @@ declare const bulmaJS: BulmaJS;
|
||||||
|
|
||||||
formElement.addEventListener("submit", updateLot);
|
formElement.addEventListener("submit", updateLot);
|
||||||
|
|
||||||
|
const formInputElements = formElement.querySelectorAll("input, select");
|
||||||
|
|
||||||
|
for (const formInputElement of formInputElements) {
|
||||||
|
formInputElement.addEventListener("change", setUnsavedChanges);
|
||||||
|
}
|
||||||
|
|
||||||
los.initializeUnlockFieldButtons(formElement);
|
los.initializeUnlockFieldButtons(formElement);
|
||||||
|
|
||||||
if (!isCreate) {
|
if (!isCreate) {
|
||||||
|
|
@ -95,6 +118,158 @@ declare const bulmaJS: BulmaJS;
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Lot Type
|
||||||
|
|
||||||
|
const lotTypeIdElement = document.querySelector("#lot--lotTypeId") as HTMLSelectElement;
|
||||||
|
|
||||||
|
if (isCreate) {
|
||||||
|
const lotFieldsContainerElement = document.querySelector(
|
||||||
|
"#container--lotFields"
|
||||||
|
) as HTMLElement;
|
||||||
|
|
||||||
|
lotTypeIdElement.addEventListener("change", () => {
|
||||||
|
if (lotTypeIdElement.value === "") {
|
||||||
|
lotFieldsContainerElement.innerHTML =
|
||||||
|
'<div class="message is-info">' +
|
||||||
|
'<p class="message-body">Select the ' +
|
||||||
|
exports.aliases.lot.toLowerCase() +
|
||||||
|
" type to load the available fields.</p>" +
|
||||||
|
"</div>";
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
cityssm.postJSON(
|
||||||
|
los.urlPrefix + "/lots/doGetLotTypeFields",
|
||||||
|
{
|
||||||
|
lotTypeId: lotTypeIdElement.value
|
||||||
|
},
|
||||||
|
(responseJSON: { lotTypeFields: recordTypes.LotTypeField[] }) => {
|
||||||
|
if (responseJSON.lotTypeFields.length === 0) {
|
||||||
|
lotFieldsContainerElement.innerHTML =
|
||||||
|
'<div class="message is-info">' +
|
||||||
|
'<p class="message-body">There are no additional fields for this ' +
|
||||||
|
exports.aliases.lot.toLowerCase() +
|
||||||
|
" type.</p>" +
|
||||||
|
"</div>";
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
lotFieldsContainerElement.innerHTML = "";
|
||||||
|
|
||||||
|
let lotTypeFieldIds = "";
|
||||||
|
|
||||||
|
for (const lotTypeField of responseJSON.lotTypeFields) {
|
||||||
|
lotTypeFieldIds += "," + lotTypeField.lotTypeFieldId;
|
||||||
|
|
||||||
|
const fieldName = "lotFieldValue_" + lotTypeField.lotTypeFieldId;
|
||||||
|
|
||||||
|
const fieldId = "lot--" + fieldName;
|
||||||
|
|
||||||
|
const fieldElement = document.createElement("div");
|
||||||
|
fieldElement.className = "field";
|
||||||
|
fieldElement.innerHTML =
|
||||||
|
'<label class="label" for="' +
|
||||||
|
fieldId +
|
||||||
|
'"></label>' +
|
||||||
|
'<div class="control"></div>';
|
||||||
|
|
||||||
|
(fieldElement.querySelector("label") as HTMLLabelElement).textContent =
|
||||||
|
lotTypeField.lotTypeField as string;
|
||||||
|
|
||||||
|
if (lotTypeField.lotTypeFieldValues === "") {
|
||||||
|
const inputElement = document.createElement("input");
|
||||||
|
|
||||||
|
inputElement.className = "input";
|
||||||
|
|
||||||
|
inputElement.id = fieldId;
|
||||||
|
|
||||||
|
inputElement.name = fieldName;
|
||||||
|
|
||||||
|
inputElement.type = "text";
|
||||||
|
|
||||||
|
inputElement.required = lotTypeField.isRequired as boolean;
|
||||||
|
inputElement.minLength = lotTypeField.minimumLength as number;
|
||||||
|
inputElement.maxLength = lotTypeField.maximumLength as number;
|
||||||
|
|
||||||
|
if (lotTypeField.pattern && lotTypeField.pattern !== "") {
|
||||||
|
inputElement.pattern = lotTypeField.pattern;
|
||||||
|
}
|
||||||
|
|
||||||
|
(fieldElement.querySelector(".control") as HTMLElement).append(
|
||||||
|
inputElement
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
(fieldElement.querySelector(".control") as HTMLElement).innerHTML =
|
||||||
|
'<div class="select is-fullwidth"><select id="' +
|
||||||
|
fieldId +
|
||||||
|
'" name="' +
|
||||||
|
fieldName +
|
||||||
|
'">' +
|
||||||
|
'<option value="">(Not Set)</option>' +
|
||||||
|
"</select></div>";
|
||||||
|
|
||||||
|
const selectElement = fieldElement.querySelector(
|
||||||
|
"select"
|
||||||
|
) as HTMLSelectElement;
|
||||||
|
|
||||||
|
selectElement.required = lotTypeField.isRequired as boolean;
|
||||||
|
|
||||||
|
const optionValues = (lotTypeField.lotTypeFieldValues as string).split(
|
||||||
|
"\n"
|
||||||
|
);
|
||||||
|
|
||||||
|
for (const optionValue of optionValues) {
|
||||||
|
const optionElement = document.createElement("option");
|
||||||
|
optionElement.value = optionValue;
|
||||||
|
optionElement.textContent = optionValue;
|
||||||
|
selectElement.append(optionElement);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
lotFieldsContainerElement.append(fieldElement);
|
||||||
|
}
|
||||||
|
|
||||||
|
lotFieldsContainerElement.insertAdjacentHTML(
|
||||||
|
"beforeend",
|
||||||
|
'<input name="lotTypeFieldIds" type="hidden" value="' +
|
||||||
|
lotTypeFieldIds.slice(1) +
|
||||||
|
'" />'
|
||||||
|
);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
const originalLotTypeId = lotTypeIdElement.value;
|
||||||
|
|
||||||
|
lotTypeIdElement.addEventListener("change", () => {
|
||||||
|
if (lotTypeIdElement.value !== originalLotTypeId) {
|
||||||
|
bulmaJS.confirm({
|
||||||
|
title: "Confirm Change",
|
||||||
|
message:
|
||||||
|
"Are you sure you want to change the " +
|
||||||
|
exports.aliases.lot.toLowerCase() +
|
||||||
|
" type?\n" +
|
||||||
|
"This change affects the additional fields associated with this record.",
|
||||||
|
contextualColorName: "warning",
|
||||||
|
okButton: {
|
||||||
|
text: "Yes, Keep the Change",
|
||||||
|
callbackFunction: () => {
|
||||||
|
refreshAfterSave = true;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
cancelButton: {
|
||||||
|
text: "Revert the Change",
|
||||||
|
callbackFunction: () => {
|
||||||
|
lotTypeIdElement.value = originalLotTypeId;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
// Comments
|
// Comments
|
||||||
|
|
||||||
let lotComments: recordTypes.LotComment[] = exports.lotComments;
|
let lotComments: recordTypes.LotComment[] = exports.lotComments;
|
||||||
|
|
|
||||||
File diff suppressed because one or more lines are too long
|
|
@ -7,6 +7,7 @@ import handler_next from "../handlers/lots-get/next.js";
|
||||||
import handler_previous from "../handlers/lots-get/previous.js";
|
import handler_previous from "../handlers/lots-get/previous.js";
|
||||||
import handler_new from "../handlers/lots-get/new.js";
|
import handler_new from "../handlers/lots-get/new.js";
|
||||||
import handler_edit from "../handlers/lots-get/edit.js";
|
import handler_edit from "../handlers/lots-get/edit.js";
|
||||||
|
import handler_doGetLotTypeFields from "../handlers/lots-post/doGetLotTypeFields.js";
|
||||||
import handler_doCreateLot from "../handlers/lots-post/doCreateLot.js";
|
import handler_doCreateLot from "../handlers/lots-post/doCreateLot.js";
|
||||||
import handler_doUpdateLot from "../handlers/lots-post/doUpdateLot.js";
|
import handler_doUpdateLot from "../handlers/lots-post/doUpdateLot.js";
|
||||||
import handler_doDeleteLot from "../handlers/lots-post/doDeleteLot.js";
|
import handler_doDeleteLot from "../handlers/lots-post/doDeleteLot.js";
|
||||||
|
|
@ -21,6 +22,7 @@ router.get("/:lotId", handler_view);
|
||||||
router.get("/:lotId/next", handler_next);
|
router.get("/:lotId/next", handler_next);
|
||||||
router.get("/:lotId/previous", handler_previous);
|
router.get("/:lotId/previous", handler_previous);
|
||||||
router.get("/:lotId/edit", permissionHandlers.updateGetHandler, handler_edit);
|
router.get("/:lotId/edit", permissionHandlers.updateGetHandler, handler_edit);
|
||||||
|
router.post("/doGetLotTypeFields", permissionHandlers.updatePostHandler, handler_doGetLotTypeFields);
|
||||||
router.post("/doCreateLot", permissionHandlers.updatePostHandler, handler_doCreateLot);
|
router.post("/doCreateLot", permissionHandlers.updatePostHandler, handler_doCreateLot);
|
||||||
router.post("/doUpdateLot", permissionHandlers.updatePostHandler, handler_doUpdateLot);
|
router.post("/doUpdateLot", permissionHandlers.updatePostHandler, handler_doUpdateLot);
|
||||||
router.post("/doDeleteLot", permissionHandlers.updatePostHandler, handler_doDeleteLot);
|
router.post("/doDeleteLot", permissionHandlers.updatePostHandler, handler_doDeleteLot);
|
||||||
|
|
|
||||||
|
|
@ -12,6 +12,8 @@ import handler_previous from "../handlers/lots-get/previous.js";
|
||||||
import handler_new from "../handlers/lots-get/new.js";
|
import handler_new from "../handlers/lots-get/new.js";
|
||||||
import handler_edit from "../handlers/lots-get/edit.js";
|
import handler_edit from "../handlers/lots-get/edit.js";
|
||||||
|
|
||||||
|
import handler_doGetLotTypeFields from "../handlers/lots-post/doGetLotTypeFields.js";
|
||||||
|
|
||||||
import handler_doCreateLot from "../handlers/lots-post/doCreateLot.js";
|
import handler_doCreateLot from "../handlers/lots-post/doCreateLot.js";
|
||||||
import handler_doUpdateLot from "../handlers/lots-post/doUpdateLot.js";
|
import handler_doUpdateLot from "../handlers/lots-post/doUpdateLot.js";
|
||||||
import handler_doDeleteLot from "../handlers/lots-post/doDeleteLot.js";
|
import handler_doDeleteLot from "../handlers/lots-post/doDeleteLot.js";
|
||||||
|
|
@ -44,6 +46,8 @@ router.get("/:lotId/previous", handler_previous);
|
||||||
|
|
||||||
router.get("/:lotId/edit", permissionHandlers.updateGetHandler, handler_edit);
|
router.get("/:lotId/edit", permissionHandlers.updateGetHandler, handler_edit);
|
||||||
|
|
||||||
|
router.post("/doGetLotTypeFields", permissionHandlers.updatePostHandler, handler_doGetLotTypeFields);
|
||||||
|
|
||||||
router.post("/doCreateLot", permissionHandlers.updatePostHandler, handler_doCreateLot);
|
router.post("/doCreateLot", permissionHandlers.updatePostHandler, handler_doCreateLot);
|
||||||
|
|
||||||
router.post("/doUpdateLot", permissionHandlers.updatePostHandler, handler_doUpdateLot);
|
router.post("/doUpdateLot", permissionHandlers.updatePostHandler, handler_doUpdateLot);
|
||||||
|
|
|
||||||
|
|
@ -62,6 +62,7 @@ export interface Lot extends Record {
|
||||||
lotLongitude?: number;
|
lotLongitude?: number;
|
||||||
lotStatusId?: number;
|
lotStatusId?: number;
|
||||||
lotStatus?: string;
|
lotStatus?: string;
|
||||||
|
lotFields?: LotField[];
|
||||||
lotOccupancyCount?: number;
|
lotOccupancyCount?: number;
|
||||||
lotOccupancies?: LotOccupancy[];
|
lotOccupancies?: LotOccupancy[];
|
||||||
lotComments?: LotComment[];
|
lotComments?: LotComment[];
|
||||||
|
|
@ -75,6 +76,11 @@ export interface LotComment extends Record {
|
||||||
lotCommentTimeString?: string;
|
lotCommentTimeString?: string;
|
||||||
lotComment?: string;
|
lotComment?: string;
|
||||||
}
|
}
|
||||||
|
export interface LotField extends LotTypeField, Record {
|
||||||
|
lotId?: number;
|
||||||
|
lotTypeFieldId?: number;
|
||||||
|
lotFieldValue?: string;
|
||||||
|
}
|
||||||
export interface OccupancyType extends Record {
|
export interface OccupancyType extends Record {
|
||||||
occupancyTypeId: number;
|
occupancyTypeId: number;
|
||||||
occupancyType: string;
|
occupancyType: string;
|
||||||
|
|
|
||||||
|
|
@ -84,6 +84,8 @@ export interface Lot extends Record {
|
||||||
lotStatusId?: number;
|
lotStatusId?: number;
|
||||||
lotStatus?: string;
|
lotStatus?: string;
|
||||||
|
|
||||||
|
lotFields?: LotField[];
|
||||||
|
|
||||||
lotOccupancyCount?: number;
|
lotOccupancyCount?: number;
|
||||||
lotOccupancies?: LotOccupancy[];
|
lotOccupancies?: LotOccupancy[];
|
||||||
|
|
||||||
|
|
@ -103,6 +105,12 @@ export interface LotComment extends Record {
|
||||||
lotComment?: string;
|
lotComment?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface LotField extends LotTypeField, Record {
|
||||||
|
lotId?: number;
|
||||||
|
lotTypeFieldId?: number;
|
||||||
|
lotFieldValue?: string;
|
||||||
|
}
|
||||||
|
|
||||||
export interface OccupancyType extends Record {
|
export interface OccupancyType extends Record {
|
||||||
occupancyTypeId: number;
|
occupancyTypeId: number;
|
||||||
occupancyType: string;
|
occupancyType: string;
|
||||||
|
|
|
||||||
|
|
@ -106,8 +106,6 @@
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
|
||||||
<div class="column">
|
|
||||||
<label class="label" for="lot--lotStatusId">
|
<label class="label" for="lot--lotStatusId">
|
||||||
<%= configFunctions.getProperty("aliases.lot") %> Status
|
<%= configFunctions.getProperty("aliases.lot") %> Status
|
||||||
</label>
|
</label>
|
||||||
|
|
@ -138,6 +136,78 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="column">
|
||||||
|
<div id="container--lotFields">
|
||||||
|
<% if (isCreate) { %>
|
||||||
|
<div class="message is-info">
|
||||||
|
<p class="message-body">
|
||||||
|
Select the <%= configFunctions.getProperty("aliases.lot").toLowerCase() %> type to load the available fields.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
<% } else if (lot.lotFields.length === 0) { %>
|
||||||
|
<div class="message is-info">
|
||||||
|
<p class="message-body">
|
||||||
|
The current <%= configFunctions.getProperty("aliases.lot").toLowerCase() %> type has no additional fields.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
<% } else { %>
|
||||||
|
<% let lotTypeFieldIds = ""; %>
|
||||||
|
<% for (const lotField of lot.lotFields) { %>
|
||||||
|
<% lotTypeFieldIds += "," + lotField.lotTypeFieldId; %>
|
||||||
|
<div class="field">
|
||||||
|
<label class="label" for="lot--lotFieldValue_<%= lotField.lotTypeFieldId %>">
|
||||||
|
<%= lotField.lotTypeField %>
|
||||||
|
</label>
|
||||||
|
<div class="control">
|
||||||
|
<% if (!lotField.lotTypeFieldValues || lotField.lotTypeFieldValues === "") { %>
|
||||||
|
<input class="input"
|
||||||
|
id="lot--lotFieldValue_<%= lotField.lotTypeFieldId %>"
|
||||||
|
name="lotFieldValue_<%= lotField.lotTypeFieldId %>"
|
||||||
|
type="text"
|
||||||
|
value="<%= lotField.lotFieldValue %>"
|
||||||
|
<% if (lotField.pattern !== "") { %>
|
||||||
|
pattern="<%= lotField.pattern %>"
|
||||||
|
<% } %>
|
||||||
|
minlength="<%= lotField.minimumLength %>"
|
||||||
|
maxlength="<%= lotField.maximumLength %>"
|
||||||
|
<%= lotField.isRequired ? " required" : "" %> />
|
||||||
|
<% } else { %>
|
||||||
|
<%
|
||||||
|
const fieldValues = lotField.lotTypeFieldValues.split("\n");
|
||||||
|
let valueFound = false;
|
||||||
|
%>
|
||||||
|
<div class="select is-fullwidth">
|
||||||
|
<select id="lot--lotFieldValue_<%= lotField.lotTypeFieldId %>"
|
||||||
|
name="lotFieldValue_<%= lotField.lotTypeFieldId %>">
|
||||||
|
<% if (!lotField.isRequired || lotField.lotFieldValue === "") { %>
|
||||||
|
<option value="">(Not Set)</option>
|
||||||
|
<% } %>
|
||||||
|
<% for (const fieldValue of fieldValues) { %>
|
||||||
|
<%
|
||||||
|
if (fieldValue === lotField.lotFieldValue) {
|
||||||
|
valueFound = true;
|
||||||
|
}
|
||||||
|
%>
|
||||||
|
<option value="<%= fieldValue %>"
|
||||||
|
<%= (fieldValue === lotField.lotFieldValue ? " selected" : "") %>>
|
||||||
|
<%= fieldValue %>
|
||||||
|
</option>
|
||||||
|
<% } %>
|
||||||
|
<% if (!valueFound && lotField.lotFieldValue !== "") { %>
|
||||||
|
<option value="<%= lotField.lotFieldValue %>" selected>
|
||||||
|
<%= lotField.lotFieldValue %>
|
||||||
|
</option>
|
||||||
|
<% } %>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
<% } %>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<% } %>
|
||||||
|
<input id="lot--lotTypeFieldIds" name="lotTypeFieldIds" type="hidden" value="<%= lotTypeFieldIds.slice(1) %>" />
|
||||||
|
<% } %>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -46,9 +46,7 @@
|
||||||
<% } %>
|
<% } %>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="columns">
|
<div class="panel">
|
||||||
<div class="column">
|
|
||||||
<div class="panel">
|
|
||||||
<div class="panel-block is-block">
|
<div class="panel-block is-block">
|
||||||
<p>
|
<p>
|
||||||
<strong><%= configFunctions.getProperty("aliases.map") %></strong><br />
|
<strong><%= configFunctions.getProperty("aliases.map") %></strong><br />
|
||||||
|
|
@ -69,30 +67,36 @@
|
||||||
<%= lot.lotStatus %>
|
<%= lot.lotStatus %>
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="column">
|
<div class="column">
|
||||||
<div class="panel">
|
<% if (lot.lotFields.length > 0) { %>
|
||||||
<h2 class="panel-heading">Image</h2>
|
<% for (const lotField of lot.lotFields) { %>
|
||||||
<div class="panel-block is-block">
|
<p class="mb-2">
|
||||||
<% if (lot.mapSVG) { %>
|
<strong><%= lotField.lotTypeField %></strong><br />
|
||||||
<% const imageURL = urlPrefix + "/images/maps/" + lot.mapSVG %>
|
<% if (lotField.lotFieldValue) { %>
|
||||||
<div class="image" id="lot--map" data-map-key="<%= lot.mapKey %>">
|
<%= lotField.lotFieldValue %>
|
||||||
<%- include('../public/images/maps/' + lot.mapSVG); -%>
|
|
||||||
</div>
|
|
||||||
<% } else { %>
|
<% } else { %>
|
||||||
<div class="message is-info">
|
<span class="has-text-grey">(No Value)</span>
|
||||||
<p class="message-body">There are no image associated with this
|
<% } %>
|
||||||
<%= configFunctions.getProperty("aliases.lot").toLowerCase() %>.</p>
|
</p>
|
||||||
</div>
|
<% } %>
|
||||||
<% } %>
|
<% } %>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<% if (lot.mapSVG) { %>
|
||||||
|
<div class="panel">
|
||||||
|
<h2 class="panel-heading">Image</h2>
|
||||||
|
<div class="panel-block is-block">
|
||||||
|
<% const imageURL = urlPrefix + "/images/maps/" + lot.mapSVG %>
|
||||||
|
<div class="image" id="lot--map" data-map-key="<%= lot.mapKey %>">
|
||||||
|
<%- include('../public/images/maps/' + lot.mapSVG); -%>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<% } %>
|
||||||
|
|
||||||
<% if (lot.lotComments.length > 0) { %>
|
<% if (lot.lotComments.length > 0) { %>
|
||||||
<div class="panel">
|
<div class="panel">
|
||||||
<h2 class="panel-heading">Comments</h2>
|
<h2 class="panel-heading">Comments</h2>
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue