feat: implement livestream post functionality and update site theme assets
This commit is contained in:
@@ -0,0 +1,21 @@
|
||||
import java.sql.Connection;
|
||||
import java.sql.DriverManager;
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.Statement;
|
||||
|
||||
public class CheckSnippets {
|
||||
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 slug, content FROM html_snippet");
|
||||
while (rs.next()) {
|
||||
if (rs.getString("content") != null && rs.getString("content").contains("news-grid")) {
|
||||
System.out.println("Snippet with news-grid: " + rs.getString("slug"));
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,93 @@
|
||||
import java.sql.Connection;
|
||||
import java.sql.DriverManager;
|
||||
import java.sql.PreparedStatement;
|
||||
import java.sql.ResultSet;
|
||||
|
||||
public class CreateLivestreamPost {
|
||||
public static void main(String[] args) {
|
||||
try {
|
||||
Class.forName("oracle.jdbc.OracleDriver");
|
||||
Connection conn = DriverManager.getConnection("jdbc:oracle:thin:@localhost:1521/sisvietnam", "sisvietnam", "sisvietnam");
|
||||
|
||||
// 1. Check if tag 'livestream' exists, if not create it
|
||||
long tagId = -1;
|
||||
PreparedStatement checkTag = conn.prepareStatement("SELECT id FROM sis_tag WHERE slug = 'livestream'");
|
||||
ResultSet rsTag = checkTag.executeQuery();
|
||||
if (rsTag.next()) {
|
||||
tagId = rsTag.getLong("id");
|
||||
} else {
|
||||
PreparedStatement insertTag = conn.prepareStatement(
|
||||
"INSERT INTO sis_tag (id, name, slug, created_by) VALUES (sequence_generator.NEXTVAL, ?, ?, 'system')"
|
||||
);
|
||||
insertTag.setString(1, "Livestream");
|
||||
insertTag.setString(2, "livestream");
|
||||
insertTag.executeUpdate();
|
||||
|
||||
PreparedStatement getTagId = conn.prepareStatement("SELECT id FROM sis_tag WHERE slug = 'livestream'");
|
||||
ResultSet rsTag2 = getTagId.executeQuery();
|
||||
if (rsTag2.next()) {
|
||||
tagId = rsTag2.getLong("id");
|
||||
}
|
||||
}
|
||||
|
||||
if (tagId == -1) {
|
||||
System.out.println("Failed to find or create livestream tag.");
|
||||
return;
|
||||
}
|
||||
|
||||
// 2. Insert Post
|
||||
// We set Title as "Tuần 1" (so it shows nicely on the tab label)
|
||||
// We set Excerpt as the long Title they provided.
|
||||
String postTitle = "Tuần 1";
|
||||
String postExcerpt = "SIS Vì Sức khỏe Cộng đồng kỳ 134 Thoát vị đĩa đệm – Khi nào mới phẫu thuật?";
|
||||
String postContent = "Đau lưng, đau cổ, tê tay, tê chân... là những triệu chứng thường gặp của thoát vị đĩa đệm. Tuy nhiên, không phải ai mắc bệnh cũng cần phẫu thuật.\n" +
|
||||
"⚠️ Vậy khi nào nên điều trị bảo tồn? Khi nào cần phẫu thuật? Làm sao để tránh bỏ lỡ \"thời điểm vàng\" điều trị?\n" +
|
||||
"Cùng lắng nghe những chia sẻ từ các chuyên gia trong chương trình Livestream \"S.I.S vì sức khỏe cộng đồng\" vào lúc 𝟏𝟗𝐡𝟒𝟓 Thứ Ba, ngày 𝟎𝟕/𝟎𝟕/𝟐𝟎𝟐𝟔.\n" +
|
||||
"📌 Đồng hành và tư vấn trực tiếp cùng quý khán giả là các bác sĩ giàu kinh nghiệm tại Bệnh viện ĐKQT S.I.S Cần Thơ:\n" +
|
||||
"• BS.CKI Nguyễn Quang Hưng, chuyên khoa Ngoại Thần kinh\n" +
|
||||
"• BS.CKI Trương Đan Kha, chuyên khoa Vật lý trị liệu - Phục hồi chức năng \n" +
|
||||
"• ThS.BS Lê Thị Chi Lan, chuyên khoa Ngoại Thần kinh.";
|
||||
|
||||
// Convert standard youtube link to embed link
|
||||
String embedUrl = "https://www.youtube.com/embed/j63kT9Bjrb4";
|
||||
|
||||
PreparedStatement insertPost = conn.prepareStatement(
|
||||
"INSERT INTO sis_post (id, title, slug, content, excerpt, meta_description, featured_image, created_by, status) " +
|
||||
"VALUES (sequence_generator.NEXTVAL, ?, ?, ?, ?, ?, ?, 'system', 'PUBLISHED')"
|
||||
);
|
||||
insertPost.setString(1, postTitle);
|
||||
insertPost.setString(2, "sis-vi-suc-khoe-cong-dong-ky-134");
|
||||
insertPost.setString(3, postContent);
|
||||
insertPost.setString(4, postExcerpt);
|
||||
insertPost.setString(5, embedUrl);
|
||||
insertPost.setString(6, "/media/livestream/livestream_tuan1.jpg"); // uploaded image
|
||||
insertPost.executeUpdate();
|
||||
|
||||
// Get new post ID
|
||||
long postId = -1;
|
||||
PreparedStatement getPostId = conn.prepareStatement("SELECT id FROM sis_post WHERE slug = 'sis-vi-suc-khoe-cong-dong-ky-134'");
|
||||
ResultSet rsPost = getPostId.executeQuery();
|
||||
if (rsPost.next()) {
|
||||
postId = rsPost.getLong("id");
|
||||
}
|
||||
|
||||
if (postId == -1) {
|
||||
System.out.println("Failed to retrieve created post ID.");
|
||||
return;
|
||||
}
|
||||
|
||||
// 3. Link post with tag
|
||||
PreparedStatement linkPostTag = conn.prepareStatement(
|
||||
"INSERT INTO sis_post_tag (post_id, tag_id) VALUES (?, ?)"
|
||||
);
|
||||
linkPostTag.setLong(1, postId);
|
||||
linkPostTag.setLong(2, tagId);
|
||||
linkPostTag.executeUpdate();
|
||||
|
||||
System.out.println("Successfully created post and linked it with the 'livestream' tag.");
|
||||
conn.close();
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,158 @@
|
||||
import java.sql.Connection;
|
||||
import java.sql.DriverManager;
|
||||
import java.sql.PreparedStatement;
|
||||
|
||||
public class UpdateLivestreamJs {
|
||||
public static void main(String[] args) {
|
||||
try {
|
||||
Class.forName("oracle.jdbc.OracleDriver");
|
||||
Connection conn = DriverManager.getConnection("jdbc:oracle:thin:@localhost:1521/sisvietnam", "sisvietnam", "sisvietnam");
|
||||
|
||||
String htmlTemplate =
|
||||
"<style>\n" +
|
||||
" .tabbed-media-content-media-item { width: 100%; aspect-ratio: 16/9; position: relative; display: flex; align-items: center; justify-content: center; }\n" +
|
||||
" .tabbed-media-content-media-item .f--video-embed { display: none; width: 100%; height: 100%; position: absolute; top: 0; left: 0; }\n" +
|
||||
" .tabbed-media-content-media-item .f--video-embed iframe { width: 100%; height: 100%; }\n" +
|
||||
" .tabbed-media-content-media-item .f--image { width: 100%; height: 100%; position: absolute; top: 0; left: 0; }\n" +
|
||||
" .tabbed-media-content-media-item .button-play { z-index: 10; }\n" +
|
||||
"</style>\n" +
|
||||
"<div class=\"cc--component-container cc--tabbed-media-content\" style=\"background-color: var(--color-gray-100);\">\n" +
|
||||
" <div class=\"c--component c--tabbed-media-content\">\n" +
|
||||
" <div class=\"tabbed-media-content-text-col\">\n" +
|
||||
" <div data-component-id=\"umass_base:section-title\" class=\"f--section-title\">\n" +
|
||||
" <h2 style=\"color: var(--color-brand);\">LiveStream</h2>\n" +
|
||||
" </div>\n" +
|
||||
" <div data-component-id=\"umass_base:tabbed-container\" data-once=\"tabbed-container\">\n" +
|
||||
" <div class=\"tab-labels-container\" role=\"tablist\">\n" +
|
||||
" <div class=\"tab-labels-inner\">\n" +
|
||||
" {{#each livestream_posts}}\n" +
|
||||
" <a href=\"#tabbed-content-{{index}}\" class=\"tab-label link-context-dark\" role=\"tab\" aria-selected=\"false\" aria-controls=\"tabbed-content-{{index}}\">{{title}}</a>\n" +
|
||||
" {{/each}}\n" +
|
||||
" </div>\n" +
|
||||
" </div>\n" +
|
||||
" <div class=\"tab-content-container\">\n" +
|
||||
" {{#each livestream_posts}}\n" +
|
||||
" <div class=\"tab-content-panel\" id=\"tabbed-content-{{index}}\" role=\"tabpanel\" aria-live=\"polite\">\n" +
|
||||
" <div class=\"f--field f--cta-title\">\n" +
|
||||
" <h2 style=\"color: var(--color-black);\"> {{excerpt}} </h2>\n" +
|
||||
" </div>\n" +
|
||||
" <div data-component-id=\"umass_base:description\" class=\"f--description\">\n" +
|
||||
" <div style=\"color:var(--color-black);\">{{content}}</div>\n" +
|
||||
" </div>\n" +
|
||||
" <div class=\"cta-container\">\n" +
|
||||
" <div class=\"f--field f--button\">\n" +
|
||||
" <a href=\"/post/{{slug}}\" class=\"button-primary button-context-light \" aria-label=\"Tìm Hiểu Thêm\" data-component-id=\"umass_base:button\">\n" +
|
||||
" <span class=\"button-text\"> Tìm Hiểu Thêm </span>\n" +
|
||||
" </a>\n" +
|
||||
" </div>\n" +
|
||||
" </div>\n" +
|
||||
" </div>\n" +
|
||||
" {{/each}}\n" +
|
||||
" </div>\n" +
|
||||
" </div>\n" +
|
||||
" </div>\n" +
|
||||
" <div class=\"tabbed-media-content-media-col\">\n" +
|
||||
" {{#each livestream_posts}}\n" +
|
||||
" <div class=\"tabbed-media-content-media-item with-video\" data-tab-id=\"tabbed-content-{{index}}\">\n" +
|
||||
" <div class=\"f--field f--image\">\n" +
|
||||
" <img src=\"{{featuredImageUrl}}\" data-src=\"{{featuredImageUrl}}\" class=\"lazyload\" alt=\"{{title}}\" style=\"width:100%;height:100%;object-fit:cover;\">\n" +
|
||||
" </div>\n" +
|
||||
" <div class=\"f--field f--button\">\n" +
|
||||
" <a href=\"#\" class=\"button-play button-context-light \" aria-label=\"Play video\" data-component-id=\"umass_base:button\">\n" +
|
||||
" <span class=\"button-icon button-icon-play\">\n" +
|
||||
" <svg width=\"18\" height=\"27\" viewBox=\"0 0 18 27\" fill=\"currentColor\" xmlns=\"http://www.w3.org/2000/svg\">\n" +
|
||||
" <path d=\"M18 13.5L0 0V27L18 13.5Z\"></path>\n" +
|
||||
" </svg>\n" +
|
||||
" </span>\n" +
|
||||
" <span class=\"button-text visually-hidden\"> Play </span>\n" +
|
||||
" </a>\n" +
|
||||
" </div>\n" +
|
||||
" <div data-component-id=\"umass_base:video-embed\" class=\"f--field f--video-embed\">\n" +
|
||||
" <iframe title=\"Video Content\" src=\"{{metaDescription}}\" frameborder=\"0\" allow=\"accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture\" allowfullscreen=\"\"></iframe>\n" +
|
||||
" </div>\n" +
|
||||
" </div>\n" +
|
||||
" {{/each}}\n" +
|
||||
" </div>\n" +
|
||||
" </div>\n" +
|
||||
"</div>\n" +
|
||||
"<script>\n" +
|
||||
" document.addEventListener(\"DOMContentLoaded\", function() {\n" +
|
||||
" // Set the first tab and panel as active if they exist\n" +
|
||||
" var tabs = document.querySelectorAll('.tabbed-media-content-media-item[data-tab-id=\"tabbed-content-0\"]');\n" +
|
||||
" if(tabs.length > 0) tabs[0].classList.add('is-active');\n" +
|
||||
" \n" +
|
||||
" var panels = document.querySelectorAll('#tabbed-content-0.tab-content-panel');\n" +
|
||||
" if(panels.length > 0) panels[0].classList.add('is-active');\n" +
|
||||
"\n" +
|
||||
" var labels = document.querySelectorAll('a.tab-label[aria-controls=\"tabbed-content-0\"]');\n" +
|
||||
" if(labels.length > 0) labels[0].setAttribute('aria-selected', 'true');\n" +
|
||||
"\n" +
|
||||
" // Tab Switching Logic\n" +
|
||||
" var allLabels = document.querySelectorAll('.tab-labels-inner .tab-label');\n" +
|
||||
" allLabels.forEach(function(label) {\n" +
|
||||
" label.addEventListener('click', function(e) {\n" +
|
||||
" e.preventDefault();\n" +
|
||||
" allLabels.forEach(function(l) { l.setAttribute('aria-selected', 'false'); });\n" +
|
||||
" this.setAttribute('aria-selected', 'true');\n" +
|
||||
" \n" +
|
||||
" var targetId = this.getAttribute('aria-controls');\n" +
|
||||
" document.querySelectorAll('.tab-content-panel').forEach(function(p) { p.classList.remove('is-active'); });\n" +
|
||||
" document.querySelectorAll('.tabbed-media-content-media-item').forEach(function(m) { \n" +
|
||||
" m.classList.remove('is-active'); \n" +
|
||||
" // Reset video when switching tabs\n" +
|
||||
" var vEmbed = m.querySelector('.f--video-embed');\n" +
|
||||
" if(vEmbed) vEmbed.style.display = 'none';\n" +
|
||||
" var img = m.querySelector('.f--image');\n" +
|
||||
" if(img) img.style.display = 'block';\n" +
|
||||
" var btn = m.querySelector('.button-play');\n" +
|
||||
" if(btn) btn.style.display = 'flex'; // Or whatever default display is\n" +
|
||||
" var iframe = m.querySelector('iframe');\n" +
|
||||
" if(iframe) { \n" +
|
||||
" var src = iframe.src;\n" +
|
||||
" iframe.src = src.replace('&autoplay=1', '').replace('?autoplay=1', '');\n" +
|
||||
" }\n" +
|
||||
" });\n" +
|
||||
" \n" +
|
||||
" var targetPanel = document.getElementById(targetId);\n" +
|
||||
" if(targetPanel) targetPanel.classList.add('is-active');\n" +
|
||||
" var targetMedia = document.querySelector('.tabbed-media-content-media-item[data-tab-id=\"' + targetId + '\"]');\n" +
|
||||
" if(targetMedia) targetMedia.classList.add('is-active');\n" +
|
||||
" });\n" +
|
||||
" });\n" +
|
||||
"\n" +
|
||||
" // Play Button Logic\n" +
|
||||
" var playButtons = document.querySelectorAll('.tabbed-media-content-media-item .button-play');\n" +
|
||||
" playButtons.forEach(function(btn) {\n" +
|
||||
" btn.addEventListener('click', function(e) {\n" +
|
||||
" e.preventDefault();\n" +
|
||||
" var mediaItem = this.closest('.tabbed-media-content-media-item');\n" +
|
||||
" var img = mediaItem.querySelector('.f--image');\n" +
|
||||
" var videoEmbed = mediaItem.querySelector('.f--video-embed');\n" +
|
||||
" \n" +
|
||||
" if(img) img.style.display = 'none';\n" +
|
||||
" this.style.display = 'none';\n" +
|
||||
" if(videoEmbed) videoEmbed.style.display = 'block';\n" +
|
||||
" \n" +
|
||||
" var iframe = mediaItem.querySelector('iframe');\n" +
|
||||
" if(iframe && iframe.src.indexOf('autoplay=1') === -1) {\n" +
|
||||
" iframe.src = iframe.src + (iframe.src.indexOf('?') > -1 ? '&' : '?') + 'autoplay=1';\n" +
|
||||
" }\n" +
|
||||
" });\n" +
|
||||
" });\n" +
|
||||
" });\n" +
|
||||
"</script>";
|
||||
|
||||
PreparedStatement updateTemplate = conn.prepareStatement(
|
||||
"UPDATE sis_component_template SET html_template = ? WHERE slug = 'tabbed-livestream'"
|
||||
);
|
||||
updateTemplate.setString(1, htmlTemplate);
|
||||
|
||||
int rows = updateTemplate.executeUpdate();
|
||||
System.out.println("Updated rows: " + rows);
|
||||
|
||||
conn.close();
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
import java.sql.Connection;
|
||||
import java.sql.DriverManager;
|
||||
import java.sql.PreparedStatement;
|
||||
|
||||
public class UpdateLivestreamPost {
|
||||
public static void main(String[] args) {
|
||||
try {
|
||||
Class.forName("oracle.jdbc.OracleDriver");
|
||||
Connection conn = DriverManager.getConnection("jdbc:oracle:thin:@localhost:1521/sisvietnam", "sisvietnam", "sisvietnam");
|
||||
|
||||
String postTitle = "Tuần 1";
|
||||
String postExcerpt = "SIS Vì Sức khỏe Cộng đồng kỳ 134 Thoát vị đĩa đệm – Khi nào mới phẫu thuật?";
|
||||
String postContent = "Đau lưng, đau cổ, tê tay, tê chân... là những triệu chứng thường gặp của thoát vị đĩa đệm. Tuy nhiên, không phải ai mắc bệnh cũng cần phẫu thuật.\n" +
|
||||
"⚠️ Vậy khi nào nên điều trị bảo tồn? Khi nào cần phẫu thuật? Làm sao để tránh bỏ lỡ \"thời điểm vàng\" điều trị?\n" +
|
||||
"Cùng lắng nghe những chia sẻ từ các chuyên gia trong chương trình Livestream \"S.I.S vì sức khỏe cộng đồng\" vào lúc 𝟏𝟗𝐡𝟒𝟓 Thứ Ba, ngày 𝟎𝟕/𝟎𝟕/𝟐𝟎𝟐𝟔.\n" +
|
||||
"📌 Đồng hành và tư vấn trực tiếp cùng quý khán giả là các bác sĩ giàu kinh nghiệm tại Bệnh viện ĐKQT S.I.S Cần Thơ:\n" +
|
||||
"• BS.CKI Nguyễn Quang Hưng, chuyên khoa Ngoại Thần kinh\n" +
|
||||
"• BS.CKI Trương Đan Kha, chuyên khoa Vật lý trị liệu - Phục hồi chức năng \n" +
|
||||
"• ThS.BS Lê Thị Chi Lan, chuyên khoa Ngoại Thần kinh.";
|
||||
|
||||
String embedUrl = "https://www.youtube.com/embed/j63kT9Bjrb4";
|
||||
|
||||
PreparedStatement updatePost = conn.prepareStatement(
|
||||
"UPDATE sis_post SET title = ?, content = ?, excerpt = ?, meta_description = ?, featured_image = ? WHERE slug = 'sis-vi-suc-khoe-cong-dong-ky-134'"
|
||||
);
|
||||
updatePost.setString(1, postTitle);
|
||||
updatePost.setString(2, postContent);
|
||||
updatePost.setString(3, postExcerpt);
|
||||
updatePost.setString(4, embedUrl);
|
||||
updatePost.setString(5, "/uploads/livestream/livestream_tuan1.jpg");
|
||||
|
||||
int rows = updatePost.executeUpdate();
|
||||
System.out.println("Updated rows: " + rows);
|
||||
|
||||
conn.close();
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,162 @@
|
||||
import java.sql.Connection;
|
||||
import java.sql.DriverManager;
|
||||
import java.sql.PreparedStatement;
|
||||
|
||||
public class UpdateLivestreamTemplate {
|
||||
public static void main(String[] args) {
|
||||
try {
|
||||
Class.forName("oracle.jdbc.OracleDriver");
|
||||
Connection conn = DriverManager.getConnection("jdbc:oracle:thin:@localhost:1521/sisvietnam", "sisvietnam", "sisvietnam");
|
||||
|
||||
// 1. Update the Post's meta_description (YouTube URL)
|
||||
PreparedStatement updatePost = conn.prepareStatement(
|
||||
"UPDATE sis_post SET meta_description = ? WHERE slug = 'sis-vi-suc-khoe-cong-dong-ky-134'"
|
||||
);
|
||||
updatePost.setString(1, "https://www.youtube.com/embed/j63kT9Bjrb4?si=N5JwIcuRn-iRxkYu");
|
||||
updatePost.executeUpdate();
|
||||
|
||||
// 2. Update the template's iframe attributes
|
||||
String htmlTemplate =
|
||||
"<style>\n" +
|
||||
" .tabbed-media-content-media-item { width: 100%; aspect-ratio: 16/9; position: relative; display: flex; align-items: center; justify-content: center; }\n" +
|
||||
" .tabbed-media-content-media-item .f--video-embed { display: none; width: 100%; height: 100%; position: absolute; top: 0; left: 0; }\n" +
|
||||
" .tabbed-media-content-media-item .f--video-embed iframe { width: 100%; height: 100%; }\n" +
|
||||
" .tabbed-media-content-media-item .f--image { width: 100%; height: 100%; position: absolute; top: 0; left: 0; }\n" +
|
||||
" .tabbed-media-content-media-item .button-play { z-index: 10; }\n" +
|
||||
"</style>\n" +
|
||||
"<div class=\"cc--component-container cc--tabbed-media-content\" style=\"background-color: var(--color-gray-100);\">\n" +
|
||||
" <div class=\"c--component c--tabbed-media-content\">\n" +
|
||||
" <div class=\"tabbed-media-content-text-col\">\n" +
|
||||
" <div data-component-id=\"umass_base:section-title\" class=\"f--section-title\">\n" +
|
||||
" <h2 style=\"color: var(--color-brand);\">LiveStream</h2>\n" +
|
||||
" </div>\n" +
|
||||
" <div data-component-id=\"umass_base:tabbed-container\" data-once=\"tabbed-container\">\n" +
|
||||
" <div class=\"tab-labels-container\" role=\"tablist\">\n" +
|
||||
" <div class=\"tab-labels-inner\">\n" +
|
||||
" {{#each livestream_posts}}\n" +
|
||||
" <a href=\"#tabbed-content-{{index}}\" class=\"tab-label link-context-dark\" role=\"tab\" aria-selected=\"false\" aria-controls=\"tabbed-content-{{index}}\">{{title}}</a>\n" +
|
||||
" {{/each}}\n" +
|
||||
" </div>\n" +
|
||||
" </div>\n" +
|
||||
" <div class=\"tab-content-container\">\n" +
|
||||
" {{#each livestream_posts}}\n" +
|
||||
" <div class=\"tab-content-panel\" id=\"tabbed-content-{{index}}\" role=\"tabpanel\" aria-live=\"polite\">\n" +
|
||||
" <div class=\"f--field f--cta-title\">\n" +
|
||||
" <h2 style=\"color: var(--color-black);\"> {{excerpt}} </h2>\n" +
|
||||
" </div>\n" +
|
||||
" <div data-component-id=\"umass_base:description\" class=\"f--description\">\n" +
|
||||
" <div style=\"color:var(--color-black);\">{{content}}</div>\n" +
|
||||
" </div>\n" +
|
||||
" <div class=\"cta-container\">\n" +
|
||||
" <div class=\"f--field f--button\">\n" +
|
||||
" <a href=\"/post/{{slug}}\" class=\"button-primary button-context-light \" aria-label=\"Tìm Hiểu Thêm\" data-component-id=\"umass_base:button\">\n" +
|
||||
" <span class=\"button-text\"> Tìm Hiểu Thêm </span>\n" +
|
||||
" </a>\n" +
|
||||
" </div>\n" +
|
||||
" </div>\n" +
|
||||
" </div>\n" +
|
||||
" {{/each}}\n" +
|
||||
" </div>\n" +
|
||||
" </div>\n" +
|
||||
" </div>\n" +
|
||||
" <div class=\"tabbed-media-content-media-col\">\n" +
|
||||
" {{#each livestream_posts}}\n" +
|
||||
" <div class=\"tabbed-media-content-media-item with-video\" data-tab-id=\"tabbed-content-{{index}}\">\n" +
|
||||
" <div class=\"f--field f--image\">\n" +
|
||||
" <img src=\"{{featuredImageUrl}}\" data-src=\"{{featuredImageUrl}}\" class=\"lazyload\" alt=\"{{title}}\" style=\"width:100%;height:100%;object-fit:cover;\">\n" +
|
||||
" </div>\n" +
|
||||
" <div class=\"f--field f--button\">\n" +
|
||||
" <a href=\"#\" class=\"button-play button-context-light \" aria-label=\"Play video\" data-component-id=\"umass_base:button\">\n" +
|
||||
" <span class=\"button-icon button-icon-play\">\n" +
|
||||
" <svg width=\"18\" height=\"27\" viewBox=\"0 0 18 27\" fill=\"currentColor\" xmlns=\"http://www.w3.org/2000/svg\">\n" +
|
||||
" <path d=\"M18 13.5L0 0V27L18 13.5Z\"></path>\n" +
|
||||
" </svg>\n" +
|
||||
" </span>\n" +
|
||||
" <span class=\"button-text visually-hidden\"> Play </span>\n" +
|
||||
" </a>\n" +
|
||||
" </div>\n" +
|
||||
" <div data-component-id=\"umass_base:video-embed\" class=\"f--field f--video-embed\">\n" +
|
||||
" <iframe title=\"YouTube video player\" src=\"{{metaDescription}}\" frameborder=\"0\" allow=\"accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share\" referrerpolicy=\"strict-origin-when-cross-origin\" allowfullscreen></iframe>\n" +
|
||||
" </div>\n" +
|
||||
" </div>\n" +
|
||||
" {{/each}}\n" +
|
||||
" </div>\n" +
|
||||
" </div>\n" +
|
||||
"</div>\n" +
|
||||
"<script>\n" +
|
||||
" document.addEventListener(\"DOMContentLoaded\", function() {\n" +
|
||||
" var tabs = document.querySelectorAll('.tabbed-media-content-media-item[data-tab-id=\"tabbed-content-0\"]');\n" +
|
||||
" if(tabs.length > 0) tabs[0].classList.add('is-active');\n" +
|
||||
" \n" +
|
||||
" var panels = document.querySelectorAll('#tabbed-content-0.tab-content-panel');\n" +
|
||||
" if(panels.length > 0) panels[0].classList.add('is-active');\n" +
|
||||
"\n" +
|
||||
" var labels = document.querySelectorAll('a.tab-label[aria-controls=\"tabbed-content-0\"]');\n" +
|
||||
" if(labels.length > 0) labels[0].setAttribute('aria-selected', 'true');\n" +
|
||||
"\n" +
|
||||
" var allLabels = document.querySelectorAll('.tab-labels-inner .tab-label');\n" +
|
||||
" allLabels.forEach(function(label) {\n" +
|
||||
" label.addEventListener('click', function(e) {\n" +
|
||||
" e.preventDefault();\n" +
|
||||
" allLabels.forEach(function(l) { l.setAttribute('aria-selected', 'false'); });\n" +
|
||||
" this.setAttribute('aria-selected', 'true');\n" +
|
||||
" \n" +
|
||||
" var targetId = this.getAttribute('aria-controls');\n" +
|
||||
" document.querySelectorAll('.tab-content-panel').forEach(function(p) { p.classList.remove('is-active'); });\n" +
|
||||
" document.querySelectorAll('.tabbed-media-content-media-item').forEach(function(m) { \n" +
|
||||
" m.classList.remove('is-active'); \n" +
|
||||
" var vEmbed = m.querySelector('.f--video-embed');\n" +
|
||||
" if(vEmbed) vEmbed.style.display = 'none';\n" +
|
||||
" var img = m.querySelector('.f--image');\n" +
|
||||
" if(img) img.style.display = 'block';\n" +
|
||||
" var btn = m.querySelector('.button-play');\n" +
|
||||
" if(btn) btn.style.display = 'flex';\n" +
|
||||
" var iframe = m.querySelector('iframe');\n" +
|
||||
" if(iframe) { \n" +
|
||||
" var src = iframe.src;\n" +
|
||||
" iframe.src = src.replace('&autoplay=1', '').replace('?autoplay=1', '');\n" +
|
||||
" }\n" +
|
||||
" });\n" +
|
||||
" \n" +
|
||||
" var targetPanel = document.getElementById(targetId);\n" +
|
||||
" if(targetPanel) targetPanel.classList.add('is-active');\n" +
|
||||
" var targetMedia = document.querySelector('.tabbed-media-content-media-item[data-tab-id=\"' + targetId + '\"]');\n" +
|
||||
" if(targetMedia) targetMedia.classList.add('is-active');\n" +
|
||||
" });\n" +
|
||||
" });\n" +
|
||||
"\n" +
|
||||
" var playButtons = document.querySelectorAll('.tabbed-media-content-media-item .button-play');\n" +
|
||||
" playButtons.forEach(function(btn) {\n" +
|
||||
" btn.addEventListener('click', function(e) {\n" +
|
||||
" e.preventDefault();\n" +
|
||||
" var mediaItem = this.closest('.tabbed-media-content-media-item');\n" +
|
||||
" var img = mediaItem.querySelector('.f--image');\n" +
|
||||
" var videoEmbed = mediaItem.querySelector('.f--video-embed');\n" +
|
||||
" \n" +
|
||||
" if(img) img.style.display = 'none';\n" +
|
||||
" this.style.display = 'none';\n" +
|
||||
" if(videoEmbed) videoEmbed.style.display = 'block';\n" +
|
||||
" \n" +
|
||||
" var iframe = mediaItem.querySelector('iframe');\n" +
|
||||
" if(iframe && iframe.src.indexOf('autoplay=1') === -1) {\n" +
|
||||
" iframe.src = iframe.src + (iframe.src.indexOf('?') > -1 ? '&' : '?') + 'autoplay=1';\n" +
|
||||
" }\n" +
|
||||
" });\n" +
|
||||
" });\n" +
|
||||
" });\n" +
|
||||
"</script>";
|
||||
|
||||
PreparedStatement updateTemplate = conn.prepareStatement(
|
||||
"UPDATE sis_component_template SET html_template = ? WHERE slug = 'tabbed-livestream'"
|
||||
);
|
||||
updateTemplate.setString(1, htmlTemplate);
|
||||
updateTemplate.executeUpdate();
|
||||
|
||||
System.out.println("Update complete!");
|
||||
|
||||
conn.close();
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,161 @@
|
||||
import java.sql.Connection;
|
||||
import java.sql.DriverManager;
|
||||
import java.sql.PreparedStatement;
|
||||
|
||||
public class UpdateLivestreamTemplate2 {
|
||||
public static void main(String[] args) {
|
||||
try {
|
||||
Class.forName("oracle.jdbc.OracleDriver");
|
||||
Connection conn = DriverManager.getConnection("jdbc:oracle:thin:@localhost:1521/sisvietnam", "sisvietnam", "sisvietnam");
|
||||
|
||||
// We append &autoplay=1 to the URL in the database so it's ready to play
|
||||
PreparedStatement updatePost = conn.prepareStatement(
|
||||
"UPDATE sis_post SET meta_description = ? WHERE slug = 'sis-vi-suc-khoe-cong-dong-ky-134'"
|
||||
);
|
||||
updatePost.setString(1, "https://www.youtube.com/embed/j63kT9Bjrb4?si=N5JwIcuRn-iRxkYu&autoplay=1");
|
||||
updatePost.executeUpdate();
|
||||
|
||||
// 2. Update the template to use data-src instead of src.
|
||||
String htmlTemplate =
|
||||
"<style>\n" +
|
||||
" .tabbed-media-content-media-item { width: 100%; aspect-ratio: 16/9; position: relative; display: flex; align-items: center; justify-content: center; background: #000; overflow: hidden; }\n" +
|
||||
" .tabbed-media-content-media-item .f--video-embed { display: none; width: 100%; height: 100%; }\n" +
|
||||
" .tabbed-media-content-media-item .f--video-embed iframe { width: 100%; height: 100%; border: none; }\n" +
|
||||
" .tabbed-media-content-media-item .f--image { width: 100%; height: 100%; position: absolute; top: 0; left: 0; }\n" +
|
||||
" .tabbed-media-content-media-item .button-play { z-index: 10; }\n" +
|
||||
"</style>\n" +
|
||||
"<div class=\"cc--component-container cc--tabbed-media-content\" style=\"background-color: var(--color-gray-100);\">\n" +
|
||||
" <div class=\"c--component c--tabbed-media-content\">\n" +
|
||||
" <div class=\"tabbed-media-content-text-col\">\n" +
|
||||
" <div data-component-id=\"umass_base:section-title\" class=\"f--section-title\">\n" +
|
||||
" <h2 style=\"color: var(--color-brand);\">LiveStream</h2>\n" +
|
||||
" </div>\n" +
|
||||
" <div data-component-id=\"umass_base:tabbed-container\" data-once=\"tabbed-container\">\n" +
|
||||
" <div class=\"tab-labels-container\" role=\"tablist\">\n" +
|
||||
" <div class=\"tab-labels-inner\">\n" +
|
||||
" {{#each livestream_posts}}\n" +
|
||||
" <a href=\"#tabbed-content-{{index}}\" class=\"tab-label link-context-dark\" role=\"tab\" aria-selected=\"false\" aria-controls=\"tabbed-content-{{index}}\">{{title}}</a>\n" +
|
||||
" {{/each}}\n" +
|
||||
" </div>\n" +
|
||||
" </div>\n" +
|
||||
" <div class=\"tab-content-container\">\n" +
|
||||
" {{#each livestream_posts}}\n" +
|
||||
" <div class=\"tab-content-panel\" id=\"tabbed-content-{{index}}\" role=\"tabpanel\" aria-live=\"polite\">\n" +
|
||||
" <div class=\"f--field f--cta-title\">\n" +
|
||||
" <h2 style=\"color: var(--color-black);\"> {{excerpt}} </h2>\n" +
|
||||
" </div>\n" +
|
||||
" <div data-component-id=\"umass_base:description\" class=\"f--description\">\n" +
|
||||
" <div style=\"color:var(--color-black);\">{{content}}</div>\n" +
|
||||
" </div>\n" +
|
||||
" <div class=\"cta-container\">\n" +
|
||||
" <div class=\"f--field f--button\">\n" +
|
||||
" <a href=\"/post/{{slug}}\" class=\"button-primary button-context-light \" aria-label=\"Tìm Hiểu Thêm\" data-component-id=\"umass_base:button\">\n" +
|
||||
" <span class=\"button-text\"> Tìm Hiểu Thêm </span>\n" +
|
||||
" </a>\n" +
|
||||
" </div>\n" +
|
||||
" </div>\n" +
|
||||
" </div>\n" +
|
||||
" {{/each}}\n" +
|
||||
" </div>\n" +
|
||||
" </div>\n" +
|
||||
" </div>\n" +
|
||||
" <div class=\"tabbed-media-content-media-col\">\n" +
|
||||
" {{#each livestream_posts}}\n" +
|
||||
" <div class=\"tabbed-media-content-media-item with-video\" data-tab-id=\"tabbed-content-{{index}}\">\n" +
|
||||
" <div class=\"f--field f--image\">\n" +
|
||||
" <img src=\"{{featuredImageUrl}}\" data-src=\"{{featuredImageUrl}}\" class=\"lazyload\" alt=\"{{title}}\" style=\"width:100%;height:100%;object-fit:cover;\">\n" +
|
||||
" </div>\n" +
|
||||
" <div class=\"f--field f--button\">\n" +
|
||||
" <a href=\"#\" class=\"button-play button-context-light \" aria-label=\"Play video\" data-component-id=\"umass_base:button\">\n" +
|
||||
" <span class=\"button-icon button-icon-play\">\n" +
|
||||
" <svg width=\"18\" height=\"27\" viewBox=\"0 0 18 27\" fill=\"currentColor\" xmlns=\"http://www.w3.org/2000/svg\">\n" +
|
||||
" <path d=\"M18 13.5L0 0V27L18 13.5Z\"></path>\n" +
|
||||
" </svg>\n" +
|
||||
" </span>\n" +
|
||||
" <span class=\"button-text visually-hidden\"> Play </span>\n" +
|
||||
" </a>\n" +
|
||||
" </div>\n" +
|
||||
" <div data-component-id=\"umass_base:video-embed\" class=\"f--field f--video-embed\">\n" +
|
||||
" <iframe title=\"YouTube video player\" data-src=\"{{metaDescription}}\" frameborder=\"0\" allow=\"accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share\" referrerpolicy=\"strict-origin-when-cross-origin\" allowfullscreen></iframe>\n" +
|
||||
" </div>\n" +
|
||||
" </div>\n" +
|
||||
" {{/each}}\n" +
|
||||
" </div>\n" +
|
||||
" </div>\n" +
|
||||
"</div>\n" +
|
||||
"<script>\n" +
|
||||
" document.addEventListener(\"DOMContentLoaded\", function() {\n" +
|
||||
" var tabs = document.querySelectorAll('.tabbed-media-content-media-item[data-tab-id=\"tabbed-content-0\"]');\n" +
|
||||
" if(tabs.length > 0) tabs[0].classList.add('is-active');\n" +
|
||||
" \n" +
|
||||
" var panels = document.querySelectorAll('#tabbed-content-0.tab-content-panel');\n" +
|
||||
" if(panels.length > 0) panels[0].classList.add('is-active');\n" +
|
||||
"\n" +
|
||||
" var labels = document.querySelectorAll('a.tab-label[aria-controls=\"tabbed-content-0\"]');\n" +
|
||||
" if(labels.length > 0) labels[0].setAttribute('aria-selected', 'true');\n" +
|
||||
"\n" +
|
||||
" var allLabels = document.querySelectorAll('.tab-labels-inner .tab-label');\n" +
|
||||
" allLabels.forEach(function(label) {\n" +
|
||||
" label.addEventListener('click', function(e) {\n" +
|
||||
" e.preventDefault();\n" +
|
||||
" allLabels.forEach(function(l) { l.setAttribute('aria-selected', 'false'); });\n" +
|
||||
" this.setAttribute('aria-selected', 'true');\n" +
|
||||
" \n" +
|
||||
" var targetId = this.getAttribute('aria-controls');\n" +
|
||||
" document.querySelectorAll('.tab-content-panel').forEach(function(p) { p.classList.remove('is-active'); });\n" +
|
||||
" document.querySelectorAll('.tabbed-media-content-media-item').forEach(function(m) { \n" +
|
||||
" m.classList.remove('is-active'); \n" +
|
||||
" var vEmbed = m.querySelector('.f--video-embed');\n" +
|
||||
" if(vEmbed) vEmbed.style.display = 'none';\n" +
|
||||
" var img = m.querySelector('.f--image');\n" +
|
||||
" if(img) img.style.display = 'block';\n" +
|
||||
" var btn = m.querySelector('.button-play');\n" +
|
||||
" if(btn) btn.style.display = 'flex';\n" +
|
||||
" var iframe = m.querySelector('iframe');\n" +
|
||||
" if(iframe) { \n" +
|
||||
" iframe.src = '';\n" +
|
||||
" }\n" +
|
||||
" });\n" +
|
||||
" \n" +
|
||||
" var targetPanel = document.getElementById(targetId);\n" +
|
||||
" if(targetPanel) targetPanel.classList.add('is-active');\n" +
|
||||
" var targetMedia = document.querySelector('.tabbed-media-content-media-item[data-tab-id=\"' + targetId + '\"]');\n" +
|
||||
" if(targetMedia) targetMedia.classList.add('is-active');\n" +
|
||||
" });\n" +
|
||||
" });\n" +
|
||||
"\n" +
|
||||
" var playButtons = document.querySelectorAll('.tabbed-media-content-media-item .button-play');\n" +
|
||||
" playButtons.forEach(function(btn) {\n" +
|
||||
" btn.addEventListener('click', function(e) {\n" +
|
||||
" e.preventDefault();\n" +
|
||||
" var mediaItem = this.closest('.tabbed-media-content-media-item');\n" +
|
||||
" var img = mediaItem.querySelector('.f--image');\n" +
|
||||
" var videoEmbed = mediaItem.querySelector('.f--video-embed');\n" +
|
||||
" \n" +
|
||||
" if(img) img.style.display = 'none';\n" +
|
||||
" this.style.display = 'none';\n" +
|
||||
" if(videoEmbed) videoEmbed.style.display = 'block';\n" +
|
||||
" \n" +
|
||||
" var iframe = mediaItem.querySelector('iframe');\n" +
|
||||
" if(iframe && iframe.getAttribute('data-src')) {\n" +
|
||||
" iframe.src = iframe.getAttribute('data-src');\n" +
|
||||
" }\n" +
|
||||
" });\n" +
|
||||
" });\n" +
|
||||
" });\n" +
|
||||
"</script>";
|
||||
|
||||
PreparedStatement updateTemplate = conn.prepareStatement(
|
||||
"UPDATE sis_component_template SET html_template = ? WHERE slug = 'tabbed-livestream'"
|
||||
);
|
||||
updateTemplate.setString(1, htmlTemplate);
|
||||
updateTemplate.executeUpdate();
|
||||
|
||||
System.out.println("Update complete!");
|
||||
|
||||
conn.close();
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,146 @@
|
||||
import java.sql.Connection;
|
||||
import java.sql.DriverManager;
|
||||
import java.sql.PreparedStatement;
|
||||
|
||||
public class UpdateLivestreamTemplate3 {
|
||||
public static void main(String[] args) {
|
||||
try {
|
||||
Class.forName("oracle.jdbc.OracleDriver");
|
||||
Connection conn = DriverManager.getConnection("jdbc:oracle:thin:@localhost:1521/sisvietnam", "sisvietnam", "sisvietnam");
|
||||
|
||||
// We ensure it is just the standard embed without JS tampering
|
||||
String htmlTemplate =
|
||||
"<style>\n" +
|
||||
" .tabbed-media-content-media-item { width: 100%; aspect-ratio: 16/9; position: relative; display: flex; align-items: center; justify-content: center; background: #000; overflow: hidden; }\n" +
|
||||
" .tabbed-media-content-media-item .f--video-embed { display: none; width: 100%; height: 100%; }\n" +
|
||||
" .tabbed-media-content-media-item .f--video-embed iframe { width: 100%; height: 100%; border: none; }\n" +
|
||||
" .tabbed-media-content-media-item .f--image { width: 100%; height: 100%; position: absolute; top: 0; left: 0; z-index: 5; }\n" +
|
||||
" .tabbed-media-content-media-item .button-play { z-index: 10; }\n" +
|
||||
"</style>\n" +
|
||||
"<div class=\"cc--component-container cc--tabbed-media-content\" style=\"background-color: var(--color-gray-100);\">\n" +
|
||||
" <div class=\"c--component c--tabbed-media-content\">\n" +
|
||||
" <div class=\"tabbed-media-content-text-col\">\n" +
|
||||
" <div data-component-id=\"umass_base:section-title\" class=\"f--section-title\">\n" +
|
||||
" <h2 style=\"color: var(--color-brand);\">LiveStream</h2>\n" +
|
||||
" </div>\n" +
|
||||
" <div data-component-id=\"umass_base:tabbed-container\" data-once=\"tabbed-container\">\n" +
|
||||
" <div class=\"tab-labels-container\" role=\"tablist\">\n" +
|
||||
" <div class=\"tab-labels-inner\">\n" +
|
||||
" {{#each livestream_posts}}\n" +
|
||||
" <a href=\"#tabbed-content-{{index}}\" class=\"tab-label link-context-dark\" role=\"tab\" aria-selected=\"false\" aria-controls=\"tabbed-content-{{index}}\">{{title}}</a>\n" +
|
||||
" {{/each}}\n" +
|
||||
" </div>\n" +
|
||||
" </div>\n" +
|
||||
" <div class=\"tab-content-container\">\n" +
|
||||
" {{#each livestream_posts}}\n" +
|
||||
" <div class=\"tab-content-panel\" id=\"tabbed-content-{{index}}\" role=\"tabpanel\" aria-live=\"polite\">\n" +
|
||||
" <div class=\"f--field f--cta-title\">\n" +
|
||||
" <h2 style=\"color: var(--color-black);\"> {{excerpt}} </h2>\n" +
|
||||
" </div>\n" +
|
||||
" <div data-component-id=\"umass_base:description\" class=\"f--description\">\n" +
|
||||
" <div style=\"color:var(--color-black);\">{{content}}</div>\n" +
|
||||
" </div>\n" +
|
||||
" <div class=\"cta-container\">\n" +
|
||||
" <div class=\"f--field f--button\">\n" +
|
||||
" <a href=\"/post/{{slug}}\" class=\"button-primary button-context-light \" aria-label=\"Tìm Hiểu Thêm\" data-component-id=\"umass_base:button\">\n" +
|
||||
" <span class=\"button-text\"> Tìm Hiểu Thêm </span>\n" +
|
||||
" </a>\n" +
|
||||
" </div>\n" +
|
||||
" </div>\n" +
|
||||
" </div>\n" +
|
||||
" {{/each}}\n" +
|
||||
" </div>\n" +
|
||||
" </div>\n" +
|
||||
" </div>\n" +
|
||||
" <div class=\"tabbed-media-content-media-col\">\n" +
|
||||
" {{#each livestream_posts}}\n" +
|
||||
" <div class=\"tabbed-media-content-media-item with-video\" data-tab-id=\"tabbed-content-{{index}}\">\n" +
|
||||
" <div class=\"f--field f--image\">\n" +
|
||||
" <img src=\"{{featuredImageUrl}}\" data-src=\"{{featuredImageUrl}}\" class=\"lazyload\" alt=\"{{title}}\" style=\"width:100%;height:100%;object-fit:cover;\">\n" +
|
||||
" </div>\n" +
|
||||
" <div class=\"f--field f--button\" style=\"position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%); z-index: 10;\">\n" +
|
||||
" <a href=\"#\" class=\"button-play button-context-light \" aria-label=\"Play video\" data-component-id=\"umass_base:button\">\n" +
|
||||
" <span class=\"button-icon button-icon-play\">\n" +
|
||||
" <svg width=\"18\" height=\"27\" viewBox=\"0 0 18 27\" fill=\"currentColor\" xmlns=\"http://www.w3.org/2000/svg\">\n" +
|
||||
" <path d=\"M18 13.5L0 0V27L18 13.5Z\"></path>\n" +
|
||||
" </svg>\n" +
|
||||
" </span>\n" +
|
||||
" <span class=\"button-text visually-hidden\"> Play </span>\n" +
|
||||
" </a>\n" +
|
||||
" </div>\n" +
|
||||
" <div data-component-id=\"umass_base:video-embed\" class=\"f--field f--video-embed\">\n" +
|
||||
" <iframe title=\"YouTube video player\" src=\"{{metaDescription}}\" frameborder=\"0\" allow=\"accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share\" referrerpolicy=\"strict-origin-when-cross-origin\" allowfullscreen></iframe>\n" +
|
||||
" </div>\n" +
|
||||
" </div>\n" +
|
||||
" {{/each}}\n" +
|
||||
" </div>\n" +
|
||||
" </div>\n" +
|
||||
"</div>\n" +
|
||||
"<script>\n" +
|
||||
" document.addEventListener(\"DOMContentLoaded\", function() {\n" +
|
||||
" var tabs = document.querySelectorAll('.tabbed-media-content-media-item[data-tab-id=\"tabbed-content-0\"]');\n" +
|
||||
" if(tabs.length > 0) tabs[0].classList.add('is-active');\n" +
|
||||
" \n" +
|
||||
" var panels = document.querySelectorAll('#tabbed-content-0.tab-content-panel');\n" +
|
||||
" if(panels.length > 0) panels[0].classList.add('is-active');\n" +
|
||||
"\n" +
|
||||
" var labels = document.querySelectorAll('a.tab-label[aria-controls=\"tabbed-content-0\"]');\n" +
|
||||
" if(labels.length > 0) labels[0].setAttribute('aria-selected', 'true');\n" +
|
||||
"\n" +
|
||||
" var allLabels = document.querySelectorAll('.tab-labels-inner .tab-label');\n" +
|
||||
" allLabels.forEach(function(label) {\n" +
|
||||
" label.addEventListener('click', function(e) {\n" +
|
||||
" e.preventDefault();\n" +
|
||||
" allLabels.forEach(function(l) { l.setAttribute('aria-selected', 'false'); });\n" +
|
||||
" this.setAttribute('aria-selected', 'true');\n" +
|
||||
" \n" +
|
||||
" var targetId = this.getAttribute('aria-controls');\n" +
|
||||
" document.querySelectorAll('.tab-content-panel').forEach(function(p) { p.classList.remove('is-active'); });\n" +
|
||||
" document.querySelectorAll('.tabbed-media-content-media-item').forEach(function(m) { \n" +
|
||||
" m.classList.remove('is-active'); \n" +
|
||||
" var vEmbed = m.querySelector('.f--video-embed');\n" +
|
||||
" if(vEmbed) vEmbed.style.display = 'none';\n" +
|
||||
" var img = m.querySelector('.f--image');\n" +
|
||||
" if(img) img.style.display = 'block';\n" +
|
||||
" var btnContainer = m.querySelector('.f--field.f--button');\n" +
|
||||
" if(btnContainer) btnContainer.style.display = 'block';\n" +
|
||||
" });\n" +
|
||||
" \n" +
|
||||
" var targetPanel = document.getElementById(targetId);\n" +
|
||||
" if(targetPanel) targetPanel.classList.add('is-active');\n" +
|
||||
" var targetMedia = document.querySelector('.tabbed-media-content-media-item[data-tab-id=\"' + targetId + '\"]');\n" +
|
||||
" if(targetMedia) targetMedia.classList.add('is-active');\n" +
|
||||
" });\n" +
|
||||
" });\n" +
|
||||
"\n" +
|
||||
" var playButtons = document.querySelectorAll('.tabbed-media-content-media-item .button-play');\n" +
|
||||
" playButtons.forEach(function(btn) {\n" +
|
||||
" btn.addEventListener('click', function(e) {\n" +
|
||||
" e.preventDefault();\n" +
|
||||
" var mediaItem = this.closest('.tabbed-media-content-media-item');\n" +
|
||||
" var img = mediaItem.querySelector('.f--image');\n" +
|
||||
" var videoEmbed = mediaItem.querySelector('.f--video-embed');\n" +
|
||||
" var btnContainer = mediaItem.querySelector('.f--field.f--button');\n" +
|
||||
" \n" +
|
||||
" if(img) img.style.display = 'none';\n" +
|
||||
" if(btnContainer) btnContainer.style.display = 'none';\n" +
|
||||
" if(videoEmbed) videoEmbed.style.display = 'block';\n" +
|
||||
" });\n" +
|
||||
" });\n" +
|
||||
" });\n" +
|
||||
"</script>";
|
||||
|
||||
PreparedStatement updateTemplate = conn.prepareStatement(
|
||||
"UPDATE sis_component_template SET html_template = ? WHERE slug = 'tabbed-livestream'"
|
||||
);
|
||||
updateTemplate.setString(1, htmlTemplate);
|
||||
updateTemplate.executeUpdate();
|
||||
|
||||
System.out.println("Update complete!");
|
||||
|
||||
conn.close();
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,155 @@
|
||||
import java.sql.Connection;
|
||||
import java.sql.DriverManager;
|
||||
import java.sql.PreparedStatement;
|
||||
|
||||
public class UpdateLivestreamTemplate4 {
|
||||
public static void main(String[] args) {
|
||||
try {
|
||||
Class.forName("oracle.jdbc.OracleDriver");
|
||||
Connection conn = DriverManager.getConnection("jdbc:oracle:thin:@localhost:1521/sisvietnam", "sisvietnam", "sisvietnam");
|
||||
|
||||
// Re-apply the URL to be just the embed URL without autoplay so we can append it cleanly in data-src
|
||||
PreparedStatement updatePost = conn.prepareStatement(
|
||||
"UPDATE sis_post SET meta_description = ? WHERE slug = 'sis-vi-suc-khoe-cong-dong-ky-134'"
|
||||
);
|
||||
updatePost.setString(1, "https://www.youtube.com/embed/j63kT9Bjrb4?si=N5JwIcuRn-iRxkYu");
|
||||
updatePost.executeUpdate();
|
||||
|
||||
// We ensure it is just the standard embed without JS tampering
|
||||
String htmlTemplate =
|
||||
"<style>\n" +
|
||||
" .tabbed-media-content-media-item { width: 100%; aspect-ratio: 16/9; position: relative; display: block; background: #000; overflow: hidden; }\n" +
|
||||
" .tabbed-media-content-media-item .f--video-embed { display: block; position: absolute; top: 0; left: 0; width: 100%; height: 100%; z-index: 1; }\n" +
|
||||
" .tabbed-media-content-media-item .f--video-embed iframe { width: 100%; height: 100%; border: none; }\n" +
|
||||
" .tabbed-media-content-media-item .f--image { width: 100%; height: 100%; position: absolute; top: 0; left: 0; z-index: 5; }\n" +
|
||||
" .tabbed-media-content-media-item .f--button { z-index: 10; }\n" +
|
||||
"</style>\n" +
|
||||
"<div class=\"cc--component-container cc--tabbed-media-content\" style=\"background-color: var(--color-gray-100);\">\n" +
|
||||
" <div class=\"c--component c--tabbed-media-content\">\n" +
|
||||
" <div class=\"tabbed-media-content-text-col\">\n" +
|
||||
" <div data-component-id=\"umass_base:section-title\" class=\"f--section-title\">\n" +
|
||||
" <h2 style=\"color: var(--color-brand);\">LiveStream</h2>\n" +
|
||||
" </div>\n" +
|
||||
" <div data-component-id=\"umass_base:tabbed-container\" data-once=\"tabbed-container\">\n" +
|
||||
" <div class=\"tab-labels-container\" role=\"tablist\">\n" +
|
||||
" <div class=\"tab-labels-inner\">\n" +
|
||||
" {{#each livestream_posts}}\n" +
|
||||
" <a href=\"#tabbed-content-{{index}}\" class=\"tab-label link-context-dark\" role=\"tab\" aria-selected=\"false\" aria-controls=\"tabbed-content-{{index}}\">{{title}}</a>\n" +
|
||||
" {{/each}}\n" +
|
||||
" </div>\n" +
|
||||
" </div>\n" +
|
||||
" <div class=\"tab-content-container\">\n" +
|
||||
" {{#each livestream_posts}}\n" +
|
||||
" <div class=\"tab-content-panel\" id=\"tabbed-content-{{index}}\" role=\"tabpanel\" aria-live=\"polite\">\n" +
|
||||
" <div class=\"f--field f--cta-title\">\n" +
|
||||
" <h2 style=\"color: var(--color-black);\"> {{excerpt}} </h2>\n" +
|
||||
" </div>\n" +
|
||||
" <div data-component-id=\"umass_base:description\" class=\"f--description\">\n" +
|
||||
" <div style=\"color:var(--color-black);\">{{content}}</div>\n" +
|
||||
" </div>\n" +
|
||||
" <div class=\"cta-container\">\n" +
|
||||
" <div class=\"f--field f--button\">\n" +
|
||||
" <a href=\"/post/{{slug}}\" class=\"button-primary button-context-light \" aria-label=\"Tìm Hiểu Thêm\" data-component-id=\"umass_base:button\">\n" +
|
||||
" <span class=\"button-text\"> Tìm Hiểu Thêm </span>\n" +
|
||||
" </a>\n" +
|
||||
" </div>\n" +
|
||||
" </div>\n" +
|
||||
" </div>\n" +
|
||||
" {{/each}}\n" +
|
||||
" </div>\n" +
|
||||
" </div>\n" +
|
||||
" </div>\n" +
|
||||
" <div class=\"tabbed-media-content-media-col\">\n" +
|
||||
" {{#each livestream_posts}}\n" +
|
||||
" <div class=\"tabbed-media-content-media-item with-video\" data-tab-id=\"tabbed-content-{{index}}\">\n" +
|
||||
" <div class=\"f--field f--image\">\n" +
|
||||
" <img src=\"{{featuredImageUrl}}\" data-src=\"{{featuredImageUrl}}\" class=\"lazyload\" alt=\"{{title}}\" style=\"width:100%;height:100%;object-fit:cover;\">\n" +
|
||||
" </div>\n" +
|
||||
" <div class=\"f--field f--button\" style=\"position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%); z-index: 10;\">\n" +
|
||||
" <a href=\"#\" class=\"button-play button-context-light \" aria-label=\"Play video\" data-component-id=\"umass_base:button\">\n" +
|
||||
" <span class=\"button-icon button-icon-play\">\n" +
|
||||
" <svg width=\"18\" height=\"27\" viewBox=\"0 0 18 27\" fill=\"currentColor\" xmlns=\"http://www.w3.org/2000/svg\">\n" +
|
||||
" <path d=\"M18 13.5L0 0V27L18 13.5Z\"></path>\n" +
|
||||
" </svg>\n" +
|
||||
" </span>\n" +
|
||||
" <span class=\"button-text visually-hidden\"> Play </span>\n" +
|
||||
" </a>\n" +
|
||||
" </div>\n" +
|
||||
" <div data-component-id=\"umass_base:video-embed\" class=\"f--field f--video-embed\">\n" +
|
||||
" <iframe title=\"YouTube video player\" data-src=\"{{metaDescription}}&autoplay=1\" frameborder=\"0\" allow=\"accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share\" referrerpolicy=\"strict-origin-when-cross-origin\" allowfullscreen></iframe>\n" +
|
||||
" </div>\n" +
|
||||
" </div>\n" +
|
||||
" {{/each}}\n" +
|
||||
" </div>\n" +
|
||||
" </div>\n" +
|
||||
"</div>\n" +
|
||||
"<script>\n" +
|
||||
" document.addEventListener(\"DOMContentLoaded\", function() {\n" +
|
||||
" var tabs = document.querySelectorAll('.tabbed-media-content-media-item[data-tab-id=\"tabbed-content-0\"]');\n" +
|
||||
" if(tabs.length > 0) tabs[0].classList.add('is-active');\n" +
|
||||
" \n" +
|
||||
" var panels = document.querySelectorAll('#tabbed-content-0.tab-content-panel');\n" +
|
||||
" if(panels.length > 0) panels[0].classList.add('is-active');\n" +
|
||||
"\n" +
|
||||
" var labels = document.querySelectorAll('a.tab-label[aria-controls=\"tabbed-content-0\"]');\n" +
|
||||
" if(labels.length > 0) labels[0].setAttribute('aria-selected', 'true');\n" +
|
||||
"\n" +
|
||||
" var allLabels = document.querySelectorAll('.tab-labels-inner .tab-label');\n" +
|
||||
" allLabels.forEach(function(label) {\n" +
|
||||
" label.addEventListener('click', function(e) {\n" +
|
||||
" e.preventDefault();\n" +
|
||||
" allLabels.forEach(function(l) { l.setAttribute('aria-selected', 'false'); });\n" +
|
||||
" this.setAttribute('aria-selected', 'true');\n" +
|
||||
" \n" +
|
||||
" var targetId = this.getAttribute('aria-controls');\n" +
|
||||
" document.querySelectorAll('.tab-content-panel').forEach(function(p) { p.classList.remove('is-active'); });\n" +
|
||||
" document.querySelectorAll('.tabbed-media-content-media-item').forEach(function(m) { \n" +
|
||||
" m.classList.remove('is-active'); \n" +
|
||||
" var img = m.querySelector('.f--image');\n" +
|
||||
" if(img) img.style.display = 'block';\n" +
|
||||
" var btnContainer = m.querySelector('.f--field.f--button');\n" +
|
||||
" if(btnContainer) btnContainer.style.display = 'block';\n" +
|
||||
" var iframe = m.querySelector('iframe');\n" +
|
||||
" if(iframe) iframe.removeAttribute('src'); // Stop video playing if they switch tabs\n" +
|
||||
" });\n" +
|
||||
" \n" +
|
||||
" var targetPanel = document.getElementById(targetId);\n" +
|
||||
" if(targetPanel) targetPanel.classList.add('is-active');\n" +
|
||||
" var targetMedia = document.querySelector('.tabbed-media-content-media-item[data-tab-id=\"' + targetId + '\"]');\n" +
|
||||
" if(targetMedia) targetMedia.classList.add('is-active');\n" +
|
||||
" });\n" +
|
||||
" });\n" +
|
||||
"\n" +
|
||||
" var playButtons = document.querySelectorAll('.tabbed-media-content-media-item .button-play');\n" +
|
||||
" playButtons.forEach(function(btn) {\n" +
|
||||
" btn.addEventListener('click', function(e) {\n" +
|
||||
" e.preventDefault();\n" +
|
||||
" var mediaItem = this.closest('.tabbed-media-content-media-item');\n" +
|
||||
" var img = mediaItem.querySelector('.f--image');\n" +
|
||||
" var btnContainer = mediaItem.querySelector('.f--field.f--button');\n" +
|
||||
" var iframe = mediaItem.querySelector('iframe');\n" +
|
||||
" \n" +
|
||||
" if(img) img.style.display = 'none';\n" +
|
||||
" if(btnContainer) btnContainer.style.display = 'none';\n" +
|
||||
" if(iframe && iframe.getAttribute('data-src')) {\n" +
|
||||
" iframe.setAttribute('src', iframe.getAttribute('data-src'));\n" +
|
||||
" }\n" +
|
||||
" });\n" +
|
||||
" });\n" +
|
||||
" });\n" +
|
||||
"</script>";
|
||||
|
||||
PreparedStatement updateTemplate = conn.prepareStatement(
|
||||
"UPDATE sis_component_template SET html_template = ? WHERE slug = 'tabbed-livestream'"
|
||||
);
|
||||
updateTemplate.setString(1, htmlTemplate);
|
||||
updateTemplate.executeUpdate();
|
||||
|
||||
System.out.println("Update complete!");
|
||||
|
||||
conn.close();
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,117 @@
|
||||
import java.sql.Connection;
|
||||
import java.sql.DriverManager;
|
||||
import java.sql.PreparedStatement;
|
||||
|
||||
public class UpdateLivestreamTemplate5 {
|
||||
public static void main(String[] args) {
|
||||
try {
|
||||
Class.forName("oracle.jdbc.OracleDriver");
|
||||
Connection conn = DriverManager.getConnection("jdbc:oracle:thin:@localhost:1521/sisvietnam", "sisvietnam", "sisvietnam");
|
||||
|
||||
// Revert the URL in the database to exactly what the user requested, without autoplay
|
||||
PreparedStatement updatePost = conn.prepareStatement(
|
||||
"UPDATE sis_post SET meta_description = ? WHERE slug = 'sis-vi-suc-khoe-cong-dong-ky-134'"
|
||||
);
|
||||
updatePost.setString(1, "https://www.youtube.com/embed/j63kT9Bjrb4?si=N5JwIcuRn-iRxkYu");
|
||||
updatePost.executeUpdate();
|
||||
|
||||
// We remove the custom image and play button entirely and let YouTube handle it!
|
||||
String htmlTemplate =
|
||||
"<style>\n" +
|
||||
" .tabbed-media-content-media-item { width: 100%; aspect-ratio: 16/9; position: relative; display: block; overflow: hidden; }\n" +
|
||||
" .tabbed-media-content-media-item .f--video-embed { width: 100%; height: 100%; }\n" +
|
||||
" .tabbed-media-content-media-item .f--video-embed iframe { width: 100%; height: 100%; border: none; }\n" +
|
||||
"</style>\n" +
|
||||
"<div class=\"cc--component-container cc--tabbed-media-content\" style=\"background-color: var(--color-gray-100);\">\n" +
|
||||
" <div class=\"c--component c--tabbed-media-content\">\n" +
|
||||
" <div class=\"tabbed-media-content-text-col\">\n" +
|
||||
" <div data-component-id=\"umass_base:section-title\" class=\"f--section-title\">\n" +
|
||||
" <h2 style=\"color: var(--color-brand);\">LiveStream</h2>\n" +
|
||||
" </div>\n" +
|
||||
" <div data-component-id=\"umass_base:tabbed-container\" data-once=\"tabbed-container\">\n" +
|
||||
" <div class=\"tab-labels-container\" role=\"tablist\">\n" +
|
||||
" <div class=\"tab-labels-inner\">\n" +
|
||||
" {{#each livestream_posts}}\n" +
|
||||
" <a href=\"#tabbed-content-{{index}}\" class=\"tab-label link-context-dark\" role=\"tab\" aria-selected=\"false\" aria-controls=\"tabbed-content-{{index}}\">{{title}}</a>\n" +
|
||||
" {{/each}}\n" +
|
||||
" </div>\n" +
|
||||
" </div>\n" +
|
||||
" <div class=\"tab-content-container\">\n" +
|
||||
" {{#each livestream_posts}}\n" +
|
||||
" <div class=\"tab-content-panel\" id=\"tabbed-content-{{index}}\" role=\"tabpanel\" aria-live=\"polite\">\n" +
|
||||
" <div class=\"f--field f--cta-title\">\n" +
|
||||
" <h2 style=\"color: var(--color-black);\"> {{excerpt}} </h2>\n" +
|
||||
" </div>\n" +
|
||||
" <div data-component-id=\"umass_base:description\" class=\"f--description\">\n" +
|
||||
" <div style=\"color:var(--color-black);\">{{content}}</div>\n" +
|
||||
" </div>\n" +
|
||||
" <div class=\"cta-container\">\n" +
|
||||
" <div class=\"f--field f--button\">\n" +
|
||||
" <a href=\"/post/{{slug}}\" class=\"button-primary button-context-light \" aria-label=\"Tìm Hiểu Thêm\" data-component-id=\"umass_base:button\">\n" +
|
||||
" <span class=\"button-text\"> Tìm Hiểu Thêm </span>\n" +
|
||||
" </a>\n" +
|
||||
" </div>\n" +
|
||||
" </div>\n" +
|
||||
" </div>\n" +
|
||||
" {{/each}}\n" +
|
||||
" </div>\n" +
|
||||
" </div>\n" +
|
||||
" </div>\n" +
|
||||
" <div class=\"tabbed-media-content-media-col\">\n" +
|
||||
" {{#each livestream_posts}}\n" +
|
||||
" <div class=\"tabbed-media-content-media-item with-video\" data-tab-id=\"tabbed-content-{{index}}\">\n" +
|
||||
" <div data-component-id=\"umass_base:video-embed\" class=\"f--field f--video-embed\">\n" +
|
||||
" <iframe title=\"YouTube video player\" src=\"{{metaDescription}}\" frameborder=\"0\" allow=\"accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share\" referrerpolicy=\"strict-origin-when-cross-origin\" allowfullscreen></iframe>\n" +
|
||||
" </div>\n" +
|
||||
" </div>\n" +
|
||||
" {{/each}}\n" +
|
||||
" </div>\n" +
|
||||
" </div>\n" +
|
||||
"</div>\n" +
|
||||
"<script>\n" +
|
||||
" document.addEventListener(\"DOMContentLoaded\", function() {\n" +
|
||||
" var tabs = document.querySelectorAll('.tabbed-media-content-media-item[data-tab-id=\"tabbed-content-0\"]');\n" +
|
||||
" if(tabs.length > 0) tabs[0].classList.add('is-active');\n" +
|
||||
" \n" +
|
||||
" var panels = document.querySelectorAll('#tabbed-content-0.tab-content-panel');\n" +
|
||||
" if(panels.length > 0) panels[0].classList.add('is-active');\n" +
|
||||
"\n" +
|
||||
" var labels = document.querySelectorAll('a.tab-label[aria-controls=\"tabbed-content-0\"]');\n" +
|
||||
" if(labels.length > 0) labels[0].setAttribute('aria-selected', 'true');\n" +
|
||||
"\n" +
|
||||
" var allLabels = document.querySelectorAll('.tab-labels-inner .tab-label');\n" +
|
||||
" allLabels.forEach(function(label) {\n" +
|
||||
" label.addEventListener('click', function(e) {\n" +
|
||||
" e.preventDefault();\n" +
|
||||
" allLabels.forEach(function(l) { l.setAttribute('aria-selected', 'false'); });\n" +
|
||||
" this.setAttribute('aria-selected', 'true');\n" +
|
||||
" \n" +
|
||||
" var targetId = this.getAttribute('aria-controls');\n" +
|
||||
" document.querySelectorAll('.tab-content-panel').forEach(function(p) { p.classList.remove('is-active'); });\n" +
|
||||
" document.querySelectorAll('.tabbed-media-content-media-item').forEach(function(m) { \n" +
|
||||
" m.classList.remove('is-active'); \n" +
|
||||
" });\n" +
|
||||
" \n" +
|
||||
" var targetPanel = document.getElementById(targetId);\n" +
|
||||
" if(targetPanel) targetPanel.classList.add('is-active');\n" +
|
||||
" var targetMedia = document.querySelector('.tabbed-media-content-media-item[data-tab-id=\"' + targetId + '\"]');\n" +
|
||||
" if(targetMedia) targetMedia.classList.add('is-active');\n" +
|
||||
" });\n" +
|
||||
" });\n" +
|
||||
" });\n" +
|
||||
"</script>";
|
||||
|
||||
PreparedStatement updateTemplate = conn.prepareStatement(
|
||||
"UPDATE sis_component_template SET html_template = ? WHERE slug = 'tabbed-livestream'"
|
||||
);
|
||||
updateTemplate.setString(1, htmlTemplate);
|
||||
updateTemplate.executeUpdate();
|
||||
|
||||
System.out.println("Update complete!");
|
||||
|
||||
conn.close();
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,124 @@
|
||||
import java.sql.Connection;
|
||||
import java.sql.DriverManager;
|
||||
import java.sql.PreparedStatement;
|
||||
|
||||
public class UpdateNewsGridDesktop {
|
||||
public static void main(String[] args) {
|
||||
try {
|
||||
Connection conn = DriverManager.getConnection("jdbc:oracle:thin:@localhost:1521/sisvietnam", "sisvietnam", "sisvietnam");
|
||||
String correctHtml = "<style>\n" +
|
||||
"@media screen and (min-width: 1024px) {\n" +
|
||||
" .featured-grid {\n" +
|
||||
" display: grid;\n" +
|
||||
" grid-template-columns: repeat(2, 1fr);\n" +
|
||||
" gap: 24px;\n" +
|
||||
" align-items: stretch;\n" +
|
||||
" }\n" +
|
||||
" .featured-grid__item {\n" +
|
||||
" height: 100%;\n" +
|
||||
" display: flex;\n" +
|
||||
" }\n" +
|
||||
" .featured-grid__item .news-card--featured {\n" +
|
||||
" display: flex;\n" +
|
||||
" flex-direction: row;\n" +
|
||||
" border: 1px solid #881C1C;\n" +
|
||||
" border-radius: 16px;\n" +
|
||||
" padding: 16px;\n" +
|
||||
" box-sizing: border-box;\n" +
|
||||
" width: 100%;\n" +
|
||||
" height: 100%;\n" +
|
||||
" gap: 16px;\n" +
|
||||
" background: #fff;\n" +
|
||||
" margin-bottom: 0 !important;\n" +
|
||||
" }\n" +
|
||||
" .featured-grid__item .news-card__image {\n" +
|
||||
" flex: 0 0 45%;\n" +
|
||||
" max-width: 45%;\n" +
|
||||
" margin-bottom: 0 !important;\n" +
|
||||
" }\n" +
|
||||
" .featured-grid__item .news-card__image > div {\n" +
|
||||
" height: 100%;\n" +
|
||||
" }\n" +
|
||||
" .featured-grid__item .news-card__image img {\n" +
|
||||
" width: 100%;\n" +
|
||||
" height: 100%;\n" +
|
||||
" object-fit: cover;\n" +
|
||||
" border-radius: 8px;\n" +
|
||||
" }\n" +
|
||||
" .featured-grid__item .news-card__content {\n" +
|
||||
" flex: 1;\n" +
|
||||
" display: flex;\n" +
|
||||
" flex-direction: column;\n" +
|
||||
" justify-content: flex-start;\n" +
|
||||
" min-width: 0;\n" +
|
||||
" padding: 0 !important;\n" +
|
||||
" margin: 0 !important;\n" +
|
||||
" }\n" +
|
||||
" .featured-grid__item .featured-grid__category {\n" +
|
||||
" margin-bottom: 12px;\n" +
|
||||
" }\n" +
|
||||
" .featured-grid__item .featured-grid__category a {\n" +
|
||||
" display: inline-block;\n" +
|
||||
" background-color: #f2f2f2;\n" +
|
||||
" color: #881C1C;\n" +
|
||||
" padding: 4px 8px;\n" +
|
||||
" border-radius: 4px;\n" +
|
||||
" font-size: 0.75rem;\n" +
|
||||
" font-weight: bold;\n" +
|
||||
" text-decoration: none;\n" +
|
||||
" text-transform: uppercase;\n" +
|
||||
" }\n" +
|
||||
" .featured-grid__item .news-card__title {\n" +
|
||||
" font-size: 1.1rem;\n" +
|
||||
" font-weight: 700;\n" +
|
||||
" margin-top: 0;\n" +
|
||||
" margin-bottom: 12px;\n" +
|
||||
" line-height: 1.4;\n" +
|
||||
" }\n" +
|
||||
" .featured-grid__item .news-card__title a {\n" +
|
||||
" color: #000;\n" +
|
||||
" text-decoration: none;\n" +
|
||||
" }\n" +
|
||||
" .featured-grid__item .news-card__title a:hover {\n" +
|
||||
" color: #881C1C;\n" +
|
||||
" }\n" +
|
||||
" .featured-grid__item .news-card__date {\n" +
|
||||
" margin-top: auto;\n" +
|
||||
" color: #881C1C;\n" +
|
||||
" font-size: 0.85rem;\n" +
|
||||
" font-weight: 500;\n" +
|
||||
" }\n" +
|
||||
"}\n" +
|
||||
"</style>\n" +
|
||||
"{{#each news_posts}}\n" +
|
||||
"<div class=\"featured-grid__item\">\n" +
|
||||
" <article class=\"news-card news-card--featured\">\n" +
|
||||
" <div class=\"news-card__image\">\n" +
|
||||
" <div>\n" +
|
||||
" <img loading=\"lazy\" src=\"{{featuredImageUrl}}\" alt=\"{{title}}\">\n" +
|
||||
" </div>\n" +
|
||||
" </div>\n" +
|
||||
" <div class=\"news-card__content\">\n" +
|
||||
" <div class=\"featured-grid__category\">\n" +
|
||||
" <a href=\"#\">TIN TỨC</a>\n" +
|
||||
" </div>\n" +
|
||||
" <h3 class=\"news-card__title\">\n" +
|
||||
" <a href=\"/post/{{slug}}\" rel=\"bookmark\">\n" +
|
||||
" <span>{{title}}</span>\n" +
|
||||
" </a>\n" +
|
||||
" </h3>\n" +
|
||||
" <div class=\"news-card__date\">{{date}}</div>\n" +
|
||||
" </div>\n" +
|
||||
" </article>\n" +
|
||||
"</div>\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();
|
||||
}
|
||||
}
|
||||
}
|
||||
Executable
+39
@@ -0,0 +1,39 @@
|
||||
#!/bin/bash
|
||||
|
||||
# Exit on any error
|
||||
set -e
|
||||
|
||||
CONTAINER_NAME="sisvietnam-oracle-sisvietnam-oracle-1"
|
||||
DUMP_FILE="sisvietnam_backup.dmp"
|
||||
LOG_FILE="sisvietnam_backup.log"
|
||||
|
||||
echo "=== Starting Database Backup ==="
|
||||
echo "Running expdp inside container: ${CONTAINER_NAME}..."
|
||||
|
||||
# Run expdp inside the container
|
||||
docker exec ${CONTAINER_NAME} expdp sisvietnam/sisvietnam@//localhost:1521/sisvietnam \
|
||||
schemas=sisvietnam \
|
||||
directory=DATA_PUMP_DIR \
|
||||
dumpfile=${DUMP_FILE} \
|
||||
logfile=${LOG_FILE} \
|
||||
reuse_dumpfiles=y
|
||||
|
||||
echo "=== Export Completed ==="
|
||||
echo "Locating the backup file inside the container..."
|
||||
|
||||
# Find the file dynamically because the directory path contains a dynamic GUID
|
||||
CONTAINER_PATH=$(docker exec ${CONTAINER_NAME} find /opt/oracle/admin/FREE/dpdump/ -name ${DUMP_FILE} | tr -d '\r')
|
||||
|
||||
if [ -z "${CONTAINER_PATH}" ]; then
|
||||
echo "Error: Could not locate ${DUMP_FILE} inside the container."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "Found backup file at: ${CONTAINER_PATH}"
|
||||
echo "Copying backup to local directory..."
|
||||
|
||||
# Copy to host
|
||||
docker cp "${CONTAINER_NAME}:${CONTAINER_PATH}" "./${DUMP_FILE}"
|
||||
|
||||
echo "=== Backup Successfully Created ==="
|
||||
echo "Saved to: ./${DUMP_FILE}"
|
||||
@@ -0,0 +1 @@
|
||||
SELECT meta_description FROM sis_post WHERE slug = 'sis-vi-suc-khoe-cong-dong-ky-134';
|
||||
@@ -0,0 +1 @@
|
||||
SELECT id, title, featured_image FROM sis_post WHERE slug = 'sis-vi-suc-khoe-cong-dong-ky-134';
|
||||
@@ -0,0 +1 @@
|
||||
SELECT sequence_name FROM user_sequences;
|
||||
@@ -0,0 +1,72 @@
|
||||
<div class="cc--component-container cc--tabbed-media-content" style="background-color: var(--color-gray-100);">
|
||||
<div class="c--component c--tabbed-media-content">
|
||||
<div class="tabbed-media-content-text-col">
|
||||
<div data-component-id="umass_base:section-title" class="f--section-title">
|
||||
<h2 style="color: var(--color-brand);">LiveStream</h2>
|
||||
</div>
|
||||
<div data-component-id="umass_base:tabbed-container" data-once="tabbed-container">
|
||||
<div class="tab-labels-container" role="tablist">
|
||||
<div class="tab-labels-inner">
|
||||
{{#each livestream_posts}}
|
||||
<a href="#tabbed-content-{{index}}" class="tab-label link-context-dark" role="tab" aria-selected="false" aria-controls="tabbed-content-{{index}}">{{title}}</a>
|
||||
{{/each}}
|
||||
</div>
|
||||
</div>
|
||||
<div class="tab-content-container">
|
||||
{{#each livestream_posts}}
|
||||
<div class="tab-content-panel" id="tabbed-content-{{index}}" role="tabpanel" aria-live="polite">
|
||||
<div class="f--field f--cta-title">
|
||||
<h2 style="color: var(--color-black);"> {{excerpt}} </h2>
|
||||
</div>
|
||||
<div data-component-id="umass_base:description" class="f--description">
|
||||
<div style="color:var(--color-black);">{{content}}</div>
|
||||
</div>
|
||||
<div class="cta-container">
|
||||
<div class="f--field f--button">
|
||||
<a href="{{slug}}" class="button-primary button-context-light " aria-label="Tìm Hiểu Thêm" data-component-id="umass_base:button">
|
||||
<span class="button-text"> Tìm Hiểu Thêm </span>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{{/each}}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="tabbed-media-content-media-col">
|
||||
{{#each livestream_posts}}
|
||||
<div class="tabbed-media-content-media-item with-video" data-tab-id="tabbed-content-{{index}}">
|
||||
<div class="f--field f--image">
|
||||
<img src="{{featuredImageUrl}}" data-src="{{featuredImageUrl}}" class="lazyload" alt="{{title}}">
|
||||
</div>
|
||||
<div class="f--field f--button">
|
||||
<a href="#" class="button-play button-context-light " aria-label="Play video" data-component-id="umass_base:button">
|
||||
<span class="button-icon button-icon-play">
|
||||
<svg width="18" height="27" viewBox="0 0 18 27" fill="currentColor" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M18 13.5L0 0V27L18 13.5Z"></path>
|
||||
</svg>
|
||||
</span>
|
||||
<span class="button-text visually-hidden"> Play </span>
|
||||
</a>
|
||||
</div>
|
||||
<div data-component-id="umass_base:video-embed" class="f--field f--video-embed">
|
||||
<iframe title="Video Content" width="900" height="1600" src="{{metaDescription}}" frameborder="0" allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture" allowfullscreen=""></iframe>
|
||||
</div>
|
||||
</div>
|
||||
{{/each}}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<script>
|
||||
document.addEventListener("DOMContentLoaded", function() {
|
||||
// Set the first tab and panel as active if they exist
|
||||
var tabs = document.querySelectorAll('.tabbed-media-content-media-item[data-tab-id="tabbed-content-0"]');
|
||||
if(tabs.length > 0) tabs[0].classList.add('is-active');
|
||||
|
||||
var panels = document.querySelectorAll('#tabbed-content-0.tab-content-panel');
|
||||
if(panels.length > 0) panels[0].classList.add('is-active');
|
||||
|
||||
var labels = document.querySelectorAll('a.tab-label[aria-controls="tabbed-content-0"]');
|
||||
if(labels.length > 0) labels[0].setAttribute('aria-selected', 'true');
|
||||
});
|
||||
</script>
|
||||
@@ -1,31 +1,180 @@
|
||||
<div data-component-id="umass_base:block-multiple-ctas" data-background="solid" data-layout-variant="default">
|
||||
<div class="container" th:unless="${ctaMenu != null and not #lists.isEmpty(ctaMenu.items)}">
|
||||
<div class="text-container">
|
||||
<div data-component-id="umass_base:section-title" class="f--section-title">
|
||||
<h2>TÌM HIỂU<span class="highlight">CHUYÊN KHOA</span></h2>
|
||||
</div>
|
||||
</div>
|
||||
<div class="links-container">
|
||||
<div class="f--field f--button">
|
||||
<a href="https://www.umass.edu/admissions/apply" class="button-text-link button-context-light " aria-label="Apply" target="_self" data-component-id="umass_base:button">
|
||||
<span class="button-text"> Apply </span>
|
||||
</a>
|
||||
</div>
|
||||
<div class="f--field f--button">
|
||||
<a href="https://www.umass.edu/gateway/academics/explore-our-programs" class="button-text-link button-context-light " aria-label="Majors & Minors" target="_self" data-component-id="umass_base:button">
|
||||
<span class="button-text"> Majors & Minors </span>
|
||||
</a>
|
||||
</div>
|
||||
<div class="f--field f--button">
|
||||
<a href="https://www.umass.edu/admissions/undergraduate-admissions/costs-aid" class="button-text-link button-context-light " aria-label="Tuition & Costs" target="_self" data-component-id="umass_base:button">
|
||||
<span class="button-text"> Tuition & Costs </span>
|
||||
</a>
|
||||
</div>
|
||||
<div class="f--field f--button">
|
||||
<a href="https://www.umass.edu/admissions/visit" class="button-text-link button-context-light " aria-label="Take a Tour" target="_self" data-component-id="umass_base:button">
|
||||
<span class="button-text"> Take a Tour </span>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<body>
|
||||
<div class="cc--component-container cc--tabbed-media-content" style="background-color: var(--color-gray-100);">
|
||||
<div class="c--component c--tabbed-media-content">
|
||||
<div class="tabbed-media-content-text-col">
|
||||
<div data-component-id="umass_base:section-title" class="f--section-title">
|
||||
<h2 style="color: var(--color-brand);">LiveStream tháng 07</h2>
|
||||
</div>
|
||||
<div data-component-id="umass_base:tabbed-container" data-once="tabbed-container">
|
||||
<div class="tab-labels-container" role="tablist">
|
||||
<div class="tab-labels-inner">
|
||||
<a href="https://www.umass.edu/#tabbed-content-campus-life" class="tab-label link-context-dark" role="tab" aria-selected="true" aria-controls="tabbed-content-campus-life">Tuần 1</a>
|
||||
<a href="https://www.umass.edu/#tabbed-content-campus-housing" class="tab-label link-context-dark" role="tab" aria-selected="false" aria-controls="tabbed-content-campus-housing">Tuần 2</a>
|
||||
<a href="https://www.umass.edu/#tabbed-content-dining" class="tab-label link-context-dark" role="tab" aria-selected="false" aria-controls="tabbed-content-dining">Tuần 3</a>
|
||||
<a href="https://www.umass.edu/#tabbed-content-around-amherst" class="tab-label link-context-dark" role="tab" aria-selected="false" aria-controls="tabbed-content-around-amherst">Tuần 4</a>
|
||||
</div>
|
||||
</div>
|
||||
<div class="tab-content-container">
|
||||
<div class="tab-content-panel is-active" id="tabbed-content-campus-life" role="tabpanel" aria-live="polite">
|
||||
<div class="f--field f--cta-title">
|
||||
<h2 style="color: var(--color-black);"> Tầm soát và phòng ngừa ung thư gan </h2>
|
||||
</div>
|
||||
<div data-component-id="umass_base:description" class="f--description">
|
||||
<p style="color:var(--color-black);">Ung thư gan là một trong những bệnh ung thư có tỷ lệ tử vong hàng đầu tại Việt Nam. Đáng lo ngại, phần lớn người bệnh chỉ được phát hiện khi bệnh đã ở giai đoạn muộn, khi các cơ hội điều trị hiệu quả đã bị thu hẹp đáng kể.</p>
|
||||
</div>
|
||||
<div class="cta-container">
|
||||
<div class="f--field f--button">
|
||||
<a href="https://www.umass.edu/gateway/campus-life/student-activities" class="button-primary button-context-light " aria-label="Tìm Hiểu Thêm" data-component-id="umass_base:button">
|
||||
<span class="button-text"> Tìm Hiểu Thêm </span>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="tab-content-panel" id="tabbed-content-campus-housing" role="tabpanel" aria-live="polite">
|
||||
<div class="f--field f--cta-title">
|
||||
<h3> Your Campus Home </h3>
|
||||
</div>
|
||||
<div data-component-id="umass_base:description" class="f--description">
|
||||
<p>Choose from vibrant residential communities where students live, study, and build lasting friendships steps from the classroom.</p>
|
||||
</div>
|
||||
<div class="cta-container">
|
||||
<div class="f--field f--button">
|
||||
<a href="https://www.umass.edu/gateway/campus-life/living-and-dining" class="button-primary button-context-light " aria-label="Learn About Living at UMass" data-component-id="umass_base:button">
|
||||
<span class="button-text"> Tìm hiểu thêm </span>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="tab-content-panel" id="tabbed-content-dining" role="tabpanel" aria-live="polite">
|
||||
<div class="f--field f--cta-title">
|
||||
<h3> Food Worth Talking About </h3>
|
||||
</div>
|
||||
<div data-component-id="umass_base:description" class="f--description">
|
||||
<p>Discover why UMass dining is ranked #1 nationally—recognized for quality, variety, and sustainability.</p>
|
||||
</div>
|
||||
<div class="cta-container">
|
||||
<div class="f--field f--button">
|
||||
<a href="https://www.umassdining.com/" class="button-primary button-context-light ext" aria-label="Learn Why UMass is #1 in Dining" data-component-id="umass_base:button" data-extlink="">
|
||||
<span class="button-text"> Learn Why UMass is #1 in Dining </span>
|
||||
<svg focusable="false" width="1em" height="1em" class="ext" data-extlink-placement="append" aria-label="(link is external)" viewBox="0 0 80 40" role="img" aria-hidden="false">
|
||||
<title>(link is external)</title>
|
||||
<path d="M48 26c-1.1 0-2 0.9-2 2v26H10V18h26c1.1 0 2-0.9 2-2s-0.9-2-2-2H8c-1.1 0-2 0.9-2 2v40c0 1.1 0.9 2 2 2h40c1.1 0 2-0.9 2-2V28C50 26.9 49.1 26 48 26z"></path>
|
||||
<path d="M56 6H44c-1.1 0-2 0.9-2 2s0.9 2 2 2h7.2L30.6 30.6c-0.8 0.8-0.8 2 0 2.8C31 33.8 31.5 34 32 34s1-0.2 1.4-0.6L54 12.8V20c0 1.1 0.9 2 2 2s2-0.9 2-2V8C58 6.9 57.1 6 56 6z"></path>
|
||||
</svg>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="tab-content-panel" id="tabbed-content-around-amherst" role="tabpanel" aria-live="polite">
|
||||
<div class="f--field f--cta-title">
|
||||
<h3> Amherst, Uncommon </h3>
|
||||
</div>
|
||||
<div data-component-id="umass_base:description" class="f--description">
|
||||
<p>A vibrant creative culture, great food, and the natural beauty of the Pioneer Valley come together to shape this town’s distinctive, welcoming spirit.</p>
|
||||
</div>
|
||||
<div class="cta-container">
|
||||
<div class="f--field f--button">
|
||||
<a href="https://www.umass.edu/gateway/student-life/life-amherst" class="button-primary button-context-light " aria-label="Learn More About Amherst" data-component-id="umass_base:button">
|
||||
<span class="button-text"> Learn More About Amherst </span>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="tabbed-media-content-media-col">
|
||||
<div class="tabbed-media-content-media-item is-active with-video" data-tab-id="tabbed-content-campus-life">
|
||||
<div class="f--field f--image">
|
||||
<img data-src="https://www.umass.edu/sites/default/files/styles/9_16_720x1280/public/2026-03/medium_jpg-2026_Vertical_Assets_5179_John_Solem_.jpg?h=7c5befa5&itok=DZUe-3fS" class=" ls-is-cached lazyloaded" alt="A UMass student plays ping pong." src="/UMass%20Amherst%20_%20UMass%20Amherst_files/medium_jpg-2026_Vertical_Assets_5179_John_Solem_.jpg">
|
||||
</div>
|
||||
<div class="f--field f--button">
|
||||
<a href="https://www.umass.edu/#" class="button-play button-context-light " aria-label="Play video" data-component-id="umass_base:button">
|
||||
<span class="button-icon button-icon-play">
|
||||
<svg width="18" height="27" viewBox="0 0 18 27" fill="currentColor" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M18 13.5L0 0V27L18 13.5Z"></path>
|
||||
</svg>
|
||||
</span>
|
||||
<span class="button-text visually-hidden"> Play </span>
|
||||
</a>
|
||||
</div>
|
||||
<div data-component-id="umass_base:video-embed" class="f--field f--video-embed">
|
||||
<iframe title="Video Content" id="video-132086-1" width="900" height="1600" src="https://www.youtube.com/embed/q0ZxZVbnMqs" frameborder="0" allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture" allowfullscreen=""></iframe>
|
||||
</div>
|
||||
</div>
|
||||
<div class="tabbed-media-content-media-item with-video" data-tab-id="tabbed-content-campus-housing">
|
||||
<div class="f--field f--image">
|
||||
<img data-src="https://www.umass.edu/sites/default/files/styles/9_16_720x1280/public/2026-03/FY26_Vertical-Campus-Housing.jpg?h=75081741&itok=6kDcYqy3" class="lazyload" alt="A UMass student sits on her bed in a dorm room.">
|
||||
</div>
|
||||
<div class="f--field f--button">
|
||||
<a href="https://www.umass.edu/#" class="button-play button-context-light " aria-label="Play video" data-component-id="umass_base:button">
|
||||
<span class="button-icon button-icon-play">
|
||||
<svg width="18" height="27" viewBox="0 0 18 27" fill="currentColor" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M18 13.5L0 0V27L18 13.5Z"></path>
|
||||
</svg>
|
||||
</span>
|
||||
<span class="button-text visually-hidden"> Play </span>
|
||||
</a>
|
||||
</div>
|
||||
<div data-component-id="umass_base:video-embed" class="f--field f--video-embed">
|
||||
<iframe title="Video Content" id="video-132086-2" width="900" height="1600" src="https://www.youtube.com/embed/7D_TnBztQhU" frameborder="0" allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture" allowfullscreen=""></iframe>
|
||||
</div>
|
||||
</div>
|
||||
<div class="tabbed-media-content-media-item with-video" data-tab-id="tabbed-content-dining">
|
||||
<div class="f--field f--image">
|
||||
<img data-src="https://www.umass.edu/sites/default/files/styles/9_16_720x1280/public/2026-03/FY26_Vertical-Dining2.jpg?h=75081741&itok=_34BDcqA" class="lazyload" alt="A student gets food at a UMass Amherst dining hall.">
|
||||
</div>
|
||||
<div class="f--field f--button">
|
||||
<a href="https://www.umass.edu/#" class="button-play button-context-light " aria-label="Play video" data-component-id="umass_base:button">
|
||||
<span class="button-icon button-icon-play">
|
||||
<svg width="18" height="27" viewBox="0 0 18 27" fill="currentColor" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M18 13.5L0 0V27L18 13.5Z"></path>
|
||||
</svg>
|
||||
</span>
|
||||
<span class="button-text visually-hidden"> Play </span>
|
||||
</a>
|
||||
</div>
|
||||
<div data-component-id="umass_base:video-embed" class="f--field f--video-embed">
|
||||
<iframe title="Video Content" id="video-132086-3" width="900" height="1600" src="https://www.youtube.com/embed/YRzZ9aRZ69w" frameborder="0" allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture" allowfullscreen=""></iframe>
|
||||
</div>
|
||||
</div>
|
||||
<div class="tabbed-media-content-media-item with-video" data-tab-id="tabbed-content-around-amherst">
|
||||
<div class="f--field f--image">
|
||||
<img data-src="https://www.umass.edu/sites/default/files/styles/9_16_720x1280/public/2026-03/FY26_Vertical-Downtown-Amherst.jpg?h=75081741&itok=irWjha4q" class="lazyload" alt="A UMass student holds a hote bag that reads "I Love Amherst."">
|
||||
</div>
|
||||
<div class="f--field f--button">
|
||||
<a href="https://www.umass.edu/#" class="button-play button-context-light " aria-label="Play video" data-component-id="umass_base:button">
|
||||
<span class="button-icon button-icon-play">
|
||||
<svg width="18" height="27" viewBox="0 0 18 27" fill="currentColor" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M18 13.5L0 0V27L18 13.5Z"></path>
|
||||
</svg>
|
||||
</span>
|
||||
<span class="button-text visually-hidden"> Play </span>
|
||||
</a>
|
||||
</div>
|
||||
<div data-component-id="umass_base:video-embed" class="f--field f--video-embed">
|
||||
<iframe title="Video Content" id="video-132086-4" width="900" height="1600" src="https://www.youtube.com/embed/agqIJlJpbAY" frameborder="0" allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture" allowfullscreen=""></iframe>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
<style>* { box-sizing: border-box; } body {margin: 0;}
|
||||
.tab-labels-inner {
|
||||
border-bottom-color: var(--color-gray-800);
|
||||
.tab-label {
|
||||
font-weight: var(--font-weight-bold) !important;
|
||||
color: var(--color-black) !important;
|
||||
}
|
||||
.tab-label {
|
||||
&[aria-selected="true"] {
|
||||
font-weight: 700;
|
||||
color: var(--color-black);
|
||||
border-bottom: 2px solid var(--color-brand) !important;
|
||||
position: relative;
|
||||
z-index: 10;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,22 @@
|
||||
import java.sql.Connection;
|
||||
import java.sql.DriverManager;
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.Statement;
|
||||
|
||||
public class ReadSnippets {
|
||||
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 slug, content FROM html_snippet");
|
||||
while (rs.next()) {
|
||||
System.out.println("Snippet: " + rs.getString("slug"));
|
||||
if (rs.getString("slug").equals("content_main")) {
|
||||
System.out.println(rs.getString("content"));
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
Binary file not shown.
@@ -56,6 +56,8 @@ public class PostController {
|
||||
return "posts/sidebar";
|
||||
case FULL_WIDTH:
|
||||
return "posts/full-width";
|
||||
case LIVESTREAM:
|
||||
return "posts/livestream";
|
||||
case STANDARD:
|
||||
default:
|
||||
return "posts/standard";
|
||||
|
||||
+1
-1
@@ -156,7 +156,7 @@ public class ManagePostController {
|
||||
}
|
||||
postService.saveWithTags(post, tagNames);
|
||||
redirectAttributes.addFlashAttribute("successMessage", "Post updated successfully!");
|
||||
return "redirect:/manage/posts";
|
||||
return "redirect:/manage/posts/" + id + "/edit";
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -63,6 +63,10 @@ public class Post extends AbstractAuditingEntity<Long> {
|
||||
@Column(name = "event_time")
|
||||
private java.time.Instant eventTime;
|
||||
|
||||
@Size(max = 255)
|
||||
@Column(name = "location", length = 255)
|
||||
private String location;
|
||||
|
||||
@ManyToOne(fetch = FetchType.LAZY)
|
||||
@JoinColumn(name = "category_id")
|
||||
private Category category;
|
||||
@@ -166,6 +170,14 @@ public class Post extends AbstractAuditingEntity<Long> {
|
||||
this.eventTime = eventTime;
|
||||
}
|
||||
|
||||
public String getLocation() {
|
||||
return location;
|
||||
}
|
||||
|
||||
public void setLocation(String location) {
|
||||
this.location = location;
|
||||
}
|
||||
|
||||
@jakarta.persistence.Transient
|
||||
public String getEventTimeLocal() {
|
||||
if (this.eventTime != null) {
|
||||
|
||||
@@ -7,5 +7,6 @@ public enum PostLayout {
|
||||
STANDARD,
|
||||
SIDEBAR,
|
||||
FULL_WIDTH,
|
||||
EVENT
|
||||
EVENT,
|
||||
LIVESTREAM
|
||||
}
|
||||
|
||||
+109
-9
@@ -1,19 +1,20 @@
|
||||
package com.sisvietnamvn.web.service;
|
||||
|
||||
import com.sisvietnamvn.web.domain.ComponentTemplate;
|
||||
import com.sisvietnamvn.web.domain.Menu;
|
||||
import com.sisvietnamvn.web.domain.MenuItem;
|
||||
import com.sisvietnamvn.web.repository.ComponentTemplateRepository;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import com.sisvietnamvn.web.domain.ComponentTemplate;
|
||||
import com.sisvietnamvn.web.domain.Menu;
|
||||
import com.sisvietnamvn.web.domain.MenuItem;
|
||||
import com.sisvietnamvn.web.repository.ComponentTemplateRepository;
|
||||
|
||||
/**
|
||||
* Service for managing Component Templates and rendering them with dynamic data.
|
||||
*
|
||||
@@ -221,6 +222,8 @@ public class ComponentTemplateService {
|
||||
itemHtml = itemHtml.replace("{{title}}", safeTitle);
|
||||
itemHtml = itemHtml.replace("{{slug}}", post.getSlug() != null ? post.getSlug() : "");
|
||||
itemHtml = itemHtml.replace("{{excerpt}}", safeExcerpt);
|
||||
itemHtml = itemHtml.replace("{{content}}", post.getContent() != null ? parseContentToHtml(post.getContent()) : "");
|
||||
itemHtml = itemHtml.replace("{{metaDescription}}", post.getMetaDescription() != null ? org.springframework.web.util.HtmlUtils.htmlEscape(post.getMetaDescription()) : "");
|
||||
itemHtml = itemHtml.replace("{{featuredImageUrl}}", post.getFeaturedImage() != null ? post.getFeaturedImage() : "");
|
||||
String dateStr = post.getCreatedDate() != null ? formatter.format(post.getCreatedDate()) : "";
|
||||
itemHtml = itemHtml.replace("{{date}}", dateStr);
|
||||
@@ -235,6 +238,13 @@ public class ComponentTemplateService {
|
||||
itemHtml = itemHtml.replace("{{eventTimeStr}}", "");
|
||||
}
|
||||
|
||||
if (post.getLocation() != null && !post.getLocation().isEmpty()) {
|
||||
String locHtml = "<div class=\"event-location\">" + org.springframework.web.util.HtmlUtils.htmlEscape(post.getLocation()) + "</div>";
|
||||
itemHtml = itemHtml.replace("{{locationHtml}}", locHtml);
|
||||
} else {
|
||||
itemHtml = itemHtml.replace("{{locationHtml}}", "");
|
||||
}
|
||||
|
||||
itemHtml = itemHtml.replace("{{index}}", String.valueOf(index));
|
||||
rendered.append(itemHtml);
|
||||
index++;
|
||||
@@ -257,6 +267,56 @@ public class ComponentTemplateService {
|
||||
public void seedDefaults() {
|
||||
seedCtaButtons();
|
||||
seedInfoDropdown();
|
||||
seedNewsGrid();
|
||||
}
|
||||
|
||||
private void seedNewsGrid() {
|
||||
Optional<ComponentTemplate> existing = templateRepository.findBySlug("news-grid");
|
||||
if (existing.isPresent()) {
|
||||
ComponentTemplate t = existing.get();
|
||||
if (t.getHtmlTemplate() == null || !t.getHtmlTemplate().contains("<style>")) {
|
||||
return; // Already clean
|
||||
}
|
||||
// Update the existing one
|
||||
t.setHtmlTemplate(getNewsGridHtml());
|
||||
templateRepository.save(t);
|
||||
LOG.info("Cleaned up hardcoded CSS in news-grid component template");
|
||||
return;
|
||||
}
|
||||
|
||||
ComponentTemplate t = new ComponentTemplate();
|
||||
t.setSlug("news-grid");
|
||||
t.setName("News Grid");
|
||||
t.setDescription("Dynamic grid layout for news.");
|
||||
t.setActive(true);
|
||||
t.setHtmlTemplate(getNewsGridHtml());
|
||||
templateRepository.save(t);
|
||||
LOG.info("Seeded default component template: news-grid");
|
||||
}
|
||||
|
||||
private String getNewsGridHtml() {
|
||||
return "{{#each news_posts}}\n" +
|
||||
"<div class=\"featured-grid__item\">\n" +
|
||||
" <article class=\"news-card news-card--featured\">\n" +
|
||||
" <div class=\"news-card__image\">\n" +
|
||||
" <div>\n" +
|
||||
" <img loading=\"lazy\" src=\"{{featuredImageUrl}}\" alt=\"{{title}}\">\n" +
|
||||
" </div>\n" +
|
||||
" </div>\n" +
|
||||
" <div class=\"news-card__content\">\n" +
|
||||
" <div class=\"featured-grid__category\">\n" +
|
||||
" <a href=\"#\">TIN TỨC</a>\n" +
|
||||
" </div>\n" +
|
||||
" <h3 class=\"news-card__title\">\n" +
|
||||
" <a href=\"/post/{{slug}}\" rel=\"bookmark\">\n" +
|
||||
" <span>{{title}}</span>\n" +
|
||||
" </a>\n" +
|
||||
" </h3>\n" +
|
||||
" <div class=\"news-card__date\">{{date}}</div>\n" +
|
||||
" </div>\n" +
|
||||
" </article>\n" +
|
||||
"</div>\n" +
|
||||
"{{/each}}";
|
||||
}
|
||||
|
||||
private void seedCtaButtons() {
|
||||
@@ -325,4 +385,44 @@ public class ComponentTemplateService {
|
||||
templateRepository.save(t);
|
||||
LOG.info("Seeded default component template: info-dropdown");
|
||||
}
|
||||
|
||||
private String parseContentToHtml(String content) {
|
||||
if (content == null || !content.trim().startsWith("{")) {
|
||||
return content;
|
||||
}
|
||||
try {
|
||||
com.fasterxml.jackson.databind.ObjectMapper mapper = new com.fasterxml.jackson.databind.ObjectMapper();
|
||||
java.util.Map<String, Object> data = mapper.readValue(content, new com.fasterxml.jackson.core.type.TypeReference<>() {});
|
||||
if (data.containsKey("blocks")) {
|
||||
java.util.List<java.util.Map<String, Object>> blocks = (java.util.List<java.util.Map<String, Object>>) data.get("blocks");
|
||||
StringBuilder sb = new StringBuilder();
|
||||
for (java.util.Map<String, Object> block : blocks) {
|
||||
String type = (String) block.get("type");
|
||||
java.util.Map<String, Object> blockData = (java.util.Map<String, Object>) block.get("data");
|
||||
if (blockData != null) {
|
||||
if ("paragraph".equals(type)) {
|
||||
sb.append("<p>").append(blockData.get("text")).append("</p>");
|
||||
} else if ("header".equals(type)) {
|
||||
sb.append("<h").append(blockData.get("level")).append(">").append(blockData.get("text")).append("</h").append(blockData.get("level")).append(">");
|
||||
} else if ("list".equals(type)) {
|
||||
String style = (String) blockData.get("style");
|
||||
String listTag = "ordered".equals(style) ? "ol" : "ul";
|
||||
sb.append("<").append(listTag).append(">");
|
||||
java.util.List<String> items = (java.util.List<String>) blockData.get("items");
|
||||
if (items != null) {
|
||||
for (String item : items) {
|
||||
sb.append("<li>").append(item).append("</li>");
|
||||
}
|
||||
}
|
||||
sb.append("</").append(listTag).append(">");
|
||||
}
|
||||
}
|
||||
}
|
||||
return sb.toString();
|
||||
}
|
||||
} catch (Exception e) {
|
||||
// Fallback to raw content if parsing fails
|
||||
}
|
||||
return content;
|
||||
}
|
||||
}
|
||||
|
||||
+7
-3
@@ -6,12 +6,16 @@
|
||||
xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-4.20.xsd">
|
||||
|
||||
<changeSet id="20260714080000-1" author="antigravity">
|
||||
<preConditions onFail="MARK_RAN">
|
||||
<sqlCheck expectedResult="0">SELECT COUNT(*) FROM sis_component_template WHERE slug = 'news-grid'</sqlCheck>
|
||||
</preConditions>
|
||||
<insert tableName="sis_component_template">
|
||||
<column name="id" valueComputed="(select coalesce(max(id), 0) + 1 from sis_component_template)"/>
|
||||
<column name="slug" value="news-grid"/>
|
||||
<column name="name" value="News Grid"/>
|
||||
<column name="description" value="Dynamic grid layout for news."/>
|
||||
<column name="active" valueBoolean="true"/>
|
||||
<column name="created_by" value="system"/>
|
||||
<column name="html_template"><![CDATA[{{#each news_posts}}
|
||||
<div class="featured-grid__item">
|
||||
<article class="news-card news-card--featured">
|
||||
@@ -43,6 +47,7 @@
|
||||
<column name="name" value="Events List"/>
|
||||
<column name="description" value="List layout for events."/>
|
||||
<column name="active" valueBoolean="true"/>
|
||||
<column name="created_by" value="system"/>
|
||||
<column name="html_template"><![CDATA[<style>
|
||||
.campus-events-widget { background: transparent; padding: 0; font-family: inherit; }
|
||||
.campus-events-widget .events-list { list-style: none; margin: 0; padding: 0; }
|
||||
@@ -95,6 +100,8 @@
|
||||
</div>]]></column>
|
||||
<column name="created_date" valueComputed="CURRENT_TIMESTAMP"/>
|
||||
</insert>
|
||||
</changeSet>
|
||||
|
||||
<changeSet id="20260714080000-3" author="antigravity" runAlways="true">
|
||||
<update tableName="sis_component_template">
|
||||
<column name="html_template"><![CDATA[{{#each news_posts}}
|
||||
@@ -122,9 +129,6 @@
|
||||
<where>slug = 'news-grid'</where>
|
||||
</update>
|
||||
</changeSet>
|
||||
</databaseChangeLog>
|
||||
|
||||
xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-4.20.xsd">
|
||||
|
||||
<changeSet id="20260714080000-2" author="antigravity" runAlways="true">
|
||||
<update tableName="sis_component_template">
|
||||
|
||||
+20
@@ -0,0 +1,20 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<databaseChangeLog
|
||||
xmlns="http://www.liquibase.org/xml/ns/dbchangelog"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-latest.xsd">
|
||||
|
||||
<changeSet id="20260714112000-1" author="antigravity">
|
||||
<preConditions onFail="MARK_RAN">
|
||||
<not>
|
||||
<columnExists tableName="sis_post" columnName="location"/>
|
||||
</not>
|
||||
</preConditions>
|
||||
<addColumn tableName="sis_post">
|
||||
<column name="location" type="varchar(255)">
|
||||
<constraints nullable="true" />
|
||||
</column>
|
||||
</addColumn>
|
||||
</changeSet>
|
||||
|
||||
</databaseChangeLog>
|
||||
+64
@@ -0,0 +1,64 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<databaseChangeLog
|
||||
xmlns="http://www.liquibase.org/xml/ns/dbchangelog"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-latest.xsd">
|
||||
|
||||
<changeSet id="20260714113000-1" author="antigravity" runAlways="true">
|
||||
<update tableName="sis_component_template">
|
||||
<column name="html_template"><![CDATA[<style>
|
||||
.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; }
|
||||
}
|
||||
</style>
|
||||
<div class="campus-events-widget">
|
||||
<div class="events-list">
|
||||
{{#each event_posts}}
|
||||
<div class="teaser-item">
|
||||
<div class="event-wrapper">
|
||||
<div class="event-date">
|
||||
<div class="event-date__month">{{eventMonth}}</div>
|
||||
<div class="event-date__day">{{eventDay}}</div>
|
||||
</div>
|
||||
<div class="event-details">
|
||||
<div class="event-title">
|
||||
<a href="/post/{{slug}}">{{title}}</a>
|
||||
</div>
|
||||
<div class="event-time">{{eventTimeStr}}</div>
|
||||
{{locationHtml}}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{{/each}}
|
||||
</div>
|
||||
</div>]]></column>
|
||||
<where>slug = 'events-list'</where>
|
||||
</update>
|
||||
</changeSet>
|
||||
|
||||
</databaseChangeLog>
|
||||
@@ -37,4 +37,6 @@
|
||||
<!-- jhipster-needle-liquibase-add-constraints-changelog - JHipster will add liquibase constraints changelogs here -->
|
||||
<!-- jhipster-needle-liquibase-add-incremental-changelog - JHipster will add incremental liquibase changelogs here -->
|
||||
<include file="config/liquibase/changelog/20260714080000_seed_news_events_components.xml" relativeToChangelogFile="false"/>
|
||||
<include file="config/liquibase/changelog/20260714112000_add_location_to_post.xml" relativeToChangelogFile="false"/>
|
||||
<include file="config/liquibase/changelog/20260714113000_update_events_list.xml" relativeToChangelogFile="false"/>
|
||||
</databaseChangeLog>
|
||||
|
||||
+8
-8
File diff suppressed because one or more lines are too long
@@ -60,4 +60,465 @@
|
||||
/* Ensures it sits above the video */
|
||||
}
|
||||
|
||||
/* News Grid Tablet Layout */
|
||||
@media screen and (min-width: 769px) and (max-width: 1024px) {
|
||||
.news-list {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(2, 1fr);
|
||||
gap: 24px;
|
||||
align-items: stretch;
|
||||
}
|
||||
.featured-grid__item {
|
||||
height: 100%;
|
||||
display: flex;
|
||||
}
|
||||
.featured-grid__item .news-card--featured {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: flex-start;
|
||||
border: 1px solid #881C1C;
|
||||
border-radius: 16px;
|
||||
padding: 16px;
|
||||
box-sizing: border-box;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
gap: 16px;
|
||||
background: #fff;
|
||||
margin-bottom: 0 !important;
|
||||
}
|
||||
.featured-grid__item .news-card__image {
|
||||
flex: none;
|
||||
width: 100%;
|
||||
aspect-ratio: 1 / 1;
|
||||
margin-bottom: 0 !important;
|
||||
}
|
||||
.featured-grid__item .news-card__image > div {
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
}
|
||||
.featured-grid__item .news-card__image img {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
object-fit: cover;
|
||||
object-position: center;
|
||||
border-radius: 8px;
|
||||
}
|
||||
.featured-grid__item .news-card__content {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: flex-start;
|
||||
min-width: 0;
|
||||
padding: 0 !important;
|
||||
margin: 0 !important;
|
||||
}
|
||||
.featured-grid__item .featured-grid__category {
|
||||
margin-bottom: 12px;
|
||||
}
|
||||
.featured-grid__item .featured-grid__category a {
|
||||
display: inline-block;
|
||||
background-color: #f2f2f2;
|
||||
color: #881C1C;
|
||||
padding: 4px 8px;
|
||||
border-radius: 4px;
|
||||
font-size: 0.75rem;
|
||||
font-weight: bold;
|
||||
text-decoration: none;
|
||||
text-transform: uppercase;
|
||||
}
|
||||
.featured-grid__item .news-card__title {
|
||||
font-size: 1.1rem;
|
||||
font-weight: 700;
|
||||
margin-top: 0;
|
||||
margin-bottom: 12px;
|
||||
line-height: 1.4;
|
||||
}
|
||||
.featured-grid__item .news-card__title a {
|
||||
color: #000;
|
||||
text-decoration: none;
|
||||
}
|
||||
.featured-grid__item .news-card__title a:hover {
|
||||
color: #881C1C;
|
||||
}
|
||||
.featured-grid__item .news-card__date {
|
||||
margin-top: auto;
|
||||
color: #881C1C;
|
||||
font-size: 0.85rem;
|
||||
font-weight: 500;
|
||||
}
|
||||
}
|
||||
|
||||
/* News Grid Desktop Layout */
|
||||
@media screen and (min-width: 1025px){
|
||||
.news-list {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(2, 1fr);
|
||||
gap: 24px;
|
||||
align-items: stretch;
|
||||
}
|
||||
|
||||
.education-column .news-list {
|
||||
grid-template-columns: repeat(3, 1fr);
|
||||
}
|
||||
|
||||
.featured-grid__item {
|
||||
height: 100%;
|
||||
display: flex;
|
||||
}
|
||||
.featured-grid__item .news-card--featured {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: flex-start;
|
||||
border: 1px solid #881C1C;
|
||||
border-radius: 16px;
|
||||
padding: 16px;
|
||||
box-sizing: border-box;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
gap: 16px;
|
||||
background: #fff;
|
||||
margin-bottom: 0 !important;
|
||||
}
|
||||
.featured-grid__item .news-card__image {
|
||||
flex: 0 0 170px;
|
||||
width: 100%;
|
||||
height: 170px;
|
||||
margin-bottom: 0 !important;
|
||||
}
|
||||
.featured-grid__item .news-card__image > div {
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
}
|
||||
.featured-grid__item .news-card__image img {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
object-fit: cover;
|
||||
object-position: center;
|
||||
border-radius: 8px;
|
||||
}
|
||||
.featured-grid__item .news-card__content {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: flex-start;
|
||||
min-width: 0;
|
||||
padding: 0 !important;
|
||||
margin: 0 !important;
|
||||
}
|
||||
.featured-grid__item .featured-grid__category {
|
||||
margin-bottom: 12px;
|
||||
}
|
||||
.featured-grid__item .featured-grid__category a {
|
||||
display: inline-block;
|
||||
background-color: #f2f2f2;
|
||||
color: #881C1C;
|
||||
padding: 4px 8px;
|
||||
border-radius: 4px;
|
||||
font-size: 0.75rem;
|
||||
font-weight: bold;
|
||||
text-decoration: none;
|
||||
text-transform: uppercase;
|
||||
}
|
||||
.featured-grid__item .news-card__title {
|
||||
font-size: 1.1rem;
|
||||
font-weight: 700;
|
||||
margin-top: 0;
|
||||
margin-bottom: 12px;
|
||||
line-height: 1.4;
|
||||
}
|
||||
.featured-grid__item .news-card__title a {
|
||||
color: #000;
|
||||
text-decoration: none;
|
||||
}
|
||||
.featured-grid__item .news-card__title a:hover {
|
||||
color: #881C1C;
|
||||
}
|
||||
.featured-grid__item .news-card__date {
|
||||
margin-top: auto;
|
||||
color: #881C1C;
|
||||
font-size: 0.85rem;
|
||||
font-weight: 500;
|
||||
}
|
||||
}
|
||||
|
||||
/* ==========================================================================
|
||||
Desktop Layouts (>= 1024px)
|
||||
========================================================================== */
|
||||
@media screen and (min-width: 1025px) {
|
||||
/* Side-by-side layout for News and Events */
|
||||
.news-events-row {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
gap: 40px;
|
||||
align-items: stretch;
|
||||
}
|
||||
.news-events-row > .news-column {
|
||||
flex: 1.8;
|
||||
min-width: 0;
|
||||
}
|
||||
.news-events-row > .events-column {
|
||||
flex: 1;
|
||||
min-width: 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* ==========================================================================
|
||||
Navigation Container & Mobile Menu
|
||||
========================================================================== */
|
||||
|
||||
/* --- Desktop (>1024px) --- */
|
||||
.navigation-container {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: flex-end;
|
||||
gap: 1.5rem;
|
||||
flex-grow: 1;
|
||||
}
|
||||
|
||||
/* Desktop: show horizontal menu, hide hamburger */
|
||||
@media (min-width: 1025px) {
|
||||
#mobile-hamburger {
|
||||
display: none !important;
|
||||
}
|
||||
#mobile-flyout-container {
|
||||
display: flex !important;
|
||||
align-items: center;
|
||||
}
|
||||
.primary-navigation {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
/* Desktop: hide arrow toggles and back buttons */
|
||||
.mc--main-menu .arrow-toggle,
|
||||
.mc--main-menu .button-back,
|
||||
.mc--main-menu .navigation-title {
|
||||
display: none !important;
|
||||
}
|
||||
/* Desktop: horizontal main menu */
|
||||
.m--main-menu {
|
||||
display: flex;
|
||||
gap: 0;
|
||||
list-style: none;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
.m--main-menu > .menu-item > .link-arrow-wrapper > a {
|
||||
text-transform: uppercase;
|
||||
font-weight: 700;
|
||||
padding: 10px 15px;
|
||||
white-space: nowrap;
|
||||
}
|
||||
}
|
||||
|
||||
/* --- Mobile (<= 768px) --- */
|
||||
@media (max-width: 768px) {
|
||||
/* Hide ambient video on mobile to save bandwidth and use image fallback */
|
||||
.f--ambient-video,
|
||||
.video-controls {
|
||||
display: none !important;
|
||||
}
|
||||
}
|
||||
|
||||
/* Override Tabbed Media Content text colors since background was changed to light gray */
|
||||
.cc--tabbed-media-content .f--description p {
|
||||
color: #000000 !important;
|
||||
}
|
||||
.cc--tabbed-media-content .f--description a {
|
||||
color: var(--color-brand) !important;
|
||||
}
|
||||
|
||||
/* Style tab labels and borders to black */
|
||||
.cc--tabbed-media-content .tab-labels-inner {
|
||||
border-bottom-color: #cccccc !important; /* light gray line for the tab row */
|
||||
}
|
||||
.cc--tabbed-media-content .tab-label {
|
||||
color: #555555 !important; /* dark gray for inactive tabs */
|
||||
font-weight: 700 !important;
|
||||
}
|
||||
.cc--tabbed-media-content .tab-label[aria-selected="true"] {
|
||||
color: #000000 !important; /* solid black for active tab */
|
||||
border-bottom: 3px solid #000000 !important; /* solid black underline for active tab */
|
||||
}
|
||||
|
||||
/* Center children inside tabbed-media-content-media-col */
|
||||
.cc--tabbed-media-content .tabbed-media-content-media-col {
|
||||
align-items: center !important;
|
||||
justify-content: center !important;
|
||||
}
|
||||
|
||||
/* --- Mobile & Tablet (<=1024px) --- */
|
||||
@media (max-width: 1024px) {
|
||||
.navigation-container {
|
||||
gap: 0.5rem;
|
||||
}
|
||||
|
||||
/* Hamburger button */
|
||||
#mobile-hamburger {
|
||||
display: block;
|
||||
z-index: 1001;
|
||||
background: none;
|
||||
border: none;
|
||||
cursor: pointer;
|
||||
padding: 10px;
|
||||
}
|
||||
.hamburger-box {
|
||||
width: 30px;
|
||||
height: 24px;
|
||||
display: inline-block;
|
||||
position: relative;
|
||||
}
|
||||
.hamburger-inner,
|
||||
.hamburger-inner::before,
|
||||
.hamburger-inner::after {
|
||||
width: 30px;
|
||||
height: 3px;
|
||||
background-color: #fff;
|
||||
border-radius: 2px;
|
||||
position: absolute;
|
||||
transition: transform 0.3s ease, opacity 0.2s ease;
|
||||
}
|
||||
.hamburger-inner {
|
||||
top: 50%;
|
||||
transform: translateY(-50%);
|
||||
}
|
||||
.hamburger-inner::before {
|
||||
content: '';
|
||||
top: -9px;
|
||||
}
|
||||
.hamburger-inner::after {
|
||||
content: '';
|
||||
bottom: -9px;
|
||||
}
|
||||
/* Hamburger X state */
|
||||
#mobile-hamburger.is-active .hamburger-inner {
|
||||
transform: rotate(45deg);
|
||||
}
|
||||
#mobile-hamburger.is-active .hamburger-inner::before {
|
||||
top: 0;
|
||||
opacity: 0;
|
||||
}
|
||||
#mobile-hamburger.is-active .hamburger-inner::after {
|
||||
bottom: 0;
|
||||
transform: rotate(-90deg);
|
||||
}
|
||||
|
||||
/* Mobile flyout container */
|
||||
#mobile-flyout-container {
|
||||
display: none;
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: auto;
|
||||
background: #fff;
|
||||
z-index: 1000;
|
||||
overflow-y: auto;
|
||||
overflow-x: hidden;
|
||||
padding-top: 80px;
|
||||
}
|
||||
|
||||
/* Primary navigation inside flyout */
|
||||
.primary-navigation {
|
||||
display: block;
|
||||
}
|
||||
|
||||
/* Main menu list - vertical */
|
||||
.m--main-menu {
|
||||
list-style: none;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
.m--main-menu > .menu-item {
|
||||
border-bottom: 1px solid #e0e0e0;
|
||||
}
|
||||
|
||||
/* Link + arrow wrapper */
|
||||
.link-arrow-wrapper {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
padding: 0;
|
||||
}
|
||||
.link-arrow-wrapper > a {
|
||||
flex: 1;
|
||||
padding: 15px 20px;
|
||||
color: #333;
|
||||
text-decoration: none;
|
||||
font-weight: 700;
|
||||
font-size: 16px;
|
||||
text-transform: uppercase;
|
||||
letter-spacing: 0.05em;
|
||||
}
|
||||
|
||||
/* Arrow toggle button */
|
||||
.arrow-toggle {
|
||||
background: none;
|
||||
border: none;
|
||||
/* border-left: 1px solid #e0e0e0; */
|
||||
/* padding: 15px 20px; */
|
||||
cursor: pointer;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
min-width: 50px;
|
||||
}
|
||||
.arrow-toggle svg {
|
||||
transition: transform 0.3s ease;
|
||||
}
|
||||
.arrow-toggle.is-active svg {
|
||||
transform: rotate(180deg);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* Submenu list */
|
||||
.submenu {
|
||||
list-style: none;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
.submenu .menu-item {
|
||||
border-bottom: 1px solid #f0f0f0;
|
||||
}
|
||||
.submenu .menu-item a,
|
||||
.submenu .menu-item span {
|
||||
display: block;
|
||||
padding: 12px 20px;
|
||||
color: #333;
|
||||
text-decoration: none;
|
||||
font-size: 15px;
|
||||
text-transform: uppercase;
|
||||
font-weight: 600;
|
||||
letter-spacing: 0.03em;
|
||||
}
|
||||
.submenu .menu-item a:hover {
|
||||
background-color: #f5f5f5;
|
||||
color: #881c1c;
|
||||
}
|
||||
|
||||
/* Hide desktop-only elements on mobile */
|
||||
.desktop-only {
|
||||
display: none !important;
|
||||
}
|
||||
|
||||
/* Show mobile-only elements on mobile */
|
||||
.mobile-only {
|
||||
display: block !important;
|
||||
}
|
||||
|
||||
/* Hide quicklink buttons, utility menu, and social links on mobile flyout */
|
||||
.mc--quicklink-button-menu,
|
||||
.mc--utility-menu,
|
||||
[data-component-id="umass_base:header-socials"] {
|
||||
margin-top: 20px;
|
||||
border-top: 2px solid #881c1c;
|
||||
padding-top: 10px;
|
||||
}
|
||||
}
|
||||
|
||||
/* On Desktop, hide mobile-only elements */
|
||||
@media (min-width: 1366) {
|
||||
.mobile-only {
|
||||
display: none !important;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,45 @@
|
||||
document.addEventListener('DOMContentLoaded', function () {
|
||||
document.querySelectorAll('.video-controls').forEach(function (controls) {
|
||||
var playBtn = controls.querySelector('.video-play-button');
|
||||
var pauseBtn = controls.querySelector('.video-pause-button');
|
||||
|
||||
// Find the associated ambient video. In the HTML structure, the .f--ambient-video
|
||||
// container is a sibling (specifically previousElementSibling) of .video-controls.
|
||||
// If not, we fall back to searching within the closest parent.
|
||||
var videoContainer = controls.previousElementSibling;
|
||||
if (!videoContainer || !videoContainer.classList.contains('f--ambient-video')) {
|
||||
var parent = controls.closest('.image-video-container');
|
||||
if (parent) {
|
||||
videoContainer = parent.querySelector('.f--ambient-video');
|
||||
}
|
||||
}
|
||||
|
||||
if (!videoContainer) return;
|
||||
var video = videoContainer.querySelector('video');
|
||||
if (!video) return;
|
||||
|
||||
if (pauseBtn) {
|
||||
pauseBtn.addEventListener('click', function (e) {
|
||||
e.preventDefault();
|
||||
pauseBtn.classList.add('hidden');
|
||||
if (playBtn) {
|
||||
playBtn.classList.add('active');
|
||||
playBtn.focus();
|
||||
}
|
||||
video.pause();
|
||||
});
|
||||
}
|
||||
|
||||
if (playBtn) {
|
||||
playBtn.addEventListener('click', function (e) {
|
||||
e.preventDefault();
|
||||
playBtn.classList.remove('active');
|
||||
if (pauseBtn) {
|
||||
pauseBtn.classList.remove('hidden');
|
||||
pauseBtn.focus();
|
||||
}
|
||||
video.play();
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,88 @@
|
||||
/**
|
||||
* Mobile Menu - Hamburger toggle, submenu accordion interactions.
|
||||
* Pure vanilla JS — jQuery is NOT available.
|
||||
* Only active on mobile/tablet (≤1024px via CSS).
|
||||
*/
|
||||
document.addEventListener('DOMContentLoaded', function () {
|
||||
var hamburger = document.getElementById('mobile-hamburger');
|
||||
var flyout = document.getElementById('mobile-flyout-container');
|
||||
var header = document.querySelector('[data-component-id="umass_base:site-header"]');
|
||||
|
||||
// Helper functions for fade animation
|
||||
function fadeIn(el) {
|
||||
el.style.display = 'block';
|
||||
var anim = el.animate([{ opacity: 0 }, { opacity: 1 }], { duration: 300, fill: 'forwards' });
|
||||
el._fadeAnim = anim;
|
||||
}
|
||||
|
||||
function fadeOut(el) {
|
||||
var anim = el.animate([{ opacity: 1 }, { opacity: 0 }], { duration: 300, fill: 'forwards' });
|
||||
el._fadeAnim = anim;
|
||||
anim.onfinish = function() {
|
||||
if (el._fadeAnim === anim) {
|
||||
el.style.display = 'none';
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
// --- Hamburger toggle ---
|
||||
if (hamburger && flyout) {
|
||||
hamburger.addEventListener('click', function () {
|
||||
var isActive = hamburger.classList.toggle('is-active');
|
||||
if (isActive) {
|
||||
fadeIn(flyout);
|
||||
} else {
|
||||
fadeOut(flyout);
|
||||
// Close all open submenus when closing the flyout
|
||||
flyout.querySelectorAll('.submenu-wrapper').forEach(function (w) {
|
||||
if (w.style.display !== 'none') fadeOut(w);
|
||||
});
|
||||
flyout.querySelectorAll('.arrow-toggle.is-active').forEach(function (a) {
|
||||
a.classList.remove('is-active');
|
||||
});
|
||||
}
|
||||
if (header) header.classList.toggle('mobile-menu-active', isActive);
|
||||
});
|
||||
}
|
||||
|
||||
// --- Arrow toggle: open/close submenu (fade style) ---
|
||||
document.querySelectorAll('#mobile-flyout-container .arrow-toggle').forEach(function (btn) {
|
||||
btn.addEventListener('click', function (e) {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
|
||||
// The submenu-wrapper is the next sibling of .link-arrow-wrapper
|
||||
var linkArrowWrapper = btn.closest('.link-arrow-wrapper');
|
||||
if (!linkArrowWrapper) return;
|
||||
var wrapper = linkArrowWrapper.nextElementSibling;
|
||||
if (!wrapper || !wrapper.classList.contains('submenu-wrapper')) return;
|
||||
|
||||
var isActive = btn.classList.toggle('is-active');
|
||||
if (isActive) {
|
||||
fadeIn(wrapper);
|
||||
} else {
|
||||
fadeOut(wrapper);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
// --- Back button: close submenu ---
|
||||
document.querySelectorAll('.button-back').forEach(function (btn) {
|
||||
btn.addEventListener('click', function (e) {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
var wrapper = btn.closest('.submenu-wrapper');
|
||||
if (wrapper) {
|
||||
fadeOut(wrapper);
|
||||
// Also reset the arrow toggle on the parent li
|
||||
var li = wrapper.closest('li');
|
||||
if (li) {
|
||||
var toggle = li.querySelector('.link-arrow-wrapper > .arrow-toggle');
|
||||
if (toggle) {
|
||||
toggle.classList.remove('is-active');
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 176 KiB |
+8
-8
File diff suppressed because one or more lines are too long
BIN
Binary file not shown.
|
After Width: | Height: | Size: 176 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 176 KiB |
@@ -19,10 +19,33 @@
|
||||
|
||||
<nav class="mc--menu mc--main-menu" th:if="${primaryMenu != null}">
|
||||
<ul class="menu m--menu m--main-menu">
|
||||
<li class="megamenu menu-item" th:each="item : ${primaryMenu.items}">
|
||||
<li th:each="item : ${primaryMenu.items}" th:if="${item.parent == null}"
|
||||
th:class="${item.children.empty} ? 'menu-item' : 'menu-item menu-item--expanded'">
|
||||
|
||||
<div class="link-arrow-wrapper">
|
||||
<a th:href="${item.url}" th:text="${item.label}">Menu Item</a>
|
||||
|
||||
<button th:if="${!item.children.empty}" type="button" class="has-submenu arrow-toggle" aria-expanded="false" aria-haspopup="true" th:attr="aria-label='Display Sub Menu for ' + ${item.label}" data-once="site-header-arrow">
|
||||
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" viewBox="0 0 16 7" enable-background="new 0 0 16 7" xml:space="preserve" width="16" height="7">
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" fill="#881c1c" d="M7.88,7L15.75,0H0s7.88,7,7.88,7Z"></path>
|
||||
</svg>
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div class="submenu-wrapper" th:if="${!item.children.empty}">
|
||||
<button class="button-back">
|
||||
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" viewBox="0 0 5 10" enable-background="new 0 0 5 10" xml:space="preserve" width="5" height="10">
|
||||
<polygon fill-rule="evenodd" clip-rule="evenodd" fill="#881c1c" points="0,5 5,0 5,10 "></polygon>
|
||||
</svg> Back
|
||||
</button>
|
||||
<span class="navigation-title" th:text="${item.label}">Submenu Title</span>
|
||||
<ul class="submenu">
|
||||
<li class="menu-item" th:each="child : ${item.children}">
|
||||
<a th:href="${child.url}" th:text="${child.label}">Child Item</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
</li>
|
||||
</ul>
|
||||
</nav>
|
||||
|
||||
@@ -2242,11 +2242,17 @@
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<h3 class="section-title">
|
||||
BÀI VIẾT NỔI BẬT
|
||||
</h3>
|
||||
</div>
|
||||
|
||||
<div class="featured-grid">
|
||||
<div class="news-events-row">
|
||||
|
||||
<div class="news-column">
|
||||
<h3 class="section-title--news">
|
||||
TIN TỨC
|
||||
</h3>
|
||||
|
||||
|
||||
<div class="featured-grid">
|
||||
<div class="featured-grid__item">
|
||||
|
||||
<article class="news-card news-card--featured">
|
||||
@@ -2405,108 +2411,8 @@
|
||||
</article>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<div class="news-events-row">
|
||||
|
||||
<div class="news-column">
|
||||
<h3 class="section-title--news">
|
||||
TIN TỨC MỚI NHẤT
|
||||
</h3>
|
||||
|
||||
<div class="news-list">
|
||||
<div class="news-list__item">
|
||||
|
||||
<article class="news-teaser">
|
||||
|
||||
<div class="news-teaser__image">
|
||||
|
||||
<div> <img loading="lazy"
|
||||
src="https://sisvietnam.vn/wp-content/uploads/2026/06/S.I.S-Can-Tho-trao-tang-xe-dap-cho-thieu-nhi-1.jpg"
|
||||
width="4500" height="3006"
|
||||
alt="Pyrotechnics erupt over the Football Performance Center at the conclusion of the 2026 UMass Amherst Undergraduate Commencement Ceremony">
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="news-teaser__content">
|
||||
|
||||
<div class="news-list__category">
|
||||
<a href="https://sisvietnam.vn/taxonomy/term/1001" hreflang="vi">Tin Tức Bệnh
|
||||
Viện</a>
|
||||
</div>
|
||||
|
||||
<h3 class="news-teaser__title">
|
||||
<a href="https://sisvietnam.vn/news/article/tuan-le-nang-cao-nhan-thuc"
|
||||
rel="bookmark">
|
||||
<span>Bệnh Viện S.I.S Cần Thơ Tổ Chức Thành Công Tuần Lễ Nâng Cao Nhận Thức
|
||||
Về Đột Quỵ</span>
|
||||
|
||||
</a>
|
||||
</h3>
|
||||
|
||||
<div class="news-teaser__summary">
|
||||
|
||||
<div>
|
||||
<p>Ban Giám đốc Bệnh viện cùng đội ngũ chuyên gia đã tổ chức chuỗi sự kiện
|
||||
truyền thông, tư vấn sức khỏe miễn phí thu hút hàng nghìn người dân tham
|
||||
gia tìm hiểu và phòng ngừa bệnh.</p>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
</article>
|
||||
|
||||
</div>
|
||||
<div class="news-list__item">
|
||||
|
||||
<article class="news-teaser">
|
||||
|
||||
<div class="news-teaser__image">
|
||||
|
||||
<div> <img loading="lazy"
|
||||
src="https://sisvietnam.vn/wp-content/uploads/2026/04/Mo-hinh-S.I.S-gop-phan-hoan-thien-mang-luoi-dot-quy-khu-vuc-huong-den-APEC-2027-08.jpg"
|
||||
width="5392" height="3592"
|
||||
alt="Student speaker Mansi Maheshwari addresses the 2026 Master’s and Education Specialist Commencement Ceremony at the Mullins Center on May 15, 2026.">
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="news-teaser__content">
|
||||
|
||||
<div class="news-list__category">
|
||||
<a href="https://sisvietnam.vn/taxonomy/term/1001" hreflang="vi">Tin Tức Bệnh
|
||||
Viện</a>
|
||||
</div>
|
||||
|
||||
<h3 class="news-teaser__title">
|
||||
<a href="https://sisvietnam.vn/news/article/tiep-nhan-thiet-bi" rel="bookmark">
|
||||
<span>Bệnh Viện Đa Khoa Quốc Tế S.I.S Cần Thơ Tiếp Nhận Thêm Dàn Thiết Bị Y
|
||||
Tế Hiện Đại Bậc Nhất</span>
|
||||
|
||||
</a>
|
||||
</h3>
|
||||
|
||||
<div class="news-teaser__summary">
|
||||
|
||||
<div>
|
||||
<p>Nhằm nâng cao chất lượng chẩn đoán và điều trị, S.I.S Cần Thơ đã chính
|
||||
thức đưa vào hoạt động hệ thống máy DSA và MRI thế hệ mới, hỗ trợ tối đa
|
||||
cho các ca can thiệp thần kinh phức tạp.</p>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
</article>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="events-column">
|
||||
|
||||
@@ -275,6 +275,13 @@
|
||||
<input type="datetime-local" class="form-control" id="postEventTime" th:field="*{eventTimeLocal}">
|
||||
<small class="form-text text-muted">Specify the date and time for this event.</small>
|
||||
</div>
|
||||
<div class="form-group mt-3" id="eventLocationGroup" style="display: none;">
|
||||
<label for="postLocation" class="font-weight-bold text-danger">
|
||||
<i class="fas fa-map-marker-alt"></i> Location
|
||||
</label>
|
||||
<input type="text" class="form-control" id="postLocation" th:field="*{location}" placeholder="e.g. Room 101">
|
||||
<small class="form-text text-muted">Specify the location for this event.</small>
|
||||
</div>
|
||||
<hr>
|
||||
<div class="d-flex justify-content-between">
|
||||
<a th:href="@{/manage/posts}" class="btn btn-secondary btn-sm">
|
||||
@@ -481,11 +488,14 @@
|
||||
// --- Event Time Layout Toggle ---
|
||||
var layoutSelect = document.getElementById('postLayout');
|
||||
var eventTimeGroup = document.getElementById('eventTimeGroup');
|
||||
var eventLocationGroup = document.getElementById('eventLocationGroup');
|
||||
function toggleEventTime() {
|
||||
if (layoutSelect.value === 'EVENT') {
|
||||
eventTimeGroup.style.display = 'block';
|
||||
if (eventLocationGroup) eventLocationGroup.style.display = 'block';
|
||||
} else {
|
||||
eventTimeGroup.style.display = 'none';
|
||||
if (eventLocationGroup) eventLocationGroup.style.display = 'none';
|
||||
}
|
||||
}
|
||||
layoutSelect.addEventListener('change', toggleEventTime);
|
||||
|
||||
@@ -0,0 +1,150 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en" xmlns:th="http://www.thymeleaf.org" xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout"
|
||||
layout:decorate="~{fragments/layout}">
|
||||
|
||||
<head>
|
||||
<title th:text="${post.title} + ' | UMass Amherst'">Post Title | UMass Amherst</title>
|
||||
<meta name="description" th:content="${post.metaDescription ?: post.excerpt}">
|
||||
<style>
|
||||
.livestream-video-wrapper {
|
||||
position: relative;
|
||||
padding-bottom: 56.25%; /* 16:9 Aspect Ratio */
|
||||
height: 0;
|
||||
overflow: hidden;
|
||||
border-radius: 12px;
|
||||
box-shadow: 0 4px 20px rgba(0, 0, 0, 0.15);
|
||||
margin-bottom: 2rem;
|
||||
background: #000;
|
||||
}
|
||||
.livestream-video-wrapper iframe {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
border: 0;
|
||||
}
|
||||
.livestream-meta {
|
||||
margin-bottom: 2rem;
|
||||
border-bottom: 1px solid #eee;
|
||||
padding-bottom: 1rem;
|
||||
}
|
||||
.livestream-title {
|
||||
font-size: 2.25rem;
|
||||
font-weight: 800;
|
||||
color: #111;
|
||||
margin-bottom: 0.5rem;
|
||||
line-height: 1.25;
|
||||
}
|
||||
.livestream-date {
|
||||
color: #881C1C;
|
||||
font-weight: 700;
|
||||
font-size: 0.95rem;
|
||||
text-transform: uppercase;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div layout:fragment="content">
|
||||
<div id="block-umass-base-content" class="block block-system block-system-main-block tc--template-container tc--article">
|
||||
<div class="t--template t--article">
|
||||
|
||||
<!-- Content Top (Video Embed or Placeholder) -->
|
||||
<div class="content-top">
|
||||
<div class="lc--layout-container lc--one-column">
|
||||
<div class="l--layout l--one-column">
|
||||
<div class="lr--layout-region lr--main">
|
||||
<div class="cc--component-container">
|
||||
<!-- YouTube Embed -->
|
||||
<div th:if="${post.metaDescription != null and !post.metaDescription.isEmpty()}" class="livestream-video-wrapper">
|
||||
<iframe th:src="${post.metaDescription}"
|
||||
title="Livestream Video"
|
||||
allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share"
|
||||
allowfullscreen></iframe>
|
||||
</div>
|
||||
<!-- Fallback Hero Image if no video -->
|
||||
<div th:if="${post.metaDescription == null or post.metaDescription.isEmpty()}" class="cc--component-container cc--hero-article">
|
||||
<div class="c--component c--hero-article">
|
||||
<div class="f--field f--image" th:if="${post.featuredImage != null and !post.featuredImage.isEmpty()}">
|
||||
<img th:src="${post.featuredImage}" th:alt="${post.title}">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Content Main (Description and Info) -->
|
||||
<div class="content-main">
|
||||
<div class="lc--layout-container lc--one-column">
|
||||
<div class="l--layout l--one-column">
|
||||
<div class="lr--layout-region lr--main">
|
||||
<div class="livestream-meta">
|
||||
<!-- If the excerpt is used for the display title, show it. Otherwise show standard post title -->
|
||||
<h1 class="livestream-title" th:text="${post.excerpt != null and !post.excerpt.isEmpty() ? post.excerpt : post.title}">Post Title</h1>
|
||||
<p class="livestream-date" th:if="${formattedDate != null}" th:text="${formattedDate}">Date</p>
|
||||
</div>
|
||||
<section class="cc--component-container cc--wysiwyg">
|
||||
<div class="c--component c--wysiwyg">
|
||||
<div class="f--field f--wysiwyg editorjs-content" id="postContentRaw" style="display:none;" th:text="${post.content}"></div>
|
||||
<div class="f--field f--wysiwyg" id="postContentParsed"></div>
|
||||
</div>
|
||||
</section>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Include Editor.js parser to render the content on the frontend -->
|
||||
<script>
|
||||
document.addEventListener("DOMContentLoaded", function() {
|
||||
var rawData = document.getElementById("postContentRaw").textContent;
|
||||
var parsedContainer = document.getElementById("postContentParsed");
|
||||
|
||||
try {
|
||||
var data = JSON.parse(rawData);
|
||||
var html = "";
|
||||
if (data.blocks) {
|
||||
data.blocks.forEach(function(block) {
|
||||
switch(block.type) {
|
||||
case "paragraph":
|
||||
html += "<p>" + block.data.text + "</p>";
|
||||
break;
|
||||
case "header":
|
||||
html += "<h" + block.data.level + ">" + block.data.text + "</h" + block.data.level + ">";
|
||||
break;
|
||||
case "list":
|
||||
var tag = block.data.style === "ordered" ? "ol" : "ul";
|
||||
html += "<" + tag + ">";
|
||||
block.data.items.forEach(function(item) {
|
||||
html += "<li>" + item + "</li>";
|
||||
});
|
||||
html += "</" + tag + ">";
|
||||
break;
|
||||
case "image":
|
||||
html += "<figure><img src='" + block.data.file.url + "' alt='" + (block.data.caption || "") + "'><figcaption>" + (block.data.caption || "") + "</figcaption></figure>";
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
});
|
||||
parsedContainer.innerHTML = html;
|
||||
} else {
|
||||
parsedContainer.innerHTML = rawData.replace(/\n/g, "<br>");
|
||||
}
|
||||
} catch(e) {
|
||||
// Fallback to raw text if it is not JSON
|
||||
parsedContainer.innerHTML = rawData.replace(/\n/g, "<br>");
|
||||
}
|
||||
});
|
||||
</script>
|
||||
</div>
|
||||
</body>
|
||||
|
||||
</html>
|
||||
@@ -242,8 +242,15 @@
|
||||
</svg> Back </button>
|
||||
<span class="navigation-title" th:text="${item.label}">Menu Item</span>
|
||||
|
||||
<!-- Mobile Submenu Layout (Simple List) -->
|
||||
<ul class="submenu mobile-only">
|
||||
<li class="menu-item" th:each="child : ${item.children}">
|
||||
<a th:href="${child.url}" th:text="${child.label}">Child Item</a>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<!-- Mega Menu Content Layout -->
|
||||
<div class="mega-menu-content">
|
||||
<div class="mega-menu-content desktop-only">
|
||||
<!-- Column 1: Info (Title and Text) -->
|
||||
<div class="mega-col-info">
|
||||
<h3 th:text="${item.label}">Về Bệnh viện</h3>
|
||||
@@ -275,115 +282,6 @@
|
||||
</th:block>
|
||||
</ul>
|
||||
</nav>
|
||||
<div data-component-id="umass_base:nav-quicklink-buttons">
|
||||
<nav class="mc--menu mc--quicklink-button-menu">
|
||||
<ul class="menu m--menu m--quicklink-button-menu">
|
||||
<li class="menu-item">
|
||||
<div class="f--field f--button">
|
||||
<a href="https://www.umass.edu/admissions/apply" class="button-primary button-context-light " aria-label="Apply" data-component-id="umass_base:button">
|
||||
<span class="button-text"> Apply </span>
|
||||
</a>
|
||||
</div>
|
||||
</li>
|
||||
<li class="menu-item">
|
||||
<div class="f--field f--button">
|
||||
<a href="https://minutefund.uma-foundation.org/project/29554/donate" class="button-primary button-context-light ext" aria-label="Give" data-component-id="umass_base:button" data-extlink="">
|
||||
<span class="button-text"> Give </span>
|
||||
<svg focusable="false" width="1em" height="1em" class="ext" data-extlink-placement="append" aria-label="(link is external)" viewBox="0 0 80 40" role="img" aria-hidden="false">
|
||||
<title>(link is external)</title>
|
||||
<path d="M48 26c-1.1 0-2 0.9-2 2v26H10V18h26c1.1 0 2-0.9 2-2s-0.9-2-2-2H8c-1.1 0-2 0.9-2 2v40c0 1.1 0.9 2 2 2h40c1.1 0 2-0.9 2-2V28C50 26.9 49.1 26 48 26z"></path>
|
||||
<path d="M56 6H44c-1.1 0-2 0.9-2 2s0.9 2 2 2h7.2L30.6 30.6c-0.8 0.8-0.8 2 0 2.8C31 33.8 31.5 34 32 34s1-0.2 1.4-0.6L54 12.8V20c0 1.1 0.9 2 2 2s2-0.9 2-2V8C58 6.9 57.1 6 56 6z"></path>
|
||||
</svg>
|
||||
</a>
|
||||
</div>
|
||||
</li>
|
||||
<li class="menu-item">
|
||||
<div class="f--field f--button">
|
||||
<a href="https://www.umass.edu/admissions/visit" class="button-primary button-context-light " aria-label="Visit" data-component-id="umass_base:button">
|
||||
<span class="button-text"> Visit </span>
|
||||
</a>
|
||||
</div>
|
||||
</li>
|
||||
</ul>
|
||||
</nav>
|
||||
</div>
|
||||
<nav class="mc--menu mc--utility-menu">
|
||||
<ul class="menu m--menu m--utility-menu">
|
||||
<li class="menu-item menu-item--expanded">
|
||||
<div class="utility-button-wrapper">
|
||||
<button type="button" class="utility-button arrow-toggle information-for-toggle" aria-label="Display submenu for Information menu" aria-expanded="false" aria-haspopup="true" data-once="site-header-arrow"> Info For <svg version="1.1" class="arrow-down" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" viewBox="0 0 10 5" enable-background="new 0 0 10 5" xml:space="preserve" width="10" height="5">
|
||||
<polygon fill-rule="evenodd" clip-rule="evenodd" fill="#881c1c" points="5,5 0,0 10,0 "></polygon>
|
||||
</svg>
|
||||
<svg version="1.1" class="arrow-right" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" viewBox="0 0 5 10" enable-background="new 0 0 5 10" xml:space="preserve" width="5" height="10">
|
||||
<polygon fill-rule="evenodd" clip-rule="evenodd" fill="#881c1c" points="5,5 0,10 0,0 "></polygon>
|
||||
</svg>
|
||||
</button>
|
||||
<div class="submenu-wrapper">
|
||||
<button class="button-back">
|
||||
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" viewBox="0 0 5 10" enable-background="new 0 0 5 10" xml:space="preserve" width="5" height="10">
|
||||
<polygon fill-rule="evenodd" clip-rule="evenodd" fill="#881c1c" points="0,5 5,0 5,10 "></polygon>
|
||||
</svg> Back </button>
|
||||
<span class="navigation-title">Info For</span>
|
||||
<ul class="submenu">
|
||||
<li class="menu-item">
|
||||
<a href="https://www.umass.edu/gateway/info/prospective-students" data-drupal-link-system-path="node/42831">Prospective Students</a>
|
||||
</li>
|
||||
<li class="menu-item">
|
||||
<a href="https://www.umass.edu/gateway/info/current-students" title="Click here for info for current students" data-drupal-link-system-path="node/61">Current Students</a>
|
||||
</li>
|
||||
<li class="menu-item">
|
||||
<a href="https://www.umass.edu/gateway/info/faculty-and-staff" title="Click here for info for faculty and staff" data-drupal-link-system-path="node/66">Faculty and Staff</a>
|
||||
</li>
|
||||
<li class="menu-item">
|
||||
<a href="https://www.umass.edu/gateway/info/parents-and-families" title="Click here for info for parents" data-drupal-link-system-path="node/81">Parents and Families</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</li>
|
||||
<li class="menu-item">
|
||||
<a href="https://www.umassalumni.com/" title="UMass Amherst Alumni Association">Alumni</a>
|
||||
</li>
|
||||
<li class="menu-item">
|
||||
<a href="https://umassathletics.com/" title="UMass Amherst Athletics">Athletics</a>
|
||||
</li>
|
||||
<li class="menu-item">
|
||||
<a href="https://www.uma-foundation.org/" title="Giving to UMass Amherst">Giving</a>
|
||||
</li>
|
||||
<li class="menu-item">
|
||||
<a href="https://www.library.umass.edu/">Libraries</a>
|
||||
</li>
|
||||
</ul>
|
||||
</nav>
|
||||
<nav data-component-id="umass_base:header-socials">
|
||||
<ul class="social-media-links--platforms platforms ally-focus-within">
|
||||
<li>
|
||||
<a class="ext" href="https://www.facebook.com/UMassAmherst/" target="_blank" rel="noopener noreferrer">
|
||||
<svg aria-hidden="true" focusable="false" viewBox="0 0 17 17">
|
||||
<title>Find UMass Amherst on Facebook</title>
|
||||
<path fill-rule="evenodd" fill="currentColor" d="M17,8.5C17,3.81,13.19,0,8.5,0S0,3.81,0,8.5c0,3.98,2.75,7.33,6.45,8.25v-5.65h-1.75v-2.6h1.75v-1.12c0-2.89,1.31-4.23,4.15-4.23.54,0,1.47.11,1.85.21v2.35c-.2-.02-.55-.03-.98-.03-1.39,0-1.93.53-1.93,1.9v.92h2.78l-.48,2.6h-2.3v5.84c4.21-.51,7.47-4.09,7.47-8.44Z"></path>
|
||||
</svg>
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
<a class="ext" href="https://www.instagram.com/umass/" target="_blank" rel="noopener noreferrer">
|
||||
<!--?xml version="1.0" encoding="UTF-8"?-->
|
||||
<svg aria-hidden="true" focusable="false" viewBox="0 0 17 20">
|
||||
<title>Find UMass Amherst on Instagram</title>
|
||||
<path fill-rule="evenodd" fill="currentColor" <path="" d="M8.51,5.51c-.57,0-1.14.11-1.67.34-.53.22-1.01.55-1.42.97-.82.84-1.28,1.98-1.29,3.17,0,1.19.45,2.34,1.27,3.18.82.84,1.93,1.32,3.08,1.32,1.16,0,2.27-.47,3.09-1.31.82-.84,1.28-1.98,1.29-3.17,0-1.19-.45-2.34-1.27-3.18-.82-.84-1.93-1.32-3.08-1.32ZM8.49,7.09c.37,0,.74.07,1.08.22.34.15.66.36.92.63.26.27.47.59.62.94.14.35.22.73.22,1.11,0,.38-.07.76-.21,1.12-.14.35-.35.68-.61.95-.26.27-.57.49-.92.64-.34.15-.71.22-1.08.23-.37,0-.74-.07-1.08-.22-.34-.15-.66-.36-.92-.63-.26-.27-.47-.59-.62-.94-.14-.35-.22-.73-.22-1.11,0-.38.07-.76.21-1.12.14-.35.35-.68.61-.95.26-.27.57-.49.92-.64.34-.15.71-.22,1.08-.23ZM12.03,5.32c0-.28.11-.54.3-.74.19-.2.45-.31.72-.31s.53.11.72.31c.19.2.3.46.3.74s-.11.54-.3.74c-.19.2-.45.31-.72.31s-.53-.11-.72-.31c-.19-.2-.3-.46-.3-.74ZM16.95,6.39c-.06-1.4-.38-2.64-1.37-3.67-.99-1.02-2.2-1.34-3.56-1.41-1.4-.08-5.61-.08-7.02,0-1.36.07-2.57.39-3.56,1.41C.44,3.74.13,4.98.06,6.38-.02,7.83-.02,12.16.06,13.61c.06,1.4.38,2.64,1.37,3.67,1,1.02,2.2,1.34,3.56,1.41,1.4.08,5.61.08,7.02,0,1.36-.07,2.57-.39,3.56-1.41.99-1.02,1.31-2.27,1.37-3.67.08-1.45.08-5.77,0-7.22ZM15.14,15.16c-.3.77-.87,1.36-1.62,1.66-1.12.46-3.78.35-5.01.35s-3.9.1-5.01-.35c-.74-.3-1.32-.89-1.62-1.66-.44-1.15-.34-3.89-.34-5.16s-.1-4.01.34-5.16c.3-.77.87-1.36,1.62-1.66,1.12-.46,3.78-.35,5.01-.35s3.9-.1,5.01.35c.74.3,1.32.89,1.62,1.66.44,1.15.34,3.89.34,5.16s.1,4.01-.34,5.16Z"></path>
|
||||
</svg>
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
<a class="ext" href="https://www.snapchat.com/add/umassamherst" target="_blank" rel="noopener noreferrer">
|
||||
<svg aria-hidden="true" focusable="false" viewBox="0 0 17 17">
|
||||
<title>Add UMass Amherst on Snapchat</title>
|
||||
<path d="m12.8333333 20.3333333c-.0833333 0-.0833333 0-.1666666 0h-.0833334c-1.0833333 0-1.6666666-.3333333-2.25-.75-.41666663-.3333333-.74999997-.5833333-1.16666663-.5833333-.25 0-.41666667-.0833333-.66666667-.0833333-.33333333 0-.66666667.0833333-.91666667.0833333-.16666666 0-.33333333.0833333-.41666666.0833333-.33333334 0-.5-.25-.5-.4166666 0-.1666667-.08333334-.25-.08333334-.4166667 0-.0833333-.08333333-.25-.08333333-.3333333-1.33333333-.25-2.08333333-.5-2.25-1-.08333333 0-.08333333-.0833334-.08333333-.1666667 0-.25.16666666-.4166667.41666666-.5 2.25-.3333333 3.33333334-2.75 3.33333334-2.8333333.08333333-.25.16666666-.4166667.08333333-.5833334-.08333333-.1666666-.58333333-.3333333-.91666667-.4166666-.08333333 0-.16666666-.0833334-.25-.0833334-.83333333-.3333333-1-.75-.91666666-1.0833333.08333333-.5.83333333-.75 1.25-.5833333.33333333.1666666.58333333.1666666.75.1666666h.25c0-.0833333 0-.25 0-.3333333-.08333334-1.16666667-.25-2.66666667.16666666-3.5 1.16666667-2.66666667 3.66666667-2.83333333 4.33333337-2.83333333h.3333333c.75 0 3.1666667.16666666 4.3333333 2.83333333.4166667.91666667.3333334 2.33333333.25 3.5v.0833333.25h.1666667c.1666667 0 .4166667-.0833333.6666667-.1666666.1666666-.0833334.25-.0833334.4166666-.0833334.1666667 0 .25 0 .4166667.0833334.3333333.0833333.5833333.4166666.5833333.6666666 0 .4166667-.3333333.6666667-.9166666.9166667-.0833334 0-.1666667.0833333-.25.0833333-.3333334.0833334-.8333334.25-.9166667.5-.0833333.1666667 0 .3333334.0833333.5.0833334.25 1.0833334 2.5 3.25 2.8333334.25 0 .4166667.25.4166667.5 0 .0833333 0 .1666666-.0833333.1666666-.1666667.4166667-.9166667.75-2.25 1 0 .0833334-.0833334.25-.0833334.3333334 0 .1666666-.0833333.25-.0833333.4166666-.0833333.25-.25.4166667-.5.4166667-.0833333 0-.25 0-.4166667-.0833333-.25-.0833334-.5-.0833334-.9166666-.0833334-.1666667 0-.4166667 0-.6666667.0833334-.4166667.0833333-.75.3333333-1.1666667.5833333-.6666666.5833333-1.5.8333333-2.5.8333333" fill="currentColor" fill-rule="evenodd" transform="translate(-4 -3)"></path>
|
||||
</svg>
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
</nav>
|
||||
</div>
|
||||
</div>
|
||||
<button id="search-drawer-trigger" aria-label="Open Search" data-once="header-search">
|
||||
|
||||
@@ -9,6 +9,8 @@
|
||||
<link rel="stylesheet" media="all" th:href="@{/theme-assets/umass/css/css_09S7WcUyhLeUXabknzECn_ua5zOangtv2BF4OXAW2fM.css}">
|
||||
<link rel="stylesheet" media="all" th:href="@{/theme-assets/umass/css/css_5USufIKxGNJyomvgpy2m9ITQlTN9qcrtJQsw_06dSbo.css}">
|
||||
<link rel="stylesheet" media="all" th:href="@{/theme-assets/umass/css/css_G5ztZKRblBn54t8h9F_EK5Y3CsZrMvA2BWPMI5jJoO4.css}">
|
||||
<!-- Custom CSS -->
|
||||
<link rel="stylesheet" th:href="@{/css/custom.css}">
|
||||
<!-- Theme Customizer CSS Output -->
|
||||
<style th:utext="${themeCss}"></style>
|
||||
<!-- wp_head hook -->
|
||||
@@ -46,6 +48,8 @@
|
||||
</div>
|
||||
<!-- UMass Scripts -->
|
||||
<script th:src="@{/theme-assets/umass/js/js_aQtUyeGxehNR84AlGzGB1VfMu1Wn3lqHxvL8rocj1EU.js}"></script>
|
||||
<script th:src="@{/js/mobile-menu.js}"></script>
|
||||
<script th:src="@{/js/ambient-video.js}"></script>
|
||||
<!-- wp_footer hook -->
|
||||
<th:block th:utext="${hookManager.doActionAndReturn('wp_footer')}"></th:block>
|
||||
</body>
|
||||
|
||||
@@ -0,0 +1,10 @@
|
||||
<style>
|
||||
.tabbed-media-content-media-item { width: 100%; aspect-ratio: 16/9; position: relative; display: flex; align-items: center; justify-content: center; background: red;}
|
||||
.tabbed-media-content-media-item .f--video-embed { display: none; width: 100%; height: 100%; position: absolute; top: 0; left: 0; }
|
||||
.tabbed-media-content-media-item .f--video-embed iframe { width: 100%; height: 100%; }
|
||||
</style>
|
||||
<div class="tabbed-media-content-media-item">
|
||||
<div class="f--video-embed" style="display:block;">
|
||||
<iframe title="YouTube video player" src="https://www.youtube.com/embed/j63kT9Bjrb4?si=N5JwIcuRn-iRxkYu" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen></iframe>
|
||||
</div>
|
||||
</div>
|
||||
@@ -0,0 +1,61 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head></head>
|
||||
<body>
|
||||
<script>
|
||||
document.addEventListener("DOMContentLoaded", function() {
|
||||
var tabs = document.querySelectorAll('.tabbed-media-content-media-item[data-tab-id="tabbed-content-0"]');
|
||||
if(tabs.length > 0) tabs[0].classList.add('is-active');
|
||||
|
||||
var panels = document.querySelectorAll('#tabbed-content-0.tab-content-panel');
|
||||
if(panels.length > 0) panels[0].classList.add('is-active');
|
||||
|
||||
var labels = document.querySelectorAll('a.tab-label[aria-controls="tabbed-content-0"]');
|
||||
if(labels.length > 0) labels[0].setAttribute('aria-selected', 'true');
|
||||
|
||||
var allLabels = document.querySelectorAll('.tab-labels-inner .tab-label');
|
||||
allLabels.forEach(function(label) {
|
||||
label.addEventListener('click', function(e) {
|
||||
e.preventDefault();
|
||||
allLabels.forEach(function(l) { l.setAttribute('aria-selected', 'false'); });
|
||||
this.setAttribute('aria-selected', 'true');
|
||||
|
||||
var targetId = this.getAttribute('aria-controls');
|
||||
document.querySelectorAll('.tab-content-panel').forEach(function(p) { p.classList.remove('is-active'); });
|
||||
document.querySelectorAll('.tabbed-media-content-media-item').forEach(function(m) {
|
||||
m.classList.remove('is-active');
|
||||
var img = m.querySelector('.f--image');
|
||||
if(img) img.style.display = 'block';
|
||||
var btnContainer = m.querySelector('.f--field.f--button');
|
||||
if(btnContainer) btnContainer.style.display = 'block';
|
||||
var iframe = m.querySelector('iframe');
|
||||
if(iframe) iframe.removeAttribute('src'); // Stop video playing if they switch tabs
|
||||
});
|
||||
|
||||
var targetPanel = document.getElementById(targetId);
|
||||
if(targetPanel) targetPanel.classList.add('is-active');
|
||||
var targetMedia = document.querySelector('.tabbed-media-content-media-item[data-tab-id="' + targetId + '"]');
|
||||
if(targetMedia) targetMedia.classList.add('is-active');
|
||||
});
|
||||
});
|
||||
|
||||
var playButtons = document.querySelectorAll('.tabbed-media-content-media-item .button-play');
|
||||
playButtons.forEach(function(btn) {
|
||||
btn.addEventListener('click', function(e) {
|
||||
e.preventDefault();
|
||||
var mediaItem = this.closest('.tabbed-media-content-media-item');
|
||||
var img = mediaItem.querySelector('.f--image');
|
||||
var btnContainer = mediaItem.querySelector('.f--field.f--button');
|
||||
var iframe = mediaItem.querySelector('iframe');
|
||||
|
||||
if(img) img.style.display = 'none';
|
||||
if(btnContainer) btnContainer.style.display = 'none';
|
||||
if(iframe && iframe.getAttribute('data-src')) {
|
||||
iframe.setAttribute('src', iframe.getAttribute('data-src'));
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
Executable
+2
@@ -0,0 +1,2 @@
|
||||
#!/bin/bash
|
||||
# A dummy script just to make sure things are flushed
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 176 KiB |
Reference in New Issue
Block a user