fix(users/Profpatsch/whatcd-resolver): make getTorrent no js
Start of an effort to make the app work without javascript enabled (graceful degradation yay). We use a trick where buttons are nested into a form element, passing their value as input; this should be better than depending on `hx-vals`. If htmx is disabled, just redirect and reload the full page instead of sending back the snippet. Probably depends on the use-case of each snippet though. Change-Id: I6c73e624c4bd29b1cbd5492b2f84f48102edc68b Reviewed-on: https://cl.tvl.fyi/c/depot/+/12056 Tested-by: BuildkiteCI Reviewed-by: Profpatsch <mail@profpatsch.de>
This commit is contained in:
parent
a86dca8c78
commit
e682e5ce2a
1 changed files with 32 additions and 5 deletions
|
@ -135,7 +135,7 @@ htmlUi = do
|
||||||
Html.mkVal <$> (runTransaction $ getTorrentById dat)
|
Html.mkVal <$> (runTransaction $ getTorrentById dat)
|
||||||
),
|
),
|
||||||
( "snips/redacted/getTorrentFile",
|
( "snips/redacted/getTorrentFile",
|
||||||
respond.html $ \span -> do
|
respond.htmlOrReferer $ \span -> do
|
||||||
dat <- torrentIdMp span
|
dat <- torrentIdMp span
|
||||||
runTransaction $ do
|
runTransaction $ do
|
||||||
inserted <- redactedGetTorrentFileAndInsert dat
|
inserted <- redactedGetTorrentFileAndInsert dat
|
||||||
|
@ -292,6 +292,17 @@ htmlUi = do
|
||||||
/>
|
/>
|
||||||
|]
|
|]
|
||||||
|
|
||||||
|
-- | Reload the current page (via the Referer header) if the browser has Javascript disabled (and thus htmx does not work). This should make post requests work out of the box.
|
||||||
|
htmxOrReferer :: Wai.Request -> Wai.Response -> Wai.Response
|
||||||
|
htmxOrReferer req act = do
|
||||||
|
let fnd h = req & Wai.requestHeaders & List.find (\(hdr, _) -> hdr == h)
|
||||||
|
let referer = fnd "Referer"
|
||||||
|
if
|
||||||
|
| Just _ <- fnd "Hx-Request" -> act
|
||||||
|
| Nothing <- referer -> act
|
||||||
|
| Just (_, rfr) <- referer -> do
|
||||||
|
Wai.responseLBS seeOther303 [("Location", rfr)] ""
|
||||||
|
|
||||||
htmlPageChrome :: (ToHtml a) => Text -> a -> Html
|
htmlPageChrome :: (ToHtml a) => Text -> a -> Html
|
||||||
htmlPageChrome title body =
|
htmlPageChrome title body =
|
||||||
Html.docTypeHtml $
|
Html.docTypeHtml $
|
||||||
|
@ -350,6 +361,8 @@ data HandlerResponses m = HandlerResponses
|
||||||
html :: (Otel.Span -> m Html) -> m ResponseReceived,
|
html :: (Otel.Span -> m Html) -> m ResponseReceived,
|
||||||
-- | render html after parsing some query arguments
|
-- | render html after parsing some query arguments
|
||||||
htmlWithQueryArgs :: forall a. (Parse Query a -> (a -> Otel.Span -> m Html) -> m ResponseReceived),
|
htmlWithQueryArgs :: forall a. (Parse Query a -> (a -> Otel.Span -> m Html) -> m ResponseReceived),
|
||||||
|
-- | render html or reload the page via the Referer header if no htmx
|
||||||
|
htmlOrReferer :: (Otel.Span -> m Html) -> m ResponseReceived,
|
||||||
-- | render a plain wai response
|
-- | render a plain wai response
|
||||||
plain :: (m Wai.Response -> m ResponseReceived)
|
plain :: (m Wai.Response -> m ResponseReceived)
|
||||||
}
|
}
|
||||||
|
@ -363,7 +376,7 @@ runHandlers ::
|
||||||
m ResponseReceived
|
m ResponseReceived
|
||||||
runHandlers defaultHandler handlers req respond = withRunInIO $ \runInIO -> do
|
runHandlers defaultHandler handlers req respond = withRunInIO $ \runInIO -> do
|
||||||
let path = req & Wai.pathInfo & Text.intercalate "/"
|
let path = req & Wai.pathInfo & Text.intercalate "/"
|
||||||
let html act =
|
let html' resp act =
|
||||||
Otel.inSpan'
|
Otel.inSpan'
|
||||||
[fmt|Route /{path}|]
|
[fmt|Route /{path}|]
|
||||||
( Otel.defaultSpanArguments
|
( Otel.defaultSpanArguments
|
||||||
|
@ -376,8 +389,11 @@ runHandlers defaultHandler handlers req respond = withRunInIO $ \runInIO -> do
|
||||||
)
|
)
|
||||||
( \span -> do
|
( \span -> do
|
||||||
res <- act span <&> (\h -> T2 (label @"html" h) (label @"extraHeaders" []))
|
res <- act span <&> (\h -> T2 (label @"html" h) (label @"extraHeaders" []))
|
||||||
liftIO $ respond . Wai.responseLBS Http.ok200 ([("Content-Type", "text/html")] <> res.extraHeaders) . Html.renderHtml $ res.html
|
liftIO $ respond (resp res)
|
||||||
)
|
)
|
||||||
|
let htmlResp res = Wai.responseLBS Http.ok200 ([("Content-Type", "text/html")] <> res.extraHeaders) . Html.renderHtml $ res.html
|
||||||
|
let html = html' htmlResp
|
||||||
|
let htmlOrReferer = html' $ \res -> htmxOrReferer req (htmlResp res)
|
||||||
|
|
||||||
let handlerResponses =
|
let handlerResponses =
|
||||||
( HandlerResponses
|
( HandlerResponses
|
||||||
|
@ -401,7 +417,8 @@ runHandlers defaultHandler handlers req respond = withRunInIO $ \runInIO -> do
|
||||||
<h1>Error:</h1>
|
<h1>Error:</h1>
|
||||||
<pre>{err & prettyErrorTree}</pre>
|
<pre>{err & prettyErrorTree}</pre>
|
||||||
|]
|
|]
|
||||||
)
|
),
|
||||||
|
htmlOrReferer
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
let handler =
|
let handler =
|
||||||
|
@ -542,7 +559,17 @@ getBestTorrentsData artistFilter = do
|
||||||
mkBestTorrentsTable :: [TorrentData (Label "percentDone" Percentage)] -> Html
|
mkBestTorrentsTable :: [TorrentData (Label "percentDone" Percentage)] -> Html
|
||||||
mkBestTorrentsTable fresh = do
|
mkBestTorrentsTable fresh = do
|
||||||
let localTorrent b = case b.torrentStatus of
|
let localTorrent b = case b.torrentStatus of
|
||||||
NoTorrentFileYet -> [hsx|<button hx-post="snips/redacted/getTorrentFile" hx-swap="outerHTML" hx-vals={Enc.encToBytesUtf8 $ Enc.object [("torrent-id", Enc.int b.torrentId)]}>Upload Torrent</button>|]
|
NoTorrentFileYet ->
|
||||||
|
[hsx|
|
||||||
|
<form method="post">
|
||||||
|
<input type="hidden" name="torrent-id" value={b.torrentId & show} />
|
||||||
|
<button
|
||||||
|
formaction="snips/redacted/getTorrentFile"
|
||||||
|
hx-post="snips/redacted/getTorrentFile"
|
||||||
|
hx-swap="outerHTML"
|
||||||
|
hx-vals={Enc.encToBytesUtf8 $ Enc.object [("torrent-id", Enc.int b.torrentId)]}>Upload Torrent</button>
|
||||||
|
</form>
|
||||||
|
|]
|
||||||
InTransmission info -> [hsx|{info.transmissionInfo.percentDone.unPercentage}% done|]
|
InTransmission info -> [hsx|{info.transmissionInfo.percentDone.unPercentage}% done|]
|
||||||
NotInTransmissionYet -> [hsx|<button hx-post="snips/redacted/startTorrentFile" hx-swap="outerHTML" hx-vals={Enc.encToBytesUtf8 $ Enc.object [("torrent-id", Enc.int b.torrentId)]}>Start Torrent</button>|]
|
NotInTransmissionYet -> [hsx|<button hx-post="snips/redacted/startTorrentFile" hx-swap="outerHTML" hx-vals={Enc.encToBytesUtf8 $ Enc.object [("torrent-id", Enc.int b.torrentId)]}>Start Torrent</button>|]
|
||||||
let bestRows =
|
let bestRows =
|
||||||
|
|
Loading…
Reference in a new issue