Skip to content

Commit

Permalink
feat: Add announcements feature
Browse files Browse the repository at this point in the history
  • Loading branch information
prateekj117 authored and iamareebjamal committed Aug 27, 2018
1 parent 6f3df0b commit 97ebf3a
Show file tree
Hide file tree
Showing 19 changed files with 755 additions and 0 deletions.
41 changes: 41 additions & 0 deletions src/main/java/amu/zhcet/announcement/Announcement.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
package amu.zhcet.announcement;

import amu.zhcet.common.model.BaseIdEntity;
import amu.zhcet.data.user.User;
import amu.zhcet.email.LinkMessage;
import lombok.*;
import org.hibernate.envers.Audited;
import javax.persistence.*;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Size;
import java.time.LocalDateTime;
import java.util.function.Function;

@Data
@Entity
@Audited
@Builder
@NoArgsConstructor
@AllArgsConstructor
@EqualsAndHashCode(callSuper = false)
public class Announcement extends BaseIdEntity {

@OneToOne(fetch = FetchType.LAZY)
private User sender;
@Size(max = 150)
private String title;
@NotBlank
@Size(max = 500)
private String message;
@NotNull
private boolean scheduled;
private LocalDateTime sentTime = LocalDateTime.now();
private boolean automated;

private transient boolean stopEmailPropagation;
private transient boolean stopFirebasePropagation;
private transient String icon = "https://zhcet-backend.firebaseapp.com/static/img/icon.png";
private transient Function<Announcement, LinkMessage> linkMessageConverter;

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package amu.zhcet.announcement;

import amu.zhcet.data.ItemNotFoundException;

import javax.annotation.Nullable;

public class AnnouncementNotFoundException extends ItemNotFoundException {
public AnnouncementNotFoundException() {
super("Announcement");
}

public AnnouncementNotFoundException(@Nullable String id) {
super("Announcement", id);
}
}
11 changes: 11 additions & 0 deletions src/main/java/amu/zhcet/announcement/AnnouncementRepository.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package amu.zhcet.announcement;

import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.repository.PagingAndSortingRepository;

public interface AnnouncementRepository extends PagingAndSortingRepository<Announcement, Long> {

Page<Announcement> findBySenderUserId(String userId, Pageable Page);

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
package amu.zhcet.announcement.management;

import amu.zhcet.announcement.Announcement;
import amu.zhcet.common.utils.NotificationUtils;
import amu.zhcet.core.error.ErrorUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.servlet.mvc.support.RedirectAttributes;

import javax.validation.Valid;

@Slf4j
@Controller
@RequestMapping("/management/announcements/{announcement}/edit")
public class AnnouncementEditController {

private final AnnouncementManagementService announcementManagementService;

@Autowired
public AnnouncementEditController (AnnouncementManagementService announcementManagementService) {
this.announcementManagementService = announcementManagementService;
}

@GetMapping
public String editAnnouncement(@PathVariable Announcement announcement, Model model) {
ErrorUtils.requireNonNullAnnouncement(announcement);

model.addAttribute("page_title", "Edit Announcement");
model.addAttribute("page_subtitle", "Announcement Manager");
model.addAttribute("page_description", "Edit sent Announcement");

if (!model.containsAttribute("announcement"))
model.addAttribute("announcement", announcement);
return "management/edit_announcement";
}

@PostMapping
public String saveEditAnnouncement(@RequestParam(required = false) Integer page, @PathVariable Announcement announcement,
@Valid Announcement edited, BindingResult result,
RedirectAttributes redirectAttributes)
{
ErrorUtils.requireNonNullAnnouncement(announcement);
int currentPage = NotificationUtils.normalizePage(page);

String redirectUrl = String.format("redirect:/management/announcements/%d/edit?page=%d", announcement.getId(), currentPage);

if (result.hasErrors()) {
redirectAttributes.addFlashAttribute("announcement", edited);
redirectAttributes.addFlashAttribute("org.springframework.validation.BindingResult.announcement", result);
return redirectUrl;
}

announcement.setTitle(edited.getTitle());
announcement.setMessage(edited.getMessage());
announcementManagementService.saveAnnouncement(announcement);
redirectAttributes.addFlashAttribute("announcement_success", "Announcement Edited");
return "redirect:/management/announcements?page=" + currentPage;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
package amu.zhcet.announcement.management;

import amu.zhcet.announcement.Announcement;
import amu.zhcet.common.utils.NotificationUtils;
import amu.zhcet.core.error.ErrorUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
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.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.servlet.mvc.support.RedirectAttributes;

import java.util.List;

@Slf4j
@Controller
@RequestMapping("/management/announcements")
public class AnnouncementManagementController {

private final AnnouncementManagementService announcementManagementService;

@Autowired
public AnnouncementManagementController(AnnouncementManagementService announcementManagementService) {
this.announcementManagementService = announcementManagementService;
}

@GetMapping
public String manageAnnouncements(@RequestParam(required = false) Integer page, Model model) {
model.addAttribute("page_title", "Manage Announcements");
model.addAttribute("page_subtitle", "Announcement Manager");
model.addAttribute("page_description", "Manage and monitor sent announcements");

int currentPage = NotificationUtils.normalizePage(page);
Page<Announcement> announcementPage = announcementManagementService.getAnnouncements(currentPage);

NotificationUtils.prepareNotifications(model, announcementPage, currentPage);
List<Announcement> announcements = announcementPage.getContent();
model.addAttribute("announcements", announcements);

return "management/manage_announcements";
}

@GetMapping("/{announcement}/delete")
public String deleteAnnouncement(@RequestParam(required = false) Integer page, @PathVariable Announcement announcement, RedirectAttributes redirectAttributes) {
ErrorUtils.requireNonNullAnnouncement(announcement);
int currentPage = NotificationUtils.normalizePage(page);

announcementManagementService.deleteAnnouncement(announcement);
redirectAttributes.addFlashAttribute("announcement_success", "Announcement Deleted");
return "redirect:/management/announcements?page=" + currentPage;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
package amu.zhcet.announcement.management;

import amu.zhcet.announcement.Announcement;
import amu.zhcet.announcement.AnnouncementRepository;
import amu.zhcet.auth.Auditor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Sort;
import org.springframework.stereotype.Service;

@Slf4j
@Service
public class AnnouncementManagementService {

private static final int PAGE_SIZE = 10;

private final AnnouncementRepository announcementRepository;

@Autowired
public AnnouncementManagementService(AnnouncementRepository announcementRepository) {
this.announcementRepository = announcementRepository;
}

public Page<Announcement> getAnnouncements(int page) {
PageRequest pageRequest = PageRequest.of(page - 1, PAGE_SIZE, Sort.Direction.DESC, "sentTime");
return announcementRepository.findBySenderUserId(Auditor.getLoggedInUsername(), pageRequest);
}

public void deleteAnnouncement(Announcement announcement) { announcementRepository.delete(announcement);}

public void saveAnnouncement(Announcement announcement) { announcementRepository.save(announcement);}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
package amu.zhcet.announcement.reading;

import amu.zhcet.announcement.Announcement;
import amu.zhcet.common.utils.NotificationUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;

@Slf4j
@Controller
@RequestMapping("/announcements")
public class AnnouncementController {

private final AnnouncementReadingService announcementReadingService;

@Autowired
public AnnouncementController(AnnouncementReadingService announcementReadingService) {
this.announcementReadingService = announcementReadingService;
}

private static void prepareModel(Model model) {
model.addAttribute("page_title", "Announcements");
model.addAttribute("page_subtitle", "Announcement Manager");
model.addAttribute("page_description", "View and manage announcements");
}

@GetMapping
public String getAnnouncements(@RequestParam(required = false) Integer page, Model model) {
int currentPage = NotificationUtils.normalizePage(page);
Page<Announcement> announcementPage = announcementReadingService.getAnnouncements(currentPage);

prepareModel(model);
NotificationUtils.prepareNotifications(model, announcementPage, currentPage);
model.addAttribute("announcements", announcementPage.getContent());
model.addAttribute("favorite_page", false);

return "user/announcements";
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
package amu.zhcet.announcement.reading;

import amu.zhcet.announcement.Announcement;
import amu.zhcet.announcement.AnnouncementRepository;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Scope;
import org.springframework.context.annotation.ScopedProxyMode;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Sort;
import org.springframework.stereotype.Service;

import javax.transaction.Transactional;

@Slf4j
@Service
@Transactional
@Scope(proxyMode = ScopedProxyMode.TARGET_CLASS)
public class AnnouncementReadingService {

public static final int PAGE_SIZE = 10;

private final AnnouncementRepository announcementRepository;

@Autowired
public AnnouncementReadingService(AnnouncementRepository announcementRepository) {
this.announcementRepository = announcementRepository;
}

public Page<Announcement> getAnnouncements(int page) {
PageRequest pageRequest = PageRequest.of(page - 1, PAGE_SIZE, Sort.Direction.DESC, "sentTime");
return announcementRepository.findAll(pageRequest);
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
package amu.zhcet.announcement.sending;

import amu.zhcet.announcement.Announcement;
import amu.zhcet.data.user.User;
import amu.zhcet.data.user.UserService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.security.access.AccessDeniedException;
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.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.mvc.support.RedirectAttributes;

import javax.validation.Valid;

@Slf4j
@Controller
@RequestMapping("/management/announcement/send")
public class AnnouncementSendingController {

private final UserService userService;
private final AnnouncementSendingService announcementSendingService;

public AnnouncementSendingController(UserService userService, AnnouncementSendingService announcementSendingService) {
this.userService = userService;
this.announcementSendingService = announcementSendingService;
}

@GetMapping
public String sendAnnouncement(Model model) {
User user = userService.getLoggedInUser().orElseThrow(() -> new AccessDeniedException("403"));

model.addAttribute("page_title", "Send Announcements");
model.addAttribute("page_subtitle", "Announcement Manager");
model.addAttribute("page_description", "Send announcements to everyone");

if (!model.containsAttribute("announcement")) {
Announcement announcement = new Announcement();
announcement.setSender(user);
model.addAttribute("announcement", announcement);
}

return "management/send_announcement";
}

@PostMapping
public String handleSentAnnouncement(@Valid Announcement announcement, BindingResult bindingResult, RedirectAttributes redirectAttribute) {
User user = userService.getLoggedInUser().orElseThrow(() -> new AccessDeniedException("403"));

if (bindingResult.hasErrors()) {
redirectAttribute.addFlashAttribute("announcement", announcement);
redirectAttribute.addFlashAttribute("org.springframework.validation.BindingResult.announcement", bindingResult);
} else {
announcement.setSender(user);
announcementSendingService.sendAnnouncement(announcement);
redirectAttribute.addFlashAttribute("announcement_success", "Announcement sending in background");
}

return "redirect:/management/announcement/send";
}

}
Loading

0 comments on commit 97ebf3a

Please sign in to comment.