Keine Rollen
- {roleFilter === 'mandate'
+ {scopeFilter === 'mandate'
? 'Es gibt noch keine mandantenspezifischen Rollen.'
- : roleFilter === 'global'
+ : scopeFilter === 'global'
? 'Es gibt noch keine globalen Rollen.'
: 'Es gibt noch keine Rollen für diesen Mandanten.'}
@@ -420,7 +413,7 @@ export const AdminMandateRolesPage: React.FC = () => {
) : (
{
type: 'edit' as const,
onAction: handleEditClick,
title: 'Rolle bearbeiten',
+ disabled: (row: Role) => row.isSystemRole ? { disabled: true, message: 'System-Rollen können nicht bearbeitet werden' } : false
},
{
type: 'delete' as const,
@@ -443,7 +437,7 @@ export const AdminMandateRolesPage: React.FC = () => {
]}
onDelete={handleDeleteRole}
hookData={{
- refetch: refetchWithPagination,
+ refetch: refetchWithParams,
pagination: pagination,
handleDelete: handleDeleteRole,
}}
@@ -477,7 +471,7 @@ export const AdminMandateRolesPage: React.FC = () => {
mode="create"
onSubmit={handleCreateRole}
onCancel={() => setShowCreateModal(false)}
- submitButtonText="Rolle erstellen"
+ submitButtonText={isSubmitting ? 'Erstelle...' : 'Rolle erstellen'}
cancelButtonText="Abbrechen"
/>
)}
@@ -507,22 +501,20 @@ export const AdminMandateRolesPage: React.FC = () => {
) : (
<>
- {editingRole.isSystemRole && (
-
-
- System-Rollen können nur eingeschränkt bearbeitet werden.
-
- )}
+
+
+
+ Geltungsbereich: {editingRole.mandateId ? 'Mandant-spezifisch' : 'Global'}
+ {' '}(kann nicht geändert werden)
+
+
setEditingRole(null)}
- submitButtonText="Speichern"
+ submitButtonText={isSubmitting ? 'Speichern...' : 'Speichern'}
cancelButtonText="Abbrechen"
/>
>
diff --git a/src/pages/admin/AdminRolesPage.tsx b/src/pages/admin/AdminRolesPage.tsx
deleted file mode 100644
index 9d9987b..0000000
--- a/src/pages/admin/AdminRolesPage.tsx
+++ /dev/null
@@ -1,273 +0,0 @@
-/**
- * AdminRolesPage
- *
- * Admin page for managing global RBAC Roles using FormGeneratorTable.
- */
-
-import React, { useState, useMemo } from 'react';
-import { useAdminRoles, type Role } from '../../hooks/useRoles';
-import { FormGeneratorTable } from '../../components/FormGenerator/FormGeneratorTable';
-import { FormGeneratorForm, type AttributeDefinition } from '../../components/FormGenerator/FormGeneratorForm';
-import { FaPlus, FaSync, FaUserShield } from 'react-icons/fa';
-import styles from './Admin.module.css';
-
-export const AdminRolesPage: React.FC = () => {
- const {
- roles,
- attributes,
- columns,
- permissions,
- pagination,
- loading,
- error,
- refetch,
- fetchRoleById,
- handleCreate,
- handleUpdate,
- handleDelete,
- handleInlineUpdate,
- updateOptimistically,
- } = useAdminRoles();
-
- const [showCreateModal, setShowCreateModal] = useState(false);
- const [editingRole, setEditingRole] = useState(null);
- const [isSubmitting, setIsSubmitting] = useState(false);
-
- // Columns for global roles - exclude mandate/feature-specific columns
- // Global roles don't have mandate or feature instance associations
- const displayColumns = useMemo(() => {
- const excludedColumns = ['mandateId', 'featureInstanceId', 'featureCode'];
- return columns.filter(col => !excludedColumns.includes(col.key));
- }, [columns]);
-
- // Check permissions
- const canCreate = permissions?.create !== 'n';
- const canUpdate = permissions?.update !== 'n';
- const canDelete = permissions?.delete !== 'n';
-
- // Handle edit click
- const handleEditClick = async (role: Role) => {
- const fullRole = await fetchRoleById(role.id);
- if (fullRole) {
- setEditingRole(fullRole);
- }
- };
-
- // Handle create submit
- const handleCreateSubmit = async (data: Partial) => {
- setIsSubmitting(true);
- try {
- const success = await handleCreate(data);
- if (success) {
- setShowCreateModal(false);
- }
- } finally {
- setIsSubmitting(false);
- }
- };
-
- // Handle edit submit
- const handleEditSubmit = async (data: Partial) => {
- if (!editingRole) return;
- setIsSubmitting(true);
- try {
- const success = await handleUpdate(editingRole.id, data);
- if (success) {
- setEditingRole(null);
- }
- } finally {
- setIsSubmitting(false);
- }
- };
-
- // Handle delete
- const handleDeleteRole = async (role: Role) => {
- if (window.confirm(`Möchten Sie die Rolle "${role.roleLabel || role.id}" wirklich löschen?`)) {
- await handleDelete(role.id);
- }
- };
-
- // Form attributes from backend - filter for create/edit forms
- // Exclude fields not relevant for global roles (mandateId, featureInstanceId, etc.)
- const formAttributes: AttributeDefinition[] = useMemo(() => {
- const excludedFields = ['id', 'mandateId', 'featureInstanceId', 'featureCode', 'isSystemRole'];
- return attributes
- .filter(attr => !excludedFields.includes(attr.name))
- .map(attr => ({
- ...attr,
- // Map backend type names to form types
- type: attr.type === 'multilingual' ? 'multilingual' : attr.type,
- })) as AttributeDefinition[];
- }, [attributes]);
-
- if (error) {
- return (
-
-
-
⚠️
-
Fehler beim Laden der Rollen: {error}
-
refetch()}>
- Erneut versuchen
-
-
-
- );
- }
-
- return (
-
-
-
-
Globale Rollen
-
Verwalten Sie die systemweiten RBAC-Rollen
-
-
- refetch()}
- disabled={loading}
- >
- Aktualisieren
-
- {canCreate && (
- setShowCreateModal(true)}
- >
- Neue Rolle
-
- )}
-
-
-
-
- {loading && roles.length === 0 ? (
-
- ) : roles.length === 0 ? (
-
-
-
Keine Rollen vorhanden
-
- Erstellen Sie eine neue Rolle, um Berechtigungen zu definieren.
-
- {canCreate && (
-
setShowCreateModal(true)}
- >
- Erste Rolle erstellen
-
- )}
-
- ) : (
-
- )}
-
-
- {/* Create Modal */}
- {showCreateModal && (
-
setShowCreateModal(false)}>
-
e.stopPropagation()}>
-
-
Neue Rolle
- setShowCreateModal(false)}
- >
- ✕
-
-
-
- {formAttributes.length === 0 ? (
-
- ) : (
-
setShowCreateModal(false)}
- submitButtonText={isSubmitting ? 'Erstelle...' : 'Erstellen'}
- cancelButtonText="Abbrechen"
- />
- )}
-
-
-
- )}
-
- {/* Edit Modal */}
- {editingRole && (
-
setEditingRole(null)}>
-
e.stopPropagation()}>
-
-
Rolle bearbeiten
- setEditingRole(null)}
- >
- ✕
-
-
-
- {formAttributes.length === 0 ? (
-
- ) : (
-
setEditingRole(null)}
- submitButtonText={isSubmitting ? 'Speichern...' : 'Speichern'}
- cancelButtonText="Abbrechen"
- />
- )}
-
-
-
- )}
-
- );
-};
-
-export default AdminRolesPage;
diff --git a/src/pages/admin/AdminUserMandatesPage.tsx b/src/pages/admin/AdminUserMandatesPage.tsx
index cfa5b8d..9c15529 100644
--- a/src/pages/admin/AdminUserMandatesPage.tsx
+++ b/src/pages/admin/AdminUserMandatesPage.tsx
@@ -5,7 +5,7 @@
* Allows assigning users to mandates and managing their roles within mandates.
*/
-import React, { useState, useEffect, useMemo, useCallback } from 'react';
+import React, { useState, useEffect, useMemo, useCallback, useRef } from 'react';
import { useUserMandates, type MandateUser, type Mandate, type Role, type PaginationParams } from '../../hooks/useUserMandates';
import { FormGeneratorTable } from '../../components/FormGenerator/FormGeneratorTable';
import { FormGeneratorForm, type AttributeDefinition } from '../../components/FormGenerator/FormGeneratorForm';
@@ -27,6 +27,9 @@ export const AdminUserMandatesPage: React.FC = () => {
fetchRoles,
fetchAllUsers,
} = useUserMandates();
+
+ // Store current mandateId for refetch
+ const currentMandateIdRef = useRef('');
// State
const [mandates, setMandates] = useState([]);
@@ -59,11 +62,23 @@ export const AdminUserMandatesPage: React.FC = () => {
// Load users when mandate changes
useEffect(() => {
if (selectedMandateId) {
+ currentMandateIdRef.current = selectedMandateId;
fetchMandateUsers(selectedMandateId);
fetchRoles(selectedMandateId).then(setRoles);
}
}, [selectedMandateId, fetchMandateUsers, fetchRoles]);
+ // Refetch wrapper that accepts pagination params from FormGeneratorTable
+ const refetchWithParams = useCallback(async (paginationParams?: PaginationParams) => {
+ const mandateId = currentMandateIdRef.current;
+ if (!mandateId) return;
+ // If pagination params provided, pass them; otherwise just use mandateId
+ if (paginationParams && Object.keys(paginationParams).length > 0) {
+ return fetchMandateUsers(paginationParams);
+ }
+ return fetchMandateUsers(mandateId);
+ }, [fetchMandateUsers]);
+
// Load all users for the add modal
useEffect(() => {
fetchAllUsers().then(setAllUsers);
@@ -357,8 +372,8 @@ export const AdminUserMandatesPage: React.FC = () => {
]}
onDelete={handleRemoveUser}
hookData={{
- refetch: fetchMandateUsers,
- pagination,
+ refetch: refetchWithParams,
+ pagination: pagination,
handleDelete: async (userMandateId: string) => {
// Find user by UserMandate ID to get userId for API call
const user = users.find(u => u.id === userMandateId);
@@ -401,7 +416,7 @@ export const AdminUserMandatesPage: React.FC = () => {
mode="create"
onSubmit={handleAddUser}
onCancel={() => setShowAddModal(false)}
- submitButtonText="Hinzufügen"
+ submitButtonText={isSubmitting ? 'Hinzufügen...' : 'Hinzufügen'}
cancelButtonText="Abbrechen"
/>
)}
@@ -430,7 +445,7 @@ export const AdminUserMandatesPage: React.FC = () => {
mode="edit"
onSubmit={handleEditRoles}
onCancel={() => setEditingUser(null)}
- submitButtonText="Speichern"
+ submitButtonText={isSubmitting ? 'Speichern...' : 'Speichern'}
cancelButtonText="Abbrechen"
/>
diff --git a/src/pages/admin/index.ts b/src/pages/admin/index.ts
index 67215b4..90ee496 100644
--- a/src/pages/admin/index.ts
+++ b/src/pages/admin/index.ts
@@ -6,9 +6,9 @@
export { AdminMandatesPage } from './AdminMandatesPage';
export { AdminUsersPage } from './AdminUsersPage';
-export { AdminRolesPage } from './AdminRolesPage';
export { AdminUserMandatesPage } from './AdminUserMandatesPage';
export { AdminFeatureAccessPage } from './AdminFeatureAccessPage';
export { AdminInvitationsPage } from './AdminInvitationsPage';
export { AdminMandateRolesPage } from './AdminMandateRolesPage';
+export { AdminFeatureRolesPage } from './AdminFeatureRolesPage';
export { AdminFeatureInstanceUsersPage } from './AdminFeatureInstanceUsersPage';
\ No newline at end of file