big restructure
This commit is contained in:
@@ -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>
|
||||
Reference in New Issue
Block a user