Add a card detail view

This commit is contained in:
Correl Roush 2021-07-16 23:18:06 -04:00
parent b12d0c62ca
commit b0fff226ea
4 changed files with 99 additions and 32 deletions

View file

@ -90,6 +90,7 @@ class SearchHandler(tornado.web.RequestHandler):
"color_identity": tutor.models.Color.to_string( "color_identity": tutor.models.Color.to_string(
card.color_identity card.color_identity
), ),
"oracle_text": card.oracle_text,
} }
for card in cards[:limit] for card in cards[:limit]
] ]

View file

@ -2,6 +2,9 @@
<head> <head>
<title>Bulk Tagging Dashboard</title> <title>Bulk Tagging Dashboard</title>
<script type="text/javascript" src="elm.js"></script> <script type="text/javascript" src="elm.js"></script>
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Libre+Baskerville&display=swap" rel="stylesheet">
</head> </head>
<meta charset="utf-8"/> <meta charset="utf-8"/>
<body> <body>

View file

@ -10,6 +10,7 @@ import Dict
import Element as E import Element as E
import Element.Background as Background import Element.Background as Background
import Element.Border as Border import Element.Border as Border
import Element.Events as Events
import Element.Font as Font import Element.Font as Font
import Element.Input as Input import Element.Input as Input
import Html.Events import Html.Events
@ -24,7 +25,7 @@ import Url.Parser exposing ((</>), (<?>))
import Url.Parser.Query import Url.Parser.Query
type alias Window = type alias Dimensions =
{ width : Int { width : Int
, height : Int , height : Int
} }
@ -38,22 +39,25 @@ type alias Criteria =
type alias Model = type alias Model =
{ navigationKey : Browser.Navigation.Key { navigationKey : Browser.Navigation.Key
, viewport : Window , viewport : Dimensions
, spinner : Spinner.Model , spinner : Spinner.Model
, criteria : Criteria , criteria : Criteria
, cardPage : CardPage , cardPage : CardPage
, activeCard : Maybe Card.Card
} }
type Msg type Msg
= UrlChanged Url.Url = UrlChanged Url.Url
| ViewportChanged Window | ViewportChanged Dimensions
| LinkClicked Browser.UrlRequest | LinkClicked Browser.UrlRequest
| SpinnerMsg Spinner.Msg | SpinnerMsg Spinner.Msg
| UpdateCriteria CriteriaMsg | UpdateCriteria CriteriaMsg
| Search | Search
| GetPage Url.Url | GetPage Url.Url
| FoundCards (Result Http.Error (Paginated.Page Card.Card)) | FoundCards (Result Http.Error (Paginated.Page Card.Card))
| ShowCardDetails Card.Card
| ClearCardDetails
type CriteriaMsg type CriteriaMsg
@ -181,6 +185,7 @@ init _ url key =
, spinner = Spinner.init , spinner = Spinner.init
, criteria = criteria , criteria = criteria
, cardPage = Loading Paginated.empty , cardPage = Loading Paginated.empty
, activeCard = Nothing
} }
, Cmd.batch , Cmd.batch
[ search criteria [ search criteria
@ -262,6 +267,12 @@ update msg model =
FoundCards (Err _) -> FoundCards (Err _) ->
( model, Cmd.none ) ( model, Cmd.none )
ShowCardDetails card ->
( { model | activeCard = Just card }, Cmd.none )
ClearCardDetails ->
( { model | activeCard = Nothing }, Cmd.none )
colors = colors =
let let
@ -288,36 +299,51 @@ viewCardBrowser : Model -> E.Element Msg
viewCardBrowser model = viewCardBrowser model =
let let
cardWidth = cardWidth =
-- 50% of the Scryfall border_crop image width -- 30% of the Scryfall border_crop image width (480)
240 144
cardHeight = cardHeight =
-- 50% of the Scryfall border_crop image height -- 30% of the Scryfall border_crop image height (680)
340 204
cardSpacing = cardSpacing =
10 5
navigationButtonWidth = availableWidth =
100 (model.viewport.width // 5) * 4
cardColumns = cardColumns =
-- Either 3, 6, or 9, based on viewport width -- Either 6 or 9, based on viewport width
let let
availableColumns = availableColumns =
(model.viewport.width - (2 * navigationButtonWidth)) availableWidth
// (cardWidth + cardSpacing) // (cardWidth + cardSpacing)
in in
(max 3 >> min 9) (availableColumns // 3 * 3) (max 6 >> min 9) (availableColumns // 3 * 3)
cardRows = cardRows =
18 // cardColumns 18 // cardColumns
viewCard cardModel = minInfoWidth =
E.el [ Border.rounded 10, E.clip, E.width <| E.px cardWidth, E.height <| E.px cardHeight ] <| 1230 // 5
minBrowserWidth =
minInfoWidth * 4
viewCard : Dimensions -> Card.Card -> E.Element Msg
viewCard dimensions cardModel =
E.el
[ Border.rounded 10
, E.clip
, E.width <| E.px dimensions.width
, E.height <| E.px dimensions.height
, Events.onMouseEnter <| ShowCardDetails cardModel
, Events.onMouseLeave <| ClearCardDetails
]
<|
E.image E.image
[ E.width <| E.px cardWidth [ E.width <| E.px dimensions.width
, E.height <| E.px cardHeight , E.height <| E.px dimensions.height
, E.behindContent <| , E.behindContent <|
E.html <| E.html <|
Spinner.view manaSpinner model.spinner Spinner.view manaSpinner model.spinner
@ -336,15 +362,27 @@ viewCardBrowser model =
Just url -> Just url ->
Input.button Input.button
[ E.height E.fill [ E.height E.fill
, E.width (E.px navigationButtonWidth) , E.width E.fill
, Background.color colors.primary , Background.color colors.primary
, Border.rounded 5
, Font.color colors.text , Font.color colors.text
, Font.center , Font.center
] ]
{ label = E.text text, onPress = Just (GetPage url) } { label = E.text text, onPress = Just (GetPage url) }
Nothing -> Nothing ->
E.el [ E.width (E.px navigationButtonWidth) ] E.none E.el [ E.width E.fill ] E.none
cardDetails card =
E.column
[ E.spacing 20
, E.padding 10
]
<|
E.el [ E.centerX ] (viewCard { width = 192, height = 272 } card)
:: E.paragraph [ Font.heavy, Font.size 24, Font.center ] [ E.text card.name ]
:: List.map (\text -> E.paragraph [ Font.size 16 ] [ E.text text ])
(String.lines card.oracleText)
in in
case model.cardPage of case model.cardPage of
Failed -> Failed ->
@ -371,20 +409,40 @@ viewCardBrowser model =
Ready cardPage -> Ready cardPage ->
E.row E.row
[ E.width E.fill [ E.centerX
, E.height (E.px (cardRows * (cardHeight + cardSpacing))) , E.height (E.px (3 * (cardHeight + cardSpacing)))
, E.centerX , Font.family
[ Font.typeface
"Libre Baskerville"
, Font.serif
]
]
[ E.column
[ E.height E.fill
, E.width <| E.px minInfoWidth
, Font.color colors.text
]
[ Maybe.map cardDetails model.activeCard |> Maybe.withDefault E.none ]
, E.column
[ E.width (E.fill |> E.minimum minBrowserWidth)
, E.height E.fill
, E.spacing 10
] ]
<| <|
[ navButton "" cardPage.prev [ E.wrappedRow
, E.wrappedRow
[ E.width (E.px (cardColumns * (cardWidth + cardSpacing))) [ E.width (E.px (cardColumns * (cardWidth + cardSpacing)))
, E.centerX
, E.spacing cardSpacing , E.spacing cardSpacing
, E.paddingEach { left = cardSpacing // 2, top = 0, bottom = 0, right = 0 }
, E.centerX
, E.centerY
] ]
(List.map viewCard cardPage.values) (List.map (viewCard { width = cardWidth, height = cardHeight }) cardPage.values)
, E.row [ E.width E.fill, E.spacing 20 ]
[ navButton "" cardPage.prev
, navButton "" cardPage.next , navButton "" cardPage.next
] ]
]
]
onEnter : msg -> E.Attribute msg onEnter : msg -> E.Attribute msg
@ -409,7 +467,7 @@ view model =
{ title = "Tutor" { title = "Tutor"
, body = , body =
[ E.layout [ Background.color colors.background ] <| [ E.layout [ Background.color colors.background ] <|
E.column [ E.width E.fill, E.spacing 20 ] E.column [ E.width (E.fill |> E.minimum 1280), E.spacing 20 ]
[ E.row [ E.row
[ E.padding 10 [ E.padding 10
, E.spacing 10 , E.spacing 10

View file

@ -9,6 +9,7 @@ type alias Card =
, name : String , name : String
, setCode : String , setCode : String
, rarity : String , rarity : String
, oracleText : String
} }
@ -19,3 +20,7 @@ decode =
|> JDP.required "name" Json.Decode.string |> JDP.required "name" Json.Decode.string
|> JDP.required "set_code" Json.Decode.string |> JDP.required "set_code" Json.Decode.string
|> JDP.required "rarity" Json.Decode.string |> JDP.required "rarity" Json.Decode.string
|> JDP.required "oracle_text"
(Json.Decode.nullable Json.Decode.string
|> Json.Decode.map (Maybe.withDefault "")
)