summaryrefslogtreecommitdiff
path: root/elm/ProducerEdit.elm
blob: f301d20c33679976c7d0a81813a61d27acdf73d5 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
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 ()