diff --git a/src/main/java/org/olat/commons/info/ui/InfoDisplayController.java b/src/main/java/org/olat/commons/info/ui/InfoDisplayController.java index 101f9c47e1c5ea6ec37859df925d03af95a89626..cdf14d6a1aa0b664b1dece15dfab29264b330084 100644 --- a/src/main/java/org/olat/commons/info/ui/InfoDisplayController.java +++ b/src/main/java/org/olat/commons/info/ui/InfoDisplayController.java @@ -75,9 +75,7 @@ import org.olat.core.util.resource.OresHelper; import org.olat.core.util.vfs.VFSConstants; import org.olat.core.util.vfs.VFSLeaf; import org.olat.core.util.vfs.VFSMediaResource; -import org.olat.course.nodes.info.InfoCourseNodeConfiguration; import org.olat.group.BusinessGroup; -import org.olat.modules.ModuleConfiguration; import org.olat.user.UserManager; import org.olat.util.logging.activity.LoggingResourceable; import org.springframework.beans.factory.annotation.Autowired; @@ -115,7 +113,6 @@ public class InfoDisplayController extends FormBasicController { private int maxResults = 0; private int maxResultsConfig = 0; - private int duration = -1; private Date after = null; private Date afterConfig = null; @@ -148,16 +145,16 @@ public class InfoDisplayController extends FormBasicController { loadMessages(); } - public InfoDisplayController(UserRequest ureq, WindowControl wControl, ModuleConfiguration config, + public InfoDisplayController(UserRequest ureq, WindowControl wControl, int maxResults, int duration, InfoSecurityCallback secCallback, OLATResourceable ores, String resSubPath, String businessPath) { super(ureq, wControl, "display"); this.secCallback = secCallback; this.ores = ores; this.resSubPath = resSubPath; this.businessPath = businessPath; + this.maxResults = maxResults; + this.maxResultsConfig = maxResults; - maxResults = maxResultsConfig = getConfigValue(config, InfoCourseNodeConfiguration.CONFIG_LENGTH, 10); - duration = getConfigValue(config, InfoCourseNodeConfiguration.CONFIG_DURATION, 90); thumbnailMapper = registerCacheableMapper(ureq, "InfoMessagesThumbnail", new ThumbnailMapper()); attachmentMapper = registerCacheableMapper(ureq, "InfoMessages", new AttachmentMapper()); @@ -189,19 +186,7 @@ public class InfoDisplayController extends FormBasicController { // now load with configuration loadMessages(); } - - private int getConfigValue(ModuleConfiguration config, String key, int def) { - String durationStr = (String)config.get(key); - if("\u221E".equals(durationStr)) { - return -1; - } else if(StringHelper.containsNonWhitespace(durationStr)) { - try { - return Integer.parseInt(durationStr); - } catch(NumberFormatException e) { /* fallback to default */ } - } - return def; - } - + public List<SendMailOption> getSendMailOptions() { return sendMailOptions; } diff --git a/src/main/java/org/olat/core/logging/activity/ActionObject.java b/src/main/java/org/olat/core/logging/activity/ActionObject.java index 08d3d67f33615349901e9e7a17d9344420ea6d7a..b948478af4c5561a2fa7ccc4244bf426831781de 100644 --- a/src/main/java/org/olat/core/logging/activity/ActionObject.java +++ b/src/main/java/org/olat/core/logging/activity/ActionObject.java @@ -72,6 +72,7 @@ public enum ActionObject { node, owner, participant, + participantList, portfolioartefact, portfoliomap, portfoliomedia, diff --git a/src/main/java/org/olat/core/logging/activity/LearningResourceLoggingAction.java b/src/main/java/org/olat/core/logging/activity/LearningResourceLoggingAction.java index 07b8d608dda0c9a8a1cc245665470120918de20b..ba5d8cbb3f3e6142a5fd1ed4cc4210970df5bfbb 100644 --- a/src/main/java/org/olat/core/logging/activity/LearningResourceLoggingAction.java +++ b/src/main/java/org/olat/core/logging/activity/LearningResourceLoggingAction.java @@ -95,6 +95,18 @@ public class LearningResourceLoggingAction extends BaseLoggingAction { new LearningResourceLoggingAction(ActionType.admin, CrudAction.update, ActionVerb.add, ActionObject.search).setTypeList(LEARNING_RESOURCE_OPEN_CLOSE_LIST); public static final ILoggingAction REPOSITORY_ENTRY_PROPERTIES_COURSESEARCH_DISABLED = new LearningResourceLoggingAction(ActionType.admin, CrudAction.update, ActionVerb.remove, ActionObject.search).setTypeList(LEARNING_RESOURCE_OPEN_CLOSE_LIST); + public static final ILoggingAction REPOSITORY_ENTRY_PROPERTIES_PARTICIPANTLIST_ENABLED = + new LearningResourceLoggingAction(ActionType.admin, CrudAction.update, ActionVerb.add, ActionObject.participantList).setTypeList(LEARNING_RESOURCE_OPEN_CLOSE_LIST); + public static final ILoggingAction REPOSITORY_ENTRY_PROPERTIES_PARTICIPANTLIST_DISABLED = + new LearningResourceLoggingAction(ActionType.admin, CrudAction.update, ActionVerb.remove, ActionObject.participantList).setTypeList(LEARNING_RESOURCE_OPEN_CLOSE_LIST); + public static final ILoggingAction REPOSITORY_ENTRY_PROPERTIES_PARTICIPANTINFO_ENABLED = + new LearningResourceLoggingAction(ActionType.admin, CrudAction.update, ActionVerb.add, ActionObject.infomessage).setTypeList(LEARNING_RESOURCE_OPEN_CLOSE_LIST); + public static final ILoggingAction REPOSITORY_ENTRY_PROPERTIES_PARTICIPANTINFO_DISABLED = + new LearningResourceLoggingAction(ActionType.admin, CrudAction.update, ActionVerb.remove, ActionObject.infomessage).setTypeList(LEARNING_RESOURCE_OPEN_CLOSE_LIST); + public static final ILoggingAction REPOSITORY_ENTRY_PROPERTIES_EMAIL_ENABLED = + new LearningResourceLoggingAction(ActionType.admin, CrudAction.update, ActionVerb.add, ActionObject.mail).setTypeList(LEARNING_RESOURCE_OPEN_CLOSE_LIST); + public static final ILoggingAction REPOSITORY_ENTRY_PROPERTIES_EMAIL_DISABLED = + new LearningResourceLoggingAction(ActionType.admin, CrudAction.update, ActionVerb.remove, ActionObject.mail).setTypeList(LEARNING_RESOURCE_OPEN_CLOSE_LIST); public static final ILoggingAction REPOSITORY_ENTRY_PROPERTIES_GLOSSARY_ENABLED = new LearningResourceLoggingAction(ActionType.admin, CrudAction.update, ActionVerb.add, ActionObject.glossar).setTypeList(LEARNING_RESOURCE_OPEN_CLOSE_LIST); public static final ILoggingAction REPOSITORY_ENTRY_PROPERTIES_GLOSSARY_DISABLED = @@ -169,6 +181,7 @@ public class LearningResourceLoggingAction extends BaseLoggingAction { * @see BaseLoggingAction#BaseLoggingAction(boolean, CrudAction, ActionVerb, String) * @deprecated */ + @Deprecated LearningResourceLoggingAction(ActionType resourceActionType, CrudAction action, ActionVerb actionVerb, String actionObject) { super(resourceActionType, action, actionVerb, actionObject); } diff --git a/src/main/java/org/olat/course/config/CourseConfig.java b/src/main/java/org/olat/course/config/CourseConfig.java index bb14583ccad99677c98c844f41a4029a62c5ebf0..9e059823e5a7735e2af11307d92e731de907ffba 100644 --- a/src/main/java/org/olat/course/config/CourseConfig.java +++ b/src/main/java/org/olat/course/config/CourseConfig.java @@ -72,26 +72,12 @@ public class CourseConfig implements Serializable, Cloneable { /** * current config file version */ - private static final transient int CURRENTVERSION = 14; - /** - * Log levels - */ + private static final transient int CURRENTVERSION = 15; + public static final transient String KEY_LOGLEVEL_ADMIN = "LOGLEVELADMIN"; - /** - * Log levels - */ public static final transient String KEY_LOGLEVEL_USER = "LOGLEVELUSER"; - /** - * Log levels - */ public static final transient String KEY_LOGLEVEL_STATISTIC = "LOGLEVELSTAT"; - /** - * Chat enabled boolean - */ - public static final transient String KEY_CHAT_ENABLED = "COURSE_CHAT_ENABLED"; - /** - * efficency statement - */ + public static final transient String KEY_EFFICENCY_ENABLED = "KEY_EFFICENCY_ENABLED"; public static final transient String CERTIFICATE_AUTO_ENABLED = "CERTIFICATE_AUTO"; public static final transient String CERTIFICATE_MANUAL_ENABLED = "CERTIFICATE_MANUAL"; @@ -103,47 +89,24 @@ public class CourseConfig implements Serializable, Cloneable { public static final transient String RECERTIFICATION_TIMELAPSE = "RECERTIFICATION_TIMELAPSE"; public static final transient String RECERTIFICATION_TIMELAPSE_UNIT = "RECERTIFICATION_TIMELAPSE_UNIT"; - /** - * The menu is enabled by default - */ public static final transient String MENU_ENABLED = "MENU_ENABLED"; - /** - * The toolbar is enabled by default - */ public static final transient String TOOLBAR_ENABLED = "TOOLBAR_ENABLED"; - /** - * The bread crumb is enabled by default - */ public static final transient String BREADCRUMB_ENABLED = "BREADCRUMB_ENABLED"; - /** - * The course search is enabled by default - */ + public static final transient String COURSESEARCH_ENABLED = "COURSESEARCH_ENABLED"; - /** - * course calendar - */ + public static final transient String KEY_CHAT_ENABLED = "COURSE_CHAT_ENABLED"; + public static final transient String PARTICIPANT_LIST_ENABLED = "PARTICIPANT_LIST_ENABLED"; + public static final transient String PARTICIPANT_INFO_ENABLED = "PARTICIPANT_INFO_ENABLED"; + public static final transient String EMAIL_ENABLED = "EMAIL_ENABLED"; public static final transient String KEY_CALENDAR_ENABLED = "KEY_CALENDAR_ENABLED"; - /** - * course glossary in toolbar enabled - */ public static final transient String KEY_GLOSSARY_ENABLED = "KEY_GLOSSARY_ENABLED"; - /** - * course glossary - */ public static final transient String KEY_GLOSSARY_SOFTKEY = "KEY_GLOSSARY_SOFTKEY"; - /** - * - */ public static final transient String KEY_CSS_FILEREF = "CSS_FILEREF"; - /** - * - */ + public static final transient String KEY_SHAREDFOLDER_SOFTKEY = "SHAREDFOLDER_SOFTKEY"; - /** - * - */ public static final transient String KEY_SHAREDFOLDER_READONLY = "SHAREDFOLDER_RO"; + /** * current key set */ @@ -156,18 +119,22 @@ public class CourseConfig implements Serializable, Cloneable { * holds the configuration */ private Map<String,Object> configuration = new Hashtable<>(); - + public CourseConfig() { - // empty, for XSTream + // empty, for XSTream } - + /** * @return version of this loaded/created instance */ public int getVersion() { return version; } - + + public void setVersion(int version) { + this.version = version; + } + /** * initialize with default values */ @@ -190,11 +157,13 @@ public class CourseConfig implements Serializable, Cloneable { configuration.remove(KEY_LOGLEVEL_USER); configuration.remove(KEY_LOGLEVEL_STATISTIC); - configuration.put(MENU_ENABLED, Boolean.TRUE); configuration.put(TOOLBAR_ENABLED, Boolean.TRUE); configuration.put(COURSESEARCH_ENABLED, Boolean.TRUE); + configuration.put(PARTICIPANT_LIST_ENABLED, Boolean.FALSE); + configuration.put(PARTICIPANT_INFO_ENABLED, Boolean.FALSE); + configuration.put(EMAIL_ENABLED, Boolean.FALSE); this.version = CURRENTVERSION; } @@ -213,47 +182,41 @@ public class CourseConfig implements Serializable, Cloneable { public boolean resolveVersionIssues() { boolean versionChanged = false; if (version < CURRENTVERSION) { - // from version 1 -> 2 if (version == 1) { this.version = 2; } - // from version 2 -> 3 + if (version == 2) { - // add the new key if (!configuration.containsKey(KEY_CHAT_ENABLED)) configuration.put(KEY_CHAT_ENABLED, Boolean.TRUE); this.version = 3; } - // from version 3 -> 4 + if (version == 3) { - // add the new key if (!configuration.containsKey(KEY_CSS_FILEREF)) configuration.put(KEY_CSS_FILEREF, VALUE_EMPTY_CSS_FILEREF); this.version = 4; } - // from version 4 -> 5 + if (version == 4) { - // add the new key if (!configuration.containsKey(KEY_SHAREDFOLDER_SOFTKEY)) configuration.put(KEY_SHAREDFOLDER_SOFTKEY, VALUE_EMPTY_SHAREDFOLDER_SOFTKEY); this.version = 5; } - // from version 5 -> 6 + if (version == 5) { - // add the new key if (!configuration.containsKey(KEY_EFFICENCY_ENABLED)) configuration.put(KEY_EFFICENCY_ENABLED, Boolean.FALSE); this.version = 6; } - // from version 6 -> 7 + if (version == 6) { - // add the new key if (!configuration.containsKey(KEY_CALENDAR_ENABLED)) configuration.put(KEY_CALENDAR_ENABLED, Boolean.TRUE); this.version = 7; } - // from version 7 -> 8 + if (version == 7) { // glossary configuration has been added. no default values needed this.version = 8; } - // from version 8 -> 9 + if (version == 8) { if (configuration.containsKey(KEY_LOGLEVEL_ADMIN)) configuration.remove(KEY_LOGLEVEL_ADMIN); if (configuration.containsKey(KEY_LOGLEVEL_USER)) configuration.remove(KEY_LOGLEVEL_USER); @@ -280,7 +243,7 @@ public class CourseConfig implements Serializable, Cloneable { if (!configuration.containsKey(COURSESEARCH_ENABLED)) configuration.put(COURSESEARCH_ENABLED, Boolean.FALSE); this.version = 12; } - + if (version == 12) { if (!configuration.containsKey(BREADCRUMB_ENABLED)) configuration.put(BREADCRUMB_ENABLED, Boolean.TRUE); this.version = 13; @@ -293,6 +256,14 @@ public class CourseConfig implements Serializable, Cloneable { this.version = 14; } + + if (version == 14) { + if (!configuration.containsKey(PARTICIPANT_LIST_ENABLED)) configuration.put(PARTICIPANT_LIST_ENABLED, Boolean.FALSE); + if (!configuration.containsKey(PARTICIPANT_INFO_ENABLED)) configuration.put(PARTICIPANT_INFO_ENABLED, Boolean.FALSE); + if (!configuration.containsKey(EMAIL_ENABLED)) configuration.put(EMAIL_ENABLED, Boolean.FALSE); + + this.version = 15; + } /* @@ -324,37 +295,24 @@ public class CourseConfig implements Serializable, Cloneable { return versionChanged; } - /** - * @return if chat is enabled - */ public boolean isChatEnabled() { Boolean bool = (Boolean) configuration.get(KEY_CHAT_ENABLED); return bool != null && bool.booleanValue(); } - /** - * @param b - */ public void setChatIsEnabled(boolean b) { configuration.put(KEY_CHAT_ENABLED, Boolean.valueOf(b)); } - /** - * @return if chat is enabled - */ public boolean isGlossaryEnabled() { Boolean bool = (Boolean) configuration.get(KEY_GLOSSARY_ENABLED); return bool != null && bool.booleanValue(); } - /** - * @param b - */ public void setGlossaryIsEnabled(boolean b) { configuration.put(KEY_GLOSSARY_ENABLED, Boolean.valueOf(b)); } - /** * set the course layout by adding a reference to a css file, or disabling * custom layout by adding the empty css fileref @@ -396,23 +354,14 @@ public class CourseConfig implements Serializable, Cloneable { return (String) configuration.get(KEY_GLOSSARY_SOFTKEY); } - /** - * @return boolean - */ public boolean hasGlossary() { return (getGlossarySoftKey() != null); } - /** - * @return boolean - */ public boolean hasCustomCourseCSS() { return !(VALUE_EMPTY_CSS_FILEREF.equals(getCssLayoutRef())); } - /** - * @param softkey - */ public void setSharedFolderSoftkey(String softkey) { if(softkey == null) { configuration.put(KEY_SHAREDFOLDER_SOFTKEY, VALUE_EMPTY_SHAREDFOLDER_SOFTKEY); @@ -421,16 +370,10 @@ public class CourseConfig implements Serializable, Cloneable { } } - /** - * @return softkey - */ public String getSharedFolderSoftkey() { return (String) configuration.get(KEY_SHAREDFOLDER_SOFTKEY); } - /** - * @return boolean - */ public boolean hasCustomSharedFolder() { return !(VALUE_EMPTY_SHAREDFOLDER_SOFTKEY.equals(getSharedFolderSoftkey())); } @@ -444,25 +387,15 @@ public class CourseConfig implements Serializable, Cloneable { configuration.put(KEY_SHAREDFOLDER_READONLY, Boolean.valueOf(mount)); } - /** - * @param b - */ public void setEfficencyStatementIsEnabled(boolean b) { configuration.put(KEY_EFFICENCY_ENABLED, Boolean.valueOf(b)); } - /** - * @return true if the efficency statement is enabled - */ public boolean isEfficencyStatementEnabled() { Boolean bool = (Boolean) configuration.get(KEY_EFFICENCY_ENABLED); return bool.booleanValue(); } - - /** - * @return true if the efficency statement is enabled - */ public Long getCertificateTemplate() { Object templateIdObj = configuration.get(CERTIFICATE_TEMPLATE); Long templateId = null; @@ -508,9 +441,6 @@ public class CourseConfig implements Serializable, Cloneable { } } - /** - * @param b - */ public void setCertificateTemplate(Long templateId ) { if(templateId != null) { configuration.put(CERTIFICATE_TEMPLATE, templateId); @@ -541,17 +471,11 @@ public class CourseConfig implements Serializable, Cloneable { configuration.put(CERTIFICATE_MANUAL_ENABLED, Boolean.valueOf(enabled)); } - /** - * @return true if the efficency statement is enabled - */ public boolean isRecertificationEnabled() { Boolean bool = (Boolean) configuration.get(RECERTIFICATION_ENABLED); return bool != null && bool.booleanValue(); } - /** - * @param b - */ public void setRecertificationEnabled(boolean b) { configuration.put(RECERTIFICATION_ENABLED, Boolean.valueOf(b)); } @@ -585,17 +509,11 @@ public class CourseConfig implements Serializable, Cloneable { } } - /** - * @return true if calendar is enabled - */ public boolean isCalendarEnabled() { Boolean bool = (Boolean) configuration.get(KEY_CALENDAR_ENABLED); return bool != null && bool.booleanValue(); } - /** - * @param b - */ public void setCalendarEnabled(boolean b) { configuration.put(KEY_CALENDAR_ENABLED, Boolean.valueOf(b)); } @@ -617,6 +535,33 @@ public class CourseConfig implements Serializable, Cloneable { public void setCourseSearchEnabled(boolean b) { configuration.put(COURSESEARCH_ENABLED, Boolean.valueOf(b)); } + + public boolean isParticipantListEnabled() { + Boolean bool = (Boolean) configuration.get(PARTICIPANT_LIST_ENABLED); + return bool.booleanValue(); + } + + public void setParticipantListEnabled(boolean b) { + configuration.put(PARTICIPANT_LIST_ENABLED, Boolean.valueOf(b)); + } + + public boolean isParticipantInfoEnabled() { + Boolean bool = (Boolean) configuration.get(PARTICIPANT_INFO_ENABLED); + return bool.booleanValue(); + } + + public void setParticipantInfoEnabled(boolean b) { + configuration.put(PARTICIPANT_INFO_ENABLED, Boolean.valueOf(b)); + } + + public boolean isEmailEnabled() { + Boolean bool = (Boolean) configuration.get(EMAIL_ENABLED); + return bool.booleanValue(); + } + + public void setEmailEnabled(boolean b) { + configuration.put(EMAIL_ENABLED, Boolean.valueOf(b)); + } public boolean isToolbarEnabled() { Boolean bool = (Boolean) configuration.get(TOOLBAR_ENABLED); @@ -636,11 +581,6 @@ public class CourseConfig implements Serializable, Cloneable { configuration.put(BREADCRUMB_ENABLED, Boolean.valueOf(b)); } - /** - * Creates a deep clone for the current object. - * - * @see java.lang.Object#clone() - */ @Override public CourseConfig clone() { CourseConfig clone = new CourseConfig(); @@ -665,13 +605,12 @@ public class CourseConfig implements Serializable, Cloneable { clone.setToolbarEnabled(isToolbarEnabled()); clone.setBreadCrumbEnabled(isBreadCrumbEnabled()); clone.setCourseSearchEnabled(isCourseSearchEnabled()); + clone.setParticipantListEnabled(isParticipantListEnabled()); + clone.setParticipantInfoEnabled(isParticipantInfoEnabled()); + clone.setEmailEnabled(isEmailEnabled()); return clone; } - /** - * - * @see java.lang.Object#equals(java.lang.Object) - */ @Override public boolean equals(Object obj) { if(obj == this) { @@ -704,11 +643,4 @@ public class CourseConfig implements Serializable, Cloneable { return false; } - /** - * @param version The version to set. - */ - public void setVersion(int version) { - this.version = version; - } - } diff --git a/src/main/java/org/olat/course/config/CourseConfigEvent.java b/src/main/java/org/olat/course/config/CourseConfigEvent.java index f6622b66ba98060ea1691fa3cbf03aea92cfc9e0..9265caad49691b9b2784bc8cd46872e97cd5e626 100644 --- a/src/main/java/org/olat/course/config/CourseConfigEvent.java +++ b/src/main/java/org/olat/course/config/CourseConfigEvent.java @@ -58,8 +58,11 @@ public class CourseConfigEvent extends MultiUserEvent { public enum CourseConfigType { efficiencyStatement, - calendar, search, + calendar, + participantList, + participantInfo, + email, chat, glossary, layout diff --git a/src/main/java/org/olat/course/config/ui/CourseToolbarController.java b/src/main/java/org/olat/course/config/ui/CourseToolbarController.java index 2b5b1fe84d46c5e9399ffdc38058e5f79286d90f..2e7b52cc514d1453243e2f839c4989d177b8a00b 100644 --- a/src/main/java/org/olat/course/config/ui/CourseToolbarController.java +++ b/src/main/java/org/olat/course/config/ui/CourseToolbarController.java @@ -26,6 +26,7 @@ import org.olat.core.gui.UserRequest; import org.olat.core.gui.components.form.flexible.FormItem; import org.olat.core.gui.components.form.flexible.FormItemContainer; import org.olat.core.gui.components.form.flexible.elements.SelectionElement; +import org.olat.core.gui.components.form.flexible.elements.StaticTextElement; import org.olat.core.gui.components.form.flexible.impl.FormBasicController; import org.olat.core.gui.components.form.flexible.impl.FormEvent; import org.olat.core.gui.components.form.flexible.impl.FormLayoutContainer; @@ -66,8 +67,12 @@ public class CourseToolbarController extends FormBasicController { private final String[] onValues; private SelectionElement toolbarEl; - private SelectionElement calendarEl; + private StaticTextElement explainEl; private SelectionElement searchEl; + private SelectionElement calendarEl; + private SelectionElement participantListEl; + private SelectionElement participantInfoEl; + private SelectionElement emailEl; private SelectionElement chatEl; private SelectionElement glossaryEl; @@ -122,9 +127,19 @@ public class CourseToolbarController extends FormBasicController { toolbarEl.addActionListener(FormEvent.ONCHANGE); toolbarEl.setEnabled(editable); - uifactory.addStaticTextElement("chkbx.toolbar.explain", "", formLayout); + explainEl = uifactory.addStaticTextElement("chkbx.toolbar.explain", "", formLayout); boolean canHideToolbar = true; + + boolean searchEnabled = courseConfig.isCourseSearchEnabled(); + boolean managedSearch = RepositoryEntryManagedFlag.isManaged(entry, RepositoryEntryManagedFlag.search); + searchEl = uifactory.addCheckboxesHorizontal("searchIsOn", "chkbx.search.onoff", formLayout, onKeys, onValues); + searchEl.select(onKeys[0], searchEnabled); + searchEl.setEnabled(editable && !managedSearch); + if(managedSearch && searchEnabled) { + canHideToolbar &= false; + } + if(calendarModule.isEnabled() && calendarModule.isEnableCourseToolCalendar()) { boolean calendarEnabled = courseConfig.isCalendarEnabled(); boolean managedCal = RepositoryEntryManagedFlag.isManaged(entry, RepositoryEntryManagedFlag.calendar); @@ -137,16 +152,34 @@ public class CourseToolbarController extends FormBasicController { canHideToolbar &= false; } } - - boolean searchEnabled = courseConfig.isCourseSearchEnabled(); - boolean managedSearch = RepositoryEntryManagedFlag.isManaged(entry, RepositoryEntryManagedFlag.search); - searchEl = uifactory.addCheckboxesHorizontal("searchIsOn", "chkbx.search.onoff", formLayout, onKeys, onValues); - searchEl.select(onKeys[0], searchEnabled); - searchEl.setEnabled(editable && !managedSearch); - if(managedSearch && searchEnabled) { + + boolean participantListEnabled = courseConfig.isParticipantListEnabled(); + boolean managedList = RepositoryEntryManagedFlag.isManaged(entry, RepositoryEntryManagedFlag.participantList); + participantListEl = uifactory.addCheckboxesHorizontal("listIsOn", "chkbx.participantlist.onoff", formLayout, onKeys, onValues); + participantListEl.select(onKeys[0], participantListEnabled); + participantListEl.setEnabled(editable && !managedList); + if(managedList && participantListEnabled) { + canHideToolbar &= false; + } + + boolean participantInfoEnabled = courseConfig.isParticipantInfoEnabled(); + boolean managedInfo = RepositoryEntryManagedFlag.isManaged(entry, RepositoryEntryManagedFlag.participantInfo); + participantInfoEl = uifactory.addCheckboxesHorizontal("infoIsOn", "chkbx.participantinfo.onoff", formLayout, onKeys, onValues); + participantInfoEl.select(onKeys[0], participantInfoEnabled); + participantInfoEl.setEnabled(editable && !managedInfo); + if(managedInfo && participantInfoEnabled) { canHideToolbar &= false; } + boolean emailEnabled = courseConfig.isEmailEnabled(); + boolean managedEmail = RepositoryEntryManagedFlag.isManaged(entry, RepositoryEntryManagedFlag.email); + emailEl = uifactory.addCheckboxesHorizontal("emailIsOn", "chkbx.email.onoff", formLayout, onKeys, onValues); + emailEl.select(onKeys[0], emailEnabled); + emailEl.setEnabled(editable && !managedEmail); + if(managedEmail && emailEnabled) { + canHideToolbar &= false; + } + boolean chatEnabled = courseConfig.isChatEnabled(); boolean managedChat = RepositoryEntryManagedFlag.isManaged(entry, RepositoryEntryManagedFlag.chat); chatEl = uifactory.addCheckboxesHorizontal("chatIsOn", "chkbx.chat.onoff", formLayout, onKeys, onValues); @@ -180,7 +213,7 @@ public class CourseToolbarController extends FormBasicController { @Override protected void formInnerEvent(UserRequest ureq, FormItem source, FormEvent event) { if(toolbarEl == source) { - if(!toolbarEl.isSelected(0)) { + if(!toolbarEl.isSelected(0) && isAnyToolSelected()) { showWarning("chkbx.toolbar.off.warning"); } updateToolbar(); @@ -188,13 +221,28 @@ public class CourseToolbarController extends FormBasicController { super.formInnerEvent(ureq, source, event); } + private boolean isAnyToolSelected() { + return searchEl.isSelected(0) + || (calendarEl != null && calendarEl.isSelected(0)) + || participantListEl.isSelected(0) + || participantInfoEl.isSelected(0) + || emailEl.isSelected(0) + || chatEl.isSelected(0) + || glossaryEl.isSelected(0); + } + private void updateToolbar() { boolean enabled = toolbarEl.isSelected(0); + explainEl.setVisible(enabled); + searchEl.setVisible(enabled); if(calendarEl != null) { calendarEl.setVisible(enabled); } + participantListEl.setVisible(enabled); + participantInfoEl.setVisible(enabled); + emailEl.setVisible(enabled); chatEl.setVisible(enabled); - searchEl.setVisible(enabled); + glossaryEl.setVisible(enabled); } @Override @@ -210,14 +258,26 @@ public class CourseToolbarController extends FormBasicController { boolean updateSearch = courseConfig.isCourseSearchEnabled() != enableSearch; courseConfig.setCourseSearchEnabled(enableSearch && toolbarEnabled); - boolean enableChat = chatEl.isSelected(0); - boolean updateChat = courseConfig.isChatEnabled() != enableChat; - courseConfig.setChatIsEnabled(enableChat && toolbarEnabled); - boolean enableCalendar = calendarEl != null && calendarEl.isSelected(0); boolean updateCalendar = courseConfig.isCalendarEnabled() != enableCalendar && calendarModule.isEnableCourseToolCalendar(); courseConfig.setCalendarEnabled(enableCalendar && toolbarEnabled); + boolean enableParticipantList = participantListEl.isSelected(0); + boolean updateParticipantList = courseConfig.isParticipantListEnabled() != enableParticipantList; + courseConfig.setParticipantListEnabled(enableParticipantList && toolbarEnabled); + + boolean enableParticipantInfo = participantInfoEl.isSelected(0); + boolean updateParticipantInfo = courseConfig.isParticipantInfoEnabled() != enableParticipantInfo; + courseConfig.setParticipantInfoEnabled(enableParticipantInfo && toolbarEnabled); + + boolean enableEmail = emailEl.isSelected(0); + boolean updateEmail = courseConfig.isEmailEnabled() != enableEmail; + courseConfig.setEmailEnabled(enableEmail && toolbarEnabled); + + boolean enableChat = chatEl.isSelected(0); + boolean updateChat = courseConfig.isChatEnabled() != enableChat; + courseConfig.setChatIsEnabled(enableChat && toolbarEnabled); + boolean enableGlossary = glossaryEl != null && glossaryEl.isSelected(0); boolean updateGlossary = courseConfig.isGlossaryEnabled() != enableGlossary; courseConfig.setGlossaryIsEnabled(enableGlossary && toolbarEnabled); @@ -226,45 +286,75 @@ public class CourseToolbarController extends FormBasicController { CourseFactory.closeCourseEditSession(course.getResourceableId(), true); if(updateSearch) { - ILoggingAction loggingAction = enableSearch ? - LearningResourceLoggingAction.REPOSITORY_ENTRY_PROPERTIES_COURSESEARCH_ENABLED : + ILoggingAction loggingAction = enableSearch ? + LearningResourceLoggingAction.REPOSITORY_ENTRY_PROPERTIES_COURSESEARCH_ENABLED: LearningResourceLoggingAction.REPOSITORY_ENTRY_PROPERTIES_COURSESEARCH_DISABLED; - ThreadLocalUserActivityLogger.log(loggingAction, getClass()); - - CoordinatorManager.getInstance().getCoordinator().getEventBus() - .fireEventToListenersOf(new CourseConfigEvent(CourseConfigType.search, course.getResourceableId()), course); + ThreadLocalUserActivityLogger.log(loggingAction, getClass()); + + CoordinatorManager.getInstance().getCoordinator().getEventBus() + .fireEventToListenersOf(new CourseConfigEvent(CourseConfigType.search, course.getResourceableId()), course); } + + if(updateCalendar) { + ILoggingAction loggingAction = enableCalendar ? + LearningResourceLoggingAction.REPOSITORY_ENTRY_PROPERTIES_CALENDAR_ENABLED: + LearningResourceLoggingAction.REPOSITORY_ENTRY_PROPERTIES_CALENDAR_DISABLED; + ThreadLocalUserActivityLogger.log(loggingAction, getClass()); + CoordinatorManager.getInstance().getCoordinator().getEventBus() + .fireEventToListenersOf(new CalendarGUIModifiedEvent(), OresHelper.lookupType(CalendarManager.class)); + CoordinatorManager.getInstance().getCoordinator().getEventBus() + .fireEventToListenersOf(new CourseConfigEvent(CourseConfigType.calendar, course.getResourceableId()), course); + } + + if(updateParticipantList) { + ILoggingAction loggingAction = enableParticipantList ? + LearningResourceLoggingAction.REPOSITORY_ENTRY_PROPERTIES_PARTICIPANTLIST_ENABLED: + LearningResourceLoggingAction.REPOSITORY_ENTRY_PROPERTIES_PARTICIPANTLIST_DISABLED; + ThreadLocalUserActivityLogger.log(loggingAction, getClass()); + + CoordinatorManager.getInstance().getCoordinator().getEventBus() + .fireEventToListenersOf(new CourseConfigEvent(CourseConfigType.participantList, course.getResourceableId()), course); + } + + if(updateParticipantInfo) { + ILoggingAction loggingAction = enableParticipantInfo ? + LearningResourceLoggingAction.REPOSITORY_ENTRY_PROPERTIES_PARTICIPANTINFO_ENABLED: + LearningResourceLoggingAction.REPOSITORY_ENTRY_PROPERTIES_PARTICIPANTINFO_DISABLED; + ThreadLocalUserActivityLogger.log(loggingAction, getClass()); + + CoordinatorManager.getInstance().getCoordinator().getEventBus() + .fireEventToListenersOf(new CourseConfigEvent(CourseConfigType.participantInfo, course.getResourceableId()), course); + } + + if(updateEmail) { + ILoggingAction loggingAction = enableEmail ? + LearningResourceLoggingAction.REPOSITORY_ENTRY_PROPERTIES_EMAIL_ENABLED: + LearningResourceLoggingAction.REPOSITORY_ENTRY_PROPERTIES_EMAIL_DISABLED; + ThreadLocalUserActivityLogger.log(loggingAction, getClass()); + + CoordinatorManager.getInstance().getCoordinator().getEventBus() + .fireEventToListenersOf(new CourseConfigEvent(CourseConfigType.email, course.getResourceableId()), course); + } + if(updateChat) { - ILoggingAction loggingAction = enableChat ? - LearningResourceLoggingAction.REPOSITORY_ENTRY_PROPERTIES_IM_ENABLED : + ILoggingAction loggingAction =enableChat ? + LearningResourceLoggingAction.REPOSITORY_ENTRY_PROPERTIES_IM_ENABLED: LearningResourceLoggingAction.REPOSITORY_ENTRY_PROPERTIES_IM_DISABLED; - ThreadLocalUserActivityLogger.log(loggingAction, getClass()); + ThreadLocalUserActivityLogger.log(loggingAction, getClass()); - CoordinatorManager.getInstance().getCoordinator().getEventBus() - .fireEventToListenersOf(new CourseConfigEvent(CourseConfigType.chat, course.getResourceableId()), course); + CoordinatorManager.getInstance().getCoordinator().getEventBus() + .fireEventToListenersOf(new CourseConfigEvent(CourseConfigType.chat, course.getResourceableId()), course); } if(updateGlossary) { ILoggingAction loggingAction = enableCalendar ? - LearningResourceLoggingAction.REPOSITORY_ENTRY_PROPERTIES_GLOSSARY_ENABLED : + LearningResourceLoggingAction.REPOSITORY_ENTRY_PROPERTIES_GLOSSARY_ENABLED: LearningResourceLoggingAction.REPOSITORY_ENTRY_PROPERTIES_GLOSSARY_DISABLED; ThreadLocalUserActivityLogger.log(loggingAction, getClass()); - CoordinatorManager.getInstance().getCoordinator().getEventBus() - .fireEventToListenersOf(new CourseConfigEvent(CourseConfigType.glossary, course.getResourceableId()), course); - } - - if(updateCalendar) { - ILoggingAction loggingAction = enableCalendar ? - LearningResourceLoggingAction.REPOSITORY_ENTRY_PROPERTIES_CALENDAR_ENABLED : - LearningResourceLoggingAction.REPOSITORY_ENTRY_PROPERTIES_CALENDAR_DISABLED; - - ThreadLocalUserActivityLogger.log(loggingAction, getClass()); - CoordinatorManager.getInstance().getCoordinator().getEventBus() - .fireEventToListenersOf(new CalendarGUIModifiedEvent(), OresHelper.lookupType(CalendarManager.class)); - CoordinatorManager.getInstance().getCoordinator().getEventBus() - .fireEventToListenersOf(new CourseConfigEvent(CourseConfigType.calendar, course.getResourceableId()), course); + CoordinatorManager.getInstance().getCoordinator().getEventBus() + .fireEventToListenersOf(new CourseConfigEvent(CourseConfigType.glossary, course.getResourceableId()), course); } fireEvent(ureq, new ReloadSettingsEvent(false, false, true, false)); diff --git a/src/main/java/org/olat/course/config/ui/_i18n/LocalStrings_de.properties b/src/main/java/org/olat/course/config/ui/_i18n/LocalStrings_de.properties index 7dd27afe7ea0d2af0216305be13ad61c6a539a56..c69e1b4036d43888272d36b5635a9c85a874ecf0 100644 --- a/src/main/java/org/olat/course/config/ui/_i18n/LocalStrings_de.properties +++ b/src/main/java/org/olat/course/config/ui/_i18n/LocalStrings_de.properties @@ -2,14 +2,17 @@ chkbx.calendar.onoff=Kurskalender chkbx.chat.onoff=Kurs-Chat chkbx.efficency.onoff=Leistungsnachweis verwenden +chkbx.email.onoff=E-Mail chkbx.glossary.explain=Das Glossar muss unter "Optionen" konfiguriert werden. chkbx.glossary.inverse.explain=Glossar Menu in Toolbar muss unter "Toolbar" konfiguriert werden. chkbx.glossary.onoff=Glossar chkbx.search.onoff=Kurssuche chkbx.menu.onoff=Menu sichtbar f\u00FCr Teilnehmer und Betreuer +chkbx.participantinfo.onoff=Teilnehmer Infos +chkbx.participantlist.onoff=Teilnehmerliste chkbx.toolbar.explain=Werkzeuge in Toolbar aktivieren: chkbx.toolbar.onoff=Toolbar sichtbar f\u00FCr Teilnehmer -chkbx.toolbar.off.warning=Wenn sie den Toolbar abschalten, stehen die folgende Werkzeuge nicht mehr zur Verf\u00fcgung: Glossar, Kurs-Chat und Kalender. +chkbx.toolbar.off.warning=Wenn sie die Toolbar abschalten, stehen die einzelnen Werkzeuge ebenfalls nicht mehr zur Verf\u00FCgung. chkbx.breadcrumb.onoff=Kr\u00FCmelnavigation command.choose=W\u00E4hlen command.glossary.add=Glossar w\u00E4hlen diff --git a/src/main/java/org/olat/course/config/ui/_i18n/LocalStrings_en.properties b/src/main/java/org/olat/course/config/ui/_i18n/LocalStrings_en.properties index f8f93a81c3576a204c245789ad5468abd66777fc..6007cec9805e2391fac17632b589bacc63feea2a 100644 --- a/src/main/java/org/olat/course/config/ui/_i18n/LocalStrings_en.properties +++ b/src/main/java/org/olat/course/config/ui/_i18n/LocalStrings_en.properties @@ -1,15 +1,18 @@ #Fri Jan 21 11:22:00 CET 2011 chkbx.calendar.onoff=Course calendar -chkbx.chat.onoff=Use course chat -chkbx.search.onoff=Enable course search +chkbx.chat.onoff=Course chat +chkbx.search.onoff=Course search +chkbx.email.onoff=E-mail chkbx.efficency.onoff=Use evidence of achievement chkbx.glossary.explain=The glossary need to be configured under "Options". chkbx.glossary.inverse.explain=Glossary menu in toolbar is configured under "Toolbar". chkbx.glossary.onoff=Glossary chkbx.menu.onoff=Menu visible for participants and coaches +chkbx.participantinfo.onoff=Participant infos +chkbx.participantlist.onoff=Participant list chkbx.toolbar.explain=Activate tools in toolbar: chkbx.toolbar.onoff=Toolbar visible for participants -chkbx.toolbar.off.warning=If you disable the toolbar the participants cannot use the calendar, chat and glossary. +chkbx.toolbar.off.warning=If you disable the toolbar, the individual tools are also no longer available. chkbx.breadcrumb.onoff=Bread-crumb navigation command.choose=Choose command.glossary.add=Select glossary diff --git a/src/main/java/org/olat/course/config/ui/_i18n/LocalStrings_fr.properties b/src/main/java/org/olat/course/config/ui/_i18n/LocalStrings_fr.properties index a813f3d55800f766cbfb10581d0db2abb8be7332..4c6383ea221281b5dd3c6f9f2a91a3a8ac78808e 100644 --- a/src/main/java/org/olat/course/config/ui/_i18n/LocalStrings_fr.properties +++ b/src/main/java/org/olat/course/config/ui/_i18n/LocalStrings_fr.properties @@ -4,12 +4,11 @@ chkbx.calendar.onoff=Calendrier du cours chkbx.chat.onoff=Chat du cours chkbx.efficency.onoff=Utiliser l'attestation de performance chkbx.glossary.explain=Le glossaire doit \u00EAtre configurer sous "Options". -chkbx.glossary.inverse.explain=Le menu du glossaire dans la barre d'outils est à configurer sous "Barre d'outils". +chkbx.glossary.inverse.explain=Le menu du glossaire dans la barre d'outils est \uFFFD configurer sous "Barre d'outils". chkbx.glossary.onoff=Glossaire chkbx.menu.onoff=Menu visible pour les participants et les coaches chkbx.search.onoff=Recherche au sein du cours chkbx.toolbar.explain=Activer les outils de la barre d'outils\: -chkbx.toolbar.off.warning=Si vous d\u00E9sactiv\u00E9 la barre d'outils, les participants ne peuvent plus acc\u00E9der aux fonctions calendrier, chat et glossaire. chkbx.toolbar.onoff=Barre d'outils visible pour les participants command.choose=S\u00E9lectionner command.glossary.add=Choisir glossaire diff --git a/src/main/java/org/olat/course/config/ui/_i18n/LocalStrings_it.properties b/src/main/java/org/olat/course/config/ui/_i18n/LocalStrings_it.properties index 0ae3b7fe7c7a57da79eb569d14fc6898ec48eab1..0f0e6608de92f3075e50b3ecd10ce7b5d7150006 100644 --- a/src/main/java/org/olat/course/config/ui/_i18n/LocalStrings_it.properties +++ b/src/main/java/org/olat/course/config/ui/_i18n/LocalStrings_it.properties @@ -3,8 +3,7 @@ chkbx.calendar.onoff=Utilizza il calendario chkbx.chat.onoff=Utilizza la chat di corso chkbx.efficency.onoff=Utilizza l'attestato di efficienza chkbx.menu.onoff=Menu visibile per partecipanti e tutori -chkbx.search.onoff=Abilitare ricerca nel corso -chkbx.toolbar.off.warning=Se disabiliti la barra degli strumenti, i partecipanti non potranno usare il calendario, la chat e il glossario. +chkbx.search.onoff=Ricerca nel corso chkbx.toolbar.onoff=Barre degli strumenti visibili ai partecipanti command.choose=Selezionare command.glossary.add=Selezionare glossario diff --git a/src/main/java/org/olat/course/config/ui/_i18n/LocalStrings_pt_BR.properties b/src/main/java/org/olat/course/config/ui/_i18n/LocalStrings_pt_BR.properties index 5dac9ae1c2f1b685cc478058b944170279f4956a..2eb52419f84d9036ced233f0d76fa30150ff0e3b 100644 --- a/src/main/java/org/olat/course/config/ui/_i18n/LocalStrings_pt_BR.properties +++ b/src/main/java/org/olat/course/config/ui/_i18n/LocalStrings_pt_BR.properties @@ -7,9 +7,8 @@ chkbx.glossary.explain=O gloss\u00E1rio precisa ser configurado em "Op\u00E7\u00 chkbx.glossary.inverse.explain=O menu do gloss\u00E1rio na barra de ferramentas est\u00E1 configurado em "Barra de ferramentas". chkbx.glossary.onoff=Gloss\u00E1rio chkbx.menu.onoff=Menu vis\u00EDvel para os participantes e treinadores -chkbx.search.onoff=Ativar pesquisa no curso +chkbx.search.onoff=Pesquisa no curso chkbx.toolbar.explain=Ativar ferramentas na barra de ferramentas\: -chkbx.toolbar.off.warning=Se voc\u00EA desativar a barra de ferramentas os participantes n\u00E3o podem usar o calend\u00E1rio, o chat e o gloss\u00E1rio. chkbx.toolbar.onoff=Barra de ferramentas vis\u00EDvel para os participantes command.choose=Escolher command.glossary.add=Usar um gloss\u00E1rio diff --git a/src/main/java/org/olat/course/nodes/co/COEditController.java b/src/main/java/org/olat/course/nodes/co/COEditController.java index 4dd90c7845bc6c870f4fa3657484451f68c814ee..21fbd8146a24e6efc12d20b94b2cc20387bd4c46 100755 --- a/src/main/java/org/olat/course/nodes/co/COEditController.java +++ b/src/main/java/org/olat/course/nodes/co/COEditController.java @@ -128,18 +128,11 @@ public class COEditController extends ActivateableTabbableDefaultController impl listenTo(accessibilityCondContr); } - /** - * @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 public void event(UserRequest ureq, Component source, Event event) { // } - /** - * @see org.olat.core.gui.control.DefaultController#event(org.olat.core.gui.UserRequest, - * org.olat.core.gui.control.Controller, org.olat.core.gui.control.Event) - */ @Override public void event(UserRequest ureq, Controller source, Event event) { if (source == accessibilityCondContr) { @@ -156,9 +149,7 @@ public class COEditController extends ActivateableTabbableDefaultController impl } } - /** - * @see org.olat.core.gui.control.generic.tabbable.TabbableDefaultController#addTabs(org.olat.core.gui.components.TabbedPane) - */ + @Override public void addTabs(TabbedPane tabbedPane) { myTabbedPane = tabbedPane; @@ -166,17 +157,17 @@ public class COEditController extends ActivateableTabbableDefaultController impl tabbedPane.addTab(translate(PANE_TAB_COCONFIG), myContent); } - /** - * @see org.olat.core.gui.control.DefaultController#doDispose(boolean) - */ + @Override protected void doDispose() { - //nothing to do + // } + @Override public String[] getPaneKeys() { return paneKeys; } + @Override public TabbedPane getTabbedPane() { return myTabbedPane; } diff --git a/src/main/java/org/olat/course/nodes/co/CORunController.java b/src/main/java/org/olat/course/nodes/co/CORunController.java index 08555c64a133bb145534a5a2e07c85375a6ddf75..ea211ba4b6946a85c93057b5c5e77ab3c0145e42 100755 --- a/src/main/java/org/olat/course/nodes/co/CORunController.java +++ b/src/main/java/org/olat/course/nodes/co/CORunController.java @@ -300,17 +300,12 @@ public class CORunController extends BasicController { return cl; } - /** - * @see org.olat.core.gui.control.DefaultController#event(org.olat.core.gui.UserRequest, - * @see org.olat.core.gui.components.Component, @see org.olat.core.gui.control.Event) - */ + @Override public void event(UserRequest ureq, Component source, Event event) { - // no components to listen to + // } - /** - * @see org.olat.core.gui.control.DefaultController#doDispose(boolean) - */ + @Override protected void doDispose() { // } diff --git a/src/main/java/org/olat/course/nodes/co/COToolController.java b/src/main/java/org/olat/course/nodes/co/COToolController.java new file mode 100644 index 0000000000000000000000000000000000000000..60784427c9e9e6f1ed11f9a2feac2071b31cd34b --- /dev/null +++ b/src/main/java/org/olat/course/nodes/co/COToolController.java @@ -0,0 +1,147 @@ +/** + * <a href="http://www.openolat.org"> + * OpenOLAT - Online Learning and Training</a><br> + * <p> + * Licensed under the Apache License, Version 2.0 (the "License"); <br> + * you may not use this file except in compliance with the License.<br> + * You may obtain a copy of the License at the + * <a href="http://www.apache.org/licenses/LICENSE-2.0">Apache homepage</a> + * <p> + * Unless required by applicable law or agreed to in writing,<br> + * software distributed under the License is distributed on an "AS IS" BASIS, <br> + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. <br> + * See the License for the specific language governing permissions and <br> + * limitations under the License. + * <p> + * Initial code contributed and copyrighted by<br> + * frentix GmbH, http://www.frentix.com + * <p> + */ +package org.olat.course.nodes.co; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; +import java.util.Set; + +import org.olat.core.gui.UserRequest; +import org.olat.core.gui.components.Component; +import org.olat.core.gui.components.form.flexible.impl.FormEvent; +import org.olat.core.gui.components.velocity.VelocityContainer; +import org.olat.core.gui.control.Controller; +import org.olat.core.gui.control.Event; +import org.olat.core.gui.control.WindowControl; +import org.olat.core.gui.control.controller.BasicController; +import org.olat.core.id.Identity; +import org.olat.core.util.mail.ContactList; +import org.olat.core.util.mail.ContactMessage; +import org.olat.course.groupsandrights.CourseGroupManager; +import org.olat.course.nodes.co.COToolRecipientsController.Recipients; +import org.olat.course.nodes.members.MembersHelpers; +import org.olat.course.run.userview.UserCourseEnvironment; +import org.olat.modules.co.ContactFormController; +import org.olat.repository.RepositoryEntry; +import org.olat.repository.RepositoryService; +import org.springframework.beans.factory.annotation.Autowired; + +/** + * + * Initial date: 6 Aug 2019<br> + * @author uhensler, urs.hensler@frentix.com, http://www.frentix.com + * + */ +public class COToolController extends BasicController { + + private final ContactFormController emailCtrl; + private final COToolRecipientsController recipientCtrl; + + private final RepositoryEntry courseRepositoryEntry; + private final CourseGroupManager courseGroupManager; + + @Autowired + private RepositoryService repositoryService; + + public COToolController(UserRequest ureq, WindowControl wControl, UserCourseEnvironment userCourseEnv) { + super(ureq, wControl); + courseGroupManager = userCourseEnv.getCourseEnvironment().getCourseGroupManager(); + this.courseRepositoryEntry = userCourseEnv.getCourseEnvironment().getCourseGroupManager().getCourseEntry(); + + VelocityContainer mainVC = createVelocityContainer("tool"); + + recipientCtrl = new COToolRecipientsController(ureq, wControl); + listenTo(recipientCtrl); + mainVC.put("recipients", recipientCtrl.getInitialComponent()); + + ContactMessage cmsg = new ContactMessage(getIdentity()); + Set<Recipients> recipients = recipientCtrl.getSelectedRecipients(); + for (ContactList recipientList : getRecipientsLists(recipients)) { + cmsg.addEmailTo(recipientList); + } + emailCtrl = new ContactFormController(ureq, getWindowControl(), false, false, false, cmsg, null); + emailCtrl.setContactFormTitle(null); + listenTo(emailCtrl); + mainVC.put("email", emailCtrl.getInitialComponent()); + + putInitialPanel(mainVC); + } + + @Override + protected void event(UserRequest ureq, Controller source, Event event) { + if (source == recipientCtrl && event == FormEvent.CHANGED_EVENT) { + Set<Recipients> recipients = recipientCtrl.getSelectedRecipients(); + doSetReciepients(recipients); + } + super.event(ureq, source, event); + } + + private void doSetReciepients(Set<Recipients> recipients) { + List<ContactList> contactLists = getRecipientsLists(recipients); + emailCtrl.setRecipientsLists(contactLists); + } + + private List<ContactList> getRecipientsLists(Set<Recipients> recipients) { + List<ContactList> contactLists = new ArrayList<>(); + if (recipients.contains(Recipients.participants)) { + contactLists.add(getParticipantsContactList()); + } + if (recipients.contains(Recipients.coaches)) { + contactLists.add(getCoachesContactList()); + } + if (recipients.contains(Recipients.owners)) { + contactLists.add(getOwnersContactList()); + } + return contactLists; + } + + private ContactList getOwnersContactList() { + ContactList cl = new ContactList(translate("form.message.chckbx.owners")); + List<Identity> identities = MembersHelpers.getOwners(repositoryService, courseRepositoryEntry); + cl.addAllIdentites(identities); + return cl; + } + + private ContactList getCoachesContactList() { + ContactList cl = new ContactList(translate("form.message.chckbx.coaches")); + Collection<Identity> identities = courseGroupManager.getCoaches(); + cl.addAllIdentites(identities); + return cl; + } + + private ContactList getParticipantsContactList() { + ContactList cl = new ContactList(translate("form.message.chckbx.partips")); + Collection<Identity> identities = courseGroupManager.getParticipants(); + cl.addAllIdentites(identities); + return cl; + } + + @Override + protected void event(UserRequest ureq, Component source, Event event) { + // + } + + @Override + protected void doDispose() { + // + } + +} diff --git a/src/main/java/org/olat/course/nodes/co/COToolRecipientsController.java b/src/main/java/org/olat/course/nodes/co/COToolRecipientsController.java new file mode 100644 index 0000000000000000000000000000000000000000..469f1be52998fb64ba5ee9ed1ed194d4a9948ead --- /dev/null +++ b/src/main/java/org/olat/course/nodes/co/COToolRecipientsController.java @@ -0,0 +1,124 @@ +/** + * <a href="http://www.openolat.org"> + * OpenOLAT - Online Learning and Training</a><br> + * <p> + * Licensed under the Apache License, Version 2.0 (the "License"); <br> + * you may not use this file except in compliance with the License.<br> + * You may obtain a copy of the License at the + * <a href="http://www.apache.org/licenses/LICENSE-2.0">Apache homepage</a> + * <p> + * Unless required by applicable law or agreed to in writing,<br> + * software distributed under the License is distributed on an "AS IS" BASIS, <br> + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. <br> + * See the License for the specific language governing permissions and <br> + * limitations under the License. + * <p> + * Initial code contributed and copyrighted by<br> + * frentix GmbH, http://www.frentix.com + * <p> + */ +package org.olat.course.nodes.co; + +import static org.olat.core.gui.components.util.KeyValues.entry; + +import java.util.HashSet; +import java.util.Set; + +import org.olat.core.gui.UserRequest; +import org.olat.core.gui.components.form.flexible.FormItem; +import org.olat.core.gui.components.form.flexible.FormItemContainer; +import org.olat.core.gui.components.form.flexible.elements.MultipleSelectionElement; +import org.olat.core.gui.components.form.flexible.impl.FormBasicController; +import org.olat.core.gui.components.form.flexible.impl.FormEvent; +import org.olat.core.gui.components.util.KeyValues; +import org.olat.core.gui.control.Controller; +import org.olat.core.gui.control.WindowControl; + +/** + * + * Initial date: 6 Aug 2019<br> + * @author uhensler, urs.hensler@frentix.com, http://www.frentix.com + * + */ +public class COToolRecipientsController extends FormBasicController { + + public enum Recipients { + owners("tool.recipients.owners"), + coaches("tool.recipients.coaches"), + participants("tool.recipients.participants"); + + private final String i18nKey; + + private Recipients(String i18nKey) { + this.i18nKey = i18nKey; + + } + + public String getI18nKey() { + return i18nKey; + } + } + + private MultipleSelectionElement recipientsEl; + + public COToolRecipientsController(UserRequest ureq, WindowControl wControl) { + super(ureq, wControl); + initForm(ureq); + } + + public Set<Recipients> getSelectedRecipients() { + Set<Recipients> recipients = new HashSet<>(); + for (String key : recipientsEl.getSelectedKeys()) { + recipients.add(Recipients.valueOf(key)); + } + return recipients; + } + + @Override + protected void initForm(FormItemContainer formLayout, Controller listener, UserRequest ureq) { + setFormTitle("tool.title"); + + KeyValues recipientKV = new KeyValues(); + for (Recipients recipient : Recipients.values()) { + recipientKV.add(entry(recipient.name(), translate(recipient.getI18nKey()))); + } + recipientsEl = uifactory.addCheckboxesHorizontal("tool.recipients", formLayout, recipientKV.keys(), recipientKV.values()); + recipientsEl.select(Recipients.owners.name(), true); + recipientsEl.addActionListener(FormEvent.ONCHANGE); + } + + @Override + protected void formInnerEvent(UserRequest ureq, FormItem source, FormEvent event) { + if (source == recipientsEl) { + boolean valid = validateFormLogic(ureq); + if (valid) { + fireEvent(ureq, FormEvent.CHANGED_EVENT); + } + } + super.formInnerEvent(ureq, source, event); + } + + @Override + protected boolean validateFormLogic(UserRequest ureq) { + boolean allOk = true; + + recipientsEl.clearError(); + if (!recipientsEl.isAtLeastSelected(1)) { + recipientsEl.setErrorKey("tool.recipients.mandatory", null); + allOk = false; + } + + return allOk & super.validateFormLogic(ureq); + } + + @Override + protected void formOK(UserRequest ureq) { + // + } + + @Override + protected void doDispose() { + // + } + +} diff --git a/src/main/java/org/olat/course/nodes/co/_content/tool.html b/src/main/java/org/olat/course/nodes/co/_content/tool.html new file mode 100644 index 0000000000000000000000000000000000000000..1d2b31ec095b553a8444c354f32b18a26d049d53 --- /dev/null +++ b/src/main/java/org/olat/course/nodes/co/_content/tool.html @@ -0,0 +1,2 @@ +$r.render("recipients") +$r.render("email") \ No newline at end of file diff --git a/src/main/java/org/olat/course/nodes/co/_i18n/LocalStrings_de.properties b/src/main/java/org/olat/course/nodes/co/_i18n/LocalStrings_de.properties index 0146dbdfad2b207cbec3853c063989dc55bf9f8b..c19bc69bff11346a016ad5fcf31565e0269a7f01 100755 --- a/src/main/java/org/olat/course/nodes/co/_i18n/LocalStrings_de.properties +++ b/src/main/java/org/olat/course/nodes/co/_i18n/LocalStrings_de.properties @@ -1,14 +1,4 @@ #Mon Mar 02 09:54:04 CET 2009 - - - - - - - - - - groupCoachesChoose=Gruppe ausw\u00E4hlen groupParticipantsChoose=Gruppe ausw\u00E4hlen groupCreate=Gruppe erstellen @@ -22,7 +12,7 @@ error.norecipients.long=Es sind keine Empf\u00E4nger f\u00FCr {0} definiert. Die error.norecipients.short=Empf\u00E4nger f\u00FCr {0} fehlen. error.notfound.name=Der angegebene Name ({1}) wurde im Gruppenmanagement dieses Kurses nicht gefunden. error.notfound.names=Die angegebenen Namen ({1}) wurden im Gruppenmanagement dieses Kurses nicht gefunden. -error.no.choice.specified=W\u00e4hlen Sie mindestens +error.no.choice.specified=W\u00E4hlen Sie mindestens error.no.group.specified=W\u00E4hlen Sie eine Gruppe/Lernbereich form.areanames.wrong=Geben Sie Namen von Lernbereichen getrennt mit Kommas ein oder lassen Sie dieses Feld leer. form.choose.coachesandpartips=Sie m\u00FCssen Teilnehmer oder Betreuer ausw\u00E4hlen @@ -42,7 +32,6 @@ form.message.participants.group=Nur Teilnehmer aus den Gruppen form.message.participants.course=Nur Teilnehmer aus dem Kurs form.noGroupsOrAreas=Es muss mindestens eine Lerngruppe oder ein Lernbereich angegeben werden header=Empf\u00E4nger - message.body=Nachricht (Vorlage) message.emailtoadresses=E-Mailadressen message.subject=Betreff (Vorlage) @@ -57,3 +46,9 @@ pane.tab.coconfig=Empf\u00E4nger popupchooseareas=Lernbereiche aus Gruppenmanagement w\u00E4hlen popupchoosegroups=Gruppen aus Gruppenmanagement w\u00E4hlen recipients=Externe Empf\u00E4nger +tool.recipients=Empf\u00E4nger +tool.recipients.coaches=Betreuer +tool.recipients.participants=Kursbesitzer +tool.recipients.mandatory=Sie m\u00FCssen mindestens eine Option ausw\u00E4hlen. +tool.recipients.owners=Teilnehmer +tool.title=E-Mail diff --git a/src/main/java/org/olat/course/nodes/co/_i18n/LocalStrings_en.properties b/src/main/java/org/olat/course/nodes/co/_i18n/LocalStrings_en.properties index 5d1937ef10f4e8863ccbbe82890d2245e94d0830..e1f012deee45621d8d8f0f1d9d63467ce2f56bc9 100755 --- a/src/main/java/org/olat/course/nodes/co/_i18n/LocalStrings_en.properties +++ b/src/main/java/org/olat/course/nodes/co/_i18n/LocalStrings_en.properties @@ -1,14 +1,4 @@ #Sun Aug 15 18:44:08 CEST 2010 - - - - - - - - - - groupCoachesChoose=Select group groupParticipantsChoose=Select group groupCreate=Create group @@ -28,7 +18,7 @@ form.areanames.wrong=Please indicate titles of learning areas separated by comma form.choose.coachesandpartips=You have to select some participants or tutors form.groupnames.wrong=Please indicate titles of learning groups separated by commas or leave this box blank. form.message.area=Selected areas -form.message.chckbx.coaches=Tutors of selected learning groups +form.message.chckbx.coaches=Coaches of selected learning groups form.message.chckbx.partips=Participants of selected learning groups form.message.chckbx.owners=Course owners form.message.example.area=(Example\: Gr_1, Gr_2) @@ -42,7 +32,6 @@ form.message.participants.group=Only group participants form.message.participants.course=Only course participants form.noGroupsOrAreas=At least one learning group or learning area has to be indicated header=Recipient - message.body=Message (template) message.emailtoadresses=E-mail addresses message.subject=Subject (template) @@ -56,4 +45,10 @@ pane.tab.accessibility=Access pane.tab.coconfig=Recipient popupchooseareas=Select learning areas from group management popupchoosegroups=Select groups from group management -recipients=External recipients \ No newline at end of file +recipients=External recipients +tool.recipients=Recipients +tool.recipients.coaches=Coaches +tool.recipients.participants=Participants +tool.recipients.mandatory=You have to select at least one option. +tool.recipients.owners=Owners +tool.title=E-mail \ No newline at end of file diff --git a/src/main/java/org/olat/course/nodes/info/InfoRunController.java b/src/main/java/org/olat/course/nodes/info/InfoRunController.java index 0357267bb55727106864c4059c79448e6177a7b2..a14fdcdf600f33acb62d6925fa9588439aceef62 100644 --- a/src/main/java/org/olat/course/nodes/info/InfoRunController.java +++ b/src/main/java/org/olat/course/nodes/info/InfoRunController.java @@ -45,6 +45,7 @@ import org.olat.core.gui.control.WindowControl; import org.olat.core.gui.control.controller.BasicController; import org.olat.core.id.Identity; import org.olat.core.id.OLATResourceable; +import org.olat.core.util.StringHelper; import org.olat.core.util.UserSession; import org.olat.core.util.resource.OresHelper; import org.olat.course.CourseFactory; @@ -55,6 +56,7 @@ import org.olat.course.nodes.InfoCourseNode; import org.olat.course.run.userview.NodeEvaluation; import org.olat.course.run.userview.UserCourseEnvironment; import org.olat.modules.ModuleConfiguration; +import org.olat.repository.RepositoryEntry; import org.springframework.beans.factory.annotation.Autowired; /** @@ -68,11 +70,11 @@ import org.springframework.beans.factory.annotation.Autowired; */ public class InfoRunController extends BasicController { - private final VelocityContainer runVc; - private final InfoDisplayController infoDisplayController; + private VelocityContainer runVc; + private InfoDisplayController infoDisplayController; private ContextualSubscriptionController subscriptionController; - private final String businessPath; + private String businessPath; @Autowired private InfoSubscriptionManager subscriptionManager; @@ -81,21 +83,49 @@ public class InfoRunController extends BasicController { NodeEvaluation ne, InfoCourseNode courseNode) { super(ureq, wControl); ModuleConfiguration config = courseNode.getModuleConfiguration(); - - Long resId = userCourseEnv.getCourseEnvironment().getCourseResourceableId(); - String resSubPath = courseNode.getIdent(); + + boolean canAdd; + boolean canAdmin; + if(userCourseEnv.isCourseReadOnly()) { + canAdd = false; + canAdmin = false; + } else { + boolean isAdmin = userCourseEnv.isAdmin(); + canAdd = isAdmin || ne.isCapabilityAccessible(InfoCourseNode.EDIT_CONDITION_ID); + canAdmin = isAdmin || ne.isCapabilityAccessible(InfoCourseNode.ADMIN_CONDITION_ID); + } + + boolean autoSubscribe = InfoCourseNodeEditController.getAutoSubscribe(config); + int maxResults = getConfigValue(config, InfoCourseNodeConfiguration.CONFIG_LENGTH, 10); + int duration = getConfigValue(config, InfoCourseNodeConfiguration.CONFIG_DURATION, 90); + + initVC(ureq, userCourseEnv, resSubPath, canAdd, canAdmin, autoSubscribe, maxResults, duration); + } + + public InfoRunController(UserRequest ureq, WindowControl wControl, UserCourseEnvironment userCourseEnv, + String resSubPath, boolean canAdd, boolean canAdmin, boolean autoSubscribe) { + super(ureq, wControl); + initVC(ureq, userCourseEnv, resSubPath, canAdd, canAdmin, autoSubscribe, -1, -1); + } + + private void initVC(UserRequest ureq, UserCourseEnvironment userCourseEnv, + String resSubPath, boolean canAdd, boolean canAdmin, boolean autoSubscribe, int maxResults, int duration) { + Long resId = userCourseEnv.getCourseEnvironment().getCourseResourceableId(); OLATResourceable infoResourceable = new InfoOLATResourceable(resId); - businessPath = normalizeBusinessPath(wControl.getBusinessControl().getAsString()); + businessPath = normalizeBusinessPath(getWindowControl().getBusinessControl().getAsString()); ICourse course = CourseFactory.loadCourse(resId); + CourseGroupManager cgm = userCourseEnv.getCourseEnvironment().getCourseGroupManager(); + RepositoryEntry courseEntry = cgm.getCourseEntry(); + String infoMailTitle = course.getCourseTitle(); //manage opt-out subscription UserSession usess = ureq.getUserSession(); if(!usess.getRoles().isGuestOnly()) { SubscriptionContext subContext = subscriptionManager.getInfoSubscriptionContext(infoResourceable, resSubPath); PublisherData pdata = subscriptionManager.getInfoPublisherData(infoResourceable, businessPath); - if(InfoCourseNodeEditController.getAutoSubscribe(config)) { + if(autoSubscribe) { InfoSubscription infoSubscription = subscriptionManager.getInfoSubscription(usess.getGuiPreferences()); if(infoSubscription.subscribed(businessPath, false)) { subscriptionManager.subscribe(infoResourceable, resSubPath, businessPath, getIdentity()); @@ -104,26 +134,17 @@ public class InfoRunController extends BasicController { subscriptionController = new ContextualSubscriptionController(ureq, getWindowControl(), subContext, pdata); listenTo(subscriptionController); } - boolean canAdd; - boolean canAdmin; - if(userCourseEnv.isCourseReadOnly()) { - canAdd = false; - canAdmin = false; - } else { - boolean isAdmin = userCourseEnv.isAdmin(); - canAdd = isAdmin || ne.isCapabilityAccessible(InfoCourseNode.EDIT_CONDITION_ID); - canAdmin = isAdmin || ne.isCapabilityAccessible(InfoCourseNode.ADMIN_CONDITION_ID); - } InfoSecurityCallback secCallback = new InfoCourseSecurityCallback(getIdentity(), canAdd, canAdmin); - infoDisplayController = new InfoDisplayController(ureq, wControl, config, secCallback, infoResourceable, resSubPath, businessPath); + + infoDisplayController = new InfoDisplayController(ureq, getWindowControl(), maxResults, duration, secCallback, infoResourceable, resSubPath, businessPath); infoDisplayController.addSendMailOptions(new SendSubscriberMailOption(infoResourceable, resSubPath, getLocale())); - infoDisplayController.addSendMailOptions(new SendMembersMailOption(cgm.getCourseEntry(), GroupRoles.owner, translate("wizard.step1.send_option.owner"))); - infoDisplayController.addSendMailOptions(new SendMembersMailOption(cgm.getCourseEntry(), GroupRoles.coach, translate("wizard.step1.send_option.coach"))); - infoDisplayController.addSendMailOptions(new SendMembersMailOption(cgm.getCourseEntry(), GroupRoles.participant, translate("wizard.step1.send_option.participant"))); + infoDisplayController.addSendMailOptions(new SendMembersMailOption(courseEntry, GroupRoles.owner, translate("wizard.step1.send_option.owner"))); + infoDisplayController.addSendMailOptions(new SendMembersMailOption(courseEntry, GroupRoles.coach, translate("wizard.step1.send_option.coach"))); + infoDisplayController.addSendMailOptions(new SendMembersMailOption(courseEntry, GroupRoles.participant, translate("wizard.step1.send_option.participant"))); - MailFormatter mailFormatter = new SendInfoMailFormatter(course.getCourseTitle(), businessPath, getTranslator()); + MailFormatter mailFormatter = new SendInfoMailFormatter(infoMailTitle, businessPath, getTranslator()); infoDisplayController.setSendMailFormatter(mailFormatter); listenTo(infoDisplayController); @@ -136,6 +157,18 @@ public class InfoRunController extends BasicController { putInitialPanel(runVc); } + private int getConfigValue(ModuleConfiguration config, String key, int def) { + String durationStr = (String)config.get(key); + if("\u221E".equals(durationStr)) { + return -1; + } else if(StringHelper.containsNonWhitespace(durationStr)) { + try { + return Integer.parseInt(durationStr); + } catch(NumberFormatException e) { /* fallback to default */ } + } + return def; + } + /** * Remove ROOT, remove identity context entry or duplicate, * @param url diff --git a/src/main/java/org/olat/course/nodes/members/MembersToolRunController.java b/src/main/java/org/olat/course/nodes/members/MembersToolRunController.java new file mode 100644 index 0000000000000000000000000000000000000000..5cf5b399f40eeeaef1d4c4a36647ca7089a45511 --- /dev/null +++ b/src/main/java/org/olat/course/nodes/members/MembersToolRunController.java @@ -0,0 +1,101 @@ +/** + * <a href="http://www.openolat.org"> + * OpenOLAT - Online Learning and Training</a><br> + * <p> + * Licensed under the Apache License, Version 2.0 (the "License"); <br> + * you may not use this file except in compliance with the License.<br> + * You may obtain a copy of the License at the + * <a href="http://www.apache.org/licenses/LICENSE-2.0">Apache homepage</a> + * <p> + * Unless required by applicable law or agreed to in writing,<br> + * software distributed under the License is distributed on an "AS IS" BASIS, <br> + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. <br> + * See the License for the specific language governing permissions and <br> + * limitations under the License. + * <p> + * Initial code contributed and copyrighted by<br> + * frentix GmbH, http://www.frentix.com + * <p> + */ +package org.olat.course.nodes.members; + +import java.util.Collections; +import java.util.List; +import java.util.Map; + +import org.olat.commons.memberlist.manager.MembersExportManager; +import org.olat.commons.memberlist.model.CurriculumMemberInfos; +import org.olat.commons.memberlist.ui.MembersDisplayRunController; +import org.olat.core.gui.UserRequest; +import org.olat.core.gui.components.Component; +import org.olat.core.gui.control.Event; +import org.olat.core.gui.control.WindowControl; +import org.olat.core.gui.control.controller.BasicController; +import org.olat.core.id.Identity; +import org.olat.course.run.environment.CourseEnvironment; +import org.olat.course.run.userview.UserCourseEnvironment; +import org.olat.modules.curriculum.CurriculumModule; +import org.olat.repository.RepositoryEntry; +import org.olat.repository.RepositoryService; +import org.springframework.beans.factory.annotation.Autowired; + +/** + * + * Initial date: 6 Aug 2019<br> + * @author uhensler, urs.hensler@frentix.com, http://www.frentix.com + * + */ +public class MembersToolRunController extends BasicController { + +private MembersDisplayRunController membersDisplayRunController; + + @Autowired + private RepositoryService repositoryService; + @Autowired + private CurriculumModule curriculumModule; + @Autowired + private MembersExportManager exportManager; + + public MembersToolRunController(UserRequest ureq, WindowControl wControl, UserCourseEnvironment userCourseEnv) { + super(ureq, wControl); + + CourseEnvironment courseEnv = userCourseEnv.getCourseEnvironment(); + RepositoryEntry courseRepositoryEntry = courseEnv.getCourseGroupManager().getCourseEntry(); + + List<Identity> owners = MembersHelpers.getOwners(repositoryService, courseRepositoryEntry); + List<Identity> coaches = courseEnv.getCourseGroupManager().getCoaches(); + List<Identity> participants = courseEnv.getCourseGroupManager().getParticipants(); + List<Identity> waiting = Collections.emptyList(); + + Map<Long,CurriculumMemberInfos> curriculumInfos = null; + if(curriculumModule.isEnabled()) { + curriculumInfos = exportManager.getCurriculumMemberInfos(courseRepositoryEntry); + } + + boolean canEmail = true; + boolean canDownload = false; + boolean deduplicateList = true; + boolean showOwners = true; + boolean showCoaches = true; + boolean showParticipants = true; + boolean showWaiting = false; + boolean editable = false; + membersDisplayRunController = new MembersDisplayRunController(ureq, wControl, getTranslator(), userCourseEnv, + null, owners, coaches, participants, waiting, curriculumInfos, canEmail, canDownload, deduplicateList, + showOwners, showCoaches, showParticipants, showWaiting, editable); + listenTo(membersDisplayRunController); + + putInitialPanel(membersDisplayRunController.getInitialComponent()); + } + + @Override + protected void doDispose() { + // + } + + @Override + protected void event(UserRequest ureq, Component source, Event event) { + // + } + +} diff --git a/src/main/java/org/olat/course/nodes/members/ui/group/_i18n/LocalStrings_en.properties b/src/main/java/org/olat/course/nodes/members/ui/group/_i18n/LocalStrings_en.properties index bd8c02edb9bfe7f83bba378564e5e771a06e5f71..7b09e5babe72c0aae193cc94e1e13a761049c284 100755 --- a/src/main/java/org/olat/course/nodes/members/ui/group/_i18n/LocalStrings_en.properties +++ b/src/main/java/org/olat/course/nodes/members/ui/group/_i18n/LocalStrings_en.properties @@ -31,7 +31,7 @@ form.areanames.wrong=Please indicate titles of learning areas separated by comma form.choose.coachesandpartips=You have to select some participants or tutors form.groupnames.wrong=Please indicate titles of learning groups separated by commas or leave this box blank. form.message.area=Selected areas -form.message.chckbx.coaches=Tutors of selected learning groups +form.message.chckbx.coaches=Coaches of selected learning groups form.message.chckbx.partips=Participants of selected learning groups form.message.chckbx.owners=Course owners form.message.curriculum.element=Curriculum diff --git a/src/main/java/org/olat/course/run/CourseRuntimeController.java b/src/main/java/org/olat/course/run/CourseRuntimeController.java index 3e9ade336741c1348990e2578434231de06fd853..0b13c02606053c47eac142fda661929ab5543abb 100644 --- a/src/main/java/org/olat/course/run/CourseRuntimeController.java +++ b/src/main/java/org/olat/course/run/CourseRuntimeController.java @@ -103,6 +103,9 @@ import org.olat.course.groupsandrights.CourseRights; import org.olat.course.member.MembersManagementMainController; import org.olat.course.nodes.CourseNode; import org.olat.course.nodes.ENCourseNode; +import org.olat.course.nodes.co.COToolController; +import org.olat.course.nodes.info.InfoRunController; +import org.olat.course.nodes.members.MembersToolRunController; import org.olat.course.reminder.ui.CourseRemindersController; import org.olat.course.run.calendar.CourseCalendarController; import org.olat.course.run.glossary.CourseGlossaryFactory; @@ -172,22 +175,26 @@ public class CourseRuntimeController extends RepositoryEntryRuntimeController im assessmentModeLink, lifeCycleChangeLink, //my course efficiencyStatementsLink, calendarLink, noteLink, chatLink, leaveLink, searchLink, + participantListLink, participantInfoLink, emailLink, //glossary openGlossaryLink, enableGlossaryLink, lecturesLink; private Link currentUserCountLink; private Dropdown myCourse, glossary; private CloseableModalController cmc; + private COToolController emailCtrl; private CourseAreasController areasCtrl; private ConfirmLeaveController leaveDialogBox; private ArchiverMainController archiverCtrl; private CustomDBMainController databasesCtrl; private FolderRunController courseFolderCtrl; + private InfoRunController participatInfoCtrl; private SearchInputController searchController; private StatisticMainController statisticsCtrl; private CourseRemindersController remindersCtrl; private TeacherOverviewController lecturesCtrl; private AssessmentToolController assessmentToolCtr; + private MembersToolRunController participatListCtrl; private MembersManagementMainController membersCtrl; private StatisticCourseNodesController statsToolCtr; private AssessmentModeListController assessmentModeCtrl; @@ -778,7 +785,7 @@ public class CourseRuntimeController extends RepositoryEntryRuntimeController im UserCourseEnvironment userCourseEnv = getUserCourseEnvironment(); CourseConfig cc = course.getCourseConfig(); - if (!assessmentLock && showInfos) { + if (!assessmentLock && showDetails) { detailsLink = LinkFactory.createToolLink("courseconfig",translate("command.courseconfig"), this, "o_icon_details"); toolbarPanel.addTool(detailsLink); } @@ -792,6 +799,29 @@ public class CourseRuntimeController extends RepositoryEntryRuntimeController im toolbarPanel.addTool(calendarLink); } + if(!assessmentLock && isLecturesLinkEnabled()) { + lecturesLink = LinkFactory.createToolLink("command.lectures", translate("command.lectures"), this, "o_icon_lecture"); + toolbarPanel.addTool(lecturesLink); + } + + if(!assessmentLock && !isGuestOnly) { + participantListLink = LinkFactory.createToolLink("participantlist", translate("command.participant.list"), this, "o_cmembers_icon"); + participantListLink.setVisible(cc.isParticipantListEnabled()); + toolbarPanel.addTool(participantListLink); + } + + if(!assessmentLock) { + participantInfoLink = LinkFactory.createToolLink("participantinfo", translate("command.participant.info"), this, "o_infomsg_icon"); + participantInfoLink.setVisible(cc.isParticipantInfoEnabled()); + toolbarPanel.addTool(participantInfoLink); + } + + if(!assessmentLock && !isGuestOnly && userCourseEnv != null && !userCourseEnv.isCourseReadOnly()) { + emailLink = LinkFactory.createToolLink("email", translate("command.email"), this, "o_co_icon"); + emailLink.setVisible(cc.isEmailEnabled()); + toolbarPanel.addTool(emailLink); + } + if(!assessmentLock) { glossary = new Dropdown("glossary", "command.glossary", false, getTranslator()); glossary.setIconCSS("o_icon o_FileResource-GLOSSARY_icon"); @@ -806,11 +836,6 @@ public class CourseRuntimeController extends RepositoryEntryRuntimeController im toolbarPanel.addTool(glossary); } - if(!assessmentLock && isLecturesLinkEnabled()) { - lecturesLink = LinkFactory.createToolLink("command.lectures", translate("command.lectures"), this, "o_icon_lecture"); - toolbarPanel.addTool(lecturesLink); - } - //add group chat to toolbox boolean chatIsEnabled = !assessmentLock && !isGuestOnly && imModule.isEnabled() && imModule.isCourseEnabled() && reSecurity.canLaunch(); @@ -828,7 +853,7 @@ public class CourseRuntimeController extends RepositoryEntryRuntimeController im toolbarPanel.addTool(searchLink); } } - + //check the configuration enable the lectures and the user is a teacher private boolean isLecturesLinkEnabled() { if(lectureModule.isEnabled()) { @@ -923,6 +948,12 @@ public class CourseRuntimeController extends RepositoryEntryRuntimeController im doAssessmentSurveyStatistics(ureq); } else if(assessmentLink == source) { doAssessmentTool(ureq); + } else if(participantListLink == source) { + doParticipantList(ureq); + } else if(participantInfoLink == source) { + doParticipantInfo(ureq); + } else if(emailLink == source) { + doEmail(ureq); } else if(calendarLink == source) { launchCalendar(ureq); } else if(chatLink == source) { @@ -1024,6 +1055,9 @@ public class CourseRuntimeController extends RepositoryEntryRuntimeController im case orders: doOrders(ureq); break; case close: doClose(ureq); break; case pop: popToRoot(ureq); cleanUp(); break; + case participantList: doParticipantList(ureq); break; + case participantInfo: doParticipantInfo(ureq); break; + case email: doEmail(ureq); break; } delayedClose = null; } else { @@ -1090,6 +1124,18 @@ public class CourseRuntimeController extends RepositoryEntryRuntimeController im } else if("Settings".equalsIgnoreCase(type) || "EditDescription".equalsIgnoreCase(type)) { List<ContextEntry> subEntries = entries.subList(1, entries.size()); doSettings(ureq, subEntries); + } else if("ParticipantList".equalsIgnoreCase(type)) { + if (participantListLink != null && participantListLink.isVisible()) { + doParticipantList(ureq); + } + } else if("ParticipantInfos".equalsIgnoreCase(type)) { + if (participantInfoLink != null && participantInfoLink.isVisible()) { + doParticipantInfo(ureq); + } + } else if("Email".equalsIgnoreCase(type)) { + if (emailLink != null && emailLink.isVisible()) { + doEmail(ureq); + } } else if("Certification".equalsIgnoreCase(type)) { doEfficiencyStatements(ureq); } else if("Reminders".equalsIgnoreCase(type) || "RemindersLogs".equalsIgnoreCase(type)) { @@ -1622,12 +1668,73 @@ public class CourseRuntimeController extends RepositoryEntryRuntimeController im listenTo(courseSearchCalloutCtr); } + private void doParticipantList(UserRequest ureq) { + if(delayedClose == Delayed.participantList || requestForClose(ureq)) { + removeCustomCSS(); + + OLATResourceable ores = OresHelper.createOLATResourceableType("ParticipantList"); + WindowControl swControl = addToHistory(ureq, ores, null); + participatListCtrl = new MembersToolRunController(ureq, swControl, getUserCourseEnvironment()); + + pushController(ureq, translate("command.participant.list"), participatListCtrl); + setActiveTool(participantListLink); + currentToolCtr = participatListCtrl; + } else { + delayedClose = Delayed.participantList; + }; + } + + private void doParticipantInfo(UserRequest ureq) { + if(delayedClose == Delayed.participantInfo || requestForClose(ureq)) { + removeCustomCSS(); + + boolean autoSubscribe = false; + boolean canAdd; + boolean canAdmin; + if(getUserCourseEnvironment().isCourseReadOnly()) { + canAdd = false; + canAdmin = false; + } else { + boolean isAdmin = getUserCourseEnvironment().isAdmin(); + canAdd = isAdmin; + canAdmin = isAdmin; + } + + OLATResourceable ores = OresHelper.createOLATResourceableType("ParticipantInfos"); + WindowControl swControl = addToHistory(ureq, ores, null); + participatInfoCtrl = new InfoRunController(ureq, swControl, getUserCourseEnvironment(), "ParticipantInfos", + canAdd, canAdmin, autoSubscribe); + + pushController(ureq, translate("command.participant.info"), participatInfoCtrl); + setActiveTool(participantInfoLink); + currentToolCtr = participatInfoCtrl; + } else { + delayedClose = Delayed.participantInfo; + }; + } + + private void doEmail(UserRequest ureq) { + if(delayedClose == Delayed.email || requestForClose(ureq)) { + removeCustomCSS(); + + OLATResourceable ores = OresHelper.createOLATResourceableType("email"); + WindowControl swControl = addToHistory(ureq, ores, null); + emailCtrl = new COToolController(ureq, swControl, getUserCourseEnvironment()); + + pushController(ureq, translate("command.email"), emailCtrl); + setActiveTool(emailLink); + currentToolCtr = emailCtrl; + } else { + delayedClose = Delayed.email; + }; + } + private void launchCalendar(UserRequest ureq) { ControllerCreator ctrlCreator = (lureq, lwControl) -> { ICourse course = CourseFactory.loadCourse(getRepositoryEntry()); ContextEntry ce = BusinessControlFactory.getInstance().createContextEntry(getRepositoryEntry()); WindowControl llwControl = BusinessControlFactory.getInstance().createBusinessWindowControl(ce, lwControl); - CourseCalendarController calendarController = new CourseCalendarController(lureq, llwControl, getUserCourseEnvironment()); + CourseCalendarController calendarController = new CourseCalendarController(lureq, llwControl, getUserCourseEnvironment()); // use a one-column main layout LayoutMain3ColsController layoutCtr = new LayoutMain3ColsController(lureq, llwControl, calendarController); layoutCtr.setCustomCSS(CourseFactory.getCustomCourseCss(lureq.getUserSession(), course.getCourseEnvironment())); @@ -1729,6 +1836,15 @@ public class CourseRuntimeController extends RepositoryEntryRuntimeController im private void processCourseConfigEvent(CourseConfigEvent event) { switch(event.getType()) { + case search: { + if(searchLink != null) { + ICourse course = CourseFactory.loadCourse(getRepositoryEntry()); + CourseConfig cc = course.getCourseEnvironment().getCourseConfig(); + searchLink.setVisible(cc.isCourseSearchEnabled()); + toolbarPanel.setDirty(true); + } + break; + } case calendar: { if(calendarLink != null) { ICourse course = CourseFactory.loadCourse(getRepositoryEntry()); @@ -1738,11 +1854,29 @@ public class CourseRuntimeController extends RepositoryEntryRuntimeController im } break; } - case search: { - if(searchLink != null) { + case participantList: { + if(participantListLink != null) { ICourse course = CourseFactory.loadCourse(getRepositoryEntry()); CourseConfig cc = course.getCourseEnvironment().getCourseConfig(); - searchLink.setVisible(cc.isCourseSearchEnabled()); + participantListLink.setVisible(cc.isParticipantListEnabled()); + toolbarPanel.setDirty(true); + } + break; + } + case participantInfo: { + if(participantInfoLink != null) { + ICourse course = CourseFactory.loadCourse(getRepositoryEntry()); + CourseConfig cc = course.getCourseEnvironment().getCourseConfig(); + participantInfoLink.setVisible(cc.isParticipantInfoEnabled()); + toolbarPanel.setDirty(true); + } + break; + } + case email: { + if(emailLink != null) { + ICourse course = CourseFactory.loadCourse(getRepositoryEntry()); + CourseConfig cc = course.getCourseEnvironment().getCourseConfig(); + emailLink.setVisible(cc.isEmailEnabled()); toolbarPanel.setDirty(true); } break; @@ -1883,6 +2017,9 @@ public class CourseRuntimeController extends RepositoryEntryRuntimeController im members, orders, close, - pop + pop, + participantList, + participantInfo, + email } } \ No newline at end of file diff --git a/src/main/java/org/olat/course/run/_i18n/LocalStrings_de.properties b/src/main/java/org/olat/course/run/_i18n/LocalStrings_de.properties index f2a30ca4e581faac8c0271f7e255e37f0287237c..fa932ad6d66cf76ff140b802c5521e5547d25c22 100644 --- a/src/main/java/org/olat/course/run/_i18n/LocalStrings_de.properties +++ b/src/main/java/org/olat/course/run/_i18n/LocalStrings_de.properties @@ -13,8 +13,9 @@ command.courseconfig=Kursinfo command.coursefolder=Ablageordner command.coursesearch=Kurssuche command.efficiencystatement=Leistungsnachweis +command.email=E-Mail command.glossary=Glossar -command.glossary.open=Glossar in separatem Fenster \u00f6ffnen +command.glossary.open=Glossar in separatem Fenster \u00F6ffnen command.glossary.off=aus command.glossary.off.alt=Glossarbegriffe von Lerninhalt ausblenden command.glossary.on=ein @@ -36,6 +37,8 @@ command.options=Optionen command.options.certificates=Leistungnachweis command.options.lectures.admin=Lektionen und Absenzen command.options.reminders=Erinnerung +command.participant.info=Teilnehmerinfos +command.participant.list=Teilnehmerliste command.personalnote=Notizen command.previous=Zur\u00FCck zur letzten Seite command.reminders=Erinnerung diff --git a/src/main/java/org/olat/course/run/_i18n/LocalStrings_en.properties b/src/main/java/org/olat/course/run/_i18n/LocalStrings_en.properties index 7869161e707d66e3a378d06d2807a5d204271c49..bbb9249bc7e9f17d4a3b77c10b8cf86aef0753c4 100644 --- a/src/main/java/org/olat/course/run/_i18n/LocalStrings_en.properties +++ b/src/main/java/org/olat/course/run/_i18n/LocalStrings_en.properties @@ -13,6 +13,7 @@ command.courseconfig=Course info command.coursefolder=Storage folder command.coursesearch=Course search command.efficiencystatement=Evidence of achievement +command.email=E-Mail command.glossary=Glossary command.glossary.off=off command.glossary.off.alt=Hide glossary terms of learning content @@ -36,6 +37,8 @@ command.options=Options command.options.certificates=Evidence of achievement command.options.lectures.admin=Lectures and absences command.options.reminders=Reminders +command.participant.info=Participant infos +command.participant.list=Participant list command.personalnote=Notes command.previous=Go to previous page command.reminders=Reminders diff --git a/src/main/java/org/olat/modules/co/ContactForm.java b/src/main/java/org/olat/modules/co/ContactForm.java index 0a3305e72e9dda3d898607eb2a65336af52219e1..1bbd87a17d9b7405067b3bc30e75199db8008fee 100644 --- a/src/main/java/org/olat/modules/co/ContactForm.java +++ b/src/main/java/org/olat/modules/co/ContactForm.java @@ -100,7 +100,7 @@ public class ContactForm extends FormBasicController { private FileElement attachmentEl; private List<FormLink> attachmentLinks = new ArrayList<>(); private FormLayoutContainer uploadCont; - private boolean recipientsAreEditable = false; + private final boolean recipientsAreEditable; private static final int emailCols = 60; private boolean readOnly=false; private boolean hasMsgCancel=false; @@ -146,6 +146,15 @@ public class ContactForm extends FormBasicController { tsubject.setMandatory(tsubject.isEnabled()); } + public void setRecipientsLists(List<ContactList> recipientsLists) { + contactLists.clear(); + tto.setValue(""); + ttoBig.setValue(""); + for (ContactList contactList : recipientsLists) { + addEmailTo(contactList); + } + } + /** * add a ContactList as EmailTo: * @@ -171,9 +180,6 @@ public class ContactForm extends FormBasicController { defaultEmailTo += tto.getValue(); tto.setValue(defaultEmailTo); ttoBig.setValue(defaultEmailTo); - - tto.setVisible(!recipientsAreEditable); - ttoBig.setVisible(recipientsAreEditable); } public void setBody(String defaultBody) { @@ -371,18 +377,17 @@ public class ContactForm extends FormBasicController { fullName = "[" + fullName + "]"; } tfrom = uifactory.addTextElement("ttfrom", NLS_CONTACT_FROM, 255, fullName, formLayout); - tfrom.setElementCssClass("o_sel_contact_to"); + tfrom.setElementCssClass("o_sel_contact_from"); // When no identity is set, let user enter a valid email address tfrom.setEnabled((this.emailFrom == null)); tto = uifactory.addTextElement("tto", NLS_CONTACT_TO, 255, "", formLayout); tto.setElementCssClass("o_sel_contact_to"); tto.setEnabled(false); - tto.setVisible(false); + tto.setVisible(!recipientsAreEditable); ttoBig = uifactory.addTextAreaElement("ttoBig", NLS_CONTACT_TO, -1, 2, emailCols, true, false, "", formLayout); - ttoBig.setEnabled(false); - ttoBig.setVisible(false); + ttoBig.setVisible(recipientsAreEditable); tsubject = uifactory.addTextElement("tsubject", NLS_CONTACT_SUBJECT, 255, "", formLayout); tsubject.setElementCssClass("o_sel_contact_subject"); @@ -422,5 +427,5 @@ public class ContactForm extends FormBasicController { protected void doDispose() { cleanUpAttachments(); } - + } \ No newline at end of file diff --git a/src/main/java/org/olat/modules/co/ContactFormController.java b/src/main/java/org/olat/modules/co/ContactFormController.java index 2153c8a9898d20a636d83280d3597713409d38fe..4561b8ad0d702a42c3a8e00d41c416d0c9033047 100644 --- a/src/main/java/org/olat/modules/co/ContactFormController.java +++ b/src/main/java/org/olat/modules/co/ContactFormController.java @@ -188,6 +188,12 @@ public class ContactFormController extends BasicController { } return null; } + + public void setRecipientsLists(List<ContactList> recipientsLists) { + if (cntctForm != null) { + cntctForm.setRecipientsLists(recipientsLists); + } + } private void init(UserRequest ureq, boolean hasAtLeastOneAddress, List<Identity> disabledIdentities) { if (hasAtLeastOneAddress) { diff --git a/src/main/java/org/olat/repository/RepositoryEntryManagedFlag.java b/src/main/java/org/olat/repository/RepositoryEntryManagedFlag.java index 8335710926ba27c30817ab8dc0f1419f9e01d74b..591545ab9feb558ef0895a08293ffec6b920c55e 100644 --- a/src/main/java/org/olat/repository/RepositoryEntryManagedFlag.java +++ b/src/main/java/org/olat/repository/RepositoryEntryManagedFlag.java @@ -21,8 +21,8 @@ package org.olat.repository; import java.util.Arrays; -import org.olat.core.CoreSpringFactory; import org.apache.logging.log4j.Logger; +import org.olat.core.CoreSpringFactory; import org.olat.core.logging.Tracing; import org.olat.core.util.StringHelper; @@ -47,6 +47,9 @@ public enum RepositoryEntryManagedFlag { settings(all),//max num of participants... access(settings,all), search(settings, all), + participantList(settings, all), + participantInfo(settings, all), + email(settings, all), chat(settings,all), layout(settings,all), resourcefolder(settings,all), diff --git a/src/main/java/org/olat/repository/ui/RepositoryEntryRuntimeController.java b/src/main/java/org/olat/repository/ui/RepositoryEntryRuntimeController.java index 640b2d205fa5d8b8a12036b1048d19b6ef62e3a7..e13aad62a35e4e9b40e535f91c6ceeb88468e12c 100644 --- a/src/main/java/org/olat/repository/ui/RepositoryEntryRuntimeController.java +++ b/src/main/java/org/olat/repository/ui/RepositoryEntryRuntimeController.java @@ -148,7 +148,7 @@ public class RepositoryEntryRuntimeController extends MainLayoutBasicController protected RepositoryEntrySecurity reSecurity; protected final Roles roles; - protected final boolean showInfos; + protected final boolean showDetails; protected final boolean allowBookmark; protected boolean corrupted; @@ -190,7 +190,7 @@ public class RepositoryEntryRuntimeController extends MainLayoutBasicController } public RepositoryEntryRuntimeController(UserRequest ureq, WindowControl wControl, RepositoryEntry re, - RepositoryEntrySecurity reSecurity, RuntimeControllerCreator runtimeControllerCreator, boolean allowBookmark, boolean showInfos) { + RepositoryEntrySecurity reSecurity, RuntimeControllerCreator runtimeControllerCreator, boolean allowBookmark, boolean showDetails) { super(ureq, wControl); setTranslator(Util.createPackageTranslator(RepositoryService.class, getLocale(), getTranslator())); @@ -208,7 +208,7 @@ public class RepositoryEntryRuntimeController extends MainLayoutBasicController } this.re = re; - this.showInfos = showInfos; + this.showDetails = showDetails; this.allowBookmark = allowBookmark; this.runtimeControllerCreator = runtimeControllerCreator; organisations = repositoryService.getOrganisationReferences(re); @@ -372,7 +372,7 @@ public class RepositoryEntryRuntimeController extends MainLayoutBasicController detailsLink = LinkFactory.createToolLink("details", translate("details.header"), this, "o_sel_repo_details"); detailsLink.setIconLeftCSS("o_icon o_icon-fw o_icon_details"); detailsLink.setElementCssClass("o_sel_author_details"); - detailsLink.setVisible(showInfos); + detailsLink.setVisible(showDetails); toolbarPanel.addTool(detailsLink); boolean marked = markManager.isMarked(re, getIdentity(), null);