#1
Now that pagination and audit logs are working, let’s add filtering and sorting features. These will make the dashboard more powerful and user-friendly

1. Extend the Repository with Sorting and Filtering

Spring Data JPA provides sorting and query methods automatically.
public interface UserRepository extends JpaRepository<User, Long> {
    Page<User> findByUsernameContainingIgnoreCase(String keyword, Pageable pageable);
}

This method will allow searching users by partial name, case-insensitive, and still use pagination.

2. Update the Service Layer

Add filtering and sorting options in your service:
@Service
public class DashboardService {
    @Autowired private UserRepository userRepo;
    @Autowired private AuditLogRepository logRepo;

    public Page<User> getUsers(String keyword, int page, int size, String sortField, String sortDir) {
        Sort sort = sortDir.equalsIgnoreCase("asc") ? 
                    Sort.by(sortField).ascending() : Sort.by(sortField).descending();
        Pageable pageable = PageRequest.of(page, size, sort);
        if (keyword != null && !keyword.isEmpty()) {
            return userRepo.findByUsernameContainingIgnoreCase(keyword, pageable);
        }
        return userRepo.findAll(pageable);
    }

    public void logAction(String action, String user) {
        AuditLog log = new AuditLog();
        log.setAction(action);
        log.setPerformedBy(user);
        log.setTimestamp(LocalDateTime.now());
        logRepo.save(log);
    }
}

3. Update the Controller

Let’s add query parameters for filtering and sorting.
@Controller
@RequestMapping("/dashboard")
public class DashboardController {
    @Autowired private DashboardService dashboardService;

    @GetMapping
    public String viewDashboard(
            @RequestParam(defaultValue = "") String keyword,
            @RequestParam(defaultValue = "username") String sortField,
            @RequestParam(defaultValue = "asc") String sortDir,
            @RequestParam(defaultValue = "0") int page,
            Model model) {

        Page<User> users = dashboardService.getUsers(keyword, page, 5, sortField, sortDir);

        model.addAttribute("users", users.getContent());
        model.addAttribute("currentPage", page);
        model.addAttribute("totalPages", users.getTotalPages());
        model.addAttribute("sortField", sortField);
        model.addAttribute("sortDir", sortDir);
        model.addAttribute("reverseSortDir", sortDir.equals("asc") ? "desc" : "asc");
        model.addAttribute("keyword", keyword);
        return "dashboard";
    }
}

4. Update the HTML Dashboard

Now enhance the dashboard with a search form and clickable sort links.
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
  <title>Dashboard</title>
</head>
<body>
<h2>User Dashboard</h2>

<form th:action="@{/dashboard}" method="get">
  <input type="text" name="keyword" placeholder="Search username..." th:value="${keyword}">
  <button type="submit">Search</button>
</form>

<table border="1">
<tr>
  <th><a th:href="@{/dashboard(sortField='username', sortDir=${reverseSortDir}, keyword=${keyword})}">Username</a></th>
  <th><a th:href="@{/dashboard(sortField='role', sortDir=${reverseSortDir}, keyword=${keyword})}">Role</a></th>
</tr>
<tr th:each="u : ${users}">
  <td th:text="${u.username}"></td>
  <td th:text="${u.role}"></td>
</tr>
</table>

<div>
  <a th:if="${currentPage > 0}" 
     th:href="@{/dashboard(page=${currentPage - 1}, keyword=${keyword}, sortField=${sortField}, sortDir=${sortDir})}">Prev</a>
  <span th:text="${currentPage + 1}"></span> /
  <span th:text="${totalPages}"></span>
  <a th:if="${currentPage + 1 < totalPages}" 
     th:href="@{/dashboard(page=${currentPage + 1}, keyword=${keyword}, sortField=${sortField}, sortDir=${sortDir})}">Next</a>
</div>
</body>
</html>

5. Test the Dashboard

Run your Spring Boot app again.
  • Try searching usernames with partial keywords.
  • Click column headers to sort ascending or descending.
  • Check pagination still works alongside search and sort.
  • All actions remain logged automatically in your AuditLog table.
#ads

image quote pre code