add filter "only non-blocked" - resolves #674

Fri, 05 Sep 2025 22:09:08 +0200

author
Mike Becker <universe@uap-core.de>
date
Fri, 05 Sep 2025 22:09:08 +0200
changeset 379
9ee8b52879fa
parent 378
ee605da75f78
child 380
a14b143330c4

add filter "only non-blocked" - resolves #674

src/main/kotlin/de/uapcore/lightpit/Constants.kt file | annotate | diff | comparison | revisions
src/main/kotlin/de/uapcore/lightpit/dao/DataAccessObject.kt file | annotate | diff | comparison | revisions
src/main/kotlin/de/uapcore/lightpit/dao/PostgresDataAccessObject.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/jspf/issue-filter.jspf file | annotate | diff | comparison | revisions
--- a/src/main/kotlin/de/uapcore/lightpit/Constants.kt	Thu Sep 04 20:35:29 2025 +0200
+++ b/src/main/kotlin/de/uapcore/lightpit/Constants.kt	Fri Sep 05 22:09:08 2025 +0200
@@ -29,7 +29,7 @@
     /**
      * A data in yyyy-mm-dd format to identify the release.
      */
-    const val VERSION_DATE = "2025-09-04"
+    const val VERSION_DATE = "2025-09-05"
 
     /**
      * The path where the JSP files reside.
--- a/src/main/kotlin/de/uapcore/lightpit/dao/DataAccessObject.kt	Thu Sep 04 20:35:29 2025 +0200
+++ b/src/main/kotlin/de/uapcore/lightpit/dao/DataAccessObject.kt	Fri Sep 05 22:09:08 2025 +0200
@@ -135,8 +135,7 @@
     fun insertIssueRelation(rel: IssueRelation)
     fun deleteIssueRelation(rel: IssueRelation)
     fun listIssueRelations(issue: Issue): List<IssueRelation>
-    fun getIssueRelationMap(includeDone: Boolean): IssueRelationMap
-    fun getIssueRelationMap(project: Project, includeDone: Boolean): IssueRelationMap
+    fun getIssueRelationMap(includeDone: Boolean, project: Project? = null): IssueRelationMap
 
     fun insertHistoryEvent(author: User?, issue: Issue, newId: Int = 0)
     fun insertHistoryEvent(author: User?, issue: Issue, issueComment: IssueComment, newId: Int = 0)
--- a/src/main/kotlin/de/uapcore/lightpit/dao/PostgresDataAccessObject.kt	Thu Sep 04 20:35:29 2025 +0200
+++ b/src/main/kotlin/de/uapcore/lightpit/dao/PostgresDataAccessObject.kt	Fri Sep 05 22:09:08 2025 +0200
@@ -1068,13 +1068,7 @@
         }.forEach(this::add)
     }
 
-    override fun getIssueRelationMap(project: Project, includeDone: Boolean): IssueRelationMap =
-        getIssueRelationMapImpl(project, includeDone)
-
-    override fun getIssueRelationMap(includeDone: Boolean): IssueRelationMap =
-        getIssueRelationMapImpl(null, includeDone)
-
-    private fun getIssueRelationMapImpl(project: Project?, includeDone: Boolean): IssueRelationMap =
+    override fun getIssueRelationMap(includeDone: Boolean, project: Project?): IssueRelationMap =
         withStatement(
             """
                 select r.from_issue, r.to_issue, r.type
--- a/src/main/kotlin/de/uapcore/lightpit/servlet/IssuesServlet.kt	Thu Sep 04 20:35:29 2025 +0200
+++ b/src/main/kotlin/de/uapcore/lightpit/servlet/IssuesServlet.kt	Fri Sep 05 22:09:08 2025 +0200
@@ -28,12 +28,10 @@
 
     private fun issues(http: HttpRequest, dao: DataAccessObject) {
         val filter = IssueFilter(http, dao)
-        val needRelationsMap = filter.onlyBlocker
-        val relationsMap = if (needRelationsMap) dao.getIssueRelationMap(filter.includeDone) else emptyMap()
 
         val issues = dao.listIssues(filter.includeDone)
             .sortedWith(IssueSorter(filter.sortPrimary, filter.sortSecondary, filter.sortTertiary))
-            .filter(issueFilterFunction(filter, relationsMap, http.user?.username ?: "<Anonymous>"))
+            .filter(issueFilterFunction(filter, dao, http.user?.username ?: "<Anonymous>"))
 
         with(http) {
             pageTitle = i18n("issues")
--- a/src/main/kotlin/de/uapcore/lightpit/servlet/ProjectServlet.kt	Thu Sep 04 20:35:29 2025 +0200
+++ b/src/main/kotlin/de/uapcore/lightpit/servlet/ProjectServlet.kt	Fri Sep 05 22:09:08 2025 +0200
@@ -106,10 +106,6 @@
 
             val filter = IssueFilter(http, dao)
 
-            val needRelationsMap = filter.onlyBlocker
-
-            val relationsMap = if (needRelationsMap) dao.getIssueRelationMap(project, filter.includeDone) else emptyMap()
-
             val specificVersion = path.versionInfo !is OptionalPathInfo.All
             val version = if (path.versionInfo is OptionalPathInfo.Specific) path.versionInfo.elem else null
             val specificComponent = path.componentInfo !is OptionalPathInfo.All
@@ -123,7 +119,7 @@
                 specificVariant, variant
             )
                 .sortedWith(IssueSorter(filter.sortPrimary, filter.sortSecondary, filter.sortTertiary))
-                .filter(issueFilterFunction(filter, relationsMap, http.user?.username ?: "<Anonymous>"))
+                .filter(issueFilterFunction(filter, dao, http.user?.username ?: "<Anonymous>", project))
 
             with(http) {
                 pageTitle = project.name
--- a/src/main/kotlin/de/uapcore/lightpit/viewmodel/Issues.kt	Thu Sep 04 20:35:29 2025 +0200
+++ b/src/main/kotlin/de/uapcore/lightpit/viewmodel/Issues.kt	Fri Sep 05 22:09:08 2025 +0200
@@ -216,10 +216,12 @@
     val flagIncludeDone = "f.0"
     val flagMine = "f.1"
     val flagBlocker = "f.2"
+    val flagNonBlocked = "f.3"
 
     val includeDone: Boolean = evalFlag(http, flagIncludeDone)
     val onlyMine: Boolean = evalFlag(http, flagMine)
     val onlyBlocker: Boolean = evalFlag(http, flagBlocker)
+    val onlyNonBlocked: Boolean = evalFlag(http, flagNonBlocked)
     val status: List<IssueStatus> = evalEnum(http, "s") { issueStatusOf(IssueStatusPhase(it)) }
     val category: List<IssueCategory> = evalEnum(http, "c")
     val assignee: List<Int> = evalInts(http, "u")
@@ -323,13 +325,18 @@
 
 fun issueFilterFunction(
     filter: IssueFilter,
-    relationsMap: IssueRelationMap,
-    currentUserName: String
-): (issue: Issue) -> Boolean =
-    {
-        (!filter.onlyMine || (it.assignee?.username ?: "") == currentUserName) &&
-                (!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))
+    dao: DataAccessObject,
+    currentUserName: String,
+    project: Project? = null
+): (Issue) -> Boolean {
+    val relationsMap = if (filter.onlyBlocker || filter.onlyNonBlocked)
+        dao.getIssueRelationMap(filter.includeDone, project) else emptyMap()
+    return { issue ->
+        (!filter.onlyMine || (issue.assignee?.username ?: "") == currentUserName) &&
+                (!filter.onlyBlocker || (relationsMap[issue.id]?.any { (_, type) -> type.blocking } ?: false)) &&
+                (!filter.onlyNonBlocked || (relationsMap.none { it.value.any { (id, type) -> type.blocking && id == issue.id } })) &&
+                (filter.status.isEmpty() || filter.status.contains(issue.status)) &&
+                (filter.category.isEmpty() || filter.category.contains(issue.category)) &&
+                (filter.onlyMine || filter.assignee.isEmpty() || filter.assignee.contains(issue.assignee?.id ?: -1))
     }
+}
--- a/src/main/resources/localization/strings.properties	Thu Sep 04 20:35:29 2025 +0200
+++ b/src/main/resources/localization/strings.properties	Fri Sep 05 22:09:08 2025 +0200
@@ -96,6 +96,7 @@
 issue.eta=ETA
 issue.filter=Filter and Sorting
 issue.filter.blocking=show only blocking
+issue.filter.non-blocked=show only non-blocked
 issue.filter.done=show resolved
 issue.filter.mine=only assigned to me
 issue.filter.more=more filter and sort options
--- a/src/main/resources/localization/strings_de.properties	Thu Sep 04 20:35:29 2025 +0200
+++ b/src/main/resources/localization/strings_de.properties	Fri Sep 05 22:09:08 2025 +0200
@@ -96,6 +96,7 @@
 issue.eta=Zieldatum
 issue.filter=Filter und Sortierung
 issue.filter.blocking=zeige nur blockierende
+issue.filter.non-blocked=zeige nur nicht-blockierte
 issue.filter.done=zeige erledigte
 issue.filter.mine=nur mir zugewiesene
 issue.filter.more=mehr Filter und Sortieroptionen
--- a/src/main/webapp/WEB-INF/changelogs/changelog-de.jspf	Thu Sep 04 20:35:29 2025 +0200
+++ b/src/main/webapp/WEB-INF/changelogs/changelog-de.jspf	Fri Sep 05 22:09:08 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>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>
     <li>Vorgänge können nicht länger mit sich selbst verlinkt werden.</li>
--- a/src/main/webapp/WEB-INF/changelogs/changelog.jspf	Thu Sep 04 20:35:29 2025 +0200
+++ b/src/main/webapp/WEB-INF/changelogs/changelog.jspf	Fri Sep 05 22:09:08 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 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>
     <li>Fix that issues could relate to themselves.</li>
--- a/src/main/webapp/WEB-INF/jspf/issue-filter.jspf	Thu Sep 04 20:35:29 2025 +0200
+++ b/src/main/webapp/WEB-INF/jspf/issue-filter.jspf	Fri Sep 05 22:09:08 2025 +0200
@@ -27,6 +27,14 @@
             <fmt:message key="issue.filter.blocking"/>
         </label>
         <label>
+            <input name="filter"
+                   type="checkbox"
+                   value="${viewmodel.filter.flagNonBlocked}"
+                   <c:if test="${viewmodel.filter.onlyNonBlocked}">checked</c:if>
+            >
+            <fmt:message key="issue.filter.non-blocked"/>
+        </label>
+        <label>
             <input id="show-more-filters" type="checkbox" onclick="toggleFilterDetails()"
                 <c:if test="${viewmodel.filter.anyListFilterActive}">checked</c:if> >
             <fmt:message key="issue.filter.more"/>

mercurial