Refactoring stores and templates pages to comp. api
This commit is contained in:
@@ -1,14 +1,14 @@
|
||||
<template>
|
||||
<div class="flex flex-col min-h-full">
|
||||
<breadcrumb :path="breadcrumbs">
|
||||
<breadcrumb :path="breadcrumbs" v-if="template">
|
||||
<template #left>
|
||||
<div v-if="canEditTemplate" class="ml-5">
|
||||
<v-button color="gray" size="small" @click.prevent="showFormTemplateModal=true">
|
||||
Edit Template
|
||||
</v-button>
|
||||
<form-template-modal v-if="form" :form="form" :template="template" :show="showFormTemplateModal"
|
||||
@close="showFormTemplateModal=false"
|
||||
/>
|
||||
<!-- <form-template-modal v-if="form" :form="form" :template="template" :show="showFormTemplateModal"-->
|
||||
<!-- @close="showFormTemplateModal=false"-->
|
||||
<!-- />-->
|
||||
</div>
|
||||
</template>
|
||||
<template #right>
|
||||
@@ -25,10 +25,7 @@
|
||||
</template>
|
||||
</breadcrumb>
|
||||
|
||||
<div v-if="templatesLoading" class="text-center my-4">
|
||||
<Loader class="h-6 w-6 text-nt-blue mx-auto"/>
|
||||
</div>
|
||||
<p v-else-if="template === null || !template" class="text-center my-4">
|
||||
<p v-if="template === null || !template" class="text-center my-4">
|
||||
We could not find this template.
|
||||
</p>
|
||||
<template v-else>
|
||||
@@ -48,9 +45,9 @@
|
||||
<p class="mt-2 text-lg font-normal text-gray-600">
|
||||
{{ cleanQuotes(template.short_description) }}
|
||||
</p>
|
||||
<template-tags :slug="template.slug" :display-all="true"
|
||||
class="flex flex-wrap items-center justify-center gap-3 mt-4 md:justify-start"
|
||||
/>
|
||||
<!-- <template-tags :slug="template.slug" :display-all="true"-->
|
||||
<!-- class="flex flex-wrap items-center justify-center gap-3 mt-4 md:justify-start"-->
|
||||
<!-- />-->
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -119,7 +116,8 @@
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section v-if="template.related_templates.length > 0" class="py-12 bg-white border-t border-gray-200 sm:py-16">
|
||||
<section v-if="relatedTemplates && relatedTemplates.length > 0"
|
||||
class="py-12 bg-white border-t border-gray-200 sm:py-16">
|
||||
<div class="px-4 mx-auto sm:px-6 lg:px-8 max-w-7xl">
|
||||
<div class="flex items-center justify-between">
|
||||
<h4 class="text-xl font-bold tracking-tight text-gray-900 sm:text-2xl">
|
||||
@@ -131,7 +129,7 @@
|
||||
</div>
|
||||
|
||||
<div class="grid grid-cols-1 gap-8 mt-8 sm:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4 sm:gap-y-12">
|
||||
<single-template v-for="related in template.related_templates" :key="related.id" :template="related"/>
|
||||
<single-template v-for="related in relatedTemplates" :key="related.id" :template="related"/>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
@@ -196,108 +194,93 @@
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import Form from 'vform'
|
||||
<script setup>
|
||||
import {computed} from 'vue'
|
||||
import OpenCompleteForm from '../../components/open/forms/OpenCompleteForm.vue'
|
||||
import Breadcrumb from '~/components/global/Breadcrumb.vue'
|
||||
import SeoMeta from '../../mixins/seo-meta.js'
|
||||
import TemplateTags from '../../components/pages/templates/TemplateTags.vue'
|
||||
import SingleTemplate from '../../components/pages/templates/SingleTemplate.vue'
|
||||
import FormTemplateModal from '../../components/open/forms/components/templates/FormTemplateModal.vue'
|
||||
import {fetchTemplate} from "~/stores/templates.js";
|
||||
|
||||
export default {
|
||||
const authStore = useAuthStore()
|
||||
const templatesStore = useTemplatesStore()
|
||||
|
||||
components: {Breadcrumb, OpenCompleteForm, TemplateTags, SingleTemplate, FormTemplateModal},
|
||||
mixins: [SeoMeta],
|
||||
const route = useRoute()
|
||||
const slug = computed(() => route.params.slug)
|
||||
|
||||
setup() {
|
||||
const authStore = useAuthStore()
|
||||
const templatesStore = useTemplatesStore()
|
||||
const template = computed(() => templatesStore.getByKey(slug.value))
|
||||
const form = computed(() => template.value.structure)
|
||||
|
||||
const route = useRoute()
|
||||
const slug = computed(() => route.params.slug)
|
||||
if (slug) {
|
||||
templatesStore.loadTemplate(slug)
|
||||
}
|
||||
|
||||
|
||||
return {
|
||||
templatesStore,
|
||||
authenticated: computed(() => authStore.check),
|
||||
user: computed(() => authStore.user),
|
||||
templatesLoading: computed(() => templatesStore.loading)
|
||||
}
|
||||
},
|
||||
|
||||
data() {
|
||||
return {
|
||||
showFormTemplateModal: false
|
||||
}
|
||||
},
|
||||
|
||||
mounted() {
|
||||
},
|
||||
|
||||
methods: {
|
||||
cleanQuotes(str) {
|
||||
// Remove starting and ending quotes if any
|
||||
return (str) ? str.replace(/^"/, '').replace(/"$/, '') : ''
|
||||
},
|
||||
copyTemplateUrl() {
|
||||
const str = this.template.share_url
|
||||
const el = document.createElement('textarea')
|
||||
el.value = str
|
||||
document.body.appendChild(el)
|
||||
el.select()
|
||||
document.execCommand('copy')
|
||||
document.body.removeChild(el)
|
||||
this.alertSuccess('Copied!')
|
||||
}
|
||||
},
|
||||
|
||||
computed: {
|
||||
breadcrumbs() {
|
||||
if (!this.template) {
|
||||
return [{route: {name: 'templates'}, label: 'Templates'}]
|
||||
}
|
||||
return [{route: {name: 'templates'}, label: 'Templates'}, {label: this.template.name}]
|
||||
},
|
||||
template() {
|
||||
return this.templatesStore.getBySlug(this.$route.params.slug)
|
||||
},
|
||||
form() {
|
||||
return this.template ? new Form(this.template.structure) : null
|
||||
},
|
||||
canEditTemplate() {
|
||||
return this.user && this.template && (this.user.admin || this.user.template_editor || this.template.creator_id === this.user.id)
|
||||
},
|
||||
metaTitle() {
|
||||
return this.template ? this.template.name : 'Form Template'
|
||||
},
|
||||
metaDescription() {
|
||||
if (!this.template) return null
|
||||
// take the first 140 characters of the description
|
||||
return this.template.short_description?.substring(0, 140) + '... | Customize any template and create your own form in minutes.'
|
||||
},
|
||||
metaImage() {
|
||||
if (!this.template) return null
|
||||
return this.template.image_url
|
||||
},
|
||||
metaTags() {
|
||||
if (!this.template) {
|
||||
return [];
|
||||
}
|
||||
return this.template.publicly_listed ? [] : [{name: 'robots', content: 'noindex'}]
|
||||
},
|
||||
createFormWithTemplateUrl() {
|
||||
if (this.authenticated) {
|
||||
return '/forms/create?template=' + this.template?.slug
|
||||
}
|
||||
return '/forms/create/guest?template=' + this.template?.slug
|
||||
}
|
||||
}
|
||||
// Fetch the template
|
||||
if (!template.value) {
|
||||
const {data} = await fetchTemplate(slug.value)
|
||||
templatesStore.save(data.value)
|
||||
}
|
||||
|
||||
// Fetch related templates
|
||||
const {data: relatedTemplatesData} = await useAsyncData('related-templates', () => {
|
||||
return Promise.all(template.value.related_templates.map((slug) => {
|
||||
if (templatesStore.getByKey(slug)) {
|
||||
return Promise.resolve(templatesStore.getByKey(slug))
|
||||
}
|
||||
return fetchTemplate(slug).then((res) => res.data.value)
|
||||
}))
|
||||
})
|
||||
templatesStore.save(relatedTemplatesData.value)
|
||||
|
||||
// State
|
||||
const showFormTemplateModal = ref(false)
|
||||
|
||||
// Computed
|
||||
const breadcrumbs = computed(() => {
|
||||
if (!template.value) {
|
||||
return [{route: {name: 'templates'}, label: 'Templates'}]
|
||||
}
|
||||
return [{route: {name: 'templates'}, label: 'Templates'}, {label: template.name}]
|
||||
})
|
||||
const relatedTemplates = computed(() => templatesStore.getByKey(template?.value?.related_templates))
|
||||
const canEditTemplate = computed(() => authStore.authenticated && template.value && (authStore.user.admin || authStore.user.template_editor || template.creator_id === authStore.user.id))
|
||||
const createFormWithTemplateUrl = computed(() => {
|
||||
if (authStore.authenticated) {
|
||||
return '/forms/create?template=' + template?.value?.slug
|
||||
}
|
||||
return '/forms/create/guest?template=' + template?.value?.slug
|
||||
})
|
||||
|
||||
// methods
|
||||
const cleanQuotes = (str) => {
|
||||
// Remove starting and ending quotes if any
|
||||
return (str) ? str.replace(/^"/, '').replace(/"$/, '') : ''
|
||||
}
|
||||
|
||||
const copyTemplateUrl = () => {
|
||||
const str = template.value.share_url
|
||||
const el = document.createElement('textarea')
|
||||
el.value = str
|
||||
document.body.appendChild(el)
|
||||
el.select()
|
||||
document.execCommand('copy')
|
||||
document.body.removeChild(el)
|
||||
this.alertSuccess('Copied!')
|
||||
}
|
||||
|
||||
// metaTitle() {
|
||||
// return this.template ? this.template.name : 'Form Template'
|
||||
// },
|
||||
// metaDescription() {
|
||||
// if (!this.template) return null
|
||||
// // take the first 140 characters of the description
|
||||
// return this.template.short_description?.substring(0, 140) + '... | Customize any template and create your own form in minutes.'
|
||||
// },
|
||||
// metaImage() {
|
||||
// if (!this.template) return null
|
||||
// return this.template.image_url
|
||||
// },
|
||||
// metaTags() {
|
||||
// if (!this.template) {
|
||||
// return [];
|
||||
// }
|
||||
// return this.template.publicly_listed ? [] : [{name: 'robots', content: 'noindex'}]
|
||||
// },
|
||||
</script>
|
||||
|
||||
<style lang='scss'>
|
||||
|
||||
@@ -13,32 +13,28 @@
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<templates-list :templates="templates" :loading="loading" />
|
||||
<templates-list :templates="templates"/>
|
||||
|
||||
<open-form-footer class="mt-8 border-t"/>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import SeoMeta from '../../mixins/seo-meta.js'
|
||||
import {useTemplatesStore} from "~/stores/templates.js";
|
||||
<script setup>
|
||||
import {fetchAllTemplates} from "~/stores/templates.js";
|
||||
|
||||
export default {
|
||||
// props: {
|
||||
// metaTitle: { type: String, default: 'Templates' },
|
||||
// metaDescription: { type: String, default: 'Our collection of beautiful templates to create your own forms!' }
|
||||
// },
|
||||
|
||||
mixins: [SeoMeta],
|
||||
const templatesStore = useTemplatesStore()
|
||||
|
||||
props: {
|
||||
metaTitle: { type: String, default: 'Templates' },
|
||||
metaDescription: { type: String, default: 'Our collection of beautiful templates to create your own forms!' }
|
||||
},
|
||||
|
||||
setup() {
|
||||
const templatesStore = useTemplatesStore()
|
||||
templatesStore.loadAll()
|
||||
return {
|
||||
templates: templatesStore.content,
|
||||
loading: templatesStore.loading
|
||||
}
|
||||
},
|
||||
if (!templatesStore.allLoaded) {
|
||||
templatesStore.startLoading()
|
||||
const {data} = await fetchAllTemplates()
|
||||
templatesStore.set(data.value)
|
||||
templatesStore.allLoaded = true
|
||||
}
|
||||
|
||||
const templates = computed(() => templatesStore.getAll)
|
||||
</script>
|
||||
|
||||
Reference in New Issue
Block a user