diff --git a/guides/example-tx-config.yml b/guides/example-tx-config.yml index 08ae2f0153..364de2ee18 100644 --- a/guides/example-tx-config.yml +++ b/guides/example-tx-config.yml @@ -192,3 +192,11 @@ filters: source_file: src/locale/properties/account/account.en.properties # path expression to translation files, must contain placeholder translation_files_expression: src/locale/properties/account/account..properties + + - filter_type: file + # all supported i18n types: https://docs.transifex.com/formats + file_format: UNICODEPROPERTIES + source_language: en + source_file: src/locale/properties/interstitials/interstitials.en.properties + # path expression to translation files, must contain placeholder + translation_files_expression: src/locale/properties/interstitials/interstitials..properties \ No newline at end of file diff --git a/src/app/authorize/authorize.module.ts b/src/app/authorize/authorize.module.ts index 0e7fdbfd1d..e5a8cd822e 100644 --- a/src/app/authorize/authorize.module.ts +++ b/src/app/authorize/authorize.module.ts @@ -15,6 +15,8 @@ import { AuthorizeRoutingModule } from './authorize-routing.module' import { OauthErrorComponent } from './components/oauth-error/oauth-error.component' import { AuthorizeComponent } from './pages/authorize/authorize.component' import { FormAuthorizeComponent } from './components/form-authorize/form-authorize.component' +import { ShareEmailsDomainsComponent } from '../cdk/interstitials/share-emails-domains/share-emails-domains.component' +import { InterstitialsModule } from '../cdk/interstitials/interstitials.module' @NgModule({ declarations: [ @@ -35,6 +37,7 @@ import { FormAuthorizeComponent } from './components/form-authorize/form-authori TrustedIndividualsDropdownModule, InfoDropDownModule, MatProgressBarModule, + InterstitialsModule ], }) export class AuthorizeModule {} diff --git a/src/app/authorize/components/form-authorize/form-authorize.component.ts b/src/app/authorize/components/form-authorize/form-authorize.component.ts index d2bd993dea..fb6c91e507 100644 --- a/src/app/authorize/components/form-authorize/form-authorize.component.ts +++ b/src/app/authorize/components/form-authorize/form-authorize.component.ts @@ -1,4 +1,12 @@ -import { Component, Inject, Input, OnDestroy, OnInit } from '@angular/core' +import { + Component, + EventEmitter, + Inject, + Input, + OnDestroy, + OnInit, + Output, +} from '@angular/core' import { Router } from '@angular/router' import { forkJoin, Observable, Subject } from 'rxjs' import { catchError, map, take, takeUntil } from 'rxjs/operators' @@ -31,6 +39,8 @@ import { Title } from '@angular/platform-browser' preserveWhitespaces: true, }) export class FormAuthorizeComponent implements OnInit, OnDestroy { + @Output() redirectUrl = new EventEmitter() + @Output() organizationName = new EventEmitter() environment = environment $destroy: Subject = new Subject() orcidUrl: string @@ -57,7 +67,9 @@ export class FormAuthorizeComponent implements OnInit, OnDestroy { private _errorHandler: ErrorHandlerService, private _trustedIndividuals: TrustedIndividualsService, private _titleService: Title - ) { + ) {} + + ngOnInit(): void { this._platformInfo .get() .pipe(take(1)) @@ -73,6 +85,8 @@ export class FormAuthorizeComponent implements OnInit, OnDestroy { this.loadingUserInfo = false this.loadingTrustedIndividuals = false this.oauthRequest = userInfo.oauthSession + this.organizationName.emit(this.oauthRequest.clientName) + console.log('this ', this.oauthRequest.clientName) if (userInfo.loggedIn) { this.userName = userInfo.displayName this.orcidUrl = userInfo.effectiveOrcidUrl @@ -92,9 +106,7 @@ export class FormAuthorizeComponent implements OnInit, OnDestroy { this._trustedIndividuals.getTrustedIndividuals().subscribe((value) => { this.trustedIndividuals = value }) - } - ngOnInit(): void { setTimeout(() => { this._titleService.setTitle( this.authorizeAccessFor + @@ -141,8 +153,8 @@ export class FormAuthorizeComponent implements OnInit, OnDestroy { ) ) .subscribe( - () => (this.window as any).outOfRouterNavigation(data.redirectUrl), - () => (this.window as any).outOfRouterNavigation(data.redirectUrl) + () => this.redirectUrl.next(data.redirectUrl), + () => this.redirectUrl.next(data.redirectUrl) ) }) } diff --git a/src/app/authorize/pages/authorize/authorize.component.html b/src/app/authorize/pages/authorize/authorize.component.html index 637f26207a..902b309ebc 100644 --- a/src/app/authorize/pages/authorize/authorize.component.html +++ b/src/app/authorize/pages/authorize/authorize.component.html @@ -10,10 +10,16 @@ > - + + diff --git a/src/app/authorize/pages/authorize/authorize.component.ts b/src/app/authorize/pages/authorize/authorize.component.ts index 13d3c641ee..3331d2ded5 100644 --- a/src/app/authorize/pages/authorize/authorize.component.ts +++ b/src/app/authorize/pages/authorize/authorize.component.ts @@ -1,6 +1,12 @@ -import { Component } from '@angular/core' +import { Component, Inject } from '@angular/core' +import { cloneDeep } from 'lodash' +import { first, tap } 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 { RecordEmailsService } from 'src/app/core/record-emails/record-emails.service' +import { TogglzService } from 'src/app/core/togglz/togglz.service' +import { AssertionVisibilityString, EmailsEndpoint } from 'src/app/types' @Component({ templateUrl: './authorize.component.html', @@ -8,13 +14,27 @@ import { UserService } from 'src/app/core' preserveWhitespaces: true, }) export class AuthorizeComponent { + redirectUrl: string + platform: PlatformInfo showAuthorizationComponent: boolean + showAuthorizationError: boolean + showInterstital: boolean + originalEmailsBackendCopy: EmailsEndpoint + userHasPrivateDomains = false + oauthDomainsInterstitialEnabled: boolean + organizationName: string - constructor(_user: UserService, private _platformInfo: PlatformInfoService) { + constructor( + _user: UserService, + private _platformInfo: PlatformInfoService, + private _recordEmails: RecordEmailsService, + private _togglz: TogglzService, + @Inject(WINDOW) private window: Window + ) { _user.getUserSession().subscribe((session) => { if (session.oauthSession && session.oauthSession.error) { - this.showAuthorizationComponent = false + this.showAuthorizationError = true } else { this.showAuthorizationComponent = true } @@ -23,4 +43,39 @@ export class AuthorizeComponent { this.platform = platformInfo }) } + + ngOnInit() { + this._togglz.getStateOf('OAUTH_DOMAINS_INTERSTITIAL').subscribe((value) => { + this.oauthDomainsInterstitialEnabled = value + }) + this._recordEmails + .getEmails() + .pipe( + tap((value) => { + this.originalEmailsBackendCopy = cloneDeep(value) + this.userHasPrivateDomains = this.userHasPrivateEmails(value) + }), + first() + ) + .subscribe() + } + + userHasPrivateEmails(value: EmailsEndpoint): boolean { + return !!value.emailDomains.find( + (domain) => domain.visibility !== 'PUBLIC' + ) + } + + handleRedirect(url: string) { + if (url && this.userHasPrivateDomains && this.oauthDomainsInterstitialEnabled) { + this.redirectUrl = url + this.showAuthorizationComponent = false + this.showInterstital = true + } else { + this.finishRedirect() + } + } + finishRedirect() { + ;(this.window as any).outOfRouterNavigation(this.redirectUrl) + } } diff --git a/src/app/cdk/info-panel/info-panel.module.ts b/src/app/cdk/info-panel/info-panel.module.ts new file mode 100644 index 0000000000..5cad734f18 --- /dev/null +++ b/src/app/cdk/info-panel/info-panel.module.ts @@ -0,0 +1,11 @@ +import { NgModule } from '@angular/core' +import { CommonModule } from '@angular/common' +import { InfoPanelComponent } from './info-panel/info-panel.component' +import { MatIcon, MatIconModule } from '@angular/material/icon' + +@NgModule({ + declarations: [InfoPanelComponent], + imports: [CommonModule, MatIconModule], + exports: [InfoPanelComponent], +}) +export class InfoPanelModule {} diff --git a/src/app/cdk/info-panel/info-panel/info-panel.component.html b/src/app/cdk/info-panel/info-panel/info-panel.component.html new file mode 100644 index 0000000000..c97407012a --- /dev/null +++ b/src/app/cdk/info-panel/info-panel/info-panel.component.html @@ -0,0 +1,10 @@ +
+
+ +
+
+

+ +

+
+
diff --git a/src/app/cdk/info-panel/info-panel/info-panel.component.scss b/src/app/cdk/info-panel/info-panel/info-panel.component.scss new file mode 100644 index 0000000000..a846418b5e --- /dev/null +++ b/src/app/cdk/info-panel/info-panel/info-panel.component.scss @@ -0,0 +1,16 @@ +.info { + padding: 16px; + margin-top: 16px; + margin-bottom: 16px; + border: solid 2px; + border-radius: 4px; + display: flex; + + p { + margin: 0; + } + .col { + align-items: start; + padding-left: 0; + } +} diff --git a/src/app/cdk/info-panel/info-panel/info-panel.component.scss-theme.scss b/src/app/cdk/info-panel/info-panel/info-panel.component.scss-theme.scss new file mode 100644 index 0000000000..6a0e1f4b00 --- /dev/null +++ b/src/app/cdk/info-panel/info-panel/info-panel.component.scss-theme.scss @@ -0,0 +1,23 @@ +@use '@angular/material' as mat; +@import 'src/assets/scss/material.orcid-theme.scss'; + +@mixin 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); + + .info { + border-color: mat.get-color-from-palette( + $foreground, + 'state-info-darkest' + ) !important; + background-color: mat.get-color-from-palette( + $background, + 'state-info-lightest' + ) !important; + } +} + +@include theme($orcid-app-theme); diff --git a/src/app/cdk/info-panel/info-panel/info-panel.component.spec.ts b/src/app/cdk/info-panel/info-panel/info-panel.component.spec.ts new file mode 100644 index 0000000000..1cfc9e2436 --- /dev/null +++ b/src/app/cdk/info-panel/info-panel/info-panel.component.spec.ts @@ -0,0 +1,21 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { InfoPanelComponent } from './info-panel.component'; + +describe('InfoPanelComponent', () => { + let component: InfoPanelComponent; + let fixture: ComponentFixture; + + beforeEach(() => { + TestBed.configureTestingModule({ + declarations: [InfoPanelComponent] + }); + fixture = TestBed.createComponent(InfoPanelComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/cdk/info-panel/info-panel/info-panel.component.ts b/src/app/cdk/info-panel/info-panel/info-panel.component.ts new file mode 100644 index 0000000000..cff766a000 --- /dev/null +++ b/src/app/cdk/info-panel/info-panel/info-panel.component.ts @@ -0,0 +1,10 @@ +import { Component } from '@angular/core'; + +@Component({ + selector: 'app-info-panel', + templateUrl: './info-panel.component.html', + styleUrls: ['./info-panel.component.scss', './info-panel.component.scss-theme.scss'] +}) +export class InfoPanelComponent { + +} diff --git a/src/app/cdk/interstitials/interstitials.module.ts b/src/app/cdk/interstitials/interstitials.module.ts new file mode 100644 index 0000000000..72dc6cf736 --- /dev/null +++ b/src/app/cdk/interstitials/interstitials.module.ts @@ -0,0 +1,32 @@ +import { NgModule } from '@angular/core' +import { CommonModule } from '@angular/common' +import { ShareEmailsDomainsComponent } from './share-emails-domains/share-emails-domains.component' +import { MatLegacyCardModule } from '@angular/material/legacy-card' +import { MatIconModule } from '@angular/material/icon' +import { MatDividerModule } from '@angular/material/divider' +import { InfoDropDownModule } from '../info-drop-down/info-drop-down.module' +import { MatProgressBarModule } from '@angular/material/progress-bar' +import { FormsModule, ReactiveFormsModule } from '@angular/forms' +import { MatCheckboxModule } from '@angular/material/checkbox' +import { MatLegacyCheckboxModule } from '@angular/material/legacy-checkbox' +import { MatLegacyButtonModule as MatButtonModule } from '@angular/material/legacy-button' +import { InfoPanelModule } from '../info-panel/info-panel.module' + +@NgModule({ + declarations: [ShareEmailsDomainsComponent], + imports: [ + CommonModule, + MatLegacyCardModule, + MatIconModule, + MatDividerModule, + InfoDropDownModule, + MatProgressBarModule, + ReactiveFormsModule, + FormsModule, + MatLegacyCheckboxModule, + MatButtonModule, + InfoPanelModule, + ], + exports: [ShareEmailsDomainsComponent], +}) +export class InterstitialsModule {} diff --git a/src/app/cdk/interstitials/share-emails-domains/share-emails-domains.component.html b/src/app/cdk/interstitials/share-emails-domains/share-emails-domains.component.html new file mode 100644 index 0000000000..8019bf20e4 --- /dev/null +++ b/src/app/cdk/interstitials/share-emails-domains/share-emails-domains.component.html @@ -0,0 +1,148 @@ + + + + orcid logo + +

+ Share your verified email domains +

+
+
+ + +
+ We’ve found some unshared email domains in your ORCID record. +
+ +

+ Sharing your email domains lets you prove your association with an + organization or institution without having to make your full email + address public. +

+
+
+

+ Your verified email domains +

+
+ +
+ Uncheck any email domains you don’t want to share on your public ORCID + record +
+ +
+
+
+ +
+ + {{ item.get('email').value }} + + +
+
+
+
+ + + +
+ + + + + +
+ + + + orcid logo + +

+ Email domains shared +

+
+
+ +
+ The following email domains are now visible on your public ORCID record. +
+ + +
+
+ + {{ + domain + }} +
+ + +
+ +
+ Visit your ORCID record to manage your email addresses, domains, + affiliations, works and more. +
+ + + + +
+ + + + + +
diff --git a/src/app/cdk/interstitials/share-emails-domains/share-emails-domains.component.scss b/src/app/cdk/interstitials/share-emails-domains/share-emails-domains.component.scss new file mode 100644 index 0000000000..e02db7e345 --- /dev/null +++ b/src/app/cdk/interstitials/share-emails-domains/share-emails-domains.component.scss @@ -0,0 +1,166 @@ +@import '../../../../assets/scss/orcid.spacing.scss'; + + +h2 { + margin-top: 16px; + margin-bottom: 16px; + +} +.published-email-container{ + display: flex; + align-items: center; +} + +.published-domain { + margin-inline-start: 16px; +} + +.items { + margin-top: 24px; +} + +.logo { + width: 130px; +} + +.user-links { + display: flex; + justify-content: space-between; +} + +.university-dropdown { + display: flex; + align-items: center; + cursor: pointer; +} + +:host { + ul { + padding: 0; + + li { + list-style-type: none; + flex-direction: column; + align-items: baseline; + + div { + display: flex; + align-items: center; + mat-icon { + margin-bottom: -4px; // Compensates mat icon bottom with space + margin-left: $spacing-small; + margin-right: $spacing-small; + } + } + } + } +} + +button { + width: 100%; + margin-bottom: $spacing-base; +} +mat-divider { + margin-top: 16px; + margin-bottom: 16px; +} + + +mat-divider.last { + margin-top: 32px; + margin-bottom: 32px; +} + +mat-icon > img { + height: 20px; + margin-top: 2px; // Fix icon component with SVG image +} + +.col { + overflow: hidden; +} + +app-info-drop-down { + max-width: 100%; + display: block; +} + +.progress-bar { + top: 0; +} + +mat-card-header.authorize-header { + mat-card-title { + margin: 0 0 32px 0 !important; + } + + h1 { + margin-top: 0; + } + + .orc-font-heading-small { + font-style: normal; + font-weight: 500; + } + + mat-icon.logo-icon { + height: 80px; + width: 64px; + img { + height: 64px; + } + } +} + +mat-card-content.authorize-content { + margin: 0px !important; + + div.profile-icon-wrapper { + padding: 0 !important; + margin-right: 16px; + } + + div.user-wrapper { + padding: 0 !important; + } + + div.deny-button-wrapper { + justify-content: center; + } + + mat-icon.profile-icon { + height: 80px; + width: 64px; + img { + height: 64px; + } + } + + mat-icon.scope { + width: 32px; + } + + mat-icon.scope.orcid { + font-size: small; + img { + margin-top: 0 !important; + } + } + + .user-links { + width: 100%; + } + + .center-content { + justify-content: center; + } +} + +.disclaimer-box { + margin: 24px 0px 20px 0px; + display: flex; + flex-direction: column; + :first-child { + margin-bottom: 12px; + } +} diff --git a/src/app/cdk/interstitials/share-emails-domains/share-emails-domains.component.scss-theme.scss b/src/app/cdk/interstitials/share-emails-domains/share-emails-domains.component.scss-theme.scss new file mode 100644 index 0000000000..150c755f1b --- /dev/null +++ b/src/app/cdk/interstitials/share-emails-domains/share-emails-domains.component.scss-theme.scss @@ -0,0 +1,24 @@ +@use '@angular/material' as mat; +@import 'src/assets/scss/material.orcid-theme.scss'; + +@mixin 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); + + .mat-raised-button.mat-primary { + background-color: mat.get-color-from-palette($primary, 700); + } + + ::ng-deep{ + .mat-divider.green-divider { + border: solid 1px mat.get-color-from-palette($foreground, brand-primary); + } + } +} + + + +@include theme($orcid-app-theme); diff --git a/src/app/cdk/interstitials/share-emails-domains/share-emails-domains.component.spec.ts b/src/app/cdk/interstitials/share-emails-domains/share-emails-domains.component.spec.ts new file mode 100644 index 0000000000..edd68aba7d --- /dev/null +++ b/src/app/cdk/interstitials/share-emails-domains/share-emails-domains.component.spec.ts @@ -0,0 +1,21 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { ShareEmailsDomainsComponent } from './share-emails-domains.component'; + +describe('ShareEmailsDomainsComponent', () => { + let component: ShareEmailsDomainsComponent; + let fixture: ComponentFixture; + + beforeEach(() => { + TestBed.configureTestingModule({ + declarations: [ShareEmailsDomainsComponent] + }); + fixture = TestBed.createComponent(ShareEmailsDomainsComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/cdk/interstitials/share-emails-domains/share-emails-domains.component.ts b/src/app/cdk/interstitials/share-emails-domains/share-emails-domains.component.ts new file mode 100644 index 0000000000..0c5e8fac76 --- /dev/null +++ b/src/app/cdk/interstitials/share-emails-domains/share-emails-domains.component.ts @@ -0,0 +1,89 @@ +import { Component, EventEmitter, Input, Output } from '@angular/core' +import { PlatformInfoService } from '../../platform-info' +import { AssertionVisibilityString, EmailsEndpoint } from 'src/app/types' +import { FormBuilder, FormControl, FormGroup } from '@angular/forms' +import { RecordEmailsService } from 'src/app/core/record-emails/record-emails.service' +import { error } from 'console' + +@Component({ + selector: 'app-share-emails-domains', + templateUrl: './share-emails-domains.component.html', + styleUrls: [ + './share-emails-domains.component.scss', + './share-emails-domains.component.scss-theme.scss', + ], +}) +export class ShareEmailsDomainsComponent { + beforeSummit = true + afterSummit = false + userPrivateDomains: AssertionVisibilityString[] + @Input() userEmailsJson: EmailsEndpoint + @Input() organizationName: string + form: any + domainToMakePublic: string[] + constructor( + public platformInfo: PlatformInfoService, + private fb: FormBuilder, + private recordEmailsService: RecordEmailsService + ) {} + public loadingEmails = true + @Output() finish = new EventEmitter() + + ngOnInit() { + console.log(this.organizationName) + this.userPrivateDomains = this.getTop3MostRecentPrivateDomains( + this.userEmailsJson + ) + this.form = this.fb.group({ + items: this.fb.array( + this.userPrivateDomains.map((item) => this.createItemFormGroup(item)) + ), + }) + } + + getTop3MostRecentPrivateDomains( + value: EmailsEndpoint + ): AssertionVisibilityString[] { + return value.emailDomains + .filter((domain) => domain.visibility !== 'PUBLIC') + .sort((a, b) => { + return b.createdDate.timestamp - a.createdDate.timestamp + }) + .slice(0, 3) + } + + createItemFormGroup(item: AssertionVisibilityString): FormGroup { + return this.fb.group({ + email: new FormControl(item.value), + selected: new FormControl(true), + }) + } + + accept(answear: boolean) { + this.domainToMakePublic = this.form.value.items + .filter((item) => item.selected) + .map((item) => item.email) + + + if (answear && this.domainToMakePublic.length > 0) { + this.userEmailsJson.emailDomains.forEach((domain) => { + if (this.domainToMakePublic.includes(domain.value)) { + domain.visibility = 'PUBLIC' + } + }) + + this.recordEmailsService.postEmails(this.userEmailsJson).subscribe( + (response) => { + this.afterSummit = true + this.beforeSummit = false + setTimeout(() => { + this.finish.emit() + }, 10000) + }, + (error) => this.finish.emit() + ) + } else { + this.finish.emit() + } + } +} diff --git a/src/app/cdk/platform-info/browserlist.regexp.ts b/src/app/cdk/platform-info/browserlist.regexp.ts index 545a90290e..bf8c4aa5cf 100644 --- a/src/app/cdk/platform-info/browserlist.regexp.ts +++ b/src/app/cdk/platform-info/browserlist.regexp.ts @@ -1,3 +1,2 @@ // tslint:disable-next-line: max-line-length -export const BROWSERLIST_REGEXP = - /((CPU[ +]OS|iPhone[ +]OS|CPU[ +]iPhone|CPU IPhone OS)[ +]+(13[_.]4|13[_.]([5-9]|\d{2,})|13[_.]7|13[_.]([8-9]|\d{2,})|(1[4-9]|[2-9]\d|\d{3,})[_.]\d+|14[_.]0|14[_.]([1-9]|\d{2,})|14[_.]4|14[_.]([5-9]|\d{2,})|14[_.]8|14[_.](9|\d{2,})|(1[5-9]|[2-9]\d|\d{3,})[_.]\d+|15[_.]0|15[_.]([1-9]|\d{2,})|(1[6-9]|[2-9]\d|\d{3,})[_.]\d+|16[_.]0|16[_.]([1-9]|\d{2,})|(1[7-9]|[2-9]\d|\d{3,})[_.]\d+|17[_.]0|17[_.]([1-9]|\d{2,})|(1[8-9]|[2-9]\d|\d{3,})[_.]\d+)(?:[_.]\d+)?)|((?:Chrome).*OPR\/(74|(7[5-9]|[8-9]\d|\d{3,}))\.\d+\.\d+)|(Edge\/(80|(8[1-9]|9\d|\d{3,})|83|(8[4-9]|9\d|\d{3,}))(?:\.\d+)?)|((Chromium|Chrome)\/(80|(8[1-9]|9\d|\d{3,})|83|(8[4-9]|9\d|\d{3,}))\.\d+(?:\.\d+)?)|(Version\/(13\.1|13\.([2-9]|\d{2,})|(1[4-9]|[2-9]\d|\d{3,})\.\d+|14\.0|14\.([1-9]|\d{2,})|(1[5-9]|[2-9]\d|\d{3,})\.\d+|15\.0|15\.([1-9]|\d{2,})|(1[6-9]|[2-9]\d|\d{3,})\.\d+|16\.0|16\.([1-9]|\d{2,})|(1[7-9]|[2-9]\d|\d{3,})\.\d+|17\.0|17\.([1-9]|\d{2,})|(1[8-9]|[2-9]\d|\d{3,})\.\d+)(?:\.\d+)? Safari\/)|(Firefox\/(78|(79|[8-9]\d|\d{3,}))\.\d+\.\d+)|(Firefox\/(78|(79|[8-9]\d|\d{3,}))\.\d+(pre|[ab]\d+[a-z]*)?)/ +export const BROWSERLIST_REGEXP = /((CPU[ +]OS|iPhone[ +]OS|CPU[ +]iPhone|CPU IPhone OS)[ +]+(13[_.]4|13[_.]([5-9]|\d{2,})|13[_.]7|13[_.]([8-9]|\d{2,})|(1[4-9]|[2-9]\d|\d{3,})[_.]\d+|14[_.]0|14[_.]([1-9]|\d{2,})|14[_.]4|14[_.]([5-9]|\d{2,})|14[_.]8|14[_.](9|\d{2,})|(1[5-9]|[2-9]\d|\d{3,})[_.]\d+|15[_.]0|15[_.]([1-9]|\d{2,})|(1[6-9]|[2-9]\d|\d{3,})[_.]\d+|16[_.]0|16[_.]([1-9]|\d{2,})|(1[7-9]|[2-9]\d|\d{3,})[_.]\d+|17[_.]0|17[_.]([1-9]|\d{2,})|(1[8-9]|[2-9]\d|\d{3,})[_.]\d+)(?:[_.]\d+)?)|((?:Chrome).*OPR\/(74|(7[5-9]|[8-9]\d|\d{3,}))\.\d+\.\d+)|(Edge\/(80|(8[1-9]|9\d|\d{3,})|83|(8[4-9]|9\d|\d{3,}))(?:\.\d+)?)|((Chromium|Chrome)\/(80|(8[1-9]|9\d|\d{3,})|83|(8[4-9]|9\d|\d{3,}))\.\d+(?:\.\d+)?)|(Version\/(13\.1|13\.([2-9]|\d{2,})|(1[4-9]|[2-9]\d|\d{3,})\.\d+|14\.0|14\.([1-9]|\d{2,})|(1[5-9]|[2-9]\d|\d{3,})\.\d+|15\.0|15\.([1-9]|\d{2,})|(1[6-9]|[2-9]\d|\d{3,})\.\d+|16\.0|16\.([1-9]|\d{2,})|(1[7-9]|[2-9]\d|\d{3,})\.\d+|17\.0|17\.([1-9]|\d{2,})|(1[8-9]|[2-9]\d|\d{3,})\.\d+)(?:\.\d+)? Safari\/)|(Firefox\/(78|(79|[8-9]\d|\d{3,}))\.\d+\.\d+)|(Firefox\/(78|(79|[8-9]\d|\d{3,}))\.\d+(pre|[ab]\d+[a-z]*)?)/ diff --git a/src/assets/scss/material.light-theme.scss b/src/assets/scss/material.light-theme.scss index e5c9412da9..0c406c3e12 100644 --- a/src/assets/scss/material.light-theme.scss +++ b/src/assets/scss/material.light-theme.scss @@ -55,6 +55,7 @@ state-notice-light: $state-notice-light, state-notice-dark: $state-notice-dark, state-notice-darkest: $state-notice-darkest, + state-info-darkest: $state-info-darkest, state-warning-dark: $state-warning-dark, state-info-dark: $state-info-dark, text-dark-mid: $text-dark-mid, diff --git a/src/assets/vectors/check-window.svg b/src/assets/vectors/check-window.svg new file mode 100644 index 0000000000..f786d3562b --- /dev/null +++ b/src/assets/vectors/check-window.svg @@ -0,0 +1,4 @@ + + + + diff --git a/src/assets/vectors/thumbs-up.svg b/src/assets/vectors/thumbs-up.svg new file mode 100644 index 0000000000..240c45c88a --- /dev/null +++ b/src/assets/vectors/thumbs-up.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/locale/properties/interstitials/interstitials.en.properties b/src/locale/properties/interstitials/interstitials.en.properties new file mode 100644 index 0000000000..288fd383e2 --- /dev/null +++ b/src/locale/properties/interstitials/interstitials.en.properties @@ -0,0 +1,11 @@ +interstitial.continueTo=Continue to +interstitial.visitYourOrcidRecord=Visit your ORCID record to manage your email addresses, domains, affiliations, works and more. +interstitial.theFollowingEmailDomains=The following email domains are now visible on your public ORCID record. +interstitial.emailDomainsShared=Email domains shared +interstitial.continueWithoutMakingDomainsPublic=Continue without making domains public +interstitial.makeSelectedDomainsPublic=Make selected domains public +interstitial.uncheckedAnyEmail=Uncheck any email domains you don’t want to share on your public ORCID record +interstitial.yourVerifiedEmailDomains=Your verified email domains +interstitial.sharingYourEmailDomains=Sharing your email domains lets you prove your association with an organization or institution without having to make your full email address public. +interstitial.weFoundSomeUnshared=We’ve found some unshared email domains in your ORCID record. +interstitial.shareYourVerified=Share your verified email domains diff --git a/src/locale/properties/interstitials/interstitials.lr.properties b/src/locale/properties/interstitials/interstitials.lr.properties new file mode 100644 index 0000000000..653dd4c52e --- /dev/null +++ b/src/locale/properties/interstitials/interstitials.lr.properties @@ -0,0 +1,11 @@ +interstitial.continueTo=LR +interstitial.visitYourOrcidRecord=LR +interstitial.theFollowingEmailDomains=LR +interstitial.emailDomainsShared=LR +interstitial.continueWithoutMakingDomainsPublic=LR +interstitial.makeSelectedDomainsPublic=LR +interstitial.uncheckedAnyEmail=LR +interstitial.yourVerifiedEmailDomains=LR +interstitial.sharingYourEmailDomains=LR +interstitial.weFoundSomeUnshared=LR +interstitial.shareYourVerified=LR diff --git a/src/locale/properties/interstitials/interstitials.rl.properties b/src/locale/properties/interstitials/interstitials.rl.properties new file mode 100644 index 0000000000..30438a909f --- /dev/null +++ b/src/locale/properties/interstitials/interstitials.rl.properties @@ -0,0 +1,11 @@ +interstitial.continueTo=RL +interstitial.visitYourOrcidRecord=RL +interstitial.theFollowingEmailDomains=RL +interstitial.emailDomainsShared=RL +interstitial.continueWithoutMakingDomainsPublic=RL +interstitial.makeSelectedDomainsPublic=RL +interstitial.uncheckedAnyEmail=RL +interstitial.yourVerifiedEmailDomains=RL +interstitial.sharingYourEmailDomains=RL +interstitial.weFoundSomeUnshared=RL +interstitial.shareYourVerified=RL diff --git a/src/locale/properties/interstitials/interstitials.xx.properties b/src/locale/properties/interstitials/interstitials.xx.properties new file mode 100644 index 0000000000..e5b3788cb3 --- /dev/null +++ b/src/locale/properties/interstitials/interstitials.xx.properties @@ -0,0 +1,11 @@ +interstitial.continueTo=X +interstitial.visitYourOrcidRecord=X +interstitial.theFollowingEmailDomains=X +interstitial.emailDomainsShared=X +interstitial.continueWithoutMakingDomainsPublic=X +interstitial.makeSelectedDomainsPublic=X +interstitial.uncheckedAnyEmail=X +interstitial.yourVerifiedEmailDomains=X +interstitial.sharingYourEmailDomains=X +interstitial.weFoundSomeUnshared=X +interstitial.shareYourVerified=X