diff --git a/src/main/java/org/olat/course/editor/CourseAccessAndProperties.java b/src/main/java/org/olat/course/editor/CourseAccessAndProperties.java index 748088e412c573a7a332ab6ca0ccc227efc16652..39f4d5c76bbb07a3f563ba7d5b0bce38a7b6baf7 100644 --- a/src/main/java/org/olat/course/editor/CourseAccessAndProperties.java +++ b/src/main/java/org/olat/course/editor/CourseAccessAndProperties.java @@ -37,6 +37,7 @@ public class CourseAccessAndProperties { private boolean canCopy; private boolean canReference; private boolean canDownload; + private Boolean confirmationEmail; private List<OfferAccess> offerAccess; private List<OfferAccess> deletedOfferAccess; @@ -127,4 +128,12 @@ public class CourseAccessAndProperties { public void setCanDownload(boolean canDownload) { this.canDownload = canDownload; } + + public Boolean getConfirmationEmail() { + return confirmationEmail; + } + + public void setConfirmationEmail(Boolean confirmationEmail) { + this.confirmationEmail = confirmationEmail; + } } \ No newline at end of file diff --git a/src/main/java/org/olat/course/editor/PublishProcess.java b/src/main/java/org/olat/course/editor/PublishProcess.java index 0b59b5c73ec586317f8e6f6853630fac2068feb1..6446b40e37c282a3c81e95273330403b32560331 100644 --- a/src/main/java/org/olat/course/editor/PublishProcess.java +++ b/src/main/java/org/olat/course/editor/PublishProcess.java @@ -80,6 +80,7 @@ import org.olat.repository.controllers.EntryChangedEvent; import org.olat.repository.controllers.EntryChangedEvent.Change; import org.olat.repository.manager.CatalogManager; import org.olat.resource.accesscontrol.ACService; +import org.olat.resource.accesscontrol.Offer; import org.olat.resource.accesscontrol.OfferAccess; import org.olat.resource.references.Reference; import org.olat.resource.references.ReferenceManager; @@ -700,7 +701,7 @@ public class PublishProcess { return publishTreeModel; } - public void changeGeneralAccess(Identity author, int access, boolean membersOnly){ + public void changeGeneralAccess(Identity author, int access, boolean membersOnly) { RepositoryManager.getInstance().setAccess(repositoryEntry, access, membersOnly); MultiUserEvent modifiedEvent = new EntryChangedEvent(repositoryEntry, author, Change.modifiedAtPublish, "publish"); CoordinatorManager.getInstance().getCoordinator().getEventBus().fireEventToListenersOf(modifiedEvent, repositoryEntry); @@ -718,6 +719,16 @@ public class PublishProcess { // 1: add new and update existing offerings ACService acService = CoreSpringFactory.getImpl(ACService.class); for (OfferAccess newLink : offerAccess) { + if(accessAndProps.getConfirmationEmail() != null) { + Offer offer = newLink.getOffer(); + boolean confirmation = accessAndProps.getConfirmationEmail().booleanValue(); + if(offer.isConfirmationEmail() != confirmation) { + offer.setConfirmationEmail(confirmation); + if(offer.getKey() != null) { + offer = acService.save(offer); + } + } + } acService.saveOfferAccess(newLink); } // 2: remove offerings not available anymore @@ -777,6 +788,7 @@ public class PublishProcess { this.skippableNodes = new ArrayList<CourseEditorTreeNode>(); } + @Override public void visit(INode node) { /* * DO NOT add or delete nodes via editorTreeModel, ..................... @@ -787,10 +799,10 @@ public class PublishProcess { // root node changed and published CourseNode clone = (CourseNode)XStreamHelper.xstreamClone(cetn.getCourseNode()); resultingCourseRun.setRootNode(clone); - editorModelModifiedNodes.add(cetn);// TODO:pb: Review Change to fic OLAT-1644 + editorModelModifiedNodes.add(cetn); return; } - if (cetn == root) { // TODO:pb: Review Change to fix OLAT-1644 + if (cetn == root) { // root node CourseNode clone = (CourseNode)XStreamHelper.xstreamClone(cetn.getCourseNode()); resultingCourseRun.setRootNode(clone); @@ -818,7 +830,6 @@ public class PublishProcess { // already published, add it as it is. Silent "re-publish" addNodeTo(resultingCourseRun, cetn); } else { - // TODO:pb:REVIEW Change to fix OLAT-1644 // changed in edit but not published => take old from existingRun addNodeTo(resultingCourseRun, existingRun.getNode(cetn.getIdent()), cetn); } @@ -908,7 +919,6 @@ public class PublishProcess { parentClone.addChild(clone); } - // TODO:pb:REVIEW Change to fix OLAT-1644 /** * @param newRunStruct * @param cetn @@ -926,19 +936,15 @@ public class PublishProcess { /** * flat list of all CourseEditorTreeNodes starting from root * - * @param root + * @param treeNode * @param rootNodeWithSubtree */ - private void collectSubTreeNodesStartingFrom(CourseEditorTreeNode root, List<CourseEditorTreeNode> rootNodeWithSubtree) { - for (int i = 0; i < root.getChildCount(); i++) { - CourseEditorTreeNode node = (CourseEditorTreeNode)root.getChildAt(i); + private void collectSubTreeNodesStartingFrom(CourseEditorTreeNode treeNode, List<CourseEditorTreeNode> rootNodeWithSubtree) { + for (int i = 0; i < treeNode.getChildCount(); i++) { + CourseEditorTreeNode node = (CourseEditorTreeNode)treeNode.getChildAt(i); rootNodeWithSubtree.add(node); collectSubTreeNodesStartingFrom(node, rootNodeWithSubtree); } } }// end nested class - - - - } diff --git a/src/main/java/org/olat/course/editor/PublishStep01AccessForm.java b/src/main/java/org/olat/course/editor/PublishStep01AccessForm.java index 5f92779af49c5e841f17edeea65cf98819bf1239..71014ca9b89b27cfb8c3bfba3ffca37950fc214d 100644 --- a/src/main/java/org/olat/course/editor/PublishStep01AccessForm.java +++ b/src/main/java/org/olat/course/editor/PublishStep01AccessForm.java @@ -28,6 +28,7 @@ import org.olat.core.gui.UserRequest; import org.olat.core.gui.components.form.flexible.FormItem; import org.olat.core.gui.components.form.flexible.FormItemContainer; import org.olat.core.gui.components.form.flexible.elements.FormLink; +import org.olat.core.gui.components.form.flexible.elements.MultipleSelectionElement; import org.olat.core.gui.components.form.flexible.elements.SelectionElement; import org.olat.core.gui.components.form.flexible.elements.SingleSelection; import org.olat.core.gui.components.form.flexible.impl.Form; @@ -82,6 +83,8 @@ public class PublishStep01AccessForm extends StepFormBasicController { RepositoryEntryAllowToLeaveOptions.never.name() }; + private static final String[] onKeys = new String[] { "on" }; + private SingleSelection leaveEl; private RepositoryEntry entry; @@ -104,7 +107,7 @@ public class PublishStep01AccessForm extends StepFormBasicController { private static final String MEMBERSONLY_KEY = "m"; private String[] publishedKeys; - + private MultipleSelectionElement confirmationEmailEl; private List<FormLink> addMethods = new ArrayList<>(); private List<OfferAccess> offerAccess = new ArrayList<>(); private List<OfferAccess> deletedOfferAccess = new ArrayList<>(); @@ -171,6 +174,11 @@ public class PublishStep01AccessForm extends StepFormBasicController { accessProperties.setOfferAccess(offerAccess); accessProperties.setDeletedOfferAccess(deletedOfferAccess); + if(confirmationEmailEl.isVisible()) { + accessProperties.setConfirmationEmail(confirmationEmailEl.isAtLeastSelected(1)); + } else { + accessProperties.setConfirmationEmail(null); + } addToRunContext("accessAndProperties", accessProperties); @@ -310,12 +318,25 @@ public class PublishStep01AccessForm extends StepFormBasicController { accessLayout.contextPut("methods", addMethods); } + String[] onValues = new String[] { "" }; + confirmationEmailEl = uifactory.addCheckboxesHorizontal("confirmation.email", accessLayout, onKeys, onValues); + confirmationEmailEl.addActionListener(FormEvent.ONCHANGE); + confirmationEmailEl.setVisible(false); + String confPage = velocity_root + "/configuration_list.html"; confControllerContainer = FormLayoutContainer.createCustomFormLayout("conf-controllers", getTranslator(), confPage); accessLayout.add(confControllerContainer); loadConfigurations(); + boolean confirmationEmail = false; + for(AccessInfo info:confControllers) { + confirmationEmail |= info.getLink().getOffer().isConfirmationEmail(); + } + if(confirmationEmail) { + confirmationEmailEl.select(onKeys[0], true); + } + confControllerContainer.contextPut("confControllers", confControllers); confControllerContainer.contextPut("emptyConfigGrantsFullAccess", Boolean.valueOf(emptyConfigGrantsFullAccess)); @@ -351,6 +372,14 @@ public class PublishStep01AccessForm extends StepFormBasicController { delLink.setIconLeftCSS("o_icon o_icon-fw o_icon_delete_item"); confControllerContainer.add(delLink.getName(), delLink); } + updateConfirmationEmail(); + } + + private void updateConfirmationEmail() { + if(confirmationEmailEl.isVisible() != !confControllers.isEmpty()) { + confirmationEmailEl.setVisible(!confControllers.isEmpty()); + accessLayout.setDirty(true); + } } public class AccessInfo { @@ -504,6 +533,12 @@ public class PublishStep01AccessForm extends StepFormBasicController { } else if(addMethods.contains(source)) { AccessMethod method = (AccessMethod)source.getUserObject(); addMethod(ureq, method); + } else if(confirmationEmailEl == source) { + for(AccessInfo info:confControllers) { + if(!offerAccess.contains(info.getLink())) { + offerAccess.add(info.getLink()); + } + } } else if (source instanceof FormLink) { FormLink button = (FormLink)source; String cmd = button.getCmd(); @@ -515,6 +550,7 @@ public class PublishStep01AccessForm extends StepFormBasicController { deletedOfferAccess.add(deleteOffer); } confControllers.remove(infos); + updateConfirmationEmail(); fireEvent(ureq, Event.CHANGED_EVENT); } else if("edit".equals(cmd)) { AccessInfo infos = (AccessInfo)source.getUserObject(); diff --git a/src/main/java/org/olat/course/editor/_content/access_configuration.html b/src/main/java/org/olat/course/editor/_content/access_configuration.html index 0047566062bd6fad59505d6ed0513823ae76a52a..e530afecc3a5027d9e48c322bb1a87186aaa6bae 100644 --- a/src/main/java/org/olat/course/editor/_content/access_configuration.html +++ b/src/main/java/org/olat/course/editor/_content/access_configuration.html @@ -12,6 +12,12 @@ #if ($off_info) <div class="o_info">$off_info</div> #end </div></div> #end + #if($r.visible("confirmation.email")) + <div class="form-group"> + <label class="control-label col-sm-3">$r.translate("confirmation.email")</label> + <div class="col-sm-9">$r.render("confirmation.email")</div> + </div> + #end <div class="form-group"> <label class="control-label col-sm-3">$r.translate("ac.methods.label") $r.render("acMethodsLabelHelp")</label> <div class="col-sm-9">$r.render("conf-controllers")</div> diff --git a/src/main/java/org/olat/group/manager/BusinessGroupMailing.java b/src/main/java/org/olat/group/manager/BusinessGroupMailing.java index 36d9c811f9fd4d78ed0e93c1e10323ad73ce5e95..4168d1e3a48f8560fb5747aeae3bc817bfd1ebbf 100644 --- a/src/main/java/org/olat/group/manager/BusinessGroupMailing.java +++ b/src/main/java/org/olat/group/manager/BusinessGroupMailing.java @@ -126,7 +126,12 @@ public class BusinessGroupMailing { MailTemplate template = mailing == null ? null : mailing.getTemplate(); if(mailing == null || mailing.getTemplate() == null) { - template = getDefaultTemplate(type, group, ureqIdentity); + //booking by myself + if(type != null && type == MailType.addParticipant && ureqIdentity != null && ureqIdentity.equals(identity)) { + template = BGMailHelper.createAddMyselfMailTemplate(group, ureqIdentity); + } else { + template = getDefaultTemplate(type, group, ureqIdentity); + } } else if(group != null && template.getContext() != null && needTemplateEnhancement(template)) { BusinessGroupService businessGroupService = CoreSpringFactory.getImpl(BusinessGroupService.class); List<RepositoryEntryShort> repoEntries = businessGroupService.findShortRepositoryEntries(Collections.singletonList(group), 0, -1); diff --git a/src/main/java/org/olat/group/ui/edit/BusinessGroupEditAccessController.java b/src/main/java/org/olat/group/ui/edit/BusinessGroupEditAccessController.java index 8c726fdf7b17349dd0d1ef8c6f17bd0dc85c9bce..2217d7905be61e614a7130e328a3a98c77810ebf 100644 --- a/src/main/java/org/olat/group/ui/edit/BusinessGroupEditAccessController.java +++ b/src/main/java/org/olat/group/ui/edit/BusinessGroupEditAccessController.java @@ -24,7 +24,6 @@ import org.olat.core.CoreSpringFactory; import org.olat.core.gui.UserRequest; import org.olat.core.gui.components.form.flexible.FormItemContainer; import org.olat.core.gui.components.form.flexible.impl.FormBasicController; -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; @@ -38,7 +37,7 @@ import org.olat.resource.accesscontrol.ui.AccessConfigurationController; /** * * Description:<br> - * Add a check box to the standard access control controller + * Wrapper for the resource's access control. * * <P> * Initial Date: 26 avr. 2011 <br> @@ -75,22 +74,11 @@ public class BusinessGroupEditAccessController extends FormBasicController { setFormTitle("accesscontrol.title"); setFormDescription("accesscontrol_group.desc"); setFormContextHelp("Group Administration#gruppensystem_buchung_ag"); + formLayout.setElementCssClass("o_block_large_bottom"); if(configController != null) { formLayout.add(configController.getInitialFormItem()); } - - if(configController != null && !managed) { - uifactory.addSpacerElement("spacer1", formLayout, false); - } - - if(!managed) { - final FormLayoutContainer buttonGroupLayout = FormLayoutContainer.createButtonLayout("buttonLayout", getTranslator()); - buttonGroupLayout.setRootForm(mainForm); - formLayout.add(buttonGroupLayout); - - uifactory.addFormSubmitButton("save", formLayout); - } } public void updateBusinessGroup(BusinessGroup businessGroup) { @@ -109,10 +97,7 @@ public class BusinessGroupEditAccessController extends FormBasicController { @Override protected void formOK(UserRequest ureq) { - if(configController != null) { - configController.formOK(ureq); - } - fireEvent(ureq, Event.DONE_EVENT); + // } @Override diff --git a/src/main/java/org/olat/repository/RepositoryMailing.java b/src/main/java/org/olat/repository/RepositoryMailing.java index 559fca1b8a049004efdb9f8927cada8607017e70..7c73d2bf7216e102b789380fb40b2cc4ee0e7936 100644 --- a/src/main/java/org/olat/repository/RepositoryMailing.java +++ b/src/main/java/org/olat/repository/RepositoryMailing.java @@ -74,6 +74,19 @@ public class RepositoryMailing { return createMailTemplate(re, actor, subjectKey, bodyKey); } + /** + * The mail template when adding users to a course. + * + * @param re + * @param actor + * @return the generated MailTemplate + */ + public static MailTemplate createAddAutoParticipantMailTemplate(RepositoryEntry re, Identity actor) { + String subjectKey = "notification.mail.added.auto.subject"; + String bodyKey = "notification.mail.added.auto.body"; + return createMailTemplate(re, actor, subjectKey, bodyKey); + } + /** * The mail template when adding tutors to a course. * @@ -119,6 +132,8 @@ public class RepositoryMailing { switch(type) { case addParticipant: return createAddParticipantMailTemplate(re, ureqIdentity); + case addParticipantItself: + return createAddAutoParticipantMailTemplate(re, ureqIdentity); case addTutor: return createAddTutorMailTemplate(re, ureqIdentity); case addOwner: @@ -131,7 +146,7 @@ public class RepositoryMailing { return null; } - protected static void sendEmail(Identity ureqIdentity, Identity identity, RepositoryEntry re, + public static void sendEmail(Identity ureqIdentity, Identity identity, RepositoryEntry re, Type type, MailPackage mailing) { if(mailing != null && !mailing.isSendEmail()) { @@ -181,7 +196,8 @@ public class RepositoryMailing { addTutor, removeTutor, addOwner, - removeOwner + removeOwner, + addParticipantItself } private static MailTemplate createMailTemplate(RepositoryEntry re, Identity actor, String subjectKey, String bodyKey) { diff --git a/src/main/java/org/olat/repository/_i18n/LocalStrings_de.properties b/src/main/java/org/olat/repository/_i18n/LocalStrings_de.properties index f25e518daa8cd227e249de38041cdbf777c21266..b1a602c46540480aa1acedf7d791c599d88b4598 100644 --- a/src/main/java/org/olat/repository/_i18n/LocalStrings_de.properties +++ b/src/main/java/org/olat/repository/_i18n/LocalStrings_de.properties @@ -384,6 +384,8 @@ no.lifecycle=Keine Einschr\u00E4nkung no.catalog.entries=Diese Resource wurde noch nicht im Katalog registriert. \r\n\r\n Verwenden Sie den "In Katalog einf\u00FCgen" Button in der Toolbar, um die Resource auf einer bestimmten Katalog-Ebenen hinzuzuf\u00FCgen. Der Katalog erlaubt es dem Benutzer je nach Zugriffskonfiguration nach bestimmten Eintr\u00E4gen zu suchen. Sie k\u00F6nnen die Resource auf mehreren Katalog-Ebenen hinzuf\u00FCgen. info.catalog.entries=Verwenden Sie den "In Katalog einf\u00FCgen" Button in der Toolbar, um die Resource auf einer bestimmten Katalog-Ebenen hinzuzuf\u00FCgen. Der Katalog erlaubt es dem Benutzer je nach Zugriffskonfiguration nach bestimmten Eintr\u00E4gen zu suchen. Sie k\u00F6nnen die Resource auf mehreren Katalog-Ebenen hinzuf\u00FCgen. nomembers=XXX No members +notification.mail.added.auto.body=*** Das ist eine automatisch generierte Nachricht. Bitte antworten Sie nicht auf diese Nachricht *** \n\nSie haben sich f\u00FCr den folgenden Kurs angemeldet\: \n\nKursname\: $coursename\nBeschreibung\: $coursedescription\nZugang\: $courseurl +notification.mail.added.auto.subject=$\:notification.mail.added.subject notification.mail.added.body=*** Das ist eine automatisch generierte Nachricht. Bitte antworten Sie nicht auf diese Nachricht *** \n\nSie wurden von {0} {1} ({2}) in einen Kurs eingeladen\: \n\nKursname\: $coursename\nBeschreibung\: $coursedescription\nZugang\: $courseurl\n\nBei Fragen kontaktieren Sie bitte {0} {1} ({2}). notification.mail.added.subject=Kurs $coursename notification.mail.removed.body=*** Das ist eine automatisch generierte Nachricht. Bitte antworten Sie nicht auf diese Nachricht *** \n\nSie wurden von {0} {1} ({2}) aus dem Kurs ausgetragen\: \n\nKursname\: $coursename\nBeschreibung\: $coursedescription\n\nBei Fragen kontaktieren Sie bitte {0} {1} ({2}). diff --git a/src/main/java/org/olat/repository/_i18n/LocalStrings_en.properties b/src/main/java/org/olat/repository/_i18n/LocalStrings_en.properties index c2a87e54010a7bd99e288dc35f80d5ca08abefa4..19026de10963c68967c64893efb76b1de13bc14a 100644 --- a/src/main/java/org/olat/repository/_i18n/LocalStrings_en.properties +++ b/src/main/java/org/olat/repository/_i18n/LocalStrings_en.properties @@ -381,6 +381,8 @@ no.lifecycle=No limitation no.catalog.entries=This resource has not been added to the catalog yet. \r\n\r\n Use the "Add to catalog" button in the toolbar above to add the resource to a specific level in the catalog. The catalog allows users to browse for available resources depending on th resource access configuration. You can add the resource to multiple catalog levels. info.catalog.entries=Use the "Add to catalog" button in the toolbar above to add the resource to a specific level in the catalog. The catalog allows users to browse for available resources depending on th resource access configuration. You can add the resource to multiple catalog levels. nomembers=XXX No members +notification.mail.added.auto.body=*** This is an automatically generated message. Please do not answer to this message *** \r\n\r\nYou registered you to the following course\:\r\n\r\nCourse name\: $coursename\r\nDescription\: $coursedescription\nLink\: $courseurl +notification.mail.added.auto.subject=$\:notification.mail.added.subject notification.mail.added.body=*** This is an automatically generated message. Please do not answer to this message *** \r\n\r\nYou have been added by {0} {1} ({2}) to a course\:\r\n\r\nCourse name\: $coursename\r\nDescription\: $coursedescription\nLink\: $courseurl\n\nIf you have questions regarding this action, please contact {0} {1} ({2}). notification.mail.added.subject=Course $coursename notification.mail.removed.body=*** This is an automatically generated message. Please do not answer to this message *** \r\n\r\nYou have been removed by {0} {1} ({2}) from a course\:\r\n\r\nCourse name\: $coursename\r\nDescription\: $coursedescription\r\n\r\nIf you have questions regarding this action, please contact {0} {1} ({2}). diff --git a/src/main/java/org/olat/resource/accesscontrol/Offer.java b/src/main/java/org/olat/resource/accesscontrol/Offer.java index 8c59b0b518b1ea78a3d40915764830ed9e54d53b..368f67cc4cdb6113ed033a424a9293dd16772682 100644 --- a/src/main/java/org/olat/resource/accesscontrol/Offer.java +++ b/src/main/java/org/olat/resource/accesscontrol/Offer.java @@ -68,5 +68,9 @@ public interface Offer extends Persistable { public boolean isAutoBooking(); public void setAutoBooking(boolean autoBooking); + + public boolean isConfirmationEmail(); + + public void setConfirmationEmail(boolean confirmationEmail); } diff --git a/src/main/java/org/olat/resource/accesscontrol/manager/ACFrontendManager.java b/src/main/java/org/olat/resource/accesscontrol/manager/ACFrontendManager.java index a517ed0173b7f314ef63370b40f63b68eefa950e..d9a3a9e2393b3cc616ac99c95bdf40e84cdaa7d1 100644 --- a/src/main/java/org/olat/resource/accesscontrol/manager/ACFrontendManager.java +++ b/src/main/java/org/olat/resource/accesscontrol/manager/ACFrontendManager.java @@ -41,6 +41,7 @@ import org.olat.core.id.Roles; import org.olat.core.logging.OLog; import org.olat.core.logging.Tracing; import org.olat.core.util.StringHelper; +import org.olat.core.util.mail.MailPackage; import org.olat.group.BusinessGroup; import org.olat.group.BusinessGroupService; import org.olat.group.manager.BusinessGroupDAO; @@ -49,6 +50,7 @@ import org.olat.group.model.EnrollState; import org.olat.repository.RepositoryEntry; import org.olat.repository.RepositoryEntryRef; import org.olat.repository.RepositoryEntryShort; +import org.olat.repository.RepositoryMailing; import org.olat.repository.RepositoryManager; import org.olat.repository.RepositoryService; import org.olat.repository.manager.RepositoryEntryRelationDAO; @@ -113,11 +115,11 @@ public class ACFrontendManager implements ACService { @Autowired private BusinessGroupDAO businessGroupDao; @Autowired + private BusinessGroupService businessGroupService; + @Autowired private BusinessGroupRelationDAO businessGroupRelationDao; @Autowired private RepositoryEntryRelationDAO repositoryEntryRelationDao; - @Autowired - private BusinessGroupService businessGroupService; /** * The rule to access the repository entry:<br/> @@ -479,14 +481,19 @@ public class ACFrontendManager implements ACService { if("BusinessGroup".equals(resourceType)) { BusinessGroup group = businessGroupService.loadBusinessGroup(resource); if(group != null) { - EnrollState result = businessGroupService.enroll(identity, null, identity, group, null); - return result.isFailed() ? Boolean.FALSE : Boolean.TRUE; + MailPackage mailing = new MailPackage(offer.isConfirmationEmail()); + EnrollState result = businessGroupService.enroll(identity, null, identity, group, mailing); + return !result.isFailed(); } } else { - RepositoryEntryRef entry = repositoryManager.lookupRepositoryEntry(resource, false); + RepositoryEntry entry = repositoryManager.lookupRepositoryEntry(resource, false); if(entry != null) { if(!repositoryEntryRelationDao.hasRole(identity, entry, GroupRoles.participant.name())) { repositoryEntryRelationDao.addRole(identity, entry, GroupRoles.participant.name()); + if(offer.isConfirmationEmail()) { + MailPackage mailing = new MailPackage(offer.isConfirmationEmail()); + RepositoryMailing.sendEmail(identity, identity, entry, RepositoryMailing.Type.addParticipantItself, mailing); + } } return true; } diff --git a/src/main/java/org/olat/resource/accesscontrol/manager/ACOfferDAO.java b/src/main/java/org/olat/resource/accesscontrol/manager/ACOfferDAO.java index 398013d122564e92ec00f6a1b2f11fe7ac74c60e..53442c6b3cb050b7523ad78f6833ecc86a3bc73c 100644 --- a/src/main/java/org/olat/resource/accesscontrol/manager/ACOfferDAO.java +++ b/src/main/java/org/olat/resource/accesscontrol/manager/ACOfferDAO.java @@ -135,6 +135,7 @@ public class ACOfferDAO { offer.setLastModified(now); offer.setResource(resource); offer.setValid(true); + offer.setConfirmationEmail(false); if(resourceName != null && resourceName.length() > 255) { resourceName = resourceName.substring(0, 250); } diff --git a/src/main/java/org/olat/resource/accesscontrol/model/OfferImpl.java b/src/main/java/org/olat/resource/accesscontrol/model/OfferImpl.java index 5c4f6cb4223d33c17b82bd88aa7e2caad5be54d0..3aa9c4f7183d52ecea65b13f35409c82b14f0bbd 100644 --- a/src/main/java/org/olat/resource/accesscontrol/model/OfferImpl.java +++ b/src/main/java/org/olat/resource/accesscontrol/model/OfferImpl.java @@ -98,6 +98,8 @@ public class OfferImpl implements Persistable, Offer, ModifiedInfo { private String token; @Column(name="autobooking", nullable=true, insertable=true, updatable=true) private boolean autoBooking; + @Column(name="confirmation_email", nullable=true, insertable=true, updatable=true) + private boolean confirmationEmail; @Column(name="resourceid", nullable=true, insertable=true, updatable=true) private Long resourceId; @@ -182,6 +184,7 @@ public class OfferImpl implements Persistable, Offer, ModifiedInfo { this.validTo = validTo; } + @Override public Long getResourceId() { return resourceId; } @@ -190,6 +193,7 @@ public class OfferImpl implements Persistable, Offer, ModifiedInfo { this.resourceId = resourceId; } + @Override public String getResourceTypeName() { return resourceTypeName; } @@ -198,6 +202,7 @@ public class OfferImpl implements Persistable, Offer, ModifiedInfo { this.resourceTypeName = resourceTypeName; } + @Override public String getResourceDisplayName() { return resourceDisplayName; } @@ -215,15 +220,25 @@ public class OfferImpl implements Persistable, Offer, ModifiedInfo { public void setDescription(String description) { this.description = description; } - + + @Override public boolean isAutoBooking() { return autoBooking; } - + + @Override public void setAutoBooking(boolean autoBooking) { this.autoBooking = autoBooking; } + public boolean isConfirmationEmail() { + return confirmationEmail; + } + + public void setConfirmationEmail(boolean confirmationEmail) { + this.confirmationEmail = confirmationEmail; + } + public String getToken() { return token; } diff --git a/src/main/java/org/olat/resource/accesscontrol/ui/AbstractConfigurationMethodController.java b/src/main/java/org/olat/resource/accesscontrol/ui/AbstractConfigurationMethodController.java index 67cc9d65aac158c16646d195abd6c884b152feea..3b9462286db794b5837cb2642eb5335cf8592760 100644 --- a/src/main/java/org/olat/resource/accesscontrol/ui/AbstractConfigurationMethodController.java +++ b/src/main/java/org/olat/resource/accesscontrol/ui/AbstractConfigurationMethodController.java @@ -33,10 +33,6 @@ import org.olat.resource.accesscontrol.model.AccessMethod; /** * - * Description:<br> - * TODO: srosse Class Description for AbstractConfigurationMethodController - * - * <P> * Initial Date: 18 avr. 2011 <br> * @author srosse, stephane.rosse@frentix.com, http://www.frentix.com */ @@ -73,6 +69,7 @@ public abstract class AbstractConfigurationMethodController extends FormBasicCon public abstract AccessMethod getMethod(); + @Override public FormItem getInitialFormItem() { return flc; } diff --git a/src/main/java/org/olat/resource/accesscontrol/ui/AccessConfigurationController.java b/src/main/java/org/olat/resource/accesscontrol/ui/AccessConfigurationController.java index 5f30e7fa5e75db21fa9bfb89c99f6bbee46b72dc..e95c3beeb16b3574b7af0c9bd30a7d729c909563 100644 --- a/src/main/java/org/olat/resource/accesscontrol/ui/AccessConfigurationController.java +++ b/src/main/java/org/olat/resource/accesscontrol/ui/AccessConfigurationController.java @@ -24,14 +24,13 @@ import java.math.BigDecimal; import java.util.ArrayList; import java.util.Date; import java.util.List; -import java.util.Map; +import org.olat.core.commons.persistence.DB; import org.olat.core.gui.UserRequest; -import org.olat.core.gui.components.Component; import org.olat.core.gui.components.form.flexible.FormItem; import org.olat.core.gui.components.form.flexible.FormItemContainer; -import org.olat.core.gui.components.form.flexible.elements.DateChooser; import org.olat.core.gui.components.form.flexible.elements.FormLink; +import org.olat.core.gui.components.form.flexible.elements.MultipleSelectionElement; import org.olat.core.gui.components.form.flexible.impl.Form; import org.olat.core.gui.components.form.flexible.impl.FormBasicController; import org.olat.core.gui.components.form.flexible.impl.FormEvent; @@ -64,8 +63,12 @@ import org.springframework.beans.factory.annotation.Autowired; * @author srosse, stephane.rosse@frentix.com, http://www.frentix.com */ public class AccessConfigurationController extends FormBasicController { + + private static final String[] onKeys = new String[] { "on" }; - private List<FormLink> addMethods = new ArrayList<FormLink>(); + private MultipleSelectionElement confirmationEmailEl; + private final List<FormLink> addMethods = new ArrayList<>(); + private final String displayName; private final OLATResource resource; @@ -73,7 +76,7 @@ public class AccessConfigurationController extends FormBasicController { private FormLayoutContainer confControllerContainer; private AbstractConfigurationMethodController newMethodCtrl, editMethodCtrl; - private final List<AccessInfo> confControllers = new ArrayList<AccessInfo>(); + private final List<AccessInfo> confControllers = new ArrayList<>(); private final boolean embbed; private final boolean emptyConfigGrantsFullAccess; @@ -82,6 +85,8 @@ public class AccessConfigurationController extends FormBasicController { private final Formatter formatter; + @Autowired + private DB dbInstance; @Autowired private ACService acService; @Autowired @@ -144,6 +149,11 @@ public class AccessConfigurationController extends FormBasicController { } ((FormLayoutContainer)formLayout).contextPut("methods", addMethods); } + + String[] onValues = new String[] { "" }; + confirmationEmailEl = uifactory.addCheckboxesHorizontal("confirmation.email", formLayout, onKeys, onValues); + confirmationEmailEl.addActionListener(FormEvent.ONCHANGE); + confirmationEmailEl.setVisible(false); String confPage = velocity_root + "/configuration_list.html"; confControllerContainer = FormLayoutContainer.createCustomFormLayout("conf-controllers", getTranslator(), confPage); @@ -154,6 +164,15 @@ public class AccessConfigurationController extends FormBasicController { confControllerContainer.contextPut("confControllers", confControllers); + boolean confirmationEmail = false; + for(AccessInfo info:confControllers) { + Offer offer = info.getLink().getOffer(); + confirmationEmail |= offer.isConfirmationEmail(); + } + if(confirmationEmail) { + confirmationEmailEl.select(onKeys[0], true); + } + if(!embbed) { setFormTitle("accesscontrol.title"); @@ -187,16 +206,6 @@ public class AccessConfigurationController extends FormBasicController { // } - @Override - public void event(UserRequest ureq, Component source, Event event) { - if(addMethods.contains(source)) { - AccessMethod method = (AccessMethod)((Link)source).getUserObject(); - addMethod(ureq, method); - } else { - super.event(ureq, source, event); - } - } - @Override protected void event(UserRequest ureq, Controller source, Event event) { if(newMethodCtrl == source) { @@ -243,39 +252,21 @@ public class AccessConfigurationController extends FormBasicController { String cmd = button.getCmd(); if("delete".equals(cmd)) { AccessInfo infos = (AccessInfo)source.getUserObject(); - acService.deleteOffer(infos.getLink().getOffer()); - confControllers.remove(infos); + removeMethod(infos); fireEvent(ureq, Event.CHANGED_EVENT); } else if("edit".equals(cmd)) { AccessInfo infos = (AccessInfo)source.getUserObject(); editMethod(ureq, infos); } + } else if(confirmationEmailEl == source) { + setConfirmationEmail(confirmationEmailEl.isAtLeastSelected(1)); } super.formInnerEvent(ureq, source, event); } @Override public void formOK(UserRequest ureq) { - Map<String,FormItem> formItemMap = confControllerContainer.getFormComponents(); - - List<OfferAccess> links = new ArrayList<OfferAccess>(); - for(AccessInfo info:confControllers) { - FormItem dateFrom = formItemMap.get("from_" + info.getLink().getKey()); - if(dateFrom instanceof DateChooser) { - Date from = ((DateChooser)dateFrom).getDate(); - info.getLink().setValidFrom(from); - info.getLink().getOffer().setValidFrom(from); - } - - FormItem dateTo = formItemMap.get("to_" + info.getLink().getKey()); - if(dateTo instanceof DateChooser) { - Date to = ((DateChooser)dateTo).getDate(); - info.getLink().setValidTo(to); - info.getLink().getOffer().setValidTo(to); - } - - links.add(info.getLink()); - } + // } protected void loadConfigurations() { @@ -320,6 +311,15 @@ public class AccessConfigurationController extends FormBasicController { delLink.setIconLeftCSS("o_icon o_icon-fw o_icon_delete_item"); confControllerContainer.add(delLink.getName(), delLink); } + + updateConfirmationEmail(); + } + + private void updateConfirmationEmail() { + if(confirmationEmailEl.isVisible() != !confControllers.isEmpty()) { + confirmationEmailEl.setVisible(!confControllers.isEmpty()); + flc.setDirty(true); + } } private void editMethod(UserRequest ureq, AccessInfo infos) { @@ -342,7 +342,9 @@ public class AccessConfigurationController extends FormBasicController { } protected void addMethod(UserRequest ureq, AccessMethod method) { + boolean confirmationEmail = confirmationEmailEl.isVisible() && confirmationEmailEl.isAtLeastSelected(1); Offer offer = acService.createOffer(resource, displayName); + offer.setConfirmationEmail(confirmationEmail); OfferAccess link = acService.createOfferAccess(offer, method); removeAsListenerAndDispose(newMethodCtrl); @@ -362,6 +364,23 @@ public class AccessConfigurationController extends FormBasicController { addConfiguration(newLink); } } + + private void removeMethod(AccessInfo infos) { + acService.deleteOffer(infos.getLink().getOffer()); + confControllers.remove(infos); + updateConfirmationEmail(); + } + + private void setConfirmationEmail(boolean confirmationEmail) { + for(AccessInfo info:confControllers) { + Offer offer = info.getLink().getOffer(); + offer.setConfirmationEmail(confirmationEmail); + offer = acService.save(offer); + } + dbInstance.commit();//make sure all is on the dabatase + confControllers.clear(); + loadConfigurations(); + } public class AccessInfo { private String name; diff --git a/src/main/java/org/olat/resource/accesscontrol/ui/_content/access_configuration.html b/src/main/java/org/olat/resource/accesscontrol/ui/_content/access_configuration.html index 0047566062bd6fad59505d6ed0513823ae76a52a..e530afecc3a5027d9e48c322bb1a87186aaa6bae 100644 --- a/src/main/java/org/olat/resource/accesscontrol/ui/_content/access_configuration.html +++ b/src/main/java/org/olat/resource/accesscontrol/ui/_content/access_configuration.html @@ -12,6 +12,12 @@ #if ($off_info) <div class="o_info">$off_info</div> #end </div></div> #end + #if($r.visible("confirmation.email")) + <div class="form-group"> + <label class="control-label col-sm-3">$r.translate("confirmation.email")</label> + <div class="col-sm-9">$r.render("confirmation.email")</div> + </div> + #end <div class="form-group"> <label class="control-label col-sm-3">$r.translate("ac.methods.label") $r.render("acMethodsLabelHelp")</label> <div class="col-sm-9">$r.render("conf-controllers")</div> diff --git a/src/main/java/org/olat/resource/accesscontrol/ui/_i18n/LocalStrings_de.properties b/src/main/java/org/olat/resource/accesscontrol/ui/_i18n/LocalStrings_de.properties index be5ad639800744c5ea0412081a581203497cc5c0..c7a441396c7f8356b0f6c62b076a9f2f370749fd 100644 --- a/src/main/java/org/olat/resource/accesscontrol/ui/_i18n/LocalStrings_de.properties +++ b/src/main/java/org/olat/resource/accesscontrol/ui/_i18n/LocalStrings_de.properties @@ -38,6 +38,7 @@ admin.menu.title.alt=$\:admin.title admin.title=Verwaltung der Zugangskontrolle und Buchungsmethoden cmd.close=Schliessen cmd.title=Zugangskontrolle +confirmation.email=Best\u00E4tigungsemail f\u00FCr selbst eingetragene Benutzer course.closed=$org.olat.course.run\:course.closed create=Erstellen from=Von\: diff --git a/src/main/java/org/olat/resource/accesscontrol/ui/_i18n/LocalStrings_en.properties b/src/main/java/org/olat/resource/accesscontrol/ui/_i18n/LocalStrings_en.properties index 701fa5425c9c805a9a16402e168a5b166581a2c7..a47f66b45d118e7e662482cd069e723c093b40f8 100644 --- a/src/main/java/org/olat/resource/accesscontrol/ui/_i18n/LocalStrings_en.properties +++ b/src/main/java/org/olat/resource/accesscontrol/ui/_i18n/LocalStrings_en.properties @@ -61,6 +61,7 @@ admin.title=Access control and booking methods administration cmd.close=Close cmd.title=Access control +confirmation.email=Confirmation email for self-registered users course.closed=$org.olat.course.run\:course.closed create=Create from=From\: diff --git a/src/main/resources/database/mysql/alter_12_3_x_to_12_4_0.sql b/src/main/resources/database/mysql/alter_12_3_x_to_12_4_0.sql new file mode 100644 index 0000000000000000000000000000000000000000..eed82324d58fb72217f4b71d2637645a8742fdeb --- /dev/null +++ b/src/main/resources/database/mysql/alter_12_3_x_to_12_4_0.sql @@ -0,0 +1,2 @@ +-- access control +alter table o_ac_offer add column confirmation_email bit default 0; \ No newline at end of file diff --git a/src/main/resources/database/mysql/setupDatabase.sql b/src/main/resources/database/mysql/setupDatabase.sql index 1b81da60dffea76270135dc13ec9f305e8135759..79046cbddc5a42f883901f96964d399ea4666565 100644 --- a/src/main/resources/database/mysql/setupDatabase.sql +++ b/src/main/resources/database/mysql/setupDatabase.sql @@ -973,6 +973,7 @@ create table if not exists o_ac_offer ( resourcetypename varchar(255), resourcedisplayname varchar(255), autobooking boolean default 0, + confirmation_email bit default 0, token varchar(255), price_amount DECIMAL(12,4), price_currency_code VARCHAR(3), diff --git a/src/main/resources/database/oracle/alter_12_3_x_to_12_4_0.sql b/src/main/resources/database/oracle/alter_12_3_x_to_12_4_0.sql new file mode 100644 index 0000000000000000000000000000000000000000..d257c2d6adbf503de92a841694dafa9247cfd3d2 --- /dev/null +++ b/src/main/resources/database/oracle/alter_12_3_x_to_12_4_0.sql @@ -0,0 +1,2 @@ +-- access control +alter table o_ac_offer add confirmation_email number default 0; \ No newline at end of file diff --git a/src/main/resources/database/oracle/setupDatabase.sql b/src/main/resources/database/oracle/setupDatabase.sql index 63874e71921ac61afb6e9dff7d6e47e7e1be2fd1..99d5060b4f1c53cd0acd500b02c13f49e25d48ce 100644 --- a/src/main/resources/database/oracle/setupDatabase.sql +++ b/src/main/resources/database/oracle/setupDatabase.sql @@ -889,6 +889,7 @@ create table o_ac_offer ( resourcedisplayname varchar(255 char), token varchar(255 char), autobooking number default 0 not null, + confirmation_email number default 0, price_amount number(20,2), price_currency_code VARCHAR(3 char), offer_desc VARCHAR(2000 char), diff --git a/src/main/resources/database/postgresql/alter_12_3_x_to_12_4_0.sql b/src/main/resources/database/postgresql/alter_12_3_x_to_12_4_0.sql new file mode 100644 index 0000000000000000000000000000000000000000..954df84e25a37d0131652627c7938183b06a7c70 --- /dev/null +++ b/src/main/resources/database/postgresql/alter_12_3_x_to_12_4_0.sql @@ -0,0 +1,2 @@ +-- access control +alter table o_ac_offer add column confirmation_email bool default false; \ No newline at end of file diff --git a/src/main/resources/database/postgresql/setupDatabase.sql b/src/main/resources/database/postgresql/setupDatabase.sql index 871f4d4101836e0bd5312c8c46fd7fd7db6ff14a..e1865dc2d22f50a5262c54acda65a5864902e909 100644 --- a/src/main/resources/database/postgresql/setupDatabase.sql +++ b/src/main/resources/database/postgresql/setupDatabase.sql @@ -837,6 +837,7 @@ create table o_ac_offer ( resourcetypename varchar(255), resourcedisplayname varchar(255), autobooking bool not null default false, + confirmation_email bool default false, token varchar(255), price_amount DECIMAL, price_currency_code VARCHAR(3),