Jul 26 - Update scheduled inspection settings (weekly/monthly)
This commit is contained in:
@@ -48,7 +48,7 @@
|
||||
<div class="table-responsive">
|
||||
<table class="table table-sm table-hover mb-0 align-middle">
|
||||
<thead class="table-light">
|
||||
<tr><th>Facility</th><th>Template</th><th>Inspector</th><th>Due</th><th></th></tr>
|
||||
<tr><th>Facility</th><th>Template</th><th>Inspector</th><th>Repeats</th><th>Due</th><th></th></tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% for s in sched_upcoming %}
|
||||
@@ -56,13 +56,21 @@
|
||||
<td>{{ s.facility.name if s.facility else '—' }}</td>
|
||||
<td class="small">{{ s.template.name if s.template else '—' }}</td>
|
||||
<td class="small">{{ s.inspector.display_name if s.inspector else '—' }}</td>
|
||||
<td class="small text-muted">{{ s.recurrence_label }}</td>
|
||||
<td class="small">{{ s.next_due_date.strftime('%b %d') }}</td>
|
||||
<td class="text-end">
|
||||
{# Start is shown only to the assignee — the inspection is theirs to do. #}
|
||||
{% if s.inspector_id and s.inspector_id == current_user.id %}
|
||||
{% set open_id = sched_open_inspections.get(s.id) %}
|
||||
{% if open_id %}
|
||||
<a href="{{ url_for('inspections.execute', inspection_id=open_id) }}"
|
||||
class="btn btn-sm btn-warning py-0" title="You already started this — resume it">
|
||||
<i class="bi bi-pencil-square"></i> Continue</a>
|
||||
{% else %}
|
||||
<a href="{{ url_for('scheduled_inspections.start', schedule_id=s.id) }}"
|
||||
class="btn btn-sm btn-success py-0"><i class="bi bi-play-fill"></i> Start</a>
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
|
||||
@@ -49,6 +49,64 @@
|
||||
{{ form.next_due_date.label(class="form-label fw-semibold") }}
|
||||
{{ form.next_due_date(class="form-control", type="date") }}
|
||||
{% for e in form.next_due_date.errors %}<div class="text-danger small">{{ e }}</div>{% endfor %}
|
||||
<div class="form-text">Snapped forward to the first matching day.</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{# ── Weekly: which days of the week ──────────────────────────── #}
|
||||
<div class="mb-3 p-3 rounded bg-light border" id="weekly_block" hidden>
|
||||
<label class="form-label fw-semibold d-block">{{ form.weekdays.label.text }}</label>
|
||||
<div class="d-flex flex-wrap gap-3">
|
||||
{% for value, label in form.weekdays.choices %}
|
||||
<div class="form-check">
|
||||
<input class="form-check-input" type="checkbox" name="weekdays"
|
||||
id="weekday_{{ value }}" value="{{ value }}"
|
||||
{% if form.weekdays.data and value in form.weekdays.data %}checked{% endif %}>
|
||||
<label class="form-check-label" for="weekday_{{ value }}">{{ label[:3] }}</label>
|
||||
</div>
|
||||
{% endfor %}
|
||||
</div>
|
||||
{% for e in form.weekdays.errors %}<div class="text-danger small">{{ e }}</div>{% endfor %}
|
||||
<div class="form-text mb-0">
|
||||
Pick every day the inspection recurs — e.g. Mon, Wed, Fri gives three
|
||||
inspections a week. The due date rolls to the next selected day each
|
||||
time one is submitted.
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{# ── Monthly: day-of-month OR nth weekday ────────────────────── #}
|
||||
<div class="mb-3 p-3 rounded bg-light border" id="monthly_block" hidden>
|
||||
<label class="form-label fw-semibold d-block">{{ form.month_mode.label.text }}</label>
|
||||
|
||||
<div class="form-check">
|
||||
<input class="form-check-input" type="radio" name="month_mode"
|
||||
id="month_mode_day" value="day_of_month"
|
||||
{% if form.month_mode.data != 'nth_weekday' %}checked{% endif %}>
|
||||
<label class="form-check-label" for="month_mode_day">On a day of the month</label>
|
||||
</div>
|
||||
<div class="ms-4 mb-2" id="dom_row">
|
||||
<div class="input-group input-group-sm" style="max-width:16rem;">
|
||||
<span class="input-group-text">Day</span>
|
||||
{{ form.day_of_month(class="form-control", type="number", min=1, max=31,
|
||||
placeholder="15") }}
|
||||
</div>
|
||||
{% for e in form.day_of_month.errors %}<div class="text-danger small">{{ e }}</div>{% endfor %}
|
||||
<div class="form-text mb-0">Months without that day use their last day.</div>
|
||||
</div>
|
||||
|
||||
<div class="form-check">
|
||||
<input class="form-check-input" type="radio" name="month_mode"
|
||||
id="month_mode_nth" value="nth_weekday"
|
||||
{% if form.month_mode.data == 'nth_weekday' %}checked{% endif %}>
|
||||
<label class="form-check-label" for="month_mode_nth">On a weekday of the month</label>
|
||||
</div>
|
||||
<div class="ms-4" id="nth_row">
|
||||
<div class="d-flex gap-2 flex-wrap" style="max-width:24rem;">
|
||||
{{ form.nth_week(class="form-select form-select-sm", style="max-width:7rem;") }}
|
||||
{{ form.nth_weekday(class="form-select form-select-sm", style="max-width:11rem;") }}
|
||||
</div>
|
||||
{% for e in form.nth_week.errors %}<div class="text-danger small">{{ e }}</div>{% endfor %}
|
||||
<div class="form-text mb-0">e.g. the 2nd Tuesday of every month.</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -129,5 +187,40 @@
|
||||
setPlaceholder();
|
||||
}
|
||||
}());
|
||||
|
||||
// Recurrence blocks: only the one matching the chosen frequency is shown.
|
||||
// The server clears the columns for the hidden blocks on save, so stale values
|
||||
// left in the DOM never take effect.
|
||||
(function () {
|
||||
'use strict';
|
||||
var freq = document.getElementById('frequency') ||
|
||||
document.querySelector('[name="frequency"]');
|
||||
var weekly = document.getElementById('weekly_block');
|
||||
var monthly = document.getElementById('monthly_block');
|
||||
if (!freq || !weekly || !monthly) { return; }
|
||||
|
||||
var domRadio = document.getElementById('month_mode_day');
|
||||
var nthRadio = document.getElementById('month_mode_nth');
|
||||
var domRow = document.getElementById('dom_row');
|
||||
var nthRow = document.getElementById('nth_row');
|
||||
|
||||
function syncMonthMode() {
|
||||
var useNth = nthRadio && nthRadio.checked;
|
||||
domRow.style.opacity = useNth ? '.45' : '1';
|
||||
nthRow.style.opacity = useNth ? '1' : '.45';
|
||||
}
|
||||
|
||||
function syncFrequency() {
|
||||
weekly.hidden = freq.value !== 'weekly';
|
||||
monthly.hidden = freq.value !== 'monthly';
|
||||
syncMonthMode();
|
||||
}
|
||||
|
||||
freq.addEventListener('change', syncFrequency);
|
||||
[domRadio, nthRadio].forEach(function (r) {
|
||||
if (r) { r.addEventListener('change', syncMonthMode); }
|
||||
});
|
||||
syncFrequency();
|
||||
}());
|
||||
</script>
|
||||
{% endblock %}
|
||||
|
||||
@@ -43,7 +43,7 @@
|
||||
<td><strong>{{ s.facility.name if s.facility else '—' }}</strong></td>
|
||||
<td>{{ s.template.name if s.template else '—' }}</td>
|
||||
<td>{{ s.inspector.display_name if s.inspector else '— Unassigned —' }}</td>
|
||||
<td><span class="badge bg-secondary">{{ s.frequency_label }}</span></td>
|
||||
<td><span class="badge bg-secondary">{{ s.recurrence_label }}</span></td>
|
||||
<td>
|
||||
{{ s.next_due_date.strftime('%b %d, %Y') }}
|
||||
{% if overdue %}
|
||||
@@ -62,11 +62,19 @@
|
||||
<td class="text-end text-nowrap">
|
||||
{# Start is shown only to the assignee — the inspection is theirs to do. #}
|
||||
{% if s.active and s.inspector_id and s.inspector_id == current_user.id %}
|
||||
{% set open_id = open_inspections.get(s.id) %}
|
||||
{% if open_id %}
|
||||
<a href="{{ url_for('inspections.execute', inspection_id=open_id) }}"
|
||||
class="btn btn-sm btn-warning" title="You already started this — resume it">
|
||||
<i class="bi bi-pencil-square"></i> Continue
|
||||
</a>
|
||||
{% else %}
|
||||
<a href="{{ url_for('scheduled_inspections.start', schedule_id=s.id) }}"
|
||||
class="btn btn-sm btn-success" title="Start this inspection">
|
||||
<i class="bi bi-play-fill"></i> Start
|
||||
</a>
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
{% if current_user.role in ['admin','director','project_manager','auditor'] %}
|
||||
<a href="{{ url_for('scheduled_inspections.edit', schedule_id=s.id) }}"
|
||||
class="btn btn-sm btn-outline-primary"><i class="bi bi-pencil"></i></a>
|
||||
|
||||
Reference in New Issue
Block a user