Tue, 30 Jul 2024 18:53:39 +0200
add filter for assignee - fixes #403
--- 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()