first commit:
- we have a static astro website under /website. It has the implementation docs of the homepage/gaufre templates, and it handles the few API endpoints (the gaufre js, backgrounds, logos) - we have a vite app under /packages/integration. It has the react components generating the homepage and the gaufre button, and their css. Its used to generate an npm package
This commit is contained in:
8
website/src/components/Aside.tsx
Normal file
8
website/src/components/Aside.tsx
Normal file
@@ -0,0 +1,8 @@
|
||||
export default function Aside({ type = "note", title = "", children }) {
|
||||
return (
|
||||
<div className={`starlight-aside starlight-aside--${type}`}>
|
||||
<p className="starlight-aside__title">{title}</p>
|
||||
<section className="starlight-aside__content">{children}</section>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
24
website/src/components/Code.tsx
Normal file
24
website/src/components/Code.tsx
Normal file
@@ -0,0 +1,24 @@
|
||||
import { useEffect } from "react"
|
||||
import * as Prism from "prismjs"
|
||||
import "prismjs/components/prism-jsx"
|
||||
import "@/styles/prism.css"
|
||||
|
||||
export default function Code({ children, language, fixedHeight = false }) {
|
||||
useEffect(() => {
|
||||
Prism.highlightAll()
|
||||
}, [children, language])
|
||||
return (
|
||||
<div className={fixedHeight ? "language-fixedheight react-code" : "react-code"}>
|
||||
<pre>
|
||||
<code className={`language-${language}`}>{children}</code>
|
||||
</pre>
|
||||
<button
|
||||
onClick={() => {
|
||||
navigator.clipboard.writeText(children)
|
||||
}}
|
||||
>
|
||||
Copier
|
||||
</button>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
237
website/src/components/HomepageGenerator.tsx
Normal file
237
website/src/components/HomepageGenerator.tsx
Normal file
@@ -0,0 +1,237 @@
|
||||
import { useEffect, useState } from "react"
|
||||
import { renderToStaticMarkup } from "react-dom/server"
|
||||
import services from "@/data/services.json"
|
||||
import Code from "./Code"
|
||||
import {
|
||||
Homepage,
|
||||
HomepageEmail,
|
||||
HomepageEmailOrProconnect,
|
||||
HomepageProconnect,
|
||||
} from "@gouvfr-lasuite/integration"
|
||||
import * as prettier from "prettier/standalone"
|
||||
import prettierHtml from "prettier/plugins/html"
|
||||
|
||||
const defaultFormData = {
|
||||
serviceId: "",
|
||||
serviceName: "Service",
|
||||
tagline: "**Service**, un outil sécurisé <br>pour les agents de l'État",
|
||||
entity: "Gouvernement",
|
||||
homepageType: "proconnect",
|
||||
}
|
||||
|
||||
const homepageTypes = {
|
||||
proconnect: {
|
||||
label: "ProConnect uniquement",
|
||||
importCode: "HomepageProconnect",
|
||||
componentCode: `<HomepageProconnect url="~~replace~~" />`,
|
||||
Component: <HomepageProconnect url="~~replace~~" />,
|
||||
},
|
||||
"email-or-proconnect": {
|
||||
label: "E-mail + ProConnect",
|
||||
importCode: "HomepageEmailOrProconnect",
|
||||
componentCode: `<HomepageEmailOrProconnect proconnectUrl="~~replace~~" emailForm={{ action: "~~replace~~" }} />`,
|
||||
Component: (
|
||||
<HomepageEmailOrProconnect
|
||||
proconnectUrl="~~replace~~"
|
||||
emailForm={{ action: "~~replace~~" }}
|
||||
/>
|
||||
),
|
||||
},
|
||||
email: {
|
||||
label: "E-mail uniquement",
|
||||
importCode: "HomepageEmail",
|
||||
componentCode: `<HomepageEmail action="~~replace~~" />`,
|
||||
Component: <HomepageEmail action="~~replace~~" />,
|
||||
},
|
||||
custom: {
|
||||
label: "Autre",
|
||||
importCode: null,
|
||||
componentCode: `~~replace~~`,
|
||||
Component: null,
|
||||
},
|
||||
}
|
||||
|
||||
export default function HomepageGenerator() {
|
||||
const [codeData, setCodeData] = useState<any>(defaultFormData)
|
||||
const [htmlMarkup, setHtmlMarkup] = useState<string>("")
|
||||
useEffect(() => {
|
||||
getHTMLMarkup(codeData).then((html) => {
|
||||
setHtmlMarkup(html)
|
||||
})
|
||||
}, [codeData])
|
||||
|
||||
return (
|
||||
<div style={{ margin: "1.5rem 0" }}>
|
||||
<form
|
||||
className="react-form not-content"
|
||||
onChange={(e) => {
|
||||
const formData = new FormData(e.currentTarget)
|
||||
setCodeData({
|
||||
...Object.fromEntries(formData),
|
||||
serviceId:
|
||||
formData.get("serviceId") && formData.get("serviceId") !== "other"
|
||||
? formData.get("serviceId")
|
||||
: undefined,
|
||||
})
|
||||
}}
|
||||
>
|
||||
<div className="react-form-input">
|
||||
<label htmlFor="serviceId">Service</label>
|
||||
<select
|
||||
name="serviceId"
|
||||
id="serviceId"
|
||||
defaultValue={defaultFormData.serviceId}
|
||||
onChange={(e) => {
|
||||
const serviceId = e.currentTarget.value
|
||||
const service = services.find((service) => service.id === serviceId)
|
||||
;(document.querySelector("#tagline") as HTMLInputElement).value = (
|
||||
service || defaultFormData
|
||||
).tagline
|
||||
;(document.querySelector("#entity") as HTMLInputElement).value = (
|
||||
service || defaultFormData
|
||||
).entity
|
||||
;(document.querySelector("#serviceName") as HTMLInputElement).value = service
|
||||
? service.name
|
||||
: defaultFormData.serviceName
|
||||
;(document.querySelector("#homepageType") as HTMLInputElement).value = (
|
||||
service || defaultFormData
|
||||
).homepageType
|
||||
}}
|
||||
>
|
||||
<option value="">Choisir votre service pour pré-remplir les champs</option>
|
||||
{services.map((service) => (
|
||||
<option key={service.id} value={service.id}>
|
||||
{service.name}
|
||||
</option>
|
||||
))}
|
||||
<option value="other">Autre…</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div className="react-form-input">
|
||||
<label htmlFor="serviceName">Nom du service</label>
|
||||
<input
|
||||
type="text"
|
||||
name="serviceName"
|
||||
id="serviceName"
|
||||
defaultValue={defaultFormData.serviceName}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<input type="hidden" name="entity" id="entity" defaultValue={defaultFormData.entity} />
|
||||
|
||||
<div className="react-form-input">
|
||||
<label htmlFor="tagline">
|
||||
Phrase d'accroche
|
||||
<span>
|
||||
Mettre le texte entre ** pour l'écrire en gras, usage de <code><br></code>{" "}
|
||||
possible
|
||||
</span>
|
||||
</label>
|
||||
<input type="text" name="tagline" id="tagline" defaultValue={defaultFormData.tagline} />
|
||||
</div>
|
||||
|
||||
<div className="react-form-input">
|
||||
<label htmlFor="homepageType">Type de connexion</label>
|
||||
<select name="homepageType" id="homepageType">
|
||||
<option value="">Choisir…</option>
|
||||
{Object.keys(homepageTypes).map((key) => (
|
||||
<option key={key} value={key}>
|
||||
{homepageTypes[key].label}
|
||||
</option>
|
||||
))}
|
||||
</select>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
{!!codeData && (
|
||||
<>
|
||||
<div>
|
||||
<h2 style={{ marginTop: "1.5em" }}>Code React correspondant</h2>
|
||||
<Code language="jsx">{getReactMarkup(codeData)}</Code>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<h2 style={{ marginTop: "1.5em" }}>Code HTML correspondant</h2>
|
||||
<Code language="html" fixedHeight>
|
||||
{htmlMarkup}
|
||||
</Code>
|
||||
</div>
|
||||
</>
|
||||
)}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
const getReactMarkup = (codeData) => {
|
||||
return `import { Homepage${
|
||||
codeData.homepageType && homepageTypes[codeData.homepageType].importCode
|
||||
? `, ${homepageTypes[codeData.homepageType].importCode}`
|
||||
: ""
|
||||
} } from "@gouvfr-lasuite/integration"
|
||||
|
||||
export default function MyHomepage() {
|
||||
return (
|
||||
<Homepage
|
||||
lasuiteApiUrl="${import.meta.env.PUBLIC_LASUITE_API_URL}"
|
||||
entity="${codeData.entity}"
|
||||
tagline="${codeData.tagline}"
|
||||
serviceName="${codeData.serviceName}" ${
|
||||
!!codeData.serviceId
|
||||
? `
|
||||
serviceId="${codeData.serviceId}"`
|
||||
: ""
|
||||
}
|
||||
logo="~~replace~~"
|
||||
homepageUrl="/"
|
||||
footerOptions={{
|
||||
description: "Un service de la Direction interministérielle du numérique",
|
||||
sitemapUrl: "~~replace~~",
|
||||
a11yUrl: "~~replace~~",
|
||||
a11yLevel: "~~replace~~",
|
||||
termsUrl: "~~replace~~",
|
||||
privacyUrl: "~~replace~~",
|
||||
}}
|
||||
>
|
||||
${codeData.homepageType ? homepageTypes[codeData.homepageType].componentCode : ""}
|
||||
</Homepage>
|
||||
)
|
||||
}`
|
||||
}
|
||||
|
||||
const getHTMLMarkup = (codeData) => {
|
||||
const Component = (
|
||||
<Homepage
|
||||
lasuiteApiUrl={import.meta.env.PUBLIC_LASUITE_API_URL}
|
||||
entity={codeData.entity}
|
||||
tagline={codeData.tagline}
|
||||
serviceName={codeData.serviceName}
|
||||
serviceId={codeData.serviceId}
|
||||
logo={
|
||||
codeData.serviceId
|
||||
? `${import.meta.env.PUBLIC_LASUITE_API_URL}/api/logos/v1/${codeData.serviceId}.svg`
|
||||
: "~~replace~~"
|
||||
}
|
||||
homepageUrl="/"
|
||||
footerOptions={{
|
||||
description: "Un service de la Direction interministérielle du numérique",
|
||||
sitemapUrl: "~~replace~~",
|
||||
a11yUrl: "~~replace~~",
|
||||
a11yLevel: "~~replace~~" as "non compliant",
|
||||
termsUrl: "~~replace~~",
|
||||
privacyUrl: "~~replace~~",
|
||||
}}
|
||||
>
|
||||
{codeData.homepageType ? homepageTypes[codeData.homepageType].Component : ""}
|
||||
</Homepage>
|
||||
)
|
||||
const markup = renderToStaticMarkup(Component)
|
||||
return prettier.format(markup, {
|
||||
parser: "html",
|
||||
plugins: [prettierHtml],
|
||||
printWidth: 100,
|
||||
tabWidth: 4,
|
||||
bracketSameLine: false,
|
||||
htmlWhitespaceSensitivity: "ignore",
|
||||
})
|
||||
}
|
||||
Reference in New Issue
Block a user