mirror of
				https://github.com/TheAnachronism/docspell.git
				synced 2025-11-03 18:00:11 +00:00 
			
		
		
		
	Merge pull request #1816 from eikek/1775-edit-extracted-text
Allow to change extracted text of attachments
This commit is contained in:
		@@ -4823,6 +4823,72 @@ paths:
 | 
			
		||||
            application/json:
 | 
			
		||||
              schema:
 | 
			
		||||
                $ref: "#/components/schemas/BasicResult"
 | 
			
		||||
  /sec/attachment/{id}/extracted-text:
 | 
			
		||||
    get:
 | 
			
		||||
      operationId: "sec-attachment-get-extracted-text"
 | 
			
		||||
      tags: [ Attachment ]
 | 
			
		||||
      summary: Get the extracted text of the given attachment.
 | 
			
		||||
      description: |
 | 
			
		||||
        Returns the extracted text of the attachment with the given
 | 
			
		||||
        id.
 | 
			
		||||
      security:
 | 
			
		||||
        - authTokenHeader: []
 | 
			
		||||
      parameters:
 | 
			
		||||
        - $ref: "#/components/parameters/id"
 | 
			
		||||
      responses:
 | 
			
		||||
        422:
 | 
			
		||||
          description: BadRequest
 | 
			
		||||
        200:
 | 
			
		||||
          description: Ok
 | 
			
		||||
          content:
 | 
			
		||||
            application/json:
 | 
			
		||||
              schema:
 | 
			
		||||
                $ref: "#/components/schemas/OptionalText"
 | 
			
		||||
    delete:
 | 
			
		||||
      operationId: "sec-attachment-delete-extracted-text"
 | 
			
		||||
      summary: Removes extracted text for the given attachment.
 | 
			
		||||
      description: |
 | 
			
		||||
        Removes any extracted text for the given attachment.
 | 
			
		||||
      security:
 | 
			
		||||
        - authTokenHeader: []
 | 
			
		||||
      parameters:
 | 
			
		||||
        - $ref: "#/components/parameters/id"
 | 
			
		||||
      responses:
 | 
			
		||||
        422:
 | 
			
		||||
          description: BadRequest
 | 
			
		||||
        200:
 | 
			
		||||
          description: Ok
 | 
			
		||||
          content:
 | 
			
		||||
            application/json:
 | 
			
		||||
              schema:
 | 
			
		||||
                $ref: "#/components/schemas/BasicResult"    
 | 
			
		||||
    post:
 | 
			
		||||
      operationId: "sec-attachment-post-extracted-text"
 | 
			
		||||
      tags: [ Attachment ]
 | 
			
		||||
      summary: Changes the extracted text for an attachment
 | 
			
		||||
      description: |
 | 
			
		||||
        Changes the extracted text of the attachment with the given
 | 
			
		||||
        id. The attachment must be part of an item that belongs to the
 | 
			
		||||
        collective of the current user. This can be used to correct
 | 
			
		||||
        poor ocr-ed files.
 | 
			
		||||
      security:
 | 
			
		||||
        - authTokenHeader: []
 | 
			
		||||
      parameters:
 | 
			
		||||
        - $ref: "#/components/parameters/id"
 | 
			
		||||
      requestBody:
 | 
			
		||||
        content:
 | 
			
		||||
          application/json:
 | 
			
		||||
            schema:
 | 
			
		||||
              $ref: "#/components/schemas/OptionalText"
 | 
			
		||||
      responses:
 | 
			
		||||
        422:
 | 
			
		||||
          description: BadRequest
 | 
			
		||||
        200:
 | 
			
		||||
          description: Ok
 | 
			
		||||
          content:
 | 
			
		||||
            application/json:
 | 
			
		||||
              schema:
 | 
			
		||||
                $ref: "#/components/schemas/BasicResult"
 | 
			
		||||
 | 
			
		||||
  /sec/attachments/delete:
 | 
			
		||||
    post:
 | 
			
		||||
 
 | 
			
		||||
@@ -6,8 +6,9 @@
 | 
			
		||||
 | 
			
		||||
package docspell.restserver.routes
 | 
			
		||||
 | 
			
		||||
import cats.data.OptionT
 | 
			
		||||
import cats.effect._
 | 
			
		||||
import cats.implicits._
 | 
			
		||||
import cats.syntax.all._
 | 
			
		||||
 | 
			
		||||
import docspell.backend.BackendApp
 | 
			
		||||
import docspell.backend.auth.AuthToken
 | 
			
		||||
@@ -157,6 +158,40 @@ object AttachmentRoutes {
 | 
			
		||||
          resp <- Ok(Conversions.basicResult(res, "Name updated."))
 | 
			
		||||
        } yield resp
 | 
			
		||||
 | 
			
		||||
      case req @ POST -> Root / Ident(id) / "extracted-text" =>
 | 
			
		||||
        (for {
 | 
			
		||||
          itemId <- OptionT(
 | 
			
		||||
            backend.itemSearch.findAttachment(id, user.account.collectiveId)
 | 
			
		||||
          ).map(_.ra.itemId)
 | 
			
		||||
          nn <- OptionT.liftF(req.as[OptionalText])
 | 
			
		||||
          newText = nn.text.getOrElse("").pure[F]
 | 
			
		||||
          _ <- OptionT.liftF(
 | 
			
		||||
            backend.attachment
 | 
			
		||||
              .setExtractedText(user.account.collectiveId, itemId, id, newText)
 | 
			
		||||
          )
 | 
			
		||||
          resp <- OptionT.liftF(Ok(BasicResult(true, "Extracted text updated.")))
 | 
			
		||||
        } yield resp).getOrElseF(NotFound(BasicResult(false, "Attachment not found")))
 | 
			
		||||
 | 
			
		||||
      case DELETE -> Root / Ident(id) / "extracted-text" =>
 | 
			
		||||
        (for {
 | 
			
		||||
          itemId <- OptionT(
 | 
			
		||||
            backend.itemSearch.findAttachment(id, user.account.collectiveId)
 | 
			
		||||
          ).map(_.ra.itemId)
 | 
			
		||||
          _ <- OptionT.liftF(
 | 
			
		||||
            backend.attachment
 | 
			
		||||
              .setExtractedText(user.account.collectiveId, itemId, id, "".pure[F])
 | 
			
		||||
          )
 | 
			
		||||
          resp <- OptionT.liftF(Ok(BasicResult(true, "Extracted text cleared.")))
 | 
			
		||||
        } yield resp).getOrElseF(NotFound())
 | 
			
		||||
 | 
			
		||||
      case GET -> Root / Ident(id) / "extracted-text" =>
 | 
			
		||||
        (for {
 | 
			
		||||
          meta <- OptionT(
 | 
			
		||||
            backend.itemSearch.findAttachmentMeta(id, user.account.collectiveId)
 | 
			
		||||
          )
 | 
			
		||||
          resp <- OptionT.liftF(Ok(OptionalText(meta.content)))
 | 
			
		||||
        } yield resp).getOrElseF(NotFound(BasicResult(false, "Attachment not found")))
 | 
			
		||||
 | 
			
		||||
      case DELETE -> Root / Ident(id) =>
 | 
			
		||||
        for {
 | 
			
		||||
          n <- backend.item.deleteAttachment(id, user.account.collectiveId)
 | 
			
		||||
 
 | 
			
		||||
@@ -159,6 +159,7 @@ module Api exposing
 | 
			
		||||
    , searchShare
 | 
			
		||||
    , searchShareStats
 | 
			
		||||
    , sendMail
 | 
			
		||||
    , setAttachmentExtractedText
 | 
			
		||||
    , setAttachmentName
 | 
			
		||||
    , setCollectiveSettings
 | 
			
		||||
    , setConcEquip
 | 
			
		||||
@@ -2049,6 +2050,21 @@ setAttachmentName flags attachId newName receive =
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
setAttachmentExtractedText :
 | 
			
		||||
    Flags
 | 
			
		||||
    -> String
 | 
			
		||||
    -> Maybe String
 | 
			
		||||
    -> (Result Http.Error BasicResult -> msg)
 | 
			
		||||
    -> Cmd msg
 | 
			
		||||
setAttachmentExtractedText flags attachId newName receive =
 | 
			
		||||
    Http2.authPost
 | 
			
		||||
        { url = flags.config.baseUrl ++ "/api/v1/sec/attachment/" ++ attachId ++ "/extracted-text"
 | 
			
		||||
        , account = getAccount flags
 | 
			
		||||
        , body = Http.jsonBody (Api.Model.OptionalText.encode (OptionalText newName))
 | 
			
		||||
        , expect = Http.expectJson receive Api.Model.BasicResult.decoder
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
moveAttachmentBefore :
 | 
			
		||||
    Flags
 | 
			
		||||
    -> String
 | 
			
		||||
 
 | 
			
		||||
@@ -15,12 +15,14 @@ module Comp.AttachmentMeta exposing
 | 
			
		||||
 | 
			
		||||
import Api
 | 
			
		||||
import Api.Model.AttachmentMeta exposing (AttachmentMeta)
 | 
			
		||||
import Api.Model.BasicResult exposing (BasicResult)
 | 
			
		||||
import Api.Model.ItemProposals exposing (ItemProposals)
 | 
			
		||||
import Api.Model.Label exposing (Label)
 | 
			
		||||
import Comp.Basic as B
 | 
			
		||||
import Data.Flags exposing (Flags)
 | 
			
		||||
import Html exposing (..)
 | 
			
		||||
import Html.Attributes exposing (..)
 | 
			
		||||
import Html.Events exposing (onClick, onInput)
 | 
			
		||||
import Http
 | 
			
		||||
import Messages.Comp.AttachmentMeta exposing (Texts)
 | 
			
		||||
import Styles as S
 | 
			
		||||
@@ -28,13 +30,20 @@ import Styles as S
 | 
			
		||||
 | 
			
		||||
type alias Model =
 | 
			
		||||
    { id : String
 | 
			
		||||
    , meta : DataResult AttachmentMeta
 | 
			
		||||
    , meta : DataResult
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
type DataResult a
 | 
			
		||||
type alias EditModel =
 | 
			
		||||
    { meta : AttachmentMeta
 | 
			
		||||
    , text : String
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
type DataResult
 | 
			
		||||
    = NotAvailable
 | 
			
		||||
    | Success a
 | 
			
		||||
    | Success AttachmentMeta
 | 
			
		||||
    | Editing EditModel
 | 
			
		||||
    | HttpFailure Http.Error
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@@ -54,16 +63,64 @@ init flags id =
 | 
			
		||||
 | 
			
		||||
type Msg
 | 
			
		||||
    = MetaResp (Result Http.Error AttachmentMeta)
 | 
			
		||||
    | SaveResp String (Result Http.Error BasicResult)
 | 
			
		||||
    | ToggleEdit
 | 
			
		||||
    | SaveExtractedText
 | 
			
		||||
    | SetExtractedText String
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
update : Msg -> Model -> Model
 | 
			
		||||
update msg model =
 | 
			
		||||
update : Flags -> Msg -> Model -> ( Model, Cmd Msg )
 | 
			
		||||
update flags msg model =
 | 
			
		||||
    case msg of
 | 
			
		||||
        MetaResp (Ok am) ->
 | 
			
		||||
            { model | meta = Success am }
 | 
			
		||||
            ( { model | meta = Success am }, Cmd.none )
 | 
			
		||||
 | 
			
		||||
        MetaResp (Err err) ->
 | 
			
		||||
            { model | meta = HttpFailure err }
 | 
			
		||||
            ( { model | meta = HttpFailure err }, Cmd.none )
 | 
			
		||||
 | 
			
		||||
        SaveResp newText (Ok result) ->
 | 
			
		||||
            if result.success then
 | 
			
		||||
                case model.meta of
 | 
			
		||||
                    Editing { meta } ->
 | 
			
		||||
                        ( { model | meta = Success { meta | content = newText } }, Cmd.none )
 | 
			
		||||
 | 
			
		||||
                    _ ->
 | 
			
		||||
                        ( model, Cmd.none )
 | 
			
		||||
 | 
			
		||||
            else
 | 
			
		||||
                ( model, Cmd.none )
 | 
			
		||||
 | 
			
		||||
        SaveResp _ (Err err) ->
 | 
			
		||||
            ( { model | meta = HttpFailure err }, Cmd.none )
 | 
			
		||||
 | 
			
		||||
        ToggleEdit ->
 | 
			
		||||
            case model.meta of
 | 
			
		||||
                Editing m ->
 | 
			
		||||
                    ( { model | meta = Success m.meta }, Cmd.none )
 | 
			
		||||
 | 
			
		||||
                Success m ->
 | 
			
		||||
                    ( { model | meta = Editing { meta = m, text = m.content } }, Cmd.none )
 | 
			
		||||
 | 
			
		||||
                _ ->
 | 
			
		||||
                    ( model, Cmd.none )
 | 
			
		||||
 | 
			
		||||
        SaveExtractedText ->
 | 
			
		||||
            case model.meta of
 | 
			
		||||
                Editing em ->
 | 
			
		||||
                    ( model
 | 
			
		||||
                    , Api.setAttachmentExtractedText flags model.id (Just em.text) (SaveResp em.text)
 | 
			
		||||
                    )
 | 
			
		||||
 | 
			
		||||
                _ ->
 | 
			
		||||
                    ( model, Cmd.none )
 | 
			
		||||
 | 
			
		||||
        SetExtractedText txt ->
 | 
			
		||||
            case model.meta of
 | 
			
		||||
                Editing em ->
 | 
			
		||||
                    ( { model | meta = Editing { em | text = txt } }, Cmd.none )
 | 
			
		||||
 | 
			
		||||
                _ ->
 | 
			
		||||
                    ( model, Cmd.none )
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@@ -89,19 +146,55 @@ view2 texts attrs model =
 | 
			
		||||
                    ]
 | 
			
		||||
 | 
			
		||||
            Success data ->
 | 
			
		||||
                viewData2 texts data
 | 
			
		||||
                viewData2 texts data Nothing
 | 
			
		||||
 | 
			
		||||
            Editing em ->
 | 
			
		||||
                viewData2 texts em.meta (Just em.text)
 | 
			
		||||
        ]
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
viewData2 : Texts -> AttachmentMeta -> Html Msg
 | 
			
		||||
viewData2 texts meta =
 | 
			
		||||
viewData2 : Texts -> AttachmentMeta -> Maybe String -> Html Msg
 | 
			
		||||
viewData2 texts meta maybeText =
 | 
			
		||||
    div [ class "flex flex-col" ]
 | 
			
		||||
        [ div [ class "text-lg font-bold" ]
 | 
			
		||||
            [ text texts.content
 | 
			
		||||
            ]
 | 
			
		||||
        , div [ class "px-2 py-2 text-sm bg-yellow-50 dark:bg-stone-800 break-words whitespace-pre max-h-80 overflow-auto" ]
 | 
			
		||||
            [ text meta.content
 | 
			
		||||
        [ div [ class "flex flex-row items-center" ]
 | 
			
		||||
            [ div [ class "text-lg font-bold flex flex-grow" ]
 | 
			
		||||
                [ text texts.content
 | 
			
		||||
                ]
 | 
			
		||||
            , case maybeText of
 | 
			
		||||
                Nothing ->
 | 
			
		||||
                    div [ class "flex text-sm" ]
 | 
			
		||||
                        [ a [ href "#", class S.link, onClick ToggleEdit ]
 | 
			
		||||
                            [ i [ class "fa fa-edit pr-1" ] []
 | 
			
		||||
                            , text texts.basics.edit
 | 
			
		||||
                            ]
 | 
			
		||||
                        ]
 | 
			
		||||
 | 
			
		||||
                Just _ ->
 | 
			
		||||
                    div [ class "flex text-sm" ]
 | 
			
		||||
                        [ a [ href "#", class S.link, onClick ToggleEdit ]
 | 
			
		||||
                            [ text texts.basics.cancel
 | 
			
		||||
                            ]
 | 
			
		||||
                        , span [ class "px-2" ] [ text "•" ]
 | 
			
		||||
                        , a [ href "#", class S.link, onClick SaveExtractedText ]
 | 
			
		||||
                            [ i [ class "fa fa-save pr-1" ] []
 | 
			
		||||
                            , text texts.basics.submit
 | 
			
		||||
                            ]
 | 
			
		||||
                        ]
 | 
			
		||||
            ]
 | 
			
		||||
        , case maybeText of
 | 
			
		||||
            Nothing ->
 | 
			
		||||
                div [ class "px-2 py-2 text-sm bg-yellow-50 dark:bg-stone-800 break-words whitespace-pre max-h-80 overflow-auto" ]
 | 
			
		||||
                    [ text meta.content
 | 
			
		||||
                    ]
 | 
			
		||||
 | 
			
		||||
            Just em ->
 | 
			
		||||
                textarea
 | 
			
		||||
                    [ class "px-2 py-2 text-sm bg-yellow-50 dark:bg-stone-800 break-words whitespace-pre h-80 overflow-auto"
 | 
			
		||||
                    , value em
 | 
			
		||||
                    , onInput SetExtractedText
 | 
			
		||||
                    , rows 10
 | 
			
		||||
                    ]
 | 
			
		||||
                    []
 | 
			
		||||
        , div [ class "text-lg font-bold mt-2" ]
 | 
			
		||||
            [ text texts.labels
 | 
			
		||||
            ]
 | 
			
		||||
 
 | 
			
		||||
@@ -991,11 +991,13 @@ update inav env msg model =
 | 
			
		||||
            case Dict.get id model.attachMeta of
 | 
			
		||||
                Just cm ->
 | 
			
		||||
                    let
 | 
			
		||||
                        am =
 | 
			
		||||
                            Comp.AttachmentMeta.update lmsg cm
 | 
			
		||||
                        ( am, ac ) =
 | 
			
		||||
                            Comp.AttachmentMeta.update env.flags lmsg cm
 | 
			
		||||
                    in
 | 
			
		||||
                    resultModel
 | 
			
		||||
                        { model | attachMeta = Dict.insert id am model.attachMeta }
 | 
			
		||||
                    resultModelCmd
 | 
			
		||||
                        ( { model | attachMeta = Dict.insert id am model.attachMeta }
 | 
			
		||||
                        , Cmd.map (AttachMetaMsg id) ac
 | 
			
		||||
                        )
 | 
			
		||||
 | 
			
		||||
                Nothing ->
 | 
			
		||||
                    resultModel model
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user