Browse Source

New login form (#8171)

The legacy LoginForm is substituted with the new one which is compatible
in API.
The patch contains modified code from the addon
https://vaadin.com/directory#addon/loginform

Change-Id: I2178291c97c2f66840f832a0bf932271534beb49
tags/7.7.0.alpha3
Ingo Kegel 9 years ago
parent
commit
c0babd786c

+ 3
- 0
all/src/main/templates/release-notes.html View File

@@ -116,6 +116,9 @@
<li>The return type of BootstrapHandler.getWidgetsetForUI() has changed.</li>
<li>Vaadin shared no longer depends on a custom build of Guava. Any project that depends on Guava as a transitive dependency should use standard Guava.</li>
<li>Valo theme field error styles now apply to NativeSelect, ListSelect and TwinColSelect as well.</li>
<li>The LoginForm component has been rewritten to better support auto-completion of passwords on modern browsers.
Its API, look and DOM structure have changed somewhat, so any application level customizations of LoginForm need changes.
See also <a href="http://dev.vaadin.com/ticket/8171">#8171</a></li>
<li>The way we handle GWT dependencies has been completely changed. See <a href="#gwtdep">this section</a> for more details</li>
</ul>
<h3 id="knownissues">Known Issues and Limitations</h3>

+ 194
- 0
client/src/main/java/com/vaadin/client/ui/loginform/LoginFormConnector.java View File

@@ -0,0 +1,194 @@
/*
* Copyright 2000-2014 Vaadin Ltd.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/

package com.vaadin.client.ui.loginform;

import com.google.gwt.dom.client.Element;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
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.user.client.DOM;
import com.google.gwt.user.client.ui.FocusWidget;
import com.google.gwt.user.client.ui.FormPanel;
import com.vaadin.client.ComponentConnector;
import com.vaadin.client.ConnectorHierarchyChangeEvent;
import com.vaadin.client.communication.StateChangeEvent;
import com.vaadin.client.ui.AbstractSingleComponentContainerConnector;
import com.vaadin.client.ui.VTextField;
import com.vaadin.client.ui.button.ButtonConnector;
import com.vaadin.client.ui.nativebutton.NativeButtonConnector;
import com.vaadin.client.ui.textfield.TextFieldConnector;
import com.vaadin.shared.Connector;
import com.vaadin.shared.ui.Connect;
import com.vaadin.shared.ui.loginform.LoginFormConstants;
import com.vaadin.shared.ui.loginform.LoginFormRpc;
import com.vaadin.shared.ui.loginform.LoginFormState;
import com.google.gwt.core.client.Scheduler;

@Connect(com.vaadin.ui.LoginForm.class)
public class LoginFormConnector extends
AbstractSingleComponentContainerConnector {

private VTextField passwordField;
private VTextField userField;
private LoginFormRpc loginFormRpc;

@Override
public void updateCaption(ComponentConnector connector) {

}

@Override
public VLoginForm getWidget() {
return (VLoginForm) super.getWidget();
}

@Override
protected void init() {
super.init();

loginFormRpc = getRpcProxy(LoginFormRpc.class);
getWidget().addSubmitCompleteHandler(new FormPanel.SubmitCompleteHandler() {
@Override
public void onSubmitComplete(FormPanel.SubmitCompleteEvent event) {
valuesChanged();
loginFormRpc.submitCompleted();
}
});
}

@Override
public LoginFormState getState() {
return (LoginFormState) super.getState();
}

@Override
public void onConnectorHierarchyChange(ConnectorHierarchyChangeEvent event) {
ComponentConnector content = getContent();
if (content != null) {
getWidget().setWidget(getContentWidget());
}
}

@Override
public void onStateChanged(StateChangeEvent stateChangeEvent) {
super.onStateChanged(stateChangeEvent);

LoginFormState state = getState();
userField = configureTextField(state.userNameFieldConnector, "username");
passwordField = configureTextField(state.passwordFieldConnector,
"password");
addSubmitButtonClickHandler(state.loginButtonConnector);
getWidget().setAction(
getResourceUrl(LoginFormConstants.LOGIN_RESOURCE_NAME));
}

private VTextField configureTextField(Connector connector, String id) {
if (connector != null) {
VTextField textField = ((TextFieldConnector) connector).getWidget();

textField.addKeyDownHandler(new SubmitKeyHandler());

Element element = textField.getElement();
String externalId = element.getId();
if (externalId == null || externalId.isEmpty()
|| externalId.startsWith("gwt-")) {
element.setId(id);
}
DOM.setElementAttribute(element, "name", id);
DOM.setElementAttribute(element, "autocomplete", "on");

return textField;
} else {
return null;
}
}

private void loginLater() {
Scheduler.get().scheduleFixedDelay(new Scheduler.RepeatingCommand() {
@Override
public boolean execute() {
login();
return false;
}
}, 100);
}

private void login() {
getWidget().submit();
}

private void addSubmitButtonClickHandler(Connector buttonConnector) {
if (buttonConnector instanceof ButtonConnector) {
addSubmitButtonClickHandler(((ButtonConnector) buttonConnector)
.getWidget());
} else if (buttonConnector instanceof NativeButtonConnector) {
addSubmitButtonClickHandler(((NativeButtonConnector) buttonConnector)
.getWidget());
}
}

private void addSubmitButtonClickHandler(FocusWidget button) {
button.addClickHandler(new ClickHandler() {
@Override
public void onClick(ClickEvent event) {
login();
}
});
}

private void valuesChanged() {
if (passwordField != null) {
passwordField.valueChange(true);
}
if (userField != null) {
userField.valueChange(true);
}
}

private class SubmitKeyHandler implements KeyDownHandler {

private int previousKeyCode;

@Override
public void onKeyDown(KeyDownEvent event) {
int keyCode = event.getNativeKeyCode();
if (keyCode == KeyCodes.KEY_ENTER) {
if (isInAutoComplete()) {
previousKeyCode = keyCode;
} else {
loginLater();
}
} else {
previousKeyCode = keyCode;
}
}

private boolean isInAutoComplete() {
switch (previousKeyCode) {
case KeyCodes.KEY_PAGEUP:
case KeyCodes.KEY_PAGEDOWN:
case KeyCodes.KEY_UP:
case KeyCodes.KEY_DOWN:
return true;
default:
return false;
}
}
}
}

+ 27
- 0
client/src/main/java/com/vaadin/client/ui/loginform/VLoginForm.java View File

@@ -0,0 +1,27 @@
/*
* Copyright 2000-2014 Vaadin Ltd.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/

package com.vaadin.client.ui.loginform;

import com.google.gwt.user.client.ui.FormPanel;

public class VLoginForm extends FormPanel {

public VLoginForm() {
getElement().setId("loginForm");
setMethod(METHOD_POST);
}
}

+ 260
- 232
server/src/main/java/com/vaadin/ui/LoginForm.java View File

@@ -13,181 +13,48 @@
* License for the specific language governing permissions and limitations under
* the License.
*/

package com.vaadin.ui;

import java.io.IOException;
import java.io.ByteArrayInputStream;
import java.io.InputStream;
import java.io.Serializable;
import java.io.UnsupportedEncodingException;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;

import com.vaadin.server.ConnectorResource;
import com.vaadin.server.ExternalResource;
import com.vaadin.server.VaadinRequest;
import com.vaadin.server.VaadinResponse;
import com.vaadin.server.VaadinService;
import com.vaadin.server.VaadinServletService;
import com.vaadin.shared.ApplicationConstants;
import com.vaadin.server.StreamResource;
import com.vaadin.shared.ui.loginform.LoginFormConstants;
import com.vaadin.shared.ui.loginform.LoginFormRpc;
import com.vaadin.shared.ui.loginform.LoginFormState;

/**
* LoginForm is a Vaadin component to handle common problem among Ajax
* applications: browsers password managers don't fill dynamically created forms
* like all those UI elements created by Vaadin.
* Login form with auto-completion and auto-fill for all major browsers. You can
* derive from this class and implement the
* {@link #createContent(com.vaadin.ui.TextField, com.vaadin.ui.PasswordField, com.vaadin.ui.Button)}
* method to build the layout using the text fields and login button that are
* passed to that method. The supplied components are specially treated so that
* they work with password managers.
* <p>
* For developer it is easy to use: add component to a desired place in you UI
* and add LoginListener to validate form input. Behind the curtain LoginForm
* creates an iframe with static html that browsers detect.
* If you need to change the URL as part of the login procedure, call
* {@link #setLoginMode(LoginMode)} with the argument {@link LoginMode#DEFERRED}
* in your implementation of
* {@link #createContent(com.vaadin.ui.TextField, com.vaadin.ui.PasswordField, com.vaadin.ui.Button)
* createContent}.
* <p>
* Login form is by default 100% width and height, so consider using it inside a
* sized {@link Panel} or {@link Window}.
* To customize the fields or to replace them with your own implementations, you
* can override {@link #createUsernameField()}, {@link #createPasswordField()}
* and {@link #createLoginButton()}. These methods are called automatically and
* cannot be called by your code. Captions can be reset by overriding
* {@link #getUsernameFieldCaption()}, {@link #getPasswordFieldCaption()} and
* {@link #getLoginButtonCaption()}.
* <p>
* Login page html can be overridden by replacing protected getLoginHTML method.
* As the login page is actually an iframe, styles must be handled manually. By
* default component tries to guess the right place for theme css.
*
* Note that the API of LoginForm changed significantly in Vaadin 7.7.
*
* @since 5.3
* @deprecated As of 7.0. This component no longer fulfills its duty reliably in
* the supported browsers and a {@link VerticalLayout} with two
* {@link TextField}s can be used instead.
*/
@Deprecated
public class LoginForm extends CustomComponent {

private String usernameCaption = "Username";
private String passwordCaption = "Password";
private String loginButtonCaption = "Login";

private Embedded iframe = new Embedded();

@Override
public boolean handleConnectorRequest(final VaadinRequest request,
final VaadinResponse response, String path) throws IOException {
if (!path.equals("login")) {
return super.handleConnectorRequest(request, response, path);
}
final StringBuilder responseBuilder = new StringBuilder();

getUI().accessSynchronously(new Runnable() {
@Override
public void run() {
String method = VaadinServletService.getCurrentServletRequest()
.getMethod();
if (method.equalsIgnoreCase("post")) {
responseBuilder.append(handleLogin(request));
} else {
responseBuilder.append(getLoginHTML());
}
}
});

if (responseBuilder.length() > 0) {
response.setContentType("text/html; charset=utf-8");
response.setCacheTime(-1);
response.getWriter().write(responseBuilder.toString());
return true;
} else {
return false;
}
}

private String handleLogin(VaadinRequest request) {
// Ensure UI.getCurrent() works in listeners

Map<String, String[]> parameters = VaadinService.getCurrentRequest()
.getParameterMap();

HashMap<String, String> params = new HashMap<String, String>();
// expecting single params
for (Iterator<String> it = parameters.keySet().iterator(); it.hasNext();) {
String key = it.next();
String value = (parameters.get(key))[0];
params.put(key, value);
}
LoginEvent event = new LoginEvent(LoginForm.this, params);
fireEvent(event);

return "<html><body>Login form handled."
+ "<script type='text/javascript'>parent.parent.vaadin.forceSync();"
+ "</script></body></html>";
}

public LoginForm() {
iframe.setType(Embedded.TYPE_BROWSER);
iframe.setSizeFull();
setSizeFull();
setCompositionRoot(iframe);
addStyleName("v-loginform");
}

@Override
public void beforeClientResponse(boolean initial) {
// Generate magic URL now when UI id and connectorId are known
iframe.setSource(new ExternalResource(
ApplicationConstants.APP_PROTOCOL_PREFIX
+ ApplicationConstants.APP_PATH + '/'
+ ConnectorResource.CONNECTOR_PATH + '/'
+ getUI().getUIId() + '/' + getConnectorId() + "/login"));
super.beforeClientResponse(initial);
}

/**
* Returns byte array containing login page html. If you need to override
* the login html, use the default html as basis. Login page sets its target
* with javascript.
*
* @return byte array containing login page html
*/
protected String getLoginHTML() {
return "<!DOCTYPE html>\n"
+ "<html>"
+ "<head><script type='text/javascript'>"
+ "var setTarget = function() {"
+ "var uri = window.location;"
+ "var f = document.getElementById('loginf');"
+ "document.forms[0].action = uri;document.forms[0].username.focus();};"
+ ""
+ "var styles = window.parent.document.styleSheets;"
+ "for(var j = 0; j < styles.length; j++) {\n"
+ "if(styles[j].href) {"
+ "var stylesheet = document.createElement('link');\n"
+ "stylesheet.setAttribute('rel', 'stylesheet');\n"
+ "stylesheet.setAttribute('type', 'text/css');\n"
+ "stylesheet.setAttribute('href', styles[j].href);\n"
+ "document.getElementsByTagName('head')[0].appendChild(stylesheet);\n"
+ "}"
+ "}\n"
+ "function submitOnEnter(e) { var keycode = e.keyCode || e.which;"
+ " if (keycode == 13) {document.forms[0].submit();} } \n"
+ "</script>"
+ "</head><body onload='setTarget();' style='margin:0;padding:0; background:transparent;' class=\""
+ ApplicationConstants.GENERATED_BODY_CLASSNAME
+ "\">"
+ "<div class='v-app v-app-loginpage "
+ getUIThemeClassName()
+ "' style=\"background:transparent;\">"
+ "<iframe name='logintarget' style='width:0;height:0;"
+ "border:0;margin:0;padding:0;display:block'></iframe>"
+ "<form id='loginf' target='logintarget' onkeypress=\"submitOnEnter(event)\" method=\"post\">"
+ "<div>"
+ usernameCaption
+ "</div><div >"
+ "<input class='v-textfield v-widget' style='display:block;' type='text' name='username'></div>"
+ "<div>"
+ passwordCaption
+ "</div>"
+ "<div><input class='v-textfield v-widget' style='display:block;' type='password' name='password'></div>"
+ "<div><div onclick=\"document.forms[0].submit();\" tabindex=\"0\" class=\"v-button\" role=\"button\" ><span class=\"v-button-wrap\"><span class=\"v-button-caption\">"
+ loginButtonCaption
+ "</span></span></div></div></form></div>" + "</body></html>";
}

private String getUIThemeClassName() {
if (getUI() != null) {
return getUI().getTheme();
}
return "";
}
public class LoginForm extends AbstractSingleComponentContainer {

/**
* This event is sent when login form is submitted.
@@ -225,14 +92,28 @@ public class LoginForm extends CustomComponent {
* This method is fired on each login form post.
*
* @param event
* Login event
*/
public void onLogin(LoginForm.LoginEvent event);
public void onLogin(LoginEvent event);
}

private static final Method ON_LOGIN_METHOD;
/**
* Internal stream source for the login URL - always returns "Success" and
* ignores the values received.
*/
private static class LoginStreamSource implements StreamResource.StreamSource {
@Override
public InputStream getStream() {
try {
return new ByteArrayInputStream("<html>Success</html>".toString().getBytes(
"UTF-8"));
} catch (UnsupportedEncodingException e) {
return null;
}

}
}

private static final String UNDEFINED_HEIGHT = "140px";
private static final String UNDEFINED_WIDTH = "200px";

static {
try {
@@ -245,121 +126,268 @@ public class LoginForm extends CustomComponent {
}
}

private static final Method ON_LOGIN_METHOD;

private boolean initialized;

private String usernameCaption = "Username";
private String passwordCaption = "Password";
private String loginButtonCaption = "Login";

/**
* Adds LoginListener to handle login logic
* Customize the user name field. Only for overriding, do not call.
*
* @param listener
* @return the user name field
* @since 7.7
*/
public void addLoginListener(LoginListener listener) {
addListener(LoginEvent.class, listener, ON_LOGIN_METHOD);
protected TextField createUsernameField() {
checkInitialized();
TextField field = new TextField(getUsernameCaption());
field.focus();
return field;
}

/**
* @deprecated As of 7.0, replaced by
* {@link #addLoginListener(LoginListener)}
**/
@Deprecated
public void addListener(LoginListener listener) {
addLoginListener(listener);
* Returns the caption set with {@link #setUsernameCaption(String)}. Note
* that this method might not match what is shown to the user if
* {@link #createUsernameField()} has been overridden.
*
* @return user name field caption
*/
public String getUsernameCaption() {
return usernameCaption;
}

/**
* Removes LoginListener
* Set the caption of the user name field. Note that the caption can only be
* set with this method before the login form has been initialized
* (attached).
* <p>
* As an alternative to calling this method, the method
* {@link #createUsernameField()} can be overridden.
*
* @param listener
* @param cap
* new caption
*/
public void removeLoginListener(LoginListener listener) {
removeListener(LoginEvent.class, listener, ON_LOGIN_METHOD);
public void setUsernameCaption(String cap) {
usernameCaption = cap;
}

/**
* @deprecated As of 7.0, replaced by
* {@link #removeLoginListener(LoginListener)}
**/
@Deprecated
public void removeListener(LoginListener listener) {
removeLoginListener(listener);
* Customize the password field. Only for overriding, do not call.
*
* @return the password field
* @since 7.7
*/
protected PasswordField createPasswordField() {
checkInitialized();
return new PasswordField(getPasswordCaption());
}

@Override
public void setWidth(float width, Unit unit) {
super.setWidth(width, unit);
if (iframe != null) {
if (width < 0) {
iframe.setWidth(UNDEFINED_WIDTH);
} else {
iframe.setWidth("100%");
}
}
/**
* Returns the caption set with {@link #setPasswordCaption(String)}. Note
* that this method might not match what is shown to the user if
* {@link #createPasswordField()} has been overridden.
*
* @return password field caption
*/
public String getPasswordCaption() {
return passwordCaption;
}

@Override
public void setHeight(float height, Unit unit) {
super.setHeight(height, unit);
if (iframe != null) {
if (height < 0) {
iframe.setHeight(UNDEFINED_HEIGHT);
} else {
iframe.setHeight("100%");
}
}
/**
* Set the caption of the password field. Note that the caption can only be
* set with this method before the login form has been initialized
* (attached).
* <p>
* As an alternative to calling this method, the method
* {@link #createPasswordField()} can be overridden.
*
* @param cap new caption
*/
public void setPasswordCaption(String cap) {
passwordCaption = cap;
;
}

/**
* Returns the caption for the user name field.
* Customize the login button. Only for overriding, do not call.
*
* @return String
* @return the login button
* @since 7.7
*/
public String getUsernameCaption() {
return usernameCaption;
protected Button createLoginButton() {
checkInitialized();
return new Button(getLoginButtonCaption());
}

/**
* Sets the caption to show for the user name field. The caption cannot be
* changed after the form has been shown to the user.
* Returns the caption set with {@link #setLoginButtonCaption(String)}. Note
* that this method might not match what is shown to the user if
* {@link #createLoginButton()} has been overridden.
*
* @param usernameCaption
* @return login button caption
*/
public void setUsernameCaption(String usernameCaption) {
this.usernameCaption = usernameCaption;
public String getLoginButtonCaption() {
return loginButtonCaption;
}

/**
* Returns the caption for the password field.
* Set the caption of the login button. Note that the caption can only be
* set with this method before the login form has been initialized
* (attached).
* <p>
* As an alternative to calling this method, the method
* {@link #createLoginButton()} can be overridden.
*
* @return String
* @param cap new caption
*/
public String getPasswordCaption() {
return passwordCaption;
public void setLoginButtonCaption(String cap) {
loginButtonCaption = cap;
}

@Override
protected LoginFormState getState() {
return (LoginFormState) super.getState();
}

@Override
public void attach() {
super.attach();
init();
}

private void checkInitialized() {
if (initialized) {
throw new IllegalStateException(
"Already initialized. The create methods may not be called explicitly.");
}
}

/**
* Sets the caption to show for the password field. The caption cannot be
* changed after the form has been shown to the user.
* Create the content for the login form with the supplied user name field,
* password field and the login button. You cannot use any other text fields
* or buttons for this purpose. To replace these components with your own
* implementations, override {@link #createUsernameField()},
* {@link #createPasswordField()} and {@link #createLoginButton()}. If you
* only want to change the default captions, override
* {@link #getUsernameFieldCaption()}, {@link #getPasswordFieldCaption()}
* and {@link #getLoginButtonCaption()}. You do not have to use the login
* button in your layout.
*
* @param passwordCaption
* @param userNameField
* the user name text field
* @param passwordField
* the password field
* @param loginButton
* the login button
* @return content component
* @since 7.7
*/
public void setPasswordCaption(String passwordCaption) {
this.passwordCaption = passwordCaption;
protected Component createContent(TextField userNameField,
PasswordField passwordField, Button loginButton) {
VerticalLayout layout = new VerticalLayout();
layout.setSpacing(true);
layout.setMargin(true);
layout.addComponent(userNameField);
layout.addComponent(passwordField);
layout.addComponent(loginButton);
return layout;
}

private void init() {
if (initialized) {
return;
}

LoginFormState state = getState();
state.userNameFieldConnector = createUsernameField();
state.passwordFieldConnector = createPasswordField();
state.loginButtonConnector = createLoginButton();

StreamResource resource = new StreamResource(new LoginStreamSource(),
LoginFormConstants.LOGIN_RESOURCE_NAME);
resource.setMIMEType("text/html; charset=utf-8");
resource.setCacheTime(-1);
setResource(LoginFormConstants.LOGIN_RESOURCE_NAME, resource);

registerRpc(new LoginFormRpc() {
@Override
public void submitCompleted() {
login();
}
});

initialized = true;

setContent(createContent(getUsernameField(), getPasswordField(),
getLoginButton()));
}

private TextField getUsernameField() {
return (TextField) getState().userNameFieldConnector;
}

private PasswordField getPasswordField() {
return (PasswordField) getState().passwordFieldConnector;
}

private Button getLoginButton() {
return (Button) getState().loginButtonConnector;
}

/*
* (non-Javadoc)
*
* Handle the login. In deferred mode, this method is called after the dummy
* POST request that triggers the password manager has been completed. In
* direct mode (the default setting), it is called directly when the user
* hits the enter key or clicks on the login button. In the latter case, you
* cannot change the URL in the method or the password manager will not be
* triggered.
*/
private void login() {
HashMap<String, String> params = new HashMap<String, String>();
params.put("username", getUsernameField().getValue());
params.put("password", getPasswordField().getValue());
LoginEvent event = new LoginEvent(LoginForm.this, params);
fireEvent(event);
}

/**
* Returns the caption for the login button.
* Adds LoginListener to handle login logic
*
* @return String
* @param listener
*/
public String getLoginButtonCaption() {
return loginButtonCaption;
public void addLoginListener(LoginListener listener) {
addListener(LoginEvent.class, listener, ON_LOGIN_METHOD);
}

/**
* @deprecated As of 7.0, replaced by
* {@link #addLoginListener(LoginListener)}
**/
@Deprecated
public void addListener(LoginListener listener) {
addLoginListener(listener);
}

/**
* Sets the caption (button text) to show for the login button. The caption
* cannot be changed after the form has been shown to the user.
* Removes LoginListener
*
* @param loginButtonCaption
* @param listener
*/
public void setLoginButtonCaption(String loginButtonCaption) {
this.loginButtonCaption = loginButtonCaption;
public void removeLoginListener(LoginListener listener) {
removeListener(LoginEvent.class, listener, ON_LOGIN_METHOD);
}

/**
* @deprecated As of 7.0, replaced by
* {@link #removeLoginListener(LoginListener)}
**/
@Deprecated
public void removeListener(LoginListener listener) {
removeLoginListener(listener);
}

}

+ 31
- 0
shared/src/main/java/com/vaadin/shared/ui/loginform/LoginFormConstants.java View File

@@ -0,0 +1,31 @@
/*
* Copyright 2000-2014 Vaadin Ltd.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/
package com.vaadin.shared.ui.loginform;

import java.io.Serializable;

/**
* Constants for LoginForm
*
* @since 7.7
* @author Vaadin Ltd
*/
public class LoginFormConstants implements Serializable {

public static final String LOGIN_RESOURCE_NAME = "loginForm";

}


+ 23
- 0
shared/src/main/java/com/vaadin/shared/ui/loginform/LoginFormRpc.java View File

@@ -0,0 +1,23 @@
/*
* Copyright 2000-2014 Vaadin Ltd.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/

package com.vaadin.shared.ui.loginform;

import com.vaadin.shared.communication.ServerRpc;

public interface LoginFormRpc extends ServerRpc {
void submitCompleted();
}

+ 28
- 0
shared/src/main/java/com/vaadin/shared/ui/loginform/LoginFormState.java View File

@@ -0,0 +1,28 @@
/*
* Copyright 2000-2014 Vaadin Ltd.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/

package com.vaadin.shared.ui.loginform;

import com.vaadin.shared.AbstractComponentState;
import com.vaadin.shared.Connector;
import com.vaadin.shared.communication.URLReference;

public class LoginFormState extends AbstractComponentState {
public Connector userNameFieldConnector;
public Connector passwordFieldConnector;
public Connector loginButtonConnector;
public URLReference loginResource;
}

Loading…
Cancel
Save