diff --git a/core/urls.py b/core/urls.py index 4cc8cd679..14fbe74ad 100644 --- a/core/urls.py +++ b/core/urls.py @@ -32,7 +32,7 @@ from qfdmd.models import Synonyme from .api import api -from .views import robots_txt +from .views import backlink, robots_txt info_dict = { "queryset": Synonyme.objects.filter().order_by("nom"), @@ -54,6 +54,7 @@ class PaginatedSitemap(GenericSitemap): path("admin/", admin.site.urls), path("api/", api.urls), path("robots.txt", robots_txt), + path("embed/backlink", backlink), path( "sitemap.xml", index, diff --git a/core/views.py b/core/views.py index 5359bb802..fd1d359aa 100644 --- a/core/views.py +++ b/core/views.py @@ -4,8 +4,25 @@ from django.contrib.staticfiles import finders from django.http import HttpResponse from django.template.loader import render_to_string +from django.utils.safestring import mark_safe from django.views.decorators.cache import cache_control +from qfdmd.models import EmbedSettings + + +@cache_control(max_age=3600) # an hour +def backlink(request): + key = request.GET.get("key") + text_content = "" + if key == "assistant": + text_content = EmbedSettings.objects.first().backlink_assistant + if key == "carte": + text_content = EmbedSettings.objects.first().backlink_carte + if key == "formulaire": + text_content = EmbedSettings.objects.first().backlink_formulaire + + return HttpResponse(mark_safe(text_content), content_type="text/plain") + @cache_control(max_age=31536000) def robots_txt(request): diff --git a/qfdmd/migrations/0057_embedsettings.py b/qfdmd/migrations/0057_embedsettings.py new file mode 100644 index 000000000..49f0bded3 --- /dev/null +++ b/qfdmd/migrations/0057_embedsettings.py @@ -0,0 +1,49 @@ +# Generated by Django 5.2.5 on 2025-09-11 11:34 + +import wagtail.fields +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ("qfdmd", "0056_alter_produitpage_body"), + ] + + operations = [ + migrations.CreateModel( + name="EmbedSettings", + fields=[ + ( + "id", + models.BigAutoField( + auto_created=True, + primary_key=True, + serialize=False, + verbose_name="ID", + ), + ), + ( + "backlink_assistant", + wagtail.fields.RichTextField( + verbose_name="Backlink de l'iframe de l'assistant" + ), + ), + ( + "backlink_carte", + wagtail.fields.RichTextField( + verbose_name="Backlink de l'iframe de la carte" + ), + ), + ( + "backlink_formulaire", + wagtail.fields.RichTextField( + verbose_name="Backlink de l'iframe du formulaire" + ), + ), + ], + options={ + "verbose_name": "Réglage des iframes", + }, + ), + ] diff --git a/qfdmd/models.py b/qfdmd/models.py index 92fb7f62c..712251c82 100644 --- a/qfdmd/models.py +++ b/qfdmd/models.py @@ -21,6 +21,10 @@ ObjectList, TabbedInterface, ) +from wagtail.contrib.settings.models import ( + BaseGenericSetting, + register_setting, +) from wagtail.fields import RichTextField, StreamField from wagtail.images.blocks import ImageBlock from wagtail.models import Page, ParentalKey @@ -770,3 +774,29 @@ class Suggestion(models.Model): def __str__(self) -> str: return str(self.produit) + + +@register_setting +class EmbedSettings(BaseGenericSetting): + backlink_assistant = RichTextField("Backlink de l'iframe de l'assistant") + backlink_carte = RichTextField("Backlink de l'iframe de la carte") + backlink_formulaire = RichTextField("Backlink de l'iframe du formulaire") + + panels = [ + MultiFieldPanel( + [ + FieldPanel("backlink_assistant"), + FieldPanel("backlink_carte"), + FieldPanel("backlink_formulaire"), + HelpPanel( + "Les backlink sont cachés pendant dix minutes.\n" + "Cela veut dire qu'une mise à jour du contenu ci-dessus " + "ne sera reflétée qu'après ce délai." + ), + ], + heading="Backlink", + ) + ] + + class Meta: + verbose_name = "Réglage des iframes" diff --git a/static/to_compile/embed/assistant.ts b/static/to_compile/embed/assistant.ts index d7b9ce3aa..28ed59ef3 100644 --- a/static/to_compile/embed/assistant.ts +++ b/static/to_compile/embed/assistant.ts @@ -1,5 +1,6 @@ import iframeResize from "@iframe-resizer/parent" import { URL_PARAM_NAME_FOR_IFRAME_SCRIPT_MODE } from "../js/helpers" +import { generateBackLink } from "./helpers" import { iframeResizer } from "@iframe-resizer/child" const script = document.currentScript as HTMLScriptElement @@ -11,7 +12,7 @@ if (process.env.BASE_URL) { origin = process.env.BASE_URL } -function initScript() { +async function initScript() { const parts = [origin] const iframeResizerOptions: iframeResizer.IFramePageOptions = { license: "GPLv3", @@ -52,6 +53,7 @@ function initScript() { } script.parentNode?.insertBefore(iframe, script) + await generateBackLink(iframe, "assistant") iframe.onload = () => { iframeResize(iframeResizerOptions, iframe) } diff --git a/static/to_compile/embed/carte.ts b/static/to_compile/embed/carte.ts index cf8fcfe15..f3e3d60f7 100644 --- a/static/to_compile/embed/carte.ts +++ b/static/to_compile/embed/carte.ts @@ -10,7 +10,7 @@ const setupIframe = () => { scriptTag, "carte", ) - buildAndInsertIframeFrom(iframeAttributes, iframeExtraAttributes, scriptTag) + buildAndInsertIframeFrom(iframeAttributes, iframeExtraAttributes, scriptTag, "carte") } setupIframe() diff --git a/static/to_compile/embed/formulaire.ts b/static/to_compile/embed/formulaire.ts index 3f1352f64..7ffd0efdf 100644 --- a/static/to_compile/embed/formulaire.ts +++ b/static/to_compile/embed/formulaire.ts @@ -11,7 +11,12 @@ const setupIframe = () => { "formulaire", { maxWidth: "800px" }, ) - buildAndInsertIframeFrom(iframeAttributes, iframeExtraAttributes, scriptTag) + buildAndInsertIframeFrom( + iframeAttributes, + iframeExtraAttributes, + scriptTag, + "formulaire", + ) } setupIframe() diff --git a/static/to_compile/embed/helpers.ts b/static/to_compile/embed/helpers.ts new file mode 100644 index 000000000..0a622fa89 --- /dev/null +++ b/static/to_compile/embed/helpers.ts @@ -0,0 +1,11 @@ +export type BacklinkKey = "assistant" | "carte" | "formulaire" +export async function generateBackLink(iframe: HTMLIFrameElement, key: BacklinkKey) { + const backlinkTag = document.createElement("div") + backlinkTag.setAttribute( + "style", + "font-size: 0.9rem; text-align: center; padding-top: 0.5rem;", + ) + const backlinkContent = await fetch(`${origin}/embed/backlink?key=${key}`) + backlinkTag.innerHTML = await backlinkContent.text() + iframe.insertAdjacentElement("afterend", backlinkTag) +} diff --git a/static/to_compile/js/iframe_functions.ts b/static/to_compile/js/iframe_functions.ts index 105998163..0fc2129e8 100644 --- a/static/to_compile/js/iframe_functions.ts +++ b/static/to_compile/js/iframe_functions.ts @@ -1,3 +1,5 @@ +import { BacklinkKey } from "../embed/helpers" + function compileIframeAttributes( baseUrl: string, urlParams: URLSearchParams, @@ -30,8 +32,10 @@ export function buildAndInsertIframeFrom( iframeAttributes: object, iframeExtraAttributes: object, scriptTag: HTMLScriptElement, + backlinkKey: BacklinkKey, ) { const iframe = document.createElement("iframe") + await generateBackLink(iframe, key) for (var key in iframeAttributes) { iframe.setAttribute(key, iframeAttributes[key]) }