Newer
Older
/**
* <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.run;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicInteger;
import org.olat.NewControllerFactory;
import org.olat.commons.calendar.CalendarModule;
import org.olat.commons.info.ui.InfoSecurityCallback;
import org.olat.core.CoreSpringFactory;
import org.olat.core.commons.controllers.linkchooser.CustomLinkTreeModel;
import org.olat.core.commons.fullWebApp.LayoutMain3ColsController;
import org.olat.core.commons.fullWebApp.popup.BaseFullWebappPopupLayoutFactory;
import org.olat.core.commons.modules.bc.FolderRunController;
import org.olat.core.commons.modules.glossary.GlossaryMainController;
import org.olat.core.commons.persistence.PersistenceHelper;
import org.olat.core.commons.services.mark.Mark;
import org.olat.core.gui.UserRequest;
import org.olat.core.gui.Windows;
import org.olat.core.gui.components.Component;
import org.olat.core.gui.components.dropdown.Dropdown;
import org.olat.core.gui.components.dropdown.Dropdown.Spacer;
import org.olat.core.gui.components.htmlheader.jscss.CustomCSS;
import org.olat.core.gui.components.link.Link;
import org.olat.core.gui.components.link.LinkFactory;
import org.olat.core.gui.components.link.LinkPopupSettings;
import org.olat.core.gui.components.stack.BreadcrumbedStackedPanel.BreadCrumb;
import org.olat.core.gui.components.stack.PopEvent;
import org.olat.core.gui.components.stack.TooledStackedPanel.Align;
import org.olat.core.gui.components.stack.VetoPopEvent;
import org.olat.core.gui.control.ChiefController;
import org.olat.core.gui.control.Controller;
import org.olat.core.gui.control.Event;
import org.olat.core.gui.control.VetoableCloseController;
import org.olat.core.gui.control.WindowControl;
import org.olat.core.gui.control.creator.ControllerCreator;
import org.olat.core.gui.control.generic.closablewrapper.CloseableCalloutWindowController;
import org.olat.core.gui.control.generic.closablewrapper.CloseableModalController;
import org.olat.core.gui.control.generic.dtabs.Activateable2;
import org.olat.core.gui.control.generic.dtabs.DTab;
import org.olat.core.gui.control.generic.dtabs.DTabs;
import org.olat.core.gui.control.generic.messages.MessageUIFactory;
import org.olat.core.gui.control.generic.popup.PopupBrowserWindow;
import org.olat.core.id.Identity;
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.logging.OLATSecurityException;
import org.olat.core.logging.activity.ThreadLocalUserActivityLogger;
import org.olat.core.util.StringHelper;
import org.olat.core.util.coordinate.CoordinatorManager;
import org.olat.core.util.event.GenericEventListener;
import org.olat.core.util.event.MultiUserEvent;
import org.olat.core.util.mail.MailPackage;
import org.olat.core.util.mail.MailerResult;
import org.olat.core.util.prefs.Preferences;
import org.olat.core.util.resource.OresHelper;
import org.olat.core.util.tree.TreeVisitor;
import org.olat.core.util.vfs.NamedContainerImpl;
import org.olat.core.util.vfs.VFSContainer;
import org.olat.course.CourseFactory;
import org.olat.course.CourseModule;
import org.olat.course.ICourse;
import org.olat.course.archiver.ArchiverMainController;
import org.olat.course.archiver.FullAccessArchiverCallback;
import org.olat.course.area.CourseAreasController;
import org.olat.course.assessment.AssessmentModule;

srosse
committed
import org.olat.course.assessment.ui.mode.AssessmentModeListController;
import org.olat.course.assessment.ui.mode.AssessmentModeSecurityCallback;
import org.olat.course.assessment.ui.mode.AssessmentModeSecurityCallbackFactory;
import org.olat.course.assessment.ui.tool.AssessmentToolController;
import org.olat.course.certificate.ui.CertificateAndEfficiencyStatementController;
import org.olat.course.config.CourseConfig;
import org.olat.course.config.CourseConfigEvent;
import org.olat.course.config.ui.CourseSettingsController;
import org.olat.course.db.CourseDBManager;
import org.olat.course.db.CustomDBMainController;
import org.olat.course.editor.EditorMainController;
import org.olat.course.groupsandrights.CourseGroupManager;
import org.olat.course.groupsandrights.CourseRights;
import org.olat.course.learningpath.LearningPathService;
import org.olat.course.learningpath.manager.LearningPathNodeAccessProvider;
import org.olat.course.learningpath.ui.LearningPathIdentityListController;
import org.olat.course.learningpath.ui.MyLearningPathController;
import org.olat.course.member.MembersManagementMainController;
import org.olat.course.nodeaccess.ui.UnsupportedCourseNodesController;
import org.olat.course.nodes.CourseNode;
import org.olat.course.nodes.ENCourseNode;
import org.olat.course.nodes.bc.CourseDocumentsController;
import org.olat.course.nodes.co.COToolController;
import org.olat.course.nodes.feed.blog.BlogToolController;
import org.olat.course.nodes.fo.FOToolController;
import org.olat.course.nodes.info.InfoCourseSecurityCallback;
import org.olat.course.nodes.info.InfoRunController;
import org.olat.course.nodes.members.MembersToolRunController;
import org.olat.course.nodes.wiki._content.WikiToolController;
import org.olat.course.reminder.ui.CourseRemindersController;
import org.olat.course.run.calendar.CourseCalendarController;
import org.olat.course.run.glossary.CourseGlossaryFactory;
import org.olat.course.run.glossary.CourseGlossaryToolLinkController;
import org.olat.course.run.userview.UserCourseEnvironment;
import org.olat.course.run.userview.UserCourseEnvironmentImpl;
import org.olat.course.statistic.StatisticCourseNodesController;
import org.olat.course.statistic.StatisticMainController;
import org.olat.course.statistic.StatisticType;
import org.olat.course.tree.CourseInternalLinkTreeModel;
import org.olat.group.BusinessGroup;
import org.olat.group.BusinessGroupRef;
import org.olat.group.BusinessGroupService;
import org.olat.group.ui.edit.BusinessGroupModifiedEvent;
import org.olat.instantMessaging.InstantMessagingModule;
import org.olat.instantMessaging.InstantMessagingService;
import org.olat.instantMessaging.OpenInstantMessageEvent;
import org.olat.modules.assessment.ui.AssessmentToolSecurityCallback;
import org.olat.modules.lecture.LectureModule;
import org.olat.modules.lecture.LectureService;
import org.olat.modules.lecture.RepositoryEntryLectureConfiguration;
import org.olat.modules.lecture.ui.LectureRepositoryAdminController;
import org.olat.modules.lecture.ui.LecturesSecurityCallback;
import org.olat.modules.lecture.ui.LecturesSecurityCallbackFactory;
import org.olat.modules.lecture.ui.TeacherOverviewController;
import org.olat.modules.reminder.ReminderModule;
import org.olat.note.NoteController;
import org.olat.repository.LeavingStatusList;
import org.olat.repository.RepositoryEntry;
import org.olat.repository.RepositoryEntryManagedFlag;
import org.olat.repository.RepositoryEntrySecurity;
import org.olat.repository.RepositoryEntryStatusEnum;
import org.olat.repository.RepositoryManager;
import org.olat.repository.controllers.EntryChangedEvent;
import org.olat.repository.ui.RepositoryEntryLifeCycleChangeController;
import org.olat.repository.ui.RepositoryEntryRuntimeController;
import org.olat.resource.OLATResource;
import org.olat.search.SearchModule;
import org.olat.search.SearchServiceUIFactory;
import org.olat.search.SearchServiceUIFactory.DisplayOption;
import org.olat.search.service.QuickSearchEvent;
import org.olat.search.ui.SearchInputController;
import org.olat.util.logging.activity.LoggingResourceable;
import org.springframework.beans.factory.annotation.Autowired;
/**
*
* Initial date: 20.08.2014<br>
* @author srosse, stephane.rosse@frentix.com, http://www.frentix.com
*
*/
public class CourseRuntimeController extends RepositoryEntryRuntimeController implements GenericEventListener, VetoableCloseController {
private static final String JOINED = "joined";
private static final String LEFT = "left";
private static final String CMD_START_GROUP_PREFIX = "cmd.group.start.ident.";
private Delayed delayedClose;
//tools
private Link folderLink,
assessmentLink, archiverLink,
courseStatisticLink, surveyStatisticLink, testStatisticLink,
areaLink, dbLink, convertLearningPathLink,
lecturesAdminLink, reminderLink,
assessmentModeLink, lifeCycleChangeLink,
efficiencyStatementsLink, noteLink, leaveLink,
// course tools
learningPathLink, learningPathsLink, calendarLink, chatLink, participantListLink, participantInfoLink,
blogLink, wikiLink, forumLink, documentsLink, emailLink, searchLink,
openGlossaryLink, enableGlossaryLink, lecturesLink;
private Link currentUserCountLink;
private Dropdown myCourse, glossary;
private CloseableModalController cmc;
private CourseDocumentsController documentsCtrl;
private CourseAreasController areasCtrl;
private ConfirmLeaveController leaveDialogBox;
private ArchiverMainController archiverCtrl;
private CustomDBMainController databasesCtrl;
private FolderRunController courseFolderCtrl;
private InfoRunController participatInfoCtrl;
private SearchInputController searchController;
private StatisticMainController statisticsCtrl;
private CourseRemindersController remindersCtrl;
private TeacherOverviewController lecturesCtrl;
private AssessmentToolController assessmentToolCtr;
private MembersToolRunController participatListCtrl;
private MembersManagementMainController membersCtrl;
private StatisticCourseNodesController statsToolCtr;
private AssessmentModeListController assessmentModeCtrl;
private LectureRepositoryAdminController lecturesAdminCtrl;
private UnsupportedCourseNodesController unsupportedCourseNodesCtrl;
private CloseableCalloutWindowController courseSearchCalloutCtr;
protected RepositoryEntryLifeCycleChangeController lifeCycleChangeCtr;
private Map<String, Boolean> courseRightsCache;
@Autowired
private CourseModule courseModule;
private LectureModule lectureModule;
@Autowired
private LectureService lectureService;
@Autowired
private ReminderModule reminderModule;
@Autowired
private CalendarModule calendarModule;
@Autowired
private CoordinatorManager coordinatorManager;
@Autowired
private BusinessGroupService businessGroupService;
@Autowired
private AssessmentModule assessmentModule;
private InstantMessagingModule imModule;
@Autowired
@Autowired
private SearchModule searchModule;
@Autowired
private LearningPathService learningPathService;
public CourseRuntimeController(UserRequest ureq, WindowControl wControl,
RepositoryEntry re, RepositoryEntrySecurity reSecurity, RuntimeControllerCreator runtimeControllerCreator,
boolean offerBookmark, boolean showCourseConfigLink) {
super(ureq, wControl, re, reSecurity, runtimeControllerCreator, offerBookmark, showCourseConfigLink);
if(!corrupted) {
ICourse course = CourseFactory.loadCourse(getRepositoryEntry());
addLoggingResourceable(LoggingResourceable.wrap(course));
coordinatorManager.getCoordinator().getEventBus().registerFor(this, getIdentity(), getOlatResourceable());
// - group modification events
coordinatorManager.getCoordinator().getEventBus().registerFor(this, getIdentity(), getRepositoryEntry());
if (courseModule.displayParticipantsCount()) {
coordinatorManager.getCoordinator().getEventBus().fireEventToListenersOf(new MultiUserEvent(JOINED), getOlatResourceable());
updateCurrentUserCount();
}
if(enableGlossaryLink != null) {
Preferences prefs = ureq.getUserSession().getGuiPreferences();
String guiPrefsKey = CourseGlossaryFactory.createGuiPrefsKey(course);
Boolean state = (Boolean) prefs.get(CourseGlossaryToolLinkController.class, guiPrefsKey);
setGlossaryLinkTitle(ureq, state);
}
}
}
@Override
protected boolean isCorrupted(RepositoryEntry entry) {
try {
CourseFactory.loadCourse(entry);
return false;
} catch (Exception e) {
return true;
}
}
@Override
protected void onSecurityReloaded(UserRequest ureq) {
if(corrupted) return;
loadRights();
RunMainController runMainController = getRunMainController();
if(runMainController != null) {
runMainController.reloadGroupMemberships(reSecurity);
runMainController.updateCurrentCourseNode(ureq);
}
}
private void loadRights() {
ICourse course = CourseFactory.loadCourse(getRepositoryEntry());
CourseGroupManager cgm = course.getCourseEnvironment().getCourseGroupManager();
// 3) all other rights are defined in the groupmanagement using the learning
// group rights
UserCourseEnvironmentImpl uce = getUserCourseEnvironment();
if(uce != null) {
uce.setUserRoles(reSecurity.isEntryAdmin() || reSecurity.isPrincipal() || reSecurity.isMasterCoach(), reSecurity.isCoach(), reSecurity.isParticipant());
if(reSecurity.isOnlyPrincipal() || reSecurity.isOnlyMasterCoach()) {
uce.setCourseReadOnly(Boolean.TRUE);
} else if(reSecurity.isReadOnly()) {
if(overrideReadOnly) {
uce.setCourseReadOnly(Boolean.FALSE);
} else {
uce.setCourseReadOnly(Boolean.TRUE);
}
} else {
uce.setCourseReadOnly(Boolean.FALSE);
}
uce.getScoreAccounting().evaluateAll(true);
courseRightsCache = new HashMap<>();
if(!reSecurity.isEntryAdmin() && !isGuestOnly) {
List<String> rights = cgm.getRights(getIdentity());
courseRightsCache.put(CourseRights.RIGHT_GROUPMANAGEMENT, Boolean.valueOf(rights.contains(CourseRights.RIGHT_GROUPMANAGEMENT)));
courseRightsCache.put(CourseRights.RIGHT_MEMBERMANAGEMENT, Boolean.valueOf(rights.contains(CourseRights.RIGHT_MEMBERMANAGEMENT)));
courseRightsCache.put(CourseRights.RIGHT_COURSEEDITOR, Boolean.valueOf(rights.contains(CourseRights.RIGHT_COURSEEDITOR)));
courseRightsCache.put(CourseRights.RIGHT_ARCHIVING, Boolean.valueOf(rights.contains(CourseRights.RIGHT_ARCHIVING)));
courseRightsCache.put(CourseRights.RIGHT_ASSESSMENT, Boolean.valueOf(rights.contains(CourseRights.RIGHT_ASSESSMENT)));
courseRightsCache.put(CourseRights.RIGHT_ASSESSMENT_MODE, Boolean.valueOf(rights.contains(CourseRights.RIGHT_ASSESSMENT_MODE)));
courseRightsCache.put(CourseRights.RIGHT_GLOSSARY, Boolean.valueOf(rights.contains(CourseRights.RIGHT_GLOSSARY)));
courseRightsCache.put(CourseRights.RIGHT_STATISTICS, Boolean.valueOf(rights.contains(CourseRights.RIGHT_STATISTICS)));
courseRightsCache.put(CourseRights.RIGHT_DB, Boolean.valueOf(rights.contains(CourseRights.RIGHT_DB)));
}
private boolean hasCourseRight(String right) {
Boolean bool = courseRightsCache.get(right);
return bool != null && bool.booleanValue();
}
private UserCourseEnvironmentImpl getUserCourseEnvironment() {
RunMainController run = getRunMainController();
UserCourseEnvironmentImpl uce = run == null ? null : run.getUce();
if(uce != null && uce.isCourseReadOnly() && overrideReadOnly) {
uce.setCourseReadOnly(Boolean.FALSE);
}
return uce;
/**
* Refresh the cached repository entry of the course
* @return
*/
@Override
protected RepositoryEntry loadRepositoryEntry() {
RepositoryEntry refreshedEntry = super.loadRepositoryEntry();
ICourse course = CourseFactory.loadCourse(getRepositoryEntry());
course.getCourseEnvironment().updateCourseEntry(refreshedEntry);
return refreshedEntry;
}
/**
* Refresh the cached repository entry of the course
* @return
*/
@Override
protected RepositoryEntry refreshRepositoryEntry(RepositoryEntry refreshedEntry) {
ICourse course = CourseFactory.loadCourse(refreshedEntry);
course.getCourseEnvironment().updateCourseEntry(refreshedEntry);
return super.refreshRepositoryEntry(refreshedEntry);
}
private RunMainController getRunMainController() {
return getRuntimeController() instanceof RunMainController ?
(RunMainController)getRuntimeController() : null;
}
private CourseNode getCurrentCourseNode() {
RunMainController run = getRunMainController();
return run == null ? null : run.getCurrentCourseNode();
}
private boolean isInEditor() {
RunMainController run = getRunMainController();
return run != null && run.isInEditor();
}
private void setIsInEditor(boolean editor) {
RunMainController run = getRunMainController();
if(run != null) run.setInEditor(editor);
}
private void reloadGroupMemberships() {
RunMainController run = getRunMainController();
if(run != null) {
run.reloadGroupMemberships(reSecurity);
}
}
private void toolControllerDone(UserRequest ureq) {
RunMainController run = getRunMainController();
if(run != null) {
addCustomCSS(ureq);
run.toolCtrDone(ureq, reSecurity);

srosse
committed
currentToolCtr = null;
}
}
private void setTextMarkingEnabled(boolean enable) {
RunMainController run = getRunMainController();
if(run != null) run.setTextMarkingEnabled(enable);
}
public void setCourseCloseEnabled(boolean enabled) {
toolbarPanel.setShowCloseLink(true, enabled);
}
public void setToolControllerEnabled(boolean enabled) {
toolbarPanel.setToolbarEnabled(enabled);
}
private void addCustomCSS(UserRequest ureq) {
ICourse course = CourseFactory.loadCourse(getRepositoryEntry());
CustomCSS customCSS = CourseFactory.getCustomCourseCss(ureq.getUserSession(), course.getCourseEnvironment());
ChiefController cc = getWindowControl().getWindowBackOffice().getChiefController();
if (cc != null) {
if(customCSS == null) {
cc.removeCurrentCustomCSSFromView();
} else {
cc.addCurrentCustomCSSToView(customCSS);
}
}
setCustomCSS(customCSS);
}
private void removeCustomCSS() {
ChiefController cc = getWindowControl().getWindowBackOffice().getChiefController();
if (cc != null) {
cc.removeCurrentCustomCSSFromView();
}
setCustomCSS(null);
protected void initToolbar(Dropdown toolsDropdown) {
toolsDropdown.removeAllComponents();
if(corrupted) return;
ICourse course = CourseFactory.loadCourse(getRepositoryEntry());
if(!course.getCourseConfig().isToolbarEnabled() && !reSecurity.isEntryAdmin() && !reSecurity.isCoach()
&& !hasCourseRight(CourseRights.RIGHT_COURSEEDITOR) && !hasCourseRight(CourseRights.RIGHT_MEMBERMANAGEMENT)
&& !hasCourseRight(CourseRights.RIGHT_GROUPMANAGEMENT) && !hasCourseRight(CourseRights.RIGHT_ARCHIVING)
&& !hasCourseRight(CourseRights.RIGHT_STATISTICS) && !hasCourseRight(CourseRights.RIGHT_DB)
&& !hasCourseRight(CourseRights.RIGHT_ASSESSMENT) && !hasCourseRight(CourseRights.RIGHT_ASSESSMENT_MODE)) {
toolbarPanel.setToolbarEnabled(false);
} else {
toolbarPanel.setToolbarEnabled(true);
}
// make bread crumb disappear if not enabled
if (!course.getCourseConfig().isBreadCrumbEnabled() && !toolbarPanel.isToolbarEnabled()) {
// disable if toolbar also not visible
toolbarPanel.setBreadcrumbEnabled(false);
initToolsMenu(toolsDropdown);
initToolsMyCourse(course);
initGeneralTools(course);
RunMainController rmc = getRunMainController();
if(rmc != null) {
rmc.initToolbarAndProgressbar();
}
private void setCourseClosedMessage() {
UserCourseEnvironment userCourseEnv = getUserCourseEnvironment();
if(userCourseEnv != null && getRepositoryEntry().getEntryStatus() == RepositoryEntryStatusEnum.closed) {
toolbarPanel.setMessage(translate("course.closed"));
toolbarPanel.setMessageCssClass("o_warning");
} else {
toolbarPanel.setMessage(null);
toolbarPanel.setMessageComponent(null);
}
protected void initToolsMenu(Dropdown toolsDropdown) {
toolsDropdown.removeAllComponents();
toolsDropdown.setDirty(true);
if(!isAssessmentLock()) {
ICourse course = CourseFactory.loadCourse(getRepositoryEntry());
UserCourseEnvironmentImpl uce = getUserCourseEnvironment();
initToolsMenuSettings(toolsDropdown);
initToolsMenuEditor(toolsDropdown, uce);
initToolsMenuRuntime(toolsDropdown, uce);
initToolsMenuStatistics(toolsDropdown, course, uce);
initToolsMenuEdition(toolsDropdown);
initToolsMenuDelete(toolsDropdown);
}
}
@Override
protected void initToolsMenuSettings(Dropdown tools) {
// 1) administrative tools
if (reSecurity.isEntryAdmin() || reSecurity.isPrincipal() || reSecurity.isMasterCoach() || reSecurity.isCoach()
|| hasCourseRight(CourseRights.RIGHT_COURSEEDITOR) || hasCourseRight(CourseRights.RIGHT_MEMBERMANAGEMENT)
|| hasCourseRight(CourseRights.RIGHT_GROUPMANAGEMENT)) {
tools.setI18nKey("header.tools");
tools.setElementCssClass("o_sel_course_tools");
if(reSecurity.isEntryAdmin() || hasCourseRight(CourseRights.RIGHT_COURSEEDITOR)) {
settingsLink = LinkFactory.createToolLink("settings", translate("details.settings"), this, "o_sel_repo_settings");
settingsLink.setIconLeftCSS("o_icon o_icon-fw o_icon_settings");
settingsLink.setElementCssClass("o_sel_course_settings");
settingsLink.setUrl(BusinessControlFactory.getInstance()
.getAuthenticatedURLFromBusinessPathStrings(businessPathEntry, "[Settings:0]"));
tools.addComponent(settingsLink);
if (reSecurity.isEntryAdmin() || reSecurity.isPrincipal() || reSecurity.isMasterCoach() || hasCourseRight(CourseRights.RIGHT_GROUPMANAGEMENT) || hasCourseRight(CourseRights.RIGHT_MEMBERMANAGEMENT)) {
membersLink = LinkFactory.createToolLink("unifiedusermngt", translate("command.opensimplegroupmngt"), this, "o_icon_membersmanagement");
membersLink.setUrl(BusinessControlFactory.getInstance()
.getAuthenticatedURLFromBusinessPathStrings(businessPathEntry, "[MembersMgmt:0][Members:0][All:0]"));

srosse
committed
membersLink.setElementCssClass("o_sel_course_members");
tools.addComponent(membersLink);
}
tools.addComponent(new Spacer("first"));
}
}
private void initToolsMenuEditor(Dropdown tools, final UserCourseEnvironmentImpl uce) {
if(uce == null) return;
if (reSecurity.isEntryAdmin() || hasCourseRight(CourseRights.RIGHT_COURSEEDITOR)) {
boolean managed = RepositoryEntryManagedFlag.isManaged(getRepositoryEntry(), RepositoryEntryManagedFlag.editcontent);
boolean readOnly = uce.isCourseReadOnly();
editLink = LinkFactory.createToolLink("edit.cmd", translate("command.openeditor"), this, "o_icon_courseeditor");
editLink.setUrl(BusinessControlFactory.getInstance()
.getAuthenticatedURLFromBusinessPathStrings(businessPathEntry, "[Editor:0]]"));
editLink.setElementCssClass("o_sel_course_editor");
editLink.setEnabled(!corrupted && !managed);
editLink.setVisible(!readOnly);
tools.addComponent(editLink);
}
if (reSecurity.isEntryAdmin() || reSecurity.isPrincipal() || reSecurity.isMasterCoach() || hasCourseRight(CourseRights.RIGHT_COURSEEDITOR)) {
folderLink = LinkFactory.createToolLink("cfd", translate("command.coursefolder"), this, "o_icon_coursefolder");
folderLink.setUrl(BusinessControlFactory.getInstance()
.getAuthenticatedURLFromBusinessPathStrings(businessPathEntry, "[Coursefolder:0]]"));
folderLink.setElementCssClass("o_sel_course_folder");
tools.addComponent(folderLink);
tools.addComponent(new Spacer(""));
}
}
private void initToolsMenuRuntime(Dropdown tools, final UserCourseEnvironmentImpl uce) {
boolean courseAuthorRight = reSecurity.isEntryAdmin() || hasCourseRight(CourseRights.RIGHT_COURSEEDITOR);
if (courseAuthorRight || reSecurity.isPrincipal() || reSecurity.isMasterCoach() || reSecurity.isCoach()
|| hasCourseRight(CourseRights.RIGHT_DB)
|| hasCourseRight(CourseRights.RIGHT_ASSESSMENT) || hasCourseRight(CourseRights.RIGHT_ASSESSMENT_MODE)) {
tools.addComponent(new Spacer(""));
if (reSecurity.isEntryAdmin() || reSecurity.isPrincipal() || reSecurity.isMasterCoach() || reSecurity.isCoach() || hasCourseRight(CourseRights.RIGHT_ASSESSMENT)) {
assessmentLink = LinkFactory.createToolLink("assessment", translate("command.openassessment"), this, "o_icon_assessment_tool");
assessmentLink.setUrl(BusinessControlFactory.getInstance()
.getAuthenticatedURLFromBusinessPathStrings(businessPathEntry, "[assessmentToolv2:0]"));
assessmentLink.setElementCssClass("o_sel_course_assessment_tool");
tools.addComponent(assessmentLink);
if(lectureModule.isEnabled() && (courseAuthorRight || reSecurity.isPrincipal() || reSecurity.isMasterCoach()) && isLectureEnabled()) {
lecturesAdminLink = LinkFactory.createToolLink("lectures.admin.cmd", translate("command.options.lectures.admin"), this, "o_icon_lecture");
lecturesAdminLink.setUrl(BusinessControlFactory.getInstance()
.getAuthenticatedURLFromBusinessPathStrings(businessPathEntry, "[LecturesAdmin:0][LectureBlocks:0]"));
lecturesAdminLink.setElementCssClass("o_sel_course_lectures_admin");
tools.addComponent(lecturesAdminLink);
}
if(reminderModule.isEnabled() && courseAuthorRight) {
reminderLink = LinkFactory.createToolLink("reminders.cmd", translate("command.options.reminders"), this, "o_icon_reminder");
reminderLink.setUrl(BusinessControlFactory.getInstance()
.getAuthenticatedURLFromBusinessPathStrings(businessPathEntry, "[Reminders:0]"));
reminderLink.setElementCssClass("o_sel_course_reminders");
reminderLink.setVisible(!uce.isCourseReadOnly());
tools.addComponent(reminderLink);
if (courseAuthorRight || reSecurity.isPrincipal() || reSecurity.isMasterCoach() || hasCourseRight(CourseRights.RIGHT_ASSESSMENT_MODE)) {
//course author right or the assessment mode access right
boolean managed = RepositoryEntryManagedFlag.isManaged(getRepositoryEntry(), RepositoryEntryManagedFlag.editcontent);
assessmentModeLink = LinkFactory.createToolLink("assessment.mode.cmd", translate("command.assessment.mode"), this, "o_icon_assessment_mode");
assessmentModeLink.setUrl(BusinessControlFactory.getInstance()
.getAuthenticatedURLFromBusinessPathStrings(businessPathEntry, "[AssessmentMode:0]"));
assessmentModeLink.setElementCssClass("o_sel_course_assessment_mode");
assessmentModeLink.setEnabled(!managed);
assessmentModeLink.setVisible(assessmentModule.isAssessmentModeEnabled() && !uce.isCourseReadOnly());
tools.addComponent(assessmentModeLink);
}
if (reSecurity.isEntryAdmin() || hasCourseRight(CourseRights.RIGHT_COURSEEDITOR)) {
areaLink = LinkFactory.createToolLink("careas", translate("command.courseareas"), this, "o_icon_courseareas");
areaLink.setUrl(BusinessControlFactory.getInstance()
.getAuthenticatedURLFromBusinessPathStrings(businessPathEntry, "[CourseAreas:0]"));
areaLink.setElementCssClass("o_sel_course_areas");
tools.addComponent(areaLink);
}
if (courseDBManager.isEnabled() && (reSecurity.isEntryAdmin() || hasCourseRight(CourseRights.RIGHT_DB))) {
dbLink = LinkFactory.createToolLink("customDb",translate("command.opendb"), this, "o_icon_coursedb");
tools.addComponent(dbLink);
}
}
}
private boolean isLectureEnabled() {
RepositoryEntryLectureConfiguration lectureConfig = lectureService.getRepositoryEntryLectureConfiguration(getRepositoryEntry());
return lectureConfig != null && lectureConfig.isLectureEnabled();
}
private void initToolsMenuStatistics(Dropdown tools, ICourse course, final UserCourseEnvironmentImpl uce) {
if (reSecurity.isEntryAdmin() || reSecurity.isPrincipal() || reSecurity.isMasterCoach() || reSecurity.isCoach()
|| hasCourseRight(CourseRights.RIGHT_ARCHIVING) || hasCourseRight(CourseRights.RIGHT_STATISTICS)) {
tools.addComponent(new Spacer(""));
if (reSecurity.isEntryAdmin() || reSecurity.isPrincipal() || reSecurity.isMasterCoach() || hasCourseRight(CourseRights.RIGHT_STATISTICS)) {
courseStatisticLink = LinkFactory.createToolLink("statistic",translate("command.openstatistic"), this, "o_icon_statistics_tool");
courseStatisticLink.setUrl(BusinessControlFactory.getInstance()
.getAuthenticatedURLFromBusinessPathStrings(businessPathEntry, "[CourseStatistics:0]"));
tools.addComponent(courseStatisticLink);
}
if (uce != null && (reSecurity.isEntryAdmin() || reSecurity.isPrincipal() || reSecurity.isMasterCoach() || reSecurity.isCoach() || hasCourseRight(CourseRights.RIGHT_STATISTICS))) {
final AtomicInteger testNodes = new AtomicInteger();
final AtomicInteger surveyNodes = new AtomicInteger();
new TreeVisitor(node -> {
if(((CourseNode)node).isStatisticNodeResultAvailable(uce, StatisticType.TEST)) {
testNodes.incrementAndGet();
} else if(((CourseNode)node).isStatisticNodeResultAvailable(uce, StatisticType.SURVEY)) {
surveyNodes.incrementAndGet();
}
}, course.getRunStructure().getRootNode(), true).visitAll();
if(testNodes.intValue() > 0) {
testStatisticLink = LinkFactory.createToolLink("qtistatistic", translate("command.openteststatistic"), this, "o_icon_statistics_tool");
testStatisticLink.setUrl(BusinessControlFactory.getInstance()
.getAuthenticatedURLFromBusinessPathStrings(businessPathEntry, "[TestStatistics:0]"));
tools.addComponent(testStatisticLink);
}
if(surveyNodes.intValue() > 0) {
surveyStatisticLink = LinkFactory.createToolLink("qtistatistic", translate("command.opensurveystatistic"), this, "o_icon_statistics_tool");
surveyStatisticLink.setUrl(BusinessControlFactory.getInstance()
.getAuthenticatedURLFromBusinessPathStrings(businessPathEntry, "[SurveyStatistics:0]"));
tools.addComponent(surveyStatisticLink);
}
}
if (reSecurity.isEntryAdmin() || hasCourseRight(CourseRights.RIGHT_ARCHIVING)) {
archiverLink = LinkFactory.createToolLink("archiver", translate("command.openarchiver"), this, "o_icon_archive_tool");
archiverLink.setUrl(BusinessControlFactory.getInstance()
.getAuthenticatedURLFromBusinessPathStrings(businessPathEntry, "[Archives:0]"));
tools.addComponent(archiverLink);
}
ordersLink = LinkFactory.createToolLink("bookings", translate("details.orders"), this, "o_sel_repo_booking");
ordersLink.setIconLeftCSS("o_icon o_icon-fw o_icon_booking");
ordersLink.setElementCssClass("o_sel_course_ac_tool");
boolean booking = acService.isResourceAccessControled(getRepositoryEntry().getOlatResource(), null);
ordersLink.setVisible(!corrupted && booking);
tools.addComponent(ordersLink);
}
}
@Override
protected void initToolsMenuEdition(Dropdown toolsDropdown) {
super.initToolsMenuEdition(toolsDropdown);
if (copyLink != null) {
ICourse course = CourseFactory.loadCourse(getRepositoryEntry());
if (course != null && !LearningPathNodeAccessProvider.TYPE.equals(course.getCourseConfig().getNodeAccessType().getType())) {
Integer index = toolsDropdown.getComponentIndex(copyLink);
if(index != null) {
convertLearningPathLink = LinkFactory.createToolLink("convert.course.learning.path",
translate("tools.convert.course.learning.path"), this, "o_icon o_icon-fw o_icon_learning_path");
toolsDropdown.addComponent(index.intValue() + 1, convertLearningPathLink);
}
}
}
}
@Override
protected void initToolsMenuDelete(Dropdown settingsDropdown) {
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
RepositoryEntry re = getRepositoryEntry();
boolean closeManged = RepositoryEntryManagedFlag.isManaged(re, RepositoryEntryManagedFlag.close);
if(reSecurity.isEntryAdmin()) {
boolean deleteManaged = RepositoryEntryManagedFlag.isManaged(re, RepositoryEntryManagedFlag.delete);
if(settingsDropdown.size() > 0 && !deleteManaged) {
settingsDropdown.addComponent(new Spacer("close-delete"));
}
if(!closeManged || !deleteManaged) {
// If a resource is closable (currently only course) and
// deletable (currently all resources) we offer those two
// actions in a separate page, unless both are managed
// operations. In that case we don't show anything at all.
// If only one of the two actions are managed, we go to the
// separate page as well and show only the relevant action
// there.
lifeCycleChangeLink = LinkFactory.createToolLink("lifeCycleChange", translate("details.lifecycle.change"), this, "o_icon o_icon-fw o_icon_lifecycle");
settingsDropdown.addComponent(lifeCycleChangeLink);
} else {
if(!deleteManaged) {
String type = translate(handler.getSupportedType());
String deleteTitle = translate("details.delete.alt", new String[]{ type });
deleteLink = LinkFactory.createToolLink("delete", deleteTitle, this, "o_icon o_icon-fw o_icon_delete_item");
deleteLink.setElementCssClass("o_sel_repo_close");
settingsDropdown.addComponent(deleteLink);
}
}
}
}
private void initToolsMyCourse(ICourse course) {
boolean assessmentLock = isAssessmentLock();
UserCourseEnvironment userCourseEnv = getUserCourseEnvironment();
myCourse = new Dropdown("myCourse", "header.tools.mycourse", false, getTranslator());
myCourse.setElementCssClass("dropdown-menu-right");
myCourse.setIconCSS("o_icon o_icon_user");
// Personal tools on right side
CourseConfig cc = course.getCourseConfig();
if ((cc.isEfficencyStatementEnabled() || cc.isCertificateEnabled()) && !isGuestOnly && !assessmentLock
&& userCourseEnv != null && userCourseEnv.isParticipant()) {
efficiencyStatementsLink = LinkFactory.createToolLink("efficiencystatement",
translate("command.efficiencystatement"), this, "o_icon_certificate");
myCourse.addComponent(efficiencyStatementsLink);
if (!isGuestOnly && !assessmentLock) {
noteLink = LinkFactory.createToolLink("personalnote",translate("command.personalnote"), this, "o_icon_notes");
noteLink.setPopup(new LinkPopupSettings(750, 550, "notes"));
myCourse.addComponent(noteLink);
}
if (allowBookmark && !isGuestOnly) {
boolean marked = markManager.isMarked(getRepositoryEntry(), getIdentity(), null);
String css = marked ? Mark.MARK_CSS_ICON : Mark.MARK_ADD_CSS_ICON;
bookmarkLink = LinkFactory.createToolLink("bookmark",translate("command.bookmark"), this, css);
bookmarkLink.setTitle(translate(marked ? "details.bookmark.remove" : "details.bookmark"));
myCourse.addComponent(bookmarkLink);
}
if (userCourseEnv != null) {
if(myCourse.size() > 0 && (!userCourseEnv.getCoachedGroups().isEmpty() || !userCourseEnv.getParticipatingGroups().isEmpty() || !userCourseEnv.getWaitingLists().isEmpty())) {
myCourse.addComponent(new Spacer(""));
}
// 2) add coached groups
if (!userCourseEnv.getCoachedGroups().isEmpty()) {
for (BusinessGroup group: userCourseEnv.getCoachedGroups()) {
Link link = LinkFactory.createToolLink(CMD_START_GROUP_PREFIX + group.getKey(), "group", StringHelper.escapeHtml(group.getName()), this);
link.setIconLeftCSS("o_icon o_icon-fw o_icon_group");
link.setUserObject(group);
link.setEnabled(!assessmentLock);
myCourse.addComponent(link);
}
// 3) add participating groups
if (!userCourseEnv.getParticipatingGroups().isEmpty()) {
for (BusinessGroup group: userCourseEnv.getParticipatingGroups()) {
Link link = LinkFactory.createToolLink(CMD_START_GROUP_PREFIX + group.getKey(), "group", StringHelper.escapeHtml(group.getName()), this);
link.setIconLeftCSS("o_icon o_icon-fw o_icon_group");
link.setUserObject(group);
link.setEnabled(!assessmentLock);
myCourse.addComponent(link);
}
// 5) add waiting-list groups
if (!userCourseEnv.getWaitingLists().isEmpty()) {
for (BusinessGroup group: userCourseEnv.getWaitingLists()) {
int pos = businessGroupService.getPositionInWaitingListFor(getIdentity(), group);
String name = StringHelper.escapeHtml(group.getName()) + " (" + pos + ")";
Link link = LinkFactory.createToolLink(CMD_START_GROUP_PREFIX + group.getKey(), "group", name, this);
link.setIconLeftCSS("o_icon o_icon-fw o_icon_group");
link.setUserObject(group);
link.setEnabled(false);
myCourse.addComponent(link);
}
}
if(repositoryService.isParticipantAllowedToLeave(getRepositoryEntry())
&& !assessmentLock && !roles.isGuestOnly() && !userCourseEnv.isCourseReadOnly()
&& isAllowedToLeave(userCourseEnv)) {
leaveLink = LinkFactory.createToolLink("sign.out", "leave", translate("sign.out"), this);
leaveLink.setIconLeftCSS("o_icon o_icon-fw o_icon_sign_out");
myCourse.addComponent(new Spacer("leaving-space"));
myCourse.addComponent(leaveLink);
}
if(myCourse.size() > 0) {
toolbarPanel.addTool(myCourse, Align.right);
}
}
private boolean isAllowedToLeave(UserCourseEnvironment userCourseEnv) {
if(!userCourseEnv.getParticipatingGroups().isEmpty()) {
CourseNode rootNode = userCourseEnv.getCourseEnvironment().getRunStructure().getRootNode();
OLATResource courseResource = userCourseEnv.getCourseEnvironment().getCourseGroupManager().getCourseResource();
AtomicBoolean bool = new AtomicBoolean(false);
new TreeVisitor(node -> {
if(!bool.get() && node instanceof ENCourseNode) {
try {
ENCourseNode enNode = (ENCourseNode)node;
boolean cancelEnrollEnabled = enNode.getModuleConfiguration().getBooleanSafe(ENCourseNode.CONF_CANCEL_ENROLL_ENABLED);
if(!cancelEnrollEnabled && enNode.isUsedForEnrollment(userCourseEnv.getParticipatingGroups(), courseResource)) {
}
} catch (Exception e) {
logError("", e);
}
}
}, rootNode, true).visitAll();
if(bool.get()) {
return false;// is in a enrollment group
}
}
return (userCourseEnv.isParticipant() || !userCourseEnv.getParticipatingGroups().isEmpty());
}
private void initGeneralTools(ICourse course) {
boolean assessmentLock = isAssessmentLock();
UserCourseEnvironment userCourseEnv = getUserCourseEnvironment();
CourseConfig cc = course.getCourseConfig();
if (!assessmentLock && showDetails) {
detailsLink = LinkFactory.createToolLink("courseconfig",translate("command.courseconfig"), this, "o_icon_details");
detailsLink.setUrl(BusinessControlFactory.getInstance()
.getAuthenticatedURLFromBusinessPathStrings(businessPathEntry, "[Infos:0]"));
toolbarPanel.addTool(detailsLink);
}
if (!assessmentLock && !isGuestOnly
&& LearningPathNodeAccessProvider.TYPE.equals(cc.getNodeAccessType().getType())) {
learningPathLink = LinkFactory.createToolLink("learningPath", translate("command.learning.path") + "-LP", this, "o_icon_learning_path");
learningPathLink.setUrl(BusinessControlFactory.getInstance()
.getAuthenticatedURLFromBusinessPathStrings(businessPathEntry, "[LearningPath:0]"));
toolbarPanel.addTool(learningPathLink);
if (learningPathLink != null) {
learningPathLink.setVisible(userCourseEnv != null && userCourseEnv.isParticipant());
}
if (!assessmentLock && !isGuestOnly
&& LearningPathNodeAccessProvider.TYPE.equals(cc.getNodeAccessType().getType())) {
learningPathsLink = LinkFactory.createToolLink("learningPaths", translate("command.learning.paths"), this, "o_icon_learning_path");
learningPathsLink.setUrl(BusinessControlFactory.getInstance()
.getAuthenticatedURLFromBusinessPathStrings(businessPathEntry, "[LearningPaths:0]"));
toolbarPanel.addTool(learningPathsLink);
}
if (learningPathsLink != null) {
learningPathsLink.setVisible(userCourseEnv != null && (userCourseEnv.isCoach() || userCourseEnv.isAdmin()));
boolean calendarIsEnabled = !assessmentLock && !isGuestOnly && calendarModule.isEnabled()
&& calendarModule.isEnableCourseToolCalendar() && reSecurity.canLaunch();
if (calendarIsEnabled && userCourseEnv != null) {
calendarLink = LinkFactory.createToolLink("calendar",translate("command.calendar"), this, "o_icon_calendar");
calendarLink.setPopup(new LinkPopupSettings(950, 750, "cal"));
calendarLink.setVisible(cc.isCalendarEnabled());
toolbarPanel.addTool(calendarLink);
}
if(!assessmentLock && isLecturesLinkEnabled()) {
lecturesLink = LinkFactory.createToolLink("command.lectures", translate("command.lectures"), this, "o_icon_lecture");
lecturesLink.setUrl(BusinessControlFactory.getInstance()
.getAuthenticatedURLFromBusinessPathStrings(businessPathEntry, "[Lectures:0]"));
toolbarPanel.addTool(lecturesLink);
}
if(!assessmentLock && !isGuestOnly && userCourseEnv != null) {
participantListLink = LinkFactory.createToolLink("participantlist", translate("command.participant.list"), this, "o_cmembers_icon");
participantListLink.setUrl(BusinessControlFactory.getInstance()
.getAuthenticatedURLFromBusinessPathStrings(businessPathEntry, "[ParticipantList:0]"));
participantListLink.setVisible(cc.isParticipantListEnabled());
toolbarPanel.addTool(participantListLink);
}
if(!assessmentLock && userCourseEnv != null) {
participantInfoLink = LinkFactory.createToolLink("participantinfo", translate("command.participant.info"), this, "o_infomsg_icon");
participantInfoLink.setUrl(BusinessControlFactory.getInstance()
.getAuthenticatedURLFromBusinessPathStrings(businessPathEntry, "[ParticipantInfos:0]"));
participantInfoLink.setVisible(cc.isParticipantInfoEnabled());
toolbarPanel.addTool(participantInfoLink);
}
if(!assessmentLock && !isGuestOnly && userCourseEnv != null && !userCourseEnv.isCourseReadOnly()) {
emailLink = LinkFactory.createToolLink("email", translate("command.email"), this, "o_co_icon");
emailLink.setUrl(BusinessControlFactory.getInstance()
.getAuthenticatedURLFromBusinessPathStrings(businessPathEntry, "[email:0]"));
emailLink.setVisible(cc.isEmailEnabled());
if(!assessmentLock && userCourseEnv != null) {
blogLink = LinkFactory.createToolLink("blog", translate("command.blog"), this, "o_blog_icon");
blogLink.setUrl(BusinessControlFactory.getInstance()
.getAuthenticatedURLFromBusinessPathStrings(businessPathEntry, "[blog:0]"));
blogLink.setVisible(cc.isBlogEnabled());
toolbarPanel.addTool(blogLink);
}
if(!assessmentLock && userCourseEnv != null) {
wikiLink = LinkFactory.createToolLink("wiki", translate("command.wiki"), this, "o_wiki_icon");
wikiLink.setUrl(BusinessControlFactory.getInstance()
.getAuthenticatedURLFromBusinessPathStrings(businessPathEntry, "[wiki:0]"));
wikiLink.setVisible(cc.isWikiEnabled());
toolbarPanel.addTool(wikiLink);
}
if(!assessmentLock && userCourseEnv != null) {
forumLink = LinkFactory.createToolLink("forum", translate("command.forum"), this, "o_fo_icon");
forumLink.setUrl(BusinessControlFactory.getInstance()
.getAuthenticatedURLFromBusinessPathStrings(businessPathEntry, "[forum:0]"));
forumLink.setVisible(cc.isForumEnabled());
toolbarPanel.addTool(forumLink);
}
if(!assessmentLock && userCourseEnv != null) {
documentsLink = LinkFactory.createToolLink("documents", translate("command.documents"), this, "o_bc_icon");
documentsLink.setUrl(BusinessControlFactory.getInstance()
.getAuthenticatedURLFromBusinessPathStrings(businessPathEntry, "[documents:0]"));
documentsLink.setVisible(cc.isDocumentsEnabled());
toolbarPanel.addTool(documentsLink);
}
if(!assessmentLock) {
glossary = new Dropdown("glossary", "command.glossary", false, getTranslator());
glossary.setIconCSS("o_icon o_FileResource-GLOSSARY_icon");
glossary.setVisible(cc.hasGlossary() && cc.isGlossaryEnabled());
openGlossaryLink = LinkFactory.createToolLink("command.glossary.open", translate("command.glossary.open"), this);
openGlossaryLink.setPopup(new LinkPopupSettings(950, 750, "gloss"));
glossary.addComponent(openGlossaryLink);
enableGlossaryLink = LinkFactory.createToolLink("command.glossary.on.off", translate("command.glossary.on.alt"), this);
glossary.addComponent(enableGlossaryLink);
toolbarPanel.addTool(glossary);
}
//add group chat to toolbox
boolean chatIsEnabled = !assessmentLock && !isGuestOnly && imModule.isEnabled()
&& imModule.isCourseEnabled() && reSecurity.canLaunch();
if(chatIsEnabled && userCourseEnv != null && !userCourseEnv.isCourseReadOnly()) {
chatLink = LinkFactory.createToolLink("chat",translate("command.coursechat"), this, "o_icon_chat");
chatLink.setVisible(imModule.isCourseEnabled() && cc.isChatEnabled());
toolbarPanel.addTool(chatLink);
}
// add course search to toolbox
boolean isSearchEnabled = !assessmentLock && searchModule.isSearchAllowed(roles);

fkiefer
committed
if (isSearchEnabled) {
searchLink = LinkFactory.createToolLink("coursesearch", translate("command.coursesearch"), this, "o_icon_search");

fkiefer
committed
searchLink.setVisible(cc.isCourseSearchEnabled());
toolbarPanel.addTool(searchLink);
}
//check the configuration enable the lectures and the user is a teacher
private boolean isLecturesLinkEnabled() {
if(lectureModule.isEnabled()) {
if(reSecurity.isEntryAdmin()) {
return lectureService.isRepositoryEntryLectureEnabled(getRepositoryEntry());
} else {
//check the configuration enable the lectures and the user is a teacher
return lectureService.hasLecturesAsTeacher(getRepositoryEntry(), getIdentity());
}
}
return false;