mirror of
https://github.com/DSpace/dspace-angular.git
synced 2025-10-07 10:04:11 +00:00
Merge remote-tracking branch '4Science-bitbucket/CST-5668' into CST-5307
This commit is contained in:
@@ -30,4 +30,5 @@ export enum FeatureID {
|
|||||||
CanSendFeedback = 'canSendFeedback',
|
CanSendFeedback = 'canSendFeedback',
|
||||||
ShowClaimItem = 'showClaimItem',
|
ShowClaimItem = 'showClaimItem',
|
||||||
CanClaimItem = 'canClaimItem',
|
CanClaimItem = 'canClaimItem',
|
||||||
|
CanSynchronizeWithORCID = 'canSynchronizeWithORCID'
|
||||||
}
|
}
|
||||||
|
@@ -2,7 +2,8 @@
|
|||||||
<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]="[object?.firstMetadata('person.familyName'), object?.firstMetadata('person.givenName')]" [separator]="', '"></ds-metadata-values>
|
||||||
</h2>
|
</h2>
|
||||||
<div class="pl-2 space-children-mr">
|
<div class="pl-2">
|
||||||
|
<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>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@@ -50,3 +50,4 @@ export const ITEM_EDIT_PATH = 'edit';
|
|||||||
export const ITEM_EDIT_VERSIONHISTORY_PATH = 'versionhistory';
|
export const ITEM_EDIT_VERSIONHISTORY_PATH = 'versionhistory';
|
||||||
export const ITEM_VERSION_PATH = 'version';
|
export const ITEM_VERSION_PATH = 'version';
|
||||||
export const UPLOAD_BITSTREAM_PATH = 'bitstreams/new';
|
export const UPLOAD_BITSTREAM_PATH = 'bitstreams/new';
|
||||||
|
export const ORCID_PATH = 'orcid';
|
@@ -7,7 +7,7 @@ import { VersionResolver } from './version-page/version.resolver';
|
|||||||
import { DSOBreadcrumbsService } from '../core/breadcrumbs/dso-breadcrumbs.service';
|
import { DSOBreadcrumbsService } from '../core/breadcrumbs/dso-breadcrumbs.service';
|
||||||
import { LinkService } from '../core/cache/builders/link.service';
|
import { LinkService } from '../core/cache/builders/link.service';
|
||||||
import { UploadBitstreamComponent } from './bitstreams/upload/upload-bitstream.component';
|
import { UploadBitstreamComponent } from './bitstreams/upload/upload-bitstream.component';
|
||||||
import { ITEM_EDIT_PATH, UPLOAD_BITSTREAM_PATH } from './item-page-routing-paths';
|
import { ITEM_EDIT_PATH, ORCID_PATH, UPLOAD_BITSTREAM_PATH } from './item-page-routing-paths';
|
||||||
import { ItemPageAdministratorGuard } from './item-page-administrator.guard';
|
import { ItemPageAdministratorGuard } from './item-page-administrator.guard';
|
||||||
import { LinkMenuItemModel } from '../shared/menu/menu-item/models/link.model';
|
import { LinkMenuItemModel } from '../shared/menu/menu-item/models/link.model';
|
||||||
import { ThemedItemPageComponent } from './simple/themed-item-page.component';
|
import { ThemedItemPageComponent } from './simple/themed-item-page.component';
|
||||||
@@ -16,6 +16,8 @@ import { MenuItemType } from '../shared/menu/menu-item-type.model';
|
|||||||
import { VersionPageComponent } from './version-page/version-page/version-page.component';
|
import { VersionPageComponent } from './version-page/version-page/version-page.component';
|
||||||
import { BitstreamRequestACopyPageComponent } from '../shared/bitstream-request-a-copy-page/bitstream-request-a-copy-page.component';
|
import { BitstreamRequestACopyPageComponent } from '../shared/bitstream-request-a-copy-page/bitstream-request-a-copy-page.component';
|
||||||
import { REQUEST_COPY_MODULE_PATH } from '../app-routing-paths';
|
import { REQUEST_COPY_MODULE_PATH } from '../app-routing-paths';
|
||||||
|
import { OrcidPageComponent } from './orcid-page/orcid-page.component';
|
||||||
|
import { OrcidPageGuard } from './orcid-page/orcid-page.guard';
|
||||||
|
|
||||||
@NgModule({
|
@NgModule({
|
||||||
imports: [
|
imports: [
|
||||||
@@ -50,6 +52,11 @@ import { REQUEST_COPY_MODULE_PATH } from '../app-routing-paths';
|
|||||||
{
|
{
|
||||||
path: REQUEST_COPY_MODULE_PATH,
|
path: REQUEST_COPY_MODULE_PATH,
|
||||||
component: BitstreamRequestACopyPageComponent,
|
component: BitstreamRequestACopyPageComponent,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: ORCID_PATH,
|
||||||
|
component: OrcidPageComponent,
|
||||||
|
canActivate: [OrcidPageGuard]
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
data: {
|
data: {
|
||||||
@@ -88,6 +95,7 @@ import { REQUEST_COPY_MODULE_PATH } from '../app-routing-paths';
|
|||||||
LinkService,
|
LinkService,
|
||||||
ItemPageAdministratorGuard,
|
ItemPageAdministratorGuard,
|
||||||
VersionResolver,
|
VersionResolver,
|
||||||
|
OrcidPageGuard
|
||||||
]
|
]
|
||||||
|
|
||||||
})
|
})
|
||||||
|
@@ -34,6 +34,9 @@ import { MiradorViewerComponent } from './mirador-viewer/mirador-viewer.componen
|
|||||||
import { VersionPageComponent } from './version-page/version-page/version-page.component';
|
import { VersionPageComponent } from './version-page/version-page/version-page.component';
|
||||||
import { VersionedItemComponent } from './simple/item-types/versioned-item/versioned-item.component';
|
import { VersionedItemComponent } from './simple/item-types/versioned-item/versioned-item.component';
|
||||||
import { ThemedFileSectionComponent } from './simple/field-components/file-section/themed-file-section.component';
|
import { ThemedFileSectionComponent } from './simple/field-components/file-section/themed-file-section.component';
|
||||||
|
import { OrcidAuthComponent } from './orcid-page/orcid-auth/orcid-auth.component';
|
||||||
|
import { OrcidPageComponent } from './orcid-page/orcid-page.component';
|
||||||
|
import { NgbAccordionModule } from '@ng-bootstrap/ng-bootstrap';
|
||||||
|
|
||||||
|
|
||||||
const ENTRY_COMPONENTS = [
|
const ENTRY_COMPONENTS = [
|
||||||
@@ -67,6 +70,8 @@ const DECLARATIONS = [
|
|||||||
MediaViewerImageComponent,
|
MediaViewerImageComponent,
|
||||||
MiradorViewerComponent,
|
MiradorViewerComponent,
|
||||||
VersionPageComponent,
|
VersionPageComponent,
|
||||||
|
OrcidPageComponent,
|
||||||
|
OrcidAuthComponent
|
||||||
];
|
];
|
||||||
|
|
||||||
@NgModule({
|
@NgModule({
|
||||||
@@ -79,6 +84,7 @@ const DECLARATIONS = [
|
|||||||
JournalEntitiesModule.withEntryComponents(),
|
JournalEntitiesModule.withEntryComponents(),
|
||||||
ResearchEntitiesModule.withEntryComponents(),
|
ResearchEntitiesModule.withEntryComponents(),
|
||||||
NgxGalleryModule,
|
NgxGalleryModule,
|
||||||
|
NgbAccordionModule
|
||||||
],
|
],
|
||||||
declarations: [
|
declarations: [
|
||||||
...DECLARATIONS,
|
...DECLARATIONS,
|
||||||
|
@@ -0,0 +1,71 @@
|
|||||||
|
<div class="container custom-accordion mb-4">
|
||||||
|
<ngb-accordion activeIds="auth">
|
||||||
|
<ngb-panel title="{{'person.orcid.registry.auth' | translate}}" id="auth">
|
||||||
|
<ng-template ngbPanelContent>
|
||||||
|
<div class="container">
|
||||||
|
<ng-container *ngIf="isLinkedToOrcid(); then orcidLinked; else orcidNotLinked"></ng-container>
|
||||||
|
</div>
|
||||||
|
</ng-template>
|
||||||
|
</ngb-panel>
|
||||||
|
</ngb-accordion>
|
||||||
|
|
||||||
|
<ng-template #orcidLinked>
|
||||||
|
<div class="row mt-3">
|
||||||
|
<div *ngIf="getOrcidAuthorizations().length > 0" class="card m-2 col-md p-0">
|
||||||
|
<div class="card-header">{{ 'person.page.orcid.granted-authorizations'| translate }}</div>
|
||||||
|
<div class="card-body">
|
||||||
|
<div class="container">
|
||||||
|
<ul>
|
||||||
|
<li *ngFor="let auth of getOrcidAuthorizations()"> {{getAuthorizationDescription(auth) | translate}} </li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="card m-2 col-md p-0">
|
||||||
|
<div class="card-header">{{ 'person.page.orcid.missing-authorizations'| translate }}</div>
|
||||||
|
<div class="card-body">
|
||||||
|
<div class="container">
|
||||||
|
<div *ngIf="( missingAuthorizations$ | async ).length === 0" class="p-3 mb-2 alert alert-success rounded">
|
||||||
|
{{'person.page.orcid.no-missing-authorizations-message' | translate}}
|
||||||
|
</div>
|
||||||
|
<div *ngIf="( missingAuthorizations$ | async ).length > 0" class="p-3 mb-2 alert alert-warning rounded" >
|
||||||
|
{{'person.page.orcid.missing-authorizations-message' | translate}}
|
||||||
|
<ul>
|
||||||
|
<li *ngFor="let auth of ( ( missingAuthorizations$ | async ) )"> {{getAuthorizationDescription(auth) | translate }} </li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div *ngIf="(onlyAdminCanDisconnectProfileFromOrcid() | async)" class="row mt-3 p-3 mb-2 bg-info text-white rounded d-flex justify-content-center">
|
||||||
|
{{ 'person.page.orcid.remove-orcid-message' | translate}}
|
||||||
|
</div>
|
||||||
|
<div class="row" *ngIf="(ownerCanDisconnectProfileFromOrcid() | async)">
|
||||||
|
<div class="col-md">
|
||||||
|
<button type="submit" class="btn btn-danger float-right m-2" (click)="unlinkOrcid()" [disabled]=unlinkProcessing>
|
||||||
|
<span *ngIf="!unlinkProcessing"><i class="fas fa-unlink"></i> {{ 'person.page.orcid.unlink' | translate }}</span>
|
||||||
|
<span *ngIf="unlinkProcessing"><i class='fas fa-circle-notch fa-spin'></i> {{'person.page.orcid.unlink.processing' | translate}}</span>
|
||||||
|
</button>
|
||||||
|
<button *ngIf="( missingAuthorizations$ | async ).length > 0" type="submit" class="btn btn-primary float-right m-2" (click)="linkOrcid()">
|
||||||
|
<span><i class="fas fa-check"></i> {{ 'person.page.orcid.grant-authorizations' | translate }}</span>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</ng-template>
|
||||||
|
|
||||||
|
<ng-template #orcidNotLinked>
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-2"><img alt="orcid-logo" src="../../../../assets/images/orcid.logo.icon.svg"/></div>
|
||||||
|
<div class="alert alert-info col">{{ getOrcidNotLinkedMessage() | async }}</div>
|
||||||
|
</div>
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-md">
|
||||||
|
<button class="btn btn-primary float-right" (click)="linkOrcid()">
|
||||||
|
<i class="fas fa-link"></i>
|
||||||
|
{{'person.page.orcid.link' | translate}}
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</ng-template>
|
||||||
|
</div>
|
@@ -0,0 +1,98 @@
|
|||||||
|
import { Component, Inject, OnInit } from '@angular/core';
|
||||||
|
import { ActivatedRoute } from '@angular/router';
|
||||||
|
import { TranslateService } from '@ngx-translate/core';
|
||||||
|
import { BehaviorSubject, Observable } from 'rxjs';
|
||||||
|
import { map } from 'rxjs/operators';
|
||||||
|
import { ConfigurationDataService } from '../../../core/data/configuration-data.service';
|
||||||
|
import { ItemDataService } from '../../../core/data/item-data.service';
|
||||||
|
import { RemoteData } from '../../../core/data/remote-data';
|
||||||
|
import { ResearcherProfileService } from '../../../core/profile/researcher-profile.service';
|
||||||
|
import { NativeWindowRef, NativeWindowService } from '../../../core/services/window.service';
|
||||||
|
import { Item } from '../../../core/shared/item.model';
|
||||||
|
import { getFirstCompletedRemoteData, getFirstSucceededRemoteDataPayload } from '../../../core/shared/operators';
|
||||||
|
import { NotificationsService } from '../../../shared/notifications/notifications.service';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'ds-orcid-auth',
|
||||||
|
templateUrl: './orcid-auth.component.html',
|
||||||
|
styleUrls: ['./orcid-auth.component.scss']
|
||||||
|
})
|
||||||
|
export class OrcidAuthComponent implements OnInit {
|
||||||
|
|
||||||
|
missingAuthorizations$ = new BehaviorSubject<string[]>([]);
|
||||||
|
|
||||||
|
unlinkProcessing = false;
|
||||||
|
|
||||||
|
item: Item
|
||||||
|
|
||||||
|
constructor(
|
||||||
|
private configurationService: ConfigurationDataService,
|
||||||
|
private researcherProfileService: ResearcherProfileService,
|
||||||
|
protected translateService: TranslateService,
|
||||||
|
private notificationsService: NotificationsService,
|
||||||
|
private itemService: ItemDataService,
|
||||||
|
private route: ActivatedRoute,
|
||||||
|
@Inject(NativeWindowService) private _window: NativeWindowRef,
|
||||||
|
) {
|
||||||
|
this.itemService.findById(this.route.snapshot.paramMap.get('id'), true, true).pipe(getFirstCompletedRemoteData()).subscribe((data: RemoteData<Item>) => {
|
||||||
|
this.item = data.payload;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
ngOnInit() {
|
||||||
|
const scopes = this.getOrcidAuthorizations();
|
||||||
|
return this.configurationService.findByPropertyName('orcid.scope')
|
||||||
|
.pipe(getFirstSucceededRemoteDataPayload(),
|
||||||
|
map((configurationProperty) => configurationProperty.values),
|
||||||
|
map((allScopes) => allScopes.filter((scope) => !scopes.includes(scope))))
|
||||||
|
.subscribe((missingScopes) => this.missingAuthorizations$.next(missingScopes));
|
||||||
|
}
|
||||||
|
|
||||||
|
getOrcidAuthorizations(): string[] {
|
||||||
|
return this.item.allMetadataValues('cris.orcid.scope');
|
||||||
|
}
|
||||||
|
|
||||||
|
isLinkedToOrcid(): boolean {
|
||||||
|
return this.researcherProfileService.isLinkedToOrcid(this.item);
|
||||||
|
}
|
||||||
|
|
||||||
|
getOrcidNotLinkedMessage(): Observable<string> {
|
||||||
|
const orcid = this.item.firstMetadataValue('person.identifier.orcid');
|
||||||
|
if (orcid) {
|
||||||
|
return this.translateService.get('person.page.orcid.orcid-not-linked-message', { 'orcid': orcid });
|
||||||
|
} else {
|
||||||
|
return this.translateService.get('person.page.orcid.no-orcid-message');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
getAuthorizationDescription(scope: string) {
|
||||||
|
return 'person.page.orcid.scope.' + scope.substring(1).replace('/', '-');
|
||||||
|
}
|
||||||
|
|
||||||
|
onlyAdminCanDisconnectProfileFromOrcid(): Observable<boolean> {
|
||||||
|
return this.researcherProfileService.onlyAdminCanDisconnectProfileFromOrcid();
|
||||||
|
}
|
||||||
|
|
||||||
|
ownerCanDisconnectProfileFromOrcid(): Observable<boolean> {
|
||||||
|
return this.researcherProfileService.ownerCanDisconnectProfileFromOrcid();
|
||||||
|
}
|
||||||
|
|
||||||
|
linkOrcid(): void {
|
||||||
|
this.researcherProfileService.getOrcidAuthorizeUrl(this.item).subscribe((authorizeUrl) => {
|
||||||
|
this._window.nativeWindow.location.href = authorizeUrl;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
unlinkOrcid(): void {
|
||||||
|
this.unlinkProcessing = true;
|
||||||
|
this.researcherProfileService.unlinkOrcid(this.item).subscribe((remoteData) => {
|
||||||
|
this.unlinkProcessing = false;
|
||||||
|
if (remoteData.isSuccess) {
|
||||||
|
this.notificationsService.success(this.translateService.get('person.page.orcid.unlink.success'));
|
||||||
|
} else {
|
||||||
|
this.notificationsService.error(this.translateService.get('person.page.orcid.unlink.error'));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
1
src/app/item-page/orcid-page/orcid-page.component.html
Normal file
1
src/app/item-page/orcid-page/orcid-page.component.html
Normal file
@@ -0,0 +1 @@
|
|||||||
|
<ds-orcid-auth></ds-orcid-auth>
|
9
src/app/item-page/orcid-page/orcid-page.component.ts
Normal file
9
src/app/item-page/orcid-page/orcid-page.component.ts
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
import { Component } from '@angular/core';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'ds-orcid-page',
|
||||||
|
templateUrl: './orcid-page.component.html',
|
||||||
|
styleUrls: ['./orcid-page.component.scss']
|
||||||
|
})
|
||||||
|
export class OrcidPageComponent {
|
||||||
|
}
|
31
src/app/item-page/orcid-page/orcid-page.guard.ts
Normal file
31
src/app/item-page/orcid-page/orcid-page.guard.ts
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
import { Injectable } from '@angular/core';
|
||||||
|
import { ActivatedRouteSnapshot, Router, RouterStateSnapshot } from '@angular/router';
|
||||||
|
import { Observable, of as observableOf } from 'rxjs';
|
||||||
|
import { AuthService } from '../../core/auth/auth.service';
|
||||||
|
import { AuthorizationDataService } from '../../core/data/feature-authorization/authorization-data.service';
|
||||||
|
import { DsoPageSingleFeatureGuard } from '../../core/data/feature-authorization/feature-authorization-guard/dso-page-single-feature.guard';
|
||||||
|
import { FeatureID } from '../../core/data/feature-authorization/feature-id';
|
||||||
|
import { Item } from '../../core/shared/item.model';
|
||||||
|
import { ItemPageResolver } from '../item-page.resolver';
|
||||||
|
|
||||||
|
@Injectable({
|
||||||
|
providedIn: 'root'
|
||||||
|
})
|
||||||
|
/**
|
||||||
|
* Guard for preventing unauthorized access to certain {@link Item} pages requiring administrator rights
|
||||||
|
*/
|
||||||
|
export class OrcidPageGuard extends DsoPageSingleFeatureGuard<Item> {
|
||||||
|
constructor(protected resolver: ItemPageResolver,
|
||||||
|
protected authorizationService: AuthorizationDataService,
|
||||||
|
protected router: Router,
|
||||||
|
protected authService: AuthService) {
|
||||||
|
super(resolver, authorizationService, router, authService);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check administrator authorization rights
|
||||||
|
*/
|
||||||
|
getFeatureID(next: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable<FeatureID> {
|
||||||
|
return observableOf(FeatureID.CanSynchronizeWithORCID);
|
||||||
|
}
|
||||||
|
}
|
@@ -0,0 +1,5 @@
|
|||||||
|
<a *ngIf="isAuthorized | async"
|
||||||
|
[routerLink]="[pageRoute, 'orcid']"
|
||||||
|
class="btn btn-dark btn-sm"
|
||||||
|
role="button" >ORCID
|
||||||
|
</a>
|
@@ -0,0 +1,76 @@
|
|||||||
|
import { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing';
|
||||||
|
import { DSpaceObject } from '../../../core/shared/dspace-object.model';
|
||||||
|
import { Item } from '../../../core/shared/item.model';
|
||||||
|
import { AuthorizationDataService } from '../../../core/data/feature-authorization/authorization-data.service';
|
||||||
|
import { of as observableOf } from 'rxjs';
|
||||||
|
import { TranslateModule } from '@ngx-translate/core';
|
||||||
|
import { RouterTestingModule } from '@angular/router/testing';
|
||||||
|
import { FeatureID } from '../../../core/data/feature-authorization/feature-id';
|
||||||
|
import { By } from '@angular/platform-browser';
|
||||||
|
import { NgbModule } from '@ng-bootstrap/ng-bootstrap';
|
||||||
|
import { DsoPageOrcidButtonComponent } from './dso-page-orcid-button.component';
|
||||||
|
|
||||||
|
describe('DsoPageOrcidButtonComponent', () => {
|
||||||
|
let component: DsoPageOrcidButtonComponent;
|
||||||
|
let fixture: ComponentFixture<DsoPageOrcidButtonComponent>;
|
||||||
|
|
||||||
|
let authorizationService: AuthorizationDataService;
|
||||||
|
let dso: DSpaceObject;
|
||||||
|
|
||||||
|
beforeEach(waitForAsync(() => {
|
||||||
|
dso = Object.assign(new Item(), {
|
||||||
|
id: 'test-item',
|
||||||
|
_links: {
|
||||||
|
self: { href: 'test-item-selflink' }
|
||||||
|
}
|
||||||
|
});
|
||||||
|
authorizationService = jasmine.createSpyObj('authorizationService', {
|
||||||
|
isAuthorized: observableOf(true)
|
||||||
|
});
|
||||||
|
TestBed.configureTestingModule({
|
||||||
|
declarations: [DsoPageOrcidButtonComponent],
|
||||||
|
imports: [TranslateModule.forRoot(), RouterTestingModule.withRoutes([]), NgbModule],
|
||||||
|
providers: [
|
||||||
|
{ provide: AuthorizationDataService, useValue: authorizationService }
|
||||||
|
]
|
||||||
|
}).compileComponents();
|
||||||
|
}));
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
fixture = TestBed.createComponent(DsoPageOrcidButtonComponent);
|
||||||
|
component = fixture.componentInstance;
|
||||||
|
component.dso = dso;
|
||||||
|
component.pageRoute = 'test';
|
||||||
|
fixture.detectChanges();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should check the authorization of the current user', () => {
|
||||||
|
expect(authorizationService.isAuthorized).toHaveBeenCalledWith(FeatureID.CanEditOrcid, dso.self);
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('when the user is authorized', () => {
|
||||||
|
beforeEach(() => {
|
||||||
|
(authorizationService.isAuthorized as jasmine.Spy).and.returnValue(observableOf(true));
|
||||||
|
component.ngOnInit();
|
||||||
|
fixture.detectChanges();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should render a link', () => {
|
||||||
|
const link = fixture.debugElement.query(By.css('a'));
|
||||||
|
expect(link).not.toBeNull();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('when the user is not authorized', () => {
|
||||||
|
beforeEach(() => {
|
||||||
|
(authorizationService.isAuthorized as jasmine.Spy).and.returnValue(observableOf(false));
|
||||||
|
component.ngOnInit();
|
||||||
|
fixture.detectChanges();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should not render a link', () => {
|
||||||
|
const link = fixture.debugElement.query(By.css('a'));
|
||||||
|
expect(link).toBeNull();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
@@ -0,0 +1,43 @@
|
|||||||
|
import { Component, Input, OnInit } from '@angular/core';
|
||||||
|
import { BehaviorSubject } from 'rxjs';
|
||||||
|
import { take } from 'rxjs/operators';
|
||||||
|
import { AuthorizationDataService } from 'src/app/core/data/feature-authorization/authorization-data.service';
|
||||||
|
import { FeatureID } from 'src/app/core/data/feature-authorization/feature-id';
|
||||||
|
import { DSpaceObject } from 'src/app/core/shared/dspace-object.model';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'ds-dso-page-orcid-button',
|
||||||
|
templateUrl: './dso-page-orcid-button.component.html',
|
||||||
|
styleUrls: ['./dso-page-orcid-button.component.scss']
|
||||||
|
})
|
||||||
|
export class DsoPageOrcidButtonComponent implements OnInit {
|
||||||
|
/**
|
||||||
|
* The DSpaceObject to display a button to the edit page for
|
||||||
|
*/
|
||||||
|
@Input() dso: DSpaceObject;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The prefix of the route to the edit page (before the object's UUID, e.g. "items")
|
||||||
|
*/
|
||||||
|
@Input() pageRoute: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A message for the tooltip on the button
|
||||||
|
* Supports i18n keys
|
||||||
|
*/
|
||||||
|
@Input() tooltipMsg: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Whether or not the current user is authorized to edit the DSpaceObject
|
||||||
|
*/
|
||||||
|
isAuthorized: BehaviorSubject<boolean> = new BehaviorSubject(false);
|
||||||
|
|
||||||
|
constructor(protected authorizationService: AuthorizationDataService) { }
|
||||||
|
|
||||||
|
ngOnInit() {
|
||||||
|
this.authorizationService.isAuthorized(FeatureID.CanSynchronizeWithORCID, this.dso.self).pipe(take(1)).subscribe((isAuthorized: boolean) => {
|
||||||
|
this.isAuthorized.next(isAuthorized);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@@ -174,6 +174,7 @@ import { LogInOidcComponent } from './log-in/methods/oidc/log-in-oidc.component'
|
|||||||
import { ThemedItemListPreviewComponent } from './object-list/my-dspace-result-list-element/item-list-preview/themed-item-list-preview.component';
|
import { ThemedItemListPreviewComponent } from './object-list/my-dspace-result-list-element/item-list-preview/themed-item-list-preview.component';
|
||||||
import { ClaimItemSelectorComponent } from './dso-selector/modal-wrappers/claim-item-selector/claim-item-selector.component';
|
import { ClaimItemSelectorComponent } from './dso-selector/modal-wrappers/claim-item-selector/claim-item-selector.component';
|
||||||
import { ExternalLinkMenuItemComponent } from './menu/menu-item/external-link-menu-item.component';
|
import { ExternalLinkMenuItemComponent } from './menu/menu-item/external-link-menu-item.component';
|
||||||
|
import { DsoPageOrcidButtonComponent } from './dso-page/dso-page-orcid-button/dso-page-orcid-button.component';
|
||||||
|
|
||||||
const MODULES = [
|
const MODULES = [
|
||||||
// Do NOT include UniversalModule, HttpModule, or JsonpModule here
|
// Do NOT include UniversalModule, HttpModule, or JsonpModule here
|
||||||
@@ -414,6 +415,7 @@ const SHARED_ITEM_PAGE_COMPONENTS = [
|
|||||||
GenericItemPageFieldComponent,
|
GenericItemPageFieldComponent,
|
||||||
MetadataRepresentationListComponent,
|
MetadataRepresentationListComponent,
|
||||||
RelatedItemsComponent,
|
RelatedItemsComponent,
|
||||||
|
DsoPageOrcidButtonComponent
|
||||||
|
|
||||||
];
|
];
|
||||||
|
|
||||||
|
@@ -4212,4 +4212,195 @@
|
|||||||
"researcherprofile.success.claim.body" : "Profile claimed with success",
|
"researcherprofile.success.claim.body" : "Profile claimed with success",
|
||||||
|
|
||||||
"researcherprofile.success.claim.title" : "Success",
|
"researcherprofile.success.claim.title" : "Success",
|
||||||
|
|
||||||
|
"person.page.orcid": "ORCID",
|
||||||
|
|
||||||
|
"person.page.orcid.create": "Create an ORCID ID",
|
||||||
|
|
||||||
|
"person.page.orcid.granted-authorizations": "Granted authorizations",
|
||||||
|
|
||||||
|
"person.page.orcid.grant-authorizations" : "Grant authorizations",
|
||||||
|
|
||||||
|
"person.page.orcid.link": "Connect to ORCID ID",
|
||||||
|
|
||||||
|
"person.page.orcid.orcid-not-linked-message": "The ORCID iD of this profile ({{ orcid }}) has not yet been connected to an account on the ORCID registry or the connection is expired.",
|
||||||
|
|
||||||
|
"person.page.orcid.unlink": "Disconnect from ORCID",
|
||||||
|
|
||||||
|
"person.page.orcid.unlink.processing": "Processing...",
|
||||||
|
|
||||||
|
"person.page.orcid.missing-authorizations": "Missing authorizations",
|
||||||
|
|
||||||
|
"person.page.orcid.missing-authorizations-message": "The following authorizations are missing:",
|
||||||
|
|
||||||
|
"person.page.orcid.no-missing-authorizations-message": "Great! This box is empty, so you have granted all access rights to use all functions offers by your institution.",
|
||||||
|
|
||||||
|
"person.page.orcid.no-orcid-message": "No ORCID iD associated yet. By clicking on the button below it is possible to link this profile with an ORCID account.",
|
||||||
|
|
||||||
|
"person.page.orcid.profile-preferences": "Profile preferences",
|
||||||
|
|
||||||
|
"person.page.orcid.funding-preferences": "Funding preferences",
|
||||||
|
|
||||||
|
"person.page.orcid.publications-preferences": "Publication preferences",
|
||||||
|
|
||||||
|
"person.page.orcid.remove-orcid-message": "If you need to remove your ORCID, please contact the repository administrator",
|
||||||
|
|
||||||
|
"person.page.orcid.save.preference.changes": "Update settings",
|
||||||
|
|
||||||
|
"person.page.orcid.sync-profile.affiliation" : "Affiliation",
|
||||||
|
|
||||||
|
"person.page.orcid.sync-profile.biographical" : "Biographical data",
|
||||||
|
|
||||||
|
"person.page.orcid.sync-profile.education" : "Education",
|
||||||
|
|
||||||
|
"person.page.orcid.sync-profile.identifiers" : "Identifiers",
|
||||||
|
|
||||||
|
"person.page.orcid.sync-fundings.all" : "All fundings",
|
||||||
|
|
||||||
|
"person.page.orcid.sync-fundings.mine" : "My fundings",
|
||||||
|
|
||||||
|
"person.page.orcid.sync-fundings.my_selected" : "Selected fundings",
|
||||||
|
|
||||||
|
"person.page.orcid.sync-fundings.disabled" : "Disabled",
|
||||||
|
|
||||||
|
"person.page.orcid.sync-publications.all" : "All publications",
|
||||||
|
|
||||||
|
"person.page.orcid.sync-publications.mine" : "My publications",
|
||||||
|
|
||||||
|
"person.page.orcid.sync-publications.my_selected" : "Selected publications",
|
||||||
|
|
||||||
|
"person.page.orcid.sync-publications.disabled" : "Disabled",
|
||||||
|
|
||||||
|
"person.page.orcid.sync-queue.discard" : "Discard the change and do not synchronize with the ORCID registry",
|
||||||
|
|
||||||
|
"person.page.orcid.sync-queue.discard.error": "The discarding of the ORCID queue record failed",
|
||||||
|
|
||||||
|
"person.page.orcid.sync-queue.discard.success": "The ORCID queue record have been discarded successfully",
|
||||||
|
|
||||||
|
"person.page.orcid.sync-queue.empty-message": "The ORCID queue registry is empty",
|
||||||
|
|
||||||
|
"person.page.orcid.sync-queue.description" : "Description",
|
||||||
|
|
||||||
|
"person.page.orcid.sync-queue.description.affiliation": "Affiliations",
|
||||||
|
|
||||||
|
"person.page.orcid.sync-queue.description.country": "Country",
|
||||||
|
|
||||||
|
"person.page.orcid.sync-queue.description.education": "Educations",
|
||||||
|
|
||||||
|
"person.page.orcid.sync-queue.description.external_ids": "External ids",
|
||||||
|
|
||||||
|
"person.page.orcid.sync-queue.description.other_names": "Other names",
|
||||||
|
|
||||||
|
"person.page.orcid.sync-queue.description.qualification": "Qualifications",
|
||||||
|
|
||||||
|
"person.page.orcid.sync-queue.description.researcher_urls": "Researcher urls",
|
||||||
|
|
||||||
|
"person.page.orcid.sync-queue.description.keywords": "Keywords",
|
||||||
|
|
||||||
|
"person.page.orcid.sync-queue.tooltip.insert": "Add a new entry in the ORCID registry",
|
||||||
|
|
||||||
|
"person.page.orcid.sync-queue.tooltip.update": "Update this entry on the ORCID registry",
|
||||||
|
|
||||||
|
"person.page.orcid.sync-queue.tooltip.delete": "Remove this entry from the ORCID registry",
|
||||||
|
|
||||||
|
"person.page.orcid.sync-queue.tooltip.publication": "Publication",
|
||||||
|
|
||||||
|
"person.page.orcid.sync-queue.tooltip.funding": "Funding",
|
||||||
|
|
||||||
|
"person.page.orcid.sync-queue.tooltip.affiliation": "Affiliation",
|
||||||
|
|
||||||
|
"person.page.orcid.sync-queue.tooltip.education": "Education",
|
||||||
|
|
||||||
|
"person.page.orcid.sync-queue.tooltip.qualification": "Qualification",
|
||||||
|
|
||||||
|
"person.page.orcid.sync-queue.tooltip.other_names": "Other name",
|
||||||
|
|
||||||
|
"person.page.orcid.sync-queue.tooltip.country": "Country",
|
||||||
|
|
||||||
|
"person.page.orcid.sync-queue.tooltip.keywords": "Keyword",
|
||||||
|
|
||||||
|
"person.page.orcid.sync-queue.tooltip.external_ids": "External identifier",
|
||||||
|
|
||||||
|
"person.page.orcid.sync-queue.tooltip.researcher_urls": "Researcher url",
|
||||||
|
|
||||||
|
"person.page.orcid.sync-queue.send" : "Synchronize with ORCID registry",
|
||||||
|
|
||||||
|
"person.page.orcid.sync-queue.send.unauthorized-error.title": "The submission to ORCID failed for missing authorizations.",
|
||||||
|
|
||||||
|
"person.page.orcid.sync-queue.send.unauthorized-error.content": "Click <a href='{{orcid}}'>here</a> to grant again the required permissions. If the problem persists, contact the administrator",
|
||||||
|
|
||||||
|
"person.page.orcid.sync-queue.send.bad-request-error": "The submission to ORCID failed because the resource sent to ORCID registry is not valid",
|
||||||
|
|
||||||
|
"person.page.orcid.sync-queue.send.error": "The submission to ORCID failed",
|
||||||
|
|
||||||
|
"person.page.orcid.sync-queue.send.conflict-error": "The submission to ORCID failed because the resource is already present on the ORCID registry",
|
||||||
|
|
||||||
|
"person.page.orcid.sync-queue.send.not-found-warning": "The resource does not exists anymore on the ORCID registry.",
|
||||||
|
|
||||||
|
"person.page.orcid.sync-queue.send.success": "The submission to ORCID was completed successfully",
|
||||||
|
|
||||||
|
"person.page.orcid.sync-queue.send.validation-error": "The data that you want to synchronize with ORCID is not valid",
|
||||||
|
|
||||||
|
"person.page.orcid.sync-queue.send.validation-error.amount-currency.required": "The amount's currency is required",
|
||||||
|
|
||||||
|
"person.page.orcid.sync-queue.send.validation-error.external-id.required": "The resource to be sent requires at least one identifier",
|
||||||
|
|
||||||
|
"person.page.orcid.sync-queue.send.validation-error.title.required": "The title is required",
|
||||||
|
|
||||||
|
"person.page.orcid.sync-queue.send.validation-error.type.required": "The type is required",
|
||||||
|
|
||||||
|
"person.page.orcid.sync-queue.send.validation-error.start-date.required": "The start date is required",
|
||||||
|
|
||||||
|
"person.page.orcid.sync-queue.send.validation-error.funder.required": "The funder is required",
|
||||||
|
|
||||||
|
"person.page.orcid.sync-queue.send.validation-error.organization.required": "The organization is required",
|
||||||
|
|
||||||
|
"person.page.orcid.sync-queue.send.validation-error.organization.name-required": "The organization's name is required",
|
||||||
|
|
||||||
|
"person.page.orcid.sync-queue.send.validation-error.organization.address-required": "The organization to be sent requires an address",
|
||||||
|
|
||||||
|
"person.page.orcid.sync-queue.send.validation-error.organization.city-required": "The address of the organization to be sent requires a city",
|
||||||
|
|
||||||
|
"person.page.orcid.sync-queue.send.validation-error.organization.country-required": "The address of the organization to be sent requires a country",
|
||||||
|
|
||||||
|
"person.page.orcid.sync-queue.send.validation-error.disambiguated-organization.required": "An identifier to disambiguate organizations is required. Supported ids are GRID, Ringgold, Legal Entity identifiers (LEIs) and Crossref Funder Registry identifiers",
|
||||||
|
|
||||||
|
"person.page.orcid.sync-queue.send.validation-error.disambiguated-organization.value-required": "The organization's identifiers requires a value",
|
||||||
|
|
||||||
|
"person.page.orcid.sync-queue.send.validation-error.disambiguation-source.required": "The organization's identifiers requires a source",
|
||||||
|
|
||||||
|
"person.page.orcid.sync-queue.send.validation-error.disambiguation-source.invalid": "The source of one of the organization identifiers is invalid. Supported sources are RINGGOLD, GRID, LEI and FUNDREF",
|
||||||
|
|
||||||
|
"person.page.orcid.synchronization-mode": "Synchronization mode",
|
||||||
|
|
||||||
|
"person.page.orcid.synchronization-mode.batch": "Batch",
|
||||||
|
|
||||||
|
"person.page.orcid.synchronization-mode.label": "Synchronization mode",
|
||||||
|
|
||||||
|
"person.page.orcid.synchronization-mode-message": "Enable 'Manual' Synchronization mode to disable batch synchronization, so you must send your data to ORCID Registry manually",
|
||||||
|
|
||||||
|
"person.page.orcid.synchronization-settings-update.success": "The synchronization settings have been updated successfully",
|
||||||
|
|
||||||
|
"person.page.orcid.synchronization-settings-update.error": "The update of the synchronization settings failed",
|
||||||
|
|
||||||
|
"person.page.orcid.synchronization-mode.manual": "Manual",
|
||||||
|
|
||||||
|
"person.page.orcid.scope.authenticate": "Get your ORCID iD",
|
||||||
|
|
||||||
|
"person.page.orcid.scope.read-limited": "Read your information with visibility set to Trusted Parties",
|
||||||
|
|
||||||
|
"person.page.orcid.scope.activities-update": "Add/update your research activities",
|
||||||
|
|
||||||
|
"person.page.orcid.scope.person-update": "Add/update other information about you",
|
||||||
|
|
||||||
|
"person.page.orcid.unlink.success": "The disconnection between the profile and the ORCID registry was successful",
|
||||||
|
|
||||||
|
"person.page.orcid.unlink.error": "An error occurred while disconnecting between the profile and the ORCID registry. Try again",
|
||||||
|
|
||||||
|
"person.orcid.sync.setting": "ORCID Synchronization settings",
|
||||||
|
|
||||||
|
"person.orcid.registry.queue": "ORCID Registry Queue",
|
||||||
|
|
||||||
|
"person.orcid.registry.auth": "ORCID Authorizations",
|
||||||
|
|
||||||
}
|
}
|
||||||
|
21
src/assets/images/orcid.logo.icon.svg
Normal file
21
src/assets/images/orcid.logo.icon.svg
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<svg width="72px" height="72px" viewBox="0 0 72 72" version="1.1"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||||
|
<!-- Generator: sketchtool 53.1 (72631) - https://sketchapp.com -->
|
||||||
|
<title>Orcid logo</title>
|
||||||
|
<g id="Symbols" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
|
||||||
|
<g id="hero" transform="translate(-924.000000, -72.000000)" fill-rule="nonzero">
|
||||||
|
<g id="Group-4">
|
||||||
|
<g id="vector_iD_icon" transform="translate(924.000000, 72.000000)">
|
||||||
|
<path d="M72,36 C72,55.884375 55.884375,72 36,72 C16.115625,72 0,55.884375 0,36 C0,16.115625 16.115625,0 36,0 C55.884375,0 72,16.115625 72,36 Z" id="Path" fill="#A6CE39"></path>
|
||||||
|
<g id="Group" transform="translate(18.868966, 12.910345)" fill="#FFFFFF">
|
||||||
|
<polygon id="Path" points="5.03734929 39.1250878 0.695429861 39.1250878 0.695429861 9.14431787 5.03734929 9.14431787 5.03734929 22.6930505 5.03734929 39.1250878"></polygon>
|
||||||
|
<path d="M11.409257,9.14431787 L23.1380784,9.14431787 C34.303014,9.14431787 39.2088191,17.0664074 39.2088191,24.1486995 C39.2088191,31.846843 33.1470485,39.1530811 23.1944669,39.1530811 L11.409257,39.1530811 L11.409257,9.14431787 Z M15.7511765,35.2620194 L22.6587756,35.2620194 C32.49858,35.2620194 34.7541226,27.8438084 34.7541226,24.1486995 C34.7541226,18.1301509 30.8915059,13.0353795 22.4332213,13.0353795 L15.7511765,13.0353795 L15.7511765,35.2620194 Z" id="Shape"></path>
|
||||||
|
<path d="M5.71401206,2.90182329 C5.71401206,4.441452 4.44526937,5.72914146 2.86638958,5.72914146 C1.28750978,5.72914146 0.0187670918,4.441452 0.0187670918,2.90182329 C0.0187670918,1.33420133 1.28750978,0.0745051096 2.86638958,0.0745051096 C4.44526937,0.0745051096 5.71401206,1.36219458 5.71401206,2.90182329 Z" id="Path"></path>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
</svg>
|
After Width: | Height: | Size: 2.0 KiB |
@@ -115,3 +115,14 @@ ngb-modal-backdrop {
|
|||||||
.ml-gap {
|
.ml-gap {
|
||||||
margin-left: var(--ds-gap);
|
margin-left: var(--ds-gap);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.custom-accordion .card-header button {
|
||||||
|
-webkit-box-shadow: none!important;
|
||||||
|
box-shadow: none!important;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
.custom-accordion .card:first-of-type {
|
||||||
|
border-bottom: var(--bs-card-border-width) solid var(--bs-card-border-color)!important;
|
||||||
|
border-bottom-left-radius: var(--bs-card-border-radius)!important;
|
||||||
|
border-bottom-right-radius: var(--bs-card-border-radius)!important;
|
||||||
|
}
|
||||||
|
Reference in New Issue
Block a user