@equinor/fusion-framework-react-components-people-provider 1.0.1 → 1.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +41 -0
- package/README.md +15 -1
- package/dist/esm/PeopleResolver.js +4 -3
- package/dist/esm/PeopleResolver.js.map +1 -1
- package/dist/esm/PeopleResolverProvider.js +3 -2
- package/dist/esm/PeopleResolverProvider.js.map +1 -1
- package/dist/esm/PersonController.js +57 -55
- package/dist/esm/PersonController.js.map +1 -1
- package/dist/esm/create-resolver.js.map +1 -1
- package/dist/esm/makeResolver.js +4 -4
- package/dist/esm/makeResolver.js.map +1 -1
- package/dist/esm/version.js +1 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/dist/types/PeopleResolver.d.ts +2 -1
- package/dist/types/PeopleResolverProvider.d.ts +6 -3
- package/dist/types/PersonController.d.ts +27 -14
- package/dist/types/makeResolver.d.ts +2 -1
- package/dist/types/version.d.ts +1 -1
- package/package.json +9 -9
- package/src/PeopleResolver.tsx +6 -2
- package/src/PeopleResolverProvider.tsx +9 -3
- package/src/PersonController.ts +118 -112
- package/src/create-resolver.ts +1 -1
- package/src/makeResolver.tsx +5 -5
- package/src/version.ts +1 -1
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { PersonResolver } from '@equinor/fusion-wc-person';
|
|
2
|
-
export
|
|
2
|
+
export { PersonResolver };
|
|
3
|
+
export declare const PeopleResolverComponent: (props: React.PropsWithChildren<{
|
|
3
4
|
resolver: PersonResolver;
|
|
4
5
|
}>) => import("react/jsx-runtime").JSX.Element;
|
|
@@ -1,4 +1,7 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
1
|
+
import { PropsWithChildren } from 'react';
|
|
2
|
+
import { PersonControllerOptions } from './PersonController';
|
|
3
|
+
type PeopleResolverProviderProps = PropsWithChildren<{
|
|
4
|
+
readonly options?: PersonControllerOptions;
|
|
5
|
+
}>;
|
|
6
|
+
export declare const PeopleResolverProvider: (props: PeopleResolverProviderProps) => import("react/jsx-runtime").JSX.Element;
|
|
4
7
|
export default PeopleResolverProvider;
|
|
@@ -14,28 +14,41 @@ type MatcherArgs = {
|
|
|
14
14
|
upn?: string;
|
|
15
15
|
azureId: string;
|
|
16
16
|
};
|
|
17
|
+
type ResolverArgs<T> = T extends object ? {
|
|
18
|
+
[K in keyof T]: T[K];
|
|
19
|
+
} & {
|
|
20
|
+
signal?: AbortSignal;
|
|
21
|
+
} : {
|
|
22
|
+
signal?: AbortSignal;
|
|
23
|
+
};
|
|
17
24
|
export interface IPersonController {
|
|
18
|
-
getPerson(args: MatcherArgs): Observable<GetPersonResult>;
|
|
19
|
-
getPersonInfo(args: MatcherArgs): Observable<ApiPerson<'v2'>>;
|
|
20
|
-
getPhoto(args: MatcherArgs): Observable<string>;
|
|
21
|
-
search(args: {
|
|
25
|
+
getPerson(args: ResolverArgs<MatcherArgs>): Observable<GetPersonResult>;
|
|
26
|
+
getPersonInfo(args: ResolverArgs<MatcherArgs>): Observable<ApiPerson<'v2'>>;
|
|
27
|
+
getPhoto(args: ResolverArgs<MatcherArgs>): Observable<string>;
|
|
28
|
+
search(args: ResolverArgs<{
|
|
22
29
|
search: string;
|
|
23
|
-
}): Observable<PersonSearchResult>;
|
|
30
|
+
}>): Observable<PersonSearchResult>;
|
|
24
31
|
}
|
|
32
|
+
export type PersonControllerOptions = {
|
|
33
|
+
fallbackImage?: Blob;
|
|
34
|
+
};
|
|
25
35
|
export declare class PersonController implements IPersonController {
|
|
26
36
|
#private;
|
|
27
|
-
constructor(client: PeopleApiClient);
|
|
28
|
-
getPhoto(args: MatcherArgs): Observable<string>;
|
|
29
|
-
getPerson(args: MatcherArgs): Observable<GetPersonResult>;
|
|
30
|
-
getPersonInfo(args: MatcherArgs): Observable<ApiPerson<'v2'>>;
|
|
37
|
+
constructor(client: PeopleApiClient, options?: PersonControllerOptions);
|
|
31
38
|
search(args: {
|
|
32
39
|
search: string;
|
|
40
|
+
signal?: AbortSignal;
|
|
33
41
|
}): Observable<PersonSearchResult>;
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
protected
|
|
42
|
+
getPhoto(args: ResolverArgs<MatcherArgs>): Observable<string>;
|
|
43
|
+
getPerson(args: ResolverArgs<MatcherArgs>): Observable<GetPersonResult>;
|
|
44
|
+
getPersonInfo(args: ResolverArgs<MatcherArgs>): Observable<ApiPerson<'v2'>>;
|
|
45
|
+
protected _getPersonByUpn(upn: string, signal?: AbortSignal): Observable<GetPersonResult>;
|
|
46
|
+
_getPersonByAzureId(azureId: string, signal?: AbortSignal): Observable<GetPersonResult>;
|
|
47
|
+
protected _getPersonInfoById(azureId: string, signal?: AbortSignal): Observable<ApiPerson<'v2'>>;
|
|
48
|
+
protected _getPersonInfoByUpn(upn: string, signal?: AbortSignal): Observable<ApiPerson<'v2'>>;
|
|
49
|
+
protected _getPersonPhotoByAzureId(azureId: string, signal?: AbortSignal): Observable<string>;
|
|
50
|
+
protected _getPersonPhotoByUpn(upn: string, signal?: AbortSignal): Observable<string>;
|
|
38
51
|
protected _personCache$(args: MatcherArgs): Observable<GetPersonResult>;
|
|
39
|
-
protected _queryCache$(args: MatcherArgs): Observable<
|
|
52
|
+
protected _queryCache$(args: MatcherArgs): Observable<ApiPerson<'v2'>>;
|
|
40
53
|
}
|
|
41
54
|
export {};
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
/// <reference types="react" />
|
|
2
|
+
import { PersonControllerOptions } from './PersonController';
|
|
2
3
|
import { IApiProvider } from '@equinor/fusion-framework-module-services';
|
|
3
|
-
export declare const makeResolver: (services: IApiProvider) => import("react").LazyExoticComponent<({ children }: {
|
|
4
|
+
export declare const makeResolver: (services: IApiProvider, options?: PersonControllerOptions) => import("react").LazyExoticComponent<({ children }: {
|
|
4
5
|
readonly children?: React.ReactNode;
|
|
5
6
|
}) => import("react/jsx-runtime").JSX.Element>;
|
package/dist/types/version.d.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export declare const version = "1.0
|
|
1
|
+
export declare const version = "1.1.0";
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@equinor/fusion-framework-react-components-people-provider",
|
|
3
|
-
"version": "1.0
|
|
3
|
+
"version": "1.1.0",
|
|
4
4
|
"description": "",
|
|
5
5
|
"main": "dist/esm/index.js",
|
|
6
6
|
"exports": {
|
|
@@ -20,20 +20,20 @@
|
|
|
20
20
|
},
|
|
21
21
|
"dependencies": {
|
|
22
22
|
"rxjs": "^7.8.1",
|
|
23
|
-
"@equinor/fusion-framework-
|
|
23
|
+
"@equinor/fusion-framework-module-services": "^3.2.2",
|
|
24
|
+
"@equinor/fusion-framework-react": "^5.3.2",
|
|
24
25
|
"@equinor/fusion-framework-react-module": "^3.0.6",
|
|
25
|
-
"@equinor/fusion-framework-react-module-bookmark": "^2.0.
|
|
26
|
-
"@equinor/fusion-query": "^4.0.
|
|
26
|
+
"@equinor/fusion-framework-react-module-bookmark": "^2.0.20",
|
|
27
|
+
"@equinor/fusion-query": "^4.0.2"
|
|
27
28
|
},
|
|
28
29
|
"devDependencies": {
|
|
29
|
-
"@equinor/fusion-wc-person": "
|
|
30
|
+
"@equinor/fusion-wc-person": "^2.0.1",
|
|
30
31
|
"@types/react": "^18.2.20",
|
|
31
32
|
"react": "^18.2.0",
|
|
32
33
|
"typescript": "^5.1.3",
|
|
33
|
-
"@equinor/fusion-framework-module-app": "^5.2.
|
|
34
|
-
"@equinor/fusion-framework-module-bookmark": "^1.0.
|
|
35
|
-
"@equinor/fusion-framework-module-event": "^4.0.6"
|
|
36
|
-
"@equinor/fusion-framework-module-services": "^3.2.1"
|
|
34
|
+
"@equinor/fusion-framework-module-app": "^5.2.7",
|
|
35
|
+
"@equinor/fusion-framework-module-bookmark": "^1.0.13",
|
|
36
|
+
"@equinor/fusion-framework-module-event": "^4.0.6"
|
|
37
37
|
},
|
|
38
38
|
"peerDependencies": {
|
|
39
39
|
"@types/react": "^17.0.0 || ^18.0.0",
|
package/src/PeopleResolver.tsx
CHANGED
|
@@ -6,19 +6,23 @@ import {
|
|
|
6
6
|
PersonCardElement,
|
|
7
7
|
PersonResolver,
|
|
8
8
|
PersonListItemElement,
|
|
9
|
+
PersonSelectElement,
|
|
9
10
|
} from '@equinor/fusion-wc-person';
|
|
10
11
|
|
|
11
12
|
PersonProviderElement;
|
|
12
13
|
PersonAvatarElement;
|
|
13
14
|
PersonCardElement;
|
|
14
15
|
PersonListItemElement;
|
|
16
|
+
PersonSelectElement;
|
|
15
17
|
|
|
16
|
-
export
|
|
18
|
+
export { PersonResolver };
|
|
19
|
+
|
|
20
|
+
export const PeopleResolverComponent = (props: React.PropsWithChildren<{ resolver: PersonResolver }>) => {
|
|
17
21
|
const { resolver, children } = props;
|
|
18
22
|
const ref = useRef<PersonProviderElement | null>(null);
|
|
19
23
|
useEffect(() => {
|
|
20
24
|
if (ref.current && resolver) {
|
|
21
|
-
ref.current.
|
|
25
|
+
ref.current.resolver = resolver;
|
|
22
26
|
}
|
|
23
27
|
}, [ref, resolver]);
|
|
24
28
|
return <fwc-person-provider ref={ref}>{children}</fwc-person-provider>;
|
|
@@ -1,14 +1,20 @@
|
|
|
1
|
-
import { Suspense, useMemo } from 'react';
|
|
1
|
+
import { PropsWithChildren, Suspense, useMemo } from 'react';
|
|
2
2
|
import { ServicesModule } from '@equinor/fusion-framework-module-services';
|
|
3
3
|
import { useModule } from '@equinor/fusion-framework-react-module';
|
|
4
4
|
import { makeResolver } from './makeResolver';
|
|
5
|
+
import { PersonControllerOptions } from './PersonController';
|
|
5
6
|
|
|
6
|
-
|
|
7
|
+
type PeopleResolverProviderProps = PropsWithChildren<{
|
|
8
|
+
readonly options?: PersonControllerOptions;
|
|
9
|
+
}>;
|
|
10
|
+
|
|
11
|
+
export const PeopleResolverProvider = (props: PeopleResolverProviderProps) => {
|
|
12
|
+
const { children, options } = props;
|
|
7
13
|
const services = useModule<ServicesModule>('services');
|
|
8
14
|
if (!services) {
|
|
9
15
|
throw Error('missing service module');
|
|
10
16
|
}
|
|
11
|
-
const Component = useMemo(() => makeResolver(services), [services]);
|
|
17
|
+
const Component = useMemo(() => makeResolver(services, options), [services, options]);
|
|
12
18
|
return (
|
|
13
19
|
<Suspense fallback={<span>TODO</span>}>
|
|
14
20
|
<Component>{children}</Component>
|
package/src/PersonController.ts
CHANGED
|
@@ -1,10 +1,14 @@
|
|
|
1
|
-
import { Observable, concat, from } from 'rxjs';
|
|
2
|
-
import { filter, find, map,
|
|
1
|
+
import { EMPTY, Observable, concat, from, fromEvent, of } from 'rxjs';
|
|
2
|
+
import { catchError, filter, find, map, switchMap, take, takeUntil } from 'rxjs/operators';
|
|
3
3
|
|
|
4
4
|
import type { ApiPerson, PeopleApiClient } from '@equinor/fusion-framework-module-services/people';
|
|
5
|
+
import { isApiPerson } from '@equinor/fusion-framework-module-services/people/utils';
|
|
5
6
|
import type { ApiResponse as GetPersonApiResponse } from '@equinor/fusion-framework-module-services/people/get';
|
|
6
7
|
import type { ApiResponse as QueryPersonApiResponse } from '@equinor/fusion-framework-module-services/people/query';
|
|
7
|
-
import Query from '@equinor/fusion-query';
|
|
8
|
+
import { Query } from '@equinor/fusion-query';
|
|
9
|
+
import { queryValue } from '@equinor/fusion-query/operators';
|
|
10
|
+
|
|
11
|
+
import { ApiProviderError } from '@equinor/fusion-framework-module-services/provider';
|
|
8
12
|
|
|
9
13
|
type GetPersonResult = GetPersonApiResponse<
|
|
10
14
|
'v4',
|
|
@@ -15,6 +19,10 @@ type PersonSearchResult = QueryPersonApiResponse<'v2'>;
|
|
|
15
19
|
|
|
16
20
|
type MatcherArgs = { upn: string; azureId?: string } | { upn?: string; azureId: string };
|
|
17
21
|
|
|
22
|
+
type ResolverArgs<T> = T extends object
|
|
23
|
+
? { [K in keyof T]: T[K] } & { signal?: AbortSignal }
|
|
24
|
+
: { signal?: AbortSignal };
|
|
25
|
+
|
|
18
26
|
const personMatcher =
|
|
19
27
|
(args: MatcherArgs) =>
|
|
20
28
|
<T extends { azureUniqueId?: string; upn?: string }>(value: T): value is T => {
|
|
@@ -33,18 +41,22 @@ const personMatcher =
|
|
|
33
41
|
};
|
|
34
42
|
|
|
35
43
|
export interface IPersonController {
|
|
36
|
-
getPerson(args: MatcherArgs): Observable<GetPersonResult>;
|
|
37
|
-
getPersonInfo(args: MatcherArgs): Observable<ApiPerson<'v2'>>;
|
|
38
|
-
getPhoto(args: MatcherArgs): Observable<string>;
|
|
39
|
-
search(args: { search: string }): Observable<PersonSearchResult>;
|
|
44
|
+
getPerson(args: ResolverArgs<MatcherArgs>): Observable<GetPersonResult>;
|
|
45
|
+
getPersonInfo(args: ResolverArgs<MatcherArgs>): Observable<ApiPerson<'v2'>>;
|
|
46
|
+
getPhoto(args: ResolverArgs<MatcherArgs>): Observable<string>;
|
|
47
|
+
search(args: ResolverArgs<{ search: string }>): Observable<PersonSearchResult>;
|
|
40
48
|
}
|
|
41
49
|
|
|
50
|
+
export type PersonControllerOptions = {
|
|
51
|
+
fallbackImage?: Blob;
|
|
52
|
+
};
|
|
53
|
+
|
|
42
54
|
export class PersonController implements IPersonController {
|
|
43
|
-
#personQuery: Query<GetPersonResult, { azureId: string }
|
|
44
|
-
#personSearchQuery: Query<PersonSearchResult, { search: string }
|
|
45
|
-
#personPhotoQuery: Query<Blob, { azureId: string }
|
|
55
|
+
#personQuery: Query<GetPersonResult, ResolverArgs<{ azureId: string }>>;
|
|
56
|
+
#personSearchQuery: Query<PersonSearchResult, ResolverArgs<{ search: string }>>;
|
|
57
|
+
#personPhotoQuery: Query<Blob, ResolverArgs<{ azureId: string }>>;
|
|
46
58
|
|
|
47
|
-
constructor(client: PeopleApiClient) {
|
|
59
|
+
constructor(client: PeopleApiClient, options?: PersonControllerOptions) {
|
|
48
60
|
const expire = 3 * 60 * 1000;
|
|
49
61
|
this.#personQuery = new Query({
|
|
50
62
|
expire,
|
|
@@ -77,137 +89,129 @@ export class PersonController implements IPersonController {
|
|
|
77
89
|
key: ({ azureId }) => azureId,
|
|
78
90
|
client: {
|
|
79
91
|
fn: ({ azureId }, signal) => {
|
|
80
|
-
return client.photo('v2', 'blob$', { azureId }, { signal })
|
|
92
|
+
return client.photo('v2', 'blob$', { azureId }, { signal }).pipe(
|
|
93
|
+
catchError((err) => {
|
|
94
|
+
const apiError = err as ApiProviderError;
|
|
95
|
+
if (apiError.response.status === 404 && options?.fallbackImage) {
|
|
96
|
+
return of(options?.fallbackImage);
|
|
97
|
+
}
|
|
98
|
+
return of(err);
|
|
99
|
+
}),
|
|
100
|
+
);
|
|
81
101
|
},
|
|
82
102
|
},
|
|
83
103
|
});
|
|
84
104
|
}
|
|
85
105
|
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
106
|
+
public search(args: { search: string; signal?: AbortSignal }): Observable<PersonSearchResult> {
|
|
107
|
+
const { search, signal } = args;
|
|
108
|
+
return this.#personSearchQuery.query({ search }, { signal }).pipe(queryValue);
|
|
109
|
+
}
|
|
89
110
|
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
.pipe(map((blob) => URL.createObjectURL(blob.value)));
|
|
111
|
+
/** TODO why does this need to have data?!? */
|
|
112
|
+
public getPhoto(args: ResolverArgs<MatcherArgs>): Observable<string> {
|
|
113
|
+
const { azureId, upn, signal } = args;
|
|
94
114
|
|
|
95
115
|
if (azureId) {
|
|
96
|
-
return
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
if (!azureId && upn) {
|
|
100
|
-
const matcher = personMatcher({ upn });
|
|
101
|
-
const cache$ = this._personCache$(args).pipe(raceWith(this._queryCache$(args)));
|
|
102
|
-
return concat(
|
|
103
|
-
/** */
|
|
104
|
-
cache$.pipe(
|
|
105
|
-
find(matcher),
|
|
106
|
-
filter((x) => !!x),
|
|
107
|
-
),
|
|
108
|
-
this.getPersonInfo({ upn }),
|
|
109
|
-
).pipe(
|
|
110
|
-
/** */
|
|
111
|
-
filter((x): x is ApiPerson<'v2'> => {
|
|
112
|
-
return !!x;
|
|
113
|
-
}),
|
|
114
|
-
switchMap((x) => resolve(x.azureUniqueId)),
|
|
115
|
-
);
|
|
116
|
+
return this._getPersonPhotoByAzureId(azureId, signal);
|
|
117
|
+
} else if (upn) {
|
|
118
|
+
return this._getPersonPhotoByUpn(upn, signal);
|
|
116
119
|
}
|
|
117
120
|
throw Error('invalid args provided');
|
|
118
121
|
}
|
|
119
122
|
|
|
120
|
-
public getPerson(args: MatcherArgs): Observable<GetPersonResult> {
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
123
|
+
public getPerson(args: ResolverArgs<MatcherArgs>): Observable<GetPersonResult> {
|
|
124
|
+
const { azureId, upn, signal } = args;
|
|
125
|
+
if (azureId) {
|
|
126
|
+
return this._getPersonByAzureId(azureId, signal);
|
|
127
|
+
} else if (upn) {
|
|
128
|
+
return this._getPersonByUpn(upn, signal);
|
|
125
129
|
}
|
|
126
130
|
throw Error('invalid args provided');
|
|
127
131
|
}
|
|
128
132
|
|
|
129
|
-
public getPersonInfo(args: MatcherArgs): Observable<ApiPerson<'v2'>> {
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
133
|
+
public getPersonInfo(args: ResolverArgs<MatcherArgs>): Observable<ApiPerson<'v2'>> {
|
|
134
|
+
const { azureId, upn, signal } = args;
|
|
135
|
+
if (azureId) {
|
|
136
|
+
return this._getPersonInfoById(azureId, signal);
|
|
137
|
+
} else if (upn) {
|
|
138
|
+
return this._getPersonInfoByUpn(upn, signal);
|
|
134
139
|
}
|
|
135
140
|
throw Error('invalid args provided');
|
|
136
141
|
}
|
|
137
142
|
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
143
|
+
protected _getPersonByUpn(upn: string, signal?: AbortSignal): Observable<GetPersonResult> {
|
|
144
|
+
const abort$ = signal ? fromEvent(signal, 'abort') : EMPTY;
|
|
145
|
+
return concat(
|
|
146
|
+
this._personCache$({ upn }),
|
|
147
|
+
this._getPersonInfoByUpn(upn, signal).pipe(
|
|
148
|
+
filter(isApiPerson('v2')),
|
|
149
|
+
switchMap(({ azureUniqueId: azureId }) => {
|
|
150
|
+
return this._getPersonByAzureId(azureId, signal);
|
|
151
|
+
}),
|
|
152
|
+
),
|
|
153
|
+
).pipe(
|
|
154
|
+
/** */
|
|
155
|
+
filter(isApiPerson('v4')),
|
|
156
|
+
takeUntil(abort$),
|
|
142
157
|
);
|
|
143
158
|
}
|
|
144
159
|
|
|
145
|
-
|
|
146
|
-
return this.#personQuery.query({ azureId }).pipe(
|
|
160
|
+
public _getPersonByAzureId(azureId: string, signal?: AbortSignal): Observable<GetPersonResult> {
|
|
161
|
+
return this.#personQuery.query({ azureId }, { signal }).pipe(queryValue);
|
|
147
162
|
}
|
|
148
163
|
|
|
149
|
-
protected _getPersonInfoById(
|
|
164
|
+
protected _getPersonInfoById(
|
|
165
|
+
azureId: string,
|
|
166
|
+
signal?: AbortSignal,
|
|
167
|
+
): Observable<ApiPerson<'v2'>> {
|
|
168
|
+
const abort$ = signal ? fromEvent(signal, 'abort') : EMPTY;
|
|
150
169
|
return concat(
|
|
170
|
+
/** */
|
|
151
171
|
this._personCache$({ azureId }),
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
this.#personQuery.query({ azureId }).pipe(
|
|
155
|
-
// TODO add mapper from v4 -> v2
|
|
156
|
-
map((x) => x.value as ApiPerson<'v2'>),
|
|
157
|
-
),
|
|
158
|
-
).pipe(filter((x): x is ApiPerson<'v2'> => !!x)),
|
|
172
|
+
this._queryCache$({ azureId }),
|
|
173
|
+
this._getPersonByAzureId(azureId, signal),
|
|
159
174
|
).pipe(
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
}
|
|
164
|
-
return x as ApiPerson<'v2'>;
|
|
165
|
-
}),
|
|
175
|
+
/** */
|
|
176
|
+
filter(isApiPerson('v2')),
|
|
177
|
+
takeUntil(abort$),
|
|
166
178
|
);
|
|
167
179
|
}
|
|
168
180
|
|
|
169
|
-
protected
|
|
181
|
+
protected _getPersonInfoByUpn(upn: string, signal?: AbortSignal): Observable<ApiPerson<'v2'>> {
|
|
182
|
+
const matcher = personMatcher({ upn });
|
|
183
|
+
const abort$ = signal ? fromEvent(signal, 'abort') : EMPTY;
|
|
170
184
|
return concat(
|
|
171
185
|
this._personCache$({ upn }),
|
|
172
|
-
this.
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
),
|
|
179
|
-
),
|
|
186
|
+
this._queryCache$({ upn }),
|
|
187
|
+
this.#personSearchQuery.query({ search: upn }, { signal }).pipe(
|
|
188
|
+
/** extract first match, should only be 0 or 1 */
|
|
189
|
+
map((x) => x.value.find(matcher)),
|
|
190
|
+
/** type cast and end stream */
|
|
191
|
+
find(isApiPerson('v2')),
|
|
180
192
|
),
|
|
181
193
|
).pipe(
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
}),
|
|
194
|
+
/** */
|
|
195
|
+
find(isApiPerson('v2')),
|
|
196
|
+
filter(isApiPerson('v2')),
|
|
197
|
+
filter(isApiPerson('v2')),
|
|
198
|
+
takeUntil(abort$),
|
|
188
199
|
);
|
|
189
200
|
}
|
|
190
201
|
|
|
191
|
-
protected
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
).pipe(
|
|
205
|
-
map((x) => {
|
|
206
|
-
if (!x) {
|
|
207
|
-
throw Error(`upn [${upn}] not found`);
|
|
208
|
-
}
|
|
209
|
-
return x as ApiPerson<'v2'>;
|
|
210
|
-
}),
|
|
202
|
+
protected _getPersonPhotoByAzureId(azureId: string, signal?: AbortSignal): Observable<string> {
|
|
203
|
+
return this.#personPhotoQuery.query({ azureId }, { signal }).pipe(
|
|
204
|
+
/** */
|
|
205
|
+
take(1),
|
|
206
|
+
map((result) => URL.createObjectURL(result.value)),
|
|
207
|
+
);
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
protected _getPersonPhotoByUpn(upn: string, signal?: AbortSignal) {
|
|
211
|
+
return this._getPersonInfoByUpn(upn, signal).pipe(
|
|
212
|
+
/** */
|
|
213
|
+
take(1),
|
|
214
|
+
switchMap((x) => this._getPersonPhotoByAzureId(x.azureUniqueId, signal)),
|
|
211
215
|
);
|
|
212
216
|
}
|
|
213
217
|
|
|
@@ -218,25 +222,27 @@ export class PersonController implements IPersonController {
|
|
|
218
222
|
take(1),
|
|
219
223
|
/** map out cached ApiPerson_v2 which matches upn */
|
|
220
224
|
map((x) => Object.values(x).find((x) => mather(x.value))?.value),
|
|
221
|
-
|
|
225
|
+
find(isApiPerson('v4')),
|
|
226
|
+
filter(isApiPerson('v4')),
|
|
222
227
|
);
|
|
223
228
|
}
|
|
224
229
|
|
|
225
|
-
protected _queryCache$(args: MatcherArgs) {
|
|
230
|
+
protected _queryCache$(args: MatcherArgs): Observable<ApiPerson<'v2'>> {
|
|
226
231
|
const mather = personMatcher(args);
|
|
227
232
|
return this.#personSearchQuery.cache.state$.pipe(
|
|
228
233
|
/** make subscription cold */
|
|
229
234
|
take(1),
|
|
230
|
-
switchMap((entry) =>
|
|
235
|
+
switchMap((entry) => {
|
|
231
236
|
/** expand cache records */
|
|
232
|
-
from(Object.values(entry)).pipe(
|
|
237
|
+
return from(Object.values(entry)).pipe(
|
|
233
238
|
/** find matching cache record item */
|
|
234
239
|
map((x) => x.value.find((x) => mather(x))),
|
|
235
240
|
/** type cast and end stream */
|
|
236
|
-
find((
|
|
237
|
-
)
|
|
238
|
-
),
|
|
239
|
-
|
|
241
|
+
find(isApiPerson('v2')),
|
|
242
|
+
);
|
|
243
|
+
}),
|
|
244
|
+
find(isApiPerson('v2')),
|
|
245
|
+
filter(isApiPerson('v2')),
|
|
240
246
|
);
|
|
241
247
|
}
|
|
242
248
|
}
|
package/src/create-resolver.ts
CHANGED
|
@@ -16,7 +16,7 @@ export const createResolver = (controller: IPersonController): PersonResolver =>
|
|
|
16
16
|
return firstValueFrom(
|
|
17
17
|
controller.getPersonInfo(args).pipe(
|
|
18
18
|
/** TODO */
|
|
19
|
-
map((x) => ({ ...x, azureId: x.azureUniqueId }) as unknown as
|
|
19
|
+
map((x) => ({ ...x, azureId: x.azureUniqueId }) as unknown as PersonInfo),
|
|
20
20
|
),
|
|
21
21
|
);
|
|
22
22
|
},
|
package/src/makeResolver.tsx
CHANGED
|
@@ -1,16 +1,16 @@
|
|
|
1
1
|
import { lazy } from 'react';
|
|
2
|
-
import {
|
|
3
|
-
import { PersonController } from './PersonController';
|
|
2
|
+
import { PeopleResolverComponent } from './PeopleResolver';
|
|
3
|
+
import { PersonController, PersonControllerOptions } from './PersonController';
|
|
4
4
|
import { createResolver } from './create-resolver';
|
|
5
5
|
import { IApiProvider } from '@equinor/fusion-framework-module-services';
|
|
6
6
|
|
|
7
|
-
export const makeResolver = (services: IApiProvider) => {
|
|
7
|
+
export const makeResolver = (services: IApiProvider, options?: PersonControllerOptions) => {
|
|
8
8
|
return lazy(async () => {
|
|
9
9
|
const client = await services.createPeopleClient();
|
|
10
|
-
const controller = new PersonController(client);
|
|
10
|
+
const controller = new PersonController(client, options);
|
|
11
11
|
const resolver = createResolver(controller);
|
|
12
12
|
const Component = ({ children }: { readonly children?: React.ReactNode }) => (
|
|
13
|
-
<
|
|
13
|
+
<PeopleResolverComponent resolver={resolver}>{children}</PeopleResolverComponent>
|
|
14
14
|
);
|
|
15
15
|
return {
|
|
16
16
|
default: Component,
|
package/src/version.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
// Generated by genversion.
|
|
2
|
-
export const version = '1.0
|
|
2
|
+
export const version = '1.1.0';
|