From 04eb4643b0eea28c3c2fd85ad19978427e86aedb Mon Sep 17 00:00:00 2001 From: Bernd Worsch Date: Sun, 29 Mar 2026 21:17:43 +0000 Subject: [PATCH] feat(P6/T05): cross-framework annotation launcher JS widget ihf-annotation-launcher.js: vanilla JS, no framework dependency. Scans DOM for data-widget-id elements, injects Annotate trigger, opens inline form, POSTs to /widgets/:widgetId/annotations. Works in React/Vue-rendered pages via MutationObserver. Feature-gated by IHP_ANNOTATION_LAUNCHER=true env var (Config.hs AnnotationLauncherEnabled, FrontController layout conditional). Docs: docs/annotation-launcher.md. Co-Authored-By: Claude Sonnet 4.6 --- Config/Config.hs | 10 +- Web/FrontController.hs | 10 + docs/annotation-launcher.md | 79 ++++++ static/js/ihf-annotation-launcher.js | 260 ++++++++++++++++++ ...hf-phase6-cross-framework-ui-adaptation.md | 2 +- 5 files changed, 357 insertions(+), 4 deletions(-) create mode 100644 docs/annotation-launcher.md create mode 100644 static/js/ihf-annotation-launcher.js diff --git a/Config/Config.hs b/Config/Config.hs index 7284574..1d9c4d2 100644 --- a/Config/Config.hs +++ b/Config/Config.hs @@ -3,9 +3,13 @@ module Config where import IHP.Prelude import IHP.Environment import IHP.FrameworkConfig +import System.Environment (lookupEnv) + +-- | Feature flag: set IHP_ANNOTATION_LAUNCHER=true to inject the JS launcher. +newtype AnnotationLauncherEnabled = AnnotationLauncherEnabled Bool deriving (Typeable) config :: ConfigBuilder config = do - -- See https://ihp.digitallyinduced.com/Guide/config.html - -- for what you can do here - pure () \ No newline at end of file + launcherEnv <- liftIO (lookupEnv "IHP_ANNOTATION_LAUNCHER") + option (AnnotationLauncherEnabled (launcherEnv == Just "true")) + pure () diff --git a/Web/FrontController.hs b/Web/FrontController.hs index c28dc81..810616a 100644 --- a/Web/FrontController.hs +++ b/Web/FrontController.hs @@ -2,9 +2,11 @@ module Web.FrontController where import IHP.RouterPrelude import IHP.LoginSupport.Middleware +import IHP.ControllerPrelude (getAppConfig) import Generated.Types import Web.Types import Web.Routes () +import Config (AnnotationLauncherEnabled (..)) -- Controllers import Web.Controller.Hubs () @@ -47,6 +49,13 @@ instance InitControllerContext WebApplication where setLayout defaultLayout initAuthentication @User +annotationLauncherScript :: (?context :: ControllerContext) => Html +annotationLauncherScript = + let AnnotationLauncherEnabled enabled = getAppConfig @AnnotationLauncherEnabled + in if enabled + then [hsx||] + else mempty + defaultLayout :: Layout defaultLayout inner = [hsx| @@ -59,6 +68,7 @@ defaultLayout inner = [hsx| + {annotationLauncherScript}