Compare commits

...

4 commits

4 changed files with 91 additions and 26 deletions

View file

@ -141,12 +141,19 @@ async def advanced_search(
joins.append("LEFT JOIN copies ON (cards.scryfall_id = copies.scryfall_id)")
constraints.append("copies.id IS NULL")
joins.append("JOIN sets ON (cards.set_code = sets.set_code)")
joins.append("JOIN rarities ON (cards.rarity = rarities.rarity)")
query = " ".join(
[
"SELECT cards.* FROM cards",
" ".join(joins),
"WHERE" if constraints else "",
" AND ".join(constraints),
"ORDER BY rarities.rarity_ord DESC",
", length(cards.color_identity) DESC",
", CASE ",
" WHEN length(cards.color_identity) > 0 THEN '0'"
" ELSE cards.color_identity END ASC",
", cards.name ASC",
f"LIMIT {offset},{limit}",
]
)

View file

@ -118,7 +118,7 @@ expansion_string = (
parsy.regex(r"[a-zA-Z0-9]+").map(lambda s: s.upper()).desc("expansion set code")
)
is_expansion = lstring_from("e", "s") >> matches >> expansion_string.map(IsExpansion)
is_expansion = lstring_from("e", "expansion", "s", "set") >> matches >> expansion_string.map(IsExpansion)
in_expansion = lstring("in") >> matches >> expansion_string.map(InExpansion)

View file

@ -65,7 +65,9 @@ class SearchHandler(tornado.web.RequestHandler):
search,
limit=limit + 1,
offset=limit * (page - 1),
in_collection=in_collection,
in_collection=in_collection in ("yes", "true")
if in_collection
else None,
)
has_more = cards and len(cards) > limit
self.set_header("Content-Type", "application/json")

View file

@ -3,6 +3,7 @@ module App exposing (main)
import Browser
import Browser.Dom
import Browser.Events
import Browser.Navigation
import Dict
import Element as E
import Element.Background as Background
@ -18,6 +19,8 @@ import Regex
import Task
import Url
import Url.Builder
import Url.Parser exposing ((</>), (<?>))
import Url.Parser.Query
type alias Window =
@ -41,7 +44,8 @@ type alias Card =
type alias Model =
{ viewport : Window
{ navigationKey : Browser.Navigation.Key
, viewport : Window
, criteria : Criteria
, cardPage : Maybe (ResultPage Card)
}
@ -130,22 +134,26 @@ expectPaginatedJson toMsg decoder =
Err (Http.BadBody (Json.Decode.errorToString err))
searchQuery : Criteria -> List Url.Builder.QueryParameter
searchQuery criteria =
[ Url.Builder.string "q" criteria.query
, Url.Builder.string "in_collection"
(if criteria.ownedOnly then
"yes"
else
""
)
]
search : Criteria -> Cmd Msg
search criteria =
Http.get
{ url =
Url.Builder.absolute
[ "search" ]
[ Url.Builder.string "q" criteria.query
, Url.Builder.string "in_collection"
(if criteria.ownedOnly then
"yes"
else
""
)
, Url.Builder.int "limit" 18
]
(Url.Builder.int "limit" 18 :: searchQuery criteria)
, expect = expectPaginatedJson FoundCards decodeCard
}
@ -167,13 +175,45 @@ decodeCard =
|> JDP.required "rarity" Json.Decode.string
init : Json.Decode.Value -> url -> key -> ( Model, Cmd Msg )
init _ _ _ =
parseUrl : Url.Parser.Parser (Criteria -> a) a
parseUrl =
let
criteria =
query =
Url.Parser.Query.string "q"
|> Url.Parser.Query.map (Maybe.withDefault "")
inCollection =
Url.Parser.Query.enum "in_collection"
(Dict.fromList
[ ( "true", True )
, ( "false", False )
, ( "yes", True )
, ( "no", False )
]
)
|> Url.Parser.Query.map (Maybe.withDefault True)
in
Url.Parser.top <?> Url.Parser.Query.map2 Criteria query inCollection
criteriaFromUrl : Url.Url -> Criteria
criteriaFromUrl url =
let
emptyCriteria =
{ query = "", ownedOnly = True }
in
( { viewport = { width = 1280, height = 720 }
Url.Parser.parse parseUrl url
|> Maybe.withDefault emptyCriteria
init : Json.Decode.Value -> Url.Url -> Browser.Navigation.Key -> ( Model, Cmd Msg )
init _ url key =
let
criteria =
criteriaFromUrl url
in
( { navigationKey = key
, viewport = { width = 1280, height = 720 }
, criteria = criteria
, cardPage = Nothing
}
@ -191,14 +231,18 @@ init _ _ _ =
)
updateCriteria : CriteriaMsg -> Criteria -> Criteria
updateCriteria : CriteriaMsg -> Criteria -> ( Criteria, Cmd Msg )
updateCriteria msg model =
case msg of
UpdateName text ->
{ model | query = text }
( { model | query = text }, Cmd.none )
UpdateOwnedOnly value ->
{ model | ownedOnly = value }
let
newCriteria =
{ model | ownedOnly = value }
in
( newCriteria, search newCriteria )
updateCardPage cardpage newCards =
@ -208,8 +252,12 @@ updateCardPage cardpage newCards =
update : Msg -> Model -> ( Model, Cmd Msg )
update msg model =
case msg of
UrlChanged _ ->
( model, Cmd.none )
UrlChanged url ->
let
criteria =
criteriaFromUrl url
in
( { model | criteria = criteria }, search criteria )
LinkClicked _ ->
( model, Cmd.none )
@ -218,12 +266,20 @@ update msg model =
( { model | viewport = viewport }, Cmd.none )
UpdateCriteria criteriaMsg ->
( { model | criteria = updateCriteria criteriaMsg model.criteria }
, Cmd.none
)
let
( newCriteria, cmd ) =
updateCriteria criteriaMsg model.criteria
in
( { model | criteria = newCriteria }, cmd )
Search ->
( model, search model.criteria )
( model
, Cmd.batch
[ search model.criteria
, Browser.Navigation.pushUrl model.navigationKey <|
Url.Builder.relative [] (searchQuery model.criteria)
]
)
GetPage url ->
( model, loadPage url )