diff --git a/functional-test/src/main/java/org/zanata/page/utility/ContactAdminFormPage.java b/functional-test/src/main/java/org/zanata/page/utility/ContactAdminFormPage.java index 9c76bf2dd7..9fdcc493ec 100644 --- a/functional-test/src/main/java/org/zanata/page/utility/ContactAdminFormPage.java +++ b/functional-test/src/main/java/org/zanata/page/utility/ContactAdminFormPage.java @@ -35,7 +35,7 @@ public class ContactAdminFormPage extends BasePage { private By subjectField = By.id("contactAdminForm:subjectField:subject"); private By messageField = By.id("contactAdminForm:messageField:message"); - private By sendButton = By.id("contactAdminForm:send"); + private By sendButton = By.id("send"); public ContactAdminFormPage(WebDriver driver) { super(driver); diff --git a/functional-test/src/test/java/org/zanata/feature/language/ContactLanguageTeamTest.java b/functional-test/src/test/java/org/zanata/feature/language/ContactLanguageTeamTest.java index bbf575ffe1..eae40c245e 100644 --- a/functional-test/src/test/java/org/zanata/feature/language/ContactLanguageTeamTest.java +++ b/functional-test/src/test/java/org/zanata/feature/language/ContactLanguageTeamTest.java @@ -78,6 +78,7 @@ public void translatorContactsLanguageTeamCoordinator() throws Exception { assertThat(content) .contains("Dear Language Team Coordinator") + .contains("There is no coordinator for") .as("The email is to the language team coordinator"); assertThat(languagesPage.getNotificationMessage()) .contains("Your message has been sent to the administrator") diff --git a/zanata-war/src/main/java/org/zanata/action/ContactAdminAction.java b/zanata-war/src/main/java/org/zanata/action/ContactAdminAction.java new file mode 100644 index 0000000000..5f08308031 --- /dev/null +++ b/zanata-war/src/main/java/org/zanata/action/ContactAdminAction.java @@ -0,0 +1,96 @@ +/* + * Copyright 2015, Red Hat, Inc. and individual contributors as indicated by the + * @author tags. See the copyright.txt file in the distribution for a full + * listing of individual contributors. + * + * This is free software; you can redistribute it and/or modify it under the + * terms of the GNU Lesser General Public License as published by the Free + * Software Foundation; either version 2.1 of the License, or (at your option) + * any later version. + * + * This software is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more + * details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this software; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA, or see the FSF + * site: http://www.fsf.org. + */ + +package org.zanata.action; + +import java.io.Serializable; + +import org.jboss.seam.ScopeType; +import org.jboss.seam.annotations.Create; +import org.jboss.seam.annotations.In; +import org.jboss.seam.annotations.Name; +import org.jboss.seam.annotations.Scope; +import org.jboss.seam.annotations.security.Restrict; +import org.jboss.seam.faces.FacesMessages; +import org.jboss.seam.security.management.JpaIdentityStore; +import org.zanata.email.ContactAdminEmailStrategy; +import org.zanata.email.EmailStrategy; +import org.zanata.model.HAccount; +import org.zanata.service.EmailService; + +import lombok.Getter; +import lombok.Setter; +import lombok.extern.slf4j.Slf4j; + +/** + * Handles send email to admin. + * Need to separate from SendEmailAction as contact admin now pages which has footer.xhtml + * + * @see org.zanata.action.SendEmailAction + * + * @author Alex Eng aeng@redhat.com + */ +@Name("contactAdminAction") +@Scope(ScopeType.PAGE) +@Restrict("#{identity.loggedIn}") +@Slf4j +public class ContactAdminAction implements Serializable { + + @In(value = JpaIdentityStore.AUTHENTICATED_USER, required = false) + private HAccount authenticatedAccount; + + @In + private EmailService emailServiceImpl; + + @Getter + private String replyEmail; + + @Getter + @Setter + private String subject; + + @Getter + @Setter + private String htmlMessage; + + private String fromName; + + private String fromLoginName; + + @Create + public void onCreate() { + fromName = authenticatedAccount.getPerson().getName(); + fromLoginName = authenticatedAccount.getUsername(); + replyEmail = authenticatedAccount.getPerson().getEmail(); + + subject = ""; + htmlMessage = ""; + } + + public void send() { + EmailStrategy strategy = new ContactAdminEmailStrategy( + fromLoginName, fromName, replyEmail, subject, htmlMessage); + + String msg = emailServiceImpl.sendToAdmins(strategy, null); + + FacesMessages.instance().add(msg); + } +} diff --git a/zanata-war/src/main/java/org/zanata/action/SendEmailAction.java b/zanata-war/src/main/java/org/zanata/action/SendEmailAction.java index cbb6d78aff..b6c5627cd2 100644 --- a/zanata-war/src/main/java/org/zanata/action/SendEmailAction.java +++ b/zanata-war/src/main/java/org/zanata/action/SendEmailAction.java @@ -67,8 +67,6 @@ /** * Sends an email to a specified role. * - * Currently just sends an email to admin. - * * @author damason@redhat.com * */ @@ -196,11 +194,11 @@ public String send() { fromLoginName, fromName, replyEmail, subject, htmlMessage); - String msg = emailServiceImpl.sendToAdmins(strategy); + String msg = emailServiceImpl.sendToAdmins(strategy, null); facesMessages.addGlobal(msg); conversationScopeMessages.setMessage( - FacesMessage.SEVERITY_INFO, msg); + FacesMessage.SEVERITY_INFO, msg); return SUCCESS; } case EMAIL_TYPE_CONTACT_COORDINATOR: { diff --git a/zanata-war/src/main/java/org/zanata/email/EmailBuilder.java b/zanata-war/src/main/java/org/zanata/email/EmailBuilder.java index 65fcb7ec7d..af4ce37eb2 100644 --- a/zanata-war/src/main/java/org/zanata/email/EmailBuilder.java +++ b/zanata-war/src/main/java/org/zanata/email/EmailBuilder.java @@ -5,6 +5,7 @@ import java.io.StringWriter; import java.net.ConnectException; +import java.util.List; import javax.mail.MessagingException; import javax.mail.Multipart; @@ -89,8 +90,8 @@ private static VelocityEngine makeVelocityEngine() { * @throws javax.mail.MessagingException */ public void sendMessage(EmailStrategy strategy, - String receivedReason, InternetAddress toAddress) { - sendMessage(strategy, receivedReason, new InternetAddress[] { + List receivedReasons, InternetAddress toAddress) { + sendMessage(strategy, receivedReasons, new InternetAddress[] { toAddress }); } @@ -100,10 +101,10 @@ public void sendMessage(EmailStrategy strategy, * @throws javax.mail.MessagingException */ public void sendMessage(EmailStrategy strategy, - String receivedReason, InternetAddress[] toAddresses) { + List receivedReasons, InternetAddress[] toAddresses) { try { MimeMessage email = new MimeMessage(mailSession); - buildMessage(email, strategy, toAddresses, receivedReason); + buildMessage(email, strategy, toAddresses, receivedReasons); logMessage(email); Transport.send(email); } catch (MessagingException e) { @@ -145,7 +146,7 @@ private void logMessage(MimeMessage msg) { */ @VisibleForTesting MimeMessage buildMessage(MimeMessage msg, EmailStrategy strategy, - InternetAddress[] toAddresses, String receivedReason) + InternetAddress[] toAddresses, List receivedReasons) throws MessagingException { Optional from = strategy.getFromAddress(); @@ -162,7 +163,7 @@ MimeMessage buildMessage(MimeMessage msg, EmailStrategy strategy, PersistentMap genericContext = map( "msgs", msgs, - "receivedReason", receivedReason, + "receivedReasons", receivedReasons, "serverPath", emailContext.getServerPath()); // the Map needs to be mutable for "foreach" to work diff --git a/zanata-war/src/main/java/org/zanata/notification/LanguageTeamPermissionChangeJmsMessagePayloadHandler.java b/zanata-war/src/main/java/org/zanata/notification/LanguageTeamPermissionChangeJmsMessagePayloadHandler.java index 7be3f15617..f8b473b8fe 100644 --- a/zanata-war/src/main/java/org/zanata/notification/LanguageTeamPermissionChangeJmsMessagePayloadHandler.java +++ b/zanata-war/src/main/java/org/zanata/notification/LanguageTeamPermissionChangeJmsMessagePayloadHandler.java @@ -35,6 +35,8 @@ import org.zanata.email.LanguageTeamPermissionChangeEmailStrategy; import org.zanata.events.LanguageTeamPermissionChangedEvent; import org.zanata.i18n.Messages; + +import com.google.common.collect.Lists; import lombok.extern.slf4j.Slf4j; /** @@ -91,7 +93,8 @@ public void handle(Serializable data) { Addresses.getAddress(changedEvent.getEmail(), changedEvent.getName()); - emailBuilder.sendMessage(emailStrategy, receivedReason, to); + emailBuilder.sendMessage(emailStrategy, + Lists.newArrayList(receivedReason), to); } } diff --git a/zanata-war/src/main/java/org/zanata/service/EmailService.java b/zanata-war/src/main/java/org/zanata/service/EmailService.java index dfc19dff13..108572bd15 100644 --- a/zanata-war/src/main/java/org/zanata/service/EmailService.java +++ b/zanata-war/src/main/java/org/zanata/service/EmailService.java @@ -22,6 +22,8 @@ import java.util.List; +import javax.annotation.Nullable; + import org.zanata.email.EmailStrategy; import org.zanata.model.HLocale; import org.zanata.model.HPerson; @@ -50,8 +52,18 @@ String sendEmailValidationEmail(String toName, /** * sends emails to configured admin emails for server, or admin users if no * server emails are configured. + * + * @param strategy - Email template + * @param receivedReasons + * - Reasons of why users are receiving email as admin can + * received via: 1) Direct email from logged in users. 2) User + * request to join language team when there's no coordinator. 3) + * User request to update their role in language team when + * there's no coordinator. 4) User request to join a version group + * when there's no maintainer. */ - String sendToAdmins(EmailStrategy strategy); + String sendToAdmins(EmailStrategy strategy, + @Nullable List receivedReasons); /** * sends emails to version group maintainers -> admin -> admin users diff --git a/zanata-war/src/main/java/org/zanata/service/impl/EmailServiceImpl.java b/zanata-war/src/main/java/org/zanata/service/impl/EmailServiceImpl.java index f1d7957dee..b232ca02c2 100644 --- a/zanata-war/src/main/java/org/zanata/service/impl/EmailServiceImpl.java +++ b/zanata-war/src/main/java/org/zanata/service/impl/EmailServiceImpl.java @@ -49,8 +49,11 @@ import org.zanata.model.HPerson; import org.zanata.service.EmailService; +import javax.annotation.Nullable; import javax.mail.internet.InternetAddress; +import com.google.common.collect.Lists; + import static org.zanata.email.Addresses.getAddresses; /** @@ -135,17 +138,36 @@ public String sendPasswordResetEmail(HPerson person, String key) { return msgs.get("jsf.email.passwordreset.SentNotification"); } + + /** + * sends emails to configured admin emails for server, or admin users if no + * server emails are configured. + * + * @param strategy - Email template + * @param receivedReasons + * - Reasons of why users are receiving email as admin can + * received via: 1) Direct email from logged in users. 2) User + * request to join language team when there's no coordinator. 3) + * User request to update their role in language team when + * there's no coordinator. 4) User request to join a version group + * when there's no maintainer. + */ @Override - public String sendToAdmins(EmailStrategy strategy) { + public String sendToAdmins(EmailStrategy strategy, + @Nullable List receivedReasons) { List adminEmails = applicationConfiguration.getAdminEmail(); + receivedReasons = + receivedReasons == null ? Lists. newArrayList() + : receivedReasons; + if (!adminEmails.isEmpty()) { - String receivedReason = msgs.get("jsf.email.admin.ReceivedReason"); + receivedReasons.add(msgs.get("jsf.email.admin.ReceivedReason")); String toName = msgs.get("jsf.ZanataAdministrator"); - emailBuilder.sendMessage(strategy, receivedReason, + emailBuilder.sendMessage(strategy, receivedReasons, getAddresses(adminEmails, toName)); return msgs.get("jsf.email.admin.SentNotification"); } else { - return sendToAdminUsers(strategy); + return sendToAdminUsers(strategy, receivedReasons); } } @@ -153,11 +175,11 @@ public String sendToAdmins(EmailStrategy strategy) { * Emails admin users with given template * */ - private String sendToAdminUsers(EmailStrategy strategy) { - String receivedReason = msgs.get( - "jsf.email.admin.user.ReceivedReason"); - emailBuilder.sendMessage(strategy, receivedReason, - getAddresses(getAdmins())); + private String sendToAdminUsers(EmailStrategy strategy, + List receivedReasons) { + receivedReasons.add(msgs.get("jsf.email.admin.user.ReceivedReason")); + emailBuilder.sendMessage(strategy, receivedReasons, + getAddresses(getAdmins())); return msgs.get("jsf.email.admin.SentNotification"); } @@ -170,12 +192,17 @@ public String sendToLanguageCoordinators(HLocale locale, "jsf.email.coordinator.ReceivedReason", locale.retrieveNativeName()); - emailBuilder.sendMessage(strategy, receivedReason, + emailBuilder.sendMessage(strategy, + Lists.newArrayList(receivedReason), getAddresses(coordinators)); return msgs.format("jsf.email.coordinator.SentNotification", locale.retrieveNativeName()); } else { - return sendToAdmins(strategy); + String receivedReason = + msgs.format( + "jsf.email.admin.ReceivedReason.language.noCoordinator", + locale.getLocaleId(), locale.retrieveDisplayName()); + return sendToAdmins(strategy, Lists.newArrayList(receivedReason)); } } @@ -186,12 +213,17 @@ public String sendToVersionGroupMaintainers(List maintainers, String receivedReason = msgs.format( "jsf.email.group.maintainer.ReceivedReason", versionGroupJoinAction.getGroupName()); - emailBuilder.sendMessage(strategy, receivedReason, + emailBuilder.sendMessage(strategy, + Lists.newArrayList(receivedReason), getAddresses(maintainers)); return msgs.format("jsf.email.group.maintainer.SentNotification", versionGroupJoinAction.getGroupName()); } else { - return sendToAdmins(strategy); + String receivedReason = + msgs.format( + "jsf.email.admin.ReceivedReason.versionGroup.noMaintainer", + versionGroupJoinAction.getGroupName()); + return sendToAdmins(strategy, Lists.newArrayList(receivedReason)); } } diff --git a/zanata-war/src/main/resources/messages.properties b/zanata-war/src/main/resources/messages.properties index ee56a9e161..b8ce0d33c6 100644 --- a/zanata-war/src/main/resources/messages.properties +++ b/zanata-war/src/main/resources/messages.properties @@ -1168,6 +1168,8 @@ jsf.email.admin.UserMessageIntro=Zanata user "{0}" with id "{1}" has sent the fo jsf.email.ReplyInstructions=You can reply to {0} at {1} jsf.email.admin.ReceivedReason=You are an administrator in the system configuration jsf.email.admin.user.ReceivedReason=You are an administrator +jsf.email.admin.ReceivedReason.language.noCoordinator=There is no coordinator for language "{0} ({1})" +jsf.email.admin.ReceivedReason.versionGroup.noMaintainer=There is no maintainer for version group "{0}" #------ contact-language-team-coordinator email ------ diff --git a/zanata-war/src/main/resources/org/zanata/email/templates/template_email.vm b/zanata-war/src/main/resources/org/zanata/email/templates/template_email.vm index 81541f96b5..8267600d29 100644 --- a/zanata-war/src/main/resources/org/zanata/email/templates/template_email.vm +++ b/zanata-war/src/main/resources/org/zanata/email/templates/template_email.vm @@ -5,11 +5,13 @@ #parse($body)
- #if ($receivedReason) + #if ($receivedReasons && !$receivedReasons.isEmpty())

$msgs.get("jsf.email.YouAreReceivingThisMailBecause")
- $receivedReason
+ #foreach ($receivedReason in $receivedReasons) + $receivedReason
+ #end

#end diff --git a/zanata-war/src/main/webapp/WEB-INF/layout/admin/contact_admin_modal.xhtml b/zanata-war/src/main/webapp/WEB-INF/layout/admin/contact_admin_modal.xhtml index a38dda18bd..c972dc0af9 100644 --- a/zanata-war/src/main/webapp/WEB-INF/layout/admin/contact_admin_modal.xhtml +++ b/zanata-war/src/main/webapp/WEB-INF/layout/admin/contact_admin_modal.xhtml @@ -2,18 +2,16 @@ xmlns:h="http://java.sun.com/jsf/html" xmlns:s="http://jboss.org/schema/seam/taglib" xmlns:rich="http://richfaces.org/rich" + xmlns:a4j="http://richfaces.org/a4j" class="modal" id="contactAdminDialog" tabindex="-1" role="dialog" aria-labelledby="myModalLabel" aria-hidden="true"> @@ -31,14 +29,12 @@ - - @@ -58,12 +56,17 @@ #{msgs['jsf.email.MessageBody']} - + + + + +
@@ -74,8 +77,10 @@ #{msgs['jsf.Cancel']} - +
diff --git a/zanata-war/src/main/webapp/WEB-INF/layout/language/contact_coordinator_modal.xhtml b/zanata-war/src/main/webapp/WEB-INF/layout/language/contact_coordinator_modal.xhtml index 0510a5cf3d..9b5a0a4f36 100644 --- a/zanata-war/src/main/webapp/WEB-INF/layout/language/contact_coordinator_modal.xhtml +++ b/zanata-war/src/main/webapp/WEB-INF/layout/language/contact_coordinator_modal.xhtml @@ -2,12 +2,17 @@ xmlns:h="http://java.sun.com/jsf/html" xmlns:s="http://jboss.org/schema/seam/taglib" xmlns:rich="http://richfaces.org/rich" + xmlns:a4j="http://richfaces.org/a4j" class="modal" id="contactCoordinatorDialog" tabindex="-1" role="dialog" aria-labelledby="myModalLabel" aria-hidden="true"> @@ -33,7 +40,7 @@ - + -
#{msgs['jsf.email.MessageBody']} + required="true"> + +
diff --git a/zanata-war/src/main/webapp/WEB-INF/template/footer.xhtml b/zanata-war/src/main/webapp/WEB-INF/template/footer.xhtml index a791e61571..8a11c03324 100644 --- a/zanata-war/src/main/webapp/WEB-INF/template/footer.xhtml +++ b/zanata-war/src/main/webapp/WEB-INF/template/footer.xhtml @@ -19,9 +19,7 @@
  • #{msgs['jsf.Help']}
  • - - - +
  • #{msgs['jsf.ContactAdmin']}
  • diff --git a/zanata-war/src/main/webapp/WEB-INF/urlrewrite.xml b/zanata-war/src/main/webapp/WEB-INF/urlrewrite.xml index b5f55a3c4d..f514d9209d 100644 --- a/zanata-war/src/main/webapp/WEB-INF/urlrewrite.xml +++ b/zanata-war/src/main/webapp/WEB-INF/urlrewrite.xml @@ -207,21 +207,6 @@ /tm/create.seam$1 - - - - - ^/help/view(.+)?$ - /help/view.seam$1 - - - - ^/help/contact(.+)?$ - - /help/contact_admin.seam\?emailType=contact_admin - - ^/$ diff --git a/zanata-war/src/main/webapp/language/language.xhtml b/zanata-war/src/main/webapp/language/language.xhtml index 28a9c29c53..3fce5e23ee 100644 --- a/zanata-war/src/main/webapp/language/language.xhtml +++ b/zanata-war/src/main/webapp/language/language.xhtml @@ -108,7 +108,6 @@ - diff --git a/zanata-war/src/test/java/org/zanata/email/EmailStrategyTest.java b/zanata-war/src/test/java/org/zanata/email/EmailStrategyTest.java index a5d9146e96..4b6b121a1e 100644 --- a/zanata-war/src/test/java/org/zanata/email/EmailStrategyTest.java +++ b/zanata-war/src/test/java/org/zanata/email/EmailStrategyTest.java @@ -158,7 +158,8 @@ public void activation() throws Exception { EmailStrategy strategy = new ActivationEmailStrategy(key); - builder.buildMessage(message, strategy, toAddresses, "activation test"); + builder.buildMessage(message, strategy, toAddresses, + Lists.newArrayList("activation test")); checkFromAndTo(message); assertThat(message.getSubject()).isEqualTo(msgs.get( @@ -180,7 +181,7 @@ public void contactAdmin() throws Exception { fromLoginName, fromName, replyEmail, userSubject, htmlMessage); - builder.buildMessage(message, strategy, toAddresses, "contactAdmin test"); + builder.buildMessage(message, strategy, toAddresses, Lists.newArrayList("contactAdmin test")); checkFromAndTo(message); assertThat(message.getSubject()).isEqualTo(msgs.format( @@ -204,7 +205,7 @@ public void contactLanguageCoordinator() throws Exception { localeId, localeNativeName, htmlMessage); builder.buildMessage(message, strategy, toAddresses, - "contactLanguageCoordinator test"); + Lists.newArrayList("contactLanguageCoordinator test")); checkFromAndTo(message); assertThat(message.getSubject()).isEqualTo(msgs.format( @@ -229,7 +230,7 @@ public void emailValidation() throws Exception { new EmailValidationEmailStrategy(key); builder.buildMessage(message, strategy, toAddresses, - "emailValidation test"); + Lists.newArrayList("emailValidation test")); checkFromAndTo(message); assertThat(message.getSubject()).isEqualTo(msgs.get( @@ -251,7 +252,7 @@ public void passwordReset() throws Exception { new PasswordResetEmailStrategy(key); builder.buildMessage(message, strategy, toAddresses, - "passwordReset test"); + Lists.newArrayList("passwordReset test")); checkFromAndTo(message); assertThat(message.getSubject()).isEqualTo(msgs.get( @@ -275,7 +276,7 @@ public void requestRoleLanguage() throws Exception { true, true, true); builder.buildMessage(message, strategy, toAddresses, - "requestRoleLanguage test"); + Lists.newArrayList("requestRoleLanguage test")); checkFromAndTo(message); assertThat(message.getSubject()).isEqualTo( @@ -302,7 +303,7 @@ public void requestToJoinLanguage() throws Exception { true, true, true); builder.buildMessage(message, strategy, toAddresses, - "requestToJoinLanguage test"); + Lists.newArrayList("requestToJoinLanguage test")); checkFromAndTo(message); assertThat(message.getSubject()).isEqualTo(msgs.format( @@ -336,7 +337,7 @@ public void requestToJoinVersionGroup() throws Exception { projectIterIds, htmlMessage); builder.buildMessage(message, strategy, toAddresses, - "requestToJoinVersionGroup test"); + Lists.newArrayList("requestToJoinVersionGroup test")); checkFromAndTo(message); assertThat(message.getSubject()).isEqualTo(msgs.format( @@ -362,7 +363,7 @@ public void usernameChanged() throws Exception { new UsernameChangedEmailStrategy(newUsername, true); builder.buildMessage(message, strategy, toAddresses, - "usernameChanged test"); + Lists.newArrayList("usernameChanged test")); checkFromAndTo(message); assertThat(message.getSubject()).isEqualTo(msgs.get(