feat: add stats block widget management and update block_3_button component content
This commit is contained in:
@@ -0,0 +1 @@
|
|||||||
|
{"username":"admin","password":"admin"}
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
# Netscape HTTP Cookie File
|
||||||
|
# https://curl.se/docs/http-cookies.html
|
||||||
|
# This file was generated by libcurl! Edit at your own risk.
|
||||||
|
|
||||||
|
#HttpOnly_localhost FALSE / FALSE 0 JSESSIONID 3E56DBE7CD23EAE763EA48EB5CF98B29
|
||||||
+1
-1
@@ -3,7 +3,7 @@
|
|||||||
<div class="container">
|
<div class="container">
|
||||||
<div class="text-container">
|
<div class="text-container">
|
||||||
<div data-component-id="umass_base:section-title" class="f--section-title">
|
<div data-component-id="umass_base:section-title" class="f--section-title">
|
||||||
<h2>Step Into <span class="highlight">Your Future</span>
|
<h2>TÌM HIỂU<span class="highlight">CHUYÊN KHOA</span>
|
||||||
</h2>
|
</h2>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -1,39 +1,35 @@
|
|||||||
<body>
|
<body>
|
||||||
<div class="cc--component-container cc--stats-block ">
|
<div class="cc--component-container cc--stats-block bg-old-brick" style="color: white;">
|
||||||
<div class="c--component c--stats-block">
|
<div class="c--component c--stats-block">
|
||||||
<div class="f--field f--stats-block">
|
<div class="f--field f--stats-block">
|
||||||
|
<div class="cc--component-container cc--stat">
|
||||||
|
<div class="c--component c--stat">
|
||||||
|
<div class="f--field f--stat-number">50.000+</div>
|
||||||
|
<div class="f--field f--description">
|
||||||
|
<p>Tổng số ca cấp cứu</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="cc--component-container cc--stat">
|
||||||
|
<div class="c--component c--stat">
|
||||||
|
<div class="f--field f--stat-number">1.6tr+</div>
|
||||||
|
<div class="f--field f--description">
|
||||||
|
<p>Tổng số ca khám bệnh</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
<div class="cc--component-container cc--stat">
|
<div class="cc--component-container cc--stat">
|
||||||
<div class="c--component c--stat">
|
<div class="c--component c--stat">
|
||||||
<div class="f--field f--stat-number">#1</div>
|
<div class="f--field f--stat-number">#1</div>
|
||||||
<div class="f--field f--description">
|
<div class="f--field f--description">
|
||||||
<p>Public Research University in New England, <br>Non-Medical School R&D Expenditures </p>
|
<p>Về điều trị đột quỵ</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="cc--component-container cc--stat">
|
|
||||||
<div class="c--component c--stat">
|
|
||||||
<div class="f--field f--stat-number">251</div>
|
|
||||||
<div class="f--field f--description">
|
|
||||||
<p>Total Degree Programs</p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="cc--component-container cc--stat">
|
|
||||||
<div class="c--component c--stat">
|
|
||||||
<div class="f--field f--stat-number">Top 50</div>
|
|
||||||
<div class="f--field f--description">
|
|
||||||
<p>Best Value Colleges (Public), <em>The Princeton Review</em>
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="f--field f--button">
|
|
||||||
<a href="https://www.umass.edu/gateway/why-umass/about-umass-amherst/umass-amherst-numbers" class="button-primary button-context-light " aria-label="UMass Amherst By The Numbers" data-component-id="umass_base:button">
|
|
||||||
<span class="button-text"> UMass Amherst By The Numbers </span>
|
|
||||||
</a>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</body>
|
</body>
|
||||||
<style>* { box-sizing: border-box; } body {margin: 0;}</style>
|
<style>
|
||||||
|
* { box-sizing: border-box; } body {margin: 0;}*{box-sizing:border-box;}body{margin-top:0px;margin-right:0px;margin-bottom:0px;margin-left:0px;}
|
||||||
|
</style>
|
||||||
@@ -33,57 +33,35 @@
|
|||||||
<div class="text-container centered">
|
<div class="text-container centered">
|
||||||
<div class="slide-text-container-inner">
|
<div class="slide-text-container-inner">
|
||||||
<h3>
|
<h3>
|
||||||
<a href="https://www.umass.edu/gateway/why-umass">Be the Future You Want to See.</a>
|
<a href="https://www.umass.edu/gateway/why-umass">Stroke International School.</a>
|
||||||
</h3>
|
</h3>
|
||||||
<div class="f--field f--button">
|
<div class="f--field f--button">
|
||||||
<a href="https://www.umass.edu/gateway/why-umass" aria-label="Learn More Learn more about UMass Amherst." data-component-id="umass_base:button" class="button-secondary button-context-dark">
|
<a href="https://www.umass.edu/gateway/why-umass" aria-label="Learn More Learn more about UMass Amherst." data-component-id="umass_base:button" class="button-secondary button-context-dark">
|
||||||
<span class="button-text"> Learn More </span>
|
<span class="button-text"> Learn More </span>
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
<nav class="mc--menu mc--info-menu">
|
<nav class="mc--menu mc--info-menu" th:if="${infoMenu != null and not #lists.isEmpty(infoMenu.items)}">
|
||||||
<ul class="menu m--menu m--info-menu">
|
<ul class="menu m--menu m--info-menu">
|
||||||
<li class="menu-item menu-item--expanded">
|
<li class="menu-item menu-item--expanded">
|
||||||
<details class="utility-button-wrapper mc--info-menu-container">
|
<details class="utility-button-wrapper mc--info-menu-container">
|
||||||
<summary type="button" aria-label="Display submenu for Information menu" aria-expanded="false" aria-haspopup="true" class="utility-button arrow-toggle information-for-toggle"> Info For <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" class="arrow">
|
<summary type="button" aria-label="Display submenu for Information menu" aria-expanded="false" aria-haspopup="true" class="utility-button arrow-toggle information-for-toggle">
|
||||||
|
<span th:text="${infoMenu.name}">Info For</span>
|
||||||
|
<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" class="arrow">
|
||||||
<polygon fill-rule="evenodd" clip-rule="evenodd" fill="#ffffff" points="7,7 0,0 16,0 "></polygon>
|
<polygon fill-rule="evenodd" clip-rule="evenodd" fill="#ffffff" points="7,7 0,0 16,0 "></polygon>
|
||||||
</svg>
|
</svg>
|
||||||
</summary>
|
</summary>
|
||||||
<div class="submenu-wrapper">
|
<div class="submenu-wrapper">
|
||||||
<ul class="submenu">
|
<ul class="submenu">
|
||||||
<li class="menu-item">
|
<li class="menu-item" th:each="item : ${infoMenu.items}">
|
||||||
<a href="https://www.umass.edu/gateway/info/prospective-students">Prospective Students</a>
|
<a th:href="${item.url}" th:text="${item.label}">Prospective Students</a>
|
||||||
</li>
|
|
||||||
<li class="menu-item">
|
|
||||||
<a href="https://www.umass.edu/gateway/info/current-students">Current Students</a>
|
|
||||||
</li>
|
|
||||||
<li class="menu-item">
|
|
||||||
<a href="https://www.umass.edu/gateway/info/parents-and-families">Parents & Family</a>
|
|
||||||
</li>
|
|
||||||
<li class="menu-item">
|
|
||||||
<a href="https://www.umass.edu/gateway/info/faculty-and-staff">Faculty & Staff</a>
|
|
||||||
</li>
|
|
||||||
<li class="menu-item">
|
|
||||||
<a href="https://www.umassalumni.com/">Alumni</a>
|
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
</details>
|
</details>
|
||||||
<div class="submenu-wrapper-desktop">
|
<div class="submenu-wrapper-desktop">
|
||||||
<ul class="submenu">
|
<ul class="submenu">
|
||||||
<li class="menu-item">
|
<li class="menu-item" th:each="item : ${infoMenu.items}">
|
||||||
<a href="https://www.umass.edu/gateway/info/prospective-students">Prospective Students</a>
|
<a th:href="${item.url}" th:text="${item.label}">Prospective Students</a>
|
||||||
</li>
|
|
||||||
<li class="menu-item">
|
|
||||||
<a href="https://www.umass.edu/gateway/info/current-students">Current Students</a>
|
|
||||||
</li>
|
|
||||||
<li class="menu-item">
|
|
||||||
<a href="https://www.umass.edu/gateway/info/parents-and-families">Parents & Family</a>
|
|
||||||
</li>
|
|
||||||
<li class="menu-item">
|
|
||||||
<a href="https://www.umass.edu/gateway/info/faculty-and-staff">Faculty & Staff</a>
|
|
||||||
</li>
|
|
||||||
<li class="menu-item">
|
|
||||||
<a href="https://www.umassalumni.com/">Alumni</a>
|
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
+15
@@ -62,6 +62,11 @@ public class GlobalControllerAdvice {
|
|||||||
return menuService.findByLocation("FOOTER").orElse(null);
|
return menuService.findByLocation("FOOTER").orElse(null);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ModelAttribute("infoMenu")
|
||||||
|
public com.sisvietnamvn.web.domain.Menu getInfoMenu() {
|
||||||
|
return menuService.findByLocation("INFO").orElse(null);
|
||||||
|
}
|
||||||
|
|
||||||
@ModelAttribute("sidebarWidgets")
|
@ModelAttribute("sidebarWidgets")
|
||||||
public java.util.List<com.sisvietnamvn.web.service.dto.WidgetDto> getSidebarWidgets() {
|
public java.util.List<com.sisvietnamvn.web.service.dto.WidgetDto> getSidebarWidgets() {
|
||||||
return getWidgets("sidebar");
|
return getWidgets("sidebar");
|
||||||
@@ -72,6 +77,16 @@ public class GlobalControllerAdvice {
|
|||||||
return getWidgets("footer");
|
return getWidgets("footer");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ModelAttribute("statsWidgets")
|
||||||
|
public java.util.List<com.sisvietnamvn.web.service.dto.WidgetDto> getStatsWidgets() {
|
||||||
|
return getWidgets("stats");
|
||||||
|
}
|
||||||
|
|
||||||
|
@ModelAttribute("ctaMenu")
|
||||||
|
public com.sisvietnamvn.web.domain.Menu getCtaMenu() {
|
||||||
|
return menuService.findByLocation("CTA").orElse(null);
|
||||||
|
}
|
||||||
|
|
||||||
@ModelAttribute("hookManager")
|
@ModelAttribute("hookManager")
|
||||||
public com.sisvietnamvn.web.hook.HookManager getHookManager() {
|
public com.sisvietnamvn.web.hook.HookManager getHookManager() {
|
||||||
return hookManager;
|
return hookManager;
|
||||||
|
|||||||
+1
@@ -54,6 +54,7 @@ public class ManageWidgetController {
|
|||||||
public String listWidgets(Model model) {
|
public String listWidgets(Model model) {
|
||||||
model.addAttribute("sidebarWidgets", getWidgets("sidebar"));
|
model.addAttribute("sidebarWidgets", getWidgets("sidebar"));
|
||||||
model.addAttribute("footerWidgets", getWidgets("footer"));
|
model.addAttribute("footerWidgets", getWidgets("footer"));
|
||||||
|
model.addAttribute("statsWidgets", getWidgets("stats"));
|
||||||
return "manage/widgets/list";
|
return "manage/widgets/list";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -14,6 +14,7 @@
|
|||||||
--color-success: #28a745;
|
--color-success: #28a745;
|
||||||
--color-warning: #ffc107;
|
--color-warning: #ffc107;
|
||||||
--color-danger: #dc3545;
|
--color-danger: #dc3545;
|
||||||
|
--color-old-brick: #881C1C;
|
||||||
|
|
||||||
/* Neutrals */
|
/* Neutrals */
|
||||||
--color-background: #ffffff;
|
--color-background: #ffffff;
|
||||||
@@ -58,3 +59,11 @@
|
|||||||
z-index: 1;
|
z-index: 1;
|
||||||
/* Ensures it sits above the video */
|
/* Ensures it sits above the video */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Custom Color Utilities */
|
||||||
|
.text-old-brick {
|
||||||
|
color: var(--color-old-brick) !important;
|
||||||
|
}
|
||||||
|
.bg-old-brick {
|
||||||
|
background-color: var(--color-old-brick) !important;
|
||||||
|
}
|
||||||
+114
-32
@@ -1,5 +1,6 @@
|
|||||||
/**
|
/**
|
||||||
* Custom Editor.js Block Tool for embedding predefined HTML snippets.
|
* Custom Editor.js Block Tool for embedding predefined HTML snippets.
|
||||||
|
* Uses iframe for WYSIWYG preview - snippets look exactly like on the live page.
|
||||||
*/
|
*/
|
||||||
class HtmlSnippetTool {
|
class HtmlSnippetTool {
|
||||||
static get toolbox() {
|
static get toolbox() {
|
||||||
@@ -21,12 +22,10 @@ class HtmlSnippetTool {
|
|||||||
this.wrapper = document.createElement('div');
|
this.wrapper = document.createElement('div');
|
||||||
this.wrapper.classList.add('ce-snippet-wrapper');
|
this.wrapper.classList.add('ce-snippet-wrapper');
|
||||||
this.wrapper.style.border = '1px solid #ddd';
|
this.wrapper.style.border = '1px solid #ddd';
|
||||||
this.wrapper.style.padding = '15px';
|
|
||||||
this.wrapper.style.borderRadius = '5px';
|
this.wrapper.style.borderRadius = '5px';
|
||||||
this.wrapper.style.background = '#fafafa';
|
this.wrapper.style.background = '#fafafa';
|
||||||
this.wrapper.style.width = '100%';
|
this.wrapper.style.width = '100%';
|
||||||
this.wrapper.style.boxSizing = 'border-box';
|
this.wrapper.style.boxSizing = 'border-box';
|
||||||
this.wrapper.style.overflowX = 'auto'; // allow scrolling instead of stretching editor
|
|
||||||
|
|
||||||
if (this.data.id) {
|
if (this.data.id) {
|
||||||
this._showPreview(this.data.id);
|
this._showPreview(this.data.id);
|
||||||
@@ -43,11 +42,13 @@ class HtmlSnippetTool {
|
|||||||
const title = document.createElement('h4');
|
const title = document.createElement('h4');
|
||||||
title.style.marginTop = '0';
|
title.style.marginTop = '0';
|
||||||
title.style.marginBottom = '10px';
|
title.style.marginBottom = '10px';
|
||||||
|
title.style.padding = '15px 15px 0 15px';
|
||||||
title.innerText = 'Insert Predefined HTML Snippet';
|
title.innerText = 'Insert Predefined HTML Snippet';
|
||||||
|
|
||||||
const inputContainer = document.createElement('div');
|
const inputContainer = document.createElement('div');
|
||||||
inputContainer.style.display = 'flex';
|
inputContainer.style.display = 'flex';
|
||||||
inputContainer.style.gap = '10px';
|
inputContainer.style.gap = '10px';
|
||||||
|
inputContainer.style.padding = '0 15px 15px 15px';
|
||||||
|
|
||||||
const input = document.createElement('input');
|
const input = document.createElement('input');
|
||||||
input.classList.add('ce-input');
|
input.classList.add('ce-input');
|
||||||
@@ -73,8 +74,48 @@ class HtmlSnippetTool {
|
|||||||
}
|
}
|
||||||
|
|
||||||
_showPreview(snippetId) {
|
_showPreview(snippetId) {
|
||||||
this.wrapper.innerHTML = '<div style="color: #666;">Loading preview...</div>';
|
this.wrapper.innerHTML = '';
|
||||||
|
|
||||||
|
// Header bar with snippet name and Edit ID button
|
||||||
|
const header = document.createElement('div');
|
||||||
|
header.style.display = 'flex';
|
||||||
|
header.style.justifyContent = 'space-between';
|
||||||
|
header.style.alignItems = 'center';
|
||||||
|
header.style.padding = '8px 15px';
|
||||||
|
header.style.borderBottom = '1px solid #ddd';
|
||||||
|
header.style.background = '#f0f0f0';
|
||||||
|
header.style.borderRadius = '5px 5px 0 0';
|
||||||
|
|
||||||
|
const title = document.createElement('strong');
|
||||||
|
title.innerText = 'Snippet: ' + snippetId;
|
||||||
|
title.style.fontSize = '13px';
|
||||||
|
title.style.color = '#555';
|
||||||
|
|
||||||
|
const editBtn = document.createElement('button');
|
||||||
|
editBtn.innerText = 'Edit ID';
|
||||||
|
editBtn.style.fontSize = '12px';
|
||||||
|
editBtn.style.cursor = 'pointer';
|
||||||
|
editBtn.style.padding = '2px 8px';
|
||||||
|
editBtn.style.border = '1px solid #ccc';
|
||||||
|
editBtn.style.borderRadius = '3px';
|
||||||
|
editBtn.style.background = '#fff';
|
||||||
|
editBtn.addEventListener('click', () => {
|
||||||
|
this._showInput();
|
||||||
|
});
|
||||||
|
|
||||||
|
header.appendChild(title);
|
||||||
|
header.appendChild(editBtn);
|
||||||
|
this.wrapper.appendChild(header);
|
||||||
|
|
||||||
|
// Loading indicator
|
||||||
|
const loadingDiv = document.createElement('div');
|
||||||
|
loadingDiv.style.padding = '20px';
|
||||||
|
loadingDiv.style.color = '#666';
|
||||||
|
loadingDiv.style.textAlign = 'center';
|
||||||
|
loadingDiv.innerText = 'Loading preview...';
|
||||||
|
this.wrapper.appendChild(loadingDiv);
|
||||||
|
|
||||||
|
// Fetch the snippet HTML
|
||||||
fetch('/api/manage/snippets/' + encodeURIComponent(snippetId))
|
fetch('/api/manage/snippets/' + encodeURIComponent(snippetId))
|
||||||
.then(response => {
|
.then(response => {
|
||||||
if (!response.ok) throw new Error('Snippet not found');
|
if (!response.ok) throw new Error('Snippet not found');
|
||||||
@@ -83,47 +124,88 @@ class HtmlSnippetTool {
|
|||||||
.then(html => {
|
.then(html => {
|
||||||
this.data.id = snippetId;
|
this.data.id = snippetId;
|
||||||
|
|
||||||
this.wrapper.innerHTML = '';
|
// Remove loading indicator
|
||||||
|
loadingDiv.remove();
|
||||||
|
|
||||||
const header = document.createElement('div');
|
// Create an iframe for isolated WYSIWYG rendering
|
||||||
header.style.display = 'flex';
|
const iframe = document.createElement('iframe');
|
||||||
header.style.justifyContent = 'space-between';
|
iframe.style.width = '100%';
|
||||||
header.style.alignItems = 'center';
|
iframe.style.border = 'none';
|
||||||
header.style.marginBottom = '10px';
|
iframe.style.display = 'block';
|
||||||
header.style.borderBottom = '1px solid #ddd';
|
iframe.style.borderRadius = '0 0 5px 5px';
|
||||||
header.style.paddingBottom = '5px';
|
iframe.style.minHeight = '80px';
|
||||||
|
// Scrolling is disabled; height auto-adjusts
|
||||||
|
iframe.scrolling = 'no';
|
||||||
|
|
||||||
const title = document.createElement('strong');
|
this.wrapper.appendChild(iframe);
|
||||||
title.innerText = 'Snippet: ' + snippetId;
|
|
||||||
|
|
||||||
const editBtn = document.createElement('button');
|
// Write the full HTML document into the iframe, including theme CSS
|
||||||
editBtn.innerText = 'Edit ID';
|
const iframeDoc = iframe.contentDocument || iframe.contentWindow.document;
|
||||||
editBtn.style.fontSize = '12px';
|
iframeDoc.open();
|
||||||
editBtn.style.cursor = 'pointer';
|
iframeDoc.write(`
|
||||||
editBtn.addEventListener('click', () => {
|
<!DOCTYPE html>
|
||||||
this._showInput();
|
<html>
|
||||||
});
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
|
<link rel="preconnect" href="https://fonts.googleapis.com">
|
||||||
|
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
||||||
|
<link href="https://fonts.googleapis.com/css2?family=Lora:ital,wght@0,400..700;1,400..700&family=Open+Sans:ital,wght@0,300..800;1,300..800&display=swap" rel="stylesheet">
|
||||||
|
<link rel="stylesheet" href="/css/umass.css">
|
||||||
|
<link rel="stylesheet" href="/css/custom.css">
|
||||||
|
<style>
|
||||||
|
body {
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
overflow: hidden;
|
||||||
|
background: #fff;
|
||||||
|
}
|
||||||
|
/* Prevent any internal links from being clickable */
|
||||||
|
a { pointer-events: none; }
|
||||||
|
/* Ensure images/videos scale properly */
|
||||||
|
img, video, iframe { max-width: 100%; height: auto; }
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
${html}
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
`);
|
||||||
|
iframeDoc.close();
|
||||||
|
|
||||||
header.appendChild(title);
|
// Auto-resize iframe to fit content
|
||||||
header.appendChild(editBtn);
|
const resizeIframe = () => {
|
||||||
|
try {
|
||||||
|
const body = iframeDoc.body;
|
||||||
|
const docEl = iframeDoc.documentElement;
|
||||||
|
const height = Math.max(
|
||||||
|
body.scrollHeight, body.offsetHeight,
|
||||||
|
docEl.clientHeight, docEl.scrollHeight, docEl.offsetHeight
|
||||||
|
);
|
||||||
|
iframe.style.height = height + 'px';
|
||||||
|
} catch (e) {
|
||||||
|
iframe.style.height = '300px';
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
const previewArea = document.createElement('div');
|
// Resize after load and after images load
|
||||||
previewArea.innerHTML = html;
|
iframe.addEventListener('load', resizeIframe);
|
||||||
|
setTimeout(resizeIframe, 500);
|
||||||
// Prevent interactions inside preview from submitting forms or acting up
|
setTimeout(resizeIframe, 1500);
|
||||||
previewArea.style.pointerEvents = 'none';
|
setTimeout(resizeIframe, 3000);
|
||||||
|
|
||||||
this.wrapper.appendChild(header);
|
|
||||||
this.wrapper.appendChild(previewArea);
|
|
||||||
})
|
})
|
||||||
.catch(error => {
|
.catch(error => {
|
||||||
this.wrapper.innerHTML = '<div style="color: red;">Error: ' + error.message + '</div>';
|
loadingDiv.remove();
|
||||||
|
const errorDiv = document.createElement('div');
|
||||||
|
errorDiv.style.padding = '15px';
|
||||||
|
errorDiv.innerHTML = '<div style="color: red;">Error: ' + error.message + '</div>';
|
||||||
const backBtn = document.createElement('button');
|
const backBtn = document.createElement('button');
|
||||||
backBtn.innerText = 'Try Again';
|
backBtn.innerText = 'Try Again';
|
||||||
backBtn.style.marginTop = '10px';
|
backBtn.style.marginTop = '10px';
|
||||||
backBtn.style.cursor = 'pointer';
|
backBtn.style.cursor = 'pointer';
|
||||||
backBtn.addEventListener('click', () => this._showInput());
|
backBtn.addEventListener('click', () => this._showInput());
|
||||||
this.wrapper.appendChild(backBtn);
|
errorDiv.appendChild(backBtn);
|
||||||
|
this.wrapper.appendChild(errorDiv);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -35,9 +35,11 @@
|
|||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label for="location">Location</label>
|
<label for="location">Location</label>
|
||||||
<select class="form-control" id="location" name="location">
|
<select class="form-control" id="location" name="location">
|
||||||
<option value="" th:selected="${menu.location == null || menu.location == '' || menu.location == 'Unassigned'}">Unassigned</option>
|
<option value="" th:selected="${menu.location == null or menu.location == ''}">None</option>
|
||||||
<option value="PRIMARY" th:selected="${menu.location == 'PRIMARY'}">Primary Navigation</option>
|
<option value="PRIMARY" th:selected="${menu.location == 'PRIMARY'}">Primary Navigation</option>
|
||||||
<option value="FOOTER" th:selected="${menu.location == 'FOOTER'}">Footer Navigation</option>
|
<option value="FOOTER" th:selected="${menu.location == 'FOOTER'}">Footer Navigation</option>
|
||||||
|
<option value="INFO" th:selected="${menu.location == 'INFO'}">Info For Navigation</option>
|
||||||
|
<option value="CTA" th:selected="${menu.location == 'CTA'}">Call To Action Links</option>
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
<button type="submit" class="btn btn-primary btn-block">Save Properties</button>
|
<button type="submit" class="btn btn-primary btn-block">Save Properties</button>
|
||||||
|
|||||||
@@ -35,6 +35,8 @@
|
|||||||
<option value="">-- No Location Assigned --</option>
|
<option value="">-- No Location Assigned --</option>
|
||||||
<option value="PRIMARY">Primary Navigation</option>
|
<option value="PRIMARY">Primary Navigation</option>
|
||||||
<option value="FOOTER">Footer Navigation</option>
|
<option value="FOOTER">Footer Navigation</option>
|
||||||
|
<option value="INFO">Info For Navigation</option>
|
||||||
|
<option value="CTA">Call To Action Links</option>
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
<button type="submit" class="btn btn-primary btn-block">Create Menu</button>
|
<button type="submit" class="btn btn-primary btn-block">Create Menu</button>
|
||||||
|
|||||||
@@ -4,6 +4,11 @@
|
|||||||
<title th:text="${isNew} ? 'Add New Snippet' : 'Edit Snippet'">Edit Snippet</title>
|
<title th:text="${isNew} ? 'Add New Snippet' : 'Edit Snippet'">Edit Snippet</title>
|
||||||
<!-- GrapesJS CSS -->
|
<!-- GrapesJS CSS -->
|
||||||
<link href="https://unpkg.com/grapesjs/dist/css/grapes.min.css" rel="stylesheet">
|
<link href="https://unpkg.com/grapesjs/dist/css/grapes.min.css" rel="stylesheet">
|
||||||
|
|
||||||
|
<!-- CodeMirror CSS for beautiful code editing -->
|
||||||
|
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.65.13/codemirror.min.css">
|
||||||
|
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.65.13/theme/monokai.min.css">
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
/* ── GrapesJS Layout Overrides ── */
|
/* ── GrapesJS Layout Overrides ── */
|
||||||
#gjs-editor-wrap {
|
#gjs-editor-wrap {
|
||||||
@@ -197,6 +202,16 @@
|
|||||||
<section layout:fragment="scripts">
|
<section layout:fragment="scripts">
|
||||||
<script src="https://unpkg.com/grapesjs"></script>
|
<script src="https://unpkg.com/grapesjs"></script>
|
||||||
|
|
||||||
|
<!-- JS-Beautify for formatting HTML -->
|
||||||
|
<script src="https://cdnjs.cloudflare.com/ajax/libs/js-beautify/1.14.7/beautify-html.min.js"></script>
|
||||||
|
|
||||||
|
<!-- CodeMirror JS for syntax highlighting -->
|
||||||
|
<script src="https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.65.13/codemirror.min.js"></script>
|
||||||
|
<script src="https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.65.13/mode/xml/xml.min.js"></script>
|
||||||
|
<script src="https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.65.13/mode/css/css.min.js"></script>
|
||||||
|
<script src="https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.65.13/mode/javascript/javascript.min.js"></script>
|
||||||
|
<script src="https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.65.13/mode/htmlmixed/htmlmixed.min.js"></script>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
document.addEventListener('DOMContentLoaded', function() {
|
document.addEventListener('DOMContentLoaded', function() {
|
||||||
var textArea = document.getElementById('snippetContent');
|
var textArea = document.getElementById('snippetContent');
|
||||||
@@ -628,16 +643,76 @@
|
|||||||
editor.setComponents(existingContent);
|
editor.setComponents(existingContent);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var cmEditor = null;
|
||||||
|
var isGrapesJsModified = false;
|
||||||
|
|
||||||
|
// Track if user made visual changes
|
||||||
|
editor.on('change:changesCount', function() {
|
||||||
|
isGrapesJsModified = true;
|
||||||
|
});
|
||||||
|
|
||||||
toggleBtn.addEventListener('click', function() {
|
toggleBtn.addEventListener('click', function() {
|
||||||
if (isVisual) {
|
if (isVisual) {
|
||||||
|
var rawOutput;
|
||||||
|
|
||||||
|
if (isGrapesJsModified) {
|
||||||
|
// User made visual changes, pull from GrapesJS
|
||||||
var html = editor.getHtml();
|
var html = editor.getHtml();
|
||||||
var css = editor.getCss();
|
var css = editor.getCss();
|
||||||
textArea.value = html + (css ? '<style>' + css + '</style>' : '');
|
var combined = html + (css && css.trim() !== '' && css.trim() !== '* { box-sizing: border-box; } body {margin: 0;}' ? '<style>' + css + '</style>' : '');
|
||||||
|
|
||||||
|
rawOutput = html_beautify(combined, {
|
||||||
|
indent_size: 4,
|
||||||
|
wrap_line_length: 0,
|
||||||
|
preserve_newlines: true
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
// User didn't make visual changes, KEEP IT RAW exactly as it was
|
||||||
|
rawOutput = textArea.value;
|
||||||
|
}
|
||||||
|
|
||||||
|
textArea.value = rawOutput;
|
||||||
gjsWrap.style.display = 'none';
|
gjsWrap.style.display = 'none';
|
||||||
textArea.style.display = 'block';
|
// We don't display textArea because CodeMirror handles the UI
|
||||||
|
textArea.style.display = 'none';
|
||||||
|
|
||||||
|
// Initialize CodeMirror if not already
|
||||||
|
if (!cmEditor) {
|
||||||
|
cmEditor = CodeMirror.fromTextArea(textArea, {
|
||||||
|
mode: "htmlmixed",
|
||||||
|
theme: "monokai",
|
||||||
|
lineNumbers: true,
|
||||||
|
matchBrackets: true,
|
||||||
|
autoCloseTags: true,
|
||||||
|
indentUnit: 4,
|
||||||
|
lineWrapping: true
|
||||||
|
});
|
||||||
|
// Fix for initially hidden textarea
|
||||||
|
setTimeout(function() {
|
||||||
|
cmEditor.refresh();
|
||||||
|
}, 10);
|
||||||
|
} else {
|
||||||
|
cmEditor.setValue(rawOutput);
|
||||||
|
setTimeout(function() {
|
||||||
|
cmEditor.refresh();
|
||||||
|
}, 10);
|
||||||
|
}
|
||||||
|
|
||||||
|
// CodeMirror wrapper needs to be visible
|
||||||
|
if(cmEditor.getWrapperElement()) {
|
||||||
|
cmEditor.getWrapperElement().style.display = 'block';
|
||||||
|
}
|
||||||
|
|
||||||
toggleBtn.innerHTML = '<i class="fas fa-paint-brush"></i> Use Visual Builder';
|
toggleBtn.innerHTML = '<i class="fas fa-paint-brush"></i> Use Visual Builder';
|
||||||
} else {
|
} else {
|
||||||
|
// Get value from CodeMirror back to textarea and GrapesJS
|
||||||
|
if (cmEditor) {
|
||||||
|
textArea.value = cmEditor.getValue();
|
||||||
|
cmEditor.getWrapperElement().style.display = 'none';
|
||||||
|
}
|
||||||
editor.setComponents(textArea.value);
|
editor.setComponents(textArea.value);
|
||||||
|
isGrapesJsModified = false; // Reset flag since we just synced
|
||||||
|
|
||||||
textArea.style.display = 'none';
|
textArea.style.display = 'none';
|
||||||
gjsWrap.style.display = 'block';
|
gjsWrap.style.display = 'block';
|
||||||
toggleBtn.innerHTML = '<i class="fas fa-code"></i> Use Code Editor';
|
toggleBtn.innerHTML = '<i class="fas fa-code"></i> Use Code Editor';
|
||||||
@@ -647,6 +722,7 @@
|
|||||||
|
|
||||||
form.addEventListener('submit', function() {
|
form.addEventListener('submit', function() {
|
||||||
if (isVisual) {
|
if (isVisual) {
|
||||||
|
if (isGrapesJsModified) {
|
||||||
var html = editor.getHtml();
|
var html = editor.getHtml();
|
||||||
var css = editor.getCss();
|
var css = editor.getCss();
|
||||||
var finalOutput = html;
|
var finalOutput = html;
|
||||||
@@ -655,6 +731,11 @@
|
|||||||
}
|
}
|
||||||
textArea.value = finalOutput;
|
textArea.value = finalOutput;
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
if (cmEditor) {
|
||||||
|
textArea.value = cmEditor.getValue();
|
||||||
|
}
|
||||||
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@@ -31,6 +31,7 @@
|
|||||||
<select class="form-control" id="area" name="area">
|
<select class="form-control" id="area" name="area">
|
||||||
<option value="sidebar">Sidebar</option>
|
<option value="sidebar">Sidebar</option>
|
||||||
<option value="footer">Footer</option>
|
<option value="footer">Footer</option>
|
||||||
|
<option value="stats">Stats Block</option>
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
@@ -73,6 +74,7 @@
|
|||||||
</div>
|
</div>
|
||||||
<small class="text-muted" th:text="${widget.type}">Type</small>
|
<small class="text-muted" th:text="${widget.type}">Type</small>
|
||||||
<p class="mb-1" th:text="${widget.content}">Content...</p>
|
<p class="mb-1" th:text="${widget.content}">Content...</p>
|
||||||
|
<small class="text-muted d-block mt-1"><strong>Area:</strong> Sidebar</small>
|
||||||
</div>
|
</div>
|
||||||
<div th:if="${sidebarWidgets.empty}" class="text-center text-muted p-3">
|
<div th:if="${sidebarWidgets.empty}" class="text-center text-muted p-3">
|
||||||
No widgets in Sidebar.
|
No widgets in Sidebar.
|
||||||
@@ -101,6 +103,7 @@
|
|||||||
</div>
|
</div>
|
||||||
<small class="text-muted" th:text="${widget.type}">Type</small>
|
<small class="text-muted" th:text="${widget.type}">Type</small>
|
||||||
<p class="mb-1" th:text="${widget.content}">Content...</p>
|
<p class="mb-1" th:text="${widget.content}">Content...</p>
|
||||||
|
<small class="text-muted d-block mt-1"><strong>Area:</strong> Footer</small>
|
||||||
</div>
|
</div>
|
||||||
<div th:if="${footerWidgets.empty}" class="text-center text-muted p-3">
|
<div th:if="${footerWidgets.empty}" class="text-center text-muted p-3">
|
||||||
No widgets in Footer.
|
No widgets in Footer.
|
||||||
@@ -109,6 +112,35 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<!-- Stats Widgets -->
|
||||||
|
<div class="col-lg-4">
|
||||||
|
<div class="card shadow mb-4">
|
||||||
|
<div class="card-header py-3">
|
||||||
|
<h6 class="m-0 font-weight-bold text-primary">Stats Widgets</h6>
|
||||||
|
</div>
|
||||||
|
<div class="card-body">
|
||||||
|
<div class="list-group">
|
||||||
|
<div class="list-group-item" th:each="widget : ${statsWidgets}">
|
||||||
|
<div class="d-flex w-100 justify-content-between">
|
||||||
|
<h5 class="mb-1" th:text="${widget.title}">Title</h5>
|
||||||
|
<form th:action="@{/manage/widgets/delete}" method="post">
|
||||||
|
<input type="hidden" name="area" value="stats">
|
||||||
|
<input type="hidden" name="id" th:value="${widget.id}">
|
||||||
|
<button type="submit" class="btn btn-sm btn-danger"><i class="fas fa-trash"></i></button>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
<small class="text-muted" th:text="${widget.type}">Type</small>
|
||||||
|
<p class="mb-1" th:text="${widget.content}">Content...</p>
|
||||||
|
<small class="text-muted d-block mt-1"><strong>Area:</strong> Stats Block</small>
|
||||||
|
</div>
|
||||||
|
<div th:if="${statsWidgets.empty}" class="text-center text-muted p-3">
|
||||||
|
No widgets in Stats Block.
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</body>
|
</body>
|
||||||
|
|||||||
@@ -26,8 +26,16 @@
|
|||||||
|
|
||||||
<!-- 1. HTML Snippet Block (Custom) -->
|
<!-- 1. HTML Snippet Block (Custom) -->
|
||||||
<th:block th:if="${block.type == 'snippet'}">
|
<th:block th:if="${block.type == 'snippet'}">
|
||||||
|
<th:block th:if="${block.data.id == 'top-banner' or block.data.id == 'umass_banner_snippet' or block.data.id == 'content_top_snippet' or block.data.id == 'top_banner' or block.data.id == 'content-top'}">
|
||||||
|
<div th:replace="~{themes/__${activeTheme}__/content-top}"></div>
|
||||||
|
</th:block>
|
||||||
|
<th:block th:if="${block.data.id == 'block_1_block-multiple-ctas' or block.data.id == 'block-multiple-ctas'}">
|
||||||
|
<div th:replace="~{themes/__${activeTheme}__/content-main-blocks-cta}"></div>
|
||||||
|
</th:block>
|
||||||
|
<th:block th:unless="${block.data.id == 'top-banner' or block.data.id == 'umass_banner_snippet' or block.data.id == 'content_top_snippet' or block.data.id == 'top_banner' or block.data.id == 'content-top' or block.data.id == 'block_1_block-multiple-ctas' or block.data.id == 'block-multiple-ctas'}">
|
||||||
<div th:utext="${block.data.htmlContent}" th:remove="tag"></div>
|
<div th:utext="${block.data.htmlContent}" th:remove="tag"></div>
|
||||||
</th:block>
|
</th:block>
|
||||||
|
</th:block>
|
||||||
|
|
||||||
<!-- 2. Header Block -->
|
<!-- 2. Header Block -->
|
||||||
<th:block th:if="${block.type == 'header'}">
|
<th:block th:if="${block.type == 'header'}">
|
||||||
|
|||||||
+46
@@ -0,0 +1,46 @@
|
|||||||
|
<div data-component-id="umass_base:block-multiple-ctas" data-background="solid" data-layout-variant="default">
|
||||||
|
<div class="container" th:if="${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><span th:utext="${ctaMenu.name}">TÌM HIỂU CHUYÊN KHOA</span></h2>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="links-container">
|
||||||
|
<div class="f--field f--button" th:each="item : ${ctaMenu.items}">
|
||||||
|
<a th:href="${item.url}" class="button-text-link button-context-light " th:aria-label="${item.label}" target="_self" data-component-id="umass_base:button">
|
||||||
|
<span class="button-text" th:text="${item.label}"> Apply </span>
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<!-- Fallback if menu is empty, show default CTA block -->
|
||||||
|
<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>
|
||||||
@@ -32,57 +32,35 @@
|
|||||||
<div class="text-container centered">
|
<div class="text-container centered">
|
||||||
<div class="slide-text-container-inner">
|
<div class="slide-text-container-inner">
|
||||||
<h3>
|
<h3>
|
||||||
<a href="https://www.umass.edu/gateway/why-umass">Be the Future You Want to See.</a>
|
<a href="https://www.umass.edu/gateway/why-umass">Stroke International School 2026.</a>
|
||||||
</h3>
|
</h3>
|
||||||
<div class="f--field f--button">
|
<div class="f--field f--button">
|
||||||
<a href="https://www.umass.edu/gateway/why-umass" class="button-secondary button-context-dark " aria-label="Learn More Learn more about UMass Amherst." data-component-id="umass_base:button">
|
<a href="https://www.umass.edu/gateway/why-umass" class="button-secondary button-context-dark " aria-label="Learn More Learn more about UMass Amherst." data-component-id="umass_base:button">
|
||||||
<span class="button-text"> Learn More </span>
|
<span class="button-text"> Learn More </span>
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
<nav class="mc--menu mc--info-menu">
|
<nav class="mc--menu mc--info-menu" th:if="${infoMenu != null and not #lists.isEmpty(infoMenu.items)}">
|
||||||
<ul class="menu m--menu m--info-menu">
|
<ul class="menu m--menu m--info-menu">
|
||||||
<li class="menu-item menu-item--expanded">
|
<li class="menu-item menu-item--expanded">
|
||||||
<details class="utility-button-wrapper mc--info-menu-container">
|
<details class="utility-button-wrapper mc--info-menu-container">
|
||||||
<summary type="button" class="utility-button arrow-toggle information-for-toggle" aria-label="Display submenu for Information menu" aria-expanded="false" aria-haspopup="true"> Info For <svg version="1.1" class="arrow" 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">
|
<summary type="button" aria-label="Display submenu for Information menu" aria-expanded="false" aria-haspopup="true" class="utility-button arrow-toggle information-for-toggle">
|
||||||
|
<span th:text="${infoMenu.name}">Info For</span>
|
||||||
|
<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" class="arrow">
|
||||||
<polygon fill-rule="evenodd" clip-rule="evenodd" fill="#ffffff" points="7,7 0,0 16,0 "></polygon>
|
<polygon fill-rule="evenodd" clip-rule="evenodd" fill="#ffffff" points="7,7 0,0 16,0 "></polygon>
|
||||||
</svg>
|
</svg>
|
||||||
</summary>
|
</summary>
|
||||||
<div class="submenu-wrapper">
|
<div class="submenu-wrapper">
|
||||||
<ul class="submenu">
|
<ul class="submenu">
|
||||||
<li class="menu-item">
|
<li class="menu-item" th:each="item : ${infoMenu.items}">
|
||||||
<a href="https://www.umass.edu/gateway/info/prospective-students">Prospective Students</a>
|
<a th:href="${item.url}" th:text="${item.label}">Prospective Students</a>
|
||||||
</li>
|
|
||||||
<li class="menu-item">
|
|
||||||
<a href="https://www.umass.edu/gateway/info/current-students">Current Students</a>
|
|
||||||
</li>
|
|
||||||
<li class="menu-item">
|
|
||||||
<a href="https://www.umass.edu/gateway/info/parents-and-families">Parents & Family</a>
|
|
||||||
</li>
|
|
||||||
<li class="menu-item">
|
|
||||||
<a href="https://www.umass.edu/gateway/info/faculty-and-staff">Faculty & Staff</a>
|
|
||||||
</li>
|
|
||||||
<li class="menu-item">
|
|
||||||
<a href="https://www.umassalumni.com/">Alumni</a>
|
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
</details>
|
</details>
|
||||||
<div class="submenu-wrapper-desktop">
|
<div class="submenu-wrapper-desktop">
|
||||||
<ul class="submenu">
|
<ul class="submenu">
|
||||||
<li class="menu-item">
|
<li class="menu-item" th:each="item : ${infoMenu.items}">
|
||||||
<a href="https://www.umass.edu/gateway/info/prospective-students">Prospective Students</a>
|
<a th:href="${item.url}" th:text="${item.label}">Prospective Students</a>
|
||||||
</li>
|
|
||||||
<li class="menu-item">
|
|
||||||
<a href="https://www.umass.edu/gateway/info/current-students">Current Students</a>
|
|
||||||
</li>
|
|
||||||
<li class="menu-item">
|
|
||||||
<a href="https://www.umass.edu/gateway/info/parents-and-families">Parents & Family</a>
|
|
||||||
</li>
|
|
||||||
<li class="menu-item">
|
|
||||||
<a href="https://www.umass.edu/gateway/info/faculty-and-staff">Faculty & Staff</a>
|
|
||||||
</li>
|
|
||||||
<li class="menu-item">
|
|
||||||
<a href="https://www.umassalumni.com/">Alumni</a>
|
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -0,0 +1,35 @@
|
|||||||
|
SET DEFINE OFF;
|
||||||
|
UPDATE html_snippet SET content = '
|
||||||
|
<div class="cc--component-container cc--stats-block bg-old-brick" style="color: white;">
|
||||||
|
<div class="c--component c--stats-block">
|
||||||
|
<div class="f--field f--stats-block">
|
||||||
|
<div class="cc--component-container cc--stat">
|
||||||
|
<div class="c--component c--stat">
|
||||||
|
<div class="f--field f--stat-number">50.000+</div>
|
||||||
|
<div class="f--field f--description">
|
||||||
|
<p>Tổng số ca cấp cứu</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="cc--component-container cc--stat">
|
||||||
|
<div class="c--component c--stat">
|
||||||
|
<div class="f--field f--stat-number">1.6tr+</div>
|
||||||
|
<div class="f--field f--description">
|
||||||
|
<p>Tổng số ca khám bệnh</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="cc--component-container cc--stat">
|
||||||
|
<div class="c--component c--stat">
|
||||||
|
<div class="f--field f--stat-number">#1</div>
|
||||||
|
<div class="f--field f--description">
|
||||||
|
<p>Về điều trị đột quỵ</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
' WHERE slug = 'block_3_button';
|
||||||
|
COMMIT;
|
||||||
|
EXIT;
|
||||||
Reference in New Issue
Block a user