-
Notifications
You must be signed in to change notification settings - Fork 441
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge branch 'main' of github.com:jeffmorin/dspace-angular
- Loading branch information
Showing
26 changed files
with
391 additions
and
35 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,10 +1,19 @@ | ||
<ds-themed-home-news></ds-themed-home-news> | ||
<div class="container"> | ||
<ng-container *ngIf="(site$ | async) as site"> | ||
<ds-view-tracker [object]="site"></ds-view-tracker> | ||
</ng-container> | ||
<ds-themed-search-form [inPlaceSearch]="false" [searchPlaceholder]="'home.search-form.placeholder' | translate"></ds-themed-search-form> | ||
<ds-themed-top-level-community-list></ds-themed-top-level-community-list> | ||
<ds-recent-item-list *ngIf="recentSubmissionspageSize>0"></ds-recent-item-list> | ||
<div [ngClass]="appConfig.homePage.showDiscoverFilters ? 'container-fluid' : 'container'"> | ||
<div class="row m-5"> | ||
<div class="col-sm-3" *ngIf="appConfig.homePage.showDiscoverFilters"> | ||
<ds-configuration-search-page [sideBarWidth]="12" [showViewModes]="false" [searchEnabled]="false" | ||
[inPlaceSearch]="false" [showScopeSelector]="false"></ds-configuration-search-page> | ||
</div> | ||
<div [ngClass]="appConfig.homePage.showDiscoverFilters ? 'col-sm-9' : 'col-sm-12'"> | ||
<ng-container *ngIf="(site$ | async) as site"> | ||
<ds-view-tracker [object]="site"></ds-view-tracker> | ||
</ng-container> | ||
<ds-themed-search-form [inPlaceSearch]="false" | ||
[searchPlaceholder]="'home.search-form.placeholder' | translate"></ds-themed-search-form> | ||
<ds-themed-top-level-community-list></ds-themed-top-level-community-list> | ||
<ds-recent-item-list *ngIf="recentSubmissionspageSize>0"></ds-recent-item-list> | ||
</div> | ||
</div> | ||
</div> | ||
<ds-suggestions-popup></ds-suggestions-popup> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
51 changes: 51 additions & 0 deletions
51
src/app/shared/search/advanced-search/advanced-search.component.html
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,51 @@ | ||
<div class="facet-filter d-block mb-3 p-3" [ngClass]="{ 'focus': focusBox }" role="region"> | ||
<button (click)="toggle()" (focusin)="focusBox = true" (focusout)="focusBox = false" class="filter-name d-flex" | ||
[attr.aria-expanded]="false" | ||
[attr.aria-label]="((collapsedSearch ? 'search.filters.filter.expand' : 'search.filters.filter.collapse') | translate) + ' ' + (('search.advanced.filters.head') | translate | lowercase)" | ||
[attr.data-test]="'filter-toggle' | dsBrowserOnly"> | ||
<span class="h4 d-inline-block text-left mt-auto mb-auto"> | ||
{{'search.advanced.filters.head' | translate}} | ||
</span> | ||
<i class="filter-toggle flex-grow-1 fas p-auto" aria-hidden="true" [ngClass]="collapsedSearch ? 'fa-plus' : 'fa-minus'" | ||
[title]="(collapsedSearch ? 'search.filters.filter.expand' : 'search.filters.filter.collapse') | translate"> | ||
</i> | ||
</button> | ||
<div [@slide]="collapsedSearch ? 'collapsed' : 'expanded'" (@slide.start)="startSlide($event)" | ||
(@slide.done)="finishSlide($event)" class="search-filter-wrapper" | ||
[ngClass]="{ 'closed' : closed, 'notab': notab }"> | ||
<form [class]="'ng-invalid'" [formGroup]="advSearchForm" (ngSubmit)="onSubmit(advSearchForm.value)"> | ||
<div class="row"> | ||
<div class="col-lg-12"> | ||
<select | ||
[className]="(filter.invalid) && (filter.dirty || filter.touched) ? 'form-control is-invalid' :'form-control'" | ||
aria-label="filter" name="filter" id="filter" placeholder="select operator" | ||
formControlName="filter" required> | ||
<ng-container *ngFor="let filter of appConfig.search.advancedFilters.filter;"> | ||
<option [value]="filter"> | ||
{{'search.filters.filter.' + filter + '.text'| translate}} | ||
</option> | ||
</ng-container> | ||
</select> | ||
</div> | ||
<div class="col-lg-12 mt-1"> | ||
<select | ||
[className]="(operator.invalid) && (operator.dirty || operator.touched) ? 'form-control is-invalid' :'form-control'" | ||
aria-label="operator" name="operator" id="operator" formControlName="operator" required> | ||
<option value="equals">{{'search.filters.operator.equals.text'| translate}}</option> | ||
<option value="notequals">{{'search.filters.operator.notequals.text'| translate}}</option> | ||
<option value="contains">{{'search.filters.operator.contains.text'| translate}}</option> | ||
<option value="notcontains">{{'search.filters.operator.notcontains.text'| translate}}</option> | ||
</select> | ||
</div> | ||
<div class="col-lg-12 mt-1"> | ||
<input type="text" aria-label="textsearch" class="form-control" id="textsearch" name="textsearch" | ||
formControlName="textsearch" #text [placeholder]="('filter.search.text.placeholder' | translate)" required> | ||
</div> | ||
<div class="col-lg-12 mt-1"> | ||
<button class="form-control btn w-50 float-right btn-primary" type="submit" | ||
[disabled]="advSearchForm.invalid">{{'advancesearch.form.submit'| translate}}</button> | ||
</div> | ||
</div> | ||
</form> | ||
</div> | ||
</div> |
1 change: 1 addition & 0 deletions
1
src/app/shared/search/advanced-search/advanced-search.component.scss
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
@import '../search-filters/search-filter/search-filter.component.scss'; |
74 changes: 74 additions & 0 deletions
74
src/app/shared/search/advanced-search/advanced-search.component.spec.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,74 @@ | ||
import { ComponentFixture, TestBed } from '@angular/core/testing'; | ||
import { FormBuilderService } from '../../../shared/form/builder/form-builder.service'; | ||
import { AdvancedSearchComponent } from './advanced-search.component'; | ||
import { getMockFormBuilderService } from '../../../shared/mocks/form-builder-service.mock'; | ||
import { SearchService } from '../../../core/shared/search/search.service'; | ||
import { SEARCH_CONFIG_SERVICE } from '../../../my-dspace-page/my-dspace-page.component'; | ||
import { SearchConfigurationServiceStub } from '../../testing/search-configuration-service.stub'; | ||
import { RemoteDataBuildService } from '../../../core/cache/builders/remote-data-build.service'; | ||
import { FormBuilder, FormsModule, ReactiveFormsModule } from '@angular/forms'; | ||
import { APP_CONFIG } from '../../../../config/app-config.interface'; | ||
import { environment } from '../../../../environments/environment'; | ||
import { RouterStub } from '../../testing/router.stub'; | ||
import { Router } from '@angular/router'; | ||
import { ChangeDetectionStrategy, NO_ERRORS_SCHEMA } from '@angular/core'; | ||
import { BrowserOnlyMockPipe } from '../../testing/browser-only-mock.pipe'; | ||
import { RouterTestingModule } from '@angular/router/testing'; | ||
import { TranslateModule } from '@ngx-translate/core'; | ||
import { BrowserAnimationsModule } from '@angular/platform-browser/animations'; | ||
describe('AdvancedSearchComponent', () => { | ||
let component: AdvancedSearchComponent; | ||
let fixture: ComponentFixture<AdvancedSearchComponent>; | ||
let builderService: FormBuilderService = getMockFormBuilderService(); | ||
let searchService: SearchService; | ||
let router; | ||
const searchServiceStub = { | ||
/* eslint-disable no-empty,@typescript-eslint/no-empty-function */ | ||
getClearFiltersQueryParams: () => { | ||
}, | ||
getSearchLink: () => { | ||
}, | ||
getConfigurationSearchConfig: () => { }, | ||
/* eslint-enable no-empty, @typescript-eslint/no-empty-function */ | ||
}; | ||
beforeEach(async () => { | ||
await TestBed.configureTestingModule({ | ||
declarations: [AdvancedSearchComponent, BrowserOnlyMockPipe], | ||
imports: [FormsModule, RouterTestingModule, TranslateModule.forRoot(), BrowserAnimationsModule, ReactiveFormsModule], | ||
providers: [ | ||
FormBuilder, | ||
{ provide: APP_CONFIG, useValue: environment }, | ||
{ provide: FormBuilderService, useValue: builderService }, | ||
{ provide: Router, useValue: new RouterStub() }, | ||
{ provide: SEARCH_CONFIG_SERVICE, useValue: new SearchConfigurationServiceStub() }, | ||
{ provide: RemoteDataBuildService, useValue: {} }, | ||
{ provide: SearchService, useValue: searchServiceStub }, | ||
], | ||
schemas: [NO_ERRORS_SCHEMA] | ||
}).overrideComponent(AdvancedSearchComponent, { | ||
set: { changeDetection: ChangeDetectionStrategy.Default } | ||
}).compileComponents(); | ||
}); | ||
|
||
beforeEach(() => { | ||
fixture = TestBed.createComponent(AdvancedSearchComponent); | ||
component = fixture.componentInstance; | ||
router = TestBed.inject(Router); | ||
fixture.detectChanges(); | ||
}); | ||
describe('when the getSearchLink method is called', () => { | ||
const data = { filter: 'title', textsearch: 'demo', operator: 'equals' }; | ||
it('should call navigate on the router with the right searchlink and parameters when the filter is provided with a valid operator', () => { | ||
component.advSearchForm.get('textsearch').patchValue('1'); | ||
component.advSearchForm.get('filter').patchValue('1'); | ||
component.advSearchForm.get('operator').patchValue('1'); | ||
|
||
component.onSubmit(data); | ||
expect(router.navigate).toHaveBeenCalledWith([undefined], { | ||
queryParams: { ['f.' + data.filter]: data.textsearch + ',' + data.operator }, | ||
queryParamsHandling: 'merge' | ||
}); | ||
|
||
}); | ||
}); | ||
}); |
115 changes: 115 additions & 0 deletions
115
src/app/shared/search/advanced-search/advanced-search.component.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,115 @@ | ||
import { Component, Inject, Input, OnInit } from '@angular/core'; | ||
import { Router } from '@angular/router'; | ||
import { slide } from '../../animations/slide'; | ||
import { FormBuilder } from '@angular/forms'; | ||
import { FormControl, FormGroup, Validators } from '@angular/forms'; | ||
import { SearchService } from '../../../core/shared/search/search.service'; | ||
import { SearchConfigurationService } from '../../../core/shared/search/search-configuration.service'; | ||
import { SEARCH_CONFIG_SERVICE } from '../../../my-dspace-page/my-dspace-page.component'; | ||
import { AppConfig, APP_CONFIG } from 'src/config/app-config.interface'; | ||
@Component({ | ||
selector: 'ds-advanced-search', | ||
templateUrl: './advanced-search.component.html', | ||
styleUrls: ['./advanced-search.component.scss'], | ||
animations: [slide], | ||
}) | ||
/** | ||
* This component represents the part of the search sidebar that contains advanced filters. | ||
*/ | ||
export class AdvancedSearchComponent implements OnInit { | ||
/** | ||
* True when the search component should show results on the current page | ||
*/ | ||
@Input() inPlaceSearch; | ||
|
||
|
||
/** | ||
* Link to the search page | ||
*/ | ||
notab: boolean; | ||
|
||
closed: boolean; | ||
collapsedSearch = false; | ||
focusBox = false; | ||
|
||
advSearchForm: FormGroup; | ||
constructor( | ||
@Inject(APP_CONFIG) protected appConfig: AppConfig, | ||
private formBuilder: FormBuilder, | ||
protected searchService: SearchService, | ||
protected router: Router, | ||
@Inject(SEARCH_CONFIG_SERVICE) public searchConfigService: SearchConfigurationService) { | ||
} | ||
|
||
ngOnInit(): void { | ||
|
||
this.advSearchForm = this.formBuilder.group({ | ||
textsearch: new FormControl('', { | ||
validators: [Validators.required], | ||
}), | ||
filter: new FormControl('title', { | ||
validators: [Validators.required], | ||
}), | ||
operator: new FormControl('equals', | ||
{ validators: [Validators.required], }), | ||
|
||
}); | ||
this.collapsedSearch = this.isCollapsed(); | ||
|
||
} | ||
|
||
get textsearch() { | ||
return this.advSearchForm.get('textsearch'); | ||
} | ||
|
||
get filter() { | ||
return this.advSearchForm.get('filter'); | ||
} | ||
|
||
get operator() { | ||
return this.advSearchForm.get('operator'); | ||
} | ||
paramName(filter) { | ||
return 'f.' + filter; | ||
} | ||
onSubmit(data) { | ||
if (this.advSearchForm.valid) { | ||
let queryParams = { [this.paramName(data.filter)]: data.textsearch + ',' + data.operator }; | ||
if (!this.inPlaceSearch) { | ||
this.router.navigate([this.searchService.getSearchLink()], { queryParams: queryParams, queryParamsHandling: 'merge' }); | ||
} else { | ||
if (!this.router.url.includes('?')) { | ||
this.router.navigateByUrl(this.router.url + '?f.' + data.filter + '=' + data.textsearch + ',' + data.operator); | ||
} else { | ||
this.router.navigateByUrl(this.router.url + '&f.' + data.filter + '=' + data.textsearch + ',' + data.operator); | ||
} | ||
} | ||
|
||
this.advSearchForm.reset({ operator: data.operator, filter: data.filter, textsearch: '' }); | ||
} | ||
} | ||
startSlide(event: any): void { | ||
if (event.toState === 'collapsed') { | ||
this.closed = true; | ||
} | ||
if (event.fromState === 'collapsed') { | ||
this.notab = false; | ||
} | ||
} | ||
finishSlide(event: any): void { | ||
if (event.fromState === 'collapsed') { | ||
this.closed = false; | ||
} | ||
if (event.toState === 'collapsed') { | ||
this.notab = true; | ||
} | ||
} | ||
toggle() { | ||
this.collapsedSearch = !this.collapsedSearch; | ||
} | ||
private isCollapsed(): boolean { | ||
return !this.collapsedSearch; | ||
} | ||
|
||
} | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
5 changes: 4 additions & 1 deletion
5
src/app/shared/search/search-filters/search-filters.component.html
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,7 +1,10 @@ | ||
<h3>{{"search.filters.head" | translate}}</h3> | ||
<h3 *ngIf="inPlaceSearch">{{filterLabel+'.filters.head' | translate}}</h3> | ||
<h2 *ngIf="!inPlaceSearch">{{filterLabel+'.filters.head' | translate}}</h2> | ||
<div *ngIf="(filters | async)?.hasSucceeded"> | ||
<div *ngFor="let filter of (filters | async)?.payload; trackBy: trackUpdate"> | ||
<ds-search-filter [scope]="currentScope" [filter]="filter" [inPlaceSearch]="inPlaceSearch" [refreshFilters]="refreshFilters"></ds-search-filter> | ||
</div> | ||
</div> | ||
<ds-advanced-search *ngIf="appConfig.search.advancedFilters.enabled" | ||
[inPlaceSearch]="inPlaceSearch"></ds-advanced-search> | ||
<a class="btn btn-primary" [routerLink]="[searchLink]" [queryParams]="clearParams | async" queryParamsHandling="merge" role="button"><i class="fas fa-undo"></i> {{"search.filters.reset" | translate}}</a> |
Oops, something went wrong.