feat(10-01): serve the embedded admin SPA at backend.uri with cookie login
- backend.uri prefix (default /backend) mounts the admin API at {prefix}/api/v1
and the embedded SPA shell at {prefix} with an api/ JSON 404 fallback
- cookie transport: an X-Requested-With login sets the HttpOnly summer_admin
cookie and returns no token; the backend guard reads the cookie after Bearer
- CSRF wrapper refuses cookie-only POST/PUT/DELETE without X-Requested-With
- boardwalk package embeds boardwalk/dist, rewrites index.html once per prefix
and sets cache and security headers
- framework admin OpenAPI pipeline (swag, swagger2openapi, openapi-typescript)
with prefix-relative paths and typed envelopes for the tracer routes
- admin/ Vite SPA: login, plugin rail, section panel and read-only list
through the openapi-fetch client typed by the generated schema
This commit is contained in:
111
admin/src/app/icons.ts
Normal file
111
admin/src/app/icons.ts
Normal file
@@ -0,0 +1,111 @@
|
||||
// Navigation icons (D-11). The registry stores lucide names; ported Winter
|
||||
// plugins may still send icon-* names, which map onto lucide equivalents.
|
||||
// Named imports only: a namespace import would bundle every lucide icon.
|
||||
import type { Component } from 'vue'
|
||||
import {
|
||||
Archive,
|
||||
ArrowDown,
|
||||
ArrowLeft,
|
||||
ArrowRight,
|
||||
ArrowUp,
|
||||
ArrowUpRight,
|
||||
CassetteTape,
|
||||
Check,
|
||||
ChevronDown,
|
||||
ChevronLeft,
|
||||
ChevronRight,
|
||||
Circle,
|
||||
CircleAlert,
|
||||
Disc,
|
||||
Disc3,
|
||||
Image,
|
||||
Library,
|
||||
List,
|
||||
LogOut,
|
||||
MicVocal,
|
||||
Minus,
|
||||
Palette,
|
||||
PanelLeftClose,
|
||||
PanelLeftOpen,
|
||||
Plus,
|
||||
Puzzle,
|
||||
Search,
|
||||
SearchX,
|
||||
Settings,
|
||||
ShieldCheck,
|
||||
Square,
|
||||
Sun,
|
||||
Tags,
|
||||
Trash2,
|
||||
User,
|
||||
UserMinus,
|
||||
UserPlus,
|
||||
Users,
|
||||
UsersRound,
|
||||
X,
|
||||
} from '@lucide/vue'
|
||||
|
||||
export const icons: Readonly<Record<string, Component>> = {
|
||||
archive: Archive,
|
||||
'arrow-down': ArrowDown,
|
||||
'arrow-left': ArrowLeft,
|
||||
'arrow-right': ArrowRight,
|
||||
'arrow-up': ArrowUp,
|
||||
'arrow-up-right': ArrowUpRight,
|
||||
'cassette-tape': CassetteTape,
|
||||
check: Check,
|
||||
'chevron-down': ChevronDown,
|
||||
'chevron-left': ChevronLeft,
|
||||
'chevron-right': ChevronRight,
|
||||
circle: Circle,
|
||||
'circle-alert': CircleAlert,
|
||||
disc: Disc,
|
||||
'disc-3': Disc3,
|
||||
image: Image,
|
||||
library: Library,
|
||||
list: List,
|
||||
'log-out': LogOut,
|
||||
'mic-vocal': MicVocal,
|
||||
minus: Minus,
|
||||
palette: Palette,
|
||||
'panel-left-close': PanelLeftClose,
|
||||
'panel-left-open': PanelLeftOpen,
|
||||
plus: Plus,
|
||||
puzzle: Puzzle,
|
||||
search: Search,
|
||||
'search-x': SearchX,
|
||||
settings: Settings,
|
||||
'shield-check': ShieldCheck,
|
||||
sun: Sun,
|
||||
tags: Tags,
|
||||
'trash-2': Trash2,
|
||||
user: User,
|
||||
'user-minus': UserMinus,
|
||||
'user-plus': UserPlus,
|
||||
users: Users,
|
||||
'users-round': UsersRound,
|
||||
x: X,
|
||||
}
|
||||
|
||||
/** Winter backend icon classes mapped to lucide names. */
|
||||
export const winterIcons: Readonly<Record<string, string>> = {
|
||||
'icon-archive': 'archive',
|
||||
'icon-circle': 'circle',
|
||||
'icon-list-ul': 'list',
|
||||
'icon-tags': 'tags',
|
||||
'icon-user': 'user',
|
||||
'icon-search': 'search',
|
||||
'icon-cog': 'settings',
|
||||
'icon-users': 'users',
|
||||
}
|
||||
|
||||
/** Neutral icon for names neither lucide map knows. */
|
||||
export const fallbackIcon: Component = Square
|
||||
|
||||
export function iconFor(name: string | null | undefined): Component {
|
||||
if (!name) {
|
||||
return fallbackIcon
|
||||
}
|
||||
const key = name.trim()
|
||||
return icons[key] ?? icons[winterIcons[key] ?? ''] ?? fallbackIcon
|
||||
}
|
||||
Reference in New Issue
Block a user