diff -r bbf4eb9a71f8 -r bf67e0ff7131 src/main/kotlin/de/uapcore/lightpit/servlet/ProjectServlet.kt --- a/src/main/kotlin/de/uapcore/lightpit/servlet/ProjectServlet.kt Mon Aug 05 17:41:56 2024 +0200 +++ b/src/main/kotlin/de/uapcore/lightpit/servlet/ProjectServlet.kt Mon Aug 05 18:40:47 2024 +0200 @@ -27,8 +27,15 @@ import de.uapcore.lightpit.* import de.uapcore.lightpit.dao.DataAccessObject -import de.uapcore.lightpit.entities.* -import de.uapcore.lightpit.types.* +import de.uapcore.lightpit.entities.Component +import de.uapcore.lightpit.entities.Issue +import de.uapcore.lightpit.entities.Project +import de.uapcore.lightpit.entities.Version +import de.uapcore.lightpit.logic.* +import de.uapcore.lightpit.types.VcsType +import de.uapcore.lightpit.types.VersionStatus +import de.uapcore.lightpit.types.WebColor +import de.uapcore.lightpit.types.parseCommitRefs import de.uapcore.lightpit.viewmodel.* import jakarta.servlet.annotation.WebServlet import java.sql.Date @@ -92,13 +99,11 @@ } } - private fun feedPath(project: Project) = "feed/${project.node}/issues.rss" - private fun project(http: HttpRequest, dao: DataAccessObject) { withPathInfo(http, dao)?.let {path -> val project = path.projectInfo.project - val filter = IssueFilter(http) + val filter = IssueFilter(http, dao) val needRelationsMap = filter.onlyBlocker @@ -111,21 +116,14 @@ val issues = dao.listIssues(project, filter.includeDone, specificVersion, version, specificComponent, component) .sortedWith(IssueSorter(filter.sortPrimary, filter.sortSecondary, filter.sortTertiary)) - .filter { - (!filter.onlyMine || (it.assignee?.username ?: "") == (http.remoteUser ?: "")) && - (!filter.onlyBlocker || (relationsMap[it.id]?.any { (_,type) -> type.blocking }?:false)) && - (filter.status.isEmpty() || filter.status.contains(it.status)) && - (filter.category.isEmpty() || filter.category.contains(it.category)) && - (filter.onlyMine || filter.assignee.isEmpty() || filter.assignee.contains(it.assignee?.id ?: -1)) - } + .filter(issueFilterFunction(filter, relationsMap, http.remoteUser ?: "")) with(http) { pageTitle = project.name - view = ProjectDetails(path, issues, filter, dao.listUsers().sortedBy(User::shortDisplayname)) - feedPath = feedPath(project) + view = ProjectDetails(path, issues, filter) navigationMenu = projectNavMenu(dao.listProjects(), path) styleSheets = listOf("projects") - javascript = "project-details" + javascript = "issue-overview" render("project-details") } } @@ -196,10 +194,9 @@ path.projectInfo, dao.listVersionSummaries(path.projectInfo.project) ) - feedPath = feedPath(path.projectInfo.project) navigationMenu = projectNavMenu(dao.listProjects(), path) styleSheets = listOf("projects") - javascript = "project-details" + javascript = "issue-overview" render("versions") } } @@ -212,7 +209,6 @@ with(http) { view = VersionEditView(path.projectInfo, version) - feedPath = feedPath(path.projectInfo.project) navigationMenu = projectNavMenu(dao.listProjects(), path) styleSheets = listOf("projects") render("version-form") @@ -274,10 +270,9 @@ path.projectInfo, dao.listComponentSummaries(path.projectInfo.project) ) - feedPath = feedPath(path.projectInfo.project) navigationMenu = projectNavMenu(dao.listProjects(), path) styleSheets = listOf("projects") - javascript = "project-details" + javascript = "issue-overview" render("components") } } @@ -290,7 +285,6 @@ with(http) { view = ComponentEditView(path.projectInfo, component, dao.listUsers()) - feedPath = feedPath(path.projectInfo.project) navigationMenu = projectNavMenu(dao.listProjects(), path) styleSheets = listOf("projects") render("component-form") @@ -334,36 +328,8 @@ http.response.sendError(404) return } - renderIssueView(http, dao, issue) - } - - private fun renderIssueView( - http: HttpRequest, - dao: DataAccessObject, - issue: Issue, - relationError: String? = null - ) { - withPathInfo(http, dao)?.let {path -> - val comments = dao.listComments(issue) - - with(http) { - pageTitle = "#${issue.id} ${issue.subject} (${path.projectInfo.project.name})" - view = IssueDetailView( - path, - issue, - comments, - path.projectInfo.project, - dao.listIssues(path.projectInfo.project, true), - dao.listIssueRelations(issue), - relationError, - dao.listCommitRefs(issue) - ) - feedPath = feedPath(path.projectInfo.project) - navigationMenu = projectNavMenu(dao.listProjects(), path) - styleSheets = listOf("projects") - javascript = "issue-editor" - render("issue-view") - } + withPathInfo(http, dao)?.let { path -> + renderIssueView(http, dao, issue, path) } } @@ -400,7 +366,6 @@ path.projectInfo.project, path ) - feedPath = feedPath(path.projectInfo.project) navigationMenu = projectNavMenu(dao.listProjects(), path) styleSheets = listOf("projects") javascript = "issue-editor" @@ -410,44 +375,8 @@ } private fun issueComment(http: HttpRequest, dao: DataAccessObject) { - withPathInfo(http, dao)?.run { - val issue = http.pathParams["issue"]?.toIntOrNull()?.let(dao::findIssue) - if (issue == null) { - http.response.sendError(404) - return - } - - val commentId = http.param("commentid")?.toIntOrNull() ?: -1 - if (commentId > 0) { - val comment = dao.findComment(commentId) - if (comment == null) { - http.response.sendError(404) - return - } - 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 { - logger.debug("Not updating comment ${comment.id} because nothing changed.") - } - } else { - http.response.sendError(403) - return - } - } 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) - } - - http.renderCommit("${issuesHref}${issue.id}") + withPathInfo(http, dao)?.let {path -> + commitIssueComment(http, dao, path) } } @@ -456,25 +385,7 @@ val issue = Issue( http.param("id")?.toIntOrNull() ?: -1, projectInfo.project - ).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 ?: projectInfo.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) } - } + ).applyFormData(http, dao) val openId = if (issue.id < 0) { val id = dao.insertIssue(issue) @@ -486,23 +397,7 @@ http.response.sendError(404) return } - - if (issue.hasChanged(reference)) { - dao.updateIssue(issue) - dao.insertHistoryEvent(issue) - } else { - logger.debug("Not updating issue ${issue.id} because nothing changed.") - } - - 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) - } + processIssueForm(issue, reference, http, dao) issue.id } @@ -517,86 +412,14 @@ } private fun issueRelation(http: HttpRequest, dao: DataAccessObject) { - withPathInfo(http, dao)?.run { - val issue = http.pathParams["issue"]?.toIntOrNull()?.let(dao::findIssue) - if (issue == null) { - http.response.sendError(404) - return - } - - // determine the relation type - val type: Pair? = 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, "issue.relations.target.invalid") - return - } - - // commit the result - dao.insertIssueRelation(IssueRelation(issue, targetIssue, type.first, type.second)) - http.renderCommit("${issuesHref}${issue.id}") + withPathInfo(http, dao)?.let {path -> + addIssueRelation(http, dao, path) } } private fun issueRemoveRelation(http: HttpRequest, dao: DataAccessObject) { - withPathInfo(http, dao)?.run { - 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("${issuesHref}${issue.id}") + withPathInfo(http, dao)?.let {path -> + removeIssueRelation(http, dao, path) } } } \ No newline at end of file