Преглед на файлове

사용자 페이지, 기타 수정

Gayeon Park преди 3 години
родител
ревизия
b1087757bb

+ 74 - 56
realworld/src/main/webapp/WEB-INF/jsp/main.jsp

@@ -26,6 +26,14 @@
             .join('&');
 
     let url = '/article/page?' + query;
+    
+    function selectFeed() {
+        if ("${ssIsLogin}" === 'true') {
+            return 'your-feed'
+        } else {
+            return 'global-feed';
+        }
+    }
 
     // 1. feed를 바꾼 경우
     // 2. 태그를 클릭한 경우
@@ -47,7 +55,7 @@
             } else if (clickedTag !== undefined) { // 태그가 클릭된 경우
                 const tags = article.querySelectorAll('.tag');
                 const tagSet = new Set(Array.from(tags).map(tag => tag.textContent));
-
+                
                 if (targetFeed.id === 'global-feed' && tagSet.has(clickedTag)) {
                     display = 'block';
                 }
@@ -97,6 +105,7 @@
         targetFeed = unFocusedFeed;
         setLoading('on');
 
+        // 태그와 게시글 초기화
         tagArray = [];
         articleList = document.querySelector('#article-list');
         while(articleList.firstChild) {
@@ -104,12 +113,11 @@
         }
 
         params['articleId'] = -1;
-        params['feed'] = unFocusedFeed.id;
+        params['feed'] = targetFeed.id;
 
         query = Object.keys(params)
             .map(key => encodeURIComponent(key) + '=' + encodeURIComponent(params[key]))
             .join('&');
-
         url = '/article/page?' + query;
 
         fetch(url, options)
@@ -119,8 +127,7 @@
                 username = "${ssUsername}";
 
                 loadArticle(articles);
-                document.addEventListener("scroll", nextPageLoad(articles, paging));
-                // nextPageLoad(articles, paging);
+                nextPageLoad(articles, paging);
             });
 
         filterArticle({ 'clickedFeed': unFocusedFeed.id })
@@ -129,63 +136,68 @@
         }, 2000);
     }
 
-    
+    // 좋아요 버튼
     function favoriteBtn(indexNumber) {
         const favoriteNum = event.target.querySelector('.count').textContent;
+        const favorite = event.target.querySelector('.favorite-btn');
         let counts = parseInt(favoriteNum);
         let newCounts = counts + 1;
+        console.log(event.target);
         
-        const favBtn = document.querySelectorAll('.favorite-btn');
+        // 로그인한 경우에만 실행
         if ("${ssIsLogin}" === "true") {
-            favBtn.forEach(value => {
-                if (value.classList.contains(indexNumber)) {
-                    if(event.target.classList.contains('active')){
-                        event.target.querySelector('.count').textContent = counts - 1;
-
-                        fetch('/article/' + indexNumber + '/favorite', { method: 'DELETE' })
-                            .then(response => {
-                                if(response.status === 200) {
-                                return value.classList.remove('active');
-                                }
-                            });
-                    } else {
-                        event.target.querySelector('.count').textContent = newCounts;
-
-                        fetch('/article/'+ indexNumber + '/favorite', {
-                            body: JSON.stringify({
-                                articleId: indexNumber,
-                                userId: "${ssId}",
-                                created: new Date()
-                            }),
-                            method: 'POST',
-                            headers: {
-                                "Content-Type": "application/json"
-                            }
-                        })
-                            .then(response => {
-                                if(response.status === 201){
-                                    return value.classList.add('active');
-                                }
-                            })
+            if (event.target.classList.contains('active')) { // 이미 좋아요 버튼을 클릭한 경우
+                event.target.querySelector('.count').textContent = counts - 1;
+                event.target.classList.remove('active');
+
+                fetch('/article/' + indexNumber + '/favorite', { method: 'DELETE' })
+                    .then(response => {
+                        if (response.status === 200) {
+                            return ;
+                        }
+                    });
+            } else { // 좋아요 버튼을 클릭하지 않을 경우
+                event.target.querySelector('.count').textContent = newCounts;
+                event.target.classList.add('active')
+
+                fetch('/article/' + indexNumber + '/favorite', {
+                    body: JSON.stringify({
+                        articleId: indexNumber,
+                        userId: "${ssId}",
+                        created: new Date()
+                    }),
+                    method: 'POST',
+                    headers: {
+                        "Content-Type": "application/json"
                     }
-                }
-            });
+                })
+                    .then(response => {
+                        if (response.status === 201) {
+                            return ;
+                        }
+                    })
+            }
+            
         } else {
             location.href = "/user/signin"
         }
     }
 
+    // 태그 정렬 https://curryyou.tistory.com/229
     function getSortedArr(array) {
+        // 출현 빈도 구하기
         const counts = array.reduce((pv, cv) => {
             pv[cv] = (pv[cv] || 0) + 1;
             return pv;
         }, {});
 
+        // 배열 생성 => [ [ key: 개수 ], [ key: 개수 ], ...]
         const result = [];
         for (let key in counts) {
             result.push([key, counts[key]]);
         };
 
+        // 빈도별로 정렬
         result.sort((first, second) => {
             return second[1] - first[1];
         });
@@ -193,28 +205,23 @@
         return result.slice(0, 10);
     }
 
+    // 클릭한 태그 표시
     function tagFilter(event) {
         let currentValue = document.querySelector('.tag.active');
+
         if (currentValue !== null) {
-            currentValue.classList.remove('active');
+            currentValue.classList.remove('active');       
         }
         event.target.classList.add('active');
     }
 
-    function selectFeed() {
-            if ("${ssIsLogin}" === 'true') {
-                return 'your-feed'
-            } else {
-                return 'global-feed';
-            }
-    }
-
-    //게시글 표시
+    // 게시글 및 태그 표시
     function loadArticle(articles) { 
         articles.forEach(article => {
             console.log(JSON.stringify(article))
             const domParser = new DOMParser();
-
+            
+            // 게시글 정보 표시
             const domStrArticleMeta =
                 `
                 <div class="article-meta">
@@ -243,6 +250,7 @@
                 divArticleMeta.querySelector('.favorite-btn').classList.add('active');
             }
 
+            // 게시글 내용 및 게시글태그 표시
             const domStrPreviewLink =
                 `
                 <a href="/article/\${article.id}" class="preview-link">
@@ -286,9 +294,8 @@
 
             articleList.appendChild(articlePreview);
 
-            //태그 배열 생성
-            let tagsArray = article.tags.split(',')
-            
+            // 태그 배열 생성
+            let tagsArray = article.tags.split(',')          
             const tagList = document.querySelector('#tag-list');
             
             while(tagList.firstChild) {
@@ -303,7 +310,7 @@
             })
         });
 
-        //태그 정렬
+        // 태그 표시
         const tags = Array.from(tagSet);
         const tagList = window.document.querySelector('#tag-list');
 
@@ -316,6 +323,11 @@
             a.classList.add("tag");
             a.textContent = `\${tagValue} (\${tagCount})`
             a.onclick = (event) => {
+                // 해당 태그의 토글버튼 생성
+                const tagToggle = document.querySelector('#tag-feed');
+                tagToggle.textContent = tagValue;
+                
+                // 해당 태그의 게시물 표시
                 filterArticle({ 'clickedTag': tagValue });
             }
             tagList.appendChild(a);
@@ -329,18 +341,21 @@
             const articleList = document.querySelector('#article-list');
             const loading = document.createElement('div');
 
-            moreButton.textContent = 'More';
+            moreButton.textContent = '더보기';
             moreButton.classList.add('more-button');
             loading.setAttribute('id', 'loading');
             articleList.appendChild(moreButton);
+
+            // more 버튼 클릭 시 다음페이지 게시물을 가져온다
             moreButton.onclick = () => {
                 articleList.removeChild(moreButton);
                 articleList.appendChild(loading);
+
+                // 마지막 게시글의 id
                 params['articleId'] = articles[articles.length - 1].id;
                 query = Object.keys(params)
                         .map(key => encodeURIComponent(key) + '=' + encodeURIComponent(params[key]))
                         .join('&');
-
                 url = '/article/page?' + query;
 
                 fetch(url, options)
@@ -445,6 +460,9 @@
                                 <a href="javascript:void(0);" onclick="focusFeed()">Global
                                     Feed</a>
                             </li>
+                            <li id="tag-feed" class="nav-item">
+                                <a href="javascript:void(0);"></a>
+                            </li>
                         </ul>
                     </div>
 

+ 20 - 1
realworld/src/main/webapp/WEB-INF/jsp/user/settings.jsp

@@ -54,7 +54,26 @@ const submitForm = () => {
         })
 }
 
+// 입력폼 벨리데이션
+const validateForm = () => {
+    const articleTitle = editForm['article-title'].value;
+    if (articleTitle === null || articleTitle === "") {
+        alert("제목을 입력해주세요.");
+        return false;
+    }
+    const subtitle = editForm['subtitle'].value;
+    if (subtitle === null || subtitle === "") {
+        alert("부제목을 입력해주세요.");
+        return false;
+    }
+    const articleBody = editForm['article-body'].value;
+    if (articleBody === null || articleBody === "") {
+        alert("내용을 입력해주세요.");
+        return false;
+    }
 
+    return true;
+}
 
 
 </script>
@@ -120,7 +139,7 @@ const submitForm = () => {
                     <button class="btn-settings" onclick="submitForm()">Update Settings</button>
                 </div>
                 <hr>
-                <button type="button" class="btn-logout" onclick="location.href='/'">Or click here to logout.</button>
+                <button type="button" class="btn-logout" onclick="location.href='/user/logout'">Or click here to logout.</button>
             </form>
         </div>
     </div>

+ 145 - 0
realworld/src/main/webapp/WEB-INF/jsp/user/userInfo.jsp

@@ -0,0 +1,145 @@
+<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
+<%@ taglib uri="http://www.springframework.org/tags/form" prefix="form" %>
+<%@ taglib uri="http://java.sun.com/jsp/jstl/fmt" prefix="fmt" %>
+<%@ taglib uri="http://www.springframework.org/tags" prefix="spring" %>
+<%@ taglib uri="http://java.sun.com/jsp/jstl/functions" prefix="fn" %>
+<%@ page language="java" contentType="text/html;charset=UTF-8" pageEncoding="UTF-8" %>
+
+<jsp:include page="/WEB-INF/jsp/include/head.jsp"></jsp:include>
+<script>
+
+
+</script>
+</head>
+
+<body>
+    <jsp:include page="/WEB-INF/jsp/include/header.jsp"></jsp:include>
+    <!-- user-page content -->
+    <div class="user-page">
+        <!-- User Info -->
+        <section class="user-info">
+            <div class="container">
+                <div class="row">
+                    <div class="col-10">
+                        <img src="img/avatar.jpg" alt="" class="user-img">
+                        <h4 class="user-name">username</h4>
+                        <p class="profile-bio">short bio</p>
+                        <a href="settings.html" class="action-btn btn-sm">
+                            <i class="fas fa-cog"></i> Edit Profile Settings
+                        </a>
+                    </div>
+                </div>
+            </div>
+        </section>
+        <!-- Body -->
+        <div class="container main">
+            <div class="row">
+                <div class="col-10">
+                    <!-- 토글 버튼으로 피드 내용 보기 -->
+                    <div class="toggle">
+                        <ul class="nav">
+                            <li class="nav-item active">
+                                <a href="#">My Articles</a>
+                            </li>
+                            <li class="nav-item">
+                                <a href="userpage-favorited.html">Favorited Articles</a>
+                            </li>
+                        </ul>
+                    </div>
+                    <div class="article">
+                        <article class="article-preview">
+                            <div class="article-meta">
+                                <div class="metadata">
+                                    <a href="#" class="profile-link">
+                                        <img src="img/avatar.jpg" alt="">
+                                    </a>
+                                    <div class="article-info">
+                                        <a href="#" class="name">username</a>
+                                        <span class=date>November 24, 2021</span>
+                                    </div>
+                                </div>
+                                <div>
+                                    <button class="favorite-btn">
+                                        <i class="fas fa-heart"></i>
+                                        <span class="count">564</span>
+                                    </button>
+                                </div>
+                            </div>
+                            <a href="article-my.html" class="preview-link">
+                                <h1 class="preview-title">Create a new implementation</h1>
+                                <p>join the community by creating a new implementation</p>
+                                <div class="tag-data">
+                                    <span>Read more...</span>
+                                    <ul class="tag-list">
+                                        <li class="tag">implementations</li>
+                                        <li class="tag">implementations</li>
+                                    </ul>
+                                </div>
+                            </a>
+                        </article>
+                        <article class="article-preview">
+                            <div class="article-meta">
+                                <div class="metadata">
+                                    <a href="#" class="profile-link">
+                                        <img src="img/avatar.jpg" alt="">
+                                    </a>
+                                    <div class="article-info">
+                                        <a href="#" class="name">username</a>
+                                        <span class=date>November 24, 2021</span>
+                                    </div>
+                                </div>
+                                <div>
+                                    <button class="favorite-btn">
+                                        <i class="fas fa-heart"></i>
+                                        <span class="count">564</span>
+                                    </button>
+                                </div>
+                            </div>
+                            <a href="article-my.html" class="preview-link">
+                                <h1 class="preview-title">Create a new implementation</h1>
+                                <p>join the community by creating a new implementation</p>
+                                <div class="tag-data">
+                                    <span>Read more...</span>
+                                    <ul class="tag-list">
+                                        <li class="tag">implementations</li>
+                                    </ul>
+                                </div>
+                            </a>
+                        </article>
+                        <article class="article-preview">
+                            <div class="article-meta">
+                                <div class="metadata">
+                                    <a href="#" class="profile-link">
+                                        <img src="img/avatar.jpg" alt="">
+                                    </a>
+                                    <div class="article-info">
+                                        <a href="#" class="name">username</a>
+                                        <span class=date>November 24, 2021</span>
+                                    </div>
+                                </div>
+                                <div>
+                                    <button class="favorite-btn">
+                                        <i class="fas fa-heart"></i>
+                                        <span class="count">564</span>
+                                    </button>
+                                </div>
+                            </div>
+                            <a href="article-my.html" class="preview-link">
+                                <h1 class="preview-title">Create a new implementation</h1>
+                                <p>join the community by creating a new implementation</p>
+                                <div class="tag-data">
+                                    <span>Read more...</span>
+                                    <ul class="tag-list">
+                                        <li class="tag">implementations</li>
+                                    </ul>
+                                </div>
+                            </a>
+                        </article>
+                    </div>
+                </div>
+            </div>
+        </div>
+    </div>
+</body>
+
+</html>

+ 5 - 0
realworld/src/main/webapp/resources/css/style.css

@@ -216,6 +216,7 @@ button {
     float: left;
     padding: 0.5rem 1rem;
     margin-bottom: -1px;
+    color: var(--light-grey-color);
 }
 
 .toggle .nav .nav-item a {
@@ -384,6 +385,10 @@ img {
     background-color: #646d74;
 }
 
+.home-page .aside .tag-list .tag.active {
+    text-decoration: underline;
+}
+
 .home-page #article-list .more-button {
     float: right;
     margin-top: 0.6rem;