fix(web): Oberflaechentexte ohne Mandanten-Begriff, Organisationsauswahl im Marktplatz nur bei mehreren
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -13,7 +13,7 @@ const messages: Record<string, Record<string, unknown>> = {
|
||||
title: 'Freigaben-Matrix',
|
||||
searchPlaceholder: 'Module oder Gruppen durchsuchen...',
|
||||
emptyModules:
|
||||
'Es sind noch keine Module für diesen Mandanten aktiviert. Aktiviere zuerst ein Modul unter Module.',
|
||||
'Es sind noch keine Module aktiviert. Aktiviere zuerst ein Modul unter Module.',
|
||||
emptyModulesLink: 'Zu Module',
|
||||
adminNote:
|
||||
'ADMIN und SUPER_ADMIN haben immer Zugriff auf alle aktiven Module — diese Matrix betrifft nur die Rolle USER.',
|
||||
@@ -153,7 +153,7 @@ describe('AdminModuleGrantsPage (Permission-Matrix)', () => {
|
||||
render(<AdminModuleGrantsPage />);
|
||||
|
||||
await waitFor(() => {
|
||||
expect(screen.getByText(/keine Module für diesen Mandanten aktiviert/)).toBeInTheDocument();
|
||||
expect(screen.getByText(/noch keine Module aktiviert/)).toBeInTheDocument();
|
||||
});
|
||||
const link = screen.getByText('Zu Module');
|
||||
expect(link.closest('a')).toHaveAttribute('href', '/admin/modules');
|
||||
|
||||
@@ -34,7 +34,8 @@ export function TenantContextSelector() {
|
||||
.finally(() => setLoading(false));
|
||||
}, [isSuperAdmin]);
|
||||
|
||||
if (!isSuperAdmin) return null;
|
||||
// Nur bei mehreren Organisationen sinnvoll; im Ein-Firmen-Betrieb ausgeblendet.
|
||||
if (!isSuperAdmin || (!loading && tenants.length <= 1)) return null;
|
||||
|
||||
return (
|
||||
<div className="flex flex-wrap items-center gap-3 rounded-lg bg-card px-4 py-3 shadow-sm dark:border dark:border-border">
|
||||
|
||||
@@ -25,7 +25,7 @@ vi.mock('next-intl', () => ({
|
||||
errorLoad: 'Module konnten nicht geladen werden.',
|
||||
toastActivated: 'Modul erfolgreich aktiviert',
|
||||
accessDenied: 'Zugriff verweigert',
|
||||
tenantContextLabel: 'Mandanten-Kontext',
|
||||
tenantContextLabel: 'Organisation',
|
||||
};
|
||||
let result = translations[key] ?? key;
|
||||
if (params) {
|
||||
|
||||
@@ -27,7 +27,7 @@ vi.mock('next-intl', () => ({
|
||||
toastActivated: 'Modul erfolgreich aktiviert',
|
||||
toastDeactivated: 'Modul erfolgreich deaktiviert',
|
||||
accessDenied: 'Zugriff verweigert',
|
||||
tenantContextLabel: 'Mandanten-Kontext',
|
||||
tenantContextLabel: 'Organisation',
|
||||
deactivateDialogTitle: 'Modul deaktivieren',
|
||||
deactivateDialogBody: 'Moechten Sie {moduleName} fuer diesen Mandanten deaktivieren?',
|
||||
deactivateDialogConfirm: 'Deaktivieren',
|
||||
@@ -118,6 +118,21 @@ describe('TenantContextSelector', () => {
|
||||
expect(screen.getByText('Tenant Beta')).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('blendet die Auswahl bei nur einer Organisation aus', async () => {
|
||||
mockAuthStore.mockImplementation(
|
||||
(selector: (state: { user: { id: string; username: string; displayName: string; role: string; tenantId: string } }) => unknown) =>
|
||||
selector({
|
||||
user: { id: 'u1', username: 'superadmin', displayName: 'Super', role: 'SUPER_ADMIN', tenantId: 't1' },
|
||||
}),
|
||||
);
|
||||
vi.stubGlobal(
|
||||
'fetch',
|
||||
vi.fn(() => Promise.resolve({ ok: true, json: () => Promise.resolve([mockTenants[0]]) })),
|
||||
);
|
||||
const { container } = render(<TenantContextSelector />);
|
||||
await waitFor(() => expect(container.innerHTML).toBe(''));
|
||||
});
|
||||
|
||||
it('renders nothing for ADMIN and does not load the tenant list', () => {
|
||||
mockAuthStore.mockImplementation(
|
||||
(selector: (state: { user: { id: string; username: string; displayName: string; role: string; tenantId: string } }) => unknown) =>
|
||||
|
||||
@@ -120,7 +120,7 @@ describe('WelcomeMailTemplateEditor', () => {
|
||||
]) {
|
||||
expect(within(box).getByRole('button', { name: `${token} einfügen` })).toBeTruthy();
|
||||
}
|
||||
expect(within(box).getByText('Name Ihres Mandanten')).toBeTruthy();
|
||||
expect(within(box).getByText('Name Ihrer Organisation')).toBeTruthy();
|
||||
expect(within(box).getByText('max.mustermann@example.com')).toBeTruthy();
|
||||
});
|
||||
|
||||
|
||||
@@ -555,7 +555,7 @@
|
||||
"viaGroupsColumn": "Über Gruppe(n)",
|
||||
"directColumn": "Direkt",
|
||||
"noInheritance": "–",
|
||||
"noActiveModules": "Für diesen Mandanten sind keine Module aktiviert.",
|
||||
"noActiveModules": "Es sind keine Module aktiviert.",
|
||||
"directCheckboxLabel": "{module} direkt für {user} {granted, select, true {freigeben} other {entziehen}}",
|
||||
"directLevelLabel": "Stufe der direkten Freigabe von {module} für {user}",
|
||||
"manageMarker": "Verwalten",
|
||||
@@ -751,7 +751,7 @@
|
||||
},
|
||||
"welcomeMail": {
|
||||
"title": "Willkommensmail",
|
||||
"description": "Hier legen Sie fest, mit welchen Worten Tessera neue Benutzer begrüßt. Die Vorlage gilt für Ihren Mandanten und wird bei jeder Willkommensmail aus der Benutzerverwaltung verwendet.",
|
||||
"description": "Hier legen Sie fest, mit welchen Worten Tessera neue Benutzer begrüßt. Die Vorlage gilt für alle Benutzer und wird bei jeder Willkommensmail aus der Benutzerverwaltung verwendet.",
|
||||
"loading": "Vorlage wird geladen …",
|
||||
"fixed": {
|
||||
"title": "Was Sie anpassen können – und was immer drin bleibt",
|
||||
@@ -832,7 +832,7 @@
|
||||
"example": "https://tessera.example.com"
|
||||
},
|
||||
"firma": {
|
||||
"meaning": "Name Ihres Mandanten",
|
||||
"meaning": "Name Ihrer Organisation",
|
||||
"example": "Beispiel GmbH"
|
||||
}
|
||||
}
|
||||
@@ -846,13 +846,13 @@
|
||||
"frameTitle": "Vorschau der Willkommensmail",
|
||||
"error": "Die Vorschau konnte nicht erstellt werden.",
|
||||
"blocked": "Die Vorschau wird aktualisiert, sobald alle Felder in Ordnung sind.",
|
||||
"sampleHint": "Die Vorschau verwendet Beispielwerte (Max Mustermann) und den Namen Ihres Mandanten. Der Link „Passwort festlegen“ ist in der Vorschau nur ein Beispiel."
|
||||
"sampleHint": "Die Vorschau verwendet Beispielwerte (Max Mustermann) und den Namen Ihrer Organisation. Der Link „Passwort festlegen“ ist in der Vorschau nur ein Beispiel."
|
||||
}
|
||||
}
|
||||
},
|
||||
"adminModules": {
|
||||
"title": "Modulverwaltung",
|
||||
"description": "Module für Ihren Mandanten aktivieren oder deaktivieren",
|
||||
"description": "Module aktivieren oder deaktivieren",
|
||||
"activate": "Aktivieren",
|
||||
"deactivate": "Deaktivieren",
|
||||
"activated": "Aktiviert",
|
||||
@@ -868,7 +868,7 @@
|
||||
"grants": {
|
||||
"title": "Freigaben-Matrix",
|
||||
"searchPlaceholder": "Module oder Gruppen durchsuchen...",
|
||||
"emptyModules": "Es sind noch keine Module für diesen Mandanten aktiviert. Aktiviere zuerst ein Modul unter Module.",
|
||||
"emptyModules": "Es sind noch keine Module aktiviert. Aktiviere zuerst ein Modul unter Module.",
|
||||
"emptyModulesLink": "Zu Module",
|
||||
"levelExplanation": "„Benutzen“: Das Modul öffnen und damit arbeiten. „Verwalten“: zusätzlich die Einstellungen dieses Moduls ändern. Freigaben vergeben und Module aktivieren dürfen weiterhin nur Administratoren. Hat jemand über mehrere Wege Zugriff, gilt die höhere Stufe.",
|
||||
"adminNote": "Administratoren haben immer Zugriff auf alle aktiven Module und dürfen deren Einstellungen ändern – diese Matrix betrifft nur Benutzer ohne Administratorrechte.",
|
||||
@@ -964,7 +964,7 @@
|
||||
"notFoundDescription": "Das angeforderte Modul existiert nicht oder ist nicht aktiviert.",
|
||||
"backToCategory": "Zurück zur Kategorie",
|
||||
"allModules": "Module",
|
||||
"allModulesDescription": "Verfügbare Module für Ihren Mandanten",
|
||||
"allModulesDescription": "Verfügbare Module",
|
||||
"noActiveModules": "Keine Module aktiviert. Bitten Sie Ihren Administrator, Module zu aktivieren.",
|
||||
"accessDenied": {
|
||||
"title": "Kein Zugriff auf dieses Modul",
|
||||
@@ -1194,7 +1194,7 @@
|
||||
},
|
||||
"marketplace": {
|
||||
"title": "Marktplatz",
|
||||
"subtitle": "Entdecken und aktivieren Sie Module für Ihren Mandanten",
|
||||
"subtitle": "Entdecken und aktivieren Sie Module",
|
||||
"activate": "Modul aktivieren",
|
||||
"deactivate": "Deaktivieren",
|
||||
"searchPlaceholder": "Module suchen...",
|
||||
@@ -1212,13 +1212,13 @@
|
||||
"toastActivateError": "Aktivierung fehlgeschlagen. Bitte versuchen Sie es erneut.",
|
||||
"toastDeactivateError": "Deaktivierung fehlgeschlagen. Bitte versuchen Sie es erneut.",
|
||||
"deactivateDialogTitle": "Modul deaktivieren",
|
||||
"deactivateDialogBody": "Möchten Sie {moduleName} für diesen Mandanten deaktivieren? Das Modul wird aus der Seitenleiste entfernt.",
|
||||
"deactivateDialogBody": "Möchten Sie {moduleName} deaktivieren? Das Modul wird aus der Seitenleiste entfernt.",
|
||||
"deactivateDialogConfirm": "Deaktivieren",
|
||||
"deactivateDialogCancel": "Abbrechen",
|
||||
"tenantContextLabel": "Mandanten-Kontext",
|
||||
"tenantContextLabel": "Organisation",
|
||||
"backToMarketplace": "Zurück zum Marktplatz",
|
||||
"detailVersion": "Version {version}",
|
||||
"detailStatusActive": "Aktiviert für diesen Mandanten",
|
||||
"detailStatusActive": "Aktiviert",
|
||||
"detailStatusInactive": "Nicht aktiviert",
|
||||
"accessDenied": "Zugriff verweigert",
|
||||
"statusNoAccess": "Kein Zugriff",
|
||||
@@ -1528,7 +1528,7 @@
|
||||
"settings": {
|
||||
"title": "Ausschreibungs-Radar — Einstellungen",
|
||||
"rssSectionTitle": "RSS-Feeds",
|
||||
"rssSectionBody": "Öffentliche, plattformweite RSS-Quellen (z. B. service.bund.de oder eine subreport-elvis-Kommunalfeed) — gilt für alle Mandanten gleich, nicht pro Mandant konfigurierbar.",
|
||||
"rssSectionBody": "Öffentliche, plattformweite RSS-Quellen (z. B. service.bund.de oder eine subreport-elvis-Kommunalfeed) — gilt für alle gleich.",
|
||||
"rssSectionUserNote": "Persönliche Feeds legen Sie auf „Meine Quellen\" an.",
|
||||
"accessDeniedText": "Diese Seite verwaltet plattformweite Einstellungen und ist Administratoren vorbehalten.",
|
||||
"digestIntervalLabel": "Digest-Intervall",
|
||||
@@ -1611,7 +1611,7 @@
|
||||
},
|
||||
"mySources": {
|
||||
"title": "Meine Quellen",
|
||||
"intro": "Ausschreibungen, die aus Ihrem Postfach hereinkommen, erscheinen danach in der Trefferliste aller Kolleginnen und Kollegen Ihres Mandanten — es gibt keine getrennte Sichtbarkeit je Postfach.",
|
||||
"intro": "Ausschreibungen, die aus Ihrem Postfach hereinkommen, erscheinen danach in der Trefferliste aller Kolleginnen und Kollegen — es gibt keine getrennte Sichtbarkeit je Postfach.",
|
||||
"mailboxSectionTitle": "Mein Postfach",
|
||||
"feedsSectionTitle": "Meine Feeds",
|
||||
"notificationSectionTitle": "Benachrichtigung",
|
||||
|
||||
@@ -555,7 +555,7 @@
|
||||
"viaGroupsColumn": "Via Group(s)",
|
||||
"directColumn": "Direct",
|
||||
"noInheritance": "–",
|
||||
"noActiveModules": "No modules are activated for this tenant.",
|
||||
"noActiveModules": "No modules are activated.",
|
||||
"directCheckboxLabel": "{granted, select, true {Grant} other {Revoke}} {module} directly for {user}",
|
||||
"directLevelLabel": "Level of the direct grant of {module} for {user}",
|
||||
"manageMarker": "Manage",
|
||||
@@ -751,7 +751,7 @@
|
||||
},
|
||||
"welcomeMail": {
|
||||
"title": "Welcome email",
|
||||
"description": "Choose the words Tessera uses to greet new users. The template applies to your tenant and is used for every welcome email sent from user management.",
|
||||
"description": "Choose the words Tessera uses to greet new users. The template applies to all users and is used for every welcome email sent from user management.",
|
||||
"loading": "Loading template …",
|
||||
"fixed": {
|
||||
"title": "What you can change – and what always stays",
|
||||
@@ -832,7 +832,7 @@
|
||||
"example": "https://tessera.example.com"
|
||||
},
|
||||
"firma": {
|
||||
"meaning": "Name of your tenant",
|
||||
"meaning": "Name of your organization",
|
||||
"example": "Example Ltd"
|
||||
}
|
||||
}
|
||||
@@ -846,13 +846,13 @@
|
||||
"frameTitle": "Welcome email preview",
|
||||
"error": "The preview could not be created.",
|
||||
"blocked": "The preview updates as soon as all fields are valid.",
|
||||
"sampleHint": "The preview uses sample values (Max Mustermann) and the name of your tenant. The “Set password” link is only an example in the preview."
|
||||
"sampleHint": "The preview uses sample values (Max Mustermann) and the name of your organization. The “Set password” link is only an example in the preview."
|
||||
}
|
||||
}
|
||||
},
|
||||
"adminModules": {
|
||||
"title": "Module Management",
|
||||
"description": "Activate or deactivate modules for your tenant",
|
||||
"description": "Activate or deactivate modules",
|
||||
"activate": "Activate",
|
||||
"deactivate": "Deactivate",
|
||||
"activated": "Activated",
|
||||
@@ -868,7 +868,7 @@
|
||||
"grants": {
|
||||
"title": "Grants Matrix",
|
||||
"searchPlaceholder": "Search modules or groups...",
|
||||
"emptyModules": "No modules are activated for this tenant yet. Activate a module under Modules first.",
|
||||
"emptyModules": "No modules are activated yet. Activate a module under Modules first.",
|
||||
"emptyModulesLink": "Go to Modules",
|
||||
"levelExplanation": "“Use”: open the module and work with it. “Manage”: additionally change the settings of this module. Only administrators may grant access and activate modules. If someone has access through several routes, the higher level applies.",
|
||||
"adminNote": "Administrators always have access to all active modules and may change their settings — this matrix only affects users without administrator rights.",
|
||||
@@ -964,7 +964,7 @@
|
||||
"notFoundDescription": "The requested module does not exist or is not activated.",
|
||||
"backToCategory": "Back to category",
|
||||
"allModules": "Modules",
|
||||
"allModulesDescription": "Available modules for your tenant",
|
||||
"allModulesDescription": "Available modules",
|
||||
"noActiveModules": "No modules activated. Ask your administrator to enable modules.",
|
||||
"accessDenied": {
|
||||
"title": "No Access to This Module",
|
||||
@@ -1194,7 +1194,7 @@
|
||||
},
|
||||
"marketplace": {
|
||||
"title": "Marketplace",
|
||||
"subtitle": "Discover and activate modules for your tenant",
|
||||
"subtitle": "Discover and activate modules",
|
||||
"activate": "Activate Module",
|
||||
"deactivate": "Deactivate",
|
||||
"searchPlaceholder": "Search modules...",
|
||||
@@ -1212,13 +1212,13 @@
|
||||
"toastActivateError": "Activation failed. Please try again.",
|
||||
"toastDeactivateError": "Deactivation failed. Please try again.",
|
||||
"deactivateDialogTitle": "Deactivate Module",
|
||||
"deactivateDialogBody": "Do you want to deactivate {moduleName} for this tenant? The module will be removed from the sidebar.",
|
||||
"deactivateDialogBody": "Do you want to deactivate {moduleName}? The module will be removed from the sidebar.",
|
||||
"deactivateDialogConfirm": "Deactivate",
|
||||
"deactivateDialogCancel": "Cancel",
|
||||
"tenantContextLabel": "Tenant Context",
|
||||
"tenantContextLabel": "Organization",
|
||||
"backToMarketplace": "Back to Marketplace",
|
||||
"detailVersion": "Version {version}",
|
||||
"detailStatusActive": "Activated for this tenant",
|
||||
"detailStatusActive": "Activated",
|
||||
"detailStatusInactive": "Not activated",
|
||||
"accessDenied": "Access denied",
|
||||
"statusNoAccess": "No Access",
|
||||
@@ -1528,7 +1528,7 @@
|
||||
"settings": {
|
||||
"title": "Tender Radar — Settings",
|
||||
"rssSectionTitle": "RSS Feeds",
|
||||
"rssSectionBody": "Public, platform-wide RSS sources (e.g. service.bund.de or a subreport-elvis municipal feed) — applies equally to all tenants, not configurable per tenant.",
|
||||
"rssSectionBody": "Public, platform-wide RSS sources (e.g. service.bund.de or a subreport-elvis municipal feed) — applies to everyone equally.",
|
||||
"rssSectionUserNote": "Add personal feeds under \"My sources\".",
|
||||
"accessDeniedText": "This page manages platform-wide settings and is reserved for administrators.",
|
||||
"digestIntervalLabel": "Digest Interval",
|
||||
|
||||
Reference in New Issue
Block a user