mirror of
https://github.com/TheAnachronism/docspell.git
synced 2025-06-05 22:55:58 +00:00
Show attachment meta data in ui
Allow to view the extracted text and results from text analysis of an attachment.
This commit is contained in:
parent
070b4f8452
commit
d2edddd238
@ -10,6 +10,7 @@ module Api exposing
|
|||||||
, deleteSource
|
, deleteSource
|
||||||
, deleteTag
|
, deleteTag
|
||||||
, deleteUser
|
, deleteUser
|
||||||
|
, getAttachmentMeta
|
||||||
, getCollective
|
, getCollective
|
||||||
, getCollectiveSettings
|
, getCollectiveSettings
|
||||||
, getContacts
|
, getContacts
|
||||||
@ -61,6 +62,7 @@ module Api exposing
|
|||||||
, versionInfo
|
, versionInfo
|
||||||
)
|
)
|
||||||
|
|
||||||
|
import Api.Model.AttachmentMeta exposing (AttachmentMeta)
|
||||||
import Api.Model.AuthResult exposing (AuthResult)
|
import Api.Model.AuthResult exposing (AuthResult)
|
||||||
import Api.Model.BasicResult exposing (BasicResult)
|
import Api.Model.BasicResult exposing (BasicResult)
|
||||||
import Api.Model.Collective exposing (Collective)
|
import Api.Model.Collective exposing (Collective)
|
||||||
@ -112,6 +114,23 @@ import Util.Http as Http2
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
--- Attachment Metadata
|
||||||
|
|
||||||
|
|
||||||
|
getAttachmentMeta :
|
||||||
|
Flags
|
||||||
|
-> String
|
||||||
|
-> (Result Http.Error AttachmentMeta -> msg)
|
||||||
|
-> Cmd msg
|
||||||
|
getAttachmentMeta flags id receive =
|
||||||
|
Http2.authGet
|
||||||
|
{ url = flags.config.baseUrl ++ "/api/v1/sec/attachment/" ++ id ++ "/meta"
|
||||||
|
, account = getAccount flags
|
||||||
|
, expect = Http.expectJson receive Api.Model.AttachmentMeta.decoder
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
--- Get Sent Mails
|
--- Get Sent Mails
|
||||||
|
|
||||||
|
|
||||||
|
209
modules/webapp/src/main/elm/Comp/AttachmentMeta.elm
Normal file
209
modules/webapp/src/main/elm/Comp/AttachmentMeta.elm
Normal file
@ -0,0 +1,209 @@
|
|||||||
|
module Comp.AttachmentMeta exposing
|
||||||
|
( Model
|
||||||
|
, Msg
|
||||||
|
, init
|
||||||
|
, update
|
||||||
|
, view
|
||||||
|
)
|
||||||
|
|
||||||
|
import Api
|
||||||
|
import Api.Model.AttachmentMeta exposing (AttachmentMeta)
|
||||||
|
import Api.Model.ItemProposals exposing (ItemProposals)
|
||||||
|
import Api.Model.Label exposing (Label)
|
||||||
|
import Data.Flags exposing (Flags)
|
||||||
|
import Html exposing (..)
|
||||||
|
import Html.Attributes exposing (..)
|
||||||
|
import Http
|
||||||
|
import Util.Http
|
||||||
|
import Util.Time
|
||||||
|
|
||||||
|
|
||||||
|
type alias Model =
|
||||||
|
{ id : String
|
||||||
|
, meta : DataResult AttachmentMeta
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
type DataResult a
|
||||||
|
= NotAvailable
|
||||||
|
| Success a
|
||||||
|
| Failure String
|
||||||
|
|
||||||
|
|
||||||
|
emptyModel : Model
|
||||||
|
emptyModel =
|
||||||
|
{ id = ""
|
||||||
|
, meta = NotAvailable
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
init : Flags -> String -> ( Model, Cmd Msg )
|
||||||
|
init flags id =
|
||||||
|
( { emptyModel | id = id }
|
||||||
|
, Api.getAttachmentMeta flags id MetaResp
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
type Msg
|
||||||
|
= MetaResp (Result Http.Error AttachmentMeta)
|
||||||
|
|
||||||
|
|
||||||
|
update : Msg -> Model -> Model
|
||||||
|
update msg model =
|
||||||
|
case msg of
|
||||||
|
MetaResp (Ok am) ->
|
||||||
|
{ model | meta = Success am }
|
||||||
|
|
||||||
|
MetaResp (Err err) ->
|
||||||
|
{ model | meta = Failure (Util.Http.errorToString err) }
|
||||||
|
|
||||||
|
|
||||||
|
view : Model -> Html Msg
|
||||||
|
view model =
|
||||||
|
div []
|
||||||
|
[ h3 [ class "ui header" ]
|
||||||
|
[ text "Extracted Meta Data"
|
||||||
|
]
|
||||||
|
, case model.meta of
|
||||||
|
NotAvailable ->
|
||||||
|
div [ class "ui active dimmer" ]
|
||||||
|
[ div [ class "ui loader" ]
|
||||||
|
[]
|
||||||
|
]
|
||||||
|
|
||||||
|
Failure msg ->
|
||||||
|
div [ class "ui error message" ]
|
||||||
|
[ text msg
|
||||||
|
]
|
||||||
|
|
||||||
|
Success data ->
|
||||||
|
viewData data
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
|
viewData : AttachmentMeta -> Html Msg
|
||||||
|
viewData meta =
|
||||||
|
div []
|
||||||
|
[ div [ class "ui dividing header" ]
|
||||||
|
[ text "Content"
|
||||||
|
]
|
||||||
|
, div [ class "extracted-text" ]
|
||||||
|
[ text meta.content
|
||||||
|
]
|
||||||
|
, div [ class "ui dividing header" ]
|
||||||
|
[ text "Labels"
|
||||||
|
]
|
||||||
|
, div []
|
||||||
|
[ div [ class "ui horizontal list" ]
|
||||||
|
(List.map renderLabelItem meta.labels)
|
||||||
|
]
|
||||||
|
, div [ class "ui dividing header" ]
|
||||||
|
[ text "Proposals"
|
||||||
|
]
|
||||||
|
, viewProposals meta.proposals
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
|
viewProposals : ItemProposals -> Html Msg
|
||||||
|
viewProposals props =
|
||||||
|
let
|
||||||
|
mkItem n lbl =
|
||||||
|
div [ class "item" ]
|
||||||
|
[ div [ class "ui label" ]
|
||||||
|
[ text lbl.name
|
||||||
|
, div [ class "detail" ]
|
||||||
|
[ (String.fromInt (n + 1) ++ ".")
|
||||||
|
|> text
|
||||||
|
]
|
||||||
|
]
|
||||||
|
]
|
||||||
|
|
||||||
|
mkTimeItem ms =
|
||||||
|
div [ class "item" ]
|
||||||
|
[ div [ class "ui label" ]
|
||||||
|
[ Util.Time.formatDateShort ms |> text
|
||||||
|
]
|
||||||
|
]
|
||||||
|
in
|
||||||
|
div []
|
||||||
|
[ div [ class "ui small header" ]
|
||||||
|
[ text "Correspondent Organization"
|
||||||
|
]
|
||||||
|
, div [ class "ui horizontal list" ]
|
||||||
|
(List.indexedMap mkItem props.corrOrg)
|
||||||
|
, div [ class "ui small header" ]
|
||||||
|
[ text "Correspondent Person"
|
||||||
|
]
|
||||||
|
, div [ class "ui horizontal list" ]
|
||||||
|
(List.indexedMap mkItem props.corrPerson)
|
||||||
|
, div [ class "ui small header" ]
|
||||||
|
[ text "Concerning Person"
|
||||||
|
]
|
||||||
|
, div [ class "ui horizontal list" ]
|
||||||
|
(List.indexedMap mkItem props.concPerson)
|
||||||
|
, div [ class "ui small header" ]
|
||||||
|
[ text "Concerning Equipment"
|
||||||
|
]
|
||||||
|
, div [ class "ui horizontal list" ]
|
||||||
|
(List.indexedMap mkItem props.concEquipment)
|
||||||
|
, div [ class "ui small header" ]
|
||||||
|
[ text "Item Date"
|
||||||
|
]
|
||||||
|
, div [ class "ui horizontal list" ]
|
||||||
|
(List.map mkTimeItem props.itemDate)
|
||||||
|
, div [ class "ui small header" ]
|
||||||
|
[ text "Item Due Date"
|
||||||
|
]
|
||||||
|
, div [ class "ui horizontal list" ]
|
||||||
|
(List.map mkTimeItem props.dueDate)
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
|
renderLabelItem : Label -> Html Msg
|
||||||
|
renderLabelItem label =
|
||||||
|
div [ class "item" ]
|
||||||
|
[ renderLabel label
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
|
renderLabel : Label -> Html Msg
|
||||||
|
renderLabel label =
|
||||||
|
let
|
||||||
|
icon =
|
||||||
|
case label.labelType of
|
||||||
|
"organization" ->
|
||||||
|
"factory icon"
|
||||||
|
|
||||||
|
"person" ->
|
||||||
|
"user icon"
|
||||||
|
|
||||||
|
"location" ->
|
||||||
|
"map marker icon"
|
||||||
|
|
||||||
|
"date" ->
|
||||||
|
"calendar alternate icon"
|
||||||
|
|
||||||
|
"misc" ->
|
||||||
|
"help icon"
|
||||||
|
|
||||||
|
"email" ->
|
||||||
|
"at icon"
|
||||||
|
|
||||||
|
"website" ->
|
||||||
|
"external alternate icon"
|
||||||
|
|
||||||
|
_ ->
|
||||||
|
"tag icon"
|
||||||
|
in
|
||||||
|
div
|
||||||
|
[ class "ui basic label"
|
||||||
|
, title label.labelType
|
||||||
|
]
|
||||||
|
[ i [ class icon ] []
|
||||||
|
, text label.label
|
||||||
|
, div [ class "detail" ]
|
||||||
|
[ String.fromInt label.beginPos |> text
|
||||||
|
, text "-"
|
||||||
|
, String.fromInt label.endPos |> text
|
||||||
|
]
|
||||||
|
]
|
@ -22,6 +22,7 @@ import Api.Model.SentMails exposing (SentMails)
|
|||||||
import Api.Model.Tag exposing (Tag)
|
import Api.Model.Tag exposing (Tag)
|
||||||
import Api.Model.TagList exposing (TagList)
|
import Api.Model.TagList exposing (TagList)
|
||||||
import Browser.Navigation as Nav
|
import Browser.Navigation as Nav
|
||||||
|
import Comp.AttachmentMeta
|
||||||
import Comp.DatePicker
|
import Comp.DatePicker
|
||||||
import Comp.Dropdown exposing (isDropdownChangeMsg)
|
import Comp.Dropdown exposing (isDropdownChangeMsg)
|
||||||
import Comp.ItemMail
|
import Comp.ItemMail
|
||||||
@ -31,6 +32,7 @@ import Comp.YesNoDimmer
|
|||||||
import Data.Direction exposing (Direction)
|
import Data.Direction exposing (Direction)
|
||||||
import Data.Flags exposing (Flags)
|
import Data.Flags exposing (Flags)
|
||||||
import DatePicker exposing (DatePicker)
|
import DatePicker exposing (DatePicker)
|
||||||
|
import Dict exposing (Dict)
|
||||||
import Html exposing (..)
|
import Html exposing (..)
|
||||||
import Html.Attributes exposing (..)
|
import Html.Attributes exposing (..)
|
||||||
import Html.Events exposing (onClick, onInput)
|
import Html.Events exposing (onClick, onInput)
|
||||||
@ -69,6 +71,8 @@ type alias Model =
|
|||||||
, mailSendResult : Maybe BasicResult
|
, mailSendResult : Maybe BasicResult
|
||||||
, sentMails : Comp.SentMails.Model
|
, sentMails : Comp.SentMails.Model
|
||||||
, sentMailsOpen : Bool
|
, sentMailsOpen : Bool
|
||||||
|
, attachMeta : Dict String Comp.AttachmentMeta.Model
|
||||||
|
, attachMetaOpen : Bool
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -153,6 +157,8 @@ emptyModel =
|
|||||||
, mailSendResult = Nothing
|
, mailSendResult = Nothing
|
||||||
, sentMails = Comp.SentMails.init
|
, sentMails = Comp.SentMails.init
|
||||||
, sentMailsOpen = False
|
, sentMailsOpen = False
|
||||||
|
, attachMeta = Dict.empty
|
||||||
|
, attachMetaOpen = False
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -203,6 +209,8 @@ type Msg
|
|||||||
| SentMailsMsg Comp.SentMails.Msg
|
| SentMailsMsg Comp.SentMails.Msg
|
||||||
| ToggleSentMails
|
| ToggleSentMails
|
||||||
| SentMailsResp (Result Http.Error SentMails)
|
| SentMailsResp (Result Http.Error SentMails)
|
||||||
|
| AttachMetaClick String
|
||||||
|
| AttachMetaMsg String Comp.AttachmentMeta.Msg
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@ -877,6 +885,39 @@ update key flags next msg model =
|
|||||||
SentMailsResp (Err _) ->
|
SentMailsResp (Err _) ->
|
||||||
( model, Cmd.none )
|
( model, Cmd.none )
|
||||||
|
|
||||||
|
AttachMetaClick id ->
|
||||||
|
case Dict.get id model.attachMeta of
|
||||||
|
Just _ ->
|
||||||
|
( { model | attachMetaOpen = not model.attachMetaOpen }
|
||||||
|
, Cmd.none
|
||||||
|
)
|
||||||
|
|
||||||
|
Nothing ->
|
||||||
|
let
|
||||||
|
( am, ac ) =
|
||||||
|
Comp.AttachmentMeta.init flags id
|
||||||
|
|
||||||
|
nextMeta =
|
||||||
|
Dict.insert id am model.attachMeta
|
||||||
|
in
|
||||||
|
( { model | attachMeta = nextMeta, attachMetaOpen = True }
|
||||||
|
, Cmd.map (AttachMetaMsg id) ac
|
||||||
|
)
|
||||||
|
|
||||||
|
AttachMetaMsg id lmsg ->
|
||||||
|
case Dict.get id model.attachMeta of
|
||||||
|
Just cm ->
|
||||||
|
let
|
||||||
|
am =
|
||||||
|
Comp.AttachmentMeta.update lmsg cm
|
||||||
|
in
|
||||||
|
( { model | attachMeta = Dict.insert id am model.attachMeta }
|
||||||
|
, Cmd.none
|
||||||
|
)
|
||||||
|
|
||||||
|
Nothing ->
|
||||||
|
( model, Cmd.none )
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
-- view
|
-- view
|
||||||
@ -1007,7 +1048,7 @@ renderNotes model =
|
|||||||
Nothing ->
|
Nothing ->
|
||||||
[]
|
[]
|
||||||
|
|
||||||
Just str ->
|
Just _ ->
|
||||||
[ div [ class "ui segment" ]
|
[ div [ class "ui segment" ]
|
||||||
[ a
|
[ a
|
||||||
[ class "ui top left attached label"
|
[ class "ui top left attached label"
|
||||||
@ -1135,6 +1176,17 @@ renderAttachmentView model pos attach =
|
|||||||
]
|
]
|
||||||
, div [ class "right menu" ]
|
, div [ class "right menu" ]
|
||||||
[ a
|
[ a
|
||||||
|
[ classList
|
||||||
|
[ ( "toggle item", True )
|
||||||
|
, ( "active", isAttachMetaOpen model attach.id )
|
||||||
|
]
|
||||||
|
, title "Show extracted data"
|
||||||
|
, onClick (AttachMetaClick attach.id)
|
||||||
|
, href "#"
|
||||||
|
]
|
||||||
|
[ i [ class "info icon" ] []
|
||||||
|
]
|
||||||
|
, a
|
||||||
[ class "item"
|
[ class "item"
|
||||||
, title "Download to disk"
|
, title "Download to disk"
|
||||||
, download attachName
|
, download attachName
|
||||||
@ -1144,13 +1196,37 @@ renderAttachmentView model pos attach =
|
|||||||
]
|
]
|
||||||
]
|
]
|
||||||
]
|
]
|
||||||
, div [ class "ui 4:3 embed doc-embed" ]
|
, div
|
||||||
|
[ classList
|
||||||
|
[ ( "ui 4:3 embed doc-embed", True )
|
||||||
|
, ( "invisible hidden", isAttachMetaOpen model attach.id )
|
||||||
|
]
|
||||||
|
]
|
||||||
[ embed [ src fileUrl, type_ attach.contentType ]
|
[ embed [ src fileUrl, type_ attach.contentType ]
|
||||||
[]
|
[]
|
||||||
]
|
]
|
||||||
|
, div
|
||||||
|
[ classList
|
||||||
|
[ ( "ui basic segment", True )
|
||||||
|
, ( "invisible hidden", not (isAttachMetaOpen model attach.id) )
|
||||||
|
]
|
||||||
|
]
|
||||||
|
[ case Dict.get attach.id model.attachMeta of
|
||||||
|
Just am ->
|
||||||
|
Html.map (AttachMetaMsg attach.id)
|
||||||
|
(Comp.AttachmentMeta.view am)
|
||||||
|
|
||||||
|
Nothing ->
|
||||||
|
span [] []
|
||||||
|
]
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
|
isAttachMetaOpen : Model -> String -> Bool
|
||||||
|
isAttachMetaOpen model id =
|
||||||
|
model.attachMetaOpen && (Dict.get id model.attachMeta /= Nothing)
|
||||||
|
|
||||||
|
|
||||||
renderAttachmentsTabBody : Model -> List (Html Msg)
|
renderAttachmentsTabBody : Model -> List (Html Msg)
|
||||||
renderAttachmentsTabBody model =
|
renderAttachmentsTabBody model =
|
||||||
let
|
let
|
||||||
|
@ -39,6 +39,15 @@
|
|||||||
padding: 0 1em;
|
padding: 0 1em;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.default-layout .extracted-text {
|
||||||
|
font-family: monospace;
|
||||||
|
white-space: pre-wrap;
|
||||||
|
max-height: 20rem;
|
||||||
|
overflow: scroll;
|
||||||
|
background: floralwhite;
|
||||||
|
padding: 0.8em;
|
||||||
|
}
|
||||||
|
|
||||||
.markdown-preview {
|
.markdown-preview {
|
||||||
overflow: auto;
|
overflow: auto;
|
||||||
max-height: 300px;
|
max-height: 300px;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user