Improve google sheet integration (#437)

* fix integration modal error

* Provider card icon dynamic

* Google Sheets Integration Actions fetch integration data till interval

* fix show form tablist - params slug issue

* validation on delete connection

---------

Co-authored-by: Julien Nahum <julien@nahum.net>
This commit is contained in:
Chirag Chhatrala 2024-06-07 15:42:24 +05:30 committed by GitHub
parent 17476107df
commit ca0864d0c0
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
8 changed files with 61 additions and 16 deletions

View File

@ -2,6 +2,7 @@
namespace App\Policies; namespace App\Policies;
use App\Models\Integration\FormIntegration;
use App\Models\OAuthProvider; use App\Models\OAuthProvider;
use App\Models\User; use App\Models\User;
use Illuminate\Auth\Access\HandlesAuthorization; use Illuminate\Auth\Access\HandlesAuthorization;
@ -57,6 +58,10 @@ class OAuthProviderPolicy
*/ */
public function delete(User $user, OAuthProvider $provider) public function delete(User $user, OAuthProvider $provider)
{ {
$integrations = FormIntegration::where('oauth_id', $provider->id)->get();
if ($integrations->count() > 0) {
return $this->denyWithStatus(400, 'This connection cannot be removed because there is already an integration using it.');
}
return $provider->user()->is($user); return $provider->user()->is($user);
} }

View File

@ -14,7 +14,10 @@
</div> </div>
</div> </div>
<div class="ml-auto"> <div
v-if="integration.data"
class="ml-auto"
>
<v-button <v-button
:href="integration.data.url" :href="integration.data.url"
target="_blank" target="_blank"
@ -27,7 +30,30 @@
</template> </template>
<script setup> <script setup>
defineProps({ const props = defineProps({
integration: Object, integration: {
type: Object,
required: true,
},
form: {
type: Object,
required: true,
}
})
const formIntegrationsStore = useFormIntegrationsStore()
let interval = null
onMounted(() => {
if (!props.integration.data) {
interval = setInterval(() => formIntegrationsStore.fetchFormIntegrations(props.form.id), 3000)
setTimeout(() => { clearInterval(interval) }, 30000)
}
})
onBeforeUnmount(() => {
if (interval) {
clearInterval(interval)
}
}) })
</script> </script>

View File

@ -37,6 +37,7 @@
:is="actionsComponent" :is="actionsComponent"
v-if="actionsComponent" v-if="actionsComponent"
:integration="integration" :integration="integration"
:form="form"
/> />
<div <div

View File

@ -50,8 +50,7 @@ const props = defineProps({
form: { type: Object, required: true }, form: { type: Object, required: true },
integrationKey: { type: String, required: true }, integrationKey: { type: String, required: true },
integration: { type: Object, required: true }, integration: { type: Object, required: true },
formIntegrationId: { type: Number, required: false, default: null }, formIntegrationId: { type: Number, required: false, default: null }
providers: { type: Array, required: true }
}) })
const alert = useAlert() const alert = useAlert()

View File

@ -7,7 +7,7 @@
class="mr-4 text-blue-500" class="mr-4 text-blue-500"
> >
<Icon <Icon
name="mdi:google" :name="service?.icon"
size="32px" size="32px"
/> />
</div> </div>
@ -87,6 +87,7 @@ const props = defineProps({
}) })
const providersStore = useOAuthProvidersStore() const providersStore = useOAuthProvidersStore()
const service = computed(() => providersStore.getService(props.provider?.provider))
const alert = useAlert() const alert = useAlert()
function disconnect() { function disconnect() {

View File

@ -65,15 +65,7 @@ defineProps({
const emit = defineEmits(['close']) const emit = defineEmits(['close'])
const providersStore = useOAuthProvidersStore() const providersStore = useOAuthProvidersStore()
const services = computed(() => providersStore.services)
const services = [
{
name: 'google',
title: 'Google',
icon: 'mdi:google',
enabled: true
},
]
function connect(service) { function connect(service) {
providersStore.connect(service.name) providersStore.connect(service.name)

View File

@ -200,7 +200,7 @@
class="mr-6" class="mr-6"
> >
<nuxt-link <nuxt-link
:to="{ name: tab.route }" :to="{ name: tab.route, params: tab.params ?? {} }"
class="hover:no-underline inline-block py-4 rounded-t-lg border-b-2 text-gray-500 hover:text-gray-600" class="hover:no-underline inline-block py-4 rounded-t-lg border-b-2 text-gray-500 hover:text-gray-600"
active-class="text-blue-600 hover:text-blue-900 dark:text-blue-500 dark:hover:text-blue-500 border-blue-600 dark:border-blue-500" active-class="text-blue-600 hover:text-blue-900 dark:text-blue-500 dark:hover:text-blue-500 border-blue-600 dark:border-blue-500"
> >
@ -277,18 +277,22 @@ const tabsList = [
{ {
name: "Submissions", name: "Submissions",
route: "forms-slug-show-submissions", route: "forms-slug-show-submissions",
params: { 'slug': slug }
}, },
{ {
name: "Integrations", name: "Integrations",
route: "forms-slug-show-integrations", route: "forms-slug-show-integrations",
params: { 'slug': slug }
}, },
{ {
name: "Analytics", name: "Analytics",
route: "forms-slug-show-stats", route: "forms-slug-show-stats",
params: { 'slug': slug }
}, },
{ {
name: "Share", name: "Share",
route: "forms-slug-show-share", route: "forms-slug-show-share",
params: { 'slug': slug }
}, },
] ]

View File

@ -7,6 +7,21 @@ export const useOAuthProvidersStore = defineStore("oauth_providers", () => {
const contentStore = useContentStore() const contentStore = useContentStore()
const alert = useAlert() const alert = useAlert()
const services = computed(() => {
return [
{
name: 'google',
title: 'Google',
icon: 'mdi:google',
enabled: true
}
]
})
const getService = (service) => {
return services.value.find((item) => item.name === service)
}
const fetchOAuthProviders = () => { const fetchOAuthProviders = () => {
contentStore.resetState() contentStore.resetState()
contentStore.startLoading() contentStore.startLoading()
@ -50,6 +65,8 @@ export const useOAuthProvidersStore = defineStore("oauth_providers", () => {
return { return {
...contentStore, ...contentStore,
services,
getService,
fetchOAuthProviders, fetchOAuthProviders,
providers, providers,
connect connect