Files
Sitzplatzbuchungstool/pages/Sitzplätze/widgets/SeatCalendar/Custom5.json
T
2026-08-14 10:11:13 +00:00

72 lines
19 KiB
JSON
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
{
"backgroundColor": "#FFFFFF",
"borderColor": "#E0DEDE",
"borderRadius": "{{appsmith.theme.borderRadius.appBorderRadius}}",
"borderWidth": "1",
"bottomRow": 69,
"boxShadow": "{{appsmith.theme.boxShadow.appBoxShadow}}",
"defaultModel": "{{\n {\n events: GetBookings.data || [],\n seatId: appsmith.store.selectedSeatId,\n seatName: appsmith.store.selectedSeatName\n }\n}}",
"dynamicBindingPathList": [
{
"key": "theme"
},
{
"key": "borderRadius"
},
{
"key": "boxShadow"
},
{
"key": "defaultModel"
}
],
"dynamicHeight": "FIXED",
"dynamicPropertyPathList": [
{
"key": "seatSelected"
}
],
"dynamicTriggerPathList": [
{
"key": "seatSelected"
}
],
"events": [
"seatSelected"
],
"isCanvas": false,
"isLoading": false,
"isSearchWildcard": true,
"isVisible": true,
"key": "3r58ovsolf",
"leftColumn": 0,
"maxDynamicHeight": 9000,
"minDynamicHeight": 4,
"mobileBottomRow": 40,
"mobileLeftColumn": 3,
"mobileRightColumn": 26,
"mobileTopRow": 10,
"needsErrorInfo": false,
"parentColumnSpace": 7.40625,
"parentId": "ekq4ry46pv",
"parentRowSpace": 10,
"renderMode": "CANVAS",
"rightColumn": 63,
"seatSelected": "{{\n storeValue(\n \"selectedSeatId\",\n Custom4.model.selectedSeat.id\n )\n .then(() =>\n storeValue(\n \"selectedSeatName\",\n Custom4.model.selectedSeat.name\n )\n )\n .then(() => GetBookings.run())\n .then(() => showModal(SeatCalendar.name))\n}}",
"srcDoc": {
"css": "@charset \"UTF-8\";\nhtml,\nbody {\n margin: 0;\n padding: 0;\n width: 100%;\n min-height: 100%;\n font-family: Arial, sans-serif;\n overflow: hidden;\n}\n\n/* Äußerer Custom-Widget-Bereich */\n#calendarWrapper {\n width: 100%;\n min-height: 0;\n box-sizing: border-box;\n padding: 10px;\n background: #ffffff;\n overflow: visible;\n}\n\n/* Kopfbereich */\n#calendarHeader {\n display: flex;\n align-items: center;\n justify-content: space-between;\n gap: 12px;\n margin-bottom: 10px;\n padding: 8px 10px;\n border: 1px solid #d1d5db;\n border-radius: 6px;\n background: #f9fafb;\n}\n\n#calendarSeatTitle {\n font-size: 15px;\n font-weight: 600;\n color: #374151;\n}\n\n/* Kalender */\n#calendar {\n width: 100%;\n min-height: 0;\n box-sizing: border-box;\n}\n\n/* Auswahltext */\n#calendarSelection {\n margin-top: 10px;\n padding: 8px 10px;\n border: 1px solid #d1d5db;\n border-radius: 5px;\n background: #f9fafb;\n color: #374151;\n font-size: 13px;\n}\n\n/* FullCalendar-Grundformatierung */\n.fc {\n width: 100%;\n font-size: 13px;\n}\n\n.fc .fc-button {\n background: #374151;\n border-color: #374151;\n}\n\n.fc .fc-button:hover,\n.fc .fc-button-active {\n background: #111827;\n border-color: #111827;\n}\n\n.fc .fc-daygrid-day.fc-day-today,\n.fc .fc-timegrid-col.fc-day-today {\n background: #eff6ff;\n}\n\n.fc .fc-event {\n cursor: pointer;\n}\n\n/* Wochenenden grau */\n#calendar td.fc-day-sat,\n#calendar td.fc-day-sun,\n#calendar .fc-timegrid-col.fc-day-sat,\n#calendar .fc-timegrid-col.fc-day-sun {\n background-color: #eeeeee !important;\n}\n\n/* Wochenend-Kopfzellen */\n#calendar .fc-col-header-cell.fc-day-sat,\n#calendar .fc-col-header-cell.fc-day-sun {\n background-color: #d6d6d6 !important;\n}\n\n/*\n * Monatsansicht:\n * kein Scrollen innerhalb des Monats.\n */\n#calendar .fc-daygrid .fc-scroller {\n height: auto !important;\n max-height: none !important;\n overflow-y: visible !important;\n overflow-x: visible !important;\n}\n\n/*\n * Tagesansicht:\n * nur der Zeitbereich scrollt.\n */\n#calendar .fc-timegrid .fc-scroller {\n overflow-y: auto !important;\n overflow-x: hidden !important;\n overscroll-behavior: contain;\n}\n\n/*\n * Verhindert Scroll-Chaining vom TimeGrid\n * in das übergeordnete Appsmith-Widget.\n */\n#calendar .fc-timegrid {\n min-height: 0;\n}\n\n#calendar .fc-timegrid .fc-view-harness {\n min-height: 0;\n}\n\n/*\n * Tabellenbreite stabil halten.\n */\n#calendar .fc-scrollgrid {\n width: 100%;\n max-width: 100%;\n}",
"html": "<div id=\"calendarWrapper\">\n <div id=\"calendarHeader\">\n <div id=\"calendarSeatTitle\">\n Kalender\n </div>\n </div>\n\n <div id=\"calendar\"></div>\n\n <script src=\"https://cdn.jsdelivr.net/npm/[email protected]/index.global.min.js\"></script>\n</div>",
"js": "let calendar = null;\nlet resizeTimer = null;\nconst MONTH_HEIGHT = 620;\nconst MONTH_CONTENT_HEIGHT = 550;\nconst DAY_HEIGHT = 650;\nconst DAY_CONTENT_HEIGHT = 570;\nfunction getModel() {\n const model = appsmith.model || {};\n if (typeof model === \"string\") {\n try {\n return JSON.parse(model);\n } catch (error) {\n return {};\n }\n }\n return model;\n}\nfunction getEvents() {\n const model = getModel();\n return Array.isArray(model.events) ? model.events : [];\n}\nfunction getSeatName() {\n const model = getModel();\n return model.seatName || model.seatId || \"kein Platz ausgewählt\";\n}\nfunction updateSeatTitle() {\n const titleElement = document.getElementById(\"calendarSeatTitle\");\n if (!titleElement) {\n return;\n }\n titleElement.textContent = `Kalender für ${getSeatName()}`;\n}\nfunction updateSelectionText(text) {\n const selectionElement = document.getElementById(\"calendarSelection\");\n if (!selectionElement) {\n return;\n }\n selectionElement.textContent = text;\n}\nfunction updateCalendarViewSettings(viewType) {\n if (!calendar) {\n return;\n }\n if (viewType === \"timeGridDay\") {\n /*\n * Tagesansicht:\n * Feste Kalenderhöhe und fester scrollbarer\n * Inhaltsbereich.\n */\n calendar.setOption(\"height\", DAY_HEIGHT);\n calendar.setOption(\"contentHeight\", DAY_CONTENT_HEIGHT);\n calendar.setOption(\"expandRows\", false);\n } else {\n /*\n * Monatsansicht:\n * Einmalig größer setzen.\n */\n calendar.setOption(\"height\", MONTH_HEIGHT);\n calendar.setOption(\"contentHeight\", MONTH_CONTENT_HEIGHT);\n calendar.setOption(\"expandRows\", true);\n }\n if (typeof calendar.updateSize === \"function\") {\n calendar.updateSize();\n }\n}\nfunction scheduleResize() {\n window.clearTimeout(resizeTimer);\n resizeTimer = window.setTimeout(() => {\n if (!calendar) {\n return;\n }\n\n /*\n * Nur bei echter Browser-/Widget-Größenänderung\n * neu berechnen.\n */\n calendar.updateSize();\n }, 250);\n}\nfunction isWeekend(date) {\n const day = date.getDay();\n return day === 0 || day === 6;\n}\nfunction showWeekendMessage() {\n updateSelectionText(\"Samstag und Sonntag sind nicht buchbar.\");\n}\nfunction openDayView(date) {\n if (!calendar) {\n return;\n }\n if (isWeekend(date)) {\n showWeekendMessage();\n return;\n }\n calendar.changeView(\"timeGridDay\", date);\n}\nfunction createCalendar() {\n const calendarElement = document.getElementById(\"calendar\");\n if (!calendarElement) {\n return;\n }\n if (typeof FullCalendar === \"undefined\") {\n calendarElement.textContent = \"FullCalendar konnte nicht geladen werden.\";\n return;\n }\n if (calendar) {\n calendar.destroy();\n calendar = null;\n }\n calendar = new FullCalendar.Calendar(calendarElement, {\n initialView: \"dayGridMonth\",\n locale: \"de\",\n firstDay: 1,\n navLinks: true,\n navLinkDayClick(date) {\n openDayView(date);\n },\n dateClick(info) {\n if (info.view.type !== \"dayGridMonth\") {\n return;\n }\n openDayView(info.date);\n },\n selectable: false,\n editable: false,\n eventStartEditable: false,\n eventDurationEditable: false,\n /*\n * Startwerte für die Monatsansicht.\n */\n height: MONTH_HEIGHT,\n contentHeight: MONTH_CONTENT_HEIGHT,\n expandRows: true,\n headerToolbar: {\n left: \"prev,next today\",\n center: \"title\",\n right: \"dayGridMonth,timeGridDay\"\n },\n buttonText: {\n today: \"Heute\",\n month: \"Monat\",\n day: \"Tag\"\n },\n /*\n * Zeitraster der Tagesansicht.\n */\n slotDuration: \"00:30:00\",\n snapDuration: \"00:30:00\",\n slotMinTime: \"07:00:00\",\n slotMaxTime: \"20:00:00\",\n scrollTime: \"08:00:00\",\n /*\n * Verhindert das erneute Springen beim\n * erneuten Setzen eines Datumsbereichs.\n */\n scrollTimeReset: false,\n allDaySlot: false,\n nowIndicator: true,\n events: getEvents(),\n datesSet(info) {\n updateCalendarViewSettings(info.view.type);\n },\n eventClick(info) {\n const event = info.event;\n const start = event.start ? formatDateTime(event.start) : \"\";\n const end = event.end ? formatDateTime(event.end) : \"\";\n const rangeText = end ? `${start} bis ${end}` : start;\n updateSelectionText(`${event.title || \"Buchung\"} ${rangeText}`);\n }\n });\n calendar.render();\n\n /*\n * Nach dem ersten Rendern nur die aktuelle\n * Ansicht anwenden.\n */\n updateCalendarViewSettings(calendar.view.type);\n}\nfunction formatDateTime(date) {\n if (!date) {\n return \"\";\n }\n return new Intl.DateTimeFormat(\"de-DE\", {\n dateStyle: \"short\",\n timeStyle: \"short\"\n }).format(date);\n}\nfunction refreshCalendarEvents() {\n if (!calendar) {\n createCalendar();\n return;\n }\n calendar.removeAllEvents();\n calendar.addEventSource(getEvents());\n\n /*\n * Keine neue Höhe setzen und keine Ansicht\n * neu aufbauen.\n */\n calendar.updateSize();\n}\nfunction registerResizeHandling() {\n window.addEventListener(\"resize\", scheduleResize);\n}\nappsmith.onReady(() => {\n updateSeatTitle();\n createCalendar();\n registerResizeHandling();\n appsmith.onModelChange(() => {\n updateSeatTitle();\n refreshCalendarEvents();\n });\n});"
},
"theme": "{{appsmith.theme}}",
"topRow": 0,
"type": "CUSTOM_WIDGET",
"uncompiledSrcDoc": {
"css": "html,\nbody {\n margin: 0;\n padding: 0;\n width: 100%;\n min-height: 100%;\n font-family: Arial, sans-serif;\n overflow: hidden;\n}\n\n/* Äußerer Custom-Widget-Bereich */\n\n#calendarWrapper {\n width: 100%;\n min-height: 0;\n box-sizing: border-box;\n padding: 10px;\n background: #ffffff;\n overflow: visible;\n}\n\n/* Kopfbereich */\n\n#calendarHeader {\n display: flex;\n align-items: center;\n justify-content: space-between;\n gap: 12px;\n margin-bottom: 10px;\n padding: 8px 10px;\n border: 1px solid #d1d5db;\n border-radius: 6px;\n background: #f9fafb;\n}\n\n#calendarSeatTitle {\n font-size: 15px;\n font-weight: 600;\n color: #374151;\n}\n\n/* Kalender */\n\n#calendar {\n width: 100%;\n min-height: 0;\n box-sizing: border-box;\n}\n\n/* Auswahltext */\n\n#calendarSelection {\n margin-top: 10px;\n padding: 8px 10px;\n border: 1px solid #d1d5db;\n border-radius: 5px;\n background: #f9fafb;\n color: #374151;\n font-size: 13px;\n}\n\n/* FullCalendar-Grundformatierung */\n\n.fc {\n width: 100%;\n font-size: 13px;\n}\n\n.fc .fc-button {\n background: #374151;\n border-color: #374151;\n}\n\n.fc .fc-button:hover,\n.fc .fc-button-active {\n background: #111827;\n border-color: #111827;\n}\n\n.fc .fc-daygrid-day.fc-day-today,\n.fc .fc-timegrid-col.fc-day-today {\n background: #eff6ff;\n}\n\n.fc .fc-event {\n cursor: pointer;\n}\n\n/* Wochenenden grau */\n\n#calendar td.fc-day-sat,\n#calendar td.fc-day-sun,\n#calendar .fc-timegrid-col.fc-day-sat,\n#calendar .fc-timegrid-col.fc-day-sun {\n background-color: #eeeeee !important;\n}\n\n/* Wochenend-Kopfzellen */\n\n#calendar .fc-col-header-cell.fc-day-sat,\n#calendar .fc-col-header-cell.fc-day-sun {\n background-color: #d6d6d6 !important;\n}\n\n/*\n * Monatsansicht:\n * kein Scrollen innerhalb des Monats.\n */\n#calendar .fc-daygrid .fc-scroller {\n height: auto !important;\n max-height: none !important;\n overflow-y: visible !important;\n overflow-x: visible !important;\n}\n\n/*\n * Tagesansicht:\n * nur der Zeitbereich scrollt.\n */\n#calendar .fc-timegrid .fc-scroller {\n overflow-y: auto !important;\n overflow-x: hidden !important;\n overscroll-behavior: contain;\n}\n\n/*\n * Verhindert Scroll-Chaining vom TimeGrid\n * in das übergeordnete Appsmith-Widget.\n */\n#calendar .fc-timegrid {\n min-height: 0;\n}\n\n#calendar .fc-timegrid .fc-view-harness {\n min-height: 0;\n}\n\n/*\n * Tabellenbreite stabil halten.\n */\n#calendar .fc-scrollgrid {\n width: 100%;\n max-width: 100%;\n}",
"html": "<div id=\"calendarWrapper\">\n <div id=\"calendarHeader\">\n <div id=\"calendarSeatTitle\">\n Kalender\n </div>\n </div>\n\n <div id=\"calendar\"></div>\n\n <script src=\"https://cdn.jsdelivr.net/npm/[email protected]/index.global.min.js\"></script>\n</div>",
"js": "let calendar = null;\nlet resizeTimer = null;\n\nconst MONTH_HEIGHT = 620;\nconst MONTH_CONTENT_HEIGHT = 550;\n\nconst DAY_HEIGHT = 650;\nconst DAY_CONTENT_HEIGHT = 570;\n\nfunction getModel() {\n const model = appsmith.model || {};\n\n if (typeof model === \"string\") {\n try {\n return JSON.parse(model);\n } catch (error) {\n return {};\n }\n }\n\n return model;\n}\n\nfunction getEvents() {\n const model = getModel();\n\n return Array.isArray(model.events)\n ? model.events\n : [];\n}\n\nfunction getSeatName() {\n const model = getModel();\n\n return model.seatName ||\n model.seatId ||\n \"kein Platz ausgewählt\";\n}\n\nfunction updateSeatTitle() {\n const titleElement =\n document.getElementById(\"calendarSeatTitle\");\n\n if (!titleElement) {\n return;\n }\n\n titleElement.textContent =\n `Kalender für ${getSeatName()}`;\n}\n\nfunction updateSelectionText(text) {\n const selectionElement =\n document.getElementById(\"calendarSelection\");\n\n if (!selectionElement) {\n return;\n }\n\n selectionElement.textContent = text;\n}\n\nfunction updateCalendarViewSettings(viewType) {\n if (!calendar) {\n return;\n }\n\n if (viewType === \"timeGridDay\") {\n /*\n * Tagesansicht:\n * Feste Kalenderhöhe und fester scrollbarer\n * Inhaltsbereich.\n */\n calendar.setOption(\n \"height\",\n DAY_HEIGHT\n );\n\n calendar.setOption(\n \"contentHeight\",\n DAY_CONTENT_HEIGHT\n );\n\n calendar.setOption(\n \"expandRows\",\n false\n );\n } else {\n /*\n * Monatsansicht:\n * Einmalig größer setzen.\n */\n calendar.setOption(\n \"height\",\n MONTH_HEIGHT\n );\n\n calendar.setOption(\n \"contentHeight\",\n MONTH_CONTENT_HEIGHT\n );\n\n calendar.setOption(\n \"expandRows\",\n true\n );\n }\n\n if (typeof calendar.updateSize === \"function\") {\n calendar.updateSize();\n }\n}\n\nfunction scheduleResize() {\n window.clearTimeout(resizeTimer);\n\n resizeTimer = window.setTimeout(() => {\n if (!calendar) {\n return;\n }\n\n /*\n * Nur bei echter Browser-/Widget-Größenänderung\n * neu berechnen.\n */\n calendar.updateSize();\n }, 250);\n}\n\nfunction isWeekend(date) {\n const day =\n date.getDay();\n\n return day === 0 || day === 6;\n}\n\nfunction showWeekendMessage() {\n updateSelectionText(\n \"Samstag und Sonntag sind nicht buchbar.\"\n );\n}\n\nfunction openDayView(date) {\n if (!calendar) {\n return;\n }\n\n if (isWeekend(date)) {\n showWeekendMessage();\n return;\n }\n\n calendar.changeView(\n \"timeGridDay\",\n date\n );\n}\n\nfunction createCalendar() {\n const calendarElement =\n document.getElementById(\"calendar\");\n\n if (!calendarElement) {\n return;\n }\n\n if (typeof FullCalendar === \"undefined\") {\n calendarElement.textContent =\n \"FullCalendar konnte nicht geladen werden.\";\n return;\n }\n\n if (calendar) {\n calendar.destroy();\n calendar = null;\n }\n\n calendar = new FullCalendar.Calendar(\n calendarElement,\n {\n initialView: \"dayGridMonth\",\n\n locale: \"de\",\n firstDay: 1,\n\n navLinks: true,\n\n navLinkDayClick(date) {\n openDayView(date);\n },\n\n dateClick(info) {\n if (info.view.type !== \"dayGridMonth\") {\n return;\n }\n\n openDayView(info.date);\n },\n\n selectable: false,\n editable: false,\n eventStartEditable: false,\n eventDurationEditable: false,\n\n /*\n * Startwerte für die Monatsansicht.\n */\n height: MONTH_HEIGHT,\n contentHeight: MONTH_CONTENT_HEIGHT,\n expandRows: true,\n\n headerToolbar: {\n left: \"prev,next today\",\n center: \"title\",\n right: \"dayGridMonth,timeGridDay\"\n },\n\n buttonText: {\n today: \"Heute\",\n month: \"Monat\",\n day: \"Tag\"\n },\n\n /*\n * Zeitraster der Tagesansicht.\n */\n slotDuration: \"00:30:00\",\n snapDuration: \"00:30:00\",\n\n slotMinTime: \"07:00:00\",\n slotMaxTime: \"20:00:00\",\n\n scrollTime: \"08:00:00\",\n\n /*\n * Verhindert das erneute Springen beim\n * erneuten Setzen eines Datumsbereichs.\n */\n scrollTimeReset: false,\n\n allDaySlot: false,\n nowIndicator: true,\n\n events: getEvents(),\n\n datesSet(info) {\n updateCalendarViewSettings(\n info.view.type\n );\n },\n\n eventClick(info) {\n const event =\n info.event;\n\n const start =\n event.start\n ? formatDateTime(event.start)\n : \"\";\n\n const end =\n event.end\n ? formatDateTime(event.end)\n : \"\";\n\n const rangeText =\n end\n ? `${start} bis ${end}`\n : start;\n\n updateSelectionText(\n `${event.title || \"Buchung\"} ${rangeText}`\n );\n }\n }\n );\n\n calendar.render();\n\n /*\n * Nach dem ersten Rendern nur die aktuelle\n * Ansicht anwenden.\n */\n updateCalendarViewSettings(\n calendar.view.type\n );\n}\n\nfunction formatDateTime(date) {\n if (!date) {\n return \"\";\n }\n\n return new Intl.DateTimeFormat(\n \"de-DE\",\n {\n dateStyle: \"short\",\n timeStyle: \"short\"\n }\n ).format(date);\n}\n\nfunction refreshCalendarEvents() {\n if (!calendar) {\n createCalendar();\n return;\n }\n\n calendar.removeAllEvents();\n\n calendar.addEventSource(\n getEvents()\n );\n\n /*\n * Keine neue Höhe setzen und keine Ansicht\n * neu aufbauen.\n */\n calendar.updateSize();\n}\n\nfunction registerResizeHandling() {\n window.addEventListener(\n \"resize\",\n scheduleResize\n );\n}\n\nappsmith.onReady(() => {\n updateSeatTitle();\n createCalendar();\n registerResizeHandling();\n\n appsmith.onModelChange(() => {\n updateSeatTitle();\n refreshCalendarEvents();\n });\n});"
},
"version": 1,
"widgetId": "ad7fob2vs9",
"widgetName": "Custom5"
}