Refactor HTML structure and indentation in trainees bulk update template for improved readability
This commit is contained in:
@@ -1,93 +1,93 @@
|
||||
{% extends 'generic/base.html' %}
|
||||
|
||||
{% block content %}
|
||||
<h2>Bulk update trainees (paste spreadsheet text)</h2>
|
||||
<h2>Bulk update trainees (paste spreadsheet text)</h2>
|
||||
|
||||
<p>Paste the spreadsheet rows below. Headings like "Year 1 - Group 1" are used to set the grade (Year N -> STN). Rows should contain "Name <tab or 2+spaces> Supervisor".</p>
|
||||
<p>Paste the spreadsheet rows below. Headings like "Year 1 - Group 1" are used to set the grade (Year N -> STN). Rows should contain "Name <tab or 2+spaces> Supervisor".</p>
|
||||
|
||||
<form method="post">
|
||||
{% csrf_token %}
|
||||
<textarea name="data" rows="18" style="width:100%">{% if request.POST.data %}{{ request.POST.data }}{% endif %}</textarea>
|
||||
<div style="margin-top:8px">
|
||||
<button type="submit" name="action" value="preview" class="btn btn-primary">Preview</button>
|
||||
<button type="submit" name="action" value="apply" class="btn btn-danger" onclick="return confirm('This will apply updates to matched trainee profiles. Are you sure?')">Apply updates</button>
|
||||
</div>
|
||||
</form>
|
||||
<form method="post">
|
||||
{% csrf_token %}
|
||||
<textarea name="data" rows="18" style="width:100%">{% if request.POST.data %}{{ request.POST.data }}{% endif %}</textarea>
|
||||
<div style="margin-top:8px">
|
||||
<button type="submit" name="action" value="preview" class="btn btn-primary">Preview</button>
|
||||
<button type="submit" name="action" value="apply" class="btn btn-danger" onclick="return confirm('This will apply updates to matched trainee profiles. Are you sure?')">Apply updates</button>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
{% if preview %}
|
||||
<h3>Preview ({{ preview|length }} rows)</h3>
|
||||
<table class="table table-sm">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Raw</th>
|
||||
<th>Name</th>
|
||||
<th>Grade</th>
|
||||
<th>Matched user</th>
|
||||
<th>Supervisor text</th>
|
||||
<th>Matched supervisor</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% for r in preview %}
|
||||
<tr>
|
||||
<td><pre style="margin:0">{{ r.raw }}</pre></td>
|
||||
<td>{{ r.norm_name }}</td>
|
||||
<td>{{ r.grade }}</td>
|
||||
<td>
|
||||
{% if r.matched_user %}
|
||||
<a href="{% url 'account_profile' r.matched_user.username %}">{{ r.matched_user.first_name }} {{ r.matched_user.last_name }}</a>
|
||||
{% else %}
|
||||
<div>
|
||||
<span style="color:red">No match</span>
|
||||
<div>
|
||||
<form hx-get="{% url 'generic:user_search' %}" hx-target="#user-results-{{ r.row_index }}" hx-swap="innerHTML" onsubmit="return false;">
|
||||
<input type="text" name="q" id="user-search-input-{{ r.row_index }}" placeholder="Search users..." style="width:220px" />
|
||||
<input type="hidden" name="row" value="{{ r.row_index }}" />
|
||||
<button type="submit">Search</button>
|
||||
</form>
|
||||
</div>
|
||||
<div id="user-results-{{ r.row_index }}"></div>
|
||||
<input type="hidden" name="manual_user_{{ r.row_index }}" id="manual_user_{{ r.row_index }}" />
|
||||
</div>
|
||||
{% endif %}
|
||||
</td>
|
||||
<td>{{ r.supervisor_text }}</td>
|
||||
<td>{% if r.matched_supervisor %}<a href="{% url 'generic:supervisor_detail' r.matched_supervisor.pk %}">{{ r.matched_supervisor.name }}</a>{% else %}<span style="color:red">No match</span>{% endif %}</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
{% endif %}
|
||||
{% if preview %}
|
||||
<h3>Preview ({{ preview|length }} rows)</h3>
|
||||
<table class="table table-sm">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Raw</th>
|
||||
<th>Name</th>
|
||||
<th>Grade</th>
|
||||
<th>Matched user</th>
|
||||
<th>Supervisor text</th>
|
||||
<th>Matched supervisor</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% for r in preview %}
|
||||
<tr>
|
||||
<td><pre style="margin:0">{{ r.raw }}</pre></td>
|
||||
<td>{{ r.norm_name }}</td>
|
||||
<td>{{ r.grade }}</td>
|
||||
<td>
|
||||
{% if r.matched_user %}
|
||||
<a href="{% url 'account_profile' r.matched_user.username %}">{{ r.matched_user.first_name }} {{ r.matched_user.last_name }}</a>
|
||||
{% else %}
|
||||
<div>
|
||||
<span style="color:red">No match</span>
|
||||
<div>
|
||||
<form hx-get="{% url 'generic:user_search' %}" hx-target="#user-results-{{ r.row_index }}" hx-swap="innerHTML" onsubmit="return false;">
|
||||
<input type="text" name="q" id="user-search-input-{{ r.row_index }}" placeholder="Search users..." style="width:220px" />
|
||||
<input type="hidden" name="row" value="{{ r.row_index }}" />
|
||||
<button type="submit">Search</button>
|
||||
</form>
|
||||
</div>
|
||||
<div id="user-results-{{ r.row_index }}"></div>
|
||||
<input type="hidden" name="manual_user_{{ r.row_index }}" id="manual_user_{{ r.row_index }}" />
|
||||
</div>
|
||||
{% endif %}
|
||||
</td>
|
||||
<td>{{ r.supervisor_text }}</td>
|
||||
<td>{% if r.matched_supervisor %}<a href="{% url 'generic:supervisor_detail' r.matched_supervisor.pk %}">{{ r.matched_supervisor.name }}</a>{% else %}<span style="color:red">No match</span>{% endif %}</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
{% endif %}
|
||||
|
||||
{% if report %}
|
||||
<h3>Apply report</h3>
|
||||
<p>Updated: {{ report.updated }}; Skipped (no user matched): {{ report.skipped }}</p>
|
||||
{% endif %}
|
||||
{% if report %}
|
||||
<h3>Apply report</h3>
|
||||
<p>Updated: {{ report.updated }}; Skipped (no user matched): {{ report.skipped }}</p>
|
||||
{% endif %}
|
||||
|
||||
{% endblock %}
|
||||
|
||||
{% block extra_scripts %}
|
||||
<script>
|
||||
{% block js %}
|
||||
<script>
|
||||
// Called from the HTMX-rendered results fragment to set the manual selection
|
||||
function setManualUser(rowIndex, id, text) {
|
||||
const hiddenInput = document.getElementById('manual_user_' + rowIndex);
|
||||
const resultsDiv = document.getElementById('user-results-' + rowIndex);
|
||||
if (hiddenInput) {
|
||||
hiddenInput.value = id;
|
||||
}
|
||||
if (resultsDiv) {
|
||||
resultsDiv.innerHTML = '<div>Selected: ' + escapeHtml(text) + '</div>';
|
||||
}
|
||||
}
|
||||
function setManualUser(rowIndex, id, text) {
|
||||
const hiddenInput = document.getElementById('manual_user_' + rowIndex);
|
||||
const resultsDiv = document.getElementById('user-results-' + rowIndex);
|
||||
if (hiddenInput) {
|
||||
hiddenInput.value = id;
|
||||
}
|
||||
if (resultsDiv) {
|
||||
resultsDiv.innerHTML = '<div>Selected: ' + escapeHtml(text) + '</div>';
|
||||
}
|
||||
}
|
||||
|
||||
function escapeHtml(unsafe) {
|
||||
if (!unsafe) return '';
|
||||
return String(unsafe)
|
||||
.replace(/&/g, "&")
|
||||
.replace(/</g, "<")
|
||||
.replace(/>/g, ">")
|
||||
.replace(/\"/g, """)
|
||||
.replace(/'/g, "'");
|
||||
}
|
||||
</script>
|
||||
function escapeHtml(unsafe) {
|
||||
if (!unsafe) return '';
|
||||
return String(unsafe)
|
||||
.replace(/&/g, "&")
|
||||
.replace(/</g, "<")
|
||||
.replace(/>/g, ">")
|
||||
.replace(/\"/g, """)
|
||||
.replace(/'/g, "'");
|
||||
}
|
||||
</script>
|
||||
{% endblock %}
|
||||
|
||||
Reference in New Issue
Block a user