B8f7a improve templates pages for seo (#5)
* Templates * access templates without login also * Set required on UI * Improve templates pages for SEO * test case for Templates * Refactor SitemapController * Cosmetic changes to templates Co-authored-by: Julien Nahum <jhumanj@MacBook-Pro-de-Julien.local>
This commit is contained in:
@@ -224,7 +224,7 @@ export default {
|
||||
},
|
||||
init() {
|
||||
if (this.$route.name === 'forms.create') { // Set Default fields
|
||||
this.formFields = this.getDefaultFields()
|
||||
this.formFields = (this.form.properties.length > 0) ? clonedeep(this.form.properties): this.getDefaultFields()
|
||||
} else {
|
||||
this.formFields = clonedeep(this.form.properties).map((field) => {
|
||||
// Add more field properties
|
||||
|
||||
@@ -53,7 +53,6 @@ export default {
|
||||
},
|
||||
watch: {
|
||||
form () {
|
||||
debugger
|
||||
if(!this.form){
|
||||
return
|
||||
}
|
||||
|
||||
@@ -21,6 +21,13 @@
|
||||
<!-- Pricing-->
|
||||
<!-- </router-link>-->
|
||||
<!-- </li>-->
|
||||
<li>
|
||||
<router-link :to="{name:'templates'}"
|
||||
class="text-gray-600 dark:text-gray-400 transition-colors duration-300 hover:text-nt-blue"
|
||||
>
|
||||
Templates
|
||||
</router-link>
|
||||
</li>
|
||||
<li>
|
||||
<a target="_blank" :href="helpUrl"
|
||||
class="text-gray-600 dark:text-gray-400 transition-colors duration-300 hover:text-nt-blue"
|
||||
|
||||
64
resources/js/components/pages/forms/CreateTemplateModal.vue
Normal file
64
resources/js/components/pages/forms/CreateTemplateModal.vue
Normal file
@@ -0,0 +1,64 @@
|
||||
<template>
|
||||
<modal :show="show" @close="$emit('close')">
|
||||
<form @submit.prevent="createTemplate" @keydown="templateForm.onKeydown($event)">
|
||||
<div class="-m-6">
|
||||
<div class="p-6">
|
||||
<h2 class="text-nt-blue text-3xl font-bold mb-6">
|
||||
Create template
|
||||
</h2>
|
||||
<p>
|
||||
New template will be create from your form <span class="font-semibold">{{form.title}}</span>.
|
||||
Template will be public for all to create form quickly.
|
||||
</p>
|
||||
</div>
|
||||
<div class="border-t py-4 px-6">
|
||||
<text-input name="name" :form="templateForm" class="mt-4" label="Title" :required="true" />
|
||||
<text-input name="slug" :form="templateForm" class="mt-4" label="Slug" :required="true" />
|
||||
<rich-text-area-input name="description" :form="templateForm" class="mt-4" label="Description" :required="true" />
|
||||
<text-input name="image_url" :form="templateForm" class="mt-4" label="Image" :required="true" />
|
||||
<questions-editor name="questions" :form="templateForm" class="mt-4" label="Frequently asked questions" />
|
||||
</div>
|
||||
<div class="flex justify-end mt-4 pb-5 px-6">
|
||||
<v-button class="mr-2" :loading="templateForm.busy">Create</v-button>
|
||||
<v-button color="gray" shade="light" @click.prevent="$emit('close')">Close</v-button>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</modal>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import Form from 'vform'
|
||||
import QuestionsEditor from '../../templates/QuestionsEditor';
|
||||
|
||||
export default {
|
||||
name: 'CreateTemplateModal',
|
||||
components: { QuestionsEditor },
|
||||
props: {
|
||||
show: { type: Boolean, required: true },
|
||||
form: { type: Object, required: true }
|
||||
},
|
||||
|
||||
data: () => ({
|
||||
templateForm: new Form({
|
||||
name: '',
|
||||
slug: '',
|
||||
description: '',
|
||||
image_url: '',
|
||||
})
|
||||
}),
|
||||
|
||||
computed: {},
|
||||
|
||||
methods: {
|
||||
async createTemplate() {
|
||||
this.templateForm.form = this.form
|
||||
await this.templateForm.post('/api/templates').then((response) => {
|
||||
this.alertSuccess('Template was successfully created.')
|
||||
this.$emit('close')
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
80
resources/js/components/templates/QuestionsEditor.vue
Normal file
80
resources/js/components/templates/QuestionsEditor.vue
Normal file
@@ -0,0 +1,80 @@
|
||||
<template>
|
||||
<div :class="wrapperClass">
|
||||
<label v-if="label" :for="id?id:name"
|
||||
:class="[theme.default.label,{'uppercase text-xs':uppercaseLabels, 'text-sm':!uppercaseLabels}]"
|
||||
>
|
||||
{{ label }}
|
||||
<span v-if="required" class="text-red-500 required-dot">*</span>
|
||||
</label>
|
||||
|
||||
<loader v-if="loading" key="loader" class="h-6 w-6 text-nt-blue mx-auto" />
|
||||
<div v-else class="my-3">
|
||||
<div v-for="(questionForm, quesKey) in allQuestions" :key="quesKey" class="bg-gray-100 p-2 mb-4">
|
||||
<v-button color="red" size="small" nativeType="button" class="text-right mb-2" @click.prevent="onRemove(quesKey)">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" class="h-6 w-6" fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 7l-.867 12.142A2 2 0 0116.138 21H7.862a2 2 0 01-1.995-1.858L5 7m5 4v6m4-6v6m1-10V4a1 1 0 00-1-1h-4a1 1 0 00-1 1v3M4 7h16" />
|
||||
</svg>
|
||||
</v-button>
|
||||
<text-input name="question" :form="questionForm" placeholder="Question title" />
|
||||
<rich-text-area-input name="answer" :form="questionForm" class="mt-4" placeholder="Question response" />
|
||||
</div>
|
||||
<v-button v-if="addNew" color="green" size="small" nativeType="button" class="mt-2 flex" @click.prevent="onAdd">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" class="h-6 w-6 mr-1" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 9v6m3-3H9m12 0a9 9 0 11-18 0 9 9 0 0118 0z" />
|
||||
</svg>
|
||||
Add New
|
||||
</v-button>
|
||||
</div>
|
||||
|
||||
<small v-if="help" :class="theme.SelectInput.help">
|
||||
<slot name="help">{{ help }}</slot>
|
||||
</small>
|
||||
<has-error v-if="hasValidation" :form="form" :field="name" />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import inputMixin from '~/mixins/forms/input'
|
||||
import Form from 'vform'
|
||||
|
||||
export default {
|
||||
name: 'QuestionsEditor',
|
||||
mixins: [inputMixin],
|
||||
|
||||
props: {
|
||||
loading: { type: Boolean, default: false },
|
||||
addNew: { type: Boolean, default: true }
|
||||
},
|
||||
data () {
|
||||
return {
|
||||
allQuestions: [new Form({
|
||||
question: '',
|
||||
answer: '',
|
||||
})]
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
allQuestions: {
|
||||
deep: true,
|
||||
handler () {
|
||||
this.compVal = this.allQuestions.map((ques) => {
|
||||
return ques.data()
|
||||
})
|
||||
}
|
||||
}
|
||||
},
|
||||
computed: { },
|
||||
methods: {
|
||||
onAdd() {
|
||||
this.allQuestions.push(new Form({
|
||||
question: '',
|
||||
answer: '',
|
||||
}))
|
||||
},
|
||||
onRemove(key){
|
||||
this.allQuestions.splice(key, 1)
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
Reference in New Issue
Block a user