Skip to content

Commit

Permalink
fix(surveys): Render feedback preview (#1030)
Browse files Browse the repository at this point in the history
* fix text color contrast for feedback tab

* render feedback widget preview

* fix tests and render method

* load survey previews module separately otherwise it overrides generateSurveys

* add file
  • Loading branch information
liyiy authored Feb 20, 2024
1 parent a98e739 commit 1b5632d
Show file tree
Hide file tree
Showing 7 changed files with 113 additions and 15 deletions.
25 changes: 25 additions & 0 deletions cypress/e2e/surveys.cy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -536,6 +536,31 @@ describe('Surveys', () => {
cy.phCaptures().should('include', 'survey shown')
cy.phCaptures().should('include', 'survey sent')
})

it('auto contrasts text color for feedback tab', () => {
cy.intercept('GET', '**/surveys/*', {
surveys: [
{
id: '123',
name: 'Feedback tab survey',
type: 'widget',
start_date: '2021-01-01T00:00:00Z',
questions: [openTextQuestion],
appearance: {
widgetLabel: 'Feedback',
widgetType: 'tab',
widgetColor: 'white',
},
},
],
}).as('surveys')
const black = 'rgb(0, 0, 0)'
const white = 'rgb(255, 255, 255)'
cy.visit('./playground/cypress')
onPageLoad()
cy.get('.PostHogWidget123').shadow().find('.ph-survey-widget-tab').should('have.css', 'background-color', white)
cy.get('.PostHogWidget123').shadow().find('.ph-survey-widget-tab').should('have.css', 'color', black)
})
})

describe('Thank you message', () => {
Expand Down
8 changes: 7 additions & 1 deletion rollup.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -58,8 +58,14 @@ export default [
preact: 'preact',
},
},
],
plugins: [...plugins],
},
{
input: 'src/loader-surveys-preview.ts',
output: [
{
file: 'dist/surveys.esm.js',
file: 'dist/surveys-module-previews.js',
format: 'es',
sourcemap: true,
},
Expand Down
37 changes: 35 additions & 2 deletions src/__tests__/extensions/surveys.test.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import 'regenerator-runtime/runtime'
import { generateSurveys, renderSurveysPreview } from '../../extensions/surveys'
import { generateSurveys, renderSurveysPreview, renderFeedbackWidgetPreview } from '../../extensions/surveys'
import { createShadow } from '../../extensions/surveys/surveys-utils'
import { Survey, SurveyQuestionType, SurveyType } from '../../posthog-surveys-types'

Expand Down Expand Up @@ -57,7 +57,14 @@ describe('survey display logic', () => {
})
})

describe('survey render preview', () => {
describe('preview renders', () => {
beforeEach(() => {
// we have to manually reset the DOM before each test
document.getElementsByTagName('html')[0].innerHTML = ''
localStorage.clear()
jest.clearAllMocks()
})

test('renderSurveysPreview', () => {
const mockSurvey = {
id: 'testSurvey1',
Expand Down Expand Up @@ -89,4 +96,30 @@ describe('survey render preview', () => {
expect(surveyDiv.getElementsByClassName('survey-form').length).toBe(1)
expect(surveyDiv.getElementsByClassName('survey-question').length).toBe(1)
})

test('renderFeedbackWidgetPreview', () => {
const mockSurvey = {
id: 'testSurvey1',
name: 'Test survey 1',
type: SurveyType.Widget,
appearance: { widgetLabel: 'preview test', widgetColor: 'black', widgetType: 'tab' },
start_date: '2021-01-01T00:00:00.000Z',
description: 'This is a survey description',
linked_flag_key: null,
questions: [
{
question: 'What would you like to see next?',
type: SurveyQuestionType.Open,
},
],
end_date: null,
targeting_flag_key: null,
}
const root = document.createElement('div')
expect(root.innerHTML).toBe('')
renderFeedbackWidgetPreview(mockSurvey as Survey, root)
expect(root.getElementsByTagName('style').length).toBe(1)
expect(root.getElementsByClassName('ph-survey-widget-tab').length).toBe(1)
expect(root.getElementsByClassName('ph-survey-widget-tab')[0].innerHTML).toContain('preview test')
})
})
14 changes: 9 additions & 5 deletions src/extensions/surveys-widget.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,19 @@ export function createWidgetShadow(survey: Survey) {
const div = document.createElement('div')
div.className = `PostHogWidget${survey.id}`
const shadow = div.attachShadow({ mode: 'open' })
const widgetStyleSheet = `
const widgetStyleSheet = createWidgetStyle(survey.appearance?.widgetColor)
shadow.append(Object.assign(document.createElement('style'), { innerText: widgetStyleSheet }))
document.body.appendChild(div)
return shadow
}

export function createWidgetStyle(widgetColor?: string) {
return `
.ph-survey-widget-tab {
position: fixed;
top: 50%;
right: 0;
background: ${survey.appearance?.widgetColor || '#e0a045'};
background: ${widgetColor || '#e0a045'};
color: white;
transform: rotate(-90deg) translate(0, -100%);
transform-origin: right top;
Expand All @@ -32,7 +39,4 @@ export function createWidgetShadow(survey: Survey) {
position: fixed;
}
`
shadow.append(Object.assign(document.createElement('style'), { innerText: widgetStyleSheet }))
document.body.appendChild(div)
return shadow
}
42 changes: 36 additions & 6 deletions src/extensions/surveys.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ import {
} from './surveys/surveys-utils'
import * as Preact from 'preact'
import { render } from 'preact-render-to-string'
import { createWidgetShadow } from './surveys-widget'
import { createWidgetShadow, createWidgetStyle } from './surveys-widget'
import { useState, useEffect, useRef, useContext } from 'preact/hooks'
import { _isNumber } from '../utils/type-utils'
import { ConfirmationMessage } from './surveys/components/ConfirmationMessage'
Expand All @@ -41,7 +41,7 @@ const handleWidget = (posthog: PostHog, survey: Survey) => {
const shadow = createWidgetShadow(survey)
const surveyStyleSheet = style(survey.appearance)
shadow.appendChild(Object.assign(document.createElement('style'), { innerText: surveyStyleSheet }))
Preact.render(<FeedbackWidget posthog={posthog} survey={survey} />, shadow)
Preact.render(<FeedbackWidget key={'feedback-survey'} posthog={posthog} survey={survey} />, shadow)
}

export const callSurveys = (posthog: PostHog, forceReload: boolean = false) => {
Expand Down Expand Up @@ -99,7 +99,7 @@ export const callSurveys = (posthog: PostHog, forceReload: boolean = false) => {

if (!localStorage.getItem(`seenSurvey_${survey.id}`)) {
const shadow = createShadow(style(survey?.appearance), survey.id)
Preact.render(<Surveys posthog={posthog} survey={survey} />, shadow)
Preact.render(<Surveys key={'popover-survey'} posthog={posthog} survey={survey} />, shadow)
}
}
})
Expand All @@ -120,6 +120,7 @@ export const renderSurveysPreview = (
)
const surveyHtml = render(
<Surveys
key={'surveys-render-preview'}
survey={survey}
readOnly={true}
initialDisplayState={displayState}
Expand All @@ -138,6 +139,16 @@ export const renderSurveysPreview = (
root.appendChild(surveyDiv)
}

export const renderFeedbackWidgetPreview = (survey: Survey, root: HTMLElement) => {
const widgetStyleSheet = createWidgetStyle(survey.appearance?.widgetColor)
const styleElement = Object.assign(document.createElement('style'), { innerText: widgetStyleSheet })
root.appendChild(styleElement)
const widgetHtml = render(<FeedbackWidget key={'feedback-render-preview'} survey={survey} readOnly={true} />)
const widgetDiv = document.createElement('div')
widgetDiv.innerHTML = widgetHtml
root.appendChild(widgetDiv)
}

// This is the main exported function
export function generateSurveys(posthog: PostHog) {
// NOTE: Important to ensure we never try and run surveys without a window environment
Expand Down Expand Up @@ -364,12 +375,24 @@ const closeSurveyPopup = (survey: Survey, posthog?: PostHog, readOnly?: boolean)
window.dispatchEvent(new Event('PHSurveyClosed'))
}

export function FeedbackWidget({ posthog, survey }: { posthog: PostHog; survey: Survey }): JSX.Element {
export function FeedbackWidget({
survey,
posthog,
readOnly,
}: {
survey: Survey
posthog?: PostHog
readOnly?: boolean
}): JSX.Element {
const [showSurvey, setShowSurvey] = useState(false)
const [styleOverrides, setStyle] = useState({})
const widgetRef = useRef<HTMLDivElement>(null)

useEffect(() => {
if (readOnly || !posthog) {
return
}

if (survey.appearance?.widgetType === 'tab') {
if (widgetRef.current) {
const widgetPos = widgetRef.current.getBoundingClientRect()
Expand All @@ -395,12 +418,19 @@ export function FeedbackWidget({ posthog, survey }: { posthog: PostHog; survey:
return (
<>
{survey.appearance?.widgetType === 'tab' && (
<div className="ph-survey-widget-tab" ref={widgetRef} onClick={() => setShowSurvey(!showSurvey)}>
<div
className="ph-survey-widget-tab"
ref={widgetRef}
onClick={() => !readOnly && setShowSurvey(!showSurvey)}
style={{ color: getContrastingTextColor(survey.appearance.widgetColor) }}
>
<div className="ph-survey-widget-tab-icon"></div>
{survey.appearance?.widgetLabel || ''}
</div>
)}
{showSurvey && <Surveys posthog={posthog} survey={survey} style={styleOverrides} />}
{showSurvey && (
<Surveys key={'feedback-widget-survey'} posthog={posthog} survey={survey} style={styleOverrides} />
)}
</>
)
}
1 change: 1 addition & 0 deletions src/loader-surveys-preview.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export { renderSurveysPreview, renderFeedbackWidgetPreview } from './extensions/surveys'
1 change: 0 additions & 1 deletion src/loader-surveys.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import { generateSurveys } from './extensions/surveys'

import { window } from './utils/globals'
export { renderSurveysPreview } from './extensions/surveys'

if (window) {
;(window as any).extendPostHogWithSurveys = generateSurveys
Expand Down

0 comments on commit 1b5632d

Please sign in to comment.