@imposium-hub/components 2.5.17 → 2.6.0-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.
Files changed (67) hide show
  1. package/dist/cjs/Util.js +1 -2
  2. package/dist/cjs/Util.js.map +1 -1
  3. package/dist/cjs/components/app-wrapper/AppWrapper.d.ts +14 -22
  4. package/dist/cjs/components/app-wrapper/AppWrapper.js +170 -216
  5. package/dist/cjs/components/app-wrapper/AppWrapper.js.map +1 -1
  6. package/dist/cjs/components/app-wrapper/AppWrapperV2.d.ts +3 -9
  7. package/dist/cjs/components/app-wrapper/AppWrapperV2.js +119 -45
  8. package/dist/cjs/components/app-wrapper/AppWrapperV2.js.map +1 -1
  9. package/dist/cjs/components/app-wrapper/AppWrapperV3.d.ts +1 -1
  10. package/dist/cjs/components/app-wrapper/AppWrapperV3.js +7 -44
  11. package/dist/cjs/components/app-wrapper/AppWrapperV3.js.map +1 -1
  12. package/dist/cjs/components/compositions/TextLayer.js +0 -1
  13. package/dist/cjs/components/compositions/TextLayer.js.map +1 -1
  14. package/dist/cjs/components/header/Header.d.ts +6 -5
  15. package/dist/cjs/components/header/Header.js +46 -62
  16. package/dist/cjs/components/header/Header.js.map +1 -1
  17. package/dist/cjs/index.d.ts +2 -7
  18. package/dist/cjs/index.js +5 -17
  19. package/dist/cjs/index.js.map +1 -1
  20. package/dist/cjs/redux/actions/asset-uploads.js +0 -1
  21. package/dist/cjs/redux/actions/asset-uploads.js.map +1 -1
  22. package/dist/cjs/services/API.d.ts +6 -0
  23. package/dist/cjs/services/API.js +38 -9
  24. package/dist/cjs/services/API.js.map +1 -1
  25. package/dist/cjs/services/Session.d.ts +0 -11
  26. package/dist/cjs/services/Session.js +3 -126
  27. package/dist/cjs/services/Session.js.map +1 -1
  28. package/dist/esm/Util.js +1 -2
  29. package/dist/esm/Util.js.map +1 -1
  30. package/dist/esm/components/app-wrapper/AppWrapper.d.ts +14 -22
  31. package/dist/esm/components/app-wrapper/AppWrapper.js +75 -182
  32. package/dist/esm/components/app-wrapper/AppWrapper.js.map +1 -1
  33. package/dist/esm/components/app-wrapper/AppWrapperV2.d.ts +3 -9
  34. package/dist/esm/components/app-wrapper/AppWrapperV2.js +30 -33
  35. package/dist/esm/components/app-wrapper/AppWrapperV2.js.map +1 -1
  36. package/dist/esm/components/app-wrapper/AppWrapperV3.d.ts +1 -1
  37. package/dist/esm/components/app-wrapper/AppWrapperV3.js +5 -42
  38. package/dist/esm/components/app-wrapper/AppWrapperV3.js.map +1 -1
  39. package/dist/esm/components/compositions/TextLayer.js +0 -1
  40. package/dist/esm/components/compositions/TextLayer.js.map +1 -1
  41. package/dist/esm/components/header/Header.d.ts +6 -5
  42. package/dist/esm/components/header/Header.js +46 -60
  43. package/dist/esm/components/header/Header.js.map +1 -1
  44. package/dist/esm/index.d.ts +2 -7
  45. package/dist/esm/index.js +2 -7
  46. package/dist/esm/index.js.map +1 -1
  47. package/dist/esm/redux/actions/asset-uploads.js +0 -1
  48. package/dist/esm/redux/actions/asset-uploads.js.map +1 -1
  49. package/dist/esm/services/API.d.ts +6 -0
  50. package/dist/esm/services/API.js +37 -9
  51. package/dist/esm/services/API.js.map +1 -1
  52. package/dist/esm/services/Session.d.ts +0 -11
  53. package/dist/esm/services/Session.js +3 -84
  54. package/dist/esm/services/Session.js.map +1 -1
  55. package/package.json +3 -2
  56. package/src/Util.ts +1 -2
  57. package/src/components/app-wrapper/AppWrapper.tsx +131 -272
  58. package/src/components/compositions/TextLayer.tsx +0 -1
  59. package/src/components/header/Header.tsx +55 -80
  60. package/src/index.ts +1 -14
  61. package/src/redux/actions/asset-uploads.ts +0 -1
  62. package/src/services/API.ts +48 -9
  63. package/src/components/auth-gate/AuthGate.tsx +0 -84
  64. package/src/redux/actions/auth.ts +0 -30
  65. package/src/redux/reducers/auth.ts +0 -33
  66. package/src/services/Auth0.ts +0 -82
  67. package/src/services/Session.ts +0 -153
@@ -1,308 +1,167 @@
1
1
  import * as React from 'react';
2
- import NoAccess from '../no-access/NoAccess';
3
2
  import Header from '../header/Header';
4
- import SessionService from '../../services/Session';
5
- import AuthService, { IIdentity } from '../../services/Auth0';
6
- import { connect } from 'react-redux';
7
- import { bindActionCreators } from 'redux';
8
- import { login, clearCachedAuth } from '../../redux/actions/auth';
9
3
  import { validateAccessLevel } from '../../Util';
10
- import { setAccessData } from '../../redux/actions/access';
11
4
  import { ConfirmModal } from '../confirm-modal/ConfirmModal';
5
+ import API, { IImposiumAPI } from '../../services/API';
6
+ import { useAuth0 } from '@auth0/auth0-react';
12
7
 
13
8
  export interface IAppWrapperProps {
14
- children: React.ReactChildren;
15
- auth0Domain: string;
16
- auth0ClientId: string;
17
- organizationId: string;
18
9
  baseUrl: string;
19
- storyId?: string;
10
+ api: IImposiumAPI;
11
+ children?: any;
12
+ organizationId: string;
20
13
  serviceId: number;
21
- access: any;
22
- auth: any;
23
- isFreshUser: boolean;
24
- setAccessData(accessData: any): any;
25
- allowUnauthenticatedRender: boolean;
26
- onAuthenticated: (activeOrgId: string, activeStoryId: string) => any;
27
- onAuthenticationFailure: (e: Error) => any;
28
- showRequestAccess?: boolean;
29
- login: (id: IIdentity) => any;
30
- clearCachedAuth: () => any;
31
- }
32
-
33
- export interface IAppWrapperState {
34
- blockRender: boolean;
35
- restrictAccess: boolean;
14
+ setAccessData(getAccessData): void;
15
+ onAuthenticated: (token: string, activeOrgId: string, activeStoryId: string) => any;
16
+ onStoryChange(storyId: string): any;
17
+ onOrganizationChange(orgId: string, storyId: string): any;
18
+ storyId?: string;
19
+ CrMLink?: string;
20
+ hideStoryPicker?: boolean;
21
+ hideDocs?: boolean;
22
+ hideOrgPicker?: boolean;
36
23
  }
37
24
 
38
- class AppWrapper extends React.Component<IAppWrapperProps, IAppWrapperState> {
39
- private static readonly RESTRICTED_REQUEST: JSX.Element = (
40
- <NoAccess
41
- key='restriction-msg'
42
- type='request'
43
- />
44
- );
45
-
46
- private static readonly RESTRICTED_BLOCK: JSX.Element = (
47
- <NoAccess
48
- key='restriction-msg'
49
- type='restrict'
50
- />
51
- );
52
-
53
- constructor(p: IAppWrapperProps) {
54
- super(p);
55
-
56
- this.state = {
57
- blockRender: true,
58
- restrictAccess: false
59
- };
60
- }
61
-
62
- public componentDidMount = (): void => {
63
- const { auth0ClientId, auth0Domain } = this.props;
64
-
65
- AuthService.bindToClient(auth0ClientId, auth0Domain);
66
-
67
- const validAccessLevel = validateAccessLevel(
68
- this.props.organizationId,
69
- this.props.serviceId,
70
- this.props.access
71
- );
72
-
73
- if (!this.state.restrictAccess && !validAccessLevel) {
74
- this.setState({ restrictAccess: true });
75
- }
25
+ const APP_WRAPPER_ERROR_STATES = {
26
+ UNAUTHORIZED_ORG: 'UNAUTHORIZED_ORG',
27
+ UNAUTHORIZED_APP: 'UNAUTHORIZED_APP'
28
+ };
76
29
 
77
- if (this.state.restrictAccess && validAccessLevel) {
78
- this.setState({ restrictAccess: false });
30
+ export const AppWrapper = (props: IAppWrapperProps) => {
31
+ const [blockRender, setBlockRender] = React.useState(true);
32
+ const {
33
+ children,
34
+ organizationId,
35
+ storyId,
36
+ hideStoryPicker,
37
+ hideDocs,
38
+ hideOrgPicker,
39
+ CrMLink,
40
+ baseUrl,
41
+ api,
42
+ serviceId
43
+ } = props;
44
+ const { isAuthenticated, isLoading, getAccessTokenSilently, loginWithRedirect, logout } =
45
+ useAuth0();
46
+ const [errorState, setErrorState] = React.useState(null);
47
+
48
+ React.useEffect(() => {
49
+ void doCheckSession(true);
50
+ }, [isAuthenticated, isLoading]);
51
+
52
+ const getCachedStoryAndOrgForService = (freshAccess, sId) => {
53
+ const service = freshAccess.services.find((s) => s.id === sId);
54
+ if (service) {
55
+ return {
56
+ story_id: service.story_id,
57
+ organization_id: service.organization_id
58
+ };
79
59
  }
80
-
81
- // Always check the session
82
- this.doCheckSession(true);
83
60
  };
84
61
 
85
- /*
86
- Check the auth0 session expiry
87
- */
88
- public componentDidUpdate = (prevProps): void => {
89
- const { auth } = this.props;
90
- let validAccessLevel: boolean;
91
-
92
- if (auth) {
93
- const {
94
- idTokenPayload: { exp }
95
- } = auth;
96
- const validSession: boolean = AuthService.checkExpiry(exp);
62
+ const propagateCreds = (freshAccess, token): void => {
63
+ const { storyId: initialStoryId, organizationId: initialOrganizationId } = props;
97
64
 
98
- if (!validSession) {
99
- this.props.clearCachedAuth();
100
- this.doCheckSession();
101
- }
102
- }
103
-
104
- if (
105
- this.props.organizationId !== prevProps.organizationId ||
106
- this.props.access !== prevProps.access
107
- ) {
108
- validAccessLevel = validateAccessLevel(
109
- this.props.organizationId,
110
- this.props.serviceId,
111
- this.props.access
65
+ // If an org and story ID was passed in, we're following a deeplink. Verify we have access to it, and if so, propagate those IDs and set them on the service
66
+ if (initialOrganizationId && initialStoryId) {
67
+ // Validate the user has access to the orgId and storyID passed in, if not, show the "Unauthorized" interface
68
+ const validAccessLevel = validateAccessLevel(
69
+ initialOrganizationId,
70
+ serviceId,
71
+ freshAccess
112
72
  );
113
73
 
114
- if (!this.state.restrictAccess && !validAccessLevel) {
115
- this.setState({ restrictAccess: true });
116
- }
117
-
118
- if (this.state.restrictAccess && validAccessLevel) {
119
- this.setState({ restrictAccess: false });
120
- }
121
- }
122
- };
123
-
124
- /*
125
- Emit creds to React parent
126
- */
127
- private propagateCreds = (freshAccess, freshIdentity): void => {
128
- const { storyId, organizationId, onAuthenticated } = this.props;
129
-
130
- let initialStoryId = storyId;
131
- let initialOrganizationId = organizationId;
132
-
133
- const firstOrg = freshAccess.organizations[0];
134
-
135
- const getIDsFromSession = () => {
136
- const session = SessionService.getSession();
137
- if (session && session.story_id && session.organization_id) {
138
- const org = freshAccess.organizations.find(
139
- (o: any) => o.id === session.organization_id
140
- );
141
- if (org) {
142
- const story = org.stories.find((s: any) => s.id === session.story_id);
143
- if (story) {
144
- return { orgId: org.id, storyId: story.id };
145
- }
146
- }
147
- }
148
- return null;
149
- };
150
-
151
- // If the org ID is not provided, but the storyID is provided, find the org ID if we can, if not, use the first org ID found and we'll show the story not found interface
152
- if (!initialOrganizationId && initialStoryId) {
153
- const org = freshAccess.organizations.find((o: any) =>
154
- o.stories.find((s: any) => s.id === initialStoryId)
155
- );
156
- if (org) {
157
- initialOrganizationId = org.id;
158
- } else if (firstOrg) {
159
- initialOrganizationId = firstOrg.id;
160
- }
161
- }
162
-
163
- if (!initialStoryId) {
164
- // If storyID is not provided, try to use the one from the previous session
165
- const sessionIds = getIDsFromSession();
166
- if (sessionIds) {
167
- initialOrganizationId = sessionIds.orgId;
168
- initialStoryId = sessionIds.storyId;
74
+ if (validAccessLevel) {
75
+ props.onAuthenticated(token, initialOrganizationId, initialStoryId);
76
+ setBlockRender(false);
169
77
  } else {
170
- // If that doesn't work - default to the first org & story
171
- if (firstOrg) {
172
- initialOrganizationId = firstOrg.id;
173
- const story = firstOrg.stories[0];
174
- if (story) {
175
- initialStoryId = story.id;
176
- } else {
177
- initialStoryId = null;
178
- }
179
- } else {
180
- initialOrganizationId = null;
181
- initialStoryId = null;
182
- }
78
+ setErrorState(APP_WRAPPER_ERROR_STATES.UNAUTHORIZED_APP);
183
79
  }
184
- }
185
-
186
- // If at least one org was found, propagate that
187
- if (initialOrganizationId) {
188
- SessionService.buildFreshSession(freshIdentity, initialOrganizationId, initialStoryId);
189
- onAuthenticated(initialOrganizationId, initialStoryId);
190
-
191
- if (this.state.blockRender) {
192
- this.setState({ blockRender: false });
193
- }
194
-
195
- // If not, show the no-orgs interface
196
- } else {
197
- this.setState({ restrictAccess: true, blockRender: false });
198
- }
199
- };
200
80
 
201
- /*
202
- Bust cached creds if exist, invoke auth failure handler
203
- */
204
- private handleCheckSessionFailure = (e: Error): void => {
205
- if (this.props.storyId) {
206
- SessionService.cacheStoryId(this.props.storyId);
81
+ // If no orgID or storyID was passed in from the URL use the cached orgID and story ID on the service
207
82
  } else {
208
- SessionService.clearCachedStoryId();
209
- }
210
-
211
- if (this.props.organizationId) {
212
- SessionService.cacheOrgId(this.props.organizationId);
213
- } else {
214
- SessionService.clearCachedOrgId();
83
+ const { story_id, organization_id } = getCachedStoryAndOrgForService(
84
+ freshAccess,
85
+ serviceId
86
+ );
87
+ props.onAuthenticated(token, organization_id, story_id);
88
+ setBlockRender(false);
215
89
  }
216
-
217
- this.props.clearCachedAuth();
218
- this.props.onAuthenticationFailure(e);
219
90
  };
220
91
 
221
92
  /*
222
93
  Check auth0 session, pull Imposium access creds on success and initialize app-wrapper
223
94
  */
224
- private doCheckSession = (blockRender: boolean = false): void => {
225
- const { baseUrl } = this.props;
226
-
227
- if (blockRender) {
228
- this.setState({ blockRender: true });
95
+ const doCheckSession = async (doBlockRender: boolean = false) => {
96
+ if (doBlockRender) {
97
+ setBlockRender(true);
229
98
  }
230
- AuthService.checkSession()
231
- .then((freshIdentity: IIdentity) => {
232
- const orgId = this.props.organizationId
233
- ? this.props.organizationId
234
- : SessionService.getCachedOrgId();
235
- SessionService.getAccessData(freshIdentity.accessToken, baseUrl, false, orgId)
236
- .then((freshAccess: any) => {
237
- this.props.setAccessData(freshAccess);
238
- this.props.login(freshIdentity);
239
- this.propagateCreds(freshAccess, freshIdentity);
240
- })
241
- .catch((e: Error) => {
242
- this.setState({ restrictAccess: true, blockRender: false });
243
- });
244
- })
245
- .catch((e: Error) => {
246
- this.handleCheckSessionFailure(e);
247
- });
248
- };
249
-
250
- public render = (): JSX.Element => {
251
- const { blockRender, restrictAccess } = this.state;
252
- const { children, showRequestAccess, allowUnauthenticatedRender } = this.props;
253
-
254
- let innerContent: any;
255
99
 
256
- if (!blockRender && restrictAccess) {
257
- const showNoOrgs =
258
- this.props.access &&
259
- this.props.access.organizations &&
260
- this.props.access.organizations.length === 0;
261
- const errorIndicator = showNoOrgs ? (
262
- <NoAccess
263
- email={this.props.auth.idTokenPayload.userEmail}
264
- key='restriction-msg'
265
- type='no-orgs'
266
- />
267
- ) : showRequestAccess ? (
268
- AppWrapper.RESTRICTED_REQUEST
269
- ) : (
270
- AppWrapper.RESTRICTED_BLOCK
271
- );
272
- innerContent = [
273
- typeof children[0] === 'object' && children[0].type === Header && children[0],
274
- errorIndicator
275
- ];
276
- }
100
+ // If we're authenticated, get the access token, pull the access data, and propagate back to the parent component
101
+ if (isAuthenticated) {
102
+ let token;
103
+ try {
104
+ token = await getAccessTokenSilently();
105
+ } catch (e) {
106
+ // Trigger a logout if we can't get the access token
107
+ onLogout();
108
+ }
277
109
 
278
- if ((!blockRender && !restrictAccess) || allowUnauthenticatedRender) {
279
- innerContent = children;
110
+ const orgId = organizationId ? organizationId : null;
111
+
112
+ const tempAPI = new API(baseUrl, token, orgId);
113
+ tempAPI
114
+ .getAccessData(false)
115
+ .then((freshAccess: any) => {
116
+ props.setAccessData(freshAccess);
117
+ propagateCreds(freshAccess, token);
118
+ })
119
+ .catch((e: Error) => {
120
+ setErrorState(APP_WRAPPER_ERROR_STATES.UNAUTHORIZED_ORG);
121
+ });
122
+
123
+ // If we're not loading, and we're not authenticated, call login, and cache story + org ID from URL if it's there
124
+ } else if (!isLoading && !isAuthenticated) {
125
+ void loginWithRedirect({
126
+ appState: { returnTo: window.location.href }
127
+ });
280
128
  }
129
+ };
281
130
 
282
- return (
283
- <div
284
- id='app'
285
- className='app'>
286
- {innerContent}
287
- <ConfirmModal />
288
- </div>
289
- );
131
+ const onLogout = () => {
132
+ setBlockRender(true);
133
+ void logout({ logoutParams: { returnTo: window.location.origin } });
290
134
  };
291
- }
292
135
 
293
- const mapDispatchToProps = (dispatch) => {
294
- return bindActionCreators(
295
- {
296
- login,
297
- setAccessData,
298
- clearCachedAuth
299
- },
300
- dispatch
301
- );
302
- };
136
+ let innerContent: any;
303
137
 
304
- const mapStateToProps = (state): any => {
305
- return { auth: state.auth, access: state.access };
306
- };
138
+ if (errorState) {
139
+ innerContent = errorState;
140
+ } else if (!blockRender) {
141
+ innerContent = children;
142
+ }
307
143
 
308
- export default connect(mapStateToProps, mapDispatchToProps)(AppWrapper);
144
+ return (
145
+ <div
146
+ id='app'
147
+ className='app'>
148
+ <Header
149
+ onLogout={onLogout}
150
+ activeServiceId={serviceId}
151
+ baseUrl={baseUrl}
152
+ api={api}
153
+ activeOrganization={organizationId}
154
+ activeStory={storyId}
155
+ hideStoryPicker={hideStoryPicker}
156
+ hideDocs={hideDocs}
157
+ showFTLogo={false}
158
+ hideOrgPicker={hideOrgPicker}
159
+ CrMLink={CrMLink}
160
+ onStoryChange={props.onStoryChange}
161
+ onOrganizationChange={props.onOrganizationChange}
162
+ />
163
+ {innerContent}
164
+ <ConfirmModal />
165
+ </div>
166
+ );
167
+ };
@@ -122,7 +122,6 @@ export default class TextLayer extends React.PureComponent<ITextLayerProps, ITex
122
122
  this.fontReady();
123
123
  }
124
124
  } else if (font_type === FONT_TYPES.STANDARD) {
125
- // TODO: check this?
126
125
  this.fontReady();
127
126
  }
128
127
  }