diff --git a/data/db.mv.db b/data/db.mv.db index 49a6a54..1c534f2 100644 Binary files a/data/db.mv.db and b/data/db.mv.db differ diff --git a/src/main/java/ru/ulstu/configuration/SecurityConfiguration.java b/src/main/java/ru/ulstu/configuration/SecurityConfiguration.java index f893257..f479e11 100644 --- a/src/main/java/ru/ulstu/configuration/SecurityConfiguration.java +++ b/src/main/java/ru/ulstu/configuration/SecurityConfiguration.java @@ -45,7 +45,7 @@ public class SecurityConfiguration extends WebSecurityConfigurerAdapter { log.debug("Security enabled"); http.authorizeRequests() .antMatchers("/").permitAll() - .antMatchers("/login", "/index", "/news/**", "/h2-console/*", "/h2-console").permitAll() + .antMatchers("/login", "/index", "/news/**", "/meetings/**", "/h2-console/*", "/h2-console").permitAll() .antMatchers("/swagger-ui.html").hasAuthority(UserRoleConstants.ADMIN) .anyRequest().authenticated() .and() diff --git a/src/main/java/ru/ulstu/controller/NewsController.java b/src/main/java/ru/ulstu/controller/NewsController.java index a2f2859..139daa5 100644 --- a/src/main/java/ru/ulstu/controller/NewsController.java +++ b/src/main/java/ru/ulstu/controller/NewsController.java @@ -59,6 +59,7 @@ public class NewsController { } @GetMapping("/editNews/{newsId}") + @Secured({UserRoleConstants.ADMIN}) public String editNews(@PathVariable(value = "newsId") Integer id, Model model) { model.addAttribute("news", (id != null && id != 0) ? newsService.getById(id) : new News()); return "editNews"; @@ -82,6 +83,7 @@ public class NewsController { } @GetMapping("deleteNews/{newsId}") + @Secured({UserRoleConstants.ADMIN}) public String delete(@PathVariable(value = "newsId") Integer id) { newsService.delete(id); return "redirect:/news/news"; diff --git a/src/main/java/ru/ulstu/meeting/Meeting.java b/src/main/java/ru/ulstu/meeting/Meeting.java new file mode 100644 index 0000000..fcc9266 --- /dev/null +++ b/src/main/java/ru/ulstu/meeting/Meeting.java @@ -0,0 +1,55 @@ +package ru.ulstu.meeting; + +import org.springframework.format.annotation.DateTimeFormat; +import ru.ulstu.model.BaseEntity; + +import javax.persistence.Entity; +import javax.persistence.Lob; +import javax.validation.constraints.NotEmpty; +import java.util.Date; + +@Entity +public class Meeting extends BaseEntity { + @NotEmpty(message = "Заголовок не может быть пустым") + private String title; + + @DateTimeFormat(pattern = "yyyy-MM-dd'T'HH:mm") + private Date date; + + @Lob + @NotEmpty(message = "Текст заседания не может быть пустым") + private String text; + + public Meeting() { + } + + public Meeting(String title, String text, Date date) { + this.title = title; + this.date = date; + this.text = text; + } + + public String getTitle() { + return title; + } + + public Date getDate() { + return date; + } + + public void setDate(Date date) { + this.date = date; + } + + public void setTitle(String title) { + this.title = title; + } + + public void setText(String text) { + this.text = text; + } + + public String getText() { + return text; + } +} diff --git a/src/main/java/ru/ulstu/meeting/MeetingController.java b/src/main/java/ru/ulstu/meeting/MeetingController.java new file mode 100644 index 0000000..f85eea3 --- /dev/null +++ b/src/main/java/ru/ulstu/meeting/MeetingController.java @@ -0,0 +1,88 @@ +/* + * Copyright (C) 2021 Anton Romanov - All Rights Reserved + * You may use, distribute and modify this code, please write to: romanov73@gmail.com. + * + */ + +package ru.ulstu.meeting; + +import org.springframework.data.domain.Page; +import org.springframework.security.access.annotation.Secured; +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.PathVariable; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; +import ru.ulstu.model.OffsetablePageRequest; +import ru.ulstu.model.UserRoleConstants; + +import javax.validation.Valid; +import java.util.List; +import java.util.Optional; +import java.util.stream.Collectors; +import java.util.stream.IntStream; + +@Controller +@RequestMapping("meetings") +public class MeetingController { + private final static int DEFAULT_PAGE_SIZE = 10; + private final MeetingService meetingService; + + public MeetingController(MeetingService meetingService) { + this.meetingService = meetingService; + } + + @GetMapping("/meetings") + public String listMeetings(Model model, + @RequestParam Optional page, + @RequestParam Optional size) { + int currentPage = page.orElse(1); + int pageSize = size.orElse(DEFAULT_PAGE_SIZE); + + Page meetingsPage = meetingService.getMeetings(new OffsetablePageRequest(currentPage - 1, pageSize)); + model.addAttribute("meetings", meetingsPage); + int totalPages = meetingsPage.getTotalPages(); + if (totalPages > 0) { + List pageNumbers = IntStream.rangeClosed(1, totalPages) + .boxed() + .collect(Collectors.toList()); + model.addAttribute("pageNumbers", pageNumbers); + } + return "meetings"; + } + + @GetMapping("/editMeeting/{meetingId}") + @Secured({UserRoleConstants.ADMIN}) + public String editMeeting(@PathVariable(value = "meetingId") Integer id, Model model) { + model.addAttribute("meeting", (id != null && id != 0) ? meetingService.getById(id) : new Meeting()); + return "editMeeting"; + } + + @GetMapping("/meetings/{meetingId}") + public String viewMeeting(@PathVariable(value = "meetingId") Integer id, Model model) { + model.addAttribute("meeting", id != null ? meetingService.getById(id) : new Meeting()); + return "viewMeeting"; + } + + @PostMapping("saveMeeting") + @Secured({UserRoleConstants.ADMIN}) + public String saveNews(@Valid @ModelAttribute Meeting meeting, + BindingResult result) { + if (result.hasErrors()) { + return "editMeeting"; + } + meetingService.save(meeting); + return "redirect:/meetings/meetings"; + } + + @GetMapping("deleteMeeting/{meetingId}") + @Secured({UserRoleConstants.ADMIN}) + public String delete(@PathVariable(value = "meetingId") Integer id) { + meetingService.delete(id); + return "redirect:/meetings/meetings"; + } +} diff --git a/src/main/java/ru/ulstu/meeting/MeetingRepository.java b/src/main/java/ru/ulstu/meeting/MeetingRepository.java new file mode 100644 index 0000000..e3e964d --- /dev/null +++ b/src/main/java/ru/ulstu/meeting/MeetingRepository.java @@ -0,0 +1,9 @@ +package ru.ulstu.meeting; + +import org.springframework.data.domain.Page; +import org.springframework.data.domain.Pageable; +import org.springframework.data.jpa.repository.JpaRepository; + +interface MeetingRepository extends JpaRepository { + Page findByOrderByDateDesc(Pageable pageable); +} diff --git a/src/main/java/ru/ulstu/meeting/MeetingService.java b/src/main/java/ru/ulstu/meeting/MeetingService.java new file mode 100644 index 0000000..fb92aef --- /dev/null +++ b/src/main/java/ru/ulstu/meeting/MeetingService.java @@ -0,0 +1,47 @@ +package ru.ulstu.meeting; + +import org.springframework.data.domain.Page; +import org.springframework.data.domain.Pageable; +import org.springframework.stereotype.Service; +import ru.ulstu.service.NewsService; + +import javax.validation.constraints.NotNull; + +@Service +public class MeetingService { + private final MeetingRepository meetingRepository; + private final NewsService newsService; + + public MeetingService(MeetingRepository meetingRepository, + NewsService newsService) { + this.meetingRepository = meetingRepository; + this.newsService = newsService; + } + + public void create(Meeting meeting) { + meetingRepository.save(meeting); + newsService.create("Очередное заседание семинара", "Заседание семинара состоится " + meeting.getDate()); + } + + public void save(Meeting meeting) { + if (meeting.getId() != null && (meeting.getId() != 0)) { + meetingRepository.save(meeting); + } else { + create(meeting); + } + } + + public Meeting getById(@NotNull Integer id) { + return meetingRepository + .findById(id) + .orElseThrow(() -> new RuntimeException("Запись о заседании не найдена")); + } + + public void delete(Integer id) { + meetingRepository.deleteById(id); + } + + public Page getMeetings(Pageable pageable) { + return meetingRepository.findByOrderByDateDesc(pageable); + } +} diff --git a/src/main/resources/templates/admin.html b/src/main/resources/templates/admin.html index 22e05cf..a76d673 100644 --- a/src/main/resources/templates/admin.html +++ b/src/main/resources/templates/admin.html @@ -10,5 +10,8 @@ + + + diff --git a/src/main/resources/templates/default.html b/src/main/resources/templates/default.html index 99f7ed0..505c93c 100644 --- a/src/main/resources/templates/default.html +++ b/src/main/resources/templates/default.html @@ -36,10 +36,10 @@ Новости