2023-12-09 15:47:03 +01:00
|
|
|
<template>
|
2024-04-15 19:39:03 +02:00
|
|
|
<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"
|
|
|
|
|
/>
|
|
|
|
|
<div
|
|
|
|
|
v-if="form.description"
|
|
|
|
|
class="form-description mb-4 text-gray-700 dark:text-gray-300 whitespace-pre-wrap px-2"
|
|
|
|
|
v-html="form.description"
|
|
|
|
|
/>
|
2023-12-09 15:47:03 +01:00
|
|
|
|
|
|
|
|
<div v-if="isPublicFormPage && form.is_password_protected">
|
|
|
|
|
<p class="form-description mb-4 text-gray-700 dark:text-gray-300 px-2">
|
|
|
|
|
This form is protected by a password.
|
|
|
|
|
</p>
|
|
|
|
|
<div class="form-group flex flex-wrap w-full">
|
|
|
|
|
<div class="relative mb-3 w-full px-2">
|
2024-04-15 19:39:03 +02:00
|
|
|
<text-input
|
|
|
|
|
:theme="theme"
|
|
|
|
|
:form="passwordForm"
|
|
|
|
|
name="password"
|
|
|
|
|
native-type="password"
|
|
|
|
|
label="Password"
|
|
|
|
|
/>
|
2023-12-09 15:47:03 +01:00
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
<div class="flex flex-wrap justify-center w-full text-center">
|
2024-04-15 19:39:03 +02:00
|
|
|
<open-form-button
|
|
|
|
|
:theme="theme"
|
|
|
|
|
:color="form.color"
|
|
|
|
|
class="my-4"
|
|
|
|
|
@click="passwordEntered"
|
|
|
|
|
>
|
2023-12-09 15:47:03 +01:00
|
|
|
Submit
|
2024-01-29 21:26:01 +01:00
|
|
|
</open-form-button>
|
2023-12-09 15:47:03 +01:00
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
<v-transition>
|
2024-04-15 19:39:03 +02:00
|
|
|
<div
|
|
|
|
|
v-if="!form.is_password_protected && form.password && !hidePasswordDisabledMsg"
|
2024-06-13 11:47:23 +02:00
|
|
|
class="border shadow-sm p-2 my-4 flex items-center rounded-md bg-yellow-100 dark:bg-yellow-600/20 border-yellow-500 dark:border-yellow-500/20"
|
2023-12-09 15:47:03 +01:00
|
|
|
>
|
|
|
|
|
<div class="flex flex-grow">
|
2024-01-16 15:00:22 +01:00
|
|
|
<p class="mb-0 py-2 px-4 text-yellow-600 dark:text-yellow-600">
|
2023-12-09 15:47:03 +01:00
|
|
|
We disabled the password protection for this form because you are an owner of it.
|
|
|
|
|
</p>
|
2024-04-15 19:39:03 +02:00
|
|
|
<v-button
|
|
|
|
|
color="yellow"
|
|
|
|
|
@click="hidePasswordDisabledMsg=true"
|
|
|
|
|
>
|
2023-12-09 15:47:03 +01:00
|
|
|
OK
|
|
|
|
|
</v-button>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
</v-transition>
|
|
|
|
|
|
2024-04-15 19:39:03 +02:00
|
|
|
<div
|
|
|
|
|
v-if="isPublicFormPage && (form.is_closed || form.visibility=='closed')"
|
2024-06-13 11:47:23 +02:00
|
|
|
class="border shadow-sm p-2 my-4 flex items-center rounded-md bg-yellow-100 dark:bg-yellow-600/20 border-yellow-500 dark:border-yellow-500/20"
|
2023-12-09 15:47:03 +01:00
|
|
|
>
|
|
|
|
|
<div class="flex-grow">
|
2024-04-15 19:39:03 +02:00
|
|
|
<p
|
|
|
|
|
class="mb-0 py-2 px-4 text-yellow-600"
|
|
|
|
|
v-html="form.closed_text"
|
|
|
|
|
/>
|
2023-12-09 15:47:03 +01:00
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
|
2024-04-15 19:39:03 +02:00
|
|
|
<div
|
|
|
|
|
v-if="isPublicFormPage && form.max_number_of_submissions_reached"
|
2024-06-13 11:47:23 +02:00
|
|
|
class="border shadow-sm p-2 my-4 flex items-center rounded-md bg-yellow-100 dark:bg-yellow-600/20 border-yellow-500 dark:border-yellow-500/20"
|
2023-12-09 15:47:03 +01:00
|
|
|
>
|
|
|
|
|
<div class="flex-grow">
|
2024-06-13 11:47:23 +02:00
|
|
|
<div
|
|
|
|
|
class="mb-0 py-2 px-4 text-yellow-600 dark:text-yellow-600"
|
2024-04-15 19:39:03 +02:00
|
|
|
v-html="form.max_submissions_reached_text"
|
|
|
|
|
/>
|
2023-12-09 15:47:03 +01:00
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
|
2024-04-15 19:39:03 +02:00
|
|
|
<form-cleanings
|
|
|
|
|
v-if="!adminPreview"
|
|
|
|
|
:hideable="true"
|
|
|
|
|
class="mb-4 mx-2"
|
|
|
|
|
:form="form"
|
|
|
|
|
:specify-form-owner="true"
|
|
|
|
|
/>
|
2023-12-09 15:47:03 +01:00
|
|
|
|
|
|
|
|
<transition
|
|
|
|
|
v-if="!form.is_password_protected && (!isPublicFormPage || (!form.is_closed && !form.max_number_of_submissions_reached && form.visibility!='closed'))"
|
|
|
|
|
enter-active-class="duration-500 ease-out"
|
|
|
|
|
enter-from-class="translate-x-full opacity-0"
|
|
|
|
|
enter-to-class="translate-x-0 opacity-100"
|
|
|
|
|
leave-active-class="duration-500 ease-in"
|
|
|
|
|
leave-from-class="translate-x-0 opacity-100"
|
|
|
|
|
leave-to-class="translate-x-full opacity-0"
|
|
|
|
|
mode="out-in"
|
|
|
|
|
>
|
2024-04-15 19:39:03 +02:00
|
|
|
<div
|
|
|
|
|
v-if="!submitted"
|
|
|
|
|
key="form"
|
|
|
|
|
>
|
|
|
|
|
<open-form
|
|
|
|
|
v-if="form"
|
|
|
|
|
:form="form"
|
|
|
|
|
:loading="loading"
|
|
|
|
|
:fields="form.properties"
|
|
|
|
|
:theme="theme"
|
|
|
|
|
:dark-mode="darkMode"
|
|
|
|
|
:admin-preview="adminPreview"
|
|
|
|
|
@submit="submitForm"
|
2023-12-09 15:47:03 +01:00
|
|
|
>
|
|
|
|
|
<template #submit-btn="{submitForm}">
|
2024-04-15 19:39:03 +02:00
|
|
|
<open-form-button
|
|
|
|
|
:loading="loading"
|
|
|
|
|
:theme="theme"
|
|
|
|
|
:color="form.color"
|
|
|
|
|
class="mt-2 px-8 mx-1"
|
|
|
|
|
:class="submitButtonClass"
|
|
|
|
|
@click.prevent="submitForm"
|
2023-12-09 15:47:03 +01:00
|
|
|
>
|
|
|
|
|
{{ form.submit_button_text }}
|
|
|
|
|
</open-form-button>
|
|
|
|
|
</template>
|
|
|
|
|
</open-form>
|
2024-04-15 19:39:03 +02:00
|
|
|
<p
|
|
|
|
|
v-if="!form.no_branding"
|
|
|
|
|
class="text-center w-full mt-2"
|
|
|
|
|
>
|
|
|
|
|
<a
|
|
|
|
|
href="https://opnform.com?utm_source=form&utm_content=powered_by"
|
|
|
|
|
class="text-gray-400 hover:text-gray-500 dark:text-gray-600 dark:hover:text-gray-500 cursor-pointer hover:underline text-xs"
|
|
|
|
|
target="_blank"
|
2024-01-11 09:48:57 +01:00
|
|
|
>
|
|
|
|
|
Powered by <span class="font-semibold">OpnForm</span>
|
|
|
|
|
</a>
|
2023-12-09 15:47:03 +01:00
|
|
|
</p>
|
|
|
|
|
</div>
|
2024-04-15 19:39:03 +02:00
|
|
|
<div
|
|
|
|
|
v-else
|
|
|
|
|
key="submitted"
|
|
|
|
|
class="px-2"
|
|
|
|
|
>
|
|
|
|
|
<p
|
|
|
|
|
class="form-description text-gray-700 dark:text-gray-300 whitespace-pre-wrap"
|
|
|
|
|
v-html="form.submitted_text "
|
|
|
|
|
/>
|
|
|
|
|
<open-form-button
|
|
|
|
|
v-if="form.re_fillable"
|
|
|
|
|
:theme="theme"
|
|
|
|
|
:color="form.color"
|
|
|
|
|
class="my-4"
|
|
|
|
|
@click="restart"
|
|
|
|
|
>
|
2023-12-09 15:47:03 +01:00
|
|
|
{{ form.re_fill_button_text }}
|
|
|
|
|
</open-form-button>
|
2024-04-15 19:39:03 +02:00
|
|
|
<p
|
|
|
|
|
v-if="form.editable_submissions && submissionId"
|
|
|
|
|
class="mt-5"
|
|
|
|
|
>
|
|
|
|
|
<a
|
|
|
|
|
target="_parent"
|
|
|
|
|
:href="form.share_url+'?submission_id='+submissionId"
|
|
|
|
|
class="text-nt-blue hover:underline"
|
|
|
|
|
>
|
2023-12-09 15:47:03 +01:00
|
|
|
{{ form.editable_submissions_button_text }}
|
|
|
|
|
</a>
|
|
|
|
|
</p>
|
2024-04-15 19:39:03 +02:00
|
|
|
<p
|
|
|
|
|
v-if="!form.no_branding"
|
|
|
|
|
class="mt-5"
|
|
|
|
|
>
|
|
|
|
|
<a
|
|
|
|
|
target="_parent"
|
|
|
|
|
href="https://opnform.com/?utm_source=form&utm_content=create_form_free"
|
|
|
|
|
class="text-nt-blue hover:underline"
|
|
|
|
|
>
|
2024-01-11 09:48:57 +01:00
|
|
|
Create your form for free with OpnForm
|
|
|
|
|
</a>
|
2023-12-09 15:47:03 +01:00
|
|
|
</p>
|
|
|
|
|
</div>
|
|
|
|
|
</transition>
|
|
|
|
|
</div>
|
|
|
|
|
</template>
|
|
|
|
|
|
|
|
|
|
<script>
|
|
|
|
|
import OpenForm from './OpenForm.vue'
|
|
|
|
|
import OpenFormButton from './OpenFormButton.vue'
|
|
|
|
|
import VButton from '~/components/global/VButton.vue'
|
|
|
|
|
import FormCleanings from '../../pages/forms/show/FormCleanings.vue'
|
2023-12-24 20:19:59 +01:00
|
|
|
import VTransition from '~/components/global/transitions/VTransition.vue'
|
2024-04-15 19:39:03 +02:00
|
|
|
import {pendingSubmission} from "~/composables/forms/pendingSubmission.js"
|
|
|
|
|
import clonedeep from "clone-deep"
|
2024-06-27 17:52:49 +02:00
|
|
|
import ThemeBuilder from "~/lib/forms/themes/ThemeBuilder.js"
|
2023-12-09 15:47:03 +01:00
|
|
|
|
|
|
|
|
export default {
|
|
|
|
|
components: { VTransition, VButton, OpenFormButton, OpenForm, FormCleanings },
|
|
|
|
|
|
|
|
|
|
props: {
|
|
|
|
|
form: { type: Object, required: true },
|
|
|
|
|
creating: { type: Boolean, default: false }, // If true, fake form submit
|
|
|
|
|
adminPreview: { type: Boolean, default: false }, // If used in FormEditorPreview
|
2024-04-15 15:19:37 +02:00
|
|
|
submitButtonClass: { type: String, default: '' },
|
|
|
|
|
darkMode: {
|
|
|
|
|
type: Boolean,
|
|
|
|
|
default: false
|
|
|
|
|
}
|
2023-12-09 15:47:03 +01:00
|
|
|
},
|
|
|
|
|
|
2023-12-24 20:19:59 +01:00
|
|
|
setup(props) {
|
2023-12-19 13:46:55 +01:00
|
|
|
return {
|
2023-12-24 20:19:59 +01:00
|
|
|
isIframe: useIsIframe(),
|
2023-12-31 12:39:01 +01:00
|
|
|
pendingSubmission: pendingSubmission(props.form),
|
|
|
|
|
confetti: useConfetti()
|
2023-12-19 13:46:55 +01:00
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
|
2023-12-09 15:47:03 +01:00
|
|
|
data () {
|
|
|
|
|
return {
|
|
|
|
|
loading: false,
|
|
|
|
|
submitted: false,
|
2023-12-24 20:19:59 +01:00
|
|
|
passwordForm: useForm({
|
2023-12-09 15:47:03 +01:00
|
|
|
password: null
|
|
|
|
|
}),
|
|
|
|
|
hidePasswordDisabledMsg: false,
|
|
|
|
|
submissionId: false
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
computed: {
|
|
|
|
|
isEmbedPopup () {
|
2024-03-28 17:59:41 +01:00
|
|
|
return import.meta.client && window.location.href.includes('popup=true')
|
2023-12-09 15:47:03 +01:00
|
|
|
},
|
|
|
|
|
theme () {
|
2024-06-27 17:52:49 +02:00
|
|
|
return new ThemeBuilder(this.form.theme, {
|
|
|
|
|
size: this.form.size,
|
|
|
|
|
borderRadius: this.form.border_radius
|
|
|
|
|
}).getAllComponents()
|
2023-12-09 15:47:03 +01:00
|
|
|
},
|
|
|
|
|
isPublicFormPage () {
|
2024-01-16 12:58:41 +01:00
|
|
|
return this.$route.name === 'forms-slug'
|
2023-12-09 15:47:03 +01:00
|
|
|
},
|
|
|
|
|
isHideTitle () {
|
2024-03-28 17:59:41 +01:00
|
|
|
return this.form.hide_title || (import.meta.client && window.location.href.includes('hide_title=true'))
|
2023-12-09 15:47:03 +01:00
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
methods: {
|
|
|
|
|
submitForm (form, onFailure) {
|
|
|
|
|
if (this.creating) {
|
|
|
|
|
this.submitted = true
|
|
|
|
|
this.$emit('submitted', true)
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
2024-01-02 14:40:47 +01:00
|
|
|
if (form.busy) return
|
2023-12-09 15:47:03 +01:00
|
|
|
this.loading = true
|
2023-12-24 20:19:59 +01:00
|
|
|
// this.closeAlert()
|
|
|
|
|
form.post('/forms/' + this.form.slug + '/answer').then((data) => {
|
2024-01-13 19:57:39 +01:00
|
|
|
useAmplitude().logEvent('form_submission', {
|
2023-12-09 15:47:03 +01:00
|
|
|
workspace_id: this.form.workspace_id,
|
|
|
|
|
form_id: this.form.id
|
|
|
|
|
})
|
|
|
|
|
|
2024-01-13 19:57:39 +01:00
|
|
|
const payload = clonedeep({
|
2023-12-09 15:47:03 +01:00
|
|
|
type: 'form-submitted',
|
|
|
|
|
form: {
|
|
|
|
|
slug: this.form.slug,
|
2024-06-27 16:00:54 +02:00
|
|
|
id: this.form.id,
|
|
|
|
|
redirect_target_url: (this.form.is_pro && data.redirect && data.redirect_url) ? data.redirect_url : null
|
2023-12-09 15:47:03 +01:00
|
|
|
},
|
|
|
|
|
submission_data: form.data()
|
2024-01-13 19:57:39 +01:00
|
|
|
})
|
|
|
|
|
|
|
|
|
|
if (this.isIframe) {
|
|
|
|
|
window.parent.postMessage(payload, '*')
|
|
|
|
|
}
|
|
|
|
|
window.postMessage(payload, '*')
|
2024-02-03 12:50:57 +01:00
|
|
|
this.pendingSubmission.remove()
|
2023-12-09 15:47:03 +01:00
|
|
|
|
2023-12-24 20:19:59 +01:00
|
|
|
if (data.redirect && data.redirect_url) {
|
|
|
|
|
window.location.href = data.redirect_url
|
2023-12-09 15:47:03 +01:00
|
|
|
}
|
|
|
|
|
|
2023-12-24 20:19:59 +01:00
|
|
|
if (data.submission_id) {
|
|
|
|
|
this.submissionId = data.submission_id
|
2023-12-09 15:47:03 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
this.loading = false
|
|
|
|
|
this.submitted = true
|
|
|
|
|
this.$emit('submitted', true)
|
|
|
|
|
|
|
|
|
|
// If enabled display confetti
|
|
|
|
|
if (this.form.confetti_on_submission) {
|
2023-12-31 12:39:01 +01:00
|
|
|
this.confetti.play()
|
2023-12-09 15:47:03 +01:00
|
|
|
}
|
|
|
|
|
}).catch((error) => {
|
2024-01-13 19:57:39 +01:00
|
|
|
console.error(error)
|
2024-01-02 14:40:47 +01:00
|
|
|
if (error.response && error.data && error.data.message) {
|
|
|
|
|
useAlert().error(error.data.message)
|
2023-12-09 15:47:03 +01:00
|
|
|
}
|
|
|
|
|
this.loading = false
|
|
|
|
|
onFailure()
|
|
|
|
|
})
|
|
|
|
|
},
|
|
|
|
|
restart () {
|
|
|
|
|
this.submitted = false
|
|
|
|
|
this.$emit('restarted', true)
|
|
|
|
|
},
|
|
|
|
|
passwordEntered () {
|
|
|
|
|
if (this.passwordForm.password !== '' && this.passwordForm.password !== null) {
|
|
|
|
|
this.$emit('password-entered', this.passwordForm.password)
|
|
|
|
|
} else {
|
|
|
|
|
this.addPasswordError('The Password field is required.')
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
addPasswordError (msg) {
|
|
|
|
|
this.passwordForm.errors.set('password', msg)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
</script>
|
|
|
|
|
|
|
|
|
|
<style lang="scss">
|
|
|
|
|
.open-complete-form {
|
|
|
|
|
.form-description, .nf-text {
|
|
|
|
|
ol {
|
|
|
|
|
@apply list-decimal list-inside;
|
|
|
|
|
margin-left: 10px;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ul {
|
|
|
|
|
@apply list-disc list-inside;
|
|
|
|
|
margin-left: 10px;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
</style>
|