Browse Source

기타 수정

Gayeon Park 3 years ago
parent
commit
1de6682a8e

+ 163 - 116
realworld/src/main/webapp/WEB-INF/jsp/main.jsp

@@ -13,33 +13,30 @@
     let ssIsLogin = null;
     let targetFeed = null;
     let username = null;
-    const options = { method: 'GET' };
+    const options = {
+        method: 'GET'
+    };
     const tagSet = new Set();
     let tagArray = [];
+    // fetch url info
+    const selectFeed = ("${ssIsLogin}" === "true") ? 'your-feed' : 'flobal-feed';
     let params = {
-            articleId: -1,
-            feed: selectFeed()
-        };
-    
+        articleId: -1,
+        feed: selectFeed
+    };
     let query = Object.keys(params)
-            .map(key => encodeURIComponent(key) + '=' + encodeURIComponent(params[key]))
-            .join('&');
-
+        .map(key => encodeURIComponent(key) + '=' + encodeURIComponent(params[key]))
+        .join('&');
     let url = '/article/page?' + query;
-    
-    function selectFeed() {
-        if ("${ssIsLogin}" === 'true') {
-            return 'your-feed'
-        } else {
-            return 'global-feed';
-        }
-    }
 
     // 1. feed를 바꾼 경우
     // 2. 태그를 클릭한 경우
     const filterArticle = (option) => {
-        const { clickedTag, clickedFeed } = option;
-        const articles = window.document.querySelectorAll('.article-preview'); 
+        const {
+            clickedTag,
+            clickedFeed
+        } = option;
+        const articles = window.document.querySelectorAll('.article-preview');
         const articleList = document.querySelector('#article-list');
 
         articles.forEach(article => {
@@ -55,12 +52,8 @@
             } 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';
-                }
 
-                if (targetFeed.id === 'your-feed' && username === writerName && tagSet.has(clickedTag)) {
+                if (tagSet.has(clickedTag)) {
                     display = 'block';
                 }
             }
@@ -87,6 +80,22 @@
         tagList.style.display = contentDisplay;
     }
 
+    // 자신의 게시글이 없는 경우
+    const noContent = () => {
+        articleList = document.querySelector('#article-list');
+        tagList = document.querySelector('#tag-list');
+
+        if (articleList.firstChild === null) {
+            const p = document.createElement('p');
+            const pTag = document.createElement('p');
+
+            p.classList.add('article-preview');
+            p.textContent = 'No articles are here... yet.';
+            pTag.textContent = 'No tags are here... yet.';
+            articleList.appendChild(p);
+            tagList.appendChild(pTag);
+        }
+    }
 
     const focusFeed = () => {
         // 이미 포커싱된 탭이라면 중지
@@ -96,10 +105,23 @@
         }
 
         const unFocusedFeed = parentNode;
-        const currentFeed = (unFocusedFeed.id === 'global-feed') ? window.document.querySelector('#your-feed') : window.document.querySelector('#global-feed');
+        const currentFeed = (unFocusedFeed.id === 'global-feed') ? window.document.querySelector('#your-feed') :
+            window.document.querySelector('#global-feed');
 
         unFocusedFeed.classList.add('active');
-        currentFeed.classList.remove('active');
+        if ("${ssIsLogin}" === "true") {
+            currentFeed.classList.remove('active');
+        }
+
+
+        // your-feed 또는 global-feed 클릭시 tag-feed 없애기
+        const tagToggle = document.querySelector('#tag-feed');
+        const spanTag = document.querySelector('#tag-feed span');
+        if (tagToggle.classList.contains('active')) {
+            tagToggle.classList.remove('active');
+            spanTag.textContent = null;
+            document.querySelector('.fa-hashtag').style.display = 'none';
+        }
 
         // targetFeed 초기화
         targetFeed = unFocusedFeed;
@@ -108,83 +130,92 @@
         // 태그와 게시글 초기화
         tagArray = [];
         articleList = document.querySelector('#article-list');
-        while(articleList.firstChild) {
+        while (articleList.firstChild) {
             articleList.firstChild.remove();
         }
 
-        params['articleId'] = -1;
-        params['feed'] = targetFeed.id;
-
+        params = {
+            articleId: -1,
+            feed: targetFeed.id
+        };
         query = Object.keys(params)
-            .map(key => encodeURIComponent(key) + '=' + encodeURIComponent(params[key]))
-            .join('&');
+                .map(key => encodeURIComponent(key) + '=' + encodeURIComponent(params[key]))
+                .join('&');
         url = '/article/page?' + query;
 
         fetch(url, options)
             .then(response => response.json())
             .then(json => {
-                const { articles, paging } = json;
+                const {
+                    articles,
+                    paging
+                } = json;
                 username = "${ssUsername}";
 
                 loadArticle(articles);
                 nextPageLoad(articles, paging);
+                console.log(tagArray);
             });
 
-        filterArticle({ 'clickedFeed': unFocusedFeed.id })
+        filterArticle({
+            'clickedFeed': unFocusedFeed.id
+        })
         setTimeout(() => {
             setLoading('off');
+            noContent();
         }, 2000);
     }
 
     // 좋아요 버튼
-    function favoriteBtn(indexNumber) {
+    const 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);
-        
+
         // 로그인한 경우에만 실행
         if ("${ssIsLogin}" === "true") {
             if (event.target.classList.contains('active')) { // 이미 좋아요 버튼을 클릭한 경우
                 event.target.querySelector('.count').textContent = counts - 1;
                 event.target.classList.remove('active');
 
-                fetch('/article/' + indexNumber + '/favorite', { method: 'DELETE' })
+                fetch('/article/' + indexNumber + '/favorite', {
+                        method: 'DELETE'
+                    })
                     .then(response => {
                         if (response.status === 200) {
-                            return ;
+                            return;
                         }
                     });
-            } else { // 좋아요 버튼을 클릭하지 않 경우
+            } else { // 좋아요 버튼을 클릭하지 않 경우
                 event.target.querySelector('.count').textContent = newCounts;
-                event.target.classList.add('active')
+                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"
-                    }
-                })
+                        body: JSON.stringify({
+                            articleId: indexNumber,
+                            userId: "${ssId}",
+                            created: new Date()
+                        }),
+                        method: 'POST',
+                        headers: {
+                            "Content-Type": "application/json"
+                        }
+                    })
                     .then(response => {
                         if (response.status === 201) {
-                            return ;
+                            return;
                         }
                     })
             }
-            
+
         } else {
             location.href = "/user/signin"
         }
     }
 
     // 태그 정렬 https://curryyou.tistory.com/229
-    function getSortedArr(array) {
+    const getSortedArr = (array) => {
         // 출현 빈도 구하기
         const counts = array.reduce((pv, cv) => {
             pv[cv] = (pv[cv] || 0) + 1;
@@ -202,51 +233,54 @@
             return second[1] - first[1];
         });
 
+        // 최대 10개까지만 표시
         return result.slice(0, 10);
     }
 
-    // 클릭한 태그 표시
-    function tagFilter(event) {
+    // 현재 클릭한 태그 표시
+    const focusTag = () => {
         let currentValue = document.querySelector('.tag.active');
 
         if (currentValue !== null) {
-            currentValue.classList.remove('active');       
+            currentValue.classList.remove('active');
         }
         event.target.classList.add('active');
     }
 
     // 게시글 및 태그 표시
-    function loadArticle(articles) { 
+    const loadArticle = (articles) => {
         articles.forEach(article => {
             console.log(JSON.stringify(article))
             const domParser = new DOMParser();
-            
+
             // 게시글 정보 표시
             const domStrArticleMeta =
                 `
                 <div class="article-meta">
                     <div class="metadata">
-                        <a href="#" class="profile-link">
+                        <a href="/user/\${article.writerId}" class="profile-link">
                             <img src="/resources/images/avatar.png" alt="avatar">
                         </a>
                         <div class="article-info">
-                            <a href="#" class="name"></a>
+                            <a href="/user/\${article.writerId}" class="name"></a>
                             <span class="date"></span>
                         </div>
                     </div>
                     <div>
-                        <button class="favorite-btn \${article.id}" onclick="favoriteBtn(\${article.id})">
+                        <button class="favorite-btn" onclick="favoriteBtn(\${article.id})">
                             <i class="fas fa-heart"></i>
                             <span class="count">\${article.favoriteNum}</span>
                         </button>
                     </div>
                 </div>
                 `;
-            const divArticleMeta = domParser.parseFromString(domStrArticleMeta, 'text/html').body.firstChild;
+            const divArticleMeta = domParser.parseFromString(domStrArticleMeta, 'text/html').body
+                .firstChild;
             divArticleMeta.querySelector('.name').textContent = article.writerName;
             divArticleMeta.querySelector('.date').textContent = new Date(article.created).toLocaleString();
-            
-            if(article.favorite) {
+
+            // 좋아요한 게시글의 경우
+            if (article.favorite) {
                 divArticleMeta.querySelector('.favorite-btn').classList.add('active');
             }
 
@@ -294,26 +328,27 @@
 
             articleList.appendChild(articlePreview);
 
-            // 태그 배열 생성
-            let tagsArray = article.tags.split(',')          
+            // Popular tag 배열 생성
+            let tagsArray = article.tags.split(',');
             const tagList = document.querySelector('#tag-list');
-            
-            while(tagList.firstChild) {
+
+            while (tagList.firstChild) {
                 tagList.firstChild.remove();
             }
 
             tagsArray.forEach(tag => {
-                
+
                 if (tag !== '') {
                     tagArray.push(tag);
                 }
             })
         });
 
-        // 태그 표시
+
         const tags = Array.from(tagSet);
         const tagList = window.document.querySelector('#tag-list');
 
+        // Popular tag 표시
         getSortedArr(tagArray).forEach(tag => {
             const a = document.createElement('a');
             const tagString = tag.join(',');
@@ -323,19 +358,40 @@
             a.classList.add("tag");
             a.textContent = `\${tagValue} (\${tagCount})`
             a.onclick = (event) => {
-                // 해당 태그의 토글버튼 생성
                 const tagToggle = document.querySelector('#tag-feed');
-                tagToggle.textContent = tagValue;
-                
+                const yourToggle = document.querySelector('#your-feed');
+                const globalToggle = document.querySelector('#global-feed');
+                const moreBtn = document.querySelector('.more-button');
+                const spanTag = document.querySelector('#tag-feed span');
+
                 // 해당 태그의 게시물 표시
-                filterArticle({ 'clickedTag': tagValue });
+                filterArticle({
+                    'clickedTag': tagValue
+                });
+
+                // 해당 태그의 토글버튼 생성
+                document.querySelector('.fa-hashtag').style.display = 'block';
+                spanTag.textContent = '\u00A0' + tagValue;
+                tagToggle.classList.add('active');
+                globalToggle.classList.remove('active');
+
+                // 로그인한 경우에만 your-feed가 생기므로 조건문 처리
+                if ("${ssIsLogin}" === "true") {
+                    yourToggle.classList.remove('active');
+                }
+
+                // more 버튼 삭제
+                if (moreBtn !== null) {
+                    moreBtn.remove();
+                }
             }
             tagList.appendChild(a);
         });
     }
 
-    //다음페이지 로드
-    function nextPageLoad(articles, paging) {
+    // 다음페이지 로드
+    const nextPageLoad = (articles, paging) => {
+        // 더 조회될 수 있는 게시글이 있는지 여부
         if (paging.isNext) {
             const moreButton = document.createElement('button');
             const articleList = document.querySelector('#article-list');
@@ -349,9 +405,9 @@
             // more 버튼 클릭 시 다음페이지 게시물을 가져온다
             moreButton.onclick = () => {
                 articleList.removeChild(moreButton);
-                articleList.appendChild(loading);
+                articleList.appendChild(loading); // 로딩 생성
 
-                // 마지막 게시글 id
+                // 현재 페이지의 마지막 게시글 id
                 params['articleId'] = articles[articles.length - 1].id;
                 query = Object.keys(params)
                         .map(key => encodeURIComponent(key) + '=' + encodeURIComponent(params[key]))
@@ -361,12 +417,16 @@
                 fetch(url, options)
                     .then(response => response.json())
                     .then(json => {
-                        const { articles, paging } = json;
+                        const {
+                            articles,
+                            paging
+                        } = json;
                         username = "${ssUsername}";
-                        articleList.removeChild(loading);
-                        loadArticle(articles);
-                        nextPageLoad(articles, paging);
-                        
+                        setTimeout(() => {
+                            articleList.removeChild(loading);
+                            loadArticle(articles);
+                            nextPageLoad(articles, paging);
+                        }, 1000);
                     })
             }
         }
@@ -376,7 +436,8 @@
 
         ssIsLogin = "${ssIsLogin}";
 
-        targetFeed = (ssIsLogin === "true") ? window.document.querySelector('#your-feed') : window.document.querySelector('#global-feed');
+        targetFeed = (ssIsLogin === "true") ? window.document.querySelector('#your-feed') : window.document
+            .querySelector('#global-feed');
         targetFeed.classList.add('active');
 
         loadingTag = window.document.querySelector('#tag-loading');
@@ -385,43 +446,28 @@
         noTag = window.document.querySelector('#no-tag');
         tagList = window.document.querySelector('#tag-list');
 
-        //fetch api call       
-        let params = {
-            articleId: -1,
-            feed: selectFeed()
-        };
-        let query = Object.keys(params)
-                    .map(key => encodeURIComponent(key) + '=' + encodeURIComponent(params[key]))
-                    .join('&');
-        let url = '/article/page?' + query;
-
         setLoading('on');
-
+        //fetch api call 
         fetch(url, options)
             .then(response => response.json())
             .then(json => {
-                const { articles, paging } = json;
+                const {
+                    articles,
+                    paging
+                } = json;
                 username = "${ssUsername}";
 
                 loadArticle(articles);
                 nextPageLoad(articles, paging);
-            
+                console.log(articles)
+
                 // hide loadings
-                setLoading('off');
-
-                
-                // loadingTag.style.display = 'none';
-                // loadingArticle.style.display = 'none';
-
-                // // show articles and tags
-                // articleList.style.display = 'block';
-                // if (tagSet.size === 0) {
-                //     noTag.style.display = 'block';
-                // } else {
-                //     tagList.style.display = 'block';
-                // }
+                setTimeout(() => {
+                    setLoading('off');
+                    noContent();
+                }, 2000);
             });
-    } 
+    }
 </script>
 <style>
 
@@ -461,7 +507,10 @@
                                     Feed</a>
                             </li>
                             <li id="tag-feed" class="nav-item">
-                                <a href="javascript:void(0);"></a>
+                                <a href="javascript:void(0);">
+                                    <i class="fas fa-hashtag" style="display: none;"></i>
+                                    <span></span>
+                                </a>
                             </li>
                         </ul>
                     </div>
@@ -474,9 +523,7 @@
                         </article>
 
                         <!-- article list -->
-                        <div id="article-list" style="display: none;">
-                            <!-- <article class="noArticle" style="display: none;">Feed not here yet.</article> -->
-                        </div>
+                        <div id="article-list" style="display: none;"></div>
                     </div>
                 </div>
 
@@ -490,7 +537,7 @@
                         </div>
 
                         <!-- 태그 -->
-                        <div id="tag-list" class="tag-list" style="display: none;" onclick="tagFilter(event)">
+                        <div id="tag-list" class="tag-list" style="display: none;" onclick="focusTag()">
                         </div>
                     </div>
                 </div>

+ 8 - 6
realworld/src/main/webapp/resources/css/style.css

@@ -208,7 +208,6 @@ button {
 
 .toggle .nav {
     overflow: hidden;
-    /* border-bottom: 1px solid rgb(0, 0, 0, 0.2); */
     margin-bottom: -1px;
 }
 
@@ -254,9 +253,10 @@ button {
     clear: both;
 }
 
-.article-preview, #article-loading, .noArticle {
+.article-preview, #article-loading {
     border-top: 1px solid rgb(0, 0, 0, 0.2);
     padding: 1.5rem 0;
+    text-align: start;
 }
 
 .article-preview .article-meta {
@@ -402,16 +402,18 @@ img {
     font-weight: 600;
 }
 
-/* .home-page #article-list .more-button:hover {
-    background-color: #dddddd;
-} */
+.home-page #article-list {
+    text-align: center;
+}
 
+/* 로딩 애니메이션 https://codepen.io/mandelid/pen/vwKoe */
 #loading {
     display: inline-block;
     position: absolute;
-    left: 33%;
     width: 50px;
     height: 50px;
+    margin-left: -25px;
+    padding-bottom: 2rem;
     border: 3px solid rgba(255,255,255, 0.1);
     border-radius: 50%;
     border-top-color: #aaa;