Skip to content

Commit

Permalink
feat: Add announcements feature
Browse files Browse the repository at this point in the history
  • Loading branch information
prateekj117 committed Aug 22, 2018
1 parent 6f3df0b commit 9e763fd
Show file tree
Hide file tree
Showing 15 changed files with 635 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);
}
}
13 changes: 13 additions & 0 deletions src/main/java/amu/zhcet/announcement/AnnouncementRepository.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
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);

Page<Announcement> findAll(String userId, Pageable pageable);

}
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,43 @@
package amu.zhcet.announcement.management;

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;

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";
}
}
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,38 @@
package amu.zhcet.announcement.reading;

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.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) {
String userId = Auditor.getLoggedInUsername();
PageRequest pageRequest = PageRequest.of(page - 1, PAGE_SIZE, Sort.Direction.DESC, "announcement.sentTime");
return announcementRepository.findAll(userId, pageRequest);
}

}
6 changes: 6 additions & 0 deletions src/main/java/amu/zhcet/core/error/ErrorUtils.java
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
package amu.zhcet.core.error;

import amu.zhcet.announcement.Announcement;
import amu.zhcet.auth.UserAuth;
import amu.zhcet.notification.Notification;
import amu.zhcet.notification.NotificationNotFoundException;
import amu.zhcet.announcement.AnnouncementNotFoundException;
import amu.zhcet.notification.recipient.NotificationRecipient;
import amu.zhcet.data.course.Course;
import amu.zhcet.data.course.CourseNotFoundException;
Expand Down Expand Up @@ -48,4 +50,8 @@ public static void requireNonNullUser(UserAuth user) {
public static void requireNonNullFacultyMember(FacultyMember facultyMember) {
if (facultyMember == null) throw new FacultyMemberNotFoundException();
}

public static void requireNonNullAnnouncement(Announcement announcement) {
if (announcement == null) throw new AnnouncementNotFoundException();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
CREATE TABLE announcement
(
id BIGINT(20) PRIMARY KEY AUTO_INCREMENT,
sender_user_id VARCHAR(255) NOT NULL,
title VARCHAR(150),
message VARCHAR(500) NOT NULL,
scheduled BIT(1) DEFAULT 0,
sent_time DATETIME DEFAULT NOW(),
automated BIT(1) DEFAULT FALSE,
created_at DATETIME,
updated_at DATETIME,
created_by VARCHAR(255),
modified_by VARCHAR(255),
version int(11) DEFAULT 0,
CONSTRAINT announcement__sender_fk FOREIGN KEY (sender_user_id) REFERENCES user(user_id) ON DELETE CASCADE ON UPDATE CASCADE
);

CREATE TABLE announcement_aud
(
id BIGINT(20) NOT NULL,
rev integer not null,
revtype tinyint,
sender_user_id VARCHAR(255),
title VARCHAR(150),
message VARCHAR(500),
scheduled BIT(1),
sent_time DATETIME,
automated BIT(1) DEFAULT FALSE,
PRIMARY KEY (id, rev)
);
Loading

0 comments on commit 9e763fd

Please sign in to comment.