@imposium-hub/components 2.2.42 → 2.2.44-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 (69) hide show
  1. package/dist/cjs/Util.js +22 -4
  2. package/dist/cjs/Util.js.map +1 -1
  3. package/dist/cjs/components/app-wrapper/AppWrapper.d.ts +1 -0
  4. package/dist/cjs/components/app-wrapper/AppWrapper.js +23 -6
  5. package/dist/cjs/components/app-wrapper/AppWrapper.js.map +1 -1
  6. package/dist/cjs/components/assets/AssetsTableDateCell.js +3 -0
  7. package/dist/cjs/components/assets/AssetsTableDateCell.js.map +1 -1
  8. package/dist/cjs/components/assets/AssetsTableDurationCell.js +9 -2
  9. package/dist/cjs/components/assets/AssetsTableDurationCell.js.map +1 -1
  10. package/dist/cjs/components/auth-gate/AuthGate.js +2 -2
  11. package/dist/cjs/components/auth-gate/AuthGate.js.map +1 -1
  12. package/dist/cjs/components/header/Header.d.ts +1 -0
  13. package/dist/cjs/components/header/Header.js +12 -3
  14. package/dist/cjs/components/header/Header.js.map +1 -1
  15. package/dist/cjs/components/no-access/NoAccess.d.ts +1 -1
  16. package/dist/cjs/components/no-access/NoAccess.js +11 -2
  17. package/dist/cjs/components/no-access/NoAccess.js.map +1 -1
  18. package/dist/cjs/components/story-previewer/StoryPreviewer.js +29 -15
  19. package/dist/cjs/components/story-previewer/StoryPreviewer.js.map +1 -1
  20. package/dist/cjs/constants/copy.d.ts +1 -0
  21. package/dist/cjs/constants/copy.js +2 -1
  22. package/dist/cjs/constants/copy.js.map +1 -1
  23. package/dist/cjs/services/Auth0.d.ts +1 -1
  24. package/dist/cjs/services/Auth0.js +2 -3
  25. package/dist/cjs/services/Auth0.js.map +1 -1
  26. package/dist/cjs/services/Session.js +3 -0
  27. package/dist/cjs/services/Session.js.map +1 -1
  28. package/dist/esm/Util.js +26 -4
  29. package/dist/esm/Util.js.map +1 -1
  30. package/dist/esm/components/app-wrapper/AppWrapper.d.ts +1 -0
  31. package/dist/esm/components/app-wrapper/AppWrapper.js +24 -7
  32. package/dist/esm/components/app-wrapper/AppWrapper.js.map +1 -1
  33. package/dist/esm/components/assets/AssetsTableDateCell.js +3 -0
  34. package/dist/esm/components/assets/AssetsTableDateCell.js.map +1 -1
  35. package/dist/esm/components/assets/AssetsTableDurationCell.js +9 -2
  36. package/dist/esm/components/assets/AssetsTableDurationCell.js.map +1 -1
  37. package/dist/esm/components/auth-gate/AuthGate.js +2 -2
  38. package/dist/esm/components/auth-gate/AuthGate.js.map +1 -1
  39. package/dist/esm/components/header/Header.d.ts +1 -0
  40. package/dist/esm/components/header/Header.js +9 -3
  41. package/dist/esm/components/header/Header.js.map +1 -1
  42. package/dist/esm/components/no-access/NoAccess.d.ts +1 -1
  43. package/dist/esm/components/no-access/NoAccess.js +11 -2
  44. package/dist/esm/components/no-access/NoAccess.js.map +1 -1
  45. package/dist/esm/components/story-previewer/StoryPreviewer.js +25 -15
  46. package/dist/esm/components/story-previewer/StoryPreviewer.js.map +1 -1
  47. package/dist/esm/constants/copy.d.ts +1 -0
  48. package/dist/esm/constants/copy.js +2 -1
  49. package/dist/esm/constants/copy.js.map +1 -1
  50. package/dist/esm/services/Auth0.d.ts +1 -1
  51. package/dist/esm/services/Auth0.js +2 -2
  52. package/dist/esm/services/Auth0.js.map +1 -1
  53. package/dist/esm/services/Session.js +3 -0
  54. package/dist/esm/services/Session.js.map +1 -1
  55. package/dist/styles.css +1 -0
  56. package/dist/styles.less +1 -0
  57. package/less/components/context-menu.less +1 -0
  58. package/package.json +4 -6
  59. package/src/Util.ts +23 -6
  60. package/src/components/app-wrapper/AppWrapper.tsx +40 -7
  61. package/src/components/assets/AssetsTableDateCell.tsx +2 -0
  62. package/src/components/assets/AssetsTableDurationCell.tsx +11 -2
  63. package/src/components/auth-gate/AuthGate.tsx +3 -2
  64. package/src/components/header/Header.tsx +14 -3
  65. package/src/components/no-access/NoAccess.tsx +14 -3
  66. package/src/components/story-previewer/StoryPreviewer.tsx +29 -32
  67. package/src/constants/copy.ts +2 -1
  68. package/src/services/Auth0.ts +2 -2
  69. package/src/services/Session.ts +3 -0
@@ -7,10 +7,11 @@ import { connect } from 'react-redux';
7
7
  import { bindActionCreators } from 'redux';
8
8
  import { login, clearCachedAuth } from '../../redux/actions/auth';
9
9
  import { cacheAccessData, clearCachedAccessList } from '../../redux/actions/access';
10
- import { checkStoryId, getLastModifiedStoryInOrg, validateAccessLevel } from '../../Util';
10
+ import { validateAccessLevel } from '../../Util';
11
11
 
12
12
  export interface IAppWrapperProps {
13
13
  children: React.ReactChildren;
14
+ auth0Domain: string;
14
15
  auth0ClientId: string;
15
16
  organizationId: string;
16
17
  baseUrl: string;
@@ -49,6 +50,13 @@ class AppWrapper extends React.Component<IAppWrapperProps, IAppWrapperState> {
49
50
  />
50
51
  );
51
52
 
53
+ private static readonly NO_ORGS: JSX.Element = (
54
+ <NoAccess
55
+ key='restriction-msg'
56
+ type='no-orgs'
57
+ />
58
+ );
59
+
52
60
  constructor(p: IAppWrapperProps) {
53
61
  super(p);
54
62
 
@@ -59,10 +67,24 @@ class AppWrapper extends React.Component<IAppWrapperProps, IAppWrapperState> {
59
67
  }
60
68
 
61
69
  public componentDidMount = (): void => {
62
- const { auth, access, auth0ClientId, isFreshUser } = this.props;
70
+ const { auth, access, auth0ClientId, auth0Domain, isFreshUser } = this.props;
63
71
  const session: IHubSession = SessionService.getSession();
64
72
 
65
- AuthService.bindToClient(auth0ClientId);
73
+ AuthService.bindToClient(auth0ClientId, auth0Domain);
74
+
75
+ const validAccessLevel = validateAccessLevel(
76
+ this.props.organizationId,
77
+ this.props.serviceId,
78
+ this.props.access
79
+ );
80
+
81
+ if (!this.state.restrictAccess && !validAccessLevel) {
82
+ this.setState({ restrictAccess: true });
83
+ }
84
+
85
+ if (this.state.restrictAccess && validAccessLevel) {
86
+ this.setState({ restrictAccess: false });
87
+ }
66
88
 
67
89
  // If cookie, auth or access data is missing / mismatched,
68
90
  // silently check auth0 session and refresh flow on success
@@ -128,9 +150,11 @@ class AppWrapper extends React.Component<IAppWrapperProps, IAppWrapperState> {
128
150
  private propagateCreds = (): void => {
129
151
  const { auth, access, storyId, onAuthenticated } = this.props;
130
152
  const activeOrgId: string = this.determineActiveOrganization(auth, access);
131
- const activeStoryId: string = checkStoryId(storyId, activeOrgId, access)
132
- ? storyId
133
- : getLastModifiedStoryInOrg(activeOrgId, access);
153
+ let activeStoryId: string = SessionService.getSession().story_id;
154
+
155
+ if (storyId) {
156
+ activeStoryId = storyId;
157
+ }
134
158
 
135
159
  onAuthenticated(activeOrgId, activeStoryId);
136
160
 
@@ -265,9 +289,18 @@ class AppWrapper extends React.Component<IAppWrapperProps, IAppWrapperState> {
265
289
  let innerContent: any;
266
290
 
267
291
  if (!blockRender && restrictAccess) {
292
+ const showNoOrgs =
293
+ this.props.access &&
294
+ this.props.access.organizations &&
295
+ this.props.access.organizations.length === 0;
296
+ const errorIndicator = showNoOrgs
297
+ ? AppWrapper.NO_ORGS
298
+ : showRequestAccess
299
+ ? AppWrapper.RESTRICTED_REQUEST
300
+ : AppWrapper.RESTRICTED_BLOCK;
268
301
  innerContent = [
269
302
  typeof children[0] === 'object' && children[0].type === Header && children[0],
270
- showRequestAccess ? AppWrapper.RESTRICTED_REQUEST : AppWrapper.RESTRICTED_BLOCK
303
+ errorIndicator
271
304
  ];
272
305
  }
273
306
 
@@ -18,6 +18,8 @@ const AssetsTableDateCell: React.FC<IAssetsTableDateCell> = (p: IAssetsTableDate
18
18
  return <div>{formatDateDefault(values.date_created)}</div>;
19
19
  } else if (values.date_modified) {
20
20
  return <div>{formatDateDefault(values.date_modified)}</div>;
21
+ } else if (values.date_updated) {
22
+ return <div>{formatDateDefault(values.date_updated)}</div>;
21
23
  } else {
22
24
  return null;
23
25
  }
@@ -1,4 +1,6 @@
1
1
  import * as React from 'react';
2
+ import { ASSET_TYPES } from '../../constants/assets';
3
+ import { getDuration } from '../../Util';
2
4
 
3
5
  interface IAssetsTableDurationCell {
4
6
  cell: any;
@@ -10,13 +12,20 @@ const AssetsTableDurationCell: React.FC<IAssetsTableDurationCell> = (
10
12
  const {
11
13
  cell: {
12
14
  row: {
13
- original: { duration }
15
+ original: { type, data, rate, frame_count }
14
16
  }
15
17
  }
16
18
  } = props;
17
19
 
20
+ let duration = rate && frame_count ? getDuration(frame_count, rate) : '';
21
+
22
+ if (type === ASSET_TYPES.VIDEO_COMPOSITION) {
23
+ const { frames, rate: frame_rate } = JSON.parse(data);
24
+ duration = getDuration(frames, frame_rate);
25
+ }
26
+
18
27
  if (duration !== null && duration !== undefined) {
19
- return <div className='asset-duration-cell'>{secondsToTime(duration)}</div>;
28
+ return <div className='asset-duration-cell'>{duration}</div>;
20
29
  } else {
21
30
  return <div className='asset-duration-cell'></div>;
22
31
  }
@@ -9,6 +9,7 @@ import { cacheAccessData } from '../../redux/actions/access';
9
9
 
10
10
  interface IAuthGateProps {
11
11
  auth0ClientId: string;
12
+ auth0Domain: string;
12
13
  auth0Hash: string;
13
14
  onAuthenticated: () => any;
14
15
  baseUrl?: string;
@@ -24,9 +25,9 @@ class AuthGate extends React.PureComponent<IAuthGateProps> {
24
25
  }
25
26
 
26
27
  public componentDidMount = (): void => {
27
- const { auth0ClientId, auth0Hash, onAuthenticated, baseUrl } = this.props;
28
+ const { auth0ClientId, auth0Hash, auth0Domain, onAuthenticated, baseUrl } = this.props;
28
29
 
29
- AuthService.bindToClient(auth0ClientId);
30
+ AuthService.bindToClient(auth0ClientId, auth0Domain);
30
31
 
31
32
  if (!auth0Hash) {
32
33
  AuthService.login();
@@ -21,6 +21,7 @@ export interface IHeaderProps {
21
21
  auth: any;
22
22
  story: any;
23
23
  baseUrl: any;
24
+ access: any;
24
25
  }
25
26
 
26
27
  export interface IHeaderState {
@@ -160,7 +161,7 @@ class ImposiumHeader extends React.PureComponent<IHeaderProps, IHeaderState> {
160
161
 
161
162
  public componentDidUpdate(prevProps: Readonly<IHeaderProps>): void {
162
163
  const { accessData } = this.state;
163
- const { activeOrganization } = this.props;
164
+ const { activeOrganization, access } = this.props;
164
165
 
165
166
  if (activeOrganization !== prevProps.activeOrganization) {
166
167
  if (accessData !== null) {
@@ -169,6 +170,12 @@ class ImposiumHeader extends React.PureComponent<IHeaderProps, IHeaderState> {
169
170
  this.getAccessDataHandler();
170
171
  }
171
172
  }
173
+
174
+ if (!_.isEqual(access, accessData)) {
175
+ this.setState({ accessData: access }, () =>
176
+ this.parseAccessData(access, activeOrganization)
177
+ );
178
+ }
172
179
  }
173
180
 
174
181
  private parseAccessData = (accessData: any, activeOrganization: string): void => {
@@ -299,7 +306,6 @@ class ImposiumHeader extends React.PureComponent<IHeaderProps, IHeaderState> {
299
306
 
300
307
  this.setState({ dataLoading: true });
301
308
 
302
- // SessionService.getAccessData(idToken, baseUrl, true, activeOrganization)
303
309
  SessionService.getAccessData(idToken, baseUrl)
304
310
  .then((res) => {
305
311
  this.setState({ dataLoading: false, accessData: res }, () =>
@@ -457,6 +463,10 @@ class ImposiumHeader extends React.PureComponent<IHeaderProps, IHeaderState> {
457
463
  );
458
464
  }
459
465
 
466
+ if (accessData && accessData.organizations && accessData.organizations.length === 0) {
467
+ storyToggle = null;
468
+ }
469
+
460
470
  if (accessData && activeOrganizationBlob && !hideStoryPicker) {
461
471
  currentStory = activeOrganizationBlob.stories.find((s: any) => s.id === activeStory);
462
472
  storyToggle = (
@@ -596,7 +606,8 @@ class ImposiumHeader extends React.PureComponent<IHeaderProps, IHeaderState> {
596
606
  const mapStateToProps = (state): any => {
597
607
  return {
598
608
  auth: state.auth,
599
- story: state.story
609
+ story: state.story,
610
+ access: state.access
600
611
  };
601
612
  };
602
613
 
@@ -4,20 +4,22 @@ import { faUserLock } from '@fortawesome/free-solid-svg-icons/faUserLock';
4
4
  import { faExclamationTriangle } from '@fortawesome/free-solid-svg-icons/faExclamationTriangle';
5
5
 
6
6
  interface INoAccessProps {
7
- type: 'request' | 'restrict';
7
+ type: 'request' | 'restrict' | 'no-orgs';
8
8
  }
9
9
 
10
10
  const MAIL_TO: string = 'mailto:info@imposium.com?subject=My access to Imposium is restricted';
11
11
  const REQUEST_ACCESS_TITLE: string = "You don't have access to Imposium yet";
12
12
  const REQUEST_HREF_COPY: string = 'Request Access';
13
13
  const RESTRICTED_ACCESS_TITLE: string = 'Service not found';
14
+ const NO_ORGS_TITLE = 'No organizations found';
14
15
 
15
16
  const NoAccess: React.FC<INoAccessProps> = (p: INoAccessProps) => {
16
17
  if (!p.type) {
17
- throw new Error('NoAccess requires a type of either: request or restrict');
18
+ throw new Error('NoAccess requires a type of either: request or restrict or no-orgs');
18
19
  }
19
20
 
20
21
  const isRequest: boolean = p.type === 'request';
22
+ const isNoOrgs: boolean = p.type === 'no-orgs';
21
23
 
22
24
  return (
23
25
  <div className='no-access'>
@@ -35,8 +37,17 @@ const NoAccess: React.FC<INoAccessProps> = (p: INoAccessProps) => {
35
37
 
36
38
  <div className='no-access-copy'>
37
39
  <h1 className='no-access-heading'>
38
- {isRequest ? REQUEST_ACCESS_TITLE : RESTRICTED_ACCESS_TITLE}
40
+ {isRequest
41
+ ? REQUEST_ACCESS_TITLE
42
+ : isNoOrgs
43
+ ? NO_ORGS_TITLE
44
+ : RESTRICTED_ACCESS_TITLE}
39
45
  </h1>
46
+ <p>
47
+ {isNoOrgs
48
+ ? 'Please request access from an admin already on the organization'
49
+ : null}
50
+ </p>
40
51
  {isRequest && <a href={MAIL_TO}>{REQUEST_HREF_COPY}</a>}
41
52
  </div>
42
53
  </div>
@@ -57,6 +57,7 @@ interface IStoryPreviewerState {
57
57
  isTimeOut: boolean;
58
58
  error: boolean;
59
59
  jobLogLoading: boolean;
60
+ errorMsg: string;
60
61
  }
61
62
 
62
63
  class StoryPreviewer extends React.PureComponent<IStoryPreviewerProps, IStoryPreviewerState> {
@@ -86,7 +87,8 @@ class StoryPreviewer extends React.PureComponent<IStoryPreviewerProps, IStoryPre
86
87
  isTimeOut: false,
87
88
  compositionOverride: null,
88
89
  error: false,
89
- jobLogLoading: false
90
+ jobLogLoading: false,
91
+ errorMsg: ''
90
92
  };
91
93
 
92
94
  this.timer = new Timer({
@@ -191,7 +193,8 @@ class StoryPreviewer extends React.PureComponent<IStoryPreviewerProps, IStoryPre
191
193
  public componentDidUpdate(prevProps, prevState) {
192
194
  if (!prevProps.editor?.autoRender && this.props.editor?.autoRender) {
193
195
  this.props.updateEditorConfig({ autoRender: false });
194
- this.createExperience();
196
+ this.evtHandlers.gotExperience = null;
197
+ this.props.api.cancelExperiencePolling().then(() => this.createExperience());
195
198
  }
196
199
 
197
200
  if (
@@ -225,7 +228,7 @@ class StoryPreviewer extends React.PureComponent<IStoryPreviewerProps, IStoryPre
225
228
  const { experienceId } = this.state;
226
229
 
227
230
  api.cancelExperiencePolling().then(() => {
228
- onError(copy.runExpError.replace('[expId]', experienceId));
231
+ onError(copy.runExpIdError.replace('[expId]', experienceId));
229
232
 
230
233
  this.resetState(
231
234
  true,
@@ -507,8 +510,8 @@ class StoryPreviewer extends React.PureComponent<IStoryPreviewerProps, IStoryPre
507
510
  () => {
508
511
  onError(
509
512
  copy.runExpError.replace(
510
- '[expId]',
511
- experienceId
513
+ '[error]',
514
+ e.error
512
515
  )
513
516
  );
514
517
 
@@ -516,7 +519,8 @@ class StoryPreviewer extends React.PureComponent<IStoryPreviewerProps, IStoryPre
516
519
  true,
517
520
  () => {
518
521
  this.setState({
519
- isTimeOut: true
522
+ isTimeOut: true,
523
+ errorMsg: e.error
520
524
  });
521
525
  },
522
526
  experienceId
@@ -525,7 +529,7 @@ class StoryPreviewer extends React.PureComponent<IStoryPreviewerProps, IStoryPre
525
529
  );
526
530
  } else {
527
531
  onError(
528
- copy.runExpError.replace(
532
+ copy.runExpIdError.replace(
529
533
  '[expId]',
530
534
  experienceId
531
535
  )
@@ -569,10 +573,10 @@ class StoryPreviewer extends React.PureComponent<IStoryPreviewerProps, IStoryPre
569
573
  this.resetState();
570
574
  if (onError) {
571
575
  if (e.error) {
572
- onError(e.error);
576
+ onError(copy.runExpError.replace('[error]', e.error));
573
577
  } else {
574
578
  onError(
575
- copy.runExpError.replace('[expId]', experienceId)
579
+ copy.runExpIdError.replace('[expId]', experienceId)
576
580
  );
577
581
  }
578
582
  }
@@ -585,16 +589,10 @@ class StoryPreviewer extends React.PureComponent<IStoryPreviewerProps, IStoryPre
585
589
  }
586
590
 
587
591
  private createExperience() {
588
- const {
589
- storyId,
590
- onNotification,
591
- onError,
592
- api,
593
- onExperienceCreated,
594
- useWorkingCopy,
595
- editor: { fastRender }
596
- } = this.props;
592
+ const { storyId, onNotification, onError, api, onExperienceCreated, useWorkingCopy } =
593
+ this.props;
597
594
 
595
+ const fastRender = this.props.editor?.fastRender || false;
598
596
  const compId = this.getCompId();
599
597
 
600
598
  this.resetState(false, () => {
@@ -658,13 +656,12 @@ class StoryPreviewer extends React.PureComponent<IStoryPreviewerProps, IStoryPre
658
656
  }
659
657
 
660
658
  private renderViewerContent() {
661
- const { rendering, experience, timeElapsed, activeOutput, isTimeOut } = this.state;
659
+ const { rendering, experience, timeElapsed, activeOutput, isTimeOut, errorMsg } =
660
+ this.state;
662
661
 
663
- const {
664
- api,
665
- onError,
666
- editor: { playbackRate }
667
- } = this.props;
662
+ const { api, onError } = this.props;
663
+
664
+ const playbackRate = this.props.editor?.playbackRate || 1;
668
665
 
669
666
  if (rendering) {
670
667
  return (
@@ -684,6 +681,8 @@ class StoryPreviewer extends React.PureComponent<IStoryPreviewerProps, IStoryPre
684
681
  <p>
685
682
  {copy.time}&nbsp;{formattedTime(timeElapsed)}
686
683
  </p>
684
+ <br />
685
+ <p>{`${copy.runExpError.replace('[error]', errorMsg)}`}</p>
687
686
  </div>
688
687
  );
689
688
  } else if (experience && activeOutput) {
@@ -840,23 +839,21 @@ class StoryPreviewer extends React.PureComponent<IStoryPreviewerProps, IStoryPre
840
839
  }
841
840
 
842
841
  private changePlaybackRate() {
843
- const {
844
- editor: { playbackRate }
845
- } = this.props;
842
+ const playbackRate = this.props.editor?.playbackRate || 1;
846
843
  let newRate = playbackRate + 0.5;
847
844
 
848
845
  if (newRate > this.maxPlaybackRate) {
849
846
  newRate = 1;
850
847
  }
851
848
 
852
- this.props.updateEditorConfig({ playbackRate: newRate });
849
+ if (this.props.updateEditorConfig) {
850
+ this.props.updateEditorConfig({ playbackRate: newRate });
851
+ }
853
852
  }
854
853
 
855
854
  public render() {
856
- const {
857
- allowCompOverride,
858
- editor: { playbackRate }
859
- } = this.props;
855
+ const { allowCompOverride } = this.props;
856
+ const playbackRate = this.props.editor?.playbackRate || 1;
860
857
  const { rendering, experience, activeOutput, experienceId, error } = this.state;
861
858
  const { storyId } = this.props;
862
859
  const renderCopy = experience ? copy.btnReRender : copy.btnRender;
@@ -58,7 +58,8 @@ export const previewer = {
58
58
  time: 'Time Elapsed:',
59
59
  expRunning: 'Rendering Experience',
60
60
  runExpStart: 'Creating Experience',
61
- runExpError: 'Error running experience - ID: [expId]',
61
+ runExpIdError: 'Error running experience - ID: [expId]',
62
+ runExpError: 'Error running experience: [error]',
62
63
  triggerExpError: 'Error triggering experience - ID: [expId]',
63
64
  expId: 'Running Experience - ID: [expId]',
64
65
  createExpError: 'Error creating experience',
@@ -11,7 +11,6 @@ export interface IIdentity {
11
11
 
12
12
  export default class AuthService {
13
13
  private static readonly IMPOSIUM_APP_DEFAULTS: any = {
14
- domain: 'imposium.auth0.com',
15
14
  scope: 'openid',
16
15
  responseType: 'token id_token',
17
16
  redirectUri: `${window.location.origin}/auth`
@@ -23,9 +22,10 @@ export default class AuthService {
23
22
  /*
24
23
  Initialize the auth0 web client with client ID for a given app-wrapper
25
24
  */
26
- public static bindToClient = (clientID: string): void => {
25
+ public static bindToClient = (clientID: string, domain: string): void => {
27
26
  AuthService.auth0Client = new auth0.WebAuth({
28
27
  clientID,
28
+ domain,
29
29
  ...AuthService.IMPOSIUM_APP_DEFAULTS
30
30
  });
31
31
  };
@@ -98,6 +98,7 @@ export default class SessionService {
98
98
  if (
99
99
  cachedStoryId &&
100
100
  organizationId &&
101
+ activeOrg.stories &&
101
102
  activeOrg.stories.find((s: any) => s.id === cachedStoryId)
102
103
  ) {
103
104
  activeStoryId = cachedStoryId;
@@ -116,6 +117,8 @@ export default class SessionService {
116
117
  // Same for story id if the cache was missing / belonging to a different org
117
118
  if (
118
119
  !activeStoryId &&
120
+ organizations &&
121
+ organizations[0] &&
119
122
  organizations[0].stories.length > 0 &&
120
123
  typeof organizations[0].stories[0] === 'object' &&
121
124
  organizations[0].stories[0].hasOwnProperty('id')