Skip to content
Snippets Groups Projects
Commit 4aabf29c authored by srosse's avatar srosse
Browse files

OO-2057: add invitation and mails

parent 09eba4ec
No related branches found
No related tags found
No related merge requests found
Showing
with 707 additions and 57 deletions
......@@ -68,6 +68,10 @@ public class BinderConfiguration {
return new BinderConfiguration(false, false, false);
}
public static BinderConfiguration createInvitationConfig() {
return new BinderConfiguration(false, false, false);
}
public static BinderConfiguration createMyPagesConfig() {
return new BinderConfiguration(false, false, false);
}
......
/**
* <a href="http://www.openolat.org">
* OpenOLAT - Online Learning and Training</a><br>
* <p>
* Licensed under the Apache License, Version 2.0 (the "License"); <br>
* you may not use this file except in compliance with the License.<br>
* You may obtain a copy of the License at the
* <a href="http://www.apache.org/licenses/LICENSE-2.0">Apache homepage</a>
* <p>
* Unless required by applicable law or agreed to in writing,<br>
* software distributed under the License is distributed on an "AS IS" BASIS, <br>
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. <br>
* See the License for the specific language governing permissions and <br>
* limitations under the License.
* <p>
* Initial code contributed and copyrighted by<br>
* frentix GmbH, http://www.frentix.com
* <p>
*/
package org.olat.modules.portfolio;
import java.util.List;
import org.olat.core.CoreSpringFactory;
import org.olat.core.commons.fullWebApp.LayoutMain3ColsController;
import org.olat.core.gui.UserRequest;
import org.olat.core.gui.control.Controller;
import org.olat.core.gui.control.WindowControl;
import org.olat.core.id.context.ContextEntry;
import org.olat.core.id.context.ContextEntryControllerCreator;
import org.olat.core.id.context.DefaultContextEntryControllerCreator;
import org.olat.modules.portfolio.ui.PortfolioInvitationController;
/**
*
* Initial date: 29.06.2016<br>
* @author srosse, stephane.rosse@frentix.com, http://www.frentix.com
*
*/
public class BinderInvitationContextEntryControllerCreator extends DefaultContextEntryControllerCreator {
private Binder cachedBinder;
@Override
public ContextEntryControllerCreator clone() {
return new BinderInvitationContextEntryControllerCreator();
}
@Override
public Controller createController(List<ContextEntry> ces, UserRequest ureq, WindowControl wControl) {
if(!ureq.getUserSession().getRoles().isInvitee()) {
return null;
}
Binder binder = getBinderFromContext(ces.get(0));
BinderConfiguration config = BinderConfiguration.createInvitationConfig();
BinderSecurityCallback secCallback = BinderSecurityCallbackFactory.getCallbackForInvitation();
Controller binderCtrl = new PortfolioInvitationController(ureq, wControl, secCallback, binder, config);
LayoutMain3ColsController layoutCtr = new LayoutMain3ColsController(ureq, wControl, binderCtrl);
layoutCtr.addDisposableChildController(binderCtrl);
return layoutCtr;
}
@Override
public String getTabName(ContextEntry ce, UserRequest ureq) {
Binder binder = getBinderFromContext(ce);
if(binder != null) {
return binder.getTitle();
}
return null;
}
@Override
public boolean validateContextEntryAndShowError(ContextEntry ce, UserRequest ureq, WindowControl wControl) {
if(!ureq.getUserSession().getRoles().isInvitee()) {
return false;
}
Binder binder = getBinderFromContext(ce);
if (binder == null) {
return false;
}
final PortfolioService portfolioService = CoreSpringFactory.getImpl(PortfolioService.class);
boolean visible = portfolioService.isBinderVisible(ureq.getIdentity(), binder);
return visible;
}
/**
* @param ContextEntry
* @return the loaded map or null if not found
*/
private Binder getBinderFromContext(final ContextEntry ce) {
if(cachedBinder == null) {
Long mapKey = ce.getOLATResourceable().getResourceableId();
cachedBinder = CoreSpringFactory.getImpl(PortfolioService.class).getBinderByKey(mapKey);
}
return cachedBinder;
}
}
\ No newline at end of file
......@@ -53,7 +53,19 @@ public class BinderSecurityCallbackFactory {
return new BinderSecurityCallbackImpl(rights);
}
private static class BinderSecurityCallbackForTemplate implements BinderSecurityCallback {
public static final BinderSecurityCallback getCallbackForInvitation() {
return new BinderSecurityCallbackForInvitation();
}
private static class BinderSecurityCallbackForInvitation extends DefaultBinderSecurityCallback {
@Override
public boolean canComment(PortfolioElement element) {
return true;
}
}
private static class BinderSecurityCallbackForTemplate extends DefaultBinderSecurityCallback {
private final boolean admin;
......@@ -80,46 +92,6 @@ public class BinderSecurityCallbackFactory {
public boolean canEditSection() {
return admin;
}
@Override
public boolean canAddPage() {
return false;
}
@Override
public boolean canEditPage(Page page) {
return false;
}
@Override
public boolean canPublish(Page page) {
return false;
}
@Override
public boolean canEditAccessRights(PortfolioElement element) {
return false;
}
@Override
public boolean canViewElement(PortfolioElement element) {
return false;
}
@Override
public boolean canComment(PortfolioElement element) {
return false;
}
@Override
public boolean canReview(PortfolioElement element) {
return false;
}
@Override
public boolean canAssess(Section section) {
return false;
}
}
private static class BinderSecurityCallbackImpl implements BinderSecurityCallback {
......@@ -231,4 +203,67 @@ public class BinderSecurityCallbackFactory {
return false;
}
}
private static class DefaultBinderSecurityCallback implements BinderSecurityCallback {
@Override
public boolean canEditBinder() {
return false;
}
@Override
public boolean canEditMetadataBinder() {
return false;
}
@Override
public boolean canAddSection() {
return false;
}
@Override
public boolean canEditSection() {
return false;
}
@Override
public boolean canAddPage() {
return false;
}
@Override
public boolean canEditPage(Page page) {
return false;
}
@Override
public boolean canPublish(Page page) {
return false;
}
@Override
public boolean canEditAccessRights(PortfolioElement element) {
return false;
}
@Override
public boolean canViewElement(PortfolioElement element) {
return false;
}
@Override
public boolean canComment(PortfolioElement element) {
return false;
}
@Override
public boolean canReview(PortfolioElement element) {
return false;
}
@Override
public boolean canAssess(Section section) {
return false;
}
}
}
\ No newline at end of file
......@@ -28,7 +28,8 @@ package org.olat.modules.portfolio;
public enum PortfolioRoles {
owner,//same as GroupRoles.owner
coach,
coach,//same as GroupRoles.coach
reviewer,
invitee,//same as GroupRoles.invitee
}
......@@ -84,6 +84,14 @@ public interface PortfolioService {
*/
public List<AssessedBinder> searchSharedBindersWith(Identity coach);
/**
*
* @param identity
* @param binder
* @return
*/
public boolean isBinderVisible(Identity identity, Binder binder);
/**
* Search all the binders which the specified identity shared
* with some people.
......
......@@ -19,6 +19,7 @@
*/
package org.olat.modules.portfolio;
import org.olat.NewControllerFactory;
import org.olat.core.configuration.AbstractSpringModule;
import org.olat.core.configuration.ConfigOnOff;
import org.olat.core.util.StringHelper;
......@@ -56,7 +57,8 @@ public class PortfolioV2Module extends AbstractSpringModule implements ConfigOnO
enabled = "true".equals(enabledObj);
}
RepositoryHandlerFactory.registerHandler(new BinderTemplateHandler(), 10);
RepositoryHandlerFactory.registerHandler(new BinderTemplateHandler(), 40);
NewControllerFactory.getInstance().addContextEntryControllerCreator("BinderInvitation", new BinderInvitationContextEntryControllerCreator());
}
@Override
......
......@@ -263,6 +263,11 @@ public class PortfolioServiceImpl implements PortfolioService {
return binderDao.getMembers(binder, roles);
}
@Override
public boolean isBinderVisible(Identity identity, Binder binder) {
return true;
}
@Override
public List<AccessRights> getAccessRights(Binder binder) {
List<AccessRights> rights = binderDao.getBinderAccesRights(binder, null);
......
/**
* <a href="http://www.openolat.org">
* OpenOLAT - Online Learning and Training</a><br>
* <p>
* Licensed under the Apache License, Version 2.0 (the "License"); <br>
* you may not use this file except in compliance with the License.<br>
* You may obtain a copy of the License at the
* <a href="http://www.apache.org/licenses/LICENSE-2.0">Apache homepage</a>
* <p>
* Unless required by applicable law or agreed to in writing,<br>
* software distributed under the License is distributed on an "AS IS" BASIS, <br>
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. <br>
* See the License for the specific language governing permissions and <br>
* limitations under the License.
* <p>
* Initial code contributed and copyrighted by<br>
* frentix GmbH, http://www.frentix.com
* <p>
*/
package org.olat.modules.portfolio.ui;
import org.olat.basesecurity.BaseSecurity;
import org.olat.basesecurity.Constants;
import org.olat.basesecurity.Invitation;
import org.olat.basesecurity.SecurityGroup;
import org.olat.core.gui.UserRequest;
import org.olat.core.gui.components.form.flexible.FormItemContainer;
import org.olat.core.gui.components.form.flexible.elements.StaticTextElement;
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.FormLayoutContainer;
import org.olat.core.gui.control.Controller;
import org.olat.core.gui.control.Event;
import org.olat.core.gui.control.WindowControl;
import org.olat.core.helpers.Settings;
import org.olat.core.id.Identity;
import org.olat.core.id.UserConstants;
import org.olat.core.util.StringHelper;
import org.olat.core.util.WebappHelper;
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.MailHelper;
import org.olat.core.util.mail.MailManager;
import org.olat.core.util.mail.MailerResult;
import org.olat.modules.portfolio.Binder;
import org.olat.portfolio.manager.InvitationDAO;
import org.olat.user.UserManager;
import org.springframework.beans.factory.annotation.Autowired;
/**
*
* Initial date: 29.06.2016<br>
* @author srosse, stephane.rosse@frentix.com, http://www.frentix.com
*
*/
public class AddInvitationRightsController extends FormBasicController {
private TextElement firstNameEl, lastNameEl, mailEl;
private Binder binder;
private Invitation invitation;
@Autowired
private MailManager mailManager;
@Autowired
private UserManager userManager;
@Autowired
private InvitationDAO invitationDao;
@Autowired
private BaseSecurity securityManager;
public AddInvitationRightsController(UserRequest ureq, WindowControl wControl, Binder binder) {
super(ureq, wControl);
this.binder = binder;
invitation = invitationDao.createInvitation();
initForm(ureq);
}
@Override
protected void initForm(FormItemContainer formLayout, Controller listener, UserRequest ureq) {
firstNameEl = uifactory.addTextElement("firstName", "firstName", 64, invitation.getFirstName(), formLayout);
firstNameEl.setMandatory(true);
lastNameEl = uifactory.addTextElement("lastName", "lastName", 64, invitation.getLastName(), formLayout);
lastNameEl.setMandatory(true);
mailEl = uifactory.addTextElement("mail", "mail", 128, invitation.getMail(), formLayout);
mailEl.setMandatory(true);
mailEl.setNotEmptyCheck("map.share.empty.warn");
if(StringHelper.containsNonWhitespace(invitation.getMail()) && MailHelper.isValidEmailAddress(invitation.getMail())) {
SecurityGroup allUsers = securityManager.findSecurityGroupByName(Constants.GROUP_OLATUSERS);
Identity currentIdentity = userManager.findIdentityByEmail(invitation.getMail());
if(currentIdentity != null && securityManager.isIdentityInSecurityGroup(currentIdentity, allUsers)) {
mailEl.setErrorKey("map.share.with.mail.error.olatUser", new String[]{ invitation.getMail() });
}
}
String link = getInvitationLink();
StaticTextElement linkEl = uifactory.addStaticTextElement("invitation.link" , link, formLayout);
linkEl.setLabel("invitation.link", null);
FormLayoutContainer buttonsCont = FormLayoutContainer.createButtonLayout("buttons", getTranslator());
formLayout.add(buttonsCont);
buttonsCont.setRootForm(mainForm);
uifactory.addFormCancelButton("cancel", buttonsCont, ureq, getWindowControl());
uifactory.addFormSubmitButton("save", buttonsCont);
}
private String getInvitationLink() {
return Settings.getServerContextPathURI() + "/url/BinderInvitation/" + binder.getKey() + "?invitation=" + invitation.getToken();
}
@Override
protected void doDispose() {
//
}
@Override
protected boolean validateFormLogic(UserRequest ureq) {
boolean allOk = true;
if (mailEl != null) {
String mail = mailEl.getValue();
if (StringHelper.containsNonWhitespace(mail)) {
if (MailHelper.isValidEmailAddress(mail)) {
SecurityGroup allUsers = securityManager.findSecurityGroupByName(Constants.GROUP_OLATUSERS);
Identity currentIdentity = userManager.findIdentityByEmail(mail);
if (currentIdentity != null && securityManager.isIdentityInSecurityGroup(currentIdentity, allUsers)) {
mailEl.setErrorKey("map.share.with.mail.error.olatUser", new String[] { mail });
allOk &= false;
}
} else {
mailEl.setErrorKey("error.mail.invalid", null);
allOk &= false;
}
} else {
mailEl.setErrorKey("form.legende.mandatory", null);
allOk &= false;
}
}
return allOk & super.validateFormLogic(ureq);
}
@Override
protected void formOK(UserRequest ureq) {
invitation.setFirstName(firstNameEl.getValue());
invitation.setLastName(lastNameEl.getValue());
invitation.setMail(mailEl.getValue());
if(invitation.getKey() == null) {
Identity invitee = invitationDao.createIdentityAndPersistInvitation(invitation, binder.getBaseGroup(), getLocale());
sendInvitation(invitee);
fireEvent(ureq, Event.DONE_EVENT);
} else {
invitationDao.update(invitation);
fireEvent(ureq, Event.CHANGED_EVENT);
}
}
@Override
protected void formCancelled(UserRequest ureq) {
fireEvent(ureq, Event.CANCELLED_EVENT);
}
private void sendInvitation(Identity invitee) {
String inviteeEmail = invitee.getUser().getProperty(UserConstants.EMAIL, getLocale());
ContactList contactList = new ContactList(inviteeEmail);
contactList.add(inviteeEmail);
String busLink = getInvitationLink();
boolean success = false;
try {
String first = getIdentity().getUser().getProperty(UserConstants.FIRSTNAME, null);
String last = getIdentity().getUser().getProperty(UserConstants.LASTNAME, null);
String sender = first + " " + last;
String[] bodyArgs = new String[]{busLink, sender};
MailContext context = new MailContextImpl(binder, null, getWindowControl().getBusinessControl().getAsString());
MailBundle bundle = new MailBundle();
bundle.setContext(context);
bundle.setFrom(WebappHelper.getMailConfig("mailReplyTo"));
bundle.setContactList(contactList);
bundle.setContent(translate("invitation.mail.subject"), translate("invitation.mail.body", bodyArgs));
MailerResult result = mailManager.sendExternMessage(bundle, null, true);
success = result.isSuccessful();
} catch (Exception e) {
logError("Error on sending invitation mail to contactlist, invalid address.", e);
}
if (success) {
showInfo("invitation.mail.success");
} else {
showError("invitation.mail.failure");
}
}
}
/**
* <a href="http://www.openolat.org">
* OpenOLAT - Online Learning and Training</a><br>
* <p>
* Licensed under the Apache License, Version 2.0 (the "License"); <br>
* you may not use this file except in compliance with the License.<br>
* You may obtain a copy of the License at the
* <a href="http://www.apache.org/licenses/LICENSE-2.0">Apache homepage</a>
* <p>
* Unless required by applicable law or agreed to in writing,<br>
* software distributed under the License is distributed on an "AS IS" BASIS, <br>
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. <br>
* See the License for the specific language governing permissions and <br>
* limitations under the License.
* <p>
* Initial code contributed and copyrighted by<br>
* frentix GmbH, http://www.frentix.com
* <p>
*/
package org.olat.modules.portfolio.ui;
import java.util.List;
import org.olat.core.gui.UserRequest;
import org.olat.core.gui.components.Component;
import org.olat.core.gui.components.stack.TooledStackedPanel;
import org.olat.core.gui.control.Event;
import org.olat.core.gui.control.WindowControl;
import org.olat.core.gui.control.controller.BasicController;
import org.olat.core.gui.control.generic.dtabs.Activateable2;
import org.olat.core.id.OLATResourceable;
import org.olat.core.id.context.ContextEntry;
import org.olat.core.id.context.StateEntry;
import org.olat.core.util.resource.OresHelper;
import org.olat.home.ReusableHomeController;
import org.olat.modules.portfolio.Binder;
import org.olat.modules.portfolio.BinderConfiguration;
import org.olat.modules.portfolio.BinderSecurityCallback;
/**
*
* Initial date: 29.06.2016<br>
* @author srosse, stephane.rosse@frentix.com, http://www.frentix.com
*
*/
public class PortfolioInvitationController extends BasicController implements Activateable2, ReusableHomeController {
private final TooledStackedPanel stackPanel;
private final BinderController binderCtrl;
public PortfolioInvitationController(UserRequest ureq, WindowControl wControl,
BinderSecurityCallback secCallback, Binder binder, BinderConfiguration config) {
super(ureq, wControl);
stackPanel = new TooledStackedPanel("portfolioStackPanel", getTranslator(), this);
stackPanel.setToolbarAutoEnabled(true);
stackPanel.setShowCloseLink(true, true);
stackPanel.setInvisibleCrumb(0);
putInitialPanel(stackPanel);
OLATResourceable ores = OresHelper.createOLATResourceableInstance("PortfolioV2", 0l);
WindowControl swControl = addToHistory(ureq, ores, null, getWindowControl(), true);
binderCtrl = new BinderController(ureq, swControl, stackPanel, secCallback, binder, config);
listenTo(binderCtrl);
stackPanel.pushController(translate("portfolio.root.breadcrump"), binderCtrl);
stackPanel.setCssClass("o_portfolio");
}
@Override
protected void doDispose() {
//
}
@Override
public void activate(UserRequest ureq, List<ContextEntry> entries, StateEntry state) {
if(binderCtrl != null) {
binderCtrl.activate(ureq, entries, state);
}
}
@Override
protected void event(UserRequest ureq, Component source, Event event) {
//
}
}
......@@ -27,6 +27,8 @@ import java.util.Map;
import org.olat.core.gui.UserRequest;
import org.olat.core.gui.components.Component;
import org.olat.core.gui.components.dropdown.Dropdown;
import org.olat.core.gui.components.dropdown.DropdownOrientation;
import org.olat.core.gui.components.link.Link;
import org.olat.core.gui.components.link.LinkFactory;
import org.olat.core.gui.components.stack.TooledController;
......@@ -43,6 +45,14 @@ import org.olat.core.gui.control.generic.wizard.StepRunnerCallback;
import org.olat.core.gui.control.generic.wizard.StepsMainRunController;
import org.olat.core.gui.control.generic.wizard.StepsRunContext;
import org.olat.core.id.Identity;
import org.olat.core.util.WebappHelper;
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.MailManager;
import org.olat.core.util.mail.MailTemplate;
import org.olat.core.util.mail.MailerResult;
import org.olat.modules.portfolio.AssessmentSection;
import org.olat.modules.portfolio.Binder;
import org.olat.modules.portfolio.BinderConfiguration;
......@@ -70,11 +80,13 @@ import org.springframework.beans.factory.annotation.Autowired;
*/
public class PublishController extends BasicController implements TooledController {
private Link addAccessRightsLink;
private Dropdown accessDropdown;
private Link addAccessRightsLink, addInvitationLink;
private final VelocityContainer mainVC;
private final TooledStackedPanel stackPanel;
private CloseableModalController cmc;
private AddInvitationRightsController addInvitationCtrl;
private AccessRightsEditController editAccessRightsCtrl;
private StepsMainRunController addMembersWizard;
......@@ -84,6 +96,8 @@ public class PublishController extends BasicController implements TooledControll
private final BinderConfiguration config;
private final BinderSecurityCallback secCallback;
@Autowired
private MailManager mailManager;
@Autowired
private UserManager userManager;
@Autowired
......@@ -109,9 +123,19 @@ public class PublishController extends BasicController implements TooledControll
@Override
public void initTools() {
if(secCallback.canEditAccessRights(binder)) {
accessDropdown = new Dropdown("access.rights", "access.rights", false, getTranslator());
accessDropdown.setIconCSS("o_icon o_icon-fw o_icon_new_portfolio");
accessDropdown.setOrientation(DropdownOrientation.right);
addAccessRightsLink = LinkFactory.createToolLink("add.member", translate("add.member"), this);
addAccessRightsLink.setIconLeftCSS("o_icon o_icon-lg o_icon_new_portfolio");
stackPanel.addTool(addAccessRightsLink, Align.right);
accessDropdown.addComponent(addAccessRightsLink);
addInvitationLink = LinkFactory.createToolLink("add.invitation", translate("add.invitation"), this);
addInvitationLink.setIconLeftCSS("o_icon o_icon-lg o_icon_new_portfolio");
accessDropdown.addComponent(addInvitationLink);
stackPanel.addTool(accessDropdown, Align.right);
}
}
......@@ -129,7 +153,9 @@ public class PublishController extends BasicController implements TooledControll
for(AccessRights right:rights) {
if(right.getSectionKey() == null && right.getPageKey() == null) {
Link editLink = null;
if(canEditBinderAccessRights && !PortfolioRoles.owner.equals(right.getRole())) {
if(canEditBinderAccessRights
&& !PortfolioRoles.owner.equals(right.getRole())
&&!PortfolioRoles.invitee.equals(right.getRole())) {
editLink = LinkFactory.createLink("edit_" + (counter++), "edit", "edit_access", mainVC, this);
}
binderRow.getAccessRights().add(new AccessRightsRow(binder, right, editLink));
......@@ -182,12 +208,16 @@ public class PublishController extends BasicController implements TooledControll
}
}
}
mainVC.setDirty(true);
}
@Override
protected void event(UserRequest ureq, Component source, Event event) {
if(addAccessRightsLink == source) {
doAddAccessRights(ureq);
} else if(addInvitationLink == source) {
doAddInvitation(ureq);
} else if(source instanceof Link) {
Link link = (Link)source;
String cmd = link.getCommand();
......@@ -208,6 +238,14 @@ public class PublishController extends BasicController implements TooledControll
}
cleanUp();
}
} else if(addInvitationCtrl == source) {
if(event == Event.CANCELLED_EVENT || event == Event.DONE_EVENT || event == Event.CHANGED_EVENT) {
getWindowControl().pop();
if(event == Event.DONE_EVENT || event == Event.CHANGED_EVENT) {
reloadData();
}
cleanUp();
}
} else if(editAccessRightsCtrl == source) {
if(event == Event.DONE_EVENT) {
List<AccessRightChange> changes = editAccessRightsCtrl.getChanges();
......@@ -225,13 +263,27 @@ public class PublishController extends BasicController implements TooledControll
private void cleanUp() {
removeAsListenerAndDispose(editAccessRightsCtrl);
removeAsListenerAndDispose(addInvitationCtrl);
removeAsListenerAndDispose(addMembersWizard);
removeAsListenerAndDispose(cmc);
editAccessRightsCtrl = null;
addInvitationCtrl = null;
addMembersWizard = null;
cmc = null;
}
private void doAddInvitation(UserRequest ureq) {
if(addInvitationCtrl != null) return;
addInvitationCtrl = new AddInvitationRightsController(ureq, getWindowControl(), binder);
listenTo(addInvitationCtrl);
String title = translate("add.invitation");
cmc = new CloseableModalController(getWindowControl(), null, addInvitationCtrl.getInitialComponent(), true, title, true);
listenTo(cmc);
cmc.activate();
}
private void doEditAccessRights(UserRequest ureq, PortfolioElement element, Identity member) {
if(editAccessRightsCtrl != null) return;
......@@ -253,7 +305,8 @@ public class PublishController extends BasicController implements TooledControll
@Override
public Step execute(UserRequest uureq, WindowControl wControl, StepsRunContext runContext) {
AccessRightsContext rightsContext = (AccessRightsContext)runContext.get("rightsContext");
addMembers(rightsContext);
MailTemplate mailTemplate = (MailTemplate)runContext.get("mailTemplate");
addMembers(rightsContext, mailTemplate);
return StepsMainRunController.DONE_MODIFIED;
}
};
......@@ -265,13 +318,41 @@ public class PublishController extends BasicController implements TooledControll
}
private void addMembers(AccessRightsContext rightsContext) {
private void addMembers(AccessRightsContext rightsContext, MailTemplate mailTemplate) {
List<Identity> identities = rightsContext.getIdentities();
List<AccessRightChange> changes = rightsContext.getAccessRightChanges();
portfolioService.changeAccessRights(identities, changes);
if(mailTemplate != null) {
sendInvitation(identities, mailTemplate);
}
reloadData();
}
private void sendInvitation(List<Identity> identities, MailTemplate mailTemplate) {
ContactList contactList = new ContactList("Invitation");
contactList.addAllIdentites(identities);
boolean success = false;
try {
MailContext context = new MailContextImpl(binder, null, getWindowControl().getBusinessControl().getAsString());
MailBundle bundle = new MailBundle();
bundle.setContext(context);
bundle.setFrom(WebappHelper.getMailConfig("mailReplyTo"));
bundle.setContactList(contactList);
bundle.setContent(mailTemplate.getSubjectTemplate(), mailTemplate.getBodyTemplate());
MailerResult result = mailManager.sendMessage(bundle);
success = result.isSuccessful();
} catch (Exception e) {
logError("Error on sending invitation mail to contactlist, invalid address.", e);
}
if (success) {
showInfo("invitation.mail.success");
} else {
showError("invitation.mail.failure");
}
}
public class AccessRightsRow {
private final AccessRights rights;
......@@ -328,6 +409,8 @@ public class PublishController extends BasicController implements TooledControll
explanation = translate("access.rights.coach.long");
} else if(PortfolioRoles.reviewer.equals(rights.getRole())) {
explanation = translate("access.rights.reviewer.long");
} else if(PortfolioRoles.invitee.equals(rights.getRole())) {
explanation = translate("access.rights.invitee.long");
}
return explanation;
}
......
......@@ -4,9 +4,13 @@ access.rights.coach=Betreuer
access.rights.coach.long=als Betreuer (lesen / kommentieren / bewerten)
access.rights.date=Datum
access.rights.element=Zugang zu
access.rights.invitee=Einladung
access.rights.invitee.long=als eingeladet Benutzer (lesen / kommentieren)
access.rights.owner.long=als Besitzer (lesen / schreiben)
access.rights.reviewer=Reviewer
access.rights.reviewer.long=als Reviewer (lesen / kommentieren)
access.rights=Zugangsrecht hinzuf\u00FCgen
add.invitation=Einladung hinzuf\u00FCgen
add.file=Dokument hinzuf\u00FCgen
add.html=HTML hinzuf\u00FCgen
add.image=Bild hinzuf\u00FCgen
......@@ -50,13 +54,23 @@ edit.binder.metadata=Metadaten bearbeiten
edit.page=Eintrag bearbeiten
edit.page.metadata=Metadaten bearbeiten
end.date=Enddatum
error.mail.invalid=Bitte geben Sie eine g\u00FCltige E-Mailadresse an.
error.invitation.mail.used=Diese E-Mailadresse wird bereits von einem OpenOLAT-Benutzer verwendet.
fileupload=Titelbild
firstName=Vorname
goto.media.center=Mediencenter \u00F6ffnen
goto.my.binders=zu meinen Mappen
goto.my.pages=zeige meine Eintr\u00E4ge
goto.my.shared.items=zu meinen freigegebenen Mappen
goto.shared.with.me=zeige an mich freigegebene Mappen
import.artefactV1=Artefakte importieren
invitation.link=Link
invitation.mail.subject=Einladung zu einer freigegebenen Sammelmappe
invitation.mail.body=Sie wurden von {1} eingeladen, eine Sammelmappe in OLAT zu betrachten. Sie finden diese unter folgender Adresse: {0}
invitation.mail.success=Die eingeladenen Personen wurden erfolgreich per E-Mail benachrichtigt.
invitation.mail.failure=Fehler beim Versenden der E-Mail. Die eingeladenen Personen konnten nicht per E-Mail benachrichtigt werden. Versuchen Sie es spter noch einmal oder kontaktieren Sie den Support.
lastName=Name
mail=Mail
map.available=$org.olat.course.nodes.portfolio\:map.available
map.comment=$org.olat.course.assessment\:map.comment
map.copyDate=$org.olat.course.nodes.portfolio\:map.copyDate
......
......@@ -4,9 +4,13 @@ access.rights.coach=Coach
access.rights.coach.long=as coach (read / comment / assess)
access.rights.date=Date
access.rights.element=Element
access.rights.invitee=Invitee
access.rights.invitee.long=as invitee (read / comment)
access.rights.owner.long=as owner (read / write)
access.rights.reviewer=Reviewer
access.rights.reviewer.long=as reviewer (read / comment)
access.rights=Add access rights
add.invitation=Add invitation
add.file=Add document
add.html=Add HTML
add.image=Add image
......@@ -52,13 +56,25 @@ edit.binder.metadata=Edit metadata
edit.page=Edit entry
edit.page.metadata=Edit metadata
end.date=End
error.mail.invalid=Please provide a valid e-mail address.
error.invitation.mail.used=This e-mail address is already used by an OpenOLAT user.
fileupload=Teaser Image
firstName=First name
goto.media.center=open media center
goto.my.binders=go to my binders
goto.my.pages=show my entries
goto.my.shared.items=go to my shares
goto.shared.with.me=go to shared items
import.artefactV1=Import artefacts
invitation.link=Link
invitation.mail.subject=Invitation to a binder already released
invitation.mail.body=You have been invited by {1} to have a look at a binder in OpenOLAT. Please go to\: {0}
invitation.mail.success=The persons invited have been notified successfully via e-mail.
invitation.mail.failure=Error while sending your e-mail. The persons invited could not be notified. Please try again later or contact your support team.
lastName=Last name
mail=E-Mail
map.available=$org.olat.course.nodes.portfolio\:map.available
map.comment=$org.olat.course.assessment\:map.comment
map.copyDate=$org.olat.course.nodes.portfolio\:map.copyDate
......
#Tue Jun 28 15:08:23 CEST 2016
error.mail.invalid=Indiquez une adresse e-mail valide, svp.
error.invitation.mail.used=Cette adresse e-mail est d\u00E9j\u00E0 utilis\u00E9e par un utilisateur OLAT.
invitation.mail.subject=Invitation \u00E0 consulter un classeur OLAT partag\u00E9
invitation.mail.body=Vous avez \u00E9t\u00E9 invit\u00E9 par {0} \u00E0 consulter un classeur OLAT. Vous pouvez le trouver \u00E0 l'adresse suivante\: {0}
invitation.mail.success=Les personnes invit\u00E9es ont \u00E9t\u00E9 inform\u00E9es par e-mail.
invitation.mail.failure=Les personnes invit\u00E9es n'ont pas pu \u00EAtre averties par e-mail. R\u00E9essayez plus tard ou contactez le support.
\ No newline at end of file
#Tue Jun 28 15:08:23 CEST 2016
error.mail.invalid=Indichi un indirizzi e-mail valido, p.f.
error.invitation.mail.used=Questo indirizzo e-mail viene gi\u00E0 utilizzato da un utente OpenOLAT.
invitation.mail.subject=Invito a consultare un raccoglitore OLAT condiviso
invitation.mail.body=Lei \u00E8 stata/o invitata/o da {0} a consultare un raccoglitore OLAT. Lo pu\u00F2 trovare all'indirizzo seguente\: {0}
invitation.mail.success=Le persone invitate sono state informate via e-mail.
invitation.mail.failure=Errore durante l'invio della e-mail. Le persone invitate non possono essere avvisate via e-mail. Riprovi pi\u00F9 tardi o contatti il Suo punto di supporto.
\ No newline at end of file
#Tue Jun 28 15:08:23 CEST 2016
error.mail.invalid=Gelieve een geldig e-mailadres in te voeren.
error.invitation.mail.used=Dit e-mailadres wordt al gebruikt door een OpenOLAT gebruiker.
invitation.mail.subject=Er is reeds een uitnodiging voor de accumulatieve map vrijgegeven
invitation.mail.body=U bent uitgenodigd door {1} om een kijkje te nemen in een accumulatieve map op OLAT. Gelieve naar hier te gaan\: {0}
invitation.mail.success=De uitgenodigde persoon is succesvol verwittigd via e-mail.
invitation.mail.failure=Er is een fout opgetreden tijdens het versturen van uw e-mail. De uitgenodigde persoon kon niet verwittigd worden. Gelieve het later opnieuw te proberen of uw ondersteuningsteam te contacteren.
\ No newline at end of file
#Tue Jun 28 15:08:23 CEST 2016
error.mail.invalid=Podaj prawid\u0142owy adres e-mail.
error.invitation.mail.used=Ten adres e-mail jest ju\u017C wykorzystywany przez innego u\u017Cytkownika OpenOLAT.
invitation.mail.body=Zosta\u0142e\u015B zaproszony przez {1} do obejrzenia folderu zbiorczego w OLAT. W tym celu przejd\u017A do\: {0}
invitation.mail.failure=Wyst\u0105pi\u0142 b\u0142\u0105d podczas wysy\u0142ania wiadomo\u015Bci e-mail. Osoby, kt\u00F3re zaprosi\u0142e\u015B nie zostan\u0105 powiadomione. Spr\u00F3buj ponownie p\u00F3\u017Aniej lub skontaktuj si\u0119 z osob\u0105 odpowiedzialn\u0105 za wsparcie.
invitation.mail.subject=Zaproszenie do folderu zbiorczego zosta\u0142o ju\u017C udost\u0119pnione
invitation.mail.success=Zaproszone osoby zosta\u0142y powiadomione mailem.
\ No newline at end of file
#Tue Jun 28 15:08:23 CEST 2016
error.mail.invalid=Por favor, forne\u00E7a um endere\u00E7o de e-mail v\u00E1lido.
error.invitation.mail.used=Este endere\u00E7o de e-mail j\u00E1 \u00E9 utilizado por um usu\u00E1rio OpenOLAT.
invitation.mail.body=Voc\u00EA foi convidado por {1} para olhar uma pasta acumulativa no OLAT. Por favor, v\u00E1 para\: {0}
invitation.mail.failure=Erro ao enviar seu e-mail. As pessoas convidadas n\u00E3o puderam ser notificadas. Por favor, tente novamente mais tarde ou entre em contato com sua equipe de suporte.
invitation.mail.subject=Convite para uma pasta acumulativa j\u00E1 lan\u00E7ada
invitation.mail.success=As pessoas convidadas foram notificadas com sucesso via e-mail.
\ No newline at end of file
......@@ -19,16 +19,27 @@
*/
package org.olat.modules.portfolio.ui.wizard;
import org.apache.velocity.VelocityContext;
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.SelectionElement;
import org.olat.core.gui.components.form.flexible.elements.TextElement;
import org.olat.core.gui.components.form.flexible.impl.Form;
import org.olat.core.gui.components.form.flexible.impl.FormEvent;
import org.olat.core.gui.control.Controller;
import org.olat.core.gui.control.WindowControl;
import org.olat.core.gui.control.generic.wizard.StepFormBasicController;
import org.olat.core.gui.control.generic.wizard.StepsEvent;
import org.olat.core.gui.control.generic.wizard.StepsRunContext;
import org.olat.core.helpers.Settings;
import org.olat.core.id.Identity;
import org.olat.core.util.Util;
import org.olat.core.util.mail.MailTemplate;
import org.olat.modules.portfolio.Binder;
import org.olat.modules.portfolio.ui.PortfolioHomeController;
import org.olat.user.UserManager;
import org.springframework.beans.factory.annotation.Autowired;
/**
*
......@@ -38,19 +49,52 @@ import org.olat.modules.portfolio.Binder;
*/
public class MemberMailController extends StepFormBasicController {
private TextElement subjectEl;
private TextElement bodyEl;
private SelectionElement sendMailEl;
private MailTemplate mailTemplate;
private final Binder binder;
@Autowired
private UserManager userManager;
public MemberMailController(UserRequest ureq, WindowControl wControl, Binder binder,
Form rootForm, StepsRunContext runContext) {
super(ureq, wControl, rootForm, runContext, LAYOUT_CUSTOM, "mail_template");
this.binder = binder;
super(ureq, wControl, rootForm, runContext, LAYOUT_DEFAULT, null);
setTranslator(Util.createPackageTranslator(PortfolioHomeController.class, getLocale(), getTranslator()));
mailTemplate = (MailTemplate)runContext.get("maiTemplate");
if(mailTemplate == null) {
String subject = translate("invitation.mail.subject");
String sender = userManager.getUserDisplayName(getIdentity());
String busLink = Settings.getServerContextPathURI() + "/url/HomeSite/0/PortfolioV2/0/SharedWithMe/0/Binder/" + binder.getKey();
String body = translate("invitation.mail.body", new String[]{ busLink, sender});
mailTemplate = new MailTemplate(subject, body, null) {
@Override
public void putVariablesInMailContext(VelocityContext vContext, Identity recipient) {
//
}
};
}
initForm (ureq);
}
@Override
protected void initForm(FormItemContainer formLayout, Controller listener, UserRequest ureq) {
//formLayout.add("template", mailTemplateForm.getInitialFormItem());
sendMailEl = uifactory.addCheckboxesVertical("sendmail", "", formLayout, new String[]{"xx"}, new String[]{translate("mail.sendMail")}, 1);
sendMailEl.select("xx", true);
sendMailEl.addActionListener(FormEvent.ONCLICK);
subjectEl = uifactory.addTextElement("subjectElem", "mail.subject", 128, mailTemplate.getSubjectTemplate(), formLayout);
subjectEl.setDisplaySize(60);
subjectEl.setMandatory(true);
bodyEl = uifactory.addTextAreaElement("bodyElem", "mail.body", -1, 15, 60, true, mailTemplate.getBodyTemplate(), formLayout);
bodyEl.setHelpText(translate("mailtemplateform.body.hover"));
bodyEl.setHelpUrlForManualPage("E-Mail");
bodyEl.setMandatory(true);
}
@Override
......@@ -64,16 +108,25 @@ public class MemberMailController extends StepFormBasicController {
return allOk & super.validateFormLogic(ureq);
}
@Override
protected void formInnerEvent(UserRequest ureq, FormItem source, FormEvent event) {
if(sendMailEl == source) {
boolean sm = sendMailEl.isSelected(0);
subjectEl.setVisible(sm);
bodyEl.setVisible(sm);
}
super.formInnerEvent(ureq, source, event);
}
@Override
protected void formOK(UserRequest ureq) {
/*if(mailTemplateForm.sendMailSwitchEnabled()) {
if(!mailTemplateForm.isDefaultTemplate()) {
mailTemplateForm.updateTemplateFromForm(mailTemplate);
}
if(sendMailEl.isSelected(0)) {
mailTemplate.setSubjectTemplate(subjectEl.getValue());
mailTemplate.setBodyTemplate(bodyEl.getValue());
addToRunContext("mailTemplate", mailTemplate);
} else {
addToRunContext("mailTemplate", null);
}*/
}
fireEvent (ureq, StepsEvent.ACTIVATE_NEXT);
}
}
\ No newline at end of file
......@@ -3,3 +3,6 @@ add.choose.title=Benutzer w\u00E4hlen
add.confirm.title=\u00DCberblick
add.mail.title=E-Mail senden
add.permission.title=Zugang
mail.body=Nachricht
mail.sendMail=E-Mail versenden
mail.subject=Betreffzeile
......@@ -3,3 +3,6 @@ add.choose.title=Choose a user
add.confirm.title=Overview
add.permission.title=Access rights
add.mail.title=Send mail
mail.body=Mail body
mail.sendMail=Send e-mail
mail.subject=Mail subject
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment