diff -r 1ca4f27cefe8 -r b7f3e972b13c src/main/kotlin/de/uapcore/lightpit/servlet/FeedServlet.kt --- a/src/main/kotlin/de/uapcore/lightpit/servlet/FeedServlet.kt Sat Nov 27 12:12:20 2021 +0100 +++ b/src/main/kotlin/de/uapcore/lightpit/servlet/FeedServlet.kt Sat Nov 27 13:03:57 2021 +0100 @@ -30,8 +30,10 @@ import de.uapcore.lightpit.AbstractServlet import de.uapcore.lightpit.HttpRequest import de.uapcore.lightpit.dao.DataAccessObject -import de.uapcore.lightpit.entities.IssueHistoryData +import de.uapcore.lightpit.entities.IssueCommentHistoryEntry import de.uapcore.lightpit.entities.IssueHistoryEntry +import de.uapcore.lightpit.types.IssueHistoryType +import de.uapcore.lightpit.viewmodel.CommentDiff import de.uapcore.lightpit.viewmodel.IssueDiff import de.uapcore.lightpit.viewmodel.IssueFeed import de.uapcore.lightpit.viewmodel.IssueFeedEntry @@ -46,8 +48,36 @@ get("/%project/issues.rss", this::issues) } - private fun fullContent(issue: IssueHistoryData) = IssueDiff( - issue.id, + val diffGenerator by lazyOf(DiffRowGenerator.create() + .showInlineDiffs(true) + .mergeOriginalRevised(true) + .inlineDiffByWord(true) + .oldTag { start -> if (start) "" else "" } + .newTag { start -> if (start) "" else "" } + .build() + ) + + private fun fullContent(data: IssueCommentHistoryEntry) = + CommentDiff( + data.issueid, + data.commentid, + data.subject, + data.comment.replace("\r", "") + ) + + private fun diffContent(cur: IssueCommentHistoryEntry, next: IssueCommentHistoryEntry) = + CommentDiff( + cur.issueid, + cur.commentid, + cur.subject, + diffGenerator.generateDiffRows( + next.comment.replace("\r", "").split('\n'), + cur.comment.replace("\r", "").split('\n') + ).joinToString("\n", transform = DiffRow::getOldLine) + ) + + private fun fullContent(issue: IssueHistoryEntry) = IssueDiff( + issue.issueid, issue.subject, issue.component, issue.status.name, @@ -60,19 +90,10 @@ issue.resolved ) - private fun diffContent(cur: IssueHistoryData, next: IssueHistoryData): IssueDiff { - val generator = DiffRowGenerator.create() - .showInlineDiffs(true) - .mergeOriginalRevised(true) - .inlineDiffByWord(true) - .oldTag { start -> if (start) "" else "" } - .newTag { start -> if (start) "" else "" } - .build() - + private fun diffContent(cur: IssueHistoryEntry, next: IssueHistoryEntry): IssueDiff { val prev = fullContent(next) val diff = fullContent(cur) - - val result = generator.generateDiffRows( + val result = diffGenerator.generateDiffRows( listOf( prev.subject, prev.component, prev.status, prev.category, prev.assignee, prev.eta, prev.affected, prev.resolved @@ -92,7 +113,7 @@ diff.affected = result[6].oldLine diff.resolved = result[7].oldLine - diff.description = generator.generateDiffRows( + diff.description = diffGenerator.generateDiffRows( prev.description.split('\n'), diff.description.split('\n') ).joinToString("\n", transform = DiffRow::getOldLine) @@ -102,21 +123,42 @@ /** * Generates the feed entries. - * Assumes that [historyEntry] is already sorted by timestamp (descending). + * Assumes that [issueEntries] and [commentEntries] are already sorted by timestamp (descending). */ - private fun generateFeedEntries(historyEntry: List): List = - if (historyEntry.isEmpty()) { + private fun generateFeedEntries( + issueEntries: List, + commentEntries: List + ): List = + (generateIssueFeedEntries(issueEntries) + generateCommentFeedEntries(commentEntries)).sortedByDescending { it.time } + + private fun generateIssueFeedEntries(entries: List): List = + if (entries.isEmpty()) { emptyList() } else { - historyEntry.groupBy { it.data.id }.mapValues { (_, history) -> + entries.groupBy { it.issueid }.mapValues { (_, history) -> history.zipWithNext().map { (cur, next) -> IssueFeedEntry( - cur.time, cur.type, diffContent(cur.data, next.data) + cur.time, cur.type, issue = diffContent(cur, next) ) }.plus( - history.last().let { IssueFeedEntry(it.time, it.type, fullContent(it.data)) } + history.last().let { IssueFeedEntry(it.time, it.type, issue = fullContent(it)) } ) - }.flatMap { it.value }.sortedByDescending { it.time } + }.flatMap { it.value } + } + + private fun generateCommentFeedEntries(entries: List): List = + if (entries.isEmpty()) { + emptyList() + } else { + entries.groupBy { it.commentid }.mapValues { (_, history) -> + history.zipWithNext().map { (cur, next) -> + IssueFeedEntry( + cur.time, cur.type, comment = diffContent(cur, next) + ) + }.plus( + history.last().let { IssueFeedEntry(it.time, it.type, comment = fullContent(it)) } + ) + }.flatMap { it.value } } private fun issues(http: HttpRequest, dao: DataAccessObject) { @@ -126,6 +168,7 @@ return } val assignees = http.param("assignee")?.split(',') + val comments = http.param("comments") ?: "all" val days = http.param("days")?.toIntOrNull() ?: 30 @@ -133,9 +176,14 @@ val issueHistory = if (assignees == null) issuesFromDb else issuesFromDb.filter { assignees.contains(it.currentAssignee) } - // TODO: add comment history depending on parameter + val commentsFromDb = dao.listIssueCommentHistory(project.id, days) + val commentHistory = when (comments) { + "all" -> commentsFromDb + "new" -> commentsFromDb.filter { it.type == IssueHistoryType.NewComment } + else -> emptyList() + } - http.view = IssueFeed(project, generateFeedEntries(issueHistory)) + http.view = IssueFeed(project, generateFeedEntries(issueHistory, commentHistory)) http.renderFeed("issues-feed") } } \ No newline at end of file