04/06 adding some additional functions
This commit is contained in:
@@ -179,6 +179,33 @@
|
||||
accept=".png,.jpg,.jpeg,.gif,.pdf,.doc,.docx,.txt,.zip,.log"/>
|
||||
</div>
|
||||
{% if current_user.is_it_staff %}
|
||||
<!-- Canned responses picker -->
|
||||
{% if canned_responses %}
|
||||
<div class="mb-3">
|
||||
<div class="dropdown">
|
||||
<button type="button" class="btn btn-secondary btn-sm dropdown-toggle"
|
||||
id="canned-responses-btn" data-bs-toggle="dropdown" aria-expanded="false">
|
||||
<i class="bi bi-chat-square-text me-1"></i>Quick Replies
|
||||
</button>
|
||||
<ul class="dropdown-menu" style="max-height:260px;overflow-y:auto;min-width:300px;">
|
||||
{% set ns = namespace(last_cat='') %}
|
||||
{% for r in canned_responses %}
|
||||
{% if r.category and r.category != ns.last_cat %}
|
||||
{% if ns.last_cat %}<li><hr class="dropdown-divider"/></li>{% endif %}
|
||||
<li><span class="dropdown-header" style="font-size:10px;text-transform:uppercase;letter-spacing:.5px;">{{ r.category }}</span></li>
|
||||
{% set ns.last_cat = r.category %}
|
||||
{% endif %}
|
||||
<li>
|
||||
<button type="button" class="dropdown-item" style="font-size:13px;white-space:normal;"
|
||||
onclick="insertCannedResponse({{ r.id }})">
|
||||
{{ r.title }}
|
||||
</button>
|
||||
</li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
<div class="mb-3 d-flex align-items-center gap-2">
|
||||
<input type="checkbox" id="is_internal" name="is_internal" style="accent-color:var(--warning);"/>
|
||||
<label for="is_internal" style="font-size:13px;color:var(--warning);margin:0;cursor:pointer;">
|
||||
@@ -196,6 +223,20 @@
|
||||
{% endif %}
|
||||
|
||||
<script>
|
||||
const CANNED_RESPONSES = {
|
||||
{% for r in canned_responses %}
|
||||
{{ r.id }}: {{ r.body | tojson }},
|
||||
{% endfor %}
|
||||
};
|
||||
function insertCannedResponse(id) {
|
||||
const body = CANNED_RESPONSES[id];
|
||||
if (!body) return;
|
||||
const ta = document.getElementById('comment-body');
|
||||
const cur = ta.value;
|
||||
ta.value = cur ? cur + '\n\n' + body : body;
|
||||
ta.focus();
|
||||
ta.setSelectionRange(ta.value.length, ta.value.length);
|
||||
}
|
||||
const TICKET_ID = {{ ticket.id }};
|
||||
const CURRENT_UID = {{ current_user.id }};
|
||||
const IS_IT_STAFF = {{ 'true' if current_user.is_it_staff else 'false' }};
|
||||
@@ -587,6 +628,69 @@ function buildCommentEl(c) {
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
<!-- Linked Tickets -->
|
||||
{% if current_user.is_it_staff %}
|
||||
<div class="card mb-3">
|
||||
<div class="card-header d-flex align-items-center justify-content-between">
|
||||
<span><i class="bi bi-link-45deg me-2"></i>Linked Tickets</span>
|
||||
<button class="btn btn-secondary btn-sm" type="button"
|
||||
data-bs-toggle="collapse" data-bs-target="#link-form-collapse"
|
||||
style="font-size:11px;">
|
||||
<i class="bi bi-plus me-1"></i>Link
|
||||
</button>
|
||||
</div>
|
||||
<div class="card-body" style="font-size:13px;">
|
||||
{% if linked_tickets %}
|
||||
{% for lnk, other in linked_tickets %}
|
||||
<div class="d-flex align-items-center justify-content-between mb-2"
|
||||
style="padding:6px 8px;background:var(--surface2);border-radius:6px;border:1px solid var(--border);">
|
||||
<div style="min-width:0;">
|
||||
<a href="{{ url_for('tickets.ticket_detail', ticket_id=other.id) }}"
|
||||
class="mono" style="font-size:11px;color:var(--accent3);">{{ other.ticket_number }}</a>
|
||||
<span style="font-size:10px;background:var(--border);color:var(--muted);padding:1px 6px;border-radius:4px;margin-left:4px;">{{ lnk.link_type.replace('_',' ') }}</span>
|
||||
<div style="font-size:12px;color:var(--muted);white-space:nowrap;overflow:hidden;text-overflow:ellipsis;">{{ other.title }}</div>
|
||||
</div>
|
||||
<form method="POST"
|
||||
action="{{ url_for('tickets.unlink_ticket', ticket_id=ticket.id, link_id=lnk.id) }}"
|
||||
onsubmit="return confirm('Remove this link?')" style="margin:0;flex-shrink:0;">
|
||||
<input type="hidden" name="csrf_token" value="{{ csrf_token() }}"/>
|
||||
<button type="submit" class="btn btn-sm" title="Remove link"
|
||||
style="background:none;border:none;color:var(--muted);padding:2px 6px;">
|
||||
<i class="bi bi-x-lg"></i>
|
||||
</button>
|
||||
</form>
|
||||
</div>
|
||||
{% endfor %}
|
||||
{% else %}
|
||||
<p style="color:var(--muted);font-size:12px;margin:0;">No linked tickets yet.</p>
|
||||
{% endif %}
|
||||
|
||||
<!-- Link form (collapsed by default) -->
|
||||
<div class="collapse mt-3" id="link-form-collapse">
|
||||
<form method="POST" action="{{ url_for('tickets.link_ticket', ticket_id=ticket.id) }}">
|
||||
<input type="hidden" name="csrf_token" value="{{ csrf_token() }}"/>
|
||||
<div class="mb-2">
|
||||
<label class="form-label" style="font-size:12px;">Ticket ID or Number</label>
|
||||
<input type="number" class="form-control form-control-sm"
|
||||
name="linked_ticket_id" placeholder="e.g. 42" required min="1"/>
|
||||
</div>
|
||||
<div class="mb-2">
|
||||
<label class="form-label" style="font-size:12px;">Relationship</label>
|
||||
<select class="form-select form-select-sm" name="link_type">
|
||||
<option value="related">Related</option>
|
||||
<option value="duplicate">Duplicate</option>
|
||||
<option value="follow_up">Follow-up</option>
|
||||
</select>
|
||||
</div>
|
||||
<button type="submit" class="btn btn-primary btn-sm w-100">
|
||||
<i class="bi bi-link-45deg me-1"></i>Create Link
|
||||
</button>
|
||||
</form>
|
||||
</div>
|
||||
</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>
|
||||
@@ -647,4 +751,53 @@ function buildCommentEl(c) {
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Re-open modal trigger — shown to ticket creator when resolved or closed -->
|
||||
{% if ticket.status in ('resolved', 'closed') and
|
||||
(current_user.is_it_staff or ticket.created_by_id == current_user.id) %}
|
||||
<div class="card mt-4" style="border-color:var(--warning);max-width:760px;">
|
||||
<div class="card-body d-flex align-items-center gap-3" style="padding:16px 20px;">
|
||||
<i class="bi bi-arrow-repeat" style="font-size:22px;color:var(--warning);flex-shrink:0;"></i>
|
||||
<div style="flex:1;">
|
||||
<div style="font-weight:600;font-size:14px;">Has this issue returned?</div>
|
||||
<div style="font-size:12px;color:var(--muted);margin-top:2px;">
|
||||
Re-open this ticket to notify IT staff and resume tracking.
|
||||
</div>
|
||||
</div>
|
||||
<button type="button" class="btn btn-outline-warning btn-sm"
|
||||
data-bs-toggle="modal" data-bs-target="#reopen-modal">
|
||||
<i class="bi bi-arrow-repeat me-1"></i>Re-open Ticket
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Re-open modal -->
|
||||
<div class="modal fade" id="reopen-modal" tabindex="-1">
|
||||
<div class="modal-dialog modal-dialog-centered">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h5 class="modal-title"><i class="bi bi-arrow-repeat me-2"></i>Re-open Ticket</h5>
|
||||
<button type="button" class="btn-close" data-bs-dismiss="modal"></button>
|
||||
</div>
|
||||
<form method="POST" action="{{ url_for('tickets.reopen_ticket', ticket_id=ticket.id) }}">
|
||||
<input type="hidden" name="csrf_token" value="{{ csrf_token() }}"/>
|
||||
<div class="modal-body">
|
||||
<p style="font-size:13px;color:var(--muted);">
|
||||
Please describe why the issue has returned. This will be posted as a comment
|
||||
and IT staff will be notified immediately.
|
||||
</p>
|
||||
<textarea class="form-control" name="reopen_reason" rows="4" required
|
||||
placeholder="e.g. The problem came back after the weekend restart. The error message is now different: …"></textarea>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Cancel</button>
|
||||
<button type="submit" class="btn btn-warning">
|
||||
<i class="bi bi-arrow-repeat me-1"></i>Re-open & Notify IT
|
||||
</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
{% endblock %}
|
||||
Reference in New Issue
Block a user