Notification & Integrations refactoring (#346)
* Integrations Refactoring - WIP * integrations list & edit - WIP * Fix integration store binding issue * integrations refactor - WIP * Form integration - WIP * Form integration Edit - WIP * Integration Refactor - Slack - WIP * Integration Refactor - Discord - WIP * Integration Refactor - Webhook - WIP * Integration Refactor - Send Submission Confirmation - WIP * Integration Refactor - Backend handler - WIP * Form Integration Status field * Integration Refactor - Backend SubmissionConfirmation - WIP * IntegrationMigration Command * skip confirmation email test case * Small refactoring * FormIntegration status active/inactive * formIntegrationData to integrationData * Rename file name with Integration suffix for integration realted files * Loader on form integrations * WIP * form integration test case * WIP * Added Integration card - working on refactoring * change location for IntegrationCard and update package file * Form Integration Create/Edit in single Modal * Remove integration extra pages * crisp_help_page_slug for integration json * integration logic as collapse * UI improvements * WIP * Trying to debug vue devtools * WIP for integrations * getIntegrationHandler change namespace name * useForm for integration fields + validation structure * Integration Test case & apply validation rules * Apply useform changes to integration other files * validation rules for FormNotificationsMessageActions fields * Zapier integration as coming soon * Update FormCleaner * set default settings for confirmation integration * WIP * Finish validation for all integrations * Updated purify, added integration formatData * Fix testcase * Ran pint; working on integration errors * Handle integration events * command for Delete Old Integration Events * Display Past Events in Modal * on Integration event create with status error send email to form creator * Polish styling * Minor improvements * Finish badge and integration status * Fix tests and add an integration event test * Lint --------- Co-authored-by: Julien Nahum <julien@nahum.net>
This commit is contained in:
50
client/components/global/Badge.vue
Normal file
50
client/components/global/Badge.vue
Normal file
@@ -0,0 +1,50 @@
|
||||
<template>
|
||||
<div :class="classes">
|
||||
<Icon v-if="beforeIcon" :name="beforeIcon" :class="iconClasses"/>
|
||||
<slot></slot>
|
||||
<Icon v-if="afterIcon" :name="afterIcon" :class="iconClasses"/>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
|
||||
const props = defineProps({
|
||||
color: {
|
||||
type: String,
|
||||
default: 'green'
|
||||
},
|
||||
beforeIcon: {
|
||||
type: String,
|
||||
default: null
|
||||
},
|
||||
afterIcon: {
|
||||
type: String,
|
||||
default: null
|
||||
}
|
||||
})
|
||||
|
||||
const baseClasses = {
|
||||
'green': ['bg-green-100', 'border', 'border-green-300', 'text-green-700'],
|
||||
'red': ['bg-red-100', 'border', 'border-red-300', 'text-red-700'],
|
||||
'gray': ['bg-gray-100', 'border', 'border-gray-300', 'text-gray-700'],
|
||||
}
|
||||
|
||||
const iconBaseClasses = {
|
||||
'green': ['text-green-500'],
|
||||
'red': ['text-red-500'],
|
||||
'gray': ['text-gray-500'],
|
||||
}
|
||||
|
||||
const activeColor = computed(() => {
|
||||
return Object.hasOwn(baseClasses, props.color) ? props.color : 'gray'
|
||||
})
|
||||
|
||||
const classes = computed(() => {
|
||||
const classes = ['border', 'text-xs', 'px-2', 'inline-flex', 'items-center', 'rounded-full'].concat(baseClasses[activeColor.value])
|
||||
return classes.join(' ')
|
||||
})
|
||||
|
||||
const iconClasses = computed(() => {
|
||||
return iconBaseClasses[activeColor.value].concat(['w-2 h-2 mr-1']).join(' ')
|
||||
})
|
||||
</script>
|
||||
@@ -7,7 +7,7 @@
|
||||
@click.self="close"
|
||||
>
|
||||
<div ref="content"
|
||||
class="self-start bg-white dark:bg-notion-dark w-full relative p-4 md:p-6 my-6 rounded-xl shadow-xl"
|
||||
class="self-start bg-white dark:bg-notion-dark w-full relative my-6 rounded-xl shadow-xl"
|
||||
:class="maxWidthClass"
|
||||
>
|
||||
<div v-if="closeable" class="absolute top-4 right-4">
|
||||
@@ -19,15 +19,17 @@
|
||||
</svg>
|
||||
</button>
|
||||
</div>
|
||||
<div class="sm:flex sm:flex-col sm:items-start">
|
||||
<div v-if="$slots.hasOwnProperty('icon')" class="flex w-full justify-center mb-4">
|
||||
<div class="flex border-b pb-4"
|
||||
v-if="$slots.hasOwnProperty('icon') || $slots.hasOwnProperty('title')"
|
||||
:class="[{'flex-col sm:items-start':!compactHeader, 'items-center justify-center py-6 gap-x-4':compactHeader},headerInnerPadding]">
|
||||
<div v-if="$slots.hasOwnProperty('icon')" :class="{'w-full mb-4 flex justify-center':!compactHeader}">
|
||||
<div class="w-14 h-14 rounded-full flex justify-center items-center"
|
||||
:class="'bg-'+iconColor+'-100 text-'+iconColor+'-600'"
|
||||
>
|
||||
<slot name="icon"/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="mt-3 text-center sm:mt-0 w-full">
|
||||
<div class="mt-3 text-center sm:mt-0" :class="{'w-full':!compactHeader}">
|
||||
<h2 v-if="$slots.hasOwnProperty('title')"
|
||||
class="text-2xl font-semibold text-center text-gray-900"
|
||||
>
|
||||
@@ -36,11 +38,11 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="w-full">
|
||||
<div class="w-full" :class="innerPadding">
|
||||
<slot/>
|
||||
</div>
|
||||
|
||||
<div v-if="$slots.hasOwnProperty('footer')" class="px-6 py-4 bg-gray-100 text-right">
|
||||
<div v-if="$slots.hasOwnProperty('footer')" class="bg-gray-50 border-t rounded-b-xl text-right" :class="footerInnerPadding">
|
||||
<slot name="footer"/>
|
||||
</div>
|
||||
</div>
|
||||
@@ -66,19 +68,34 @@ const props = defineProps({
|
||||
maxWidth: {
|
||||
default: '2xl'
|
||||
},
|
||||
innerPadding: {
|
||||
default: 'p-6'
|
||||
},
|
||||
headerInnerPadding: {
|
||||
default: 'p-6'
|
||||
},
|
||||
footerInnerPadding: {
|
||||
default: 'p-6'
|
||||
},
|
||||
closeable: {
|
||||
default: true
|
||||
}
|
||||
},
|
||||
compactHeader: {
|
||||
default: false,
|
||||
type: Boolean
|
||||
},
|
||||
})
|
||||
|
||||
const emit = defineEmits(['close'])
|
||||
|
||||
useHead({
|
||||
bodyAttrs: {
|
||||
class: {
|
||||
'overflow-hidden': props.show
|
||||
bodyAttrs: computed(() => {
|
||||
return {
|
||||
class: {
|
||||
'overflow-hidden': props.show
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
const closeOnEscape = (e) => {
|
||||
@@ -146,7 +163,8 @@ const motionSlideBottom = {
|
||||
}
|
||||
|
||||
const onLeave = (el, done) => {
|
||||
contentMotion.value.leave(()=>{})
|
||||
contentMotion.value.leave(() => {
|
||||
})
|
||||
backdropMotion.value.leave(done)
|
||||
}
|
||||
|
||||
|
||||
@@ -1,43 +1,45 @@
|
||||
<template>
|
||||
<div class="inline" v-if="shouldDisplayProTag">
|
||||
<div class="bg-nt-blue text-white px-2 text-xs uppercase inline rounded-full font-semibold cursor-pointer"
|
||||
@click.prevent="showPremiumModal=true"
|
||||
>
|
||||
PRO
|
||||
</div>
|
||||
<modal :show="showPremiumModal" @close="showPremiumModal=false">
|
||||
<h2 class="text-nt-blue">
|
||||
OpnForm PRO
|
||||
</h2>
|
||||
<h4 v-if="user && user.is_subscribed" class="text-center mt-5">
|
||||
We're happy to have you as a Pro customer. If you're having any issue with OpnForm, or if you have a
|
||||
feature request, please <a href="mailto:contact@opnform.com">contact us</a>.
|
||||
</h4>
|
||||
<div v-if="!user || !user.is_subscribed" class="mt-4">
|
||||
<p>
|
||||
All the features with a<span
|
||||
class="bg-nt-blue text-white px-2 text-xs uppercase inline rounded-full font-semibold mx-1"
|
||||
>
|
||||
<UTooltip text="Upgrade to use this feature">
|
||||
<div role="button" class="bg-nt-blue text-white px-2 text-xs uppercase inline rounded-full font-semibold cursor-pointer"
|
||||
@click="showPremiumModal=true">
|
||||
PRO
|
||||
</div>
|
||||
<modal :show="showPremiumModal" @close="showPremiumModal=false">
|
||||
<h2 class="text-nt-blue">
|
||||
OpnForm PRO
|
||||
</h2>
|
||||
<h4 v-if="user && user.is_subscribed" class="text-center mt-5">
|
||||
We're happy to have you as a Pro customer. If you're having any issue with OpnForm, or if you have a
|
||||
feature request, please <a href="mailto:contact@opnform.com">contact us</a>.
|
||||
</h4>
|
||||
<div v-if="!user || !user.is_subscribed" class="mt-4">
|
||||
<p>
|
||||
All the features with a<span
|
||||
class="bg-nt-blue text-white px-2 text-xs uppercase inline rounded-full font-semibold mx-1"
|
||||
>
|
||||
PRO
|
||||
</span> tag are available in the Pro plan of OpnForm. <b>You can play around and try all Pro features
|
||||
within
|
||||
the form editor, but you can't use them in your real forms</b>. You can subscribe now to gain unlimited access
|
||||
to
|
||||
all our pro features!
|
||||
</p>
|
||||
</div>
|
||||
within
|
||||
the form editor, but you can't use them in your real forms</b>. You can subscribe now to gain unlimited
|
||||
access
|
||||
to
|
||||
all our pro features!
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div class="my-4 text-center">
|
||||
<v-button color="white" @click="showPremiumModal=false">
|
||||
Close
|
||||
</v-button>
|
||||
</div>
|
||||
</modal>
|
||||
<div class="my-4 text-center">
|
||||
<v-button color="white" @click="showPremiumModal=false">
|
||||
Close
|
||||
</v-button>
|
||||
</div>
|
||||
</modal>
|
||||
</UTooltip>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { computed } from 'vue'
|
||||
import {computed} from 'vue'
|
||||
|
||||
const authStore = useAuthStore()
|
||||
const workspacesStore = useWorkspacesStore()
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import throttle from 'lodash.throttle'
|
||||
import throttle from 'lodash/throttle'
|
||||
function newResizeObserver (callback) {
|
||||
// Skip this feature for browsers which
|
||||
// do not support ResizeObserver.
|
||||
|
||||
Reference in New Issue
Block a user