@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.
- package/dist/cjs/Util.d.ts +1 -1
- package/dist/cjs/Util.js +33 -20
- package/dist/cjs/Util.js.map +1 -1
- package/dist/cjs/components/app-wrapper/AppWrapper.d.ts +26 -5
- package/dist/cjs/components/app-wrapper/AppWrapper.js +110 -22
- package/dist/cjs/components/app-wrapper/AppWrapper.js.map +1 -1
- package/dist/cjs/components/assets/StoryTableNameFilter.d.ts +9 -2
- package/dist/cjs/components/assets/StoryTableNameFilter.js +3 -13
- package/dist/cjs/components/assets/StoryTableNameFilter.js.map +1 -1
- package/dist/cjs/components/context-menu/AnimateComponent.d.ts +6 -6
- package/dist/cjs/components/context-menu/AnimateComponent.js.map +1 -1
- package/dist/cjs/components/context-menu/ContextMenu.d.ts +12 -27
- package/dist/cjs/components/context-menu/ContextMenu.js +2 -15
- package/dist/cjs/components/context-menu/ContextMenu.js.map +1 -1
- package/dist/cjs/components/context-menu/ContextMenuItem.d.ts +6 -18
- package/dist/cjs/components/context-menu/ContextMenuItem.js +2 -21
- package/dist/cjs/components/context-menu/ContextMenuItem.js.map +1 -1
- package/dist/cjs/components/context-menu/ContextMenuTrigger.d.ts +6 -16
- package/dist/cjs/components/context-menu/ContextMenuTrigger.js +2 -20
- package/dist/cjs/components/context-menu/ContextMenuTrigger.js.map +1 -1
- package/dist/cjs/components/context-menu/SubMenu.d.ts +4 -12
- package/dist/cjs/components/context-menu/SubMenu.js +2 -17
- package/dist/cjs/components/context-menu/SubMenu.js.map +1 -1
- package/dist/cjs/components/data-table/Paginator.d.ts +16 -1
- package/dist/cjs/components/data-table/Paginator.js +1 -1
- package/dist/cjs/components/data-table/Paginator.js.map +1 -1
- package/dist/cjs/components/font-picker/font-manager/constants.d.ts +4 -0
- package/dist/cjs/components/font-picker/font-manager/constants.js +5 -1
- package/dist/cjs/components/font-picker/font-manager/constants.js.map +1 -1
- package/dist/cjs/components/header/Header.d.ts +4 -5
- package/dist/cjs/components/header/Header.js +77 -128
- package/dist/cjs/components/header/Header.js.map +1 -1
- package/dist/cjs/components/header/ProjectDropdown.d.ts +13 -0
- package/dist/cjs/components/header/ProjectDropdown.js +128 -0
- package/dist/cjs/components/header/ProjectDropdown.js.map +1 -0
- package/dist/cjs/components/header/StoryDropdown.d.ts +6 -0
- package/dist/cjs/components/header/StoryDropdown.js +111 -0
- package/dist/cjs/components/header/StoryDropdown.js.map +1 -0
- package/dist/cjs/components/portal/Portal.d.ts +0 -2
- package/dist/cjs/components/portal/Portal.js.map +1 -1
- package/dist/cjs/components/publish-wizard/PublishWizard.d.ts +1 -3
- package/dist/cjs/components/publish-wizard/PublishWizard.js.map +1 -1
- package/dist/cjs/components/publish-wizard/publish/EmailWorkflow.js.map +1 -1
- package/dist/cjs/constants/copy.d.ts +3 -0
- package/dist/cjs/constants/copy.js +3 -0
- package/dist/cjs/constants/copy.js.map +1 -1
- package/dist/cjs/index.d.ts +4 -2
- package/dist/cjs/index.js +10 -4
- package/dist/cjs/index.js.map +1 -1
- package/dist/cjs/redux/actions/access.js +44 -37
- package/dist/cjs/redux/actions/access.js.map +1 -1
- package/dist/cjs/services/API.d.ts +9 -2
- package/dist/cjs/services/API.js +198 -75
- package/dist/cjs/services/API.js.map +1 -1
- package/dist/cjs/utils/modal.d.ts +2 -0
- package/dist/cjs/utils/modal.js +11 -0
- package/dist/cjs/utils/modal.js.map +1 -0
- package/dist/cjs/utils/pendo.d.ts +2 -0
- package/dist/cjs/utils/pendo.js +39 -0
- package/dist/cjs/utils/pendo.js.map +1 -0
- package/dist/cjs/utils/routing.d.ts +2 -0
- package/dist/cjs/utils/routing.js +10 -1
- package/dist/cjs/utils/routing.js.map +1 -1
- package/dist/esm/Util.d.ts +1 -1
- package/dist/esm/Util.js +10 -19
- package/dist/esm/Util.js.map +1 -1
- package/dist/esm/components/app-wrapper/AppWrapper.d.ts +26 -5
- package/dist/esm/components/app-wrapper/AppWrapper.js +103 -19
- package/dist/esm/components/app-wrapper/AppWrapper.js.map +1 -1
- package/dist/esm/components/assets/StoryTableNameFilter.d.ts +9 -2
- package/dist/esm/components/assets/StoryTableNameFilter.js +3 -13
- package/dist/esm/components/assets/StoryTableNameFilter.js.map +1 -1
- package/dist/esm/components/context-menu/AnimateComponent.d.ts +6 -6
- package/dist/esm/components/context-menu/AnimateComponent.js.map +1 -1
- package/dist/esm/components/context-menu/ContextMenu.d.ts +12 -27
- package/dist/esm/components/context-menu/ContextMenu.js +2 -4
- package/dist/esm/components/context-menu/ContextMenu.js.map +1 -1
- package/dist/esm/components/context-menu/ContextMenuItem.d.ts +6 -18
- package/dist/esm/components/context-menu/ContextMenuItem.js +2 -10
- package/dist/esm/components/context-menu/ContextMenuItem.js.map +1 -1
- package/dist/esm/components/context-menu/ContextMenuTrigger.d.ts +6 -16
- package/dist/esm/components/context-menu/ContextMenuTrigger.js +2 -9
- package/dist/esm/components/context-menu/ContextMenuTrigger.js.map +1 -1
- package/dist/esm/components/context-menu/SubMenu.d.ts +4 -12
- package/dist/esm/components/context-menu/SubMenu.js +2 -6
- package/dist/esm/components/context-menu/SubMenu.js.map +1 -1
- package/dist/esm/components/data-table/Paginator.d.ts +16 -1
- package/dist/esm/components/data-table/Paginator.js +1 -1
- package/dist/esm/components/data-table/Paginator.js.map +1 -1
- package/dist/esm/components/font-picker/font-manager/constants.d.ts +4 -0
- package/dist/esm/components/font-picker/font-manager/constants.js +4 -0
- package/dist/esm/components/font-picker/font-manager/constants.js.map +1 -1
- package/dist/esm/components/header/Header.d.ts +4 -5
- package/dist/esm/components/header/Header.js +75 -117
- package/dist/esm/components/header/Header.js.map +1 -1
- package/dist/esm/components/header/ProjectDropdown.d.ts +13 -0
- package/dist/esm/components/header/ProjectDropdown.js +101 -0
- package/dist/esm/components/header/ProjectDropdown.js.map +1 -0
- package/dist/esm/components/header/StoryDropdown.d.ts +6 -0
- package/dist/esm/components/header/StoryDropdown.js +82 -0
- package/dist/esm/components/header/StoryDropdown.js.map +1 -0
- package/dist/esm/components/portal/Portal.d.ts +0 -2
- package/dist/esm/components/portal/Portal.js.map +1 -1
- package/dist/esm/components/publish-wizard/PublishWizard.d.ts +1 -3
- package/dist/esm/components/publish-wizard/PublishWizard.js.map +1 -1
- package/dist/esm/components/publish-wizard/publish/EmailWorkflow.js.map +1 -1
- package/dist/esm/constants/copy.d.ts +3 -0
- package/dist/esm/constants/copy.js +3 -0
- package/dist/esm/constants/copy.js.map +1 -1
- package/dist/esm/index.d.ts +4 -2
- package/dist/esm/index.js +4 -2
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/redux/actions/access.js +63 -56
- package/dist/esm/redux/actions/access.js.map +1 -1
- package/dist/esm/services/API.d.ts +9 -2
- package/dist/esm/services/API.js +43 -18
- package/dist/esm/services/API.js.map +1 -1
- package/dist/esm/utils/modal.d.ts +2 -0
- package/dist/esm/utils/modal.js +7 -0
- package/dist/esm/utils/modal.js.map +1 -0
- package/dist/esm/utils/pendo.d.ts +2 -0
- package/dist/esm/utils/pendo.js +29 -0
- package/dist/esm/utils/pendo.js.map +1 -0
- package/dist/esm/utils/routing.d.ts +2 -0
- package/dist/esm/utils/routing.js +7 -0
- package/dist/esm/utils/routing.js.map +1 -1
- package/package.json +10 -7
- package/src/Util.ts +10 -16
- package/src/components/app-wrapper/AppWrapper.tsx +167 -26
- package/src/components/assets/StoryTableNameFilter.tsx +6 -22
- package/src/components/context-menu/AnimateComponent.tsx +12 -1
- package/src/components/context-menu/ContextMenu.tsx +16 -8
- package/src/components/context-menu/ContextMenuItem.tsx +12 -11
- package/src/components/context-menu/ContextMenuTrigger.tsx +12 -10
- package/src/components/context-menu/SubMenu.tsx +6 -8
- package/src/components/data-table/Paginator.tsx +19 -6
- package/src/components/font-picker/font-manager/constants.ts +5 -0
- package/src/components/header/Header.tsx +105 -192
- package/src/components/header/ProjectDropdown.tsx +174 -0
- package/src/components/portal/Portal.tsx +1 -2
- package/src/components/publish-wizard/PublishWizard.tsx +1 -1
- package/src/components/publish-wizard/publish/EmailWorkflow.tsx +7 -1
- package/src/constants/copy.ts +3 -0
- package/src/index.ts +8 -3
- package/src/redux/actions/access.ts +64 -72
- package/src/services/API.ts +55 -20
- package/src/utils/modal.ts +9 -0
- package/src/utils/pendo.ts +38 -0
- 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
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
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}/${
|
|
79
|
+
return `${url}/${activeOrg}/${activeStory}`;
|
|
86
80
|
default:
|
|
87
|
-
return `${url}
|
|
81
|
+
return `${url}/${activeOrg}`;
|
|
88
82
|
}
|
|
89
83
|
} else if (activeOrg && !activeStory) {
|
|
90
|
-
return `${url}
|
|
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
|
|
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: (
|
|
16
|
-
|
|
17
|
-
|
|
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
|
-
|
|
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
|
|
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
|
|
63
|
-
const
|
|
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
|
-
|
|
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
|
-
|
|
88
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
|
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 =
|
|
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
|
-
|
|
9
|
-
|
|
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 {
|
|
11
|
+
const { filter } = this.props;
|
|
15
12
|
|
|
16
13
|
return (
|
|
17
14
|
<TextField
|
|
18
15
|
className='story-name'
|
|
19
16
|
focusOnMount
|
|
20
|
-
value={
|
|
21
|
-
onChange={(n) => this.props.
|
|
17
|
+
value={filter}
|
|
18
|
+
onChange={(n) => this.props.updateFilter({ name: n })}
|
|
22
19
|
/>
|
|
23
20
|
);
|
|
24
21
|
};
|
|
25
22
|
}
|
|
26
23
|
|
|
27
|
-
|
|
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
|
-
|
|
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
|
-
|
|
8
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
15
|
-
|
|
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<
|
|
34
|
-
const [inputItemsPerPage, setInputItemsPerPage] = React.useState<
|
|
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
|
+
};
|