Compare commits

...

2 Commits

7 changed files with 89 additions and 22 deletions

View File

@ -13,10 +13,9 @@ import org.opencdmp.authorization.Permission;
import org.opencdmp.commons.enums.DescriptionStatus; import org.opencdmp.commons.enums.DescriptionStatus;
import org.opencdmp.commons.enums.IsActive; import org.opencdmp.commons.enums.IsActive;
import org.opencdmp.commons.scope.user.UserScope; import org.opencdmp.commons.scope.user.UserScope;
import org.opencdmp.data.DescriptionEntity; import org.opencdmp.data.*;
import org.opencdmp.data.DmpDescriptionTemplateEntity; import org.opencdmp.elastic.data.nested.NestedTagElasticEntity;
import org.opencdmp.data.DmpEntity; import org.opencdmp.elastic.elasticbuilder.nested.NestedTagElasticBuilder;
import org.opencdmp.data.TenantEntityManager;
import org.opencdmp.model.PublicDescription; import org.opencdmp.model.PublicDescription;
import org.opencdmp.model.description.Description; import org.opencdmp.model.description.Description;
import org.opencdmp.query.utils.QueryUtilsService; import org.opencdmp.query.utils.QueryUtilsService;
@ -26,6 +25,7 @@ import org.springframework.stereotype.Component;
import java.time.Instant; import java.time.Instant;
import java.util.*; import java.util.*;
import java.util.stream.Collectors;
@Component @Component
@Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE) @Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)
@ -41,6 +41,8 @@ public class DescriptionQuery extends QueryBase<DescriptionEntity> {
private DmpQuery dmpQuery; private DmpQuery dmpQuery;
private DescriptionReferenceQuery descriptionReferenceQuery;
private Instant createdAfter; private Instant createdAfter;
private Instant createdBefore; private Instant createdBefore;
@ -155,6 +157,11 @@ public class DescriptionQuery extends QueryBase<DescriptionEntity> {
return this; return this;
} }
public DescriptionQuery descriptionReferenceSubQuery(DescriptionReferenceQuery subQuery) {
this.descriptionReferenceQuery = subQuery;
return this;
}
public DescriptionQuery excludedIds(Collection<UUID> values) { public DescriptionQuery excludedIds(Collection<UUID> values) {
this.excludedIds = values; this.excludedIds = values;
return this; return this;
@ -334,6 +341,10 @@ public class DescriptionQuery extends QueryBase<DescriptionEntity> {
QueryContext<DmpEntity, UUID> subQuery = this.applySubQuery(this.dmpQuery, queryContext, UUID.class, dmpEntityRoot -> dmpEntityRoot.get(DmpEntity._id)); QueryContext<DmpEntity, UUID> subQuery = this.applySubQuery(this.dmpQuery, queryContext, UUID.class, dmpEntityRoot -> dmpEntityRoot.get(DmpEntity._id));
predicates.add(queryContext.CriteriaBuilder.in(queryContext.Root.get(DescriptionEntity._dmpId)).value(subQuery.Query)); predicates.add(queryContext.CriteriaBuilder.in(queryContext.Root.get(DescriptionEntity._dmpId)).value(subQuery.Query));
} }
if (this.descriptionReferenceQuery != null) {
QueryContext<DescriptionReferenceEntity, UUID> subQuery = this.applySubQuery(this.descriptionReferenceQuery, queryContext, UUID.class, descriptionReferenceEntityRoot -> descriptionReferenceEntityRoot.get(DescriptionReferenceEntity._descriptionId));
predicates.add(queryContext.CriteriaBuilder.in(queryContext.Root.get(DescriptionEntity._id)).value(subQuery.Query));
}
if (this.dmpDescriptionTemplateIds != null) { if (this.dmpDescriptionTemplateIds != null) {
CriteriaBuilder.In<UUID> inClause = queryContext.CriteriaBuilder.in(queryContext.Root.get(DescriptionEntity._dmpDescriptionTemplateId)); CriteriaBuilder.In<UUID> inClause = queryContext.CriteriaBuilder.in(queryContext.Root.get(DescriptionEntity._dmpDescriptionTemplateId));
for (UUID item : this.dmpDescriptionTemplateIds) for (UUID item : this.dmpDescriptionTemplateIds)

View File

@ -6,6 +6,7 @@ import org.apache.commons.lang3.StringUtils;
import org.opencdmp.commons.enums.DescriptionStatus; import org.opencdmp.commons.enums.DescriptionStatus;
import org.opencdmp.commons.enums.IsActive; import org.opencdmp.commons.enums.IsActive;
import org.opencdmp.elastic.query.DescriptionElasticQuery; import org.opencdmp.elastic.query.DescriptionElasticQuery;
import org.opencdmp.model.reference.Reference;
import org.opencdmp.query.DescriptionQuery; import org.opencdmp.query.DescriptionQuery;
import java.time.Instant; import java.time.Instant;
@ -25,7 +26,8 @@ public class DescriptionLookup extends Lookup {
private Instant finalizedBefore; private Instant finalizedBefore;
private DmpLookup dmpSubQuery; private DmpLookup dmpSubQuery;
private DescriptionReferenceLookup descriptionReferenceSubQuery;
private List<IsActive> isActive; private List<IsActive> isActive;
private List<DescriptionStatus> statuses; private List<DescriptionStatus> statuses;
@ -78,6 +80,10 @@ public class DescriptionLookup extends Lookup {
this.dmpSubQuery = dmpSubQuery; this.dmpSubQuery = dmpSubQuery;
} }
public DescriptionReferenceLookup getDescriptionReferenceSubQuery() { return this.descriptionReferenceSubQuery; }
public void setDescriptionReferenceSubQuery(DescriptionReferenceLookup descriptionReferenceSubQuery) { this.descriptionReferenceSubQuery = descriptionReferenceSubQuery; }
public Instant getCreatedAfter() { public Instant getCreatedAfter() {
return this.createdAfter; return this.createdAfter;
} }
@ -116,6 +122,7 @@ public class DescriptionLookup extends Lookup {
if (this.ids != null) query.ids(this.ids); if (this.ids != null) query.ids(this.ids);
if (this.excludedIds != null) query.excludedIds(this.excludedIds); if (this.excludedIds != null) query.excludedIds(this.excludedIds);
if (this.dmpSubQuery != null) query.dmpSubQuery(this.dmpSubQuery.enrich(queryFactory)); if (this.dmpSubQuery != null) query.dmpSubQuery(this.dmpSubQuery.enrich(queryFactory));
if (this.descriptionReferenceSubQuery != null) query.descriptionReferenceSubQuery(this.descriptionReferenceSubQuery.enrich(queryFactory));
if (this.isActive != null) query.isActive(this.isActive); if (this.isActive != null) query.isActive(this.isActive);
if (this.statuses != null) query.statuses(this.statuses); if (this.statuses != null) query.statuses(this.statuses);
if (this.createdAfter != null) query.createdAfter(this.createdAfter); if (this.createdAfter != null) query.createdAfter(this.createdAfter);
@ -139,7 +146,7 @@ public class DescriptionLookup extends Lookup {
if (this.finalizedAfter != null) query.finalizedAfter(this.finalizedAfter); if (this.finalizedAfter != null) query.finalizedAfter(this.finalizedAfter);
if (this.finalizedBefore != null) query.finalizedBefore(this.finalizedBefore); if (this.finalizedBefore != null) query.finalizedBefore(this.finalizedBefore);
if (this.dmpSubQuery != null) query.dmpSubQuery(this.dmpSubQuery.enrichElasticInner(queryFactory)); if (this.dmpSubQuery != null) query.dmpSubQuery(this.dmpSubQuery.enrichElasticInner(queryFactory));
// TODO: add reference ?
this.enrichCommon(query); this.enrichCommon(query);
return query; return query;

View File

@ -8,6 +8,8 @@ import { DescriptionTag } from '../model/description/description';
import { UntypedFormBuilder, UntypedFormControl, UntypedFormGroup } from '@angular/forms'; import { UntypedFormBuilder, UntypedFormControl, UntypedFormGroup } from '@angular/forms';
import { ReferenceType } from '../model/reference-type/reference-type'; import { ReferenceType } from '../model/reference-type/reference-type';
import { Reference } from '../model/reference/reference'; import { Reference } from '../model/reference/reference';
import { ReferenceTypeLookup } from './reference-type.lookup';
import { DescriptionReferenceLookup, ReferenceLookup } from './reference.lookup';
export class DescriptionLookup extends Lookup implements DescriptionFilter { export class DescriptionLookup extends Lookup implements DescriptionFilter {
ids: Guid[]; ids: Guid[];
@ -26,7 +28,7 @@ export class DescriptionLookup extends Lookup implements DescriptionFilter {
associatedDmpIds: Guid[]; //TODO associatedDmpIds: Guid[]; //TODO
roleInDmp: DmpUserRole[]; //TODO roleInDmp: DmpUserRole[]; //TODO
tags: DescriptionTag[]; //TODO tags: DescriptionTag[]; //TODO
references: ReferenceAndTypeLookup[]; //TODO descriptionReferenceSubQuery: DescriptionReferenceLookup;
constructor() { constructor() {
super(); super();
@ -49,10 +51,13 @@ export interface DescriptionFilter {
associatedDmpIds: Guid[]; associatedDmpIds: Guid[];
roleInDmp: DmpUserRole[]; roleInDmp: DmpUserRole[];
tags: DescriptionTag[]; tags: DescriptionTag[];
references: ReferenceAndTypeLookup[]; descriptionReferenceSubQuery: DescriptionReferenceLookup;
} }
export interface ReferenceAndTypeLookup { export class ReferencesWithType {
referenceType: ReferenceType; referenceType: ReferenceType;
references: Reference[]; references: Reference[];
constructor() {
}
} }

View File

@ -15,6 +15,16 @@ export class ReferenceLookup extends Lookup implements ReferenceFilter {
super(); super();
} }
} }
export class DescriptionReferenceLookup extends Lookup {
referenceIds: Guid[];
excludedIds: Guid[];
like: string;
isActive: IsActive[];
constructor() {
super();
}
}
export interface ReferenceFilter { export interface ReferenceFilter {
ids: Guid[]; ids: Guid[];

View File

@ -11,7 +11,7 @@ import { QueryResult } from '@common/model/query-result';
import { FilterService } from '@common/modules/text-filter/filter-service'; import { FilterService } from '@common/modules/text-filter/filter-service';
import { Guid } from '@common/types/guid'; import { Guid } from '@common/types/guid';
import { Observable, throwError } from 'rxjs'; import { Observable, throwError } from 'rxjs';
import { catchError, map } from 'rxjs/operators'; import { catchError, filter, map } from 'rxjs/operators';
import { nameof } from 'ts-simple-nameof'; import { nameof } from 'ts-simple-nameof';
import { ConfigurationService } from '../configuration/configuration.service'; import { ConfigurationService } from '../configuration/configuration.service';
import { BaseHttpV2Service } from '../http/base-http-v2.service'; import { BaseHttpV2Service } from '../http/base-http-v2.service';
@ -140,8 +140,20 @@ export class ReferenceService {
public getMultipleAutoCompleteSearchConfiguration(typeId: Guid, dependencyReferences: Reference[]): MultipleAutoCompleteConfiguration { public getMultipleAutoCompleteSearchConfiguration(typeId: Guid, dependencyReferences: Reference[]): MultipleAutoCompleteConfiguration {
return { return {
initialItems: (excludedItems: any[], data?: any) => this.searchWithDefinition(this.buildAutocompleteSearchLookup(typeId, dependencyReferences, null)).pipe(map(x => x)), initialItems: (excludedItems: any[], data?: any) => this.searchWithDefinition(this.buildAutocompleteSearchLookup(typeId, dependencyReferences, null)).pipe(map(x => x.filter(r => r.id))).pipe(map(x => x)),
filterFn: (searchQuery: string, excludedItems: any[]) => this.searchWithDefinition(this.buildAutocompleteSearchLookup(typeId, dependencyReferences, searchQuery)).pipe(map(x => x)), filterFn: (searchQuery: string, excludedItems: any[]) => this.searchWithDefinition(this.buildAutocompleteSearchLookup(typeId, dependencyReferences, searchQuery)).pipe(map(x => x.filter(r => r.id))).pipe(map(x => x)),
displayFn: (item: Reference) => item.label,
titleFn: (item: Reference) => item.label,
subtitleFn: (item: Reference) => item?.sourceType === ReferenceSourceType.External ? this.language.instant('REFERENCE-FIELD-COMPONENT.EXTERNAL-SOURCE') + ': ' + item.source : this.language.instant('REFERENCE-FIELD-COMPONENT.INTERNAL-SOURCE'),
valueAssign: (item: Reference) => item,
uniqueAssign: (item: Reference) => item.source + '_' + item.reference,
};
}
public getInternalMultipleAutoCompleteConfiguration(typeId: Guid, dependencyReferences: Reference[]): MultipleAutoCompleteConfiguration {
return {
initialItems: (excludedItems: any[], data?: any) => this.searchWithDefinition(this.buildAutocompleteSearchLookup(typeId, dependencyReferences, null)).pipe(map(x => x.filter(r => r.sourceType == ReferenceSourceType.Internal))).pipe(map(x => x)),
filterFn: (searchQuery: string, excludedItems: any[]) => this.searchWithDefinition(this.buildAutocompleteSearchLookup(typeId, dependencyReferences, searchQuery)).pipe(map(x => x.filter(r => r.sourceType == ReferenceSourceType.Internal))).pipe(map(x => x)),
displayFn: (item: Reference) => item.label, displayFn: (item: Reference) => item.label,
titleFn: (item: Reference) => item.label, titleFn: (item: Reference) => item.label,
subtitleFn: (item: Reference) => item?.sourceType === ReferenceSourceType.External ? this.language.instant('REFERENCE-FIELD-COMPONENT.EXTERNAL-SOURCE') + ': ' + item.source : this.language.instant('REFERENCE-FIELD-COMPONENT.INTERNAL-SOURCE'), subtitleFn: (item: Reference) => item?.sourceType === ReferenceSourceType.External ? this.language.instant('REFERENCE-FIELD-COMPONENT.EXTERNAL-SOURCE') + ': ' + item.source : this.language.instant('REFERENCE-FIELD-COMPONENT.INTERNAL-SOURCE'),

View File

@ -8,13 +8,13 @@ import { IsActive } from '@app/core/common/enum/is-active.enum';
import { AppPermission } from '@app/core/common/enum/permission.enum'; import { AppPermission } from '@app/core/common/enum/permission.enum';
import { RecentActivityOrder } from '@app/core/common/enum/recent-activity-order'; import { RecentActivityOrder } from '@app/core/common/enum/recent-activity-order';
import { DescriptionTemplate } from '@app/core/model/description-template/description-template'; import { DescriptionTemplate } from '@app/core/model/description-template/description-template';
import { BaseDescription, Description } from '@app/core/model/description/description'; import { BaseDescription, Description, DescriptionReference } from '@app/core/model/description/description';
import { DmpBlueprint, DmpBlueprintDefinition, DmpBlueprintDefinitionSection } from '@app/core/model/dmp-blueprint/dmp-blueprint'; import { DmpBlueprint, DmpBlueprintDefinition, DmpBlueprintDefinitionSection } from '@app/core/model/dmp-blueprint/dmp-blueprint';
import { Dmp, DmpDescriptionTemplate, DmpUser } from '@app/core/model/dmp/dmp'; import { Dmp, DmpDescriptionTemplate, DmpUser } from '@app/core/model/dmp/dmp';
import { DmpReference } from '@app/core/model/dmp/dmp-reference'; import { DmpReference } from '@app/core/model/dmp/dmp-reference';
import { ReferenceType } from '@app/core/model/reference-type/reference-type'; import { ReferenceType } from '@app/core/model/reference-type/reference-type';
import { Reference } from '@app/core/model/reference/reference'; import { Reference } from '@app/core/model/reference/reference';
import { DescriptionLookup } from '@app/core/query/description.lookup'; import { DescriptionLookup, ReferencesWithType } from '@app/core/query/description.lookup';
import { AuthService } from '@app/core/services/auth/auth.service'; import { AuthService } from '@app/core/services/auth/auth.service';
import { DescriptionService } from '@app/core/services/description/description.service'; import { DescriptionService } from '@app/core/services/description/description.service';
import { AnalyticsService } from '@app/core/services/matomo/analytics-service'; import { AnalyticsService } from '@app/core/services/matomo/analytics-service';
@ -35,6 +35,8 @@ import { QueryResult } from '@common/model/query-result';
import { Observable } from 'rxjs'; import { Observable } from 'rxjs';
import { QueryParamsService } from '@app/core/services/utilities/query-params.service'; import { QueryParamsService } from '@app/core/services/utilities/query-params.service';
import { UiNotificationService } from '@app/core/services/notification/ui-notification-service'; import { UiNotificationService } from '@app/core/services/notification/ui-notification-service';
import { Guid } from '@common/types/guid';
import { DescriptionReferenceLookup } from '@app/core/query/reference.lookup';
@Component({ @Component({
selector: 'app-description-listing-component', selector: 'app-description-listing-component',
@ -62,6 +64,7 @@ export class DescriptionListingComponent extends BaseListingComponent<BaseDescri
protected ITEMS_PER_PAGE = 5; protected ITEMS_PER_PAGE = 5;
pageSize: number = 5; pageSize: number = 5;
lookup: DescriptionLookup; lookup: DescriptionLookup;
referenceFilters: ReferencesWithType[];
public formGroup = new UntypedFormBuilder().group({ public formGroup = new UntypedFormBuilder().group({
like: new UntypedFormControl(), like: new UntypedFormControl(),
order: new UntypedFormControl() order: new UntypedFormControl()
@ -166,6 +169,7 @@ export class DescriptionListingComponent extends BaseListingComponent<BaseDescri
})); }));
} }
} }
protected initializeLookup(): DescriptionLookup { protected initializeLookup(): DescriptionLookup {
const lookup = new DescriptionLookup(); const lookup = new DescriptionLookup();
lookup.metadata = { countAll: true }; lookup.metadata = { countAll: true };
@ -184,6 +188,19 @@ export class DescriptionListingComponent extends BaseListingComponent<BaseDescri
return lookup; return lookup;
} }
protected initializeReferenceLookup(): DescriptionReferenceLookup {
const lookup = new DescriptionReferenceLookup();
lookup.metadata = { countAll: true };
lookup.isActive = [IsActive.Active];
lookup.project = {
fields: [
[nameof<DescriptionReference>(x => x.reference), nameof<Reference>(x => x.id)].join('.'),
]
};
return lookup;
}
protected setupColumns() { protected setupColumns() {
} }
@ -236,7 +253,6 @@ export class DescriptionListingComponent extends BaseListingComponent<BaseDescri
} }
openFiltersDialog(): void { openFiltersDialog(): void {
//TODO: Add filters dialog
const dialogRef = this.dialog.open(DescriptionFilterDialogComponent, { const dialogRef = this.dialog.open(DescriptionFilterDialogComponent, {
width: '456px', width: '456px',
height: '100%', height: '100%',
@ -246,7 +262,7 @@ export class DescriptionListingComponent extends BaseListingComponent<BaseDescri
panelClass: 'dialog-side-panel', panelClass: 'dialog-side-panel',
data: { data: {
isPublic: this.isPublic ?? true, isPublic: this.isPublic ?? true,
filterForm: this._buildFormFromLookup(this.lookup), filterForm: this._buildFormFromLookup(this.lookup, this.referenceFilters),
} }
}); });
@ -258,10 +274,9 @@ export class DescriptionListingComponent extends BaseListingComponent<BaseDescri
} }
updateDataFn(filterForm: UntypedFormGroup): void { updateDataFn(filterForm: UntypedFormGroup): void {
this.referenceFilters = this._patchReferenceFiltersFromForm(filterForm);
this.lookup = this._patchLookupFromForm(this.lookup, filterForm); this.lookup = this._patchLookupFromForm(this.lookup, filterForm);
this.filterChanged(this.lookup) this.filterChanged(this.lookup)
// this.lookup.from(filterForm);
// this.refresh(this.lookup);
} }
hasScrollbar(): boolean { hasScrollbar(): boolean {
@ -367,15 +382,22 @@ export class DescriptionListingComponent extends BaseListingComponent<BaseDescri
lookup.tags = formGroup.get("tags")?.value ?? null; lookup.tags = formGroup.get("tags")?.value ?? null;
lookup.associatedDmpIds = formGroup.get("associatedDmpIds")?.value ?? null; lookup.associatedDmpIds = formGroup.get("associatedDmpIds")?.value ?? null;
lookup.descriptionTemplateIds = formGroup.get("descriptionTemplates")?.value ?? null; lookup.descriptionTemplateIds = formGroup.get("descriptionTemplates")?.value ?? null;
lookup.references = formGroup.get("references")?.value?.filter(reference => reference.referenceType != null && reference.references?.length > 0) ?? null; lookup.descriptionReferenceSubQuery = this.initializeReferenceLookup();
lookup.descriptionReferenceSubQuery.referenceIds = formGroup.get("references")?.value
?.filter((reference: ReferencesWithType) => reference.referenceType != null && reference.references?.length > 0)
?.flatMap((referencesWithType: ReferencesWithType) => referencesWithType.references?.map(reference => reference.id)) as Guid[];
return lookup; return lookup;
} }
_patchReferenceFiltersFromForm(formGroup: UntypedFormGroup): ReferencesWithType[] {
return formGroup?.get("references")?.value?.filter(reference => reference.referenceType != null && reference.references?.length > 0) ?? null;
}
_buildFormFromLookup(lookup: DescriptionLookup): UntypedFormGroup { _buildFormFromLookup(lookup: DescriptionLookup, referenceFilters: ReferencesWithType[]): UntypedFormGroup {
const formArray = this.formBuilder.array([]) as UntypedFormArray; const formArray = this.formBuilder.array([]) as UntypedFormArray;
lookup.references?.forEach(reference => { referenceFilters?.forEach(reference => {
let referenceForm = this.formBuilder.group({ let referenceForm = this.formBuilder.group({
referenceType: reference.referenceType, referenceType: reference.referenceType,

View File

@ -167,7 +167,7 @@ export class DescriptionFilterComponent extends BaseCriteriaComponent implements
}; };
getReferenceAutocompleteConfiguration(referenceTypeId: Guid, excludedIds: Reference[]): MultipleAutoCompleteConfiguration { getReferenceAutocompleteConfiguration(referenceTypeId: Guid, excludedIds: Reference[]): MultipleAutoCompleteConfiguration {
let autocomplete = this.referenceService.getMultipleAutoCompleteSearchConfiguration(referenceTypeId, excludedIds); let autocomplete = this.referenceService.getInternalMultipleAutoCompleteConfiguration(referenceTypeId, excludedIds);
return autocomplete; return autocomplete;
}; };