summaryrefslogtreecommitdiff
path: root/elm
diff options
context:
space:
mode:
authorYorhel <git@yorhel.nl>2020-07-19 15:53:28 +0200
committerYorhel <git@yorhel.nl>2020-07-19 15:53:30 +0200
commit52634340d6bad16e0ba922961a334354961bf9a0 (patch)
tree237dec5625979d8d9c0e10dd1299ce45796b8a71 /elm
parentd7767fa0f907e7b2a0a3d879d9000fa137bd81db (diff)
Producers::Edit: v2rw rewrite producer add/edit form
The copy-pasting here is ridiculous. But at the same time, that did allow me to quickly rewrite the form in a single commit. Here's hoping I didn't introduce too many copy-paste errors.
Diffstat (limited to 'elm')
-rw-r--r--elm/Lib/Autocomplete.elm2
-rw-r--r--elm/ProducerEdit.elm231
2 files changed, 232 insertions, 1 deletions
diff --git a/elm/Lib/Autocomplete.elm b/elm/Lib/Autocomplete.elm
index 30a8ee29..5c5dd33d 100644
--- a/elm/Lib/Autocomplete.elm
+++ b/elm/Lib/Autocomplete.elm
@@ -140,7 +140,7 @@ vnSource =
producerSource : SourceConfig m GApi.ApiProducerResult
producerSource =
- { source = Endpoint (\s -> GP.send { search = s })
+ { source = Endpoint (\s -> GP.send { search = [s], hidden = False })
<| \x -> case x of
GApi.ProducerResult e -> Just e
_ -> Nothing
diff --git a/elm/ProducerEdit.elm b/elm/ProducerEdit.elm
new file mode 100644
index 00000000..f301d20c
--- /dev/null
+++ b/elm/ProducerEdit.elm
@@ -0,0 +1,231 @@
+module ProducerEdit exposing (main)
+
+import Html exposing (..)
+import Html.Events exposing (..)
+import Html.Attributes exposing (..)
+import Browser
+import Browser.Navigation exposing (load)
+import Lib.Util exposing (..)
+import Lib.Html exposing (..)
+import Lib.TextPreview as TP
+import Lib.Autocomplete as A
+import Lib.Api as Api
+import Lib.Editsum as Editsum
+import Gen.Producers as GP
+import Gen.ProducerEdit as GPE
+import Gen.Types as GT
+import Gen.Api as GApi
+
+
+main : Program GPE.Recv Model Msg
+main = Browser.element
+ { init = \e -> (init e, Cmd.none)
+ , view = view
+ , update = update
+ , subscriptions = always Sub.none
+ }
+
+type alias Model =
+ { state : Api.State
+ , editsum : Editsum.Model
+ , ptype : String
+ , name : String
+ , original : String
+ , alias : String
+ , lang : String
+ , website : String
+ , lWikidata : Maybe Int
+ , desc : TP.Model
+ , rel : List GPE.RecvRelations
+ , relSearch : A.Model GApi.ApiProducerResult
+ , id : Maybe Int
+ , dupCheck : Bool
+ , dupProds : List GApi.ApiProducerResult
+ }
+
+
+init : GPE.Recv -> Model
+init d =
+ { state = Api.Normal
+ , editsum = { authmod = d.authmod, editsum = TP.bbcode d.editsum, locked = d.locked, hidden = d.hidden }
+ , ptype = d.ptype
+ , name = d.name
+ , original = d.original
+ , alias = d.alias
+ , lang = d.lang
+ , website = d.website
+ , lWikidata = d.l_wikidata
+ , desc = TP.bbcode d.desc
+ , rel = d.relations
+ , relSearch = A.init ""
+ , id = d.id
+ , dupCheck = False
+ , dupProds = []
+ }
+
+
+encode : Model -> GPE.Send
+encode model =
+ { id = model.id
+ , editsum = model.editsum.editsum.data
+ , hidden = model.editsum.hidden
+ , locked = model.editsum.locked
+ , ptype = model.ptype
+ , name = model.name
+ , original = model.original
+ , alias = model.alias
+ , lang = model.lang
+ , website = model.website
+ , l_wikidata = model.lWikidata
+ , desc = model.desc.data
+ , relations = List.map (\p -> { pid = p.pid, relation = p.relation }) model.rel
+ }
+
+prodConfig : A.Config Msg GApi.ApiProducerResult
+prodConfig = { wrap = RelSearch, id = "relationadd", source = A.producerSource }
+
+type Msg
+ = Editsum Editsum.Msg
+ | Submit
+ | Submitted GApi.Response
+ | PType String
+ | Name String
+ | Original String
+ | Alias String
+ | Lang String
+ | Website String
+ | LWikidata (Maybe Int)
+ | Desc TP.Msg
+ | RelDel Int
+ | RelRel Int String
+ | RelSearch (A.Msg GApi.ApiProducerResult)
+ | DupSubmit
+ | DupResults GApi.Response
+
+
+update : Msg -> Model -> (Model, Cmd Msg)
+update msg model =
+ case msg of
+ Editsum m -> let (nm,nc) = Editsum.update m model.editsum in ({ model | editsum = nm }, Cmd.map Editsum nc)
+ PType s -> ({ model | ptype = s }, Cmd.none)
+ Name s -> ({ model | name = s, dupProds = [] }, Cmd.none)
+ Original s -> ({ model | original = s, dupProds = [] }, Cmd.none)
+ Alias s -> ({ model | alias = s, dupProds = [] }, Cmd.none)
+ Lang s -> ({ model | lang = s }, Cmd.none)
+ Website s -> ({ model | website = s }, Cmd.none)
+ LWikidata n-> ({ model | lWikidata = n }, Cmd.none)
+ Desc m -> let (nm,nc) = TP.update m model.desc in ({ model | desc = nm }, Cmd.map Desc nc)
+
+ RelDel idx -> ({ model | rel = delidx idx model.rel }, Cmd.none)
+ RelRel idx rel -> ({ model | rel = modidx idx (\p -> { p | relation = rel }) model.rel }, Cmd.none)
+ RelSearch m ->
+ let (nm, c, res) = A.update prodConfig m model.relSearch
+ in case res of
+ Nothing -> ({ model | relSearch = nm }, c)
+ Just p ->
+ if List.any (\l -> l.pid == p.id) model.rel
+ then ({ model | relSearch = A.clear nm "" }, c)
+ else ({ model | relSearch = A.clear nm "", rel = model.rel ++ [{ pid = p.id, name = p.name, original = p.original, relation = "old" }] }, Cmd.none)
+
+ DupSubmit ->
+ if List.isEmpty model.dupProds
+ then ({ model | state = Api.Loading }, GP.send { hidden = True, search = model.name :: model.original :: String.lines model.alias } DupResults)
+ else ({ model | dupCheck = True, dupProds = [] }, Cmd.none)
+ DupResults (GApi.ProducerResult prods) ->
+ if List.isEmpty prods
+ then ({ model | state = Api.Normal, dupCheck = True, dupProds = [] }, Cmd.none)
+ else ({ model | state = Api.Normal, dupProds = prods }, Cmd.none)
+ DupResults r -> ({ model | state = Api.Error r }, Cmd.none)
+
+ Submit -> ({ model | state = Api.Loading }, GPE.send (encode model) Submitted)
+ Submitted (GApi.Redirect s) -> (model, load s)
+ Submitted r -> ({ model | state = Api.Error r }, Cmd.none)
+
+
+isValid : Model -> Bool
+isValid model = not
+ ( (model.name /= "" && model.name == model.original)
+ || hasDuplicates (List.map (\p -> p.pid) model.rel)
+ )
+
+
+view : Model -> Html Msg
+view model =
+ let
+ titles =
+ [ formField "name::Name (romaji)" [ inputText "name" model.name Name (style "width" "500px" :: GPE.valName) ]
+ , formField "original::Original name"
+ [ inputText "original" model.original Original (style "width" "500px" :: GPE.valOriginal)
+ , if model.name /= "" && model.name == model.original
+ then b [ class "standout" ] [ br [] [], text "Should not be the same as the Name (romaji). Leave blank is the original name is already in the latin alphabet" ]
+ else if model.original /= "" && String.toLower model.name /= String.toLower model.original && not (containsNonLatin model.original)
+ then b [ class "standout" ] [ br [] [], text "Original name does not seem to contain any non-latin characters. Leave this field empty if the name is already in the latin alphabet" ]
+ else text ""
+ ]
+ , formField "alias::Aliases"
+ [ inputTextArea "alias" model.alias Alias (rows 3 :: GPE.valAlias)
+ , br [] []
+ , if hasDuplicates <| String.lines <| String.toLower model.alias
+ then b [ class "standout" ] [ text "List contains duplicate aliases.", br [] [] ]
+ else text ""
+ , text "(Un)official aliases, separated by a newline."
+ ]
+ ]
+
+ geninfo =
+ [ formField "ptype::Type" [ inputSelect "ptype" model.ptype PType [] GT.producerTypes ] ]
+ ++ titles ++
+ [ formField "lang::Primary language" [ inputSelect "lang" model.lang Lang [] GT.languages ]
+ , formField "website::Website" [ inputText "website" model.website Website GPE.valWebsite ]
+ , formField "l_wikidata::Wikidata ID" [ inputWikidata "l_wikidata" model.lWikidata LWikidata ]
+ , formField "desc::Description"
+ [ TP.view "desc" model.desc Desc 600 (style "height" "180px" :: GPE.valDesc) [ b [ class "standout" ] [ text "English please!" ] ] ]
+
+ , tr [ class "newpart" ] [ td [ colspan 2 ] [ text "Database relations" ] ]
+ , formField "Related producers"
+ [ if List.isEmpty model.rel then text ""
+ else table [] <| List.indexedMap (\i p -> tr []
+ [ td [ style "text-align" "right" ] [ b [ class "grayedout" ] [ text <| "p" ++ String.fromInt p.pid ++ ":" ] ]
+ , td [ style "text-align" "right"] [ a [ href <| "/p" ++ String.fromInt p.pid ] [ text p.name ] ]
+ , td []
+ [ text "is an "
+ , inputSelect "" p.relation (RelRel i) [] GT.producerRelations
+ , text " of this producer"
+ ]
+ , td [] [ inputButton "remove" (RelDel i) [] ]
+ ]
+ ) model.rel
+ , A.view prodConfig model.relSearch [placeholder "Add Producer..."]
+ ]
+ ]
+
+ newform () =
+ form_ DupSubmit (model.state == Api.Loading)
+ [ div [ class "mainbox" ] [ h1 [] [ text "Add a new producer" ], table [ class "formtable" ] titles ]
+ , div [ class "mainbox" ]
+ [ if List.isEmpty model.dupProds then text "" else
+ div []
+ [ h1 [] [ text "Possible duplicates" ]
+ , text "The following is a list of producers that match the name(s) you gave. "
+ , text "Please check this list to avoid creating a duplicate producer entry. "
+ , text "Be especially wary of items that have been deleted! To see why an entry has been deleted, click on its title."
+ , ul [] <| List.map (\p -> li []
+ [ a [ href <| "/p" ++ String.fromInt p.id ] [ text p.name ]
+ , if p.hidden then b [ class "standout" ] [ text " (deleted)" ] else text ""
+ ]
+ ) model.dupProds
+ ]
+ , fieldset [ class "submit" ] [ submitButton (if List.isEmpty model.dupProds then "Continue" else "Continue anyway") model.state (isValid model) ]
+ ]
+ ]
+
+ fullform () =
+ form_ Submit (model.state == Api.Loading)
+ [ div [ class "mainbox" ] [ h1 [] [ text "Edit producer" ], table [ class "formtable" ] geninfo ]
+ , div [ class "mainbox" ] [ fieldset [ class "submit" ]
+ [ Html.map Editsum (Editsum.view model.editsum)
+ , submitButton "Submit" model.state (isValid model)
+ ]
+ ]
+ ]
+ in if model.id == Nothing && not model.dupCheck then newform () else fullform ()