319 lines
9.4 KiB
Vue
319 lines
9.4 KiB
Vue
<script setup>
|
|
import dayjs from 'dayjs'
|
|
|
|
const { isHelpSlideoverOpen } = useDashboard()
|
|
const { entries, pending, error, seenState, refresh, markAsSeen } = useChangelog()
|
|
|
|
const metaSymbol = computed(() => {
|
|
if (import.meta.server) {
|
|
return 'Ctrl'
|
|
}
|
|
|
|
return /Mac|iPhone|iPad|iPod/i.test(navigator.platform) ? '⌘' : 'Ctrl'
|
|
})
|
|
|
|
const shortcuts = ref(false)
|
|
const query = ref('')
|
|
const toast = useToast()
|
|
const router = useRouter()
|
|
|
|
|
|
const links = [{
|
|
label: 'Shortcuts',
|
|
icon: 'i-heroicons-key',
|
|
trailingIcon: 'i-heroicons-arrow-right-20-solid',
|
|
onClick: () => {
|
|
shortcuts.value = true
|
|
}
|
|
},/* {
|
|
label: 'Tickets',
|
|
icon: 'i-heroicons-clipboard-document',
|
|
to: '/support',
|
|
},*/ {
|
|
label: 'Webseite',
|
|
icon: 'i-heroicons-globe-europe-africa',
|
|
to: 'https://fedeo.de',
|
|
target: '_blank'
|
|
}, {
|
|
label: 'Versionshistorie',
|
|
icon: 'i-heroicons-rocket-launch',
|
|
to: 'https://fedeo.de/changelog',
|
|
target: '_blank'
|
|
},/* {
|
|
label: 'Roadmap',
|
|
icon: 'i-heroicons-rocket-launch',
|
|
to: 'https://fedeo.de/roadmap',
|
|
target: '_blank'
|
|
},*/ {
|
|
label: 'Doku',
|
|
icon: 'i-heroicons-book-open',
|
|
to: 'https://fedeo.de/docs',
|
|
target: '_blank'
|
|
}, {
|
|
label: 'Status',
|
|
icon: 'i-heroicons-shield-check',
|
|
to: 'https://uptime.fedeo.io/status/fedeo',
|
|
target: '_blank'
|
|
}/*, {
|
|
label: 'Bugs & Features',
|
|
icon: 'i-heroicons-book-open',
|
|
to: 'https://gitlab.federspiel.software/fedeo/software-features',
|
|
target: '_blank'
|
|
}, {
|
|
label: 'GitHub repository',
|
|
icon: 'i-simple-icons-github',
|
|
to: 'https://github.com/nuxt/ui-pro',
|
|
target: '_blank'
|
|
}, {
|
|
label: 'Buy Nuxt UI Pro',
|
|
icon: 'i-heroicons-credit-card',
|
|
to: 'https://ui.nuxt.com/pro/purchase',
|
|
target: '_blank'
|
|
}*/]
|
|
|
|
const categories = computed(() => [{
|
|
title: 'General',
|
|
items: [
|
|
{ shortcuts: [metaSymbol.value, 'K'], name: 'Hauptmenü' },
|
|
{ shortcuts: ['N'], name: 'Benachrichtigungen' },
|
|
{ shortcuts: ['?'], name: 'Help & Support' },
|
|
{ shortcuts: ['/'], name: 'Suche' }
|
|
]
|
|
}, {
|
|
title: 'Navigation',
|
|
items: [
|
|
{ shortcuts: ['G', 'H'], name: 'Gehe zu Dashboard' },
|
|
{ shortcuts: ['G', 'A'], name: 'Gehe zu Aufgaben' },
|
|
{ shortcuts: ['G', 'D'], name: 'Gehe zu Dokumente' },
|
|
{ shortcuts: ['G', 'K'], name: 'Gehe zu Kunden' },
|
|
{ shortcuts: ['G', 'L'], name: 'Gehe zu Lieferanten' },
|
|
{ shortcuts: ['G', 'P'], name: 'Gehe zu Projekte' },
|
|
{ shortcuts: ['G', 'V'], name: 'Gehe zu Verträge' },
|
|
{ shortcuts: ['G', 'O'], name: 'Gehe zu Objekte' },/*
|
|
{ shortcuts: ['G', 'I'], name: 'Go to Inbox' },
|
|
{ shortcuts: ['G', 'U'], name: 'Go to Users' },*/
|
|
{ shortcuts: ['G', 'S'], name: 'Gehe zu Einstellungen' },
|
|
{ shortcuts: ['↑'], name: 'Vorheriger Eintrag' },
|
|
{ shortcuts: ['↓'], name: 'Nächster Eintrag' },
|
|
{ shortcuts: ['↵'], name: 'Eintrag Öffnen' },
|
|
{ shortcuts: ['←'], name: 'Tab nach links wechseln' },
|
|
{ shortcuts: ['→'], name: 'Tab nach rechts wechseln' },
|
|
]
|
|
}, /*{
|
|
title: 'Inbox',
|
|
items: [
|
|
{ shortcuts: ['↑'], name: 'Prev notification' },
|
|
{ shortcuts: ['↓'], name: 'Next notification' }
|
|
]
|
|
}*/])
|
|
|
|
const filteredCategories = computed(() => {
|
|
return categories.value.map(category => ({
|
|
title: category.title,
|
|
items: category.items.filter(item => {
|
|
return item.name.search(new RegExp(query.value, 'i')) !== -1
|
|
})
|
|
})).filter(category => !!category.items.length)
|
|
})
|
|
|
|
const contactRequestData = ref({
|
|
message: "",
|
|
title: "",
|
|
})
|
|
|
|
const loadingContactRequest = ref(false)
|
|
|
|
const addContactRequest = async () => {
|
|
console.log("ADD")
|
|
loadingContactRequest.value = true
|
|
const retVal = await useFunctions().useCreateTicket(contactRequestData.value.title,contactRequestData.value.message,router.currentRoute.value.fullPath,"helpSlideover",)
|
|
|
|
if(retVal) {
|
|
toast.add({title: "Anfrage erfolgreich erstellt"})
|
|
resetContactRequest()
|
|
} else {
|
|
toast.add({title: "Anfrage konnte nicht erstellt werden",color:"error"})
|
|
}
|
|
loadingContactRequest.value = false
|
|
}
|
|
|
|
const resetContactRequest = () => {
|
|
contactRequestData.value = {
|
|
message: "",
|
|
title: "",
|
|
}
|
|
}
|
|
|
|
const lastOpenedLabel = computed(() => {
|
|
if (!seenState.value.lastOpenedAt) return 'Noch nicht geöffnet'
|
|
|
|
return dayjs(seenState.value.lastOpenedAt).format('DD.MM.YYYY HH:mm')
|
|
})
|
|
|
|
const changelogEntries = computed(() => entries.value.slice(0, 12))
|
|
|
|
watch(isHelpSlideoverOpen, async (isOpen) => {
|
|
if (!isOpen || shortcuts.value) return
|
|
|
|
await refresh(true)
|
|
markAsSeen()
|
|
})
|
|
</script>
|
|
|
|
<template>
|
|
<USlideover v-model:open="isHelpSlideoverOpen" side="right">
|
|
<template #title>
|
|
<UButton
|
|
v-if="shortcuts"
|
|
color="gray"
|
|
variant="ghost"
|
|
size="sm"
|
|
icon="i-heroicons-arrow-left-20-solid"
|
|
@click="shortcuts = false"
|
|
/>
|
|
|
|
{{ shortcuts ? 'Shortcuts' : 'Hilfe & Information' }}
|
|
</template>
|
|
|
|
<template #body>
|
|
<div v-if="shortcuts" class="space-y-6">
|
|
<UInput v-model="query" icon="i-heroicons-magnifying-glass" placeholder="Search..." autofocus color="gray" />
|
|
|
|
<div v-for="(category, index) in filteredCategories" :key="index">
|
|
<p class="mb-3 text-sm text-gray-900 dark:text-white font-semibold">
|
|
{{ category.title }}
|
|
</p>
|
|
|
|
<div class="space-y-2">
|
|
<div v-for="(item, i) in category.items" :key="i" class="flex items-center justify-between">
|
|
<span class="text-sm text-gray-500 dark:text-gray-400">{{ item.name }}</span>
|
|
|
|
<div class="flex items-center justify-end flex-shrink-0 gap-0.5">
|
|
<UKbd v-for="(shortcut, j) in item.shortcuts" :key="j">
|
|
{{ shortcut }}
|
|
</UKbd>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div v-else class="flex flex-col gap-y-6">
|
|
<div class="flex flex-col gap-y-3">
|
|
<UButton v-for="(link, index) in links" :key="index" color="white" v-bind="link" />
|
|
</div>
|
|
|
|
<UCard>
|
|
<div class="flex items-center justify-between gap-3">
|
|
<div>
|
|
<p class="text-base font-semibold text-gray-900 dark:text-white">
|
|
Changelog
|
|
</p>
|
|
<p class="text-sm text-gray-500 dark:text-gray-400">
|
|
Zuletzt geöffnet: {{ lastOpenedLabel }}
|
|
</p>
|
|
</div>
|
|
|
|
<UButton
|
|
icon="i-heroicons-arrow-path"
|
|
color="gray"
|
|
variant="ghost"
|
|
:loading="pending"
|
|
@click="refresh(true)"
|
|
/>
|
|
</div>
|
|
|
|
<UAlert
|
|
v-if="error"
|
|
class="mt-4"
|
|
color="red"
|
|
variant="soft"
|
|
title="Changelog konnte nicht geladen werden"
|
|
:description="error"
|
|
/>
|
|
|
|
<div v-else-if="pending && !changelogEntries.length" class="mt-4">
|
|
<UProgress animation="carousel"/>
|
|
</div>
|
|
|
|
<div v-else-if="changelogEntries.length" class="mt-4 flex flex-col gap-3">
|
|
<div
|
|
v-for="entry in changelogEntries"
|
|
:key="entry.hash"
|
|
class="rounded-lg border border-gray-200 dark:border-gray-800 p-3"
|
|
>
|
|
<div class="flex items-start justify-between gap-3">
|
|
<div class="min-w-0">
|
|
<p class="font-medium text-gray-900 dark:text-white break-words">
|
|
{{ entry.subject }}
|
|
</p>
|
|
<p class="text-sm text-gray-500 dark:text-gray-400 mt-1">
|
|
{{ entry.authorName }} · {{ dayjs(entry.committedAt).format('DD.MM.YYYY HH:mm') }}
|
|
</p>
|
|
</div>
|
|
|
|
<UBadge color="gray" variant="subtle">
|
|
{{ entry.shortHash }}
|
|
</UBadge>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<p v-else class="mt-4 text-sm text-gray-500 dark:text-gray-400">
|
|
Es sind noch keine Changelog-Einträge verfügbar.
|
|
</p>
|
|
</UCard>
|
|
</div>
|
|
<!-- <div class="mt-5" v-if="!loadingContactRequest">
|
|
<h1 class="font-semibold">Kontaktanfrage:</h1>
|
|
<UForm
|
|
class="p-3"
|
|
@submit="addContactRequest"
|
|
@reset="resetContactRequest"
|
|
>
|
|
<!– <UFormGroup
|
|
label="Art:"
|
|
>
|
|
<USelectMenu
|
|
:options="['Hilfe','Software Problem / Bug','Funktionsanfrage','Kontakt','Sonstiges']"
|
|
v-model="contactRequestData.contactType"
|
|
/>
|
|
</UFormGroup>–>
|
|
<UFormGroup
|
|
label="Titel:"
|
|
>
|
|
<UInput
|
|
v-model="contactRequestData.title"
|
|
/>
|
|
</UFormGroup>
|
|
<UFormGroup
|
|
label="Nachricht:"
|
|
>
|
|
<UTextarea
|
|
v-model="contactRequestData.message"
|
|
rows="6"
|
|
/>
|
|
</UFormGroup>
|
|
<InputGroup class="mt-3">
|
|
<UButton
|
|
type="submit"
|
|
:disabled="!contactRequestData.title || !contactRequestData.message"
|
|
>
|
|
Senden
|
|
</UButton>
|
|
<UButton
|
|
type="reset"
|
|
color="error"
|
|
variant="outline"
|
|
:disabled="!contactRequestData.title && !contactRequestData.message"
|
|
>
|
|
Zurücksetzen
|
|
</UButton>
|
|
</InputGroup>
|
|
|
|
</UForm>
|
|
</div>
|
|
<UProgress class="mt-5" animation="carousel" v-else/>-->
|
|
</template>
|
|
</USlideover>
|
|
</template>
|