diff --git a/frontend/src/exporter/Exporter.stories.tsx b/frontend/src/exporter/Exporter.stories.tsx index cc64aac00d502..b2be152974a2b 100644 --- a/frontend/src/exporter/Exporter.stories.tsx +++ b/frontend/src/exporter/Exporter.stories.tsx @@ -138,6 +138,7 @@ FunnelTopToBottomBreakdownInsight.args = { } export const FunnelHistoricalTrendsInsight: Story = Template.bind({}) +FunnelHistoricalTrendsInsight.tags = ['autodocs', 'test-skip'] FunnelHistoricalTrendsInsight.args = { insight: require('../mocks/fixtures/api/projects/team_id/insights/funnelHistoricalTrends.json'), } diff --git a/frontend/src/scenes/pipeline/hogfunctions/HogFunctionInputs.tsx b/frontend/src/scenes/pipeline/hogfunctions/HogFunctionInputs.tsx index 2b0dac6034ef2..6961e09250b4f 100644 --- a/frontend/src/scenes/pipeline/hogfunctions/HogFunctionInputs.tsx +++ b/frontend/src/scenes/pipeline/hogfunctions/HogFunctionInputs.tsx @@ -1,3 +1,6 @@ +import { closestCenter, DndContext } from '@dnd-kit/core' +import { arrayMove, SortableContext, useSortable, verticalListSortingStrategy } from '@dnd-kit/sortable' +import { CSS } from '@dnd-kit/utilities' import { Monaco } from '@monaco-editor/react' import { IconGear, IconPlus, IconTrash, IconX } from '@posthog/icons' import { @@ -7,6 +10,7 @@ import { LemonInputSelect, LemonLabel, LemonSelect, + LemonTag, LemonTextArea, } from '@posthog/lemon-ui' import { useActions, useValues } from 'kea' @@ -362,6 +366,7 @@ function HogFunctionInputSchemaControls({ value, onChange, onDone }: HogFunction } export function HogFunctionInputWithSchema({ schema }: HogFunctionInputWithSchemaProps): JSX.Element { + const { attributes, listeners, setNodeRef, transform, transition } = useSortable({ id: schema.key }) const { showSource, configuration } = useValues(pipelineHogFunctionConfigurationLogic) const { setConfigurationValue } = useActions(pipelineHogFunctionConfigurationLogic) const [editing, setEditing] = useState(showSource) @@ -394,38 +399,96 @@ export function HogFunctionInputWithSchema({ schema }: HogFunctionInputWithSchem } }, [showSource]) - if (!editing) { - return ( - - {({ value, onChange }) => { - return ( - <> -
- {schema.label || schema.key} - {showSource ? ( - } - onClick={() => setEditing(true)} - /> - ) : null} -
- onChange({ value: val })} - /> - - ) - }} -
- ) + return ( +
+ {!editing ? ( + + {({ value, onChange }) => { + return ( + <> +
+ + {schema.label || schema.key} + + {showSource ? ( + <> + + inputs.{schema.key} + +
+ } + onClick={() => setEditing(true)} + /> + + ) : null} +
+ onChange({ value: val })} + /> + + ) + }} + + ) : ( +
+ setEditing(false)} + /> +
+ )} +
+ ) +} + +export function HogFunctionInputs(): JSX.Element { + const { showSource, configuration } = useValues(pipelineHogFunctionConfigurationLogic) + const { setConfigurationValue } = useActions(pipelineHogFunctionConfigurationLogic) + + if (!configuration?.inputs_schema?.length) { + return This function does not require any input variables. } + const inputSchemas = configuration.inputs_schema + const inputSchemaIds = inputSchemas.map((schema) => schema.key) + return ( -
- setEditing(false)} /> -
+ <> + { + if (over && active.id !== over.id) { + const oldIndex = inputSchemaIds.indexOf(active.id as string) + const newIndex = inputSchemaIds.indexOf(over.id as string) + + setConfigurationValue('inputs_schema', arrayMove(inputSchemas, oldIndex, newIndex)) + } + }} + > + + {configuration.inputs_schema?.map((schema) => { + return + })} + + + ) } diff --git a/frontend/src/scenes/pipeline/hogfunctions/PipelineHogFunctionConfiguration.tsx b/frontend/src/scenes/pipeline/hogfunctions/PipelineHogFunctionConfiguration.tsx index 8faa305bda9f7..71d1dd694a1e6 100644 --- a/frontend/src/scenes/pipeline/hogfunctions/PipelineHogFunctionConfiguration.tsx +++ b/frontend/src/scenes/pipeline/hogfunctions/PipelineHogFunctionConfiguration.tsx @@ -25,7 +25,7 @@ import { groupsModel } from '~/models/groupsModel' import { EntityTypes } from '~/types' import { HogFunctionIconEditable } from './HogFunctionIcon' -import { HogFunctionInputWithSchema } from './HogFunctionInputs' +import { HogFunctionInputs } from './HogFunctionInputs' import { HogFunctionTest, HogFunctionTestPlaceholder } from './HogFunctionTest' import { pipelineHogFunctionConfigurationLogic } from './pipelineHogFunctionConfigurationLogic' @@ -263,15 +263,7 @@ export function PipelineHogFunctionConfiguration({
- {configuration?.inputs_schema?.length ? ( - configuration?.inputs_schema.map((schema, index) => { - return - }) - ) : ( - - This function does not require any input variables. - - )} + {showSource ? ( <> diff --git a/frontend/src/scenes/surveys/SurveyEdit.tsx b/frontend/src/scenes/surveys/SurveyEdit.tsx index c839daa5b7313..9b0372a81a91c 100644 --- a/frontend/src/scenes/surveys/SurveyEdit.tsx +++ b/frontend/src/scenes/surveys/SurveyEdit.tsx @@ -8,6 +8,7 @@ import { LemonButton, LemonCheckbox, LemonCollapse, + LemonDialog, LemonDivider, LemonInput, LemonSelect, @@ -51,6 +52,7 @@ export default function SurveyEdit(): JSX.Element { targetingFlagFilters, showSurveyRepeatSchedule, schedule, + hasBranchingLogic, } = useValues(surveyLogic) const { setSurveyValue, @@ -59,6 +61,7 @@ export default function SurveyEdit(): JSX.Element { setSelectedSection, setFlagPropertyErrors, setSchedule, + deleteBranchingLogic, } = useActions(surveyLogic) const { surveysMultipleQuestionsAvailable, surveysRecurringScheduleAvailable, surveysEventsAvailable } = useValues(surveysLogic) @@ -171,10 +174,37 @@ export default function SurveyEdit(): JSX.Element { { if (over && active.id !== over.id) { - onSortEnd({ - oldIndex: sortedItemIds.indexOf(active.id.toString()), - newIndex: sortedItemIds.indexOf(over.id.toString()), - }) + const finishDrag = (): void => + onSortEnd({ + oldIndex: sortedItemIds.indexOf(active.id.toString()), + newIndex: sortedItemIds.indexOf(over.id.toString()), + }) + + if (hasBranchingLogic) { + LemonDialog.open({ + title: 'Your survey has active branching logic', + description: ( +

+ Rearranging questions will remove your branching logic. + Are you sure you want to continue? +

+ ), + + primaryButton: { + children: 'Continue', + status: 'danger', + onClick: () => { + deleteBranchingLogic() + finishDrag() + }, + }, + secondaryButton: { + children: 'Cancel', + }, + }) + } else { + finishDrag() + } } }} > @@ -226,14 +256,48 @@ export default function SurveyEdit(): JSX.Element { icon={} data-attr="delete-survey-confirmation" onClick={(e) => { - e.stopPropagation() - setSelectedPageIndex( - survey.questions.length - 1 - ) - setSurveyValue('appearance', { - ...survey.appearance, - displayThankYouMessage: false, - }) + const deleteConfirmationMessage = + (): void => { + e.stopPropagation() + setSelectedPageIndex( + survey.questions.length - + 1 + ) + setSurveyValue('appearance', { + ...survey.appearance, + displayThankYouMessage: + false, + }) + } + + if (hasBranchingLogic) { + LemonDialog.open({ + title: 'Your survey has active branching logic', + description: ( +

+ Deleting the + confirmation message + will remove your + branching logic. Are + you sure you want to + continue? +

+ ), + primaryButton: { + children: 'Continue', + status: 'danger', + onClick: () => { + deleteBranchingLogic() + deleteConfirmationMessage() + }, + }, + secondaryButton: { + children: 'Cancel', + }, + }) + } else { + deleteConfirmationMessage() + } }} tooltipPlacement="top-end" /> diff --git a/frontend/src/scenes/surveys/SurveyEditQuestionRow.tsx b/frontend/src/scenes/surveys/SurveyEditQuestionRow.tsx index e1b24b1bea182..c6043bfc6ae3d 100644 --- a/frontend/src/scenes/surveys/SurveyEditQuestionRow.tsx +++ b/frontend/src/scenes/surveys/SurveyEditQuestionRow.tsx @@ -4,7 +4,7 @@ import { DraggableSyntheticListeners } from '@dnd-kit/core' import { useSortable } from '@dnd-kit/sortable' import { CSS } from '@dnd-kit/utilities' import { IconPlusSmall, IconTrash } from '@posthog/icons' -import { LemonButton, LemonCheckbox, LemonInput, LemonSelect } from '@posthog/lemon-ui' +import { LemonButton, LemonCheckbox, LemonDialog, LemonInput, LemonSelect } from '@posthog/lemon-ui' import { useActions, useValues } from 'kea' import { Group } from 'kea-forms' import { FEATURE_FLAGS } from 'lib/constants' @@ -38,6 +38,8 @@ export function SurveyEditQuestionHeader({ setSelectedPageIndex, setSurveyValue, }: SurveyQuestionHeaderProps): JSX.Element { + const { hasBranchingLogic } = useValues(surveyLogic) + const { deleteBranchingLogic } = useActions(surveyLogic) const { setNodeRef, attributes, transform, transition, listeners, isDragging } = useSortable({ id: index.toString(), }) @@ -71,12 +73,39 @@ export function SurveyEditQuestionHeader({ icon={} data-attr={`delete-survey-question-${index}`} onClick={(e) => { - e.stopPropagation() - setSelectedPageIndex(index <= 0 ? 0 : index - 1) - setSurveyValue( - 'questions', - survey.questions.filter((_, i) => i !== index) - ) + const deleteQuestion = (): void => { + e.stopPropagation() + setSelectedPageIndex(index <= 0 ? 0 : index - 1) + setSurveyValue( + 'questions', + survey.questions.filter((_, i) => i !== index) + ) + } + + if (hasBranchingLogic) { + LemonDialog.open({ + title: 'Your survey has active branching logic', + description: ( +

+ Deleting the question will remove your branching logic. Are you sure you want to + continue? +

+ ), + primaryButton: { + children: 'Continue', + status: 'danger', + onClick: () => { + deleteBranchingLogic() + deleteQuestion() + }, + }, + secondaryButton: { + children: 'Cancel', + }, + }) + } else { + deleteQuestion() + } }} tooltipPlacement="top-end" /> diff --git a/frontend/src/scenes/surveys/surveyLogic.tsx b/frontend/src/scenes/surveys/surveyLogic.tsx index 62948bdc12a87..2c7f48fd12ea9 100644 --- a/frontend/src/scenes/surveys/surveyLogic.tsx +++ b/frontend/src/scenes/surveys/surveyLogic.tsx @@ -170,6 +170,7 @@ export const surveyLogic = kea([ specificQuestionIndex, }), resetBranchingForQuestion: (questionIndex) => ({ questionIndex }), + deleteBranchingLogic: true, archiveSurvey: true, setWritingHTMLDescription: (writingHTML: boolean) => ({ writingHTML }), setSurveyTemplateValues: (template: any) => ({ template }), @@ -760,6 +761,17 @@ export const surveyLogic = kea([ questions: newQuestions, } }, + deleteBranchingLogic: (state) => { + const newQuestions = [...state.questions] + newQuestions.forEach((question) => { + delete question.branching + }) + + return { + ...state, + questions: newQuestions, + } + }, }, ], selectedPageIndex: [ @@ -1094,6 +1106,11 @@ export const surveyLogic = kea([ return cycleDetected }, ], + hasBranchingLogic: [ + (s) => [s.survey], + (survey) => + survey.questions.some((question) => question.branching && Object.keys(question.branching).length > 0), + ], }), forms(({ actions, props, values }) => ({ survey: { diff --git a/package.json b/package.json index 7b7a450e679da..2327d509d49d0 100644 --- a/package.json +++ b/package.json @@ -146,7 +146,7 @@ "pmtiles": "^2.11.0", "postcss": "^8.4.31", "postcss-preset-env": "^9.3.0", - "posthog-js": "1.139.3", + "posthog-js": "1.139.4", "posthog-js-lite": "3.0.0", "prettier": "^2.8.8", "prop-types": "^15.7.2", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 45bdf07dd9d4a..9974d8b091188 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -260,8 +260,8 @@ dependencies: specifier: ^9.3.0 version: 9.3.0(postcss@8.4.31) posthog-js: - specifier: 1.139.3 - version: 1.139.3 + specifier: 1.139.4 + version: 1.139.4 posthog-js-lite: specifier: 3.0.0 version: 3.0.0 @@ -17706,8 +17706,8 @@ packages: resolution: {integrity: sha512-dyajjnfzZD1tht4N7p7iwf7nBnR1MjVaVu+MKr+7gBgA39bn28wizCIJZztZPtHy4PY0YwtSGgwfBCuG/hnHgA==} dev: false - /posthog-js@1.139.3: - resolution: {integrity: sha512-NmPtOAXogxT/QSmeVCQJeIemBn8rEGfFPIXOynYKgXfntrw0KhzGXXvRXGLVjl5Zx6Nslf5NlmMnzmq1wjLZIA==} + /posthog-js@1.139.4: + resolution: {integrity: sha512-K0bV3xI7PCgJYN+qPQ26BglOtGzgXHM+BU3pBo1ukbX33O2/CktzFfnKvYdarXuIEBWsRdiiloqb+ok4pI8/Hw==} dependencies: fflate: 0.4.8 preact: 10.22.0