NDOJ/templates/ticket/ticket.html
2024-06-24 19:42:50 -05:00

225 lines
7.5 KiB
HTML

{% extends "base.html" %}
{% block media %}
{{ form.media.css }}
{% endblock %}
{% block js_media %}
{{ form.media.js }}
<script type="text/javascript" src="{{ static('event.js') }}"></script>
<script type="text/javascript">
$(function () {
var $h2 = $('#content').find('> h2:first-child');
var $status = $h2.find('.status i'), $title = $h2.find('.title');
function update_ticket_state(open) {
if (open)
$status.removeClass('fa-check-circle').addClass('fa-exclamation-circle');
else
$status.removeClass('fa-exclamation-circle').addClass('fa-check-circle');
$('.close-ticket').toggle(open);
$('.open-ticket').toggle(!open);
}
$('.close-ticket, .open-ticket').click(function () {
var open = $(this).attr('data-open') == '1';
$.ajax({
url: $(this).attr('data-ajax'), type: 'POST',
success: function () {
update_ticket_state(open);
},
error: function (data) {
alert('Could not change ticket: ' + data.responseText);
}
});
});
$('.edit-notes').featherlight({
afterOpen: function () {
var $form = $('#edit-notes');
$form.find('.submit').click(function () {
$.post($form.attr('action'), $form.serialize()).done(function (data) {
$('#ticket-notes').find('.info-empty').toggle(!data).end().find('.info-real').html(data);
$.featherlight.current().close();
});
return false;
});
}
});
var page_ref_key = 'ticket:open:{{ ticket.id }}', page_close_key = page_ref_key + ':close';
var page_ref;
function increase_page_ref() {
if (page_ref_key in localStorage)
localStorage[page_ref_key] = page_ref = +localStorage[page_ref_key] + 1;
else
localStorage[page_ref_key] = page_ref = 1;
}
function decrease_page_ref() {
if (page_ref_key in localStorage) {
localStorage[page_close_key] = page_ref;
delete localStorage[page_close_key];
localStorage[page_ref_key] = +localStorage[page_ref_key] - 1;
}
page_ref = null;
}
function is_highest_ref() {
console.log(localStorage[page_ref_key], page_ref);
if (page_ref_key in localStorage)
return +localStorage[page_ref_key] == page_ref;
return true;
}
$(window).on('storage', function (e) {
e = e.originalEvent;
if (e.key == page_close_key && e.newValue !== null)
if (page_ref != null && page_ref > +e.newValue)
--page_ref;
});
register_notify('ticket', {
change: function (enabled) {
if (enabled)
increase_page_ref();
}
});
$(window).on('beforeunload', function () {
decrease_page_ref();
});
function ticket_status(ticket) {
update_ticket_state(ticket.open);
if (is_highest_ref())
notify('ticket', (ticket.open ? '{{ _('Reopened: ') }}' :
'{{ _('Closed: ') }}') + $title.text());
}
function ticket_message(ticket) {
$.ajax({
url: '{{ url('ticket_message_ajax', ticket.id) }}',
data: {message: ticket.message},
success: function (data) {
$('#messages').append($(data.message));
},
error: function (data) {
if (data.status === 403)
console.log('No right to see: ' + ticket.message);
else {
console.log('Could not load ticket message:');
console.log(data.responseText);
}
}
});
}
window.load_dynamic_update = function (last_msg) {
return new EventReceiver(
"{{ EVENT_DAEMON_LOCATION }}", "{{ EVENT_DAEMON_POLL_LOCATION }}",
['ticket-{{ ticket.id }}'], last_msg, function (message) {
switch (message.type) {
case 'ticket-status':
ticket_status(message);
break;
case 'ticket-message':
ticket_message(message);
break;
}
}
);
}
});
</script>
{% if last_msg %}
<script type="text/javascript">
$(function () {
load_dynamic_update({{last_msg}});
});
</script>
{% endif %}
{% endblock %}
{% block content_title %}
<span class="status">
<i class="fa {% if ticket.is_open %}fa-exclamation-circle{% else %}fa-check-circle{% endif %}"></i>
</span>
<span class="title">{{ ticket.title }}</span><small>#{{ ticket.id }}</small>
{% endblock %}
{% block body %}
<div class="ticket-container">
<div class="ticket-messages">
<main id="messages" class="messages">
{% for message in ticket_messages %}
{% include "ticket/message.html" %}
{% endfor %}
</main>
<hr>
<section class="message new-message">
<div class="info">
<a href="{{ url('user_page', request.user.username) }}" class="user">
<img loading="lazy" src="{{ gravatar(request.profile, 135) }}" class="gravatar">
<div class="username {{ request.profile.css_class }}">{{ request.user.username }}</div>
</a>
</div>
<div class="detail">
<form action="" method="post">
{% csrf_token %}
{% if form.non_field_errors() or form.body.errors %}
<div class="form-errors">
{{ form.non_field_errors() }}
{{ form.body.errors }}
</div>
{% endif %}
<div class="body-block">{{ form.body }}</div>
<button type="submit" class="submit">{{ _('Post') }}</button>
</form>
</div>
</section>
</div>
<aside class="ticket-sidebar">
<div class="ticket-info">
<div class="info-box">
<div class="info-title">{{ _('Associated object') }}</div>
<div class="info-data">
<a href="{{ ticket.linked_item.get_absolute_url() }}">{{ ticket.linked_item }}</a>
</div>
</div>
<div class="info-box">
<div class="info-title">{{ _('Assignees') }}</div>
<div class="info-data">
{% if assignees %}
{{ link_users(assignees) }}
{% else %}
<div class="info-empty">{{ _('No one is assigned.') }}</div>
{% endif %}
</div>
</div>
<button data-ajax="{{ url('ticket_close', ticket.id) }}" data-open="0" class="close-ticket"
{% if not ticket.is_open %}style="display: none"{% endif %}>{{ _('Close ticket') }}</button>
<button data-ajax="{{ url('ticket_open', ticket.id) }}" data-open="1" class="open-ticket"
{% if ticket.is_open %}style="display: none"{% endif %}>{{ _('Reopen ticket') }}</button>
{% if perms.judge.change_ticket or request.profile in assignees %}
<div class="info-box">
<div class="info-title">{{ _('Assignee notes') }}
<a href="#" data-featherlight="{{ url('ticket_notes', ticket.id) }}" class="edit-notes">
<i class="fa fa-pencil"></i>
</a>
</div>
<div id="ticket-notes" class="info-data">
<div{% if ticket.notes %} style="display: none"{% endif %} class="info-empty">
{{ _('Nothing here.') }}
</div>
<div class="info-real">{{ ticket.notes|linebreaks }}</div>
</div>
</div>
{% endif %}
</div>
</aside>
</div>
{% endblock %}