Skip to content

Commit f1b60c0

Browse files
committed
Merge branch 'dspace-cris-7' into DSC-283-align-with-7.1
2 parents f811fdc + 00ecd00 commit f1b60c0

29 files changed

Lines changed: 505 additions & 67 deletions

src/app/openaire/reciter-suggestions/suggestion-actions/suggestion-actions.component.html

Lines changed: 16 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,23 @@
11
<div class="d-inline">
22
<div ngbDropdown class="d-inline">
3-
<button class="btn btn-success" id="dropdownSubmission" ngbDropdownToggle
4-
type="button">
3+
<button *ngIf="isCollectionFixed; else chooseCollection" class="btn btn-success" type="button" (click)="approveAndImportCollectionFixed()">
54
<i class="fa fa-check" aria-hidden="true"></i> {{ approveAndImportLabel() | translate}}
6-
<span class="caret"></span>
75
</button>
8-
<div ngbDropdownMenu
9-
class="dropdown-menu"
10-
id="entityControlsDropdownMenu"
11-
aria-labelledby="dropdownSubmission">
12-
<ds-entity-dropdown (selectionChange)="openDialog($event)"></ds-entity-dropdown>
13-
</div>
6+
<ng-template #chooseCollection>
7+
<button class="btn btn-success" id="dropdownSubmission" ngbDropdownToggle
8+
type="button">
9+
<i class="fa fa-check" aria-hidden="true"></i> {{ approveAndImportLabel() | translate}}
10+
<span class="caret"></span>
11+
</button>
12+
13+
<div ngbDropdownMenu
14+
class="dropdown-menu"
15+
id="entityControlsDropdownMenu"
16+
aria-labelledby="dropdownSubmission">
17+
<ds-entity-dropdown (selectionChange)="openDialog($event)"></ds-entity-dropdown>
18+
</div>
19+
</ng-template>
20+
1421
</div>
1522
<button (click)="notMine()" class="btn btn-danger ml-2"><i class="fa fa-ban"></i>
1623
{{ notMineLabel() | translate}}</button>

src/app/openaire/reciter-suggestions/suggestion-actions/suggestion-actions.component.ts

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,9 +18,11 @@ export class SuggestionActionsComponent {
1818

1919
@Input() isBulk = false;
2020

21-
@Input() public hasEvidence = false;
21+
@Input() hasEvidence = false;
2222

23-
@Input() public seeEvidence = false;
23+
@Input() seeEvidence = false;
24+
25+
@Input() isCollectionFixed = false;
2426

2527
/**
2628
* The component is used to Delete suggestion
@@ -58,6 +60,14 @@ export class SuggestionActionsComponent {
5860
});
5961
}
6062

63+
approveAndImportCollectionFixed() {
64+
this.approveAndImport.emit({
65+
suggestion: this.isBulk ? undefined : this.object,
66+
collectionId: null
67+
});
68+
}
69+
70+
6171
/**
6272
* Delete the suggestion
6373
*/

src/app/openaire/reciter-suggestions/suggestion-list-element/suggestion-list-element.component.html

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
<ds-suggestion-actions class="parent mt-2" [hasEvidence]="hasEvidences()"
2828
[seeEvidence]="seeEvidence"
2929
[object]="object"
30+
[isCollectionFixed]="isCollectionFixed"
3031
(approveAndImport)="onApproveAndImport($event)"
3132
(seeEvidences)="onSeeEvidences($event)"
3233
(notMineClicked)="onNotMine($event)"

src/app/openaire/reciter-suggestions/suggestion-list-element/suggestion-list-element.component.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,8 @@ export class SuggestionListElementComponent implements OnInit {
2424

2525
@Input() isSelected = false;
2626

27+
@Input() isCollectionFixed = false;
28+
2729
public listableObject: any;
2830

2931
public seeEvidence = false;

src/app/openaire/reciter-suggestions/suggestions-notification/suggestions-notification.component.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
<ng-container *ngIf="(suggestionsRD$ | async) as suggestions">
22
<ng-container *ngFor="let suggestion of suggestions" class="alert alert-info">
3-
<div class="alert alert-success" *ngIf="suggestion.total > 0">
3+
<div class="alert alert-success d-block" *ngIf="suggestion.total > 0">
44
<div [innerHTML]="'mydspace.notification.suggestion.page' | translate: getNotificationSuggestionInterpolation(suggestion)">
55
</div>
66
</div>

src/app/openaire/reciter-suggestions/suggestions.service.ts

Lines changed: 52 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ import { OpenaireSuggestionTarget } from '../../core/openaire/reciter-suggestion
1212
import { ResearcherProfileService } from '../../core/profile/researcher-profile.service';
1313
import { AuthService } from '../../core/auth/auth.service';
1414
import { EPerson } from '../../core/eperson/models/eperson.model';
15-
import { isNotEmpty } from '../../shared/empty.util';
15+
import { hasValue, isNotEmpty } from '../../shared/empty.util';
1616
import { ResearcherProfile } from '../../core/profile/model/researcher-profile.model';
1717
import {
1818
getAllSucceededRemoteDataPayload,
@@ -24,6 +24,9 @@ import { OpenaireSuggestion } from '../../core/openaire/reciter-suggestions/mode
2424
import { WorkspaceitemDataService } from '../../core/submission/workspaceitem-data.service';
2525
import { TranslateService } from '@ngx-translate/core';
2626
import { NoContent } from '../../core/shared/NoContent.model';
27+
import { environment } from '../../../environments/environment';
28+
import { SuggestionConfig } from '../../../config/layout-config.interfaces';
29+
import { WorkspaceItem } from '../../core/submission/models/workspaceitem.model';
2730

2831
export interface SuggestionBulkResult {
2932
success: number;
@@ -170,8 +173,10 @@ export class SuggestionsService {
170173
*/
171174
public approveAndImport(workspaceitemService: WorkspaceitemDataService,
172175
suggestion: OpenaireSuggestion,
173-
collectionId: string): Observable<string> {
174-
return workspaceitemService.importExternalSourceEntry(suggestion.externalSourceUri, collectionId)
176+
collectionId: string): Observable<WorkspaceItem> {
177+
178+
const resolvedCollectionId = this.resolveCollectionId(suggestion, collectionId);
179+
return workspaceitemService.importExternalSourceEntry(suggestion.externalSourceUri, resolvedCollectionId)
175180
.pipe(
176181
getFirstSucceededRemoteDataPayload(),
177182
catchError((error) => of(null))
@@ -200,7 +205,7 @@ export class SuggestionsService {
200205

201206
return forkJoin(suggestions.map((suggestion: OpenaireSuggestion) =>
202207
this.approveAndImport(workspaceitemService, suggestion, collectionId)))
203-
.pipe(map((results: string[]) => {
208+
.pipe(map((results: WorkspaceItem[]) => {
204209
return {
205210
success: results.filter((result) => result != null).length,
206211
fails: results.filter((result) => result == null).length
@@ -240,10 +245,52 @@ export class SuggestionsService {
240245
public getNotificationSuggestionInterpolation(suggestionTarget: OpenaireSuggestionTarget): any {
241246
return {
242247
count: suggestionTarget.total,
243-
source: this.translateService.instant('reciter.suggestion.source.' + suggestionTarget.source),
248+
source: this.translateService.instant(this.translateSuggestionSource(suggestionTarget.source)),
249+
type: this.translateService.instant(this.translateSuggestionType(suggestionTarget.source)),
244250
suggestionId: suggestionTarget.id,
245251
displayName: suggestionTarget.display
246252
};
247253
}
248254

255+
public translateSuggestionType(source: string): string {
256+
return 'reciter.suggestion.type.' + source;
257+
}
258+
259+
public translateSuggestionSource(source: string): string {
260+
return 'reciter.suggestion.source.' + source;
261+
}
262+
263+
/**
264+
* If the provided collectionId ha no value, tries to resolve it by suggestion source.
265+
* @param suggestion
266+
* @param collectionId
267+
*/
268+
public resolveCollectionId(suggestion: OpenaireSuggestion, collectionId): string {
269+
if (hasValue(collectionId)) {
270+
return collectionId;
271+
}
272+
return environment.suggestion
273+
.find((suggestionConf: SuggestionConfig) => suggestionConf.source === suggestion.source)
274+
.collectionId;
275+
}
276+
277+
/**
278+
* Return true if all the suggestion are configured with the same fixed collection
279+
* in the configuration.
280+
* @param suggestions
281+
*/
282+
public isCollectionFixed(suggestions: OpenaireSuggestion[]): boolean {
283+
return this.getFixedCollectionIds(suggestions).length === 1;
284+
}
285+
286+
private getFixedCollectionIds(suggestions: OpenaireSuggestion[]): string[] {
287+
const collectionIds = {};
288+
suggestions.forEach((suggestion: OpenaireSuggestion) => {
289+
const conf = environment.suggestion.find((suggestionConf: SuggestionConfig) => suggestionConf.source === suggestion.source);
290+
if (hasValue(conf)) {
291+
collectionIds[conf.collectionId] = true;
292+
}
293+
});
294+
return Object.keys(collectionIds);
295+
}
249296
}

src/app/profile-page/profile-page.component.html

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,10 @@ <h3 class="mb-4">{{'profile.head' | translate}}</h3>
44
<div class="card mb-4">
55
<div class="card-header">{{'profile.card.researcher' | translate}}</div>
66
<div class="card-body">
7-
<ds-profile-page-researcher-form [user]="user"></ds-profile-page-researcher-form>
7+
<div class="mb-4">
8+
<ds-profile-page-researcher-form [user]="user"></ds-profile-page-researcher-form>
9+
</div>
10+
<ds-suggestions-notification></ds-suggestions-notification>
811
</div>
912
</div>
1013
<div class="card mb-4">

src/app/profile-page/profile-page.module.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,13 +8,15 @@ import { ProfilePageSecurityFormComponent } from './profile-page-security-form/p
88
import { ProfilePageResearcherFormComponent } from './profile-page-researcher-form/profile-page-researcher-form.component';
99
import { ThemedProfilePageComponent } from './themed-profile-page.component';
1010
import { UiSwitchModule } from 'ngx-ui-switch';
11+
import { OpenaireModule } from '../openaire/openaire.module';
1112

1213
@NgModule({
1314
imports: [
1415
ProfilePageRoutingModule,
1516
CommonModule,
1617
SharedModule,
17-
UiSwitchModule
18+
UiSwitchModule,
19+
OpenaireModule
1820
],
1921
exports: [
2022
ProfilePageComponent,
Lines changed: 13 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,21 @@
11
<div class="col-12">
22
<h2>{{ 'explore.facet-section.title' | translate }}</h2>
33
<div class="row">
4-
<div *ngFor="let facet of (facets$ | async)" class="col-{{getFacetsBoxCol()}} mb-4">
4+
<div *ngFor="let facet of (facets$ | async)" class="col-{{getFacetsBoxCol(facet)}} mb-4">
55
<span>{{'explore.index.' + facet.name | translate}}</span>
6-
<div *ngFor="let facetValue of facet._embedded.values" class="border p-3">
7-
<a [routerLink]="[searchService.getSearchLink()]"
8-
[queryParams]="getSearchQueryParams(facet, facetValue)">
9-
{{facetValue.label}}
10-
</a>
11-
<span class="badge badge-secondary float-right">{{facetValue.count}}</span>
6+
<div *ngIf="facet.filterType.includes('chart'); else notChartFacet">
7+
<ds-search-chart [filter]="facet" [inPlaceSearch]="false"> </ds-search-chart>
128
</div>
9+
<ng-template #notChartFacet>
10+
<div *ngFor="let facetValue of facet._embedded.values" class="border p-3">
11+
<a [routerLink]="[searchService.getSearchLink()]"
12+
[queryParams]="getSearchQueryParams(facet, facetValue)">
13+
{{facetValue.label}}
14+
</a>
15+
<span class="badge badge-secondary float-right">{{facetValue.count}}</span>
16+
</div>
17+
</ng-template>
18+
1319
</div>
1420
</div>
1521
</div>

src/app/shared/explore/section-component/facet-section/facet-section.component.spec.ts

Lines changed: 56 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,12 @@ import { FacetValue } from '../../../search/facet-value.model';
1515
import { FilterType } from '../../../search/filter-type.model';
1616
import { SearchFilterConfig } from '../../../search/search-filter-config.model';
1717
import { FacetSectionComponent } from './facet-section.component';
18+
import {SEARCH_CONFIG_SERVICE} from '../../../../my-dspace-page/my-dspace-page.component';
19+
import {SearchConfigurationServiceStub} from '../../../testing/search-configuration-service.stub';
20+
import {StoreModule} from '@ngrx/store';
21+
import {authReducer} from '../../../../core/auth/auth.reducer';
22+
import {storeModuleConfig} from '../../../../app.reducer';
23+
import {isNotNull} from '../../../empty.util';
1824

1925
describe('FacetSectionComponent', () => {
2026
let component: FacetSectionComponent;
@@ -75,12 +81,43 @@ describe('FacetSectionComponent', () => {
7581
values: [dateIssuedValue]
7682
}
7783
});
78-
84+
const barChartFacetValue: FacetValue = {
85+
label: '2007',
86+
value: '2007',
87+
count: 13,
88+
_links: {
89+
self: { href: 'fa-selectedValue-self-link' },
90+
search: { href: '' }
91+
}
92+
};
93+
const mockGraphBarChartFilterConfig = Object.assign(new SearchFilterConfig(), {
94+
name: 'dateIssued',
95+
filterType: FilterType['chart.bar'],
96+
_embedded: {
97+
values: [barChartFacetValue]
98+
}
99+
});
100+
const pieChartFacetValue: FacetValue = {
101+
label: 'Other',
102+
value: 'Other',
103+
count: 13,
104+
_links: {
105+
self: { href: 'fa-selectedValue-self-link' },
106+
search: { href: '' }
107+
}
108+
};
109+
const mockGraphPieChartFilterConfig = Object.assign(new SearchFilterConfig(), {
110+
name: 'dateIssued',
111+
filterType: FilterType['chart.pie'],
112+
_embedded: {
113+
values: [pieChartFacetValue]
114+
}
115+
});
79116
beforeEach(async(() => {
80117

81118
searchServiceStub = {
82119
searchFacets(scope?: string, configurationName?: string): Observable<RemoteData<SearchFilterConfig[]>> {
83-
return createSuccessfulRemoteDataObject$([mockAuthorFilterConfig, mockSubjectFilterConfig, mockDateIssuedFilterConfig]);
120+
return createSuccessfulRemoteDataObject$([mockAuthorFilterConfig, mockSubjectFilterConfig, mockDateIssuedFilterConfig, mockGraphBarChartFilterConfig, mockGraphPieChartFilterConfig]);
84121
},
85122
getSearchLink(): string {
86123
return '/search';
@@ -89,6 +126,7 @@ describe('FacetSectionComponent', () => {
89126

90127
TestBed.configureTestingModule({
91128
imports: [CommonModule, NgbModule, FormsModule, ReactiveFormsModule, BrowserModule, RouterTestingModule,
129+
StoreModule.forRoot({ auth: authReducer }, storeModuleConfig),
92130
TranslateModule.forRoot({
93131
loader: {
94132
provide: TranslateLoader,
@@ -98,7 +136,8 @@ describe('FacetSectionComponent', () => {
98136
],
99137
declarations: [FacetSectionComponent],
100138
providers: [FacetSectionComponent,
101-
{ provide: SearchService, useValue: searchServiceStub }],
139+
{ provide: SearchService, useValue: searchServiceStub },
140+
{ provide: SEARCH_CONFIG_SERVICE, useValue: new SearchConfigurationServiceStub() }],
102141
schemas: [NO_ERRORS_SCHEMA]
103142
}).compileComponents();
104143

@@ -124,6 +163,20 @@ describe('FacetSectionComponent', () => {
124163
}));
125164

126165
it('should create a facet section foreach not empty filter configs', () => {
166+
// graph facets control
167+
const graphFacets = fixture.debugElement.queryAll(By.css('.col-6.mb-4'));
168+
expect(graphFacets.length).toEqual(2);
169+
const barChartFacet = graphFacets[0];
170+
expect(barChartFacet.name).toEqual('div');
171+
expect(barChartFacet.children.length).toEqual(2);
172+
const barChartComponent = barChartFacet.query(By.css('ds-search-chart'));
173+
expect(isNotNull(barChartComponent)).toBe(true);
174+
const pieChartFacet = graphFacets[1];
175+
expect(pieChartFacet.children.length).toEqual(2);
176+
expect(pieChartFacet.name).toEqual('div');
177+
const pieChartComponent = pieChartFacet.query(By.css('ds-search-chart'));
178+
expect(isNotNull(pieChartComponent)).toBe(true);
179+
127180
const facets = fixture.debugElement.queryAll(By.css('.col-3.mb-4'));
128181
expect(facets.length).toEqual(2);
129182

0 commit comments

Comments
 (0)