/**
* <a href="http://www.openolat.org">
* OpenOLAT - Online Learning and Training</a><br>
* <p>
* Licensed under the Apache License, Version 2.0 (the "License"); <br>
* you may not use this file except in compliance with the License.<br>
* You may obtain a copy of the License at the
* <a href="http://www.apache.org/licenses/LICENSE-2.0">Apache homepage</a>
* <p>
* Unless required by applicable law or agreed to in writing,<br>
* software distributed under the License is distributed on an "AS IS" BASIS, <br>
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. <br>
* See the License for the specific language governing permissions and <br>
* limitations under the License.
* <p>
* Initial code contributed and copyrighted by<br>
* frentix GmbH, http://www.frentix.com
* <p>
*/
package org.olat.course.nodes.gta.ui;
import java.io.File;
import java.util.ArrayList;
import java.util.List;
import org.olat.basesecurity.GroupRoles;
import org.olat.core.gui.UserRequest;
import org.olat.core.gui.components.Component;
import org.olat.core.gui.components.link.Link;
import org.olat.core.gui.components.link.LinkFactory;
import org.olat.core.gui.components.velocity.VelocityContainer;
import org.olat.core.gui.control.Controller;
import org.olat.core.gui.control.Event;
import org.olat.core.gui.control.WindowControl;
import org.olat.core.gui.control.controller.BasicController;
import org.olat.core.gui.control.generic.modal.DialogBoxController;
import org.olat.core.gui.control.generic.modal.DialogBoxUIFactory;
import org.olat.core.id.Identity;
import org.olat.core.id.OLATResourceable;
import org.olat.core.util.StringHelper;
import org.olat.core.util.coordinate.CoordinatorManager;
import org.olat.core.util.io.SystemFilenameFilter;
import org.olat.core.util.vfs.VFSContainer;
import org.olat.course.CourseFactory;
import org.olat.course.ICourse;
import org.olat.course.assessment.AssessmentHelper;
import org.olat.course.nodes.GTACourseNode;
import org.olat.course.nodes.gta.GTAManager;
import org.olat.course.nodes.gta.GTAType;
import org.olat.course.nodes.gta.Task;
import org.olat.course.nodes.gta.TaskHelper;
import org.olat.course.nodes.gta.TaskHelper.FilesLocked;
import org.olat.course.nodes.gta.TaskProcess;
import org.olat.course.nodes.gta.ui.events.SubmitEvent;
import org.olat.course.nodes.gta.ui.events.TaskMultiUserEvent;
import org.olat.course.run.environment.CourseEnvironment;
import org.olat.course.run.userview.UserCourseEnvironment;
import org.olat.group.BusinessGroup;
import org.olat.group.BusinessGroupService;
import org.springframework.beans.factory.annotation.Autowired;
/**
*
* Initial date: 02.03.2015<br>
* @author srosse, stephane.rosse@frentix.com, http://www.frentix.com
*
*/
public class GTAParticipantRevisionAndCorrectionsController extends BasicController {
private Link submitRevisionButton;
private final VelocityContainer mainVC;
private DialogBoxController confirmSubmitDialog;
private SubmitDocumentsController uploadRevisionsCtrl;
private DirectoryController correctionsCtrl, revisionsCtrl;
private Task assignedTask;
private final boolean businessGroupTask;
private final GTACourseNode gtaNode;
private final BusinessGroup assessedGroup;
private final CourseEnvironment courseEnv;
private final UserCourseEnvironment assessedUserCourseEnv;
private final OLATResourceable taskListEventResource;
@Autowired
private GTAManager gtaManager;
@Autowired
private BusinessGroupService businessGroupService;
public GTAParticipantRevisionAndCorrectionsController(UserRequest ureq, WindowControl wControl,
UserCourseEnvironment assessedUserCourseEnv,Task assignedTask,
GTACourseNode gtaNode, BusinessGroup assessedGroup, OLATResourceable taskListEventResource) {
super(ureq, wControl);
this.gtaNode = gtaNode;
courseEnv = assessedUserCourseEnv.getCourseEnvironment();
this.assessedUserCourseEnv = assessedUserCourseEnv;
this.assignedTask = assignedTask;
this.assessedGroup = assessedGroup;
this.taskListEventResource = taskListEventResource;
businessGroupTask = GTAType.group.name().equals(gtaNode.getModuleConfiguration().getStringValue(GTACourseNode.GTASK_TYPE));
mainVC = createVelocityContainer("participant_revisions");
putInitialPanel(mainVC);
initRevisionProcess(ureq);
}
public Task getAssignedTask() {
return assignedTask;
}
@Override
protected void doDispose() {
//
}
public void close() {
if(uploadRevisionsCtrl != null) {
uploadRevisionsCtrl.close();
}
}
private void initRevisionProcess(UserRequest ureq) {
List<String> revisionStepNames = new ArrayList<>();
mainVC.contextPut("previousRevisions", revisionStepNames);
if(assignedTask.getRevisionLoop() > 1) {
for(int i=1 ; i<assignedTask.getRevisionLoop(); i++ ) {
//revisions
setRevisionIteration(ureq, i, revisionStepNames);
}
}
TaskProcess status = assignedTask.getTaskStatus();
if(status == TaskProcess.revision) {
//assessed user can return some revised documents
setUploadRevision(ureq, assignedTask);
} else if(status == TaskProcess.correction) {
//coach can return some corrections
setRevision(ureq, "revisions", assignedTask.getRevisionLoop());
setCorrections(ureq, "corrections", assignedTask.getRevisionLoop());
} else {
int lastRevision = assignedTask.getRevisionLoop();
setRevisionIteration(ureq, lastRevision, revisionStepNames);
}
}
private void setRevisionIteration(UserRequest ureq, int iteration, List<String> revisionStepNames) {
String revCmpName = "revisions-" + iteration;
if(setRevision(ureq, revCmpName, iteration)) {
revisionStepNames.add(revCmpName);
}
//corrections;
String correctionCmpName = "corrections-" + iteration;
if(setCorrections(ureq, correctionCmpName, iteration)) {
revisionStepNames.add(correctionCmpName);
}
}
private void setUploadRevision(UserRequest ureq, Task task) {
File documentsDir;
VFSContainer documentsContainer;
int iteration = assignedTask.getRevisionLoop();
if(businessGroupTask) {
documentsDir = gtaManager.getRevisedDocumentsDirectory(courseEnv, gtaNode, iteration, assessedGroup);
documentsContainer = gtaManager.getRevisedDocumentsContainer(courseEnv, gtaNode, iteration, assessedGroup);
} else {
documentsDir = gtaManager.getRevisedDocumentsDirectory(courseEnv, gtaNode, iteration, getIdentity());
documentsContainer = gtaManager.getRevisedDocumentsContainer(courseEnv, gtaNode, iteration, getIdentity());
}
uploadRevisionsCtrl = new SubmitDocumentsController(ureq, getWindowControl(), task, documentsDir, documentsContainer, -1,
gtaNode, courseEnv, assessedUserCourseEnv.isCourseReadOnly(), null, "document");
listenTo(uploadRevisionsCtrl);
mainVC.put("uploadRevisions", uploadRevisionsCtrl.getInitialComponent());
submitRevisionButton = LinkFactory.createCustomLink("run.submit.revision.button", "submit", "run.submit.revision.button", Link.BUTTON, mainVC, this);
submitRevisionButton.setCustomEnabledLinkCSS(uploadRevisionsCtrl.hasUploadDocuments() ? "btn btn-primary" : "btn btn-default");
submitRevisionButton.setIconLeftCSS("o_icon o_icon o_icon_submit");
submitRevisionButton.setElementCssClass("o_sel_course_gta_submit_revisions");
submitRevisionButton.setVisible(!assessedUserCourseEnv.isCourseReadOnly());
}
private boolean setRevision(UserRequest ureq, String cmpName, int iteration) {
File documentsDir;
VFSContainer documentsContainer = null;
if(businessGroupTask) {
documentsDir = gtaManager.getRevisedDocumentsDirectory(courseEnv, gtaNode, iteration, assessedGroup);
documentsContainer = gtaManager.getRevisedDocumentsContainer(courseEnv, gtaNode, iteration, assessedGroup);
} else {
documentsDir = gtaManager.getRevisedDocumentsDirectory(courseEnv, gtaNode, iteration, getIdentity());
documentsContainer = gtaManager.getRevisedDocumentsContainer(courseEnv, gtaNode, iteration, getIdentity());
}
boolean hasDocument = TaskHelper.hasDocuments(documentsDir);
if(hasDocument) {
revisionsCtrl = new DirectoryController(ureq, getWindowControl(), documentsDir, documentsContainer,
"run.revised.description", "bulk.submitted.revisions", "revisions.zip");
listenTo(revisionsCtrl);
mainVC.put(cmpName, revisionsCtrl.getInitialComponent());
}
return hasDocument;
}
private boolean setCorrections(UserRequest ureq, String cmpName, int iteration) {
File documentsDir;
VFSContainer documentsContainer = null;
if(businessGroupTask) {
documentsDir = gtaManager.getRevisedDocumentsCorrectionsDirectory(courseEnv, gtaNode, iteration, assessedGroup);
documentsContainer = gtaManager.getRevisedDocumentsCorrectionsContainer(courseEnv, gtaNode, iteration, assessedGroup);
} else {
documentsDir = gtaManager.getRevisedDocumentsCorrectionsDirectory(courseEnv, gtaNode, iteration, getIdentity());
documentsContainer = gtaManager.getRevisedDocumentsCorrectionsContainer(courseEnv, gtaNode, iteration, getIdentity());
}
boolean hasDocument = TaskHelper.hasDocuments(documentsDir);
if(hasDocument) {
correctionsCtrl = new DirectoryController(ureq, getWindowControl(), documentsDir, documentsContainer,
"run.corrections.description", "bulk.review", "review");
listenTo(correctionsCtrl);
mainVC.put(cmpName, correctionsCtrl.getInitialComponent());
}
return hasDocument;
}
@Override
protected void event(UserRequest ureq, Controller source, Event event) {
if(uploadRevisionsCtrl == source) {
if(event instanceof SubmitEvent) {
Task aTask = uploadRevisionsCtrl.getAssignedTask();
gtaManager.log("Revision", (SubmitEvent)event, aTask, getIdentity(), getIdentity(), assessedGroup, courseEnv, gtaNode);
} else if(event == Event.DONE_EVENT) {
fireEvent(ureq, Event.DONE_EVENT);
}
submitRevisionButton.setCustomEnabledLinkCSS(uploadRevisionsCtrl.hasUploadDocuments() ? "btn btn-primary" : "btn btn-default");
} else if(confirmSubmitDialog == source) {
if(DialogBoxUIFactory.isOkEvent(event) || DialogBoxUIFactory.isYesEvent(event)) {
doSubmitRevisions();
fireEvent(ureq, Event.DONE_EVENT);
}
cleanUp();
}
super.event(ureq, source, event);
}
private void cleanUp() {
removeAsListenerAndDispose(confirmSubmitDialog);
confirmSubmitDialog = null;
}
@Override
protected void event(UserRequest ureq, Component source, Event event) {
if(submitRevisionButton == source) {
doConfirmSubmit(ureq);
}
}
private void doConfirmSubmit(UserRequest ureq) {
int iteration = assignedTask.getRevisionLoop();
String title = translate("run.submit.revision.button");
String text;
File[] submittedDocuments;
VFSContainer documentsContainer;
if(GTAType.group.name().equals(gtaNode.getModuleConfiguration().getStringValue(GTACourseNode.GTASK_TYPE))) {
documentsContainer = gtaManager.getRevisedDocumentsContainer(courseEnv, gtaNode, iteration, assessedGroup);
File documentsDir = gtaManager.getRevisedDocumentsDirectory(courseEnv, gtaNode, iteration, assessedGroup);
submittedDocuments = documentsDir.listFiles(new SystemFilenameFilter(true, false));
if(submittedDocuments.length == 0) {
text = "<div class='o_warning'>" + translate("run.submit.revision.confirm.warning.group", new String[]{ StringHelper.escapeHtml(assessedGroup.getName()) }) + "</div>";
} else {
text = translate("run.submit.revision.confirm.group", new String[]{ StringHelper.escapeHtml(assessedGroup.getName()) });
}
} else {
documentsContainer = gtaManager.getRevisedDocumentsContainer(courseEnv, gtaNode, iteration, getIdentity());
File documentsDir = gtaManager.getRevisedDocumentsDirectory(courseEnv, gtaNode, iteration, getIdentity());
submittedDocuments = documentsDir.listFiles(new SystemFilenameFilter(true, false));
if(submittedDocuments.length == 0) {
text = "<div class='o_warning'>" + translate("run.submit.revision.confirm.warning") + "</div>";
} else {
text = translate("run.submit.revision.confirm");
}
}
FilesLocked lockedBy = TaskHelper.getDocumentsLocked(documentsContainer, submittedDocuments);
if(lockedBy != null) {
showWarning("warning.submit.documents.edited", new String[]{ lockedBy.getLockedBy(), lockedBy.getLockedFiles() });
} else {
confirmSubmitDialog = activateOkCancelDialog(ureq, title, text, confirmSubmitDialog);
}
}
private void doSubmitRevisions() {
assignedTask = gtaManager.updateTask(assignedTask, TaskProcess.correction, gtaNode);
gtaManager.log("Revision", "revision submitted", assignedTask, getIdentity(), getIdentity(), assessedGroup, courseEnv, gtaNode);
TaskMultiUserEvent event = new TaskMultiUserEvent(TaskMultiUserEvent.SUBMIT_REVISION,
assessedGroup == null ? getIdentity() : null, assessedGroup, getIdentity());
CoordinatorManager.getInstance().getCoordinator().getEventBus()
.fireEventToListenersOf(event, taskListEventResource);
if(businessGroupTask) {
List<Identity> identities = businessGroupService.getMembers(assessedGroup, GroupRoles.participant.name());
ICourse course = CourseFactory.loadCourse(courseEnv.getCourseResourceableId());
for(Identity identity:identities) {
UserCourseEnvironment userCourseEnv = AssessmentHelper.createAndInitUserCourseEnvironment(identity, course);
gtaNode.incrementUserAttempts(userCourseEnv);
}
} else {
gtaNode.incrementUserAttempts(assessedUserCourseEnv);
}
}
}