Skip to content

Commit

Permalink
Merge pull request #778 from qbicsoftware/release/1.3.0
Browse files Browse the repository at this point in the history
Release 1.3.0
  • Loading branch information
KochTobi authored Aug 13, 2024
2 parents 22c0c75 + 39e38b2 commit 004124e
Show file tree
Hide file tree
Showing 48 changed files with 900 additions and 608 deletions.
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,8 +68,9 @@ 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> sampleNameSpec = SamplePreviewSpecs.sampleNameContains(filter);
Specification<SamplePreview> batchLabelSpec = SamplePreviewSpecs.batchLabelContains(filter);
Specification<SamplePreview> conditionSpec = SamplePreviewSpecs.conditionContains(filter);
Specification<SamplePreview> speciesSpec = SamplePreviewSpecs.speciesContains(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,
sampleNameSpec, organismIdSpec, batchLabelSpec, conditionSpec, speciesSpec,
specimenSpec, analyteSpec, analysisMethodContains, commentSpec);
Specification<SamplePreview> isDistinctSpec = SamplePreviewSpecs.isDistinct();
return Specification.where(experimentIdSpec).and(isBlankSpec)
Expand Down Expand Up @@ -126,9 +127,9 @@ public static Specification<SamplePreview> batchLabelContains(String filter) {
builder.like(root.get("batchLabel"), "%" + filter + "%");
}

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

public static Specification<SamplePreview> conditionContains(String filter) {
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 @@ -17,7 +17,7 @@ public record SampleUpdateRequest(SampleId sampleId, SampleInformation sampleInf
/**
* Sample update request.
* <p>
* @param sampleLabel a human-readable semantic descriptor of the sample
* @param sampleName a human-readable semantic descriptor of the sample
* @param organismId optional identifier of the sample's source patient or organism
* @param analysisMethod analysis method to be performed
* @param experimentalGroup the experimental group the sample is part of
Expand All @@ -26,7 +26,7 @@ public record SampleUpdateRequest(SampleId sampleId, SampleInformation sampleInf
* @param analyte the analyte the sample belongs to
* @param comment comment relating to the sample
*/
public record SampleInformation(String sampleLabel, String organismId,
public record SampleInformation(String sampleName, String organismId,
AnalysisMethod analysisMethod,
ExperimentalGroup experimentalGroup, OntologyTerm species,
OntologyTerm specimen, OntologyTerm analyte,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -169,7 +169,7 @@ public record RawData(MeasurementCode measurementCode,
* Sample Information associated with the measurements to which the {@link RawData} is linked and
* meant to be employed in the frontend
*/
public record RawDataSampleInformation(SampleCode sampleCode, String sampleLabel) {
public record RawDataSampleInformation(SampleCode sampleCode, String sampleName) {

}

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 @@ -39,7 +39,7 @@ public class SamplePreview {
private String batchLabel;

@Column(name = "label")
private String sampleLabel;
private String sampleName;

@Column(name = "organism_id")
private String organismId;
Expand All @@ -58,14 +58,14 @@ protected SamplePreview() {
}

private SamplePreview(ExperimentId experimentId, SampleId sampleId, String sampleCode,
String batchLabel, String sampleLabel, String organismId,
String batchLabel, String sampleName, String organismId,
ExperimentalGroup experimentalGroup, OntologyTerm species,
OntologyTerm specimen, OntologyTerm analyte, String analysisMethod, String comment) {
Objects.requireNonNull(experimentId);
Objects.requireNonNull(sampleId);
Objects.requireNonNull(sampleCode);
Objects.requireNonNull(batchLabel);
Objects.requireNonNull(sampleLabel);
Objects.requireNonNull(sampleName);
Objects.requireNonNull(experimentalGroup);
Objects.requireNonNull(species);
Objects.requireNonNull(specimen);
Expand All @@ -75,7 +75,7 @@ private SamplePreview(ExperimentId experimentId, SampleId sampleId, String sampl
this.sampleId = sampleId;
this.sampleCode = sampleCode;
this.batchLabel = batchLabel;
this.sampleLabel = sampleLabel;
this.sampleName = sampleName;
this.experimentalGroup = experimentalGroup;
this.species = species;
this.specimen = specimen;
Expand All @@ -95,7 +95,7 @@ private SamplePreview(ExperimentId experimentId, SampleId sampleId, String sampl
* @param batchLabel the label of the {@link Batch} which contains the {@link Sample}
* associated with this preview
* associated with this preview
* @param sampleLabel the label of the {@link Sample} associated with this preview
* @param sampleName the name of the {@link Sample} associated with this preview
* @param organismId optional identifier of the patient or organism a {@link Sample} was taken of
* @param experimentalGroup the {@link ExperimentalGroup} for the {@link Sample} associated with
* this preview
Expand All @@ -112,11 +112,11 @@ private SamplePreview(ExperimentId experimentId, SampleId sampleId, String sampl
public static SamplePreview create(ExperimentId experimentId, SampleId sampleId,
String sampleCode,
String batchLabel,
String sampleLabel, String organismId, ExperimentalGroup experimentalGroup,
String sampleName, String organismId, ExperimentalGroup experimentalGroup,
OntologyTerm species, OntologyTerm specimen, OntologyTerm analyte,
String analysisMethod, String comment) {
return new SamplePreview(experimentId, sampleId, sampleCode, batchLabel,
sampleLabel, organismId, experimentalGroup, species, specimen, analyte, analysisMethod,
sampleName, organismId, experimentalGroup, species, specimen, analyte, analysisMethod,
comment);
}

Expand All @@ -136,8 +136,8 @@ public String batchLabel() {
return batchLabel;
}

public String sampleLabel() {
return sampleLabel;
public String sampleName() {
return sampleName;
}

public OntologyTerm species() {
Expand Down Expand Up @@ -179,8 +179,8 @@ public boolean equals(Object o) {
SamplePreview that = (SamplePreview) o;
return Objects.equals(experimentId, that.experimentId) && Objects.equals(
sampleCode, that.sampleCode) && Objects.equals(sampleId, that.sampleId)
&& Objects.equals(batchLabel, that.batchLabel) && Objects.equals(sampleLabel,
that.sampleLabel) && Objects.equals(organismId, that.organismId)
&& Objects.equals(batchLabel, that.batchLabel) && Objects.equals(sampleName,
that.sampleName) && Objects.equals(organismId, that.organismId)
&& Objects.equals(species, that.species) && Objects.equals(specimen,
that.specimen) && Objects.equals(analyte, that.analyte) && Objects.equals(
experimentalGroup, that.experimentalGroup) && Objects.equals(analysisMethod,
Expand All @@ -190,7 +190,7 @@ public boolean equals(Object o) {
@Override
public int hashCode() {
return Objects.hash(experimentId, sampleCode, sampleId, batchLabel,
sampleLabel, organismId,
sampleName, organismId,
species, specimen, analyte, experimentalGroup, analysisMethod, comment);
}

Expand All @@ -201,7 +201,7 @@ public String toString() {
", sampleCode='" + sampleCode + '\'' +
", sampleId='" + sampleId + '\'' +
", batchLabel='" + batchLabel + '\'' +
", sampleLabel='" + sampleLabel + '\'' +
", sampleName='" + sampleName + '\'' +
", organismId='" + organismId + '\'' +
", species='" + species + '\'' +
", specimen='" + specimen + '\'' +
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -164,7 +164,7 @@ public void setSampleOrigin(SampleOrigin sampleOrigin) {
}

public void update(SampleUpdateRequest sampleInfo) {
setLabel(sampleInfo.sampleInformation().sampleLabel());
setLabel(sampleInfo.sampleInformation().sampleName());
setOrganismId(sampleInfo.sampleInformation().organismId());
setAnalysisMethod(sampleInfo.sampleInformation().analysisMethod());
setSampleOrigin(SampleOrigin.create(sampleInfo.sampleInformation().species(),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ public void updateSamples(Project project, Collection<SampleUpdateRequest> updat
var sampleInfo = updatedSamples.stream()
.filter(sampleUpdateRequest -> sampleUpdateRequest.sampleId().equals(sample.sampleId()))
.findFirst().orElseThrow();
sample.setLabel(sampleInfo.sampleInformation().sampleLabel());
sample.setLabel(sampleInfo.sampleInformation().sampleName());
sample.setOrganismId(sampleInfo.sampleInformation().organismId());
sample.setAnalysisMethod(sampleInfo.sampleInformation().analysisMethod());
sample.setSampleOrigin(SampleOrigin.create(sampleInfo.sampleInformation().species(),
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
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
Loading

0 comments on commit 004124e

Please sign in to comment.