From 0920690816ffc8b569b2fddfd42c42ebdd94bcc2 Mon Sep 17 00:00:00 2001 From: Sacha Al Himdani Date: Thu, 26 Mar 2026 18:04:59 +0100 Subject: [PATCH] Add ability to disconnect Slack channel from compliance page Users could connect a Slack channel to their compliance page but had no way to remove or change the connection afterward. This adds a disconnect button with a confirmation dialog next to connected Slack channels. - GraphQL: deleteSlackConnection mutation with resolver - Frontend: Disconnect button using useMutation with @deleteEdge Signed-off-by: Sacha Al Himdani --- .../CompliancePageSlackSection.tsx | 64 ++++++++++++++++--- pkg/server/api/console/v1/schema.graphql | 16 ++++- pkg/server/api/console/v1/v1_resolver.go | 28 ++++++++ 3 files changed, 99 insertions(+), 9 deletions(-) diff --git a/apps/console/src/pages/organizations/compliance-page/overview/_components/CompliancePageSlackSection.tsx b/apps/console/src/pages/organizations/compliance-page/overview/_components/CompliancePageSlackSection.tsx index 76270a85c..37a2fd437 100644 --- a/apps/console/src/pages/organizations/compliance-page/overview/_components/CompliancePageSlackSection.tsx +++ b/apps/console/src/pages/organizations/compliance-page/overview/_components/CompliancePageSlackSection.tsx @@ -1,36 +1,76 @@ import { sprintf } from "@probo/helpers"; import { useTranslate } from "@probo/i18n"; -import { Badge, Button, Card, Slack } from "@probo/ui"; -import { useFragment } from "react-relay"; +import { Badge, Button, Card, Slack, useConfirm } from "@probo/ui"; +import { useFragment, useMutation } from "react-relay"; import { graphql } from "relay-runtime"; +import type { CompliancePageSlackSectionDeleteMutation } from "#/__generated__/core/CompliancePageSlackSectionDeleteMutation.graphql"; import type { CompliancePageSlackSectionFragment$key } from "#/__generated__/core/CompliancePageSlackSectionFragment.graphql"; import { useOrganizationId } from "#/hooks/useOrganizationId"; const fragment = graphql` fragment CompliancePageSlackSectionFragment on Organization { - compliancePage: trustCenter { - canUpdate: permission(action: "core:trust-center:update") - } + canConnectSlack: permission(action: "core:connector:initiate") slackConnections(first: 100) { + __id edges { node { id channel createdAt + canDelete: permission(action: "core:connector:delete") } } } } `; +const deleteMutation = graphql` + mutation CompliancePageSlackSectionDeleteMutation( + $input: DeleteSlackConnectionInput! + $connections: [ID!]! + ) { + deleteSlackConnection(input: $input) { + deletedSlackConnectionId @deleteEdge(connections: $connections) + } + } +`; + export function CompliancePageSlackSection(props: { fragmentRef: CompliancePageSlackSectionFragment$key }) { const { fragmentRef } = props; const organizationId = useOrganizationId(); const { __, dateTimeFormat } = useTranslate(); + const confirm = useConfirm(); const organization = useFragment(fragment, fragmentRef); + const [deleteSlackConnection] = useMutation(deleteMutation); + + const connectionId = organization.slackConnections.__id; + + const handleDisconnect = (slackConnectionId: string) => { + confirm( + () => + new Promise((resolve, reject) => { + deleteSlackConnection({ + variables: { + connections: [connectionId], + input: { + slackConnectionId, + }, + }, + onCompleted: () => resolve(), + onError: error => reject(error), + }); + }), + { + title: __("Disconnect Slack"), + message: __("Are you sure you want to disconnect this Slack channel? This action cannot be undone."), + label: __("Disconnect"), + variant: "danger", + }, + ); + }; return (
@@ -60,14 +100,22 @@ export function CompliancePageSlackSection(props: { fragmentRef: CompliancePageS )}

-
+
{__("Connected")} + {slackConnection.canDelete && ( + + )}
))} - {organization.compliancePage?.canUpdate && organization.slackConnections.edges.length === 0 && ( + {organization.canConnectSlack && organization.slackConnections.edges.length === 0 && (