Sun, 05 Oct 2025 17:47:31 +0200
add convenience button to progress an issue and change behavior of the resolve button when a variant is opened - resolves #735
--- a/src/main/kotlin/de/uapcore/lightpit/entities/Issue.kt Sat Oct 04 16:59:07 2025 +0200 +++ b/src/main/kotlin/de/uapcore/lightpit/entities/Issue.kt Sun Oct 05 17:47:31 2025 +0200 @@ -62,6 +62,11 @@ return variantStatus[variant] } + /** + * The minimum status phase across all variants or the issue status phase if there are no variants. + */ + val minimumStatusPhaseAcrossAllVariants get() = variantStatus.values.minOfOrNull { it.phase } ?: status.phase + fun updateStatusFromVariants() { if (!isTrackingVariantStatus) return
--- a/src/main/kotlin/de/uapcore/lightpit/logic/IssueLogic.kt Sat Oct 04 16:59:07 2025 +0200 +++ b/src/main/kotlin/de/uapcore/lightpit/logic/IssueLogic.kt Sun Oct 05 17:47:31 2025 +0200 @@ -136,16 +136,34 @@ return true } -fun issueQuickResolve(http: HttpRequest, dao: DataAccessObject, issue: Issue) { - if (issue.status.phase == IssueStatusPhase.Done) return +fun issueQuickProgress(http: HttpRequest, dao: DataAccessObject, issue: Issue, variant: Variant? = null) { + if (issue.minimumStatusPhaseAcrossAllVariants != IssueStatusPhase.Open) return if (issue.isTrackingVariantStatus) { - issue.variantStatus.filter { it.value.phase != IssueStatusPhase.Done }.keys.forEach { + issue.variantStatus.filter { + it.value.phase == IssueStatusPhase.Open && (variant == null || it.key == variant) + }.keys.forEach { + issue.variantStatus[it] = IssueStatus.InProgress + } + issue.updateStatusFromVariants() + } else { + issue.status = IssueStatus.InProgress + } + dao.updateIssue(issue) + dao.insertHistoryEvent(http.user, issue) +} + +fun issueQuickResolve(http: HttpRequest, dao: DataAccessObject, issue: Issue, variant: Variant? = null) { + if (issue.minimumStatusPhaseAcrossAllVariants == IssueStatusPhase.Done) return + if (issue.isTrackingVariantStatus) { + issue.variantStatus.filter { + it.value.phase != IssueStatusPhase.Done && (variant == null || it.key == variant) + }.keys.forEach { issue.variantStatus[it] = IssueStatus.Done } + issue.updateStatusFromVariants() } else { issue.status = IssueStatus.Done } - issue.updateStatusFromVariants() dao.updateIssue(issue) dao.insertHistoryEvent(http.user, issue) }
--- a/src/main/kotlin/de/uapcore/lightpit/servlet/IssuesServlet.kt Sat Oct 04 16:59:07 2025 +0200 +++ b/src/main/kotlin/de/uapcore/lightpit/servlet/IssuesServlet.kt Sun Oct 05 17:47:31 2025 +0200 @@ -19,6 +19,7 @@ get("/search", this::issueSearch) get("/%issue", this::issue) get("/%issue/edit", this::issueForm) + get("/%issue/progress", this::issueProgress) get("/%issue/resolve", this::issueResolve) post("/%issue/comment", this::issueComment) post("/%issue/relation", this::issueRelation) @@ -55,6 +56,16 @@ renderIssueView(http, dao, issue, pathInfos) } + private fun issueProgress(http: HttpRequest, dao: DataAccessObject) { + val issue = http.pathParams["issue"]?.toIntOrNull()?.let(dao::findIssue) + if (issue == null) { + http.response.sendError(404) + return + } + issueQuickProgress(http, dao, issue) + http.renderCommit("${pathInfos.issuesHref}${issue.id}") + } + private fun issueResolve(http: HttpRequest, dao: DataAccessObject) { val issue = http.pathParams["issue"]?.toIntOrNull()?.let(dao::findIssue) if (issue == null) {
--- a/src/main/kotlin/de/uapcore/lightpit/servlet/ProjectServlet.kt Sat Oct 04 16:59:07 2025 +0200 +++ b/src/main/kotlin/de/uapcore/lightpit/servlet/ProjectServlet.kt Sun Oct 05 17:47:31 2025 +0200 @@ -63,6 +63,7 @@ get("/%project/issues/%version/%component/%variant/%issue", this::issue) get("/%project/issues/%version/%component/%variant/%issue/edit", this::issueForm) + get("/%project/issues/%version/%component/%variant/%issue/progress", this::issueProgress) get("/%project/issues/%version/%component/%variant/%issue/resolve", this::issueResolve) post("/%project/issues/%version/%component/%variant/%issue/comment", this::issueComment) post("/%project/issues/%version/%component/%variant/%issue/relation", this::issueRelation) @@ -392,14 +393,26 @@ } } + private fun issueProgress(http: HttpRequest, dao: DataAccessObject) { + val issue = http.pathParams["issue"]?.toIntOrNull()?.let(dao::findIssue) + if (issue == null) { + http.response.sendError(404) + return + } + withPathInfo(http, dao)?.let { path -> + issueQuickProgress(http, dao, issue, (path.variantInfo as? OptionalPathInfo.Specific)?.elem) + http.renderCommit("${path.issuesHref}${issue.id}") + } + } + private fun issueResolve(http: HttpRequest, dao: DataAccessObject) { val issue = http.pathParams["issue"]?.toIntOrNull()?.let(dao::findIssue) if (issue == null) { http.response.sendError(404) return } - issueQuickResolve(http, dao, issue) withPathInfo(http, dao)?.let { path -> + issueQuickResolve(http, dao, issue, (path.variantInfo as? OptionalPathInfo.Specific)?.elem) http.renderCommit("${path.issuesHref}${issue.id}") } }
--- a/src/main/kotlin/de/uapcore/lightpit/viewmodel/Issues.kt Sat Oct 04 16:59:07 2025 +0200 +++ b/src/main/kotlin/de/uapcore/lightpit/viewmodel/Issues.kt Sun Oct 05 17:47:31 2025 +0200 @@ -32,6 +32,7 @@ import com.vladsch.flexmark.util.data.MutableDataSet import com.vladsch.flexmark.util.data.SharedDataKeys import de.uapcore.lightpit.HttpRequest +import de.uapcore.lightpit.OptionalPathInfo import de.uapcore.lightpit.dao.DataAccessObject import de.uapcore.lightpit.entities.* import de.uapcore.lightpit.logic.compareEtaTo @@ -129,6 +130,7 @@ ) : View() { val relationTypes = RelationType.entries val commitLinks: List<CommitLink> + val openedVariant: Variant? = ((pathInfos as? PathInfosFull)?.variantInfo as? OptionalPathInfo.Specific)?.elem private val parser: Parser private val renderer: HtmlRenderer
--- a/src/main/resources/localization/strings.properties Sat Oct 04 16:59:07 2025 +0200 +++ b/src/main/resources/localization/strings.properties Sun Oct 05 17:47:31 2025 +0200 @@ -38,6 +38,7 @@ button.issue.create=New Issue button.issue.edit=Edit button.issue.open-in-project=Open in Project +button.issue.progress=Progress button.issue.resolve=Resolve button.okay=OK button.project.create=New Project
--- a/src/main/resources/localization/strings_de.properties Sat Oct 04 16:59:07 2025 +0200 +++ b/src/main/resources/localization/strings_de.properties Sun Oct 05 17:47:31 2025 +0200 @@ -38,6 +38,7 @@ button.issue.create=Neuer Vorgang button.issue.edit=Bearbeiten button.issue.open-in-project=In Projekt \u00d6ffnen +button.issue.progress=In Arbeit button.issue.resolve=Erledigt button.okay=OK button.project.create=Neues Projekt
--- a/src/main/webapp/WEB-INF/changelogs/changelog-de.jspf Sat Oct 04 16:59:07 2025 +0200 +++ b/src/main/webapp/WEB-INF/changelogs/changelog-de.jspf Sun Oct 05 17:47:31 2025 +0200 @@ -28,7 +28,7 @@ <ul> <li>Pop-Up hinzugefügt, das über eine neue LightPIT-Version informiert.</li> - <li>"Erledigt" Schaltfläche zur Vorgangsansicht hinzugefügt.</li> + <li>Neue Schaltflächen zur Vorgangsansicht hinzugefügt, mit denen der Status des Vorgangs schnell geändert werden kann.</li> <li>"In Projekt Öffnen" Schaltfläche zur (globalen) Vorgangsansicht hinzugefügt.</li> <li>Schaltflächen hinzugefügt, die schnelleren Zugang zu den Editoren für Versionen, Komponenten und Varianten bieten.</li> <li>Es können nun neue Vorgänge direkt mit einer Verknüpfung zu einem existierenden Vorgang erstellt werden.</li>
--- a/src/main/webapp/WEB-INF/changelogs/changelog.jspf Sat Oct 04 16:59:07 2025 +0200 +++ b/src/main/webapp/WEB-INF/changelogs/changelog.jspf Sun Oct 05 17:47:31 2025 +0200 @@ -28,7 +28,7 @@ <ul> <li>Add popup informing about a new LightPIT release.</li> - <li>Add convenience RESOLVE button to the issue view.</li> + <li>Add convenience buttons to the issue view to quickly change the issue status.</li> <li>Add convenience OPEN IN PROJECT button to the global issue view.</li> <li>Add buttons and hover-icons to quickly access the editor for versions, components, and variants.</li> <li>Add the possibility to create new related issues with one click.</li>
--- a/src/main/webapp/WEB-INF/jsp/issue-view.jsp Sat Oct 04 16:59:07 2025 +0200 +++ b/src/main/webapp/WEB-INF/jsp/issue-view.jsp Sun Oct 05 17:47:31 2025 +0200 @@ -189,7 +189,18 @@ <fmt:message key="button.issue.open-in-project"/> </a> </c:if> - <c:if test="${issue.status.phase ne IssueStatusPhase.Companion.done}"> + <c:if test="${not issue.trackingVariantStatus or empty viewmodel.openedVariant}"> + <c:set scope="page" var="workflowPhase" value="${issue.minimumStatusPhaseAcrossAllVariants}"/> + </c:if> + <c:if test="${issue.trackingVariantStatus and not empty viewmodel.openedVariant}"> + <c:set scope="page" var="workflowPhase" value="${issue.variantStatus[viewmodel.openedVariant].phase}"/> + </c:if> + <c:if test="${workflowPhase eq IssueStatusPhase.Companion.open}"> + <a href="${issuesHref}${issue.id}/progress" class="button submit"> + <fmt:message key="button.issue.progress"/> + </a> + </c:if> + <c:if test="${workflowPhase ne IssueStatusPhase.Companion.done}"> <a href="${issuesHref}${issue.id}/resolve" class="button submit"> <fmt:message key="button.issue.resolve"/> </a>