Mock out joining a room

This commit is contained in:
Correl Roush 2020-05-04 14:22:24 -04:00
parent 76d19e0937
commit 22436d22f7
4 changed files with 313 additions and 96 deletions

View file

@ -79,7 +79,30 @@ updateUrl url model =
toEntry model (Entry.init ()) toEntry model (Entry.init ())
Just (Room id) -> Just (Room id) ->
toRoom model (Room.init ()) case model.page of
EntryPage entryModel ->
toRoom model
(Room.init
{ room = id
, roomName =
case String.trim entryModel.roomName of
"" ->
"Planning Poker"
trimmed ->
trimmed
, playerName = entryModel.playerName
}
)
_ ->
toRoom model
(Room.init
{ room = id
, roomName = "Planning Poker"
, playerName = ""
}
)
Nothing -> Nothing ->
( model, Cmd.none ) ( model, Cmd.none )

View file

@ -11,26 +11,25 @@ import Html exposing (Html)
import PlanningPokerUI as UI import PlanningPokerUI as UI
type User
= Moderator { name : String }
type alias Model = type alias Model =
{ name : String { playerName : String
, user : Maybe User , roomName : String
, player : Maybe String
, error : Maybe String , error : Maybe String
} }
type Msg type Msg
= NameChanged String = PlayerNameChanged String
| RoomNameChanged String
| CreateRoom | CreateRoom
init : () -> ( Model, Cmd Msg ) init : () -> ( Model, Cmd Msg )
init _ = init _ =
( { name = "" ( { playerName = ""
, user = Nothing , roomName = ""
, player = Nothing
, error = Nothing , error = Nothing
} }
, Cmd.none , Cmd.none
@ -40,8 +39,11 @@ init _ =
update : Nav.Key -> Msg -> Model -> ( Model, Cmd Msg ) update : Nav.Key -> Msg -> Model -> ( Model, Cmd Msg )
update key msg model = update key msg model =
case msg of case msg of
NameChanged newName -> PlayerNameChanged newName ->
( { model | name = newName }, Cmd.none ) ( { model | playerName = newName }, Cmd.none )
RoomNameChanged newName ->
( { model | roomName = newName }, Cmd.none )
CreateRoom -> CreateRoom ->
( model, Nav.pushUrl key "/room/a0fd1422-abd9-434e-9d7c-883294b2992c" ) ( model, Nav.pushUrl key "/room/a0fd1422-abd9-434e-9d7c-883294b2992c" )
@ -62,14 +64,21 @@ layout model =
[ el [ centerX ] (text "Oh, hey!") [ el [ centerX ] (text "Oh, hey!")
, el [ centerX ] (text "Tell us who you are") , el [ centerX ] (text "Tell us who you are")
, Input.text [ centerX, width (px 300) ] , Input.text [ centerX, width (px 300) ]
{ onChange = NameChanged { onChange = PlayerNameChanged
, text = model.name , text = model.playerName
, label = Input.labelHidden "Your name" , label = Input.labelHidden "Your name"
, placeholder = Just (Input.placeholder [] (text "Your name")) , placeholder = Just (Input.placeholder [] (text "Your name"))
} }
, el [ centerX ] (text "and what you're up to")
, Input.text [ centerX, width (px 300) ]
{ onChange = RoomNameChanged
, text = model.roomName
, label = Input.labelHidden "Room name"
, placeholder = Just (Input.placeholder [] (text "Planning Poker"))
}
, el [ centerX ] (text "then") , el [ centerX ] (text "then")
, UI.actionButton [ centerX ] , UI.actionButton [ centerX ]
{ isActive = not (String.isEmpty model.name) { isActive = not (String.isEmpty model.playerName)
, onPress = CreateRoom , onPress = CreateRoom
, label = text "Make a room!" , label = text "Make a room!"
} }

View file

@ -13,8 +13,22 @@ import PlanningPokerUI as UI
type alias Model = type alias Model =
{ name : String { room : Maybe Room
, player : String , player : String
, playerName : String
}
type Msg
= Vote String
| Reset
| PlayerNameChanged String
| JoinRoom
type alias Room =
{ id : String
, name : String
, players : Dict String Player , players : Dict String Player
} }
@ -31,27 +45,52 @@ type alias Player =
} }
type Msg init : { room : String, roomName : String, playerName : String } -> ( Model, Cmd Msg )
= Vote String init { room, roomName, playerName } =
| Reset let
preparedRooms =
init : () -> ( Model, Cmd Msg )
init _ =
( { name = "Planning Poker"
, player = "099b73da-e714-4085-aa33-6419076d0765"
, players =
Dict.fromList Dict.fromList
[ ( "099b73da-e714-4085-aa33-6419076d0765" [ -- Room created from mocked entry page
, { level = Moderator, name = "Me", vote = Nothing } ( "a0fd1422-abd9-434e-9d7c-883294b2992c"
, { id = "a0fd1422-abd9-434e-9d7c-883294b2992c"
, name = roomName
, players =
Dict.fromList
[ ( "00000000-0000-0000-0000-000000000000"
, { level = Moderator, name = playerName, vote = Nothing }
)
, ( "44db0a59-28bb-4b9f-8e5d-a46f2c2a3266"
, { level = Participant, name = "John", vote = Nothing }
)
, ( "69b8b450-bc2a-4eeb-b056-91c7aa4ba528"
, { level = Participant, name = "Jane", vote = Nothing }
)
]
}
) )
, ( "44db0a59-28bb-4b9f-8e5d-a46f2c2a3266" , -- Room created from direct url access (unjoined)
, { level = Participant, name = "John", vote = Nothing } ( "joinable"
) , { id = "a0fd1422-abd9-434e-9d7c-883294b2992c"
, ( "69b8b450-bc2a-4eeb-b056-91c7aa4ba528" , name = "Today's Grooming Session"
, { level = Participant, name = "Jane", vote = Nothing } , players =
Dict.fromList
[ ( "ffffffff-ffff-ffff-ffff-ffffffffffff"
, { level = Moderator, name = "Pat", vote = Nothing }
)
, ( "44db0a59-28bb-4b9f-8e5d-a46f2c2a3266"
, { level = Participant, name = "John", vote = Nothing }
)
, ( "69b8b450-bc2a-4eeb-b056-91c7aa4ba528"
, { level = Participant, name = "Jane", vote = Nothing }
)
]
}
) )
] ]
in
( { room = Dict.get room preparedRooms
, player = "00000000-0000-0000-0000-000000000000"
, playerName = playerName
} }
, Cmd.none , Cmd.none
) )
@ -59,65 +98,119 @@ init _ =
update : Nav.Key -> Msg -> Model -> ( Model, Cmd Msg ) update : Nav.Key -> Msg -> Model -> ( Model, Cmd Msg )
update key msg model = update key msg model =
case msg of case model.room of
Vote value -> Just room ->
( { model case msg of
| players = Vote value ->
Dict.update ( { model
model.player | room =
(Maybe.map (\p -> { p | vote = Just value })) Just
model.players { room
} | players =
, Cmd.none Dict.update
) model.player
(Maybe.map (\p -> { p | vote = Just value }))
room.players
}
}
, Cmd.none
)
Reset -> Reset ->
( { model ( { model
| players = | room =
Dict.map Just
(\k v -> { v | vote = Nothing }) { room
model.players | players =
} Dict.map
, Cmd.none (\k v -> { v | vote = Nothing })
) room.players
}
}
, Cmd.none
)
PlayerNameChanged newName ->
( { model | playerName = newName }, Cmd.none )
JoinRoom ->
let
newRoom =
{ room
| players =
Dict.insert model.player
{ level = Participant
, name = model.playerName
, vote = Nothing
}
room.players
}
in
( { model | room = Just newRoom }, Cmd.none )
Nothing ->
case msg of
_ ->
( model, Cmd.none )
view : Model -> Document Msg view : Model -> Document Msg
view model = view model =
{ title = model.name case model.room of
, body = [ layout model ] Just room ->
} let
maybePlayer =
Dict.get model.player room.players
in
case maybePlayer of
Just player ->
UI.toDocument
{ title = room.name
, body =
[ navBar { title = room.name, playerName = player.name }
, viewRoom model.player room
]
}
Nothing ->
UI.toDocument
{ title = room.name
, body =
[ navBar { title = room.name, playerName = "" }
, joinForm room model.playerName
]
}
_ ->
UI.toDocument
{ title = "Loading Room..."
, body =
[ UI.heroText [ centerX, centerY ] "Loading..."
]
}
layout : Model -> Html Msg viewRoom : String -> Room -> Element Msg
layout model = viewRoom player room =
let let
myVote = myVote =
Dict.get model.player model.players Dict.get player room.players
|> Maybe.andThen .vote |> Maybe.andThen .vote
in in
Element.layout [] <| column [ width fill, spacing 20 ]
column [ width fill, spacing 20 ] [ row
[ navBar model [ width fill ]
, row [ el [ width (fillPortion 3), alignTop ] <|
[ width fill ] viewCards myVote
[ el [ width (fillPortion 3), alignTop ] <| , el [ width (fillPortion 1), alignTop ] <|
cards myVote viewPlayers (Dict.values room.players)
, el [ width (fillPortion 1), alignTop ] <|
players (Dict.values model.players)
]
, moderatorTools
] ]
, moderatorTools
]
navBar : Model -> Element Msg navBar : { title : String, playerName : String } -> Element Msg
navBar model = navBar { title, playerName } =
let
myName =
Dict.get model.player model.players
|> Maybe.map .name
|> Maybe.withDefault ""
in
row row
[ Background.color UI.blue [ Background.color UI.blue
, height (px 50) , height (px 50)
@ -129,17 +222,17 @@ navBar model =
, Font.color UI.white , Font.color UI.white
, width fill , width fill
] ]
(text model.name) (text title)
, el , el
[ Font.alignRight [ Font.alignRight
, Font.color UI.white , Font.color UI.white
] ]
(text myName) (text playerName)
] ]
cards : Maybe String -> Element Msg viewCards : Maybe String -> Element Msg
cards selected = viewCards selected =
let let
card value = card value =
Input.button Input.button
@ -166,8 +259,8 @@ cards selected =
List.map card [ "1", "3", "5", "8", "13" ] List.map card [ "1", "3", "5", "8", "13" ]
players : List Player -> Element Msg viewPlayers : List Player -> Element Msg
players playerList = viewPlayers playerList =
table [ width fill ] table [ width fill ]
{ data = playerList { data = playerList
, columns = , columns =
@ -201,3 +294,47 @@ moderatorTools =
, onPress = Reset , onPress = Reset
, label = text "Reset" , label = text "Reset"
} }
joinForm : Room -> String -> Element Msg
joinForm room playerName =
let
players =
Dict.values room.players
|> List.map .name
in
column [ width fill, spacing 20, centerX, centerY ]
[ UI.heroText [ centerX ] "Welcome!"
, el [ centerX ] (text "Tell us who you are")
, Input.text [ centerX, width (px 300), Font.center ]
{ onChange = PlayerNameChanged
, text = playerName
, label = Input.labelHidden "Your name"
, placeholder = Just (Input.placeholder [] (text "Your name"))
}
, UI.actionButton [ centerX ]
{ isActive = not (String.isEmpty playerName)
, onPress = JoinRoom
, label = text "Join!"
}
, el [ centerX ]
(text <|
case players of
[] ->
"Nobody else has joined yet."
[ player ] ->
player ++ " is already here!"
player :: rest ->
if List.length players <= 3 then
String.join ", " rest
++ ", and "
++ player
++ " are already here!"
else
String.fromInt (List.length players)
++ " People are already here"
)
]

View file

@ -1,33 +1,63 @@
module PlanningPokerUI exposing (actionButton, blue, lightGrey, red, white) module PlanningPokerUI exposing
( actionButton
, blue
, colors
, fontSizes
, heroText
, lightGrey
, red
, toDocument
, white
)
import Element exposing (Element) import Browser exposing (Document)
import Element exposing (..)
import Element.Background as Background import Element.Background as Background
import Element.Font as Font import Element.Font as Font
import Element.Input as Input import Element.Input as Input
blue : Element.Color colors =
let
primary =
blue
in
{ primary = primary
, background = white
, selected = primary
, disabled = lightGrey
, error = red
}
fontSizes =
{ huge = 80
, normal = 18
}
blue : Color
blue = blue =
Element.rgb255 100 100 255 rgb255 100 100 255
lightGrey : Element.Color lightGrey : Color
lightGrey = lightGrey =
Element.rgb255 200 200 200 rgb255 200 200 200
red : Element.Color red : Color
red = red =
Element.rgb255 255 100 100 rgb255 255 100 100
white : Element.Color white : Color
white = white =
Element.rgb255 255 255 255 rgb255 255 255 255
actionButton : actionButton :
List (Element.Attribute msg) List (Attribute msg)
-> { isActive : Bool, onPress : msg, label : Element msg } -> { isActive : Bool, onPress : msg, label : Element msg }
-> Element msg -> Element msg
actionButton attrs { isActive, onPress, label } = actionButton attrs { isActive, onPress, label } =
@ -40,7 +70,7 @@ actionButton attrs { isActive, onPress, label } =
( lightGrey, Nothing ) ( lightGrey, Nothing )
in in
Input.button Input.button
([ Element.padding 20 ([ padding 20
, Background.color color , Background.color color
, Font.color white , Font.color white
] ]
@ -49,3 +79,21 @@ actionButton attrs { isActive, onPress, label } =
{ onPress = maybeEvent { onPress = maybeEvent
, label = label , label = label
} }
heroText :
List (Attribute msg)
-> String
-> Element msg
heroText attrs s =
el ([ Font.size fontSizes.huge ] ++ attrs) (text s)
toDocument : { title : String, body : List (Element msg) } -> Document msg
toDocument { title, body } =
{ title = title
, body =
[ layout [ explain Debug.todo ] <|
column [ width fill, height fill, spacing 20 ] body
]
}