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 252a394c0b64a86c8d0d8283e8148732dcd1051a..0ed63088c43be55125d9a6da5b32a1e7843c8f7a 100644 --- a/src/main/java/org/olat/core/util/mail/ContactList.java +++ b/src/main/java/org/olat/core/util/mail/ContactList.java @@ -64,6 +64,10 @@ public class ContactList extends LogDelegator { private Map<String, Identity> identiEmails = new HashMap<String, Identity>(); private boolean emailPrioInstitutional = false; + public ContactList() { + // + } + /** * A ContacList must have at least a name != null, matching ^[^;,:]*$ * @@ -71,7 +75,6 @@ public class ContactList extends LogDelegator { */ public ContactList(String name) { setName(name); - this.description = null; } /** diff --git a/src/main/java/org/olat/course/certificate/CertificatesModule.java b/src/main/java/org/olat/course/certificate/CertificatesModule.java new file mode 100644 index 0000000000000000000000000000000000000000..73c7985e876a28d451b1173b84b6816691ea3b81 --- /dev/null +++ b/src/main/java/org/olat/course/certificate/CertificatesModule.java @@ -0,0 +1,87 @@ +/** + * <a href="http://www.openolat.org"> + * OpenOLAT - Online Learning and Training</a><br> + * <p> + * Licensed under the Apache License, Version 2.0 (the "License"); <br> + * you may not use this file except in compliance with the License.<br> + * You may obtain a copy of the License at the + * <a href="http://www.apache.org/licenses/LICENSE-2.0">Apache homepage</a> + * <p> + * Unless required by applicable law or agreed to in writing,<br> + * software distributed under the License is distributed on an "AS IS" BASIS, <br> + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. <br> + * See the License for the specific language governing permissions and <br> + * limitations under the License. + * <p> + * Initial code contributed and copyrighted by<br> + * frentix GmbH, http://www.frentix.com + * <p> + */ +package org.olat.course.certificate; + +import java.util.ArrayList; +import java.util.List; + +import org.olat.core.configuration.AbstractSpringModule; +import org.olat.core.util.StringHelper; +import org.olat.core.util.coordinate.CoordinatorManager; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.stereotype.Service; + +/** + * + * Initial date: 31 janv. 2017<br> + * @author srosse, stephane.rosse@frentix.com, http://www.frentix.com + * + */ +@Service +public class CertificatesModule extends AbstractSpringModule { + + private static final String CERTIFICATE_BCC = "certificate.bcc"; + + @Value("${certificate.bcc}") + private String certificateBcc; + + @Autowired + public CertificatesModule(CoordinatorManager coordinatorManager) { + super(coordinatorManager); + } + + @Override + public void init() { + String bccObj = getStringPropertyValue(CERTIFICATE_BCC, true); + if(StringHelper.containsNonWhitespace(bccObj)) { + certificateBcc = bccObj; + } + } + + @Override + protected void initFromChangedProperties() { + init(); + } + + public String getCertificateBcc() { + return certificateBcc; + } + + public void setCertificateBcc(String email) { + certificateBcc = email; + setStringProperty(CERTIFICATE_BCC, email, true); + } + + public List<String> getCertificatesBccEmails() { + return splitEmails(certificateBcc); + } + + public List<String> splitEmails(String emails) { + List<String> emailList = new ArrayList<>(); + if(StringHelper.containsNonWhitespace(emails)) { + String[] emailArr = emails.split("[;,]"); + for(String email:emailArr) { + emailList.add(email); + } + } + return emailList; + } +} diff --git a/src/main/java/org/olat/course/certificate/manager/CertificatesManagerImpl.java b/src/main/java/org/olat/course/certificate/manager/CertificatesManagerImpl.java index 38428eabdbacefcd4bb159719254af0fb9c0ac21..44c2f7e8f001149f26d6a1a86ac14106bbb81374 100644 --- a/src/main/java/org/olat/course/certificate/manager/CertificatesManagerImpl.java +++ b/src/main/java/org/olat/course/certificate/manager/CertificatesManagerImpl.java @@ -74,6 +74,7 @@ import org.olat.core.util.Util; import org.olat.core.util.WebappHelper; import org.olat.core.util.coordinate.CoordinatorManager; import org.olat.core.util.i18n.I18nManager; +import org.olat.core.util.mail.ContactList; import org.olat.core.util.mail.MailBundle; import org.olat.core.util.mail.MailManager; import org.olat.core.util.mail.MailerResult; @@ -92,6 +93,7 @@ import org.olat.course.certificate.CertificateLight; import org.olat.course.certificate.CertificateStatus; import org.olat.course.certificate.CertificateTemplate; import org.olat.course.certificate.CertificatesManager; +import org.olat.course.certificate.CertificatesModule; import org.olat.course.certificate.EmailStatus; import org.olat.course.certificate.RecertificationTimeUnit; import org.olat.course.certificate.model.CertificateImpl; @@ -160,6 +162,8 @@ public class CertificatesManagerImpl implements CertificatesManager, MessageList private NotificationsManager notificationsManager; @Autowired private FolderModule folderModule; + @Autowired + private CertificatesModule certificatesModule; @Resource(name="certificateQueue") @@ -935,6 +939,13 @@ public class CertificatesManagerImpl implements CertificatesManager, MessageList bundle.setToId(to); bundle.setFrom(WebappHelper.getMailConfig("mailReplyTo")); + List<String> bccs = certificatesModule.getCertificatesBccEmails(); + if(bccs.size() > 0) { + ContactList bcc = new ContactList(); + bccs.forEach(email -> { bcc.add(email); }); + bundle.setContactList(bcc); + } + String[] args = new String[] { entry.getDisplayname(), userManager.getUserDisplayName(to) diff --git a/src/main/java/org/olat/course/certificate/ui/CertificatesAdminController.java b/src/main/java/org/olat/course/certificate/ui/CertificatesAdminController.java index 32fe7d4f8bd906227124c998dea055667c2ea5aa..d9aeae267fea0c981f6fac61222bd3af1f91a1da 100644 --- a/src/main/java/org/olat/course/certificate/ui/CertificatesAdminController.java +++ b/src/main/java/org/olat/course/certificate/ui/CertificatesAdminController.java @@ -19,200 +19,92 @@ */ package org.olat.course.certificate.ui; -import java.util.List; - 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.FlexiTableElement; -import org.olat.core.gui.components.form.flexible.elements.FormLink; -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.elements.table.DefaultFlexiColumnModel; -import org.olat.core.gui.components.form.flexible.impl.elements.table.DefaultFlexiTableDataModel; -import org.olat.core.gui.components.form.flexible.impl.elements.table.FlexiTableColumnModel; -import org.olat.core.gui.components.form.flexible.impl.elements.table.FlexiTableDataModelFactory; -import org.olat.core.gui.components.form.flexible.impl.elements.table.SelectionEvent; +import org.olat.core.gui.components.Component; import org.olat.core.gui.components.link.Link; -import org.olat.core.gui.control.Controller; +import org.olat.core.gui.components.link.LinkFactory; +import org.olat.core.gui.components.segmentedview.SegmentViewComponent; +import org.olat.core.gui.components.segmentedview.SegmentViewEvent; +import org.olat.core.gui.components.segmentedview.SegmentViewFactory; +import org.olat.core.gui.components.velocity.VelocityContainer; import org.olat.core.gui.control.Event; import org.olat.core.gui.control.WindowControl; -import org.olat.core.gui.control.generic.closablewrapper.CloseableModalController; -import org.olat.core.gui.control.generic.modal.DialogBoxController; -import org.olat.core.gui.control.generic.modal.DialogBoxUIFactory; -import org.olat.course.certificate.CertificateTemplate; -import org.olat.course.certificate.CertificatesManager; -import org.springframework.beans.factory.annotation.Autowired; +import org.olat.core.gui.control.controller.BasicController; +import org.olat.core.id.OLATResourceable; +import org.olat.core.id.context.BusinessControlFactory; +import org.olat.core.util.resource.OresHelper; /** * - * Initial date: 20.10.2014<br> + * Initial date: 31 janv. 2017<br> * @author srosse, stephane.rosse@frentix.com, http://www.frentix.com * */ -public class CertificatesAdminController extends FormBasicController { +public class CertificatesAdminController extends BasicController { - private FormLink uploadLink; - private FlexiTableElement tableEl; - private TemplatesDataModel tableModel; + private final VelocityContainer mainVC; + private final Link settingsLink, certificatesLink; + private final SegmentViewComponent segmentView; - private CloseableModalController cmc; - private UploadCertificateController uploadCtrl; - private DialogBoxController confirmDeleteCtrl; + private CertificatesSettingsAdminController settingsCtrl; + private CertificatesListAdminController certificatesCtrl; - @Autowired - private CertificatesManager certificatesManager; - public CertificatesAdminController(UserRequest ureq, WindowControl wControl) { - super(ureq, wControl, "admin_certificates"); + super(ureq, wControl); - initForm(ureq); - } + mainVC = createVelocityContainer("admin_certificates"); + + segmentView = SegmentViewFactory.createSegmentView("segments", mainVC, this); + segmentView.setReselect(true); - @Override - protected void initForm(FormItemContainer formLayout, Controller listener, UserRequest ureq) { + settingsLink = LinkFactory.createLink("admin.certificates.settings", mainVC, this); + segmentView.addSegment(settingsLink, true); + certificatesLink = LinkFactory.createLink("admin.certificates.templates", mainVC, this); + segmentView.addSegment(certificatesLink, false); - FlexiTableColumnModel tableColumnModel = FlexiTableDataModelFactory.createFlexiTableColumnModel(); - tableColumnModel.addFlexiColumnModel(new DefaultFlexiColumnModel(Cols.name.i18n(), Cols.name.ordinal())); - tableColumnModel.addFlexiColumnModel(new DefaultFlexiColumnModel("replace", translate("replace"), "replace")); - tableColumnModel.addFlexiColumnModel(new DefaultFlexiColumnModel("delete", translate("delete"), "delete")); + doOpenSettings(ureq); - tableModel = new TemplatesDataModel(tableColumnModel); - tableEl = uifactory.addTableElement(getWindowControl(), "templates", tableModel, getTranslator(), formLayout); - - uploadLink = uifactory.addFormLink("upload", formLayout, Link.BUTTON); - updateDataModel(); - } - - private void updateDataModel() { - List<CertificateTemplate> templates = certificatesManager.getTemplates(); - tableModel.setObjects(templates); - tableEl.reset(); + putInitialPanel(mainVC); } @Override protected void doDispose() { // } - - @Override - protected void formOK(UserRequest ureq) { - // - } - - @Override - protected void formInnerEvent(UserRequest ureq, FormItem source, FormEvent event) { - if(source == uploadLink) { - doUpload(ureq); - } else if(source == tableEl) { - SelectionEvent se = (SelectionEvent)event; - String cmd = se.getCommand(); - CertificateTemplate selectedTemplate = tableModel.getObject(se.getIndex()); - if("replace".equals(cmd)) { - doReplace(ureq, selectedTemplate); - } else if("delete".equals(cmd)) { - doConfirmDelete(ureq, selectedTemplate); - } - } - } @Override - protected void event(UserRequest ureq, Controller source, Event event) { - if(uploadCtrl == source) { - if(event == Event.DONE_EVENT) { - updateDataModel(); - } - cmc.deactivate(); - cleanUp(); - } else if(confirmDeleteCtrl == source) { - if(DialogBoxUIFactory.isOkEvent(event)) { - CertificateTemplate template = (CertificateTemplate)confirmDeleteCtrl.getUserObject(); - doDelete(template); + protected void event(UserRequest ureq, Component source, Event event) { + if(source == segmentView) { + if(event instanceof SegmentViewEvent) { + SegmentViewEvent sve = (SegmentViewEvent)event; + String segmentCName = sve.getComponentName(); + Component clickedLink = mainVC.getComponent(segmentCName); + if (clickedLink == settingsLink) { + doOpenSettings(ureq); + } else if (clickedLink == certificatesLink) { + doOpenCertificatesList(ureq); + } } - } else if(cmc == source) { - cleanUp(); } - super.event(ureq, source, event); - } - - private void cleanUp() { - removeAsListenerAndDispose(uploadCtrl); - removeAsListenerAndDispose(cmc); - uploadCtrl = null; - cmc = null; - } - private void doConfirmDelete(UserRequest ureq, CertificateTemplate selectedTemplate) { - String title = translate("confirm.delete.title"); - String text = translate("confirm.delete.text"); - confirmDeleteCtrl = activateOkCancelDialog(ureq, title, text, confirmDeleteCtrl); - confirmDeleteCtrl.setUserObject(selectedTemplate); } - private void doDelete(CertificateTemplate template) { - certificatesManager.deleteTemplate(template); - updateDataModel(); - showInfo("confirm.certificate.template.deleted", template.getName()); - } - - private void doUpload(UserRequest ureq) { - removeAsListenerAndDispose(uploadCtrl); - removeAsListenerAndDispose(cmc); - - uploadCtrl = new UploadCertificateController(ureq, getWindowControl()); - listenTo(uploadCtrl); - - String title = translate("upload.title"); - cmc = new CloseableModalController(getWindowControl(), "close", uploadCtrl.getInitialComponent(), true, title); - listenTo(cmc); - cmc.activate(); - } - - private void doReplace(UserRequest ureq, CertificateTemplate template) { - removeAsListenerAndDispose(uploadCtrl); - removeAsListenerAndDispose(cmc); - - uploadCtrl = new UploadCertificateController(ureq, getWindowControl(), template); - listenTo(uploadCtrl); - - String title = translate("upload.title"); - cmc = new CloseableModalController(getWindowControl(), "close", uploadCtrl.getInitialComponent(), true, title); - listenTo(cmc); - cmc.activate(); - } - - public static enum Cols { - - name("template.name"); - - private final String i18n; - - private Cols(String i18n) { - this.i18n = i18n; - } - - public String i18n() { - return i18n; + private void doOpenSettings(UserRequest ureq) { + if(settingsCtrl == null) { + OLATResourceable ores = OresHelper.createOLATResourceableInstance("Certificates", 0l); + WindowControl bwControl = BusinessControlFactory.getInstance().createBusinessWindowControl(ores, null, getWindowControl()); + settingsCtrl = new CertificatesSettingsAdminController(ureq, bwControl); + listenTo(settingsCtrl); } + mainVC.put("segmentCmp", settingsCtrl.getInitialComponent()); } - private static class TemplatesDataModel extends DefaultFlexiTableDataModel<CertificateTemplate> { - - public TemplatesDataModel(FlexiTableColumnModel columnModel) { - super(columnModel); - } - - @Override - public DefaultFlexiTableDataModel<CertificateTemplate> createCopyWithEmptyList() { - return new TemplatesDataModel(getTableColumnModel()); - } - - @Override - public Object getValueAt(int row, int col) { - CertificateTemplate template = getObject(row); - switch(Cols.values()[col]) { - case name: return template.getName(); - } - return null; + private void doOpenCertificatesList(UserRequest ureq) { + if(certificatesCtrl == null) { + OLATResourceable ores = OresHelper.createOLATResourceableInstance("Certificates", 0l); + WindowControl bwControl = BusinessControlFactory.getInstance().createBusinessWindowControl(ores, null, getWindowControl()); + certificatesCtrl = new CertificatesListAdminController(ureq, bwControl); + listenTo(certificatesCtrl); } + mainVC.put("segmentCmp", certificatesCtrl.getInitialComponent()); } } diff --git a/src/main/java/org/olat/course/certificate/ui/CertificatesListAdminController.java b/src/main/java/org/olat/course/certificate/ui/CertificatesListAdminController.java new file mode 100644 index 0000000000000000000000000000000000000000..7f2f739288e97f615ffc49998be9d5cd5b128316 --- /dev/null +++ b/src/main/java/org/olat/course/certificate/ui/CertificatesListAdminController.java @@ -0,0 +1,218 @@ +/** + * <a href="http://www.openolat.org"> + * OpenOLAT - Online Learning and Training</a><br> + * <p> + * Licensed under the Apache License, Version 2.0 (the "License"); <br> + * you may not use this file except in compliance with the License.<br> + * You may obtain a copy of the License at the + * <a href="http://www.apache.org/licenses/LICENSE-2.0">Apache homepage</a> + * <p> + * Unless required by applicable law or agreed to in writing,<br> + * software distributed under the License is distributed on an "AS IS" BASIS, <br> + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. <br> + * See the License for the specific language governing permissions and <br> + * limitations under the License. + * <p> + * Initial code contributed and copyrighted by<br> + * frentix GmbH, http://www.frentix.com + * <p> + */ +package org.olat.course.certificate.ui; + +import java.util.List; + +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.FlexiTableElement; +import org.olat.core.gui.components.form.flexible.elements.FormLink; +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.elements.table.DefaultFlexiColumnModel; +import org.olat.core.gui.components.form.flexible.impl.elements.table.DefaultFlexiTableDataModel; +import org.olat.core.gui.components.form.flexible.impl.elements.table.FlexiTableColumnModel; +import org.olat.core.gui.components.form.flexible.impl.elements.table.FlexiTableDataModelFactory; +import org.olat.core.gui.components.form.flexible.impl.elements.table.SelectionEvent; +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.control.generic.closablewrapper.CloseableModalController; +import org.olat.core.gui.control.generic.modal.DialogBoxController; +import org.olat.core.gui.control.generic.modal.DialogBoxUIFactory; +import org.olat.course.certificate.CertificateTemplate; +import org.olat.course.certificate.CertificatesManager; +import org.springframework.beans.factory.annotation.Autowired; + +/** + * + * Initial date: 20.10.2014<br> + * @author srosse, stephane.rosse@frentix.com, http://www.frentix.com + * + */ +public class CertificatesListAdminController extends FormBasicController { + + private FormLink uploadLink; + private FlexiTableElement tableEl; + private TemplatesDataModel tableModel; + + private CloseableModalController cmc; + private UploadCertificateController uploadCtrl; + private DialogBoxController confirmDeleteCtrl; + + @Autowired + private CertificatesManager certificatesManager; + + public CertificatesListAdminController(UserRequest ureq, WindowControl wControl) { + super(ureq, wControl, "certificate_list"); + + initForm(ureq); + } + + @Override + protected void initForm(FormItemContainer formLayout, Controller listener, UserRequest ureq) { + + FlexiTableColumnModel tableColumnModel = FlexiTableDataModelFactory.createFlexiTableColumnModel(); + tableColumnModel.addFlexiColumnModel(new DefaultFlexiColumnModel(Cols.name.i18n(), Cols.name.ordinal())); + tableColumnModel.addFlexiColumnModel(new DefaultFlexiColumnModel("replace", translate("replace"), "replace")); + tableColumnModel.addFlexiColumnModel(new DefaultFlexiColumnModel("delete", translate("delete"), "delete")); + + tableModel = new TemplatesDataModel(tableColumnModel); + tableEl = uifactory.addTableElement(getWindowControl(), "templates", tableModel, getTranslator(), formLayout); + + uploadLink = uifactory.addFormLink("upload", formLayout, Link.BUTTON); + updateDataModel(); + } + + private void updateDataModel() { + List<CertificateTemplate> templates = certificatesManager.getTemplates(); + tableModel.setObjects(templates); + tableEl.reset(); + } + + @Override + protected void doDispose() { + // + } + + @Override + protected void formOK(UserRequest ureq) { + // + } + + @Override + protected void formInnerEvent(UserRequest ureq, FormItem source, FormEvent event) { + if(source == uploadLink) { + doUpload(ureq); + } else if(source == tableEl) { + SelectionEvent se = (SelectionEvent)event; + String cmd = se.getCommand(); + CertificateTemplate selectedTemplate = tableModel.getObject(se.getIndex()); + if("replace".equals(cmd)) { + doReplace(ureq, selectedTemplate); + } else if("delete".equals(cmd)) { + doConfirmDelete(ureq, selectedTemplate); + } + } + } + + @Override + protected void event(UserRequest ureq, Controller source, Event event) { + if(uploadCtrl == source) { + if(event == Event.DONE_EVENT) { + updateDataModel(); + } + cmc.deactivate(); + cleanUp(); + } else if(confirmDeleteCtrl == source) { + if(DialogBoxUIFactory.isOkEvent(event)) { + CertificateTemplate template = (CertificateTemplate)confirmDeleteCtrl.getUserObject(); + doDelete(template); + } + } else if(cmc == source) { + cleanUp(); + } + super.event(ureq, source, event); + } + + private void cleanUp() { + removeAsListenerAndDispose(uploadCtrl); + removeAsListenerAndDispose(cmc); + uploadCtrl = null; + cmc = null; + } + private void doConfirmDelete(UserRequest ureq, CertificateTemplate selectedTemplate) { + String title = translate("confirm.delete.title"); + String text = translate("confirm.delete.text"); + confirmDeleteCtrl = activateOkCancelDialog(ureq, title, text, confirmDeleteCtrl); + confirmDeleteCtrl.setUserObject(selectedTemplate); + } + + private void doDelete(CertificateTemplate template) { + certificatesManager.deleteTemplate(template); + updateDataModel(); + showInfo("confirm.certificate.template.deleted", template.getName()); + } + + private void doUpload(UserRequest ureq) { + removeAsListenerAndDispose(uploadCtrl); + removeAsListenerAndDispose(cmc); + + uploadCtrl = new UploadCertificateController(ureq, getWindowControl()); + listenTo(uploadCtrl); + + String title = translate("upload.title"); + cmc = new CloseableModalController(getWindowControl(), "close", uploadCtrl.getInitialComponent(), true, title); + listenTo(cmc); + cmc.activate(); + } + + private void doReplace(UserRequest ureq, CertificateTemplate template) { + removeAsListenerAndDispose(uploadCtrl); + removeAsListenerAndDispose(cmc); + + uploadCtrl = new UploadCertificateController(ureq, getWindowControl(), template); + listenTo(uploadCtrl); + + String title = translate("upload.title"); + cmc = new CloseableModalController(getWindowControl(), "close", uploadCtrl.getInitialComponent(), true, title); + listenTo(cmc); + cmc.activate(); + } + + public static enum Cols { + + name("template.name"); + + private final String i18n; + + private Cols(String i18n) { + this.i18n = i18n; + } + + public String i18n() { + return i18n; + } + } + + private static class TemplatesDataModel extends DefaultFlexiTableDataModel<CertificateTemplate> { + + public TemplatesDataModel(FlexiTableColumnModel columnModel) { + super(columnModel); + } + + @Override + public DefaultFlexiTableDataModel<CertificateTemplate> createCopyWithEmptyList() { + return new TemplatesDataModel(getTableColumnModel()); + } + + @Override + public Object getValueAt(int row, int col) { + CertificateTemplate template = getObject(row); + switch(Cols.values()[col]) { + case name: return template.getName(); + } + return null; + } + } +} diff --git a/src/main/java/org/olat/course/certificate/ui/CertificatesSettingsAdminController.java b/src/main/java/org/olat/course/certificate/ui/CertificatesSettingsAdminController.java new file mode 100644 index 0000000000000000000000000000000000000000..000c2bc4d55977127bfa12937e4e9a96c34e90b7 --- /dev/null +++ b/src/main/java/org/olat/course/certificate/ui/CertificatesSettingsAdminController.java @@ -0,0 +1,130 @@ +/** + * <a href="http://www.openolat.org"> + * OpenOLAT - Online Learning and Training</a><br> + * <p> + * Licensed under the Apache License, Version 2.0 (the "License"); <br> + * you may not use this file except in compliance with the License.<br> + * You may obtain a copy of the License at the + * <a href="http://www.apache.org/licenses/LICENSE-2.0">Apache homepage</a> + * <p> + * Unless required by applicable law or agreed to in writing,<br> + * software distributed under the License is distributed on an "AS IS" BASIS, <br> + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. <br> + * See the License for the specific language governing permissions and <br> + * limitations under the License. + * <p> + * Initial code contributed and copyrighted by<br> + * frentix GmbH, http://www.frentix.com + * <p> + */ +package org.olat.course.certificate.ui; + +import java.util.List; + +import org.olat.core.gui.UserRequest; +import org.olat.core.gui.components.form.flexible.FormItem; +import org.olat.core.gui.components.form.flexible.FormItemContainer; +import org.olat.core.gui.components.form.flexible.elements.MultipleSelectionElement; +import org.olat.core.gui.components.form.flexible.elements.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.control.Controller; +import org.olat.core.gui.control.WindowControl; +import org.olat.core.util.StringHelper; +import org.olat.core.util.mail.EmailAddressValidator; +import org.olat.course.certificate.CertificatesModule; +import org.springframework.beans.factory.annotation.Autowired; + +/** + * + * Initial date: 31 janv. 2017<br> + * @author srosse, stephane.rosse@frentix.com, http://www.frentix.com + * + */ +public class CertificatesSettingsAdminController extends FormBasicController { + + private static final String[] onKeys = new String[]{ "on" }; + private static final String[] onValues = new String[]{ "" }; + + private TextElement bccEl; + private MultipleSelectionElement enableBccEl; + + @Autowired + private CertificatesModule certificatesModule; + + /** + * @param name + * @param chatEnabled + */ + public CertificatesSettingsAdminController(UserRequest ureq, WindowControl wControl) { + super(ureq, wControl); + initForm (ureq); + } + + @Override + protected void doDispose() { + // + } + + @Override + protected void initForm(FormItemContainer formLayout, Controller listener, UserRequest ureq) { + setFormTitle("admin.certificates.options.title"); + setFormDescription("admin.certificates.options.descr", null); + + String bcc = certificatesModule.getCertificateBcc(); + enableBccEl = uifactory.addCheckboxesHorizontal("enableBcc", "admin.certificates.bcc.enable", formLayout, onKeys, onValues); + enableBccEl.addActionListener(FormEvent.ONCHANGE); + if(StringHelper.containsNonWhitespace(bcc)) { + enableBccEl.select(onKeys[0], true); + } + + bccEl = uifactory.addTextElement("bcc", "admin.certificates.bcc", 1024, bcc, formLayout); + bccEl.setVisible(enableBccEl.isAtLeastSelected(1)); + + FormLayoutContainer buttonsCont = FormLayoutContainer.createButtonLayout("buttons", getTranslator()); + formLayout.add(buttonsCont); + uifactory.addFormSubmitButton("save", buttonsCont); + } + + @Override + protected boolean validateFormLogic(UserRequest ureq) { + boolean allOk = true; + + bccEl.clearError(); + if(enableBccEl.isAtLeastSelected(1)) { + String emails = bccEl.getValue(); + if(!StringHelper.containsNonWhitespace(emails)) { + bccEl.setErrorKey("form.legende.mandatory", null); + allOk &= false; + } else { + List<String> emailList = certificatesModule.splitEmails(bccEl.getValue()); + for(String email:emailList) { + if(!EmailAddressValidator.isValidEmailAddress(email)) { + bccEl.setErrorKey("error.mail.invalid", null); + allOk &= false; + } + } + } + } + + return allOk & super.validateFormLogic(ureq); + } + + @Override + protected void formInnerEvent(UserRequest ureq, FormItem source, FormEvent event) { + if(enableBccEl == source) { + bccEl.setVisible(enableBccEl.isAtLeastSelected(1)); + } + super.formInnerEvent(ureq, source, event); + } + + @Override + protected void formOK(UserRequest ureq) { + if(enableBccEl.isAtLeastSelected(1)) { + certificatesModule.setCertificateBcc(bccEl.getValue()); + } else { + certificatesModule.setCertificateBcc(""); + } + } +} \ No newline at end of file diff --git a/src/main/java/org/olat/course/certificate/ui/_content/admin_certificates.html b/src/main/java/org/olat/course/certificate/ui/_content/admin_certificates.html index 0a2f30dbade1a2ede56934ea4fdaee12fcdcd6dc..c0fa0f020aabd1a909b24574f4c20152e418303b 100644 --- a/src/main/java/org/olat/course/certificate/ui/_content/admin_certificates.html +++ b/src/main/java/org/olat/course/certificate/ui/_content/admin_certificates.html @@ -1,11 +1,4 @@ -<fieldset> - <legend> - $r.translate("admin.certificates.title")</legend> - <div class="o_desc">$r.translate("admin.certificates.description")</div> - - $r.render("templates") - - <div class="o_button_group"> - $r.render("upload") - </div> -</fieldset> \ No newline at end of file +$r.render("segments") +<div class="o_segments_content clearfix"> + $r.render("segmentCmp") +</div> \ No newline at end of file diff --git a/src/main/java/org/olat/course/certificate/ui/_content/certificate_list.html b/src/main/java/org/olat/course/certificate/ui/_content/certificate_list.html new file mode 100644 index 0000000000000000000000000000000000000000..57f50c9a1ab8efc9fd542f91b840df1138c56ebf --- /dev/null +++ b/src/main/java/org/olat/course/certificate/ui/_content/certificate_list.html @@ -0,0 +1,7 @@ +<fieldset class="o_form"> + <div class="o_info">$r.translate("admin.certificates.description")</div> + $r.render("templates") + <div class="o_button_group"> + $r.render("upload") + </div> +</fieldset> \ No newline at end of file diff --git a/src/main/java/org/olat/course/certificate/ui/_i18n/LocalStrings_de.properties b/src/main/java/org/olat/course/certificate/ui/_i18n/LocalStrings_de.properties index 6f3de54bab14fbdbcaae227df50745f4132a38fb..6af7fea5d386db4e218a78b70798eff7dfd7171d 100644 --- a/src/main/java/org/olat/course/certificate/ui/_i18n/LocalStrings_de.properties +++ b/src/main/java/org/olat/course/certificate/ui/_i18n/LocalStrings_de.properties @@ -2,6 +2,12 @@ admin.menu.title=Zertifikate admin.menu.title.alt=Zertifikate einstellen admin.certificates.title=Zertifikate admin.certificates.description=Laden Sie PDF-Formulare als Vorlagen f\u00FCr OpenOLAT Kurszertifikate hoch. +admin.certificates.settings=Zertifikate Konfiguration +admin.certificates.templates=Zertifikate Vorlage +admin.certificates.options.title=Konfiguration +admin.certificates.options.descr=Zertifikate k\u00F6nnen an eine E-Mail-Adresse geschickt werden, zum Beispiel der Personalabteilung. Schaltet die Option an und f\u00FCllen Sie die gew\u00FCnschte Adresse ein. +admin.certificates.bcc=BCC E-Mail-Adresse +admin.certificates.bcc.enable=Zertifikate BCC einschalten certificate=Zertifikate certificate.creationdate=Zertifikat ausgestellt am {0} coaching.tool=Coaching @@ -13,7 +19,7 @@ default.template=Standardvorlage details.certificate=Zertifikat details.course.infos=Kursdetails download.button=Zertifikat herunterladen - +error.mail.invalid=Bitte geben Sie eine g\u00FCltige E-Mailadresse an. options.certificates.title=Konfiguration Leistungnachweis options.certificates.descr=Damit Kurse als bestanden angezeigt werden k\u00F6nnen, muss im Kurshauptknoten zwingend im "Punkte"-Tab die Option <strong>Bestanden berechnen?</strong> aktiviert werden. diff --git a/src/main/java/org/olat/course/certificate/ui/_i18n/LocalStrings_en.properties b/src/main/java/org/olat/course/certificate/ui/_i18n/LocalStrings_en.properties index c754e85dce250765dd278e68939b8b7e094ca7a5..d97f120c082ae6df28c6d5d38d5a31999a2617cc 100644 --- a/src/main/java/org/olat/course/certificate/ui/_i18n/LocalStrings_en.properties +++ b/src/main/java/org/olat/course/certificate/ui/_i18n/LocalStrings_en.properties @@ -3,6 +3,12 @@ admin.certificates.description=Upload PDF forms as templates for the course cert admin.certificates.title=Certificates admin.menu.title=Certificates admin.menu.title.alt=Certificates configuration +admin.certificates.settings=Certificates configuration +admin.certificates.templates=Templates for certificates +admin.certificates.options.title=Configuration +admin.certificates.options.descr=Certificates can be sent to an email address e.g. to the HR department. Enable this option and fill in the desired email address. +admin.certificates.bcc=BCC email address +admin.certificates.bcc.enable=Enable BCC of certificates certificate=Certificates certificate.creationdate=Certificate issued on {0} certificates.wizard.overview=Overview @@ -10,7 +16,7 @@ certificates.wizard.select=Select user certificates.wizard.title=Create certificates certification.email.body=Congratulations\!\r\n\r\nYou have received a certification.\r\nPlease find attached the certificate to the course "{0}". certification.email.subject=You have received an OpenOLAT certification - +error.mail.invalid=Please provide a valid e-mail address. choose.title=Select template coaching.tool=Coaching confirm.certificate.deleted=The certificate from {0} was deleted. diff --git a/src/main/java/org/olat/course/certificate/ui/_i18n/LocalStrings_fr.properties b/src/main/java/org/olat/course/certificate/ui/_i18n/LocalStrings_fr.properties index 759d62708dbbf7c30b53054cae009b0114d86110..3b5698f7eb41daa49dfef87029b0c08282038161 100644 --- a/src/main/java/org/olat/course/certificate/ui/_i18n/LocalStrings_fr.properties +++ b/src/main/java/org/olat/course/certificate/ui/_i18n/LocalStrings_fr.properties @@ -24,6 +24,7 @@ default.template=Mod\u00E8le par d\u00E9faut details.certificate=Certificat details.course.infos=D\u00E9tails du cours download.button=T\u00E9l\u00E9charger le certificat +error.mail.invalid=Indiquez une adresse courriel valide, svp. format=Format generate.certificate=G\u00E9n\u00E9rer un certificat landscape=Paysage diff --git a/src/main/resources/serviceconfig/olat.properties b/src/main/resources/serviceconfig/olat.properties index 6910d024b357977e21eb28ab7f848d17e08be35b..045d530515d4cffe42be13b32c26bc54f4d5bcaf 100644 --- a/src/main/resources/serviceconfig/olat.properties +++ b/src/main/resources/serviceconfig/olat.properties @@ -326,6 +326,11 @@ onyx.plugin.exammodelocation=${onyx.plugin.wslocation}/onyxexamservices ### set or overwrite this switch to "true" if this olat-node is either a single-node or should be the controlling entity in a clustered-olat exam.mode.masternode=true +######################################################################## +# Certificates +######################################################################## +# Send a copy of the certificates mails to someone +certificate.bcc= ##### # Help course and context help