mirror of
https://github.com/TheAnachronism/docspell.git
synced 2025-06-21 18:08:25 +00:00
Transport highlighting information to the client
This commit is contained in:
@ -91,7 +91,7 @@ docspell.server {
|
||||
# memory and disk space. It can be enabled later any time.
|
||||
#
|
||||
# Currently the SOLR search platform is supported.
|
||||
enabled = true
|
||||
enabled = false
|
||||
|
||||
# When re-creating the complete index via a REST call, this key
|
||||
# is required. If left empty (the default), recreating the index
|
||||
@ -103,7 +103,7 @@ docspell.server {
|
||||
|
||||
# Configuration for the SOLR backend.
|
||||
solr = {
|
||||
url = "http://localhost:8983/solr/docspell_core"
|
||||
url = "http://localhost:8983/solr/docspell"
|
||||
commit-within = 1000
|
||||
}
|
||||
}
|
||||
|
@ -14,8 +14,9 @@ import bitpeace.FileMeta
|
||||
import docspell.backend.ops.OCollective.{InsightData, PassChangeResult}
|
||||
import docspell.backend.ops.OJob.JobCancelResult
|
||||
import docspell.backend.ops.OUpload.{UploadData, UploadMeta, UploadResult}
|
||||
import docspell.backend.ops.{OItemSearch, OJob, OOrganization, OUpload}
|
||||
import docspell.backend.ops.{OFulltext, OItemSearch, OJob, OOrganization, OUpload}
|
||||
import docspell.store.AddResult
|
||||
import docspell.ftsclient.FtsResult
|
||||
import org.http4s.multipart.Multipart
|
||||
import org.http4s.headers.`Content-Type`
|
||||
import org.log4s.Logger
|
||||
@ -139,6 +140,17 @@ trait Conversions {
|
||||
ItemLightList(gs)
|
||||
}
|
||||
|
||||
def mkItemListFts(v: Vector[OFulltext.FtsItem]): ItemLightList = {
|
||||
val groups = v.groupBy(item => item.item.date.toUtcDate.toString.substring(0, 7))
|
||||
|
||||
def mkGroup(g: (String, Vector[OFulltext.FtsItem])): ItemLightGroup =
|
||||
ItemLightGroup(g._1, g._2.map(mkItemLight).toList)
|
||||
|
||||
val gs =
|
||||
groups.map(mkGroup _).toList.sortWith((g1, g2) => g1.name.compareTo(g2.name) >= 0)
|
||||
ItemLightList(gs)
|
||||
}
|
||||
|
||||
def mkItemListWithTags(v: Vector[OItemSearch.ListItemWithTags]): ItemLightList = {
|
||||
val groups = v.groupBy(ti => ti.item.date.toUtcDate.toString.substring(0, 7))
|
||||
|
||||
@ -150,6 +162,17 @@ trait Conversions {
|
||||
ItemLightList(gs)
|
||||
}
|
||||
|
||||
def mkItemListWithTagsFts(v: Vector[OFulltext.FtsItemWithTags]): ItemLightList = {
|
||||
val groups = v.groupBy(ti => ti.item.item.date.toUtcDate.toString.substring(0, 7))
|
||||
|
||||
def mkGroup(g: (String, Vector[OFulltext.FtsItemWithTags])): ItemLightGroup =
|
||||
ItemLightGroup(g._1, g._2.map(mkItemLightWithTags).toList)
|
||||
|
||||
val gs =
|
||||
groups.map(mkGroup _).toList.sortWith((g1, g2) => g1.name.compareTo(g2.name) >= 0)
|
||||
ItemLightList(gs)
|
||||
}
|
||||
|
||||
def mkItemLight(i: OItemSearch.ListItem): ItemLight =
|
||||
ItemLight(
|
||||
i.id,
|
||||
@ -164,12 +187,35 @@ trait Conversions {
|
||||
i.concPerson.map(mkIdName),
|
||||
i.concEquip.map(mkIdName),
|
||||
i.fileCount,
|
||||
Nil,
|
||||
Nil
|
||||
)
|
||||
|
||||
def mkItemLight(i: OFulltext.FtsItem): ItemLight = {
|
||||
val il = mkItemLight(i.item)
|
||||
val highlight = mkHighlight(i.ftsData)
|
||||
il.copy(highlighting = highlight)
|
||||
}
|
||||
|
||||
def mkItemLightWithTags(i: OItemSearch.ListItemWithTags): ItemLight =
|
||||
mkItemLight(i.item).copy(tags = i.tags.map(mkTag))
|
||||
|
||||
def mkItemLightWithTags(i: OFulltext.FtsItemWithTags): ItemLight = {
|
||||
val il = mkItemLightWithTags(i.item)
|
||||
val highlight = mkHighlight(i.ftsData)
|
||||
il.copy(highlighting = highlight)
|
||||
}
|
||||
|
||||
private def mkHighlight(ftsData: OFulltext.FtsData): List[HighlightEntry] =
|
||||
ftsData.items.filter(_.context.nonEmpty).sortBy(-_.score).map { fdi =>
|
||||
fdi.matchData match {
|
||||
case FtsResult.AttachmentData(_, aName) =>
|
||||
HighlightEntry(aName, fdi.context)
|
||||
case FtsResult.ItemData =>
|
||||
HighlightEntry("Item", fdi.context)
|
||||
}
|
||||
}
|
||||
|
||||
// job
|
||||
def mkJobQueueState(state: OJob.CollectiveQueueState): JobQueueState = {
|
||||
def desc(f: JobDetail => Option[Timestamp])(j1: JobDetail, j2: JobDetail): Boolean = {
|
||||
|
@ -5,6 +5,7 @@ import cats.implicits._
|
||||
import docspell.backend.BackendApp
|
||||
import docspell.backend.auth.AuthToken
|
||||
import docspell.backend.ops.OItemSearch.Batch
|
||||
import docspell.backend.ops.OFulltext
|
||||
import docspell.common.{Ident, ItemState}
|
||||
import org.http4s.HttpRoutes
|
||||
import org.http4s.dsl.Http4sDsl
|
||||
@ -34,11 +35,25 @@ object ItemRoutes {
|
||||
_ <- logger.ftrace(s"Got search mask: $mask")
|
||||
query = Conversions.mkQuery(mask, user.account.collective)
|
||||
_ <- logger.ftrace(s"Running query: $query")
|
||||
items <- backend.itemSearch.findItems(
|
||||
query,
|
||||
Batch(mask.offset, mask.limit).restrictLimitTo(cfg.maxItemPageSize)
|
||||
)
|
||||
resp <- Ok(Conversions.mkItemList(items))
|
||||
resp <- mask.fullText match {
|
||||
case Some(fq) if cfg.fullTextSearch.enabled =>
|
||||
for {
|
||||
items <- backend.fulltext.findItems(
|
||||
query,
|
||||
OFulltext.FtsInput(fq),
|
||||
Batch(mask.offset, mask.limit).restrictLimitTo(cfg.maxItemPageSize)
|
||||
)
|
||||
ok <- Ok(Conversions.mkItemListFts(items))
|
||||
} yield ok
|
||||
case _ =>
|
||||
for {
|
||||
items <- backend.itemSearch.findItems(
|
||||
query,
|
||||
Batch(mask.offset, mask.limit).restrictLimitTo(cfg.maxItemPageSize)
|
||||
)
|
||||
ok <- Ok(Conversions.mkItemList(items))
|
||||
} yield ok
|
||||
}
|
||||
} yield resp
|
||||
|
||||
case req @ POST -> Root / "searchWithTags" =>
|
||||
@ -47,20 +62,25 @@ object ItemRoutes {
|
||||
_ <- logger.ftrace(s"Got search mask: $mask")
|
||||
query = Conversions.mkQuery(mask, user.account.collective)
|
||||
_ <- logger.ftrace(s"Running query: $query")
|
||||
items <- mask.fullText match {
|
||||
case None =>
|
||||
backend.itemSearch.findItemsWithTags(
|
||||
query,
|
||||
Batch(mask.offset, mask.limit).restrictLimitTo(cfg.maxItemPageSize)
|
||||
)
|
||||
case Some(fq) =>
|
||||
backend.fulltext.findItemsWithTags(
|
||||
query,
|
||||
fq,
|
||||
Batch(mask.offset, mask.limit).restrictLimitTo(cfg.maxItemPageSize)
|
||||
)
|
||||
resp <- mask.fullText match {
|
||||
case Some(fq) if cfg.fullTextSearch.enabled =>
|
||||
for {
|
||||
items <- backend.fulltext.findItemsWithTags(
|
||||
query,
|
||||
OFulltext.FtsInput(fq),
|
||||
Batch(mask.offset, mask.limit).restrictLimitTo(cfg.maxItemPageSize)
|
||||
)
|
||||
ok <- Ok(Conversions.mkItemListWithTagsFts(items))
|
||||
} yield ok
|
||||
case _ =>
|
||||
for {
|
||||
items <- backend.itemSearch.findItemsWithTags(
|
||||
query,
|
||||
Batch(mask.offset, mask.limit).restrictLimitTo(cfg.maxItemPageSize)
|
||||
)
|
||||
ok <- Ok(Conversions.mkItemListWithTags(items))
|
||||
} yield ok
|
||||
}
|
||||
resp <- Ok(Conversions.mkItemListWithTags(items))
|
||||
} yield resp
|
||||
|
||||
case GET -> Root / Ident(id) =>
|
||||
|
Reference in New Issue
Block a user