diff --git a/src/main/java/org/olat/course/assessment/AssessmentAction.java b/src/main/java/org/olat/course/assessment/AssessmentAction.java index 4305bc40c2ea261b6f51b625e88b8374e3d1b698..0cf51148cef362f7d3b3df3502d186436e35c7b4 100644 --- a/src/main/java/org/olat/course/assessment/AssessmentAction.java +++ b/src/main/java/org/olat/course/assessment/AssessmentAction.java @@ -27,7 +27,7 @@ package org.olat.course.assessment; */ public enum AssessmentAction { - nodeClicked, + nodeVisited, confirmed } diff --git a/src/main/java/org/olat/course/assessment/AssessmentManager.java b/src/main/java/org/olat/course/assessment/AssessmentManager.java index 152fc0f08f7bc936775bfba940511fda26b36cb1..1e5701a2d75a1ecf0ab56f7c7d278309d11c7dea 100644 --- a/src/main/java/org/olat/course/assessment/AssessmentManager.java +++ b/src/main/java/org/olat/course/assessment/AssessmentManager.java @@ -98,6 +98,8 @@ public interface AssessmentManager { public void updateCurrentCompletion(CourseNode courseNode, Identity assessedIdentity, UserCourseEnvironment userCourseEnvironment, Double currentCompletion, AssessmentRunStatus status, Role by); + public void updateAssessmentStatus(CourseNode courseNode, Identity assessedIdentity, AssessmentEntryStatus status, Role by); + /** * Save an assessment comment for this node for a user. If there is already a comment property available, * it will be overwritten with the new value @@ -275,7 +277,7 @@ public interface AssessmentManager { */ public Boolean getNodeFullyAssessed(CourseNode courseNode, Identity identity); - + public AssessmentEntry getAssessmentEntry(CourseNode courseNode, Identity assessedIdentity); public AssessmentEntry createAssessmentEntry(CourseNode courseNode, Identity assessedIdentity, ScoreEvaluation scoreEvaluation); diff --git a/src/main/java/org/olat/course/assessment/manager/CourseAssessmentManagerImpl.java b/src/main/java/org/olat/course/assessment/manager/CourseAssessmentManagerImpl.java index 704e29e30aa6cfb338c3e8ba65656756ef3ce99a..4aeebb7908cd87fc28f3be354ca1f86d2a2fecc7 100644 --- a/src/main/java/org/olat/course/assessment/manager/CourseAssessmentManagerImpl.java +++ b/src/main/java/org/olat/course/assessment/manager/CourseAssessmentManagerImpl.java @@ -417,6 +417,20 @@ public class CourseAssessmentManagerImpl implements AssessmentManager { DBFactory.getInstance().commit(); } + @Override + public void updateAssessmentStatus(CourseNode courseNode, Identity assessedIdentity, AssessmentEntryStatus status, + Role by) { + AssessmentEntry nodeAssessment = getOrCreate(assessedIdentity, courseNode); + if(by == Role.coach) { + nodeAssessment.setLastCoachModified(new Date()); + } else if(by == Role.user) { + nodeAssessment.setLastUserModified(new Date()); + } + nodeAssessment.setAssessmentStatus(status); + assessmentService.updateAssessmentEntry(nodeAssessment); + DBFactory.getInstance().commit(); + } + @Override public void saveScoreEvaluation(CourseNode courseNode, Identity identity, Identity assessedIdentity, ScoreEvaluation scoreEvaluation, UserCourseEnvironment userCourseEnv, diff --git a/src/main/java/org/olat/course/learningpath/LearningPathConfigs.java b/src/main/java/org/olat/course/learningpath/LearningPathConfigs.java new file mode 100644 index 0000000000000000000000000000000000000000..e065ba78abb4e05aa58e21a12e418fa29fb559a7 --- /dev/null +++ b/src/main/java/org/olat/course/learningpath/LearningPathConfigs.java @@ -0,0 +1,32 @@ +/** + * <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.learningpath; + +/** + * + * Initial date: 30 Aug 2019<br> + * @author uhensler, urs.hensler@frentix.com, http://www.frentix.com + * + */ +public interface LearningPathConfigs { + + boolean isDoneOnNodeVisited(); + +} diff --git a/src/main/java/org/olat/course/learningpath/LearningPathNodeAccessProvider.java b/src/main/java/org/olat/course/learningpath/LearningPathNodeAccessProvider.java index 2c830c4c3810d6e846932149a196d65869578cb5..a06400cadb4ac10bc8cc82bc0092a184fc6b0f7d 100644 --- a/src/main/java/org/olat/course/learningpath/LearningPathNodeAccessProvider.java +++ b/src/main/java/org/olat/course/learningpath/LearningPathNodeAccessProvider.java @@ -31,12 +31,18 @@ import org.olat.core.gui.control.Controller; import org.olat.core.gui.control.WindowControl; import org.olat.core.gui.control.generic.tabbable.TabbableController; import org.olat.core.gui.translator.Translator; +import org.olat.core.id.Identity; import org.olat.core.util.Util; +import org.olat.course.assessment.AssessmentManager; import org.olat.course.learningpath.manager.UnsupportedLearningPathNodeHandler; -import org.olat.course.learningpath.ui.LeaningPathNodeConfigController; +import org.olat.course.learningpath.ui.LearningPathNodeConfigController; import org.olat.course.learningpath.ui.TabbableLeaningPathNodeConfigController; import org.olat.course.nodeaccess.NodeAccessProvider; import org.olat.course.nodes.CourseNode; +import org.olat.course.run.navigation.NodeVisitedListener; +import org.olat.course.run.userview.UserCourseEnvironment; +import org.olat.modules.assessment.Role; +import org.olat.modules.assessment.model.AssessmentEntryStatus; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; @@ -47,7 +53,7 @@ import org.springframework.stereotype.Service; * */ @Service -public class LearningPathNodeAccessProvider implements NodeAccessProvider { +public class LearningPathNodeAccessProvider implements NodeAccessProvider, NodeVisitedListener { private static final String UNSUPPORTED_LEARNING_PATH_TYPE = UnsupportedLearningPathNodeHandler.NODE_TYPE; @@ -67,7 +73,7 @@ public class LearningPathNodeAccessProvider implements NodeAccessProvider { } } - private LearningPathNodeHandler getLearningPathNodeHandler(String courseNodeType) { + private LearningPathNodeHandler getLearningPathNodeHandler(String courseNodeType) { LearningPathNodeHandler handler = learningPathNodeHandlers.get(courseNodeType); if (handler == null) { handler = nonLearningPathNodeHandler; @@ -75,10 +81,14 @@ public class LearningPathNodeAccessProvider implements NodeAccessProvider { return handler; } - private LearningPathNodeHandler getLearningPathNodeHandler(CourseNode courseNode) { + private LearningPathNodeHandler getLearningPathNodeHandler(CourseNode courseNode) { return getLearningPathNodeHandler(courseNode.getType()); } + private LearningPathConfigs getConfigs(CourseNode courseNode) { + return getLearningPathNodeHandler(courseNode).getConfigs(courseNode); + } + @Override public String getType() { return "learningpath"; @@ -86,7 +96,7 @@ public class LearningPathNodeAccessProvider implements NodeAccessProvider { @Override public String getDisplayName(Locale locale) { - Translator translator = Util.createPackageTranslator(LeaningPathNodeConfigController.class, locale); + Translator translator = Util.createPackageTranslator(LearningPathNodeConfigController.class, locale); return translator.translate("access.provider.name"); } @@ -97,8 +107,19 @@ public class LearningPathNodeAccessProvider implements NodeAccessProvider { @Override public TabbableController createEditController(UserRequest ureq, WindowControl wControl, CourseNode courseNode) { - Controller configCtrl = getLearningPathNodeHandler(courseNode).createEditController(ureq, wControl, courseNode); + Controller configCtrl = getLearningPathNodeHandler(courseNode).createConfigEditController(ureq, wControl, courseNode); return new TabbableLeaningPathNodeConfigController(ureq, wControl, configCtrl); } + @Override + public void onNodeVisited(CourseNode courseNode, UserCourseEnvironment userCourseEnvironment) { + boolean doneOnNodeStarted = getConfigs(courseNode).isDoneOnNodeVisited(); + boolean participant = userCourseEnvironment.isParticipant(); + if (doneOnNodeStarted && participant) { + AssessmentManager am = userCourseEnvironment.getCourseEnvironment().getAssessmentManager(); + Identity identity = userCourseEnvironment.getIdentityEnvironment().getIdentity(); + am.updateAssessmentStatus(courseNode, identity, AssessmentEntryStatus.done, Role.user); + } + } + } diff --git a/src/main/java/org/olat/course/learningpath/LearningPathNodeHandler.java b/src/main/java/org/olat/course/learningpath/LearningPathNodeHandler.java index b9af39fffa37830d63254583027a9de8dc382ba3..11d3a5de32d9a59486a8240f72b5dba0364761d2 100644 --- a/src/main/java/org/olat/course/learningpath/LearningPathNodeHandler.java +++ b/src/main/java/org/olat/course/learningpath/LearningPathNodeHandler.java @@ -36,6 +36,8 @@ public interface LearningPathNodeHandler { public boolean isSupported(); - public Controller createEditController(UserRequest ureq, WindowControl wControl, CourseNode courseNode); + public LearningPathConfigs getConfigs(CourseNode courseNode); + + public Controller createConfigEditController(UserRequest ureq, WindowControl wControl, CourseNode courseNode); } diff --git a/src/main/java/org/olat/course/learningpath/manager/UnsupportedLearningPathNodeHandler.java b/src/main/java/org/olat/course/learningpath/manager/UnsupportedLearningPathNodeHandler.java index 1a19f66eff356e8e1c8e9654e73f7bc26ad37f32..5446810c11ccb9100bc34f2300aead4e7db61a07 100644 --- a/src/main/java/org/olat/course/learningpath/manager/UnsupportedLearningPathNodeHandler.java +++ b/src/main/java/org/olat/course/learningpath/manager/UnsupportedLearningPathNodeHandler.java @@ -22,7 +22,9 @@ package org.olat.course.learningpath.manager; import org.olat.core.gui.UserRequest; import org.olat.core.gui.control.Controller; import org.olat.core.gui.control.WindowControl; +import org.olat.course.learningpath.LearningPathConfigs; import org.olat.course.learningpath.LearningPathNodeHandler; +import org.olat.course.learningpath.model.UnsupportedLearningPathConfigs; import org.olat.course.nodes.CourseNode; import org.springframework.stereotype.Service; @@ -37,6 +39,8 @@ public class UnsupportedLearningPathNodeHandler implements LearningPathNodeHandl public static final String NODE_TYPE = "unsupported.learning.path.nodes"; + private static final UnsupportedLearningPathConfigs UNSUPPORTED_LEARNING_PATH_CONFIGS = new UnsupportedLearningPathConfigs(); + @Override public String acceptCourseNodeType() { return NODE_TYPE; @@ -48,7 +52,12 @@ public class UnsupportedLearningPathNodeHandler implements LearningPathNodeHandl } @Override - public Controller createEditController(UserRequest ureq, WindowControl wControl, CourseNode courseNode) { + public LearningPathConfigs getConfigs(CourseNode courseNode) { + return UNSUPPORTED_LEARNING_PATH_CONFIGS; + } + + @Override + public Controller createConfigEditController(UserRequest ureq, WindowControl wControl, CourseNode courseNode) { return null; } diff --git a/src/main/java/org/olat/course/learningpath/model/ModuleLearningPathConfigs.java b/src/main/java/org/olat/course/learningpath/model/ModuleLearningPathConfigs.java new file mode 100644 index 0000000000000000000000000000000000000000..ac3e8863c1f3de93d9324470aa57dc9967919b1d --- /dev/null +++ b/src/main/java/org/olat/course/learningpath/model/ModuleLearningPathConfigs.java @@ -0,0 +1,53 @@ +/** + * <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.learningpath.model; + +import static org.olat.course.learningpath.ui.LearningPathNodeConfigController.CONFIG_DEFAULT_DONE_TRIGGER; +import static org.olat.course.learningpath.ui.LearningPathNodeConfigController.CONFIG_KEY_DONE_TRIGGER; + +import org.olat.course.assessment.AssessmentAction; +import org.olat.course.learningpath.LearningPathConfigs; +import org.olat.modules.ModuleConfiguration; + +/** + * + * Initial date: 30 Aug 2019<br> + * @author uhensler, urs.hensler@frentix.com, http://www.frentix.com + * + */ +public class ModuleLearningPathConfigs implements LearningPathConfigs { + + private final ModuleConfiguration moduleConfiguration; + + public ModuleLearningPathConfigs(ModuleConfiguration moduleConfiguration) { + this.moduleConfiguration = moduleConfiguration; + } + + @Override + public boolean isDoneOnNodeVisited() { + String doneTriggerName = getDoneTriggerName(); + return AssessmentAction.nodeVisited.name().equals(doneTriggerName); + } + + private String getDoneTriggerName() { + return moduleConfiguration.getStringValue(CONFIG_KEY_DONE_TRIGGER, CONFIG_DEFAULT_DONE_TRIGGER); + } + +} diff --git a/src/main/java/org/olat/course/learningpath/model/UnsupportedLearningPathConfigs.java b/src/main/java/org/olat/course/learningpath/model/UnsupportedLearningPathConfigs.java new file mode 100644 index 0000000000000000000000000000000000000000..18ea79773eaac3a5ecfe8e49962044624b834751 --- /dev/null +++ b/src/main/java/org/olat/course/learningpath/model/UnsupportedLearningPathConfigs.java @@ -0,0 +1,37 @@ +/** + * <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.learningpath.model; + +import org.olat.course.learningpath.LearningPathConfigs; + +/** + * + * Initial date: 30 Aug 2019<br> + * @author uhensler, urs.hensler@frentix.com, http://www.frentix.com + * + */ +public class UnsupportedLearningPathConfigs implements LearningPathConfigs { + + @Override + public boolean isDoneOnNodeVisited() { + return false; + } + +} diff --git a/src/main/java/org/olat/course/learningpath/ui/LeaningPathNodeConfigController.java b/src/main/java/org/olat/course/learningpath/ui/LearningPathNodeConfigController.java similarity index 94% rename from src/main/java/org/olat/course/learningpath/ui/LeaningPathNodeConfigController.java rename to src/main/java/org/olat/course/learningpath/ui/LearningPathNodeConfigController.java index a31ea79948e6296c71e8bb58b7f64628e514e168..0ec8510ead03e028ed1562d9722d4b094776370e 100644 --- a/src/main/java/org/olat/course/learningpath/ui/LeaningPathNodeConfigController.java +++ b/src/main/java/org/olat/course/learningpath/ui/LearningPathNodeConfigController.java @@ -45,7 +45,7 @@ import org.olat.modules.ModuleConfiguration; * @author uhensler, urs.hensler@frentix.com, http://www.frentix.com * */ -public class LeaningPathNodeConfigController extends FormBasicController { +public class LearningPathNodeConfigController extends FormBasicController { public static final String CONFIG_KEY_ESTIMATED_DURATION = "learning.path.estimated.duration"; public static final String CONFIG_KEY_OBLIGATION = "learning.path.obligation"; @@ -63,7 +63,7 @@ public class LeaningPathNodeConfigController extends FormBasicController { private final ModuleConfiguration configs; private final LearningPathControllerConfig ctrlConfig; - public LeaningPathNodeConfigController(UserRequest ureq, WindowControl wControl, + public LearningPathNodeConfigController(UserRequest ureq, WindowControl wControl, ModuleConfiguration configs, LearningPathControllerConfig ctrlConfig) { super(ureq, wControl); this.configs = configs; @@ -99,8 +99,9 @@ public class LeaningPathNodeConfigController extends FormBasicController { private KeyValues getDoneTriggerKV() { KeyValues doneTriggerKV = new KeyValues(); - if (ctrlConfig.getAssessmentActions().contains(AssessmentAction.nodeClicked)) { - doneTriggerKV.add(entry(AssessmentAction.nodeClicked.name(), translate("config.done.trigger.started"))); + doneTriggerKV.add(entry(CONFIG_VALUE_DONE_TRIGGER_NONE, translate("config.done.trigger.none"))); + if (ctrlConfig.getAssessmentActions().contains(AssessmentAction.nodeVisited)) { + doneTriggerKV.add(entry(AssessmentAction.nodeVisited.name(), translate("config.done.trigger.visited"))); } if (ctrlConfig.getAssessmentActions().contains(AssessmentAction.confirmed)) { doneTriggerKV.add(entry(AssessmentAction.confirmed.name(), translate("config.done.trigger.confirmed"))); @@ -144,10 +145,6 @@ public class LeaningPathNodeConfigController extends FormBasicController { @Override protected void formOK(UserRequest ureq) { - fireEvent(ureq, Event.DONE_EVENT); - } - - protected ModuleConfiguration getUpdatedConfig() { String estimatedTime = estimatedDurationEl.getValue(); configs.setStringValue(CONFIG_KEY_ESTIMATED_DURATION, estimatedTime); @@ -161,7 +158,7 @@ public class LeaningPathNodeConfigController extends FormBasicController { : CONFIG_DEFAULT_DONE_TRIGGER; configs.setStringValue(CONFIG_KEY_DONE_TRIGGER, doneTrigger); - return configs; + fireEvent(ureq, Event.DONE_EVENT); } @Override diff --git a/src/main/java/org/olat/course/learningpath/ui/_i18n/LocalStrings_de.properties b/src/main/java/org/olat/course/learningpath/ui/_i18n/LocalStrings_de.properties index e82e801641758af6343a6d648330f78d37c4fa11..a69096293473d7936529448126383e7675e6c1f3 100644 --- a/src/main/java/org/olat/course/learningpath/ui/_i18n/LocalStrings_de.properties +++ b/src/main/java/org/olat/course/learningpath/ui/_i18n/LocalStrings_de.properties @@ -2,7 +2,8 @@ access.provider.name=Lernpfad error.positiv.int=Geben Sie eine positive Zahl ein. config.done.trigger=Lernfortschritt config.done.trigger.confirmed=Best\u00E4tigt -config.done.trigger.started=Ge\u00F6ffnet +config.done.trigger.none=W\u00E4hlen Sie einen Eintrag aus +config.done.trigger.visited=Ge\u00F6ffnet config.estimated.duration=Zeitvorgabe (Minuten) congig.obligation=Pflicht config.obligation.mandatory=Obligatorisch diff --git a/src/main/java/org/olat/course/learningpath/ui/_i18n/LocalStrings_en.properties b/src/main/java/org/olat/course/learningpath/ui/_i18n/LocalStrings_en.properties index 389a8ac410283c1fac23b984c9ccf2b185cd7c11..9d2ccfe9eac8d228a717c45570fbd323e95c041f 100644 --- a/src/main/java/org/olat/course/learningpath/ui/_i18n/LocalStrings_en.properties +++ b/src/main/java/org/olat/course/learningpath/ui/_i18n/LocalStrings_en.properties @@ -2,7 +2,8 @@ access.provider.name=Learning path error.positiv.int=Enter a positive number. config.done.trigger=Done trigger config.done.trigger.confirmed=Confirmed -config.done.trigger.started=Opened +config.done.trigger.none=Select an entry +config.done.trigger.visited=Opened config.estimated.duration=Estimated duration (minutes) config.obligation=Obligation config.obligation.mandatory=Mandatory diff --git a/src/main/java/org/olat/course/nodeaccess/NodeAccessType.java b/src/main/java/org/olat/course/nodeaccess/NodeAccessType.java index a73f2b25fa8f5cfc31072082fd21bff7425ca8cb..c4c6d844bcdd1521393e55818dcfdd3649ede7de 100644 --- a/src/main/java/org/olat/course/nodeaccess/NodeAccessType.java +++ b/src/main/java/org/olat/course/nodeaccess/NodeAccessType.java @@ -21,6 +21,7 @@ package org.olat.course.nodeaccess; import org.olat.course.ICourse; import org.olat.course.nodeaccess.model.NodeAccessTypeImpl; +import org.olat.course.run.userview.UserCourseEnvironment; /** * @@ -39,5 +40,9 @@ public interface NodeAccessType { public static NodeAccessType of(ICourse course) { return course.getCourseConfig().getNodeAccessType(); } + + public static NodeAccessType of(UserCourseEnvironment userCourseEnvironment) { + return userCourseEnvironment.getCourseEnvironment().getCourseConfig().getNodeAccessType(); + } } diff --git a/src/main/java/org/olat/course/nodes/sp/SPLearningPathNodeHandler.java b/src/main/java/org/olat/course/nodes/sp/SPLearningPathNodeHandler.java index 0d4674e68756dfdf6082ef2fe593c050ec667b2a..91d5725d524966fd6c89ade2b2204431245e9576 100644 --- a/src/main/java/org/olat/course/nodes/sp/SPLearningPathNodeHandler.java +++ b/src/main/java/org/olat/course/nodes/sp/SPLearningPathNodeHandler.java @@ -23,9 +23,11 @@ import org.olat.core.gui.UserRequest; import org.olat.core.gui.control.Controller; import org.olat.core.gui.control.WindowControl; import org.olat.course.assessment.AssessmentAction; +import org.olat.course.learningpath.LearningPathConfigs; import org.olat.course.learningpath.LearningPathNodeHandler; -import org.olat.course.learningpath.ui.LeaningPathNodeConfigController; -import org.olat.course.learningpath.ui.LeaningPathNodeConfigController.LearningPathControllerConfig; +import org.olat.course.learningpath.model.ModuleLearningPathConfigs; +import org.olat.course.learningpath.ui.LearningPathNodeConfigController; +import org.olat.course.learningpath.ui.LearningPathNodeConfigController.LearningPathControllerConfig; import org.olat.course.nodes.CourseNode; import org.olat.course.nodes.SPCourseNode; import org.springframework.stereotype.Service; @@ -50,11 +52,16 @@ public class SPLearningPathNodeHandler implements LearningPathNodeHandler { } @Override - public Controller createEditController(UserRequest ureq, WindowControl wControl, CourseNode courseNode) { - LearningPathControllerConfig ctrlConfig = LeaningPathNodeConfigController.builder() - .addAssessmentAction(AssessmentAction.nodeClicked) + public LearningPathConfigs getConfigs(CourseNode courseNode) { + return new ModuleLearningPathConfigs(courseNode.getModuleConfiguration()); + } + + @Override + public Controller createConfigEditController(UserRequest ureq, WindowControl wControl, CourseNode courseNode) { + LearningPathControllerConfig ctrlConfig = LearningPathNodeConfigController.builder() + .addAssessmentAction(AssessmentAction.nodeVisited) .build(); - return new LeaningPathNodeConfigController(ureq, wControl, courseNode.getModuleConfiguration(), ctrlConfig); + return new LearningPathNodeConfigController(ureq, wControl, courseNode.getModuleConfiguration(), ctrlConfig); } } diff --git a/src/main/java/org/olat/course/nodes/st/STLearningPathNodeHandler.java b/src/main/java/org/olat/course/nodes/st/STLearningPathNodeHandler.java index afd7745fcfb2c2524998f4ae95c998116522195b..be6935535e8285945e1c30a8eee3643c52936ce8 100644 --- a/src/main/java/org/olat/course/nodes/st/STLearningPathNodeHandler.java +++ b/src/main/java/org/olat/course/nodes/st/STLearningPathNodeHandler.java @@ -25,7 +25,9 @@ import org.olat.core.gui.control.WindowControl; import org.olat.core.gui.control.generic.messages.MessageUIFactory; import org.olat.core.gui.translator.Translator; import org.olat.core.util.Util; +import org.olat.course.learningpath.LearningPathConfigs; import org.olat.course.learningpath.LearningPathNodeHandler; +import org.olat.course.learningpath.model.ModuleLearningPathConfigs; import org.olat.course.learningpath.ui.TabbableLeaningPathNodeConfigController; import org.olat.course.nodes.CourseNode; import org.olat.course.nodes.STCourseNode; @@ -51,7 +53,12 @@ public class STLearningPathNodeHandler implements LearningPathNodeHandler { } @Override - public Controller createEditController(UserRequest ureq, WindowControl wControl, CourseNode courseNode) { + public LearningPathConfigs getConfigs(CourseNode courseNode) { + return new ModuleLearningPathConfigs(courseNode.getModuleConfiguration()); + } + + @Override + public Controller createConfigEditController(UserRequest ureq, WindowControl wControl, CourseNode courseNode) { Translator translator = Util.createPackageTranslator(TabbableLeaningPathNodeConfigController.class, ureq.getLocale()); return MessageUIFactory.createInfoMessage(ureq, wControl, null, translator.translate("no.configurations")); } diff --git a/src/main/java/org/olat/course/nodes/video/VideoLearningPathNodeHandler.java b/src/main/java/org/olat/course/nodes/video/VideoLearningPathNodeHandler.java index 0ba8cefb528510ff902a7c169c075f28a2eec8e1..a358dcdbdeac54f134336c2419e979053e0fb6f3 100644 --- a/src/main/java/org/olat/course/nodes/video/VideoLearningPathNodeHandler.java +++ b/src/main/java/org/olat/course/nodes/video/VideoLearningPathNodeHandler.java @@ -23,9 +23,11 @@ import org.olat.core.gui.UserRequest; import org.olat.core.gui.control.Controller; import org.olat.core.gui.control.WindowControl; import org.olat.course.assessment.AssessmentAction; +import org.olat.course.learningpath.LearningPathConfigs; import org.olat.course.learningpath.LearningPathNodeHandler; -import org.olat.course.learningpath.ui.LeaningPathNodeConfigController; -import org.olat.course.learningpath.ui.LeaningPathNodeConfigController.LearningPathControllerConfig; +import org.olat.course.learningpath.model.ModuleLearningPathConfigs; +import org.olat.course.learningpath.ui.LearningPathNodeConfigController; +import org.olat.course.learningpath.ui.LearningPathNodeConfigController.LearningPathControllerConfig; import org.olat.course.nodes.CourseNode; import org.olat.course.nodes.VideoCourseNode; import org.springframework.stereotype.Service; @@ -50,11 +52,16 @@ public class VideoLearningPathNodeHandler implements LearningPathNodeHandler { } @Override - public Controller createEditController(UserRequest ureq, WindowControl wControl, CourseNode courseNode) { - LearningPathControllerConfig ctrlConfig = LeaningPathNodeConfigController.builder() - .addAssessmentAction(AssessmentAction.nodeClicked) + public LearningPathConfigs getConfigs(CourseNode courseNode) { + return new ModuleLearningPathConfigs(courseNode.getModuleConfiguration()); + } + + @Override + public Controller createConfigEditController(UserRequest ureq, WindowControl wControl, CourseNode courseNode) { + LearningPathControllerConfig ctrlConfig = LearningPathNodeConfigController.builder() + .addAssessmentAction(AssessmentAction.nodeVisited) .build(); - return new LeaningPathNodeConfigController(ureq, wControl, courseNode.getModuleConfiguration(), ctrlConfig); + return new LearningPathNodeConfigController(ureq, wControl, courseNode.getModuleConfiguration(), ctrlConfig); } } diff --git a/src/main/java/org/olat/course/run/RunMainController.java b/src/main/java/org/olat/course/run/RunMainController.java index f106a56dcd02f494568493b2d88cc1adbdaf89c1..0fb6d5760274b63d10f49c8d8e84fb9c0b05efe6 100644 --- a/src/main/java/org/olat/course/run/RunMainController.java +++ b/src/main/java/org/olat/course/run/RunMainController.java @@ -798,6 +798,7 @@ public class RunMainController extends MainLayoutBasicController implements Gene /** * @see org.olat.core.gui.control.DefaultController#doDispose(boolean) */ + @Override protected void doDispose() { // remove as listener from this course events: // - group modification events diff --git a/src/main/java/org/olat/course/run/preview/PreviewAssessmentManager.java b/src/main/java/org/olat/course/run/preview/PreviewAssessmentManager.java index bfa924cc626a18fb514ba91e415da76a46bedc3f..1c44d050103c02b1bddce4e348db1c5a6f080201 100644 --- a/src/main/java/org/olat/course/run/preview/PreviewAssessmentManager.java +++ b/src/main/java/org/olat/course/run/preview/PreviewAssessmentManager.java @@ -122,24 +122,15 @@ final class PreviewAssessmentManager implements AssessmentManager { // } - /** - * @see org.olat.course.assessment.AssessmentManager#saveNodeCoachComment(org.olat.course.nodes.CourseNode, org.olat.core.id.Identity, java.lang.String) - */ @Override public void saveNodeCoachComment(CourseNode courseNode, Identity assessedIdentity, String comment) { throw new AssertException("Not implemented for preview."); } - /** - * @see org.olat.course.assessment.AssessmentManager#saveNodePassed(org.olat.course.nodes.CourseNode, org.olat.core.id.Identity, org.olat.core.id.Identity, java.lang.Boolean) - */ private void saveNodePassed(CourseNode courseNode, Boolean passed) { nodePassed.put(courseNode.getIdent(), passed); } - /** - * @see org.olat.course.assessment.AssessmentManager#incrementNodeAttempts(org.olat.course.nodes.CourseNode, org.olat.core.id.Identity) - */ @Override public void incrementNodeAttempts(CourseNode courseNode, Identity identity, UserCourseEnvironment userCourseEnvironment, Role by) { Integer attempts = nodeAttempts.get(courseNode.getIdent()); @@ -149,10 +140,6 @@ final class PreviewAssessmentManager implements AssessmentManager { nodeAttempts.put(courseNode.getIdent(), Integer.valueOf(iAttempts)); } - /** - * @see org.olat.course.assessment.AssessmentManager#incrementNodeAttemptsInBackground(org.olat.course.nodes.CourseNode, - * org.olat.core.id.Identity, org.olat.course.run.userview.UserCourseEnvironment) - */ @Override public void incrementNodeAttemptsInBackground(CourseNode courseNode, Identity identity, UserCourseEnvironment userCourseEnvironment) { incrementNodeAttempts(courseNode, identity, userCourseEnvironment, Role.auto); @@ -164,6 +151,12 @@ final class PreviewAssessmentManager implements AssessmentManager { // } + @Override + public void updateAssessmentStatus(CourseNode courseNode, Identity assessedIdentity, AssessmentEntryStatus status, + Role by) { + // + } + @Override public void updateLastModifications(CourseNode courseNode, Identity assessedIdentity, UserCourseEnvironment userCourseEnvironment, Role by) { // @@ -174,17 +167,11 @@ final class PreviewAssessmentManager implements AssessmentManager { // } - /** - * @see org.olat.course.assessment.AssessmentManager#getNodeScore(org.olat.course.nodes.CourseNode, org.olat.core.id.Identity) - */ @Override public Float getNodeScore(CourseNode courseNode, Identity identity) { return nodeScores.get(courseNode.getIdent()); } - /** - * @see org.olat.course.assessment.AssessmentManager#getNodeComment(org.olat.course.nodes.CourseNode, org.olat.core.id.Identity) - */ @Override public String getNodeComment(CourseNode courseNode, Identity identity) { return "This is a preview"; //default comment for preview @@ -195,17 +182,11 @@ final class PreviewAssessmentManager implements AssessmentManager { return Collections.emptyList(); } - /** - * @see org.olat.course.assessment.AssessmentManager#getNodeCoachComment(org.olat.course.nodes.CourseNode, org.olat.core.id.Identity) - */ @Override public String getNodeCoachComment(CourseNode courseNode, Identity identity) { return "This is a preview"; //default comment for preview } - /** - * @see org.olat.course.assessment.AssessmentManager#getNodePassed(org.olat.course.nodes.CourseNode, org.olat.core.id.Identity) - */ @Override public Boolean getNodePassed(CourseNode courseNode, Identity identity) { return nodePassed.get(courseNode.getIdent()); @@ -216,9 +197,6 @@ final class PreviewAssessmentManager implements AssessmentManager { return nodePassed.get(courseNode.getIdent()); } - /** - * @see org.olat.course.assessment.AssessmentManager#getNodeAttempts(org.olat.course.nodes.CourseNode, org.olat.core.id.Identity) - */ @Override public Integer getNodeAttempts(CourseNode courseNode, Identity identity) { Integer attempts = nodeAttempts.get(courseNode.getIdent()); @@ -235,36 +213,20 @@ final class PreviewAssessmentManager implements AssessmentManager { return null; } - /** - * @see org.olat.course.assessment.AssessmentManager#registerForAssessmentChangeEvents(org.olat.core.util.event.GenericEventListener, org.olat.core.id.Identity) - */ @Override public void registerForAssessmentChangeEvents(GenericEventListener gel, Identity identity) { throw new AssertException("Not implemented for preview."); } - /** - * @see org.olat.course.assessment.AssessmentManager#deregisterFromAssessmentChangeEvents(org.olat.core.util.event.GenericEventListener) - */ @Override public void deregisterFromAssessmentChangeEvents(GenericEventListener gel) { throw new AssertException("Not implemented for preview."); } - /** - * - * @see org.olat.course.assessment.AssessmentManager#saveAssessmentID(org.olat.course.nodes.CourseNode, org.olat.core.id.Identity, java.lang.String) - */ private void saveAssessmentID(CourseNode courseNode, Long assessmentID) { nodeAssessmentID.put(courseNode.getIdent(), assessmentID); } - /** - * - * @param courseNode - * @param identity - * @return - */ @Override public Long getAssessmentID(CourseNode courseNode, Identity identity) { return nodeAssessmentID.get(courseNode.getIdent()); @@ -288,7 +250,7 @@ final class PreviewAssessmentManager implements AssessmentManager { } @Override - public OLATResourceable createOLATResourceableForLocking(Identity assessedIdentity) { + public OLATResourceable createOLATResourceableForLocking(Identity assessedIdentity) { throw new AssertException("Not implemented for preview."); } } \ No newline at end of file diff --git a/src/main/java/org/olat/modules/assessment/AssessmentEntry.java b/src/main/java/org/olat/modules/assessment/AssessmentEntry.java index a2ef10fa18bcc10cef38081820b195f6429b0aaa..7d7a7569b4f453f7e191afd932c24e6ddae16e20 100644 --- a/src/main/java/org/olat/modules/assessment/AssessmentEntry.java +++ b/src/main/java/org/olat/modules/assessment/AssessmentEntry.java @@ -68,6 +68,8 @@ public interface AssessmentEntry extends AssessmentEntryLight { public AssessmentEntryStatus getAssessmentStatus(); public void setAssessmentStatus(AssessmentEntryStatus assessmentStatus); + + public Date getAssessmentDone(); /** * Used by Onyx diff --git a/src/main/java/org/olat/modules/assessment/model/AssessmentEntryImpl.java b/src/main/java/org/olat/modules/assessment/model/AssessmentEntryImpl.java index d808e38b8dade221b5a854debc9ea0860bd678a1..8a5403ebe96714c23557aaf5b9e705bc5eb66497 100644 --- a/src/main/java/org/olat/modules/assessment/model/AssessmentEntryImpl.java +++ b/src/main/java/org/olat/modules/assessment/model/AssessmentEntryImpl.java @@ -89,6 +89,8 @@ public class AssessmentEntryImpl implements Persistable, ModifiedInfo, CreateInf private Boolean passed; @Column(name="a_status", nullable=true, insertable=true, updatable=true) private String status; + @Column(name="a_date_done", nullable=true, insertable=true, updatable=true) + private Date assessmentDone; @Column(name="a_details", nullable=true, insertable=true, updatable=true) private String details; @Column(name="a_user_visibility", nullable=true, insertable=true, updatable=true) @@ -240,6 +242,13 @@ public class AssessmentEntryImpl implements Persistable, ModifiedInfo, CreateInf @Override public void setAssessmentStatus(AssessmentEntryStatus assessmentStatus) { + AssessmentEntryStatus previousStatus = getAssessmentStatus(); + if (AssessmentEntryStatus.done.equals(assessmentStatus) && !AssessmentEntryStatus.done.equals(previousStatus)) { + assessmentDone = new Date(); + } else { + assessmentDone = null; + } + if(assessmentStatus == null) { this.status = null; } else { @@ -247,6 +256,11 @@ public class AssessmentEntryImpl implements Persistable, ModifiedInfo, CreateInf } } + @Override + public Date getAssessmentDone() { + return assessmentDone; + } + @Override public Boolean getUserVisibility() { return userVisibility; diff --git a/src/main/resources/database/mysql/alter_14_1_x_to_14_2_0.sql b/src/main/resources/database/mysql/alter_14_1_x_to_14_2_0.sql index 57509da67cfd58b932fee14ef1b6892b74975887..3171b6b3f8584666296fae0a420835f57cf7991f 100644 --- a/src/main/resources/database/mysql/alter_14_1_x_to_14_2_0.sql +++ b/src/main/resources/database/mysql/alter_14_1_x_to_14_2_0.sql @@ -1,4 +1,5 @@ -- Assessment -alter table o_as_entry add a_first_visit datetime null; -alter table o_as_entry add a_last_visit datetime null; -alter table o_as_entry add a_num_visits int8 null; +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; diff --git a/src/main/resources/database/oracle/alter_14_1_x_to_14_2_0.sql b/src/main/resources/database/oracle/alter_14_1_x_to_14_2_0.sql index b2c56945bb691947410a2b2a3e70fd8008b81b7f..cf8eba16f1773a737d56959ee530945a28bcb49a 100644 --- a/src/main/resources/database/oracle/alter_14_1_x_to_14_2_0.sql +++ b/src/main/resources/database/oracle/alter_14_1_x_to_14_2_0.sql @@ -2,3 +2,4 @@ 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; diff --git a/src/main/resources/database/postgresql/alter_14_1_x_to_14_2_0.sql b/src/main/resources/database/postgresql/alter_14_1_x_to_14_2_0.sql index fecbd02bb28dca2f04a95f85258c85186ea6f631..806c9d9c5c0d73cebc33d988378f4ac8899956b5 100644 --- a/src/main/resources/database/postgresql/alter_14_1_x_to_14_2_0.sql +++ b/src/main/resources/database/postgresql/alter_14_1_x_to_14_2_0.sql @@ -1,4 +1,5 @@ -- Assessment -alter table o_as_entry add a_first_visit timestamp null; -alter table o_as_entry add a_last_visit timestamp null; -alter table o_as_entry add a_num_visits int8 null; +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; diff --git a/src/test/java/org/olat/modules/assessment/manager/AssessmentEntryDAOTest.java b/src/test/java/org/olat/modules/assessment/manager/AssessmentEntryDAOTest.java index b982a7e029ada97b05acdd8d294b18a551511de9..c249aa8d6b3c540741db7d63133e3a992ad0e00f 100644 --- a/src/test/java/org/olat/modules/assessment/manager/AssessmentEntryDAOTest.java +++ b/src/test/java/org/olat/modules/assessment/manager/AssessmentEntryDAOTest.java @@ -33,6 +33,7 @@ import org.olat.group.BusinessGroup; import org.olat.group.manager.BusinessGroupDAO; import org.olat.group.manager.BusinessGroupRelationDAO; import org.olat.modules.assessment.AssessmentEntry; +import org.olat.modules.assessment.model.AssessmentEntryStatus; import org.olat.repository.RepositoryEntry; import org.olat.test.JunitTestHelper; import org.olat.test.OlatTestCase; @@ -230,6 +231,43 @@ public class AssessmentEntryDAOTest extends OlatTestCase { Assert.assertEquals(nodeAssessment.getNumberOfVisits().intValue(), 2); } + @Test + public void setAssessmentDone() { + Identity assessedIdentity = JunitTestHelper.createAndPersistIdentityAsRndUser("as-node-6"); + RepositoryEntry entry = JunitTestHelper.createAndPersistRepositoryEntry(); + RepositoryEntry refEntry = JunitTestHelper.createAndPersistRepositoryEntry(); + String subIdent = UUID.randomUUID().toString(); + AssessmentEntry nodeAssessment = assessmentEntryDao + .createAssessmentEntry(assessedIdentity, null, entry, subIdent, refEntry, 2.0f, Boolean.TRUE, null, null); + dbInstance.commitAndCloseSession(); + + Assert.assertNull(nodeAssessment.getAssessmentDone()); + + nodeAssessment.setAssessmentStatus(AssessmentEntryStatus.done); + nodeAssessment = assessmentEntryDao.updateAssessmentEntry(nodeAssessment); + dbInstance.commitAndCloseSession(); + + Assert.assertNotNull(nodeAssessment.getAssessmentDone()); + + nodeAssessment.setAssessmentStatus(null); + nodeAssessment = assessmentEntryDao.updateAssessmentEntry(nodeAssessment); + dbInstance.commitAndCloseSession(); + + Assert.assertNull(nodeAssessment.getAssessmentDone()); + + nodeAssessment.setAssessmentStatus(AssessmentEntryStatus.inProgress); + nodeAssessment = assessmentEntryDao.updateAssessmentEntry(nodeAssessment); + dbInstance.commitAndCloseSession(); + + Assert.assertNull(nodeAssessment.getAssessmentDone()); + + nodeAssessment.setAssessmentStatus(AssessmentEntryStatus.done); + nodeAssessment = assessmentEntryDao.updateAssessmentEntry(nodeAssessment); + dbInstance.commitAndCloseSession(); + + Assert.assertNotNull(nodeAssessment.getAssessmentDone()); + } + @Test public void loadAssessmentEntries_subIdent() { Identity assessedIdentity1 = JunitTestHelper.createAndPersistIdentityAsRndUser("as-node-7");