Rebuild logs view

This commit is contained in:
Igor Scheller 2020-05-01 16:29:28 +02:00 committed by msquare
parent 64dc16e4d9
commit e947e788f9
14 changed files with 218 additions and 65 deletions

View File

@ -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) {

View File

@ -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',

View File

@ -102,12 +102,14 @@ function admin_free()
form([ form([
div('row', [ div('row', [
div('col-md-12 form-inline', [ div('col-md-12 form-inline', [
div('inline-form-spacing', [
form_text('search', __('Search'), $search), form_text('search', __('Search'), $search),
form_select('angeltype', __('Angeltype'), $angel_types, $angelType), form_select('angeltype', __('Angeltype'), $angel_types, $angelType),
form_submit('submit', __('Search')) form_submit('submit', __('Search'))
]), ]),
]), ]),
]), ]),
]),
table([ table([
'name' => __('Nick'), 'name' => __('Nick'),
'shift_state' => __('Next shift'), 'shift_state' => __('Next shift'),

View File

@ -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)
]);
}

View File

@ -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',
]; ];

View File

@ -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);

View File

@ -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"

View File

@ -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"

View File

@ -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 %}

View File

@ -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) %}

View File

@ -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>

View File

@ -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]
);
}
}

View File

@ -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'));

View File

@ -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();
}
}