services/config/config-schema.jsjavascript
/**
* Declares every kiosk/device config value the app understands. Values come
* from URL params (source "param", read live by useConfig in config.jsx and
* kept alive across navigation), each with type, default and a German
* description shown in admin/debug contexts.
*
* @type {Array<{key: string, source: string, name: string, type: string, default: *, min: number, description: string}>}
*/
export const CONFIG_SCHEMA = [
// --- Stage (whole-app scale wrapper, src/components/Stage/Stage.jsx) ---
// The authored reference resolution every page's CSS is designed against -
// always the largest size for the CURRENT physical device/orientation
// combination, so real screens only ever scale the whole app *down*,
// never up (upscaling would blur the WebGL globe, see
// InteractiveGlobe.jsx). Two independent axes, not one: `stageDevice`
// picks which physical kiosk this is (each has its OWN landscape
// width/height, since a 4K panel and an iPad's CSS point resolution are
// very different - the iPad is a 2x Retina display, so its CSS points are
// roughly half its physical pixel count), and orientation (from
// PRESENTATION_MODES, see Stage.jsx) swaps that device's own pair for
// portrait routes - i.e. "the same panel, physically rotated" is still
// true WITHIN one device, just not across devices. Getting this wrong
// (treating "portrait" as one single cross-device resolution) is exactly
// what caused Rad Enablement to letterbox on the iPad but would upscale/
// blur on a rotated 4K panel - see README.md's "Scaling (Stage)" section.
// Exposed as params (not only hardcoded) so a different reference size
// can be tested/tuned on a real kiosk without a rebuild.
{
key: "stageDevice",
source: "param",
name: "stageDevice",
type: "string",
default: "4k",
description:
"Welches physische Kiosk-Gerät das hier ist ('4k' oder 'ipad', siehe stageRefWidth/Height vs. stageIpadRefWidth/Height) - bestimmt, welches Referenzauflösungs-Paar Stage.jsx verwendet.",
},
{
key: "stageRefWidth",
source: "param",
name: "stageRefWidth",
type: "number",
default: 3840,
min: 1,
description:
"Referenzbreite in px, auf die die gesamte App im Landscape entworfen ist (stageDevice='4k', Stage.jsx).",
},
{
key: "stageRefHeight",
source: "param",
name: "stageRefHeight",
type: "number",
default: 2160,
min: 1,
description:
"Referenzhöhe in px, auf die die gesamte App im Landscape entworfen ist (stageDevice='4k', Stage.jsx).",
},
{
key: "stageIpadRefWidth",
source: "param",
name: "stageIpadRefWidth",
type: "number",
default: 1366,
min: 1,
description:
"Referenzbreite in px im Landscape für stageDevice='ipad' (Stage.jsx) - Standard entspricht der CSS-Punktbreite eines 13\" iPad.",
},
{
key: "stageIpadRefHeight",
source: "param",
name: "stageIpadRefHeight",
type: "number",
default: 1024,
min: 1,
description:
"Referenzhöhe in px im Landscape für stageDevice='ipad' (Stage.jsx) - Standard entspricht der CSS-Punkthöhe eines 13\" iPad.",
},
// --- Genereic Settings (src/services/config/config.jsx) ---
{
key: "screensaverTimeout",
source: "param",
name: "screensaverTimeout",
type: "number",
default: 360,
min: 0,
description: "Sekunden ohne Interaktion, bevor der Screensaver startet.",
},
{
key: "screensaverFadeDuration",
source: "param",
name: "screensaverFadeDuration",
type: "number",
default: 1000,
min: 0,
description: "Dauer der Ein-/Ausblendanimation des Screensavers in Millisekunden.",
},
{
key: "defaultMode",
source: "param",
name: "defaultMode",
type: "string",
default: "default",
description:
'Wählt, welcher Screensaver (content.screensavers, siehe Screensaver.jsx) beim Leerlauf gezeigt wird - einer der Modus-Keys aus src/services/presentationModes.js (z.B. "value-partnership").',
},
{
key: "contentFile",
source: "param",
name: "contentFile",
type: "string",
default: null,
description:
"Erzwingt einen bestimmten Pfad zur content.json (statt der Datei, die ContentProvider anhand der aktuellen Route lädt, siehe src/services/presentationModes.js).",
},
{
key: "disableAnimations",
source: "param",
name: "disableAnimations",
type: "boolean",
default: false,
description: "Deaktiviert alle Background Animationen, wenn auf true gesetzt.",
},
// --- Value Partnership globe (InteractiveGlobe.jsx/GlobePage.jsx) -------
// Nur einfache Werte (Zahl/String) - komplexe/strukturierte Defaults
// (Filter-Startzustand, Marker-Icon-Pfade, Tab-Kategorien, Länder-Namens-
// Aliase) liegen stattdessen in globeDefaults.js, da sie sich nicht
// sinnvoll als URL-Parameter abbilden lassen.
{
key: "globeOceanColor",
source: "param",
name: "globeOceanColor",
type: "string",
default: "#000000",
description: "Farbe der Basiskugel (Ozean-Fläche zwischen den Länder-Polygonen).",
},
{
key: "globeLandStrokeColor",
source: "param",
name: "globeLandStrokeColor",
type: "string",
default: "rgba(255, 255, 255, 0.0)",
description: "Farbe der Ländergrenz-Linien auf dem Globus.",
},
{
key: "globePolygonSideColor",
source: "param",
name: "globePolygonSideColor",
type: "string",
default: "rgba(0, 0, 0, 0.6)",
description: "Farbe der seitlichen 'Wände' der erhöhten Länder-Polygone.",
},
{
key: "globeAtmosphereColor",
source: "param",
name: "globeAtmosphereColor",
type: "string",
default: "#ffffff",
description: "Farbe des Atmosphären-Leuchtens am Kugelrand.",
},
{
key: "globeFallbackCountryColor",
source: "param",
name: "globeFallbackCountryColor",
type: "string",
default: "#424242",
description:
"Länderfarbe, solange value-partnership-globe-countries.json noch nicht geladen ist (oder keine 'normal'-Farbe definiert).",
},
{
key: "globeAtmosphereAltitude",
source: "param",
name: "globeAtmosphereAltitude",
type: "number",
default: 0.15,
min: 0,
description: "Höhe des Atmosphären-Leuchtens relativ zum Kugelradius.",
},
{
key: "globePolygonAltitude",
source: "param",
name: "globePolygonAltitude",
type: "number",
default: 0.006,
min: 0,
description:
"Höhe, in der die Länder-Polygone über der Basiskugel schweben (relativ zum Kugelradius).",
},
{
key: "globeMinZoomAltitude",
source: "param",
name: "globeMinZoomAltitude",
type: "number",
default: 0.1,
min: 0,
description:
"Nächste Kamera-Distanz beim Hineinzoomen (relativ zum Kugelradius) - verhindert, dass die Kamera zwischen die erhöhten Länder-Polygone gerät (siehe InteractiveGlobe.jsx).",
},
// not currently read anywhere (InteractiveGlobe.jsx sets no initial camera
// altitude of its own, react-globe.gl's own default applies instead) -
// kept here as a declared-but-inert value rather than removed, since the
// description below still describes the intended behavior
{
key: "globeMaxZoomAltitude",
source: "param",
name: "globeMaxZoomAltitude",
type: "number",
default: 2.5,
min: 0,
description: "Kamera-Starthöhe beim Laden des Globus (relativ zum Kugelradius).",
},
{
key: "globePolygonsTransitionDurationMs",
source: "param",
name: "globePolygonsTransitionDurationMs",
type: "number",
default: 200,
min: 0,
description:
"Dauer der Farbüberblendung, wenn sich die Länder-Einfärbung ändert, in Millisekunden.",
},
{
key: "globeZoomTransitionDurationMs",
source: "param",
name: "globeZoomTransitionDurationMs",
type: "number",
default: 1000,
min: 0,
description:
"Dauer der Kamera-Zoomanimation beim Anklicken eines Markers oder Clusters, in Millisekunden.",
},
{
key: "globeFocusZoomAltitude",
source: "param",
name: "globeFocusZoomAltitude",
type: "number",
default: 0.5,
min: 0,
description:
"Kamerahöhe, auf die beim Anklicken eines einzelnen Markers gezoomt wird (relativ zum Kugelradius).",
},
{
key: "globeAutoRotateSpeed",
source: "param",
name: "globeAutoRotateSpeed",
type: "number",
default: 1.0,
min: 0,
description: "Rotationsgeschwindigkeit des automatischen Drehens im Leerlauf.",
},
{
key: "globeMarkerWidth",
source: "param",
name: "globeMarkerWidth",
type: "number",
default: 75,
min: 1,
description:
"Breite der Marker-Pins in Pixeln (Höhe ergibt sich aus dem Seitenverhältnis der Pin-Grafik).",
},
{
key: "globeAutoRotateIdleMs",
source: "param",
name: "globeAutoRotateIdleMs",
type: "number",
default: 120000,
min: 0,
description:
"Leerlaufzeit ohne Interaktion mit dem Globus, bevor die automatische Rotation einsetzt, in Millisekunden.",
},
];