diff --git a/src/dotnet/APIView/APIView/Model/CodeFile.cs b/src/dotnet/APIView/APIView/Model/CodeFile.cs index 58a1a15bae6..d8f66ab21f7 100644 --- a/src/dotnet/APIView/APIView/Model/CodeFile.cs +++ b/src/dotnet/APIView/APIView/Model/CodeFile.cs @@ -17,6 +17,7 @@ public class CodeFile private static readonly JsonSerializer JsonSerializer = new JsonSerializer() { NullValueHandling = NullValueHandling.Ignore, + ReferenceLoopHandling = ReferenceLoopHandling.Ignore }; private string _versionString; diff --git a/src/dotnet/APIView/ClientSPA/src/app/_components/code-panel/code-panel.component.html b/src/dotnet/APIView/ClientSPA/src/app/_components/code-panel/code-panel.component.html index f5e04f2aa33..d793990fe3e 100644 --- a/src/dotnet/APIView/ClientSPA/src/app/_components/code-panel/code-panel.component.html +++ b/src/dotnet/APIView/ClientSPA/src/app/_components/code-panel/code-panel.component.html @@ -8,6 +8,7 @@
{{item.lineNumber}} +
diff --git a/src/dotnet/APIView/ClientSPA/src/app/_components/code-panel/code-panel.component.scss b/src/dotnet/APIView/ClientSPA/src/app/_components/code-panel/code-panel.component.scss index 5224942b504..fe2e81583d8 100644 --- a/src/dotnet/APIView/ClientSPA/src/app/_components/code-panel/code-panel.component.scss +++ b/src/dotnet/APIView/ClientSPA/src/app/_components/code-panel/code-panel.component.scss @@ -108,7 +108,22 @@ } } - .toggle-documentation-btn.show:hover { + .toggle-documentation-btn.can-show:hover { + color: inherit; + } + + .toggle-user-comments-btn { + color: transparent; + &.hide { + visibility: invisible; + } + + &.show { + color: inherit; + } + } + + .toggle-user-comments-btn.can-show:hover { color: inherit; } diff --git a/src/dotnet/APIView/ClientSPA/src/app/_components/review-page/review-page.component.ts b/src/dotnet/APIView/ClientSPA/src/app/_components/review-page/review-page.component.ts index 460ee5e1a40..799bc546f70 100644 --- a/src/dotnet/APIView/ClientSPA/src/app/_components/review-page/review-page.component.ts +++ b/src/dotnet/APIView/ClientSPA/src/app/_components/review-page/review-page.component.ts @@ -68,7 +68,8 @@ export class ReviewPageComponent implements OnInit { } else { this.otherCodePanelData.set(data.codePanelRowData.nodeId, { documentation: [data.codePanelRowData], - diagnostics: [] + diagnostics: [], + comments: [] }); } } else { @@ -82,12 +83,25 @@ export class ReviewPageComponent implements OnInit { } else { this.otherCodePanelData.set(data.codePanelRowData.nodeId, { documentation: [], - diagnostics: [data.codePanelRowData] + diagnostics: [data.codePanelRowData], + comments: [] }); } this.codeLinesDataBuffer.push(data.codePanelRowData); } + if (data.directive === ReviewPageWorkerMessageDirective.InsertCommentRowData) { + if (this.otherCodePanelData.has(data.codePanelRowData.nodeId)) { + this.otherCodePanelData.get(data.codePanelRowData.nodeId)?.comments.push(data.codePanelRowData); + } else { + this.otherCodePanelData.set(data.codePanelRowData.nodeId, { + documentation: [], + diagnostics: [], + comments: [data.codePanelRowData] + }); + } + } + if (data.directive === ReviewPageWorkerMessageDirective.UpdateCodeLines) { this.codeLinesData = this.codeLinesDataBuffer; } diff --git a/src/dotnet/APIView/ClientSPA/src/app/_models/revision.ts b/src/dotnet/APIView/ClientSPA/src/app/_models/revision.ts index e9910c11394..a0dc5215fad 100644 --- a/src/dotnet/APIView/ClientSPA/src/app/_models/revision.ts +++ b/src/dotnet/APIView/ClientSPA/src/app/_models/revision.ts @@ -1,10 +1,11 @@ -import { ChangeHistory, CodeDiagnostic } from "./review" +import { ChangeHistory, CodeDiagnostic, CommentItemModel } from "./review" export enum ReviewPageWorkerMessageDirective { CreatePageNavigation, InsertCodeLineData, UpdateCodeLines, - InsertDiagnosticsRowData + InsertDiagnosticsRowData, + InsertCommentRowData } export enum CodePanelRowDatatype { @@ -71,12 +72,15 @@ export interface CodePanelRowData { diffKind?: string rowSize: number toggleDocumentationClasses?: string + toggleCommentsClasses?: string diagnostics?: CodeDiagnostic + comments?: CommentItemModel[] } export interface CodePanelToggleableData { documentation: CodePanelRowData[] diagnostics: CodeDiagnostic[] + comments: CommentItemModel[] } export interface InsertCodePanelRowDataMessage { diff --git a/src/dotnet/APIView/ClientSPA/src/app/_workers/apitree-builder.worker.ts b/src/dotnet/APIView/ClientSPA/src/app/_workers/apitree-builder.worker.ts index 22ac3d3d51c..ad06c5bea56 100644 --- a/src/dotnet/APIView/ClientSPA/src/app/_workers/apitree-builder.worker.ts +++ b/src/dotnet/APIView/ClientSPA/src/app/_workers/apitree-builder.worker.ts @@ -1,12 +1,13 @@ /// import { ComputeTokenDiff } from "../_helpers/worker-helpers"; -import { CodeDiagnostic, CodePanelData } from "../_models/review"; +import { CodeDiagnostic, CodePanelData, CommentItemModel } from "../_models/review"; import { CodePanelRowData, CodePanelRowDatatype, InsertCodePanelRowDataMessage, ReviewPageWorkerMessageDirective, StructuredToken } from "../_models/revision"; import { APITreeNode } from "../_models/revision"; let insertLineNumber = 0; let diagnostics: CodeDiagnostic[] = []; +let comments: CommentItemModel[] = []; let diagnosticsTargetIds = new Set(); addEventListener('message', ({ data }) => { @@ -15,6 +16,7 @@ addEventListener('message', ({ data }) => { let reviewContent: CodePanelData = JSON.parse(jsonString); diagnostics = reviewContent.diagnostics; + comments = reviewContent.comments; diagnosticsTargetIds = new Set(diagnostics.map(diagnostic => diagnostic.targetId)); let navTreeNodes: any[] = []; @@ -37,6 +39,7 @@ addEventListener('message', ({ data }) => { postMessage(updateCodeLineDataMessage); diagnostics = []; + comments = []; diagnosticsTargetIds.clear(); } }); @@ -66,9 +69,9 @@ function buildAPITree(apiTreeNode: APITreeNode, treeNodeId : string[], indent: n } let children : any[] = []; - apiTreeNode.children.forEach(child => { + apiTreeNode.children.forEach((child : APITreeNode) => { const childTreeNodes = buildAPITree(child, treeNodeId, indent + 1); - if (child.children.length > 0) { + if (!Array.from(child.tags).includes("HideFromNavigation")) { children.push(childTreeNodes); } }); @@ -222,8 +225,10 @@ function buildTokensForNonDiffNodes(apiTreeNode: APITreeNode, id: string, positi const tokens = (position === "top") ? apiTreeNode.topTokens : apiTreeNode.bottomTokens; const tokenLine : StructuredToken[] = []; const lineClasses = new Set(); + const tokenIdsInLine = new Set(); let precedingRowData : CodePanelRowData | undefined = undefined; + for (let token of tokens) { if ("GroupId" in token.properties) { lineClasses.add(token.properties["GroupId"]); @@ -247,20 +252,34 @@ function buildTokensForNonDiffNodes(apiTreeNode: APITreeNode, id: string, positi insertLineNumber++; insertLineOfTokensMessage.codePanelRowData.lineNumber = insertLineNumber; lineHasDocumentationAbove(precedingRowData, insertLineOfTokensMessage.codePanelRowData) ? - insertLineOfTokensMessage.codePanelRowData.toggleDocumentationClasses = "bi bi-arrow-up-square show" : + insertLineOfTokensMessage.codePanelRowData.toggleDocumentationClasses = "bi bi-arrow-up-square can-show" : insertLineOfTokensMessage.codePanelRowData.toggleDocumentationClasses = "bi bi-arrow-up-square hide"; + + // Collects comments for the line + let insertCommentMessage : InsertCodePanelRowDataMessage | undefined = undefined; + collectUserCommentsforLine(tokenIdsInLine, nodeId, insertLineOfTokensMessage, insertCommentMessage); precedingRowData = insertLineOfTokensMessage.codePanelRowData; postMessage(insertLineOfTokensMessage); + // Push comments after pussing the line + if (insertCommentMessage) { + postMessage(insertCommentMessage); + } + tokenLine.length = 0; lineClasses.clear(); + tokenIdsInLine.clear(); } else { tokenLine.push(token); + if (token.id) { + tokenIdsInLine.add(token.id); + } } } + // Handle any remaining lines if (tokenLine.length > 0) { const insertLineOfTokensMessage : InsertCodePanelRowDataMessage = { directive: ReviewPageWorkerMessageDirective.InsertCodeLineData, @@ -279,10 +298,19 @@ function buildTokensForNonDiffNodes(apiTreeNode: APITreeNode, id: string, positi insertLineNumber++; insertLineOfTokensMessage.codePanelRowData.lineNumber = insertLineNumber; lineHasDocumentationAbove(precedingRowData, insertLineOfTokensMessage.codePanelRowData) ? - insertLineOfTokensMessage.codePanelRowData.toggleDocumentationClasses = "bi bi-arrow-up-square show" : + insertLineOfTokensMessage.codePanelRowData.toggleDocumentationClasses = "bi bi-arrow-up-square can-show" : insertLineOfTokensMessage.codePanelRowData.toggleDocumentationClasses = "bi bi-arrow-up-square hide"; + // Collects comments for the line + let insertCommentMessage : InsertCodePanelRowDataMessage | undefined = undefined; + collectUserCommentsforLine(tokenIdsInLine, nodeId, insertLineOfTokensMessage, insertCommentMessage); + postMessage(insertLineOfTokensMessage); + + // Push comments after pussing the line + if (insertCommentMessage) { + postMessage(insertCommentMessage); + } } // Append associated diagnostics rows @@ -312,3 +340,30 @@ function buildTokensForNonDiffNodes(apiTreeNode: APITreeNode, id: string, positi function lineHasDocumentationAbove(precedingLine : CodePanelRowData | undefined, currentLine : CodePanelRowData) : boolean { return precedingLine !== undefined && precedingLine.rowClasses.has("documentation") && !currentLine.rowClasses.has("documentation"); } + +function collectUserCommentsforLine(tokenIdsInLine: Set, nodeId: string, insertLineOfTokensMessage : InsertCodePanelRowDataMessage, + insertCommentMessage : InsertCodePanelRowDataMessage | undefined) { + if (tokenIdsInLine.size > 0) { + insertLineOfTokensMessage.codePanelRowData.toggleCommentsClasses = "bi bi-chat-right-text can-show"; + const commentsForLine = comments.filter(comment => tokenIdsInLine.has(comment.elementId)); + insertCommentMessage = { + directive: ReviewPageWorkerMessageDirective.InsertCommentRowData, + codePanelRowData: { + rowType: CodePanelRowDatatype.Comment, + nodeId: nodeId, + rowClasses: new Set(["user-comments"]), + comments: commentsForLine, + rowSize: 21 + } + }; + + if (commentsForLine.length > 0) { + insertLineOfTokensMessage.codePanelRowData.toggleCommentsClasses = "bi bi-chat-right-text show"; + } + } + else { + insertLineOfTokensMessage.codePanelRowData.toggleCommentsClasses = "bi bi-chat-right-text hide"; + } +} + +