feat: add SSE client JS for live recipe reload on detail and index pages
Build and Deploy / build-and-deploy (push) Successful in 1m39s
Build and Deploy / build-and-deploy (push) Successful in 1m39s
This commit is contained in:
+46
-1
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user