Hoan thanh chuc nang Page

This commit is contained in:
2026-06-25 21:34:36 +07:00
parent 6fe098bc5b
commit 38d6b8234a
16 changed files with 204 additions and 111 deletions
@@ -21,13 +21,9 @@
</head>
<body>
<header th:replace="~{fragments/header :: #l--main-header}"></header>
<div layout:fragment="content">
<!-- Nội dung của các trang con sẽ được chèn vào đây -->
<!-- All elements will be defined in the editor page -->
</div>
<footer th:replace="~{fragments/footer :: footer}"></footer>
</body>
</html>
@@ -117,8 +117,19 @@
</div>
<div class="row">
<!-- Page Type -->
<div class="col-md-4">
<div class="form-group">
<label for="pageType" class="font-weight-bold">Page Type <span
class="text-danger">*</span></label>
<select class="form-control" id="pageType" th:field="*{pageType}">
<option th:each="pt : ${pageTypes}" th:value="${pt}" th:text="${pt}"></option>
</select>
</div>
</div>
<!-- Status -->
<div class="col-md-6">
<div class="col-md-4">
<div class="form-group">
<label for="pageStatus" class="font-weight-bold">Status <span
class="text-danger">*</span></label>
@@ -129,7 +140,7 @@
</div>
<!-- Display Order -->
<div class="col-md-6">
<div class="col-md-4">
<div class="form-group">
<label for="pageDisplayOrder" class="font-weight-bold">Display Order</label>
<input type="number" class="form-control" id="pageDisplayOrder"
@@ -8,102 +8,79 @@
</head>
<body>
<!--
Because the user wants absolute freedom to design the page using snippets,
we will render the blocks directly into the content fragment with NO constraining containers.
If they want a container, they can use a standard snippet.
-->
<!-- Render Editor.js Blocks -->
<div layout:fragment="content">
<!-- Render Editor.js Blocks -->
<th:block th:each="block : ${blocks}">
<!-- 1. HTML Snippet Block (Custom) -->
<th:block th:if="${block.type == 'snippet'}">
<div th:insert="~{'snippets/' + ${block.data.id}}"></div>
<!-- 1. HTML Snippet Block (Custom) -->
<th:block th:if="${block.type == 'snippet'}">
<div th:insert="~{'snippets/' + ${block.data.id}}" th:remove="tag"></div>
</th:block>
<!-- 2. Header Block -->
<th:block th:if="${block.type == 'header'}">
<th:block th:switch="${block.data.level}">
<h1 th:case="1" th:utext="${block.data.text}"></h1>
<h2 th:case="2" th:utext="${block.data.text}"></h2>
<h3 th:case="3" th:utext="${block.data.text}"></h3>
<h4 th:case="4" th:utext="${block.data.text}"></h4>
<h5 th:case="5" th:utext="${block.data.text}"></h5>
<h6 th:case="6" th:utext="${block.data.text}"></h6>
<h2 th:case="*" th:utext="${block.data.text}"></h2>
</th:block>
<!-- 2. Header Block -->
<th:block th:if="${block.type == 'header'}">
<!-- Editor.js header block has level (1-6) and text -->
<div class="container my-3">
<th:block th:switch="${block.data.level}">
<h1 th:case="1" th:utext="${block.data.text}"></h1>
<h2 th:case="2" th:utext="${block.data.text}"></h2>
<h3 th:case="3" th:utext="${block.data.text}"></h3>
<h4 th:case="4" th:utext="${block.data.text}"></h4>
<h5 th:case="5" th:utext="${block.data.text}"></h5>
<h6 th:case="6" th:utext="${block.data.text}"></h6>
<h2 th:case="*" th:utext="${block.data.text}"></h2>
</th:block>
</div>
</th:block>
<!-- 3. Paragraph Block -->
<th:block th:if="${block.type == 'paragraph'}">
<div class="container">
<p th:utext="${block.data.text}"></p>
</div>
</th:block>
<!-- 4. List Block -->
<th:block th:if="${block.type == 'list'}">
<div class="container">
<ul th:if="${block.data.style == 'unordered'}">
<li th:each="item : ${block.data.items}" th:utext="${item}"></li>
</ul>
<ol th:if="${block.data.style == 'ordered'}">
<li th:each="item : ${block.data.items}" th:utext="${item}"></li>
</ol>
</div>
</th:block>
<!-- 5. Image Block -->
<th:block th:if="${block.type == 'image'}">
<div class="container text-center my-4">
<img th:src="${block.data.file.url}" class="img-fluid" th:alt="${block.data.caption}" />
<p class="text-muted small mt-1" th:if="${block.data.caption}" th:utext="${block.data.caption}"></p>
</div>
</th:block>
<!-- 6. Quote Block -->
<th:block th:if="${block.type == 'quote'}">
<div class="container my-4">
<blockquote class="blockquote">
<p class="mb-0" th:utext="${block.data.text}"></p>
<footer class="blockquote-footer" th:if="${block.data.caption}" th:utext="${block.data.caption}"></footer>
</blockquote>
</div>
</th:block>
<!-- 7. Delimiter Block -->
<th:block th:if="${block.type == 'delimiter'}">
<div class="container text-center my-4">
<span style="font-size: 24px; letter-spacing: 10px; color: #ccc;">***</span>
</div>
</th:block>
<!-- 8. Table Block -->
<th:block th:if="${block.type == 'table'}">
<div class="container my-4">
<table class="table table-bordered">
<tbody>
<tr th:each="row, rowStat : ${block.data.content}">
<!-- If withHeadings is true, make first row <th> -->
<th:block th:if="${block.data.withHeadings == true and rowStat.index == 0}">
<th th:each="cell : ${row}" th:utext="${cell}"></th>
</th:block>
<th:block th:unless="${block.data.withHeadings == true and rowStat.index == 0}">
<td th:each="cell : ${row}" th:utext="${cell}"></td>
</th:block>
</tr>
</tbody>
</table>
</div>
</th:block>
</th:block>
<!-- 3. Paragraph Block -->
<th:block th:if="${block.type == 'paragraph'}">
<p th:utext="${block.data.text}"></p>
</th:block>
<!-- 4. List Block -->
<th:block th:if="${block.type == 'list'}">
<ul th:if="${block.data.style == 'unordered'}">
<li th:each="item : ${block.data.items}" th:utext="${item}"></li>
</ul>
<ol th:if="${block.data.style == 'ordered'}">
<li th:each="item : ${block.data.items}" th:utext="${item}"></li>
</ol>
</th:block>
<!-- 5. Image Block -->
<th:block th:if="${block.type == 'image'}">
<img th:src="${block.data.file.url}" th:alt="${block.data.caption}" />
<p th:if="${block.data.caption}" th:utext="${block.data.caption}"></p>
</th:block>
<!-- 6. Quote Block -->
<th:block th:if="${block.type == 'quote'}">
<blockquote>
<p th:utext="${block.data.text}"></p>
<footer th:if="${block.data.caption}" th:utext="${block.data.caption}"></footer>
</blockquote>
</th:block>
<!-- 7. Delimiter Block -->
<th:block th:if="${block.type == 'delimiter'}">
<hr />
</th:block>
<!-- 8. Table Block -->
<th:block th:if="${block.type == 'table'}">
<table>
<tbody>
<tr th:each="row, rowStat : ${block.data.content}">
<th:block th:if="${block.data.withHeadings == true and rowStat.index == 0}">
<th th:each="cell : ${row}" th:utext="${cell}"></th>
</th:block>
<th:block th:unless="${block.data.withHeadings == true and rowStat.index == 0}">
<td th:each="cell : ${row}" th:utext="${cell}"></td>
</th:block>
</tr>
</tbody>
</table>
</th:block>
</th:block>
</div>
</body>