diff --git a/src/main/java/org/olat/core/util/mail/ContactList.java b/src/main/java/org/olat/core/util/mail/ContactList.java index 0ed63088c43be55125d9a6da5b32a1e7843c8f7a..30e5d09f78dcdf4fff3d58cf8882e561b7111661 100644 --- a/src/main/java/org/olat/core/util/mail/ContactList.java +++ b/src/main/java/org/olat/core/util/mail/ContactList.java @@ -27,6 +27,7 @@ package org.olat.core.util.mail; import java.util.ArrayList; +import java.util.Collection; import java.util.HashMap; import java.util.Iterator; import java.util.List; @@ -272,7 +273,7 @@ public class ContactList extends LogDelegator { * * @param listOfIdentity List containing Identites */ - public void addAllIdentites(List<Identity> listOfIdentity) { + public void addAllIdentites(Collection<Identity> listOfIdentity) { for (Identity identity:listOfIdentity) { add(identity); } diff --git a/src/main/java/org/olat/repository/RepositoryService.java b/src/main/java/org/olat/repository/RepositoryService.java index e5355cfeaa3ead99b941eb2c8689792d246f7691..13aa47c236a6f3d1087874a5091edb4a27da0aa5 100644 --- a/src/main/java/org/olat/repository/RepositoryService.java +++ b/src/main/java/org/olat/repository/RepositoryService.java @@ -225,6 +225,15 @@ public interface RepositoryService { */ public List<Identity> getMembers(RepositoryEntryRef re, String... roles); + /** + * Get the + * @param re + * @param followBusinessGroups + * @param roles + * @return + */ + public List<Identity> getMembers(List<? extends RepositoryEntryRef> re, RepositoryEntryRelationType relationType, String... roles); + /** * Return all the identities the specified role linked to a repository * entry. 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 8d7f87d6003c9462a8716d2db0b4dbd60d4fff29..d7f78427fcac826bd032e78dc412fdb0fb153af4 100644 --- a/src/main/java/org/olat/repository/_i18n/LocalStrings_de.properties +++ b/src/main/java/org/olat/repository/_i18n/LocalStrings_de.properties @@ -163,6 +163,16 @@ cmd.import.ressource.desc=W\u00E4hlen Sie eine Lernressource f\u00FCr den Import comments=Kommentar confirmation.no.toolHelp=Aktion abbrechen. confirmation.yes.toolHelp=Lernressource l\u00F6schen. +contact.attachment=$org.olat.modules.co\:contact.attachment +contact.attachment.maxsize=$org.olat.modules.co\:contact.attachment.maxsize +contact.body=$org.olat.modules.co\:contact.body +contact.cp.from=$org.olat.modules.co\:contact.cp.from +contact.from=$org.olat.modules.co\:contact.from +contact.to=$org.olat.modules.co\:contact.to +contact.to.owner=Alle Kurzbesitzer +contact.to.coach=Alle Betreuer +contact.to.participant=Alle Teilnehmer +contact.subject=$org.olat.modules.co\:contact.subject copy.suffix=(Kopie) course.config.changed.text=Sie m\u00F6chten die Kurseinstellungen \u00E4ndern. Wenn Sie 'Ja' klicken, m\u00FCssen {0} Personen im Kurs den Kurs neu starten. Bei 'Nein' werden die \u00C4nderungen verworfen. Wollen Sie fortfahren? course.config.changed.title=\u00C4nderung der Einstellungen @@ -273,6 +283,7 @@ edit.lifecycle=Semester editieren edit.member=$org.olat.group.ui.main\:edit.member edit.member.groups=$org.olat.group.ui.main\:edit.member.groups error.atleastone=$org.olat.course.member\:error.atleastone +error.contact.to.empty=Es wurde kein Empf\u00E4nger gefunden. error.course.alreadylocked=Dieser Kurs wird im Moment von {0} editiert und ist daher gesperrt. error.createcopy=Beim Kopieren des Objektes ist ein Fehler aufgetreten. Die Aktion wurde abgebrochen. error.download=Beim Download des Objektes ist ein Fehler aufgetreten. Die Aktion wurde abgebrochen. @@ -598,6 +609,7 @@ tools.new.header=Herstellen tools.new.podcast=Podcast tools.new.portfolio=Portfoliovorlage tools.new.wiki=Wiki +tools.send.mail=E-Mail versenden tools.restore=Wiederherstellen user.notfound=Folgende Benutzer wurden nicht gefunden\: {0} warn.config.reference.no.access=Beachten Sie bitte, dass die Konfiguration "Referenzierung m\u00F6glich" erst aktiv wird wenn der Zugriff auch f\u00FCr Autoren freigegeben wurde. 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 2d52836b4d9e1056955f04358d2e1c0dcac78575..ab778c9684cd0ff8bc97518ebe5294e001abdc92 100644 --- a/src/main/java/org/olat/repository/_i18n/LocalStrings_en.properties +++ b/src/main/java/org/olat/repository/_i18n/LocalStrings_en.properties @@ -159,6 +159,16 @@ cmd.import.ressource.desc=Choose a learning resource to import\:<ul><li>OpenOLAT comments=Comments confirmation.no.toolHelp=Cancel action. confirmation.yes.toolHelp=Delete learning resource. +contact.attachment=$org.olat.modules.co\:contact.attachment +contact.attachment.maxsize=$org.olat.modules.co\:contact.attachment.maxsize +contact.body=$org.olat.modules.co\:contact.body +contact.cp.from=$org.olat.modules.co\:contact.cp.from +contact.from=$org.olat.modules.co\:contact.from +contact.to=$org.olat.modules.co\:contact.to +contact.to.owner=Alle Kurzbesitzer +contact.to.coach=Alle Betreuer +contact.to.participant=Alle Teilnehmer +contact.subject=$org.olat.modules.co\:contact.subject copy.suffix=(copy) course.config.changed.text=You want to modify your course settings. When clicking on 'Yes' {0} participants will have to restart this course. When clicking on 'No' all modifications will be discarded. Do you wish to proceed? course.config.changed.title=Modification of settings @@ -269,6 +279,7 @@ edit.lifecycle=Edit semester edit.member=$org.olat.group.ui.main\:edit.member edit.member.groups=$org.olat.group.ui.main\:edit.member.groups error.atleastone=$org.olat.course.member\:error.atleastone +error.contact.to.empty=No recipient can be found. error.course.alreadylocked=This course is currently edited by {0} and therefore locked. error.createcopy=An error occurred while trying to copy the object. Action canceled. error.download=An error occurred while trying to download the object. Action canceled. @@ -595,6 +606,7 @@ tools.new.header=Create tools.new.podcast=Podcast tools.new.portfolio=Portfolio template tools.new.wiki=Wiki +tools.send.mail=Send E-mail tools.restore=Restore user.notfound=The following users have not been found\: {0} warn.config.reference.no.access=Please note that the configuration "Can be referenced" is activated only after access to this resource is granted to other authors as well. diff --git a/src/main/java/org/olat/repository/manager/RepositoryEntryRelationDAO.java b/src/main/java/org/olat/repository/manager/RepositoryEntryRelationDAO.java index 81def30930e5286b2c0273cc5277744f9e42ca03..bf4d203dda9ad1ef4dcbd1bec981a93e7ef9d294 100644 --- a/src/main/java/org/olat/repository/manager/RepositoryEntryRelationDAO.java +++ b/src/main/java/org/olat/repository/manager/RepositoryEntryRelationDAO.java @@ -28,6 +28,7 @@ import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Set; +import java.util.stream.Collectors; import javax.persistence.EntityManager; import javax.persistence.TypedQuery; @@ -420,6 +421,12 @@ public class RepositoryEntryRelationDAO { } public List<Identity> getMembers(RepositoryEntryRef re, RepositoryEntryRelationType type, String... roles) { + return getMembers(Collections.singletonList(re), type, roles); + } + + public List<Identity> getMembers(List<? extends RepositoryEntryRef> res, RepositoryEntryRelationType type, String... roles) { + if(res == null || res.isEmpty()) return Collections.emptyList(); + List<String> roleList = GroupRoles.toList(roles); String def; @@ -436,14 +443,15 @@ public class RepositoryEntryRelationDAO { .append(" inner join baseGroup.members as memberships") .append(" inner join memberships.identity as ident") .append(" inner join fetch ident.user as identUser") - .append(" where v.key=:repoKey"); + .append(" where v.key in (:repoKeys)"); if(roleList.size() > 0) { sb.append(" and memberships.role in (:roles)"); } - + + List<Long> repoKeys = res.stream().map(re -> re.getKey()).collect(Collectors.toList()); TypedQuery<Identity> query = dbInstance.getCurrentEntityManager() .createQuery(sb.toString(), Identity.class) - .setParameter("repoKey", re.getKey()); + .setParameter("repoKeys", repoKeys); if(roleList.size() > 0) { query.setParameter("roles", roleList); } diff --git a/src/main/java/org/olat/repository/manager/RepositoryServiceImpl.java b/src/main/java/org/olat/repository/manager/RepositoryServiceImpl.java index bfc6933b253efa78f889a1ea850f05fcb8c6276f..d84ac4f53899fd50f8412d0a5ce826b5c2f44744 100644 --- a/src/main/java/org/olat/repository/manager/RepositoryServiceImpl.java +++ b/src/main/java/org/olat/repository/manager/RepositoryServiceImpl.java @@ -609,6 +609,11 @@ public class RepositoryServiceImpl implements RepositoryService { return reToGroupDao.getMembers(re, RepositoryEntryRelationType.defaultGroup, roles); } + @Override + public List<Identity> getMembers(List<? extends RepositoryEntryRef> res, RepositoryEntryRelationType relationType, String... roles) { + return reToGroupDao.getMembers(res, relationType, roles); + } + @Override public List<Identity> getIdentitiesWithRole(String role) { return reToGroupDao.getIdentitiesWithRole(role); diff --git a/src/main/java/org/olat/repository/ui/author/AuthorListController.java b/src/main/java/org/olat/repository/ui/author/AuthorListController.java index 6130c5c4d16a3ec82097aec1307be360e844846a..dc1e936ba4eed01322cd25ee4c0f0254d52f97e7 100644 --- a/src/main/java/org/olat/repository/ui/author/AuthorListController.java +++ b/src/main/java/org/olat/repository/ui/author/AuthorListController.java @@ -127,6 +127,7 @@ public class AuthorListController extends FormBasicController implements Activat private ToolsController toolsCtrl; protected CloseableModalController cmc; + private SendMailController sendMailCtrl; private StepsMainRunController wizardCtrl; private AuthorSearchController searchCtrl; private UserSearchController userSearchCtr; @@ -143,7 +144,7 @@ public class AuthorListController extends FormBasicController implements Activat private Link importLink; private Dropdown createDropdown; - private FormLink addOwnersButton, deleteButton, copyButton; + private FormLink sendMailButton, addOwnersButton, deleteButton, copyButton; private LockResult lockResult; private final AtomicInteger counter = new AtomicInteger(); @@ -331,6 +332,7 @@ public class AuthorListController extends FormBasicController implements Activat protected void initBatchButtons(FormItemContainer formLayout) { if(hasAuthorRight) { + sendMailButton = uifactory.addFormLink("tools.send.mail", formLayout, Link.BUTTON); addOwnersButton = uifactory.addFormLink("tools.add.owners", formLayout, Link.BUTTON); copyButton = uifactory.addFormLink("details.copy", formLayout, Link.BUTTON); deleteButton = uifactory.addFormLink("details.delete", formLayout, Link.BUTTON); @@ -478,6 +480,9 @@ public class AuthorListController extends FormBasicController implements Activat } cmc.deactivate(); cleanUp(); + } else if(sendMailCtrl == source) { + cmc.deactivate(); + cleanUp(); } else if(toolsCtrl == source) { if(event == Event.DONE_EVENT) { toolsCalloutCtrl.deactivate(); @@ -516,6 +521,7 @@ public class AuthorListController extends FormBasicController implements Activat removeAsListenerAndDispose(confirmDeleteCtrl); removeAsListenerAndDispose(toolsCalloutCtrl); removeAsListenerAndDispose(userSearchCtr); + removeAsListenerAndDispose(sendMailCtrl); removeAsListenerAndDispose(createCtrl); removeAsListenerAndDispose(importCtrl); removeAsListenerAndDispose(wizardCtrl); @@ -525,6 +531,7 @@ public class AuthorListController extends FormBasicController implements Activat confirmDeleteCtrl = null; toolsCalloutCtrl = null; userSearchCtr = null; + sendMailCtrl = null; createCtrl = null; importCtrl = null; wizardCtrl = null; @@ -547,6 +554,13 @@ public class AuthorListController extends FormBasicController implements Activat } else { showWarning("bulk.update.nothing.selected"); } + } else if(sendMailButton == source) { + List<AuthoringEntryRow> rows = getMultiSelectedRows(); + if(!rows.isEmpty()) { + doSendMail(ureq, rows); + } else { + showWarning("bulk.update.nothing.selected"); + } } else if(copyButton == source) { List<AuthoringEntryRow> rows = getMultiSelectedRows(); if(!rows.isEmpty()) { @@ -732,6 +746,20 @@ public class AuthorListController extends FormBasicController implements Activat return rows; } + private void doSendMail(UserRequest ureq, List<AuthoringEntryRow> rows) { + if(sendMailCtrl != null) return; + + removeAsListenerAndDispose(userSearchCtr); + sendMailCtrl = new SendMailController(ureq, getWindowControl(), rows); + listenTo(sendMailCtrl); + + String title = translate("tools.send.mail"); + cmc = new CloseableModalController(getWindowControl(), translate("close"), sendMailCtrl.getInitialComponent(), + true, title); + listenTo(cmc); + cmc.activate(); + } + private void doAddOwners(UserRequest ureq, List<AuthoringEntryRow> rows) { if(userSearchCtr != null) return; diff --git a/src/main/java/org/olat/repository/ui/author/SendMailController.java b/src/main/java/org/olat/repository/ui/author/SendMailController.java new file mode 100644 index 0000000000000000000000000000000000000000..f6875fe5c5d6f069c07e0ca783d9aa1d15f00627 --- /dev/null +++ b/src/main/java/org/olat/repository/ui/author/SendMailController.java @@ -0,0 +1,344 @@ +/** + * <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.repository.ui.author; + +import java.io.File; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +import org.olat.basesecurity.GroupRoles; +import org.olat.core.commons.modules.bc.FileUploadController; +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.FileElement; +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.RichTextElement; +import org.olat.core.gui.components.form.flexible.elements.TextElement; +import org.olat.core.gui.components.form.flexible.impl.FormBasicController; +import org.olat.core.gui.components.form.flexible.impl.FormEvent; +import org.olat.core.gui.components.form.flexible.impl.FormLayoutContainer; +import org.olat.core.gui.components.link.Link; +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.gui.util.CSSHelper; +import org.olat.core.id.Identity; +import org.olat.core.logging.activity.ThreadLocalUserActivityLogger; +import org.olat.core.util.FileUtils; +import org.olat.core.util.StringHelper; +import org.olat.core.util.Util; +import org.olat.core.util.mail.ContactList; +import org.olat.core.util.mail.MailBundle; +import org.olat.core.util.mail.MailContext; +import org.olat.core.util.mail.MailContextImpl; +import org.olat.core.util.mail.MailLoggingAction; +import org.olat.core.util.mail.MailManager; +import org.olat.core.util.mail.MailModule; +import org.olat.core.util.mail.MailerResult; +import org.olat.repository.RepositoryEntryRef; +import org.olat.repository.RepositoryEntryRelationType; +import org.olat.repository.RepositoryService; +import org.olat.user.UserManager; +import org.springframework.beans.factory.annotation.Autowired; + +/** + * + * Initial date: 27 avr. 2017<br> + * @author srosse, stephane.rosse@frentix.com, http://www.frentix.com + * + */ +public class SendMailController extends FormBasicController { + + private static final String[] onKeys = new String[]{ "on" }; + private static final String[] contactKeys = new String[]{ GroupRoles.owner.name(), GroupRoles.coach.name(), GroupRoles.participant.name() }; + + private RichTextElement bodyEl; + private FileElement attachmentEl; + private TextElement subjectEl; + private MultipleSelectionElement contactEl, copyFromEl; + private FormLayoutContainer uploadCont; + + private int counter = 0; + private long attachmentSize = 0l; + private File attachementTempDir; + private final int contactAttachmentMaxSizeInMb; + private List<Attachment> attachments = new ArrayList<>(); + private final List<? extends RepositoryEntryRef> repoEntries; + + @Autowired + private UserManager userManager; + @Autowired + private MailManager mailService; + @Autowired + private MailModule mailModule; + @Autowired + private RepositoryService repositoryService; + + public SendMailController(UserRequest ureq, WindowControl wControl, List<? extends RepositoryEntryRef> repoEntries) { + super(ureq, wControl); + setTranslator(Util.createPackageTranslator(RepositoryService.class, getLocale(), getTranslator())); + this.repoEntries = repoEntries; + this.contactAttachmentMaxSizeInMb = mailModule.getMaxSizeForAttachement(); + initForm(ureq); + } + + @Override + protected void initForm(FormItemContainer formLayout, Controller listener, UserRequest ureq) { + String fullName = userManager.getUserDisplayName(getIdentity()); + if(StringHelper.containsNonWhitespace(fullName)) { + fullName = "[" + fullName + "]"; + } + TextElement fromEl = uifactory.addTextElement("from", "contact.from", 255, fullName, formLayout); + fromEl.setEnabled(false); + + String[] contactValues = new String[] { + translate("contact.to.owner"), + translate("contact.to.coach"), + translate("contact.to.participant"), + }; + contactEl = uifactory.addCheckboxesVertical("to", "contact.to", formLayout, contactKeys, contactValues, 1); + + subjectEl = uifactory.addTextElement("subject", "contact.subject", 255, "", formLayout); + subjectEl.setDisplaySize(255); + subjectEl.setMandatory(true); + bodyEl = uifactory.addRichTextElementForStringDataMinimalistic("body", "contact.body", "", 15, 8, formLayout, getWindowControl()); + bodyEl.setMandatory(true); + + attachmentEl = uifactory.addFileElement(getWindowControl(), "file_upload_1", "contact.attachment", formLayout); + attachmentEl.addActionListener(FormEvent.ONCHANGE); + attachmentEl.setExampleKey("contact.attachment.maxsize", new String[]{ Integer.toString(contactAttachmentMaxSizeInMb) }); + + String attachmentPage = velocity_root + "/attachments.html"; + uploadCont = FormLayoutContainer.createCustomFormLayout("file_upload_inner", getTranslator(), attachmentPage); + uploadCont.setRootForm(mainForm); + uploadCont.setVisible(false); + uploadCont.contextPut("attachments", attachments); + formLayout.add(uploadCont); + + copyFromEl = uifactory.addCheckboxesHorizontal("copy.from", "contact.cp.from", formLayout, onKeys, new String[] { "" }); + + FormLayoutContainer buttonGroupLayout = FormLayoutContainer.createButtonLayout("buttonGroupLayout", getTranslator()); + formLayout.add(buttonGroupLayout); + uifactory.addFormCancelButton("cancel", buttonGroupLayout, ureq, getWindowControl()); + uifactory.addFormSubmitButton("tools.send.mail", buttonGroupLayout); + } + + @Override + protected void doDispose() { + if(attachementTempDir != null && attachementTempDir.exists()) { + FileUtils.deleteDirsAndFiles(attachementTempDir, true, true); + } + } + + @Override + protected boolean validateFormLogic(UserRequest ureq) { + boolean allOk = true; + + subjectEl.clearError(); + if(!StringHelper.containsNonWhitespace(subjectEl.getValue())) { + subjectEl.setErrorKey("form.legende.mandatory", null); + allOk &= false; + } + + bodyEl.clearError(); + if(!StringHelper.containsNonWhitespace(bodyEl.getValue())) { + bodyEl.setErrorKey("form.legende.mandatory", null); + allOk &= false; + } + + contactEl.clearError(); + if(contactEl.getSelectedKeys().isEmpty()) { + contactEl.setErrorKey("form.legende.mandatory", null); + allOk &= false; + } + + return allOk & super.validateFormLogic(ureq); + } + + private File[] getAttachments() { + File[] atttachmentArr = new File[attachments.size()]; + for(int i=attachments.size(); i-->0; ) { + atttachmentArr[i] = attachments.get(i).getFile(); + } + return atttachmentArr; + } + + @Override + protected void formInnerEvent(UserRequest ureq, FormItem source, FormEvent event) { + if(source == attachmentEl) { + doUploadAttachement(); + } if(source instanceof FormLink) { + FormLink link = (FormLink)source; + String cmd = link.getCmd(); + if("delete".equals(cmd)) { + Attachment attachment = (Attachment)link.getUserObject(); + doDeleteAttachment(attachment); + } + } + super.formInnerEvent(ureq, source, event); + } + + private void doDeleteAttachment(Attachment attachment) { + attachmentSize -= attachment.getFile().length(); + attachment.getFile().delete(); + attachments.remove(attachment); + uploadCont.setVisible(attachments.size() > 0); + uploadCont.setDirty(true); + } + + private void doUploadAttachement() { + if(attachementTempDir == null) { + attachementTempDir = FileUtils.createTempDir("attachements", null, null); + } + + long size = attachmentEl.getUploadSize(); + String filename = attachmentEl.getUploadFileName(); + if(size + attachmentSize > (contactAttachmentMaxSizeInMb * 1024 * 1024)) { + showWarning("contact.attachment,maxsize", Integer.toString(contactAttachmentMaxSizeInMb)); + attachmentEl.reset(); + } else { + File attachment = attachmentEl.moveUploadFileTo(attachementTempDir); + attachmentEl.reset(); + if(attachment == null) { + logError("Could not move contact-form attachment to " + attachementTempDir.getAbsolutePath(), null); + setTranslator(Util.createPackageTranslator(FileUploadController.class, getLocale(), getTranslator())); + showError("FileMoveCopyFailed",""); + } else { + attachmentSize += size; + FormLink removeFile = uifactory.addFormLink("delete_" + (++counter), "delete", "delete", null, uploadCont, Link.LINK); + removeFile.setIconLeftCSS("o_icon o_icon-fw o_icon_delete"); + String css = CSSHelper.createFiletypeIconCssClassFor(filename); + Attachment wrapper = new Attachment(attachment, attachment.getName(), css, removeFile); + removeFile.setUserObject(wrapper); + attachments.add(wrapper); + uploadCont.setVisible(true); + } + } + } + + private void handleAddressException(boolean success) { + StringBuilder error = new StringBuilder(); + if (success) { + error.append(translate("error.msg.send.partially.nok")) + .append("<br />") + .append(translate("error.msg.send.invalid.rcps")); + } else { + error.append(translate("error.msg.send.nok")) + .append("<br />") + .append(translate("error.msg.send.553")); + } + getWindowControl().setError(error.toString()); + } + + @Override + protected void formOK(UserRequest ureq) { + ContactList contactList = new ContactList(""); + Collection<String> roleList = contactEl.getSelectedKeys(); + String[] roles = roleList.toArray(new String[roleList.size()]); + List<Identity> identities = repositoryService.getMembers(repoEntries, RepositoryEntryRelationType.both, roles); + if(identities.isEmpty()) { + showWarning("error.contact.to.empty"); + } else { + Set<Identity> deduplicates = new HashSet<>(identities); + contactList.addAllIdentites(deduplicates); + + boolean success = false; + try { + File[] attachmentArr = getAttachments(); + MailContext context = new MailContextImpl(getWindowControl().getBusinessControl().getAsString()); + MailBundle bundle = new MailBundle(); + bundle.setContext(context); + bundle.setFromId(getIdentity()); + bundle.setContactLists(Collections.singletonList(contactList)); + bundle.setContent(subjectEl.getValue(), bodyEl.getValue(), attachmentArr); + MailerResult result = mailService.sendMessage(bundle); + if(copyFromEl.isAtLeastSelected(1)) { + MailBundle ccBundle = new MailBundle(); + ccBundle.setContext(context); + ccBundle.setFromId(getIdentity()); + ccBundle.setCc(getIdentity()); + ccBundle.setContent(subjectEl.getValue(), bodyEl.getValue(), attachmentArr); + MailerResult ccResult = mailService.sendMessage(ccBundle); + result.append(ccResult); + } + success = result.isSuccessful(); + } catch (Exception e) { + //error in recipient email address(es) + handleAddressException(success); + } + + if (success) { + showInfo("msg.send.ok"); + // do logging + ThreadLocalUserActivityLogger.log(MailLoggingAction.MAIL_SENT, getClass()); + fireEvent(ureq, Event.DONE_EVENT); + } else { + showInfo("error.msg.send.nok"); + fireEvent(ureq, Event.FAILED_EVENT); + } + } + } + + @Override + protected void formCancelled(UserRequest ureq) { + fireEvent(ureq, Event.CANCELLED_EVENT); + } + + public static class Attachment { + + private final File file; + private final String filename; + private final String cssClass; + private final FormLink deleteLink; + + public Attachment(File file, String filename, String cssClass, FormLink deleteLink) { + this.file = file; + this.filename = filename; + this.cssClass = cssClass; + this.deleteLink = deleteLink; + } + + public File getFile() { + return file; + } + + public String getCssClass() { + return cssClass; + } + + public String getFilename() { + return filename; + } + + public FormLink getDeleteLink() { + return deleteLink; + } + + public String getDeleteComponentName() { + return deleteLink.getComponent().getComponentName(); + } + } +} \ No newline at end of file diff --git a/src/main/java/org/olat/repository/ui/author/_content/attachments.html b/src/main/java/org/olat/repository/ui/author/_content/attachments.html new file mode 100644 index 0000000000000000000000000000000000000000..3ae6db278f2b54d25c792a37a62fdba5ed7ba7ec --- /dev/null +++ b/src/main/java/org/olat/repository/ui/author/_content/attachments.html @@ -0,0 +1,6 @@ +<ul class="list-unstyled"> + #foreach ($attachment in $attachments) + <li><i class="o_icon o_icon-fw $attachment.cssClass"> </i> $attachment.filename $r.render(${attachment.getDeleteComponentName()})</li> + #end +</ul> + diff --git a/src/main/java/org/olat/repository/ui/author/_content/entries.html b/src/main/java/org/olat/repository/ui/author/_content/entries.html index 06b129dcb081910c85b9b1910ce185605eb53733..9bd02f0ce2a8e565dd5d9fb1da8e5db4951f2619 100644 --- a/src/main/java/org/olat/repository/ui/author/_content/entries.html +++ b/src/main/java/org/olat/repository/ui/author/_content/entries.html @@ -3,6 +3,9 @@ #end $r.render("table") <div class="o_button_group clearfix"> + #if($r.available("tools.send.mail")) + $r.render("tools.send.mail") + #end #if($r.available("tools.add.owners")) $r.render("tools.add.owners") #end