@dargmuesli/nuxt-vio 2.0.1 → 3.0.0-beta.10
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/app.config.ts +83 -40
- package/components/vio/_/VioApp.vue +92 -0
- package/components/{VioError.vue → vio/_/VioError.vue} +1 -1
- package/components/{VioLink.vue → vio/_/VioLink.vue} +2 -2
- package/components/vio/button/VioButtonColored.vue +52 -0
- package/components/vio/card/VioCard.vue +19 -0
- package/components/vio/card/state/VioCardState.vue +20 -0
- package/components/vio/card/state/VioCardStateAlert.vue +14 -0
- package/components/vio/form/VioForm.vue +84 -0
- package/components/vio/form/VioFormCheckbox.vue +27 -0
- package/components/vio/form/input/VioFormInput.vue +192 -0
- package/components/vio/form/input/VioFormInputIconWrapper.vue +7 -0
- package/components/vio/form/input/VioFormInputUrl.vue +54 -0
- package/components/vio/form/input/state/VioFormInputState.vue +5 -0
- package/components/vio/form/input/state/VioFormInputStateError.vue +32 -0
- package/components/vio/form/input/state/VioFormInputStateInfo.vue +32 -0
- package/components/vio/icon/IconArrowRight.vue +31 -0
- package/components/vio/icon/IconCalendar.vue +31 -0
- package/components/vio/icon/IconChatOutline.vue +27 -0
- package/components/vio/icon/IconChatSolid.vue +26 -0
- package/components/vio/icon/IconCheckCircle.vue +29 -0
- package/components/vio/icon/IconContainer.vue +15 -0
- package/components/vio/icon/IconDownload.vue +31 -0
- package/components/vio/icon/IconExclamationCircle.vue +29 -0
- package/components/vio/icon/IconHome.vue +31 -0
- package/components/vio/icon/IconHourglass.vue +32 -0
- package/components/vio/icon/IconLightbulb.vue +27 -0
- package/components/vio/icon/IconLogo.vue +17 -0
- package/components/vio/icon/IconMixcloud.vue +23 -0
- package/components/vio/icon/IconMusic.vue +27 -0
- package/components/vio/icon/IconPlay.vue +25 -0
- package/components/vio/icon/IconShare.vue +27 -0
- package/components/{VioLayout.vue → vio/layout/VioLayout.vue} +1 -1
- package/components/vio/layout/VioLayoutBreadcrumbs.vue +83 -0
- package/components/vio/layout/VioLayoutFooter.vue +40 -0
- package/components/vio/layout/VioLayoutFooterCategory.vue +17 -0
- package/components/vio/layout/VioLayoutHeader.vue +98 -0
- package/components/vio/layout/VioLayoutSpanList.vue +20 -0
- package/components/vio/loader/indicator/VioLoaderIndicator.vue +14 -0
- package/components/vio/loader/indicator/VioLoaderIndicatorPing.vue +12 -0
- package/components/vio/loader/indicator/VioLoaderIndicatorSpinner.vue +24 -0
- package/components/{VioLegalNotice.vue → vio/page/VioPageLegalNotice.vue} +10 -8
- package/components/{VioPrivacyPolicy.vue → vio/page/VioPagePrivacyPolicy.vue} +19 -12
- package/composables/useAppLayout.ts +12 -18
- package/composables/useDateTime.ts +17 -0
- package/composables/useFavicons.ts +5 -33
- package/composables/useFireError.ts +17 -0
- package/composables/useGetServiceHref.ts +21 -0
- package/composables/useHeadDefault.ts +21 -0
- package/composables/usePolyfills.ts +23 -0
- package/composables/useStrapiFetch.ts +10 -0
- package/error.vue +5 -2
- package/locales/de.json +7 -1
- package/locales/en.json +7 -1
- package/nuxt.config.ts +56 -10
- package/package.json +37 -25
- package/pages/legal-notice.vue +1 -1
- package/pages/privacy-policy.vue +1 -1
- package/plugins/dayjs.ts +34 -0
- package/plugins/gtag.client.ts +3 -0
- package/plugins/i18n.ts +5 -0
- package/plugins/marked.ts +9 -0
- package/server/middleware/headers.ts +41 -10
- package/server/tsconfig.json +1 -1
- package/server/utils/util.ts +2 -0
- package/store/auth.ts +32 -0
- package/tailwind.config.ts +131 -10
- package/types/api.d.ts +9 -0
- package/types/fetch.d.ts +8 -0
- package/types/modules/gql.d.ts +6 -0
- package/types/modules/graphql.d.ts +6 -0
- package/utils/constants.ts +10 -1
- package/utils/form.ts +19 -0
- package/utils/networking.ts +117 -0
- package/utils/text.ts +20 -0
- package/LICENSE +0 -674
- package/components/VioApp.vue +0 -59
- /package/components/{VioButton.vue → vio/button/VioButton.vue} +0 -0
- /package/components/{VioHr.vue → vio/layout/VioLayoutHr.vue} +0 -0
@@ -0,0 +1,40 @@
|
|
1
|
+
<template>
|
2
|
+
<footer class="text-sm leading-6">
|
3
|
+
<div class="flex flex-col gap-8">
|
4
|
+
<div class="flex items-center">
|
5
|
+
<VioLayoutHr />
|
6
|
+
<IconLogo class="mx-12 h-12 w-12 brightness-0 opacity-60 invert" />
|
7
|
+
<VioLayoutHr />
|
8
|
+
</div>
|
9
|
+
<!-- Justifying evenly, instead of "between", centers a single element. -->
|
10
|
+
<div class="flex flex-wrap justify-evenly">
|
11
|
+
<slot />
|
12
|
+
</div>
|
13
|
+
<p class="text-center text-gray-500 dark:text-gray-400">
|
14
|
+
{{
|
15
|
+
t('copyright', {
|
16
|
+
name: 'Jonas Thelemann',
|
17
|
+
year,
|
18
|
+
})
|
19
|
+
}}
|
20
|
+
</p>
|
21
|
+
</div>
|
22
|
+
</footer>
|
23
|
+
</template>
|
24
|
+
|
25
|
+
<script setup lang="ts">
|
26
|
+
const { t } = useI18n()
|
27
|
+
const config = useRuntimeConfig()
|
28
|
+
|
29
|
+
// computations
|
30
|
+
const year = computed(() =>
|
31
|
+
config.public.isTesting ? 1337 : new Date().getFullYear(),
|
32
|
+
)
|
33
|
+
</script>
|
34
|
+
|
35
|
+
<i18n lang="yaml">
|
36
|
+
de:
|
37
|
+
copyright: © {year} {name}. Alle Rechte vorbehalten.
|
38
|
+
en:
|
39
|
+
copyright: © {year} {name}. All rights reserved.
|
40
|
+
</i18n>
|
@@ -0,0 +1,17 @@
|
|
1
|
+
<template>
|
2
|
+
<div
|
3
|
+
class="flex flex-1 flex-col items-start p-4 basis-1/2 md:flex-none md:basis-auto gap-2"
|
4
|
+
>
|
5
|
+
<span class="whitespace-nowrap text-lg font-medium leading-7">
|
6
|
+
{{ heading }}
|
7
|
+
</span>
|
8
|
+
<slot />
|
9
|
+
</div>
|
10
|
+
</template>
|
11
|
+
|
12
|
+
<script setup lang="ts">
|
13
|
+
export interface Props {
|
14
|
+
heading: string
|
15
|
+
}
|
16
|
+
withDefaults(defineProps<Props>(), {})
|
17
|
+
</script>
|
@@ -0,0 +1,98 @@
|
|
1
|
+
<template>
|
2
|
+
<header class="flex items-center justify-between gap-4 mb-8">
|
3
|
+
<VioButton :aria-label="t('creal')" :to="localePath('/')">
|
4
|
+
<span class="text-lg font-bold">{{ t('creal') }}</span>
|
5
|
+
<template #prefix>
|
6
|
+
<IconLogo class="h-10 w-10" />
|
7
|
+
</template>
|
8
|
+
</VioButton>
|
9
|
+
<VioLink
|
10
|
+
v-if="eventsCurrentCount"
|
11
|
+
class="flex items-center gap-2 rounded-full border px-4 py-2 font-bold focus:rounded-full sm:px-4"
|
12
|
+
:is-colored="false"
|
13
|
+
:to="localePath('/events')"
|
14
|
+
>
|
15
|
+
<VioLayoutLivePulse />
|
16
|
+
<span class="hidden whitespace-nowrap sm:inline">
|
17
|
+
{{ t('live') }}
|
18
|
+
</span>
|
19
|
+
</VioLink>
|
20
|
+
<VioLink
|
21
|
+
v-else-if="eventsFutureCount"
|
22
|
+
class="flex items-center gap-2 rounded-full border px-2 py-2 font-bold focus:rounded-full sm:px-4"
|
23
|
+
:is-colored="false"
|
24
|
+
:to="localePath('/events')"
|
25
|
+
>
|
26
|
+
<VioLayoutLivePulse />
|
27
|
+
<span class="hidden whitespace-nowrap sm:inline">
|
28
|
+
{{ t('eventsFuture') }}
|
29
|
+
</span>
|
30
|
+
</VioLink>
|
31
|
+
<VioButton
|
32
|
+
:aria-label="t('bookCreal')"
|
33
|
+
class="basis-0 text-lg font-bold"
|
34
|
+
:is-colored="false"
|
35
|
+
:to="`mailto:e-mail+creal@jonas-thelemann.de?subject=${encodeURIComponent(
|
36
|
+
t('bookingSubject'),
|
37
|
+
)}`"
|
38
|
+
>
|
39
|
+
<span class="basis-0 whitespace-nowrap">{{ t('bookCreal') }}</span>
|
40
|
+
<template #suffix>
|
41
|
+
<IconArrowRight />
|
42
|
+
</template>
|
43
|
+
</VioButton>
|
44
|
+
</header>
|
45
|
+
</template>
|
46
|
+
|
47
|
+
<script setup lang="ts">
|
48
|
+
const { $dayjs } = useNuxtApp()
|
49
|
+
const { t } = useI18n()
|
50
|
+
const localePath = useLocalePath()
|
51
|
+
const strapiFetch = useStrapiFetch()
|
52
|
+
|
53
|
+
// async data
|
54
|
+
let eventsCurrentCount = 0
|
55
|
+
let eventsFutureCount = 0
|
56
|
+
|
57
|
+
// methods
|
58
|
+
const init = async () => {
|
59
|
+
eventsCurrentCount = (
|
60
|
+
(await strapiFetch('/events', {
|
61
|
+
query: {
|
62
|
+
'filters[$and][0][dateStart][$lte]': $dayjs().toISOString(),
|
63
|
+
'filters[$and][1][$or][0][dateEnd][$gt]': $dayjs().toISOString(),
|
64
|
+
'filters[$and][1][$or][1][dateStart][$gte]': $dayjs()
|
65
|
+
.startOf('day')
|
66
|
+
.toISOString(),
|
67
|
+
},
|
68
|
+
})) as any
|
69
|
+
).meta.pagination.total
|
70
|
+
eventsFutureCount = (
|
71
|
+
(await strapiFetch('/events', {
|
72
|
+
query: {
|
73
|
+
'filters[dateStart][$gt]': $dayjs().toISOString(),
|
74
|
+
},
|
75
|
+
})) as any
|
76
|
+
).meta.pagination.total
|
77
|
+
}
|
78
|
+
|
79
|
+
// initialization
|
80
|
+
try {
|
81
|
+
await init()
|
82
|
+
} catch (error: any) {}
|
83
|
+
</script>
|
84
|
+
|
85
|
+
<i18n lang="yaml">
|
86
|
+
en:
|
87
|
+
bookCreal: Book cReal
|
88
|
+
bookingSubject: Booking Request
|
89
|
+
creal: cReal
|
90
|
+
eventsFuture: Upcoming events
|
91
|
+
live: Live
|
92
|
+
de:
|
93
|
+
bookCreal: cReal buchen
|
94
|
+
bookingSubject: Buchungsanfrage
|
95
|
+
creal: cReal
|
96
|
+
eventsFuture: Kommende Veranstaltungen
|
97
|
+
live: Live
|
98
|
+
</i18n>
|
@@ -0,0 +1,20 @@
|
|
1
|
+
<template>
|
2
|
+
<span v-if="span instanceof String">
|
3
|
+
{{ span }}
|
4
|
+
</span>
|
5
|
+
<span v-else-if="Array.isArray(span) && span.length === 1">
|
6
|
+
{{ span[0] }}
|
7
|
+
</span>
|
8
|
+
<ol v-else-if="Array.isArray(span)" class="list-decimal">
|
9
|
+
<li v-for="spanItem in span" :key="spanItem.toString()">
|
10
|
+
{{ spanItem }}
|
11
|
+
</li>
|
12
|
+
</ol>
|
13
|
+
</template>
|
14
|
+
|
15
|
+
<script setup lang="ts">
|
16
|
+
export interface Props {
|
17
|
+
span: Array<string | Array<string>>
|
18
|
+
}
|
19
|
+
withDefaults(defineProps<Props>(), {})
|
20
|
+
</script>
|
@@ -0,0 +1,14 @@
|
|
1
|
+
<template>
|
2
|
+
<div
|
3
|
+
class="flex h-full items-center justify-center"
|
4
|
+
:title="t('globalStatusLoading')"
|
5
|
+
>
|
6
|
+
<div class="flex items-center justify-center w-1/2">
|
7
|
+
<slot />
|
8
|
+
</div>
|
9
|
+
</div>
|
10
|
+
</template>
|
11
|
+
|
12
|
+
<script setup lang="ts">
|
13
|
+
const { t } = useI18n()
|
14
|
+
</script>
|
@@ -0,0 +1,12 @@
|
|
1
|
+
<template>
|
2
|
+
<VioLoaderIndicator>
|
3
|
+
<div
|
4
|
+
class="w-1/2 aspect-square animate-ping rounded-full bg-gray-500"
|
5
|
+
:title="t('globalStatusLoading')"
|
6
|
+
/>
|
7
|
+
</VioLoaderIndicator>
|
8
|
+
</template>
|
9
|
+
|
10
|
+
<script setup lang="ts">
|
11
|
+
const { t } = useI18n()
|
12
|
+
</script>
|
@@ -0,0 +1,24 @@
|
|
1
|
+
<template>
|
2
|
+
<VioLoaderIndicator>
|
3
|
+
<svg
|
4
|
+
class="animate-spin text-black dark:text-white"
|
5
|
+
xmlns="http://www.w3.org/2000/svg"
|
6
|
+
fill="none"
|
7
|
+
viewBox="0 0 24 24"
|
8
|
+
>
|
9
|
+
<circle
|
10
|
+
class="opacity-25"
|
11
|
+
cx="12"
|
12
|
+
cy="12"
|
13
|
+
r="10"
|
14
|
+
stroke="currentColor"
|
15
|
+
stroke-width="4"
|
16
|
+
/>
|
17
|
+
<path
|
18
|
+
class="opacity-75"
|
19
|
+
fill="currentColor"
|
20
|
+
d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"
|
21
|
+
/>
|
22
|
+
</svg>
|
23
|
+
</VioLoaderIndicator>
|
24
|
+
</template>
|
@@ -9,13 +9,13 @@
|
|
9
9
|
<br />
|
10
10
|
</template>
|
11
11
|
<template #city>
|
12
|
-
{{ appConfig.legalNotice.tmg.address.city }}
|
12
|
+
{{ appConfig.vio.pages.legalNotice.tmg.address.city }}
|
13
13
|
</template>
|
14
14
|
<template #name>
|
15
|
-
{{ appConfig.legalNotice.tmg.address.name }}
|
15
|
+
{{ appConfig.vio.pages.legalNotice.tmg.address.name }}
|
16
16
|
</template>
|
17
17
|
<template #street>
|
18
|
-
{{ appConfig.legalNotice.tmg.address.street }}
|
18
|
+
{{ appConfig.vio.pages.legalNotice.tmg.address.street }}
|
19
19
|
</template>
|
20
20
|
</i18n-t>
|
21
21
|
</address>
|
@@ -24,7 +24,9 @@
|
|
24
24
|
<p>
|
25
25
|
<slot v-if="$slots.contactEmail" name="contactEmail" />
|
26
26
|
<span v-else>
|
27
|
-
{{
|
27
|
+
{{
|
28
|
+
t('email', { email: appConfig.vio.pages.legalNotice.contact.email })
|
29
|
+
}}
|
28
30
|
</span>
|
29
31
|
</p>
|
30
32
|
|
@@ -36,13 +38,13 @@
|
|
36
38
|
<br />
|
37
39
|
</template>
|
38
40
|
<template #city>
|
39
|
-
{{ appConfig.legalNotice.responsibility.address.city }}
|
41
|
+
{{ appConfig.vio.pages.legalNotice.responsibility.address.city }}
|
40
42
|
</template>
|
41
43
|
<template #name>
|
42
|
-
{{ appConfig.legalNotice.responsibility.address.name }}
|
44
|
+
{{ appConfig.vio.pages.legalNotice.responsibility.address.name }}
|
43
45
|
</template>
|
44
46
|
<template #street>
|
45
|
-
{{ appConfig.legalNotice.responsibility.address.street }}
|
47
|
+
{{ appConfig.vio.pages.legalNotice.responsibility.address.street }}
|
46
48
|
</template>
|
47
49
|
</i18n-t>
|
48
50
|
</address>
|
@@ -73,7 +75,7 @@ const { t } = useI18n()
|
|
73
75
|
const title = t('title')
|
74
76
|
|
75
77
|
// initialization
|
76
|
-
|
78
|
+
useServerSeoMeta({ title })
|
77
79
|
</script>
|
78
80
|
|
79
81
|
<i18n lang="yaml">
|
@@ -64,14 +64,21 @@
|
|
64
64
|
<br />
|
65
65
|
</template>
|
66
66
|
<template #city>
|
67
|
-
{{
|
67
|
+
{{
|
68
|
+
appConfig.vio.pages.privacyPolicy.hostingCdn.external
|
69
|
+
.address.city
|
70
|
+
}}
|
68
71
|
</template>
|
69
72
|
<template #name>
|
70
|
-
{{
|
73
|
+
{{
|
74
|
+
appConfig.vio.pages.privacyPolicy.hostingCdn.external
|
75
|
+
.address.name
|
76
|
+
}}
|
71
77
|
</template>
|
72
78
|
<template #street>
|
73
79
|
{{
|
74
|
-
appConfig.privacyPolicy.hostingCdn.external
|
80
|
+
appConfig.vio.pages.privacyPolicy.hostingCdn.external
|
81
|
+
.address.street
|
75
82
|
}}
|
76
83
|
</template>
|
77
84
|
</i18n-t>
|
@@ -109,29 +116,29 @@
|
|
109
116
|
</template>
|
110
117
|
<template #city>
|
111
118
|
{{
|
112
|
-
appConfig.privacyPolicy.mandatoryInfo.responsible
|
113
|
-
.city
|
119
|
+
appConfig.vio.pages.privacyPolicy.mandatoryInfo.responsible
|
120
|
+
.address.city
|
114
121
|
}}
|
115
122
|
</template>
|
116
123
|
<template #email>
|
117
124
|
{{
|
118
125
|
t('email', {
|
119
126
|
email:
|
120
|
-
appConfig.privacyPolicy.mandatoryInfo
|
121
|
-
.address.email,
|
127
|
+
appConfig.vio.pages.privacyPolicy.mandatoryInfo
|
128
|
+
.responsible.address.email,
|
122
129
|
})
|
123
130
|
}}
|
124
131
|
</template>
|
125
132
|
<template #name>
|
126
133
|
{{
|
127
|
-
appConfig.privacyPolicy.mandatoryInfo.responsible
|
128
|
-
.name
|
134
|
+
appConfig.vio.pages.privacyPolicy.mandatoryInfo.responsible
|
135
|
+
.address.name
|
129
136
|
}}
|
130
137
|
</template>
|
131
138
|
<template #street>
|
132
139
|
{{
|
133
|
-
appConfig.privacyPolicy.mandatoryInfo.responsible
|
134
|
-
.street
|
140
|
+
appConfig.vio.pages.privacyPolicy.mandatoryInfo.responsible
|
141
|
+
.address.street
|
135
142
|
}}
|
136
143
|
</template>
|
137
144
|
</i18n-t>
|
@@ -502,7 +509,7 @@ const { t } = useI18n()
|
|
502
509
|
const title = t('title')
|
503
510
|
|
504
511
|
// initialization
|
505
|
-
|
512
|
+
useServerSeoMeta({ title })
|
506
513
|
</script>
|
507
514
|
|
508
515
|
<i18n lang="yaml">
|
@@ -1,29 +1,23 @@
|
|
1
1
|
export const useAppLayout = () => {
|
2
2
|
const appConfig = useAppConfig()
|
3
|
+
const siteConfig = useSiteConfig()
|
3
4
|
|
4
|
-
|
5
|
+
useServerHeadSafe({
|
5
6
|
...useLocaleHead({ addSeoAttributes: true }).value,
|
6
7
|
bodyAttrs: {
|
7
8
|
class:
|
8
9
|
'bg-background-bright dark:bg-background-dark font-sans text-text-dark dark:text-text-bright',
|
9
10
|
},
|
10
|
-
...(appConfig.themeColor
|
11
|
-
? {
|
12
|
-
meta: [
|
13
|
-
{
|
14
|
-
content: appConfig.themeColor,
|
15
|
-
name: 'msapplication-TileColor',
|
16
|
-
},
|
17
|
-
{
|
18
|
-
content: appConfig.themeColor,
|
19
|
-
name: 'theme-color',
|
20
|
-
},
|
21
|
-
],
|
22
|
-
}
|
23
|
-
: {}),
|
24
11
|
})
|
25
12
|
|
26
|
-
|
27
|
-
|
28
|
-
|
13
|
+
useServerSeoMeta({
|
14
|
+
msapplicationTileColor: appConfig.vio.themeColor,
|
15
|
+
themeColor: appConfig.vio.themeColor,
|
16
|
+
titleTemplate: (titleChunk) => {
|
17
|
+
return titleChunk && titleChunk !== siteConfig.name
|
18
|
+
? `${titleChunk} ${siteConfig.titleSeparator} ${siteConfig.name}`
|
19
|
+
: siteConfig.name
|
20
|
+
},
|
21
|
+
...(appConfig.vio.seoMeta ? appConfig.vio.seoMeta : {}),
|
22
|
+
})
|
29
23
|
}
|
@@ -0,0 +1,17 @@
|
|
1
|
+
import { Dayjs } from 'dayjs'
|
2
|
+
|
3
|
+
export const useDateTime = () => {
|
4
|
+
const event = useRequestEvent()
|
5
|
+
const { $dayjs } = useNuxtApp()
|
6
|
+
const timezoneCookie = useCookie(TIMEZONE_COOKIE_NAME)
|
7
|
+
|
8
|
+
const timezoneHeader = event?.node.req.headers[TIMEZONE_HEADER_KEY]
|
9
|
+
const timezone =
|
10
|
+
timezoneHeader && !Array.isArray(timezoneHeader)
|
11
|
+
? timezoneHeader
|
12
|
+
: timezoneCookie.value || undefined
|
13
|
+
|
14
|
+
return (dateTime?: string | number | Dayjs | Date | null) =>
|
15
|
+
// @ts-ignore `tz` should be part of `$dayjs` (https://github.com/iamkun/dayjs/issues/2106)
|
16
|
+
$dayjs(dateTime).tz(timezone)
|
17
|
+
}
|
@@ -1,49 +1,21 @@
|
|
1
1
|
export const useFavicons = () => {
|
2
2
|
const appConfig = useAppConfig()
|
3
3
|
|
4
|
-
|
4
|
+
useServerHeadSafe({
|
5
5
|
link: [
|
6
6
|
{
|
7
|
-
href:
|
8
|
-
rel: 'apple-touch-icon',
|
9
|
-
sizes: '180x180',
|
10
|
-
},
|
11
|
-
{
|
12
|
-
href: '/assets/static/favicon/favicon-16x16.png?v=bOXMwoKlJr',
|
13
|
-
rel: 'icon',
|
14
|
-
sizes: '16x16',
|
15
|
-
type: 'image/png',
|
16
|
-
},
|
17
|
-
{
|
18
|
-
href: '/assets/static/favicon/favicon-32x32.png?v=bOXMwoKlJr',
|
19
|
-
rel: 'icon',
|
20
|
-
sizes: '32x32',
|
21
|
-
type: 'image/png',
|
22
|
-
},
|
23
|
-
{
|
24
|
-
href: '/favicon.ico',
|
25
|
-
rel: 'icon',
|
26
|
-
type: 'image/x-icon',
|
27
|
-
},
|
28
|
-
{
|
29
|
-
href: '/assets/static/favicon/site.webmanifest?v=bOXMwoKlJr',
|
7
|
+
href: `/assets/static/favicon/site.webmanifest?v=${CACHE_VERSION}`,
|
30
8
|
rel: 'manifest',
|
31
9
|
},
|
32
10
|
{
|
33
|
-
color: appConfig.themeColor,
|
34
|
-
href:
|
11
|
+
color: appConfig.vio.themeColor,
|
12
|
+
href: `/assets/static/favicon/safari-pinned-tab.svg?v=${CACHE_VERSION}`,
|
35
13
|
rel: 'mask-icon',
|
36
14
|
},
|
37
15
|
{
|
38
|
-
href:
|
16
|
+
href: `/favicon.ico?v=${CACHE_VERSION}`,
|
39
17
|
rel: 'shortcut icon',
|
40
18
|
},
|
41
19
|
],
|
42
|
-
meta: [
|
43
|
-
{
|
44
|
-
content: '/assets/static/favicon/browserconfig.xml?v=bOXMwoKlJr',
|
45
|
-
name: 'msapplication-config',
|
46
|
-
},
|
47
|
-
],
|
48
20
|
})
|
49
21
|
}
|
@@ -0,0 +1,17 @@
|
|
1
|
+
import { consola } from 'consola'
|
2
|
+
import Swal from 'sweetalert2'
|
3
|
+
import { Ref } from 'vue'
|
4
|
+
|
5
|
+
export const useFireError = () => {
|
6
|
+
const { t } = useI18n()
|
7
|
+
|
8
|
+
return ({ error }: { error: Error }, api?: Ref<any>) => {
|
9
|
+
Swal.fire({
|
10
|
+
icon: 'error',
|
11
|
+
title: t('globalStatusError'),
|
12
|
+
text: error.message,
|
13
|
+
})
|
14
|
+
api?.value.errors.push(error)
|
15
|
+
consola.error(error)
|
16
|
+
}
|
17
|
+
}
|
@@ -0,0 +1,21 @@
|
|
1
|
+
export const useGetServiceHref = () => {
|
2
|
+
const host = useHost()
|
3
|
+
const runtimeConfig = useRuntimeConfig()
|
4
|
+
|
5
|
+
return ({
|
6
|
+
isSsr = true,
|
7
|
+
name,
|
8
|
+
port,
|
9
|
+
}: {
|
10
|
+
isSsr?: boolean
|
11
|
+
name?: string
|
12
|
+
port?: number
|
13
|
+
}) =>
|
14
|
+
getServiceHref({
|
15
|
+
host,
|
16
|
+
isSsr,
|
17
|
+
name,
|
18
|
+
port,
|
19
|
+
stagingHost: runtimeConfig.public.stagingHost,
|
20
|
+
})
|
21
|
+
}
|
@@ -0,0 +1,21 @@
|
|
1
|
+
import { defu } from 'defu'
|
2
|
+
import type { ComputedRef } from 'vue'
|
3
|
+
|
4
|
+
export const useHeadDefault = ({
|
5
|
+
extension,
|
6
|
+
title,
|
7
|
+
}: {
|
8
|
+
extension?: Parameters<typeof useServerSeoMeta>[0]
|
9
|
+
title: string | ComputedRef<string>
|
10
|
+
}) => {
|
11
|
+
const attrs = useAttrs()
|
12
|
+
|
13
|
+
const defaults: Parameters<typeof useServerSeoMeta>[0] = {
|
14
|
+
msapplicationConfig: `/assets/static/favicon/browserconfig.xml?v=${CACHE_VERSION}`,
|
15
|
+
title,
|
16
|
+
twitterDescription: attrs['site-description'] as string,
|
17
|
+
twitterTitle: title,
|
18
|
+
}
|
19
|
+
|
20
|
+
useServerSeoMeta(defu(extension, defaults))
|
21
|
+
}
|
@@ -0,0 +1,23 @@
|
|
1
|
+
export const usePolyfills = () => {
|
2
|
+
const polyfills =
|
3
|
+
'https://polyfill.io/v3/polyfill.min.js?features=Promise&flags=gated'
|
4
|
+
|
5
|
+
useServerHead({
|
6
|
+
link: [
|
7
|
+
{
|
8
|
+
rel: 'preload',
|
9
|
+
href: polyfills,
|
10
|
+
crossorigin: 'anonymous',
|
11
|
+
as: 'script',
|
12
|
+
'data-testid': 'polyfill-preload',
|
13
|
+
},
|
14
|
+
],
|
15
|
+
script: [
|
16
|
+
{
|
17
|
+
src: polyfills,
|
18
|
+
crossorigin: 'anonymous',
|
19
|
+
'data-testid': 'polyfill-script',
|
20
|
+
},
|
21
|
+
],
|
22
|
+
})
|
23
|
+
}
|
@@ -0,0 +1,10 @@
|
|
1
|
+
import { ofetch } from 'ofetch'
|
2
|
+
|
3
|
+
export const useStrapiFetch = () => {
|
4
|
+
const getServiceHref = useGetServiceHref()
|
5
|
+
|
6
|
+
// TODO: switch back to $fetch (https://github.com/unjs/nitro/issues/470)
|
7
|
+
return ofetch.create({
|
8
|
+
baseURL: getServiceHref({ name: 'creal_strapi', port: 1337 }) + '/api',
|
9
|
+
})
|
10
|
+
}
|
package/error.vue
CHANGED
@@ -16,8 +16,11 @@ export interface Props {
|
|
16
16
|
error: NuxtError
|
17
17
|
}
|
18
18
|
const props = withDefaults(defineProps<Props>(), {})
|
19
|
+
const errorProp = toRef(() => props.error)
|
19
20
|
|
20
|
-
|
21
|
-
|
21
|
+
// initialization
|
22
|
+
useAppLayout()
|
23
|
+
useServerHeadSafe({
|
24
|
+
title: `${errorProp.value.statusCode} - ${errorProp.value.message}`,
|
22
25
|
})
|
23
26
|
</script>
|
package/locales/de.json
CHANGED
@@ -1,3 +1,9 @@
|
|
1
1
|
{
|
2
|
-
"
|
2
|
+
"globalPlaceholderUrl": "https://websei.te",
|
3
|
+
"globalStatusError": "Fehler",
|
4
|
+
"globalStatusLoading": "Lade...",
|
5
|
+
"globalValidationFailed": "Bitte überprüfe deine Eingaben 🙈",
|
6
|
+
"globalValidationFormatUrlHttps": "Muss mit \"https://\" beginnen",
|
7
|
+
"globalValidationLength": "Zu lang",
|
8
|
+
"globalValidationRequired": "Pflichtfeld"
|
3
9
|
}
|
package/locales/en.json
CHANGED
@@ -1,3 +1,9 @@
|
|
1
1
|
{
|
2
|
-
"
|
2
|
+
"globalPlaceholderUrl": "https://websi.te",
|
3
|
+
"globalStatusError": "Error",
|
4
|
+
"globalStatusLoading": "Loading...",
|
5
|
+
"globalValidationFailed": "Please check your input 🙈",
|
6
|
+
"globalValidationFormatUrlHttps": "Must start with \"https://\"",
|
7
|
+
"globalValidationLength": "Too long",
|
8
|
+
"globalValidationRequired": "Required"
|
3
9
|
}
|