summaryrefslogtreecommitdiff
path: root/elm3/User/Settings.elm
diff options
context:
space:
mode:
Diffstat (limited to 'elm3/User/Settings.elm')
-rw-r--r--elm3/User/Settings.elm206
1 files changed, 206 insertions, 0 deletions
diff --git a/elm3/User/Settings.elm b/elm3/User/Settings.elm
new file mode 100644
index 00000000..538225ca
--- /dev/null
+++ b/elm3/User/Settings.elm
@@ -0,0 +1,206 @@
+module User.Settings exposing (main)
+
+import Bitwise exposing (..)
+import Html exposing (..)
+import Html.Attributes exposing (..)
+import Html.Events exposing (..)
+import Browser
+import Browser.Navigation exposing (reload)
+import Lib.Html exposing (..)
+import Lib.Gen exposing (..)
+import Lib.Api as Api
+
+
+main : Program UserEdit Model Msg
+main = Browser.element
+ { init = init
+ , view = view
+ , update = update
+ , subscriptions = always Sub.none
+ }
+
+
+type alias Model =
+ { state : Api.State
+ , saved : Bool
+ , data : UserEdit
+ , cpass : Bool
+ , pass1 : String
+ , pass2 : String
+ , opass : String
+ , passNeq : Bool
+ }
+
+
+init : UserEdit -> (Model, Cmd Msg)
+init d =
+ ({state = Api.Normal
+ , saved = False
+ , data = d
+ , cpass = False
+ , pass1 = ""
+ , pass2 = ""
+ , opass = ""
+ , passNeq = False
+ }, Cmd.none)
+
+
+encode : Model -> UserEditSend
+encode model =
+ { hide_list = model.data.hide_list
+ , ign_votes = model.data.ign_votes
+ , mail = model.data.mail
+ , password = if model.cpass then Just { old = model.opass, new = model.pass1 } else Nothing
+ , perm = model.data.perm
+ , show_nsfw = model.data.show_nsfw
+ , spoilers = model.data.spoilers
+ , tags_all = model.data.tags_all
+ , tags_cont = model.data.tags_cont
+ , tags_ero = model.data.tags_ero
+ , tags_tech = model.data.tags_tech
+ , traits_sexual = model.data.traits_sexual
+ , username = model.data.username
+ }
+
+
+type UpdateMsg
+ = Username String
+ | Email String
+ | Perm Int Bool
+ | IgnVotes Bool
+ | HideList Bool
+ | ShowNsfw Bool
+ | TraitsSexual Bool
+ | Spoilers String
+ | TagsAll Bool
+ | TagsCont Bool
+ | TagsEro Bool
+ | TagsTech Bool
+
+type Msg
+ = Submit
+ | Submitted Api.Response
+ | Set UpdateMsg
+ | CPass Bool
+ | OPass String
+ | Pass1 String
+ | Pass2 String
+
+
+updateField : UpdateMsg -> UserEdit -> UserEdit
+updateField msg model =
+ case msg of
+ Username s -> { model | username = s }
+ Email s -> { model | mail = s }
+ Perm n b -> { model | perm = if b then or model.perm n else and model.perm (complement n) }
+ IgnVotes b -> { model | ign_votes = b }
+ HideList b -> { model | hide_list = b }
+ ShowNsfw b -> { model | show_nsfw = b }
+ TraitsSexual b -> { model | traits_sexual = b }
+ Spoilers s -> { model | spoilers = Maybe.withDefault model.spoilers (String.toInt s) }
+ TagsAll b -> { model | tags_all = b }
+ TagsCont b -> { model | tags_cont = b }
+ TagsEro b -> { model | tags_ero = b }
+ TagsTech b -> { model | tags_tech = b }
+
+
+update : Msg -> Model -> (Model, Cmd Msg)
+update msg model =
+ case msg of
+ Set m -> ({ model | saved = False, data = updateField m model.data }, Cmd.none)
+ CPass b -> ({ model | saved = False, cpass = b }, Cmd.none)
+ OPass s -> ({ model | saved = False, opass = s }, Cmd.none)
+ Pass1 s -> ({ model | saved = False, pass1 = s, passNeq = s /= model.pass2 }, Cmd.none)
+ Pass2 s -> ({ model | saved = False, pass2 = s, passNeq = s /= model.pass1 }, Cmd.none)
+
+ Submit ->
+ let
+ path = "/u" ++ String.fromInt model.data.id ++ "/edit"
+ body = usereditSendEncode (encode model)
+ in ({ model | state = Api.Loading }, Api.post path body Submitted)
+
+ Submitted (Api.Success) ->
+ ( { model | state = Api.Normal, saved = True, cpass = False, opass = "", pass1 = "", pass2 = "" }
+ , if model.cpass then reload else Cmd.none
+ )
+ Submitted r -> ({ model | state = Api.Error r }, Cmd.none)
+
+
+view : Model -> Html Msg
+view model =
+ form_ Submit (model.state == Api.Loading)
+ [ card "account" "Account info" [] <|
+
+ [ cardRow "General" Nothing <| formGroups
+ [ [ label [ for "username" ] [ text "Username" ]
+ , inputText "username" model.data.username (Set << Username) [required True, maxlength 200, pattern "[a-z0-9-]{2,15}", disabled (not model.data.authmod)]
+ ]
+ , [ label [ for "email" ] [ text "Email address" ]
+ , inputText "email" model.data.mail (Set << Email) [type_ "email", required True, pattern emailPattern]
+ ]
+ ]
+
+ , cardRow "Password" Nothing <| formGroups <|
+ [ label [ class "checkbox" ]
+ [ inputCheck "" model.cpass CPass
+ , text " Change password" ]
+ ]
+ :: if not model.cpass then [] else
+ [ [ label [ class "opass" ] [ text "Current password" ]
+ , inputText "opass" model.opass OPass [type_ "password", required True, minlength 4, maxlength 500]
+ ]
+ , [ label [ class "pass1" ] [ text "New password" ]
+ , inputText "pass1" model.pass1 Pass1 [type_ "password", required True, minlength 4, maxlength 500]
+ ]
+ , [ label [ class "pass2" ] [ text "Repeat" ]
+ , inputText "pass2" model.pass2 Pass2 [type_ "password", required True, minlength 4, maxlength 500, classList [("is-invalid", model.passNeq)]]
+ , if model.passNeq
+ then div [class "invalid-feedback"]
+ [ text "Passwords do not match." ]
+ else text ""
+ ]
+ ]
+
+ ] ++ if not model.data.authmod then [] else
+ [ cardRow "Mod options" Nothing <| formGroups
+ [ [ label [] [ text "Permissions" ]
+ ] ++ List.map (\(n,s) ->
+ label [ class "checkbox" ] [ inputCheck "" (and model.data.perm n > 0) (Set << Perm n), text (" " ++ s) ]
+ ) userPerms
+ , [ label [] [ text "Other" ]
+ , label [ class "checkbox" ] [ inputCheck "" model.data.ign_votes (Set << IgnVotes), text "Ignore votes in VN statistics" ]
+ ]
+ ]
+ ]
+
+ , card "preferences" "Preferences" [] <|
+
+ [ cardRow "Privacy" Nothing <| formGroup
+ [ label [ class "checkbox" ] [ inputCheck "" model.data.hide_list (Set << HideList), text "Hide my visual novel list, vote list and wishlist" ] ]
+
+ , cardRow "NSFW" Nothing <| formGroups
+ [ [ label [ class "checkbox" ] [ inputCheck "" model.data.show_nsfw (Set << ShowNsfw), text "Disable warnings for images that are not safe for work" ] ]
+ , [ label [ class "checkbox" ] [ inputCheck "" model.data.traits_sexual (Set << TraitsSexual), text "Show sexual traits by default on character pages" ] ]
+ ]
+
+ , cardRow "Spoilers" Nothing <| formGroup
+ [ label [ for "spoilers" ] [ text "Default spoiler level" ]
+ , inputSelect [onInput (Set << Spoilers)] (String.fromInt model.data.spoilers)
+ [ ("0", "Hide spoilers")
+ , ("1", "Show only minor spoilers")
+ , ("2", "Show all spoilers")
+ ]
+ ]
+
+ , cardRow "Tags" Nothing <| formGroups
+ [ [ label [ class "checkbox" ] [ inputCheck "" model.data.tags_all (Set << TagsAll), text "Show all tags by default on visual novel pages (don't summarize)" ] ]
+ , [ label [] [ text "Default tag categories on visual novel pages:" ]
+ , label [ class "chexkbox" ] [ inputCheck "" model.data.tags_cont (Set << TagsCont), text "Content" ]
+ , label [ class "chexkbox" ] [ inputCheck "" model.data.tags_ero (Set << TagsEro ), text "Sexual content" ]
+ , label [ class "chexkbox" ] [ inputCheck "" model.data.tags_tech (Set << TagsTech), text "Technical" ]
+ ]
+ ]
+ ]
+
+ , submitButton (if model.saved then "Saved!" else "Save") model.state (not model.passNeq) False
+ ]