Learn: drag handles on the left, chapters always expanded
This commit is contained in:
@@ -246,19 +246,20 @@ code.code { padding: 0.125rem 0.5rem; border-radius: 0.25rem; font-family: monos
|
|||||||
.chip-neg { background: #b3283b; color: #fff; }
|
.chip-neg { background: #b3283b; color: #fff; }
|
||||||
|
|
||||||
/* Defense timer */
|
/* Defense timer */
|
||||||
/* Accordion (главы/разделы в /learn) */
|
/* Материалы: ряды и ручки перетаскивания слева, одним столбцом */
|
||||||
details.accordion > summary.acc-head { list-style: none; cursor: pointer; display: flex; align-items: center; justify-content: space-between; }
|
.sort-row { display: flex; align-items: center; gap: 0.5rem; min-width: 0; }
|
||||||
details.accordion > summary::-webkit-details-marker { display: none; }
|
.sort-title { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
|
||||||
details.accordion[open] > .acc-head, details.accordion > summary { margin-bottom: 0; }
|
.sort-actions { margin-left: auto; display: flex; flex-wrap: wrap; align-items: center; gap: 0.5rem; }
|
||||||
.acc-arrow { width: 10px; height: 10px; border-right: 2px solid var(--c-text-muted); border-bottom: 2px solid var(--c-text-muted); transform: rotate(45deg); transition: transform 0.2s; margin-left: .75rem;}
|
.sort-list { list-style: none; margin: 0; padding: 0; }
|
||||||
details.accordion[open] > summary > .acc-arrow { transform: rotate(-135deg); }
|
.sort-list > li { display: flex; align-items: center; gap: 0.5rem; min-width: 0; padding: 0.15rem 0; }
|
||||||
.acc-title { margin: 0; font-size: 1.0625rem; }
|
.chapter-card { padding: 0.75rem 1rem; }
|
||||||
.acc-body { border-top: 1px solid var(--c-border); }
|
details.sub-acc { margin-top: 0.25rem; border-top: 1px solid var(--c-border); }
|
||||||
details.sub-acc > summary.sub-head { list-style: none; cursor: pointer; }
|
[data-section-list] > details.sub-acc:first-of-type { border-top: none; }
|
||||||
|
details.sub-acc > summary.sub-head { list-style: none; cursor: pointer; padding: 0.4rem 0; }
|
||||||
details.sub-acc > summary::-webkit-details-marker { display: none; }
|
details.sub-acc > summary::-webkit-details-marker { display: none; }
|
||||||
.sub-arrow { display: inline-block; width: 8px; height: 8px; border-right: 2px solid var(--c-text-muted); border-bottom: 2px solid var(--c-text-muted); transform: rotate(45deg); transition: transform 0.2s; margin-right: 6px; vertical-align: 2px;}
|
.sub-arrow { flex: 0 0 auto; width: 8px; height: 8px; border-right: 2px solid var(--c-text-muted); border-bottom: 2px solid var(--c-text-muted); transform: rotate(45deg); transition: transform 0.2s; }
|
||||||
details.sub-acc[open] > summary .sub-arrow { transform: rotate(-135deg); }
|
details.sub-acc[open] > summary .sub-arrow { transform: rotate(-135deg); }
|
||||||
.sub-actions { margin: 0 0 2px 18px; }
|
.section-body { padding-bottom: 0.4rem; }
|
||||||
|
|
||||||
/* ---- Матрица группы и карточки защиты ---- */
|
/* ---- Матрица группы и карточки защиты ---- */
|
||||||
.m-0 { margin: 0; }
|
.m-0 { margin: 0; }
|
||||||
@@ -351,8 +352,9 @@ th.th-filterable { padding-bottom: 0.35rem; }
|
|||||||
|
|
||||||
/* drag & drop материалов */
|
/* drag & drop материалов */
|
||||||
.drag-handle {
|
.drag-handle {
|
||||||
|
display: inline-block; flex: 0 0 auto; width: 1.5rem; text-align: center;
|
||||||
cursor: grab; user-select: none; color: var(--c-text-muted);
|
cursor: grab; user-select: none; color: var(--c-text-muted);
|
||||||
font-size: 1rem; line-height: 1; padding: 0.15rem 0.3rem; border-radius: 0.35rem;
|
font-size: 1rem; line-height: 1; padding: 0.15rem 0; border-radius: 0.35rem;
|
||||||
}
|
}
|
||||||
.drag-handle:hover { background: var(--c-bg); color: var(--c-text); }
|
.drag-handle:hover { background: var(--c-bg); color: var(--c-text); }
|
||||||
.drag-handle:active { cursor: grabbing; }
|
.drag-handle:active { cursor: grabbing; }
|
||||||
|
|||||||
@@ -35,8 +35,8 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div th:if="${currentUser != null and currentUser.admin}" class="card card-body text-sm text-muted mb-4">
|
<div th:if="${currentUser != null and currentUser.admin}" class="card card-body text-sm text-muted mb-4">
|
||||||
Перетаскивайте разделы и статьи за значок ⠿, чтобы менять порядок и переносить статьи между
|
Перетаскивайте за значок ⠿ слева, чтобы менять порядок разделов и переносить статьи
|
||||||
разделами этой главы. Порядок сохраняется сразу.
|
между разделами этой главы. Порядок сохраняется сразу.
|
||||||
</div>
|
</div>
|
||||||
<div th:if="${currentUser != null and currentUser.admin}" id="sort-status" class="sort-status" hidden>
|
<div th:if="${currentUser != null and currentUser.admin}" id="sort-status" class="sort-status" hidden>
|
||||||
<span id="sort-status-text">Изменения не сохранены…</span>
|
<span id="sort-status-text">Изменения не сохранены…</span>
|
||||||
@@ -46,65 +46,69 @@
|
|||||||
В этой главе пока нет разделов.
|
В этой главе пока нет разделов.
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div data-section-list>
|
<div class="card card-body chapter-card mb-4" data-section-list>
|
||||||
<div th:each="section : ${chapter.sections}" class="card card-body mb-4"
|
<details th:each="section : ${chapter.sections}" class="sub-acc" th:attr="data-section-id=${section.id}">
|
||||||
th:attr="data-section-id=${section.id}">
|
<summary class="sub-head sort-row">
|
||||||
<div class="flex flex-wrap items-center justify-between gap-2 mb-2">
|
<span th:if="${currentUser != null and currentUser.admin}" class="drag-handle" draggable="true"
|
||||||
<h2 class="group-title m-0">
|
th:attr="data-drag-kind='section',data-drag-id=${section.id}"
|
||||||
<span th:if="${currentUser != null and currentUser.admin}" class="drag-handle" draggable="true"
|
title="Перетащите мышью: изменить порядок разделов">⠿</span>
|
||||||
th:attr="data-drag-kind='section',data-drag-id=${section.id}"
|
<span class="sub-arrow" aria-hidden="true"></span>
|
||||||
title="Перетащите, чтобы изменить порядок разделов">⠿</span>
|
<a class="group-title sort-title m-0"
|
||||||
<a th:href="@{/learn/{c}/{s}(c=${chapter.slug}, s=${section.slug})}" th:text="${section.title}">Раздел</a>
|
th:href="@{/learn/{c}/{s}(c=${chapter.slug}, s=${section.slug})}"
|
||||||
<span th:if="${!section.published}" class="badge badge-warn">скрыто</span>
|
th:text="${section.title}">Раздел</a>
|
||||||
</h2>
|
<span th:if="${!section.published}" class="badge badge-warn">скрыто</span>
|
||||||
<div th:if="${currentUser != null and currentUser.admin}" class="flex flex-wrap gap-2">
|
</summary>
|
||||||
<button class="btn btn-secondary btn-sm" type="button"
|
<div class="section-body">
|
||||||
th:data-modal="|modal-rename-section-${section.id}|" onclick="openModalData(this)">Переименовать</button>
|
<div th:if="${currentUser != null and currentUser.admin}" class="sort-row">
|
||||||
<form class="inline-form" th:action="@{/admin/content/sections/toggle-published}" method="post">
|
<div class="sort-actions">
|
||||||
<input type="hidden" name="_csrf" th:value="${csrfToken}">
|
<button class="btn btn-secondary btn-sm" type="button"
|
||||||
<input type="hidden" name="id" th:value="${section.id}">
|
th:data-modal="|modal-rename-section-${section.id}|" onclick="openModalData(this)">Переименовать</button>
|
||||||
<input type="hidden" name="published" th:value="${!section.published}">
|
<form class="inline-form" th:action="@{/admin/content/sections/toggle-published}" method="post">
|
||||||
<input type="hidden" name="back" th:value="${back}">
|
|
||||||
<button class="btn btn-sm" type="submit"
|
|
||||||
th:classappend="${section.published} ? 'btn-secondary' : 'btn-primary'"
|
|
||||||
th:text="${section.published} ? 'Скрыть' : 'Опубликовать'">Скрыть</button>
|
|
||||||
</form>
|
|
||||||
<button class="btn btn-secondary btn-sm" type="button"
|
|
||||||
th:data-modal="|modal-move-${section.id}|" onclick="openModalData(this)">Перенести статьи и удалить</button>
|
|
||||||
<form class="inline-form" th:action="@{/admin/content/sections/{id}/delete(id=${section.id})}" method="post"
|
|
||||||
onsubmit="return confirm('Удалить раздел вместе со статьями?')">
|
|
||||||
<input type="hidden" name="_csrf" th:value="${csrfToken}">
|
|
||||||
<input type="hidden" name="back" th:value="${back}">
|
|
||||||
<button class="btn btn-danger btn-sm" type="submit">Удалить</button>
|
|
||||||
</form>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<ul class="list-pad text-sm" data-article-list>
|
|
||||||
<li th:each="article : ${section.articles}" class="flex items-center gap-2"
|
|
||||||
th:attr="data-article-id=${article.id}">
|
|
||||||
<span th:if="${currentUser != null and currentUser.admin}" class="drag-handle" draggable="true"
|
|
||||||
th:attr="data-drag-kind='article',data-drag-id=${article.id}"
|
|
||||||
title="Перетащите, чтобы изменить порядок или перенести в другой раздел">⠿</span>
|
|
||||||
<a th:href="@{/learn/{c}/{s}/{a}(c=${chapter.slug}, s=${section.slug}, a=${article.slug})}"
|
|
||||||
th:text="${article.title}">Статья</a>
|
|
||||||
<span th:if="${!article.published}" class="badge badge-warn">скрыто</span>
|
|
||||||
<th:block th:if="${currentUser != null and currentUser.admin}">
|
|
||||||
<a class="btn btn-secondary btn-sm"
|
|
||||||
th:href="@{/learn/{c}/{s}/{a}(c=${chapter.slug}, s=${section.slug}, a=${article.slug}, edit=1)}">Править</a>
|
|
||||||
<form class="inline-form" th:action="@{/admin/content/articles/toggle-published}" method="post">
|
|
||||||
<input type="hidden" name="_csrf" th:value="${csrfToken}">
|
<input type="hidden" name="_csrf" th:value="${csrfToken}">
|
||||||
<input type="hidden" name="id" th:value="${article.id}">
|
<input type="hidden" name="id" th:value="${section.id}">
|
||||||
<input type="hidden" name="published" th:value="${!article.published}">
|
<input type="hidden" name="published" th:value="${!section.published}">
|
||||||
<input type="hidden" name="back" th:value="${back}">
|
<input type="hidden" name="back" th:value="${back}">
|
||||||
<button class="btn btn-sm" type="submit"
|
<button class="btn btn-sm" type="submit"
|
||||||
th:classappend="${article.published} ? 'btn-secondary' : 'btn-primary'"
|
th:classappend="${section.published} ? 'btn-secondary' : 'btn-primary'"
|
||||||
th:text="${article.published} ? 'Скрыть' : 'Опубликовать'">Скрыть</button>
|
th:text="${section.published} ? 'Скрыть' : 'Опубликовать'">Скрыть</button>
|
||||||
</form>
|
</form>
|
||||||
</th:block>
|
<button class="btn btn-secondary btn-sm" type="button"
|
||||||
</li>
|
th:data-modal="|modal-move-${section.id}|" onclick="openModalData(this)">Перенести статьи и удалить</button>
|
||||||
<li th:if="${#lists.isEmpty(section.articles)}" class="text-muted">Статей пока нет</li>
|
<form class="inline-form" th:action="@{/admin/content/sections/{id}/delete(id=${section.id})}" method="post"
|
||||||
</ul>
|
onsubmit="return confirm('Удалить раздел вместе со статьями?')">
|
||||||
|
<input type="hidden" name="_csrf" th:value="${csrfToken}">
|
||||||
|
<input type="hidden" name="back" th:value="${back}">
|
||||||
|
<button class="btn btn-danger btn-sm" type="submit">Удалить</button>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<ul class="sort-list text-sm" data-article-list>
|
||||||
|
<li th:each="article : ${section.articles}" th:attr="data-article-id=${article.id}">
|
||||||
|
<span th:if="${currentUser != null and currentUser.admin}" class="drag-handle" draggable="true"
|
||||||
|
th:attr="data-drag-kind='article',data-drag-id=${article.id}"
|
||||||
|
title="Перетащите мышью: изменить порядок или перенести в другой раздел">⠿</span>
|
||||||
|
<a class="sort-title"
|
||||||
|
th:href="@{/learn/{c}/{s}/{a}(c=${chapter.slug}, s=${section.slug}, a=${article.slug})}"
|
||||||
|
th:text="${article.title}">Статья</a>
|
||||||
|
<span th:if="${!article.published}" class="badge badge-warn">скрыто</span>
|
||||||
|
<div th:if="${currentUser != null and currentUser.admin}" class="sort-actions">
|
||||||
|
<a class="btn btn-secondary btn-sm"
|
||||||
|
th:href="@{/learn/{c}/{s}/{a}(c=${chapter.slug}, s=${section.slug}, a=${article.slug}, edit=1)}">Править</a>
|
||||||
|
<form class="inline-form" th:action="@{/admin/content/articles/toggle-published}" method="post">
|
||||||
|
<input type="hidden" name="_csrf" th:value="${csrfToken}">
|
||||||
|
<input type="hidden" name="id" th:value="${article.id}">
|
||||||
|
<input type="hidden" name="published" th:value="${!article.published}">
|
||||||
|
<input type="hidden" name="back" th:value="${back}">
|
||||||
|
<button class="btn btn-sm" type="submit"
|
||||||
|
th:classappend="${article.published} ? 'btn-secondary' : 'btn-primary'"
|
||||||
|
th:text="${article.published} ? 'Скрыть' : 'Опубликовать'">Скрыть</button>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</li>
|
||||||
|
<li th:if="${#lists.isEmpty(section.articles)}" class="text-muted">Статей пока нет</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
|
||||||
<th:block th:if="${currentUser != null and currentUser.admin}">
|
<th:block th:if="${currentUser != null and currentUser.admin}">
|
||||||
<dialog th:id="|modal-rename-section-${section.id}|" class="modal">
|
<dialog th:id="|modal-rename-section-${section.id}|" class="modal">
|
||||||
@@ -145,7 +149,7 @@
|
|||||||
</div>
|
</div>
|
||||||
</dialog>
|
</dialog>
|
||||||
</th:block>
|
</th:block>
|
||||||
</div>
|
</details>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<dialog id="modal-rename-chapter" class="modal">
|
<dialog id="modal-rename-chapter" class="modal">
|
||||||
|
|||||||
@@ -13,9 +13,8 @@
|
|||||||
</div>
|
</div>
|
||||||
<div th:if="${currentUser != null and currentUser.admin}" class="card card-body text-sm text-muted mb-4">
|
<div th:if="${currentUser != null and currentUser.admin}" class="card card-body text-sm text-muted mb-4">
|
||||||
Режим администратора: скрытые главы, разделы и статьи помечены значком «скрыто»
|
Режим администратора: скрытые главы, разделы и статьи помечены значком «скрыто»
|
||||||
и видны только вам. Кнопка-значок публикует материал для студентов или снова скрывает его.
|
и видны только вам. Перетаскивайте за значок ⠿ слева, чтобы менять порядок глав, разделов
|
||||||
Перетаскивайте за значок ⠿, чтобы менять порядок глав, разделов и статей, а также
|
и статей, а также переносить разделы в другую главу и статьи — в другой раздел.
|
||||||
переносить разделы в другую главу и статьи — в другой раздел.
|
|
||||||
</div>
|
</div>
|
||||||
<div th:if="${currentUser != null and currentUser.admin}" id="sort-status" class="sort-status" hidden>
|
<div th:if="${currentUser != null and currentUser.admin}" id="sort-status" class="sort-status" hidden>
|
||||||
<span id="sort-status-text">Изменения не сохранены…</span>
|
<span id="sort-status-text">Изменения не сохранены…</span>
|
||||||
@@ -28,105 +27,101 @@
|
|||||||
Материалы ещё не добавлены.
|
Материалы ещё не добавлены.
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<details th:each="chapter, chStat : ${tree?.chapters}" class="card mb-4 accordion"
|
<div th:each="chapter : ${tree?.chapters}" class="card card-body chapter-card mb-4"
|
||||||
th:attr="open=${chStat.last},data-chapter-id=${chapter.id}">
|
th:attr="data-chapter-id=${chapter.id}">
|
||||||
<summary class="card-body acc-head">
|
<div class="sort-row">
|
||||||
<h2 class="section-title acc-title" th:text="${chapter.title}">Глава</h2>
|
<span th:if="${currentUser != null and currentUser.admin}" class="drag-handle" draggable="true"
|
||||||
<span class="acc-arrow" aria-hidden="true"></span>
|
th:attr="data-drag-kind='chapter',data-drag-id=${chapter.id}"
|
||||||
</summary>
|
title="Перетащите мышью: изменить порядок глав">⠿</span>
|
||||||
<div class="card-body acc-body" data-section-list>
|
<h2 class="section-title sort-title m-0" th:text="${chapter.title}">Глава</h2>
|
||||||
<div class="flex flex-wrap items-center justify-between gap-4 mb-4">
|
<span th:if="${!chapter.published}" class="badge badge-warn">скрыто</span>
|
||||||
<h2 class="section-title m-0">
|
<div th:if="${currentUser != null and currentUser.admin}" class="sort-actions">
|
||||||
<span th:text="${chapter.title}">Глава</span>
|
<form class="inline-form" th:action="@{/admin/content/chapters/toggle-published}" method="post">
|
||||||
<span th:if="${!chapter.published}" class="badge badge-warn ml-2">скрыто</span>
|
<input type="hidden" name="_csrf" th:value="${csrfToken}">
|
||||||
</h2>
|
<input type="hidden" name="id" th:value="${chapter.id}">
|
||||||
<div th:if="${currentUser != null and currentUser.admin}" class="flex flex-wrap items-center gap-2">
|
<input type="hidden" name="published" th:value="${!chapter.published}">
|
||||||
<span class="drag-handle" draggable="true"
|
<button class="btn btn-sm" type="submit"
|
||||||
th:attr="data-drag-kind='chapter',data-drag-id=${chapter.id}"
|
th:classappend="${chapter.published} ? 'btn-secondary' : 'btn-primary'"
|
||||||
title="Перетащите мышью: изменить порядок или перенести главу">⠿</span>
|
th:text="${chapter.published} ? 'Скрыть главу' : 'Опубликовать главу'">Скрыть главу</button>
|
||||||
<form class="inline-form" th:action="@{/admin/content/chapters/toggle-published}" method="post">
|
</form>
|
||||||
<input type="hidden" name="_csrf" th:value="${csrfToken}">
|
<button class="btn btn-secondary btn-sm" type="button"
|
||||||
<input type="hidden" name="id" th:value="${chapter.id}">
|
th:data-modal="|modal-rename-chapter-${chapter.id}|" onclick="openModalData(this)">Переименовать</button>
|
||||||
<input type="hidden" name="published" th:value="${!chapter.published}">
|
<form class="inline-form" th:action="@{/admin/content/chapters/{id}/delete(id=${chapter.id})}" method="post"
|
||||||
<button class="btn btn-sm" type="submit"
|
onsubmit="return confirm('Удалить главу со всеми разделами и статьями?')">
|
||||||
th:classappend="${chapter.published} ? 'btn-secondary' : 'btn-primary'"
|
<input type="hidden" name="_csrf" th:value="${csrfToken}">
|
||||||
th:text="${chapter.published} ? 'Скрыть главу' : 'Опубликовать главу'">Скрыть главу</button>
|
<button class="btn btn-danger btn-sm" type="submit">Удалить главу</button>
|
||||||
</form>
|
</form>
|
||||||
<button class="btn btn-secondary btn-sm" type="button"
|
|
||||||
th:data-modal="|modal-rename-chapter-${chapter.id}|" onclick="openModalData(this)">Переименовать</button>
|
|
||||||
<form th:action="@{/admin/content/chapters/{id}/delete(id=${chapter.id})}" method="post"
|
|
||||||
onsubmit="return confirm('Удалить главу со всеми разделами и статьями?')">
|
|
||||||
<input type="hidden" name="_csrf" th:value="${csrfToken}">
|
|
||||||
<button class="btn btn-danger btn-sm" type="submit">Удалить главу</button>
|
|
||||||
</form>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
<p th:if="${#lists.isEmpty(chapter.sections)}" class="text-sm text-muted">Разделов пока нет</p>
|
<div data-section-list>
|
||||||
|
<p th:if="${#lists.isEmpty(chapter.sections)}" class="text-sm text-muted mt-2 mb-0">Разделов пока нет</p>
|
||||||
|
|
||||||
<details th:each="section : ${chapter.sections}" class="mt-4 sub-acc"
|
<details th:each="section : ${chapter.sections}" class="sub-acc"
|
||||||
th:attr="data-section-id=${section.id}">
|
th:attr="data-section-id=${section.id}">
|
||||||
<summary class="sub-head">
|
<summary class="sub-head sort-row">
|
||||||
<h3 class="group-title m-0">
|
<span th:if="${currentUser != null and currentUser.admin}" class="drag-handle" draggable="true"
|
||||||
<span class="sub-arrow" aria-hidden="true"></span>
|
th:attr="data-drag-kind='section',data-drag-id=${section.id}"
|
||||||
<a th:href="@{/learn/{c}/{s}(c=${chapter.slug}, s=${section.slug})}" th:text="${section.title}">Раздел</a>
|
title="Перетащите мышью: изменить порядок или перенести раздел">⠿</span>
|
||||||
<span th:if="${!section.published}" class="badge badge-warn ml-2">скрыто</span>
|
<span class="sub-arrow" aria-hidden="true"></span>
|
||||||
</h3>
|
<a class="group-title sort-title m-0"
|
||||||
|
th:href="@{/learn/{c}/{s}(c=${chapter.slug}, s=${section.slug})}"
|
||||||
|
th:text="${section.title}">Раздел</a>
|
||||||
|
<span th:if="${!section.published}" class="badge badge-warn">скрыто</span>
|
||||||
</summary>
|
</summary>
|
||||||
<div class="flex flex-wrap items-center justify-between gap-4 sub-actions">
|
<div class="section-body">
|
||||||
<div class="spacer"></div>
|
<div th:if="${currentUser != null and currentUser.admin}" class="sort-row">
|
||||||
<div th:if="${currentUser != null and currentUser.admin}" class="flex flex-wrap items-center gap-2">
|
<div class="sort-actions">
|
||||||
<span class="drag-handle" draggable="true"
|
<form class="inline-form" th:action="@{/admin/content/sections/toggle-published}" method="post">
|
||||||
th:attr="data-drag-kind='section',data-drag-id=${section.id}"
|
|
||||||
title="Перетащите мышью: изменить порядок или перенести раздел">⠿</span>
|
|
||||||
<form class="inline-form" th:action="@{/admin/content/sections/toggle-published}" method="post">
|
|
||||||
<input type="hidden" name="_csrf" th:value="${csrfToken}">
|
|
||||||
<input type="hidden" name="id" th:value="${section.id}">
|
|
||||||
<input type="hidden" name="published" th:value="${!section.published}">
|
|
||||||
<button class="btn btn-sm" type="submit"
|
|
||||||
th:classappend="${section.published} ? 'btn-secondary' : 'btn-primary'"
|
|
||||||
th:text="${section.published} ? 'Скрыть раздел' : 'Опубликовать раздел'">Скрыть раздел</button>
|
|
||||||
</form>
|
|
||||||
<button class="btn btn-secondary btn-sm" type="button"
|
|
||||||
th:data-modal="|modal-rename-section-${section.id}|" onclick="openModalData(this)">Переименовать</button>
|
|
||||||
<button class="btn btn-secondary btn-sm" type="button"
|
|
||||||
th:data-modal="|modal-move-${section.id}|" onclick="openModalData(this)">Перенести статьи</button>
|
|
||||||
<form class="inline-form" th:action="@{/admin/content/sections/{id}/delete(id=${section.id})}" method="post"
|
|
||||||
onsubmit="return confirm('Удалить раздел со всеми статьями?')">
|
|
||||||
<input type="hidden" name="_csrf" th:value="${csrfToken}">
|
|
||||||
<button class="btn btn-danger btn-sm" type="submit">Удалить раздел</button>
|
|
||||||
</form>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<ul class="list-pad text-sm" data-article-list>
|
|
||||||
<li th:each="article : ${section.articles}" class="flex items-center gap-2"
|
|
||||||
th:attr="data-article-id=${article.id}">
|
|
||||||
<a th:href="@{/learn/{c}/{s}/{a}(c=${chapter.slug}, s=${section.slug}, a=${article.slug})}"
|
|
||||||
th:text="${article.title}">Статья</a>
|
|
||||||
<span th:if="${!article.published}" class="badge badge-warn">скрыто</span>
|
|
||||||
<th:block th:if="${currentUser != null and currentUser.admin}">
|
|
||||||
<span class="drag-handle" draggable="true"
|
|
||||||
th:attr="data-drag-kind='article',data-drag-id=${article.id}"
|
|
||||||
title="Перетащите мышью: изменить порядок или перенести статью">⠿</span>
|
|
||||||
<form class="inline-form" th:action="@{/admin/content/articles/toggle-published}" method="post">
|
|
||||||
<input type="hidden" name="_csrf" th:value="${csrfToken}">
|
<input type="hidden" name="_csrf" th:value="${csrfToken}">
|
||||||
<input type="hidden" name="id" th:value="${article.id}">
|
<input type="hidden" name="id" th:value="${section.id}">
|
||||||
<input type="hidden" name="published" th:value="${!article.published}">
|
<input type="hidden" name="published" th:value="${!section.published}">
|
||||||
<button class="btn btn-sm" type="submit"
|
<button class="btn btn-sm" type="submit"
|
||||||
th:classappend="${article.published} ? 'btn-secondary' : 'btn-primary'"
|
th:classappend="${section.published} ? 'btn-secondary' : 'btn-primary'"
|
||||||
th:text="${article.published} ? 'Скрыть' : 'Опубликовать'">Скрыть</button>
|
th:text="${section.published} ? 'Скрыть раздел' : 'Опубликовать раздел'">Скрыть раздел</button>
|
||||||
</form>
|
</form>
|
||||||
<a class="btn btn-secondary btn-sm"
|
<button class="btn btn-secondary btn-sm" type="button"
|
||||||
th:href="@{/learn/{c}/{s}/{a}(c=${chapter.slug}, s=${section.slug}, a=${article.slug}, edit=1)}">Править</a>
|
th:data-modal="|modal-rename-section-${section.id}|" onclick="openModalData(this)">Переименовать</button>
|
||||||
<form class="inline-form" th:action="@{/admin/content/articles/{id}/delete(id=${article.id})}" method="post"
|
<button class="btn btn-secondary btn-sm" type="button"
|
||||||
onsubmit="return confirm('Удалить статью?')">
|
th:data-modal="|modal-move-${section.id}|" onclick="openModalData(this)">Перенести статьи</button>
|
||||||
|
<form class="inline-form" th:action="@{/admin/content/sections/{id}/delete(id=${section.id})}" method="post"
|
||||||
|
onsubmit="return confirm('Удалить раздел со всеми статьями?')">
|
||||||
<input type="hidden" name="_csrf" th:value="${csrfToken}">
|
<input type="hidden" name="_csrf" th:value="${csrfToken}">
|
||||||
<button class="btn btn-danger btn-sm" type="submit">✕</button>
|
<button class="btn btn-danger btn-sm" type="submit">Удалить раздел</button>
|
||||||
</form>
|
</form>
|
||||||
</th:block>
|
</div>
|
||||||
</li>
|
</div>
|
||||||
<li th:if="${#lists.isEmpty(section.articles)}" class="text-muted">Статей пока нет</li>
|
|
||||||
</ul>
|
<ul class="sort-list text-sm" data-article-list>
|
||||||
|
<li th:each="article : ${section.articles}" th:attr="data-article-id=${article.id}">
|
||||||
|
<span th:if="${currentUser != null and currentUser.admin}" class="drag-handle" draggable="true"
|
||||||
|
th:attr="data-drag-kind='article',data-drag-id=${article.id}"
|
||||||
|
title="Перетащите мышью: изменить порядок или перенести статью">⠿</span>
|
||||||
|
<a class="sort-title"
|
||||||
|
th:href="@{/learn/{c}/{s}/{a}(c=${chapter.slug}, s=${section.slug}, a=${article.slug})}"
|
||||||
|
th:text="${article.title}">Статья</a>
|
||||||
|
<span th:if="${!article.published}" class="badge badge-warn">скрыто</span>
|
||||||
|
<div th:if="${currentUser != null and currentUser.admin}" class="sort-actions">
|
||||||
|
<form class="inline-form" th:action="@{/admin/content/articles/toggle-published}" method="post">
|
||||||
|
<input type="hidden" name="_csrf" th:value="${csrfToken}">
|
||||||
|
<input type="hidden" name="id" th:value="${article.id}">
|
||||||
|
<input type="hidden" name="published" th:value="${!article.published}">
|
||||||
|
<button class="btn btn-sm" type="submit"
|
||||||
|
th:classappend="${article.published} ? 'btn-secondary' : 'btn-primary'"
|
||||||
|
th:text="${article.published} ? 'Скрыть' : 'Опубликовать'">Скрыть</button>
|
||||||
|
</form>
|
||||||
|
<a class="btn btn-secondary btn-sm"
|
||||||
|
th:href="@{/learn/{c}/{s}/{a}(c=${chapter.slug}, s=${section.slug}, a=${article.slug}, edit=1)}">Править</a>
|
||||||
|
<form class="inline-form" th:action="@{/admin/content/articles/{id}/delete(id=${article.id})}" method="post"
|
||||||
|
onsubmit="return confirm('Удалить статью?')">
|
||||||
|
<input type="hidden" name="_csrf" th:value="${csrfToken}">
|
||||||
|
<button class="btn btn-danger btn-sm" type="submit">✕</button>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</li>
|
||||||
|
<li th:if="${#lists.isEmpty(section.articles)}" class="text-muted">Статей пока нет</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
|
||||||
<th:block th:if="${currentUser != null and currentUser.admin}">
|
<th:block th:if="${currentUser != null and currentUser.admin}">
|
||||||
<dialog th:id="|modal-rename-section-${section.id}|" class="modal">
|
<dialog th:id="|modal-rename-section-${section.id}|" class="modal">
|
||||||
@@ -165,25 +160,26 @@
|
|||||||
</dialog>
|
</dialog>
|
||||||
</th:block>
|
</th:block>
|
||||||
</details>
|
</details>
|
||||||
<th:block th:if="${currentUser != null and currentUser.admin}">
|
|
||||||
<dialog th:id="|modal-rename-chapter-${chapter.id}|" class="modal">
|
|
||||||
<div class="modal-header">
|
|
||||||
<h2 class="modal-title">Переименовать главу</h2>
|
|
||||||
<button class="modal-close" type="button"
|
|
||||||
th:data-modal="|modal-rename-chapter-${chapter.id}|" onclick="closeModalData(this)">✕</button>
|
|
||||||
</div>
|
|
||||||
<div class="modal-body">
|
|
||||||
<form class="form-stack" th:action="@{/admin/content/chapters/{id}/rename(id=${chapter.id})}" method="post">
|
|
||||||
<input type="hidden" name="_csrf" th:value="${csrfToken}">
|
|
||||||
<div><label class="label">Название</label>
|
|
||||||
<input class="input" name="title" th:value="${chapter.title}" required></div>
|
|
||||||
<button class="btn btn-primary" type="submit">Сохранить</button>
|
|
||||||
</form>
|
|
||||||
</div>
|
|
||||||
</dialog>
|
|
||||||
</th:block>
|
|
||||||
</div>
|
</div>
|
||||||
</details>
|
|
||||||
|
<th:block th:if="${currentUser != null and currentUser.admin}">
|
||||||
|
<dialog th:id="|modal-rename-chapter-${chapter.id}|" class="modal">
|
||||||
|
<div class="modal-header">
|
||||||
|
<h2 class="modal-title">Переименовать главу</h2>
|
||||||
|
<button class="modal-close" type="button"
|
||||||
|
th:data-modal="|modal-rename-chapter-${chapter.id}|" onclick="closeModalData(this)">✕</button>
|
||||||
|
</div>
|
||||||
|
<div class="modal-body">
|
||||||
|
<form class="form-stack" th:action="@{/admin/content/chapters/{id}/rename(id=${chapter.id})}" method="post">
|
||||||
|
<input type="hidden" name="_csrf" th:value="${csrfToken}">
|
||||||
|
<div><label class="label">Название</label>
|
||||||
|
<input class="input" name="title" th:value="${chapter.title}" required></div>
|
||||||
|
<button class="btn btn-primary" type="submit">Сохранить</button>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</dialog>
|
||||||
|
</th:block>
|
||||||
|
</div>
|
||||||
|
|
||||||
<dialog id="modal-import" class="modal">
|
<dialog id="modal-import" class="modal">
|
||||||
<div class="modal-header">
|
<div class="modal-header">
|
||||||
|
|||||||
Reference in New Issue
Block a user