mirror of
				https://github.com/TheAnachronism/docspell.git
				synced 2025-10-30 21:40:12 +00:00 
			
		
		
		
	Edit name of multiple items
This commit is contained in:
		| @@ -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] | ||||
|           } | ||||
|       }) | ||||
|   | ||||
| @@ -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 | ||||
|   | ||||
| @@ -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 | ||||
|  | ||||
|   | ||||
| @@ -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 | ||||
|   | ||||
		Reference in New Issue
	
	Block a user