baseline
This commit is contained in:
57
pages/admin/mail-log/data().php
Normal file
57
pages/admin/mail-log/data().php
Normal file
@@ -0,0 +1,57 @@
|
||||
<?php
|
||||
|
||||
use MintyPHP\Router;
|
||||
use MintyPHP\Support\Guard;
|
||||
use MintyPHP\Service\MailLogService;
|
||||
use MintyPHP\Service\PermissionService;
|
||||
|
||||
Guard::requireLogin();
|
||||
Guard::requirePermissionOrForbidden(PermissionService::MAIL_LOG_VIEW);
|
||||
|
||||
$limit = (int) ($_GET['limit'] ?? 10);
|
||||
$offset = (int) ($_GET['offset'] ?? 0);
|
||||
$search = trim((string) ($_GET['search'] ?? ''));
|
||||
$order = (string) ($_GET['order'] ?? 'created_at');
|
||||
$dir = (string) ($_GET['dir'] ?? 'desc');
|
||||
$status = trim((string) ($_GET['status'] ?? ''));
|
||||
$createdFrom = trim((string) ($_GET['created_from'] ?? ''));
|
||||
$createdTo = trim((string) ($_GET['created_to'] ?? ''));
|
||||
|
||||
$result = MailLogService::listPaged([
|
||||
'limit' => $limit,
|
||||
'offset' => $offset,
|
||||
'search' => $search,
|
||||
'order' => $order,
|
||||
'dir' => $dir,
|
||||
'status' => $status,
|
||||
'created_from' => $createdFrom,
|
||||
'created_to' => $createdTo,
|
||||
]);
|
||||
|
||||
$rows = [];
|
||||
foreach ($result['rows'] as $row) {
|
||||
$status = (string) ($row['status'] ?? '');
|
||||
$statusBadge = 'neutral';
|
||||
if ($status === 'sent') {
|
||||
$statusBadge = 'success';
|
||||
} elseif ($status === 'failed') {
|
||||
$statusBadge = 'danger';
|
||||
}
|
||||
|
||||
$rows[] = [
|
||||
'id' => $row['id'] ?? null,
|
||||
'to_email' => $row['to_email'] ?? '',
|
||||
'subject' => $row['subject'] ?? '',
|
||||
'template' => $row['template'] ?? '',
|
||||
'status' => $status,
|
||||
'status_badge' => $statusBadge,
|
||||
'status_label' => t(ucfirst($status)),
|
||||
'created_at' => dt($row['created_at'] ?? ''),
|
||||
'sent_at' => dt($row['sent_at'] ?? ''),
|
||||
];
|
||||
}
|
||||
|
||||
Router::json([
|
||||
'data' => $rows,
|
||||
'total' => $result['total'] ?? 0,
|
||||
]);
|
||||
23
pages/admin/mail-log/index().php
Normal file
23
pages/admin/mail-log/index().php
Normal file
@@ -0,0 +1,23 @@
|
||||
<?php
|
||||
|
||||
use MintyPHP\Buffer;
|
||||
use MintyPHP\Support\Guard;
|
||||
use MintyPHP\Session;
|
||||
use MintyPHP\Service\PermissionService;
|
||||
|
||||
Guard::requireLogin();
|
||||
Guard::requirePermission(PermissionService::MAIL_LOG_VIEW);
|
||||
|
||||
$currentUserId = (int) ($_SESSION['user']['id'] ?? 0);
|
||||
if ($currentUserId > 0) {
|
||||
PermissionService::getUserPermissions($currentUserId);
|
||||
}
|
||||
|
||||
Buffer::set('title', t('Mail logs'));
|
||||
Buffer::set('grid_lang', json_encode(gridLang(), JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES));
|
||||
$csrfKey = Session::$csrfSessionKey;
|
||||
$csrfToken = $_SESSION[$csrfKey] ?? '';
|
||||
Buffer::set(
|
||||
'grid_csrf',
|
||||
json_encode(['key' => $csrfKey, 'token' => $csrfToken], JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES)
|
||||
);
|
||||
174
pages/admin/mail-log/index(default).phtml
Normal file
174
pages/admin/mail-log/index(default).phtml
Normal file
@@ -0,0 +1,174 @@
|
||||
<?php
|
||||
use MintyPHP\Router;
|
||||
?>
|
||||
<div class="app-breadcrumb">
|
||||
<a href="/admin">Startseite</a><i class="bi bi-chevron-right"></i><?php e(t('Mail logs')); ?>
|
||||
</div>
|
||||
<div class="app-list-titlebar">
|
||||
<h1><?php e(t('Mail logs')); ?></h1>
|
||||
<div class="app-list-titlebar-actions">
|
||||
<button
|
||||
class="outline secondary"
|
||||
type="button"
|
||||
data-toolbar-toggle
|
||||
data-toolbar-target="#mail-log-toolbar"
|
||||
data-toolbar-text-show="<?php e(t('Show filters')); ?>"
|
||||
data-toolbar-text-hide="<?php e(t('Hide filters')); ?>"
|
||||
>
|
||||
<i class="bi bi-funnel-fill"></i> <span data-toolbar-label><?php e(t('Hide filters')); ?></span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="app-list-toolbar" id="mail-log-toolbar">
|
||||
<label class="app-field">
|
||||
<span><?php e(t('Search')); ?></span>
|
||||
<input type="search" id="mail-log-search" placeholder="<?php e(t('Search...')); ?>">
|
||||
</label>
|
||||
<label class="app-field">
|
||||
<span><?php e(t('Status')); ?></span>
|
||||
<select id="mail-log-status-filter">
|
||||
<option value=""><?php e(t('All statuses')); ?></option>
|
||||
<option value="sent"><?php e(t('Sent')); ?></option>
|
||||
<option value="queued"><?php e(t('Queued')); ?></option>
|
||||
<option value="failed"><?php e(t('Failed')); ?></option>
|
||||
</select>
|
||||
</label>
|
||||
<label class="app-field">
|
||||
<span><?php e(t('Created from')); ?></span>
|
||||
<input type="date" id="mail-log-created-from">
|
||||
</label>
|
||||
<label class="app-field">
|
||||
<span><?php e(t('Created to')); ?></span>
|
||||
<input type="date" id="mail-log-created-to">
|
||||
</label>
|
||||
</div>
|
||||
<div class="app-list-table">
|
||||
<div id="mail-log-grid"></div>
|
||||
</div>
|
||||
|
||||
<?php $gridFactoryVersion = @filemtime('web/js/core/app-grid-factory.js') ?: time(); ?>
|
||||
<script src="<?php e(asset('vendor/gridjs/gridjs.umd.js')); ?>"></script>
|
||||
<script type="module">
|
||||
import { initToolbarToggles } from "<?php e(asset('js/components/app-toggle-toolbar.js')); ?>";
|
||||
import { createServerGrid } from "<?php e(asset('js/core/app-grid-factory.js?v=' . $gridFactoryVersion)); ?>";
|
||||
import { buildUrl, badgeHtml } from "<?php e(asset('js/pages/app-list-utils.js')); ?>";
|
||||
|
||||
initToolbarToggles();
|
||||
|
||||
const appBase = "<?php e(localeBase()); ?>";
|
||||
|
||||
const initMailLogGrid = () => {
|
||||
const formatBadge = (value) => badgeHtml(gridjs, value);
|
||||
const gridConfig = createServerGrid({
|
||||
gridjs: window.gridjs,
|
||||
container: '#mail-log-grid',
|
||||
dataUrl: 'admin/mail-log/data',
|
||||
appBase,
|
||||
columns: [
|
||||
{
|
||||
name: "<?php e(t('Created')); ?>",
|
||||
sort: true,
|
||||
formatter: (cell) => formatBadge(cell)
|
||||
},
|
||||
{
|
||||
name: "<?php e(t('Recipient')); ?>",
|
||||
sort: true,
|
||||
formatter: (cell) => {
|
||||
if (!cell || typeof cell !== 'object') {
|
||||
return gridjs.html(String(cell ?? ''));
|
||||
}
|
||||
return gridjs.html(String(cell ?? ''));
|
||||
}
|
||||
},
|
||||
{
|
||||
name: "<?php e(t('Subject')); ?>",
|
||||
sort: true
|
||||
},
|
||||
{
|
||||
name: "<?php e(t('Template')); ?>",
|
||||
sort: false
|
||||
},
|
||||
{
|
||||
name: "<?php e(t('Status')); ?>",
|
||||
sort: true,
|
||||
formatter: (cell) => {
|
||||
if (!cell || typeof cell !== 'object') {
|
||||
return gridjs.html('');
|
||||
}
|
||||
const variant = cell.variant || 'neutral';
|
||||
const label = cell.label || '';
|
||||
return gridjs.html(`<span class="badge" data-variant="${variant}">${label}</span>`);
|
||||
}
|
||||
},
|
||||
{
|
||||
name: "ID",
|
||||
hidden: true
|
||||
}
|
||||
],
|
||||
sortColumns: ['created_at', 'to_email', 'subject', null, 'status', null],
|
||||
paginationLimit: 10,
|
||||
language: <?php MintyPHP\Buffer::get('grid_lang'); ?>,
|
||||
mapData: (data) => data.data.map((row) => [
|
||||
row.created_at,
|
||||
row.to_email,
|
||||
row.subject,
|
||||
row.template || '-',
|
||||
{
|
||||
variant: row.status_badge,
|
||||
label: row.status_label
|
||||
},
|
||||
row.id
|
||||
]),
|
||||
actions: {
|
||||
enabled: true,
|
||||
label: "<?php e(t('Actions')); ?>",
|
||||
getRowId: (row) => row?.cells?.[5]?.data,
|
||||
items: [
|
||||
{
|
||||
key: 'view',
|
||||
type: 'link',
|
||||
label: "<i class=\"bi bi-eye-fill\"></i>",
|
||||
href: ({ id }) => buildUrl(appBase, `admin/mail-log/view/${id}`)
|
||||
}
|
||||
]
|
||||
},
|
||||
search: {
|
||||
input: '#mail-log-search',
|
||||
param: 'search',
|
||||
debounce: 250
|
||||
},
|
||||
filters: [
|
||||
{
|
||||
input: '#mail-log-status-filter',
|
||||
param: 'status'
|
||||
},
|
||||
{
|
||||
input: '#mail-log-created-from',
|
||||
param: 'created_from',
|
||||
normalize: (value) => (value ? value : '')
|
||||
},
|
||||
{
|
||||
input: '#mail-log-created-to',
|
||||
param: 'created_to',
|
||||
normalize: (value) => (value ? value : '')
|
||||
}
|
||||
],
|
||||
urlSync: true,
|
||||
rowDblClick: {
|
||||
getUrl: (rowData) => {
|
||||
const id = rowData?.cells?.[5]?.data;
|
||||
return id ? new URL(`admin/mail-log/view/${id}`, appBase).toString() : '';
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
if (!gridConfig || !gridConfig.grid) {
|
||||
console.warn('Mail log grid init failed');
|
||||
return null;
|
||||
}
|
||||
|
||||
return gridConfig;
|
||||
};
|
||||
|
||||
initMailLogGrid();
|
||||
</script>
|
||||
25
pages/admin/mail-log/view($id).php
Normal file
25
pages/admin/mail-log/view($id).php
Normal file
@@ -0,0 +1,25 @@
|
||||
<?php
|
||||
|
||||
use MintyPHP\Buffer;
|
||||
use MintyPHP\Support\Flash;
|
||||
use MintyPHP\Support\Guard;
|
||||
use MintyPHP\Router;
|
||||
use MintyPHP\Service\MailLogService;
|
||||
use MintyPHP\Service\PermissionService;
|
||||
|
||||
Guard::requireLogin();
|
||||
Guard::requirePermission(PermissionService::MAIL_LOG_VIEW);
|
||||
|
||||
$currentUserId = (int) ($_SESSION['user']['id'] ?? 0);
|
||||
if ($currentUserId > 0) {
|
||||
PermissionService::getUserPermissions($currentUserId);
|
||||
}
|
||||
|
||||
$mailLogId = (int) ($id ?? 0);
|
||||
$mailLog = $mailLogId > 0 ? MailLogService::find($mailLogId) : null;
|
||||
if (!$mailLog) {
|
||||
Flash::error('Mail log not found', 'admin/mail-log', 'mail_log_not_found');
|
||||
Router::redirect('admin/mail-log');
|
||||
}
|
||||
|
||||
Buffer::set('title', t('View mail log'));
|
||||
137
pages/admin/mail-log/view(default).phtml
Normal file
137
pages/admin/mail-log/view(default).phtml
Normal file
@@ -0,0 +1,137 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @var array $mailLog
|
||||
*/
|
||||
|
||||
$mailLog = $mailLog ?? [];
|
||||
$status = (string) ($mailLog['status'] ?? '');
|
||||
$statusBadge = 'neutral';
|
||||
if ($status === 'sent') {
|
||||
$statusBadge = 'success';
|
||||
} elseif ($status === 'failed') {
|
||||
$statusBadge = 'danger';
|
||||
}
|
||||
|
||||
?>
|
||||
|
||||
<div class="app-details-container">
|
||||
<section>
|
||||
<div class="app-breadcrumb">
|
||||
<a href="/admin">Startseite</a><i class="bi bi-chevron-right"></i><a
|
||||
href="/admin/mail-log"><?php e(t('Mail logs')); ?></a><i class="bi bi-chevron-right"></i><?php e(t('View')); ?>
|
||||
</div>
|
||||
<div class="app-details-titlebar">
|
||||
<h1>
|
||||
<a href="admin/mail-log" title="<?php e(t('Back')); ?>"><i class="bi bi-arrow-left"></i></a>
|
||||
<?php e(t('View mail log')); ?>
|
||||
</h1>
|
||||
</div>
|
||||
|
||||
<div class="app-details-content">
|
||||
<details open>
|
||||
<summary><?php e(t('Email details')); ?></summary>
|
||||
<hr>
|
||||
<div class="app-details-section">
|
||||
<div class="grid">
|
||||
<div class="app-form-group">
|
||||
<label><?php e(t('Recipient')); ?></label>
|
||||
<input type="text" value="<?php e($mailLog['to_email'] ?? ''); ?>" readonly>
|
||||
</div>
|
||||
<div class="app-form-group">
|
||||
<label><?php e(t('Subject')); ?></label>
|
||||
<input type="text" value="<?php e($mailLog['subject'] ?? ''); ?>" readonly>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
<div class="app-form-group">
|
||||
<label><?php e(t('Template')); ?></label>
|
||||
<input type="text" value="<?php e($mailLog['template'] ?? '-'); ?>" readonly>
|
||||
</div>
|
||||
</div>
|
||||
</details>
|
||||
|
||||
<?php if ($status === 'sent'): ?>
|
||||
<hr>
|
||||
<details open>
|
||||
<summary><?php e(t('Delivery information')); ?></summary>
|
||||
<hr>
|
||||
<div class="app-details-section">
|
||||
<div class="app-form-group">
|
||||
<label><?php e(t('Sent at')); ?></label>
|
||||
<input type="text" value="<?php e(dt($mailLog['sent_at'] ?? '')); ?>" readonly>
|
||||
</div>
|
||||
<?php if (!empty($mailLog['provider_message_id'])): ?>
|
||||
<div class="app-form-group">
|
||||
<label><?php e(t('Provider message ID')); ?></label>
|
||||
<input type="text" value="<?php e($mailLog['provider_message_id'] ?? ''); ?>" readonly>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
</details>
|
||||
<?php endif; ?>
|
||||
|
||||
<?php if ($status === 'failed' && !empty($mailLog['error_message'])): ?>
|
||||
<hr>
|
||||
<details open>
|
||||
<summary><?php e(t('Error information')); ?></summary>
|
||||
<hr>
|
||||
<div class="app-details-section">
|
||||
<div class="app-form-group">
|
||||
<label><?php e(t('Error message')); ?></label>
|
||||
<textarea readonly rows="6"><?php e($mailLog['error_message'] ?? ''); ?></textarea>
|
||||
</div>
|
||||
</div>
|
||||
</details>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
</section>
|
||||
<aside id="app-details-aside-section">
|
||||
<div class="app-details-aside-section">
|
||||
<hgroup>
|
||||
<strong><?php e($mailLog['to_email'] ?? ''); ?></strong>
|
||||
<p><small><?php e(t('Mail log')); ?></small></p>
|
||||
</hgroup>
|
||||
<hr>
|
||||
<div class="grid">
|
||||
<div>
|
||||
<small><?php e(t('ID')); ?></small>
|
||||
<p>
|
||||
<span class="badge" data-variant="neutral">
|
||||
<?php e($mailLog['id'] ?? '-'); ?>
|
||||
</span>
|
||||
</p>
|
||||
</div>
|
||||
<div>
|
||||
<small>
|
||||
<?php e(t('Status')); ?>
|
||||
</small>
|
||||
<div>
|
||||
<span class="badge" data-variant="<?php e($statusBadge); ?>">
|
||||
<?php e(t(ucfirst($status))); ?>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<small><?php e(t('Created')); ?></small>
|
||||
<p><?php e(dt($mailLog['created_at'] ?? '') ?: '-'); ?></p>
|
||||
</div>
|
||||
<?php if ($status === 'sent' && !empty($mailLog['sent_at'])): ?>
|
||||
<div>
|
||||
<small><?php e(t('Sent')); ?></small>
|
||||
<p><?php e(dt($mailLog['sent_at'] ?? '') ?: '-'); ?></p>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
<?php if (!empty($mailLog['provider_message_id'])): ?>
|
||||
<div class="grid">
|
||||
<div>
|
||||
<small><?php e(t('Provider message ID')); ?></small>
|
||||
<span class="badge" data-copy="true" data-copy-value="<?php e($mailLog['provider_message_id']); ?>"
|
||||
data-variant="neutral"><?php e(substr($mailLog['provider_message_id'], 0, 20)); ?></span>
|
||||
</div>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
</aside>
|
||||
</div>
|
||||
Reference in New Issue
Block a user