diff --git a/apps/web/app/(app)/environments/[environmentId]/integrations/slack/components/SlackWrapper.tsx b/apps/web/app/(app)/environments/[environmentId]/integrations/slack/components/SlackWrapper.tsx
index b207f3faa8..cbbaab6649 100644
--- a/apps/web/app/(app)/environments/[environmentId]/integrations/slack/components/SlackWrapper.tsx
+++ b/apps/web/app/(app)/environments/[environmentId]/integrations/slack/components/SlackWrapper.tsx
@@ -1,11 +1,11 @@
"use client";
-import { refreshChannelsAction } from "@/app/(app)/environments/[environmentId]/integrations/slack/actions";
+import { getSlackChannelsAction } from "@/app/(app)/environments/[environmentId]/integrations/slack/actions";
import { AddChannelMappingModal } from "@/app/(app)/environments/[environmentId]/integrations/slack/components/AddChannelMappingModal";
import { ManageIntegration } from "@/app/(app)/environments/[environmentId]/integrations/slack/components/ManageIntegration";
import { authorize } from "@/app/(app)/environments/[environmentId]/integrations/slack/lib/slack";
import slackLogo from "@/images/slacklogo.png";
-import { useState } from "react";
+import { useEffect, useState } from "react";
import { TAttributeClass } from "@formbricks/types/attribute-classes";
import { TEnvironment } from "@formbricks/types/environment";
import { TIntegrationItem } from "@formbricks/types/integration";
@@ -18,7 +18,6 @@ interface SlackWrapperProps {
isEnabled: boolean;
environment: TEnvironment;
surveys: TSurvey[];
- channelsArray: TIntegrationItem[];
slackIntegration?: TIntegrationSlack;
webAppUrl: string;
attributeClasses: TAttributeClass[];
@@ -29,27 +28,38 @@ export const SlackWrapper = ({
isEnabled,
environment,
surveys,
- channelsArray,
slackIntegration,
webAppUrl,
attributeClasses,
locale,
}: SlackWrapperProps) => {
const [isConnected, setIsConnected] = useState(slackIntegration ? slackIntegration.config?.key : false);
- const [slackChannels, setSlackChannels] = useState(channelsArray);
+ const [slackChannels, setSlackChannels] = useState([]);
const [isModalOpen, setModalOpen] = useState(false);
+ const [showReconnectButton, setShowReconnectButton] = useState(false);
const [selectedIntegration, setSelectedIntegration] = useState<
(TIntegrationSlackConfigData & { index: number }) | null
>(null);
- const refreshChannels = async () => {
- const refreshChannelsResponse = await refreshChannelsAction({ environmentId: environment.id });
+ const getSlackChannels = async () => {
+ const getSlackChannelsResponse = await getSlackChannelsAction({ environmentId: environment.id });
- if (refreshChannelsResponse?.data) {
- setSlackChannels(refreshChannelsResponse.data);
+ if (
+ getSlackChannelsResponse?.serverError &&
+ getSlackChannelsResponse.serverError.includes("missing_scope")
+ ) {
+ setShowReconnectButton(true);
+ }
+
+ if (getSlackChannelsResponse?.data) {
+ setSlackChannels(getSlackChannelsResponse.data);
}
};
+ useEffect(() => {
+ getSlackChannels();
+ }, []);
+
const handleSlackAuthorization = async () => {
authorize(environment.id, webAppUrl).then((url: string) => {
if (url) {
@@ -76,7 +86,9 @@ export const SlackWrapper = ({
setOpenAddIntegrationModal={setModalOpen}
setIsConnected={setIsConnected}
setSelectedIntegration={setSelectedIntegration}
- refreshChannels={refreshChannels}
+ refreshChannels={getSlackChannels}
+ showReconnectButton={showReconnectButton}
+ handleSlackAuthorization={handleSlackAuthorization}
locale={locale}
/>
>
diff --git a/apps/web/app/(app)/environments/[environmentId]/integrations/slack/page.tsx b/apps/web/app/(app)/environments/[environmentId]/integrations/slack/page.tsx
index 10687c64c8..2fb8ee989b 100644
--- a/apps/web/app/(app)/environments/[environmentId]/integrations/slack/page.tsx
+++ b/apps/web/app/(app)/environments/[environmentId]/integrations/slack/page.tsx
@@ -12,10 +12,8 @@ import { getIntegrationByType } from "@formbricks/lib/integration/service";
import { getMembershipByUserIdOrganizationId } from "@formbricks/lib/membership/service";
import { getAccessFlags } from "@formbricks/lib/membership/utils";
import { getProductByEnvironmentId } from "@formbricks/lib/product/service";
-import { getSlackChannels } from "@formbricks/lib/slack/service";
import { getSurveys } from "@formbricks/lib/survey/service";
import { findMatchingLocale } from "@formbricks/lib/utils/locale";
-import { TIntegrationItem } from "@formbricks/types/integration";
import { TIntegrationSlack } from "@formbricks/types/integration/slack";
import { GoBackButton } from "@formbricks/ui/components/GoBackButton";
import { PageContentWrapper } from "@formbricks/ui/components/PageContentWrapper";
@@ -45,10 +43,6 @@ const Page = async ({ params }) => {
throw new Error(t("common.product_not_found"));
}
- let channelsArray: TIntegrationItem[] = [];
- if (slackIntegration && slackIntegration.config.key) {
- channelsArray = await getSlackChannels(params.environmentId);
- }
const locale = await findMatchingLocale();
const currentUserMembership = await getMembershipByUserIdOrganizationId(
@@ -75,7 +69,6 @@ const Page = async ({ params }) => {
{
const url = req.url;
@@ -58,18 +62,20 @@ export const GET = async (req: NextRequest) => {
team: data.team,
};
+ const slackIntegration = await getIntegrationByType(environmentId, "slack");
+
const slackConfiguration: TIntegrationSlackConfig = {
- data: [],
+ data: (slackIntegration?.config.data as TIntegrationSlackConfigData[]) ?? [],
key: slackCredentials,
};
- const slackIntegration = {
+ const integration = {
type: "slack" as "slack",
environment: environmentId,
config: slackConfiguration,
};
- const result = await createOrUpdateIntegration(environmentId, slackIntegration);
+ const result = await createOrUpdateIntegration(environmentId, integration);
if (result) {
return Response.redirect(`${WEBAPP_URL}/environments/${environmentId}/integrations/slack`);
diff --git a/apps/web/lib/utils/action-client.ts b/apps/web/lib/utils/action-client.ts
index 495f11562d..67c94f7774 100644
--- a/apps/web/lib/utils/action-client.ts
+++ b/apps/web/lib/utils/action-client.ts
@@ -22,7 +22,6 @@ export const actionClient = createSafeActionClient({
}
console.error("SERVER ERROR: ", e);
-
return DEFAULT_SERVER_ERROR_MESSAGE;
},
});
diff --git a/packages/lib/constants.ts b/packages/lib/constants.ts
index fc557b7904..da1b192fc7 100644
--- a/packages/lib/constants.ts
+++ b/packages/lib/constants.ts
@@ -53,7 +53,7 @@ export const INVITE_DISABLED = env.INVITE_DISABLED === "1";
export const SLACK_CLIENT_SECRET = env.SLACK_CLIENT_SECRET;
export const SLACK_CLIENT_ID = env.SLACK_CLIENT_ID;
-export const SLACK_AUTH_URL = `https://slack.com/oauth/v2/authorize?client_id=${env.SLACK_CLIENT_ID}&scope=channels:read,chat:write,chat:write.public,chat:write.customize`;
+export const SLACK_AUTH_URL = `https://slack.com/oauth/v2/authorize?client_id=${env.SLACK_CLIENT_ID}&scope=channels:read,chat:write,chat:write.public,chat:write.customize,groups:read`;
export const GOOGLE_SHEETS_CLIENT_ID = env.GOOGLE_SHEETS_CLIENT_ID;
export const GOOGLE_SHEETS_CLIENT_SECRET = env.GOOGLE_SHEETS_CLIENT_SECRET;
diff --git a/packages/lib/messages/de-DE.json b/packages/lib/messages/de-DE.json
index 9f419483be..9c0b5759a9 100644
--- a/packages/lib/messages/de-DE.json
+++ b/packages/lib/messages/de-DE.json
@@ -685,7 +685,9 @@
"select_channel": "Kanal auswählen",
"slack_integration": "Slack Integration",
"slack_integration_description": "Sende Antworten direkt an Slack.",
- "slack_integration_is_not_configured": "Slack Integration ist in deiner Instanz von Formbricks nicht konfiguriert."
+ "slack_integration_is_not_configured": "Slack Integration ist in deiner Instanz von Formbricks nicht konfiguriert.",
+ "slack_reconnect_button": "Erneut verbinden",
+ "slack_reconnect_button_description": "Hinweis: Wir haben kürzlich unsere Slack-Integration geändert, um auch private Kanäle zu unterstützen. Bitte verbinden Sie Ihren Slack-Workspace erneut."
},
"slack_integration_description": "Verbinde deinen Slack Arbeitsbereich sofort mit Formbricks",
"to_configure_it": "es zu konfigurieren.",
diff --git a/packages/lib/messages/en-US.json b/packages/lib/messages/en-US.json
index 5d937a2409..6dfb1a5449 100644
--- a/packages/lib/messages/en-US.json
+++ b/packages/lib/messages/en-US.json
@@ -685,7 +685,9 @@
"select_channel": "Select Channel",
"slack_integration": "Slack Integration",
"slack_integration_description": "Send responses directly to Slack.",
- "slack_integration_is_not_configured": "Slack Integration is not configured in your instance of Formbricks."
+ "slack_integration_is_not_configured": "Slack Integration is not configured in your instance of Formbricks.",
+ "slack_reconnect_button": "Reconnect",
+ "slack_reconnect_button_description": "Note: We recently changed our Slack integration to also support private channels. Please reconnect your Slack workspace."
},
"slack_integration_description": "Instantly connect your Slack Workspace with Formbricks",
"to_configure_it": "to configure it.",
diff --git a/packages/lib/messages/pt-BR.json b/packages/lib/messages/pt-BR.json
index 4c9ebf7374..1dcd7d4c57 100644
--- a/packages/lib/messages/pt-BR.json
+++ b/packages/lib/messages/pt-BR.json
@@ -685,7 +685,9 @@
"select_channel": "Selecionar Canal",
"slack_integration": "Integração com o Slack",
"slack_integration_description": "Manda as respostas direto pro Slack.",
- "slack_integration_is_not_configured": "A integração do Slack não está configurada na sua instância do Formbricks."
+ "slack_integration_is_not_configured": "A integração do Slack não está configurada na sua instância do Formbricks.",
+ "slack_reconnect_button": "Reconectar",
+ "slack_reconnect_button_description": "Observação: Recentemente, alteramos nossa integração com o Slack para também suportar canais privados. Por favor, reconecte seu workspace do Slack."
},
"slack_integration_description": "Conecte instantaneamente seu Workspace do Slack com o Formbricks",
"to_configure_it": "configurar isso.",
diff --git a/packages/lib/slack/service.ts b/packages/lib/slack/service.ts
index 5adbef16dd..f76f893998 100644
--- a/packages/lib/slack/service.ts
+++ b/packages/lib/slack/service.ts
@@ -1,5 +1,5 @@
import { Prisma } from "@prisma/client";
-import { DatabaseError } from "@formbricks/types/errors";
+import { DatabaseError, UnknownError } from "@formbricks/types/errors";
import { TIntegration, TIntegrationItem } from "@formbricks/types/integration";
import { TIntegrationSlack, TIntegrationSlackCredential } from "@formbricks/types/integration/slack";
import { deleteIntegration, getIntegrationByType } from "../integration/service";
@@ -11,8 +11,9 @@ export const fetchChannels = async (slackIntegration: TIntegration): Promise