This commit is contained in:
lunaticbum 2024-10-23 10:07:45 +09:00
parent c4001848fc
commit 69d2df4ac4
19 changed files with 513 additions and 81 deletions

View File

@ -1,8 +1,13 @@
import com.github.jk1.license.render.*
import com.github.jk1.license.filter.ExcludeTransitiveDependenciesFilter
import com.github.jk1.license.filter.LicenseBundleNormalizer
plugins { plugins {
kotlin("jvm") version "1.9.25" kotlin("jvm") version "1.9.25"
kotlin("plugin.spring") version "1.9.25" kotlin("plugin.spring") version "1.9.25"
id("org.springframework.boot") version "3.3.4" id("org.springframework.boot") version "3.3.4"
id("io.spring.dependency-management") version "1.1.6" id("io.spring.dependency-management") version "1.1.6"
id("com.github.jk1.dependency-license-report") version "2.0"
} }
group = "kr.lunaticbum.back" group = "kr.lunaticbum.back"
@ -101,3 +106,19 @@ tasks.jar {
} }
licenseReport {
// 라이센스 고지 파일을 반환할 경로 default는 $projectDir/reports/dependency-license
outputDir = "$projectDir/build/licenses"
// markdown 생성
// renderers = listOf(InventoryMarkdownReportRenderer()).toTypedArray()
// html 생성
renderers = listOf(InventoryHtmlReportRenderer()).toTypedArray()
// xml 생성
// renderers = [new XmlReportRenderer()]
// 보고서에 첫 번째 수준 종속성만 표기
filters = listOf(LicenseBundleNormalizer(), ExcludeTransitiveDependenciesFilter()).toTypedArray()
}

View File

@ -6,9 +6,10 @@ import com.google.gson.Gson
import jakarta.servlet.http.HttpServletRequest import jakarta.servlet.http.HttpServletRequest
import jakarta.servlet.http.HttpServletResponse import jakarta.servlet.http.HttpServletResponse
import kr.lunaticbum.back.lun.configs.GlobalEnvironment import kr.lunaticbum.back.lun.configs.GlobalEnvironment
import kr.lunaticbum.back.lun.model.CurrentWeather import kr.lunaticbum.back.lun.controllers.UserController.Companion.ApiKeyWordKey
import kr.lunaticbum.back.lun.model.FileSaveResult import kr.lunaticbum.back.lun.controllers.UserController.Companion.EncType11
import kr.lunaticbum.back.lun.model.LocationLogService import kr.lunaticbum.back.lun.controllers.UserController.Companion.EncTypeKey
import kr.lunaticbum.back.lun.model.*
import kr.lunaticbum.back.lun.utils.LogService import kr.lunaticbum.back.lun.utils.LogService
import kr.lunaticbum.back.lun.utils.getFileExtension import kr.lunaticbum.back.lun.utils.getFileExtension
import org.springframework.beans.factory.annotation.Autowired import org.springframework.beans.factory.annotation.Autowired
@ -17,6 +18,7 @@ import org.springframework.core.io.Resource
import org.springframework.core.io.UrlResource import org.springframework.core.io.UrlResource
import org.springframework.http.MediaType import org.springframework.http.MediaType
import org.springframework.http.ResponseEntity import org.springframework.http.ResponseEntity
import org.springframework.security.core.userdetails.UserDetails
import org.springframework.web.bind.annotation.* import org.springframework.web.bind.annotation.*
import org.springframework.web.multipart.MultipartFile import org.springframework.web.multipart.MultipartFile
import org.springframework.web.reactive.function.client.WebClient import org.springframework.web.reactive.function.client.WebClient
@ -36,11 +38,22 @@ class BlogController() {
private lateinit var locationLogService: LocationLogService private lateinit var locationLogService: LocationLogService
@Autowired @Autowired
lateinit var logService: LogService private lateinit var postManageg: PostManageg
@GetMapping("write") @Autowired
fun writ() : ModelAndView{ lateinit var logService: LogService
val WRITE_PERMISSION_KEY = "PERMISSION"
@GetMapping("write/{token}","write")
fun writ(@PathVariable token : String? ) : ModelAndView{
val vm = ModelAndView("content/blog/write") val vm = ModelAndView("content/blog/write")
if (token.equals("TEMP_TOKEN_VIBUM")) {
vm.modelMap.put(WRITE_PERMISSION_KEY,"OK")
vm.modelMap.put(EncTypeKey, EncType11)
vm.modelMap.put(ApiKeyWordKey,"WRITE")
vm.modelMap.put("title","회원이 들어는 구나~!!")
} else {
vm.modelMap.put(WRITE_PERMISSION_KEY,"NO")
}
// when(System.currentTimeMillis() % 5L) { // when(System.currentTimeMillis() % 5L) {
// 0L -> vm.modelMap.put(EncTypeKey,"T4") // 0L -> vm.modelMap.put(EncTypeKey,"T4")
// 1L -> vm.modelMap.put(EncTypeKey,"T3") // 1L -> vm.modelMap.put(EncTypeKey,"T3")
@ -51,6 +64,53 @@ class BlogController() {
return vm return vm
} }
@PostMapping("post.ajax")
fun post(httpServletRequest: HttpServletRequest, @RequestBody jsonString: String) : ResponseEntity<ResponceResult> {
logService.log("${httpServletRequest.requestURI}")
logService.log(jsonString)
var lResultCode = 0
var lResultMsg = "Suscces"
var u : UserDetails? = null
val decodedBytes: ByteArray = Base64.getDecoder().decode(jsonString)
String(decodedBytes).let {
Gson().fromJson<RequestModel>(it, RequestModel::class.java)?.let { model ->
logService.log(Gson().toJson(model))
model.data?.let { jsonString ->
try {
val reqString = jsonString.split(globalEvv.padding(model.getKeyword()))
val nb = arrayListOf<String>()
val na = arrayListOf<String>()
reqString[0].replace(globalEvv.padding(model.getKeyword()),"").split("").toList().let { na.addAll(it) }
reqString[1].replace(globalEvv.padding(model.getKeyword()),"").split("").toList().let { nb.addAll(it) }
var max = nb.size + na.size
var fullData = arrayListOf<String>()
for (idx in 0..max) { if (idx % 2 == 0) { if (nb.size > 0) { fullData.add(nb.removeLast()) } } else { if (na.size > 0) { fullData.add(na.removeLast()) } } }
logService.log(fullData.joinToString(""))
val target = Gson().fromJson(fullData.joinToString(""), Post::class.java) ?: Post()
var user = postManageg.save(target)
if (user != null) {
lResultMsg = "save post"
lResultCode = 0
} else {
lResultMsg = "not founding user[can't find same id,email.. ]"
lResultCode = 7100
}
} catch (e: Exception) {
e.printStackTrace()
lResultMsg = "unknown exception"
lResultCode = 7999
}
}
}
}
val responce = ResponseEntity.ok().headers {
}.contentType(MediaType.APPLICATION_JSON).body(ResponceResult().apply {
this.resultCode = lResultCode
this.resultMsg = lResultMsg
})
return responce
}
@GetMapping("viewer/{blogId}") @GetMapping("viewer/{blogId}")
fun viewer(@PathVariable blogId : String) : ModelAndView{ fun viewer(@PathVariable blogId : String) : ModelAndView{
val vm = ModelAndView("content/blog/viewer") val vm = ModelAndView("content/blog/viewer")
@ -67,7 +127,7 @@ class BlogController() {
@GetMapping("recent") @GetMapping("recent")
fun recent() : ModelAndView{ fun recent() : ModelAndView{
val vm = ModelAndView("content/blog/viewer") val vm = ModelAndView("content/blog/viewer")
locationLogService.find50().forEach { locationLogService.find20().forEach {
logService.log(Gson().toJson(it)) logService.log(Gson().toJson(it))
} }
locationLogService.getLocationLog()?.let { locationLogService.getLocationLog()?.let {

View File

@ -11,9 +11,9 @@ import kr.lunaticbum.back.lun.utils.LogService
import org.springframework.beans.factory.annotation.Autowired import org.springframework.beans.factory.annotation.Autowired
import org.springframework.http.MediaType import org.springframework.http.MediaType
import org.springframework.http.ResponseEntity import org.springframework.http.ResponseEntity
import org.springframework.security.core.userdetails.UserDetails
import org.springframework.web.bind.annotation.* import org.springframework.web.bind.annotation.*
import org.springframework.web.reactive.function.client.WebClient import org.springframework.web.reactive.function.client.WebClient
import org.springframework.web.servlet.ModelAndView
import java.util.* import java.util.*
@ -29,6 +29,19 @@ class BumsPrivate {
@Autowired @Autowired
lateinit var locationService: LocationLogService lateinit var locationService: LocationLogService
@GetMapping("where")
fun where() : ModelAndView {
val m = ModelAndView("content/private/where")
locationService.find20().apply {
m.modelMap.put("locations",this.reversed())
forEach {
logService.log(it.timeString.plus(it.mAddressLines.joinToString(",")))
}
}
m.modelMap.put("title","돼지 여기있다요~!!")
return m
}
@ResponseBody @ResponseBody
@PostMapping("save/loc.api") @PostMapping("save/loc.api")
fun login(httpServletRequest: HttpServletRequest, @RequestBody jsonString: String) : ResponseEntity<ResponceResult> { fun login(httpServletRequest: HttpServletRequest, @RequestBody jsonString: String) : ResponseEntity<ResponceResult> {

View File

@ -1,5 +1,9 @@
package kr.lunaticbum.back.lun.controllers package kr.lunaticbum.back.lun.controllers
import com.google.gson.Gson
import kr.lunaticbum.back.lun.model.PostManageg
import kr.lunaticbum.back.lun.utils.LogService
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.web.bind.annotation.GetMapping import org.springframework.web.bind.annotation.GetMapping
import org.springframework.web.bind.annotation.RequestMapping import org.springframework.web.bind.annotation.RequestMapping
import org.springframework.web.bind.annotation.RestController import org.springframework.web.bind.annotation.RestController
@ -9,9 +13,28 @@ import org.springframework.web.servlet.ModelAndView
@RequestMapping() @RequestMapping()
class Home { class Home {
@Autowired
lateinit var logService: LogService
@Autowired
private lateinit var postManageg: PostManageg
@GetMapping("/","/home") @GetMapping("/","/home")
fun home() : ModelAndView { fun home() : ModelAndView {
val vm = ModelAndView("content/blog/write") val vm = ModelAndView("content/home")
vm.modelMap.put("posts", postManageg.find20().apply {
this.forEach {
logService.log(Gson().toJson(it))
}
})
return vm return vm
} }
@GetMapping("/licenses")
fun licenses() : ModelAndView {
val vm = ModelAndView("content/licenses")
return vm
}
} }

View File

@ -18,8 +18,11 @@ import org.springframework.scheduling.annotation.Scheduled
import org.springframework.web.bind.annotation.* import org.springframework.web.bind.annotation.*
import org.springframework.web.reactive.function.client.WebClient import org.springframework.web.reactive.function.client.WebClient
import java.math.BigDecimal import java.math.BigDecimal
import java.math.RoundingMode
import java.text.SimpleDateFormat import java.text.SimpleDateFormat
import java.time.Duration
import java.util.* import java.util.*
import java.util.concurrent.TimeUnit
@RestController @RestController
@ -131,19 +134,21 @@ class Telegram {
) { ) {
locationLogService.getLocationLog()?.let { locationLogService.getLocationLog()?.let {
try { try {
val client0 = WebClient.create() WebClient.create().get()
val result = client0.get()
.uri("http://api.weatherapi.com/v1/current.json?key=${globalEvv.weatherApiKey}&q=${it.mLatitude},${it.mLongitude}&aqi=no") .uri("http://api.weatherapi.com/v1/current.json?key=${globalEvv.weatherApiKey}&q=${it.mLatitude},${it.mLongitude}&aqi=no")
.retrieve() .retrieve()
.bodyToMono(String::class.java) .bodyToMono(String::class.java)
.block() ?: "FAIL" .timeout(Duration.ofSeconds(30L))
Gson().fromJson(result, CurrentWeather::class.java)?.let { sss -> .block()?.let { result ->
val client = WebClient.create() Gson().fromJson(result, CurrentWeather::class.java)?.let { sss ->
client.get() val fullUrl = "https://api.telegram.org/${globalEvv.telegramBotKey}/sendMessage?chat_id=${globalEvv.telegramMyId}&text=${sss.getSummaryInfo(BigDecimal(it.mLatitude).setScale(3, RoundingMode.HALF_UP).toString(),BigDecimal(it.mLongitude).setScale(3, RoundingMode.HALF_UP).toString())}"
.uri("https://api.telegram.org/${globalEvv.telegramBotKey}/sendMessage?chat_id=${globalEvv.telegramMyId}&text=${sss.getSummaryInfo(BigDecimal(it.mLatitude).setScale(5).toString(),BigDecimal(it.mLongitude).setScale(5).toString())}") logService.log("fullUrl >>> ${fullUrl}")
.retrieve() WebClient.create().get()
.bodyToMono(String::class.java).block() ?: "FAIL" .uri(fullUrl)
} .retrieve()
.bodyToMono(String::class.java).block() ?: "FAIL"
}
}
} }
catch (e : Exception) { catch (e : Exception) {

View File

@ -23,12 +23,15 @@ import kotlin.math.log
@RestController @RestController
@RequestMapping("/user") @RequestMapping("/user")
class UserController { class UserController {
val EncTypeKey = "enc" companion object{
val EncType00 = "T0" val EncTypeKey = "enc"
val EncType11 = "T3" val EncType00 = "T0"
val EncType10 = "T2" val EncType11 = "T3"
val EncType01 = "T1" val EncType10 = "T2"
val ApiKeyWordKey = "keyword" val EncType01 = "T1"
val ApiKeyWordKey = "keyword"
}
@Autowired @Autowired
lateinit var globalEvv : GlobalEnvironment lateinit var globalEvv : GlobalEnvironment

View File

@ -1,10 +1,6 @@
package kr.lunaticbum.back.lun.model package kr.lunaticbum.back.lun.model
import com.google.gson.Gson import com.google.gson.Gson
import com.mongodb.client.model.Sorts.descending
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import kr.lunaticbum.back.lun.configs.GlobalEnvironment import kr.lunaticbum.back.lun.configs.GlobalEnvironment
import kr.lunaticbum.back.lun.utils.LogService import kr.lunaticbum.back.lun.utils.LogService
import lombok.AllArgsConstructor import lombok.AllArgsConstructor
@ -14,13 +10,11 @@ import org.bson.codecs.pojo.annotations.BsonIgnore
import org.jsoup.Jsoup import org.jsoup.Jsoup
import org.springframework.beans.factory.annotation.Autowired import org.springframework.beans.factory.annotation.Autowired
import org.springframework.data.annotation.Id import org.springframework.data.annotation.Id
import org.springframework.data.domain.Page
import org.springframework.data.mongodb.core.mapping.Document import org.springframework.data.mongodb.core.mapping.Document
import org.springframework.data.mongodb.repository.ReactiveMongoRepository import org.springframework.data.mongodb.repository.ReactiveMongoRepository
import org.springframework.stereotype.Repository import org.springframework.stereotype.Repository
import org.springframework.stereotype.Service import org.springframework.stereotype.Service
import org.springframework.web.reactive.function.client.WebClient import org.springframework.web.reactive.function.client.WebClient
import reactor.core.publisher.Flux
import reactor.core.publisher.Mono import reactor.core.publisher.Mono
import java.text.SimpleDateFormat import java.text.SimpleDateFormat
import java.time.Duration import java.time.Duration
@ -97,8 +91,8 @@ class LocationLogService : LocationService {
@Autowired @Autowired
private lateinit var logRepository: LocationLogRepository private lateinit var logRepository: LocationLogRepository
fun find50() : List<LocationLog> { fun find20() : List<LocationLog> {
return logRepository.findAll().takeLast(50).buffer(50).blockLast(Duration.ofSeconds(30)) ?: listOf() return logRepository.findAll().takeLast(20).buffer(20).blockLast(Duration.ofSeconds(30)) ?: listOf()
} }
fun getLocationLog() : LocationLog? { fun getLocationLog() : LocationLog? {
return logRepository.findFirstByOrderByTimeDesc().block() return logRepository.findFirstByOrderByTimeDesc().block()
@ -110,7 +104,6 @@ class LocationLogService : LocationService {
logRepository.save(log).subscribe( { println("saved msg after ${it}") },{e -> e.printStackTrace()},{ logRepository.save(log).subscribe( { println("saved msg after ${it}") },{e -> e.printStackTrace()},{
println("saved msg comp") println("saved msg comp")
}) })
} }
} }

View File

@ -0,0 +1,75 @@
package kr.lunaticbum.back.lun.model
import kr.lunaticbum.back.lun.utils.LogService
import lombok.AllArgsConstructor
import lombok.Data
import lombok.NoArgsConstructor
import org.bson.BsonType
import org.bson.codecs.pojo.annotations.BsonCreator
import org.bson.codecs.pojo.annotations.BsonId
import org.bson.codecs.pojo.annotations.BsonRepresentation
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.data.mongodb.core.mapping.Document
import org.springframework.data.mongodb.repository.Query
import org.springframework.data.mongodb.repository.ReactiveMongoRepository
import org.springframework.security.core.userdetails.UserDetails
import org.springframework.security.core.userdetails.UserDetailsService
import org.springframework.security.crypto.password.PasswordEncoder
import org.springframework.stereotype.Repository
import org.springframework.stereotype.Service
import reactor.core.publisher.Mono
import java.time.Duration
@Data
@NoArgsConstructor
@AllArgsConstructor
@Document(collection = "Post")
class Post {
@BsonId
@BsonRepresentation(BsonType.OBJECT_ID)
var id: String? = null
var title : String? = null
var content : String? = null
var category : String? = null
var tags : String? = null
var writer : String? = null
var writeTime : Long = 0
var modifyTime : Long = 0
var posting : Boolean = false
}
@Repository
interface PostRepository : ReactiveMongoRepository<Post, String> {
}
@Service
class PostManageg {
@Autowired
private lateinit var logService: LogService
@Autowired
private lateinit var postRepository: PostRepository
@Autowired
private lateinit var bCryptPasswordEncoder: PasswordEncoder
fun find20() : List<Post> {
return postRepository.findAll().takeLast(20).buffer(20).blockLast(Duration.ofSeconds(30)) ?: listOf()
}
fun save(post: Post): Mono<Post> {
println("saved user before ${post}")
// user.hashPassword(bCryptPasswordEncoder)
return postRepository.save(post).apply {
subscribe {
println("saved user after ${this@apply}")
}
}
}
}

View File

@ -10,7 +10,16 @@ html {
margin: 1vh 1vw; margin: 1vh 1vw;
background: #202025ee; background: #202025ee;
} }
#where{
table-layout: fixed;
}
.where_item {
display: table-cell;
}
body { body {
user-select: none;
-webkit-user-select: none;
align-content: center; align-content: center;
padding: 1vh 1vw; padding: 1vh 1vw;
background-image: url("data:image/svg+xml,<svg id='patternId' width='100%' height='100%' xmlns='http://www.w3.org/2000/svg'><defs><pattern id='a' patternUnits='userSpaceOnUse' width='45' height='51.96' patternTransform='scale(2) rotate(20)'><rect x='0' y='0' width='100%' height='100%' fill='%23202025ff'/><path d='M52.48 44.47a15 15 0 01-14.96 0 15 15 0 00-7.48 12.96M7.48 44.42a15 15 0 01-14.96 0M15 57.44c0-5.35-2.9-10.35-7.52-13.02a15 15 0 017.48-12.97M7.48 18.5a14.97 14.97 0 01-14.98-.03m15.02-.03A15 15 0 0115 5.47a15 15 0 00-4.4-10.62m23.8.05A15 15 0 0030 5.53a15 15 0 017.48 12.96 14.9 14.9 0 0015.02-.03m-22.5 13a15.13 15.13 0 017.52 13.01m-7.56-39a15 15 0 01-14.96 0M7.48 18.5a15 15 0 017.48 12.96 15 15 0 0015.04 0 15 15 0 017.48-12.96' stroke-width='3' stroke='%23ec914b8f' fill='none'/></pattern></defs><rect width='800%' height='800%' transform='translate(-38,-21.84)' fill='url(%23a)'/></svg>") background-image: url("data:image/svg+xml,<svg id='patternId' width='100%' height='100%' xmlns='http://www.w3.org/2000/svg'><defs><pattern id='a' patternUnits='userSpaceOnUse' width='45' height='51.96' patternTransform='scale(2) rotate(20)'><rect x='0' y='0' width='100%' height='100%' fill='%23202025ff'/><path d='M52.48 44.47a15 15 0 01-14.96 0 15 15 0 00-7.48 12.96M7.48 44.42a15 15 0 01-14.96 0M15 57.44c0-5.35-2.9-10.35-7.52-13.02a15 15 0 017.48-12.97M7.48 18.5a14.97 14.97 0 01-14.98-.03m15.02-.03A15 15 0 0115 5.47a15 15 0 00-4.4-10.62m23.8.05A15 15 0 0030 5.53a15 15 0 017.48 12.96 14.9 14.9 0 0015.02-.03m-22.5 13a15.13 15.13 0 017.52 13.01m-7.56-39a15 15 0 01-14.96 0M7.48 18.5a15 15 0 017.48 12.96 15 15 0 0015.04 0 15 15 0 017.48-12.96' stroke-width='3' stroke='%23ec914b8f' fill='none'/></pattern></defs><rect width='800%' height='800%' transform='translate(-38,-21.84)' fill='url(%23a)'/></svg>")
@ -55,13 +64,41 @@ header {
display: flex; display: flex;
position: relative; position: relative;
} }
#bottom {
float: right;
display: inline-block;
justify-content: space-between;
margin-left: auto;
grid-auto-flow: column;
grid-template-columns: 3fr;
position: absolute;
right: 30px;
}
#top {
float: left;
display: inline-block;
justify-content: space-between;
margin-left: auto;
grid-auto-flow: column;
grid-template-columns: 3fr;
position: absolute;
left: 30px;
}
h2 {
margin: 1vw;
}
#main_layer { #main_layer {
border-radius: 10px 10px 0px 10px;
padding: 10px;
margin: 1vw 1vh; margin: 1vw 1vh;
position: relative; position: relative;
overflow-y: auto; overflow-y: auto;
overflow-x: clip; overflow-x: clip;
height: 70vh; height: 68vh;
max-height: 68vh;
min-height: 8vh; min-height: 8vh;
} }

View File

@ -0,0 +1,18 @@
function onclickWrite(type, keyword, html) {
let title_field = document.getElementById('title_field')
var hasValues = true
if (hasValues) {
let data = {
'title': title_field.value,
'content': encodeURIComponent(html),
}
let uploadUrl = location.protocol + "//" + location.hostname + "/blog/post.ajax";
if(confirm(JSON.stringify(data) + "\n해당 내용으로\n유저 등록 하실??")) {
post(uploadUrl,type,JSON.stringify(data),keyword, function (resultData) {
alert(resultData)
})
} else {
}
}
}

View File

@ -51,14 +51,16 @@
</script> </script>
</th:block> </th:block>
<th:block layout:fragment="content" id="content"> <th:block layout:fragment="content" id="content">
<input id="title_layer" /> <div id="main_layer">
<div id="editor" ></div> <input id="title_layer" />
<div id="hashtag_layer"> <div id="editor" ></div>
<select > </select> <div id="hashtag_layer">
<input id="hashtag" /> <select > </select>
</div> <input id="hashtag" />
<div id="controll_layer" > </div>
<button onclick="save()">asdsad</button> <div id="controll_layer" >
<button onclick="save()">asdsad</button>
</div>
</div> </div>
</th:block> </th:block>
</html> </html>

View File

@ -7,6 +7,7 @@
<th:block layout:fragment="head" id="head"> <th:block layout:fragment="head" id="head">
<script type="text/javascript" th:src="@{https://code.jquery.com/jquery-3.5.1.min.js}" crossorigin="anonymous"></script> <script type="text/javascript" th:src="@{https://code.jquery.com/jquery-3.5.1.min.js}" crossorigin="anonymous"></script>
<script type="text/javascript" th:src="@{/js/toast-ui.js}"></script> <script type="text/javascript" th:src="@{/js/toast-ui.js}"></script>
<script type="text/javascript" th:src="@{/js/blog.js}"></script>
<link th:href="@{/css/blog.css}" rel="stylesheet" /> <link th:href="@{/css/blog.css}" rel="stylesheet" />
<link th:href="@{/css/toast-ui.css}" rel="stylesheet" /> <link th:href="@{/css/toast-ui.css}" rel="stylesheet" />
<link th:href="@{/css/toast-ui-dark.css}" rel="stylesheet" /> <link th:href="@{/css/toast-ui-dark.css}" rel="stylesheet" />
@ -63,12 +64,12 @@
addImageBlobHook: (blob, callback) => { addImageBlobHook: (blob, callback) => {
const formData = new FormData(); const formData = new FormData();
formData.append('file', blob); formData.append('file', blob);
let uploadUrl = location.protocol + "//" + location.hostname + "/blog/post/imageUpload";
let url = 'post/images/'; let imageUrl = location.protocol + "//" + location.hostname + '/blog/post/images/';
$.ajax({ $.ajax({
type: 'POST', type: 'POST',
enctype: 'multipart/form-data', enctype: 'multipart/form-data',
url: 'post/imageUpload', url: uploadUrl,
data: formData, data: formData,
dataType: 'json', dataType: 'json',
processData: false, processData: false,
@ -76,8 +77,8 @@
cache: false, cache: false,
timeout: 600000, timeout: 600000,
success: function (data) { success: function (data) {
url += data.fileName; imageUrl += data.fileName;
callback(url, '사진 대체 텍스트 입력'); callback(imageUrl, '사진 대체 텍스트 입력');
}, },
error: function (e) { error: function (e) {
callback('image_load_fail', '사진 대체 텍스트 입력'); callback('image_load_fail', '사진 대체 텍스트 입력');
@ -89,20 +90,27 @@
} }
function save() { function save() {
console.log(editor.getHTML()) console.log(editor.getHTML())
console.log(editor.getMarkdown())
onclickWrite([[${enc}]],[[${keyword}]],editor.getMarkdown())
} }
</script> </script>
</th:block> </th:block>
<th:block layout:fragment="content" id="content"> <th:block layout:fragment="content" id="content">
<div id="main_layer"> <div id="main_layer">
<div class="layer"> <th:block th:if="${PERMISSION != 'OK'}">
<input id="title_layer" /> <h1>권한이 없는 뎁쇼?!</h1>
</div> </th:block>
<div id="editor" ></div> <th:block th:if="${PERMISSION == 'OK'}">
<div class="layer"> <div class="layer">
<select > </select> <input id="title_field" />
<input id="hashtag" /> </div>
<button id="save" onclick="save()">asdsad</button> <div id="editor" ></div>
</div> <div class="layer">
<select > </select>
<input id="hashtag_field" />
<button id="save" onclick="save()">asdsad</button>
</div>
</th:block>
</div> </div>
</th:block> </th:block>
</html> </html>

View File

@ -1,22 +1,12 @@
<!DOCTYPE html> <!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" <html
xmlns:th="http://www.thymeleaf.org" xmlns:th="http://www.thymeleaf.org"
xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout" xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout"
layout:decorate="~{layout/default_layout}"> layout:decorate="~{layout/default_layout}">
<th:block layout:fragment="head"> <th:block layout:fragment="head">
<title>Spring Boot</title>
<!--/* css */-->
<link th:href="@{/css/common.css}" rel="stylesheet" />
</th:block> </th:block>
<body> <th:block layout:fragment="content" id="content">
<th:block layout:fragment="header" th:include="@{fragments/header}"></th:block> <div id="main_layer"></div>
</th:block>
<div layout:fragment="content" class="content"> </html>
<h2>This is Content</h2>
</div>
<th:block layout:fragment="footer" th:include="@{fragments/footer}"></th:block>
</body>
</html>

View File

@ -0,0 +1,151 @@
<!DOCTYPE html>
<html
xmlns:th="http://www.thymeleaf.org"
xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout"
layout:decorate="~{layout/default_layout}"
>
<th:block layout:fragment="head">
<script type="text/javascript" src="https://code.jquery.com/jquery-3.5.1.min.js" crossorigin="anonymous"></script>
<script type="text/javascript" th:src="@{/js/toast-ui-view.js}"></script>
<link th:href="@{/css/toast-ui.css}" rel="stylesheet" />
<link th:href="@{/css/toast-ui-dark.css}" rel="stylesheet" />
<script th:inline="javascript">
let editor
let onChange = () => {console.log(editor.getMarkdown())}
document.addEventListener("DOMContentLoaded", onLoaded);
function onLoaded() {
var h = document.querySelector('#main_layer').getBoundingClientRect().height + 'px'
editor = new toastui.Editor({
el: document.querySelector('#editor'),
height: '500px',
width:'100%',
viewer: true,
usageStatistics : false,
initialValue:
"\n" +
"#lun\n" +
"##Dependency License Report\n" +
"_2024-10-22 15:24:32 KST_\n" +
"## Apache License, Version 2.0\n" +
"\n" +
"**1** **Group:** `com.drewnoakes` **Name:** `metadata-extractor` **Version:** `2.19.0` \n" +
"> - **POM Project URL**: [https://drewnoakes.com/code/exif/](https://drewnoakes.com/code/exif/)\n" +
"> - **POM License**: Apache License, Version 2.0 - [https://www.apache.org/licenses/LICENSE-2.0](https://www.apache.org/licenses/LICENSE-2.0)\n" +
"\n" +
"**2** **Group:** `com.fasterxml.jackson.module` **Name:** `jackson-module-kotlin` **Version:** `2.17.2` \n" +
"> - **Project URL**: [https://github.com/FasterXML/jackson-module-kotlin](https://github.com/FasterXML/jackson-module-kotlin)\n" +
"> - **Manifest License**: Apache License, Version 2.0 (Not Packaged)\n" +
"> - **POM License**: Apache License, Version 2.0 - [https://www.apache.org/licenses/LICENSE-2.0](https://www.apache.org/licenses/LICENSE-2.0)\n" +
"> - **Embedded license files**: [jackson-module-kotlin-2.17.2.jar/META-INF/LICENSE](jackson-module-kotlin-2.17.2.jar/META-INF/LICENSE) \n" +
" - [jackson-module-kotlin-2.17.2.jar/META-INF/NOTICE](jackson-module-kotlin-2.17.2.jar/META-INF/NOTICE)\n" +
"\n" +
"**3** **Group:** `com.google.code.gson` **Name:** `gson` **Version:** `2.11.0` \n" +
"> - **Manifest Project URL**: [https://github.com/google/gson](https://github.com/google/gson)\n" +
"> - **Manifest License**: \"Apache-2.0\";link=\"https://www.apache.org/licenses/LICENSE-2.0.txt\" (Not Packaged)\n" +
"> - **POM License**: Apache License, Version 2.0 - [https://www.apache.org/licenses/LICENSE-2.0](https://www.apache.org/licenses/LICENSE-2.0)\n" +
"\n" +
"**4** **Group:** `io.projectreactor.kotlin` **Name:** `reactor-kotlin-extensions` **Version:** `1.2.3` \n" +
"> - **POM Project URL**: [https://github.com/reactor/reactor-kotlin-extensions](https://github.com/reactor/reactor-kotlin-extensions)\n" +
"> - **POM License**: Apache License, Version 2.0 - [https://www.apache.org/licenses/LICENSE-2.0](https://www.apache.org/licenses/LICENSE-2.0)\n" +
"\n" +
"**5** **Group:** `nz.net.ultraq.thymeleaf` **Name:** `thymeleaf-layout-dialect` **Version:** `3.3.0` \n" +
"> - **POM Project URL**: [https://github.com/ultraq/thymeleaf-layout-dialect/](https://github.com/ultraq/thymeleaf-layout-dialect/)\n" +
"> - **POM License**: Apache License, Version 2.0 - [https://www.apache.org/licenses/LICENSE-2.0](https://www.apache.org/licenses/LICENSE-2.0)\n" +
"\n" +
"**6** **Group:** `org.apache.tomcat.embed` **Name:** `tomcat-embed-jasper` **Version:** `10.1.30` \n" +
"> - **Manifest License**: Apache License, Version 2.0 (Not Packaged)\n" +
"> - **POM Project URL**: [https://tomcat.apache.org/](https://tomcat.apache.org/)\n" +
"> - **POM License**: Apache License, Version 2.0 - [https://www.apache.org/licenses/LICENSE-2.0](https://www.apache.org/licenses/LICENSE-2.0)\n" +
"> - **Embedded license files**: [tomcat-embed-jasper-10.1.30.jar/META-INF/LICENSE](tomcat-embed-jasper-10.1.30.jar/META-INF/LICENSE) \n" +
" - [tomcat-embed-jasper-10.1.30.jar/META-INF/NOTICE](tomcat-embed-jasper-10.1.30.jar/META-INF/NOTICE)\n" +
"\n" +
"**7** **Group:** `org.jetbrains.kotlin` **Name:** `kotlin-reflect` **Version:** `1.9.25` \n" +
"> - **POM Project URL**: [https://kotlinlang.org/](https://kotlinlang.org/)\n" +
"> - **POM License**: Apache License, Version 2.0 - [https://www.apache.org/licenses/LICENSE-2.0](https://www.apache.org/licenses/LICENSE-2.0)\n" +
"\n" +
"**8** **Group:** `org.jetbrains.kotlin` **Name:** `kotlin-stdlib` **Version:** `1.9.25` \n" +
"> - **POM Project URL**: [https://kotlinlang.org/](https://kotlinlang.org/)\n" +
"> - **POM License**: Apache License, Version 2.0 - [https://www.apache.org/licenses/LICENSE-2.0](https://www.apache.org/licenses/LICENSE-2.0)\n" +
"\n" +
"**9** **Group:** `org.jetbrains.kotlinx` **Name:** `kotlinx-coroutines-reactor` **Version:** `1.8.1` \n" +
"> - **POM Project URL**: [https://github.com/Kotlin/kotlinx.coroutines](https://github.com/Kotlin/kotlinx.coroutines)\n" +
"> - **POM License**: Apache License, Version 2.0 - [https://www.apache.org/licenses/LICENSE-2.0](https://www.apache.org/licenses/LICENSE-2.0)\n" +
"\n" +
"**10** **Group:** `org.slf4j` **Name:** `jcl-over-slf4j` **Version:** `2.0.16` \n" +
"> - **Project URL**: [http://www.slf4j.org](http://www.slf4j.org)\n" +
"> - **Manifest License**: Apache License, Version 2.0 (Not Packaged)\n" +
"> - **POM License**: Apache License, Version 2.0 - [https://www.apache.org/licenses/LICENSE-2.0](https://www.apache.org/licenses/LICENSE-2.0)\n" +
"> - **POM License**: MIT License - [https://opensource.org/licenses/MIT](https://opensource.org/licenses/MIT)\n" +
"> - **Embedded license files**: [jcl-over-slf4j-2.0.16.jar/META-INF/LICENSE.txt](jcl-over-slf4j-2.0.16.jar/META-INF/LICENSE.txt)\n" +
"\n" +
"**11** **Group:** `org.springframework.boot` **Name:** `spring-boot-starter-data-mongodb-reactive` **Version:** `3.3.4` \n" +
"> - **POM Project URL**: [https://spring.io/projects/spring-boot](https://spring.io/projects/spring-boot)\n" +
"> - **POM License**: Apache License, Version 2.0 - [https://www.apache.org/licenses/LICENSE-2.0](https://www.apache.org/licenses/LICENSE-2.0)\n" +
"> - **Embedded license files**: [spring-boot-starter-data-mongodb-reactive-3.3.4.jar/META-INF/LICENSE.txt](spring-boot-starter-data-mongodb-reactive-3.3.4.jar/META-INF/LICENSE.txt) \n" +
" - [spring-boot-starter-data-mongodb-reactive-3.3.4.jar/META-INF/NOTICE.txt](spring-boot-starter-data-mongodb-reactive-3.3.4.jar/META-INF/NOTICE.txt)\n" +
"\n" +
"**12** **Group:** `org.springframework.boot` **Name:** `spring-boot-starter-security` **Version:** `3.3.4` \n" +
"> - **POM Project URL**: [https://spring.io/projects/spring-boot](https://spring.io/projects/spring-boot)\n" +
"> - **POM License**: Apache License, Version 2.0 - [https://www.apache.org/licenses/LICENSE-2.0](https://www.apache.org/licenses/LICENSE-2.0)\n" +
"> - **Embedded license files**: [spring-boot-starter-security-3.3.4.jar/META-INF/LICENSE.txt](spring-boot-starter-security-3.3.4.jar/META-INF/LICENSE.txt) \n" +
" - [spring-boot-starter-security-3.3.4.jar/META-INF/NOTICE.txt](spring-boot-starter-security-3.3.4.jar/META-INF/NOTICE.txt)\n" +
"\n" +
"**13** **Group:** `org.springframework.boot` **Name:** `spring-boot-starter-quartz` **Version:** `3.3.4` \n" +
"> - **POM Project URL**: [https://spring.io/projects/spring-boot](https://spring.io/projects/spring-boot)\n" +
"> - **POM License**: Apache License, Version 2.0 - [https://www.apache.org/licenses/LICENSE-2.0](https://www.apache.org/licenses/LICENSE-2.0)\n" +
"> - **Embedded license files**: [spring-boot-starter-quartz-3.3.4.jar/META-INF/LICENSE.txt](spring-boot-starter-quartz-3.3.4.jar/META-INF/LICENSE.txt) \n" +
" - [spring-boot-starter-quartz-3.3.4.jar/META-INF/NOTICE.txt](spring-boot-starter-quartz-3.3.4.jar/META-INF/NOTICE.txt)\n" +
"\n" +
"**14** **Group:** `org.springframework.boot` **Name:** `spring-boot-starter-thymeleaf` **Version:** `3.3.4` \n" +
"> - **POM Project URL**: [https://spring.io/projects/spring-boot](https://spring.io/projects/spring-boot)\n" +
"> - **POM License**: Apache License, Version 2.0 - [https://www.apache.org/licenses/LICENSE-2.0](https://www.apache.org/licenses/LICENSE-2.0)\n" +
"> - **Embedded license files**: [spring-boot-starter-thymeleaf-3.3.4.jar/META-INF/LICENSE.txt](spring-boot-starter-thymeleaf-3.3.4.jar/META-INF/LICENSE.txt) \n" +
" - [spring-boot-starter-thymeleaf-3.3.4.jar/META-INF/NOTICE.txt](spring-boot-starter-thymeleaf-3.3.4.jar/META-INF/NOTICE.txt)\n" +
"\n" +
"**15** **Group:** `org.springframework.boot` **Name:** `spring-boot-starter-webflux` **Version:** `3.3.4` \n" +
"> - **POM Project URL**: [https://spring.io/projects/spring-boot](https://spring.io/projects/spring-boot)\n" +
"> - **POM License**: Apache License, Version 2.0 - [https://www.apache.org/licenses/LICENSE-2.0](https://www.apache.org/licenses/LICENSE-2.0)\n" +
"> - **Embedded license files**: [spring-boot-starter-webflux-3.3.4.jar/META-INF/LICENSE.txt](spring-boot-starter-webflux-3.3.4.jar/META-INF/LICENSE.txt) \n" +
" - [spring-boot-starter-webflux-3.3.4.jar/META-INF/NOTICE.txt](spring-boot-starter-webflux-3.3.4.jar/META-INF/NOTICE.txt)\n" +
"\n" +
"**16** **Group:** `org.springframework.boot` **Name:** `spring-boot-starter-web` **Version:** `3.3.4` \n" +
"> - **POM Project URL**: [https://spring.io/projects/spring-boot](https://spring.io/projects/spring-boot)\n" +
"> - **POM License**: Apache License, Version 2.0 - [https://www.apache.org/licenses/LICENSE-2.0](https://www.apache.org/licenses/LICENSE-2.0)\n" +
"> - **Embedded license files**: [spring-boot-starter-web-3.3.4.jar/META-INF/LICENSE.txt](spring-boot-starter-web-3.3.4.jar/META-INF/LICENSE.txt) \n" +
" - [spring-boot-starter-web-3.3.4.jar/META-INF/NOTICE.txt](spring-boot-starter-web-3.3.4.jar/META-INF/NOTICE.txt)\n" +
"\n" +
"## LGPL-2.1\n" +
"\n" +
"**17** **Group:** `org.mariadb.jdbc` **Name:** `mariadb-java-client` **Version:** `3.3.3` \n" +
"> - **Project URL**: [https://mariadb.com/kb/en/mariadb/about-mariadb-connector-j/](https://mariadb.com/kb/en/mariadb/about-mariadb-connector-j/)\n" +
"> - **Manifest License**: \"LGPL-2.1\" (Not Packaged)\n" +
"> - **POM License**: LGPL-2.1\n" +
"\n" +
"## MIT License\n" +
"\n" +
"**18** **Group:** `org.jsoup` **Name:** `jsoup` **Version:** `1.18.1` \n" +
"> - **Project URL**: [https://jsoup.org/](https://jsoup.org/)\n" +
"> - **POM License**: MIT License - [https://opensource.org/licenses/MIT](https://opensource.org/licenses/MIT)\n" +
"> - **Embedded license files**: [jsoup-1.18.1.jar/META-INF/LICENSE](jsoup-1.18.1.jar/META-INF/LICENSE) \n" +
" - [jsoup-1.18.1.jar/META-INF/README.md](jsoup-1.18.1.jar/META-INF/README.md)\n" +
"\n" +
"**19** **Group:** `org.slf4j` **Name:** `jcl-over-slf4j` **Version:** `2.0.16` \n" +
"> - **Project URL**: [http://www.slf4j.org](http://www.slf4j.org)\n" +
"> - **Manifest License**: Apache License, Version 2.0 (Not Packaged)\n" +
"> - **POM License**: Apache License, Version 2.0 - [https://www.apache.org/licenses/LICENSE-2.0](https://www.apache.org/licenses/LICENSE-2.0)\n" +
"> - **POM License**: MIT License - [https://opensource.org/licenses/MIT](https://opensource.org/licenses/MIT)\n" +
"> - **Embedded license files**: [jcl-over-slf4j-2.0.16.jar/META-INF/LICENSE.txt](jcl-over-slf4j-2.0.16.jar/META-INF/LICENSE.txt)\n" +
"\n" +
"\n"
,
theme:"dark",
});
}
</script>
</th:block>
<th:block layout:fragment="content" id="content">
<div id="main_layer" style="background:#30303594;">
<div id="editor" ></div>
</div>
</th:block>
</html>

View File

@ -0,0 +1,20 @@
<!DOCTYPE html>
<html
xmlns:th="http://www.thymeleaf.org"
xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout"
layout:decorate="~{layout/default_layout}">
<th:block layout:fragment="head">
</th:block>
<th:block layout:fragment="content" id="content">
<table id="main_layer">
<tr id="where" th:each="location : ${locations}">
<td class="where_item"><span th:text="${location.timeString}"></span></td>
<td class="where_item"><span th:text="${location.mAddressLines}"></span></td>
<td class="where_item"><span th:text="${location.mCountryName}"></span></td>
<td class="where_item"><span th:text="${location.mLatitude}"></span></td>
<td class="where_item"><span th:text="${location.mLongitude}"></span></td>
</tr>
</table>
</th:block>
</html>

View File

@ -1,6 +1,13 @@
<!DOCTYPE html> <!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org"> <html xmlns:th="http://www.thymeleaf.org">
<th:block th:fragment="footer"> <th:block th:fragment="footer">
<footer></footer> <footer>
<table >
<tr id="bottom">
<td><h2><a aria-label="licenses" style="color: white" href="../licenses" title="Gmail">licenses</a></h2></td>
<td><h2><a aria-label="sendToMe" style="color: white" href="mailto:lunaticbum@gmail.com" title="Gmail">lunaticbum@gmail.com</a></h2></td>
</tr>
</table>
</footer>
</th:block> </th:block>
</html> </html>

View File

@ -2,7 +2,11 @@
<html xmlns:th="http://www.thymeleaf.org"> <html xmlns:th="http://www.thymeleaf.org">
<th:block th:fragment="header"> <th:block th:fragment="header">
<header> <header>
<table >
<tr id="top">
<td><h2><a aria-label="licenses" style="color: white" href="../" title="Gmail">HOME</a></h2></td>
</tr>
</table>
</header> </header>
</th:block> </th:block>
</html> </html>

View File

@ -8,5 +8,6 @@
<meta name="viewport" content="width=device-width,height=device-height,initial-scale=1"/> <meta name="viewport" content="width=device-width,height=device-height,initial-scale=1"/>
<link th:href="@{/css/common.css}" rel="stylesheet" /> <link th:href="@{/css/common.css}" rel="stylesheet" />
<script type="text/javascript" th:src="@{/js/common.js}"></script> <script type="text/javascript" th:src="@{/js/common.js}"></script>
<script async th:src="@{https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js?client=ca-pub-9504446465764716}" crossorigin="anonymous"></script>
</th:block> </th:block>
</html> </html>

View File

@ -5,20 +5,21 @@
xmlns="http://www.w3.org/1999/html"> xmlns="http://www.w3.org/1999/html">
<head> <head>
<!-- <th:block layout:replace="fragments/includes" ></th:block>--> <!-- <th:block layout:replace="fragments/includes" ></th:block>-->
<th:block th:replace="fragments/includes :: includes"></th:block> <th:block th:replace="~{fragments/includes :: includes}"></th:block>
<!-- layout:fragment="head" --> <!-- layout:fragment="head" -->
<th:block layout:fragment="head"></th:block> <th:block layout:fragment="head"></th:block>
<!-- <th:block layout:replace="fragments/title" ></th:block> --> <!-- <th:block layout:replace="fragments/title" ></th:block> -->
<th:block th:replace="fragments/title :: title"></th:block> <th:block th:replace="~{fragments/title :: title}"></th:block>
</head> </head>
<body> <body>
<!--<th:block th:replace="fragments/header :: header"></th:block>--> <!--<th:block th:replace="fragments/header :: header"></th:block>-->
<th:block th:replace="fragments/header :: header"></th:block> <th:block th:replace="~{fragments/header :: header}"></th:block>
<!--<th:block layout:fragment="content"></th:block>--> <!--<th:block layout:fragment="content"></th:block>-->
<th:block layout:fragment="content"></th:block> <th:block layout:fragment="content"></th:block>
<!--<th:block th:replace="fragments/footer :: footer"></th:block>--> <!--<th:block th:replace="fragments/footer :: footer"></th:block>-->
<th:block th:replace="fragments/footer :: footer"></th:block> <th:block th:replace="~{fragments/footer :: footer}"></th:block>
</body> </body>
</html> </html>