Instead of client only, make bookmarks a server aware feature

Makes it much more useful
This commit is contained in:
eikek
2022-01-09 23:50:34 +01:00
parent 063ae56488
commit 9415f72ec0
19 changed files with 618 additions and 345 deletions

View File

@ -0,0 +1,12 @@
CREATE TABLE "query_bookmark" (
"id" varchar(254) not null primary key,
"name" varchar(254) not null,
"label" varchar(254),
"user_id" varchar(254),
"cid" varchar(254) not null,
"query" varchar(2000) not null,
"created" timestamp,
foreign key ("user_id") references "user_"("uid") on delete cascade,
foreign key ("cid") references "collective"("cid") on delete cascade,
unique("cid", "user_id", "name")
)

View File

@ -0,0 +1,12 @@
CREATE TABLE `query_bookmark` (
`id` varchar(254) not null primary key,
`name` varchar(254) not null,
`label` varchar(254),
`user_id` varchar(254),
`cid` varchar(254) not null,
`query` varchar(2000) not null,
`created` timestamp,
foreign key (`user_id`) references `user_`(`uid`) on delete cascade,
foreign key (`cid`) references `collective`(`cid`) on delete cascade,
unique(`cid`, `user_id`, `name`)
)

View File

@ -0,0 +1,12 @@
CREATE TABLE "query_bookmark" (
"id" varchar(254) not null primary key,
"name" varchar(254) not null,
"label" varchar(254),
"user_id" varchar(254),
"cid" varchar(254) not null,
"query" varchar(2000) not null,
"created" timestamp,
foreign key ("user_id") references "user_"("uid") on delete cascade,
foreign key ("cid") references "collective"("cid") on delete cascade,
unique("cid", "user_id", "name")
)

View File

@ -0,0 +1,108 @@
package docspell.store.records
import docspell.common._
import docspell.query.ItemQuery
import docspell.store.qb.DSL._
import docspell.store.qb._
import doobie._
import doobie.implicits._
import cats.data.NonEmptyList
import cats.syntax.option._
final case class RQueryBookmark(
id: Ident,
name: String,
label: Option[String],
userId: Option[Ident],
cid: Ident,
query: ItemQuery,
created: Timestamp
) {
def isPersonal: Boolean =
userId.isDefined
def asGlobal: RQueryBookmark =
copy(userId = None)
def asPersonal(userId: Ident): RQueryBookmark =
copy(userId = userId.some)
}
object RQueryBookmark {
final case class Table(alias: Option[String]) extends TableDef {
val tableName = "query_bookmark";
val id = Column[Ident]("id", this)
val name = Column[String]("name", this)
val label = Column[String]("label", this)
val userId = Column[Ident]("user_id", this)
val cid = Column[Ident]("cid", this)
val query = Column[ItemQuery]("query", this)
val created = Column[Timestamp]("created", this)
val all: NonEmptyList[Column[_]] =
NonEmptyList.of(id, name, label, userId, cid, query, created)
}
val T: Table = Table(None)
def as(alias: String): Table = Table(Some(alias))
def createNew(
account: AccountId,
name: String,
label: Option[String],
query: ItemQuery,
personal: Boolean
): ConnectionIO[RQueryBookmark] =
for {
userId <- RUser.getIdByAccount(account)
curTime <- Timestamp.current[ConnectionIO]
id <- Ident.randomId[ConnectionIO]
} yield RQueryBookmark(
id,
name,
label,
if (personal) userId.some else None,
account.collective,
query,
curTime
)
def insert(r: RQueryBookmark): ConnectionIO[Int] =
DML.insert(
T,
T.all,
sql"${r.id},${r.name},${r.label},${r.userId},${r.cid},${r.query},${r.created}"
)
def update(r: RQueryBookmark): ConnectionIO[Int] =
DML.update(
T,
T.id === r.id,
DML.set(
T.name.setTo(r.name),
T.label.setTo(r.label),
T.query.setTo(r.query)
)
)
def deleteById(cid: Ident, id: Ident): ConnectionIO[Int] =
DML.delete(T, T.id === id && T.cid === cid)
def allForUser(account: AccountId): ConnectionIO[Vector[RQueryBookmark]] = {
val user = RUser.as("u")
val bm = RQueryBookmark.as("bm")
val users = Select(
user.uid.s,
from(user),
user.cid === account.collective && user.login === account.user
)
Select(
select(bm.all),
from(bm),
bm.cid === account.collective && (bm.userId.isNull || bm.userId.in(users))
).build.query[RQueryBookmark].to[Vector]
}
}

View File

@ -14,6 +14,8 @@ import docspell.store.qb._
import doobie._
import doobie.implicits._
import cats.data.OptionT
import cats.effect.Sync
case class RUser(
uid: Ident,
@ -150,6 +152,13 @@ object RUser {
.query[Ident]
.option
def getIdByAccount(account: AccountId): ConnectionIO[Ident] =
OptionT(findIdByAccount(account)).getOrElseF(
Sync[ConnectionIO].raiseError(
new Exception(s"No user found for: ${account.asString}")
)
)
def updateLogin(accountId: AccountId): ConnectionIO[Int] = {
val t = Table(None)
def stmt(now: Timestamp) =