From f9fef32d062839400c765e9c1a75c16518a199f7 Mon Sep 17 00:00:00 2001 From: hugocasa Date: Thu, 15 Oct 2026 18:50:57 +0200 Subject: [PATCH] feat: show the OAuth app status in each native trigger card's header App actions move into a menu, the card body holds only the shared account, and service descriptions name what fires the trigger. Co-Authored-By: Claude Opus 5.5 --- .../native/NativeConnectionPicker.svelte | 2 +- .../WorkspaceIntegrations.svelte | 185 ++++++++---------- 2 files changed, 81 insertions(+), 106 deletions(-) diff --git a/frontend/src/lib/components/triggers/native/NativeConnectionPicker.svelte b/frontend/src/lib/components/triggers/native/NativeConnectionPicker.svelte index 19ea251241..9a280bd758 100644 --- a/frontend/src/lib/components/triggers/native/NativeConnectionPicker.svelte +++ b/frontend/src/lib/components/triggers/native/NativeConnectionPicker.svelte @@ -121,7 +121,7 @@ const items = $derived.by(() => { const list = (connections ?? []).map((c) => ({ - label: c.workspace && labelWorkspace ? `${c.path} (workspace connection)` : c.path, + label: c.workspace && labelWorkspace ? `${c.path} (shared account)` : c.path, value: c.path })) if (value && !list.some((i) => i.value === value)) { diff --git a/frontend/src/lib/components/workspaceSettings/WorkspaceIntegrations.svelte b/frontend/src/lib/components/workspaceSettings/WorkspaceIntegrations.svelte index 2335ab1d5e..7dbb6f9fce 100644 --- a/frontend/src/lib/components/workspaceSettings/WorkspaceIntegrations.svelte +++ b/frontend/src/lib/components/workspaceSettings/WorkspaceIntegrations.svelte @@ -4,7 +4,9 @@ import { Button, Alert } from '$lib/components/common' import Skeleton from '$lib/components/common/skeleton/Skeleton.svelte' import SettingsPageHeader from '$lib/components/settings/SettingsPageHeader.svelte' - import { ExternalLink } from 'lucide-svelte' + import { ExternalLink, KeyRound, Pencil, Trash2 } from 'lucide-svelte' + import DropdownV2 from '$lib/components/DropdownV2.svelte' + import type { Item } from '$lib/utils' import NextcloudIcon from '$lib/components/icons/NextcloudIcon.svelte' import GithubIcon from '$lib/components/icons/GithubIcon.svelte' import GoogleIcon from '$lib/components/icons/GoogleIcon.svelte' @@ -13,7 +15,6 @@ type NativeServiceName, type NativeTriggerConnection } from '$lib/gen' - import ClipboardPanel from '$lib/components/details/ClipboardPanel.svelte' import OAuthClientConfig from './OAuthClientConfig.svelte' import ConfirmationModal from '../common/confirmationModal/ConfirmationModal.svelte' import { createAsyncConfirmationModal } from '../common/confirmationModal/asyncConfirmationModal.svelte' @@ -46,7 +47,7 @@ nextcloud: { name: 'nextcloud', displayName: 'Nextcloud', - description: 'Connect to Nextcloud for file operations and webhook triggers', + description: 'File events', icon: NextcloudIcon, docsUrl: 'https://www.windmill.dev/docs/integrations/nextcloud', setupInstructions: [ @@ -58,7 +59,7 @@ google: { name: 'google', displayName: 'Google', - description: 'Connect to Google for Drive and Calendar triggers', + description: 'Drive and Calendar changes', icon: GoogleIcon, docsUrl: 'https://www.windmill.dev/docs/core_concepts/native_triggers#google-triggers', requiresBaseUrl: false, @@ -75,7 +76,7 @@ github: { name: 'github', displayName: 'GitHub', - description: 'Connect to GitHub for repository webhook triggers', + description: 'Repository events', icon: GithubIcon, docsUrl: 'https://www.windmill.dev/docs/core_concepts/native_triggers#github-triggers', requiresBaseUrl: false, @@ -171,7 +172,7 @@ if (!confirmed) return } else { const confirmed = await confirmationModal.ask({ - title: 'Stop sharing the workspace connection?', + title: 'Stop sharing this account?', confirmationText: 'Stop sharing', children: `Members will no longer be able to create or edit ${displayName} triggers through it, unless they can read it. Its triggers keep running.` }) @@ -184,13 +185,19 @@ serviceName: serviceName as NativeServiceName, requestBody: { path: path ?? null } }) - sendUserToast(path ? `${path} is now the workspace connection` : 'Stopped sharing') + sendUserToast(path ? `${path} is now the shared account` : 'Stopped sharing') await loadConnections(serviceName) } catch (err: any) { - sendUserToast(`Failed to update the workspace connection: ${err.body ?? err.message}`, true) + sendUserToast(`Failed to update the shared account: ${err.body ?? err.message}`, true) } } + function docsItem(config: ServiceConfig): Item[] { + return config.docsUrl + ? [{ displayName: 'Docs', icon: ExternalLink, href: config.docsUrl, hrefTarget: '_blank' }] + : [] + } + async function openConfig(serviceName: string, leavingInstanceApp: boolean) { const displayName = supportedServices[serviceName]?.displayName ?? serviceName // A refresh token only works with the OAuth app that issued it. @@ -286,7 +293,7 @@
@@ -304,112 +311,80 @@ {@const usesInstanceApp = !workspaceApp && instanceSharingAvailable[serviceName]} {@const workspaceConnection = connections[serviceName]?.find((c) => c.workspace)?.path} -
-
-
- -
-
{config.displayName}
-
{config.description}
-
+
+
+ +
+
{config.displayName}
+
{config.description}
- {#if config.docsUrl} +
+ + {workspaceApp + ? 'Workspace OAuth app' + : usesInstanceApp + ? 'Instance OAuth app' + : 'Not set up'} +
+ {#if workspaceApp || usesInstanceApp} + openConfig(serviceName, false) + }, + ...docsItem(config), + { + displayName: `Remove ${config.displayName}`, + icon: Trash2, + type: 'delete', + action: () => deleteIntegration(serviceName) + } + ] + : [ + { + displayName: 'Use a workspace OAuth app', + icon: KeyRound, + action: () => openConfig(serviceName, true) + }, + ...docsItem(config) + ]} + /> + {:else} {/if}
-
-
-
-
- {#if workspaceApp} - Workspace OAuth app - {:else if usesInstanceApp} - Shared by your instance admin - {:else} - No OAuth app yet - {/if} -
- {#if usesInstanceApp} - - {/if} -
-
- {#if workspaceApp} - - - {:else if !usesInstanceApp} - - {/if} + {#if workspaceApp || usesInstanceApp} +
+
Shared account
+
+ Members can create triggers as this account without seeing its token.
+ setWorkspaceConnection(serviceName, path)} + onConnectionsChange={() => loadConnections(serviceName)} + />
- - {#if usesInstanceApp && serviceName === 'google'} -
-
- The instance app must list this redirect URI in the - Google Cloud Console -
- -
- {/if} - - {#if workspaceApp || usesInstanceApp} -
-
Workspace connection
-
- Members can create triggers as this account without seeing its token. -
- setWorkspaceConnection(serviceName, path)} - onConnectionsChange={() => loadConnections(serviceName)} - /> -
- {/if} -
+ {/if}