improve first time setup ui

This commit is contained in:
f43nd1r 2019-03-06 15:15:18 +01:00
parent e38945e193
commit 3c65baaa38
5 changed files with 72 additions and 5 deletions

View file

@ -34,7 +34,23 @@ public interface HasStyle extends com.vaadin.flow.component.HasStyle {
getStyle().set("color","inherit"); getStyle().set("color","inherit");
} }
default void setPadding(int value, HasSize.Unit unit) { default void setPadding(double value, HasSize.Unit unit) {
getStyle().set("padding", value + unit.getText()); getStyle().set("padding", value + unit.getText());
} }
default void setPaddingLeft(double value, HasSize.Unit unit) {
getStyle().set("padding-left", value + unit.getText());
}
default void setPaddingTop(double value, HasSize.Unit unit) {
getStyle().set("padding-top", value + unit.getText());
}
default void setPaddingRight(double value, HasSize.Unit unit) {
getStyle().set("padding-right", value + unit.getText());
}
default void setPaddingBottom(double value, HasSize.Unit unit) {
getStyle().set("padding-bottom", value + unit.getText());
}
} }

View file

@ -19,13 +19,18 @@ package com.faendir.acra.ui.component;
import com.faendir.acra.i18n.Messages; import com.faendir.acra.i18n.Messages;
import com.faendir.acra.model.User; import com.faendir.acra.model.User;
import com.faendir.acra.service.UserService; import com.faendir.acra.service.UserService;
import com.vaadin.flow.component.AbstractField;
import com.vaadin.flow.component.Component;
import com.vaadin.flow.component.Composite; import com.vaadin.flow.component.Composite;
import com.vaadin.flow.component.HasValue;
import com.vaadin.flow.component.button.Button; import com.vaadin.flow.component.button.Button;
import com.vaadin.flow.component.textfield.PasswordField; import com.vaadin.flow.component.textfield.PasswordField;
import com.vaadin.flow.component.textfield.TextField; import com.vaadin.flow.component.textfield.TextField;
import com.vaadin.flow.data.binder.Binder; import com.vaadin.flow.data.binder.Binder;
import com.vaadin.flow.data.binder.ValidationResult; import com.vaadin.flow.data.binder.ValidationResult;
import com.vaadin.flow.data.validator.EmailValidator; import com.vaadin.flow.data.validator.EmailValidator;
import com.vaadin.flow.dom.Element;
import com.vaadin.flow.dom.ElementFactory;
import org.springframework.lang.NonNull; import org.springframework.lang.NonNull;
import org.springframework.lang.Nullable; import org.springframework.lang.Nullable;
@ -44,6 +49,8 @@ public class UserEditor extends Composite<FlexLayout> {
this.user = newUser ? new User("", "", Arrays.asList(User.Role.ADMIN, User.Role.USER)) : u; this.user = newUser ? new User("", "", Arrays.asList(User.Role.ADMIN, User.Role.USER)) : u;
Binder<User> binder = new Binder<>(); Binder<User> binder = new Binder<>();
Translatable.Value<TextField> username = Translatable.createTextField(user.getUsername(), Messages.USERNAME); Translatable.Value<TextField> username = Translatable.createTextField(user.getUsername(), Messages.USERNAME);
exposeInput(username);
username.setWidthFull();
Binder.BindingBuilder<User, String> usernameBindingBuilder = binder.forField(username); Binder.BindingBuilder<User, String> usernameBindingBuilder = binder.forField(username);
if (newUser) { if (newUser) {
usernameBindingBuilder.asRequired(getTranslation(Messages.USERNAME_REQUIRED)); usernameBindingBuilder.asRequired(getTranslation(Messages.USERNAME_REQUIRED));
@ -52,6 +59,7 @@ public class UserEditor extends Composite<FlexLayout> {
.bind(User::getUsername, newUser ? User::setUsername : null); .bind(User::getUsername, newUser ? User::setUsername : null);
getContent().add(username); getContent().add(username);
Translatable.Value<TextField> mail = Translatable.createTextField(user.getMail(), Messages.EMAIL); Translatable.Value<TextField> mail = Translatable.createTextField(user.getMail(), Messages.EMAIL);
mail.setWidthFull();
EmailValidator emailValidator = new EmailValidator(getTranslation(Messages.INVALID_MAIL)); EmailValidator emailValidator = new EmailValidator(getTranslation(Messages.INVALID_MAIL));
binder.forField(mail).withValidator((m, c) -> { binder.forField(mail).withValidator((m, c) -> {
if (m.isEmpty()) { if (m.isEmpty()) {
@ -61,9 +69,15 @@ public class UserEditor extends Composite<FlexLayout> {
}).bind(User::getMail, User::setMail); }).bind(User::getMail, User::setMail);
getContent().add(mail); getContent().add(mail);
Translatable.Value<PasswordField> newPassword = Translatable.createPasswordField(Messages.NEW_PASSWORD); Translatable.Value<PasswordField> newPassword = Translatable.createPasswordField(Messages.NEW_PASSWORD);
exposeInput(newPassword);
newPassword.setWidthFull();
Translatable.Value<PasswordField> repeatPassword = Translatable.createPasswordField(Messages.REPEAT_PASSWORD); Translatable.Value<PasswordField> repeatPassword = Translatable.createPasswordField(Messages.REPEAT_PASSWORD);
exposeInput(repeatPassword);
repeatPassword.setWidthFull();
if (!newUser) { if (!newUser) {
Translatable.Value<PasswordField> oldPassword = Translatable.createPasswordField(Messages.OLD_PASSWORD); Translatable.Value<PasswordField> oldPassword = Translatable.createPasswordField(Messages.OLD_PASSWORD);
exposeInput(oldPassword);
oldPassword.setWidthFull();
Binder.Binding<User, String> oldPasswordBinding = binder.forField(oldPassword).withValidator(p -> { Binder.Binding<User, String> oldPasswordBinding = binder.forField(oldPassword).withValidator(p -> {
if (!newPassword.getValue().isEmpty() || !oldPassword.getValue().isEmpty()) { if (!newPassword.getValue().isEmpty() || !oldPassword.getValue().isEmpty()) {
return userService.checkPassword(user, p); return userService.checkPassword(user, p);
@ -76,12 +90,14 @@ public class UserEditor extends Composite<FlexLayout> {
repeatPassword.addValueChangeListener(e -> oldPasswordBinding.validate()); repeatPassword.addValueChangeListener(e -> oldPasswordBinding.validate());
} }
Binder.BindingBuilder<User, String> newPasswordBindingBuilder = binder.forField(newPassword); Binder.BindingBuilder<User, String> newPasswordBindingBuilder = binder.forField(newPassword);
Binder.BindingBuilder<User, String> repeatPasswordBindingBuilder = binder.forField(repeatPassword);
if (newUser) { if (newUser) {
newPasswordBindingBuilder.asRequired(getTranslation(Messages.PASSWORD_REQUIRED)); newPasswordBindingBuilder.asRequired(getTranslation(Messages.PASSWORD_REQUIRED));
repeatPasswordBindingBuilder.asRequired(getTranslation(Messages.PASSWORD_REQUIRED));
} }
newPasswordBindingBuilder.bind(user1 -> "", User::setPlainTextPassword); newPasswordBindingBuilder.bind(user1 -> "", User::setPlainTextPassword);
getContent().add(newPassword); getContent().add(newPassword);
Binder.Binding<User, String> repeatPasswordBinding = binder.forField(repeatPassword).withValidator(p -> p.equals(newPassword.getValue()), getTranslation(Messages.PASSWORDS_NOT_MATCHING)).bind(user1 -> "", (user1, s) -> doNothing()); Binder.Binding<User, String> repeatPasswordBinding = repeatPasswordBindingBuilder.withValidator(p -> p.equals(newPassword.getValue()), getTranslation(Messages.PASSWORDS_NOT_MATCHING)).bind(user1 -> "", (user1, s) -> doNothing());
newPassword.addValueChangeListener(e -> { newPassword.addValueChangeListener(e -> {
if (!repeatPassword.getValue().isEmpty()) { if (!repeatPassword.getValue().isEmpty()) {
repeatPasswordBinding.validate(); repeatPasswordBinding.validate();
@ -96,10 +112,24 @@ public class UserEditor extends Composite<FlexLayout> {
onSuccess.run(); onSuccess.run();
} }
}, Messages.CONFIRM); }, Messages.CONFIRM);
button.setWidthFull();
button.getContent().setEnabled(false); button.getContent().setEnabled(false);
binder.addStatusChangeListener(e -> button.getContent().setEnabled(e.getBinder().hasChanges())); binder.addStatusChangeListener(e -> button.getContent().setEnabled(e.getBinder().hasChanges()));
getContent().add(button); getContent().add(button);
getContent().setFlexDirection(FlexLayout.FlexDirection.COLUMN); getContent().setFlexDirection(FlexLayout.FlexDirection.COLUMN);
getContent().setMaxWidthFull();
getContent().setWidth("calc(var(--lumo-size-m) * 10)");
}
/**
* password managers need an input outside the shadow dom, which we add here.
* @param field the field which should be visible to password managers
* @param <T> the type of the field
*/
private <T extends Component & HasValue<AbstractField.ComponentValueChangeEvent<T, String>, String> & com.vaadin.flow.component.HasValidation> void exposeInput(Translatable.Value<T> field) {
Element input = ElementFactory.createInput();
input.setAttribute("slot", "input");
field.getElement().appendChild(input);
} }
private void doNothing() { private void doNothing() {

View file

@ -25,6 +25,7 @@ import com.faendir.acra.ui.base.Path;
import com.faendir.acra.ui.base.popup.Popup; import com.faendir.acra.ui.base.popup.Popup;
import com.faendir.acra.ui.component.DropdownMenu; import com.faendir.acra.ui.component.DropdownMenu;
import com.faendir.acra.ui.component.FlexLayout; import com.faendir.acra.ui.component.FlexLayout;
import com.faendir.acra.ui.component.Label;
import com.faendir.acra.ui.component.Translatable; import com.faendir.acra.ui.component.Translatable;
import com.faendir.acra.ui.component.UserEditor; import com.faendir.acra.ui.component.UserEditor;
import com.faendir.acra.ui.view.user.AccountView; import com.faendir.acra.ui.view.user.AccountView;
@ -151,7 +152,23 @@ public class MainView extends ParentLayout {
} }
private void showFirstTimeSetup() { private void showFirstTimeSetup() {
setContent(new UserEditor(userService, null, () -> UI.getCurrent().getPage().reload())); Translatable<Image> logo = Translatable.createImage("frontend/logo.png", Messages.ACRARIUM);
logo.setWidthFull();
logo.setPaddingTop(0.5, Unit.REM);
logo.setPaddingBottom(1, Unit.REM);
Translatable<Label> welcomeLabel = Translatable.createLabel(Messages.WELCOME);
welcomeLabel.getStyle().set("font-size", "var(--lumo-font-size-xxl");
FlexLayout header = new FlexLayout(welcomeLabel, logo, Translatable.createLabel(Messages.CREATE_ADMIN));
header.setFlexDirection(FlexDirection.COLUMN);
header.setAlignSelf(Alignment.CENTER, welcomeLabel);
header.setWidth(0, Unit.PIXEL);
FlexLayout wrapper = new FlexLayout(header);
wrapper.expand(header);
UserEditor userEditor = new UserEditor(userService, null, () -> UI.getCurrent().getPage().reload());
FlexLayout layout = new FlexLayout(wrapper, userEditor);
layout.setFlexDirection(FlexDirection.COLUMN);
layout.setSizeUndefined();
setContent(layout);
} }
private boolean login(@NonNull String username, @NonNull String password) { private boolean login(@NonNull String username, @NonNull String password) {

View file

@ -153,4 +153,6 @@ spikeMailSubject=Große Anzahl an Berichten für %s
spikeMailTemplate=<a href='%s'>%s</a> hat stark erhöhtes Berichtaufkommen in Version %s mit %d Berichten heute spikeMailTemplate=<a href='%s'>%s</a> hat stark erhöhtes Berichtaufkommen in Version %s mit %d Berichten heute
usernameRequired=Sie müssen einen Nutzernamen wählen usernameRequired=Sie müssen einen Nutzernamen wählen
usernameTaken=Dieser Nutzername ist bereits vergeben usernameTaken=Dieser Nutzername ist bereits vergeben
passwordRequired=Ein Passwort muss gesetzt werden passwordRequired=Ein Passwort muss gesetzt werden
welcome=Willkommen zu
createAdmin=Zuerst müssen Sie einen Adminstrator anlegen:

View file

@ -153,4 +153,6 @@ account=Account
invalidMail=Invalid email invalidMail=Invalid email
usernameRequired=A username is required usernameRequired=A username is required
usernameTaken=That username is already taken usernameTaken=That username is already taken
passwordRequired=A password is required passwordRequired=A password is required
welcome=Welcome to
createAdmin=First, you have to create an administrator: