Edit name of multiple items

This commit is contained in:
Eike Kettner 2020-10-26 12:17:55 +01:00
parent 7ad37c8d26
commit 17472fa4ca
4 changed files with 100 additions and 39 deletions

View File

@ -51,7 +51,7 @@ trait OItem[F[_]] {
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]
@ -69,9 +69,15 @@ trait OItem[F[_]] {
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] =
setStates(NonEmptyList.of(item), state, collective)
@ -102,7 +108,7 @@ trait OItem[F[_]] {
attachId: Ident,
name: Option[String],
collective: Ident
): F[AddResult]
): F[UpdateResult]
/** 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.
@ -253,11 +259,12 @@ object OItem {
item: Ident,
folder: Option[Ident],
collective: Ident
): F[AddResult] =
store
.transact(RItem.updateFolder(item, collective, folder))
.attempt
.map(AddResult.fromUpdate)
): F[UpdateResult] =
UpdateResult
.fromUpdate(
store
.transact(RItem.updateFolder(item, collective, folder))
)
.flatTap(
onSuccessIgnoreError(fts.updateFolder(logger, item, collective, folder))
)
@ -390,24 +397,47 @@ object OItem {
item: Ident,
notes: Option[String],
collective: Ident
): F[AddResult] =
store
.transact(RItem.updateNotes(item, collective, notes))
.attempt
.map(AddResult.fromUpdate)
): F[UpdateResult] =
UpdateResult
.fromUpdate(
store
.transact(RItem.updateNotes(item, collective, notes))
)
.flatTap(
onSuccessIgnoreError(fts.updateItemNotes(logger, item, collective, notes))
)
def setName(item: Ident, name: String, collective: Ident): F[AddResult] =
store
.transact(RItem.updateName(item, collective, name))
.attempt
.map(AddResult.fromUpdate)
def setName(item: Ident, name: String, collective: Ident): F[UpdateResult] =
UpdateResult
.fromUpdate(
store
.transact(RItem.updateName(item, collective, name))
)
.flatTap(
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(
items: NonEmptyList[Ident],
state: ItemState,
@ -455,11 +485,12 @@ object OItem {
attachId: Ident,
name: Option[String],
collective: Ident
): F[AddResult] =
store
.transact(RAttachment.updateName(attachId, collective, name))
.attempt
.map(AddResult.fromUpdate)
): F[UpdateResult] =
UpdateResult
.fromUpdate(
store
.transact(RAttachment.updateName(attachId, collective, name))
)
.flatTap(
onSuccessIgnoreError(
OptionT(store.transact(RAttachment.findItemId(attachId)))
@ -499,17 +530,17 @@ object OItem {
_ <- if (notifyJoex) joex.notifyAllNodes else ().pure[F]
} 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 {
case AddResult.Success =>
case UpdateResult.Success =>
update.attempt.flatMap {
case Right(()) => ().pure[F]
case Left(ex) =>
logger.warn(s"Error updating full-text index: ${ex.getMessage}")
}
case AddResult.Failure(_) =>
case UpdateResult.Failure(_) =>
().pure[F]
case AddResult.EntityExists(_) =>
case UpdateResult.NotFound =>
().pure[F]
}
})

View File

@ -74,6 +74,19 @@ object ItemMultiRoutes {
resp <- Ok(Conversions.basicResult(res, "Tags added."))
} 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" =>
// for {
// dir <- req.as[DirectionValue]
@ -116,17 +129,6 @@ object ItemMultiRoutes {
// resp <- Ok(Conversions.basicResult(res, "Concerned equipment updated"))
// } 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" =>
// for {
// date <- req.as[OptionalDate]
@ -165,6 +167,10 @@ object ItemMultiRoutes {
def notEmpty: Option[String] =
opt.map(_.trim).filter(_.nonEmpty)
}
implicit final class StringOps(str: String) {
def notEmpty: Option[String] =
Option(str).notEmpty
}
private def readId[F[_]](
id: String

View File

@ -88,6 +88,7 @@ module Api exposing
, setItemName
, setItemNotes
, setJobPrio
, setNameMultiple
, setTags
, setTagsMultiple
, setUnconfirmed
@ -132,6 +133,7 @@ import Api.Model.ItemLightList exposing (ItemLightList)
import Api.Model.ItemProposals exposing (ItemProposals)
import Api.Model.ItemSearch exposing (ItemSearch)
import Api.Model.ItemUploadMeta exposing (ItemUploadMeta)
import Api.Model.ItemsAndName exposing (ItemsAndName)
import Api.Model.ItemsAndRefs exposing (ItemsAndRefs)
import Api.Model.JobPriority exposing (JobPriority)
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

View File

@ -6,6 +6,7 @@ module Comp.ItemDetail.FormChange exposing
import Api
import Api.Model.BasicResult exposing (BasicResult)
import Api.Model.IdName exposing (IdName)
import Api.Model.ItemsAndName exposing (ItemsAndName)
import Api.Model.ItemsAndRefs exposing (ItemsAndRefs)
import Api.Model.ReferenceList exposing (ReferenceList)
import Data.Direction exposing (Direction)
@ -47,5 +48,12 @@ multiUpdate flags ids change receive =
in
Api.setTagsMultiple flags data receive
NameChange name ->
let
data =
ItemsAndName items name
in
Api.setNameMultiple flags data receive
_ ->
Cmd.none