mirror of
https://github.com/cryptomator/cryptomator.git
synced 2026-05-14 08:41:28 +00:00
Depeding on state of selected task, show appropiate status text in check detail view
This commit is contained in:
@@ -7,7 +7,6 @@ import org.cryptomator.ui.common.FxController;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import javafx.beans.binding.Binding;
|
||||
import javafx.beans.binding.BooleanBinding;
|
||||
import javafx.beans.property.LongProperty;
|
||||
import javafx.beans.property.ObjectProperty;
|
||||
import javafx.beans.property.SimpleLongProperty;
|
||||
@@ -25,71 +24,76 @@ import java.util.Map;
|
||||
@HealthCheckScoped
|
||||
public class CheckDetailController implements FxController {
|
||||
|
||||
private final Map<ObservableList<DiagnosticResult>, WarnAndErrorEntry> cachedWarnAndErrorCounts;
|
||||
private final Map<ObservableList<DiagnosticResult>, WarnAndErrorEntry> cachedWarnAndCritCounts;
|
||||
private final Binding<ObservableList<DiagnosticResult>> results;
|
||||
private final OptionalBinding<Worker.State> taskState;
|
||||
private final Binding<String> taskName;
|
||||
private final Binding<Number> taskDuration;
|
||||
private final ResultListCellFactory resultListCellFactory;
|
||||
private final BooleanBinding producingResults;
|
||||
private final LongProperty numOfWarnings;
|
||||
private final LongProperty numOfErrors;
|
||||
private final Binding<Boolean> taskRunning;
|
||||
private final Binding<Boolean> taskScheduled;
|
||||
private final Binding<Boolean> taskFinished;
|
||||
private final Binding<Boolean> taskNotStarted;
|
||||
private final Binding<Boolean> taskSucceeded;
|
||||
private final Binding<Boolean> taskFailed;
|
||||
private final Binding<Boolean> taskCancelled;
|
||||
private final LongProperty countOfWarnSeverity;
|
||||
private final LongProperty countOfCritSeverity;
|
||||
|
||||
public ListView<DiagnosticResult> resultsListView;
|
||||
|
||||
@Inject
|
||||
public CheckDetailController(ObjectProperty<HealthCheckTask> selectedTask, ResultListCellFactory resultListCellFactory) {
|
||||
selectedTask.addListener(this::rebindWarnAndErrorCount);
|
||||
selectedTask.addListener(this::rebindWarnAndCritProperties);
|
||||
this.results = EasyBind.wrapNullable(selectedTask).map(HealthCheckTask::results).orElse(FXCollections.emptyObservableList());
|
||||
this.taskState = EasyBind.wrapNullable(selectedTask).mapObservable(HealthCheckTask::stateProperty);
|
||||
this.taskName = EasyBind.wrapNullable(selectedTask).map(HealthCheckTask::getTitle).orElse("");
|
||||
this.taskDuration = EasyBind.wrapNullable(selectedTask).mapObservable(HealthCheckTask::durationInMillisProperty).orElse(-1L);
|
||||
this.resultListCellFactory = resultListCellFactory;
|
||||
this.producingResults = taskState.filter(this::producesResults).isPresent();
|
||||
this.numOfWarnings = new SimpleLongProperty(0);
|
||||
this.numOfErrors = new SimpleLongProperty(0);
|
||||
this.cachedWarnAndErrorCounts = new IdentityHashMap<>(); //important to use an identity hashmap, because collections violate the immnutable hashkey contract
|
||||
this.taskRunning = EasyBind.wrapNullable(selectedTask).mapObservable(HealthCheckTask::runningProperty).orElse(false); //TODO: DOES NOT WORK
|
||||
this.taskScheduled = taskState.map(Worker.State.SCHEDULED::equals).orElse(false);
|
||||
this.taskNotStarted = taskState.map(Worker.State.READY::equals).orElse(false);
|
||||
this.taskSucceeded = taskState.map(Worker.State.SUCCEEDED::equals).orElse(false);
|
||||
this.taskFailed = taskState.map(Worker.State.FAILED::equals).orElse(false);
|
||||
this.taskCancelled = taskState.map(Worker.State.CANCELLED::equals).orElse(false);
|
||||
this.taskFinished = EasyBind.combine(taskSucceeded, taskFailed, taskCancelled, (a, b, c) -> a || b || c);
|
||||
this.countOfWarnSeverity = new SimpleLongProperty(0);
|
||||
this.countOfCritSeverity = new SimpleLongProperty(0);
|
||||
this.cachedWarnAndCritCounts = new IdentityHashMap<>(); //important to use an identity hashmap, because collections violate the immnutable hashkey contract
|
||||
}
|
||||
|
||||
private synchronized void rebindWarnAndErrorCount(ObservableValue<? extends HealthCheckTask> observable, HealthCheckTask oldVal, HealthCheckTask newVal) {
|
||||
private synchronized void rebindWarnAndCritProperties(ObservableValue<? extends HealthCheckTask> observable, HealthCheckTask oldVal, HealthCheckTask newVal) {
|
||||
//create and cache properites for the newList, if not already present
|
||||
final var listToUpdate = newVal.results();
|
||||
cachedWarnAndErrorCounts.computeIfAbsent(listToUpdate, key -> {
|
||||
cachedWarnAndCritCounts.computeIfAbsent(listToUpdate, key -> {
|
||||
var warnProperty = new SimpleLongProperty(countSeverityInList(listToUpdate, DiagnosticResult.Severity.WARN));
|
||||
var errProperty = new SimpleLongProperty(countSeverityInList(listToUpdate, DiagnosticResult.Severity.CRITICAL));
|
||||
return new WarnAndErrorEntry(warnProperty, errProperty);
|
||||
});
|
||||
listToUpdate.addListener(this::updateListSpecificWarnAndErrorCount);
|
||||
listToUpdate.addListener(this::updateListSpecificWarnAndCritCount);
|
||||
|
||||
//updateBindings
|
||||
numOfErrors.bind(cachedWarnAndErrorCounts.get(listToUpdate).errorCount);
|
||||
numOfWarnings.bind(cachedWarnAndErrorCounts.get(listToUpdate).warningCount);
|
||||
countOfCritSeverity.bind(cachedWarnAndCritCounts.get(listToUpdate).errorCount);
|
||||
countOfWarnSeverity.bind(cachedWarnAndCritCounts.get(listToUpdate).warningCount);
|
||||
}
|
||||
|
||||
private synchronized void updateListSpecificWarnAndErrorCount(ListChangeListener.Change<? extends DiagnosticResult> c) {
|
||||
long tmpErr = cachedWarnAndErrorCounts.get(c.getList()).errorCount.get();
|
||||
long tmpWarn = cachedWarnAndErrorCounts.get(c.getList()).warningCount.get();
|
||||
private synchronized void updateListSpecificWarnAndCritCount(ListChangeListener.Change<? extends DiagnosticResult> c) {
|
||||
long tmpErr = cachedWarnAndCritCounts.get(c.getList()).errorCount.get();
|
||||
long tmpWarn = cachedWarnAndCritCounts.get(c.getList()).warningCount.get();
|
||||
while (c.next()) {
|
||||
if (c.wasAdded()) {
|
||||
tmpWarn += countSeverityInList(c.getAddedSubList(), DiagnosticResult.Severity.WARN);
|
||||
tmpErr += countSeverityInList(c.getAddedSubList(), DiagnosticResult.Severity.CRITICAL);
|
||||
}
|
||||
}
|
||||
cachedWarnAndErrorCounts.get(c.getList()).errorCount.set(tmpErr);
|
||||
cachedWarnAndErrorCounts.get(c.getList()).warningCount.set(tmpWarn);
|
||||
cachedWarnAndCritCounts.get(c.getList()).errorCount.set(tmpErr);
|
||||
cachedWarnAndCritCounts.get(c.getList()).warningCount.set(tmpWarn);
|
||||
}
|
||||
|
||||
private long countSeverityInList(List<? extends DiagnosticResult> list, DiagnosticResult.Severity severityToCount) {
|
||||
return list.stream().map(DiagnosticResult::getServerity).filter(severityToCount::equals).count();
|
||||
}
|
||||
|
||||
private boolean producesResults(Worker.State state) {
|
||||
return switch (state) {
|
||||
case SCHEDULED, RUNNING -> true;
|
||||
case READY, SUCCEEDED, CANCELLED, FAILED -> false;
|
||||
};
|
||||
}
|
||||
|
||||
@FXML
|
||||
public void initialize() {
|
||||
resultsListView.itemsProperty().bind(results);
|
||||
@@ -106,14 +110,6 @@ public class CheckDetailController implements FxController {
|
||||
return taskName;
|
||||
}
|
||||
|
||||
public boolean isProducingResults() {
|
||||
return producingResults.get();
|
||||
}
|
||||
|
||||
public BooleanBinding producingResultsProperty() {
|
||||
return producingResults;
|
||||
}
|
||||
|
||||
public Number getTaskDuration() {
|
||||
return taskDuration.getValue();
|
||||
}
|
||||
@@ -122,20 +118,76 @@ public class CheckDetailController implements FxController {
|
||||
return taskDuration;
|
||||
}
|
||||
|
||||
public long getNumOfWarnings() {
|
||||
return numOfWarnings.get();
|
||||
public long getCountOfWarnSeverity() {
|
||||
return countOfWarnSeverity.get();
|
||||
}
|
||||
|
||||
public LongProperty numOfWarningsProperty() {
|
||||
return numOfWarnings;
|
||||
public LongProperty countOfWarnSeverityProperty() {
|
||||
return countOfWarnSeverity;
|
||||
}
|
||||
|
||||
public long getNumOfErrors() {
|
||||
return numOfErrors.get();
|
||||
public long getCountOfCritSeverity() {
|
||||
return countOfCritSeverity.get();
|
||||
}
|
||||
|
||||
public LongProperty numOfErrorsProperty() {
|
||||
return numOfErrors;
|
||||
public LongProperty countOfCritSeverityProperty() {
|
||||
return countOfCritSeverity;
|
||||
}
|
||||
|
||||
public boolean isTaskRunning() {
|
||||
return taskRunning.getValue();
|
||||
}
|
||||
|
||||
public Binding<Boolean> taskRunningProperty() {
|
||||
return taskRunning;
|
||||
}
|
||||
|
||||
public boolean isTaskFinished() {
|
||||
return taskFinished.getValue();
|
||||
}
|
||||
|
||||
public Binding<Boolean> taskFinishedProperty() {
|
||||
return taskFinished;
|
||||
}
|
||||
|
||||
public boolean isTaskScheduled() {
|
||||
return taskScheduled.getValue();
|
||||
}
|
||||
|
||||
public Binding<Boolean> taskScheduledProperty() {
|
||||
return taskScheduled;
|
||||
}
|
||||
|
||||
public boolean isTaskNotStarted() {
|
||||
return taskNotStarted.getValue();
|
||||
}
|
||||
|
||||
public Binding<Boolean> taskNotStartedProperty() {
|
||||
return taskNotStarted;
|
||||
}
|
||||
|
||||
public boolean isTaskSucceeded() {
|
||||
return taskSucceeded.getValue();
|
||||
}
|
||||
|
||||
public Binding<Boolean> taskSucceededProperty() {
|
||||
return taskSucceeded;
|
||||
}
|
||||
|
||||
public boolean isTaskFailed() {
|
||||
return taskFailed.getValue();
|
||||
}
|
||||
|
||||
public Binding<Boolean> taskFailedProperty() {
|
||||
return taskFailed;
|
||||
}
|
||||
|
||||
public boolean isTaskCancelled() {
|
||||
return taskCancelled.getValue();
|
||||
}
|
||||
|
||||
public Binding<Boolean> taskCancelledProperty() {
|
||||
return taskCancelled;
|
||||
}
|
||||
|
||||
private static class WarnAndErrorEntry {
|
||||
|
||||
@@ -9,10 +9,16 @@
|
||||
xmlns="http://javafx.com/javafx"
|
||||
fx:controller="org.cryptomator.ui.health.CheckDetailController"
|
||||
spacing="6">
|
||||
<FormattedLabel fx:id="checkTitle" styleClass="label-large" format="%health.check.result.header" arg1="${controller.taskName}"/>
|
||||
<Label text="The check is currently running..." visible="${controller.producingResults}" managed="${controller.producingResults}"/>
|
||||
<!-- TODO: what if the check was canceled? Should be indicated in ui -->
|
||||
<FormattedLabel fx:id="checkDescription" styleClass="label" format="The check finished after %d milliseconds." arg1="${controller.taskDuration}" visible="${!controller.producingResults}" managed="${!controller.producingResults}"/>
|
||||
<FormattedLabel2 styleClass="label" format="Found %d Warnings and %d unfixable Errors." arg1="${controller.numOfWarnings}" arg2="${controller.numOfErrors}" />
|
||||
<FormattedLabel fx:id="checkTitle" styleClass="label-large" format="%health.check.detail.header" arg1="${controller.taskName}"/>
|
||||
|
||||
<Label text="%health.check.detail.taskNotStarted" visible="${controller.taskNotStarted}" managed="${controller.taskNotStarted}"/>
|
||||
<Label text="%health.check.detail.taskRunning" visible="${controller.taskRunning}" managed="${controller.taskRunning}"/>
|
||||
<Label text="%health.check.detail.taskScheduled" visible="${controller.taskScheduled}" managed="${controller.taskScheduled}"/>
|
||||
<Label text="%health.check.detail.taskCancelled" visible="${controller.taskCancelled}" managed="${controller.taskCancelled}"/>
|
||||
<Label text="%health.check.detail.taskFailed" visible="${controller.taskFailed}" managed="${controller.taskFailed}"/>
|
||||
<FormattedLabel styleClass="label" format="%health.check.detail.taskSucceeded" arg1="${controller.taskDuration}" visible="${controller.taskSucceeded}" managed="${controller.taskSucceeded}"/>
|
||||
|
||||
<FormattedLabel2 styleClass="label" format="%health.check.detail.problemCount" arg1="${controller.countOfWarnSeverity}" arg2="${controller.countOfCritSeverity}" visible="${!controller.taskNotStarted}"
|
||||
managed="${!controller.taskNotStarted}" />
|
||||
<ListView fx:id="resultsListView" VBox.vgrow="ALWAYS"/>
|
||||
</VBox>
|
||||
@@ -30,7 +30,7 @@
|
||||
</VBox>
|
||||
<StackPane visible="${controller.showResultScreen}" managed="${controller.showResultScreen}" HBox.hgrow="ALWAYS" >
|
||||
<VBox minWidth="300" alignment="CENTER" visible="${!controller.anyCheckSelected}" managed="${!controller.anyCheckSelected}" >
|
||||
<Label text="%health.check.result.noSelectedCheck" wrapText="true" alignment="CENTER" />
|
||||
<Label text="%health.check.detail.noSelectedCheck" wrapText="true" alignment="CENTER" />
|
||||
</VBox>
|
||||
<fx:include source="/fxml/health_check_details.fxml" visible="${controller.anyCheckSelected}" managed="${controller.anyCheckSelected}" />
|
||||
</StackPane>
|
||||
|
||||
@@ -154,8 +154,16 @@ health.start.configInvalid=Error while reading and parsing the vault configurati
|
||||
health.checkList.header=Available Checks
|
||||
health.checkList.selectAllBox=Select All
|
||||
health.check.runBatchBtn=Run selected Checks
|
||||
health.check.result.noSelectedCheck=For results select a finished check in the left list.
|
||||
health.check.result.header=Results of %s
|
||||
## Detail view
|
||||
health.check.detail.noSelectedCheck=For results select a finished check in the left list.
|
||||
health.check.detail.header=Results of %s
|
||||
health.check.detail.taskNotStarted=The check was not selected to run.
|
||||
health.check.detail.taskScheduled=The check is scheduled.
|
||||
health.check.detail.taskRunning=The check is currently running…
|
||||
health.check.detail.taskSucceeded=The check finished successfully after %d milliseconds.
|
||||
health.check.detail.taskFailed=The check exited with errors.
|
||||
health.check.detail.taskCancelled=The check was cancelled.
|
||||
health.check.detail.problemCount=Found %d Problems and %d unfixable Errors.
|
||||
health.check.exportBtn=Export Report
|
||||
health.check.fixBtn=Fix
|
||||
## Checks
|
||||
|
||||
Reference in New Issue
Block a user