mirror of
https://github.com/yu-i-i/overleaf-cep.git
synced 2026-11-15 14:43:46 +01:00
Merge pull request #17910 from overleaf/em-comment-ids
Include id in history Comment instances GitOrigin-RevId: 25b897e8e9e8d7b19dfe2d90d7f0cafeb5e6e97f
This commit is contained in:
@@ -21,10 +21,12 @@ class Comment {
|
||||
resolved = false
|
||||
|
||||
/**
|
||||
* @param {string} id
|
||||
* @param {ReadonlyArray<Range>} ranges
|
||||
* @param {boolean} [resolved]
|
||||
*/
|
||||
constructor(ranges, resolved = false) {
|
||||
constructor(id, ranges, resolved = false) {
|
||||
this.id = id
|
||||
this.resolved = resolved
|
||||
this.ranges = this.mergeRanges(ranges)
|
||||
}
|
||||
@@ -87,7 +89,7 @@ class Comment {
|
||||
newRanges.push(new Range(cursor, length))
|
||||
}
|
||||
|
||||
return new Comment(newRanges, this.resolved)
|
||||
return new Comment(this.id, newRanges, this.resolved)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -108,7 +110,7 @@ class Comment {
|
||||
}
|
||||
}
|
||||
|
||||
return new Comment(newRanges, this.resolved)
|
||||
return new Comment(this.id, newRanges, this.resolved)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -148,6 +150,7 @@ class Comment {
|
||||
*/
|
||||
toRaw() {
|
||||
return {
|
||||
id: this.id,
|
||||
resolved: this.resolved,
|
||||
ranges: this.ranges.map(range => range.toRaw()),
|
||||
}
|
||||
@@ -189,6 +192,7 @@ class Comment {
|
||||
*/
|
||||
static fromRaw(rawComment) {
|
||||
return new Comment(
|
||||
rawComment.id,
|
||||
rawComment.ranges.map(range => Range.fromRaw(range)),
|
||||
rawComment.resolved
|
||||
)
|
||||
|
||||
@@ -15,6 +15,7 @@ const StringFileData = require('./file_data/string_file_data')
|
||||
* @typedef {import("./types").ReadonlyBlobStore} ReadonlyBlobStore
|
||||
* @typedef {import("./types").StringFileRawData} StringFileRawData
|
||||
* @typedef {import("./types").CommentRawData} CommentRawData
|
||||
* @typedef {import("./file_data/comment_list")} CommentList
|
||||
* @typedef {import("./operation/text_operation")} TextOperation
|
||||
* @typedef {{filterTrackedDeletes?: boolean}} FileGetContentOptions
|
||||
*/
|
||||
@@ -203,7 +204,7 @@ class File {
|
||||
/**
|
||||
* Get the comments for this file.
|
||||
*
|
||||
* @return {CommentRawData[]}
|
||||
* @return {CommentList}
|
||||
*/
|
||||
getComments() {
|
||||
return this.data.getComments()
|
||||
|
||||
@@ -2,28 +2,45 @@
|
||||
const Comment = require('../comment')
|
||||
|
||||
/**
|
||||
* @typedef {import("../types").CommentsListRawData} CommentsListRawData
|
||||
* @typedef {import("../types").CommentRawData} CommentRawData
|
||||
* @typedef {import("../range")} Range
|
||||
*/
|
||||
|
||||
class CommentList {
|
||||
/**
|
||||
* @param {Map<string, Comment>} comments
|
||||
* @param {Comment[]} comments
|
||||
*/
|
||||
constructor(comments) {
|
||||
this.comments = comments
|
||||
this.comments = new Map(comments.map(comment => [comment.id, comment]))
|
||||
}
|
||||
|
||||
/**
|
||||
* @returns {CommentsListRawData}
|
||||
* @returns {IterableIterator<Comment>}
|
||||
*/
|
||||
getComments() {
|
||||
return Array.from(this.comments).map(([commentId, comment]) => {
|
||||
return {
|
||||
id: commentId,
|
||||
...comment.toRaw(),
|
||||
}
|
||||
})
|
||||
[Symbol.iterator]() {
|
||||
return this.comments.values()
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the length of the comment list
|
||||
*
|
||||
* @returns {number}
|
||||
*/
|
||||
get length() {
|
||||
return this.comments.size
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the raw version of the comment list
|
||||
*
|
||||
* @returns {CommentRawData[]}
|
||||
*/
|
||||
toRaw() {
|
||||
const raw = []
|
||||
for (const comment of this.comments.values()) {
|
||||
raw.push(comment.toRaw())
|
||||
}
|
||||
return raw
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -35,11 +52,10 @@ class CommentList {
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string} id
|
||||
* @param {Comment} newComment
|
||||
*/
|
||||
add(id, newComment) {
|
||||
this.comments.set(id, newComment)
|
||||
add(newComment) {
|
||||
this.comments.set(newComment.id, newComment)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -50,14 +66,10 @@ class CommentList {
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {CommentsListRawData} rawComments
|
||||
* @param {CommentRawData[]} rawComments
|
||||
*/
|
||||
static fromRaw(rawComments) {
|
||||
const comments = new Map()
|
||||
for (const rawComment of rawComments) {
|
||||
comments.set(rawComment.id, Comment.fromRaw(rawComment))
|
||||
}
|
||||
return new CommentList(comments)
|
||||
return new CommentList(rawComments.map(Comment.fromRaw))
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
// @ts-check
|
||||
|
||||
'use strict'
|
||||
|
||||
const assert = require('check-types').assert
|
||||
@@ -17,6 +19,7 @@ let StringFileData = null
|
||||
* @typedef {import("../types").BlobStore} BlobStore
|
||||
* @typedef {import("../types").ReadonlyBlobStore} ReadonlyBlobStore
|
||||
* @typedef {import("../operation/edit_operation")} EditOperation
|
||||
* @typedef {import("../file_data/comment_list")} CommentList
|
||||
* @typedef {import("../types").CommentRawData} CommentRawData
|
||||
*/
|
||||
|
||||
@@ -190,7 +193,7 @@ class FileData {
|
||||
/**
|
||||
* @see File#getComments
|
||||
* @function
|
||||
* @return {CommentRawData[]}
|
||||
* @return {CommentList}
|
||||
* @abstract
|
||||
*/
|
||||
getComments() {
|
||||
|
||||
@@ -11,7 +11,7 @@ const TrackedChangeList = require('./tracked_change_list')
|
||||
* @typedef {import("../types").StringFileRawData} StringFileRawData
|
||||
* @typedef {import("../operation/edit_operation")} EditOperation
|
||||
* @typedef {import("../types").BlobStore} BlobStore
|
||||
* @typedef {import("../types").CommentsListRawData} CommentsListRawData
|
||||
* @typedef {import("../types").CommentRawData} CommentRawData
|
||||
* @typedef {import("../types").TrackedChangeRawData} TrackedChangeRawData
|
||||
* @typedef {import('../types').RangesBlob} RangesBlob
|
||||
*/
|
||||
@@ -19,7 +19,7 @@ const TrackedChangeList = require('./tracked_change_list')
|
||||
class StringFileData extends FileData {
|
||||
/**
|
||||
* @param {string} content
|
||||
* @param {CommentsListRawData} [rawComments]
|
||||
* @param {CommentRawData[]} [rawComments]
|
||||
* @param {TrackedChangeRawData[]} [rawTrackedChanges]
|
||||
*/
|
||||
constructor(content, rawComments = [], rawTrackedChanges = []) {
|
||||
@@ -49,9 +49,8 @@ class StringFileData extends FileData {
|
||||
toRaw() {
|
||||
const raw = { content: this.content }
|
||||
|
||||
const comments = this.getComments()
|
||||
if (comments.length) {
|
||||
raw.comments = comments
|
||||
if (this.comments.length) {
|
||||
raw.comments = this.comments.toRaw()
|
||||
}
|
||||
|
||||
if (this.trackedChanges.length) {
|
||||
@@ -110,7 +109,7 @@ class StringFileData extends FileData {
|
||||
|
||||
/** @inheritdoc */
|
||||
getComments() {
|
||||
return this.comments.getComments()
|
||||
return this.comments
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -135,7 +134,7 @@ class StringFileData extends FileData {
|
||||
if (this.comments.comments.size || this.trackedChanges.length) {
|
||||
/** @type {RangesBlob} */
|
||||
const ranges = {
|
||||
comments: this.getComments(),
|
||||
comments: this.getComments().toRaw(),
|
||||
trackedChanges: this.trackedChanges.toRaw(),
|
||||
}
|
||||
const rangesBlob = await blobStore.putObject(ranges)
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
// @ts-check
|
||||
const core = require('../../index')
|
||||
const Comment = require('../comment')
|
||||
const Range = require('../range')
|
||||
const EditOperation = require('./edit_operation')
|
||||
|
||||
/**
|
||||
@@ -16,12 +17,20 @@ const EditOperation = require('./edit_operation')
|
||||
class AddCommentOperation extends EditOperation {
|
||||
/**
|
||||
* @param {string} commentId
|
||||
* @param {Comment} comment
|
||||
* @param {ReadonlyArray<Range>} ranges
|
||||
* @param {boolean} resolved
|
||||
*/
|
||||
constructor(commentId, comment) {
|
||||
constructor(commentId, ranges, resolved = false) {
|
||||
super()
|
||||
|
||||
/** @readonly */
|
||||
this.commentId = commentId
|
||||
this.comment = comment
|
||||
|
||||
/** @readonly */
|
||||
this.ranges = ranges
|
||||
|
||||
/** @readonly */
|
||||
this.resolved = resolved
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -30,8 +39,9 @@ class AddCommentOperation extends EditOperation {
|
||||
*/
|
||||
toJSON() {
|
||||
return {
|
||||
...this.comment.toRaw(),
|
||||
commentId: this.commentId,
|
||||
ranges: this.ranges.map(range => range.toRaw()),
|
||||
resolved: this.resolved,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -39,7 +49,9 @@ class AddCommentOperation extends EditOperation {
|
||||
* @param {StringFileData} fileData
|
||||
*/
|
||||
apply(fileData) {
|
||||
fileData.comments.add(this.commentId, this.comment)
|
||||
fileData.comments.add(
|
||||
new Comment(this.commentId, this.ranges, this.resolved)
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -90,8 +102,11 @@ class AddCommentOperation extends EditOperation {
|
||||
other instanceof core.SetCommentStateOperation &&
|
||||
other.commentId === this.commentId
|
||||
) {
|
||||
const comment = new Comment(this.comment.ranges, other.resolved)
|
||||
return new AddCommentOperation(this.commentId, comment)
|
||||
return new AddCommentOperation(
|
||||
this.commentId,
|
||||
this.ranges,
|
||||
other.resolved
|
||||
)
|
||||
}
|
||||
|
||||
throw new Error(
|
||||
@@ -105,7 +120,11 @@ class AddCommentOperation extends EditOperation {
|
||||
* @returns {AddCommentOperation}
|
||||
*/
|
||||
static fromJSON(raw) {
|
||||
return new AddCommentOperation(raw.commentId, Comment.fromRaw(raw))
|
||||
return new AddCommentOperation(
|
||||
raw.commentId,
|
||||
raw.ranges.map(Range.fromRaw),
|
||||
raw.resolved ?? false
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -50,7 +50,11 @@ class DeleteCommentOperation extends EditOperation {
|
||||
return new EditNoOperation()
|
||||
}
|
||||
|
||||
return new core.AddCommentOperation(this.commentId, comment)
|
||||
return new core.AddCommentOperation(
|
||||
comment.id,
|
||||
comment.ranges.slice(),
|
||||
comment.resolved
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -29,8 +29,16 @@ class EditOperationTransformer {
|
||||
createTransformer(TextOperation, SetCommentStateOperation, noConflict),
|
||||
createTransformer(TextOperation, AddCommentOperation, (a, b) => {
|
||||
// apply the text operation to the comment
|
||||
const movedComment = b.comment.applyTextOperation(a, b.commentId)
|
||||
return [a, new AddCommentOperation(b.commentId, movedComment)]
|
||||
const originalComment = new Comment(b.commentId, b.ranges, b.resolved)
|
||||
const movedComment = originalComment.applyTextOperation(a, b.commentId)
|
||||
return [
|
||||
a,
|
||||
new AddCommentOperation(
|
||||
movedComment.id,
|
||||
movedComment.ranges,
|
||||
movedComment.resolved
|
||||
),
|
||||
]
|
||||
}),
|
||||
createTransformer(AddCommentOperation, AddCommentOperation, (a, b) => {
|
||||
if (a.commentId === b.commentId) {
|
||||
@@ -50,8 +58,11 @@ class EditOperationTransformer {
|
||||
SetCommentStateOperation,
|
||||
(a, b) => {
|
||||
if (a.commentId === b.commentId) {
|
||||
const mergedComment = new Comment(a.comment.ranges, b.resolved)
|
||||
const newA = new AddCommentOperation(a.commentId, mergedComment)
|
||||
const newA = new AddCommentOperation(
|
||||
a.commentId,
|
||||
a.ranges,
|
||||
b.resolved
|
||||
)
|
||||
return [newA, b]
|
||||
}
|
||||
return [a, b]
|
||||
|
||||
@@ -42,8 +42,8 @@ class SetCommentStateOperation extends EditOperation {
|
||||
apply(fileData) {
|
||||
const comment = fileData.comments.getComment(this.commentId)
|
||||
if (comment) {
|
||||
const newComment = new Comment(comment.ranges, this.resolved)
|
||||
fileData.comments.add(this.commentId, newComment)
|
||||
const newComment = new Comment(comment.id, comment.ranges, this.resolved)
|
||||
fileData.comments.add(newComment)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -11,7 +11,7 @@ export type BlobStore = {
|
||||
export type ReadonlyBlobStore = Pick<BlobStore, 'getString' | 'getObject'>
|
||||
|
||||
export type RangesBlob = {
|
||||
comments: CommentsListRawData
|
||||
comments: CommentRawData[]
|
||||
trackedChanges: TrackedChangeRawData[]
|
||||
}
|
||||
|
||||
@@ -21,6 +21,7 @@ type Range = {
|
||||
}
|
||||
|
||||
export type CommentRawData = {
|
||||
id: string
|
||||
ranges: Range[]
|
||||
resolved?: boolean
|
||||
}
|
||||
@@ -36,11 +37,9 @@ export type TrackingPropsRawData = {
|
||||
ts: string
|
||||
}
|
||||
|
||||
export type CommentsListRawData = Array<{ id: string } & CommentRawData>
|
||||
|
||||
export type StringFileRawData = {
|
||||
content: string
|
||||
comments?: CommentsListRawData
|
||||
comments?: CommentRawData[]
|
||||
trackedChanges?: TrackedChangeRawData[]
|
||||
}
|
||||
|
||||
@@ -69,11 +68,18 @@ export type RawTextOperation = {
|
||||
textOperation: RawScanOp[]
|
||||
}
|
||||
|
||||
export type RawAddCommentOperation = CommentRawData & { commentId: string }
|
||||
export type RawAddCommentOperation = {
|
||||
commentId: string
|
||||
ranges: Range[]
|
||||
resolved?: boolean
|
||||
}
|
||||
|
||||
export type RawDeleteCommentOperation = { deleteComment: string }
|
||||
|
||||
export type RawSetCommentStateOperation = { commentId: string; resolved: boolean }
|
||||
export type RawSetCommentStateOperation = {
|
||||
commentId: string
|
||||
resolved: boolean
|
||||
}
|
||||
|
||||
export type RawEditOperation =
|
||||
| RawTextOperation
|
||||
|
||||
Reference in New Issue
Block a user