Improved the warning management UI.
This commit is contained in:
parent
a34a546ace
commit
e1c2c97669
8 changed files with 228 additions and 76 deletions
assets/less/classes
public/manage
src/Users
templates
|
@ -8,6 +8,10 @@
|
|||
overflow: hidden;
|
||||
word-wrap: break-word;
|
||||
|
||||
&--lazy {
|
||||
margin-bottom: 2px;
|
||||
}
|
||||
|
||||
&__title {
|
||||
display: block;
|
||||
overflow: hidden;
|
||||
|
|
|
@ -19,6 +19,10 @@
|
|||
--accent-colour: #c33;
|
||||
}
|
||||
|
||||
&--extendo {
|
||||
margin: 4px;
|
||||
}
|
||||
|
||||
&__background {
|
||||
background-color: var(--accent-colour);
|
||||
position: absolute;
|
||||
|
@ -77,4 +81,57 @@
|
|||
opacity: 1;
|
||||
}
|
||||
}
|
||||
|
||||
&__tools {
|
||||
display: flex;
|
||||
padding-bottom: 1px;
|
||||
|
||||
@media (max-width: @site-mobile-width) {
|
||||
flex-direction: column;
|
||||
}
|
||||
}
|
||||
|
||||
&__options {
|
||||
flex: 1 1 auto;
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
align-items: center;
|
||||
|
||||
@media (max-width: @site-mobile-width) {
|
||||
justify-content: flex-start;
|
||||
}
|
||||
}
|
||||
|
||||
&__option {
|
||||
padding: 2px 5px;
|
||||
color: inherit;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
&__user {
|
||||
display: flex;
|
||||
padding: 2px;
|
||||
min-width: 300px;
|
||||
|
||||
&__avatar {
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
}
|
||||
|
||||
&__username {
|
||||
padding: 0 5px;
|
||||
min-width: 60px;
|
||||
}
|
||||
|
||||
&__ip {
|
||||
display: inline-flex;
|
||||
|
||||
&:before {
|
||||
content: "(";
|
||||
}
|
||||
&:after {
|
||||
content: ")";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -111,10 +111,6 @@ switch ($_GET['v'] ?? null) {
|
|||
tpl_var('permissions', $permissions = manage_perms_list(perms_get_user_raw($userId)));
|
||||
}
|
||||
|
||||
if ($canManageWarnings) {
|
||||
tpl_var('warning_types', $warnTypes = user_warning_get_types());
|
||||
}
|
||||
|
||||
if ($isPostRequest) {
|
||||
if (!csrf_verify('users_edit', $_POST['csrf'] ?? '')) {
|
||||
echo 'csrf err';
|
||||
|
@ -238,18 +234,6 @@ switch ($_GET['v'] ?? null) {
|
|||
}
|
||||
}
|
||||
|
||||
if (!empty($warnTypes) && !empty($_POST['warning']) && is_array($_POST['warning'])) {
|
||||
user_warning_add(
|
||||
$userId,
|
||||
user_get_last_ip($userId),
|
||||
user_session_current('user_id'),
|
||||
ip_remote_address(),
|
||||
$_POST['warning']['type'],
|
||||
$_POST['warning']['note'],
|
||||
$_POST['warning']['private']
|
||||
);
|
||||
}
|
||||
|
||||
header("Location: ?v=view&u={$manageUser['user_id']}");
|
||||
break;
|
||||
}
|
||||
|
@ -290,13 +274,12 @@ switch ($_GET['v'] ?? null) {
|
|||
$getManageRoles->bindValue('take', $rolesTake);
|
||||
$manageRoles = $getManageRoles->execute() ? $getManageRoles->fetchAll() : [];
|
||||
|
||||
tpl_vars([
|
||||
echo tpl_render('manage.users.roles', [
|
||||
'manage_roles' => $manageRoles,
|
||||
'manage_roles_count' => $manageRolesCount,
|
||||
'manage_roles_range' => $rolesTake,
|
||||
'manage_roles_offset' => $queryQffset,
|
||||
]);
|
||||
echo tpl_render('manage.users.roles');
|
||||
break;
|
||||
|
||||
case 'role':
|
||||
|
@ -485,10 +468,49 @@ switch ($_GET['v'] ?? null) {
|
|||
break;
|
||||
}
|
||||
|
||||
if (!empty($_POST['warning']) && is_array($_POST['warning'])) {
|
||||
$warningType = (int)($_POST['warning']['type'] ?? 0);
|
||||
|
||||
if (user_warning_type_is_valid($warningType)) {
|
||||
$warningsUser = max(0, (int)($_POST['warning']['user'] ?? 0));
|
||||
$warningId = user_warning_add(
|
||||
$warningsUser,
|
||||
user_get_last_ip($warningsUser),
|
||||
user_session_current('user_id'),
|
||||
ip_remote_address(),
|
||||
$warningType,
|
||||
$_POST['warning']['note'],
|
||||
$_POST['warning']['private']
|
||||
);
|
||||
}
|
||||
} elseif (!empty($_POST['lookup']) && is_string($_POST['lookup'])) {
|
||||
$userId = user_id_from_username($_POST['lookup']);
|
||||
header("Location: ?v=warnings&u={$userId}");
|
||||
return;
|
||||
} elseif (!empty($_GET['m'])) {
|
||||
$warningId = (int)($_GET['w'] ?? 0);
|
||||
$modeName = $_GET['m'] ?? '';
|
||||
$csrfRealm = "warning-{$modeName}[{$warningId}]";
|
||||
|
||||
if (csrf_verify($csrfRealm, $_GET['c'] ?? '')) {
|
||||
switch ($modeName) {
|
||||
case 'delete':
|
||||
user_warning_remove($warningId);
|
||||
break;
|
||||
}
|
||||
header('Location: ' . ($_SERVER['HTTP_REFERER'] ?? '?m=warnings' . (empty($_GET['u']) ? '' : '&u=' . (int)($_GET['u']))));
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (empty($warningsUser)) {
|
||||
$warningsUser = max(0, (int)($_GET['u'] ?? 0));
|
||||
}
|
||||
|
||||
$warningsCount = user_warning_global_count();
|
||||
$warningsTake = 50;
|
||||
$warningsOffset = max(0, (int)($_GET['o'] ?? 0));
|
||||
$warningsList = user_warning_global_fetch($warningsOffset, $warningsTake);
|
||||
$warningsList = user_warning_global_fetch($warningsOffset, $warningsTake, $warningsUser);
|
||||
|
||||
echo tpl_render('manage.users.warnings', [
|
||||
'warnings' => [
|
||||
|
@ -496,6 +518,9 @@ switch ($_GET['v'] ?? null) {
|
|||
'take' => $warningsTake,
|
||||
'offset' => $warningsOffset,
|
||||
'list' => $warningsList,
|
||||
'user_id' => $warningsUser,
|
||||
'username' => user_username_from_id($warningsUser),
|
||||
'types' => user_warning_get_types(),
|
||||
],
|
||||
]);
|
||||
break;
|
||||
|
|
|
@ -138,6 +138,13 @@ function user_id_from_username(string $username): int
|
|||
return $getId->execute() ? (int)$getId->fetchColumn() : 0;
|
||||
}
|
||||
|
||||
function user_username_from_id(int $userId): string
|
||||
{
|
||||
$getName = db_prepare('SELECT `username` FROM `msz_users` WHERE `user_id` = :user_id');
|
||||
$getName->bindValue('user_id', $userId);
|
||||
return $getName->execute() ? $getName->fetchColumn() : '';
|
||||
}
|
||||
|
||||
function user_bump_last_active(int $userId, string $ipAddress = null): void
|
||||
{
|
||||
$bumpUserLast = db_prepare('
|
||||
|
|
|
@ -54,6 +54,10 @@ function user_warning_add(
|
|||
return -1;
|
||||
}
|
||||
|
||||
if ($userId < 1) {
|
||||
return -2;
|
||||
}
|
||||
|
||||
$addWarning = db_prepare('
|
||||
INSERT INTO `msz_user_warnings`
|
||||
(`user_id`, `user_ip`, `issuer_id`, `issuer_ip`, `warning_type`, `warning_note`, `warning_note_private`)
|
||||
|
@ -144,25 +148,34 @@ function user_warning_global_count(): int
|
|||
return (int)$countWarnings->fetchColumn();
|
||||
}
|
||||
|
||||
function user_warning_global_fetch(int $offset, int $take): array
|
||||
function user_warning_global_fetch(int $offset = 0, int $take = 50, ?int $userId = null): array
|
||||
{
|
||||
$fetchWarnings = db_prepare('
|
||||
SELECT
|
||||
uw.`warning_id`, uw.`warning_created`, uw.`warning_type`, uw.`warning_note`,
|
||||
uw.`warning_note_private`, uw.`user_id`, uw.`issuer_id`, uw.`warning_duration`,
|
||||
TIMESTAMPDIFF(SECOND, uw.`warning_created`, uw.`warning_duration`) AS `warning_duration_secs`,
|
||||
INET6_NTOA(uw.`user_ip`) AS `user_ip`, INET6_NTOA(uw.`issuer_ip`) AS `issuer_ip`,
|
||||
iu.`username` AS `issuer_username`, wu.`username` AS `username`
|
||||
FROM `msz_user_warnings` AS uw
|
||||
LEFT JOIN `msz_users` AS iu
|
||||
ON iu.`user_id` = uw.`issuer_id`
|
||||
LEFT JOIN `msz_users` AS wu
|
||||
ON wu.`user_id` = uw.`user_id`
|
||||
ORDER BY uw.`warning_id` DESC
|
||||
LIMIT :offset, :take
|
||||
');
|
||||
$fetchWarnings = db_prepare(sprintf(
|
||||
'
|
||||
SELECT
|
||||
uw.`warning_id`, uw.`warning_created`, uw.`warning_type`, uw.`warning_note`,
|
||||
uw.`warning_note_private`, uw.`user_id`, uw.`issuer_id`, uw.`warning_duration`,
|
||||
TIMESTAMPDIFF(SECOND, uw.`warning_created`, uw.`warning_duration`) AS `warning_duration_secs`,
|
||||
INET6_NTOA(uw.`user_ip`) AS `user_ip`, INET6_NTOA(uw.`issuer_ip`) AS `issuer_ip`,
|
||||
iu.`username` AS `issuer_username`, wu.`username` AS `username`
|
||||
FROM `msz_user_warnings` AS uw
|
||||
LEFT JOIN `msz_users` AS iu
|
||||
ON iu.`user_id` = uw.`issuer_id`
|
||||
LEFT JOIN `msz_users` AS wu
|
||||
ON wu.`user_id` = uw.`user_id`
|
||||
%1$s
|
||||
ORDER BY uw.`warning_id` DESC
|
||||
LIMIT :offset, :take
|
||||
',
|
||||
$userId > 0 ? 'WHERE uw.`user_id` = :user_id' : ''
|
||||
));
|
||||
$fetchWarnings->bindValue('offset', $offset);
|
||||
$fetchWarnings->bindValue('take', $take);
|
||||
|
||||
if ($userId > 0) {
|
||||
$fetchWarnings->bindValue('user_id', $userId);
|
||||
}
|
||||
|
||||
$warnings = $fetchWarnings->execute() ? $fetchWarnings->fetchAll(PDO::FETCH_ASSOC) : false;
|
||||
return $warnings ? $warnings : [];
|
||||
}
|
||||
|
|
|
@ -139,20 +139,6 @@
|
|||
</form>
|
||||
{% endif %}
|
||||
|
||||
{% if can_manage_warns %}
|
||||
<form class="container" method="post" action="">
|
||||
{{ container_title('Add Warning') }}
|
||||
{{ input_csrf('users_edit') }}
|
||||
|
||||
{{ input_select('warning[type]', warning_types) }}
|
||||
{{ input_text('warning[note]', '', '', 'text', 'Public note') }}
|
||||
{{ input_text('warning[until]', '', ''|date('c'), 'datetime-local') }} (empty to set null)
|
||||
<button class="input__button">Add</button><br>
|
||||
|
||||
<textarea class="input__textarea" name="warning[private]" placeholder="Private note"></textarea>
|
||||
</form>
|
||||
{% endif %}
|
||||
|
||||
{% if can_manage_users %}
|
||||
{% if has_roles|length > 0 %}
|
||||
<form method="post" action="" class="container">
|
||||
|
|
|
@ -1,18 +1,60 @@
|
|||
{% extends 'manage/users/master.twig' %}
|
||||
{% from 'macros.twig' import pagination, container_title %}
|
||||
{% from 'user/macros.twig' import user_profile_warning %}
|
||||
{% from '_layout/input.twig' import input_text, input_csrf, input_select, input_hidden %}
|
||||
|
||||
{% block manage_content %}
|
||||
<div class="container">
|
||||
<form class="container container--lazy" action="" method="post">
|
||||
{{ container_title('<i class="fas fa-users fa-fw"></i> Filters') }}
|
||||
{{ input_text('lookup', null, warnings.username, 'text', 'Enter a username') }}
|
||||
<button class="input__button">Filter</button>
|
||||
</form>
|
||||
|
||||
{% if warnings.user_id > 0 and warnings.username|length > 0 %}{# shittiest validation in the world, but it should work #}
|
||||
<form class="container container--lazy" method="post" action="">
|
||||
{{ container_title('<i class="fas fa-user-shield fa-fw"></i> Warn ' ~ warnings.username) }}
|
||||
{{ input_csrf('users_edit') }}
|
||||
{{ input_hidden('warning[user]', warnings.user_id) }}
|
||||
|
||||
{{ input_select('warning[type]', warnings.types) }}
|
||||
{{ input_text('warning[note]', '', '', 'text', 'Public note') }}
|
||||
{{ input_text('warning[until]', '', ''|date('c'), 'datetime-local') }} (empty to set null)
|
||||
<button class="input__button">Add</button><br>
|
||||
|
||||
<textarea class="input__textarea" name="warning[private]" placeholder="Private note"></textarea>
|
||||
</form>
|
||||
{% endif %}
|
||||
|
||||
<div class="container container--lazy">
|
||||
{{ container_title('<i class="fas fa-exclamation-circle fa-fw"></i> Warnings') }}
|
||||
{% set warnpag = pagination(warnings.count, warnings.take, warnings.offset, '/manage/users.php?v=warnings') %}
|
||||
|
||||
{{ warnpag }}
|
||||
|
||||
<div class="profile__warnings__container">
|
||||
<div class="profile__warning">
|
||||
<div class="profile__warning profile__warning--extendo">
|
||||
<div class="profile__warning__background"></div>
|
||||
|
||||
<div class="profile__warning__tools">
|
||||
<div class="profile__warning__user">
|
||||
<div class="profile__warning__user__username">
|
||||
User
|
||||
</div>
|
||||
<div class="profile__warning__user__ip">
|
||||
User IP
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="profile__warning__user">
|
||||
<div class="profile__warning__user__username">
|
||||
Issuer
|
||||
</div>
|
||||
<div class="profile__warning__user__ip">
|
||||
Issuer IP
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="profile__warning__content">
|
||||
<div class="profile__warning__type">
|
||||
Type
|
||||
|
@ -33,30 +75,8 @@
|
|||
</div>
|
||||
|
||||
{% for warning in warnings.list %}
|
||||
{{ user_profile_warning(warning) }}
|
||||
{{ user_profile_warning(warning, true, true, true, true, csrf_token('warning-delete[%d]'|format(warning.warning_id))) }}
|
||||
{% endfor %}
|
||||
|
||||
<div class="profile__warning">
|
||||
<div class="profile__warning__background"></div>
|
||||
|
||||
<div class="profile__warning__content">
|
||||
<div class="profile__warning__type">
|
||||
Type
|
||||
</div>
|
||||
|
||||
<div class="profile__warning__created">
|
||||
Created
|
||||
</div>
|
||||
|
||||
<div class="profile__warning__duration">
|
||||
Expires
|
||||
</div>
|
||||
|
||||
<div class="profile__warning__note">
|
||||
Note
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{{ warnpag }}
|
||||
|
|
|
@ -222,7 +222,7 @@
|
|||
</div>
|
||||
{% endmacro %}
|
||||
|
||||
{% macro user_profile_warning(warning, show_private_note) %}
|
||||
{% macro user_profile_warning(warning, show_private_note, show_user, show_issuer, show_ips, delete_csrf) %}
|
||||
{% if warning.warning_type == constant('MSZ_WARN_SILENCE') %}
|
||||
{% set warning_text = 'Silence' %}
|
||||
{% set warning_class = 'silence' %}
|
||||
|
@ -237,9 +237,49 @@
|
|||
{% set warning_class = 'note' %}
|
||||
{% endif %}
|
||||
|
||||
<div class="profile__warning profile__warning--{{ warning_class }}">
|
||||
<div class="profile__warning profile__warning--{{ warning_class }}{% if show_user or show_issuer or delete_csrf %} profile__warning--extendo{% endif %}">
|
||||
<div class="profile__warning__background"></div>
|
||||
|
||||
{% if show_user or show_issuer or delete_csrf %}
|
||||
<div class="profile__warning__tools">
|
||||
{% if show_user %}
|
||||
<div class="profile__warning__user">
|
||||
<div class="avatar profile__warning__user__avatar" style="background-image:url('/profile.php?m=avatar&u={{ warning.user_id }}');"></div>
|
||||
<div class="profile__warning__user__username">
|
||||
{{ warning.username }}
|
||||
</div>
|
||||
|
||||
{% if show_ips %}
|
||||
<div class="profile__warning__user__ip">
|
||||
{{ warning.user_ip }}
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
{% if show_issuer %}
|
||||
<div class="profile__warning__user">
|
||||
<div class="avatar profile__warning__user__avatar" style="background-image:url('/profile.php?m=avatar&u={{ warning.issuer_id }}');"></div>
|
||||
<div class="profile__warning__user__username">
|
||||
{{ warning.issuer_username }}
|
||||
</div>
|
||||
|
||||
{% if show_ips %}
|
||||
<div class="profile__warning__user__ip">
|
||||
{{ warning.issuer_ip }}
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
{% if delete_csrf %}
|
||||
<div class="profile__warning__options">
|
||||
<a href="/manage/users.php?v=warnings&u={{ warning.user_id }}&w={{ warning.warning_id }}&m=delete&c={{ delete_csrf }}" class="profile__warning__option"><i class="far fa-trash-alt"></i> Delete</a>
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
<div class="profile__warning__content">
|
||||
<div class="profile__warning__type">
|
||||
{{ warning_text }}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue