feat: add SSE client JS for live recipe reload on detail and index pages
Build and Deploy / build-and-deploy (push) Successful in 1m39s

This commit is contained in:
2026-05-20 10:23:42 -04:00
parent f5c693a2b5
commit 71cef21daf
+46 -1
View File
@@ -329,6 +329,39 @@ searchJs =
, "})();"
]
-- ---------------------------------------------------------------------------
-- SSE live-reload scripts
-- ---------------------------------------------------------------------------
-- | Inline JavaScript for SSE live-reload on the recipe detail page.
sseRecipeJs :: Text
sseRecipeJs =
T.unlines
[ "(function(){"
, "'use strict';"
, "if (!window.EventSource) return;"
, "var el = document.getElementById('roux-current-recipe');"
, "if (!el) return;"
, "var currentRecipe = el.textContent;"
, "var es = new EventSource('/events');"
, "es.addEventListener('recipe-changed', function(e) {"
, " if (e.data === currentRecipe) location.reload();"
, "});"
, "})();"
]
-- | Inline JavaScript for SSE live-reload on the index page.
sseIndexJs :: Text
sseIndexJs =
T.unlines
[ "(function(){"
, "'use strict';"
, "if (!window.EventSource) return;"
, "var es = new EventSource('/events');"
, "es.addEventListener('recipe-changed', function() { location.reload(); });"
, "})();"
]
-- | Render the recipe index page -- shell with embedded JSON + JS rendering.
indexPage :: SortMode -> [Idx.RecipeInfo] -> ByteString
indexPage _mode recipes =
@@ -356,6 +389,8 @@ indexPage _mode recipes =
H.toHtml (decodeUtf8 (LB.toStrict (Fleece.encode (Fleece.encoder (FC.list Idx.recipeSearchEntrySchema)) (Prelude.map Idx.toSearchEntry (filterBad recipes)))))
-- Inline JS
H.script ! A.type_ "text/javascript" $ H.preEscapedText searchJs
-- Inline JS for SSE live-reload
H.script ! A.type_ "text/javascript" $ H.preEscapedText sseIndexJs
where
filterOk = filter (isRight . Idx.riRecipe)
filterBad = filter (isLeft . Idx.riRecipe)
@@ -368,9 +403,19 @@ recipePage info =
H.nav $ H.ul $ H.li $ H.a ! A.href "/" $ "← Back"
H.h2 "Parse Error"
H.p $ H.toHtml (Idx.riTitle info <> ": " <> T.pack err)
hiddenRecipeSpan info
sseScript
Right recipe ->
page (titleText recipe) $
page (titleText recipe) $ do
renderRecipe recipe
hiddenRecipeSpan info
sseScript
where
hiddenRecipeSpan rInfo =
H.span ! A.id "roux-current-recipe" ! A.style "display: none;" $
H.toHtml (T.pack (Idx.riFilename rInfo))
sseScript =
H.script ! A.type_ "text/javascript" $ H.preEscapedText sseRecipeJs
-- | Render the body of a recipe page (no page shell).
renderRecipe :: Recipe -> Html