Skip to content
Closed
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
1 change: 1 addition & 0 deletions frontend/src/lib/constants.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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]
Expand Down
25 changes: 17 additions & 8 deletions frontend/src/scenes/experiments/ExperimentView/components.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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'
Expand Down Expand Up @@ -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'
Expand Down Expand Up @@ -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(() => {
Expand Down Expand Up @@ -578,12 +582,12 @@ export function PageHeaderCustom(): JSX.Element {
<IconPlusSmall /> Create dashboard
</ButtonPrimitive>

{experiment.feature_flag && (
{surveyHasFeatureFlag && (
<ButtonPrimitive
menuItem
onClick={openMax || undefined}
onClick={handleSurveyClick}
disabledReasons={{
'PostHog AI not available': !openMax,
'PostHog AI not available': isSurveyDisabled,
}}
>
<IconPlusSmall /> Create survey
Expand All @@ -607,6 +611,11 @@ export function PageHeaderCustom(): JSX.Element {
</ScenePanelActionsSection>
</ScenePanel>
)}
<QuickSurveyModal
context={{ type: QuickSurveyType.EXPERIMENT, experiment }}
isOpen={surveyModalOpen}
onCancel={() => setSurveyModalOpen(false)}
/>
</>
)
}
Expand Down
78 changes: 69 additions & 9 deletions frontend/src/scenes/experiments/Experiments.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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'
Expand All @@ -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'

Expand Down Expand Up @@ -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 (
<LemonButton
onClick={openMax || undefined}
onClick={handleClick}
size="small"
fullWidth
data-attr="create-survey"
disabled={!openMax}
disabledReason={isDisabled ? 'PostHog AI not available' : undefined}
>
Create survey
</LemonButton>
Expand Down Expand Up @@ -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)
Expand Down Expand Up @@ -255,7 +294,10 @@ const ExperimentsTable = ({
<LemonButton onClick={() => openDuplicateModal(experiment)} size="small" fullWidth>
Duplicate
</LemonButton>
<ExperimentSurveyButton experiment={experiment} />
<ExperimentSurveyButton
experiment={experiment}
onOpenModal={() => openSurveyModal(experiment)}
/>
{!experiment.archived &&
experiment?.end_date &&
dayjs().isSameOrAfter(dayjs(experiment.end_date), 'day') && (
Expand Down Expand Up @@ -425,6 +467,7 @@ export function Experiments(): JSX.Element {
const { setExperimentsTab, loadExperiments } = useActions(experimentsLogic)

const [duplicateModalExperiment, setDuplicateModalExperiment] = useState<Experiment | null>(null)
const [surveyModalExperiment, setSurveyModalExperiment] = useState<Experiment | null>(null)

// Register feature flag creation tool so that it's always available on experiments page
useMaxTool({
Expand Down Expand Up @@ -497,12 +540,22 @@ export function Experiments(): JSX.Element {
{
key: ExperimentsTabs.All,
label: 'All experiments',
content: <ExperimentsTable openDuplicateModal={setDuplicateModalExperiment} />,
content: (
<ExperimentsTable
openDuplicateModal={setDuplicateModalExperiment}
openSurveyModal={setSurveyModalExperiment}
/>
),
},
{
key: ExperimentsTabs.Archived,
label: 'Archived experiments',
content: <ExperimentsTable openDuplicateModal={setDuplicateModalExperiment} />,
content: (
<ExperimentsTable
openDuplicateModal={setDuplicateModalExperiment}
openSurveyModal={setSurveyModalExperiment}
/>
),
},
{
key: ExperimentsTabs.SharedMetrics,
Expand All @@ -529,6 +582,13 @@ export function Experiments(): JSX.Element {
experiment={duplicateModalExperiment}
/>
)}
{surveyModalExperiment && (
<QuickSurveyModal
context={{ type: QuickSurveyType.EXPERIMENT, experiment: surveyModalExperiment }}
isOpen={true}
onCancel={() => setSurveyModalExperiment(null)}
/>
)}
</SceneContent>
)
}
Loading