diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/Config.elm | 6 | ||||
| -rw-r--r-- | src/Main.elm | 72 | ||||
| -rw-r--r-- | src/Pages/Feed.elm | 57 | ||||
| -rw-r--r-- | src/Types.elm | 13 | ||||
| -rw-r--r-- | src/index.html | 22 |
5 files changed, 131 insertions, 39 deletions
diff --git a/src/Config.elm b/src/Config.elm index c3df2b0..ecd263b 100644 --- a/src/Config.elm +++ b/src/Config.elm @@ -9,6 +9,7 @@ baseUrl = type ApiResource = ApiPosts | ApiLikePost String + | ApiCompose makeApiUrl : ApiResource -> String @@ -16,8 +17,11 @@ makeApiUrl res = String.replace "{baseUrl}" baseUrl <| case res of ApiPosts -> - "{baseUrl}/posts" + "{baseUrl}/posts?_sort=createdAt&_order=desc" ApiLikePost postId -> "{baseUrl}/posts/{postId}" |> String.replace "{postId}" postId + + ApiCompose -> + "{baseUrl}/posts" diff --git a/src/Main.elm b/src/Main.elm index d359eaa..bd145e0 100644 --- a/src/Main.elm +++ b/src/Main.elm @@ -1,4 +1,4 @@ -module Main exposing (..) +port module Main exposing (..) import Browser exposing (Document) import Browser.Navigation exposing (Key) @@ -10,7 +10,7 @@ import Json.Encode import Pages.Feed exposing (feedView) import Task import Time -import Types exposing (Author, DisplayableError(..), Model, Msg(..), Post) +import Types exposing (Author, Model, Msg(..), Post) import Url exposing (Url) @@ -27,14 +27,21 @@ main = +-- PORTS + + +port showAlert : String -> Cmd msg + + + -- INIT init : () -> Url -> Key -> ( Model, Cmd Msg ) init _ _ _ = - ( { posts = [] - , displayError = DNoError + ( { posts = Nothing , now = Time.millisToPosix 0 + , composeInputValue = "" } , Cmd.batch [ getPosts, Task.perform SetNowPosix Time.now ] ) @@ -57,26 +64,51 @@ update msg model = ( model, getPosts ) GotPosts (Result.Ok posts) -> - ( { model | posts = posts }, Cmd.none ) + ( { model | posts = Just posts }, Cmd.none ) GotPosts (Result.Err httpErr) -> - ( { model | displayError = DHttpError httpErr } - , Cmd.none + ( model + , showAlert (Debug.toString httpErr) ) LikePost post -> ( model, likePost post ) LikedPost (Result.Ok post) -> - ( { model | posts = replaceMatchingPost post model.posts } + ( { model | posts = Just <| replaceMatchingPost post (Maybe.withDefault [] model.posts) } , Cmd.none ) LikedPost (Result.Err httpErr) -> - ( { model | displayError = DHttpError httpErr } + ( model + , showAlert (Debug.toString httpErr) + ) + + ComposeInputChanged value -> + ( { model | composeInputValue = value }, Cmd.none ) + + ComposePost -> + ( model + , if String.length model.composeInputValue > 0 then + composePost model + + else + Cmd.none + ) + + ComposedPost (Result.Ok post) -> + ( { model + | posts = Maybe.map (\posts -> post :: posts) model.posts + , composeInputValue = "" + } , Cmd.none ) + ComposedPost (Result.Err httpErr) -> + ( model + , showAlert (Debug.toString httpErr) + ) + replaceMatchingPost : Post -> List Post -> List Post replaceMatchingPost post posts = @@ -116,6 +148,28 @@ likePost post = } +composePost : Model -> Cmd Msg +composePost model = + Http.post + { url = makeApiUrl Config.ApiCompose + , expect = Http.expectJson ComposedPost postDecoder + , body = + Http.jsonBody + (Json.Encode.object + [ ( "content", Json.Encode.string model.composeInputValue ) + , ( "createdAt", Json.Encode.int <| Time.posixToMillis model.now // 1000 ) + , ( "likes", Json.Encode.int 0 ) + , ( "author" + , Json.Encode.object + [ ( "id", Json.Encode.string "logged-in-user-id" ) + , ( "name", Json.Encode.string "Logged in user" ) + ] + ) + ] + ) + } + + subscriptions : Model -> Sub Msg subscriptions _ = Time.every 5000 SetNowPosix diff --git a/src/Pages/Feed.elm b/src/Pages/Feed.elm index a848200..583c097 100644 --- a/src/Pages/Feed.elm +++ b/src/Pages/Feed.elm @@ -3,10 +3,10 @@ module Pages.Feed exposing (..) import Css exposing (..) import DateFormat.Relative exposing (relativeTime) import Html.Styled exposing (..) -import Html.Styled.Attributes exposing (css) -import Html.Styled.Events exposing (onClick) +import Html.Styled.Attributes exposing (css, placeholder, type_, value) +import Html.Styled.Events exposing (onClick, onInput, onSubmit) import Time exposing (now) -import Types exposing (DisplayableError(..), Model, Msg(..), Post) +import Types exposing (Model, Msg(..), Post) styles = @@ -19,6 +19,7 @@ styles = css [ padding2 (px 15) (px 20) , backgroundColor (hex "#eee") + , marginBottom (px 10) ] , postTitle = css @@ -28,25 +29,18 @@ styles = [ marginRight (px 5) , cursor pointer ] + , composeForm = + css + [ displayFlex + , flexFlow2 row wrap + ] + , composeInput = + css + [ flex (int 1) + ] } -derrorToHtml : DisplayableError -> Html Msg -derrorToHtml derror = - case derror of - DNoError -> - text "" - - DHttpError httpErr -> - text <| Debug.toString httpErr - - -derrorDiv : Model -> Html Msg -derrorDiv model = - div [] - [ derrorToHtml model.displayError ] - - postDiv : Time.Posix -> Post -> Html Msg postDiv now post = div [ styles.post ] @@ -64,7 +58,26 @@ postDiv now post = postsDiv : Model -> Html Msg postsDiv model = - div [] <| List.map (postDiv model.now) model.posts + case model.posts of + Just posts -> + div [] <| List.map (postDiv model.now) posts + + Nothing -> + div [] [ text "Loading posts..." ] + + +composeDiv : Model -> Html Msg +composeDiv model = + form [ styles.composeForm, onSubmit ComposePost ] + [ input + [ styles.composeInput + , placeholder "Type a new post..." + , onInput ComposeInputChanged + , value model.composeInputValue + ] + [] + , button [ type_ "submit" ] [ text "➡️" ] + ] headerSection : Model -> Html msg @@ -77,8 +90,8 @@ headerSection _ = mainSection : Model -> Html Msg mainSection model = main_ [] <| - [ derrorDiv model - , postsDiv model + [ postsDiv model + , composeDiv model ] diff --git a/src/Types.elm b/src/Types.elm index 02e1257..3736bbf 100644 --- a/src/Types.elm +++ b/src/Types.elm @@ -5,8 +5,8 @@ import Time type alias Model = - { posts : List Post - , displayError : DisplayableError + { posts : Maybe (List Post) + , composeInputValue : String , now : Time.Posix } @@ -20,11 +20,10 @@ type Msg | GotPosts (Result Http.Error (List Post)) | LikePost Post | LikedPost (Result Http.Error Post) - - -type DisplayableError - = DHttpError Http.Error - | DNoError + -- COMPOSE POST + | ComposeInputChanged String + | ComposePost + | ComposedPost (Result Http.Error Post) type alias Author = diff --git a/src/index.html b/src/index.html new file mode 100644 index 0000000..ccf508a --- /dev/null +++ b/src/index.html @@ -0,0 +1,22 @@ +<html> + +<head> + <meta charset="UTF-8"> + <title>Main</title> + <link rel="stylesheet" href="main.css"> + </link> + <script src="main.js"></script> +</head> + +<body> + <div id="app"></div> + <script> + var app = Elm.Main.init({ + node: document.getElementById("app") + }); + + app.ports.showAlert.subscribe((message) => window.alert(message)); + </script> +</body> + +</html>
\ No newline at end of file |
