mirror of
https://github.com/TheAnachronism/docspell.git
synced 2025-04-04 10:29:34 +00:00
Edit name of multiple items
This commit is contained in:
parent
7ad37c8d26
commit
17472fa4ca
modules
backend/src/main/scala/docspell/backend/ops
restserver/src/main/scala/docspell/restserver/routes
webapp/src/main/elm
@ -51,7 +51,7 @@ trait OItem[F[_]] {
|
|||||||
|
|
||||||
def setDirection(item: Ident, direction: Direction, collective: Ident): F[AddResult]
|
def setDirection(item: Ident, direction: Direction, collective: Ident): F[AddResult]
|
||||||
|
|
||||||
def setFolder(item: Ident, folder: Option[Ident], collective: Ident): F[AddResult]
|
def setFolder(item: Ident, folder: Option[Ident], collective: Ident): F[UpdateResult]
|
||||||
|
|
||||||
def setCorrOrg(item: Ident, org: Option[Ident], collective: Ident): F[AddResult]
|
def setCorrOrg(item: Ident, org: Option[Ident], collective: Ident): F[AddResult]
|
||||||
|
|
||||||
@ -69,9 +69,15 @@ trait OItem[F[_]] {
|
|||||||
|
|
||||||
def addConcEquip(item: Ident, equip: REquipment): F[AddResult]
|
def addConcEquip(item: Ident, equip: REquipment): F[AddResult]
|
||||||
|
|
||||||
def setNotes(item: Ident, notes: Option[String], collective: Ident): F[AddResult]
|
def setNotes(item: Ident, notes: Option[String], collective: Ident): F[UpdateResult]
|
||||||
|
|
||||||
def setName(item: Ident, name: String, collective: Ident): F[AddResult]
|
def setName(item: Ident, name: String, collective: Ident): F[UpdateResult]
|
||||||
|
|
||||||
|
def setNameMultiple(
|
||||||
|
items: NonEmptyList[Ident],
|
||||||
|
name: String,
|
||||||
|
collective: Ident
|
||||||
|
): F[UpdateResult]
|
||||||
|
|
||||||
def setState(item: Ident, state: ItemState, collective: Ident): F[AddResult] =
|
def setState(item: Ident, state: ItemState, collective: Ident): F[AddResult] =
|
||||||
setStates(NonEmptyList.of(item), state, collective)
|
setStates(NonEmptyList.of(item), state, collective)
|
||||||
@ -102,7 +108,7 @@ trait OItem[F[_]] {
|
|||||||
attachId: Ident,
|
attachId: Ident,
|
||||||
name: Option[String],
|
name: Option[String],
|
||||||
collective: Ident
|
collective: Ident
|
||||||
): F[AddResult]
|
): F[UpdateResult]
|
||||||
|
|
||||||
/** Submits the item for re-processing. The list of attachment ids can
|
/** Submits the item for re-processing. The list of attachment ids can
|
||||||
* be used to only re-process a subset of the item's attachments.
|
* be used to only re-process a subset of the item's attachments.
|
||||||
@ -253,11 +259,12 @@ object OItem {
|
|||||||
item: Ident,
|
item: Ident,
|
||||||
folder: Option[Ident],
|
folder: Option[Ident],
|
||||||
collective: Ident
|
collective: Ident
|
||||||
): F[AddResult] =
|
): F[UpdateResult] =
|
||||||
store
|
UpdateResult
|
||||||
.transact(RItem.updateFolder(item, collective, folder))
|
.fromUpdate(
|
||||||
.attempt
|
store
|
||||||
.map(AddResult.fromUpdate)
|
.transact(RItem.updateFolder(item, collective, folder))
|
||||||
|
)
|
||||||
.flatTap(
|
.flatTap(
|
||||||
onSuccessIgnoreError(fts.updateFolder(logger, item, collective, folder))
|
onSuccessIgnoreError(fts.updateFolder(logger, item, collective, folder))
|
||||||
)
|
)
|
||||||
@ -390,24 +397,47 @@ object OItem {
|
|||||||
item: Ident,
|
item: Ident,
|
||||||
notes: Option[String],
|
notes: Option[String],
|
||||||
collective: Ident
|
collective: Ident
|
||||||
): F[AddResult] =
|
): F[UpdateResult] =
|
||||||
store
|
UpdateResult
|
||||||
.transact(RItem.updateNotes(item, collective, notes))
|
.fromUpdate(
|
||||||
.attempt
|
store
|
||||||
.map(AddResult.fromUpdate)
|
.transact(RItem.updateNotes(item, collective, notes))
|
||||||
|
)
|
||||||
.flatTap(
|
.flatTap(
|
||||||
onSuccessIgnoreError(fts.updateItemNotes(logger, item, collective, notes))
|
onSuccessIgnoreError(fts.updateItemNotes(logger, item, collective, notes))
|
||||||
)
|
)
|
||||||
|
|
||||||
def setName(item: Ident, name: String, collective: Ident): F[AddResult] =
|
def setName(item: Ident, name: String, collective: Ident): F[UpdateResult] =
|
||||||
store
|
UpdateResult
|
||||||
.transact(RItem.updateName(item, collective, name))
|
.fromUpdate(
|
||||||
.attempt
|
store
|
||||||
.map(AddResult.fromUpdate)
|
.transact(RItem.updateName(item, collective, name))
|
||||||
|
)
|
||||||
.flatTap(
|
.flatTap(
|
||||||
onSuccessIgnoreError(fts.updateItemName(logger, item, collective, name))
|
onSuccessIgnoreError(fts.updateItemName(logger, item, collective, name))
|
||||||
)
|
)
|
||||||
|
|
||||||
|
def setNameMultiple(
|
||||||
|
items: NonEmptyList[Ident],
|
||||||
|
name: String,
|
||||||
|
collective: Ident
|
||||||
|
): F[UpdateResult] =
|
||||||
|
for {
|
||||||
|
results <- items.traverse(i => setName(i, name, collective))
|
||||||
|
err <- results.traverse {
|
||||||
|
case UpdateResult.NotFound =>
|
||||||
|
logger.info("An item was not found when updating the name") *> 0.pure[F]
|
||||||
|
case UpdateResult.Failure(err) =>
|
||||||
|
logger.error(err)("An item failed to update its name") *> 1.pure[F]
|
||||||
|
case UpdateResult.Success =>
|
||||||
|
0.pure[F]
|
||||||
|
}
|
||||||
|
res =
|
||||||
|
if (results.size == err.fold)
|
||||||
|
UpdateResult.failure(new Exception("All items failed to update"))
|
||||||
|
else UpdateResult.success
|
||||||
|
} yield res
|
||||||
|
|
||||||
def setStates(
|
def setStates(
|
||||||
items: NonEmptyList[Ident],
|
items: NonEmptyList[Ident],
|
||||||
state: ItemState,
|
state: ItemState,
|
||||||
@ -455,11 +485,12 @@ object OItem {
|
|||||||
attachId: Ident,
|
attachId: Ident,
|
||||||
name: Option[String],
|
name: Option[String],
|
||||||
collective: Ident
|
collective: Ident
|
||||||
): F[AddResult] =
|
): F[UpdateResult] =
|
||||||
store
|
UpdateResult
|
||||||
.transact(RAttachment.updateName(attachId, collective, name))
|
.fromUpdate(
|
||||||
.attempt
|
store
|
||||||
.map(AddResult.fromUpdate)
|
.transact(RAttachment.updateName(attachId, collective, name))
|
||||||
|
)
|
||||||
.flatTap(
|
.flatTap(
|
||||||
onSuccessIgnoreError(
|
onSuccessIgnoreError(
|
||||||
OptionT(store.transact(RAttachment.findItemId(attachId)))
|
OptionT(store.transact(RAttachment.findItemId(attachId)))
|
||||||
@ -499,17 +530,17 @@ object OItem {
|
|||||||
_ <- if (notifyJoex) joex.notifyAllNodes else ().pure[F]
|
_ <- if (notifyJoex) joex.notifyAllNodes else ().pure[F]
|
||||||
} yield UpdateResult.success
|
} yield UpdateResult.success
|
||||||
|
|
||||||
private def onSuccessIgnoreError(update: F[Unit])(ar: AddResult): F[Unit] =
|
private def onSuccessIgnoreError(update: F[Unit])(ar: UpdateResult): F[Unit] =
|
||||||
ar match {
|
ar match {
|
||||||
case AddResult.Success =>
|
case UpdateResult.Success =>
|
||||||
update.attempt.flatMap {
|
update.attempt.flatMap {
|
||||||
case Right(()) => ().pure[F]
|
case Right(()) => ().pure[F]
|
||||||
case Left(ex) =>
|
case Left(ex) =>
|
||||||
logger.warn(s"Error updating full-text index: ${ex.getMessage}")
|
logger.warn(s"Error updating full-text index: ${ex.getMessage}")
|
||||||
}
|
}
|
||||||
case AddResult.Failure(_) =>
|
case UpdateResult.Failure(_) =>
|
||||||
().pure[F]
|
().pure[F]
|
||||||
case AddResult.EntityExists(_) =>
|
case UpdateResult.NotFound =>
|
||||||
().pure[F]
|
().pure[F]
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
@ -74,6 +74,19 @@ object ItemMultiRoutes {
|
|||||||
resp <- Ok(Conversions.basicResult(res, "Tags added."))
|
resp <- Ok(Conversions.basicResult(res, "Tags added."))
|
||||||
} yield resp
|
} yield resp
|
||||||
|
|
||||||
|
case req @ PUT -> Root / "name" =>
|
||||||
|
for {
|
||||||
|
json <- req.as[ItemsAndName]
|
||||||
|
items <- readIds[F](json.items)
|
||||||
|
res <- backend.item.setNameMultiple(
|
||||||
|
items,
|
||||||
|
json.name.notEmpty.getOrElse(""),
|
||||||
|
user.account.collective
|
||||||
|
)
|
||||||
|
resp <- Ok(Conversions.basicResult(res, "Name updated"))
|
||||||
|
} yield resp
|
||||||
|
|
||||||
|
|
||||||
// case req @ PUT -> Root / "direction" =>
|
// case req @ PUT -> Root / "direction" =>
|
||||||
// for {
|
// for {
|
||||||
// dir <- req.as[DirectionValue]
|
// dir <- req.as[DirectionValue]
|
||||||
@ -116,17 +129,6 @@ object ItemMultiRoutes {
|
|||||||
// resp <- Ok(Conversions.basicResult(res, "Concerned equipment updated"))
|
// resp <- Ok(Conversions.basicResult(res, "Concerned equipment updated"))
|
||||||
// } yield resp
|
// } yield resp
|
||||||
|
|
||||||
// case req @ PUT -> Root / "name" =>
|
|
||||||
// for {
|
|
||||||
// text <- req.as[OptionalText]
|
|
||||||
// res <- backend.item.setName(
|
|
||||||
// id,
|
|
||||||
// text.text.notEmpty.getOrElse(""),
|
|
||||||
// user.account.collective
|
|
||||||
// )
|
|
||||||
// resp <- Ok(Conversions.basicResult(res, "Name updated"))
|
|
||||||
// } yield resp
|
|
||||||
|
|
||||||
// case req @ PUT -> Root / "duedate" =>
|
// case req @ PUT -> Root / "duedate" =>
|
||||||
// for {
|
// for {
|
||||||
// date <- req.as[OptionalDate]
|
// date <- req.as[OptionalDate]
|
||||||
@ -165,6 +167,10 @@ object ItemMultiRoutes {
|
|||||||
def notEmpty: Option[String] =
|
def notEmpty: Option[String] =
|
||||||
opt.map(_.trim).filter(_.nonEmpty)
|
opt.map(_.trim).filter(_.nonEmpty)
|
||||||
}
|
}
|
||||||
|
implicit final class StringOps(str: String) {
|
||||||
|
def notEmpty: Option[String] =
|
||||||
|
Option(str).notEmpty
|
||||||
|
}
|
||||||
|
|
||||||
private def readId[F[_]](
|
private def readId[F[_]](
|
||||||
id: String
|
id: String
|
||||||
|
@ -88,6 +88,7 @@ module Api exposing
|
|||||||
, setItemName
|
, setItemName
|
||||||
, setItemNotes
|
, setItemNotes
|
||||||
, setJobPrio
|
, setJobPrio
|
||||||
|
, setNameMultiple
|
||||||
, setTags
|
, setTags
|
||||||
, setTagsMultiple
|
, setTagsMultiple
|
||||||
, setUnconfirmed
|
, setUnconfirmed
|
||||||
@ -132,6 +133,7 @@ import Api.Model.ItemLightList exposing (ItemLightList)
|
|||||||
import Api.Model.ItemProposals exposing (ItemProposals)
|
import Api.Model.ItemProposals exposing (ItemProposals)
|
||||||
import Api.Model.ItemSearch exposing (ItemSearch)
|
import Api.Model.ItemSearch exposing (ItemSearch)
|
||||||
import Api.Model.ItemUploadMeta exposing (ItemUploadMeta)
|
import Api.Model.ItemUploadMeta exposing (ItemUploadMeta)
|
||||||
|
import Api.Model.ItemsAndName exposing (ItemsAndName)
|
||||||
import Api.Model.ItemsAndRefs exposing (ItemsAndRefs)
|
import Api.Model.ItemsAndRefs exposing (ItemsAndRefs)
|
||||||
import Api.Model.JobPriority exposing (JobPriority)
|
import Api.Model.JobPriority exposing (JobPriority)
|
||||||
import Api.Model.JobQueueState exposing (JobQueueState)
|
import Api.Model.JobQueueState exposing (JobQueueState)
|
||||||
@ -1296,6 +1298,20 @@ addTagsMultiple flags data receive =
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
setNameMultiple :
|
||||||
|
Flags
|
||||||
|
-> ItemsAndName
|
||||||
|
-> (Result Http.Error BasicResult -> msg)
|
||||||
|
-> Cmd msg
|
||||||
|
setNameMultiple flags data receive =
|
||||||
|
Http2.authPut
|
||||||
|
{ url = flags.config.baseUrl ++ "/api/v1/sec/items/name"
|
||||||
|
, account = getAccount flags
|
||||||
|
, body = Http.jsonBody (Api.Model.ItemsAndName.encode data)
|
||||||
|
, expect = Http.expectJson receive Api.Model.BasicResult.decoder
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
--- Item
|
--- Item
|
||||||
|
|
||||||
|
@ -6,6 +6,7 @@ module Comp.ItemDetail.FormChange exposing
|
|||||||
import Api
|
import Api
|
||||||
import Api.Model.BasicResult exposing (BasicResult)
|
import Api.Model.BasicResult exposing (BasicResult)
|
||||||
import Api.Model.IdName exposing (IdName)
|
import Api.Model.IdName exposing (IdName)
|
||||||
|
import Api.Model.ItemsAndName exposing (ItemsAndName)
|
||||||
import Api.Model.ItemsAndRefs exposing (ItemsAndRefs)
|
import Api.Model.ItemsAndRefs exposing (ItemsAndRefs)
|
||||||
import Api.Model.ReferenceList exposing (ReferenceList)
|
import Api.Model.ReferenceList exposing (ReferenceList)
|
||||||
import Data.Direction exposing (Direction)
|
import Data.Direction exposing (Direction)
|
||||||
@ -47,5 +48,12 @@ multiUpdate flags ids change receive =
|
|||||||
in
|
in
|
||||||
Api.setTagsMultiple flags data receive
|
Api.setTagsMultiple flags data receive
|
||||||
|
|
||||||
|
NameChange name ->
|
||||||
|
let
|
||||||
|
data =
|
||||||
|
ItemsAndName items name
|
||||||
|
in
|
||||||
|
Api.setNameMultiple flags data receive
|
||||||
|
|
||||||
_ ->
|
_ ->
|
||||||
Cmd.none
|
Cmd.none
|
||||||
|
Loading…
x
Reference in New Issue
Block a user