From b2de9f45b573fbea6a4e7be905540d185a689203 Mon Sep 17 00:00:00 2001 From: sunghyuki Date: Sun, 17 Apr 2022 15:22:50 +0900 Subject: [PATCH 1/9] =?UTF-8?q?fix=20:=20show.html=20=EC=98=A4=ED=83=80=20?= =?UTF-8?q?=EC=88=98=EC=A0=95=20-=20=EC=88=98=EC=A0=95=20=EB=B2=84?= =?UTF-8?q?=ED=8A=BC=20=EC=98=86=EC=9D=98=20'=EA=B0=80'=20=EC=A7=80?= =?UTF-8?q?=EC=9A=B0=EA=B8=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/resources/templates/qna/show.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/resources/templates/qna/show.html b/src/main/resources/templates/qna/show.html index ef8f8ec4..16e09d4f 100755 --- a/src/main/resources/templates/qna/show.html +++ b/src/main/resources/templates/qna/show.html @@ -76,7 +76,7 @@

{{title}}

수정
  • -가
    +
    From 070ed34af79c0fbd5a996e2cd3ac6f258510b729 Mon Sep 17 00:00:00 2001 From: sunghyuki Date: Mon, 18 Apr 2022 16:10:02 +0900 Subject: [PATCH 2/9] =?UTF-8?q?feat=20:=20=EC=82=AD=EC=A0=9C=20=EC=83=81?= =?UTF-8?q?=ED=83=9C=20=ED=95=84=EB=93=9C=20=EC=96=B4=EB=85=B8=ED=85=8C?= =?UTF-8?q?=EC=9D=B4=EC=85=98=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/codesquad/domain/answer/Answer.java | 7 ++++--- src/main/java/codesquad/domain/question/Question.java | 3 ++- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/src/main/java/codesquad/domain/answer/Answer.java b/src/main/java/codesquad/domain/answer/Answer.java index 42498777..d4659bf3 100644 --- a/src/main/java/codesquad/domain/answer/Answer.java +++ b/src/main/java/codesquad/domain/answer/Answer.java @@ -15,14 +15,15 @@ public class Answer { @JoinColumn(foreignKey = @ForeignKey(name = "fk_answer_writer")) private User writer; - @ManyToOne + @ManyToOne(fetch = FetchType.LAZY) @JoinColumn(foreignKey = @ForeignKey(name = "fk_answer_to_question")) private Question question; @Column(columnDefinition = "TEXT", length = 300, nullable = false) private String contents; - private Boolean isDeleted = false; + @Column(columnDefinition = "boolean default false") + private boolean isDeleted = false; public Long getId() { return id; @@ -56,7 +57,7 @@ public void setContents(String contents) { this.contents = contents; } - public Boolean getDeleted() { + public boolean getDeleted() { return isDeleted; } diff --git a/src/main/java/codesquad/domain/question/Question.java b/src/main/java/codesquad/domain/question/Question.java index 06a6aedb..158615c6 100644 --- a/src/main/java/codesquad/domain/question/Question.java +++ b/src/main/java/codesquad/domain/question/Question.java @@ -27,7 +27,8 @@ public class Question { private Integer countOfAnswer = 0; - private Boolean isDeleted = false; + @Column(columnDefinition = "boolean default false") + private boolean isDeleted = false; public Long getIndex() { return index; From d93303c91f004023d590f3606d77eb51322e1f29 Mon Sep 17 00:00:00 2001 From: sunghyuki Date: Thu, 21 Apr 2022 09:01:20 +0900 Subject: [PATCH 3/9] =?UTF-8?q?feat=20:=20JpaAuditing=20=EA=B8=B0=EB=8A=A5?= =?UTF-8?q?=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/codesquad/QnaApplication.java | 2 ++ .../java/codesquad/domain/BaseTimeEntity.java | 20 +++++++++++++++++++ .../java/codesquad/domain/answer/Answer.java | 3 ++- .../codesquad/domain/question/Question.java | 3 ++- src/main/java/codesquad/domain/user/User.java | 4 +++- src/main/resources/data.sql | 4 ++-- src/main/resources/templates/index.html | 2 +- src/main/resources/templates/qna/show.html | 4 ++-- 8 files changed, 34 insertions(+), 8 deletions(-) create mode 100644 src/main/java/codesquad/domain/BaseTimeEntity.java diff --git a/src/main/java/codesquad/QnaApplication.java b/src/main/java/codesquad/QnaApplication.java index 6d19f8aa..8959ef06 100644 --- a/src/main/java/codesquad/QnaApplication.java +++ b/src/main/java/codesquad/QnaApplication.java @@ -2,7 +2,9 @@ import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.data.jpa.repository.config.EnableJpaAuditing; +@EnableJpaAuditing @SpringBootApplication public class QnaApplication { public static void main(String[] args) { diff --git a/src/main/java/codesquad/domain/BaseTimeEntity.java b/src/main/java/codesquad/domain/BaseTimeEntity.java new file mode 100644 index 00000000..bed7895a --- /dev/null +++ b/src/main/java/codesquad/domain/BaseTimeEntity.java @@ -0,0 +1,20 @@ +package codesquad.domain; + +import org.springframework.data.annotation.CreatedDate; +import org.springframework.data.jpa.domain.support.AuditingEntityListener; + +import javax.persistence.EntityListeners; +import javax.persistence.MappedSuperclass; +import java.time.LocalDateTime; + +@MappedSuperclass +@EntityListeners(AuditingEntityListener.class) +public class BaseTimeEntity { + + @CreatedDate + private LocalDateTime createdDate; + + public LocalDateTime getCreatedDate() { + return createdDate; + } +} diff --git a/src/main/java/codesquad/domain/answer/Answer.java b/src/main/java/codesquad/domain/answer/Answer.java index d4659bf3..299e5db3 100644 --- a/src/main/java/codesquad/domain/answer/Answer.java +++ b/src/main/java/codesquad/domain/answer/Answer.java @@ -1,12 +1,13 @@ package codesquad.domain.answer; +import codesquad.domain.BaseTimeEntity; import codesquad.domain.question.Question; import codesquad.domain.user.User; import javax.persistence.*; @Entity -public class Answer { +public class Answer extends BaseTimeEntity { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; diff --git a/src/main/java/codesquad/domain/question/Question.java b/src/main/java/codesquad/domain/question/Question.java index 158615c6..477d44b1 100644 --- a/src/main/java/codesquad/domain/question/Question.java +++ b/src/main/java/codesquad/domain/question/Question.java @@ -1,5 +1,6 @@ package codesquad.domain.question; +import codesquad.domain.BaseTimeEntity; import codesquad.domain.answer.Answer; import codesquad.domain.user.User; @@ -7,7 +8,7 @@ import java.util.List; @Entity -public class Question { +public class Question extends BaseTimeEntity { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long index; diff --git a/src/main/java/codesquad/domain/user/User.java b/src/main/java/codesquad/domain/user/User.java index ecf23768..20cb46f0 100644 --- a/src/main/java/codesquad/domain/user/User.java +++ b/src/main/java/codesquad/domain/user/User.java @@ -1,9 +1,11 @@ package codesquad.domain.user; +import codesquad.domain.BaseTimeEntity; + import javax.persistence.*; @Entity -public class User { +public class User extends BaseTimeEntity { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; diff --git a/src/main/resources/data.sql b/src/main/resources/data.sql index 4538cadd..8d2ad674 100644 --- a/src/main/resources/data.sql +++ b/src/main/resources/data.sql @@ -1,2 +1,2 @@ -INSERT INTO USER (id, user_id, password, name, email) VALUES (1, 'javajigi', 'test', '자바지기', 'javajigi@slipp.net'); -INSERT INTO USER (id, user_id, password, name, email) VALUES (2, 'sanjigi', 'test', '산지기', 'sanjigi@slipp.net'); \ No newline at end of file +INSERT INTO USER (id, created_date, user_id, password, name, email) VALUES (1, '2022-04-18 16:20:29.311', 'javajigi', 'test', '자바지기', 'javajigi@slipp.net'); +INSERT INTO USER (id, created_date, user_id, password, name, email) VALUES (2, '2022-04-18 16:20:29.311', 'sanjigi', 'test', '산지기', 'sanjigi@slipp.net'); \ No newline at end of file diff --git a/src/main/resources/templates/index.html b/src/main/resources/templates/index.html index 115ba412..93169d48 100755 --- a/src/main/resources/templates/index.html +++ b/src/main/resources/templates/index.html @@ -14,7 +14,7 @@
    - 2016-01-15 18:47 + {{createdDate}} {{writer.name}}
    diff --git a/src/main/resources/templates/qna/show.html b/src/main/resources/templates/qna/show.html index 16e09d4f..e49c515e 100755 --- a/src/main/resources/templates/qna/show.html +++ b/src/main/resources/templates/qna/show.html @@ -16,7 +16,7 @@

    {{title}}

    - 2015-12-30 01:47 + {{createdDate}}
    @@ -63,7 +63,7 @@

    {{title}}

    - 2016-01-12 14:06 + {{createdDate}}
    From 49bd31aed85e02935860b2714f04ac68d98cf6f9 Mon Sep 17 00:00:00 2001 From: sunghyuki Date: Fri, 22 Apr 2022 00:11:44 +0900 Subject: [PATCH 4/9] =?UTF-8?q?feat=20:=20AJAX=EB=A1=9C=20=EB=8B=B5?= =?UTF-8?q?=EB=B3=80=ED=95=98=EA=B8=B0=20=EA=B8=B0=EB=8A=A5=20=EA=B5=AC?= =?UTF-8?q?=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/codesquad/domain/answer/Answer.java | 18 ++++- .../codesquad/domain/question/Question.java | 10 ++- .../codesquad/web/ApiAnswerController.java | 39 ++++++++++ .../web/dto/AnswerSaveRequestDto.java | 10 +++ src/main/resources/data.sql | 4 +- src/main/resources/static/js/scripts.js | 74 ++++++++++++++++++- src/main/resources/templates/failed.html | 3 - src/main/resources/templates/index.html | 4 +- .../resources/templates/layout/footer.html | 6 +- src/main/resources/templates/qna/show.html | 36 +-------- 10 files changed, 155 insertions(+), 49 deletions(-) create mode 100644 src/main/java/codesquad/web/ApiAnswerController.java create mode 100644 src/main/java/codesquad/web/dto/AnswerSaveRequestDto.java delete mode 100644 src/main/resources/templates/failed.html diff --git a/src/main/java/codesquad/domain/answer/Answer.java b/src/main/java/codesquad/domain/answer/Answer.java index 299e5db3..8eb4d1da 100644 --- a/src/main/java/codesquad/domain/answer/Answer.java +++ b/src/main/java/codesquad/domain/answer/Answer.java @@ -24,7 +24,17 @@ public class Answer extends BaseTimeEntity { private String contents; @Column(columnDefinition = "boolean default false") - private boolean isDeleted = false; + private boolean deleted = false; + + public Answer() { + + } + + public Answer(User writer, Question question, String contents) { + this.writer = writer; + this.question = question; + this.contents = contents; + } public Long getId() { return id; @@ -58,8 +68,8 @@ public void setContents(String contents) { this.contents = contents; } - public boolean getDeleted() { - return isDeleted; + public boolean isDeleted() { + return deleted; } public boolean isSameWriter(User user) { @@ -67,6 +77,6 @@ public boolean isSameWriter(User user) { } public void delete() { - isDeleted = true; + deleted = true; } } diff --git a/src/main/java/codesquad/domain/question/Question.java b/src/main/java/codesquad/domain/question/Question.java index 477d44b1..47b0fdcd 100644 --- a/src/main/java/codesquad/domain/question/Question.java +++ b/src/main/java/codesquad/domain/question/Question.java @@ -3,6 +3,7 @@ import codesquad.domain.BaseTimeEntity; import codesquad.domain.answer.Answer; import codesquad.domain.user.User; +import com.fasterxml.jackson.annotation.JsonIgnore; import javax.persistence.*; import java.util.List; @@ -24,12 +25,13 @@ public class Question extends BaseTimeEntity { private String contents; @OneToMany(mappedBy = "question") + @JsonIgnore private List answers; private Integer countOfAnswer = 0; @Column(columnDefinition = "boolean default false") - private boolean isDeleted = false; + private boolean deleted = false; public Long getIndex() { return index; @@ -101,7 +103,11 @@ public void deleteAnswer() { } public void delete() { - isDeleted = true; + deleted = true; + } + + public boolean isDeleted() { + return deleted; } public boolean canDelete() { diff --git a/src/main/java/codesquad/web/ApiAnswerController.java b/src/main/java/codesquad/web/ApiAnswerController.java new file mode 100644 index 00000000..1c61ab7e --- /dev/null +++ b/src/main/java/codesquad/web/ApiAnswerController.java @@ -0,0 +1,39 @@ +package codesquad.web; + +import codesquad.domain.answer.Answer; +import codesquad.domain.answer.AnswerRepository; +import codesquad.domain.question.Question; +import codesquad.domain.question.QuestionRepository; +import codesquad.domain.user.User; +import codesquad.util.HttpSessionUtil; +import codesquad.web.dto.AnswerSaveRequestDto; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.*; + +import javax.servlet.http.HttpSession; +import java.util.NoSuchElementException; + +@RestController +@RequestMapping("/api/questions/{index}/answers") +public class ApiAnswerController { + + @Autowired + private QuestionRepository questionRepository; + + @Autowired + private AnswerRepository answerRepository; + + @PostMapping("") + public Answer create(@PathVariable Long index, @RequestBody AnswerSaveRequestDto answerSaveRequestDto, HttpSession httpSession) { + if(!HttpSessionUtil.isLoginUser(httpSession)) { + return null; + } + + User sessionedUser = HttpSessionUtil.getUserFrom(httpSession); + Question savedQuestion = questionRepository.findById(index).orElseThrow(() -> new NoSuchElementException("게시글이 존재하지 않습니다.")); + Answer answer = new Answer(sessionedUser, savedQuestion, answerSaveRequestDto.getContents()); + savedQuestion.addCountOfAnswer(); + + return answerRepository.save(answer); + } +} diff --git a/src/main/java/codesquad/web/dto/AnswerSaveRequestDto.java b/src/main/java/codesquad/web/dto/AnswerSaveRequestDto.java new file mode 100644 index 00000000..dbf7c780 --- /dev/null +++ b/src/main/java/codesquad/web/dto/AnswerSaveRequestDto.java @@ -0,0 +1,10 @@ +package codesquad.web.dto; + +public class AnswerSaveRequestDto { + + private String contents; + + public String getContents() { + return contents; + } +} diff --git a/src/main/resources/data.sql b/src/main/resources/data.sql index 8d2ad674..df491baf 100644 --- a/src/main/resources/data.sql +++ b/src/main/resources/data.sql @@ -1,2 +1,4 @@ INSERT INTO USER (id, created_date, user_id, password, name, email) VALUES (1, '2022-04-18 16:20:29.311', 'javajigi', 'test', '자바지기', 'javajigi@slipp.net'); -INSERT INTO USER (id, created_date, user_id, password, name, email) VALUES (2, '2022-04-18 16:20:29.311', 'sanjigi', 'test', '산지기', 'sanjigi@slipp.net'); \ No newline at end of file +INSERT INTO USER (id, created_date, user_id, password, name, email) VALUES (2, '2022-04-18 16:20:29.311', 'sanjigi', 'test', '산지기', 'sanjigi@slipp.net'); + +INSERT INTO QUESTION(index, created_date, contents, count_of_answer, deleted, title, writer_id) VALUES(1, '2022-04-19 16:20:29.311', '자동차 경주 게임을 수행하세요.', 0, false, '오늘의 미션은?', 1); \ No newline at end of file diff --git a/src/main/resources/static/js/scripts.js b/src/main/resources/static/js/scripts.js index 01f85bd2..219a128c 100755 --- a/src/main/resources/static/js/scripts.js +++ b/src/main/resources/static/js/scripts.js @@ -6,4 +6,76 @@ String.prototype.format = function() { : match ; }); -}; \ No newline at end of file +}; + +function $(selector) { + return document.querySelector(selector); +} + +document.addEventListener("DOMContentLoaded", () => { + initEvents(); +}) + +function initEvents() { + const answerBtn = $(".submit-write .btn"); + if(answerBtn === null) return; + answerBtn.addEventListener("click", registerAnswerHandler); +} + +function fetchManager({ url, method, body, headers, callback}) { + fetch(url, {method,body,headers,credentials: "same-origin"}) + .then((response) => { + return response.json() + }).then((result) => { + callback(result) + }) +} + +function registerAnswerHandler(evt) { + evt.preventDefault(); + const contents = $(".submit-write textarea").value; + $(".form-control").value = ""; + + const url = $(".submit-write").action; + + fetchManager({ + url: url, + method: 'POST', + headers: { 'content-type': 'application/json'}, + body: JSON.stringify({contents}), + callback: appendAnswer + }) +} + +function appendAnswer({id, contents, question, writer, createdDate}) { + const html = ` +
    +
    +
    + +
    +
    + +
    ${createdDate}
    +
    +
    +
    + ${contents} +
    +
    +
      +
    • + 수정 +
    • +
    • +
      + + +
      +
    • +
    +
    +
    ` + + $('.qna-comment-slipp-articles').insertAdjacentHTML('afterbegin', html); +} \ No newline at end of file diff --git a/src/main/resources/templates/failed.html b/src/main/resources/templates/failed.html deleted file mode 100644 index 64e90c12..00000000 --- a/src/main/resources/templates/failed.html +++ /dev/null @@ -1,3 +0,0 @@ -{{>layout/header}} -

    수정할 수 없습니다.

    -{{>layout/footer}} \ No newline at end of file diff --git a/src/main/resources/templates/index.html b/src/main/resources/templates/index.html index 93169d48..1f09f607 100755 --- a/src/main/resources/templates/index.html +++ b/src/main/resources/templates/index.html @@ -5,7 +5,7 @@
      {{#questions}} - {{^isDeleted}} + {{^deleted}}
    • @@ -24,7 +24,7 @@
    • - {{/isDeleted}} + {{/deleted}} {{/questions}}
    diff --git a/src/main/resources/templates/layout/footer.html b/src/main/resources/templates/layout/footer.html index 0cc611b1..b26824cb 100644 --- a/src/main/resources/templates/layout/footer.html +++ b/src/main/resources/templates/layout/footer.html @@ -1,6 +1,6 @@ - - - + + + \ No newline at end of file diff --git a/src/main/resources/templates/qna/show.html b/src/main/resources/templates/qna/show.html index e49c515e..4d7c78cf 100755 --- a/src/main/resources/templates/qna/show.html +++ b/src/main/resources/templates/qna/show.html @@ -54,7 +54,7 @@

    {{title}}

    {{countOfAnswer}}개의 의견

    {{#answers}} - {{^isDeleted}} + {{^deleted}}
    @@ -84,9 +84,9 @@

    {{title}}

    - {{/isDeleted}} + {{/deleted}} {{/answers}} -
    +
    @@ -102,34 +102,4 @@

    {{title}}

    - - {{>layout/footer}} \ No newline at end of file From a5f3571ec68435b472b22c5b333acd519c0af1bb Mon Sep 17 00:00:00 2001 From: sunghyuki Date: Fri, 22 Apr 2022 10:32:03 +0900 Subject: [PATCH 5/9] =?UTF-8?q?feat=20:=20AJAX=EB=A1=9C=20=EB=8B=B5?= =?UTF-8?q?=EB=B3=80=ED=95=98=EA=B8=B0=20=EC=82=AD=EC=A0=9C=20=EA=B8=B0?= =?UTF-8?q?=EB=8A=A5=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../codesquad/web/ApiAnswerController.java | 24 ++++++++++++++++++ src/main/resources/static/js/scripts.js | 25 +++++++++++++++++-- src/main/resources/templates/qna/show.html | 2 +- 3 files changed, 48 insertions(+), 3 deletions(-) diff --git a/src/main/java/codesquad/web/ApiAnswerController.java b/src/main/java/codesquad/web/ApiAnswerController.java index 1c61ab7e..6906f4b5 100644 --- a/src/main/java/codesquad/web/ApiAnswerController.java +++ b/src/main/java/codesquad/web/ApiAnswerController.java @@ -36,4 +36,28 @@ public Answer create(@PathVariable Long index, @RequestBody AnswerSaveRequestDto return answerRepository.save(answer); } + + @DeleteMapping("/{id}") + public Long delete(@PathVariable Long index, @PathVariable Long id, HttpSession httpSession) { + if(!HttpSessionUtil.isLoginUser(httpSession)) { + return null; + } + + Answer savedAnswer = answerRepository.findById(id).orElseThrow(() -> new NoSuchElementException("답변이 존재하지 않습니다.")); + User sessionedUser = HttpSessionUtil.getUserFrom(httpSession); + + if (!savedAnswer.isSameWriter(sessionedUser)) { + throw new IllegalStateException("다른 사람의 게시글을 삭제할 수 없습니다."); + } + + savedAnswer.delete(); + + answerRepository.save(savedAnswer); + + Question savedQuestion = questionRepository.findById(index).orElseThrow(() -> new NoSuchElementException("게시글이 존재하지 않습니다.")); + savedQuestion.deleteAnswer(); + + questionRepository.save(savedQuestion); + return id; + } } diff --git a/src/main/resources/static/js/scripts.js b/src/main/resources/static/js/scripts.js index 219a128c..1a29bce0 100755 --- a/src/main/resources/static/js/scripts.js +++ b/src/main/resources/static/js/scripts.js @@ -18,8 +18,9 @@ document.addEventListener("DOMContentLoaded", () => { function initEvents() { const answerBtn = $(".submit-write .btn"); - if(answerBtn === null) return; + const deleteBtn = $(".delete-answer-button"); answerBtn.addEventListener("click", registerAnswerHandler); + deleteBtn.addEventListener("click", deleteAnswerHandler); } function fetchManager({ url, method, body, headers, callback}) { @@ -49,7 +50,7 @@ function registerAnswerHandler(evt) { function appendAnswer({id, contents, question, writer, createdDate}) { const html = ` -
    +
    @@ -78,4 +79,24 @@ function appendAnswer({id, contents, question, writer, createdDate}) {
    ` $('.qna-comment-slipp-articles').insertAdjacentHTML('afterbegin', html); +} + +function deleteAnswerHandler(evt) { + if(evt.target.className !== "answer-delete-button") return; + evt.preventDefault(); + + const url = $(".delete-answer-form").action; + + fetchManager({ + url: url, + method: 'DELETE', + headers: { 'content-type': 'application/json'}, + callback: deleteAnswer + }) +} + +function deleteAnswer({id}) { + const target = $(`.article-comment[data-id='${id}']`); + target.parentNode.removeChild(target); + } \ No newline at end of file diff --git a/src/main/resources/templates/qna/show.html b/src/main/resources/templates/qna/show.html index 4d7c78cf..b10b7936 100755 --- a/src/main/resources/templates/qna/show.html +++ b/src/main/resources/templates/qna/show.html @@ -76,7 +76,7 @@

    {{title}}

    수정
  • - + From cbcb90e92a25a400300a09a6c4a36d1abcd35b74 Mon Sep 17 00:00:00 2001 From: sunghyuki Date: Fri, 22 Apr 2022 22:06:16 +0900 Subject: [PATCH 6/9] =?UTF-8?q?feat=20:=20=EC=82=AD=EC=A0=9C=20=EA=B8=B0?= =?UTF-8?q?=EB=8A=A5=20event=20delegation=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../domain/answer/AnswerRepository.java | 6 ++++++ .../codesquad/web/ApiAnswerController.java | 9 +++++---- src/main/resources/static/js/scripts.js | 18 +++++++++++------- src/main/resources/templates/qna/show.html | 2 +- 4 files changed, 23 insertions(+), 12 deletions(-) diff --git a/src/main/java/codesquad/domain/answer/AnswerRepository.java b/src/main/java/codesquad/domain/answer/AnswerRepository.java index 8c2e8f87..6d4fb3de 100644 --- a/src/main/java/codesquad/domain/answer/AnswerRepository.java +++ b/src/main/java/codesquad/domain/answer/AnswerRepository.java @@ -1,6 +1,12 @@ package codesquad.domain.answer; +import org.springframework.data.jpa.repository.EntityGraph; import org.springframework.data.jpa.repository.JpaRepository; +import java.util.Optional; + public interface AnswerRepository extends JpaRepository { + + @EntityGraph(attributePaths = {"question"}) + Optional findQuestionFetchJoinById(Long id); } diff --git a/src/main/java/codesquad/web/ApiAnswerController.java b/src/main/java/codesquad/web/ApiAnswerController.java index 6906f4b5..05e6e9b6 100644 --- a/src/main/java/codesquad/web/ApiAnswerController.java +++ b/src/main/java/codesquad/web/ApiAnswerController.java @@ -38,12 +38,12 @@ public Answer create(@PathVariable Long index, @RequestBody AnswerSaveRequestDto } @DeleteMapping("/{id}") - public Long delete(@PathVariable Long index, @PathVariable Long id, HttpSession httpSession) { + public Answer delete(@PathVariable Long index, @PathVariable Long id, HttpSession httpSession) { if(!HttpSessionUtil.isLoginUser(httpSession)) { - return null; + throw new IllegalStateException("세션이 만료되었습니다. 다시 로그인 해주세요."); } - Answer savedAnswer = answerRepository.findById(id).orElseThrow(() -> new NoSuchElementException("답변이 존재하지 않습니다.")); + Answer savedAnswer = answerRepository.findQuestionFetchJoinById(id).orElseThrow(() -> new NoSuchElementException("답변이 존재하지 않습니다.")); User sessionedUser = HttpSessionUtil.getUserFrom(httpSession); if (!savedAnswer.isSameWriter(sessionedUser)) { @@ -58,6 +58,7 @@ public Long delete(@PathVariable Long index, @PathVariable Long id, HttpSession savedQuestion.deleteAnswer(); questionRepository.save(savedQuestion); - return id; + + return savedAnswer; } } diff --git a/src/main/resources/static/js/scripts.js b/src/main/resources/static/js/scripts.js index 1a29bce0..987f1c90 100755 --- a/src/main/resources/static/js/scripts.js +++ b/src/main/resources/static/js/scripts.js @@ -18,9 +18,10 @@ document.addEventListener("DOMContentLoaded", () => { function initEvents() { const answerBtn = $(".submit-write .btn"); - const deleteBtn = $(".delete-answer-button"); + + console.log(answerBtn); answerBtn.addEventListener("click", registerAnswerHandler); - deleteBtn.addEventListener("click", deleteAnswerHandler); + $('.qna-comment-slipp-articles').addEventListener('click',deleteAnswerHandler); } function fetchManager({ url, method, body, headers, callback}) { @@ -35,8 +36,7 @@ function fetchManager({ url, method, body, headers, callback}) { function registerAnswerHandler(evt) { evt.preventDefault(); const contents = $(".submit-write textarea").value; - $(".form-control").value = ""; - + $(".submit-write textarea").value = ""; const url = $(".submit-write").action; fetchManager({ @@ -69,7 +69,7 @@ function appendAnswer({id, contents, question, writer, createdDate}) { 수정
  • -
    +
    @@ -82,10 +82,12 @@ function appendAnswer({id, contents, question, writer, createdDate}) { } function deleteAnswerHandler(evt) { - if(evt.target.className !== "answer-delete-button") return; + console.log(evt.target.className); + if(evt.target.className !== "delete-answer-button") return; evt.preventDefault(); const url = $(".delete-answer-form").action; + console.log(url); fetchManager({ url: url, @@ -96,7 +98,9 @@ function deleteAnswerHandler(evt) { } function deleteAnswer({id}) { + console.log(id); const target = $(`.article-comment[data-id='${id}']`); + console.log(target); + console.log(target.parentNode); target.parentNode.removeChild(target); - } \ No newline at end of file diff --git a/src/main/resources/templates/qna/show.html b/src/main/resources/templates/qna/show.html index b10b7936..1f7ee0a0 100755 --- a/src/main/resources/templates/qna/show.html +++ b/src/main/resources/templates/qna/show.html @@ -55,7 +55,7 @@

    {{title}}

    {{#answers}} {{^deleted}} -
    +
    From 2cd580f8a93087ce11d88162fd14983fb0881c21 Mon Sep 17 00:00:00 2001 From: sunghyuki Date: Sat, 23 Apr 2022 00:26:02 +0900 Subject: [PATCH 7/9] =?UTF-8?q?feat=20:=20=EC=9D=91=EB=8B=B5=EC=97=90=20?= =?UTF-8?q?=ED=95=B4=EB=8B=B9=ED=95=98=EB=8A=94=20=EB=8D=B0=EC=9D=B4?= =?UTF-8?q?=ED=84=B0=EB=A5=BC=20=ED=8F=AC=ED=95=A8=ED=95=98=EB=8A=94=20Res?= =?UTF-8?q?ult=20=ED=81=B4=EB=9E=98=EC=8A=A4=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/codesquad/domain/Result.java | 28 +++++++++++++++++++ .../codesquad/web/ApiAnswerController.java | 9 +++--- src/main/resources/static/js/scripts.js | 7 +++-- 3 files changed, 37 insertions(+), 7 deletions(-) create mode 100644 src/main/java/codesquad/domain/Result.java diff --git a/src/main/java/codesquad/domain/Result.java b/src/main/java/codesquad/domain/Result.java new file mode 100644 index 00000000..3e64cebe --- /dev/null +++ b/src/main/java/codesquad/domain/Result.java @@ -0,0 +1,28 @@ +package codesquad.domain; + +public class Result { + + private T data; + private String errorMessage; + + private Result(T data, String errorMessage) { + this.data = data; + this.errorMessage = errorMessage; + } + + public static Result ok(T data) { + return new Result<>(data, null); + } + + public static Result fail(String errorMessage) { + return new Result<>(null, errorMessage); + } + + public T getData() { + return data; + } + + public String getErrorMessage() { + return errorMessage; + } +} diff --git a/src/main/java/codesquad/web/ApiAnswerController.java b/src/main/java/codesquad/web/ApiAnswerController.java index 05e6e9b6..1e8ebdfd 100644 --- a/src/main/java/codesquad/web/ApiAnswerController.java +++ b/src/main/java/codesquad/web/ApiAnswerController.java @@ -1,5 +1,6 @@ package codesquad.web; +import codesquad.domain.Result; import codesquad.domain.answer.Answer; import codesquad.domain.answer.AnswerRepository; import codesquad.domain.question.Question; @@ -38,16 +39,16 @@ public Answer create(@PathVariable Long index, @RequestBody AnswerSaveRequestDto } @DeleteMapping("/{id}") - public Answer delete(@PathVariable Long index, @PathVariable Long id, HttpSession httpSession) { + public Result delete(@PathVariable Long index, @PathVariable Long id, HttpSession httpSession) { if(!HttpSessionUtil.isLoginUser(httpSession)) { - throw new IllegalStateException("세션이 만료되었습니다. 다시 로그인 해주세요."); + return Result.fail("세션이 만료되었습니다. 다시 로그인 해주세요."); } Answer savedAnswer = answerRepository.findQuestionFetchJoinById(id).orElseThrow(() -> new NoSuchElementException("답변이 존재하지 않습니다.")); User sessionedUser = HttpSessionUtil.getUserFrom(httpSession); if (!savedAnswer.isSameWriter(sessionedUser)) { - throw new IllegalStateException("다른 사람의 게시글을 삭제할 수 없습니다."); + return Result.fail("다른 사람의 게시글을 삭제할 수 없습니다."); } savedAnswer.delete(); @@ -59,6 +60,6 @@ public Answer delete(@PathVariable Long index, @PathVariable Long id, HttpSessio questionRepository.save(savedQuestion); - return savedAnswer; + return Result.ok(savedAnswer); } } diff --git a/src/main/resources/static/js/scripts.js b/src/main/resources/static/js/scripts.js index 987f1c90..2555b9c3 100755 --- a/src/main/resources/static/js/scripts.js +++ b/src/main/resources/static/js/scripts.js @@ -97,9 +97,10 @@ function deleteAnswerHandler(evt) { }) } -function deleteAnswer({id}) { - console.log(id); - const target = $(`.article-comment[data-id='${id}']`); +function deleteAnswer({data}) { + console.log(data); + console.log(data.id); + const target = $(`.article-comment[data-id='${data.id}']`); console.log(target); console.log(target.parentNode); target.parentNode.removeChild(target); From a7a8637e8a64af942644a3c203039657bcef4007 Mon Sep 17 00:00:00 2001 From: sunghyuki Date: Sat, 23 Apr 2022 10:27:41 +0900 Subject: [PATCH 8/9] =?UTF-8?q?feat=20:=20=EC=A7=88=EB=AC=B8=20=EB=8D=B0?= =?UTF-8?q?=EC=9D=B4=ED=84=B0=20=EC=82=AD=EC=A0=9C=20=EA=B0=80=EB=8A=A5=20?= =?UTF-8?q?=EC=A1=B0=EA=B1=B4=20=EC=B6=94=EA=B0=80=20-=20=EC=A7=88?= =?UTF-8?q?=EB=AC=B8=20=EB=8D=B0=EC=9D=B4=ED=84=B0=EA=B0=80=20=EB=B3=B4?= =?UTF-8?q?=EC=9C=A0=ED=95=9C=20=EB=AA=A8=EB=93=A0=20=EB=8B=B5=EB=B3=80=20?= =?UTF-8?q?=EB=8D=B0=EC=9D=B4=ED=84=B0=EC=9D=98=20=EC=82=AD=EC=A0=9C=20?= =?UTF-8?q?=EC=83=81=ED=83=9C=EA=B0=80=20true=EB=A5=BC=20=EA=B0=80?= =?UTF-8?q?=EC=A7=80=EB=8A=94=20=EA=B2=BD=EC=9A=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/codesquad/domain/question/Question.java | 7 +++++-- src/main/java/codesquad/web/QuestionController.java | 2 +- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/src/main/java/codesquad/domain/question/Question.java b/src/main/java/codesquad/domain/question/Question.java index 47b0fdcd..9ea76fba 100644 --- a/src/main/java/codesquad/domain/question/Question.java +++ b/src/main/java/codesquad/domain/question/Question.java @@ -24,7 +24,7 @@ public class Question extends BaseTimeEntity { @Column(nullable = false, columnDefinition = "TEXT") private String contents; - @OneToMany(mappedBy = "question") + @OneToMany(mappedBy = "question", cascade = CascadeType.ALL) @JsonIgnore private List answers; @@ -111,7 +111,10 @@ public boolean isDeleted() { } public boolean canDelete() { - if (countOfAnswer.equals(0)) { + boolean isAnswerStatusAllTrue = answers.stream() + .allMatch(answer -> answer.isDeleted() == true); + + if (countOfAnswer.equals(0) || isAnswerStatusAllTrue) { return true; } return false; diff --git a/src/main/java/codesquad/web/QuestionController.java b/src/main/java/codesquad/web/QuestionController.java index c8df6e0c..1abfe79a 100644 --- a/src/main/java/codesquad/web/QuestionController.java +++ b/src/main/java/codesquad/web/QuestionController.java @@ -134,7 +134,7 @@ public String delete(@PathVariable Long index, HttpSession httpSession, Redirect } if (!savedQuestion.canDelete()) { - throw new IllegalStateException("질문에 다른 사용자의 답변이 존재하여 질문을 삭제할 수 없습니다."); + throw new IllegalStateException("질문을 삭제할 수 없습니다."); } savedQuestion.delete(); From 8428d4e7ffbd3d620aabdad814b0f9fbe92d0840 Mon Sep 17 00:00:00 2001 From: sunghyuki Date: Sat, 23 Apr 2022 10:34:00 +0900 Subject: [PATCH 9/9] =?UTF-8?q?refactor=20:=20=EC=98=81=EC=86=8D=EC=84=B1?= =?UTF-8?q?=20=EC=A0=84=EC=9D=B4=20=EC=86=8D=EC=84=B1=20=EC=A0=9C=EA=B1=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/codesquad/domain/question/Question.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/codesquad/domain/question/Question.java b/src/main/java/codesquad/domain/question/Question.java index 9ea76fba..b85291ee 100644 --- a/src/main/java/codesquad/domain/question/Question.java +++ b/src/main/java/codesquad/domain/question/Question.java @@ -24,7 +24,7 @@ public class Question extends BaseTimeEntity { @Column(nullable = false, columnDefinition = "TEXT") private String contents; - @OneToMany(mappedBy = "question", cascade = CascadeType.ALL) + @OneToMany(mappedBy = "question") @JsonIgnore private List answers;