feat(geschichten): frontend foundation — canBlogWrite, sanitize util, nav, i18n
- Derives canBlogWrite in +layout.server.ts the same way as canAnnotate. - Adds Geschichten link to AppNav (desktop + mobile, between Stammbaum and Admin). - Adds error_geschichte_not_found mapping to errors.ts and translation keys for the Geschichten index, detail, editor, and confirmation copy in de/en/es. - Adds isomorphic-dompurify-backed safeHtml() helper with allow-list matching the backend OWASP policy (p/br/strong/em/h2/h3/ul/ol/li), plus Vitest spec. - Updates legacy spec test data so the new required canBlogWrite layout prop type-checks. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
@@ -7,6 +7,7 @@ export const load: LayoutServerLoad = async ({ locals }) => {
|
||||
canWrite: groups.some((g) => g.permissions.includes('WRITE_ALL')),
|
||||
canAnnotate: groups.some(
|
||||
(g) => g.permissions.includes('WRITE_ALL') || g.permissions.includes('ANNOTATE_ALL')
|
||||
)
|
||||
),
|
||||
canBlogWrite: groups.some((g) => g.permissions.includes('BLOG_WRITE'))
|
||||
};
|
||||
};
|
||||
|
||||
@@ -68,6 +68,16 @@ function handleOverlayKeydown(event: KeyboardEvent) {
|
||||
>
|
||||
{m.nav_stammbaum()}
|
||||
</a>
|
||||
|
||||
<a
|
||||
href="/geschichten"
|
||||
class="my-2 inline-flex items-center px-3 font-sans text-xs font-bold tracking-widest uppercase transition-colors focus:outline-none focus-visible:rounded focus-visible:ring-2 focus-visible:ring-focus-ring
|
||||
{page.url.pathname.startsWith('/geschichten')
|
||||
? 'border-b-2 border-accent text-white'
|
||||
: 'text-white/70 hover:text-white'}"
|
||||
>
|
||||
{m.nav_geschichten()}
|
||||
</a>
|
||||
{#if isAdmin}
|
||||
<a
|
||||
href="/admin"
|
||||
@@ -170,6 +180,16 @@ function handleOverlayKeydown(event: KeyboardEvent) {
|
||||
{m.nav_stammbaum()}
|
||||
</a>
|
||||
|
||||
<a
|
||||
href="/geschichten"
|
||||
class="block flex min-h-[44px] w-full items-center px-4 py-3 font-sans text-sm font-bold tracking-widest uppercase transition-colors focus:outline-none focus-visible:ring-2 focus-visible:ring-focus-ring focus-visible:ring-inset
|
||||
{page.url.pathname.startsWith('/geschichten')
|
||||
? 'bg-accent-bg text-ink'
|
||||
: 'text-ink-2 hover:bg-muted hover:text-ink'}"
|
||||
>
|
||||
{m.nav_geschichten()}
|
||||
</a>
|
||||
|
||||
{#if isAdmin}
|
||||
<a
|
||||
href="/admin"
|
||||
|
||||
@@ -41,6 +41,7 @@ const baseData = {
|
||||
user: undefined,
|
||||
canWrite: true,
|
||||
canAnnotate: false,
|
||||
canBlogWrite: false,
|
||||
editUser: makeUser(),
|
||||
groups
|
||||
};
|
||||
|
||||
@@ -10,7 +10,13 @@ const groups = [
|
||||
{ id: 'g2', name: 'Admins', permissions: ['ADMIN'] }
|
||||
];
|
||||
|
||||
const baseData = { user: undefined, canWrite: true, canAnnotate: false, groups };
|
||||
const baseData = {
|
||||
user: undefined,
|
||||
canWrite: true,
|
||||
canAnnotate: false,
|
||||
canBlogWrite: false,
|
||||
groups
|
||||
};
|
||||
|
||||
afterEach(cleanup);
|
||||
|
||||
|
||||
@@ -13,6 +13,7 @@ const baseData = {
|
||||
user: undefined,
|
||||
canWrite: true,
|
||||
canAnnotate: false,
|
||||
canBlogWrite: false,
|
||||
documents: [],
|
||||
initialValues: { senderName: '', receiverName: '' },
|
||||
filters: { senderId: '', receiverId: '', from: '', to: '', dir: 'DESC' as const }
|
||||
|
||||
@@ -11,6 +11,7 @@ const baseData = {
|
||||
user: undefined,
|
||||
canWrite: true,
|
||||
canAnnotate: false,
|
||||
canBlogWrite: false,
|
||||
persons: [],
|
||||
initialSenderId: '',
|
||||
initialSenderName: '',
|
||||
|
||||
@@ -25,6 +25,7 @@ const makeData = (overrides = {}) => ({
|
||||
},
|
||||
canWrite: true,
|
||||
canAnnotate: false,
|
||||
canBlogWrite: false,
|
||||
...overrides
|
||||
});
|
||||
|
||||
|
||||
@@ -22,6 +22,7 @@ const baseData = {
|
||||
} as User,
|
||||
canWrite: true,
|
||||
canAnnotate: false,
|
||||
canBlogWrite: false,
|
||||
resumeDoc: null,
|
||||
pulse: null,
|
||||
activityFeed: [],
|
||||
|
||||
@@ -21,6 +21,7 @@ const emptyData = {
|
||||
user: undefined,
|
||||
canWrite: true,
|
||||
canAnnotate: false,
|
||||
canBlogWrite: false,
|
||||
q: '',
|
||||
persons: [],
|
||||
stats: defaultStats
|
||||
|
||||
Reference in New Issue
Block a user