add convenience button to progress an issue and change behavior of the resolve button when a variant is opened - resolves #735

Sun, 05 Oct 2025 17:47:31 +0200

author
Mike Becker <universe@uap-core.de>
date
Sun, 05 Oct 2025 17:47:31 +0200
changeset 396
288cb8d22584
parent 395
c3ef1c328b36
child 397
11bb10ff8b4d

add convenience button to progress an issue and change behavior of the resolve button when a variant is opened - resolves #735

src/main/kotlin/de/uapcore/lightpit/entities/Issue.kt file | annotate | diff | comparison | revisions
src/main/kotlin/de/uapcore/lightpit/logic/IssueLogic.kt file | annotate | diff | comparison | revisions
src/main/kotlin/de/uapcore/lightpit/servlet/IssuesServlet.kt file | annotate | diff | comparison | revisions
src/main/kotlin/de/uapcore/lightpit/servlet/ProjectServlet.kt file | annotate | diff | comparison | revisions
src/main/kotlin/de/uapcore/lightpit/viewmodel/Issues.kt file | annotate | diff | comparison | revisions
src/main/resources/localization/strings.properties file | annotate | diff | comparison | revisions
src/main/resources/localization/strings_de.properties file | annotate | diff | comparison | revisions
src/main/webapp/WEB-INF/changelogs/changelog-de.jspf file | annotate | diff | comparison | revisions
src/main/webapp/WEB-INF/changelogs/changelog.jspf file | annotate | diff | comparison | revisions
src/main/webapp/WEB-INF/jsp/issue-view.jsp file | annotate | diff | comparison | revisions
--- 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>

mercurial