Refactor: bind content admin forms via @ModelAttribute DTOs

This commit is contained in:
2026-09-27 22:06:09 +03:00
parent 82b912ba46
commit 5fbd9cb6cb
2 changed files with 52 additions and 33 deletions

View File

@@ -3,6 +3,7 @@ package ru.ysu.lms.web.admin
import jakarta.servlet.http.HttpSession import jakarta.servlet.http.HttpSession
import org.springframework.stereotype.Controller import org.springframework.stereotype.Controller
import org.springframework.web.bind.annotation.GetMapping import org.springframework.web.bind.annotation.GetMapping
import org.springframework.web.bind.annotation.ModelAttribute
import org.springframework.web.bind.annotation.PathVariable import org.springframework.web.bind.annotation.PathVariable
import org.springframework.web.bind.annotation.PostMapping import org.springframework.web.bind.annotation.PostMapping
import org.springframework.web.bind.annotation.RequestBody import org.springframework.web.bind.annotation.RequestBody
@@ -91,19 +92,17 @@ class ContentAdminController(
@PostMapping("/{kind}/toggle-published") @PostMapping("/{kind}/toggle-published")
fun togglePublished( fun togglePublished(
@PathVariable kind: String, @PathVariable kind: String,
@RequestParam id: String, @ModelAttribute form: TogglePublishedForm,
@RequestParam published: Boolean,
@RequestParam(required = false) back: String?,
session: HttpSession, session: HttpSession,
redirect: RedirectAttributes, redirect: RedirectAttributes,
): String = ): String =
try { try {
api.setContentPublished(token(session), kind, id, published) api.setContentPublished(token(session), kind, form.id, form.published)
redirect.addFlashAttribute( redirect.addFlashAttribute(
"notice", "notice",
if (published) "Материал опубликован — теперь его видят студенты" else "Материал скрыт от студентов", if (form.published) "Материал опубликован — теперь его видят студенты" else "Материал скрыт от студентов",
) )
redirectBack(back, "redirect:/learn") redirectBack(form.back, "redirect:/learn")
} catch (ex: ApiException) { } catch (ex: ApiException) {
redirect.addFlashAttribute("error", ex.message) redirect.addFlashAttribute("error", ex.message)
"redirect:/learn" "redirect:/learn"
@@ -112,16 +111,14 @@ class ContentAdminController(
@PostMapping("/articles/{id}/save") @PostMapping("/articles/{id}/save")
fun save( fun save(
@PathVariable id: String, @PathVariable id: String,
@RequestParam title: String, @ModelAttribute form: ArticleSaveForm,
@RequestParam bodyMd: String,
@RequestParam(required = false) back: String?,
session: HttpSession, session: HttpSession,
redirect: RedirectAttributes, redirect: RedirectAttributes,
): String = ): String =
try { try {
api.updateContentArticle(token(session), id, title, bodyMd) api.updateContentArticle(token(session), id, form.title, form.bodyMd)
redirect.addFlashAttribute("notice", "Статья сохранена") redirect.addFlashAttribute("notice", "Статья сохранена")
redirectBack(back, "redirect:/admin/content") redirectBack(form.back, "redirect:/admin/content")
} catch (ex: ApiException) { } catch (ex: ApiException) {
redirect.addFlashAttribute("error", ex.message) redirect.addFlashAttribute("error", ex.message)
"redirect:/admin/content/articles/$id/edit" "redirect:/admin/content/articles/$id/edit"
@@ -195,17 +192,14 @@ class ContentAdminController(
@PostMapping("/sections/create") @PostMapping("/sections/create")
fun createSection( fun createSection(
@RequestParam chapterId: String, @ModelAttribute form: SectionCreateForm,
@RequestParam title: String,
@RequestParam(required = false) slug: String?,
@RequestParam(required = false) back: String?,
session: HttpSession, session: HttpSession,
redirect: RedirectAttributes, redirect: RedirectAttributes,
): String = ): String =
try { try {
api.createSection(token(session), chapterId, title.trim(), slug) api.createSection(token(session), form.chapterId, form.title.trim(), form.slug)
redirect.addFlashAttribute("notice", "Раздел «${title.trim()}» создан") redirect.addFlashAttribute("notice", "Раздел «${form.title.trim()}» создан")
redirectBack(back, "redirect:/admin/content") redirectBack(form.back, "redirect:/admin/content")
} catch (ex: ApiException) { } catch (ex: ApiException) {
redirect.addFlashAttribute("error", ex.message) redirect.addFlashAttribute("error", ex.message)
"redirect:/admin/content" "redirect:/admin/content"
@@ -252,28 +246,22 @@ class ContentAdminController(
@PostMapping("/articles/create") @PostMapping("/articles/create")
fun createArticle( fun createArticle(
@RequestParam(required = false) chapterId: String?, @ModelAttribute form: ArticleCreateForm,
@RequestParam(required = false) sectionId: String?,
@RequestParam(required = false) newChapterTitle: String?,
@RequestParam(required = false) newSectionTitle: String?,
@RequestParam title: String,
@RequestParam(required = false, defaultValue = "") bodyMd: String,
@RequestParam(required = false) back: String?,
session: HttpSession, session: HttpSession,
redirect: RedirectAttributes, redirect: RedirectAttributes,
): String = ): String =
try { try {
api.createArticle( api.createArticle(
token(session), token(session),
chapterId, form.chapterId,
sectionId, form.sectionId,
newChapterTitle?.takeIf { it.isNotBlank() }, form.newChapterTitle?.takeIf { it.isNotBlank() },
newSectionTitle?.takeIf { it.isNotBlank() }, form.newSectionTitle?.takeIf { it.isNotBlank() },
title.trim(), form.title.trim(),
bodyMd, form.bodyMd,
) )
redirect.addFlashAttribute("notice", "Статья «${title.trim()}» создана") redirect.addFlashAttribute("notice", "Статья «${form.title.trim()}» создана")
redirectBack(back, "redirect:/admin/content") redirectBack(form.back, "redirect:/admin/content")
} catch (ex: ApiException) { } catch (ex: ApiException) {
redirect.addFlashAttribute("error", ex.message) redirect.addFlashAttribute("error", ex.message)
"redirect:/admin/content" "redirect:/admin/content"

View File

@@ -0,0 +1,31 @@
package ru.ysu.lms.web.admin
/** Формы админки материалов: связываются через @ModelAttribute, имена полей = имена в шаблонах. */
data class TogglePublishedForm(
val id: String = "",
val published: Boolean = false,
val back: String? = null,
)
data class ArticleSaveForm(
val title: String = "",
val bodyMd: String = "",
val back: String? = null,
)
data class SectionCreateForm(
val chapterId: String = "",
val title: String = "",
val slug: String? = null,
val back: String? = null,
)
data class ArticleCreateForm(
val chapterId: String? = null,
val sectionId: String? = null,
val newChapterTitle: String? = null,
val newSectionTitle: String? = null,
val title: String = "",
val bodyMd: String = "",
val back: String? = null,
)