Skip to content
This repository has been archived by the owner on Nov 9, 2017. It is now read-only.

Commit

Permalink
feat(language team): allow coordinator to contact members
Browse files Browse the repository at this point in the history
  • Loading branch information
Alex Eng committed Apr 29, 2016
1 parent 5bf24ba commit f89b139
Show file tree
Hide file tree
Showing 14 changed files with 464 additions and 3 deletions.
8 changes: 8 additions & 0 deletions docs/release-notes.md
@@ -1,3 +1,11 @@
## 4.0

<h5>New Features</h5>
* [ZNTA-1059](https://zanata.atlassian.net/browse/ZNTA-1059) - Language coordinator can contact team members


-----------------------

## 3.9

<h5>Infrastructure Changes</h5>
Expand Down
@@ -0,0 +1,145 @@
/*
* Copyright 2016, 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 com.google.common.collect.Lists;
import lombok.Getter;
import lombok.Setter;
import lombok.extern.slf4j.Slf4j;
import org.zanata.ApplicationConfiguration;
import org.zanata.common.LocaleId;
import org.zanata.dao.LocaleMemberDAO;
import org.zanata.email.ContactLanguageTeamMembersEmailStrategy;
import org.zanata.email.EmailStrategy;
import org.zanata.i18n.Messages;
import org.zanata.model.HAccount;
import org.zanata.model.HLocale;
import org.zanata.model.HLocaleMember;
import org.zanata.security.annotations.Authenticated;
import org.zanata.security.annotations.CheckLoggedIn;
import org.zanata.service.EmailService;
import org.zanata.service.LocaleService;
import org.zanata.ui.faces.FacesMessages;

import javax.inject.Inject;
import javax.inject.Named;
import java.io.Serializable;
import java.util.List;

/**
* @author Alex Eng <a href="mailto:aeng@redhat.com">aeng@redhat.com</a>
*/

@Named("contactLanguageTeamMembersAction")
@javax.faces.bean.ViewScoped

@Slf4j
public class ContactLanguageTeamMembersAction implements Serializable {

@Inject
@Authenticated
private HAccount authenticatedAccount;

@Inject
private FacesMessages facesMessages;

@Inject
private EmailService emailServiceImpl;

@Inject
private LocaleService localeServiceImpl;

@Inject
private Messages msgs;

@Inject
private ApplicationConfiguration applicationConfiguration;

@Inject
private LocaleMemberDAO localeMemberDAO;

@Getter
@Setter
private String message;

@Getter
@Setter
private String subject;

@Getter
@Setter
private String localeId;

private HLocale locale;

private List<HLocaleMember> getMembers() {
return localeMemberDAO.findActiveMembers(new LocaleId(localeId));
}


@CheckLoggedIn
public void send() {
List<HLocaleMember> members = getMembers();
if(!members.isEmpty()) {
String fromName = authenticatedAccount.getPerson().getName();
String fromLoginName = authenticatedAccount.getUsername();
String replyEmail = authenticatedAccount.getPerson().getEmail();
String contactCoordinatorLink =
applicationConfiguration.getServerPath() +
"/language/view/" + localeId;

String localeNativeName = getLocale().retrieveNativeName();

EmailStrategy strategy =
new ContactLanguageTeamMembersEmailStrategy(
fromLoginName, fromName, replyEmail,
getSubject(),
getLocale().getLocaleId().getId(),
localeNativeName, message, contactCoordinatorLink);
try {
String msg = emailServiceImpl.sendToLanguageTeamMembers(
getLocale().getLocaleId(), strategy, members);
facesMessages.addGlobal(msg);
} catch (Exception e) {
String subject = strategy.getSubject(msgs);

StringBuilder sb =
new StringBuilder()
.append("Failed to send email with subject '")
.append(strategy.getSubject(msgs))
.append("' , message '").append(message)
.append("'");
log.error(
"Failed to send email: fromName '{}', fromLoginName '{}', replyEmail '{}', subject '{}', message '{}'. {}",
fromName, fromLoginName, replyEmail, subject, message, e);
facesMessages.addGlobal(sb.toString());
}
}
}

public HLocale getLocale() {
if (locale == null) {
locale = localeServiceImpl.getByLocaleId(new LocaleId(localeId));
}
return locale;
}
}
15 changes: 15 additions & 0 deletions zanata-war/src/main/java/org/zanata/dao/LocaleMemberDAO.java
Expand Up @@ -56,6 +56,21 @@ public List<HLocaleMember> findAllByLocale(LocaleId localeId) {
return query.list();
}

public List<HLocaleMember> findActiveMembers(LocaleId localeId) {
StringBuilder sb = new StringBuilder();
sb.append("from HLocaleMember ")
.append("where id.supportedLanguage.localeId = :localeId ")
.append("and (isTranslator = true ")
.append("or isReviewer = true ")
.append("or isCoordinator = true) ")
.append("order by lower(id.person.name)");
Query query = getSession().createQuery(sb.toString());
query.setParameter("localeId", localeId);
query.setCacheable(true);
query.setComment("LocaleMemberDAO.findActiveMembers");
return query.list();
}

/**
* Check if person is a reviewer of any language
*
Expand Down
11 changes: 11 additions & 0 deletions zanata-war/src/main/java/org/zanata/email/Addresses.java
Expand Up @@ -31,6 +31,7 @@
import lombok.AccessLevel;
import lombok.NoArgsConstructor;

import org.zanata.model.HLocaleMember;
import org.zanata.model.HPerson;

/**
Expand Down Expand Up @@ -61,6 +62,16 @@ public static InternetAddress[] getAddresses(List<HPerson> personList) {
return toAddresses.toArray(new InternetAddress[toAddresses.size()]);
}

public static InternetAddress[] getLocaleMemberAddresses(
List<HLocaleMember> members) {
List<InternetAddress> toAddresses = new ArrayList<InternetAddress>();
for (HLocaleMember member : members) {
toAddresses.add(getAddress(member.getPerson().getEmail(),
member.getPerson().getName()));
}
return toAddresses.toArray(new InternetAddress[toAddresses.size()]);
}

public static InternetAddress[] getAddresses(List<String> emailList, String name) {
List<InternetAddress> toAddresses = new ArrayList<InternetAddress>();
for (String email : emailList) {
Expand Down
@@ -0,0 +1,80 @@
/*
* Copyright 2016, 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.email;

import com.google.common.base.Optional;
import com.googlecode.totallylazy.collections.PersistentMap;
import lombok.RequiredArgsConstructor;
import org.zanata.i18n.Messages;
import org.zanata.util.HtmlUtil;

import javax.mail.internet.InternetAddress;

import static org.zanata.email.Addresses.getReplyTo;

/**
* @author Alex Eng <a href="aeng@redhat.com">aeng@redhat.com</a>
*/
@RequiredArgsConstructor
public class ContactLanguageTeamMembersEmailStrategy
extends EmailStrategy {
private final String fromLoginName;
private final String fromName;
private final String replyEmail;
private final String userSubject;
private final String localeId;
private final String localeNativeName;
private final String htmlMessage;
private final String contactCoordinatorLink;

@Override
public String getBodyResourceName() {
return "org/zanata/email/templates/email_language_team_members.vm";
}

@Override
public Optional<InternetAddress[]> getReplyToAddress() {
return Optional.of(getReplyTo(replyEmail, fromName));
}

@Override
public String getSubject(Messages msgs) {
return msgs.format("jsf.email.language.members.SubjectPrefix",
localeId, fromLoginName) + " " + userSubject;
}

@Override
public PersistentMap<String, Object> makeContext(
PersistentMap<String, Object> genericContext,
InternetAddress[] toAddresses) {
PersistentMap<String, Object> context = super.makeContext(genericContext,
toAddresses);
String safeHTML = HtmlUtil.SANITIZER.sanitize(htmlMessage);
return context
.insert("fromLoginName", fromLoginName)
.insert("fromName", fromName)
.insert("replyEmail", replyEmail)
.insert("localeId", localeId)
.insert("contactCoordinatorLink", contactCoordinatorLink)
.insert("localeNativeName", localeNativeName)
.insert("htmlMessage", safeHTML);
}
}
Expand Up @@ -26,7 +26,7 @@

import org.zanata.common.LocaleId;
import org.zanata.email.EmailStrategy;
import org.zanata.model.HLocale;
import org.zanata.model.HLocaleMember;
import org.zanata.model.HPerson;

/**
Expand Down Expand Up @@ -85,4 +85,10 @@ String sendToLanguageCoordinators(LocaleId localeId,
* sends email to requester of the language request
*/
void sendToLanguageRequester(EmailStrategy strategy, HPerson person);

/**
* sends email to language team members.
*/
String sendToLanguageTeamMembers(LocaleId localeId, EmailStrategy strategy,
List<HLocaleMember> members);
}
Expand Up @@ -56,6 +56,7 @@
import com.google.common.collect.Lists;

import static org.zanata.email.Addresses.getAddresses;
import static org.zanata.email.Addresses.getLocaleMemberAddresses;

/**
* @author Alex Eng <a href="mailto:aeng@redhat.com">aeng@redhat.com</a>
Expand Down Expand Up @@ -250,4 +251,19 @@ public void sendToLanguageRequester(EmailStrategy strategy,
emailBuilder.sendMessage(strategy, null, to);
}
}

@Override
public String sendToLanguageTeamMembers(LocaleId localeId,
EmailStrategy strategy, List<HLocaleMember> members) {
if (!members.isEmpty()) {
String receivedReason = msgs.format(
"jsf.email.language.members.ReceivedReason", localeId);
emailBuilder.sendMessage(strategy,
Lists.newArrayList(receivedReason),
getLocaleMemberAddresses(members));
return msgs.format("jsf.email.language.members.SentNotification",
localeId);
}
return msgs.format("jsf.email.language.members.EmptyMembersNotification", localeId);
}
}
9 changes: 9 additions & 0 deletions zanata-war/src/main/resources/messages.properties
Expand Up @@ -832,6 +832,7 @@ jsf.LeaveLanguageTeam=Leave Team
jsf.RequestToJoinLanguageTeam=Request To Join
jsf.RequestUpdateRoleLanguageTeam=Request Role
jsf.contactLanguageTeamCoordinator=Contact Coordinators
jsf.contactLanguageTeamMembers=Contact team members
jsf.AddTeamMember=Add Team Member
jsf.FindUsersToAdd=Find Users To Add
jsf.Loading=Loading...
Expand Down Expand Up @@ -1269,6 +1270,8 @@ jsf.message.admin.inquiry.title=Message to Zanata Administrator
jsf.message.coordinator.inquiry.subject=Inquiry on language {0} [{1}]
! Windows title for contact language coordinator dialog
jsf.message.coordinator.inquiry.title=Message to {0} [{1}] coordinator
!{0} - members count, {1} - language name
jsf.message.contact.members.title=Send message to {0} team members in the {1} team


! used in all emails
Expand Down Expand Up @@ -1341,6 +1344,12 @@ jsf.email.coordinator.request.responseInstructions=You can click the link below
jsf.email.coordinator.ResponseInstructions=You can click the link below to go directly to the {0} Language Team Page. Please reply to {1} at {2} when you have finished processing this request.
jsf.email.coordinator.ReceivedReason=You are a coordinator in the "{0}" language team

#--------- contact-language-member email -------
jsf.email.language.members.SubjectPrefix=Zanata: Message from {0} language team coordinator "{1}":
jsf.email.language.members.DearMember=Dear team member,
jsf.email.language.members.SentNotification=Your message has been sent to {0} team members.
jsf.email.language.members.EmptyMembersNotification=No team members in "{0}" to contact.
jsf.email.language.members.ReceivedReason=You are a member of {0} language team

#------ request-to-join-language email ------
# name, loginName, localeId, nativeName
Expand Down
@@ -0,0 +1,4 @@
<p>$msgs.get("jsf.email.language.members.DearMember")</p>
$htmlMessage
<hr/>
<p>$msgs.format("jsf.email.languageteam.permission.howToReply", $contactCoordinatorLink)</p>

0 comments on commit f89b139

Please sign in to comment.