diff --git a/src/main/java/com/faendir/acra/ui/component/HasStyle.java b/src/main/java/com/faendir/acra/ui/component/HasStyle.java index 5db7377..fdfa7d2 100644 --- a/src/main/java/com/faendir/acra/ui/component/HasStyle.java +++ b/src/main/java/com/faendir/acra/ui/component/HasStyle.java @@ -34,7 +34,23 @@ public interface HasStyle extends com.vaadin.flow.component.HasStyle { 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()); } + + 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()); + } } diff --git a/src/main/java/com/faendir/acra/ui/component/UserEditor.java b/src/main/java/com/faendir/acra/ui/component/UserEditor.java index 6d381d1..55a7125 100644 --- a/src/main/java/com/faendir/acra/ui/component/UserEditor.java +++ b/src/main/java/com/faendir/acra/ui/component/UserEditor.java @@ -19,13 +19,18 @@ package com.faendir.acra.ui.component; import com.faendir.acra.i18n.Messages; import com.faendir.acra.model.User; 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.HasValue; import com.vaadin.flow.component.button.Button; import com.vaadin.flow.component.textfield.PasswordField; import com.vaadin.flow.component.textfield.TextField; import com.vaadin.flow.data.binder.Binder; import com.vaadin.flow.data.binder.ValidationResult; 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.Nullable; @@ -44,6 +49,8 @@ public class UserEditor extends Composite { this.user = newUser ? new User("", "", Arrays.asList(User.Role.ADMIN, User.Role.USER)) : u; Binder binder = new Binder<>(); Translatable.Value username = Translatable.createTextField(user.getUsername(), Messages.USERNAME); + exposeInput(username); + username.setWidthFull(); Binder.BindingBuilder usernameBindingBuilder = binder.forField(username); if (newUser) { usernameBindingBuilder.asRequired(getTranslation(Messages.USERNAME_REQUIRED)); @@ -52,6 +59,7 @@ public class UserEditor extends Composite { .bind(User::getUsername, newUser ? User::setUsername : null); getContent().add(username); Translatable.Value mail = Translatable.createTextField(user.getMail(), Messages.EMAIL); + mail.setWidthFull(); EmailValidator emailValidator = new EmailValidator(getTranslation(Messages.INVALID_MAIL)); binder.forField(mail).withValidator((m, c) -> { if (m.isEmpty()) { @@ -61,9 +69,15 @@ public class UserEditor extends Composite { }).bind(User::getMail, User::setMail); getContent().add(mail); Translatable.Value newPassword = Translatable.createPasswordField(Messages.NEW_PASSWORD); + exposeInput(newPassword); + newPassword.setWidthFull(); Translatable.Value repeatPassword = Translatable.createPasswordField(Messages.REPEAT_PASSWORD); + exposeInput(repeatPassword); + repeatPassword.setWidthFull(); if (!newUser) { Translatable.Value oldPassword = Translatable.createPasswordField(Messages.OLD_PASSWORD); + exposeInput(oldPassword); + oldPassword.setWidthFull(); Binder.Binding oldPasswordBinding = binder.forField(oldPassword).withValidator(p -> { if (!newPassword.getValue().isEmpty() || !oldPassword.getValue().isEmpty()) { return userService.checkPassword(user, p); @@ -76,12 +90,14 @@ public class UserEditor extends Composite { repeatPassword.addValueChangeListener(e -> oldPasswordBinding.validate()); } Binder.BindingBuilder newPasswordBindingBuilder = binder.forField(newPassword); + Binder.BindingBuilder repeatPasswordBindingBuilder = binder.forField(repeatPassword); if (newUser) { newPasswordBindingBuilder.asRequired(getTranslation(Messages.PASSWORD_REQUIRED)); + repeatPasswordBindingBuilder.asRequired(getTranslation(Messages.PASSWORD_REQUIRED)); } newPasswordBindingBuilder.bind(user1 -> "", User::setPlainTextPassword); getContent().add(newPassword); - Binder.Binding repeatPasswordBinding = binder.forField(repeatPassword).withValidator(p -> p.equals(newPassword.getValue()), getTranslation(Messages.PASSWORDS_NOT_MATCHING)).bind(user1 -> "", (user1, s) -> doNothing()); + Binder.Binding repeatPasswordBinding = repeatPasswordBindingBuilder.withValidator(p -> p.equals(newPassword.getValue()), getTranslation(Messages.PASSWORDS_NOT_MATCHING)).bind(user1 -> "", (user1, s) -> doNothing()); newPassword.addValueChangeListener(e -> { if (!repeatPassword.getValue().isEmpty()) { repeatPasswordBinding.validate(); @@ -96,10 +112,24 @@ public class UserEditor extends Composite { onSuccess.run(); } }, Messages.CONFIRM); + button.setWidthFull(); button.getContent().setEnabled(false); binder.addStatusChangeListener(e -> button.getContent().setEnabled(e.getBinder().hasChanges())); getContent().add(button); 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 the type of the field + */ + private , String> & com.vaadin.flow.component.HasValidation> void exposeInput(Translatable.Value field) { + Element input = ElementFactory.createInput(); + input.setAttribute("slot", "input"); + field.getElement().appendChild(input); } private void doNothing() { diff --git a/src/main/java/com/faendir/acra/ui/view/MainView.java b/src/main/java/com/faendir/acra/ui/view/MainView.java index 625cb12..1071341 100644 --- a/src/main/java/com/faendir/acra/ui/view/MainView.java +++ b/src/main/java/com/faendir/acra/ui/view/MainView.java @@ -25,6 +25,7 @@ import com.faendir.acra.ui.base.Path; import com.faendir.acra.ui.base.popup.Popup; import com.faendir.acra.ui.component.DropdownMenu; 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.UserEditor; import com.faendir.acra.ui.view.user.AccountView; @@ -151,7 +152,23 @@ public class MainView extends ParentLayout { } private void showFirstTimeSetup() { - setContent(new UserEditor(userService, null, () -> UI.getCurrent().getPage().reload())); + Translatable logo = Translatable.createImage("frontend/logo.png", Messages.ACRARIUM); + logo.setWidthFull(); + logo.setPaddingTop(0.5, Unit.REM); + logo.setPaddingBottom(1, Unit.REM); + Translatable