{- Copyright 2020 Eike K. & Contributors SPDX-License-Identifier: AGPL-3.0-or-later -} module Comp.BookmarkManage exposing (Model, Msg, init, loadBookmarks, update, view) import Api import Api.Model.BasicResult exposing (BasicResult) import Comp.Basic as B import Comp.BookmarkQueryForm import Comp.BookmarkTable import Comp.ItemDetail.Model exposing (Msg(..)) import Comp.MenuBar as MB import Data.Bookmarks exposing (AllBookmarks) 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.BookmarkManage exposing (Texts) import Page exposing (Page(..)) import Styles as S type FormError = FormErrorNone | FormErrorHttp Http.Error | FormErrorInvalid | FormErrorSubmit String type ViewMode = Table | Form type DeleteConfirm = DeleteConfirmOff | DeleteConfirmOn type alias Model = { viewMode : ViewMode , bookmarks : AllBookmarks , formModel : Comp.BookmarkQueryForm.Model , loading : Bool , formError : FormError , deleteConfirm : DeleteConfirm } init : Flags -> ( Model, Cmd Msg ) init flags = let ( fm, fc ) = Comp.BookmarkQueryForm.init in ( { viewMode = Table , bookmarks = Data.Bookmarks.empty , formModel = fm , loading = False , formError = FormErrorNone , deleteConfirm = DeleteConfirmOff } , Cmd.batch [ Cmd.map FormMsg fc , Api.getBookmarks flags LoadBookmarksResp ] ) type Msg = LoadBookmarks | TableMsg Comp.BookmarkTable.Msg | FormMsg Comp.BookmarkQueryForm.Msg | InitNewBookmark | SetViewMode ViewMode | Submit | RequestDelete | CancelDelete | DeleteBookmarkNow String | LoadBookmarksResp (Result Http.Error AllBookmarks) | AddBookmarkResp (Result Http.Error BasicResult) | UpdateBookmarkResp (Result Http.Error BasicResult) | DeleteBookmarkResp (Result Http.Error BasicResult) loadBookmarks : Msg loadBookmarks = LoadBookmarks --- update update : Flags -> Msg -> Model -> ( Model, Cmd Msg, Sub Msg ) update flags msg model = case msg of InitNewBookmark -> let ( bm, bc ) = Comp.BookmarkQueryForm.init nm = { model | viewMode = Form , formError = FormErrorNone , formModel = bm } in ( nm, Cmd.map FormMsg bc, Sub.none ) SetViewMode vm -> ( { model | viewMode = vm, formError = FormErrorNone } , if vm == Table then Api.getBookmarks flags LoadBookmarksResp else Cmd.none , Sub.none ) FormMsg lm -> let ( fm, fc, fs ) = Comp.BookmarkQueryForm.update flags lm model.formModel in ( { model | formModel = fm, formError = FormErrorNone } , Cmd.map FormMsg fc , Sub.map FormMsg fs ) TableMsg lm -> let action = Comp.BookmarkTable.update lm in case action of Comp.BookmarkTable.Edit bookmark -> let ( bm, bc ) = Comp.BookmarkQueryForm.initWith bookmark in ( { model | viewMode = Form , formError = FormErrorNone , formModel = bm } , Cmd.map FormMsg bc , Sub.none ) RequestDelete -> ( { model | deleteConfirm = DeleteConfirmOn }, Cmd.none, Sub.none ) CancelDelete -> ( { model | deleteConfirm = DeleteConfirmOff }, Cmd.none, Sub.none ) DeleteBookmarkNow id -> ( { model | deleteConfirm = DeleteConfirmOff, loading = True } , Api.deleteBookmark flags id DeleteBookmarkResp , Sub.none ) LoadBookmarks -> ( { model | loading = True } , Api.getBookmarks flags LoadBookmarksResp , Sub.none ) LoadBookmarksResp (Ok list) -> ( { model | loading = False, bookmarks = list, formError = FormErrorNone } , Cmd.none , Sub.none ) LoadBookmarksResp (Err err) -> ( { model | loading = False, formError = FormErrorHttp err }, Cmd.none, Sub.none ) Submit -> case Comp.BookmarkQueryForm.get model.formModel of Just data -> if data.id /= "" then ( { model | loading = True }, Api.updateBookmark flags data AddBookmarkResp, Sub.none ) else ( { model | loading = True }, Api.addBookmark flags data AddBookmarkResp, Sub.none ) Nothing -> ( { model | formError = FormErrorInvalid }, Cmd.none, Sub.none ) AddBookmarkResp (Ok res) -> if res.success then ( { model | loading = True, viewMode = Table }, Api.getBookmarks flags LoadBookmarksResp, Sub.none ) else ( { model | loading = False, formError = FormErrorSubmit res.message }, Cmd.none, Sub.none ) AddBookmarkResp (Err err) -> ( { model | loading = False, formError = FormErrorHttp err }, Cmd.none, Sub.none ) UpdateBookmarkResp (Ok res) -> if res.success then ( model, Api.getBookmarks flags LoadBookmarksResp, Sub.none ) else ( { model | loading = False, formError = FormErrorSubmit res.message }, Cmd.none, Sub.none ) UpdateBookmarkResp (Err err) -> ( { model | loading = False, formError = FormErrorHttp err }, Cmd.none, Sub.none ) DeleteBookmarkResp (Ok res) -> if res.success then update flags (SetViewMode Table) { model | loading = False } else ( { model | formError = FormErrorSubmit res.message, loading = False }, Cmd.none, Sub.none ) DeleteBookmarkResp (Err err) -> ( { model | formError = FormErrorHttp err, loading = False }, Cmd.none, Sub.none ) --- view view : Texts -> UiSettings -> Flags -> Model -> Html Msg view texts settings flags model = if model.viewMode == Table then viewTable texts model else viewForm texts settings flags model viewTable : Texts -> Model -> Html Msg viewTable texts model = let ( user, coll ) = List.partition .personal model.bookmarks.bookmarks in div [ class "flex flex-col" ] [ MB.view { start = [] , end = [ MB.PrimaryButton { tagger = InitNewBookmark , title = texts.createNewBookmark , icon = Just "fa fa-plus" , label = texts.newBookmark } ] , rootClasses = "mb-4" , sticky = True } , div [ class "flex flex-col" , classList [ ( "hidden", user == [] ) ] ] [ h3 [ class S.header3 ] [ text texts.userBookmarks ] , Html.map TableMsg (Comp.BookmarkTable.view texts.bookmarkTable user) ] , div [ class "flex flex-col mt-3" , classList [ ( "hidden", coll == [] ) ] ] [ h3 [ class S.header3 ] [ text texts.collectiveBookmarks ] , Html.map TableMsg (Comp.BookmarkTable.view texts.bookmarkTable coll) ] , B.loadingDimmer { label = "" , active = model.loading } ] viewForm : Texts -> UiSettings -> Flags -> Model -> Html Msg viewForm texts _ _ model = let newBookmark = model.formModel.bookmark.id == "" isValid = Comp.BookmarkQueryForm.get model.formModel /= Nothing in div [] [ Html.form [] [ if newBookmark then h1 [ class S.header2 ] [ text texts.createNewBookmark ] else h1 [ class S.header2 ] [ text (Comp.BookmarkQueryForm.getName model.formModel |> Maybe.withDefault "") ] , MB.view { start = [ MB.CustomElement <| B.primaryButton { handler = onClick Submit , title = texts.basics.submitThisForm , icon = "fa fa-save" , label = texts.basics.submit , disabled = not isValid , attrs = [ href "#" ] } , MB.SecondaryButton { tagger = SetViewMode Table , title = texts.basics.backToList , icon = Just "fa fa-arrow-left" , label = texts.basics.cancel } ] , end = if not newBookmark then [ MB.DeleteButton { tagger = RequestDelete , title = texts.deleteThisBookmark , icon = Just "fa fa-trash" , label = texts.basics.delete } ] else [] , rootClasses = "mb-4" , sticky = True } , div [ classList [ ( "hidden", model.formError == FormErrorNone ) ] , class "my-2" , class S.errorMessage ] [ case model.formError of FormErrorNone -> text "" FormErrorHttp err -> text (texts.httpError err) FormErrorInvalid -> text texts.correctFormErrors FormErrorSubmit m -> text m ] , div [] [ Html.map FormMsg (Comp.BookmarkQueryForm.view texts.bookmarkForm model.formModel) ] , B.loadingDimmer { active = model.loading , label = texts.basics.loading } , B.contentDimmer (model.deleteConfirm == DeleteConfirmOn) (div [ class "flex flex-col" ] [ div [ class "text-lg" ] [ i [ class "fa fa-info-circle mr-2" ] [] , text texts.reallyDeleteBookmark ] , div [ class "mt-4 flex flex-row items-center" ] [ B.deleteButton { label = texts.basics.yes , icon = "fa fa-check" , disabled = False , handler = onClick (DeleteBookmarkNow model.formModel.bookmark.id) , attrs = [ href "#" ] } , B.secondaryButton { label = texts.basics.no , icon = "fa fa-times" , disabled = False , handler = onClick CancelDelete , attrs = [ href "#", class "ml-2" ] } ] ] ) ] ]