diff --git a/frontend/src/lib/constants.tsx b/frontend/src/lib/constants.tsx index ed1e9c5c7f0f0..67871e3e05cef 100644 --- a/frontend/src/lib/constants.tsx +++ b/frontend/src/lib/constants.tsx @@ -351,6 +351,7 @@ export const FEATURE_FLAGS = { SURVEYS_FF_CROSS_SELL: 'surveys-ff-cross-sell', // owner: @adboio #team-surveys SURVEYS_INSIGHT_BUTTON_EXPERIMENT: 'ask-users-why-ai-vs-quickcreate', // owner: @adboio #team-surveys multivariate SURVEYS_EXPERIMENTS_CROSS_SELL: 'surveys-experiments-cross-sell', // owner: @adboio #team-surveys + SURVEYS_EXPERIMENTS_BUTTON_EXPERIMENT: 'create-survey-from-experiment---ai-vs-modal', // owner: @adboio #team-surveys multivariate } as const export type FeatureFlagLookupKey = keyof typeof FEATURE_FLAGS export type FeatureFlagKey = (typeof FEATURE_FLAGS)[keyof typeof FEATURE_FLAGS] diff --git a/frontend/src/scenes/experiments/ExperimentView/components.tsx b/frontend/src/scenes/experiments/ExperimentView/components.tsx index 1f40fce313504..22d6d3a29ecb8 100644 --- a/frontend/src/scenes/experiments/ExperimentView/components.tsx +++ b/frontend/src/scenes/experiments/ExperimentView/components.tsx @@ -29,12 +29,12 @@ import { IconAreaChart } from 'lib/lemon-ui/icons' import { ButtonPrimitive } from 'lib/ui/Button/ButtonPrimitives' import { userHasAccess } from 'lib/utils/accessControlUtils' import { addProductIntent } from 'lib/utils/product-intents' -import { useMaxTool } from 'scenes/max/useMaxTool' import { sceneLogic } from 'scenes/sceneLogic' import { SURVEY_CREATED_SOURCE } from 'scenes/surveys/constants' +import { QuickSurveyModal } from 'scenes/surveys/quick-create/QuickSurveyModal' +import { QuickSurveyType } from 'scenes/surveys/quick-create/types' import { captureMaxAISurveyCreationException } from 'scenes/surveys/utils' import { urls } from 'scenes/urls' -import { userLogic } from 'scenes/userLogic' import { iconForType } from '~/layout/panel-layout/ProjectTree/defaultTree' import { ScenePanel, ScenePanelActionsSection } from '~/layout/scenes/SceneLayout' @@ -65,6 +65,7 @@ import { } from '~/types' import { DuplicateExperimentModal } from '../DuplicateExperimentModal' +import { useExperimentSurvey } from '../Experiments' import { CONCLUSION_DISPLAY_CONFIG, EXPERIMENT_VARIANT_MULTIPLE } from '../constants' import { experimentLogic } from '../experimentLogic' import { getExperimentStatusColor } from '../experimentsLogic' @@ -421,11 +422,14 @@ export function PageHeaderCustom(): JSX.Element { setHogfettiTrigger, } = useActions(experimentLogic) const { openShipVariantModal, openStopExperimentModal } = useActions(modalsLogic) - const { user } = useValues(userLogic) const [duplicateModalOpen, setDuplicateModalOpen] = useState(false) + const [surveyModalOpen, setSurveyModalOpen] = useState(false) const { newTab } = useActions(sceneLogic) - // Initialize MaxTool hook for experiment survey creation - const { openMax } = useMaxTool(createMaxToolExperimentSurveyConfig(experiment, user)) + const { + handleClick: handleSurveyClick, + isDisabled: isSurveyDisabled, + hasFeatureFlag: surveyHasFeatureFlag, + } = useExperimentSurvey(experiment, () => setSurveyModalOpen(true)) const { trigger, HogfettiComponent } = useHogfetti() useOnMountEffect(() => { @@ -578,12 +582,12 @@ export function PageHeaderCustom(): JSX.Element { Create dashboard - {experiment.feature_flag && ( + {surveyHasFeatureFlag && ( Create survey @@ -607,6 +611,11 @@ export function PageHeaderCustom(): JSX.Element { )} + setSurveyModalOpen(false)} + /> ) } diff --git a/frontend/src/scenes/experiments/Experiments.tsx b/frontend/src/scenes/experiments/Experiments.tsx index 0d08b5c5eb8a5..894842c308dff 100644 --- a/frontend/src/scenes/experiments/Experiments.tsx +++ b/frontend/src/scenes/experiments/Experiments.tsx @@ -10,6 +10,7 @@ import { ActivityLog } from 'lib/components/ActivityLog/ActivityLog' import { MemberSelect } from 'lib/components/MemberSelect' import { ProductIntroduction } from 'lib/components/ProductIntroduction/ProductIntroduction' import { ExperimentsHog } from 'lib/components/hedgehogs' +import { FEATURE_FLAGS } from 'lib/constants' import { dayjs } from 'lib/dayjs' import { LemonButton } from 'lib/lemon-ui/LemonButton' import { More } from 'lib/lemon-ui/LemonButton/More' @@ -18,11 +19,14 @@ import { LemonTable, LemonTableColumn, LemonTableColumns } from 'lib/lemon-ui/Le import { LemonTableLink } from 'lib/lemon-ui/LemonTable/LemonTableLink' import { atColumn, createdAtColumn, createdByColumn } from 'lib/lemon-ui/LemonTable/columnUtils' import { LemonTabs } from 'lib/lemon-ui/LemonTabs' +import { featureFlagLogic } from 'lib/logic/featureFlagLogic' import { deleteWithUndo } from 'lib/utils/deleteWithUndo' import stringWithWBR from 'lib/utils/stringWithWBR' import MaxTool from 'scenes/max/MaxTool' import { useMaxTool } from 'scenes/max/useMaxTool' import { SceneExport } from 'scenes/sceneTypes' +import { QuickSurveyModal } from 'scenes/surveys/quick-create/QuickSurveyModal' +import { QuickSurveyType } from 'scenes/surveys/quick-create/types' import { urls } from 'scenes/urls' import { userLogic } from 'scenes/userLogic' @@ -55,23 +59,56 @@ export const scene: SceneExport = { export const EXPERIMENTS_PRODUCT_DESCRIPTION = 'Experiments help you test changes to your product to see which changes will lead to optimal results. Automatic statistical calculations let you see if the results are valid or if they are likely just a chance occurrence.' -// Component for the survey button using MaxTool -const ExperimentSurveyButton = ({ experiment }: { experiment: Experiment }): JSX.Element => { +export function useExperimentSurvey( + experiment: Experiment, + onOpenModal?: () => void +): { + handleClick: () => void + isDisabled: boolean + hasFeatureFlag: boolean +} { const { user } = useValues(userLogic) const { openMax } = useMaxTool(createMaxToolExperimentSurveyConfig(experiment, user)) + const { featureFlags } = useValues(featureFlagLogic) + + const shouldUseQuickCreate = featureFlags[FEATURE_FLAGS.SURVEYS_EXPERIMENTS_BUTTON_EXPERIMENT] === 'test' + + const handleClick = (): void => { + if (shouldUseQuickCreate) { + onOpenModal?.() + } else { + openMax?.() + } + } + + return { + handleClick, + isDisabled: !shouldUseQuickCreate && !openMax, + hasFeatureFlag: !!experiment.feature_flag, + } +} + +const ExperimentSurveyButton = ({ + experiment, + onOpenModal, +}: { + experiment: Experiment + onOpenModal: () => void +}): JSX.Element | null => { + const { handleClick, isDisabled, hasFeatureFlag } = useExperimentSurvey(experiment, onOpenModal) // Don't show the button if there's no feature flag associated with the experiment - if (!experiment.feature_flag) { - return <> + if (!hasFeatureFlag) { + return null } return ( Create survey @@ -158,8 +195,10 @@ const ExperimentsTableFilters = ({ const ExperimentsTable = ({ openDuplicateModal, + openSurveyModal, }: { openDuplicateModal: (experiment: Experiment) => void + openSurveyModal: (experiment: Experiment) => void }): JSX.Element => { const { currentProjectId, experiments, experimentsLoading, tab, shouldShowEmptyState, filters, count, pagination } = useValues(experimentsLogic) @@ -255,7 +294,10 @@ const ExperimentsTable = ({ openDuplicateModal(experiment)} size="small" fullWidth> Duplicate - + openSurveyModal(experiment)} + /> {!experiment.archived && experiment?.end_date && dayjs().isSameOrAfter(dayjs(experiment.end_date), 'day') && ( @@ -425,6 +467,7 @@ export function Experiments(): JSX.Element { const { setExperimentsTab, loadExperiments } = useActions(experimentsLogic) const [duplicateModalExperiment, setDuplicateModalExperiment] = useState(null) + const [surveyModalExperiment, setSurveyModalExperiment] = useState(null) // Register feature flag creation tool so that it's always available on experiments page useMaxTool({ @@ -497,12 +540,22 @@ export function Experiments(): JSX.Element { { key: ExperimentsTabs.All, label: 'All experiments', - content: , + content: ( + + ), }, { key: ExperimentsTabs.Archived, label: 'Archived experiments', - content: , + content: ( + + ), }, { key: ExperimentsTabs.SharedMetrics, @@ -529,6 +582,13 @@ export function Experiments(): JSX.Element { experiment={duplicateModalExperiment} /> )} + {surveyModalExperiment && ( + setSurveyModalExperiment(null)} + /> + )} ) }