2024-10-05 19:42:29 +09:00
<!DOCTYPE html>
2024-10-23 10:07:45 +09:00
< html
xmlns:th = "http://www.thymeleaf.org"
xmlns:layout = "http://www.ultraq.net.nz/thymeleaf/layout"
2025-08-04 16:35:49 +09:00
xmlns:sec = "http://www.thymeleaf.org/extras/spring-security"
2024-10-23 10:07:45 +09:00
layout:decorate = "~{layout/default_layout}" >
< th:block layout:fragment = "content" id = "content" >
2025-09-12 16:55:21 +09:00
< section id = "banner"
2025-09-16 18:42:55 +09:00
th:styleappend = "${randomBannerImage != null} ? |background-image: url('${apiBaseUrl}${randomBannerImage}');| : ''" >
2025-09-24 17:29:33 +09:00
< header th:if = "${gibberish != null}" >
< h2 > Bum's Gibberish: < em > [[${gibberish}]]</ em ></ h2 >
< a th:href = "@{/blog/viewer/{id}(id=${gibberishId})}" class = "button" > 코멘트 남기기< br > [Leave a Comment]</ a >
</ header >
< header th:if = "${gibberish == null}" >
2025-03-11 17:44:21 +09:00
< h2 > Bum's: < em > 짧은 헛소리 혹은 기사?! 링크 있으면 링크까지</ a ></ em ></ h2 >
2025-03-19 18:27:39 +09:00
< a href = "#" class = "button" > 더 읽으쉴?!< br > [Read More Gibberish]</ a >
2025-03-11 17:44:21 +09:00
</ header >
</ section >
2024-10-25 18:28:25 +09:00
2025-09-23 17:37:22 +09:00
<!-- <section class="wrapper style2">-->
<!-- <div class="container">-->
<!-- <header class="major">-->
<!-- <h2>A gigantic heading you can use for whatever</h2>-->
<!-- <p>With a much smaller subtitle hanging out just below it</p>-->
<!-- </header>-->
<!-- </div>-->
<!-- </section>-->
<!-- <section id="cta2" class="wrapper style3">-->
<!-- <div class="container">-->
<!-- <header>-->
<!-- <h2>Are you ready to continue your quest?</h2>-->
<!-- </header>-->
<!-- </div>-->
<!-- </section>-->
2025-09-12 16:55:21 +09:00
< section class = "wrapper style1" >
2025-03-11 17:44:21 +09:00
< div class = "container" >
2025-12-26 17:31:21 +09:00
< article id = "feed-container" >
< section th:each = "item, iterStat : ${feedItems}" class = "feed-item" >
2025-09-12 16:55:21 +09:00
2025-12-26 17:31:21 +09:00
< div th:if = "${item.type.name() == 'POST'}" class = "box post"
th:onclick = "|location.href='@{${item.url}}'|" style = "cursor: pointer;" >
< span class = "image left" >
< img th:if = "${item.thumbnail}" th:src = "${apiBaseUrl + item.thumbnail}"
alt = "Thumbnail" th:onerror = "|this.onerror=null; this.src='@{/images/pic01.jpg}';|" />
< img th:unless = "${item.thumbnail}" th:src = "@{/images/pic01.jpg}" alt = "Default Thumbnail" />
</ span >
< div class = "inner" >
< h3 th:text = "${item.title}" > 제목</ h3 >
< p style = "font-size: 0.9em; color: #555; margin-bottom: 0.5em;"
th:text = "${#dates.format(new java.util.Date(item.createdAt), 'yyyy-MM-dd HH:mm')} + ' by ' + ${item.writer}" ></ p >
< p th:text = "${#strings.abbreviate(item.content, 150)}" > 내용 요약</ p >
</ div >
2025-03-11 17:44:21 +09:00
</ div >
2025-12-26 17:31:21 +09:00
< div th:if = "${item.type.name() == 'GIBBERISH'}" class = "box post gibberish-card"
th:onclick = "|location.href='@{${item.url}}'|"
style = "cursor: pointer; background-color: #fff9c4; border-left: 5px solid #fbc02d;" >
< div class = "inner" >
< blockquote >
< i class = "icon fa-quote-left" style = "color:#fbc02d; margin-right:10px;" ></ i >
< span th:text = "${item.content}" style = "font-size: 1.1em; font-weight: bold; color: #333;" ></ span >
< i class = "icon fa-quote-right" style = "color:#fbc02d; margin-left:10px;" ></ i >
</ blockquote >
< p style = "text-align: right; font-size: 0.8em; color: #777; margin-top: 10px;"
th:text = "${#dates.format(new java.util.Date(item.createdAt), 'yyyy-MM-dd HH:mm')}" ></ p >
</ div >
</ div >
< div th:if = "${item.type.name() == 'BOOKMARK'}" class = "box post bookmark-card"
style = "border: 1px dashed #3498db;" >
< div class = "inner" style = "display: flex; align-items: center;" >
< div style = "flex-shrink: 0; margin-right: 20px;" th:if = "${item.thumbnail}" >
< img th:src = "${apiBaseUrl + item.thumbnail}"
style = "width: 100px; height: 100px; object-fit: cover; border-radius: 5px;" />
</ div >
< div style = "flex-grow: 1;" >
< h4 >
< a th:href = "${item.url}" target = "_blank" style = "text-decoration: none; color: #3498db;" >
< i class = "icon solid fa-bookmark" ></ i > < span th:text = "${item.title}" > 북마크 제목</ span >
< i class = "icon solid fa-external-link-alt" style = "font-size: 0.7em;" ></ i >
</ a >
</ h4 >
< p th:if = "${item.content}" th:text = "${item.content}" style = "font-size: 0.9em; color: #666; margin-bottom: 0.5em;" ></ p >
< p style = "font-size: 0.8em; color: #999;" >
Saved on < span th:text = "${#dates.format(new java.util.Date(item.createdAt), 'yyyy-MM-dd')}" ></ span >
</ p >
</ div >
</ div >
</ div >
< div th:if = "${iterStat.count % 3 == 0}" class = "box ad-container" style = "padding: 1em; text-align: center; margin-bottom: 2em; background: #f4f4f4;" >
< span style = "font-size: 0.8em; color: #aaa;" > - Advertisement -</ span >
< ins class = "adsbygoogle"
style = "display:block"
data-ad-client = "ca-pub-9504446465764716"
data-ad-slot = "5334609005"
data-ad-format = "auto"
data-full-width-responsive = "true" ></ ins >
< script >( adsbygoogle = window . adsbygoogle || []). push ({});</ script >
</ div >
</ section >
</ article >
< div id = "load-more-container" style = "text-align: center; margin-top: 2em; margin-bottom: 2em;" >
< button id = "btn-load-more" class = "button alt"
th:if = "${nextCursor != null}"
th:data-cursor = "${nextCursor}"
onclick = "loadMoreFeed()" >
More Stories < i class = "icon solid fa-chevron-down" ></ i >
</ button >
< div id = "loading-spinner" style = "display:none;" >
< i class = "icon solid fa-spinner fa-spin fa-2x" ></ i >
2025-09-12 16:55:21 +09:00
</ div >
2025-03-11 17:44:21 +09:00
</ div >
</ div >
</ section >
< section class = "wrapper style1" >
< div class = "container" >
< div class = "row gtr-200" >
< section class = "col-4 col-12-narrower" >
< div class = "box highlight" >
< i class = "icon solid major fa-paper-plane" ></ i >
< h3 > This Is Important</ h3 >
< p > Duis neque nisi, dapibus sed mattis et quis, nibh. Sed et dapibus nisl amet mattis, sed a rutrum accumsan sed. Suspendisse eu.</ p >
</ div >
</ section >
< section class = "col-4 col-12-narrower" >
2025-09-05 18:02:27 +09:00
2025-08-04 16:35:49 +09:00
< div class = "box highlight" sec:authorize = "isAuthenticated()" onclick = gotoWrite() >
2025-03-21 17:15:55 +09:00
< i class = "icon solid major fa-pencil-alt" ></ i >
< h3 > 글쓰기[Writing]</ h3 >
< p > 오직 주인장 만의 권한 임요. 그냥 내가 쓰기 편하게 여기 놔둔 메뉴임. 님들은 못씀요.< br > [Only the owner has the authority. This is just a menu that I put here for my convenience. You can't use it.]</ p >
</ div >
2025-09-05 18:02:27 +09:00
< div class = "box highlight open-login-popup" sec:authorize = "isAnonymous()" to = "#loginPopup" style = "cursor: pointer;" >
2025-03-11 17:44:21 +09:00
< i class = "icon solid major fa-pencil-alt" ></ i >
< h3 > 글쓰기[Writing]</ h3 >
2025-03-12 22:35:13 +09:00
< p > 오직 주인장 만의 권한 임요. 그냥 내가 쓰기 편하게 여기 놔둔 메뉴임. 님들은 못씀요.< br > [Only the owner has the authority. This is just a menu that I put here for my convenience. You can't use it.]</ p >
2025-03-11 17:44:21 +09:00
</ div >
</ section >
< section class = "col-4 col-12-narrower" >
< div class = "box highlight" >
< i class = "icon solid major fa-wrench" ></ i >
< h3 > Probably Important</ h3 >
< p > Duis neque nisi, dapibus sed mattis et quis, nibh. Sed et dapibus nisl amet mattis, sed a rutrum accumsan sed. Suspendisse eu.</ p >
</ div >
</ section >
</ div >
</ div >
</ section >
2025-09-24 17:29:33 +09:00
< section class = "wrapper style1" sec:authorize = "isAuthenticated()" >
< div class = "container" >
< div id = "gibberish-form" class = "box post" >
< h4 > 오늘의 Gibberish 남기기 (100자 이내)</ h4 >
< textarea id = "gibberish-content" rows = "3" maxlength = "100" placeholder = "문득 떠오른 생각을 적어보세요..." ></ textarea >
< button class = "button" style = "margin-top: 1em;" onclick = "submitGibberish()" > 등록</ button >
</ div >
</ div >
</ section >
2025-03-19 18:27:39 +09:00
< section id = "cta2" class = "wrapper style3" >
2025-03-11 17:44:21 +09:00
< div class = "container" >
< header >
2025-09-24 17:29:33 +09:00
<!-- <h2>Are you ready to continue your quest?</h2>-->
2025-03-11 17:44:21 +09:00
</ header >
</ div >
</ section >
2025-12-26 17:31:21 +09:00
< script th:inline = "javascript" >
const apiBaseUrl = /*[[${apiBaseUrl}]]*/ '' ; // Thymeleaf 변수 바인딩
function loadMoreFeed () {
const btn = document . getElementById ( 'btn-load-more' );
const spinner = document . getElementById ( 'loading-spinner' );
const container = document . getElementById ( 'feed-container' );
// 현재 커서 값 가져오기
const cursor = btn . getAttribute ( 'data-cursor' );
if ( ! cursor ) return ;
// UI 상태 변경 (로딩 중)
btn . style . display = 'none' ;
spinner . style . display = 'inline-block' ;
// API 호출
fetch ( `/api/feed?cursor= ${ cursor } ` )
. then ( response => response . json ())
. then ( data => {
// 데이터가 없으면 버튼 숨기고 종료
if ( ! data . items || data . items . length === 0 ) {
spinner . style . display = 'none' ;
return ;
}
// 받아온 데이터를 HTML로 변환하여 추가
data . items . forEach ( item => {
const html = createFeedItemHtml ( item );
// section 태그로 감싸서 추가
const section = document . createElement ( 'section' );
section . className = 'feed-item' ;
section . innerHTML = html ;
container . appendChild ( section );
});
// 다음 커서 업데이트
if ( data . nextCursor ) {
btn . setAttribute ( 'data-cursor' , data . nextCursor );
btn . style . display = 'inline-block' ;
} else {
// 더 이상 불러올 게 없으면 버튼 제거
btn . remove ();
}
})
. catch ( err => {
console . error ( 'Feed load error:' , err );
alert ( '추가 콘텐츠를 불러오는 중 오류가 발생했습니다.' );
btn . style . display = 'inline-block' ;
})
. finally (() => {
spinner . style . display = 'none' ;
});
}
// JSON 데이터를 HTML 문자열로 변환하는 헬퍼 함수
function createFeedItemHtml ( item ) {
const dateStr = new Date ( item . createdAt ). toISOString (). split ( 'T' )[ 0 ];
if ( item . type === 'POST' ) {
const thumbSrc = item . thumbnail ? ( apiBaseUrl + item . thumbnail ) : '/images/pic01.jpg' ;
return `
<div class="box post" onclick="location.href=' ${ item . url } '" style="cursor: pointer;">
<span class="image left"><img src=" ${ thumbSrc } " onerror="this.onerror=null; this.src='/images/pic01.jpg';" /></span>
<div class="inner">
<h3> ${ item . title || 'Untitled' } </h3>
<p style="font-size: 0.9em; color: #555; margin-bottom: 0.5em;"> ${ dateStr } by ${ item . writer || 'Bum' } </p>
<p> ${ item . content ? item . content . substring ( 0 , 150 ) + '...' : '' } </p>
</div>
</div>` ;
}
else if ( item . type === 'GIBBERISH' ) {
return `
<div class="box post gibberish-card" onclick="location.href=' ${ item . url } '"
style="cursor: pointer; background-color: #fff9c4; border-left: 5px solid #fbc02d;">
<div class="inner">
<blockquote>
<i class="icon fa-quote-left" style="color:#fbc02d; margin-right:10px;"></i>
<span style="font-size: 1.1em; font-weight: bold; color: #333;"> ${ item . content } </span>
</blockquote>
<p style="text-align: right; font-size: 0.8em; color: #777;"> ${ dateStr } </p>
</div>
</div>` ;
}
else if ( item . type === 'BOOKMARK' ) {
const thumbImg = item . thumbnail ?
`<div style="flex-shrink: 0; margin-right: 20px;"><img src=" ${ apiBaseUrl + item . thumbnail } " style="width: 100px; height: 100px; object-fit: cover; border-radius: 5px;" /></div>` : '' ;
return `
<div class="box post bookmark-card" style="border: 1px dashed #3498db;">
<div class="inner" style="display: flex; align-items: center;">
${ thumbImg }
<div style="flex-grow: 1;">
<h4>
<a href=" ${ item . url } " target="_blank" style="text-decoration: none; color: #3498db;">
<i class="icon solid fa-bookmark"></i> ${ item . title }
<i class="icon solid fa-external-link-alt" style="font-size: 0.7em;"></i>
</a>
</h4>
<p style="font-size: 0.9em; color: #666; margin-bottom: 0.5em;"> ${ item . content || '' } </p>
<p style="font-size: 0.8em; color: #999;">Saved on ${ dateStr } </p>
</div>
</div>
</div>` ;
}
return '' ;
}
</ script >
2024-10-23 10:07:45 +09:00
</ th:block >
2025-09-12 16:55:21 +09:00
</ html >