opnform/resources/js/components/App.vue

143 lines
4.3 KiB
Vue

<template>
<div id="app" class="bg-white dark:bg-notion-dark">
<loading v-show="!isIframe" ref="loading" />
<!-- <hotjar />-->
<amplitude />
<crisp />
<!-- <llamafi />-->
<transition enter-active-class="linear duration-200 overflow-hidden"
enter-class="max-h-0"
enter-to-class="max-h-screen"
leave-active-class="linear duration-200 overflow-hidden"
leave-class="max-h-screen"
leave-to-class="max-h-0"
>
<div v-if="announcement && !isIframe" class="bg-nt-blue text-white text-center p-3 relative">
<a class="text-white font-semibold" href="" target="_blank">🚨
OpnForm beta is over 🚨</a>
<div role="button" class="text-white absolute right-0 top-0 p-3 cursor-pointer" @click="announcement=false">
<svg xmlns="http://www.w3.org/2000/svg" class="h-6 w-6" viewBox="0 0 20 20" fill="currentColor">
<path fill-rule="evenodd"
d="M10 18a8 8 0 100-16 8 8 0 000 16zM8.707 7.293a1 1 0 00-1.414 1.414L8.586 10l-1.293 1.293a1 1 0 101.414 1.414L10 11.414l1.293 1.293a1 1 0 001.414-1.414L11.414 10l1.293-1.293a1 1 0 00-1.414-1.414L10 8.586 8.707 7.293z"
clip-rule="evenodd"
/>
</svg>
</div>
</div>
</transition>
<transition name="page" mode="out-in">
<component :is="layout" v-if="layout" />
</transition>
<portal-target name="modals" multiple />
<stop-impersonation />
</div>
</template>
<script>
import Loading from './Loading'
import { mapState } from 'vuex'
import Hotjar from './service/Hotjar'
import Amplitude from './service/Amplitude'
import Crisp from './service/Crisp'
import StopImpersonation from './pages/StopImpersonation'
// Load layout components dynamically.
const requireContext = require.context('~/layouts', false, /.*\.vue$/)
const layouts = requireContext.keys()
.map(file =>
[file.replace(/(^.\/)|(\.vue$)/g, ''), requireContext(file)]
)
.reduce((components, [name, component]) => {
components[name] = component.default || component
return components
}, {})
export default {
el: '#app',
components: {
StopImpersonation,
Crisp,
Amplitude,
Hotjar,
Loading
},
data: () => ({
layout: null,
defaultLayout: 'default',
announcement: false,
alert: {
type: null,
autoClose: 0,
message: '',
confirmationProceed: null,
confirmationCancel: null
}
}),
metaInfo () {
const { appName } = window.config
const description = "Create beautiful forms for free. Unlimited fields, unlimited submissions. It's free and it takes less than 1 minute to create your first form."
return {
title: appName,
titleTemplate: `%s · ${appName}`,
meta: [
{ vmid: 'description', name: 'description', content: description },
{ vmid: 'og:title', property: 'og:title', content: appName },
{ vmid: 'og:description', property: 'og:description', content: description },
{ vmid: 'og:image', property: 'og:image', content: '/img/social-preview.png' },
{ vmid: 'twitter:title', property: 'twitter:title', content: appName },
{ vmid: 'twitter:description', property: 'twitter:description', content: description },
{ vmid: 'twitter:image', property: 'twitter:image', content: '/img/social-preview.png' },
{ vmid: 'twitter:card', property: 'twitter:card', content: 'summary_large_image' }
]
}
},
mounted () {
this.$loading = this.$refs.loading
// Dark mode
if (window.localStorage.getItem('opnform-dark-mode-enabled') === '1' || window.matchMedia('(prefers-color-scheme: dark)').matches) {
document.body.classList.add('dark')
}
},
methods: {
/**
* Set the application layout.
*
* @param {String} layout
*/
setLayout (layout) {
if (!layout || !layouts[layout]) {
layout = this.defaultLayout
}
this.layout = layouts[layout]
},
workspaceAdded () {
this.$router.push({ name: 'home' })
}
},
computed: {
isIframe () {
return window.location !== window.parent.location || window.frameElement
},
isOnboardingPage () {
return this.$route.name === 'onboarding'
}
},
watch: {
}
}
</script>