/**
* <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.assessment.ui.tool;
import java.util.List;
import org.olat.basesecurity.BaseSecurity;
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.stack.TooledStackedPanel;
import org.olat.core.gui.components.stack.TooledStackedPanel.Align;
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.closablewrapper.CloseableCalloutWindowController;
import org.olat.core.id.Identity;
import org.olat.core.id.IdentityEnvironment;
import org.olat.core.id.Roles;
import org.olat.core.id.context.ContextEntry;
import org.olat.core.id.context.StateEntry;
import org.olat.course.CourseFactory;
import org.olat.course.ICourse;
import org.olat.course.assessment.ui.tool.event.CourseNodeEvent;
import org.olat.course.config.CourseConfig;
import org.olat.course.nodes.AssessableCourseNode;
import org.olat.course.nodes.CourseNode;
import org.olat.course.nodes.CourseNodeFactory;
import org.olat.course.nodes.STCourseNode;
import org.olat.course.run.userview.UserCourseEnvironment;
import org.olat.course.run.userview.UserCourseEnvironmentImpl;
import org.olat.modules.assessment.ui.AssessedIdentityController;
import org.olat.modules.assessment.ui.event.AssessmentFormEvent;
import org.olat.repository.RepositoryEntry;
import org.springframework.beans.factory.annotation.Autowired;
/**
*
* Initial date: 09.10.2015<br>
* @author srosse, stephane.rosse@frentix.com, http://www.frentix.com
*
*/
public class AssessmentIdentityCourseController extends BasicController implements AssessedIdentityController {
private final TooledStackedPanel stackPanel;
private final VelocityContainer identityAssessmentVC;
private Link nextLink, previousLink, courseNodeSelectionLink;
private IdentityCertificatesController certificateCtrl;
private AssessedIdentityLargeInfosController infosController;
private IdentityAssessmentOverviewController treeOverviewCtrl;
private AssessmentIdentityCourseNodeController currentNodeCtrl;
private CourseNodeSelectionController courseNodeChooserCtrl;
private CloseableCalloutWindowController courseNodeChooserCalloutCtrl;
private CourseNode currentCourseNode;
private final Identity assessedIdentity;
private final RepositoryEntry courseEntry;
private final UserCourseEnvironment coachCourseEnv;
@Autowired
private BaseSecurity securityManager;
public AssessmentIdentityCourseController(UserRequest ureq, WindowControl wControl, TooledStackedPanel stackPanel,
RepositoryEntry courseEntry, UserCourseEnvironment coachCourseEnv, Identity assessedIdentity) {
super(ureq, wControl);
this.stackPanel = stackPanel;
this.courseEntry = courseEntry;
this.coachCourseEnv = coachCourseEnv;
this.assessedIdentity = assessedIdentity;
identityAssessmentVC = createVelocityContainer("identity_personal_infos");
identityAssessmentVC.contextPut("user", assessedIdentity.getUser());
infosController = new AssessedIdentityLargeInfosController(ureq, wControl, assessedIdentity);
listenTo(infosController);
identityAssessmentVC.put("identityInfos", infosController.getInitialComponent());
ICourse course = CourseFactory.loadCourse(courseEntry);
CourseConfig courseConfig = course.getCourseConfig();
Roles roles = securityManager.getRoles(assessedIdentity);
IdentityEnvironment identityEnv = new IdentityEnvironment(assessedIdentity, roles);
UserCourseEnvironment assessedUserCourseEnv = new UserCourseEnvironmentImpl(identityEnv, course.getCourseEnvironment(), coachCourseEnv.isCourseReadOnly());
if(courseConfig.isAutomaticCertificationEnabled() || courseConfig.isManualCertificationEnabled()) {
certificateCtrl = new IdentityCertificatesController(ureq, wControl, courseEntry, assessedIdentity);
identityAssessmentVC.put("certificateInfos", certificateCtrl.getInitialComponent());
listenTo(certificateCtrl);
}
treeOverviewCtrl = new IdentityAssessmentOverviewController(ureq, getWindowControl(), assessedUserCourseEnv, true, false, true);
listenTo(treeOverviewCtrl);
identityAssessmentVC.put("courseOverview", treeOverviewCtrl.getInitialComponent());
putInitialPanel(identityAssessmentVC);
}
@Override
public Identity getAssessedIdentity() {
return assessedIdentity;
}
@Override
protected void doDispose() {
//
}
@Override
public void activate(UserRequest ureq, List<ContextEntry> entries, StateEntry state) {
if(entries != null || state != null) {
treeOverviewCtrl.activate(ureq, entries, state);
}
}
@Override
protected void event(UserRequest ureq, Controller source, Event event) {
if(treeOverviewCtrl == source) {
if(IdentityAssessmentOverviewController.EVENT_NODE_SELECTED.equals(event)) {
doSelectCourseNode(ureq, treeOverviewCtrl.getSelectedCourseNode());
}
} else if(courseNodeChooserCtrl == source) {
if(CourseNodeEvent.SELECT_COURSE_NODE.equals(event.getCommand())
&& event instanceof CourseNodeEvent) {
CourseNodeEvent cne = (CourseNodeEvent)event;
CourseNode selectedNode = treeOverviewCtrl.getNodeByIdent(cne.getIdent());
if(selectedNode != null) {
doSelectCourseNode(ureq, selectedNode);
}
}
courseNodeChooserCalloutCtrl.deactivate();
cleanUp();
} else if(courseNodeChooserCalloutCtrl == source) {
cleanUp();
} else if(currentNodeCtrl == source) {
if(event instanceof AssessmentFormEvent) {
AssessmentFormEvent aee = (AssessmentFormEvent)event;
treeOverviewCtrl.loadModel();
if(aee.isClose()) {
stackPanel.popController(currentNodeCtrl);
}
fireEvent(ureq, aee.cloneNotClose());
} else if(event == Event.CANCELLED_EVENT) {
stackPanel.popController(currentNodeCtrl);
} else if(event == Event.CHANGED_EVENT) {
treeOverviewCtrl.loadModel();
fireEvent(ureq, event);
}
}
super.event(ureq, source, event);
}
@Override
protected void event(UserRequest ureq, Component source, Event event) {
if(previousLink == source) {
doPreviousNode(ureq);
} else if(nextLink == source) {
doNextNode(ureq);
} else if(courseNodeSelectionLink == source) {
doSelectCourseNode(ureq);
}
}
private void cleanUp() {
removeAsListenerAndDispose(courseNodeChooserCtrl);
removeAsListenerAndDispose(courseNodeChooserCalloutCtrl);
courseNodeChooserCalloutCtrl = null;
courseNodeChooserCtrl = null;
}
private void doSelectCourseNode(UserRequest ureq) {
removeAsListenerAndDispose(courseNodeChooserCtrl);
removeAsListenerAndDispose(courseNodeChooserCalloutCtrl);
courseNodeChooserCtrl = new CourseNodeSelectionController(ureq, getWindowControl(), courseEntry);
listenTo(courseNodeChooserCtrl);
if(currentCourseNode != null) {
courseNodeChooserCtrl.selectedCourseNode(currentCourseNode);
} else {
courseNodeChooserCtrl.selectedCourseNode(treeOverviewCtrl.getSelectedCourseNode());
}
courseNodeChooserCalloutCtrl = new CloseableCalloutWindowController(ureq, getWindowControl(),
courseNodeChooserCtrl.getInitialComponent(), courseNodeSelectionLink, "", true, "");
listenTo(courseNodeChooserCalloutCtrl);
courseNodeChooserCalloutCtrl.activate();
}
private void doNextNode(UserRequest ureq) {
stackPanel.popController(currentNodeCtrl);
CourseNode nextNode = treeOverviewCtrl.getNextNode(currentNodeCtrl.getCourseNode());
if(nextNode != null && nextNode.getParent() != null) {
if(nextNode instanceof STCourseNode) {
for(nextNode=treeOverviewCtrl.getNextNode(nextNode); nextNode instanceof STCourseNode; ) {
//search the next node which is not a structure node
}
}
if(nextNode.getParent() != null) {
doSelectCourseNode(ureq, nextNode);
}
}
}
private void doPreviousNode(UserRequest ureq) {
stackPanel.popController(currentNodeCtrl);
CourseNode previousNode = treeOverviewCtrl.getPreviousNode(currentNodeCtrl.getCourseNode());
if(previousNode != null && previousNode.getParent() != null) {
if(previousNode instanceof STCourseNode) {
CourseNode node = previousNode;
for(previousNode=treeOverviewCtrl.getPreviousNode(previousNode); previousNode instanceof STCourseNode && node != previousNode; ) {
//search the previous node which is not a structure node
node = previousNode;
}
}
doSelectCourseNode(ureq, previousNode);
}
}
private void doSelectCourseNode(UserRequest ureq, CourseNode courseNode) {
if(courseNode == null || courseNode.getParent() == null) {
return;
}
currentCourseNode = courseNode;
stackPanel.popUpToController(this);
if(treeOverviewCtrl.isRoot(courseNode)) {
return;
}
removeAsListenerAndDispose(currentNodeCtrl);
currentNodeCtrl = new AssessmentIdentityCourseNodeController(ureq, getWindowControl(), stackPanel,
courseEntry, courseNode, coachCourseEnv, assessedIdentity, true);
listenTo(currentNodeCtrl);
stackPanel.pushController(courseNode.getShortTitle(), currentNodeCtrl);
previousLink = LinkFactory.createToolLink("previouselement", translate("previous"), this, "o_icon_previous");
previousLink.setTitle(translate("command.previous"));
previousLink.setEnabled(hasPrevious(courseNode));
stackPanel.addTool(previousLink, Align.rightEdge, false);
courseNodeSelectionLink = LinkFactory.createToolLink("node.select", "node.select", courseNode.getShortTitle(), this);
String courseNodeCssClass = CourseNodeFactory.getInstance()
.getCourseNodeConfigurationEvenForDisabledBB(courseNode.getType()).getIconCSSClass();
courseNodeSelectionLink.setElementCssClass("dropdown-toggle ");
courseNodeSelectionLink.setIconLeftCSS("o_icon " + courseNodeCssClass);
courseNodeSelectionLink.setIconRightCSS("o_icon o_icon_caret");
stackPanel.addTool(courseNodeSelectionLink, Align.rightEdge, false, "o_tool_dropdown dropdown");
nextLink = LinkFactory.createToolLink("nextelement", translate("next"), this, "o_icon_next");
nextLink.setTitle(translate("command.next"));
CourseNode nextNode = treeOverviewCtrl.getNextNode(courseNode);
boolean hasNext = (nextNode != null && nextNode.getParent() != null);
nextLink.setEnabled(hasNext);
stackPanel.addTool(nextLink, Align.rightEdge, false);
}
private boolean hasPrevious(CourseNode courseNode) {
int index = treeOverviewCtrl.getIndexOf(courseNode);
int numOfNodes = treeOverviewCtrl.getNumberOfNodes();
if(index > 0 && index <= numOfNodes) {
for(int i=index; i-->0; ) {
CourseNode previousNode = treeOverviewCtrl.getNode(i);
if(previousNode instanceof AssessableCourseNode && !(previousNode instanceof STCourseNode)) {
return true;
}
}
}
return false;
}
}