Skip to content

Commit

Permalink
Refactor SamplePage UI to current Prototype (#769)
Browse files Browse the repository at this point in the history
* Remove batch view button from batchregistration component

* Fix sample grid layout

* WIP in progress

* Update column width of batch component and remove unnecessary logic in BatchDetailsComponent

* Update column width of sample grid and remove unnecessary logic in SampleDetailsComponent

* Allow user to filter via organismId while searching for samples in SampleInformationMain

* Update CSS to behave similar to MeasurementMain

* Move search and download logic into samplemain and remove unnecessary logic and components

* Remove unused logger

* Make columns resizable, change sample label to name in spreadsheet and freeze action and id column

* Reset search field value if page is refreshed due to any reason (project switch etc.)

---------

Co-authored-by: Steffengreiner <[email protected]>
Co-authored-by: Steffengreiner <[email protected]>
  • Loading branch information
3 people committed Aug 13, 2024
1 parent 00121b2 commit ad9eebd
Show file tree
Hide file tree
Showing 7 changed files with 339 additions and 383 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@ private Specification<SamplePreview> generateExperimentIdandFilterSpecification(
Specification<SamplePreview> isBlankSpec = SamplePreviewSpecs.isBlank(filter);
Specification<SamplePreview> experimentIdSpec = SamplePreviewSpecs.experimentIdEquals(
experimentId);
Specification<SamplePreview> organismIdSpec = SamplePreviewSpecs.organismIdContains(filter);
Specification<SamplePreview> sampleCodeSpec = SamplePreviewSpecs.sampleCodeContains(filter);
Specification<SamplePreview> sampleLabelSpec = SamplePreviewSpecs.sampleLabelContains(filter);
Specification<SamplePreview> batchLabelSpec = SamplePreviewSpecs.batchLabelContains(filter);
Expand All @@ -79,7 +80,7 @@ private Specification<SamplePreview> generateExperimentIdandFilterSpecification(
filter);
Specification<SamplePreview> commentSpec = SamplePreviewSpecs.commentContains(filter);
Specification<SamplePreview> containsFilterSpec = Specification.anyOf(sampleCodeSpec,
sampleLabelSpec, batchLabelSpec, conditionSpec, speciesSpec,
sampleLabelSpec, organismIdSpec, batchLabelSpec, conditionSpec, speciesSpec,
specimenSpec, analyteSpec, analysisMethodContains, commentSpec);
Specification<SamplePreview> isDistinctSpec = SamplePreviewSpecs.isDistinct();
return Specification.where(experimentIdSpec).and(isBlankSpec)
Expand Down Expand Up @@ -157,6 +158,11 @@ private static Specification<SamplePreview> ontologyColumnContains(String col, S
};
}

public static Specification<SamplePreview> organismIdContains(String filter) {
return (root, query, builder) ->
builder.like(root.get("organismId"), "%" + filter + "%");
}

public static Specification<SamplePreview> speciesContains(String filter) {
return ontologyColumnContains("species", filter);
}
Expand Down
44 changes: 41 additions & 3 deletions user-interface/frontend/themes/datamanager/components/main.css
Original file line number Diff line number Diff line change
Expand Up @@ -364,8 +364,8 @@
}

.main.sample {
grid-template-columns: minmax(min-content, 60%) minmax(min-content, 50%);
grid-template-rows: minmax(min-content, 20%) minmax(min-content, 75%);
grid-template-columns: minmax(min-content, 50%) minmax(min-content, 50%);
grid-template-rows: minmax(min-content, 25%) minmax(min-content, 70%);
grid-template-areas:
". batchdetails"
"sampledetails sampledetails";
Expand All @@ -377,6 +377,43 @@
border-radius: var(--lumo-border-radius-m);
}

/*We want to show disclaimer centralized over the whole main width and height independent of defined areas */
.main.sample .no-samples-registered-disclaimer {
grid-column-start: 1;
grid-column-end: -1;
grid-row-start: 1;
grid-row-end: -1;
}

/*We want to show disclaimer centralized over the whole main width and height independent of defined areas */
.main.sample .no-experimental-groups-registered-disclaimer {
grid-column-start: 1;
grid-column-end: -1;
grid-row-start: 1;
grid-row-end: -1;
}

.main.sample .sample-main-content {
display: flex;
flex-direction: column;
row-gap: var(--lumo-space-m);
padding: var(--lumo-space-m);
justify-content: space-between;
}

.main.sample .sample-main-content .title {
font-weight: bold;
color: var(--lumo-secondary-text-color);
font-size: var(--lumo-font-size-xxl);
margin-bottom: 0.5rem;
}

.main.sample .sample-main-content .buttonAndField {
display: inline-flex;
justify-content: space-between;
gap: var(--lumo-space-m);
}

.main.sample .batch-details-component {
grid-area: batchdetails;
}
Expand Down Expand Up @@ -440,9 +477,10 @@
.main.sample {
grid-template-columns: minmax(min-content, 1fr);
grid-template-areas:
"."
"batchdetails"
"sampledetails";
grid-template-rows: minmax(min-content, 20%) minmax(min-content, 75%);
grid-template-rows: minmax(min-content, 20%) minmax(min-content, 20%) minmax(min-content, 60%);
}


Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -548,35 +548,17 @@
white-space: nowrap;
}

.sample-details-component .button-and-search-bar {
display: flex;
justify-content: space-between;
gap: var(--lumo-space-s);
margin-bottom: var(--lumo-space-m);
}

.sample-details-component .button-bar {
gap: var(--lumo-space-s);
display: inline-flex;
align-items: end;
}

.sample-details-component .sample-details-content {
display: flex;
flex-direction: column;
margin-bottom: var(--lumo-space-m);
height: 100%;
}

.sample-details-component .sample-tab-content {
height: 100%;
width: 100%;
}

.sample-details-component .search-bar {
gap: var(--lumo-space-s);
.sample-details-component .sample-count {
display: inline-flex;
align-items: end;
padding-bottom: var(--lumo-space-s);
color: var(--lumo-secondary-text-color);
}

.user-profile-component {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,6 @@
import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.util.Collection;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Objects;
import java.util.stream.Stream;
Expand All @@ -32,9 +31,7 @@
import life.qbic.datamanager.ClientDetailsProvider.ClientDetails;
import life.qbic.datamanager.views.Context;
import life.qbic.datamanager.views.general.PageArea;
import life.qbic.datamanager.views.projects.project.samples.BatchDetailsComponent.BatchPreview.ViewBatchEvent;
import life.qbic.projectmanagement.application.batch.BatchInformationService;
import life.qbic.projectmanagement.application.experiment.ExperimentInformationService;
import life.qbic.projectmanagement.domain.model.batch.Batch;
import life.qbic.projectmanagement.domain.model.batch.BatchId;
import life.qbic.projectmanagement.domain.model.experiment.Experiment;
Expand Down Expand Up @@ -63,24 +60,19 @@ public class BatchDetailsComponent extends PageArea implements Serializable {
private final Div content = new Div();
private final Grid<BatchPreview> batchGrid = new Grid<>();
private final transient BatchInformationService batchInformationService;
private final transient ExperimentInformationService experimentInformationService;
private final Collection<BatchPreview> batchPreviews = new LinkedHashSet<>();
private final ClientDetailsProvider clientDetailsProvider;
private Context context;

public BatchDetailsComponent(@Autowired BatchInformationService batchInformationService,
@Autowired ExperimentInformationService experimentInformationService,
ClientDetailsProvider clientDetailsProvider) {
Objects.requireNonNull(batchInformationService);
Objects.requireNonNull(experimentInformationService);
Objects.requireNonNull(clientDetailsProvider);
this.batchInformationService = Objects.requireNonNull(batchInformationService,
"BatchInformationService cannot be null");
this.clientDetailsProvider = Objects.requireNonNull(clientDetailsProvider,
"ClientDetailsProvider cannot be null");
addClassName("batch-details-component");
createTitleAndControls();
createBatchGrid();
add(content);
this.experimentInformationService = experimentInformationService;
this.batchInformationService = batchInformationService;
this.clientDetailsProvider = clientDetailsProvider;
}

private void createTitleAndControls() {
Expand All @@ -98,47 +90,48 @@ private void createBatchGrid() {
content.addClassName("content");
batchGrid.addColumn(BatchPreview::batchLabel)
.setHeader("Name").setSortable(true)
.setTooltipGenerator(BatchPreview::batchLabel).setFlexGrow(1).setAutoWidth(true);
.setTooltipGenerator(BatchPreview::batchLabel)
.setAutoWidth(true)
.setResizable(true);
batchGrid.addColumn(new LocalDateTimeRenderer<>(
batchPreview -> asClientLocalDateTime(batchPreview.createdOn()),
"yyyy-MM-dd"))
.setKey("createdOn")
.setHeader("Date Created")
.setSortable(true)
.setComparator(BatchPreview::createdOn);
.setComparator(BatchPreview::createdOn)
.setAutoWidth(true);
batchGrid.addColumn(new LocalDateTimeRenderer<>(
batchPreview -> asClientLocalDateTime(batchPreview.lastModified()),
"yyyy-MM-dd"))
.setKey("lastModified")
.setHeader("Date Modified")
.setSortable(true)
.setComparator(BatchPreview::lastModified);
.setComparator(BatchPreview::lastModified)
.setAutoWidth(true);
batchGrid.addColumn(batchPreview -> batchPreview.samples.size())
.setKey("samples")
.setHeader("Samples")
.setSortable(true);
batchGrid.addComponentColumn(this::generateEditorButtons).setAutoWidth(true)
.setHeader("Action");
.setSortable(true)
.setAutoWidth(true);
batchGrid.addComponentColumn(this::generateEditorButtons)
.setAutoWidth(true)
.setHeader("Action")
.setFrozenToEnd(true);
batchGrid.addThemeVariants(GridVariant.LUMO_COMPACT);
batchGrid.addClassName("batch-grid");
batchGrid.setAllRowsVisible(true);
}

public void setContext(Context context) {
batchPreviews.clear();
if (context.experimentId().isEmpty()) {
throw new ApplicationException("no experiment id in context " + context);
}
if (context.projectId().isEmpty()) {
throw new ApplicationException("no project id in context " + context);
}
this.context = context;
ExperimentId experimentId = context.experimentId().get();
Experiment experiment = experimentInformationService.find(
context.projectId().orElseThrow().value(), experimentId).orElseThrow();
loadBatchesForExperiment(experiment);
batchGrid.setItems(batchPreviews)
.setSortOrder(BatchPreview::lastModified, SortDirection.DESCENDING);
updateBatchGridDataProvider(context.experimentId().get());
}

private Span generateEditorButtons(BatchPreview batchPreview) {
Expand All @@ -149,6 +142,7 @@ private Span generateEditorButtons(BatchPreview batchPreview) {
editButton.addThemeVariants(ButtonVariant.LUMO_ICON, ButtonVariant.LUMO_TERTIARY_INLINE);
deleteButton.addThemeVariants(ButtonVariant.LUMO_ICON, ButtonVariant.LUMO_TERTIARY_INLINE,
ButtonVariant.LUMO_ERROR);
deleteButton.addThemeVariants(ButtonVariant.LUMO_ICON, ButtonVariant.LUMO_TERTIARY_INLINE);
deleteButton.addClickListener(e -> fireEvent(new DeleteBatchEvent(this, batchPreview.batchId(),
e.isFromClient())));
editButton.addClickListener(
Expand All @@ -165,23 +159,16 @@ private BatchPreview generatePreviewFromBatch(Batch batch) {
batch.lastModified());
}

private void loadBatchesForExperiment(Experiment experiment) {
batchInformationService.retrieveBatchesForExperiment(experiment.experimentId())

private void updateBatchGridDataProvider(ExperimentId experimentId) {
List<BatchPreview> experimentBatches = batchInformationService.retrieveBatchesForExperiment(
experimentId)
.map(Collection::stream)
.map(batchStream -> batchStream.map(this::generatePreviewFromBatch))
.map(Stream::toList)
.onValue(batchPreviews::addAll);
}

/**
* Register a {@link ComponentEventListener} that will get informed with an
* {@link ViewBatchEvent}, as soon as a user wants to view a {@link Batch}
*
* @param batchViewListener a listener on the batch view trigger
*/
public void addBatchViewListener(
ComponentEventListener<ViewBatchEvent> batchViewListener) {
addListener(ViewBatchEvent.class, batchViewListener);
.map(Stream::toList).getValue();
batchGrid.setItems(experimentBatches);
batchGrid.getListDataView().setSortOrder(BatchPreview::batchLabel, SortDirection.DESCENDING);
batchGrid.recalculateColumnWidths();
}

/**
Expand Down Expand Up @@ -237,29 +224,6 @@ public record BatchPreview(BatchId batchId, String batchLabel, List<SampleId> sa
Objects.requireNonNull(lastModified);
}

/**
* <b>View Batch Event</b>
*
* <p>Indicates that a user wants to view a {@link Batch}
* within the {@link BatchDetailsComponent} of a project</p>
*/
public static class ViewBatchEvent extends ComponentEvent<BatchDetailsComponent> {

@Serial
private static final long serialVersionUID = -5108638994476271770L;

private final BatchPreview batchPreview;

public ViewBatchEvent(BatchDetailsComponent source, BatchPreview batchPreview,
boolean fromClient) {
super(source, fromClient);
this.batchPreview = batchPreview;
}

public BatchPreview batchPreview() {
return batchPreview;
}
}
}

/**
Expand Down
Loading

0 comments on commit ad9eebd

Please sign in to comment.