Rebuild logs view
This commit is contained in:
parent
64dc16e4d9
commit
e947e788f9
|
@ -39,6 +39,10 @@ $route->get('/design', 'DesignController@index');
|
||||||
$route->addGroup(
|
$route->addGroup(
|
||||||
'/admin',
|
'/admin',
|
||||||
function (RouteCollector $route) {
|
function (RouteCollector $route) {
|
||||||
|
// Log
|
||||||
|
$route->get('/logs', 'Admin\\LogsController@index');
|
||||||
|
$route->post('/logs', 'Admin\\LogsController@index');
|
||||||
|
|
||||||
// Schedule
|
// Schedule
|
||||||
$route->addGroup(
|
$route->addGroup(
|
||||||
'/schedule',
|
'/schedule',
|
||||||
|
@ -48,6 +52,8 @@ $route->addGroup(
|
||||||
$route->post('/import', 'Admin\\Schedule\\ImportSchedule@importSchedule');
|
$route->post('/import', 'Admin\\Schedule\\ImportSchedule@importSchedule');
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// News
|
||||||
$route->addGroup(
|
$route->addGroup(
|
||||||
'/news',
|
'/news',
|
||||||
function (RouteCollector $route) {
|
function (RouteCollector $route) {
|
||||||
|
|
|
@ -68,7 +68,6 @@ $includeFiles = [
|
||||||
__DIR__ . '/../includes/pages/admin_arrive.php',
|
__DIR__ . '/../includes/pages/admin_arrive.php',
|
||||||
__DIR__ . '/../includes/pages/admin_free.php',
|
__DIR__ . '/../includes/pages/admin_free.php',
|
||||||
__DIR__ . '/../includes/pages/admin_groups.php',
|
__DIR__ . '/../includes/pages/admin_groups.php',
|
||||||
__DIR__ . '/../includes/pages/admin_log.php',
|
|
||||||
__DIR__ . '/../includes/pages/admin_questions.php',
|
__DIR__ . '/../includes/pages/admin_questions.php',
|
||||||
__DIR__ . '/../includes/pages/admin_rooms.php',
|
__DIR__ . '/../includes/pages/admin_rooms.php',
|
||||||
__DIR__ . '/../includes/pages/admin_shifts.php',
|
__DIR__ . '/../includes/pages/admin_shifts.php',
|
||||||
|
|
|
@ -102,9 +102,11 @@ function admin_free()
|
||||||
form([
|
form([
|
||||||
div('row', [
|
div('row', [
|
||||||
div('col-md-12 form-inline', [
|
div('col-md-12 form-inline', [
|
||||||
form_text('search', __('Search'), $search),
|
div('inline-form-spacing', [
|
||||||
form_select('angeltype', __('Angeltype'), $angel_types, $angelType),
|
form_text('search', __('Search'), $search),
|
||||||
form_submit('submit', __('Search'))
|
form_select('angeltype', __('Angeltype'), $angel_types, $angelType),
|
||||||
|
form_submit('submit', __('Search'))
|
||||||
|
]),
|
||||||
]),
|
]),
|
||||||
]),
|
]),
|
||||||
]),
|
]),
|
||||||
|
|
|
@ -1,45 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
use Engelsystem\Models\LogEntry;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return string
|
|
||||||
*/
|
|
||||||
function admin_log_title()
|
|
||||||
{
|
|
||||||
return __('Log');
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return string
|
|
||||||
*/
|
|
||||||
function admin_log()
|
|
||||||
{
|
|
||||||
$filter = '';
|
|
||||||
if (request()->has('keyword')) {
|
|
||||||
$filter = strip_request_item('keyword');
|
|
||||||
}
|
|
||||||
|
|
||||||
$log_entries = LogEntry::filter($filter);
|
|
||||||
|
|
||||||
$entries = [];
|
|
||||||
foreach ($log_entries as $entry) {
|
|
||||||
$data = $entry->toArray();
|
|
||||||
$data['message'] = nl2br(htmlspecialchars($data['message']));
|
|
||||||
$data['created_at'] = date_format($entry->created_at, 'd.m.Y H:i');
|
|
||||||
$entries[] = $data;
|
|
||||||
}
|
|
||||||
|
|
||||||
return page_with_title(admin_log_title(), [
|
|
||||||
msg(),
|
|
||||||
form([
|
|
||||||
form_text('keyword', __('Search'), $filter),
|
|
||||||
form_submit(__('Search'), 'Go')
|
|
||||||
]),
|
|
||||||
table([
|
|
||||||
'created_at' => 'Time',
|
|
||||||
'level' => 'Type',
|
|
||||||
'message' => 'Log Entry'
|
|
||||||
], $entries)
|
|
||||||
]);
|
|
||||||
}
|
|
|
@ -108,6 +108,8 @@ function make_navigation()
|
||||||
|
|
||||||
$admin_menu = [];
|
$admin_menu = [];
|
||||||
$admin_pages = [
|
$admin_pages = [
|
||||||
|
// path => name
|
||||||
|
// path => [name, permission]
|
||||||
'admin_arrive' => 'Arrived angels',
|
'admin_arrive' => 'Arrived angels',
|
||||||
'admin_active' => 'Active angels',
|
'admin_active' => 'Active angels',
|
||||||
'admin_user' => 'All Angels',
|
'admin_user' => 'All Angels',
|
||||||
|
@ -118,7 +120,7 @@ function make_navigation()
|
||||||
'admin_rooms' => 'Rooms',
|
'admin_rooms' => 'Rooms',
|
||||||
'admin_groups' => 'Grouprights',
|
'admin_groups' => 'Grouprights',
|
||||||
'admin/schedule' => ['schedule.import', 'schedule.import'],
|
'admin/schedule' => ['schedule.import', 'schedule.import'],
|
||||||
'admin_log' => 'Log',
|
'admin/logs' => ['log.log', 'admin_log'],
|
||||||
'admin_event_config' => 'Event config',
|
'admin_event_config' => 'Event config',
|
||||||
];
|
];
|
||||||
|
|
||||||
|
|
|
@ -248,6 +248,10 @@ h1, h2, h3, h4, h5, h6, .h1, .h2, .h3, .h4, .h5, .h6 {
|
||||||
overflow-x: inherit;
|
overflow-x: inherit;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.inline-form-spacing {
|
||||||
|
margin-bottom: @form-group-margin-bottom;
|
||||||
|
}
|
||||||
|
|
||||||
@keyframes pulse {
|
@keyframes pulse {
|
||||||
0% {
|
0% {
|
||||||
transform: rotate(0deg);
|
transform: rotate(0deg);
|
||||||
|
|
|
@ -986,8 +986,6 @@ msgstr "Alle Schichten anzeigen"
|
||||||
|
|
||||||
#: includes/pages/admin_active.php:307 includes/pages/admin_arrive.php:178
|
#: includes/pages/admin_active.php:307 includes/pages/admin_arrive.php:178
|
||||||
#: includes/pages/admin_arrive.php:179 includes/pages/admin_free.php:105
|
#: includes/pages/admin_arrive.php:179 includes/pages/admin_free.php:105
|
||||||
#: includes/pages/admin_free.php:107 includes/pages/admin_log.php:36
|
|
||||||
#: includes/pages/admin_log.php:37
|
|
||||||
msgid "Search"
|
msgid "Search"
|
||||||
msgstr "Suche"
|
msgstr "Suche"
|
||||||
|
|
||||||
|
@ -1294,10 +1292,6 @@ msgstr "Zu löschende Schichten"
|
||||||
msgid "It's done!"
|
msgid "It's done!"
|
||||||
msgstr "Erledigt!"
|
msgstr "Erledigt!"
|
||||||
|
|
||||||
#: includes/pages/admin_log.php:10 includes/sys_menu.php:121
|
|
||||||
msgid "Log"
|
|
||||||
msgstr "Log"
|
|
||||||
|
|
||||||
#: includes/pages/user_messages.php:121
|
#: includes/pages/user_messages.php:121
|
||||||
msgid "Message"
|
msgid "Message"
|
||||||
msgstr "Nachricht"
|
msgstr "Nachricht"
|
||||||
|
@ -2866,3 +2860,18 @@ msgstr "Treffen"
|
||||||
|
|
||||||
msgid "news.edit.message"
|
msgid "news.edit.message"
|
||||||
msgstr "Nachricht"
|
msgstr "Nachricht"
|
||||||
|
|
||||||
|
msgid "form.search"
|
||||||
|
msgstr "Suchen"
|
||||||
|
|
||||||
|
msgid "log.log"
|
||||||
|
msgstr "Logs"
|
||||||
|
|
||||||
|
msgid "log.time"
|
||||||
|
msgstr "Zeit"
|
||||||
|
|
||||||
|
msgid "log.level"
|
||||||
|
msgstr "Level"
|
||||||
|
|
||||||
|
msgid "log.message"
|
||||||
|
msgstr "Nachricht"
|
||||||
|
|
|
@ -144,3 +144,18 @@ msgstr "Meeting"
|
||||||
|
|
||||||
msgid "news.edit.message"
|
msgid "news.edit.message"
|
||||||
msgstr "Message"
|
msgstr "Message"
|
||||||
|
|
||||||
|
msgid "form.search"
|
||||||
|
msgstr "Search"
|
||||||
|
|
||||||
|
msgid "log.log"
|
||||||
|
msgstr "Logs"
|
||||||
|
|
||||||
|
msgid "log.time"
|
||||||
|
msgstr "Time"
|
||||||
|
|
||||||
|
msgid "log.level"
|
||||||
|
msgstr "Level"
|
||||||
|
|
||||||
|
msgid "log.message"
|
||||||
|
msgstr "Message"
|
||||||
|
|
|
@ -0,0 +1,58 @@
|
||||||
|
{% extends 'layouts/app.twig' %}
|
||||||
|
{% import 'macros/base.twig' as m %}
|
||||||
|
{% import 'macros/form.twig' as f %}
|
||||||
|
|
||||||
|
{% set title %}{% block title %}{{ __('log.log') }}{% endblock %}{% endset %}
|
||||||
|
|
||||||
|
{% block content %}
|
||||||
|
<div class="col-md-12">
|
||||||
|
<h1>{{ block('title') }}</h1>
|
||||||
|
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-md-12">
|
||||||
|
<div class="inline-form-spacing">
|
||||||
|
<form method="POST" action="{{ url('/admin/logs') }}" class="form-inline">
|
||||||
|
{{ csrf() }}
|
||||||
|
|
||||||
|
{{ f.input('search', __('form.search'), 'text', {'value': search, 'hide_label': true}) }}
|
||||||
|
|
||||||
|
{{ f.submit(__('form.search')) }}
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<table class="table table-striped">
|
||||||
|
<tr>
|
||||||
|
<th>{{ __('log.time') }}</th>
|
||||||
|
<th>{{ __('log.level') }}</th>
|
||||||
|
<th>{{ __('log.message') }}</th>
|
||||||
|
</tr>
|
||||||
|
{% for entry in entries %}
|
||||||
|
{%- set type = 'default' %}
|
||||||
|
{%- if entry.level in ['notice', 'info'] %}
|
||||||
|
{%- set type = 'info' %}
|
||||||
|
{%- endif %}
|
||||||
|
{%- if entry.level in ['error', 'warning'] %}
|
||||||
|
{%- set type = 'warning' %}
|
||||||
|
{%- endif %}
|
||||||
|
{%- if entry.level in ['emergency', 'alert', 'critical'] %}
|
||||||
|
{%- set type = 'danger' %}
|
||||||
|
{%- endif %}
|
||||||
|
|
||||||
|
{%- set td_type = '' %}
|
||||||
|
{%- if type in ['warning', 'danger'] %}
|
||||||
|
{%- set td_type = type %}
|
||||||
|
{%- endif %}
|
||||||
|
|
||||||
|
<tr>
|
||||||
|
<td class="{{ td_type }}">{{ entry.created_at.format(__('Y-m-d H:i')) }}</td>
|
||||||
|
<td class="{{ td_type }}">
|
||||||
|
<span class="label label-{{ type }}">{{ entry.level|capitalize }}</span>
|
||||||
|
</td>
|
||||||
|
<td>{{ entry.message|nl2br }}</td>
|
||||||
|
</tr>
|
||||||
|
{% endfor %}
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{% endblock %}
|
|
@ -1,11 +1,11 @@
|
||||||
{% macro input(name, label, type, opt) %}
|
{% macro input(name, label, type, opt) %}
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
{% if label -%}
|
{% if label -%}
|
||||||
<label for="{{ name }}">{{ label }}</label>
|
<label for="{{ name }}"{% if opt.hide_label|default(false) %} class="sr-only"{% endif %}>{{ label }}</label>
|
||||||
{%- endif %}
|
{%- endif %}
|
||||||
<input type="{{ type|default('text') }}" class="form-control"
|
<input type="{{ type|default('text') }}" class="form-control"
|
||||||
id="{{ name }}" name="{{ name }}"
|
id="{{ name }}" name="{{ name }}"
|
||||||
value="{{ opt.value|default('') }}"
|
value="{{ opt.value|default('')|escape('html_attr') }}"
|
||||||
{%- if opt.required|default(false) %}
|
{%- if opt.required|default(false) %}
|
||||||
required
|
required
|
||||||
{%- endif -%}
|
{%- endif -%}
|
||||||
|
@ -59,7 +59,7 @@
|
||||||
{%- endmacro %}
|
{%- endmacro %}
|
||||||
|
|
||||||
{% macro hidden(name, value) %}
|
{% macro hidden(name, value) %}
|
||||||
<input type="hidden" id="{{ name }}" name="{{ name }}" value="{{ value }}">
|
<input type="hidden" id="{{ name }}" name="{{ name }}" value="{{ value|escape('html_attr') }}">
|
||||||
{%- endmacro %}
|
{%- endmacro %}
|
||||||
|
|
||||||
{% macro button(label, opt) %}
|
{% macro button(label, opt) %}
|
||||||
|
|
|
@ -101,6 +101,9 @@
|
||||||
<div class="col-md-2">
|
<div class="col-md-2">
|
||||||
{{ f.input('form-input-text', 'Text', 'text', {'value': 'Value'}) }}
|
{{ f.input('form-input-text', 'Text', 'text', {'value': 'Value'}) }}
|
||||||
</div>
|
</div>
|
||||||
|
<div class="col-md-2">
|
||||||
|
{{ f.input('form-input-text-hidden-label', 'Hidden label', 'text', {'value': 'Hidden label', 'hide_label': true}) }}
|
||||||
|
</div>
|
||||||
<div class="col-md-2">
|
<div class="col-md-2">
|
||||||
{{ f.input('form-input-text-disabled', 'Disabled', 'text', {'disabled': true, 'value': 'Value'}) }}
|
{{ f.input('form-input-text-disabled', 'Disabled', 'text', {'disabled': true, 'value': 'Value'}) }}
|
||||||
</div>
|
</div>
|
||||||
|
@ -113,11 +116,11 @@
|
||||||
<div class="col-md-2">
|
<div class="col-md-2">
|
||||||
{{ f.input('form-input-number', 'Number', 'number', {'value': 42}) }}
|
{{ f.input('form-input-number', 'Number', 'number', {'value': 42}) }}
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="row">
|
||||||
<div class="col-md-2">
|
<div class="col-md-2">
|
||||||
{{ f.textarea('form-input-textarea', 'Textarea', {'rows': 2, 'value': lipsum}) }}
|
{{ f.textarea('form-input-textarea', 'Textarea', {'rows': 2, 'value': lipsum}) }}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
|
||||||
<div class="row">
|
|
||||||
<div class="col-md-2">
|
<div class="col-md-2">
|
||||||
{{ f.select('form-input-select', {'lorem': 'Ipsum', 'dolor': 'Sit'}, 'Select', 'dolor') }}
|
{{ f.select('form-input-select', {'lorem': 'Ipsum', 'dolor': 'Sit'}, 'Select', 'dolor') }}
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -0,0 +1,47 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Engelsystem\Controllers\Admin;
|
||||||
|
|
||||||
|
use Engelsystem\Controllers\BaseController;
|
||||||
|
use Engelsystem\Http\Request;
|
||||||
|
use Engelsystem\Http\Response;
|
||||||
|
use Engelsystem\Models\LogEntry;
|
||||||
|
|
||||||
|
class LogsController extends BaseController
|
||||||
|
{
|
||||||
|
/** @var LogEntry */
|
||||||
|
protected $log;
|
||||||
|
|
||||||
|
/** @var Response */
|
||||||
|
protected $response;
|
||||||
|
|
||||||
|
/** @var array */
|
||||||
|
protected $permissions = [
|
||||||
|
'admin_log',
|
||||||
|
];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param LogEntry $log
|
||||||
|
* @param Response $response
|
||||||
|
*/
|
||||||
|
public function __construct(LogEntry $log, Response $response)
|
||||||
|
{
|
||||||
|
$this->log = $log;
|
||||||
|
$this->response = $response;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param Request $request
|
||||||
|
* @return Response
|
||||||
|
*/
|
||||||
|
public function index(Request $request): Response
|
||||||
|
{
|
||||||
|
$search = $request->input('search');
|
||||||
|
$entries = $this->log->filter($search);
|
||||||
|
|
||||||
|
return $this->response->withView(
|
||||||
|
'admin/log.twig',
|
||||||
|
['entries' => $entries, 'search' => $search]
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
|
@ -188,10 +188,6 @@ class LegacyMiddleware implements MiddlewareInterface
|
||||||
$title = admin_shifts_title();
|
$title = admin_shifts_title();
|
||||||
$content = admin_shifts();
|
$content = admin_shifts();
|
||||||
return [$title, $content];
|
return [$title, $content];
|
||||||
case 'admin_log':
|
|
||||||
$title = admin_log_title();
|
|
||||||
$content = admin_log();
|
|
||||||
return [$title, $content];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
throw_redirect(page_link_to('login'));
|
throw_redirect(page_link_to('login'));
|
||||||
|
|
|
@ -0,0 +1,57 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Engelsystem\Test\Unit\Controllers\Admin;
|
||||||
|
|
||||||
|
use Engelsystem\Controllers\Admin\LogsController;
|
||||||
|
use Engelsystem\Http\Request;
|
||||||
|
use Engelsystem\Http\Response;
|
||||||
|
use Engelsystem\Models\LogEntry;
|
||||||
|
use Engelsystem\Test\Unit\HasDatabase;
|
||||||
|
use Engelsystem\Test\Unit\TestCase;
|
||||||
|
use Illuminate\Database\Eloquent\Collection;
|
||||||
|
use Psr\Log\LogLevel;
|
||||||
|
|
||||||
|
class LogsControllerTest extends TestCase
|
||||||
|
{
|
||||||
|
use HasDatabase;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @covers \Engelsystem\Controllers\Admin\LogsController::index
|
||||||
|
* @covers \Engelsystem\Controllers\Admin\LogsController::__construct
|
||||||
|
*/
|
||||||
|
public function testIndex()
|
||||||
|
{
|
||||||
|
$log = new LogEntry();
|
||||||
|
$alert = $log->create(['level' => LogLevel::ALERT, 'message' => 'Alert test']);
|
||||||
|
$alert = $log->find($alert)->first();
|
||||||
|
$error = $log->create(['level' => LogLevel::ERROR, 'message' => 'Error test']);
|
||||||
|
$error = $log->find($error)->first();
|
||||||
|
|
||||||
|
$response = $this->createMock(Response::class);
|
||||||
|
$response->expects($this->exactly(2))
|
||||||
|
->method('withView')
|
||||||
|
->withConsecutive(
|
||||||
|
['admin/log.twig', ['entries' => new Collection([$error, $alert]), 'search' => null]],
|
||||||
|
['admin/log.twig', ['entries' => new Collection([$error]), 'search' => 'error']]
|
||||||
|
)
|
||||||
|
->willReturn($response);
|
||||||
|
|
||||||
|
$request = Request::create('/');
|
||||||
|
|
||||||
|
$controller = new LogsController($log, $response);
|
||||||
|
$controller->index($request);
|
||||||
|
|
||||||
|
$request->request->set('search', 'error');
|
||||||
|
$controller->index($request);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Setup the DB
|
||||||
|
*/
|
||||||
|
public function setUp(): void
|
||||||
|
{
|
||||||
|
parent::setUp();
|
||||||
|
|
||||||
|
$this->initDatabase();
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue