work order development
- add lot occupancies - add lots - display milestones - complete milestones - reopen milestonesdeepsource-autofix-76c6eb20
parent
ab87f933c7
commit
2b38da7bea
|
|
@ -1,4 +1,4 @@
|
||||||
import { getWorkOrderTypes } from "../../helpers/functions.cache.js";
|
import { getLotStatuses, getWorkOrderTypes } from "../../helpers/functions.cache.js";
|
||||||
import * as configFunctions from "../../helpers/functions.config.js";
|
import * as configFunctions from "../../helpers/functions.config.js";
|
||||||
import { getWorkOrder } from "../../helpers/lotOccupancyDB/getWorkOrder.js";
|
import { getWorkOrder } from "../../helpers/lotOccupancyDB/getWorkOrder.js";
|
||||||
export const handler = (request, response) => {
|
export const handler = (request, response) => {
|
||||||
|
|
@ -9,14 +9,18 @@ export const handler = (request, response) => {
|
||||||
}
|
}
|
||||||
if (workOrder.workOrderCloseDate) {
|
if (workOrder.workOrderCloseDate) {
|
||||||
return response.redirect(configFunctions.getProperty("reverseProxy.urlPrefix") +
|
return response.redirect(configFunctions.getProperty("reverseProxy.urlPrefix") +
|
||||||
"/workOrders/" + workOrder.workOrderId.toString() + "/?error=workOrderIsClosed");
|
"/workOrders/" +
|
||||||
|
workOrder.workOrderId.toString() +
|
||||||
|
"/?error=workOrderIsClosed");
|
||||||
}
|
}
|
||||||
const workOrderTypes = getWorkOrderTypes();
|
const workOrderTypes = getWorkOrderTypes();
|
||||||
|
const lotStatuses = getLotStatuses();
|
||||||
response.render("workOrder-edit", {
|
response.render("workOrder-edit", {
|
||||||
headTitle: "Work Order #" + workOrder.workOrderNumber,
|
headTitle: "Work Order #" + workOrder.workOrderNumber,
|
||||||
workOrder,
|
workOrder,
|
||||||
isCreate: false,
|
isCreate: false,
|
||||||
workOrderTypes
|
workOrderTypes,
|
||||||
|
lotStatuses
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
export default handler;
|
export default handler;
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,9 @@
|
||||||
import type { RequestHandler } from "express";
|
import type { RequestHandler } from "express";
|
||||||
import { getWorkOrderTypes } from "../../helpers/functions.cache.js";
|
|
||||||
|
import {
|
||||||
|
getLotStatuses,
|
||||||
|
getWorkOrderTypes
|
||||||
|
} from "../../helpers/functions.cache.js";
|
||||||
|
|
||||||
import * as configFunctions from "../../helpers/functions.config.js";
|
import * as configFunctions from "../../helpers/functions.config.js";
|
||||||
|
|
||||||
|
|
@ -18,17 +22,22 @@ export const handler: RequestHandler = (request, response) => {
|
||||||
if (workOrder.workOrderCloseDate) {
|
if (workOrder.workOrderCloseDate) {
|
||||||
return response.redirect(
|
return response.redirect(
|
||||||
configFunctions.getProperty("reverseProxy.urlPrefix") +
|
configFunctions.getProperty("reverseProxy.urlPrefix") +
|
||||||
"/workOrders/" + workOrder.workOrderId.toString() + "/?error=workOrderIsClosed"
|
"/workOrders/" +
|
||||||
|
workOrder.workOrderId.toString() +
|
||||||
|
"/?error=workOrderIsClosed"
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
const workOrderTypes = getWorkOrderTypes();
|
const workOrderTypes = getWorkOrderTypes();
|
||||||
|
|
||||||
|
const lotStatuses = getLotStatuses();
|
||||||
|
|
||||||
response.render("workOrder-edit", {
|
response.render("workOrder-edit", {
|
||||||
headTitle: "Work Order #" + workOrder.workOrderNumber,
|
headTitle: "Work Order #" + workOrder.workOrderNumber,
|
||||||
workOrder,
|
workOrder,
|
||||||
isCreate: false,
|
isCreate: false,
|
||||||
workOrderTypes
|
workOrderTypes,
|
||||||
|
lotStatuses
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,3 @@
|
||||||
|
import type { RequestHandler } from "express";
|
||||||
|
export declare const handler: RequestHandler;
|
||||||
|
export default handler;
|
||||||
|
|
@ -0,0 +1,19 @@
|
||||||
|
import { addWorkOrderLot } from "../../helpers/lotOccupancyDB/addWorkOrderLot.js";
|
||||||
|
import { getLots } from "../../helpers/lotOccupancyDB/getLots.js";
|
||||||
|
export const handler = async (request, response) => {
|
||||||
|
const success = addWorkOrderLot({
|
||||||
|
workOrderId: request.body.workOrderId,
|
||||||
|
lotId: request.body.lotId
|
||||||
|
}, request.session);
|
||||||
|
const workOrderLots = getLots({
|
||||||
|
workOrderId: request.body.workOrderId
|
||||||
|
}, {
|
||||||
|
limit: -1,
|
||||||
|
offset: 0
|
||||||
|
}).lots;
|
||||||
|
response.json({
|
||||||
|
success,
|
||||||
|
workOrderLots
|
||||||
|
});
|
||||||
|
};
|
||||||
|
export default handler;
|
||||||
|
|
@ -0,0 +1,31 @@
|
||||||
|
import type { RequestHandler } from "express";
|
||||||
|
|
||||||
|
import { addWorkOrderLot } from "../../helpers/lotOccupancyDB/addWorkOrderLot.js";
|
||||||
|
import { getLots } from "../../helpers/lotOccupancyDB/getLots.js";
|
||||||
|
|
||||||
|
export const handler: RequestHandler = async (request, response) => {
|
||||||
|
const success = addWorkOrderLot(
|
||||||
|
{
|
||||||
|
workOrderId: request.body.workOrderId,
|
||||||
|
lotId: request.body.lotId
|
||||||
|
},
|
||||||
|
request.session
|
||||||
|
);
|
||||||
|
|
||||||
|
const workOrderLots = getLots(
|
||||||
|
{
|
||||||
|
workOrderId: request.body.workOrderId
|
||||||
|
},
|
||||||
|
{
|
||||||
|
limit: -1,
|
||||||
|
offset: 0
|
||||||
|
}
|
||||||
|
).lots;
|
||||||
|
|
||||||
|
response.json({
|
||||||
|
success,
|
||||||
|
workOrderLots
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
export default handler;
|
||||||
|
|
@ -0,0 +1,3 @@
|
||||||
|
import type { RequestHandler } from "express";
|
||||||
|
export declare const handler: RequestHandler;
|
||||||
|
export default handler;
|
||||||
|
|
@ -0,0 +1,20 @@
|
||||||
|
import { addWorkOrderLotOccupancy } from "../../helpers/lotOccupancyDB/addWorkOrderLotOccupancy.js";
|
||||||
|
import { getLotOccupancies } from "../../helpers/lotOccupancyDB/getLotOccupancies.js";
|
||||||
|
export const handler = async (request, response) => {
|
||||||
|
const success = addWorkOrderLotOccupancy({
|
||||||
|
workOrderId: request.body.workOrderId,
|
||||||
|
lotOccupancyId: request.body.lotOccupancyId
|
||||||
|
}, request.session);
|
||||||
|
const workOrderLotOccupancies = getLotOccupancies({
|
||||||
|
workOrderId: request.body.workOrderId
|
||||||
|
}, {
|
||||||
|
limit: -1,
|
||||||
|
offset: 0,
|
||||||
|
includeOccupants: true
|
||||||
|
}).lotOccupancies;
|
||||||
|
response.json({
|
||||||
|
success,
|
||||||
|
workOrderLotOccupancies
|
||||||
|
});
|
||||||
|
};
|
||||||
|
export default handler;
|
||||||
|
|
@ -0,0 +1,32 @@
|
||||||
|
import type { RequestHandler } from "express";
|
||||||
|
|
||||||
|
import { addWorkOrderLotOccupancy } from "../../helpers/lotOccupancyDB/addWorkOrderLotOccupancy.js";
|
||||||
|
import { getLotOccupancies } from "../../helpers/lotOccupancyDB/getLotOccupancies.js";
|
||||||
|
|
||||||
|
export const handler: RequestHandler = async (request, response) => {
|
||||||
|
const success = addWorkOrderLotOccupancy(
|
||||||
|
{
|
||||||
|
workOrderId: request.body.workOrderId,
|
||||||
|
lotOccupancyId: request.body.lotOccupancyId
|
||||||
|
},
|
||||||
|
request.session
|
||||||
|
);
|
||||||
|
|
||||||
|
const workOrderLotOccupancies = getLotOccupancies(
|
||||||
|
{
|
||||||
|
workOrderId: request.body.workOrderId
|
||||||
|
},
|
||||||
|
{
|
||||||
|
limit: -1,
|
||||||
|
offset: 0,
|
||||||
|
includeOccupants: true
|
||||||
|
}
|
||||||
|
).lotOccupancies;
|
||||||
|
|
||||||
|
response.json({
|
||||||
|
success,
|
||||||
|
workOrderLotOccupancies
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
export default handler;
|
||||||
|
|
@ -0,0 +1,3 @@
|
||||||
|
import type { RequestHandler } from "express";
|
||||||
|
export declare const handler: RequestHandler;
|
||||||
|
export default handler;
|
||||||
|
|
@ -0,0 +1,13 @@
|
||||||
|
import { completeWorkOrderMilestone } from "../../helpers/lotOccupancyDB/completeWorkOrderMiletstone.js";
|
||||||
|
import { getWorkOrderMilestones } from "../../helpers/lotOccupancyDB/getWorkOrderMilestones.js";
|
||||||
|
export const handler = async (request, response) => {
|
||||||
|
const success = completeWorkOrderMilestone({
|
||||||
|
workOrderMilestoneId: request.body.workOrderMilestoneId
|
||||||
|
}, request.session);
|
||||||
|
const workOrderMilestones = getWorkOrderMilestones(request.body.workOrderId);
|
||||||
|
response.json({
|
||||||
|
success,
|
||||||
|
workOrderMilestones
|
||||||
|
});
|
||||||
|
};
|
||||||
|
export default handler;
|
||||||
|
|
@ -0,0 +1,25 @@
|
||||||
|
import type { RequestHandler } from "express";
|
||||||
|
|
||||||
|
import { completeWorkOrderMilestone } from "../../helpers/lotOccupancyDB/completeWorkOrderMiletstone.js";
|
||||||
|
|
||||||
|
import { getWorkOrderMilestones } from "../../helpers/lotOccupancyDB/getWorkOrderMilestones.js";
|
||||||
|
|
||||||
|
export const handler: RequestHandler = async (request, response) => {
|
||||||
|
const success = completeWorkOrderMilestone(
|
||||||
|
{
|
||||||
|
workOrderMilestoneId: request.body.workOrderMilestoneId
|
||||||
|
},
|
||||||
|
request.session
|
||||||
|
);
|
||||||
|
|
||||||
|
const workOrderMilestones = getWorkOrderMilestones(
|
||||||
|
request.body.workOrderId
|
||||||
|
);
|
||||||
|
|
||||||
|
response.json({
|
||||||
|
success,
|
||||||
|
workOrderMilestones
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
export default handler;
|
||||||
|
|
@ -0,0 +1,3 @@
|
||||||
|
import type { RequestHandler } from "express";
|
||||||
|
export declare const handler: RequestHandler;
|
||||||
|
export default handler;
|
||||||
|
|
@ -0,0 +1,11 @@
|
||||||
|
import { reopenWorkOrderMilestone } from "../../helpers/lotOccupancyDB/reopenWorkOrderMilestone.js";
|
||||||
|
import { getWorkOrderMilestones } from "../../helpers/lotOccupancyDB/getWorkOrderMilestones.js";
|
||||||
|
export const handler = async (request, response) => {
|
||||||
|
const success = reopenWorkOrderMilestone(request.body.workOrderMilestoneId, request.session);
|
||||||
|
const workOrderMilestones = getWorkOrderMilestones(request.body.workOrderId);
|
||||||
|
response.json({
|
||||||
|
success,
|
||||||
|
workOrderMilestones
|
||||||
|
});
|
||||||
|
};
|
||||||
|
export default handler;
|
||||||
|
|
@ -0,0 +1,23 @@
|
||||||
|
import type { RequestHandler } from "express";
|
||||||
|
|
||||||
|
import { reopenWorkOrderMilestone } from "../../helpers/lotOccupancyDB/reopenWorkOrderMilestone.js";
|
||||||
|
|
||||||
|
import { getWorkOrderMilestones } from "../../helpers/lotOccupancyDB/getWorkOrderMilestones.js";
|
||||||
|
|
||||||
|
export const handler: RequestHandler = async (request, response) => {
|
||||||
|
const success = reopenWorkOrderMilestone(
|
||||||
|
request.body.workOrderMilestoneId,
|
||||||
|
request.session
|
||||||
|
);
|
||||||
|
|
||||||
|
const workOrderMilestones = getWorkOrderMilestones(
|
||||||
|
request.body.workOrderId
|
||||||
|
);
|
||||||
|
|
||||||
|
response.json({
|
||||||
|
success,
|
||||||
|
workOrderMilestones
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
export default handler;
|
||||||
|
|
@ -3,14 +3,37 @@ import { lotOccupancyDB as databasePath } from "../../data/databasePaths.js";
|
||||||
export const addWorkOrderLotOccupancy = (workOrderLotOccupancyForm, requestSession) => {
|
export const addWorkOrderLotOccupancy = (workOrderLotOccupancyForm, requestSession) => {
|
||||||
const database = sqlite(databasePath);
|
const database = sqlite(databasePath);
|
||||||
const rightNowMillis = Date.now();
|
const rightNowMillis = Date.now();
|
||||||
const result = database
|
const row = database
|
||||||
|
.prepare("select recordDelete_timeMillis" +
|
||||||
|
" from WorkOrderLotOccupancies" +
|
||||||
|
" where workOrderId = ?" +
|
||||||
|
" and lotOccupancyId = ?")
|
||||||
|
.get(workOrderLotOccupancyForm.workOrderId, workOrderLotOccupancyForm.lotOccupancyId);
|
||||||
|
if (row) {
|
||||||
|
if (row.recordDelete_timeMillis) {
|
||||||
|
database
|
||||||
|
.prepare("update WorkOrderLotOccupancies" +
|
||||||
|
" set recordCreate_userName = ?," +
|
||||||
|
" recordCreate_timeMillis = ?," +
|
||||||
|
" recordUpdate_userName = ?," +
|
||||||
|
" recordUpdate_timeMillis = ?," +
|
||||||
|
" recordDelete_userName = null," +
|
||||||
|
" recordDelete_timeMillis = null" +
|
||||||
|
" where workOrderId = ?" +
|
||||||
|
" and lotOccupancyId = ?")
|
||||||
|
.run(requestSession.user.userName, rightNowMillis, requestSession.user.userName, rightNowMillis, workOrderLotOccupancyForm.workOrderId, workOrderLotOccupancyForm.lotOccupancyId);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
database
|
||||||
.prepare("insert into WorkOrderLotOccupancies (" +
|
.prepare("insert into WorkOrderLotOccupancies (" +
|
||||||
"workOrderId, lotOccupancyId," +
|
"workOrderId, lotOccupancyId," +
|
||||||
" recordCreate_userName, recordCreate_timeMillis," +
|
" recordCreate_userName, recordCreate_timeMillis," +
|
||||||
" recordUpdate_userName, recordUpdate_timeMillis)" +
|
" recordUpdate_userName, recordUpdate_timeMillis)" +
|
||||||
" values (?, ?, ?, ?, ?, ?)")
|
" values (?, ?, ?, ?, ?, ?)")
|
||||||
.run(workOrderLotOccupancyForm.workOrderId, workOrderLotOccupancyForm.lotOccupancyId, requestSession.user.userName, rightNowMillis, requestSession.user.userName, rightNowMillis);
|
.run(workOrderLotOccupancyForm.workOrderId, workOrderLotOccupancyForm.lotOccupancyId, requestSession.user.userName, rightNowMillis, requestSession.user.userName, rightNowMillis);
|
||||||
|
}
|
||||||
database.close();
|
database.close();
|
||||||
return result.changes > 0;
|
return true;
|
||||||
};
|
};
|
||||||
export default addWorkOrderLotOccupancy;
|
export default addWorkOrderLotOccupancy;
|
||||||
|
|
|
||||||
|
|
@ -17,7 +17,43 @@ export const addWorkOrderLotOccupancy = (
|
||||||
|
|
||||||
const rightNowMillis = Date.now();
|
const rightNowMillis = Date.now();
|
||||||
|
|
||||||
const result = database
|
const row: { recordDelete_timeMillis?: number } = database
|
||||||
|
.prepare(
|
||||||
|
"select recordDelete_timeMillis" +
|
||||||
|
" from WorkOrderLotOccupancies" +
|
||||||
|
" where workOrderId = ?" +
|
||||||
|
" and lotOccupancyId = ?"
|
||||||
|
)
|
||||||
|
.get(
|
||||||
|
workOrderLotOccupancyForm.workOrderId,
|
||||||
|
workOrderLotOccupancyForm.lotOccupancyId
|
||||||
|
);
|
||||||
|
|
||||||
|
if (row) {
|
||||||
|
if (row.recordDelete_timeMillis) {
|
||||||
|
database
|
||||||
|
.prepare(
|
||||||
|
"update WorkOrderLotOccupancies" +
|
||||||
|
" set recordCreate_userName = ?," +
|
||||||
|
" recordCreate_timeMillis = ?," +
|
||||||
|
" recordUpdate_userName = ?," +
|
||||||
|
" recordUpdate_timeMillis = ?," +
|
||||||
|
" recordDelete_userName = null," +
|
||||||
|
" recordDelete_timeMillis = null" +
|
||||||
|
" where workOrderId = ?" +
|
||||||
|
" and lotOccupancyId = ?"
|
||||||
|
)
|
||||||
|
.run(
|
||||||
|
requestSession.user.userName,
|
||||||
|
rightNowMillis,
|
||||||
|
requestSession.user.userName,
|
||||||
|
rightNowMillis,
|
||||||
|
workOrderLotOccupancyForm.workOrderId,
|
||||||
|
workOrderLotOccupancyForm.lotOccupancyId
|
||||||
|
);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
database
|
||||||
.prepare(
|
.prepare(
|
||||||
"insert into WorkOrderLotOccupancies (" +
|
"insert into WorkOrderLotOccupancies (" +
|
||||||
"workOrderId, lotOccupancyId," +
|
"workOrderId, lotOccupancyId," +
|
||||||
|
|
@ -33,10 +69,11 @@ export const addWorkOrderLotOccupancy = (
|
||||||
requestSession.user.userName,
|
requestSession.user.userName,
|
||||||
rightNowMillis
|
rightNowMillis
|
||||||
);
|
);
|
||||||
|
}
|
||||||
|
|
||||||
database.close();
|
database.close();
|
||||||
|
|
||||||
return result.changes > 0;
|
return true;
|
||||||
};
|
};
|
||||||
|
|
||||||
export default addWorkOrderLotOccupancy;
|
export default addWorkOrderLotOccupancy;
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,8 @@
|
||||||
|
import type * as recordTypes from "../../types/recordTypes";
|
||||||
|
interface CompleteWorkOrderMilestoneForm {
|
||||||
|
workOrderMilestoneId: string | number;
|
||||||
|
workOrderMilestoneCompletionDateString?: string;
|
||||||
|
workOrderMilestoneCompletionTimeString?: string;
|
||||||
|
}
|
||||||
|
export declare const completeWorkOrderMilestone: (milestoneForm: CompleteWorkOrderMilestoneForm, requestSession: recordTypes.PartialSession) => boolean;
|
||||||
|
export default completeWorkOrderMilestone;
|
||||||
|
|
@ -0,0 +1,22 @@
|
||||||
|
import sqlite from "better-sqlite3";
|
||||||
|
import { lotOccupancyDB as databasePath } from "../../data/databasePaths.js";
|
||||||
|
import { dateStringToInteger, dateToInteger, dateToTimeInteger, timeStringToInteger } from "@cityssm/expressjs-server-js/dateTimeFns.js";
|
||||||
|
export const completeWorkOrderMilestone = (milestoneForm, requestSession) => {
|
||||||
|
const rightNow = new Date();
|
||||||
|
const database = sqlite(databasePath);
|
||||||
|
const result = database
|
||||||
|
.prepare("update WorkOrderMilestones" +
|
||||||
|
" set workOrderMilestoneCompletionDate = ?," +
|
||||||
|
" workOrderMilestoneCompletionTime = ?," +
|
||||||
|
" recordUpdate_userName = ?," +
|
||||||
|
" recordUpdate_timeMillis = ?" +
|
||||||
|
" where workOrderMilestoneId = ?")
|
||||||
|
.run(milestoneForm.workOrderMilestoneCompletionDateString
|
||||||
|
? dateStringToInteger(milestoneForm.workOrderMilestoneCompletionDateString)
|
||||||
|
: dateToInteger(rightNow), milestoneForm.workOrderMilestoneCompletionTimeString
|
||||||
|
? timeStringToInteger(milestoneForm.workOrderMilestoneCompletionTimeString)
|
||||||
|
: dateToTimeInteger(rightNow), requestSession.user.userName, rightNow.getTime(), milestoneForm.workOrderMilestoneId);
|
||||||
|
database.close();
|
||||||
|
return result.changes > 0;
|
||||||
|
};
|
||||||
|
export default completeWorkOrderMilestone;
|
||||||
|
|
@ -0,0 +1,58 @@
|
||||||
|
import sqlite from "better-sqlite3";
|
||||||
|
|
||||||
|
import { lotOccupancyDB as databasePath } from "../../data/databasePaths.js";
|
||||||
|
|
||||||
|
import {
|
||||||
|
dateStringToInteger,
|
||||||
|
dateToInteger,
|
||||||
|
dateToTimeInteger,
|
||||||
|
timeStringToInteger
|
||||||
|
} from "@cityssm/expressjs-server-js/dateTimeFns.js";
|
||||||
|
|
||||||
|
import type * as recordTypes from "../../types/recordTypes";
|
||||||
|
|
||||||
|
interface CompleteWorkOrderMilestoneForm {
|
||||||
|
workOrderMilestoneId: string | number;
|
||||||
|
workOrderMilestoneCompletionDateString?: string;
|
||||||
|
workOrderMilestoneCompletionTimeString?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const completeWorkOrderMilestone = (
|
||||||
|
milestoneForm: CompleteWorkOrderMilestoneForm,
|
||||||
|
requestSession: recordTypes.PartialSession
|
||||||
|
): boolean => {
|
||||||
|
const rightNow = new Date();
|
||||||
|
|
||||||
|
const database = sqlite(databasePath);
|
||||||
|
|
||||||
|
const result = database
|
||||||
|
.prepare(
|
||||||
|
"update WorkOrderMilestones" +
|
||||||
|
" set workOrderMilestoneCompletionDate = ?," +
|
||||||
|
" workOrderMilestoneCompletionTime = ?," +
|
||||||
|
" recordUpdate_userName = ?," +
|
||||||
|
" recordUpdate_timeMillis = ?" +
|
||||||
|
" where workOrderMilestoneId = ?"
|
||||||
|
)
|
||||||
|
.run(
|
||||||
|
milestoneForm.workOrderMilestoneCompletionDateString
|
||||||
|
? dateStringToInteger(
|
||||||
|
milestoneForm.workOrderMilestoneCompletionDateString
|
||||||
|
)
|
||||||
|
: dateToInteger(rightNow),
|
||||||
|
milestoneForm.workOrderMilestoneCompletionTimeString
|
||||||
|
? timeStringToInteger(
|
||||||
|
milestoneForm.workOrderMilestoneCompletionTimeString
|
||||||
|
)
|
||||||
|
: dateToTimeInteger(rightNow),
|
||||||
|
requestSession.user.userName,
|
||||||
|
rightNow.getTime(),
|
||||||
|
milestoneForm.workOrderMilestoneId
|
||||||
|
);
|
||||||
|
|
||||||
|
database.close();
|
||||||
|
|
||||||
|
return result.changes > 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
export default completeWorkOrderMilestone;
|
||||||
|
|
@ -4,12 +4,14 @@ interface GetLotOccupanciesFilters {
|
||||||
lotId?: number | string;
|
lotId?: number | string;
|
||||||
occupancyTime?: "" | "past" | "current" | "future";
|
occupancyTime?: "" | "past" | "current" | "future";
|
||||||
occupancyStartDateString?: string;
|
occupancyStartDateString?: string;
|
||||||
|
occupancyEffectiveDateString?: string;
|
||||||
occupantName?: string;
|
occupantName?: string;
|
||||||
occupancyTypeId?: number | string;
|
occupancyTypeId?: number | string;
|
||||||
mapId?: number | string;
|
mapId?: number | string;
|
||||||
lotName?: string;
|
lotName?: string;
|
||||||
lotTypeId?: number | string;
|
lotTypeId?: number | string;
|
||||||
workOrderId?: number | string;
|
workOrderId?: number | string;
|
||||||
|
notWorkOrderId?: number | string;
|
||||||
}
|
}
|
||||||
interface GetLotOccupanciesOptions {
|
interface GetLotOccupanciesOptions {
|
||||||
limit: -1 | number;
|
limit: -1 | number;
|
||||||
|
|
|
||||||
|
|
@ -57,6 +57,11 @@ export const getLotOccupancies = (filters, options, connectedDatabase) => {
|
||||||
sqlWhereClause += " and o.occupancyStartDate = ?";
|
sqlWhereClause += " and o.occupancyStartDate = ?";
|
||||||
sqlParameters.push(dateStringToInteger(filters.occupancyStartDateString));
|
sqlParameters.push(dateStringToInteger(filters.occupancyStartDateString));
|
||||||
}
|
}
|
||||||
|
if (filters.occupancyEffectiveDateString) {
|
||||||
|
sqlWhereClause +=
|
||||||
|
" and (o.occupancyStartDate <= ? and (o.occupancyEndDate is null or o.occupancyEndDate >= ?))";
|
||||||
|
sqlParameters.push(dateStringToInteger(filters.occupancyEffectiveDateString), dateStringToInteger(filters.occupancyEffectiveDateString));
|
||||||
|
}
|
||||||
if (filters.mapId) {
|
if (filters.mapId) {
|
||||||
sqlWhereClause += " and l.mapId = ?";
|
sqlWhereClause += " and l.mapId = ?";
|
||||||
sqlParameters.push(filters.mapId);
|
sqlParameters.push(filters.mapId);
|
||||||
|
|
@ -70,6 +75,11 @@ export const getLotOccupancies = (filters, options, connectedDatabase) => {
|
||||||
" and o.lotOccupancyId in (select lotOccupancyId from WorkOrderLotOccupancies where recordDelete_timeMillis is null and workOrderId = ?)";
|
" and o.lotOccupancyId in (select lotOccupancyId from WorkOrderLotOccupancies where recordDelete_timeMillis is null and workOrderId = ?)";
|
||||||
sqlParameters.push(filters.workOrderId);
|
sqlParameters.push(filters.workOrderId);
|
||||||
}
|
}
|
||||||
|
if (filters.notWorkOrderId) {
|
||||||
|
sqlWhereClause +=
|
||||||
|
" and o.lotOccupancyId not in (select lotOccupancyId from WorkOrderLotOccupancies where recordDelete_timeMillis is null and workOrderId = ?)";
|
||||||
|
sqlParameters.push(filters.notWorkOrderId);
|
||||||
|
}
|
||||||
const count = database
|
const count = database
|
||||||
.prepare("select count(*) as recordCount" +
|
.prepare("select count(*) as recordCount" +
|
||||||
" from LotOccupancies o" +
|
" from LotOccupancies o" +
|
||||||
|
|
|
||||||
|
|
@ -16,12 +16,14 @@ interface GetLotOccupanciesFilters {
|
||||||
lotId?: number | string;
|
lotId?: number | string;
|
||||||
occupancyTime?: "" | "past" | "current" | "future";
|
occupancyTime?: "" | "past" | "current" | "future";
|
||||||
occupancyStartDateString?: string;
|
occupancyStartDateString?: string;
|
||||||
|
occupancyEffectiveDateString?: string;
|
||||||
occupantName?: string;
|
occupantName?: string;
|
||||||
occupancyTypeId?: number | string;
|
occupancyTypeId?: number | string;
|
||||||
mapId?: number | string;
|
mapId?: number | string;
|
||||||
lotName?: string;
|
lotName?: string;
|
||||||
lotTypeId?: number | string;
|
lotTypeId?: number | string;
|
||||||
workOrderId?: number | string;
|
workOrderId?: number | string;
|
||||||
|
notWorkOrderId?: number | string;
|
||||||
}
|
}
|
||||||
|
|
||||||
interface GetLotOccupanciesOptions {
|
interface GetLotOccupanciesOptions {
|
||||||
|
|
@ -107,6 +109,15 @@ export const getLotOccupancies = (
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (filters.occupancyEffectiveDateString) {
|
||||||
|
sqlWhereClause +=
|
||||||
|
" and (o.occupancyStartDate <= ? and (o.occupancyEndDate is null or o.occupancyEndDate >= ?))";
|
||||||
|
sqlParameters.push(
|
||||||
|
dateStringToInteger(filters.occupancyEffectiveDateString),
|
||||||
|
dateStringToInteger(filters.occupancyEffectiveDateString)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
if (filters.mapId) {
|
if (filters.mapId) {
|
||||||
sqlWhereClause += " and l.mapId = ?";
|
sqlWhereClause += " and l.mapId = ?";
|
||||||
sqlParameters.push(filters.mapId);
|
sqlParameters.push(filters.mapId);
|
||||||
|
|
@ -123,6 +134,12 @@ export const getLotOccupancies = (
|
||||||
sqlParameters.push(filters.workOrderId);
|
sqlParameters.push(filters.workOrderId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (filters.notWorkOrderId) {
|
||||||
|
sqlWhereClause +=
|
||||||
|
" and o.lotOccupancyId not in (select lotOccupancyId from WorkOrderLotOccupancies where recordDelete_timeMillis is null and workOrderId = ?)";
|
||||||
|
sqlParameters.push(filters.notWorkOrderId);
|
||||||
|
}
|
||||||
|
|
||||||
const count: number = database
|
const count: number = database
|
||||||
.prepare(
|
.prepare(
|
||||||
"select count(*) as recordCount" +
|
"select count(*) as recordCount" +
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,3 @@
|
||||||
|
import type * as recordTypes from "../../types/recordTypes";
|
||||||
|
export declare const reopenWorkOrderMilestone: (workOrderMilestoneId: number | string, requestSession: recordTypes.PartialSession) => boolean;
|
||||||
|
export default reopenWorkOrderMilestone;
|
||||||
|
|
@ -0,0 +1,18 @@
|
||||||
|
import sqlite from "better-sqlite3";
|
||||||
|
import { lotOccupancyDB as databasePath } from "../../data/databasePaths.js";
|
||||||
|
export const reopenWorkOrderMilestone = (workOrderMilestoneId, requestSession) => {
|
||||||
|
const database = sqlite(databasePath);
|
||||||
|
const rightNowMillis = Date.now();
|
||||||
|
const result = database
|
||||||
|
.prepare("update WorkOrderMilestones" +
|
||||||
|
" set workOrderMilestoneCompletionDate = null," +
|
||||||
|
" workOrderMilestoneCompletionTime = null," +
|
||||||
|
" recordUpdate_userName = ?," +
|
||||||
|
" recordUpdate_timeMillis = ?" +
|
||||||
|
" where workOrderMilestoneId = ?" +
|
||||||
|
" and workOrderMilestoneCompletionDate is not null")
|
||||||
|
.run(requestSession.user.userName, rightNowMillis, workOrderMilestoneId);
|
||||||
|
database.close();
|
||||||
|
return result.changes > 0;
|
||||||
|
};
|
||||||
|
export default reopenWorkOrderMilestone;
|
||||||
|
|
@ -0,0 +1,36 @@
|
||||||
|
import sqlite from "better-sqlite3";
|
||||||
|
|
||||||
|
import { lotOccupancyDB as databasePath } from "../../data/databasePaths.js";
|
||||||
|
|
||||||
|
import type * as recordTypes from "../../types/recordTypes";
|
||||||
|
|
||||||
|
export const reopenWorkOrderMilestone = (
|
||||||
|
workOrderMilestoneId: number | string,
|
||||||
|
requestSession: recordTypes.PartialSession
|
||||||
|
): boolean => {
|
||||||
|
const database = sqlite(databasePath);
|
||||||
|
|
||||||
|
const rightNowMillis = Date.now();
|
||||||
|
|
||||||
|
const result = database
|
||||||
|
.prepare(
|
||||||
|
"update WorkOrderMilestones" +
|
||||||
|
" set workOrderMilestoneCompletionDate = null," +
|
||||||
|
" workOrderMilestoneCompletionTime = null," +
|
||||||
|
" recordUpdate_userName = ?," +
|
||||||
|
" recordUpdate_timeMillis = ?" +
|
||||||
|
" where workOrderMilestoneId = ?" +
|
||||||
|
" and workOrderMilestoneCompletionDate is not null"
|
||||||
|
)
|
||||||
|
.run(
|
||||||
|
requestSession.user.userName,
|
||||||
|
rightNowMillis,
|
||||||
|
workOrderMilestoneId
|
||||||
|
);
|
||||||
|
|
||||||
|
database.close();
|
||||||
|
|
||||||
|
return result.changes > 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
export default reopenWorkOrderMilestone;
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
"use strict";
|
"use strict";
|
||||||
Object.defineProperty(exports, "__esModule", { value: true });
|
Object.defineProperty(exports, "__esModule", { value: true });
|
||||||
(() => {
|
(() => {
|
||||||
|
const los = exports.los;
|
||||||
const urlPrefix = document.querySelector("main").dataset.urlPrefix;
|
const urlPrefix = document.querySelector("main").dataset.urlPrefix;
|
||||||
const workOrderId = document.querySelector("#workOrderEdit--workOrderId").value;
|
const workOrderId = document.querySelector("#workOrderEdit--workOrderId").value;
|
||||||
const isCreate = workOrderId === "";
|
const isCreate = workOrderId === "";
|
||||||
|
|
@ -79,8 +80,56 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
const addLot = (lotId, callbackFunction) => {
|
||||||
|
cityssm.postJSON(urlPrefix + "/workOrders/doAddWorkOrderLot", {
|
||||||
|
workOrderId,
|
||||||
|
lotId
|
||||||
|
}, (responseJSON) => {
|
||||||
|
if (responseJSON.success) {
|
||||||
|
workOrderLots = responseJSON.workOrderLots;
|
||||||
|
renderRelatedLotsAndOccupancies();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
bulmaJS.alert({
|
||||||
|
title: "Error Adding " + exports.aliases.lot,
|
||||||
|
message: responseJSON.errorMessage,
|
||||||
|
contextualColorName: "danger"
|
||||||
|
});
|
||||||
|
}
|
||||||
|
if (callbackFunction) {
|
||||||
|
callbackFunction(responseJSON.success);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
const addLotOccupancy = (lotOccupancyId, callbackFunction) => {
|
||||||
|
cityssm.postJSON(urlPrefix + "/workOrders/doAddWorkOrderLotOccupancy", {
|
||||||
|
workOrderId,
|
||||||
|
lotOccupancyId
|
||||||
|
}, (responseJSON) => {
|
||||||
|
if (responseJSON.success) {
|
||||||
|
workOrderLotOccupancies =
|
||||||
|
responseJSON.workOrderLotOccupancies;
|
||||||
|
renderRelatedLotsAndOccupancies();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
bulmaJS.alert({
|
||||||
|
title: "Error Adding " + exports.aliases.occupancy,
|
||||||
|
message: responseJSON.errorMessage,
|
||||||
|
contextualColorName: "danger"
|
||||||
|
});
|
||||||
|
}
|
||||||
|
if (callbackFunction) {
|
||||||
|
callbackFunction(responseJSON.success);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
const addLotFromLotOccupancy = (clickEvent) => {
|
||||||
|
const lotId = clickEvent.currentTarget.dataset
|
||||||
|
.lotId;
|
||||||
|
addLot(lotId);
|
||||||
|
};
|
||||||
const renderRelatedOccupancies = () => {
|
const renderRelatedOccupancies = () => {
|
||||||
const occupanciesContainerElement = document.querySelector("#relatedTab--lotOccupancies");
|
const occupanciesContainerElement = document.querySelector("#container--lotOccupancies");
|
||||||
document.querySelector(".tabs a[href='#relatedTab--lotOccupancies'] .tag").textContent = workOrderLotOccupancies.length.toString();
|
document.querySelector(".tabs a[href='#relatedTab--lotOccupancies'] .tag").textContent = workOrderLotOccupancies.length.toString();
|
||||||
if (workOrderLotOccupancies.length === 0) {
|
if (workOrderLotOccupancies.length === 0) {
|
||||||
occupanciesContainerElement.innerHTML =
|
occupanciesContainerElement.innerHTML =
|
||||||
|
|
@ -114,6 +163,10 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
||||||
lotOccupancy.lotOccupancyId.toString();
|
lotOccupancy.lotOccupancyId.toString();
|
||||||
const isActive = !(lotOccupancy.occupancyEndDate &&
|
const isActive = !(lotOccupancy.occupancyEndDate &&
|
||||||
lotOccupancy.occupancyEndDateString < currentDateString);
|
lotOccupancy.occupancyEndDateString < currentDateString);
|
||||||
|
const hasLotRecord = lotOccupancy.lotId &&
|
||||||
|
workOrderLots.some((lot) => {
|
||||||
|
return lotOccupancy.lotId === lot.lotId;
|
||||||
|
});
|
||||||
rowElement.innerHTML =
|
rowElement.innerHTML =
|
||||||
'<td class="has-text-centered">' +
|
'<td class="has-text-centered">' +
|
||||||
(isActive
|
(isActive
|
||||||
|
|
@ -132,15 +185,36 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
||||||
'">' +
|
'">' +
|
||||||
cityssm.escapeHTML(lotOccupancy.occupancyType) +
|
cityssm.escapeHTML(lotOccupancy.occupancyType) +
|
||||||
"</a>" +
|
"</a>" +
|
||||||
"</td>") +
|
"</td>");
|
||||||
("<td>" +
|
if (lotOccupancy.lotId) {
|
||||||
(lotOccupancy.lotId
|
rowElement.insertAdjacentHTML("beforeend", "<td>" +
|
||||||
? cityssm.escapeHTML(lotOccupancy.lotName)
|
cityssm.escapeHTML(lotOccupancy.lotName) +
|
||||||
: '<span class="has-text-grey">(No ' +
|
(hasLotRecord
|
||||||
|
? ""
|
||||||
|
: ' <button class="button is-small is-light is-success button--addLot"' +
|
||||||
|
' data-lot-id="' +
|
||||||
|
lotOccupancy.lotId +
|
||||||
|
'"' +
|
||||||
|
' data-tooltip="Add ' +
|
||||||
|
cityssm.escapeHTML(exports.aliases.lot) +
|
||||||
|
'"' +
|
||||||
|
' aria-label="Add ' +
|
||||||
|
cityssm.escapeHTML(exports.aliases.lot) +
|
||||||
|
'" type="button">' +
|
||||||
|
'<i class="fas fa-plus" aria-hidden="true"></i>' +
|
||||||
|
"</button>") +
|
||||||
|
"</td>");
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
rowElement.insertAdjacentHTML("beforeend", "<td>" +
|
||||||
|
'<span class="has-text-grey">(No ' +
|
||||||
exports.aliases.lot +
|
exports.aliases.lot +
|
||||||
")</span>") +
|
")</span>" +
|
||||||
"</td>") +
|
"</td>");
|
||||||
("<td>" + lotOccupancy.occupancyStartDateString + "</td>") +
|
}
|
||||||
|
rowElement.insertAdjacentHTML("beforeend", "<td>" +
|
||||||
|
lotOccupancy.occupancyStartDateString +
|
||||||
|
"</td>" +
|
||||||
("<td>" +
|
("<td>" +
|
||||||
(lotOccupancy.occupancyEndDate
|
(lotOccupancy.occupancyEndDate
|
||||||
? lotOccupancy.occupancyEndDateString
|
? lotOccupancy.occupancyEndDateString
|
||||||
|
|
@ -155,7 +229,8 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
||||||
.occupantName) +
|
.occupantName) +
|
||||||
(lotOccupancy.lotOccupancyOccupants.length > 1
|
(lotOccupancy.lotOccupancyOccupants.length > 1
|
||||||
? " plus " +
|
? " plus " +
|
||||||
(lotOccupancy.lotOccupancyOccupants.length -
|
(lotOccupancy.lotOccupancyOccupants
|
||||||
|
.length -
|
||||||
1)
|
1)
|
||||||
: "")) +
|
: "")) +
|
||||||
"</td>") +
|
"</td>") +
|
||||||
|
|
@ -163,7 +238,12 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
||||||
'<button class="button is-small is-light is-danger button--deleteLotOccupancy" data-tooltip="Delete Relationship" type="button">' +
|
'<button class="button is-small is-light is-danger button--deleteLotOccupancy" data-tooltip="Delete Relationship" type="button">' +
|
||||||
'<i class="fas fa-trash" aria-hidden="true"></i>' +
|
'<i class="fas fa-trash" aria-hidden="true"></i>' +
|
||||||
"</button>" +
|
"</button>" +
|
||||||
"</td>");
|
"</td>"));
|
||||||
|
if (lotOccupancy.lotId && !hasLotRecord) {
|
||||||
|
rowElement
|
||||||
|
.querySelector(".button--addLot")
|
||||||
|
.addEventListener("click", addLotFromLotOccupancy);
|
||||||
|
}
|
||||||
rowElement
|
rowElement
|
||||||
.querySelector(".button--deleteLotOccupancy")
|
.querySelector(".button--deleteLotOccupancy")
|
||||||
.addEventListener("click", deleteLotOccupancy);
|
.addEventListener("click", deleteLotOccupancy);
|
||||||
|
|
@ -180,8 +260,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
||||||
lotId
|
lotId
|
||||||
}, (responseJSON) => {
|
}, (responseJSON) => {
|
||||||
if (responseJSON.success) {
|
if (responseJSON.success) {
|
||||||
workOrderLots =
|
workOrderLots = responseJSON.workOrderLots;
|
||||||
responseJSON.workOrderLots;
|
|
||||||
renderRelatedLotsAndOccupancies();
|
renderRelatedLotsAndOccupancies();
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
|
@ -212,7 +291,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
const renderRelatedLots = () => {
|
const renderRelatedLots = () => {
|
||||||
const lotsContainerElement = document.querySelector("#relatedTab--lots");
|
const lotsContainerElement = document.querySelector("#container--lots");
|
||||||
document.querySelector(".tabs a[href='#relatedTab--lots'] .tag").textContent = workOrderLots.length.toString();
|
document.querySelector(".tabs a[href='#relatedTab--lots'] .tag").textContent = workOrderLots.length.toString();
|
||||||
if (workOrderLots.length === 0) {
|
if (workOrderLots.length === 0) {
|
||||||
lotsContainerElement.innerHTML =
|
lotsContainerElement.innerHTML =
|
||||||
|
|
@ -269,5 +348,398 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
||||||
renderRelatedLots();
|
renderRelatedLots();
|
||||||
};
|
};
|
||||||
renderRelatedLotsAndOccupancies();
|
renderRelatedLotsAndOccupancies();
|
||||||
|
document
|
||||||
|
.querySelector("#button--addLotOccupancy")
|
||||||
|
.addEventListener("click", () => {
|
||||||
|
let searchFormElement;
|
||||||
|
let searchResultsContainerElement;
|
||||||
|
const doAddLotOccupancy = (clickEvent) => {
|
||||||
|
const rowElement = clickEvent.currentTarget.closest("tr");
|
||||||
|
const lotOccupancyId = rowElement.dataset.lotOccupancyId;
|
||||||
|
addLotOccupancy(lotOccupancyId, (success) => {
|
||||||
|
if (success) {
|
||||||
|
rowElement.remove();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
const doSearch = (event) => {
|
||||||
|
if (event) {
|
||||||
|
event.preventDefault();
|
||||||
|
}
|
||||||
|
searchResultsContainerElement.innerHTML =
|
||||||
|
'<p class="has-text-centered has-text-grey-dark">' +
|
||||||
|
'<i class="fas fa-5x fa-circle-notch fa-spin" aria-hidden="true"></i><br />' +
|
||||||
|
"Searching..." +
|
||||||
|
"</p>";
|
||||||
|
cityssm.postJSON(urlPrefix + "/lotOccupancies/doSearchLotOccupancies", searchFormElement, (responseJSON) => {
|
||||||
|
if (responseJSON.lotOccupancies.length === 0) {
|
||||||
|
searchResultsContainerElement.innerHTML =
|
||||||
|
'<div class="message is-info">' +
|
||||||
|
'<p class="message-body">There are no records that meet the search criteria.</p>' +
|
||||||
|
"</div>";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
searchResultsContainerElement.innerHTML =
|
||||||
|
'<table class="table is-fullwidth is-striped is-hoverable">' +
|
||||||
|
"<thead>" +
|
||||||
|
"<tr>" +
|
||||||
|
'<th class="has-width-1"></th>' +
|
||||||
|
("<th>" +
|
||||||
|
exports.aliases.occupancy +
|
||||||
|
" Type</th>") +
|
||||||
|
("<th>" + exports.aliases.lot + "</th>") +
|
||||||
|
"<th>Start Date</th>" +
|
||||||
|
"<th>End Date</th>" +
|
||||||
|
("<th>" + exports.aliases.occupants + "</th>") +
|
||||||
|
"</tr>" +
|
||||||
|
"</thead>" +
|
||||||
|
"<tbody></tbody>" +
|
||||||
|
"</table>";
|
||||||
|
for (const lotOccupancy of responseJSON.lotOccupancies) {
|
||||||
|
const rowElement = document.createElement("tr");
|
||||||
|
rowElement.className =
|
||||||
|
"container--lotOccupancy";
|
||||||
|
rowElement.dataset.lotOccupancyId =
|
||||||
|
lotOccupancy.lotOccupancyId.toString();
|
||||||
|
rowElement.innerHTML =
|
||||||
|
'<td class="has-text-centered">' +
|
||||||
|
'<button class="button is-small is-success button--addLotOccupancy" data-tooltip="Add" type="button" aria-label="Add">' +
|
||||||
|
'<i class="fas fa-plus" aria-hidden="true"></i>' +
|
||||||
|
"</button>" +
|
||||||
|
"</td>" +
|
||||||
|
('<td class="has-text-weight-bold">' +
|
||||||
|
cityssm.escapeHTML(lotOccupancy.occupancyType) +
|
||||||
|
"</td>");
|
||||||
|
if (lotOccupancy.lotId) {
|
||||||
|
rowElement.insertAdjacentHTML("beforeend", "<td>" +
|
||||||
|
cityssm.escapeHTML(lotOccupancy.lotName) +
|
||||||
|
"</td>");
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
rowElement.insertAdjacentHTML("beforeend", "<td>" +
|
||||||
|
'<span class="has-text-grey">(No ' +
|
||||||
|
exports.aliases.lot +
|
||||||
|
")</span>" +
|
||||||
|
"</td>");
|
||||||
|
}
|
||||||
|
rowElement.insertAdjacentHTML("beforeend", "<td>" +
|
||||||
|
lotOccupancy.occupancyStartDateString +
|
||||||
|
"</td>" +
|
||||||
|
("<td>" +
|
||||||
|
(lotOccupancy.occupancyEndDate
|
||||||
|
? lotOccupancy.occupancyEndDateString
|
||||||
|
: '<span class="has-text-grey">(No End Date)</span>') +
|
||||||
|
"</td>") +
|
||||||
|
("<td>" +
|
||||||
|
(lotOccupancy.lotOccupancyOccupants
|
||||||
|
.length === 0
|
||||||
|
? '<span class="has-text-grey">(No ' +
|
||||||
|
cityssm.escapeHTML(exports.aliases.occupants) +
|
||||||
|
")</span>"
|
||||||
|
: cityssm.escapeHTML(lotOccupancy
|
||||||
|
.lotOccupancyOccupants[0]
|
||||||
|
.occupantName) +
|
||||||
|
(lotOccupancy
|
||||||
|
.lotOccupancyOccupants
|
||||||
|
.length > 1
|
||||||
|
? " plus " +
|
||||||
|
(lotOccupancy
|
||||||
|
.lotOccupancyOccupants
|
||||||
|
.length -
|
||||||
|
1)
|
||||||
|
: "")) +
|
||||||
|
"</td>"));
|
||||||
|
rowElement
|
||||||
|
.querySelector(".button--addLotOccupancy")
|
||||||
|
.addEventListener("click", doAddLotOccupancy);
|
||||||
|
searchResultsContainerElement
|
||||||
|
.querySelector("tbody")
|
||||||
|
.append(rowElement);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
cityssm.openHtmlModal("workOrder-addLotOccupancy", {
|
||||||
|
onshow: (modalElement) => {
|
||||||
|
los.populateAliases(modalElement);
|
||||||
|
searchFormElement = modalElement.querySelector("form");
|
||||||
|
searchResultsContainerElement =
|
||||||
|
modalElement.querySelector("#resultsContainer--lotOccupancyAdd");
|
||||||
|
modalElement.querySelector("#lotOccupancySearch--notWorkOrderId").value = workOrderId;
|
||||||
|
modalElement.querySelector("#lotOccupancySearch--occupancyEffectiveDateString").value = document.querySelector("#workOrderEdit--workOrderOpenDateString").value;
|
||||||
|
doSearch();
|
||||||
|
},
|
||||||
|
onshown: (modalElement) => {
|
||||||
|
bulmaJS.toggleHtmlClipped();
|
||||||
|
modalElement
|
||||||
|
.querySelector("#lotOccupancySearch--occupantName")
|
||||||
|
.addEventListener("change", doSearch);
|
||||||
|
modalElement
|
||||||
|
.querySelector("#lotOccupancySearch--lotName")
|
||||||
|
.addEventListener("change", doSearch);
|
||||||
|
searchFormElement.addEventListener("submit", doSearch);
|
||||||
|
},
|
||||||
|
onremoved: () => {
|
||||||
|
bulmaJS.toggleHtmlClipped();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
document
|
||||||
|
.querySelector("#button--addLot")
|
||||||
|
.addEventListener("click", () => {
|
||||||
|
let searchFormElement;
|
||||||
|
let searchResultsContainerElement;
|
||||||
|
const doAddLot = (clickEvent) => {
|
||||||
|
const rowElement = clickEvent.currentTarget.closest("tr");
|
||||||
|
const lotId = rowElement.dataset.lotId;
|
||||||
|
addLot(lotId, (success) => {
|
||||||
|
if (success) {
|
||||||
|
rowElement.remove();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
const doSearch = (event) => {
|
||||||
|
if (event) {
|
||||||
|
event.preventDefault();
|
||||||
|
}
|
||||||
|
searchResultsContainerElement.innerHTML =
|
||||||
|
'<p class="has-text-centered has-text-grey-dark">' +
|
||||||
|
'<i class="fas fa-5x fa-circle-notch fa-spin" aria-hidden="true"></i><br />' +
|
||||||
|
"Searching..." +
|
||||||
|
"</p>";
|
||||||
|
cityssm.postJSON(urlPrefix + "/lots/doSearchLots", searchFormElement, (responseJSON) => {
|
||||||
|
if (responseJSON.lots.length === 0) {
|
||||||
|
searchResultsContainerElement.innerHTML =
|
||||||
|
'<div class="message is-info">' +
|
||||||
|
'<p class="message-body">There are no records that meet the search criteria.</p>' +
|
||||||
|
"</div>";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
searchResultsContainerElement.innerHTML =
|
||||||
|
'<table class="table is-fullwidth is-striped is-hoverable">' +
|
||||||
|
"<thead>" +
|
||||||
|
"<tr>" +
|
||||||
|
'<th class="has-width-1"></th>' +
|
||||||
|
("<th>" + exports.aliases.lot + "</th>") +
|
||||||
|
("<th>" + exports.aliases.map + "</th>") +
|
||||||
|
("<th>" + exports.aliases.lot + " Type</th>") +
|
||||||
|
"<th>Status</th>" +
|
||||||
|
"</tr>" +
|
||||||
|
"</thead>" +
|
||||||
|
"<tbody></tbody>" +
|
||||||
|
"</table>";
|
||||||
|
for (const lot of responseJSON.lots) {
|
||||||
|
const rowElement = document.createElement("tr");
|
||||||
|
rowElement.className = "container--lot";
|
||||||
|
rowElement.dataset.lotId = lot.lotId.toString();
|
||||||
|
rowElement.innerHTML =
|
||||||
|
'<td class="has-text-centered">' +
|
||||||
|
'<button class="button is-small is-success button--addLot" data-tooltip="Add" type="button" aria-label="Add">' +
|
||||||
|
'<i class="fas fa-plus" aria-hidden="true"></i>' +
|
||||||
|
"</button>" +
|
||||||
|
"</td>" +
|
||||||
|
('<td class="has-text-weight-bold">' +
|
||||||
|
cityssm.escapeHTML(lot.lotName) +
|
||||||
|
"</td>") +
|
||||||
|
"<td>" +
|
||||||
|
cityssm.escapeHTML(lot.mapName) +
|
||||||
|
"</td>" +
|
||||||
|
("<td>" +
|
||||||
|
cityssm.escapeHTML(lot.lotType) +
|
||||||
|
"</td>") +
|
||||||
|
("<td>" +
|
||||||
|
cityssm.escapeHTML(lot.lotStatus) +
|
||||||
|
"</td>");
|
||||||
|
rowElement
|
||||||
|
.querySelector(".button--addLot")
|
||||||
|
.addEventListener("click", doAddLot);
|
||||||
|
searchResultsContainerElement
|
||||||
|
.querySelector("tbody")
|
||||||
|
.append(rowElement);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
cityssm.openHtmlModal("workOrder-addLot", {
|
||||||
|
onshow: (modalElement) => {
|
||||||
|
los.populateAliases(modalElement);
|
||||||
|
searchFormElement = modalElement.querySelector("form");
|
||||||
|
searchResultsContainerElement =
|
||||||
|
modalElement.querySelector("#resultsContainer--lotAdd");
|
||||||
|
modalElement.querySelector("#lotSearch--notWorkOrderId").value = workOrderId;
|
||||||
|
const lotStatusElement = modalElement.querySelector("#lotSearch--lotStatusId");
|
||||||
|
for (const lotStatus of exports.lotStatuses) {
|
||||||
|
const optionElement = document.createElement("option");
|
||||||
|
optionElement.value =
|
||||||
|
lotStatus.lotStatusId.toString();
|
||||||
|
optionElement.textContent = lotStatus.lotStatus;
|
||||||
|
lotStatusElement.append(optionElement);
|
||||||
|
}
|
||||||
|
doSearch();
|
||||||
|
},
|
||||||
|
onshown: (modalElement) => {
|
||||||
|
bulmaJS.toggleHtmlClipped();
|
||||||
|
modalElement
|
||||||
|
.querySelector("#lotSearch--lotName")
|
||||||
|
.addEventListener("change", doSearch);
|
||||||
|
modalElement
|
||||||
|
.querySelector("#lotSearch--lotStatusId")
|
||||||
|
.addEventListener("change", doSearch);
|
||||||
|
searchFormElement.addEventListener("submit", doSearch);
|
||||||
|
},
|
||||||
|
onremoved: () => {
|
||||||
|
bulmaJS.toggleHtmlClipped();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
if (!isCreate) {
|
||||||
|
let workOrderMilestones = exports.workOrderMilestones;
|
||||||
|
delete exports.workOrderMilestones;
|
||||||
|
const completeMilestone = (clickEvent) => {
|
||||||
|
clickEvent.preventDefault();
|
||||||
|
const workOrderMilestoneId = clickEvent.currentTarget.closest(".container--milestone").dataset.workOrderMilestoneId;
|
||||||
|
const doComplete = () => {
|
||||||
|
cityssm.postJSON(urlPrefix + "/workOrders/doCompleteWorkOrderMilestone", {
|
||||||
|
workOrderId,
|
||||||
|
workOrderMilestoneId
|
||||||
|
}, (responseJSON) => {
|
||||||
|
if (responseJSON.success) {
|
||||||
|
workOrderMilestones = responseJSON.workOrderMilestones;
|
||||||
|
renderMilestones();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
bulmaJS.alert({
|
||||||
|
title: "Error Completing Milestone",
|
||||||
|
message: responseJSON.errorMessage,
|
||||||
|
contextualColorName: "danger"
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
bulmaJS.confirm({
|
||||||
|
title: "Complete Milestone",
|
||||||
|
message: "Are you sure you want to complete this milestone?",
|
||||||
|
contextualColorName: "warning",
|
||||||
|
okButton: {
|
||||||
|
text: "Yes, Complete Milestone",
|
||||||
|
callbackFunction: doComplete
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
const reopenMilestone = (clickEvent) => {
|
||||||
|
clickEvent.preventDefault();
|
||||||
|
const workOrderMilestoneId = clickEvent.currentTarget.closest(".container--milestone").dataset.workOrderMilestoneId;
|
||||||
|
const doReopen = () => {
|
||||||
|
cityssm.postJSON(urlPrefix + "/workOrders/doReopenWorkOrderMilestone", {
|
||||||
|
workOrderId,
|
||||||
|
workOrderMilestoneId
|
||||||
|
}, (responseJSON) => {
|
||||||
|
if (responseJSON.success) {
|
||||||
|
workOrderMilestones = responseJSON.workOrderMilestones;
|
||||||
|
renderMilestones();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
bulmaJS.alert({
|
||||||
|
title: "Error Reopening Milestone",
|
||||||
|
message: responseJSON.errorMessage,
|
||||||
|
contextualColorName: "danger"
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
bulmaJS.confirm({
|
||||||
|
title: "Reopen Milestone",
|
||||||
|
message: "Are you sure you want to remove the completion status from this milestone, and reopen it?",
|
||||||
|
contextualColorName: "warning",
|
||||||
|
okButton: {
|
||||||
|
text: "Yes, Reopen Milestone",
|
||||||
|
callbackFunction: doReopen
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
const deleteMilestone = (clickEvent) => {
|
||||||
|
clickEvent.preventDefault();
|
||||||
|
};
|
||||||
|
const renderMilestones = () => {
|
||||||
|
const milestonesPanelElement = document.querySelector("#panel--milestones");
|
||||||
|
const panelBlockElementsToDelete = milestonesPanelElement.querySelectorAll(".panel-block");
|
||||||
|
for (const panelBlockToDelete of panelBlockElementsToDelete) {
|
||||||
|
panelBlockToDelete.remove();
|
||||||
|
}
|
||||||
|
for (const milestone of workOrderMilestones) {
|
||||||
|
const panelBlockElement = document.createElement("div");
|
||||||
|
panelBlockElement.className =
|
||||||
|
"panel-block is-block container--milestone";
|
||||||
|
panelBlockElement.dataset.workOrderMilestoneId =
|
||||||
|
milestone.workOrderMilestoneId.toString();
|
||||||
|
panelBlockElement.innerHTML =
|
||||||
|
'<div class="columns">' +
|
||||||
|
('<div class="column is-narrow">' +
|
||||||
|
(milestone.workOrderMilestoneCompletionDate
|
||||||
|
? '<span class="button is-static" data-tooltip="Completed ' +
|
||||||
|
milestone.workOrderMilestoneCompletionDateString +
|
||||||
|
'" aria-label="Completed ' +
|
||||||
|
milestone.workOrderMilestoneCompletionDateString +
|
||||||
|
'">' +
|
||||||
|
'<span class="icon is-small"><i class="fas fa-check" aria-hidden="true"></i></span>' +
|
||||||
|
"</span>"
|
||||||
|
: '<button class="button button--completeMilestone" data-tooltip="Incomplete" type="button" aria-label="Incomplete">' +
|
||||||
|
'<span class="icon is-small"><i class="far fa-square" aria-hidden="true"></i></span>' +
|
||||||
|
"</button>") +
|
||||||
|
"</div>") +
|
||||||
|
('<div class="column">' +
|
||||||
|
(milestone.workOrderMilestoneTypeId
|
||||||
|
? "<strong>" +
|
||||||
|
cityssm.escapeHTML(milestone.workOrderMilestoneType) +
|
||||||
|
"</strong><br />"
|
||||||
|
: "") +
|
||||||
|
milestone.workOrderMilestoneDateString +
|
||||||
|
"<br />" +
|
||||||
|
'<span class="is-size-7">' +
|
||||||
|
cityssm.escapeHTML(milestone.workOrderMilestoneDescription) +
|
||||||
|
"</span>" +
|
||||||
|
"</div>") +
|
||||||
|
('<div class="column is-narrow">' +
|
||||||
|
'<div class="dropdown is-right">' +
|
||||||
|
('<div class="dropdown-trigger">' +
|
||||||
|
'<button class="button is-small" data-tooltip="Options" type="button" aria-label="Options">' +
|
||||||
|
'<i class="fas fa-ellipsis-v" aria-hidden="true"></i>' +
|
||||||
|
"</button>" +
|
||||||
|
"</div>") +
|
||||||
|
('<div class="dropdown-menu">' +
|
||||||
|
'<div class="dropdown-content">' +
|
||||||
|
(milestone.workOrderMilestoneCompletionDate
|
||||||
|
? '<a class="dropdown-item button--reopenMilestone" href="#">' +
|
||||||
|
'<span class="icon is-small"><i class="fas fa-times" aria-hidden="true"></i></span>' +
|
||||||
|
" <span>Reopen Milestone</span>" +
|
||||||
|
"</a>" +
|
||||||
|
'<hr class="dropdown-divider" />'
|
||||||
|
: "") +
|
||||||
|
'<a class="dropdown-item button--deleteMilestone" href="#">' +
|
||||||
|
'<span class="icon is-small"><i class="fas fa-trash has-text-danger" aria-hidden="true"></i></span>' +
|
||||||
|
" <span>Delete Milestone</span>" +
|
||||||
|
"</a>" +
|
||||||
|
"</div>" +
|
||||||
|
"</div>") +
|
||||||
|
"</div>" +
|
||||||
|
"</div>") +
|
||||||
|
"</div>";
|
||||||
|
if (milestone.workOrderMilestoneCompletionDate) {
|
||||||
|
panelBlockElement
|
||||||
|
.querySelector(".button--reopenMilestone")
|
||||||
|
.addEventListener("click", reopenMilestone);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
panelBlockElement
|
||||||
|
.querySelector(".button--completeMilestone")
|
||||||
|
.addEventListener("click", completeMilestone);
|
||||||
|
}
|
||||||
|
panelBlockElement
|
||||||
|
.querySelector(".button--deleteMilestone")
|
||||||
|
.addEventListener("click", deleteMilestone);
|
||||||
|
milestonesPanelElement.append(panelBlockElement);
|
||||||
|
}
|
||||||
|
bulmaJS.init(milestonesPanelElement);
|
||||||
|
};
|
||||||
|
renderMilestones();
|
||||||
}
|
}
|
||||||
})();
|
})();
|
||||||
|
|
|
||||||
|
|
@ -2,12 +2,17 @@
|
||||||
|
|
||||||
import type { cityssmGlobal } from "@cityssm/bulma-webapp-js/src/types";
|
import type { cityssmGlobal } from "@cityssm/bulma-webapp-js/src/types";
|
||||||
import type { BulmaJS } from "@cityssm/bulma-js/types";
|
import type { BulmaJS } from "@cityssm/bulma-js/types";
|
||||||
|
|
||||||
|
import type * as globalTypes from "../types/globalTypes";
|
||||||
import type * as recordTypes from "../types/recordTypes";
|
import type * as recordTypes from "../types/recordTypes";
|
||||||
|
import { response } from "express";
|
||||||
|
|
||||||
declare const cityssm: cityssmGlobal;
|
declare const cityssm: cityssmGlobal;
|
||||||
declare const bulmaJS: BulmaJS;
|
declare const bulmaJS: BulmaJS;
|
||||||
|
|
||||||
(() => {
|
(() => {
|
||||||
|
const los = exports.los as globalTypes.LOS;
|
||||||
|
|
||||||
const urlPrefix = document.querySelector("main").dataset.urlPrefix;
|
const urlPrefix = document.querySelector("main").dataset.urlPrefix;
|
||||||
|
|
||||||
const workOrderId = (
|
const workOrderId = (
|
||||||
|
|
@ -124,9 +129,82 @@ declare const bulmaJS: BulmaJS;
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const addLot = (
|
||||||
|
lotId: number | string,
|
||||||
|
callbackFunction?: (success?: boolean) => void
|
||||||
|
) => {
|
||||||
|
cityssm.postJSON(
|
||||||
|
urlPrefix + "/workOrders/doAddWorkOrderLot",
|
||||||
|
{
|
||||||
|
workOrderId,
|
||||||
|
lotId
|
||||||
|
},
|
||||||
|
(responseJSON: {
|
||||||
|
success: boolean;
|
||||||
|
errorMessage?: string;
|
||||||
|
workOrderLots?: recordTypes.Lot[];
|
||||||
|
}) => {
|
||||||
|
if (responseJSON.success) {
|
||||||
|
workOrderLots = responseJSON.workOrderLots;
|
||||||
|
renderRelatedLotsAndOccupancies();
|
||||||
|
} else {
|
||||||
|
bulmaJS.alert({
|
||||||
|
title: "Error Adding " + exports.aliases.lot,
|
||||||
|
message: responseJSON.errorMessage,
|
||||||
|
contextualColorName: "danger"
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
if (callbackFunction) {
|
||||||
|
callbackFunction(responseJSON.success);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
const addLotOccupancy = (
|
||||||
|
lotOccupancyId: number | string,
|
||||||
|
callbackFunction?: (success?: boolean) => void
|
||||||
|
) => {
|
||||||
|
cityssm.postJSON(
|
||||||
|
urlPrefix + "/workOrders/doAddWorkOrderLotOccupancy",
|
||||||
|
{
|
||||||
|
workOrderId,
|
||||||
|
lotOccupancyId
|
||||||
|
},
|
||||||
|
(responseJSON: {
|
||||||
|
success: boolean;
|
||||||
|
errorMessage?: string;
|
||||||
|
workOrderLotOccupancies?: recordTypes.LotOccupancy[];
|
||||||
|
}) => {
|
||||||
|
if (responseJSON.success) {
|
||||||
|
workOrderLotOccupancies =
|
||||||
|
responseJSON.workOrderLotOccupancies;
|
||||||
|
renderRelatedLotsAndOccupancies();
|
||||||
|
} else {
|
||||||
|
bulmaJS.alert({
|
||||||
|
title: "Error Adding " + exports.aliases.occupancy,
|
||||||
|
message: responseJSON.errorMessage,
|
||||||
|
contextualColorName: "danger"
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
if (callbackFunction) {
|
||||||
|
callbackFunction(responseJSON.success);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
const addLotFromLotOccupancy = (clickEvent: Event) => {
|
||||||
|
const lotId = (clickEvent.currentTarget as HTMLElement).dataset
|
||||||
|
.lotId;
|
||||||
|
addLot(lotId);
|
||||||
|
};
|
||||||
|
|
||||||
const renderRelatedOccupancies = () => {
|
const renderRelatedOccupancies = () => {
|
||||||
const occupanciesContainerElement = document.querySelector(
|
const occupanciesContainerElement = document.querySelector(
|
||||||
"#relatedTab--lotOccupancies"
|
"#container--lotOccupancies"
|
||||||
) as HTMLElement;
|
) as HTMLElement;
|
||||||
|
|
||||||
document.querySelector(
|
document.querySelector(
|
||||||
|
|
@ -173,6 +251,12 @@ declare const bulmaJS: BulmaJS;
|
||||||
lotOccupancy.occupancyEndDateString < currentDateString
|
lotOccupancy.occupancyEndDateString < currentDateString
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const hasLotRecord =
|
||||||
|
lotOccupancy.lotId &&
|
||||||
|
workOrderLots.some((lot) => {
|
||||||
|
return lotOccupancy.lotId === lot.lotId;
|
||||||
|
});
|
||||||
|
|
||||||
rowElement.innerHTML =
|
rowElement.innerHTML =
|
||||||
'<td class="has-text-centered">' +
|
'<td class="has-text-centered">' +
|
||||||
(isActive
|
(isActive
|
||||||
|
|
@ -191,15 +275,45 @@ declare const bulmaJS: BulmaJS;
|
||||||
'">' +
|
'">' +
|
||||||
cityssm.escapeHTML(lotOccupancy.occupancyType) +
|
cityssm.escapeHTML(lotOccupancy.occupancyType) +
|
||||||
"</a>" +
|
"</a>" +
|
||||||
"</td>") +
|
"</td>");
|
||||||
("<td>" +
|
|
||||||
(lotOccupancy.lotId
|
if (lotOccupancy.lotId) {
|
||||||
? cityssm.escapeHTML(lotOccupancy.lotName)
|
rowElement.insertAdjacentHTML(
|
||||||
: '<span class="has-text-grey">(No ' +
|
"beforeend",
|
||||||
|
"<td>" +
|
||||||
|
cityssm.escapeHTML(lotOccupancy.lotName) +
|
||||||
|
(hasLotRecord
|
||||||
|
? ""
|
||||||
|
: ' <button class="button is-small is-light is-success button--addLot"' +
|
||||||
|
' data-lot-id="' +
|
||||||
|
lotOccupancy.lotId +
|
||||||
|
'"' +
|
||||||
|
' data-tooltip="Add ' +
|
||||||
|
cityssm.escapeHTML(exports.aliases.lot) +
|
||||||
|
'"' +
|
||||||
|
' aria-label="Add ' +
|
||||||
|
cityssm.escapeHTML(exports.aliases.lot) +
|
||||||
|
'" type="button">' +
|
||||||
|
'<i class="fas fa-plus" aria-hidden="true"></i>' +
|
||||||
|
"</button>") +
|
||||||
|
"</td>"
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
rowElement.insertAdjacentHTML(
|
||||||
|
"beforeend",
|
||||||
|
"<td>" +
|
||||||
|
'<span class="has-text-grey">(No ' +
|
||||||
exports.aliases.lot +
|
exports.aliases.lot +
|
||||||
")</span>") +
|
")</span>" +
|
||||||
"</td>") +
|
"</td>"
|
||||||
("<td>" + lotOccupancy.occupancyStartDateString + "</td>") +
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
rowElement.insertAdjacentHTML(
|
||||||
|
"beforeend",
|
||||||
|
"<td>" +
|
||||||
|
lotOccupancy.occupancyStartDateString +
|
||||||
|
"</td>" +
|
||||||
("<td>" +
|
("<td>" +
|
||||||
(lotOccupancy.occupancyEndDate
|
(lotOccupancy.occupancyEndDate
|
||||||
? lotOccupancy.occupancyEndDateString
|
? lotOccupancy.occupancyEndDateString
|
||||||
|
|
@ -208,7 +322,9 @@ declare const bulmaJS: BulmaJS;
|
||||||
("<td>" +
|
("<td>" +
|
||||||
(lotOccupancy.lotOccupancyOccupants.length === 0
|
(lotOccupancy.lotOccupancyOccupants.length === 0
|
||||||
? '<span class="has-text-grey">(No ' +
|
? '<span class="has-text-grey">(No ' +
|
||||||
cityssm.escapeHTML(exports.aliases.occupants) +
|
cityssm.escapeHTML(
|
||||||
|
exports.aliases.occupants
|
||||||
|
) +
|
||||||
")</span>"
|
")</span>"
|
||||||
: cityssm.escapeHTML(
|
: cityssm.escapeHTML(
|
||||||
lotOccupancy.lotOccupancyOccupants[0]
|
lotOccupancy.lotOccupancyOccupants[0]
|
||||||
|
|
@ -216,7 +332,8 @@ declare const bulmaJS: BulmaJS;
|
||||||
) +
|
) +
|
||||||
(lotOccupancy.lotOccupancyOccupants.length > 1
|
(lotOccupancy.lotOccupancyOccupants.length > 1
|
||||||
? " plus " +
|
? " plus " +
|
||||||
(lotOccupancy.lotOccupancyOccupants.length -
|
(lotOccupancy.lotOccupancyOccupants
|
||||||
|
.length -
|
||||||
1)
|
1)
|
||||||
: "")) +
|
: "")) +
|
||||||
"</td>") +
|
"</td>") +
|
||||||
|
|
@ -224,7 +341,14 @@ declare const bulmaJS: BulmaJS;
|
||||||
'<button class="button is-small is-light is-danger button--deleteLotOccupancy" data-tooltip="Delete Relationship" type="button">' +
|
'<button class="button is-small is-light is-danger button--deleteLotOccupancy" data-tooltip="Delete Relationship" type="button">' +
|
||||||
'<i class="fas fa-trash" aria-hidden="true"></i>' +
|
'<i class="fas fa-trash" aria-hidden="true"></i>' +
|
||||||
"</button>" +
|
"</button>" +
|
||||||
"</td>");
|
"</td>")
|
||||||
|
);
|
||||||
|
|
||||||
|
if (lotOccupancy.lotId && !hasLotRecord) {
|
||||||
|
rowElement
|
||||||
|
.querySelector(".button--addLot")
|
||||||
|
.addEventListener("click", addLotFromLotOccupancy);
|
||||||
|
}
|
||||||
|
|
||||||
rowElement
|
rowElement
|
||||||
.querySelector(".button--deleteLotOccupancy")
|
.querySelector(".button--deleteLotOccupancy")
|
||||||
|
|
@ -256,8 +380,7 @@ declare const bulmaJS: BulmaJS;
|
||||||
workOrderLots?: recordTypes.Lot[];
|
workOrderLots?: recordTypes.Lot[];
|
||||||
}) => {
|
}) => {
|
||||||
if (responseJSON.success) {
|
if (responseJSON.success) {
|
||||||
workOrderLots =
|
workOrderLots = responseJSON.workOrderLots;
|
||||||
responseJSON.workOrderLots;
|
|
||||||
renderRelatedLotsAndOccupancies();
|
renderRelatedLotsAndOccupancies();
|
||||||
} else {
|
} else {
|
||||||
bulmaJS.alert({
|
bulmaJS.alert({
|
||||||
|
|
@ -293,7 +416,7 @@ declare const bulmaJS: BulmaJS;
|
||||||
|
|
||||||
const renderRelatedLots = () => {
|
const renderRelatedLots = () => {
|
||||||
const lotsContainerElement = document.querySelector(
|
const lotsContainerElement = document.querySelector(
|
||||||
"#relatedTab--lots"
|
"#container--lots"
|
||||||
) as HTMLElement;
|
) as HTMLElement;
|
||||||
|
|
||||||
document.querySelector(
|
document.querySelector(
|
||||||
|
|
@ -364,6 +487,348 @@ declare const bulmaJS: BulmaJS;
|
||||||
};
|
};
|
||||||
|
|
||||||
renderRelatedLotsAndOccupancies();
|
renderRelatedLotsAndOccupancies();
|
||||||
|
|
||||||
|
document
|
||||||
|
.querySelector("#button--addLotOccupancy")
|
||||||
|
.addEventListener("click", () => {
|
||||||
|
let searchFormElement: HTMLFormElement;
|
||||||
|
let searchResultsContainerElement: HTMLElement;
|
||||||
|
|
||||||
|
const doAddLotOccupancy = (clickEvent: Event) => {
|
||||||
|
const rowElement = (
|
||||||
|
clickEvent.currentTarget as HTMLElement
|
||||||
|
).closest("tr");
|
||||||
|
|
||||||
|
const lotOccupancyId = rowElement.dataset.lotOccupancyId;
|
||||||
|
|
||||||
|
addLotOccupancy(lotOccupancyId, (success) => {
|
||||||
|
if (success) {
|
||||||
|
rowElement.remove();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
const doSearch = (event?: Event) => {
|
||||||
|
if (event) {
|
||||||
|
event.preventDefault();
|
||||||
|
}
|
||||||
|
|
||||||
|
searchResultsContainerElement.innerHTML =
|
||||||
|
'<p class="has-text-centered has-text-grey-dark">' +
|
||||||
|
'<i class="fas fa-5x fa-circle-notch fa-spin" aria-hidden="true"></i><br />' +
|
||||||
|
"Searching..." +
|
||||||
|
"</p>";
|
||||||
|
|
||||||
|
cityssm.postJSON(
|
||||||
|
urlPrefix + "/lotOccupancies/doSearchLotOccupancies",
|
||||||
|
searchFormElement,
|
||||||
|
(responseJSON: {
|
||||||
|
lotOccupancies: recordTypes.LotOccupancy[];
|
||||||
|
}) => {
|
||||||
|
if (responseJSON.lotOccupancies.length === 0) {
|
||||||
|
searchResultsContainerElement.innerHTML =
|
||||||
|
'<div class="message is-info">' +
|
||||||
|
'<p class="message-body">There are no records that meet the search criteria.</p>' +
|
||||||
|
"</div>";
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
searchResultsContainerElement.innerHTML =
|
||||||
|
'<table class="table is-fullwidth is-striped is-hoverable">' +
|
||||||
|
"<thead>" +
|
||||||
|
"<tr>" +
|
||||||
|
'<th class="has-width-1"></th>' +
|
||||||
|
("<th>" +
|
||||||
|
exports.aliases.occupancy +
|
||||||
|
" Type</th>") +
|
||||||
|
("<th>" + exports.aliases.lot + "</th>") +
|
||||||
|
"<th>Start Date</th>" +
|
||||||
|
"<th>End Date</th>" +
|
||||||
|
("<th>" + exports.aliases.occupants + "</th>") +
|
||||||
|
"</tr>" +
|
||||||
|
"</thead>" +
|
||||||
|
"<tbody></tbody>" +
|
||||||
|
"</table>";
|
||||||
|
|
||||||
|
for (const lotOccupancy of responseJSON.lotOccupancies) {
|
||||||
|
const rowElement = document.createElement("tr");
|
||||||
|
rowElement.className =
|
||||||
|
"container--lotOccupancy";
|
||||||
|
rowElement.dataset.lotOccupancyId =
|
||||||
|
lotOccupancy.lotOccupancyId.toString();
|
||||||
|
|
||||||
|
rowElement.innerHTML =
|
||||||
|
'<td class="has-text-centered">' +
|
||||||
|
'<button class="button is-small is-success button--addLotOccupancy" data-tooltip="Add" type="button" aria-label="Add">' +
|
||||||
|
'<i class="fas fa-plus" aria-hidden="true"></i>' +
|
||||||
|
"</button>" +
|
||||||
|
"</td>" +
|
||||||
|
('<td class="has-text-weight-bold">' +
|
||||||
|
cityssm.escapeHTML(
|
||||||
|
lotOccupancy.occupancyType
|
||||||
|
) +
|
||||||
|
"</td>");
|
||||||
|
|
||||||
|
if (lotOccupancy.lotId) {
|
||||||
|
rowElement.insertAdjacentHTML(
|
||||||
|
"beforeend",
|
||||||
|
"<td>" +
|
||||||
|
cityssm.escapeHTML(
|
||||||
|
lotOccupancy.lotName
|
||||||
|
) +
|
||||||
|
"</td>"
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
rowElement.insertAdjacentHTML(
|
||||||
|
"beforeend",
|
||||||
|
"<td>" +
|
||||||
|
'<span class="has-text-grey">(No ' +
|
||||||
|
exports.aliases.lot +
|
||||||
|
")</span>" +
|
||||||
|
"</td>"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
rowElement.insertAdjacentHTML(
|
||||||
|
"beforeend",
|
||||||
|
"<td>" +
|
||||||
|
lotOccupancy.occupancyStartDateString +
|
||||||
|
"</td>" +
|
||||||
|
("<td>" +
|
||||||
|
(lotOccupancy.occupancyEndDate
|
||||||
|
? lotOccupancy.occupancyEndDateString
|
||||||
|
: '<span class="has-text-grey">(No End Date)</span>') +
|
||||||
|
"</td>") +
|
||||||
|
("<td>" +
|
||||||
|
(lotOccupancy.lotOccupancyOccupants
|
||||||
|
.length === 0
|
||||||
|
? '<span class="has-text-grey">(No ' +
|
||||||
|
cityssm.escapeHTML(
|
||||||
|
exports.aliases.occupants
|
||||||
|
) +
|
||||||
|
")</span>"
|
||||||
|
: cityssm.escapeHTML(
|
||||||
|
lotOccupancy
|
||||||
|
.lotOccupancyOccupants[0]
|
||||||
|
.occupantName
|
||||||
|
) +
|
||||||
|
(lotOccupancy
|
||||||
|
.lotOccupancyOccupants
|
||||||
|
.length > 1
|
||||||
|
? " plus " +
|
||||||
|
(lotOccupancy
|
||||||
|
.lotOccupancyOccupants
|
||||||
|
.length -
|
||||||
|
1)
|
||||||
|
: "")) +
|
||||||
|
"</td>")
|
||||||
|
);
|
||||||
|
|
||||||
|
rowElement
|
||||||
|
.querySelector(".button--addLotOccupancy")
|
||||||
|
.addEventListener(
|
||||||
|
"click",
|
||||||
|
doAddLotOccupancy
|
||||||
|
);
|
||||||
|
|
||||||
|
searchResultsContainerElement
|
||||||
|
.querySelector("tbody")
|
||||||
|
.append(rowElement);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
cityssm.openHtmlModal("workOrder-addLotOccupancy", {
|
||||||
|
onshow: (modalElement) => {
|
||||||
|
los.populateAliases(modalElement);
|
||||||
|
|
||||||
|
searchFormElement = modalElement.querySelector("form");
|
||||||
|
searchResultsContainerElement =
|
||||||
|
modalElement.querySelector(
|
||||||
|
"#resultsContainer--lotOccupancyAdd"
|
||||||
|
);
|
||||||
|
|
||||||
|
(
|
||||||
|
modalElement.querySelector(
|
||||||
|
"#lotOccupancySearch--notWorkOrderId"
|
||||||
|
) as HTMLInputElement
|
||||||
|
).value = workOrderId;
|
||||||
|
|
||||||
|
(
|
||||||
|
modalElement.querySelector(
|
||||||
|
"#lotOccupancySearch--occupancyEffectiveDateString"
|
||||||
|
) as HTMLInputElement
|
||||||
|
).value = (
|
||||||
|
document.querySelector(
|
||||||
|
"#workOrderEdit--workOrderOpenDateString"
|
||||||
|
) as HTMLInputElement
|
||||||
|
).value;
|
||||||
|
|
||||||
|
doSearch();
|
||||||
|
},
|
||||||
|
onshown: (modalElement) => {
|
||||||
|
bulmaJS.toggleHtmlClipped();
|
||||||
|
|
||||||
|
modalElement
|
||||||
|
.querySelector("#lotOccupancySearch--occupantName")
|
||||||
|
.addEventListener("change", doSearch);
|
||||||
|
modalElement
|
||||||
|
.querySelector("#lotOccupancySearch--lotName")
|
||||||
|
.addEventListener("change", doSearch);
|
||||||
|
|
||||||
|
searchFormElement.addEventListener("submit", doSearch);
|
||||||
|
},
|
||||||
|
onremoved: () => {
|
||||||
|
bulmaJS.toggleHtmlClipped();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
document
|
||||||
|
.querySelector("#button--addLot")
|
||||||
|
.addEventListener("click", () => {
|
||||||
|
let searchFormElement: HTMLFormElement;
|
||||||
|
let searchResultsContainerElement: HTMLElement;
|
||||||
|
|
||||||
|
const doAddLot = (clickEvent: Event) => {
|
||||||
|
const rowElement = (
|
||||||
|
clickEvent.currentTarget as HTMLElement
|
||||||
|
).closest("tr");
|
||||||
|
|
||||||
|
const lotId = rowElement.dataset.lotId;
|
||||||
|
|
||||||
|
addLot(lotId, (success) => {
|
||||||
|
if (success) {
|
||||||
|
rowElement.remove();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
const doSearch = (event?: Event) => {
|
||||||
|
if (event) {
|
||||||
|
event.preventDefault();
|
||||||
|
}
|
||||||
|
|
||||||
|
searchResultsContainerElement.innerHTML =
|
||||||
|
'<p class="has-text-centered has-text-grey-dark">' +
|
||||||
|
'<i class="fas fa-5x fa-circle-notch fa-spin" aria-hidden="true"></i><br />' +
|
||||||
|
"Searching..." +
|
||||||
|
"</p>";
|
||||||
|
|
||||||
|
cityssm.postJSON(
|
||||||
|
urlPrefix + "/lots/doSearchLots",
|
||||||
|
searchFormElement,
|
||||||
|
(responseJSON: { lots: recordTypes.Lot[] }) => {
|
||||||
|
if (responseJSON.lots.length === 0) {
|
||||||
|
searchResultsContainerElement.innerHTML =
|
||||||
|
'<div class="message is-info">' +
|
||||||
|
'<p class="message-body">There are no records that meet the search criteria.</p>' +
|
||||||
|
"</div>";
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
searchResultsContainerElement.innerHTML =
|
||||||
|
'<table class="table is-fullwidth is-striped is-hoverable">' +
|
||||||
|
"<thead>" +
|
||||||
|
"<tr>" +
|
||||||
|
'<th class="has-width-1"></th>' +
|
||||||
|
("<th>" + exports.aliases.lot + "</th>") +
|
||||||
|
("<th>" + exports.aliases.map + "</th>") +
|
||||||
|
("<th>" + exports.aliases.lot + " Type</th>") +
|
||||||
|
"<th>Status</th>" +
|
||||||
|
"</tr>" +
|
||||||
|
"</thead>" +
|
||||||
|
"<tbody></tbody>" +
|
||||||
|
"</table>";
|
||||||
|
|
||||||
|
for (const lot of responseJSON.lots) {
|
||||||
|
const rowElement = document.createElement("tr");
|
||||||
|
rowElement.className = "container--lot";
|
||||||
|
rowElement.dataset.lotId = lot.lotId.toString();
|
||||||
|
|
||||||
|
rowElement.innerHTML =
|
||||||
|
'<td class="has-text-centered">' +
|
||||||
|
'<button class="button is-small is-success button--addLot" data-tooltip="Add" type="button" aria-label="Add">' +
|
||||||
|
'<i class="fas fa-plus" aria-hidden="true"></i>' +
|
||||||
|
"</button>" +
|
||||||
|
"</td>" +
|
||||||
|
('<td class="has-text-weight-bold">' +
|
||||||
|
cityssm.escapeHTML(lot.lotName) +
|
||||||
|
"</td>") +
|
||||||
|
"<td>" +
|
||||||
|
cityssm.escapeHTML(lot.mapName) +
|
||||||
|
"</td>" +
|
||||||
|
("<td>" +
|
||||||
|
cityssm.escapeHTML(lot.lotType) +
|
||||||
|
"</td>") +
|
||||||
|
("<td>" +
|
||||||
|
cityssm.escapeHTML(lot.lotStatus) +
|
||||||
|
"</td>");
|
||||||
|
|
||||||
|
rowElement
|
||||||
|
.querySelector(".button--addLot")
|
||||||
|
.addEventListener("click", doAddLot);
|
||||||
|
|
||||||
|
searchResultsContainerElement
|
||||||
|
.querySelector("tbody")
|
||||||
|
.append(rowElement);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
cityssm.openHtmlModal("workOrder-addLot", {
|
||||||
|
onshow: (modalElement) => {
|
||||||
|
los.populateAliases(modalElement);
|
||||||
|
|
||||||
|
searchFormElement = modalElement.querySelector("form");
|
||||||
|
searchResultsContainerElement =
|
||||||
|
modalElement.querySelector(
|
||||||
|
"#resultsContainer--lotAdd"
|
||||||
|
);
|
||||||
|
|
||||||
|
(
|
||||||
|
modalElement.querySelector(
|
||||||
|
"#lotSearch--notWorkOrderId"
|
||||||
|
) as HTMLInputElement
|
||||||
|
).value = workOrderId;
|
||||||
|
|
||||||
|
const lotStatusElement = modalElement.querySelector(
|
||||||
|
"#lotSearch--lotStatusId"
|
||||||
|
) as HTMLSelectElement;
|
||||||
|
|
||||||
|
for (const lotStatus of exports.lotStatuses as recordTypes.LotStatus[]) {
|
||||||
|
const optionElement =
|
||||||
|
document.createElement("option");
|
||||||
|
optionElement.value =
|
||||||
|
lotStatus.lotStatusId.toString();
|
||||||
|
optionElement.textContent = lotStatus.lotStatus;
|
||||||
|
lotStatusElement.append(optionElement);
|
||||||
|
}
|
||||||
|
|
||||||
|
doSearch();
|
||||||
|
},
|
||||||
|
onshown: (modalElement) => {
|
||||||
|
bulmaJS.toggleHtmlClipped();
|
||||||
|
|
||||||
|
modalElement
|
||||||
|
.querySelector("#lotSearch--lotName")
|
||||||
|
.addEventListener("change", doSearch);
|
||||||
|
|
||||||
|
modalElement
|
||||||
|
.querySelector("#lotSearch--lotStatusId")
|
||||||
|
.addEventListener("change", doSearch);
|
||||||
|
|
||||||
|
searchFormElement.addEventListener("submit", doSearch);
|
||||||
|
},
|
||||||
|
onremoved: () => {
|
||||||
|
bulmaJS.toggleHtmlClipped();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
@ -373,4 +838,193 @@ declare const bulmaJS: BulmaJS;
|
||||||
/*
|
/*
|
||||||
* Milestones
|
* Milestones
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
if (!isCreate) {
|
||||||
|
let workOrderMilestones =
|
||||||
|
exports.workOrderMilestones as recordTypes.WorkOrderMilestone[];
|
||||||
|
delete exports.workOrderMilestones;
|
||||||
|
|
||||||
|
const completeMilestone = (clickEvent: Event) => {
|
||||||
|
clickEvent.preventDefault();
|
||||||
|
|
||||||
|
const workOrderMilestoneId = (
|
||||||
|
(clickEvent.currentTarget as HTMLElement).closest(
|
||||||
|
".container--milestone"
|
||||||
|
) as HTMLElement
|
||||||
|
).dataset.workOrderMilestoneId;
|
||||||
|
|
||||||
|
const doComplete = () => {
|
||||||
|
cityssm.postJSON(urlPrefix + "/workOrders/doCompleteWorkOrderMilestone", {
|
||||||
|
workOrderId,
|
||||||
|
workOrderMilestoneId
|
||||||
|
},
|
||||||
|
(responseJSON: {success: boolean; errorMessage?: string; workOrderMilestones?: recordTypes.WorkOrderMilestone[];}) => {
|
||||||
|
if (responseJSON.success) {
|
||||||
|
workOrderMilestones = responseJSON.workOrderMilestones;
|
||||||
|
renderMilestones();
|
||||||
|
} else {
|
||||||
|
bulmaJS.alert({
|
||||||
|
title: "Error Completing Milestone",
|
||||||
|
message: responseJSON.errorMessage,
|
||||||
|
contextualColorName: "danger"
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
bulmaJS.confirm({
|
||||||
|
title: "Complete Milestone",
|
||||||
|
message: "Are you sure you want to complete this milestone?",
|
||||||
|
contextualColorName: "warning",
|
||||||
|
okButton: {
|
||||||
|
text: "Yes, Complete Milestone",
|
||||||
|
callbackFunction: doComplete
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
const reopenMilestone = (clickEvent: Event) => {
|
||||||
|
clickEvent.preventDefault();
|
||||||
|
|
||||||
|
const workOrderMilestoneId = (
|
||||||
|
(clickEvent.currentTarget as HTMLElement).closest(
|
||||||
|
".container--milestone"
|
||||||
|
) as HTMLElement
|
||||||
|
).dataset.workOrderMilestoneId;
|
||||||
|
|
||||||
|
const doReopen = () => {
|
||||||
|
cityssm.postJSON(urlPrefix + "/workOrders/doReopenWorkOrderMilestone", {
|
||||||
|
workOrderId,
|
||||||
|
workOrderMilestoneId
|
||||||
|
},
|
||||||
|
(responseJSON: {success: boolean; errorMessage?: string; workOrderMilestones?: recordTypes.WorkOrderMilestone[];}) => {
|
||||||
|
if (responseJSON.success) {
|
||||||
|
workOrderMilestones = responseJSON.workOrderMilestones;
|
||||||
|
renderMilestones();
|
||||||
|
} else {
|
||||||
|
bulmaJS.alert({
|
||||||
|
title: "Error Reopening Milestone",
|
||||||
|
message: responseJSON.errorMessage,
|
||||||
|
contextualColorName: "danger"
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
bulmaJS.confirm({
|
||||||
|
title: "Reopen Milestone",
|
||||||
|
message: "Are you sure you want to remove the completion status from this milestone, and reopen it?",
|
||||||
|
contextualColorName: "warning",
|
||||||
|
okButton: {
|
||||||
|
text: "Yes, Reopen Milestone",
|
||||||
|
callbackFunction: doReopen
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
const deleteMilestone = (clickEvent: Event) => {
|
||||||
|
clickEvent.preventDefault();
|
||||||
|
};
|
||||||
|
|
||||||
|
const renderMilestones = () => {
|
||||||
|
// Clear milestones panel
|
||||||
|
|
||||||
|
const milestonesPanelElement = document.querySelector(
|
||||||
|
"#panel--milestones"
|
||||||
|
) as HTMLElement;
|
||||||
|
|
||||||
|
const panelBlockElementsToDelete =
|
||||||
|
milestonesPanelElement.querySelectorAll(".panel-block");
|
||||||
|
|
||||||
|
for (const panelBlockToDelete of panelBlockElementsToDelete) {
|
||||||
|
panelBlockToDelete.remove();
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const milestone of workOrderMilestones) {
|
||||||
|
const panelBlockElement = document.createElement("div");
|
||||||
|
panelBlockElement.className =
|
||||||
|
"panel-block is-block container--milestone";
|
||||||
|
|
||||||
|
panelBlockElement.dataset.workOrderMilestoneId =
|
||||||
|
milestone.workOrderMilestoneId.toString();
|
||||||
|
|
||||||
|
panelBlockElement.innerHTML =
|
||||||
|
'<div class="columns">' +
|
||||||
|
('<div class="column is-narrow">' +
|
||||||
|
(milestone.workOrderMilestoneCompletionDate
|
||||||
|
? '<span class="button is-static" data-tooltip="Completed ' +
|
||||||
|
milestone.workOrderMilestoneCompletionDateString +
|
||||||
|
'" aria-label="Completed ' +
|
||||||
|
milestone.workOrderMilestoneCompletionDateString +
|
||||||
|
'">' +
|
||||||
|
'<span class="icon is-small"><i class="fas fa-check" aria-hidden="true"></i></span>' +
|
||||||
|
"</span>"
|
||||||
|
: '<button class="button button--completeMilestone" data-tooltip="Incomplete" type="button" aria-label="Incomplete">' +
|
||||||
|
'<span class="icon is-small"><i class="far fa-square" aria-hidden="true"></i></span>' +
|
||||||
|
"</button>") +
|
||||||
|
"</div>") +
|
||||||
|
('<div class="column">' +
|
||||||
|
(milestone.workOrderMilestoneTypeId
|
||||||
|
? "<strong>" +
|
||||||
|
cityssm.escapeHTML(
|
||||||
|
milestone.workOrderMilestoneType
|
||||||
|
) +
|
||||||
|
"</strong><br />"
|
||||||
|
: "") +
|
||||||
|
milestone.workOrderMilestoneDateString +
|
||||||
|
"<br />" +
|
||||||
|
'<span class="is-size-7">' +
|
||||||
|
cityssm.escapeHTML(
|
||||||
|
milestone.workOrderMilestoneDescription
|
||||||
|
) +
|
||||||
|
"</span>" +
|
||||||
|
"</div>") +
|
||||||
|
('<div class="column is-narrow">' +
|
||||||
|
'<div class="dropdown is-right">' +
|
||||||
|
('<div class="dropdown-trigger">' +
|
||||||
|
'<button class="button is-small" data-tooltip="Options" type="button" aria-label="Options">' +
|
||||||
|
'<i class="fas fa-ellipsis-v" aria-hidden="true"></i>' +
|
||||||
|
"</button>" +
|
||||||
|
"</div>") +
|
||||||
|
('<div class="dropdown-menu">' +
|
||||||
|
'<div class="dropdown-content">' +
|
||||||
|
(milestone.workOrderMilestoneCompletionDate
|
||||||
|
? '<a class="dropdown-item button--reopenMilestone" href="#">' +
|
||||||
|
'<span class="icon is-small"><i class="fas fa-times" aria-hidden="true"></i></span>' +
|
||||||
|
" <span>Reopen Milestone</span>" +
|
||||||
|
"</a>" +
|
||||||
|
'<hr class="dropdown-divider" />'
|
||||||
|
: "") +
|
||||||
|
'<a class="dropdown-item button--deleteMilestone" href="#">' +
|
||||||
|
'<span class="icon is-small"><i class="fas fa-trash has-text-danger" aria-hidden="true"></i></span>' +
|
||||||
|
" <span>Delete Milestone</span>" +
|
||||||
|
"</a>" +
|
||||||
|
"</div>" +
|
||||||
|
"</div>") +
|
||||||
|
"</div>" +
|
||||||
|
"</div>") +
|
||||||
|
"</div>";
|
||||||
|
|
||||||
|
if (milestone.workOrderMilestoneCompletionDate) {
|
||||||
|
panelBlockElement
|
||||||
|
.querySelector(".button--reopenMilestone")
|
||||||
|
.addEventListener("click", reopenMilestone);
|
||||||
|
} else {
|
||||||
|
panelBlockElement
|
||||||
|
.querySelector(".button--completeMilestone")
|
||||||
|
.addEventListener("click", completeMilestone);
|
||||||
|
}
|
||||||
|
|
||||||
|
panelBlockElement
|
||||||
|
.querySelector(".button--deleteMilestone")
|
||||||
|
.addEventListener("click", deleteMilestone);
|
||||||
|
|
||||||
|
milestonesPanelElement.append(panelBlockElement);
|
||||||
|
}
|
||||||
|
|
||||||
|
bulmaJS.init(milestonesPanelElement);
|
||||||
|
};
|
||||||
|
|
||||||
|
renderMilestones();
|
||||||
|
}
|
||||||
})();
|
})();
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,56 @@
|
||||||
|
<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 Related <span class="alias" data-alias="Lot"></span> to Work Order
|
||||||
|
</h3>
|
||||||
|
<button class="delete is-close-modal-button" aria-label="close" type="button"></button>
|
||||||
|
</header>
|
||||||
|
<section class="modal-card-body">
|
||||||
|
<div class="box">
|
||||||
|
<form id="form--lotSearch">
|
||||||
|
<input name="limit" type="hidden" value="100" />
|
||||||
|
<input name="offset" type="hidden" value="0" />
|
||||||
|
<input id="lotSearch--notWorkOrderId" name="notWorkOrderId" type="hidden" value="" />
|
||||||
|
|
||||||
|
<div class="columns">
|
||||||
|
<div class="column">
|
||||||
|
<div class="field">
|
||||||
|
<label class="label" for="lotSearch--lotName">
|
||||||
|
<span class="alias" data-alias="Lot"></span>
|
||||||
|
Name
|
||||||
|
</label>
|
||||||
|
<div class="control has-icons-left">
|
||||||
|
<input class="input" id="lotSearch--lotName" name="lotName" type="text" />
|
||||||
|
<span class="icon is-small is-left">
|
||||||
|
<i class="fas fa-search" aria-hidden="true"></i>
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="column">
|
||||||
|
<div class="field">
|
||||||
|
<label class="label" for="lotSearch--lotStatusId">Status</label>
|
||||||
|
<div class="control has-icons-left">
|
||||||
|
<div class="select is-fullwidth">
|
||||||
|
<select id="lotSearch--lotStatusId" name="lotStatusId">
|
||||||
|
<option value="">(All Statuses)</option>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
<span class="icon is-small is-left">
|
||||||
|
<i class="fas fa-search" aria-hidden="true"></i>
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
<div id="resultsContainer--lotAdd"></div>
|
||||||
|
</section>
|
||||||
|
<footer class="modal-card-foot justify-right">
|
||||||
|
<button class="button is-close-modal-button" type="button">Close</button>
|
||||||
|
</footer>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
@ -0,0 +1,55 @@
|
||||||
|
<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 Related <span class="alias" data-alias="Occupancy"></span> to Work Order
|
||||||
|
</h3>
|
||||||
|
<button class="delete is-close-modal-button" aria-label="close" type="button"></button>
|
||||||
|
</header>
|
||||||
|
<section class="modal-card-body">
|
||||||
|
<div class="box">
|
||||||
|
<form id="form--lotOccupancySearch">
|
||||||
|
<input name="limit" type="hidden" value="100" />
|
||||||
|
<input name="offset" type="hidden" value="0" />
|
||||||
|
<input id="lotOccupancySearch--notWorkOrderId" name="notWorkOrderId" type="hidden" value="" />
|
||||||
|
<input id="lotOccupancySearch--occupancyEffectiveDateString" name="occupancyEffectiveDateString" type="hidden" value="" />
|
||||||
|
<div class="columns">
|
||||||
|
<div class="column">
|
||||||
|
<div class="field">
|
||||||
|
<label class="label" for="lotOccupancySearch--occupantName">
|
||||||
|
<span class="alias" data-alias="Occupant"></span>
|
||||||
|
Name
|
||||||
|
</label>
|
||||||
|
<div class="control has-icons-left">
|
||||||
|
<input class="input" id="lotOccupancySearch--occupantName" name="occupantName" type="text" />
|
||||||
|
<span class="icon is-small is-left">
|
||||||
|
<i class="fas fa-search" aria-hidden="true"></i>
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="column">
|
||||||
|
<div class="field">
|
||||||
|
<label class="label" for="lotOccupancySearch--lotName">
|
||||||
|
<span class="alias" data-alias="Lot"></span>
|
||||||
|
Name
|
||||||
|
</label>
|
||||||
|
<div class="control has-icons-left">
|
||||||
|
<input class="input" id="lotOccupancySearch--lotName" name="lotName" type="text" />
|
||||||
|
<span class="icon is-small is-left">
|
||||||
|
<i class="fas fa-search" aria-hidden="true"></i>
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
<div id="resultsContainer--lotOccupancyAdd"></div>
|
||||||
|
</section>
|
||||||
|
<footer class="modal-card-foot justify-right">
|
||||||
|
<button class="button is-close-modal-button" type="button">Close</button>
|
||||||
|
</footer>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
File diff suppressed because one or more lines are too long
|
|
@ -6,8 +6,12 @@ import handler_view from "../handlers/workOrders-get/view.js";
|
||||||
import handler_doReopenWorkOrder from "../handlers/workOrders-post/doReopenWorkOrder.js";
|
import handler_doReopenWorkOrder from "../handlers/workOrders-post/doReopenWorkOrder.js";
|
||||||
import handler_edit from "../handlers/workOrders-get/edit.js";
|
import handler_edit from "../handlers/workOrders-get/edit.js";
|
||||||
import handler_doUpdateWorkOrder from "../handlers/workOrders-post/doUpdateWorkOrder.js";
|
import handler_doUpdateWorkOrder from "../handlers/workOrders-post/doUpdateWorkOrder.js";
|
||||||
|
import handler_doAddWorkOrderLotOccupancy from "../handlers/workOrders-post/doAddWorkOrderLotOccupancy.js";
|
||||||
import handler_doDeleteWorkOrderLotOccupancy from "../handlers/workOrders-post/doDeleteWorkOrderLotOccupancy.js";
|
import handler_doDeleteWorkOrderLotOccupancy from "../handlers/workOrders-post/doDeleteWorkOrderLotOccupancy.js";
|
||||||
|
import handler_doAddWorkOrderLot from "../handlers/workOrders-post/doAddWorkOrderLot.js";
|
||||||
import handler_doDeleteWorkOrderLot from "../handlers/workOrders-post/doDeleteWorkOrderLot.js";
|
import handler_doDeleteWorkOrderLot from "../handlers/workOrders-post/doDeleteWorkOrderLot.js";
|
||||||
|
import handler_doCompleteWorkOrderMilestone from "../handlers/workOrders-post/doCompleteWorkOrderMilestone.js";
|
||||||
|
import handler_doReopenWorkOrderMilestone from "../handlers/workOrders-post/doReopenWorkOrderMilestone.js";
|
||||||
export const router = Router();
|
export const router = Router();
|
||||||
router.get("/", handler_search);
|
router.get("/", handler_search);
|
||||||
router.post("/doSearchWorkOrders", handler_doSearchWorkOrders);
|
router.post("/doSearchWorkOrders", handler_doSearchWorkOrders);
|
||||||
|
|
@ -15,6 +19,10 @@ router.get("/:workOrderId", handler_view);
|
||||||
router.post("/doReopenWorkOrder", permissionHandlers.updatePostHandler, handler_doReopenWorkOrder);
|
router.post("/doReopenWorkOrder", permissionHandlers.updatePostHandler, handler_doReopenWorkOrder);
|
||||||
router.get("/:workOrderId/edit", permissionHandlers.updateGetHandler, handler_edit);
|
router.get("/:workOrderId/edit", permissionHandlers.updateGetHandler, handler_edit);
|
||||||
router.post("/doUpdateWorkOrder", permissionHandlers.updatePostHandler, handler_doUpdateWorkOrder);
|
router.post("/doUpdateWorkOrder", permissionHandlers.updatePostHandler, handler_doUpdateWorkOrder);
|
||||||
|
router.post("/doAddWorkOrderLotOccupancy", permissionHandlers.updatePostHandler, handler_doAddWorkOrderLotOccupancy);
|
||||||
router.post("/doDeleteWorkOrderLotOccupancy", permissionHandlers.updatePostHandler, handler_doDeleteWorkOrderLotOccupancy);
|
router.post("/doDeleteWorkOrderLotOccupancy", permissionHandlers.updatePostHandler, handler_doDeleteWorkOrderLotOccupancy);
|
||||||
|
router.post("/doAddWorkOrderLot", permissionHandlers.updatePostHandler, handler_doAddWorkOrderLot);
|
||||||
router.post("/doDeleteWorkOrderLot", permissionHandlers.updatePostHandler, handler_doDeleteWorkOrderLot);
|
router.post("/doDeleteWorkOrderLot", permissionHandlers.updatePostHandler, handler_doDeleteWorkOrderLot);
|
||||||
|
router.post("/doCompleteWorkOrderMilestone", permissionHandlers.updatePostHandler, handler_doCompleteWorkOrderMilestone);
|
||||||
|
router.post("/doReopenWorkOrderMilestone", permissionHandlers.updatePostHandler, handler_doReopenWorkOrderMilestone);
|
||||||
export default router;
|
export default router;
|
||||||
|
|
|
||||||
|
|
@ -10,9 +10,16 @@ import handler_doReopenWorkOrder from "../handlers/workOrders-post/doReopenWorkO
|
||||||
|
|
||||||
import handler_edit from "../handlers/workOrders-get/edit.js";
|
import handler_edit from "../handlers/workOrders-get/edit.js";
|
||||||
import handler_doUpdateWorkOrder from "../handlers/workOrders-post/doUpdateWorkOrder.js";
|
import handler_doUpdateWorkOrder from "../handlers/workOrders-post/doUpdateWorkOrder.js";
|
||||||
|
|
||||||
|
import handler_doAddWorkOrderLotOccupancy from "../handlers/workOrders-post/doAddWorkOrderLotOccupancy.js";
|
||||||
import handler_doDeleteWorkOrderLotOccupancy from "../handlers/workOrders-post/doDeleteWorkOrderLotOccupancy.js";
|
import handler_doDeleteWorkOrderLotOccupancy from "../handlers/workOrders-post/doDeleteWorkOrderLotOccupancy.js";
|
||||||
|
|
||||||
|
import handler_doAddWorkOrderLot from "../handlers/workOrders-post/doAddWorkOrderLot.js";
|
||||||
import handler_doDeleteWorkOrderLot from "../handlers/workOrders-post/doDeleteWorkOrderLot.js";
|
import handler_doDeleteWorkOrderLot from "../handlers/workOrders-post/doDeleteWorkOrderLot.js";
|
||||||
|
|
||||||
|
import handler_doCompleteWorkOrderMilestone from "../handlers/workOrders-post/doCompleteWorkOrderMilestone.js";
|
||||||
|
import handler_doReopenWorkOrderMilestone from "../handlers/workOrders-post/doReopenWorkOrderMilestone.js";
|
||||||
|
|
||||||
export const router = Router();
|
export const router = Router();
|
||||||
|
|
||||||
router.get("/", handler_search);
|
router.get("/", handler_search);
|
||||||
|
|
@ -39,16 +46,40 @@ router.post(
|
||||||
handler_doUpdateWorkOrder
|
handler_doUpdateWorkOrder
|
||||||
);
|
);
|
||||||
|
|
||||||
|
router.post(
|
||||||
|
"/doAddWorkOrderLotOccupancy",
|
||||||
|
permissionHandlers.updatePostHandler,
|
||||||
|
handler_doAddWorkOrderLotOccupancy
|
||||||
|
);
|
||||||
|
|
||||||
router.post(
|
router.post(
|
||||||
"/doDeleteWorkOrderLotOccupancy",
|
"/doDeleteWorkOrderLotOccupancy",
|
||||||
permissionHandlers.updatePostHandler,
|
permissionHandlers.updatePostHandler,
|
||||||
handler_doDeleteWorkOrderLotOccupancy
|
handler_doDeleteWorkOrderLotOccupancy
|
||||||
);
|
);
|
||||||
|
|
||||||
|
router.post(
|
||||||
|
"/doAddWorkOrderLot",
|
||||||
|
permissionHandlers.updatePostHandler,
|
||||||
|
handler_doAddWorkOrderLot
|
||||||
|
);
|
||||||
|
|
||||||
router.post(
|
router.post(
|
||||||
"/doDeleteWorkOrderLot",
|
"/doDeleteWorkOrderLot",
|
||||||
permissionHandlers.updatePostHandler,
|
permissionHandlers.updatePostHandler,
|
||||||
handler_doDeleteWorkOrderLot
|
handler_doDeleteWorkOrderLot
|
||||||
);
|
);
|
||||||
|
|
||||||
|
router.post(
|
||||||
|
"/doCompleteWorkOrderMilestone",
|
||||||
|
permissionHandlers.updatePostHandler,
|
||||||
|
handler_doCompleteWorkOrderMilestone
|
||||||
|
);
|
||||||
|
|
||||||
|
router.post(
|
||||||
|
"/doReopenWorkOrderMilestone",
|
||||||
|
permissionHandlers.updatePostHandler,
|
||||||
|
handler_doReopenWorkOrderMilestone
|
||||||
|
);
|
||||||
|
|
||||||
export default router;
|
export default router;
|
||||||
|
|
|
||||||
|
|
@ -38,7 +38,9 @@
|
||||||
<% } %>
|
<% } %>
|
||||||
</h1>
|
</h1>
|
||||||
|
|
||||||
<form id="form--workOrderEdit">
|
<div class="columns">
|
||||||
|
<div class="column">
|
||||||
|
<form id="form--workOrderEdit">
|
||||||
<input id="workOrderEdit--workOrderId" name="workOrderId" type="hidden" value="<%= workOrder.workOrderId %>" />
|
<input id="workOrderEdit--workOrderId" name="workOrderId" type="hidden" value="<%= workOrder.workOrderId %>" />
|
||||||
<div class="panel">
|
<div class="panel">
|
||||||
<div class="panel-block is-block">
|
<div class="panel-block is-block">
|
||||||
|
|
@ -126,25 +128,11 @@
|
||||||
<% } %>
|
<% } %>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
</form>
|
||||||
|
|
||||||
<% if (!isCreate) { %>
|
<% if (!isCreate) { %>
|
||||||
<div class="panel">
|
<div class="panel mt-4">
|
||||||
<div class="panel-heading">
|
<h2 class="panel-heading">Related <%= configFunctions.getProperty("aliases.lots") %></h2>
|
||||||
<div class="level">
|
|
||||||
<div class="level-left">
|
|
||||||
<div class="level-item">
|
|
||||||
<h2 class="title has-text-weight-bold is-5">Related <%= configFunctions.getProperty("aliases.lots") %></h2>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="level-right">
|
|
||||||
<div class="level-item">
|
|
||||||
<button class="button is-small is-success" id="button--addWorkOrderLot" type="button">
|
|
||||||
<span class="icon is-small"><i class="fas fa-plus" aria-hidden="true"></i></span>
|
|
||||||
<span>Add <%= configFunctions.getProperty("aliases.lots") %></span>
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="panel-block is-block">
|
<div class="panel-block is-block">
|
||||||
<%
|
<%
|
||||||
const tabToSelect = (workOrder.workOrderLotOccupancies.length > 0 || workOrder.workOrderLots.length === 0 ? "lotOccupancies" : "lots");
|
const tabToSelect = (workOrder.workOrderLotOccupancies.length > 0 || workOrder.workOrderLots.length === 0 ? "lotOccupancies" : "lots");
|
||||||
|
|
@ -167,14 +155,53 @@
|
||||||
</div>
|
</div>
|
||||||
<div class="tab-container">
|
<div class="tab-container">
|
||||||
<div class="<%= (tabToSelect === "lotOccupancies" ? "" : "is-hidden") %>" id="relatedTab--lotOccupancies">
|
<div class="<%= (tabToSelect === "lotOccupancies" ? "" : "is-hidden") %>" id="relatedTab--lotOccupancies">
|
||||||
|
<div class="box has-background-light has-text-right p-3">
|
||||||
|
<button class="button is-success" id="button--addLotOccupancy" type="button">
|
||||||
|
<span class="icon is-small"><i class="fas fa-plus" aria-hidden="true"></i></span>
|
||||||
|
<span>Add Related <%= configFunctions.getProperty("aliases.occupancy") %></span>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
<div id="container--lotOccupancies"></div>
|
||||||
</div>
|
</div>
|
||||||
<div class="<%= (tabToSelect === "lots" ? "" : "is-hidden") %>" id="relatedTab--lots">
|
<div class="<%= (tabToSelect === "lots" ? "" : "is-hidden") %>" id="relatedTab--lots">
|
||||||
|
<div class="box has-background-light has-text-right p-3">
|
||||||
|
<button class="button is-success" id="button--addLot" type="button">
|
||||||
|
<span class="icon is-small"><i class="fas fa-plus" aria-hidden="true"></i></span>
|
||||||
|
<span>Add Related <%= configFunctions.getProperty("aliases.lot") %></span>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
<div id="container--lots"></div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<% } %>
|
<% } %>
|
||||||
</form>
|
</div>
|
||||||
|
<% if (!isCreate) { %>
|
||||||
|
<div class="column is-4">
|
||||||
|
<div class="panel" id="panel--milestones">
|
||||||
|
<div class="panel-heading">
|
||||||
|
<div class="level">
|
||||||
|
<div class="level-left">
|
||||||
|
<div class="level-item">
|
||||||
|
<h2 class="title has-text-weight-bold is-5">Milestones</h2>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="level-right">
|
||||||
|
<div class="level-item">
|
||||||
|
<button class="button is-small is-success" id="button--addMilestone" type="button">
|
||||||
|
<span class="icon is-small"><i class="fas fa-plus" aria-hidden="true"></i></span>
|
||||||
|
<span>Add Milestone</span>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<% } %>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
<%- include('_footerA'); -%>
|
<%- include('_footerA'); -%>
|
||||||
|
|
||||||
|
|
@ -183,6 +210,8 @@
|
||||||
exports.workOrderLots = <%- JSON.stringify(workOrder.workOrderLots) %>;
|
exports.workOrderLots = <%- JSON.stringify(workOrder.workOrderLots) %>;
|
||||||
exports.workOrderLotOccupancies = <%- JSON.stringify(workOrder.workOrderLotOccupancies) %>;
|
exports.workOrderLotOccupancies = <%- JSON.stringify(workOrder.workOrderLotOccupancies) %>;
|
||||||
exports.workOrderMilestones = <%- JSON.stringify(workOrder.workOrderMilestones) %>;
|
exports.workOrderMilestones = <%- JSON.stringify(workOrder.workOrderMilestones) %>;
|
||||||
|
|
||||||
|
exports.lotStatuses = <%- JSON.stringify(lotStatuses) %>;
|
||||||
</script>
|
</script>
|
||||||
<script src="<% urlPrefix %>/javascripts/workOrderEdit.min.js"></script>
|
<script src="<% urlPrefix %>/javascripts/workOrderEdit.min.js"></script>
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue