PHP Classes

File: templates/admin/echomail_moderation.twig

Recommend this page to a friend!
  Packages of Matthew Asham   Binkterm PHP   templates/admin/echomail_moderation.twig   Download  
File: templates/admin/echomail_moderation.twig
Role: Auxiliary data
Content type: text/plain
Description: Auxiliary data
Class: Binkterm PHP
Bulletin board system based on the Web
Author: By
Last change:
Date: 5 days ago
Size: 8,787 bytes
 

Contents

Class file image Download
{% extends "base.twig" %} {% block title %}{{ t('ui.admin.echomail_moderation.page_title', {}, 'common') }} - {{ parent() }}{% endblock %} {% block content %} <div class="d-flex justify-content-between align-items-center mb-4"> <h2> <i class="fas fa-shield-alt"></i> {{ t('ui.admin.echomail_moderation.heading', {}, 'common') }} <span class="badge bg-warning text-dark ms-2" id="pendingCountBadge" style="display:none;"></span> </h2> </div> <div class="row"> <div class="col-lg-9"> <div class="card"> <div class="card-body p-0"> <div id="queueContainer"> <div class="text-center py-4"> <i class="fas fa-spinner fa-spin me-2"></i> {{ t('ui.common.loading', {}, 'common') }} </div> </div> </div> </div> </div> <div class="col-lg-3"> <div class="card"> <div class="card-header"> <h6 class="mb-0">{{ t('ui.admin.echomail_moderation.about_title', {}, 'common') }}</h6> </div> <div class="card-body"> <p class="small text-muted mb-2"> {{ t('ui.admin.echomail_moderation.about_text', {}, 'common') }} </p> <p class="small text-muted mb-0"> {{ t('ui.admin.echomail_moderation.threshold_hint', {}, 'common') }} <a href="/admin/bbs-settings">{{ t('ui.admin.echomail_moderation.bbs_settings_link', {}, 'common') }}</a>. </p> </div> </div> </div> </div> {# ?? Message Preview Modal ????????????????????????????????????????????????? #} <div class="modal fade" id="previewModal" tabindex="-1"> <div class="modal-dialog modal-lg"> <div class="modal-content"> <div class="modal-header"> <h5 class="modal-title" id="previewModalTitle"></h5> <button type="button" class="btn-close" data-bs-dismiss="modal"></button> </div> <div class="modal-body"> <dl class="row small mb-3"> <dt class="col-sm-3">{{ t('ui.admin.echomail_moderation.col_area', {}, 'common') }}</dt> <dd class="col-sm-9 font-monospace" id="previewArea"></dd> <dt class="col-sm-3">{{ t('ui.admin.echomail_moderation.col_author', {}, 'common') }}</dt> <dd class="col-sm-9" id="previewAuthor"></dd> <dt class="col-sm-3">{{ t('ui.admin.echomail_moderation.col_date', {}, 'common') }}</dt> <dd class="col-sm-9" id="previewDate"></dd> </dl> <pre id="previewBody" class="bg-light p-3 rounded" style="white-space:pre-wrap;word-break:break-word;max-height:50vh;overflow-y:auto;"></pre> </div> <div class="modal-footer"> <button type="button" class="btn btn-secondary" data-bs-dismiss="modal">{{ t('ui.common.close', {}, 'common') }}</button> <button type="button" class="btn btn-danger" id="previewRejectBtn"> <i class="fas fa-ban me-1"></i>{{ t('ui.admin.echomail_moderation.action_reject', {}, 'common') }} </button> <button type="button" class="btn btn-success" id="previewApproveBtn"> <i class="fas fa-check me-1"></i>{{ t('ui.admin.echomail_moderation.action_approve', {}, 'common') }} </button> </div> </div> </div> </div> {% endblock %} {% block scripts %} <script> function uiT(key, fallback, params) { return window.t ? window.t(key, params || {}, fallback) : fallback; } function apiErr(payload, fallback) { return window.getApiErrorMessage ? window.getApiErrorMessage(payload, fallback) : (payload?.error || fallback); } let pendingMessages = []; let currentPreviewId = null; $(document).ready(function() { const init = function() { loadQueue(); }; if (typeof loadUserSettings === 'function') { loadUserSettings().finally(init); } else { init(); } }); function loadQueue() { $('#queueContainer').html('<div class="text-center py-4"><i class="fas fa-spinner fa-spin me-2"></i> ' + uiT('ui.common.loading', 'Loading...') + '</div>'); $.get('/admin/api/echomail-moderation') .done(function(data) { pendingMessages = data.messages || []; renderQueue(pendingMessages); }) .fail(function(xhr) { $('#queueContainer').html('<div class="text-center text-danger py-4">' + apiErr(xhr.responseJSON, 'Failed to load moderation queue') + '</div>'); }); } function renderQueue(messages) { const container = $('#queueContainer'); if (!messages || messages.length === 0) { $('#pendingCountBadge').hide(); container.html('<div class="text-center text-muted py-5"><i class="fas fa-check-circle fa-2x mb-3 d-block text-success"></i>' + uiT('ui.admin.echomail_moderation.empty_queue', 'No messages pending moderation.') + '</div>'); return; } $('#pendingCountBadge').text(messages.length).show(); let html = '<div class="table-responsive"><table class="table table-hover mb-0"><thead><tr>' + '<th>' + uiT('ui.admin.echomail_moderation.col_area', 'Area') + '</th>' + '<th>' + uiT('ui.admin.echomail_moderation.col_author', 'Author') + '</th>' + '<th>' + uiT('ui.admin.echomail_moderation.col_subject', 'Subject') + '</th>' + '<th>' + uiT('ui.admin.echomail_moderation.col_date', 'Date') + '</th>' + '<th>' + uiT('ui.admin.echomail_moderation.col_actions', 'Actions') + '</th>' + '</tr></thead><tbody>'; messages.forEach(function(m) { const date = m.date_received ? new Date(m.date_received).toLocaleString() : ''; html += '<tr>' + '<td><span class="font-monospace small">' + escapeHtml(m.echoarea_tag || '') + '</span></td>' + '<td>' + escapeHtml(m.author_username || m.from_name || '') + '</td>' + '<td><a href="#" class="text-decoration-none" onclick="showPreview(' + m.id + '); return false;">' + escapeHtml(m.subject || '') + '</a></td>' + '<td><small>' + escapeHtml(date) + '</small></td>' + '<td>' + '<div class="btn-group" role="group">' + '<button class="btn btn-sm btn-outline-success" onclick="approveMessage(' + m.id + ')" title="' + uiT('ui.admin.echomail_moderation.action_approve', 'Approve') + '">' + '<i class="fas fa-check"></i>' + '</button>' + '<button class="btn btn-sm btn-outline-danger" onclick="rejectMessage(' + m.id + ')" title="' + uiT('ui.admin.echomail_moderation.action_reject', 'Reject') + '">' + '<i class="fas fa-ban"></i>' + '</button>' + '</div>' + '</td>' + '</tr>'; }); html += '</tbody></table></div>'; container.html(html); } function showPreview(id) { const m = pendingMessages.find(function(x) { return x.id == id; }); if (!m) return; currentPreviewId = id; $('#previewModalTitle').text(escapeHtml(m.subject || '')); $('#previewArea').text(m.echoarea_tag || ''); $('#previewAuthor').text(m.author_username || m.from_name || ''); $('#previewDate').text(m.date_received ? new Date(m.date_received).toLocaleString() : ''); $('#previewBody').text(m.message_text || ''); $('#previewApproveBtn').off('click').on('click', function() { $('#previewModal').modal('hide'); approveMessage(id); }); $('#previewRejectBtn').off('click').on('click', function() { $('#previewModal').modal('hide'); rejectMessage(id); }); $('#previewModal').modal('show'); } function approveMessage(id) { $.post('/admin/api/echomail/' + id + '/approve') .done(function() { showSuccess(uiT('ui.admin.echomail_moderation.approved_success', 'Message approved and queued for transmission.')); loadQueue(); }) .fail(function(xhr) { showError(apiErr(xhr.responseJSON, 'Failed to approve message')); }); } function rejectMessage(id) { $.post('/admin/api/echomail/' + id + '/reject') .done(function() { showSuccess(uiT('ui.admin.echomail_moderation.rejected_success', 'Message rejected.')); loadQueue(); }) .fail(function(xhr) { showError(apiErr(xhr.responseJSON, 'Failed to reject message')); }); } </script> {% endblock %}