/**
* Copyright © ${project.inceptionYear} Instituto Superior Técnico
*
* This file is part of Fenix IST.
*
* Fenix IST is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Fenix IST is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Fenix IST. If not, see <http://www.gnu.org/licenses/>.
*/
package pt.ist.fenix.ui.spring;
import static java.lang.String.format;
import static org.fenixedu.bennu.core.i18n.BundleUtil.getLocalizedString;
import static org.fenixedu.bennu.core.security.Authenticate.getUser;
import static org.fenixedu.cms.domain.Post.CREATION_DATE_COMPARATOR;
import static pt.ist.fenixframework.FenixFramework.atomic;
import java.io.IOException;
import java.math.RoundingMode;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
import javax.servlet.http.HttpServletRequest;
import org.fenixedu.academic.domain.ExecutionCourse;
import org.fenixedu.academic.domain.Professorship;
import org.fenixedu.academic.predicate.AccessControl;
import org.fenixedu.academic.ui.struts.action.teacher.ManageExecutionCourseDA;
import org.fenixedu.bennu.core.groups.AnyoneGroup;
import org.fenixedu.bennu.io.domain.GroupBasedFile;
import org.fenixedu.bennu.io.servlets.FileDownloadServlet;
import org.fenixedu.cms.domain.Category;
import org.fenixedu.cms.domain.Post;
import org.fenixedu.cms.domain.Site;
import org.fenixedu.cms.ui.AdminSites;
import org.fenixedu.commons.i18n.LocalizedString;
import org.joda.time.DateTime;
import org.springframework.format.annotation.DateTimeFormat;
import org.springframework.format.annotation.DateTimeFormat.ISO;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.servlet.view.JstlView;
import org.springframework.web.servlet.view.RedirectView;
import pt.ist.fenixframework.Atomic;
import com.google.common.math.IntMath;
import com.google.gson.JsonArray;
import com.google.gson.JsonObject;
@Controller
@RequestMapping("/teacher/{executionCourse}/announcements")
public class AnnouncementsAdminController extends ExecutionCourseController {
private static final LocalizedString ANNOUNCEMENT = getLocalizedString("resources.FenixEduLearningResources",
"label.announcements");
private static final int PER_PAGE = 5;
@RequestMapping(method = RequestMethod.GET)
public AnnouncementsAdminView all(Model model, @PathVariable ExecutionCourse executionCourse, @RequestParam(required = false,
defaultValue = "1") int page) {
Professorship professorship = executionCourse.getProfessorship(AccessControl.getPerson());
AccessControl.check(person -> professorship != null && professorship.getPermissions().getAnnouncements());
List<Post> announcements = getAnnouncements(executionCourse.getSite());
model.addAttribute("executionCourse", executionCourse);
int pages = IntMath.divide(announcements.size(), PER_PAGE, RoundingMode.CEILING);
if (page < 1) {
page = 1;
}
if (pages > 0 && page > pages) {
page = pages;
}
model.addAttribute("currentPage", page);
model.addAttribute("pages", pages);
model.addAttribute("announcements",
announcements.stream().skip((page - 1) * PER_PAGE).limit(PER_PAGE).collect(Collectors.toList()));
model.addAttribute("professorship", professorship);
return new AnnouncementsAdminView();
}
@RequestMapping(value = "{postSlug}/delete", method = RequestMethod.POST)
public RedirectView delete(@PathVariable ExecutionCourse executionCourse, @PathVariable String postSlug) {
Post post = executionCourse.getSite().postForSlug(postSlug);
atomic(() -> post.delete());
return viewAll(executionCourse);
}
@RequestMapping(value = "{postSlug}/addFile.json", method = RequestMethod.POST, produces = "application/json")
public @ResponseBody String addFileJson(Model model, @PathVariable ExecutionCourse executionCourse, @PathVariable(
value = "postSlug") String slugPost, @RequestParam("attachment") MultipartFile[] attachments) throws IOException {
Site s = executionCourse.getSite();
AdminSites.canEdit(s);
Post p = s.postForSlug(slugPost);
JsonArray array = new JsonArray();
Arrays.asList(attachments).stream().map((attachment) -> {
GroupBasedFile f = null;
try {
f = addFile(attachment, p);
} catch (IOException e) {
e.printStackTrace();
}
JsonObject obj = new JsonObject();
obj.addProperty("displayname", f.getDisplayName());
obj.addProperty("filename", f.getFilename());
obj.addProperty("url", FileDownloadServlet.getDownloadUrl(f));
return obj;
}).forEach(x -> array.add(x));
return array.toString();
}
@Atomic
private GroupBasedFile addFile(MultipartFile attachment, Post p) throws IOException {
GroupBasedFile f =
new GroupBasedFile(attachment.getOriginalFilename(), attachment.getOriginalFilename(), attachment.getBytes(),
AnyoneGroup.get());
p.getPostFiles().putFile(f);
return f;
}
@RequestMapping(value = "create", method = RequestMethod.POST)
public RedirectView create(@PathVariable ExecutionCourse executionCourse, @RequestParam LocalizedString name,
@RequestParam LocalizedString body, @RequestParam(required = false, defaultValue = "false") boolean active,
@RequestParam(required = false) @DateTimeFormat(iso = ISO.DATE_TIME) DateTime publicationStarts) throws Exception {
Site site = executionCourse.getSite();
atomic(() -> {
Post post =
Post.create(site, null, Post.sanitize(name), Post.sanitize(body), announcementsCategory(site), active,
getUser());
if (publicationStarts == null) {
post.setPublicationBegin(null);
post.setPublicationEnd(null);
} else {
post.setPublicationBegin(publicationStarts);
post.setPublicationEnd(DateTime.now().plusYears(20));
}
});
return viewAll(executionCourse);
}
@RequestMapping(value = "{postSlug}/edit", method = RequestMethod.POST)
public RedirectView edit(@PathVariable ExecutionCourse executionCourse, @PathVariable String postSlug,
@RequestParam LocalizedString name, @RequestParam LocalizedString body, @RequestParam(required = false,
defaultValue = "false") boolean active,
@RequestParam(required = false) @DateTimeFormat(iso = ISO.DATE_TIME) DateTime publicationStarts) {
Post post = executionCourse.getSite().postForSlug(postSlug);
atomic(() -> {
post.setName(Post.sanitize(name));
post.setBody(Post.sanitize(body));
post.setActive(active);
if (publicationStarts == null) {
post.setPublicationBegin(null);
post.setPublicationEnd(null);
} else {
post.setPublicationBegin(publicationStarts);
post.setPublicationEnd(DateTime.now().plusYears(20));
}
});
return viewAll(executionCourse);
}
private RedirectView viewAll(ExecutionCourse executionCourse) {
return new RedirectView(format("/teacher/%s/announcements", executionCourse.getExternalId()), true);
}
private List<Post> getAnnouncements(Site site) {
return announcementsCategory(site).getPostsSet().stream().sorted(CREATION_DATE_COMPARATOR).collect(Collectors.toList());
}
private Category announcementsCategory(Site site) {
return site.getOrCreateCategoryForSlug("announcement", ANNOUNCEMENT);
}
@Override
protected Class<?> getFunctionalityType() {
return ManageExecutionCourseDA.class;
}
@Override
Boolean getPermission(Professorship prof) {
return prof.getPermissions().getAnnouncements();
}
public class AnnouncementsAdminView extends JstlView {
@Override
protected void exposeHelpers(HttpServletRequest request) throws Exception {
setServletContext(request.getServletContext());
super.exposeHelpers(request);
request.setAttribute("teacher$actual$page", "/WEB-INF/fenix-learning/announcements.jsp");
}
@Override
public String getUrl() {
return "/teacher/executionCourse/executionCourseFrame.jsp";
}
}
}