Jul 9 - Update the 'Handled by' more clear and understandable
This commit is contained in:
@@ -256,10 +256,12 @@ issues: id, inspection_id (nullable), area_id, facility_id (nullable), severity
|
|||||||
|
|
||||||
| Value | Meaning | Detail fields | `assigned_to` role |
|
| Value | Meaning | Detail fields | `assigned_to` role |
|
||||||
|---|---|---|---|
|
|---|---|---|---|
|
||||||
| `internal` (default) | Our staff | — (the assignee IS the handler) | the handler |
|
| `internal` (default) | Janitorial Staff (our crew) | — (the assignee IS the handler) | the handler |
|
||||||
| `facility` | The facility's own staff | `facility_handler_name/contact/notes` (free text) | internal **follow-up owner** |
|
| `facility` | The facility's own staff | `facility_handler_name/contact/notes` (free text) | internal **follow-up owner** |
|
||||||
| `vendor` | External contractor | `vendor_name/contact/notes` (Phase 26) | internal **follow-up owner** |
|
| `vendor` | External contractor | `vendor_name/contact/notes` (Phase 26) | internal **follow-up owner** |
|
||||||
|
|
||||||
|
**Display labels are perspective-neutral** (they read the same for staff and customers) with a descriptor line under the selector and a tooltip on badges: `internal` → **"Janitorial Staff"** ("Our janitorial crew handles it."), `facility` → **"Facility Staff"** ("The facility's own on-site staff handle it."), `vendor` → **"External Vendor"** ("An outside contractor handles it."). Labels/descriptions live in `Issue.HANDLER_LABELS` / `HANDLER_DESCRIPTIONS`, the WTForms `handler_type` choices, and the `HANDLER_DESC` JS map in both issue templates — keep these in sync. Do **not** use viewer-relative words like "Our"/"Your" for the stored categories.
|
||||||
|
|
||||||
`assigned_to` (a JQC User) is **always** available: it is the handler for `internal`, and the internal follow-up owner (e.g. the inspector who verifies/updates) for `facility`/`vendor`. Settable in **two places**, both with a "Handled By" selector that reveals the facility or vendor sub-fields via JS:
|
`assigned_to` (a JQC User) is **always** available: it is the handler for `internal`, and the internal follow-up owner (e.g. the inspector who verifies/updates) for `facility`/`vendor`. Settable in **two places**, both with a "Handled By" selector that reveals the facility or vendor sub-fields via JS:
|
||||||
- **Log New Issue** form (`issues/form.html`) — at creation, for non-customer staff. Customer-created issues stay `internal` (the handler UI is hidden for them, same as `assigned_to`).
|
- **Log New Issue** form (`issues/form.html`) — at creation, for non-customer staff. Customer-created issues stay `internal` (the handler UI is hidden for them, same as `assigned_to`).
|
||||||
- **Update Issue** panel on the issue detail page (`issues/view.html`) — triage after creation.
|
- **Update Issue** panel on the issue detail page (`issues/view.html`) — triage after creation.
|
||||||
|
|||||||
+8
-2
@@ -115,15 +115,21 @@ class Issue(db.Model):
|
|||||||
return self.followers.filter_by(user_id=user.id).first() is not None
|
return self.followers.filter_by(user_id=user.id).first() is not None
|
||||||
|
|
||||||
# Human-readable label for the handler category (phase35).
|
# Human-readable label for the handler category (phase35).
|
||||||
|
# Perspective-neutral wording so it reads the same for staff and customers.
|
||||||
HANDLER_LABELS = {
|
HANDLER_LABELS = {
|
||||||
'internal': 'Our Staff',
|
'internal': 'Janitorial Staff',
|
||||||
'facility': 'Facility Staff',
|
'facility': 'Facility Staff',
|
||||||
'vendor': 'External Vendor',
|
'vendor': 'External Vendor',
|
||||||
}
|
}
|
||||||
|
HANDLER_DESCRIPTIONS = {
|
||||||
|
'internal': 'Our janitorial crew handles it.',
|
||||||
|
'facility': "The facility's own on-site staff handle it.",
|
||||||
|
'vendor': 'An outside contractor handles it.',
|
||||||
|
}
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def handler_label(self):
|
def handler_label(self):
|
||||||
return self.HANDLER_LABELS.get(self.handler_type or 'internal', 'Our Staff')
|
return self.HANDLER_LABELS.get(self.handler_type or 'internal', 'Janitorial Staff')
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def resolved_facility(self):
|
def resolved_facility(self):
|
||||||
|
|||||||
@@ -41,6 +41,7 @@
|
|||||||
<div class="mb-3">
|
<div class="mb-3">
|
||||||
{{ form.handler_type.label(class="form-label fw-semibold") }}
|
{{ form.handler_type.label(class="form-label fw-semibold") }}
|
||||||
{{ form.handler_type(class="form-select", id="handler_type_select") }}
|
{{ form.handler_type(class="form-select", id="handler_type_select") }}
|
||||||
|
<div class="form-text" id="handler_desc"></div>
|
||||||
</div>
|
</div>
|
||||||
<div class="mb-3">
|
<div class="mb-3">
|
||||||
<label class="form-label fw-semibold" id="assigned_to_label">Assign To</label>
|
<label class="form-label fw-semibold" id="assigned_to_label">Assign To</label>
|
||||||
@@ -157,6 +158,11 @@
|
|||||||
|
|
||||||
// ── "Handled By" — reveal the facility/vendor sub-block + relabel assignee ──
|
// ── "Handled By" — reveal the facility/vendor sub-block + relabel assignee ──
|
||||||
var handlerSelect = document.getElementById('handler_type_select');
|
var handlerSelect = document.getElementById('handler_type_select');
|
||||||
|
var HANDLER_DESC = {
|
||||||
|
'internal': 'Our janitorial crew handles it.',
|
||||||
|
'facility': "The facility's own on-site staff handle it.",
|
||||||
|
'vendor': 'An outside contractor handles it.'
|
||||||
|
};
|
||||||
function syncHandlerUI() {
|
function syncHandlerUI() {
|
||||||
if (!handlerSelect) { return; }
|
if (!handlerSelect) { return; }
|
||||||
var v = handlerSelect.value;
|
var v = handlerSelect.value;
|
||||||
@@ -164,6 +170,8 @@
|
|||||||
var venBlock = document.getElementById('vendor_block');
|
var venBlock = document.getElementById('vendor_block');
|
||||||
if (facBlock) { facBlock.style.display = (v === 'facility') ? '' : 'none'; }
|
if (facBlock) { facBlock.style.display = (v === 'facility') ? '' : 'none'; }
|
||||||
if (venBlock) { venBlock.style.display = (v === 'vendor') ? '' : 'none'; }
|
if (venBlock) { venBlock.style.display = (v === 'vendor') ? '' : 'none'; }
|
||||||
|
var desc = document.getElementById('handler_desc');
|
||||||
|
if (desc) { desc.textContent = HANDLER_DESC[v] || ''; }
|
||||||
var label = document.getElementById('assigned_to_label');
|
var label = document.getElementById('assigned_to_label');
|
||||||
var help = document.getElementById('assigned_to_help');
|
var help = document.getElementById('assigned_to_help');
|
||||||
if (label) {
|
if (label) {
|
||||||
|
|||||||
@@ -86,7 +86,7 @@
|
|||||||
<label class="form-label small mb-1">Handled By</label>
|
<label class="form-label small mb-1">Handled By</label>
|
||||||
<select name="handler_type" class="form-select form-select-sm">
|
<select name="handler_type" class="form-select form-select-sm">
|
||||||
<option value="">All Handlers</option>
|
<option value="">All Handlers</option>
|
||||||
<option value="internal" {{ 'selected' if handler_filter == 'internal' }}>Our Staff</option>
|
<option value="internal" {{ 'selected' if handler_filter == 'internal' }}>Janitorial Staff</option>
|
||||||
<option value="facility" {{ 'selected' if handler_filter == 'facility' }}>Facility Staff</option>
|
<option value="facility" {{ 'selected' if handler_filter == 'facility' }}>Facility Staff</option>
|
||||||
<option value="vendor" {{ 'selected' if handler_filter == 'vendor' }}>External Vendor</option>
|
<option value="vendor" {{ 'selected' if handler_filter == 'vendor' }}>External Vendor</option>
|
||||||
</select>
|
</select>
|
||||||
|
|||||||
@@ -76,11 +76,11 @@
|
|||||||
<dt class="col-sm-3">Handled By</dt>
|
<dt class="col-sm-3">Handled By</dt>
|
||||||
<dd class="col-sm-9">
|
<dd class="col-sm-9">
|
||||||
{% if issue.handler_type == 'facility' %}
|
{% if issue.handler_type == 'facility' %}
|
||||||
<span class="badge bg-info text-dark"><i class="bi bi-building me-1"></i>Facility Staff</span>
|
<span class="badge bg-info text-dark" title="The facility's own on-site staff handle it."><i class="bi bi-building me-1"></i>Facility Staff</span>
|
||||||
{% elif issue.handler_type == 'vendor' %}
|
{% elif issue.handler_type == 'vendor' %}
|
||||||
<span class="badge bg-warning text-dark"><i class="bi bi-person-gear me-1"></i>External Vendor</span>
|
<span class="badge bg-warning text-dark" title="An outside contractor handles it."><i class="bi bi-person-gear me-1"></i>External Vendor</span>
|
||||||
{% else %}
|
{% else %}
|
||||||
<span class="badge bg-primary"><i class="bi bi-people me-1"></i>Our Staff</span>
|
<span class="badge bg-primary" title="Our janitorial crew handles it."><i class="bi bi-people me-1"></i>Janitorial Staff</span>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</dd>
|
</dd>
|
||||||
|
|
||||||
@@ -373,6 +373,7 @@
|
|||||||
<div class="mb-3">
|
<div class="mb-3">
|
||||||
{{ form.handler_type.label(class="form-label fw-semibold") }}
|
{{ form.handler_type.label(class="form-label fw-semibold") }}
|
||||||
{{ form.handler_type(class="form-select", id="handler_type_select") }}
|
{{ form.handler_type(class="form-select", id="handler_type_select") }}
|
||||||
|
<div class="form-text" id="handler_desc"></div>
|
||||||
</div>
|
</div>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
@@ -549,6 +550,11 @@
|
|||||||
// ── "Handled By" — show the relevant sub-block (facility vs vendor) and
|
// ── "Handled By" — show the relevant sub-block (facility vs vendor) and
|
||||||
// relabel the assignee as a follow-up owner for facility/vendor. ──
|
// relabel the assignee as a follow-up owner for facility/vendor. ──
|
||||||
var handlerSelect = document.getElementById('handler_type_select');
|
var handlerSelect = document.getElementById('handler_type_select');
|
||||||
|
var HANDLER_DESC = {
|
||||||
|
'internal': 'Our janitorial crew handles it.',
|
||||||
|
'facility': "The facility's own on-site staff handle it.",
|
||||||
|
'vendor': 'An outside contractor handles it.'
|
||||||
|
};
|
||||||
function syncHandlerUI() {
|
function syncHandlerUI() {
|
||||||
if (!handlerSelect) { return; }
|
if (!handlerSelect) { return; }
|
||||||
var v = handlerSelect.value;
|
var v = handlerSelect.value;
|
||||||
@@ -557,6 +563,9 @@
|
|||||||
if (facBlock) { facBlock.style.display = (v === 'facility') ? '' : 'none'; }
|
if (facBlock) { facBlock.style.display = (v === 'facility') ? '' : 'none'; }
|
||||||
if (venBlock) { venBlock.style.display = (v === 'vendor') ? '' : 'none'; }
|
if (venBlock) { venBlock.style.display = (v === 'vendor') ? '' : 'none'; }
|
||||||
|
|
||||||
|
var desc = document.getElementById('handler_desc');
|
||||||
|
if (desc) { desc.textContent = HANDLER_DESC[v] || ''; }
|
||||||
|
|
||||||
var label = document.getElementById('assigned_to_label');
|
var label = document.getElementById('assigned_to_label');
|
||||||
var help = document.getElementById('assigned_to_help');
|
var help = document.getElementById('assigned_to_help');
|
||||||
if (label) {
|
if (label) {
|
||||||
|
|||||||
+2
-2
@@ -173,7 +173,7 @@ class IssueForm(FlaskForm):
|
|||||||
assigned_to = SelectField('Assign To', coerce=int, validators=[Optional()])
|
assigned_to = SelectField('Assign To', coerce=int, validators=[Optional()])
|
||||||
# Who handles the issue (phase35) — set at creation by staff
|
# Who handles the issue (phase35) — set at creation by staff
|
||||||
handler_type = SelectField('Handled By', choices=[
|
handler_type = SelectField('Handled By', choices=[
|
||||||
('internal', 'Our Staff'),
|
('internal', 'Janitorial Staff'),
|
||||||
('facility', 'Facility Staff'),
|
('facility', 'Facility Staff'),
|
||||||
('vendor', 'External Vendor'),
|
('vendor', 'External Vendor'),
|
||||||
], validators=[Optional()])
|
], validators=[Optional()])
|
||||||
@@ -199,7 +199,7 @@ class IssueUpdateForm(FlaskForm):
|
|||||||
])
|
])
|
||||||
# Who handles the issue (phase35)
|
# Who handles the issue (phase35)
|
||||||
handler_type = SelectField('Handled By', choices=[
|
handler_type = SelectField('Handled By', choices=[
|
||||||
('internal', 'Our Staff'),
|
('internal', 'Janitorial Staff'),
|
||||||
('facility', 'Facility Staff'),
|
('facility', 'Facility Staff'),
|
||||||
('vendor', 'External Vendor'),
|
('vendor', 'External Vendor'),
|
||||||
], validators=[Optional()])
|
], validators=[Optional()])
|
||||||
|
|||||||
@@ -68,9 +68,9 @@ notified immediately. You'll see a confirmation message when it's received.
|
|||||||
When you view an issue, it now shows **Handled By**, indicating who is
|
When you view an issue, it now shows **Handled By**, indicating who is
|
||||||
responsible for resolving it:
|
responsible for resolving it:
|
||||||
|
|
||||||
- **Our Staff** — a member of the janitorial quality-control team.
|
- **Janitorial Staff** — our janitorial crew handles it.
|
||||||
- **Facility Staff** — the facility's own on-site staff are handling it.
|
- **Facility Staff** — the facility's own on-site staff handle it.
|
||||||
- **External Vendor** — an outside contractor has been engaged.
|
- **External Vendor** — an outside contractor handles it.
|
||||||
|
|
||||||
In every case, one of our team members remains the **follow-up owner** who
|
In every case, one of our team members remains the **follow-up owner** who
|
||||||
verifies the work and updates the issue. You do not set this field — it is
|
verifies the work and updates the issue. You do not set this field — it is
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ unchanged:
|
|||||||
|
|
||||||
- **Scheduled inspections** — created and executed through the web app. The iPad
|
- **Scheduled inspections** — created and executed through the web app. The iPad
|
||||||
app has no scheduled-inspection list or "Start from schedule" action.
|
app has no scheduled-inspection list or "Start from schedule" action.
|
||||||
- **Issue "Handled By" (Our Staff / Facility Staff / External Vendor)** — set and
|
- **Issue "Handled By" (Janitorial Staff / Facility Staff / External Vendor)** — set and
|
||||||
displayed on the web only. The mobile issue screens are unchanged.
|
displayed on the web only. The mobile issue screens are unchanged.
|
||||||
- **Facility QR codes / occupant report-a-problem** — a public web page; not part
|
- **Facility QR codes / occupant report-a-problem** — a public web page; not part
|
||||||
of the inspector app.
|
of the inspector app.
|
||||||
|
|||||||
@@ -61,8 +61,8 @@ who follows up:
|
|||||||
|
|
||||||
| Handled By | Meaning |
|
| Handled By | Meaning |
|
||||||
|---|---|
|
|---|---|
|
||||||
| **Our Staff** | A JQC team member resolves it. |
|
| **Janitorial Staff** | Our janitorial crew resolves it. |
|
||||||
| **Facility Staff** | The facility's own staff handle it (their contact is recorded on the issue). |
|
| **Facility Staff** | The facility's own on-site staff handle it (their contact is recorded on the issue). |
|
||||||
| **External Vendor** | An outside contractor handles it (vendor details are recorded on the issue). |
|
| **External Vendor** | An outside contractor handles it (vendor details are recorded on the issue). |
|
||||||
|
|
||||||
Regardless of who does the work, **one of our staff is always the follow-up
|
Regardless of who does the work, **one of our staff is always the follow-up
|
||||||
|
|||||||
Reference in New Issue
Block a user