diff --git a/src/main/kotlin/wanijo/wanijo2/domain/document.kt b/src/main/kotlin/wanijo/wanijo2/domain/document.kt index bf5d251..aa4ea4b 100644 --- a/src/main/kotlin/wanijo/wanijo2/domain/document.kt +++ b/src/main/kotlin/wanijo/wanijo2/domain/document.kt @@ -17,12 +17,7 @@ data class Document( val createdAt: ZonedDateTime = ZonedDateTime.now(), val labelFields: Set = emptySet(), val dateFields: Set = emptySet(), -) { - - @Transient - val tags: Set = emptySet() - -} +) interface DocumentDao: Repository { fun findAll(): List diff --git a/src/main/kotlin/wanijo/wanijo2/domain/event/NewDocumentCommand.kt b/src/main/kotlin/wanijo/wanijo2/domain/event/NewDocumentCommand.kt new file mode 100644 index 0000000..92bccd0 --- /dev/null +++ b/src/main/kotlin/wanijo/wanijo2/domain/event/NewDocumentCommand.kt @@ -0,0 +1,11 @@ +package wanijo.wanijo2.domain.event + +import jakarta.validation.constraints.NotEmpty + +data class NewDocumentCommand( + @NotEmpty + val name: String = "", + val description: String = "", + val tagIds: List = emptyList(), + val newTags: String = "" +) diff --git a/src/main/kotlin/wanijo/wanijo2/domain/handler/NewDocumentCommandHandler.kt b/src/main/kotlin/wanijo/wanijo2/domain/handler/NewDocumentCommandHandler.kt new file mode 100644 index 0000000..a661adf --- /dev/null +++ b/src/main/kotlin/wanijo/wanijo2/domain/handler/NewDocumentCommandHandler.kt @@ -0,0 +1,49 @@ +package wanijo.wanijo2.domain.handler + +import org.springframework.stereotype.Service +import wanijo.wanijo2.domain.Document +import wanijo.wanijo2.domain.DocumentDao +import wanijo.wanijo2.domain.DocumentTagging +import wanijo.wanijo2.domain.DocumentTaggingDao +import wanijo.wanijo2.domain.Tag +import wanijo.wanijo2.domain.TagDao +import wanijo.wanijo2.domain.event.NewDocumentCommand + +@Service +class NewDocumentCommandHandler( + val tagDao: TagDao, + val documentDao: DocumentDao, + val documentTaggingDao: DocumentTaggingDao +) { + + fun exec(event: NewDocumentCommand): Document { + val document = documentDao.save( + Document( + name = event.name, + description = event.description + ) + ) + + val tags = event.newTags + .split(",") + .map { it.trim() } + .map { it to tagDao.findByName(it) } + .map { (name, tag) -> + if (tag == null) { + tagDao.save(Tag(name = name)) + } else { + tag + } + } + + val tagIdsToAttach = tags.map { it.id } + event.tagIds + tagIdsToAttach.forEach { + documentTaggingDao.save( + DocumentTagging.between(document, it) + ) + } + + return document + } + +} diff --git a/src/main/kotlin/wanijo/wanijo2/domain/tag.kt b/src/main/kotlin/wanijo/wanijo2/domain/tag.kt index 6b5cc8d..cc0cfdf 100644 --- a/src/main/kotlin/wanijo/wanijo2/domain/tag.kt +++ b/src/main/kotlin/wanijo/wanijo2/domain/tag.kt @@ -2,6 +2,7 @@ package wanijo.wanijo2.domain import org.springframework.data.annotation.Id import org.springframework.data.jdbc.core.mapping.AggregateReference +import org.springframework.data.jdbc.repository.query.Query import org.springframework.data.relational.core.mapping.Table import org.springframework.data.repository.Repository import java.time.ZonedDateTime @@ -20,14 +21,34 @@ data class DocumentTagging( val id: Long = 0, val tagId: AggregateReference, val documentId: AggregateReference -) +) { + companion object { + fun between(doc: Document, tagId: Long) = + DocumentTagging( + tagId = AggregateReference.to(tagId), + documentId = AggregateReference.to(doc.id) + ) + } +} interface DocumentTaggingDao : Repository { fun save(tagging: DocumentTagging) } -interface TagDao: Repository { +interface TagDao : Repository { fun save(tag: Tag): Tag fun findByName(name: String): Tag? - fun findAll(): List + fun findAll(): Set + @Query( + """ + SELECT tag.* + FROM t_tag tag + JOIN t_document_tagging tdt + ON tag.id = tdt.tag_id + JOIN t_document td + ON tdt.document_id = td.id + WHERE td.id = :documentId + """ + ) + fun ofDocument(documentId: Long): Set } diff --git a/src/main/kotlin/wanijo/wanijo2/http/controller/NewController.kt b/src/main/kotlin/wanijo/wanijo2/http/controller/NewController.kt index dcf561c..28e4a3d 100644 --- a/src/main/kotlin/wanijo/wanijo2/http/controller/NewController.kt +++ b/src/main/kotlin/wanijo/wanijo2/http/controller/NewController.kt @@ -9,12 +9,14 @@ import org.springframework.web.bind.annotation.GetMapping import org.springframework.web.bind.annotation.PostMapping import org.springframework.web.bind.annotation.RequestMapping import wanijo.wanijo2.domain.TagDao -import wanijo.wanijo2.http.form.NewForm +import wanijo.wanijo2.domain.event.NewDocumentCommand +import wanijo.wanijo2.domain.handler.NewDocumentCommandHandler @Controller @RequestMapping("/document") class NewController( - private val tagDao: TagDao + private val tagDao: TagDao, + private val newDocumentCommandHandler: NewDocumentCommandHandler, ) { @GetMapping("/new") @@ -22,22 +24,24 @@ class NewController( model: Model ): String { model["tags"] = tagDao.findAll() - model["form"] = NewForm() + model["form"] = NewDocumentCommand() return "new" } @PostMapping("/new") fun saveNewDocument( - model: Model, @Valid - newForm: NewForm, + newDocument: NewDocumentCommand, + model: Model, bindingResult: BindingResult ): String { if (bindingResult.hasErrors()) { return newDocument(model) } - return "redirect:/" + val doc = newDocumentCommandHandler.exec(newDocument) + + return "redirect:/document/${doc.id}" } } diff --git a/src/main/kotlin/wanijo/wanijo2/http/controller/ShowController.kt b/src/main/kotlin/wanijo/wanijo2/http/controller/ShowController.kt index 6df5c92..b384188 100644 --- a/src/main/kotlin/wanijo/wanijo2/http/controller/ShowController.kt +++ b/src/main/kotlin/wanijo/wanijo2/http/controller/ShowController.kt @@ -8,11 +8,13 @@ import org.springframework.ui.set import org.springframework.web.bind.annotation.GetMapping import org.springframework.web.bind.annotation.PathVariable import wanijo.wanijo2.domain.DocumentDao +import wanijo.wanijo2.domain.TagDao import wanijo.wanijo2.http.DocumentNotFound @Controller class ShowController( - private val docDao: DocumentDao + val docDao: DocumentDao, + val tagDao: TagDao ) { @GetMapping("/document/{id}") @@ -23,6 +25,8 @@ class ShowController( val document = docDao.findById(id) ?: throw DocumentNotFound() model["document"] = document + model["tags"] = tagDao.ofDocument(id) + val descHtml = Parser.builder().build().parse(document.description).let { HtmlRenderer.builder().build().render(it) } diff --git a/src/main/kotlin/wanijo/wanijo2/http/form/NewForm.kt b/src/main/kotlin/wanijo/wanijo2/http/form/NewForm.kt deleted file mode 100644 index ee4b22d..0000000 --- a/src/main/kotlin/wanijo/wanijo2/http/form/NewForm.kt +++ /dev/null @@ -1,10 +0,0 @@ -package wanijo.wanijo2.http.form - -import jakarta.validation.constraints.NotEmpty - -data class NewForm ( - @NotEmpty - val name: String = "", - val description: String = "", - val tagIds: List = emptyList() -) diff --git a/src/main/resources/static/stylesheet.css b/src/main/resources/static/stylesheet.css index abb4bb7..7c1b84d 100644 --- a/src/main/resources/static/stylesheet.css +++ b/src/main/resources/static/stylesheet.css @@ -29,8 +29,25 @@ main { font-size: 90%; } + .show__tags { + ul { + list-style-type: none; + margin: 0; + padding: 0; + + display: flex; + justify-content: space-evenly; + + li { + border-left: .5rem solid AccentColor; + padding-left: .5rem; + } + } + } + fieldset { border: 1px solid AccentColor; + margin-bottom: 1rem; } } @@ -56,13 +73,13 @@ form { display: grid; grid-template-columns: 30% 70%; grid-auto-flow: row; - row-gap: .5rem; + row-gap: 1rem; label { grid-column: 1; } - input, textarea, select, button { + input, textarea, select, button, .form__widget { grid-column: 2; } diff --git a/src/main/resources/templates/new.html b/src/main/resources/templates/new.html index 0eabeb2..36f87e4 100644 --- a/src/main/resources/templates/new.html +++ b/src/main/resources/templates/new.html @@ -15,10 +15,17 @@ +
+ +
+ - +