diff --git a/src/app/cdk/side-bar/side-bar/side-bar.component.html b/src/app/cdk/side-bar/side-bar/side-bar.component.html index 007bf37dd5..e77d2b2d60 100644 --- a/src/app/cdk/side-bar/side-bar/side-bar.component.html +++ b/src/app/cdk/side-bar/side-bar/side-bar.component.html @@ -4,17 +4,22 @@ [attr.aria-label]="regionPersonalInformation" *ngIf="!hideOrcidId || !orcidId" > -

+

Personal information

- + + + { - if (!this.orcidId && userRecord?.userInfo?.RECORD_WITH_ISSUES) { + this.recordWithIssues = userRecord?.userInfo?.RECORD_WITH_ISSUES + if (!this.orcidId && this.recordWithIssues) { this.orcidId = true } this.userRecord = userRecord diff --git a/src/app/record/components/record-header/record-header.component.html b/src/app/record/components/record-header/record-header.component.html new file mode 100644 index 0000000000..a12397cf21 --- /dev/null +++ b/src/app/record/components/record-header/record-header.component.html @@ -0,0 +1,79 @@ + +
+
+
+
+

+ {{ creditName }} + + {{ givenNames + ' ' }} + {{ familyName }} + +

+
+
+

{{ otherNames }}

+
+
+
+

+ This record has been deactivated + + This record is locked + + This record has been + deprecated +

+
+
+

+ No public information available. + +

+
+
+ +
+
+
+
+ +
+

{{ orcidId }}

+
+ + +
+
+
+
+
diff --git a/src/app/record/components/record-header/record-header.component.scss b/src/app/record/components/record-header/record-header.component.scss new file mode 100644 index 0000000000..53512d7485 --- /dev/null +++ b/src/app/record/components/record-header/record-header.component.scss @@ -0,0 +1,75 @@ +.record-header { + display: flex; + box-sizing: border-box; + width: 100%; + padding: 32px; + margin-bottom: 32px; + align-items: flex-start; + gap: 16px; + word-break: break-all; + + h1,p { + margin: 0; + } + + h2 { + margin: auto; + font-weight: normal; + } + + .divider { + width: 100%; + height: 2px; + } + + .names-wrapper { + .names { + line-height: 40px; + } + + .other-names { + line-height: 24px; + } + + .other-names.mobile { + justify-content: center; + } + } + + .issue { + h1 { + font-weight: normal; + } + } + + .id-wrapper { + align-items: center; + + .col { + padding: 0 !important + } + + .orcid-logo { + width: 40px; + margin-right: 8px; + } + + .orcid-logo.mobile { + width: 32px; + } + + .buttons-wrapper { + margin-left: 16px; + } + + .buttons-wrapper.mobile { + justify-content: center; + margin-left: 0; + } + } +} + +.record-header.mobile { + justify-content: center; + padding: 18px; +} diff --git a/src/app/record/components/record-header/record-header.component.scss-theme.scss b/src/app/record/components/record-header/record-header.component.scss-theme.scss new file mode 100644 index 0000000000..0e7a8e58b5 --- /dev/null +++ b/src/app/record/components/record-header/record-header.component.scss-theme.scss @@ -0,0 +1,25 @@ +@use '@angular/material' as mat; +@import 'src/assets/scss/material.orcid-theme.scss'; + +@mixin top-bar-public-names-theme($theme) { + $primary: map-get($theme, primary); + $accent: map-get($theme, accent); + $warn: map-get($theme, accent); + $foreground: map-get($theme, foreground); + $background: map-get($theme, background); + $config: mat.define-legacy-typography-config(); + + .record-header { + color: $orcid-light-primary-text; + background: mat.get-color-from-palette($primary, 900); + } + + .divider { + background: mat.get-color-from-palette($primary, 700); + } + + .other-names { + color: mat.get-color-from-palette($primary, 50); + } +} +@include top-bar-public-names-theme($orcid-app-theme); diff --git a/src/app/record/components/record-header/record-header.component.spec.ts b/src/app/record/components/record-header/record-header.component.spec.ts new file mode 100644 index 0000000000..60ca1a17ee --- /dev/null +++ b/src/app/record/components/record-header/record-header.component.spec.ts @@ -0,0 +1,45 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { RecordHeaderComponent } from './record-header.component'; +import { HttpClientTestingModule } from '@angular/common/http/testing'; +import { WINDOW_PROVIDERS } from 'src/app/cdk/window'; +import { PlatformInfoService } from 'src/app/cdk/platform-info'; +import { ErrorHandlerService } from 'src/app/core/error-handler/error-handler.service'; +import { SnackbarService } from 'src/app/cdk/snackbar/snackbar.service'; +import { MatLegacySnackBar as MatSnackBar } from '@angular/material/legacy-snack-bar' +import { MatLegacyDialog as MatDialog } from '@angular/material/legacy-dialog' +import { Overlay } from '@angular/cdk/overlay'; +import { RouterTestingModule } from '@angular/router/testing'; +import { RecordService } from 'src/app/core/record/record.service'; + +describe('RecordHeaderComponent', () => { + let component: RecordHeaderComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + imports: [HttpClientTestingModule, RouterTestingModule], + declarations: [RecordHeaderComponent], + providers: [ + WINDOW_PROVIDERS, + RecordService , + PlatformInfoService, + ErrorHandlerService, + SnackbarService, + MatSnackBar, + MatDialog, + Overlay, + ], + }).compileComponents() + }) + + beforeEach(() => { + fixture = TestBed.createComponent(RecordHeaderComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/record/components/record-header/record-header.component.ts b/src/app/record/components/record-header/record-header.component.ts new file mode 100644 index 0000000000..f53f1fec9d --- /dev/null +++ b/src/app/record/components/record-header/record-header.component.ts @@ -0,0 +1,106 @@ +import { Component, Inject, Input, OnInit } from '@angular/core'; +import { isEmpty } from 'lodash'; +import { Subject } from 'rxjs'; +import { takeUntil } from 'rxjs/operators'; +import { PlatformInfo, PlatformInfoService } from 'src/app/cdk/platform-info'; +import { WINDOW } from 'src/app/cdk/window'; +import { UserService } from 'src/app/core'; +import { RecordService } from 'src/app/core/record/record.service'; +import { NamesUtil } from 'src/app/shared/utils/names.util'; +import { Assertion, UserInfo } from 'src/app/types'; +import { UserRecord } from 'src/app/types/record.local'; +import { environment } from 'src/environments/environment'; + +@Component({ + selector: 'app-record-header', + templateUrl: './record-header.component.html', + styleUrls: [ + './record-header.component.scss', + './record-header.component.scss-theme.scss' + ] +}) +export class RecordHeaderComponent implements OnInit { + $destroy: Subject = new Subject() + @Input() loadingUserRecord = true + @Input() isPublicRecord: string + @Input() affiliations: number + + platform: PlatformInfo + recordWithIssues: boolean + userRecord: UserRecord + userInfo: UserInfo + environment = environment + givenNames = '' + familyName = '' + creditName = '' + otherNames = '' + ariaLabelName = '' + orcidId = '' + + regionNames = $localize`:@@topBar.names:Names` + regionOrcidId = 'Orcid iD' + tooltipPrintableVersion = $localize`:@@topBar.printableRecord:Printable record` + tooltipCopy = $localize`:@@topBar.copyId:Copy iD` + privateName = $localize`:@@account.nameIsPri:Name is private` + + ariaLabelCopyOrcidId = $localize`:@@topBar.ariaLabelCopyOrcidId:Copy your ORCID iD to the clipboard` + ariaLabelViewPrintable = $localize`:@@topBar.ariaLabelViewPrintable:View a printable version of your ORCID record (Opens in new tab)` + + constructor( + @Inject(WINDOW) private window: Window, + private _platform: PlatformInfoService, + private _user: UserService, + private _record: RecordService, + ) { } + + ngOnInit(): void { + this.orcidId = 'https:' + environment.BASE_URL + this.isPublicRecord + + this._platform + .get() + .pipe(takeUntil(this.$destroy)) + .subscribe((data) => { + this.platform = data + }) + + this._record + .getRecord({ + publicRecordId: this.isPublicRecord || undefined, + }) + .pipe(takeUntil(this.$destroy)) + .subscribe((userRecord) => { + this.recordWithIssues = userRecord?.userInfo?.RECORD_WITH_ISSUES + this.userRecord = userRecord + this.userInfo = userRecord?.userInfo + + if (!isEmpty(this.userRecord?.names)) { + this.givenNames = NamesUtil.getGivenNames(this.userRecord) + this.familyName = NamesUtil.getFamilyName(this.userRecord) + this.creditName = NamesUtil.getCreditName(this.userRecord) + this.ariaLabelName = NamesUtil.getAriaLabelName(this.userRecord, this.ariaLabelName) + } else { + if (this.affiliations > 0) { + this.creditName = this.privateName + } + } + + if (!isEmpty(this.userRecord.otherNames?.otherNames)) { + this.otherNames = NamesUtil.getOtherNamesUnique(userRecord.otherNames?.otherNames) + } + }) + } + + clipboard() { + this.window.navigator.clipboard.writeText( + this.orcidId + ) + } + + printRecord() { + this.window.open( + environment.BASE_URL + + this.userRecord?.userInfo?.EFFECTIVE_USER_ORCID + + '/print' + ) + } +} diff --git a/src/app/record/components/record-info/record-info.component.html b/src/app/record/components/record-info/record-info.component.html new file mode 100644 index 0000000000..87612bd5e6 --- /dev/null +++ b/src/app/record/components/record-info/record-info.component.html @@ -0,0 +1,68 @@ +
+
+ +

+ + We lock records when they violate conditions of our + + terms of + service. +

+

+ + If you feel this record has been locked in error please + + contact + ORCID + support for further assistance. + +

+
+ + +

+ + When an ORCID record is deactivated all information in the record is deleted. Deactivated records are not + shown + in registry searches. + +

+

+ Find + out more about reactivating an ORCID account + +

+
+ + +

+ + A deprecated record is a duplicate or unwanted ORCID record that has been merged with another owned by the + same + person. + +

+

+ Find out more about removing additional or duplicate ORCID records + +

+
+ +

+ No public information available. +

+

+ + The record owner may not have added information to their record or the visibility for items on their record may be to Trusted parties or Only me. + +

+

+ Find out more about visibility settings in ORCID + +

+
+
+
diff --git a/src/app/record/components/record-info/record-info.component.scss b/src/app/record/components/record-info/record-info.component.scss new file mode 100644 index 0000000000..7314b2e5e6 --- /dev/null +++ b/src/app/record/components/record-info/record-info.component.scss @@ -0,0 +1,14 @@ +.record-info { + display: flex; + padding: 0px 32px; + flex-direction: column; + align-items: start; + gap: 32px; + flex: 1 0 0; + align-self: stretch; + + p { + margin: 0; + line-height: 21px; + } +} diff --git a/src/app/record/components/record-info/record-info.component.spec.ts b/src/app/record/components/record-info/record-info.component.spec.ts new file mode 100644 index 0000000000..9ed8462152 --- /dev/null +++ b/src/app/record/components/record-info/record-info.component.spec.ts @@ -0,0 +1,44 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { RecordInfoComponent } from './record-info.component'; +import { HttpClientTestingModule } from '@angular/common/http/testing'; +import { RouterTestingModule } from '@angular/router/testing'; +import { WINDOW_PROVIDERS } from 'src/app/cdk/window'; +import { PlatformInfoService } from 'src/app/cdk/platform-info'; +import { ErrorHandlerService } from 'src/app/core/error-handler/error-handler.service'; +import { SnackbarService } from 'src/app/cdk/snackbar/snackbar.service'; +import { MatLegacySnackBar as MatSnackBar } from '@angular/material/legacy-snack-bar' +import { MatLegacyDialog as MatDialog } from '@angular/material/legacy-dialog' +import { Overlay } from '@angular/cdk/overlay'; + +describe('RecordInfoComponent', () => { + let component: RecordInfoComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + imports: [HttpClientTestingModule, RouterTestingModule], + declarations: [RecordInfoComponent], + providers: [ + WINDOW_PROVIDERS, + PlatformInfoService, + ErrorHandlerService, + SnackbarService, + MatSnackBar, + MatDialog, + Overlay, + ], + }).compileComponents() + }) + + beforeEach(() => { + fixture = TestBed.createComponent(RecordInfoComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/record/components/record-info/record-info.component.ts b/src/app/record/components/record-info/record-info.component.ts new file mode 100644 index 0000000000..60d4008553 --- /dev/null +++ b/src/app/record/components/record-info/record-info.component.ts @@ -0,0 +1,35 @@ +import { Component, Input, OnInit } from '@angular/core'; +import { Subject } from 'rxjs'; +import { takeUntil } from 'rxjs/operators'; +import { RecordService } from 'src/app/core/record/record.service'; +import { NamesUtil } from 'src/app/shared/utils/names.util'; +import { UserInfo } from 'src/app/types'; + +@Component({ + selector: 'app-record-info', + templateUrl: './record-info.component.html', + styleUrls: ['./record-info.component.scss'] +}) +export class RecordInfoComponent implements OnInit { + $destroy: Subject = new Subject() + + @Input() isPublicRecord: string + @Input() affiliations: number + + userInfo: UserInfo + isNamePublic: boolean + + constructor(private _record: RecordService) {} + + ngOnInit(): void { + this._record + .getRecord({ + publicRecordId: this.isPublicRecord || undefined, + }) + .pipe(takeUntil(this.$destroy)) + .subscribe((userRecord) => { + this.userInfo = userRecord?.userInfo + this.isNamePublic = NamesUtil.isNamePublicAndAffiliations(userRecord, this.affiliations) + }) + } +} diff --git a/src/app/record/components/top-bar/top-bar.component.html b/src/app/record/components/top-bar/top-bar.component.html index c55ecb2693..793e5b5d5b 100644 --- a/src/app/record/components/top-bar/top-bar.component.html +++ b/src/app/record/components/top-bar/top-bar.component.html @@ -1,9 +1,10 @@ @@ -12,7 +13,7 @@ [userRecord]="userRecord" [userStatus]="userStatus" [isPublicRecord]="isPublicRecord" - *ngIf="!recordWithIssues" + *ngIf="!newRecordHeaderTogglz && !recordWithIssues" [showPrintButton]="!platform.columns12" > @@ -150,7 +151,7 @@

[id]="'names'" role="region" [attr.aria-label]="regionNames" - *ngIf="userRecord?.names || userRecord?.otherNames" + *ngIf="!newRecordHeaderTogglz && (userRecord?.names || userRecord?.otherNames)" >
@@ -216,7 +217,7 @@

Also known as

- {{ getOtherNamesUnique(userRecord.otherNames?.otherNames) }} + {{ otherNames }}

[userRecord]="userRecord" [userStatus]="userStatus" [isPublicRecord]="isPublicRecord" - *ngIf="!recordWithIssues && !platform.columns12" + *ngIf="!newRecordHeaderTogglz && !recordWithIssues && !platform.columns12" [showIsThisYouButton]="true" > @@ -277,7 +278,10 @@

[attr.aria-label]="regionBiography" *ngIf="userRecord?.biography?.biography" > -
+

Biography

diff --git a/src/app/record/components/top-bar/top-bar.component.scss b/src/app/record/components/top-bar/top-bar.component.scss index cebdfa3141..1cae0aa5d7 100644 --- a/src/app/record/components/top-bar/top-bar.component.scss +++ b/src/app/record/components/top-bar/top-bar.component.scss @@ -133,12 +133,16 @@ app-top-bar-actions { } .biography-container { + margin-top: 1em; .biography-header { margin: 0; } - margin-top: 1em; p { overflow-wrap: break-word; } } + + .no-margin-top { + margin-top: 0 !important; + } } diff --git a/src/app/record/components/top-bar/top-bar.component.ts b/src/app/record/components/top-bar/top-bar.component.ts index 9417410c8f..eac4c347e6 100644 --- a/src/app/record/components/top-bar/top-bar.component.ts +++ b/src/app/record/components/top-bar/top-bar.component.ts @@ -13,6 +13,7 @@ import { RecordEmailsService } from '../../../core/record-emails/record-emails.s import { MatLegacyDialog as MatDialog } from '@angular/material/legacy-dialog' import { VerificationEmailModalService } from '../../../core/verification-email-modal/verification-email-modal.service' import { isEmpty } from 'lodash' +import { NamesUtil } from 'src/app/shared/utils/names.util' @Component({ selector: 'app-top-bar', @@ -38,6 +39,7 @@ export class TopBarComponent implements OnInit, OnDestroy { givenNames = '' familyName = '' creditName = '' + otherNames = '' expandedContent = false recordWithIssues: boolean justRegistered: boolean @@ -45,6 +47,7 @@ export class TopBarComponent implements OnInit, OnDestroy { checkEmailValidated: boolean inDelegationMode: boolean @Input() loadingUserRecord = true + @Input() newRecordHeaderTogglz: boolean regionNames = $localize`:@@topBar.names:Names` regionBiography = $localize`:@@topBar.biography:Biography` @@ -91,60 +94,16 @@ export class TopBarComponent implements OnInit, OnDestroy { this.userInfo = userRecord?.userInfo if (!isEmpty(this.userRecord?.names)) { - this.setNames() - this.getAriaLabelName() + this.givenNames = NamesUtil.getGivenNames(this.userRecord) + this.familyName = NamesUtil.getFamilyName(this.userRecord) + this.creditName = NamesUtil.getCreditName(this.userRecord) + this.ariaLabelName = NamesUtil.getAriaLabelName(this.userRecord, this.ariaLabelName) } - }) - } - - private setNames() { - this.givenNames = this.userRecord?.names?.givenNames - ? this.userRecord.names.givenNames.value - : '' - this.familyName = this.userRecord?.names?.familyName - ? this.userRecord.names.familyName.value - : '' - this.creditName = this.userRecord?.names?.creditName - ? this.userRecord.names.creditName.value - : '' - } - private getAriaLabelName() { - if (this.userRecord?.names) { - if (this.userRecord?.names?.creditName?.value) { - this.ariaLabelName = this.userRecord?.names?.creditName?.value - } else { - if (this.userRecord?.names?.givenNames?.value) { - this.ariaLabelName = this.userRecord?.names?.givenNames?.value + if (!isEmpty(this.userRecord.otherNames?.otherNames)) { + this.otherNames = NamesUtil.getOtherNamesUnique(userRecord.otherNames?.otherNames) } - if (this.userRecord?.names?.familyName?.value) { - if (this.ariaLabelName) { - this.ariaLabelName = - this.ariaLabelName + - ' ' + - this.userRecord?.names?.familyName?.value - } else { - this.ariaLabelName = this.userRecord?.names?.familyName?.value - } - } - } - } - return - } - - getOtherNamesUnique(otherNames: Assertion[]): string { - return otherNames - .map((otherName) => { - return otherName.content - }) - .filter(function (item, pos, array) { - return ( - array - .map((x) => x.toLowerCase().trim()) - .indexOf(item.toLowerCase().trim()) === pos - ) }) - .join(', ') } resendVerificationEmailModal(email: string) { diff --git a/src/app/record/pages/my-orcid/my-orcid.component.html b/src/app/record/pages/my-orcid/my-orcid.component.html index aacacf7f8c..8b9fd7639f 100644 --- a/src/app/record/pages/my-orcid/my-orcid.component.html +++ b/src/app/record/pages/my-orcid/my-orcid.component.html @@ -1,14 +1,27 @@
-
+ + +
@@ -17,6 +30,7 @@ [isPublicRecord]="publicOrcid" class="row" [loadingUserRecord]="loadingUserRecord" + [newRecordHeaderTogglz]="newRecordHeaderTogglz" >
error
diff --git a/src/app/record/pages/my-orcid/my-orcid.component.scss-theme.scss b/src/app/record/pages/my-orcid/my-orcid.component.scss-theme.scss index 4be10231a8..7921c4c753 100644 --- a/src/app/record/pages/my-orcid/my-orcid.component.scss-theme.scss +++ b/src/app/record/pages/my-orcid/my-orcid.component.scss-theme.scss @@ -11,6 +11,10 @@ .no-public-info { color: mat.get-color-from-palette($background, dark-grey); } + + .new-header { + background-color: transparent; + } } @include my-orcid-theme($orcid-app-theme); diff --git a/src/app/record/pages/my-orcid/my-orcid.component.ts b/src/app/record/pages/my-orcid/my-orcid.component.ts index df00ce5585..6ab434490b 100644 --- a/src/app/record/pages/my-orcid/my-orcid.component.ts +++ b/src/app/record/pages/my-orcid/my-orcid.component.ts @@ -70,6 +70,7 @@ export class MyOrcidComponent implements OnInit, OnDestroy { regionActivities = $localize`:@@shared.activities:Activities` readyForIndexing: boolean fragment: string + newRecordHeaderTogglz = false constructor( _userInfoService: UserInfoService, @@ -211,6 +212,10 @@ export class MyOrcidComponent implements OnInit, OnDestroy { } } + if (togglz.messages['NEW_RECORD_HEADER'] === 'true') { + this.newRecordHeaderTogglz = true + } + if (togglz.messages['CRAZY_EGG'] === 'true') { this._scriptService .load({ diff --git a/src/app/record/record.module.ts b/src/app/record/record.module.ts index 5a4c34317a..a2c5b08684 100644 --- a/src/app/record/record.module.ts +++ b/src/app/record/record.module.ts @@ -77,7 +77,9 @@ import { TopBarMyPublicRecordPreviewModule } from '../cdk/top-bar-my-public-reco import { WorkContributorRolesComponent } from './components/work-contributor-role/work-contributor-roles.component' import { WorkContributorsComponent } from './components/work-contributors/work-contributors.component' import { VisibilitySelectorModule } from '../cdk/visibility-selector/visibility-selector.module' -import { TopBarVerificationEmailModule } from '../cdk/top-bar-verification-email/top-bar-verification-email.module' +import { TopBarVerificationEmailModule } from '../cdk/top-bar-verification-email/top-bar-verification-email.module'; +import { RecordHeaderComponent } from './components/record-header/record-header.component'; +import { RecordInfoComponent } from './components/record-info/record-info.component' @NgModule({ declarations: [ @@ -129,6 +131,8 @@ import { TopBarVerificationEmailModule } from '../cdk/top-bar-verification-email ModalCombineWorksWithSelectorComponent, WorkContributorRolesComponent, WorkContributorsComponent, + RecordHeaderComponent, + RecordInfoComponent, ], imports: [ CommonModule, diff --git a/src/app/shared/utils/names.util.ts b/src/app/shared/utils/names.util.ts new file mode 100644 index 0000000000..1838931d98 --- /dev/null +++ b/src/app/shared/utils/names.util.ts @@ -0,0 +1,70 @@ +import { Assertion } from "src/app/types" +import { UserRecord } from "src/app/types/record.local" + +export class NamesUtil { + + static getGivenNames(userRecord: UserRecord): string { + return userRecord?.names?.givenNames + ? userRecord.names.givenNames.value + : '' + } + + static getFamilyName(userRecord: UserRecord): string { + return userRecord?.names?.familyName + ? userRecord.names.familyName.value + : '' + } + + static getCreditName(userRecord: UserRecord): string { + return userRecord?.names?.creditName + ? userRecord.names.creditName.value + : '' + } + + static isNamePublicAndAffiliations(userRecord: UserRecord, affiliations: number): boolean { + if ( + affiliations === 0 && + !!this.getGivenNames(userRecord) || + !!this.getFamilyName(userRecord) || + !!this.getCreditName(userRecord) + ) { + return true + } + return false + } + + static getAriaLabelName(userRecord: UserRecord,ariaLabelName: string): string { + if (userRecord?.names) { + if (userRecord?.names?.creditName?.value) { + return userRecord?.names?.creditName?.value + } else { + if (userRecord?.names?.givenNames?.value) { + return userRecord?.names?.givenNames?.value + } + if (userRecord?.names?.familyName?.value) { + if (ariaLabelName) { + return ariaLabelName + ' ' + userRecord?.names?.familyName?.value + } else { + return userRecord?.names?.familyName?.value + } + } + } + } + return + } + + static getOtherNamesUnique(otherNames: Assertion[]): string { + return otherNames + .map((otherName) => { + return otherName.content + }) + .filter(function (item, pos, array) { + return ( + array + .map((x) => x.toLowerCase().trim()) + .indexOf(item.toLowerCase().trim()) === pos + ) + }) + .join(', ') + } +} diff --git a/src/locale/properties/top-bar/top-bar.en.properties b/src/locale/properties/top-bar/top-bar.en.properties index eee1347bbc..d569d4445e 100644 --- a/src/locale/properties/top-bar/top-bar.en.properties +++ b/src/locale/properties/top-bar/top-bar.en.properties @@ -98,3 +98,17 @@ topBar.ariaLabelDeleteOtherName=Delete other name topBar.addBiography=Add your biography topBar.weHaveSentForCredentials=We have sent verification messages to each of your registered email addresses. You will need to verify your primary email address before you can register your ORCID Public API credentials. developerTools.ariaLabelClose=Close +topBar.copyId=Copy iD +topBar.printableRecord=Printable record +topBar.whenOrcidDeactivated=When an ORCID record is deactivated all information in the record is deleted. Deactivated records are not shown in registry searches. +topBar.findOutReactivating=Find out more about reactivating an ORCID account +topBar.weLockRecords=We lock records when they violate conditions of our +topBar.termsOfService=terms of service. +topBar.recordLockedInError=If you feel this record has been locked in error please +topBar.contactOrcid=contact ORCID support for further assistance. +topBar.deprecatedRecordIsDuplicate=A deprecated record is a duplicate or unwanted ORCID record that has been merged with another owned by the same person. +topBar.findOutMoreAboutRemoving=Find out more about removing additional or duplicate ORCID records +topBar.recordOwnerNotHaveAdded=The record owner may not have added information to their record or the visibility for items on their record may be to Trusted parties or Only me. +topBar.findOutVisibility=Find out more about visibility settings in ORCID +topBar.ariaLabelCopyOrcidId=Copy your ORCID iD to the clipboard +topBar.ariaLabelViewPrintable=View a printable version of your ORCID record (Opens in new tab)