create new doucments, show tags

master
Josha von Gizycki 2 days ago
parent ae0a87b53d
commit 7bc290a3ad

@ -17,12 +17,7 @@ data class Document(
val createdAt: ZonedDateTime = ZonedDateTime.now(), val createdAt: ZonedDateTime = ZonedDateTime.now(),
val labelFields: Set<LabelField> = emptySet(), val labelFields: Set<LabelField> = emptySet(),
val dateFields: Set<DateField> = emptySet(), val dateFields: Set<DateField> = emptySet(),
) { )
@Transient
val tags: Set<Tag> = emptySet()
}
interface DocumentDao: Repository<Document, Int> { interface DocumentDao: Repository<Document, Int> {
fun findAll(): List<Document> fun findAll(): List<Document>

@ -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<Long> = emptyList(),
val newTags: String = ""
)

@ -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
}
}

@ -2,6 +2,7 @@ package wanijo.wanijo2.domain
import org.springframework.data.annotation.Id import org.springframework.data.annotation.Id
import org.springframework.data.jdbc.core.mapping.AggregateReference 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.relational.core.mapping.Table
import org.springframework.data.repository.Repository import org.springframework.data.repository.Repository
import java.time.ZonedDateTime import java.time.ZonedDateTime
@ -20,14 +21,34 @@ data class DocumentTagging(
val id: Long = 0, val id: Long = 0,
val tagId: AggregateReference<Tag, Long>, val tagId: AggregateReference<Tag, Long>,
val documentId: AggregateReference<Document, Long> val documentId: AggregateReference<Document, Long>
) ) {
companion object {
fun between(doc: Document, tagId: Long) =
DocumentTagging(
tagId = AggregateReference.to(tagId),
documentId = AggregateReference.to(doc.id)
)
}
}
interface DocumentTaggingDao : Repository<DocumentTagging, Long> { interface DocumentTaggingDao : Repository<DocumentTagging, Long> {
fun save(tagging: DocumentTagging) fun save(tagging: DocumentTagging)
} }
interface TagDao: Repository<Tag, Long> { interface TagDao : Repository<Tag, Long> {
fun save(tag: Tag): Tag fun save(tag: Tag): Tag
fun findByName(name: String): Tag? fun findByName(name: String): Tag?
fun findAll(): List<Tag> fun findAll(): Set<Tag>
@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<Tag>
} }

@ -9,12 +9,14 @@ import org.springframework.web.bind.annotation.GetMapping
import org.springframework.web.bind.annotation.PostMapping import org.springframework.web.bind.annotation.PostMapping
import org.springframework.web.bind.annotation.RequestMapping import org.springframework.web.bind.annotation.RequestMapping
import wanijo.wanijo2.domain.TagDao import wanijo.wanijo2.domain.TagDao
import wanijo.wanijo2.http.form.NewForm import wanijo.wanijo2.domain.event.NewDocumentCommand
import wanijo.wanijo2.domain.handler.NewDocumentCommandHandler
@Controller @Controller
@RequestMapping("/document") @RequestMapping("/document")
class NewController( class NewController(
private val tagDao: TagDao private val tagDao: TagDao,
private val newDocumentCommandHandler: NewDocumentCommandHandler,
) { ) {
@GetMapping("/new") @GetMapping("/new")
@ -22,22 +24,24 @@ class NewController(
model: Model model: Model
): String { ): String {
model["tags"] = tagDao.findAll() model["tags"] = tagDao.findAll()
model["form"] = NewForm() model["form"] = NewDocumentCommand()
return "new" return "new"
} }
@PostMapping("/new") @PostMapping("/new")
fun saveNewDocument( fun saveNewDocument(
model: Model,
@Valid @Valid
newForm: NewForm, newDocument: NewDocumentCommand,
model: Model,
bindingResult: BindingResult bindingResult: BindingResult
): String { ): String {
if (bindingResult.hasErrors()) { if (bindingResult.hasErrors()) {
return newDocument(model) return newDocument(model)
} }
return "redirect:/" val doc = newDocumentCommandHandler.exec(newDocument)
return "redirect:/document/${doc.id}"
} }
} }

@ -8,11 +8,13 @@ import org.springframework.ui.set
import org.springframework.web.bind.annotation.GetMapping import org.springframework.web.bind.annotation.GetMapping
import org.springframework.web.bind.annotation.PathVariable import org.springframework.web.bind.annotation.PathVariable
import wanijo.wanijo2.domain.DocumentDao import wanijo.wanijo2.domain.DocumentDao
import wanijo.wanijo2.domain.TagDao
import wanijo.wanijo2.http.DocumentNotFound import wanijo.wanijo2.http.DocumentNotFound
@Controller @Controller
class ShowController( class ShowController(
private val docDao: DocumentDao val docDao: DocumentDao,
val tagDao: TagDao
) { ) {
@GetMapping("/document/{id}") @GetMapping("/document/{id}")
@ -23,6 +25,8 @@ class ShowController(
val document = docDao.findById(id) ?: throw DocumentNotFound() val document = docDao.findById(id) ?: throw DocumentNotFound()
model["document"] = document model["document"] = document
model["tags"] = tagDao.ofDocument(id)
val descHtml = Parser.builder().build().parse(document.description).let { val descHtml = Parser.builder().build().parse(document.description).let {
HtmlRenderer.builder().build().render(it) HtmlRenderer.builder().build().render(it)
} }

@ -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<Long> = emptyList()
)

@ -29,8 +29,25 @@ main {
font-size: 90%; 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 { fieldset {
border: 1px solid AccentColor; border: 1px solid AccentColor;
margin-bottom: 1rem;
} }
} }
@ -56,13 +73,13 @@ form {
display: grid; display: grid;
grid-template-columns: 30% 70%; grid-template-columns: 30% 70%;
grid-auto-flow: row; grid-auto-flow: row;
row-gap: .5rem; row-gap: 1rem;
label { label {
grid-column: 1; grid-column: 1;
} }
input, textarea, select, button { input, textarea, select, button, .form__widget {
grid-column: 2; grid-column: 2;
} }

@ -15,10 +15,17 @@
<label for="description">beschreibung</label> <label for="description">beschreibung</label>
<textarea id="description" th:field="*{description}"></textarea> <textarea id="description" th:field="*{description}"></textarea>
<div class="form__widget" th:each="tag : ${tags}">
<label>
<input type="checkbox"
th:field="*{tagIds}"
th:value="${tag.id}">
<th:block th:text="${tag.name}"/>
</label>
</div>
<label for="tags">tags</label> <label for="tags">tags</label>
<select multiple th:field="*{tagIds}" id="tags"> <input id="tags" type="text" th:field="*{newTags}">
<option th:each="tag: ${tags}" th:value="${tag.id}" th:text="${tag.name}"></option>
</select>
<button type="submit"> <button type="submit">
anlegen anlegen

@ -31,6 +31,14 @@
</span> </span>
</fieldset> </fieldset>
<fieldset class="show__tags">
<legend>tags</legend>
<ul>
<li th:each="tag : ${tags}" th:text="${tag.name}"></li>
</ul>
</fieldset>
<fieldset> <fieldset>
<legend>beschreibung</legend> <legend>beschreibung</legend>
<div class="show__markdown" th:utext="${descHtml}"></div> <div class="show__markdown" th:utext="${descHtml}"></div>

Loading…
Cancel
Save