@learningpool/ui 1.15.5 → 1.16.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/assets/Images.js +7 -18
- package/components/atoms/Autocomplete/Autocomplete.js +3 -14
- package/components/atoms/Button/Button.js +2 -13
- package/components/atoms/Checkbox/Checkbox.js +3 -26
- package/components/atoms/IconButton/IconButton.js +2 -13
- package/components/atoms/Radio/Radio.js +3 -26
- package/components/atoms/Select/Select.js +3 -26
- package/components/atoms/Slider/Slider.js +3 -26
- package/components/atoms/Switch/Switch.js +3 -26
- package/components/atoms/TextField/TextField.js +2 -13
- package/components/atoms/ToggleButton/ToggleButton.js +3 -26
- package/components/datadisplay/Avatar/Avatar.js +13 -28
- package/components/datadisplay/Chip/Chip.js +3 -26
- package/components/datadisplay/List/List.js +2 -13
- package/components/feedback/Alert/Alert.js +3 -26
- package/components/landmarks/Header/Header.js +15 -41
- package/components/landmarks/Header/HeaderActionButtons.d.ts +1 -2
- package/components/landmarks/Header/HeaderActionButtons.js +22 -33
- package/components/landmarks/Header/HeaderStyles.js +54 -11
- package/components/navigation/Drawer/Drawer.js +5 -31
- package/components/navigation/MobileNavigation/MobileNavigation.js +70 -82
- package/components/navigation/MobileNavigation/MobileNavigationAvatar.js +75 -83
- package/components/navigation/MobileNavigation/MobileNavigationAvatarStyles.d.ts +102 -52
- package/components/navigation/MobileNavigation/MobileNavigationAvatarStyles.js +71 -13
- package/components/navigation/MobileNavigation/MobileNavigationDrawer.d.ts +1 -1
- package/components/navigation/MobileNavigation/MobileNavigationDrawer.js +41 -68
- package/components/navigation/MobileNavigation/MobileNavigationDrawerStyles.d.ts +34 -18
- package/components/navigation/MobileNavigation/MobileNavigationDrawerStyles.js +133 -20
- package/components/navigation/MobileNavigation/MobileNavigationItem/MobileNavigationItem.js +22 -45
- package/components/navigation/MobileNavigation/MobileNavigationItem/MobileNavigationItemFlyoutMenu.js +8 -19
- package/components/navigation/MobileNavigation/MobileNavigationItem/MobileNavigationItemFlyoutMenuStyles.js +151 -52
- package/components/navigation/MobileNavigation/MobileNavigationItem/MobileNavigationItemStyles.js +171 -50
- package/components/navigation/MobileNavigation/MobileNavigationMotion.js +11 -11
- package/components/navigation/MobileNavigation/MobileNavigationNotchIndicator.js +11 -15
- package/components/navigation/MobileNavigation/MobileNavigationSearch.d.ts +1 -2
- package/components/navigation/MobileNavigation/MobileNavigationSearch.js +25 -34
- package/components/navigation/MobileNavigation/MobileNavigationSearchStyles.d.ts +34 -18
- package/components/navigation/MobileNavigation/MobileNavigationSearchStyles.js +47 -9
- package/components/navigation/MobileNavigation/MobileNavigationStyles.js +262 -66
- package/components/navigation/MobileNavigation/MobileNavigationToggleSearchX.js +21 -20
- package/components/navigation/MobileNavigation/MobileNavigationToggleX.js +21 -20
- package/components/navigation/VerticalNavigation/VerticalNavigation.js +150 -185
- package/components/navigation/VerticalNavigation/VerticalNavigationAvatar.js +50 -61
- package/components/navigation/VerticalNavigation/VerticalNavigationAvatarStyles.d.ts +102 -52
- package/components/navigation/VerticalNavigation/VerticalNavigationAvatarStyles.js +86 -14
- package/components/navigation/VerticalNavigation/VerticalNavigationItem/VerticalNavigationItem.js +27 -51
- package/components/navigation/VerticalNavigation/VerticalNavigationItem/VerticalNavigationItemFlyoutMenu.js +15 -28
- package/components/navigation/VerticalNavigation/VerticalNavigationItem/VerticalNavigationItemFlyoutMenuStyles.js +135 -39
- package/components/navigation/VerticalNavigation/VerticalNavigationItem/VerticalNavigationItemStyles.js +167 -29
- package/components/navigation/VerticalNavigation/VerticalNavigationMotion.js +11 -11
- package/components/navigation/VerticalNavigation/VerticalNavigationStyles.d.ts +34 -18
- package/components/navigation/VerticalNavigation/VerticalNavigationStyles.js +236 -42
- package/components/navigation/helpers.d.ts +1 -2
- package/components/navigation/helpers.js +28 -32
- package/components/pages/ErrorPage/ErrorPage.js +6 -17
- package/components/pages/ErrorPage/ErrorPageStyles.js +13 -18
- package/components/pages/SideInSide/SideInSide.js +12 -23
- package/components/pages/SideInSide/SideInSideStyles.js +6 -6
- package/components/stream/AppHub/AppHub.js +13 -42
- package/components/stream/AppHub/AppHubAdvertStyles.js +24 -8
- package/components/stream/AppHub/AppHubBannerAdvert.d.ts +1 -2
- package/components/stream/AppHub/AppHubBannerAdvert.js +9 -20
- package/components/stream/AppHub/AppHubCustom.js +8 -19
- package/components/stream/AppHub/AppHubCustomStyles.d.ts +1 -1
- package/components/stream/AppHub/AppHubCustomStyles.js +78 -18
- package/components/stream/AppHub/AppHubProduct.js +26 -48
- package/components/stream/AppHub/AppHubProductStyles.js +104 -19
- package/components/stream/AppHub/AppHubStyles.js +31 -11
- package/components/stream/AppHub/constants.d.ts +1 -2
- package/components/stream/AppHub/constants.js +14 -14
- package/components/stream/AppSwitcher/AppSwitcher.js +225 -316
- package/components/stream/AppSwitcher/AppSwitcherItem.js +11 -22
- package/components/stream/AppSwitcher/AppSwitcherStyles.js +337 -42
- package/components/stream/AppSwitcher/AppSwitcherStylesStandalone.js +255 -21
- package/components/stream/AppSwitcher/PromotionalCampaignItem.js +7 -19
- package/components/stream/AppSwitcher/constants.js +3 -3
- package/lang/en-us.js +1 -1
- package/package.json +7 -2
- package/utils/constants.d.ts +7 -0
- package/utils/constants.js +11 -4
- package/utils/dataAttributes.js +1 -1
- package/utils/helpers.js +33 -40
- package/utils/hooks.js +10 -11
- package/utils/theme.js +26 -19
|
@@ -1,51 +1,4 @@
|
|
|
1
|
-
|
|
2
|
-
__assign = Object.assign || function(t) {
|
|
3
|
-
for (var s, i = 1, n = arguments.length; i < n; i++) {
|
|
4
|
-
s = arguments[i];
|
|
5
|
-
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
|
|
6
|
-
t[p] = s[p];
|
|
7
|
-
}
|
|
8
|
-
return t;
|
|
9
|
-
};
|
|
10
|
-
return __assign.apply(this, arguments);
|
|
11
|
-
};
|
|
12
|
-
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
13
|
-
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
14
|
-
return new (P || (P = Promise))(function (resolve, reject) {
|
|
15
|
-
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
16
|
-
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
17
|
-
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
18
|
-
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
19
|
-
});
|
|
20
|
-
};
|
|
21
|
-
var __generator = (this && this.__generator) || function (thisArg, body) {
|
|
22
|
-
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
|
|
23
|
-
return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
|
|
24
|
-
function verb(n) { return function (v) { return step([n, v]); }; }
|
|
25
|
-
function step(op) {
|
|
26
|
-
if (f) throw new TypeError("Generator is already executing.");
|
|
27
|
-
while (g && (g = 0, op[0] && (_ = 0)), _) try {
|
|
28
|
-
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
|
|
29
|
-
if (y = 0, t) op = [op[0] & 2, t.value];
|
|
30
|
-
switch (op[0]) {
|
|
31
|
-
case 0: case 1: t = op; break;
|
|
32
|
-
case 4: _.label++; return { value: op[1], done: false };
|
|
33
|
-
case 5: _.label++; y = op[1]; op = [0]; continue;
|
|
34
|
-
case 7: op = _.ops.pop(); _.trys.pop(); continue;
|
|
35
|
-
default:
|
|
36
|
-
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
|
|
37
|
-
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
|
|
38
|
-
if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
|
|
39
|
-
if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
|
|
40
|
-
if (t[2]) _.ops.pop();
|
|
41
|
-
_.trys.pop(); continue;
|
|
42
|
-
}
|
|
43
|
-
op = body.call(thisArg, _);
|
|
44
|
-
} catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
|
|
45
|
-
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
|
|
46
|
-
}
|
|
47
|
-
};
|
|
48
|
-
import { Fragment as _Fragment, jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
1
|
+
import { Fragment as _Fragment, jsx as _jsx, jsxs as _jsxs } from "@emotion/react/jsx-runtime";
|
|
49
2
|
import { useState, useEffect } from 'react';
|
|
50
3
|
import PropTypes from 'prop-types';
|
|
51
4
|
import jwtDecode from 'jwt-decode';
|
|
@@ -56,9 +9,10 @@ import { Constants } from './constants';
|
|
|
56
9
|
import { defaultAttributes } from '../../../utils/dataAttributes';
|
|
57
10
|
import ChevronRightIcon from '@mui/icons-material/ChevronRight';
|
|
58
11
|
import PromotionalCampaignItem from './PromotionalCampaignItem';
|
|
59
|
-
|
|
12
|
+
import { EVENT_KEYS } from '../../../utils/constants';
|
|
13
|
+
const addUtmParams = (baseUrl, source, medium, campaign) => {
|
|
60
14
|
try {
|
|
61
|
-
|
|
15
|
+
const url = new URL(baseUrl);
|
|
62
16
|
url.searchParams.append('utm_source', source);
|
|
63
17
|
url.searchParams.append('utm_medium', medium);
|
|
64
18
|
url.searchParams.append('utm_campaign', campaign);
|
|
@@ -69,92 +23,76 @@ var addUtmParams = function (baseUrl, source, medium, campaign) {
|
|
|
69
23
|
return baseUrl;
|
|
70
24
|
}
|
|
71
25
|
};
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
var token = props.token;
|
|
26
|
+
const AppSwitcher = (props) => {
|
|
27
|
+
const { isAppSwitcherOpen, handleToggleAppSwitcher, isDrawerOpen, localization, dataAttributes, apiKey = '', baseUrl } = props;
|
|
28
|
+
let { token } = props;
|
|
76
29
|
// Holds the applications which are displayed.
|
|
77
|
-
|
|
30
|
+
const [applications, setApplications] = useState([]);
|
|
78
31
|
// Holds the latest promotional campaign advert.
|
|
79
|
-
|
|
32
|
+
const [promotionalCampaigns, setPromotionalCampaigns] = useState(null);
|
|
80
33
|
// Controls which tab is active.
|
|
81
|
-
|
|
34
|
+
const [activeTab, setActiveTab] = useState(Constants.Tabs.ListApplications);
|
|
82
35
|
// Holds the list of filtered organisations (on the second tab).
|
|
83
|
-
|
|
36
|
+
const [filteredOrgs, setFilteredOrgs] = useState([]);
|
|
84
37
|
// Holds a reference to the active application (on the second tab).
|
|
85
|
-
|
|
38
|
+
const [activeApplication, setActiveApplication] = useState(null);
|
|
86
39
|
// Stores any org filter text (on the second tab).
|
|
87
|
-
|
|
40
|
+
const [searchString, setSearchString] = useState('');
|
|
88
41
|
// Holds the number of valid promotional campaigns.
|
|
89
|
-
|
|
42
|
+
const [validCampaignCount, setValidCampaignCount] = useState(promotionalCampaigns?.length || 0);
|
|
90
43
|
// Decrease the valid campaign count if an image fails to load.
|
|
91
|
-
|
|
92
|
-
setValidCampaignCount(
|
|
44
|
+
const handleCampaignImageError = () => {
|
|
45
|
+
setValidCampaignCount(prev => Math.max(0, prev - 1));
|
|
93
46
|
};
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
47
|
+
const messages = { ...Constants.DefaultMessages, ...localization };
|
|
48
|
+
const dataIds = { ...defaultAttributes, ...dataAttributes };
|
|
49
|
+
let userId = props.userId ?? '';
|
|
97
50
|
/**
|
|
98
51
|
* Queries the Hub/Home API to fetch latest promotional campaign.
|
|
99
52
|
* @returns {Promise<IApplication[]>} Get a Promotional Campaign to show.
|
|
100
53
|
*/
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
'x-api-key': apiKey
|
|
118
|
-
})
|
|
119
|
-
})];
|
|
120
|
-
case 2:
|
|
121
|
-
response = _a.sent();
|
|
122
|
-
if (!response.ok) {
|
|
123
|
-
console.error('Unable to retrieve latest promotional campaign from Hub API, returned statuscode:', response.status);
|
|
124
|
-
return [2 /*return*/, null];
|
|
125
|
-
}
|
|
126
|
-
return [4 /*yield*/, response.json()];
|
|
127
|
-
case 3:
|
|
128
|
-
responseData = _a.sent();
|
|
129
|
-
data = responseData.records;
|
|
130
|
-
// Store the latest access token
|
|
131
|
-
window.localStorage.setItem(Constants.LocalStorageKey.Token, token);
|
|
132
|
-
return [2 /*return*/, (data === null || data === void 0 ? void 0 : data.map(function (_a) {
|
|
133
|
-
var id = _a.id, name = _a.name, appSwitcherImageUrl = _a.appSwitcherImageUrl, hubImageUrl = _a.hubImageUrl, altText = _a.altText, basePromoUrl = _a.basePromoUrl, isActive = _a.isActive;
|
|
134
|
-
return ({
|
|
135
|
-
id: id,
|
|
136
|
-
name: name,
|
|
137
|
-
appSwitcherImageUrl: appSwitcherImageUrl,
|
|
138
|
-
hubImageUrl: hubImageUrl,
|
|
139
|
-
altText: altText,
|
|
140
|
-
basePromoUrl: basePromoUrl,
|
|
141
|
-
isActive: isActive
|
|
142
|
-
});
|
|
143
|
-
})) || null];
|
|
144
|
-
case 4:
|
|
145
|
-
error_1 = _a.sent();
|
|
146
|
-
console.error('Unable to retrieve and display latest promotional campaign from Hub API', error_1);
|
|
147
|
-
return [2 /*return*/, null];
|
|
148
|
-
case 5: return [2 /*return*/];
|
|
54
|
+
const getLatestPromotionalCampaign = async () => {
|
|
55
|
+
// If the access token has changed the endpoint should be called again.
|
|
56
|
+
if (!token || typeof token !== 'string') {
|
|
57
|
+
return null;
|
|
58
|
+
}
|
|
59
|
+
try {
|
|
60
|
+
const response = await fetch(`${baseUrl ?? Constants.BaseUrl}/promotional-campaigns?onlyLatest=true&isActive=true`, {
|
|
61
|
+
method: 'get',
|
|
62
|
+
headers: new Headers({
|
|
63
|
+
Authorization: `Bearer ${token}`,
|
|
64
|
+
'x-api-key': apiKey
|
|
65
|
+
})
|
|
66
|
+
});
|
|
67
|
+
if (!response.ok) {
|
|
68
|
+
console.error('Unable to retrieve latest promotional campaign from Hub API, returned statuscode:', response.status);
|
|
69
|
+
return null;
|
|
149
70
|
}
|
|
150
|
-
|
|
151
|
-
|
|
71
|
+
const responseData = await response.json();
|
|
72
|
+
const data = responseData.records;
|
|
73
|
+
// Store the latest access token
|
|
74
|
+
window.localStorage.setItem(Constants.LocalStorageKey.Token, token);
|
|
75
|
+
return data?.map(({ id, name, appSwitcherImageUrl, hubImageUrl, altText, basePromoUrl, isActive }) => ({
|
|
76
|
+
id,
|
|
77
|
+
name,
|
|
78
|
+
appSwitcherImageUrl,
|
|
79
|
+
hubImageUrl,
|
|
80
|
+
altText,
|
|
81
|
+
basePromoUrl,
|
|
82
|
+
isActive
|
|
83
|
+
})) || null;
|
|
84
|
+
}
|
|
85
|
+
catch (error) {
|
|
86
|
+
console.error('Unable to retrieve and display latest promotional campaign from Hub API', error);
|
|
87
|
+
return null;
|
|
88
|
+
}
|
|
89
|
+
};
|
|
152
90
|
/**
|
|
153
91
|
* Handles closing of the application dialog.
|
|
154
92
|
*/
|
|
155
|
-
|
|
93
|
+
const handleDialogClose = () => {
|
|
156
94
|
handleToggleAppSwitcher();
|
|
157
|
-
setTimeout(
|
|
95
|
+
setTimeout(() => {
|
|
158
96
|
setSearchString('');
|
|
159
97
|
setActiveApplication(null);
|
|
160
98
|
setActiveTab(Constants.Tabs.ListApplications);
|
|
@@ -164,7 +102,7 @@ var AppSwitcher = function (props) {
|
|
|
164
102
|
* Updates the search/filter text.
|
|
165
103
|
* @param event {React.ChangeEvent}
|
|
166
104
|
*/
|
|
167
|
-
|
|
105
|
+
const handleSearchChange = (event) => {
|
|
168
106
|
setSearchString(event.target.value);
|
|
169
107
|
};
|
|
170
108
|
/**
|
|
@@ -173,13 +111,13 @@ var AppSwitcher = function (props) {
|
|
|
173
111
|
* @param applicationId {number | undefined} - Unique identifier of the application.
|
|
174
112
|
* @returns {void}
|
|
175
113
|
*/
|
|
176
|
-
|
|
177
|
-
event
|
|
178
|
-
event
|
|
114
|
+
const handleGoToAppClick = (event, applicationId) => {
|
|
115
|
+
event?.preventDefault();
|
|
116
|
+
event?.stopPropagation();
|
|
179
117
|
if (!applicationId) {
|
|
180
118
|
return;
|
|
181
119
|
}
|
|
182
|
-
|
|
120
|
+
const selectedApplication = applications.find(a => a.applicationId === applicationId);
|
|
183
121
|
if (!selectedApplication) {
|
|
184
122
|
return;
|
|
185
123
|
}
|
|
@@ -192,222 +130,196 @@ var AppSwitcher = function (props) {
|
|
|
192
130
|
* @param internalName {string | null | undefined } - Internal name of the application.
|
|
193
131
|
* @returns {ReactElement | null } SVG containing the application logo retrieved from the CDN.
|
|
194
132
|
*/
|
|
195
|
-
|
|
133
|
+
const renderApplicationLogo = (internalName, logoVariant) => {
|
|
196
134
|
if (!internalName) {
|
|
197
135
|
return _jsx(_Fragment, {});
|
|
198
136
|
}
|
|
199
|
-
|
|
137
|
+
const urlToIcon = `${Constants.AssetsUrl}${internalName}/logo/latest/${logoVariant ?? LogoVariants.Default}.svg`;
|
|
200
138
|
return (_jsx("svg", { children: _jsx("image", { xlinkHref: urlToIcon, width: "60", height: "60" }) }));
|
|
201
139
|
};
|
|
202
140
|
/**
|
|
203
141
|
* Queries the Steam Home API to fetch a list of applications.
|
|
204
142
|
* @returns {Promise<IApplication[]>} A list of applications the user has access to.
|
|
205
143
|
*/
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
144
|
+
const getApplicationsForUser = async () => {
|
|
145
|
+
// If the access token has changed the endpoint should be called again.
|
|
146
|
+
if (token && typeof token === 'string' && token !== window.localStorage.getItem(Constants.LocalStorageKey.Token)) {
|
|
147
|
+
if (!userId) {
|
|
148
|
+
// Extract user identifier from the JWT.
|
|
149
|
+
const decodedToken = jwtDecode(token);
|
|
150
|
+
userId = decodedToken[Constants.HomeAttributes.UserId];
|
|
151
|
+
}
|
|
152
|
+
const response = await fetch(`${baseUrl ?? Constants.BaseUrl}/users/${userId}/application-instances`, {
|
|
153
|
+
method: 'get',
|
|
154
|
+
headers: new Headers({
|
|
155
|
+
Authorization: `Bearer ${token}`,
|
|
156
|
+
'x-api-key': apiKey
|
|
157
|
+
})
|
|
158
|
+
});
|
|
159
|
+
if (response.status !== 200) {
|
|
160
|
+
console.error('Unable to retrieve user applications from Stream Home');
|
|
161
|
+
return [];
|
|
162
|
+
}
|
|
163
|
+
const data = await response.json();
|
|
164
|
+
// Store the latest access token.
|
|
165
|
+
window.localStorage.setItem(Constants.LocalStorageKey.Token, token);
|
|
166
|
+
return data.map((application) => {
|
|
167
|
+
const { applicationId, applicationName, shortName, internalName, customName, url } = application;
|
|
168
|
+
return {
|
|
169
|
+
applicationId,
|
|
170
|
+
applicationName,
|
|
171
|
+
shortName,
|
|
172
|
+
internalName,
|
|
173
|
+
customName,
|
|
174
|
+
url: url || ''
|
|
175
|
+
};
|
|
176
|
+
});
|
|
177
|
+
}
|
|
178
|
+
else {
|
|
179
|
+
return [];
|
|
180
|
+
}
|
|
181
|
+
};
|
|
182
|
+
useEffect(() => {
|
|
183
|
+
const loadData = async () => {
|
|
184
|
+
let applicationInstances = [];
|
|
185
|
+
let userApplications = [];
|
|
186
|
+
if (!token) {
|
|
187
|
+
const parsedQueryString = queryString.parse(window.location.search);
|
|
188
|
+
if (parsedQueryString.token && typeof parsedQueryString.token === 'string') {
|
|
189
|
+
token = parsedQueryString.token;
|
|
190
|
+
}
|
|
191
|
+
else {
|
|
192
|
+
// Check the 'hash'.
|
|
193
|
+
const match = window.location.hash.match(/token=(.*)/);
|
|
194
|
+
token = (match && match.length === 2 && match[1]) || '';
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
if (!props.applications || props.applications.length === 0) {
|
|
198
|
+
applicationInstances = await getApplicationsForUser();
|
|
199
|
+
}
|
|
200
|
+
else {
|
|
201
|
+
// A hard-coded list of applications has been passed to the component.
|
|
202
|
+
applicationInstances = props.applications;
|
|
203
|
+
}
|
|
204
|
+
if (Array.isArray(applicationInstances) && applicationInstances.length) {
|
|
205
|
+
// Get a distinct list of applications the user has access to.
|
|
206
|
+
const uniqueApplicationIds = applicationInstances.map((item) => item.applicationId).filter((value, index, self) => self.indexOf(value) === index);
|
|
207
|
+
// Iterate over these to build up the userApplications array.
|
|
208
|
+
uniqueApplicationIds.forEach(applicationId => {
|
|
209
|
+
const applications = applicationInstances.filter(instance => instance.applicationId === applicationId);
|
|
210
|
+
if (applications.length > 1) {
|
|
211
|
+
// This is an application with multiple orgs/tenants the user has access to.
|
|
212
|
+
userApplications.push({
|
|
213
|
+
applicationId,
|
|
214
|
+
applicationName: applications[0].applicationName,
|
|
215
|
+
shortName: applications[0].shortName,
|
|
216
|
+
customName: applications[0].customName,
|
|
217
|
+
internalName: applications[0].internalName,
|
|
218
|
+
url: '',
|
|
219
|
+
children: applications.map(a => {
|
|
220
|
+
return {
|
|
221
|
+
name: a.customName ?? a.applicationName,
|
|
222
|
+
url: a.url
|
|
223
|
+
};
|
|
221
224
|
})
|
|
222
|
-
})
|
|
223
|
-
case 1:
|
|
224
|
-
response = _a.sent();
|
|
225
|
-
if (response.status !== 200) {
|
|
226
|
-
console.error('Unable to retrieve user applications from Stream Home');
|
|
227
|
-
return [2 /*return*/, []];
|
|
225
|
+
});
|
|
228
226
|
}
|
|
229
|
-
|
|
230
|
-
//
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
customName: customName,
|
|
244
|
-
url: url || ''
|
|
245
|
-
};
|
|
246
|
-
})];
|
|
247
|
-
case 3: return [2 /*return*/, []];
|
|
227
|
+
else {
|
|
228
|
+
// This is a standalone application.
|
|
229
|
+
userApplications.push({
|
|
230
|
+
applicationId: applications[0].applicationId,
|
|
231
|
+
applicationName: applications[0].applicationName,
|
|
232
|
+
shortName: applications[0].shortName,
|
|
233
|
+
customName: applications[0].customName,
|
|
234
|
+
internalName: applications[0].internalName,
|
|
235
|
+
url: applications[0].url
|
|
236
|
+
});
|
|
237
|
+
}
|
|
238
|
+
});
|
|
239
|
+
// Serialize and cache the applications returned.
|
|
240
|
+
window.localStorage.setItem(Constants.LocalStorageKey.Applications, JSON.stringify(userApplications));
|
|
248
241
|
}
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
return __generator(this, function (_a) {
|
|
255
|
-
switch (_a.label) {
|
|
256
|
-
case 0:
|
|
257
|
-
applicationInstances = [];
|
|
258
|
-
userApplications = [];
|
|
259
|
-
if (!token) {
|
|
260
|
-
parsedQueryString = queryString.parse(window.location.search);
|
|
261
|
-
if (parsedQueryString.token && typeof parsedQueryString.token === 'string') {
|
|
262
|
-
token = parsedQueryString.token;
|
|
263
|
-
}
|
|
264
|
-
else {
|
|
265
|
-
match = window.location.hash.match(/token=(.*)/);
|
|
266
|
-
token = (match && match.length === 2 && match[1]) || '';
|
|
267
|
-
}
|
|
268
|
-
}
|
|
269
|
-
if (!(!props.applications || props.applications.length === 0)) return [3 /*break*/, 2];
|
|
270
|
-
return [4 /*yield*/, getApplicationsForUser()];
|
|
271
|
-
case 1:
|
|
272
|
-
applicationInstances = _a.sent();
|
|
273
|
-
return [3 /*break*/, 3];
|
|
274
|
-
case 2:
|
|
275
|
-
// A hard-coded list of applications has been passed to the component.
|
|
276
|
-
applicationInstances = props.applications;
|
|
277
|
-
_a.label = 3;
|
|
278
|
-
case 3:
|
|
279
|
-
if (Array.isArray(applicationInstances) && applicationInstances.length) {
|
|
280
|
-
uniqueApplicationIds = applicationInstances.map(function (item) { return item.applicationId; }).filter(function (value, index, self) { return self.indexOf(value) === index; });
|
|
281
|
-
// Iterate over these to build up the userApplications array.
|
|
282
|
-
uniqueApplicationIds.forEach(function (applicationId) {
|
|
283
|
-
var applications = applicationInstances.filter(function (instance) { return instance.applicationId === applicationId; });
|
|
284
|
-
if (applications.length > 1) {
|
|
285
|
-
// This is an application with multiple orgs/tenants the user has access to.
|
|
286
|
-
userApplications.push({
|
|
287
|
-
applicationId: applicationId,
|
|
288
|
-
applicationName: applications[0].applicationName,
|
|
289
|
-
shortName: applications[0].shortName,
|
|
290
|
-
customName: applications[0].customName,
|
|
291
|
-
internalName: applications[0].internalName,
|
|
292
|
-
url: '',
|
|
293
|
-
children: applications.map(function (a) {
|
|
294
|
-
var _a;
|
|
295
|
-
return {
|
|
296
|
-
name: (_a = a.customName) !== null && _a !== void 0 ? _a : a.applicationName,
|
|
297
|
-
url: a.url
|
|
298
|
-
};
|
|
299
|
-
})
|
|
300
|
-
});
|
|
301
|
-
}
|
|
302
|
-
else {
|
|
303
|
-
// This is a standalone application.
|
|
304
|
-
userApplications.push({
|
|
305
|
-
applicationId: applications[0].applicationId,
|
|
306
|
-
applicationName: applications[0].applicationName,
|
|
307
|
-
shortName: applications[0].shortName,
|
|
308
|
-
customName: applications[0].customName,
|
|
309
|
-
internalName: applications[0].internalName,
|
|
310
|
-
url: applications[0].url
|
|
311
|
-
});
|
|
312
|
-
}
|
|
313
|
-
});
|
|
314
|
-
// Serialize and cache the applications returned.
|
|
315
|
-
window.localStorage.setItem(Constants.LocalStorageKey.Applications, JSON.stringify(userApplications));
|
|
316
|
-
}
|
|
317
|
-
else {
|
|
318
|
-
localApplications = window.localStorage.getItem(Constants.LocalStorageKey.Applications);
|
|
319
|
-
if (localApplications) {
|
|
320
|
-
// Recreate the application state from local storage.
|
|
321
|
-
userApplications = JSON.parse(localApplications);
|
|
322
|
-
}
|
|
323
|
-
}
|
|
324
|
-
// Store the user's applications.
|
|
325
|
-
setApplications(userApplications);
|
|
326
|
-
return [2 /*return*/];
|
|
242
|
+
else {
|
|
243
|
+
const localApplications = window.localStorage.getItem(Constants.LocalStorageKey.Applications);
|
|
244
|
+
if (localApplications) {
|
|
245
|
+
// Recreate the application state from local storage.
|
|
246
|
+
userApplications = JSON.parse(localApplications);
|
|
327
247
|
}
|
|
328
|
-
}
|
|
329
|
-
|
|
248
|
+
}
|
|
249
|
+
// Store the user's applications.
|
|
250
|
+
setApplications(userApplications);
|
|
251
|
+
};
|
|
330
252
|
loadData()
|
|
331
253
|
.catch(console.error);
|
|
332
254
|
}, [token, userId, props.applications]);
|
|
333
|
-
useEffect(
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
if (localPromotionalCampaignsJson) {
|
|
355
|
-
try {
|
|
356
|
-
parsedCampaigns = JSON.parse(localPromotionalCampaignsJson);
|
|
357
|
-
if (Array.isArray(parsedCampaigns)) {
|
|
358
|
-
promotionalCampaigns_1 = parsedCampaigns;
|
|
359
|
-
}
|
|
360
|
-
}
|
|
361
|
-
catch (error) {
|
|
362
|
-
console.error('Error parsing stored campaigns:', error);
|
|
255
|
+
useEffect(() => {
|
|
256
|
+
const loadPromotionalCampaigns = async () => {
|
|
257
|
+
try {
|
|
258
|
+
let promotionalCampaigns = null;
|
|
259
|
+
// Use props if available
|
|
260
|
+
if (props.promotionalCampaigns && props.promotionalCampaigns.length > 0) {
|
|
261
|
+
promotionalCampaigns = props.promotionalCampaigns;
|
|
262
|
+
}
|
|
263
|
+
else if (token && typeof token === 'string' &&
|
|
264
|
+
token !== window.localStorage.getItem(Constants.LocalStorageKey.Token)) {
|
|
265
|
+
// Fetch from API if token has changed
|
|
266
|
+
promotionalCampaigns = await getLatestPromotionalCampaign();
|
|
267
|
+
}
|
|
268
|
+
else {
|
|
269
|
+
// Check localStorage
|
|
270
|
+
const localPromotionalCampaignsJson = window.localStorage.getItem(Constants.LocalStorageKey.PromotionalCampaigns);
|
|
271
|
+
if (localPromotionalCampaignsJson) {
|
|
272
|
+
try {
|
|
273
|
+
const parsedCampaigns = JSON.parse(localPromotionalCampaignsJson);
|
|
274
|
+
if (Array.isArray(parsedCampaigns)) {
|
|
275
|
+
promotionalCampaigns = parsedCampaigns;
|
|
363
276
|
}
|
|
364
277
|
}
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
// Update state and cache if we have campaigns
|
|
368
|
-
if (Array.isArray(promotionalCampaigns_1) && promotionalCampaigns_1.length > 0) {
|
|
369
|
-
setPromotionalCampaigns(promotionalCampaigns_1);
|
|
370
|
-
setValidCampaignCount(promotionalCampaigns_1.length);
|
|
371
|
-
window.localStorage.setItem(Constants.LocalStorageKey.PromotionalCampaigns, JSON.stringify(promotionalCampaigns_1));
|
|
372
|
-
}
|
|
373
|
-
else {
|
|
374
|
-
setPromotionalCampaigns(null);
|
|
278
|
+
catch (error) {
|
|
279
|
+
console.error('Error parsing stored campaigns:', error);
|
|
375
280
|
}
|
|
376
|
-
|
|
377
|
-
case 5:
|
|
378
|
-
error_2 = _a.sent();
|
|
379
|
-
console.error('Error loading promotional campaigns:', error_2);
|
|
380
|
-
setPromotionalCampaigns(null);
|
|
381
|
-
return [3 /*break*/, 6];
|
|
382
|
-
case 6: return [2 /*return*/];
|
|
281
|
+
}
|
|
383
282
|
}
|
|
384
|
-
|
|
385
|
-
|
|
283
|
+
// Update state and cache if we have campaigns
|
|
284
|
+
if (Array.isArray(promotionalCampaigns) && promotionalCampaigns.length > 0) {
|
|
285
|
+
setPromotionalCampaigns(promotionalCampaigns);
|
|
286
|
+
setValidCampaignCount(promotionalCampaigns.length);
|
|
287
|
+
window.localStorage.setItem(Constants.LocalStorageKey.PromotionalCampaigns, JSON.stringify(promotionalCampaigns));
|
|
288
|
+
}
|
|
289
|
+
else {
|
|
290
|
+
setPromotionalCampaigns(null);
|
|
291
|
+
}
|
|
292
|
+
}
|
|
293
|
+
catch (error) {
|
|
294
|
+
console.error('Error loading promotional campaigns:', error);
|
|
295
|
+
setPromotionalCampaigns(null);
|
|
296
|
+
}
|
|
297
|
+
};
|
|
386
298
|
loadPromotionalCampaigns()
|
|
387
299
|
.catch(console.error);
|
|
388
300
|
}, [token, props.promotionalCampaigns]);
|
|
389
|
-
useEffect(
|
|
301
|
+
useEffect(() => {
|
|
390
302
|
if (isAppSwitcherOpen) {
|
|
391
303
|
document.addEventListener('mousedown', handleAppSwitcherClose);
|
|
392
304
|
}
|
|
393
|
-
return
|
|
305
|
+
return () => {
|
|
394
306
|
document.removeEventListener('mousedown', handleAppSwitcherClose);
|
|
395
307
|
};
|
|
396
308
|
}, [isAppSwitcherOpen]);
|
|
397
|
-
useEffect(
|
|
398
|
-
|
|
399
|
-
|
|
309
|
+
useEffect(() => document.addEventListener('keydown', handleKeyDown));
|
|
310
|
+
const handleAppSwitcherClose = (event) => {
|
|
311
|
+
const appSwitcherButton = document.getElementById(defaultAttributes.VerticalNavigationAppSwitcherToggle);
|
|
400
312
|
// Allow the appswitcher button to handle closing instead of closing it here.
|
|
401
|
-
if (appSwitcherButton
|
|
313
|
+
if (appSwitcherButton?.contains(event.target)) {
|
|
402
314
|
return;
|
|
403
315
|
}
|
|
404
316
|
// Close the dialog when clicking outside the panel.
|
|
405
317
|
handleDialogClose();
|
|
406
318
|
};
|
|
407
|
-
|
|
408
|
-
if (isAppSwitcherOpen && event && event.type ===
|
|
319
|
+
const handleKeyDown = (event) => {
|
|
320
|
+
if (isAppSwitcherOpen && event && event.type === EVENT_KEYS.Keydown) {
|
|
409
321
|
// Close AppSwitcher if Escape key is pressed
|
|
410
|
-
if (event.key ===
|
|
322
|
+
if (event.key === EVENT_KEYS.Escape) {
|
|
411
323
|
handleDialogClose();
|
|
412
324
|
// Doesn't return focus but we need to investigate MUI again
|
|
413
325
|
// so that should handle it
|
|
@@ -417,26 +329,23 @@ var AppSwitcher = function (props) {
|
|
|
417
329
|
if (!props.applications && (!token || !apiKey)) {
|
|
418
330
|
return null;
|
|
419
331
|
}
|
|
420
|
-
|
|
421
|
-
return (_jsxs(AppSwitcherPanel,
|
|
332
|
+
const { hidePromotionalCampaign = false } = props;
|
|
333
|
+
return (_jsxs(AppSwitcherPanel, { id: "app-switcher-menu", style: {
|
|
422
334
|
display: isAppSwitcherOpen ? 'block' : 'none',
|
|
423
335
|
left: isDrawerOpen ? Constants.DrawerWidth.Expanded : Constants.DrawerWidth.Collapsed - 3
|
|
424
|
-
}, role: 'dialog', "aria-label": "App Switcher", onKeyDown: handleKeyDown, "data-id": dataIds.AppSwitcherContainer, hasPromotionalCampaign: validCampaignCount > 0, onMouseDown:
|
|
425
|
-
? (_jsxs("div", { children: [!hidePromotionalCampaign && promotionalCampaigns && promotionalCampaigns.length > 0 && (_jsx("div",
|
|
426
|
-
_jsx(StyleHomeButton,
|
|
336
|
+
}, role: 'dialog', "aria-label": "App Switcher", onKeyDown: handleKeyDown, "data-id": dataIds.AppSwitcherContainer, hasPromotionalCampaign: validCampaignCount > 0, onMouseDown: (event) => event.stopPropagation(), children: [activeTab === Constants.Tabs.ListApplications
|
|
337
|
+
? (_jsxs("div", { children: [!hidePromotionalCampaign && promotionalCampaigns && promotionalCampaigns.length > 0 && (_jsx("div", { className: "promotional-campaigns-container", children: promotionalCampaigns.map((campaign) => (_jsx(PromotionalCampaignItem, { imageUrl: campaign.appSwitcherImageUrl, altText: campaign.altText || messages['app-switcher-alt-text'], linkUrl: addUtmParams(campaign.basePromoUrl, document.title || 'app_switcher', 'app_switcher_advert', campaign.name), onImageError: handleCampaignImageError }, campaign.id))) })), _jsxs(AppListHeader, { "data-id": dataIds.AppSwitcherHeader, children: [messages['your-apps'], !props.hideStreamHomeButton &&
|
|
338
|
+
_jsx(StyleHomeButton, { "aria-label": messages['go-to-hub'], endIcon: _jsx(ChevronRightIcon, {}), onClick: e => window.open(props.StreamHomeUrl ?? Constants.DefaultStreamHomeUrl), children: messages['go-to-hub'] })] }), _jsx(MenuContent, { style: {
|
|
427
339
|
display: activeTab === 1 ? 'flex' : 'none'
|
|
428
|
-
}, "data-id": dataIds.AppSwitcherList }, { children:
|
|
429
|
-
var applicationId = _a.applicationId, applicationName = _a.applicationName, shortName = _a.shortName, customName = _a.customName, internalName = _a.internalName, url = _a.url, children = _a.children;
|
|
430
|
-
return (_jsxs(AppListItem, __assign({ "data-id": dataIds.AppSwitcherItem }, { children: [url && (_jsx(AppSwitcherItem, { internalName: internalName, shortName: shortName, customName: customName, url: url, handleGoToAppClick: handleGoToAppClick })), !url && (_jsx(AppSwitcherItem, { internalName: internalName, shortName: shortName, customName: customName, handleGoToAppClick: handleGoToAppClick, applicationId: applicationId })), children && (_jsx(AppOrganisationCount, __assign({ "data-id": dataIds.AppSwitcherOrgCount }, { children: children.length })))] }), applicationId));
|
|
431
|
-
}) }))] }))
|
|
340
|
+
}, "data-id": dataIds.AppSwitcherList, children: applications.map(({ applicationId, applicationName, shortName, customName, internalName, url, children }) => (_jsxs(AppListItem, { "data-id": dataIds.AppSwitcherItem, children: [url && (_jsx(AppSwitcherItem, { internalName: internalName, shortName: shortName, customName: customName, url: url, handleGoToAppClick: handleGoToAppClick })), !url && (_jsx(AppSwitcherItem, { internalName: internalName, shortName: shortName, customName: customName, handleGoToAppClick: handleGoToAppClick, applicationId: applicationId })), children && (_jsx(AppOrganisationCount, { "data-id": dataIds.AppSwitcherOrgCount, children: children.length }))] }, applicationId))) })] }))
|
|
432
341
|
: null, activeTab === Constants.Tabs.ListOrgs
|
|
433
|
-
? (_jsxs(SearchContent,
|
|
342
|
+
? (_jsxs(SearchContent, { style: {
|
|
434
343
|
display: activeTab === 2 ? 'flex' : 'none'
|
|
435
|
-
}, "data-id": dataIds.AppSwitcherOrgPanel
|
|
344
|
+
}, "data-id": dataIds.AppSwitcherOrgPanel, children: [_jsxs(BackButton, { onClick: () => {
|
|
436
345
|
setActiveTab(Constants.Tabs.ListApplications);
|
|
437
346
|
setSearchString('');
|
|
438
|
-
}, "data-id": dataIds.AppSwitcherOrgBackButton
|
|
439
|
-
: null] }))
|
|
347
|
+
}, "data-id": dataIds.AppSwitcherOrgBackButton, children: [_jsx(StyledSVG, { className: "MuiSvgIcon-root MuiSvgIcon-fontSizeMedium MuiBox-root css-1om0hkc", focusable: "false", "aria-hidden": "true", viewBox: "0 0 24 24", "data-testid": "ChevronLeftIcon", children: _jsx("path", { d: "M15.41 7.41 14 6l-6 6 6 6 1.41-1.41L10.83 12z" }) }), messages['back-to']] }), _jsxs(SelectedOrganisation, { "data-id": dataIds.AppSwitcherOrgHeader, children: [renderApplicationLogo(activeApplication?.internalName, LogoVariants.Solid), _jsx("span", { children: activeApplication ? activeApplication.applicationName : '' })] }), _jsx(SearchBox, { id: "app-switcher-search-org", type: 'text', value: searchString, onChange: handleSearchChange, placeholder: messages.search, "data-id": dataIds.AppSwitcherOrgSearch }), _jsx(OrganisationList, { "data-id": dataIds.AppSwitcherOrgList, children: filteredOrgs?.filter(o => o.name.toLowerCase().includes(searchString.toLowerCase())).map((org, i) => (_jsxs(OrganisationLink, { href: org.url, target: "_blank", "data-id": dataIds.AppSwitcherOrgItem, children: [org.name, _jsx(StyledSVG, { className: "MuiSvgIcon-root MuiSvgIcon-fontSizeMedium MuiBox-root css-1om0hkc", focusable: "false", "aria-hidden": "true", viewBox: "0 0 24 24", "data-testid": "ChevronRightIcon", children: _jsx("path", { d: "M10 6 8.59 7.41 13.17 12l-4.58 4.59L10 18l6-6z" }) })] }, i))) })] }))
|
|
348
|
+
: null] }));
|
|
440
349
|
};
|
|
441
350
|
AppSwitcher.propTypes = {
|
|
442
351
|
token: PropTypes.string,
|