Apply Mentions everywhere (#595)

* variables and mentions

* fix lint

* add missing changes

* fix tests

* update quilly, fix bugs

* fix lint

* apply fixes

* apply fixes

* Fix MentionParser

* Apply Mentions everywhere

* Fix MentionParserTest

* Small refactoring

* Fixing quill import issues

* Polished email integration, added customer sender mail

* Add missing changes

* improve migration command

---------

Co-authored-by: Frank <csskfaves@gmail.com>
Co-authored-by: Julien Nahum <julien@nahum.net>
This commit is contained in:
Chirag Chhatrala
2024-10-22 14:04:29 +05:30
committed by GitHub
parent 2fdf2a439b
commit dad5c825b1
50 changed files with 1903 additions and 874 deletions

View File

@@ -29,7 +29,10 @@
<h4 class="font-bold mt-4">
Discord message options
</h4>
<notifications-message-actions v-model="integrationData.settings" />
<notifications-message-actions
v-model="integrationData.settings"
:form="form"
/>
</IntegrationWrapper>
</template>

View File

@@ -14,18 +14,66 @@
</NuxtLink> to send emails from your own domain.
</p>
<text-area-input
<MentionInput
:form="integrationData"
name="settings.notification_emails"
:mentions="form.properties"
:disable-mention="!form.is_pro"
name="settings.send_to"
required
label="Notification Emails"
label="Send To"
help="Add one email per line"
/>
<text-input
/>
<div class="flex space-x-4">
<text-input
:form="integrationData"
name="settings.sender_name"
label="Sender Name"
class="flex-1"
/>
<text-input
v-if="selfHosted"
:form="integrationData"
name="settings.sender_email"
label="Sender Email"
help="If supported by email provider - default otherwise"
class="flex-1"
/>
</div>
<MentionInput
:form="integrationData"
name="settings.notification_reply_to"
label="Notification Reply To"
:help="notifiesHelp"
:mentions="form.properties"
required
name="settings.subject"
label="Subject"
/>
<rich-text-area-input
:form="integrationData"
:enable-mentions="true"
:mentions="form.properties"
name="settings.email_content"
label="Email Content"
/>
<toggle-switch-input
:form="integrationData"
name="settings.include_submission_data"
class="mt-4"
label="Include submission data"
help="If enabled the email will contain form submission answers"
/>
<toggle-switch-input
v-if="integrationData.settings.include_submission_data"
:form="integrationData"
name="settings.include_hidden_fields_submission_data"
class="mt-4"
label="Include hidden fields"
help="If enabled the email will contain hidden fields"
/>
<MentionInput
:form="integrationData"
:mentions="form.properties"
name="settings.reply_to"
label="Reply To"
help="If empty, Reply-to will be your own email."
/>
</IntegrationWrapper>
</template>
@@ -40,22 +88,19 @@ const props = defineProps({
formIntegrationId: { type: Number, required: false, default: null },
})
const replayToEmailField = computed(() => {
const emailFields = props.form.properties.filter((field) => {
return field.type === "email" && !field.hidden
})
if (emailFields.length === 1) return emailFields[0]
return null
})
const selfHosted = computed(() => useFeatureFlag('self_hosted'))
const notifiesHelp = computed(() => {
if (replayToEmailField.value) {
return (
'If empty, Reply-to for this notification will be the email filled in the field "' +
replayToEmailField.value.name +
'".'
)
onBeforeMount(() => {
for (const [keyname, defaultValue] of Object.entries({
sender_name: "OpnForm",
subject: "We saved your answers",
email_content: "Hello there 👋 <br>This is a confirmation that your submission was successfully saved.",
include_submission_data: true,
include_hidden_fields_submission_data: false,
})) {
if (props.integrationData.settings[keyname] === undefined) {
props.integrationData.settings[keyname] = defaultValue
}
}
return "If empty, Reply-to for this notification will be your own email. Add a single email field to your form, and it will automatically become the reply to value."
})
</script>

View File

@@ -29,7 +29,10 @@
<h4 class="font-bold mt-4">
Slack message actions
</h4>
<notifications-message-actions v-model="integrationData.settings" />
<notifications-message-actions
v-model="integrationData.settings"
:form="form"
/>
</IntegrationWrapper>
</template>

View File

@@ -1,108 +0,0 @@
<template>
<IntegrationWrapper
v-model="props.integrationData"
:integration="props.integration"
:form="form"
>
<div class="text-gray-500 text-sm">
{{ emailSubmissionConfirmationHelp }}
</div>
<p class="text-gray-500 text-sm mb-3">
You can <NuxtLink
class="underline"
:to="{ name: 'settings-workspace' }"
target="_blank"
>
use our custom SMTP feature
</NuxtLink> to send emails from your own domain.
</p>
<div v-if="emailSubmissionConfirmationField">
<text-input
:form="integrationData"
name="settings.notification_sender"
class="mt-4"
required
label="Confirmation Email Sender Name"
help="Emails will be sent from our email address but you can customize the name of the Sender"
/>
<text-input
:form="integrationData"
name="settings.notification_subject"
class="mt-4"
required
label="Confirmation email subject"
help="Subject of the confirmation email that will be sent"
/>
<rich-text-area-input
:form="integrationData"
name="settings.notification_body"
class="mt-4"
required
label="Confirmation email content"
help="Content of the confirmation email that will be sent"
/>
<text-input
:form="integrationData"
name="settings.confirmation_reply_to"
class="mt-4"
label="Confirmation Reply To"
help="If empty, Reply-to will be your own email."
/>
<toggle-switch-input
:form="integrationData"
name="settings.notifications_include_submission"
class="mt-4"
label="Include submission data"
help="If enabled the confirmation email will contain form submission answers"
/>
</div>
</IntegrationWrapper>
</template>
<script setup>
import IntegrationWrapper from "./components/IntegrationWrapper.vue"
const props = defineProps({
integration: { type: Object, required: true },
form: { type: Object, required: true },
integrationData: { type: Object, required: true },
formIntegrationId: { type: Number, required: false, default: null },
})
const emailSubmissionConfirmationField = computed(() => {
if (!props.form.properties || !Array.isArray(props.form.properties))
return null
const emailFields = props.form.properties.filter((field) => {
return field.type === "email" && !field.hidden
})
if (emailFields.length === 1) return emailFields[0]
return null
})
const emailSubmissionConfirmationHelp = computed(() => {
if (emailSubmissionConfirmationField.value) {
return (
'Confirmation will be sent to the email in the "' +
emailSubmissionConfirmationField.value.name +
'" field.'
)
}
return "Only available if your form contains 1 email field."
})
onBeforeMount(() => {
for (const [keyname, defaultValue] of Object.entries({
respondent_email: emailSubmissionConfirmationField.value !== null,
notification_sender: "OpnForm",
notification_subject: "We saved your answers",
notification_body:
"Hello there 👋 <br>This is a confirmation that your submission was successfully saved.",
notifications_include_submission: true,
})) {
if (keyname === 'respondent_email' || props.integrationData.settings[keyname] === undefined) {
props.integrationData.settings[keyname] = defaultValue
}
}
})
</script>

View File

@@ -11,19 +11,18 @@
label="Enabled"
/>
</slot>
<slot name="help">
<v-button
class="flex"
color="white"
size="small"
<slot
v-if="integration?.crisp_help_page_slug"
name="help"
>
<UButton
color="gray"
size="sm"
icon="i-heroicons-question-mark-circle-solid"
@click="openHelp"
>
<Icon
name="heroicons:question-mark-circle-16-solid"
class="w-4 h-4 text-gray-500 -mt-[3px]"
/>
<span class="text-gray-500"> Help </span>
</v-button>
Help
</UButton>
</slot>
</div>

View File

@@ -1,5 +1,13 @@
<template>
<div>
<MentionInput
v-model="compVal.message"
:mentions="form.properties"
name="message"
class="mt-4"
label="Notification Message"
help="Customize the text of the notification message. Click @ to include form field values."
/>
<toggle-switch-input
v-model="compVal.include_submission_data"
name="include_submission_data"
@@ -43,6 +51,7 @@ export default {
components: {},
props: {
modelValue: { type: Object, required: false },
form: { type: Object, required: true },
},
emits: ['modelValue', 'input'],
data() {
@@ -74,6 +83,7 @@ export default {
this.compVal = {}
}
[
"message",
"include_submission_data",
"link_open_form",
"link_edit_form",
@@ -81,7 +91,11 @@ export default {
"link_edit_submission",
].forEach((keyname) => {
if (this.compVal[keyname] === undefined) {
this.compVal[keyname] = true
if (keyname === 'message') {
this.compVal[keyname] = 'New form submission'
} else {
this.compVal[keyname] = true
}
}
})
},