-
Notifications
You must be signed in to change notification settings - Fork 151
Issue #906 backend админ панель раздел интервью #954
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Issue #906 backend админ панель раздел интервью #954
The head ref may contain hidden characters: "Issue-#906-Backend-\u0410\u0434\u043C\u0438\u043D-\u043F\u0430\u043D\u0435\u043B\u044C-\u0440\u0430\u0437\u0434\u0435\u043B-\u0438\u043D\u0442\u0435\u0440\u0432\u044C\u044E"
Conversation
…or firstName/lastName of speaker [iss 906].
…r. In case speaker not present in update request - do nothing, if speakerId : null - update Interview and set speaker to null, if speakerId : someValue - update Interview and set speaker [iss 906].
…guments, search method now receives String except for DTO, method for update Interview now uses custom created method in InterviewMapper [iss 906].
…nterview [iss 906].
…Id in InterviewDTO [iss 906].
…l field, fix naming of lastName field, move class in user package [iss 906].
…l field, fix naming of lastName field in InterviewMapper [iss 906].
…viewController [iss 906].
…update dto [iss 906].
…xlet. Dont understand how these files appears in my branch [iss 906].
|
|
Мы мигрировали логику через application.yml c использованием Pageable (напрямую в параметрах метода) |
|
`catch (InterviewNotFoundException ex) { Дублирование кода в контроллере. |
JsonNullable в DTO .get() никогда не вернет null если isPresent() == true (мне так кажется) не только в этом методе |
У тебя сервис создает интервью и возвращает данные, но контроллер эти данные теряет и делает редирект( нужен редирект на создание интервью, а не на весь список) там надо + createdInterview.get..... И у тебя POST HTTP. статус другой 302 Found у тебя CREATE. Это моё мнение может быть не прав |
здесь у тебя одно исключение, а в сервисе UserNotFoundException и InterviewNotFoundException (посмотри в коде) несогласованность. Вроде как рекомендовано использовать единообразие в исключениях, так как разные исключения затрудняют обработку ошибок. В контроллере ловится у тебя InterviewNotFoundException |
Не понял о чем тут речь. Зашел глянуть на application.yml ы в main ветке, но ничего связанного с Pageable не вижу |
|
|
||
| @GetMapping | ||
| @ResponseStatus(HttpStatus.OK) | ||
| public ResponseEntity<?> index(@PathVariable("locale") String locale, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
локаль в запросы не передаем, интерфейс будет локализовываться на фронте
|
|
||
| Map<String, Object> props = flashPropsService.buildProps(locale, request); | ||
|
|
||
| int safeSize = Math.min(size, MAX_INTERVIEWS_ON_PAGE); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
логику принято держать в сервисах, перенеси, пжл, вот этот кусок:
Pageable pageable = PageRequest.of(page, safeSize, Sort.by("createdAt").descending());
Page<InterviewDTO> interviewPage = StringUtils.hasText(interviewSearchWord)
? interviewService.search(interviewSearchWord, pageable)
: interviewService.getAll(pageable);
| private final UserService userService; | ||
| private final InterviewService interviewService; | ||
|
|
||
| private static final int MAX_INTERVIEWS_ON_PAGE = 100; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Вероятно, эти константы больше не нужны, так как в application.yml добавили
data:
web:
pageable:
default-page-size: 10
max-page-size: 100
| @ResponseStatus(HttpStatus.OK) | ||
| public ResponseEntity<?> index(@PathVariable("locale") String locale, | ||
| @RequestParam(required = false) String interviewSearchWord, | ||
| @RequestParam(defaultValue = DEFAULT_PAGE_TO_SHOW) int page, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Можно сделать передачу параметров как в LearningProgressController:
public Object getProgress(@PageableDefault(size = 10) Pageable pageable)
Заодно потести, пжл, можно ли обойтись вообще без @PageableDefault(size = 10), весь в ямле вроде указали дефолт default-page-size: 10
|
|
||
| return inertia.render("Admin/Interviews/Show", props); | ||
|
|
||
| } catch (InterviewNotFoundException ex) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Обработку ошибок лучше вынести в GlobalExceptionHandler
| RedirectAttributes redirectAttributes) { | ||
| try { | ||
| interviewService.update(updateDTO, id); | ||
| redirectAttributes.addFlashAttribute("success", "Интервью успешно обновлено"); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Локализованные константы убираем с бэкенда, лучше типа такого:
redirectAttributes.addFlashAttribute("success", "update.success");
| return dto; | ||
| } | ||
|
|
||
| /*public Interview convertDtoToEntity(InterviewDTO dto) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
если код не нужен, лучше удалить
|
Пожалуйста, опиши более подробно, что именно и как реализовано, по аналогии с тем, как сделано здесь: |
| @Getter | ||
| @Setter | ||
| public class InterviewUpdateDTO { | ||
| private JsonNullable<String> title; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
для полей входящих дто можно использовать валидацию с помощью аннотаций, например @notblank, тогда не придется валидировать в конвертере
| } | ||
| } | ||
|
|
||
| public User speakerIdToSpeaker(Long speakerId) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
метод получения сущности по id должен быть в сервисе, а не в конвертере
| public UserDTO speakerToSummary(User speaker) { | ||
| UserDTO result = new UserDTO(); | ||
|
|
||
| if (speaker == null) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
первым делом проверить на null и вернуть то, что нужно, и дальше уже писать не в ветке else, а просто
| if (speaker == null) { | ||
| return null; | ||
| } else { | ||
| result.setEmail(speaker.getEmail()); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Лучше через билдер
| @NotBlank(message = "Title is required.") | ||
| private String title; | ||
|
|
||
| private Long speakerId; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Это поле будет приходить с фронта при создании сущности? По идее не должно, и тогда его лучше из дто убрать
| public abstract class ReferenceMapper { | ||
|
|
||
| @Autowired | ||
| private EntityManager entityManager; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Мапперы только перекладывают готовые поля из одних дто в другие, в них не нужно ходить в базу
| @@ -0,0 +1,4 @@ | |||
| package io.hexlet.cv.model; | |||
|
|
|||
| public interface BaseEntity { | |||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Расскажи, пожалуйста, как ты видишь дальнейшее использование этого базового класса?
| return dto; | ||
| } | ||
|
|
||
| public InterviewDTO update(InterviewUpdateDTO updateDTO, Long id) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Лучше спроектировать апи так, чтобы для изменения приходило одно поле или ограниченный логически связанный набор полей. Можно поговорить с фронтами и узнать, как выглядит окно редактирования, предложить вариант, когда разные поля редактируются и сохраняются отдельно.
|
|
||
| Join<Interview, User> speakerJoin = root.join("speaker", JoinType.LEFT); | ||
|
|
||
| conditions.add(builder.like(builder.lower(root.get("title")), "%" + processedKeyword + "%")); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
вместо конкатенации можно использовать builder.like
|
|
||
| @AfterEach | ||
| void cleanUp() { | ||
| interviewRepository.deleteAll(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Получится ли сделать так, чтобы у каждого теста были свои тестовые данные, не зависящие от другого теста, чтобы не приходилось после каждого запуска теста чистить базу?
| assertThat(result.getIsPublished()).isFalse(); | ||
| } | ||
|
|
||
| /*@Test |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Если код не нужен, лучше удалить
Реализовал логику для интервью в разделе админ