add filter for assignee - fixes #403

Tue, 30 Jul 2024 18:53:39 +0200

author
Mike Becker <universe@uap-core.de>
date
Tue, 30 Jul 2024 18:53:39 +0200
changeset 307
23fe9f174d2d
parent 306
1ab9f65e683e
child 308
7b5f6dd8dad6

add filter for assignee - fixes #403

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/kotlin/de/uapcore/lightpit/viewmodel/Projects.kt 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/site.jsp file | annotate | diff | comparison | revisions
src/main/webapp/WEB-INF/jspf/issue-filter.jspf file | annotate | diff | comparison | revisions
src/main/webapp/project-details.js file | annotate | diff | comparison | revisions
--- a/src/main/kotlin/de/uapcore/lightpit/servlet/ProjectServlet.kt	Sun Jul 28 14:13:36 2024 +0200
+++ b/src/main/kotlin/de/uapcore/lightpit/servlet/ProjectServlet.kt	Tue Jul 30 18:53:39 2024 +0200
@@ -115,12 +115,13 @@
                     (!filter.onlyMine || (it.assignee?.username ?: "") == (http.remoteUser ?: "<Anonymous>")) &&
                     (!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.category.isEmpty() || filter.category.contains(it.category)) &&
+                    (filter.onlyMine || filter.assignee.isEmpty() || filter.assignee.contains(it.assignee?.id ?: -1))
                 }
 
             with(http) {
                 pageTitle = project.name
-                view = ProjectDetails(path, issues, filter)
+                view = ProjectDetails(path, issues, filter, dao.listUsers().sortedBy(User::shortDisplayname))
                 feedPath = feedPath(project)
                 navigationMenu = projectNavMenu(dao.listProjects(), path)
                 styleSheets = listOf("projects")
--- a/src/main/kotlin/de/uapcore/lightpit/viewmodel/Issues.kt	Sun Jul 28 14:13:36 2024 +0200
+++ b/src/main/kotlin/de/uapcore/lightpit/viewmodel/Issues.kt	Tue Jul 30 18:53:39 2024 +0200
@@ -208,11 +208,14 @@
     val onlyBlocker: Boolean = evalFlag(http, flagBlocker)
     val status: List<IssueStatus> = evalEnum(http, "s")
     val category: List<IssueCategory> = evalEnum(http, "c")
+    val assignee: List<Int> = evalInts(http, "u")
 
     val sortPrimary: IssueSorter.Criteria = evalSort(http, "primary", IssueSorter.Criteria(IssueSorter.Field.DONE))
     val sortSecondary: IssueSorter.Criteria = evalSort(http, "secondary", IssueSorter.Criteria(IssueSorter.Field.ETA))
     val sortTertiary: IssueSorter.Criteria = evalSort(http, "tertiary", IssueSorter.Criteria(IssueSorter.Field.UPDATED, false))
 
+    fun containsAssignee(user: User?): Boolean = assignee.contains(user?.id?:-1)
+
     private fun evalSort(http: HttpRequest, prio: String, defaultValue: IssueSorter.Criteria): IssueSorter.Criteria {
         val param = http.param("sort_$prio")
         if (param != null) {
@@ -268,4 +271,25 @@
             ?.map { enumValueOf(it) }
             ?: emptyList()
     }
+
+    private fun evalInts(http: HttpRequest, prefix: String): List<Int> {
+        val sattr = "f.${prefix}"
+        val param = http.paramArray("filter")
+        if (param.isNotEmpty()) {
+            val list = param.filter { it.startsWith("${prefix}.") }
+                .map { it.substring(prefix.length + 1) }
+                .mapNotNull(String::toIntOrNull)
+            if (list.isEmpty()) {
+                http.session.removeAttribute(sattr)
+            } else {
+                http.session.setAttribute(sattr, list.joinToString(","))
+            }
+        }
+
+        return http.session.getAttribute(sattr)
+            ?.toString()
+            ?.split(",")
+            ?.map(String::toInt)
+            ?: emptyList()
+    }
 }
--- a/src/main/kotlin/de/uapcore/lightpit/viewmodel/Projects.kt	Sun Jul 28 14:13:36 2024 +0200
+++ b/src/main/kotlin/de/uapcore/lightpit/viewmodel/Projects.kt	Tue Jul 30 18:53:39 2024 +0200
@@ -49,6 +49,7 @@
     val pathInfos: PathInfos,
     val issues: List<Issue>,
     val filter: IssueFilter,
+    val users: List<User>
 ) : View() {
     val projectInfo = pathInfos.projectInfo
     val issueSummary = IssueSummary()
--- a/src/main/resources/localization/strings_de.properties	Sun Jul 28 14:13:36 2024 +0200
+++ b/src/main/resources/localization/strings_de.properties	Tue Jul 30 18:53:39 2024 +0200
@@ -72,7 +72,7 @@
 feed.issues.type.UpdateComment=Kommentar Update
 feed=Feed
 issue.affected-versions=Betroffen
-issue.assignee=Zugewiesen
+issue.assignee=Bearbeiter
 issue.category.Bug=Fehler
 issue.category.Feature=Feature
 issue.category.Improvement=Verbesserung
--- a/src/main/webapp/WEB-INF/changelogs/changelog-de.jspf	Sun Jul 28 14:13:36 2024 +0200
+++ b/src/main/webapp/WEB-INF/changelogs/changelog-de.jspf	Tue Jul 30 18:53:39 2024 +0200
@@ -27,6 +27,7 @@
 <h3>Version 1.3.0 - Vorschau</h3>
 
 <ul>
+    <li>Filter für Bearbeiter hinzugefügt.</li>
     <li>Automatische Zuweisung von Vorgängen bezieht neben der Leitung für eine Komponente nun auch die Leitung des Projektes ein.</li>
     <li>Der "OK" Button im Vorgangseditor führt nun zurück zur Vorgangsübersicht.</li>
     <li>Ein neuer "Speichern" Button im Vorgangseditor führt, wie zuvor, zurück zur Vorgangsansicht.</li>
--- a/src/main/webapp/WEB-INF/changelogs/changelog.jspf	Sun Jul 28 14:13:36 2024 +0200
+++ b/src/main/webapp/WEB-INF/changelogs/changelog.jspf	Tue Jul 30 18:53:39 2024 +0200
@@ -27,6 +27,7 @@
 <h3>Version 1.3.0 - preview</h3>
 
 <ul>
+    <li>Add filter for assignee.</li>
     <li>Automatic assignment of issue now uses the project lead as fallback when no component lead is available.</li>
     <li>The "OK" button in the issue editor now leads to the issue overview.</li>
     <li>A new "Save" button in the issue editor retains the old behavior and returns to the issue viewer.</li>
--- a/src/main/webapp/WEB-INF/jsp/site.jsp	Sun Jul 28 14:13:36 2024 +0200
+++ b/src/main/webapp/WEB-INF/jsp/site.jsp	Tue Jul 30 18:53:39 2024 +0200
@@ -31,7 +31,7 @@
 <%@taglib prefix="fn" uri="http://java.sun.com/jsp/jstl/functions" %>
 
 <%-- Version suffix for forcing browsers to update the CSS / JS files --%>
-<c:set scope="page" var="versionSuffix" value="20230903"/>
+<c:set scope="page" var="versionSuffix" value="20240730"/>
 
 <%-- Make the base href easily available at request scope --%>
 <c:set scope="page" var="baseHref" value="${requestScope[Constants.REQ_ATTR_BASE_HREF]}"/>
--- a/src/main/webapp/WEB-INF/jspf/issue-filter.jspf	Sun Jul 28 14:13:36 2024 +0200
+++ b/src/main/webapp/WEB-INF/jspf/issue-filter.jspf	Tue Jul 30 18:53:39 2024 +0200
@@ -9,10 +9,12 @@
             <fmt:message key="issue.filter.done"/>
         </label>
         <label>
-            <input name="filter"
+            <input id="filter-only-mine"
+                   name="filter"
                    type="checkbox"
                    value="${viewmodel.filter.flagMine}"
                    <c:if test="${viewmodel.filter.onlyMine}">checked</c:if>
+                   onclick="toggleAssigneeOnlyMine()"
             >
             <fmt:message key="issue.filter.mine"/>
         </label>
@@ -50,6 +52,19 @@
                 </c:forEach>
             </select>
         </div>
+        <div style="display: inline-block">
+            <label class="caption" style="display:block;" for="filter-assignee"><fmt:message key="issue.assignee"/></label>
+            <select id="filter-assignee" name="filter" multiple size="10" <c:if test="${viewmodel.filter.onlyMine}">disabled</c:if> >
+                <option value="u.-1" <c:if test="${viewmodel.filter.containsAssignee(null) }">selected</c:if>>
+                    <fmt:message key="placeholder.null-assignee" />
+                </option>
+                <c:forEach var="user" items="${viewmodel.users}">
+                    <option value="u.${user.id}" <c:if test="${viewmodel.filter.containsAssignee(user) }">selected</c:if>>
+                        <c:out value="${user.shortDisplayname}"/>
+                    </option>
+                </c:forEach>
+            </select>
+        </div>
         <c:set var="sortPriority" value="primary"/>
         <c:set var="currentSort" value="${viewmodel.filter.sortPrimary}"/>
         <%@include file="sort-box.jspf"%>
--- a/src/main/webapp/project-details.js	Sun Jul 28 14:13:36 2024 +0200
+++ b/src/main/webapp/project-details.js	Tue Jul 30 18:53:39 2024 +0200
@@ -63,6 +63,16 @@
     }
 }
 
+function toggleAssigneeOnlyMine() {
+    const filters = document.getElementById('filter-assignee')
+    const toggle = document.getElementById('filter-only-mine')
+    if (toggle.checked) {
+        filters.disabled = true;
+    } else {
+        filters.disabled = false;
+    }
+}
+
 function toggleDetails() {
     toggleProjectDetails()
     toggleFilterDetails()

mercurial