Skip to content

Commit

Permalink
fix(surveys): enable button text per question instead (#18623)
Browse files Browse the repository at this point in the history
* add button text field to question

* clean up last traces of new surveys with submitButtonText

* button text

* fix empty string bug

* clean up

* linter
  • Loading branch information
liyiy authored and pauldambra committed Nov 15, 2023
1 parent 3932732 commit 6a19c30
Show file tree
Hide file tree
Showing 11 changed files with 74 additions and 92 deletions.
Binary file modified frontend/__snapshots__/scenes-app-insights--stickiness--webkit.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified frontend/__snapshots__/scenes-app-surveys--new-survey.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified frontend/__snapshots__/scenes-app-surveys--survey-templates.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
9 changes: 1 addition & 8 deletions frontend/src/scenes/notebooks/Nodes/NotebookNodeSurvey.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { createPostHogWidgetNode } from 'scenes/notebooks/Nodes/NodeWrapper'
import { FeatureFlagBasicType, NotebookNodeType, Survey, SurveyQuestionType } from '~/types'
import { FeatureFlagBasicType, NotebookNodeType, Survey } from '~/types'
import { BindLogic, useActions, useValues } from 'kea'
import { IconSurveys } from 'lib/lemon-ui/icons'
import { LemonDivider } from '@posthog/lemon-ui'
Expand Down Expand Up @@ -81,13 +81,6 @@ const Component = ({ attributes }: NotebookNodeProps<NotebookNodeSurveyAttribute
type={survey.questions[0].type}
surveyQuestionItem={survey.questions[0]}
appearance={survey.appearance || defaultSurveyAppearance}
question={survey.questions[0].question}
description={survey.questions[0].description}
link={
survey.questions[0].type === SurveyQuestionType.Link
? survey.questions[0].link
: undefined
}
/>
</div>
</div>
Expand Down
86 changes: 37 additions & 49 deletions frontend/src/scenes/surveys/SurveyAppearance.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ import {
SurveyQuestionType,
MultipleSurveyQuestion,
AvailableFeature,
BasicSurveyQuestion,
LinkSurveyQuestion,
} from '~/types'
import { defaultSurveyAppearance } from './constants'
import {
Expand All @@ -28,11 +30,8 @@ import { sanitizeHTML } from './utils'

interface SurveyAppearanceProps {
type: SurveyQuestionType
question: string
appearance: SurveyAppearanceType
surveyQuestionItem: SurveyQuestion
description?: string | null
link?: string | null
preview?: boolean
}

Expand Down Expand Up @@ -87,11 +86,8 @@ const Button = ({

export function SurveyAppearance({
type,
question,
appearance,
surveyQuestionItem,
description,
link,
preview,
}: SurveyAppearanceProps): JSX.Element {
return (
Expand All @@ -101,8 +97,6 @@ export function SurveyAppearance({
preview={preview}
ratingSurveyQuestion={surveyQuestionItem as RatingSurveyQuestion}
appearance={appearance}
question={question}
description={description}
onSubmit={() => undefined}
/>
)}
Expand All @@ -112,20 +106,15 @@ export function SurveyAppearance({
preview={preview}
multipleChoiceQuestion={surveyQuestionItem as MultipleSurveyQuestion}
appearance={appearance}
question={question}
description={description}
onSubmit={() => undefined}
/>
)}
{(surveyQuestionItem.type === SurveyQuestionType.Open ||
surveyQuestionItem.type === SurveyQuestionType.Link) && (
<BaseAppearance
preview={preview}
type={type}
question={question}
description={description}
question={surveyQuestionItem}
appearance={appearance}
link={link}
onSubmit={() => undefined}
/>
)}
Expand All @@ -143,11 +132,6 @@ export function Customization({ appearance, surveyQuestionItem, onAppearanceChan
<></>
</PayGateMini>
)}
<div className="mt-2">Button text</div>
<LemonInput
value={appearance?.submitButtonText || defaultSurveyAppearance.submitButtonText}
onChange={(submitButtonText) => onAppearanceChange({ ...appearance, submitButtonText })}
/>
<div className="mt-2">Background color</div>
<LemonInput
value={appearance?.backgroundColor}
Expand Down Expand Up @@ -234,20 +218,14 @@ export function Customization({ appearance, surveyQuestionItem, onAppearanceChan

// This should be synced to the UI of the surveys app plugin
export function BaseAppearance({
type,
question,
appearance,
onSubmit,
description,
link,
preview,
}: {
type: SurveyQuestionType
question: string
question: BasicSurveyQuestion | LinkSurveyQuestion
appearance: SurveyAppearanceType
onSubmit: () => void
description?: string | null
link?: string | null
preview?: boolean
}): JSX.Element {
const [textColor, setTextColor] = useState('black')
Expand Down Expand Up @@ -284,14 +262,20 @@ export function BaseAppearance({
</div>
)}
<div className="question-textarea-wrapper">
<div className="survey-question" dangerouslySetInnerHTML={{ __html: sanitizeHTML(question) }} />
<div
className="survey-question"
dangerouslySetInnerHTML={{ __html: sanitizeHTML(question.question) }}
/>
{/* Using dangerouslySetInnerHTML is safe here, because it's taking the user's input and showing it to the same user.
They can try passing in arbitrary scripts, but it would show up only for them, so it's like trying to XSS yourself, where
you already have all the data. Furthermore, sanitization should catch all obvious attempts */}
{description && (
<div className="description" dangerouslySetInnerHTML={{ __html: sanitizeHTML(description) }} />
{question.description && (
<div
className="description"
dangerouslySetInnerHTML={{ __html: sanitizeHTML(question.description) }}
/>
)}
{type === SurveyQuestionType.Open && (
{question.type === SurveyQuestionType.Open && (
<textarea
{...(preview ? { tabIndex: -1 } : null)}
style={{
Expand All @@ -310,11 +294,11 @@ export function BaseAppearance({
<Button
{...(preview ? { tabIndex: -1 } : null)}
appearance={appearance}
link={link}
link={question.type === SurveyQuestionType.Link ? question.link : null}
onSubmit={onSubmit}
type={type}
type={question.type}
>
{appearance.submitButtonText}
{question.buttonText || appearance.submitButtonText}
</Button>
</div>

Expand Down Expand Up @@ -446,16 +430,12 @@ const EmojiRating = ({
export function SurveyRatingAppearance({
ratingSurveyQuestion,
appearance,
question,
onSubmit,
description,
preview,
}: {
ratingSurveyQuestion: RatingSurveyQuestion
appearance: SurveyAppearanceType
question: string
onSubmit: () => void
description?: string | null
preview?: boolean
}): JSX.Element {
const [textColor, setTextColor] = useState('black')
Expand Down Expand Up @@ -491,9 +471,15 @@ export function SurveyRatingAppearance({
</button>
</div>
)}
<div className="survey-question" dangerouslySetInnerHTML={{ __html: sanitizeHTML(question) }} />
{description && (
<div className="description" dangerouslySetInnerHTML={{ __html: sanitizeHTML(description) }} />
<div
className="survey-question"
dangerouslySetInnerHTML={{ __html: sanitizeHTML(ratingSurveyQuestion.question) }}
/>
{ratingSurveyQuestion.description && (
<div
className="description"
dangerouslySetInnerHTML={{ __html: sanitizeHTML(ratingSurveyQuestion.description) }}
/>
)}
<div className="rating-section">
<div className="rating-options">
Expand Down Expand Up @@ -524,7 +510,7 @@ export function SurveyRatingAppearance({
appearance={appearance}
onSubmit={onSubmit}
>
{appearance.submitButtonText}
{ratingSurveyQuestion.buttonText || appearance.submitButtonText}
</Button>
</div>

Expand All @@ -543,17 +529,13 @@ export function SurveyRatingAppearance({
export function SurveyMultipleChoiceAppearance({
multipleChoiceQuestion,
appearance,
question,
onSubmit,
description,
preview,
initialChecked,
}: {
multipleChoiceQuestion: MultipleSurveyQuestion
appearance: SurveyAppearanceType
question: string
onSubmit: () => void
description?: string | null
preview?: boolean
initialChecked?: number[]
}): JSX.Element {
Expand Down Expand Up @@ -591,9 +573,15 @@ export function SurveyMultipleChoiceAppearance({
</button>
</div>
)}
<div className="survey-question" dangerouslySetInnerHTML={{ __html: sanitizeHTML(question) }} />
{description && (
<div className="description" dangerouslySetInnerHTML={{ __html: sanitizeHTML(description) }} />
<div
className="survey-question"
dangerouslySetInnerHTML={{ __html: sanitizeHTML(multipleChoiceQuestion.question) }}
/>
{multipleChoiceQuestion.description && (
<div
className="description"
dangerouslySetInnerHTML={{ __html: sanitizeHTML(multipleChoiceQuestion.description) }}
/>
)}
<div className="multiple-choice-options">
{(multipleChoiceQuestion.choices || []).map((choice, idx) => (
Expand All @@ -612,7 +600,7 @@ export function SurveyMultipleChoiceAppearance({
<div className="bottom-section">
<div className="buttons">
<Button {...(preview ? { tabIndex: -1 } : null)} appearance={appearance} onSubmit={onSubmit}>
{appearance.submitButtonText}
{multipleChoiceQuestion.buttonText || appearance.submitButtonText}
</Button>
</div>

Expand Down
Loading

0 comments on commit 6a19c30

Please sign in to comment.