From 3e4fbfba4de6aefa38d9de6eacd47fc2474681a5 Mon Sep 17 00:00:00 2001 From: srosse <none@none> Date: Fri, 30 Oct 2015 17:21:29 +0100 Subject: [PATCH] OO-1593: navigate around course element with next, previous and menu --- .../course/assessment/AssessmentHelper.java | 57 +++++++++++++ .../IdentityAssessmentOverviewController.java | 14 +++- .../AssessedIdentityLargeInfosController.java | 66 +++++++++++++++ .../AssessmentCourseOverviewController.java | 25 +++++- ...ssmentCourseStatisticsSmallController.java | 13 +-- ...essmentIdentitiesCourseTreeController.java | 68 +++------------- .../AssessmentIdentityCourseController.java | 79 +++++++++++++++--- ...ssessmentIdentityCourseNodeController.java | 14 ++-- .../ui/tool/AssessmentToolController.java | 21 ++++- .../tool/CourseNodeSelectionController.java | 81 +++++++++++++++++++ .../ui/tool/_content/course_node_chooser.html | 1 + .../ui/tool/_content/course_overview.html | 12 ++- .../identity_personal_node_infos.html | 5 +- .../ui/tool/_content/user_infos_large.html | 4 + .../ui/tool/_i18n/LocalStrings_de.properties | 2 + .../ui/tool/event/CourseNodeEvent.java | 46 +++++++++++ 16 files changed, 421 insertions(+), 87 deletions(-) create mode 100644 src/main/java/org/olat/course/assessment/ui/tool/AssessedIdentityLargeInfosController.java create mode 100644 src/main/java/org/olat/course/assessment/ui/tool/CourseNodeSelectionController.java create mode 100644 src/main/java/org/olat/course/assessment/ui/tool/_content/course_node_chooser.html create mode 100644 src/main/java/org/olat/course/assessment/ui/tool/_content/user_infos_large.html create mode 100644 src/main/java/org/olat/course/assessment/ui/tool/event/CourseNodeEvent.java diff --git a/src/main/java/org/olat/course/assessment/AssessmentHelper.java b/src/main/java/org/olat/course/assessment/AssessmentHelper.java index 3bba13632ac..6b2c4b37b8d 100644 --- a/src/main/java/org/olat/course/assessment/AssessmentHelper.java +++ b/src/main/java/org/olat/course/assessment/AssessmentHelper.java @@ -35,6 +35,9 @@ import java.util.List; import java.util.Locale; import java.util.Map; +import org.olat.core.gui.components.tree.GenericTreeModel; +import org.olat.core.gui.components.tree.GenericTreeNode; +import org.olat.core.gui.components.tree.TreeModel; import org.olat.core.id.Identity; import org.olat.core.id.IdentityEnvironment; import org.olat.core.logging.OLog; @@ -47,6 +50,7 @@ import org.olat.course.ICourse; import org.olat.course.assessment.model.AssessmentNodeData; import org.olat.course.nodes.AssessableCourseNode; import org.olat.course.nodes.CourseNode; +import org.olat.course.nodes.CourseNodeFactory; import org.olat.course.nodes.ProjectBrokerCourseNode; import org.olat.course.nodes.STCourseNode; import org.olat.course.nodes.ScormCourseNode; @@ -308,6 +312,59 @@ public class AssessmentHelper { } } + /** + * + * @param course + * @return + */ + public static TreeModel assessmentTreeModel(ICourse course) { + CourseNode rootNode = course.getRunStructure().getRootNode(); + GenericTreeModel gtm = new GenericTreeModel(); + GenericTreeNode node = new GenericTreeNode(); + node.setTitle(rootNode.getShortTitle()); + node.setUserObject(rootNode); + node.setIconCssClass(CourseNodeFactory.getInstance().getCourseNodeConfiguration(rootNode.getType()).getIconCSSClass()); + gtm.setRootNode(node); + + List<GenericTreeNode> children = addAssessableNodesToList(rootNode); + children.forEach((child) -> node.addChild(child)); + return gtm; + } + + private static List<GenericTreeNode> addAssessableNodesToList(CourseNode parentCourseNode) { + List<GenericTreeNode> result = new ArrayList<>(); + for(int i=0; i<parentCourseNode.getChildCount(); i++) { + CourseNode courseNode = (CourseNode)parentCourseNode.getChildAt(i); + List<GenericTreeNode> assessableChildren = addAssessableNodesToList(courseNode); + + if (assessableChildren.size() > 0 || isAssessable(courseNode)) { + GenericTreeNode node = new GenericTreeNode(); + node.setTitle(courseNode.getShortTitle()); + node.setUserObject(courseNode); + node.setIconCssClass(CourseNodeFactory.getInstance().getCourseNodeConfiguration(courseNode.getType()).getIconCSSClass()); + result.add(node); + assessableChildren.forEach((child) -> node.addChild(child)); + } + } + return result; + } + + private static boolean isAssessable(CourseNode courseNode) { + boolean assessable = false; + if (courseNode instanceof AssessableCourseNode && !(courseNode instanceof ProjectBrokerCourseNode)) { + AssessableCourseNode assessableCourseNode = (AssessableCourseNode) courseNode; + if (assessableCourseNode.hasDetails() + || assessableCourseNode.hasAttemptsConfigured() + || assessableCourseNode.hasScoreConfigured() + || assessableCourseNode.hasPassedConfigured() + || assessableCourseNode.hasCommentConfigured()) { + + assessable = true; + } + } + return assessable; + } + public static List<Map<String,Object>> assessmentNodeDataListToMap(List<AssessmentNodeData> assessmentNodeData) { List<Map<String,Object>> maps = new ArrayList<>(assessmentNodeData.size()); diff --git a/src/main/java/org/olat/course/assessment/IdentityAssessmentOverviewController.java b/src/main/java/org/olat/course/assessment/IdentityAssessmentOverviewController.java index 72fed0ed2f7..d87f9cba9b0 100644 --- a/src/main/java/org/olat/course/assessment/IdentityAssessmentOverviewController.java +++ b/src/main/java/org/olat/course/assessment/IdentityAssessmentOverviewController.java @@ -140,6 +140,18 @@ public class IdentityAssessmentOverviewController extends BasicController { putInitialPanel(main); } + public boolean isRoot(CourseNode node) { + return node != null && node.getIdent().equals(runStructure.getRootNode().getIdent()); + } + + public int getNumberOfNodes() { + return nodesTableModel.getRowCount(); + } + + public CourseNode getNodeByIdent(String ident) { + return runStructure.getNode(ident); + } + public CourseNode getNextNode(CourseNode node) { int index = getIndexOf(node); @@ -178,7 +190,7 @@ public class IdentityAssessmentOverviewController extends BasicController { return null; } - private int getIndexOf(CourseNode node) { + public int getIndexOf(CourseNode node) { for(int i=nodesTableModel.getRowCount(); i-->0; ) { Object rowIdentityKey = nodesTableModel.getObject(i).getIdent(); if(rowIdentityKey.equals(node.getIdent())) { diff --git a/src/main/java/org/olat/course/assessment/ui/tool/AssessedIdentityLargeInfosController.java b/src/main/java/org/olat/course/assessment/ui/tool/AssessedIdentityLargeInfosController.java new file mode 100644 index 00000000000..78e7f306a13 --- /dev/null +++ b/src/main/java/org/olat/course/assessment/ui/tool/AssessedIdentityLargeInfosController.java @@ -0,0 +1,66 @@ +/** + * <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 org.olat.admin.user.UserShortDescription; +import org.olat.core.gui.UserRequest; +import org.olat.core.gui.components.Component; +import org.olat.core.gui.components.velocity.VelocityContainer; +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.id.Identity; +import org.olat.user.DisplayPortraitController; + +/** + * + * Initial date: 28.10.2015<br> + * @author srosse, stephane.rosse@frentix.com, http://www.frentix.com + * + */ +public class AssessedIdentityLargeInfosController extends BasicController { + + private final VelocityContainer mainVC; + private final DisplayPortraitController portraitCtr; + private final UserShortDescription userShortDescrCtr; + + public AssessedIdentityLargeInfosController(UserRequest ureq, WindowControl wControl, Identity assessedIdentity) { + super(ureq, wControl); + mainVC = createVelocityContainer("user_infos_large"); + mainVC.contextPut("user", assessedIdentity.getUser()); + + portraitCtr = new DisplayPortraitController(ureq, getWindowControl(), assessedIdentity, true, true); + mainVC.put("portrait", portraitCtr.getInitialComponent()); + userShortDescrCtr = new UserShortDescription(ureq, getWindowControl(), assessedIdentity); + mainVC.put("userShortDescription", userShortDescrCtr.getInitialComponent()); + + putInitialPanel(mainVC); + } + + @Override + protected void doDispose() { + // + } + + @Override + protected void event(UserRequest ureq, Component source, Event event) { + // + } +} diff --git a/src/main/java/org/olat/course/assessment/ui/tool/AssessmentCourseOverviewController.java b/src/main/java/org/olat/course/assessment/ui/tool/AssessmentCourseOverviewController.java index 31f93a4ebaa..15df0e978cc 100644 --- a/src/main/java/org/olat/course/assessment/ui/tool/AssessmentCourseOverviewController.java +++ b/src/main/java/org/olat/course/assessment/ui/tool/AssessmentCourseOverviewController.java @@ -19,12 +19,19 @@ */ package org.olat.course.assessment.ui.tool; +import java.util.List; + 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.Event; import org.olat.core.gui.control.WindowControl; import org.olat.core.gui.control.controller.BasicController; +import org.olat.core.gui.control.generic.dtabs.Activateable2; +import org.olat.core.id.context.ContextEntry; +import org.olat.core.id.context.StateEntry; import org.olat.modules.assessment.ui.AssessmentToolSecurityCallback; import org.olat.repository.RepositoryEntry; @@ -34,12 +41,15 @@ import org.olat.repository.RepositoryEntry; * @author srosse, stephane.rosse@frentix.com, http://www.frentix.com * */ -public class AssessmentCourseOverviewController extends BasicController { +public class AssessmentCourseOverviewController extends BasicController implements Activateable2 { + + protected static final Event SELECT_USERS_EVENT = new Event("assessment-tool-select-users"); private final VelocityContainer mainVC; private final AssessmentToReviewSmallController toReviewCtrl; private final AssessmentCourseStatisticsSmallController statisticsCtrl; + private Link assessedIdentitiesLink; public AssessmentCourseOverviewController(UserRequest ureq, WindowControl wControl, RepositoryEntry courseEntry, AssessmentToolSecurityCallback assessmentCallback) { @@ -54,6 +64,10 @@ public class AssessmentCourseOverviewController extends BasicController { statisticsCtrl = new AssessmentCourseStatisticsSmallController(ureq, getWindowControl(), courseEntry, assessmentCallback); listenTo(statisticsCtrl); mainVC.put("statistics", statisticsCtrl.getInitialComponent()); + + int numOfAssessedIdentities = statisticsCtrl.getNumOfAssessedIdentities(); + assessedIdentitiesLink = LinkFactory.createLink("assessed.identities", "assessed.identities", getTranslator(), mainVC, this, Link.NONTRANSLATED); + assessedIdentitiesLink.setCustomDisplayText(translate("assessment.tool.numOfAssessedIdentities", new String[]{ Integer.toString(numOfAssessedIdentities) })); putInitialPanel(mainVC); } @@ -64,9 +78,14 @@ public class AssessmentCourseOverviewController extends BasicController { } @Override - protected void event(UserRequest ureq, Component source, Event event) { + public void activate(UserRequest ureq, List<ContextEntry> entries, StateEntry state) { // } - + @Override + protected void event(UserRequest ureq, Component source, Event event) { + if(assessedIdentitiesLink == source) { + fireEvent(ureq, SELECT_USERS_EVENT); + } + } } diff --git a/src/main/java/org/olat/course/assessment/ui/tool/AssessmentCourseStatisticsSmallController.java b/src/main/java/org/olat/course/assessment/ui/tool/AssessmentCourseStatisticsSmallController.java index 8616e2c5309..3ca65b82a46 100644 --- a/src/main/java/org/olat/course/assessment/ui/tool/AssessmentCourseStatisticsSmallController.java +++ b/src/main/java/org/olat/course/assessment/ui/tool/AssessmentCourseStatisticsSmallController.java @@ -46,6 +46,8 @@ public class AssessmentCourseStatisticsSmallController extends BasicController { private final RepositoryEntry courseEntry; private final AssessmentToolSecurityCallback assessmentCallback; + private int numOfAssessedIdentities; + @Autowired private AssessmentToolManager assessmentToolManager; @@ -60,11 +62,16 @@ public class AssessmentCourseStatisticsSmallController extends BasicController { updateStatistics(); } + public int getNumOfAssessedIdentities() { + return numOfAssessedIdentities; + } + public void updateStatistics() { SearchAssessedIdentityParams params = new SearchAssessedIdentityParams(courseEntry, null, null, assessmentCallback); CourseStatistics stats = assessmentToolManager.getStatistics(getIdentity(), params); - mainVC.contextPut("numOfAssessedIdentities", stats.getNumOfAssessedIdentities()); + numOfAssessedIdentities = stats.getNumOfAssessedIdentities(); + mainVC.contextPut("numOfAssessedIdentities", numOfAssessedIdentities); mainVC.contextPut("scoreAverage", AssessmentHelper.getRoundedScore(stats.getAverageScore())); mainVC.contextPut("numOfPassed", stats.getCountPassed()); int percentPassed = Math.round(100.0f * ((float)stats.getCountPassed() / (float)stats.getNumOfAssessedIdentities())); @@ -74,8 +81,6 @@ public class AssessmentCourseStatisticsSmallController extends BasicController { mainVC.contextPut("percentFailed", percentFailed); mainVC.contextPut("numOfInitialLaunch", stats.getInitialLaunch()); - - } @Override @@ -87,6 +92,4 @@ public class AssessmentCourseStatisticsSmallController extends BasicController { protected void event(UserRequest ureq, Component source, Event event) { // } - - } diff --git a/src/main/java/org/olat/course/assessment/ui/tool/AssessmentIdentitiesCourseTreeController.java b/src/main/java/org/olat/course/assessment/ui/tool/AssessmentIdentitiesCourseTreeController.java index 42d7a5784f1..39712ccaf26 100644 --- a/src/main/java/org/olat/course/assessment/ui/tool/AssessmentIdentitiesCourseTreeController.java +++ b/src/main/java/org/olat/course/assessment/ui/tool/AssessmentIdentitiesCourseTreeController.java @@ -19,7 +19,6 @@ */ package org.olat.course.assessment.ui.tool; -import java.util.ArrayList; import java.util.List; import org.olat.core.commons.fullWebApp.LayoutMain3ColsController; @@ -27,8 +26,6 @@ import org.olat.core.gui.UserRequest; import org.olat.core.gui.components.Component; import org.olat.core.gui.components.panel.Panel; import org.olat.core.gui.components.stack.TooledStackedPanel; -import org.olat.core.gui.components.tree.GenericTreeModel; -import org.olat.core.gui.components.tree.GenericTreeNode; import org.olat.core.gui.components.tree.MenuTree; import org.olat.core.gui.components.tree.TreeModel; import org.olat.core.gui.components.tree.TreeNode; @@ -37,14 +34,15 @@ 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.dtabs.Activateable2; +import org.olat.core.id.OLATResourceable; +import org.olat.core.id.context.BusinessControlFactory; import org.olat.core.id.context.ContextEntry; import org.olat.core.id.context.StateEntry; +import org.olat.core.util.resource.OresHelper; import org.olat.course.CourseFactory; import org.olat.course.ICourse; -import org.olat.course.nodes.AssessableCourseNode; +import org.olat.course.assessment.AssessmentHelper; import org.olat.course.nodes.CourseNode; -import org.olat.course.nodes.CourseNodeFactory; -import org.olat.course.nodes.ProjectBrokerCourseNode; import org.olat.modules.assessment.ui.AssessmentToolSecurityCallback; import org.olat.repository.RepositoryEntry; @@ -75,7 +73,7 @@ public class AssessmentIdentitiesCourseTreeController extends BasicController im // Navigation menu menuTree = new MenuTree("menuTree"); - TreeModel tm = buildTreeModel(course); + TreeModel tm = AssessmentHelper.assessmentTreeModel(course); menuTree.setTreeModel(tm); menuTree.setSelectedNodeId(tm.getRootNode().getIdent()); menuTree.addListener(this); @@ -88,54 +86,6 @@ public class AssessmentIdentitiesCourseTreeController extends BasicController im putInitialPanel(columLayoutCtr.getInitialComponent()); } - private TreeModel buildTreeModel(ICourse course) { - CourseNode rootNode = course.getRunStructure().getRootNode(); - GenericTreeModel gtm = new GenericTreeModel(); - GenericTreeNode node = new GenericTreeNode(); - node.setTitle(rootNode.getShortTitle()); - node.setUserObject(rootNode); - node.setIconCssClass(CourseNodeFactory.getInstance().getCourseNodeConfiguration(rootNode.getType()).getIconCSSClass()); - gtm.setRootNode(node); - - List<GenericTreeNode> children = addAssessableNodesToList(rootNode); - children.forEach((child) -> node.addChild(child)); - return gtm; - } - - private List<GenericTreeNode> addAssessableNodesToList(CourseNode parentCourseNode) { - List<GenericTreeNode> result = new ArrayList<>(); - for(int i=0; i<parentCourseNode.getChildCount(); i++) { - CourseNode courseNode = (CourseNode)parentCourseNode.getChildAt(i); - List<GenericTreeNode> assessableChildren = addAssessableNodesToList(courseNode); - - if (assessableChildren.size() > 0 || isAssessable(courseNode)) { - GenericTreeNode node = new GenericTreeNode(); - node.setTitle(courseNode.getShortTitle()); - node.setUserObject(courseNode); - node.setIconCssClass(CourseNodeFactory.getInstance().getCourseNodeConfiguration(courseNode.getType()).getIconCSSClass()); - result.add(node); - assessableChildren.forEach((child) -> node.addChild(child)); - } - } - return result; - } - - private boolean isAssessable(CourseNode courseNode) { - boolean assessable = false; - if (courseNode instanceof AssessableCourseNode && !(courseNode instanceof ProjectBrokerCourseNode)) { - AssessableCourseNode assessableCourseNode = (AssessableCourseNode) courseNode; - if (assessableCourseNode.hasDetails() - || assessableCourseNode.hasAttemptsConfigured() - || assessableCourseNode.hasScoreConfigured() - || assessableCourseNode.hasPassedConfigured() - || assessableCourseNode.hasCommentConfigured()) { - - assessable = true; - } - } - return assessable; - } - @Override protected void doDispose() { // @@ -165,14 +115,18 @@ public class AssessmentIdentitiesCourseTreeController extends BasicController im private void doSelectCourseNode(UserRequest ureq, CourseNode courseNode) { removeAsListenerAndDispose(currentCtrl); + + OLATResourceable ores = OresHelper.createOLATResourceableInstance("Node", new Long(courseNode.getIdent())); + WindowControl bwControl = BusinessControlFactory.getInstance().createBusinessWindowControl(ores, null, getWindowControl()); ICourse course = CourseFactory.loadCourse(courseEntry); if(course.getRunStructure().getRootNode().equals(courseNode)) { - currentCtrl = new AssessmentIdentitiesCourseController(ureq, getWindowControl(), stackPanel, courseEntry, assessmentCallback); + currentCtrl = new AssessmentIdentitiesCourseController(ureq, bwControl, stackPanel, courseEntry, assessmentCallback); } else { - currentCtrl = new AssessmentIdentitiesCourseNodeController(ureq, getWindowControl(), stackPanel, courseEntry, courseNode, assessmentCallback); + currentCtrl = new AssessmentIdentitiesCourseNodeController(ureq, bwControl, stackPanel, courseEntry, courseNode, assessmentCallback); } listenTo(currentCtrl); mainPanel.setContent(currentCtrl.getInitialComponent()); + addToHistory(ureq, currentCtrl); } } diff --git a/src/main/java/org/olat/course/assessment/ui/tool/AssessmentIdentityCourseController.java b/src/main/java/org/olat/course/assessment/ui/tool/AssessmentIdentityCourseController.java index 422a9b0fd44..3d1ba2f1275 100644 --- a/src/main/java/org/olat/course/assessment/ui/tool/AssessmentIdentityCourseController.java +++ b/src/main/java/org/olat/course/assessment/ui/tool/AssessmentIdentityCourseController.java @@ -31,15 +31,17 @@ 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.course.CourseFactory; import org.olat.course.ICourse; -import org.olat.course.assessment.AssessedIdentityInfosController; import org.olat.course.assessment.IdentityAssessmentOverviewController; +import org.olat.course.assessment.ui.tool.event.CourseNodeEvent; import org.olat.course.config.CourseConfig; import org.olat.course.nodes.CourseNode; +import org.olat.course.nodes.CourseNodeFactory; import org.olat.course.run.userview.UserCourseEnvironment; import org.olat.course.run.userview.UserCourseEnvironmentImpl; import org.olat.repository.RepositoryEntry; @@ -56,14 +58,16 @@ public class AssessmentIdentityCourseController extends BasicController { private final Identity assessedIdentity; private final RepositoryEntry courseEntry; - private Link nextLink, previousLink; private final TooledStackedPanel stackPanel; private final VelocityContainer identityAssessmentVC; + private Link nextLink, previousLink, courseNodeSelectionLink; private IdentityCertificatesController certificateCtrl; - private AssessedIdentityInfosController infosController; + private AssessedIdentityLargeInfosController infosController; private IdentityAssessmentOverviewController treeOverviewCtrl; private AssessmentIdentityCourseNodeController currentNodeCtrl; + private CourseNodeSelectionController courseNodeChooserCtrl; + private CloseableCalloutWindowController courseNodeChooserCalloutCtrl; @Autowired private BaseSecurity securityManager; @@ -79,7 +83,7 @@ public class AssessmentIdentityCourseController extends BasicController { identityAssessmentVC = createVelocityContainer("identity_personal_infos"); identityAssessmentVC.contextPut("user", assessedIdentity.getUser()); - infosController = new AssessedIdentityInfosController(ureq, wControl, assessedIdentity); + infosController = new AssessedIdentityLargeInfosController(ureq, wControl, assessedIdentity); listenTo(infosController); identityAssessmentVC.put("identityInfos", infosController.getInitialComponent()); @@ -95,7 +99,7 @@ public class AssessmentIdentityCourseController extends BasicController { listenTo(certificateCtrl); } - treeOverviewCtrl = new IdentityAssessmentOverviewController(ureq, getWindowControl(), assessedUserCourseEnv, true, true, false); + treeOverviewCtrl = new IdentityAssessmentOverviewController(ureq, getWindowControl(), assessedUserCourseEnv, true, false, true); listenTo(treeOverviewCtrl); identityAssessmentVC.put("courseOverview", treeOverviewCtrl.getInitialComponent()); @@ -117,6 +121,19 @@ public class AssessmentIdentityCourseController extends BasicController { 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(); } super.event(ureq, source, event); } @@ -127,9 +144,31 @@ public class AssessmentIdentityCourseController extends BasicController { 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); + + courseNodeChooserCalloutCtrl = new CloseableCalloutWindowController(ureq, getWindowControl(), + courseNodeChooserCtrl.getInitialComponent(), courseNodeSelectionLink, "", true, ""); + listenTo(courseNodeChooserCalloutCtrl); + courseNodeChooserCalloutCtrl.activate(); + } + private void doNextNode(UserRequest ureq) { stackPanel.popController(currentNodeCtrl); @@ -149,7 +188,14 @@ public class AssessmentIdentityCourseController extends BasicController { } private void doSelectCourseNode(UserRequest ureq, CourseNode courseNode) { - if(courseNode == null) return; + if(courseNode == null) { + return; + } + stackPanel.popUpToController(this); + if(treeOverviewCtrl.isRoot(courseNode)) { + return; + } + removeAsListenerAndDispose(currentNodeCtrl); currentNodeCtrl = new AssessmentIdentityCourseNodeController(ureq, getWindowControl(), stackPanel, @@ -157,11 +203,24 @@ public class AssessmentIdentityCourseController extends BasicController { listenTo(currentNodeCtrl); stackPanel.pushController(courseNode.getShortTitle(), currentNodeCtrl); - previousLink = LinkFactory.createToolLink("previouselement","", this, "o_icon_previous_toolbar"); + int index = treeOverviewCtrl.getIndexOf(courseNode); + int numOfNodes = treeOverviewCtrl.getNumberOfNodes(); + + previousLink = LinkFactory.createToolLink("previouselement","", this, "o_icon_previous"); previousLink.setTitle(translate("command.previous")); - stackPanel.addTool(previousLink, Align.rightEdge, false, "o_tool_previous"); - nextLink = LinkFactory.createToolLink("nextelement","", this, "o_icon_next_toolbar"); + previousLink.setEnabled(index > 1 && index <= numOfNodes); + 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.setIconLeftCSS("o_icon " + courseNodeCssClass); + courseNodeSelectionLink.setIconRightCSS("o_icon o_icon_caret"); + stackPanel.addTool(courseNodeSelectionLink, Align.rightEdge, false); + + nextLink = LinkFactory.createToolLink("nextelement","", this, "o_icon_next"); nextLink.setTitle(translate("command.next")); - stackPanel.addTool(nextLink, Align.rightEdge, false, "o_tool_next"); + nextLink.setEnabled(index > 0 && index < numOfNodes); + stackPanel.addTool(nextLink, Align.rightEdge, false, ""); } } diff --git a/src/main/java/org/olat/course/assessment/ui/tool/AssessmentIdentityCourseNodeController.java b/src/main/java/org/olat/course/assessment/ui/tool/AssessmentIdentityCourseNodeController.java index a902308fbd8..2d98fcd76bd 100644 --- a/src/main/java/org/olat/course/assessment/ui/tool/AssessmentIdentityCourseNodeController.java +++ b/src/main/java/org/olat/course/assessment/ui/tool/AssessmentIdentityCourseNodeController.java @@ -34,16 +34,17 @@ import org.olat.core.id.Roles; import org.olat.core.util.Formatter; import org.olat.course.CourseFactory; import org.olat.course.ICourse; -import org.olat.course.assessment.AssessedIdentityInfosController; import org.olat.course.assessment.AssessmentForm; import org.olat.course.assessment.OpenSubDetailsEvent; import org.olat.course.nodes.AssessableCourseNode; import org.olat.course.nodes.CourseNode; +import org.olat.course.nodes.CourseNodeFactory; import org.olat.course.nodes.MSCourseNode; import org.olat.course.run.userview.UserCourseEnvironment; import org.olat.course.run.userview.UserCourseEnvironmentImpl; import org.olat.modules.ModuleConfiguration; import org.olat.repository.RepositoryEntry; +import org.olat.user.UserManager; import org.springframework.beans.factory.annotation.Autowired; /** @@ -60,11 +61,12 @@ public class AssessmentIdentityCourseNodeController extends BasicController { private AssessmentForm assessmentForm; private Controller subDetailsController; private Controller detailsEditController; - private AssessedIdentityInfosController infosController; private final CourseNode courseNode; private final Identity assessedIdentity; + @Autowired + private UserManager userManager; @Autowired private BaseSecurity securityManager; @@ -78,10 +80,12 @@ public class AssessmentIdentityCourseNodeController extends BasicController { identityAssessmentVC = createVelocityContainer("identity_personal_node_infos"); identityAssessmentVC.contextPut("user", assessedIdentity.getUser()); + identityAssessmentVC.contextPut("fullName", userManager.getUserDisplayName(assessedIdentity)); + identityAssessmentVC.contextPut("courseNode", courseNode.getShortTitle()); - infosController = new AssessedIdentityInfosController(ureq, wControl, assessedIdentity); - listenTo(infosController); - identityAssessmentVC.put("identityInfos", infosController.getInitialComponent()); + String courseNodeCssClass = CourseNodeFactory.getInstance() + .getCourseNodeConfigurationEvenForDisabledBB(courseNode.getType()).getIconCSSClass(); + identityAssessmentVC.contextPut("courseNodeCss", courseNodeCssClass); ModuleConfiguration modConfig = courseNode.getModuleConfiguration(); String infoCoach = (String) modConfig.get(MSCourseNode.CONFIG_KEY_INFOTEXT_COACH); diff --git a/src/main/java/org/olat/course/assessment/ui/tool/AssessmentToolController.java b/src/main/java/org/olat/course/assessment/ui/tool/AssessmentToolController.java index 6d6cd13f79a..adcc94063f5 100644 --- a/src/main/java/org/olat/course/assessment/ui/tool/AssessmentToolController.java +++ b/src/main/java/org/olat/course/assessment/ui/tool/AssessmentToolController.java @@ -26,13 +26,17 @@ 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.control.Controller; import org.olat.core.gui.control.Event; import org.olat.core.gui.control.WindowControl; import org.olat.core.gui.control.controller.MainLayoutBasicController; import org.olat.core.gui.control.generic.dtabs.Activateable2; +import org.olat.core.id.OLATResourceable; +import org.olat.core.id.context.BusinessControlFactory; import org.olat.core.id.context.ContextEntry; import org.olat.core.id.context.StateEntry; import org.olat.core.util.Util; +import org.olat.core.util.resource.OresHelper; import org.olat.course.assessment.AssessmentMainController; import org.olat.modules.assessment.ui.AssessmentToolSecurityCallback; import org.olat.repository.RepositoryEntry; @@ -92,11 +96,24 @@ public class AssessmentToolController extends MainLayoutBasicController implemen doSelectUsersView(ureq); } } - + + @Override + protected void event(UserRequest ureq, Controller source, Event event) { + if(overviewCtrl == source) { + if(event == AssessmentCourseOverviewController.SELECT_USERS_EVENT) { + doSelectUsersView(ureq); + } + } + super.event(ureq, source, event); + } + private void doSelectUsersView(UserRequest ureq) { removeAsListenerAndDispose(currentCtl); - AssessmentIdentitiesCourseTreeController treeCtrl = new AssessmentIdentitiesCourseTreeController(ureq, getWindowControl(), stackPanel, + OLATResourceable ores = OresHelper.createOLATResourceableInstance("Users", 0l); + WindowControl bwControl = BusinessControlFactory.getInstance().createBusinessWindowControl(ores, null, getWindowControl()); + addToHistory(ureq, bwControl); + AssessmentIdentitiesCourseTreeController treeCtrl = new AssessmentIdentitiesCourseTreeController(ureq, bwControl, stackPanel, courseEntry, assessmentCallback); listenTo(treeCtrl); stackPanel.pushController(translate("users"), treeCtrl); diff --git a/src/main/java/org/olat/course/assessment/ui/tool/CourseNodeSelectionController.java b/src/main/java/org/olat/course/assessment/ui/tool/CourseNodeSelectionController.java new file mode 100644 index 00000000000..4102b829d3d --- /dev/null +++ b/src/main/java/org/olat/course/assessment/ui/tool/CourseNodeSelectionController.java @@ -0,0 +1,81 @@ +/** + * <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 org.olat.core.gui.UserRequest; +import org.olat.core.gui.components.Component; +import org.olat.core.gui.components.tree.MenuTree; +import org.olat.core.gui.components.tree.TreeModel; +import org.olat.core.gui.components.velocity.VelocityContainer; +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.course.CourseFactory; +import org.olat.course.ICourse; +import org.olat.course.assessment.AssessmentHelper; +import org.olat.course.assessment.ui.tool.event.CourseNodeEvent; +import org.olat.course.nodes.CourseNode; +import org.olat.repository.RepositoryEntry; + +/** + * + * Initial date: 30.10.2015<br> + * @author srosse, stephane.rosse@frentix.com, http://www.frentix.com + * + */ +public class CourseNodeSelectionController extends BasicController { + + private final MenuTree menuTree; + + public CourseNodeSelectionController(UserRequest ureq, WindowControl wControl, RepositoryEntry courseEntry) { + super(ureq, wControl); + + ICourse course = CourseFactory.loadCourse(courseEntry); + + // Navigation menu + menuTree = new MenuTree("menuTree"); + TreeModel tm = AssessmentHelper.assessmentTreeModel(course); + menuTree.setTreeModel(tm); + menuTree.setSelectedNodeId(tm.getRootNode().getIdent()); + menuTree.addListener(this); + + VelocityContainer mainVC = createVelocityContainer("course_node_chooser"); + mainVC.put("courseTree", menuTree); + putInitialPanel(mainVC); + } + + @Override + protected void doDispose() { + // + } + + @Override + protected void event(UserRequest ureq, Component source, Event event) { + if (source == menuTree) { + if (event.getCommand().equals(MenuTree.COMMAND_TREENODE_CLICKED)) { + Object uo = menuTree.getSelectedNode().getUserObject(); + if(uo instanceof CourseNode) { + CourseNode selectedNode = (CourseNode)uo; + fireEvent(ureq, new CourseNodeEvent(CourseNodeEvent.SELECT_COURSE_NODE, selectedNode.getIdent())); + } + } + } + } +} \ No newline at end of file diff --git a/src/main/java/org/olat/course/assessment/ui/tool/_content/course_node_chooser.html b/src/main/java/org/olat/course/assessment/ui/tool/_content/course_node_chooser.html new file mode 100644 index 00000000000..24564e84732 --- /dev/null +++ b/src/main/java/org/olat/course/assessment/ui/tool/_content/course_node_chooser.html @@ -0,0 +1 @@ +$r.render("courseTree") \ No newline at end of file diff --git a/src/main/java/org/olat/course/assessment/ui/tool/_content/course_overview.html b/src/main/java/org/olat/course/assessment/ui/tool/_content/course_overview.html index 37a52450f2b..a1071244267 100644 --- a/src/main/java/org/olat/course/assessment/ui/tool/_content/course_overview.html +++ b/src/main/java/org/olat/course/assessment/ui/tool/_content/course_overview.html @@ -1,4 +1,14 @@ -<h2>Overview</h2> +<h2>$r.translate("assessment.tool.overview")</h2> +<div class="row o_block"> + <div class="col-sm-6"> + #if($r.available("assessed.identities")) + $r.render("assessed.identities") + #end + </div> + <div class="col-sm-6"> + Other links + </div> +</div> <div class="row"> <div class="col-sm-6"> #if($r.available("toReview")) diff --git a/src/main/java/org/olat/course/assessment/ui/tool/_content/identity_personal_node_infos.html b/src/main/java/org/olat/course/assessment/ui/tool/_content/identity_personal_node_infos.html index 98387945179..86e3e2f2efa 100644 --- a/src/main/java/org/olat/course/assessment/ui/tool/_content/identity_personal_node_infos.html +++ b/src/main/java/org/olat/course/assessment/ui/tool/_content/identity_personal_node_infos.html @@ -1,6 +1,5 @@ -#if($r.available("identityInfos")) - $r.render("identityInfos") -#end +<h2><i class="o_icon $courseNodeCss"> </i> $r.escapeHtml($courseNode) <small><i class="o_icon o_icon_user"> </i> $r.escapeHtml($fullName) </small></h2> + #if($r.available("details")) $r.render("details") #end diff --git a/src/main/java/org/olat/course/assessment/ui/tool/_content/user_infos_large.html b/src/main/java/org/olat/course/assessment/ui/tool/_content/user_infos_large.html new file mode 100644 index 00000000000..6358348f651 --- /dev/null +++ b/src/main/java/org/olat/course/assessment/ui/tool/_content/user_infos_large.html @@ -0,0 +1,4 @@ +<div class="o_user_infos"> + <div class="o_user_portrait">$r.render("portrait")</div> + <div class="o_user_infos_inner">$r.render("userShortDescription")</div> +</div> \ No newline at end of file diff --git a/src/main/java/org/olat/course/assessment/ui/tool/_i18n/LocalStrings_de.properties b/src/main/java/org/olat/course/assessment/ui/tool/_i18n/LocalStrings_de.properties index 02320e5e1a0..b35ed82517a 100644 --- a/src/main/java/org/olat/course/assessment/ui/tool/_i18n/LocalStrings_de.properties +++ b/src/main/java/org/olat/course/assessment/ui/tool/_i18n/LocalStrings_de.properties @@ -16,6 +16,8 @@ assessment.status.notStart=Nicht gestartet assessment.status.inProgress=Gestartet assessment.status.inReview=Korrigieren assessment.status.done=Bewertet +assessment.tool.overview=Ubersicht +assessment.tool.numOfAssessedIdentities={0} bewertete Benutzer table.entries=Entries waiting.review=Pending reviews no.certificate=Kein Zertifikat vorhanden diff --git a/src/main/java/org/olat/course/assessment/ui/tool/event/CourseNodeEvent.java b/src/main/java/org/olat/course/assessment/ui/tool/event/CourseNodeEvent.java new file mode 100644 index 00000000000..a26ed88cec3 --- /dev/null +++ b/src/main/java/org/olat/course/assessment/ui/tool/event/CourseNodeEvent.java @@ -0,0 +1,46 @@ +/** + * <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.event; + +import org.olat.core.gui.control.Event; + +/** + * + * Initial date: 30.10.2015<br> + * @author srosse, stephane.rosse@frentix.com, http://www.frentix.com + * + */ +public class CourseNodeEvent extends Event { + + private static final long serialVersionUID = 4176476041353487088L; + + public static final String SELECT_COURSE_NODE = "sel-cou-nod"; + + private final String ident; + + public CourseNodeEvent(String cmd, String ident) { + super(cmd); + this.ident = ident; + } + + public String getIdent() { + return ident; + } +} -- GitLab