Aug 7 - Update: add external inspector
This commit is contained in:
@@ -80,7 +80,20 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
{# MT-15 — an External Inspector is invited by email and chooses
|
||||
their own password, so the admin never sets one. The JS at the
|
||||
foot of this page swaps these two blocks when the role changes;
|
||||
the server decides independently of the JS. #}
|
||||
<div id="inviteNotice" class="alert alert-info d-none">
|
||||
<i class="bi bi-envelope me-1"></i>
|
||||
<strong>This account will be invited by email.</strong>
|
||||
External inspectors work outside the business, so we do not set
|
||||
a password for them. On save, an invitation is sent to the email
|
||||
address above with a link to choose their own password. The link
|
||||
is valid for 72 hours.
|
||||
</div>
|
||||
|
||||
<div class="row" id="passwordFields">
|
||||
<div class="col-md-6 mb-3">
|
||||
{{ form.password.label(class="form-label") }}
|
||||
{{ form.password(class="form-control", placeholder="Leave blank to keep current" if user else "") }}
|
||||
@@ -128,4 +141,27 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
(function () {
|
||||
'use strict';
|
||||
var roleSel = document.getElementById('role');
|
||||
var pwBlock = document.getElementById('passwordFields');
|
||||
var notice = document.getElementById('inviteNotice');
|
||||
if (!roleSel || !pwBlock || !notice) return; // director view has no role select
|
||||
|
||||
function sync() {
|
||||
var invited = roleSel.value === 'external_inspector';
|
||||
pwBlock.classList.toggle('d-none', invited);
|
||||
notice.classList.toggle('d-none', !invited);
|
||||
// Clear anything already typed so an invited account can never be created
|
||||
// with an admin-chosen password sitting in the POST body.
|
||||
if (invited) {
|
||||
pwBlock.querySelectorAll('input').forEach(function (i) { i.value = ''; });
|
||||
}
|
||||
}
|
||||
roleSel.addEventListener('change', sync);
|
||||
sync();
|
||||
})();
|
||||
</script>
|
||||
{% endblock %}
|
||||
@@ -37,12 +37,12 @@
|
||||
<td>{{ user.full_name or '—' }}</td>
|
||||
<td>{{ user.email }}</td>
|
||||
<td>
|
||||
<span class="badge bg-{% if user.role == 'admin' %}danger{% elif user.role == 'director' %}warning{% elif user.role == 'project_manager' %}primary{% elif user.role == 'auditor' %}secondary{% elif user.role == 'customer' %}success{% else %}info{% endif %}">
|
||||
{{ user.role.replace('_',' ')|title }}
|
||||
<span class="badge bg-{% if user.role == 'admin' %}danger{% elif user.role == 'director' %}warning{% elif user.role == 'project_manager' %}primary{% elif user.role == 'auditor' %}secondary{% elif user.role == 'customer' %}success{% elif user.role == 'external_inspector' %}dark{% else %}info{% endif %}">
|
||||
{{ user.role_label }}
|
||||
</span>
|
||||
</td>
|
||||
<td>
|
||||
{% if user.role == 'inspector' %}
|
||||
{% if user.is_inspector %}
|
||||
{% set cnt = inspector_contract_counts.get(user.id, 0) %}
|
||||
{% if cnt > 0 %}
|
||||
<span class="badge bg-success">{{ cnt }} contract{{ 's' if cnt != 1 else '' }}</span>
|
||||
@@ -65,12 +65,23 @@
|
||||
<a href="{{ url_for('auth.edit_user', user_id=user.id) }}" class="btn btn-sm btn-outline-primary" title="Edit">
|
||||
<i class="bi bi-pencil"></i>
|
||||
</a>
|
||||
{% if user.role == 'inspector' %}
|
||||
{% if user.is_inspector %}
|
||||
<a href="{{ url_for('auth.assign_inspector_contracts', user_id=user.id) }}"
|
||||
class="btn btn-sm btn-outline-secondary" title="Assign contracts">
|
||||
<i class="bi bi-briefcase"></i>
|
||||
</a>
|
||||
{% endif %}
|
||||
{% if not user.password_set %}
|
||||
<form method="POST" action="{{ url_for('auth.resend_invite', user_id=user.id) }}"
|
||||
class="d-inline"
|
||||
onsubmit="return confirm('Resend the invitation email to {{ user.email }}? The previous link will stop working.');">
|
||||
<input type="hidden" name="csrf_token" value="{{ csrf_token() }}">
|
||||
<button type="submit" class="btn btn-sm btn-outline-warning"
|
||||
title="Resend invitation email">
|
||||
<i class="bi bi-envelope-arrow-up"></i>
|
||||
</button>
|
||||
</form>
|
||||
{% endif %}
|
||||
{% if user.id != current_user.id %}
|
||||
<form method="POST" action="{{ url_for('auth.toggle_active', user_id=user.id) }}" class="d-inline">
|
||||
<input type="hidden" name="csrf_token" value="{{ csrf_token() }}">
|
||||
|
||||
Reference in New Issue
Block a user