Compare commits

...

6 Commits

Author SHA1 Message Date
210667ced6 makes filter search case insensitive 2019-12-18 15:45:06 +01:00
90bad7e481 adds filter text input, add player for admin 2019-12-18 15:27:13 +01:00
1636248686 adds conflicts information on claims 2019-12-17 16:11:16 +01:00
0241175b03 Merge branch 'try_to_scale' of elm/lootalot-client into master
Refactors to improve scalability
2019-12-15 15:30:11 +01:00
18c39eac1d updates for production env 2019-12-15 14:30:28 +01:00
ef3dd1f2ac updates style 2019-12-14 14:05:47 +01:00
13 changed files with 362 additions and 168 deletions

View File

@@ -1,9 +1,11 @@
@charset "UTF-8"; @charset "UTF-8";
.navbar.is-spaced a.navbar-item.is-active { /*
border-bottom: 1px solid #2e3440; .navbar.is-spaced a.navbar-item.is-active {
border-radius: 0; border-bottom: 1px solid $dark;
border-radius: 0;
} }
/*/
.hero.is-dark.is-bold { .hero.is-dark.is-bold {
background-image: linear-gradient(280deg, #191c22 0%, #2e3440 71%, #3b4252 100%) !important; background-image: linear-gradient(280deg, #191c22 0%, #2e3440 71%, #3b4252 100%) !important;
} }

View File

@@ -30,11 +30,14 @@ $notification-padding: 0.8rem 2.5rem 0.8rem 1rem;
//$box-radius: 0 0 2rem 2rem; //$box-radius: 0 0 2rem 2rem;
.navbar.is-spaced a.navbar-item.is-active { /*
.navbar.is-spaced a.navbar-item.is-active {
border-bottom: 1px solid $dark; border-bottom: 1px solid $dark;
border-radius: 0; border-radius: 0;
} }
/*/
.hero.is-dark.is-bold { .hero.is-dark.is-bold {
background-image: linear-gradient(280deg, darken($dark, 10) 0%, $dark 71%, $dark-bis 100%) !important; background-image: linear-gradient(280deg, darken($dark, 10) 0%, $dark 71%, $dark-bis 100%) !important;
} }

View File

@@ -8,6 +8,7 @@ module Api exposing
, RequestData(..) , RequestData(..)
, ToChest(..) , ToChest(..)
, Update(..) , Update(..)
, adminAddPlayer
, checkList , checkList
, confirmAction , confirmAction
, fetchLoot , fetchLoot
@@ -92,10 +93,6 @@ type alias Loot =
List Item List Item
-- Location of a loot
lootDecoder : Decoder Loot lootDecoder : Decoder Loot
lootDecoder = lootDecoder =
D.list itemDecoder D.list itemDecoder
@@ -107,23 +104,23 @@ type ToChest
| OfShop | OfShop
fetchLoot : (ToChest -> Result Http.Error Loot -> msg) -> ToChest -> Cmd msg fetchLoot : (Result Http.Error Loot -> msg) -> ToChest -> Cmd msg
fetchLoot toMsg dest = fetchLoot toMsg dest =
let let
url = url =
case dest of case dest of
OfPlayer id -> OfPlayer id ->
"http://localhost:8088/api/players/" ++ String.fromInt id ++ "/loot" "api/players/" ++ String.fromInt id ++ "/loot"
OfShop -> OfShop ->
"http://localhost:8088/api/shop" "api/shop"
OfGroup -> OfGroup ->
"http://localhost:8088/api/players/0/loot" "api/players/0/loot"
in in
Http.get Http.get
{ url = url { url = url
, expect = Http.expectJson (toMsg dest) (valueDecoder lootDecoder) , expect = Http.expectJson toMsg (valueDecoder lootDecoder)
} }
@@ -139,14 +136,16 @@ type alias Claim =
{ id : Int { id : Int
, player_id : Int , player_id : Int
, loot_id : Int , loot_id : Int
, conflicts : Bool
} }
claimDecoder = claimDecoder =
D.map3 Claim D.map4 Claim
(D.field "id" int) (D.field "id" int)
(D.field "player_id" int) (D.field "player_id" int)
(D.field "loot_id" int) (D.field "loot_id" int)
(D.succeed False)
@@ -187,7 +186,7 @@ checkList toMsg itemList =
toMsg [] <| Just (printError e) toMsg [] <| Just (printError e)
in in
Http.post Http.post
{ url = "http://localhost:8088/api/items" { url = "api/items"
, body = , body =
E.list (\t -> E.string t) itemList E.list (\t -> E.string t) itemList
|> Http.jsonBody |> Http.jsonBody
@@ -244,6 +243,10 @@ apiResponseDecoder toValue =
(D.maybe (field "errors" string)) (D.maybe (field "errors" string))
emptyResponse =
apiResponseDecoder (D.succeed ())
{- ACTIONS {- ACTIONS
@@ -330,27 +333,27 @@ confirmAction id data =
( endpoint, method ) = ( endpoint, method ) =
case data of case data of
AddPayload _ _ -> AddPayload _ _ ->
( "http://localhost:8088/api/players/" ++ id ++ "/loot" ( "api/players/" ++ id ++ "/loot"
, "POST" , "POST"
) )
BuyPayload _ _ _ -> BuyPayload _ _ _ ->
( "http://localhost:8088/api/players/" ++ id ++ "/loot" ( "api/players/" ++ id ++ "/loot"
, "PUT" , "PUT"
) )
SellPayload _ _ _ _ -> SellPayload _ _ _ _ ->
( "http://localhost:8088/api/players/" ++ id ++ "/loot" ( "api/players/" ++ id ++ "/loot"
, "DELETE" , "DELETE"
) )
GrabPayload _ -> GrabPayload _ ->
( "http://localhost:8088/api/players/" ++ id ++ "/claims" ( "api/players/" ++ id ++ "/claims"
, "POST" , "POST"
) )
WealthPayload _ -> WealthPayload _ ->
( "http://localhost:8088/api/players/" ++ id ++ "/wealth" ( "api/players/" ++ id ++ "/wealth"
, "PUT" , "PUT"
) )
in in
@@ -367,7 +370,7 @@ confirmAction id data =
undoLastAction id = undoLastAction id =
Http.request Http.request
{ url = "http://localhost:8088/api/players/" ++ String.fromInt id ++ "/events/last" { url = "api/players/" ++ String.fromInt id ++ "/events/last"
, method = "DELETE" , method = "DELETE"
, headers = [] , headers = []
, body = Http.emptyBody , body = Http.emptyBody
@@ -398,11 +401,11 @@ replaceShopItems toMsg loot =
toMsg Nothing toMsg Nothing
in in
Http.request Http.request
{ url = "http://localhost:8088/api/shop" { url = "api/shop"
, method = "POST" , method = "POST"
, headers = [] , headers = []
, body = Http.jsonBody data , body = Http.jsonBody data
, expect = Http.expectJson gotResponse (apiResponseDecoder <| D.succeed ()) , expect = Http.expectJson gotResponse emptyResponse
, timeout = Nothing , timeout = Nothing
, tracker = Nothing , tracker = Nothing
} }
@@ -412,7 +415,7 @@ send : { method : String, path : String, decoder : Decoder a } -> Task Http.Erro
send { method, path, decoder } = send { method, path, decoder } =
Http.task Http.task
{ method = method { method = method
, url = "http://localhost:8088/" ++ path , url = path
, headers = [] , headers = []
, body = Http.emptyBody , body = Http.emptyBody
, resolver = Http.stringResolver <| handleJsonResponse decoder , resolver = Http.stringResolver <| handleJsonResponse decoder
@@ -432,20 +435,85 @@ getLoot id =
} }
getClaims id =
let
path =
if id == 0 then
"api/claims"
else -- Updates the conflicts field on every claims
"api/players/" ++ String.fromInt id ++ "/claims"
in
groupByLoot : List Claims -> Claims -> List Claims
groupByLoot acc claims =
case claims of
last :: [] ->
groupByLoot ([ last ] :: acc) []
first :: rest ->
let
( newGroup, left ) =
List.partition (\c -> c.loot_id == first.loot_id) rest
in
groupByLoot ((first :: newGroup) :: acc) left
[] ->
acc
updateConflicts : Claims -> Claims
updateConflicts claims =
groupByLoot [] claims
|> List.concatMap
(\group ->
let
_ =
Debug.log "updating group" group
in
case group of
[] ->
[]
[ c ] ->
[ { c | conflicts = False } ]
xs ->
List.map (\c -> { c | conflicts = True }) xs
)
parseClaims : Int -> Claims -> Task x Claims
parseClaims id claims =
-- Filter claims relevant to player
Task.succeed <|
List.filter (\claim -> id == 0 || claim.player_id == id) <|
updateConflicts claims
getClaims : Int -> Task Http.Error Claims
getClaims id =
send send
{ method = "GET" { method = "GET"
, path = path , path = "api/claims"
, decoder = valueDecoder (D.list claimDecoder) , decoder = valueDecoder (D.list claimDecoder)
} }
|> Task.andThen (parseClaims id)
-- ADMIN
--
adminAddPlayer : { d | name : String, wealth : Float } -> Cmd Msg
adminAddPlayer data =
let
json =
E.object
[ ( "name", E.string data.name )
, ( "wealth", E.float data.wealth )
]
in
Http.post
{ url = "api/players/"
, body = Http.jsonBody json
, expect = Http.expectJson GotActionResult emptyResponse
}

View File

@@ -49,7 +49,7 @@ blankPlayer =
get : (Result Http.Error Player -> msg) -> Int -> Cmd msg get : (Result Http.Error Player -> msg) -> Int -> Cmd msg
get toMsg id = get toMsg id =
Http.get Http.get
{ url = "http://localhost:8088/api/players/" ++ String.fromInt id ++ "/" { url = "api/players/" ++ String.fromInt id ++ "/"
, expect = Http.expectJson toMsg (valueDecoder playerDecoder) , expect = Http.expectJson toMsg (valueDecoder playerDecoder)
} }
@@ -64,11 +64,14 @@ list toMsg =
toMsg players toMsg players
Err e -> Err e ->
Debug.log ("Player's list fetch error : " ++ Debug.toString e) <| let
toMsg [] _ =
Debug.log "Player's list fetch error" (Debug.toString e)
in
toMsg []
in in
Http.get Http.get
{ url = "http://localhost:8088/api/players/" { url = "api/players/"
, expect = Http.expectJson parseResponse (valueDecoder <| D.list playerDecoder) , expect = Http.expectJson parseResponse (valueDecoder <| D.list playerDecoder)
} }

View File

@@ -88,9 +88,23 @@ levelItem =
-- INPUTS
--
inputField : String -> (String -> msg) -> Html msg
inputField val toMsg =
input [ class "input", value val, onInput toMsg ] []
-- COLORS -- COLORS
-- --
isInfo = isInfo =
class "is-info" class "is-info"
isError =
class "is-error"

View File

@@ -29,10 +29,10 @@ type alias RowRenderer msg =
type Chest type Chest
= New NewFromInventory.Model = New NewFromInventory.Model
| View (Item -> Html Never) | View FilterText (Item -> Html Never)
| Buy Selection.Model | Buy FilterText Selection.Model
| Sell Selection.Model | Sell FilterText Selection.Model
| Claim Selection.Model | Claim FilterText Selection.Model
type IntoMode type IntoMode
@@ -44,6 +44,10 @@ type IntoMode
| IntoClaim Claims | IntoClaim Claims
type alias FilterText =
String
{- {-
@@ -66,7 +70,7 @@ type IntoMode
init = init =
View Table.name View "" Table.name
intoMode : IntoMode -> Msg intoMode : IntoMode -> Msg
@@ -100,31 +104,51 @@ claim initialClaims =
showWith : Table.ItemRenderer Item Never -> Chest showWith : Table.ItemRenderer Item Never -> Chest
showWith renderItem = showWith renderItem =
View <| Table.renderRowLevel renderItem (\_ -> []) View "" <| Table.renderRowLevel renderItem (\_ -> [])
view : Chest -> Loot -> Html Msg view : Chest -> Loot -> Html Msg
view model loot = view model loot =
let
filterLoot txt ls =
List.filter (\i -> String.contains (String.toLower txt) (String.toLower i.name)) ls
in
case model of case model of
View renderItem -> View filterText renderItem ->
Table.view renderItem loot div []
|> Html.map GotViewMsg [ viewFilterInput filterText
, Table.view renderItem (filterLoot filterText loot)
|> Html.map GotViewMsg
]
Buy subModel -> Buy filterText subModel ->
Selection.view subModel loot div []
|> Html.map GotSelectionMsg [ viewFilterInput filterText
, Selection.view subModel (filterLoot filterText loot)
|> Html.map GotSelectionMsg
]
Sell subModel -> Sell filterText subModel ->
Selection.view subModel loot div []
|> Html.map GotSelectionMsg [ viewFilterInput filterText
, Selection.view subModel (filterLoot filterText loot)
|> Html.map GotSelectionMsg
]
New subModel -> New subModel ->
NewFromInventory.view subModel NewFromInventory.view subModel
|> Html.map GotNewMsg |> Html.map GotNewMsg
Claim subModel -> Claim filterText subModel ->
Selection.view subModel loot div []
|> Html.map GotSelectionMsg [ viewFilterInput filterText
, Selection.view subModel (filterLoot filterText loot)
|> Html.map GotSelectionMsg
]
viewFilterInput filterText =
B.inputField filterText FilterTextChanged
type Msg type Msg
@@ -132,11 +156,15 @@ type Msg
| GotSelectionMsg Selection.Msg | GotSelectionMsg Selection.Msg
| GotViewMsg Never | GotViewMsg Never
| IntoMode IntoMode | IntoMode IntoMode
| FilterTextChanged String
update : Msg -> Chest -> ( Chest, Cmd Msg ) update : Msg -> Chest -> ( Chest, Cmd Msg )
update msg model = update msg model =
case ( msg, model ) of case ( msg, model ) of
( FilterTextChanged newText, m ) ->
( updateFilterText newText m, Cmd.none )
( GotNewMsg subMsg, New subModel ) -> ( GotNewMsg subMsg, New subModel ) ->
NewFromInventory.update subMsg subModel NewFromInventory.update subMsg subModel
|> updateChest GotNewMsg New |> updateChest GotNewMsg New
@@ -144,17 +172,17 @@ update msg model =
( GotNewMsg subMsg, _ ) -> ( GotNewMsg subMsg, _ ) ->
( model, Cmd.none ) ( model, Cmd.none )
( GotSelectionMsg subMsg, Buy subModel ) -> ( GotSelectionMsg subMsg, Buy f subModel ) ->
Selection.update subMsg subModel Selection.update subMsg subModel
|> updateChest GotSelectionMsg Buy |> updateChest GotSelectionMsg (Buy f)
( GotSelectionMsg subMsg, Sell subModel ) -> ( GotSelectionMsg subMsg, Sell f subModel ) ->
Selection.update subMsg subModel Selection.update subMsg subModel
|> updateChest GotSelectionMsg Sell |> updateChest GotSelectionMsg (Sell f)
( GotSelectionMsg subMsg, Claim subModel ) -> ( GotSelectionMsg subMsg, Claim f subModel ) ->
Selection.update subMsg subModel Selection.update subMsg subModel
|> updateChest GotSelectionMsg Claim |> updateChest GotSelectionMsg (Claim f)
( GotSelectionMsg subMsg, _ ) -> ( GotSelectionMsg subMsg, _ ) ->
( model, Cmd.none ) ( model, Cmd.none )
@@ -162,43 +190,59 @@ update msg model =
( IntoMode newMode, _ ) -> ( IntoMode newMode, _ ) ->
case newMode of case newMode of
IntoView -> IntoView ->
( View Table.name, Cmd.none ) ( View "" Table.name, Cmd.none )
IntoViewWithClaims claims -> IntoViewWithClaims claims ->
let let
isClaimed item = isClaimed item =
List.any (\claim_ -> claim_.loot_id == item.id) claims case List.filter (\c -> c.loot_id == item.id) claims of
[ c ] ->
Just c
[] ->
Nothing
_ ->
Debug.log "Warning ! Duplicated claim found" Nothing
renderItem item = renderItem item =
[ p [ B.levelItem ] [ text item.name ] [ p [ B.levelItem ] [ text item.name ]
, if isClaimed item then , case isClaimed item of
B.tag [ B.levelItem, B.isInfo ] Just c ->
[ B.icon B.tag
{ icon = "fas fa-praying-hands" [ B.levelItem
, size = Just "is-small" , if c.conflicts then
, ratio = Just "fa-1x" B.isError
}
, text "time left..."
]
else else
text "" B.isInfo
]
[ B.icon
{ icon = "fas fa-praying-hands"
, size = Just "is-small"
, ratio = Just "fa-1x"
}
, p [] [ text "en attente..." ]
]
Nothing ->
text ""
] ]
in in
( View <| Table.renderRowLevel renderItem (\_ -> []), Cmd.none ) ( View "" <| Table.renderRowLevel renderItem (\_ -> []), Cmd.none )
IntoBuy -> IntoBuy ->
( Buy <| Selection.init Nothing (Just .base_price), Cmd.none ) ( Buy "" <| Selection.init Nothing (Just .base_price), Cmd.none )
IntoSell -> IntoSell ->
( Sell <| Selection.init Nothing (Just (\i -> i.base_price // 2)), Cmd.none ) ( Sell "" <| Selection.init Nothing (Just (\i -> i.base_price // 2)), Cmd.none )
IntoClaim claims -> IntoClaim claims ->
let let
initialSelection = initialSelection =
List.map .loot_id claims List.map .loot_id claims
in in
( Claim <| Selection.init (Just initialSelection) Nothing, Cmd.none ) ( Claim "" <| Selection.init (Just initialSelection) Nothing, Cmd.none )
IntoAdd -> IntoAdd ->
( New NewFromInventory.init, Cmd.none ) ( New NewFromInventory.init, Cmd.none )
@@ -213,6 +257,24 @@ updateChest toMsg toChest ( model, cmd ) =
) )
updateFilterText txt model =
case model of
New _ ->
model
View _ a ->
View txt a
Buy _ a ->
Buy txt a
Sell _ a ->
Sell txt a
Claim _ a ->
Claim txt a
-- Helpers -- Helpers
-- --
@@ -223,7 +285,7 @@ updateChest toMsg toChest ( model, cmd ) =
confirmBuy : Int -> Chest -> Loot -> Cmd Api.Msg confirmBuy : Int -> Chest -> Loot -> Cmd Api.Msg
confirmBuy playerId model loot = confirmBuy playerId model loot =
case model of case model of
Buy chest -> Buy _ chest ->
let let
items = items =
Selection.selected chest loot Selection.selected chest loot
@@ -245,7 +307,7 @@ confirmBuy playerId model loot =
confirmSell : Int -> Chest -> Loot -> List Int -> Cmd Api.Msg confirmSell : Int -> Chest -> Loot -> List Int -> Cmd Api.Msg
confirmSell playerId model loot players = confirmSell playerId model loot players =
case model of case model of
Sell chest -> Sell _ chest ->
let let
items = items =
Selection.selected chest loot Selection.selected chest loot
@@ -286,7 +348,7 @@ confirmAdd playerId sourceName model =
confirmGrab : Int -> Loot -> Chest -> Cmd Api.Msg confirmGrab : Int -> Loot -> Chest -> Cmd Api.Msg
confirmGrab playerId loot model = confirmGrab playerId loot model =
case model of case model of
Claim chest -> Claim _ chest ->
let let
items = items =
Selection.selected chest loot Selection.selected chest loot

View File

@@ -60,7 +60,11 @@ setPage page model =
init : () -> Url.Url -> Nav.Key -> ( Model, Cmd Msg ) init : () -> Url.Url -> Nav.Key -> ( Model, Cmd Msg )
init _ _ key = init _ url key =
let
_ =
Debug.log "init with url" (Debug.toString url)
in
( { navbar = initNavbar key ( { navbar = initNavbar key
, page = Page.Loading , page = Page.Loading
} }
@@ -165,6 +169,10 @@ update msg model =
( LinkClicked urlRequest, _ ) -> ( LinkClicked urlRequest, _ ) ->
case urlRequest of case urlRequest of
Browser.Internal url -> Browser.Internal url ->
let
_ =
Debug.log "internal url request" (Debug.toString url)
in
( model, Nav.pushUrl model.navbar.navKey (Url.toString url) ) ( model, Nav.pushUrl model.navbar.navKey (Url.toString url) )
Browser.External href -> Browser.External href ->

View File

@@ -10,7 +10,7 @@ import Page.Dashboard as Home
import Page.GroupChest as GroupChest import Page.GroupChest as GroupChest
import Page.Shop as Shop import Page.Shop as Shop
import Process import Process
import Route import Route exposing (toHref)
import Session exposing (Session) import Session exposing (Session)
import Task import Task
import Wealth import Wealth
@@ -216,19 +216,19 @@ renderLevel left right =
navLink icon route page = navLink icon route page =
let let
( link, url ) = linkText =
case route of case route of
Route.Merchant -> Route.Merchant ->
( "Marchand", "/marchand" ) "Marchand"
Route.GroupChest -> Route.GroupChest ->
( "Coffre de groupe", "/groupe" ) "Coffre de groupe"
Route.Home -> Route.Home ->
( "Accueil", "/" ) "Accueil"
Route.About -> Route.About ->
( "About", "/" ) "About"
isActive = isActive =
case ( route, page ) of case ( route, page ) of
@@ -247,9 +247,9 @@ navLink icon route page =
_ -> _ ->
False False
in in
a [ class "navbar-item", classList [ ( "is-active", isActive ) ], href url ] a [ class "navbar-item", classList [ ( "is-active", isActive ) ], href (toHref route) ]
[ B.icon { icon = icon, ratio = Just "fa-1x", size = Just "is-medium" } [ B.icon { icon = icon, ratio = Just "fa-1x", size = Just "is-medium" }
, span [] [ text link ] , span [] [ text linkText ]
] ]

View File

@@ -109,7 +109,7 @@ view model =
in in
( Html.map PlayerViewer <| ( Html.map PlayerViewer <|
case config.chest of case config.chest of
Chest.View _ -> Chest.View _ _ ->
case data.player.id of case data.player.id of
0 -> 0 ->
B.buttons B.buttons
@@ -135,7 +135,7 @@ view model =
, color = "is-primary" , color = "is-primary"
} }
Chest.Sell selection -> Chest.Sell _ selection ->
let let
sellText = sellText =
case Selection.totalSelectedPrice selection data.loot of case Selection.totalSelectedPrice selection data.loot of
@@ -177,7 +177,7 @@ view model =
[] []
] ]
( Chest.Sell _, True ) -> ( Chest.Sell _ _, True ) ->
selectPlayers config.extra.players selectPlayers config.extra.players
_ -> _ ->
@@ -303,28 +303,35 @@ type PlayerMsg
update msg model = update msg model =
case ( msg, model ) of case ( msg, model ) of
( AdminViewer aMsg, Admin config ) -> ( AdminViewer ConfirmNewPlayer, Admin config ) ->
(case ( aMsg, config.playerForm ) of ( Admin { config | playerForm = Nothing }
( EditPlayer, Nothing ) -> , case config.playerForm of
( Admin { config | playerForm = Just <| NewPlayerForm "" 0.0 } Just form ->
, Cmd.none Cmd.map Api <|
) Api.adminAddPlayer form
( GotFormMsg subMsg, Just f ) -> Nothing ->
( Admin { config | playerForm = Just (updateForm subMsg f) } Cmd.none
, Cmd.none
)
( ConfirmNewPlayer, Just f ) ->
( model, Cmd.none )
( CloseEdit, _ ) ->
( Admin { config | playerForm = Nothing }, Cmd.none )
_ ->
( model, Cmd.none )
) )
|> Tuple.mapSecond (Cmd.map AdminViewer)
( AdminViewer aMsg, Admin config ) ->
Tuple.mapSecond (Cmd.map AdminViewer) <|
case ( aMsg, config.playerForm ) of
( EditPlayer, Nothing ) ->
( Admin { config | playerForm = Just <| NewPlayerForm "" 0.0 }
, Cmd.none
)
( GotFormMsg subMsg, Just f ) ->
( Admin { config | playerForm = Just (updateForm subMsg f) }
, Cmd.none
)
( CloseEdit, _ ) ->
( Admin { config | playerForm = Nothing }, Cmd.none )
_ ->
( model, Cmd.none )
( PlayerViewer ConfirmSell, Player config ) -> ( PlayerViewer ConfirmSell, Player config ) ->
( model ( model

View File

@@ -71,12 +71,12 @@ view model =
( True, data.player.id == 0 ) ( True, data.player.id == 0 )
in in
case ( model.chest, isPlayer && not isGroup ) of case ( model.chest, isPlayer && not isGroup ) of
( Chest.View _, True ) -> ( Chest.View _ _, True ) ->
B.btn B.btn
(GotChestMsg <| Chest.claim (getClaimsFromSession model.session)) (GotChestMsg <| Chest.claim (getClaimsFromSession model.session))
{ text = "Demander", icon = "fas fa-praying-hands", color = "is-primary" } { text = "Demander", icon = "fas fa-praying-hands", color = "is-primary" }
( Chest.Claim _, True ) -> ( Chest.Claim _ _, True ) ->
B.confirmButtons ConfirmGrab (GotChestMsg Chest.show) B.confirmButtons ConfirmGrab (GotChestMsg Chest.show)
( _, _ ) -> ( _, _ ) ->
@@ -93,7 +93,7 @@ type Msg
type InnerMsg type InnerMsg
= GotLoot Api.ToChest (HttpResult Loot) = GotLoot (HttpResult Loot)
| GotChestMsg Chest.Msg | GotChestMsg Chest.Msg
| ConfirmGrab | ConfirmGrab
@@ -106,7 +106,7 @@ update msg model =
Internal ConfirmGrab -> Internal ConfirmGrab ->
case ( Session.user model.session, model.loot, model.chest ) of case ( Session.user model.session, model.loot, model.chest ) of
( Player data, Loaded loot, Chest.Claim _ ) -> ( Player data, Loaded loot, Chest.Claim _ _ ) ->
( model ( model
, Chest.confirmGrab , Chest.confirmGrab
data.player.id data.player.id
@@ -121,11 +121,11 @@ update msg model =
Internal innerMsg -> Internal innerMsg ->
Tuple.mapSecond (Cmd.map Internal) <| Tuple.mapSecond (Cmd.map Internal) <|
case innerMsg of case innerMsg of
GotLoot _ (Ok loot) -> GotLoot (Ok loot) ->
( { model | loot = Loaded loot }, Cmd.none ) ( { model | loot = Loaded loot }, Cmd.none )
GotLoot _ (Err _) -> GotLoot (Err e) ->
( { model | loot = LoadError "Le chargement a échoué" }, Cmd.none ) ( { model | loot = LoadError <| Debug.toString e }, Cmd.none )
GotChestMsg chestMsg -> GotChestMsg chestMsg ->
Chest.update chestMsg model.chest Chest.update chestMsg model.chest

View File

@@ -47,13 +47,13 @@ view model =
Loaded loot -> Loaded loot ->
( Html.map Internal <| ( Html.map Internal <|
case ( model.chest, Session.user model.session ) of case ( model.chest, Session.user model.session ) of
( Chest.View _, Session.Admin _ ) -> ( Chest.View _ _, Session.Admin _ ) ->
B.btn (GotChestMsg Chest.new) { text = "Remplacer", icon = "fas fa-sync-alt", color = "is-primary" } B.btn (GotChestMsg Chest.new) { text = "Remplacer", icon = "fas fa-sync-alt", color = "is-primary" }
( Chest.View _, Session.Player _ ) -> ( Chest.View _ _, Session.Player _ ) ->
B.btn (GotChestMsg Chest.buy) { text = "Acheter", icon = "fas fa-coins", color = "is-primary" } B.btn (GotChestMsg Chest.buy) { text = "Acheter", icon = "fas fa-coins", color = "is-primary" }
( Chest.Buy _, Session.Player _ ) -> ( Chest.Buy _ _, Session.Player _ ) ->
B.confirmButtons ConfirmBuy (GotChestMsg Chest.show) B.confirmButtons ConfirmBuy (GotChestMsg Chest.show)
( Chest.New _, Session.Admin _ ) -> ( Chest.New _, Session.Admin _ ) ->
@@ -78,7 +78,7 @@ type Msg
type ShopMsg type ShopMsg
= GotLoot Api.ToChest (HttpResult Loot) = GotLoot (HttpResult Loot)
| ConfirmRefresh | ConfirmRefresh
| GotRefreshResult (Maybe ()) | GotRefreshResult (Maybe ())
| ConfirmBuy | ConfirmBuy
@@ -97,7 +97,7 @@ update msg model =
case msg of case msg of
Internal ConfirmBuy -> Internal ConfirmBuy ->
case ( Session.user (getSession model), model.loot, model.chest ) of case ( Session.user (getSession model), model.loot, model.chest ) of
( Session.Player data, Loaded loot, Chest.Buy _ ) -> ( Session.Player data, Loaded loot, Chest.Buy _ _ ) ->
( model ( model
, Chest.confirmBuy , Chest.confirmBuy
data.player.id data.player.id
@@ -120,49 +120,46 @@ update msg model =
) )
Internal shopMsg -> Internal shopMsg ->
let Tuple.mapSecond (Cmd.map Internal) <|
( nModel, cmd ) = case shopMsg of
case shopMsg of GotLoot response ->
GotLoot Api.OfShop response -> case response of
case response of Ok loot ->
Ok loot -> ( { model | loot = Loaded loot }, Cmd.none )
( { model | loot = Loaded loot }, Cmd.none )
-- TODO: handle error -- TODO: handle error
Err e -> Err e ->
( { model | loot = LoadError <| Debug.toString e }, Cmd.none ) ( { model | loot = LoadError <| Debug.toString e }, Cmd.none )
ConfirmRefresh -> ConfirmRefresh ->
case Session.user (getSession model) of case Session.user (getSession model) of
Session.Admin _ -> Session.Admin _ ->
let let
loot = loot =
case model.chest of case model.chest of
Chest.New chest -> Chest.New chest ->
NewChest.allLoot chest NewChest.allLoot chest
_ -> _ ->
[] []
in in
( model, Api.replaceShopItems GotRefreshResult loot ) ( model, Api.replaceShopItems GotRefreshResult loot )
_ -> _ ->
let let
_ = _ =
Debug.log "Forbidden action ! (is not admin)" () Debug.log "Forbidden action ! (is not admin)" ()
in in
( model, Cmd.none ) ( model, Cmd.none )
GotChestMsg subMsg -> GotChestMsg subMsg ->
Chest.update subMsg model.chest Chest.update subMsg model.chest
|> Tuple.mapBoth |> Tuple.mapBoth
(\c -> { model | chest = c }) (\c -> { model | chest = c })
(Cmd.map GotChestMsg) (Cmd.map GotChestMsg)
_ -> _ ->
( model, Cmd.none ) ( model, Cmd.none )
in
( nModel, Cmd.map Internal cmd )
_ -> _ ->
( model, Cmd.none ) ( model, Cmd.none )

View File

@@ -5,6 +5,18 @@ import Url.Parser as P exposing ((</>), Parser, oneOf, s)
-- Name of the application, prepended to it's actual root
scriptName =
"lootalot"
root =
P.s scriptName
-- ROUTES -- ROUTES
@@ -18,13 +30,32 @@ type Route
parser : P.Parser (Route -> a) a parser : P.Parser (Route -> a) a
parser = parser =
oneOf oneOf
[ P.map Home P.top [ P.map Home root
, P.map GroupChest (P.s "groupe") , P.map GroupChest (root </> P.s "groupe")
, P.map Merchant (P.s "marchand") , P.map Merchant (root </> P.s "marchand")
, P.map About (P.s "about") , P.map About (root </> P.s "about")
] ]
fromUrl : Url.Url -> Maybe Route fromUrl : Url.Url -> Maybe Route
fromUrl url = fromUrl url =
P.parse parser url P.parse parser url
toHref : Route -> String
toHref route =
"/"
++ scriptName
++ (case route of
Home ->
"/"
About ->
"/"
Merchant ->
"/marchand"
GroupChest ->
"/groupe"
)

View File

@@ -16,8 +16,7 @@ type alias ItemRenderer a msg =
view : RowRenderer a msg -> List a -> Html msg view : RowRenderer a msg -> List a -> Html msg
view rowRenderer content = view rowRenderer content =
table [ class "table is-fullwidth" ] table [ class "table is-fullwidth" ]
[ thead [ class "table-header" ] [ thead [] [ th [] [ text "Nom" ] ]
[ th [] [ text "Nom" ] ]
, tbody [] <| , tbody [] <|
List.map List.map
rowRenderer rowRenderer