{% extends "base.html" %} {% block media %} {{ form.media.css }} {% endblock %} {% block js_media %} {{ form.media.js }} <script src="{{ static('libs/featherlight/featherlight.min.js') }}" type="text/javascript"></script> <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-o').addClass('fa-exclamation-circle'); else $status.removeClass('fa-exclamation-circle').addClass('fa-check-circle-o'); $('.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-o{% 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 %} {% block bodyend %} {{ super() }} {% include "comments/math.html" %} {% endblock %}