Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,8 @@ const renderElementSelection = ({
setIncludeMetadata,
includeCreatedAt,
setIncludeCreatedAt,
includeContactAttributes,
setIncludeContactAttributes,
}: {
t: TFunction;
selectedSurvey: TSurvey;
Expand All @@ -135,6 +137,8 @@ const renderElementSelection = ({
setIncludeMetadata: (value: boolean) => void;
includeCreatedAt: boolean;
setIncludeCreatedAt: (value: boolean) => void;
includeContactAttributes: boolean;
setIncludeContactAttributes: (value: boolean) => void;
}) => {
return (
<div className="space-y-4">
Expand Down Expand Up @@ -164,6 +168,8 @@ const renderElementSelection = ({
setIncludeMetadata={setIncludeMetadata}
includeCreatedAt={includeCreatedAt}
setIncludeCreatedAt={setIncludeCreatedAt}
includeContactAttributes={includeContactAttributes}
setIncludeContactAttributes={setIncludeContactAttributes}
/>
</div>
);
Expand All @@ -187,6 +193,7 @@ export const AddIntegrationModal = ({
const [includeHiddenFields, setIncludeHiddenFields] = useState(false);
const [includeMetadata, setIncludeMetadata] = useState(false);
const [includeCreatedAt, setIncludeCreatedAt] = useState(true);
const [includeContactAttributes, setIncludeContactAttributes] = useState(false);
const airtableIntegrationData: TIntegrationAirtableInput = {
type: "airtable",
config: {
Expand All @@ -205,6 +212,7 @@ export const AddIntegrationModal = ({
setIncludeHiddenFields(!!defaultData.includeHiddenFields);
setIncludeMetadata(!!defaultData.includeMetadata);
setIncludeCreatedAt(!!defaultData.includeCreatedAt);
setIncludeContactAttributes(!!defaultData.includeContactAttributes);
} else {
reset();
}
Expand Down Expand Up @@ -259,6 +267,7 @@ export const AddIntegrationModal = ({
includeHiddenFields,
includeMetadata,
includeCreatedAt,
includeContactAttributes,
};

if (isEditMode) {
Expand Down Expand Up @@ -446,6 +455,8 @@ export const AddIntegrationModal = ({
setIncludeMetadata,
includeCreatedAt,
setIncludeCreatedAt,
includeContactAttributes,
setIncludeContactAttributes,
})}
</div>
</DialogBody>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -147,6 +147,7 @@ export const ManageIntegration = ({
includeHiddenFields: !!data.includeHiddenFields,
includeMetadata: !!data.includeMetadata,
includeCreatedAt: !!data.includeCreatedAt,
includeContactAttributes: !!data.includeContactAttributes,
index,
});
setIsModalOpen(true);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,4 +7,5 @@ export type IntegrationModalInputs = {
includeHiddenFields: boolean;
includeMetadata: boolean;
includeCreatedAt: boolean;
includeContactAttributes: boolean;
};
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,7 @@ export const AddIntegrationModal = ({
const [includeHiddenFields, setIncludeHiddenFields] = useState(false);
const [includeMetadata, setIncludeMetadata] = useState(false);
const [includeCreatedAt, setIncludeCreatedAt] = useState(true);
const [includeContactAttributes, setIncludeContactAttributes] = useState(false);
const googleSheetIntegrationData: TIntegrationGoogleSheetsInput = {
type: "googleSheets",
config: {
Expand Down Expand Up @@ -115,6 +116,7 @@ export const AddIntegrationModal = ({
setIncludeHiddenFields(!!selectedIntegration.includeHiddenFields);
setIncludeMetadata(!!selectedIntegration.includeMetadata);
setIncludeCreatedAt(!!selectedIntegration.includeCreatedAt);
setIncludeContactAttributes(!!selectedIntegration.includeContactAttributes);
return;
} else {
setSpreadsheetUrl("");
Expand Down Expand Up @@ -172,6 +174,7 @@ export const AddIntegrationModal = ({
integrationData.includeHiddenFields = includeHiddenFields;
integrationData.includeMetadata = includeMetadata;
integrationData.includeCreatedAt = includeCreatedAt;
integrationData.includeContactAttributes = includeContactAttributes;
if (selectedIntegration) {
// update action
googleSheetIntegrationData.config.data[selectedIntegration.index] = integrationData;
Expand Down Expand Up @@ -331,6 +334,8 @@ export const AddIntegrationModal = ({
setIncludeMetadata={setIncludeMetadata}
includeCreatedAt={includeCreatedAt}
setIncludeCreatedAt={setIncludeCreatedAt}
includeContactAttributes={includeContactAttributes}
setIncludeContactAttributes={setIncludeContactAttributes}
/>
</div>
)}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import { useEffect, useMemo, useState } from "react";
import { useForm } from "react-hook-form";
import toast from "react-hot-toast";
import { useTranslation } from "react-i18next";
import { TContactAttributeKey } from "@formbricks/types/contact-attribute-key";
import { TIntegrationInput } from "@formbricks/types/integration";
import {
TIntegrationNotion,
Expand Down Expand Up @@ -46,6 +47,7 @@ interface AddIntegrationModalProps {
notionIntegration: TIntegrationNotion;
databases: TIntegrationNotionDatabase[];
selectedIntegration: (TIntegrationNotionConfigData & { index: number }) | null;
contactAttributeKeys: TContactAttributeKey[];
}

export const AddIntegrationModal = ({
Expand All @@ -56,6 +58,7 @@ export const AddIntegrationModal = ({
notionIntegration,
databases,
selectedIntegration,
contactAttributeKeys,
}: AddIntegrationModalProps) => {
const { t } = useTranslation();
const { handleSubmit } = useForm();
Expand Down Expand Up @@ -146,10 +149,15 @@ export const AddIntegrationModal = ({
type: TSurveyElementTypeEnum.Date,
},
];
const personAttributes = contactAttributeKeys.map((attributeKey) => ({
id: `person.${attributeKey.key}`,
name: `${t("common.person")}: ${attributeKey.name ?? attributeKey.key}`,
type: TSurveyElementTypeEnum.OpenText,
}));

return [...mappedElements, ...variables, ...hiddenFields, ...Metadata, ...createdAt];
return [...mappedElements, ...variables, ...hiddenFields, ...Metadata, ...createdAt, ...personAttributes];
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [selectedSurvey?.id]);
}, [selectedSurvey?.id, contactAttributeKeys]);

useEffect(() => {
if (selectedIntegration) {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
"use client";

import { useState } from "react";
import { TContactAttributeKey } from "@formbricks/types/contact-attribute-key";
import {
TIntegrationNotion,
TIntegrationNotionConfigData,
Expand All @@ -22,6 +23,7 @@ interface NotionWrapperProps {
surveys: TSurvey[];
databasesArray: TIntegrationNotionDatabase[];
locale: TUserLocale;
contactAttributeKeys: TContactAttributeKey[];
}

export const NotionWrapper = ({
Expand All @@ -32,6 +34,7 @@ export const NotionWrapper = ({
surveys,
databasesArray,
locale,
contactAttributeKeys,
}: NotionWrapperProps) => {
const [isModalOpen, setIsModalOpen] = useState(false);
const [isConnected, setIsConnected] = useState(
Expand Down Expand Up @@ -61,6 +64,7 @@ export const NotionWrapper = ({
notionIntegration={notionIntegration}
databases={databasesArray}
selectedIntegration={selectedIntegration}
contactAttributeKeys={contactAttributeKeys}
/>
<ManageIntegration
notionIntegration={notionIntegration}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import { getIntegrationByType } from "@/lib/integration/service";
import { getNotionDatabases } from "@/lib/notion/service";
import { getUserLocale } from "@/lib/user/service";
import { getTranslate } from "@/lingodotdev/server";
import { getContactAttributeKeys } from "@/modules/ee/contacts/lib/contact-attribute-keys";
import { GoBackButton } from "@/modules/ui/components/go-back-button";
import { PageContentWrapper } from "@/modules/ui/components/page-content-wrapper";
import { PageHeader } from "@/modules/ui/components/page-header";
Expand All @@ -31,10 +32,11 @@ const Page = async (props: { params: Promise<{ workspaceId: string }> }) => {

const { isReadOnly, session, workspace } = await getWorkspaceAuth(params.workspaceId);

const [surveys, notionIntegration, locale] = await Promise.all([
const [surveys, notionIntegration, locale, contactAttributeKeys] = await Promise.all([
getSurveys(workspace.id),
getIntegrationByType(workspace.id, "notion"),
getUserLocale(session.user.id),
getContactAttributeKeys(workspace.id),
]);

let databasesArray: TIntegrationNotionDatabase[] = [];
Expand All @@ -58,6 +60,7 @@ const Page = async (props: { params: Promise<{ workspaceId: string }> }) => {
webAppUrl={WEBAPP_URL}
databasesArray={databasesArray}
locale={locale ?? DEFAULT_LOCALE}
contactAttributeKeys={contactAttributeKeys}
/>
</PageContentWrapper>
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@ export const AddChannelMappingModal = ({
const [includeHiddenFields, setIncludeHiddenFields] = useState(false);
const [includeMetadata, setIncludeMetadata] = useState(false);
const [includeCreatedAt, setIncludeCreatedAt] = useState(true);
const [includeContactAttributes, setIncludeContactAttributes] = useState(false);
const existingIntegrationData = slackIntegration?.config?.data;
const slackIntegrationData: TIntegrationSlackInput = {
type: "slack",
Expand Down Expand Up @@ -104,6 +105,7 @@ export const AddChannelMappingModal = ({
setIncludeHiddenFields(!!selectedIntegration.includeHiddenFields);
setIncludeMetadata(!!selectedIntegration.includeMetadata);
setIncludeCreatedAt(!!selectedIntegration.includeCreatedAt);
setIncludeContactAttributes(!!selectedIntegration.includeContactAttributes);
return;
}
resetForm();
Expand Down Expand Up @@ -137,6 +139,7 @@ export const AddChannelMappingModal = ({
includeHiddenFields,
includeMetadata,
includeCreatedAt,
includeContactAttributes,
};
if (selectedIntegration) {
// update action
Expand Down Expand Up @@ -324,6 +327,8 @@ export const AddChannelMappingModal = ({
setIncludeMetadata={setIncludeMetadata}
includeCreatedAt={includeCreatedAt}
setIncludeCreatedAt={setIncludeCreatedAt}
includeContactAttributes={includeContactAttributes}
setIncludeContactAttributes={setIncludeContactAttributes}
/>
</div>
)}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { AuthenticationError, ResourceNotFoundError } from "@formbricks/types/er
import { SurveyAnalysisNavigation } from "@/app/(app)/workspaces/[workspaceId]/surveys/[surveyId]/(analysis)/components/SurveyAnalysisNavigation";
import { ResponsePage } from "@/app/(app)/workspaces/[workspaceId]/surveys/[surveyId]/(analysis)/responses/components/ResponsePage";
import { SurveyAnalysisCTA } from "@/app/(app)/workspaces/[workspaceId]/surveys/[surveyId]/(analysis)/summary/components/SurveyAnalysisCTA";
import { getAISmartToolsUnavailableReason, getOrganizationAIConfig } from "@/lib/ai/service";
import {
ENTERPRISE_LICENSE_REQUEST_FORM_URL,
IS_FORMBRICKS_CLOUD,
Expand Down Expand Up @@ -60,6 +61,9 @@ const Page = async (props: { params: Promise<{ workspaceId: string; surveyId: st
const isQuotasAllowed = await getIsQuotasEnabled(organization.id);
const quotas = isQuotasAllowed ? await getQuotas(survey.id) : [];

const aiConfig = await getOrganizationAIConfig(organization.id);
const aiUnavailableReason = getAISmartToolsUnavailableReason(aiConfig) ?? null;

// Fetch initial responses on the server to prevent duplicate client-side fetch
const initialResponses = await getResponses(params.surveyId, RESPONSES_PER_PAGE, 0);

Expand All @@ -78,6 +82,7 @@ const Page = async (props: { params: Promise<{ workspaceId: string; surveyId: st
isFormbricksCloud={IS_FORMBRICKS_CLOUD}
isStorageConfigured={IS_STORAGE_CONFIGURED}
enterpriseLicenseRequestFormUrl={ENTERPRISE_LICENSE_REQUEST_FORM_URL}
aiUnavailableReason={aiUnavailableReason}
/>
}>
<SurveyAnalysisNavigation survey={survey} activeId="responses" />
Expand Down
Loading
Loading