Skip to content

Commit

Permalink
save
Browse files Browse the repository at this point in the history
  • Loading branch information
tschuehly committed Aug 11, 2023
1 parent 00cd5dd commit d0b4fd6
Show file tree
Hide file tree
Showing 37 changed files with 246 additions and 124 deletions.
7 changes: 6 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -331,7 +331,12 @@ class ActionViewComponent(
exampleService.addItemToList(actionFormDTO.item)
return render()
}


@DeleteViewAction
fun deleteItem(id: Int): ViewContext {
exampleService.deleteItem(id)
return render()
}
@PutViewAction
fun savePersonPut(person: Person): ViewContext {
this.person = person
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,8 +33,6 @@ annotation class DeleteViewAction(

object ViewActionConstant {
val attributeName = "view:action"
val nestedViewComponentAttributeName = "data-nested-view-component"

}


Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import org.springframework.web.method.support.ModelAndViewContainer
import reactor.core.publisher.Mono

@Component
class ViewContextAsyncHandlerMethodReturnValueHandler() : AsyncHandlerMethodReturnValueHandler {
class ViewContextMonoHandler : AsyncHandlerMethodReturnValueHandler {
override fun supportsReturnType(returnType: MethodParameter): Boolean {
return Mono::class.java.isAssignableFrom(returnType.parameterType)
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
package de.tschuehly.spring.viewcomponent.core.processor

import de.tschuehly.spring.viewcomponent.core.action.*
import java.io.File
import java.nio.file.FileSystems
import java.nio.file.Path
import javax.annotation.processing.AbstractProcessor
import javax.annotation.processing.RoundEnvironment
import javax.annotation.processing.SupportedAnnotationTypes
Expand All @@ -11,6 +13,7 @@ import javax.lang.model.element.Element
import javax.lang.model.element.TypeElement
import javax.tools.Diagnostic
import kotlin.io.path.createDirectories
import kotlin.io.path.exists

@SupportedAnnotationTypes("de.tschuehly.spring.viewcomponent.core.component.ViewComponent")
@SupportedSourceVersion(SourceVersion.RELEASE_17)
Expand All @@ -26,15 +29,19 @@ class Processor : AbstractProcessor() {
val seperator = FileSystems.getDefault().separator
val rootDir = filePath.split("build")[0].split(seperator)
val directoryPath = "${element.enclosingElement}".replace(".", seperator)
val elementPath = "${element.simpleName}".replace(".", seperator)
val srcDirPath = FileSystems.getDefault()
.getPath("", *rootDir.toTypedArray(), "src", "main", "kotlin", directoryPath)
val srcHtmlFile = srcDirPath.resolve("$elementPath.html").toFile()
.getPath("", *rootDir.toTypedArray(), "src", "main", "kotlin", directoryPath)


val (srcHtmlFile, fileName) = srcDirPath.resolveFileOrNull(element.simpleName.toString()) ?: let {
val msg = "No Template File found for ${srcDirPath.toAbsolutePath()}$seperator${element.simpleName}"
processingEnv.messager.printMessage(Diagnostic.Kind.ERROR, msg)
throw Exception(msg)
}
val resourceDir = FileSystems.getDefault()
.getPath("", *rootDir.toTypedArray(), "build", "resources", "main", directoryPath)
.getPath("", *rootDir.toTypedArray(), "build", "resources", "main", directoryPath)
resourceDir.createDirectories()
val resourceHtmlFile = resourceDir.resolve("$elementPath.html").toFile()

val resourceHtmlFile = resourceDir.resolve(fileName).toFile()
if (resourceHtmlFile.exists()) {
resourceHtmlFile.delete()
}
Expand All @@ -43,23 +50,9 @@ class Processor : AbstractProcessor() {

val viewComponentName = element.simpleName.toString().lowercase()
srcHtmlFile.forEachLine { htmlLine ->

if (htmlLine.contains("view:action")) {
val beforeViewAction = htmlLine.split("view:action=\"")[0]
val viewActionAttrVal = htmlLine.split("view:action=\"")[1].split("\"")[0]
val afterViewActionAttrVal = htmlLine.split("view:action=\"")[1].split("\"")[1]
val methodName = if (viewActionAttrVal.startsWith("|") &&
viewActionAttrVal.contains("?")) {
viewActionAttrVal.substring(1,viewActionAttrVal.indexOf("?")).lowercase()
} else {
viewActionAttrVal.lowercase()
}
val method = element.enclosedElements.find { it.simpleName.toString().lowercase() == methodName }
?: throw RuntimeException("viewAction method $methodName does not exist")

val (htmxAttr, path) = getHtmxAttribute(element, method, methodName)
val htmxAttrVal = viewActionAttrVal.replace(methodName,path,true)
val newLine = "$beforeViewAction$htmxAttr\"$htmxAttrVal\" hx-target=\"#$viewComponentName\"$afterViewActionAttrVal"
val newLine =
createViewAction(htmlLine, element, viewComponentName)

resourceFileWriter.write(newLine)
resourceFileWriter.println()
Expand All @@ -83,6 +76,42 @@ class Processor : AbstractProcessor() {
return true
}

private fun Path.resolveFileOrNull(fileName: String): Pair<File, String>? {
val fileEndings = arrayOf(".html", ".jte")
fileEndings.forEach { fileEnding ->
if (this.resolve("$fileName$fileEnding").exists()) {
return this.resolve("$fileName$fileEnding").toFile() to "$fileName$fileEnding"
}
}
return null
}

private fun createViewAction(
htmlLine: String,
element: Element,
viewComponentName: String
): String {
val beforeViewAction = htmlLine.split("view:action=\"")[0]
val viewActionAttrVal = htmlLine.split("view:action=\"")[1].split("\"")[0]
val afterViewActionAttrVal = htmlLine.split("view:action=\"")[1].split("\"")[1]
val methodName = if (viewActionAttrVal.startsWith("|") &&
viewActionAttrVal.contains("?")
) {
viewActionAttrVal.substring(1, viewActionAttrVal.indexOf("?")).lowercase()
} else {
viewActionAttrVal.lowercase()
}
val method =
element.enclosedElements.find { it.simpleName.toString().lowercase() == methodName }
?: throw RuntimeException("viewAction method $methodName does not exist")

val (htmxAttr, path) = getHtmxAttribute(element, method, methodName)
val htmxAttrVal = viewActionAttrVal.replace(methodName, path, true)
val newLine =
"$beforeViewAction$htmxAttr\"$htmxAttrVal\" hx-target=\"#$viewComponentName\"$afterViewActionAttrVal"
return newLine
}

private fun getHtmxAttribute(element: Element, method: Element, methodName: String): Pair<String, String> {
method.getAnnotation(GetViewAction::class.java)?.let {
val action = if (it.path == "") "/${element.simpleName}/$methodName" else it.path
Expand Down
12 changes: 0 additions & 12 deletions examples/jte-demo/settings.gradle.kts

This file was deleted.

This file was deleted.

This file was deleted.

This file was deleted.

This file was deleted.

This file was deleted.

File renamed without changes.
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,10 @@ import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
plugins {
id("org.springframework.boot") version "3.0.6"
id("io.spring.dependency-management") version "1.1.2"
kotlin("jvm") version "1.7.22"
kotlin("plugin.spring") version "1.7.22"
kotlin("jvm") version "1.8.21"
kotlin("plugin.spring") version "1.8.21"

kotlin("kapt") version "1.8.21"
}

group = "de.tschuehly"
Expand All @@ -18,8 +20,8 @@ repositories {

dependencies {
implementation("de.tschuehly:spring-view-component-jte:0.6.1-SNAPSHOT")
// implementation("de.tschuehly:spring-view-component-jte")

kapt("de.tschuehly:spring-view-component-core:0.6.1-SNAPSHOT")
implementation("org.springframework.boot:spring-boot-starter")
implementation("org.springframework.boot:spring-boot-starter-web")
implementation("org.springframework.boot:spring-boot-starter-actuator")
Expand Down
File renamed without changes.
File renamed without changes.
12 changes: 12 additions & 0 deletions examples/jte-example/settings.gradle.kts
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
rootProject.name = "jte-example"

includeBuild("..\\..\\jte"){
dependencySubstitution {
substitute(module("de.tschuehly:spring-view-component-jte")).using(project(":"))
}
}
includeBuild("..\\..\\core"){
dependencySubstitution {
substitute(module("de.tschuehly:spring-view-component-core")).using(project(":"))
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
package de.tschuehly.jteviewcomponentdemo.core

import org.springframework.stereotype.Service
import java.util.NoSuchElementException

@Service
class ExampleService {
var dataIndex = 0
val itemList = mutableMapOf<Int, String>()

fun getHelloWorld(): String {
return "Hello World"
}

fun addItemToList(item: String){
itemList[dataIndex] = item
dataIndex += 1
}

fun deleteItem(id: Int) {
itemList.remove(id) ?: throw NoSuchElementException("No Element with Id: $id found")
}


}
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
@import de.tschuehly.jteviewcomponentdemo.web.action.ActionViewComponent.Person
@param Integer counter
@param java.util.Map<int,String> itemList
@param Person person

<html>
<body>
<h2>ViewAction Get CountUp</h2>

<button view:action="countUp">Default ViewAction [GET]</button>
<h3 th:text="${counter}"></h3>

<h2>ViewAction Post AddItem</h2>
<form view:action="addItem">
<input type="text" name="item">
<button type="submit">Save Item</button>
</form>
<table>
<tr>
<th>Item</th>
<th>Action</th>
</tr>
<tr th:each="item : ${itemList}">
<td>
<span th:text="${item.value}"></span>
</td>
<td>
<button th:view:action="|deleteItem?id=${item.key}|">Delete Item [[${item.key}]]</button>
</td>
</tr>
</table>

<h2>ViewAction Put/Patch Person Form</h2>

<form th:object="${person}" style="display: inline-grid; gap: 0.5rem">
<label>
Name <input type="text" th:field="*{name}">
</label>
<label>
Age: <input type="number" th:field="*{age}">
</label>
<label>
Location: <input type="text" th:field="*{location}">
</label>
<button type="submit" view:action="savePersonPut">Save Changes using Put</button>
<button type="submit" view:action="savePersonPatch">Save Changes using Patch</button>
</form>
</body>

</html>
Loading

0 comments on commit d0b4fd6

Please sign in to comment.