start adding ui for new version structure

This commit is contained in:
f43nd1r 2019-02-11 05:07:49 +01:00
parent 981a6659d3
commit 9c3ac2c6f2
8 changed files with 91 additions and 47 deletions

View file

@ -31,6 +31,7 @@ import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
/**
@ -47,6 +48,7 @@ public class Bug {
private App app;
@Nullable
@ManyToOne(cascade = {CascadeType.MERGE, CascadeType.REFRESH}, fetch = FetchType.EAGER)
@JoinColumn(name = "solved_version")
private Version solvedVersion;
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)

View file

@ -20,6 +20,7 @@ import org.hibernate.annotations.OnDelete;
import org.hibernate.annotations.OnDeleteAction;
import org.hibernate.annotations.Type;
import org.springframework.data.annotation.PersistenceConstructor;
import org.springframework.lang.NonNull;
import org.springframework.lang.Nullable;
import javax.persistence.Entity;
@ -33,7 +34,7 @@ import javax.persistence.ManyToOne;
* @since 26.07.18
*/
@Entity
public class Version {
public class Version implements Comparable<Version>{
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private int id;
@ -50,11 +51,17 @@ public class Version {
Version() {
}
public Version(int code, String name) {
public Version(App app, int code, String name) {
this.app = app;
this.code = code;
this.name = name;
}
public Version(App app, int code, String name, String mappings) {
this(app, code, name);
this.mappings = mappings;
}
public int getCode() {
return code;
}
@ -67,4 +74,9 @@ public class Version {
public String getMappings() {
return mappings;
}
@Override
public int compareTo(@NonNull Version o) {
return Integer.compare(code, o.code);
}
}

View file

@ -79,6 +79,7 @@ import static com.faendir.acra.model.QAttachment.attachment;
import static com.faendir.acra.model.QBug.bug;
import static com.faendir.acra.model.QReport.report;
import static com.faendir.acra.model.QStacktrace.stacktrace1;
import static com.faendir.acra.model.QVersion.version;
/**
* @author lukas
@ -174,11 +175,11 @@ public class DataService implements Serializable {
return new JPAQuery<>(entityManager).from(report).where(where).select(report.id).fetch();
}
/*@NonNull
@NonNull
@PreAuthorize("T(com.faendir.acra.security.SecurityUtils).hasPermission(#app, T(com.faendir.acra.model.Permission$Level).VIEW)")
public QueryDslDataProvider<ProguardMapping> getMappingProvider(@NonNull App app) {
return new QueryDslDataProvider<>(new JPAQuery<>(entityManager).from(proguardMapping).where(proguardMapping.app.eq(app)).select(proguardMapping));
}*/
public QueryDslDataProvider<Version> getVersionProvider(@NonNull App app) {
return new QueryDslDataProvider<>(new JPAQuery<>(entityManager).from(version).where(version.app.eq(app)).select(version));
}
@Transactional
public <T> T store(T entity) {
@ -309,6 +310,12 @@ public class DataService implements Serializable {
.fetchFirst());
}
@NonNull
@PreAuthorize("T(com.faendir.acra.security.SecurityUtils).hasPermission(#app, T(com.faendir.acra.model.Permission$Level).VIEW)")
public List<Version> findAllVersions(@NonNull App app) {
return new JPAQuery<>(entityManager).from(version).where(version.app.eq(app)).select(version).fetch();
}
@Transactional
@PreAuthorize("T(com.faendir.acra.security.SecurityUtils).hasPermission(#app, T(com.faendir.acra.model.Permission$Level).EDIT)")
public void changeConfiguration(@NonNull App app, @NonNull App.Configuration configuration) {
@ -342,7 +349,7 @@ public class DataService implements Serializable {
if (app != null) {
JSONObject jsonObject = new JSONObject(content);
String trace = jsonObject.optString(ReportField.STACK_TRACE.name());
Version version = getVersion(jsonObject);
Version version = getVersion(app, jsonObject);
Stacktrace stacktrace = findStacktrace(app, trace, version.getCode()).orElseGet(() -> {
synchronized (stacktraceLock) {
return findStacktrace(app, trace, version.getCode()).orElseGet(() -> store(new Stacktrace(findBug(app, trace).orElseGet(() -> new Bug(app, trace)), trace, version)));
@ -363,7 +370,7 @@ public class DataService implements Serializable {
}
}
private Version getVersion(JSONObject jsonObject) {
private Version getVersion(App app, JSONObject jsonObject) {
JSONObject buildConfig = jsonObject.optJSONObject(ReportField.BUILD_CONFIG.name());
Integer versionCode = null;
String versionName = null;
@ -383,7 +390,7 @@ public class DataService implements Serializable {
if (versionName == null) {
versionName = jsonObject.optString(ReportField.APP_VERSION_NAME.name(), "N/A");
}
return new Version(versionCode, versionName);
return new Version(app, versionCode, versionName);
}
@NonNull
@ -420,11 +427,11 @@ public class DataService implements Serializable {
return new JPAQuery<>(entityManager).from(stacktrace1).where(stacktrace1.bug.eq(bug)).select(stacktrace1).fetch();
}
/*@NonNull
@NonNull
@PreAuthorize("T(com.faendir.acra.security.SecurityUtils).hasPermission(#app, T(com.faendir.acra.model.Permission$Level).VIEW)")
public Optional<Integer> getMaximumMappingVersion(@NonNull App app) {
return Optional.ofNullable(new JPAQuery<>(entityManager).from(proguardMapping).where(proguardMapping.app.eq(app)).select(proguardMapping.versionCode.max()).fetchOne());
}*/
public Optional<Integer> getMaxVersion(@NonNull App app) {
return Optional.ofNullable(new JPAQuery<>(entityManager).from(version).where(version.app.eq(app)).select(version.code.max()).fetchOne());
}
@Transactional
@PreAuthorize("hasRole(T(com.faendir.acra.model.User$Role).ADMIN)")

View file

@ -76,7 +76,7 @@ public class MailService {
}
private void check(MailSettings.SendMode sendMode) {
List<MailSettings> settings = new JPAQuery<>(entityManager).select(mailSettings).where(mailSettings.sendMode.eq(sendMode)).fetch();
List<MailSettings> settings = new JPAQuery<>(entityManager).select(mailSettings).from(mailSettings).where(mailSettings.sendMode.eq(sendMode)).fetch();
Map<App, List<MailSettings>> appMap = settings.stream().collect(Collectors.groupingBy(MailSettings::getApp));
for (Map.Entry<App, List<MailSettings>> appEntry : appMap.entrySet()) {
List<Report> reports = new JPAQuery<>(entityManager).select(report).where(report.date.after(ZonedDateTime.now().minus(1, sendMode.getUnit())).and(report.stacktrace.bug.app.eq(appEntry.getKey()))).fetch();

View file

@ -18,9 +18,14 @@ package com.faendir.acra.ui.view.app.tabs;
import com.faendir.acra.i18n.Messages;
import com.faendir.acra.model.App;
import com.faendir.acra.model.Permission;
import com.faendir.acra.model.QReport;
import com.faendir.acra.model.QVersion;
import com.faendir.acra.model.Version;
import com.faendir.acra.security.SecurityUtils;
import com.faendir.acra.service.DataService;
import com.faendir.acra.ui.base.ConfigurationLabel;
import com.faendir.acra.ui.base.MyGrid;
import com.faendir.acra.ui.base.popup.Popup;
import com.faendir.acra.ui.component.Card;
import com.faendir.acra.ui.component.DownloadButton;
@ -36,14 +41,22 @@ import com.vaadin.flow.component.UI;
import com.vaadin.flow.component.button.Button;
import com.vaadin.flow.component.combobox.ComboBox;
import com.vaadin.flow.component.html.Div;
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;
import com.vaadin.flow.data.renderer.ComponentRenderer;
import com.vaadin.flow.router.Route;
import com.vaadin.flow.server.StreamResource;
import com.vaadin.flow.spring.annotation.SpringComponent;
import com.vaadin.flow.spring.annotation.UIScope;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.StreamUtils;
import java.io.ByteArrayInputStream;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.util.stream.Collectors;
@ -70,41 +83,40 @@ public class AdminTab extends AppTab<Div> {
FlexLayout layout = new FlexLayout();
layout.setFlexWrap(FlexLayout.FlexWrap.WRAP);
layout.setWidthFull();
//TODO
/*
MyGrid<ProguardMapping> mappingGrid = new MyGrid<>(getDataService().getMappingProvider(app));
mappingGrid.setHeightToRows();
mappingGrid.addColumn(ProguardMapping::getVersionCode, QProguardMapping.proguardMapping.versionCode, Messages.VERSION).setFlexGrow(1);
mappingGrid.setHeight("");
Card mappingCard = new Card(mappingGrid);
mappingCard.setHeader(Translatable.createText(Messages.DE_OBFUSCATION));
mappingCard.setWidth(500, HasSize.Unit.PIXEL);
MyGrid<Version> versionGrid = new MyGrid<>(getDataService().getVersionProvider(app));
versionGrid.setHeightToRows();
versionGrid.addColumn(Version::getCode, QVersion.version.code, Messages.VERSION_CODE).setFlexGrow(1);
versionGrid.addColumn(Version::getName, QVersion.version.name, Messages.VERSION).setFlexGrow(1);
versionGrid.setHeight("");
Card versionCard = new Card(versionGrid);
versionCard.setHeader(Translatable.createText(Messages.VERSIONS));
versionCard.setWidth(500, HasSize.Unit.PIXEL);
if (SecurityUtils.hasPermission(app, Permission.Level.EDIT)) {
mappingGrid.addColumn(new ComponentRenderer<>(mapping -> new Button(new Icon(VaadinIcon.TRASH), e -> new Popup().addComponent(Translatable.createText(Messages.DELETE_MAPPING_CONFIRM, mapping.getVersionCode())).addYesNoButtons(p -> {
getDataService().delete(mapping);
mappingGrid.getDataProvider().refreshAll();
versionGrid.addColumn(new ComponentRenderer<>(v -> new Button(new Icon(VaadinIcon.TRASH), e -> new Popup().addComponent(Translatable.createText(Messages.DELETE_MAPPING_CONFIRM, v.getCode())).addYesNoButtons(p -> {
getDataService().delete(v);
versionGrid.getDataProvider().refreshAll();
}, true).show())));
mappingGrid.appendFooterRow().getCell(mappingGrid.getColumns().get(0)).setComponent(Translatable.createButton(e -> {
NumberInput version = new NumberInput(getDataService().getMaximumMappingVersion(app).map(i -> i + 1).orElse(1));//, Messages.VERSION_CODE);
versionGrid.appendFooterRow().getCell(versionGrid.getColumns().get(0)).setComponent(Translatable.createButton(e -> {
TextField name = new TextField();
NumberInput version = new NumberInput(getDataService().getMaxVersion(app).map(i -> i + 1).orElse(1));//, Messages.VERSION_CODE);
MemoryBuffer buffer = new MemoryBuffer();
Upload upload = new Upload(buffer);
new Popup()
.setTitle(Messages.NEW_MAPPING)
new Popup().setTitle(Messages.NEW_MAPPING)
.addComponent(name)
.addComponent(version)
.addComponent(upload)
.addCreateButton(popup -> {
try {
getDataService().store(new ProguardMapping(app, version.getValue().intValue(), StreamUtils.copyToString(buffer.getInputStream(), Charset.defaultCharset())));
getDataService().store(new Version(app, version.getValue().intValue(), name.getValue(), StreamUtils.copyToString(buffer.getInputStream(), Charset.defaultCharset())));
} catch (Exception ex) {
//TODO
}
mappingGrid.getDataProvider().refreshAll();
}, true)
.show();
}, Messages.NEW_FILE));
versionGrid.getDataProvider().refreshAll();
}, true).show();
}, Messages.NEW_VERSION));
}
layout.add(mappingCard);
layout.expand(mappingCard);*/
layout.add(versionCard);
layout.expand(versionCard);
Translatable<ComboBox<String>> mailBox = Translatable.createComboBox(getDataService().getFromReports(app, null, QReport.report.userEmail), Messages.BY_MAIL);
mailBox.setWidthFull();

View file

@ -18,9 +18,12 @@ package com.faendir.acra.ui.view.app.tabs;
import com.faendir.acra.i18n.Messages;
import com.faendir.acra.model.App;
import com.faendir.acra.model.Permission;
import com.faendir.acra.model.QBug;
import com.faendir.acra.model.QReport;
import com.faendir.acra.model.Version;
import com.faendir.acra.model.view.VBug;
import com.faendir.acra.security.SecurityUtils;
import com.faendir.acra.service.BugMerger;
import com.faendir.acra.service.DataService;
import com.faendir.acra.ui.base.MyGrid;
@ -31,12 +34,14 @@ import com.faendir.acra.ui.view.bug.tabs.ReportTab;
import com.faendir.acra.util.TimeSpanRenderer;
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.grid.FooterRow;
import com.vaadin.flow.component.grid.Grid;
import com.vaadin.flow.component.notification.Notification;
import com.vaadin.flow.component.orderedlayout.FlexComponent;
import com.vaadin.flow.component.orderedlayout.VerticalLayout;
import com.vaadin.flow.component.radiobutton.RadioButtonGroup;
import com.vaadin.flow.data.renderer.ComponentRenderer;
import com.vaadin.flow.router.Route;
import com.vaadin.flow.spring.annotation.SpringComponent;
import com.vaadin.flow.spring.annotation.UIScope;
@ -92,17 +97,19 @@ public class BugTab extends AppTab<VerticalLayout> {
bugs.addColumn(VBug::getHighestVersionCode, QReport.report.stacktrace.version.code.max(), Messages.LATEST_VERSION);
bugs.addColumn(VBug::getUserCount, QReport.report.installationId.countDistinct(), Messages.AFFECTED_USERS);
bugs.addColumn(bug -> bug.getBug().getTitle(), QBug.bug.title, Messages.TITLE).setFlexGrow(1);
//TODO
/*Grid.Column<VBug> solvedColumn = bugs.addColumn(new ComponentRenderer<>(bug -> {
Checkbox checkbox = new Checkbox(bug.getBug().isSolved());
checkbox.setEnabled(SecurityUtils.hasPermission(app, Permission.Level.EDIT));
checkbox.addValueChangeListener(e -> getDataService().setBugSolved(bug.getBug(), e.getValue()));
return checkbox;
}), QBug.bug.solved, Messages.SOLVED);*/
List<Version> versions = getDataService().findAllVersions(app);
Grid.Column<VBug> solvedColumn = bugs.addColumn(new ComponentRenderer<>((VBug bug) -> {
ComboBox<Version> comboBox = new ComboBox<>("", versions);
comboBox.setItemLabelGenerator(Version::getName);
comboBox.setValue(bug.getBug().getSolvedVersion());
comboBox.setEnabled(SecurityUtils.hasPermission(app, Permission.Level.EDIT));
comboBox.addValueChangeListener(e -> getDataService().setBugSolved(bug.getBug(), e.getValue()));
return comboBox;
}), QBug.bug.solvedVersion, Messages.SOLVED);
bugs.addOnClickNavigation(ReportTab.class, bug -> bug.getBug().getId());
FooterRow footerRow = bugs.appendFooterRow();
footerRow.getCell(countColumn).setComponent(merge);
//footerRow.getCell(solvedColumn).setComponent(hideSolved);
footerRow.getCell(solvedColumn).setComponent(hideSolved);
getContent().removeAll();
getContent().add(bugs);
getContent().setFlexGrow(1, bugs);

View file

@ -131,4 +131,6 @@ login=Login
oneArg=%s
api=API-Zugriff
about=Info
overview=Übersicht
overview=Übersicht
versions=Versionen
newVersion=Neue Version

View file

@ -131,4 +131,6 @@ login=Login
oneArg=%s
api=API Access
about=About
overview=Overview
overview=Overview
versions=Versions
newVersion=New Version