111 lines
2.5 KiB
Elm
111 lines
2.5 KiB
Elm
module Route exposing (Route(..), fromUrl, href, replaceUrl)
|
|
|
|
import Article.Slug as Slug exposing (Slug)
|
|
import Browser.Navigation as Nav
|
|
import Html exposing (Attribute)
|
|
import Html.Attributes as Attr
|
|
import Profile exposing (Profile)
|
|
import Url exposing (Url)
|
|
import Url.Parser as Parser exposing ((</>), Parser, oneOf, s, string)
|
|
import Username exposing (Username)
|
|
|
|
|
|
|
|
-- ROUTING
|
|
|
|
|
|
type Route
|
|
= Home
|
|
| Root
|
|
| Login
|
|
| Logout
|
|
| Register
|
|
| Settings
|
|
| Article Slug
|
|
| Profile Username
|
|
| NewArticle
|
|
| EditArticle Slug
|
|
|
|
|
|
parser : Parser (Route -> a) a
|
|
parser =
|
|
oneOf
|
|
[ Parser.map Home Parser.top
|
|
, Parser.map Login (s "login")
|
|
, Parser.map Logout (s "logout")
|
|
, Parser.map Profile (s "profile" </> Username.urlParser)
|
|
|
|
-- 👉 TODO /settings → Settings
|
|
-- 👉 TODO /register → Register
|
|
-- 👉 TODO /article/[slug] → Article [slug]
|
|
-- 👉 TODO /editor/[slug] → EditArticle [slug]
|
|
-- 👉 TODO /editor → NewArticle
|
|
--
|
|
-- 💡 HINT: Article and EditArticle work similarly to how Profile works.
|
|
]
|
|
|
|
|
|
|
|
-- PUBLIC HELPERS
|
|
|
|
|
|
href : Route -> Attribute msg
|
|
href targetRoute =
|
|
Attr.href (routeToString targetRoute)
|
|
|
|
|
|
replaceUrl : Nav.Key -> Route -> Cmd msg
|
|
replaceUrl key route =
|
|
Nav.replaceUrl key (routeToString route)
|
|
|
|
|
|
fromUrl : Url -> Maybe Route
|
|
fromUrl url =
|
|
-- The RealWorld spec treats the fragment like a path.
|
|
-- This makes it *literally* the path, so we can proceed
|
|
-- with parsing as if it had been a normal path all along.
|
|
{ url | path = Maybe.withDefault "" url.fragment, fragment = Nothing }
|
|
|> Parser.parse parser
|
|
|
|
|
|
|
|
-- INTERNAL
|
|
|
|
|
|
routeToString : Route -> String
|
|
routeToString page =
|
|
let
|
|
pieces =
|
|
case page of
|
|
Home ->
|
|
[]
|
|
|
|
Root ->
|
|
[]
|
|
|
|
Login ->
|
|
[ "login" ]
|
|
|
|
Logout ->
|
|
[ "logout" ]
|
|
|
|
Register ->
|
|
[ "register" ]
|
|
|
|
Settings ->
|
|
[ "settings" ]
|
|
|
|
Article slug ->
|
|
[ "article", Slug.toString slug ]
|
|
|
|
Profile username ->
|
|
[ "profile", Username.toString username ]
|
|
|
|
NewArticle ->
|
|
[ "editor" ]
|
|
|
|
EditArticle slug ->
|
|
[ "editor", Slug.toString slug ]
|
|
in
|
|
"#/" ++ String.join "/" pieces
|