diff --git a/src/main/java/org/olat/basesecurity/AuthHelper.java b/src/main/java/org/olat/basesecurity/AuthHelper.java index 3aaa608f680c6dc6c7ed9ddfde0467132c4cc152..5c3d65f67efed8dfedd757cfd21f65ec21789b92 100644 --- a/src/main/java/org/olat/basesecurity/AuthHelper.java +++ b/src/main/java/org/olat/basesecurity/AuthHelper.java @@ -30,6 +30,7 @@ import java.net.UnknownHostException; import java.util.Collection; import java.util.Date; import java.util.HashMap; +import java.util.List; import java.util.Locale; import java.util.Map; @@ -37,7 +38,6 @@ import javax.servlet.http.Cookie; import javax.servlet.http.HttpSession; import org.olat.basesecurity.manager.GroupDAO; -import org.olat.commons.rss.RSSUtil; import org.olat.core.CoreSpringFactory; import org.olat.core.commons.fullWebApp.BaseFullWebappController; import org.olat.core.commons.fullWebApp.BaseFullWebappControllerParts; @@ -66,6 +66,8 @@ import org.olat.core.util.WebappHelper; import org.olat.core.util.i18n.I18nManager; import org.olat.core.util.i18n.I18nModule; import org.olat.core.util.session.UserSessionManager; +import org.olat.course.assessment.AssessmentMode; +import org.olat.course.assessment.AssessmentModeManager; import org.olat.login.AuthBFWCParts; import org.olat.login.GuestBFWCParts; import org.olat.portfolio.manager.InvitationDAO; @@ -304,15 +306,17 @@ public class AuthHelper { return LOGIN_NOTAVAILABLE; } - // set authprovider - //usess.getIdentityEnvironment().setAuthProvider(authProvider); + //need to block the all things for assessment? + AssessmentModeManager assessmentManager = CoreSpringFactory.getImpl(AssessmentModeManager.class); + List<AssessmentMode> modes = assessmentManager.getAssessmentModeFor(identity); + if(!modes.isEmpty()) { + usess.setAssessmentModes(modes); + } //set the language usess.setLocale( I18nManager.getInstance().getLocaleOrDefault(identity.getUser().getPreferences().getLanguage()) ); // update fontsize in users session globalsettings Windows.getWindows(ureq).getWindowManager().setFontSize(Integer.parseInt(identity.getUser().getPreferences().getFontsize() )); - // put users personal rss token into session - RSSUtil.putPersonalRssTokenInSession(ureq); // calculate session info and attach it to the user session setSessionInfoFor(identity, authProvider, ureq, rest); //confirm signedOn diff --git a/src/main/java/org/olat/commons/rss/RSSUtil.java b/src/main/java/org/olat/commons/rss/RSSUtil.java index e8d7b7191c21c52467b929e5f653a65d8a074dea..a12adc91839bd9423447d9c478a25155ea4acf86 100644 --- a/src/main/java/org/olat/commons/rss/RSSUtil.java +++ b/src/main/java/org/olat/commons/rss/RSSUtil.java @@ -50,62 +50,37 @@ public class RSSUtil { public static final String RSS_AUTH_TOKEN_KEY = "rsstoken"; /** path prefix for personal rss feed **/ public static final String RSS_PREFIX_PERSONAL = "/personal/"; - /** path prefix for public rss feed **/ - public static final String RSS_PREFIX_PUBLIC = "/public/"; /** OLAT server URI **/ - public static final String URI_SERVER; - /** Personal rss channel URI prefix **/ - public static final String URI_PERSONAL_CHANNEL; - /** Public rss channel URI prefix **/ - public static final String URI_PUBLIC_CHANNEL; - static { + public static final String URI_SERVER; + /** Personal rss channel URI prefix **/ + public static final String URI_PERSONAL_CHANNEL; + + static { URI_SERVER = Settings.getServerContextPathURI() + "/"; URI_PERSONAL_CHANNEL = URI_SERVER + "rss" + RSS_PREFIX_PERSONAL; - URI_PUBLIC_CHANNEL = URI_SERVER + "rss" + RSS_PREFIX_PUBLIC; - } - + } /** - * Puts the users rss token into the httpsession. If no token is available one is - * generated and peristed in the database + * Calculates the absolute URL to the users personal rss feed * @param ureq - * @return String the token + * @return String */ - public static String putPersonalRssTokenInSession(UserRequest ureq) { - Identity identity = ureq.getIdentity(); + public static String getPersonalRssLink(UserRequest ureq) { String token = null; + Identity identity = ureq.getIdentity(); BaseSecurity secManager = BaseSecurityManager.getInstance(); - Authentication auth = secManager.findAuthentication(identity, RSSUtil.RSS_AUTH_PROVIDER); + Authentication auth = secManager.findAuthentication(identity, RSS_AUTH_PROVIDER); if (auth == null) { // no token found - create one token = RandomStringUtils.randomAlphanumeric(6); - auth = secManager.createAndPersistAuthentication(identity, RSSUtil.RSS_AUTH_PROVIDER, identity.getName(), token, null); + auth = secManager.createAndPersistAuthentication(identity, RSS_AUTH_PROVIDER, identity.getName(), token, null); } else { token = auth.getCredential(); } - ureq.getUserSession().putEntry(RSSUtil.RSS_AUTH_TOKEN_KEY, token); - return token; - } - - /** - * Calculates the absolute URL to the users personal rss feed - * @param ureq - * @return String - */ - public static String getPersonalRssLink(UserRequest ureq) { - String token = (String) ureq.getUserSession().getEntry(RSSUtil.RSS_AUTH_TOKEN_KEY); - return(getPersonalRssLink(ureq.getIdentity(), token)); - } - - /** - * Calculates the absolute URL to the users personal rss feed - * @param identity - * @param token - * @return String - */ - public static String getPersonalRssLink(Identity identity, String token) { - String link = RSSUtil.URI_PERSONAL_CHANNEL + identity.getName() + "/" + token + "/" + "olat.rss"; - return link; + + StringBuilder sb = new StringBuilder(); + return sb.append(RSSUtil.URI_PERSONAL_CHANNEL).append(ureq.getIdentity().getName()) + .append("/").append(token).append("/olat.rss").toString(); } } diff --git a/src/main/java/org/olat/core/commons/contextHelp/ContextHelpLayoutControllerCreator.java b/src/main/java/org/olat/core/commons/contextHelp/ContextHelpLayoutControllerCreator.java index d737e3fe514b6a8c438175572b637c4820764dca..2552a1c6c8b5ba6e14eeaf0efbfc09cc4c5ecd25 100644 --- a/src/main/java/org/olat/core/commons/contextHelp/ContextHelpLayoutControllerCreator.java +++ b/src/main/java/org/olat/core/commons/contextHelp/ContextHelpLayoutControllerCreator.java @@ -28,6 +28,7 @@ import java.util.List; import org.olat.core.CoreSpringFactory; import org.olat.core.commons.fullWebApp.BaseFullWebappControllerParts; +import org.olat.core.commons.fullWebApp.TopNavController; import org.olat.core.commons.fullWebApp.popup.BaseFullWebappPopupLayout; import org.olat.core.gui.UserRequest; import org.olat.core.gui.control.Controller; @@ -55,29 +56,35 @@ class ContextHelpLayoutControllerCreator implements BaseFullWebappPopupLayout { /** * @see org.olat.core.commons.fullWebApp.popup.BaseFullWebappPopupLayout#getFullWebappParts() */ + @Override public BaseFullWebappControllerParts getFullWebappParts() { - return new BaseFullWebappControllerParts() { + return new BaseFullWebappControllerParts() { + + @Override public List<SiteInstance> getSiteInstances(UserRequest ureq, WindowControl control) { // no static sites return null; } - + + @Override public Controller getContentController(UserRequest ureq, WindowControl wControl) { // the content for the Pop-up Window return contentControllerCreator.createController(ureq, wControl); } - - public Controller createTopNavController(UserRequest ureq, WindowControl wControl) { - Controller topnavCtr = null; + + @Override + public TopNavController createTopNavController(UserRequest ureq, WindowControl wControl) { + TopNavController topnavCtr = null; // ----------- topnav, optional (e.g. for imprint, logout) ------------------ if (CoreSpringFactory.containsBean("fullWebApp.ContextHelpTopNavControllerCreator")) { ControllerCreator topnavControllerCreator = (ControllerCreator) CoreSpringFactory.getBean("fullWebApp.ContextHelpTopNavControllerCreator"); - topnavCtr = topnavControllerCreator.createController(ureq, wControl); + topnavCtr = (TopNavController)topnavControllerCreator.createController(ureq, wControl); } return topnavCtr; } - + + @Override public Controller createHeaderController(UserRequest ureq, WindowControl control) { Controller headerCtr = null; // ----------- header, optional (e.g. for logo, advertising ) ------------------ @@ -87,7 +94,8 @@ class ContextHelpLayoutControllerCreator implements BaseFullWebappPopupLayout { } return headerCtr; } - + + @Override public Controller createFooterController(UserRequest ureq, WindowControl control) { Controller footerCtr = null; // ----------- footer, optional (e.g. for copyright, powerd by) ------------------ diff --git a/src/main/java/org/olat/core/commons/fullWebApp/BaseFullWebappController.java b/src/main/java/org/olat/core/commons/fullWebApp/BaseFullWebappController.java index 4618c9316401fbb4546bdb7cb82f31593bf3ea38..e873996591192596753d993963cc1e94d09631ee 100644 --- a/src/main/java/org/olat/core/commons/fullWebApp/BaseFullWebappController.java +++ b/src/main/java/org/olat/core/commons/fullWebApp/BaseFullWebappController.java @@ -26,6 +26,7 @@ package org.olat.core.commons.fullWebApp; import java.util.ArrayList; +import java.util.Collections; import java.util.HashMap; import java.util.Iterator; import java.util.List; @@ -69,7 +70,6 @@ import org.olat.core.gui.control.VetoableCloseController; import org.olat.core.gui.control.WindowBackOffice; import org.olat.core.gui.control.WindowControl; import org.olat.core.gui.control.controller.BasicController; -import org.olat.core.gui.control.creator.ControllerCreator; 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.DTabImpl; @@ -81,6 +81,7 @@ import org.olat.core.gui.control.navigation.SiteInstance; import org.olat.core.gui.control.util.ZIndexWrapper; import org.olat.core.gui.control.winmgr.JSCommand; import org.olat.core.gui.themes.Theme; +import org.olat.core.gui.util.SyntheticUserRequest; import org.olat.core.helpers.Settings; import org.olat.core.id.OLATResourceable; import org.olat.core.id.context.BusinessControlFactory; @@ -95,13 +96,20 @@ import org.olat.core.logging.JavaScriptTracingController; import org.olat.core.util.CodeHelper; import org.olat.core.util.Formatter; 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.i18n.I18nManager; import org.olat.core.util.i18n.I18nModule; import org.olat.core.util.prefs.Preferences; import org.olat.core.util.resource.OresHelper; +import org.olat.course.assessment.AssessmentMode; +import org.olat.course.assessment.AssessmentModeManager; +import org.olat.course.assessment.AssessmentModeNotificationEvent; +import org.olat.course.assessment.model.TransientAssessmentMode; +import org.olat.course.assessment.ui.AssessmentModeUserConfirmationController; import org.olat.gui.control.UserToolsMenuController; import org.olat.home.HomeSite; +import org.olat.login.AfterLoginInterceptionController; /** * Description:<br> @@ -136,8 +144,10 @@ public class BaseFullWebappController extends BasicController implements ChiefCo private Panel cssHolder, guimsgHolder, currentMsgHolder; private VelocityContainer guimsgVc, stickymsgVc, mainVc, navSitesVc, navTabsVc; + private OLATResourceable lockedResource; // NEW FROM FullChiefController - private Controller topnavCtr, footerCtr; + private TopNavController topnavCtr; + private Controller footerCtr; private UserToolsMenuController userToolsMenuCtrl; private SiteInstance curSite; private DTab curDTab; @@ -152,17 +162,16 @@ public class BaseFullWebappController extends BasicController implements ChiefCo // used as link id which is load url safe (e.g. replayable private int dtabCreateCounter = 0; // the sites list - private SiteInstance userTools; private List<SiteInstance> sites; private Map<SiteInstance, BornSiteInstance> siteToBornSite = new HashMap<SiteInstance, BornSiteInstance>(); - //fxdiff BAKS-7 Resume function private Map<SiteInstance,HistoryPoint> siteToBusinessPath = new HashMap<SiteInstance,HistoryPoint>(); - // private BaseFullWebappControllerParts baseFullWebappControllerParts; protected Controller contentCtrl; - private Controller aftLHookCtr; + private AfterLoginInterceptionController aftLHookCtr; + private AssessmentModeUserConfirmationController modeCtrl; + private StackedPanel initialPanel; private DTabs myDTabsImpl; private static Integer MAX_TAB; @@ -186,12 +195,6 @@ public class BaseFullWebappController extends BasicController implements ChiefCo // define the new windowcontrol WindowControl myWControl = new BaseFullWebappWindowControl(this, wbo); overrideWindowControl(myWControl); - - /* - * BaseFullWebappController provides access to Dynamic Tabs - * on the same window and not on all Windows! - * TODO:pb discuss with HJZ multi window concept. - */ // detach DTabs implementation from the controller - DTabs may be fetched from the window and locked on (synchronized access). // if this is controller the controller is locked instead of only the DTabs part. @@ -216,19 +219,23 @@ public class BaseFullWebappController extends BasicController implements ChiefCo // ------ all the frame preparation is finished ---- initializeBase(ureq, winman, initialPanel); - - // present an overlay with configured afterlogin-controllers or nothing if none configured. - // presented only once per session. - Boolean alreadySeen = ((Boolean)ureq.getUserSession().getEntry(PRESENTED_AFTER_LOGIN_WORKFLOW)); - if (ureq.getUserSession().isAuthenticated() && alreadySeen == null) { - aftLHookCtr = ((ControllerCreator) CoreSpringFactory.getBean("fullWebApp.AfterLoginInterceptionControllerCreator")) - .createController(ureq, getWindowControl()); - listenTo(aftLHookCtr); - aftLHookCtr.getInitialComponent(); - ureq.getUserSession().putEntry(PRESENTED_AFTER_LOGIN_WORKFLOW, Boolean.TRUE); + if(ureq.getUserSession().isAuthenticated() && ureq.getUserSession().getAssessmentModes() != null && ureq.getUserSession().getAssessmentModes().size() > 0) { + modeCtrl = new AssessmentModeUserConfirmationController(ureq, getWindowControl()); + listenTo(modeCtrl); + modeCtrl.getInitialComponent(); + } else { + // present an overlay with configured afterlogin-controllers or nothing if none configured. + // presented only once per session. + Boolean alreadySeen = ((Boolean)ureq.getUserSession().getEntry(PRESENTED_AFTER_LOGIN_WORKFLOW)); + if (ureq.getUserSession().isAuthenticated() && alreadySeen == null) { + aftLHookCtr = new AfterLoginInterceptionController(ureq, getWindowControl()); + listenTo(aftLHookCtr); + aftLHookCtr.getInitialComponent(); + ureq.getUserSession().putEntry(PRESENTED_AFTER_LOGIN_WORKFLOW, Boolean.TRUE); + } } - if(aftLHookCtr == null || aftLHookCtr.isDisposed()) { + if(modeCtrl == null && (aftLHookCtr == null || aftLHookCtr.isDisposed())) { initializeDefaultSite(ureq); } @@ -244,6 +251,9 @@ public class BaseFullWebappController extends BasicController implements ChiefCo //move to a i18nModule? languageManger? languageChooserController? OLATResourceable wrappedLocale = OresHelper.createOLATResourceableType(Locale.class); ureq.getUserSession().getSingleUserEventCenter().registerFor(this, getIdentity(), wrappedLocale); + //register for assessment mode + CoordinatorManager.getInstance().getCoordinator().getEventBus() + .registerFor(this, getIdentity(), AssessmentModeNotificationEvent.ASSESSMENT_MODE_NOTIFICATION); // register for global sticky message changed events GlobalStickyMessage.registerForGlobalStickyMessage(this, ureq.getIdentity()); } @@ -475,7 +485,7 @@ public class BaseFullWebappController extends BasicController implements ChiefCo private void initializeDefaultSite(UserRequest ureq) { if (sites != null && sites.size() > 0 && curSite == null && curDTab == null - && contentCtrl == null) { + && contentCtrl == null && lockedResource == null) { SiteInstance s = sites.get(0); //activate site only if no content was set -> allow content before activation of default site. activateSite(s, ureq, null, false); @@ -636,6 +646,8 @@ public class BaseFullWebappController extends BasicController implements ChiefCo protected void event(UserRequest ureq, Controller source, Event event) { if(aftLHookCtr == source) { initializeDefaultSite(ureq); + } else if(modeCtrl == source) { + initializeDefaultSite(ureq); } else { int tabIndex = dtabsControllers.indexOf(source); if (tabIndex > -1) { @@ -710,9 +722,18 @@ public class BaseFullWebappController extends BasicController implements ChiefCo modalPanel.setContent(modalStackP); } - // FROM FULLCHIEFCONTROLLER + /** + * Activate a site if not locked + * + * @param s + * @param ureq + * @param entries + * @param forceReload + */ private void activateSite(SiteInstance s, UserRequest ureq, List<ContextEntry> entries, boolean forceReload) { + if(lockedResource != null) return; + BornSiteInstance bs = siteToBornSite.get(s); GuiStack gs; Controller resC; @@ -894,8 +915,6 @@ public class BaseFullWebappController extends BasicController implements ChiefCo // closing one dtab in _browser tab one_ and then closing the same dtab // once again in the _browser tab two_ leads to the case where dtabIndex // is -1, e.g. not found causing the redscreen described in the issue. - // TODO:2008-07-25: pb: define concept of "multi windowing" "main windowing" - // and reconsider this place. // // NOTHING TO REMOVE, return return; @@ -918,7 +937,7 @@ public class BaseFullWebappController extends BasicController implements ChiefCo navTabsVc.remove(navTabsVc.getComponent("a" + delt.hashCode())); navTabsVc.remove(navTabsVc.getComponent("ca" + delt.hashCode())); navTabsVc.remove(navTabsVc.getComponent("cp" + delt.hashCode())); - if (delt == curDTab) { // if we close the current tab -> return to the previous + if (delt == curDTab && ureq != null) { // if we close the current tab -> return to the previous popTheTabState(ureq); } // else just remove the dtabs delt.dispose();//dispose tab and controllers in tab @@ -964,9 +983,7 @@ public class BaseFullWebappController extends BasicController implements ChiefCo * @param dt */ private void requestCloseTab(UserRequest ureq, DTab delt) { - - Controller c = delt.getController(); // FIXME:fj: test - // vetoableclosecontroller + Controller c = delt.getController(); if (c instanceof VetoableCloseController) { VetoableCloseController vcc = (VetoableCloseController) c; // rembember current dtab, and swap to the temporary one @@ -1009,11 +1026,17 @@ public class BaseFullWebappController extends BasicController implements ChiefCo * java.lang.String) */ public DTab createDTab(OLATResourceable ores, OLATResourceable repoOres, String title) { + final DTabImpl dt; if (dtabs.size() >= getMaxTabs()) { getWindowControl().setError(translate("warn.tabsfull")); - return null; + dt = null; + } else if(lockedResource != null && ( + !lockedResource.getResourceableId().equals(ores.getResourceableId()) + || !lockedResource.getResourceableTypeName().equals(ores.getResourceableTypeName()))) { + dt = null; + } else { + dt = new DTabImpl(ores, repoOres, title, getWindowControl()); } - DTabImpl dt = new DTabImpl(ores, repoOres, title, getWindowControl()); return dt; } @@ -1110,17 +1133,9 @@ public class BaseFullWebappController extends BasicController implements ChiefCo // in all other cases the "focus of interest" (where the calculation of the // guipath is started) matches the controller which listens to the // event caused by a user interaction. - // WindowBackOffice wboNew = getWindowControl().getWindowBackOffice(); // // this is the starting point. - // getWindowControl().getWindowBackOffice().adjustGuiPathCenter(getWindowControl().getWindowControlInfo()); } - /** - * FIXME:fj: change className to class - * - * @see org.olat.core.gui.control.generic.dtabs.DTabs#activateStatic(org.olat.core.gui.UserRequest, - * java.lang.String, java.lang.String) - */ public void activateStatic(UserRequest ureq, String className, List<ContextEntry> entries) { if(className != null && className.endsWith("HomeSite")) { activateSite(userTools, ureq, entries, false); @@ -1136,6 +1151,7 @@ public class BaseFullWebappController extends BasicController implements ChiefCo } } + @Override public void event(Event event) { if (event == Window.AFTER_VALIDATING) { // now update the guimessage @@ -1179,9 +1195,18 @@ public class BaseFullWebappController extends BasicController implements ChiefCo } else if (event instanceof ChiefControllerMessageEvent) { // msg can be set to show only on one node or on all nodes updateStickyMessage(); + } else if (AssessmentModeNotificationEvent.command.equals(event.getCommand()) + && event instanceof AssessmentModeNotificationEvent) { + if(lockedResource == null) { + AssessmentModeNotificationEvent amne = (AssessmentModeNotificationEvent)event; + if(amne.getAssessedIdentityKeys().contains(getIdentity().getKey())) { + asyncLockResource(amne.getAssessementMode()); + } + } } } + @Override public boolean hasStaticSite(Class<? extends SiteInstance> type) { boolean hasSite = false; if(sites != null && sites.size() > 0) { @@ -1194,6 +1219,35 @@ public class BaseFullWebappController extends BasicController implements ChiefCo return hasSite; } + @Override + public void lockResource(OLATResourceable resource) { + this.lockedResource = resource; + if(topnavCtr != null) { + topnavCtr.lockResource(resource); + } + if(userToolsMenuCtrl != null) { + userToolsMenuCtrl.lockResource(resource); + } + + navSitesVc.setVisible(false); + for(int i=dtabsControllers.size(); i-->0; ) { + DTab tab = dtabs.get(i); + removeDTab(null, tab); + } + } + + private void asyncLockResource(TransientAssessmentMode mode) { + logAudit("Async lock resource for user: " + getIdentity().getName() + " (" + mode.getResource() + ")", null); + lockResource(mode.getResource()); + + AssessmentModeManager assessmentModeManager = CoreSpringFactory.getImpl(AssessmentModeManager.class); + + UserRequest ureq = new SyntheticUserRequest(getIdentity(), getLocale()); + modeCtrl = new AssessmentModeUserConfirmationController(ureq, getWindowControl(), Collections.singletonList(mode)); + listenTo(modeCtrl); + modeCtrl.getInitialComponent(); + } + /** * [used by velocity] helper for velocity * diff --git a/src/main/java/org/olat/core/commons/fullWebApp/BaseFullWebappControllerParts.java b/src/main/java/org/olat/core/commons/fullWebApp/BaseFullWebappControllerParts.java index 190ddbbf58fb5fff97637b7539b9d725de297787..163f501b566d51f0fd9448a66c06fd8aa2c38444 100644 --- a/src/main/java/org/olat/core/commons/fullWebApp/BaseFullWebappControllerParts.java +++ b/src/main/java/org/olat/core/commons/fullWebApp/BaseFullWebappControllerParts.java @@ -69,7 +69,7 @@ public interface BaseFullWebappControllerParts { * @param wControl * @return */ - public Controller createTopNavController(UserRequest ureq, WindowControl wControl); + public TopNavController createTopNavController(UserRequest ureq, WindowControl wControl); /** * footer controller (user count, logged in user, logo, verson info, etc) diff --git a/src/main/java/org/olat/core/commons/fullWebApp/BaseFullWebappDTabs.java b/src/main/java/org/olat/core/commons/fullWebApp/BaseFullWebappDTabs.java index 1c0dce780b3d677d2dc1632729281fa53a4b5433..e90c94855f8c3bc2a227f8f906b4a546645eb65a 100644 --- a/src/main/java/org/olat/core/commons/fullWebApp/BaseFullWebappDTabs.java +++ b/src/main/java/org/olat/core/commons/fullWebApp/BaseFullWebappDTabs.java @@ -51,22 +51,22 @@ class BaseFullWebappDTabs implements DTabs { webappCtrl.activateStatic(ureq, className, entries); } + @Override public boolean addDTab(UserRequest ureq, DTab dt) { return webappCtrl.addDTab(ureq, dt); } - - public DTab createDTab(OLATResourceable ores, String title) { - return webappCtrl.createDTab(ores, null, title); - } - + + @Override public DTab createDTab(OLATResourceable ores, OLATResourceable initialOres, String title) { return webappCtrl.createDTab(ores, initialOres, title); } + @Override public DTab getDTab(OLATResourceable ores) { return webappCtrl.getDTab(ores); } + @Override public void removeDTab(UserRequest ureq, DTab dt) { webappCtrl.removeDTab(ureq, dt); } diff --git a/src/main/java/org/olat/core/commons/fullWebApp/TopNavController.java b/src/main/java/org/olat/core/commons/fullWebApp/TopNavController.java new file mode 100644 index 0000000000000000000000000000000000000000..98b367baba4f6df0d0b06b37465a17166c2f6e00 --- /dev/null +++ b/src/main/java/org/olat/core/commons/fullWebApp/TopNavController.java @@ -0,0 +1,35 @@ +/** + * <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.core.commons.fullWebApp; + +import org.olat.core.gui.control.Controller; +import org.olat.core.id.OLATResourceable; + +/** + * + * Initial date: 18.12.2014<br> + * @author srosse, stephane.rosse@frentix.com, http://www.frentix.com + * + */ +public interface TopNavController extends Controller { + + public void lockResource(OLATResourceable resource); + +} diff --git a/src/main/java/org/olat/core/commons/fullWebApp/popup/BaseFullWebappMinimalLayoutControllerCreator.java b/src/main/java/org/olat/core/commons/fullWebApp/popup/BaseFullWebappMinimalLayoutControllerCreator.java index a78493b8d8b50fdf5a6cdbf55dfd1e01b8fda0c3..174ad0d5a1f63384c2d63384c008b29aee126afd 100644 --- a/src/main/java/org/olat/core/commons/fullWebApp/popup/BaseFullWebappMinimalLayoutControllerCreator.java +++ b/src/main/java/org/olat/core/commons/fullWebApp/popup/BaseFullWebappMinimalLayoutControllerCreator.java @@ -28,6 +28,7 @@ import java.util.List; import org.olat.core.CoreSpringFactory; import org.olat.core.commons.fullWebApp.BaseFullWebappControllerParts; +import org.olat.core.commons.fullWebApp.TopNavController; import org.olat.core.gui.UserRequest; import org.olat.core.gui.control.Controller; import org.olat.core.gui.control.WindowControl; @@ -69,12 +70,12 @@ class BaseFullWebappMinimalLayoutControllerCreator implements BaseFullWebappPopu return contentControllerCreator.createController(ureq, wControl); } - public Controller createTopNavController(UserRequest ureq, WindowControl wControl) { - Controller topnavCtr = null; + public TopNavController createTopNavController(UserRequest ureq, WindowControl wControl) { + TopNavController topnavCtr = null; // ----------- topnav, optional (e.g. for imprint, logout) ------------------ if (CoreSpringFactory.containsBean("fullWebApp.MinimalTopNavControllerCreator")) { ControllerCreator topnavControllerCreator = (ControllerCreator) CoreSpringFactory.getBean("fullWebApp.MinimalTopNavControllerCreator"); - topnavCtr = topnavControllerCreator.createController(ureq, wControl); + topnavCtr = (TopNavController)topnavControllerCreator.createController(ureq, wControl); } return topnavCtr; } diff --git a/src/main/java/org/olat/core/commons/fullWebApp/popup/BaseFullWebappPrintLayoutControllerCreator.java b/src/main/java/org/olat/core/commons/fullWebApp/popup/BaseFullWebappPrintLayoutControllerCreator.java index 5ebef78f3f88e7d2a7fe80f4dfe5235fbed20d4f..bf2a85ebdcbf53747622aae4634f01b39f928199 100644 --- a/src/main/java/org/olat/core/commons/fullWebApp/popup/BaseFullWebappPrintLayoutControllerCreator.java +++ b/src/main/java/org/olat/core/commons/fullWebApp/popup/BaseFullWebappPrintLayoutControllerCreator.java @@ -22,6 +22,7 @@ package org.olat.core.commons.fullWebApp.popup; import java.util.List; import org.olat.core.commons.fullWebApp.BaseFullWebappControllerParts; +import org.olat.core.commons.fullWebApp.TopNavController; import org.olat.core.gui.UserRequest; import org.olat.core.gui.control.Controller; import org.olat.core.gui.control.WindowControl; @@ -58,7 +59,7 @@ class BaseFullWebappPrintLayoutControllerCreator implements BaseFullWebappPopupL } @Override - public Controller createTopNavController(UserRequest ureq, WindowControl wControl) { + public TopNavController createTopNavController(UserRequest ureq, WindowControl wControl) { return null; } diff --git a/src/main/java/org/olat/core/commons/services/scheduler/_spring/schedulerContext.xml b/src/main/java/org/olat/core/commons/services/scheduler/_spring/schedulerContext.xml index a32dc8bb97b701bc4079104f08804a1a843f4f96..e586b67bde018096fd40e9b10ccf38aa7604ce6f 100644 --- a/src/main/java/org/olat/core/commons/services/scheduler/_spring/schedulerContext.xml +++ b/src/main/java/org/olat/core/commons/services/scheduler/_spring/schedulerContext.xml @@ -45,6 +45,7 @@ How to add a new job: <ref bean="updateQtiResultsTriggerOnyx"/> <ref bean="acReservationCleanupJob"/> <ref bean="mapperSlayerTrigger"/> + <ref bean="assessmentNotificationsTrigger"/> </list> </property> </bean> diff --git a/src/main/java/org/olat/core/gui/control/ChiefController.java b/src/main/java/org/olat/core/gui/control/ChiefController.java index aba2002dad324df30ce33c6ddbf10ec212b1a211..e67580fcd0db3178346014f53316710046030dc6 100644 --- a/src/main/java/org/olat/core/gui/control/ChiefController.java +++ b/src/main/java/org/olat/core/gui/control/ChiefController.java @@ -27,8 +27,9 @@ package org.olat.core.gui.control; import org.olat.core.gui.components.Window; -import org.olat.core.gui.control.navigation.SiteInstance; import org.olat.core.gui.components.htmlheader.jscss.CustomCSS; +import org.olat.core.gui.control.navigation.SiteInstance; +import org.olat.core.id.OLATResourceable; /** * Description: <br> * @@ -49,6 +50,8 @@ public interface ChiefController extends Controller { public boolean wishReload(boolean erase); + public void lockResource(OLATResourceable resource); + /** * Set a class to the <body> * @param cssClass diff --git a/src/main/java/org/olat/core/gui/control/DefaultChiefController.java b/src/main/java/org/olat/core/gui/control/DefaultChiefController.java index d00a61080c18821bdc7ecd4624134942c4f56ff2..88d3ed77da10a2a6350a0ea23b9e07dba50b8256 100644 --- a/src/main/java/org/olat/core/gui/control/DefaultChiefController.java +++ b/src/main/java/org/olat/core/gui/control/DefaultChiefController.java @@ -29,6 +29,7 @@ package org.olat.core.gui.control; import org.olat.core.gui.UserRequest; import org.olat.core.gui.components.Component; import org.olat.core.gui.components.Window; +import org.olat.core.id.OLATResourceable; import org.olat.core.logging.AssertException; /** @@ -72,6 +73,11 @@ public abstract class DefaultChiefController extends DefaultController implement public ScreenMode getScreenMode() { return screenMode; } + + @Override + public void lockResource(OLATResourceable resource) { + // + } /** * @see org.olat.core.gui.control.DefaultController#event(org.olat.core.gui.UserRequest, org.olat.core.gui.components.Component, org.olat.core.gui.control.Event) diff --git a/src/main/java/org/olat/core/gui/control/_spring/fullWebAppContext.xml b/src/main/java/org/olat/core/gui/control/_spring/fullWebAppContext.xml index 222dbf25579b8c69e772cfc31f5ee998750d2463..5b76b421fead582d2b70a8282bd6b095c3041c4f 100644 --- a/src/main/java/org/olat/core/gui/control/_spring/fullWebAppContext.xml +++ b/src/main/java/org/olat/core/gui/control/_spring/fullWebAppContext.xml @@ -5,16 +5,6 @@ http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"> - <!-- - ************************************************************************** - *** Configure the controller-workflow which should be presented *** - *** right after a user logged in. *** - *** See comment in AfterLoginInterceptorController *** - ************************************************************************** - --> - <bean id="fullWebApp.AfterLoginInterceptionControllerCreator" class="org.olat.core.gui.control.creator.AutoCreator" > - <property name="className" value="org.olat.login.AfterLoginInterceptionController"/> - </bean> <!-- the specifed creator is responsible for the frameworks popup browser window layout. Special layouts must be implemented by wrapping the content into a content-layouting controller --> diff --git a/src/main/java/org/olat/core/gui/control/generic/dtabs/DTabs.java b/src/main/java/org/olat/core/gui/control/generic/dtabs/DTabs.java index e563067b8f9bca4dea97b682aec072333fb595dc..4658cbc2537ca9395a14663744a64f5217842e79 100644 --- a/src/main/java/org/olat/core/gui/control/generic/dtabs/DTabs.java +++ b/src/main/java/org/olat/core/gui/control/generic/dtabs/DTabs.java @@ -46,13 +46,6 @@ public interface DTabs { */ public DTab getDTab(OLATResourceable ores); - /** - * @param ores - * @param title - * @return the tab or null if the headerbar is full. if null, the implementation of the DTabs should issue a warning to the current windowcontrol - */ - public DTab createDTab(OLATResourceable ores, String title); - /** * @param ores * @param repoOres diff --git a/src/main/java/org/olat/core/util/UserSession.java b/src/main/java/org/olat/core/util/UserSession.java index 2d461eb366240febee13fd35f536ae93d35c2c5b..d3e9238679fc0557d68cb2f2ef5cee26e900237d 100644 --- a/src/main/java/org/olat/core/util/UserSession.java +++ b/src/main/java/org/olat/core/util/UserSession.java @@ -60,6 +60,7 @@ import org.olat.core.util.prefs.Preferences; import org.olat.core.util.prefs.PreferencesFactory; import org.olat.core.util.resource.OresHelper; import org.olat.core.util.session.UserSessionManager; +import org.olat.course.assessment.AssessmentMode; /** * Description: <BR/>the httpsession contains an instance of this class. the @@ -76,6 +77,7 @@ public class UserSession implements HttpSessionBindingListener, GenericEventList // the environment (identity, locale, ..) of the identity private IdentityEnvironment identityEnvironment; private SessionInfo sessionInfo; + private List<AssessmentMode> assessmentModes; private transient Map<String,Object> store; /** * things to put into that should not be clear when signing on (e.g. remember url for a direct jump) @@ -286,6 +288,14 @@ public class UserSession implements HttpSessionBindingListener, GenericEventList return identityEnvironment; } + public List<AssessmentMode> getAssessmentModes() { + return assessmentModes; + } + + public void setAssessmentModes(List<AssessmentMode> assessmentModes) { + this.assessmentModes = assessmentModes; + } + /** * may be null * <p> diff --git a/src/main/java/org/olat/course/assessment/AssessmentMode.java b/src/main/java/org/olat/course/assessment/AssessmentMode.java index cfd906bcaeec9bf2a3fa802da63a816d68786e7c..fcf5d32f6fc8fc2ec69942aeba619a41f9064d2a 100644 --- a/src/main/java/org/olat/course/assessment/AssessmentMode.java +++ b/src/main/java/org/olat/course/assessment/AssessmentMode.java @@ -24,6 +24,7 @@ import java.util.Set; import org.olat.core.id.CreateInfo; import org.olat.core.id.ModifiedInfo; +import org.olat.repository.RepositoryEntry; /** * @@ -42,6 +43,8 @@ public interface AssessmentMode extends ModifiedInfo, CreateInfo { public String getDescription(); public void setDescription(String description); + + public RepositoryEntry getRepositoryEntry(); public Date getBegin(); diff --git a/src/main/java/org/olat/course/assessment/AssessmentModeManager.java b/src/main/java/org/olat/course/assessment/AssessmentModeManager.java index ff64a3e1c3868dec1f1f2647e62ed0df7bfb03ae..0b295149b8eb25934e0aa0853676dd79f5b9fbc0 100644 --- a/src/main/java/org/olat/course/assessment/AssessmentModeManager.java +++ b/src/main/java/org/olat/course/assessment/AssessmentModeManager.java @@ -20,6 +20,7 @@ package org.olat.course.assessment; import java.util.List; +import java.util.Set; import org.olat.basesecurity.IdentityRef; import org.olat.group.BusinessGroup; @@ -41,11 +42,13 @@ public interface AssessmentModeManager { */ public AssessmentMode createAssessmentMode(RepositoryEntry entry); + public AssessmentModeToGroup createAssessmentModeToGroup(AssessmentMode mode, BusinessGroup group); + public AssessmentMode save(AssessmentMode assessmentMode); - public AssessmentMode loadById(Long key); + public AssessmentMode getAssessmentModeById(Long key); - public List<AssessmentMode> loadAssessmentMode(RepositoryEntryRef entry); + public List<AssessmentMode> getAssessmentModeFor(RepositoryEntryRef entry); /** * Load the assessment mode for a specific user now. @@ -53,10 +56,11 @@ public interface AssessmentModeManager { * @param identity * @return */ - public List<AssessmentMode> loadAssessmentModeFor(IdentityRef identity); + public List<AssessmentMode> getAssessmentModeFor(IdentityRef identity); - public List<AssessmentMode> loadCurrentAssessmentModes(); + public List<AssessmentMode> getCurrentAssessmentModes(); + + public Set<Long> getAssessedIdentities(AssessmentMode assessmentMode); - public AssessmentModeToGroup createAssessmentModeToGroup(AssessmentMode mode, BusinessGroup group); } diff --git a/src/main/java/org/olat/course/assessment/AssessmentModeNotificationEvent.java b/src/main/java/org/olat/course/assessment/AssessmentModeNotificationEvent.java new file mode 100644 index 0000000000000000000000000000000000000000..f1466cf0546ca7429fd95d598433f974e776907b --- /dev/null +++ b/src/main/java/org/olat/course/assessment/AssessmentModeNotificationEvent.java @@ -0,0 +1,59 @@ +/** + * <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; + +import java.util.Set; + +import org.olat.core.id.OLATResourceable; +import org.olat.core.util.event.MultiUserEvent; +import org.olat.core.util.resource.OresHelper; +import org.olat.course.assessment.model.TransientAssessmentMode; + +/** + * + * Initial date: 18.12.2014<br> + * @author srosse, stephane.rosse@frentix.com, http://www.frentix.com + * + */ +public class AssessmentModeNotificationEvent extends MultiUserEvent { + + public static final String command = "assessment-mode-notification"; + public static final OLATResourceable ASSESSMENT_MODE_NOTIFICATION = OresHelper.createOLATResourceableType(command); + + private static final long serialVersionUID = 1539360689947584111L; + + private TransientAssessmentMode mode; + private Set<Long> assessedIdentityKeys; + + public AssessmentModeNotificationEvent(TransientAssessmentMode mode, Set<Long> assessedIdentityKeys) { + super(command); + this.mode = mode; + this.assessedIdentityKeys = assessedIdentityKeys; + } + + public TransientAssessmentMode getAssessementMode() { + return mode; + } + + + public Set<Long> getAssessedIdentityKeys() { + return assessedIdentityKeys; + } +} diff --git a/src/main/java/org/olat/course/assessment/AssessmentModeToGroup.java b/src/main/java/org/olat/course/assessment/AssessmentModeToGroup.java index 765eede429b72d1f4fccf734935804945f328715..1c94406d77d48e45ab5e2b82ab3a0ccc63b71cfb 100644 --- a/src/main/java/org/olat/course/assessment/AssessmentModeToGroup.java +++ b/src/main/java/org/olat/course/assessment/AssessmentModeToGroup.java @@ -1,3 +1,22 @@ +/** + * <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; import org.olat.group.BusinessGroup; diff --git a/src/main/java/org/olat/course/assessment/_spring/assessmentContext.xml b/src/main/java/org/olat/course/assessment/_spring/assessmentContext.xml index 39b5e21a35b05627f2cfb7a4a937b7d1091e22fb..eeaa6225ea61c9e6ad8f1bd160d15b9ba4023497 100644 --- a/src/main/java/org/olat/course/assessment/_spring/assessmentContext.xml +++ b/src/main/java/org/olat/course/assessment/_spring/assessmentContext.xml @@ -20,5 +20,15 @@ <property name="userManager" ref="userManager"/> <property name="repositoryManager" ref="repositoryManager"/> </bean> + + <bean id="assessmentNotificationsTrigger" class="org.springframework.scheduling.quartz.CronTriggerBean"> + <property name="jobDetail" ref="assessmentNotificationsJob" /> + <property name="cronExpression" value="25 */5 * * * ?" /> + <property name="startDelay" value="55000" /> + </bean> + + <bean id="assessmentNotificationsJob" class="org.springframework.scheduling.quartz.JobDetailBean" lazy-init="true"> + <property name="jobClass" value="org.olat.course.assessment.manager.AssessmentModeNotificationJob" /> + </bean> </beans> diff --git a/src/main/java/org/olat/course/assessment/manager/AssessmentModeManagerImpl.java b/src/main/java/org/olat/course/assessment/manager/AssessmentModeManagerImpl.java index fcfe9c020c14a1ec1f5178609a85479d6263708f..12d2d7ae06da0d5866bbd31b68cc02cf9f1db917 100644 --- a/src/main/java/org/olat/course/assessment/manager/AssessmentModeManagerImpl.java +++ b/src/main/java/org/olat/course/assessment/manager/AssessmentModeManagerImpl.java @@ -21,22 +21,28 @@ package org.olat.course.assessment.manager; import java.util.ArrayList; import java.util.Calendar; +import java.util.Collections; import java.util.Date; +import java.util.HashSet; import java.util.List; +import java.util.Set; import org.olat.basesecurity.GroupRoles; import org.olat.basesecurity.IdentityRef; import org.olat.core.commons.persistence.DB; -import org.olat.core.commons.persistence.PersistenceHelper; import org.olat.course.assessment.AssessmentMode; +import org.olat.course.assessment.AssessmentMode.Target; import org.olat.course.assessment.AssessmentModeManager; import org.olat.course.assessment.AssessmentModeToGroup; import org.olat.course.assessment.model.AssessmentModeImpl; import org.olat.course.assessment.model.AssessmentModeToGroupImpl; import org.olat.group.BusinessGroup; import org.olat.group.BusinessGroupImpl; +import org.olat.group.manager.BusinessGroupRelationDAO; import org.olat.repository.RepositoryEntry; import org.olat.repository.RepositoryEntryRef; +import org.olat.repository.RepositoryEntryRelationType; +import org.olat.repository.manager.RepositoryEntryRelationDAO; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; @@ -51,13 +57,17 @@ public class AssessmentModeManagerImpl implements AssessmentModeManager { @Autowired private DB dbInstance; + @Autowired + private BusinessGroupRelationDAO businessGroupRelationDao; + @Autowired + private RepositoryEntryRelationDAO repositoryEntryRelationDao; @Override public AssessmentMode createAssessmentMode(RepositoryEntry entry) { AssessmentModeImpl mode = new AssessmentModeImpl(); mode.setCreationDate(new Date()); mode.setLastModified(new Date()); - mode.setEntry(entry); + mode.setRepositoryEntry(entry); return mode; } @@ -76,7 +86,7 @@ public class AssessmentModeManagerImpl implements AssessmentModeManager { } @Override - public AssessmentMode loadById(Long key) { + public AssessmentMode getAssessmentModeById(Long key) { String q = "select mode from courseassessmentmode mode where mode.key=:modeKey"; List<AssessmentMode> modes = dbInstance.getCurrentEntityManager() .createQuery(q, AssessmentMode.class) @@ -87,7 +97,7 @@ public class AssessmentModeManagerImpl implements AssessmentModeManager { } @Override - public List<AssessmentMode> loadAssessmentMode(RepositoryEntryRef entry) { + public List<AssessmentMode> getAssessmentModeFor(RepositoryEntryRef entry) { return dbInstance.getCurrentEntityManager() .createNamedQuery("assessmentModeByRepoEntry", AssessmentMode.class) .setParameter("entryKey", entry.getKey()) @@ -95,18 +105,20 @@ public class AssessmentModeManagerImpl implements AssessmentModeManager { } @Override - public List<AssessmentMode> loadAssessmentModeFor(IdentityRef identity) { - List<AssessmentMode> currentModes = loadCurrentAssessmentModes(); + public List<AssessmentMode> getAssessmentModeFor(IdentityRef identity) { + List<AssessmentMode> currentModes = getCurrentAssessmentModes(); + List<AssessmentMode> myModes = null; if(currentModes.size() > 0) { //check permissions, groups, areas, course - currentModes = loadAssessmentModeFor(identity, currentModes); + myModes = loadAssessmentModeFor(identity, currentModes); } - return currentModes; + return myModes == null ? Collections.<AssessmentMode>emptyList() : myModes; } private List<AssessmentMode> loadAssessmentModeFor(IdentityRef identity, List<AssessmentMode> currentModes) { StringBuilder sb = new StringBuilder(1000); sb.append("select mode from courseassessmentmode mode ") + .append(" inner join fetch mode.repositoryEntry entry") .append(" left join mode.groups as modeToGroup") .append(" where mode.key in (:modeKeys)") .append(" and ((mode.targetAudienceString in ('").append(AssessmentMode.Target.courseAndGroups.name()).append("','").append(AssessmentMode.Target.groups.name()).append("')") @@ -116,7 +128,7 @@ public class AssessmentModeManagerImpl implements AssessmentModeManager { .append(" (mode.applySettingsForCoach=true and membership.role='").append(GroupRoles.coach.name()).append("'))") .append(" )) or (mode.targetAudienceString in ('").append(AssessmentMode.Target.courseAndGroups.name()).append("','").append(AssessmentMode.Target.course.name()).append("')") .append(" and exists (select rel from repoentrytogroup as rel, bgroupmember as membership ") - .append(" where mode.entry=rel.entry and membership.group=rel.group and membership.identity.key=:identityKey") + .append(" where mode.repositoryEntry=rel.entry and membership.group=rel.group and membership.identity.key=:identityKey") .append(" and (membership.role='").append(GroupRoles.participant.name()).append("' or ") .append(" (mode.applySettingsForCoach=true and membership.role='").append(GroupRoles.coach.name()).append("'))") .append(" ))") @@ -126,15 +138,48 @@ public class AssessmentModeManagerImpl implements AssessmentModeManager { for(AssessmentMode mode:currentModes) { modeKeys.add(mode.getKey()); } - return dbInstance.getCurrentEntityManager() + List<AssessmentMode> modeList = dbInstance.getCurrentEntityManager() .createQuery(sb.toString(), AssessmentMode.class) .setParameter("identityKey", identity.getKey()) .setParameter("modeKeys", modeKeys) .getResultList(); + //quicker than distinct + return new ArrayList<AssessmentMode>(new HashSet<AssessmentMode>(modeList)); + } + + @Override + public Set<Long> getAssessedIdentities(AssessmentMode assessmentMode) { + Target targetAudience = assessmentMode.getTargetAudience(); + RepositoryEntry re = assessmentMode.getRepositoryEntry(); + + Set<Long> assessedKeys = new HashSet<>(); + if(targetAudience == Target.course || targetAudience == Target.courseAndGroups) { + List<Long> courseMemberKeys = assessmentMode.isApplySettingsForCoach() + ? repositoryEntryRelationDao.getMemberKeys(re, RepositoryEntryRelationType.defaultGroup, GroupRoles.coach.name(), GroupRoles.participant.name()) + : repositoryEntryRelationDao.getMemberKeys(re, RepositoryEntryRelationType.defaultGroup, GroupRoles.participant.name()); + assessedKeys.addAll(courseMemberKeys); + } + if(targetAudience == Target.groups || targetAudience == Target.courseAndGroups) { + Set<AssessmentModeToGroup> modeToGroups = assessmentMode.getGroups(); + if(modeToGroups.size() > 0) { + List<BusinessGroup> groups = new ArrayList<>(modeToGroups.size()); + for(AssessmentModeToGroup modeToGroup: modeToGroups) { + groups.add(modeToGroup.getBusinessGroup()); + } + + List<Long> groupMemberKeys = assessmentMode.isApplySettingsForCoach() + ? businessGroupRelationDao.getMemberKeys(groups, GroupRoles.coach.name(), GroupRoles.participant.name()) + : businessGroupRelationDao.getMemberKeys(groups, GroupRoles.participant.name()); + assessedKeys.addAll(groupMemberKeys); + } + + } + + return assessedKeys; } @Override - public List<AssessmentMode> loadCurrentAssessmentModes() { + public List<AssessmentMode> getCurrentAssessmentModes() { Calendar cal = Calendar.getInstance(); cal.set(Calendar.MILLISECOND, 0); cal.set(Calendar.SECOND, 0); diff --git a/src/main/java/org/olat/course/assessment/manager/AssessmentModeNotificationJob.java b/src/main/java/org/olat/course/assessment/manager/AssessmentModeNotificationJob.java new file mode 100644 index 0000000000000000000000000000000000000000..e5c147bc231888edd9c9e9b130f7c5c952fd9707 --- /dev/null +++ b/src/main/java/org/olat/course/assessment/manager/AssessmentModeNotificationJob.java @@ -0,0 +1,56 @@ +/** + * <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.manager; + +import java.util.List; +import java.util.Set; + +import org.olat.core.CoreSpringFactory; +import org.olat.core.commons.services.scheduler.JobWithDB; +import org.olat.core.util.coordinate.CoordinatorManager; +import org.olat.course.assessment.AssessmentMode; +import org.olat.course.assessment.AssessmentModeManager; +import org.olat.course.assessment.AssessmentModeNotificationEvent; +import org.olat.course.assessment.model.TransientAssessmentMode; +import org.quartz.JobExecutionContext; +import org.quartz.JobExecutionException; + +/** + * + * Initial date: 18.12.2014<br> + * @author srosse, stephane.rosse@frentix.com, http://www.frentix.com + * + */ +public class AssessmentModeNotificationJob extends JobWithDB { + + @Override + public void executeWithDB(JobExecutionContext context) + throws JobExecutionException { + AssessmentModeManager assessmentModeManager = CoreSpringFactory.getImpl(AssessmentModeManager.class); + List<AssessmentMode> currentModes = assessmentModeManager.getCurrentAssessmentModes(); + for(AssessmentMode currentMode:currentModes) { + Set<Long> assessedIdentityKeys = assessmentModeManager.getAssessedIdentities(currentMode); + TransientAssessmentMode transientMode = new TransientAssessmentMode(currentMode); + AssessmentModeNotificationEvent event = new AssessmentModeNotificationEvent(transientMode, assessedIdentityKeys); + CoordinatorManager.getInstance().getCoordinator().getEventBus() + .fireEventToListenersOf(event, AssessmentModeNotificationEvent.ASSESSMENT_MODE_NOTIFICATION); + } + } +} diff --git a/src/main/java/org/olat/course/assessment/manager/IPRangeChecker.java b/src/main/java/org/olat/course/assessment/manager/IPRangeChecker.java new file mode 100644 index 0000000000000000000000000000000000000000..dec104a2f9d58a6b4865985018829d3696661c39 --- /dev/null +++ b/src/main/java/org/olat/course/assessment/manager/IPRangeChecker.java @@ -0,0 +1,63 @@ +/** + * <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.manager; + +import java.net.InetAddress; +import java.net.UnknownHostException; + +/** + * + * Thanks: https://gist.github.com/madan712/6651967 + * + * Initial date: 18.12.2014<br> + * @author srosse, stephane.rosse@frentix.com, http://www.frentix.com + * + */ +public class IPRangeChecker { + + public static long ipToLong(InetAddress ip) { + byte[] octets = ip.getAddress(); + long result = 0; + for (byte octet : octets) { + result <<= 8; + result |= octet & 0xff; + } + return result; + } + + /** + * TODO replace perhaps with guava, jdk make a round trip to the address. + * @param ipStart + * @param ipEnd + * @param ipToCheck + * @return + */ + public static boolean isValidRange(String ipStart, String ipEnd, String ipToCheck) { + try { + long ipLo = ipToLong(InetAddress.getByName(ipStart)); + long ipHi = ipToLong(InetAddress.getByName(ipEnd)); + long ipToTest = ipToLong(InetAddress.getByName(ipToCheck)); + return (ipToTest >= ipLo && ipToTest <= ipHi); + } catch (UnknownHostException e) { + e.printStackTrace(); + return false; + } + } +} diff --git a/src/main/java/org/olat/course/assessment/model/AssessmentModeImpl.java b/src/main/java/org/olat/course/assessment/model/AssessmentModeImpl.java index 94e9cce2ac41a20800b6d490e0b93a2d8a0fd2f1..2990d6e55de636693089dd32b3fe72819089bdee 100644 --- a/src/main/java/org/olat/course/assessment/model/AssessmentModeImpl.java +++ b/src/main/java/org/olat/course/assessment/model/AssessmentModeImpl.java @@ -52,7 +52,7 @@ import org.olat.repository.RepositoryEntry; @Entity(name="courseassessmentmode") @Table(name="o_as_mode_course") @NamedQueries({ - @NamedQuery(name="assessmentModeByRepoEntry", query="select mode from courseassessmentmode mode where mode.entry.key=:entryKey"), + @NamedQuery(name="assessmentModeByRepoEntry", query="select mode from courseassessmentmode mode where mode.repositoryEntry.key=:entryKey"), @NamedQuery(name="currentAssessmentModes", query="select mode from courseassessmentmode mode where mode.begin<=:now and mode.end>=:now") }) public class AssessmentModeImpl implements Persistable, AssessmentMode { @@ -114,7 +114,7 @@ public class AssessmentModeImpl implements Persistable, AssessmentMode { @ManyToOne(targetEntity=RepositoryEntry.class,fetch=FetchType.LAZY,optional=false) @JoinColumn(name="fk_entry", nullable=false, updatable=false) - private RepositoryEntry entry; + private RepositoryEntry repositoryEntry; @Override @@ -302,12 +302,13 @@ public class AssessmentModeImpl implements Persistable, AssessmentMode { this.applySettingsForCoach = applySettingsForCoach; } - public RepositoryEntry getEntry() { - return entry; + @Override + public RepositoryEntry getRepositoryEntry() { + return repositoryEntry; } - public void setEntry(RepositoryEntry entry) { - this.entry = entry; + public void setRepositoryEntry(RepositoryEntry entry) { + this.repositoryEntry = entry; } @Override diff --git a/src/main/java/org/olat/course/assessment/model/AssessmentModeToGroupImpl.java b/src/main/java/org/olat/course/assessment/model/AssessmentModeToGroupImpl.java index 2ce5faab16bbe963b1490c20a131c412c79c6e97..b709392b275ecd9b2c62e74ab9e28a938327b445 100644 --- a/src/main/java/org/olat/course/assessment/model/AssessmentModeToGroupImpl.java +++ b/src/main/java/org/olat/course/assessment/model/AssessmentModeToGroupImpl.java @@ -1,3 +1,22 @@ +/** + * <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.model; import javax.persistence.Column; diff --git a/src/main/java/org/olat/course/assessment/model/TransientAssessmentMode.java b/src/main/java/org/olat/course/assessment/model/TransientAssessmentMode.java new file mode 100644 index 0000000000000000000000000000000000000000..85b074bdfe0d495b06a83e421aaaee89e5acb45e --- /dev/null +++ b/src/main/java/org/olat/course/assessment/model/TransientAssessmentMode.java @@ -0,0 +1,121 @@ +/** + * <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.model; + +import java.io.Serializable; +import java.util.ArrayList; +import java.util.Date; +import java.util.List; + +import org.olat.core.id.OLATResourceable; +import org.olat.core.util.resource.OresHelper; +import org.olat.course.assessment.AssessmentMode; + +/** + * + * Initial date: 18.12.2014<br> + * @author srosse, stephane.rosse@frentix.com, http://www.frentix.com + * + */ +public class TransientAssessmentMode implements Serializable { + + private static final long serialVersionUID = -5738682288044689497L; + private String displayName; + private Long repositoryEntryKey; + private OLATResourceable resource; + + private String name; + private String description; + private Date begin; + private Date end; + private int leadTime; + + public TransientAssessmentMode(AssessmentMode mode) { + displayName = mode.getRepositoryEntry().getDisplayname(); + resource = OresHelper.clone(mode.getRepositoryEntry().getOlatResource()); + repositoryEntryKey = mode.getRepositoryEntry().getKey(); + + name = mode.getName(); + description = mode.getDescription(); + begin = mode.getBegin(); + end = mode.getEnd(); + leadTime = mode.getLeadTime(); + } + + public static List<TransientAssessmentMode> create(List<AssessmentMode> modes) { + List<TransientAssessmentMode> transientModes = new ArrayList<>(modes.size()); + for(AssessmentMode mode:modes) { + transientModes.add(new TransientAssessmentMode(mode)); + } + return transientModes; + } + + public String getDisplayName() { + return displayName; + } + + public void setDisplayName(String displayName) { + this.displayName = displayName; + } + + public Long getRepositoryEntryKey() { + return repositoryEntryKey; + } + + public OLATResourceable getResource() { + return resource; + } + + public void setResource(OLATResourceable resource) { + this.resource = resource; + } + + public String getName() { + return name; + } + + public String getDescription() { + return description; + } + + public Date getBegin() { + return begin; + } + + public void setBegin(Date begin) { + this.begin = begin; + } + + public Date getEnd() { + return end; + } + + public void setEnd(Date end) { + this.end = end; + } + + public int getLeadTime() { + return leadTime; + } + + public void setLeadTime(int leadTime) { + this.leadTime = leadTime; + } +} \ No newline at end of file diff --git a/src/main/java/org/olat/course/assessment/ui/AssessmentModeEditController.java b/src/main/java/org/olat/course/assessment/ui/AssessmentModeEditController.java index 91fd337e95ab68c84f69195bf8c1b219c6ace928..5eebeb3df2fd0935fd999329043f15fe148ef268 100644 --- a/src/main/java/org/olat/course/assessment/ui/AssessmentModeEditController.java +++ b/src/main/java/org/olat/course/assessment/ui/AssessmentModeEditController.java @@ -108,7 +108,7 @@ public class AssessmentModeEditController extends FormBasicController { if(assessmentMode.getKey() == null) { this.assessmentMode = assessmentMode; } else { - this.assessmentMode = assessmentModeMgr.loadById(assessmentMode.getKey()); + this.assessmentMode = assessmentModeMgr.getAssessmentModeById(assessmentMode.getKey()); } initForm(ureq); } @@ -152,8 +152,8 @@ public class AssessmentModeEditController extends FormBasicController { String[] audienceKeys = new String[] { AssessmentMode.Target.courseAndGroups.name(), - AssessmentMode.Target.groups.name(), - AssessmentMode.Target.course.name() + AssessmentMode.Target.course.name(), + AssessmentMode.Target.groups.name() }; String[] audienceValues = new String[] { translate("target.courseAndGroups"), diff --git a/src/main/java/org/olat/course/assessment/ui/AssessmentModeListController.java b/src/main/java/org/olat/course/assessment/ui/AssessmentModeListController.java index 2a76cc70f7ef68bc45f8c8a24eb4b0063abb60df..18d53640bdc4f298dcbc0fd14d5dc1d721a37d58 100644 --- a/src/main/java/org/olat/course/assessment/ui/AssessmentModeListController.java +++ b/src/main/java/org/olat/course/assessment/ui/AssessmentModeListController.java @@ -102,7 +102,7 @@ public class AssessmentModeListController extends FormBasicController { } private void loadModel() { - List<AssessmentMode> modes = assessmentModeMgr.loadAssessmentMode(entry); + List<AssessmentMode> modes = assessmentModeMgr.getAssessmentModeFor(entry); model.setObjects(modes); tableEl.reloadData(); } diff --git a/src/main/java/org/olat/course/assessment/ui/AssessmentModeUserConfirmationController.java b/src/main/java/org/olat/course/assessment/ui/AssessmentModeUserConfirmationController.java new file mode 100644 index 0000000000000000000000000000000000000000..cf727b57c2c03c7a6e197edebd0cda501471291d --- /dev/null +++ b/src/main/java/org/olat/course/assessment/ui/AssessmentModeUserConfirmationController.java @@ -0,0 +1,158 @@ +/** + * <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; + +import java.util.ArrayList; +import java.util.List; +import java.util.Locale; + +import org.olat.NewControllerFactory; +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.link.Link; +import org.olat.core.gui.components.link.LinkFactory; +import org.olat.core.gui.components.panel.Panel; +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.closablewrapper.CloseableModalController; +import org.olat.core.id.OLATResourceable; +import org.olat.core.util.CodeHelper; +import org.olat.core.util.Formatter; +import org.olat.course.assessment.model.TransientAssessmentMode; + +/** + * + * Initial date: 18.12.2014<br> + * @author srosse, stephane.rosse@frentix.com, http://www.frentix.com + * + */ +public class AssessmentModeUserConfirmationController extends BasicController { + + private final CloseableModalController cmc; + + public AssessmentModeUserConfirmationController(UserRequest ureq, WindowControl wControl) { + this(ureq, wControl, TransientAssessmentMode.create(ureq.getUserSession().getAssessmentModes())); + } + + public AssessmentModeUserConfirmationController(UserRequest ureq, WindowControl wControl, List<TransientAssessmentMode> modes) { + super(ureq, wControl); + putInitialPanel(new Panel("assessment-mode-chooser")); + + VelocityContainer mainVC = createVelocityContainer("choose_mode"); + List<Mode> modeWrappers = new ArrayList<Mode>(); + for(TransientAssessmentMode mode:modes) { + String name = "go-" + CodeHelper.getRAMUniqueID(); + Link button = LinkFactory.createCustomLink(name, "go", "current.mode.start", Link.BUTTON, mainVC, this); + button.setUserObject(mode); + + Mode wrapper = new Mode(button, mode, getLocale()); + modeWrappers.add(wrapper); + } + mainVC.contextPut("modeWrappers", modeWrappers); + + cmc = new CloseableModalController(getWindowControl(), translate("close"), mainVC, true, translate("current.mode"), false); + cmc.activate(); + listenTo(cmc); + } + + @Override + protected void doDispose() { + // + } + + @Override + protected void event(UserRequest ureq, Component source, Event event) { + if(source instanceof Link) { + Link link = (Link)source; + if("go".equals(link.getCommand())) { + launchAssessmentMode(ureq, (TransientAssessmentMode)link.getUserObject()); + } + } + } + + /** + * Remove thie list of assessment modes and lock the chief controller. + * + * + * @param ureq + * @param mode + */ + private void launchAssessmentMode(UserRequest ureq, TransientAssessmentMode mode) { + ureq.getUserSession().setAssessmentModes(null); + OLATResourceable resource = mode.getResource(); + Windows.getWindows(ureq).getChiefController().lockResource(resource); + fireEvent(ureq, new ChooseAssessmentModeEvent(mode)); + + String businessPath = "[RepositoryEntry:" + mode.getRepositoryEntryKey() + "]"; //TODO node + NewControllerFactory.getInstance().launch(businessPath, ureq, getWindowControl()); + } + + public static final class Mode { + + private final Locale locale; + private final Link goButton; + private final TransientAssessmentMode mode; + + public Mode(Link goButton, TransientAssessmentMode mode, Locale locale) { + this.goButton = goButton; + this.mode = mode; + this.locale = locale; + } + + public String getName() { + return mode.getName(); + } + + public String getDescription() { + return mode.getDescription(); + } + + public String getDisplayName() { + return mode.getDisplayName(); + } + + public String getBegin() { + return Formatter.getInstance(locale).formatDateAndTime(mode.getBegin()); + } + + public String getEnd() { + return Formatter.getInstance(locale).formatDateAndTime(mode.getEnd()); + } + + public String getLeadTime() { + String lt = ""; + if(mode.getLeadTime() > 0) { + lt = Integer.toString(mode.getLeadTime()); + } + return lt; + } + + public String getButtonName() { + return goButton.getComponentName(); + } + + public TransientAssessmentMode getMode() { + return mode; + } + } +} diff --git a/src/main/java/org/olat/course/assessment/ui/ChooseAssessmentModeEvent.java b/src/main/java/org/olat/course/assessment/ui/ChooseAssessmentModeEvent.java new file mode 100644 index 0000000000000000000000000000000000000000..bc39d2bf801b87d49f5804cee91df794981bda76 --- /dev/null +++ b/src/main/java/org/olat/course/assessment/ui/ChooseAssessmentModeEvent.java @@ -0,0 +1,45 @@ +/** + * <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; + +import org.olat.core.gui.control.Event; +import org.olat.course.assessment.model.TransientAssessmentMode; + +/** + * + * Initial date: 18.12.2014<br> + * @author srosse, stephane.rosse@frentix.com, http://www.frentix.com + * + */ +public class ChooseAssessmentModeEvent extends Event { + + private static final long serialVersionUID = -3064859162799070354L; + private TransientAssessmentMode assessmentMode; + + public ChooseAssessmentModeEvent(TransientAssessmentMode assessmentMode) { + super("choose-assessment-mode"); + this.assessmentMode = assessmentMode; + } + + public TransientAssessmentMode getAssessmentMode() { + return assessmentMode; + } + +} diff --git a/src/main/java/org/olat/course/assessment/ui/_content/choose_mode.html b/src/main/java/org/olat/course/assessment/ui/_content/choose_mode.html new file mode 100644 index 0000000000000000000000000000000000000000..4506849bc6efd9f5e9382715f25430bf8cc74138 --- /dev/null +++ b/src/main/java/org/olat/course/assessment/ui/_content/choose_mode.html @@ -0,0 +1,12 @@ +<div class="o_info">$r.translate("current.mode.desc")</div> +#foreach($mode in $modeWrappers) + <h2>$mode.name <small>$r.translate("current.mode.course", $mode.displayName)</small></h2> + <p><em>$r.translate("current.mode.datetimes", $mode.begin, $mode.end)</em> + #if(!$mode.leadTime.empty) + <br/><em>$r.translate("current.mode.leadtime", $mode.leadTime)</em> + #end + </p> + <p>$mode.description</p> + <div class="o_button_group">$r.render($mode.buttonName)</div> +#end + diff --git a/src/main/java/org/olat/course/assessment/ui/_i18n/LocalStrings_de.properties b/src/main/java/org/olat/course/assessment/ui/_i18n/LocalStrings_de.properties index eea9b2543d00a7341a62af3ee699bd0e5e3c2e94..a327692a1d9bb5e42fcf50448ac450782df03149 100644 --- a/src/main/java/org/olat/course/assessment/ui/_i18n/LocalStrings_de.properties +++ b/src/main/java/org/olat/course/assessment/ui/_i18n/LocalStrings_de.properties @@ -4,6 +4,12 @@ areas=Lernbereich choose.areas=Lernbereich auswählen choose.elements=Kursbausteine auswählen choose.groups=Gruppen auswählen +current.mode=Aktuelle Prüfung +current.mode.desc=Im folgenden Kurs ist für den aktuellen Zeitraum eine Prüfung für Sie vorgesehen. Während dieser Prüfung können keine anderen Funktionen in OpenOLAT verwendet werden: +current.mode.start=Zur Prüfung +current.mode.course=in Kurs "{0}" +current.mode.datetimes=Von {0} bis {1} +current.mode.leadtime=Ab {0} Minuten vor Prüfungsbeginn können keine andere Kurse mehr geöffnet werden. delete.mode=Pr\u00FCfungssetting l\u00F6schen elements=Kursbausteine form.mode.description=Erstellen Sie ein neues Pr\u00FCfungssetting um f\u00FCr diesen Kurs oder Elemets aus diesem Kurs in einem gesch\u00FCtzten Modus mit einem eingeschr\u00E4nken M\u00F6glichkeiten zu betreiben. @@ -18,7 +24,7 @@ mode.leadTime=Vorlaufzeit mode.name=Title mode.ips=Einschränkung auf IP Adressen mode.ips.list=Zulässige IP Adressen -mode.for.coach=Prüfundssettings auch bei Betreuer anwenden +mode.for.coach=Pr\u00FCfundssettings auch bei Betreuer anwenden mode.description=Beschreibung mode.safeexambrowser=Safe exam Browser verwenden mode.safeexambrowser.key=Browser Exam key @@ -33,7 +39,7 @@ table.header.name=Pr table.header.begin=Von table.header.end=Bis table.header.leadTime=Vorlauf -table.header.target=Für +table.header.target=F\u00FCr target.courseAndGroups=Teilnehmer aus kurs und Gruppen target.groups=Nur Gruppenteilnehmer target.course=Nur Kursteilnehmer \ No newline at end of file diff --git a/src/main/java/org/olat/group/manager/BusinessGroupRelationDAO.java b/src/main/java/org/olat/group/manager/BusinessGroupRelationDAO.java index 1aaa48a646a8a417cfd1fd57771759f8d3f466e4..2ab194a79680556f7b803530c12e72ae4781ba05 100644 --- a/src/main/java/org/olat/group/manager/BusinessGroupRelationDAO.java +++ b/src/main/java/org/olat/group/manager/BusinessGroupRelationDAO.java @@ -214,6 +214,29 @@ public class BusinessGroupRelationDAO { return members; } + public List<Long> getMemberKeys(List<? extends BusinessGroupRef> groups, String... roles) { + if(groups == null || groups.isEmpty()) return Collections.emptyList(); + + StringBuilder sb = new StringBuilder(); + sb.append("select membership.identity.key from ").append(BusinessGroupImpl.class.getName()).append(" as bgroup ") + .append(" inner join bgroup.baseGroup as baseGroup") + .append(" inner join baseGroup.members as membership") + .append(" where bgroup.key in (:businessGroupKeys) and membership.role in (:roles)"); + + List<String> roleList = GroupRoles.toList(roles); + List<Long> groupKeys = new ArrayList<>(groups.size()); + for(BusinessGroupRef group:groups) { + groupKeys.add(group.getKey()); + } + + List<Long> members = dbInstance.getCurrentEntityManager() + .createQuery(sb.toString(), Long.class) + .setParameter("businessGroupKeys", groupKeys) + .setParameter("roles", roleList) + .getResultList(); + return members; + } + public List<Identity> getMembersOrderByDate(BusinessGroupRef group, String... roles) { StringBuilder sb = new StringBuilder(); sb.append("select membership.identity from ").append(BusinessGroupImpl.class.getName()).append(" as bgroup ") diff --git a/src/main/java/org/olat/gui/control/OlatDmzTopNavController.java b/src/main/java/org/olat/gui/control/OlatDmzTopNavController.java index c0aa927c461b3e3644ff9c40288a6db7e11c4ee5..9ff13be45bfe6818a0d782f58fb2b328bd8ad4bc 100644 --- a/src/main/java/org/olat/gui/control/OlatDmzTopNavController.java +++ b/src/main/java/org/olat/gui/control/OlatDmzTopNavController.java @@ -29,6 +29,7 @@ import org.olat.core.commons.contextHelp.ContextHelpModule; import org.olat.core.commons.controllers.impressum.ImpressumDmzMainController; import org.olat.core.commons.controllers.impressum.ImpressumInformations; import org.olat.core.commons.controllers.impressum.ImpressumModule; +import org.olat.core.commons.fullWebApp.TopNavController; import org.olat.core.gui.UserRequest; import org.olat.core.gui.Windows; import org.olat.core.gui.components.Component; @@ -41,9 +42,10 @@ import org.olat.core.gui.control.WindowControl; import org.olat.core.gui.control.controller.BasicController; import org.olat.core.gui.control.creator.ControllerCreator; import org.olat.core.gui.control.generic.popup.PopupBrowserWindow; +import org.olat.core.id.OLATResourceable; import org.springframework.beans.factory.annotation.Autowired; -public class OlatDmzTopNavController extends BasicController { +public class OlatDmzTopNavController extends BasicController implements TopNavController { private static final Boolean contextHelpEnabled = Boolean.valueOf(ContextHelpModule.isContextHelpEnabled()); private Link impressumLink; @@ -79,6 +81,11 @@ public class OlatDmzTopNavController extends BasicController { putInitialPanel(vc); } + @Override + public void lockResource(OLATResourceable resource) { + // + } + @Override public void event(UserRequest ureq, Component source, Event event) { if (source == impressumLink) { diff --git a/src/main/java/org/olat/gui/control/OlatGuestTopNavController.java b/src/main/java/org/olat/gui/control/OlatGuestTopNavController.java index e55df675d8dc70e40bcaa0f9ad38304c9518b056..b935626b12d0088353736bf57fd9e5a11b39d5d8 100644 --- a/src/main/java/org/olat/gui/control/OlatGuestTopNavController.java +++ b/src/main/java/org/olat/gui/control/OlatGuestTopNavController.java @@ -29,6 +29,7 @@ import org.olat.basesecurity.AuthHelper; import org.olat.core.commons.controllers.impressum.ImpressumInformations; import org.olat.core.commons.controllers.impressum.ImpressumMainController; import org.olat.core.commons.controllers.impressum.ImpressumModule; +import org.olat.core.commons.fullWebApp.TopNavController; import org.olat.core.commons.fullWebApp.popup.BaseFullWebappPopupLayoutFactory; import org.olat.core.gui.UserRequest; import org.olat.core.gui.Windows; @@ -42,6 +43,7 @@ import org.olat.core.gui.control.WindowControl; import org.olat.core.gui.control.controller.BasicController; import org.olat.core.gui.control.creator.ControllerCreator; import org.olat.core.gui.control.generic.popup.PopupBrowserWindow; +import org.olat.core.id.OLATResourceable; import org.olat.course.CourseFactory; import org.olat.course.CourseModule; import org.springframework.beans.factory.annotation.Autowired; @@ -52,7 +54,7 @@ import org.springframework.beans.factory.annotation.Autowired; * * @author patrickb */ -public class OlatGuestTopNavController extends BasicController { +public class OlatGuestTopNavController extends BasicController implements TopNavController { private Link helpLink, loginLink, impressumLink; @@ -86,6 +88,11 @@ public class OlatGuestTopNavController extends BasicController { putInitialPanel(vc); } + + @Override + public void lockResource(OLATResourceable resource) { + // + } @Override public void event(UserRequest ureq, Component source, Event event) { diff --git a/src/main/java/org/olat/gui/control/OlatMinimalTopNavController.java b/src/main/java/org/olat/gui/control/OlatMinimalTopNavController.java index d6d2a37b72ab18e256ad49834f4acb26ada02e0e..fad0eafa4d38ec18aab2c216df0317e4940cea8c 100644 --- a/src/main/java/org/olat/gui/control/OlatMinimalTopNavController.java +++ b/src/main/java/org/olat/gui/control/OlatMinimalTopNavController.java @@ -24,6 +24,7 @@ */ package org.olat.gui.control; +import org.olat.core.commons.fullWebApp.TopNavController; import org.olat.core.dispatcher.impl.StaticMediaDispatcher; import org.olat.core.gui.UserRequest; import org.olat.core.gui.Windows; @@ -37,6 +38,7 @@ import org.olat.core.gui.control.WindowBackOffice; import org.olat.core.gui.control.WindowControl; import org.olat.core.gui.control.controller.BasicController; import org.olat.core.gui.media.RedirectMediaResource; +import org.olat.core.id.OLATResourceable; /** * Description:<br> @@ -46,7 +48,7 @@ import org.olat.core.gui.media.RedirectMediaResource; * Initial Date: 15.02.2008 <br> * @author patrickb */ -public class OlatMinimalTopNavController extends BasicController { +public class OlatMinimalTopNavController extends BasicController implements TopNavController { private final Link closeLink; @@ -58,17 +60,16 @@ public class OlatMinimalTopNavController extends BasicController { putInitialPanel(vc); } - /** - * @see org.olat.core.gui.control.DefaultController#doDispose() - */ @Override protected void doDispose() { // } + + @Override + public void lockResource(OLATResourceable resource) { + // + } - /** - * @see org.olat.core.gui.control.DefaultController#event(org.olat.core.gui.UserRequest, org.olat.core.gui.components.Component, org.olat.core.gui.control.Event) - */ @Override protected void event(UserRequest ureq, Component source, Event event) { if(source == closeLink){ diff --git a/src/main/java/org/olat/gui/control/OlatTopNavController.java b/src/main/java/org/olat/gui/control/OlatTopNavController.java index de3e4d95a1a89bf7eafcd0ab80b5ca0d65e5259c..8a3c91aac2f4263cca6fec4882f52da32d1f7d07 100644 --- a/src/main/java/org/olat/gui/control/OlatTopNavController.java +++ b/src/main/java/org/olat/gui/control/OlatTopNavController.java @@ -27,6 +27,7 @@ import java.util.Set; import org.olat.admin.user.tools.UserTool; import org.olat.admin.user.tools.UserToolExtension; import org.olat.admin.user.tools.UserToolsModule; +import org.olat.core.commons.fullWebApp.TopNavController; import org.olat.core.dispatcher.DispatcherModule; import org.olat.core.extensions.ExtManager; import org.olat.core.gui.UserRequest; @@ -39,6 +40,7 @@ import org.olat.core.gui.control.Disposable; 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.OLATResourceable; import org.olat.core.id.User; import org.olat.core.id.UserConstants; import org.olat.core.util.StringHelper; @@ -54,7 +56,7 @@ import org.springframework.beans.factory.annotation.Autowired; * @author srosse, stephane.rosse@frentix.com, http://www.frentix.com * */ -public class OlatTopNavController extends BasicController { +public class OlatTopNavController extends BasicController implements TopNavController { private Link loginLink; private VelocityContainer topNavVC; @@ -100,9 +102,15 @@ public class OlatTopNavController extends BasicController { topNavVC.contextPut("myMenuLabel", myMenuText); } + topNavVC.contextPut("locked", Boolean.FALSE); putInitialPanel(topNavVC); } + @Override + public void lockResource(OLATResourceable resource) { + topNavVC.contextPut("locked", Boolean.TRUE); + } + @Override public void event(UserRequest ureq, Component source, Event event) { if (source == loginLink) { diff --git a/src/main/java/org/olat/gui/control/UserToolsMenuController.java b/src/main/java/org/olat/gui/control/UserToolsMenuController.java index 61e48d9f253e36b0ad79823e3eebc997e74d6161..f4836cd9a3ddf600c0375aba79d659b3c7667257 100644 --- a/src/main/java/org/olat/gui/control/UserToolsMenuController.java +++ b/src/main/java/org/olat/gui/control/UserToolsMenuController.java @@ -29,6 +29,7 @@ import org.olat.admin.user.tools.UserToolCategory; import org.olat.admin.user.tools.UserToolExtension; import org.olat.admin.user.tools.UserToolsModule; import org.olat.basesecurity.AuthHelper; +import org.olat.core.commons.fullWebApp.TopNavController; import org.olat.core.gui.UserRequest; import org.olat.core.gui.components.Component; import org.olat.core.gui.components.velocity.VelocityContainer; @@ -36,6 +37,7 @@ import org.olat.core.gui.control.Disposable; 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.OLATResourceable; import org.olat.core.util.StringHelper; import org.olat.core.util.prefs.Preferences; import org.springframework.beans.factory.annotation.Autowired; @@ -46,7 +48,7 @@ import org.springframework.beans.factory.annotation.Autowired; * @author srosse, stephane.rosse@frentix.com, http://www.frentix.com * */ -public class UserToolsMenuController extends BasicController { +public class UserToolsMenuController extends BasicController implements TopNavController { private static final String ACTION_LOGOUT = "logout"; @@ -115,6 +117,12 @@ public class UserToolsMenuController extends BasicController { menuVC.contextPut("configs", configLinksName); menuVC.contextPut("systems", systemLinksName); menuVC.contextPut("searchs", searchLinksName); + menuVC.contextPut("locked", Boolean.FALSE); + } + + @Override + public void lockResource(OLATResourceable resource) { + menuVC.contextPut("locked", Boolean.TRUE); } @Override diff --git a/src/main/java/org/olat/gui/control/_content/menu.html b/src/main/java/org/olat/gui/control/_content/menu.html index 4bc8b3133f9021380338ae375736eb92e5246394..0e955e974788f2ad4c235be0500d25e346595f88 100644 --- a/src/main/java/org/olat/gui/control/_content/menu.html +++ b/src/main/java/org/olat/gui/control/_content/menu.html @@ -1,29 +1,31 @@ ## DOM replacement implemented via ID on UL element - bypass standard OO wrapper DIV <ul id="$r.getCId()" class="nav o_navbar-nav o_navbar-right o_sel_menu_tools"> - #foreach($search in $searchs) - <li>$r.render($search)</li> - #end - #if($personalTools && $personalTools.size() > 0) - <li role="presentation" class="dropdown-header">$r.translate("topnav.my.menu.tools")</li> - #foreach($personalTool in $personalTools) - <li>$r.render($personalTool)</li> + #if(!$locked) + #foreach($search in $searchs) + <li>$r.render($search)</li> #end - #end - #if($configs && $configs.size() > 0) - <li role="presentation" class="divider"></li> - <li role="presentation" class="dropdown-header">$r.translate("topnav.my.menu.configurations")</li> - #foreach($config in $configs) - <li>$r.render($config)</li> + #if($personalTools && $personalTools.size() > 0) + <li role="presentation" class="dropdown-header">$r.translate("topnav.my.menu.tools")</li> + #foreach($personalTool in $personalTools) + <li>$r.render($personalTool)</li> + #end #end - #end - #if($systems && $systems.size() > 0) - <li role="presentation" class="divider"></li> - <li role="presentation" class="dropdown-header">$r.translate("topnav.my.menu.systems")</li> - #foreach($system in $systems) - <li>$r.render($system)</li> + #if($configs && $configs.size() > 0) + <li role="presentation" class="divider"></li> + <li role="presentation" class="dropdown-header">$r.translate("topnav.my.menu.configurations")</li> + #foreach($config in $configs) + <li>$r.render($config)</li> + #end + #end + #if($systems && $systems.size() > 0) + <li role="presentation" class="divider"></li> + <li role="presentation" class="dropdown-header">$r.translate("topnav.my.menu.systems")</li> + #foreach($system in $systems) + <li>$r.render($system)</li> + #end #end + <li role="presentation" class="divider"></li> #end - <li role="presentation" class="divider"></li> <li> ## make logout link very basic without onClick handler in case javaScript is broken it is still possible to log out ## except for the onolatunload() method which must be executed to correctly finish SCORM modules (OLAT-6255) diff --git a/src/main/java/org/olat/gui/control/_content/topnav.html b/src/main/java/org/olat/gui/control/_content/topnav.html index 04cbd9a6e90b59b9bf0076db880e0a4336f27fe8..6d496be71440c341cadfe2c75c480686de291d01 100644 --- a/src/main/java/org/olat/gui/control/_content/topnav.html +++ b/src/main/java/org/olat/gui/control/_content/topnav.html @@ -1,7 +1,9 @@ <div id="$r.getCId()" class="o_navbar_tools"> <ul id="o_navbar_tools_permanent" class="nav o_navbar-nav o_navbar-right"> - #foreach($personalTool in $toolSet) - <li #if($personalTool.shortCutCssId) id="$personalTool.shortCutCssId" #end class="o_navbar_tool #if($personalTool.shortCutCssClass) $personalTool.shortCutCssClass #end">$r.render($personalTool.shortCutComponentName)</li> + #if(!$locked) + #foreach($personalTool in $toolSet) + <li #if($personalTool.shortCutCssId) id="$personalTool.shortCutCssId" #end class="o_navbar_tool #if($personalTool.shortCutCssClass) $personalTool.shortCutCssClass #end">$r.render($personalTool.shortCutComponentName)</li> + #end #end #if (!$isGuest && !$isInvitee) <li id="o_navbar_my_menu" class="o_portrait"> diff --git a/src/main/java/org/olat/login/AfterLoginInterceptionController.java b/src/main/java/org/olat/login/AfterLoginInterceptionController.java index 63533746dee055b34ed480880a6597bcd99d27db..3d1e30d821e97ce9af635bfecaf6bc7a56e8439f 100644 --- a/src/main/java/org/olat/login/AfterLoginInterceptionController.java +++ b/src/main/java/org/olat/login/AfterLoginInterceptionController.java @@ -64,7 +64,6 @@ public class AfterLoginInterceptionController extends BasicController { private List<Map<String, Object>> aftctrls; private int actualCtrNr; private List<Property> ctrlPropList; - private PropertyManager pm; private boolean actualForceUser; // must match with keys in XML private static final String CONTROLLER_KEY = "controller"; @@ -76,6 +75,8 @@ public class AfterLoginInterceptionController extends BasicController { private static final String PROPERTY_CAT = "afterLogin"; + @Autowired + private PropertyManager pm; @Autowired private AfterLoginInterceptionManager aLIM; @@ -95,7 +96,6 @@ public class AfterLoginInterceptionController extends BasicController { // load all UserProps concerning afterlogin/runOnce workflow => only 1 // db-call for all props - pm = PropertyManager.getInstance(); ctrlPropList = pm.listProperties(ureq.getIdentity(), null, null, null, PROPERTY_CAT, null); // loop over possible controllers and check if user already did it before configured timeout diff --git a/src/main/java/org/olat/login/AuthBFWCParts.java b/src/main/java/org/olat/login/AuthBFWCParts.java index b312464d14f44ed0d2828823490f24be382ca4f0..11726e0d28054d1bd1bbad3db1b4ec45afe1ef8c 100644 --- a/src/main/java/org/olat/login/AuthBFWCParts.java +++ b/src/main/java/org/olat/login/AuthBFWCParts.java @@ -29,6 +29,7 @@ import java.util.List; import org.olat.core.CoreSpringFactory; import org.olat.core.commons.fullWebApp.BaseFullWebappControllerParts; +import org.olat.core.commons.fullWebApp.TopNavController; import org.olat.core.gui.UserRequest; import org.olat.core.gui.control.Controller; import org.olat.core.gui.control.WindowControl; @@ -80,14 +81,14 @@ public class AuthBFWCParts implements BaseFullWebappControllerParts { * @see org.olat.core.commons.fullWebApp.BaseFullWebappControllerParts#createTopNavController(org.olat.core.gui.UserRequest, org.olat.core.gui.control.WindowControl) */ @Override - public Controller createTopNavController(UserRequest ureq, WindowControl wControl) { + public TopNavController createTopNavController(UserRequest ureq, WindowControl wControl) { Controller topnavCtr = null; // ----------- topnav, optional (e.g. for imprint, logout) ------------------ if (CoreSpringFactory.containsBean("fullWebApp.TopNavControllerCreator")) { ControllerCreator topnavControllerCreator = (ControllerCreator) CoreSpringFactory.getBean("fullWebApp.TopNavControllerCreator"); topnavCtr = topnavControllerCreator.createController(ureq, wControl); } - return topnavCtr; + return (TopNavController)topnavCtr; } /** diff --git a/src/main/java/org/olat/login/DmzBFWCParts.java b/src/main/java/org/olat/login/DmzBFWCParts.java index 28195534b465a8fac3c7384059a7afd308874a03..5f04f4447d714562f9c648a2d79c147ffee63a3a 100644 --- a/src/main/java/org/olat/login/DmzBFWCParts.java +++ b/src/main/java/org/olat/login/DmzBFWCParts.java @@ -28,6 +28,7 @@ import java.util.List; import org.olat.core.CoreSpringFactory; import org.olat.core.commons.fullWebApp.BaseFullWebappControllerParts; +import org.olat.core.commons.fullWebApp.TopNavController; import org.olat.core.gui.UserRequest; import org.olat.core.gui.control.Controller; import org.olat.core.gui.control.WindowControl; @@ -36,10 +37,6 @@ import org.olat.core.gui.control.navigation.SiteInstance; import org.olat.gui.control.OlatFooterController; /** - * Description:<br> - * TODO: patrickb Class Description for DmzBFWCParts - * - * <P> * Initial Date: 29.01.2008 <br> * @author patrickb */ @@ -48,9 +45,7 @@ public class DmzBFWCParts implements BaseFullWebappControllerParts { private ControllerCreator contentControllerCreator; private boolean showTopNav = true; // default - /** - * @see org.olat.core.commons.fullWebApp.BaseFullWebappControllerParts#createFooterController(org.olat.core.gui.UserRequest, org.olat.core.gui.control.WindowControl) - */ + @Override public Controller createFooterController(UserRequest ureq, WindowControl wControl) { Controller footerCtr = null; // ----------- footer, optional (e.g. for copyright, powered by) ------------------ @@ -63,9 +58,7 @@ public class DmzBFWCParts implements BaseFullWebappControllerParts { return footerCtr; } - /** - * @see org.olat.core.commons.fullWebApp.BaseFullWebappControllerParts#createHeaderController(org.olat.core.gui.UserRequest, org.olat.core.gui.control.WindowControl) - */ + @Override public Controller createHeaderController(UserRequest ureq, WindowControl wControl) { Controller headerCtr = null; // ----------- header, optional (e.g. for logo, advertising ) ------------------ @@ -76,15 +69,13 @@ public class DmzBFWCParts implements BaseFullWebappControllerParts { return headerCtr; } - /** - * @see org.olat.core.commons.fullWebApp.BaseFullWebappControllerParts#createTopNavController(org.olat.core.gui.UserRequest, org.olat.core.gui.control.WindowControl) - */ - public Controller createTopNavController(UserRequest ureq, WindowControl wControl) { + @Override + public TopNavController createTopNavController(UserRequest ureq, WindowControl wControl) { if (showTopNav) { - Controller topNavCtr = null; + TopNavController topNavCtr = null; if (CoreSpringFactory.containsBean("fullWebApp.DMZTopNavControllerCreator")) { ControllerCreator headerControllerCreator = (ControllerCreator) CoreSpringFactory.getBean("fullWebApp.DMZTopNavControllerCreator"); - topNavCtr = headerControllerCreator.createController(ureq, wControl); + topNavCtr = (TopNavController)headerControllerCreator.createController(ureq, wControl); } return topNavCtr; } else { @@ -95,14 +86,14 @@ public class DmzBFWCParts implements BaseFullWebappControllerParts { public void setContentControllerCreator(ControllerCreator contentControllerCreator){ this.contentControllerCreator = contentControllerCreator; } - + + @Override public Controller getContentController(UserRequest ureq, WindowControl wControl) { return contentControllerCreator.createController(ureq, wControl); } - /** - * @see org.olat.core.commons.fullWebApp.BaseFullWebappControllerParts#getSiteInstances(org.olat.core.gui.UserRequest, org.olat.core.gui.control.WindowControl) - */ + + @Override public List<SiteInstance> getSiteInstances(UserRequest ureq, WindowControl wControl) { return null; } @@ -116,5 +107,4 @@ public class DmzBFWCParts implements BaseFullWebappControllerParts { public void showTopNav(boolean showTopNavController) { this.showTopNav = showTopNavController ; } - -} +} \ No newline at end of file diff --git a/src/main/java/org/olat/login/GuestBFWCParts.java b/src/main/java/org/olat/login/GuestBFWCParts.java index ebab38669337533d64cf3d87189c756252713acb..adc2be7d853d638181e3622845126fea9e07a381 100644 --- a/src/main/java/org/olat/login/GuestBFWCParts.java +++ b/src/main/java/org/olat/login/GuestBFWCParts.java @@ -29,6 +29,7 @@ import java.util.List; import org.olat.core.CoreSpringFactory; import org.olat.core.commons.fullWebApp.BaseFullWebappControllerParts; +import org.olat.core.commons.fullWebApp.TopNavController; import org.olat.core.gui.UserRequest; import org.olat.core.gui.control.Controller; import org.olat.core.gui.control.WindowControl; @@ -84,12 +85,12 @@ public class GuestBFWCParts implements BaseFullWebappControllerParts { * @see org.olat.core.commons.fullWebApp.BaseFullWebappControllerParts#createTopNavController(org.olat.core.gui.UserRequest, org.olat.core.gui.control.WindowControl) */ @Override - public Controller createTopNavController(UserRequest ureq, WindowControl wControl) { + public TopNavController createTopNavController(UserRequest ureq, WindowControl wControl) { if (showTopNav) { - Controller topNavCtr = null; + TopNavController topNavCtr = null; if (CoreSpringFactory.containsBean("fullWebApp.GuestTopNavControllerCreator")) { ControllerCreator headerControllerCreator = (ControllerCreator) CoreSpringFactory.getBean("fullWebApp.GuestTopNavControllerCreator"); - topNavCtr = headerControllerCreator.createController(ureq, wControl); + topNavCtr = (TopNavController)headerControllerCreator.createController(ureq, wControl); } return topNavCtr; } else { diff --git a/src/main/java/org/olat/repository/manager/RepositoryEntryRelationDAO.java b/src/main/java/org/olat/repository/manager/RepositoryEntryRelationDAO.java index 3b11b3d0ed5cde7f9886dda16ff08f838ce2dfe7..0ca15dd2eaa1f6afc22c90c843ac3299e2c24ba1 100644 --- a/src/main/java/org/olat/repository/manager/RepositoryEntryRelationDAO.java +++ b/src/main/java/org/olat/repository/manager/RepositoryEntryRelationDAO.java @@ -288,6 +288,35 @@ public class RepositoryEntryRelationDAO { return query.getResultList(); } + public List<Long> getMemberKeys(RepositoryEntryRef re, RepositoryEntryRelationType type, String... roles) { + List<String> roleList = GroupRoles.toList(roles); + + String def; + switch(type) { + case defaultGroup: def = " on relGroup.defaultGroup=true"; break; + case notDefaultGroup: def = " on relGroup.defaultGroup=false"; break; + default: def = ""; + } + + StringBuilder sb = new StringBuilder(); + sb.append("select members.identity.key from ").append(RepositoryEntry.class.getName()).append(" as v") + .append(" inner join v.groups as relGroup").append(def) + .append(" inner join relGroup.group as baseGroup") + .append(" inner join baseGroup.members as members") + .append(" where v.key=:repoKey"); + if(roleList.size() > 0) { + sb.append(" and members.role in (:roles)"); + } + + TypedQuery<Long> query = dbInstance.getCurrentEntityManager() + .createQuery(sb.toString(), Long.class) + .setParameter("repoKey", re.getKey()); + if(roleList.size() > 0) { + query.setParameter("roles", roleList); + } + return query.getResultList(); + } + public boolean removeMembers(RepositoryEntry re, List<Identity> members) { Group group = getDefaultGroup(re); for(Identity member:members) { diff --git a/src/test/java/org/olat/course/assessment/manager/AssessmentModeManagerTest.java b/src/test/java/org/olat/course/assessment/manager/AssessmentModeManagerTest.java index 144e01d6fb47a9262cf0a2e642b68e28df22bbb2..6eab9fe96a562110c796aea38b61332530e2010d 100644 --- a/src/test/java/org/olat/course/assessment/manager/AssessmentModeManagerTest.java +++ b/src/test/java/org/olat/course/assessment/manager/AssessmentModeManagerTest.java @@ -101,7 +101,7 @@ public class AssessmentModeManagerTest extends OlatTestCase { Assert.assertNotNull(savedMode.getLastModified()); //reload and check - AssessmentMode reloadedMode = assessmentModeMgr.loadById(savedMode.getKey()); + AssessmentMode reloadedMode = assessmentModeMgr.getAssessmentModeById(savedMode.getKey()); Assert.assertNotNull(reloadedMode); Assert.assertEquals(savedMode.getKey(), reloadedMode.getKey()); Assert.assertNotNull(reloadedMode.getCreationDate()); @@ -142,7 +142,7 @@ public class AssessmentModeManagerTest extends OlatTestCase { dbInstance.commitAndCloseSession(); Assert.assertNotNull(savedMode); - List<AssessmentMode> assessmentModes = assessmentModeMgr.loadAssessmentMode(entry); + List<AssessmentMode> assessmentModes = assessmentModeMgr.getAssessmentModeFor(entry); Assert.assertNotNull(assessmentModes); Assert.assertEquals(1, assessmentModes.size()); Assert.assertEquals(savedMode, assessmentModes.get(0)); @@ -164,7 +164,7 @@ public class AssessmentModeManagerTest extends OlatTestCase { AssessmentMode savedMode = assessmentModeMgr.save(mode); dbInstance.commitAndCloseSession(); - AssessmentMode reloadedMode = assessmentModeMgr.loadById(mode.getKey()); + AssessmentMode reloadedMode = assessmentModeMgr.getAssessmentModeById(mode.getKey()); Assert.assertEquals(mode, reloadedMode); Assert.assertEquals(savedMode, reloadedMode); Assert.assertNotNull(reloadedMode.getGroups()); @@ -182,7 +182,7 @@ public class AssessmentModeManagerTest extends OlatTestCase { Assert.assertNotNull(mode); //check - List<AssessmentMode> currentModes = assessmentModeMgr.loadAssessmentMode(entry); + List<AssessmentMode> currentModes = assessmentModeMgr.getAssessmentModeFor(entry); Assert.assertNotNull(currentModes); Assert.assertEquals(1, currentModes.size()); Assert.assertTrue(currentModes.contains(mode)); @@ -197,7 +197,7 @@ public class AssessmentModeManagerTest extends OlatTestCase { Assert.assertNotNull(mode); //check - List<AssessmentMode> currentModes = assessmentModeMgr.loadCurrentAssessmentModes(); + List<AssessmentMode> currentModes = assessmentModeMgr.getCurrentAssessmentModes(); Assert.assertNotNull(currentModes); Assert.assertFalse(currentModes.isEmpty()); Assert.assertTrue(currentModes.contains(mode)); @@ -229,18 +229,18 @@ public class AssessmentModeManagerTest extends OlatTestCase { Assert.assertNotNull(mode); //check participant - List<AssessmentMode> currentModes = assessmentModeMgr.loadAssessmentModeFor(participant); + List<AssessmentMode> currentModes = assessmentModeMgr.getAssessmentModeFor(participant); Assert.assertNotNull(currentModes); Assert.assertEquals(1, currentModes.size()); Assert.assertTrue(currentModes.contains(mode)); //check coach - List<AssessmentMode> currentCoachModes = assessmentModeMgr.loadAssessmentModeFor(coach); + List<AssessmentMode> currentCoachModes = assessmentModeMgr.getAssessmentModeFor(coach); Assert.assertNotNull(currentCoachModes); Assert.assertTrue(currentCoachModes.isEmpty()); //check author - List<AssessmentMode> currentAuthorModes = assessmentModeMgr.loadAssessmentModeFor(author); + List<AssessmentMode> currentAuthorModes = assessmentModeMgr.getAssessmentModeFor(author); Assert.assertNotNull(currentAuthorModes); Assert.assertTrue(currentAuthorModes.isEmpty()); } @@ -272,19 +272,19 @@ public class AssessmentModeManagerTest extends OlatTestCase { Assert.assertNotNull(mode); //check participant - List<AssessmentMode> currentModes = assessmentModeMgr.loadAssessmentModeFor(participant); + List<AssessmentMode> currentModes = assessmentModeMgr.getAssessmentModeFor(participant); Assert.assertNotNull(currentModes); Assert.assertEquals(1, currentModes.size()); Assert.assertTrue(currentModes.contains(mode)); //check coach - List<AssessmentMode> currentCoachModes = assessmentModeMgr.loadAssessmentModeFor(coach); + List<AssessmentMode> currentCoachModes = assessmentModeMgr.getAssessmentModeFor(coach); Assert.assertNotNull(currentCoachModes); Assert.assertEquals(1, currentCoachModes.size()); Assert.assertTrue(currentCoachModes.contains(mode)); //check author - List<AssessmentMode> currentAuthorModes = assessmentModeMgr.loadAssessmentModeFor(author); + List<AssessmentMode> currentAuthorModes = assessmentModeMgr.getAssessmentModeFor(author); Assert.assertNotNull(currentAuthorModes); Assert.assertTrue(currentAuthorModes.isEmpty()); } @@ -307,18 +307,18 @@ public class AssessmentModeManagerTest extends OlatTestCase { Assert.assertNotNull(mode); //check participant - List<AssessmentMode> currentModes = assessmentModeMgr.loadAssessmentModeFor(participant); + List<AssessmentMode> currentModes = assessmentModeMgr.getAssessmentModeFor(participant); Assert.assertNotNull(currentModes); Assert.assertEquals(1, currentModes.size()); Assert.assertTrue(currentModes.contains(mode)); //check coach - List<AssessmentMode> currentCoachModes = assessmentModeMgr.loadAssessmentModeFor(coach); + List<AssessmentMode> currentCoachModes = assessmentModeMgr.getAssessmentModeFor(coach); Assert.assertNotNull(currentCoachModes); Assert.assertTrue(currentCoachModes.isEmpty()); //check author - List<AssessmentMode> currentAuthorModes = assessmentModeMgr.loadAssessmentModeFor(author); + List<AssessmentMode> currentAuthorModes = assessmentModeMgr.getAssessmentModeFor(author); Assert.assertNotNull(currentAuthorModes); Assert.assertTrue(currentAuthorModes.isEmpty()); } @@ -341,19 +341,19 @@ public class AssessmentModeManagerTest extends OlatTestCase { Assert.assertNotNull(mode); //check participant - List<AssessmentMode> currentModes = assessmentModeMgr.loadAssessmentModeFor(participant); + List<AssessmentMode> currentModes = assessmentModeMgr.getAssessmentModeFor(participant); Assert.assertNotNull(currentModes); Assert.assertEquals(1, currentModes.size()); Assert.assertTrue(currentModes.contains(mode)); //check coach - List<AssessmentMode> currentCoachModes = assessmentModeMgr.loadAssessmentModeFor(coach); + List<AssessmentMode> currentCoachModes = assessmentModeMgr.getAssessmentModeFor(coach); Assert.assertNotNull(currentCoachModes); Assert.assertEquals(1, currentCoachModes.size()); Assert.assertTrue(currentCoachModes.contains(mode)); //check author - List<AssessmentMode> currentAuthorModes = assessmentModeMgr.loadAssessmentModeFor(author); + List<AssessmentMode> currentAuthorModes = assessmentModeMgr.getAssessmentModeFor(author); Assert.assertNotNull(currentAuthorModes); Assert.assertTrue(currentAuthorModes.isEmpty()); }