Zapier integration (#491)

* create zapier app

* install sanctum

* move OAuthProviderController

* make `api-external` middleware

* add zapier endpoints

* add tests

* token management

* zapier event handler

* add policy

* use `slug` instead of `id`

* wip

* check policies

* change api prefix to `external`

* ui tweaks

* validate token abilities

* open zapier URL

* zapier ui tweaks

* update zap

* Fix linting

* Added sample endpoints + minor UI changes

* Run PHP code linter

---------

Co-authored-by: Julien Nahum <julien@nahum.net>
This commit is contained in:
Boris Lepikhin
2024-08-12 02:14:02 -07:00
committed by GitHub
parent 7ad62fb3ea
commit 517bccc695
61 changed files with 5799 additions and 51 deletions

View File

@@ -1,7 +1,7 @@
<template>
<div class="flex flex-wrap sm:flex-nowrap my-4 w-full">
<div
class="w-full sm:w-auto border border-gray-300 rounded-md p-2 flex-grow select-all bg-gray-100"
class="flex-1 truncate sm:w-auto border border-gray-300 rounded-md p-2 flex-grow select-all bg-gray-100"
>
<p class="select-all text-gray-900">
{{ content }}
@@ -11,7 +11,7 @@
<v-button
color="light-gray"
class="w-full"
@click="copyToClipboard"
@click.prevent="copyToClipboard"
>
<slot name="icon">
<svg

View File

@@ -92,6 +92,7 @@
</v-button>
</template>
<a
v-if="integrationTypeInfo.is_editable !== false"
v-track.edit_form_integration_click="{
form_slug: form.slug,
form_integration_id: integration.id,
@@ -106,6 +107,21 @@
/>
Edit
</a>
<a
v-else-if="integrationTypeInfo.url"
v-track.edit_form_integration_click="{
form_slug: form.slug,
form_integration_id: integration.id,
}"
:href="integrationTypeInfo.url"
class="flex px-4 py-2 text-md text-gray-700 hover:bg-gray-100 hover:no-underline hover:text-gray-900 items-center"
>
<Icon
name="heroicons:pencil"
class="w-5 h-5 mr-2"
/>
Edit on {{ integrationTypeInfo.name }}
</a>
<a
v-track.past_events_form_integration_click="{
form_slug: form.slug,

View File

@@ -1,7 +1,7 @@
<template>
<UTooltip
:text="tooltipText"
:prevent="!unavailable"
:prevent="!unavailable || !tooltipText"
>
<div
v-track.new_integration_click="{ name: integration.id }"
@@ -32,6 +32,11 @@
>
(coming soon)</span>
</div>
<Icon
v-if="integration.is_external"
class="inline h-4 w-4 ml-1 inline text-gray-500"
name="heroicons:arrow-top-right-on-square-20-solid"
/>
</div>
<pro-tag
v-if="integration?.is_pro === true"
@@ -42,8 +47,10 @@
</template>
<script setup>
const emit = defineEmits(["select"])
import { computed } from 'vue'
import { useWorkspacesStore } from '@/stores/workspaces'
const emit = defineEmits(["select"])
const props = defineProps({
integration: {
type: Object,
@@ -51,22 +58,25 @@ const props = defineProps({
},
})
const workspacesStore = useWorkspacesStore()
const currentWorkspace = computed(() => workspacesStore.getCurrent)
const unavailable = computed(() => {
return (
props.integration.coming_soon || props.integration.requires_subscription
props.integration.coming_soon ||
(props.integration.requires_subscription && !currentWorkspace.value.is_pro)
)
})
const tooltipText = computed(() => {
if (props.integration.coming_soon) return "This integration is coming soon"
if (props.integration.requires_subscription)
if (props.integration.requires_subscription && !currentWorkspace.value.is_pro )
return "You need a subscription to use this integration."
return ""
return null
})
const onClick = () => {
if (props.integration.coming_soon || props.integration.requires_subscription)
return
if (unavailable.value) return
emit("select", props.integration.id)
}
</script>
</script>