feat(ccli): integrate CCLI buttons in ArrangementDialog and SongDB Index

This commit is contained in:
Thorsten Bus 2026-05-11 10:29:52 +02:00
parent 3020800acb
commit b0320fbef5
2 changed files with 72 additions and 9 deletions

View file

@ -2,6 +2,7 @@
import { computed, nextTick, ref, watch, onMounted, onUnmounted } from 'vue'
import { router } from '@inertiajs/vue3'
import { VueDraggable } from 'vue-draggable-plus'
import CcliPasteDialog from '@/Components/CcliPasteDialog.vue'
const MASTER_ID = 'master'
@ -42,6 +43,7 @@ const searchQuery = ref('')
const selectedSongId = ref('')
const dropdownOpen = ref(false)
const assignError = ref('')
const ccliDialogOpen = ref(false)
function normalize(value) {
return (value ?? '').toString().toLowerCase().trim()
@ -539,14 +541,34 @@ function closeOnBackdrop(e) {
<p v-if="assignError" class="text-sm text-red-600">{{ assignError }}</p>
<button
type="button"
class="inline-flex items-center justify-center rounded-md bg-emerald-600 px-5 py-2 text-sm font-semibold text-white shadow transition hover:bg-emerald-700"
data-testid="song-assign-button"
@click="assignSong"
>
Zuordnen
</button>
<div class="flex items-center gap-2">
<button
type="button"
class="inline-flex items-center justify-center rounded-md bg-emerald-600 px-5 py-2 text-sm font-semibold text-white shadow transition hover:bg-emerald-700"
data-testid="song-assign-button"
@click="assignSong"
>
Zuordnen
</button>
<a
v-if="searchQuery"
:href="'https://songselect.ccli.com/Search/Results?searchText=' + encodeURIComponent(searchQuery)"
target="_blank"
rel="noopener noreferrer"
data-testid="songselect-search-button"
class="inline-flex items-center justify-center rounded-md border border-gray-300 bg-white px-3 py-2 text-sm font-medium text-gray-700 shadow-sm transition hover:bg-gray-50"
>
Auf SongSelect suchen
</a>
<button
type="button"
data-testid="open-ccli-paste-dialog-button"
@click="ccliDialogOpen = true"
class="inline-flex items-center justify-center rounded-md border border-blue-300 bg-blue-50 px-3 py-2 text-sm font-medium text-blue-700 shadow-sm transition hover:bg-blue-100"
>
Aus CCLI importieren
</button>
</div>
</div>
</div>
@ -735,6 +757,15 @@ function closeOnBackdrop(e) {
</div>
</Transition>
</Teleport>
<!-- CCLI Paste Dialog -->
<CcliPasteDialog
:open="ccliDialogOpen"
mode="service-form"
:service-song-id="props.serviceSongId"
@close="ccliDialogOpen = false"
@imported="(songId) => { ccliDialogOpen = false; router.reload({ only: ['service'] }) }"
/>
</template>
<style scoped>

View file

@ -1,7 +1,8 @@
<script setup>
import AuthenticatedLayout from '@/Layouts/AuthenticatedLayout.vue'
import SongEditModal from '@/Components/SongEditModal.vue'
import { Head } from '@inertiajs/vue3'
import CcliPasteDialog from '@/Components/CcliPasteDialog.vue'
import { Head, router } from '@inertiajs/vue3'
import axios from 'axios'
import { ref, watch, onMounted } from 'vue'
@ -22,6 +23,7 @@ const fileInput = ref(null)
// Edit modal state
const showEditModal = ref(false)
const editSongId = ref(null)
const ccliDialogOpen = ref(false)
let debounceTimer = null
// Preview modal state
@ -387,6 +389,28 @@ function pageRange() {
</Transition>
</div>
<!-- CCLI Import Buttons -->
<div class="mb-4 flex items-center gap-2">
<a
v-if="search"
:href="'https://songselect.ccli.com/Search/Results?searchText=' + encodeURIComponent(search)"
target="_blank"
rel="noopener noreferrer"
data-testid="songselect-search-button-songdb"
class="inline-flex items-center gap-1 rounded-md border border-gray-300 bg-white px-3 py-1.5 text-sm font-medium text-gray-700 shadow-sm transition hover:bg-gray-50"
>
Auf SongSelect suchen
</a>
<button
type="button"
data-testid="open-ccli-paste-dialog-button-songdb"
@click="ccliDialogOpen = true"
class="inline-flex items-center gap-1 rounded-md border border-blue-300 bg-blue-50 px-3 py-1.5 text-sm font-medium text-blue-700 shadow-sm transition hover:bg-blue-100"
>
Aus CCLI importieren
</button>
</div>
<!-- Song Count + Loading -->
<div class="mb-3 flex items-center justify-between px-1">
<p class="text-xs font-medium text-gray-500">
@ -758,4 +782,12 @@ function pageRange() {
</Teleport>
</AuthenticatedLayout>
<!-- CCLI Paste Dialog -->
<CcliPasteDialog
:open="ccliDialogOpen"
mode="songdb"
@close="ccliDialogOpen = false"
@imported="(songId, mode) => { ccliDialogOpen = false; if (mode === 'stay') { router.reload({ only: ['songs'] }) } }"
/>
</template>