Utilise une vraie iframe pour la prévisualisation de l'intégration (#2193)

pull/2197/head
Maxime Quandalle 2022-07-05 19:18:03 +02:00 committed by GitHub
parent 5a482f7c3a
commit 537d2bfe39
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 71 additions and 88 deletions

View File

@ -1,4 +1,5 @@
import React, { useEffect, useMemo, useRef } from 'react'
import { hexToHSL } from '@/hexToHSL'
import React, { useEffect, useMemo, useRef, useState } from 'react'
import { ThemeProvider } from 'styled-components'
import { useIsEmbedded } from './embeddedContext'
@ -27,17 +28,21 @@ const rawIframeColor = new URLSearchParams(
const IFRAME_COLOR = rawIframeColor
? (JSON.parse(decodeURIComponent(rawIframeColor)) as number[])
: DEFAULT_COLOR_HS
// Note that the iframeColor is first set in the index.html file, but without
// the full palette generation that happen here. This is to prevent a UI
// flash, cf. #1786.
export function ThemeColorsProvider({ color, children }: ProviderProps) {
export function ThemeColorsProvider({ children }: ProviderProps) {
const divRef = useRef<HTMLDivElement>(null)
const [hue, saturation] = useMemo(
() => (color ? color.slice(0, 2) : IFRAME_COLOR),
[color]
)
const [themeColor, setThemeColor] = useState(IFRAME_COLOR)
useEffect(() => {
window.addEventListener('message', (evt: MessageEvent) => {
if (evt.data.kind === 'change-theme-color') {
setThemeColor(hexToHSL(evt.data.value))
}
})
}, [])
const [hue, saturation] = themeColor
useEffect(() => {
const root = document.querySelector(':root') as HTMLElement | undefined
root?.style.setProperty(`--${HUE_CSS_VARIABLE_NAME}`, `${hue}deg`)
@ -48,7 +53,7 @@ export function ThemeColorsProvider({ color, children }: ProviderProps) {
}, [hue, saturation])
const isEmbedded = useIsEmbedded()
if (!color && !isEmbedded) {
if (!themeColor && !isEmbedded) {
return <>{children}</>
}

View File

@ -4,9 +4,7 @@ const script = document.currentScript
const moduleName = script.dataset.module || 'simulateur-embauche'
const couleur =
script.dataset.couleur &&
encodeURIComponent(
JSON.stringify(hexToHSL(script.dataset.couleur.toUpperCase()))
)
encodeURIComponent(JSON.stringify(hexToHSL(script.dataset.couleur)))
const lang = script.dataset.lang || 'fr'

View File

@ -1,10 +1,8 @@
import { ThemeColorsProvider } from '@/components/utils/colors'
import { IsEmbeded } from '@/components/utils/embeddedContext'
import { useEffect } from 'react'
import { Helmet } from 'react-helmet-async'
import { Route, Switch } from 'react-router-dom'
import useSimulatorsData from '../Simulateurs/metadata'
import SimulateurPage from '../../components/PageData'
import useSimulatorsData from '../Simulateurs/metadata'
import IframeFooter from './IframeFooter'
export default function Iframes() {
@ -17,31 +15,29 @@ export default function Iframes() {
Our own link are handled in-app by the router, and aren't affected by this directive.
*/}
<base target="_parent" />
<ThemeColorsProvider>
<Switch>
{Object.values(simulators)
.filter((el) => !!('iframePath' in el && el.iframePath))
.map(
(s) =>
'iframePath' in s &&
s.iframePath && (
<Route
key={s.iframePath}
path={`/iframes/${s.iframePath}`}
render={() => (
<>
<Helmet>
<link rel="canonical" href={s.path} />
</Helmet>
<SimulateurPage {...s} />
</>
)}
/>
)
)}
</Switch>
<IframeFooter />
</ThemeColorsProvider>
<Switch>
{Object.values(simulators)
.filter((el) => !!('iframePath' in el && el.iframePath))
.map(
(s) =>
'iframePath' in s &&
s.iframePath && (
<Route
key={s.iframePath}
path={`/iframes/${s.iframePath}`}
render={() => (
<>
<Helmet>
<link rel="canonical" href={s.path} />
</Helmet>
<SimulateurPage {...s} />
</>
)}
/>
)
)}
</Switch>
<IframeFooter />
</IsEmbeded>
)
}

View File

@ -1,8 +1,4 @@
import { Log } from '@/ATInternetTracking/Tracker'
import { ThemeColorsProvider } from '@/components/utils/colors'
import { IsEmbeddedProvider } from '@/components/utils/embeddedContext'
import Emoji from '@/components/utils/Emoji'
import { SitePathsContext } from '@/components/utils/SitePathsContext'
import { PopoverWithTrigger } from '@/design-system'
import { Article } from '@/design-system/card'
import { Item, Select } from '@/design-system/field/Select'
@ -11,18 +7,11 @@ import { H1, H2, H3 } from '@/design-system/typography/heading'
import { Link } from '@/design-system/typography/link'
import { Body, Intro } from '@/design-system/typography/paragraphs'
import urssafLogo from '@/images/Urssaf.svg'
import { lazy, Suspense, useContext, useEffect, useRef, useState } from 'react'
import { lazy, Suspense, useEffect, useRef, useState } from 'react'
import { Trans, useTranslation } from 'react-i18next'
import { Route } from 'react-router'
import { MemoryRouter, useSearchParams } from 'react-router-dom-v5-compat'
import { useHref, useSearchParams } from 'react-router-dom-v5-compat'
import styled from 'styled-components'
import { TrackingContext, TrackPage } from '../../ATInternetTracking'
import { hexToHSL } from '../../hexToHSL'
import Créer from '../Creer'
import Documentation from '../Documentation'
import AssistantDéclarationRevenuIndépendant from '../gerer/declaration-revenu-independants'
import Iframes from '../Iframes'
import Simulateurs from '../Simulateurs'
import { TrackPage } from '../../ATInternetTracking'
import useSimulatorsData, { SimulatorData } from '../Simulateurs/metadata'
import './iframe.css'
import cciLogo from './images/cci.png'
@ -46,7 +35,6 @@ const getFromSimu = <S extends SimulatorData, T extends string>(
function IntegrationCustomizer() {
const simulatorsData = useSimulatorsData()
const sitePaths = useContext(SitePathsContext)
const [searchParams, setSearchParams] = useSearchParams()
const defaultModuleFromUrl = searchParams.get('module') ?? ''
@ -71,6 +59,27 @@ function IntegrationCustomizer() {
currentSimulator.iframePath) ||
''
const iframeRef = useRef<HTMLIFrameElement>(null)
const iframeSrc = useHref(`/iframes/${currentIframePath}?iframe`)
useEffect(() => {
window.addEventListener(
'message',
function (evt: MessageEvent<{ kind: string; value: string }>) {
if (iframeRef.current && evt.data.kind === 'resize-height') {
iframeRef.current.style.height = evt.data.value + 'px'
}
}
)
}, [iframeRef])
useEffect(() => {
iframeRef.current?.contentWindow?.postMessage({
kind: 'change-theme-color',
value: color,
})
}, [iframeRef, color])
return (
<>
<H2>
@ -143,50 +152,25 @@ function IntegrationCustomizer() {
</H3>
<PrevisualisationContainer>
<Previsualisation>
<TrackingContext.Provider value={DummyTracker}>
<MemoryRouter
key={currentModule}
initialEntries={[`/iframes/${currentIframePath}`]}
>
<ThemeColorsProvider
color={color == null ? color : hexToHSL(color)}
>
<IsEmbeddedProvider isEmbeded>
<Route
path={sitePaths.simulateurs.index}
component={Simulateurs}
/>
<Route path={sitePaths.créer.index} component={Créer} />
<Route
path={sitePaths.gérer.déclarationIndépendant.beta}
component={AssistantDéclarationRevenuIndépendant}
/>
<Route
path={sitePaths.documentation.index}
component={Documentation}
/>
<Iframes />
</IsEmbeddedProvider>
</ThemeColorsProvider>
</MemoryRouter>
</TrackingContext.Provider>
</Previsualisation>
<PreviewIframe src={iframeSrc} ref={iframeRef} />
</PrevisualisationContainer>
</Grid>
</Grid>
</>
)
}
const DummyTracker = new Log()
const Previsualisation = styled.div`
background-color: white;
margin-top: 2rem;
overflow: hidden;
const PreviewIframe = styled.iframe`
width: 100%;
height: 700px;
border: 0px;
`
const PrevisualisationContainer = styled.div`
outline: 2px solid ${({ theme }) => theme.colors.extended.grey[300]};
margin-top: 2rem;
overflow: hidden;
background-color: white;
outline-offset: 1rem;
`