mirror of
https://github.com/DSpace/dspace-angular.git
synced 2025-10-07 10:04:11 +00:00
Merge branch 'CST-5307' into CST-5668
This commit is contained in:
@@ -4,7 +4,7 @@ import { HALLink } from '../../shared/hal-link.model';
|
|||||||
import { ResourceType } from '../../shared/resource-type';
|
import { ResourceType } from '../../shared/resource-type';
|
||||||
import { excludeFromEquals } from '../../utilities/equals.decorators';
|
import { excludeFromEquals } from '../../utilities/equals.decorators';
|
||||||
import { RESEARCHER_PROFILE } from './researcher-profile.resource-type';
|
import { RESEARCHER_PROFILE } from './researcher-profile.resource-type';
|
||||||
import {CacheableObject} from "../../cache/cacheable-object.model";
|
import {CacheableObject} from '../../cache/cacheable-object.model';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Class the represents a Researcher Profile.
|
* Class the represents a Researcher Profile.
|
||||||
|
@@ -1,3 +1,4 @@
|
|||||||
|
/* eslint-disable max-classes-per-file */
|
||||||
import { HttpClient, HttpHeaders } from '@angular/common/http';
|
import { HttpClient, HttpHeaders } from '@angular/common/http';
|
||||||
import { Injectable } from '@angular/core';
|
import { Injectable } from '@angular/core';
|
||||||
import { Router } from '@angular/router';
|
import { Router } from '@angular/router';
|
||||||
@@ -30,9 +31,7 @@ import { RESEARCHER_PROFILE } from './model/researcher-profile.resource-type';
|
|||||||
import { HttpOptions } from '../dspace-rest/dspace-rest.service';
|
import { HttpOptions } from '../dspace-rest/dspace-rest.service';
|
||||||
import { PostRequest } from '../data/request.models';
|
import { PostRequest } from '../data/request.models';
|
||||||
import { hasValue } from '../../shared/empty.util';
|
import { hasValue } from '../../shared/empty.util';
|
||||||
import {CoreState} from "../core-state.model";
|
import {CoreState} from '../core-state.model';
|
||||||
|
|
||||||
/* tslint:disable:max-classes-per-file */
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A private DataService implementation to delegate specific methods to.
|
* A private DataService implementation to delegate specific methods to.
|
||||||
|
@@ -2,6 +2,9 @@ import { Component } from '@angular/core';
|
|||||||
import { listableObjectComponent } from '../../../../../shared/object-collection/shared/listable-object/listable-object.decorator';
|
import { listableObjectComponent } from '../../../../../shared/object-collection/shared/listable-object/listable-object.decorator';
|
||||||
import { ViewMode } from '../../../../../core/shared/view-mode.model';
|
import { ViewMode } from '../../../../../core/shared/view-mode.model';
|
||||||
import { ItemSearchResultListElementComponent } from '../../../../../shared/object-list/search-result-list-element/item-search-result/item-types/item/item-search-result-list-element.component';
|
import { ItemSearchResultListElementComponent } from '../../../../../shared/object-list/search-result-list-element/item-search-result/item-types/item/item-search-result-list-element.component';
|
||||||
|
import {TruncatableService} from '../../../../../shared/truncatable/truncatable.service';
|
||||||
|
import {DSONameService} from '../../../../../core/breadcrumbs/dso-name.service';
|
||||||
|
import {isNotEmpty} from '../../../../../shared/empty.util';
|
||||||
|
|
||||||
@listableObjectComponent('PersonSearchResult', ViewMode.ListElement)
|
@listableObjectComponent('PersonSearchResult', ViewMode.ListElement)
|
||||||
@Component({
|
@Component({
|
||||||
@@ -14,9 +17,15 @@ import { ItemSearchResultListElementComponent } from '../../../../../shared/obje
|
|||||||
*/
|
*/
|
||||||
export class PersonSearchResultListElementComponent extends ItemSearchResultListElementComponent {
|
export class PersonSearchResultListElementComponent extends ItemSearchResultListElementComponent {
|
||||||
|
|
||||||
|
public constructor(protected truncatableService: TruncatableService, protected dsoNameService: DSONameService) {
|
||||||
|
super(truncatableService, dsoNameService);
|
||||||
|
}
|
||||||
|
|
||||||
get name() {
|
get name() {
|
||||||
return this.value ?
|
let personName = this.dsoNameService.getName(this.dso);
|
||||||
this.value :
|
if (isNotEmpty(this.firstMetadataValue('person.familyName')) && isNotEmpty(this.firstMetadataValue('person.givenName'))) {
|
||||||
this.firstMetadataValue('person.familyName') + ', ' + this.firstMetadataValue('person.givenName');
|
personName = this.firstMetadataValue('person.familyName') + ', ' + this.firstMetadataValue('person.givenName');
|
||||||
|
}
|
||||||
|
return personName;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -1,10 +1,11 @@
|
|||||||
<div class="d-flex flex-row">
|
<div class="d-flex flex-row">
|
||||||
<h2 class="item-page-title-field mr-auto">
|
<h2 class="item-page-title-field mr-auto">
|
||||||
{{'person.page.titleprefix' | translate}}<ds-metadata-values [mdValues]="[object?.firstMetadata('person.familyName'), object?.firstMetadata('person.givenName')]" [separator]="', '"></ds-metadata-values>
|
{{'person.page.titleprefix' | translate}}<ds-metadata-values [mdValues]="getTitleMetadataValues()" [separator]="', '"></ds-metadata-values>
|
||||||
</h2>
|
</h2>
|
||||||
<div class="pl-2">
|
<div class="pl-2">
|
||||||
<ds-dso-page-orcid-button [pageRoute]="itemPageRoute" [dso]="object"></ds-dso-page-orcid-button>
|
<ds-dso-page-orcid-button [pageRoute]="itemPageRoute" [dso]="object"></ds-dso-page-orcid-button>
|
||||||
<ds-dso-page-edit-button [pageRoute]="itemPageRoute" [dso]="object" [tooltipMsg]="'person.page.edit'"></ds-dso-page-edit-button>
|
<ds-dso-page-edit-button [pageRoute]="itemPageRoute" [dso]="object" [tooltipMsg]="'person.page.edit'"></ds-dso-page-edit-button>
|
||||||
|
<button class="edit-button btn btn-dark btn-sm" *ngIf="(isClaimable() | async)" (click)="claim()"> {{"item.page.claim.button" | translate }} </button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="row">
|
<div class="row">
|
||||||
|
@@ -54,7 +54,12 @@ const mockItem: Item = Object.assign(new Item(), {
|
|||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
relationships: createRelationshipsObservable()
|
relationships: createRelationshipsObservable(),
|
||||||
|
_links: {
|
||||||
|
self : {
|
||||||
|
href: 'item-href'
|
||||||
|
}
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('PersonComponent', getItemPageFieldsTest(mockItem, PersonComponent));
|
describe('PersonComponent', getItemPageFieldsTest(mockItem, PersonComponent));
|
||||||
|
@@ -1,7 +1,20 @@
|
|||||||
import { Component } from '@angular/core';
|
import {Component, OnInit} from '@angular/core';
|
||||||
import { ItemComponent } from '../../../../item-page/simple/item-types/shared/item.component';
|
import { ItemComponent } from '../../../../item-page/simple/item-types/shared/item.component';
|
||||||
import { ViewMode } from '../../../../core/shared/view-mode.model';
|
import { ViewMode } from '../../../../core/shared/view-mode.model';
|
||||||
import { listableObjectComponent } from '../../../../shared/object-collection/shared/listable-object/listable-object.decorator';
|
import { listableObjectComponent } from '../../../../shared/object-collection/shared/listable-object/listable-object.decorator';
|
||||||
|
import {MetadataValue} from '../../../../core/shared/metadata.models';
|
||||||
|
import {FeatureID} from '../../../../core/data/feature-authorization/feature-id';
|
||||||
|
import {mergeMap, take} from 'rxjs/operators';
|
||||||
|
import {getFirstSucceededRemoteData} from '../../../../core/shared/operators';
|
||||||
|
import {RemoteData} from '../../../../core/data/remote-data';
|
||||||
|
import {ResearcherProfile} from '../../../../core/profile/model/researcher-profile.model';
|
||||||
|
import {isNotUndefined} from '../../../../shared/empty.util';
|
||||||
|
import {BehaviorSubject, Observable} from 'rxjs';
|
||||||
|
import {RouteService} from '../../../../core/services/route.service';
|
||||||
|
import {AuthorizationDataService} from '../../../../core/data/feature-authorization/authorization-data.service';
|
||||||
|
import {ResearcherProfileService} from '../../../../core/profile/researcher-profile.service';
|
||||||
|
import {NotificationsService} from '../../../../shared/notifications/notifications.service';
|
||||||
|
import {TranslateService} from '@ngx-translate/core';
|
||||||
|
|
||||||
@listableObjectComponent('Person', ViewMode.StandalonePage)
|
@listableObjectComponent('Person', ViewMode.StandalonePage)
|
||||||
@Component({
|
@Component({
|
||||||
@@ -12,5 +25,81 @@ import { listableObjectComponent } from '../../../../shared/object-collection/sh
|
|||||||
/**
|
/**
|
||||||
* The component for displaying metadata and relations of an item of the type Person
|
* The component for displaying metadata and relations of an item of the type Person
|
||||||
*/
|
*/
|
||||||
export class PersonComponent extends ItemComponent {
|
export class PersonComponent extends ItemComponent implements OnInit {
|
||||||
|
|
||||||
|
claimable$: BehaviorSubject<boolean> = new BehaviorSubject<boolean>(false);
|
||||||
|
|
||||||
|
constructor(protected routeService: RouteService,
|
||||||
|
protected authorizationService: AuthorizationDataService,
|
||||||
|
protected notificationsService: NotificationsService,
|
||||||
|
protected translate: TranslateService,
|
||||||
|
protected researcherProfileService: ResearcherProfileService) {
|
||||||
|
super(routeService);
|
||||||
|
}
|
||||||
|
|
||||||
|
ngOnInit(): void {
|
||||||
|
super.ngOnInit();
|
||||||
|
|
||||||
|
this.authorizationService.isAuthorized(FeatureID.ShowClaimItem, this.object._links.self.href).pipe(
|
||||||
|
take(1)
|
||||||
|
).subscribe((isAuthorized: boolean) => {
|
||||||
|
this.claimable$.next(isAuthorized);
|
||||||
|
});
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
claim() {
|
||||||
|
|
||||||
|
this.authorizationService.isAuthorized(FeatureID.CanClaimItem, this.object._links.self.href).pipe(
|
||||||
|
take(1)
|
||||||
|
).subscribe((isAuthorized: boolean) => {
|
||||||
|
if (!isAuthorized) {
|
||||||
|
this.notificationsService.warning(this.translate.get('researcherprofile.claim.not-authorized'));
|
||||||
|
} else {
|
||||||
|
this.createFromExternalSource();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
createFromExternalSource() {
|
||||||
|
this.researcherProfileService.createFromExternalSource(this.object._links.self.href).pipe(
|
||||||
|
getFirstSucceededRemoteData(),
|
||||||
|
mergeMap((rd: RemoteData<ResearcherProfile>) => {
|
||||||
|
return this.researcherProfileService.findRelatedItemId(rd.payload);
|
||||||
|
}))
|
||||||
|
.subscribe((id: string) => {
|
||||||
|
if (isNotUndefined(id)) {
|
||||||
|
this.notificationsService.success(this.translate.get('researcherprofile.success.claim.title'),
|
||||||
|
this.translate.get('researcherprofile.success.claim.body'));
|
||||||
|
this.claimable$.next(false);
|
||||||
|
} else {
|
||||||
|
this.notificationsService.error(
|
||||||
|
this.translate.get('researcherprofile.error.claim.title'),
|
||||||
|
this.translate.get('researcherprofile.error.claim.body'));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
isClaimable(): Observable<boolean> {
|
||||||
|
return this.claimable$;
|
||||||
|
}
|
||||||
|
|
||||||
|
getTitleMetadataValues(): MetadataValue[]{
|
||||||
|
const metadataValues = [];
|
||||||
|
const familyName = this.object?.firstMetadata('person.familyName');
|
||||||
|
const givenName = this.object?.firstMetadata('person.givenName');
|
||||||
|
const title = this.object?.firstMetadata('dc.title');
|
||||||
|
if (familyName){
|
||||||
|
metadataValues.push(familyName);
|
||||||
|
}
|
||||||
|
if (givenName){
|
||||||
|
metadataValues.push(givenName);
|
||||||
|
}
|
||||||
|
if (metadataValues.length === 0 && title){
|
||||||
|
metadataValues.push(title);
|
||||||
|
}
|
||||||
|
return metadataValues;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@@ -10,7 +10,6 @@
|
|||||||
<div class="pl-2 space-children-mr">
|
<div class="pl-2 space-children-mr">
|
||||||
<ds-dso-page-edit-button [pageRoute]="itemPageRoute$ | async" [dso]="item"
|
<ds-dso-page-edit-button [pageRoute]="itemPageRoute$ | async" [dso]="item"
|
||||||
[tooltipMsg]="'item.page.edit'"></ds-dso-page-edit-button>
|
[tooltipMsg]="'item.page.edit'"></ds-dso-page-edit-button>
|
||||||
<button class="edit-button btn btn-dark btn-sm" *ngIf="(isClaimable() | async)" (click)="claim()"> {{"item.page.claim.button" | translate }} </button>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="simple-view-link my-3" *ngIf="!fromWfi">
|
<div class="simple-view-link my-3" *ngIf="!fromWfi">
|
||||||
|
@@ -16,10 +16,6 @@ import { hasValue } from '../../shared/empty.util';
|
|||||||
import { AuthService } from '../../core/auth/auth.service';
|
import { AuthService } from '../../core/auth/auth.service';
|
||||||
import { Location } from '@angular/common';
|
import { Location } from '@angular/common';
|
||||||
import { AuthorizationDataService } from '../../core/data/feature-authorization/authorization-data.service';
|
import { AuthorizationDataService } from '../../core/data/feature-authorization/authorization-data.service';
|
||||||
import { TranslateService } from '@ngx-translate/core';
|
|
||||||
import { NotificationsService } from '../../shared/notifications/notifications.service';
|
|
||||||
import { ResearcherProfileService } from '../../core/profile/researcher-profile.service';
|
|
||||||
import { CollectionDataService } from '../../core/data/collection-data.service';
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -52,11 +48,8 @@ export class FullItemPageComponent extends ItemPageComponent implements OnInit,
|
|||||||
items: ItemDataService,
|
items: ItemDataService,
|
||||||
authService: AuthService,
|
authService: AuthService,
|
||||||
authorizationService: AuthorizationDataService,
|
authorizationService: AuthorizationDataService,
|
||||||
translate: TranslateService,
|
|
||||||
notificationsService: NotificationsService,
|
|
||||||
researcherProfileService: ResearcherProfileService,
|
|
||||||
private _location: Location) {
|
private _location: Location) {
|
||||||
super(route, router, items, authService, authorizationService, translate, notificationsService, researcherProfileService);
|
super(route, router, items, authService, authorizationService);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*** AoT inheritance fix, will hopefully be resolved in the near future **/
|
/*** AoT inheritance fix, will hopefully be resolved in the near future **/
|
||||||
|
@@ -64,24 +64,13 @@ export class ItemPageComponent implements OnInit {
|
|||||||
|
|
||||||
itemUrl: string;
|
itemUrl: string;
|
||||||
|
|
||||||
public claimable$: BehaviorSubject<boolean> = new BehaviorSubject<boolean>(false);
|
|
||||||
public isProcessing$: BehaviorSubject<boolean> = new BehaviorSubject<boolean>(false);
|
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
protected route: ActivatedRoute,
|
protected route: ActivatedRoute,
|
||||||
private router: Router,
|
private router: Router,
|
||||||
private items: ItemDataService,
|
private items: ItemDataService,
|
||||||
private authService: AuthService,
|
private authService: AuthService,
|
||||||
private authorizationService: AuthorizationDataService,
|
private authorizationService: AuthorizationDataService
|
||||||
private translate: TranslateService,
|
|
||||||
private notificationsService: NotificationsService,
|
|
||||||
private researcherProfileService: ResearcherProfileService
|
|
||||||
) {
|
) {
|
||||||
this.route.data.pipe(
|
|
||||||
map((data) => data.dso as RemoteData<Item>)
|
|
||||||
).subscribe((data: RemoteData<Item>) => {
|
|
||||||
this.itemUrl = data?.payload?.self
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -99,55 +88,5 @@ export class ItemPageComponent implements OnInit {
|
|||||||
|
|
||||||
this.isAdmin$ = this.authorizationService.isAuthorized(FeatureID.AdministratorOf);
|
this.isAdmin$ = this.authorizationService.isAuthorized(FeatureID.AdministratorOf);
|
||||||
|
|
||||||
this.authorizationService.isAuthorized(FeatureID.ShowClaimItem, this.itemUrl).pipe(
|
|
||||||
take(1)
|
|
||||||
).subscribe((isAuthorized: boolean) => {
|
|
||||||
this.claimable$.next(isAuthorized)
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
claim() {
|
|
||||||
this.isProcessing$.next(true);
|
|
||||||
|
|
||||||
this.authorizationService.isAuthorized(FeatureID.CanClaimItem, this.itemUrl).pipe(
|
|
||||||
take(1)
|
|
||||||
).subscribe((isAuthorized: boolean) => {
|
|
||||||
if (!isAuthorized) {
|
|
||||||
this.notificationsService.warning(this.translate.get('researcherprofile.claim.not-authorized'));
|
|
||||||
this.isProcessing$.next(false);
|
|
||||||
} else {
|
|
||||||
this.createFromExternalSource();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
createFromExternalSource() {
|
|
||||||
this.researcherProfileService.createFromExternalSource(this.itemUrl).pipe(
|
|
||||||
tap((rd: any) => {
|
|
||||||
if (!rd.hasSucceeded) {
|
|
||||||
this.isProcessing$.next(false);
|
|
||||||
}
|
|
||||||
}),
|
|
||||||
getFirstSucceededRemoteData(),
|
|
||||||
mergeMap((rd: RemoteData<ResearcherProfile>) => {
|
|
||||||
return this.researcherProfileService.findRelatedItemId(rd.payload);
|
|
||||||
}))
|
|
||||||
.subscribe((id: string) => {
|
|
||||||
if (isNotUndefined(id)) {
|
|
||||||
this.notificationsService.success(this.translate.get('researcherprofile.success.claim.title'),
|
|
||||||
this.translate.get('researcherprofile.success.claim.body'));
|
|
||||||
this.claimable$.next(false);
|
|
||||||
this.isProcessing$.next(false);
|
|
||||||
} else {
|
|
||||||
this.notificationsService.error(
|
|
||||||
this.translate.get('researcherprofile.error.claim.title'),
|
|
||||||
this.translate.get('researcherprofile.error.claim.body'));
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
isClaimable(): Observable<boolean> {
|
|
||||||
return this.claimable$;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -4,7 +4,7 @@ import { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing';
|
|||||||
import { By } from '@angular/platform-browser';
|
import { By } from '@angular/platform-browser';
|
||||||
import { Store } from '@ngrx/store';
|
import { Store } from '@ngrx/store';
|
||||||
import { TranslateLoader, TranslateModule } from '@ngx-translate/core';
|
import { TranslateLoader, TranslateModule } from '@ngx-translate/core';
|
||||||
import { Observable } from 'rxjs';
|
import {Observable, of as observableOf} from 'rxjs';
|
||||||
import { RemoteDataBuildService } from '../../../../core/cache/builders/remote-data-build.service';
|
import { RemoteDataBuildService } from '../../../../core/cache/builders/remote-data-build.service';
|
||||||
import { ObjectCacheService } from '../../../../core/cache/object-cache.service';
|
import { ObjectCacheService } from '../../../../core/cache/object-cache.service';
|
||||||
import { BitstreamDataService } from '../../../../core/data/bitstream-data.service';
|
import { BitstreamDataService } from '../../../../core/data/bitstream-data.service';
|
||||||
@@ -32,6 +32,8 @@ import { ItemComponent } from './item.component';
|
|||||||
import { createPaginatedList } from '../../../../shared/testing/utils.test';
|
import { createPaginatedList } from '../../../../shared/testing/utils.test';
|
||||||
import { RouteService } from '../../../../core/services/route.service';
|
import { RouteService } from '../../../../core/services/route.service';
|
||||||
import { MetadataValue } from '../../../../core/shared/metadata.models';
|
import { MetadataValue } from '../../../../core/shared/metadata.models';
|
||||||
|
import {AuthorizationDataService} from '../../../../core/data/feature-authorization/authorization-data.service';
|
||||||
|
import {ResearcherProfileService} from '../../../../core/profile/researcher-profile.service';
|
||||||
|
|
||||||
export const iiifEnabled = Object.assign(new MetadataValue(),{
|
export const iiifEnabled = Object.assign(new MetadataValue(),{
|
||||||
'value': 'true',
|
'value': 'true',
|
||||||
@@ -69,6 +71,11 @@ export function getItemPageFieldsTest(mockItem: Item, component) {
|
|||||||
return createSuccessfulRemoteDataObject$(new Bitstream());
|
return createSuccessfulRemoteDataObject$(new Bitstream());
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const authorizationService = jasmine.createSpyObj('authorizationService', {
|
||||||
|
isAuthorized: observableOf(true)
|
||||||
|
});
|
||||||
|
|
||||||
TestBed.configureTestingModule({
|
TestBed.configureTestingModule({
|
||||||
imports: [TranslateModule.forRoot({
|
imports: [TranslateModule.forRoot({
|
||||||
loader: {
|
loader: {
|
||||||
@@ -92,7 +99,9 @@ export function getItemPageFieldsTest(mockItem: Item, component) {
|
|||||||
{ provide: NotificationsService, useValue: {} },
|
{ provide: NotificationsService, useValue: {} },
|
||||||
{ provide: DefaultChangeAnalyzer, useValue: {} },
|
{ provide: DefaultChangeAnalyzer, useValue: {} },
|
||||||
{ provide: BitstreamDataService, useValue: mockBitstreamDataService },
|
{ provide: BitstreamDataService, useValue: mockBitstreamDataService },
|
||||||
{ provide: RouteService, useValue: {} }
|
{ provide: RouteService, useValue: {} },
|
||||||
|
{ provide: AuthorizationDataService, useValue: authorizationService },
|
||||||
|
{ provide: ResearcherProfileService, useValue: {} }
|
||||||
],
|
],
|
||||||
|
|
||||||
schemas: [NO_ERRORS_SCHEMA]
|
schemas: [NO_ERRORS_SCHEMA]
|
||||||
|
@@ -9,7 +9,7 @@
|
|||||||
<div *ngIf="!researcherProfile">
|
<div *ngIf="!researcherProfile">
|
||||||
<p>{{'researcher.profile.not.associated' | translate}}</p>
|
<p>{{'researcher.profile.not.associated' | translate}}</p>
|
||||||
</div>
|
</div>
|
||||||
<button class="btn btn-primary"
|
<button class="btn btn-primary mr-2"
|
||||||
[disabled]="researcherProfile || (isProcessingCreate() | async)"
|
[disabled]="researcherProfile || (isProcessingCreate() | async)"
|
||||||
(click)="createProfile()">
|
(click)="createProfile()">
|
||||||
<span *ngIf="(isProcessingCreate() | async)">
|
<span *ngIf="(isProcessingCreate() | async)">
|
||||||
@@ -20,7 +20,7 @@
|
|||||||
</span>
|
</span>
|
||||||
</button>
|
</button>
|
||||||
<ng-container *ngIf="researcherProfile">
|
<ng-container *ngIf="researcherProfile">
|
||||||
<button class="btn btn-primary" [disabled]="!researcherProfile" (click)="viewProfile(researcherProfile)">
|
<button class="btn btn-primary mr-2" [disabled]="!researcherProfile" (click)="viewProfile(researcherProfile)">
|
||||||
<i class="fas fa-info-circle"></i> {{'researcher.profile.view' | translate}}
|
<i class="fas fa-info-circle"></i> {{'researcher.profile.view' | translate}}
|
||||||
</button>
|
</button>
|
||||||
<button class="btn btn-danger" [disabled]="!researcherProfile" (click)="deleteProfile(researcherProfile)">
|
<button class="btn btn-danger" [disabled]="!researcherProfile" (click)="deleteProfile(researcherProfile)">
|
||||||
|
@@ -16,11 +16,6 @@ import { ProfilePageResearcherFormComponent } from './profile-page-researcher-fo
|
|||||||
import { ProfileClaimService } from '../profile-claim/profile-claim.service';
|
import { ProfileClaimService } from '../profile-claim/profile-claim.service';
|
||||||
import { NgbModal } from '@ng-bootstrap/ng-bootstrap';
|
import { NgbModal } from '@ng-bootstrap/ng-bootstrap';
|
||||||
import { AuthService } from 'src/app/core/auth/auth.service';
|
import { AuthService } from 'src/app/core/auth/auth.service';
|
||||||
import { EditItemDataService } from '../../core/submission/edititem-data.service';
|
|
||||||
import { createSuccessfulRemoteDataObject$ } from '../../shared/remote-data.utils';
|
|
||||||
import { EditItemMode } from '../../core/submission/models/edititem-mode.model';
|
|
||||||
import { EditItem } from '../../core/submission/models/edititem.model';
|
|
||||||
import { createPaginatedList } from '../../shared/testing/utils.test';
|
|
||||||
|
|
||||||
describe('ProfilePageResearcherFormComponent', () => {
|
describe('ProfilePageResearcherFormComponent', () => {
|
||||||
|
|
||||||
@@ -39,17 +34,6 @@ describe('ProfilePageResearcherFormComponent', () => {
|
|||||||
|
|
||||||
let authService: AuthService;
|
let authService: AuthService;
|
||||||
|
|
||||||
let editItemDataService: any;
|
|
||||||
|
|
||||||
const editItemMode: EditItemMode = Object.assign(new EditItemMode(), {
|
|
||||||
name: 'test',
|
|
||||||
label: 'test'
|
|
||||||
});
|
|
||||||
|
|
||||||
const editItem: EditItem = Object.assign(new EditItem(), {
|
|
||||||
modes: createSuccessfulRemoteDataObject$(createPaginatedList([editItemMode]))
|
|
||||||
});
|
|
||||||
|
|
||||||
function init() {
|
function init() {
|
||||||
|
|
||||||
user = Object.assign(new EPerson(), {
|
user = Object.assign(new EPerson(), {
|
||||||
@@ -80,10 +64,6 @@ describe('ProfilePageResearcherFormComponent', () => {
|
|||||||
canClaimProfiles: observableOf(false),
|
canClaimProfiles: observableOf(false),
|
||||||
});
|
});
|
||||||
|
|
||||||
editItemDataService = jasmine.createSpyObj('EditItemDataService', {
|
|
||||||
findById: createSuccessfulRemoteDataObject$(editItem)
|
|
||||||
});
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
beforeEach(waitForAsync(() => {
|
beforeEach(waitForAsync(() => {
|
||||||
@@ -96,8 +76,7 @@ describe('ProfilePageResearcherFormComponent', () => {
|
|||||||
{ provide: ResearcherProfileService, useValue: researcherProfileService },
|
{ provide: ResearcherProfileService, useValue: researcherProfileService },
|
||||||
{ provide: NotificationsService, useValue: notificationsServiceStub },
|
{ provide: NotificationsService, useValue: notificationsServiceStub },
|
||||||
{ provide: ProfileClaimService, useValue: profileClaimService },
|
{ provide: ProfileClaimService, useValue: profileClaimService },
|
||||||
{ provide: AuthService, useValue: authService },
|
{ provide: AuthService, useValue: authService }
|
||||||
{ provide: EditItemDataService, useValue: editItemDataService }
|
|
||||||
],
|
],
|
||||||
schemas: [NO_ERRORS_SCHEMA]
|
schemas: [NO_ERRORS_SCHEMA]
|
||||||
}).compileComponents();
|
}).compileComponents();
|
||||||
|
@@ -128,10 +128,10 @@ export class ProfilePageResearcherFormComponent implements OnInit {
|
|||||||
* @param researcherProfile the profile to update
|
* @param researcherProfile the profile to update
|
||||||
*/
|
*/
|
||||||
toggleProfileVisibility(researcherProfile: ResearcherProfile): void {
|
toggleProfileVisibility(researcherProfile: ResearcherProfile): void {
|
||||||
/* tslint:disable:no-empty */
|
|
||||||
this.researcherProfileService.setVisibility(researcherProfile, !researcherProfile.visible)
|
this.researcherProfileService.setVisibility(researcherProfile, !researcherProfile.visible)
|
||||||
.subscribe((updatedProfile) => {}); // this.researcherProfile$.next(updatedProfile);
|
.subscribe((updatedProfile) => {
|
||||||
/* tslint:enable:no-empty */
|
this.researcherProfile$.next(updatedProfile);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@@ -1,5 +1,6 @@
|
|||||||
<ng-container *ngVar="(user$ | async) as user">
|
<ng-container *ngVar="(user$ | async) as user">
|
||||||
<div class="container" *ngIf="user">
|
<div class="container" *ngIf="user">
|
||||||
|
<ng-container *ngIf="isResearcherProfileEnabled() | async">
|
||||||
<h3 class="mb-4">{{'profile.head' | translate}}</h3>
|
<h3 class="mb-4">{{'profile.head' | translate}}</h3>
|
||||||
<div class="card mb-4">
|
<div class="card mb-4">
|
||||||
<div class="card-header">{{'profile.card.researcher' | translate}}</div>
|
<div class="card-header">{{'profile.card.researcher' | translate}}</div>
|
||||||
@@ -7,9 +8,9 @@
|
|||||||
<div class="mb-4">
|
<div class="mb-4">
|
||||||
<ds-profile-page-researcher-form [user]="user" ></ds-profile-page-researcher-form>
|
<ds-profile-page-researcher-form [user]="user" ></ds-profile-page-researcher-form>
|
||||||
</div>
|
</div>
|
||||||
<!-- <ds-suggestions-notification></ds-suggestions-notification> -->
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
</ng-container>
|
||||||
<div class="card mb-4">
|
<div class="card mb-4">
|
||||||
<div class="card-header">{{'profile.card.identify' | translate}}</div>
|
<div class="card-header">{{'profile.card.identify' | translate}}</div>
|
||||||
<div class="card-body">
|
<div class="card-body">
|
||||||
|
@@ -20,6 +20,8 @@ import { provideMockStore } from '@ngrx/store/testing';
|
|||||||
import { AuthorizationDataService } from '../core/data/feature-authorization/authorization-data.service';
|
import { AuthorizationDataService } from '../core/data/feature-authorization/authorization-data.service';
|
||||||
import { getTestScheduler } from 'jasmine-marbles';
|
import { getTestScheduler } from 'jasmine-marbles';
|
||||||
import { By } from '@angular/platform-browser';
|
import { By } from '@angular/platform-browser';
|
||||||
|
import {ConfigurationDataService} from '../core/data/configuration-data.service';
|
||||||
|
import {ConfigurationProperty} from '../core/shared/configuration-property.model';
|
||||||
|
|
||||||
describe('ProfilePageComponent', () => {
|
describe('ProfilePageComponent', () => {
|
||||||
let component: ProfilePageComponent;
|
let component: ProfilePageComponent;
|
||||||
@@ -80,6 +82,14 @@ describe('ProfilePageComponent', () => {
|
|||||||
{ provide: EPersonDataService, useValue: epersonService },
|
{ provide: EPersonDataService, useValue: epersonService },
|
||||||
{ provide: NotificationsService, useValue: notificationsService },
|
{ provide: NotificationsService, useValue: notificationsService },
|
||||||
{ provide: AuthService, useValue: authService },
|
{ provide: AuthService, useValue: authService },
|
||||||
|
{ provide: ConfigurationDataService, useValue: jasmine.createSpyObj('configurationDataService', {
|
||||||
|
findByPropertyName: createSuccessfulRemoteDataObject$(Object.assign(new ConfigurationProperty(), {
|
||||||
|
name: 'researcher-profile.entity-type',
|
||||||
|
values: [
|
||||||
|
'Person'
|
||||||
|
]
|
||||||
|
}))
|
||||||
|
})},
|
||||||
{ provide: AuthorizationDataService, useValue: jasmine.createSpyObj('authorizationService', { isAuthorized: canChangePassword }) },
|
{ provide: AuthorizationDataService, useValue: jasmine.createSpyObj('authorizationService', { isAuthorized: canChangePassword }) },
|
||||||
provideMockStore({ initialState }),
|
provideMockStore({ initialState }),
|
||||||
],
|
],
|
||||||
|
@@ -1,5 +1,5 @@
|
|||||||
import { Component, OnInit, ViewChild } from '@angular/core';
|
import { Component, OnInit, ViewChild } from '@angular/core';
|
||||||
import { Observable } from 'rxjs';
|
import {BehaviorSubject, Observable} from 'rxjs';
|
||||||
import { EPerson } from '../core/eperson/models/eperson.model';
|
import { EPerson } from '../core/eperson/models/eperson.model';
|
||||||
import { ProfilePageMetadataFormComponent } from './profile-page-metadata-form/profile-page-metadata-form.component';
|
import { ProfilePageMetadataFormComponent } from './profile-page-metadata-form/profile-page-metadata-form.component';
|
||||||
import { NotificationsService } from '../shared/notifications/notifications.service';
|
import { NotificationsService } from '../shared/notifications/notifications.service';
|
||||||
@@ -12,7 +12,7 @@ import { EPersonDataService } from '../core/eperson/eperson-data.service';
|
|||||||
import {
|
import {
|
||||||
getAllSucceededRemoteData,
|
getAllSucceededRemoteData,
|
||||||
getRemoteDataPayload,
|
getRemoteDataPayload,
|
||||||
getFirstCompletedRemoteData
|
getFirstCompletedRemoteData, getFirstSucceededRemoteDataPayload
|
||||||
} from '../core/shared/operators';
|
} from '../core/shared/operators';
|
||||||
import { hasValue, isNotEmpty } from '../shared/empty.util';
|
import { hasValue, isNotEmpty } from '../shared/empty.util';
|
||||||
import { followLink } from '../shared/utils/follow-link-config.model';
|
import { followLink } from '../shared/utils/follow-link-config.model';
|
||||||
@@ -20,6 +20,7 @@ import { AuthService } from '../core/auth/auth.service';
|
|||||||
import { Operation } from 'fast-json-patch';
|
import { Operation } from 'fast-json-patch';
|
||||||
import { AuthorizationDataService } from '../core/data/feature-authorization/authorization-data.service';
|
import { AuthorizationDataService } from '../core/data/feature-authorization/authorization-data.service';
|
||||||
import { FeatureID } from '../core/data/feature-authorization/feature-id';
|
import { FeatureID } from '../core/data/feature-authorization/feature-id';
|
||||||
|
import {ConfigurationDataService} from '../core/data/configuration-data.service';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'ds-profile-page',
|
selector: 'ds-profile-page',
|
||||||
@@ -71,11 +72,14 @@ export class ProfilePageComponent implements OnInit {
|
|||||||
private currentUser: EPerson;
|
private currentUser: EPerson;
|
||||||
canChangePassword$: Observable<boolean>;
|
canChangePassword$: Observable<boolean>;
|
||||||
|
|
||||||
|
isResearcherProfileEnabled$: BehaviorSubject<boolean> = new BehaviorSubject<boolean>(false);
|
||||||
|
|
||||||
constructor(private authService: AuthService,
|
constructor(private authService: AuthService,
|
||||||
private notificationsService: NotificationsService,
|
private notificationsService: NotificationsService,
|
||||||
private translate: TranslateService,
|
private translate: TranslateService,
|
||||||
private epersonService: EPersonDataService,
|
private epersonService: EPersonDataService,
|
||||||
private authorizationService: AuthorizationDataService) {
|
private authorizationService: AuthorizationDataService,
|
||||||
|
private configurationService: ConfigurationDataService) {
|
||||||
}
|
}
|
||||||
|
|
||||||
ngOnInit(): void {
|
ngOnInit(): void {
|
||||||
@@ -88,6 +92,10 @@ export class ProfilePageComponent implements OnInit {
|
|||||||
);
|
);
|
||||||
this.groupsRD$ = this.user$.pipe(switchMap((user: EPerson) => user.groups));
|
this.groupsRD$ = this.user$.pipe(switchMap((user: EPerson) => user.groups));
|
||||||
this.canChangePassword$ = this.user$.pipe(switchMap((user: EPerson) => this.authorizationService.isAuthorized(FeatureID.CanChangePassword, user._links.self.href)));
|
this.canChangePassword$ = this.user$.pipe(switchMap((user: EPerson) => this.authorizationService.isAuthorized(FeatureID.CanChangePassword, user._links.self.href)));
|
||||||
|
|
||||||
|
this.configurationService.findByPropertyName('researcher-profile.entity-type').pipe(
|
||||||
|
getFirstSucceededRemoteDataPayload()
|
||||||
|
).subscribe(() => this.isResearcherProfileEnabled$.next(true));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -163,4 +171,9 @@ export class ProfilePageComponent implements OnInit {
|
|||||||
submit() {
|
submit() {
|
||||||
this.updateProfile();
|
this.updateProfile();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
isResearcherProfileEnabled(){
|
||||||
|
return this.isResearcherProfileEnabled$;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user