Files
docspell/modules/webapp/src/main/elm/Comp/BoxEdit.elm
2022-01-26 23:26:06 +01:00

475 lines
13 KiB
Elm

{-
Copyright 2020 Eike K. & Contributors
SPDX-License-Identifier: AGPL-3.0-or-later
-}
module Comp.BoxEdit exposing
( BoxAction(..)
, Model
, Msg
, UpdateResult
, init
, update
, view
)
import Comp.Basic as B
import Comp.BoxMessageEdit
import Comp.BoxQueryEdit
import Comp.BoxStatsEdit
import Comp.BoxUploadEdit
import Comp.FixedDropdown
import Comp.MenuBar as MB
import Data.Box exposing (Box)
import Data.BoxContent exposing (BoxContent(..))
import Data.DropdownStyle as DS
import Data.Flags exposing (Flags)
import Data.UiSettings exposing (UiSettings)
import Html exposing (Html, div, i, input, label, text)
import Html.Attributes exposing (class, classList, placeholder, type_, value)
import Html.Events exposing (onInput, onMouseEnter, onMouseLeave)
import Messages.Comp.BoxEdit exposing (Texts)
import Styles as S
type alias Model =
{ box : Box
, content : ContentModel
, colspanModel : Comp.FixedDropdown.Model Int
, focus : Bool
, deleteRequested : Bool
}
type ContentModel
= ContentMessage Comp.BoxMessageEdit.Model
| ContentQuery Comp.BoxQueryEdit.Model
| ContentStats Comp.BoxStatsEdit.Model
| ContentUpload Comp.BoxUploadEdit.Model
type Msg
= ToggleVisible
| ToggleDecoration
| SetName String
| ColspanMsg (Comp.FixedDropdown.Msg Int)
| MessageMsg Comp.BoxMessageEdit.Msg
| UploadMsg Comp.BoxUploadEdit.Msg
| QueryMsg Comp.BoxQueryEdit.Msg
| StatsMsg Comp.BoxStatsEdit.Msg
| SetFocus Bool
| RequestDelete
| DeleteBox
| CancelDelete
| MoveLeft
| MoveRight
init : Flags -> Box -> ( Model, Cmd Msg, Sub Msg )
init flags box =
let
( cm, cc, cs ) =
contentInit flags box.content
in
( { box = box
, content = cm
, colspanModel = Comp.FixedDropdown.init [ 1, 2, 3, 4, 5 ]
, focus = False
, deleteRequested = False
}
, cc
, cs
)
contentInit : Flags -> BoxContent -> ( ContentModel, Cmd Msg, Sub Msg )
contentInit flags content =
case content of
BoxMessage data ->
( ContentMessage (Comp.BoxMessageEdit.init data), Cmd.none, Sub.none )
BoxUpload data ->
let
( um, uc ) =
Comp.BoxUploadEdit.init flags data
in
( ContentUpload um, Cmd.map UploadMsg uc, Sub.none )
BoxQuery data ->
let
( qm, qc, qs ) =
Comp.BoxQueryEdit.init flags data
in
( ContentQuery qm, Cmd.map QueryMsg qc, Sub.map QueryMsg qs )
BoxStats data ->
let
( qm, qc, qs ) =
Comp.BoxStatsEdit.init flags data
in
( ContentStats qm, Cmd.map StatsMsg qc, Sub.map StatsMsg qs )
--- Update
type BoxAction
= BoxNoAction
| BoxMoveLeft
| BoxMoveRight
| BoxDelete
type alias UpdateResult =
{ model : Model
, cmd : Cmd Msg
, sub : Sub Msg
, action : BoxAction
}
update : Flags -> Msg -> Model -> UpdateResult
update flags msg model =
case msg of
MessageMsg lm ->
case model.content of
ContentMessage m ->
let
( mm, data ) =
Comp.BoxMessageEdit.update lm m
boxn =
model.box
box_ =
{ boxn | content = BoxMessage data }
in
{ model = { model | content = ContentMessage mm, box = box_ }
, cmd = Cmd.none
, sub = Sub.none
, action = BoxNoAction
}
_ ->
unit model
UploadMsg lm ->
case model.content of
ContentUpload m ->
let
( um, data ) =
Comp.BoxUploadEdit.update lm m
boxn =
model.box
box_ =
{ boxn | content = BoxUpload data }
in
{ model = { model | content = ContentUpload um, box = box_ }
, cmd = Cmd.none
, sub = Sub.none
, action = BoxNoAction
}
_ ->
unit model
QueryMsg lm ->
case model.content of
ContentQuery m ->
let
result =
Comp.BoxQueryEdit.update flags lm m
boxn =
model.box
box_ =
{ boxn | content = BoxQuery result.data }
in
{ model = { model | content = ContentQuery result.model, box = box_ }
, cmd = Cmd.map QueryMsg result.cmd
, sub = Sub.map QueryMsg result.sub
, action = BoxNoAction
}
_ ->
unit model
StatsMsg lm ->
case model.content of
ContentStats m ->
let
result =
Comp.BoxStatsEdit.update flags lm m
boxn =
model.box
box_ =
{ boxn | content = BoxStats result.data }
in
{ model = { model | content = ContentStats result.model, box = box_ }
, cmd = Cmd.map StatsMsg result.cmd
, sub = Sub.map StatsMsg result.sub
, action = BoxNoAction
}
_ ->
unit model
ColspanMsg lm ->
let
( cm, num ) =
Comp.FixedDropdown.update lm model.colspanModel
boxn =
model.box
box_ =
{ boxn | colspan = Maybe.withDefault boxn.colspan num }
in
unit { model | box = box_, colspanModel = cm }
ToggleVisible ->
let
box =
model.box
box_ =
{ box | visible = not box.visible }
in
unit { model | box = box_ }
ToggleDecoration ->
let
box =
model.box
box_ =
{ box | decoration = not box.decoration }
in
unit { model | box = box_ }
SetName name ->
let
box =
model.box
box_ =
{ box | name = name }
in
unit { model | box = box_ }
SetFocus flag ->
unit { model | focus = flag }
RequestDelete ->
unit { model | deleteRequested = True }
DeleteBox ->
UpdateResult model Cmd.none Sub.none BoxDelete
CancelDelete ->
unit { model | deleteRequested = False }
MoveLeft ->
UpdateResult model Cmd.none Sub.none BoxMoveLeft
MoveRight ->
UpdateResult model Cmd.none Sub.none BoxMoveRight
unit : Model -> UpdateResult
unit model =
UpdateResult model Cmd.none Sub.none BoxNoAction
--- View
view : Texts -> Flags -> UiSettings -> Model -> Html Msg
view texts flags settings model =
div
[ class (S.box ++ "rounded md:relative")
, class " h-full"
, classList [ ( "ring ring-opacity-50 ring-blue-600 dark:ring-sky-600", model.focus ) ]
, onMouseEnter (SetFocus True)
, onMouseLeave (SetFocus False)
]
[ B.contentDimmer model.deleteRequested
(div [ class "flex flex-col" ]
[ div [ class "text-xl" ]
[ i [ class "fa fa-info-circle mr-2" ] []
, text texts.reallyDeleteBox
]
, div [ class "mt-4 flex flex-row items-center space-x-2" ]
[ MB.viewItem <|
MB.DeleteButton
{ tagger = DeleteBox
, title = ""
, label = texts.basics.yes
, icon = Just "fa fa-check"
}
, MB.viewItem <|
MB.SecondaryButton
{ tagger = CancelDelete
, title = ""
, label = texts.basics.no
, icon = Just "fa fa-times"
}
]
]
)
, boxHeader texts model
, formHeader (texts.boxContent.forContent model.box.content)
, div [ class "mb-4 pl-2" ]
[ metaForm texts flags model
]
, formHeader texts.contentProperties
, div [ class "pl-4 pr-2 py-2 h-5/6" ]
[ boxContent texts flags settings model
]
]
formHeader : String -> Html msg
formHeader heading =
div
[ class "mx-2 border-b dark:border-slate-500 text-lg mt-1"
]
[ text heading
]
metaForm : Texts -> Flags -> Model -> Html Msg
metaForm texts _ model =
let
colspanCfg =
{ display = String.fromInt
, icon = \_ -> Nothing
, selectPlaceholder = ""
, style = DS.mainStyle
}
in
div [ class "my-1 px-2 " ]
[ div []
[ label [ class S.inputLabel ]
[ text texts.basics.name
]
, input
[ type_ "text"
, placeholder texts.namePlaceholder
, class S.textInput
, value model.box.name
, onInput SetName
]
[]
]
, div [ class "mt-1" ]
[ MB.viewItem <|
MB.Checkbox
{ tagger = \_ -> ToggleVisible
, label = texts.visible
, value = model.box.visible
, id = ""
}
]
, div [ class "mt-1" ]
[ MB.viewItem <|
MB.Checkbox
{ tagger = \_ -> ToggleDecoration
, label = texts.decorations
, value = model.box.decoration
, id = ""
}
]
, div [ class "mt-1" ]
[ label [ class S.inputLabel ]
[ text texts.colspan ]
, Html.map ColspanMsg
(Comp.FixedDropdown.viewStyled2
colspanCfg
False
(Just model.box.colspan)
model.colspanModel
)
]
]
boxHeader : Texts -> Model -> Html Msg
boxHeader texts model =
div
[ class "flex flex-row py-1 bg-blue-50 dark:bg-slate-700 rounded-t"
]
[ div [ class "flex flex-row items-center text-lg tracking-medium italic px-2" ]
[ i
[ class (Data.Box.boxIcon model.box)
, class "mr-2"
]
[]
, text model.box.name
]
, div [ class "flex flex-grow justify-end pr-1" ]
[ MB.viewItem <|
MB.CustomButton
{ tagger = MoveLeft
, title = texts.moveToLeft
, label = ""
, icon = Just "fa fa-arrow-left"
, inputClass =
[ ( S.secondaryBasicButton, True )
, ( "text-xs", True )
]
}
, MB.viewItem <|
MB.CustomButton
{ tagger = MoveRight
, title = texts.moveToRight
, label = ""
, icon = Just "fa fa-arrow-right"
, inputClass =
[ ( S.secondaryBasicButton, True )
, ( "text-xs mr-3", True )
]
}
, MB.viewItem <|
MB.CustomButton
{ tagger = RequestDelete
, title = texts.deleteBox
, label = ""
, icon = Just "fa fa-trash"
, inputClass =
[ ( S.deleteButton, True )
, ( "text-xs", True )
]
}
]
]
boxContent : Texts -> Flags -> UiSettings -> Model -> Html Msg
boxContent texts flags settings model =
case model.content of
ContentMessage m ->
Html.map MessageMsg
(Comp.BoxMessageEdit.view texts.messageEdit m)
ContentUpload m ->
Html.map UploadMsg
(Comp.BoxUploadEdit.view texts.uploadEdit m)
ContentQuery m ->
Html.map QueryMsg
(Comp.BoxQueryEdit.view texts.queryEdit settings m)
ContentStats m ->
Html.map StatsMsg
(Comp.BoxStatsEdit.view texts.statsEdit settings m)