[T16] Export to CSV (5 doi tuong) - #3
Merged
Conversation
- ClientTeamService: list team phan trang, dem thanh vien theo team, chi tiet team
- ClientTeamController: GET /teams + GET /teams/{id}
- Templates client/teams/list.html (card grid + pagination) + detail.html (members + projects)
- TeamRepository.findWithLeaderById @EntityGraph(leader)
- UserRepository.findByTeamIdOrderByNameAsc @EntityGraph(position) + countGroupedByTeam
- Navbar: link Teams -> /teams
Verified: list 2 teams + member count; detail hien members/projects dung; anon -> login
Co-authored-by: Cursor <cursoragent@cursor.com>
[T13] Client: List all teams (pagination + members)
- ClientMemberController: GET /teams/{teamId}/members (phan trang) + GET /members/{id} (profile cong khai)
- ClientTeamService.getMembers(teamId, Pageable)
- UserRepository.findByTeamId(Long, Pageable) @EntityGraph(position)
- Templates: client/teams/members.html + client/members/profile.html
- Team detail: ten thanh vien link sang /members/{id} + nut "Xem tat ca"
Verified: list phan trang, profile thanh vien (info/projects/skills), anon -> login
Co-authored-by: Cursor <cursoragent@cursor.com>
[T14] Client: List members in a team (pagination + profile)
- CsvUtil: sinh CSV RFC4180 (escape, CRLF, BOM UTF-8)
- CsvExportService: export Users(+skills)/Positions/Skills/Teams/Projects(+members)
- AdminExportController GET /admin/export/{entity}.csv (text/csv; attachment)
- Nut Export CSV tren 5 trang list admin
Verified: 5 file 200 + text/csv UTF-8 + BOM + header dung; USER 403
Co-authored-by: Cursor <cursoragent@cursor.com>
There was a problem hiding this comment.
Pull request overview
This PR adds CSV export capabilities for multiple admin-managed entities (via new controller/service/util) and wires the export actions into the admin list pages. It also introduces a client-facing Teams browsing flow (navbar link + new client controllers/templates).
Changes:
- Add CSV generation utility and export service for Users/Positions/Skills/Teams/Projects, and expose them via
/admin/export/*.csv. - Add Export CSV buttons to 5 admin list pages.
- Add client Teams navigation + pages (teams list/detail/members) and member profile page.
Reviewed changes
Copilot reviewed 18 out of 18 changed files in this pull request and generated 6 comments.
Show a summary per file
| File | Description |
|---|---|
| src/main/resources/templates/fragments/client-navbar.html | Enables client Teams navigation link. |
| src/main/resources/templates/client/teams/members.html | New client page: paginated team members list. |
| src/main/resources/templates/client/teams/list.html | New client page: teams listing with member counts. |
| src/main/resources/templates/client/teams/detail.html | New client page: team detail with members/projects preview. |
| src/main/resources/templates/client/members/profile.html | New client page: member profile (projects + skills). |
| src/main/resources/templates/admin/users/list.html | Adds Export CSV button for users. |
| src/main/resources/templates/admin/teams/list.html | Adds Export CSV button for teams. |
| src/main/resources/templates/admin/skills/list.html | Adds Export CSV button for skills. |
| src/main/resources/templates/admin/projects/list.html | Adds Export CSV button for projects. |
| src/main/resources/templates/admin/positions/list.html | Adds Export CSV button for positions. |
| src/main/java/com/slearn/membermanagement/util/CsvUtil.java | New CSV builder (BOM + CRLF + escaping). |
| src/main/java/com/slearn/membermanagement/service/CsvExportService.java | New export service building CSV for 5 entities. |
| src/main/java/com/slearn/membermanagement/service/ClientTeamService.java | New client service for teams, members, projects, member counts. |
| src/main/java/com/slearn/membermanagement/repository/UserRepository.java | Adds entity graphs + grouped count query for team member counts. |
| src/main/java/com/slearn/membermanagement/repository/TeamRepository.java | Adds entity graph query for fetching team + leader by id. |
| src/main/java/com/slearn/membermanagement/controller/ClientTeamController.java | New client controller for teams list/detail. |
| src/main/java/com/slearn/membermanagement/controller/ClientMemberController.java | New client controller for team members list + member profile. |
| src/main/java/com/slearn/membermanagement/controller/admin/AdminExportController.java | New admin controller exposing CSV download endpoints. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Comment on lines
+37
to
+44
| private static String escape(String value) { | ||
| String v = (value == null) ? "" : value; | ||
| boolean mustQuote = v.contains(",") || v.contains("\"") || v.contains("\n") || v.contains("\r"); | ||
| if (mustQuote) { | ||
| return "\"" + v.replace("\"", "\"\"") + "\""; | ||
| } | ||
| return v; | ||
| } |
Comment on lines
+102
to
+115
| @Transactional(readOnly = true) | ||
| public String exportTeams() { | ||
| List<List<String>> rows = new ArrayList<>(); | ||
| for (Team t : teamRepository.findAll(BY_ID)) { | ||
| rows.add(List.of( | ||
| str(t.getId()), | ||
| nz(t.getName()), | ||
| nz(t.getDescription()), | ||
| t.getLeader() != null ? nz(t.getLeader().getName()) : "", | ||
| str(userRepository.countByTeamId(t.getId())) | ||
| )); | ||
| } | ||
| return CsvUtil.build(List.of("ID", "Name", "Description", "Leader", "MemberCount"), rows); | ||
| } |
|
|
||
| import com.slearn.membermanagement.entity.Position; | ||
| import com.slearn.membermanagement.entity.Project; | ||
| import com.slearn.membermanagement.entity.ProjectMember; |
Comment on lines
22
to
25
| @Override | ||
| @EntityGraph(attributePaths = {"team", "position"}) | ||
| Page<User> findAll(Pageable pageable); | ||
|
|
Comment on lines
13
to
15
| @Override | ||
| @EntityGraph(attributePaths = "leader") | ||
| Page<Team> findAll(Pageable pageable); |
| </li> | ||
| <li class="nav-item"> | ||
| <a class="nav-link" href="#" | ||
| <a class="nav-link" th:href="@{/teams}" |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Mục tiêu
Export dữ liệu ra CSV (UTF-8) cho 5 đối tượng: User (kèm skills), Position, Skill, Team, Project (kèm members).
Thay đổi
CsvUtil: sinh CSV theo RFC 4180 (escape, " \n), CRLF, BOM UTF-8.CsvExportService:exportUsers/Positions/Skills/Teams/Projects(readOnly tx; gom skills/members bằng group-by tránh N+1).AdminExportController:GET /admin/export/{entity}.csv→text/csv; charset=UTF-8+Content-Disposition: attachment.Kiểm thử (đã verify)
/admin/export/users.csv/admin/export/positions.csv/admin/export/skills.csv/admin/export/teams.csv/admin/export/projects.csvtext/csv; charset=UTF-8, BOMefbbbf, attachmentDoD
✅ Tải về được CSV đúng dữ liệu cho 5 đối tượng, UTF-8 hiển thị tiếng Việt chuẩn.