단 하나의 맥락
- Update / Delete 기능 구현
Semiflow Bundle
(Question Update)
- modifyDate
- 수정 버튼
- 수정 버튼 > @GetMapping
- CSRF 토큰 수동발행
- Service에서 modify method 추가
- Controller에서 서비스의 modify 메서드 연동
(Question Delete)
- 삭제 버튼
- 삭제 버튼 확인창 자바스크립트 연동
- 자바스크립트 블록 layout.html에 삽입
- QuestionService에 pubic void delete 추가
- QuestionController에 public String questiondelete 기능 구현
(Answer Update)
- 답변 수정 버튼 추가
- AnswerService에서 getAnswer, modify 기능 구현
- AnswerController
자각
(질문 수정)
수정 일시를 추가
> Quesiton, Answer Entity에
- private LoaclDateTIme modifyDate;
-
수정 버튼 추가
> question_detail 에
날짜 카드 밑에
- <div class="my-3"></div> 내부
- <a th:href="@{|/question/modify/${question.id}|}" class="btn btn-sm btn-outline-secondary"
- sec:authorize="isAuthenticated()"
- th:if="${question.author != null and #authentication.getPrincipal().getUsername() == question.author.username}"
- th:text="수정"></a>
-
@GetMapping으로 수정양식 불러오기 + 양식 내부에 기존 question 내용이 들어가 있다
> QuestionController에
// import org.springframework.http.HttpStatus;
// import org.springframework.web.server.ResponseStatusException;
- @PreAuthorize("isAuthenticated()")
- @GetMapping("/modify/{id}")
- M : public String questionModify
- S : (QuestionForm questionForm, @PathVariable("id") Integer id, Principal principal)
- A1 : Question question = this.questionService.getQuestion(id);
- A2 : if (!question.getAuthor().getUsername().equals(principal.getName())) {}
- throw new ResponseStatusException(HttpStatus.BAD_REQUEST, "수정권한이 없습니다.");
- A3 : questionForm.setSubject(question.getSubject);
- A4 : questionForm.setContent(question.getContent);
- A5 : return "question_form";
추가
-
CSRF 토큰을 수동으로 추가한다
> question_form.html에
폼 형식에
- <form
th:action="@{/question/create}"th:object="${questionForm}" method="post"></form>
를 삭제하고, 내부 에러 메세지 위
- <input type="hidden" th:name="${_csrf.parameterName}" th:value="${_csrf.token}" />
-
> QuestionService에 modify 메서드 신규 작성
- public void modify(Question question, String subject, String content)
- A1 : question.setSubject(subject);
- A2 : question.setContent(content);
- A3 : question.setModifyDate(LocalDateTime.now());
- A4 : this.questionRepository.save(question);
-
> QuestionController에 @PostMapping 추가
- @PreAuthorize("isAuthenticated()")
- @PostMapping("/modify/{id}")
- M : public String questionModify
- S : (@Valid QuestionForm questionForm, BindingResult bindingResult, Principal principal, @PathVariable("id") Integer id) {}
- A1 : if(bindingResult.hasErrors())
- { retrun "question_form";}
- A2 : Question question = this.questionService.getQuestion(id);
- A3 : if (!question.getAuthor().getUsername().equals(principal.getName()))
- {throw new ResponseStatusException(HttpStatus.BAD_REQUEST, "수정권한이 없습니다.");}
- A4 : this.questionService.modify(question, questionForm.getSubject()), questionForm.getContent());
- A5 : return String.format("redirect:/question/detail/%s", id);
-
로컬 서버를 실행시켜, 수정 버튼이 잘 동작하는 지 확인한다
-
질문 삭제
질문 삭제 버튼을 추가하기 위해
> question_detail.html 에서
- <a href="javascript:void(0)"
- th:data-uri="@{|/question/delete/${question.id}|}"
- class="delete btn btn-sm btn-outline-secondary"
- sec:authorize="isAuthenticated()"
- th:if="${question.author !=null and #authentication.getPrincipal().getUsername() == question.quthor.username}"
- th:text="삭제"></a>
수정버튼 하단에 작성
-
자바스크립트 블록을 추가하기 위해
> layout.html 에서
화면 렌더링이 완료된 후에 작동할 수 있도록 바디 태그 바로 위에 삽입하고
- <!-- JS Start -->
- <th:block layout:fragment="script"></th:block>
- <!-- JS End -->
> question_detail.html 에서
- <div layout:fragment="content" class="container my-3"></div>
하단에
- <script layout:fragment="script" type='text/javascript'></script> 내부
- const delete_elements = documents.getElementsByClassName("delete");
- Array.from(delete_elements).forEach(function(element)) {
- element.addEventListener('click', function()) {
- if (confirm("정말로 삭제하시겠습니까?")) {
- location.href = this.dataset.uri;
- };
- });
- element.addEventListener('click', function()) {
- });
를 작성한다
-
> QuestionService 에 질문 삭제 기능을 추가한다
- public void delete(Question question) {}
- this.quesitonRepository.delete(question);
-
> QuestionController에
삭제 메서드를 추가한다
- @PreAuthorize("isAuthenticated()")
- @GetMapping("/delete/{id}")
- M : public String questionDelete
- S : (Principal principal, @PathVariable("id") Integer id) {}
- A1 : Question question = this.questionService.getQuestion(id);
- A2 : if (!question.getAuthor.getUsername().equals(princiapl.getName())) {
- throw new ReponseStatusException(HttpStatus.BAD_REQUEST, "삭제권한이 없습니다."); }
- A3 : this.questionService.delete(question);
- A4 : return "redirect:/";
-
답변 수정
> question_detail.html 에서
답변 수정 버튼을 추가한다
답변 카드 내부, 답변 작성자와 답변 시각이 담긴 뱃지 하단에
- <div class="my-3"></div> 내부
- <a th:href="@{|/answer/modify/${answer.id}|}"
- class="btn btn-sm btn-outline-secondary"
- sec:authorize="isAuthenticated()"
- th:if="${answer.author != null and #authentiaction.getPrincipal().getUsername() == answer.author.username}"
- th:text="수정"></a>
로 버튼 작성
-
> AnswerService에 답변 조회와 답변 수정 기능 구현
// import java.util.Optional;
// import com.mysite.sbb.DataNotFoundException;
- public Answer getAnswer(Integer id) {}
- A1 : Optional<Answer> answer = this.answerRepository.findById(id);
- A2 :
- if (answer.isPresent))
- return answer.get();
- } else {
- throw new DataNotFoundException("answer not found"); }
- if (answer.isPresent))
- public void modify(Answer answer, String content)
- A1 : answer.setContent(content);
- A2 : answer.setModifyDate(LocalDateTime.now());
- A3 : this.answerRepository.save(answer);
-
> AnswerController에 서비스의 답변조회와 수정기능을 구현
// import org.springframework.http.HttpStatus;
// import org.springframework.web.bind.annotation.GetMapping;
// import org.springframework.web.server.ResponseStatusException;
- @PreAuthorize("isAuthenticated()")
- @GetMapping("/modify/{id}")
- M : public String answerModify
- S : (AnswerForm answerForm, @PathVariable("id") Integer id, Principal principal)
- A1: Answer answer = this.answerService.getAnswer(id);
- A2 : if (!anwer.getAuthor().getUsername().equals(principal.getName())) {}
- throw new ResponseStatusException(HttpStatus.BAD_REQUEST, "수정권한이 없습니다.");
- A3 : answerForm.setContent(answer.getContent());
- A4 : return "answer_form";
-
> answer_form.html 신규 작성
틀
- <html layout:decorate="~{layout}"></html> 내부
- <div layout:fragment="content" class="container"></div>
틀 내부 최상단에 제목
- <h5 class="my-3 border-bottom pb-2">답변 수정</h5>
제목 아래 폼 작성
- <form th:object="${answerForm}" method="post"></form>
폼 내부
- 1 : <input type="hidden" th:name="${_csrf.parameterName}" th:value="${_csrt.token}" />
- 2 : <div th:replace="form_errors :: formErrorsFragment"></div>
- 3 :
- <div class="mb-3"></div> 내부
- <label for="content" class="form-label">내용</label>
- <textarea th:field="*{content}" class="form-control" rows="10"></textarea>
- 4 : <input type="submit" value="저장하기" class="btn btn-primary my-2">
-
> AnswerController에서
- @PreAuthorize("isAuthenticated()")
- @PostMapping("/modify/{id}")
- M : public String answerModify
- S : (@Valid AnswerForm answerForm, BindingResult bindingResult, @PathVariable("id") Integer id, Principal principal)
- A1 : if (bindingResult.hasErrors())
- return "answer_form";
- A2 : Answer answer = this.answerService.getAnswer(id);
- A3 : if (!answer.getAuthor().getUsername().equals(principal.getName()))
- throw new ResponseStatusException(HttpStatus.BAD_REQUEST, "수정권한이 없습니다");
- A4 : this.answerService.modify(answer, answerForm.getContent());
- R : return String.format("redirect:/question/detail/%s", answer.getQuestion().getId());
- A1 : if (bindingResult.hasErrors())
-
답변 수정 동작 확인
-
답변 삭제
-
> question_detail.html
수정 버튼 하단에 답변 삭제 버튼을 추가한다
- <a href="javascript:void(0);"
- th:data-uri="@{|/answer/delete/${answer.id}|}"
- class="delete btn btn-sm btn-outline-secondary"
- sec:authorize="isAuthenticated()"
- th:if="${answer.author != null and #authentication.getPrincipal().getUsername() == answer.author.username}"
- th:text="삭제"></a>
-
> AnswerService에
답변 삭제 메서드 추가
- public void delete(Answer answer) {}
- this.answerRespository.delete(answer);
-
> AnswerController에
- @PreAuthorize("isAuthenticated()")
- @GetMapping("/delete/{id}")
- M : public String answerDelete
- S : (Principal principal, @PathVariable("id") Integer id)
- A1 : Answer answer = this.answerService.getAnswer(id);
- A2 : if (!answer.getAuthor().getUsername().equals(principal.getName()))
- throw new ResponseStatusException(HttpStatus.BAD_REQUEST, "삭제권한이 없습니다");
- A3 : this.answerService.delete(answer);
- R : return String.format("redirect:/question/detatil/%s", answer.getQuestion().getId());
-
로컬 서버 켜서 삭제 버튼 확인
수정일시 표시하기
> question_detail.html 에서
동일 "d-flex justify-contend-end" 클래스 내부, 질문 작성자 및 작성일시 뱃지 위에
- <div th:if="${question.modifyDate != null}"
- class="badge bg-light text-dark p-2 text-start"></div> 로 뱃지를 잡고
- <div class="mb-2">modified at</div>
- <div th:text="${#temporals.format(question.modifyDate, 'yyyy-MM-dd HH:mm')}"></div>
로 내용 기재
동일 "d-flex justify-contend-end" 클래스 내부, 답변 작성자 및 작성일시 뱃지 위에
- <div th:if="${answer.modifyDate != null}"
- class="badge bg-light text-dark p-2 text-start"></div> 로 뱃지를 잡고
- <div class="mb-2">modified at</div>
- <div th:text="${#temporals.format(question.modifyDate, 'yyyy-MM-dd HH:mm')}"></div>
'포트폴리오 > SPRINGBOOT 옛날' 카테고리의 다른 글
3-11 : 추천 (0) | 2022.10.13 |
---|---|
03 : GetMapping과 PostMapping (0) | 2022.10.13 |
3 - 09 : 글쓴이 표시 (0) | 2022.10.10 |
3-08 : entity에 author 추가하기 (0) | 2022.10.10 |
3-07 : 로그인과 로그아웃 (0) | 2022.10.09 |