diff --git a/database/getWorkOrderMilestones.d.ts b/database/getWorkOrderMilestones.d.ts index 49659686..69010a77 100644 --- a/database/getWorkOrderMilestones.d.ts +++ b/database/getWorkOrderMilestones.d.ts @@ -1,9 +1,10 @@ +import { type DateString } from '@cityssm/utils-datetime'; import type { PoolConnection } from 'better-sqlite-pool'; import type { WorkOrderMilestone } from '../types/recordTypes.js'; export interface WorkOrderMilestoneFilters { workOrderId?: number | string; workOrderMilestoneDateFilter?: 'upcomingMissed' | 'recent' | 'date' | 'blank' | 'notBlank'; - workOrderMilestoneDateString?: string; + workOrderMilestoneDateString?: '' | DateString; workOrderTypeIds?: string; workOrderMilestoneTypeIds?: string; } diff --git a/database/getWorkOrderMilestones.js b/database/getWorkOrderMilestones.js index 64452530..32fc3249 100644 --- a/database/getWorkOrderMilestones.js +++ b/database/getWorkOrderMilestones.js @@ -42,11 +42,12 @@ function buildWhereClause(filters) { break; } } - if ((filters.workOrderMilestoneDateString ?? '') !== '') { + if (filters.workOrderMilestoneDateString !== undefined && filters.workOrderMilestoneDateString !== '') { sqlWhereClause += ' and m.workOrderMilestoneDate = ?'; sqlParameters.push(dateStringToInteger(filters.workOrderMilestoneDateString)); } - if ((filters.workOrderTypeIds ?? '') !== '' && + if (filters.workOrderTypeIds !== undefined && + filters.workOrderTypeIds !== '' && commaSeparatedNumbersRegex.test(filters.workOrderTypeIds)) { sqlWhereClause += ` and w.workOrderTypeId in (${filters.workOrderTypeIds})`; } diff --git a/database/getWorkOrderMilestones.ts b/database/getWorkOrderMilestones.ts index c918ac61..82938e83 100644 --- a/database/getWorkOrderMilestones.ts +++ b/database/getWorkOrderMilestones.ts @@ -23,7 +23,7 @@ export interface WorkOrderMilestoneFilters { | 'date' | 'blank' | 'notBlank' - workOrderMilestoneDateString?: string + workOrderMilestoneDateString?: '' | DateString workOrderTypeIds?: string workOrderMilestoneTypeIds?: string } @@ -33,6 +33,7 @@ interface WorkOrderMilestoneOptions { orderBy: 'completion' | 'date' } +// eslint-disable-next-line security/detect-unsafe-regex const commaSeparatedNumbersRegex = /^\d+(?:,\d+)*$/ function buildWhereClause(filters: WorkOrderMilestoneFilters): { @@ -98,16 +99,17 @@ function buildWhereClause(filters: WorkOrderMilestoneFilters): { } } - if ((filters.workOrderMilestoneDateString ?? '') !== '') { + if (filters.workOrderMilestoneDateString !== undefined && filters.workOrderMilestoneDateString !== '') { sqlWhereClause += ' and m.workOrderMilestoneDate = ?' sqlParameters.push( - dateStringToInteger(filters.workOrderMilestoneDateString as DateString) + dateStringToInteger(filters.workOrderMilestoneDateString) ) } if ( - (filters.workOrderTypeIds ?? '') !== '' && - commaSeparatedNumbersRegex.test(filters.workOrderTypeIds!) + filters.workOrderTypeIds !== undefined && + filters.workOrderTypeIds !== '' && + commaSeparatedNumbersRegex.test(filters.workOrderTypeIds) ) { sqlWhereClause += ` and w.workOrderTypeId in (${filters.workOrderTypeIds})` } @@ -115,7 +117,7 @@ function buildWhereClause(filters: WorkOrderMilestoneFilters): { if ( filters.workOrderMilestoneTypeIds !== undefined && filters.workOrderMilestoneTypeIds !== '' && - commaSeparatedNumbersRegex.test(filters.workOrderMilestoneTypeIds!) + commaSeparatedNumbersRegex.test(filters.workOrderMilestoneTypeIds) ) { sqlWhereClause += ` and m.workOrderMilestoneTypeId in (${filters.workOrderMilestoneTypeIds})` } diff --git a/handlers/workOrders-post/doGetWorkOrderMilestones.ts b/handlers/workOrders-post/doGetWorkOrderMilestones.ts index f761a67c..176578dc 100644 --- a/handlers/workOrders-post/doGetWorkOrderMilestones.ts +++ b/handlers/workOrders-post/doGetWorkOrderMilestones.ts @@ -1,15 +1,20 @@ import type { Request, Response } from 'express' -import getWorkOrderMilestones from '../../database/getWorkOrderMilestones.js' +import getWorkOrderMilestones, { + type WorkOrderMilestoneFilters +} from '../../database/getWorkOrderMilestones.js' export default async function handler( request: Request, response: Response ): Promise { - const workOrderMilestones = await getWorkOrderMilestones(request.body, { - includeWorkOrders: true, - orderBy: 'date' - }) + const workOrderMilestones = await getWorkOrderMilestones( + request.body as WorkOrderMilestoneFilters, + { + includeWorkOrders: true, + orderBy: 'date' + } + ) response.json({ workOrderMilestones diff --git a/public-typescript/workOrderEdit.js b/public-typescript/workOrderEdit.js index f14b499f..315bf58d 100644 --- a/public-typescript/workOrderEdit.js +++ b/public-typescript/workOrderEdit.js @@ -1,15 +1,15 @@ "use strict"; -/* eslint-disable spaced-comment, @typescript-eslint/no-non-null-assertion, unicorn/prefer-module */ +// eslint-disable-next-line @eslint-community/eslint-comments/disable-enable-pair +/* eslint-disable unicorn/prefer-module */ Object.defineProperty(exports, "__esModule", { value: true }); (() => { - var _a, _b, _c; + var _a, _b, _c, _d; const los = exports.los; const workOrderId = document.querySelector('#workOrderEdit--workOrderId').value; const isCreate = workOrderId === ''; const workOrderFormElement = document.querySelector('#form--workOrderEdit'); - los.initializeDatePickers(workOrderFormElement - .querySelector('#workOrderEdit--workOrderOpenDateString') - .closest('.field')); + los.initializeDatePickers((_a = workOrderFormElement + .querySelector('#workOrderEdit--workOrderOpenDateString')) === null || _a === void 0 ? void 0 : _a.closest('.field')); los.initializeUnlockFieldButtons(workOrderFormElement); function setUnsavedChanges() { var _a; @@ -59,7 +59,7 @@ Object.defineProperty(exports, "__esModule", { value: true }); * Work Order Options */ function doClose() { - cityssm.postJSON(los.urlPrefix + '/workOrders/doCloseWorkOrder', { + cityssm.postJSON(`${los.urlPrefix}/workOrders/doCloseWorkOrder`, { workOrderId }, (rawResponseJSON) => { var _a; @@ -78,14 +78,14 @@ Object.defineProperty(exports, "__esModule", { value: true }); }); } function doDelete() { - cityssm.postJSON(los.urlPrefix + '/workOrders/doDeleteWorkOrder', { + cityssm.postJSON(`${los.urlPrefix}/workOrders/doDeleteWorkOrder`, { workOrderId }, (rawResponseJSON) => { var _a; const responseJSON = rawResponseJSON; if (responseJSON.success) { clearUnsavedChanges(); - window.location.href = los.urlPrefix + '/workOrders'; + window.location.href = `${los.urlPrefix}/workOrders`; } else { bulmaJS.alert({ @@ -97,8 +97,8 @@ Object.defineProperty(exports, "__esModule", { value: true }); }); } let workOrderMilestones; - (_a = document - .querySelector('#button--closeWorkOrder')) === null || _a === void 0 ? void 0 : _a.addEventListener('click', () => { + (_b = document + .querySelector('#button--closeWorkOrder')) === null || _b === void 0 ? void 0 : _b.addEventListener('click', () => { const hasOpenMilestones = workOrderMilestones.some((milestone) => { return !milestone.workOrderMilestoneCompletionDate; }); @@ -137,8 +137,8 @@ Object.defineProperty(exports, "__esModule", { value: true }); }); } }); - (_b = document - .querySelector('#button--deleteWorkOrder')) === null || _b === void 0 ? void 0 : _b.addEventListener('click', (clickEvent) => { + (_c = document + .querySelector('#button--deleteWorkOrder')) === null || _c === void 0 ? void 0 : _c.addEventListener('click', (clickEvent) => { clickEvent.preventDefault(); bulmaJS.confirm({ title: 'Delete Work Order', @@ -914,6 +914,56 @@ Object.defineProperty(exports, "__esModule", { value: true }); /* * Milestones */ + function clearPanelBlockElements(panelElement) { + for (const panelBlockElement of panelElement.querySelectorAll('.panel-block')) { + panelBlockElement.remove(); + } + } + function refreshConflictingMilestones(workOrderMilestoneDateString, targetPanelElement) { + // Clear panel-block elements + clearPanelBlockElements(targetPanelElement); + // eslint-disable-next-line no-unsanitized/method + targetPanelElement.insertAdjacentHTML('beforeend', `
+ ${los.getLoadingParagraphHTML('Loading conflicting milestones...')} +
`); + cityssm.postJSON(`${los.urlPrefix}/workOrders/doGetWorkOrderMilestones`, { + workOrderMilestoneDateFilter: 'date', + workOrderMilestoneDateString + }, (rawResponseJSON) => { + var _a, _b, _c, _d; + const responseJSON = rawResponseJSON; + const workOrderMilestones = responseJSON.workOrderMilestones.filter((possibleMilestone) => { + return possibleMilestone.workOrderId.toString() !== workOrderId; + }); + clearPanelBlockElements(targetPanelElement); + for (const milestone of workOrderMilestones) { + targetPanelElement.insertAdjacentHTML('beforeend', `
+
+
+ ${cityssm.escapeHTML(milestone.workOrderMilestoneTime === 0 ? 'No Time' : (_a = milestone.workOrderMilestoneTimePeriodString) !== null && _a !== void 0 ? _a : '')}
+ ${cityssm.escapeHTML((_b = milestone.workOrderMilestoneType) !== null && _b !== void 0 ? _b : '')} +
+
+ ${cityssm.escapeHTML((_c = milestone.workOrderNumber) !== null && _c !== void 0 ? _c : '')}
+ + ${cityssm.escapeHTML((_d = milestone.workOrderDescription) !== null && _d !== void 0 ? _d : '')} + +
+
+
`); + } + if (workOrderMilestones.length === 0) { + targetPanelElement.insertAdjacentHTML('beforeend', `
+
+

+ There are no milestones on other work orders scheduled for + ${cityssm.escapeHTML(workOrderMilestoneDateString)}. +

+
+
`); + } + }); + } function processMilestoneResponse(rawResponseJSON) { var _a; const responseJSON = rawResponseJSON; @@ -1002,9 +1052,10 @@ Object.defineProperty(exports, "__esModule", { value: true }); return currentMilestone.workOrderMilestoneId === workOrderMilestoneId; }); let editCloseModalFunction; + let workOrderMilestoneDateStringElement; function doEdit(submitEvent) { submitEvent.preventDefault(); - cityssm.postJSON(los.urlPrefix + '/workOrders/doUpdateWorkOrderMilestone', submitEvent.currentTarget, (rawResponseJSON) => { + cityssm.postJSON(`${los.urlPrefix}/workOrders/doUpdateWorkOrderMilestone`, submitEvent.currentTarget, (rawResponseJSON) => { const responseJSON = rawResponseJSON; processMilestoneResponse(responseJSON); if (responseJSON.success) { @@ -1014,9 +1065,10 @@ Object.defineProperty(exports, "__esModule", { value: true }); } cityssm.openHtmlModal('workOrder-editMilestone', { onshow(modalElement) { + var _a, _b, _c, _d, _e; ; modalElement.querySelector('#milestoneEdit--workOrderId').value = workOrderId; - modalElement.querySelector('#milestoneEdit--workOrderMilestoneId').value = workOrderMilestone.workOrderMilestoneId.toString(); + modalElement.querySelector('#milestoneEdit--workOrderMilestoneId').value = (_b = (_a = workOrderMilestone.workOrderMilestoneId) === null || _a === void 0 ? void 0 : _a.toString()) !== null && _b !== void 0 ? _b : ''; const milestoneTypeElement = modalElement.querySelector('#milestoneEdit--workOrderMilestoneTypeId'); let milestoneTypeFound = false; for (const milestoneType of exports.workOrderMilestoneTypes) { @@ -1040,21 +1092,27 @@ Object.defineProperty(exports, "__esModule", { value: true }); optionElement.selected = true; milestoneTypeElement.append(optionElement); } - ; - modalElement.querySelector('#milestoneEdit--workOrderMilestoneDateString').value = workOrderMilestone.workOrderMilestoneDateString; + workOrderMilestoneDateStringElement = modalElement.querySelector('#milestoneEdit--workOrderMilestoneDateString'); + workOrderMilestoneDateStringElement.value = (_c = workOrderMilestone.workOrderMilestoneDateString) !== null && _c !== void 0 ? _c : ''; if (workOrderMilestone.workOrderMilestoneTime) { ; - modalElement.querySelector('#milestoneEdit--workOrderMilestoneTimeString').value = workOrderMilestone.workOrderMilestoneTimeString; + modalElement.querySelector('#milestoneEdit--workOrderMilestoneTimeString').value = (_d = workOrderMilestone.workOrderMilestoneTimeString) !== null && _d !== void 0 ? _d : ''; } ; - modalElement.querySelector('#milestoneEdit--workOrderMilestoneDescription').value = workOrderMilestone.workOrderMilestoneDescription; + modalElement.querySelector('#milestoneEdit--workOrderMilestoneDescription').value = (_e = workOrderMilestone.workOrderMilestoneDescription) !== null && _e !== void 0 ? _e : ''; }, onshown(modalElement, closeModalFunction) { + var _a; editCloseModalFunction = closeModalFunction; bulmaJS.toggleHtmlClipped(); los.initializeDatePickers(modalElement); // los.initializeTimePickers(modalElement); - modalElement.querySelector('form').addEventListener('submit', doEdit); + (_a = modalElement.querySelector('form')) === null || _a === void 0 ? void 0 : _a.addEventListener('submit', doEdit); + const conflictingMilestonePanelElement = document.querySelector('#milestoneEdit--conflictingMilestonesPanel'); + workOrderMilestoneDateStringElement.addEventListener('change', () => { + refreshConflictingMilestones(workOrderMilestoneDateStringElement.value, conflictingMilestonePanelElement); + }); + refreshConflictingMilestones(workOrderMilestoneDateStringElement.value, conflictingMilestonePanelElement); }, onremoved() { bulmaJS.toggleHtmlClipped(); @@ -1152,10 +1210,10 @@ Object.defineProperty(exports, "__esModule", { value: true }); exports.workOrderMilestones; delete exports.workOrderMilestones; renderMilestones(); - (_c = document - .querySelector('#button--addMilestone')) === null || _c === void 0 ? void 0 : _c.addEventListener('click', () => { - let addModalElement; + (_d = document + .querySelector('#button--addMilestone')) === null || _d === void 0 ? void 0 : _d.addEventListener('click', () => { let addFormElement; + let workOrderMilestoneDateStringElement; let addCloseModalFunction; function doAdd(submitEvent) { if (submitEvent) { @@ -1163,7 +1221,7 @@ Object.defineProperty(exports, "__esModule", { value: true }); } const currentDateString = cityssm.dateToString(new Date()); function _doAdd() { - cityssm.postJSON(los.urlPrefix + '/workOrders/doAddWorkOrderMilestone', addFormElement, (rawResponseJSON) => { + cityssm.postJSON(`${los.urlPrefix}/workOrders/doAddWorkOrderMilestone`, addFormElement, (rawResponseJSON) => { const responseJSON = rawResponseJSON; processMilestoneResponse(responseJSON); if (responseJSON.success) { @@ -1171,7 +1229,7 @@ Object.defineProperty(exports, "__esModule", { value: true }); } }); } - const milestoneDateString = addModalElement.querySelector('#milestoneAdd--workOrderMilestoneDateString').value; + const milestoneDateString = workOrderMilestoneDateStringElement.value; if (milestoneDateString !== '' && milestoneDateString < currentDateString) { bulmaJS.confirm({ @@ -1200,11 +1258,10 @@ Object.defineProperty(exports, "__esModule", { value: true }); optionElement.textContent = milestoneType.workOrderMilestoneType; milestoneTypeElement.append(optionElement); } - ; - modalElement.querySelector('#milestoneAdd--workOrderMilestoneDateString').valueAsDate = new Date(); + workOrderMilestoneDateStringElement = modalElement.querySelector('#milestoneAdd--workOrderMilestoneDateString'); + workOrderMilestoneDateStringElement.valueAsDate = new Date(); }, onshown(modalElement, closeModalFunction) { - addModalElement = modalElement; addCloseModalFunction = closeModalFunction; los.initializeDatePickers(modalElement); // los.initializeTimePickers(modalElement); @@ -1212,6 +1269,11 @@ Object.defineProperty(exports, "__esModule", { value: true }); modalElement.querySelector('#milestoneAdd--workOrderMilestoneTypeId').focus(); addFormElement = modalElement.querySelector('form'); addFormElement.addEventListener('submit', doAdd); + const conflictingMilestonePanelElement = document.querySelector('#milestoneAdd--conflictingMilestonesPanel'); + workOrderMilestoneDateStringElement.addEventListener('change', () => { + refreshConflictingMilestones(workOrderMilestoneDateStringElement.value, conflictingMilestonePanelElement); + }); + refreshConflictingMilestones(workOrderMilestoneDateStringElement.value, conflictingMilestonePanelElement); }, onremoved() { bulmaJS.toggleHtmlClipped(); diff --git a/public-typescript/workOrderEdit/workOrderEdit.js b/public-typescript/workOrderEdit/workOrderEdit.js index 9c7ff5de..f7f7a604 100644 --- a/public-typescript/workOrderEdit/workOrderEdit.js +++ b/public-typescript/workOrderEdit/workOrderEdit.js @@ -1,15 +1,15 @@ "use strict"; -/* eslint-disable spaced-comment, @typescript-eslint/no-non-null-assertion, unicorn/prefer-module */ +// eslint-disable-next-line @eslint-community/eslint-comments/disable-enable-pair +/* eslint-disable unicorn/prefer-module */ Object.defineProperty(exports, "__esModule", { value: true }); (() => { - var _a, _b, _c; + var _a, _b, _c, _d; const los = exports.los; const workOrderId = document.querySelector('#workOrderEdit--workOrderId').value; const isCreate = workOrderId === ''; const workOrderFormElement = document.querySelector('#form--workOrderEdit'); - los.initializeDatePickers(workOrderFormElement - .querySelector('#workOrderEdit--workOrderOpenDateString') - .closest('.field')); + los.initializeDatePickers((_a = workOrderFormElement + .querySelector('#workOrderEdit--workOrderOpenDateString')) === null || _a === void 0 ? void 0 : _a.closest('.field')); los.initializeUnlockFieldButtons(workOrderFormElement); function setUnsavedChanges() { var _a; @@ -59,7 +59,7 @@ Object.defineProperty(exports, "__esModule", { value: true }); * Work Order Options */ function doClose() { - cityssm.postJSON(los.urlPrefix + '/workOrders/doCloseWorkOrder', { + cityssm.postJSON(`${los.urlPrefix}/workOrders/doCloseWorkOrder`, { workOrderId }, (rawResponseJSON) => { var _a; @@ -78,14 +78,14 @@ Object.defineProperty(exports, "__esModule", { value: true }); }); } function doDelete() { - cityssm.postJSON(los.urlPrefix + '/workOrders/doDeleteWorkOrder', { + cityssm.postJSON(`${los.urlPrefix}/workOrders/doDeleteWorkOrder`, { workOrderId }, (rawResponseJSON) => { var _a; const responseJSON = rawResponseJSON; if (responseJSON.success) { clearUnsavedChanges(); - window.location.href = los.urlPrefix + '/workOrders'; + window.location.href = `${los.urlPrefix}/workOrders`; } else { bulmaJS.alert({ @@ -97,8 +97,8 @@ Object.defineProperty(exports, "__esModule", { value: true }); }); } let workOrderMilestones; - (_a = document - .querySelector('#button--closeWorkOrder')) === null || _a === void 0 ? void 0 : _a.addEventListener('click', () => { + (_b = document + .querySelector('#button--closeWorkOrder')) === null || _b === void 0 ? void 0 : _b.addEventListener('click', () => { const hasOpenMilestones = workOrderMilestones.some((milestone) => { return !milestone.workOrderMilestoneCompletionDate; }); @@ -137,8 +137,8 @@ Object.defineProperty(exports, "__esModule", { value: true }); }); } }); - (_b = document - .querySelector('#button--deleteWorkOrder')) === null || _b === void 0 ? void 0 : _b.addEventListener('click', (clickEvent) => { + (_c = document + .querySelector('#button--deleteWorkOrder')) === null || _c === void 0 ? void 0 : _c.addEventListener('click', (clickEvent) => { clickEvent.preventDefault(); bulmaJS.confirm({ title: 'Delete Work Order', @@ -163,6 +163,56 @@ Object.defineProperty(exports, "__esModule", { value: true }); /* * Milestones */ + function clearPanelBlockElements(panelElement) { + for (const panelBlockElement of panelElement.querySelectorAll('.panel-block')) { + panelBlockElement.remove(); + } + } + function refreshConflictingMilestones(workOrderMilestoneDateString, targetPanelElement) { + // Clear panel-block elements + clearPanelBlockElements(targetPanelElement); + // eslint-disable-next-line no-unsanitized/method + targetPanelElement.insertAdjacentHTML('beforeend', `
+ ${los.getLoadingParagraphHTML('Loading conflicting milestones...')} +
`); + cityssm.postJSON(`${los.urlPrefix}/workOrders/doGetWorkOrderMilestones`, { + workOrderMilestoneDateFilter: 'date', + workOrderMilestoneDateString + }, (rawResponseJSON) => { + var _a, _b, _c, _d; + const responseJSON = rawResponseJSON; + const workOrderMilestones = responseJSON.workOrderMilestones.filter((possibleMilestone) => { + return possibleMilestone.workOrderId.toString() !== workOrderId; + }); + clearPanelBlockElements(targetPanelElement); + for (const milestone of workOrderMilestones) { + targetPanelElement.insertAdjacentHTML('beforeend', `
+
+
+ ${cityssm.escapeHTML(milestone.workOrderMilestoneTime === 0 ? 'No Time' : (_a = milestone.workOrderMilestoneTimePeriodString) !== null && _a !== void 0 ? _a : '')}
+ ${cityssm.escapeHTML((_b = milestone.workOrderMilestoneType) !== null && _b !== void 0 ? _b : '')} +
+
+ ${cityssm.escapeHTML((_c = milestone.workOrderNumber) !== null && _c !== void 0 ? _c : '')}
+ + ${cityssm.escapeHTML((_d = milestone.workOrderDescription) !== null && _d !== void 0 ? _d : '')} + +
+
+
`); + } + if (workOrderMilestones.length === 0) { + targetPanelElement.insertAdjacentHTML('beforeend', `
+
+

+ There are no milestones on other work orders scheduled for + ${cityssm.escapeHTML(workOrderMilestoneDateString)}. +

+
+
`); + } + }); + } function processMilestoneResponse(rawResponseJSON) { var _a; const responseJSON = rawResponseJSON; @@ -251,9 +301,10 @@ Object.defineProperty(exports, "__esModule", { value: true }); return currentMilestone.workOrderMilestoneId === workOrderMilestoneId; }); let editCloseModalFunction; + let workOrderMilestoneDateStringElement; function doEdit(submitEvent) { submitEvent.preventDefault(); - cityssm.postJSON(los.urlPrefix + '/workOrders/doUpdateWorkOrderMilestone', submitEvent.currentTarget, (rawResponseJSON) => { + cityssm.postJSON(`${los.urlPrefix}/workOrders/doUpdateWorkOrderMilestone`, submitEvent.currentTarget, (rawResponseJSON) => { const responseJSON = rawResponseJSON; processMilestoneResponse(responseJSON); if (responseJSON.success) { @@ -263,9 +314,10 @@ Object.defineProperty(exports, "__esModule", { value: true }); } cityssm.openHtmlModal('workOrder-editMilestone', { onshow(modalElement) { + var _a, _b, _c, _d, _e; ; modalElement.querySelector('#milestoneEdit--workOrderId').value = workOrderId; - modalElement.querySelector('#milestoneEdit--workOrderMilestoneId').value = workOrderMilestone.workOrderMilestoneId.toString(); + modalElement.querySelector('#milestoneEdit--workOrderMilestoneId').value = (_b = (_a = workOrderMilestone.workOrderMilestoneId) === null || _a === void 0 ? void 0 : _a.toString()) !== null && _b !== void 0 ? _b : ''; const milestoneTypeElement = modalElement.querySelector('#milestoneEdit--workOrderMilestoneTypeId'); let milestoneTypeFound = false; for (const milestoneType of exports.workOrderMilestoneTypes) { @@ -289,21 +341,27 @@ Object.defineProperty(exports, "__esModule", { value: true }); optionElement.selected = true; milestoneTypeElement.append(optionElement); } - ; - modalElement.querySelector('#milestoneEdit--workOrderMilestoneDateString').value = workOrderMilestone.workOrderMilestoneDateString; + workOrderMilestoneDateStringElement = modalElement.querySelector('#milestoneEdit--workOrderMilestoneDateString'); + workOrderMilestoneDateStringElement.value = (_c = workOrderMilestone.workOrderMilestoneDateString) !== null && _c !== void 0 ? _c : ''; if (workOrderMilestone.workOrderMilestoneTime) { ; - modalElement.querySelector('#milestoneEdit--workOrderMilestoneTimeString').value = workOrderMilestone.workOrderMilestoneTimeString; + modalElement.querySelector('#milestoneEdit--workOrderMilestoneTimeString').value = (_d = workOrderMilestone.workOrderMilestoneTimeString) !== null && _d !== void 0 ? _d : ''; } ; - modalElement.querySelector('#milestoneEdit--workOrderMilestoneDescription').value = workOrderMilestone.workOrderMilestoneDescription; + modalElement.querySelector('#milestoneEdit--workOrderMilestoneDescription').value = (_e = workOrderMilestone.workOrderMilestoneDescription) !== null && _e !== void 0 ? _e : ''; }, onshown(modalElement, closeModalFunction) { + var _a; editCloseModalFunction = closeModalFunction; bulmaJS.toggleHtmlClipped(); los.initializeDatePickers(modalElement); // los.initializeTimePickers(modalElement); - modalElement.querySelector('form').addEventListener('submit', doEdit); + (_a = modalElement.querySelector('form')) === null || _a === void 0 ? void 0 : _a.addEventListener('submit', doEdit); + const conflictingMilestonePanelElement = document.querySelector('#milestoneEdit--conflictingMilestonesPanel'); + workOrderMilestoneDateStringElement.addEventListener('change', () => { + refreshConflictingMilestones(workOrderMilestoneDateStringElement.value, conflictingMilestonePanelElement); + }); + refreshConflictingMilestones(workOrderMilestoneDateStringElement.value, conflictingMilestonePanelElement); }, onremoved() { bulmaJS.toggleHtmlClipped(); @@ -401,10 +459,10 @@ Object.defineProperty(exports, "__esModule", { value: true }); exports.workOrderMilestones; delete exports.workOrderMilestones; renderMilestones(); - (_c = document - .querySelector('#button--addMilestone')) === null || _c === void 0 ? void 0 : _c.addEventListener('click', () => { - let addModalElement; + (_d = document + .querySelector('#button--addMilestone')) === null || _d === void 0 ? void 0 : _d.addEventListener('click', () => { let addFormElement; + let workOrderMilestoneDateStringElement; let addCloseModalFunction; function doAdd(submitEvent) { if (submitEvent) { @@ -412,7 +470,7 @@ Object.defineProperty(exports, "__esModule", { value: true }); } const currentDateString = cityssm.dateToString(new Date()); function _doAdd() { - cityssm.postJSON(los.urlPrefix + '/workOrders/doAddWorkOrderMilestone', addFormElement, (rawResponseJSON) => { + cityssm.postJSON(`${los.urlPrefix}/workOrders/doAddWorkOrderMilestone`, addFormElement, (rawResponseJSON) => { const responseJSON = rawResponseJSON; processMilestoneResponse(responseJSON); if (responseJSON.success) { @@ -420,7 +478,7 @@ Object.defineProperty(exports, "__esModule", { value: true }); } }); } - const milestoneDateString = addModalElement.querySelector('#milestoneAdd--workOrderMilestoneDateString').value; + const milestoneDateString = workOrderMilestoneDateStringElement.value; if (milestoneDateString !== '' && milestoneDateString < currentDateString) { bulmaJS.confirm({ @@ -449,11 +507,10 @@ Object.defineProperty(exports, "__esModule", { value: true }); optionElement.textContent = milestoneType.workOrderMilestoneType; milestoneTypeElement.append(optionElement); } - ; - modalElement.querySelector('#milestoneAdd--workOrderMilestoneDateString').valueAsDate = new Date(); + workOrderMilestoneDateStringElement = modalElement.querySelector('#milestoneAdd--workOrderMilestoneDateString'); + workOrderMilestoneDateStringElement.valueAsDate = new Date(); }, onshown(modalElement, closeModalFunction) { - addModalElement = modalElement; addCloseModalFunction = closeModalFunction; los.initializeDatePickers(modalElement); // los.initializeTimePickers(modalElement); @@ -461,6 +518,11 @@ Object.defineProperty(exports, "__esModule", { value: true }); modalElement.querySelector('#milestoneAdd--workOrderMilestoneTypeId').focus(); addFormElement = modalElement.querySelector('form'); addFormElement.addEventListener('submit', doAdd); + const conflictingMilestonePanelElement = document.querySelector('#milestoneAdd--conflictingMilestonesPanel'); + workOrderMilestoneDateStringElement.addEventListener('change', () => { + refreshConflictingMilestones(workOrderMilestoneDateStringElement.value, conflictingMilestonePanelElement); + }); + refreshConflictingMilestones(workOrderMilestoneDateStringElement.value, conflictingMilestonePanelElement); }, onremoved() { bulmaJS.toggleHtmlClipped(); diff --git a/public-typescript/workOrderEdit/workOrderEdit.ts b/public-typescript/workOrderEdit/workOrderEdit.ts index 7c340ae9..bbed42e4 100644 --- a/public-typescript/workOrderEdit/workOrderEdit.ts +++ b/public-typescript/workOrderEdit/workOrderEdit.ts @@ -1,13 +1,16 @@ -/* eslint-disable spaced-comment, @typescript-eslint/no-non-null-assertion, unicorn/prefer-module */ +// eslint-disable-next-line @eslint-community/eslint-comments/disable-enable-pair +/* eslint-disable unicorn/prefer-module */ -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.js' +import type { cityssmGlobal } from '@cityssm/bulma-webapp-js/src/types.js' -import type * as globalTypes from '../../types/globalTypes' -import type * as recordTypes from '../../types/recordTypes' +import type * as globalTypes from '../../types/globalTypes.js' +import type * as recordTypes from '../../types/recordTypes.js' declare const cityssm: cityssmGlobal declare const bulmaJS: BulmaJS + +declare const exports: Record ;(() => { const los = exports.los as globalTypes.LOS @@ -23,8 +26,8 @@ declare const bulmaJS: BulmaJS los.initializeDatePickers( workOrderFormElement - .querySelector('#workOrderEdit--workOrderOpenDateString')! - .closest('.field') as HTMLElement + .querySelector('#workOrderEdit--workOrderOpenDateString') + ?.closest('.field') as HTMLElement ) los.initializeUnlockFieldButtons(workOrderFormElement) @@ -96,7 +99,7 @@ declare const bulmaJS: BulmaJS function doClose(): void { cityssm.postJSON( - los.urlPrefix + '/workOrders/doCloseWorkOrder', + `${los.urlPrefix}/workOrders/doCloseWorkOrder`, { workOrderId }, @@ -122,7 +125,7 @@ declare const bulmaJS: BulmaJS function doDelete(): void { cityssm.postJSON( - los.urlPrefix + '/workOrders/doDeleteWorkOrder', + `${los.urlPrefix}/workOrders/doDeleteWorkOrder`, { workOrderId }, @@ -134,7 +137,7 @@ declare const bulmaJS: BulmaJS if (responseJSON.success) { clearUnsavedChanges() - window.location.href = los.urlPrefix + '/workOrders' + window.location.href = `${los.urlPrefix}/workOrders` } else { bulmaJS.alert({ title: 'Error Deleting Work Order', @@ -225,15 +228,94 @@ declare const bulmaJS: BulmaJS * Milestones */ + function clearPanelBlockElements(panelElement: HTMLElement): void { + for (const panelBlockElement of panelElement.querySelectorAll( + '.panel-block' + )) { + panelBlockElement.remove() + } + } + + function refreshConflictingMilestones( + workOrderMilestoneDateString: string, + targetPanelElement: HTMLElement + ): void { + // Clear panel-block elements + clearPanelBlockElements(targetPanelElement) + + // eslint-disable-next-line no-unsanitized/method + targetPanelElement.insertAdjacentHTML( + 'beforeend', + `
+ ${los.getLoadingParagraphHTML('Loading conflicting milestones...')} +
` + ) + + cityssm.postJSON( + `${los.urlPrefix}/workOrders/doGetWorkOrderMilestones`, + { + workOrderMilestoneDateFilter: 'date', + workOrderMilestoneDateString + }, + (rawResponseJSON) => { + const responseJSON = rawResponseJSON as { + workOrderMilestones: recordTypes.WorkOrderMilestone[] + } + + const workOrderMilestones = responseJSON.workOrderMilestones.filter( + (possibleMilestone) => { + return possibleMilestone.workOrderId.toString() !== workOrderId + } + ) + + clearPanelBlockElements(targetPanelElement) + + for (const milestone of workOrderMilestones) { + targetPanelElement.insertAdjacentHTML( + 'beforeend', + `
+
+
+ ${cityssm.escapeHTML(milestone.workOrderMilestoneTime === 0 ? 'No Time' : milestone.workOrderMilestoneTimePeriodString ?? '')}
+ ${cityssm.escapeHTML(milestone.workOrderMilestoneType ?? '')} +
+
+ ${cityssm.escapeHTML(milestone.workOrderNumber ?? '')}
+ + ${cityssm.escapeHTML(milestone.workOrderDescription ?? '')} + +
+
+
` + ) + } + + if (workOrderMilestones.length === 0) { + targetPanelElement.insertAdjacentHTML( + 'beforeend', + `
+
+

+ There are no milestones on other work orders scheduled for + ${cityssm.escapeHTML(workOrderMilestoneDateString)}. +

+
+
` + ) + } + } + ) + } + function processMilestoneResponse(rawResponseJSON: unknown): void { const responseJSON = rawResponseJSON as { success: boolean errorMessage?: string - workOrderMilestones?: recordTypes.WorkOrderMilestone[] + workOrderMilestones: recordTypes.WorkOrderMilestone[] } if (responseJSON.success) { - workOrderMilestones = responseJSON.workOrderMilestones! + workOrderMilestones = responseJSON.workOrderMilestones renderMilestones() } else { bulmaJS.alert({ @@ -370,12 +452,13 @@ declare const bulmaJS: BulmaJS })! let editCloseModalFunction: () => void + let workOrderMilestoneDateStringElement: HTMLInputElement function doEdit(submitEvent: SubmitEvent): void { submitEvent.preventDefault() cityssm.postJSON( - los.urlPrefix + '/workOrders/doUpdateWorkOrderMilestone', + `${los.urlPrefix}/workOrders/doUpdateWorkOrderMilestone`, submitEvent.currentTarget, (rawResponseJSON) => { const responseJSON = rawResponseJSON as { @@ -403,7 +486,7 @@ declare const bulmaJS: BulmaJS modalElement.querySelector( '#milestoneEdit--workOrderMilestoneId' ) as HTMLInputElement - ).value = workOrderMilestone.workOrderMilestoneId!.toString() + ).value = workOrderMilestone.workOrderMilestoneId?.toString() ?? '' const milestoneTypeElement = modalElement.querySelector( '#milestoneEdit--workOrderMilestoneTypeId' @@ -441,25 +524,27 @@ declare const bulmaJS: BulmaJS milestoneTypeElement.append(optionElement) } - ;( + workOrderMilestoneDateStringElement = ( modalElement.querySelector( '#milestoneEdit--workOrderMilestoneDateString' ) as HTMLInputElement - ).value = workOrderMilestone.workOrderMilestoneDateString! + ) + + workOrderMilestoneDateStringElement.value = workOrderMilestone.workOrderMilestoneDateString ?? '' if (workOrderMilestone.workOrderMilestoneTime) { ;( modalElement.querySelector( '#milestoneEdit--workOrderMilestoneTimeString' ) as HTMLInputElement - ).value = workOrderMilestone.workOrderMilestoneTimeString! + ).value = workOrderMilestone.workOrderMilestoneTimeString ?? '' } ;( modalElement.querySelector( '#milestoneEdit--workOrderMilestoneDescription' ) as HTMLTextAreaElement - ).value = workOrderMilestone.workOrderMilestoneDescription! + ).value = workOrderMilestone.workOrderMilestoneDescription ?? '' }, onshown(modalElement, closeModalFunction) { editCloseModalFunction = closeModalFunction @@ -468,7 +553,26 @@ declare const bulmaJS: BulmaJS los.initializeDatePickers(modalElement) // los.initializeTimePickers(modalElement); - modalElement.querySelector('form')!.addEventListener('submit', doEdit) + modalElement.querySelector('form')?.addEventListener('submit', doEdit) + + const conflictingMilestonePanelElement = document.querySelector( + '#milestoneEdit--conflictingMilestonesPanel' + ) as HTMLElement + + workOrderMilestoneDateStringElement.addEventListener( + 'change', + () => { + refreshConflictingMilestones( + workOrderMilestoneDateStringElement.value, + conflictingMilestonePanelElement + ) + } + ) + + refreshConflictingMilestones( + workOrderMilestoneDateStringElement.value, + conflictingMilestonePanelElement + ) }, onremoved() { bulmaJS.toggleHtmlClipped() @@ -588,8 +692,9 @@ declare const bulmaJS: BulmaJS document .querySelector('#button--addMilestone') ?.addEventListener('click', () => { - let addModalElement: HTMLElement + let addFormElement: HTMLFormElement + let workOrderMilestoneDateStringElement: HTMLInputElement let addCloseModalFunction: () => void function doAdd(submitEvent: SubmitEvent): void { @@ -601,7 +706,7 @@ declare const bulmaJS: BulmaJS function _doAdd(): void { cityssm.postJSON( - los.urlPrefix + '/workOrders/doAddWorkOrderMilestone', + `${los.urlPrefix}/workOrders/doAddWorkOrderMilestone`, addFormElement, (rawResponseJSON) => { const responseJSON = rawResponseJSON as { @@ -619,11 +724,7 @@ declare const bulmaJS: BulmaJS ) } - const milestoneDateString = ( - addModalElement.querySelector( - '#milestoneAdd--workOrderMilestoneDateString' - ) as HTMLInputElement - ).value + const milestoneDateString = workOrderMilestoneDateStringElement.value if ( milestoneDateString !== '' && @@ -666,14 +767,14 @@ declare const bulmaJS: BulmaJS milestoneTypeElement.append(optionElement) } - ;( - modalElement.querySelector( - '#milestoneAdd--workOrderMilestoneDateString' - ) as HTMLInputElement - ).valueAsDate = new Date() + workOrderMilestoneDateStringElement = modalElement.querySelector( + '#milestoneAdd--workOrderMilestoneDateString' + ) as HTMLInputElement + + workOrderMilestoneDateStringElement.valueAsDate = new Date() }, onshown(modalElement, closeModalFunction) { - addModalElement = modalElement + addCloseModalFunction = closeModalFunction los.initializeDatePickers(modalElement) @@ -686,8 +787,29 @@ declare const bulmaJS: BulmaJS ) as HTMLSelectElement ).focus() - addFormElement = modalElement.querySelector('form')! + addFormElement = modalElement.querySelector( + 'form' + ) as HTMLFormElement addFormElement.addEventListener('submit', doAdd) + + const conflictingMilestonePanelElement = document.querySelector( + '#milestoneAdd--conflictingMilestonesPanel' + ) as HTMLElement + + workOrderMilestoneDateStringElement.addEventListener( + 'change', + () => { + refreshConflictingMilestones( + workOrderMilestoneDateStringElement.value, + conflictingMilestonePanelElement + ) + } + ) + + refreshConflictingMilestones( + workOrderMilestoneDateStringElement.value, + conflictingMilestonePanelElement + ) }, onremoved() { bulmaJS.toggleHtmlClipped() diff --git a/public/html/workOrder-addMilestone.html b/public/html/workOrder-addMilestone.html index 1c6807f3..c6c262bf 100644 --- a/public/html/workOrder-addMilestone.html +++ b/public/html/workOrder-addMilestone.html @@ -1,6 +1,6 @@