#15 add sort options

Sun, 08 Jan 2023 19:32:11 +0100

author
Mike Becker <universe@uap-core.de>
date
Sun, 08 Jan 2023 19:32:11 +0100
changeset 271
f8f5e82944fa
parent 270
8c088c628a20
child 272
edb6f12b334b

#15 add sort options

src/main/kotlin/de/uapcore/lightpit/servlet/ProjectServlet.kt file | annotate | diff | comparison | revisions
src/main/kotlin/de/uapcore/lightpit/types/IssueCategory.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
src/main/webapp/WEB-INF/jspf/sort-box.jspf file | annotate | diff | comparison | revisions
--- a/src/main/kotlin/de/uapcore/lightpit/servlet/ProjectServlet.kt	Sun Jan 08 17:57:05 2023 +0100
+++ b/src/main/kotlin/de/uapcore/lightpit/servlet/ProjectServlet.kt	Sun Jan 08 19:32:11 2023 +0100
@@ -191,13 +191,7 @@
             val relationsMap = if (needRelationsMap) dao.getIssueRelationMap(project, filter.includeDone) else emptyMap()
 
             val issues = dao.listIssues(project, filter.includeDone, version, component)
-                .sortedWith(
-                    IssueSorter(
-                        IssueSorter.Criteria(IssueSorter.Field.DONE),
-                        IssueSorter.Criteria(IssueSorter.Field.ETA),
-                        IssueSorter.Criteria(IssueSorter.Field.UPDATED, false)
-                    )
-                )
+                .sortedWith(IssueSorter(filter.sortPrimary, filter.sortSecondary, filter.sortTertiary))
                 .filter {
                     (!filter.onlyMine || (it.assignee?.username ?: "") == (http.remoteUser ?: "<Anonymous>")) &&
                     (!filter.onlyBlocker || (relationsMap[it.id]?.any { (_,type) -> type.blocking }?:false)) &&
--- a/src/main/kotlin/de/uapcore/lightpit/types/IssueCategory.kt	Sun Jan 08 17:57:05 2023 +0100
+++ b/src/main/kotlin/de/uapcore/lightpit/types/IssueCategory.kt	Sun Jan 08 19:32:11 2023 +0100
@@ -26,5 +26,5 @@
 package de.uapcore.lightpit.types
 
 enum class IssueCategory {
-    Feature, Improvement, Bug, Task, Test
+    Bug, Feature, Improvement, Task, Test
 }
\ No newline at end of file
--- a/src/main/kotlin/de/uapcore/lightpit/viewmodel/Issues.kt	Sun Jan 08 17:57:05 2023 +0100
+++ b/src/main/kotlin/de/uapcore/lightpit/viewmodel/Issues.kt	Sun Jan 08 19:32:11 2023 +0100
@@ -38,10 +38,20 @@
 
 class IssueSorter(private vararg val criteria: Criteria) : Comparator<Issue> {
     enum class Field {
-        DONE, PHASE, STATUS, CATEGORY, ETA, UPDATED, CREATED
+        DONE, PHASE, STATUS, CATEGORY, ETA, UPDATED, CREATED;
+
+        val resourceKey: String by lazy {
+            if (this == DONE) "issue.filter.sort.done"
+            else if (this == PHASE) "issue.filter.sort.phase"
+            else "issue.${this.name.lowercase()}"
+        }
     }
 
-    data class Criteria(val field: Field, val asc: Boolean = true)
+    data class Criteria(val field: Field, val asc: Boolean = true) {
+        override fun toString(): String {
+            return "$field.$asc"
+        }
+    }
 
     override fun compare(left: Issue, right: Issue): Int {
         if (left == right) {
@@ -170,6 +180,7 @@
 
     val issueStatus = IssueStatus.values()
     val issueCategory = IssueCategory.values()
+    val sortCriteria = IssueSorter.Field.values().flatMap { listOf(IssueSorter.Criteria(it, true), IssueSorter.Criteria(it, false)) }
     val flagIncludeDone = "f.0"
     val flagMine = "f.1"
     val flagBlocker = "f.2"
@@ -180,6 +191,26 @@
     val status: List<IssueStatus> = evalEnum(http, "s")
     val category: List<IssueCategory> = evalEnum(http, "c")
 
+    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))
+
+    private fun evalSort(http: HttpRequest, prio: String, defaultValue: IssueSorter.Criteria): IssueSorter.Criteria {
+        val param = http.param("sort_$prio")
+        if (param != null) {
+            http.session.removeAttribute("sort_$prio")
+            val p = param.split(".")
+            if (p.size > 1) {
+                try {
+                    http.session.setAttribute("sort_$prio", IssueSorter.Criteria(enumValueOf(p[0]), p[1].toBoolean()))
+                } catch (_:IllegalArgumentException) {
+                    // ignore malfored values
+                }
+            }
+        }
+        return http.session.getAttribute("sort_$prio") as IssueSorter.Criteria? ?: defaultValue
+    }
+
     private fun evalFlag(http: HttpRequest, name: String): Boolean {
         val param = http.paramArray("filter")
         if (param.isNotEmpty()) {
--- a/src/main/resources/localization/strings.properties	Sun Jan 08 17:57:05 2023 +0100
+++ b/src/main/resources/localization/strings.properties	Sun Jan 08 19:32:11 2023 +0100
@@ -86,11 +86,11 @@
 issue.created=Created
 issue.description=Description
 issue.eta=ETA
-issue.filter=Filter
+issue.filter=Filter and Sorting
 issue.filter.blocking=show only blocking
 issue.filter.done=show resolved
 issue.filter.mine=only assigned to me
-issue.filter.more=more filters
+issue.filter.more=more filter and sort options
 issue.id=Issue ID
 issue.relations=Relations
 issue.relations.issue=Issue
@@ -177,4 +177,9 @@
 version.status=Status
 version=Version
 issue.relations.type.DefectOf=defect of
-issue.relations.type.DefectOf.rev=defect
\ No newline at end of file
+issue.relations.type.DefectOf.rev=defect
+issue.filter.sort.primary=Primary Order
+issue.filter.sort.secondary=Secondary Order
+issue.filter.sort.tertiary=Tertiary Order
+issue.filter.sort.done=resolved
+issue.filter.sort.phase=Phase
\ No newline at end of file
--- a/src/main/resources/localization/strings_de.properties	Sun Jan 08 17:57:05 2023 +0100
+++ b/src/main/resources/localization/strings_de.properties	Sun Jan 08 19:32:11 2023 +0100
@@ -86,11 +86,11 @@
 issue.created=Erstellt
 issue.description=Beschreibung
 issue.eta=Zieldatum
-issue.filter=Filter
+issue.filter=Filter und Sortierung
 issue.filter.blocking=zeige nur blockierende
 issue.filter.done=zeige erledigte
 issue.filter.mine=nur mir zugewiesene
-issue.filter.more=mehr Filter
+issue.filter.more=mehr Filter und Sortieroptionen
 issue.id=Vorgangs-ID
 issue.relations=Beziehungen
 issue.relations.issue=Vorgang
@@ -178,3 +178,8 @@
 version=Version
 issue.relations.type.DefectOf.rev=Fehler
 issue.relations.type.DefectOf=Fehler von
+issue.filter.sort.primary=Prim\u00e4re Sortierung
+issue.filter.sort.secondary=Sekund\u00e4re Sortierung
+issue.filter.sort.tertiary=Terti\u00e4re Sortierung
+issue.filter.sort.done=erledigt
+issue.filter.sort.phase=Phase
--- a/src/main/webapp/WEB-INF/changelogs/changelog-de.jspf	Sun Jan 08 17:57:05 2023 +0100
+++ b/src/main/webapp/WEB-INF/changelogs/changelog-de.jspf	Sun Jan 08 19:32:11 2023 +0100
@@ -32,7 +32,7 @@
     <li>Mehrfachauswahl für Versionen im Vorgang entfernt.</li>
     <li>RSS Feeds für Projekte hinzugefügt.</li>
     <li>Vorgangsansicht vereinfacht.</li>
-    <li>Filteroptionen hinzugefügt.</li>
+    <li>Filter- und Sortieroptionen hinzugefügt.</li>
     <li>Möglichkeit zum Deaktivieren einer Komponente hinzugefügt.</li>
     <li>Datum der Veröffentlichung und des Supportendes zu Versionen hinzugefügt.</li>
     <li>Gesamtanzahl der Kommentare wird nun angezeigt.</li>
--- a/src/main/webapp/WEB-INF/changelogs/changelog.jspf	Sun Jan 08 17:57:05 2023 +0100
+++ b/src/main/webapp/WEB-INF/changelogs/changelog.jspf	Sun Jan 08 19:32:11 2023 +0100
@@ -32,7 +32,7 @@
     <li>Remove multi selection of versions within an issue.</li>
     <li>Add RSS feeds for projects.</li>
     <li>Simplify issue view.</li>
-    <li>Add filtering options.</li>
+    <li>Add filtering and sorting options.</li>
     <li>Add possibility to deactivate a component.</li>
     <li>Add release and end of life dates to versions.</li>
     <li>Add the total number of comments to the caption.</li>
--- a/src/main/webapp/WEB-INF/jspf/issue-filter.jspf	Sun Jan 08 17:57:05 2023 +0100
+++ b/src/main/webapp/WEB-INF/jspf/issue-filter.jspf	Sun Jan 08 19:32:11 2023 +0100
@@ -1,6 +1,3 @@
-<%--
-
---%>
 <form method="GET" id="filter-form">
     <div>
         <label>
@@ -53,6 +50,15 @@
                 </c:forEach>
             </select>
         </div>
+        <c:set var="sortPriority" value="primary"/>
+        <c:set var="currentSort" value="${viewmodel.filter.sortPrimary}"/>
+        <%@include file="sort-box.jspf"%>
+        <c:set var="sortPriority" value="secondary"/>
+        <c:set var="currentSort" value="${viewmodel.filter.sortSecondary}"/>
+        <%@include file="sort-box.jspf"%>
+        <c:set var="sortPriority" value="tertiary"/>
+        <c:set var="currentSort" value="${viewmodel.filter.sortTertiary}"/>
+        <%@include file="sort-box.jspf"%>
     </div>
     <div class="medskip">
         <button name="filter" type="submit"><fmt:message key="button.apply"/></button>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/main/webapp/WEB-INF/jspf/sort-box.jspf	Sun Jan 08 19:32:11 2023 +0100
@@ -0,0 +1,17 @@
+<%--
+Page attribute:
+  sortPriority: String
+  currentSort: IssueSorter.Criteria
+--%>
+<div style="display: inline-block">
+    <label class="caption" style="display:block;" for="sort_${sortPriority}"><fmt:message key="issue.filter.sort.${sortPriority}"/></label>
+    <select id="sort_${sortPriority}" name="sort_${sortPriority}">
+        <c:forEach var="criteria" items="${viewmodel.filter.sortCriteria}">
+            <option value="${criteria}" <c:if test="${currentSort eq criteria}">selected</c:if> >
+                <fmt:message key="${criteria.field.resourceKey}"/>
+                <c:if test="${criteria.asc}">&uarr;</c:if>
+                <c:if test="${not criteria.asc}">&darr;</c:if>
+            </option>
+        </c:forEach>
+    </select>
+</div>

mercurial