diff --git a/pom.xml b/pom.xml index 756fa1e91ff4129063cc75cf00c6a6665486eb06..20ea423af3b292887e3708d25dedf66f0c2e3ec0 100644 --- a/pom.xml +++ b/pom.xml @@ -98,9 +98,9 @@ <test.env.db.oracle.host.port>1521</test.env.db.oracle.host.port> <test.env.instance.id>myolat</test.env.instance.id> <test.env.webdriver.browser>chrome</test.env.webdriver.browser> - <test.env.webdriver.firefox.version>v0.27.0</test.env.webdriver.firefox.version> - <test.env.webdriver.chrome.version>86.0.4240.22</test.env.webdriver.chrome.version> - <test.env.webdriver.chrome.arguments /> + <test.env.webdriver.firefox.version>v0.29.0</test.env.webdriver.firefox.version> + <test.env.webdriver.chrome.version>88.0.4324.96</test.env.webdriver.chrome.version> + <test.env.webdriver.chrome.arguments></test.env.webdriver.chrome.arguments> <skipTests>true</skipTests> <skipSeleniumTests>false</skipSeleniumTests> diff --git a/src/main/java/org/olat/commons/calendar/ui/ExternalLinksController.java b/src/main/java/org/olat/commons/calendar/ui/ExternalLinksController.java index 94f6951a8e04a037f6bf2a59cf6ec21f251e7f2e..f4eda5f9c4c46b8f451954b0100b271e6560b800 100644 --- a/src/main/java/org/olat/commons/calendar/ui/ExternalLinksController.java +++ b/src/main/java/org/olat/commons/calendar/ui/ExternalLinksController.java @@ -124,36 +124,36 @@ public class ExternalLinksController extends FormBasicController { String id = link.getId(); String uri = link.getLink().getURI(); if(!StringHelper.containsNonWhitespace(uri)) { - uri = "http://"; + uri = "https://"; } - TextElement url = uifactory.addTextElement("url_" + id, null, -1, uri, layoutContainer); + TextElement url = uifactory.addTextElement("url_".concat(id), null, -1, uri, layoutContainer); url.clearError(); url.setDisplaySize(60); url.setMandatory(true); link.setUrl(url); // add link description - TextElement name = uifactory.addTextElement("displayName_" + id, null, -1, link.getLink().getDisplayName(), layoutContainer); + TextElement name = uifactory.addTextElement("displayName_".concat(id), null, -1, link.getLink().getDisplayName(), layoutContainer); name.clearError(); name.setDisplaySize(40); name.setMandatory(true); link.setName(name); // add link add action button - FormLink addButton = uifactory.addFormLink("add_" + id, "table.add", "table.add", layoutContainer, Link.BUTTON); + FormLink addButton = uifactory.addFormLink("add_".concat(id), "table.add", "table.add", layoutContainer, Link.BUTTON); addButton.setUserObject(link); link.setAddButton(addButton); // add link deletion action button - FormLink delButton = uifactory.addFormLink("del_" + id, "table.delete", "table.delete", layoutContainer, Link.BUTTON); + FormLink delButton = uifactory.addFormLink("del_".concat(id), "table.delete", "table.delete", layoutContainer, Link.BUTTON); delButton.setUserObject(link); link.setDelButton(delButton); } @Override protected boolean validateFormLogic(UserRequest ureq) { + boolean allOk = super.validateFormLogic(ureq); - boolean allOk = true; for(LinkWrapper link:externalLinks) { link.getUrl().clearError(); link.getName().clearError(); @@ -182,13 +182,13 @@ public class ExternalLinksController extends FormBasicController { } } - return allOk && super.validateFormLogic(ureq); + return allOk; } @Override protected void formInnerEvent(UserRequest ureq, FormItem source, FormEvent event) { if(source == newButton) { - String id = UUID.randomUUID().toString().replaceAll("-", ""); + String id = UUID.randomUUID().toString().replace("-", ""); KalendarEventLink link = new KalendarEventLink(EXTERNAL_LINKS_PROVIDER, id, "", "", ""); LinkWrapper linkWrapper = new LinkWrapper(link); externalLinks.add(linkWrapper); @@ -246,7 +246,7 @@ public class ExternalLinksController extends FormBasicController { //remove deleted links for(Iterator<KalendarEventLink> it=links.iterator(); it.hasNext(); ) { KalendarEventLink link = it.next(); - if(EXTERNAL_LINKS_PROVIDER.equals(link.getId()) && !usedUuids.contains(link.getId())) { + if(EXTERNAL_LINKS_PROVIDER.equals(link.getProvider()) && !usedUuids.contains(link.getId())) { it.remove(); } } @@ -261,10 +261,9 @@ public class ExternalLinksController extends FormBasicController { private LinkWrapper createLinkWrapper() { - String id = UUID.randomUUID().toString().replaceAll("-", ""); + String id = UUID.randomUUID().toString().replace("-", ""); KalendarEventLink newLink = new KalendarEventLink(EXTERNAL_LINKS_PROVIDER, id, "", "", ""); - LinkWrapper newLinkWrapper = new LinkWrapper(newLink); - return newLinkWrapper; + return new LinkWrapper(newLink); } public class LinkWrapper { diff --git a/src/main/java/org/olat/core/commons/services/doceditor/onlyoffice/manager/OnlyOfficeServiceImpl.java b/src/main/java/org/olat/core/commons/services/doceditor/onlyoffice/manager/OnlyOfficeServiceImpl.java index b1aba56d3dccc854091f179fa389495d4e101a14..ac72c676ce8d3859f2e324e5b071a7c4f239fad1 100644 --- a/src/main/java/org/olat/core/commons/services/doceditor/onlyoffice/manager/OnlyOfficeServiceImpl.java +++ b/src/main/java/org/olat/core/commons/services/doceditor/onlyoffice/manager/OnlyOfficeServiceImpl.java @@ -293,7 +293,7 @@ public class OnlyOfficeServiceImpl implements OnlyOfficeService { if (licenseEdit.intValue() <= 0) return false; Long accessCount = documentEditorServie.getAccessCount(OnlyOfficeEditor.TYPE, Mode.EDIT); - return accessCount < licenseEdit.intValue(); + return accessCount <= licenseEdit.intValue(); } @Override diff --git a/src/main/java/org/olat/core/commons/services/doceditor/onlyoffice/ui/OnlyOfficeEditorController.java b/src/main/java/org/olat/core/commons/services/doceditor/onlyoffice/ui/OnlyOfficeEditorController.java index a838c432e4e6d128eaeff64dcb98c83c15d5d92e..13768de4941cb5395bbb7658728d2e9361243547 100644 --- a/src/main/java/org/olat/core/commons/services/doceditor/onlyoffice/ui/OnlyOfficeEditorController.java +++ b/src/main/java/org/olat/core/commons/services/doceditor/onlyoffice/ui/OnlyOfficeEditorController.java @@ -30,6 +30,7 @@ import org.olat.core.commons.services.doceditor.onlyoffice.OnlyOfficeService; import org.olat.core.commons.services.vfs.VFSMetadata; import org.olat.core.gui.UserRequest; import org.olat.core.gui.components.Component; +import org.olat.core.gui.components.Window; import org.olat.core.gui.components.velocity.VelocityContainer; import org.olat.core.gui.control.Event; import org.olat.core.gui.control.WindowControl; @@ -65,6 +66,8 @@ public class OnlyOfficeEditorController extends BasicController { final DocEditorConfigs configs, Access runAccess) { super(ureq, wControl); access = runAccess; + + wControl.getWindowBackOffice().getWindow().addListener(this); if (Mode.EDIT == access.getMode() && !onlyOfficeService.isEditLicenseAvailable()) { access = docEditorService.updateMode(access, Mode.VIEW); @@ -111,11 +114,14 @@ public class OnlyOfficeEditorController extends BasicController { putInitialPanel(mainVC); } - + @Override - protected void event(UserRequest ureq, Component source, Event event) { - // + public void event(UserRequest ureq, Component source, Event event) { + if(event == Window.CLOSE_WINDOW) { + deleteAccess(); + } } + @Override protected void doDispose() { diff --git a/src/main/java/org/olat/core/commons/services/scheduler/_spring/schedulerContext.xml b/src/main/java/org/olat/core/commons/services/scheduler/_spring/schedulerContext.xml index 907b85c71e4a05f4c84ada968ce87427b87803ab..aefc59b1293951d99e23ac1023691ce660a45bc8 100644 --- a/src/main/java/org/olat/core/commons/services/scheduler/_spring/schedulerContext.xml +++ b/src/main/java/org/olat/core/commons/services/scheduler/_spring/schedulerContext.xml @@ -37,7 +37,6 @@ How to add a new job: <ref bean="sendNotificationsEmailTrigger" /> <ref bean="updateStatisticsTrigger"/> <ref bean="searchIndexingTrigger"/> - <ref bean="invitationCleanupTrigger" /> <ref bean="restTokenTrigger" /> <ref bean="taskExecutorTrigger" /> <ref bean="procSamplerTrigger"/> diff --git a/src/main/java/org/olat/course/nodes/CheckListCourseNode.java b/src/main/java/org/olat/course/nodes/CheckListCourseNode.java index 6c6a6ca33bd5b9cb07f10574002a3c9d72314589..971380d1ea0ad73ad7d7eeb1ca4373b859ed1bf0 100644 --- a/src/main/java/org/olat/course/nodes/CheckListCourseNode.java +++ b/src/main/java/org/olat/course/nodes/CheckListCourseNode.java @@ -457,7 +457,7 @@ public class CheckListCourseNode extends AbstractAccessableCourseNode { } } - ScoreEvaluation sceval = new ScoreEvaluation(score, new Boolean(passed)); + ScoreEvaluation sceval = new ScoreEvaluation(score, Boolean.valueOf(passed)); CourseAssessmentService courseAssessmentService = CoreSpringFactory.getImpl(CourseAssessmentService.class); courseAssessmentService.saveScoreEvaluation(this, identity, sceval, assessedUserCourseEnv, false, by); @@ -475,7 +475,7 @@ public class CheckListCourseNode extends AbstractAccessableCourseNode { CourseAssessmentService courseAssessmentService = CoreSpringFactory.getImpl(CourseAssessmentService.class); ScoreEvaluation currentEval = courseAssessmentService.getAssessmentEvaluation(this, assessedUserCourseEnv); - ScoreEvaluation sceval = new ScoreEvaluation(new Float(score), currentEval.getPassed()); + ScoreEvaluation sceval = new ScoreEvaluation(Float.valueOf(score), currentEval.getPassed()); courseAssessmentService.saveScoreEvaluation(this, identity, sceval, assessedUserCourseEnv, false, by); } @@ -558,10 +558,15 @@ public class CheckListCourseNode extends AbstractAccessableCourseNode { private void updateScorePassedOnPublish(Identity assessedIdentity, Identity coachIdentity, CheckboxManager checkboxManager, ICourse course) { AssessmentManager am = course.getCourseEnvironment().getAssessmentManager(); - Float currentScore = am.getNodeScore(this, assessedIdentity); - Boolean currentPassed = am.getNodePassed(this, assessedIdentity); + Float currentScore = null; + Boolean currentPassed = null; + AssessmentEntry ae = am.getAssessmentEntry(this, assessedIdentity); + if(ae != null) { + currentScore = ae.getScore() == null ? null : ae.getScore().floatValue(); + currentPassed = ae.getPassed(); + } - Float updatedScore = null; + Float updatedScore; Boolean updatedPassed = null; ModuleConfiguration config = getModuleConfiguration(); @@ -616,7 +621,7 @@ public class CheckListCourseNode extends AbstractAccessableCourseNode { || (currentScore != null && updatedScore == null) || (currentScore != null && !currentScore.equals(updatedScore))) { needUpdate = true; - } + } if(needUpdate) { ScoreEvaluation scoreEval = new ScoreEvaluation(updatedScore, updatedPassed); diff --git a/src/main/java/org/olat/course/nodes/cl/ui/CheckListExcelExport.java b/src/main/java/org/olat/course/nodes/cl/ui/CheckListExcelExport.java index 838335d5d8a84f3b72372874c53d11e45a44a03c..f946e509db3302ccc64d23e7ced3bb0e85792576 100644 --- a/src/main/java/org/olat/course/nodes/cl/ui/CheckListExcelExport.java +++ b/src/main/java/org/olat/course/nodes/cl/ui/CheckListExcelExport.java @@ -78,6 +78,7 @@ public class CheckListExcelExport { private final CheckListCourseNode courseNode; private final boolean hasScore; private final boolean hasPassed; + private final boolean hasComment; private final List<UserPropertyHandler> userPropertyHandlers; private final UserManager userManager; @@ -91,6 +92,7 @@ public class CheckListExcelExport { AssessmentConfig assessmentConfig = courseAssessmentService.getAssessmentConfig(courseNode); this.hasScore = Mode.none != assessmentConfig.getScoreMode(); this.hasPassed = Mode.none != assessmentConfig.getPassedMode(); + this.hasComment = assessmentConfig.hasComment(); userManager = CoreSpringFactory.getImpl(UserManager.class); checkboxManager = CoreSpringFactory.getImpl(CheckboxManager.class); @@ -150,6 +152,9 @@ public class CheckListExcelExport { if(hasPassed) { header2Row.addCell(col++, translator.translate("column.header.node.passed"), headerStyle); } + if(hasComment) { + header2Row.addCell(col++, translator.translate("column.header.usercomment"), headerStyle); + } ModuleConfiguration config = courseNode.getModuleConfiguration(); CheckboxList list = (CheckboxList)config.get(CheckListCourseNode.CONFIG_KEY_CHECKBOX); @@ -214,6 +219,14 @@ public class CheckListExcelExport { col++; } } + + if(hasComment) { + if(entry != null) { + dataRow.addCell(col++, entry.getComment(), null); + } else { + col++; + } + } ModuleConfiguration config = courseNode.getModuleConfiguration(); CheckboxList list = (CheckboxList)config.get(CheckListCourseNode.CONFIG_KEY_CHECKBOX); diff --git a/src/main/java/org/olat/course/nodes/cl/ui/_i18n/LocalStrings_de.properties b/src/main/java/org/olat/course/nodes/cl/ui/_i18n/LocalStrings_de.properties index a9b49dc9f7bbc9b9b22ed43f2489fdf934c9e119..3ff4361f49d073029730351d64367c95116ba81e 100644 --- a/src/main/java/org/olat/course/nodes/cl/ui/_i18n/LocalStrings_de.properties +++ b/src/main/java/org/olat/course/nodes/cl/ui/_i18n/LocalStrings_de.properties @@ -21,6 +21,7 @@ column.header.homepage=Homepage column.header.node.passed=Kursbaustein bestanden column.header.node.points=Kursbaustein Punkte column.header.points=$\:box.points +column.header.usercomment=Kommentar f\u00FCr Benutzer comment.nocomment=$org.olat.course.nodes.ms\:comment.nocomment comment.title=$org.olat.course.nodes.ms\:comment.title config.checkbox.description=W\u00e4hlen Sie "$\:add.checkbox" um eine neue Checkbox zu erzeugen oder "$org.olat.core\:edit" um eine bestehende Checkbox zu ver\u00e4ndern. diff --git a/src/main/java/org/olat/course/nodes/cl/ui/_i18n/LocalStrings_en.properties b/src/main/java/org/olat/course/nodes/cl/ui/_i18n/LocalStrings_en.properties index 90f8e83a2f64f20e792fb58337eaf314d908b18c..cdc96b54877c3065be923e95dfb0dc83c1c8b133 100644 --- a/src/main/java/org/olat/course/nodes/cl/ui/_i18n/LocalStrings_en.properties +++ b/src/main/java/org/olat/course/nodes/cl/ui/_i18n/LocalStrings_en.properties @@ -21,6 +21,7 @@ column.header.node.passed=Passed course element column.header.node.points=Score course element column.header.points=$\:box.points column.header.seqnum=Sequence number +column.header.usercomment=Comments for users comment.nocomment=$org.olat.course.nodes.ms\:comment.nocomment comment.title=$org.olat.course.nodes.ms\:comment.title config.checkbox.description=Click "$\:add.checkbox" to create a new checkbox or select "$org.olat.core\:edit" to configure an existing checkbox. diff --git a/src/main/java/org/olat/course/nodes/cl/ui/_i18n/LocalStrings_fr.properties b/src/main/java/org/olat/course/nodes/cl/ui/_i18n/LocalStrings_fr.properties index fe675148d8a6467a0d136cd862013d01c4a4f633..80c1fc87bd23118f3d5e921d8882b8f4f0532b8a 100644 --- a/src/main/java/org/olat/course/nodes/cl/ui/_i18n/LocalStrings_fr.properties +++ b/src/main/java/org/olat/course/nodes/cl/ui/_i18n/LocalStrings_fr.properties @@ -21,6 +21,7 @@ column.header.node.passed=\u00C9l\u00E9ment de cours r\u00E9ussi column.header.node.points=Points \u00E9l\u00E9ment de cours column.header.points=$\:box.points column.header.seqnum=Num\u00E9ro +column.header.usercomment=Commentaires pour l'utilisateur comment.nocomment=$org.olat.course.nodes.ms\:comment.nocomment comment.title=$org.olat.course.nodes.ms\:comment.title config.checkbox.description=Clicuez "$\:add.checkbox" pour cr\u00E9er une nouvelle case \u00E0 cocher ou s\u00E9lectionnez "$org.olat.core\:edit" pour configurer une case \u00E0 cocher existante. diff --git a/src/main/java/org/olat/course/nodes/gta/ui/SubmitDocumentsController.java b/src/main/java/org/olat/course/nodes/gta/ui/SubmitDocumentsController.java index e592d98c3b66454cdb216e4f5f6c3de910f36171..d3d8d7246215edcb5ed6741a4bbd2da2dce65b4a 100644 --- a/src/main/java/org/olat/course/nodes/gta/ui/SubmitDocumentsController.java +++ b/src/main/java/org/olat/course/nodes/gta/ui/SubmitDocumentsController.java @@ -234,6 +234,12 @@ class SubmitDocumentsController extends FormBasicController { private void updateWarnings() { if(minDocs > 0 && model.getRowCount() < minDocs) { String msg = translate("error.min.documents", new String[]{ Integer.toString(minDocs) }); + if(uploadDocButton != null) { + uploadDocButton.setEnabled(true); + } + if(createDocButton != null) { + createDocButton.setEnabled(true); + } flc.contextPut("minDocsWarning", msg); flc.contextRemove("maxDocsWarning"); } else if(maxDocs > 0 && model.getRowCount() >= maxDocs) { diff --git a/src/main/java/org/olat/course/run/CourseRuntimeController.java b/src/main/java/org/olat/course/run/CourseRuntimeController.java index a9c70778a0aef95fb4acd456fc213b309191ff90..1dbc506ca73a419793cb8d8840e2dff59aecdaa8 100644 --- a/src/main/java/org/olat/course/run/CourseRuntimeController.java +++ b/src/main/java/org/olat/course/run/CourseRuntimeController.java @@ -481,9 +481,15 @@ public class CourseRuntimeController extends RepositoryEntryRuntimeController im private void setCourseClosedMessage() { UserCourseEnvironment userCourseEnv = getUserCourseEnvironment(); - if(userCourseEnv != null && getRepositoryEntry().getEntryStatus() == RepositoryEntryStatusEnum.closed) { - toolbarPanel.setMessage(translate("course.closed")); - toolbarPanel.setMessageCssClass("o_warning"); + if(userCourseEnv != null) { + if(getRepositoryEntry().getEntryStatus() == RepositoryEntryStatusEnum.closed) { + toolbarPanel.setMessage(translate("course.closed")); + toolbarPanel.setMessageCssClass("o_warning"); + } else if(getRepositoryEntry().getEntryStatus() == RepositoryEntryStatusEnum.deleted + || getRepositoryEntry().getEntryStatus() == RepositoryEntryStatusEnum.trash) { + toolbarPanel.setMessage(translate("course.deleted")); + toolbarPanel.setMessageCssClass("o_warning"); + } } else { toolbarPanel.setMessage(null); toolbarPanel.setMessageComponent(null); 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 fd13bbb9485ab7009da7ba65786b88ed774b6352..3be482b63fee7927b84e9a2b8dafa055be57f09c 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 @@ -55,6 +55,7 @@ command.run=Kurs Laufzeitumgebung command.settings=Kursinfo \u00e4ndern command.wiki=Wiki course.closed=Dieser Kurs wurde beendet und kann nicht mehr bearbeitet oder aktualisiert werden. +course.deleted=Dieser Kurs wurde gel\u00f6scht und kann nicht mehr bearbeitet oder aktualisiert werden. course.disposed.command.restart=Den Kurs beenden und neu starten course.disposed.message=Bitte beenden Sie diesen Kurs und starten Sie ihn neu. course.disposed.title=Dieser Kurs wurde ver\u00e4ndert. 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 0defb69156aab597a9f7b758ad3acb14343a811d..5d0f8ecd4f7fce6e3b5d1fbf3b03014792ff5cf7 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 @@ -55,6 +55,7 @@ command.run=Course runtime command.settings=Change course info command.wiki=Wiki course.closed=This course is finished and can therefore no longer be edited or updated. +course.deleted=This course is deleted and can therefore no longer be edited or updated. course.disposed.command.restart=Close course and restart course.disposed.message=Please close this course and restart. course.disposed.title=This course has been modified. diff --git a/src/main/java/org/olat/course/run/_i18n/LocalStrings_fr.properties b/src/main/java/org/olat/course/run/_i18n/LocalStrings_fr.properties index d954f235e95ea3d0724b87eee1cb76c9783ded9d..7dd82aaddc4a0e8445fa237a3b61cab6fcf5c3be 100644 --- a/src/main/java/org/olat/course/run/_i18n/LocalStrings_fr.properties +++ b/src/main/java/org/olat/course/run/_i18n/LocalStrings_fr.properties @@ -55,6 +55,7 @@ command.run=Cours command.settings=Modifier la description command.wiki=Wiki course.closed=Ce cours est termin\u00E9 et n'est plus \u00E9dit\u00E9 ou actualis\u00E9. +course.deleted=Ce cours a \u00E9t\u00E9 effac\u00E9 et n'est plus \u00E9dit\u00E9 ou actualis\u00E9. course.disposed.command.restart=Fermer le cours et red\u00E9marrer. course.disposed.message=Fermez le cours et red\u00E9marrez-le \u00E0 nouveau SVP. course.disposed.title=Le cours a \u00E9t\u00E9 modifi\u00E9. diff --git a/src/main/java/org/olat/course/run/userview/UserCourseEnvironmentImpl.java b/src/main/java/org/olat/course/run/userview/UserCourseEnvironmentImpl.java index bf905bc81e75759d343cae970f0d29e9cc76302b..075cc4099ead66b02a4e3b3cc29cb30172469d74 100644 --- a/src/main/java/org/olat/course/run/userview/UserCourseEnvironmentImpl.java +++ b/src/main/java/org/olat/course/run/userview/UserCourseEnvironmentImpl.java @@ -50,7 +50,6 @@ import org.olat.group.BusinessGroup; import org.olat.modules.curriculum.CurriculumElement; import org.olat.repository.RepositoryEntry; import org.olat.repository.RepositoryEntrySecurity; -import org.olat.repository.RepositoryEntryStatusEnum; import org.olat.repository.model.RepositoryEntryLifecycle; /** @@ -80,8 +79,8 @@ public class UserCourseEnvironmentImpl implements UserCourseEnvironment { public UserCourseEnvironmentImpl(IdentityEnvironment identityEnvironment, CourseEnvironment courseEnvironment) { this(identityEnvironment, courseEnvironment, null, null, null, null, null, null, null, null); - if(courseEnvironment != null) { - courseReadOnly = courseEnvironment.getCourseGroupManager().getCourseEntry().getEntryStatus() == RepositoryEntryStatusEnum.closed; + if(courseEnvironment != null && courseEnvironment.getCourseGroupManager().getCourseEntry().getEntryStatus() != null) { + courseReadOnly = courseEnvironment.getCourseGroupManager().getCourseEntry().getEntryStatus().decommissioned(); } } diff --git a/src/main/java/org/olat/ims/qti21/model/xml/AssessmentHtmlBuilder.java b/src/main/java/org/olat/ims/qti21/model/xml/AssessmentHtmlBuilder.java index 5b5c9caff705a1cef7f90173b6b58174fd8f86bf..66337fd5ad624df0390d50fc79892f9892d7fb54 100644 --- a/src/main/java/org/olat/ims/qti21/model/xml/AssessmentHtmlBuilder.java +++ b/src/main/java/org/olat/ims/qti21/model/xml/AssessmentHtmlBuilder.java @@ -342,6 +342,7 @@ public class AssessmentHtmlBuilder { String parameters = content.substring(start + startScript.length(), end); translateToObject(parameters); } + scriptBuffer = new StringBuilder(); video = false; } return; diff --git a/src/main/java/org/olat/modules/_spring/modulesContext.xml b/src/main/java/org/olat/modules/_spring/modulesContext.xml index 7d55dd77fc2b86d1ca97a9f076b817c75b8ffbdc..5ad479379006dcf44568aa072505a53e51e9c049 100644 --- a/src/main/java/org/olat/modules/_spring/modulesContext.xml +++ b/src/main/java/org/olat/modules/_spring/modulesContext.xml @@ -197,37 +197,6 @@ </property> </bean> - <bean id="invitationCleanupTrigger" class="org.springframework.scheduling.quartz.CronTriggerFactoryBean"> - <property name="jobDetail" ref="invitationCleanupJob.${cluster.singleton.services}" /> - <!-- adjust cron style syntax for your notification needs - "0 10 0 * *" e.g. 10 minutes after midnight - - A "Cron-Expression" is a string comprised of 6 or 7 fields separated by white space. The 6 mandatory and 1 optional fields are as follows: - Field Name Allowed Values Allowed Special Characters - Seconds 0-59 , - * / - Minutes 0-59 , - * / - Hours 0-23 , - * / - Day-of-month 1-31 , - * ? / L W C - Month 1-12 or JAN-DEC , - * / - Day-of-Week 1-7 or SUN-SAT , - * ? / L C # - Year (Optional) empty, 1970-2099 , - * / - - As of OLAT 6.3 it's best to let the cronjob run every two hours since users can now choose how often - they will get notified. The shortest interval is set to two hours. - --> - <property name="cronExpression" value="0 2 */12 * * ?" /> - <property name="startDelay" value="150000" /> - </bean> - - <bean id="invitationCleanupJob.enabled" class="org.springframework.scheduling.quartz.JobDetailFactoryBean" lazy-init="true"> - <property name="jobClass" value="org.olat.modules.portfolio.manager.InvitationCleanupJob" /> - </bean> - <!-- dummy bean --> - <bean id="invitationCleanupJob.disabled" class="org.springframework.scheduling.quartz.JobDetailFactoryBean" lazy-init="true"> - <property name="jobClass" value="org.olat.core.commons.services.scheduler.DummyJob" /> - </bean> - - <!-- vitero admin. panel --> <bean class="org.olat.core.extensions.action.GenericActionExtension" init-method="initExtensionPoints"> <property name="order" value="8228" /> diff --git a/src/main/java/org/olat/modules/bigbluebutton/ui/BigBlueButtonGuestJoinController.java b/src/main/java/org/olat/modules/bigbluebutton/ui/BigBlueButtonGuestJoinController.java index 20cb30768aaaf36853a2324b200c70891a39b449..5e18aab9a3ab3f7d80e4e2fd3c0690f0f22ef9aa 100644 --- a/src/main/java/org/olat/modules/bigbluebutton/ui/BigBlueButtonGuestJoinController.java +++ b/src/main/java/org/olat/modules/bigbluebutton/ui/BigBlueButtonGuestJoinController.java @@ -307,12 +307,21 @@ public class BigBlueButtonGuestJoinController extends FormBasicController implem allOk &= false; } + if(!joinButton.isEnabled()) { + if(!nameEl.hasError()) {// don't overwrite the validation error of name + nameEl.setErrorKey("meeting.create.intro", null); + } + allOk &= false; + } + return allOk; } @Override protected void formOK(UserRequest ureq) { - doJoin(ureq); + if(joinButton.isEnabled()) { + doJoin(ureq); + } } @Override diff --git a/src/main/java/org/olat/modules/lecture/ui/_i18n/LocalStrings_de.properties b/src/main/java/org/olat/modules/lecture/ui/_i18n/LocalStrings_de.properties index 69c22f300fa42e5fc1f3902a000c58ab7552c2e5..97850769f1fbfb88085a95baf5c9b4bf8e1405de 100644 --- a/src/main/java/org/olat/modules/lecture/ui/_i18n/LocalStrings_de.properties +++ b/src/main/java/org/olat/modules/lecture/ui/_i18n/LocalStrings_de.properties @@ -74,7 +74,7 @@ closed=Erledigt coach.absence=Absenzen coach.appeals=Rekurse coach.cockpit=Cockpit -coach.dispensation=Abmeldungen / Dispensen +coach.dispensation=Abmeldungen / Dispense coach.lectures=Lektionen coach.lectures.search=Benutzersuche coach.report=Report @@ -122,7 +122,7 @@ delete.lectures.title=Lektionenblock l\u00F6schen delete.title=Begr\u00FCndung l\u00F6schen detailled.list=Detaillierte Liste details=Details -dispensations.title=Abmeldungen und Dispensen +dispensations.title=Abmeldungen und Dispense done=Erledigt edit.absence.category=Absenzenbegr\u00FCndung bearbeiten edit.assessment.mode=Pr\u00FCfung editieren @@ -132,7 +132,7 @@ edit.type.absence=Absenz editieren edit.type.dispensation=Dispens editieren edit.type.notice.absence=Abmeldung editieren effective.lectures=Effektive Lektionen -empty.absences.list=Es wurden kein Absenzen/Dispensen gefunden, welche den Kriterien entsprechen. +empty.absences.list=Es wurden kein Absenzen/Dispense gefunden, welche den Kriterien entsprechen. empty.appeals.list=Es wurden kein Rekurs gefunden, welcher den Kriterien entspricht. empty.lectures.list=Die Tabelle ist leer empty.repository.entry.lectures=Sie mussten in diesem Kurs noch keine Lektionen besuchen. @@ -212,7 +212,7 @@ lecture.groups=Kurs / Gruppe / Curriculum lecture.location=Ort lecture.mastercoach.can.authorize.absence=Klassenlehrer d\u00FCrfen Absenzen entschuldigen lecture.mastercoach.can.authorize.appeal=Klassenlehrer d\u00FCrfen Rekurse bewiligen -lecture.mastercoach.can.record.notice=Klassenlehrer d\u00FCrfen Absenzen/Abmeldung/Dispensen erfassen +lecture.mastercoach.can.record.notice=Klassenlehrer d\u00FCrfen Absenzen/Abmeldung/Dispens erfassen lecture.mastercoach.can.see.absence=Klassenlehrer d\u00FCrfen Absenzen einsehen lecture.mastercoach.can.see.appeal=Klassenlehrer d\u00FCrfen Rekurse einsehen lecture.owner.can.view.all.curriculum.elements=Kursbesitzer d\u00FCrfen alle Kurse in Curriculum Elementen sehen @@ -523,7 +523,7 @@ unauthorized.filter.label=Anzeige unoverride.lecture=\u00DCbergehen anhalten upto=bis {0} user.overview.appeals=Rekurse -user.overview.dispensation=Dispensen +user.overview.dispensation=Dispense user.overview.lectures=Lektionen und Absenzen user.profil=Benutzerprofil warning.choose.at.least.one.appeal=Sie m\u00FCssen mindestens einen Rekurs w\u00E4hlen. diff --git a/src/main/java/org/olat/modules/portfolio/manager/BinderDAO.java b/src/main/java/org/olat/modules/portfolio/manager/BinderDAO.java index faa4cc5c5b256667b6d47d1a52b666840f5e1266..37a4adf45ef1f3a65bf3732de8969e37dc79c903 100644 --- a/src/main/java/org/olat/modules/portfolio/manager/BinderDAO.java +++ b/src/main/java/org/olat/modules/portfolio/manager/BinderDAO.java @@ -84,6 +84,8 @@ public class BinderDAO { @Autowired private GroupDAO groupDao; @Autowired + private InvitationDAO invitationDao; + @Autowired private AssignmentDAO assignmentDao; @Autowired private PageUserInfosDAO pageUserInfosDao; @@ -459,8 +461,8 @@ public class BinderDAO { binder.getSections().clear(); - Group baseGroup = binder.getBaseGroup(); + invitationDao.deleteInvitation(baseGroup); rows += groupDao.removeMemberships(baseGroup); dbInstance.getCurrentEntityManager().remove(binder); dbInstance.getCurrentEntityManager().remove(baseGroup); @@ -495,22 +497,20 @@ public class BinderDAO { public int detachBinderFromRepositoryEntry(RepositoryEntry entry) { //remove reference to the course and the course node String sb = "update pfbinder binder set binder.entry=null,binder.subIdent=null where binder.entry.key=:entryKey"; - int rows = dbInstance.getCurrentEntityManager() + return dbInstance.getCurrentEntityManager() .createQuery(sb) .setParameter("entryKey", entry.getKey()) .executeUpdate(); - return rows; } public int detachBinderFromRepositoryEntry(RepositoryEntry entry, PortfolioCourseNode node) { //remove reference to the course and the course node String sb = "update pfbinder binder set binder.entry=null,binder.subIdent=null where binder.entry.key=:entryKey and binder.subIdent=:nodeIdent"; - int rows = dbInstance.getCurrentEntityManager() + return dbInstance.getCurrentEntityManager() .createQuery(sb) .setParameter("entryKey", entry.getKey()) .setParameter("nodeIdent", node.getIdent()) .executeUpdate(); - return rows; } /** diff --git a/src/main/java/org/olat/modules/portfolio/manager/InvitationCleanupJob.java b/src/main/java/org/olat/modules/portfolio/manager/InvitationCleanupJob.java deleted file mode 100644 index ed3b1cfb6de869edb12e576650ad2a4b54cea2a0..0000000000000000000000000000000000000000 --- a/src/main/java/org/olat/modules/portfolio/manager/InvitationCleanupJob.java +++ /dev/null @@ -1,54 +0,0 @@ -/** - * <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.modules.portfolio.manager; - -import org.apache.logging.log4j.Logger; -import org.olat.core.CoreSpringFactory; -import org.olat.core.commons.services.scheduler.JobWithDB; -import org.olat.core.logging.Tracing; -import org.quartz.DisallowConcurrentExecution; -import org.quartz.JobExecutionContext; - -/** - * Description:<br> - * A job to remove invitation without policies. - * - * <P> - * Initial Date: 11 nov. 2010 <br> - * @author srosse - */ -@DisallowConcurrentExecution -public class InvitationCleanupJob extends JobWithDB { - - private static final Logger log = Tracing.createLoggerFor(InvitationCleanupJob.class); - - @Override - public void executeWithDB(JobExecutionContext context) { - try { - log.info("Starting invitation clean up job"); - InvitationDAO invitationDao = CoreSpringFactory.getImpl(InvitationDAO.class); - invitationDao.cleanUpInvitations(); - } catch (Exception e) { - // ups, something went completely wrong! We log this but continue next time - log.error("Error while cleaning up invitation", e); - } - // db closed by JobWithDB class - } -} diff --git a/src/main/java/org/olat/modules/portfolio/manager/InvitationDAO.java b/src/main/java/org/olat/modules/portfolio/manager/InvitationDAO.java index b7a3df765e71e29fdfbe29bd0a4332e7decdf4bd..cc716f4c053f87f36ae9bbfe080398599f850ad8 100644 --- a/src/main/java/org/olat/modules/portfolio/manager/InvitationDAO.java +++ b/src/main/java/org/olat/modules/portfolio/manager/InvitationDAO.java @@ -19,7 +19,6 @@ */ package org.olat.modules.portfolio.manager; -import java.util.Calendar; import java.util.Date; import java.util.List; import java.util.Locale; @@ -35,13 +34,11 @@ import org.olat.basesecurity.Invitation; import org.olat.basesecurity.OrganisationRoles; import org.olat.basesecurity.OrganisationService; import org.olat.basesecurity.manager.GroupDAO; -import org.olat.basesecurity.manager.OrganisationDAO; import org.olat.core.commons.persistence.DB; import org.olat.core.id.Identity; import org.olat.core.id.User; import org.olat.core.id.UserConstants; import org.olat.modules.portfolio.model.InvitationImpl; -import org.olat.user.UserLifecycleManager; import org.olat.user.UserManager; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; @@ -69,11 +66,7 @@ public class InvitationDAO { @Autowired private BaseSecurity securityManager; @Autowired - private OrganisationDAO organisationDao; - @Autowired private OrganisationService organisationService; - @Autowired - private UserLifecycleManager userLifecycleManager; public Invitation createInvitation() { InvitationImpl invitation = new InvitationImpl(); @@ -164,10 +157,10 @@ public class InvitationDAO { StringBuilder sb = new StringBuilder(); sb.append("select invitation.key from binvitation as invitation") .append(" inner join invitation.baseGroup as baseGroup") - .append(" where invitation.token=:token ") - .append(" and exists(select binder from pfbinder as binder") - .append(" where binder.baseGroup.key=baseGroup.key") - .append(" )"); + .append(" where invitation.token=:token") + .append(" and exists(select binder from pfbinder as binder") + .append(" where binder.baseGroup.key=baseGroup.key") + .append(" )"); TypedQuery<Long> query = dbInstance.getCurrentEntityManager() .createQuery(sb.toString(), Long.class) @@ -177,7 +170,7 @@ public class InvitationDAO { .setFirstResult(0) .setMaxResults(1) .getResultList(); - return keys == null || keys.isEmpty() || keys.get(0) == null ? false : keys.get(0).longValue() > 0; + return keys != null && !keys.isEmpty() && keys.get(0) != null && keys.get(0).longValue() > 0; } /** @@ -198,25 +191,6 @@ public class InvitationDAO { return invitations.isEmpty() ? null : invitations.get(0); } - /** - * Find an invitation by its security group - * @param secGroup - * @return The invitation or null if not found - */ - public Invitation findInvitation(Group group) { - StringBuilder sb = new StringBuilder(); - sb.append("select invitation from binvitation as invitation ") - .append(" inner join fetch invitation.baseGroup bGroup") - .append(" where bGroup=:group"); - - List<Invitation> invitations = dbInstance.getCurrentEntityManager() - .createQuery(sb.toString(), Invitation.class) - .setParameter("group", group) - .getResultList(); - if(invitations.isEmpty()) return null; - return invitations.get(0); - } - /** * * Warning! The E-mail is used in this case as a foreign key to match @@ -295,7 +269,7 @@ public class InvitationDAO { .createQuery(sb.toString(), Number.class) .setParameter("identityKey", identity.getKey()) .getSingleResult(); - return invitations == null ? false : invitations.intValue() > 0; + return invitations != null && invitations.intValue() > 0; } /** @@ -310,46 +284,13 @@ public class InvitationDAO { dbInstance.getCurrentEntityManager().remove(refInvitation); } - /** - * Clean up old invitation and set to deleted temporary users - */ - public void cleanUpInvitations() { - Calendar cal = Calendar.getInstance(); - cal.setTime(new Date()); - cal.add(Calendar.HOUR, -6); - Date dateLimit = cal.getTime(); - - StringBuilder sb = new StringBuilder(512); - sb.append("select invitation from ").append(InvitationImpl.class.getName()).append(" as invitation ") - .append(" inner join invitation.baseGroup baseGroup ") - .append(" where invitation.creationDate<:dateLimit"); - - List<Invitation> oldInvitations = dbInstance.getCurrentEntityManager() - .createQuery(sb.toString(), Invitation.class) - .setParameter("dateLimit", dateLimit) - .getResultList(); + public int deleteInvitation(Group group) { + if(group == null || group.getKey() == null) return 0; - if(oldInvitations.isEmpty()) { - return; - } - - for(Invitation invitation:oldInvitations) { - List<Identity> identities = groupDao.getMembers(invitation.getBaseGroup(), GroupRoles.invitee.name()); - //normally only one identity - for(Identity identity:identities) { - if(identity.getStatus().equals(Identity.STATUS_DELETED)) { - //already deleted - } else if(organisationDao.hasAnyRole(identity, OrganisationRoles.invitee.name())) { - //out of scope - } else { - //delete user - userLifecycleManager.deleteIdentity(identity, null); - } - } - Invitation invitationRef = dbInstance.getCurrentEntityManager() - .getReference(InvitationImpl.class, invitation.getKey()); - dbInstance.getCurrentEntityManager().remove(invitationRef); - dbInstance.commit(); - } + String delete = "delete from binvitation as invitation where invitation.baseGroup.key=:groupKey"; + return dbInstance.getCurrentEntityManager() + .createQuery(delete) + .setParameter("groupKey", group.getKey()) + .executeUpdate(); } } diff --git a/src/main/java/org/olat/modules/portfolio/ui/BinderListController.java b/src/main/java/org/olat/modules/portfolio/ui/BinderListController.java index 51bcc10c34670101b8e1cb7de8b382b5e10e68bc..96020a285a3b7c947ad82d726b4ceb657aaf74cd 100644 --- a/src/main/java/org/olat/modules/portfolio/ui/BinderListController.java +++ b/src/main/java/org/olat/modules/portfolio/ui/BinderListController.java @@ -26,6 +26,7 @@ import java.util.Map; import java.util.Set; import java.util.stream.Collectors; +import org.olat.core.commons.persistence.DB; import org.olat.core.commons.persistence.DBFactory; import org.olat.core.gui.UserRequest; import org.olat.core.gui.components.Component; @@ -133,6 +134,8 @@ public class BinderListController extends FormBasicController private ConfirmMoveBinderToTrashController moveBinderToTrashCtrl; private DialogBoxController confirmRestoreBinderCtrl; + @Autowired + private DB dbInstance; @Autowired private PortfolioV2Module portfolioModule; @Autowired @@ -736,7 +739,8 @@ public class BinderListController extends FormBasicController private void doMoveBinderToTrash(BinderRow row) { Binder binder = portfolioService.getBinderByKey(row.getKey()); binder.setBinderStatus(BinderStatus.deleted); - binder = portfolioService.updateBinder(binder); + portfolioService.updateBinder(binder); + dbInstance.commit(); showInfo("delete.binder.success"); } @@ -756,6 +760,7 @@ public class BinderListController extends FormBasicController private void doDeleteBinder(BinderRef binder) { portfolioService.deleteBinder(binder); + dbInstance.commit(); showInfo("delete.binder.success"); } @@ -769,7 +774,7 @@ public class BinderListController extends FormBasicController private void doRestore(BinderRef row) { Binder binder = portfolioService.getBinderByKey(row.getKey()); binder.setBinderStatus(BinderStatus.open); - binder = portfolioService.updateBinder(binder); + portfolioService.updateBinder(binder); showInfo("restore.binder.success"); } diff --git a/src/main/java/org/olat/modules/portfolio/ui/BinderMetadataEditController.java b/src/main/java/org/olat/modules/portfolio/ui/BinderMetadataEditController.java index b83aa4cf10b441fe3604e0da6514aeadfc8348bd..aee71ac92ed76d38313ea1caadd5e7087113e4ea 100644 --- a/src/main/java/org/olat/modules/portfolio/ui/BinderMetadataEditController.java +++ b/src/main/java/org/olat/modules/portfolio/ui/BinderMetadataEditController.java @@ -26,6 +26,7 @@ import java.util.List; import java.util.Map; import java.util.Set; +import org.olat.core.commons.persistence.DB; import org.olat.core.gui.UserRequest; import org.olat.core.gui.components.form.flexible.FormItem; import org.olat.core.gui.components.form.flexible.FormItemContainer; @@ -79,6 +80,8 @@ public class BinderMetadataEditController extends FormBasicController { private Map<String,String> categories = new HashMap<>(); private Map<String,Category> categoriesMap = new HashMap<>(); + @Autowired + private DB dbInstance; @Autowired private UserManager userManager; @Autowired @@ -229,6 +232,7 @@ public class BinderMetadataEditController extends FormBasicController { List<String> updatedCategories = categoriesEl.getValueList(); portfolioService.updateCategories(binder, updatedCategories); + dbInstance.commit(); fireEvent(ureq, Event.DONE_EVENT); } diff --git a/src/main/java/org/olat/modules/portfolio/ui/DeletedBinderController.java b/src/main/java/org/olat/modules/portfolio/ui/DeletedBinderController.java index 4840ab4fe5096a6a1c86b6d0ba83b321d6eba772..181963144030cdf043caa737aace66b13a47d8a8 100644 --- a/src/main/java/org/olat/modules/portfolio/ui/DeletedBinderController.java +++ b/src/main/java/org/olat/modules/portfolio/ui/DeletedBinderController.java @@ -22,6 +22,7 @@ package org.olat.modules.portfolio.ui; import java.util.ArrayList; import java.util.List; +import org.olat.core.commons.persistence.DB; import org.olat.core.gui.UserRequest; import org.olat.core.gui.components.form.flexible.FormItem; import org.olat.core.gui.components.form.flexible.FormItemContainer; @@ -52,6 +53,7 @@ import org.olat.modules.portfolio.model.BinderStatistics; import org.olat.modules.portfolio.ui.event.DeleteBinderEvent; import org.olat.modules.portfolio.ui.event.RestoreBinderEvent; import org.olat.modules.portfolio.ui.model.BinderRow; +import org.springframework.beans.factory.annotation.Autowired; /** * @@ -66,6 +68,9 @@ public class DeletedBinderController extends BinderListController { private DialogBoxController confirmRestoreBinderCtrl; private ConfirmDeleteBinderController deleteBinderCtrl; + @Autowired + private DB dbInstance; + public DeletedBinderController(UserRequest ureq, WindowControl wControl, TooledStackedPanel stackPanel) { super(ureq, wControl, stackPanel); } @@ -225,7 +230,8 @@ public class DeletedBinderController extends BinderListController { private void doRestore(BinderRow row) { Binder binder = portfolioService.getBinderByKey(row.getKey()); binder.setBinderStatus(BinderStatus.open); - binder = portfolioService.updateBinder(binder); + portfolioService.updateBinder(binder); + dbInstance.commit(); showInfo("restore.binder.success"); } } \ No newline at end of file diff --git a/src/main/java/org/olat/modules/portfolio/ui/SectionEditController.java b/src/main/java/org/olat/modules/portfolio/ui/SectionEditController.java index 49e460f3a7ae142179f1ad4d6314278bf0b24bda..cc08533beedb71584a6ab8bc385db5be96195768 100644 --- a/src/main/java/org/olat/modules/portfolio/ui/SectionEditController.java +++ b/src/main/java/org/olat/modules/portfolio/ui/SectionEditController.java @@ -31,6 +31,7 @@ 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.modules.portfolio.BinderRef; import org.olat.modules.portfolio.BinderSecurityCallback; import org.olat.modules.portfolio.PortfolioService; @@ -95,6 +96,9 @@ public class SectionEditController extends FormBasicController { titleEl = uifactory.addTextElement("title", "title", 255, title, formLayout); titleEl.setElementCssClass("o_sel_pf_edit_section_title"); titleEl.setMandatory(true); + if(!StringHelper.containsNonWhitespace(title)) { + titleEl.setFocus(true); + } String description = section == null ? null : section.getDescription(); descriptionEl = uifactory.addRichTextElementForStringDataMinimalistic("summary", "page.summary", description, 8, 60, formLayout, getWindowControl()); diff --git a/src/main/java/org/olat/modules/portfolio/ui/TableOfContentController.java b/src/main/java/org/olat/modules/portfolio/ui/TableOfContentController.java index debe917bf60f238a486f8775917b8d4c25723e77..daf0f4dbfc1b26340f11255dd1cd7c13ff92f8d3 100644 --- a/src/main/java/org/olat/modules/portfolio/ui/TableOfContentController.java +++ b/src/main/java/org/olat/modules/portfolio/ui/TableOfContentController.java @@ -27,6 +27,7 @@ import java.util.Map; import org.olat.NewControllerFactory; import org.olat.core.commons.fullWebApp.LayoutMain3ColsController; import org.olat.core.commons.fullWebApp.popup.BaseFullWebappPopupLayoutFactory; +import org.olat.core.commons.persistence.DB; import org.olat.core.commons.services.commentAndRating.CommentAndRatingDefaultSecurityCallback; import org.olat.core.commons.services.commentAndRating.CommentAndRatingSecurityCallback; import org.olat.core.commons.services.commentAndRating.ReadOnlyCommentsSecurityCallback; @@ -151,6 +152,8 @@ public class TableOfContentController extends BasicController implements TooledC private final BinderConfiguration config; private final BinderSecurityCallback secCallback; + @Autowired + private DB dbInstance; @Autowired private PdfModule pdfModule; @Autowired @@ -955,8 +958,10 @@ public class TableOfContentController extends BasicController implements TooledC } private void doMoveBinderToTrash() { + binder = portfolioService.getBinderByKey(binder.getKey()); binder.setBinderStatus(BinderStatus.deleted); binder = portfolioService.updateBinder(binder); + dbInstance.commit(); showInfo("delete.binder.success"); } @@ -967,8 +972,10 @@ public class TableOfContentController extends BasicController implements TooledC } private void doRestore() { + binder = portfolioService.getBinderByKey(binder.getKey()); binder.setBinderStatus(BinderStatus.open); binder = portfolioService.updateBinder(binder); + dbInstance.commit(); showInfo("restore.binder.success"); } diff --git a/src/main/java/org/olat/modules/reminder/ui/_i18n/LocalStrings_de.properties b/src/main/java/org/olat/modules/reminder/ui/_i18n/LocalStrings_de.properties index 7d94e86f2699b2a933179d662ae8ee45425f5f26..fe14058b803c070a27aa592aa2762e3173667c06 100644 --- a/src/main/java/org/olat/modules/reminder/ui/_i18n/LocalStrings_de.properties +++ b/src/main/java/org/olat/modules/reminder/ui/_i18n/LocalStrings_de.properties @@ -23,7 +23,7 @@ rule.after.date=Nach Datum rule.before.date=Bis Datum rule.course.enrollment.date=Einschreibedatum rule.course.role=Kursrolle -rule.group.member=Gruppenteilnehmer +rule.group.member=Gruppenmitglieder rule.initial.course.launch.date=Erster Kursbesuch rule.lifecycle.validfrom=Beginndatum von Kurs-Durchf\u00FChrungzeitraum rule.lifecycle.validto=Enddatum von Kurs-Durchf\u00FChrungzeitraum diff --git a/src/main/java/org/olat/modules/reminder/ui/_i18n/LocalStrings_fr.properties b/src/main/java/org/olat/modules/reminder/ui/_i18n/LocalStrings_fr.properties index 043b930d02a6216b63148a9f5bb1c902336cbee9..fcb2b6f661ee279a0d9aa2be1e51a3f1cdcb023d 100644 --- a/src/main/java/org/olat/modules/reminder/ui/_i18n/LocalStrings_fr.properties +++ b/src/main/java/org/olat/modules/reminder/ui/_i18n/LocalStrings_fr.properties @@ -23,7 +23,7 @@ rule.after.date=Fonction de la date rule.before.date=Jusqu'\u00E0 rule.course.enrollment.date=Date d'inscription rule.course.role=R\u00F4le au sein du cours -rule.group.member=Participant \u00E0 un groupe +rule.group.member=Membre \u00E0 un groupe rule.initial.course.launch.date=Premi\u00E8re visite du cours rule.lifecycle.validfrom=Date de comment de la p\u00E9riode du cours rule.lifecycle.validto=Date de fin de la p\u00E9riode de mise en \u0153uvre diff --git a/src/main/java/org/olat/repository/RepositoryManager.java b/src/main/java/org/olat/repository/RepositoryManager.java index c363cc7e23f39a8b4e59653017b73aeaee836542..0fcc5567e08b1413f4343a5a0f7832044909c365 100644 --- a/src/main/java/org/olat/repository/RepositoryManager.java +++ b/src/main/java/org/olat/repository/RepositoryManager.java @@ -69,7 +69,6 @@ import org.olat.core.util.coordinate.CoordinatorManager; import org.olat.core.util.event.EventBus; import org.olat.core.util.event.MultiUserEvent; import org.olat.core.util.mail.MailPackage; -import org.olat.core.util.resource.OresHelper; import org.olat.core.util.vfs.LocalFolderImpl; import org.olat.core.util.vfs.VFSContainer; import org.olat.core.util.vfs.VFSItem; @@ -641,7 +640,7 @@ public class RepositoryManager { } } - boolean readOnly = re.getEntryStatus() == RepositoryEntryStatusEnum.closed; + boolean readOnly = re.getEntryStatus().decommissioned(); return new RepositoryEntrySecurityImpl(isEntryAdmin, isOwner, isCourseParticipant, isCourseCoach, @@ -1397,11 +1396,10 @@ public class RepositoryManager { sendDeferredEvents(deferredEvents, re); } - private void sendDeferredEvents(List<? extends MultiUserEvent> events, OLATResourceable ores) { + private void sendDeferredEvents(List<? extends MultiUserEvent> events, RepositoryEntry ores) { EventBus eventBus = CoordinatorManager.getInstance().getCoordinator().getEventBus(); for(MultiUserEvent event:events) { eventBus.fireEventToListenersOf(event, ores); - eventBus.fireEventToListenersOf(event, OresHelper.lookupType(RepositoryEntry.class)); } } @@ -1419,8 +1417,8 @@ public class RepositoryManager { ThreadLocalUserActivityLogger.setStickyActionType(actionType); } - log.info(Tracing.M_AUDIT, "Identity(.key):" + ureqIdentity.getKey() + " removed identity '" + identity.getKey() - + "' as owner from repositoryentry with key " + re.getKey()); + log.info(Tracing.M_AUDIT, "Identity(.key):{} removed identity '{}' as owner from repositoryentry with key {}", + ureqIdentity.getKey(), identity.getKey(), re.getKey()); } } @@ -1609,8 +1607,8 @@ public class RepositoryManager { } finally { ThreadLocalUserActivityLogger.setStickyActionType(actionType); } - log.info(Tracing.M_AUDIT, "Identity(.key):" + ureqIdentity.getKey() + " added identity '" + identity.getKey() - + "' to repositoryentry with key " + re.getKey()); + log.info(Tracing.M_AUDIT, "Identity(.key):{} added identity '{}' to repositoryentry with key {}", + ureqIdentity.getKey(), identity.getKey(), re.getKey()); } /** @@ -2082,7 +2080,6 @@ public class RepositoryManager { if(changes.getRepoParticipant() != null) { if(changes.getRepoParticipant().booleanValue()) { addParticipants(ureqIdentity, ureqRoles, new IdentitiesAddEvent(changes.getMember()), re, mailing); - deferredEvents.add(RepositoryEntryMembershipModifiedEvent.roleParticipantAdded(changes.getMember(), re)); } else { removeParticipant(ureqIdentity, changes.getMember(), re, mailing, true); deferredEvents.add(RepositoryEntryMembershipModifiedEvent.removed(changes.getMember(), re)); diff --git a/src/main/java/org/olat/repository/model/SingleRoleRepositoryEntrySecurity.java b/src/main/java/org/olat/repository/model/SingleRoleRepositoryEntrySecurity.java index 991fce053e27db6faeb165964483fa889c09bae4..3b78d27beba190d9c347f13fc9bdbc0728d60d78 100644 --- a/src/main/java/org/olat/repository/model/SingleRoleRepositoryEntrySecurity.java +++ b/src/main/java/org/olat/repository/model/SingleRoleRepositoryEntrySecurity.java @@ -58,7 +58,7 @@ public class SingleRoleRepositoryEntrySecurity implements RepositoryEntrySecurit return iconCssClass; } - }; + } private Role currentRole; private RepositoryEntrySecurity wrappedSecurity; diff --git a/src/main/resources/serviceconfig/olat.properties b/src/main/resources/serviceconfig/olat.properties index deead65890da4f5bd9df16c9655e2e8345b44004..4088f089a7d74a425afa4b1a8a325dc4d457760f 100644 --- a/src/main/resources/serviceconfig/olat.properties +++ b/src/main/resources/serviceconfig/olat.properties @@ -1374,8 +1374,8 @@ ldap.learningResourceManagerRoleValue= # Build properties ##### application.name=OpenOlat -build.version=15.3.8 -build.identifier=openolat1538-dev +build.version=15.3.9 +build.identifier=openolat1539-dev build.repo.revision=local-devel ##### diff --git a/src/main/webapp/static/js/openolat/iframe.js b/src/main/webapp/static/js/openolat/iframe.js index a146933fb726a8b5ac061989e41fea4063026822..bfd7431ce048435add48042d42bc88e3314a1b25 100644 --- a/src/main/webapp/static/js/openolat/iframe.js +++ b/src/main/webapp/static/js/openolat/iframe.js @@ -205,23 +205,7 @@ function b_changeLinkTargets() { var anchor = anchors[i]; if (anchor.getAttribute('href')) { var target = anchor.getAttribute('target'); - var href = anchor.getAttribute("href"); - if ((href.indexOf("/url/") != -1 || href.indexOf("/auth/") != -1) && - ( - href.indexOf("/repo/go?rid=") != -1 - || href.indexOf("/RepositoryEntry/") != -1 - || href.indexOf("/BusinessGroup/") != -1 - || href.indexOf("Site/") != -1 - || href.indexOf("/CatalogEntry/") != -1 - || href.indexOf("/Portal/") != -1 - || href.indexOf("/CatalogAdmin/") != -1 - || href.indexOf("/GMCMenuTree/") != -1 - ) - ) { - // absolute links to repository entries have to by opened in the parent frame - // /auth/repo/ is legacy format, /url/RepositoryEntry/ is new format - anchor.target = "_parent"; - } else if (target != null && target != undefined && (target == '_top' || target == '_parent')) { + if (target != null && target != undefined && (target == '_top' || target == '_parent')) { // fix broken legacy links that try to open content in top window // iframe content must always stay within iframe var mainwindow = b_getMainWindow(window.parent); diff --git a/src/test/java/org/olat/core/commons/services/doceditor/onlyoffice/manager/OnlyOfficeServiceImplTest.java b/src/test/java/org/olat/core/commons/services/doceditor/onlyoffice/manager/OnlyOfficeServiceImplTest.java index 6784dbb2b78b08266fe24f27f0ded8f619778f8c..85cf1c04be820010bf038672195dd31922330a45 100644 --- a/src/test/java/org/olat/core/commons/services/doceditor/onlyoffice/manager/OnlyOfficeServiceImplTest.java +++ b/src/test/java/org/olat/core/commons/services/doceditor/onlyoffice/manager/OnlyOfficeServiceImplTest.java @@ -81,12 +81,24 @@ public class OnlyOfficeServiceImplTest { } @Test - public void shouldNotAllowEditIfAllLicensesInUse() { + public void shouldAllowEditIfAlmostAllLicensesInUse() { + // Because the access is created before the license check is done, + // the access is demanding for the last license. when(onlyOfficeModuleMock.getLicenseEdit()).thenReturn(10); when(documentEditorServiceMock.getAccessCount(any(), any())).thenReturn(Long.valueOf(10)); boolean editLicenseAvailable = sut.isEditLicenseAvailable(); + assertThat(editLicenseAvailable).isTrue(); + } + + @Test + public void shouldNotAllowEditIfAllLicensesInUse() { + when(onlyOfficeModuleMock.getLicenseEdit()).thenReturn(10); + when(documentEditorServiceMock.getAccessCount(any(), any())).thenReturn(Long.valueOf(11)); + + boolean editLicenseAvailable = sut.isEditLicenseAvailable(); + assertThat(editLicenseAvailable).isFalse(); } diff --git a/src/test/java/org/olat/modules/portfolio/manager/InvitationDAOTest.java b/src/test/java/org/olat/modules/portfolio/manager/InvitationDAOTest.java index af3e5d241080675b0d676fe008352637eaa99f89..1a6c556e06a46c6c3a6531d9b5077a8bdf888801 100644 --- a/src/test/java/org/olat/modules/portfolio/manager/InvitationDAOTest.java +++ b/src/test/java/org/olat/modules/portfolio/manager/InvitationDAOTest.java @@ -30,6 +30,7 @@ import org.olat.basesecurity.Invitation; import org.olat.basesecurity.manager.GroupDAO; import org.olat.core.commons.persistence.DB; import org.olat.core.id.Identity; +import org.olat.test.JunitTestHelper; import org.olat.test.OlatTestCase; import org.springframework.beans.factory.annotation.Autowired; @@ -63,21 +64,6 @@ public class InvitationDAOTest extends OlatTestCase { Assert.assertNotNull(invitation.getToken()); } - @Test - public void findInvitation_group() { - Invitation invitation = invitationDao.createAndPersistInvitation(); - Group baseGroup = invitation.getBaseGroup(); - Assert.assertNotNull(invitation); - dbInstance.commitAndCloseSession(); - - Invitation reloadedInvitation = invitationDao.findInvitation(baseGroup); - Assert.assertNotNull(reloadedInvitation); - Assert.assertNotNull(reloadedInvitation.getKey()); - Assert.assertEquals(baseGroup, reloadedInvitation.getBaseGroup()); - Assert.assertEquals(invitation, reloadedInvitation); - Assert.assertEquals(invitation.getToken(), reloadedInvitation.getToken()); - } - @Test public void findInvitation_token() { Invitation invitation = invitationDao.createAndPersistInvitation(); @@ -93,12 +79,31 @@ public class InvitationDAOTest extends OlatTestCase { } @Test - public void hasInvitationPolicies_testHQL() { + public void hasInvitationTestHQL() { String token = UUID.randomUUID().toString(); boolean hasInvitation = invitationDao.hasInvitations(token); Assert.assertFalse(hasInvitation); } + @Test + public void isInvitee() { + Invitation invitation = invitationDao.createInvitation(); + String uuid = UUID.randomUUID().toString().replace("-", ""); + invitation.setFirstName("Fiona"); + invitation.setLastName("Laurence".concat(uuid)); + invitation.setMail(uuid.concat("@frentix.com")); + + Group group = groupDao.createGroup(); + Identity id2 = invitationDao.loadOrCreateIdentityAndPersistInvitation(invitation, group, Locale.ENGLISH); + Identity id1 = JunitTestHelper.createAndPersistIdentityAsRndUser("Invitee-2"); + dbInstance.commitAndCloseSession(); + + boolean invitee = invitationDao.isInvitee(id2); + Assert.assertTrue(invitee); + boolean notInvitee = invitationDao.isInvitee(id1); + Assert.assertFalse(notInvitee); + } + @Test public void createAndUpdateInvitation() { Invitation invitation = invitationDao.createAndPersistInvitation(); @@ -174,12 +179,16 @@ public class InvitationDAOTest extends OlatTestCase { Assert.assertTrue(numOfInvitations > 0l); } - /** - * Only check if the query is valid. - */ @Test - public void cleanUpInvitations() { - invitationDao.cleanUpInvitations(); + public void deleteInvitationByGroup() { + Invitation invitation = invitationDao.createAndPersistInvitation(); + dbInstance.commit(); + Assert.assertNotNull(invitation); + + invitationDao.deleteInvitation(invitation.getBaseGroup()); + dbInstance.commit(); + + Invitation deletedInvitation = invitationDao.findInvitation(invitation.getToken()); + Assert.assertNull(deletedInvitation); } - } diff --git a/src/test/java/org/olat/selenium/AssessmentTest.java b/src/test/java/org/olat/selenium/AssessmentTest.java index a927df45d81601f9b5063c66129002f2d038c17b..454f083c8fb27a67a4fdbcfc3577d93409291ed8 100644 --- a/src/test/java/org/olat/selenium/AssessmentTest.java +++ b/src/test/java/org/olat/selenium/AssessmentTest.java @@ -597,9 +597,8 @@ public class AssessmentTest extends Deployments { .stop(assessmentName) .confirmStop(); - By continueBy = By.className("o_sel_assessment_continue"); - OOGraphene.waitElementSlowly(continueBy, 20, ryomouBrowser); - OOGraphene.waitElementSlowly(continueBy, 20, kanuBrowser); + kanuAssessment.waitBackToOpenOlat(); + ryomouAssessment.waitBackToOpenOlat(); kanuAssessment.backToOpenOLAT(); ryomouAssessment.backToOpenOLAT(); @@ -1689,7 +1688,7 @@ public class AssessmentTest extends Deployments { .clickToolbarBack(); coursePage .clickTree() - .selectWithTitle(gtaNodeTitle); + .assertWithTitleSelected(gtaNodeTitle); //Participant log in LoginPage ryomouLoginPage = LoginPage.load(ryomouBrowser, deploymentUrl); @@ -1707,7 +1706,7 @@ public class AssessmentTest extends Deployments { CoursePageFragment ryomouTestCourse = new CoursePageFragment(ryomouBrowser); ryomouTestCourse .clickTree() - .selectWithTitle(gtaNodeTitle); + .assertWithTitleSelected(gtaNodeTitle); OOGraphene.waitAndCloseBlueMessageWindow(ryomouBrowser); GroupTaskPage ryomouTask = new GroupTaskPage(ryomouBrowser); @@ -1728,7 +1727,7 @@ public class AssessmentTest extends Deployments { //back to author coursePage .clickTree() - .selectWithTitle(gtaNodeTitle); + .assertWithTitleSelected(gtaNodeTitle); GroupTaskToCoachPage participantToCoach = new GroupTaskToCoachPage(browser); participantToCoach @@ -1742,7 +1741,7 @@ public class AssessmentTest extends Deployments { //participant checks she passed the task ryomouTestCourse .clickTree() - .selectWithTitle(gtaNodeTitle); + .assertWithTitleSelected(gtaNodeTitle); ryomouTask .assertPassed(); } diff --git a/src/test/java/org/olat/selenium/page/core/MenuTreePageFragment.java b/src/test/java/org/olat/selenium/page/core/MenuTreePageFragment.java index 71f7d03830f63826ee17b8f0a35b63563001a0f9..ebe0bd3a6654866627c1add7138a5431c3a76cd8 100644 --- a/src/test/java/org/olat/selenium/page/core/MenuTreePageFragment.java +++ b/src/test/java/org/olat/selenium/page/core/MenuTreePageFragment.java @@ -65,6 +65,8 @@ public class MenuTreePageFragment { OOGraphene.waitElement(linkBy, browser); browser.findElement(linkBy).click(); OOGraphene.waitBusy(browser); + By activeLinkBy = By.xpath("//div[contains(@class,'o_tree')]//li[contains(@class,'active')]/div/span[contains(@class,'o_tree_link')][contains(@class,'active')]/a[span[contains(text(),'" + title + "')]]"); + OOGraphene.waitElement(activeLinkBy, browser); return this; } diff --git a/src/test/java/org/olat/selenium/page/course/AssessmentModePage.java b/src/test/java/org/olat/selenium/page/course/AssessmentModePage.java index a75c6c045e7f0ea67efade3c3b5f66e0f214ab20..9ab464212be997a8da598235e79d4e6cd88486fa 100644 --- a/src/test/java/org/olat/selenium/page/course/AssessmentModePage.java +++ b/src/test/java/org/olat/selenium/page/course/AssessmentModePage.java @@ -164,6 +164,12 @@ public class AssessmentModePage { return this; } + public AssessmentModePage waitBackToOpenOlat() { + By continueBy = By.xpath("//div[@class='modal-content']//a[contains(@class,'o_sel_assessment_continue')]"); + OOGraphene.waitElementSlowly(continueBy, 20, browser); + return this; + } + /** * After an assessment, go back to OpenOLAT. */ diff --git a/src/test/resources/arquillian.xml b/src/test/resources/arquillian.xml index af3b32c9eea16cce433fe89879d4d4d44c4dffa5..6cd16fe3f81467614ce99471455adcc328a5457e 100644 --- a/src/test/resources/arquillian.xml +++ b/src/test/resources/arquillian.xml @@ -28,9 +28,9 @@ <property name="chromeDriverBinary">target/drone/675a673c111fdcc9678d11df0e69b334/chromedriver</property> <property name="firefoxDriverBinary">target/drone/ce03addb1fc8c24900011f90fc80f3c1/geckodriver</property> --> - <property name="firefoxDriverVersion">${webdriver.firefox.version:v0.28.0}</property> + <property name="firefoxDriverVersion">${webdriver.firefox.version:v0.29.0}</property> <property name="firefoxUserPreferences">src/test/profile/firefox/prefs.js</property> - <property name="chromeDriverVersion">${webdriver.chrome.version:87.0.4280.88}</property> + <property name="chromeDriverVersion">${webdriver.chrome.version:88.0.4324.96}</property> <property name="chromeArguments">${webdriver.chrome.arguments}</property> <property name="chromeExperimentalOption">{ "prefs":{"credentials_enable_service": false, "profile.password_manager_enabled": false }