From 516006f352d2554fe28b406c6c06cf88b16d2db5 Mon Sep 17 00:00:00 2001 From: Artus Date: Fri, 15 Nov 2019 16:05:17 +0100 Subject: [PATCH] adds type variable for Api.Response value field --- src/Api.elm | 89 ++++++++++++++++++++++++++++++---------------- src/Page/Chest.elm | 66 ++++++++++++++++------------------ 2 files changed, 90 insertions(+), 65 deletions(-) diff --git a/src/Api.elm b/src/Api.elm index de0f383..17a2985 100644 --- a/src/Api.elm +++ b/src/Api.elm @@ -8,6 +8,7 @@ module Api exposing , Msg(..) , Player , RequestData(..) + , ToChest(..) , Update(..) , Wealth , blankPlayer @@ -31,13 +32,8 @@ type alias HttpResult a = -- Format of the server's response -type Value - = Text String - | Items Loot - - -type alias Response = - { value : Maybe Value +type alias Response a = + { value : Maybe a , notification : Maybe String , updates : Maybe (List Update) , errors : Maybe String @@ -53,7 +49,7 @@ type Update type Msg - = GotActionResult (HttpResult Response) + = GotActionResult (HttpResult (Response ())) @@ -186,25 +182,47 @@ lootDecoder = D.list itemDecoder -fetchLoot : String -> (Result Http.Error Loot -> msg) -> Cmd msg -fetchLoot url toMsg = +type ToChest + = OfPlayer Int + | OfGroup + | OfShop + + +fetchLoot : (ToChest -> Result Http.Error Loot -> msg) -> ToChest -> Cmd msg +fetchLoot toMsg dest = + let + url = + case dest of + OfPlayer id -> + "http://localhost:8088/api/players/" ++ String.fromInt id ++ "/loot" + + OfShop -> + "http://localhost:8088/api/items" + + OfGroup -> + "http://localhost:8088/api/players/0/loot" + in Http.get { url = url - , expect = Http.expectJson toMsg (valueDecoder lootDecoder) + , expect = Http.expectJson (toMsg dest) (valueDecoder lootDecoder) } + +-- Retrieves items from a list of names + + checkList : (Loot -> Maybe String -> msg) -> List String -> Cmd msg checkList toMsg itemList = let - parseResponse : Result Http.Error Response -> msg + parseResponse : Result Http.Error (Response Loot) -> msg parseResponse response = case response of Ok r -> let items = case r.value of - Just (Items loot) -> + Just loot -> loot _ -> @@ -237,9 +255,13 @@ checkList toMsg itemList = --- CLAIMS --- API Response +-- API RESPONSE -- +-- Loot-a-lot API use a flat response format with four fields : +-- * value +-- * notification +-- * updates +-- * errors valueDecoder : Decoder a -> Decoder a @@ -266,10 +288,13 @@ updatesDecoder = --- TODO: add a valueDecoder to get a proper value out of Json +-- The 'value' field is actually a union-type +-- with heterogeneous data. We need to provide a +-- decoder to extract the value we expect, or ignore +-- it with (). -apiResponseDecoder : Decoder Value -> Decoder Response +apiResponseDecoder : Decoder a -> Decoder (Response a) apiResponseDecoder toValue = D.map4 Response (D.maybe (field "value" toValue)) @@ -278,18 +303,6 @@ apiResponseDecoder toValue = (D.maybe (field "errors" string)) -undoLastAction id = - Http.request - { url = "http://localhost:8088/api/players/" ++ String.fromInt id ++ "/events/last" - , method = "DELETE" - , headers = [] - , body = Http.emptyBody - , expect = Http.expectJson GotActionResult (apiResponseDecoder string) - , timeout = Nothing - , tracker = Nothing - } - - {- ACTIONS @@ -370,12 +383,28 @@ confirmAction id data = , headers = [] , url = endpoint , body = Http.jsonBody <| buildPayload data - , expect = Http.expectJson GotActionResult (apiResponseDecoder string) + , expect = Http.expectJson GotActionResult (apiResponseDecoder <| D.succeed ()) , timeout = Nothing , tracker = Nothing } +undoLastAction id = + Http.request + { url = "http://localhost:8088/api/players/" ++ String.fromInt id ++ "/events/last" + , method = "DELETE" + , headers = [] + , body = Http.emptyBody + , expect = Http.expectJson GotActionResult (apiResponseDecoder <| D.succeed ()) + , timeout = Nothing + , tracker = Nothing + } + + + +-- UTILS + + printError : Http.Error -> String printError error = case error of diff --git a/src/Page/Chest.elm b/src/Page/Chest.elm index 8987e47..a1d6440 100644 --- a/src/Page/Chest.elm +++ b/src/Page/Chest.elm @@ -87,9 +87,9 @@ init (Player navKey playerId) = , Cmd.batch [ Api.fetchPlayer GotPlayer playerId , Api.fetchClaims GotClaims playerId - , fetchLoot (OfPlayer playerId) - , fetchLoot OfGroup - , fetchLoot OfShop + , Api.fetchLoot GotLoot (Api.OfPlayer playerId) + , Api.fetchLoot GotLoot Api.OfGroup + , Api.fetchLoot GotLoot Api.OfShop ] ) @@ -173,13 +173,17 @@ viewHeaderBar title model = [ renderIcon { icon = "fab fa-d-and-d", size = "medium", ratio = "2x" } , span [ class "title is-4", style "padding-left" "0.4em" ] [ text title ] ] - , a [ class "navbar-burger is-active" ] + , a + [ class "navbar-burger" + , classList [ ( "is-active", model.state.menuOpen ) ] + , onClick SwitchMenuOpen + ] [ span [ attribute "aria-hidden" "true" ] [] , span [ attribute "aria-hidden" "true" ] [] , span [ attribute "aria-hidden" "true" ] [] ] ] - , div [ class "navbar-menu is-active" ] + , div [ class "navbar-menu", classList [ ( "is-active", model.state.menuOpen ) ] ] [ div [ class "navbar-end" ] [ a [ class "navbar-item", href "/marchand" ] [ renderIcon { icon = "fas fa-store-alt", ratio = "1x", size = "medium" } @@ -344,8 +348,6 @@ view model = ] ) ] - , hr [] [] - , section [ class "container" ] [ viewDebugSection model ] ] @@ -733,10 +735,11 @@ viewControls mode content = type Msg = ApiMsg Api.Msg | ClearNotification + | SwitchMenuOpen | SetContent ChestContent | SetSelection (Maybe Selection) | SwitchSelectionState Int - | GotLoot ToChest (HttpResult Loot) + | GotLoot Api.ToChest (HttpResult Loot) | GotClaims (HttpResult Claims) | GotPlayer (HttpResult Api.Player) | SearchTextChanged String @@ -763,6 +766,15 @@ insensitiveContains substring string = update : Msg -> Model -> ( Model, Cmd Msg ) update msg model = case msg of + SwitchMenuOpen -> + let + state = + model.state + in + ( { model | state = { state | menuOpen = not model.state.menuOpen } } + , Cmd.none + ) + NewItemsFromList newLoot maybeErrors -> let state = @@ -1031,13 +1043,13 @@ update msg model = model.state in case dest of - OfPlayer _ -> + Api.OfPlayer _ -> { model | state = { state | playerLoot = loot } } - OfGroup -> + Api.OfGroup -> { model | state = { state | groupLoot = loot } } - OfShop -> + Api.OfShop -> { model | state = { state | merchantLoot = loot } } , Cmd.none ) @@ -1067,10 +1079,17 @@ setError error model = let state = model.state + + newError = + if error == "" then + Nothing + + else + Just error in { model | state = - { state | error = Just error } + { state | error = newError } } @@ -1124,29 +1143,6 @@ applyUpdate u model = { model | claims = List.filter (\c -> c.id /= claim.id) model.claims } -type ToChest - = OfPlayer Int - | OfGroup - | OfShop - - -fetchLoot : ToChest -> Cmd Msg -fetchLoot dest = - let - url = - case dest of - OfPlayer id -> - "http://localhost:8088/api/players/" ++ String.fromInt id ++ "/loot" - - OfShop -> - "http://localhost:8088/api/items" - - OfGroup -> - "http://localhost:8088/api/players/0/loot" - in - Api.fetchLoot url (GotLoot dest) - - -- Selection -- Get list of selected items