diff --git a/.classpath b/.classpath new file mode 100644 index 0000000..b834c89 --- /dev/null +++ b/.classpath @@ -0,0 +1,37 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/.project b/.project new file mode 100644 index 0000000..3471369 --- /dev/null +++ b/.project @@ -0,0 +1,42 @@ + + + invite-friends-widget + + + + + + org.eclipse.wst.jsdt.core.javascriptValidator + + + + + org.eclipse.jdt.core.javabuilder + + + + + org.eclipse.wst.common.project.facet.core.builder + + + + + org.eclipse.wst.validation.validationbuilder + + + + + org.eclipse.m2e.core.maven2Builder + + + + + + org.eclipse.jem.workbench.JavaEMFNature + org.eclipse.wst.common.modulecore.ModuleCoreNature + org.eclipse.jdt.core.javanature + org.eclipse.m2e.core.maven2Nature + org.eclipse.wst.common.project.facet.core.nature + org.eclipse.wst.jsdt.core.jsNature + + diff --git a/.settings/.jsdtscope b/.settings/.jsdtscope new file mode 100644 index 0000000..b72a6a4 --- /dev/null +++ b/.settings/.jsdtscope @@ -0,0 +1,13 @@ + + + + + + + + + + + + + diff --git a/.settings/com.google.gdt.eclipse.core.prefs b/.settings/com.google.gdt.eclipse.core.prefs new file mode 100644 index 0000000..2c23f71 --- /dev/null +++ b/.settings/com.google.gdt.eclipse.core.prefs @@ -0,0 +1,5 @@ +eclipse.preferences.version=1 +jarsExcludedFromWebInfLib= +lastWarOutDir=/Users/massi/Documents/workspace/invite-friends-wdiget/target/session-checker-0.1.0-SNAPSHOT +warSrcDir=src/main/webapp +warSrcDirIsOutput=false diff --git a/.settings/com.google.gwt.eclipse.core.prefs b/.settings/com.google.gwt.eclipse.core.prefs new file mode 100644 index 0000000..c803c44 --- /dev/null +++ b/.settings/com.google.gwt.eclipse.core.prefs @@ -0,0 +1,5 @@ +#Thu Jun 16 11:14:17 CEST 2011 +eclipse.preferences.version=1 +entryPointModules= +filesCopiedToWebInfLib=gwt-servlet.jar +gwtCompileSettings=PGd3dC1jb21waWxlLXNldHRpbmdzPjxsb2ctbGV2ZWw+SU5GTzwvbG9nLWxldmVsPjxvdXRwdXQtc3R5bGU+T0JGVVNDQVRFRDwvb3V0cHV0LXN0eWxlPjxleHRyYS1hcmdzPjwhW0NEQVRBWy13YXIgc3JjL21haW4vd2ViYXBwXV0+PC9leHRyYS1hcmdzPjx2bS1hcmdzPjwhW0NEQVRBWy1YbXg1MTJtXV0+PC92bS1hcmdzPjxlbnRyeS1wb2ludC1tb2R1bGU+Y29tLmNvbXBhbnkuU29tZU1vZHVsZTwvZW50cnktcG9pbnQtbW9kdWxlPjwvZ3d0LWNvbXBpbGUtc2V0dGluZ3M+ diff --git a/.settings/org.eclipse.core.resources.prefs b/.settings/org.eclipse.core.resources.prefs new file mode 100644 index 0000000..29abf99 --- /dev/null +++ b/.settings/org.eclipse.core.resources.prefs @@ -0,0 +1,6 @@ +eclipse.preferences.version=1 +encoding//src/main/java=UTF-8 +encoding//src/main/resources=UTF-8 +encoding//src/test/java=UTF-8 +encoding//src/test/resources=UTF-8 +encoding/=UTF-8 diff --git a/.settings/org.eclipse.jdt.core.prefs b/.settings/org.eclipse.jdt.core.prefs new file mode 100644 index 0000000..443e085 --- /dev/null +++ b/.settings/org.eclipse.jdt.core.prefs @@ -0,0 +1,8 @@ +eclipse.preferences.version=1 +org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled +org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.7 +org.eclipse.jdt.core.compiler.compliance=1.7 +org.eclipse.jdt.core.compiler.problem.assertIdentifier=error +org.eclipse.jdt.core.compiler.problem.enumIdentifier=error +org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning +org.eclipse.jdt.core.compiler.source=1.7 diff --git a/.settings/org.eclipse.m2e.core.prefs b/.settings/org.eclipse.m2e.core.prefs new file mode 100644 index 0000000..f897a7f --- /dev/null +++ b/.settings/org.eclipse.m2e.core.prefs @@ -0,0 +1,4 @@ +activeProfiles= +eclipse.preferences.version=1 +resolveWorkspaceProjects=true +version=1 diff --git a/.settings/org.eclipse.wst.common.component b/.settings/org.eclipse.wst.common.component new file mode 100644 index 0000000..10d1970 --- /dev/null +++ b/.settings/org.eclipse.wst.common.component @@ -0,0 +1,13 @@ + + + + + + + + uses + + + + + diff --git a/.settings/org.eclipse.wst.common.project.facet.core.xml b/.settings/org.eclipse.wst.common.project.facet.core.xml new file mode 100644 index 0000000..735eb31 --- /dev/null +++ b/.settings/org.eclipse.wst.common.project.facet.core.xml @@ -0,0 +1,7 @@ + + + + + + + diff --git a/.settings/org.eclipse.wst.jsdt.ui.superType.container b/.settings/org.eclipse.wst.jsdt.ui.superType.container new file mode 100644 index 0000000..3bd5d0a --- /dev/null +++ b/.settings/org.eclipse.wst.jsdt.ui.superType.container @@ -0,0 +1 @@ +org.eclipse.wst.jsdt.launching.baseBrowserLibrary \ No newline at end of file diff --git a/.settings/org.eclipse.wst.jsdt.ui.superType.name b/.settings/org.eclipse.wst.jsdt.ui.superType.name new file mode 100644 index 0000000..05bd71b --- /dev/null +++ b/.settings/org.eclipse.wst.jsdt.ui.superType.name @@ -0,0 +1 @@ +Window \ No newline at end of file diff --git a/.settings/org.eclipse.wst.validation.prefs b/.settings/org.eclipse.wst.validation.prefs new file mode 100644 index 0000000..04cad8c --- /dev/null +++ b/.settings/org.eclipse.wst.validation.prefs @@ -0,0 +1,2 @@ +disabled=06target +eclipse.preferences.version=1 diff --git a/pom.xml b/pom.xml new file mode 100644 index 0000000..b054090 --- /dev/null +++ b/pom.xml @@ -0,0 +1,244 @@ + + + + 4.0.0 + org.gcube.portlets.widgets + invite-friends-widget + war + 0.0.1-SNAPSHOT + gCube Invites widget + + gCube Session Checker Widget is a GWT Widget that can be used to automatically check if the session expired. + + + scm:svn:http://svn.d4science.research-infrastructures.eu/gcube/trunk/portlets/widgets/${project.artifactId} + scm:https://svn.d4science.research-infrastructures.eu/gcube/trunk/portlets/widgets/${project.artifactId} + http://svn.d4science.research-infrastructures.eu/gcube/trunk/portlets/widgets/${project.artifactId} + + + + + 2.7.0 + distro + 1.7 + 1.7 + UTF-8 + UTF-8 + + + + + org.gcube.distribution + maven-portal-bom + LATEST + pom + import + + + com.google.gwt + gwt + ${gwtVersion} + pom + import + + + + + + + org.gcube.common.portal + portal-manager + provided + + + com.google.gwt + gwt-servlet + ${gwtVersion} + provided + + + com.google.gwt + gwt-user + ${gwtVersion} + provided + + + com.google.gwt + gwt-dev + ${gwtVersion} + provided + + + org.gcube.portlets.user + gcube-widgets + provided + + + org.gcube.portal + custom-portal-handler + provided + + + org.gcube.common.portal + portal-manager + provided + + + org.gcube.applicationsupportlayer + aslcore + provided + + + org.gcube.portal + invites-common-library + [0.1.0-SNAPSHOT,) + + + org.gcube.portal + social-networking-library + provided + + + com.google + gwt-jsonmaker + + + com.github.gwtbootstrap + gwt-bootstrap + 2.3.2.0 + + + org.jsoup + jsoup + 1.6.2 + + + javax.portlet + portlet-api + provided + + + com.liferay.portal + portal-service + provided + + + + + ${webappDirectory}/WEB-INF/classes + + + src/main/java + + **/*.* + + + + src/main/resources + + **/*.* + + + + + + + org.codehaus.mojo + gwt-maven-plugin + ${gwtVersion} + + + + org.gcube.portlets.widgets.inviteswidget.InvitesWidget + + + + + + + + + + InvitesWidget.html + ${webappDirectory} + + + + + + org.apache.maven.plugins + maven-war-plugin + 2.1.1 + + + compile + + exploded + + + + + ${webappDirectory} + + + + org.apache.maven.plugins + maven-compiler-plugin + 2.3.2 + + 1.7 + 1.7 + + + + + org.apache.maven.plugins + maven-assembly-plugin + 2.2 + + + ${distroDirectory}/descriptor.xml + + + + + servicearchive + install + + single + + + + + + org.apache.maven.plugins + maven-resources-plugin + 2.5 + + + copy-profile + install + + copy-resources + + + target + + + ${distroDirectory} + true + + profile.xml + + + + + + + + + + + \ No newline at end of file diff --git a/src/main/java/org/gcube/portlets/widgets/inviteswidget/client/InviteService.java b/src/main/java/org/gcube/portlets/widgets/inviteswidget/client/InviteService.java new file mode 100644 index 0000000..e74951a --- /dev/null +++ b/src/main/java/org/gcube/portlets/widgets/inviteswidget/client/InviteService.java @@ -0,0 +1,14 @@ +package org.gcube.portlets.widgets.inviteswidget.client; + +import org.gcube.portal.databook.shared.InviteOperationResult; + +import com.google.gwt.user.client.rpc.RemoteService; +import com.google.gwt.user.client.rpc.RemoteServiceRelativePath; + +/** + * The client side stub for the RPC service. + */ +@RemoteServiceRelativePath("greet") +public interface InviteService extends RemoteService { + InviteOperationResult sendInvite(String name, String lastName, String email) throws IllegalArgumentException; +} diff --git a/src/main/java/org/gcube/portlets/widgets/inviteswidget/client/InviteServiceAsync.java b/src/main/java/org/gcube/portlets/widgets/inviteswidget/client/InviteServiceAsync.java new file mode 100644 index 0000000..b9f8bcc --- /dev/null +++ b/src/main/java/org/gcube/portlets/widgets/inviteswidget/client/InviteServiceAsync.java @@ -0,0 +1,12 @@ +package org.gcube.portlets.widgets.inviteswidget.client; + +import org.gcube.portal.databook.shared.InviteOperationResult; + +import com.google.gwt.user.client.rpc.AsyncCallback; + +public interface InviteServiceAsync { + + void sendInvite(String name, String lastName, String email, + AsyncCallback callback); + +} diff --git a/src/main/java/org/gcube/portlets/widgets/inviteswidget/client/InvitesWidget.java b/src/main/java/org/gcube/portlets/widgets/inviteswidget/client/InvitesWidget.java new file mode 100644 index 0000000..015c3d3 --- /dev/null +++ b/src/main/java/org/gcube/portlets/widgets/inviteswidget/client/InvitesWidget.java @@ -0,0 +1,18 @@ +package org.gcube.portlets.widgets.inviteswidget.client; + +import org.gcube.portlets.widgets.inviteswidget.client.ui.InviteWidget; + +import com.google.gwt.core.client.EntryPoint; +import com.google.gwt.user.client.ui.RootPanel; + +/** + * Entry point classes define onModuleLoad(). + */ +public class InvitesWidget implements EntryPoint { + /** + * This is the entry point method. + */ + public void onModuleLoad() { + RootPanel.get("invite-friends-DIV").add(new InviteWidget()); + } +} diff --git a/src/main/java/org/gcube/portlets/widgets/inviteswidget/client/ui/FormViewImpl.java b/src/main/java/org/gcube/portlets/widgets/inviteswidget/client/ui/FormViewImpl.java new file mode 100644 index 0000000..3d35dae --- /dev/null +++ b/src/main/java/org/gcube/portlets/widgets/inviteswidget/client/ui/FormViewImpl.java @@ -0,0 +1,164 @@ +/** + * + */ +package org.gcube.portlets.widgets.inviteswidget.client.ui; + +import org.gcube.portal.databook.shared.InviteOperationResult; +import org.gcube.portlets.widgets.inviteswidget.client.InviteService; +import org.gcube.portlets.widgets.inviteswidget.client.InviteServiceAsync; +import org.gcube.portlets.widgets.inviteswidget.client.validation.FormView; + +import com.github.gwtbootstrap.client.ui.Button; +import com.github.gwtbootstrap.client.ui.ControlGroup; +import com.github.gwtbootstrap.client.ui.HelpBlock; +import com.github.gwtbootstrap.client.ui.Modal; +import com.github.gwtbootstrap.client.ui.TextBox; +import com.github.gwtbootstrap.client.ui.constants.ControlGroupType; +import com.google.gwt.core.client.GWT; +import com.google.gwt.editor.client.Editor; +import com.google.gwt.editor.client.EditorDriver; +import com.google.gwt.editor.client.SimpleBeanEditorDriver; +import com.google.gwt.event.dom.client.ClickEvent; +import com.google.gwt.event.dom.client.KeyCodes; +import com.google.gwt.event.dom.client.KeyDownEvent; +import com.google.gwt.event.dom.client.KeyDownHandler; +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.Timer; +import com.google.gwt.user.client.rpc.AsyncCallback; +import com.google.gwt.user.client.ui.Composite; +import com.google.gwt.user.client.ui.Widget; + +/** + * + * @author Massimiliano Assante, ISTI-CNR + * + */ +public class FormViewImpl extends Composite implements FormView, Editor { + + /** + * Create a remote service proxy to talk to the server-side service + */ + private final InviteServiceAsync service = GWT.create(InviteService.class); + + interface Binder extends UiBinder {} + private static Binder uiBinder = GWT.create(Binder.class); + + interface Driver extends SimpleBeanEditorDriver { } + private Driver driver = GWT.create(Driver.class); + + private final Delegate delegate; + + @UiField TextBox email; + @UiField TextBox name; + + @UiField Button openModal; + @UiField Button cancelInvite; + @UiField Button sendInvite; + @UiField Modal modalWindow; + @UiField HelpBlock nameErrors; + @UiField HelpBlock feedback; + + @UiField + ControlGroup nameGroup; + @UiField + ControlGroup feedbackGroup; + + public FormViewImpl(Delegate delegate) { + super(); + this.delegate = delegate; + initWidget(uiBinder.createAndBindUi(this)); + driver.initialize(this); + driver.edit(new UserDetails()); + + email.addKeyDownHandler(new KeyDownHandler() { + @Override + public void onKeyDown(KeyDownEvent event) { + if (event.getNativeKeyCode() == KeyCodes.KEY_ENTER) + openModal.click(); + } + }); + + name.addKeyDownHandler(new KeyDownHandler() { + @Override + public void onKeyDown(KeyDownEvent event) { + if (event.getNativeKeyCode() == KeyCodes.KEY_ENTER) + sendInvite.click(); + } + }); + + sendInvite.setEnabled(true); + } + + @UiHandler("openModal") + void onUserClick(ClickEvent event) { + if (!delegate.onSendClick()) { + sendInvite.setEnabled(true); + feedback.setText("We will send the invitation email to: "+email.getText() + " and put you in cc, we'll never email your contacts without your say so."); + name.setText(""); + modalWindow.show(); + Timer t = new Timer() { + @Override + public void run() { + name.setFocus(true); + } + }; + t.schedule(1000); + } + } + + @UiHandler("sendInvite") + void onSendInviteClick(ClickEvent event) { + if (delegate.onEmailSendInviteClick()) { + nameGroup.setType(ControlGroupType.ERROR); + nameErrors.setText("Name must not be null"); + } else { + nameGroup.setType(ControlGroupType.NONE); + nameErrors.setText(""); + service.sendInvite(name.getText(), "", email.getText(), new AsyncCallback() { + + @Override + public void onSuccess(InviteOperationResult result) { + switch (result) { + case SUCCESS: + feedback.setText("Thanks for inviting, we sent the email correctly."); + feedbackGroup.setType(ControlGroupType.SUCCESS); + break; + case ALREADY_INVITED: + feedback.setText("Thanks for inviting, however the user was already invited."); + feedbackGroup.setType(ControlGroupType.WARNING); + break; + case FAILED: + feedback.setText("Sorry, an error occurred in the server and we could not send the invite, please try again later."); + feedbackGroup.setType(ControlGroupType.ERROR); + break; + } + sendInvite.setEnabled(false); + cancelInvite.setText("Close"); + email.setText(""); + } + + @Override + public void onFailure(Throwable caught) { + feedback.setText("Sorry, an error occurred and we could not send the invite, please try again later."); + feedbackGroup.setType(ControlGroupType.ERROR); + sendInvite.setEnabled(false); + email.setText(""); + } + }); + } + } + + @UiHandler("cancelInvite") + public void onCancelClick(ClickEvent e) { + modalWindow.hide(); + email.setText(""); + } + + @Override + public EditorDriver getEditorDriver() { + return driver; + } +} + diff --git a/src/main/java/org/gcube/portlets/widgets/inviteswidget/client/ui/FormViewImpl.ui.xml b/src/main/java/org/gcube/portlets/widgets/inviteswidget/client/ui/FormViewImpl.ui.xml new file mode 100644 index 0000000..d103a9c --- /dev/null +++ b/src/main/java/org/gcube/portlets/widgets/inviteswidget/client/ui/FormViewImpl.ui.xml @@ -0,0 +1,30 @@ + + + + + + + + Send Invite + + + + + + + + + + + + + + Cancel + Send Invite + + + + \ No newline at end of file diff --git a/src/main/java/org/gcube/portlets/widgets/inviteswidget/client/ui/InviteWidget.java b/src/main/java/org/gcube/portlets/widgets/inviteswidget/client/ui/InviteWidget.java new file mode 100644 index 0000000..a6c1108 --- /dev/null +++ b/src/main/java/org/gcube/portlets/widgets/inviteswidget/client/ui/InviteWidget.java @@ -0,0 +1,35 @@ +package org.gcube.portlets.widgets.inviteswidget.client.ui; + +import org.gcube.portlets.widgets.inviteswidget.client.validation.FormErrorsValidation; + +import com.google.gwt.core.client.GWT; +import com.google.gwt.uibinder.client.UiBinder; +import com.google.gwt.uibinder.client.UiField; +import com.google.gwt.user.client.ui.Composite; +import com.google.gwt.user.client.ui.HTML; +import com.google.gwt.user.client.ui.SimplePanel; +import com.google.gwt.user.client.ui.Widget; +/** + * + * @author Massimiliano Assante, ISTI-CNR + * + */ +public class InviteWidget extends Composite{ + + public static final String DISPLAY_NAME = "Invite whoever's missing"; + + private static InviteWidgetUiBinder uiBinder = GWT.create(InviteWidgetUiBinder.class); + + interface InviteWidgetUiBinder extends UiBinder { } + + @UiField HTML header; + @UiField SimplePanel validationErrorsFormPanel; + + public InviteWidget() { + super(); + initWidget(uiBinder.createAndBindUi(this)); + header.setText(DISPLAY_NAME); + new FormErrorsValidation().start(validationErrorsFormPanel, null); + } + +} diff --git a/src/main/java/org/gcube/portlets/widgets/inviteswidget/client/ui/InviteWidget.ui.xml b/src/main/java/org/gcube/portlets/widgets/inviteswidget/client/ui/InviteWidget.ui.xml new file mode 100644 index 0000000..8101f43 --- /dev/null +++ b/src/main/java/org/gcube/portlets/widgets/inviteswidget/client/ui/InviteWidget.ui.xml @@ -0,0 +1,8 @@ + + + + + + + \ No newline at end of file diff --git a/src/main/java/org/gcube/portlets/widgets/inviteswidget/client/validation/FormErrorsValidation.java b/src/main/java/org/gcube/portlets/widgets/inviteswidget/client/validation/FormErrorsValidation.java new file mode 100644 index 0000000..382447f --- /dev/null +++ b/src/main/java/org/gcube/portlets/widgets/inviteswidget/client/validation/FormErrorsValidation.java @@ -0,0 +1,178 @@ +/** + * + */ +package org.gcube.portlets.widgets.inviteswidget.client.validation; + +import java.util.HashSet; +import java.util.Set; + +import javax.validation.ConstraintViolation; +import javax.validation.Path; +import javax.validation.metadata.ConstraintDescriptor; + +import org.gcube.portlets.widgets.inviteswidget.client.ui.FormViewImpl; +import org.gcube.portlets.widgets.inviteswidget.client.validation.FormView.UserDetails; + +import com.google.gwt.activity.shared.AbstractActivity; +import com.google.gwt.editor.client.EditorDriver; +import com.google.gwt.event.shared.EventBus; +import com.google.gwt.user.client.ui.AcceptsOneWidget; +import com.google.gwt.validation.client.impl.PathImpl; + +/** + * + * @author Massimiliano Assante, ISTI-CNR + * + */ +public class FormErrorsValidation extends AbstractActivity implements FormView.Delegate { + + private FormView view; + /** + * @see com.google.gwt.activity.shared.Activity#start(com.google.gwt.user.client.ui.AcceptsOneWidget, com.google.gwt.event.shared.EventBus) + */ + @Override + public void start(AcceptsOneWidget panel, EventBus eventBus) { + view = new FormViewImpl(this); + panel.setWidget(view); + } + + @SuppressWarnings({ "unchecked", "rawtypes" }) + @Override + public boolean onSendClick() { + EditorDriver editorDriver = view.getEditorDriver(); + UserDetails details = editorDriver.flush(); + Set> violations = validateEmailTextBox(details); + //decorate widgets implementing HasEditorErrors with validation messages + return editorDriver.setConstraintViolations( (Set) violations); + } + + @SuppressWarnings({ "unchecked", "rawtypes" }) + @Override + public boolean onEmailSendInviteClick() { + EditorDriver editorDriver = view.getEditorDriver(); + UserDetails details = editorDriver.flush(); + Set> violations = validateName(details); + return !violations.isEmpty(); + } + + private Set> validateName(UserDetails user2InviteBean) { + Set> violations = new HashSet>(); + if(user2InviteBean.getName() == null || "".equals(user2InviteBean.getName().trim())) { + violations.add(buildNotNullConstraintViolation(user2InviteBean, "name")); + } + return violations; + } + + private Set> validateEmailTextBox(UserDetails user2InviteBean){ + Set> violations = new HashSet>(); + if(user2InviteBean.getEmail() == null || "".equals(user2InviteBean.getEmail().trim())) { + violations.add(buildNotNullConstraintViolation(user2InviteBean, "email")); + } + else if (!isValidEmailAddress(user2InviteBean.getEmail())) { + violations.add(buildInvalidEmailAddressConstraintViolation(user2InviteBean, "email")); + } + + return violations; + } + + + private ConstraintViolation buildNotNullConstraintViolation(final UserDetails bean, final String path) { + return new ConstraintViolation() { + @Override + public String getMessage() { + return "must not be empty"; + } + @Override + public String getMessageTemplate() { + return null; + } + @Override + public UserDetails getRootBean() { + return bean; + } + @Override + public Class getRootBeanClass() { + return UserDetails.class; + } + @Override + public Object getLeafBean() { + return bean; + } + + @Override + public Path getPropertyPath() { + return new PathImpl().append(path); + } + + @Override + public Object getInvalidValue() { + return null; + } + @Override + public ConstraintDescriptor getConstraintDescriptor() { + return null; + } + }; + } + + private ConstraintViolation buildInvalidEmailAddressConstraintViolation(final UserDetails bean, final String path) { + return new ConstraintViolation() { + @Override + public String getMessage() { + return "email address must be valid"; + } + @Override + public String getMessageTemplate() { + return null; + } + @Override + public UserDetails getRootBean() { + return bean; + } + @Override + public Class getRootBeanClass() { + return UserDetails.class; + } + @Override + public Object getLeafBean() { + return bean; + } + + @Override + public Path getPropertyPath() { + return new PathImpl().append(path); + } + + @Override + public Object getInvalidValue() { + return null; + } + @Override + public ConstraintDescriptor getConstraintDescriptor() { + return null; + } + }; + } + /** + * + * @param emailValue + * @return + */ + private boolean isValidEmailAddress(String emailValue) { + if(emailValue == null) return true; + + String emailPattern = "^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.(?:[a-zA-Z]{2,6})$"; + + boolean valid = false; + + if(emailValue.getClass().toString().equals(String.class.toString())) { + valid = ((String)emailValue).matches(emailPattern); + } else { + valid = ((Object)emailValue).toString().matches(emailPattern); + } + + return valid; +} + + +} diff --git a/src/main/java/org/gcube/portlets/widgets/inviteswidget/client/validation/FormView.java b/src/main/java/org/gcube/portlets/widgets/inviteswidget/client/validation/FormView.java new file mode 100644 index 0000000..d99b552 --- /dev/null +++ b/src/main/java/org/gcube/portlets/widgets/inviteswidget/client/validation/FormView.java @@ -0,0 +1,57 @@ +/** + * + */ +package org.gcube.portlets.widgets.inviteswidget.client.validation; + +import com.google.gwt.editor.client.EditorDriver; +import com.google.gwt.user.client.ui.IsWidget; + +/** + * + * @author Massimiliano Assante, ISTI-CNR + * + */ +public interface FormView extends IsWidget { + + public static class UserDetails { + String email; + String name; + String lastName; + + public String getEmail() { + return email; + } + public void setEmail(String email) { + this.email = email; + } + public String getName() { + return name; + } + public void setName(String name) { + this.name = name; + } + + public String getLastName() { + return lastName; + } + public void setLastName(String lastName) { + this.lastName = lastName; + } + @Override + public String toString() { + return "UserDetails [email=" + email + ", name=" + name + + ", lastName=" + lastName + "]"; + } + + } + + public interface Delegate { + boolean onSendClick(); + + boolean onEmailSendInviteClick(); + } + + + + EditorDriver getEditorDriver(); +} diff --git a/src/main/java/org/gcube/portlets/widgets/inviteswidget/server/InviteServiceImpl.java b/src/main/java/org/gcube/portlets/widgets/inviteswidget/server/InviteServiceImpl.java new file mode 100644 index 0000000..d30cb8b --- /dev/null +++ b/src/main/java/org/gcube/portlets/widgets/inviteswidget/server/InviteServiceImpl.java @@ -0,0 +1,68 @@ +package org.gcube.portlets.widgets.inviteswidget.server; + +import org.gcube.application.framework.core.session.ASLSession; +import org.gcube.application.framework.core.session.SessionManager; +import org.gcube.common.portal.*; +import org.gcube.portal.custom.communitymanager.OrganizationsUtil; +import org.gcube.portal.custom.scopemanager.scopehelper.ScopeHelper; +import org.gcube.portal.databook.shared.InviteOperationResult; +import org.gcube.portal.invites.InvitesManager; +import org.gcube.portlets.widgets.inviteswidget.client.InviteService; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import com.liferay.portal.util.PortalUtil; +import com.google.gwt.user.server.rpc.RemoteServiceServlet; +import com.liferay.portal.service.OrganizationLocalServiceUtil; + + +/** + * The server side implementation of the RPC service. + */ +@SuppressWarnings("serial") +public class InviteServiceImpl extends RemoteServiceServlet implements InviteService { + + private final static Logger _log = LoggerFactory.getLogger(InviteServiceImpl.class); + + /** + * the current ASLSession + * @return the session + */ + private ASLSession getASLSession() { + String sessionID = this.getThreadLocalRequest().getSession().getId(); + String user = (String) this.getThreadLocalRequest().getSession().getAttribute(ScopeHelper.USERNAME_ATTRIBUTE); + if (user == null) { + _log.warn("USER IS NULL setting test.user"); + user = "test.user"; + } + else { + _log.info("LIFERAY PORTAL DETECTED user=" + user); + } + return SessionManager.getInstance().getASLSession(sessionID, user); + } + /** + * + */ + @Override + public InviteOperationResult sendInvite(String name, String lastName, String email) throws IllegalArgumentException { + ASLSession aslSession = getASLSession(); + + String portalUrl = null; + String vreDescription = null; + long organizationId = getASLSession().getGroupId(); + try { + portalUrl = PortalUtil.getPortalURL(OrganizationsUtil.getCompany().getVirtualHost(), PortalUtil.getPortalPort(), true); + vreDescription = OrganizationLocalServiceUtil.getOrganization(organizationId).getComments(); + } catch (Exception e1) { + e1.printStackTrace(); + _log.warn("While trying to send email for invitation to " + email); + return null; + } + String portalSenderEmail = PortalContext.getConfiguration().getSenderEmail(); + return InvitesManager.getInstance().sendInvite(aslSession, portalSenderEmail, portalUrl, name, lastName, email, vreDescription); + } + + + + + +} diff --git a/src/main/java/org/gcube/portlets/widgets/inviteswidget/shared/FieldVerifier.java b/src/main/java/org/gcube/portlets/widgets/inviteswidget/shared/FieldVerifier.java new file mode 100644 index 0000000..45c7207 --- /dev/null +++ b/src/main/java/org/gcube/portlets/widgets/inviteswidget/shared/FieldVerifier.java @@ -0,0 +1,42 @@ +package org.gcube.portlets.widgets.inviteswidget.shared; + +/** + *

+ * FieldVerifier validates that the name the user enters is valid. + *

+ *

+ * This class is in the shared packing because we use it in both + * the client code and on the server. On the client, we verify that the name is + * valid before sending an RPC request so the user doesn't have to wait for a + * network round trip to get feedback. On the server, we verify that the name is + * correct to ensure that the input is correct regardless of where the RPC + * originates. + *

+ *

+ * When creating a class that is used on both the client and the server, be sure + * that all code is translatable and does not use native JavaScript. Code that + * is note translatable (such as code that interacts with a database or the file + * system) cannot be compiled into client side JavaScript. Code that uses native + * JavaScript (such as Widgets) cannot be run on the server. + *

+ */ +public class FieldVerifier { + + /** + * Verifies that the specified name is valid for our service. + * + * In this example, we only require that the name is at least four + * characters. In your application, you can use more complex checks to ensure + * that usernames, passwords, email addresses, URLs, and other fields have the + * proper syntax. + * + * @param name the name to validate + * @return true if valid, false if invalid + */ + public static boolean isValidName(String name) { + if (name == null) { + return false; + } + return name.length() > 3; + } +} diff --git a/src/main/resources/org/gcube/portlets/widgets/inviteswidget/InvitesWidget.gwt.xml b/src/main/resources/org/gcube/portlets/widgets/inviteswidget/InvitesWidget.gwt.xml new file mode 100644 index 0000000..fe892e5 --- /dev/null +++ b/src/main/resources/org/gcube/portlets/widgets/inviteswidget/InvitesWidget.gwt.xml @@ -0,0 +1,20 @@ + + + + + + + + + + + + + + + + + + + diff --git a/src/main/webapp/InvitesWidget.css b/src/main/webapp/InvitesWidget.css new file mode 100644 index 0000000..7aca7ac --- /dev/null +++ b/src/main/webapp/InvitesWidget.css @@ -0,0 +1,34 @@ +/** Add css rules here for your application. */ + + +/** Example rules used by the template application (remove for your app) */ +h1 { + font-size: 2em; + font-weight: bold; + color: #777777; + margin: 40px 0px 70px; + text-align: center; +} + +.sendButton { + display: block; + font-size: 16pt; +} + +/** Most GWT widgets already have a style name defined */ +.gwt-DialogBox { + width: 400px; +} + +.dialogVPanel { + margin: 5px; +} + +.serverResponseLabelError { + color: red; +} + +/** Set ids using widget.getElement().setId("idOfElement") */ +#closeButton { + margin: 15px 6px 6px; +} diff --git a/src/main/webapp/InvitesWidget.html b/src/main/webapp/InvitesWidget.html new file mode 100644 index 0000000..60561bd --- /dev/null +++ b/src/main/webapp/InvitesWidget.html @@ -0,0 +1,38 @@ + + + + + + + + + + + + + + + + + + + + Web Application Starter Project + + + + + + + + + + + + + + + +
+ + diff --git a/src/main/webapp/WEB-INF/web.xml b/src/main/webapp/WEB-INF/web.xml new file mode 100644 index 0000000..60959c7 --- /dev/null +++ b/src/main/webapp/WEB-INF/web.xml @@ -0,0 +1,24 @@ + + + + + + + + greetServlet + org.gcube.portlets.widgets.inviteswidget.server.InviteServiceImpl + + + + greetServlet + /InvitesWidget/greet + + + + + InvitesWidget.html + + + diff --git a/src/test/resources/org/gcube/portlets/widgets/inviteswidget/InvitesWidgetJUnit.gwt.xml b/src/test/resources/org/gcube/portlets/widgets/inviteswidget/InvitesWidgetJUnit.gwt.xml new file mode 100644 index 0000000..8f786a9 --- /dev/null +++ b/src/test/resources/org/gcube/portlets/widgets/inviteswidget/InvitesWidgetJUnit.gwt.xml @@ -0,0 +1,9 @@ + + + + + + + + +