Working on form/show and editor
This commit is contained in:
parent
56e533581c
commit
d93b696b05
|
@ -11,7 +11,7 @@
|
||||||
:class="maxWidthClass"
|
:class="maxWidthClass"
|
||||||
>
|
>
|
||||||
<div v-if="closeable" class="absolute top-4 right-4">
|
<div v-if="closeable" class="absolute top-4 right-4">
|
||||||
<button class="text-gray-500 hover:text-gray-900 cursor-pointer" @click.prevent="close">
|
<button class="text-gray-500 hover:text-gray-900 cursor-pointer" @click="close()">
|
||||||
<svg class="h-6 w-6" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
<svg class="h-6 w-6" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
<path d="M18 6L6 18M6 6L18 18" stroke="currentColor" stroke-width="2" stroke-linecap="round"
|
<path d="M18 6L6 18M6 6L18 18" stroke="currentColor" stroke-width="2" stroke-linecap="round"
|
||||||
stroke-linejoin="round"
|
stroke-linejoin="round"
|
||||||
|
|
|
@ -74,7 +74,9 @@ export default {
|
||||||
window.removeEventListener('resize', this.calcDimensions)
|
window.removeEventListener('resize', this.calcDimensions)
|
||||||
// Cleanup when the component is unmounted.
|
// Cleanup when the component is unmounted.
|
||||||
this.wrapObserver.disconnect()
|
this.wrapObserver.disconnect()
|
||||||
|
if (this.scrollContainerObserver) {
|
||||||
this.scrollContainerObserver.disconnect()
|
this.scrollContainerObserver.disconnect()
|
||||||
|
}
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
async calcDimensions () {
|
async calcDimensions () {
|
||||||
|
@ -88,6 +90,7 @@ export default {
|
||||||
},
|
},
|
||||||
// Check if shadows are needed.
|
// Check if shadows are needed.
|
||||||
toggleShadow () {
|
toggleShadow () {
|
||||||
|
if (!this.$refs.scrollContainer) return
|
||||||
const hasHorizontalScrollbar =
|
const hasHorizontalScrollbar =
|
||||||
this.$refs.scrollContainer.clientWidth <
|
this.$refs.scrollContainer.clientWidth <
|
||||||
this.$refs.scrollContainer.scrollWidth
|
this.$refs.scrollContainer.scrollWidth
|
||||||
|
|
|
@ -200,7 +200,7 @@ export default {
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
helpUrl: () => this.$config.links.help
|
helpUrl: () => useAppConfig().links.help
|
||||||
},
|
},
|
||||||
|
|
||||||
watch: {},
|
watch: {},
|
||||||
|
@ -217,9 +217,9 @@ export default {
|
||||||
methods: {
|
methods: {
|
||||||
displayFormModificationAlert (responseData) {
|
displayFormModificationAlert (responseData) {
|
||||||
if (responseData.form && responseData.form.cleanings && Object.keys(responseData.form.cleanings).length > 0) {
|
if (responseData.form && responseData.form.cleanings && Object.keys(responseData.form.cleanings).length > 0) {
|
||||||
this.alertWarning(responseData.message)
|
// this.alertWarning(responseData.message)
|
||||||
} else {
|
} else {
|
||||||
this.alertSuccess(responseData.message)
|
// this.alertSuccess(responseData.message)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
openCrisp () {
|
openCrisp () {
|
||||||
|
@ -244,12 +244,13 @@ export default {
|
||||||
this.updateFormLoading = true
|
this.updateFormLoading = true
|
||||||
this.validationErrorResponse = null
|
this.validationErrorResponse = null
|
||||||
this.form.put('/open/forms/{id}/'.replace('{id}', this.form.id)).then((data) => {
|
this.form.put('/open/forms/{id}/'.replace('{id}', this.form.id)).then((data) => {
|
||||||
this.formsStore.addOrUpdate(data.form)
|
this.formsStore.save(data.form)
|
||||||
this.$emit('on-save')
|
this.$emit('on-save')
|
||||||
this.$router.push({ name: 'forms-slug-show', params: { slug: this.form.slug } })
|
this.$router.push({ name: 'forms-slug-show-share', params: { slug: this.form.slug } })
|
||||||
this.amplitude.logEvent('form_saved', { form_id: this.form.id, form_slug: this.form.slug })
|
this.amplitude.logEvent('form_saved', { form_id: this.form.id, form_slug: this.form.slug })
|
||||||
this.displayFormModificationAlert(data)
|
this.displayFormModificationAlert(data)
|
||||||
}).catch((error) => {
|
}).catch((error) => {
|
||||||
|
console.log(error)
|
||||||
if (error.response.status === 422) {
|
if (error.response.status === 422) {
|
||||||
this.validationErrorResponse = error.response.data
|
this.validationErrorResponse = error.response.data
|
||||||
this.showValidationErrors()
|
this.showValidationErrors()
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
<template>
|
<template>
|
||||||
<div>
|
<div>
|
||||||
<v-button v-if="formFields && formFields.length > 8"
|
<v-button v-if="form.properties && form.properties.length > 8"
|
||||||
class="w-full mb-3" color="light-gray"
|
class="w-full mb-3" color="light-gray"
|
||||||
@click="openAddFieldSidebar"
|
@click="openAddFieldSidebar"
|
||||||
>
|
>
|
||||||
|
@ -14,7 +14,7 @@
|
||||||
Add block
|
Add block
|
||||||
</v-button>
|
</v-button>
|
||||||
|
|
||||||
<draggable v-model="formFields"
|
<draggable v-model="form.properties"
|
||||||
item-key="id"
|
item-key="id"
|
||||||
class="bg-white overflow-hidden dark:bg-notion-dark-light rounded-md w-full mx-auto border transition-colors"
|
class="bg-white overflow-hidden dark:bg-notion-dark-light rounded-md w-full mx-auto border transition-colors"
|
||||||
ghost-class="bg-gray-50"
|
ghost-class="bg-gray-50"
|
||||||
|
@ -23,7 +23,7 @@
|
||||||
>
|
>
|
||||||
<template #item="{element, index}">
|
<template #item="{element, index}">
|
||||||
<div class="w-full mx-auto transition-colors"
|
<div class="w-full mx-auto transition-colors"
|
||||||
:class="{'bg-gray-100 dark:bg-gray-800':element.hidden,'bg-white dark:bg-notion-dark-light':!element.hidden && !element.type==='nf-page-break', 'border-b': (index!== formFields.length -1), 'bg-blue-50 dark:bg-blue-900':element && element.type==='nf-page-break'}"
|
:class="{'bg-gray-100 dark:bg-gray-800':element.hidden,'bg-white dark:bg-notion-dark-light':!element.hidden && !element.type==='nf-page-break', 'border-b': (index!== form.properties.length -1), 'bg-blue-50 dark:bg-blue-900':element && element.type==='nf-page-break'}"
|
||||||
>
|
>
|
||||||
<div v-if="element" class="flex items-center space-x-1 group py-2 pr-4 relative">
|
<div v-if="element" class="flex items-center space-x-1 group py-2 pr-4 relative">
|
||||||
<!-- Drag handler -->
|
<!-- Drag handler -->
|
||||||
|
@ -186,51 +186,23 @@ export default {
|
||||||
const workingFormStore = useWorkingFormStore()
|
const workingFormStore = useWorkingFormStore()
|
||||||
return {
|
return {
|
||||||
route: useRoute(),
|
route: useRoute(),
|
||||||
workingFormStore
|
workingFormStore,
|
||||||
|
form: storeToRefs(workingFormStore).content,
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
data () {
|
data () {
|
||||||
return {
|
return {
|
||||||
formFields: [],
|
|
||||||
removing: null
|
removing: null
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
computed: {
|
beforeMount() {
|
||||||
form: {
|
console.log('beforemounted formfields editor with', this.form)
|
||||||
get () {
|
|
||||||
return this.workingFormStore.content
|
|
||||||
},
|
|
||||||
/* We add a setter */
|
|
||||||
set (value) {
|
|
||||||
this.workingFormStore.set(value)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
watch: {
|
|
||||||
formFields: {
|
|
||||||
deep: true,
|
|
||||||
handler () {
|
|
||||||
this.form.properties = this.formFields
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
'form.properties': {
|
|
||||||
deep: true,
|
|
||||||
handler () {
|
|
||||||
// If different, then update
|
|
||||||
if (this.form.properties.length !== this.formFields.length ||
|
|
||||||
JSON.stringify(this.form.properties) !== JSON.stringify(this.formFields)) {
|
|
||||||
this.formFields = clonedeep(this.form.properties)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
},
|
},
|
||||||
|
|
||||||
mounted () {
|
mounted () {
|
||||||
|
console.log('mounted formfields editor with', this.form)
|
||||||
this.init()
|
this.init()
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -279,9 +251,11 @@ export default {
|
||||||
},
|
},
|
||||||
init () {
|
init () {
|
||||||
if (this.route.name === 'forms-create' || this.route.name === 'forms-create-guest') { // Set Default fields
|
if (this.route.name === 'forms-create' || this.route.name === 'forms-create-guest') { // Set Default fields
|
||||||
this.formFields = (this.form.properties.length > 0) ? clonedeep(this.form.properties) : this.getDefaultFields()
|
if (!this.form.properties) {
|
||||||
|
this.form.properties = this.getDefaultFields()
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
this.formFields = clonedeep(this.form.properties).map((field) => {
|
this.form.properties = this.form.properties.map((field) => {
|
||||||
// Add more field properties
|
// Add more field properties
|
||||||
field.placeholder = field.placeholder || null
|
field.placeholder = field.placeholder || null
|
||||||
field.prefill = field.prefill || null
|
field.prefill = field.prefill || null
|
||||||
|
@ -291,7 +265,6 @@ export default {
|
||||||
return field
|
return field
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
this.form.properties = this.formFields
|
|
||||||
},
|
},
|
||||||
generateUUID () {
|
generateUUID () {
|
||||||
let d = new Date().getTime()// Timestamp
|
let d = new Date().getTime()// Timestamp
|
||||||
|
@ -324,9 +297,7 @@ export default {
|
||||||
this.workingFormStore.openSettingsForField(index)
|
this.workingFormStore.openSettingsForField(index)
|
||||||
},
|
},
|
||||||
removeBlock (blockIndex) {
|
removeBlock (blockIndex) {
|
||||||
const newFields = clonedeep(this.formFields)
|
this.form.properties.splice(blockIndex, 1)
|
||||||
newFields.splice(blockIndex, 1)
|
|
||||||
this.formFields = newFields
|
|
||||||
this.closeSidebar()
|
this.closeSidebar()
|
||||||
},
|
},
|
||||||
closeSidebar () {
|
closeSidebar () {
|
||||||
|
|
|
@ -23,19 +23,27 @@
|
||||||
<h4 class="font-bold mb-2">
|
<h4 class="font-bold mb-2">
|
||||||
Form Fields
|
Form Fields
|
||||||
</h4>
|
</h4>
|
||||||
<div v-for="field in properties" :key="field.id" class="p-2 border">
|
<div class="border border-gray-300 rounded-md">
|
||||||
|
<div v-for="(field,index) in properties" :key="field.id" class="p-2 border-gray-300 flex items-center" :class="{'border-t':index!=0}">
|
||||||
|
<p class="flex-grow truncate">
|
||||||
{{ field.name }}
|
{{ field.name }}
|
||||||
|
</p>
|
||||||
<v-switch v-model="displayColumns[field.id]" class="float-right" @update:model-value="onChangeDisplayColumns" />
|
<v-switch v-model="displayColumns[field.id]" class="float-right" @update:model-value="onChangeDisplayColumns" />
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<template v-if="removed_properties.length > 0">
|
<template v-if="removed_properties.length > 0">
|
||||||
<h4 class="font-bold mb-2 mt-4">
|
<h4 class="font-bold mb-2 mt-4">
|
||||||
Removed Fields
|
Removed Fields
|
||||||
</h4>
|
</h4>
|
||||||
<div v-for="field in removed_properties" :key="field.id" class="p-2 border">
|
<div class="border border-gray-300 rounded-md">
|
||||||
|
<div v-for="(field,index) in removed_properties" :key="field.id" class="p-2 border-gray-300 flex items-center" :class="{'border-t':index!=0}">
|
||||||
|
<p class="flex-grow truncate">
|
||||||
{{ field.name }}
|
{{ field.name }}
|
||||||
|
</p>
|
||||||
<v-switch v-model="displayColumns[field.id]" class="float-right" @update:model-value="onChangeDisplayColumns" />
|
<v-switch v-model="displayColumns[field.id]" class="float-right" @update:model-value="onChangeDisplayColumns" />
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
</template>
|
</template>
|
||||||
</div>
|
</div>
|
||||||
</modal>
|
</modal>
|
||||||
|
@ -80,18 +88,15 @@
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import axios from 'axios'
|
|
||||||
import Fuse from 'fuse.js'
|
import Fuse from 'fuse.js'
|
||||||
import Form from 'vform'
|
import Form from 'vform'
|
||||||
import { useWorkingFormStore } from '../../../../stores/working_form'
|
|
||||||
import ScrollShadow from '~/components/global/ScrollShadow.vue'
|
|
||||||
import OpenTable from '../../tables/OpenTable.vue'
|
|
||||||
import clonedeep from 'clone-deep'
|
import clonedeep from 'clone-deep'
|
||||||
import VSwitch from '../../../forms/components/VSwitch.vue'
|
import VSwitch from '../../../forms/components/VSwitch.vue'
|
||||||
|
import OpenTable from '../../tables/OpenTable.vue'
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'FormSubmissions',
|
name: 'FormSubmissions',
|
||||||
components: { ScrollShadow, OpenTable, VSwitch },
|
components: { OpenTable, VSwitch },
|
||||||
props: {},
|
props: {},
|
||||||
|
|
||||||
setup () {
|
setup () {
|
||||||
|
|
|
@ -43,7 +43,7 @@ export default {
|
||||||
this.w = parseInt(styles.width, 10)
|
this.w = parseInt(styles.width, 10)
|
||||||
|
|
||||||
// Attach the listeners to `document`
|
// Attach the listeners to `document`
|
||||||
if (process.server) {
|
if (process.client) {
|
||||||
document.addEventListener('mousemove', this.mouseMoveHandler)
|
document.addEventListener('mousemove', this.mouseMoveHandler)
|
||||||
document.addEventListener('mouseup', this.mouseUpHandler)
|
document.addEventListener('mouseup', this.mouseUpHandler)
|
||||||
}
|
}
|
||||||
|
@ -57,7 +57,7 @@ export default {
|
||||||
},
|
},
|
||||||
mouseUpHandler () {
|
mouseUpHandler () {
|
||||||
// Remove the handlers of `mousemove` and `mouseup`
|
// Remove the handlers of `mousemove` and `mouseup`
|
||||||
if (process.server) {
|
if (process.client) {
|
||||||
document.removeEventListener('mousemove', this.mouseMoveHandler)
|
document.removeEventListener('mousemove', this.mouseMoveHandler)
|
||||||
document.removeEventListener('mouseup', this.mouseUpHandler)
|
document.removeEventListener('mouseup', this.mouseUpHandler)
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,12 +6,12 @@
|
||||||
color="light-gray"
|
color="light-gray"
|
||||||
@click="showEmbedFormAsPopupModal=true"
|
@click="showEmbedFormAsPopupModal=true"
|
||||||
>
|
>
|
||||||
<svg xmlns="http://www.w3.org/2000/svg" class="h-6 w-6 mr-4 text-blue-600 inline" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor">
|
<svg xmlns="http://www.w3.org/2000/svg" class="h-6 w-6 mr-2 text-blue-600 inline" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor">
|
||||||
<path stroke-linecap="round" stroke-linejoin="round"
|
<path stroke-linecap="round" stroke-linejoin="round"
|
||||||
d="M2.25 12.76c0 1.6 1.123 2.994 2.707 3.227 1.068.157 2.148.279 3.238.364.466.037.893.281 1.153.671L12 21l2.652-3.978c.26-.39.687-.634 1.153-.67 1.09-.086 2.17-.208 3.238-.365 1.584-.233 2.707-1.626 2.707-3.228V6.741c0-1.602-1.123-2.995-2.707-3.228A48.394 48.394 0 0012 3c-2.392 0-4.744.175-7.043.513C3.373 3.746 2.25 5.14 2.25 6.741v6.018z"
|
d="M2.25 12.76c0 1.6 1.123 2.994 2.707 3.227 1.068.157 2.148.279 3.238.364.466.037.893.281 1.153.671L12 21l2.652-3.978c.26-.39.687-.634 1.153-.67 1.09-.086 2.17-.208 3.238-.365 1.584-.233 2.707-1.626 2.707-3.228V6.741c0-1.602-1.123-2.995-2.707-3.228A48.394 48.394 0 0012 3c-2.392 0-4.744.175-7.043.513C3.373 3.746 2.25 5.14 2.25 6.741v6.018z"
|
||||||
/>
|
/>
|
||||||
</svg>
|
</svg>
|
||||||
Embed form as popup
|
Embed as popup
|
||||||
</v-button>
|
</v-button>
|
||||||
|
|
||||||
<modal :show="showEmbedFormAsPopupModal" @close="onClose">
|
<modal :show="showEmbedFormAsPopupModal" @close="onClose">
|
||||||
|
|
|
@ -6,13 +6,13 @@
|
||||||
v-track.regenerate_form_link_click="{form_id:form.id, form_slug:form.slug}"
|
v-track.regenerate_form_link_click="{form_id:form.id, form_slug:form.slug}"
|
||||||
@click="showGenerateFormLinkModal=true"
|
@click="showGenerateFormLinkModal=true"
|
||||||
>
|
>
|
||||||
<svg xmlns="http://www.w3.org/2000/svg" class="h-6 w-6 mr-4 text-blue-600 inline" fill="none"
|
<svg xmlns="http://www.w3.org/2000/svg" class="h-6 w-6 mr-2 text-blue-600 inline" fill="none"
|
||||||
viewBox="0 0 24 24" stroke="currentColor">
|
viewBox="0 0 24 24" stroke="currentColor">
|
||||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
|
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
|
||||||
d="M13.828 10.172a4 4 0 00-5.656 0l-4 4a4 4 0 105.656 5.656l1.102-1.101m-.758-4.899a4 4 0 005.656 0l4-4a4 4 0 00-5.656-5.656l-1.1 1.1"
|
d="M13.828 10.172a4 4 0 00-5.656 0l-4 4a4 4 0 105.656 5.656l1.102-1.101m-.758-4.899a4 4 0 005.656 0l4-4a4 4 0 00-5.656-5.656l-1.1 1.1"
|
||||||
/>
|
/>
|
||||||
</svg>
|
</svg>
|
||||||
Regenerate form link
|
Regenerate link
|
||||||
</v-button>
|
</v-button>
|
||||||
|
|
||||||
<!-- Regenerate form link modal -->
|
<!-- Regenerate form link modal -->
|
||||||
|
@ -105,7 +105,7 @@ export default {
|
||||||
this.loadingNewLink = true
|
this.loadingNewLink = true
|
||||||
axios.put(this.formEndpoint.replace('{id}', this.form.id) + '/regenerate-link/' + option).then((response) => {
|
axios.put(this.formEndpoint.replace('{id}', this.form.id) + '/regenerate-link/' + option).then((response) => {
|
||||||
this.formsStore.addOrUpdate(response.data.form)
|
this.formsStore.addOrUpdate(response.data.form)
|
||||||
this.$router.push({name: 'forms-slug-show', params: {slug: response.data.form.slug}})
|
this.$router.push({name: 'forms-slug-show-share', params: {slug: response.data.form.slug}})
|
||||||
this.alertSuccess(response.data.message)
|
this.alertSuccess(response.data.message)
|
||||||
this.loadingNewLink = false
|
this.loadingNewLink = false
|
||||||
}).finally(() => {
|
}).finally(() => {
|
||||||
|
|
|
@ -6,13 +6,13 @@
|
||||||
v-track.url_form_prefill_click="{form_id:form.id, form_slug:form.slug}"
|
v-track.url_form_prefill_click="{form_id:form.id, form_slug:form.slug}"
|
||||||
@click="showUrlFormPrefillModal=true"
|
@click="showUrlFormPrefillModal=true"
|
||||||
>
|
>
|
||||||
<svg xmlns="http://www.w3.org/2000/svg" class="h-6 w-6 mr-4 text-blue-600 inline" fill="none"
|
<svg xmlns="http://www.w3.org/2000/svg" class="h-6 w-6 mr-2 text-blue-600 inline" fill="none"
|
||||||
viewBox="0 0 24 24" stroke="currentColor">
|
viewBox="0 0 24 24" stroke="currentColor">
|
||||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
|
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
|
||||||
d="M17 16v2a2 2 0 01-2 2H5a2 2 0 01-2-2v-7a2 2 0 012-2h2m3-4H9a2 2 0 00-2 2v7a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-1m-1 4l-3 3m0 0l-3-3m3 3V3"
|
d="M17 16v2a2 2 0 01-2 2H5a2 2 0 01-2-2v-7a2 2 0 012-2h2m3-4H9a2 2 0 00-2 2v7a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-1m-1 4l-3 3m0 0l-3-3m3 3V3"
|
||||||
/>
|
/>
|
||||||
</svg>
|
</svg>
|
||||||
Url form pre-fill
|
Url pre-fill
|
||||||
</v-button>
|
</v-button>
|
||||||
|
|
||||||
<modal :show="showUrlFormPrefillModal" @close="showUrlFormPrefillModal=false">
|
<modal :show="showUrlFormPrefillModal" @close="showUrlFormPrefillModal=false">
|
||||||
|
|
|
@ -1,10 +1,10 @@
|
||||||
<template>
|
<template>
|
||||||
<div class="w-full flex flex-col">
|
<div class="w-full flex flex-col">
|
||||||
<form-editor v-if="pageLoaded" ref="editor"
|
<form-editor v-if="!formsLoading || form" ref="editor"
|
||||||
:is-edit="true"
|
:is-edit="true"
|
||||||
@on-save="formInitialHash=null"
|
@on-save="formInitialHash=null"
|
||||||
/>
|
/>
|
||||||
<div v-else-if="!loading && error" class="mt-4 rounded-lg max-w-xl mx-auto p-6 bg-red-100 text-red-500">
|
<div v-else-if="!formsLoading && error" class="mt-4 rounded-lg max-w-xl mx-auto p-6 bg-red-100 text-red-500">
|
||||||
{{ error }}
|
{{ error }}
|
||||||
</div>
|
</div>
|
||||||
<div v-else class="text-center mt-4 py-6">
|
<div v-else class="text-center mt-4 py-6">
|
||||||
|
@ -15,14 +15,12 @@
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import { computed } from 'vue'
|
import { computed } from 'vue'
|
||||||
import Form from 'vform'
|
|
||||||
import Breadcrumb from '~/components/global/Breadcrumb.vue'
|
import Breadcrumb from '~/components/global/Breadcrumb.vue'
|
||||||
import SeoMeta from '../../../mixins/seo-meta.js'
|
import FormEditor from "~/components/open/forms/components/FormEditor.vue";
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'EditForm',
|
name: 'EditForm',
|
||||||
components: { Breadcrumb },
|
components: { Breadcrumb, FormEditor },
|
||||||
mixins: [SeoMeta],
|
|
||||||
middleware: 'auth',
|
middleware: 'auth',
|
||||||
|
|
||||||
beforeRouteLeave (to, from, next) {
|
beforeRouteLeave (to, from, next) {
|
||||||
|
@ -41,71 +39,56 @@ export default {
|
||||||
const workspacesStore = useWorkspacesStore()
|
const workspacesStore = useWorkspacesStore()
|
||||||
|
|
||||||
if (!formsStore.allLoaded) {
|
if (!formsStore.allLoaded) {
|
||||||
formsStore.loadAll(useWorkspacesStore().currentId)
|
formsStore.startLoading()
|
||||||
}
|
}
|
||||||
workingFormStore.set(null) // Reset old working form
|
const updatedForm = storeToRefs(workingFormStore).content
|
||||||
|
const form = computed(() => formsStore.getByKey(useRoute().params.slug))
|
||||||
|
|
||||||
|
// Create a form.id watcher that updates working form
|
||||||
|
watch(form, (form) => {
|
||||||
|
if (form) {
|
||||||
|
updatedForm.value = useForm(form)
|
||||||
|
console.log('updatedForm.value',updatedForm.value)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
return {
|
return {
|
||||||
formsStore,
|
formsStore,
|
||||||
workingFormStore,
|
workingFormStore,
|
||||||
workspacesStore,
|
workspacesStore,
|
||||||
formsLoading: computed(() => formsStore.loading)
|
updatedForm,
|
||||||
|
form,
|
||||||
|
formsLoading: computed(() => formsStore.loading),
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
data () {
|
data () {
|
||||||
return {
|
return {
|
||||||
loading: false,
|
|
||||||
error: null,
|
error: null,
|
||||||
formInitialHash: null
|
formInitialHash: null
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
computed: {
|
computed: {
|
||||||
updatedForm: {
|
|
||||||
get () {
|
|
||||||
return this.workingFormStore.content
|
|
||||||
},
|
|
||||||
/* We add a setter */
|
|
||||||
set (value) {
|
|
||||||
this.workingFormStore.set(value)
|
|
||||||
}
|
|
||||||
},
|
|
||||||
form () {
|
|
||||||
return this.formsStore.getByKey(this.$route.params.slug)
|
|
||||||
},
|
|
||||||
pageLoaded () {
|
|
||||||
return !this.loading && this.updatedForm !== null
|
|
||||||
},
|
|
||||||
metaTitle () {
|
metaTitle () {
|
||||||
return 'Edit ' + (this.form ? this.form.title : 'Your Form')
|
return 'Edit ' + (this.form ? this.form.title : 'Your Form')
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
watch: {
|
async beforeMount() {
|
||||||
form () {
|
|
||||||
this.updatedForm = new Form(this.form)
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
created () {},
|
|
||||||
unmounted () {},
|
|
||||||
|
|
||||||
mounted () {
|
|
||||||
window.onbeforeunload = () => {
|
window.onbeforeunload = () => {
|
||||||
if (this.isDirty()) {
|
if (this.isDirty()) {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// this.closeAlert()
|
if (!this.form && !this.formsStore.allLoaded) {
|
||||||
if (!this.form) {
|
await this.formsStore.loadAll(this.workspacesStore.currentId)
|
||||||
loadForms()
|
|
||||||
} else {
|
|
||||||
this.updatedForm = new Form(this.form)
|
|
||||||
this.formInitialHash = this.hashString(JSON.stringify(this.updatedForm.data()))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
this.updatedForm = useForm(this.form)
|
||||||
|
this.formInitialHash = this.hashString(JSON.stringify(this.updatedForm.data()))
|
||||||
|
|
||||||
if (this.updatedForm && (!this.updatedForm.notification_settings || Array.isArray(this.updatedForm.notification_settings))) {
|
if (this.updatedForm && (!this.updatedForm.notification_settings || Array.isArray(this.updatedForm.notification_settings))) {
|
||||||
this.updatedForm.notification_settings = {}
|
this.updatedForm.notification_settings = {}
|
||||||
}
|
}
|
||||||
|
@ -113,7 +96,7 @@ export default {
|
||||||
|
|
||||||
methods: {
|
methods: {
|
||||||
isDirty () {
|
isDirty () {
|
||||||
return !this.loading && this.formInitialHash && this.formInitialHash !== this.hashString(JSON.stringify(this.updatedForm.data()))
|
return this.formInitialHash && this.formInitialHash !== this.hashString(JSON.stringify(this.updatedForm.data()))
|
||||||
},
|
},
|
||||||
hashString (str, seed = 0) {
|
hashString (str, seed = 0) {
|
||||||
let h1 = 0xdeadbeef ^ seed
|
let h1 = 0xdeadbeef ^ seed
|
||||||
|
|
|
@ -132,7 +132,6 @@ import Form from 'vform'
|
||||||
import ProTag from '~/components/global/ProTag.vue'
|
import ProTag from '~/components/global/ProTag.vue'
|
||||||
import VButton from '~/components/global/VButton.vue'
|
import VButton from '~/components/global/VButton.vue'
|
||||||
import ExtraMenu from '../../../components/pages/forms/show/ExtraMenu.vue'
|
import ExtraMenu from '../../../components/pages/forms/show/ExtraMenu.vue'
|
||||||
import SeoMeta from '../../../mixins/seo-meta.js'
|
|
||||||
import FormCleanings from '../../../components/pages/forms/show/FormCleanings.vue'
|
import FormCleanings from '../../../components/pages/forms/show/FormCleanings.vue'
|
||||||
export default {
|
export default {
|
||||||
name: 'ShowForm',
|
name: 'ShowForm',
|
||||||
|
@ -142,11 +141,6 @@ export default {
|
||||||
ExtraMenu,
|
ExtraMenu,
|
||||||
FormCleanings
|
FormCleanings
|
||||||
},
|
},
|
||||||
mixins: [SeoMeta],
|
|
||||||
|
|
||||||
beforeUnmount() {
|
|
||||||
this.workingForm = null
|
|
||||||
},
|
|
||||||
|
|
||||||
middleware: 'auth',
|
middleware: 'auth',
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,14 @@
|
||||||
<template>
|
<template>
|
||||||
<div>
|
<div class="mb-20">
|
||||||
|
|
||||||
|
<div class="mb-6 pb-6 border-b w-full flex flex-col sm:flex-row gap-2">
|
||||||
|
<regenerate-form-link class="sm:w-1/2 flex" :form="form" />
|
||||||
|
|
||||||
|
<url-form-prefill class="sm:w-1/2" :form="form" :extra-query-param="shareUrlForQueryParams" />
|
||||||
|
|
||||||
|
<embed-form-as-popup-modal class="sm:w-1/2 flex" :form="form" />
|
||||||
|
</div>
|
||||||
|
|
||||||
<share-link class="mt-4" :form="form" :extra-query-param="shareUrlForQueryParams" />
|
<share-link class="mt-4" :form="form" :extra-query-param="shareUrlForQueryParams" />
|
||||||
|
|
||||||
<embed-code class="mt-6" :form="form" :extra-query-param="shareUrlForQueryParams" />
|
<embed-code class="mt-6" :form="form" :extra-query-param="shareUrlForQueryParams" />
|
||||||
|
@ -8,13 +17,6 @@
|
||||||
|
|
||||||
<advanced-form-url-settings :form="form" v-model="shareFormConfig" />
|
<advanced-form-url-settings :form="form" v-model="shareFormConfig" />
|
||||||
|
|
||||||
<div class="mt-6 pt-6 border-t w-full flex">
|
|
||||||
<regenerate-form-link class="sm:w-1/2 mr-4" :form="form" />
|
|
||||||
|
|
||||||
<url-form-prefill class="sm:w-1/2 mr-4" :form="form" :extra-query-param="shareUrlForQueryParams" />
|
|
||||||
|
|
||||||
<embed-form-as-popup-modal class="sm:w-1/2" :form="form" />
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
|
|
@ -65,8 +65,9 @@
|
||||||
<div v-for="(form) in enrichedForms" :key="form.id"
|
<div v-for="(form) in enrichedForms" :key="form.id"
|
||||||
class="mt-4 p-4 flex group bg-white hover:bg-gray-50 dark:bg-notion-dark items-center relative"
|
class="mt-4 p-4 flex group bg-white hover:bg-gray-50 dark:bg-notion-dark items-center relative"
|
||||||
>
|
>
|
||||||
<div class="flex-grow items-center truncate cursor-pointer" role="button"
|
<div class="flex-grow items-center truncate cursor-pointer relative">
|
||||||
@click.prevent="viewForm(form)">
|
<NuxtLink :to="{name:'forms-slug-show-submissions', params: {slug:form.slug}}"
|
||||||
|
class="absolute inset-0"/>
|
||||||
<span class="font-semibold text-gray-900 dark:text-white">{{ form.title }}</span>
|
<span class="font-semibold text-gray-900 dark:text-white">{{ form.title }}</span>
|
||||||
<ul class="flex text-gray-500">
|
<ul class="flex text-gray-500">
|
||||||
<li class="pr-1">
|
<li class="pr-1">
|
||||||
|
@ -164,9 +165,6 @@ const onTagClick = (tag) => {
|
||||||
selectedTags.value.add(tag)
|
selectedTags.value.add(tag)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
const viewForm = (form) => {
|
|
||||||
useRouter().push({name: 'forms-slug-show', params: {slug: form.slug}})
|
|
||||||
}
|
|
||||||
|
|
||||||
// Computed
|
// Computed
|
||||||
const isFilteringForms = computed(() => {
|
const isFilteringForms = computed(() => {
|
||||||
|
|
|
@ -27,14 +27,18 @@ export const useFormsStore = defineStore('forms', () => {
|
||||||
contentStore.stopLoading()
|
contentStore.stopLoading()
|
||||||
currentPage.value = 1
|
currentPage.value = 1
|
||||||
}
|
}
|
||||||
|
}).catch((error) => {
|
||||||
|
contentStore.stopLoading()
|
||||||
|
currentPage.value = 1
|
||||||
|
throw error
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
const load = (workspaceId, slug) => {
|
const load = (workspaceId, slug) => {
|
||||||
contentStore.startLoading()
|
contentStore.startLoading()
|
||||||
return opnFetch(formsEndpoint.replace('{workspaceId}', workspaceId) + '/' + slug)
|
return opnFetch(formsEndpoint.replace('{workspaceId}', workspaceId) + '/' + slug)
|
||||||
.then((response) => {
|
.finally(() => {
|
||||||
console.log(response.data.value)
|
contentStore.stopLoading()
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -13,6 +13,8 @@ export const useWorkingFormStore = defineStore('working_form', {
|
||||||
}),
|
}),
|
||||||
actions: {
|
actions: {
|
||||||
set (form) {
|
set (form) {
|
||||||
|
console.log('setting working form', form)
|
||||||
|
console.trace();
|
||||||
this.content = form
|
this.content = form
|
||||||
},
|
},
|
||||||
setProperties (properties) {
|
setProperties (properties) {
|
||||||
|
|
|
@ -22,7 +22,7 @@ export const useWorkspacesStore = defineStore('workspaces', () => {
|
||||||
|
|
||||||
const save = (items) => {
|
const save = (items) => {
|
||||||
contentStore.save(items)
|
contentStore.save(items)
|
||||||
if (currentId.value == null && contentStore.length.value) {
|
if ((getCurrent.value == null) && contentStore.length.value) {
|
||||||
setCurrentId(items[0].id)
|
setCurrentId(items[0].id)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue