05/22 Enhance codes and fix bugs 2

This commit is contained in:
2026-05-22 14:18:21 -04:00
parent 3511ac2b56
commit 12b5fd9ce0
12 changed files with 235 additions and 11 deletions
+41 -5
View File
@@ -52,28 +52,64 @@
</div>
<div class="card-body p-0">
{% if my_tickets %}
<div class="table-responsive">
<table class="table mb-0">
<thead>
<tr>
<th>Ticket #</th>
<th>Title</th>
<th>Status</th>
<th>Progress</th>
<th>Priority</th>
<th>Date</th>
</tr>
</thead>
<tbody>
{% for t in my_tickets %}
{% set is_done = t.status in ('resolved', 'closed') %}
{% set is_overdue = t.due_date and not is_done and t.due_date < now %}
{% set stage = 0 %}
{% if t.status == 'in_progress' %}{% set stage = 1 %}{% endif %}
{% if t.status == 'pending' %}{% set stage = 2 %}{% endif %}
{% if is_done %}{% set stage = 3 %}{% endif %}
<tr style="cursor:pointer;" onclick="window.location='/tickets/{{ t.id }}'">
<td><span class="mono" style="font-size:12px;color:var(--accent3);">{{ t.ticket_number }}</span></td>
<td>{{ t.title[:45] }}{% if t.title|length > 45 %}…{% endif %}</td>
<td><span class="badge badge-{{ t.status }}">{{ t.status.replace('_',' ').upper() }}</span></td>
<td style="white-space:nowrap;">
<span class="mono" style="font-size:12px;color:var(--accent3);">{{ t.ticket_number }}</span>
</td>
<td>
<div style="font-size:13px;">
{{ t.title[:40] }}{% if t.title|length > 40 %}…{% endif %}
</div>
<div style="margin-top:3px;display:flex;gap:4px;flex-wrap:wrap;">
{% if is_overdue %}
<span style="font-size:10px;padding:1px 6px;border-radius:4px;background:rgba(220,38,38,.12);color:var(--danger);font-weight:600;">
<i class="bi bi-exclamation-triangle-fill" style="font-size:9px;"></i> Overdue
</span>
{% endif %}
{% if t.priority == 'critical' %}
<span style="font-size:10px;padding:1px 6px;border-radius:4px;background:rgba(220,38,38,.12);color:var(--danger);font-weight:600;">Critical</span>
{% elif t.priority == 'high' %}
<span style="font-size:10px;padding:1px 6px;border-radius:4px;background:rgba(217,119,6,.12);color:var(--warning);font-weight:600;">High</span>
{% endif %}
</div>
</td>
<td style="min-width:110px;">
<div style="font-size:10px;color:var(--muted);margin-bottom:4px;">
{{ t.status.replace('_',' ').title() }}
</div>
<div style="display:flex;gap:2px;">
{% for i in range(4) %}
<div style="height:4px;flex:1;border-radius:2px;
background:{% if i <= stage %}{% if is_overdue %}var(--danger){% elif is_done %}var(--success){% else %}var(--accent){% endif %}{% else %}var(--border2){% endif %};"></div>
{% endfor %}
</div>
</td>
<td><span class="badge badge-{{ t.priority }}">{{ t.priority.upper() }}</span></td>
<td style="font-size:12px;color:var(--muted);">{{ t.created_at | localtime("%b %d") }}</td>
<td style="font-size:12px;color:var(--muted);white-space:nowrap;">{{ t.created_at | localtime("%b %d") }}</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
{% else %}
<div class="p-5 text-center" style="color:var(--muted);">
<i class="bi bi-inbox" style="font-size:36px;display:block;margin-bottom:12px;"></i>
+4
View File
@@ -38,6 +38,7 @@
</div>
<div class="card-body p-0">
{% if my_tickets %}
<div class="table-responsive">
<table class="table mb-0">
<thead><tr><th>Ticket #</th><th>Title</th><th>Priority</th><th>Status</th></tr></thead>
<tbody>
@@ -51,6 +52,7 @@
{% endfor %}
</tbody>
</table>
</div>
{% else %}
<div class="p-4 text-center" style="color:var(--muted);font-size:13px;"><i class="bi bi-inbox" style="font-size:28px;display:block;margin-bottom:8px;"></i>No tickets assigned to you.</div>
{% endif %}
@@ -66,6 +68,7 @@
<a href="{{ url_for('admin.all_tickets') }}" style="font-size:12px;color:var(--accent3);">All tickets →</a>
</div>
<div class="card-body p-0">
<div class="table-responsive">
<table class="table mb-0">
<thead><tr><th>Ticket #</th><th>User</th><th>Priority</th><th>Status</th><th>Assignee</th></tr></thead>
<tbody>
@@ -86,6 +89,7 @@
{% endfor %}
</tbody>
</table>
</div>
</div>
</div>
</div>
+67 -4
View File
@@ -579,7 +579,7 @@ function buildCommentEl(c) {
<div class="card mb-3">
<div class="card-header"><i class="bi bi-pencil-square me-2"></i>Update Ticket</div>
<div class="card-body">
<form method="POST" action="{{ url_for('tickets.update_ticket', ticket_id=ticket.id) }}">
<form id="ticket-update-form" method="POST" action="{{ url_for('tickets.update_ticket', ticket_id=ticket.id) }}">
<input type="hidden" name="csrf_token" value="{{ csrf_token() }}"/>
<div class="mb-3">
<label class="form-label">Status</label>
@@ -623,10 +623,55 @@ function buildCommentEl(c) {
<textarea class="form-control" name="internal_notes" rows="2"
placeholder="Private notes for IT team…">{{ ticket.internal_notes or '' }}</textarea>
</div>
<button type="submit" class="btn btn-primary w-100">
<i class="bi bi-check2 me-2"></i>Save Changes
</button>
<div class="d-flex align-items-center gap-2">
<button type="submit" id="update-save-btn" class="btn btn-primary flex-grow-1">
<i class="bi bi-check2 me-2"></i>Save Changes
</button>
<span id="update-feedback" style="font-size:12px;display:none;"></span>
</div>
</form>
<script>
(function() {
const form = document.getElementById('ticket-update-form');
if (!form) return;
form.addEventListener('submit', function(e) {
e.preventDefault();
const btn = document.getElementById('update-save-btn');
const fb = document.getElementById('update-feedback');
btn.disabled = true;
btn.innerHTML = '<span class="spinner-border spinner-border-sm me-1"></span>Saving…';
fb.style.display = 'none';
fetch(form.action, {
method: 'POST',
headers: { 'X-Requested-With': 'XMLHttpRequest',
'X-CSRFToken': document.querySelector('meta[name="csrf-token"]').content },
body: new FormData(form)
})
.then(r => r.json())
.then(data => {
btn.disabled = false;
btn.innerHTML = '<i class="bi bi-check2 me-2"></i>Save Changes';
if (data.ok) {
fb.textContent = '✓ Saved';
fb.style.color = 'var(--success)';
fb.style.display = 'inline';
setTimeout(() => { fb.style.display = 'none'; }, 3000);
} else {
fb.textContent = 'Error saving';
fb.style.color = 'var(--danger)';
fb.style.display = 'inline';
}
})
.catch(() => {
btn.disabled = false;
btn.innerHTML = '<i class="bi bi-check2 me-2"></i>Save Changes';
fb.textContent = 'Network error';
fb.style.color = 'var(--danger)';
fb.style.display = 'inline';
});
});
})();
</script>
</div>
</div>
{% endif %}
@@ -728,6 +773,24 @@ function buildCommentEl(c) {
</div>
{% endif %}
<!-- Linked Tickets (read-only for employees) -->
{% if not current_user.is_it_staff and linked_tickets %}
<div class="card mb-3">
<div class="card-header"><i class="bi bi-link-45deg me-2"></i>Linked Tickets</div>
<div class="card-body" style="font-size:13px;">
{% for lnk, other in linked_tickets %}
<div class="d-flex align-items-center gap-2 mb-2"
style="padding:6px 8px;background:var(--surface2);border-radius:6px;border:1px solid var(--border);">
<a href="{{ url_for('tickets.ticket_detail', ticket_id=other.id) }}"
class="mono" style="font-size:11px;color:var(--accent3);flex-shrink:0;">{{ other.ticket_number }}</a>
<span style="font-size:10px;background:var(--border);color:var(--muted);padding:1px 6px;border-radius:4px;flex-shrink:0;">{{ lnk.link_type.replace('_',' ') }}</span>
<div style="font-size:12px;color:var(--muted);white-space:nowrap;overflow:hidden;text-overflow:ellipsis;min-width:0;">{{ other.title }}</div>
</div>
{% endfor %}
</div>
</div>
{% endif %}
<!-- Ticket Info -->
<div class="card mb-3">
<div class="card-header"><i class="bi bi-info-circle me-2"></i>Ticket Details</div>
+2
View File
@@ -59,6 +59,7 @@
</div>
<div class="card-body p-0">
{% if tickets.items %}
<div class="table-responsive">
<table class="table mb-0">
<thead>
<tr>
@@ -103,6 +104,7 @@
{% endfor %}
</tbody>
</table>
</div>
<!-- Pagination -->
{% if tickets.pages > 1 %}