Added input validation in invitation form (issue #1815)
[pithos-web-client] / src / gr / grnet / pithos / web / client / InvitationsDialog.java
index 97dd954..3b11130 100644 (file)
@@ -52,22 +52,32 @@ import com.google.gwt.user.client.ui.FlexTable;
 import com.google.gwt.user.client.ui.HTML;
 import com.google.gwt.user.client.ui.HasHorizontalAlignment;
 import com.google.gwt.user.client.ui.HorizontalPanel;
+import com.google.gwt.user.client.ui.Image;
 import com.google.gwt.user.client.ui.TextBox;
 import com.google.gwt.user.client.ui.VerticalPanel;
+import com.google.gwt.user.client.ui.Widget;
 
 
 /**
  * A dialog box that displays info about invitations
  */
 public class InvitationsDialog extends DialogBox {
-
-       private final String WIDTH_FIELD = "35em";
-       private final String WIDTH_TEXT = "42em";
-
+       private static final int INV_PER_PAGE = 5;
+       
+       Pithos app;
+       VerticalPanel messagesPanel;
+       int rows = 0;
+       FlexTable sentInvitationsTable; 
+       /**
+        * The current displayed page of sent invitations 
+        */
+       int currentPage = 0;
+       HorizontalPanel pagerPanel;     
        /**
         * The widget constructor.
         */
-       public InvitationsDialog(final Pithos app, Invitations inv) {
+       public InvitationsDialog(Pithos _app, final Invitations inv) {
+               this.app = _app;
                Anchor close = new Anchor();
                close.addStyleName("close");
                close.addClickHandler(new ClickHandler() {
@@ -78,80 +88,270 @@ public class InvitationsDialog extends DialogBox {
                        }
                });
                // Set the dialog's caption.
-               setText("Invite people (" + inv.getInvitationsLeft() + " invitations left)");
+               setText("Invite friends");
                setAnimationEnabled(true);
                setGlassEnabled(true);
                setStyleName("pithos-DialogBox");
                VerticalPanel outer = new VerticalPanel();
-               outer.add(close);
+               outer.addStyleName("outer");
+               outer.setHorizontalAlignment(HasHorizontalAlignment.ALIGN_LEFT);
 
                VerticalPanel inner = new VerticalPanel();
                inner.addStyleName("inner");
                // Create the text and set a style name so we can style it with CSS.
-               HTML text = new HTML("You have " + inv.getInvitationsLeft() + " invitations left in your account.");
-               text.setStyleName("pithos-credentialsText");
-               text.setWidth(WIDTH_TEXT);
+               HTML text = new HTML("You have <span class='pithos-leftInvitationsNumber'>" + inv.getInvitationsLeft() + "</span> invitations left");
+               text.addStyleName("pithos-invitationsLeft");
                inner.add(text);
-               FlexTable table = new FlexTable();
-               table.setText(0, 0, "Name");
-               table.setText(1, 0, "E-mail");
-               final TextBox name = new TextBox();
-               name.setWidth(WIDTH_FIELD);
-               table.setWidget(0, 1, name);
+               
+               HorizontalPanel split = new HorizontalPanel();
+               split.addStyleName("pithos-invitationsSplitPanel");
 
-               final TextBox emailBox = new TextBox();
-               emailBox.setWidth(WIDTH_FIELD);
-               table.setWidget(1, 1, emailBox);
+               VerticalPanel left = new VerticalPanel();
+               left.addStyleName("pithos-sendInvitationsPanel");
+               left.setVisible(inv.getInvitationsLeft() > 0);
 
-               table.getFlexCellFormatter().setStyleName(0, 0, "props-labels");
-               table.getFlexCellFormatter().setStyleName(0, 1, "props-values");
-               table.getFlexCellFormatter().setStyleName(1, 0, "props-labels");
-               table.getFlexCellFormatter().setStyleName(1, 1, "props-values");
-               inner.add(table);
+               HorizontalPanel sendLabelPanel = new HorizontalPanel();
+               HTML sendLabel = new HTML("Send new invitations");
+               sendLabel.addStyleName("pithos-sendInvitationsTitle");
+               sendLabelPanel.add(sendLabel);
+               Image plus = new Image("images/plus.png");
+               plus.addStyleName("pithos-addInvitationImg");
+               sendLabelPanel.add(plus);
+               left.add(sendLabelPanel);
 
-               Button confirm = new Button("Send", new ClickHandler() {
+               messagesPanel = new VerticalPanel();
+               messagesPanel.setSpacing(5);
+               left.add(messagesPanel);
+               
+               final FlexTable table = new FlexTable();
+               table.setCellSpacing(0);
+               if (inv.getInvitationsLeft() > 0) {
+                       table.setHTML(0, 0, "Name <span class='eg'>e.g. John Smith</span>");
+                       table.getFlexCellFormatter().setStyleName(0, 0, "props-labels");
+                       table.setText(0, 1, "Email");
+                       table.getFlexCellFormatter().setStyleName(0, 1, "props-labels");
+                       rows = 1;
+                       addFormLine(table);
+               }
+               left.add(table);
+               plus.addClickHandler(new ClickHandler() {
+                       
                        @Override
                        public void onClick(ClickEvent event) {
-                               PostRequest sendInvitation = new PostRequest("/im/", "", "invitations?uniq=" + emailBox.getText().trim() + "&realname=" + name.getText().trim()) {
-                                       
-                                       @Override
-                                       protected void onUnauthorized(Response response) {
-                                               app.sessionExpired();
-                                       }
-                                       
-                                       @Override
-                                       public void onSuccess(Resource result) {
-                                       }
-                                       
-                                       @Override
-                                       public void onError(Throwable t) {
-                                               GWT.log("", t);
-                                       }
-                               };
-                               sendInvitation.setHeader("X-Auth-Token", app.getToken());
-                               Scheduler.get().scheduleDeferred(sendInvitation);
-                               hide();
+                               if (rows == 0) {
+                                       table.setHTML(0, 0, "Name <span class='eg'>e.g. John Smith</span>");
+                                       table.getFlexCellFormatter().setStyleName(0, 0, "props-labels");
+                                       table.setText(0, 1, "Email");
+                                       table.getFlexCellFormatter().setStyleName(0, 1, "props-labels");
+                                       rows++;
+                               }
+                               addFormLine(table);
+                       }
+               });
+
+               Button send = new Button("send invitations", new ClickHandler() {
+                       @Override
+                       public void onClick(ClickEvent event) {
+                               int rowCount = table.getRowCount();
+                               
+                               for (int i = 1; i<rowCount; i++) {
+                                       String name = ((TextBox) table.getWidget(i, 0)).getText().trim();
+                                       String email = ((TextBox) table.getWidget(i, 1)).getText().trim();
+                                       sendInvitation(email, name);
+                               }
                        }
                });
-               confirm.addStyleName("button");
-               inner.add(confirm);
+               send.addStyleName("pithos-sendInvitationButton");
+               send.setVisible(inv.getInvitationsLeft() > 0);
+               left.add(send);
+               
+               split.add(left);
+               split.setCellWidth(left, "50%");
+
+               VerticalPanel right = new VerticalPanel();
+               right.addStyleName("pithos-sentInvitationsPanel");
+               
+               HTML sentLabel = new HTML("Invitations sent");
+               sentLabel.addStyleName("pithos-sentInvitationsTitle");
+               right.add(sentLabel);
+               
+               sentInvitationsTable = new FlexTable();
+               sentInvitationsTable.setCellSpacing(0);
+               sentInvitationsTable.addStyleName("pithos-sentInvitationsTable");
+               fillSentInvitationsTable(inv);
+               right.add(sentInvitationsTable);
+               
+               pagerPanel = new HorizontalPanel();
+               pagerPanel.setSpacing(5);
+               Button prev = new Button("Prev");
+               prev.addStyleName("pithos-pagerButton");
+               prev.addClickHandler(new ClickHandler() {
+                       
+                       @Override
+                       public void onClick(ClickEvent event) {
+                               if (currentPage > 0) {
+                                       pagerPanel.getWidget(currentPage + 1).removeStyleName("pithos-pagerButtonCurrent");
+                                       currentPage--;
+                                       fillSentInvitationsTable(inv);
+                                       pagerPanel.getWidget(currentPage + 1).addStyleName("pithos-pagerButtonCurrent");
+                               }
+                       }
+               });
+               pagerPanel.add(prev);
+               Button next = new Button("Next");
+               next.addStyleName("pithos-pagerButton");
+               next.addClickHandler(new ClickHandler() {
+                       
+                       @Override
+                       public void onClick(ClickEvent event) {
+                               int numOfInvs = inv.getSentInvitations().size();
+                               int numOfPages = numOfInvs / INV_PER_PAGE + (numOfInvs % INV_PER_PAGE == 0 ? 0 : 1);
+                               if (currentPage < numOfPages - 1) {
+                                       pagerPanel.getWidget(currentPage + 1).removeStyleName("pithos-pagerButtonCurrent");
+                                       currentPage++;
+                                       pagerPanel.getWidget(currentPage + 1).addStyleName("pithos-pagerButtonCurrent");
+                                       fillSentInvitationsTable(inv);
+                               }
+                       }
+               });
+               pagerPanel.add(next);
+               right.add(pagerPanel);
+               updatePagerPanel(inv);
+               
+               split.add(right);
+               
+               inner.add(split);
+               
                outer.add(inner);
+               outer.add(close);
                outer.setCellHorizontalAlignment(inner, HasHorizontalAlignment.ALIGN_CENTER);
                setWidget(outer);
        }
 
-       @Override
-       protected void onPreviewNativeEvent(NativePreviewEvent preview) {
-               super.onPreviewNativeEvent(preview);
-               NativeEvent evt = preview.getNativeEvent();
-               if (evt.getType().equals("keydown"))
-                       // Use the popup's key preview hooks to close the dialog when
-                       // either enter or escape is pressed.
-                       switch (evt.getKeyCode()) {
-                               case KeyCodes.KEY_ENTER:
-                               case KeyCodes.KEY_ESCAPE:
-                                       hide();
-                                       break;
+       private void addFormLine(final FlexTable table) {
+               table.setWidget(rows, 0, new TextBox());
+               table.getFlexCellFormatter().setStyleName(1, 0, "props-values");
+
+               table.setWidget(rows, 1, new TextBox());
+               table.getFlexCellFormatter().setStyleName(1, 1, "props-values");
+               
+               Image delete = new Image("images/delete.png");
+               delete.addStyleName("pithos-invitationDeleteImg");
+               delete.addClickHandler(new ClickHandler() {
+                       
+                       @Override
+                       public void onClick(ClickEvent event) {
+                               int rowIndex = table.getCellForEvent(event).getRowIndex();
+                               table.removeRow(rowIndex);
+                               if (rowIndex == 1 && table.getRowCount() > 1) {
+                                       table.getCellFormatter().removeStyleName(rowIndex, 0, "pithos-invitationFormRow");
+                                       table.getCellFormatter().removeStyleName(rowIndex, 1, "pithos-invitationFormRow");
+                                       table.getCellFormatter().removeStyleName(rowIndex, 2, "pithos-invitationFormRow");
+                               }
+                               rows--;
+                       }
+               });
+               table.setWidget(rows, 2, delete);
+
+               if (rows > 1) {
+                       table.getCellFormatter().addStyleName(rows, 0, "pithos-invitationFormRow");
+                       table.getCellFormatter().addStyleName(rows, 1, "pithos-invitationFormRow");
+                       table.getCellFormatter().addStyleName(rows, 2, "pithos-invitationFormRow");
+               }
+               rows++;
+       }
+
+       void sendInvitation(String email, final String realname) {
+               if (realname == null || realname.length() == 0) {
+                       HTML msg = new HTML("Name cannot be empty");
+                       msg.addStyleName("pithos-invitationResponseError");
+                       messagesPanel.add(msg);
+               }
+               else if (email == null || email.length() == 0 || !email.contains("@") || 
+                               email.substring(email.indexOf("@")).length() < 3 || !email.substring(email.indexOf("@") + 2).contains(".")) {
+                       HTML msg = new HTML("Invalid email");
+                       msg.addStyleName("pithos-invitationResponseError");
+                       messagesPanel.add(msg);
+               }
+               else {
+                       PostRequest sendInvitation = new PostRequest("/im/", "", "invite", "uniq=" + email + "&realname=" + realname) {
+                               
+                               @Override
+                               protected void onUnauthorized(Response response) {
+                                       app.sessionExpired();
+                               }
+                               
+                               @Override
+                               public void onSuccess(Resource result) {
+                                       HTML msg = new HTML("Invitation to <span class='user'>" + realname + "</span> was sent.");
+                                       msg.addStyleName("pithos-invitationResponse");
+                                       messagesPanel.add(msg);
+                               }
+                               
+                               @Override
+                               public void onError(Throwable t) {
+                                       GWT.log("", t);
+                               }
+                       };
+                       sendInvitation.setHeader("X-Auth-Token", app.getToken());
+                       Scheduler.get().scheduleDeferred(sendInvitation);
+               }
+       }
+       
+       void fillSentInvitationsTable(Invitations inv) {
+               sentInvitationsTable.removeAllRows();
+               int row = 0;
+               for (int j=currentPage * INV_PER_PAGE + 0; j<inv.getSentInvitations().size() && j<(currentPage + 1)* INV_PER_PAGE; j++) {
+                       final Invitation i = inv.getSentInvitations().get(j);
+                       sentInvitationsTable.setText(row, 0, i.getRealname());
+                       if (i.isAccepted())
+                               sentInvitationsTable.setWidget(row, 1, new Image("images/invitation_accepted.png"));
+                       else {
+                               Image img = new Image("images/resend.png");
+                               img.addStyleName("pithos-resendInvitation");
+                               img.addClickHandler(new ClickHandler() {
+                                       
+                                       @Override
+                                       public void onClick(ClickEvent event) {
+                                               sendInvitation(i.getEmail(), i.getRealname());
+                                       }
+                               });
+                               sentInvitationsTable.setWidget(row, 1, img);
                        }
+                       sentInvitationsTable.getFlexCellFormatter().setRowSpan(row, 1, 2);
+                       sentInvitationsTable.getFlexCellFormatter().setHorizontalAlignment(row, 1, HasHorizontalAlignment.ALIGN_RIGHT);
+                       if (j < inv.getSentInvitations().size() - 1 && j < (currentPage + 1)* INV_PER_PAGE - 1)
+                               sentInvitationsTable.getFlexCellFormatter().addStyleName(row, 1, "pithos-invitedEmailBorder");
+                       row++;
+                       sentInvitationsTable.setText(row, 0, i.getEmail());
+                       sentInvitationsTable.getFlexCellFormatter().addStyleName(row, 0, "pithos-invitedEmail");
+                       if (j < inv.getSentInvitations().size() - 1 && j < (currentPage + 1)* INV_PER_PAGE - 1)
+                               sentInvitationsTable.getFlexCellFormatter().addStyleName(row, 0, "pithos-invitedEmailBorder");
+                       row++;
+               }
+       }
+       
+       void updatePagerPanel(final Invitations inv) {
+               int numOfInvitations = inv.getSentInvitations().size();
+               int numOfPages = numOfInvitations / INV_PER_PAGE + (numOfInvitations % INV_PER_PAGE == 0 ? 0 : 1);
+               for (int i=0; i<numOfPages; i++) {
+                       final Button page = new Button(String.valueOf(i + 1));
+                       page.addStyleName("pithos-pagerButton");
+                       if (i == currentPage)
+                               page.addStyleName("pithos-pagerButtonCurrent");
+                               
+                       final int j = i;
+                       page.addClickHandler(new ClickHandler() {
+                               
+                               @Override
+                               public void onClick(ClickEvent event) {
+                                       pagerPanel.getWidget(currentPage + 1).removeStyleName("pithos-pagerButtonCurrent");
+                                       currentPage = j;
+                                       fillSentInvitationsTable(inv);
+                                       page.addStyleName("pithos-pagerButtonCurrent");
+                               }
+                       });
+                       pagerPanel.insert(page, i + 1);
+               }
        }
 }