From 8de06c2dd6b6f511f34684eaf6b2e8cd5bb73894 Mon Sep 17 00:00:00 2001 From: uhensler <urs.hensler@frentix.com> Date: Fri, 21 Feb 2020 16:44:03 +0100 Subject: [PATCH] OO-4533: Configurations for create and manage notifications --- .../org/olat/course/nodes/InfoCourseNode.java | 105 +++++++++++++----- ...figForm.java => InfoConfigController.java} | 99 ++++++++++++++--- .../info/InfoCourseNodeEditController.java | 71 ++++++------ .../info/InfoCourseSecurityCallback.java | 56 ++++++++++ .../course/nodes/info/InfoRunController.java | 90 ++++++++------- .../olat/course/nodes/info/_content/edit.html | 1 - .../info/_i18n/LocalStrings_de.properties | 5 + .../info/_i18n/LocalStrings_en.properties | 5 + .../course/run/CourseRuntimeController.java | 5 +- 9 files changed, 310 insertions(+), 127 deletions(-) rename src/main/java/org/olat/course/nodes/info/{InfoConfigForm.java => InfoConfigController.java} (55%) create mode 100644 src/main/java/org/olat/course/nodes/info/InfoCourseSecurityCallback.java delete mode 100644 src/main/java/org/olat/course/nodes/info/_content/edit.html diff --git a/src/main/java/org/olat/course/nodes/InfoCourseNode.java b/src/main/java/org/olat/course/nodes/InfoCourseNode.java index 395be586f44..e3f1cf61ebb 100644 --- a/src/main/java/org/olat/course/nodes/InfoCourseNode.java +++ b/src/main/java/org/olat/course/nodes/InfoCourseNode.java @@ -41,6 +41,7 @@ import org.olat.course.ICourse; import org.olat.course.condition.Condition; import org.olat.course.condition.interpreter.ConditionExpression; import org.olat.course.condition.interpreter.ConditionInterpreter; +import org.olat.course.editor.ConditionAccessEditConfig; import org.olat.course.editor.CourseEditorEnv; import org.olat.course.editor.NodeEditController; import org.olat.course.editor.StatusDescription; @@ -66,10 +67,20 @@ import org.olat.repository.RepositoryEntry; * @author srosse, stephane.rosse@frentix.com, http://www.frentix.com */ public class InfoCourseNode extends AbstractAccessableCourseNode { + + @SuppressWarnings("deprecation") + private static final String TRANSLATOR_PACKAGE = Util.getPackageName(InfoCourseNodeEditController.class); public static final String TYPE = "info"; public static final String EDIT_CONDITION_ID = "editinfos"; public static final String ADMIN_CONDITION_ID = "admininfos"; + + // Configs + private static final int CURRENT_VERSION = 2; + public static final String CONFIG_KEY_ADMIN_BY_COACH = "admin.by.coach"; + public static final String CONFIG_KEY_EDIT_BY_COACH = "edit.by.coach"; + public static final String CONFIG_KEY_EDIT_BY_PARTICIPANT = "edit.by.participant"; + private Condition preConditionEdit; private Condition preConditionAdmin; @@ -90,6 +101,40 @@ public class InfoCourseNode extends AbstractAccessableCourseNode { config.set(InfoCourseNodeConfiguration.CONFIG_DURATION, "90"); config.set(InfoCourseNodeConfiguration.CONFIG_LENGTH, "10"); } + + int version = config.getConfigurationVersion(); + if (version < 2) { + config.setBooleanEntry(CONFIG_KEY_ADMIN_BY_COACH, true); + config.setBooleanEntry(CONFIG_KEY_EDIT_BY_COACH, true); + config.setBooleanEntry(CONFIG_KEY_EDIT_BY_PARTICIPANT, false); + removeDefaultPreconditions(); + } + config.setConfigurationVersion(CURRENT_VERSION); + } + + private void removeDefaultPreconditions() { + if (hasCustomPreConditions()) { + boolean defaultPreconditions = + !preConditionAdmin.isExpertMode() + && preConditionAdmin.isEasyModeCoachesAndAdmins() + && !preConditionAdmin.isEasyModeAlwaysAllowCoachesAndAdmins() + && !preConditionAdmin.isAssessmentMode() + && !preConditionAdmin.isAssessmentModeViewResults() + && !preConditionEdit.isExpertMode() + && preConditionEdit.isEasyModeCoachesAndAdmins() + && !preConditionEdit.isEasyModeAlwaysAllowCoachesAndAdmins() + && !preConditionEdit.isAssessmentMode() + && !preConditionEdit.isAssessmentModeViewResults(); + if (defaultPreconditions) { + removeCustomPreconditions(); + } + } + } + + public void removeCustomPreconditions() { + preConditionAdmin = null; + preConditionEdit = null; + setPreConditionAccess(null); } @Override @@ -124,19 +169,24 @@ public class InfoCourseNode extends AbstractAccessableCourseNode { @Override public StatusDescription[] isConfigValid(CourseEditorEnv cev) { oneClickStatusCache = null; - String translatorStr = Util.getPackageName(InfoCourseNodeEditController.class); - List<StatusDescription> statusDescs =isConfigValidWithTranslator(cev, translatorStr, getConditionExpressions()); + List<StatusDescription> statusDescs = isConfigValidWithTranslator(cev, TRANSLATOR_PACKAGE, getConditionExpressions()); oneClickStatusCache = StatusDescriptionHelper.sort(statusDescs); return oneClickStatusCache; } - @Override public TabbableController createEditController(UserRequest ureq, WindowControl wControl, BreadcrumbPanel stackPanel, ICourse course, UserCourseEnvironment euce) { - InfoCourseNodeEditController childTabCntrllr = new InfoCourseNodeEditController(ureq, wControl, getModuleConfiguration(), this, course, euce); + InfoCourseNodeEditController childTabCntrllr = new InfoCourseNodeEditController(ureq, wControl, this, course, euce); CourseNode chosenNode = course.getEditorTreeModel().getCourseNode(euce.getCourseEditorEnv().getCurrentCourseNodeId()); return new NodeEditController(ureq, wControl, course, chosenNode, euce, childTabCntrllr); } + + @Override + public ConditionAccessEditConfig getAccessEditConfig() { + return hasCustomPreConditions() + ? ConditionAccessEditConfig.custom() + : ConditionAccessEditConfig.regular(false); + } @Override public Controller createPeekViewRunController(UserRequest ureq, WindowControl wControl, UserCourseEnvironment userCourseEnv, @@ -144,9 +194,8 @@ public class InfoCourseNode extends AbstractAccessableCourseNode { if (nodeSecCallback.isAccessible()) { InfoPeekViewController ctrl = new InfoPeekViewController(ureq, wControl, userCourseEnv, this); return ctrl; - } else { - return super.createPeekViewRunController(ureq, wControl, userCourseEnv, nodeSecCallback); } + return super.createPeekViewRunController(ureq, wControl, userCourseEnv, nodeSecCallback); } @Override @@ -165,21 +214,27 @@ public class InfoCourseNode extends AbstractAccessableCourseNode { conditions.addAll(parentConditions); } - Condition editCondition = getPreConditionEdit(); - if(editCondition != null && StringHelper.containsNonWhitespace(editCondition.getConditionExpression())) { - ConditionExpression ce = new ConditionExpression(editCondition.getConditionId()); - ce.setExpressionString(editCondition.getConditionExpression()); - conditions.add(ce); - } - Condition adminCondition = getPreConditionAdmin(); - if(adminCondition != null && StringHelper.containsNonWhitespace(adminCondition.getConditionExpression())) { - ConditionExpression ce = new ConditionExpression(adminCondition.getConditionId()); - ce.setExpressionString(adminCondition.getConditionExpression()); - conditions.add(ce); + if (hasCustomPreConditions()) { + Condition editCondition = getPreConditionEdit(); + if(editCondition != null && StringHelper.containsNonWhitespace(editCondition.getConditionExpression())) { + ConditionExpression ce = new ConditionExpression(editCondition.getConditionId()); + ce.setExpressionString(editCondition.getConditionExpression()); + conditions.add(ce); + } + Condition adminCondition = getPreConditionAdmin(); + if(adminCondition != null && StringHelper.containsNonWhitespace(adminCondition.getConditionExpression())) { + ConditionExpression ce = new ConditionExpression(adminCondition.getConditionId()); + ce.setExpressionString(adminCondition.getConditionExpression()); + conditions.add(ce); + } } return conditions; } + public boolean hasCustomPreConditions() { + return preConditionAdmin != null || preConditionEdit != null; + } + /** * Default set the write privileges to coaches and admin only * @return @@ -236,21 +291,21 @@ public class InfoCourseNode extends AbstractAccessableCourseNode { @Override public void calcAccessAndVisibility(ConditionInterpreter ci, NodeEvaluation nodeEval) { - //nodeEval.setVisible(true); super.calcAccessAndVisibility(ci, nodeEval); - // evaluate the preconditions - boolean editor = (getPreConditionEdit().getConditionExpression() == null ? true : ci.evaluateCondition(getPreConditionEdit())); - nodeEval.putAccessStatus(EDIT_CONDITION_ID, editor); - - boolean admin = (getPreConditionAdmin().getConditionExpression() == null ? true : ci.evaluateCondition(getPreConditionAdmin())); - nodeEval.putAccessStatus(ADMIN_CONDITION_ID, admin); + if (hasCustomPreConditions()) { + boolean editor = (getPreConditionEdit().getConditionExpression() == null ? true : ci.evaluateCondition(getPreConditionEdit())); + nodeEval.putAccessStatus(EDIT_CONDITION_ID, editor); + + boolean admin = (getPreConditionAdmin().getConditionExpression() == null ? true : ci.evaluateCondition(getPreConditionAdmin())); + nodeEval.putAccessStatus(ADMIN_CONDITION_ID, admin); + } } - @Override /** * is called when deleting this node, clean up info-messages and subscriptions! */ + @Override public void cleanupOnDelete(ICourse course) { super.cleanupOnDelete(course); // delete infoMessages and subscriptions (OLAT-6171) diff --git a/src/main/java/org/olat/course/nodes/info/InfoConfigForm.java b/src/main/java/org/olat/course/nodes/info/InfoConfigController.java similarity index 55% rename from src/main/java/org/olat/course/nodes/info/InfoConfigForm.java rename to src/main/java/org/olat/course/nodes/info/InfoConfigController.java index 10f2f49dac6..f41f0eba836 100644 --- a/src/main/java/org/olat/course/nodes/info/InfoConfigForm.java +++ b/src/main/java/org/olat/course/nodes/info/InfoConfigController.java @@ -20,16 +20,23 @@ package org.olat.course.nodes.info; +import static org.olat.core.gui.translator.TranslatorHelper.translateAll; + +import java.util.Collection; + 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.elements.SingleSelection; 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; 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.util.StringHelper; +import org.olat.course.editor.NodeEditController; +import org.olat.course.nodes.InfoCourseNode; import org.olat.modules.ModuleConfiguration; /** @@ -41,7 +48,7 @@ import org.olat.modules.ModuleConfiguration; * Initial Date: 3 aug. 2010 <br> * @author srosse, stephane.rosse@frentix.com, http://www.frentix.com */ -public class InfoConfigForm extends FormBasicController { +public class InfoConfigController extends FormBasicController { private static final String[] maxDurationValues = new String[] { @@ -60,34 +67,50 @@ public class InfoConfigForm extends FormBasicController { null }; + private static final String ROLE_COACH = "config.role.coach"; + private static final String ROLE_PARTICIPANT = "config.role.participant"; + private static final String[] ADMIN_KEYS = new String[] { + ROLE_COACH + }; + private static final String[] EDIT_KEYS = new String[] { + ROLE_COACH, + ROLE_PARTICIPANT + }; + + private final InfoCourseNode courseNode; private final ModuleConfiguration config; private SingleSelection durationSelection; private SingleSelection lengthSelection; private MultipleSelectionElement autoSubscribeSelection; - - public InfoConfigForm(UserRequest ureq, WindowControl wControl, ModuleConfiguration config) { - super(ureq, wControl); - - this.config = config; + private MultipleSelectionElement adminRolesEl; + private MultipleSelectionElement editRolesEl; + + public InfoConfigController(UserRequest ureq, WindowControl wControl, InfoCourseNode courseNode) { + super(ureq, wControl, LAYOUT_BAREBONE); + this.courseNode = courseNode; + this.config = courseNode.getModuleConfiguration(); autoSubscribeValues[0] = translate("pane.tab.infos_config.auto_subscribe.on"); initForm(ureq); } @Override protected void initForm(FormItemContainer formLayout, Controller listener, UserRequest ureq) { - formLayout.setElementCssClass("o_sel_course_info_form"); - setFormTitle("pane.tab.infos_config.title"); - setFormContextHelp("Administration and Organisation#_mitteilung_zugang"); - + FormLayoutContainer generalCont = FormLayoutContainer.createDefaultFormLayout("general", getTranslator()); + generalCont.setFormTitle(translate("pane.tab.infos_config.title")); + generalCont.setFormContextHelp("Administration and Organisation#_mitteilung_zugang"); + generalCont.setElementCssClass("o_sel_course_info_form"); + formLayout.add(generalCont); + String page = velocity_root + "/editShow.html"; final FormLayoutContainer showLayout = FormLayoutContainer.createCustomFormLayout("pane.tab.infos_config.shown", getTranslator(), page); showLayout.setLabel("pane.tab.infos_config.shown", null); - formLayout.add(showLayout); + generalCont.add(showLayout); durationSelection = uifactory.addDropdownSingleselect("pane.tab.infos_config.max_duration", showLayout, maxDurationValues, maxDurationValues, null); durationSelection.setLabel("pane.tab.infos_config.max", null); durationSelection.setElementCssClass("o_sel_course_info_duration"); + durationSelection.addActionListener(FormEvent.ONCHANGE); String durationStr = (String)config.get(InfoCourseNodeConfiguration.CONFIG_DURATION); if(StringHelper.containsNonWhitespace(durationStr)) { durationSelection.select(durationStr, true); @@ -98,6 +121,7 @@ public class InfoConfigForm extends FormBasicController { lengthSelection = uifactory.addDropdownSingleselect("pane.tab.infos_config.max_shown", null, showLayout, maxLengthValues, maxLengthValues, null); lengthSelection.setElementCssClass("o_sel_course_info_length"); lengthSelection.setLabel("pane.tab.infos_config.max", null); + lengthSelection.addActionListener(FormEvent.ONCHANGE); String lengthStr = (String)config.get(InfoCourseNodeConfiguration.CONFIG_LENGTH); if(StringHelper.containsNonWhitespace(lengthStr)) { lengthSelection.select(lengthStr, true); @@ -105,16 +129,49 @@ public class InfoConfigForm extends FormBasicController { lengthSelection.select("5", true); } - autoSubscribeSelection = uifactory.addCheckboxesHorizontal("auto_subscribe", formLayout, autoSubscribeKeys, autoSubscribeValues); + autoSubscribeSelection = uifactory.addCheckboxesHorizontal("auto_subscribe", generalCont, autoSubscribeKeys, autoSubscribeValues); + autoSubscribeSelection.addActionListener(FormEvent.ONCHANGE); String autoSubscribeStr = (String)config.get(InfoCourseNodeConfiguration.CONFIG_AUTOSUBSCRIBE); if("on".equals(autoSubscribeStr) || !StringHelper.containsNonWhitespace(autoSubscribeStr)) { autoSubscribeSelection.select("on", true); } - uifactory.addFormSubmitButton("save", formLayout); + if (!courseNode.hasCustomPreConditions()) { + FormLayoutContainer rightsCont = FormLayoutContainer.createDefaultFormLayout("rights", getTranslator()); + formLayout.add(rightsCont); + rightsCont.setFormTitle(translate("config.rights")); + + adminRolesEl = uifactory.addCheckboxesVertical("config.admin", rightsCont, ADMIN_KEYS, + translateAll(getTranslator(), ADMIN_KEYS), 1); + adminRolesEl.select(ROLE_COACH, config.getBooleanSafe(InfoCourseNode.CONFIG_KEY_ADMIN_BY_COACH)); + adminRolesEl.addActionListener(FormEvent.ONCHANGE); + + editRolesEl = uifactory.addCheckboxesVertical("config.edit", rightsCont, EDIT_KEYS, + translateAll(getTranslator(), EDIT_KEYS), 1); + editRolesEl.select(ROLE_COACH, config.getBooleanSafe(InfoCourseNode.CONFIG_KEY_EDIT_BY_COACH)); + editRolesEl.select(ROLE_PARTICIPANT, + config.getBooleanSafe(InfoCourseNode.CONFIG_KEY_EDIT_BY_PARTICIPANT)); + editRolesEl.addActionListener(FormEvent.ONCHANGE); + } } - protected ModuleConfiguration getUpdatedConfig() { + @Override + protected void formInnerEvent(UserRequest ureq, FormItem source, FormEvent event) { + if (source == durationSelection) { + doUpdatedConfig(ureq); + } else if (source == lengthSelection) { + doUpdatedConfig(ureq); + } else if (source == autoSubscribeSelection) { + doUpdatedConfig(ureq); + } else if (source == adminRolesEl) { + doUpdatedConfig(ureq); + } else if (source == editRolesEl) { + doUpdatedConfig(ureq); + } + super.formInnerEvent(ureq, source, event); + } + + private void doUpdatedConfig(UserRequest ureq) { String durationStr = durationSelection.getSelectedKey(); config.set(InfoCourseNodeConfiguration.CONFIG_DURATION, durationStr); @@ -123,7 +180,15 @@ public class InfoConfigForm extends FormBasicController { String autoSubscribeStr = autoSubscribeSelection.isSelected(0) ? "on" : "off"; config.set(InfoCourseNodeConfiguration.CONFIG_AUTOSUBSCRIBE, autoSubscribeStr); - return config; + + Collection<String> selectedAdminKeys = adminRolesEl.getSelectedKeys(); + config.setBooleanEntry(InfoCourseNode.CONFIG_KEY_ADMIN_BY_COACH, selectedAdminKeys.contains(ROLE_COACH)); + + Collection<String> selectedEditKeys = editRolesEl.getSelectedKeys(); + config.setBooleanEntry(InfoCourseNode.CONFIG_KEY_EDIT_BY_COACH, selectedEditKeys.contains(ROLE_COACH)); + config.setBooleanEntry(InfoCourseNode.CONFIG_KEY_EDIT_BY_PARTICIPANT, selectedEditKeys.contains(ROLE_PARTICIPANT)); + + fireEvent(ureq, NodeEditController.NODECONFIG_CHANGED_EVENT); } @Override @@ -133,6 +198,6 @@ public class InfoConfigForm extends FormBasicController { @Override protected void formOK(UserRequest ureq) { - fireEvent (ureq, Event.DONE_EVENT); + // } } diff --git a/src/main/java/org/olat/course/nodes/info/InfoCourseNodeEditController.java b/src/main/java/org/olat/course/nodes/info/InfoCourseNodeEditController.java index ed95ee3b9b4..c5ddfc0e0cd 100644 --- a/src/main/java/org/olat/course/nodes/info/InfoCourseNodeEditController.java +++ b/src/main/java/org/olat/course/nodes/info/InfoCourseNodeEditController.java @@ -57,47 +57,45 @@ public class InfoCourseNodeEditController extends ActivateableTabbableDefaultCon private final InfoCourseNode courseNode; private TabbedPane myTabbedPane; - private VelocityContainer configContent; - private InfoConfigForm infoConfigForm; + private InfoConfigController configCtrl; private VelocityContainer editAccessVc; private ConditionEditController accessCondContr; private ConditionEditController editCondContr; private ConditionEditController adminCondContr; - public InfoCourseNodeEditController(UserRequest ureq, WindowControl wControl, ModuleConfiguration config, InfoCourseNode courseNode, ICourse course, - UserCourseEnvironment euce) { + public InfoCourseNodeEditController(UserRequest ureq, WindowControl wControl, InfoCourseNode courseNode, + ICourse course, UserCourseEnvironment euce) { super(ureq,wControl); this.courseNode = courseNode; - infoConfigForm = new InfoConfigForm(ureq, wControl, config); - listenTo(infoConfigForm); + configCtrl = new InfoConfigController(ureq, wControl, courseNode); + listenTo(configCtrl); - editAccessVc = createVelocityContainer("edit_access"); - CourseEditorTreeModel editorModel = course.getEditorTreeModel(); - // Accessibility precondition - Condition accessCondition = courseNode.getPreConditionAccess(); - accessCondContr = new ConditionEditController(ureq, getWindowControl(), euce, accessCondition, - AssessmentHelper.getAssessableNodes(editorModel, courseNode)); - listenTo(accessCondContr); - editAccessVc.put("readerCondition", accessCondContr.getInitialComponent()); + if (courseNode.hasCustomPreConditions()) { + editAccessVc = createVelocityContainer("edit_access"); + CourseEditorTreeModel editorModel = course.getEditorTreeModel(); + // Accessibility precondition + Condition accessCondition = courseNode.getPreConditionAccess(); + accessCondContr = new ConditionEditController(ureq, getWindowControl(), euce, accessCondition, + AssessmentHelper.getAssessableNodes(editorModel, courseNode)); + listenTo(accessCondContr); + editAccessVc.put("readerCondition", accessCondContr.getInitialComponent()); - // read / write preconditions - Condition editCondition = courseNode.getPreConditionEdit(); - editCondContr = new ConditionEditController(ureq, getWindowControl(), euce, editCondition, AssessmentHelper - .getAssessableNodes(editorModel, courseNode)); - listenTo(editCondContr); - editAccessVc.put("editCondition", editCondContr.getInitialComponent()); - - // administration preconditions - Condition adminCondition = courseNode.getPreConditionAdmin(); - adminCondContr = new ConditionEditController(ureq, getWindowControl(), euce, adminCondition, AssessmentHelper - .getAssessableNodes(editorModel, courseNode)); - listenTo(adminCondContr); - editAccessVc.put("adminCondition", adminCondContr.getInitialComponent()); - - configContent = createVelocityContainer("edit"); - configContent.put("infoConfigForm", infoConfigForm.getInitialComponent()); + // read / write preconditions + Condition editCondition = courseNode.getPreConditionEdit(); + editCondContr = new ConditionEditController(ureq, getWindowControl(), euce, editCondition, AssessmentHelper + .getAssessableNodes(editorModel, courseNode)); + listenTo(editCondContr); + editAccessVc.put("editCondition", editCondContr.getInitialComponent()); + + // administration preconditions + Condition adminCondition = courseNode.getPreConditionAdmin(); + adminCondContr = new ConditionEditController(ureq, getWindowControl(), euce, adminCondition, AssessmentHelper + .getAssessableNodes(editorModel, courseNode)); + listenTo(adminCondContr); + editAccessVc.put("adminCondition", adminCondContr.getInitialComponent()); + } } @Override @@ -118,8 +116,10 @@ public class InfoCourseNodeEditController extends ActivateableTabbableDefaultCon @Override public void addTabs(TabbedPane tabbedPane) { myTabbedPane = tabbedPane; - tabbedPane.addTab(translate(PANE_TAB_ACCESSIBILITY), editAccessVc); - tabbedPane.addTab(translate(PANE_TAB_CONFIG), configContent); + if (editAccessVc != null) { + tabbedPane.addTab(translate(PANE_TAB_ACCESSIBILITY), editAccessVc); + } + tabbedPane.addTab(translate(PANE_TAB_CONFIG), configCtrl.getInitialComponent()); } @@ -130,11 +130,8 @@ public class InfoCourseNodeEditController extends ActivateableTabbableDefaultCon @Override public void event(UserRequest ureq, Controller source, Event event) { - if (source == infoConfigForm) { - if (event == Event.DONE_EVENT) { - infoConfigForm.getUpdatedConfig(); - fireEvent(ureq, NodeEditController.NODECONFIG_CHANGED_EVENT); - } + if (source == configCtrl) { + fireEvent(ureq, event); } else if (source == accessCondContr) { if (event == Event.CHANGED_EVENT) { Condition cond = accessCondContr.getCondition(); diff --git a/src/main/java/org/olat/course/nodes/info/InfoCourseSecurityCallback.java b/src/main/java/org/olat/course/nodes/info/InfoCourseSecurityCallback.java new file mode 100644 index 00000000000..524326e43e4 --- /dev/null +++ b/src/main/java/org/olat/course/nodes/info/InfoCourseSecurityCallback.java @@ -0,0 +1,56 @@ +/** + * <a href="http://www.openolat.org"> + * OpenOLAT - Online Learning and Training</a><br> + * <p> + * Licensed under the Apache License, Version 2.0 (the "License"); <br> + * you may not use this file except in compliance with the License.<br> + * You may obtain a copy of the License at the + * <a href="http://www.apache.org/licenses/LICENSE-2.0">Apache homepage</a> + * <p> + * Unless required by applicable law or agreed to in writing,<br> + * software distributed under the License is distributed on an "AS IS" BASIS, <br> + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. <br> + * See the License for the specific language governing permissions and <br> + * limitations under the License. + * <p> + * Initial code contributed and copyrighted by<br> + * frentix GmbH, http://www.frentix.com + * <p> + */ +package org.olat.course.nodes.info; + +import org.olat.commons.info.InfoMessage; +import org.olat.commons.info.ui.InfoSecurityCallback; +import org.olat.core.id.Identity; + +public class InfoCourseSecurityCallback implements InfoSecurityCallback { + private final boolean canAdd; + private final boolean canAdmin; + private final Identity identity; + + public InfoCourseSecurityCallback(Identity identity, boolean canAdd, boolean canAdmin) { + this.canAdd = canAdd; + this.canAdmin = canAdmin; + this.identity = identity; + } + + @Override + public boolean canRead() { + return true; + } + + @Override + public boolean canAdd() { + return canAdd; + } + + @Override + public boolean canEdit(InfoMessage infoMessage) { + return identity.equals(infoMessage.getAuthor()) || canAdmin; + } + + @Override + public boolean canDelete() { + return canAdmin; + } +} \ 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 f8fa4c9b3bf..60483ad4b30 100644 --- a/src/main/java/org/olat/course/nodes/info/InfoRunController.java +++ b/src/main/java/org/olat/course/nodes/info/InfoRunController.java @@ -25,7 +25,6 @@ import java.util.List; import java.util.StringTokenizer; import org.olat.basesecurity.GroupRoles; -import org.olat.commons.info.InfoMessage; import org.olat.commons.info.InfoSubscriptionManager; import org.olat.commons.info.manager.MailFormatter; import org.olat.commons.info.ui.InfoDisplayController; @@ -41,7 +40,6 @@ import org.olat.core.gui.components.velocity.VelocityContainer; import org.olat.core.gui.control.Event; import org.olat.core.gui.control.WindowControl; import org.olat.core.gui.control.controller.BasicController; -import org.olat.core.id.Identity; import org.olat.core.id.OLATResourceable; import org.olat.core.util.StringHelper; import org.olat.core.util.UserSession; @@ -89,26 +87,61 @@ public class InfoRunController extends BasicController { 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); + canAdd = canEdit(courseNode, userCourseEnv, ne); + canAdmin = canAdmin(courseNode, userCourseEnv, ne); } + InfoSecurityCallback secCallback = new InfoCourseSecurityCallback(getIdentity(), canAdd, canAdmin); 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); + + initVC(ureq, userCourseEnv, resSubPath, secCallback, autoSubscribe, maxResults, duration); + } + + private boolean canEdit(InfoCourseNode courseNode, UserCourseEnvironment userCourseEnv, NodeEvaluation ne) { + if (userCourseEnv.isAdmin()) { + return true; + } + + if (courseNode.hasCustomPreConditions()) { + return ne.isCapabilityAccessible(InfoCourseNode.EDIT_CONDITION_ID); + } + + ModuleConfiguration moduleConfig = courseNode.getModuleConfiguration(); + if ((moduleConfig.getBooleanSafe(InfoCourseNode.CONFIG_KEY_EDIT_BY_COACH) && userCourseEnv.isCoach()) + || (moduleConfig.getBooleanSafe(InfoCourseNode.CONFIG_KEY_EDIT_BY_PARTICIPANT) && userCourseEnv.isParticipant())) { + return true; + } + + return false; + } + + private boolean canAdmin(InfoCourseNode courseNode, UserCourseEnvironment userCourseEnv, NodeEvaluation ne) { + if (userCourseEnv.isAdmin()) { + return true; + } + + if (courseNode.hasCustomPreConditions()) { + return ne.isCapabilityAccessible(InfoCourseNode.ADMIN_CONDITION_ID); + } + + ModuleConfiguration moduleConfig = courseNode.getModuleConfiguration(); + if (moduleConfig.getBooleanSafe(InfoCourseNode.CONFIG_KEY_ADMIN_BY_COACH) && userCourseEnv.isCoach()) { + return true; + } + + return false; } public InfoRunController(UserRequest ureq, WindowControl wControl, UserCourseEnvironment userCourseEnv, - String resSubPath, boolean canAdd, boolean canAdmin, boolean autoSubscribe) { + String resSubPath, InfoSecurityCallback secCallback, boolean autoSubscribe) { super(ureq, wControl); - initVC(ureq, userCourseEnv, resSubPath, canAdd, canAdmin, autoSubscribe, -1, -1); + initVC(ureq, userCourseEnv, resSubPath, secCallback, autoSubscribe, -1, -1); } private void initVC(UserRequest ureq, UserCourseEnvironment userCourseEnv, - String resSubPath, boolean canAdd, boolean canAdmin, boolean autoSubscribe, int maxResults, int duration) { + String resSubPath, InfoSecurityCallback secCallback, boolean autoSubscribe, int maxResults, int duration) { Long resId = userCourseEnv.getCourseEnvironment().getCourseResourceableId(); OLATResourceable infoResourceable = new InfoOLATResourceable(resId); businessPath = normalizeBusinessPath(getWindowControl().getBusinessControl().getAsString()); @@ -125,10 +158,7 @@ public class InfoRunController extends BasicController { PublisherData pdata = subscriptionManager.getInfoPublisherData(infoResourceable, businessPath); subscriptionController = new ContextualSubscriptionController(ureq, getWindowControl(), subContext, pdata, autoSubscribe); listenTo(subscriptionController); - } - - InfoSecurityCallback secCallback = new InfoCourseSecurityCallback(getIdentity(), canAdd, canAdmin); - + } infoDisplayController = new InfoDisplayController(ureq, getWindowControl(), maxResults, duration, secCallback, infoResourceable, resSubPath, businessPath); infoDisplayController.addSendMailOptions(new SendSubscriberMailOption(infoResourceable, resSubPath, getLocale())); @@ -201,38 +231,6 @@ public class InfoRunController extends BasicController { // } - private class InfoCourseSecurityCallback implements InfoSecurityCallback { - private final boolean canAdd; - private final boolean canAdmin; - private final Identity identity; - - public InfoCourseSecurityCallback(Identity identity, boolean canAdd, boolean canAdmin) { - this.canAdd = canAdd; - this.canAdmin = canAdmin; - this.identity = identity; - } - - @Override - public boolean canRead() { - return true; - } - - @Override - public boolean canAdd() { - return canAdd; - } - - @Override - public boolean canEdit(InfoMessage infoMessage) { - return identity.equals(infoMessage.getAuthor()) || canAdmin; - } - - @Override - public boolean canDelete() { - return canAdmin; - } - } - private class InfoOLATResourceable implements OLATResourceable { private final Long resId; diff --git a/src/main/java/org/olat/course/nodes/info/_content/edit.html b/src/main/java/org/olat/course/nodes/info/_content/edit.html deleted file mode 100644 index d83973964af..00000000000 --- a/src/main/java/org/olat/course/nodes/info/_content/edit.html +++ /dev/null @@ -1 +0,0 @@ -$r.render("infoConfigForm") \ No newline at end of file diff --git a/src/main/java/org/olat/course/nodes/info/_i18n/LocalStrings_de.properties b/src/main/java/org/olat/course/nodes/info/_i18n/LocalStrings_de.properties index 43042c7409c..a2eec4abdf1 100644 --- a/src/main/java/org/olat/course/nodes/info/_i18n/LocalStrings_de.properties +++ b/src/main/java/org/olat/course/nodes/info/_i18n/LocalStrings_de.properties @@ -3,6 +3,11 @@ title_info=Mitteilungen condition.accessibility.title=Mitteilungen lesen condition.admin.title=Mitteilungen verwalten condition.editable.title=Mitteilung verfassen +config.admin=$\:condition.admin.title +config.edit=$\:condition.editable.title +config.rights=Benutzerberechtigungen +config.role.coach=Betreuer +config.role.participant=Teilnehmer mail.body.title=Mitteilung aus Kurs {0} mail.body.from=Verfasst von {0} am {1} mail.body.more=Weitere Mitteilungen diff --git a/src/main/java/org/olat/course/nodes/info/_i18n/LocalStrings_en.properties b/src/main/java/org/olat/course/nodes/info/_i18n/LocalStrings_en.properties index 617278a2e9a..5bf4c527f65 100644 --- a/src/main/java/org/olat/course/nodes/info/_i18n/LocalStrings_en.properties +++ b/src/main/java/org/olat/course/nodes/info/_i18n/LocalStrings_en.properties @@ -3,6 +3,11 @@ auto_subscribe=Subscribe automatically condition.accessibility.title=Read notifications condition.admin.title=Manage notifications condition.editable.title=Create notifications +config.admin=$\:condition.admin.title +config.edit=$\:condition.editable.title +config.rights=User rights +config.role.coach=Coach +config.role.participant=Participant mail.body.title=Notification regarding course {0} mail.body.from=Written by {0} on {1} mail.body.more=Further information diff --git a/src/main/java/org/olat/course/run/CourseRuntimeController.java b/src/main/java/org/olat/course/run/CourseRuntimeController.java index 03ba19173b5..e5f21f4d07a 100644 --- a/src/main/java/org/olat/course/run/CourseRuntimeController.java +++ b/src/main/java/org/olat/course/run/CourseRuntimeController.java @@ -27,6 +27,7 @@ import java.util.concurrent.atomic.AtomicInteger; import org.olat.NewControllerFactory; import org.olat.commons.calendar.CalendarModule; +import org.olat.commons.info.ui.InfoSecurityCallback; import org.olat.core.CoreSpringFactory; import org.olat.core.commons.controllers.linkchooser.CustomLinkTreeModel; import org.olat.core.commons.fullWebApp.LayoutMain3ColsController; @@ -109,6 +110,7 @@ import org.olat.course.nodes.bc.CourseDocumentsController; import org.olat.course.nodes.co.COToolController; import org.olat.course.nodes.feed.blog.BlogToolController; import org.olat.course.nodes.fo.FOToolController; +import org.olat.course.nodes.info.InfoCourseSecurityCallback; import org.olat.course.nodes.info.InfoRunController; import org.olat.course.nodes.members.MembersToolRunController; import org.olat.course.reminder.ui.CourseRemindersController; @@ -1812,11 +1814,12 @@ public class CourseRuntimeController extends RepositoryEntryRuntimeController im canAdd = isAdmin; canAdmin = isAdmin; } + InfoSecurityCallback secCallback = new InfoCourseSecurityCallback(getIdentity(), canAdd, canAdmin); OLATResourceable ores = OresHelper.createOLATResourceableType("ParticipantInfos"); WindowControl swControl = addToHistory(ureq, ores, null); participatInfoCtrl = new InfoRunController(ureq, swControl, getUserCourseEnvironment(), "ParticipantInfos", - canAdd, canAdmin, autoSubscribe); + secCallback, autoSubscribe); pushController(ureq, translate("command.participant.info"), participatInfoCtrl); setActiveTool(participantInfoLink); -- GitLab