{- Copyright 2020 Eike K. & Contributors SPDX-License-Identifier: AGPL-3.0-or-later -} module Comp.NotificationHookManage exposing ( Model , Msg , init , update , view ) import Api import Api.Model.BasicResult exposing (BasicResult) import Api.Model.NotificationHook exposing (NotificationHook) import Comp.Basic as B import Comp.MenuBar as MB import Comp.NotificationHookForm import Comp.NotificationHookTable import Data.Flags exposing (Flags) import Data.UiSettings exposing (UiSettings) import Html exposing (..) import Html.Attributes exposing (..) import Html.Events exposing (onClick) import Http import Messages.Comp.NotificationHookManage exposing (Texts) import Styles as S type alias Model = { listModel : Comp.NotificationHookTable.Model , detailModel : Maybe Comp.NotificationHookForm.Model , items : List NotificationHook , deleteConfirm : DeleteConfirm , loading : Bool , formState : FormState , jsonFilterError : Maybe String } type DeleteConfirm = DeleteConfirmOff | DeleteConfirmOn type SubmitType = SubmitDelete | SubmitUpdate | SubmitCreate type FormState = FormStateInitial | FormErrorHttp Http.Error | FormSubmitSuccessful SubmitType | FormErrorSubmit String | FormErrorInvalid type Msg = TableMsg Comp.NotificationHookTable.Msg | DetailMsg Comp.NotificationHookForm.Msg | GetDataResp (Result Http.Error (List NotificationHook)) | SubmitResp SubmitType (Result Http.Error BasicResult) | NewHookInit | BackToTable | Submit | RequestDelete | CancelDelete | DeleteHookNow String | VerifyFilterResp NotificationHook (Result Http.Error BasicResult) initModel : Model initModel = { listModel = Comp.NotificationHookTable.init , detailModel = Nothing , items = [] , loading = False , formState = FormStateInitial , deleteConfirm = DeleteConfirmOff , jsonFilterError = Nothing } initCmd : Flags -> Cmd Msg initCmd flags = Api.getHooks flags GetDataResp init : Flags -> ( Model, Cmd Msg ) init flags = ( initModel, initCmd flags ) --- Update update : Flags -> Msg -> Model -> ( Model, Cmd Msg ) update flags msg model = case msg of VerifyFilterResp hook (Ok res) -> if res.success then postHook flags hook model else ( { model | loading = False , formState = FormErrorInvalid , jsonFilterError = Just res.message } , Cmd.none ) VerifyFilterResp _ (Err err) -> ( { model | formState = FormErrorHttp err } , Cmd.none ) GetDataResp (Ok res) -> ( { model | items = res , formState = FormStateInitial } , Cmd.none ) GetDataResp (Err err) -> ( { model | formState = FormErrorHttp err } , Cmd.none ) TableMsg lm -> let ( mm, action ) = Comp.NotificationHookTable.update flags lm model.listModel ( detail, cmd ) = case action of Comp.NotificationHookTable.NoAction -> ( Nothing, Cmd.none ) Comp.NotificationHookTable.EditAction hook -> let ( dm, dc ) = Comp.NotificationHookForm.initWith flags hook in ( Just dm, Cmd.map DetailMsg dc ) in ( { model | listModel = mm , detailModel = detail } , cmd ) DetailMsg lm -> case model.detailModel of Just dm -> let ( mm, mc ) = Comp.NotificationHookForm.update flags lm dm in ( { model | detailModel = Just mm } , Cmd.map DetailMsg mc ) Nothing -> ( model, Cmd.none ) SubmitResp submitType (Ok res) -> ( { model | formState = if res.success then FormSubmitSuccessful submitType else FormErrorSubmit res.message , detailModel = if submitType == SubmitDelete then Nothing else model.detailModel , loading = False } , if submitType == SubmitDelete then initCmd flags else Cmd.none ) SubmitResp _ (Err err) -> ( { model | formState = FormErrorHttp err, loading = False } , Cmd.none ) NewHookInit -> let ( mm, mc ) = Comp.NotificationHookForm.init flags in ( { model | detailModel = Just mm }, Cmd.map DetailMsg mc ) BackToTable -> ( { model | detailModel = Nothing }, initCmd flags ) Submit -> case model.detailModel of Just dm -> case Comp.NotificationHookForm.getHook dm of Just data -> case data.eventFilter of Nothing -> postHook flags data model Just jf -> ( { model | loading = True }, Api.verifyJsonFilter flags jf (VerifyFilterResp data) ) Nothing -> ( { model | formState = FormErrorInvalid }, Cmd.none ) Nothing -> ( model, Cmd.none ) RequestDelete -> ( { model | deleteConfirm = DeleteConfirmOn }, Cmd.none ) CancelDelete -> ( { model | deleteConfirm = DeleteConfirmOff }, Cmd.none ) DeleteHookNow id -> ( { model | deleteConfirm = DeleteConfirmOff, loading = True } , Api.deleteHook flags id (SubmitResp SubmitDelete) ) postHook : Flags -> NotificationHook -> Model -> ( Model, Cmd Msg ) postHook flags hook model = if hook.id == "" then ( { model | loading = True }, Api.createHook flags hook (SubmitResp SubmitCreate) ) else ( { model | loading = True }, Api.updateHook flags hook (SubmitResp SubmitUpdate) ) --- View2 view : Texts -> UiSettings -> Model -> Html Msg view texts settings model = div [ class "flex flex-col" ] (case model.detailModel of Just msett -> viewForm texts settings model msett Nothing -> viewList texts model ) viewState : Texts -> Model -> Html Msg viewState texts model = div [ classList [ ( S.errorMessage, not (isSuccess model.formState) ) , ( S.successMessage, isSuccess model.formState ) , ( "hidden", model.formState == FormStateInitial ) ] , class "mb-2" ] [ case model.formState of FormStateInitial -> text "" FormSubmitSuccessful SubmitCreate -> text texts.hookCreated FormSubmitSuccessful SubmitUpdate -> text texts.hookUpdated FormSubmitSuccessful SubmitDelete -> text texts.hookDeleted FormErrorSubmit m -> text m FormErrorHttp err -> text (texts.httpError err) FormErrorInvalid -> case model.jsonFilterError of Just m -> text (texts.invalidJsonFilter m) Nothing -> text texts.formInvalid ] isSuccess : FormState -> Bool isSuccess state = case state of FormSubmitSuccessful _ -> True _ -> False viewForm : Texts -> UiSettings -> Model -> Comp.NotificationHookForm.Model -> List (Html Msg) viewForm texts settings outerModel model = let newHook = model.hook.id == "" in [ h1 [ class S.header2 ] [ if newHook then text texts.addWebhook else text texts.updateWebhook ] , MB.view { start = [ MB.CustomElement <| B.primaryButton { handler = onClick Submit , title = texts.basics.submitThisForm , icon = "fa fa-save" , label = texts.basics.submit , disabled = False , attrs = [ href "#" ] } , MB.SecondaryButton { tagger = BackToTable , title = texts.basics.backToList , icon = Just "fa fa-arrow-left" , label = texts.basics.backToList } ] , end = if not newHook then [ MB.DeleteButton { tagger = RequestDelete , title = texts.deleteThisHook , icon = Just "fa fa-trash" , label = texts.basics.delete } ] else [] , rootClasses = "mb-4" , sticky = True } , div [ class "mt-2" ] [ viewState texts outerModel ] , Html.map DetailMsg (Comp.NotificationHookForm.view texts.notificationForm settings model) , B.loadingDimmer { active = outerModel.loading , label = texts.basics.loading } , B.contentDimmer (outerModel.deleteConfirm == DeleteConfirmOn) (div [ class "flex flex-col" ] [ div [ class "text-lg" ] [ i [ class "fa fa-info-circle mr-2" ] [] , text texts.reallyDeleteHook ] , div [ class "mt-4 flex flex-row items-center" ] [ B.deleteButton { label = texts.basics.yes , icon = "fa fa-check" , disabled = False , handler = onClick (DeleteHookNow model.hook.id) , attrs = [ href "#" ] } , B.secondaryButton { label = texts.basics.no , icon = "fa fa-times" , disabled = False , handler = onClick CancelDelete , attrs = [ href "#", class "ml-2" ] } ] ] ) ] viewList : Texts -> Model -> List (Html Msg) viewList texts model = [ MB.view { start = [] , end = [ MB.PrimaryButton { tagger = NewHookInit , title = texts.newHook , icon = Just "fa fa-plus" , label = texts.newHook } ] , rootClasses = "mb-4" , sticky = True } , Html.map TableMsg (Comp.NotificationHookTable.view texts.notificationTable model.listModel model.items ) ]