Skip to content

Commit

Permalink
Merge branch 'development' into feature/#973-show-toast-on-sample-bat…
Browse files Browse the repository at this point in the history
…ch-add-update-remove
  • Loading branch information
sven1103 authored Jan 15, 2025
2 parents 9d84872 + fc0c1f6 commit 2ffe812
Show file tree
Hide file tree
Showing 5 changed files with 162 additions and 88 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -118,8 +118,8 @@ private static void evaluateMandatoryMetadata(NGSMethodMetadata method)
}

/**
* Creates a new pooled {@link NGSMeasurement} object instance, that describes an NGS measurement entity
* with many describing properties about provenance and instrumentation.
* Creates a new pooled {@link NGSMeasurement} object instance, that describes an NGS measurement
* entity with many describing properties about provenance and instrumentation.
*
* @param projectId the project id the measurement belongs to
* @param samplePool the sample pool label the measurement represents
Expand Down Expand Up @@ -201,6 +201,17 @@ public void updateMethod(NGSMethodMetadata methodMetadata) {
setMethod(methodMetadata);
}

/**
* Convenience method to query if the measurement was derived from a single sample.
*
* @return true, if the measurement was performed on a single sample, else returns false if the
* measurement was derived from pooled samples
* @since 1.0.0
*/
public boolean isSingleSampleMeasurement() {
return specificMetadata.size() <= 1;
}


public MeasurementCode measurementCode() {
return this.measurementCode;
Expand All @@ -209,6 +220,7 @@ public MeasurementCode measurementCode() {
public MeasurementId measurementId() {
return measurementId;
}

public ProjectId projectId() {
return projectId;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -192,13 +192,14 @@ public void addSpecificMetadata(ProteomicsSpecificMeasurementMetadata specificMe
}

/**
* Convenience method to query if the measurement was derived from a pooled sample.
* Convenience method to query if the measurement was derived from a single Sample.
*
* @return true, if the measurement was performed on a pooled sample, else returns false
* @return true, if the measurement was performed on a single Sample, else returns false if the
* measurement was derived from pooled samples
* @since 1.0.0
*/
public boolean isPooledSampleMeasurement() {
return specificMetadata.size() > 1;
public boolean isSingleSampleMeasurement() {
return specificMetadata.size() <= 1;
}

public MeasurementCode measurementCode() {
Expand Down Expand Up @@ -253,7 +254,7 @@ public String lcmsMethod() {
public Instant registrationDate() {
return registration;
}

public void updateMethod(ProteomicsMethodMetadata method) {
setMethodMetadata(method);
emitUpdatedEvent();
Expand Down Expand Up @@ -320,10 +321,6 @@ public int hashCode() {
return measurementId != null ? measurementId.hashCode() : 0;
}

public Optional<String> comment() {
return Optional.empty();
}

public Optional<String> technicalReplicateName() {
return Optional.ofNullable(technicalReplicateName);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import jakarta.persistence.Column;
import jakarta.persistence.Embeddable;
import java.util.Objects;
import java.util.Optional;
import life.qbic.projectmanagement.domain.model.sample.SampleId;

/**
Expand Down Expand Up @@ -80,8 +81,8 @@ public String fractionName() {
return fractionName;
}

public String comment() {
return comment;
public Optional<String> comment() {
return comment.isBlank() ? Optional.empty() : Optional.of(comment);
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -70,10 +70,10 @@
@PermitAll
public class MeasurementDetailsComponent extends PageArea implements Serializable {

public static final String CLICKABLE = "clickable";
@Serial
private static final long serialVersionUID = 5086686432247130622L;
private static final String DATE_TIME_FORMAT = "yyyy-MM-dd HH:mm";
public static final String CLICKABLE = "clickable";
private final TabSheet registeredMeasurementsTabSheet = new TabSheet();
private final MultiSelectLazyLoadingGrid<NGSMeasurement> ngsMeasurementGrid = new MultiSelectLazyLoadingGrid<>();
private final MultiSelectLazyLoadingGrid<ProteomicsMeasurement> proteomicsMeasurementGrid = new MultiSelectLazyLoadingGrid<>();
Expand Down Expand Up @@ -156,7 +156,7 @@ private void resetTabsInTabsheet() {
}

private void addMeasurementTab(GridLazyDataView<?> gridLazyDataView) {
if(gridLazyDataView.getItems().findAny().isEmpty()) {
if (gridLazyDataView.getItems().findAny().isEmpty()) {
return;
}
if (gridLazyDataView.getItem(0) instanceof ProteomicsMeasurement) {
Expand Down Expand Up @@ -186,18 +186,18 @@ private void createNGSMeasurementGrid() {
.setAutoWidth(true)
.setFlexGrow(0);
ngsMeasurementGrid.addComponentColumn(measurement -> {
if (measurement.samplePoolGroup().isEmpty()) {
if (measurement.isSingleSampleMeasurement()) {
return new Span(
String.join(" ", groupSampleInfoIntoCodeAndLabel(measurement.measuredSamples())));
}
MeasurementPooledSamplesDialog measurementPooledSamplesDialog = new MeasurementPooledSamplesDialog(
measurement);
Icon expandIcon = VaadinIcon.EXPAND_SQUARE.create();
expandIcon.addClassName("expand-icon");
Span expandSpan = new Span(new Span("Pooled sample"), expandIcon);
expandSpan.addClassNames("sample-column-cell", CLICKABLE);
expandSpan.addClickListener(event -> measurementPooledSamplesDialog.open());
return expandSpan;
return createNGSPooledSampleComponent(measurement);
})
.setTooltipGenerator(measurement -> {
if (measurement.isSingleSampleMeasurement()) {
return String.join(" ", groupSampleInfoIntoCodeAndLabel(measurement.measuredSamples()));
} else {
return "";
}
})
.setHeader("Samples")
.setAutoWidth(true);
Expand Down Expand Up @@ -242,6 +242,27 @@ private void createNGSMeasurementGrid() {
ngsMeasurement -> asClientLocalDateTime(ngsMeasurement.registrationDate())
.format(DateTimeFormatter.ofPattern(DATE_TIME_FORMAT)))
.setAutoWidth(true);
ngsMeasurementGrid.addComponentColumn(measurement -> {
if (measurement.isSingleSampleMeasurement()) {
Span singularComment = new Span();
var optMetadata = measurement.specificMeasurementMetadata().stream().findFirst();
optMetadata.ifPresent(metadata -> singularComment.setText(metadata.comment().orElse("")));
return singularComment;
} else {
return createNGSPooledSampleComponent(measurement);
}
})
.setHeader("Comment")
.setTooltipGenerator(measurement -> {
if (measurement.isSingleSampleMeasurement()) {
var optMetadata = measurement.specificMeasurementMetadata().stream().findFirst();
if (optMetadata.isPresent()) {
return optMetadata.get().comment().orElse("");
}
}
return "";
})
.setAutoWidth(true);
GridLazyDataView<NGSMeasurement> ngsGridDataView = ngsMeasurementGrid.setItems(query -> {
List<SortOrder> sortOrders = query.getSortOrders().stream().map(
it -> new SortOrder(it.getSorted(), it.getDirection().equals(SortDirection.ASCENDING)))
Expand Down Expand Up @@ -277,20 +298,19 @@ private void createProteomicsGrid() {
.setAutoWidth(true)
.setFlexGrow(0);
proteomicsMeasurementGrid.addComponentColumn(measurement -> {
if (!measurement.isPooledSampleMeasurement()) {
if (measurement.isSingleSampleMeasurement()) {
return new Span(
String.join(" ", groupSampleInfoIntoCodeAndLabel(measurement.measuredSamples())));
}
MeasurementPooledSamplesDialog measurementPooledSamplesDialog = new MeasurementPooledSamplesDialog(
measurement);
Icon expandIcon = VaadinIcon.EXPAND_SQUARE.create();
expandIcon.addClassName("expand-icon");
Span expandSpan = new Span(new Span("Pooled sample"), expandIcon);
expandSpan.addClassNames("sample-column-cell", CLICKABLE);
expandSpan.addClickListener(event -> measurementPooledSamplesDialog.open());
return expandSpan;
return createProteomicsPooledSampleComponent(measurement);
})
.setHeader("Samples")
.setTooltipGenerator(measurement -> {
if (measurement.isSingleSampleMeasurement()) {
return String.join(" ", groupSampleInfoIntoCodeAndLabel(measurement.measuredSamples()));
}
return "";
})
.setAutoWidth(true);
proteomicsMeasurementGrid.addComponentColumn(
proteomicsMeasurement -> renderOrganisation(proteomicsMeasurement.organisation()))
Expand Down Expand Up @@ -339,21 +359,38 @@ private void createProteomicsGrid() {
.setTooltipGenerator(measurement -> asClientLocalDateTime(measurement.registrationDate())
.format(DateTimeFormatter.ofPattern(DATE_TIME_FORMAT)))
.setAutoWidth(true);
proteomicsMeasurementGrid.addColumn(measurement -> measurement.comment().orElse(""))
proteomicsMeasurementGrid.addComponentColumn(measurement -> {
if (measurement.isSingleSampleMeasurement()) {
Span singularComment = new Span();
var optMetadata = measurement.specificMetadata().stream().findFirst();
optMetadata.ifPresent(metadata -> singularComment.setText(metadata.comment().orElse("")));
return singularComment;
} else {
return createProteomicsPooledSampleComponent(measurement);
}
})
.setHeader("Comment")
.setTooltipGenerator(measurement -> measurement.comment().orElse(""))
.setTooltipGenerator(measurement -> {
if (measurement.isSingleSampleMeasurement()) {
var optMetadata = measurement.specificMetadata().stream().findFirst();
if (optMetadata.isPresent()) {
return optMetadata.get().comment().orElse("");
}
}
return "";
})
.setAutoWidth(true);
GridLazyDataView<ProteomicsMeasurement> proteomicsGridDataView = proteomicsMeasurementGrid.setItems(
query -> {
List<SortOrder> sortOrders = query.getSortOrders().stream().map(
it -> new SortOrder(it.getSorted(),
it.getDirection().equals(SortDirection.ASCENDING)))
.collect(Collectors.toList());
sortOrders.add(SortOrder.of("measurementCode").ascending());
return measurementService.findProteomicsMeasurements(searchTerm,
context.experimentId().orElseThrow(),
query.getOffset(), query.getLimit(), sortOrders, context.projectId().orElseThrow())
.stream();
sortOrders.add(SortOrder.of("measurementCode").ascending());
return measurementService.findProteomicsMeasurements(searchTerm,
context.experimentId().orElseThrow(),
query.getOffset(), query.getLimit(), sortOrders, context.projectId().orElseThrow())
.stream();

});
proteomicsGridDataView
Expand All @@ -365,6 +402,28 @@ private void createProteomicsGrid() {
measurementsGridDataViews.add(proteomicsGridDataView);
}

private Span createProteomicsPooledSampleComponent(ProteomicsMeasurement measurement) {
MeasurementPooledSamplesDialog measurementPooledSamplesDialog = new MeasurementPooledSamplesDialog(
measurement);
Icon expandIcon = VaadinIcon.EXPAND_SQUARE.create();
expandIcon.addClassName("expand-icon");
Span expandSpan = new Span(new Span("Pooled sample"), expandIcon);
expandSpan.addClassNames("sample-column-cell", CLICKABLE);
expandSpan.addClickListener(event -> measurementPooledSamplesDialog.open());
return expandSpan;
}

private Span createNGSPooledSampleComponent(NGSMeasurement measurement) {
MeasurementPooledSamplesDialog measurementPooledSamplesDialog = new MeasurementPooledSamplesDialog(
measurement);
Icon expandIcon = VaadinIcon.EXPAND_SQUARE.create();
expandIcon.addClassName("expand-icon");
Span expandSpan = new Span(new Span("Pooled sample"), expandIcon);
expandSpan.addClassNames("sample-column-cell", CLICKABLE);
expandSpan.addClickListener(event -> measurementPooledSamplesDialog.open());
return expandSpan;
}

private void updateSelectedMeasurementsInfo(boolean isFromClient) {
listeners.forEach(listener -> listener.onComponentEvent(
new MeasurementSelectionChangedEvent(this, isFromClient)));
Expand Down Expand Up @@ -473,6 +532,54 @@ public MeasurementSelectionChangedEvent(MeasurementDetailsComponent source,
}
}

public static class MeasurementTechnologyTab extends Tab {

private final Span countBadge;
private final Span technologyNameComponent;
private final String technology;

public MeasurementTechnologyTab(String technology, int measurementCount) {
this.technology = technology;
technologyNameComponent = new Span();
this.countBadge = createBadge();
Span sampleCountComponent = new Span();
sampleCountComponent.add(countBadge);
this.add(technologyNameComponent, sampleCountComponent);
setTechnologyName(technology);
setMeasurementCount(measurementCount);
addClassName("tab-with-count");
}

/**
* Helper method for creating a badge.
*/
private static Span createBadge() {
Tag tag = new Tag(String.valueOf(0));
tag.setTagColor(TagColor.CONTRAST);
return tag;
}

public String getTabLabel() {
return technology;
}

/**
* Setter method for specifying the number of measurements of the technology type shown in this
* component
*
* @param measurementCount number of samples associated with the experiment shown in this
* component
*/
public void setMeasurementCount(int measurementCount) {
countBadge.setText(String.valueOf(measurementCount));
}

public void setTechnologyName(String technologyName) {
this.technologyNameComponent.setText(technologyName);
}

}

public class MeasurementPooledSamplesDialog extends Dialog {

/**
Expand Down Expand Up @@ -542,6 +649,10 @@ private void setPooledProteomicSampleDetails(
.setHeader("Measurement Label")
.setTooltipGenerator(ProteomicsSpecificMeasurementMetadata::label)
.setAutoWidth(true);
sampleDetailsGrid.addColumn(metadata -> metadata.comment().orElse(""))
.setHeader("comment")
.setTooltipGenerator(metadata -> metadata.comment().orElse(""))
.setAutoWidth(true);
sampleDetailsGrid.setItems(proteomicsSpecificMeasurementMetadata);
add(sampleDetailsGrid);
}
Expand Down Expand Up @@ -611,51 +722,4 @@ private Span pooledMeasurementEntry(String propertyLabel, String propertyValue)
}
}

public static class MeasurementTechnologyTab extends Tab {

private final Span countBadge;
private final Span technologyNameComponent;
private final String technology;

public MeasurementTechnologyTab(String technology, int measurementCount) {
this.technology = technology;
technologyNameComponent = new Span();
this.countBadge = createBadge();
Span sampleCountComponent = new Span();
sampleCountComponent.add(countBadge);
this.add(technologyNameComponent, sampleCountComponent);
setTechnologyName(technology);
setMeasurementCount(measurementCount);
addClassName("tab-with-count");
}

public String getTabLabel() {
return technology;
}

/**
* Helper method for creating a badge.
*/
private static Span createBadge() {
Tag tag = new Tag(String.valueOf(0));
tag.setTagColor(TagColor.CONTRAST);
return tag;
}

/**
* Setter method for specifying the number of measurements of the technology type shown in
* this component
*
* @param measurementCount number of samples associated with the experiment shown in this component
*/
public void setMeasurementCount(int measurementCount) {
countBadge.setText(String.valueOf(measurementCount));
}

public void setTechnologyName(String technologyName) {
this.technologyNameComponent.setText(technologyName);
}

}

}
Loading

0 comments on commit 2ffe812

Please sign in to comment.