add button for creating a new related issue default tip

Sat, 06 Sep 2025 14:22:38 +0200

author
Mike Becker <universe@uap-core.de>
date
Sat, 06 Sep 2025 14:22:38 +0200
changeset 380
a14b143330c4
parent 379
9ee8b52879fa

add button for creating a new related issue

resolves #714

src/main/kotlin/de/uapcore/lightpit/Constants.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/ProjectServlet.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-form.jsp 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/Constants.kt	Fri Sep 05 22:09:08 2025 +0200
+++ b/src/main/kotlin/de/uapcore/lightpit/Constants.kt	Sat Sep 06 14:22:38 2025 +0200
@@ -29,7 +29,7 @@
     /**
      * A data in yyyy-mm-dd format to identify the release.
      */
-    const val VERSION_DATE = "2025-09-05"
+    const val VERSION_DATE = "2025-09-06"
 
     /**
      * The path where the JSP files reside.
--- a/src/main/kotlin/de/uapcore/lightpit/logic/IssueLogic.kt	Fri Sep 05 22:09:08 2025 +0200
+++ b/src/main/kotlin/de/uapcore/lightpit/logic/IssueLogic.kt	Sat Sep 06 14:22:38 2025 +0200
@@ -8,10 +8,7 @@
 import de.uapcore.lightpit.types.IssueStatus
 import de.uapcore.lightpit.types.IssueStatusPhase
 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 de.uapcore.lightpit.viewmodel.*
 import java.sql.Date
 
 fun Issue.hasChanged(reference: Issue) =
@@ -180,6 +177,19 @@
     }
 }
 
+fun determineRelationType(str: String?): Pair<RelationType, Boolean>? {
+    if (str.isNullOrBlank()) return null
+    return try {
+        if (str.startsWith("!")) {
+            Pair(RelationType.valueOf(str.substring(1)), true)
+        } else {
+            Pair(RelationType.valueOf(str), false)
+        }
+    } catch (_: IllegalArgumentException) {
+        null
+    }
+}
+
 fun addIssueRelation(http: HttpRequest, dao: DataAccessObject, pathInfos: PathInfos) {
     val issue = http.pathParams["issue"]?.toIntOrNull()?.let(dao::findIssue)
     if (issue == null) {
@@ -188,17 +198,7 @@
     }
 
     // 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
-        }
-    }
+    val type = determineRelationType(http.param("type"))
 
     // if the relation type was invalid, send HTTP 500
     if (type == null) {
@@ -206,6 +206,13 @@
         return
     }
 
+    // check if a new issue should be created
+    if (http.param("issue").isNullOrBlank()) {
+        val redirectBase = if (pathInfos.inProject) pathInfos.issuesHref else PathInfosSimple(issue.project).issuesHref
+        http.response.sendRedirect("${http.baseHref}${redirectBase}-/create?r=${http.param("type")}:${issue.id}")
+        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]) else it)
--- a/src/main/kotlin/de/uapcore/lightpit/servlet/ProjectServlet.kt	Fri Sep 05 22:09:08 2025 +0200
+++ b/src/main/kotlin/de/uapcore/lightpit/servlet/ProjectServlet.kt	Sat Sep 06 14:22:38 2025 +0200
@@ -422,6 +422,7 @@
                 if (path.versionInfo is OptionalPathInfo.Specific) {
                     if (path.versionInfo.elem.status.isReleased) {
                         issue.affected = path.versionInfo.elem
+                        // issues in past versions are most likely bugs
                         issue.category = IssueCategory.Bug
                     } else {
                         issue.resolved = path.versionInfo.elem
@@ -434,6 +435,24 @@
                 http.request.setAttribute("more", true)
             }
 
+            // test if we are auto-relating issues
+            val autoRelate = http.param("r")
+            if (autoRelate != null) {
+                val type = determineRelationType(autoRelate.split(":", limit=2)[0])
+                // only relay sane query parameters
+                if (type != null) {
+                    http.request.setAttribute("autoRelate", autoRelate)
+                    // pick a useful category for the relation
+                    if (type.first == RelationType.Tests && type.second) {
+                        // tested by a Test
+                        issue.category = IssueCategory.Test
+                    } else if (type.first == RelationType.DefectOf && !type.second) {
+                        // defect of a Bug
+                        issue.category = IssueCategory.Bug
+                    }
+                }
+            }
+
             with(http) {
                 pageTitle = (if (issue.id < 0) i18n("button.issue.create")
                     else "#${issue.id} ${issue.subject}") + " (${issue.project.name})"
@@ -481,6 +500,18 @@
                 issue.id
             }
 
+            // check if we shall relate the issue to something
+            val autoRelate = http.param("auto-relate")
+            if (autoRelate != null) {
+                val autoRelateInfo = autoRelate.split(":", limit = 2)
+                val type = determineRelationType(autoRelateInfo.getOrNull(0))
+                val relatedIssue = autoRelateInfo.getOrNull(1)?.toIntOrNull()?.let(dao::findIssue)
+                // insert the relation when the parameter is sane, but do not report an invalid parameter
+                if (type != null && relatedIssue != null) {
+                    dao.insertIssueRelation(IssueRelation(relatedIssue, Issue(openId, project), type.first, type.second))
+                }
+            }
+
             if (http.param("more") != null) {
                 http.renderCommit("${issuesHref}-/create?more=true")
             } else if (http.param("save") != null) {
--- a/src/main/resources/localization/strings.properties	Fri Sep 05 22:09:08 2025 +0200
+++ b/src/main/resources/localization/strings.properties	Sat Sep 06 14:22:38 2025 +0200
@@ -103,6 +103,7 @@
 issue.id=Issue ID
 issue.relations=Relations
 issue.relations.issue=Issue
+issue.relations.target.placeholder=Search an issue or click Add to create a new one.
 issue.relations.target.invalid=Target issue cannot be linked.
 issue.relations.type=Type
 issue.relations.type.RelatesTo=relates to
@@ -117,6 +118,8 @@
 issue.relations.type.Blocks.rev=blocked by
 issue.relations.type.Tests=tests
 issue.relations.type.Tests.rev=tested by
+issue.relations.type.DefectOf=defect of
+issue.relations.type.DefectOf.rev=defect
 issue.relations.type.Duplicates=duplicates
 issue.relations.type.Duplicates.rev=duplicated by
 issue.resolved-versions=Target
@@ -199,8 +202,6 @@
 version.status=Status
 version=Version
 whats-new.info = A new version of LightPIT has been released. Do you want to check the release notes?
-issue.relations.type.DefectOf=defect of
-issue.relations.type.DefectOf.rev=defect
 issue.filter.sort.primary=Order by
 issue.filter.sort.secondary=then by
 issue.filter.sort.tertiary=then by
--- a/src/main/resources/localization/strings_de.properties	Fri Sep 05 22:09:08 2025 +0200
+++ b/src/main/resources/localization/strings_de.properties	Sat Sep 06 14:22:38 2025 +0200
@@ -103,6 +103,7 @@
 issue.id=Vorgangs-ID
 issue.relations=Beziehungen
 issue.relations.issue=Vorgang
+issue.relations.target.placeholder=Vorgang suchen oder einen neuen Hinzuf\u00fcgen.
 issue.relations.target.invalid=Vorgang kann nicht verkn\u00fcpft werden.
 issue.relations.type=Typ
 issue.relations.type.RelatesTo=verwandt mit
@@ -117,6 +118,8 @@
 issue.relations.type.Blocks.rev=blockiert von
 issue.relations.type.Tests=testet
 issue.relations.type.Tests.rev=getestet durch
+issue.relations.type.DefectOf=Fehler von
+issue.relations.type.DefectOf.rev=Fehler
 issue.relations.type.Duplicates=Duplikat von
 issue.relations.type.Duplicates.rev=Duplikat
 issue.resolved-versions=Ziel
@@ -199,8 +202,6 @@
 version.status=Status
 version=Version
 whats-new.info = Eine neue LightPIT-Version wurde ver\u00f6ffentlicht. Wollen Sie mehr erfahren?
-issue.relations.type.DefectOf.rev=Fehler
-issue.relations.type.DefectOf=Fehler von
 issue.filter.sort.primary=Sortiere nach
 issue.filter.sort.secondary=dann nach
 issue.filter.sort.tertiary=dann nach
--- a/src/main/webapp/WEB-INF/changelogs/changelog-de.jspf	Fri Sep 05 22:09:08 2025 +0200
+++ b/src/main/webapp/WEB-INF/changelogs/changelog-de.jspf	Sat Sep 06 14:22:38 2025 +0200
@@ -30,6 +30,7 @@
     <li>Pop-Up hinzugefügt, das über eine neue LightPIT-Version informiert.</li>
     <li>"Erledigt" Schaltfläche zur Vorgangsansicht hinzugefügt.</li>
     <li>"In Projekt Öffnen" Schaltfläche zur (globalen) Vorgangsansicht hinzugefügt.</li>
+    <li>Es können nun neue Vorgänge direkt mit einer Verknüpfung zu einem existierenden Vorgang erstellt werden.</li>
     <li>Neuen Filter "zeige nur nicht-blockierte" hinzugefügt.</li>
     <li>Vorgänge können nun auch direkt über die Vorgangsnummer (anstatt Raute + Nummer) verlinkt werden.</li>
     <li>Die Standardkategorie für neue Vorgänge in veröffentlichten Versionen ist nun "Fehler" anstelle von "Feature".</li>
--- a/src/main/webapp/WEB-INF/changelogs/changelog.jspf	Fri Sep 05 22:09:08 2025 +0200
+++ b/src/main/webapp/WEB-INF/changelogs/changelog.jspf	Sat Sep 06 14:22:38 2025 +0200
@@ -30,6 +30,7 @@
     <li>Add popup informing about a new LightPIT release.</li>
     <li>Add convenience RESOLVE button to the issue view.</li>
     <li>Add convenience OPEN IN PROJECT button to the global issue view.</li>
+    <li>Add the possibility to create new related issues with one click.</li>
     <li>Add new filter "show only non-blocked".</li>
     <li>Change that you can now relate issues by just submitting their number (instead of hash + number).</li>
     <li>Change that the default category for new issues in released versions is Bug instead of Feature.</li>
--- a/src/main/webapp/WEB-INF/jsp/issue-form.jsp	Fri Sep 05 22:09:08 2025 +0200
+++ b/src/main/webapp/WEB-INF/jsp/issue-form.jsp	Sat Sep 06 14:22:38 2025 +0200
@@ -201,6 +201,7 @@
         <tr>
             <td colspan="2">
                 <input type="hidden" name="id" value="${issue.id}"/>
+                <input type="hidden" name="auto-relate" value="${autoRelate}" />
                 <c:if test="${not empty viewmodel.pathInfos}">
                 <input type="checkbox" id="more" name="more" <c:if test="${more}">checked</c:if> />
                 <label for="more"><fmt:message key="button.issue.create.another"/> </label>
--- a/src/main/webapp/WEB-INF/jsp/issue-view.jsp	Fri Sep 05 22:09:08 2025 +0200
+++ b/src/main/webapp/WEB-INF/jsp/issue-view.jsp	Sat Sep 06 14:22:38 2025 +0200
@@ -263,7 +263,8 @@
             </select>
         </td>
         <td>
-            <input id="linkable-issues" data-project="${issue.project.id}" name="issue" list="linkable-issues-list" autocomplete="off">
+            <input id="linkable-issues" data-project="${issue.project.id}" name="issue"
+                   list="linkable-issues-list" autocomplete="off" placeholder="<fmt:message key="issue.relations.target.placeholder"/>">
             <datalist id="linkable-issues-list"></datalist>
         </td>
     </tr>

mercurial