- Add virtual MASTER arrangement to all songs (read-only, shows all groups in song order, clonable)
- Fix drop zone staying open after slide upload and thumbnail 403 (double slides/ path)
- Add click-to-preview overlay with download button, prev/next navigation, and slide counter
- Add X delete button with confirmation dialog and hover tooltip preview on agenda thumbnails
- Fix arrangement select not updating after add/clone (emit + re-fetch pattern)
- Move InformationBlock below agenda; announcement row scrolls to it instead of showing upload
- Create storage symlink (public/storage -> storage/app/public)
- Remove drag handle restriction — entire pill box is now draggable
- Keep local copy of arrangements so edits survive switching between
arrangements (was reading stale props after switch-back)
- Highlight corresponding left pill when hovering right lyric preview
- Replace card-based agenda layout with a 6-column table (Nr, Zeit, Dauer, Titel, Verantwortlich, Aktionen)
- Fix isHeaderType to only match type=header, not all non-song items
- Format start time from ISO 8601 to HH:MM (Europe/Berlin)
- Format duration from seconds string to H:MM
- Fix responsible parsing for CTS data structure ({text, persons[{person:{title}}]})
- Move unmatched song search/assign UI into ArrangementDialog popup
- Add colored row backgrounds (song/sermon/announcement/slides) with left border
- Invert header rows to dark grey background with white text
- Transform arrangement data in Edit.vue to flat {id, name, color, slides}
format expected by ArrangementDialog (was passing raw Eloquent structure
with nested arrangement_groups[].group instead of flat .groups[])
- Stop arrangement select change from closing the dialog (only close on X)
- Fallback to all available groups when no arrangement selected (Master)
Events without an agenda in ChurchTools now gracefully set has_agenda=false
instead of throwing errors during sync. The edit/finalize buttons are
disabled in the frontend for services without an agenda.
Also fixes missing cts_song_id column on service_songs table.
The ModerationBlock, SermonBlock, and SongsBlock Vue components are no longer
imported or used in the Edit.vue page after Task 12 restructuring. Removed
deprecated files, keeping ArrangementConfigurator which is still used by
SongEditModal and ArrangementDialog.
- Fix uploaded_at in InformationBlockTest and ServiceControllerTest
(Faker ignores Carbon::setTestNow, generating future dates that fail
the uploaded_at <= service.date filter)
- Add agenda item association tests to ModerationBlockTest (3 new tests)
- Add agenda item association tests to SermonBlockTest (3 new tests)
- Verify legacy slides without agenda item still work
Test results: 12 failures (down from 14 baseline), all pre-existing
(ProPresenter parser path issues + suite ordering flake)
Faker's dateTimeBetween ignores Carbon::setTestNow, producing dates
after the frozen test time. This caused the info_slides_count
assertion to fail non-deterministically when the system date diverged
from the test-frozen date.
Replace file-path-based zip entries with in-memory content via
file_get_contents. Rename .pro entry to 'data' (raw protobuf),
add addStoredEntry() helper with CM_STORE compression, and remove
temp directory management.
Specify explicit order values for SongGroup factories to avoid unique
constraint violations on the composite (song_id, order) key when
faker generates duplicate random values.
Simplify ArrangementConfigurator: replace color pickers with compact
pills, add click-to-add from pool, use watcher-based auto-select for
new/cloned arrangements, remove group_colors from save payload.
Enhance SongsBlock preview: color-coded group headers with tinted
backgrounds, PDF download button inside preview modal, .pro download
link per matched song, show DB ccli_id with fallback to CTS ccli_id.
Fix Modal z-index for nested dialogs. Fix SlideUploader duplicate
upload on watch by adding deep option and upload guard. Expand API
log detail sections by default and increase JSON tree depth. Convert
song download button from emit to direct .pro download link.
Add information, moderation, and sermon slide presentations as .pro
files in the generated .proplaylist bundle. Each block queries slides
by type/service, converts stored images, and generates a ProPresenter
presentation via ProFileGenerator.
Add test_download_pro_roundtrip_preserves_content that imports a .pro
file, exports it, re-reads with the parser, and asserts song name,
groups, slides, translations, arrangements, and CCLI metadata survive
the round-trip.
Add sort_order to slides table with migration and model fillable.
Add destroyBulk() for batch soft-delete by type/service_id and
reorder() for drag-and-drop slide ordering. Auto-assign sort_order
on image and zip uploads.
- Migration: settings table with key (unique), value (text), timestamps
- Model: Setting with static get/set helpers using DB upsert
- Controller: SettingsController with index (Inertia) and update (JSON)
- Vue: Settings page with 4 macro fields, auto-save on blur
- Navigation: Einstellungen link in desktop + mobile nav after API-Log
- Shared props: macroSettings added to HandleInertiaRequests
- Integration: ProExportService injects macro into COPYRIGHT group slides
- Gracefully skips macro injection when settings empty/null
- Hide translate button for already-translated songs in SongDB
- Auto-select newly created/cloned arrangement via onSuccess + nextTick
- Add preview button to SongDB list (fetches default arrangement preview)
- Show success toast with count after .pro file import
- Replace search+select with single searchable combo/autocomplete field
- Wire preview modal and PDF download to real endpoints in service songs
- Disable preview/PDF buttons when no arrangement selected
- Slide grid now 1-2-3 columns (4x larger thumbnails)
- Delete button left, fullscreen right, always visible (no hover)
- Upload area appears inline as last grid item (no side-by-side layout)
- SlideUploader supports inline mode for grid integration
- Add recursive collapsible JsonTreeViewer component (no external deps)
- Replace raw JSON pre tags in API logs with tree viewer
- Add cts_song_id column to songs and service_songs for CCLI-free matching fallback
- Filter information slides by uploaded_at <= service date (not shown before upload)
- New arrangements use song's default group ordering instead of cloning
- Auto-set use_translation=true when matched song has translation
- Update syncSongs/syncServiceAgendaSongs to store and use cts_song_id
- Add tests for CTS song ID fallback, upload date filtering, and translation defaults
- Add trash icon button with confirmation dialog on service list
- DELETE /services/{service} hard-deletes service, its songs, and non-info slides
- Service will be recreated on next CTS sync
- Add response_body longText column to api_request_logs table
- Store serialized response (max 500KB) in ChurchToolsService::logApiCall
- Add GET /api-logs/{log}/response-body endpoint for lazy loading
- Replace static 'Array mit X Einträgen' with collapsible JSON viewer
- Response body fetched on-demand when user clicks to expand
- Replace placeholder exception with real uploadProFiles() function
- POST files to /api/songs/import-pro endpoint
- Show success/error toast and refresh song list after import
- Add EnsureFrontendRequestsAreStateful to api middleware stack
- Create config/sanctum.php with cts-work.test as stateful domain
- Fixes 'Unauthenticated' error on SongDB and other API-backed pages