@imposium-hub/components 2.6.0-0 → 2.6.0-2

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 (149) hide show
  1. package/dist/cjs/Util.d.ts +1 -1
  2. package/dist/cjs/Util.js +33 -20
  3. package/dist/cjs/Util.js.map +1 -1
  4. package/dist/cjs/components/app-wrapper/AppWrapper.d.ts +26 -5
  5. package/dist/cjs/components/app-wrapper/AppWrapper.js +110 -22
  6. package/dist/cjs/components/app-wrapper/AppWrapper.js.map +1 -1
  7. package/dist/cjs/components/assets/StoryTableNameFilter.d.ts +9 -2
  8. package/dist/cjs/components/assets/StoryTableNameFilter.js +3 -13
  9. package/dist/cjs/components/assets/StoryTableNameFilter.js.map +1 -1
  10. package/dist/cjs/components/context-menu/AnimateComponent.d.ts +6 -6
  11. package/dist/cjs/components/context-menu/AnimateComponent.js.map +1 -1
  12. package/dist/cjs/components/context-menu/ContextMenu.d.ts +12 -27
  13. package/dist/cjs/components/context-menu/ContextMenu.js +2 -15
  14. package/dist/cjs/components/context-menu/ContextMenu.js.map +1 -1
  15. package/dist/cjs/components/context-menu/ContextMenuItem.d.ts +6 -18
  16. package/dist/cjs/components/context-menu/ContextMenuItem.js +2 -21
  17. package/dist/cjs/components/context-menu/ContextMenuItem.js.map +1 -1
  18. package/dist/cjs/components/context-menu/ContextMenuTrigger.d.ts +6 -16
  19. package/dist/cjs/components/context-menu/ContextMenuTrigger.js +2 -20
  20. package/dist/cjs/components/context-menu/ContextMenuTrigger.js.map +1 -1
  21. package/dist/cjs/components/context-menu/SubMenu.d.ts +4 -12
  22. package/dist/cjs/components/context-menu/SubMenu.js +2 -17
  23. package/dist/cjs/components/context-menu/SubMenu.js.map +1 -1
  24. package/dist/cjs/components/data-table/Paginator.d.ts +16 -1
  25. package/dist/cjs/components/data-table/Paginator.js +1 -1
  26. package/dist/cjs/components/data-table/Paginator.js.map +1 -1
  27. package/dist/cjs/components/font-picker/font-manager/constants.d.ts +4 -0
  28. package/dist/cjs/components/font-picker/font-manager/constants.js +5 -1
  29. package/dist/cjs/components/font-picker/font-manager/constants.js.map +1 -1
  30. package/dist/cjs/components/header/Header.d.ts +4 -5
  31. package/dist/cjs/components/header/Header.js +77 -128
  32. package/dist/cjs/components/header/Header.js.map +1 -1
  33. package/dist/cjs/components/header/ProjectDropdown.d.ts +13 -0
  34. package/dist/cjs/components/header/ProjectDropdown.js +128 -0
  35. package/dist/cjs/components/header/ProjectDropdown.js.map +1 -0
  36. package/dist/cjs/components/header/StoryDropdown.d.ts +6 -0
  37. package/dist/cjs/components/header/StoryDropdown.js +111 -0
  38. package/dist/cjs/components/header/StoryDropdown.js.map +1 -0
  39. package/dist/cjs/components/portal/Portal.d.ts +0 -2
  40. package/dist/cjs/components/portal/Portal.js.map +1 -1
  41. package/dist/cjs/components/publish-wizard/PublishWizard.d.ts +1 -3
  42. package/dist/cjs/components/publish-wizard/PublishWizard.js.map +1 -1
  43. package/dist/cjs/components/publish-wizard/publish/EmailWorkflow.js.map +1 -1
  44. package/dist/cjs/constants/copy.d.ts +3 -0
  45. package/dist/cjs/constants/copy.js +3 -0
  46. package/dist/cjs/constants/copy.js.map +1 -1
  47. package/dist/cjs/index.d.ts +4 -2
  48. package/dist/cjs/index.js +10 -4
  49. package/dist/cjs/index.js.map +1 -1
  50. package/dist/cjs/redux/actions/access.js +44 -37
  51. package/dist/cjs/redux/actions/access.js.map +1 -1
  52. package/dist/cjs/services/API.d.ts +9 -2
  53. package/dist/cjs/services/API.js +198 -75
  54. package/dist/cjs/services/API.js.map +1 -1
  55. package/dist/cjs/utils/modal.d.ts +2 -0
  56. package/dist/cjs/utils/modal.js +11 -0
  57. package/dist/cjs/utils/modal.js.map +1 -0
  58. package/dist/cjs/utils/pendo.d.ts +2 -0
  59. package/dist/cjs/utils/pendo.js +39 -0
  60. package/dist/cjs/utils/pendo.js.map +1 -0
  61. package/dist/cjs/utils/routing.d.ts +2 -0
  62. package/dist/cjs/utils/routing.js +10 -1
  63. package/dist/cjs/utils/routing.js.map +1 -1
  64. package/dist/esm/Util.d.ts +1 -1
  65. package/dist/esm/Util.js +10 -19
  66. package/dist/esm/Util.js.map +1 -1
  67. package/dist/esm/components/app-wrapper/AppWrapper.d.ts +26 -5
  68. package/dist/esm/components/app-wrapper/AppWrapper.js +103 -19
  69. package/dist/esm/components/app-wrapper/AppWrapper.js.map +1 -1
  70. package/dist/esm/components/assets/StoryTableNameFilter.d.ts +9 -2
  71. package/dist/esm/components/assets/StoryTableNameFilter.js +3 -13
  72. package/dist/esm/components/assets/StoryTableNameFilter.js.map +1 -1
  73. package/dist/esm/components/context-menu/AnimateComponent.d.ts +6 -6
  74. package/dist/esm/components/context-menu/AnimateComponent.js.map +1 -1
  75. package/dist/esm/components/context-menu/ContextMenu.d.ts +12 -27
  76. package/dist/esm/components/context-menu/ContextMenu.js +2 -4
  77. package/dist/esm/components/context-menu/ContextMenu.js.map +1 -1
  78. package/dist/esm/components/context-menu/ContextMenuItem.d.ts +6 -18
  79. package/dist/esm/components/context-menu/ContextMenuItem.js +2 -10
  80. package/dist/esm/components/context-menu/ContextMenuItem.js.map +1 -1
  81. package/dist/esm/components/context-menu/ContextMenuTrigger.d.ts +6 -16
  82. package/dist/esm/components/context-menu/ContextMenuTrigger.js +2 -9
  83. package/dist/esm/components/context-menu/ContextMenuTrigger.js.map +1 -1
  84. package/dist/esm/components/context-menu/SubMenu.d.ts +4 -12
  85. package/dist/esm/components/context-menu/SubMenu.js +2 -6
  86. package/dist/esm/components/context-menu/SubMenu.js.map +1 -1
  87. package/dist/esm/components/data-table/Paginator.d.ts +16 -1
  88. package/dist/esm/components/data-table/Paginator.js +1 -1
  89. package/dist/esm/components/data-table/Paginator.js.map +1 -1
  90. package/dist/esm/components/font-picker/font-manager/constants.d.ts +4 -0
  91. package/dist/esm/components/font-picker/font-manager/constants.js +4 -0
  92. package/dist/esm/components/font-picker/font-manager/constants.js.map +1 -1
  93. package/dist/esm/components/header/Header.d.ts +4 -5
  94. package/dist/esm/components/header/Header.js +75 -117
  95. package/dist/esm/components/header/Header.js.map +1 -1
  96. package/dist/esm/components/header/ProjectDropdown.d.ts +13 -0
  97. package/dist/esm/components/header/ProjectDropdown.js +101 -0
  98. package/dist/esm/components/header/ProjectDropdown.js.map +1 -0
  99. package/dist/esm/components/header/StoryDropdown.d.ts +6 -0
  100. package/dist/esm/components/header/StoryDropdown.js +82 -0
  101. package/dist/esm/components/header/StoryDropdown.js.map +1 -0
  102. package/dist/esm/components/portal/Portal.d.ts +0 -2
  103. package/dist/esm/components/portal/Portal.js.map +1 -1
  104. package/dist/esm/components/publish-wizard/PublishWizard.d.ts +1 -3
  105. package/dist/esm/components/publish-wizard/PublishWizard.js.map +1 -1
  106. package/dist/esm/components/publish-wizard/publish/EmailWorkflow.js.map +1 -1
  107. package/dist/esm/constants/copy.d.ts +3 -0
  108. package/dist/esm/constants/copy.js +3 -0
  109. package/dist/esm/constants/copy.js.map +1 -1
  110. package/dist/esm/index.d.ts +4 -2
  111. package/dist/esm/index.js +4 -2
  112. package/dist/esm/index.js.map +1 -1
  113. package/dist/esm/redux/actions/access.js +63 -56
  114. package/dist/esm/redux/actions/access.js.map +1 -1
  115. package/dist/esm/services/API.d.ts +9 -2
  116. package/dist/esm/services/API.js +43 -18
  117. package/dist/esm/services/API.js.map +1 -1
  118. package/dist/esm/utils/modal.d.ts +2 -0
  119. package/dist/esm/utils/modal.js +7 -0
  120. package/dist/esm/utils/modal.js.map +1 -0
  121. package/dist/esm/utils/pendo.d.ts +2 -0
  122. package/dist/esm/utils/pendo.js +29 -0
  123. package/dist/esm/utils/pendo.js.map +1 -0
  124. package/dist/esm/utils/routing.d.ts +2 -0
  125. package/dist/esm/utils/routing.js +7 -0
  126. package/dist/esm/utils/routing.js.map +1 -1
  127. package/package.json +10 -7
  128. package/src/Util.ts +10 -16
  129. package/src/components/app-wrapper/AppWrapper.tsx +167 -26
  130. package/src/components/assets/StoryTableNameFilter.tsx +6 -22
  131. package/src/components/context-menu/AnimateComponent.tsx +12 -1
  132. package/src/components/context-menu/ContextMenu.tsx +16 -8
  133. package/src/components/context-menu/ContextMenuItem.tsx +12 -11
  134. package/src/components/context-menu/ContextMenuTrigger.tsx +12 -10
  135. package/src/components/context-menu/SubMenu.tsx +6 -8
  136. package/src/components/data-table/Paginator.tsx +19 -6
  137. package/src/components/font-picker/font-manager/constants.ts +5 -0
  138. package/src/components/header/Header.tsx +105 -192
  139. package/src/components/header/ProjectDropdown.tsx +174 -0
  140. package/src/components/portal/Portal.tsx +1 -2
  141. package/src/components/publish-wizard/PublishWizard.tsx +1 -1
  142. package/src/components/publish-wizard/publish/EmailWorkflow.tsx +7 -1
  143. package/src/constants/copy.ts +3 -0
  144. package/src/index.ts +8 -3
  145. package/src/redux/actions/access.ts +64 -72
  146. package/src/services/API.ts +55 -20
  147. package/src/utils/modal.ts +9 -0
  148. package/src/utils/pendo.ts +38 -0
  149. package/src/utils/routing.ts +10 -0
package/src/Util.ts CHANGED
@@ -51,17 +51,14 @@ export const getLastModifiedStoryInOrg = (orgId: string, access: any): string =>
51
51
  }
52
52
  };
53
53
 
54
- export const scrapeEmail = (auth: any): string => {
55
- if (auth && auth.idTokenPayload) {
56
- if (auth.idTokenPayload['https://imposium.com/email']) {
57
- return auth.idTokenPayload['https://imposium.com/email'];
58
- } else if (auth.idTokenPayload['userEmail']) {
59
- return auth.idTokenPayload['userEmail'];
60
- } else {
61
- return '';
54
+ export const getOrgIdFromStory = (storyId: string, access: any): string => {
55
+ for (const org of access.organizations) {
56
+ const stories = org.stories;
57
+ for (const story in stories) {
58
+ if (stories[story].id === storyId) {
59
+ return org.id;
60
+ }
62
61
  }
63
- } else {
64
- return '';
65
62
  }
66
63
  };
67
64
 
@@ -75,19 +72,16 @@ export const parameterizeServiceUrl = (
75
72
  switch (id) {
76
73
  case 1:
77
74
  case 2:
78
- return `${url}/${activeStory}?organization_id=${activeOrg}`;
79
- case 3:
80
- return `${url}/dashboard/live/${activeStory}?organization_id=${activeOrg}`;
81
75
  case 4:
82
76
  case 5:
83
77
  case 6:
84
78
  case 8:
85
- return `${url}/${activeStory}?organization_id=${activeOrg}`;
79
+ return `${url}/${activeOrg}/${activeStory}`;
86
80
  default:
87
- return `${url}?organization_id=${activeOrg}`;
81
+ return `${url}/${activeOrg}`;
88
82
  }
89
83
  } else if (activeOrg && !activeStory) {
90
- return `${url}?organization_id=${activeOrg}`;
84
+ return `${url}/${activeOrg}`;
91
85
  } else {
92
86
  return url;
93
87
  }
@@ -2,19 +2,25 @@ import * as React from 'react';
2
2
  import Header from '../header/Header';
3
3
  import { validateAccessLevel } from '../../Util';
4
4
  import { ConfirmModal } from '../confirm-modal/ConfirmModal';
5
- import API, { IImposiumAPI } from '../../services/API';
5
+ import { IImposiumAPI } from '../../services/API';
6
6
  import { useAuth0 } from '@auth0/auth0-react';
7
+ import { replaceRoute } from '../../utils/routing';
8
+ import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
9
+ import { faExclamationTriangle } from '@fortawesome/pro-light-svg-icons';
10
+ import { initPendo } from '../../utils/pendo';
7
11
 
8
12
  export interface IAppWrapperProps {
13
+ appLabel: string;
14
+ environment: string;
9
15
  baseUrl: string;
10
16
  api: IImposiumAPI;
11
- children?: any;
12
17
  organizationId: string;
13
18
  serviceId: number;
19
+ unsavedChanges?: boolean;
14
20
  setAccessData(getAccessData): void;
15
- onAuthenticated: (token: string, activeOrgId: string, activeStoryId: string) => any;
16
- onStoryChange(storyId: string): any;
17
- onOrganizationChange(orgId: string, storyId: string): any;
21
+ onAuthenticated: (orgId: string, storyId?: string) => any;
22
+ allowNoStories?: boolean;
23
+ saveStory?(): void;
18
24
  storyId?: string;
19
25
  CrMLink?: string;
20
26
  hideStoryPicker?: boolean;
@@ -22,12 +28,15 @@ export interface IAppWrapperProps {
22
28
  hideOrgPicker?: boolean;
23
29
  }
24
30
 
25
- const APP_WRAPPER_ERROR_STATES = {
31
+ export const APP_WRAPPER_ERROR_STATES = {
26
32
  UNAUTHORIZED_ORG: 'UNAUTHORIZED_ORG',
27
- UNAUTHORIZED_APP: 'UNAUTHORIZED_APP'
33
+ NO_ORGS_FOUND: 'NO_ORGS_FOUND',
34
+ NO_STORIES: 'NO_STORIES',
35
+ UNAUTHORIZED_APP: 'UNAUTHORIZED_APP',
36
+ STORY_NOT_FOUND: 'STORY_NOT_FOUND'
28
37
  };
29
38
 
30
- export const AppWrapper = (props: IAppWrapperProps) => {
39
+ export const AppWrapper: React.FC<IAppWrapperProps> = (props) => {
31
40
  const [blockRender, setBlockRender] = React.useState(true);
32
41
  const {
33
42
  children,
@@ -39,16 +48,31 @@ export const AppWrapper = (props: IAppWrapperProps) => {
39
48
  CrMLink,
40
49
  baseUrl,
41
50
  api,
42
- serviceId
51
+ serviceId,
52
+ unsavedChanges,
53
+ saveStory,
54
+ environment,
55
+ appLabel,
56
+ allowNoStories
43
57
  } = props;
44
- const { isAuthenticated, isLoading, getAccessTokenSilently, loginWithRedirect, logout } =
58
+ const { isAuthenticated, isLoading, getAccessTokenSilently, loginWithRedirect, logout, user } =
45
59
  useAuth0();
46
60
  const [errorState, setErrorState] = React.useState(null);
47
61
 
62
+ React.useEffect(() => {
63
+ if (user) {
64
+ initPendo(appLabel, environment, user);
65
+ }
66
+ }, [user]);
67
+
48
68
  React.useEffect(() => {
49
69
  void doCheckSession(true);
50
70
  }, [isAuthenticated, isLoading]);
51
71
 
72
+ React.useEffect(() => {
73
+ void doCheckSession(false);
74
+ }, [organizationId, storyId]);
75
+
52
76
  const getCachedStoryAndOrgForService = (freshAccess, sId) => {
53
77
  const service = freshAccess.services.find((s) => s.id === sId);
54
78
  if (service) {
@@ -59,8 +83,27 @@ export const AppWrapper = (props: IAppWrapperProps) => {
59
83
  }
60
84
  };
61
85
 
62
- const propagateCreds = (freshAccess, token): void => {
63
- const { storyId: initialStoryId, organizationId: initialOrganizationId } = props;
86
+ const validateStoryExists = (freshAccess, oId, sId) => {
87
+ const org = freshAccess.organizations.find((o) => o.id === oId);
88
+ if (!org) {
89
+ return false;
90
+ }
91
+
92
+ const story = org.stories.find((s) => s.id === sId);
93
+
94
+ if (!story) {
95
+ return false;
96
+ }
97
+
98
+ return true;
99
+ };
100
+
101
+ const propagateCreds = (freshAccess): void => {
102
+ const {
103
+ storyId: initialStoryId,
104
+ organizationId: initialOrganizationId,
105
+ onAuthenticated
106
+ } = props;
64
107
 
65
108
  // 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
109
  if (initialOrganizationId && initialStoryId) {
@@ -72,20 +115,68 @@ export const AppWrapper = (props: IAppWrapperProps) => {
72
115
  );
73
116
 
74
117
  if (validAccessLevel) {
75
- props.onAuthenticated(token, initialOrganizationId, initialStoryId);
118
+ // Check to see if the story exists, if not, show the error state
119
+ const storyExists = validateStoryExists(
120
+ freshAccess,
121
+ initialOrganizationId,
122
+ initialStoryId
123
+ );
124
+ if (!storyExists) {
125
+ setErrorState(APP_WRAPPER_ERROR_STATES.STORY_NOT_FOUND);
126
+ return;
127
+ }
128
+
129
+ api.init(baseUrl, getAccessTokenSilently, initialOrganizationId);
130
+ onAuthenticated(initialOrganizationId, initialStoryId);
76
131
  setBlockRender(false);
132
+ setErrorState(null);
77
133
  } else {
78
134
  setErrorState(APP_WRAPPER_ERROR_STATES.UNAUTHORIZED_APP);
135
+ return;
79
136
  }
80
137
 
81
138
  // If no orgID or storyID was passed in from the URL use the cached orgID and story ID on the service
82
- } else {
139
+ } else if (!initialOrganizationId && !initialStoryId) {
83
140
  const { story_id, organization_id } = getCachedStoryAndOrgForService(
84
141
  freshAccess,
85
142
  serviceId
86
143
  );
87
- props.onAuthenticated(token, organization_id, story_id);
88
- setBlockRender(false);
144
+
145
+ // No org was found to show the user
146
+ if (!organization_id) {
147
+ setErrorState(APP_WRAPPER_ERROR_STATES.NO_ORGS_FOUND);
148
+ return;
149
+ }
150
+
151
+ const validAccessLevel = validateAccessLevel(organization_id, serviceId, freshAccess);
152
+
153
+ if (validAccessLevel) {
154
+ api.init(baseUrl, getAccessTokenSilently, organization_id);
155
+ onAuthenticated(organization_id, story_id);
156
+ replaceRoute(`/${organization_id}/${story_id}`);
157
+ setBlockRender(false);
158
+ setErrorState(null);
159
+ } else {
160
+ setErrorState(APP_WRAPPER_ERROR_STATES.UNAUTHORIZED_APP);
161
+ }
162
+ } else if (initialOrganizationId) {
163
+ if (allowNoStories) {
164
+ const validAccessLevel = validateAccessLevel(
165
+ initialOrganizationId,
166
+ serviceId,
167
+ freshAccess
168
+ );
169
+ if (validAccessLevel) {
170
+ api.init(baseUrl, getAccessTokenSilently, initialOrganizationId);
171
+ onAuthenticated(initialOrganizationId, null);
172
+ setBlockRender(false);
173
+ setErrorState(null);
174
+ } else {
175
+ setErrorState(APP_WRAPPER_ERROR_STATES.UNAUTHORIZED_APP);
176
+ }
177
+ } else {
178
+ setErrorState(APP_WRAPPER_ERROR_STATES.NO_STORIES);
179
+ }
89
180
  }
90
181
  };
91
182
 
@@ -99,22 +190,19 @@ export const AppWrapper = (props: IAppWrapperProps) => {
99
190
 
100
191
  // If we're authenticated, get the access token, pull the access data, and propagate back to the parent component
101
192
  if (isAuthenticated) {
102
- let token;
103
193
  try {
104
- token = await getAccessTokenSilently();
194
+ await getAccessTokenSilently();
105
195
  } catch (e) {
106
196
  // Trigger a logout if we can't get the access token
107
197
  onLogout();
108
198
  }
109
199
 
110
200
  const orgId = organizationId ? organizationId : null;
111
-
112
- const tempAPI = new API(baseUrl, token, orgId);
113
- tempAPI
114
- .getAccessData(false)
201
+ api.init(baseUrl, getAccessTokenSilently, orgId);
202
+ api.getAccessData(false)
115
203
  .then((freshAccess: any) => {
116
204
  props.setAccessData(freshAccess);
117
- propagateCreds(freshAccess, token);
205
+ propagateCreds(freshAccess);
118
206
  })
119
207
  .catch((e: Error) => {
120
208
  setErrorState(APP_WRAPPER_ERROR_STATES.UNAUTHORIZED_ORG);
@@ -136,7 +224,12 @@ export const AppWrapper = (props: IAppWrapperProps) => {
136
224
  let innerContent: any;
137
225
 
138
226
  if (errorState) {
139
- innerContent = errorState;
227
+ innerContent = (
228
+ <AppWrapperErrors
229
+ error={errorState}
230
+ email={user.userEmail}
231
+ />
232
+ );
140
233
  } else if (!blockRender) {
141
234
  innerContent = children;
142
235
  }
@@ -146,10 +239,14 @@ export const AppWrapper = (props: IAppWrapperProps) => {
146
239
  id='app'
147
240
  className='app'>
148
241
  <Header
242
+ email={user?.userEmail}
243
+ errorState={errorState}
244
+ saveStory={saveStory}
149
245
  onLogout={onLogout}
150
246
  activeServiceId={serviceId}
151
247
  baseUrl={baseUrl}
152
248
  api={api}
249
+ unsavedChanges={unsavedChanges}
153
250
  activeOrganization={organizationId}
154
251
  activeStory={storyId}
155
252
  hideStoryPicker={hideStoryPicker}
@@ -157,11 +254,55 @@ export const AppWrapper = (props: IAppWrapperProps) => {
157
254
  showFTLogo={false}
158
255
  hideOrgPicker={hideOrgPicker}
159
256
  CrMLink={CrMLink}
160
- onStoryChange={props.onStoryChange}
161
- onOrganizationChange={props.onOrganizationChange}
162
257
  />
163
258
  {innerContent}
164
259
  <ConfirmModal />
165
260
  </div>
166
261
  );
167
262
  };
263
+
264
+ export const ERROR_HEADINGS = {
265
+ [APP_WRAPPER_ERROR_STATES.UNAUTHORIZED_ORG]: 'Organization Not Found',
266
+ [APP_WRAPPER_ERROR_STATES.NO_ORGS_FOUND]: 'No Organizations Found',
267
+ [APP_WRAPPER_ERROR_STATES.UNAUTHORIZED_APP]: 'Service Not Found',
268
+ [APP_WRAPPER_ERROR_STATES.NO_STORIES]: 'No Projects Found',
269
+ [APP_WRAPPER_ERROR_STATES.STORY_NOT_FOUND]: 'Project Not Found'
270
+ };
271
+
272
+ export const ERROR_DESCRIPTIONS = {
273
+ [APP_WRAPPER_ERROR_STATES.UNAUTHORIZED_ORG]:
274
+ 'Your user "[email]" does not have access to this organization. Please request access from an admin already on the organization.',
275
+ [APP_WRAPPER_ERROR_STATES.NO_ORGS_FOUND]:
276
+ 'Your user "[email]" has not been added to any organizations. Please request access from an admin.',
277
+ [APP_WRAPPER_ERROR_STATES.UNAUTHORIZED_APP]:
278
+ 'Your user "[email]" does not have access to this serivce. Please request access from an admin.',
279
+ [APP_WRAPPER_ERROR_STATES.NO_STORIES]: 'There are no projects on this organization.',
280
+ [APP_WRAPPER_ERROR_STATES.STORY_NOT_FOUND]:
281
+ 'The Project cound not be found. Please check the URL and try again.'
282
+ };
283
+
284
+ export interface AppWrappeErrorProps {
285
+ error: string;
286
+ email: string;
287
+ onCreateStory?: () => void;
288
+ }
289
+
290
+ export const AppWrapperErrors: React.FC<AppWrappeErrorProps> = ({
291
+ error,
292
+ email,
293
+ onCreateStory
294
+ }) => {
295
+ return (
296
+ <div className='no-access'>
297
+ <FontAwesomeIcon
298
+ icon={faExclamationTriangle}
299
+ size='6x'
300
+ />
301
+
302
+ <div className='no-access-copy'>
303
+ <h1 className='no-access-heading'>{ERROR_HEADINGS[error]}</h1>
304
+ <p>{ERROR_DESCRIPTIONS[error].replace('[email]', email)}</p>
305
+ </div>
306
+ </div>
307
+ );
308
+ };
@@ -1,40 +1,24 @@
1
1
  import * as React from 'react';
2
2
  import TextField from '../text-field/TextField';
3
- import { connect } from 'react-redux';
4
- import { bindActionCreators } from 'redux';
5
- import { updateStoryFilter } from '../../redux/actions/story-filter';
6
3
 
7
4
  interface IStoryTableNameFilterProps {
8
- storyFilter: any;
9
- updateStoryFilter: (filters: any) => any;
5
+ filter: any;
6
+ updateFilter: (filters: any) => any;
10
7
  }
11
8
 
12
9
  class StoryTableNameFilter extends React.PureComponent<IStoryTableNameFilterProps> {
13
10
  public render = (): JSX.Element => {
14
- const { storyFilter } = this.props;
11
+ const { filter } = this.props;
15
12
 
16
13
  return (
17
14
  <TextField
18
15
  className='story-name'
19
16
  focusOnMount
20
- value={storyFilter}
21
- onChange={(n) => this.props.updateStoryFilter({ name: n })}
17
+ value={filter}
18
+ onChange={(n) => this.props.updateFilter({ name: n })}
22
19
  />
23
20
  );
24
21
  };
25
22
  }
26
23
 
27
- const mapDispatchToProps = (dispatch): any => {
28
- return bindActionCreators({ updateStoryFilter }, dispatch);
29
- };
30
-
31
- const mapStateToProps = (state): any => {
32
- return { storyFilter: state.storyFilter.name };
33
- };
34
-
35
- const StoryTableNameFilterMemoized = connect(
36
- mapStateToProps,
37
- mapDispatchToProps
38
- )(React.memo(StoryTableNameFilter));
39
-
40
- export default StoryTableNameFilterMemoized;
24
+ export default StoryTableNameFilter;
@@ -1,7 +1,18 @@
1
1
  import React from 'react';
2
2
  import CSSTransition from 'react-transition-group/CSSTransition';
3
3
 
4
- const AnimateComponent = ({ children, isVisible, timeout, className }) => {
4
+ interface IAnimateComponentProps {
5
+ isVisible: boolean;
6
+ timeout: number;
7
+ className: string;
8
+ }
9
+
10
+ const AnimateComponent: React.FC<IAnimateComponentProps> = ({
11
+ children,
12
+ isVisible,
13
+ timeout,
14
+ className
15
+ }) => {
5
16
  const nodeRef = React.useRef(null);
6
17
 
7
18
  return (
@@ -4,9 +4,21 @@ import { registerEvent, callHideEvent } from './registerEvent';
4
4
  import AnimateComponent from './AnimateComponent';
5
5
  import { throttle } from './helper';
6
6
 
7
- const ContextMenu = ({
8
- children,
7
+ interface IContextMenuProps {
8
+ id: string;
9
+ appendTo: string;
10
+ hideOnLeave?: boolean;
11
+ onMouseLeave?: (e: any) => void;
12
+ onHide?: () => void;
13
+ onShow?: () => void;
14
+ preventHideOnScroll?: boolean;
15
+ preventHideOnResize?: boolean;
16
+ animation?: string;
17
+ }
18
+
19
+ const ContextMenu: React.FC<IContextMenuProps> = ({
9
20
  id,
21
+ children,
10
22
  appendTo,
11
23
  hideOnLeave,
12
24
  onMouseLeave,
@@ -14,7 +26,6 @@ const ContextMenu = ({
14
26
  onShow,
15
27
  preventHideOnScroll,
16
28
  preventHideOnResize,
17
- attributes,
18
29
  animation
19
30
  }) => {
20
31
  const contextMenuEl = useRef(null);
@@ -116,7 +127,7 @@ const ContextMenu = ({
116
127
  }
117
128
  }, [isVisible, clientPosition]);
118
129
 
119
- const childrenWithProps = React.Children.map(children, (child) =>
130
+ const childrenWithProps = React.Children.map(children, (child: any) =>
120
131
  React.cloneElement(child, { id })
121
132
  );
122
133
 
@@ -126,8 +137,7 @@ const ContextMenu = ({
126
137
  className={`contextmenu`}
127
138
  ref={contextMenuEl}
128
139
  style={{ top, left }}
129
- onMouseLeave={handleMouseLeave}
130
- {...attributes}>
140
+ onMouseLeave={handleMouseLeave}>
131
141
  {childrenWithProps}
132
142
  </div>
133
143
  );
@@ -168,8 +178,6 @@ ContextMenu.defaultProps = {
168
178
  hideOnLeave: false,
169
179
  preventHideOnResize: false,
170
180
  preventHideOnScroll: false,
171
- attributes: {},
172
- className: '',
173
181
  animation: 'fade',
174
182
  onMouseLeave: () => null,
175
183
  onHide: () => null,
@@ -1,7 +1,18 @@
1
1
  import React, { useCallback, useRef } from 'react';
2
2
  import { callHideEvent } from './registerEvent';
3
3
 
4
- const ContextMenuItem = ({ children, onClick, disabled, preventClose, attributes, className }) => {
4
+ interface IContextMenuItemProps {
5
+ onClick?(e: React.MouseEvent): void;
6
+ disabled?: boolean;
7
+ preventClose?: boolean;
8
+ }
9
+
10
+ const ContextMenuItem: React.FC<IContextMenuItemProps> = ({
11
+ children,
12
+ onClick,
13
+ disabled,
14
+ preventClose
15
+ }) => {
5
16
  const contextMenuItem = useRef(null);
6
17
 
7
18
  const handleClickEvent = useCallback((e) => {
@@ -15,7 +26,6 @@ const ContextMenuItem = ({ children, onClick, disabled, preventClose, attributes
15
26
  <div
16
27
  className={`${disabled ? 'contextmenu__item--disabled' : 'contextmenu__item'}`}
17
28
  onClick={handleClickEvent}
18
- {...attributes}
19
29
  ref={contextMenuItem}>
20
30
  {children}
21
31
  </div>
@@ -23,12 +33,3 @@ const ContextMenuItem = ({ children, onClick, disabled, preventClose, attributes
23
33
  };
24
34
 
25
35
  export default ContextMenuItem;
26
-
27
- ContextMenuItem.defaultProps = {
28
- disabled: false,
29
- preventClose: false,
30
- attributes: {},
31
- className: '',
32
- onClick: () => null,
33
- onItemHover: () => null
34
- };
@@ -1,7 +1,18 @@
1
1
  import React, { useRef, useCallback } from 'react';
2
2
  import { callShowEvent, callHideEvent } from './registerEvent';
3
3
 
4
- const ContextMenuTrigger = ({ children, id, disableWhileShiftPressed, attributes, disable }) => {
4
+ interface IContextMenuTriggerProps {
5
+ id: string;
6
+ disableWhileShiftPressed?: boolean;
7
+ disable?: boolean;
8
+ }
9
+
10
+ const ContextMenuTrigger: React.FC<IContextMenuTriggerProps> = ({
11
+ children,
12
+ id,
13
+ disableWhileShiftPressed,
14
+ disable
15
+ }) => {
5
16
  const menuTrigger = useRef(null);
6
17
 
7
18
  const handleContextMenu = useCallback((e) => {
@@ -29,7 +40,6 @@ const ContextMenuTrigger = ({ children, id, disableWhileShiftPressed, attributes
29
40
  <div
30
41
  className='menu-trigger'
31
42
  ref={menuTrigger}
32
- {...attributes}
33
43
  onContextMenu={(e) => handleContextMenu(e)}>
34
44
  {children}
35
45
  </div>
@@ -37,11 +47,3 @@ const ContextMenuTrigger = ({ children, id, disableWhileShiftPressed, attributes
37
47
  };
38
48
 
39
49
  export default ContextMenuTrigger;
40
-
41
- ContextMenuTrigger.defaultProps = {
42
- attributes: {},
43
- disable: false,
44
- renderTag: 'div',
45
- disableWhileShiftPressed: false,
46
- className: ''
47
- };
@@ -1,7 +1,11 @@
1
1
  import React, { useCallback, useState, useRef } from 'react';
2
2
  import ContextMenuItem from './ContextMenuItem';
3
3
 
4
- const Submenu = ({ children, title, attributes, className }) => {
4
+ interface ISubmenuProps {
5
+ title: string;
6
+ }
7
+
8
+ const Submenu: React.FC<ISubmenuProps> = ({ children, title }) => {
5
9
  const [submenuStyle, setSubmenuStyle] = useState(null);
6
10
  const submenuEl = useRef(null);
7
11
  const submenuItem = useRef(null);
@@ -49,8 +53,7 @@ const Submenu = ({ children, title, attributes, className }) => {
49
53
  onMouseOut={() => hideSubmenu()}
50
54
  onFocus={() => null}
51
55
  onBlur={() => null}
52
- ref={submenuItem}
53
- {...attributes}>
56
+ ref={submenuItem}>
54
57
  <ContextMenuItem>{title}</ContextMenuItem>
55
58
  <div
56
59
  className='submenu__item'
@@ -63,8 +66,3 @@ const Submenu = ({ children, title, attributes, className }) => {
63
66
  };
64
67
 
65
68
  export default Submenu;
66
-
67
- Submenu.defaultProps = {
68
- title: 'Sub Menu',
69
- className: ''
70
- };
@@ -11,27 +11,40 @@ import {
11
11
  import { assets as copy } from '../../constants/copy';
12
12
  let textInputTimeout: number;
13
13
 
14
- const Paginator: React.FC<any> = ({
15
- manualPagination,
14
+ interface IPaginatorProps {
15
+ pageCount: number;
16
+ pageIndex: number;
17
+ pageSize: number;
18
+ pageOptions: any;
19
+ totalItems: number;
20
+ canPreviousPage: boolean;
21
+ canNextPage: boolean;
22
+ gotoPage: (page: number, pageSize: number) => void;
23
+ previousPage: () => void;
24
+ nextPage: () => void;
25
+ setPageSize: (size: number) => void;
26
+ itemsPerPage: number;
27
+ onItemsPerPage: (size: number) => void;
28
+ }
29
+
30
+ const Paginator: React.FC<IPaginatorProps> = ({
16
31
  pageCount,
17
32
  pageIndex,
18
33
  pageSize,
19
- pageOptions,
20
34
  totalItems,
21
35
  canPreviousPage,
22
36
  canNextPage,
23
37
  gotoPage,
24
38
  previousPage,
25
39
  nextPage,
26
- setPageSize,
27
40
  itemsPerPage,
28
41
  onItemsPerPage
29
42
  }) => {
30
43
  const [getPageIndex, setPageIndex] = React.useState<number>(pageIndex);
31
44
  const [getItemsPerPage, setItemsPerPage] = React.useState<number>(itemsPerPage);
32
45
  const [getPageCount, setPageCount] = React.useState<number>(pageCount);
33
- const [inputPageIndex, setInputPageIndex] = React.useState<string>('');
34
- const [inputItemsPerPage, setInputItemsPerPage] = React.useState<string>('');
46
+ const [inputPageIndex, setInputPageIndex] = React.useState<any>('');
47
+ const [inputItemsPerPage, setInputItemsPerPage] = React.useState<any>('');
35
48
 
36
49
  React.useEffect(() => {
37
50
  if (pageCount === 0) {
@@ -5,3 +5,8 @@ export const LIST_BASE_URL = 'https://www.googleapis.com/webfonts/v1/webfonts';
5
5
  export const FONT_FACE_REGEX = /@font-face {([\s\S]*?)}/gm;
6
6
 
7
7
  export const FONT_FAMILY_DEFAULT = 'Open Sans';
8
+
9
+ export const API_AUTH_TYPES = {
10
+ TOKEN: 'TOKEN',
11
+ ACCESS_KEY: 'ACCESS_KEY'
12
+ };