Select list/tile view and store to ui settings

Issue: #526
This commit is contained in:
eikek 2021-12-13 14:49:22 +01:00
parent 05843876cc
commit 1eb1db730c
20 changed files with 850 additions and 75 deletions

View File

@ -12,10 +12,9 @@ module Comp.ItemCard exposing
, ViewConfig
, init
, update
, view2
, view
)
import Api
import Api.Model.AttachmentLight exposing (AttachmentLight)
import Api.Model.HighlightEntry exposing (HighlightEntry)
import Api.Model.ItemLight exposing (ItemLight)
@ -24,6 +23,7 @@ import Data.Direction
import Data.Fields
import Data.Flags exposing (Flags)
import Data.Icons as Icons
import Data.ItemArrange exposing (ItemArrange)
import Data.ItemSelection exposing (ItemSelection)
import Data.ItemTemplate as IT
import Data.UiSettings exposing (UiSettings)
@ -52,6 +52,7 @@ type Msg
| ToggleSelectItem (Set String) String
| ItemDDMsg DD.Msg
| SetLinkTarget LinkTarget
| ToggleRowOpen String
type alias ViewConfig =
@ -61,6 +62,8 @@ type alias ViewConfig =
, previewUrlFallback : ItemLight -> String
, attachUrl : AttachmentLight -> String
, detailPage : ItemLight -> Page
, isRowOpen : Bool
, arrange : ItemArrange
}
@ -69,6 +72,7 @@ type alias UpdateResult =
, dragModel : DD.Model
, selection : ItemSelection
, linkTarget : LinkTarget
, toggleRow : Maybe String
}
@ -112,12 +116,15 @@ currentPosition model item =
update : DD.Model -> Msg -> Model -> UpdateResult
update ddm msg model =
case msg of
ToggleRowOpen id ->
UpdateResult model ddm Data.ItemSelection.Inactive LinkNone (Just id)
ItemDDMsg lm ->
let
ddd =
DD.update lm ddm
in
UpdateResult model ddd.model Data.ItemSelection.Inactive LinkNone
UpdateResult model ddd.model Data.ItemSelection.Inactive LinkNone Nothing
ToggleSelectItem ids id ->
let
@ -128,7 +135,7 @@ update ddm msg model =
else
Set.insert id ids
in
UpdateResult model ddm (Data.ItemSelection.Active newSet) LinkNone
UpdateResult model ddm (Data.ItemSelection.Active newSet) LinkNone Nothing
CyclePreview item ->
let
@ -142,17 +149,28 @@ update ddm msg model =
ddm
Data.ItemSelection.Inactive
LinkNone
Nothing
SetLinkTarget target ->
UpdateResult model ddm Data.ItemSelection.Inactive target
UpdateResult model ddm Data.ItemSelection.Inactive target Nothing
--- View2
view2 : Texts -> ViewConfig -> UiSettings -> Flags -> Model -> ItemLight -> Html Msg
view2 texts cfg settings flags model item =
view : Texts -> ViewConfig -> UiSettings -> Flags -> Model -> ItemLight -> Html Msg
view texts cfg settings flags model item =
case cfg.arrange of
Data.ItemArrange.List ->
viewRow texts cfg settings flags model item
Data.ItemArrange.Cards ->
viewCard texts cfg settings flags model item
viewRow : Texts -> ViewConfig -> UiSettings -> Flags -> Model -> ItemLight -> Html Msg
viewRow texts cfg settings flags model item =
let
isCreated =
item.state == "created"
@ -170,19 +188,304 @@ view2 texts cfg settings flags model item =
else
""
attachCount =
List.length item.attachments
rowOpen =
cfg.isRowOpen
mkAttachUrl attach =
Data.UiSettings.pdfUrl settings flags (cfg.attachUrl attach)
mainAttach =
currentAttachment model item
attachUrl =
Maybe.map mkAttachUrl mainAttach
|> Maybe.withDefault "/api/v1/sec/attachment/none"
fieldHidden f =
Data.UiSettings.fieldHidden settings f
cardAction =
case cfg.selection of
Data.ItemSelection.Inactive ->
[ Page.href (cfg.detailPage item)
expandCollapseLink =
a
[ classList
[ ( "my-auto flex text-lg w-4 text-left w-1", not rowOpen )
, ( "flex w-full block text-xl bg-gray-50 dark:bg-bluegray-700 mb-2 rounded ", rowOpen )
, ( "invisible", isSelected cfg item.id )
]
, href "#"
, onClick (ToggleRowOpen item.id)
]
[ if rowOpen then
i [ class "fa fa-caret-down pl-1" ] []
Data.ItemSelection.Active ids ->
[ onClick (ToggleSelectItem ids item.id)
, href "#"
else
i [ class "fa fa-caret-right" ] []
]
titleTemplate =
settings.cardTitleTemplate.template
subtitleTemplate =
settings.cardSubtitleTemplate.template
dirIcon =
i
[ class (Data.Direction.iconFromMaybe2 item.direction)
, class "mr-2 w-4 text-center"
, classList [ ( "hidden", fieldHidden Data.Fields.Direction ) ]
, IT.render IT.direction (templateCtx texts) item |> title
]
[]
newIcon =
i
[ class "fa fa-exclamation-circle mr-1"
, class cardColor
, title texts.new
, classList [ ( "hidden", not isCreated ) ]
]
[]
trashIcon =
i
[ class Icons.trash
, class "mr-1"
, classList [ ( "hidden", not isDeleted ) ]
]
[]
dueDateLong =
IT.render IT.dueDateLong (templateCtx texts) item
selectedDimmer =
div
[ classList
[ ( "hidden", not (isSelected cfg item.id) )
]
, class S.dimmerRow
]
[ div [ class "text-2xl font-bold text-blue-100 hover:text-blue-200 dark:text-lightblue-300 dark:hover:text-lightblue-200" ]
[ a
(mkCardAction texts cfg settings item)
[ i [ class "fa fa-check-circle" ] []
]
]
]
cardAction =
mkCardAction texts cfg settings item
in
div
([ classList [ ( "border border-gray-800 border-dashed dark:border-lightblue-500", isMultiSelectMode cfg ) ]
, class "flex flex-col border-b pb-1 dark:border-bluegray-600 ds-item-row relative "
, class cfg.extraClasses
, id item.id
]
++ DD.draggable ItemDDMsg item.id
)
[ div
[ class "h-14 flex flex-row space-x-1 justify-items-start truncate"
, classList [ ( "hidden", rowOpen ) ]
]
[ div [ class "flex flex-row mr-1" ]
[ expandCollapseLink
, div
[ class "flex pt-0.5 w-12"
, classList [ ( "hidden", fieldHidden Data.Fields.PreviewImage ) ]
]
[ previewImage2 texts cfg settings model item
]
]
, div [ class "flex flex-grow flex-col truncate text-left" ]
[ div
[ class "truncate w-full text-lg pointer font-medium"
]
[ trashIcon
, newIcon
, i
[ class Icons.dueDate2
, class "mr-1"
, title (texts.dueOn ++ " " ++ dueDateLong)
, classList [ ( "hidden", item.dueDate == Nothing ) ]
]
[]
, a (href "#" :: cardAction)
[ IT.render titleTemplate (templateCtx texts) item |> text
]
, a
[ classList [ ( "hidden", List.length item.attachments == 1 ) ]
, class "ml-2 opacity-50 text-xs hover:opacity-75"
, title texts.cycleAttachments
, href "#"
, onClick (CyclePreview item)
]
[ currentPosition model item
|> String.fromInt
|> text
, text "/"
, text (attachCount |> String.fromInt)
]
]
, div
[ class "opacity-75 truncate flex flex-row items-center"
, classList
[ ( "hidden", IT.render subtitleTemplate (templateCtx texts) item == "" )
]
]
[ div [ class "flex mr-2 flex-grow items-center" ]
[ dirIcon
, IT.render subtitleTemplate (templateCtx texts) item |> text
]
, div [ class "opacity-90" ]
[ mainTagsAndFields2 settings "flex truncate overflow-hidden flex-nowrap text-xs justify-start hidden md:flex" item
]
]
]
, div [ class "flex items-end" ]
[ a
[ class S.secondaryBasicButtonPlain
, class "px-2 py-1 border rounded "
, href attachUrl
, target "_blank"
, title texts.openAttachmentFile
]
[ i [ class "fa fa-eye" ] []
]
, a
[ class S.secondaryBasicButtonPlain
, class "px-2 py-1 border rounded ml-2"
, Page.href (cfg.detailPage item)
, title texts.gotoDetail
]
[ i [ class "fa fa-edit" ] []
]
]
]
, div
[ class "flex flex-col py-1"
, classList [ ( "hidden", not rowOpen ) ]
]
[ expandCollapseLink
, div [ class "flex flex-col sm:flex-row ml-2" ]
[ div
[ class "flex max-w-sm flex-col max-h-96 sm:max-h-full"
, classList [ ( "hidden", fieldHidden Data.Fields.PreviewImage ) ]
]
[ previewImage2 texts cfg settings model item
, previewMenu2 texts settings flags cfg model item (currentAttachment model item)
]
, div [ class "flex flex-grow flex-col ml-2 text-base" ]
[ h3 [ class "text-xl tracking-wide font-bold" ]
[ newIcon
, trashIcon
, IT.render titleTemplate (templateCtx texts) item |> text
]
, h4 [ class "opacity-75 font-normal mb-3" ]
[ dirIcon
, IT.render subtitleTemplate (templateCtx texts) item |> text
]
, div [ class "space-y-1 mb-3" ]
[ div
[ classList
[ ( "hidden"
, fieldHidden Data.Fields.CorrOrg
&& fieldHidden Data.Fields.CorrPerson
)
]
, title texts.basics.correspondent
]
(Icons.correspondentIcon2 "mr-2 w-4 text-center"
:: Comp.LinkTarget.makeCorrLink item [ ( "hover:opacity-75", True ) ] SetLinkTarget
)
, div
[ classList
[ ( "hidden"
, fieldHidden Data.Fields.ConcPerson
&& fieldHidden Data.Fields.ConcEquip
)
]
, title texts.basics.concerning
]
(Icons.concernedIcon2 "mr-2 w-4 text-center"
:: Comp.LinkTarget.makeConcLink item [ ( "hover:opacity-75", True ) ] SetLinkTarget
)
, div
[ classList
[ ( "hidden", fieldHidden Data.Fields.Folder )
]
, class "hover:opacity-60"
, title texts.basics.folder
]
[ Icons.folderIcon2 "mr-2"
, Comp.LinkTarget.makeFolderLink item
[ ( "hover:opacity-60", True ) ]
SetLinkTarget
]
, div
[ classList
[ ( "hidden", fieldHidden Data.Fields.Date ) ]
]
[ Icons.dateIcon2 "mr-2"
, IT.render IT.dateLong (templateCtx texts) item
|> Util.String.withDefault "-"
|> text
]
, div
[ classList
[ ( "hidden", fieldHidden Data.Fields.DueDate ) ]
]
[ Icons.dueDateIcon2 "mr-2"
, dueDateLong
|> Util.String.withDefault "-"
|> text
]
, div
[ classList
[ ( "hidden", fieldHidden Data.Fields.SourceName ) ]
]
[ Icons.sourceIcon2 "mr-2"
, Comp.LinkTarget.makeSourceLink
[ ( "hover:opacity-60", True ) ]
SetLinkTarget
(IT.render IT.source (templateCtx texts) item)
]
]
, mainTagsAndFields2 settings "justify-start text-sm" item
, notesContent2 settings item
]
]
]
, fulltextResultsContent2 item
, selectedDimmer
]
viewCard : Texts -> ViewConfig -> UiSettings -> Flags -> Model -> ItemLight -> Html Msg
viewCard texts cfg settings flags model item =
let
isCreated =
item.state == "created"
isDeleted =
item.state == "deleted"
cardColor =
if isCreated then
"text-blue-500 dark:text-lightblue-500"
else if isDeleted then
"text-red-600 dark:text-orange-600"
else
""
cardAction =
mkCardAction texts cfg settings item
fieldHidden f =
Data.UiSettings.fieldHidden settings f
selectedDimmer =
div
@ -215,7 +518,7 @@ view2 texts cfg settings flags model item =
[]
else
[ previewImage2 cfg settings cardAction model item
[ previewImage2 texts cfg settings model item
]
)
++ [ mainContent2 texts cardAction cardColor isCreated isDeleted settings cfg item
@ -228,10 +531,37 @@ view2 texts cfg settings flags model item =
)
mkCardAction : Texts -> ViewConfig -> UiSettings -> ItemLight -> List (Attribute Msg)
mkCardAction texts cfg settings item =
case cfg.selection of
Data.ItemSelection.Inactive ->
case cfg.arrange of
Data.ItemArrange.List ->
if cfg.isRowOpen then
[ Page.href (cfg.detailPage item)
, title texts.gotoDetail
]
else
[ onClick (ToggleRowOpen item.id)
, href "#"
]
Data.ItemArrange.Cards ->
[ Page.href (cfg.detailPage item)
, title texts.gotoDetail
]
Data.ItemSelection.Active ids ->
[ onClick (ToggleSelectItem ids item.id)
, href "#"
]
fulltextResultsContent2 : ItemLight -> Html Msg
fulltextResultsContent2 item =
div
[ class "ds-card-search-hl flex flex-col text-sm px-2 bg-yellow-50 dark:bg-indigo-800 dark:bg-opacity-60 "
[ class "ds-card-search-hl flex flex-col text-sm px-2 bg-yellow-50 dark:bg-indigo-800 dark:bg-opacity-10 bg-opacity-50"
, classList
[ ( "hidden", item.highlighting == [] )
]
@ -391,13 +721,13 @@ mainContent2 texts _ cardColor isCreated isDeleted settings _ item =
, IT.render subtitlePattern (templateCtx texts) item |> text
]
, div [ class "" ]
[ mainTagsAndFields2 settings item
[ mainTagsAndFields2 settings "justify-end text-xs" item
]
]
mainTagsAndFields2 : UiSettings -> ItemLight -> Html Msg
mainTagsAndFields2 settings item =
mainTagsAndFields2 : UiSettings -> String -> ItemLight -> Html Msg
mainTagsAndFields2 settings extraCss item =
let
fieldHidden f =
Data.UiSettings.fieldHidden settings f
@ -441,15 +771,16 @@ mainTagsAndFields2 settings item =
in
div
[ classList
[ ( "flex flex-row items-center flex-wrap justify-end text-xs font-medium my-1", True )
[ ( "flex flex-row items-center flex-wrap font-medium", True )
, ( "hidden", hideTags && hideFields )
]
, class extraCss
]
(renderFields ++ renderTags)
previewImage2 : ViewConfig -> UiSettings -> List (Attribute Msg) -> Model -> ItemLight -> Html Msg
previewImage2 cfg settings cardAction model item =
previewImage2 : Texts -> ViewConfig -> UiSettings -> Model -> ItemLight -> Html Msg
previewImage2 texts cfg settings model item =
let
mainAttach =
currentAttachment model item
@ -457,18 +788,37 @@ previewImage2 cfg settings cardAction model item =
previewUrl =
Maybe.map cfg.previewUrl mainAttach
|> Maybe.withDefault (cfg.previewUrlFallback item)
isCardView =
case cfg.arrange of
Data.ItemArrange.List ->
False
Data.ItemArrange.Cards ->
True
isRowOpen =
cfg.isRowOpen
isListView =
not isCardView
in
a
([ class "overflow-hidden block bg-gray-50 dark:bg-bluegray-700 dark:bg-opacity-40 border-gray-400 dark:hover:border-bluegray-500 rounded-t-lg"
, class (Data.UiSettings.cardPreviewSize2 settings)
([ class "overflow-hidden block bg-gray-50 dark:bg-bluegray-700 dark:bg-opacity-40 border-gray-400 dark:hover:border-bluegray-500 w-full"
, classList
[ ( "rounded-t-lg", isCardView )
, ( Data.UiSettings.cardPreviewSize2 settings, isCardView && not isRowOpen )
]
]
++ cardAction
++ mkCardAction texts cfg settings item
)
[ img
[ class "preview-image mx-auto pt-1"
[ class "preview-image mx-auto"
, classList
[ ( "rounded-t-lg w-full -mt-1", settings.cardPreviewFullWidth )
, ( Data.UiSettings.cardPreviewSize2 settings, not settings.cardPreviewFullWidth )
[ ( "rounded-t-lg w-full -mt-1", settings.cardPreviewFullWidth && isCardView )
, ( Data.UiSettings.cardPreviewSize2 settings, not settings.cardPreviewFullWidth && isCardView )
, ( "h-12", isListView && not isRowOpen )
, ( "border-t border-r border-l dark:border-bluegray-600", isListView && isRowOpen )
]
, src previewUrl
]
@ -514,8 +864,28 @@ previewMenu2 texts settings flags cfg model item mainAttach =
[ Icons.dueDateIcon2 "mr-2"
, text (" " ++ dueDate)
]
isCardView =
case cfg.arrange of
Data.ItemArrange.List ->
False
Data.ItemArrange.Cards ->
True
isRowOpen =
cfg.isRowOpen
isListView =
not isCardView
in
div [ class "px-2 py-1 flex flex-row flex-wrap bg-gray-50 dark:bg-bluegray-700 dark:bg-opacity-40 border-0 rounded-b-lg md:text-sm" ]
div
[ class "px-2 py-1 flex flex-row flex-wrap bg-gray-50 dark:bg-bluegray-700 dark:bg-opacity-40 rounded-b-lg md:text-sm"
, classList
[ ( "border-0", isCardView || not isRowOpen )
, ( "border-b border-l border-r dark:border-bluegray-600", isListView && isRowOpen )
]
]
[ a
[ class S.secondaryBasicButtonPlain
, class "px-2 py-1 border rounded "
@ -587,7 +957,7 @@ renderHighlightEntry2 entry =
in
div [ class "content" ]
(div [ class "font-semibold" ]
[ i [ class "fa fa-caret-right mr-1 " ] []
[ i [ class "fa fa-file font-thin mr-1 " ] []
, text (entry.name ++ ":")
]
:: List.map

View File

@ -14,7 +14,7 @@ module Comp.ItemCardList exposing
, prevItem
, update
, updateDrag
, view2
, view
)
import Api.Model.AttachmentLight exposing (AttachmentLight)
@ -24,6 +24,7 @@ import Api.Model.ItemLightList exposing (ItemLightList)
import Comp.ItemCard
import Comp.LinkTarget exposing (LinkTarget)
import Data.Flags exposing (Flags)
import Data.ItemArrange exposing (ItemArrange)
import Data.ItemSelection exposing (ItemSelection)
import Data.Items
import Data.UiSettings exposing (UiSettings)
@ -32,6 +33,7 @@ import Html exposing (..)
import Html.Attributes exposing (..)
import Messages.Comp.ItemCardList exposing (Texts)
import Page exposing (Page(..))
import Set exposing (Set)
import Styles as S
import Util.ItemDragDrop as DD
import Util.List
@ -73,13 +75,9 @@ prevItem model id =
--- Update
update : Flags -> Msg -> Model -> ( Model, Cmd Msg, LinkTarget )
update : Flags -> Msg -> Model -> UpdateResult
update flags msg model =
let
res =
updateDrag DD.init flags msg model
in
( res.model, res.cmd, res.linkTarget )
updateDrag DD.init flags msg model
type alias UpdateResult =
@ -88,6 +86,7 @@ type alias UpdateResult =
, dragModel : DD.Model
, selection : ItemSelection
, linkTarget : LinkTarget
, toggleOpenRow : Maybe String
}
@ -109,6 +108,7 @@ updateDrag dm _ msg model =
dm
Data.ItemSelection.Inactive
Comp.LinkTarget.LinkNone
Nothing
AddResults list ->
if list.groups == [] then
@ -117,6 +117,7 @@ updateDrag dm _ msg model =
dm
Data.ItemSelection.Inactive
Comp.LinkTarget.LinkNone
Nothing
else
let
@ -128,6 +129,7 @@ updateDrag dm _ msg model =
dm
Data.ItemSelection.Inactive
Comp.LinkTarget.LinkNone
Nothing
ItemCardMsg item lm ->
let
@ -146,6 +148,7 @@ updateDrag dm _ msg model =
result.dragModel
result.selection
result.linkTarget
result.toggleRow
RemoveItem id ->
UpdateResult { model | results = removeItemById id model.results }
@ -153,6 +156,7 @@ updateDrag dm _ msg model =
dm
Data.ItemSelection.Inactive
Comp.LinkTarget.LinkNone
Nothing
@ -166,22 +170,78 @@ type alias ViewConfig =
, previewUrlFallback : ItemLight -> String
, attachUrl : AttachmentLight -> String
, detailPage : ItemLight -> Page
, arrange : ItemArrange
, showGroups : Bool
, rowOpen : String -> Bool
}
view2 : Texts -> ViewConfig -> UiSettings -> Flags -> Model -> Html Msg
view2 texts cfg settings flags model =
div
[ classList
[ ( "ds-item-list", True )
, ( "ds-multi-select-mode", isMultiSelectMode cfg )
view : Texts -> ViewConfig -> UiSettings -> Flags -> Model -> Html Msg
view texts cfg settings flags model =
case cfg.arrange of
Data.ItemArrange.Cards ->
viewCards texts cfg settings flags model
Data.ItemArrange.List ->
viewList texts cfg settings flags model
viewList : Texts -> ViewConfig -> UiSettings -> Flags -> Model -> Html Msg
viewList texts cfg settings flags model =
let
items =
Data.Items.unwrapGroups model.results.groups
listingCss =
"grid grid-cols-1 space-y-1"
in
if cfg.showGroups then
div [ class listingCss ]
(List.map (viewGroup texts model cfg settings flags) model.results.groups)
else
div [ class listingCss ]
(List.map (viewItem texts model cfg settings flags) items)
itemContainerCss : ViewConfig -> String
itemContainerCss cfg =
case cfg.arrange of
Data.ItemArrange.Cards ->
"grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 2xl:grid-cols-4 gap-2"
Data.ItemArrange.List ->
"flex flex-col space-y-1"
viewCards : Texts -> ViewConfig -> UiSettings -> Flags -> Model -> Html Msg
viewCards texts cfg settings flags model =
let
items =
Data.Items.unwrapGroups model.results.groups
in
if cfg.showGroups then
div
[ classList
[ ( "ds-item-list", True )
, ( "ds-multi-select-mode", isMultiSelectMode cfg )
]
]
]
(List.map (viewGroup2 texts model cfg settings flags) model.results.groups)
(List.map (viewGroup texts model cfg settings flags) model.results.groups)
else
div
[ class "ds-item-list"
, class (itemContainerCss cfg)
, classList
[ ( "ds-multi-select-mode", isMultiSelectMode cfg )
]
]
(List.map (viewItem texts model cfg settings flags) items)
viewGroup2 : Texts -> Model -> ViewConfig -> UiSettings -> Flags -> ItemLightGroup -> Html Msg
viewGroup2 texts model cfg settings flags group =
viewGroup : Texts -> Model -> ViewConfig -> UiSettings -> Flags -> ItemLightGroup -> Html Msg
viewGroup texts model cfg settings flags group =
div [ class "ds-item-group" ]
[ div
[ class "flex py-1 mt-2 mb-2 flex flex-row items-center"
@ -205,13 +265,13 @@ viewGroup2 texts model cfg settings flags group =
]
[]
]
, div [ class "grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 2xl:grid-cols-4 gap-2" ]
(List.map (viewItem2 texts model cfg settings flags) group.items)
, div [ class (itemContainerCss cfg) ]
(List.map (viewItem texts model cfg settings flags) group.items)
]
viewItem2 : Texts -> Model -> ViewConfig -> UiSettings -> Flags -> ItemLight -> Html Msg
viewItem2 texts model cfg settings flags item =
viewItem : Texts -> Model -> ViewConfig -> UiSettings -> Flags -> ItemLight -> Html Msg
viewItem texts model cfg settings flags item =
let
currentClass =
if cfg.current == Just item.id then
@ -220,15 +280,31 @@ viewItem2 texts model cfg settings flags item =
else
""
itemClass =
case cfg.arrange of
Data.ItemArrange.List ->
" mb-1"
Data.ItemArrange.Cards ->
""
vvcfg =
Comp.ItemCard.ViewConfig cfg.selection currentClass cfg.previewUrl cfg.previewUrlFallback cfg.attachUrl cfg.detailPage
{ selection = cfg.selection
, extraClasses = currentClass ++ itemClass
, previewUrl = cfg.previewUrl
, previewUrlFallback = cfg.previewUrlFallback
, attachUrl = cfg.attachUrl
, detailPage = cfg.detailPage
, isRowOpen = cfg.rowOpen item.id
, arrange = cfg.arrange
}
cardModel =
Dict.get item.id model.itemCards
|> Maybe.withDefault Comp.ItemCard.init
cardHtml =
Comp.ItemCard.view2 texts.itemCard vvcfg settings flags cardModel item
Comp.ItemCard.view texts.itemCard vvcfg settings flags cardModel item
in
Html.map (ItemCardMsg item) cardHtml

View File

@ -130,12 +130,12 @@ view texts settings model =
[ if isDeleted then
div
[ classList
[ ( "text-red-500 dark:text-orange-600 text-4xl", True )
[ ( " text-4xl", True )
, ( "hidden", not isDeleted )
]
, title texts.basics.deleted
]
[ i [ class "mr-2 fa fa-trash-alt" ] []
[ Icons.trashIcon "mr-2"
]
else

View File

@ -72,6 +72,8 @@ module Data.Icons exposing
, tagIcon2
, tags2
, tagsIcon2
, trash
, trashIcon
)
import Data.CustomFieldType exposing (CustomFieldType)
@ -81,6 +83,20 @@ import Svg
import Svg.Attributes as SA
trash : String
trash =
"fa fa-trash-alt text-red-500 dark:text-orange-600"
trashIcon : String -> Html msg
trashIcon classes =
i
[ class classes
, class trash
]
[]
share : String
share =
"fa fa-share-alt"

View File

@ -0,0 +1,36 @@
{-
Copyright 2020 Eike K. & Contributors
SPDX-License-Identifier: AGPL-3.0-or-later
-}
module Data.ItemArrange exposing (ItemArrange(..), asString, fromString)
type ItemArrange
= Cards
| List
asString : ItemArrange -> String
asString arr =
case arr of
Cards ->
"cards"
List ->
"list"
fromString : String -> Maybe ItemArrange
fromString str =
case String.toLower str of
"cards" ->
Just Cards
"list" ->
Just List
_ ->
Nothing

View File

@ -12,6 +12,7 @@ module Data.Items exposing
, idSet
, length
, replaceIn
, unwrapGroups
)
import Api.Model.ItemLight exposing (ItemLight)
@ -27,6 +28,11 @@ flatten list =
List.concatMap .items list.groups
unwrapGroups : List ItemLightGroup -> List ItemLight
unwrapGroups groups =
List.concatMap .items groups
concat : ItemLightList -> ItemLightList -> ItemLightList
concat l0 l1 =
let

View File

@ -36,6 +36,7 @@ import Data.BasicSize exposing (BasicSize)
import Data.Color exposing (Color)
import Data.Fields exposing (Field)
import Data.Flags exposing (Flags)
import Data.ItemArrange exposing (ItemArrange)
import Data.ItemTemplate exposing (ItemTemplate)
import Data.Pdf exposing (PdfMode)
import Data.UiTheme exposing (UiTheme)
@ -50,7 +51,7 @@ import Messages.UiLanguage exposing (UiLanguage)
{-| Settings for the web ui. All fields should be optional, since it
is loaded from local storage.
is loaded from the server and mus be backward compatible.
Making fields optional, allows it to evolve without breaking previous
versions. Also if a user is logged out, an empty object is send to
@ -79,6 +80,8 @@ type alias StoredUiSettings =
, sideMenuVisible : Bool
, powerSearchEnabled : Bool
, uiLang : Maybe String
, itemSearchShowGroups : Bool
, itemSearchArrange : Maybe String
}
@ -113,6 +116,8 @@ storedUiSettingsDecoder =
|> P.optional "sideMenuVisible" Decode.bool False
|> P.optional "powerSearchEnabled" Decode.bool False
|> P.optional "uiLang" maybeString Nothing
|> P.optional "itemSearchShowGroups" Decode.bool True
|> P.optional "itemSearchArrange" maybeString Nothing
storedUiSettingsEncode : StoredUiSettings -> Encode.Value
@ -143,6 +148,8 @@ storedUiSettingsEncode value =
, ( "sideMenuVisible", Encode.bool value.sideMenuVisible )
, ( "powerSearchEnabled", Encode.bool value.powerSearchEnabled )
, ( "uiLang", maybeEnc Encode.string value.uiLang )
, ( "itemSearchShowGroups", Encode.bool value.itemSearchShowGroups )
, ( "itemSearchArrange", maybeEnc Encode.string value.itemSearchArrange )
]
@ -176,6 +183,8 @@ type alias UiSettings =
, sideMenuVisible : Bool
, powerSearchEnabled : Bool
, uiLang : UiLanguage
, itemSearchShowGroups : Bool
, itemSearchArrange : ItemArrange
}
@ -248,6 +257,8 @@ defaults =
, sideMenuVisible = True
, powerSearchEnabled = False
, uiLang = Messages.UiLanguage.English
, itemSearchShowGroups = True
, itemSearchArrange = Data.ItemArrange.Cards
}
@ -306,6 +317,10 @@ merge given fallback =
, uiLang =
Maybe.map Messages.fromIso2 given.uiLang
|> Maybe.withDefault Messages.UiLanguage.English
, itemSearchShowGroups = given.itemSearchShowGroups
, itemSearchArrange =
Maybe.andThen Data.ItemArrange.fromString given.itemSearchArrange
|> Maybe.withDefault fallback.itemSearchArrange
}
@ -344,6 +359,8 @@ toStoredUiSettings settings =
, sideMenuVisible = settings.sideMenuVisible
, powerSearchEnabled = settings.powerSearchEnabled
, uiLang = Just <| Messages.toIso2 settings.uiLang
, itemSearchShowGroups = settings.itemSearchShowGroups
, itemSearchArrange = Data.ItemArrange.asString settings.itemSearchArrange |> Just
}

View File

@ -115,7 +115,7 @@ de =
, addMoreFiles = "Diesem Dokument weitere Dateien anfügen"
, confirmItemMetadata = "Metadaten bestätigen"
, confirm = "Bestätige"
, unconfirmItemMetadata = "Widerrufe Bestätigung"
, unconfirmItemMetadata = "Widerrufe"
, reprocessItem = "Das Dokument erneut verarbeiten"
, deleteThisItem = "Das Dokument löschen"
, undeleteThisItem = "Das Dokument wiederherstellen"

View File

@ -60,7 +60,7 @@ de =
, chooseDirection = "Wähle eine Richtung"
, confirmUnconfirm = "Bestätige/Widerrufe Metadaten"
, confirm = "Bestätige"
, unconfirm = "Widerrufe Bestätigung"
, unconfirm = "Widerrufe"
, changeTagMode = "Wechsel den Änderungsmodus für Tags"
, dueDateTab = "Fälligkeitsdatum"
, direction = Messages.Data.Direction.de

View File

@ -49,6 +49,10 @@ type alias Texts =
, nothingSelectedToShare : String
, loadMore : String
, thatsAll : String
, showItemGroups : String
, listView : String
, tileView : String
, expandCollapseRows : String
}
@ -83,6 +87,10 @@ gb =
, nothingSelectedToShare = "Sharing everything doesn't work. You need to apply some criteria."
, loadMore = "Load more"
, thatsAll = "That's all"
, showItemGroups = "Group by month"
, listView = "List view"
, tileView = "Tile view"
, expandCollapseRows = "Expand/Collapse all"
}
@ -117,4 +125,8 @@ de =
, nothingSelectedToShare = "Alles kann nicht geteilt werden; es muss etwas gesucht werden."
, loadMore = "Mehr laden"
, thatsAll = "Mehr gibt es nicht"
, showItemGroups = "nach Monat gruppieren"
, listView = "Listenansicht"
, tileView = "Kachelansicht"
, expandCollapseRows = "Alle ein-/ausklappen"
}

View File

@ -26,6 +26,9 @@ type alias Texts =
, powerSearchPlaceholder : String
, normalSearchPlaceholder : String
, extendedSearch : String
, showItemGroups : String
, listView : String
, tileView : String
}
@ -41,6 +44,9 @@ gb =
, powerSearchPlaceholder = "Extended search"
, extendedSearch = "Extended search query"
, normalSearchPlaceholder = "Search"
, showItemGroups = "Group by month"
, listView = "List view"
, tileView = "Tile view"
}
@ -56,4 +62,7 @@ de =
, powerSearchPlaceholder = "Erweiterte Suche"
, extendedSearch = "Erweiterte Suchanfrage"
, normalSearchPlaceholder = "Suche"
, showItemGroups = "nach Monat gruppieren"
, listView = "Listenansicht"
, tileView = "Kachelansicht"
}

View File

@ -27,7 +27,6 @@ module Page.Home.Data exposing
import Api
import Api.Model.BasicResult exposing (BasicResult)
import Api.Model.ItemLight exposing (ItemLight)
import Api.Model.ItemLightList exposing (ItemLightList)
import Api.Model.SearchStats exposing (SearchStats)
import Browser.Dom as Dom
@ -40,6 +39,7 @@ import Comp.PowerSearchInput
import Comp.PublishItems
import Comp.SearchMenu
import Data.Flags exposing (Flags)
import Data.ItemArrange exposing (ItemArrange)
import Data.ItemNav exposing (ItemNav)
import Data.ItemQuery as Q
import Data.Items
@ -66,6 +66,8 @@ type alias Model =
, scrollToCard : Maybe String
, searchStats : SearchStats
, powerSearchInput : Comp.PowerSearchInput.Model
, viewMenuOpen : Bool
, itemRowsOpen : Set String
}
@ -133,6 +135,8 @@ init flags viewMode =
, viewMode = viewMode
, searchStats = Api.Model.SearchStats.empty
, powerSearchInput = Comp.PowerSearchInput.init
, viewMenuOpen = False
, itemRowsOpen = Set.empty
}
@ -230,6 +234,10 @@ type Msg
| TogglePublishCurrentQueryView
| PublishViewMsg Comp.PublishItems.Msg
| RefreshView
| ToggleViewMenu
| ToggleShowGroups
| ToggleArrange ItemArrange
| ToggleExpandCollapseRows
type SearchType

View File

@ -144,16 +144,40 @@ update mId key flags texts settings msg model =
( v, _ ) ->
v
itemRows =
case result.toggleOpenRow of
Just rid ->
if Set.member rid model.itemRowsOpen then
Set.remove rid model.itemRowsOpen
else
Set.insert rid model.itemRowsOpen
Nothing ->
model.itemRowsOpen
in
withSub
( { model
| itemListModel = result.model
, viewMode = nextView
, itemRowsOpen = itemRows
, dragDropData = DD.DragDropData result.dragModel Nothing
}
, Cmd.batch [ Cmd.map ItemCardListMsg result.cmd, searchMsg ]
)
ToggleExpandCollapseRows ->
let
itemRows =
if Set.isEmpty model.itemRowsOpen then
Set.singleton "all"
else
Set.empty
in
noSub ( { model | itemRowsOpen = itemRows, viewMenuOpen = False }, Cmd.none )
ItemSearchResp scroll (Ok list) ->
let
noff =
@ -923,6 +947,29 @@ update mId key flags texts settings msg model =
_ ->
noSub ( model, Cmd.none )
ToggleViewMenu ->
noSub ( { model | viewMenuOpen = not model.viewMenuOpen }, Cmd.none )
ToggleShowGroups ->
let
newSettings =
{ settings | itemSearchShowGroups = not settings.itemSearchShowGroups }
cmd =
Api.saveClientSettings flags newSettings (ClientSettingsSaveResp newSettings)
in
noSub ( { model | viewMenuOpen = False }, cmd )
ToggleArrange am ->
let
newSettings =
{ settings | itemSearchArrange = am }
cmd =
Api.saveClientSettings flags newSettings (ClientSettingsSaveResp newSettings)
in
noSub ( { model | viewMenuOpen = False }, cmd )
--- Helpers

View File

@ -19,7 +19,7 @@ import Comp.SearchMenu
import Comp.SearchStatsView
import Data.Flags exposing (Flags)
import Data.Icons as Icons
import Data.ItemQuery as Q
import Data.ItemArrange
import Data.ItemSelection
import Data.SearchMode
import Data.UiSettings exposing (UiSettings)
@ -182,7 +182,7 @@ itemsBar texts flags settings model =
SelectView svm ->
[ editMenuBar texts model svm ]
PublishView query ->
PublishView _ ->
[ defaultMenuBar texts flags settings model ]
@ -248,6 +248,12 @@ defaultMenuBar texts flags settings model =
, Html.map PowerSearchMsg
(Comp.PowerSearchInput.viewResult [] model.powerSearchInput)
]
isCardView =
settings.itemSearchArrange == Data.ItemArrange.Cards
isListView =
settings.itemSearchArrange == Data.ItemArrange.List
in
MB.view
{ end =
@ -293,6 +299,61 @@ defaultMenuBar texts flags settings model =
, ( "bg-gray-200 dark:bg-bluegray-600", selectActive model )
]
}
, MB.Dropdown
{ linkIcon = "fa fa-grip-vertical"
, label = ""
, linkClass =
[ ( S.secondaryBasicButton, True )
]
, toggleMenu = ToggleViewMenu
, menuOpen = model.viewMenuOpen
, items =
[ { icon =
if settings.itemSearchShowGroups then
i [ class "fa fa-check-square font-thin" ] []
else
i [ class "fa fa-square font-thin" ] []
, label = texts.showItemGroups
, attrs =
[ href "#"
, onClick ToggleShowGroups
]
}
, { icon =
if isListView then
i [ class "fa fa-check" ] []
else
i [ class "fa fa-list" ] []
, label = texts.listView
, attrs =
[ href "#"
, onClick (ToggleArrange Data.ItemArrange.List)
]
}
, { icon =
if isCardView then
i [ class "fa fa-check" ] []
else
i [ class "fa fa-th-large" ] []
, label = texts.tileView
, attrs =
[ href "#"
, onClick (ToggleArrange Data.ItemArrange.Cards)
]
}
, { icon = i [ class "fa fa-compress" ] []
, label = texts.expandCollapseRows
, attrs =
[ href "#"
, classList [ ( "hidden", not isListView ) ]
, onClick ToggleExpandCollapseRows
]
}
]
}
]
, start =
[ MB.CustomElement <|
@ -469,13 +530,16 @@ itemCardList texts flags settings model =
Api.itemBasePreviewURL item.id
viewCfg sel =
Comp.ItemCardList.ViewConfig
model.scrollToCard
sel
previewUrl
previewUrlFallback
(.id >> Api.fileURL)
(.id >> ItemDetailPage)
{ current = model.scrollToCard
, selection = sel
, previewUrl = previewUrl
, previewUrlFallback = previewUrlFallback
, attachUrl = .id >> Api.fileURL
, detailPage = .id >> ItemDetailPage
, arrange = settings.itemSearchArrange
, showGroups = settings.itemSearchShowGroups
, rowOpen = \id -> Set.member "all" model.itemRowsOpen || Set.member id model.itemRowsOpen
}
itemViewCfg =
case model.viewMode of
@ -486,7 +550,7 @@ itemCardList texts flags settings model =
viewCfg Data.ItemSelection.Inactive
in
[ Html.map ItemCardListMsg
(Comp.ItemCardList.view2 texts.itemCardList
(Comp.ItemCardList.view texts.itemCardList
itemViewCfg
settings
flags

View File

@ -17,7 +17,10 @@ import Comp.PowerSearchInput
import Comp.SearchMenu
import Comp.SharePasswordForm
import Data.Flags exposing (Flags)
import Data.ItemArrange exposing (ItemArrange)
import Http
import Page.Home.Data exposing (Msg(..))
import Set exposing (Set)
import Util.Html exposing (KeyCode)
@ -50,6 +53,12 @@ type alias Model =
, initialized : Bool
, contentSearch : Maybe String
, searchMode : SearchBarMode
, viewMode :
{ menuOpen : Bool
, showGroups : Bool
, arrange : ItemArrange
, rowsOpen : Set String
}
}
@ -66,6 +75,12 @@ emptyModel flags =
, initialized = False
, contentSearch = Nothing
, searchMode = SearchBarContent
, viewMode =
{ menuOpen = False
, showGroups = True
, arrange = Data.ItemArrange.Cards
, rowsOpen = Set.empty
}
}
@ -100,3 +115,6 @@ type Msg
| ToggleSearchBar
| SetContentSearch String
| ContentSearchKey (Maybe KeyCode)
| ToggleViewMenu
| ToggleArrange ItemArrange
| ToggleShowGroups

View File

@ -11,6 +11,7 @@ import Comp.Basic as B
import Comp.MenuBar as MB
import Comp.PowerSearchInput
import Data.Flags exposing (Flags)
import Data.ItemArrange
import Html exposing (..)
import Html.Attributes exposing (..)
import Html.Events exposing (onClick, onInput)
@ -108,6 +109,43 @@ view texts flags model =
, handler = onClick ResetSearch
, attrs = [ href "#" ]
}
, MB.Dropdown
{ linkIcon = "fa fa-grip-vertical"
, label = ""
, linkClass =
[ ( S.secondaryBasicButton, True )
]
, toggleMenu = ToggleViewMenu
, menuOpen = model.viewMode.menuOpen
, items =
[ { icon =
if model.viewMode.showGroups then
i [ class "fa fa-check-square font-thin" ] []
else
i [ class "fa fa-square font-thin" ] []
, label = texts.showItemGroups
, attrs =
[ href "#"
, onClick ToggleShowGroups
]
}
, { icon = i [ class "fa fa-list" ] []
, label = texts.listView
, attrs =
[ href "#"
, onClick (ToggleArrange Data.ItemArrange.List)
]
}
, { icon = i [ class "fa fa-th-large" ] []
, label = texts.tileView
, attrs =
[ href "#"
, onClick (ToggleArrange Data.ItemArrange.Cards)
]
}
]
}
]
, rootClasses = "mb-2 pt-1 dark:bg-bluegray-700 items-center text-sm"
}

View File

@ -17,6 +17,7 @@ import Html.Attributes exposing (..)
import Messages.Page.Share exposing (Texts)
import Page exposing (Page(..))
import Page.Share.Data exposing (Model, Msg(..))
import Set
view : Texts -> UiSettings -> Flags -> String -> Model -> Html Msg
@ -29,9 +30,12 @@ view texts settings flags shareId model =
, previewUrlFallback = \item -> Api.shareItemBasePreviewURL item.id
, attachUrl = .id >> Api.shareFileURL
, detailPage = \item -> ShareDetailPage shareId item.id
, arrange = model.viewMode.arrange
, showGroups = model.viewMode.showGroups
, rowOpen = \id -> Set.member id model.viewMode.rowsOpen
}
in
div []
[ Html.map ItemListMsg
(Comp.ItemCardList.view2 texts.itemCardList viewCfg settings flags model.itemListModel)
(Comp.ItemCardList.view texts.itemCardList viewCfg settings flags model.itemListModel)
]

View File

@ -19,6 +19,7 @@ import Data.ItemQuery as Q
import Data.SearchMode
import Data.UiSettings exposing (UiSettings)
import Page.Share.Data exposing (..)
import Set
import Util.Html
import Util.Maybe
import Util.Update
@ -161,16 +162,31 @@ update flags settings shareId msg model =
ItemListMsg lm ->
let
( im, ic, linkTarget ) =
result =
Comp.ItemCardList.update flags lm model.itemListModel
searchMsg =
Maybe.map Util.Update.cmdUnit (linkTargetMsg linkTarget)
Maybe.map Util.Update.cmdUnit (linkTargetMsg result.linkTarget)
|> Maybe.withDefault Cmd.none
vm =
model.viewMode
itemRows =
case result.toggleOpenRow of
Just rid ->
if Set.member rid vm.rowsOpen then
Set.remove rid vm.rowsOpen
else
Set.insert rid vm.rowsOpen
Nothing ->
vm.rowsOpen
in
noSub
( { model | itemListModel = im }
, Cmd.batch [ Cmd.map ItemListMsg ic, searchMsg ]
( { model | itemListModel = result.model, viewMode = { vm | rowsOpen = itemRows } }
, Cmd.batch [ Cmd.map ItemListMsg result.cmd, searchMsg ]
)
ToggleSearchBar ->
@ -196,6 +212,36 @@ update flags settings shareId msg model =
ContentSearchKey _ ->
noSub ( model, Cmd.none )
ToggleShowGroups ->
let
vm =
model.viewMode
next =
{ vm | showGroups = not vm.showGroups, menuOpen = False }
in
noSub ( { model | viewMode = next }, Cmd.none )
ToggleViewMenu ->
let
vm =
model.viewMode
next =
{ vm | menuOpen = not vm.menuOpen }
in
noSub ( { model | viewMode = next }, Cmd.none )
ToggleArrange am ->
let
vm =
model.viewMode
next =
{ vm | arrange = am, menuOpen = False }
in
noSub ( { model | viewMode = next }, Cmd.none )
noSub : ( Model, Cmd Msg ) -> UpdateResult
noSub ( m, c ) =

View File

@ -375,6 +375,11 @@ dimmerCard =
" absolute top-0 left-0 w-full h-full bg-black bg-opacity-60 dark:bg-lightblue-900 dark:bg-opacity-60 z-30 flex flex-col items-center justify-center px-4 py-2 "
dimmerRow : String
dimmerRow =
" absolute top-0 left-0 w-full h-full bg-black bg-opacity-50 dark:bg-lightblue-900 dark:bg-opacity-50 z-30 flex flex-row items-center px-1 py-2 "
tableMain : String
tableMain =
"border-collapse table w-full"

View File

@ -16,6 +16,9 @@
.ds-item-card.current {
@apply shadow-lg dark:border-lightblue-600;
}
.ds-item-row.current {
@apply bg-gray-200 bg-opacity-50 dark:bg-lightblue-600 dark:bg-opacity-10;
}
.elm-datepicker--input {
@apply pl-10 rounded w-full placeholder-gray-400 dark:text-bluegray-200 dark:border-bluegray-500;
@ -188,6 +191,6 @@
}
.ds-card-search-hl strong {
@apply bg-lime-200 dark:bg-lightblue-700 italic font-bold px-1;
@apply bg-lime-200 dark:bg-lightblue-700 italic font-bold px-1 bg-opacity-60 dark:bg-opacity-60;
}
}