refactor popups for consistency and code reduction
This commit is contained in:
parent
fb49597377
commit
897ee9cbb9
14 changed files with 312 additions and 191 deletions
|
@ -9,6 +9,7 @@ import org.springframework.security.core.Authentication;
|
|||
import org.springframework.security.core.authority.SimpleGrantedAuthority;
|
||||
import org.springframework.security.core.context.SecurityContextHolder;
|
||||
|
||||
import java.util.function.BooleanSupplier;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
public final class SecurityUtils {
|
||||
|
@ -34,18 +35,19 @@ public final class SecurityUtils {
|
|||
public static boolean hasPermission(@NonNull App app, @NonNull Permission.Level level) {
|
||||
Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
|
||||
return authentication != null
|
||||
&& getPermission(app, authentication.getAuthorities().stream().filter(Permission.class::isInstance).map(Permission.class::cast)).ordinal() >= level.ordinal();
|
||||
&& getPermission(app, authentication.getAuthorities().stream().filter(Permission.class::isInstance).map(Permission.class::cast),
|
||||
() -> hasRole(UserManager.ROLE_ADMIN)).ordinal() >= level.ordinal();
|
||||
}
|
||||
|
||||
public static Permission.Level getPermission(@NonNull App app, @NonNull User user){
|
||||
return getPermission(app, user.getPermissions().stream());
|
||||
public static Permission.Level getPermission(@NonNull App app, @NonNull User user) {
|
||||
return getPermission(app, user.getPermissions().stream(), () -> user.getRoles().contains(UserManager.ROLE_ADMIN));
|
||||
}
|
||||
|
||||
@NonNull
|
||||
private static Permission.Level getPermission(@NonNull App app, @NonNull Stream<Permission> permissionStream) {
|
||||
private static Permission.Level getPermission(@NonNull App app, @NonNull Stream<Permission> permissionStream, BooleanSupplier isAdmin) {
|
||||
return permissionStream.filter(permission -> permission.getApp().equals(app))
|
||||
.findAny()
|
||||
.map(Permission::getLevel)
|
||||
.orElseGet(() -> hasRole(UserManager.ROLE_ADMIN) ? Permission.Level.ADMIN : Permission.Level.NONE);
|
||||
.orElseGet(() -> isAdmin.getAsBoolean() ? Permission.Level.ADMIN : Permission.Level.NONE);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -7,7 +7,6 @@ import org.springframework.data.domain.Slice;
|
|||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
import org.springframework.lang.NonNull;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
|
||||
/**
|
||||
|
@ -15,7 +14,6 @@ import java.util.Optional;
|
|||
* @since 11.12.2017
|
||||
*/
|
||||
public interface BugRepository extends JpaRepository<Bug, Integer> {
|
||||
List<Bug> findAllByApp(@NonNull App app);
|
||||
Slice<Bug> findAllByApp(@NonNull App app, @NonNull Pageable pageable);
|
||||
Slice<Bug> findAllByAppAndSolvedFalse(@NonNull App app, @NonNull Pageable pageable);
|
||||
int countAllByApp(@NonNull App app);
|
||||
|
|
|
@ -2,10 +2,11 @@ package com.faendir.acra.sql.data;
|
|||
|
||||
import com.faendir.acra.sql.model.App;
|
||||
import com.faendir.acra.sql.model.ProguardMapping;
|
||||
import org.springframework.data.domain.Pageable;
|
||||
import org.springframework.data.domain.Slice;
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
import org.springframework.lang.NonNull;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
|
||||
/**
|
||||
|
@ -13,7 +14,9 @@ import java.util.Optional;
|
|||
* @since 11.12.2017
|
||||
*/
|
||||
public interface ProguardMappingRepository extends JpaRepository<ProguardMapping, ProguardMapping.MetaData> {
|
||||
List<ProguardMapping> findAllByApp(@NonNull App app);
|
||||
Slice<ProguardMapping> findAllByApp(@NonNull App app, @NonNull Pageable pageable);
|
||||
|
||||
int countAllByApp(@NonNull App app);
|
||||
|
||||
default Optional<ProguardMapping> findById(@NonNull App app, int versionCode) {
|
||||
return findById(new ProguardMapping.MetaData(app, versionCode));
|
||||
|
|
|
@ -47,7 +47,7 @@ public class ProguardMapping {
|
|||
}
|
||||
|
||||
public static class MetaData implements Serializable {
|
||||
private App app;
|
||||
private int app;
|
||||
private int versionCode;
|
||||
|
||||
@PersistenceConstructor
|
||||
|
@ -55,18 +55,10 @@ public class ProguardMapping {
|
|||
}
|
||||
|
||||
public MetaData(App app, int versionCode) {
|
||||
this.app = app;
|
||||
this.app = app.getId();
|
||||
this.versionCode = versionCode;
|
||||
}
|
||||
|
||||
public App getApp() {
|
||||
return app;
|
||||
}
|
||||
|
||||
public int getVersionCode() {
|
||||
return versionCode;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
|
|
|
@ -17,7 +17,6 @@ import org.springframework.stereotype.Component;
|
|||
import java.security.SecureRandom;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
|
||||
/**
|
||||
|
@ -104,15 +103,6 @@ public class UserManager {
|
|||
userRepository.save(user);
|
||||
}
|
||||
|
||||
@NonNull
|
||||
public List<User> getUsers() {
|
||||
List<User> users = userRepository.findAll();
|
||||
if (users.stream().noneMatch(user -> user.getUsername().equals(acraConfiguration.getUser().getName()))) {
|
||||
users.add(getDefaultUser());
|
||||
}
|
||||
return users;
|
||||
}
|
||||
|
||||
@NonNull
|
||||
private User getDefaultUser() {
|
||||
return new User(acraConfiguration.getUser().getName(), passwordEncoder.encode(acraConfiguration.getUser().getPassword()), Arrays.asList(ROLE_USER, ROLE_ADMIN));
|
||||
|
|
|
@ -1,11 +1,17 @@
|
|||
package com.faendir.acra.sql.user;
|
||||
|
||||
import com.faendir.acra.sql.model.User;
|
||||
import org.springframework.data.domain.Pageable;
|
||||
import org.springframework.data.domain.Slice;
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
import org.springframework.lang.NonNull;
|
||||
|
||||
/**
|
||||
* @author Lukas
|
||||
* @since 20.05.2017
|
||||
*/
|
||||
interface UserRepository extends JpaRepository<User, String> {
|
||||
public interface UserRepository extends JpaRepository<User, String> {
|
||||
Slice<User> findAllByRoles(@NonNull String role, @NonNull Pageable pageable);
|
||||
|
||||
int countAllByRoles(@NonNull String role);
|
||||
}
|
||||
|
|
|
@ -10,6 +10,7 @@ import com.faendir.acra.sql.user.UserManager;
|
|||
import com.faendir.acra.ui.view.base.ConfigurationLabel;
|
||||
import com.faendir.acra.ui.view.base.MyGrid;
|
||||
import com.faendir.acra.ui.view.base.NamedView;
|
||||
import com.faendir.acra.ui.view.base.Popup;
|
||||
import com.faendir.acra.util.BufferedDataProvider;
|
||||
import com.faendir.acra.util.Style;
|
||||
import com.vaadin.data.provider.ConfigurableFilterDataProvider;
|
||||
|
@ -18,9 +19,7 @@ import com.vaadin.spring.annotation.SpringView;
|
|||
import com.vaadin.ui.Button;
|
||||
import com.vaadin.ui.Grid;
|
||||
import com.vaadin.ui.TextField;
|
||||
import com.vaadin.ui.UI;
|
||||
import com.vaadin.ui.VerticalLayout;
|
||||
import com.vaadin.ui.Window;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.data.util.Pair;
|
||||
import org.springframework.lang.NonNull;
|
||||
|
@ -66,21 +65,12 @@ public class Overview extends NamedView {
|
|||
}
|
||||
|
||||
private void addApp() {
|
||||
Window window = new Window("New App");
|
||||
TextField name = new TextField("Name");
|
||||
Button create = new Button("Create");
|
||||
VerticalLayout layout = new VerticalLayout(name, create);
|
||||
create.addClickListener(e -> {
|
||||
new Popup().setTitle("New App").addComponent(name).addCreateButton(popup -> {
|
||||
Pair<User, String> userPasswordPair = userManager.createReporterUser();
|
||||
appRepository.save(new App(name.getValue(), userPasswordPair.getFirst()));
|
||||
grid.getDataProvider().refreshAll();
|
||||
layout.removeAllComponents();
|
||||
layout.addComponent(new ConfigurationLabel(userPasswordPair.getFirst().getUsername(), userPasswordPair.getSecond()));
|
||||
layout.addComponent(new Button("Close", e2 -> window.close()));
|
||||
window.center();
|
||||
});
|
||||
window.setContent(layout);
|
||||
window.center();
|
||||
UI.getCurrent().addWindow(window);
|
||||
popup.clear().addComponent(new ConfigurationLabel(userPasswordPair.getFirst().getUsername(), userPasswordPair.getSecond())).addCloseButton().show();
|
||||
}).show();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,32 @@
|
|||
package com.faendir.acra.ui.view.base;
|
||||
|
||||
import com.vaadin.ui.Upload;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
|
||||
/**
|
||||
* @author Lukas
|
||||
* @since 19.12.2017
|
||||
*/
|
||||
public class InMemoryUpload extends Upload {
|
||||
private final ByteArrayOutputStream outputStream;
|
||||
private boolean finished;
|
||||
|
||||
public InMemoryUpload(String caption) {
|
||||
super();
|
||||
outputStream = new ByteArrayOutputStream();
|
||||
finished = false;
|
||||
setCaption(caption);
|
||||
setReceiver((filename, mimeType) -> outputStream);
|
||||
addSucceededListener(event -> finished = true);
|
||||
addFailedListener(event -> finished = false);
|
||||
}
|
||||
|
||||
public boolean isUploaded() {
|
||||
return finished;
|
||||
}
|
||||
|
||||
public String getUploadedString() {
|
||||
return outputStream.toString();
|
||||
}
|
||||
}
|
114
src/main/java/com/faendir/acra/ui/view/base/Popup.java
Normal file
114
src/main/java/com/faendir/acra/ui/view/base/Popup.java
Normal file
|
@ -0,0 +1,114 @@
|
|||
package com.faendir.acra.ui.view.base;
|
||||
|
||||
import com.faendir.acra.util.Style;
|
||||
import com.vaadin.ui.Button;
|
||||
import com.vaadin.ui.Component;
|
||||
import com.vaadin.ui.FormLayout;
|
||||
import com.vaadin.ui.HorizontalLayout;
|
||||
import com.vaadin.ui.UI;
|
||||
import com.vaadin.ui.Window;
|
||||
import org.springframework.data.util.Pair;
|
||||
import org.springframework.lang.NonNull;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
/**
|
||||
* @author Lukas
|
||||
* @since 19.12.2017
|
||||
*/
|
||||
public class Popup extends Window {
|
||||
private final List<Component> components;
|
||||
private final Map<ValidatedField<?, ?>, Pair<Boolean, ValidatedField.Listener>> fields;
|
||||
private final List<Button> buttons;
|
||||
|
||||
public Popup() {
|
||||
components = new ArrayList<>();
|
||||
fields = new HashMap<>();
|
||||
buttons = new ArrayList<>();
|
||||
}
|
||||
|
||||
@NonNull
|
||||
public Popup setTitle(@NonNull String title) {
|
||||
super.setCaption(title);
|
||||
return this;
|
||||
}
|
||||
|
||||
@NonNull
|
||||
public Popup addCreateButton(@NonNull Consumer<Popup> onCreateAction) {
|
||||
buttons.add(new Button("Create", event -> onCreateAction.accept(this)));
|
||||
return this;
|
||||
}
|
||||
|
||||
@NonNull
|
||||
public Popup addCloseButton() {
|
||||
buttons.add(new Button("Close", event -> close()));
|
||||
return this;
|
||||
}
|
||||
|
||||
@NonNull
|
||||
public Popup addYesNoButtons(@NonNull Consumer<Popup> onYesAction) {
|
||||
buttons.add(new Button("Yes", event -> onYesAction.accept(this)));
|
||||
buttons.add(new Button("No", event -> close()));
|
||||
return this;
|
||||
}
|
||||
|
||||
@NonNull
|
||||
public Popup addComponent(@NonNull Component component) {
|
||||
components.add(component);
|
||||
return this;
|
||||
}
|
||||
|
||||
public Popup addValidatedField(@NonNull ValidatedField<?, ?> validatedField) {
|
||||
return addValidatedField(validatedField, false);
|
||||
}
|
||||
|
||||
public Popup addValidatedField(@NonNull ValidatedField<?, ?> validatedField, boolean isInitialValid) {
|
||||
ValidatedField.Listener listener = value -> updateField(validatedField, value);
|
||||
validatedField.addListener(listener);
|
||||
fields.put(validatedField, Pair.of(isInitialValid, listener));
|
||||
return addComponent(validatedField.getField());
|
||||
}
|
||||
|
||||
private void updateField(@NonNull ValidatedField<?, ?> field, boolean value) {
|
||||
fields.put(field, Pair.of(value, fields.get(field).getSecond()));
|
||||
checkValid();
|
||||
}
|
||||
|
||||
public Popup clear() {
|
||||
components.clear();
|
||||
fields.forEach((field, booleanListenerPair) -> field.removeListener(booleanListenerPair.getSecond()));
|
||||
fields.clear();
|
||||
buttons.clear();
|
||||
return this;
|
||||
}
|
||||
|
||||
public void show() {
|
||||
if (buttons.size() == 1) {
|
||||
components.add(buttons.get(0));
|
||||
} else if (buttons.size() > 1) {
|
||||
HorizontalLayout buttonLayout = new HorizontalLayout();
|
||||
components.add(buttonLayout);
|
||||
buttons.forEach(buttonLayout::addComponent);
|
||||
buttons.forEach(button -> button.setWidth(100, Unit.PERCENTAGE));
|
||||
}
|
||||
components.forEach(component -> component.setWidth(100, Unit.PERCENTAGE));
|
||||
FormLayout layout = new FormLayout();
|
||||
components.forEach(layout::addComponent);
|
||||
checkValid();
|
||||
Style.apply(layout, Style.PADDING_LEFT, Style.PADDING_RIGHT);
|
||||
setContent(layout);
|
||||
center();
|
||||
if (!isAttached()) {
|
||||
UI.getCurrent().addWindow(this);
|
||||
}
|
||||
}
|
||||
|
||||
private void checkValid() {
|
||||
boolean valid = fields.values().stream().map(Pair::getFirst).reduce(Boolean::logicalAnd).orElse(true);
|
||||
buttons.forEach(button -> button.setEnabled(valid));
|
||||
}
|
||||
}
|
|
@ -1,24 +1,44 @@
|
|||
package com.faendir.acra.ui.view.base;
|
||||
|
||||
import com.vaadin.server.UserError;
|
||||
import com.vaadin.ui.AbstractComponent;
|
||||
import com.vaadin.ui.AbstractField;
|
||||
import org.springframework.lang.NonNull;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.function.Function;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
/**
|
||||
* @author Lukas
|
||||
* @since 22.06.2017
|
||||
*/
|
||||
public class ValidatedField<V, T extends AbstractField<V>> {
|
||||
public class ValidatedField<V, T extends AbstractComponent> {
|
||||
private final T field;
|
||||
private final Supplier<V> valueSupplier;
|
||||
private final Map<Function<V, Boolean>, String> validators;
|
||||
private final List<Listener> listeners;
|
||||
private boolean valid;
|
||||
|
||||
public ValidatedField(T field) {
|
||||
private ValidatedField(T field, Supplier<V> valueSupplier, Consumer<Consumer<V>> listenerRegistration){
|
||||
this.field = field;
|
||||
validators = new HashMap<>();
|
||||
field.addValueChangeListener(e -> validate(e.getValue()));
|
||||
this.valueSupplier = valueSupplier;
|
||||
this.validators = new HashMap<>();
|
||||
this.listeners = new ArrayList<>();
|
||||
this.valid = false;
|
||||
listenerRegistration.accept(this::validate);
|
||||
}
|
||||
|
||||
public static <V, T extends AbstractField<V>> ValidatedField<V, T> of(T field) {
|
||||
return new ValidatedField<>(field, field::getValue, vConsumer -> field.addValueChangeListener(event -> vConsumer.accept(event.getValue())));
|
||||
}
|
||||
|
||||
public static <V, T extends AbstractComponent> ValidatedField<V, T> of(T field, Supplier<V> valueSupplier, Consumer<Consumer<V>> listenerRegistration){
|
||||
return new ValidatedField<>(field, valueSupplier, listenerRegistration);
|
||||
}
|
||||
|
||||
public ValidatedField<V, T> addValidator(Function<V, Boolean> validator, String errorMessage) {
|
||||
|
@ -31,11 +51,11 @@ public class ValidatedField<V, T extends AbstractField<V>> {
|
|||
}
|
||||
|
||||
public boolean isValid() {
|
||||
return validate(field.getValue());
|
||||
return validate(valueSupplier.get());
|
||||
}
|
||||
|
||||
private boolean validate(V value) {
|
||||
return validators.entrySet().stream().allMatch(entry -> {
|
||||
boolean valid = validators.entrySet().stream().allMatch(entry -> {
|
||||
if (entry.getKey().apply(value)) {
|
||||
field.setComponentError(null);
|
||||
return true;
|
||||
|
@ -44,9 +64,22 @@ public class ValidatedField<V, T extends AbstractField<V>> {
|
|||
return false;
|
||||
}
|
||||
});
|
||||
if(this.valid != valid){
|
||||
this.valid = valid;
|
||||
listeners.forEach(listener -> listener.onValidationChanged(valid));
|
||||
}
|
||||
return valid;
|
||||
}
|
||||
|
||||
public V getValue() {
|
||||
return field.getValue();
|
||||
public void addListener(@NonNull Listener listener) {
|
||||
listeners.add(listener);
|
||||
}
|
||||
|
||||
public void removeListener(@NonNull Listener listener) {
|
||||
listeners.remove(listener);
|
||||
}
|
||||
|
||||
public interface Listener {
|
||||
void onValidationChanged(boolean value);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -35,7 +35,7 @@ import java.util.Set;
|
|||
*/
|
||||
@SpringComponent
|
||||
@ViewScope
|
||||
public class BugTab extends VerticalLayout implements MyTabSheet.Tab {
|
||||
public class BugTab implements MyTabSheet.Tab {
|
||||
public static final String CAPTION = "Bugs";
|
||||
@NonNull private final BugRepository bugRepository;
|
||||
@NonNull private final ReportRepository reportRepository;
|
||||
|
@ -45,16 +45,21 @@ public class BugTab extends VerticalLayout implements MyTabSheet.Tab {
|
|||
public BugTab(@NonNull BugRepository bugRepository, @NonNull ReportRepository reportRepository) {
|
||||
this.bugRepository = bugRepository;
|
||||
this.reportRepository = reportRepository;
|
||||
setCaption(CAPTION);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getCaption() {
|
||||
return CAPTION;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Component createContent(@NonNull App app, @NonNull NavigationManager navigationManager) {
|
||||
VerticalLayout layout = new VerticalLayout();
|
||||
CheckBox hideSolved = new CheckBox("Hide solved", true);
|
||||
addComponent(hideSolved);
|
||||
setComponentAlignment(hideSolved, Alignment.MIDDLE_RIGHT);
|
||||
layout.addComponent(hideSolved);
|
||||
layout.setComponentAlignment(hideSolved, Alignment.MIDDLE_RIGHT);
|
||||
MyGrid<Bug> bugs = new MyGrid<>(null, createDataProvider(app, true));
|
||||
hideSolved.addValueChangeListener(e -> getUI().access(() -> {
|
||||
hideSolved.addValueChangeListener(e -> layout.getUI().access(() -> {
|
||||
Set<Bug> selection = bugs.getSelectedItems();
|
||||
bugs.setDataProvider(createDataProvider(app, e.getValue()));
|
||||
selection.forEach(bugs::select);
|
||||
|
@ -72,10 +77,10 @@ public class BugTab extends VerticalLayout implements MyTabSheet.Tab {
|
|||
reports = new ReportList(app, navigationManager, reportRepository::delete,
|
||||
new BufferedDataProvider<>(selection.get(), reportRepository::findAllByBug, reportRepository::countAllByBug));
|
||||
reports.setSizeFull();
|
||||
replaceComponent(this.reportList, reports);
|
||||
setExpandRatio(reports, 1);
|
||||
layout.replaceComponent(this.reportList, reports);
|
||||
layout.setExpandRatio(reports, 1);
|
||||
} else if (this.reportList != null) {
|
||||
removeComponent(this.reportList);
|
||||
layout.removeComponent(this.reportList);
|
||||
}
|
||||
this.reportList = reports;
|
||||
});
|
||||
|
@ -83,11 +88,11 @@ public class BugTab extends VerticalLayout implements MyTabSheet.Tab {
|
|||
bug.setSolved(e.getValue());
|
||||
bugRepository.save(bug);
|
||||
}), new ComponentRenderer(), "Solved");
|
||||
addComponent(bugs);
|
||||
setExpandRatio(bugs, 1);
|
||||
setSizeFull();
|
||||
Style.NO_PADDING.apply(this);
|
||||
return this;
|
||||
layout.addComponent(bugs);
|
||||
layout.setExpandRatio(bugs, 1);
|
||||
layout.setSizeFull();
|
||||
Style.NO_PADDING.apply(layout);
|
||||
return layout;
|
||||
}
|
||||
|
||||
private BufferedDataProvider<Bug> createDataProvider(@NonNull App app, boolean hideSolved) {
|
||||
|
|
|
@ -6,24 +6,21 @@ import com.faendir.acra.sql.model.App;
|
|||
import com.faendir.acra.sql.model.Permission;
|
||||
import com.faendir.acra.sql.model.ProguardMapping;
|
||||
import com.faendir.acra.ui.NavigationManager;
|
||||
import com.faendir.acra.ui.view.base.InMemoryUpload;
|
||||
import com.faendir.acra.ui.view.base.MyGrid;
|
||||
import com.faendir.acra.ui.view.base.MyTabSheet;
|
||||
import com.faendir.acra.ui.view.base.Popup;
|
||||
import com.faendir.acra.ui.view.base.ValidatedField;
|
||||
import com.faendir.acra.util.BufferedDataProvider;
|
||||
import com.faendir.acra.util.Style;
|
||||
import com.vaadin.server.UserError;
|
||||
import com.vaadin.spring.annotation.SpringComponent;
|
||||
import com.vaadin.spring.annotation.ViewScope;
|
||||
import com.vaadin.ui.AbstractComponent;
|
||||
import com.vaadin.ui.Button;
|
||||
import com.vaadin.ui.Component;
|
||||
import com.vaadin.ui.ProgressBar;
|
||||
import com.vaadin.ui.TextField;
|
||||
import com.vaadin.ui.UI;
|
||||
import com.vaadin.ui.Upload;
|
||||
import com.vaadin.ui.VerticalLayout;
|
||||
import com.vaadin.ui.Window;
|
||||
import org.springframework.lang.NonNull;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import org.vaadin.risto.stepper.IntStepper;
|
||||
|
||||
/**
|
||||
* @author Lukas
|
||||
|
@ -31,70 +28,49 @@ import java.io.ByteArrayOutputStream;
|
|||
*/
|
||||
@SpringComponent
|
||||
@ViewScope
|
||||
public class DeObfuscationTab extends VerticalLayout implements MyTabSheet.Tab{
|
||||
public class DeObfuscationTab implements MyTabSheet.Tab {
|
||||
public static final String CAPTION = "De-Obfuscation";
|
||||
@NonNull private final ProguardMappingRepository mappingRepository;
|
||||
private boolean validNumber;
|
||||
private boolean validFile;
|
||||
|
||||
public DeObfuscationTab(@NonNull ProguardMappingRepository mappingRepository) {
|
||||
this.mappingRepository = mappingRepository;
|
||||
setCaption(CAPTION);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Component createContent(@NonNull App app, @NonNull NavigationManager navigationManager) {
|
||||
MyGrid<ProguardMapping> grid = new MyGrid<>(null, mappingRepository.findAllByApp(app));
|
||||
VerticalLayout layout = new VerticalLayout();
|
||||
MyGrid<ProguardMapping> grid = new MyGrid<>(null, new BufferedDataProvider<>(app, mappingRepository::findAllByApp, mappingRepository::countAllByApp));
|
||||
grid.addColumn(ProguardMapping::getVersionCode, "Version");
|
||||
grid.setWidth(100, Unit.PERCENTAGE);
|
||||
addComponent(grid);
|
||||
setSizeFull();
|
||||
Style.NO_PADDING.apply(this);
|
||||
grid.setWidth(100, VerticalLayout.Unit.PERCENTAGE);
|
||||
layout.addComponent(grid);
|
||||
layout.setSizeFull();
|
||||
Style.NO_PADDING.apply(layout);
|
||||
if (SecurityUtils.hasPermission(app, Permission.Level.EDIT)) {
|
||||
addComponent(new Button("Add File", e -> {
|
||||
Window window = new Window("New Mapping Configuration");
|
||||
Button confirm = new Button("Confirm");
|
||||
confirm.setEnabled(false);
|
||||
TextField version = new TextField("Version code", e1 -> {
|
||||
try {
|
||||
//noinspection ResultOfMethodCallIgnored
|
||||
Integer.parseInt(e1.getValue());
|
||||
validNumber = true;
|
||||
confirm.setEnabled(validFile);
|
||||
((AbstractComponent) e1.getComponent()).setComponentError(null);
|
||||
} catch (NumberFormatException ex) {
|
||||
validNumber = false;
|
||||
confirm.setEnabled(false);
|
||||
((AbstractComponent) e1.getComponent()).setComponentError(new UserError("Not a number"));
|
||||
}
|
||||
});
|
||||
ByteArrayOutputStream out = new ByteArrayOutputStream();
|
||||
Upload upload = new Upload("Mapping file:", (filename, mimeType) -> out);
|
||||
layout.addComponent(new Button("Add File", e -> {
|
||||
IntStepper version = new IntStepper("Version code");
|
||||
version.setValue(1);
|
||||
InMemoryUpload upload = new InMemoryUpload("Mapping file:");
|
||||
ProgressBar progressBar = new ProgressBar();
|
||||
progressBar.setSizeFull();
|
||||
upload.addProgressListener((readBytes, contentLength) -> getUI().access(() -> progressBar.setValue((float) readBytes / contentLength)));
|
||||
upload.addSucceededListener(e1 -> {
|
||||
validFile = true;
|
||||
confirm.setEnabled(validNumber);
|
||||
});
|
||||
upload.addFailedListener(e1 -> {
|
||||
validFile = false;
|
||||
confirm.setEnabled(false);
|
||||
});
|
||||
upload.setSizeFull();
|
||||
confirm.addClickListener(e1 -> {
|
||||
mappingRepository.save(new ProguardMapping(app, Integer.parseInt(version.getValue()), out.toString()));
|
||||
grid.setItems(mappingRepository.findAllByApp(app));
|
||||
window.close();
|
||||
});
|
||||
confirm.setSizeFull();
|
||||
VerticalLayout layout = new VerticalLayout(version, upload, progressBar, confirm);
|
||||
window.setContent(layout);
|
||||
window.center();
|
||||
UI.getCurrent().addWindow(window);
|
||||
upload.addProgressListener((readBytes, contentLength) -> layout.getUI().access(() -> progressBar.setValue((float) readBytes / contentLength)));
|
||||
new Popup().setTitle("New Mapping Configuration")
|
||||
.addComponent(version)
|
||||
.addValidatedField(ValidatedField.of(upload, () -> upload, consumer -> upload.addFinishedListener(event -> consumer.accept(upload)))
|
||||
.addValidator(InMemoryUpload::isUploaded, "Upload failed"))
|
||||
.addComponent(progressBar)
|
||||
.addCreateButton(popup -> {
|
||||
mappingRepository.save(new ProguardMapping(app, version.getValue(), upload.getUploadedString()));
|
||||
grid.getDataProvider().refreshAll();
|
||||
popup.close();
|
||||
})
|
||||
.show();
|
||||
}));
|
||||
}
|
||||
setExpandRatio(grid, 1);
|
||||
return this;
|
||||
layout.setExpandRatio(grid, 1);
|
||||
return layout;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getCaption() {
|
||||
return CAPTION;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -8,6 +8,8 @@ import com.faendir.acra.sql.user.UserManager;
|
|||
import com.faendir.acra.ui.NavigationManager;
|
||||
import com.faendir.acra.ui.view.base.ConfigurationLabel;
|
||||
import com.faendir.acra.ui.view.base.MyTabSheet;
|
||||
import com.faendir.acra.ui.view.base.Popup;
|
||||
import com.vaadin.shared.ui.ContentMode;
|
||||
import com.vaadin.spring.annotation.SpringComponent;
|
||||
import com.vaadin.spring.annotation.ViewScope;
|
||||
import com.vaadin.ui.Alignment;
|
||||
|
@ -15,9 +17,7 @@ import com.vaadin.ui.Button;
|
|||
import com.vaadin.ui.Component;
|
||||
import com.vaadin.ui.HorizontalLayout;
|
||||
import com.vaadin.ui.Label;
|
||||
import com.vaadin.ui.UI;
|
||||
import com.vaadin.ui.VerticalLayout;
|
||||
import com.vaadin.ui.Window;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.data.util.Pair;
|
||||
import org.springframework.lang.NonNull;
|
||||
|
@ -32,7 +32,7 @@ import java.util.Date;
|
|||
*/
|
||||
@SpringComponent
|
||||
@ViewScope
|
||||
public class PropertiesTab extends VerticalLayout implements MyTabSheet.Tab {
|
||||
public class PropertiesTab implements MyTabSheet.Tab {
|
||||
public static final String CAPTION = "Properties";
|
||||
@NonNull private final AppRepository appRepository;
|
||||
private final ReportRepository reportRepository;
|
||||
|
@ -43,44 +43,28 @@ public class PropertiesTab extends VerticalLayout implements MyTabSheet.Tab {
|
|||
this.appRepository = appRepository;
|
||||
this.reportRepository = reportRepository;
|
||||
this.userManager = userManager;
|
||||
setCaption(CAPTION);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Component createContent(@NonNull App app, @NonNull NavigationManager navigationManager) {
|
||||
addComponent(new Button("Create new ACRA Configuration", e -> {
|
||||
Window window = new Window("Confirm");
|
||||
VerticalLayout layout = new VerticalLayout();
|
||||
layout.addComponent(new Label("Are you sure you want to create a new ACRA configuration? The existing configuration will be invalidated"));
|
||||
Button yes = new Button("Yes", e1 -> {
|
||||
layout.removeAllComponents();
|
||||
Pair<User, String> userPasswordPair = userManager.createReporterUser();
|
||||
app.setReporter(userPasswordPair.getFirst());
|
||||
appRepository.save(app);
|
||||
layout.addComponent(new ConfigurationLabel(userPasswordPair.getFirst().getUsername(), userPasswordPair.getSecond()));
|
||||
layout.addComponent(new Button("Close", e2 -> window.close()));
|
||||
window.center();
|
||||
});
|
||||
Button no = new Button("No", e1 -> window.close());
|
||||
layout.addComponent(new HorizontalLayout(yes, no));
|
||||
window.setContent(layout);
|
||||
window.center();
|
||||
UI.getCurrent().addWindow(window);
|
||||
}));
|
||||
addComponent(new Button("Delete App", e -> {
|
||||
Window window = new Window("Confirm");
|
||||
Label label = new Label("Are you sure you want to delete this app and all its reports and mappings?");
|
||||
Button yes = new Button("Yes", e1 -> {
|
||||
appRepository.delete(app);
|
||||
window.close();
|
||||
navigationManager.navigateBack();
|
||||
});
|
||||
Button no = new Button("No", e1 -> window.close());
|
||||
VerticalLayout layout = new VerticalLayout(label, new HorizontalLayout(yes, no));
|
||||
window.setContent(layout);
|
||||
window.center();
|
||||
UI.getCurrent().addWindow(window);
|
||||
}));
|
||||
VerticalLayout layout = new VerticalLayout();
|
||||
layout.addComponent(new Button("Create new ACRA Configuration", e -> new Popup().setTitle("Confirm")
|
||||
.addComponent(new Label("Are you sure you want to create a new ACRA configuration?<br>The existing configuration will be invalidated", ContentMode.HTML))
|
||||
.addYesNoButtons(popup -> {
|
||||
Pair<User, String> userPasswordPair = userManager.createReporterUser();
|
||||
app.setReporter(userPasswordPair.getFirst());
|
||||
appRepository.save(app);
|
||||
popup.clear().addComponent(new ConfigurationLabel(userPasswordPair.getFirst().getUsername(), userPasswordPair.getSecond())).addCloseButton().show();
|
||||
})
|
||||
.show()));
|
||||
layout.addComponent(new Button("Delete App", e -> new Popup().setTitle("Confirm")
|
||||
.addComponent(new Label("Are you sure you want to delete this app and all its associated content?"))
|
||||
.addYesNoButtons(popup -> {
|
||||
appRepository.delete(app);
|
||||
popup.close();
|
||||
navigationManager.navigateBack();
|
||||
})
|
||||
.show()));
|
||||
IntStepper age = new IntStepper();
|
||||
age.setValue(30);
|
||||
age.setMinValue(0);
|
||||
|
@ -91,8 +75,13 @@ public class PropertiesTab extends VerticalLayout implements MyTabSheet.Tab {
|
|||
reportRepository.deleteAllByBugAppAndDateBefore(app, keepAfter);
|
||||
}), new Label("Reports older than "), age, new Label("Days"));
|
||||
purgeAge.setDefaultComponentAlignment(Alignment.MIDDLE_CENTER);
|
||||
addComponent(purgeAge);
|
||||
setSizeUndefined();
|
||||
return this;
|
||||
layout.addComponent(purgeAge);
|
||||
layout.setSizeUndefined();
|
||||
return layout;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getCaption() {
|
||||
return CAPTION;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,28 +6,27 @@ import com.faendir.acra.sql.model.App;
|
|||
import com.faendir.acra.sql.model.Permission;
|
||||
import com.faendir.acra.sql.model.User;
|
||||
import com.faendir.acra.sql.user.UserManager;
|
||||
import com.faendir.acra.sql.user.UserRepository;
|
||||
import com.faendir.acra.ui.view.annotation.RequiresRole;
|
||||
import com.faendir.acra.ui.view.base.MyCheckBox;
|
||||
import com.faendir.acra.ui.view.base.MyGrid;
|
||||
import com.faendir.acra.ui.view.base.NamedView;
|
||||
import com.faendir.acra.ui.view.base.Popup;
|
||||
import com.faendir.acra.ui.view.base.ValidatedField;
|
||||
import com.faendir.acra.util.BufferedDataProvider;
|
||||
import com.faendir.acra.util.Style;
|
||||
import com.vaadin.navigator.ViewChangeListener;
|
||||
import com.vaadin.spring.annotation.SpringView;
|
||||
import com.vaadin.ui.Button;
|
||||
import com.vaadin.ui.ComboBox;
|
||||
import com.vaadin.ui.FormLayout;
|
||||
import com.vaadin.ui.Grid;
|
||||
import com.vaadin.ui.PasswordField;
|
||||
import com.vaadin.ui.TextField;
|
||||
import com.vaadin.ui.UI;
|
||||
import com.vaadin.ui.VerticalLayout;
|
||||
import com.vaadin.ui.Window;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.lang.NonNull;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
|
||||
/**
|
||||
* @author Lukas
|
||||
|
@ -38,18 +37,19 @@ import java.util.Collections;
|
|||
public class UserManagerView extends NamedView {
|
||||
@NonNull private final UserManager userManager;
|
||||
@NonNull private final AppRepository appRepository;
|
||||
@NonNull private final MyGrid<User> userGrid;
|
||||
@NonNull private final UserRepository userRepository;
|
||||
private MyGrid<User> userGrid;
|
||||
|
||||
@Autowired
|
||||
public UserManagerView(@NonNull UserManager userManager, @NonNull AppRepository appRepository) {
|
||||
public UserManagerView(@NonNull UserManager userManager, @NonNull AppRepository appRepository, @NonNull UserRepository userRepository) {
|
||||
this.userManager = userManager;
|
||||
this.appRepository = appRepository;
|
||||
this.userGrid = new MyGrid<>("Users", Collections.emptyList());
|
||||
this.userRepository = userRepository;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void enter(ViewChangeListener.ViewChangeEvent event) {
|
||||
userGrid.setItems(userManager.getUsers());
|
||||
userGrid = new MyGrid<>("Users", new BufferedDataProvider<>(UserManager.ROLE_USER, userRepository::findAllByRoles, userRepository::countAllByRoles));
|
||||
userGrid.setSelectionMode(Grid.SelectionMode.NONE);
|
||||
userGrid.addColumn(User::getUsername, "Username");
|
||||
userGrid.addComponentColumn(user -> new MyCheckBox(user.getRoles().contains(UserManager.ROLE_ADMIN), !user.getUsername().equals(SecurityUtils.getUsername()),
|
||||
|
@ -75,24 +75,15 @@ public class UserManagerView extends NamedView {
|
|||
}
|
||||
|
||||
private void newUser() {
|
||||
Window window = new Window("New User");
|
||||
ValidatedField<String, TextField> name = new ValidatedField<>(new TextField("Username")).addValidator(s -> !s.isEmpty(), "Username cannot be empty")
|
||||
.addValidator(s -> userManager.getUser(s) == null, "User already exists");
|
||||
ValidatedField<String, PasswordField> password = new ValidatedField<>(new PasswordField("Password")).addValidator(s -> !s.isEmpty(), "Password cannot be empty");
|
||||
ValidatedField<String, PasswordField> repeatPassword = new ValidatedField<>(new PasswordField("Repeat Password"))
|
||||
.addValidator(s -> s.equals(password.getValue()), "Passwords do not match");
|
||||
Button create = new Button("Create");
|
||||
create.addClickListener(e -> {
|
||||
if (name.isValid() && password.isValid() && repeatPassword.isValid()) {
|
||||
userManager.createUser(name.getValue().toLowerCase(), password.getValue());
|
||||
userGrid.setItems(userManager.getUsers());
|
||||
window.close();
|
||||
}
|
||||
});
|
||||
create.setWidth(100, Unit.PERCENTAGE);
|
||||
FormLayout layout = new FormLayout(name.getField(), password.getField(), repeatPassword.getField(), create);
|
||||
window.setContent(layout);
|
||||
window.center();
|
||||
UI.getCurrent().addWindow(window);
|
||||
TextField name = new TextField("Username");
|
||||
PasswordField password = new PasswordField("Password");
|
||||
new Popup().setTitle("New User").addValidatedField(ValidatedField.of(name).addValidator(s -> !s.isEmpty(), "Username cannot be empty"))
|
||||
.addValidatedField(ValidatedField.of(password).addValidator(s -> !s.isEmpty(), "Password cannot be empty"))
|
||||
.addValidatedField(ValidatedField.of(new PasswordField("Repeat Password")).addValidator(s -> s.equals(password.getValue()), "Passwords do not match"))
|
||||
.addCreateButton(popup->{
|
||||
userManager.createUser(name.getValue().toLowerCase(), password.getValue());
|
||||
userGrid.getDataProvider().refreshAll();
|
||||
popup.close();
|
||||
}).show();
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue