minor fixes

git-svn-id: http://svn.research-infrastructures.eu/public/d4science/gcube/trunk/portlets/widgets/grsf-manage-widget@163021 82a268e6-3cf1-43bd-a215-b396298e98cf
This commit is contained in:
Costantino Perciante 2018-02-07 16:57:09 +00:00
parent 8de3c8fcdb
commit 869421bad1
5 changed files with 130 additions and 76 deletions

View File

@ -35,8 +35,11 @@ import com.github.gwtbootstrap.client.ui.Modal;
import com.github.gwtbootstrap.client.ui.TextArea;
import com.github.gwtbootstrap.client.ui.TextBox;
import com.github.gwtbootstrap.client.ui.constants.AlertType;
import com.github.gwtbootstrap.client.ui.event.HiddenEvent;
import com.github.gwtbootstrap.client.ui.event.HiddenHandler;
import com.google.gwt.core.client.GWT;
import com.google.gwt.dom.client.SelectElement;
import com.google.gwt.dom.client.Style.Unit;
import com.google.gwt.event.dom.client.ChangeEvent;
import com.google.gwt.event.dom.client.ChangeHandler;
import com.google.gwt.event.dom.client.ClickEvent;
@ -45,6 +48,7 @@ import com.google.gwt.event.shared.HandlerManager;
import com.google.gwt.uibinder.client.UiBinder;
import com.google.gwt.uibinder.client.UiField;
import com.google.gwt.uibinder.client.UiHandler;
import com.google.gwt.user.client.Window;
import com.google.gwt.user.client.rpc.AsyncCallback;
import com.google.gwt.user.client.ui.Composite;
import com.google.gwt.user.client.ui.HTML;
@ -160,6 +164,8 @@ public class ManageProductWidget extends Composite{
private SuggestMerges suggestedMergesPanel;
private ConnectToWidget connectWidget;
private boolean updateSucceeded = false;
/**
* Build a ManageProduct widget for the product with the specified id.
* @param productIdentifier
@ -178,12 +184,23 @@ public class ManageProductWidget extends Composite{
loadingImage.setUrl(LOADING_IMAGE_URL);
loadingImage.setVisible(true);
formUpdate.setVisible(false);
loaderIcon.getElement().getStyle().setMarginRight(10, Unit.PX);
// show modal
manageProductModal.addStyleName("management-metadata-modal-style");
// manageProductModal.getElement().getStyle().setWidth(60, Unit.PCT);
manageProductModal.show();
manageProductModal.addHiddenHandler(new HiddenHandler() {
@Override
public void onHidden(HiddenEvent hiddenEvent) {
if(updateSucceeded)
Window.Location.reload();
}
});
// async request to fetch the product
retrieveProductBean(productIdentifier);
@ -246,27 +263,27 @@ public class ManageProductWidget extends Composite{
GRSFNameTexBox.setText(bean.getTitle());
shortNameTextBox.setText(bean.getShortName());
shortNameTextBox.addChangeHandler(new ChangeHandler() {
@Override
public void onChange(ChangeEvent event) {
eventBus.fireEvent(new EnableConfirmButtonEvent());
}
});
semanticIdentifierTextBox.setText(bean.getSemanticIdentifier());
productGrsfType.setText(bean.getGrsfType());
currentStatus.setText(bean.getCurrentStatus().toString());
traceabilityFlag.setValue(bean.isTraceabilityFlag());
traceabilityFlag.setText("Traceability");
traceabilityFlag.setTitle("Current value for this flag in the Knowledge Base is " + bean.isTraceabilityFlag());
traceabilityFlag.addClickHandler(new ClickHandler() {
@Override
public void onClick(ClickEvent event) {
eventBus.fireEvent(new EnableConfirmButtonEvent());
}
});
@ -315,17 +332,17 @@ public class ManageProductWidget extends Composite{
}
});
annotationArea.addChangeHandler(new ChangeHandler() {
@Override
public void onChange(ChangeEvent event) {
eventBus.fireEvent(new EnableConfirmButtonEvent());
}
});
formUpdate.setVisible(true);
}
@ -374,11 +391,11 @@ public class ManageProductWidget extends Composite{
// if the status has not be changed ...
if(listBoxStatus.getSelectedIndex() <= 0){
bean.setNewStatus(bean.getCurrentStatus());
report = "-The Status is unchanged";
report = "- The Status is unchanged";
}
else{
bean.setNewStatus(Status.fromString(listBoxStatus.getSelectedItemText()));
report = "-The Status has been changed to " + bean.getNewStatus().getOrigName();
report = "- The Status has been changed to " + bean.getNewStatus().getOrigName();
hashtags.add(bean.getNewStatus().getOrigName());
}
@ -401,13 +418,19 @@ public class ManageProductWidget extends Composite{
// add the connections for the report
if(!bean.getConnections().isEmpty()){
report += "\n- Suggested connections:";
hashtags.add(HashTagsOnUpdate.CONNECT.getString());
boolean addConnectionHashtag = false;
for(ConnectedBean cb: bean.getConnections()){
if(cb.isRemove())
report += "\n\t - remove connection with record " + cb.getKnowledgeBaseId() + ";";
else if(cb.isConnect())
else if(cb.isConnect()){
addConnectionHashtag = true;
report += "\n\t - add connection with record " + cb.getKnowledgeBaseId() + ";";
}else
report += "\n\t - keep this suggestion " + cb.getKnowledgeBaseId() + ";";
}
if(addConnectionHashtag)
hashtags.add(HashTagsOnUpdate.CONNECT.getString());
}
// update similar records and to connect
@ -420,19 +443,21 @@ public class ManageProductWidget extends Composite{
bean.getSimilarGrsfRecords().addAll(suggestedMergesPanel.getSimilarRecords());
// set the merge operator on the bean if there is at least one merge to be done
for(SimilarGRSFRecord sR: bean.getSimilarGrsfRecords()){
if(!bean.getSimilarGrsfRecords().isEmpty()){
report += "\n- Suggested merges:";
if(sR.isSuggestedMerge()){
bean.setMergesInvolved(true);
report += "\n\t - merge the current record with record " + sR.getKnowledgeBaseId() + ";";
}
for(SimilarGRSFRecord sR: bean.getSimilarGrsfRecords()){
if(bean.isMergesInvolved()){
report += "\n- The update involves a merge operation.";
hashtags.add(HashTagsOnUpdate.MERGE.getString());
if(sR.isSuggestedMerge()){
bean.setMergesInvolved(true);
report += "\n\t - merge the current record with record " + sR.getKnowledgeBaseId() + ";";
}
if(bean.isMergesInvolved()){
report += "\n- The update involves a merge operation.";
hashtags.add(HashTagsOnUpdate.MERGE.getString());
}
}
}
// set new values
bean.setAnnotation(new HTML(annotationArea.getText().trim()).getText());
@ -456,6 +481,9 @@ public class ManageProductWidget extends Composite{
// set the report
bean.setReport(report);
// set hashtags
bean.setHashtags(hashtags);
GWT.log("Report is:\n" + report);
service.notifyProductUpdate(bean, new AsyncCallback<Void>() {
@ -469,6 +497,7 @@ public class ManageProductWidget extends Composite{
manageProductModal.setCloseVisible(true);
cancelButton.setEnabled(true);
loaderIcon.setVisible(false);
updateSucceeded = true;
}
@Override
@ -486,6 +515,9 @@ public class ManageProductWidget extends Composite{
@UiHandler("cancelButton")
void onCancelButton(ClickEvent ce){
manageProductModal.hide();
if(updateSucceeded)
Window.Location.reload();
}
/**

View File

@ -16,10 +16,6 @@
<b:Image ui:field="loadingImage" styleName="{style.loader-image}"
visible="true"></b:Image>
<!-- Alert blocks for info/errors -->
<b:AlertBlock type="INFO" close="false" animation="true"
visible="false" ui:field="infoBlock"></b:AlertBlock>
<b:Form type="VERTICAL" visible="true" ui:field="formUpdate"
width="100%">
@ -158,13 +154,18 @@
</b:ControlGroup>
</b:Form>
<!-- Alert blocks for info/errors -->
<b:AlertBlock type="INFO" close="false" animation="true"
visible="false" ui:field="infoBlock"></b:AlertBlock>
</g:VerticalPanel>
<b:ModalFooter>
<!-- Gear to wait while application tokens are retrieved -->
<b:Icon type="GEAR" spin="true" ui:field="loaderIcon"
visible="false" />
<b:Button ui:field="cancelButton">Cancel</b:Button>
<b:Button icon="FILE" type="PRIMARY" ui:field="confirmButton" enabled="false">Confirm</b:Button>
<b:Button icon="FILE" type="PRIMARY" ui:field="confirmButton"
enabled="false">Confirm</b:Button>
</b:ModalFooter>
</b:Modal>
</g:HTMLPanel>

View File

@ -81,7 +81,7 @@ public class GRSFUpdaterServiceClient {
}
return toReturn;
}
/**
* Send updates to the knowledge base
* @param httpClient
@ -125,8 +125,8 @@ public class GRSFUpdaterServiceClient {
cc.put(Constants.DEST_KNOWLEDGE_BASE_ID, c.getKnowledgeBaseId());
cc.put(Constants.SOURCE_DOMAIN, bean.getDomain());
cc.put(Constants.CONNECTION_TO_REMOVE, c.isRemove());
connectionsJson.add(cc);
}
connectionsJson.add(cc);
}
obj.put(Constants.CONNECTIONS, connectionsJson);
@ -143,6 +143,8 @@ public class GRSFUpdaterServiceClient {
logger.info("Update request looks like " + obj.toJSONString());
logger.info("Sending request to " + serviceUrl + Constants.SERVICE_POST_UPDATER_METHOD);
HttpPost request = new HttpPost(serviceUrl + Constants.SERVICE_POST_UPDATER_METHOD);
request.setHeader("Accept", "application/json");
request.setHeader("Content-type", "application/json");
@ -160,7 +162,7 @@ public class GRSFUpdaterServiceClient {
throw new Exception("There was a problem while performing this operation at knowledge base side");
if(response.getStatusLine().getStatusCode() == 200){
logger.info("Record updated " + bean);
logger.info("Record updated ");
}else if(!(boolean) parsedJSON.get(Constants.UPDATE_RESULT))
throw new IllegalArgumentException(
"Update failed for the following reason " + parsedJSON.get(Constants.ERROR_MESSAGE));

View File

@ -23,10 +23,9 @@ import org.gcube.datacatalogue.grsf_manage_widget.shared.RevertableOperations;
import org.gcube.resources.discovery.client.api.DiscoveryClient;
import org.gcube.resources.discovery.client.queries.api.SimpleQuery;
import org.gcube.vomanagement.usermanagement.RoleManager;
import org.gcube.vomanagement.usermanagement.UserManager;
import org.gcube.vomanagement.usermanagement.impl.LiferayRoleManager;
import org.gcube.vomanagement.usermanagement.impl.LiferayUserManager;
import org.gcube.vomanagement.usermanagement.model.GCubeTeam;
import org.gcube.vomanagement.usermanagement.model.GCubeUser;
import org.json.simple.JSONArray;
import org.json.simple.JSONObject;
import org.slf4j.Logger;
@ -59,9 +58,9 @@ public class SocialCommunications {
private static final String serviceClass = "Portal";
// social operations
private static final String SOCIAL_SERVICE_APPLICATION_TOKEN = "/2/tokens/generate-application-token/";
private static final String SOCIAL_SERVICE_WRITE_APPLICATION_POST = "/2/posts/write-post-app/";
private static final String SOCIAL_SEND_EMAIL = "/2/messages/write-message/";
private static final String SOCIAL_SERVICE_APPLICATION_TOKEN = "2/tokens/generate-application-token";
private static final String SOCIAL_SERVICE_WRITE_APPLICATION_POST = "2/posts/write-post-app";
private static final String SOCIAL_SEND_EMAIL = "2/messages/write-message";
private static final String MEDIATYPE_JSON = "application/json";
// for writing a post in the GRSF admin context
@ -70,17 +69,17 @@ public class SocialCommunications {
// emails to be sent to editors and reviewers and post to be written into the grsf admin vre
private static final String POST_MESSAGE = "Dear members,"
+ "<br>The record 'PRODUCT_TITLE' has been just updated by USER_FULLNAME."
+ "<br>You can inspect it here: PRODUCT_URL<br>";
+ "<br>You can inspect it here: LINK_RECORD.";
private static final String EMAIL_MESSAGE_REVIEWER = "Dear GRSF Reviewer,"
+ "<br>an update on the record named 'PRODUCT_TITLE' has been requested by USER_FULLNAME."
+ "<br>It is available here LINK_RECORD.";
+ "<br>You can inspect it here: LINK_RECORD.";
private static final String EMAIL_MESSAGE_EDITOR = "Dear USER_FULLNAME,"
+ "<br>your request for the record 'PRODUCT_TITLE' has been accepted."
+ "<br>It is available here LINK_RECORD.";
+ "<br>You can inspect it here: LINK_RECORD.";
private static final String ADD_REPORT = "<br>This is a summary of the actions proposed:<br>REPORT_UPDATE<br>";
private static final String ADD_REPORT = "<br> <br>This is a summary of the actions proposed: <br>REPORT_UPDATE<br>";
// revert link
private static final String REVERT_LINK_PIECE = "<br>The request involves a merge operation. You can reject the merge by exploiting this link LINK in the following 24 hours.";
@ -151,7 +150,9 @@ public class SocialCommunications {
String currentScope = ScopeProvider.instance.get();
String tokenUser = SecurityTokenProvider.instance.get();
logger.info("Current scope for writeProductPost is " + currentScope + " and token is " + tokenUser.substring(0, 10) + "***************");
//return "b159b50c-c0f8-4a4c-bac9-b6149d6b81fc-98187548";
logger.info("Current scope for requireApplicationToken is " + currentScope + " and token is " + tokenUser.substring(0, 10) + "***************");
String basePath = serviceUrl;
if(basePath == null){
@ -168,6 +169,7 @@ public class SocialCommunications {
// ask token application
HttpPost postRequest = new HttpPost(basePath + SOCIAL_SERVICE_APPLICATION_TOKEN + "?gcube-token=" + tokenUser);
JSONObject requestToken = new JSONObject();
// requestToken.put("app_id", APPLICATION_ID_CATALOGUE_MANAGER.split("\\.")[APPLICATION_ID_CATALOGUE_MANAGER.split("\\.").length - 1]); // TODO
requestToken.put("app_id", APPLICATION_ID_CATALOGUE_MANAGER);
StringEntity input = new StringEntity(requestToken.toJSONString());
input.setContentType(MEDIATYPE_JSON);
@ -189,9 +191,7 @@ public class SocialCommunications {
+ " Error message is " + mapResponseGeneratedToken.get("message"));
}else{
return (String)mapResponseGeneratedToken.get("result");
}
}
@ -219,7 +219,7 @@ public class SocialCommunications {
String currentScope = ScopeProvider.instance.get();
String tokenUser = SecurityTokenProvider.instance.get();
logger.info("Current scope for writeProductPost is " + currentScope + " and token is " + tokenUser.substring(0, 10) + "***************");
logger.info("Current scope for writePostOnRevert is " + currentScope + " and token is " + tokenUser.substring(0, 10) + "***************");
String basePath = serviceUrl;
if(basePath == null){
@ -300,12 +300,14 @@ public class SocialCommunications {
String applicationToken = requireApplicationToken(serviceUrl);
// replace
String message = POST_MESSAGE.replace("PRODUCT_TITLE", bean.getTitle()).replace("PRODUCT_URL", bean.getUrl()).
String message = POST_MESSAGE.replace("PRODUCT_TITLE", bean.getTitle()).replace("LINK_RECORD", bean.getUrl()).
replace("USER_FULLNAME", fullName);
if(bean.getReport() != null)
if(bean.getReport() != null && !bean.getReport().isEmpty())
message += ADD_REPORT.replace("REPORT_UPDATE", bean.getReport());
Set<String> hashtags = bean.getHashtags();
logger.debug("Hashtags are " + hashtags);
if(hashtags != null && !hashtags.isEmpty()){
message +="<br><br>";
for (String hashtag : hashtags) {
@ -345,30 +347,30 @@ public class SocialCommunications {
* @throws Exceptio
*/
@SuppressWarnings("unchecked")
public static void sendEmailAdministratorsOnMerge(
public static void sendEmailAdministrators(
String serviceUrl,
ManageProductBean bean,
DataCatalogue catalogue,
String username,
String fullName,
long groupId,
HttpServletRequest httpServletRequest,
String clientCurrenturl,
boolean isMergeInvolved) throws Exception {
// get the list of GRSF Reviewers to alert them as well
RoleManager roleManager = new LiferayRoleManager();
List<GCubeTeam> teamRoles = roleManager.listTeamsByGroup(groupId);
List<String> reviewers = new ArrayList<>();
UserManager um = new LiferayUserManager();
long teamRoleId = roleManager.getTeam(groupId, Constants.GRSF_CATALOGUE_REVIEWER_ROLE).getTeamId();
List<GCubeUser> reviewersGcube = new LiferayUserManager().listUsersByTeam(teamRoleId);
logger.debug("Reviewers are " + reviewersGcube);
for(GCubeTeam tr: teamRoles){
if(tr.getTeamName().equals(Constants.GRSF_CATALOGUE_REVIEWER_ROLE))
reviewers.add(um.getUserById(tr.getUserId()).getUsername());
List<String> reviewers = new ArrayList<String>(reviewersGcube.size());
for(GCubeUser gU: reviewersGcube){
// if the user is a reviewer, then send the email just once
if(!gU.getUsername().equals(username))
reviewers.add(gU.getUsername());
}
// if the user is a reviewer, then send the email just once
reviewers.remove(username);
logger.info("List of " + Constants.GRSF_CATALOGUE_REVIEWER_ROLE + " is " + reviewers);
// build the url that allows to revert the operation
@ -394,7 +396,10 @@ public class SocialCommunications {
/// require url
String applicationToken = requireApplicationToken(serviceUrl);
String revertUrl = getEncodedUrlManage(operation, username, System.currentTimeMillis(), bean.getKnowledgeBaseId(), httpServletRequest);
String revertUrl = "";
if(isMergeInvolved)
revertUrl = getEncodedUrlManage(operation, username, System.currentTimeMillis(), bean.getKnowledgeBaseId(), clientCurrenturl);
String messageToEditor = (EMAIL_MESSAGE_EDITOR +
(isMergeInvolved? REVERT_LINK_PIECE : "")).replace("USER_FULLNAME", fullName).replace("PRODUCT_TITLE", bean.getTitle()).
@ -402,6 +407,8 @@ public class SocialCommunications {
String messageToReviewer = (EMAIL_MESSAGE_REVIEWER+
(isMergeInvolved? REVERT_LINK_PIECE : "")).replace("USER_FULLNAME", fullName).replace("PRODUCT_TITLE", bean.getTitle()).
replace("LINK_RECORD", bean.getUrl()).replace("LINK", revertUrl);
String subject = "Update request on GRSF Record";
// append report
@ -410,6 +417,9 @@ public class SocialCommunications {
messageToReviewer += ADD_REPORT.replace("REPORT_UPDATE", bean.getReport());
}
messageToEditor = messageToEditor.replace("<br>", "\n");
messageToReviewer = messageToReviewer.replace("<br>", "\n");
// send email to the editor
logger.info("The message that is going to be send to the editor is\n" + messageToEditor);
HttpPost postRequest = new HttpPost(basePath + SOCIAL_SEND_EMAIL + "?gcube-token=" + applicationToken);
@ -424,6 +434,9 @@ public class SocialCommunications {
StringEntity input = new StringEntity(reqMessage.toJSONString());
input.setContentType(MEDIATYPE_JSON);
postRequest.setEntity(input);
logger.debug("Whole editor message is going to be " + reqMessage.toJSONString());
CloseableHttpResponse response = client.execute(postRequest);
Map<String, Object> mapResponseWritePost = getResponseEntityAsJSON(response);
@ -449,11 +462,14 @@ public class SocialCommunications {
input = new StringEntity(reqMessage.toJSONString());
input.setContentType(MEDIATYPE_JSON);
postRequest.setEntity(input);
logger.debug("Whole reviewers message is going to be " + reqMessage.toJSONString());
response = client.execute(postRequest);
mapResponseWritePost = getResponseEntityAsJSON(response);
if (response.getStatusLine().getStatusCode() != 201){
logger.error("Failed to send message to editor : HTTP error code : "
logger.error("Failed to send message to reviewers : HTTP error code : "
+ response.getStatusLine().getStatusCode() + mapResponseWritePost.get("message"));
}
@ -473,18 +489,18 @@ public class SocialCommunications {
// get the list of GRSF Reviewers to alert them as well
RoleManager roleManager = new LiferayRoleManager();
List<GCubeTeam> teamRoles = roleManager.listTeamsByGroup(groupId);
List<String> reviewers = new ArrayList<>();
UserManager um = new LiferayUserManager();
long teamRoleId = roleManager.getTeam(groupId, Constants.GRSF_CATALOGUE_REVIEWER_ROLE).getTeamId();
List<GCubeUser> reviewersGcube = new LiferayUserManager().listUsersByTeam(teamRoleId);
logger.debug("Reviewers are " + reviewersGcube);
for(GCubeTeam tr: teamRoles){
if(tr.getTeamName().equals(Constants.GRSF_CATALOGUE_REVIEWER_ROLE))
reviewers.add(um.getUserById(tr.getUserId()).getUsername());
List<String> reviewers = new ArrayList<String>(reviewersGcube.size());
for(GCubeUser gU: reviewersGcube){
// if the user is a reviewer, then send the email just once
if(!gU.getUsername().equals(rInfo.getUserNameOriginalAdmin()))
reviewers.add(gU.getUsername());
}
// if the user is a reviewer, then send the email just once
reviewers.remove(rInfo.getUserNameOriginalAdmin());
logger.info("List of " + Constants.GRSF_CATALOGUE_REVIEWER_ROLE + " is " + reviewers);
// discover service endpoint for the social networking library
@ -574,9 +590,9 @@ public class SocialCommunications {
* @return
* @throws Exception
*/
public static String getEncodedUrlManage(RevertableOperations operation, String administrator, long timestamp, String uuid, HttpServletRequest httpServletRequest) throws Exception{
String clientUrl = Utils.getCurrentClientUrl(httpServletRequest).split("\\?")[0]; // ignore other parameters
RevertOperationUrl operationUrl = new RevertOperationUrl(clientUrl, administrator, timestamp, uuid, operation);
public static String getEncodedUrlManage(RevertableOperations operation, String administrator, long timestamp, String uuid, String clientCurrenturl) throws Exception{
logger.info("Request for revert link. Client current url is " + clientCurrenturl);
RevertOperationUrl operationUrl = new RevertOperationUrl(clientCurrenturl, administrator, timestamp, uuid, operation);
String shortUrl = operationUrl.getShortUrl();
return shortUrl;
}

View File

@ -207,6 +207,9 @@ public class Utils {
// require social networking url
final String baseUrlSocial = SocialCommunications.getBaseUrlSocialService(httpServletRequest);
// and the user current browser url
final String currentBrowserUrl = Utils.getCurrentClientUrl(httpServletRequest).split("\\?")[0]; // ignore other parameters
// manage interactions through a separated thread but set there security token and context (and then reset them)
Thread t = new Thread(new Runnable() {
@ -217,10 +220,10 @@ public class Utils {
try{
// send email to Editors and Reviewers
SocialCommunications.sendEmailAdministratorsOnMerge(baseUrlSocial, bean, catalogue, username, fullName,
groupId, httpServletRequest, bean.isMergesInvolved());
SocialCommunications.sendEmailAdministrators(baseUrlSocial, bean, catalogue, username, fullName,
groupId, currentBrowserUrl, bean.isMergesInvolved());
// create a post about the operation
// create a post about the operation
SocialCommunications.writeProductPost(baseUrlSocial, bean, username, fullName, false);
}catch(Exception e){
@ -277,7 +280,7 @@ public class Utils {
SecurityTokenProvider.instance.reset();
}
}
});
t.start();