Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Experimental variables and groups are shown as cards with proper scrolling and size #754

Closed
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
68aa757
rename sample label to sample name
wow-such-code Jul 15, 2024
5c01848
restart actions
wow-such-code Jul 15, 2024
85d209d
adapt test to new header
wow-such-code Jul 15, 2024
f0e9b96
don't show label if 0 measurements are selected
wow-such-code Jul 15, 2024
8c21de0
Merge branch 'development' into feature-650/replace-sample-label-by-s…
wow-such-code Jul 16, 2024
22257e9
Merge branch 'development' into feature-650/replace-sample-label-by-s…
KochTobi Jul 17, 2024
bba5e38
add bundles precompile
wow-such-code Jul 18, 2024
17e4793
restore original gitignore
wow-such-code Jul 18, 2024
ddfcedf
Refactor SamplePage UI to current Prototype (#702)
Steffengreiner Jul 18, 2024
6be8ce6
Merge branch 'development' into feature-650/replace-sample-label-by-s…
wow-such-code Jul 18, 2024
827c896
rename sample ids field
wow-such-code Jul 18, 2024
fcfebcb
Merge pull request #710 from qbicsoftware/feature-650/replace-sample-…
wow-such-code Jul 18, 2024
df7aef2
Merge remote-tracking branch 'refs/remotes/origin/main' into development
KochTobi Jul 19, 2024
1d95e74
Merge remote-tracking branch 'refs/remotes/origin/main' into development
KochTobi Jul 25, 2024
3225958
Merge branch 'refs/heads/main' into development
KochTobi Jul 26, 2024
5437054
Users full name and orcid is shown and filterable during the addition…
Steffengreiner Jul 29, 2024
7866978
Provide CSS Zoom functionality to make application look smaller
Steffengreiner Aug 1, 2024
bd31658
Fix card collection spacing and scrolling for variables and groups
Steffengreiner Aug 1, 2024
8003e1f
Add zooming for main layout
Steffengreiner Aug 1, 2024
2afb231
Update data privacy statement to reflect shared user information
Steffengreiner Aug 2, 2024
98a97a1
Replace openId with orcid in privacy agreement
Steffengreiner Aug 2, 2024
05cdfbd
Merge branch 'main' into development
KochTobi Aug 6, 2024
1d1c35b
Update data privacy agreement
KochTobi Aug 6, 2024
12ef8a6
Merge branch 'development' into fix/alignment-of-variables-and-groups
wow-such-code Aug 12, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,6 @@
* @since 1.0.0
*/
public record UserInfo(String id, String fullName, String emailAddress, String platformUserName,
boolean isActive) implements Serializable {
boolean isActive, String oidcId, String oidcIssuer) implements Serializable {

}
Original file line number Diff line number Diff line change
Expand Up @@ -55,5 +55,6 @@ public interface UserInformationService {

Optional<UserInfo> findByOidc(String oidcId, String oidcIssuer);

List<UserInfo> findAllActive(String filter, int offset, int limit, List<SortOrder> sortOrders);
List<UserInfo> queryActiveUsersWithFilter(String filter, int offset, int limit,
List<SortOrder> sortOrders);
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
import life.qbic.identity.domain.model.UserId;
import org.springframework.data.domain.Pageable;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
import org.springframework.data.repository.CrudRepository;

/**
Expand All @@ -21,7 +22,8 @@
*
* @since 1.0.0
*/
public interface QbicUserRepo extends JpaRepository<User, UserId> {
public interface QbicUserRepo extends JpaRepository<User, UserId>,
JpaSpecificationExecutor<User> {

/**
* Find users by mail address in the persistent data storage
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
import life.qbic.identity.domain.repository.UserDataStorage;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Pageable;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Component;


Expand Down Expand Up @@ -60,13 +61,70 @@ public Optional<User> findUserByUserName(String userName) {
}

@Override
public List<User> findByUserNameContainingIgnoreCaseAndActiveTrue(String userName,
Pageable pageable) {
return userRepo.findAllByUserNameContainingIgnoreCaseAndActiveTrue(userName, pageable);
public List<User> queryActiveUsersWithFilter(String filter, Pageable pageable) {
Specification<User> userSpecification = generateUserFilterSpecification(filter);
return userRepo.findAll(userSpecification, pageable).getContent();
}

@Override
public Optional<User> findByOidcIdEqualsAndOidcIssuerEquals(String oidcId, String oidcIssuer) {
return userRepo.findByOidcIdEqualsAndOidcIssuerEquals(oidcId, oidcIssuer);
}

private Specification<User> generateUserFilterSpecification(String filter) {
Specification<User> isBlankSpec = UserSpec.isBlank(filter);
Specification<User> isFullName = UserSpec.isFullName(filter);
Specification<User> isUserNameSpec = UserSpec.isUserName(filter);
Specification<User> isOidc = UserSpec.isOidc(filter);
Specification<User> isOidcIssuer = UserSpec.isOidcIssuer(filter);
Specification<User> isActiveSpec = UserSpec.isActive();
Specification<User> filterSpecification =
Specification.anyOf(isFullName,
isUserNameSpec,
isOidc,
isOidcIssuer
);
return Specification.where(isBlankSpec)
.and(filterSpecification)
.and(isActiveSpec);
}

private static class UserSpec {

//If no filter was provided return all Users
public static Specification<User> isBlank(String filter) {
return (root, query, builder) -> {
if (filter != null && filter.isBlank()) {
return builder.conjunction();
}
return null;
};
}

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

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

// Should be extended if additional oidc providers are included, for now we only work with orcid
public static Specification<User> isOidc(String filter) {
return (root, query, builder) ->
builder.like(root.get("oidcId"), "%" + filter + "%");
}

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

public static Specification<User> isActive() {
return (root, query, builder) ->
builder.isTrue(root.get("active"));
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ public boolean isEmailAvailable(String email) {
}

@Override
public List<UserInfo> findAllActive(String filter, int offset, int limit,
public List<UserInfo> queryActiveUsersWithFilter(String filter, int offset, int limit,
List<SortOrder> sortOrders) {
List<Order> orders = sortOrders.stream().map(it -> {
Order order;
Expand All @@ -93,18 +93,19 @@ public List<UserInfo> findAllActive(String filter, int offset, int limit,
}
return order;
}).toList();
return userRepository.findByUserNameContainingIgnoreCaseAndActiveTrue(
return userRepository.queryActiveUsersWithFilter(
filter, new OffsetBasedRequest(offset, limit, Sort.by(orders)))
.stream()
.map(user -> new UserInfo(user.id().get(), user.fullName().get(), user.emailAddress().get(),
user.userName(), user.isActive()))
user.userName(), user.isActive(), user.getOidcId().orElse(null),
user.getOidcIssuer().orElse(null)))
.toList();
}

private UserInfo convert(User user) {
return new UserInfo(user.id().get(), user.fullName().get(), user.emailAddress().get(),
user.userName(),
user.isActive());
user.isActive(), user.getOidcId().orElse(null), user.getOidcIssuer().orElse(null));
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ public interface UserDataStorage {

Optional<User> findUserByUserName(String userName);

List<User> findByUserNameContainingIgnoreCaseAndActiveTrue(String username, Pageable pageable);
List<User> queryActiveUsersWithFilter(String filter, Pageable pageable);

Optional<User> findByOidcIdEqualsAndOidcIssuerEquals(String oidcId, String oidcIssuer);
}
Original file line number Diff line number Diff line change
Expand Up @@ -110,9 +110,9 @@ public void addUser(User user) throws UserStorageException {
saveUser(user);
}

public List<User> findByUserNameContainingIgnoreCaseAndActiveTrue(String userName,
public List<User> queryActiveUsersWithFilter(String filter,
Pageable pageable) {
return dataStorage.findByUserNameContainingIgnoreCaseAndActiveTrue(userName, pageable);
return dataStorage.queryActiveUsersWithFilter(filter, pageable);
}

public Optional<User> findByOidc(String oidcId, String oidcIssuer) {
Expand Down
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
Original file line number Diff line number Diff line change
Expand Up @@ -118,7 +118,7 @@ public ValidationResult validateUpdate(NGSMeasurementMetadata metadata, ProjectI

public enum NGS_PROPERTY {
QBIC_SAMPLE_ID("qbic sample id"),
SAMPLE_LABEL("sample label"),
SAMPLE_LABEL("sample name"),
ORGANISATION_ID("organisation id"),
FACILITY("facility"),
INSTRUMENT("instrument"),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -129,7 +129,7 @@ public ValidationResult validateUpdate(ProteomicsMeasurementMetadata metadata,

public enum PROTEOMICS_PROPERTY {
QBIC_SAMPLE_ID("qbic sample id"),
SAMPLE_LABEL("sample label"),
SAMPLE_LABEL("sample name"),
ORGANISATION_ID("organisation id"),
FACILITY("facility"),
INSTRUMENT("instrument"),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ class MeasurementMeasurementProteomicsValidatorSpec extends Specification {

final ProjectInformationService projectInformationService = Mock(ProjectInformationService.class)

final static List<String> validPXPProperties = Collections.unmodifiableList(["qbic sample id", "sample label", "organisation id", "facility", "instrument",
final static List<String> validPXPProperties = Collections.unmodifiableList(["qbic sample id", "sample name", "organisation id", "facility", "instrument",
"sample pool group", "cycle/fraction name", "digestion method", "digestion enzyme",
"enrichment method", "injection volume (uL)", "lc column",
"lcms method", "labeling type", "label", "comment"])
Expand Down
41 changes: 19 additions & 22 deletions user-interface/frontend/themes/datamanager/components/card.css
Original file line number Diff line number Diff line change
Expand Up @@ -48,22 +48,20 @@
opacity: 0.05;
}

.experimental-group {
display: flex;
flex-direction: column;
flex: auto;
font-size: var(--lumo-font-size-s);
padding: var(--lumo-space-l);
max-width: 300px;
}

.card-collection {
display: flex;
align-content: space-evenly;
flex-flow: column;
gap: 1rem;
margin-left: 1.5rem;
margin-top: 1.5rem;
padding-left: 1.5rem;
padding-top: 1.5rem;
}

.card-collection .experimental-group {
display: flex;
flex-direction: column;
font-size: var(--lumo-font-size-s);
padding: var(--lumo-space-l);
}

.card-collection .collection-title {
Expand All @@ -79,11 +77,10 @@
}

.card-collection .collection-content {
display: flex;
align-content: space-evenly;
flex-flow: row wrap;
gap: 1rem;
flex-direction: row;
display: grid;
grid-template-columns: repeat(4, 1fr);
grid-auto-rows: auto;
grid-gap: 1rem;
}

.card-collection .collection-controls {
Expand All @@ -93,29 +90,29 @@
gap: 0.5rem;
}

.experimental-group .header {
.card-collection .experimental-group .header {
display: flex;
justify-content: space-between;
align-items: baseline;
margin-bottom: var(--lumo-space-m);
}

.experimental-group .card-title {
.card-collection .experimental-group .card-title {
color: var(--lumo-secondary-text-color);
font-size: var(--lumo-font-size-m);
font-weight: bold;
white-space: nowrap;
margin-bottom: 0.5rem;
}

.experimental-group .content {
display: inline-flex;
.card-collection .experimental-group .content {
display: flex;
flex-wrap: wrap;
gap: var(--lumo-space-m);
margin-bottom: var(--lumo-space-m);
flex-direction: column;
}

.experimental-group vaadin-icon {
.card-collection .experimental-group vaadin-icon {
cursor: pointer;
width: 1em;
color: darkgrey;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -100,8 +100,8 @@ Since we want to remove the spacing between the cancel and confirm button we rep
}

.add-user-to-project-dialog::part(overlay) {
height: fit-content;
min-width: fit-content;
height: clamp(700px, 100%, 700px);
width: clamp(700px, 100%, 700px);
}

.add-user-to-project-dialog::part(content) {
Expand Down
32 changes: 32 additions & 0 deletions user-interface/frontend/themes/datamanager/components/div.css
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,38 @@
flex-flow: row wrap;
}

.user-info-component {
display: flex;
align-items: center;
gap: var(--lumo-space-l);
margin: var(--lumo-space-s);
}

.user-info-component .avatar {
width: var(--lumo-icon-size-l);
height: var(--lumo-icon-size-l);
}

.user-info-component .user-info {
display: flex;
flex-direction: column;
flex-wrap: wrap;
gap: var(--lumo-space-s);
}

.user-info-component .user-info .oidc {
display: inline-flex;
align-items: center;
gap: var(--lumo-space-s);
white-space: nowrap;
}

.user-info-component .user-info .user-name-and-full-name {
display: flex;
gap: var(--lumo-space-s);
align-items: baseline;
}

.disclaimer {
display: flex;
justify-content: center;
Expand Down
11 changes: 11 additions & 0 deletions user-interface/frontend/themes/datamanager/components/image.css
Original file line number Diff line number Diff line change
@@ -1,3 +1,14 @@
img.clickable {
cursor: pointer;
}

/*Default height and width for the oidc logo */
.oidc-logo {
width: var(--lumo-icon-size-m);
height: var(--lumo-icon-size-m);
}

.size-small {
width: var(--lumo-icon-size-s);
height: var(--lumo-icon-size-s);
}
Loading