feat: Kalender-Freigaben per Stift-Button bearbeiten
Analog zu den Datei-Freigaben: Stift neben der Muelltonne in der Share-Liste macht die Zeile zur Inline-Edit-Zeile mit Permission- Dropdown + Check/X. Speichern nutzt denselben POST /share- Endpoint, der auch das initiale Teilen erledigt - er erkennt den existierenden User und aktualisiert nur die Berechtigung. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -163,12 +163,22 @@
|
|||||||
<Button label="Teilen" size="small" @click="shareCalendar" />
|
<Button label="Teilen" size="small" @click="shareCalendar" />
|
||||||
</div>
|
</div>
|
||||||
<div v-if="calendarShares.length" class="existing-shares">
|
<div v-if="calendarShares.length" class="existing-shares">
|
||||||
<div v-for="s in calendarShares" :key="s.id" class="share-perm-item">
|
<template v-for="s in calendarShares" :key="s.id">
|
||||||
<i class="pi pi-user"></i>
|
<div v-if="editingShareId !== s.id" class="share-perm-item">
|
||||||
<span>{{ s.username }}</span>
|
<i class="pi pi-user"></i>
|
||||||
<span class="perm-label">{{ s.permission === 'readwrite' ? 'Lesen+Schreiben' : 'Lesen' }}</span>
|
<span>{{ s.username }}</span>
|
||||||
<Button icon="pi pi-trash" text size="small" severity="danger" @click="removeShare(s.id)" />
|
<span class="perm-label">{{ s.permission === 'readwrite' ? 'Lesen+Schreiben' : 'Lesen' }}</span>
|
||||||
</div>
|
<Button icon="pi pi-pencil" text size="small" title="Bearbeiten" @click="startEditShare(s)" />
|
||||||
|
<Button icon="pi pi-trash" text size="small" severity="danger" title="Entfernen" @click="removeShare(s.id)" />
|
||||||
|
</div>
|
||||||
|
<div v-else class="share-perm-item editing">
|
||||||
|
<i class="pi pi-user"></i>
|
||||||
|
<span>{{ s.username }}</span>
|
||||||
|
<Select v-model="editSharePermission" :options="permOptions" optionLabel="label" optionValue="value" />
|
||||||
|
<Button icon="pi pi-check" text size="small" severity="success" title="Speichern" @click="saveEditShare(s)" />
|
||||||
|
<Button icon="pi pi-times" text size="small" title="Abbrechen" @click="editingShareId = null" />
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@@ -300,6 +310,8 @@ const shareUsername = ref('')
|
|||||||
const sharePermission = ref('read')
|
const sharePermission = ref('read')
|
||||||
const shareSearchResults = ref([])
|
const shareSearchResults = ref([])
|
||||||
const calendarShares = ref([])
|
const calendarShares = ref([])
|
||||||
|
const editingShareId = ref(null)
|
||||||
|
const editSharePermission = ref('read')
|
||||||
let shareSearchTimer = null
|
let shareSearchTimer = null
|
||||||
const icalPassword = ref('')
|
const icalPassword = ref('')
|
||||||
const confirmDeleteEvent = ref(false)
|
const confirmDeleteEvent = ref(false)
|
||||||
@@ -706,6 +718,26 @@ async function loadShares() {
|
|||||||
} catch { calendarShares.value = [] }
|
} catch { calendarShares.value = [] }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function startEditShare(s) {
|
||||||
|
editingShareId.value = s.id
|
||||||
|
editSharePermission.value = s.permission
|
||||||
|
}
|
||||||
|
|
||||||
|
async function saveEditShare(s) {
|
||||||
|
if (!selectedCal.value) return
|
||||||
|
try {
|
||||||
|
await apiClient.post(`/calendars/${selectedCal.value.id}/share`, {
|
||||||
|
username: s.username,
|
||||||
|
permission: editSharePermission.value,
|
||||||
|
})
|
||||||
|
editingShareId.value = null
|
||||||
|
await loadShares()
|
||||||
|
toast.add({ severity: 'success', summary: 'Berechtigung aktualisiert', life: 2500 })
|
||||||
|
} catch (err) {
|
||||||
|
toast.add({ severity: 'error', summary: 'Fehler', detail: err.response?.data?.error || err.message, life: 5000 })
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
async function removeShare(shareId) {
|
async function removeShare(shareId) {
|
||||||
if (!selectedCal.value) return
|
if (!selectedCal.value) return
|
||||||
try {
|
try {
|
||||||
@@ -830,7 +862,8 @@ onMounted(async () => {
|
|||||||
.user-result { padding: 0.5rem 0.75rem; cursor: pointer; font-size: 0.875rem; display: flex; gap: 0.5rem; align-items: center; }
|
.user-result { padding: 0.5rem 0.75rem; cursor: pointer; font-size: 0.875rem; display: flex; gap: 0.5rem; align-items: center; }
|
||||||
.user-result:hover { background: var(--p-primary-50); }
|
.user-result:hover { background: var(--p-primary-50); }
|
||||||
.existing-shares { margin-top: 0.5rem; }
|
.existing-shares { margin-top: 0.5rem; }
|
||||||
.share-perm-item { display: flex; align-items: center; gap: 0.5rem; padding: 0.375rem 0; font-size: 0.875rem; }
|
.share-perm-item { display: flex; align-items: center; gap: 0.5rem; padding: 0.375rem 0; font-size: 0.875rem; flex-wrap: wrap; }
|
||||||
|
.share-perm-item.editing { background: var(--p-surface-50); padding: 0.5rem; border-radius: 4px; }
|
||||||
.perm-label { color: var(--p-text-muted-color); font-size: 0.75rem; }
|
.perm-label { color: var(--p-text-muted-color); font-size: 0.75rem; }
|
||||||
.ical-block { border-top: 1px solid var(--p-surface-200); padding-top: 1rem; margin-top: 1rem; }
|
.ical-block { border-top: 1px solid var(--p-surface-200); padding-top: 1rem; margin-top: 1rem; }
|
||||||
.ical-url { font-size: 0.8rem; display: flex; gap: 0.5rem; align-items: center; flex-wrap: wrap; }
|
.ical-url { font-size: 0.8rem; display: flex; gap: 0.5rem; align-items: center; flex-wrap: wrap; }
|
||||||
|
|||||||
Reference in New Issue
Block a user