Better form editor (#187)
This commit is contained in:
parent
a21eb851aa
commit
c66c09e17b
|
@ -84,7 +84,8 @@ export default {
|
||||||
message: '',
|
message: '',
|
||||||
confirmationProceed: null,
|
confirmationProceed: null,
|
||||||
confirmationCancel: null
|
confirmationCancel: null
|
||||||
}
|
},
|
||||||
|
navbarHidden: false
|
||||||
}),
|
}),
|
||||||
|
|
||||||
mounted () {
|
mounted () {
|
||||||
|
@ -106,6 +107,9 @@ export default {
|
||||||
},
|
},
|
||||||
workspaceAdded () {
|
workspaceAdded () {
|
||||||
this.$router.push({ name: 'home' })
|
this.$router.push({ name: 'home' })
|
||||||
|
},
|
||||||
|
hideNavbar (hidden = true) {
|
||||||
|
this.navbarHidden = hidden
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
|
@ -183,7 +183,7 @@ export default {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return true
|
return !this.$root.navbarHidden
|
||||||
},
|
},
|
||||||
isIframe() {
|
isIframe() {
|
||||||
return window.location !== window.parent.location || window.frameElement
|
return window.location !== window.parent.location || window.frameElement
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
<template>
|
<template>
|
||||||
<div v-if="form" class="open-complete-form">
|
<div v-if="form" class="open-complete-form">
|
||||||
<h1 v-if="!isHideTitle" class="mb-4 px-2" :class="{"mt-4":isEmbedPopup}" v-text="form.title" />
|
<h1 v-if="!isHideTitle" class="mb-4 px-2" :class="{'mt-4':isEmbedPopup}" v-text="form.title" />
|
||||||
|
|
||||||
<div v-if="isPublicFormPage && form.is_password_protected">
|
<div v-if="isPublicFormPage && form.is_password_protected">
|
||||||
<p class="form-description mb-4 text-gray-700 dark:text-gray-300 px-2">
|
<p class="form-description mb-4 text-gray-700 dark:text-gray-300 px-2">
|
||||||
|
@ -76,7 +76,7 @@
|
||||||
>
|
>
|
||||||
<template #submit-btn="{submitForm}">
|
<template #submit-btn="{submitForm}">
|
||||||
<open-form-button :loading="loading" :theme="theme" :color="form.color" class="mt-2 px-8 mx-1"
|
<open-form-button :loading="loading" :theme="theme" :color="form.color" class="mt-2 px-8 mx-1"
|
||||||
@click.prevent="submitForm"
|
:class="submitButtonClass" @click.prevent="submitForm"
|
||||||
>
|
>
|
||||||
{{ form.submit_button_text }}
|
{{ form.submit_button_text }}
|
||||||
</open-form-button>
|
</open-form-button>
|
||||||
|
@ -123,7 +123,8 @@ export default {
|
||||||
props: {
|
props: {
|
||||||
form: { type: Object, required: true },
|
form: { type: Object, required: true },
|
||||||
creating: { type: Boolean, default: false }, // If true, fake form submit
|
creating: { type: Boolean, default: false }, // If true, fake form submit
|
||||||
adminPreview: { type: Boolean, default: false } // If used in FormEditorPreview
|
adminPreview: { type: Boolean, default: false }, // If used in FormEditorPreview
|
||||||
|
submitButtonClass: { type: String, default: '' }
|
||||||
},
|
},
|
||||||
|
|
||||||
mixins: [FormPendingSubmissionKey],
|
mixins: [FormPendingSubmissionKey],
|
||||||
|
|
|
@ -1,35 +1,59 @@
|
||||||
<template>
|
<template>
|
||||||
<div v-if="form" id="form-editor" class="w-full flex flex-grow relative overflow-x-hidden">
|
<div v-if="form" id="form-editor" class="relative flex w-full flex-col grow max-h-screen">
|
||||||
<!-- Form fields selection -->
|
<!-- Navbar -->
|
||||||
<div class="w-full md:w-1/2 lg:w-2/5 border-r relative overflow-y-scroll md:max-w-sm flex-shrink-0">
|
<div class="w-full border-b p-2 flex items-center justify-between bg-white">
|
||||||
<div class="p-4 bg-blue-50 border-b text-nt-blue-dark md:hidden">
|
<a v-if="backButton" href="#" class="ml-2 flex text-blue font-semibold text-sm"
|
||||||
We suggest you create this form on a device with a larger screen such as computed. That will allow you
|
@click.prevent="$router.back()"
|
||||||
to preview your form changes.
|
>
|
||||||
</div>
|
|
||||||
<div class="p-4 pb-0">
|
|
||||||
<a v-if="!isGuest" href="#" @click.prevent="$router.back()" class="flex text-blue mb-2 font-semibold text-sm">
|
|
||||||
<svg class="w-3 h-3 text-blue mt-1 mr-1" viewBox="0 0 6 10" fill="none" xmlns="http://www.w3.org/2000/svg">
|
<svg class="w-3 h-3 text-blue mt-1 mr-1" viewBox="0 0 6 10" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
<path d="M5 9L1 5L5 1" stroke="currentColor" stroke-width="1.5" stroke-linecap="round"
|
<path d="M5 9L1 5L5 1" stroke="currentColor" stroke-width="1.5" stroke-linecap="round"
|
||||||
stroke-linejoin="round"/>
|
stroke-linejoin="round"
|
||||||
|
/>
|
||||||
</svg>
|
</svg>
|
||||||
Go back
|
Go back
|
||||||
</a>
|
</a>
|
||||||
<template v-if="isEdit">
|
<div class="hidden md:flex items-center ml-3">
|
||||||
<h3 class="font-semibold text-lg">{{ form.title }}</h3>
|
<h3 class="font-semibold text-lg max-w-[14rem] truncate text-gray-500">
|
||||||
<small class="text-gray-500">Edited {{ form.last_edited_human }}</small>
|
{{ form.title }}
|
||||||
</template>
|
</h3>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="p-4 border-b sticky top-0 z-10 bg-white">
|
<div class="flex items-center" :class="{'mx-auto md:mx-0':!backButton}">
|
||||||
<v-button v-track.save_form_click class="w-full" :loading="updateFormLoading"
|
<div class="hidden md:block mr-10 relative">
|
||||||
@click="saveForm">
|
<a href="#"
|
||||||
<svg class="w-4 h-4 text-white inline mr-1 -mt-1" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
class="text-sm px-3 py-2 hover:bg-gray-50 cursor-pointer rounded-md text-gray-500 px-0 sm:px-3 hover:text-gray-800 cursor-pointer mt-1"
|
||||||
<path d="M17 21V13H7V21M7 3V8H15M19 21H5C4.46957 21 3.96086 20.7893 3.58579 20.4142C3.21071 20.0391 3 19.5304 3 19V5C3 4.46957 3.21071 3.96086 3.58579 3.58579C3.96086 3.21071 4.46957 3 5 3H16L21 8V19C21 19.5304 20.7893 20.0391 20.4142 20.4142C20.0391 20.7893 19.5304 21 19 21Z" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
|
@click.prevent="$crisp.push(['do', 'helpdesk:search'])"
|
||||||
|
>
|
||||||
|
Help
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
<v-button v-track.save_form_click size="small" class="w-full px-8 md:px-4 py-2"
|
||||||
|
:loading="updateFormLoading" :class="saveButtonClass"
|
||||||
|
@click="saveForm"
|
||||||
|
>
|
||||||
|
<svg class="w-4 h-4 text-white inline mr-1 -mt-1" viewBox="0 0 24 24" fill="none"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
>
|
||||||
|
<path
|
||||||
|
d="M17 21V13H7V21M7 3V8H15M19 21H5C4.46957 21 3.96086 20.7893 3.58579 20.4142C3.21071 20.0391 3 19.5304 3 19V5C3 4.46957 3.21071 3.96086 3.58579 3.58579C3.96086 3.21071 4.46957 3 5 3H16L21 8V19C21 19.5304 20.7893 20.0391 20.4142 20.4142C20.0391 20.7893 19.5304 21 19 21Z"
|
||||||
|
stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"
|
||||||
|
/>
|
||||||
</svg>
|
</svg>
|
||||||
|
<template v-if="form.visibility === 'public'">
|
||||||
Save changes
|
Publish Form
|
||||||
|
</template>
|
||||||
|
<template v-else>
|
||||||
|
Save Changes
|
||||||
|
</template>
|
||||||
</v-button>
|
</v-button>
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="w-full flex grow overflow-y-scroll">
|
||||||
|
<div class="relative w-full shrink-0 overflow-y-scroll border-r md:w-1/2 md:max-w-sm lg:w-2/5">
|
||||||
|
<div class="border-b bg-blue-50 p-5 text-nt-blue-dark md:hidden">
|
||||||
|
Please create this form on a device with a larger screen. That will allow you to preview your form changes.
|
||||||
|
</div>
|
||||||
|
|
||||||
<form-information/>
|
<form-information/>
|
||||||
<form-structure/>
|
<form-structure/>
|
||||||
|
@ -45,11 +69,13 @@
|
||||||
<form-editor-preview/>
|
<form-editor-preview/>
|
||||||
|
|
||||||
<!-- Form Error Modal -->
|
<!-- Form Error Modal -->
|
||||||
<form-error-modal :show="showFormErrorModal"
|
<form-error-modal
|
||||||
|
:show="showFormErrorModal"
|
||||||
:validation-error-response="validationErrorResponse"
|
:validation-error-response="validationErrorResponse"
|
||||||
@close="showFormErrorModal=false"
|
@close="showFormErrorModal=false"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
<div v-else class="flex justify-center items-center">
|
<div v-else class="flex justify-center items-center">
|
||||||
<loader class="w-6 h-6"/>
|
<loader class="w-6 h-6"/>
|
||||||
</div>
|
</div>
|
||||||
|
@ -98,6 +124,16 @@ export default {
|
||||||
type: Boolean,
|
type: Boolean,
|
||||||
default: false
|
default: false
|
||||||
},
|
},
|
||||||
|
backButton: {
|
||||||
|
required: false,
|
||||||
|
type: Boolean,
|
||||||
|
default: true
|
||||||
|
},
|
||||||
|
saveButtonClass: {
|
||||||
|
required: false,
|
||||||
|
type: String,
|
||||||
|
default: ''
|
||||||
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
data() {
|
data() {
|
||||||
|
@ -170,6 +206,11 @@ export default {
|
||||||
|
|
||||||
mounted() {
|
mounted() {
|
||||||
this.$emit('mounted')
|
this.$emit('mounted')
|
||||||
|
this.$root.hideNavbar()
|
||||||
|
},
|
||||||
|
|
||||||
|
beforeDestroy () {
|
||||||
|
this.$root.hideNavbar(false)
|
||||||
},
|
},
|
||||||
|
|
||||||
methods: {
|
methods: {
|
||||||
|
|
|
@ -6,11 +6,8 @@
|
||||||
@close="showInitialFormModal=false"/>
|
@close="showInitialFormModal=false"/>
|
||||||
<form-editor v-if="!workspacesLoading" ref="editor"
|
<form-editor v-if="!workspacesLoading" ref="editor"
|
||||||
class="w-full flex flex-grow"
|
class="w-full flex flex-grow"
|
||||||
:style="{
|
:error="error"
|
||||||
'max-height': editorMaxHeight + 'px'
|
|
||||||
}" :error="error"
|
|
||||||
:isGuest="isGuest"
|
:isGuest="isGuest"
|
||||||
@mounted="onResize"
|
|
||||||
@openRegister="openRegister"
|
@openRegister="openRegister"
|
||||||
/>
|
/>
|
||||||
<div v-else class="text-center mt-4 py-6">
|
<div v-else class="text-center mt-4 py-6">
|
||||||
|
@ -61,7 +58,6 @@ export default {
|
||||||
stateReady: false,
|
stateReady: false,
|
||||||
loading: false,
|
loading: false,
|
||||||
error: '',
|
error: '',
|
||||||
editorMaxHeight: 500,
|
|
||||||
registerModal: false,
|
registerModal: false,
|
||||||
isGuest: true,
|
isGuest: true,
|
||||||
showInitialFormModal: false
|
showInitialFormModal: false
|
||||||
|
@ -120,25 +116,13 @@ export default {
|
||||||
this.stateReady = true
|
this.stateReady = true
|
||||||
},
|
},
|
||||||
|
|
||||||
created() {
|
created() {},
|
||||||
window.addEventListener('resize', this.onResize)
|
destroyed() {},
|
||||||
},
|
|
||||||
destroyed() {
|
|
||||||
window.removeEventListener('resize', this.onResize)
|
|
||||||
},
|
|
||||||
|
|
||||||
methods: {
|
methods: {
|
||||||
...mapActions({
|
...mapActions({
|
||||||
loadWorkspaces: 'open/workspaces/load'
|
loadWorkspaces: 'open/workspaces/load'
|
||||||
}),
|
}),
|
||||||
/**
|
|
||||||
* Compute max height of editor
|
|
||||||
*/
|
|
||||||
onResize() {
|
|
||||||
if (this.$refs.editor) {
|
|
||||||
this.editorMaxHeight = window.innerHeight - this.$refs.editor.$el.offsetTop
|
|
||||||
}
|
|
||||||
},
|
|
||||||
openRegister() {
|
openRegister() {
|
||||||
this.registerModal = true
|
this.registerModal = true
|
||||||
},
|
},
|
||||||
|
|
|
@ -6,10 +6,7 @@
|
||||||
@close="showInitialFormModal=false"/>
|
@close="showInitialFormModal=false"/>
|
||||||
<form-editor v-if="!workspacesLoading" ref="editor"
|
<form-editor v-if="!workspacesLoading" ref="editor"
|
||||||
class="w-full flex flex-grow"
|
class="w-full flex flex-grow"
|
||||||
:style="{
|
:error="error"
|
||||||
'max-height': editorMaxHeight + 'px'
|
|
||||||
}" :error="error"
|
|
||||||
@mounted="onResize"
|
|
||||||
@on-save="formInitialHash=null"
|
@on-save="formInitialHash=null"
|
||||||
/>
|
/>
|
||||||
<div v-else class="text-center mt-4 py-6">
|
<div v-else class="text-center mt-4 py-6">
|
||||||
|
@ -64,7 +61,6 @@ export default {
|
||||||
stateReady: false,
|
stateReady: false,
|
||||||
loading: false,
|
loading: false,
|
||||||
error: '',
|
error: '',
|
||||||
editorMaxHeight: 500,
|
|
||||||
showInitialFormModal: false,
|
showInitialFormModal: false,
|
||||||
formInitialHash: null
|
formInitialHash: null
|
||||||
}
|
}
|
||||||
|
@ -125,25 +121,13 @@ export default {
|
||||||
this.stateReady = this.user !== null
|
this.stateReady = this.user !== null
|
||||||
},
|
},
|
||||||
|
|
||||||
created() {
|
created() {},
|
||||||
window.addEventListener('resize', this.onResize)
|
destroyed() {},
|
||||||
},
|
|
||||||
destroyed() {
|
|
||||||
window.removeEventListener('resize', this.onResize)
|
|
||||||
},
|
|
||||||
|
|
||||||
methods: {
|
methods: {
|
||||||
...mapActions({
|
...mapActions({
|
||||||
loadWorkspaces: 'open/workspaces/loadIfEmpty'
|
loadWorkspaces: 'open/workspaces/loadIfEmpty'
|
||||||
}),
|
}),
|
||||||
/**
|
|
||||||
* Compute max height of editor
|
|
||||||
*/
|
|
||||||
onResize() {
|
|
||||||
if (this.$refs.editor) {
|
|
||||||
this.editorMaxHeight = window.innerHeight - this.$refs.editor.$el.offsetTop
|
|
||||||
}
|
|
||||||
},
|
|
||||||
formGenerated(form) {
|
formGenerated(form) {
|
||||||
this.form = new Form({...this.form.data(), ...form})
|
this.form = new Form({...this.form.data(), ...form})
|
||||||
},
|
},
|
||||||
|
|
|
@ -1,11 +1,7 @@
|
||||||
<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="pageLoaded" ref="editor"
|
||||||
:style="{
|
|
||||||
'max-height': editorMaxHeight + 'px'
|
|
||||||
}"
|
|
||||||
:isEdit="true"
|
:isEdit="true"
|
||||||
@mounted="onResize"
|
|
||||||
@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="!loading && error" class="mt-4 rounded-lg max-w-xl mx-auto p-6 bg-red-100 text-red-500">
|
||||||
|
@ -61,7 +57,6 @@ export default {
|
||||||
return {
|
return {
|
||||||
loading: false,
|
loading: false,
|
||||||
error: null,
|
error: null,
|
||||||
editorMaxHeight: 500,
|
|
||||||
formInitialHash: null
|
formInitialHash: null
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -96,12 +91,8 @@ export default {
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
created () {
|
created () {},
|
||||||
window.addEventListener('resize', this.onResize)
|
destroyed () {},
|
||||||
},
|
|
||||||
destroyed () {
|
|
||||||
window.removeEventListener('resize', this.onResize)
|
|
||||||
},
|
|
||||||
|
|
||||||
mounted () {
|
mounted () {
|
||||||
window.onbeforeunload = () => {
|
window.onbeforeunload = () => {
|
||||||
|
@ -120,14 +111,6 @@ export default {
|
||||||
},
|
},
|
||||||
|
|
||||||
methods: {
|
methods: {
|
||||||
/**
|
|
||||||
* Compute max height of editor
|
|
||||||
*/
|
|
||||||
onResize () {
|
|
||||||
if (this.$refs.editor) {
|
|
||||||
this.editorMaxHeight = Math.max(500, window.innerHeight - this.$refs.editor.$el.offsetTop)
|
|
||||||
}
|
|
||||||
},
|
|
||||||
isDirty () {
|
isDirty () {
|
||||||
return !this.loading && this.formInitialHash && this.formInitialHash !== this.hashString(JSON.stringify(this.updatedForm.data()))
|
return !this.loading && this.formInitialHash && this.formInitialHash !== this.hashString(JSON.stringify(this.updatedForm.data()))
|
||||||
},
|
},
|
||||||
|
|
Loading…
Reference in New Issue