mirror of
https://github.com/TheAnachronism/docspell.git
synced 2025-06-22 02:18:26 +00:00
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.
451 lines
15 KiB
Elm
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" ] []
|