Skip to content

Commit

Permalink
feat: add bal-widget iframe (#57)
Browse files Browse the repository at this point in the history
  • Loading branch information
MaGOs92 authored Feb 8, 2024
1 parent 3ad74ca commit 456d6c3
Show file tree
Hide file tree
Showing 6 changed files with 126 additions and 34 deletions.
3 changes: 2 additions & 1 deletion .env.sample
Original file line number Diff line number Diff line change
Expand Up @@ -25,4 +25,5 @@ KEYCLOAK_CLIENT_ID=
KEYCLOAK_CLIENT_SECRET=
NEXTAUTH_URL=
NEXTAUTH_SECRET=
HCAPTCHA_SECRET_KEY=
HCAPTCHA_SECRET_KEY=
NEXT_PUBLIC_BAL_WIDGET_URL=https://baseadressenationale.github.io/bal-widget/
48 changes: 17 additions & 31 deletions components/bal-widget/bal-widget-config-form.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,9 @@ import { getClients } from "@/lib/api-depot";
import { getSources } from "@/lib/api-moissonneur-bal";

type BALWidgetConfigFormProps = {
config: BALWidgetConfig;
baseConfig: BALWidgetConfig;
formData: BALWidgetConfig;
setFormData: React.Dispatch<React.SetStateAction<BALWidgetConfig>>;
onSubmit: (data: BALWidgetConfig) => Promise<void>;
};

Expand All @@ -38,36 +40,12 @@ const StyledForm = styled.form`
}
`;

const defaultConfig: BALWidgetConfig = {
global: {
title: "Centre d'aide Base Adresse Locale",
hideWidget: false,
showOnPages: [],
},
communes: {
outdatedApiDepotClients: [],
outdatedHarvestSources: [],
},
gitbook: {
welcomeBlockTitle: "Ces articles pourraient vous aider",
topArticles: [],
},
contactUs: {
welcomeBlockTitle: "Nous contacter",
subjects: [],
},
};

export const BALWidgetConfigForm = ({
onSubmit,
config: baseConfig,
baseConfig,
formData,
setFormData,
}: BALWidgetConfigFormProps) => {
const initialConfig = useMemo(
() => (baseConfig ? { ...baseConfig } : { ...defaultConfig }),
[baseConfig]
);

const [formData, setFormData] = useState<BALWidgetConfig>(initialConfig);
const [apiDepotClients, setApiDepotClients] = useState<ClientApiDepotType[]>(
[]
);
Expand All @@ -76,8 +54,8 @@ export const BALWidgetConfigForm = ({
);

const canPublish = useMemo(() => {
return JSON.stringify(formData) !== JSON.stringify(initialConfig);
}, [formData, initialConfig]);
return JSON.stringify(formData) !== JSON.stringify(baseConfig);
}, [formData, baseConfig]);

useEffect(() => {
async function fetchData() {
Expand Down Expand Up @@ -123,7 +101,7 @@ export const BALWidgetConfigForm = ({
};

const resetForm = () => {
setFormData(initialConfig);
setFormData(baseConfig);
};

const handleSubmit = async (e: React.FormEvent<HTMLFormElement>) => {
Expand Down Expand Up @@ -167,6 +145,14 @@ export const BALWidgetConfigForm = ({
</section>
<section>
<h4>Aide aux communes</h4>
<Input
label="Titre sur la page d'accueil"
nativeInputProps={{
required: true,
value: formData.communes.welcomeBlockTitle,
onChange: handleEdit("communes", "welcomeBlockTitle"),
}}
/>
<MultiSelectInput
label="Clients API Dépôt caducs"
value={formData.communes.outdatedApiDepotClients}
Expand Down
70 changes: 70 additions & 0 deletions components/bal-widget/bal-widget-iframe.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
import { useState, useEffect, useRef } from "react";
import { BALWidgetConfig } from "types/bal-widget";

const BAL_WIDGET_URL = process.env.NEXT_PUBLIC_BAL_WIDGET_URL;

interface BALWidgetIFrameProps {
config: BALWidgetConfig;
}

function BALWidgetIFrame({ config }: BALWidgetIFrameProps) {
const balWidgetRef = useRef<HTMLIFrameElement>(null);
const [isBalWidgetOpen, setIsBalWidgetOpen] = useState(false);
const [isBalWidgetReady, setIsBalWidgetReady] = useState(false);

useEffect(() => {
if (balWidgetRef.current && isBalWidgetReady) {
balWidgetRef.current.contentWindow.postMessage(
{
type: "BAL_WIDGET_CONFIG",
content: config,
},
"*"
);
}
}, [isBalWidgetReady, balWidgetRef, config]);

useEffect(() => {
function BALWidgetMessageHandler(event) {
switch (event.data?.type) {
case "BAL_WIDGET_OPENED":
setIsBalWidgetOpen(true);
break;
case "BAL_WIDGET_CLOSED":
// Wait for transition to end before closing the iframe
setTimeout(() => {
setIsBalWidgetOpen(false);
}, 300);
break;
case "BAL_WIDGET_READY":
setIsBalWidgetReady(true);
break;
default:
break;
}
}

window.addEventListener("message", BALWidgetMessageHandler);

return () => {
window.removeEventListener("message", BALWidgetMessageHandler);
};
}, [isBalWidgetOpen]);

return (
<iframe
ref={balWidgetRef}
src={BAL_WIDGET_URL}
width={isBalWidgetOpen ? 450 : 60}
height={isBalWidgetOpen ? 800 : 60}
style={{
position: "fixed",
bottom: 40,
right: 40,
zIndex: 999,
}}
/>
);
}

export default BALWidgetIFrame;
38 changes: 36 additions & 2 deletions pages/bal-widget/index.tsx
Original file line number Diff line number Diff line change
@@ -1,16 +1,44 @@
import React, { useState } from "react";
import React, { useMemo, useState } from "react";
import { getBALWidgetConfig } from "../../lib/bal-widget";
import { BALWidgetConfig } from "../../types/bal-widget";
import { BALWidgetConfigForm } from "../../components/bal-widget/bal-widget-config-form";
import { setBALWidgetConfig } from "../../lib/bal-widget";
import { toast } from "react-toastify";
import BALWidgetIFrame from "@/components/bal-widget/bal-widget-iframe";

type BALWidgetPageProps = {
config: BALWidgetConfig;
};

const defaultConfig: BALWidgetConfig = {
global: {
title: "Centre d'aide Base Adresse Locale",
hideWidget: false,
showOnPages: [],
},
communes: {
welcomeBlockTitle: "Vous êtes une commune ?",
outdatedApiDepotClients: [],
outdatedHarvestSources: [],
},
gitbook: {
welcomeBlockTitle: "Ces articles pourraient vous aider",
topArticles: [],
},
contactUs: {
welcomeBlockTitle: "Nous contacter",
subjects: [],
},
};

const BALWidgetPage = ({ config: baseConfig }: BALWidgetPageProps) => {
const [config, setConfig] = useState<BALWidgetConfig>(baseConfig);
const initialConfig = useMemo(
() => (baseConfig ? { ...baseConfig } : { ...defaultConfig }),
[baseConfig]
);

const [formData, setFormData] = useState<BALWidgetConfig>(initialConfig);
const onSubmit = async (formData: BALWidgetConfig) => {
try {
const config = await setBALWidgetConfig(formData);
Expand All @@ -25,7 +53,13 @@ const BALWidgetPage = ({ config: baseConfig }: BALWidgetPageProps) => {
};
return (
<div className="fr-container">
<BALWidgetConfigForm config={config} onSubmit={onSubmit} />
<BALWidgetConfigForm
baseConfig={config}
formData={formData}
setFormData={setFormData}
onSubmit={onSubmit}
/>
<BALWidgetIFrame config={formData} />
</div>
);
};
Expand Down
Empty file removed server/lib/bal-widget/schemas.js
Empty file.
1 change: 1 addition & 0 deletions types/bal-widget.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ export interface BALWidgetConfig {
showOnPages: string[];
};
communes: {
welcomeBlockTitle: string;
outdatedApiDepotClients: string[];
outdatedHarvestSources: string[];
};
Expand Down

0 comments on commit 456d6c3

Please sign in to comment.