diff --git a/sisvietnamvn_main/CheckNewsGrid.java b/sisvietnamvn_main/CheckNewsGrid.java new file mode 100644 index 00000000..9380f1b3 --- /dev/null +++ b/sisvietnamvn_main/CheckNewsGrid.java @@ -0,0 +1,20 @@ +import java.sql.Connection; +import java.sql.DriverManager; +import java.sql.ResultSet; +import java.sql.Statement; + +public class CheckNewsGrid { + public static void main(String[] args) { + try { + Connection conn = DriverManager.getConnection("jdbc:oracle:thin:@localhost:1521/sisvietnam", "sisvietnam", "sisvietnam"); + Statement stmt = conn.createStatement(); + ResultSet rs = stmt.executeQuery("SELECT html_template FROM sis_component_template WHERE slug = 'news-grid'"); + if (rs.next()) { + System.out.println("TEMPLATE:"); + System.out.println(rs.getString("html_template")); + } + } catch (Exception e) { + e.printStackTrace(); + } + } +} diff --git a/sisvietnamvn_main/CheckPosts.java b/sisvietnamvn_main/CheckPosts.java new file mode 100644 index 00000000..7e473cca --- /dev/null +++ b/sisvietnamvn_main/CheckPosts.java @@ -0,0 +1,19 @@ +import java.sql.Connection; +import java.sql.DriverManager; +import java.sql.ResultSet; +import java.sql.Statement; + +public class CheckPosts { + public static void main(String[] args) { + try { + Connection conn = DriverManager.getConnection("jdbc:oracle:thin:@localhost:1521/sisvietnam", "sisvietnam", "sisvietnam"); + Statement stmt = conn.createStatement(); + ResultSet rs = stmt.executeQuery("SELECT id, slug, featured_image FROM sis_post WHERE featured_image IS NOT NULL"); + while (rs.next()) { + System.out.println("ID: " + rs.getLong("id") + " Slug: " + rs.getString("slug") + " IMG: " + rs.getString("featured_image")); + } + } catch (Exception e) { + e.printStackTrace(); + } + } +} diff --git a/sisvietnamvn_main/CheckRender.java b/sisvietnamvn_main/CheckRender.java new file mode 100644 index 00000000..26da9d2c --- /dev/null +++ b/sisvietnamvn_main/CheckRender.java @@ -0,0 +1,32 @@ +import com.fasterxml.jackson.databind.ObjectMapper; +import java.io.InputStream; +import java.net.HttpURLConnection; +import java.net.URL; +import java.util.Scanner; + +public class CheckRender { + public static void main(String[] args) { + try { + URL url = new URL("http://localhost:8080/"); + HttpURLConnection conn = (HttpURLConnection) url.openConnection(); + conn.setRequestMethod("GET"); + conn.connect(); + if (conn.getResponseCode() == 200) { + InputStream is = conn.getInputStream(); + Scanner scanner = new Scanner(is, "UTF-8").useDelimiter("\\A"); + String html = scanner.hasNext() ? scanner.next() : ""; + + int idx = html.indexOf("news-card__image"); + if (idx != -1) { + System.out.println(html.substring(idx, Math.min(idx + 300, html.length()))); + } else { + System.out.println("Could not find news-card__image in HTML"); + } + } else { + System.out.println("HTTP " + conn.getResponseCode()); + } + } catch (Exception e) { + e.printStackTrace(); + } + } +} diff --git a/sisvietnamvn_main/FixNewsGrid.java b/sisvietnamvn_main/FixNewsGrid.java new file mode 100644 index 00000000..34f3e863 --- /dev/null +++ b/sisvietnamvn_main/FixNewsGrid.java @@ -0,0 +1,40 @@ +import java.sql.Connection; +import java.sql.DriverManager; +import java.sql.PreparedStatement; + +public class FixNewsGrid { + public static void main(String[] args) { + try { + Connection conn = DriverManager.getConnection("jdbc:oracle:thin:@localhost:1521/sisvietnam", "sisvietnam", "sisvietnam"); + String correctHtml = "{{#each news_posts}}\n" + + "
\n" + + "
\n" + + "
\n" + + "
\n" + + " \"{{title}}\"\n" + + "
\n" + + "
\n" + + "
\n" + + "
\n" + + " TIN TỨC\n" + + "
\n" + + "

\n" + + " \n" + + " {{title}}\n" + + " \n" + + "

\n" + + "
{{date}}
\n" + + "
\n" + + "
\n" + + "
\n" + + "{{/each}}"; + + PreparedStatement pstmt = conn.prepareStatement("UPDATE sis_component_template SET html_template = ? WHERE slug = 'news-grid'"); + pstmt.setString(1, correctHtml); + int updated = pstmt.executeUpdate(); + System.out.println("Updated rows: " + updated); + } catch (Exception e) { + e.printStackTrace(); + } + } +} diff --git a/sisvietnamvn_main/FixPosts.java b/sisvietnamvn_main/FixPosts.java new file mode 100644 index 00000000..71d6b2df --- /dev/null +++ b/sisvietnamvn_main/FixPosts.java @@ -0,0 +1,33 @@ +import java.sql.Connection; +import java.sql.DriverManager; +import java.sql.ResultSet; +import java.sql.Statement; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +public class FixPosts { + public static void main(String[] args) { + try { + Connection conn = DriverManager.getConnection("jdbc:oracle:thin:@localhost:1521/sisvietnam", "sisvietnam", "sisvietnam"); + Statement stmt = conn.createStatement(); + ResultSet rs = stmt.executeQuery("SELECT id, content FROM sis_post WHERE featured_image IS NULL"); + Pattern p = Pattern.compile("]+src\\s*=\\s*['\"]([^'\"]+)['\"][^>]*>"); + int count = 0; + while (rs.next()) { + String content = rs.getString("content"); + if (content != null) { + Matcher m = p.matcher(content); + if (m.find()) { + String imgUrl = m.group(1); + Statement updateStmt = conn.createStatement(); + updateStmt.executeUpdate("UPDATE sis_post SET featured_image = '" + imgUrl + "' WHERE id = " + rs.getLong("id")); + count++; + } + } + } + System.out.println("Updated " + count + " posts with featured images from content."); + } catch (Exception e) { + e.printStackTrace(); + } + } +} diff --git a/sisvietnamvn_main/TestDb.java b/sisvietnamvn_main/TestDb.java new file mode 100644 index 00000000..c80e86e5 --- /dev/null +++ b/sisvietnamvn_main/TestDb.java @@ -0,0 +1,26 @@ +import java.sql.Connection; +import java.sql.DriverManager; +import java.sql.ResultSet; +import java.sql.Statement; + +public class TestDb { + public static void main(String[] args) { + try { + Connection conn = DriverManager.getConnection("jdbc:oracle:thin:@localhost:1521/sisvietnam", "sisvietnam", "sisvietnam"); + Statement stmt = conn.createStatement(); + ResultSet rs = stmt.executeQuery("SELECT id, slug, html_template FROM sis_component_template"); + while (rs.next()) { + System.out.println("--- ID: " + rs.getInt("id") + " SLUG: " + rs.getString("slug") + " ---"); + String html = rs.getString("html_template"); + if (html != null && html.contains("\\n")) { + System.out.println("CONTAINS LITERAL \\n!"); + } else if (html != null && html.contains("\n")) { + System.out.println("Contains actual newlines."); + } + System.out.println(html); + } + } catch (Exception e) { + e.printStackTrace(); + } + } +} diff --git a/sisvietnamvn_main/TestReplace.java b/sisvietnamvn_main/TestReplace.java new file mode 100644 index 00000000..1af64371 --- /dev/null +++ b/sisvietnamvn_main/TestReplace.java @@ -0,0 +1,10 @@ +import java.util.regex.Matcher; +public class TestReplace { + public static void main(String[] args) { + String test = "Line 1\nLine 2"; + System.out.println("Original:"); + System.out.println(test); + System.out.println("Quote:"); + System.out.println(Matcher.quoteReplacement(test)); + } +} diff --git a/sisvietnamvn_main/src/main/java/com/sisvietnamvn/web/NewsEventsSeeder.java b/sisvietnamvn_main/src/main/java/com/sisvietnamvn/web/NewsEventsSeeder.java deleted file mode 100644 index 27866262..00000000 --- a/sisvietnamvn_main/src/main/java/com/sisvietnamvn/web/NewsEventsSeeder.java +++ /dev/null @@ -1,110 +0,0 @@ -package com.sisvietnamvn.web; - -import com.sisvietnamvn.web.domain.ComponentTemplate; -import com.sisvietnamvn.web.repository.ComponentTemplateRepository; -import org.springframework.boot.CommandLineRunner; -import org.springframework.stereotype.Component; -import org.springframework.transaction.annotation.Transactional; - -import java.util.Optional; - -@Component -public class NewsEventsSeeder implements CommandLineRunner { - - private final ComponentTemplateRepository repository; - - public NewsEventsSeeder(ComponentTemplateRepository repository) { - this.repository = repository; - } - - @Override - @Transactional - public void run(String... args) throws Exception { - seedNewsGrid(); - seedEventsList(); - } - - private void seedNewsGrid() { - String slug = "news-grid"; - Optional opt = repository.findBySlug(slug); - ComponentTemplate t = opt.orElse(new ComponentTemplate()); - t.setSlug(slug); - t.setName("News Grid"); - t.setDescription("Dynamic grid layout for news."); - t.setActive(true); - - String html = - "\n" + - "
\n" + - " {{#each news_posts}}\n" + - "
\n" + - "
\"{{title}}\"
\n" + - "
\n" + - " TIN TỨC\n" + - "

{{title}}

\n" + - "
{{date}}
\n" + - "
\n" + - "
\n" + - " {{/each}}\n" + - "
\n"; - - t.setHtmlTemplate(html); - repository.save(t); - System.out.println("====== SUCCESS: SEEDED news-grid ComponentTemplate ====="); - } - - private void seedEventsList() { - String slug = "events-list"; - Optional opt = repository.findBySlug(slug); - ComponentTemplate t = opt.orElse(new ComponentTemplate()); - t.setSlug(slug); - t.setName("Events List"); - t.setDescription("Vertical list layout for events with event times."); - t.setActive(true); - - String html = - "\n" + - "
\n" + - " {{#each event_posts}}\n" + - "
\n" + - "
\n" + - " {{eventMonth}}\n" + - " {{eventDay}}\n" + - "
\n" + - "
\n" + - "

{{title}}

\n" + - "

{{eventTimeStr}}
{{excerpt}}

\n" + - "
\n" + - "
\n" + - " {{/each}}\n" + - "
\n"; - - t.setHtmlTemplate(html); - repository.save(t); - System.out.println("====== SUCCESS: SEEDED events-list ComponentTemplate ====="); - } -} 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 64e61ad5..3fe37544 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 @@ -149,4 +149,20 @@ public class ManagePageController { redirectAttributes.addFlashAttribute("successMessage", "Page deleted successfully!"); return "redirect:/manage/pages"; } + + /** + * POST /manage/pages/{id}/duplicate — Duplicate a page. + */ + @PostMapping("/{id}/duplicate") + public String duplicatePage(@PathVariable Long id, RedirectAttributes redirectAttributes) { + LOG.debug("Request to duplicate Page : {}", id); + try { + pageService.duplicate(id); + redirectAttributes.addFlashAttribute("successMessage", "Page duplicated successfully!"); + } catch (Exception e) { + LOG.error("Failed to duplicate page", e); + redirectAttributes.addFlashAttribute("errorMessage", "Failed to duplicate page."); + } + return "redirect:/manage/pages"; + } } 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 a346e0c6..f4c19a06 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 @@ -170,6 +170,22 @@ public class ManagePostController { return "redirect:/manage/posts"; } + /** + * POST /manage/posts/{id}/duplicate — Duplicate a post. + */ + @PostMapping("/{id}/duplicate") + public String duplicatePost(@PathVariable Long id, RedirectAttributes redirectAttributes) { + LOG.debug("Request to duplicate Post : {}", id); + try { + postService.duplicate(id); + redirectAttributes.addFlashAttribute("successMessage", "Post duplicated successfully!"); + } catch (Exception e) { + LOG.error("Failed to duplicate post", e); + redirectAttributes.addFlashAttribute("errorMessage", "Failed to duplicate post."); + } + return "redirect:/manage/posts"; + } + /** * Populate common model attributes for the post form. */ diff --git a/sisvietnamvn_main/src/main/java/com/sisvietnamvn/web/controller/manage/TestTemplateController.java b/sisvietnamvn_main/src/main/java/com/sisvietnamvn/web/controller/manage/TestTemplateController.java new file mode 100644 index 00000000..f6c75047 --- /dev/null +++ b/sisvietnamvn_main/src/main/java/com/sisvietnamvn/web/controller/manage/TestTemplateController.java @@ -0,0 +1,23 @@ +package com.sisvietnamvn.web.controller.manage; + +import com.sisvietnamvn.web.domain.ComponentTemplate; +import com.sisvietnamvn.web.repository.ComponentTemplateRepository; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RestController; +import java.util.stream.Collectors; + +@RestController +public class TestTemplateController { + private final ComponentTemplateRepository repo; + + public TestTemplateController(ComponentTemplateRepository repo) { + this.repo = repo; + } + + @GetMapping("/api/test-templates") + public String test() { + return repo.findAll().stream() + .map(t -> "SLUG: " + t.getSlug() + "\nHTML: " + t.getHtmlTemplate() + "\nHAS_BACKSLASH_N: " + (t.getHtmlTemplate().contains("\\n"))) + .collect(Collectors.joining("\n\n")); + } +} diff --git a/sisvietnamvn_main/src/main/java/com/sisvietnamvn/web/domain/Post.java b/sisvietnamvn_main/src/main/java/com/sisvietnamvn/web/domain/Post.java index b14a69d9..6876c182 100644 --- a/sisvietnamvn_main/src/main/java/com/sisvietnamvn/web/domain/Post.java +++ b/sisvietnamvn_main/src/main/java/com/sisvietnamvn/web/domain/Post.java @@ -146,6 +146,10 @@ public class Post extends AbstractAuditingEntity { return layout; } + public void setLayout(PostLayout layout) { + this.layout = layout; + } + public Category getCategory() { return category; } @@ -162,6 +166,24 @@ public class Post extends AbstractAuditingEntity { this.eventTime = eventTime; } + @jakarta.persistence.Transient + public String getEventTimeLocal() { + if (this.eventTime != null) { + return java.time.LocalDateTime.ofInstant(this.eventTime, java.time.ZoneId.systemDefault()) + .format(java.time.format.DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm")); + } + return null; + } + + public void setEventTimeLocal(String eventTimeLocal) { + if (eventTimeLocal != null && !eventTimeLocal.isEmpty()) { + this.eventTime = java.time.LocalDateTime.parse(eventTimeLocal, java.time.format.DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm")) + .atZone(java.time.ZoneId.systemDefault()).toInstant(); + } else { + this.eventTime = null; + } + } + public Set getTags() { return tags; } diff --git a/sisvietnamvn_main/src/main/java/com/sisvietnamvn/web/domain/PostLayout.java b/sisvietnamvn_main/src/main/java/com/sisvietnamvn/web/domain/PostLayout.java index 1cd69c56..782691f6 100644 --- a/sisvietnamvn_main/src/main/java/com/sisvietnamvn/web/domain/PostLayout.java +++ b/sisvietnamvn_main/src/main/java/com/sisvietnamvn/web/domain/PostLayout.java @@ -6,5 +6,6 @@ package com.sisvietnamvn.web.domain; public enum PostLayout { STANDARD, SIDEBAR, - FULL_WIDTH + FULL_WIDTH, + EVENT } 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 aef72e83..78e55c54 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 @@ -215,9 +215,12 @@ public class ComponentTemplateService { java.time.format.DateTimeFormatter timeFormatter = java.time.format.DateTimeFormatter.ofPattern("hh:mm a").withZone(java.time.ZoneId.systemDefault()); for (com.sisvietnamvn.web.domain.Post post : posts) { String itemHtml = loopBody; - itemHtml = itemHtml.replace("{{title}}", post.getTitle() != null ? post.getTitle() : ""); + 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()) : ""; + + itemHtml = itemHtml.replace("{{title}}", safeTitle); itemHtml = itemHtml.replace("{{slug}}", post.getSlug() != null ? post.getSlug() : ""); - itemHtml = itemHtml.replace("{{excerpt}}", post.getExcerpt() != null ? post.getExcerpt() : ""); + itemHtml = itemHtml.replace("{{excerpt}}", safeExcerpt); itemHtml = itemHtml.replace("{{featuredImageUrl}}", post.getFeaturedImage() != null ? post.getFeaturedImage() : ""); String dateStr = post.getCreatedDate() != null ? formatter.format(post.getCreatedDate()) : ""; itemHtml = itemHtml.replace("{{date}}", dateStr); diff --git a/sisvietnamvn_main/src/main/java/com/sisvietnamvn/web/service/ImportExportService.java b/sisvietnamvn_main/src/main/java/com/sisvietnamvn/web/service/ImportExportService.java index b43788ab..860abb21 100644 --- a/sisvietnamvn_main/src/main/java/com/sisvietnamvn/web/service/ImportExportService.java +++ b/sisvietnamvn_main/src/main/java/com/sisvietnamvn/web/service/ImportExportService.java @@ -240,6 +240,15 @@ public class ImportExportService { post.setContent(content); post.setExcerpt(excerpt); post.setStatus(status); + + // Extract first image from content as fallback featured image + if (content != null) { + java.util.regex.Matcher m = java.util.regex.Pattern.compile("]+src\\s*=\\s*['\"]([^'\"]+)['\"][^>]*>").matcher(content); + if (m.find()) { + post.setFeaturedImage(m.group(1)); + } + } + postRepository.save(post); } } else if ("page".equalsIgnoreCase(postType)) { 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 92c77028..aa7f647f 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 @@ -158,4 +158,25 @@ public class PageService { slug = slug.replaceAll("^-|-$", ""); return slug.toLowerCase(Locale.ENGLISH); } + + /** + * Duplicates an existing page. + * Creates a new draft copy with "(Copy)" appended to the title. + * @param id the ID of the page to duplicate + * @return the newly created page + */ + public Page duplicate(Long id) { + LOG.debug("Request to duplicate Page : {}", id); + Page original = pageRepository.findById(id) + .orElseThrow(() -> new IllegalArgumentException("Invalid page Id:" + id)); + + Page copy = new Page(); + copy.setTitle(original.getTitle() + " (Copy)"); + copy.setContent(original.getContent()); + copy.setPageType(original.getPageType()); + copy.setDisplayOrder(original.getDisplayOrder()); + copy.setStatus(PageStatus.DRAFT); + + return save(copy); + } } diff --git a/sisvietnamvn_main/src/main/java/com/sisvietnamvn/web/service/PostService.java b/sisvietnamvn_main/src/main/java/com/sisvietnamvn/web/service/PostService.java index e2e4cfa7..0d5766bd 100644 --- a/sisvietnamvn_main/src/main/java/com/sisvietnamvn/web/service/PostService.java +++ b/sisvietnamvn_main/src/main/java/com/sisvietnamvn/web/service/PostService.java @@ -171,4 +171,30 @@ public class PostService { } return postRepository.existsBySlugAndIdNot(slug, currentPostId); } + + /** + * Duplicates an existing post. + * Creates a new draft copy with "(Copy)" appended to the title. + * @param id the ID of the post to duplicate + * @return the newly created post + */ + public Post duplicate(Long id) { + LOG.debug("Request to duplicate Post : {}", id); + Post original = postRepository.findById(id) + .orElseThrow(() -> new IllegalArgumentException("Invalid post Id:" + id)); + + Post copy = new Post(); + copy.setTitle(original.getTitle() + " (Copy)"); + copy.setContent(original.getContent()); + copy.setExcerpt(original.getExcerpt()); + copy.setFeaturedImage(original.getFeaturedImage()); + copy.setLayout(original.getLayout()); + copy.setCategory(original.getCategory()); + copy.setTags(new HashSet<>(original.getTags())); + copy.setMetaDescription(original.getMetaDescription()); + copy.setEventTime(original.getEventTime()); + copy.setStatus(PageStatus.DRAFT); + + return save(copy); + } } diff --git a/sisvietnamvn_main/src/main/java/com/sisvietnamvn/web/service/sample.html b/sisvietnamvn_main/src/main/java/com/sisvietnamvn/web/service/sample.html index 18ab3c02..c7f12d38 100644 --- a/sisvietnamvn_main/src/main/java/com/sisvietnamvn/web/service/sample.html +++ b/sisvietnamvn_main/src/main/java/com/sisvietnamvn/web/service/sample.html @@ -1,10 +1,31 @@ - -
-
- [component:news-grid data-source="posts:tag=news,limit=4,collection=news_posts"] +
+
+ +
+

TIN TỨC & SỰ KIỆN

+ Xem Thêm
-
- [component:events-list data-source="posts:tag=event,limit=4,collection=event_posts"] + + +
+
+

TIN MỚI NHẤT

+
+ [component:news-grid data-source="posts:tag=news,limit=4,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 +
\ No newline at end of file diff --git a/sisvietnamvn_main/src/main/resources/config/liquibase/changelog/20260714080000_seed_news_events_components.xml b/sisvietnamvn_main/src/main/resources/config/liquibase/changelog/20260714080000_seed_news_events_components.xml new file mode 100644 index 00000000..0618790e --- /dev/null +++ b/sisvietnamvn_main/src/main/resources/config/liquibase/changelog/20260714080000_seed_news_events_components.xml @@ -0,0 +1,135 @@ + + + + + + + + + + + + +
+{{/each}}]]> + + + + + + + + + + + .campus-events-widget { background: transparent; padding: 0; font-family: inherit; } + .campus-events-widget .events-list { list-style: none; margin: 0; padding: 0; } + .campus-events-widget .teaser-item { padding: 20px 0; border-bottom: 1px solid #e5e5e5; } + .campus-events-widget .teaser-item:last-child { border-bottom: none; } + .campus-events-widget .event-wrapper { display: flex; gap: 20px; align-items: flex-start; } + .campus-events-widget .event-date { display: flex; flex-direction: column; justify-content: center; align-items: center; gap: 0.125rem; padding: 0.25rem; background: #881C1C; width: 2.875rem; height: 3.125rem; box-sizing: border-box; } + .campus-events-widget .event-date__month { font-size: 1rem; font-weight: 800; line-height: 1.25rem; text-transform: uppercase; text-align: center; color: #fff; } + .campus-events-widget .event-date__day { font-size: 1rem; font-weight: 800; line-height: 1.25rem; text-transform: uppercase; text-align: center; color: #fff; } + .campus-events-widget .event-details { flex: 1; position: relative; } + .campus-events-widget .event-title { font-size: 1rem; font-weight: 800; line-height: 1.25rem; text-transform: uppercase; color: #000; } + .campus-events-widget .event-title a { color: inherit; text-decoration: none; } + .campus-events-widget .event-title a:hover { text-decoration: underline; } + .campus-events-widget .event-time { font-size: 16px; color: #000; margin-bottom: 4px; } + .campus-events-widget .event-location { font-size: 1rem; font-weight: 400; line-height: 1.5rem; font-style: normal; color: #000; } + @media (max-width: 768px) { + .campus-events-widget .event-title { font-size: 0.75rem; } + .campus-events-widget .event-time { font-size: 0.75rem; } + .campus-events-widget .event-location { font-size: 0.75rem; } + .campus-events-widget .event-wrapper { display: flex; flex: 1; padding-right: 10px; align-items: stretch; gap: 12px; border: 1px solid #CCC; } + .campus-events-widget .event-date { display: flex; padding: 4px 8px; flex-direction: column; justify-content: center; align-items: center; align-self: stretch; background: #881C1C; min-width: 48px; height: auto; } + .campus-events-widget .event-details { padding: 8px 10px 8px 0; } + .campus-events-widget .teaser-item { flex: 0 0 279px; display: flex; border: 0px solid #CCC; padding-bottom: 0; } + .campus-events-widget .events-list { display: flex; gap: 1rem; overflow-x: auto; padding-bottom: 1rem; } + } + @media (max-width: 480px) { + .campus-events-widget .event-wrapper { gap: 10px; } + .campus-events-widget .event-date__day { font-size: 18px; } + } + +
+
+ {{#each event_posts}} +
+
+
+
{{eventMonth}}
+
{{eventDay}}
+
+
+
+ {{title}} +
+
{{eventTimeStr}}
+
+
+
+ {{/each}} +
+
]]>
+ +
+ + + + +
+{{/each}}]]> + slug = 'news-grid' + + + + + xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-4.20.xsd"> + + + + + slug IN ('news-grid', 'events-list') + + + diff --git a/sisvietnamvn_main/src/main/resources/config/liquibase/master.xml b/sisvietnamvn_main/src/main/resources/config/liquibase/master.xml index bc0a1260..ecbe2296 100644 --- a/sisvietnamvn_main/src/main/resources/config/liquibase/master.xml +++ b/sisvietnamvn_main/src/main/resources/config/liquibase/master.xml @@ -36,4 +36,5 @@ + diff --git a/sisvietnamvn_main/src/main/resources/templates/manage/pages/list.html b/sisvietnamvn_main/src/main/resources/templates/manage/pages/list.html index 77036163..17efedee 100644 --- a/sisvietnamvn_main/src/main/resources/templates/manage/pages/list.html +++ b/sisvietnamvn_main/src/main/resources/templates/manage/pages/list.html @@ -67,16 +67,23 @@ - + Edit
-
+
+ + +
diff --git a/sisvietnamvn_main/src/main/resources/templates/manage/posts/form.html b/sisvietnamvn_main/src/main/resources/templates/manage/posts/form.html index 992c4463..884a5f7d 100644 --- a/sisvietnamvn_main/src/main/resources/templates/manage/posts/form.html +++ b/sisvietnamvn_main/src/main/resources/templates/manage/posts/form.html @@ -267,6 +267,14 @@ Controls the visual appearance on the frontend.
+ +