From f4c79c72ae7a742a66137b47fc65297bfe827517 Mon Sep 17 00:00:00 2001 From: Eike Kettner Date: Sat, 31 Oct 2020 12:03:05 +0100 Subject: [PATCH] Allow to remove tags from multiple items --- .../scala/docspell/backend/ops/OItem.scala | 29 +++++++++++++++++++ .../src/main/resources/docspell-openapi.yml | 23 +++++++++++++++ .../restserver/routes/ItemMultiRoutes.scala | 12 ++++++++ 3 files changed, 64 insertions(+) diff --git a/modules/backend/src/main/scala/docspell/backend/ops/OItem.scala b/modules/backend/src/main/scala/docspell/backend/ops/OItem.scala index fd3e5344..492d613a 100644 --- a/modules/backend/src/main/scala/docspell/backend/ops/OItem.scala +++ b/modules/backend/src/main/scala/docspell/backend/ops/OItem.scala @@ -46,6 +46,12 @@ trait OItem[F[_]] { collective: Ident ): F[UpdateResult] + def removeTagsMultipleItems( + items: NonEmptyList[Ident], + tags: List[String], + collective: Ident + ): F[UpdateResult] + /** Toggles tags of the given item. Tags must exist, but can be IDs or names. */ def toggleTags(item: Ident, tags: List[String], collective: Ident): F[UpdateResult] @@ -225,6 +231,29 @@ object OItem { } } + def removeTagsMultipleItems( + items: NonEmptyList[Ident], + tags: List[String], + collective: Ident + ): F[UpdateResult] = + tags.distinct match { + case Nil => UpdateResult.success.pure[F] + case ws => + store.transact { + (for { + itemIds <- OptionT + .liftF(RItem.filterItems(items, collective)) + .filter(_.nonEmpty) + given <- OptionT.liftF(RTag.findAllByNameOrId(ws, collective)) + _ <- OptionT.liftF( + itemIds.traverse(item => + RTagItem.removeAllTags(item, given.map(_.tagId).toList) + ) + ) + } yield UpdateResult.success).getOrElse(UpdateResult.notFound) + } + } + def toggleTags( item: Ident, tags: List[String], diff --git a/modules/restapi/src/main/resources/docspell-openapi.yml b/modules/restapi/src/main/resources/docspell-openapi.yml index 2eabe73f..881511be 100644 --- a/modules/restapi/src/main/resources/docspell-openapi.yml +++ b/modules/restapi/src/main/resources/docspell-openapi.yml @@ -1945,6 +1945,29 @@ paths: application/json: schema: $ref: "#/components/schemas/BasicResult" + + /sec/items/tagsremove: + post: + tags: + - Item (Multi Edit) + summary: Remove tags from multiple items + description: | + Remove the given tags from all given items. + security: + - authTokenHeader: [] + requestBody: + content: + application/json: + schema: + $ref: "#/components/schemas/ItemsAndRefs" + responses: + 200: + description: Ok + content: + application/json: + schema: + $ref: "#/components/schemas/BasicResult" + put: tags: - Item (Multi Edit) diff --git a/modules/restserver/src/main/scala/docspell/restserver/routes/ItemMultiRoutes.scala b/modules/restserver/src/main/scala/docspell/restserver/routes/ItemMultiRoutes.scala index 3cb50f6e..7b1dd931 100644 --- a/modules/restserver/src/main/scala/docspell/restserver/routes/ItemMultiRoutes.scala +++ b/modules/restserver/src/main/scala/docspell/restserver/routes/ItemMultiRoutes.scala @@ -73,6 +73,18 @@ object ItemMultiRoutes { resp <- Ok(Conversions.basicResult(res, "Tags added.")) } yield resp + case req @ POST -> Root / "tagsremove" => + for { + json <- req.as[ItemsAndRefs] + items <- readIds[F](json.items) + res <- backend.item.removeTagsMultipleItems( + items, + json.refs, + user.account.collective + ) + resp <- Ok(Conversions.basicResult(res, "Tags removed")) + } yield resp + case req @ PUT -> Root / "name" => for { json <- req.as[ItemsAndName]