package org.iatoki.judgels.uriel.controllers;
import org.iatoki.judgels.play.IdentityUtils;
import org.iatoki.judgels.play.InternalLink;
import org.iatoki.judgels.play.LazyHtml;
import org.iatoki.judgels.play.Page;
import org.iatoki.judgels.play.controllers.AbstractJudgelsController;
import org.iatoki.judgels.play.views.html.layouts.heading3Layout;
import org.iatoki.judgels.play.views.html.layouts.heading3WithActionLayout;
import org.iatoki.judgels.play.views.html.layouts.headingLayout;
import org.iatoki.judgels.uriel.Contest;
import org.iatoki.judgels.uriel.ContestAnnouncement;
import org.iatoki.judgels.uriel.ContestAnnouncementNotFoundException;
import org.iatoki.judgels.uriel.ContestAnnouncementStatus;
import org.iatoki.judgels.uriel.ContestPermissions;
import org.iatoki.judgels.uriel.forms.ContestAnnouncementUpsertForm;
import org.iatoki.judgels.uriel.ContestNotFoundException;
import org.iatoki.judgels.uriel.services.ContestAnnouncementService;
import org.iatoki.judgels.uriel.services.ContestService;
import org.iatoki.judgels.uriel.controllers.securities.Authenticated;
import org.iatoki.judgels.uriel.controllers.securities.HasRole;
import org.iatoki.judgels.uriel.controllers.securities.LoggedIn;
import org.iatoki.judgels.uriel.services.ContestSupervisorService;
import org.iatoki.judgels.uriel.views.html.contest.announcement.createAnnouncementView;
import org.iatoki.judgels.uriel.views.html.contest.announcement.listAnnouncementsView;
import org.iatoki.judgels.uriel.views.html.contest.announcement.updateAnnouncementView;
import org.iatoki.judgels.uriel.views.html.contest.announcement.listPublishedAnnouncementsView;
import org.iatoki.judgels.uriel.views.html.layouts.accessTypeByStatusLayout;
import play.data.Form;
import play.db.jpa.Transactional;
import play.filters.csrf.AddCSRFToken;
import play.filters.csrf.RequireCSRFCheck;
import play.i18n.Messages;
import play.mvc.Http;
import play.mvc.Result;
import javax.inject.Inject;
import javax.inject.Named;
import javax.inject.Singleton;
import java.util.Arrays;
import java.util.stream.Collectors;
@Authenticated(value = {LoggedIn.class, HasRole.class})
@Singleton
@Named
public class ContestAnnouncementController extends AbstractJudgelsController {
private static final long PAGE_SIZE = 20;
private final ContestService contestService;
private final ContestAnnouncementService contestAnnouncementService;
private final ContestSupervisorService contestSupervisorService;
@Inject
public ContestAnnouncementController(ContestService contestService, ContestAnnouncementService contestAnnouncementService, ContestSupervisorService contestSupervisorService) {
this.contestService = contestService;
this.contestAnnouncementService = contestAnnouncementService;
this.contestSupervisorService = contestSupervisorService;
}
@Transactional
public Result viewPublishedAnnouncements(long contestId) throws ContestNotFoundException {
return listPublishedAnnouncements(contestId, 0, "timeUpdate", "desc", "");
}
@Transactional
public Result listPublishedAnnouncements(long contestId, long pageIndex, String orderBy, String orderDir, String filterString) throws ContestNotFoundException {
Contest contest = contestService.findContestById(contestId);
if (ContestControllerUtils.getInstance().isAllowedToEnterContest(contest)) {
Page<ContestAnnouncement> contestAnnouncements = contestAnnouncementService.pageContestAnnouncementsByContestJid(contest.getJid(), pageIndex, PAGE_SIZE, orderBy, orderDir, filterString, ContestAnnouncementStatus.PUBLISHED.name());
contestAnnouncementService.readContestAnnouncements(IdentityUtils.getUserJid(), contestAnnouncements.getData().stream().map(c -> c.getJid()).collect(Collectors.toList()));
LazyHtml content = new LazyHtml(listPublishedAnnouncementsView.render(contest.getId(), contestAnnouncements, pageIndex, orderBy, orderDir, filterString));
content.appendLayout(c -> heading3Layout.render(Messages.get("announcement.list"), c));
if (isAllowedToSuperviseAnnouncements(contest)) {
appendSubtabsLayout(content, contest);
}
ContestControllerUtils.getInstance().appendTabsLayout(content, contest);
ControllerUtils.getInstance().appendSidebarLayout(content);
appendBreadcrumbsLayout(content, contest,
new InternalLink(Messages.get("announcement.list"), routes.ContestAnnouncementController.viewPublishedAnnouncements(contest.getId()))
);
ControllerUtils.getInstance().appendTemplateLayout(content, "Contest - Announcements");
ControllerUtils.getInstance().addActivityLog("Open list of published announcements in contest " + contest.getName() + " <a href=\"" + "http://" + Http.Context.current().request().host() + Http.Context.current().request().uri() + "\">link</a>.");
return ControllerUtils.getInstance().lazyOk(content);
} else {
return redirect(routes.ContestController.viewContest(contest.getId()));
}
}
@Transactional(readOnly = true)
public Result viewAnnouncements(long contestId) throws ContestNotFoundException {
return listAnnouncements(contestId, 0, "id", "desc", "");
}
@Transactional(readOnly = true)
public Result listAnnouncements(long contestId, long pageIndex, String orderBy, String orderDir, String filterString) throws ContestNotFoundException {
Contest contest = contestService.findContestById(contestId);
if (isAllowedToSuperviseAnnouncements(contest)) {
Page<ContestAnnouncement> contestAnnouncements = contestAnnouncementService.pageContestAnnouncementsByContestJid(contest.getJid(), pageIndex, PAGE_SIZE, orderBy, orderDir, filterString, null);
LazyHtml content = new LazyHtml(listAnnouncementsView.render(contest.getId(), contestAnnouncements, pageIndex, orderBy, orderDir, filterString));
content.appendLayout(c -> heading3WithActionLayout.render(Messages.get("announcement.list"), new InternalLink(Messages.get("commons.create"), routes.ContestAnnouncementController.createAnnouncement(contest.getId())), c));
appendSubtabsLayout(content, contest);
ContestControllerUtils.getInstance().appendTabsLayout(content, contest);
ControllerUtils.getInstance().appendSidebarLayout(content);
appendBreadcrumbsLayout(content, contest,
new InternalLink(Messages.get("announcement.list"), routes.ContestAnnouncementController.viewAnnouncements(contest.getId()))
);
ControllerUtils.getInstance().appendTemplateLayout(content, "Contest - All Announcements");
ControllerUtils.getInstance().addActivityLog("Open all announcements in contest " + contest.getName() + " <a href=\"" + "http://" + Http.Context.current().request().host() + Http.Context.current().request().uri() + "\">link</a>.");
return ControllerUtils.getInstance().lazyOk(content);
} else {
return ContestControllerUtils.getInstance().tryEnteringContest(contest);
}
}
@Transactional(readOnly = true)
@AddCSRFToken
public Result createAnnouncement(long contestId) throws ContestNotFoundException {
Contest contest = contestService.findContestById(contestId);
if (isAllowedToSuperviseAnnouncements(contest)) {
Form<ContestAnnouncementUpsertForm> form = Form.form(ContestAnnouncementUpsertForm.class);
ControllerUtils.getInstance().addActivityLog("Try to create announcement in contest " + contest.getName() + " <a href=\"" + "http://" + Http.Context.current().request().host() + Http.Context.current().request().uri() + "\">link</a>.");
return showCreateAnnouncement(form, contest);
} else {
return ContestControllerUtils.getInstance().tryEnteringContest(contest);
}
}
@Transactional
@RequireCSRFCheck
public Result postCreateAnnouncement(long contestId) throws ContestNotFoundException {
Contest contest = contestService.findContestById(contestId);
if (isAllowedToSuperviseAnnouncements(contest)) {
Form<ContestAnnouncementUpsertForm> form = Form.form(ContestAnnouncementUpsertForm.class).bindFromRequest();
if (form.hasErrors() || form.hasGlobalErrors()) {
return showCreateAnnouncement(form, contest);
} else {
ContestAnnouncementUpsertForm contestAnnouncementUpsertForm = form.get();
contestAnnouncementService.createContestAnnouncement(contest.getId(), contestAnnouncementUpsertForm.title, contestAnnouncementUpsertForm.content, ContestAnnouncementStatus.valueOf(contestAnnouncementUpsertForm.status));
ControllerUtils.getInstance().addActivityLog("Create " + contestAnnouncementUpsertForm.status + " announcement with title " + contestAnnouncementUpsertForm.title + " in contest " + contest.getName() + ".");
return redirect(routes.ContestAnnouncementController.viewAnnouncements(contest.getId()));
}
} else {
return ContestControllerUtils.getInstance().tryEnteringContest(contest);
}
}
@Transactional(readOnly = true)
@AddCSRFToken
public Result updateAnnouncement(long contestId, long contestAnnouncementId) throws ContestNotFoundException, ContestAnnouncementNotFoundException {
Contest contest = contestService.findContestById(contestId);
ContestAnnouncement contestAnnouncement = contestAnnouncementService.findContestAnnouncementByContestAnnouncementId(contestAnnouncementId);
if (isAllowedToSuperviseAnnouncements(contest) && contestAnnouncement.getContestJid().equals(contest.getJid())) {
ContestAnnouncementUpsertForm contestAnnouncementUpsertForm = new ContestAnnouncementUpsertForm(contestAnnouncement);
Form<ContestAnnouncementUpsertForm> form = Form.form(ContestAnnouncementUpsertForm.class).fill(contestAnnouncementUpsertForm);
ControllerUtils.getInstance().addActivityLog("Try to update announcement " + contestAnnouncement.getTitle() + " in contest " + contest.getName() + " <a href=\"" + "http://" + Http.Context.current().request().host() + Http.Context.current().request().uri() + "\">link</a>.");
return showUpdateAnnouncement(form, contest, contestAnnouncement);
} else {
return ContestControllerUtils.getInstance().tryEnteringContest(contest);
}
}
@Transactional
@RequireCSRFCheck
public Result postUpdateAnnouncement(long contestId, long contestAnnouncementId) throws ContestNotFoundException, ContestAnnouncementNotFoundException {
Contest contest = contestService.findContestById(contestId);
ContestAnnouncement contestAnnouncement = contestAnnouncementService.findContestAnnouncementByContestAnnouncementId(contestAnnouncementId);
if (isAllowedToSuperviseAnnouncements(contest) && contestAnnouncement.getContestJid().equals(contest.getJid())) {
Form<ContestAnnouncementUpsertForm> form = Form.form(ContestAnnouncementUpsertForm.class).bindFromRequest();
if (form.hasErrors() || form.hasGlobalErrors()) {
return showUpdateAnnouncement(form, contest, contestAnnouncement);
} else {
ContestAnnouncementUpsertForm contestAnnouncementUpsertForm = form.get();
contestAnnouncementService.updateContestAnnouncement(contestAnnouncement.getId(), contestAnnouncementUpsertForm.title, contestAnnouncementUpsertForm.content, ContestAnnouncementStatus.valueOf(contestAnnouncementUpsertForm.status));
ControllerUtils.getInstance().addActivityLog("Update announcement " + contestAnnouncement.getTitle() + " in contest " + contest.getName() + ".");
return redirect(routes.ContestAnnouncementController.viewAnnouncements(contest.getId()));
}
} else {
return ContestControllerUtils.getInstance().tryEnteringContest(contest);
}
}
private Result showCreateAnnouncement(Form<ContestAnnouncementUpsertForm> form, Contest contest){
LazyHtml content = new LazyHtml(createAnnouncementView.render(contest.getId(), form));
content.appendLayout(c -> heading3Layout.render(Messages.get("announcement.create"), c));
appendSubtabsLayout(content, contest);ContestControllerUtils.getInstance().appendTabsLayout(content, contest);
ControllerUtils.getInstance().appendSidebarLayout(content);
appendBreadcrumbsLayout(content, contest,
new InternalLink(Messages.get("status.supervisor"), routes.ContestAnnouncementController.viewAnnouncements(contest.getId())),
new InternalLink(Messages.get("announcement.create"), routes.ContestAnnouncementController.createAnnouncement(contest.getId()))
);
ControllerUtils.getInstance().appendTemplateLayout(content, "Contest - Announcement - Create");
return ControllerUtils.getInstance().lazyOk(content);
}
private Result showUpdateAnnouncement(Form<ContestAnnouncementUpsertForm> form, Contest contest, ContestAnnouncement contestAnnouncement){
LazyHtml content = new LazyHtml(updateAnnouncementView.render(contest.getId(), contestAnnouncement.getId(), form));
content.appendLayout(c -> headingLayout.render(Messages.get("announcement.update"), c));
appendSubtabsLayout(content, contest);
ContestControllerUtils.getInstance().appendTabsLayout(content, contest);
ControllerUtils.getInstance().appendSidebarLayout(content);
appendBreadcrumbsLayout(content, contest,
new InternalLink(Messages.get("status.supervisor"), routes.ContestAnnouncementController.viewPublishedAnnouncements(contest.getId())),
new InternalLink(Messages.get("announcement.update"), routes.ContestAnnouncementController.updateAnnouncement(contest.getId(), contestAnnouncement.getId()))
);
ControllerUtils.getInstance().appendTemplateLayout(content, "Contest - Announcement - Update");
return ControllerUtils.getInstance().lazyOk(content);
}
private void appendSubtabsLayout(LazyHtml content, Contest contest) {
content.appendLayout(c -> accessTypeByStatusLayout.render(routes.ContestAnnouncementController.viewPublishedAnnouncements(contest.getId()), routes.ContestAnnouncementController.viewAnnouncements(contest.getId()), c));
}
private void appendBreadcrumbsLayout(LazyHtml content, Contest contest, InternalLink... lastLinks) {
ControllerUtils.getInstance().appendBreadcrumbsLayout(content,
ContestControllerUtils.getInstance().getContestBreadcrumbsBuilder(contest)
.add(new InternalLink(Messages.get("announcement.announcements"), routes.ContestController.jumpToAnnouncements(contest.getId())))
.addAll(Arrays.asList(lastLinks))
.build()
);
}
private boolean isAllowedToSuperviseAnnouncements(Contest contest) {
return ControllerUtils.getInstance().isAdmin() || ContestControllerUtils.getInstance().isManager(contest) || (ContestControllerUtils.getInstance().isSupervisor(contest) && contestSupervisorService.findContestSupervisorByContestJidAndUserJid(contest.getJid(), IdentityUtils.getUserJid()).getContestPermission().isAllowed(ContestPermissions.ANNOUNCEMENT));
}
}