Template
deploy to production / deploy (push) Successful in 43s
- yaml-language-server-Schema direkt in jeder api-YAML statt .vscode/yaml.schemas-Mapping (exakter pro Datei, kein Glob-Rätsel) - erweiterte meta.agent-Doku in den Collections - tibi-types-Submodul auf 4c55f82 (meta.agent- + meta.query-Schemas)
151 lines
4.3 KiB
YAML
151 lines
4.3 KiB
YAML
# yaml-language-server: $schema=../../tibi-types/schemas/config/collection.schema.json
|
||
########################################################################
|
||
# Media library — reusable uploaded assets referenced via foreignMedia
|
||
########################################################################
|
||
|
||
name: medialib
|
||
uploadPath: ../media/medialib
|
||
audit:
|
||
enabled: true
|
||
meta:
|
||
label: { de: "Mediathek", en: "Media Library" }
|
||
muiIcon: folder-multiple-image
|
||
group: content
|
||
imageUrl: "https://images.unsplash.com/photo-1452587925148-ce544e77e70d?auto=format&fit=crop&q=80&w=800"
|
||
viewHint:
|
||
media:
|
||
ai:
|
||
targetField: alt
|
||
prompt: Beschreibe das Bild kurz und sachlich fuer einen barrierefreien Alt-Text.
|
||
image:
|
||
maxWidth: 1280
|
||
maxHeight: 1280
|
||
quality: 0.82
|
||
upload:
|
||
autoFill:
|
||
file: file
|
||
preview:
|
||
label: title
|
||
secondary: tags
|
||
tertiary: description
|
||
image: file
|
||
mediaFile: file
|
||
subNavigation:
|
||
- name: images
|
||
label: { de: "Bilder", en: "Images" }
|
||
muiIcon: image
|
||
filter:
|
||
file.type_like: ^image/
|
||
- name: documents
|
||
label: { de: "Dokumente", en: "Documents" }
|
||
muiIcon: file_document
|
||
filter:
|
||
file.type_like: ^(?!image/|video/|audio/).+
|
||
agent:
|
||
purpose: "Reusable uploads referenced via foreignMedia (blocks.heroImage.image, blocks.image)."
|
||
instructions: "Upload file as object {src:'data:<mime>;base64,...', path:'name.jpg'} (path optional). Stored as {src:'<field>/name.jpg', path, type}. Never {filename,data}, never file as plain string. Public read URL: /api/medialib/<entryId>/<src> plus ?filter=l-webp for raster images. downscale max 2048px applies on upload. GOTCHA 2026-10-05: filter_public.js forces active:true on anonymous reads although this schema declares no active field – without stored active:true every medialib lookup stays unresolved publicly (plain IDs, no _lookup, HeroBlock renders gradient fallback and Richtext images vanish) although PAT reads succeed. Always store active:true on every medialib doc."
|
||
fieldHints:
|
||
file: "required, widget file, max 50MB"
|
||
alt: "object {de,en}, used by MedialibImage for accessibility"
|
||
examples: [{ title: "Demo Hero 1200", file: { src: "data:image/jpeg;base64,...", path: "demo-hero-1200.jpg" }, active: true }]
|
||
hints: ["list with select excluding file.data to avoid context bloat", "verify file.src starts with <field>/ after create", "missing active:true => public lookups unresolved (verified incident 2026-10-05)"]
|
||
|
||
permissions:
|
||
public:
|
||
methods:
|
||
get: true
|
||
user:
|
||
methods:
|
||
get: true
|
||
post: true
|
||
put: true
|
||
delete: true
|
||
"token:${ADMIN_TOKEN}":
|
||
methods:
|
||
get: true
|
||
post: true
|
||
put: true
|
||
delete: true
|
||
|
||
imageFilter: !include lib/imageFilter.yml
|
||
|
||
hooks:
|
||
get:
|
||
read:
|
||
type: javascript
|
||
file: hooks/filter_public.js
|
||
post:
|
||
return:
|
||
type: javascript
|
||
file: hooks/clear_cache.js
|
||
put:
|
||
return:
|
||
type: javascript
|
||
file: hooks/clear_cache.js
|
||
delete:
|
||
return:
|
||
type: javascript
|
||
file: hooks/clear_cache.js
|
||
|
||
search:
|
||
- name: default
|
||
mode: regex
|
||
fields: [title, "alt.de", "alt.en", description]
|
||
|
||
fields:
|
||
- name: file
|
||
type: file
|
||
validator:
|
||
required: true
|
||
maxFileSize: "50MB"
|
||
meta:
|
||
label: { de: "Datei", en: "File" }
|
||
widget: file
|
||
downscale:
|
||
maxWidth: 2048
|
||
maxHeight: 2048
|
||
- name: title
|
||
type: string
|
||
validator:
|
||
maxLength: 255
|
||
meta:
|
||
label: { de: "Titel", en: "Title" }
|
||
- name: alt
|
||
type: object
|
||
meta:
|
||
label: { de: "Alt-Text", en: "Alt Text" }
|
||
subFields:
|
||
- name: de
|
||
type: string
|
||
validator:
|
||
maxLength: 500
|
||
meta:
|
||
label: Deutsch
|
||
- name: en
|
||
type: string
|
||
validator:
|
||
maxLength: 500
|
||
meta:
|
||
label: English
|
||
- name: description
|
||
type: string
|
||
validator:
|
||
maxLength: 2000
|
||
meta:
|
||
label: { de: "Beschreibung", en: "Description" }
|
||
widget: text
|
||
inputProps:
|
||
multiline: true
|
||
rows: 4
|
||
- name: tags
|
||
type: string[]
|
||
meta:
|
||
label: { de: "Schlagwörter", en: "Tags" }
|
||
widget: foreignKey
|
||
foreign:
|
||
collection: tag
|
||
- name: _testdata
|
||
type: boolean
|
||
meta:
|
||
hide: true
|