big restructure
This commit is contained in:
@@ -20,10 +20,14 @@
|
||||
* @var bool $isReadOnly
|
||||
* @var bool $showPermissions
|
||||
* @var array $permissionRows
|
||||
* @var bool $showPasswordResets
|
||||
* @var array $passwordResets
|
||||
* @var bool $showRememberTokens
|
||||
* @var array $rememberTokens
|
||||
*/
|
||||
|
||||
use MintyPHP\Session;
|
||||
use MintyPHP\Service\UserService;
|
||||
use MintyPHP\Service\User\UserService;
|
||||
use MintyPHP\I18n;
|
||||
|
||||
$values = $values ?? [];
|
||||
@@ -50,6 +54,10 @@ if (!$primaryTenantId && count($selectedTenantIds) === 1) {
|
||||
$isReadOnly = $isReadOnly ?? false;
|
||||
$permissionRows = $permissionRows ?? [];
|
||||
$showPermissions = $showPermissions ?? false;
|
||||
$passwordResets = $passwordResets ?? [];
|
||||
$showPasswordResets = $showPasswordResets ?? false;
|
||||
$rememberTokens = $rememberTokens ?? [];
|
||||
$showRememberTokens = $showRememberTokens ?? false;
|
||||
$minLength = UserService::passwordMinLength();
|
||||
$requiredAttr = $passwordRequired ? 'required' : '';
|
||||
$readonlyAttr = $isReadOnly ? 'readonly' : '';
|
||||
@@ -73,12 +81,16 @@ $showOrganization = $showTenants || $showDepartments || $showRoles;
|
||||
<?php if ($showPermissions): ?>
|
||||
<button type="button" data-tab="permissions"><?php e(t('Permissions')); ?></button>
|
||||
<?php endif; ?>
|
||||
<?php if ($showPasswordResets): ?>
|
||||
<button type="button" data-tab="password-resets"><?php e(t('Password resets')); ?></button>
|
||||
<?php endif; ?>
|
||||
<?php if ($showRememberTokens): ?>
|
||||
<button type="button" data-tab="login-tokens"><?php e(t('Login tokens')); ?></button>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
|
||||
<div data-tab-panel="profile">
|
||||
<details name="identity-data" open>
|
||||
<summary><?php e(t('Identity')); ?></summary>
|
||||
<hr>
|
||||
|
||||
<div class="grid">
|
||||
<label for="first_name">
|
||||
<span><?php e(t('First name')); ?></span>
|
||||
@@ -95,7 +107,7 @@ $showOrganization = $showTenants || $showDepartments || $showRoles;
|
||||
<span><?php e(t('Email')); ?></span>
|
||||
<input required type="email" name="email" id="email" value="<?php e($values['email'] ?? ''); ?>" <?php e($readonlyAttr); ?> />
|
||||
</label>
|
||||
</details>
|
||||
|
||||
<hr>
|
||||
<details name="profile-data" open>
|
||||
<summary><?php e(t('Profile')); ?></summary>
|
||||
@@ -119,14 +131,19 @@ $showOrganization = $showTenants || $showDepartments || $showRoles;
|
||||
<?php if (allowUserTheme()): ?>
|
||||
<label for="theme">
|
||||
<span><?php e(t('Theme')); ?></span>
|
||||
<?php $selectedTheme = $values['theme'] ?? 'light'; ?>
|
||||
<?php
|
||||
$themes = appThemes();
|
||||
$selectedTheme = (string) ($values['theme'] ?? '');
|
||||
if ($selectedTheme === '' || !isset($themes[$selectedTheme])) {
|
||||
$selectedTheme = appDefaultTheme();
|
||||
}
|
||||
?>
|
||||
<select name="theme" id="theme" <?php e($disabledAttr); ?>>
|
||||
<option value="light" <?php if ($selectedTheme === 'light') { ?>selected<?php } ?>>
|
||||
<?php e(t('Light')); ?>
|
||||
</option>
|
||||
<option value="dark" <?php if ($selectedTheme === 'dark') { ?>selected<?php } ?>>
|
||||
<?php e(t('Dark')); ?>
|
||||
</option>
|
||||
<?php foreach ($themes as $key => $label): ?>
|
||||
<option value="<?php e($key); ?>" <?php if ($selectedTheme === $key) { ?>selected<?php } ?>>
|
||||
<?php e(t($label)); ?>
|
||||
</option>
|
||||
<?php endforeach; ?>
|
||||
</select>
|
||||
</label>
|
||||
<?php endif; ?>
|
||||
@@ -154,9 +171,7 @@ $showOrganization = $showTenants || $showDepartments || $showRoles;
|
||||
</div>
|
||||
|
||||
<div data-tab-panel="access">
|
||||
<details name="access-data" open>
|
||||
<summary><?php e(t('Access & password')); ?></summary>
|
||||
<hr>
|
||||
|
||||
<div class="grid">
|
||||
<div>
|
||||
<label for="password">
|
||||
@@ -188,7 +203,6 @@ $showOrganization = $showTenants || $showDepartments || $showRoles;
|
||||
<span><?php e(t('Active')); ?></span>
|
||||
</label>
|
||||
<?php endif; ?>
|
||||
</details>
|
||||
</div>
|
||||
|
||||
<?php if ($showOrganization): ?>
|
||||
@@ -313,45 +327,152 @@ $showOrganization = $showTenants || $showDepartments || $showRoles;
|
||||
</div>
|
||||
<?php if ($showPermissions): ?>
|
||||
<div data-tab-panel="permissions">
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th><?php e(t('Description')); ?></th>
|
||||
<th><?php e(t('Permission key')); ?></th>
|
||||
<th><?php e(t('Permission origin')); ?></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<?php foreach ($permissionRows as $permissionRow): ?>
|
||||
<?php
|
||||
$permissionKey = (string) ($permissionRow['key'] ?? '');
|
||||
$labelKey = 'perm.' . $permissionKey;
|
||||
$label = t($labelKey);
|
||||
if ($label === $labelKey) {
|
||||
$label = (string) ($permissionRow['description'] ?? '');
|
||||
if ($label === '') {
|
||||
$label = $permissionKey;
|
||||
}
|
||||
}
|
||||
$rolesList = [];
|
||||
if (!empty($permissionRow['roles']) && is_array($permissionRow['roles'])) {
|
||||
$rolesList = $permissionRow['roles'];
|
||||
}
|
||||
?>
|
||||
<div class="overflow-auto white-space-nowrap">
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<td><?php e($label); ?></td>
|
||||
<td><code><?php e($permissionKey); ?></code></td>
|
||||
<td>
|
||||
<?php if ($rolesList): ?>
|
||||
<?php foreach ($rolesList as $roleLabel): ?>
|
||||
<span class="badge" data-variant="neutral"><?php e($roleLabel); ?></span>
|
||||
<?php endforeach; ?>
|
||||
<?php endif; ?>
|
||||
</td>
|
||||
<th><?php e(t('Description')); ?></th>
|
||||
<th><?php e(t('Permission key')); ?></th>
|
||||
<th><?php e(t('Permission origin')); ?></th>
|
||||
</tr>
|
||||
<?php endforeach; ?>
|
||||
</tbody>
|
||||
</table>
|
||||
</thead>
|
||||
<tbody>
|
||||
<?php foreach ($permissionRows as $permissionRow): ?>
|
||||
<?php
|
||||
$permissionKey = (string) ($permissionRow['key'] ?? '');
|
||||
$labelKey = 'perm.' . $permissionKey;
|
||||
$label = t($labelKey);
|
||||
if ($label === $labelKey) {
|
||||
$label = (string) ($permissionRow['description'] ?? '');
|
||||
if ($label === '') {
|
||||
$label = $permissionKey;
|
||||
}
|
||||
}
|
||||
$rolesList = [];
|
||||
if (!empty($permissionRow['roles']) && is_array($permissionRow['roles'])) {
|
||||
$rolesList = $permissionRow['roles'];
|
||||
}
|
||||
?>
|
||||
<tr>
|
||||
<td><?php e($label); ?></td>
|
||||
<td><code><?php e($permissionKey); ?></code></td>
|
||||
<td>
|
||||
<?php if ($rolesList): ?>
|
||||
<?php foreach ($rolesList as $roleLabel): ?>
|
||||
<span class="badge" data-variant="neutral"><?php e($roleLabel); ?></span>
|
||||
<?php endforeach; ?>
|
||||
<?php endif; ?>
|
||||
</td>
|
||||
</tr>
|
||||
<?php endforeach; ?>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
<?php if ($showPasswordResets): ?>
|
||||
<div data-tab-panel="password-resets">
|
||||
<div class="overflow-auto white-space-nowrap">
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th><?php e(t('Requested at')); ?></th>
|
||||
<th><?php e(t('Expires at')); ?></th>
|
||||
<th><?php e(t('Used at')); ?></th>
|
||||
<th><?php e(t('Attempts')); ?></th>
|
||||
<th><?php e(t('Status')); ?></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<?php foreach ($passwordResets as $reset): ?>
|
||||
<?php
|
||||
$expiresAt = (string) ($reset['expires_at'] ?? '');
|
||||
$usedAt = (string) ($reset['used_at'] ?? '');
|
||||
$status = t('Active');
|
||||
$statusVariant = 'success';
|
||||
if ($usedAt !== '') {
|
||||
$status = t('Used');
|
||||
$statusVariant = 'neutral';
|
||||
} elseif ($expiresAt !== '') {
|
||||
try {
|
||||
$expired = (new \DateTimeImmutable($expiresAt)) <= new \DateTimeImmutable('now');
|
||||
if ($expired) {
|
||||
$status = t('Expired');
|
||||
$statusVariant = 'warning';
|
||||
}
|
||||
} catch (\Exception $e) {
|
||||
// fallback: keep Active
|
||||
}
|
||||
}
|
||||
?>
|
||||
<tr>
|
||||
<td><?php e(dt($reset['created'] ?? '')); ?></td>
|
||||
<td><?php e($expiresAt !== '' ? dt($expiresAt) : '-'); ?></td>
|
||||
<td><?php e($usedAt !== '' ? dt($usedAt) : '-'); ?></td>
|
||||
<td><?php e((string) ($reset['attempts'] ?? 0)); ?></td>
|
||||
<td>
|
||||
<span class="badge" data-variant="<?php e($statusVariant); ?>">
|
||||
<?php e($status); ?>
|
||||
</span>
|
||||
</td>
|
||||
</tr>
|
||||
<?php endforeach; ?>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
<?php if ($showRememberTokens): ?>
|
||||
<div data-tab-panel="login-tokens">
|
||||
<div class="overflow-auto white-space-nowrap">
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th><?php e(t('Created at')); ?></th>
|
||||
<th><?php e(t('Expires at')); ?></th>
|
||||
<th><?php e(t('Last used')); ?></th>
|
||||
<th><?php e(t('Status')); ?></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<?php foreach ($rememberTokens as $token): ?>
|
||||
<?php
|
||||
$expiresAt = (string) ($token['expires_at'] ?? '');
|
||||
$expiredByAdminAt = (string) ($token['expired_by_admin_at'] ?? '');
|
||||
$lastUsed = (string) ($token['last_used'] ?? '');
|
||||
$status = t('Active');
|
||||
$statusVariant = 'success';
|
||||
if ($expiresAt !== '') {
|
||||
try {
|
||||
$expired = (new \DateTimeImmutable($expiresAt)) <= new \DateTimeImmutable('now');
|
||||
if ($expired) {
|
||||
if ($expiredByAdminAt !== '') {
|
||||
$status = t('Expired by admin');
|
||||
$statusVariant = 'warning';
|
||||
} else {
|
||||
$status = t('Expired');
|
||||
$statusVariant = 'warning';
|
||||
}
|
||||
}
|
||||
} catch (\Exception $e) {
|
||||
// fallback: keep Active
|
||||
}
|
||||
}
|
||||
?>
|
||||
<tr>
|
||||
<td><?php e(dt($token['created'] ?? '')); ?></td>
|
||||
<td><?php e($expiresAt !== '' ? dt($expiresAt) : '-'); ?></td>
|
||||
<td><?php e($lastUsed !== '' ? dt($lastUsed) : '-'); ?></td>
|
||||
<td>
|
||||
<span class="badge" data-variant="<?php e($statusVariant); ?>">
|
||||
<?php e($status); ?>
|
||||
</span>
|
||||
</td>
|
||||
</tr>
|
||||
<?php endforeach; ?>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
|
||||
@@ -2,9 +2,9 @@
|
||||
|
||||
use MintyPHP\Support\Guard;
|
||||
use MintyPHP\Router;
|
||||
use MintyPHP\Service\UserService;
|
||||
use MintyPHP\Service\User\UserService;
|
||||
use MintyPHP\Http\Request;
|
||||
use MintyPHP\Service\TenantScopeService;
|
||||
use MintyPHP\Service\Tenant\TenantScopeService;
|
||||
|
||||
Guard::requireLogin();
|
||||
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
<?php
|
||||
|
||||
use MintyPHP\Router;
|
||||
use MintyPHP\Service\UserAvatarService;
|
||||
use MintyPHP\Service\User\UserAvatarService;
|
||||
use MintyPHP\Support\Flash;
|
||||
use MintyPHP\Support\Guard;
|
||||
use MintyPHP\Service\UserService;
|
||||
use MintyPHP\Service\TenantScopeService;
|
||||
use MintyPHP\Service\User\UserService;
|
||||
use MintyPHP\Service\Tenant\TenantScopeService;
|
||||
|
||||
Guard::requireLogin();
|
||||
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
<?php
|
||||
|
||||
use MintyPHP\Router;
|
||||
use MintyPHP\Service\UserAvatarService;
|
||||
use MintyPHP\Service\User\UserAvatarService;
|
||||
use MintyPHP\Support\Flash;
|
||||
use MintyPHP\Support\Guard;
|
||||
use MintyPHP\Service\UserService;
|
||||
use MintyPHP\Service\TenantScopeService;
|
||||
use MintyPHP\Service\User\UserService;
|
||||
use MintyPHP\Service\Tenant\TenantScopeService;
|
||||
|
||||
Guard::requireLogin();
|
||||
|
||||
|
||||
@@ -1,10 +1,12 @@
|
||||
<?php
|
||||
|
||||
use MintyPHP\Service\UserAvatarService;
|
||||
use MintyPHP\Service\UserService;
|
||||
use MintyPHP\Service\TenantScopeService;
|
||||
use MintyPHP\Service\User\UserAvatarService;
|
||||
use MintyPHP\Service\User\UserService;
|
||||
use MintyPHP\Service\Tenant\TenantScopeService;
|
||||
use MintyPHP\Support\Guard;
|
||||
|
||||
define('MINTY_ALLOW_OUTPUT', true);
|
||||
|
||||
Guard::requireLogin();
|
||||
|
||||
$uuid = trim((string) ($_GET['uuid'] ?? ''));
|
||||
|
||||
@@ -3,9 +3,9 @@
|
||||
use MintyPHP\Support\Guard;
|
||||
use MintyPHP\Http\Request;
|
||||
use MintyPHP\Router;
|
||||
use MintyPHP\Service\PermissionService;
|
||||
use MintyPHP\Service\UserService;
|
||||
use MintyPHP\Service\MailService;
|
||||
use MintyPHP\Service\Access\PermissionService;
|
||||
use MintyPHP\Service\User\UserService;
|
||||
use MintyPHP\Service\Mail\MailService;
|
||||
use MintyPHP\I18n;
|
||||
|
||||
Guard::requireLogin();
|
||||
|
||||
@@ -5,13 +5,13 @@ use MintyPHP\Support\Flash;
|
||||
use MintyPHP\Support\Guard;
|
||||
use MintyPHP\I18n;
|
||||
use MintyPHP\Router;
|
||||
use MintyPHP\Service\PermissionService;
|
||||
use MintyPHP\Service\UserService;
|
||||
use MintyPHP\Service\TenantScopeService;
|
||||
use MintyPHP\Service\TenantService;
|
||||
use MintyPHP\Service\RoleService;
|
||||
use MintyPHP\Service\DepartmentService;
|
||||
use MintyPHP\Service\SettingService;
|
||||
use MintyPHP\Service\Access\PermissionService;
|
||||
use MintyPHP\Service\User\UserService;
|
||||
use MintyPHP\Service\Tenant\TenantScopeService;
|
||||
use MintyPHP\Service\Tenant\TenantService;
|
||||
use MintyPHP\Service\Access\RoleService;
|
||||
use MintyPHP\Service\Org\DepartmentService;
|
||||
use MintyPHP\Service\Settings\SettingService;
|
||||
|
||||
Guard::requirePermissionOrForbidden(PermissionService::USERS_CREATE);
|
||||
|
||||
@@ -27,7 +27,7 @@ if ($allowedTenantIds) {
|
||||
} elseif (TenantScopeService::isStrict()) {
|
||||
$tenants = [];
|
||||
}
|
||||
$roles = RoleService::list();
|
||||
$roles = RoleService::listActive();
|
||||
$departments = $allowedTenantIds ? DepartmentService::listByTenantIds($allowedTenantIds) : [];
|
||||
if (!$allowedTenantIds && !TenantScopeService::isStrict()) {
|
||||
$departments = DepartmentService::list();
|
||||
|
||||
@@ -11,10 +11,14 @@
|
||||
<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/users"><?php e(t('Users')); ?></a><i class="bi bi-chevron-right"></i><?php e(t('Create user')); ?>
|
||||
</div>
|
||||
<?php
|
||||
$breadcrumbs = [
|
||||
['label' => t('Home'), 'path' => 'admin'],
|
||||
['label' => t('Users'), 'path' => 'admin/users'],
|
||||
['label' => t('Create user')],
|
||||
];
|
||||
require templatePath('partials/app-breadcrumb.phtml');
|
||||
?>
|
||||
<div class="app-details-titlebar">
|
||||
<h1>
|
||||
<a href="admin/users" title="<?php e(t('Cancel')); ?>"><i class="bi bi-arrow-left"></i></a>
|
||||
@@ -48,4 +52,4 @@
|
||||
require __DIR__ . '/_form.phtml';
|
||||
?>
|
||||
</section>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
<?php
|
||||
|
||||
use MintyPHP\Router;
|
||||
use MintyPHP\Service\UserService;
|
||||
use MintyPHP\Service\UserAvatarService;
|
||||
use MintyPHP\Service\TenantScopeService;
|
||||
use MintyPHP\Service\User\UserService;
|
||||
use MintyPHP\Service\User\UserAvatarService;
|
||||
use MintyPHP\Service\Tenant\TenantScopeService;
|
||||
|
||||
if (!isset($_SESSION['user'])) {
|
||||
http_response_code(401);
|
||||
@@ -24,6 +24,7 @@ $tenant = trim((string) ($_GET['tenant'] ?? ''));
|
||||
$roles = $_GET['roles'] ?? '';
|
||||
$departments = $_GET['departments'] ?? '';
|
||||
$emailVerified = $_GET['email_verified'] ?? 'all';
|
||||
$loginStatus = $_GET['login_status'] ?? 'all';
|
||||
|
||||
$result = UserService::listPaged([
|
||||
'limit' => $limit,
|
||||
@@ -38,6 +39,7 @@ $result = UserService::listPaged([
|
||||
'roles' => $roles,
|
||||
'departments' => $departments,
|
||||
'email_verified' => $emailVerified,
|
||||
'login_status' => $loginStatus,
|
||||
'tenantUserId' => $currentUserId,
|
||||
]);
|
||||
|
||||
@@ -95,6 +97,7 @@ foreach ($result['rows'] as $row) {
|
||||
'roles' => $roleList,
|
||||
'created' => dt($row['created'] ?? ''),
|
||||
'modified' => dt($row['modified'] ?? ''),
|
||||
'last_login' => dt($row['last_login_at'] ?? ''),
|
||||
'active' => (int) ($row['active'] ?? 0),
|
||||
'has_avatar' => $uuid !== '' && UserAvatarService::hasAvatar($uuid),
|
||||
];
|
||||
|
||||
@@ -3,9 +3,9 @@
|
||||
use MintyPHP\Support\Flash;
|
||||
use MintyPHP\Support\Guard;
|
||||
use MintyPHP\Router;
|
||||
use MintyPHP\Service\UserService;
|
||||
use MintyPHP\Service\User\UserService;
|
||||
use MintyPHP\Http\Request;
|
||||
use MintyPHP\Service\TenantScopeService;
|
||||
use MintyPHP\Service\Tenant\TenantScopeService;
|
||||
|
||||
Guard::requireLogin();
|
||||
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
<?php
|
||||
|
||||
use MintyPHP\Router;
|
||||
use MintyPHP\Service\UserService;
|
||||
use MintyPHP\Service\PermissionService;
|
||||
use MintyPHP\Service\User\UserService;
|
||||
use MintyPHP\Service\Access\PermissionService;
|
||||
use MintyPHP\Support\Flash;
|
||||
use MintyPHP\Support\Guard;
|
||||
use MintyPHP\Http\Request;
|
||||
use MintyPHP\Service\TenantScopeService;
|
||||
use MintyPHP\Service\Tenant\TenantScopeService;
|
||||
|
||||
Guard::requireLogin();
|
||||
Guard::requirePermissionOrForbidden(PermissionService::USERS_DELETE);
|
||||
|
||||
@@ -5,17 +5,19 @@ use MintyPHP\Support\Flash;
|
||||
use MintyPHP\Support\Guard;
|
||||
use MintyPHP\I18n;
|
||||
use MintyPHP\Router;
|
||||
use MintyPHP\Repository\UserRoleRepository;
|
||||
use MintyPHP\Repository\UserTenantRepository;
|
||||
use MintyPHP\Repository\UserDepartmentRepository;
|
||||
use MintyPHP\Repository\RolePermissionRepository;
|
||||
use MintyPHP\Service\AuthService;
|
||||
use MintyPHP\Service\DepartmentService;
|
||||
use MintyPHP\Service\RoleService;
|
||||
use MintyPHP\Service\TenantService;
|
||||
use MintyPHP\Service\UserService;
|
||||
use MintyPHP\Service\PermissionService;
|
||||
use MintyPHP\Service\TenantScopeService;
|
||||
use MintyPHP\Repository\Access\UserRoleRepository;
|
||||
use MintyPHP\Repository\Tenant\UserTenantRepository;
|
||||
use MintyPHP\Repository\Org\UserDepartmentRepository;
|
||||
use MintyPHP\Repository\Access\RolePermissionRepository;
|
||||
use MintyPHP\Repository\Auth\PasswordResetRepository;
|
||||
use MintyPHP\Repository\Auth\RememberTokenRepository;
|
||||
use MintyPHP\Service\Auth\AuthService;
|
||||
use MintyPHP\Service\Org\DepartmentService;
|
||||
use MintyPHP\Service\Access\RoleService;
|
||||
use MintyPHP\Service\Tenant\TenantService;
|
||||
use MintyPHP\Service\User\UserService;
|
||||
use MintyPHP\Service\Access\PermissionService;
|
||||
use MintyPHP\Service\Tenant\TenantScopeService;
|
||||
|
||||
Guard::requireLogin();
|
||||
|
||||
@@ -98,7 +100,7 @@ if (!$primaryTenantId && count($selectedTenantIds) === 1) {
|
||||
$primaryTenantId = (int) $selectedTenantIds[0];
|
||||
$user['primary_tenant_id'] = $primaryTenantId;
|
||||
}
|
||||
$roles = RoleService::list();
|
||||
$roles = RoleService::listActive();
|
||||
$selectedRoleIds = UserRoleRepository::listRoleIdsByUserId($userId);
|
||||
$permissionRows = RolePermissionRepository::listPermissionsWithRolesByRoleIds($selectedRoleIds);
|
||||
$departments = DepartmentService::listForUserAssignments($selectedTenantIds, []);
|
||||
@@ -106,6 +108,14 @@ $selectedDepartmentIds = UserDepartmentRepository::listDepartmentIdsByUserId($us
|
||||
if ($selectedDepartmentIds) {
|
||||
$departments = DepartmentService::listForUserAssignments($selectedTenantIds, $selectedDepartmentIds);
|
||||
}
|
||||
$passwordResets = [];
|
||||
if ($canViewUsers || $canEditUser) {
|
||||
$passwordResets = PasswordResetRepository::listByUserId($userId, 25);
|
||||
}
|
||||
$rememberTokens = [];
|
||||
if ($canViewUsers || $canEditUser) {
|
||||
$rememberTokens = RememberTokenRepository::listByUserId($userId, 25);
|
||||
}
|
||||
// Keep initial $isOwnAccount/$canEditUser values for view permissions.
|
||||
|
||||
if (isset($_POST['email'])) {
|
||||
@@ -140,7 +150,9 @@ if (isset($_POST['email'])) {
|
||||
}
|
||||
}
|
||||
if ($currentUserId === $userId && isset($form['theme'])) {
|
||||
$_SESSION['user']['theme'] = $form['theme'] ?: 'light';
|
||||
$themes = appThemes();
|
||||
$themeValue = strtolower(trim((string) ($form['theme'] ?? '')));
|
||||
$_SESSION['user']['theme'] = isset($themes[$themeValue]) ? $themeValue : appDefaultTheme();
|
||||
}
|
||||
if ($currentUserId === $userId && isset($form['locale'])) {
|
||||
$_SESSION['user']['locale'] = $form['locale'];
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
|
||||
use MintyPHP\Router;
|
||||
use MintyPHP\Session;
|
||||
use MintyPHP\Service\UserAvatarService;
|
||||
use MintyPHP\Service\User\UserAvatarService;
|
||||
|
||||
$values = $form ?? $user ?? [];
|
||||
$avatarUuid = (string) ($values['uuid'] ?? '');
|
||||
@@ -17,6 +17,10 @@ $currentUserId = (int) ($_SESSION['user']['id'] ?? 0);
|
||||
$isOwnAccount = $currentUserId > 0 && $currentUserId === (int) ($values['id'] ?? 0);
|
||||
$titleText = $isOwnAccount ? t('My account') : t('Edit user');
|
||||
$canViewUsers = can('users.view');
|
||||
$canViewAddressBook = can('address_book.view');
|
||||
$canViewUserMeta = can('users.view_meta');
|
||||
$canViewUserAudit = can('users.view_audit');
|
||||
$hasDetailsActions = $canViewAddressBook || !empty($canEditUser) || can('users.delete');
|
||||
$hideNavigation = $isOwnAccount && !$canViewUsers;
|
||||
|
||||
?>
|
||||
@@ -24,10 +28,14 @@ $hideNavigation = $isOwnAccount && !$canViewUsers;
|
||||
<div class="app-details-container">
|
||||
<section>
|
||||
<?php if (!$hideNavigation): ?>
|
||||
<div class="app-breadcrumb">
|
||||
<a href="/admin">Startseite</a><i class="bi bi-chevron-right"></i><a
|
||||
href="/admin/users"><?php e(t('Users')); ?></a><i class="bi bi-chevron-right"></i><?php e($titleText); ?>
|
||||
</div>
|
||||
<?php
|
||||
$breadcrumbs = [
|
||||
['label' => t('Home'), 'path' => 'admin'],
|
||||
['label' => t('Users'), 'path' => 'admin/users'],
|
||||
['label' => $titleText],
|
||||
];
|
||||
require templatePath('partials/app-breadcrumb.phtml');
|
||||
?>
|
||||
<?php endif; ?>
|
||||
<div class="app-details-titlebar">
|
||||
<h1>
|
||||
@@ -37,10 +45,17 @@ $hideNavigation = $isOwnAccount && !$canViewUsers;
|
||||
<?php e($titleText); ?>
|
||||
</h1>
|
||||
<div class="app-details-titlebar-actions">
|
||||
<?php if (can('users.delete')): ?>
|
||||
<?php if ($hasDetailsActions): ?>
|
||||
<details class="dropdown">
|
||||
<summary role="button" class="outline secondary"><i class="bi bi-three-dots"></i></summary>
|
||||
<ul dir="rtl">
|
||||
<?php if ($canViewAddressBook): ?>
|
||||
<li>
|
||||
<a role="button" class="transparent" href="<?php e(lurl('address-book/view/' . ($values['uuid'] ?? ''))); ?>">
|
||||
<?php e(t('View in address book')); ?>
|
||||
</a>
|
||||
</li>
|
||||
<?php endif; ?>
|
||||
<li>
|
||||
<?php if (!empty($canEditUser)): ?>
|
||||
<form method="post" action="admin/users/send-access/<?php e($values['uuid'] ?? ''); ?>"
|
||||
@@ -119,6 +134,10 @@ $hideNavigation = $isOwnAccount && !$canViewUsers;
|
||||
$canEditAssignments = $canEditAssignments ?? false;
|
||||
$permissionRows = $permissionRows ?? [];
|
||||
$showPermissions = !empty($permissionRows) && can('permissions.view');
|
||||
$passwordResets = $passwordResets ?? [];
|
||||
$showPasswordResets = !empty($passwordResets);
|
||||
$rememberTokens = $rememberTokens ?? [];
|
||||
$showRememberTokens = !empty($rememberTokens);
|
||||
require __DIR__ . '/_form.phtml';
|
||||
?>
|
||||
</section>
|
||||
@@ -169,57 +188,59 @@ $hideNavigation = $isOwnAccount && !$canViewUsers;
|
||||
</details>
|
||||
<?php endif; ?>
|
||||
<hr>
|
||||
<details name="user-meta" open>
|
||||
<summary><?php e(t('Status & meta')); ?></summary>
|
||||
<?php if ($canViewUserMeta): ?>
|
||||
<details name="user-meta" open>
|
||||
<summary><?php e(t('Status & meta')); ?></summary>
|
||||
<hr>
|
||||
<div class="grid">
|
||||
<div>
|
||||
<small><?php e(t('ID')); ?></small>
|
||||
<p>
|
||||
<span class="badge" data-variant="neutral" data-copy="true"
|
||||
data-copy-value="<?php e($values['id'] ?? ''); ?>">
|
||||
<?php e($values['id'] ?? '-'); ?>
|
||||
</span>
|
||||
</p>
|
||||
</div>
|
||||
<div>
|
||||
<small><?php e(t('Status')); ?></small>
|
||||
<p>
|
||||
<?php if (!empty($values['active'])): ?>
|
||||
<span class="badge" data-variant="success"><?php e(t('Active')); ?></span>
|
||||
<?php else: ?>
|
||||
<span class="badge" data-variant="danger"><?php e(t('Inactive')); ?></span>
|
||||
<?php endif; ?>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<small><?php e(t('Email')); ?></small>
|
||||
<p>
|
||||
<?php if (!empty($values['email_verified_at'])): ?>
|
||||
<span class="badge" data-variant="success"><?php e(t('Verified')); ?> <?php e(dt($values['email_verified_at'])); ?></span>
|
||||
<?php else: ?>
|
||||
<span class="badge" data-variant="warning"><?php e(t('Not verified')); ?></span>
|
||||
<?php endif; ?>
|
||||
</p>
|
||||
</div>
|
||||
<div>
|
||||
<small>
|
||||
<?php e(t('UUID')); ?>
|
||||
</small>
|
||||
<p>
|
||||
<span class="badge" data-variant="neutral" data-copy="true"
|
||||
data-copy-value="<?php e($values['uuid'] ?? ''); ?>">
|
||||
<?php
|
||||
$uuidValue = (string) ($values['uuid'] ?? '');
|
||||
$uuidDisplay = $uuidValue !== '' ? substr($uuidValue, 0, 10) : '-';
|
||||
e($uuidDisplay);
|
||||
?>
|
||||
</span>
|
||||
</p>
|
||||
</div>
|
||||
</details>
|
||||
<hr>
|
||||
<div class="grid">
|
||||
<div>
|
||||
<small><?php e(t('ID')); ?></small>
|
||||
<p>
|
||||
<span class="badge" data-variant="neutral" data-copy="true"
|
||||
data-copy-value="<?php e($values['id'] ?? ''); ?>">
|
||||
<?php e($values['id'] ?? '-'); ?>
|
||||
</span>
|
||||
</p>
|
||||
</div>
|
||||
<div>
|
||||
<small><?php e(t('Status')); ?></small>
|
||||
<p>
|
||||
<?php if (!empty($values['active'])): ?>
|
||||
<span class="badge" data-variant="success"><?php e(t('Active')); ?></span>
|
||||
<?php else: ?>
|
||||
<span class="badge" data-variant="danger"><?php e(t('Inactive')); ?></span>
|
||||
<?php endif; ?>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<small><?php e(t('Email')); ?></small>
|
||||
<p>
|
||||
<?php if (!empty($values['email_verified_at'])): ?>
|
||||
<span class="badge" data-variant="success"><?php e(t('Verified')); ?> <?php e(dt($values['email_verified_at'])); ?></span>
|
||||
<?php else: ?>
|
||||
<span class="badge" data-variant="warning"><?php e(t('Not verified')); ?></span>
|
||||
<?php endif; ?>
|
||||
</p>
|
||||
</div>
|
||||
<div>
|
||||
<small>
|
||||
<?php e(t('UUID')); ?>
|
||||
</small>
|
||||
<p>
|
||||
<span class="badge" data-variant="neutral" data-copy="true"
|
||||
data-copy-value="<?php e($values['uuid'] ?? ''); ?>">
|
||||
<?php
|
||||
$uuidValue = (string) ($values['uuid'] ?? '');
|
||||
$uuidDisplay = $uuidValue !== '' ? substr($uuidValue, 0, 10) : '-';
|
||||
e($uuidDisplay);
|
||||
?>
|
||||
</span>
|
||||
</p>
|
||||
</div>
|
||||
</details>
|
||||
<hr>
|
||||
<?php endif; ?>
|
||||
<?php
|
||||
$createdByLabel = $values['created_by_label'] ?? '';
|
||||
$createdById = $values['created_by'] ?? null;
|
||||
@@ -231,82 +252,84 @@ $hideNavigation = $isOwnAccount && !$canViewUsers;
|
||||
$activeChangedById = $values['active_changed_by'] ?? null;
|
||||
$activeChangedByUuid = $values['active_changed_by_uuid'] ?? null;
|
||||
?>
|
||||
<details name="user-audit">
|
||||
<summary><?php e(t('Audit')); ?></summary>
|
||||
<hr>
|
||||
<div class="grid">
|
||||
<div>
|
||||
<small><?php e(t('Created')); ?></small>
|
||||
<p><?php e(dt($values['created'] ?? '') ?: '-'); ?></p>
|
||||
</div>
|
||||
<div>
|
||||
<small>
|
||||
<?php e(t('Created by')); ?>
|
||||
</small>
|
||||
<p>
|
||||
<?php if ($createdByLabel !== ''): ?>
|
||||
<?php if ($createdByUuid): ?>
|
||||
<a href="admin/users/edit/<?php e($createdByUuid); ?>"><?php e($createdByLabel); ?></a>
|
||||
<?php if ($canViewUserAudit): ?>
|
||||
<details name="user-audit">
|
||||
<summary><?php e(t('Audit')); ?></summary>
|
||||
<hr>
|
||||
<div class="grid">
|
||||
<div>
|
||||
<small><?php e(t('Created')); ?></small>
|
||||
<p><?php e(dt($values['created'] ?? '') ?: '-'); ?></p>
|
||||
</div>
|
||||
<div>
|
||||
<small>
|
||||
<?php e(t('Created by')); ?>
|
||||
</small>
|
||||
<p>
|
||||
<?php if ($createdByLabel !== ''): ?>
|
||||
<?php if ($createdByUuid): ?>
|
||||
<a href="admin/users/edit/<?php e($createdByUuid); ?>"><?php e($createdByLabel); ?></a>
|
||||
<?php else: ?>
|
||||
<?php e($createdByLabel); ?>
|
||||
<?php endif; ?>
|
||||
<?php elseif ($createdById): ?>
|
||||
<?php e('#' . $createdById); ?>
|
||||
<?php else: ?>
|
||||
<?php e($createdByLabel); ?>
|
||||
-
|
||||
<?php endif; ?>
|
||||
<?php elseif ($createdById): ?>
|
||||
<?php e('#' . $createdById); ?>
|
||||
<?php else: ?>
|
||||
-
|
||||
<?php endif; ?>
|
||||
</p>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="grid">
|
||||
<div>
|
||||
<small><?php e(t('Modified')); ?></small>
|
||||
<p><?php e(dt($values['modified'] ?? '') ?: '-'); ?></p>
|
||||
</div>
|
||||
<div>
|
||||
<small>
|
||||
<?php e(t('Modified by')); ?>
|
||||
</small>
|
||||
<p>
|
||||
<?php if ($modifiedByLabel !== ''): ?>
|
||||
<?php if ($modifiedByUuid): ?>
|
||||
<a href="admin/users/edit/<?php e($modifiedByUuid); ?>"><?php e($modifiedByLabel); ?></a>
|
||||
<div class="grid">
|
||||
<div>
|
||||
<small><?php e(t('Modified')); ?></small>
|
||||
<p><?php e(dt($values['modified'] ?? '') ?: '-'); ?></p>
|
||||
</div>
|
||||
<div>
|
||||
<small>
|
||||
<?php e(t('Modified by')); ?>
|
||||
</small>
|
||||
<p>
|
||||
<?php if ($modifiedByLabel !== ''): ?>
|
||||
<?php if ($modifiedByUuid): ?>
|
||||
<a href="admin/users/edit/<?php e($modifiedByUuid); ?>"><?php e($modifiedByLabel); ?></a>
|
||||
<?php else: ?>
|
||||
<?php e($modifiedByLabel); ?>
|
||||
<?php endif; ?>
|
||||
<?php elseif ($modifiedById): ?>
|
||||
<?php e('#' . $modifiedById); ?>
|
||||
<?php else: ?>
|
||||
<?php e($modifiedByLabel); ?>
|
||||
-
|
||||
<?php endif; ?>
|
||||
<?php elseif ($modifiedById): ?>
|
||||
<?php e('#' . $modifiedById); ?>
|
||||
<?php else: ?>
|
||||
-
|
||||
<?php endif; ?>
|
||||
</p>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="grid">
|
||||
<div>
|
||||
<small><?php e(t('Status changed')); ?></small>
|
||||
<p><?php e(dt($values['active_changed_at'] ?? '') ?: '-'); ?></p>
|
||||
</div>
|
||||
<div>
|
||||
<small>
|
||||
<?php e(t('Status changed by')); ?>
|
||||
</small>
|
||||
<p>
|
||||
<?php if ($activeChangedByLabel !== ''): ?>
|
||||
<?php if ($activeChangedByUuid): ?>
|
||||
<a href="admin/users/edit/<?php e($activeChangedByUuid); ?>"><?php e($activeChangedByLabel); ?></a>
|
||||
<div class="grid">
|
||||
<div>
|
||||
<small><?php e(t('Status changed')); ?></small>
|
||||
<p><?php e(dt($values['active_changed_at'] ?? '') ?: '-'); ?></p>
|
||||
</div>
|
||||
<div>
|
||||
<small>
|
||||
<?php e(t('Status changed by')); ?>
|
||||
</small>
|
||||
<p>
|
||||
<?php if ($activeChangedByLabel !== ''): ?>
|
||||
<?php if ($activeChangedByUuid): ?>
|
||||
<a href="admin/users/edit/<?php e($activeChangedByUuid); ?>"><?php e($activeChangedByLabel); ?></a>
|
||||
<?php else: ?>
|
||||
<?php e($activeChangedByLabel); ?>
|
||||
<?php endif; ?>
|
||||
<?php elseif ($activeChangedById): ?>
|
||||
<?php e('#' . $activeChangedById); ?>
|
||||
<?php else: ?>
|
||||
<?php e($activeChangedByLabel); ?>
|
||||
-
|
||||
<?php endif; ?>
|
||||
<?php elseif ($activeChangedById): ?>
|
||||
<?php e('#' . $activeChangedById); ?>
|
||||
<?php else: ?>
|
||||
-
|
||||
<?php endif; ?>
|
||||
</p>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</details>
|
||||
</details>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
</aside>
|
||||
</div>
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<?php
|
||||
|
||||
use MintyPHP\Service\UserService;
|
||||
use MintyPHP\Service\User\UserService;
|
||||
use MintyPHP\Support\Guard;
|
||||
|
||||
Guard::requireLogin();
|
||||
|
||||
@@ -3,10 +3,10 @@
|
||||
use MintyPHP\Support\Flash;
|
||||
use MintyPHP\Support\Guard;
|
||||
use MintyPHP\Router;
|
||||
use MintyPHP\Service\PermissionService;
|
||||
use MintyPHP\Service\RememberMeService;
|
||||
use MintyPHP\Service\TenantScopeService;
|
||||
use MintyPHP\Service\UserService;
|
||||
use MintyPHP\Service\Access\PermissionService;
|
||||
use MintyPHP\Service\Auth\RememberMeService;
|
||||
use MintyPHP\Service\Tenant\TenantScopeService;
|
||||
use MintyPHP\Service\User\UserService;
|
||||
|
||||
Guard::requireLogin();
|
||||
|
||||
|
||||
@@ -3,11 +3,11 @@
|
||||
use MintyPHP\Buffer;
|
||||
use MintyPHP\Support\Guard;
|
||||
use MintyPHP\Session;
|
||||
use MintyPHP\Service\DepartmentService;
|
||||
use MintyPHP\Service\RoleService;
|
||||
use MintyPHP\Service\TenantService;
|
||||
use MintyPHP\Service\PermissionService;
|
||||
use MintyPHP\Service\TenantScopeService;
|
||||
use MintyPHP\Service\Org\DepartmentService;
|
||||
use MintyPHP\Service\Access\RoleService;
|
||||
use MintyPHP\Service\Tenant\TenantService;
|
||||
use MintyPHP\Service\Access\PermissionService;
|
||||
use MintyPHP\Service\Tenant\TenantScopeService;
|
||||
|
||||
Guard::requireLogin();
|
||||
Guard::requirePermissionOrForbidden(PermissionService::USERS_VIEW);
|
||||
@@ -38,7 +38,7 @@ if ($allowedTenantIds) {
|
||||
}
|
||||
sortByDescription($tenants);
|
||||
|
||||
$roles = RoleService::list();
|
||||
$roles = RoleService::listActive();
|
||||
sortByDescription($roles);
|
||||
|
||||
$departments = $allowedTenantIds ? DepartmentService::listByTenantIds($allowedTenantIds) : [];
|
||||
|
||||
@@ -10,9 +10,13 @@ $canUpdateSelf = can('users.self_update');
|
||||
$currentUserUuid = (string) ($_SESSION['user']['uuid'] ?? '');
|
||||
$showTenantTabs = isset($tenants) && is_array($tenants) && count($tenants) > 1;
|
||||
?>
|
||||
<div class="app-breadcrumb">
|
||||
<a href="/admin">Startseite</a><i class="bi bi-chevron-right"></i><?php e(t('Users')); ?>
|
||||
</div>
|
||||
<?php
|
||||
$breadcrumbs = [
|
||||
['label' => t('Home'), 'path' => 'admin'],
|
||||
['label' => t('Users')],
|
||||
];
|
||||
require templatePath('partials/app-breadcrumb.phtml');
|
||||
?>
|
||||
<div class="app-list-titlebar">
|
||||
<h1><?php e(t('Users')); ?></h1>
|
||||
<div class="app-list-titlebar-actions">
|
||||
@@ -34,12 +38,12 @@ $showTenantTabs = isset($tenants) && is_array($tenants) && count($tenants) > 1;
|
||||
<?php endif; ?>
|
||||
|
||||
|
||||
<details class="dropdown" data-tooltip="<?php e(t("Actions"));?>" data-tooltip-pos="top">
|
||||
<details class="dropdown" data-tooltip="<?php e(t("Actions")); ?>" data-tooltip-pos="top">
|
||||
<summary role="button" class="outline secondary"><i class="bi bi-three-dots"></i></summary>
|
||||
<ul dir="rtl">
|
||||
<li dir="ltr">
|
||||
<button class="transparent" type="button" data-toolbar-toggle data-toolbar-target="#users-toolbar, #users-tabs"
|
||||
data-toolbar-text-show="<?php e(t('Show filters')); ?>"
|
||||
<button class="transparent" type="button" data-toolbar-toggle
|
||||
data-toolbar-target="#users-toolbar, #users-tabs" data-toolbar-text-show="<?php e(t('Show filters')); ?>"
|
||||
data-toolbar-text-hide="<?php e(t('Hide filters')); ?>">
|
||||
<span data-toolbar-label>
|
||||
<?php e(t('Hide filters')); ?>
|
||||
@@ -74,65 +78,102 @@ $showTenantTabs = isset($tenants) && is_array($tenants) && count($tenants) > 1;
|
||||
<?php foreach ($tenants ?? [] as $tenant): ?>
|
||||
<?php if (!empty($tenant['uuid'])): ?>
|
||||
<?php $isActive = $activeTenant === $tenant['uuid']; ?>
|
||||
<a href="admin/users?tenant=<?php e($tenant['uuid']); ?>" class="<?php e($isActive ? 'tab-link is-active' : 'tab-link'); ?>">
|
||||
<a href="admin/users?tenant=<?php e($tenant['uuid']); ?>"
|
||||
class="<?php e($isActive ? 'tab-link is-active' : 'tab-link'); ?>">
|
||||
<?php e($tenant['description'] ?? ''); ?>
|
||||
</a>
|
||||
<?php endif; ?>
|
||||
<?php endforeach; ?>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
<div class="app-list-toolbar" id="users-toolbar">
|
||||
<div class="app-list-toolbar" id="users-toolbar" data-filter-overflow>
|
||||
<input type="hidden" id="user-tenant-filter" value="">
|
||||
<label class="app-field">
|
||||
<span><?php e(t('Search')); ?></span>
|
||||
<input type="search" id="user-search" placeholder="<?php e(t('Search...')); ?>">
|
||||
</label>
|
||||
<label class="app-field">
|
||||
<span><?php e(t('Status')); ?></span>
|
||||
|
||||
<div>
|
||||
<?php multiSelectFilter('user-department-filter', 'Departments', 'Select departments', $departments ?? [], $activeDepartments); ?>
|
||||
</div>
|
||||
<div>
|
||||
<?php multiSelectFilter('user-role-filter', 'Roles', 'Select roles', $roles ?? [], $activeRoles); ?>
|
||||
</div>
|
||||
<label class="app-field" data-filter-optional>
|
||||
<span>
|
||||
<?php e(t('Status')); ?>
|
||||
</span>
|
||||
<select id="user-status-filter">
|
||||
<option value="all"><?php e(t('All')); ?></option>
|
||||
<option value="active"><?php e(t('Active')); ?></option>
|
||||
<option value="inactive"><?php e(t('Inactive')); ?></option>
|
||||
<option value="all">
|
||||
<?php e(t('All')); ?>
|
||||
</option>
|
||||
<option value="active">
|
||||
<?php e(t('Active')); ?>
|
||||
</option>
|
||||
<option value="inactive">
|
||||
<?php e(t('Inactive')); ?>
|
||||
</option>
|
||||
</select>
|
||||
</label>
|
||||
<label class="app-field">
|
||||
<span><?php e(t('Email verified')); ?></span>
|
||||
<label class="app-field" data-filter-optional>
|
||||
<span>
|
||||
<?php e(t('Email verified')); ?>
|
||||
</span>
|
||||
<select id="user-email-verified-filter">
|
||||
<option value="all"><?php e(t('All')); ?></option>
|
||||
<option value="verified"><?php e(t('Verified')); ?></option>
|
||||
<option value="unverified"><?php e(t('Unverified')); ?></option>
|
||||
<option value="all">
|
||||
<?php e(t('All')); ?>
|
||||
</option>
|
||||
<option value="verified">
|
||||
<?php e(t('Verified')); ?>
|
||||
</option>
|
||||
<option value="unverified">
|
||||
<?php e(t('Unverified')); ?>
|
||||
</option>
|
||||
</select>
|
||||
</label>
|
||||
<?php multiSelectFilter('user-department-filter', 'Departments', 'Select departments', $departments ?? [], $activeDepartments); ?>
|
||||
<?php multiSelectFilter('user-role-filter', 'Roles', 'Select roles', $roles ?? [], $activeRoles); ?>
|
||||
<label class="app-field">
|
||||
<label class="app-field" data-filter-optional>
|
||||
<span>
|
||||
<?php e(t('Login status')); ?>
|
||||
</span>
|
||||
<select id="user-login-filter">
|
||||
<option value="all">
|
||||
<?php e(t('All')); ?>
|
||||
</option>
|
||||
<option value="ever">
|
||||
<?php e(t('Logged in')); ?>
|
||||
</option>
|
||||
<option value="never">
|
||||
<?php e(t('Never logged in')); ?>
|
||||
</option>
|
||||
</select>
|
||||
</label>
|
||||
<label class="app-field" data-filter-optional>
|
||||
<span><?php e(t('Created from')); ?></span>
|
||||
<input type="date" id="user-created-from">
|
||||
</label>
|
||||
<label class="app-field">
|
||||
<label class="app-field" data-filter-optional>
|
||||
<span><?php e(t('Created to')); ?></span>
|
||||
<input type="date" id="user-created-to">
|
||||
</label>
|
||||
<button type="button" class="outline secondary icon-button" data-filter-toggle
|
||||
data-tooltip="<?php e(t('More filters')); ?>" data-tooltip-pos="top" aria-label="<?php e(t('More filters')); ?>">
|
||||
<i class="bi bi-funnel-fill"></i>
|
||||
</button>
|
||||
</div>
|
||||
<div class="app-list-table">
|
||||
<div id="users-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 src="<?php e(asset('vendor/gridjs/plugins/selection/selection.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 { createServerGrid } from "<?php e(assetVersion('js/core/app-grid-factory.js')); ?>";
|
||||
import { initUsersListPage } from "<?php e(asset('js/pages/app-users-list.js')); ?>";
|
||||
import { bindBulkVisibility } from "<?php e(asset('js/components/app-bulk-selection.js')); ?>";
|
||||
import { buildUrl, badgeHtml } from "<?php e(asset('js/pages/app-list-utils.js')); ?>";
|
||||
import { buildUrl, badgeHtml, getAppBase, escapeHtml, buildBadgeList } from "<?php e(asset('js/pages/app-list-utils.js')); ?>";
|
||||
import { showAsyncFlash, withLoading } from "<?php e(asset('js/components/app-async-flash.js')); ?>";
|
||||
|
||||
initToolbarToggles();
|
||||
|
||||
const appBase = "<?php e(localeBase()); ?>";
|
||||
const appBase = getAppBase();
|
||||
const currentUserUuid = "<?php e($currentUserUuid); ?>";
|
||||
const canUpdateUsers = <?php e($canUpdateUsers ? 'true' : 'false'); ?>;
|
||||
const canUpdateSelf = <?php e($canUpdateSelf ? 'true' : 'false'); ?>;
|
||||
@@ -140,6 +181,7 @@ $showTenantTabs = isset($tenants) && is_array($tenants) && count($tenants) > 1;
|
||||
const labels = {
|
||||
active: "<?php e(t('Active')); ?>",
|
||||
inactive: "<?php e(t('Inactive')); ?>",
|
||||
never: "<?php e(t('Never')); ?>",
|
||||
bulkActivateConfirm: "<?php e(t('Activate users?')); ?>",
|
||||
bulkDeactivateConfirm: "<?php e(t('Deactivate users?')); ?>",
|
||||
bulkDeleteConfirm: "<?php e(t('Delete users?')); ?>",
|
||||
@@ -192,29 +234,6 @@ $showTenantTabs = isset($tenants) && is_array($tenants) && count($tenants) > 1;
|
||||
return canUpdateUsers;
|
||||
};
|
||||
|
||||
const escapeHtml = (value) => String(value ?? '').replace(/[&<>"']/g, (char) => ({
|
||||
'&': '&',
|
||||
'<': '<',
|
||||
'>': '>',
|
||||
'"': '"',
|
||||
"'": '''
|
||||
}[char]));
|
||||
const buildBadgeList = (items) => {
|
||||
let list = items;
|
||||
let primary = '';
|
||||
if (items && typeof items === 'object' && !Array.isArray(items)) {
|
||||
list = Array.isArray(items.items) ? items.items : [];
|
||||
primary = String(items.primary ?? '');
|
||||
}
|
||||
if (!Array.isArray(list) || list.length === 0) return '';
|
||||
const badges = list.map((label) => {
|
||||
const isPrimary = primary !== '' && label === primary;
|
||||
const variant = isPrimary ? 'info' : 'neutral';
|
||||
const tooltip = isPrimary ? ` data-tooltip="${escapeHtml(labels.primaryTenant)}" data-tooltip-pos="top"` : '';
|
||||
return `<span class="badge" data-variant="${variant}"${tooltip}>${escapeHtml(label)}</span>`;
|
||||
}).join(' ');
|
||||
return `<div class="badge-list">${badges}</div>`;
|
||||
};
|
||||
const initialsForRow = (row) => {
|
||||
const first = row?.cells?.[3]?.data ?? '';
|
||||
const last = row?.cells?.[4]?.data ?? '';
|
||||
@@ -250,7 +269,11 @@ $showTenantTabs = isset($tenants) && is_array($tenants) && count($tenants) > 1;
|
||||
? gridjs.html(`<span class="badge" data-variant="success">${labels.active}</span>`)
|
||||
: gridjs.html(`<span class="badge" data-variant="danger">${labels.inactive}</span>`)
|
||||
},
|
||||
{ name: "<?php e(t('Tenants')); ?>", sort: false, formatter: (cell) => gridjs.html(buildBadgeList(cell)) },
|
||||
{
|
||||
name: "<?php e(t('Tenants')); ?>",
|
||||
sort: false,
|
||||
formatter: (cell) => gridjs.html(buildBadgeList(cell, { primaryTooltip: labels.primaryTenant }))
|
||||
},
|
||||
{ name: "<?php e(t('Departments')); ?>", sort: false, formatter: (cell) => gridjs.html(buildBadgeList(cell)) },
|
||||
{ name: "<?php e(t('Roles')); ?>", sort: false, formatter: (cell) => gridjs.html(buildBadgeList(cell)) },
|
||||
{ name: "<?php e(t('Phone')); ?>", sort: false },
|
||||
@@ -258,6 +281,11 @@ $showTenantTabs = isset($tenants) && is_array($tenants) && count($tenants) > 1;
|
||||
{ name: "<?php e(t('Short dial')); ?>", sort: false },
|
||||
{ name: "<?php e(t('Created')); ?>", sort: true, formatter: (cell) => badgeHtml(gridjs, cell) },
|
||||
{ name: "<?php e(t('Modified')); ?>", sort: true, formatter: (cell) => badgeHtml(gridjs, cell) },
|
||||
{
|
||||
name: "<?php e(t('Last login')); ?>",
|
||||
sort: true,
|
||||
formatter: (cell) => badgeHtml(gridjs, cell || labels.never)
|
||||
},
|
||||
{ name: 'ID', hidden: true }
|
||||
];
|
||||
|
||||
@@ -267,7 +295,7 @@ $showTenantTabs = isset($tenants) && is_array($tenants) && count($tenants) > 1;
|
||||
dataUrl: 'admin/users/data',
|
||||
appBase,
|
||||
columns,
|
||||
sortColumns: [null, null, 'first_name', 'last_name', 'email', 'active', null, null, null, null, null, null, 'created', 'modified', null],
|
||||
sortColumns: [null, null, 'first_name', 'last_name', 'email', 'active', null, null, null, null, null, null, 'created', 'modified', 'last_login_at', null],
|
||||
paginationLimit: 10,
|
||||
language: <?php MintyPHP\Buffer::get('grid_lang'); ?>,
|
||||
mapData: (data) => data.data.map((row) => [
|
||||
@@ -285,6 +313,7 @@ $showTenantTabs = isset($tenants) && is_array($tenants) && count($tenants) > 1;
|
||||
row.short_dial,
|
||||
row.created,
|
||||
row.modified,
|
||||
row.last_login,
|
||||
row.id
|
||||
]),
|
||||
selection: {
|
||||
@@ -320,6 +349,12 @@ $showTenantTabs = isset($tenants) && is_array($tenants) && count($tenants) > 1;
|
||||
default: 'all',
|
||||
normalize: (value) => (value && value !== 'all' ? value : '')
|
||||
},
|
||||
{
|
||||
input: '#user-login-filter',
|
||||
param: 'login_status',
|
||||
default: 'all',
|
||||
normalize: (value) => (value && value !== 'all' ? value : '')
|
||||
},
|
||||
{
|
||||
input: '#user-department-filter',
|
||||
param: 'departments',
|
||||
@@ -386,4 +421,4 @@ $showTenantTabs = isset($tenants) && is_array($tenants) && count($tenants) > 1;
|
||||
containerSelector: '#users-grid',
|
||||
buttonSelector: '[data-users-bulk]'
|
||||
});
|
||||
</script>
|
||||
</script>
|
||||
@@ -3,10 +3,10 @@
|
||||
use MintyPHP\Support\Flash;
|
||||
use MintyPHP\Support\Guard;
|
||||
use MintyPHP\Router;
|
||||
use MintyPHP\Service\PermissionService;
|
||||
use MintyPHP\Service\TenantScopeService;
|
||||
use MintyPHP\Service\UserService;
|
||||
use MintyPHP\Service\MailService;
|
||||
use MintyPHP\Service\Access\PermissionService;
|
||||
use MintyPHP\Service\Tenant\TenantScopeService;
|
||||
use MintyPHP\Service\User\UserService;
|
||||
use MintyPHP\Service\Mail\MailService;
|
||||
use MintyPHP\I18n;
|
||||
use MintyPHP\Http\Request;
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
use MintyPHP\Http\Request;
|
||||
use MintyPHP\Router;
|
||||
use MintyPHP\Session;
|
||||
use MintyPHP\Service\UserService;
|
||||
use MintyPHP\Service\User\UserService;
|
||||
use MintyPHP\Support\Guard;
|
||||
|
||||
Guard::requireLogin();
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
use MintyPHP\Http\Request;
|
||||
use MintyPHP\Router;
|
||||
use MintyPHP\Session;
|
||||
use MintyPHP\Service\UserService;
|
||||
use MintyPHP\Service\User\UserService;
|
||||
use MintyPHP\Support\Guard;
|
||||
|
||||
Guard::requireLogin();
|
||||
@@ -34,8 +34,9 @@ if ($userId <= 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
$theme = trim((string) ($_POST['theme'] ?? ''));
|
||||
if (!in_array($theme, ['light', 'dark'], true)) {
|
||||
$theme = strtolower(trim((string) ($_POST['theme'] ?? '')));
|
||||
$themes = appThemes();
|
||||
if ($theme === '' || !isset($themes[$theme])) {
|
||||
http_response_code(400);
|
||||
if (Request::wantsJson()) {
|
||||
Router::json(['ok' => false, 'error' => 'invalid_theme']);
|
||||
|
||||
Reference in New Issue
Block a user