mirror of
				https://github.com/TheAnachronism/docspell.git
				synced 2025-10-31 09:30:12 +00:00 
			
		
		
		
	| @@ -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 | ||||
|   | ||||
| @@ -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 | ||||
|  | ||||
|   | ||||
| @@ -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 | ||||
|   | ||||
| @@ -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" | ||||
|   | ||||
							
								
								
									
										36
									
								
								modules/webapp/src/main/elm/Data/ItemArrange.elm
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										36
									
								
								modules/webapp/src/main/elm/Data/ItemArrange.elm
									
									
									
									
									
										Normal 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 | ||||
| @@ -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 | ||||
|   | ||||
| @@ -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 | ||||
|     } | ||||
|  | ||||
|  | ||||
|   | ||||
| @@ -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" | ||||
|   | ||||
| @@ -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 | ||||
|   | ||||
| @@ -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" | ||||
|     } | ||||
|   | ||||
| @@ -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" | ||||
|     } | ||||
|   | ||||
| @@ -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 | ||||
|   | ||||
| @@ -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 | ||||
|   | ||||
| @@ -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 | ||||
|   | ||||
| @@ -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 | ||||
|   | ||||
| @@ -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" | ||||
|         } | ||||
|   | ||||
| @@ -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) | ||||
|         ] | ||||
|   | ||||
| @@ -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 ) = | ||||
|   | ||||
| @@ -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" | ||||
|   | ||||
| @@ -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; | ||||
|     } | ||||
| } | ||||
|   | ||||
		Reference in New Issue
	
	Block a user