src/main/kotlin/de/uapcore/lightpit/servlet/ProjectServlet.kt

changeset 263
aa22103809cd
parent 254
55ca6cafc3dd
child 265
6a21bb926e02
equal deleted inserted replaced
262:c357c4e69b9e 263:aa22103809cd
29 import de.uapcore.lightpit.HttpRequest 29 import de.uapcore.lightpit.HttpRequest
30 import de.uapcore.lightpit.boolValidator 30 import de.uapcore.lightpit.boolValidator
31 import de.uapcore.lightpit.dao.DataAccessObject 31 import de.uapcore.lightpit.dao.DataAccessObject
32 import de.uapcore.lightpit.dateOptValidator 32 import de.uapcore.lightpit.dateOptValidator
33 import de.uapcore.lightpit.entities.* 33 import de.uapcore.lightpit.entities.*
34 import de.uapcore.lightpit.types.IssueCategory 34 import de.uapcore.lightpit.types.*
35 import de.uapcore.lightpit.types.IssueStatus
36 import de.uapcore.lightpit.types.VersionStatus
37 import de.uapcore.lightpit.types.WebColor
38 import de.uapcore.lightpit.viewmodel.* 35 import de.uapcore.lightpit.viewmodel.*
39 import jakarta.servlet.annotation.WebServlet 36 import jakarta.servlet.annotation.WebServlet
40 import java.sql.Date 37 import java.sql.Date
41 38
42 @WebServlet(urlPatterns = ["/projects/*"]) 39 @WebServlet(urlPatterns = ["/projects/*"])
61 post("/%project/components/-/commit", this::componentCommit) 58 post("/%project/components/-/commit", this::componentCommit)
62 59
63 get("/%project/issues/%version/%component/%issue", this::issue) 60 get("/%project/issues/%version/%component/%issue", this::issue)
64 get("/%project/issues/%version/%component/%issue/edit", this::issueForm) 61 get("/%project/issues/%version/%component/%issue/edit", this::issueForm)
65 post("/%project/issues/%version/%component/%issue/comment", this::issueComment) 62 post("/%project/issues/%version/%component/%issue/comment", this::issueComment)
63 post("/%project/issues/%version/%component/%issue/relation", this::issueRelation)
64 get("/%project/issues/%version/%component/%issue/removeRelation", this::issueRemoveRelation)
66 get("/%project/issues/%version/%component/-/create", this::issueForm) 65 get("/%project/issues/%version/%component/-/create", this::issueForm)
67 post("/%project/issues/%version/%component/-/commit", this::issueCommit) 66 post("/%project/issues/%version/%component/-/commit", this::issueCommit)
68 } 67 }
69 68
70 private fun projects(http: HttpRequest, dao: DataAccessObject) { 69 private fun projects(http: HttpRequest, dao: DataAccessObject) {
438 437
439 http.renderCommit("projects/${project.node}/components/") 438 http.renderCommit("projects/${project.node}/components/")
440 } 439 }
441 440
442 private fun issue(http: HttpRequest, dao: DataAccessObject) { 441 private fun issue(http: HttpRequest, dao: DataAccessObject) {
442 val issue = http.pathParams["issue"]?.toIntOrNull()?.let(dao::findIssue)
443 if (issue == null) {
444 http.response.sendError(404)
445 return
446 }
447 renderIssueView(http, dao, issue)
448 }
449
450 private fun renderIssueView(
451 http: HttpRequest,
452 dao: DataAccessObject,
453 issue: Issue,
454 relationError: String? = null
455 ) {
443 withPathInfo(http, dao)?.run { 456 withPathInfo(http, dao)?.run {
444 val issue = dao.findIssue(http.pathParams["issue"]?.toIntOrNull() ?: -1)
445 if (issue == null) {
446 http.response.sendError(404)
447 return
448 }
449
450 val comments = dao.listComments(issue) 457 val comments = dao.listComments(issue)
451 458
452 with(http) { 459 with(http) {
453 pageTitle = "${projectInfo.project.name}: #${issue.id} ${issue.subject}" 460 pageTitle = "${projectInfo.project.name}: #${issue.id} ${issue.subject}"
454 view = IssueDetailView(issue, comments, project, version, component) 461 view = IssueDetailView(
462 issue,
463 comments,
464 project,
465 version,
466 component,
467 dao.listIssues(project),
468 dao.listIssueRelations(issue),
469 relationError
470 )
455 feedPath = feedPath(projectInfo.project) 471 feedPath = feedPath(projectInfo.project)
456 navigationMenu = activeProjectNavMenu( 472 navigationMenu = activeProjectNavMenu(
457 dao.listProjects(), 473 dao.listProjects(),
458 projectInfo, 474 projectInfo,
459 version, 475 version,
466 } 482 }
467 } 483 }
468 484
469 private fun issueForm(http: HttpRequest, dao: DataAccessObject) { 485 private fun issueForm(http: HttpRequest, dao: DataAccessObject) {
470 withPathInfo(http, dao)?.run { 486 withPathInfo(http, dao)?.run {
471 val issue = dao.findIssue(http.pathParams["issue"]?.toIntOrNull() ?: -1) ?: Issue( 487 val issue = http.pathParams["issue"]?.toIntOrNull()?.let(dao::findIssue) ?: Issue(
472 -1, 488 -1,
473 project, 489 project,
474 ) 490 )
475 491
476 // for new issues set some defaults 492 // for new issues set some defaults
512 } 528 }
513 } 529 }
514 530
515 private fun issueComment(http: HttpRequest, dao: DataAccessObject) { 531 private fun issueComment(http: HttpRequest, dao: DataAccessObject) {
516 withPathInfo(http, dao)?.run { 532 withPathInfo(http, dao)?.run {
517 val issue = dao.findIssue(http.pathParams["issue"]?.toIntOrNull() ?: -1) 533 val issue = http.pathParams["issue"]?.toIntOrNull()?.let(dao::findIssue)
518 if (issue == null) { 534 if (issue == null) {
519 http.response.sendError(404) 535 http.response.sendError(404)
520 return 536 return
521 } 537 }
522 538
614 } else { 630 } else {
615 http.renderCommit("${issuesHref}${openId}") 631 http.renderCommit("${issuesHref}${openId}")
616 } 632 }
617 } 633 }
618 } 634 }
635
636 private fun issueRelation(http: HttpRequest, dao: DataAccessObject) {
637 withPathInfo(http, dao)?.run {
638 val issue = http.pathParams["issue"]?.toIntOrNull()?.let(dao::findIssue)
639 if (issue == null) {
640 http.response.sendError(404)
641 return
642 }
643
644 // determine the relation type
645 val type: Pair<RelationType, Boolean>? = http.param("type")?.let {
646 try {
647 if (it.startsWith("!")) {
648 Pair(RelationType.valueOf(it.substring(1)), true)
649 } else {
650 Pair(RelationType.valueOf(it), false)
651 }
652 } catch (_: IllegalArgumentException) {
653 null
654 }
655 }
656
657 // if the relation type was invalid, send HTTP 500
658 if (type == null) {
659 http.response.sendError(500)
660 return
661 }
662
663 // determine the target issue
664 val targetIssue: Issue? = http.param("issue")?.let {
665 if (it.startsWith("#") && it.length > 1) {
666 it.substring(1).split(" ", limit = 2)[0].toIntOrNull()
667 ?.let(dao::findIssue)
668 ?.takeIf { target -> target.project.id == issue.project.id }
669 } else {
670 null
671 }
672 }
673
674 // check if the target issue is valid
675 if (targetIssue == null) {
676 renderIssueView(http, dao, issue, "issue.relations.target.invalid")
677 return
678 }
679
680 // commit the result
681 dao.insertIssueRelation(IssueRelation(issue, targetIssue, type.first, type.second))
682 http.renderCommit("${issuesHref}${issue.id}")
683 }
684 }
685
686 private fun issueRemoveRelation(http: HttpRequest, dao: DataAccessObject) {
687 withPathInfo(http, dao)?.run {
688 val issue = http.pathParams["issue"]?.toIntOrNull()?.let(dao::findIssue)
689 if (issue == null) {
690 http.response.sendError(404)
691 return
692 }
693
694 // determine relation
695 val type = http.param("type")?.let {
696 try {RelationType.valueOf(it)}
697 catch (_:IllegalArgumentException) {null}
698 }
699 if (type == null) {
700 http.response.sendError(500)
701 return
702 }
703 val rel = http.param("to")?.toIntOrNull()?.let(dao::findIssue)?.let {
704 IssueRelation(
705 issue,
706 it,
707 type,
708 http.param("reverse")?.toBoolean() ?: false
709 )
710 }
711
712 // execute removal, if there is something to remove
713 rel?.run(dao::deleteIssueRelation)
714
715 // always pretend that the operation was successful - if there was nothing to remove, it's okay
716 http.renderCommit("${issuesHref}${issue.id}")
717 }
718 }
619 } 719 }

mercurial