mirror of
https://github.com/TheAnachronism/docspell.git
synced 2025-06-22 02:18:26 +00:00
Merge pull request #1037 from eikek/small-list-improvements
Allow to specify ordering when retrieving meta data
This commit is contained in:
@ -12,6 +12,7 @@ case class Column[A](name: String, table: TableDef) {
|
||||
|
||||
def cast[B]: Column[B] =
|
||||
this.asInstanceOf[Column[B]]
|
||||
|
||||
}
|
||||
|
||||
object Column {}
|
||||
|
@ -303,6 +303,12 @@ trait DSL extends DoobieMeta {
|
||||
def as(otherCol: Column[_]): SelectExpr =
|
||||
SelectExpr.SelectFun(dbf, Some(otherCol.name))
|
||||
|
||||
def asc: OrderBy =
|
||||
OrderBy(SelectExpr.SelectFun(dbf, None), OrderBy.OrderType.Asc)
|
||||
|
||||
def desc: OrderBy =
|
||||
OrderBy(SelectExpr.SelectFun(dbf, None), OrderBy.OrderType.Desc)
|
||||
|
||||
def ===[A](value: A)(implicit P: Put[A]): Condition =
|
||||
Condition.CompareFVal(dbf.s, Operator.Eq, value)
|
||||
|
||||
|
@ -135,6 +135,9 @@ object Select {
|
||||
|
||||
def orderBy(ob: OrderBy, obs: OrderBy*): Ordered =
|
||||
Ordered(this, ob, obs.toVector)
|
||||
|
||||
def orderBy(ob: Nel[OrderBy]): Ordered =
|
||||
Ordered(this, ob.head, ob.tail.toVector)
|
||||
}
|
||||
|
||||
case class RawSelect(fragment: Fragment) extends Select {
|
||||
|
@ -24,9 +24,10 @@ object QCustomField {
|
||||
|
||||
def findAllLike(
|
||||
coll: Ident,
|
||||
nameQuery: Option[String]
|
||||
nameQuery: Option[String],
|
||||
order: RCustomField.Table => Nel[OrderBy]
|
||||
): ConnectionIO[Vector[CustomFieldData]] =
|
||||
findFragment(coll, nameQuery, None).build.query[CustomFieldData].to[Vector]
|
||||
findFragment(coll, nameQuery, None, order).build.query[CustomFieldData].to[Vector]
|
||||
|
||||
def findById(field: Ident, collective: Ident): ConnectionIO[Option[CustomFieldData]] =
|
||||
findFragment(collective, None, field.some).build.query[CustomFieldData].option
|
||||
@ -34,7 +35,8 @@ object QCustomField {
|
||||
private def findFragment(
|
||||
coll: Ident,
|
||||
nameQuery: Option[String],
|
||||
fieldId: Option[Ident]
|
||||
fieldId: Option[Ident],
|
||||
order: RCustomField.Table => Nel[OrderBy] = t => Nel.of(t.name.asc)
|
||||
): Select = {
|
||||
val nameFilter = nameQuery.map { q =>
|
||||
f.name.likes(q) || (f.label.isNotNull && f.label.like(q))
|
||||
@ -46,7 +48,7 @@ object QCustomField {
|
||||
.leftJoin(v, f.id === v.field),
|
||||
f.cid === coll &&? nameFilter &&? fieldId.map(fid => f.id === fid),
|
||||
GroupBy(f.all)
|
||||
)
|
||||
).orderBy(order(f))
|
||||
}
|
||||
|
||||
final case class FieldValue(
|
||||
|
@ -7,6 +7,7 @@
|
||||
package docspell.store.queries
|
||||
|
||||
import cats.data.OptionT
|
||||
import cats.data.{NonEmptyList => Nel}
|
||||
import cats.implicits._
|
||||
|
||||
import docspell.common._
|
||||
@ -156,8 +157,11 @@ object QFolder {
|
||||
).query[IdRef].to[Vector]
|
||||
|
||||
(for {
|
||||
folder <- OptionT(findAll(account, Some(id), None, None).map(_.headOption))
|
||||
memb <- OptionT.liftF(memberQ)
|
||||
folder <- OptionT(
|
||||
findAll(account, Some(id), None, None, (ft, _) => Nel.of(ft.name.asc))
|
||||
.map(_.headOption)
|
||||
)
|
||||
memb <- OptionT.liftF(memberQ)
|
||||
} yield folder.withMembers(memb.toList)).value
|
||||
}
|
||||
|
||||
@ -165,7 +169,8 @@ object QFolder {
|
||||
account: AccountId,
|
||||
idQ: Option[Ident],
|
||||
ownerLogin: Option[Ident],
|
||||
nameQ: Option[String]
|
||||
nameQ: Option[String],
|
||||
order: (RFolder.Table, RUser.Table) => Nel[OrderBy]
|
||||
): ConnectionIO[Vector[FolderItem]] = {
|
||||
// with memberlogin as
|
||||
// (select m.folder_id,u.login
|
||||
@ -239,7 +244,7 @@ object QFolder {
|
||||
nameQ.map(q => folder.name.like(s"%${q.toLowerCase}%")) &&?
|
||||
ownerLogin.map(login => user.login === login)
|
||||
)
|
||||
).orderBy(folder.name.asc)
|
||||
).orderBy(order(folder, user))
|
||||
).build.query[FolderItem].to[Vector]
|
||||
}
|
||||
|
||||
|
@ -6,7 +6,7 @@
|
||||
|
||||
package docspell.store.queries
|
||||
|
||||
import cats.data.NonEmptyList
|
||||
import cats.data.{NonEmptyList => Nel}
|
||||
import cats.implicits._
|
||||
import fs2._
|
||||
|
||||
@ -27,7 +27,7 @@ object QOrganization {
|
||||
def findOrgAndContact(
|
||||
coll: Ident,
|
||||
query: Option[String],
|
||||
order: ROrganization.Table => Column[_]
|
||||
order: ROrganization.Table => Nel[OrderBy]
|
||||
): Stream[ConnectionIO, (ROrganization, Vector[RContact])] = {
|
||||
val valFilter = query.map { q =>
|
||||
val v = s"%$q%"
|
||||
@ -74,18 +74,18 @@ object QOrganization {
|
||||
def findPersonAndContact(
|
||||
coll: Ident,
|
||||
query: Option[String],
|
||||
order: RPerson.Table => Column[_]
|
||||
order: (RPerson.Table, ROrganization.Table) => Nel[OrderBy]
|
||||
): Stream[ConnectionIO, (RPerson, Option[ROrganization], Vector[RContact])] = {
|
||||
val valFilter = query
|
||||
.map(s => s"%$s%")
|
||||
.map(v => c.value.like(v) || p.name.like(v) || p.notes.like(v))
|
||||
.map(v => c.value.like(v) || p.name.like(v) || org.name.like(v) || p.notes.like(v))
|
||||
val sql = Select(
|
||||
select(p.all, org.all, c.all),
|
||||
from(p)
|
||||
.leftJoin(org, org.oid === p.oid)
|
||||
.leftJoin(c, c.personId === p.pid),
|
||||
p.cid === coll &&? valFilter
|
||||
).orderBy(order(p))
|
||||
).orderBy(order(p, org))
|
||||
|
||||
sql.build
|
||||
.query[(RPerson, Option[ROrganization], Option[RContact])]
|
||||
@ -128,7 +128,7 @@ object QOrganization {
|
||||
coll: Ident,
|
||||
value: String,
|
||||
ck: Option[ContactKind],
|
||||
use: Option[NonEmptyList[PersonUse]]
|
||||
use: Option[Nel[PersonUse]]
|
||||
): Stream[ConnectionIO, RPerson] =
|
||||
runDistinct(
|
||||
select(p.all),
|
||||
|
@ -87,7 +87,7 @@ object REquipment {
|
||||
def findAll(
|
||||
coll: Ident,
|
||||
nameQ: Option[String],
|
||||
order: Table => Column[_]
|
||||
order: Table => NonEmptyList[OrderBy]
|
||||
): ConnectionIO[Vector[REquipment]] = {
|
||||
val t = Table(None)
|
||||
|
||||
|
@ -7,7 +7,7 @@
|
||||
package docspell.store.records
|
||||
|
||||
import cats.Eq
|
||||
import cats.data.NonEmptyList
|
||||
import cats.data.{NonEmptyList => Nel}
|
||||
import fs2.Stream
|
||||
|
||||
import docspell.common.{IdRef, _}
|
||||
@ -52,7 +52,7 @@ object ROrganization {
|
||||
val shortName = Column[String]("short_name", this)
|
||||
val use = Column[OrgUse]("org_use", this)
|
||||
val all =
|
||||
NonEmptyList.of[Column[_]](
|
||||
Nel.of[Column[_]](
|
||||
oid,
|
||||
cid,
|
||||
name,
|
||||
@ -122,7 +122,7 @@ object ROrganization {
|
||||
def findLike(
|
||||
coll: Ident,
|
||||
orgName: String,
|
||||
use: NonEmptyList[OrgUse]
|
||||
use: Nel[OrgUse]
|
||||
): ConnectionIO[Vector[IdRef]] =
|
||||
run(
|
||||
select(T.oid, T.name),
|
||||
@ -163,7 +163,7 @@ object ROrganization {
|
||||
def findAllRef(
|
||||
coll: Ident,
|
||||
nameQ: Option[String],
|
||||
order: Table => Column[_]
|
||||
order: Table => Nel[OrderBy]
|
||||
): ConnectionIO[Vector[IdRef]] = {
|
||||
val nameFilter = nameQ.map(s =>
|
||||
T.name.like(s"%${s.toLowerCase}%") || T.shortName.like(s"%${s.toLowerCase}%")
|
||||
|
@ -7,7 +7,7 @@
|
||||
package docspell.store.records
|
||||
|
||||
import cats.Eq
|
||||
import cats.data.NonEmptyList
|
||||
import cats.data.{NonEmptyList => Nel}
|
||||
import cats.effect._
|
||||
import fs2.Stream
|
||||
|
||||
@ -52,7 +52,7 @@ object RPerson {
|
||||
val updated = Column[Timestamp]("updated", this)
|
||||
val oid = Column[Ident]("oid", this)
|
||||
val use = Column[PersonUse]("person_use", this)
|
||||
val all = NonEmptyList.of[Column[_]](
|
||||
val all = Nel.of[Column[_]](
|
||||
pid,
|
||||
cid,
|
||||
name,
|
||||
@ -122,7 +122,7 @@ object RPerson {
|
||||
def findLike(
|
||||
coll: Ident,
|
||||
personName: String,
|
||||
use: NonEmptyList[PersonUse]
|
||||
use: Nel[PersonUse]
|
||||
): ConnectionIO[Vector[IdRef]] =
|
||||
run(
|
||||
select(T.pid, T.name),
|
||||
@ -134,7 +134,7 @@ object RPerson {
|
||||
coll: Ident,
|
||||
contactKind: ContactKind,
|
||||
value: String,
|
||||
use: NonEmptyList[PersonUse]
|
||||
use: Nel[PersonUse]
|
||||
): ConnectionIO[Vector[IdRef]] = {
|
||||
val p = RPerson.as("p")
|
||||
val c = RContact.as("c")
|
||||
@ -162,7 +162,7 @@ object RPerson {
|
||||
def findAllRef(
|
||||
coll: Ident,
|
||||
nameQ: Option[String],
|
||||
order: Table => Column[_]
|
||||
order: Table => Nel[OrderBy]
|
||||
): ConnectionIO[Vector[IdRef]] = {
|
||||
|
||||
val nameFilter = nameQ.map(s => T.name.like(s"%${s.toLowerCase}%"))
|
||||
@ -176,7 +176,7 @@ object RPerson {
|
||||
DML.delete(T, T.pid === personId && T.cid === coll)
|
||||
|
||||
def findOrganization(ids: Set[Ident]): ConnectionIO[Vector[PersonRef]] =
|
||||
NonEmptyList.fromList(ids.toList) match {
|
||||
Nel.fromList(ids.toList) match {
|
||||
case Some(nel) =>
|
||||
run(select(T.pid, T.name, T.oid), from(T), T.pid.in(nel))
|
||||
.query[PersonRef]
|
||||
|
@ -75,10 +75,11 @@ object RTag {
|
||||
|
||||
def findAll(
|
||||
coll: Ident,
|
||||
nameQ: Option[String],
|
||||
order: Table => Column[_]
|
||||
query: Option[String],
|
||||
order: Table => NonEmptyList[OrderBy]
|
||||
): ConnectionIO[Vector[RTag]] = {
|
||||
val nameFilter = nameQ.map(s => T.name.like(s"%${s.toLowerCase}%"))
|
||||
val nameFilter =
|
||||
query.map(_.toLowerCase).map(s => T.name.like(s"%$s%") || T.category.like(s"%$s%"))
|
||||
val sql =
|
||||
Select(select(T.all), from(T), T.cid === coll &&? nameFilter).orderBy(order(T))
|
||||
sql.build.query[RTag].to[Vector]
|
||||
|
Reference in New Issue
Block a user