add top right menu

This commit is contained in:
f43nd1r 2018-11-16 01:37:33 +01:00
parent d7d567f334
commit c429791800
24 changed files with 284 additions and 101 deletions

View file

@ -18,7 +18,7 @@ plugins {
id 'idea'
id 'war'
id 'org.springframework.boot' version '2.1.0.RELEASE'
id 'com.devsoap.vaadin-flow' version '1.0.0.RC2'
id 'com.devsoap.vaadin-flow' version '1.0.0.M6'
id 'io.spring.dependency-management' version '1.0.6.RELEASE'
id 'cn.bestwu.propdeps' version '0.0.10'
}
@ -74,16 +74,19 @@ dependencies {
implementation "com.querydsl:querydsl-jpa:$queryDslVersion"
implementation "com.querydsl:querydsl-sql:$queryDslVersion"
annotationProcessor "com.querydsl:querydsl-apt:$queryDslVersion:jpa"
annotationProcessor "javax.persistence:javax.persistence-api:2.2"
annotationProcessor "javax.annotation:javax.annotation-api:1.3.2"
implementation "com.fasterxml.jackson.datatype:jackson-datatype-jdk8"
//vaadin
implementation vaadin.bom()
implementation vaadin.platform()
implementation vaadin.dependency('icons-flow')
implementation vaadin.dependency('spring-boot-starter')
implementation 'com.vaadin:vaadin-grid-flow:2.1.0.alpha1'
implementation 'com.vaadin:vaadin-grid-flow:2.1.2'
implementation 'org.jfree:jfreechart:1.5.0'
implementation 'org.apache.xmlgraphics:batik-svggen:1.7'
implementation 'javax.servlet:javax.servlet-api:4.0.1'
implementation 'org.webjars.bowergithub.simpleelements:simple-dropdown:1.0.0'
//utility
implementation 'org.codeartisans:org.json:20161124'
implementation 'org.apache.commons:commons-text:1.4'

View file

@ -1,5 +1,5 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-5.0-rc-2-all.zip
distributionUrl=https\://services.gradle.org/distributions/gradle-4.10.2-all.zip
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists

View file

@ -1 +1,2 @@
include 'buildSrc'
include 'buildSrc'
enableFeaturePreview('IMPROVED_POM_SUPPORT')

View file

@ -91,17 +91,11 @@ public class ResourceBundleI18NProvider implements I18NProvider {
if (stream == null) {
return null; // Not found
}
Reader reader = null;
try {
reader = new InputStreamReader(stream, encoding);
try (Reader reader = new InputStreamReader(stream, encoding)) {
return new PropertyResourceBundle(reader);
} catch (UnsupportedEncodingException ex) {
stream.close();
throw ex;
} finally {
if (reader != null) {
reader.close();
}
}
} else {
return super.newBundle(baseName, locale, format, loader, reload);

View file

@ -18,7 +18,6 @@ import java.awt.*;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStreamWriter;
import java.io.Writer;
import java.nio.charset.StandardCharsets;
@ -43,46 +42,43 @@ public class JFreeChartWrapper extends Component implements HasSize, HasStyle {
this.chart = chartToBeWrapped;
getElement().setAttribute("type", "image/svg+xml");
//getElement().getStyle().set("display", "block");
getElement().setAttribute("data", new StreamResource("chart" + System.currentTimeMillis() + ".svg", new InputStreamFactory() {
@Override
public InputStream createInputStream() {
int width = getGraphWidth();
int height = getGraphHeight();
DocumentBuilderFactory docBuilderFactory = DocumentBuilderFactory.newInstance();
DocumentBuilder docBuilder;
try {
docBuilder = docBuilderFactory.newDocumentBuilder();
} catch (ParserConfigurationException e1) {
throw new RuntimeException(e1);
}
Document document = docBuilder.newDocument();
Element svgelem = document.createElement("svg");
document.appendChild(svgelem);
// Create an instance of the SVG Generator
SVGGraphics2D svgGenerator = new SVGGraphics2D(document);
// draw the chart in the SVG generator
chart.draw(svgGenerator, new Rectangle(width, height));
Element el = svgGenerator.getRoot();
el.setAttributeNS(null, "viewBox", "0 0 " + width + " " + height + "");
el.setAttributeNS(null, "style", "width:100%;height:100%;");
el.setAttributeNS(null, "preserveAspectRatio", getSvgAspectRatio());
// Write svg to buffer
try (ByteArrayOutputStream stream = new ByteArrayOutputStream();
Writer out = new OutputStreamWriter(stream, StandardCharsets.UTF_8)) {
/*
* don't use css, FF3 can'd deal with the result perfectly: wrong font sizes
*/
boolean useCSS = false;
svgGenerator.stream(el, out, useCSS, false);
stream.flush();
return new ByteArrayInputStream(stream.toByteArray());
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return null;
getElement().setAttribute("data", new StreamResource("chart" + System.currentTimeMillis() + ".svg", (InputStreamFactory) () -> {
int width = getGraphWidth();
int height = getGraphHeight();
DocumentBuilderFactory docBuilderFactory = DocumentBuilderFactory.newInstance();
DocumentBuilder docBuilder;
try {
docBuilder = docBuilderFactory.newDocumentBuilder();
} catch (ParserConfigurationException e1) {
throw new RuntimeException(e1);
}
Document document = docBuilder.newDocument();
Element svgelem = document.createElement("svg");
document.appendChild(svgelem);
// Create an instance of the SVG Generator
SVGGraphics2D svgGenerator = new SVGGraphics2D(document);
// draw the chart in the SVG generator
chart.draw(svgGenerator, new Rectangle(width, height));
Element el = svgGenerator.getRoot();
el.setAttributeNS(null, "viewBox", "0 0 " + width + " " + height + "");
el.setAttributeNS(null, "style", "width:100%;height:100%;");
el.setAttributeNS(null, "preserveAspectRatio", getSvgAspectRatio());
// Write svg to buffer
try (ByteArrayOutputStream stream = new ByteArrayOutputStream();
Writer out = new OutputStreamWriter(stream, StandardCharsets.UTF_8)) {
/*
* don't use css, FF3 can'd deal with the result perfectly: wrong font sizes
*/
boolean useCSS = false;
svgGenerator.stream(el, out, useCSS, false);
stream.flush();
return new ByteArrayInputStream(stream.toByteArray());
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return null;
}));
}

View file

@ -1,15 +1,20 @@
package com.faendir.acra.ui.base;
import com.faendir.acra.ui.component.FlexLayout;
import com.faendir.acra.ui.component.HasSize;
import com.faendir.acra.ui.component.Translatable;
import com.vaadin.flow.component.AttachEvent;
import com.vaadin.flow.component.Component;
import com.vaadin.flow.component.Composite;
import com.vaadin.flow.component.DetachEvent;
import com.vaadin.flow.component.html.Image;
import com.vaadin.flow.component.html.Paragraph;
import com.vaadin.flow.component.icon.VaadinIcon;
import com.vaadin.flow.component.orderedlayout.FlexLayout;
import com.vaadin.flow.component.orderedlayout.FlexComponent;
import com.vaadin.flow.router.AfterNavigationEvent;
import com.vaadin.flow.router.AfterNavigationListener;
import com.vaadin.flow.router.HasUrlParameter;
import com.vaadin.flow.router.RouterLink;
import com.vaadin.flow.shared.Registration;
import org.springframework.context.ApplicationContext;
@ -27,6 +32,8 @@ public class Path extends Composite<FlexLayout> implements AfterNavigationListen
public Path(ApplicationContext applicationContext) {
this.applicationContext = applicationContext;
getContent().setAlignItems(FlexComponent.Alignment.CENTER);
getContent().setFlexWrap(FlexLayout.FlexWrap.WRAP);
}
@Override
@ -66,21 +73,59 @@ public class Path extends Composite<FlexLayout> implements AfterNavigationListen
this.params = params;
}
public Component toComponent() {
return Translatable.createRouterLink(target, titleId, params);
protected RouterLink createRouterLink() {
return new RouterLink("", target);
}
protected Component createContent() {
Translatable<Paragraph> p = Translatable.createP(titleId, params);
p.setMargin(0, HasSize.Unit.PIXEL);
p.getStyle().set("padding-top", "2px");
return p;
}
public Component toComponent() {
RouterLink routerLink = createRouterLink();
Component component = createContent();
routerLink.add(component);
routerLink.getStyle().set("height", "32px");
routerLink.getStyle().set("padding", "1rem");
routerLink.getStyle().set("font-size", "130%");
routerLink.getStyle().set("text-decoration","none");
routerLink.getStyle().set("color","inherit");
return routerLink;
}
}
public static class ParametrizedElement<T extends Component & HasUrlParameter<P>, P> extends Element<T> {
public static class ParametrizedTextElement<T extends Component & HasUrlParameter<P>, P> extends Element<T> {
final P parameter;
public ParametrizedElement(Class<T> target, P parameter, String titleId, Object... params) {
public ParametrizedTextElement(Class<T> target, P parameter, String titleId, Object... params) {
super(target, titleId, params);
this.parameter = parameter;
}
public Component toComponent() {
return Translatable.createRouterLink(target, parameter, titleId, params);
@Override
protected RouterLink createRouterLink() {
return new RouterLink("", target, parameter);
}
}
public static class ImageElement<T extends Component> extends Element<T> {
private final String src;
public ImageElement(Class<T> target, String src, String titleId, Object... params) {
super(target, titleId, params);
this.src = src;
}
@Override
protected Component createContent() {
Translatable<Image> image = Translatable.createImage(src, titleId, params);
image.setMaxHeightFull();
return image;
}
}
}

View file

@ -134,7 +134,10 @@ public class Popup extends Dialog {
}
components.forEach(component -> {
if(component instanceof HasSize) {
((HasSize)component).setWidth("100%");
try {
((HasSize)component).setWidth("100%");
}catch (UnsupportedOperationException e) {
}
}
});
FormLayout layout = new FormLayout();

View file

@ -15,7 +15,7 @@
*/
package com.faendir.acra.ui.base.statistics;
import com.faendir.acra.ui.base.Card;
import com.faendir.acra.ui.component.Card;
import com.faendir.acra.ui.base.JFreeChartWrapper;
import com.faendir.acra.ui.component.HasSize;
import com.faendir.acra.ui.component.Translatable;

View file

@ -20,7 +20,7 @@ import com.faendir.acra.i18n.Messages;
import com.faendir.acra.model.App;
import com.faendir.acra.model.QReport;
import com.faendir.acra.service.DataService;
import com.faendir.acra.ui.base.Card;
import com.faendir.acra.ui.component.Card;
import com.faendir.acra.ui.component.FlexLayout;
import com.faendir.acra.ui.component.HasSize;
import com.faendir.acra.ui.component.Translatable;
@ -66,7 +66,7 @@ public class Statistics extends Composite<FlexLayout> {
properties.add(factory.createStringProperty(app, QReport.report.phoneModel, Messages.PHONE_MODEL, Messages.REPORTS_PER_PHONE_MODEL));
properties.add(factory.createStringProperty(app, QReport.report.brand, Messages.PHONE_BRAND, Messages.REPORTS_PER_BRAND));
getContent().setFlexWrap(FlexLayout.FLEX_WRAP.WRAP);
getContent().setFlexWrap(FlexLayout.FlexWrap.WRAP);
getContent().setWidthFull();
getContent().removeAll();

View file

@ -1,6 +1,5 @@
package com.faendir.acra.ui.base;
package com.faendir.acra.ui.component;
import com.faendir.acra.ui.component.HasSize;
import com.vaadin.flow.component.Component;
import com.vaadin.flow.component.Composite;
import com.vaadin.flow.component.HasStyle;
@ -21,7 +20,7 @@ public class Card extends Composite<Div> implements HasSize, HasStyle {
header = new Div();
header.getStyle().set("padding","1rem");
header.getStyle().set("box-sizing","border-box");
header.getStyle().set("background-color","#f3f5f7");
header.getStyle().set("background-color","var(--lumo-contrast-5pct)");
header.setWidth("100%");
content = new Div();
content.getStyle().set("padding","1rem");

View file

@ -0,0 +1,53 @@
package com.faendir.acra.ui.component;
import com.vaadin.flow.component.Component;
import com.vaadin.flow.component.HasComponents;
import com.vaadin.flow.component.Tag;
import com.vaadin.flow.component.dependency.HtmlImport;
import java.util.stream.Collectors;
import java.util.stream.Stream;
/**
* @author lukas
* @since 15.11.18
*/
@Tag("simple-dropdown")
@HtmlImport("bower_components/simple-dropdown/simple-dropdown.html")
public class DropdownMenu extends Component implements HasComponents, HasSize, HasStyle {
public DropdownMenu() {
}
public DropdownMenu(Component... components) {
this();
add(components);
}
public enum Origin {
LEFT, TOP, RIGHT, BOTTOM, CENTER;
}
public void setOpen(boolean open) {
getElement().setProperty("active", open);
}
public boolean isOpen() {
return getElement().getProperty("active", false);
}
public void setOrigin(Origin... origin) {
getElement().setProperty("origin", Stream.of(origin).map(Origin::name).map(String::toLowerCase).collect(Collectors.joining(" ")));
}
public Origin[] getOrigin() {
return Stream.of(getElement().getProperty("origin").split(" ")).map(String::toUpperCase).map(Origin::valueOf).toArray(Origin[]::new);
}
public void setLabel(String label) {
getElement().setProperty("label", label);
}
public String getLabel(){
return getElement().getProperty("label");
}
}

View file

@ -1,5 +1,6 @@
package com.faendir.acra.ui.component;
import com.vaadin.flow.component.Component;
import org.springframework.lang.NonNull;
/**
@ -7,29 +8,23 @@ import org.springframework.lang.NonNull;
* @since 14.11.18
*/
public class FlexLayout extends com.vaadin.flow.component.orderedlayout.FlexLayout implements HasSize, HasStyle {
public enum FLEX_WRAP {
public FlexLayout(Component... components) {
super(components);
}
public FlexLayout() {
}
public enum FlexWrap {
WRAP("wrap");
private final String value;
FLEX_WRAP(@NonNull String value) {
FlexWrap(@NonNull String value) {
this.value = value;
}
}
public enum ALIGN_CONTENT {
CENTER("center");
private final String value;
ALIGN_CONTENT(String value) {
this.value = value;
}
}
public void setFlexWrap(FLEX_WRAP flexWrap) {
public void setFlexWrap(FlexWrap flexWrap) {
getStyle().set("flex-wrap", flexWrap.value);
}
public void setAlignContent(ALIGN_CONTENT alignContent){
getStyle().set("align-content", alignContent.value);
}
}

View file

@ -15,6 +15,10 @@ public interface HasSize extends com.vaadin.flow.component.HasSize, HasStyle {
Unit(String text) {
this.text = text;
}
public String getText() {
return text;
}
}
default void setWidthFull() {
@ -22,22 +26,46 @@ public interface HasSize extends com.vaadin.flow.component.HasSize, HasStyle {
}
default void setWidth(int value, Unit unit) {
setWidth(value + unit.text);
setWidth(value + unit.getText());
}
default void setMaxWidth(int value, Unit unit) {
getStyle().set("max-width", value + unit.text);
getStyle().set("max-width", value + unit.getText());
}
default void setMaxWidthFull(){
setMaxWidth(100, Unit.PERCENTAGE);
}
default void setMinWidth(int value, Unit unit) {
getStyle().set("min-width", value + unit.getText());
}
default void setMinWidthFull(){
setMinWidth(100, Unit.PERCENTAGE);
}
default void setHeightFull() {
setHeight(100, Unit.PERCENTAGE);
}
default void setHeight(int value, Unit unit) {
setHeight(value + unit.text);
setHeight(value + unit.getText());
}
default void setMaxHeight(int value, Unit unit) {
getStyle().set("max-height", value + unit.getText());
}
default void setMaxHeightFull(){
setMaxHeight(100, Unit.PERCENTAGE);
}
default void setMinHeight(int value, Unit unit) {
getStyle().set("min-height", value + unit.getText());
}
default void setMinHeightFull(){
setMinHeight(100, Unit.PERCENTAGE);
}
}

View file

@ -8,4 +8,13 @@ public interface HasStyle extends com.vaadin.flow.component.HasStyle {
default void preventWhiteSpaceBreaking() {
getStyle().set("white-space", "nowrap");
}
default void setMargin(int value, HasSize.Unit unit) {
getStyle().set("margin", value + unit.getText());
}
default void setDefaultTextStyle() {
getStyle().set("text-decoration","none");
getStyle().set("color","inherit");
}
}

View file

@ -9,6 +9,8 @@ import com.vaadin.flow.component.Text;
import com.vaadin.flow.component.button.Button;
import com.vaadin.flow.component.checkbox.Checkbox;
import com.vaadin.flow.component.combobox.ComboBox;
import com.vaadin.flow.component.html.Anchor;
import com.vaadin.flow.component.html.Image;
import com.vaadin.flow.component.html.Paragraph;
import com.vaadin.flow.component.textfield.TextField;
import com.vaadin.flow.i18n.LocaleChangeEvent;
@ -83,6 +85,10 @@ public class Translatable<T extends Component> extends Composite<T> implements L
return create(new Paragraph(), captionId, params);
}
public static Translatable<Image> createImage(@NonNull String src, @NonNull String captionId, @NonNull Object... params) {
return new Translatable<>(new Image(src, ""), image -> image.setAlt(image.getTranslation(captionId, params)));
}
@Override
public void localeChange(LocaleChangeEvent event) {
setter.accept(getContent());

View file

@ -5,19 +5,25 @@ import com.faendir.acra.model.User;
import com.faendir.acra.security.SecurityUtils;
import com.faendir.acra.ui.base.ParentLayout;
import com.faendir.acra.ui.base.Path;
import com.faendir.acra.ui.component.DropdownMenu;
import com.faendir.acra.ui.component.FlexLayout;
import com.faendir.acra.ui.component.Translatable;
import com.vaadin.flow.component.Text;
import com.faendir.acra.ui.view.user.ChangePasswordView;
import com.faendir.acra.ui.view.user.UserManager;
import com.vaadin.flow.component.UI;
import com.vaadin.flow.component.button.Button;
import com.vaadin.flow.component.html.Anchor;
import com.vaadin.flow.component.checkbox.Checkbox;
import com.vaadin.flow.component.formlayout.FormLayout;
import com.vaadin.flow.component.html.Div;
import com.vaadin.flow.component.notification.Notification;
import com.vaadin.flow.component.orderedlayout.VerticalLayout;
import com.vaadin.flow.component.textfield.PasswordField;
import com.vaadin.flow.component.textfield.TextField;
import com.vaadin.flow.router.RouterLink;
import com.vaadin.flow.server.VaadinService;
import com.vaadin.flow.spring.annotation.SpringComponent;
import com.vaadin.flow.spring.annotation.UIScope;
import com.vaadin.flow.theme.lumo.Lumo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.lang.NonNull;
@ -60,14 +66,30 @@ public class MainView extends ParentLayout {
}
private void showMain() {
Div header = new Div(new Path(applicationContext));
Div footer = new Div(new Text("Acrarium is developed by "),
new Anchor("https://github.com/F43nd1r", "F43nd1r"),
new Text(". "),
new Anchor("https://github.com/F43nd1r/acra-backend", "Code"),
new Text(" is licensed under "),
new Anchor("https://github.com/F43nd1r/acra-backend/blob/master/LICENSE", "Apache License v2"),
new Text("."));
Translatable<Checkbox> darkTheme = Translatable.createCheckbox(false, Messages.DARK_THEME);
darkTheme.getContent().addValueChangeListener(e -> {
UI.getCurrent().getElement().setAttribute("theme", e.getValue() ? Lumo.DARK : Lumo.LIGHT);
});
Translatable<RouterLink> userManager = Translatable.createRouterLink(UserManager.class, Messages.USER_MANAGER);
userManager.setDefaultTextStyle();
Translatable<RouterLink> changePassword = Translatable.createRouterLink(ChangePasswordView.class, Messages.CHANGE_PASSWORD);
changePassword.setDefaultTextStyle();
Translatable<Button> logout = Translatable.createButton(e -> logout(), Messages.LOGOUT);
logout.getElement().setAttribute("theme", "tertiary");
logout.setDefaultTextStyle();
DropdownMenu menu = new DropdownMenu(new FormLayout(darkTheme, userManager, changePassword, logout));
menu.getStyle().set("margin", "1rem");
menu.setLabel(SecurityUtils.getUsername());
menu.setMinWidth(130, Unit.PIXEL);
menu.setOrigin(DropdownMenu.Origin.RIGHT);
Path path = new Path(applicationContext);
FlexLayout header = new FlexLayout(path, menu);
header.expand(path);
header.setWidthFull();
header.getStyle().set("box-shadow","0 3px 6px rgba(0,0,0,0.16), 0 3px 6px rgba(0,0,0,0.23)");
header.getStyle().set("border-radius","2px");
Div footer = new Div();
footer.getElement().setProperty("innerHTML", getTranslation(Messages.FOOTER));
removeAll();
add(header, layout, footer);
}

View file

@ -52,7 +52,7 @@ public class Overview extends VerticalLayout implements ComponentEventListener<A
@Override
@NonNull
public Path.Element<?> getPathElement() {
return new Path.Element<>(getClass(), Messages.ACRARIUM);
return new Path.ImageElement<>(getClass(), "frontend/logo.png", Messages.ACRARIUM);
}
@Override

View file

@ -8,7 +8,7 @@ import com.faendir.acra.model.QProguardMapping;
import com.faendir.acra.model.QReport;
import com.faendir.acra.security.SecurityUtils;
import com.faendir.acra.service.DataService;
import com.faendir.acra.ui.base.Card;
import com.faendir.acra.ui.component.Card;
import com.faendir.acra.ui.base.ConfigurationLabel;
import com.faendir.acra.ui.base.MyGrid;
import com.faendir.acra.ui.base.popup.Popup;
@ -25,6 +25,7 @@ import com.vaadin.flow.component.combobox.ComboBox;
import com.vaadin.flow.component.html.Input;
import com.vaadin.flow.component.icon.Icon;
import com.vaadin.flow.component.icon.VaadinIcon;
import com.vaadin.flow.component.orderedlayout.FlexComponent;
import com.vaadin.flow.component.textfield.TextField;
import com.vaadin.flow.component.upload.Upload;
import com.vaadin.flow.component.upload.receivers.MemoryBuffer;
@ -60,7 +61,7 @@ public class AdminTab extends AppTab<FlexLayout> {
@Override
void init(App app) {
getContent().removeAll();
getContent().setFlexWrap(FlexLayout.FLEX_WRAP.WRAP);
getContent().setFlexWrap(FlexLayout.FlexWrap.WRAP);
getContent().setWidthFull();
MyGrid<ProguardMapping> mappingGrid = new MyGrid<>(getDataService().getMappingProvider(app));
mappingGrid.setHeightToRows();
@ -105,7 +106,7 @@ public class AdminTab extends AppTab<FlexLayout> {
String mail = mailBox.getContent().getValue();
String id = idBox.getContent().getValue();
if (mail != null && !mail.isEmpty()) {
where = report.userEmail.eq(mail).and(where);
where = report.userEmail.eq(mail);
name += "_" + mail;
}
if (id != null && !id.isEmpty()) {
@ -147,7 +148,7 @@ public class AdminTab extends AppTab<FlexLayout> {
FlexLayout purgeAge = new FlexLayout();
purgeAge.setSizeFull();
purgeAge.preventWhiteSpaceBreaking();
purgeAge.setAlignContent(FlexLayout.ALIGN_CONTENT.CENTER);
purgeAge.setAlignItems(FlexComponent.Alignment.CENTER);
purgeAge.add(Translatable.createButton(e -> getDataService().deleteReportsOlderThanDays(app, Integer.parseInt(age.getValue())), Messages.PURGE),
Translatable.createP(Messages.REPORTS_OLDER_THAN1),
age, Translatable.createP(Messages.REPORTS_OLDER_THAN2));
@ -157,7 +158,7 @@ public class AdminTab extends AppTab<FlexLayout> {
FlexLayout purgeVersion = new FlexLayout();
purgeVersion.setSizeFull();
purgeVersion.preventWhiteSpaceBreaking();
purgeVersion.setAlignContent(FlexLayout.ALIGN_CONTENT.CENTER);
purgeVersion.setAlignItems(FlexComponent.Alignment.CENTER);
purgeVersion.add(Translatable.createButton(e -> {
if (versionBox.getValue() != null) {
getDataService().deleteReportsBeforeVersion(app, versionBox.getValue());

View file

@ -63,7 +63,7 @@ public abstract class AppTab<T extends Component> extends Composite<T> implement
@NonNull
public Path.Element<?> getPathElement() {
//noinspection unchecked
return new Path.ParametrizedElement<>((Class<? extends AppTab<?>>) getClass(), app.getId(), Messages.ONE_ARG, app.getName());
return new Path.ParametrizedTextElement<>((Class<? extends AppTab<?>>) getClass(), app.getId(), Messages.ONE_ARG, app.getName());
}
@Override

View file

@ -0,0 +1,14 @@
package com.faendir.acra.ui.view.user;
import com.faendir.acra.ui.component.FlexLayout;
import com.faendir.acra.ui.view.MainView;
import com.vaadin.flow.component.Composite;
import com.vaadin.flow.router.Route;
/**
* @author lukas
* @since 16.11.18
*/
@Route(value = "password", layout = MainView.class)
public class ChangePasswordView extends Composite<FlexLayout> {
}

View file

@ -0,0 +1,14 @@
package com.faendir.acra.ui.view.user;
import com.faendir.acra.ui.component.FlexLayout;
import com.faendir.acra.ui.view.MainView;
import com.vaadin.flow.component.Composite;
import com.vaadin.flow.router.Route;
/**
* @author lukas
* @since 15.11.18
*/
@Route(value = "user-manager", layout = MainView.class)
public class UserManager extends Composite<FlexLayout> {
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.4 KiB

BIN
src/main/webapp/favicon.ico Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 30 KiB