Re-enable the graphql type pres_annotation_history_curr
to receive all annotations as incremental diff.
It will make the whiteboard more consistent and easier to merge the data.
This commit is contained in:
parent
c79637f21b
commit
60c15006f2
@ -4,7 +4,7 @@ import scala.collection.immutable.HashMap
|
||||
import org.bigbluebutton.common2.msgs.AnnotationVO
|
||||
import org.bigbluebutton.core.apps.whiteboard.Whiteboard
|
||||
import org.bigbluebutton.SystemConfiguration
|
||||
import org.bigbluebutton.core.db.{ PresAnnotationDAO, PresPageWritersDAO }
|
||||
import org.bigbluebutton.core.db.{ PresAnnotationDAO, PresAnnotationHistoryDAO, PresPageWritersDAO }
|
||||
|
||||
class WhiteboardModel extends SystemConfiguration {
|
||||
private var _whiteboards = new HashMap[String, Whiteboard]()
|
||||
@ -85,7 +85,9 @@ class WhiteboardModel extends SystemConfiguration {
|
||||
}
|
||||
}
|
||||
|
||||
PresAnnotationDAO.insertOrUpdateMap(meetingId, annotationsAdded)
|
||||
val annotationUpdatedAt = System.currentTimeMillis()
|
||||
PresAnnotationHistoryDAO.insertOrUpdateMap(meetingId, annotationsDiffAdded, annotationUpdatedAt)
|
||||
PresAnnotationDAO.insertOrUpdateMap(meetingId, annotationsAdded, annotationUpdatedAt)
|
||||
|
||||
val newWb = wb.copy(annotationsMap = newAnnotationsMap)
|
||||
saveWhiteboard(newWb)
|
||||
@ -154,7 +156,9 @@ class WhiteboardModel extends SystemConfiguration {
|
||||
val updatedWb = wb.copy(annotationsMap = newAnnotationsMap)
|
||||
saveWhiteboard(updatedWb)
|
||||
|
||||
PresAnnotationDAO.delete(meetingId, userId, annotationsIdsRemoved)
|
||||
val annotationUpdatedAt = System.currentTimeMillis()
|
||||
PresAnnotationHistoryDAO.deleteAnnotations(meetingId, wb.id, userId, annotationsIdsRemoved, annotationUpdatedAt)
|
||||
PresAnnotationDAO.deleteAnnotations(meetingId, userId, annotationsIdsRemoved, annotationUpdatedAt)
|
||||
|
||||
annotationsIdsRemoved
|
||||
}
|
||||
|
@ -4,13 +4,12 @@ import org.bigbluebutton.common2.msgs.AnnotationVO
|
||||
import slick.jdbc.PostgresProfile.api._
|
||||
|
||||
case class PresAnnotationDbModel(
|
||||
annotationId: String,
|
||||
pageId: String,
|
||||
meetingId: String,
|
||||
userId: String,
|
||||
annotationInfo: String,
|
||||
lastHistorySequence: Int,
|
||||
lastUpdatedAt: java.sql.Timestamp = new java.sql.Timestamp(System.currentTimeMillis())
|
||||
annotationId: String,
|
||||
pageId: String,
|
||||
meetingId: String,
|
||||
userId: String,
|
||||
annotationInfo: String,
|
||||
lastUpdatedAt: java.sql.Timestamp = new java.sql.Timestamp(System.currentTimeMillis())
|
||||
)
|
||||
|
||||
class PresAnnotationDbTableDef(tag: Tag) extends Table[PresAnnotationDbModel](tag, None, "pres_annotation") {
|
||||
@ -19,38 +18,13 @@ class PresAnnotationDbTableDef(tag: Tag) extends Table[PresAnnotationDbModel](ta
|
||||
val meetingId = column[String]("meetingId")
|
||||
val userId = column[String]("userId")
|
||||
val annotationInfo = column[String]("annotationInfo")
|
||||
val lastHistorySequence = column[Int]("lastHistorySequence")
|
||||
val lastUpdatedAt = column[java.sql.Timestamp]("lastUpdatedAt")
|
||||
// def whiteboard = foreignKey("whiteboard_fk", whiteboardId, Whiteboards)(_.whiteboardId, onDelete = ForeignKeyAction.Cascade)
|
||||
def * = (annotationId, pageId, meetingId, userId, annotationInfo, lastHistorySequence, lastUpdatedAt) <> (PresAnnotationDbModel.tupled, PresAnnotationDbModel.unapply)
|
||||
def * = (annotationId, pageId, meetingId, userId, annotationInfo, lastUpdatedAt) <> (PresAnnotationDbModel.tupled, PresAnnotationDbModel.unapply)
|
||||
}
|
||||
|
||||
object PresAnnotationDAO {
|
||||
def insertOrUpdate(meetingId: String, annotation: AnnotationVO, annotationDiff: AnnotationVO) = {
|
||||
// //TODO do it via trigger?
|
||||
// PresAnnotationHistoryDAO.insert(meetingId, annotationDiff).onComplete {
|
||||
// case Success(sequence) => {
|
||||
// DatabaseConnection.logger.debug(s"Sequence generated to PresAnnotationHistory record: $sequence")
|
||||
//
|
||||
DatabaseConnection.enqueue(
|
||||
TableQuery[PresAnnotationDbTableDef].insertOrUpdate(
|
||||
PresAnnotationDbModel(
|
||||
annotationId = annotation.id,
|
||||
pageId = annotation.wbId,
|
||||
meetingId = meetingId,
|
||||
userId = annotation.userId,
|
||||
annotationInfo = JsonUtils.mapToJson(annotation.annotationInfo).compactPrint,
|
||||
lastHistorySequence = 0,
|
||||
lastUpdatedAt = new java.sql.Timestamp(System.currentTimeMillis())
|
||||
)
|
||||
)
|
||||
)
|
||||
|
||||
// }
|
||||
// case Failure(e) => DatabaseConnection.logger.error(s"Error inserting PresAnnotationHistory: $e")
|
||||
}
|
||||
|
||||
def prepareInsertOrUpdate(meetingId: String, annotation: AnnotationVO) = {
|
||||
def prepareInsertOrUpdate(meetingId: String, annotation: AnnotationVO, annotationUpdatedAt: Long) = {
|
||||
TableQuery[PresAnnotationDbTableDef].insertOrUpdate(
|
||||
PresAnnotationDbModel(
|
||||
annotationId = annotation.id,
|
||||
@ -58,38 +32,27 @@ object PresAnnotationDAO {
|
||||
meetingId = meetingId,
|
||||
userId = annotation.userId,
|
||||
annotationInfo = JsonUtils.mapToJson(annotation.annotationInfo).compactPrint,
|
||||
lastHistorySequence = 0,
|
||||
lastUpdatedAt = new java.sql.Timestamp(System.currentTimeMillis())
|
||||
lastUpdatedAt = new java.sql.Timestamp(annotationUpdatedAt)
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
def insertOrUpdateMap(meetingId: String, annotations: Array[AnnotationVO]) = {
|
||||
def insertOrUpdateMap(meetingId: String, annotations: Array[AnnotationVO], annotationUpdatedAt: Long) = {
|
||||
DatabaseConnection.enqueue(
|
||||
DBIO.sequence(
|
||||
annotations.map { annotation =>
|
||||
prepareInsertOrUpdate(meetingId, annotation)
|
||||
prepareInsertOrUpdate(meetingId, annotation, annotationUpdatedAt)
|
||||
}.toVector
|
||||
).transactionally
|
||||
)
|
||||
}
|
||||
|
||||
def delete(wbId: String, meetingId: String, userId: String, annotationId: String) = {
|
||||
// PresAnnotationHistoryDAO.delete(wbId, meetingId, userId, annotationId)
|
||||
DatabaseConnection.enqueue(
|
||||
TableQuery[PresAnnotationDbTableDef]
|
||||
.filter(_.annotationId === annotationId)
|
||||
.map(a => (a.annotationInfo, a.lastHistorySequence, a.meetingId, a.userId, a.lastUpdatedAt))
|
||||
.update("", 0, meetingId, userId, new java.sql.Timestamp(System.currentTimeMillis()))
|
||||
)
|
||||
}
|
||||
|
||||
def delete(meetingId: String, userId: String, annotationIds: Array[String]) = {
|
||||
def deleteAnnotations(meetingId: String, userId: String, annotationIds: Array[String], annotationUpdatedAt: Long) = {
|
||||
DatabaseConnection.enqueue(
|
||||
TableQuery[PresAnnotationDbTableDef]
|
||||
.filter(_.annotationId inSet annotationIds)
|
||||
.map(a => (a.annotationInfo, a.lastHistorySequence, a.meetingId, a.userId, a.lastUpdatedAt))
|
||||
.update("", 0, meetingId, userId, new java.sql.Timestamp(System.currentTimeMillis()))
|
||||
.map(a => (a.annotationInfo, a.meetingId, a.userId, a.lastUpdatedAt))
|
||||
.update("", meetingId, userId, new java.sql.Timestamp(annotationUpdatedAt))
|
||||
)
|
||||
}
|
||||
|
||||
|
@ -4,58 +4,85 @@ import org.bigbluebutton.common2.msgs.AnnotationVO
|
||||
import PostgresProfile.api._
|
||||
|
||||
case class PresAnnotationHistoryDbModel(
|
||||
sequence: Option[Int] = None,
|
||||
annotationId: String,
|
||||
pageId: String,
|
||||
meetingId: String,
|
||||
userId: String,
|
||||
annotationInfo: String
|
||||
// lastUpdatedAt: java.sql.Timestamp = new java.sql.Timestamp(System.currentTimeMillis())
|
||||
annotationInfo: String,
|
||||
updatedAt: java.sql.Timestamp
|
||||
)
|
||||
|
||||
class PresAnnotationHistoryDbTableDef(tag: Tag) extends Table[PresAnnotationHistoryDbModel](tag, None, "pres_annotation_history") {
|
||||
val sequence = column[Option[Int]]("sequence", O.PrimaryKey, O.AutoInc)
|
||||
val annotationId = column[String]("annotationId")
|
||||
val pageId = column[String]("pageId")
|
||||
val meetingId = column[String]("meetingId")
|
||||
val userId = column[String]("userId")
|
||||
val annotationInfo = column[String]("annotationInfo")
|
||||
// val lastUpdatedAt = column[java.sql.Timestamp]("lastUpdatedAt")
|
||||
// def whiteboard = foreignKey("whiteboard_fk", whiteboardId, Whiteboards)(_.whiteboardId, onDelete = ForeignKeyAction.Cascade)
|
||||
def * = (sequence, annotationId, pageId, meetingId, userId, annotationInfo) <> (PresAnnotationHistoryDbModel.tupled, PresAnnotationHistoryDbModel.unapply)
|
||||
val updatedAt = column[java.sql.Timestamp]("updatedAt")
|
||||
def * = (annotationId, pageId, meetingId, userId, annotationInfo, updatedAt) <> (PresAnnotationHistoryDbModel.tupled, PresAnnotationHistoryDbModel.unapply)
|
||||
}
|
||||
|
||||
object PresAnnotationHistoryDAO {
|
||||
|
||||
def insert(meetingId: String, annotationDiff: AnnotationVO) = {
|
||||
DatabaseConnection.db.run(
|
||||
//TODO not being used for now
|
||||
TableQuery[PresAnnotationHistoryDbTableDef].returning(
|
||||
TableQuery[PresAnnotationHistoryDbTableDef].map(_.sequence)
|
||||
) += PresAnnotationHistoryDbModel(
|
||||
None,
|
||||
annotationId = annotationDiff.id,
|
||||
pageId = annotationDiff.wbId,
|
||||
meetingId = meetingId,
|
||||
userId = annotationDiff.userId,
|
||||
annotationInfo = JsonUtils.mapToJson(annotationDiff.annotationInfo).compactPrint
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
def delete(wbId: String, meetingId: String, userId: String, annotationId: String) = {
|
||||
DatabaseConnection.db.run(
|
||||
//TODO not being used for now
|
||||
TableQuery[PresAnnotationHistoryDbTableDef].returning(
|
||||
TableQuery[PresAnnotationHistoryDbTableDef].map(_.sequence)
|
||||
) += PresAnnotationHistoryDbModel(
|
||||
None,
|
||||
def delete(wbId: String, meetingId: String, userId: String, annotationId: String, annotationUpdatedAt: Long) = {
|
||||
DatabaseConnection.enqueue(
|
||||
TableQuery[PresAnnotationHistoryDbTableDef].forceInsert(
|
||||
PresAnnotationHistoryDbModel(
|
||||
// None,
|
||||
annotationId = annotationId,
|
||||
pageId = wbId,
|
||||
meetingId = meetingId,
|
||||
userId = userId,
|
||||
annotationInfo = ""
|
||||
annotationInfo = "",
|
||||
updatedAt = new java.sql.Timestamp(annotationUpdatedAt)
|
||||
)
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
def prepareInsertOrUpdate(meetingId: String, annotation: AnnotationVO, annotationUpdatedAt: Long) = {
|
||||
TableQuery[PresAnnotationHistoryDbTableDef].forceInsert(
|
||||
PresAnnotationHistoryDbModel(
|
||||
annotationId = annotation.id,
|
||||
pageId = annotation.wbId,
|
||||
meetingId = meetingId,
|
||||
userId = annotation.userId,
|
||||
annotationInfo = JsonUtils.mapToJson(annotation.annotationInfo).compactPrint,
|
||||
updatedAt = new java.sql.Timestamp(annotationUpdatedAt)
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
def insertOrUpdateMap(meetingId: String, annotations: Array[AnnotationVO], annotationUpdatedAt: Long) = {
|
||||
DatabaseConnection.enqueue(
|
||||
DBIO.sequence(
|
||||
annotations.map { annotation =>
|
||||
prepareInsertOrUpdate(meetingId, annotation, annotationUpdatedAt)
|
||||
}.toVector
|
||||
).transactionally
|
||||
)
|
||||
}
|
||||
|
||||
def prepareDelete(meetingId: String, pageId: String, annotationId: String, userId: String, annotationUpdatedAt: Long) = {
|
||||
TableQuery[PresAnnotationHistoryDbTableDef].forceInsert(
|
||||
PresAnnotationHistoryDbModel(
|
||||
annotationId = annotationId,
|
||||
pageId = pageId,
|
||||
meetingId = meetingId,
|
||||
userId = userId,
|
||||
annotationInfo = "",
|
||||
updatedAt = new java.sql.Timestamp(annotationUpdatedAt)
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
def deleteAnnotations(meetingId: String, pageId: String, userId: String, annotations: Array[String], annotationUpdatedAt: Long) = {
|
||||
DatabaseConnection.enqueue(
|
||||
DBIO.sequence(
|
||||
annotations.map { annotationId =>
|
||||
prepareDelete(meetingId, pageId, annotationId, userId, annotationUpdatedAt)
|
||||
}.toVector
|
||||
).transactionally
|
||||
)
|
||||
}
|
||||
}
|
@ -1366,8 +1366,7 @@ CREATE TABLE "pres_annotation" (
|
||||
"meetingId" varchar(100),
|
||||
"userId" varchar(50),
|
||||
"annotationInfo" TEXT,
|
||||
"lastHistorySequence" integer,
|
||||
"lastUpdatedAt" timestamp with time zone DEFAULT now()
|
||||
"lastUpdatedAt" timestamp with time zone
|
||||
);
|
||||
CREATE INDEX "idx_pres_annotation_pageId" ON "pres_annotation"("pageId");
|
||||
CREATE INDEX "idx_pres_annotation_updatedAt" ON "pres_annotation"("pageId","lastUpdatedAt");
|
||||
@ -1379,25 +1378,30 @@ CREATE TABLE "pres_annotation_history" (
|
||||
"pageId" varchar(100) REFERENCES "pres_page"("pageId") ON DELETE CASCADE,
|
||||
"meetingId" varchar(100),
|
||||
"userId" varchar(50),
|
||||
"annotationInfo" TEXT
|
||||
-- "lastUpdatedAt" timestamp with time zone DEFAULT now()
|
||||
"annotationInfo" TEXT,
|
||||
"updatedAt" timestamp with time zone
|
||||
);
|
||||
CREATE INDEX "idx_pres_annotation_history_pageId" ON "pres_annotation"("pageId");
|
||||
create index "idx_pres_annotation_history_user_meeting" on "pres_annotation_history" ("userId", "meetingId");
|
||||
CREATE INDEX "idx_pres_annotation_history_updatedAt" ON "pres_annotation_history"("pageId", "updatedAt");
|
||||
|
||||
CREATE VIEW "v_pres_annotation_curr" AS
|
||||
SELECT p."meetingId", pp."presentationId", pa."annotationId", pa."pageId", pa."userId", pa."annotationInfo", pa."lastHistorySequence", pa."lastUpdatedAt"
|
||||
SELECT p."meetingId", pp."presentationId", pa."annotationId", pa."pageId", pa."userId", pa."annotationInfo",
|
||||
pa."lastUpdatedAt", "user"."isModerator" as "userIsModerator"
|
||||
FROM pres_presentation p
|
||||
JOIN pres_page pp ON pp."presentationId" = p."presentationId"
|
||||
JOIN pres_annotation pa ON pa."pageId" = pp."pageId"
|
||||
JOIN "user" on "user"."meetingId" = pa."meetingId" and "user"."userId" = pa."userId"
|
||||
WHERE p."current" IS true
|
||||
AND pp."current" IS true;
|
||||
|
||||
CREATE VIEW "v_pres_annotation_history_curr" AS
|
||||
SELECT p."meetingId", pp."presentationId", pah."pageId", pah."userId", pah."annotationId", pah."annotationInfo", pah."sequence"
|
||||
SELECT p."meetingId", pp."presentationId", pah."pageId", pah."userId", pah."annotationId", pah."annotationInfo",
|
||||
pah."updatedAt", "user"."isModerator" as "userIsModerator"
|
||||
FROM pres_presentation p
|
||||
JOIN pres_page pp ON pp."presentationId" = p."presentationId"
|
||||
JOIN pres_annotation_history pah ON pah."pageId" = pp."pageId"
|
||||
JOIN "user" on "user"."meetingId" = pah."meetingId" and "user"."userId" = pah."userId"
|
||||
WHERE p."current" IS true
|
||||
AND pp."current" IS true;
|
||||
|
||||
|
@ -24,7 +24,6 @@ select_permissions:
|
||||
- pageId
|
||||
- presentationId
|
||||
- userId
|
||||
- lastHistorySequence
|
||||
- annotationInfo
|
||||
- lastUpdatedAt
|
||||
filter:
|
||||
@ -32,9 +31,8 @@ select_permissions:
|
||||
- meetingId:
|
||||
_eq: X-Hasura-MeetingId
|
||||
- _or:
|
||||
- user:
|
||||
isModerator:
|
||||
_eq: true
|
||||
- userIsModerator:
|
||||
_eq: true
|
||||
- meetingId:
|
||||
_eq: X-Hasura-AnnotationsNotLockedInMeeting
|
||||
- userId:
|
||||
|
@ -24,16 +24,15 @@ select_permissions:
|
||||
- pageId
|
||||
- presentationId
|
||||
- userId
|
||||
- sequence
|
||||
- updatedAt
|
||||
- annotationInfo
|
||||
filter:
|
||||
_and:
|
||||
- meetingId:
|
||||
_eq: X-Hasura-MeetingId
|
||||
- _or:
|
||||
- user:
|
||||
isModerator:
|
||||
_eq: true
|
||||
- userIsModerator:
|
||||
_eq: true
|
||||
- meetingId:
|
||||
_eq: X-Hasura-AnnotationsNotLockedInMeeting
|
||||
- userId:
|
||||
|
Loading…
Reference in New Issue
Block a user