Mon, 05 Aug 2024 19:38:47 +0200
fix removing filter not working
fixes #407
package de.uapcore.lightpit.logic import de.uapcore.lightpit.HttpRequest import de.uapcore.lightpit.dao.DataAccessObject import de.uapcore.lightpit.dateOptValidator import de.uapcore.lightpit.entities.Issue import de.uapcore.lightpit.entities.IssueComment import de.uapcore.lightpit.entities.IssueRelation import de.uapcore.lightpit.entities.Version import de.uapcore.lightpit.types.IssueCategory import de.uapcore.lightpit.types.IssueStatus import de.uapcore.lightpit.types.RelationType import de.uapcore.lightpit.viewmodel.IssueDetailView import de.uapcore.lightpit.viewmodel.PathInfos import de.uapcore.lightpit.viewmodel.PathInfosFull import de.uapcore.lightpit.viewmodel.projectNavMenu import java.sql.Date fun Issue.hasChanged(reference: Issue) = !(component == reference.component && status == reference.status && category == reference.category && subject == reference.subject && description == reference.description && assignee == reference.assignee && eta == reference.eta && affected == reference.affected && resolved == reference.resolved) fun Issue.compareEtaTo(date: Date?): Int { val eta = this.eta return if (eta == null && date == null) 0 else if (eta == null) 1 else if (date == null) -1 else eta.compareTo(date) } fun Issue.applyFormData(http: HttpRequest, dao: DataAccessObject): Issue = this.apply { component = dao.findComponent(http.param("component")?.toIntOrNull() ?: -1) category = IssueCategory.valueOf(http.param("category") ?: "") status = IssueStatus.valueOf(http.param("status") ?: "") subject = http.param("subject") ?: "" description = http.param("description") ?: "" assignee = http.param("assignee")?.toIntOrNull()?.let { when (it) { -1 -> null -2 -> (component?.lead ?: project.owner) else -> dao.findUser(it) } } // TODO: process error messages eta = http.param("eta", ::dateOptValidator, null, mutableListOf()) affected = http.param("affected")?.toIntOrNull()?.takeIf { it > 0 }?.let { Version(it, project.id) } resolved = http.param("resolved")?.toIntOrNull()?.takeIf { it > 0 }?.let { Version(it, project.id) } } fun processIssueForm(issue: Issue, reference: Issue, http: HttpRequest, dao: DataAccessObject) { if (issue.hasChanged(reference)) { dao.updateIssue(issue) dao.insertHistoryEvent(issue) } val newComment = http.param("comment") if (!newComment.isNullOrBlank()) { val comment = IssueComment(-1, issue.id).apply { author = http.remoteUser?.let { dao.findUserByName(it) } comment = newComment } val commentid = dao.insertComment(comment) dao.insertHistoryEvent(issue, comment, commentid) } } fun commitIssueComment(http: HttpRequest, dao: DataAccessObject, pathInfos: PathInfos) { val issue = http.pathParams["issue"]?.toIntOrNull()?.let(dao::findIssue) if (issue == null) { http.response.sendError(404) return } if (processIssueComment(issue, http, dao)) { http.renderCommit("${pathInfos.issuesHref}${issue.id}") } } fun processIssueComment(issue:Issue, http: HttpRequest, dao: DataAccessObject): Boolean { val commentId = http.param("commentid")?.toIntOrNull() ?: -1 if (commentId > 0) { val comment = dao.findComment(commentId) if (comment == null) { http.response.sendError(404) return false } val originalAuthor = comment.author?.username if (originalAuthor != null && originalAuthor == http.remoteUser) { val newComment = http.param("comment") if (!newComment.isNullOrBlank()) { comment.comment = newComment dao.updateComment(comment) dao.insertHistoryEvent(issue, comment) } } else { http.response.sendError(403) return false } } else { val comment = IssueComment(-1, issue.id).apply { author = http.remoteUser?.let { dao.findUserByName(it) } comment = http.param("comment") ?: "" } val newId = dao.insertComment(comment) dao.insertHistoryEvent(issue, comment, newId) } return true } fun renderIssueView( http: HttpRequest, dao: DataAccessObject, issue: Issue, pathInfos: PathInfos, relationError: String? = null ) { val comments = dao.listComments(issue) with(http) { pageTitle = "#${issue.id} ${issue.subject} (${issue.project.name})" view = IssueDetailView( issue, comments, dao.listIssues(issue.project, true), dao.listIssueRelations(issue), dao.listCommitRefs(issue), relationError, pathInfos ) if (pathInfos is PathInfosFull) { navigationMenu = projectNavMenu(dao.listProjects(), pathInfos) } styleSheets = listOf("projects") javascript = "issue-editor" render("issue-view") } } fun addIssueRelation(http: HttpRequest, dao: DataAccessObject, pathInfos: PathInfos) { val issue = http.pathParams["issue"]?.toIntOrNull()?.let(dao::findIssue) if (issue == null) { http.response.sendError(404) return } // determine the relation type val type: Pair<RelationType, Boolean>? = http.param("type")?.let { try { if (it.startsWith("!")) { Pair(RelationType.valueOf(it.substring(1)), true) } else { Pair(RelationType.valueOf(it), false) } } catch (_: IllegalArgumentException) { null } } // if the relation type was invalid, send HTTP 500 if (type == null) { http.response.sendError(500) return } // determine the target issue val targetIssue: Issue? = http.param("issue")?.let { if (it.startsWith("#") && it.length > 1) { it.substring(1).split(" ", limit = 2)[0].toIntOrNull() ?.let(dao::findIssue) ?.takeIf { target -> target.project.id == issue.project.id } } else { null } } // check if the target issue is valid if (targetIssue == null) { renderIssueView(http, dao, issue, pathInfos, "issue.relations.target.invalid") return } // commit the result dao.insertIssueRelation(IssueRelation(issue, targetIssue, type.first, type.second)) http.renderCommit("${pathInfos.issuesHref}${issue.id}") } fun removeIssueRelation(http: HttpRequest, dao: DataAccessObject, pathInfos: PathInfos) { val issue = http.pathParams["issue"]?.toIntOrNull()?.let(dao::findIssue) if (issue == null) { http.response.sendError(404) return } // determine relation val type = http.param("type")?.let { try { RelationType.valueOf(it)} catch (_:IllegalArgumentException) {null} } if (type == null) { http.response.sendError(500) return } val rel = http.param("to")?.toIntOrNull()?.let(dao::findIssue)?.let { IssueRelation( issue, it, type, http.param("reverse")?.toBoolean() ?: false ) } // execute removal, if there is something to remove rel?.run(dao::deleteIssueRelation) // always pretend that the operation was successful - if there was nothing to remove, it's okay http.renderCommit("${pathInfos.issuesHref}${issue.id}") }