-
Notifications
You must be signed in to change notification settings - Fork 39
Expand file tree
/
Copy pathlogin-main-interstitials-manager.service.ts
More file actions
177 lines (164 loc) · 5.71 KB
/
Copy pathlogin-main-interstitials-manager.service.ts
File metadata and controls
177 lines (164 loc) · 5.71 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
import { Component, Injectable, Type } from '@angular/core'
import { Observable, EMPTY, from, of } from 'rxjs'
import {
concatMap,
filter,
finalize,
switchMap,
take,
tap,
} from 'rxjs/operators'
import { UserRecord } from 'src/app/types/record.local'
import { LoginDomainInterstitialManagerService } from './implementations/login-domain-interstitials-manager.service'
import { LoginAffiliationInterstitialManagerService } from './implementations/login-affiliation-interstitials-manager.service'
import { InterstitialsService } from 'src/app/cdk/interstitials/interstitials.service'
import { LoginBaseInterstitialManagerService } from './abstractions/login-abstract-interstitial-manager.service'
import {
BaseInterstitialDialogInput,
BaseInterstitialDialogOutput,
} from './abstractions/dialog-interface'
import { ComponentType } from '@angular/cdk/overlay'
@Injectable({
providedIn: 'root',
})
export class LoginMainInterstitialsManagerService {
private alreadyCheckedLoginInterstitials = false
private interstitialServices: LoginBaseInterstitialManagerService<
BaseInterstitialDialogInput,
BaseInterstitialDialogOutput,
any
>[] = []
constructor(
private interstitialsService: InterstitialsService,
LoginDomainInterstitialManagerService: LoginDomainInterstitialManagerService,
LoginAffiliationInterstitialManagerService: LoginAffiliationInterstitialManagerService
) {
// Delare here all the interstitial services.
// This are the entry points to add new interstitials.
// They should be added in the order they should be checked.
// The first one that returns a component or a dialog subscription will be used.
// The rest will be ignored.
this.interstitialServices = [
LoginDomainInterstitialManagerService,
LoginAffiliationInterstitialManagerService,
]
}
checkLoginInterstitials(
userRecord: UserRecord,
opts: { returnType: 'dialog'; togglzPrefix: 'LOGIN' }
): Observable<BaseInterstitialDialogOutput>
checkLoginInterstitials(
userRecord: UserRecord,
opts: { returnType: 'component'; togglzPrefix: 'OAUTH' }
): Observable<ComponentType<any>>
/**
* Main entry point to check whether login interstitials should be displayed.
* Only the first one that should be shown will be shown.
* Returns an Observable that completes after an interstitial is shown or if none is shown.
*/
checkLoginInterstitials(
userRecord: UserRecord,
opts: {
returnType: 'dialog' | 'component'
togglzPrefix: 'OAUTH' | 'LOGIN'
}
): Observable<BaseInterstitialDialogOutput | ComponentType<any>> {
// Basic sanity checks
if (!this.isValidUserRecord(userRecord)) return EMPTY
if (this.alreadyCheckedLoginInterstitials) return EMPTY
this.alreadyCheckedLoginInterstitials = true
if (
this.interstitialsService.checkIfSessionAlreadyCheckedInterstitialsLogic()
) {
if (runtimeEnvironment.debugger) {
console.info(
'[Interstitial Manager] Session already checked for login interstitials'
)
}
return EMPTY
}
return from(this.interstitialServices).pipe(
// For each service, run the eligibility logic
concatMap((service) =>
service.userIsElegibleForInterstitial(userRecord).pipe(
tap((result) =>
this.debugLog(service, 'user is eligible for interstitial:', result)
),
// Only pass through if eligible
filter(Boolean),
// Check togglz setting
switchMap(() => service.getInterstitialTogglz(opts.togglzPrefix)),
tap((togglzState) =>
this.debugLog(
service,
`togglz state (prefix by ${opts.togglzPrefix}):`,
togglzState
)
),
// Only pass through if togglz is enabled
filter(Boolean),
// Check if already viewed
switchMap(() => service.getInterstitialViewed()),
tap((hasBeenViewed) =>
this.debugLog(service, 'has been viewed:', hasBeenViewed, false)
),
filter((hasBeenViewed) => !hasBeenViewed),
// Show the interstitial
switchMap(() => {
if (opts?.returnType === 'component') {
this.debugLog(service, 'will show interstitial as a component 👀')
return service.showInterstitialAsComponent()
} else {
this.debugLog(service, 'show interstitial as a dialog 👀')
return service.showInterstitialAsDialog(userRecord)
}
})
)
),
// Only the first eligible service that passes all checks is used
take(1),
// On complete or error, mark the session as checked
finalize(() => {
if (runtimeEnvironment.debugger) {
console.info('[Interstitial Manager] Finalize interstitials logic')
}
this.interstitialsService.markCurrentSessionToNoCheckInterstitialsLogic()
})
)
}
debugLog(
service: any,
message: string,
value?: any,
valueShouldBe: boolean = true
) {
if (runtimeEnvironment.debugger) {
console.info(
'[Interstitial Manager]',
service.INTERSTITIAL_NAME,
message,
value !== undefined ? value : '',
value !== undefined
? valueShouldBe === value
? '✅'
: "❌ (won't show)"
: ''
)
}
}
/**
* Valid user check & ensures not impersonating
*/
isValidUserRecord(userRecord: UserRecord): boolean {
if (
!userRecord?.userInfo ||
!userRecord?.emails ||
!userRecord?.affiliations?.length
)
return false
return (
userRecord.userInfo.REAL_USER_ORCID ===
userRecord.userInfo.EFFECTIVE_USER_ORCID
)
}
}