diff --git a/.vscode/launch.json b/.vscode/launch.json index 5d0503b3..a1f46aac 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -7,6 +7,7 @@ "request": "launch", "mainClass": "com.sisvietnamvn.web.SisvietnamvnApp", "projectName": "sisvietnamvn", + "cwd": "${workspaceFolder}/sisvietnamvn_main", "vmArgs": "-Dspring.profiles.active=dev" }, { diff --git a/sisvietnamvn_main/.gitignore b/sisvietnamvn_main/.gitignore index c336dd0c..52763d99 100644 --- a/sisvietnamvn_main/.gitignore +++ b/sisvietnamvn_main/.gitignore @@ -151,3 +151,9 @@ Desktop.ini ###################### coverage/ .nyc_output/ + +###################### +# Database +###################### +src/main/docker/oracle-data/ + diff --git a/sisvietnamvn_main/gradlew b/sisvietnamvn_main/gradlew old mode 100644 new mode 100755 diff --git a/sisvietnamvn_main/src/main/java/com/sisvietnamvn/web/config/SecurityConfiguration.java b/sisvietnamvn_main/src/main/java/com/sisvietnamvn/web/config/SecurityConfiguration.java index e98db2cf..33ad11e9 100644 --- a/sisvietnamvn_main/src/main/java/com/sisvietnamvn/web/config/SecurityConfiguration.java +++ b/sisvietnamvn_main/src/main/java/com/sisvietnamvn/web/config/SecurityConfiguration.java @@ -46,7 +46,8 @@ public class SecurityConfiguration { authz .requestMatchers(HttpMethod.GET, "/", "/about", "/flex-finish", "/tin-tuc", "/tin-tuc/**", "/lien-he", "/manage/**", "/css/**", "/images/**", "/js/**", "/UMass*/**", "/Undergraduate*/**", - "/favicon.ico", "/favicons/**", "/flex-finish/**", "/contact-us/**", "/uploads/**", "/api/manage/snippets/**", "/page/**") + "/favicon.ico", "/favicons/**", "/flex-finish/**", "/contact-us/**", "/uploads/**", "/api/manage/snippets/**", "/page/**", + "/about-us", "/specialty", "/doctor", "/service", "/health-library", "/news-and-events", "/patient-support", "/medical-expert", "/umcers", "/bidding", "/contact-us") .permitAll() .requestMatchers(HttpMethod.POST, "/manage/**", "/api/manage/media/upload").permitAll() .requestMatchers(HttpMethod.GET, "/swagger-ui/**", "/v3/api-docs/**").permitAll() diff --git a/sisvietnamvn_main/src/main/java/com/sisvietnamvn/web/controller/HomeController.java b/sisvietnamvn_main/src/main/java/com/sisvietnamvn/web/controller/HomeController.java index cc530d03..c923f71f 100644 --- a/sisvietnamvn_main/src/main/java/com/sisvietnamvn/web/controller/HomeController.java +++ b/sisvietnamvn_main/src/main/java/com/sisvietnamvn/web/controller/HomeController.java @@ -6,8 +6,9 @@ import org.springframework.web.bind.annotation.GetMapping; @Controller public class HomeController { + @GetMapping("/") - public String home() { + public String index() { return "index"; } @@ -20,17 +21,17 @@ public class HomeController { // Trang Giới thiệu Bệnh viện @GetMapping("/about") public String about() { - return "about"; + return "redirect:/about-us"; } // Trang Tin tức @GetMapping("/tin-tuc") public String tintuc() { - return "tin-tuc"; + return "redirect:/news-and-events"; } @GetMapping("/lien-he") public String lienhe() { - return "lien-he"; + return "redirect:/contact-us"; } } diff --git a/sisvietnamvn_main/src/main/java/com/sisvietnamvn/web/controller/PageController.java b/sisvietnamvn_main/src/main/java/com/sisvietnamvn/web/controller/PageController.java index c85faaa5..19fb9c9e 100644 --- a/sisvietnamvn_main/src/main/java/com/sisvietnamvn/web/controller/PageController.java +++ b/sisvietnamvn_main/src/main/java/com/sisvietnamvn/web/controller/PageController.java @@ -43,15 +43,48 @@ public class PageController { @GetMapping("/page/{slug}") public String getPage(@PathVariable("slug") String slug, Model model) { LOG.debug("REST request to get public Page : {}", slug); - - Optional pageOpt = pageService.findBySlug(slug); - + return renderPage(pageService.findBySlug(slug), model); + } + + + @GetMapping("/about-us") + public String getAboutUs(Model model) { return renderPage(pageService.findByPageType(com.sisvietnamvn.web.domain.PageType.ABOUT_US), model); } + + @GetMapping("/specialty") + public String getSpecialty(Model model) { return renderPage(pageService.findByPageType(com.sisvietnamvn.web.domain.PageType.SPECIALTY), model); } + + @GetMapping("/doctor") + public String getDoctor(Model model) { return renderPage(pageService.findByPageType(com.sisvietnamvn.web.domain.PageType.DOCTOR), model); } + + @GetMapping("/service") + public String getService(Model model) { return renderPage(pageService.findByPageType(com.sisvietnamvn.web.domain.PageType.SERVICE), model); } + + @GetMapping("/health-library") + public String getHealthLibrary(Model model) { return renderPage(pageService.findByPageType(com.sisvietnamvn.web.domain.PageType.HEALTH_LIBRARY), model); } + + @GetMapping("/news-and-events") + public String getNewsAndEvents(Model model) { return renderPage(pageService.findByPageType(com.sisvietnamvn.web.domain.PageType.NEWS_AND_EVENTS), model); } + + @GetMapping("/patient-support") + public String getPatientSupport(Model model) { return renderPage(pageService.findByPageType(com.sisvietnamvn.web.domain.PageType.PATIENT_SUPPORT), model); } + + @GetMapping("/medical-expert") + public String getMedicalExpert(Model model) { return renderPage(pageService.findByPageType(com.sisvietnamvn.web.domain.PageType.MEDICAL_EXPERT), model); } + + @GetMapping("/umcers") + public String getUmcers(Model model) { return renderPage(pageService.findByPageType(com.sisvietnamvn.web.domain.PageType.UMCERS), model); } + + @GetMapping("/bidding") + public String getBidding(Model model) { return renderPage(pageService.findByPageType(com.sisvietnamvn.web.domain.PageType.BIDDING), model); } + + @GetMapping("/contact-us") + public String getContactUs(Model model) { return renderPage(pageService.findByPageType(com.sisvietnamvn.web.domain.PageType.CONTACT_US), model); } + + private String renderPage(Optional pageOpt, Model model) { if (pageOpt.isEmpty()) { throw new ResponseStatusException(HttpStatus.NOT_FOUND, "Page not found"); } - Page page = pageOpt.get(); - // Security Check: If Draft, only Admins can view if ("DRAFT".equals(page.getStatus()) && !SecurityUtils.hasCurrentUserThisAuthority(AuthoritiesConstants.ADMIN)) { throw new ResponseStatusException(HttpStatus.NOT_FOUND, "Page not found"); @@ -61,19 +94,17 @@ public class PageController { List> blocks = Collections.emptyList(); if (page.getContent() != null && !page.getContent().trim().isEmpty()) { try { - // Editor.js JSON has a "blocks" array at the root level Map editorData = objectMapper.readValue(page.getContent(), new TypeReference<>() {}); if (editorData.containsKey("blocks")) { blocks = (List>) editorData.get("blocks"); } } catch (JsonProcessingException e) { - LOG.error("Failed to parse Editor.js JSON for page slug: {}", slug, e); + LOG.error("Failed to parse Editor.js JSON for page ID: {}", page.getId(), e); } } model.addAttribute("page", page); model.addAttribute("blocks", blocks); - return "page"; } } diff --git a/sisvietnamvn_main/src/main/java/com/sisvietnamvn/web/controller/manage/ManagePageController.java b/sisvietnamvn_main/src/main/java/com/sisvietnamvn/web/controller/manage/ManagePageController.java index b4325f6a..7e7fd92c 100644 --- a/sisvietnamvn_main/src/main/java/com/sisvietnamvn/web/controller/manage/ManagePageController.java +++ b/sisvietnamvn_main/src/main/java/com/sisvietnamvn/web/controller/manage/ManagePageController.java @@ -61,6 +61,7 @@ public class ManagePageController { page.setDisplayOrder(0); model.addAttribute("page", page); model.addAttribute("statuses", PageStatus.values()); + model.addAttribute("pageTypes", com.sisvietnamvn.web.domain.PageType.values()); model.addAttribute("isNew", true); return "manage/pages/form"; } @@ -76,6 +77,7 @@ public class ManagePageController { LOG.debug("Request to create Page : {}", page); if (bindingResult.hasErrors()) { model.addAttribute("statuses", PageStatus.values()); + model.addAttribute("pageTypes", com.sisvietnamvn.web.domain.PageType.values()); model.addAttribute("isNew", true); return "manage/pages/form"; } @@ -97,6 +99,7 @@ public class ManagePageController { } model.addAttribute("page", pageOptional.get()); model.addAttribute("statuses", PageStatus.values()); + model.addAttribute("pageTypes", com.sisvietnamvn.web.domain.PageType.values()); model.addAttribute("isNew", false); return "manage/pages/form"; } @@ -113,6 +116,7 @@ public class ManagePageController { LOG.debug("Request to update Page : {}", id); if (bindingResult.hasErrors()) { model.addAttribute("statuses", PageStatus.values()); + model.addAttribute("pageTypes", com.sisvietnamvn.web.domain.PageType.values()); model.addAttribute("isNew", false); return "manage/pages/form"; } diff --git a/sisvietnamvn_main/src/main/java/com/sisvietnamvn/web/domain/Page.java b/sisvietnamvn_main/src/main/java/com/sisvietnamvn/web/domain/Page.java index 3754258a..446bfacf 100644 --- a/sisvietnamvn_main/src/main/java/com/sisvietnamvn/web/domain/Page.java +++ b/sisvietnamvn_main/src/main/java/com/sisvietnamvn/web/domain/Page.java @@ -45,6 +45,11 @@ public class Page extends AbstractAuditingEntity { @Column(name = "status", length = 20, nullable = false) private PageStatus status = PageStatus.DRAFT; + @NotNull + @Enumerated(EnumType.STRING) + @Column(name = "page_type", length = 50, nullable = false) + private PageType pageType = PageType.CUSTOM; + @Column(name = "display_order") private Integer displayOrder = 0; @@ -99,6 +104,14 @@ public class Page extends AbstractAuditingEntity { this.status = status; } + public PageType getPageType() { + return pageType; + } + + public void setPageType(PageType pageType) { + this.pageType = pageType; + } + public Integer getDisplayOrder() { return displayOrder; } @@ -129,6 +142,7 @@ public class Page extends AbstractAuditingEntity { "id=" + getId() + ", title='" + getTitle() + "'" + ", slug='" + getSlug() + "'" + + ", pageType='" + getPageType() + "'" + ", status='" + getStatus() + "'" + ", displayOrder=" + getDisplayOrder() + "}"; diff --git a/sisvietnamvn_main/src/main/java/com/sisvietnamvn/web/domain/PageType.java b/sisvietnamvn_main/src/main/java/com/sisvietnamvn/web/domain/PageType.java new file mode 100644 index 00000000..241aec85 --- /dev/null +++ b/sisvietnamvn_main/src/main/java/com/sisvietnamvn/web/domain/PageType.java @@ -0,0 +1,21 @@ +package com.sisvietnamvn.web.domain; + +/** + * The PageType enumeration. + * Specifies the template or system location that a CMS page belongs to. + */ +public enum PageType { + HOME, + ABOUT_US, + SPECIALTY, + DOCTOR, + SERVICE, + HEALTH_LIBRARY, + NEWS_AND_EVENTS, + PATIENT_SUPPORT, + MEDICAL_EXPERT, + UMCERS, + BIDDING, + CONTACT_US, + CUSTOM +} diff --git a/sisvietnamvn_main/src/main/java/com/sisvietnamvn/web/repository/PageRepository.java b/sisvietnamvn_main/src/main/java/com/sisvietnamvn/web/repository/PageRepository.java index 7bc2314a..76af63bd 100644 --- a/sisvietnamvn_main/src/main/java/com/sisvietnamvn/web/repository/PageRepository.java +++ b/sisvietnamvn_main/src/main/java/com/sisvietnamvn/web/repository/PageRepository.java @@ -23,6 +23,11 @@ public interface PageRepository extends JpaRepository { */ Optional findBySlug(String slug); + /** + * Find a page by its predefined CMS Page Type. + */ + Optional findByPageType(com.sisvietnamvn.web.domain.PageType pageType); + /** * Find all pages with a given publication status. */ diff --git a/sisvietnamvn_main/src/main/java/com/sisvietnamvn/web/service/PageService.java b/sisvietnamvn_main/src/main/java/com/sisvietnamvn/web/service/PageService.java index 6055012e..92c77028 100644 --- a/sisvietnamvn_main/src/main/java/com/sisvietnamvn/web/service/PageService.java +++ b/sisvietnamvn_main/src/main/java/com/sisvietnamvn/web/service/PageService.java @@ -61,6 +61,15 @@ public class PageService { return pageRepository.findBySlug(slug); } + /** + * Get a single page by its predefined CMS Page Type. + */ + @Transactional(readOnly = true) + public Optional findByPageType(com.sisvietnamvn.web.domain.PageType pageType) { + LOG.debug("Request to get Page by type : {}", pageType); + return pageRepository.findByPageType(pageType); + } + /** * Find all pages with a specific status. */ diff --git a/sisvietnamvn_main/src/main/resources/config/liquibase/changelog/20260625120000_add_page_type.xml b/sisvietnamvn_main/src/main/resources/config/liquibase/changelog/20260625120000_add_page_type.xml new file mode 100644 index 00000000..679e4a45 --- /dev/null +++ b/sisvietnamvn_main/src/main/resources/config/liquibase/changelog/20260625120000_add_page_type.xml @@ -0,0 +1,15 @@ + + + + + + + + + + + + diff --git a/sisvietnamvn_main/src/main/resources/config/liquibase/master.xml b/sisvietnamvn_main/src/main/resources/config/liquibase/master.xml index 2f2497d0..5a3943d1 100644 --- a/sisvietnamvn_main/src/main/resources/config/liquibase/master.xml +++ b/sisvietnamvn_main/src/main/resources/config/liquibase/master.xml @@ -20,6 +20,7 @@ + diff --git a/sisvietnamvn_main/src/main/resources/templates/fragments/layout.html b/sisvietnamvn_main/src/main/resources/templates/fragments/layout.html index fa545668..792b36c7 100644 --- a/sisvietnamvn_main/src/main/resources/templates/fragments/layout.html +++ b/sisvietnamvn_main/src/main/resources/templates/fragments/layout.html @@ -21,13 +21,9 @@ -
-
- +
- -
\ No newline at end of file diff --git a/sisvietnamvn_main/src/main/resources/templates/manage/pages/form.html b/sisvietnamvn_main/src/main/resources/templates/manage/pages/form.html index eddec91e..5f13678b 100644 --- a/sisvietnamvn_main/src/main/resources/templates/manage/pages/form.html +++ b/sisvietnamvn_main/src/main/resources/templates/manage/pages/form.html @@ -117,8 +117,19 @@
+ +
+
+ + +
+
+ -
+
@@ -129,7 +140,7 @@
-
+
- +
- - - - - -
+ + + +
+
+ + + + +

+

+

+

+
+
+

- - - - -
- -

-

-

-

-
-
-

-
-
-
- - - -
-

-
-
- - - -
-
    -
  • -
-
    -
  1. -
-
-
- - - -
- -

-
-
- - - -
-
-

-
-
-
-
- - - -
- *** -
-
- - - -
- - - - - - - - - - - - -
-
-
-
+ + +

+
+ + + +
    +
  • +
+
    +
  1. +
+
+ + + + +

+
+ + + +
+

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