Skip to content

Commit

Permalink
feat(surveys): auto opt in and out surveys for users (PostHog#18080)
Browse files Browse the repository at this point in the history
* opt in surveys when creating survey and opt out when no active surveys

* update survey banner warning

* add auto opt ins for surveys list launch and stop surveys

* remove from onboarding step

* Update UI snapshots for `chromium` (2)

* update opt in from backend instead

* add filter for api surveys and post delete to receiver

* Update query snapshots

* fix popup flicker

* ambr snapshots

* disabled popup banner rename

* exclude api surveys in query instead

---------

Co-authored-by: github-actions <41898282+github-actions[bot]@users.noreply.github.com>
  • Loading branch information
2 people authored and Justicea83 committed Oct 24, 2023
1 parent 73ff325 commit 813a60b
Show file tree
Hide file tree
Showing 9 changed files with 169 additions and 87 deletions.
31 changes: 0 additions & 31 deletions cypress/e2e/surveys.cy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,37 +39,6 @@ describe('Surveys', () => {
cy.get('tbody').should('not.exist')
})

it('shows survey disabled banner when surveys disabled', () => {
cy.get('div.LemonBanner.LemonBanner--warning.mb-2').should(
'contain',
'Survey popovers are currently disabled for this project'
)
cy.get('div.LemonBanner.LemonBanner--warning.mb-2').contains('Configure').click()

cy.contains('Surveys settings').should('exist').should('be.visible')

cy.get('[data-attr="opt-in-surveys-switch"]').click()

cy.get('[data-attr=success-toast]').contains('Surveys opt in').should('exist')

cy.contains('Done').click()

// now lemon banner should be gone
cy.get('div.LemonBanner.LemonBanner--warning.mb-2').should('not.exist')

// get it back
cy.contains('Configure').click()
cy.get('[data-attr="opt-in-surveys-switch"]').click()
cy.get('[data-attr=success-toast]').contains('Surveys opt in').should('exist')
cy.contains('Done').click()

// now lemon banner should be back
cy.get('div.LemonBanner.LemonBanner--warning.mb-2').should(
'contain',
'Survey popovers are currently disabled for this project'
)
})

it('creates a new survey', () => {
// load an empty page
cy.get('h1').should('contain', 'Surveys')
Expand Down
Binary file modified frontend/__snapshots__/scenes-app-surveys--surveys-list.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
21 changes: 0 additions & 21 deletions frontend/src/scenes/ingestion/panels/SuperpowersPanel.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@ export function SuperpowersPanel(): JSX.Element {
const { completeOnboarding } = useActions(ingestionLogic)
const [sessionRecordingsChecked, setSessionRecordingsChecked] = useState(true)
const [autocaptureChecked, setAutocaptureChecked] = useState(true)
const [surveysChecked, setSurveysChecked] = useState(true)

return (
<CardContainer
Expand All @@ -23,7 +22,6 @@ export function SuperpowersPanel(): JSX.Element {
capture_console_log_opt_in: sessionRecordingsChecked,
capture_performance_opt_in: sessionRecordingsChecked,
autocapture_opt_out: !autocaptureChecked,
surveys_opt_in: surveysChecked,
})
if (!showBillingStep) {
completeOnboarding()
Expand Down Expand Up @@ -84,25 +82,6 @@ export function SuperpowersPanel(): JSX.Element {
directly in your code snippet.
</p>
</div>
<div>
<LemonSwitch
data-attr="opt-in-surveys-switch"
onChange={(checked) => {
setSurveysChecked(checked)
}}
label="Get qualitative feedback from your users"
fullWidth={true}
labelClassName={'text-base font-semibold'}
checked={surveysChecked}
/>
<p className="prompt-text ml-0">
Collect feedback from your users directly in your product.{' '}
<Link to={'https://posthog.com/docs/surveys'} target="blank">
Learn more
</Link>{' '}
about Surveys.
</p>
</div>
</CardContainer>
)
}
24 changes: 8 additions & 16 deletions frontend/src/scenes/surveys/Surveys.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,6 @@ import { ProductIntroduction } from 'lib/components/ProductIntroduction/ProductI
import { userLogic } from 'scenes/userLogic'
import { dayjs } from 'lib/dayjs'
import { VersionCheckerBanner } from 'lib/components/VersionChecker/VersionCheckerBanner'
import { teamLogic } from 'scenes/teamLogic'
import { LemonBanner } from 'lib/lemon-ui/LemonBanner'
import { IconSettings } from 'lib/lemon-ui/icons'
import { openSurveysSettingsDialog } from './SurveySettings'
Expand All @@ -54,13 +53,12 @@ export function Surveys(): JSX.Element {
searchTerm,
filters,
uniqueCreators,
showSurveysDisabledBanner,
} = useValues(surveysLogic)

const { deleteSurvey, updateSurvey, setSearchTerm, setSurveysFilters } = useActions(surveysLogic)

const { user } = useValues(userLogic)
const { currentTeam } = useValues(teamLogic)
const surveysPopupDisabled = currentTeam && !currentTeam?.surveys_opt_in

const [tab, setSurveyTab] = useState(SurveysTabs.Active)
const shouldShowEmptyState = !surveysLoading && surveys.length === 0
Expand Down Expand Up @@ -97,13 +95,6 @@ export function Surveys(): JSX.Element {
>
New survey
</LemonButtonWithSideAction>
<LemonButton
type="secondary"
icon={<IconSettings />}
onClick={() => openSurveysSettingsDialog()}
>
Configure
</LemonButton>
</>
}
caption={
Expand Down Expand Up @@ -135,7 +126,7 @@ export function Surveys(): JSX.Element {
<div className="space-y-2">
<VersionCheckerBanner />

{surveysPopupDisabled ? (
{showSurveysDisabledBanner ? (
<LemonBanner
type="warning"
action={{
Expand All @@ -146,7 +137,8 @@ export function Surveys(): JSX.Element {
}}
className="mb-2"
>
Survey popovers are currently disabled for this project.
Survey popovers are currently disabled for this project but there are active surveys running.
Re-enable them in the settings.
</LemonBanner>
) : null}
</div>
Expand Down Expand Up @@ -306,14 +298,14 @@ export function Surveys(): JSX.Element {
<LemonButton
status="stealth"
fullWidth
onClick={() =>
onClick={() => {
updateSurvey({
id: survey.id,
updatePayload: {
end_date: dayjs().toISOString(),
},
})
}
}}
>
Stop survey
</LemonButton>
Expand All @@ -322,12 +314,12 @@ export function Surveys(): JSX.Element {
<LemonButton
status="stealth"
fullWidth
onClick={() =>
onClick={() => {
updateSurvey({
id: survey.id,
updatePayload: { end_date: null },
})
}
}}
>
Resume survey
</LemonButton>
Expand Down
2 changes: 1 addition & 1 deletion frontend/src/scenes/surveys/surveyLogic.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,7 @@ export const surveyLogic = kea<surveyLogicType>([
'reportSurveyViewed',
],
],
values: [enabledFlagLogic, ['featureFlags as enabledFlags']],
values: [enabledFlagLogic, ['featureFlags as enabledFlags'], surveysLogic, ['surveys']],
})),
actions({
setSurveyMissing: true,
Expand Down
21 changes: 19 additions & 2 deletions frontend/src/scenes/surveys/surveysLogic.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,15 @@ import { afterMount, connect, kea, listeners, path, selectors, actions, reducers
import { loaders } from 'kea-loaders'
import api from 'lib/api'
import Fuse from 'fuse.js'
import { AvailableFeature, Breadcrumb, ProgressStatus, Survey } from '~/types'
import { AvailableFeature, Breadcrumb, ProgressStatus, Survey, SurveyType } from '~/types'
import { urls } from 'scenes/urls'

import type { surveysLogicType } from './surveysLogicType'
import { lemonToast } from '@posthog/lemon-ui'
import { userLogic } from 'scenes/userLogic'
import { router } from 'kea-router'
import { LemonSelectOption } from 'lib/lemon-ui/LemonSelect'
import { teamLogic } from 'scenes/teamLogic'

export function getSurveyStatus(survey: Survey): ProgressStatus {
if (!survey.start_date) {
Expand All @@ -33,7 +34,8 @@ interface SurveysCreators {
export const surveysLogic = kea<surveysLogicType>([
path(['scenes', 'surveys', 'surveysLogic']),
connect(() => ({
values: [userLogic, ['user']],
values: [userLogic, ['user'], teamLogic, ['currentTeam', 'currentTeamLoading']],
actions: [teamLogic, ['loadCurrentTeam']],
})),
actions({
setSearchTerm: (searchTerm: string) => ({ searchTerm }),
Expand Down Expand Up @@ -87,11 +89,15 @@ export const surveysLogic = kea<surveysLogicType>([
},
updateSurveySuccess: () => {
lemonToast.success('Survey updated')
actions.loadCurrentTeam()
},
setSurveysFilters: () => {
actions.loadSurveys()
actions.loadResponsesCount()
},
loadSurveysSuccess: () => {
actions.loadCurrentTeam()
},
})),
selectors({
searchedSurveys: [
Expand Down Expand Up @@ -162,6 +168,17 @@ export const surveysLogic = kea<surveysLogicType>([
(s) => [s.user],
(user) => (user?.organization?.available_features || []).includes(AvailableFeature.WHITE_LABELLING),
],
showSurveysDisabledBanner: [
(s) => [s.currentTeam, s.currentTeamLoading, s.surveys],
(currentTeam, currentTeamLoading, surveys) => {
return (
!currentTeamLoading &&
currentTeam &&
!currentTeam.surveys_opt_in &&
surveys.some((s) => s.start_date && !s.end_date && s.type !== SurveyType.API)
)
},
],
}),
afterMount(({ actions }) => {
actions.loadSurveys()
Expand Down
30 changes: 26 additions & 4 deletions posthog/api/test/__snapshots__/test_survey.ambr
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,17 @@
'
---
# name: TestSurveysAPIList.test_list_surveys
'
SELECT COUNT(*) AS "__count"
FROM "posthog_survey"
WHERE (NOT "posthog_survey"."archived"
AND "posthog_survey"."end_date" IS NULL
AND "posthog_survey"."start_date" IS NOT NULL
AND "posthog_survey"."team_id" = 2
AND NOT ("posthog_survey"."type" = 'api'))
'
---
# name: TestSurveysAPIList.test_list_surveys.1
'
SELECT "posthog_featureflag"."id",
"posthog_featureflag"."key",
Expand All @@ -32,7 +43,7 @@
AND "posthog_featureflag"."team_id" = 2)
'
---
# name: TestSurveysAPIList.test_list_surveys.1
# name: TestSurveysAPIList.test_list_surveys.2
'
SELECT "posthog_featureflag"."id",
"posthog_featureflag"."key",
Expand All @@ -55,7 +66,18 @@
AND "posthog_featureflag"."team_id" = 2)
'
---
# name: TestSurveysAPIList.test_list_surveys.2
# name: TestSurveysAPIList.test_list_surveys.3
'
SELECT COUNT(*) AS "__count"
FROM "posthog_survey"
WHERE (NOT "posthog_survey"."archived"
AND "posthog_survey"."end_date" IS NULL
AND "posthog_survey"."start_date" IS NOT NULL
AND "posthog_survey"."team_id" = 2
AND NOT ("posthog_survey"."type" = 'api'))
'
---
# name: TestSurveysAPIList.test_list_surveys.4
'
SELECT "posthog_user"."id",
"posthog_user"."password",
Expand Down Expand Up @@ -84,7 +106,7 @@
LIMIT 21
'
---
# name: TestSurveysAPIList.test_list_surveys.3
# name: TestSurveysAPIList.test_list_surveys.5
'
SELECT "posthog_team"."id",
"posthog_team"."uuid",
Expand Down Expand Up @@ -129,7 +151,7 @@
LIMIT 21 /*controller='posthog.api.survey.surveys',route='%5Eapi/surveys/%3F%28%3F%3A%5B%3F%23%5D.%2A%29%3F%24'*/
'
---
# name: TestSurveysAPIList.test_list_surveys.4
# name: TestSurveysAPIList.test_list_surveys.6
'
SELECT "posthog_survey"."id",
"posthog_survey"."team_id",
Expand Down
Loading

0 comments on commit 813a60b

Please sign in to comment.