Files
docspell/modules/webapp/src/main/elm/Comp/ItemDetail/SingleAttachment.elm
eikek 4ffc8d1f14 Add support for more generic notification
This is a start to have different kinds of notifications. It is
possible to be notified via e-mail, matrix or gotify. It also extends
the current "periodic query" for due items by allowing notification
over different channels. A "generic periodic query" variant is added
as well.
2021-12-11 18:57:32 +01:00

451 lines
15 KiB
Elm

{-
Copyright 2020 Eike K. & Contributors
SPDX-License-Identifier: AGPL-3.0-or-later
-}
module Comp.ItemDetail.SingleAttachment exposing (view)
import Api
import Api.Model.Attachment exposing (Attachment)
import Comp.AttachmentMeta
import Comp.ItemDetail.ConfirmModalView
import Comp.ItemDetail.Model
exposing
( Model
, Msg(..)
, NotesField(..)
, SaveNameState(..)
, ViewMode(..)
, isShowQrAttach
)
import Comp.ItemDetail.ShowQrCode
import Comp.MenuBar as MB
import Data.Flags exposing (Flags)
import Data.Icons as Icons
import Data.UiSettings exposing (UiSettings)
import Dict
import Html exposing (..)
import Html.Attributes exposing (..)
import Html.Events exposing (onClick, onInput)
import Html5.DragDrop as DD
import Messages.Comp.ItemDetail.SingleAttachment exposing (Texts)
import Set
import Styles as S
import Util.Maybe
import Util.Size
import Util.String
view : Texts -> Flags -> UiSettings -> Model -> Int -> Attachment -> Html Msg
view texts flags settings model pos attach =
let
fileUrl =
Api.fileURL attach.id
in
div
[ class "flex flex-col md:relative h-full mb-2"
, classList
[ ( "hidden", not (attachmentVisible model pos) )
]
]
[ renderModal texts model
, div
[ class "flex flex-row px-2 py-2 text-sm"
, class S.border
]
[ attachHeader texts settings model pos attach
]
, editAttachmentName model attach
, attachmentSelect texts model pos attach
, if isAttachMetaOpen model attach.id then
case Dict.get attach.id model.attachMeta of
Just am ->
Html.map (AttachMetaMsg attach.id)
(Comp.AttachmentMeta.view2
texts.attachmentMeta
[ class "border-r border-l border-b dark:border-bluegray-600 px-2" ]
am
)
Nothing ->
span [ class "hidden" ] []
else if isShowQrAttach model.showQrModel then
Comp.ItemDetail.ShowQrCode.view1 flags
"border-r border-l border-b dark:border-bluegray-600 h-full"
(Comp.ItemDetail.ShowQrCode.Attach attach.id)
else
div
[ class "flex flex-col relative px-2 pt-2 h-full"
, class "border-r border-l border-b dark:border-bluegray-600"
, id "ds-pdf-view-parent"
, style "max-height" "calc(100vh - 140px)"
, style "min-height" "500px"
]
[ embed
[ src <| Data.UiSettings.pdfUrl settings flags fileUrl
, class "absolute h-full w-full top-0 left-0 mx-0 py-0"
, id "ds-pdf-view-iframe"
]
[]
]
]
{-| attachment header
- toggle thumbs
- name + size
- eye icon to open it
- toggle multi select
- menu
- rename
- meta data
- download archive
- download
- delete
- native view
-}
attachHeader : Texts -> UiSettings -> Model -> Int -> Attachment -> Html Msg
attachHeader texts settings model _ attach =
let
attachName =
Maybe.withDefault texts.noName attach.name
fileUrl =
Api.fileURL attach.id
hasArchive =
List.map .id model.item.archives
|> List.member attach.id
multiAttach =
List.length model.item.attachments > 1
selectPossible =
multiAttach && model.attachMenuOpen
selectView =
case model.viewMode of
SelectView _ ->
True
SimpleView ->
False
selectToggleText =
case model.viewMode of
SelectView _ ->
texts.exitSelectMode
SimpleView ->
texts.selectModeTitle
noAttachmentsSelected =
List.isEmpty model.item.attachments
attachSelectToggle mobile =
a
[ href "#"
, onClick ToggleAttachMenu
, class S.secondaryBasicButton
, class "mr-2"
, classList
[ ( "bg-gray-200 dark:bg-bluegray-600 ", model.attachMenuOpen )
, ( "hidden", not multiAttach )
, ( "sm:hidden", multiAttach && mobile )
, ( "hidden sm:block", multiAttach && not mobile )
]
]
[ if model.attachMenuOpen then
i [ class "fa fa-chevron-up" ] []
else
i [ class "fa fa-chevron-down" ] []
]
in
div [ class "flex flex-col sm:flex-row items-center w-full" ]
[ attachSelectToggle False
, div [ class "text-base font-bold flex-grow w-full text-center sm:text-left break-all" ]
[ text attachName
, text " ("
, text (Util.Size.bytesReadable Util.Size.B (toFloat attach.size))
, text ")"
]
, div [ class "flex flex-row justify-end items-center" ]
[ attachSelectToggle True
, a
[ href fileUrl
, target "_new"
, title texts.openFileInNewTab
, class S.secondaryBasicButton
, class "ml-2"
, classList [ ( "hidden", selectView ) ]
]
[ i [ class "fa fa-eye font-thin" ] []
]
, a
[ classList
[ ( S.secondaryBasicButton ++ " text-sm", True )
, ( "bg-gray-200 dark:bg-bluegray-600", selectView )
, ( "hidden", not selectPossible )
, ( "ml-2", True )
]
, href "#"
, title selectToggleText
, onClick ToggleSelectView
]
[ i [ class "fa fa-tasks" ] []
]
, a
[ classList
[ ( S.deleteButton, True )
, ( "disabled", noAttachmentsSelected )
, ( "hidden", not selectPossible || not selectView )
, ( "ml-2", True )
]
, href "#"
, title texts.deleteAttachments
, onClick RequestDeleteSelected
]
[ i [ class "fa fa-trash" ] []
]
, MB.viewItem <|
MB.Dropdown
{ linkIcon = "fa fa-bars"
, label = ""
, linkClass =
[ ( "ml-2", True )
, ( S.secondaryBasicButton, True )
, ( "hidden", selectView )
]
, toggleMenu = ToggleAttachmentDropdown
, menuOpen = model.attachmentDropdownOpen
, items =
[ { icon = i [ class "fa fa-download" ] []
, label = texts.downloadFile
, attrs =
[ download attachName
, href fileUrl
]
}
, { icon = i [ class "fa fa-file" ] []
, label = texts.renameFile
, attrs =
[ href "#"
, onClick (EditAttachNameStart attach.id)
]
}
, { icon = i [ class "fa fa-file-archive" ] []
, label = texts.downloadOriginalArchiveFile
, attrs =
[ href (fileUrl ++ "/archive")
, target "_new"
, classList [ ( "hidden", not hasArchive ) ]
]
}
, { icon = i [ class "fa fa-external-link-alt" ] []
, label = texts.originalFile
, attrs =
[ href (fileUrl ++ "/original")
, target "_new"
, classList [ ( "hidden", not attach.converted ) ]
]
}
, { icon =
if isAttachMetaOpen model attach.id then
i [ class "fa fa-toggle-on" ] []
else
i [ class "fa fa-toggle-off" ] []
, label = texts.viewExtractedData
, attrs =
[ onClick (AttachMetaClick attach.id)
, href "#"
]
}
, { icon = i [ class "fa fa-redo-alt" ] []
, label = texts.reprocessFile
, attrs =
[ onClick (RequestReprocessFile attach.id)
, href "#"
]
}
, { icon = i [ class Icons.showQr ] []
, label = texts.showQrCode
, attrs =
[ onClick (ToggleShowQrAttach attach.id)
, href "#"
]
}
, { icon = i [ class "fa fa-trash" ] []
, label = texts.deleteThisFile
, attrs =
[ onClick (RequestDeleteAttachment attach.id)
, href "#"
]
}
]
}
]
]
attachmentVisible : Model -> Int -> Bool
attachmentVisible model pos =
not model.sentMailsOpen
&& (if model.visibleAttach >= List.length model.item.attachments then
pos == 0
else
model.visibleAttach == pos
)
isAttachMetaOpen : Model -> String -> Bool
isAttachMetaOpen model id =
model.attachMetaOpen && (Dict.get id model.attachMeta /= Nothing)
editAttachmentName : Model -> Attachment -> Html Msg
editAttachmentName model attach =
let
am =
Util.Maybe.filter (\m -> m.id == attach.id) model.attachRename
in
case am of
Just m ->
div [ class "flex flex-row border-l border-r px-2 py-2 dark:border-bluegray-600" ]
[ input
[ type_ "text"
, value m.newName
, onInput EditAttachNameSet
, class S.textInput
, class "mr-2"
]
[]
, button
[ class S.primaryButton
, onClick EditAttachNameSubmit
]
[ i [ class "fa fa-check" ] []
]
, button
[ class S.secondaryButton
, onClick EditAttachNameCancel
]
[ i [ class "fa fa-times" ] []
]
]
Nothing ->
span [ class "hidden" ] []
attachmentSelect : Texts -> Model -> Int -> Attachment -> Html Msg
attachmentSelect texts model _ _ =
div
[ class "flex flex-row border-l border-r px-2 py-2 dark:border-bluegray-600 "
, class "overflow-x-auto overflow-y-none"
, classList
[ ( "hidden", not model.attachMenuOpen )
]
]
(List.indexedMap (menuItem texts model) model.item.attachments)
menuItem : Texts -> Model -> Int -> Attachment -> Html Msg
menuItem texts model pos attach =
let
highlight =
let
dropId =
DD.getDropId model.attachDD
dragId =
DD.getDragId model.attachDD
enable =
Just attach.id == dropId && dropId /= dragId
in
[ ( "bg-gray-300 dark:bg-bluegray-700 current-drop-target", enable )
]
iconClass =
case model.viewMode of
SelectView svm ->
if Set.member attach.id svm.ids then
"fa fa-check-circle ml-1"
else
"fa fa-circle ml-1"
SimpleView ->
"fa fa-check-circle ml-1"
visible =
case model.viewMode of
SelectView _ ->
True
SimpleView ->
model.visibleAttach == pos
msg =
case model.viewMode of
SelectView _ ->
ToggleAttachment attach.id
SimpleView ->
SetActiveAttachment pos
in
a
([ classList <|
[ ( "border-blue-500 dark:border-lightblue-500", pos == 0 )
, ( "dark:border-bluegray-600", pos /= 0 )
]
++ highlight
, class "flex flex-col relative border rounded px-1 py-1 mr-2"
, class " hover:shadow dark:hover:border-bluegray-500"
, href "#"
, onClick msg
]
++ DD.draggable AttachDDMsg attach.id
++ DD.droppable AttachDDMsg attach.id
)
[ div
[ classList
[ ( "hidden", not visible )
]
, class "absolute right-1 top-1 text-blue-400 dark:text-lightblue-400 text-xl"
]
[ i [ class iconClass ] []
]
, div [ class "flex-grow" ]
[ img
[ src (Api.attachmentPreviewURL attach.id)
, class "block w-20 mx-auto"
]
[]
]
, div [ class "mt-1 text-sm break-all w-28 text-center" ]
[ Maybe.map (Util.String.ellipsis 36) attach.name
|> Maybe.withDefault texts.noName
|> text
]
]
renderModal : Texts -> Model -> Html Msg
renderModal texts model =
case model.attachModal of
Just mm ->
Comp.ItemDetail.ConfirmModalView.view texts.confirmModal mm model
Nothing ->
span [ class "hidden" ] []