fix: recall in slack integration (#4304)

This commit is contained in:
Dhruwang Jariwala
2024-11-15 09:47:26 +05:30
committed by GitHub
parent 98181bfe6c
commit 41f42f4427
5 changed files with 47 additions and 15 deletions

View File

@@ -81,7 +81,7 @@ const Page = async (props) => {
return (
<PageContentWrapper>
<GoBackButton url={`${WEBAPP_URL}/environments/${params.environmentId}/integrations`} />
<PageHeader pageTitle={"environments.integrations.notion.notion_integration"} />
<PageHeader pageTitle={t("environments.integrations.notion.notion_integration")} />
<NotionWrapper
enabled={enabled}
surveys={surveys}

View File

@@ -91,7 +91,7 @@ export const ManageIntegration = ({
<span className="mr-4 h-4 w-4 rounded-full bg-green-600"></span>
<span className="text-slate-500">
{t("environments.integrations.slack.connected_with_team", {
team: slackIntegration.config.key.team.name,
team: slackIntegration.config.key.team?.name,
})}
</span>
</div>

View File

@@ -46,7 +46,8 @@ export const SlackWrapper = ({
if (
getSlackChannelsResponse?.serverError &&
getSlackChannelsResponse.serverError.includes("missing_scope")
(getSlackChannelsResponse.serverError.includes("missing_scope") ||
getSlackChannelsResponse.serverError.includes("invalid_auth"))
) {
setShowReconnectButton(true);
}

View File

@@ -4,8 +4,10 @@ import { getLocalizedValue } from "@formbricks/lib/i18n/utils";
import { writeData as writeNotionData } from "@formbricks/lib/notion/service";
import { processResponseData } from "@formbricks/lib/responses";
import { writeDataToSlack } from "@formbricks/lib/slack/service";
import { parseRecallInfo } from "@formbricks/lib/utils/recall";
import { TAttributes } from "@formbricks/types/attributes";
import { Result } from "@formbricks/types/error-handlers";
import { TIntegration } from "@formbricks/types/integration";
import { TIntegration, TIntegrationType } from "@formbricks/types/integration";
import { TIntegrationAirtable } from "@formbricks/types/integration/airtable";
import { TIntegrationGoogleSheets } from "@formbricks/types/integration/google-sheet";
import { TIntegrationNotion, TIntegrationNotionConfigData } from "@formbricks/types/integration/notion";
@@ -29,18 +31,20 @@ const convertMetaObjectToString = (metadata: TResponseMeta): string => {
};
const processDataForIntegration = async (
integrationType: TIntegrationType,
data: TPipelineInput,
survey: TSurvey,
includeVariables: boolean,
includeMetadata: boolean,
includeHiddenFields: boolean,
questionIds: string[]
questionIds: string[],
attributes?: TAttributes
): Promise<string[][]> => {
const ids =
includeHiddenFields && survey.hiddenFields.fieldIds
? [...questionIds, ...survey.hiddenFields.fieldIds]
: questionIds;
const values = await extractResponses(data, ids, survey);
const values = await extractResponses(integrationType, data, ids, survey, attributes);
if (includeMetadata) {
values[0].push(convertMetaObjectToString(data.response.meta));
values[1].push("Metadata");
@@ -61,7 +65,8 @@ const processDataForIntegration = async (
export const handleIntegrations = async (
integrations: TIntegration[],
data: TPipelineInput,
survey: TSurvey
survey: TSurvey,
attributes: TAttributes
) => {
for (const integration of integrations) {
switch (integration.type) {
@@ -76,7 +81,12 @@ export const handleIntegrations = async (
}
break;
case "slack":
const slackResult = await handleSlackIntegration(integration as TIntegrationSlack, data, survey);
const slackResult = await handleSlackIntegration(
integration as TIntegrationSlack,
data,
survey,
attributes
);
if (!slackResult.ok) {
console.error("Error in slack integration: ", slackResult.error);
}
@@ -111,6 +121,7 @@ const handleAirtableIntegration = async (
for (const element of integration.config.data) {
if (element.surveyId === data.surveyId) {
const values = await processDataForIntegration(
"airtable",
data,
survey,
!!element.includeVariables,
@@ -145,6 +156,7 @@ const handleGoogleSheetsIntegration = async (
for (const element of integration.config.data) {
if (element.surveyId === data.surveyId) {
const values = await processDataForIntegration(
"googleSheets",
data,
survey,
!!element.includeVariables,
@@ -177,19 +189,22 @@ const handleGoogleSheetsIntegration = async (
const handleSlackIntegration = async (
integration: TIntegrationSlack,
data: TPipelineInput,
survey: TSurvey
survey: TSurvey,
attributes: TAttributes
): Promise<Result<void, Error>> => {
try {
if (integration.config.data.length > 0) {
for (const element of integration.config.data) {
if (element.surveyId === data.surveyId) {
const values = await processDataForIntegration(
"slack",
data,
survey,
!!element.includeVariables,
!!element.includeMetadata,
!!element.includeHiddenFields,
element.questionIds
element.questionIds,
attributes
);
await writeDataToSlack(integration.config.key, element.channelId, values, survey?.name);
}
@@ -209,9 +224,11 @@ const handleSlackIntegration = async (
};
const extractResponses = async (
integrationType: TIntegrationType,
pipelineData: TPipelineInput,
questionIds: string[],
survey: TSurvey
survey: TSurvey,
attributes?: TAttributes
): Promise<string[][]> => {
const responses: string[] = [];
const questions: string[] = [];
@@ -246,7 +263,22 @@ const extractResponses = async (
} else {
responses.push("");
}
questions.push(getLocalizedValue(question?.headline, "default") || "");
// Create emptyResponseObject with same keys but empty string values
const emptyResponseObject = Object.keys(pipelineData.response.data).reduce(
(acc, key) => {
acc[key] = "";
return acc;
},
{} as Record<string, string>
);
questions.push(
parseRecallInfo(
getLocalizedValue(question?.headline, "default"),
integrationType === "slack" ? attributes : {},
integrationType === "slack" ? pipelineData.response.data : emptyResponseObject,
integrationType === "slack" ? pipelineData.response.variables : {}
) || ""
);
}
return [responses, questions];

View File

@@ -42,6 +42,7 @@ export const POST = async (request: Request) => {
}
const { environmentId, surveyId, event, response } = inputValidation.data;
const attributes = response.person?.id ? await getAttributes(response.person?.id) : {};
// Fetch webhooks
const getWebhooksForPipeline = cache(
@@ -99,7 +100,7 @@ export const POST = async (request: Request) => {
}
if (integrations.length > 0) {
await handleIntegrations(integrations, inputValidation.data, survey);
await handleIntegrations(integrations, inputValidation.data, survey, attributes);
}
// Fetch users with notifications in a single query
@@ -197,8 +198,6 @@ export const POST = async (request: Request) => {
const isAIEnabled = await getIsAIEnabled(organization);
if (isAIEnabled) {
const attributes = response.person?.id ? await getAttributes(response.person?.id) : {};
for (const question of survey.questions) {
if (question.type === "openText" && question.insightsEnabled) {
const isQuestionAnswered =