From e83bf6b750482b83a78467e930f1da8381f3b883 Mon Sep 17 00:00:00 2001 From: eikek Date: Wed, 26 Jan 2022 21:27:26 +0100 Subject: [PATCH] Editable dashboard --- modules/webapp/src/main/elm/App/Update.elm | 2 +- modules/webapp/src/main/elm/Comp/BoxEdit.elm | 467 ++++++++++++++++++ .../src/main/elm/Comp/BoxMessageEdit.elm | 92 ++++ .../webapp/src/main/elm/Comp/BoxQueryEdit.elm | 190 +++++++ .../webapp/src/main/elm/Comp/BoxQueryView.elm | 53 +- .../src/main/elm/Comp/BoxSearchQueryInput.elm | 292 +++++++++++ .../webapp/src/main/elm/Comp/BoxStatsEdit.elm | 195 ++++++++ .../{BoxSummaryView.elm => BoxStatsView.elm} | 12 +- .../src/main/elm/Comp/BoxUploadEdit.elm | 106 ++++ .../src/main/elm/Comp/BoxUploadView.elm | 7 +- modules/webapp/src/main/elm/Comp/BoxView.elm | 38 +- .../src/main/elm/Comp/DashboardEdit.elm | 458 +++++++++++++++++ .../src/main/elm/Comp/DashboardView.elm | 1 - .../src/main/elm/Comp/ItemColumnDropdown.elm | 86 ++++ .../src/main/elm/Comp/ItemColumnView.elm | 36 ++ modules/webapp/src/main/elm/Comp/MenuBar.elm | 21 +- .../src/main/elm/Comp/PowerSearchInput.elm | 10 + modules/webapp/src/main/elm/Data/Box.elm | 39 +- .../webapp/src/main/elm/Data/BoxContent.elm | 71 ++- modules/webapp/src/main/elm/Data/Icons.elm | 15 +- .../webapp/src/main/elm/Data/ItemColumn.elm | 118 +++++ .../src/main/elm/Messages/Comp/BoxEdit.elm | 67 +++ .../main/elm/Messages/Comp/BoxMessageEdit.elm | 30 ++ .../main/elm/Messages/Comp/BoxQueryEdit.elm | 27 + .../main/elm/Messages/Comp/BoxQueryView.elm | 4 + .../elm/Messages/Comp/BoxSearchQueryInput.elm | 29 ++ .../main/elm/Messages/Comp/BoxStatsEdit.elm | 32 ++ .../{BoxSummaryView.elm => BoxStatsView.elm} | 2 +- .../main/elm/Messages/Comp/BoxUploadEdit.elm | 24 + .../src/main/elm/Messages/Comp/BoxView.elm | 8 +- .../main/elm/Messages/Comp/DashboardEdit.elm | 40 ++ .../elm/Messages/Comp/ItemColumnDropdown.elm | 38 ++ .../src/main/elm/Messages/Data/BoxContent.elm | 54 ++ .../src/main/elm/Messages/Data/ItemColumn.elm | 115 +++++ .../src/main/elm/Messages/Page/Dashboard.elm | 9 +- .../elm/Messages/Page/DefaultDashboard.elm | 22 +- .../src/main/elm/Page/Dashboard/Data.elm | 24 +- .../elm/Page/Dashboard/DefaultDashboard.elm | 20 +- .../src/main/elm/Page/Dashboard/SideMenu.elm | 15 +- .../src/main/elm/Page/Dashboard/Update.elm | 67 ++- .../src/main/elm/Page/Dashboard/View.elm | 7 +- 41 files changed, 2813 insertions(+), 130 deletions(-) create mode 100644 modules/webapp/src/main/elm/Comp/BoxEdit.elm create mode 100644 modules/webapp/src/main/elm/Comp/BoxMessageEdit.elm create mode 100644 modules/webapp/src/main/elm/Comp/BoxQueryEdit.elm create mode 100644 modules/webapp/src/main/elm/Comp/BoxSearchQueryInput.elm create mode 100644 modules/webapp/src/main/elm/Comp/BoxStatsEdit.elm rename modules/webapp/src/main/elm/Comp/{BoxSummaryView.elm => BoxStatsView.elm} (92%) create mode 100644 modules/webapp/src/main/elm/Comp/BoxUploadEdit.elm create mode 100644 modules/webapp/src/main/elm/Comp/DashboardEdit.elm create mode 100644 modules/webapp/src/main/elm/Comp/ItemColumnDropdown.elm create mode 100644 modules/webapp/src/main/elm/Comp/ItemColumnView.elm create mode 100644 modules/webapp/src/main/elm/Data/ItemColumn.elm create mode 100644 modules/webapp/src/main/elm/Messages/Comp/BoxEdit.elm create mode 100644 modules/webapp/src/main/elm/Messages/Comp/BoxMessageEdit.elm create mode 100644 modules/webapp/src/main/elm/Messages/Comp/BoxQueryEdit.elm create mode 100644 modules/webapp/src/main/elm/Messages/Comp/BoxSearchQueryInput.elm create mode 100644 modules/webapp/src/main/elm/Messages/Comp/BoxStatsEdit.elm rename modules/webapp/src/main/elm/Messages/Comp/{BoxSummaryView.elm => BoxStatsView.elm} (91%) create mode 100644 modules/webapp/src/main/elm/Messages/Comp/BoxUploadEdit.elm create mode 100644 modules/webapp/src/main/elm/Messages/Comp/DashboardEdit.elm create mode 100644 modules/webapp/src/main/elm/Messages/Comp/ItemColumnDropdown.elm create mode 100644 modules/webapp/src/main/elm/Messages/Data/BoxContent.elm create mode 100644 modules/webapp/src/main/elm/Messages/Data/ItemColumn.elm diff --git a/modules/webapp/src/main/elm/App/Update.elm b/modules/webapp/src/main/elm/App/Update.elm index d039b7a3..a454c305 100644 --- a/modules/webapp/src/main/elm/App/Update.elm +++ b/modules/webapp/src/main/elm/App/Update.elm @@ -331,7 +331,7 @@ updateWithSub msg model = updateSearch texts Page.Search.Data.RefreshView newModel else if Page.isDashboardPage model.page && isProcessItem then - updateDashboard texts Page.Dashboard.Data.reloadDashboard newModel + updateDashboard texts Page.Dashboard.Data.reloadDashboardData newModel else ( newModel, Cmd.none, Sub.none ) diff --git a/modules/webapp/src/main/elm/Comp/BoxEdit.elm b/modules/webapp/src/main/elm/Comp/BoxEdit.elm new file mode 100644 index 00000000..1a91ed1c --- /dev/null +++ b/modules/webapp/src/main/elm/Comp/BoxEdit.elm @@ -0,0 +1,467 @@ +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) diff --git a/modules/webapp/src/main/elm/Comp/BoxMessageEdit.elm b/modules/webapp/src/main/elm/Comp/BoxMessageEdit.elm new file mode 100644 index 00000000..29f5c4e2 --- /dev/null +++ b/modules/webapp/src/main/elm/Comp/BoxMessageEdit.elm @@ -0,0 +1,92 @@ +module Comp.BoxMessageEdit exposing (Model, Msg, init, update, view) + +import Data.BoxContent exposing (MessageData) +import Html exposing (Html, div, input, label, text, textarea) +import Html.Attributes exposing (autocomplete, class, name, placeholder, type_, value) +import Html.Events exposing (onInput) +import Messages.Comp.BoxMessageEdit exposing (Texts) +import Styles as S + + +type alias Model = + { data : MessageData + } + + +type Msg + = SetTitle String + | SetBody String + + +init : MessageData -> Model +init data = + { data = data + } + + + +--- Update + + +update : Msg -> Model -> ( Model, MessageData ) +update msg model = + case msg of + SetTitle str -> + let + data = + model.data + + data_ = + { data | title = str } + in + ( { model | data = data_ }, data_ ) + + SetBody str -> + let + data = + model.data + + data_ = + { data | body = str } + in + ( { model | data = data_ }, data_ ) + + + +--- View + + +view : Texts -> Model -> Html Msg +view texts model = + div [] + [ div [] + [ label [ class S.inputLabel ] + [ text texts.titleLabel + ] + , input + [ type_ "text" + , name "message-title" + , autocomplete False + , onInput SetTitle + , value model.data.title + , placeholder texts.titlePlaceholder + , class S.textInput + ] + [] + ] + , div [ class "mt-2" ] + [ label [ class S.inputLabel ] + [ text texts.bodyLabel + ] + , textarea + [ value model.data.body + , onInput SetBody + , class S.textAreaInput + , placeholder texts.bodyPlaceholder + ] + [] + ] + , div [ class "opacity-75 text-sm mt-1" ] + [ text texts.infoText + ] + ] diff --git a/modules/webapp/src/main/elm/Comp/BoxQueryEdit.elm b/modules/webapp/src/main/elm/Comp/BoxQueryEdit.elm new file mode 100644 index 00000000..d20cfb0d --- /dev/null +++ b/modules/webapp/src/main/elm/Comp/BoxQueryEdit.elm @@ -0,0 +1,190 @@ +module Comp.BoxQueryEdit exposing (..) + +import Comp.BoxSearchQueryInput +import Comp.IntField +import Comp.ItemColumnDropdown +import Comp.MenuBar as MB +import Data.Bookmarks +import Data.BoxContent exposing (QueryData, SearchQuery(..)) +import Data.Flags exposing (Flags) +import Data.UiSettings exposing (UiSettings) +import Html exposing (Html, div, label, text) +import Html.Attributes exposing (class) +import Messages.Comp.BoxQueryEdit exposing (Texts) +import Styles as S + + +type alias Model = + { data : QueryData + , searchQueryModel : Comp.BoxSearchQueryInput.Model + , limitModel : Comp.IntField.Model + , limitValue : Maybe Int + , columnModel : Comp.ItemColumnDropdown.Model + } + + +type Msg + = SearchQueryMsg Comp.BoxSearchQueryInput.Msg + | LimitMsg Comp.IntField.Msg + | ColumnMsg Comp.ItemColumnDropdown.Msg + | ToggleColumnHeaders + + +init : Flags -> QueryData -> ( Model, Cmd Msg, Sub Msg ) +init flags data = + let + ( qm, qc, qs ) = + Comp.BoxSearchQueryInput.init flags data.query Data.Bookmarks.empty + + emptyModel = + { data = data + , searchQueryModel = qm + , limitModel = Comp.IntField.init (Just 1) Nothing False + , limitValue = Just data.limit + , columnModel = Comp.ItemColumnDropdown.init data.columns + } + in + ( emptyModel, Cmd.map SearchQueryMsg qc, Sub.map SearchQueryMsg qs ) + + + +--- Update + + +type alias UpdateResult = + { model : Model + , cmd : Cmd Msg + , sub : Sub Msg + , data : QueryData + } + + +update : Flags -> Msg -> Model -> UpdateResult +update flags msg model = + case msg of + SearchQueryMsg lm -> + let + result = + Comp.BoxSearchQueryInput.update flags lm model.searchQueryModel + + setData data = + { data | query = Maybe.withDefault data.query result.query } + + nextModel = + withData setData { model | searchQueryModel = result.model } + in + { model = nextModel + , cmd = Cmd.map SearchQueryMsg result.cmd + , sub = Sub.map SearchQueryMsg result.sub + , data = nextModel.data + } + + LimitMsg lm -> + let + ( im, n ) = + Comp.IntField.update lm model.limitModel + + data = + model.data + + data_ = + case n of + Just num -> + { data | limit = num } + + Nothing -> + data + in + { model = { model | limitModel = im, limitValue = n, data = data_ } + , cmd = Cmd.none + , sub = Sub.none + , data = data_ + } + + ColumnMsg lm -> + let + ( cm, cc ) = + Comp.ItemColumnDropdown.update lm model.columnModel + + selection = + Comp.ItemColumnDropdown.getSelected model.columnModel + + data = + model.data + + data_ = + { data | columns = selection } + in + { model = { model | columnModel = cm, data = data_ } + , cmd = Cmd.map ColumnMsg cc + , sub = Sub.none + , data = data_ + } + + ToggleColumnHeaders -> + let + data = + model.data + + data_ = + { data | showHeaders = not data.showHeaders } + in + { model = { model | data = data_ } + , cmd = Cmd.none + , sub = Sub.none + , data = data_ + } + + +unit : Model -> UpdateResult +unit model = + { model = model + , cmd = Cmd.none + , sub = Sub.none + , data = model.data + } + + +withData : (QueryData -> QueryData) -> Model -> Model +withData modify model = + { model | data = modify model.data } + + + +--- View + + +view : Texts -> UiSettings -> Model -> Html Msg +view texts settings model = + let + limitSettings = + { label = "Limit" + , info = "Show this many results." + , number = model.limitValue + , classes = "" + } + in + div [] + [ Html.map SearchQueryMsg + (Comp.BoxSearchQueryInput.view texts.searchQuery settings model.searchQueryModel) + , div [ class "mt-2" ] + [ Html.map LimitMsg + (Comp.IntField.view limitSettings model.limitModel) + ] + , div [ class "mt-2" ] + [ label [ class S.inputLabel ] + [ text "Columns" + ] + , Html.map ColumnMsg + (Comp.ItemColumnDropdown.view texts.columnDropdown settings model.columnModel) + ] + , div [ class "mt-2" ] + [ MB.viewItem <| + MB.Checkbox + { tagger = \_ -> ToggleColumnHeaders + , label = texts.showColumnHeaders + , value = model.data.showHeaders + , id = "" + } + ] + ] diff --git a/modules/webapp/src/main/elm/Comp/BoxQueryView.elm b/modules/webapp/src/main/elm/Comp/BoxQueryView.elm index bb6725a6..d4eb3c87 100644 --- a/modules/webapp/src/main/elm/Comp/BoxQueryView.elm +++ b/modules/webapp/src/main/elm/Comp/BoxQueryView.elm @@ -5,11 +5,13 @@ import Api.Model.ItemLight exposing (ItemLight) import Api.Model.ItemLightList exposing (ItemLightList) import Api.Model.ItemQuery exposing (ItemQuery) import Comp.Basic +import Comp.ItemColumnView import Data.BoxContent exposing (QueryData, SearchQuery(..)) import Data.Flags exposing (Flags) -import Data.ItemTemplate as IT +import Data.ItemColumn as IC exposing (ItemColumn) import Data.Items import Data.SearchMode +import Data.UiSettings exposing (UiSettings) import Html exposing (Html, a, div, i, table, tbody, td, text, th, thead, tr) import Html.Attributes exposing (class, classList) import Http @@ -70,8 +72,8 @@ update flags msg model = --- View -view : Texts -> Model -> Html Msg -view texts model = +view : Texts -> UiSettings -> Model -> Html Msg +view texts settings model = case model.results of Loading -> div [ class "h-24 " ] @@ -96,41 +98,42 @@ view texts model = viewEmpty texts else - viewItems texts model.meta list + viewItems texts settings model.meta list -viewItems : Texts -> QueryData -> ItemLightList -> Html Msg -viewItems texts meta list = +viewItems : Texts -> UiSettings -> QueryData -> ItemLightList -> Html Msg +viewItems texts settings meta list = let items = Data.Items.flatten list in table [ class "w-full divide-y dark:divide-slate-500" ] - (viewItemHead meta ++ [ tbody [] <| List.map (viewItemRow texts meta) items ]) + (viewItemHead texts meta ++ [ tbody [] <| List.map (viewItemRow texts settings meta) items ]) -viewItemHead : QueryData -> List (Html Msg) -viewItemHead meta = - case meta.header of - [] -> - [] +viewItemHead : Texts -> QueryData -> List (Html Msg) +viewItemHead texts meta = + if not meta.showHeaders || meta.columns == [] then + [] - labels -> - [ thead [] - [ tr [] - (List.map (\n -> th [ class "text-left text-sm" ] [ text n ]) labels) - ] + else + [ thead [] + [ tr [] + (List.map texts.itemColumn.header meta.columns + |> List.map (\n -> th [ class "text-left text-sm" ] [ text n ]) + ) ] + ] -viewItemRow : Texts -> QueryData -> ItemLight -> Html Msg -viewItemRow texts meta item = +viewItemRow : Texts -> UiSettings -> QueryData -> ItemLight -> Html Msg +viewItemRow texts settings meta item = let ( col1, cols ) = getColumns meta - render tpl = - IT.render tpl texts.templateCtx item + render col = + Comp.ItemColumnView.renderDiv texts.templateCtx settings col [ class "flex flex-row space-x-1" ] item td1 = td [ class "py-2 px-1" ] @@ -138,7 +141,7 @@ viewItemRow texts meta item = [ class Styles.link , Page.href (ItemDetailPage item.id) ] - [ text (render col1) + [ render col1 ] ] @@ -147,7 +150,7 @@ viewItemRow texts meta item = [ class "py-2 px-1" , classList [ ( "hidden md:table-cell", index > 1 ) ] ] - [ text (render col) + [ render col ] in tr [] @@ -168,14 +171,14 @@ viewEmpty texts = --- Helpers -getColumns : QueryData -> ( IT.ItemTemplate, List IT.ItemTemplate ) +getColumns : QueryData -> ( ItemColumn, List ItemColumn ) getColumns meta = case meta.columns of x :: xs -> ( x, xs ) [] -> - ( IT.name, [ IT.correspondent, IT.dateShort ] ) + ( IC.Name, [ IC.Correspondent, IC.DateShort ] ) mkQuery : String -> QueryData -> ItemQuery diff --git a/modules/webapp/src/main/elm/Comp/BoxSearchQueryInput.elm b/modules/webapp/src/main/elm/Comp/BoxSearchQueryInput.elm new file mode 100644 index 00000000..11e26370 --- /dev/null +++ b/modules/webapp/src/main/elm/Comp/BoxSearchQueryInput.elm @@ -0,0 +1,292 @@ +module Comp.BoxSearchQueryInput exposing + ( Model + , Msg + , UpdateResult + , init + , switchToBookmark + , switchToQuery + , toSearchQuery + , update + , view + ) + +import Api +import Comp.BookmarkDropdown +import Comp.PowerSearchInput +import Data.Bookmarks exposing (AllBookmarks) +import Data.BoxContent exposing (SearchQuery(..)) +import Data.Flags exposing (Flags) +import Data.UiSettings exposing (UiSettings) +import Html exposing (Html, div, input, label, span, text) +import Html.Attributes exposing (checked, class, type_) +import Html.Events exposing (onCheck) +import Http +import Messages.Comp.BoxSearchQueryInput exposing (Texts) +import Styles as S + + +type alias Model = + { queryModel : QueryModel + , allBookmarks : AllBookmarks + } + + +type QueryModel + = Search Comp.PowerSearchInput.Model + | Bookmark Comp.BookmarkDropdown.Model + + +toSearchQuery : Model -> Maybe SearchQuery +toSearchQuery model = + case model.queryModel of + Search pm -> + let + qstr = + Maybe.withDefault "" pm.input + in + if qstr == "" || Comp.PowerSearchInput.isValid pm then + Just (SearchQueryString qstr) + + else + Nothing + + Bookmark bm -> + Comp.BookmarkDropdown.getSelectedId bm + |> Maybe.map SearchQueryBookmark + + +type Msg + = GetBookmarksResp (Result Http.Error AllBookmarks) + | BookmarkMsg Comp.BookmarkDropdown.Msg + | PowerSearchMsg Comp.PowerSearchInput.Msg + | SwitchQueryBookmark + | SwitchQuerySearch + + +switchToBookmark : Msg +switchToBookmark = + SwitchQueryBookmark + + +switchToQuery : Msg +switchToQuery = + SwitchQuerySearch + + +init : Flags -> SearchQuery -> AllBookmarks -> ( Model, Cmd Msg, Sub Msg ) +init flags query bookmarks = + let + emptyModel = + { queryModel = Search Comp.PowerSearchInput.init + , allBookmarks = bookmarks + } + in + case query of + SearchQueryBookmark id -> + initQueryBookmark flags emptyModel (Just id) + + SearchQueryString qstr -> + initQuerySearch emptyModel qstr + + +initQueryBookmark : Flags -> Model -> Maybe String -> ( Model, Cmd Msg, Sub Msg ) +initQueryBookmark flags model bookmarkId = + ( { model + | queryModel = + Bookmark + (Comp.BookmarkDropdown.initWith model.allBookmarks bookmarkId) + } + , if model.allBookmarks == Data.Bookmarks.empty then + Api.getBookmarks flags GetBookmarksResp + + else + Cmd.none + , Sub.none + ) + + +initQuerySearch : Model -> String -> ( Model, Cmd Msg, Sub Msg ) +initQuerySearch model qstr = + let + ( qm, qc, qs ) = + Comp.PowerSearchInput.initWith qstr + in + ( { model | queryModel = Search qm } + , Cmd.map PowerSearchMsg qc + , Sub.map PowerSearchMsg qs + ) + + + +--- Update + + +type alias UpdateResult = + { model : Model + , cmd : Cmd Msg + , sub : Sub Msg + , query : Maybe SearchQuery + } + + +update : Flags -> Msg -> Model -> UpdateResult +update flags msg model = + case msg of + GetBookmarksResp (Ok list) -> + let + bmId = + case model.queryModel of + Bookmark bm -> + Comp.BookmarkDropdown.getSelectedId bm + + Search _ -> + Nothing + + nm = + { model | allBookmarks = list } + in + case model.queryModel of + Bookmark _ -> + update flags + SwitchQueryBookmark + { nm + | queryModel = + Bookmark (Comp.BookmarkDropdown.initWith model.allBookmarks bmId) + } + + Search _ -> + unit nm + + GetBookmarksResp (Err _) -> + unit model + + BookmarkMsg lm -> + case model.queryModel of + Bookmark m -> + let + ( bm, bc ) = + Comp.BookmarkDropdown.update lm m + + nextModel = + { model | queryModel = Bookmark bm } + in + { model = nextModel + , cmd = Cmd.map BookmarkMsg bc + , sub = Sub.none + , query = toSearchQuery nextModel + } + + _ -> + unit model + + PowerSearchMsg lm -> + case model.queryModel of + Search m -> + let + result = + Comp.PowerSearchInput.update lm m + + nextModel = + { model | queryModel = Search result.model } + in + { model = nextModel + , cmd = Cmd.map PowerSearchMsg result.cmd + , sub = Sub.map PowerSearchMsg result.subs + , query = toSearchQuery nextModel + } + + _ -> + unit model + + SwitchQueryBookmark -> + let + selected = + case toSearchQuery model of + Just (SearchQueryBookmark id) -> + Just id + + _ -> + Nothing + + ( m, c, s ) = + initQueryBookmark flags model selected + in + UpdateResult m c s (toSearchQuery m) + + SwitchQuerySearch -> + let + qstr = + case toSearchQuery model of + Just (SearchQueryString q) -> + q + + _ -> + "" + + ( m, c, s ) = + initQuerySearch model qstr + in + UpdateResult m c s (toSearchQuery m) + + +unit : Model -> UpdateResult +unit model = + UpdateResult model Cmd.none Sub.none Nothing + + + +--- View + + +view : Texts -> UiSettings -> Model -> Html Msg +view texts settings model = + let + ( isBookmark, isQuery ) = + case model.queryModel of + Bookmark _ -> + ( True, False ) + + Search _ -> + ( False, True ) + + searchSettings = + { placeholder = texts.searchPlaceholder + , extraAttrs = [] + } + in + div [ class "flex flex-col" ] + [ div [ class "flex flex-row space-x-4" ] + [ label [ class "inline-flex items-center" ] + [ input + [ type_ "radio" + , checked isBookmark + , onCheck (\_ -> SwitchQueryBookmark) + , class S.radioInput + ] + [] + , span [ class "ml-2" ] [ text texts.switchToBookmark ] + ] + , label [ class "inline-flex items-center" ] + [ input + [ type_ "radio" + , checked isQuery + , onCheck (\_ -> SwitchQuerySearch) + , class S.radioInput + ] + [] + , span [ class "ml-2" ] [ text texts.switchToQuery ] + ] + ] + , case model.queryModel of + Bookmark m -> + Html.map BookmarkMsg + (Comp.BookmarkDropdown.view texts.bookmarkDropdown settings m) + + Search m -> + div [ class "relative" ] + [ Html.map PowerSearchMsg + (Comp.PowerSearchInput.viewInput searchSettings m) + , Html.map PowerSearchMsg + (Comp.PowerSearchInput.viewResult [] m) + ] + ] diff --git a/modules/webapp/src/main/elm/Comp/BoxStatsEdit.elm b/modules/webapp/src/main/elm/Comp/BoxStatsEdit.elm new file mode 100644 index 00000000..933c13be --- /dev/null +++ b/modules/webapp/src/main/elm/Comp/BoxStatsEdit.elm @@ -0,0 +1,195 @@ +module Comp.BoxStatsEdit exposing (..) + +import Comp.BoxSearchQueryInput +import Comp.FixedDropdown +import Comp.MenuBar as MB +import Data.Bookmarks +import Data.BoxContent exposing (QueryData, SearchQuery(..), StatsData, SummaryShow(..)) +import Data.DropdownStyle as DS +import Data.Flags exposing (Flags) +import Data.UiSettings exposing (UiSettings) +import Html exposing (Html, div, label, span, text) +import Html.Attributes exposing (class) +import Messages.Comp.BoxStatsEdit exposing (Texts) +import Styles as S + + +type alias Model = + { data : StatsData + , searchQueryModel : Comp.BoxSearchQueryInput.Model + , showModel : Comp.FixedDropdown.Model SummaryShowLabel + , summaryShow : SummaryShow + } + + +type Msg + = SearchQueryMsg Comp.BoxSearchQueryInput.Msg + | ShowMsg (Comp.FixedDropdown.Msg SummaryShowLabel) + | ToggleItemCountVisible + + +type SummaryShowLabel + = ShowFields + | ShowGeneric + + +init : Flags -> StatsData -> ( Model, Cmd Msg, Sub Msg ) +init flags data = + let + ( qm, qc, qs ) = + Comp.BoxSearchQueryInput.init flags data.query Data.Bookmarks.empty + + emptyModel = + { data = data + , searchQueryModel = qm + , showModel = + Comp.FixedDropdown.init + [ ShowFields, ShowGeneric ] + , summaryShow = data.show + } + in + ( emptyModel, Cmd.map SearchQueryMsg qc, Sub.map SearchQueryMsg qs ) + + + +--- Update + + +type alias UpdateResult = + { model : Model + , cmd : Cmd Msg + , sub : Sub Msg + , data : StatsData + } + + +update : Flags -> Msg -> Model -> UpdateResult +update flags msg model = + case msg of + SearchQueryMsg lm -> + let + result = + Comp.BoxSearchQueryInput.update flags lm model.searchQueryModel + + setData data = + { data | query = Maybe.withDefault data.query result.query } + + nextModel = + withData setData { model | searchQueryModel = result.model } + in + { model = nextModel + , cmd = Cmd.map SearchQueryMsg result.cmd + , sub = Sub.map SearchQueryMsg result.sub + , data = nextModel.data + } + + ShowMsg lm -> + let + ( mm, sel ) = + Comp.FixedDropdown.update lm model.showModel + + nextShow = + case ( model.summaryShow, sel ) of + ( SummaryShowFields _, Just ShowGeneric ) -> + SummaryShowGeneral + + ( SummaryShowGeneral, Just ShowFields ) -> + SummaryShowFields False + + _ -> + model.summaryShow + + data = + model.data + + data_ = + { data | show = nextShow } + in + unit { model | showModel = mm, summaryShow = nextShow, data = data_ } + + ToggleItemCountVisible -> + let + nextShow = + case model.summaryShow of + SummaryShowFields flag -> + SummaryShowFields (not flag) + + _ -> + model.summaryShow + + data = + model.data + + data_ = + { data | show = nextShow } + in + unit { model | summaryShow = nextShow, data = data_ } + + +unit : Model -> UpdateResult +unit model = + { model = model + , cmd = Cmd.none + , sub = Sub.none + , data = model.data + } + + +withData : (StatsData -> StatsData) -> Model -> Model +withData modify model = + { model | data = modify model.data } + + + +--- View + + +view : Texts -> UiSettings -> Model -> Html Msg +view texts settings model = + let + showSettings = + { display = + \a -> + case a of + ShowFields -> + texts.fieldStatistics + + ShowGeneric -> + texts.basicNumbers + , icon = \_ -> Nothing + , selectPlaceholder = "" + , style = DS.mainStyle + } + + showLabel = + case model.summaryShow of + SummaryShowFields _ -> + ShowFields + + SummaryShowGeneral -> + ShowGeneric + in + div [] + [ Html.map SearchQueryMsg + (Comp.BoxSearchQueryInput.view texts.searchQuery settings model.searchQueryModel) + , div [ class "mt-2" ] + [ label [ class S.inputLabel ] + [ text texts.showLabel ] + , Html.map ShowMsg + (Comp.FixedDropdown.viewStyled2 showSettings False (Just showLabel) model.showModel) + ] + , div [ class "mt-2" ] + [ case model.summaryShow of + SummaryShowGeneral -> + span [ class "hidden" ] [] + + SummaryShowFields itemCountVisible -> + MB.viewItem <| + MB.Checkbox + { tagger = \_ -> ToggleItemCountVisible + , label = texts.showItemCount + , id = "" + , value = itemCountVisible + } + ] + ] diff --git a/modules/webapp/src/main/elm/Comp/BoxSummaryView.elm b/modules/webapp/src/main/elm/Comp/BoxStatsView.elm similarity index 92% rename from modules/webapp/src/main/elm/Comp/BoxSummaryView.elm rename to modules/webapp/src/main/elm/Comp/BoxStatsView.elm index 719a9cc7..31088894 100644 --- a/modules/webapp/src/main/elm/Comp/BoxSummaryView.elm +++ b/modules/webapp/src/main/elm/Comp/BoxStatsView.elm @@ -1,23 +1,23 @@ -module Comp.BoxSummaryView exposing (Model, Msg, init, reloadData, update, view) +module Comp.BoxStatsView exposing (Model, Msg, init, reloadData, update, view) import Api import Api.Model.ItemQuery exposing (ItemQuery) import Api.Model.SearchStats exposing (SearchStats) import Comp.Basic import Comp.SearchStatsView -import Data.BoxContent exposing (SearchQuery(..), SummaryData, SummaryShow(..)) +import Data.BoxContent exposing (SearchQuery(..), StatsData, SummaryShow(..)) import Data.Flags exposing (Flags) import Html exposing (Html, div, text) import Html.Attributes exposing (class) import Http -import Messages.Comp.BoxSummaryView exposing (Texts) +import Messages.Comp.BoxStatsView exposing (Texts) import Styles import Util.List type alias Model = { results : ViewResult - , meta : SummaryData + , meta : StatsData } @@ -32,7 +32,7 @@ type Msg | ReloadData -init : Flags -> SummaryData -> ( Model, Cmd Msg ) +init : Flags -> StatsData -> ( Model, Cmd Msg ) init flags data = ( { results = Loading , meta = data @@ -169,7 +169,7 @@ mkQuery query = } -dataCmd : Flags -> SummaryData -> Cmd Msg +dataCmd : Flags -> StatsData -> Cmd Msg dataCmd flags data = case data.query of SearchQueryString q -> diff --git a/modules/webapp/src/main/elm/Comp/BoxUploadEdit.elm b/modules/webapp/src/main/elm/Comp/BoxUploadEdit.elm new file mode 100644 index 00000000..43511106 --- /dev/null +++ b/modules/webapp/src/main/elm/Comp/BoxUploadEdit.elm @@ -0,0 +1,106 @@ +module Comp.BoxUploadEdit exposing (..) + +import Api +import Api.Model.Source exposing (Source) +import Api.Model.SourceList exposing (SourceList) +import Comp.BoxUploadView exposing (Msg) +import Comp.FixedDropdown +import Data.BoxContent exposing (UploadData) +import Data.DropdownStyle as DS +import Data.Flags exposing (Flags) +import Html exposing (Html, div, label, text) +import Html.Attributes exposing (class) +import Http +import Messages.Comp.BoxUploadEdit exposing (Texts) +import Styles as S + + +type alias Model = + { data : UploadData + , allSources : List Source + , sourceModel : Comp.FixedDropdown.Model Source + } + + +type Msg + = GetSourcesResp (Result Http.Error SourceList) + | SourceMsg (Comp.FixedDropdown.Msg Source) + + +init : Flags -> UploadData -> ( Model, Cmd Msg ) +init flags data = + ( { data = data + , allSources = [] + , sourceModel = Comp.FixedDropdown.init [] + } + , Api.getSources flags GetSourcesResp + ) + + + +--- Update + + +update : Msg -> Model -> ( Model, UploadData ) +update msg model = + case msg of + GetSourcesResp (Ok list) -> + let + all = + List.map .source list.items + |> List.filter .enabled + + dm = + Comp.FixedDropdown.init all + in + ( { model | allSources = all, sourceModel = dm } + , model.data + ) + + GetSourcesResp (Err _) -> + ( model, model.data ) + + SourceMsg lm -> + let + ( dm, sel ) = + Comp.FixedDropdown.update lm model.sourceModel + + ud = + model.data + + ud_ = + { ud | sourceId = Maybe.map .id sel } + in + ( { model | sourceModel = dm, data = ud_ }, ud_ ) + + + +--- View + + +view : Texts -> Model -> Html Msg +view texts model = + let + cfg = + { display = \s -> s.abbrev + , icon = \_ -> Nothing + , selectPlaceholder = texts.sourcePlaceholder + , style = DS.mainStyle + } + + selected = + List.filter (\e -> Just e.id == model.data.sourceId) model.allSources + |> List.head + in + div [] + [ div [] + [ label [ class S.inputLabel ] + [ text texts.sourceLabel + ] + , Html.map SourceMsg + (Comp.FixedDropdown.viewStyled2 cfg False selected model.sourceModel) + ] + , div [ class "mt-1 opacity-75 text-sm" ] + [ text texts.infoText + ] + ] diff --git a/modules/webapp/src/main/elm/Comp/BoxUploadView.elm b/modules/webapp/src/main/elm/Comp/BoxUploadView.elm index a3b6f6a8..5d5737f9 100644 --- a/modules/webapp/src/main/elm/Comp/BoxUploadView.elm +++ b/modules/webapp/src/main/elm/Comp/BoxUploadView.elm @@ -1,6 +1,7 @@ module Comp.BoxUploadView exposing (..) import Comp.UploadForm +import Data.BoxContent exposing (UploadData) import Data.Flags exposing (Flags) import Data.UiSettings exposing (UiSettings) import Html exposing (Html, div) @@ -18,10 +19,10 @@ type Msg = UploadMsg Comp.UploadForm.Msg -init : Maybe String -> Model -init sourceId = +init : UploadData -> Model +init data = { uploadForm = Comp.UploadForm.init - , sourceId = sourceId + , sourceId = data.sourceId } diff --git a/modules/webapp/src/main/elm/Comp/BoxView.elm b/modules/webapp/src/main/elm/Comp/BoxView.elm index e654e3b3..d73ce9ec 100644 --- a/modules/webapp/src/main/elm/Comp/BoxView.elm +++ b/modules/webapp/src/main/elm/Comp/BoxView.elm @@ -1,7 +1,7 @@ module Comp.BoxView exposing (..) import Comp.BoxQueryView -import Comp.BoxSummaryView +import Comp.BoxStatsView import Comp.BoxUploadView import Data.Box exposing (Box) import Data.BoxContent exposing (BoxContent(..), MessageData) @@ -25,12 +25,12 @@ type ContentModel = ContentMessage Data.BoxContent.MessageData | ContentUpload Comp.BoxUploadView.Model | ContentQuery Comp.BoxQueryView.Model - | ContentSummary Comp.BoxSummaryView.Model + | ContentStats Comp.BoxStatsView.Model type Msg = QueryMsg Comp.BoxQueryView.Msg - | SummaryMsg Comp.BoxSummaryView.Msg + | StatsMsg Comp.BoxStatsView.Msg | UploadMsg Comp.BoxUploadView.Msg | ReloadData @@ -60,10 +60,10 @@ contentInit flags content = BoxMessage data -> ( ContentMessage data, Cmd.none ) - BoxUpload source -> + BoxUpload data -> let qm = - Comp.BoxUploadView.init source + Comp.BoxUploadView.init data in ( ContentUpload qm, Cmd.none ) @@ -74,12 +74,12 @@ contentInit flags content = in ( ContentQuery qm, Cmd.map QueryMsg qc ) - BoxSummary data -> + BoxStats data -> let ( sm, sc ) = - Comp.BoxSummaryView.init flags data + Comp.BoxStatsView.init flags data in - ( ContentSummary sm, Cmd.map SummaryMsg sc ) + ( ContentStats sm, Cmd.map StatsMsg sc ) @@ -104,15 +104,15 @@ update flags msg model = _ -> unit model - SummaryMsg lm -> + StatsMsg lm -> case model.content of - ContentSummary qm -> + ContentStats qm -> let ( cm, cc, reloading ) = - Comp.BoxSummaryView.update flags lm qm + Comp.BoxStatsView.update flags lm qm in - ( { model | content = ContentSummary cm, reloading = reloading } - , Cmd.map SummaryMsg cc + ( { model | content = ContentStats cm, reloading = reloading } + , Cmd.map StatsMsg cc , Sub.none ) @@ -139,8 +139,8 @@ update flags msg model = ContentQuery _ -> update flags (QueryMsg Comp.BoxQueryView.reloadData) model - ContentSummary _ -> - update flags (SummaryMsg Comp.BoxSummaryView.reloadData) model + ContentStats _ -> + update flags (StatsMsg Comp.BoxStatsView.reloadData) model _ -> unit model @@ -206,11 +206,11 @@ boxContent texts flags settings model = ContentQuery qm -> Html.map QueryMsg - (Comp.BoxQueryView.view texts.queryView qm) + (Comp.BoxQueryView.view texts.queryView settings qm) - ContentSummary qm -> - Html.map SummaryMsg - (Comp.BoxSummaryView.view texts.summaryView qm) + ContentStats qm -> + Html.map StatsMsg + (Comp.BoxStatsView.view texts.statsView qm) spanStyle : Box -> String diff --git a/modules/webapp/src/main/elm/Comp/DashboardEdit.elm b/modules/webapp/src/main/elm/Comp/DashboardEdit.elm new file mode 100644 index 00000000..126d24d2 --- /dev/null +++ b/modules/webapp/src/main/elm/Comp/DashboardEdit.elm @@ -0,0 +1,458 @@ +module Comp.DashboardEdit exposing (Model, Msg, SubmitAction(..), init, update, view, viewBox) + +import Comp.BoxEdit +import Comp.FixedDropdown +import Comp.MenuBar as MB +import Data.Box exposing (Box) +import Data.Dashboard exposing (Dashboard) +import Data.DropdownStyle as DS +import Data.Flags exposing (Flags) +import Data.UiSettings exposing (UiSettings) +import Dict exposing (Dict) +import Html exposing (Html, div, i, input, label, text) +import Html.Attributes exposing (class, classList, href, placeholder, type_, value) +import Html.Events exposing (onClick, onInput) +import Html5.DragDrop as DD +import Messages.Comp.DashboardEdit exposing (Texts) +import Styles as S +import Util.Maybe + + +type alias Model = + { dashboard : Dashboard + , originalName : String + , boxModels : Dict Int Comp.BoxEdit.Model + , nameValue : Maybe String + , columnsModel : Comp.FixedDropdown.Model Int + , columnsValue : Maybe Int + , newBoxMenuOpen : Bool + , boxDragDrop : DD.Model Int Int + } + + +type Msg + = BoxMsg Int Comp.BoxEdit.Msg + | SaveDashboard + | Cancel + | RequestDelete + | SetName String + | ColumnsMsg (Comp.FixedDropdown.Msg Int) + | ToggleNewBoxMenu + | PrependNew Box + | DragDropMsg (DD.Msg Int Int) + + +type SubmitAction + = SubmitSave Dashboard + | SubmitCancel + | SubmitDelete String + | SubmitNone + + +init : Flags -> Dashboard -> ( Model, Cmd Msg, Sub Msg ) +init flags db = + let + ( boxModels, cmdsAndSubs ) = + List.map (Comp.BoxEdit.init flags) db.boxes + |> List.indexedMap + (\a -> + \( bm, bc, bs ) -> + ( bm, ( Cmd.map (BoxMsg a) bc, Sub.map (BoxMsg a) bs ) ) + ) + |> List.unzip + + ( cmds, subs ) = + List.unzip cmdsAndSubs + in + ( { dashboard = db + , originalName = db.name + , nameValue = Just db.name + , columnsModel = Comp.FixedDropdown.init [ 1, 2, 3, 4, 5 ] + , columnsValue = Just db.columns + , newBoxMenuOpen = False + , boxModels = + List.indexedMap Tuple.pair boxModels + |> Dict.fromList + , boxDragDrop = DD.init + } + , Cmd.batch cmds + , Sub.batch subs + ) + + + +--- Update + + +type alias UpdateResult = + { model : Model + , cmd : Cmd Msg + , sub : Sub Msg + , action : SubmitAction + } + + +update : Flags -> Msg -> Model -> UpdateResult +update flags msg model = + case msg of + BoxMsg index lm -> + case Dict.get index model.boxModels of + Just bm -> + let + result = + Comp.BoxEdit.update flags lm bm + + newBoxes = + applyBoxAction index result.action <| + Dict.insert index result.model model.boxModels + + db = + model.dashboard + + db_ = + { db | boxes = List.map .box (Dict.values newBoxes) } + in + { model = { model | boxModels = newBoxes, dashboard = db_ } + , cmd = Cmd.map (BoxMsg index) result.cmd + , sub = Sub.map (BoxMsg index) result.sub + , action = SubmitNone + } + + Nothing -> + unit model + + SetName str -> + case Util.Maybe.fromString str of + Just s -> + let + db = + model.dashboard + + db_ = + { db | name = s } + in + unit { model | dashboard = db_, nameValue = Just s } + + Nothing -> + unit { model | nameValue = Nothing } + + ColumnsMsg lm -> + let + ( cm, value ) = + Comp.FixedDropdown.update lm model.columnsModel + + db = + model.dashboard + + db_ = + { db | columns = Maybe.withDefault db.columns value } + in + unit { model | columnsValue = value, columnsModel = cm, dashboard = db_ } + + SaveDashboard -> + UpdateResult model Cmd.none Sub.none (SubmitSave model.dashboard) + + Cancel -> + UpdateResult model Cmd.none Sub.none SubmitCancel + + RequestDelete -> + UpdateResult model Cmd.none Sub.none (SubmitDelete model.originalName) + + ToggleNewBoxMenu -> + unit { model | newBoxMenuOpen = not model.newBoxMenuOpen } + + PrependNew box -> + let + min = + Dict.keys model.boxModels + |> List.minimum + |> Maybe.withDefault 1 + + index = + min - 1 + + db = + model.dashboard + + db_ = + { db | boxes = box :: db.boxes } + + ( bm, bc, bs ) = + Comp.BoxEdit.init flags box + + newBoxes = + Dict.insert index bm model.boxModels + in + { model = { model | boxModels = newBoxes, dashboard = db_, newBoxMenuOpen = False } + , cmd = Cmd.map (BoxMsg index) bc + , sub = Sub.map (BoxMsg index) bs + , action = SubmitNone + } + + DragDropMsg lm -> + let + ( dm, dropped ) = + DD.update lm model.boxDragDrop + + m_ = + { model | boxDragDrop = dm } + + nextModel = + case dropped of + Just ( dragId, dropId, _ ) -> + applyDrop dragId dropId m_ + + Nothing -> + m_ + in + unit nextModel + + +unit : Model -> UpdateResult +unit model = + UpdateResult model Cmd.none Sub.none SubmitNone + + +applyBoxAction : + Int + -> Comp.BoxEdit.BoxAction + -> Dict Int Comp.BoxEdit.Model + -> Dict Int Comp.BoxEdit.Model +applyBoxAction index action boxes = + let + swap n1 n2 = + Maybe.map2 + (\e1 -> \e2 -> Dict.insert n2 e1 boxes |> Dict.insert n1 e2) + (Dict.get n1 boxes) + (Dict.get n2 boxes) + |> Maybe.withDefault boxes + in + case action of + Comp.BoxEdit.BoxNoAction -> + boxes + + Comp.BoxEdit.BoxDelete -> + Dict.remove index boxes + + Comp.BoxEdit.BoxMoveLeft -> + swap (index - 1) index + + Comp.BoxEdit.BoxMoveRight -> + swap index (index + 1) + + +applyDrop : Int -> Int -> Model -> Model +applyDrop dragId dropId model = + let + dragEl = + Dict.get dragId model.boxModels + in + if dragId == dropId then + model + + else + case dragEl of + Just box -> + let + withoutDragged = + Dict.remove dragId model.boxModels + + ( begin, end ) = + Dict.partition (\k -> \_ -> k < dropId) withoutDragged + + incKeys = + Dict.toList end + |> List.map (\( k, v ) -> ( k + 1, v )) + |> Dict.fromList + + newBoxes = + Dict.insert dropId box (Dict.union begin incKeys) + + db = + model.dashboard + + db_ = + { db | boxes = List.map .box (Dict.values newBoxes) } + in + { model | boxModels = newBoxes, dashboard = db_ } + + Nothing -> + model + + + +--- View + + +view : Texts -> Flags -> UiSettings -> Model -> Html Msg +view texts flags settings model = + let + boxMenuItem box = + { icon = i [ class (Data.Box.boxIcon box) ] [] + , label = texts.boxContent.forContent box.content + , disabled = False + , attrs = + [ href "#" + , onClick (PrependNew box) + ] + } + in + div [] + [ viewMain texts flags settings model + , div [ class S.formHeader ] + [ text texts.dashboardBoxes + ] + , MB.view + { start = [] + , end = + [ MB.Dropdown + { linkIcon = "fa fa-plus" + , label = texts.newBox + , linkClass = + [ ( S.secondaryBasicButton, True ) + ] + , toggleMenu = ToggleNewBoxMenu + , menuOpen = model.newBoxMenuOpen + , items = + [ boxMenuItem Data.Box.queryBox + , boxMenuItem Data.Box.statsBox + , boxMenuItem Data.Box.messageBox + , boxMenuItem Data.Box.uploadBox + ] + } + ] + , rootClasses = "mb-2" + } + , div + [ class (gridStyle model.dashboard) + ] + (List.map + (viewBox texts flags settings model) + (Dict.toList model.boxModels) + ) + ] + + +viewBox : Texts -> Flags -> UiSettings -> Model -> ( Int, Comp.BoxEdit.Model ) -> Html Msg +viewBox texts flags settings model ( index, box ) = + let + dropId = + DD.getDropId model.boxDragDrop + + dragId = + DD.getDragId model.boxDragDrop + + styles = + [ classList [ ( "opacity-40", dropId == Just index && dropId /= dragId ) ] + , class (spanStyle box.box) + ] + in + div + (DD.draggable DragDropMsg index ++ DD.droppable DragDropMsg index ++ styles) + [ Html.map (BoxMsg index) + (Comp.BoxEdit.view texts.boxView flags settings box) + ] + + +viewMain : Texts -> Flags -> UiSettings -> Model -> Html Msg +viewMain texts _ _ model = + let + columnsSettings = + { display = String.fromInt + , icon = \_ -> Nothing + , selectPlaceholder = "" + , style = DS.mainStyle + } + in + div [ class "my-2 " ] + [ MB.view + { start = + [ MB.PrimaryButton + { tagger = SaveDashboard + , title = texts.basics.submitThisForm + , icon = Just "fa fa-save" + , label = texts.basics.submit + } + , MB.SecondaryButton + { tagger = Cancel + , title = texts.basics.cancel + , icon = Just "fa fa-times" + , label = texts.basics.cancel + } + ] + , end = [] + , rootClasses = "" + } + , div [ class "flex flex-col" ] + [ div [ class "mt-2" ] + [ label [ class S.inputLabel ] + [ text texts.basics.name + ] + , input + [ type_ "text" + , placeholder texts.namePlaceholder + , class S.textInput + , value (Maybe.withDefault "" model.nameValue) + , onInput SetName + ] + [] + ] + , div [ class "mt-2" ] + [ label [ class S.inputLabel ] + [ text texts.columns + ] + ] + , Html.map ColumnsMsg + (Comp.FixedDropdown.viewStyled2 columnsSettings + False + model.columnsValue + model.columnsModel + ) + ] + ] + + + +--- Helpers + + +gridStyle : Dashboard -> String +gridStyle db = + let + colStyle = + case db.columns of + 1 -> + "" + + 2 -> + "md:grid-cols-2" + + 3 -> + "md:grid-cols-3" + + 4 -> + "md:grid-cols-4" + + _ -> + "md:grid-cols-5" + in + "grid gap-4 grid-cols-1 " ++ colStyle + + +spanStyle : Box -> String +spanStyle box = + case box.colspan of + 1 -> + "" + + 2 -> + "col-span-1 md:col-span-2" + + 3 -> + "col-span-1 md:col-span-3" + + 4 -> + "col-span-1 md:col-span-4" + + _ -> + "col-span-1 md:col-span-5" diff --git a/modules/webapp/src/main/elm/Comp/DashboardView.elm b/modules/webapp/src/main/elm/Comp/DashboardView.elm index 9a4405d1..0cf20b72 100644 --- a/modules/webapp/src/main/elm/Comp/DashboardView.elm +++ b/modules/webapp/src/main/elm/Comp/DashboardView.elm @@ -1,7 +1,6 @@ module Comp.DashboardView exposing (Model, Msg, init, reloadData, update, view, viewBox) import Comp.BoxView -import Data.Box exposing (Box) import Data.Dashboard exposing (Dashboard) import Data.Flags exposing (Flags) import Data.UiSettings exposing (UiSettings) diff --git a/modules/webapp/src/main/elm/Comp/ItemColumnDropdown.elm b/modules/webapp/src/main/elm/Comp/ItemColumnDropdown.elm new file mode 100644 index 00000000..5bbbbe9c --- /dev/null +++ b/modules/webapp/src/main/elm/Comp/ItemColumnDropdown.elm @@ -0,0 +1,86 @@ +{- + Copyright 2020 Eike K. & Contributors + + SPDX-License-Identifier: AGPL-3.0-or-later +-} + + +module Comp.ItemColumnDropdown exposing (Model, Msg, getSelected, init, update, view) + +import Comp.Dropdown exposing (Option) +import Data.DropdownStyle +import Data.ItemColumn exposing (ItemColumn(..)) +import Data.UiSettings exposing (UiSettings) +import Html exposing (Html) +import Messages.Comp.ItemColumnDropdown exposing (Texts) + + +type Model + = Model (Comp.Dropdown.Model ItemColumn) + + +type Msg + = DropdownMsg (Comp.Dropdown.Msg ItemColumn) + + +init : List ItemColumn -> Model +init selected = + Model <| + Comp.Dropdown.makeMultipleList + { options = Data.ItemColumn.all, selected = selected } + + +getSelected : Model -> List ItemColumn +getSelected (Model dm) = + Comp.Dropdown.getSelected dm + + + +--- Update + + +update : Msg -> Model -> ( Model, Cmd Msg ) +update msg model = + let + dmodel = + case model of + Model a -> + a + in + case msg of + DropdownMsg lm -> + let + ( dm, dc ) = + Comp.Dropdown.update lm dmodel + in + ( Model dm, Cmd.map DropdownMsg dc ) + + + +--- View + + +itemOption : Texts -> ItemColumn -> Option +itemOption texts item = + { text = texts.column.label item + , additional = "" + } + + +view : Texts -> UiSettings -> Model -> Html Msg +view texts settings model = + let + viewSettings = + { makeOption = itemOption texts + , placeholder = texts.placeholder + , labelColor = \_ -> \_ -> "" + , style = Data.DropdownStyle.mainStyle + } + + dm = + case model of + Model a -> + a + in + Html.map DropdownMsg + (Comp.Dropdown.view2 viewSettings settings dm) diff --git a/modules/webapp/src/main/elm/Comp/ItemColumnView.elm b/modules/webapp/src/main/elm/Comp/ItemColumnView.elm new file mode 100644 index 00000000..e95ba8c5 --- /dev/null +++ b/modules/webapp/src/main/elm/Comp/ItemColumnView.elm @@ -0,0 +1,36 @@ +module Comp.ItemColumnView exposing (..) + +import Api.Model.ItemLight exposing (ItemLight) +import Data.ItemColumn exposing (ItemColumn(..)) +import Data.ItemTemplate exposing (TemplateContext) +import Data.UiSettings exposing (UiSettings) +import Html exposing (Attribute, Html, div, text) +import Html.Attributes exposing (class) + + +renderDiv : + TemplateContext + -> UiSettings + -> ItemColumn + -> List (Attribute msg) + -> ItemLight + -> Html msg +renderDiv ctx settings col attr item = + case col of + Tags -> + div attr + (List.map + (\t -> + div + [ class "label text-sm" + , class <| Data.UiSettings.tagColorString2 t settings + ] + [ text t.name ] + ) + item.tags + ) + + _ -> + div attr + [ text (Data.ItemColumn.renderString ctx col item) + ] diff --git a/modules/webapp/src/main/elm/Comp/MenuBar.elm b/modules/webapp/src/main/elm/Comp/MenuBar.elm index c25fa281..b5819ae2 100644 --- a/modules/webapp/src/main/elm/Comp/MenuBar.elm +++ b/modules/webapp/src/main/elm/Comp/MenuBar.elm @@ -308,18 +308,27 @@ makeButton btnType model = makeCheckbox : CheckboxData msg -> Html msg makeCheckbox model = + let + withId list = + if model.id == "" then + list + + else + id model.id :: list + in div [ class "" ] [ label [ class "inline-flex space-x-2 items-center" , for model.id ] [ input - [ type_ "checkbox" - , onCheck model.tagger - , checked model.value - , class S.checkboxInput - , id model.id - ] + (withId + [ type_ "checkbox" + , onCheck model.tagger + , checked model.value + , class S.checkboxInput + ] + ) [] , span [ class "truncate" ] [ text model.label diff --git a/modules/webapp/src/main/elm/Comp/PowerSearchInput.elm b/modules/webapp/src/main/elm/Comp/PowerSearchInput.elm index 1036452d..9dedaa91 100644 --- a/modules/webapp/src/main/elm/Comp/PowerSearchInput.elm +++ b/modules/webapp/src/main/elm/Comp/PowerSearchInput.elm @@ -11,6 +11,7 @@ module Comp.PowerSearchInput exposing , Msg , ViewSettings , init + , initWith , isValid , setSearchString , update @@ -45,6 +46,15 @@ init = } +initWith : String -> ( Model, Cmd Msg, Sub Msg ) +initWith qstr = + let + result = + update (setSearchString qstr) init + in + ( result.model, result.cmd, result.subs ) + + isValid : Model -> Bool isValid model = model.input /= Nothing && model.result.success diff --git a/modules/webapp/src/main/elm/Data/Box.elm b/modules/webapp/src/main/elm/Data/Box.elm index 1553b7d4..16629034 100644 --- a/modules/webapp/src/main/elm/Data/Box.elm +++ b/modules/webapp/src/main/elm/Data/Box.elm @@ -1,6 +1,6 @@ -module Data.Box exposing (Box) +module Data.Box exposing (Box, boxIcon, empty, messageBox, queryBox, statsBox, uploadBox) -import Data.BoxContent exposing (BoxContent) +import Data.BoxContent exposing (BoxContent(..)) type alias Box = @@ -10,3 +10,38 @@ type alias Box = , colspan : Int , content : BoxContent } + + +empty : BoxContent -> Box +empty cnt = + { name = "" + , visible = True + , decoration = True + , colspan = 1 + , content = cnt + } + + +boxIcon : Box -> String +boxIcon box = + Data.BoxContent.boxContentIcon box.content + + +queryBox : Box +queryBox = + empty (BoxQuery Data.BoxContent.emptyQueryData) + + +statsBox : Box +statsBox = + empty (BoxStats Data.BoxContent.emptyStatsData) + + +messageBox : Box +messageBox = + empty (BoxMessage Data.BoxContent.emptyMessageData) + + +uploadBox : Box +uploadBox = + empty (BoxUpload Data.BoxContent.emptyUploadData) diff --git a/modules/webapp/src/main/elm/Data/BoxContent.elm b/modules/webapp/src/main/elm/Data/BoxContent.elm index 7385c916..a898d4a8 100644 --- a/modules/webapp/src/main/elm/Data/BoxContent.elm +++ b/modules/webapp/src/main/elm/Data/BoxContent.elm @@ -3,18 +3,24 @@ module Data.BoxContent exposing , MessageData , QueryData , SearchQuery(..) - , SummaryData + , StatsData , SummaryShow(..) + , UploadData + , boxContentIcon + , emptyMessageData + , emptyQueryData + , emptyStatsData + , emptyUploadData ) -import Data.ItemTemplate exposing (ItemTemplate) +import Data.ItemColumn exposing (ItemColumn) type BoxContent - = BoxUpload (Maybe String) + = BoxUpload UploadData | BoxMessage MessageData | BoxQuery QueryData - | BoxSummary SummaryData + | BoxStats StatsData type alias MessageData = @@ -23,21 +29,56 @@ type alias MessageData = } +emptyMessageData : MessageData +emptyMessageData = + { title = "" + , body = "" + } + + +type alias UploadData = + { sourceId : Maybe String + } + + +emptyUploadData : UploadData +emptyUploadData = + { sourceId = Nothing + } + + type alias QueryData = { query : SearchQuery , limit : Int , details : Bool - , header : List String - , columns : List ItemTemplate + , columns : List ItemColumn + , showHeaders : Bool } -type alias SummaryData = +emptyQueryData : QueryData +emptyQueryData = + { query = SearchQueryString "" + , limit = 5 + , details = True + , columns = [] + , showHeaders = True + } + + +type alias StatsData = { query : SearchQuery , show : SummaryShow } +emptyStatsData : StatsData +emptyStatsData = + { query = SearchQueryString "" + , show = SummaryShowGeneral + } + + type SummaryShow = SummaryShowFields Bool | SummaryShowGeneral @@ -46,3 +87,19 @@ type SummaryShow type SearchQuery = SearchQueryString String | SearchQueryBookmark String + + +boxContentIcon : BoxContent -> String +boxContentIcon content = + case content of + BoxMessage _ -> + "fa fa-comment-alt font-thin" + + BoxUpload _ -> + "fa fa-file-upload" + + BoxQuery _ -> + "fa fa-search" + + BoxStats _ -> + "fa fa-chart-bar font-thin" diff --git a/modules/webapp/src/main/elm/Data/Icons.elm b/modules/webapp/src/main/elm/Data/Icons.elm index a1523966..2a769a37 100644 --- a/modules/webapp/src/main/elm/Data/Icons.elm +++ b/modules/webapp/src/main/elm/Data/Icons.elm @@ -39,8 +39,7 @@ module Data.Icons exposing , dueDate2 , dueDateIcon , dueDateIcon2 - , editNotes - , editNotesIcon + , editIcon , equipment , equipmentIcon , fileUploadIcon @@ -378,14 +377,14 @@ dueDateIcon2 classes = i [ class (dueDate2 ++ " " ++ classes) ] [] -editNotes : String -editNotes = - "comment alternate outline icon" +edit : String +edit = + "fa fa-edit font-thin" -editNotesIcon : Html msg -editNotesIcon = - i [ class editNotes ] [] +editIcon : String -> Html msg +editIcon classes = + i [ class edit, class classes ] [] addFiles2 : String diff --git a/modules/webapp/src/main/elm/Data/ItemColumn.elm b/modules/webapp/src/main/elm/Data/ItemColumn.elm new file mode 100644 index 00000000..15c5a288 --- /dev/null +++ b/modules/webapp/src/main/elm/Data/ItemColumn.elm @@ -0,0 +1,118 @@ +module Data.ItemColumn exposing (..) + +import Api.Model.ItemLight exposing (ItemLight) +import Data.ItemTemplate as IT exposing (TemplateContext) + + +type ItemColumn + = Name + | DateLong + | DateShort + | DueDateLong + | DueDateShort + | Folder + | Correspondent + | Concerning + | Tags + + +all : List ItemColumn +all = + [ Name, DateLong, DateShort, DueDateLong, DueDateShort, Folder, Correspondent, Concerning, Tags ] + + +renderString : TemplateContext -> ItemColumn -> ItemLight -> String +renderString ctx col item = + case col of + Name -> + IT.render IT.name ctx item + + DateShort -> + IT.render IT.dateShort ctx item + + DateLong -> + IT.render IT.dateLong ctx item + + DueDateShort -> + IT.render IT.dueDateShort ctx item + + DueDateLong -> + IT.render IT.dueDateLong ctx item + + Folder -> + IT.render IT.folder ctx item + + Correspondent -> + IT.render IT.correspondent ctx item + + Concerning -> + IT.render IT.concerning ctx item + + Tags -> + List.map .name item.tags + |> String.join ", " + + +asString : ItemColumn -> String +asString col = + case col of + Name -> + "name" + + DateShort -> + "dateshort" + + DateLong -> + "datelong" + + DueDateShort -> + "duedateshort" + + DueDateLong -> + "duedatelong" + + Folder -> + "folder" + + Correspondent -> + "correspodnent" + + Concerning -> + "concerning" + + Tags -> + "tags" + + +fromString : String -> Maybe ItemColumn +fromString str = + case String.toLower str of + "name" -> + Just Name + + "dateshort" -> + Just DateShort + + "datelong" -> + Just DateLong + + "duedateshort" -> + Just DueDateShort + + "duedatelong" -> + Just DueDateLong + + "folder" -> + Just Folder + + "correspodnent" -> + Just Correspondent + + "concerning" -> + Just Concerning + + "tags" -> + Just Tags + + _ -> + Nothing diff --git a/modules/webapp/src/main/elm/Messages/Comp/BoxEdit.elm b/modules/webapp/src/main/elm/Messages/Comp/BoxEdit.elm new file mode 100644 index 00000000..9b622de1 --- /dev/null +++ b/modules/webapp/src/main/elm/Messages/Comp/BoxEdit.elm @@ -0,0 +1,67 @@ +module Messages.Comp.BoxEdit exposing (Texts, de, gb) + +import Messages.Basics +import Messages.Comp.BoxMessageEdit +import Messages.Comp.BoxQueryEdit +import Messages.Comp.BoxStatsEdit +import Messages.Comp.BoxUploadEdit +import Messages.Data.BoxContent + + +type alias Texts = + { messageEdit : Messages.Comp.BoxMessageEdit.Texts + , uploadEdit : Messages.Comp.BoxUploadEdit.Texts + , queryEdit : Messages.Comp.BoxQueryEdit.Texts + , statsEdit : Messages.Comp.BoxStatsEdit.Texts + , boxContent : Messages.Data.BoxContent.Texts + , basics : Messages.Basics.Texts + , namePlaceholder : String + , visible : String + , decorations : String + , colspan : String + , contentProperties : String + , reallyDeleteBox : String + , moveToLeft : String + , moveToRight : String + , deleteBox : String + } + + +gb : Texts +gb = + { messageEdit = Messages.Comp.BoxMessageEdit.gb + , uploadEdit = Messages.Comp.BoxUploadEdit.gb + , queryEdit = Messages.Comp.BoxQueryEdit.gb + , statsEdit = Messages.Comp.BoxStatsEdit.gb + , boxContent = Messages.Data.BoxContent.gb + , basics = Messages.Basics.gb + , namePlaceholder = "Box name" + , visible = "Visible" + , decorations = "Box decorations" + , colspan = "Column span" + , contentProperties = "Content" + , reallyDeleteBox = "Really delete this box?" + , moveToLeft = "Move to left" + , moveToRight = "Move to right" + , deleteBox = "Delete box" + } + + +de : Texts +de = + { messageEdit = Messages.Comp.BoxMessageEdit.de + , uploadEdit = Messages.Comp.BoxUploadEdit.de + , queryEdit = Messages.Comp.BoxQueryEdit.de + , statsEdit = Messages.Comp.BoxStatsEdit.de + , boxContent = Messages.Data.BoxContent.de + , basics = Messages.Basics.de + , namePlaceholder = "Boxname" + , visible = "Sichtbar" + , decorations = "Kachel-Dekoration anzeigen" + , colspan = "Spalten überspannen" + , contentProperties = "Inhalt" + , reallyDeleteBox = "Die Kachel wirklich entfernen?" + , moveToLeft = "Nach links verschieben" + , moveToRight = "Nach rechts verschieben" + , deleteBox = "Kachel entfernen" + } diff --git a/modules/webapp/src/main/elm/Messages/Comp/BoxMessageEdit.elm b/modules/webapp/src/main/elm/Messages/Comp/BoxMessageEdit.elm new file mode 100644 index 00000000..fbe3ab90 --- /dev/null +++ b/modules/webapp/src/main/elm/Messages/Comp/BoxMessageEdit.elm @@ -0,0 +1,30 @@ +module Messages.Comp.BoxMessageEdit exposing (Texts, de, gb) + + +type alias Texts = + { titleLabel : String + , titlePlaceholder : String + , bodyLabel : String + , bodyPlaceholder : String + , infoText : String + } + + +gb : Texts +gb = + { titleLabel = "Title" + , titlePlaceholder = "Message title…" + , bodyLabel = "Body" + , bodyPlaceholder = "Message body…" + , infoText = "Markdown can be used in both fields for simple formatting." + } + + +de : Texts +de = + { titleLabel = "Titel" + , titlePlaceholder = "Titel…" + , bodyLabel = "Nachricht" + , bodyPlaceholder = "Text…" + , infoText = "Markdown kann in beiden Feldern für einfache Formatierung verwendet werden." + } diff --git a/modules/webapp/src/main/elm/Messages/Comp/BoxQueryEdit.elm b/modules/webapp/src/main/elm/Messages/Comp/BoxQueryEdit.elm new file mode 100644 index 00000000..2aa3032f --- /dev/null +++ b/modules/webapp/src/main/elm/Messages/Comp/BoxQueryEdit.elm @@ -0,0 +1,27 @@ +module Messages.Comp.BoxQueryEdit exposing (Texts, de, gb) + +import Messages.Comp.BoxSearchQueryInput +import Messages.Comp.ItemColumnDropdown + + +type alias Texts = + { columnDropdown : Messages.Comp.ItemColumnDropdown.Texts + , searchQuery : Messages.Comp.BoxSearchQueryInput.Texts + , showColumnHeaders : String + } + + +gb : Texts +gb = + { columnDropdown = Messages.Comp.ItemColumnDropdown.gb + , searchQuery = Messages.Comp.BoxSearchQueryInput.gb + , showColumnHeaders = "Show column headers" + } + + +de : Texts +de = + { columnDropdown = Messages.Comp.ItemColumnDropdown.de + , searchQuery = Messages.Comp.BoxSearchQueryInput.de + , showColumnHeaders = "Spaltennamen anzeigen" + } diff --git a/modules/webapp/src/main/elm/Messages/Comp/BoxQueryView.elm b/modules/webapp/src/main/elm/Messages/Comp/BoxQueryView.elm index 7b13ab8a..5afce131 100644 --- a/modules/webapp/src/main/elm/Messages/Comp/BoxQueryView.elm +++ b/modules/webapp/src/main/elm/Messages/Comp/BoxQueryView.elm @@ -5,6 +5,7 @@ import Http import Messages.Basics import Messages.Comp.HttpError import Messages.Data.Direction +import Messages.Data.ItemColumn import Messages.DateFormat as DF import Messages.UiLanguage @@ -15,6 +16,7 @@ type alias Texts = , basics : Messages.Basics.Texts , noResults : String , templateCtx : IT.TemplateContext + , itemColumn : Messages.Data.ItemColumn.Texts } @@ -29,6 +31,7 @@ gb = , dateFormatShort = DF.formatDateShort Messages.UiLanguage.English , directionLabel = Messages.Data.Direction.gb } + , itemColumn = Messages.Data.ItemColumn.gb } @@ -43,4 +46,5 @@ de = , dateFormatShort = DF.formatDateShort Messages.UiLanguage.German , directionLabel = Messages.Data.Direction.de } + , itemColumn = Messages.Data.ItemColumn.de } diff --git a/modules/webapp/src/main/elm/Messages/Comp/BoxSearchQueryInput.elm b/modules/webapp/src/main/elm/Messages/Comp/BoxSearchQueryInput.elm new file mode 100644 index 00000000..543672ca --- /dev/null +++ b/modules/webapp/src/main/elm/Messages/Comp/BoxSearchQueryInput.elm @@ -0,0 +1,29 @@ +module Messages.Comp.BoxSearchQueryInput exposing (Texts, de, gb) + +import Messages.Comp.BookmarkDropdown + + +type alias Texts = + { bookmarkDropdown : Messages.Comp.BookmarkDropdown.Texts + , switchToBookmark : String + , switchToQuery : String + , searchPlaceholder : String + } + + +gb : Texts +gb = + { bookmarkDropdown = Messages.Comp.BookmarkDropdown.gb + , switchToBookmark = "Bookmarks" + , switchToQuery = "Search query" + , searchPlaceholder = "Search…" + } + + +de : Texts +de = + { bookmarkDropdown = Messages.Comp.BookmarkDropdown.de + , switchToBookmark = "Bookmarks" + , switchToQuery = "Suchabfrage" + , searchPlaceholder = "Abfrage…" + } diff --git a/modules/webapp/src/main/elm/Messages/Comp/BoxStatsEdit.elm b/modules/webapp/src/main/elm/Messages/Comp/BoxStatsEdit.elm new file mode 100644 index 00000000..4bd13a4a --- /dev/null +++ b/modules/webapp/src/main/elm/Messages/Comp/BoxStatsEdit.elm @@ -0,0 +1,32 @@ +module Messages.Comp.BoxStatsEdit exposing (Texts, de, gb) + +import Messages.Comp.BoxSearchQueryInput + + +type alias Texts = + { searchQuery : Messages.Comp.BoxSearchQueryInput.Texts + , fieldStatistics : String + , basicNumbers : String + , showLabel : String + , showItemCount : String + } + + +gb : Texts +gb = + { searchQuery = Messages.Comp.BoxSearchQueryInput.gb + , fieldStatistics = "Field statistics" + , basicNumbers = "Basic numbers" + , showLabel = "Display" + , showItemCount = "Show item count" + } + + +de : Texts +de = + { searchQuery = Messages.Comp.BoxSearchQueryInput.de + , fieldStatistics = "Benutzerfeld Statistiken" + , basicNumbers = "Allgemeine Zahlen" + , showLabel = "Anzeige" + , showItemCount = "Gesamtanzahl Dokumente mit anzeigen" + } diff --git a/modules/webapp/src/main/elm/Messages/Comp/BoxSummaryView.elm b/modules/webapp/src/main/elm/Messages/Comp/BoxStatsView.elm similarity index 91% rename from modules/webapp/src/main/elm/Messages/Comp/BoxSummaryView.elm rename to modules/webapp/src/main/elm/Messages/Comp/BoxStatsView.elm index 865d5848..c73961e4 100644 --- a/modules/webapp/src/main/elm/Messages/Comp/BoxSummaryView.elm +++ b/modules/webapp/src/main/elm/Messages/Comp/BoxStatsView.elm @@ -1,4 +1,4 @@ -module Messages.Comp.BoxSummaryView exposing (Texts, de, gb) +module Messages.Comp.BoxStatsView exposing (Texts, de, gb) import Http import Messages.Basics diff --git a/modules/webapp/src/main/elm/Messages/Comp/BoxUploadEdit.elm b/modules/webapp/src/main/elm/Messages/Comp/BoxUploadEdit.elm new file mode 100644 index 00000000..ef0f1dbb --- /dev/null +++ b/modules/webapp/src/main/elm/Messages/Comp/BoxUploadEdit.elm @@ -0,0 +1,24 @@ +module Messages.Comp.BoxUploadEdit exposing (Texts, de, gb) + + +type alias Texts = + { sourceLabel : String + , sourcePlaceholder : String + , infoText : String + } + + +gb : Texts +gb = + { sourceLabel = "Source" + , sourcePlaceholder = "Choose source…" + , infoText = "Optionally choose a source otherwise default settings apply to all uploads." + } + + +de : Texts +de = + { sourceLabel = "Quelle" + , sourcePlaceholder = "Quelle…" + , infoText = "Optional kann eine Quelle als Einstellung gewählt werden, sonst werden Standardeinstellungen verwendet." + } diff --git a/modules/webapp/src/main/elm/Messages/Comp/BoxView.elm b/modules/webapp/src/main/elm/Messages/Comp/BoxView.elm index 34ac5340..96bd4447 100644 --- a/modules/webapp/src/main/elm/Messages/Comp/BoxView.elm +++ b/modules/webapp/src/main/elm/Messages/Comp/BoxView.elm @@ -1,13 +1,13 @@ module Messages.Comp.BoxView exposing (Texts, de, gb) import Messages.Comp.BoxQueryView -import Messages.Comp.BoxSummaryView +import Messages.Comp.BoxStatsView import Messages.Comp.BoxUploadView type alias Texts = { queryView : Messages.Comp.BoxQueryView.Texts - , summaryView : Messages.Comp.BoxSummaryView.Texts + , statsView : Messages.Comp.BoxStatsView.Texts , uploadView : Messages.Comp.BoxUploadView.Texts } @@ -15,7 +15,7 @@ type alias Texts = gb : Texts gb = { queryView = Messages.Comp.BoxQueryView.gb - , summaryView = Messages.Comp.BoxSummaryView.gb + , statsView = Messages.Comp.BoxStatsView.gb , uploadView = Messages.Comp.BoxUploadView.gb } @@ -23,6 +23,6 @@ gb = de : Texts de = { queryView = Messages.Comp.BoxQueryView.de - , summaryView = Messages.Comp.BoxSummaryView.de + , statsView = Messages.Comp.BoxStatsView.de , uploadView = Messages.Comp.BoxUploadView.de } diff --git a/modules/webapp/src/main/elm/Messages/Comp/DashboardEdit.elm b/modules/webapp/src/main/elm/Messages/Comp/DashboardEdit.elm new file mode 100644 index 00000000..70d2e468 --- /dev/null +++ b/modules/webapp/src/main/elm/Messages/Comp/DashboardEdit.elm @@ -0,0 +1,40 @@ +module Messages.Comp.DashboardEdit exposing (Texts, de, gb) + +import Messages.Basics +import Messages.Comp.BoxEdit +import Messages.Data.BoxContent + + +type alias Texts = + { boxView : Messages.Comp.BoxEdit.Texts + , boxContent : Messages.Data.BoxContent.Texts + , basics : Messages.Basics.Texts + , namePlaceholder : String + , columns : String + , dashboardBoxes : String + , newBox : String + } + + +gb : Texts +gb = + { boxView = Messages.Comp.BoxEdit.gb + , boxContent = Messages.Data.BoxContent.gb + , basics = Messages.Basics.gb + , namePlaceholder = "Dashboard name" + , columns = "Columns" + , dashboardBoxes = "Dashboard Boxes" + , newBox = "New box" + } + + +de : Texts +de = + { boxView = Messages.Comp.BoxEdit.de + , boxContent = Messages.Data.BoxContent.de + , basics = Messages.Basics.de + , namePlaceholder = "Dashboardname" + , columns = "Spalten" + , dashboardBoxes = "Dashboard Kacheln" + , newBox = "Neue Kachel" + } diff --git a/modules/webapp/src/main/elm/Messages/Comp/ItemColumnDropdown.elm b/modules/webapp/src/main/elm/Messages/Comp/ItemColumnDropdown.elm new file mode 100644 index 00000000..fd66b3b1 --- /dev/null +++ b/modules/webapp/src/main/elm/Messages/Comp/ItemColumnDropdown.elm @@ -0,0 +1,38 @@ +{- + Copyright 2020 Eike K. & Contributors + + SPDX-License-Identifier: AGPL-3.0-or-later +-} + + +module Messages.Comp.ItemColumnDropdown exposing + ( Texts + , de + , gb + ) + +import Messages.Basics +import Messages.Data.ItemColumn + + +type alias Texts = + { basics : Messages.Basics.Texts + , column : Messages.Data.ItemColumn.Texts + , placeholder : String + } + + +gb : Texts +gb = + { basics = Messages.Basics.gb + , column = Messages.Data.ItemColumn.gb + , placeholder = "Choose…" + } + + +de : Texts +de = + { basics = Messages.Basics.de + , column = Messages.Data.ItemColumn.de + , placeholder = "Wähle…" + } diff --git a/modules/webapp/src/main/elm/Messages/Data/BoxContent.elm b/modules/webapp/src/main/elm/Messages/Data/BoxContent.elm new file mode 100644 index 00000000..d1b8fa04 --- /dev/null +++ b/modules/webapp/src/main/elm/Messages/Data/BoxContent.elm @@ -0,0 +1,54 @@ +module Messages.Data.BoxContent exposing (Texts, de, gb) + +import Data.BoxContent exposing (BoxContent(..)) + + +type alias Texts = + { forContent : BoxContent -> String + , queryBox : String + , statsBox : String + , messageBox : String + , uploadBox : String + } + + +gb : Texts +gb = + updateForContent + { forContent = \_ -> "" + , queryBox = "Query box" + , statsBox = "Statistics box" + , messageBox = "Message box" + , uploadBox = "Upload box" + } + + +de : Texts +de = + updateForContent + { forContent = \_ -> "" + , queryBox = "Suchabfrage Kachel" + , statsBox = "Statistik Kachel" + , messageBox = "Mitteilung Kachel" + , uploadBox = "Datei hochladen Kachel" + } + + +updateForContent : Texts -> Texts +updateForContent init = + { init + | forContent = + \cnt -> + case cnt of + BoxMessage _ -> + init.messageBox + + BoxUpload _ -> + init.uploadBox + + BoxQuery _ -> + init.queryBox + + BoxStats _ -> + init.statsBox + } diff --git a/modules/webapp/src/main/elm/Messages/Data/ItemColumn.elm b/modules/webapp/src/main/elm/Messages/Data/ItemColumn.elm new file mode 100644 index 00000000..de49ee83 --- /dev/null +++ b/modules/webapp/src/main/elm/Messages/Data/ItemColumn.elm @@ -0,0 +1,115 @@ +module Messages.Data.ItemColumn exposing (Texts, de, gb) + +import Data.ItemColumn exposing (ItemColumn(..)) + + +type alias Texts = + { header : ItemColumn -> String + , label : ItemColumn -> String + } + + +gb : Texts +gb = + let + headerName col = + case col of + Name -> + "Name" + + DateLong -> + "Date" + + DateShort -> + "Date" + + DueDateLong -> + "Due date" + + DueDateShort -> + "Due date" + + Folder -> + "Folder" + + Correspondent -> + "Correspondent" + + Concerning -> + "Concerning" + + Tags -> + "Tags" + in + { header = headerName + , label = + \col -> + case col of + DateShort -> + headerName col ++ " (short)" + + DateLong -> + headerName col ++ " (long)" + + DueDateShort -> + headerName col ++ " (short)" + + DueDateLong -> + headerName col ++ " (long)" + + _ -> + headerName col + } + + +de : Texts +de = + let + headerName col = + case col of + Name -> + "Name" + + DateLong -> + "Datum" + + DateShort -> + "Datum" + + DueDateLong -> + "Fälligkeitsdatum" + + DueDateShort -> + "Fälligkeitsdatum" + + Folder -> + "Ordner" + + Correspondent -> + "Korrespondent" + + Concerning -> + "Betreffend" + + Tags -> + "Tags" + in + { header = headerName + , label = + \col -> + case col of + DateShort -> + headerName col ++ " (kurz)" + + DateLong -> + headerName col ++ " (lang)" + + DueDateShort -> + headerName col ++ " (kurz)" + + DueDateLong -> + headerName col ++ " (lang)" + + _ -> + headerName col + } diff --git a/modules/webapp/src/main/elm/Messages/Page/Dashboard.elm b/modules/webapp/src/main/elm/Messages/Page/Dashboard.elm index 37aa5681..f8c85467 100644 --- a/modules/webapp/src/main/elm/Messages/Page/Dashboard.elm +++ b/modules/webapp/src/main/elm/Messages/Page/Dashboard.elm @@ -2,6 +2,7 @@ module Messages.Page.Dashboard exposing (Texts, de, gb) import Messages.Basics import Messages.Comp.BookmarkChooser +import Messages.Comp.DashboardEdit import Messages.Comp.DashboardView import Messages.Comp.EquipmentManage import Messages.Comp.FolderManage @@ -30,6 +31,7 @@ type alias Texts = , folderManage : Messages.Comp.FolderManage.Texts , uploadForm : Messages.Comp.UploadForm.Texts , dashboard : Messages.Comp.DashboardView.Texts + , dashboardEdit : Messages.Comp.DashboardEdit.Texts , defaultDashboard : Messages.Page.DefaultDashboard.Texts , manage : String , dashboardLink : String @@ -38,6 +40,7 @@ type alias Texts = , settings : String , documentation : String , uploadFiles : String + , editDashboard : String } @@ -56,6 +59,7 @@ gb = , folderManage = Messages.Comp.FolderManage.gb , uploadForm = Messages.Comp.UploadForm.gb , dashboard = Messages.Comp.DashboardView.gb + , dashboardEdit = Messages.Comp.DashboardEdit.gb , defaultDashboard = Messages.Page.DefaultDashboard.gb , manage = "Manage" , dashboardLink = "Dasbhoard" @@ -64,6 +68,7 @@ gb = , settings = "Settings" , documentation = "Documentation" , uploadFiles = "Upload documents" + , editDashboard = "Edit Dashboard" } @@ -82,12 +87,14 @@ de = , folderManage = Messages.Comp.FolderManage.de , uploadForm = Messages.Comp.UploadForm.de , dashboard = Messages.Comp.DashboardView.de + , dashboardEdit = Messages.Comp.DashboardEdit.de , defaultDashboard = Messages.Page.DefaultDashboard.de - , manage = "Managen" + , manage = "Verwalten" , dashboardLink = "Dasbhoard" , bookmarks = "Bookmarks" , misc = "Anderes" , settings = "Einstellungen" , documentation = "Dokumentation" , uploadFiles = "Dokumente hochladen" + , editDashboard = "Dashboard ändern" } diff --git a/modules/webapp/src/main/elm/Messages/Page/DefaultDashboard.elm b/modules/webapp/src/main/elm/Messages/Page/DefaultDashboard.elm index 82fa5541..135c7c37 100644 --- a/modules/webapp/src/main/elm/Messages/Page/DefaultDashboard.elm +++ b/modules/webapp/src/main/elm/Messages/Page/DefaultDashboard.elm @@ -1,8 +1,6 @@ module Messages.Page.DefaultDashboard exposing (Texts, de, gb) -import Data.Fields exposing (Field) import Messages.Basics -import Messages.Data.Fields type alias Texts = @@ -13,36 +11,26 @@ type alias Texts = , welcomeBody : String , summaryName : String , dueInDays : Int -> String - , dueHeaderColumns : List String , newDocsName : String } gb : Texts gb = - let - b = - Messages.Basics.gb - in - { basics = b + { basics = Messages.Basics.gb , default = "Default" , welcomeName = "Welcome Message" , welcomeTitle = "# Welcome to Docspell" , welcomeBody = "Docspell keeps your documents organized." , summaryName = "Summary" , dueInDays = \n -> "Due in " ++ String.fromInt n ++ " days" - , dueHeaderColumns = dueHeaderCols b Messages.Data.Fields.gb , newDocsName = "New Documents" } de : Texts de = - let - b = - Messages.Basics.de - in - { basics = b + { basics = Messages.Basics.de , default = "Standard" , welcomeName = "Willkommens-Nachricht" , welcomeTitle = "# Willkommen zu Docspell" @@ -50,10 +38,4 @@ de = , summaryName = "Zahlen" , dueInDays = \n -> "Fällig in " ++ String.fromInt n ++ " Tagen" , newDocsName = "Neue Dokumente" - , dueHeaderColumns = dueHeaderCols b Messages.Data.Fields.de } - - -dueHeaderCols : Messages.Basics.Texts -> (Field -> String) -> List String -dueHeaderCols b d = - [ b.name, b.correspondent, d Data.Fields.DueDate ] diff --git a/modules/webapp/src/main/elm/Page/Dashboard/Data.elm b/modules/webapp/src/main/elm/Page/Dashboard/Data.elm index 9350ee87..04a33328 100644 --- a/modules/webapp/src/main/elm/Page/Dashboard/Data.elm +++ b/modules/webapp/src/main/elm/Page/Dashboard/Data.elm @@ -11,12 +11,14 @@ module Page.Dashboard.Data exposing , Msg(..) , SideMenuModel , init - , reloadDashboard + , isHomeContent + , reloadDashboardData , reloadUiSettings ) import Api import Comp.BookmarkChooser +import Comp.DashboardEdit import Comp.DashboardView import Comp.EquipmentManage import Comp.FolderManage @@ -72,14 +74,14 @@ initCmd flags = Api.getBookmarks flags ignoreBookmarkError -reloadDashboard : Msg -reloadDashboard = +reloadDashboardData : Msg +reloadDashboardData = ReloadDashboardData reloadUiSettings : Msg reloadUiSettings = - InitDashboard + ReloadDashboard type Msg @@ -96,6 +98,7 @@ type Msg | FolderMsg Comp.FolderManage.Msg | UploadMsg Comp.UploadForm.Msg | DashboardMsg Comp.DashboardView.Msg + | DashboardEditMsg Comp.DashboardEdit.Msg | InitNotificationHook | InitDashboard | InitPeriodicQuery @@ -107,7 +110,9 @@ type Msg | InitTags | InitFolder | InitUpload + | InitEditDashboard | ReloadDashboardData + | ReloadDashboard type Content @@ -122,3 +127,14 @@ type Content | Tags Comp.TagManage.Model | Folder Comp.FolderManage.Model | Upload Comp.UploadForm.Model + | Edit Comp.DashboardEdit.Model + + +isHomeContent : Content -> Bool +isHomeContent cnt = + case cnt of + Home _ -> + True + + _ -> + False diff --git a/modules/webapp/src/main/elm/Page/Dashboard/DefaultDashboard.elm b/modules/webapp/src/main/elm/Page/Dashboard/DefaultDashboard.elm index 7e918555..ca3a57d8 100644 --- a/modules/webapp/src/main/elm/Page/Dashboard/DefaultDashboard.elm +++ b/modules/webapp/src/main/elm/Page/Dashboard/DefaultDashboard.elm @@ -4,7 +4,7 @@ import Data.Box exposing (Box) import Data.BoxContent exposing (BoxContent(..), SearchQuery(..), SummaryShow(..)) import Data.Dashboard exposing (Dashboard) import Data.Flags exposing (Flags) -import Data.ItemTemplate as IT +import Data.ItemColumn as IC import Data.UiSettings exposing (UiSettings) import Messages import Messages.Page.DefaultDashboard exposing (Texts) @@ -67,7 +67,7 @@ newDocuments texts = { query = SearchQueryString "inbox:yes" , limit = 5 , details = True - , header = [] + , showHeaders = False , columns = [] } } @@ -84,11 +84,11 @@ dueDocuments texts = { query = SearchQueryString "due>today;-10d due VersionInfo -> UiSettings -> SideMenuModel -> Html Msg +view : Texts -> VersionInfo -> UiSettings -> Model -> Html Msg view texts versionInfo _ model = div [ class "flex flex-col flex-grow" ] [ div [ class "mt-2" ] @@ -32,7 +32,7 @@ view texts versionInfo _ model = (Comp.BookmarkChooser.viewWith { showUser = True, showCollective = True, showShares = False } texts.bookmarkChooser - model.bookmarkChooser + model.sideMenu.bookmarkChooser Comp.BookmarkChooser.emptySelection ) ] @@ -69,6 +69,13 @@ view texts versionInfo _ model = ] , div [ class "ml-2" ] [ menuLink [ onClick InitUpload, href "#" ] (Icons.fileUploadIcon "") texts.uploadFiles + , menuLink + [ onClick InitEditDashboard + , classList [ ( "hidden", not (isHomeContent model.content) ) ] + , href "#" + ] + (Icons.editIcon "") + texts.editDashboard ] , div [ class "mt-2 opacity-75" ] [ menuLink [ href Data.UiSettings.documentationSite, target "_blank" ] (Icons.documentationIcon "") texts.documentation diff --git a/modules/webapp/src/main/elm/Page/Dashboard/Update.elm b/modules/webapp/src/main/elm/Page/Dashboard/Update.elm index 6b131524..3bd1b44d 100644 --- a/modules/webapp/src/main/elm/Page/Dashboard/Update.elm +++ b/modules/webapp/src/main/elm/Page/Dashboard/Update.elm @@ -9,6 +9,7 @@ module Page.Dashboard.Update exposing (update) import Browser.Navigation as Nav import Comp.BookmarkChooser +import Comp.DashboardEdit import Comp.DashboardView import Comp.EquipmentManage import Comp.FolderManage @@ -27,7 +28,6 @@ import Page exposing (Page(..)) import Page.Dashboard.Data exposing (..) import Page.Dashboard.DefaultDashboard import Set -import Styles exposing (content) update : Texts -> UiSettings -> Nav.Key -> Flags -> Msg -> Model -> ( Model, Cmd Msg, Sub Msg ) @@ -66,14 +66,17 @@ update texts settings navKey flags msg model = update texts settings navKey flags ReloadDashboardData model _ -> - let - board = - Page.Dashboard.DefaultDashboard.getDefaultDashboard flags settings + update texts settings navKey flags ReloadDashboard model - ( dm, dc ) = - Comp.DashboardView.init flags board - in - ( { model | content = Home dm }, Cmd.map DashboardMsg dc, Sub.none ) + ReloadDashboard -> + let + board = + Page.Dashboard.DefaultDashboard.getDefaultDashboard flags settings + + ( dm, dc ) = + Comp.DashboardView.init flags board + in + ( { model | content = Home dm }, Cmd.map DashboardMsg dc, Sub.none ) InitNotificationHook -> let @@ -145,6 +148,21 @@ update texts settings navKey flags msg model = in ( { model | content = Upload um }, Cmd.none, Sub.none ) + InitEditDashboard -> + case model.content of + Home m -> + let + ( dm, dc, ds ) = + Comp.DashboardEdit.init flags m.dashboard + in + ( { model | content = Edit dm } + , Cmd.map DashboardEditMsg dc + , Sub.map DashboardEditMsg ds + ) + + _ -> + unit model + NotificationHookMsg lm -> case model.content of Webhook nhm -> @@ -283,6 +301,39 @@ update texts settings navKey flags msg model = _ -> unit model + DashboardEditMsg lm -> + case model.content of + Edit m -> + let + result = + Comp.DashboardEdit.update flags lm m + in + case result.action of + Comp.DashboardEdit.SubmitNone -> + ( { model | content = Edit result.model } + , Cmd.map DashboardEditMsg result.cmd + , Sub.map DashboardEditMsg result.sub + ) + + Comp.DashboardEdit.SubmitSave board -> + let + ( dm, dc ) = + Comp.DashboardView.init flags board + in + ( { model | content = Home dm }, Cmd.map DashboardMsg dc, Sub.none ) + + Comp.DashboardEdit.SubmitCancel -> + update texts settings navKey flags ReloadDashboard model + + Comp.DashboardEdit.SubmitDelete _ -> + ( { model | content = Edit result.model } + , Cmd.map DashboardEditMsg result.cmd + , Sub.map DashboardEditMsg result.sub + ) + + _ -> + unit model + ReloadDashboardData -> let lm = diff --git a/modules/webapp/src/main/elm/Page/Dashboard/View.elm b/modules/webapp/src/main/elm/Page/Dashboard/View.elm index dfa03b58..5bbd4091 100644 --- a/modules/webapp/src/main/elm/Page/Dashboard/View.elm +++ b/modules/webapp/src/main/elm/Page/Dashboard/View.elm @@ -8,6 +8,7 @@ module Page.Dashboard.View exposing (viewContent, viewSidebar) import Api.Model.VersionInfo exposing (VersionInfo) +import Comp.DashboardEdit import Comp.DashboardView import Comp.EquipmentManage import Comp.FolderManage @@ -37,7 +38,7 @@ viewSidebar texts visible flags versionInfo settings model = , class S.sidebarBg , classList [ ( "hidden", not visible ) ] ] - [ SideMenu.view texts versionInfo settings model.sideMenu + [ SideMenu.view texts versionInfo settings model ] @@ -52,6 +53,10 @@ viewContent texts flags settings model = Html.map DashboardMsg (Comp.DashboardView.view texts.dashboard flags settings m) + Edit m -> + Html.map DashboardEditMsg + (Comp.DashboardEdit.view texts.dashboardEdit flags settings m) + Webhook m -> viewHookManage texts settings m