empty states

This commit is contained in:
2026-03-13 09:49:11 +01:00
parent cb7256aebc
commit 082fa4c9a5
12 changed files with 174 additions and 46 deletions

View File

@@ -71,6 +71,15 @@ $disabledAttr = $isReadOnly ? 'disabled' : '';
</option>
<?php endforeach; ?>
</select>
<?php else: ?>
<?php
$emptyState = [
'message' => t('No tenants available'),
'hint' => t('Please select at least one tenant'),
'size' => 'compact',
];
require templatePath('partials/app-empty-state.phtml');
?>
<?php endif; ?>
</div>

View File

@@ -9,6 +9,7 @@
<div class="app-details-container">
<section>
<?php
$hasTenantOptions = !empty($tenants);
$breadcrumbs = [
['label' => t('Home'), 'path' => 'admin'],
['label' => t('Departments'), 'path' => 'admin/departments'],
@@ -26,6 +27,7 @@
'value' => 'create',
'class' => 'secondary outline',
'label' => t('Create'),
'disabled' => !$hasTenantOptions,
],
[
'form' => 'department-form',
@@ -33,6 +35,7 @@
'value' => 'create_close',
'class' => 'primary',
'label' => t('Create & close'),
'disabled' => !$hasTenantOptions,
],
],
];

View File

@@ -19,6 +19,7 @@ $isReadOnly = !$canUpdateDepartment;
<div class="app-details-container">
<section>
<?php
$hasTenantOptions = !empty($tenants);
$breadcrumbs = [
['label' => t('Home'), 'path' => 'admin'],
['label' => t('Departments'), 'path' => 'admin/departments'],
@@ -36,6 +37,7 @@ $isReadOnly = !$canUpdateDepartment;
'value' => 'save',
'class' => 'secondary outline',
'label' => t('Save'),
'disabled' => !$hasTenantOptions,
],
[
'form' => 'department-form',
@@ -43,6 +45,7 @@ $isReadOnly = !$canUpdateDepartment;
'value' => 'save_close',
'class' => 'primary',
'label' => t('Save & close'),
'disabled' => !$hasTenantOptions,
],
] : [],
];

View File

@@ -24,15 +24,15 @@ $dangerZoneActionLabel = (string) ($dangerZoneActionLabel ?? t('Delete'));
$detailsOpenAttr = $detailsOpenAll ? 'open' : '';
$readonlyAttr = $isReadOnly ? 'readonly' : '';
$disabledAttr = $isReadOnly ? 'disabled' : '';
$permissions = is_array($permissions ?? null) ? $permissions : [];
$selectedPermissionIds = is_array($selectedPermissionIds ?? null) ? $selectedPermissionIds : [];
?>
<form id="<?php e($formId); ?>" method="post" data-standard-detail-form="1">
<div class="app-tabs" data-tabs data-tabs-param="tab" data-tabs-storage-key="admin-role-form">
<div class="app-tabs-nav">
<button type="button" data-tab="basic" data-tab-default><?php e(t('Master data')); ?></button>
<?php if (!empty($permissions)): ?>
<button type="button" data-tab="permissions"><?php e(t('Permissions')); ?></button>
<?php endif; ?>
<button type="button" data-tab="permissions"><?php e(t('Permissions')); ?></button>
<button type="button" data-tab="visibility"><?php e(t('Visibility')); ?></button>
<?php if ($showDangerZone && $dangerZoneDeleteFormId !== ''): ?>
<button type="button" data-tab="danger"><?php e(t('Danger zone')); ?></button>
@@ -54,11 +54,20 @@ $disabledAttr = $isReadOnly ? 'disabled' : '';
</div>
</div>
<?php if (!empty($permissions)): ?>
<div data-tab-panel="permissions">
<?php multiSelectForm('role-permissions', 'permission_ids', 'Assigned permissions', 'Select permissions', $permissions, $selectedPermissionIds ?? [], $isReadOnly, ['description', 'key']); ?>
</div>
<?php endif; ?>
<div data-tab-panel="permissions">
<?php if ($permissions): ?>
<?php multiSelectForm('role-permissions', 'permission_ids', 'Assigned permissions', 'Select permissions', $permissions, $selectedPermissionIds, $isReadOnly, ['description', 'key']); ?>
<?php else: ?>
<?php
$emptyState = [
'message' => t('No permissions available'),
'hint' => t('No active permissions are configured yet.'),
'size' => 'compact',
];
require templatePath('partials/app-empty-state.phtml');
?>
<?php endif; ?>
</div>
<div data-tab-panel="visibility">
<?php

View File

@@ -265,7 +265,19 @@ $openOverrideCard = $detailsOpenAll;
<?php if ($showCustomFieldsTab): ?>
<div data-tab-panel="custom_fields">
<?php if ($customFieldTenantUuid === ''): ?>
<p class="muted"><?php e(t('Save tenant first to manage custom fields')); ?></p>
<?php
$emptyState = [
'message' => t('Save tenant first to manage custom fields'),
'size' => 'compact',
];
if (!$isReadOnly) {
$emptyState['action'] = [
'label' => t('Create'),
'form' => $formId,
];
}
require templatePath('partials/app-empty-state.phtml');
?>
<?php else: ?>
<blockquote data-variant="info">
<?php e(t('Define custom fields here. They appear per user in the "Custom fields" tab and can be maintained there.')); ?>

View File

@@ -229,7 +229,15 @@ $hasFavicon = $avatarUuid !== '' && $tenantFaviconService->hasFavicon($avatarUui
</div>
<?php endif; ?>
<?php else: ?>
<p>-</p>
<?php
$emptyState = [
'message' => t('No contact details available'),
'size' => 'small',
'align' => 'left',
'icon' => false,
];
require templatePath('partials/app-empty-state.phtml');
?>
<?php endif; ?>
</details>
<hr>
@@ -258,7 +266,15 @@ $hasFavicon = $avatarUuid !== '' && $tenantFaviconService->hasFavicon($avatarUui
</div>
<?php endif; ?>
<?php else: ?>
<p>-</p>
<?php
$emptyState = [
'message' => t('No legal links configured'),
'size' => 'small',
'align' => 'left',
'icon' => false,
];
require templatePath('partials/app-empty-state.phtml');
?>
<?php endif; ?>
</details>
<hr>

View File

@@ -315,7 +315,8 @@ foreach ($tenants as $tenant) {
<?php if (!$passwordResets): ?>
<?php
$emptyState = [
'message' => t('No entries found'),
'message' => t('No password reset requests'),
'hint' => t('No reset has been requested for this account yet.'),
'size' => 'compact',
];
require templatePath('partials/app-empty-state.phtml');
@@ -380,7 +381,8 @@ foreach ($tenants as $tenant) {
<?php if (!$rememberTokens): ?>
<?php
$emptyState = [
'message' => t('No entries found'),
'message' => t('No login tokens'),
'hint' => t('This user is currently not signed in via remember-me.'),
'size' => 'compact',
];
require templatePath('partials/app-empty-state.phtml');
@@ -543,10 +545,13 @@ foreach ($tenants as $tenant) {
</table>
</div>
<?php endif; ?>
<?php if (empty($apiTokens) && !$canManageApiTokens): ?>
<?php if (empty($apiTokens)): ?>
<?php
$emptyState = [
'message' => t('No API tokens'),
'hint' => $canManageApiTokens
? t('Create a token to enable API access for this user.')
: t('No API token has been created for this user yet.'),
'size' => 'compact',
];
require templatePath('partials/app-empty-state.phtml');
@@ -563,35 +568,46 @@ foreach ($tenants as $tenant) {
<details name="assignments-tenants" data-details-key="assignments-tenants" open>
<summary><?php e(t('Tenants')); ?></summary>
<hr>
<?php multiSelectForm('user-tenants', 'tenant_ids', 'Assigned tenants', 'Select tenants', $tenants, $selectedTenantIds, $isReadOnly); ?>
<label>
<span>
<?php e(t('Primary tenant')); ?>
</span>
</label>
<?php if ($primaryTenantDisabled && $primaryTenantId > 0): ?>
<input type="hidden" name="primary_tenant_id" value="<?php e((string) $primaryTenantId); ?>">
<?php endif; ?>
<select id="user-primary-tenant" name="primary_tenant_id" <?php e($primaryTenantDisabledAttr); ?>
<?php e($disabledAttr); ?>>
<?php if (count($selectedTenantIds) !== 1): ?>
<option value="">
<?php e(t('Select primary tenant')); ?>
</option>
<?php if (!$tenants): ?>
<?php
$emptyState = [
'message' => t('No tenants available'),
'hint' => t('No tenant is available in your current scope.'),
'size' => 'compact',
];
require templatePath('partials/app-empty-state.phtml');
?>
<?php else: ?>
<?php multiSelectForm('user-tenants', 'tenant_ids', 'Assigned tenants', 'Select tenants', $tenants, $selectedTenantIds, $isReadOnly); ?>
<label>
<span>
<?php e(t('Primary tenant')); ?>
</span>
</label>
<?php if ($primaryTenantDisabled && $primaryTenantId > 0): ?>
<input type="hidden" name="primary_tenant_id" value="<?php e((string) $primaryTenantId); ?>">
<?php endif; ?>
<?php foreach ($tenants as $tenant): ?>
<?php
$tenantId = (int) ($tenant['id'] ?? 0);
if (!in_array($tenantId, $selectedTenantIds ?? [], true)) {
continue;
}
$selected = $tenantId === $primaryTenantId ? 'selected' : '';
?>
<option value="<?php e((string) $tenantId); ?>" <?php e($selected); ?>>
<?php e($tenant['description'] ?? ''); ?>
</option>
<?php endforeach; ?>
</select>
<select id="user-primary-tenant" name="primary_tenant_id" <?php e($primaryTenantDisabledAttr); ?>
<?php e($disabledAttr); ?>>
<?php if (count($selectedTenantIds) !== 1): ?>
<option value="">
<?php e(t('Select primary tenant')); ?>
</option>
<?php endif; ?>
<?php foreach ($tenants as $tenant): ?>
<?php
$tenantId = (int) ($tenant['id'] ?? 0);
if (!in_array($tenantId, $selectedTenantIds ?? [], true)) {
continue;
}
$selected = $tenantId === $primaryTenantId ? 'selected' : '';
?>
<option value="<?php e((string) $tenantId); ?>" <?php e($selected); ?>>
<?php e($tenant['description'] ?? ''); ?>
</option>
<?php endforeach; ?>
</select>
<?php endif; ?>
</details>
<hr>
<?php endif; ?>
@@ -655,7 +671,18 @@ foreach ($tenants as $tenant) {
<details name="assignments-roles" data-details-key="assignments-roles">
<summary><?php e(t('Roles')); ?></summary>
<hr>
<?php multiSelectForm('user-roles', 'role_ids', 'Assigned roles', 'Select roles', $roles, $selectedRoleIds, $isReadOnly); ?>
<?php if (!$roles): ?>
<?php
$emptyState = [
'message' => t('No roles available'),
'hint' => t('No active roles are configured yet.'),
'size' => 'compact',
];
require templatePath('partials/app-empty-state.phtml');
?>
<?php else: ?>
<?php multiSelectForm('user-roles', 'role_ids', 'Assigned roles', 'Select roles', $roles, $selectedRoleIds, $isReadOnly); ?>
<?php endif; ?>
</details>
<?php endif; ?>
<?php endif; ?>
@@ -667,7 +694,8 @@ foreach ($tenants as $tenant) {
<?php if (!$permissionRows): ?>
<?php
$emptyState = [
'message' => t('No entries found'),
'message' => t('No effective permissions'),
'hint' => t('Assign at least one role to show effective permissions.'),
'size' => 'compact',
];
require templatePath('partials/app-empty-state.phtml');

View File

@@ -175,7 +175,7 @@ if ($canViewSecurityArtifacts) {
$apiTokens = $apiTokenService->listForUser($userId);
}
$canManageApiTokens = $canManageApiTokens && $canViewSecurityArtifacts;
$showApiTokens = $canViewSecurityArtifacts && (!empty($apiTokens) || $canManageApiTokens);
$showApiTokens = $canViewSecurityArtifacts;
if ($request->isMethod('POST') && !Session::checkCsrfToken()) {
Flash::error(t('Form expired, please try again'), $editTarget, 'csrf_expired');