Skip to content

Commit bc35bfb

Browse files
111731: Refactored SearchFacetFilterWrapperComponent to extend AbstractComponentLoaderComponent
1 parent f8759c5 commit bc35bfb

9 files changed

Lines changed: 73 additions & 131 deletions

File tree

src/app/core/shared/search/search-filter.service.ts

Lines changed: 1 addition & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,4 @@
1-
import {
2-
Injectable,
3-
InjectionToken,
4-
} from '@angular/core';
1+
import { Injectable } from '@angular/core';
52
import { Params } from '@angular/router';
63
import {
74
createSelector,
@@ -10,7 +7,6 @@ import {
107
Store,
118
} from '@ngrx/store';
129
import {
13-
BehaviorSubject,
1410
combineLatest as observableCombineLatest,
1511
Observable,
1612
of as observableOf,
@@ -60,11 +56,6 @@ import { SearchService } from './search.service';
6056

6157
const filterStateSelector = (state: SearchFiltersState) => state.searchFilter;
6258

63-
export const FILTER_CONFIG: InjectionToken<SearchFilterConfig> = new InjectionToken<SearchFilterConfig>('filterConfig');
64-
export const IN_PLACE_SEARCH: InjectionToken<boolean> = new InjectionToken<boolean>('inPlaceSearch');
65-
export const REFRESH_FILTER: InjectionToken<BehaviorSubject<any>> = new InjectionToken<boolean>('refreshFilters');
66-
export const SCOPE: InjectionToken<string> = new InjectionToken<string>('scope');
67-
6859
/**
6960
* Service that performs all actions that have to do with search filters and facets
7061
*/

src/app/shared/search/search-filters/search-filter/search-facet-filter-wrapper/search-facet-filter-wrapper.component.html

Lines changed: 0 additions & 1 deletion
This file was deleted.
Lines changed: 20 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -1,35 +1,29 @@
1-
import { NgComponentOutlet } from '@angular/common';
21
import {
32
Component,
4-
Injector,
53
Input,
6-
OnInit,
74
} from '@angular/core';
85
import { BehaviorSubject } from 'rxjs';
96

107
import { GenericConstructor } from '../../../../../core/shared/generic-constructor';
11-
import {
12-
FILTER_CONFIG,
13-
IN_PLACE_SEARCH,
14-
REFRESH_FILTER,
15-
SCOPE,
16-
} from '../../../../../core/shared/search/search-filter.service';
17-
import { FilterType } from '../../../models/filter-type.model';
8+
import { AbstractComponentLoaderComponent } from '../../../../abstract-component-loader/abstract-component-loader.component';
9+
import { DynamicComponentLoaderDirective } from '../../../../abstract-component-loader/dynamic-component-loader.directive';
1810
import { SearchFilterConfig } from '../../../models/search-filter-config.model';
19-
import { SearchFacetFilterComponent } from '../search-facet-filter/search-facet-filter.component';
2011
import { renderFilterType } from '../search-filter-type-decorator';
2112

2213
@Component({
2314
selector: 'ds-search-facet-filter-wrapper',
24-
templateUrl: './search-facet-filter-wrapper.component.html',
15+
templateUrl: '../../../../abstract-component-loader/abstract-component-loader.component.html',
2516
standalone: true,
26-
imports: [NgComponentOutlet],
17+
imports: [
18+
DynamicComponentLoaderDirective,
19+
],
2720
})
2821

2922
/**
3023
* Wrapper component that renders a specific facet filter based on the filter config's type
3124
*/
32-
export class SearchFacetFilterWrapperComponent implements OnInit {
25+
export class SearchFacetFilterWrapperComponent extends AbstractComponentLoaderComponent<Component> {
26+
3327
/**
3428
* Configuration for the filter of this wrapper component
3529
*/
@@ -38,7 +32,7 @@ export class SearchFacetFilterWrapperComponent implements OnInit {
3832
/**
3933
* True when the search component should show results on the current page
4034
*/
41-
@Input() inPlaceSearch;
35+
@Input() inPlaceSearch: boolean;
4236

4337
/**
4438
* Emits when the search filters values may be stale, and so they must be refreshed.
@@ -50,39 +44,19 @@ export class SearchFacetFilterWrapperComponent implements OnInit {
5044
*/
5145
@Input() scope: string;
5246

53-
/**
54-
* The constructor of the search facet filter that should be rendered, based on the filter config's type
55-
*/
56-
searchFilter: GenericConstructor<SearchFacetFilterComponent>;
57-
/**
58-
* Injector to inject a child component with the @Input parameters
59-
*/
60-
objectInjector: Injector;
47+
inputNamesDependentForComponent: (keyof SearchFacetFilterWrapperComponent & string)[] = [
48+
'filterConfig',
49+
];
6150

62-
constructor(private injector: Injector) {
63-
}
51+
inputNames: (keyof SearchFacetFilterWrapperComponent & string)[] = [
52+
'filterConfig',
53+
'inPlaceSearch',
54+
'refreshFilters',
55+
'scope',
56+
];
6457

65-
/**
66-
* Initialize and add the filter config to the injector
67-
*/
68-
ngOnInit(): void {
69-
this.searchFilter = this.getSearchFilter();
70-
this.objectInjector = Injector.create({
71-
providers: [
72-
{ provide: FILTER_CONFIG, useFactory: () => (this.filterConfig), deps: [] },
73-
{ provide: IN_PLACE_SEARCH, useFactory: () => (this.inPlaceSearch), deps: [] },
74-
{ provide: REFRESH_FILTER, useFactory: () => (this.refreshFilters), deps: [] },
75-
{ provide: SCOPE, useFactory: () => (this.scope), deps: [] },
76-
],
77-
parent: this.injector,
78-
});
58+
public getComponent(): GenericConstructor<Component> {
59+
return renderFilterType(this.filterConfig.filterType);
7960
}
8061

81-
/**
82-
* Find the correct component based on the filter config's type
83-
*/
84-
private getSearchFilter() {
85-
const type: FilterType = this.filterConfig.filterType;
86-
return renderFilterType(type);
87-
}
8862
}

src/app/shared/search/search-filters/search-filter/search-facet-filter/search-facet-filter.component.spec.ts

Lines changed: 3 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -18,13 +18,7 @@ import {
1818

1919
import { RemoteDataBuildService } from '../../../../../core/cache/builders/remote-data-build.service';
2020
import { SearchService } from '../../../../../core/shared/search/search.service';
21-
import {
22-
FILTER_CONFIG,
23-
IN_PLACE_SEARCH,
24-
REFRESH_FILTER,
25-
SCOPE,
26-
SearchFilterService,
27-
} from '../../../../../core/shared/search/search-filter.service';
21+
import { SearchFilterService } from '../../../../../core/shared/search/search-filter.service';
2822
import { SEARCH_CONFIG_SERVICE } from '../../../../../my-dspace-page/my-dspace-configuration.service';
2923
import { createSuccessfulRemoteDataObject$ } from '../../../../remote-data.utils';
3024
import { RouterStub } from '../../../../testing/router.stub';
@@ -93,12 +87,8 @@ describe('SearchFacetFilterComponent', () => {
9387
{ provide: SearchService, useValue: searchService },
9488
{ provide: SearchFilterService, useValue: filterService },
9589
{ provide: Router, useValue: router },
96-
{ provide: FILTER_CONFIG, useValue: new SearchFilterConfig() },
9790
{ provide: RemoteDataBuildService, useValue: { aggregate: () => observableOf({}) } },
9891
{ provide: SEARCH_CONFIG_SERVICE, useValue: searchConfigService },
99-
{ provide: IN_PLACE_SEARCH, useValue: false },
100-
{ provide: REFRESH_FILTER, useValue: new BehaviorSubject<boolean>(false) },
101-
{ provide: SCOPE, useValue: undefined },
10292
],
10393
schemas: [NO_ERRORS_SCHEMA],
10494
}).overrideComponent(SearchFacetFilterComponent, {
@@ -110,6 +100,8 @@ describe('SearchFacetFilterComponent', () => {
110100
fixture = TestBed.createComponent(SearchFacetFilterComponent);
111101
comp = fixture.componentInstance; // SearchPageComponent test instance
112102
comp.filterConfig = mockFilterConfig;
103+
comp.inPlaceSearch = false;
104+
comp.refreshFilters = new BehaviorSubject<boolean>(false);
113105
spyOn(searchService, 'getFacetValuesFor').and.returnValue(createSuccessfulRemoteDataObject$(values));
114106
fixture.detectChanges();
115107
});

src/app/shared/search/search-filters/search-filter/search-facet-filter/search-facet-filter.component.ts

Lines changed: 23 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import {
88
import {
99
Component,
1010
Inject,
11+
Input,
1112
OnDestroy,
1213
OnInit,
1314
} from '@angular/core';
@@ -37,13 +38,7 @@ import { RemoteDataBuildService } from '../../../../../core/cache/builders/remot
3738
import { getFirstSucceededRemoteDataPayload } from '../../../../../core/shared/operators';
3839
import { SearchService } from '../../../../../core/shared/search/search.service';
3940
import { SearchConfigurationService } from '../../../../../core/shared/search/search-configuration.service';
40-
import {
41-
FILTER_CONFIG,
42-
IN_PLACE_SEARCH,
43-
REFRESH_FILTER,
44-
SCOPE,
45-
SearchFilterService,
46-
} from '../../../../../core/shared/search/search-filter.service';
41+
import { SearchFilterService } from '../../../../../core/shared/search/search-filter.service';
4742
import { SEARCH_CONFIG_SERVICE } from '../../../../../my-dspace-page/my-dspace-configuration.service';
4843
import {
4944
hasNoValue,
@@ -68,6 +63,27 @@ import { stripOperatorFromFilterValue } from '../../../search.utils';
6863
* Super class for all different representations of facets
6964
*/
7065
export class SearchFacetFilterComponent implements OnInit, OnDestroy {
66+
67+
/**
68+
* Configuration for the filter of this wrapper component
69+
*/
70+
@Input() filterConfig: SearchFilterConfig;
71+
72+
/**
73+
* True when the search component should show results on the current page
74+
*/
75+
@Input() inPlaceSearch: boolean;
76+
77+
/**
78+
* Emits when the search filters values may be stale, and so they must be refreshed.
79+
*/
80+
@Input() refreshFilters: BehaviorSubject<boolean>;
81+
82+
/**
83+
* The current scope
84+
*/
85+
@Input() scope: string;
86+
7187
/**
7288
* Emits an array of pages with values found for this facet
7389
*/
@@ -125,10 +141,6 @@ export class SearchFacetFilterComponent implements OnInit, OnDestroy {
125141
protected rdbs: RemoteDataBuildService,
126142
protected router: Router,
127143
@Inject(SEARCH_CONFIG_SERVICE) public searchConfigService: SearchConfigurationService,
128-
@Inject(IN_PLACE_SEARCH) public inPlaceSearch: boolean,
129-
@Inject(FILTER_CONFIG) public filterConfig: SearchFilterConfig,
130-
@Inject(REFRESH_FILTER) public refreshFilters: BehaviorSubject<boolean>,
131-
@Inject(SCOPE) public scope: string,
132144
) {
133145
}
134146

src/app/shared/search/search-filters/search-filter/search-hierarchy-filter/search-hierarchy-filter.component.spec.ts

Lines changed: 6 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -30,13 +30,7 @@ import { RemoteData } from '../../../../../core/data/remote-data';
3030
import { RequestEntryState } from '../../../../../core/data/request-entry-state.model';
3131
import { PageInfo } from '../../../../../core/shared/page-info.model';
3232
import { SearchService } from '../../../../../core/shared/search/search.service';
33-
import {
34-
FILTER_CONFIG,
35-
IN_PLACE_SEARCH,
36-
REFRESH_FILTER,
37-
SCOPE,
38-
SearchFilterService,
39-
} from '../../../../../core/shared/search/search-filter.service';
33+
import { SearchFilterService } from '../../../../../core/shared/search/search-filter.service';
4034
import { VocabularyEntryDetail } from '../../../../../core/submission/vocabularies/models/vocabulary-entry-detail.model';
4135
import { VocabularyService } from '../../../../../core/submission/vocabularies/vocabulary.service';
4236
import { SEARCH_CONFIG_SERVICE } from '../../../../../my-dspace-page/my-dspace-configuration.service';
@@ -46,7 +40,7 @@ import { SearchFilterConfig } from '../../../models/search-filter-config.model';
4640
import { SearchHierarchyFilterComponent } from './search-hierarchy-filter.component';
4741

4842
describe('SearchHierarchyFilterComponent', () => {
49-
43+
let comp: SearchHierarchyFilterComponent;
5044
let fixture: ComponentFixture<SearchHierarchyFilterComponent>;
5145
let showVocabularyTreeLink: DebugElement;
5246

@@ -97,17 +91,17 @@ describe('SearchHierarchyFilterComponent', () => {
9791
{ provide: VocabularyService, useValue: vocabularyService },
9892
{ provide: APP_CONFIG, useValue: environment },
9993
{ provide: SEARCH_CONFIG_SERVICE, useValue: searchConfigService },
100-
{ provide: IN_PLACE_SEARCH, useValue: false },
101-
{ provide: FILTER_CONFIG, useValue: Object.assign(new SearchFilterConfig(), { name: testSearchFilter }) },
102-
{ provide: REFRESH_FILTER, useValue: new BehaviorSubject<boolean>(false) },
103-
{ provide: SCOPE, useValue: undefined },
10494
],
10595
schemas: [CUSTOM_ELEMENTS_SCHEMA],
10696
}).compileComponents();
10797
});
10898

10999
function init() {
110100
fixture = TestBed.createComponent(SearchHierarchyFilterComponent);
101+
comp = fixture.componentInstance;
102+
comp.inPlaceSearch = false;
103+
comp.filterConfig = Object.assign(new SearchFilterConfig(), { name: testSearchFilter });
104+
comp.refreshFilters = new BehaviorSubject<boolean>(false);
111105
fixture.detectChanges();
112106
showVocabularyTreeLink = fixture.debugElement.query(By.css(`a#show-${testSearchFilter}-tree`));
113107
}

src/app/shared/search/search-filters/search-filter/search-hierarchy-filter/search-hierarchy-filter.component.ts

Lines changed: 8 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,6 @@ import {
2121
} from '@ng-bootstrap/ng-bootstrap';
2222
import { TranslateModule } from '@ngx-translate/core';
2323
import {
24-
BehaviorSubject,
2524
from,
2625
Observable,
2726
} from 'rxjs';
@@ -41,20 +40,13 @@ import { RemoteDataBuildService } from '../../../../../core/cache/builders/remot
4140
import { PageInfo } from '../../../../../core/shared/page-info.model';
4241
import { SearchService } from '../../../../../core/shared/search/search.service';
4342
import { SearchConfigurationService } from '../../../../../core/shared/search/search-configuration.service';
44-
import {
45-
FILTER_CONFIG,
46-
IN_PLACE_SEARCH,
47-
REFRESH_FILTER,
48-
SCOPE,
49-
SearchFilterService,
50-
} from '../../../../../core/shared/search/search-filter.service';
43+
import { SearchFilterService } from '../../../../../core/shared/search/search-filter.service';
5144
import { VocabularyEntryDetail } from '../../../../../core/submission/vocabularies/models/vocabulary-entry-detail.model';
5245
import { VocabularyService } from '../../../../../core/submission/vocabularies/vocabulary.service';
5346
import { SEARCH_CONFIG_SERVICE } from '../../../../../my-dspace-page/my-dspace-configuration.service';
5447
import { hasValue } from '../../../../empty.util';
5548
import { VocabularyTreeviewModalComponent } from '../../../../form/vocabulary-treeview-modal/vocabulary-treeview-modal.component';
5649
import { FilterInputSuggestionsComponent } from '../../../../input-suggestions/filter-suggestions/filter-input-suggestions.component';
57-
import { SearchFilterConfig } from '../../../models/search-filter-config.model';
5850
import { addOperatorToFilterValue } from '../../../search.utils';
5951
import {
6052
facetLoad,
@@ -85,12 +77,14 @@ export class SearchHierarchyFilterComponent extends SearchFacetFilterComponent i
8577
protected vocabularyService: VocabularyService,
8678
@Inject(APP_CONFIG) protected appConfig: AppConfig,
8779
@Inject(SEARCH_CONFIG_SERVICE) public searchConfigService: SearchConfigurationService,
88-
@Inject(IN_PLACE_SEARCH) public inPlaceSearch: boolean,
89-
@Inject(FILTER_CONFIG) public filterConfig: SearchFilterConfig,
90-
@Inject(REFRESH_FILTER) public refreshFilters: BehaviorSubject<boolean>,
91-
@Inject(SCOPE) public scope: string,
9280
) {
93-
super(searchService, filterService, rdbs, router, searchConfigService, inPlaceSearch, filterConfig, refreshFilters, scope);
81+
super(
82+
searchService,
83+
filterService,
84+
rdbs,
85+
router,
86+
searchConfigService,
87+
);
9488
}
9589

9690
vocabularyExists$: Observable<boolean>;

src/app/shared/search/search-filters/search-filter/search-range-filter/search-range-filter.component.spec.ts

Lines changed: 4 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -21,13 +21,7 @@ import { buildPaginatedList } from '../../../../../core/data/paginated-list.mode
2121
import { RouteService } from '../../../../../core/services/route.service';
2222
import { PageInfo } from '../../../../../core/shared/page-info.model';
2323
import { SearchService } from '../../../../../core/shared/search/search.service';
24-
import {
25-
FILTER_CONFIG,
26-
IN_PLACE_SEARCH,
27-
REFRESH_FILTER,
28-
SCOPE,
29-
SearchFilterService,
30-
} from '../../../../../core/shared/search/search-filter.service';
24+
import { SearchFilterService } from '../../../../../core/shared/search/search-filter.service';
3125
import { SEARCH_CONFIG_SERVICE } from '../../../../../my-dspace-page/my-dspace-configuration.service';
3226
import { createSuccessfulRemoteDataObject$ } from '../../../../remote-data.utils';
3327
import { ActivatedRouteStub } from '../../../../testing/active-router.stub';
@@ -119,11 +113,7 @@ describe('SearchRangeFilterComponent', () => {
119113
{ provide: Router, useValue: router },
120114
{ provide: RouteService, useValue: routeServiceStub },
121115
{ provide: RemoteDataBuildService, useValue: { aggregate: () => observableOf({}) } },
122-
{ provide: FILTER_CONFIG, useValue: mockFilterConfig },
123116
{ provide: SEARCH_CONFIG_SERVICE, useValue: new SearchConfigurationServiceStub() },
124-
{ provide: IN_PLACE_SEARCH, useValue: false },
125-
{ provide: REFRESH_FILTER, useValue: new BehaviorSubject<boolean>(false) },
126-
{ provide: SCOPE, useValue: undefined },
127117
{ provide: ActivatedRoute, useValue: new ActivatedRouteStub() },
128118
],
129119
schemas: [CUSTOM_ELEMENTS_SCHEMA],
@@ -139,6 +129,9 @@ describe('SearchRangeFilterComponent', () => {
139129
beforeEach(() => {
140130
fixture = TestBed.createComponent(SearchRangeFilterComponent);
141131
comp = fixture.componentInstance; // SearchPageComponent test instance
132+
comp.filterConfig = mockFilterConfig;
133+
comp.inPlaceSearch = false;
134+
comp.refreshFilters = new BehaviorSubject<boolean>(false);
142135
spyOn(searchService, 'getFacetValuesFor').and.returnValue(mockValues);
143136
fixture.detectChanges();
144137
});

0 commit comments

Comments
 (0)