This commit is contained in:
lunaticbum 2024-10-25 18:28:25 +09:00
parent 5979281bab
commit 2e7192f91b
16 changed files with 188 additions and 102 deletions

View File

@ -125,16 +125,14 @@ class BlogController() {
return responce
}
@GetMapping("viewer/{blogId}")
fun viewer(@PathVariable blogId : String) : ModelAndView{
@GetMapping("viewer/{postId}")
fun viewer(@PathVariable postId : String) : ModelAndView{
val vm = ModelAndView("content/blog/viewer")
// when(System.currentTimeMillis() % 5L) {
// 0L -> vm.modelMap.put(EncTypeKey,"T4")
// 1L -> vm.modelMap.put(EncTypeKey,"T3")
// 2L -> vm.modelMap.put(EncTypeKey,"T2")
// else -> vm.modelMap.put(EncTypeKey,"T0")
// }
postManageg.getPost(postId).block().apply {
this?.title = URLDecoder.decode(this?.title)
this?.content = URLDecoder.decode(this?.content)
vm.modelMap.put("srcPost",this)
}
return vm
}
@ -163,7 +161,11 @@ class BlogController() {
@GetMapping("editor/{postId}")
fun editor(@PathVariable postId : String, @RequestParam("token") token : String?) : ModelAndView{
val vm = ModelAndView("content/blog/editor")
vm.modelMap.put("srcPost",postManageg.getPost(postId).block().apply { })
postManageg.getPost(postId).block().apply {
this?.title = URLDecoder.decode(this?.title)
this?.content = URLDecoder.decode(this?.content)
vm.modelMap.put("srcPost",this)
}
if (TEMPTOKEN.equals(token)) {
vm.modelMap.put(WRITE_PERMISSION_KEY,"OK")
} else {

View File

@ -5,10 +5,12 @@ import jakarta.servlet.http.HttpServletResponse
import kr.lunaticbum.back.lun.model.PostManageg
import kr.lunaticbum.back.lun.utils.LogService
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.data.domain.Pageable
import org.springframework.web.bind.annotation.GetMapping
import org.springframework.web.bind.annotation.RequestMapping
import org.springframework.web.bind.annotation.RestController
import org.springframework.web.servlet.ModelAndView
import java.net.URLDecoder
import java.net.http.HttpClient.Redirect
@RestController
@ -24,11 +26,14 @@ class Home {
@GetMapping("/","/home")
fun home() : ModelAndView {
val vm = ModelAndView("content/home")
vm.modelMap.put("posts", postManageg.find20().apply {
vm.modelMap.put("Posts", postManageg.find20(Pageable.ofSize(20)).apply {
this.forEach {
it.title = URLDecoder.decode(it.title)
it.content = URLDecoder.decode(it.content)
logService.log(Gson().toJson(it))
}
})
vm.modelMap.put("path","/blog/viewer/")
return vm
}
@GetMapping("/login")

View File

@ -9,6 +9,7 @@ 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.domain.Pageable
import org.springframework.data.mongodb.core.mapping.Document
import org.springframework.data.mongodb.repository.Query
import org.springframework.data.mongodb.repository.ReactiveMongoRepository
@ -52,6 +53,7 @@ class Post {
@Repository
interface PostRepository : ReactiveMongoRepository<Post, String> {
fun findAllByModifyTime(time : Long? = 0): Flux<Post>
fun findAllByPostingTrue(pageable: Pageable): Flux<Post>
}
@ -67,6 +69,10 @@ class PostManageg {
private lateinit var bCryptPasswordEncoder: PasswordEncoder
fun getPost(id : String) : Mono<Post> = postRepository.findById(id)
fun find20(pageable :Pageable) : List<Post> {
return postRepository.findAllByPostingTrue(pageable).takeLast(20).buffer(20).blockLast(Duration.ofSeconds(30)) ?: listOf()
}
fun find20() : List<Post> {
return postRepository.findAllByModifyTime(0).takeLast(20).buffer(20).blockLast(Duration.ofSeconds(30)) ?: listOf()
}

View File

@ -130,7 +130,7 @@ a.btn_layerClose:hover {
display: grid;
gap: 10px;
/*grid-auto-rows: minmax(200px, auto);*/
grid-template-columns: repeat(auto-fill, minmax(300px, auto));
grid-template-columns: repeat(auto-fill, minmax(200px, auto));
width: 100%;
}

View File

@ -3,12 +3,13 @@
--TopHeight: 160px;
--FooterHeight: 160px;
--ContentVerticalMargin: 5px;
--DEFAULT_LAYER_BACK : #2e2e2eBB
/*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>")*/
}
html {
margin: 1vh 1vw;
background: #202025ee;
background: var(--DEFAULT_LAYER_BACK);
}
#where{
table-layout: fixed;
@ -42,15 +43,44 @@ body > *{
header {
top: 0;
background: #F0F0F524;
background: var(--DEFAULT_LAYER_BACK);
border-top: #ec914b8f;
border-radius: 10px 30px;
border-width: 1px;
height: 8vh;
min-height: 8vh;
display: flex;
height: 5vh;
min-height: 5vh;
display: flex;;
position: relative;
}
.user_info {
padding: 2px;
position: absolute;
display: inline-flex;
flex-direction: column;
right: 0;
}
.login_input {
border-radius: 10px;
border-width: 2px;
border: #F0F0F514;
background: #F0F0F524;
color: white;
text-align: center;
margin: 2px;
}
.login_input::placeholder {
color: #ec914b;
}
.login_input::-webkit-input-placeholder{
color: #ec914b;
}
.login_input:-ms-input-placeholder{
color: #ec914b;
}
#bottom {
float: right;
display: inline-block;
@ -102,10 +132,10 @@ footer {
display: flex;
bottom: 0;
border-top: #ec914b8f;
background: #F0F0F524;
background: var(--DEFAULT_LAYER_BACK);
border-radius: 30px 10px;
border-width: 1px;
height: 8vh;
min-height: 8vh;
height: 5vh;
min-height: 5vh;
position: relative;
}

View File

@ -0,0 +1,18 @@
.layer {
height: 100%;
place-content: space-between;
place-items: stretch;
display: grid;
gap: 10px;
grid-auto-rows: minmax(200px, auto);
grid-template-columns: repeat(auto-fill, minmax(200px, auto));
width: 100%;
}
.where_item {
justify-content: space-between;
flex-wrap: wrap;
flex-direction: row;
width: 100%;
border-radius: 10px;
background: #F0F0F524;
}

View File

@ -75,6 +75,29 @@ function mainPath() {
}
}
function gotoLogin() {
console.log(`location.port >> ${location.port}`)
location.href = getMainPath()+"/login"
}
function goToView(path,id) {
location.href = path + id;
}
function onclickLogin(type, keyword) {
let user_id = document.getElementById('user_id')
let user_pw = document.getElementById('user_pw')
let data = {
'user_id': user_id.value,
'user_pw': user_pw.value,
}
post(getMainPath()+"/user/login.ajax",type,JSON.stringify(data),keyword, function (resultData) {
alert(resultData)
})
}
function getMainPath() {
console.log(`location.port >> ${location.port}`)
if ('443' === location.port) {

View File

@ -75,16 +75,3 @@ function onclickJoin(type, keyword) {
}
function onclickLogin(type, keyword) {
let user_id = document.getElementById('user_id')
let user_pw = document.getElementById('user_pw')
let data = {
'user_id': user_id.value,
'user_pw': user_pw.value,
}
post("login.ajax",type,JSON.stringify(data),keyword, function (resultData) {
alert(resultData)
})
}

View File

@ -17,8 +17,8 @@
document.addEventListener("DOMContentLoaded", onLoaded);
function onLoaded() {
baseData.id = [[${srcPost.id}]];
baseData.title = [[${srcPost.title}]];
baseData.content = [[${srcPost.content}]];
baseData.title = urldecode([[${srcPost.title}]]);
baseData.content = urldecode([[${srcPost.content}]]);
baseData.firstPostLat = [[${srcPost.firstPostLat}]];
baseData.firstPostLon = [[${srcPost.firstPostLon}]];
baseData.writeTime = [[${srcPost.writeTime}]];
@ -44,26 +44,7 @@
theme:'dark',
usageStatistics : false,
toolbar:null,
initialValue:
"# 제목 " +"\n" +
"평문 사이에 **볼드체** *이탤릭체*"+"\n" +
"~~어디쓰지~~"+"\n" +
"***"+"\n" +
"### 모라모라 " +"\n" +
"> 으흐흠..." +"\n" +
"* 쓸까?" +"\n" +
"1. 첫번째" +"\n" +
"* [x] 체크하자" +"\n" +
"* [ ] 체크하자" +"\n" +
" \|dd\|cc\|ff\|\n" +
" \|\-\-\-\|\-\-\-\|\-\-\-\|\n" +
" \|aa\|s\|s\|" +"\n" +
"[링크다](https://youtube.com)" +"\n" +
"`var test = 'real test'`" +"\n" +
"```\n" +
"let test= = 'real test'\n" +
"```"
,
initialValue:baseData.content,
theme:"dark",
initialEditType:"wysiwyg",
hooks: {

View File

@ -43,7 +43,7 @@
<div class="post_item" th:onclick="goToEditor([[${path}]],[[${post.id}]],[[${SK}]])" >
<span id="postTitle" class="post_attr" th:text="${post.title}"></span>
<div id="content" class="post_attr content" th:attr="data=${post.content}"></div>
<span id="writeDate" class="post_attr" th:text="${#dates.format(post.writeTime, 'dd/MMM/yyyy HH:mm')}"></span>
<span id="writeDate" class="post_attr" th:text="${#dates.format(post.writeTime, 'yyyy.MM.dd HH:mm:ss')}"></span>
<span id="postId" class="post_attr" th:text="${post.id}"></span>
</div>
</th:block>

View File

@ -7,12 +7,15 @@
<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" />
<!-- <link rel="stylesheet" href="https://uicdn.toast.com/editor/latest/toastui-editor-dark.css" />-->
<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() {
baseData.title = urldecode([[${srcPost.title}]]);
baseData.content = urldecode([[${srcPost.content}]]);
var h = document.querySelector('#main_layer').getBoundingClientRect().height + 'px'
editor = new toastui.Editor({
el: document.querySelector('#editor'),
@ -20,26 +23,7 @@
width:'100%',
viewer: true,
usageStatistics : false,
initialValue:
"# 제목 " +"\n" +
"평문 사이에 **볼드체** *이탤릭체*"+"\n" +
"~~어디쓰지~~"+"\n" +
"***"+"\n" +
"### 모라모라 " +"\n" +
"> 으흐흠..." +"\n" +
"* 쓸까?" +"\n" +
"1. 첫번째" +"\n" +
"* [x] 체크하자" +"\n" +
"* [ ] 체크하자" +"\n" +
" \|dd\|cc\|ff\|\n" +
" \|\-\-\-\|\-\-\-\|\-\-\-\|\n" +
" \|aa\|s\|s\|" +"\n" +
"[링크다](https://youtube.com)" +"\n" +
"`var test = 'real test'`" +"\n" +
"```\n" +
"let test= = 'real test'\n" +
"```"
,
initialValue:baseData.content,
theme:"dark",
});
}

View File

@ -4,9 +4,46 @@
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/blog.js}"></script>
<link th:href="@{/css/blog.css}" rel="stylesheet" />
<script type="text/javascript" th:src="@{/js/toast-ui-view.js}"></script>
<link th:href="@{/css/toast-ui-dark.css}" rel="stylesheet" />
<script th:inline="javascript">
let editor
document.addEventListener("DOMContentLoaded", onLoaded);
function onLoaded() {
var els = document.getElementsByClassName('content')
for (i=0;i<els.length;i++) {
var item = $(els[i])
console.log(item[0])
console.log(item.attr("data"))
new toastui.Editor({
el: item[0],
width : (item[0].getBoundingClientRect().width * 0.8) + 'px',
height : (item[0].getBoundingClientRect().width * 0.8) + 'px',
viewer: true,
usageStatistics : false,
initialValue: item.attr("data"),
theme:"dark",
});
}
}
</script>
</th:block>
<th:block layout:fragment="content" id="content">
<div id="main_layer"></div>
<div id="main_layer">
<div class="post_layer">
<th:block class="posts_layer" id="posts" th:each="post : ${Posts}">
<div class="post_item" th:onclick="goToView([[${path}]],[[${post.id}]])" >
<span id="postTitle" class="post_attr" th:text="${post.title}"></span>
<div id="content" class="post_attr content" th:attr="data=${post.content}"></div>
<span id="writeDate" class="post_attr" th:text="${#dates.format(post.writeTime, 'yyyy.MM.dd HH:mm:ss')}"></span>
<span id="postId" class="post_attr" th:text="${post.id}"></span>
</div>
</th:block>
</div>
</div>
</th:block>
</html>

View File

@ -4,17 +4,21 @@
xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout"
layout:decorate="~{layout/default_layout}">
<th:block layout:fragment="head">
<link th:href="@{/css/private.css}" rel="stylesheet" />
</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>
<div id="main_layer">
<div class="layer">
<th:block id="where" th:each="location : ${locations}">
<div class="where_item">
<span th:text="${location.timeString}"> </span>
<span th:text="${location.mAddressLines}"> </span>
<span th:text="${location.mCountryName}"> </span>
<span th:text="${location.mLatitude}"> </span>
<span th:text="${location.mLongitude}"> </span>
</div>
</th:block>
</div>
</div>
</th:block>
</html>

View File

@ -6,11 +6,7 @@
<head>
<title>Spring Boot</title>
<script th:inline="javascript">
function loginClick() {
onclickLogin([[${enc}]],[[${key}]])
}
</script>
<script type="text/javascript" th:src="@{/js/user.js}"></script>
</head>>
<body onload="checkDebug()">
@ -22,7 +18,7 @@
<tr><td><input id="user_id" type="text" class="text"></td></tr>
<tr><td>비밀번호</td></tr>
<tr><td><input id="user_pw" type="password" class="text"></td></tr>
<tr><td><input type="submit" value="로그인" class="btn" onclick="loginClick()"></td></tr>
<tr><td><input type="submit" value="로그인" class="btn" th:onclick="onclickLogin([[${enc}]],[[${key}]])"></td></tr>
</table>
</div>

View File

@ -4,8 +4,8 @@
<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>
<td><h3><a aria-label="licenses" style="color: white" href="../licenses" title="Gmail">licenses</a></h3></td>
<td><h3><a aria-label="sendToMe" style="color: white" href="mailto:lunaticbum@gmail.com" title="Gmail">lunaticbum@gmail.com</a></h3></td>
</tr>
</table>
</footer>

View File

@ -1,12 +1,25 @@
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<html xmlns:th="http://www.thymeleaf.org" xmlns="http://www.w3.org/1999/html">
<th:block th:fragment="header">
<header>
<table >
<tr id="top">
<td><h2><a aria-label="licenses" style="color: white" href="javascript:mainPath()" title="Gmail">HOME</a></h2></td>
</tr>
</table>
<div id="top">
<td><h3><a aria-label="licenses" style="color: white" href="javascript:mainPath()" title="Gmail">HOME</a></h3></td>
</div>
<th:block th:if="${PERMISSION != 'OK'}">
<script th:inline="javascript">
document.addEventListener("DOMContentLoaded", addListen);
function tryLogin() {if(document.getElementById("user_id").value.length > 0 && document.getElementById("user_pw").value.length > 0) {onclickLogin(null,null)}}
function addListen(){document.getElementById("user_id").addEventListener("keyup", ({key}) => {if (key === "Enter")tryLogin()});document.getElementById("user_pw").addEventListener("keyup", ({key}) => {if (key === "Enter")tryLogin()})}
</script>
<div class="user_info" >
<input th:class="login_input" placeholder="ID" enterkeyhint="next" id="user_id" type="text" class="text">
<input th:class="login_input" id="user_pw" placeholder="PW" enterkeyhint="send" type="password" class="text">
</div>
</th:block>
<th:block th:if="${PERMISSION == 'OK'}">
<!-- <div><h2><a aria-label="licenses" style="color: white" href="javascript:gotoLogin()" title="Gmail">HOME</a></h2></div>-->
</th:block>
</header>
</th:block>
</html>