feat(api,web): eigene Module — Tabelle, API, Seitenleiste, Rahmen-Seite
- Tabelle CustomModule mit Zeilenschutz (tenant_isolation_policy), Migration 20260929120000 - API /custom-modules: Lesen für jeden Angemeldeten, Schreiben nur Administrator, nur https ohne Zugangsdaten - Seitenleiste zeigt eigene Module unter ihrer Kategorie, Rahmen-Seite mit Sandbox und „In neuem Tab öffnen“ - MODULE_CATEGORIES als gemeinsame Liste, Zugriffsklassifikation nachgemessen fortgeschrieben Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -1346,6 +1346,13 @@
|
||||
"close": "Fenster schließen",
|
||||
"contentLabel": "Änderungen"
|
||||
},
|
||||
"customModules": {
|
||||
"openInNewTab": "In neuem Tab öffnen",
|
||||
"embedHint": "Manche Seiten lassen sich nicht einbetten. Öffnen Sie die Seite dann in einem neuen Tab.",
|
||||
"notFound": "Dieses Modul gibt es nicht mehr.",
|
||||
"invalidUrl": "Die Adresse dieses Moduls ist keine gültige https-Adresse und wird deshalb nicht angezeigt.",
|
||||
"loading": "Wird geladen …"
|
||||
},
|
||||
"moduleCategories": {
|
||||
"domain-tools": "Domains",
|
||||
"security-tools": "Sicherheit",
|
||||
|
||||
@@ -1346,6 +1346,13 @@
|
||||
"close": "Close window",
|
||||
"contentLabel": "Changes"
|
||||
},
|
||||
"customModules": {
|
||||
"openInNewTab": "Open in new tab",
|
||||
"embedHint": "Some pages cannot be embedded. If this one stays blank, open it in a new tab.",
|
||||
"notFound": "This module no longer exists.",
|
||||
"invalidUrl": "This module's address is not a valid https address and is therefore not shown.",
|
||||
"loading": "Loading …"
|
||||
},
|
||||
"moduleCategories": {
|
||||
"domain-tools": "Domains",
|
||||
"security-tools": "Security",
|
||||
|
||||
@@ -0,0 +1,22 @@
|
||||
import { MODULE_CATEGORIES } from '@tessera/shared';
|
||||
import { describe, expect, it } from 'vitest';
|
||||
import de from './de.json';
|
||||
import en from './en.json';
|
||||
|
||||
/**
|
||||
* Gleichlauf der Modulkategorien (quick-260929-9wc): jede Kennung aus
|
||||
* `MODULE_CATEGORIES` (Auswahl im Formular „Eigene Module“, Pruefung in der
|
||||
* API) braucht einen Anzeigenamen in `moduleCategories` beider Sprachen —
|
||||
* sonst zeigte die Seitenleiste die rohe Kennung.
|
||||
*/
|
||||
describe('MODULE_CATEGORIES', () => {
|
||||
it.each([
|
||||
['de', de],
|
||||
['en', en],
|
||||
] as const)('hat je Kennung einen Schluessel in moduleCategories (%s)', (_lang, messages) => {
|
||||
const labels = messages.moduleCategories as Record<string, string>;
|
||||
for (const category of MODULE_CATEGORIES) {
|
||||
expect(labels[category], `moduleCategories.${category}`).toBeTruthy();
|
||||
}
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user