Ajoute le widget de chat Chatwoot (essai) — issue #120

Injecte le script d'intégration Chatwoot dans app.index_string, activé
via CHATWOOT_WEBSITE_TOKEN. Vide par défaut, donc désactivé en test/CI.
This commit is contained in:
Colin Maudry
2026-07-15 15:50:17 +02:00
parent 986600d3ef
commit 85b0dd0b39
4 changed files with 51 additions and 1 deletions
+4
View File
@@ -22,6 +22,10 @@ MATOMO_ID_SITE=
MATOMO_BASE_URL=
MATOMO_TOKEN=
# Widget de chat Chatwoot (essai, offre managée, issue #120). Laisser vide
# pour désactiver le widget.
CHATWOOT_WEBSITE_TOKEN=
# API privée
API_AUTH_DISABLED="false"
MATOMO_URL=https://analytics.maudry.com/matomo.php
+7 -1
View File
@@ -35,6 +35,7 @@ from flask_login import current_user
from src.auth.setup import init_auth
from src.utils import DEVELOPMENT
from src.utils.cache import cache
from src.utils.chatwoot import build_widget_script
load_dotenv()
@@ -222,6 +223,10 @@ with open("./pyproject.toml", "rb") as f:
pyproject = tomllib.load(f)
version = "v" + pyproject["project"]["version"]
# Widget de chat Chatwoot (essai, issue #120) : chaîne vide si la variable
# d'env n'est pas définie, ce qui désactive le widget (utilisé notamment
# pour ne jamais le charger pendant les tests/CI).
chatwoot_script = build_widget_script(os.getenv("CHATWOOT_WEBSITE_TOKEN"))
app.index_string = """
<!DOCTYPE html>
@@ -266,9 +271,10 @@ app.index_string = """
g.async=true; g.src=u+'matomo.js'; s.parentNode.insertBefore(g,s);
})();
</script>
__CHATWOOT_SCRIPT__
</body>
</html>
"""
""".replace("__CHATWOOT_SCRIPT__", chatwoot_script)
navbar = dbc.Navbar(
dbc.Container(
+23
View File
@@ -0,0 +1,23 @@
def build_widget_script(website_token: str | None) -> str:
"""Bloc <script> d'intégration du widget de chat Chatwoot (offre managée).
Renvoie une chaîne vide si aucun token n'est fourni, ce qui désactive le
widget (utilisé comme interrupteur pendant l'essai, voir issue #120).
"""
if not website_token:
return ""
return f"""<script>
(function(d,t) {{
var BASE_URL="https://app.chatwoot.com";
var g=d.createElement(t),s=d.getElementsByTagName(t)[0];
g.src=BASE_URL+"/packs/js/sdk.js";
g.async = true;
s.parentNode.insertBefore(g,s);
g.onload=function(){{
window.chatwootSDK.run({{
websiteToken: '{website_token}',
baseUrl: BASE_URL
}})
}}
}})(document,"script");
</script>"""
+17
View File
@@ -0,0 +1,17 @@
from src.utils.chatwoot import build_widget_script
def test_no_token_returns_empty_string():
assert build_widget_script(None) == ""
def test_empty_token_returns_empty_string():
assert build_widget_script("") == ""
def test_token_produces_script_with_token_and_managed_base_url():
script = build_widget_script("PVejdJRyKtSZdEkJtDJQ3xCd")
assert "<script>" in script
assert "websiteToken: 'PVejdJRyKtSZdEkJtDJQ3xCd'" in script
assert "baseUrl: BASE_URL" in script
assert 'BASE_URL="https://app.chatwoot.com"' in script