feat: add sorting

This commit is contained in:
Sergey Krylov 2026-03-09 11:46:01 +03:00
parent 73b6f86aab
commit 4a2f819dba
5 changed files with 142 additions and 9 deletions

View File

@ -4,11 +4,42 @@
<head> <head>
<title>Charm Profiles</title> <title>Charm Profiles</title>
<%@ include file="style.html" %> <%@ include file="style.html" %>
<c:url var="baseUrl" value="${requestScope['javax.servlet.forward.servlet_path']}">
<c:param name="emailStartWith" value="${filter.emailStartWith}"/>
<c:param name="nameStartWith" value="${filter.nameStartWith}"/>
<c:param name="surnameStartWith" value="${filter.surnameStartWith}"/>
<c:param name="status" value="${filter.status}"/>
<c:param name="gteAge" value="${filter.gteAge}"/>
<c:param name="ltAge" value="${filter.ltAge}"/>
<c:param name="sort" value="id"/>
</c:url>
<c:url var="sortUrlWithId" value="${baseUrl}">
<c:param name="sort" value="id"/>
</c:url>
<c:url var="sortUrlWithEmail" value="${baseUrl}">
<c:param name="sort" value="email"/>
</c:url>
<c:url var="sortUrlWithName" value="${baseUrl}">
<c:param name="sort" value="name"/>
</c:url>
<c:url var="sortUrlWithSurname" value="${baseUrl}">
<c:param name="sort" value="surname"/>
</c:url>
<c:url var="sortUrlWithAge" value="${baseUrl}">
<c:param name="sort" value="birth_date"/>
</c:url>
<c:url var="sortUrlWithStatus" value="${baseUrl}">
<c:param name="sort" value="status"/>
</c:url>
<c:url var="sortUrlWithRole" value="${baseUrl}">
<c:param name="sort" value="role"/>
</c:url>
</head> </head>
<body> <body>
<%@ include file="header.jsp" %> <%@ include file="header.jsp" %>
<div> <div>
<form action="/profiles" method="get"> <form action="/profiles" method="get">
<input type="hidden" name="sort" value="${filter.sort}">
<table> <table>
<tr class="hiddenRow"> <tr class="hiddenRow">
<td> <td>
@ -73,12 +104,76 @@
</form> </form>
<table> <table>
<tr> <tr>
<td><h3>id</h3></td> <td>
<td><h3>${wordBundle.getWord("email")}</h3></td> <a href="${sortUrlWithId}" class="hiddenLink">
<td><h3>${wordBundle.getWord("name")}</h3></td> <h3>
<td><h3>${wordBundle.getWord("surname")}</h3></td> id
<td><h3>${wordBundle.getWord("age")}</h3></td> <c:if test="${filter.sort == 'id' or filter.sort == null}">
<td><h3>${wordBundle.getWord("status")}</h3></td> ^
</c:if>
</h3>
</a>
</td>
<td>
<a href="${sortUrlWithEmail}" class="hiddenLink">
<h3>
${wordBundle.getWord("email")}
<c:if test="${filter.sort == 'email'}">
^
</c:if>
</h3>
</a>
</td>
<td>
<a href="${sortUrlWithName}" class="hiddenLink">
<h3>
${wordBundle.getWord("name")}
<c:if test="${filter.sort == 'name'}">
^
</c:if>
</h3>
</a>
</td>
<td>
<a href="${sortUrlWithSurname}" class="hiddenLink">
<h3>
${wordBundle.getWord("surname")}
<c:if test="${filter.sort == 'surname'}">
^
</c:if>
</h3>
</a>
</td>
<td>
<a href="${sortUrlWithAge}" class="hiddenLink">
<h3>
${wordBundle.getWord("age")}
<c:if test="${filter.sort == 'birth_date'}">
^
</c:if>
</h3>
</a>
</td>
<td>
<a href="${sortUrlWithStatus}" class="hiddenLink">
<h3>
${wordBundle.getWord("status")}
<c:if test="${filter.sort == 'status'}">
^
</c:if>
</h3>
</a>
</td>
<td>
<a href="${sortUrlWithRole}" class="hiddenLink">
<h3>
${wordBundle.getWord("role")}
<c:if test="${filter.sort == 'role'}">
^
</c:if>
</h3>
</a>
</td>
</tr> </tr>
<c:forEach var="profile" items="${profiles}"> <c:forEach var="profile" items="${profiles}">
<tr> <tr>
@ -104,9 +199,12 @@
</c:if> </c:if>
</c:forEach> </c:forEach>
</select> </select>
<button type="submit">${wordBundle.getWord("save")}</button> <c:if test="${profile.role != 'ADMIN'}">
<button type="submit">${wordBundle.getWord("save")}</button>
</c:if>
</form> </form>
</td> </td>
<td><h4>${profile.role}</h4></td>
</tr> </tr>
</c:forEach> </c:forEach>
</table> </table>

View File

@ -27,6 +27,7 @@ public class ProfileDao {
public static final String INSERT = "INSERT INTO profile (email, password) VALUES (?, ?)"; public static final String INSERT = "INSERT INTO profile (email, password) VALUES (?, ?)";
private static final ProfileDao INSTANCE = new ProfileDao(); private static final ProfileDao INSTANCE = new ProfileDao();
private Set<String> validColumns;
@SneakyThrows @SneakyThrows
public static ProfileDao getInstance() { public static ProfileDao getInstance() {
@ -85,7 +86,7 @@ public class ProfileDao {
.addStatus(filter.getStatus()) .addStatus(filter.getStatus())
.addLTAge(filter.getLtAge()) .addLTAge(filter.getLtAge())
.addGTEAge(filter.getGteAge()) .addGTEAge(filter.getGteAge())
.build(); .build(getValidSort(filter.getSort()));
try ( try (
Connection connection = ConnectionManager.getConnection(); Connection connection = ConnectionManager.getConnection();
@ -108,6 +109,30 @@ public class ProfileDao {
} }
} }
private String getValidSort(String sort) {
if (validColumns == null) {
validColumns = new HashSet<>();
try (Connection conn = getConnection();) {
ResultSet rs = conn.getMetaData().getColumns(null, null, "profile", null);
while(rs.next()) {
String comment = rs.getString("REMARKS");
if("sortable".equals(comment)) {
validColumns.add(rs.getString("COLUMN_NAME"));
}
}
} catch (SQLException e) {
throw new RuntimeException(e);
}
}
if (validColumns.contains(sort)) {
return sort;
} else {
return "id";
}
}
public void update(Profile profile) { public void update(Profile profile) {
Query query = new ProfileUpdateQueryBuilder() Query query = new ProfileUpdateQueryBuilder()
.addEmail(profile.getEmail()) .addEmail(profile.getEmail())

View File

@ -14,4 +14,5 @@ public class ProfileFilter {
Integer ltAge; Integer ltAge;
Integer gteAge; Integer gteAge;
Status status; Status status;
String sort;
} }

View File

@ -112,4 +112,9 @@ public class ProfileSelectQueryBuilder {
public Query build() { public Query build() {
return new Query(sb.toString(), args); return new Query(sb.toString(), args);
} }
public Query build(String sort) {
sb.append(" ORDER BY ").append(sort).append(" ASC");
return new Query(sb.toString(), args);
}
} }

View File

@ -49,6 +49,10 @@ public class RequestToProfileFilterMapper implements Mapper<HttpServletRequest,
Status status = isBlank(statusArg) ? null : Status.valueOf(statusArg); Status status = isBlank(statusArg) ? null : Status.valueOf(statusArg);
filter.setStatus(status); filter.setStatus(status);
return filter; String sortArg = req.getParameter("sort");
String sort = isBlank(sortArg) ? "id" : sortArg;
filter.setSort(sort);
return filter;
} }
} }