feat: CalDAV-URLs im Kalender-Menue anzeigen
Im Drei-Punkte-Menue jedes Kalenders wird jetzt ein Info-Block mit den CalDAV-URLs angezeigt: * Auto-Discovery URL fuer Thunderbird / DAVx5 / Apple Calendar * Direkt-URL fuer diesen speziellen Kalender (z.B. Outlook CalDAV-Synchronizer) * Kurz-Hinweis welcher Client welche URL nimmt Jede URL hat ein Kopier-Icon. Ergaenzt den bestehenden iCal-Link um die bidirektionale Sync-Moeglichkeit ueber CalDAV. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -203,6 +203,29 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div class="field caldav-block">
|
||||||
|
<label><i class="pi pi-info-circle"></i> CalDAV-Zugang (native Sync)</label>
|
||||||
|
<p class="caldav-hint">
|
||||||
|
Im Handy/Laptop-Kalender als CalDAV-Account hinzufuegen. Benutzername
|
||||||
|
und Passwort sind deine normalen Mini-Cloud-Zugangsdaten.
|
||||||
|
</p>
|
||||||
|
<div class="url-row">
|
||||||
|
<strong>Auto-Discovery</strong>
|
||||||
|
<code>{{ origin }}/dav/</code>
|
||||||
|
<Button icon="pi pi-copy" text size="small" title="Kopieren" @click="copyText(origin + '/dav/')" />
|
||||||
|
</div>
|
||||||
|
<div class="url-row">
|
||||||
|
<strong>Dieser Kalender (direkt)</strong>
|
||||||
|
<code>{{ origin }}/dav/{{ username }}/cal-{{ selectedCal.id }}/</code>
|
||||||
|
<Button icon="pi pi-copy" text size="small" title="Kopieren"
|
||||||
|
@click="copyText(`${origin}/dav/${username}/cal-${selectedCal.id}/`)" />
|
||||||
|
</div>
|
||||||
|
<div class="caldav-clients">
|
||||||
|
<div><strong>Thunderbird / DAVx5 / Apple</strong>: Auto-Discovery-URL benutzen</div>
|
||||||
|
<div><strong>Outlook (CalDAV-Synchronizer)</strong>: Direkt-URL</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
<Button v-if="selectedCal.permission === 'owner'" label="Kalender loeschen"
|
<Button v-if="selectedCal.permission === 'owner'" label="Kalender loeschen"
|
||||||
severity="danger" text size="small" @click="confirmDeleteCal = true" />
|
severity="danger" text size="small" @click="confirmDeleteCal = true" />
|
||||||
</div>
|
</div>
|
||||||
@@ -239,6 +262,7 @@
|
|||||||
<script setup>
|
<script setup>
|
||||||
import { ref, computed, onMounted, reactive, watch } from 'vue'
|
import { ref, computed, onMounted, reactive, watch } from 'vue'
|
||||||
import { useToast } from 'primevue/usetoast'
|
import { useToast } from 'primevue/usetoast'
|
||||||
|
import { useAuthStore } from '../stores/auth'
|
||||||
import apiClient from '../api/client'
|
import apiClient from '../api/client'
|
||||||
import Button from 'primevue/button'
|
import Button from 'primevue/button'
|
||||||
import Dialog from 'primevue/dialog'
|
import Dialog from 'primevue/dialog'
|
||||||
@@ -253,6 +277,9 @@ import rrulePlugin from '@fullcalendar/rrule'
|
|||||||
import deLocale from '@fullcalendar/core/locales/de'
|
import deLocale from '@fullcalendar/core/locales/de'
|
||||||
|
|
||||||
const toast = useToast()
|
const toast = useToast()
|
||||||
|
const auth = useAuthStore()
|
||||||
|
const origin = computed(() => window.location.origin)
|
||||||
|
const username = computed(() => auth.user?.username || '')
|
||||||
const calendars = ref([])
|
const calendars = ref([])
|
||||||
const visibleCalendars = reactive({})
|
const visibleCalendars = reactive({})
|
||||||
const fcRef = ref(null)
|
const fcRef = ref(null)
|
||||||
@@ -789,6 +816,11 @@ function copyIcal() {
|
|||||||
toast.add({ severity: 'info', summary: 'Link kopiert', life: 2000 })
|
toast.add({ severity: 'info', summary: 'Link kopiert', life: 2000 })
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function copyText(text) {
|
||||||
|
navigator.clipboard.writeText(text)
|
||||||
|
toast.add({ severity: 'info', summary: 'Kopiert', life: 1500 })
|
||||||
|
}
|
||||||
|
|
||||||
async function deleteCalendar() {
|
async function deleteCalendar() {
|
||||||
if (!selectedCal.value) return
|
if (!selectedCal.value) return
|
||||||
await apiClient.delete(`/calendars/${selectedCal.value.id}`)
|
await apiClient.delete(`/calendars/${selectedCal.value.id}`)
|
||||||
@@ -868,6 +900,14 @@ onMounted(async () => {
|
|||||||
.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; }
|
||||||
.ical-url code { background: var(--p-surface-100); padding: 0.25rem 0.5rem; border-radius: 4px; word-break: break-all; }
|
.ical-url code { background: var(--p-surface-100); padding: 0.25rem 0.5rem; border-radius: 4px; word-break: break-all; }
|
||||||
|
.caldav-block { border-top: 1px solid var(--p-surface-200); padding-top: 1rem; margin-top: 1rem; }
|
||||||
|
.caldav-hint { font-size: 0.8rem; color: var(--p-text-muted-color); margin: 0 0 0.75rem; }
|
||||||
|
.url-row { display: flex; gap: 0.5rem; align-items: center; margin-bottom: 0.5rem; flex-wrap: wrap; }
|
||||||
|
.url-row strong { min-width: 160px; font-size: 0.8rem; }
|
||||||
|
.url-row code { background: var(--p-surface-100); padding: 0.25rem 0.5rem; border-radius: 4px;
|
||||||
|
font-size: 0.8rem; word-break: break-all; flex: 1; }
|
||||||
|
.caldav-clients { font-size: 0.75rem; color: var(--p-text-muted-color); margin-top: 0.5rem; }
|
||||||
|
.caldav-clients div { margin-bottom: 0.15rem; }
|
||||||
.hint-badge { font-size: 0.75rem; color: var(--p-primary-700); display: inline-flex; gap: 0.25rem; align-items: center; }
|
.hint-badge { font-size: 0.75rem; color: var(--p-primary-700); display: inline-flex; gap: 0.25rem; align-items: center; }
|
||||||
.fc-event-content-inner { display: flex; align-items: center; gap: 0.2rem; overflow: hidden; white-space: nowrap; text-overflow: ellipsis; padding: 0 2px; }
|
.fc-event-content-inner { display: flex; align-items: center; gap: 0.2rem; overflow: hidden; white-space: nowrap; text-overflow: ellipsis; padding: 0 2px; }
|
||||||
.fc-event-content-inner .fc-icon { flex-shrink: 0; font-size: 0.85em; }
|
.fc-event-content-inner .fc-icon { flex-shrink: 0; font-size: 0.85em; }
|
||||||
|
|||||||
Reference in New Issue
Block a user