This commit is contained in:
2025-03-20 17:57:55 +09:00
parent 2e3667d0a1
commit c3d2599754
9 changed files with 421 additions and 44 deletions
@@ -3,6 +3,9 @@ package kr.lunaticbum.back.lun.controllers
import com.drew.imaging.ImageMetadataReader
import com.drew.metadata.Metadata
import com.google.gson.Gson
import com.google.maps.GeoApiContext
import com.google.maps.GeocodingApi
import com.google.maps.model.LatLng
import jakarta.servlet.http.HttpServletRequest
import jakarta.servlet.http.HttpServletResponse
import kr.lunaticbum.back.lun.configs.GlobalEnvironment
@@ -13,15 +16,22 @@ import kr.lunaticbum.back.lun.model.*
import kr.lunaticbum.back.lun.service.JwtService
import kr.lunaticbum.back.lun.utils.LogService
import kr.lunaticbum.back.lun.utils.getFileExtension
import org.commonmark.node.Node
import org.commonmark.parser.Parser
import org.commonmark.renderer.html.HtmlRenderer
import org.jsoup.Jsoup
import org.jsoup.nodes.Element
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.beans.factory.annotation.Value
import org.springframework.core.io.Resource
import org.springframework.core.io.UrlResource
import org.springframework.data.domain.Pageable
import org.springframework.http.MediaType
import org.springframework.http.ResponseEntity
import org.springframework.web.bind.annotation.*
import org.springframework.web.multipart.MultipartFile
import org.springframework.web.reactive.function.client.WebClient
import reactor.kotlin.core.publisher.toMono
import java.io.*
import java.net.URLDecoder
import java.text.SimpleDateFormat
@@ -131,6 +141,23 @@ class BlogController() {
postManageg.getPost(postId).block().apply {
this?.title = URLDecoder.decode(this?.title)
this?.content = URLDecoder.decode(this?.content)
globalEvv.gapiKey?.let {
if (this?.firstAddress?.length ?: 0 < 4){
try {
var addrs = GeocodingApi.reverseGeocode(GeoApiContext.Builder().apiKey(it).build(), LatLng(this?.firstPostLat!!,this?.firstPostLon!!)).await()
this.firstAddress = addrs.first().formattedAddress
} catch (e: Exception) {}
}
if (this?.modifyAddress?.length ?: 0 < 4){
try {
var addrs = GeocodingApi.reverseGeocode(GeoApiContext.Builder().apiKey(it).build(), LatLng(this?.modifyLat!!,this?.modifyLon!!)).await()
this.modifyAddress = addrs.first().formattedAddress
} catch (e: Exception) {}
}
}
vm.modelMap.put("srcPost",this)
}
return vm
@@ -175,6 +202,31 @@ class BlogController() {
}
@GetMapping("posts")
fun posts() : ResultMV{
val vm = ResultMV("content/blog/posts")
try {
vm.modelMap.put("Posts", postManageg.find20().apply {
this.forEach {
it.title = URLDecoder.decode(it.title)
it.content = URLDecoder.decode(it.content)
val parser: Parser = Parser.builder().build()
val document: Node = parser.parse(it.content)
val renderer = HtmlRenderer.builder().build()
Jsoup.parse(renderer.render(document))?.let { doc ->
val firstImg: Element? = doc.select("img")?.first()
val imgSrc: String = firstImg?.attr("src") ?: ""
it.image = imgSrc
it.html = doc.text()
}
it.title = if ((it.title?.length ?: 0) >= 1) it.title else ""
}
}.chunked(2))
}catch (ex: Exception){ex.printStackTrace()}
return vm
}
@GetMapping("recent")
fun recent() : ResultMV{
val vm = ResultMV("content/blog/viewer")
@@ -42,6 +42,8 @@ class Post {
var posting : Boolean = false
var firstPostLat : Double = 0.0
var firstPostLon : Double = 0.0
var firstAddress = ""
var modifyAddress = ""
var modifyTime : Long = 0
var modifyLat : Double = 0.0
+6 -6
View File
@@ -158,9 +158,9 @@ a.btn_layerClose:hover {
overflow-y: hidden;
overflow-x: hidden;
}
#editor {
border: 1px solid #393b42;
padding: 1px;
border-radius: 10px;
background: #00000044;
}
/*#editor {*/
/* border: 1px solid #393b42;*/
/* padding: 1px;*/
/* border-radius: 10px;*/
/* background: #00000044;*/
/*}*/
+17 -17
View File
@@ -1,27 +1,27 @@
onload = function() {
history.replaceState({}, null, location.pathname);
var accToken = get_cookie("access")
var refreshToken = get_cookie("refresh")
console.log("access === " + accToken + " || " + accToken.length);
console.log("refresh === " + refreshToken + " || " + refreshToken.length);
// var accToken = get_cookie("access")
// var refreshToken = get_cookie("refresh")
// console.log("access === " + accToken + " || " + accToken.length);
// console.log("refresh === " + refreshToken + " || " + refreshToken.length);
document.cookie = "access=; expires=Thu, 01 Jan 1970 00:00:01 GMT;"
document.cookie = "refresh=; expires=Thu, 01 Jan 1970 00:00:01 GMT;"
document.cookie = "CLEAR=; expires=Thu, 01 Jan 1970 00:00:01 GMT;"
}
onbeforeunload = function () {
var accToken = get_cookie("access")
var refreshToken = get_cookie("refresh")
console.log("access === " + accToken + " || " + accToken.length);
console.log("refresh === " + refreshToken + " || " + refreshToken.length);
if (accToken.length < 1) {
document.cookie = "refresh="+ window.sessionStorage.getItem("REFRESH") + ";";
}
if (refreshToken.length < 1) {
window.sessionStorage.setItem("REFRESH",get_cookie("refresh"))
}
}
// onbeforeunload = function () {
// var accToken = get_cookie("access")
// var refreshToken = get_cookie("refresh")
// console.log("access === " + accToken + " || " + accToken.length);
// console.log("refresh === " + refreshToken + " || " + refreshToken.length);
//
// if (accToken.length < 1) {
// document.cookie = "refresh="+ window.sessionStorage.getItem("REFRESH") + ";";
// }
// if (refreshToken.length < 1) {
// window.sessionStorage.setItem("REFRESH",get_cookie("refresh"))
// }
// }
function get_cookie(name) {
var value = document.cookie.match('(^|;) ?' + name + '=([^;]*)(;|$)');
return value? value[2] : null;
@@ -0,0 +1,130 @@
<!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" th:src="@{/js/toast-ui-view.js}"></script>
<link th:href="@{/css/toast-ui-dark.css}" rel="stylesheet" />
<script type="text/javascript" th:src="@{/js/blog.js}"></script>
<link th:href="@{/css/blog.css}" rel="stylesheet" />
<script th:inline="javascript">
let editor
let onChange = () => {console.log(editor.getMarkdown())}
document.addEventListener("DOMContentLoaded", onLoaded);
function onLoaded() {
// 1. 모든 'current' 클래스를 가진 요소를 선택하고 제거
const currentElements = document.querySelectorAll('.current');
currentElements.forEach(element => {
element.classList.remove('current');
});
// 2. 특정 조건에 맞는 요소에 'current' 클래스 추가 (예: ID가 'targetElement'인 요소)
const targetElement = document.getElementById('menu_posts');
if (targetElement) {
targetElement.classList.add('current');
}
}
</script>
</th:block>
<th:block layout:fragment="content" id="content">
<section class="wrapper style1">
<div class="container">
<div class="row gtr-200">
<div class="col-3 col-12-narrower">
<div id="sidebar1">
<section>
<h3>Just a Subheading</h3>
<p>Phasellus quam turpis, feugiat sit amet ornare in, hendrerit in lectus.
Praesent semper mod quis eget mi. Etiam eu ante risus. Aliquam erat volutpat.
Aliquam luctus et mattis lectus sit amet pulvinar. Nam turpis et nisi etiam.</p>
<footer>
<a href="#" class="button">Continue Reading</a>
</footer>
</section>
<section>
<h3>Another Subheading</h3>
<ul class="links">
<li><a href="#">Amet turpis, feugiat sit amet</a></li>
<li><a href="#">Ornare in hendrerit lectus</a></li>
<li><a href="#">Semper mod quis eget dolore</a></li>
<li><a href="#">Consequat lorem phasellus</a></li>
<li><a href="#">Amet turpis feugiat amet</a></li>
<li><a href="#">Semper mod quisturpis nisi</a></li>
</ul>
<footer>
<a href="#" class="button">More Random Links</a>
</footer>
</section>
</div>
</div>
<div class="col-6 col-12-narrower imp-narrower">
<div id="content">
<article>
<header>
<h2>Two Sidebar</h2>
<p>Yup. Two sidebars at the same time.</p>
</header>
<span class="image featured"><img src="images/banner.jpg" alt="" /></span>
<p>Phasellus quam turpis, feugiat sit amet ornare in, hendrerit in lectus.
Praesent semper mod quis eget mi. Etiam eu ante risus. Aliquam erat volutpat.
Aliquam luctus et mattis lectus sit amet pulvinar. Nam turpis nisi
consequat etiam lorem ipsum dolor sit amet nullam.</p>
<h3>And Yet Another Subheading</h3>
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Maecenas ac quam risus, at tempus
justo. Sed dictum rutrum massa eu volutpat. Quisque vitae hendrerit sem. Pellentesque lorem felis,
ultricies a bibendum id, bibendum sit amet nisl. Mauris et lorem quam. Maecenas rutrum imperdiet
rhoncus dui quis euismod. Maecenas lorem tellus, congue et condimentum ac, ullamcorper non sapien.
Donec sagittis massa et leo semper a scelerisque metus faucibus. Morbi congue mattis mi.
Phasellus sed nisl vitae risus tristique volutpat. Cras rutrum commodo luctus.</p>
<p>Phasellus odio risus, faucibus et viverra vitae, eleifend ac purus. Praesent mattis, enim
quis hendrerit porttitor, sapien tortor viverra magna, sit amet rhoncus nisl lacus nec arcu.
Maecenas tortor mauris, consectetur pellentesque dapibus eget, tincidunt vitae arcu.
Vestibulum purus augue, tincidunt sit amet iaculis id, porta eu purus.</p>
</article>
</div>
</div>
<div class="col-3 col-12-narrower">
<div id="sidebar2">
<section>
<h3>Another Subheading</h3>
<ul class="links">
<li><a href="#">Amet turpis, feugiat sit amet</a></li>
<li><a href="#">Ornare in hendrerit lectus</a></li>
<li><a href="#">Semper mod quis eget dolore</a></li>
<li><a href="#">Consequat lorem phasellus</a></li>
<li><a href="#">Amet turpis feugiat amet</a></li>
<li><a href="#">Semper mod quisturpis nisi</a></li>
</ul>
<footer>
<a href="#" class="button">More Random Links</a>
</footer>
</section>
<section>
<h3>Just a Subheading</h3>
<p>Phasellus quam turpis, feugiat sit amet ornare in, hendrerit in lectus.
Praesent semper mod quis eget mi. Etiam eu ante risus. Aliquam erat volutpat.
Aliquam luctus et mattis lectus sit amet pulvinar. Nam turpis et nisi etiam.</p>
<footer>
<a href="#" class="button">Continue Reading</a>
</footer>
</section>
</div>
</div>
</div>
</div>
</section>
</th:block>
</html>
@@ -20,28 +20,31 @@
baseData.firstPostLat = [[${srcPost.firstPostLat}]];
document.getElementById('location_field').textContent = "Lat: " + baseData.firstPostLat + ", Lon: " + baseData.firstPostLon;
$('#title_layer').text(baseData.title)
var h = document.querySelector('#main_layer').getBoundingClientRect().height * 0.7
editor = new toastui.Editor({
el: document.querySelector('#editor'),
height: h+ 'px',
height: '100%',
width:'100%',
viewer: true,
usageStatistics : false,
initialValue:baseData.content,
theme:"dark",
});
}
</script>
</th:block>
<th:block layout:fragment="content" id="content">
<section class="wrapper style2">
<div class="container">
<header class="major" >
<h2 id="title_layer" th:text="${srcPost.title}">A gigantic heading you can use for whatever</h2>
<p th:text="${#temporals.format(T(java.time.Instant).ofEpochMilli(srcPost.writeTime).atZone(T(java.time.ZoneId).systemDefault()).toLocalDateTime(), 'yyyy-MM-dd HH:mm:ss')}"></p>
</header>
</div>
</section>
<section class="wrapper style1">
<div class="container">
<div id="content">
<!-- Content -->
<article>
<label id="title_layer" class="write_option" ></label>
<div id="editor" ></div>
<div class="write_controllbox">
<div class="write_option btn-example" to="#popLayer1" onclick="openPopup(this)" ></div>
@@ -50,6 +53,8 @@
<div style="width: 15px" ></div>
<label class="write_option" readonly id="location_field"></label>
</div>
<h3 id="write" th:text="${srcPost.firstAddress}"></h3>
<h3 id="modify" th:text="${srcPost.modifyAddress}"></h3>
</article>
</div>
</div>
@@ -4,14 +4,15 @@
<div id="header">
<!-- Logo -->
<h1><a href="index.html" id="logo">BUM ' <em>sPace</em></a></h1>
<h1><a th:href="@{/}" id="logo">BUM ' <em>sPace</em></a></h1>
<!-- Nav -->
<nav id="nav">
<ul>
<li class="current"><a href="index.html">Home</a></li>
<li>
<a href="#">Dropdown</a>
<li id="menu_home" class="current"><a th:href="@{/}">Home</a></li>
<li id="menu_posts"><a href="blog/posts">Posts</a></li>
<li id="menu_drop">
<a href="#">Dropdown</a>
<ul>
<li><a href="#">Lorem dolor</a></li>
<li><a href="#">Magna phasellus</a></li>
@@ -29,10 +30,10 @@
<li><a href="#">Veroeros feugiat</a></li>
</ul>
</li>
<li><a href="left-sidebar">Left Sidebar</a></li>
<li><a href="right-sidebar">Right Sidebar</a></li>
<li><a href="two-sidebar">Two Sidebar</a></li>
<li><a href="no-sidebar">No Sidebar</a></li>
<li id="menu_sec"><a href="left-sidebar">Left Sidebar</a></li>
<li id="menu_thr"><a href="right-sidebar">Right Sidebar</a></li>
<li id="menu_four"><a href="two-sidebar">Two Sidebar</a></li>
</ul>
</nav>
@@ -4,6 +4,7 @@
xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout"
xmlns="http://www.w3.org/1999/html">
<head>
<base th:href="@{/}" />
<th:block th:replace="~{fragments/includes :: includes}"></th:block>
<th:block layout:fragment="head"></th:block>
<th:block th:replace="~{fragments/title :: title}"></th:block>
@@ -19,12 +20,12 @@
<th:block th:replace="~{fragments/footer :: footer}"></th:block>
</div>
<!-- Scripts -->
<script src="assets/js/jquery.min.js"></script>
<script src="assets/js/jquery.dropotron.min.js"></script>
<script src="assets/js/browser.min.js"></script>
<script src="assets/js/breakpoints.min.js"></script>
<script src="assets/js/util.js"></script>
<script src="assets/js/main.js"></script>
<script th:src="@{/assets/js/jquery.min.js}"></script>
<script th:src="@{/assets/js/jquery.dropotron.min.js}"></script>
<script th:src="@{/assets/js/browser.min.js}"></script>
<script th:src="@{/assets/js/breakpoints.min.js}"></script>
<script th:src="@{/assets/js/util.js}"></script>
<script th:src="@{/assets/js/main.js}"></script>
</body>
</html>