Explorar o código

기타 수정

Gayeon Park %!s(int64=3) %!d(string=hai) anos
pai
achega
32406818cb

+ 1 - 1
realworld/src/main/resources/mybatis/mapper/user/ArticleMapper.xml

@@ -104,9 +104,9 @@
         <if test='feed == "your-feed"'>
           <![CDATA[
             WHERE     AR.user_id = #{userId}
-            GROUP BY  AR.user_id
           ]]>
         </if>
+            <!-- GROUP BY  AR.user_id -->
      </select>
 
 

+ 27 - 15
realworld/src/main/webapp/WEB-INF/jsp/article/articleDetails.jsp

@@ -13,12 +13,13 @@
     const favorite = 'Favorite Article';
     const unfavorite = 'Unfavorite Article';
 
+    // 사용자 팔로우
     function userFollow() {
         const followBtn = document.querySelectorAll('.follow-btn');
 
-        if ("${ssIsLogin}" === "true") {
+        if ("${ssIsLogin}" === "true") { // 로그인한 경우에만 팔로우기능 사용 가능
             followBtn.forEach(button => {
-                if (button.classList.contains('active')) {
+                if (button.classList.contains('active')) { // 팔로우 취소
                     button.querySelector('.follow').textContent = follow;
                     fetch("/user/unfollow", {
                         method: 'DELETE',
@@ -35,7 +36,7 @@
                                 return button.classList.remove('active');
                             }
                         })
-                } else {
+                } else { // 팔로우하기
                     button.querySelector('.follow').textContent = unfollow;
                     fetch("/user/follow", {
                         body: JSON.stringify({
@@ -54,19 +55,20 @@
                         })
                 }
             })
-        } else {
+        } else { // 로그인하지 않은 경우 로그인화면으로 이동
             location.href = "/user/signin"
         }
     }
 
+    // 게시물 좋아요
     function articleFavorite() {
         const favoriteBtn = document.querySelectorAll('.favorite-btn');
         let counts = parseInt(event.target.querySelector('.count').textContent);
         let newCounts = counts + 1;
 
-        if ("${ssIsLogin}" === "true") {
+        if ("${ssIsLogin}" === "true") { // 로그인한 경우에만 좋아요기능 사용가능
             favoriteBtn.forEach(button => {
-                if (button.classList.contains('active')) {
+                if (button.classList.contains('active')) { // 좋아요 취소
                     button.querySelector('.favorite').textContent = favorite;
                     button.classList.remove('active');
 
@@ -76,7 +78,7 @@
                                 return button.querySelector('.count').textContent = counts - 1;
                             }
                         })
-                } else {
+                } else { // 좋아요 하기
                     button.querySelector('.favorite').textContent = unfavorite;
                     button.classList.add('active');
 
@@ -98,11 +100,12 @@
                         })
                 }
             })
-        } else {
+        } else { // 로그인하지 않은 경우 로그인화면으로 이동
             location.href = "/user/signin"
         }
     }
 
+    // 게시글 삭제
     const deleteArticle = (targetArticleId) => {
         fetch("/article/" + targetArticleId, { method: 'DELETE' })
             .then(response => {
@@ -113,7 +116,8 @@
             })
     }
 
-    const postComments = () => {
+    // 댓글 생성
+    function postComments() {
         const commentInputArea = document.querySelector('#comment-input');
         const req = {
             userId: "${ssId}",
@@ -130,7 +134,7 @@
             }
         };
 
-        if (commentInputArea.value !== '') {
+        if (commentInputArea.value !== '') { // 공백이 아닌경우에만 댓글 생성
             fetch('/article/${articleDetail.id}/comment', postOptions)
                 .then(response => {
                     if (response.status === 201) {
@@ -141,6 +145,7 @@
         commentInputArea.value = '';
     }
 
+    // 댓글 삭제 => 자신이 작성한 댓글만 삭제 가능
     function deleteComment(targetCommentId) {
         fetch("/article/${articleDetail.id}/comment/" + targetCommentId, { method: 'DELETE' })
             .then(response => {
@@ -150,6 +155,7 @@
             })
     }
 
+    // 댓글 전체 조회
     function displayComments() {
         fetch('/article/${articleDetail.id}/comment/all', { method: 'GET' })
             .then(response => {
@@ -164,7 +170,8 @@
                 while (container.firstChild) {
                     container.firstChild.remove();
                 }
-
+                 
+                // 댓글 표시
                 comments.forEach(comment => {
                     const domParser = new DOMParser();
                     const domStrComment =
@@ -189,6 +196,8 @@
                     const divComment = domParser.parseFromString(domStrComment, 'text/html').body.firstChild;
                     divComment.querySelector('.date-posted').textContent = new Date(comment.created).toLocaleString();
                     container.appendChild(divComment);
+
+                    // 자신이 작성한 댓글에만 삭제 아이콘 표시
                     const icons = document.querySelectorAll('.comment-footer .fa-trash-alt');
                     icons.forEach(icon => {
                         if (comment.userId == "${ssId}") {
@@ -197,7 +206,6 @@
                     })
                 })
             })
-
     }
 
     window.onload = () => {
@@ -210,16 +218,19 @@
             ).join('');
         }
 
+        // 날짜표시 
         const date = "${articleDetail.created}"
         document.querySelectorAll('.date').forEach(value =>
             value.textContent = new Date(date).toLocaleString()
         )
 
+        // 좋아요 수 표시
         const count = "${articleDetail.favoriteNum}";
         document.querySelectorAll('.count').forEach(value => {
             value.textContent = count;
         })
 
+        // 좋아요 여부에 따른 버튼 표시
         const followString = document.querySelectorAll('.follow-btn');
         followString.forEach(value => {
             if(value.classList.contains('active')) {
@@ -227,6 +238,7 @@
             }
         })
 
+        // 팔로우 여부에 따른 버튼 표시
         const favoriteString = document.querySelectorAll('.favorite-btn');
         favoriteString.forEach(value => {
             if (value.classList.contains('active')) {
@@ -300,13 +312,13 @@
                 </div>
             </div>
         </section>
-
+        <!-- Article content -->
         <div class="container main">
             <div class="article-content">
                 <div class="col-12">
                     <pre>
-<c:out value="${articleDetail.content}"></c:out>
-</pre>
+                        <c:out value="${articleDetail.content}"></c:out>
+                    </pre>
                     <ul class="tag-list">
                     </ul>
                 </div>

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

@@ -7,73 +7,73 @@
 
 <jsp:include page="/WEB-INF/jsp/include/head.jsp"></jsp:include>
 <script>
+    let settingForm = null;
+    const originalSetting = {};
 
-let settingForm = null;
-const originalSetting = {};
-
-window.onload = () => {
-    settingForm = window.document.querySelector('#setting-form');
-}
-
-const submitForm = () => {
-    // 밸리데이션 하는 부분 필요
-
-    const json = {};
-
-    // 이름
-    if (settingForm['username'].value !== "${user.username}") {
-        json.username = settingForm['username'].value;
+    window.onload = () => {
+        settingForm = window.document.querySelector('#setting-form');
     }
 
-    // 이메일
-    if (settingForm['email'].value !== "${user.email}") {
-        json.email = settingForm['email'].value;
-    }
+    const submitForm = () => {
+        // 밸리데이션 하는 부분 필요
+        if(!validateForm()) {
+            return ;
+        }
 
-    // 비번
-    if (settingForm['password'].value !== "") {
-        json.password = settingForm['password'].value;
-    }
+        const json = {};
 
-    json.shortBio = settingForm['shortBio'].value;
-    json.id = "${user.id}"
+        // 이름
+        if (settingForm['username'].value !== "${user.username}") {
+            json.username = settingForm['username'].value;
+        }
 
-    const options = {
-        body: JSON.stringify(json),
-        method: 'PATCH',
-        headers: {
-            "Content-Type": "application/json"
+        // 이메일
+        if (settingForm['email'].value !== "${user.email}") {
+            json.email = settingForm['email'].value;
         }
-    };
 
-    fetch("/user/settings/${user.id}", options)
-        .then(response => {
-            if (response.status === 200) {
-                location.href = '/user/settings/${user.id}'
+        // 비번
+        if (settingForm['password'].value !== "") {
+            json.password = settingForm['password'].value;
+        }
+
+        json.shortBio = settingForm['shortBio'].value;
+        json.id = "${user.id}"
+
+        const options = {
+            body: JSON.stringify(json),
+            method: 'PATCH',
+            headers: {
+                "Content-Type": "application/json"
             }
-        })
-}
-
-// 입력폼 벨리데이션
-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;
+        };
+
+        fetch("/user/settings/${user.id}", options)
+            .then(response => {
+                if (response.status === 200) {
+                    location.href = '/user/settings/${user.id}'
+                }
+            })
     }
 
-    return true;
-}
+    // 입력폼 validation
+    const validateForm = () => {
+        const userName = settingForm['username'].value;
+        // 이름 공백 체크
+        if (userName === null || userName === "") {
+            alert("이름을 입력해주세요.");
+            return false;
+        } 
+
+        const email = settingForm['email'].value;
+        // 이메일 공백 체크
+        if (email === null || email === "") {
+            alert("이메일을 입력해주세요.");
+            return false;
+        }
+        
+        return true;
+    }
 
 
 </script>

+ 214 - 87
realworld/src/main/webapp/WEB-INF/jsp/user/userInfo.jsp

@@ -7,7 +7,117 @@
 
 <jsp:include page="/WEB-INF/jsp/include/head.jsp"></jsp:include>
 <script>
+    let targetFeed = null;
+    const loadingArticles = document.querySelector('#article-loading');
+    const articleList = document.querySelector('#article-list');
 
+    const setLoading = (type) => {
+        let loadingDisplay = null;
+        let contentDisplay = null;
+
+        if(type === 'on') {
+            loadingDisplay = 'block';
+            contentDisplay = 'none';
+        } else if(type === 'off') {
+            loadingDisplay = 'none';
+            contentDisplay = 'block';
+        }
+
+        loadingArticles.style.display = loadingDisplay;
+        articleList.style.display = contentDisplay;
+    }
+
+    const focusFeed = () => {
+        // 이미 포커싱되었으면 중단
+        if(event.target.parentNode.classList.contains('active')) {
+            return ;
+        }
+
+        const currentFeed = event.target.parentNode; // 포커싱할 피드
+        const focusedFeed = (currentFeed.id === 'favorite-feed') ? document.querySelector('#your-feed') : document.querySelector('#favorite-feed'); // 현재 포커싱되어있는 피드
+        
+        currentFeed.classList.add('active');
+        focusedFeed.classList.remove('active');
+
+        // targetFeed 초기화
+        targetFeed = currentFeed;
+        setLoading('on');
+    }
+
+    const displayArticles = (articles) => {
+        articles.forEach(article =>  {
+            const domParser = new DOMParser();
+
+            // 게시글 정보
+            const domStrArticleMeta =
+                `
+                <div class="article-meta">
+                    <div class="metadata">
+                        <a href="javascript.void(0);">
+                            <img src"/resources/images/avatar.png" alt="avatar">
+                        </a>
+                        <div class="article-info">
+                            <a href="javascript.void(0);" class="name">\${article.writerName}</a>
+                            <span class="date"></span>
+                        </div>
+                    </div>
+                    <div>
+                        <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;
+            divArticleMeta.querySelector('.date').textContent = new Date(article.create).toLocaleString();
+
+            // 게시글 좋아요한 경우 active
+            if (article.favorite) {
+                divArticleMeta.querySelector('.favorite-btn').classList.add('active');
+            }
+
+            // 게시글 내용 및 게시글태그
+            const domStrPreviewLink =
+                `
+                <a href="/article/\${articleId}" class="preview-link">
+                    <h1 class="preview-title">\${articleTitle}</h1>
+                    <p>\${articleSubtitle}</p>
+                    <div class="tag-data">
+                        <span>Read more...</span>
+                        <ul class="tag-list">
+                        </ul>
+                    </div>
+                </a>
+                `;
+            const aPreviewLink = domParser.parseFromString(domStrPreviewLink, 'text/html').body.firstChild;
+            const ul = aPreviewLink.querySelector('.tag-list');
+
+            if (article.tags !== '') {
+                article.tags.split(',').forEach(tag => {
+                    if(!tagSet.has(tag)) {
+                        tagSet.add(tag);
+                    }
+
+                    const li = document.createElement('li');
+                    li.classList.add('tag');
+                    li.textContent = tag;
+                    ul.appendChild(li);
+                });
+            }
+
+            // 게시글 완성
+            const articlePreview = document.createElement('article');
+            articlePreview.classList.add('article-preview');
+            articlePreview.append(divArticleMeta, aPreviewLink);
+            articleList.appendChild(articlePreview);
+        })
+    }
+
+    window.onload = () => {
+        targetFeed = document.querySelector('.nav-item.active');
+
+    }
 
 </script>
 </head>
@@ -25,7 +135,14 @@
                         <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
+                            <c:choose>
+                                <c:when test="{id eq ssId}">
+                                    <i class="fas fa-cog"></i>&nbsp;Edit Profile Settings
+                                </c:when>
+                                <c:otherwise>
+                                    <i class="fas fa-plus"></i>&nbsp;Follow Gerome
+                                </c:otherwise>
+                            </c:choose>
                         </a>
                     </div>
                 </div>
@@ -38,103 +155,113 @@
                     <!-- 토글 버튼으로 피드 내용 보기 -->
                     <div class="toggle">
                         <ul class="nav">
-                            <li class="nav-item active">
-                                <a href="#">My Articles</a>
+                            <li id="your-feed" class="nav-item active">
+                                <a href="javascript:void(0);" onclick="focusFeed()">My Articles</a>
                             </li>
-                            <li class="nav-item">
-                                <a href="userpage-favorited.html">Favorited Articles</a>
+                            <li id="favoreted-feed" class="nav-item">
+                                <a href="javascript:void(0);" onclick="focusFeed()">Favorited Articles</a>
                             </li>
                         </ul>
                     </div>
+
+                    <!-- Content -->
                     <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 Loading -->
+                        <article id="article-loading">
+                            Loading articles...
                         </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>
+
+                        <!-- Article List -->
+                        <div id="article-list" style="display: none;">
+                            <!-- <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>
-                                <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>
+                                        <button class="favorite-btn">
+                                            <i class="fas fa-heart"></i>
+                                            <span class="count">564</span>
+                                        </button>
                                     </div>
                                 </div>
-                                <div>
-                                    <button class="favorite-btn">
-                                        <i class="fas fa-heart"></i>
-                                        <span class="count">564</span>
-                                    </button>
+                                <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>
-                            </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>
+                                <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>
-                        </article>
+                                <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>

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

@@ -235,13 +235,16 @@ button {
     border-bottom: 3px solid var(--green-color);
 }
 
-
 .toggle .nav .nav-item.active a {
     cursor: default;
     color: var(--green-color);
 }
 
-/* 추가 */
+.toggle .nav #tag-feed a {
+    display: flex;
+    align-items: center;
+}
+
 .toggle .nav .nav-item.active div {
     cursor: default;
     color: var(--green-color);