From 6b5d17f0cb5ec0467ba0c14d5550fbeb8ea8a9c4 Mon Sep 17 00:00:00 2001 From: Factorino73 Date: Fri, 10 May 2024 23:11:17 +0400 Subject: [PATCH] LabWork04-05 / WIP 2.0 --- demo/data.mv.db | Bin 45056 -> 81920 bytes .../com/example/demo/DemoApplication.java | 3 + .../demo/core/api/PageAttributesMapper.java | 8 +- .../demo/messages/api/MessageController.java | 87 ++++++++++++++++++ .../example/demo/messages/api/MessageDto.java | 4 - .../demo/messages/service/MessageService.java | 11 +++ .../demo/users/api/UserController.java | 7 +- .../demo/users/api/UserMessageController.java | 85 +++++++++++++++++ .../demo/users/api/UserProfileController.java | 2 + .../demo/users/service/UserService.java | 1 - .../src/main/resources/templates/default.html | 2 +- .../resources/templates/message-edit.html | 24 +++++ .../main/resources/templates/messages.html | 52 +++++++---- .../src/main/resources/templates/profile.html | 14 +-- .../main/resources/templates/type-edit.html | 2 +- .../main/resources/templates/user-edit.html | 10 +- .../resources/templates/user-messages.html | 45 +++++++++ demo/src/main/resources/templates/user.html | 8 +- 18 files changed, 317 insertions(+), 48 deletions(-) create mode 100644 demo/src/main/java/com/example/demo/messages/api/MessageController.java create mode 100644 demo/src/main/java/com/example/demo/users/api/UserMessageController.java create mode 100644 demo/src/main/resources/templates/message-edit.html create mode 100644 demo/src/main/resources/templates/user-messages.html diff --git a/demo/data.mv.db b/demo/data.mv.db index 3b01bbae3f15169559292114aee76b9b333d0234..f8038221c61166ab596105ff436cd5d5686da578 100644 GIT binary patch literal 81920 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 diff --git a/demo/src/main/java/com/example/demo/DemoApplication.java b/demo/src/main/java/com/example/demo/DemoApplication.java index ce8607d..9bd34ec 100644 --- a/demo/src/main/java/com/example/demo/DemoApplication.java +++ b/demo/src/main/java/com/example/demo/DemoApplication.java @@ -66,6 +66,9 @@ public class DemoApplication implements CommandLineRunner { final var user1 = userService.create(new UserEntity("User1", "password", "mail1@gmail.com")); final var user2 = userService.create(new UserEntity("User2", "password", "mail2@gmail.com")); final var user3 = userService.create(new UserEntity("User3", "password", "mail3@gmail.com")); + final var admin = new UserEntity("admin", "admin", "admin@gmail.com"); + admin.setRole(UserRole.ADMIN); + userService.create(admin); log.info("Create default order values"); final var orders = List.of( diff --git a/demo/src/main/java/com/example/demo/core/api/PageAttributesMapper.java b/demo/src/main/java/com/example/demo/core/api/PageAttributesMapper.java index 4b5af2c..69697b3 100644 --- a/demo/src/main/java/com/example/demo/core/api/PageAttributesMapper.java +++ b/demo/src/main/java/com/example/demo/core/api/PageAttributesMapper.java @@ -11,10 +11,10 @@ public class PageAttributesMapper { } // Метод преобразования - public static Map toAttributes(Page page, Function mapper) { + public static Map toAttributes(String prefix, Page page, Function mapper) { return Map.of( - "items", page.getContent().stream().map(mapper::apply).toList(), - "currentPage", page.getNumber(), - "totalPages", page.getTotalPages()); + prefix + "Items", page.getContent().stream().map(mapper::apply).toList(), + prefix + "CurrentPage", page.getNumber(), + prefix + "TotalPages", page.getTotalPages()); } } diff --git a/demo/src/main/java/com/example/demo/messages/api/MessageController.java b/demo/src/main/java/com/example/demo/messages/api/MessageController.java new file mode 100644 index 0000000..57d3396 --- /dev/null +++ b/demo/src/main/java/com/example/demo/messages/api/MessageController.java @@ -0,0 +1,87 @@ +package com.example.demo.messages.api; + +import java.util.Map; + +import org.modelmapper.ModelMapper; +import org.springframework.stereotype.Controller; +import org.springframework.ui.Model; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.servlet.mvc.support.RedirectAttributes; + +import com.example.demo.core.api.PageAttributesMapper; +import com.example.demo.core.configuration.Constants; +import com.example.demo.messages.model.MessageEntity; +import com.example.demo.messages.service.MessageService; + +// Контроллер для сущности "Сообщение" +@Controller +@RequestMapping(MessageController.URL) +public class MessageController { + // URL для доступа к методам контроллера + public static final String URL = Constants.ADMIN_PREFIX + "/message"; + + // Представление для отображения списка сообщений + private static final String MESSAGE_VIEW = "messages"; + + // Атрибут модели для пагинации + private static final String PAGE_ATTRIBUTE = "page"; + + // Бизнес-логика для сущности "Сообщение" + private final MessageService messageService; + + // Библиотека для преобразования сущности + private final ModelMapper modelMapper; + + // Конструктор + public MessageController(MessageService messageService, ModelMapper modelMapper) { + this.messageService = messageService; + this.modelMapper = modelMapper; + } + + // Преобразовать из сущности в DTO + private MessageDto toDto(MessageEntity entity) { + return modelMapper.map(entity, MessageDto.class); + } + + // Получить все элементы + @GetMapping + public String getAll( + @RequestParam(name = PAGE_ATTRIBUTE, defaultValue = "0") int page, + Model model) { + final Map attributes = PageAttributesMapper.toAttributes( + "message", + messageService.getAll(0L, page, Constants.DEFAULT_PAGE_SIZE), this::toDto); + model.addAllAttributes(attributes); + model.addAttribute(PAGE_ATTRIBUTE, page); + return MESSAGE_VIEW; + } + + // Удалить элемент + @PostMapping("/delete/{id}") + public String delete( + @PathVariable(name = "id") Long id, + @RequestParam(name = PAGE_ATTRIBUTE, defaultValue = "0") int page, + RedirectAttributes redirectAttributes) { + redirectAttributes.addAttribute(PAGE_ATTRIBUTE, page); + final var messageEntity = messageService.get(id); + messageService.delete(messageEntity.getUser().getId(), id); + return Constants.REDIRECT_VIEW + URL; + } + + // Опубликовать сообщение + @PostMapping("/publish/{id}") + public String publish( + @PathVariable(name = "id") Long id, + @RequestParam(name = PAGE_ATTRIBUTE, defaultValue = "0") int page, + RedirectAttributes redirectAttributes) { + redirectAttributes.addAttribute(PAGE_ATTRIBUTE, page); + final var messageEntity = messageService.get(id); + messageEntity.setIsPublished(true); + messageService.update(messageEntity.getUser().getId(), id, messageEntity); + return Constants.REDIRECT_VIEW + URL; + } +} diff --git a/demo/src/main/java/com/example/demo/messages/api/MessageDto.java b/demo/src/main/java/com/example/demo/messages/api/MessageDto.java index 553c3cf..6c728db 100644 --- a/demo/src/main/java/com/example/demo/messages/api/MessageDto.java +++ b/demo/src/main/java/com/example/demo/messages/api/MessageDto.java @@ -4,9 +4,7 @@ import java.time.LocalDateTime; import com.fasterxml.jackson.annotation.JsonProperty; -import jakarta.validation.constraints.Min; import jakarta.validation.constraints.NotBlank; -import jakarta.validation.constraints.NotNull; // DTO для сущности "Сообщение" public class MessageDto { @@ -14,8 +12,6 @@ public class MessageDto { private Long id; // Электронная почта отправителя - @NotNull - @Min(1) private String userEmail; // Текст сообщения diff --git a/demo/src/main/java/com/example/demo/messages/service/MessageService.java b/demo/src/main/java/com/example/demo/messages/service/MessageService.java index 1324713..07ae0c8 100644 --- a/demo/src/main/java/com/example/demo/messages/service/MessageService.java +++ b/demo/src/main/java/com/example/demo/messages/service/MessageService.java @@ -3,6 +3,7 @@ package com.example.demo.messages.service; import java.util.List; import java.util.stream.StreamSupport; +import org.hibernate.Hibernate; import org.springframework.data.domain.Page; import org.springframework.data.domain.PageRequest; import org.springframework.stereotype.Service; @@ -62,6 +63,15 @@ public class MessageService { .orElseThrow(() -> new NotFoundException(MessageEntity.class, id)); } + // Получить элемент по идентификатору + @Transactional(readOnly = true) + public MessageEntity get(Long id) { + MessageEntity message = repository.findById(id) + .orElseThrow(() -> new NotFoundException(MessageEntity.class, id)); + Hibernate.initialize(message.getUser().getMessages()); + return message; + } + // Создать элемент @Transactional public MessageEntity create(Long userId, MessageEntity entity) { @@ -80,6 +90,7 @@ public class MessageService { final MessageEntity existsEntity = get(userId, id); existsEntity.setUser(entity.getUser()); existsEntity.setText(entity.getText()); + existsEntity.setIsPublished(entity.getIsPublished()); return repository.save(existsEntity); } diff --git a/demo/src/main/java/com/example/demo/users/api/UserController.java b/demo/src/main/java/com/example/demo/users/api/UserController.java index 47c5a81..d0ee5ab 100644 --- a/demo/src/main/java/com/example/demo/users/api/UserController.java +++ b/demo/src/main/java/com/example/demo/users/api/UserController.java @@ -3,6 +3,7 @@ package com.example.demo.users.api; import java.util.Map; import org.modelmapper.ModelMapper; +import org.springframework.stereotype.Controller; import org.springframework.ui.Model; import org.springframework.validation.BindingResult; import org.springframework.web.bind.annotation.GetMapping; @@ -11,7 +12,6 @@ import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestParam; -import org.springframework.web.bind.annotation.RestController; import org.springframework.web.servlet.mvc.support.RedirectAttributes; import com.example.demo.core.api.PageAttributesMapper; @@ -22,8 +22,8 @@ import com.example.demo.users.service.UserService; import jakarta.validation.Valid; // Контроллер для сущности "Пользователь" -@RestController -@RequestMapping(UserController.URL + "/user") +@Controller +@RequestMapping(UserController.URL) public class UserController { // URL для доступа к методам контроллера public static final String URL = Constants.ADMIN_PREFIX + "/user"; @@ -68,6 +68,7 @@ public class UserController { @RequestParam(name = PAGE_ATTRIBUTE, defaultValue = "0") int page, Model model) { final Map attributes = PageAttributesMapper.toAttributes( + "user", userService.getAll(page, Constants.DEFAULT_PAGE_SIZE), this::toDto); model.addAllAttributes(attributes); model.addAttribute(PAGE_ATTRIBUTE, page); diff --git a/demo/src/main/java/com/example/demo/users/api/UserMessageController.java b/demo/src/main/java/com/example/demo/users/api/UserMessageController.java new file mode 100644 index 0000000..3d89457 --- /dev/null +++ b/demo/src/main/java/com/example/demo/users/api/UserMessageController.java @@ -0,0 +1,85 @@ +package com.example.demo.users.api; + +import java.time.LocalDateTime; + +import org.modelmapper.ModelMapper; +import org.springframework.security.core.annotation.AuthenticationPrincipal; +import org.springframework.stereotype.Controller; +import org.springframework.ui.Model; +import org.springframework.validation.BindingResult; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.ModelAttribute; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.servlet.mvc.support.RedirectAttributes; + +import com.example.demo.core.configuration.Constants; +import com.example.demo.core.security.UserPrincipal; +import com.example.demo.messages.api.MessageDto; +import com.example.demo.messages.model.MessageEntity; +import com.example.demo.messages.service.MessageService; + +import jakarta.validation.Valid; + +// Контроллер для работы с корзиной покупок пользователя +@Controller +@RequestMapping(UserMessageController.URL) +public class UserMessageController { + // URL для доступа к методам контроллера + public static final String URL = "/message"; + + // Представление для написания сообщения + private static final String MESSAGE_EDIT_VIEW = "message-edit"; + + // Атрибут модели для обработки данных + private static final String MESSAGE_ATTRIBUTE = "message"; + + // Атрибут модели для пагинации + private static final String PAGE_ATTRIBUTE = "page"; + + // Бизнес-логика для сущости "Сообщение" + private final MessageService messageService; + + // Библиотека для преобразования сущности + private final ModelMapper modelMapper; + + public UserMessageController(MessageService messageService, ModelMapper modelMapper) { + this.messageService = messageService; + this.modelMapper = modelMapper; + } + + private MessageEntity toEntity(MessageDto dto) { + return modelMapper.map(dto, MessageEntity.class); + } + + // Отправить сообщение + @GetMapping("/send/") + public String sendMessage( + @RequestParam(name = PAGE_ATTRIBUTE, defaultValue = "0") int page, + Model model) { + model.addAttribute(MESSAGE_ATTRIBUTE, new MessageDto()); + model.addAttribute(PAGE_ATTRIBUTE, page); + return MESSAGE_EDIT_VIEW; + } + + // Отправить сообщение + @PostMapping("/send/") + public String sendMessage( + @RequestParam(name = PAGE_ATTRIBUTE, defaultValue = "0") int page, + @ModelAttribute(name = MESSAGE_ATTRIBUTE) @Valid MessageDto message, + BindingResult bindingResult, + Model model, + @AuthenticationPrincipal UserPrincipal principal, + RedirectAttributes redirectAttributes) { + if (bindingResult.hasErrors()) { + model.addAttribute(PAGE_ATTRIBUTE, page); + return MESSAGE_EDIT_VIEW; + } + + redirectAttributes.addAttribute(PAGE_ATTRIBUTE, page); + message.setDate(LocalDateTime.now()); + messageService.create(principal.getId(), toEntity(message)); + return Constants.REDIRECT_VIEW + "/"; + } +} diff --git a/demo/src/main/java/com/example/demo/users/api/UserProfileController.java b/demo/src/main/java/com/example/demo/users/api/UserProfileController.java index 619ce96..c7c38cd 100644 --- a/demo/src/main/java/com/example/demo/users/api/UserProfileController.java +++ b/demo/src/main/java/com/example/demo/users/api/UserProfileController.java @@ -87,6 +87,7 @@ public class UserProfileController { model.addAttribute(TYPEID_ATTRIBUTE, typeId); model.addAllAttributes(PageAttributesMapper.toAttributes( + "order", orderService.getAll(userId, typeId, page, Constants.DEFAULT_PAGE_SIZE), this::toDto)); @@ -101,6 +102,7 @@ public class UserProfileController { .toList()); model.addAllAttributes(PageAttributesMapper.toAttributes( + "message", messageService.getAll(userId, page, Constants.DEFAULT_PAGE_SIZE), this::toMessageDto)); return PROFILE_VIEW; diff --git a/demo/src/main/java/com/example/demo/users/service/UserService.java b/demo/src/main/java/com/example/demo/users/service/UserService.java index 8673bbe..ae3a8e4 100644 --- a/demo/src/main/java/com/example/demo/users/service/UserService.java +++ b/demo/src/main/java/com/example/demo/users/service/UserService.java @@ -107,7 +107,6 @@ public class UserService implements UserDetailsService { public UserEntity update(Long id, UserEntity entity) { final UserEntity existsEntity = get(id); existsEntity.setUsername(entity.getUsername()); - existsEntity.setPassword(entity.getPassword()); existsEntity.setEmail(entity.getEmail()); return repository.save(existsEntity); } diff --git a/demo/src/main/resources/templates/default.html b/demo/src/main/resources/templates/default.html index d18053a..359c0bf 100644 --- a/demo/src/main/resources/templates/default.html +++ b/demo/src/main/resources/templates/default.html @@ -40,7 +40,7 @@ - Список сообщений + Сообщения Консоль H2 diff --git a/demo/src/main/resources/templates/message-edit.html b/demo/src/main/resources/templates/message-edit.html new file mode 100644 index 0000000..e607b70 --- /dev/null +++ b/demo/src/main/resources/templates/message-edit.html @@ -0,0 +1,24 @@ + + + + + Отправить сообщение + + + +
+
+
+ + +
+
+
+ + Отмена +
+
+
+ + + \ No newline at end of file diff --git a/demo/src/main/resources/templates/messages.html b/demo/src/main/resources/templates/messages.html index ec1da15..c166b49 100644 --- a/demo/src/main/resources/templates/messages.html +++ b/demo/src/main/resources/templates/messages.html @@ -1,17 +1,17 @@ - + + + + Сообщения + - - +
+

Данные отсутствуют

-
-
- -
-
- +

Сообщения

+
@@ -19,28 +19,44 @@ + + + - + + + +
Отправитель Сообщение Дата отправкиОпубликовано
+ + +
+ + +
+
+
+ + +
+
- + url=${'admin/message'}, + totalPages=${messageTotalPages}, + currentPage=${messageCurrentPage}) }" /> -
- +
\ No newline at end of file diff --git a/demo/src/main/resources/templates/profile.html b/demo/src/main/resources/templates/profile.html index ebcb0b2..fc48b21 100644 --- a/demo/src/main/resources/templates/profile.html +++ b/demo/src/main/resources/templates/profile.html @@ -22,9 +22,9 @@
+ items=${orderItems}, + totalPages=${orderTotalPages}, + currentPage=${orderCurrentPage}) }" />
    @@ -36,10 +36,10 @@
- +
diff --git a/demo/src/main/resources/templates/type-edit.html b/demo/src/main/resources/templates/type-edit.html index 91f03ca..d069c04 100644 --- a/demo/src/main/resources/templates/type-edit.html +++ b/demo/src/main/resources/templates/type-edit.html @@ -2,7 +2,7 @@ - Редакторовать тип заказа + Редактировать тип заказа diff --git a/demo/src/main/resources/templates/user-edit.html b/demo/src/main/resources/templates/user-edit.html index a967148..8cb5a73 100644 --- a/demo/src/main/resources/templates/user-edit.html +++ b/demo/src/main/resources/templates/user-edit.html @@ -2,7 +2,7 @@ - Редакторовать пользователя + Редактировать пользователя @@ -14,12 +14,12 @@
- - -
+ + +
- +
diff --git a/demo/src/main/resources/templates/user-messages.html b/demo/src/main/resources/templates/user-messages.html new file mode 100644 index 0000000..5c3c570 --- /dev/null +++ b/demo/src/main/resources/templates/user-messages.html @@ -0,0 +1,45 @@ + + + + + + +

Данные отсутствуют

+ + + + + + + + + + + + + + + + + + + + + +
IDОтправительСообщениеДата отправкиОпубликовано
+ +
+
+ + + +
+ + + + \ No newline at end of file diff --git a/demo/src/main/resources/templates/user.html b/demo/src/main/resources/templates/user.html index d183859..f283313 100644 --- a/demo/src/main/resources/templates/user.html +++ b/demo/src/main/resources/templates/user.html @@ -7,7 +7,7 @@
- +

Данные отсутствуют

Пользователи

@@ -26,7 +26,7 @@ - + @@ -49,8 +49,8 @@
+ totalPages=${userTotalPages}, + currentPage=${userCurrentPage}) }" />