Aug 19 - Update New Schedule assignment scoped to contract inspector only

This commit is contained in:
2026-08-19 15:00:00 -04:00
parent 291d566f17
commit 14535ca422
2 changed files with 161 additions and 43 deletions
+58 -7
View File
@@ -108,13 +108,19 @@
<div class="mb-3">
<label class="form-label fw-semibold" for="inspector_id">Assign to inspector</label>
<select name="inspector_id" id="inspector_id" class="form-select" required>
<option value="">Choose an inspector</option>
<option value="">Select a Contract first</option>
{% for u in inspectors %}
<option value="{{ u.id }}"
{{ 'selected' if v_inspector == u.id }}>
{{ u.display_name }}{{ ' (Customer)' if u.is_external_inspector }}</option>
{% endfor %}
</select>
<div class="form-text">
Only inspectors assigned to this contract — the person named here
has to be able to open the inspection. Managers are not listed: a
manager who will do the work holds a contract assignment like
anyone else.
</div>
</div>
<div class="row">
@@ -241,7 +247,7 @@
<div class="mb-3">
<label class="form-label fw-semibold" for="notes">
Notes for the inspector <span class="text-muted small fw-normal">(optional)</span>
Instructions for the inspector <span class="text-muted small fw-normal">(optional)</span>
</label>
<textarea name="notes" id="notes" class="form-control" rows="3"
placeholder="e.g. Front lobby carpet needs extra attention. Check loading dock after 3 PM — key is at the front desk.">{{ v_notes }}</textarea>
@@ -298,21 +304,60 @@
// an empty list rather than that customer's building names.
(function () {
'use strict';
var contractSel = document.getElementById('contract_select');
var facilitySel = document.getElementById('facility_id');
var areaSel = document.getElementById('area_id');
var contractSel = document.getElementById('contract_select');
var facilitySel = document.getElementById('facility_id');
var areaSel = document.getElementById('area_id');
var inspectorSel = document.getElementById('inspector_id');
if (!contractSel || !facilitySel) { return; }
var FACILITIES_URL = '{{ url_for("inspections.facilities_for_project", project_id=0) }}'.replace('/0', '/');
var INSPECTORS_URL = '{{ url_for("inspection_schedules.inspectors_for_contract", project_id=0) }}'.replace('/0', '/');
var AREAS_URL = '{{ url_for("inspections.areas_for_facility", facility_id=0) }}'.replace('/0', '/');
var preProjectId = {{ selected_project_id | tojson }};
var preFacilityId = {{ v_facility | tojson }};
var preAreaId = {{ v_area | tojson }};
var preInspectorId = {{ v_inspector | tojson }};
function setPlaceholder() {
facilitySel.innerHTML = '<option value="">— Select a Contract first —</option>';
facilitySel.disabled = true;
loadAreas('', false);
if (inspectorSel) {
inspectorSel.innerHTML = '<option value="">— Select a Contract first —</option>';
inspectorSel.disabled = true;
}
}
// Inspectors come from the CONTRACT, not the facility: assignment rows are
// per contract. The server re-checks the chosen id against this same list.
function loadInspectors(projectId, restoreInspectorId) {
if (!inspectorSel) { return; }
inspectorSel.disabled = true;
inspectorSel.innerHTML = '<option value="">Loading…</option>';
fetch(INSPECTORS_URL + projectId)
.then(function (r) { return r.json(); })
.then(function (data) {
if (!data.length) {
// Not an error state to hide: the contract has nobody assigned yet,
// and saving will fail until someone is. Say so here.
inspectorSel.innerHTML =
'<option value="">— No inspectors assigned to this contract —</option>';
inspectorSel.disabled = false;
return;
}
inspectorSel.innerHTML = '<option value="">— Choose an inspector —</option>';
data.forEach(function (u) {
var opt = document.createElement('option');
opt.value = u.id;
opt.textContent = u.name;
if (restoreInspectorId && u.id === restoreInspectorId) { opt.selected = true; }
inspectorSel.appendChild(opt);
});
inspectorSel.disabled = false;
})
.catch(function () {
inspectorSel.innerHTML = '<option value="">Could not load inspectors</option>';
});
}
function loadAreas(facilityId, keepSelection) {
@@ -356,8 +401,12 @@
}
contractSel.addEventListener('change', function () {
if (this.value) { loadFacilities(this.value, null); }
else { setPlaceholder(); }
if (this.value) {
loadFacilities(this.value, null);
loadInspectors(this.value, null);
} else {
setPlaceholder();
}
});
facilitySel.addEventListener('change', function () {
@@ -369,11 +418,13 @@
if (preProjectId) {
contractSel.value = String(preProjectId);
loadFacilities(preProjectId, preFacilityId);
loadInspectors(preProjectId, preInspectorId);
} else if (preFacilityId) {
// Facility on no contract (or one the selector cannot name): keep the
// server-rendered options and the current choice rather than clearing it.
facilitySel.disabled = false;
loadAreas(String(preFacilityId), true);
if (inspectorSel) { inspectorSel.disabled = false; }
} else {
setPlaceholder();
}