Fix learn dialog rendering, add lab publish/draft toggle, bump to v0.1.2

- learn/index.html: restructured dialogs inside section divs to fix scope
- learn/index.html: edit-article dialogs via flat articles list in modal blocks
- LearnController: sectionChoices for select options; secure article fetching
- ContentService: createArticlePlaced: new section adjacent to anchor section
- lab status: published = student-visible, draft = hidden
- lab toggle: click badge in labs list or button in lab header to switch status
- added badge-btn CSS class, removed inline styles
- removed all th:onclick with expressions → data-modal attributes
- footer v0.1.2
This commit is contained in:
2026-09-11 20:41:11 +03:00
parent 08890875e5
commit 12383e7c39
11 changed files with 219 additions and 131 deletions

View File

@@ -231,6 +231,13 @@ class ContentService(
fun createArticlePlaced(title: String, bodyMd: String, chapterId: UUID?, newChapterTitle: String?,
sectionId: UUID?, newSectionTitle: String?): ContentArticleView {
val targetSection: ContentSection = when {
sectionId != null && !newSectionTitle.isNullOrBlank() -> {
val anchor = sections.findById(sectionId)
.orElseThrow { NotFoundException("Раздел не найден") }
val node = createSection(anchor.chapterId, newSectionTitle, null)
sections.findById(UUID.fromString(node.id))
.orElseThrow { NotFoundException("Раздел не найден") }
}
sectionId != null -> sections.findById(sectionId)
.orElseThrow { NotFoundException("Раздел не найден") }
!newSectionTitle.isNullOrBlank() -> {

View File

@@ -55,6 +55,12 @@ class LabController(private val labService: LabService) {
fun deleteVariant(@PathVariable id: UUID, @PathVariable variantId: UUID): LabDetail =
labService.deleteVariant(id, variantId)
@PostMapping("/{id}/toggle-status")
@PreAuthorize("hasAuthority('ROLE_ADMIN')")
fun toggleStatus(@PathVariable id: UUID) {
labService.toggleStatus(id)
}
@PostMapping
@PreAuthorize("hasAuthority('ROLE_ADMIN')")
fun create(@Valid @RequestBody body: LabCreateRequest): LabDetail = labService.create(body)

View File

@@ -257,10 +257,10 @@ class LabService(
return detail(labId)
}
@Transactional
@Transactional
fun addLevel(labId: UUID, request: LevelSaveRequest) {
val lab = labs.findById(labId).orElseThrow { NotFoundException("Лабораторная не найдена") }
if (request.code.isNullOrBlank()) throw BadRequestException("Код уровня не может быть пустым")
if (request.code.isBlank()) throw BadRequestException("Код уровня не может быть пустым")
val existing = labLevels.findByLabIdOrderByPosition(labId)
labLevels.save(
LabLevel(
@@ -273,6 +273,13 @@ class LabService(
)
}
@Transactional
fun toggleStatus(labId: UUID) {
val lab = labs.findById(labId).orElseThrow { NotFoundException("Лабораторная не найдена") }
lab.status = if (lab.status == "published") "draft" else "published"
labs.save(lab)
}
private fun findOrCreateSemester(title: String, year: Int): Semester {
semesters.findFirstByActiveTrue()?.let { return it }
val t = title.ifBlank { "осень" }