dashboard for org
This commit is contained in:
@@ -21,9 +21,145 @@ class TwigGlobalsExtension extends AbstractExtension
|
||||
new TwigFunction('get_current_route', [$this, 'getCurrentRoute'], ['is_safe' => ['html']]),
|
||||
new TwigFunction('render_actions', [$this, 'renderActions'], ['is_safe' => ['html']]),
|
||||
new TwigFunction('render_cell', [$this, 'renderCell'], ['is_safe' => ['html']]),
|
||||
|
||||
// Access functions
|
||||
new TwigFunction('can', [$this, 'can'], ['is_safe' => ['html']]),
|
||||
new TwigFunction('is_role', [$this, 'isRole'], ['is_safe' => ['html']]),
|
||||
new TwigFunction('is_owner', [$this, 'isOwner'], ['is_safe' => ['html']]),
|
||||
new TwigFunction('is_admin', [$this, 'isAdmin'], ['is_safe' => ['html']]),
|
||||
new TwigFunction('is_manager', [$this, 'isManager'], ['is_safe' => ['html']]),
|
||||
new TwigFunction('current_role', [$this, 'currentRole'], ['is_safe' => ['html']]),
|
||||
new TwigFunction('role_label', [$this, 'roleLabel'], ['is_safe' => ['html']]),
|
||||
new TwigFunction('can_view', [$this, 'canView'], ['is_safe' => ['html']]),
|
||||
new TwigFunction('can_create', [$this, 'canCreate'], ['is_safe' => ['html']]),
|
||||
new TwigFunction('can_edit', [$this, 'canEdit'], ['is_safe' => ['html']]),
|
||||
new TwigFunction('can_delete', [$this, 'canDelete'], ['is_safe' => ['html']]),
|
||||
new TwigFunction('can_manage_users', [$this, 'canManageUsers'], ['is_safe' => ['html']]),
|
||||
|
||||
// Role & Status badge functions
|
||||
new TwigFunction('role_badge', [$this, 'roleBadge'], ['is_safe' => ['html']]),
|
||||
new TwigFunction('status_badge', [$this, 'statusBadge'], ['is_safe' => ['html']]),
|
||||
new TwigFunction('get_all_roles', [$this, 'getAllRoles'], ['is_safe' => ['html']]),
|
||||
];
|
||||
}
|
||||
|
||||
// ========================================
|
||||
// Access Functions для Twig
|
||||
// ========================================
|
||||
|
||||
public function can(string $action, string $resource): bool
|
||||
{
|
||||
return service('access')->can($action, $resource);
|
||||
}
|
||||
|
||||
public function isRole($roles): bool
|
||||
{
|
||||
return service('access')->isRole($roles);
|
||||
}
|
||||
|
||||
public function isOwner(): bool
|
||||
{
|
||||
return service('access')->isRole(\App\Services\AccessService::ROLE_OWNER);
|
||||
}
|
||||
|
||||
public function isAdmin(): bool
|
||||
{
|
||||
$role = service('access')->getCurrentRole();
|
||||
return $role === \App\Services\AccessService::ROLE_ADMIN
|
||||
|| $role === \App\Services\AccessService::ROLE_OWNER;
|
||||
}
|
||||
|
||||
public function isManager(): bool
|
||||
{
|
||||
return service('access')->isManagerOrHigher();
|
||||
}
|
||||
|
||||
public function currentRole(): ?string
|
||||
{
|
||||
return service('access')->getCurrentRole();
|
||||
}
|
||||
|
||||
public function roleLabel(string $role): string
|
||||
{
|
||||
return service('access')->getRoleLabel($role);
|
||||
}
|
||||
|
||||
public function canView(string $resource): bool
|
||||
{
|
||||
return service('access')->can(\App\Services\AccessService::PERMISSION_VIEW, $resource);
|
||||
}
|
||||
|
||||
public function canCreate(string $resource): bool
|
||||
{
|
||||
return service('access')->can(\App\Services\AccessService::PERMISSION_CREATE, $resource);
|
||||
}
|
||||
|
||||
public function canEdit(string $resource): bool
|
||||
{
|
||||
return service('access')->can(\App\Services\AccessService::PERMISSION_EDIT, $resource);
|
||||
}
|
||||
|
||||
public function canDelete(string $resource): bool
|
||||
{
|
||||
return service('access')->can(\App\Services\AccessService::PERMISSION_DELETE, $resource);
|
||||
}
|
||||
|
||||
public function canManageUsers(): bool
|
||||
{
|
||||
return service('access')->canManageUsers();
|
||||
}
|
||||
|
||||
// ========================================
|
||||
// Role & Status Badge Functions
|
||||
// ========================================
|
||||
|
||||
public function roleBadge(string $role): string
|
||||
{
|
||||
$colors = [
|
||||
'owner' => 'bg-primary',
|
||||
'admin' => 'bg-info',
|
||||
'manager' => 'bg-success',
|
||||
'guest' => 'bg-secondary',
|
||||
];
|
||||
|
||||
$labels = [
|
||||
'owner' => 'Владелец',
|
||||
'admin' => 'Администратор',
|
||||
'manager' => 'Менеджер',
|
||||
'guest' => 'Гость',
|
||||
];
|
||||
|
||||
$color = $colors[$role] ?? 'bg-secondary';
|
||||
$label = $labels[$role] ?? $role;
|
||||
|
||||
return '<span class="badge ' . esc($color) . '">' . esc($label) . '</span>';
|
||||
}
|
||||
|
||||
public function statusBadge(string $status): string
|
||||
{
|
||||
$colors = [
|
||||
'active' => 'bg-success',
|
||||
'pending' => 'bg-warning text-dark',
|
||||
'blocked' => 'bg-danger',
|
||||
];
|
||||
|
||||
$labels = [
|
||||
'active' => 'Активен',
|
||||
'pending' => 'Ожидает',
|
||||
'blocked' => 'Заблокирован',
|
||||
];
|
||||
|
||||
$color = $colors[$status] ?? 'bg-secondary';
|
||||
$label = $labels[$status] ?? $status;
|
||||
|
||||
return '<span class="badge ' . esc($color) . '">' . esc($label) . '</span>';
|
||||
}
|
||||
|
||||
public function getAllRoles(): array
|
||||
{
|
||||
return \App\Services\AccessService::getAllRoles();
|
||||
}
|
||||
|
||||
public function getSession()
|
||||
{
|
||||
return session();
|
||||
@@ -137,7 +273,6 @@ class TwigGlobalsExtension extends AbstractExtension
|
||||
// DEBUG: логируем для отладки
|
||||
log_message('debug', 'renderActions: item type = ' . gettype($item));
|
||||
log_message('debug', 'renderActions: item keys = ' . (is_array($itemArray) ? implode(', ', array_keys($itemArray)) : 'N/A'));
|
||||
log_message('debug', 'renderActions: item = ' . print_r($itemArray, true));
|
||||
|
||||
$html = '<div class="btn-group btn-group-sm">';
|
||||
|
||||
@@ -148,11 +283,26 @@ class TwigGlobalsExtension extends AbstractExtension
|
||||
$class = $action['class'] ?? 'btn-outline-secondary';
|
||||
$title = $action['title'] ?? $label;
|
||||
$target = $action['target'] ?? '';
|
||||
$type = $action['type'] ?? '';
|
||||
|
||||
// Проверяем условия для показа кнопки
|
||||
// Владелец не может быть изменён, заблокирован или удалён
|
||||
if ($itemArray['role'] ?? '' === 'owner') {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Блокировка - только для активных пользователей
|
||||
if ($type === 'block' && ($itemArray['status'] ?? '') !== 'active') {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Разблокировка - только для заблокированных
|
||||
if ($type === 'unblock' && ($itemArray['status'] ?? '') !== 'blocked') {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Подставляем значения из item в URL
|
||||
$url = $this->interpolate($urlPattern, $itemArray);
|
||||
|
||||
log_message('debug', 'renderActions: urlPattern = ' . $urlPattern . ', url = ' . $url);
|
||||
|
||||
// Формируем HTML кнопки/ссылки
|
||||
$iconHtml = $icon ? '<i class="' . esc($icon) . '"></i> ' : '';
|
||||
@@ -251,6 +401,22 @@ class TwigGlobalsExtension extends AbstractExtension
|
||||
}
|
||||
return '<span class="badge bg-secondary">Нет</span>';
|
||||
|
||||
case 'role_badge':
|
||||
return $this->roleBadge((string) $value);
|
||||
|
||||
case 'status_badge':
|
||||
return $this->statusBadge((string) $value);
|
||||
|
||||
case 'user_display':
|
||||
// Отображение пользователя с аватаром и именем/email
|
||||
$name = $itemArray['user_name'] ?? '';
|
||||
$email = $itemArray['user_email'] ?? $value;
|
||||
$avatar = $itemArray['user_avatar'] ?? '';
|
||||
$avatarHtml = $avatar
|
||||
? '<img src="' . esc($avatar) . '" alt="" style="width: 32px; height: 32px; object-fit: cover; border-radius: 50%;">'
|
||||
: '<div class="bg-light rounded-circle d-flex align-items-center justify-content-center" style="width: 32px; height: 32px;"><i class="fa-solid fa-user text-muted small"></i></div>';
|
||||
return '<div class="d-flex align-items-center gap-2">' . $avatarHtml . '<div><div class="fw-medium">' . esc($name ?: $email) . '</div>' . ($name ? '<div class="small text-muted">' . esc($email) . '</div>' : '') . '</div></div>';
|
||||
|
||||
case 'uppercase':
|
||||
return $value ? esc(strtoupper($value)) : ($config['default'] ?? '');
|
||||
|
||||
|
||||
Reference in New Issue
Block a user