Utilise une vraie iframe pour la prévisualisation de l'intégration (#2193)
parent
5a482f7c3a
commit
537d2bfe39
|
@ -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}</>
|
||||
}
|
||||
|
||||
|
|
|
@ -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'
|
||||
|
||||
|
|
|
@ -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>
|
||||
)
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
`
|
||||
|
||||
|
|
Loading…
Reference in New Issue