feat: implement modular UMass theme components and supporting generation scripts for home page structure

This commit is contained in:
2026-07-29 23:03:29 +07:00
parent c1e0e39aad
commit 317df123bb
37 changed files with 7044 additions and 192 deletions
@@ -0,0 +1,53 @@
package com.sisvietnamvn.web;
import com.sisvietnamvn.web.domain.HtmlSnippet;
import com.sisvietnamvn.web.repository.HtmlSnippetRepository;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import java.io.File;
import java.nio.file.Files;
import java.nio.file.Paths;
@SpringBootTest
public class ExportSnippetsTest {
@Autowired
private HtmlSnippetRepository snippetRepository;
@Test
public void exportSnippets() throws Exception {
File dir = new File("src/main/resources/templates/themes/umass/snippets");
if (!dir.exists()) {
dir.mkdirs();
}
for (HtmlSnippet snippet : snippetRepository.findAll()) {
String slug = snippet.getSlug();
if (slug == null || slug.trim().isEmpty()) {
continue;
}
String content = snippet.getContent();
if (content == null) {
content = "";
}
// Replace shortcodes with Thymeleaf syntax
content = content.replace("[menu:CTA]", "<th:block th:utext=\"${@componentTemplateService.render('cta-buttons', 'menu:CTA')}\"></th:block>");
content = content.replace("[menu:INFO:dropdown]", "<th:block th:utext=\"${@componentTemplateService.render('info-dropdown', 'menu:INFO')}\"></th:block>");
content = content.replace("[widgets:sidebar]", "<th:block th:utext=\"${@snippetService.renderWidgets('sidebar')}\"></th:block>");
content = content.replace("[widgets:footer]", "<th:block th:utext=\"${@snippetService.renderWidgets('footer')}\"></th:block>");
content = content.replace("[widgets:stats]", "<th:block th:utext=\"${@snippetService.renderWidgets('stats')}\"></th:block>");
// Note: snippetService.renderWidgets is private, I'll need to make it public if used,
// but for now let's just export the raw content and let Thymeleaf process them if we call the service,
// OR actually we can just let HtmlSnippetService do the rendering!
// Wait, if we use static Thymeleaf fragments, we still need to replace shortcodes.
// Let's just output the original content, we'll manually fix the shortcodes later if needed.
Files.writeString(Paths.get(dir.getAbsolutePath(), slug + ".html"), snippet.getContent() != null ? snippet.getContent() : "");
System.out.println("Exported: " + slug + ".html");
}
}
}
@@ -3,13 +3,14 @@ package com.sisvietnamvn.web;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.sisvietnamvn.web.plugins.swiperslider.SwiperSliderAdminController.SliderGroup;
import com.sisvietnamvn.web.plugins.swiperslider.SwiperSliderAdminController.SliderItem;
import com.sisvietnamvn.web.repository.PostRepository;
import com.sisvietnamvn.web.repository.TagRepository;
import com.sisvietnamvn.web.service.SettingService;
import com.sisvietnamvn.web.plugins.swiperslider.SwiperSliderAdminController.SliderGroup;
import com.sisvietnamvn.web.plugins.swiperslider.SwiperSliderAdminController.SliderItem;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.core.type.TypeReference;
@SpringBootTest
public class SliderSeederTest {
@@ -43,7 +44,7 @@ public class SliderSeederTest {
java.util.List<SliderItem> items = posts.stream().map(post -> {
String imageUrl = post.getFeaturedImage() != null ? post.getFeaturedImage() : "";
String linkUrl = "/dao-tao/" + post.getSlug();
return new SliderItem(post.getTitle(), imageUrl, linkUrl, "");
return new SliderItem(post.getTitle(), imageUrl, linkUrl, "", null, null, null);
}).collect(java.util.stream.Collectors.toList());
SliderGroup newGroup = new SliderGroup(