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 b948478af4c5561a2fa7ccc4244bf426831781de..62c820b77fd4806510580b811e438bdae0d344b1 100644 --- a/src/main/java/org/olat/core/logging/activity/ActionObject.java +++ b/src/main/java/org/olat/core/logging/activity/ActionObject.java @@ -55,6 +55,7 @@ public enum ActionObject { feeditem, file, folder, + forum, forummessage, forumthread, glossar, 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 ba5d8cbb3f3e6142a5fd1ed4cc4210970df5bfbb..9725031a9d21dd481b454ddee8aed320b511f2e2 100644 --- a/src/main/java/org/olat/core/logging/activity/LearningResourceLoggingAction.java +++ b/src/main/java/org/olat/core/logging/activity/LearningResourceLoggingAction.java @@ -107,6 +107,10 @@ public class LearningResourceLoggingAction extends BaseLoggingAction { 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_FORUM_ENABLED = + new LearningResourceLoggingAction(ActionType.admin, CrudAction.update, ActionVerb.add, ActionObject.forum).setTypeList(LEARNING_RESOURCE_OPEN_CLOSE_LIST); + public static final ILoggingAction REPOSITORY_ENTRY_PROPERTIES_FORUM_DISABLED = + new LearningResourceLoggingAction(ActionType.admin, CrudAction.update, ActionVerb.remove, ActionObject.forum).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 = diff --git a/src/main/java/org/olat/course/config/CourseConfig.java b/src/main/java/org/olat/course/config/CourseConfig.java index 40e16246b07164e45d439472efbb147fa0cda3f3..b0245530be83c894abe602807168ef3ea0773442 100644 --- a/src/main/java/org/olat/course/config/CourseConfig.java +++ b/src/main/java/org/olat/course/config/CourseConfig.java @@ -74,7 +74,7 @@ public class CourseConfig implements Serializable, Cloneable { /** * current config file version */ - private static final transient int CURRENTVERSION = 16; + private static final transient int CURRENTVERSION = 17; public static final transient String KEY_LOGLEVEL_ADMIN = "LOGLEVELADMIN"; public static final transient String KEY_LOGLEVEL_USER = "LOGLEVELUSER"; @@ -103,6 +103,8 @@ public class CourseConfig implements Serializable, Cloneable { 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 FORUM_ENABLED = "FORUM_ENABLED"; + public static final transient String DOCUMENTS_ENABLED = "DOCUMENTS_ENABLED"; public static final transient String KEY_CALENDAR_ENABLED = "KEY_CALENDAR_ENABLED"; public static final transient String KEY_GLOSSARY_ENABLED = "KEY_GLOSSARY_ENABLED"; @@ -169,6 +171,8 @@ public class CourseConfig implements Serializable, Cloneable { configuration.put(PARTICIPANT_LIST_ENABLED, Boolean.FALSE); configuration.put(PARTICIPANT_INFO_ENABLED, Boolean.FALSE); configuration.put(EMAIL_ENABLED, Boolean.FALSE); + configuration.put(FORUM_ENABLED, Boolean.FALSE); + configuration.put(DOCUMENTS_ENABLED, Boolean.FALSE); configuration.put(NODE_ACCESS_TYPE, NODE_ACCESS_TYPE_DEFAULT); @@ -277,6 +281,13 @@ public class CourseConfig implements Serializable, Cloneable { this.version = 16; } + + if (version == 17) { + if (!configuration.containsKey(FORUM_ENABLED)) configuration.put(FORUM_ENABLED, Boolean.FALSE); + if (!configuration.containsKey(DOCUMENTS_ENABLED)) configuration.put(FORUM_ENABLED, Boolean.FALSE); + + this.version = 17; + } /* @@ -584,6 +595,24 @@ public class CourseConfig implements Serializable, Cloneable { configuration.put(EMAIL_ENABLED, Boolean.valueOf(b)); } + public boolean isForumEnabled() { + Boolean bool = (Boolean) configuration.get(FORUM_ENABLED); + return bool.booleanValue(); + } + + public void setForumEnabled(boolean b) { + configuration.put(FORUM_ENABLED, Boolean.valueOf(b)); + } + + public boolean isDocumentsEnabled() { + Boolean bool = (Boolean) configuration.get(DOCUMENTS_ENABLED); + return bool.booleanValue(); + } + + public void setDocumentsEnabled(boolean b) { + configuration.put(DOCUMENTS_ENABLED, Boolean.valueOf(b)); + } + public boolean isToolbarEnabled() { Boolean bool = (Boolean) configuration.get(TOOLBAR_ENABLED); return bool.booleanValue(); @@ -629,6 +658,8 @@ public class CourseConfig implements Serializable, Cloneable { clone.setParticipantListEnabled(isParticipantListEnabled()); clone.setParticipantInfoEnabled(isParticipantInfoEnabled()); clone.setEmailEnabled(isEmailEnabled()); + clone.setForumEnabled(isForumEnabled()); + clone.setDocumentsEnabled(isDocumentsEnabled()); return clone; } diff --git a/src/main/java/org/olat/course/config/CourseConfigEvent.java b/src/main/java/org/olat/course/config/CourseConfigEvent.java index 9265caad49691b9b2784bc8cd46872e97cd5e626..55e52b0cae0032405f65f80af1df554b4ebdd534 100644 --- a/src/main/java/org/olat/course/config/CourseConfigEvent.java +++ b/src/main/java/org/olat/course/config/CourseConfigEvent.java @@ -63,6 +63,7 @@ public class CourseConfigEvent extends MultiUserEvent { participantList, participantInfo, email, + forum, 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 2e7b52cc514d1453243e2f839c4989d177b8a00b..300b2d8c4f6acf8bac761715f3b32571bf8b7da2 100644 --- a/src/main/java/org/olat/course/config/ui/CourseToolbarController.java +++ b/src/main/java/org/olat/course/config/ui/CourseToolbarController.java @@ -73,6 +73,7 @@ public class CourseToolbarController extends FormBasicController { private SelectionElement participantListEl; private SelectionElement participantInfoEl; private SelectionElement emailEl; + private SelectionElement forumEl; private SelectionElement chatEl; private SelectionElement glossaryEl; @@ -180,6 +181,15 @@ public class CourseToolbarController extends FormBasicController { canHideToolbar &= false; } + boolean forumEnabled = courseConfig.isForumEnabled(); + boolean managedForum = RepositoryEntryManagedFlag.isManaged(entry, RepositoryEntryManagedFlag.forum); + forumEl = uifactory.addCheckboxesHorizontal("forumIsOn", "chkbx.forum.onoff", formLayout, onKeys, onValues); + forumEl.select(onKeys[0], forumEnabled); + forumEl.setEnabled(editable && !managedEmail); + if(managedForum && forumEnabled) { + canHideToolbar &= false; + } + boolean chatEnabled = courseConfig.isChatEnabled(); boolean managedChat = RepositoryEntryManagedFlag.isManaged(entry, RepositoryEntryManagedFlag.chat); chatEl = uifactory.addCheckboxesHorizontal("chatIsOn", "chkbx.chat.onoff", formLayout, onKeys, onValues); @@ -227,6 +237,7 @@ public class CourseToolbarController extends FormBasicController { || participantListEl.isSelected(0) || participantInfoEl.isSelected(0) || emailEl.isSelected(0) + || forumEl.isSelected(0) || chatEl.isSelected(0) || glossaryEl.isSelected(0); } @@ -241,6 +252,7 @@ public class CourseToolbarController extends FormBasicController { participantListEl.setVisible(enabled); participantInfoEl.setVisible(enabled); emailEl.setVisible(enabled); + forumEl.setVisible(enabled); chatEl.setVisible(enabled); glossaryEl.setVisible(enabled); } @@ -274,6 +286,10 @@ public class CourseToolbarController extends FormBasicController { boolean updateEmail = courseConfig.isEmailEnabled() != enableEmail; courseConfig.setEmailEnabled(enableEmail && toolbarEnabled); + boolean enableForum = forumEl.isSelected(0); + boolean updateForum = courseConfig.isForumEnabled() != enableForum; + courseConfig.setForumEnabled(enableForum && toolbarEnabled); + boolean enableChat = chatEl.isSelected(0); boolean updateChat = courseConfig.isChatEnabled() != enableChat; courseConfig.setChatIsEnabled(enableChat && toolbarEnabled); @@ -337,6 +353,16 @@ public class CourseToolbarController extends FormBasicController { .fireEventToListenersOf(new CourseConfigEvent(CourseConfigType.email, course.getResourceableId()), course); } + if(updateForum) { + ILoggingAction loggingAction = enableForum ? + LearningResourceLoggingAction.REPOSITORY_ENTRY_PROPERTIES_FORUM_ENABLED: + LearningResourceLoggingAction.REPOSITORY_ENTRY_PROPERTIES_FORUM_DISABLED; + ThreadLocalUserActivityLogger.log(loggingAction, getClass()); + + CoordinatorManager.getInstance().getCoordinator().getEventBus() + .fireEventToListenersOf(new CourseConfigEvent(CourseConfigType.forum, course.getResourceableId()), course); + } + if(updateChat) { ILoggingAction loggingAction =enableChat ? LearningResourceLoggingAction.REPOSITORY_ENTRY_PROPERTIES_IM_ENABLED: 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 c69e1b4036d43888272d36b5635a9c85a874ecf0..08d41f9b4cb5dac210956bfcb4cbcf6152ec781b 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 @@ -3,6 +3,7 @@ chkbx.calendar.onoff=Kurskalender chkbx.chat.onoff=Kurs-Chat chkbx.efficency.onoff=Leistungsnachweis verwenden chkbx.email.onoff=E-Mail +chkbx.forum.onoff=Forum 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 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 6007cec9805e2391fac17632b589bacc63feea2a..820d771b41374c44299adb3cda2f2469bf4108cb 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 @@ -3,6 +3,7 @@ chkbx.calendar.onoff=Course calendar chkbx.chat.onoff=Course chat chkbx.search.onoff=Course search chkbx.email.onoff=E-mail +chkbx.forum.onoff=Forum 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". diff --git a/src/main/java/org/olat/course/nodes/fo/FOToolController.java b/src/main/java/org/olat/course/nodes/fo/FOToolController.java new file mode 100644 index 0000000000000000000000000000000000000000..2aaf6325be0ed01f8b0880f41c0cfe35ae995e2e --- /dev/null +++ b/src/main/java/org/olat/course/nodes/fo/FOToolController.java @@ -0,0 +1,211 @@ +/** + * <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.fo; + +import org.olat.core.commons.services.notifications.SubscriptionContext; +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.course.run.userview.UserCourseEnvironment; +import org.olat.modules.fo.Forum; +import org.olat.modules.fo.ForumCallback; +import org.olat.modules.fo.manager.ForumManager; +import org.olat.modules.fo.ui.ForumController; +import org.olat.repository.RepositoryEntry; +import org.springframework.beans.factory.annotation.Autowired; + +/** + * + * Initial date: 13 Sep 2019<br> + * @author uhensler, urs.hensler@frentix.com, http://www.frentix.com + * + */ +public class FOToolController extends BasicController { + + private static final String SUBSCRIPTION_SUBIDENTIFIER = "forum"; + + private final ForumController forumCtrl; + + @Autowired + private ForumManager forumManager; + + public FOToolController(UserRequest ureq, WindowControl wControl, UserCourseEnvironment userCourseEnv) { + super(ureq, wControl); + + RepositoryEntry courseEntry = userCourseEnv.getCourseEnvironment().getCourseGroupManager().getCourseEntry(); + Forum forum = getOrCreateForum(courseEntry); + + + SubscriptionContext forumSubContext = new SubscriptionContext(courseEntry, SUBSCRIPTION_SUBIDENTIFIER); + ForumCallback forumCallback = userCourseEnv.isCourseReadOnly() || ureq.getUserSession().getRoles().isGuestOnly() + ? new ReadOnlyForumCallback(userCourseEnv) + : new ToolSecurityCallback(userCourseEnv, forumSubContext); + + forumCtrl = new ForumController(ureq, wControl, forum, forumCallback, true); + listenTo(forumCtrl); + putInitialPanel(forumCtrl.getInitialComponent()); + } + + private Forum getOrCreateForum(RepositoryEntry courseEntry) { + Forum forum = forumManager.loadForum(courseEntry); + if (forum == null) { + forum = forumManager.addAForum(courseEntry); + } + return forum; + } + + @Override + protected void event(UserRequest ureq, Component source, Event event) { + // + } + + @Override + protected void doDispose() { + // + } + + private static class ToolSecurityCallback implements ForumCallback { + + private final boolean admin; + private final boolean coach; + private final SubscriptionContext subscriptionContext; + + private ToolSecurityCallback(UserCourseEnvironment userCourseEnv, SubscriptionContext subscriptionContext) { + this.admin = userCourseEnv.isAdmin(); + this.coach = userCourseEnv.isCoach(); + this.subscriptionContext = subscriptionContext; + } + + @Override + public boolean mayUsePseudonym() { + return false; + } + + @Override + public boolean mayOpenNewThread() { + return true; + } + + @Override + public boolean mayReplyMessage() { + return true; + } + + @Override + public boolean mayEditOwnMessage() { + return true; + } + + @Override + public boolean mayDeleteOwnMessage() { + return true; + } + + @Override + public boolean mayEditMessageAsModerator() { + return admin || coach; + } + + @Override + public boolean mayDeleteMessageAsModerator() { + return admin || coach; + } + + @Override + public boolean mayArchiveForum() { + return false; + } + + @Override + public boolean mayFilterForUser() { + return admin || coach; + } + + @Override + public SubscriptionContext getSubscriptionContext() { + return subscriptionContext; + } + + } + + private static class ReadOnlyForumCallback implements ForumCallback { + + private final boolean admin; + private final boolean coach; + + public ReadOnlyForumCallback(UserCourseEnvironment userCourseEnv) { + this.admin = userCourseEnv.isAdmin(); + this.coach = userCourseEnv.isCoach(); + } + + @Override + public boolean mayUsePseudonym() { + return false; + } + + @Override + public boolean mayOpenNewThread() { + return false; + } + + @Override + public boolean mayReplyMessage() { + return false; + } + + @Override + public boolean mayEditOwnMessage() { + return false; + } + + @Override + public boolean mayDeleteOwnMessage() { + return false; + } + + @Override + public boolean mayEditMessageAsModerator() { + return false; + } + + @Override + public boolean mayDeleteMessageAsModerator() { + return false; + } + + @Override + public boolean mayArchiveForum() { + return false; + } + + @Override + public boolean mayFilterForUser() { + return admin || coach; + } + + @Override + public SubscriptionContext getSubscriptionContext() { + return null; + } + } + +} diff --git a/src/main/java/org/olat/course/run/CourseRuntimeController.java b/src/main/java/org/olat/course/run/CourseRuntimeController.java index e227298964a19f402b451bbb31bbe3e51b2bb36a..dba0e1fc6dc7eb38a29919852a6f47b3b6b7984f 100644 --- a/src/main/java/org/olat/course/run/CourseRuntimeController.java +++ b/src/main/java/org/olat/course/run/CourseRuntimeController.java @@ -106,6 +106,7 @@ 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.fo.FOToolController; import org.olat.course.nodes.info.InfoRunController; import org.olat.course.nodes.members.MembersToolRunController; import org.olat.course.reminder.ui.CourseRemindersController; @@ -178,7 +179,8 @@ public class CourseRuntimeController extends RepositoryEntryRuntimeController im //my course efficiencyStatementsLink, noteLink, leaveLink, //course tools - learninPathLink, calendarLink, chatLink, participantListLink, participantInfoLink, emailLink, searchLink, + learninPathLink, calendarLink, chatLink, participantListLink, participantInfoLink, forumLink, emailLink, + searchLink, //glossary openGlossaryLink, enableGlossaryLink, lecturesLink; private Link currentUserCountLink; @@ -186,6 +188,7 @@ public class CourseRuntimeController extends RepositoryEntryRuntimeController im private CloseableModalController cmc; private COToolController emailCtrl; + private FOToolController forumCtrl; private CourseAreasController areasCtrl; private ConfirmLeaveController leaveDialogBox; private ArchiverMainController archiverCtrl; @@ -830,6 +833,12 @@ public class CourseRuntimeController extends RepositoryEntryRuntimeController im toolbarPanel.addTool(emailLink); } + if(!assessmentLock) { + forumLink = LinkFactory.createToolLink("forum", translate("command.forum"), this, "o_fo_icon"); + forumLink.setVisible(cc.isForumEnabled()); + toolbarPanel.addTool(forumLink); + } + if(!assessmentLock) { glossary = new Dropdown("glossary", "command.glossary", false, getTranslator()); glossary.setIconCSS("o_icon o_FileResource-GLOSSARY_icon"); @@ -962,6 +971,8 @@ public class CourseRuntimeController extends RepositoryEntryRuntimeController im doParticipantInfo(ureq); } else if(emailLink == source) { doEmail(ureq); + } else if(forumLink == source) { + doForum(ureq); } else if(learninPathLink == source) { doLearningPath(ureq); } else if(calendarLink == source) { @@ -1069,6 +1080,7 @@ public class CourseRuntimeController extends RepositoryEntryRuntimeController im case participantList: doParticipantList(ureq); break; case participantInfo: doParticipantInfo(ureq); break; case email: doEmail(ureq); break; + case forum: doForum(ureq); break; } delayedClose = null; } else { @@ -1151,6 +1163,10 @@ public class CourseRuntimeController extends RepositoryEntryRuntimeController im if (emailLink != null && emailLink.isVisible()) { doEmail(ureq); } + } else if("Forum".equalsIgnoreCase(type)) { + if (forumLink != null && forumLink.isVisible()) { + doForum(ureq); + } } else if("Certification".equalsIgnoreCase(type)) { doEfficiencyStatements(ureq); } else if("Reminders".equalsIgnoreCase(type) || "RemindersLogs".equalsIgnoreCase(type)) { @@ -1760,6 +1776,22 @@ public class CourseRuntimeController extends RepositoryEntryRuntimeController im }; } + private void doForum(UserRequest ureq) { + if(delayedClose == Delayed.forum || requestForClose(ureq)) { + removeCustomCSS(); + + OLATResourceable ores = OresHelper.createOLATResourceableType("forum"); + WindowControl swControl = addToHistory(ureq, ores, null); + forumCtrl = new FOToolController(ureq, swControl, getUserCourseEnvironment()); + + pushController(ureq, translate("command.forum"), forumCtrl); + setActiveTool(forumLink); + currentToolCtr = forumCtrl; + } else { + delayedClose = Delayed.forum; + }; + } + private void launchCalendar(UserRequest ureq) { ControllerCreator ctrlCreator = (lureq, lwControl) -> { ICourse course = CourseFactory.loadCourse(getRepositoryEntry()); @@ -1912,6 +1944,15 @@ public class CourseRuntimeController extends RepositoryEntryRuntimeController im } break; } + case forum: { + if(forumLink != null) { + ICourse course = CourseFactory.loadCourse(getRepositoryEntry()); + CourseConfig cc = course.getCourseEnvironment().getCourseConfig(); + forumLink.setVisible(cc.isForumEnabled()); + toolbarPanel.setDirty(true); + } + break; + } case chat: { if(chatLink != null) { ICourse course = CourseFactory.loadCourse(getRepositoryEntry()); @@ -2052,6 +2093,7 @@ public class CourseRuntimeController extends RepositoryEntryRuntimeController im pop, participantList, participantInfo, - email + email, + forum } } \ 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 0dfba24b95589d6c10e52c8b6c5db97b3738b131..e61d9057560eeefdea2f3688db6b244bbe91c704 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 @@ -14,6 +14,7 @@ command.coursefolder=Ablageordner command.coursesearch=Kurssuche command.efficiencystatement=Leistungsnachweis command.email=E-Mail +command.forum=Forum command.glossary=Glossar command.glossary.open=Glossar in separatem Fenster \u00F6ffnen command.glossary.off=aus 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 e70f42d6494b9ad4016e2f5104b1ed89781712b1..d46f5e276ef47b0b130f82908ca7c1b67f01b43c 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 @@ -14,6 +14,7 @@ command.coursefolder=Storage folder command.coursesearch=Course search command.efficiencystatement=Evidence of achievement command.email=E-Mail +command.forum=Forum command.glossary=Glossary command.glossary.off=off command.glossary.off.alt=Hide glossary terms of learning content diff --git a/src/main/java/org/olat/modules/fo/Forum.java b/src/main/java/org/olat/modules/fo/Forum.java index 5590cf35d85fdb18dabd0430872975815aa0dd61..be748b5a2a6a51861bca084810724f85642a2ed5 100644 --- a/src/main/java/org/olat/modules/fo/Forum.java +++ b/src/main/java/org/olat/modules/fo/Forum.java @@ -35,5 +35,8 @@ import org.olat.core.id.Persistable; * @author Felix Jost */ public interface Forum extends CreateInfo, Persistable, OLATResourceable { - // nothing to be declared + + public OLATResourceable getReference(); + + public void setReference(OLATResourceable ores); } \ No newline at end of file diff --git a/src/main/java/org/olat/modules/fo/manager/ForumManager.java b/src/main/java/org/olat/modules/fo/manager/ForumManager.java index 9efe68af6d2c10834fb367cac788fa57d5965d30..d43e87ce37557302771c9a485ce18bd10f3c121e 100644 --- a/src/main/java/org/olat/modules/fo/manager/ForumManager.java +++ b/src/main/java/org/olat/modules/fo/manager/ForumManager.java @@ -40,6 +40,7 @@ import java.util.Set; import javax.persistence.TemporalType; import javax.persistence.TypedQuery; +import org.apache.logging.log4j.Logger; import org.olat.basesecurity.IdentityRef; import org.olat.core.commons.modules.bc.FolderConfig; import org.olat.core.commons.persistence.DB; @@ -50,7 +51,6 @@ import org.olat.core.commons.services.text.TextService; import org.olat.core.id.Identity; import org.olat.core.id.OLATResourceable; import org.olat.core.logging.AssertException; -import org.apache.logging.log4j.Logger; import org.olat.core.logging.Tracing; import org.olat.core.util.Encoder; import org.olat.core.util.Encoder.Algorithm; @@ -706,8 +706,13 @@ public class ForumManager { * @return the newly created and persisted forum */ public Forum addAForum() { + return addAForum(null); + } + + public Forum addAForum(OLATResourceable refrence) { ForumImpl fo = new ForumImpl(); fo.setCreationDate(new Date()); + fo.setReference(refrence); dbInstance.getCurrentEntityManager().persist(fo); return fo; } @@ -724,6 +729,16 @@ public class ForumManager { .getResultList(); return forumList == null || forumList.isEmpty() ? null : forumList.get(0); } + + public Forum loadForum(OLATResourceable refrence) { + String q = "select fo from forum as fo where fo.refResName=:refResName and fo.refResId=:refResId"; + List<Forum> forumList = dbInstance.getCurrentEntityManager() + .createQuery(q, Forum.class) + .setParameter("refResName", refrence.getResourceableTypeName()) + .setParameter("refResId", refrence.getResourceableId()) + .getResultList(); + return forumList == null || forumList.isEmpty() ? null : forumList.get(0); + } /** * @param forumKey diff --git a/src/main/java/org/olat/modules/fo/model/ForumImpl.java b/src/main/java/org/olat/modules/fo/model/ForumImpl.java index 11635603b6ae47720a7899dd958fe26170539485..55754a98f0c9dd9dceb899160847cd4f4f0359a4 100644 --- a/src/main/java/org/olat/modules/fo/model/ForumImpl.java +++ b/src/main/java/org/olat/modules/fo/model/ForumImpl.java @@ -39,6 +39,7 @@ import javax.persistence.Version; import org.hibernate.annotations.GenericGenerator; import org.hibernate.annotations.Parameter; import org.olat.core.id.CreateInfo; +import org.olat.core.id.OLATResourceable; import org.olat.core.id.Persistable; import org.olat.core.logging.AssertException; import org.olat.core.util.resource.OresHelper; @@ -74,6 +75,11 @@ public class ForumImpl implements Forum, CreateInfo, Persistable{ @Temporal(TemporalType.TIMESTAMP) @Column(name="creationdate", nullable=false, insertable=true, updatable=false) private Date creationDate; + + @Column(name="f_refresname", nullable=true, insertable=true, updatable=false) + private String refResName; + @Column(name="f_refresid", nullable=true, insertable=true, updatable=false) + private Long refResId; @Override public Long getKey() { @@ -108,6 +114,33 @@ public class ForumImpl implements Forum, CreateInfo, Persistable{ return id; } + @Override + public void setReference(OLATResourceable ores) { + if (ores != null) { + this.refResName = ores.getResourceableTypeName(); + this.refResId = ores.getResourceableId(); + } else { + this.refResName = null; + this.refResId = null; + } + } + + @Override + public OLATResourceable getReference() { + return new OLATResourceable() { + + @Override + public String getResourceableTypeName() { + return refResName; + } + + @Override + public Long getResourceableId() { + return refResId; + } + }; + } + @Override public int hashCode() { return key == null ? 835245 : key.hashCode(); diff --git a/src/main/java/org/olat/repository/RepositoryEntryManagedFlag.java b/src/main/java/org/olat/repository/RepositoryEntryManagedFlag.java index 591545ab9feb558ef0895a08293ffec6b920c55e..b6011ea310b8e3d31188631beedc54a643c38140 100644 --- a/src/main/java/org/olat/repository/RepositoryEntryManagedFlag.java +++ b/src/main/java/org/olat/repository/RepositoryEntryManagedFlag.java @@ -50,6 +50,7 @@ public enum RepositoryEntryManagedFlag { participantList(settings, all), participantInfo(settings, all), email(settings, all), + forum(settings, all), chat(settings,all), layout(settings,all), resourcefolder(settings,all), diff --git a/src/main/resources/database/mysql/alter_14_2_x_to_15_0_0.sql b/src/main/resources/database/mysql/alter_14_2_x_to_15_0_0.sql index 3171b6b3f8584666296fae0a420835f57cf7991f..3daaf6c051df08da9fe9fcfd2b7689c42c299986 100644 --- a/src/main/resources/database/mysql/alter_14_2_x_to_15_0_0.sql +++ b/src/main/resources/database/mysql/alter_14_2_x_to_15_0_0.sql @@ -3,3 +3,8 @@ alter table o_as_entry add a_first_visit datetime; alter table o_as_entry add a_last_visit datetime; alter table o_as_entry add a_num_visits int8; alter table o_as_entry add a_date_done datetime; + +-- forum +alter table o_forum add f_refresname varchar(50); +alter table o_forum add f_refresid bigint; +create index idx_forum_ref_idx on o_forum (f_refresid, f_refresname); diff --git a/src/main/resources/database/mysql/setupDatabase.sql b/src/main/resources/database/mysql/setupDatabase.sql index 5f619e2b8cd9de53a99aa63044f1c2d7b85f270c..daeb2b0b2edabdf2a962931d6cb513e638e1b5de 100644 --- a/src/main/resources/database/mysql/setupDatabase.sql +++ b/src/main/resources/database/mysql/setupDatabase.sql @@ -4,6 +4,8 @@ create table if not exists o_forum ( forum_id bigint not null, version mediumint unsigned not null, creationdate datetime, + f_refresname varchar(50), + f_refresid bigint, primary key (forum_id) ); create table o_forum_pseudonym ( @@ -3547,6 +3549,7 @@ create index mark_subpath_idx on o_mark(ressubpath(255)); create index mark_businesspath_idx on o_mark(businesspath(255)); -- forum +create index idx_forum_ref_idx on o_forum (f_refresid, f_refresname); alter table o_message add constraint FKF26C8375236F20E foreign key (creator_id) references o_bs_identity (id); alter table o_message add constraint FKF26C837A3FBEB83 foreign key (modifier_id) references o_bs_identity (id); alter table o_message add constraint FKF26C8377B66B0D0 foreign key (parent_id) references o_message (message_id); diff --git a/src/main/resources/database/oracle/alter_14_2_x_to_15_0_0.sql b/src/main/resources/database/oracle/alter_14_2_x_to_15_0_0.sql index cf8eba16f1773a737d56959ee530945a28bcb49a..a9e5d98d13fbcc96436980272434f9ba61e84d5e 100644 --- a/src/main/resources/database/oracle/alter_14_2_x_to_15_0_0.sql +++ b/src/main/resources/database/oracle/alter_14_2_x_to_15_0_0.sql @@ -3,3 +3,9 @@ alter table o_as_entry add a_first_visit date; alter table o_as_entry add a_last_visit date; alter table o_as_entry add a_num_visits number(20); alter table o_as_entry add a_date_done date; + +-- Forum +alter table o_forum add f_refresname varchar(50); +alter table o_forum add f_refresid number(20); +create index idx_forum_ref_idx on o_forum (f_refresid, f_refresname); + diff --git a/src/main/resources/database/oracle/setupDatabase.sql b/src/main/resources/database/oracle/setupDatabase.sql index 9da5127079a41136b1331ab0df86f53d4861a69b..eb0df25fc8103393ed166ff8c2d07aa4a851b432 100644 --- a/src/main/resources/database/oracle/setupDatabase.sql +++ b/src/main/resources/database/oracle/setupDatabase.sql @@ -5,6 +5,8 @@ CREATE TABLE o_forum ( forum_id number(20) NOT NULL, version number(20) NOT NULL, creationdate date, + f_refresname varchar(50), + f_refresid number(20), PRIMARY KEY (forum_id) ); CREATE TABLE o_forum_pseudonym ( @@ -3563,6 +3565,7 @@ create index mark_subpath_idx on o_mark(substr(ressubpath,0,255)); create index mark_businesspath_idx on o_mark(substr(businesspath,0,255)); -- forum +create index idx_forum_ref_idx on o_forum (f_refresid, f_refresname); alter table o_message add constraint FKF26C8375236F20E foreign key (creator_id) references o_bs_identity (id); create index FKF26C8375236F20E on o_message (creator_id); alter table o_message add constraint FKF26C837A3FBEB83 foreign key (modifier_id) references o_bs_identity (id); diff --git a/src/main/resources/database/postgresql/alter_14_2_x_to_15_0_0.sql b/src/main/resources/database/postgresql/alter_14_2_x_to_15_0_0.sql index 806c9d9c5c0d73cebc33d988378f4ac8899956b5..d83f14debe3271d359b00ca1ff2f966875005920 100644 --- a/src/main/resources/database/postgresql/alter_14_2_x_to_15_0_0.sql +++ b/src/main/resources/database/postgresql/alter_14_2_x_to_15_0_0.sql @@ -3,3 +3,8 @@ alter table o_as_entry add a_first_visit timestamp; alter table o_as_entry add a_last_visit timestamp; alter table o_as_entry add a_num_visits int8; alter table o_as_entry add a_date_done timestamp; + +-- Forum +alter table o_forum add f_refresname varchar(50); +alter table o_forum add f_refresid bigint; +create index idx_forum_ref_idx on o_forum (f_refresid, f_refresname); diff --git a/src/main/resources/database/postgresql/setupDatabase.sql b/src/main/resources/database/postgresql/setupDatabase.sql index 1a40cb4c398345e0ba90bbd1ee7784e708733800..48e3fcb881f370301a9af78554ca9df328921f35 100644 --- a/src/main/resources/database/postgresql/setupDatabase.sql +++ b/src/main/resources/database/postgresql/setupDatabase.sql @@ -2,6 +2,8 @@ create table o_forum ( forum_id int8 not null, version int4 not null, creationdate timestamp, + f_refresname varchar(50), + f_refresid bigint, primary key (forum_id) ); create table o_forum_pseudonym ( @@ -3456,6 +3458,7 @@ create index mark_subpath_idx on o_mark(ressubpath); create index mark_businesspath_idx on o_mark(businesspath); -- forum +create index idx_forum_ref_idx on o_forum (f_refresid, f_refresname); alter table o_message add constraint FKF26C8375236F20E foreign key (creator_id) references o_bs_identity; create index idx_message_creator_idx on o_message (creator_id); alter table o_message add constraint FKF26C837A3FBEB83 foreign key (modifier_id) references o_bs_identity; diff --git a/src/test/java/org/olat/modules/fo/ForumManagerTest.java b/src/test/java/org/olat/modules/fo/ForumManagerTest.java index 121ef64eae26f8de90196d7a1225964baf7c2287..2bd6074c560aa09f29be86d17fdbc0284c0e810c 100644 --- a/src/test/java/org/olat/modules/fo/ForumManagerTest.java +++ b/src/test/java/org/olat/modules/fo/ForumManagerTest.java @@ -45,6 +45,7 @@ import org.olat.modules.fo.model.ForumUserStatistics; import org.olat.modules.fo.model.MessageImpl; import org.olat.modules.fo.model.PseudonymStatistics; import org.olat.modules.fo.ui.MessagePeekview; +import org.olat.repository.RepositoryEntry; import org.olat.test.JunitTestHelper; import org.olat.test.OlatTestCase; import org.olat.user.UserManager; @@ -67,6 +68,27 @@ public class ForumManagerTest extends OlatTestCase { @Autowired public BaseSecurity securityManager; + @Test + public void addAForum() { + Forum fo = forumManager.addAForum(); + dbInstance.commitAndCloseSession(); + + fo = forumManager.loadForum(fo.getKey()); + + Assert.assertNotNull(fo); + } + + @Test + public void addAForumForOlatResourceable() { + RepositoryEntry repositoryEntry = JunitTestHelper.createAndPersistRepositoryEntry(); + Forum fo = forumManager.addAForum(repositoryEntry); + dbInstance.commitAndCloseSession(); + + fo = forumManager.loadForum(repositoryEntry); + + Assert.assertNotNull(fo); + } + @Test public void getThread() { Identity id = JunitTestHelper.createAndPersistIdentityAsRndUser("fo-4");