Browse Source

Improve styles and navigation; add mobile warning

Cadel Watson 4 tháng trước cách đây
mục cha
commit
01e5d152c2
5 tập tin đã thay đổi với 83 bổ sung122 xóa
  1. 4 0
      css/styles.css
  2. 0 3
      js/app.js
  3. 0 77
      server/main.py
  4. 1 6
      src/Draft.elm
  5. 78 36
      src/Main.elm

+ 4 - 0
css/styles.css

@@ -326,3 +326,7 @@ body {
 ::-webkit-scrollbar-thumb:hover {
     background: #334155;
 }
+
+body {
+	background-color: rgb(241 245 249);
+}

+ 0 - 3
js/app.js

@@ -1,5 +1,3 @@
-import draftData from "../data/drafts/draft_tdm_bad.json";
-
 import {Elm} from '../src/Main.elm';
 
 function getSetData(db, setCode, callback) {
@@ -77,7 +75,6 @@ openDBRequest.onsuccess = (event) => {
             node: document.getElementById('myapp'),
             flags: {
                 sets: sets,
-                draftData: JSON.stringify(draftData),
             }
         });
 

+ 0 - 77
server/main.py

@@ -84,80 +84,3 @@ def read_item(set_name: str):
         ratings_data = json.load(f)
 
     return {"code": set_name, "data": {"cards": card_data, "ratings": ratings_data}}
-
-USER_ID_REGEX = r'user_history\/(.*)\?'
-
-class DraftMeta(TypedDict):
-    expansion: str
-    format: str
-    timestamp: str
-    draft_id: str
-
-async def get_drafts_from_17lands(user_id: str) -> List[DraftMeta]:
-    url = f"https://www.17lands.com/user/data/{user_id}"
-
-    drafts = []
-    async with httpx.AsyncClient() as client:
-        res = await client.get(
-            url,
-            headers={
-                "Accept": "application/json"
-            }
-        )
-        print(res)
-        json_res = res.json()
-
-        for draft in json_res["drafts"]:
-            drafts.append({
-                "expansion": draft["expansion"],
-                "format": draft["format"],
-                "timestamp": draft["first_event_server_time"],
-                "draft_id": draft["id"],
-            })
-
-    return drafts
-
-async def get_draft_data(draft_id:str, client: httpx.AsyncClient):
-    url = f"https://www.17lands.com/data/draft?draft_id={draft_id}"
-    res = await client.get(
-        url,
-        headers={
-            "Accept": "application/json"
-        }
-    )
-
-    print(res)
-    print(res.text)
-    print(res.json())
-    return res.json()["picks"]
-
-async def get_all_draft_data(draft_ids: List[str]) -> Dict[str, Any]:
-    async with httpx.AsyncClient() as client:
-        tasks = [get_draft_data(draft_id, client) for draft_id in draft_ids]
-        results = await asyncio.gather(*tasks)
-
-    return {
-        draft_id: {"picks": result["picks"]}
-        for draft_id, result in zip(draft_ids, results)
-    }
-
-@app.get("/drafts")
-async def read_item(history: str):
-    user_id = re.search(USER_ID_REGEX, history).group(1)
-
-    all_drafts = await get_drafts_from_17lands(user_id)
-    all_draft_data = await get_all_draft_data([draft["draft_id"] for draft in all_drafts])
-
-    drafts = [
-        {
-            "set_code" : draft["expansion"],
-            "format" : draft["format"],
-            "timestamp" : draft["timestamp"],
-            "draft_data" : all_draft_data[draft["draft_id"]],
-        }
-        for draft in all_drafts
-    ]
-
-    print(drafts)
-
-    return {"drafts":drafts}

+ 1 - 6
src/Draft.elm

@@ -1,4 +1,4 @@
-module Draft exposing (Draft, Pick, PickCard, decode, decodeDraft)
+module Draft exposing (Draft, Pick, PickCard, decodeDraft)
 
 import Json.Decode as Decode exposing (Decoder)
 import Json.Decode.Pipeline as Decode
@@ -22,11 +22,6 @@ type alias PickCard =
     }
 
 
-decode : String -> Result String Draft
-decode x =
-    Decode.decodeString decodeDraft x |> Result.mapError Decode.errorToString
-
-
 decodeDraft : Decoder Draft
 decodeDraft =
     Decode.list decodePick

+ 78 - 36
src/Main.elm

@@ -11,7 +11,7 @@ import Deck
 import Dict exposing (Dict)
 import Draft exposing (Draft)
 import DraftMeta exposing (DraftMeta, parseDraftIDFromPublicURL)
-import Html exposing (Html, a, button, div, h1, img, input, label, li, p, span, text, ul)
+import Html exposing (Html, a, button, div, h1, h2, h3, header, img, input, label, li, p, span, text, ul)
 import Html.Attributes exposing (alt, class, classList, disabled, href, src, type_, value)
 import Html.Events as Events exposing (onClick, onInput, onMouseEnter)
 import Html.Keyed as Keyed
@@ -77,14 +77,11 @@ type ImportDraft
     = EditingImportUrl String
     | LoadingDraft
     | ImportDraftParseError String
-    | DraftImported DraftMeta
 
 
 type alias ChooseSetModel =
-    { draftData : String
-    , sets : Dict String SetLoadStatus
+    { sets : Dict String SetLoadStatus
     , importDraft : ImportDraft
-    , importDraftParseError : Maybe String
     }
 
 
@@ -98,6 +95,9 @@ type alias ReadyModel =
     , deckProgress : DeckProgress
     , toolboxAccordion : ToolboxAccordion
     , deckSortOrder : Deck.DeckSortMethod
+
+    -- Save state for returning to menu
+    , sets : Dict String SetLoadStatus
     }
 
 
@@ -107,6 +107,9 @@ type alias CardExplorerModel =
     , flipHighlighted : Bool
     , performanceDistributions : CardPerformanceDistributions
     , sortOrder : SortOrder
+
+    -- Save state for returning to menu
+    , sets : Dict String SetLoadStatus
     }
 
 
@@ -115,7 +118,7 @@ type alias ErrorModel =
     }
 
 
-init : { sets : List String, draftData : String } -> ( Model, Cmd Msg )
+init : { sets : List String } -> ( Model, Cmd Msg )
 init flags =
     let
         setStatus : Dict String SetLoadStatus
@@ -131,19 +134,17 @@ init flags =
                 flags.sets
     in
     ( ChooseSet
-        { draftData = flags.draftData
-        , sets = setStatus
+        { sets = setStatus
         , importDraft = EditingImportUrl ""
-        , importDraftParseError = Nothing
         }
     , Cmd.batch (API.getSets IOGotSets :: setCmds)
     )
 
 
 type Msg
-    = Increment
-    | Decrement
-    | Highlight String
+    = Increment -- forward one pick
+    | Decrement -- backward one pick
+    | Highlight String -- hover a card to highlight it
     | ChangeDraftImportUrlField String
     | AcknowledgeParseError
     | SubmitImportDraft
@@ -164,10 +165,11 @@ type Msg
     | IOGotDeleteSetData String -- Successful deletion by set code
     | PortReceiveDoesSetHaveLocalData String
     | OpenCardExplorer String Database.Database
+    | BackToMenu
 
 
-startDraft : DraftMeta -> Database.Database -> ( Model, Cmd Msg )
-startDraft draft database =
+startDraft : Dict String SetLoadStatus -> DraftMeta -> Database.Database -> ( Model, Cmd Msg )
+startDraft sets draft database =
     ( Ready
         { draft = draft.draftData
         , database = database
@@ -183,19 +185,21 @@ startDraft draft database =
             , deckList = False
             }
         , deckSortOrder = Deck.SortByPickNumber
+        , sets = sets
         }
     , Cmd.none
     )
 
 
 openCardExplorer : ChooseSetModel -> Database.Database -> ( Model, Cmd Msg )
-openCardExplorer initFlags database =
+openCardExplorer chooseSet database =
     ( CardExplorer
         { database = database
         , performanceDistributions = calculatePerformanceDistributions (Database.getAll database)
         , highlighted = Nothing
         , flipHighlighted = False
         , sortOrder = SortOrderDefault
+        , sets = chooseSet.sets
         }
     , Cmd.none
     )
@@ -333,7 +337,7 @@ update msg model =
                     in
                     case setData of
                         Just (HasLocalData db) ->
-                            startDraft draft db
+                            startDraft mdl.sets draft db
 
                         _ ->
                             ( Error { error = "You must download the set data for the draft before you can open it. (" ++ draft.setCode ++ ")" }, Cmd.none )
@@ -346,6 +350,14 @@ update msg model =
 
         Ready mdl ->
             case msg of
+                BackToMenu ->
+                    ( ChooseSet
+                        { sets = mdl.sets
+                        , importDraft = EditingImportUrl ""
+                        }
+                    , Cmd.none
+                    )
+
                 Increment ->
                     ( Ready { mdl | draft = Zipper.moveRight mdl.draft }, Cmd.none )
 
@@ -451,6 +463,14 @@ update msg model =
                 SetSortOrder sortOrder ->
                     ( CardExplorer { mdl | sortOrder = sortOrder }, Cmd.none )
 
+                BackToMenu ->
+                    ( ChooseSet
+                        { sets = mdl.sets
+                        , importDraft = EditingImportUrl ""
+                        }
+                    , Cmd.none
+                    )
+
                 _ ->
                     ( CardExplorer mdl, Cmd.none )
 
@@ -502,14 +522,19 @@ viewChooseSet model =
                         , Button.make "Delete" (IODeleteSetData setCode) |> Button.view
                         ]
     in
-    div [ class "w-full h-full bg-slate-100 flex flex-col gap-4 justify-center items-center" ]
-        [ div [ class "max-w-4xl max-h-2xl bg-slate-500 rounded-lg p-6 shadow-xl" ]
-            [ h1 [ class "text-3xl text-white font-medium" ] [ text "Drafter" ]
+    div [ class "mt-2 flex flex-col gap-4 justify-center items-center overflow-y-scroll" ]
+        [ viewMobileWarning
+        , div
+            [ class "max-w-xl bg-slate-500 rounded-lg p-6 shadow-xl" ]
+            [ h2 [ class "text-3xl text-white font-medium" ] [ text "Drafter" ]
             , p [ class "text-white font-medium" ] [ text "Explore sets and analyse your draft events." ]
             , viewDraftURL model
             ]
-        , div [ class "max-w-4xl max-h-2xl bg-slate-500 rounded-lg p-6 shadow-xl" ]
-            [ ul [ class "divide-y divide-slate-600" ]
+        , div [ class "max-w-xl max-h-2xl bg-slate-500 rounded-lg p-6 shadow-xl" ]
+            [ h3 [ class "text-xl text-white font-medium" ] [ text "Set data" ]
+            , p [ class "text-white font-medium" ] [ text "Before analysing a draft, you need to download the data for the sets you want to analyse. After the first download, they are saved in your browser's local storage." ]
+            , p [ class "text-white font-medium" ] [ text "The performance data for each set is updated as new data is available in 17Lands. To make sure you have the latest data, you can delete the set and re-download it." ]
+            , ul [ class "divide-y divide-slate-600" ]
                 (List.map
                     (\s ->
                         li [ class "py-2 text-white flex gap-2 items-center space-between w-full" ] <|
@@ -533,34 +558,50 @@ viewDraftURL model =
     case model.importDraft of
         EditingImportUrl url ->
             div [ class "mt-4" ]
-                [ label [ class "block text-sm font-medium text-white" ] [ text "Enter your 17Lands public event history URL:" ]
-                , input
-                    [ type_ "text"
-                    , onInput ChangeDraftImportUrlField
-                    , value url
+                [ div [ class "mb-2" ]
+                    [ label [ class "block text-sm font-medium text-white" ] [ text "Enter your 17Lands public draft URL:" ]
+                    , input
+                        [ type_ "text"
+                        , onInput ChangeDraftImportUrlField
+                        , value url
+                        , class "w-full"
+                        ]
+                        []
                     ]
-                    []
-                , Button.make "Save" SubmitImportDraft |> Button.view
+                , Button.make "Import draft" SubmitImportDraft |> Button.view
                 ]
 
         ImportDraftParseError e ->
             div [ class "mt-4 text-white" ]
-                [ p [] [ text ("Could not extract draft ID from URL: " ++ e) ]
-                , p [] [ text "Please make sure your URL looks like: https://www.17lands.com/draft/490bda1edc574d71a2768a7d7a415a25" ]
+                [ p [ class "mb-2 bg-red-300 text-black" ] [ text ("Could not extract draft ID from URL: " ++ e) ]
+                , p [ class "mb-2" ] [ text "Please make sure your URL looks like: https://www.17lands.com/draft/490bda1edc574d71a2768a7d7a415a25" ]
+                , Button.make "Try again" AcknowledgeParseError |> Button.view
                 ]
 
         LoadingDraft ->
             div [ class "mt-4" ]
                 [ text "Loading..." ]
 
-        _ ->
-            div [] []
+
+viewHeader : Html Msg
+viewHeader =
+    header [ class "bg-slate-600 p-4 w-full flex justify-between align-center col-span-12" ]
+        [ h1 [ class "text-3xl text-white font-medium" ] [ text "Drafter" ]
+        , Button.make "Home" BackToMenu |> Button.view
+        ]
+
+
+viewMobileWarning : Html Msg
+viewMobileWarning =
+    div [ class "bg-red-300 p-4 w-full md:hidden " ]
+        [ p [] [ text "This app is not optimized for mobile devices. Please use a desktop computer." ] ]
 
 
 viewReady : ReadyModel -> Html Msg
 viewReady model =
-    div [ class "grid grid-cols-12 gap-6 h-full bg-slate-100" ]
-        [ viewSidebar model
+    div [ class "grid grid-cols-12 gap-2 h-full grid-rows-[70px_1fr] bg-slate-100" ]
+        [ viewHeader
+        , viewSidebar model
         , viewDraft model
         , viewHighlightedCard model
         ]
@@ -568,8 +609,9 @@ viewReady model =
 
 viewCardExplorer : CardExplorerModel -> Html Msg
 viewCardExplorer model =
-    div [ class "grid grid-cols-12 gap-6 h-full bg-slate-100" ]
-        [ viewAllCards model
+    div [ class "grid grid-cols-12 gap-2 h-full bg-slate-100 grid-rows-[70px_1fr]" ]
+        [ viewHeader
+        , viewAllCards model
         , viewHighlightedCard model
         ]