diff --git a/sisvietnamvn_main/html_snippets/content_main_blocks/temp b/sisvietnamvn_main/html_snippets/content_main_blocks/temp index bae56d4d..2f60aca7 100644 --- a/sisvietnamvn_main/html_snippets/content_main_blocks/temp +++ b/sisvietnamvn_main/html_snippets/content_main_blocks/temp @@ -1,172 +1,264 @@ - + + +
+ +
+

+ LATEST NEWS +

+ +
+
+ + + +
+
+ + + +
+
+
+ +
+

+ Events +

+ +
+
JUL
18
10:00 am – 12:00 pm
UMass Downtown
JUL
20
10:00 am – 4:00 pm
UMass Downtown
JUL
21
JUL
21
5:00 pm – 6:00 pm
Orchard Hill Pavilion
+
+
+ +
+ + + + + \ No newline at end of file diff --git a/sisvietnamvn_main/html_snippets/content_main_blocks/temp_2 b/sisvietnamvn_main/html_snippets/content_main_blocks/temp_2 new file mode 100644 index 00000000..8d2d84a0 --- /dev/null +++ b/sisvietnamvn_main/html_snippets/content_main_blocks/temp_2 @@ -0,0 +1,37 @@ +
+
+ + +
+ +
+

+ TIN TỨC MỚI +

+
+ + [component:news-grid data-source="posts:tag=news,limit=2,collection=news_posts"] +
+
+ +
+

+ SỰ KIỆN +

+
+ + [component:events-list data-source="posts:tag=event,limit=4,collection=event_posts"] +
+
+ +
+ + + + +
+
\ No newline at end of file diff --git a/sisvietnamvn_main/html_snippets/content_main_blocks/temp_clean.html b/sisvietnamvn_main/html_snippets/content_main_blocks/temp_clean.html new file mode 100644 index 00000000..b3cdbd39 --- /dev/null +++ b/sisvietnamvn_main/html_snippets/content_main_blocks/temp_clean.html @@ -0,0 +1,264 @@ +
+
+ + +
+

+ NEWS & EVENTS +

+ + + More News & Events + +
+ +

+ FEATURED ARTICLES +

+ + + +
+ +
+

+ LATEST NEWS +

+ +
+
+ + + +
+
+ + + +
+
+
+ +
+

+ Events +

+ +
+
JUL
18
10:00 am – 12:00 pm
UMass Downtown
JUL
20
10:00 am – 4:00 pm
UMass Downtown
JUL
21
JUL
21
5:00 pm – 6:00 pm
Orchard Hill Pavilion
+
+
+ +
+ + + + +
\ No newline at end of file diff --git a/sisvietnamvn_main/src/main/java/com/sisvietnamvn/web/controller/manage/ManagePostController.java b/sisvietnamvn_main/src/main/java/com/sisvietnamvn/web/controller/manage/ManagePostController.java index d7861cf6..b37435da 100644 --- a/sisvietnamvn_main/src/main/java/com/sisvietnamvn/web/controller/manage/ManagePostController.java +++ b/sisvietnamvn_main/src/main/java/com/sisvietnamvn/web/controller/manage/ManagePostController.java @@ -53,13 +53,16 @@ public class ManagePostController { } /** - * GET /manage/posts — List all posts with optional filters. + * GET /manage/posts — List all posts with optional filters, search, and pagination. */ @GetMapping public String listPosts(@RequestParam(value = "categoryId", required = false) Long categoryId, @RequestParam(value = "status", required = false) String statusStr, + @RequestParam(value = "search", required = false) String search, + @RequestParam(value = "page", defaultValue = "0") int page, + @RequestParam(value = "size", defaultValue = "10") int size, Model model) { - LOG.debug("Request to list all posts (categoryId={}, status={})", categoryId, statusStr); + LOG.debug("Request to list all posts (categoryId={}, status={}, search={}, page={}, size={})", categoryId, statusStr, search, page, size); PageStatus status = null; if (statusStr != null && !statusStr.isBlank()) { @@ -70,11 +73,17 @@ public class ManagePostController { } } - model.addAttribute("posts", postService.findFiltered(categoryId, status)); + org.springframework.data.domain.Pageable pageable = org.springframework.data.domain.PageRequest.of(page, size, org.springframework.data.domain.Sort.by("createdDate").descending()); + org.springframework.data.domain.Page postPage = postService.findFilteredAndSearch(categoryId, status, search, pageable); + + model.addAttribute("postPage", postPage); + model.addAttribute("posts", postPage.getContent()); model.addAttribute("categories", categoryService.findAll()); model.addAttribute("statuses", PageStatus.values()); model.addAttribute("selectedCategoryId", categoryId); model.addAttribute("selectedStatus", statusStr); + model.addAttribute("selectedSearch", search); + model.addAttribute("pageSize", size); return "manage/posts/list"; } diff --git a/sisvietnamvn_main/src/main/java/com/sisvietnamvn/web/repository/PostRepository.java b/sisvietnamvn_main/src/main/java/com/sisvietnamvn/web/repository/PostRepository.java index 2ac73a88..cb0f45d7 100644 --- a/sisvietnamvn_main/src/main/java/com/sisvietnamvn/web/repository/PostRepository.java +++ b/sisvietnamvn_main/src/main/java/com/sisvietnamvn/web/repository/PostRepository.java @@ -82,4 +82,16 @@ public interface PostRepository extends JpaRepository { */ @Query("SELECT p FROM Post p JOIN p.tags t WHERE t.id = :tagId ORDER BY p.createdDate DESC") List findByTagId(@Param("tagId") Long tagId, org.springframework.data.domain.Pageable pageable); + + /** + * Find posts with filters, search text, and pagination. + */ + @org.springframework.data.jpa.repository.EntityGraph(attributePaths = {"category"}) + @Query("SELECT p FROM Post p WHERE (:categoryId IS NULL OR p.category.id = :categoryId) " + + "AND (:status IS NULL OR p.status = :status) " + + "AND (:search IS NULL OR LOWER(p.title) LIKE LOWER(:search) OR LOWER(p.excerpt) LIKE LOWER(:search))") + org.springframework.data.domain.Page findFilteredAndSearch(@Param("categoryId") Long categoryId, + @Param("status") PageStatus status, + @Param("search") String search, + org.springframework.data.domain.Pageable pageable); } diff --git a/sisvietnamvn_main/src/main/java/com/sisvietnamvn/web/service/ComponentTemplateService.java b/sisvietnamvn_main/src/main/java/com/sisvietnamvn/web/service/ComponentTemplateService.java index a17d4b59..217b6dcc 100644 --- a/sisvietnamvn_main/src/main/java/com/sisvietnamvn/web/service/ComponentTemplateService.java +++ b/sisvietnamvn_main/src/main/java/com/sisvietnamvn/web/service/ComponentTemplateService.java @@ -217,7 +217,18 @@ public class ComponentTemplateService { for (com.sisvietnamvn.web.domain.Post post : posts) { String itemHtml = loopBody; String safeTitle = post.getTitle() != null ? org.springframework.web.util.HtmlUtils.htmlEscape(post.getTitle()) : ""; - String safeExcerpt = post.getExcerpt() != null ? org.springframework.web.util.HtmlUtils.htmlEscape(post.getExcerpt()) : ""; + String rawExcerpt = post.getExcerpt(); + if (rawExcerpt == null || rawExcerpt.trim().isEmpty()) { + rawExcerpt = post.getMetaDescription(); + } + if (rawExcerpt == null || rawExcerpt.trim().isEmpty()) { + String rawContent = post.getContent(); + if (rawContent != null) { + rawContent = rawContent.replaceAll("<[^>]*>", " ").replaceAll("\\s+", " ").trim(); + rawExcerpt = rawContent.length() > 150 ? rawContent.substring(0, 150) + "..." : rawContent; + } + } + String safeExcerpt = rawExcerpt != null ? org.springframework.web.util.HtmlUtils.htmlEscape(rawExcerpt) : ""; itemHtml = itemHtml.replace("{{title}}", safeTitle); itemHtml = itemHtml.replace("{{slug}}", post.getSlug() != null ? post.getSlug() : ""); @@ -275,13 +286,16 @@ public class ComponentTemplateService { Optional existing = templateRepository.findBySlug("news-grid"); if (existing.isPresent()) { ComponentTemplate t = existing.get(); - if (t.getHtmlTemplate() == null || !t.getHtmlTemplate().contains("