@os1-platform/console-ui-react 0.1.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/dist/commonjs/aaa/index.js +319 -0
- package/package.json +68 -0
- package/readme.md +294 -0
- package/src/aaa/index.tsx +318 -0
- package/src/components/modal/index.tsx +18 -0
- package/src/components/modal/interface.ts +32 -0
- package/src/components/toast/index.tsx +19 -0
- package/src/components/toast/interface.ts +20 -0
- package/src/index.ts +6 -0
- package/src/init/index.tsx +149 -0
- package/src/init/interface.ts +6 -0
- package/tsconfig.json +26 -0
|
@@ -0,0 +1,319 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __assign = (this && this.__assign) || function () {
|
|
3
|
+
__assign = Object.assign || function(t) {
|
|
4
|
+
for (var s, i = 1, n = arguments.length; i < n; i++) {
|
|
5
|
+
s = arguments[i];
|
|
6
|
+
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
|
|
7
|
+
t[p] = s[p];
|
|
8
|
+
}
|
|
9
|
+
return t;
|
|
10
|
+
};
|
|
11
|
+
return __assign.apply(this, arguments);
|
|
12
|
+
};
|
|
13
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
14
|
+
if (k2 === undefined) k2 = k;
|
|
15
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
16
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
17
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
18
|
+
}
|
|
19
|
+
Object.defineProperty(o, k2, desc);
|
|
20
|
+
}) : (function(o, m, k, k2) {
|
|
21
|
+
if (k2 === undefined) k2 = k;
|
|
22
|
+
o[k2] = m[k];
|
|
23
|
+
}));
|
|
24
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
25
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
26
|
+
}) : function(o, v) {
|
|
27
|
+
o["default"] = v;
|
|
28
|
+
});
|
|
29
|
+
var __importStar = (this && this.__importStar) || function (mod) {
|
|
30
|
+
if (mod && mod.__esModule) return mod;
|
|
31
|
+
var result = {};
|
|
32
|
+
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
|
33
|
+
__setModuleDefault(result, mod);
|
|
34
|
+
return result;
|
|
35
|
+
};
|
|
36
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
37
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
38
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
39
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
40
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
41
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
42
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
43
|
+
});
|
|
44
|
+
};
|
|
45
|
+
var __generator = (this && this.__generator) || function (thisArg, body) {
|
|
46
|
+
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
|
|
47
|
+
return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
|
|
48
|
+
function verb(n) { return function (v) { return step([n, v]); }; }
|
|
49
|
+
function step(op) {
|
|
50
|
+
if (f) throw new TypeError("Generator is already executing.");
|
|
51
|
+
while (g && (g = 0, op[0] && (_ = 0)), _) try {
|
|
52
|
+
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;
|
|
53
|
+
if (y = 0, t) op = [op[0] & 2, t.value];
|
|
54
|
+
switch (op[0]) {
|
|
55
|
+
case 0: case 1: t = op; break;
|
|
56
|
+
case 4: _.label++; return { value: op[1], done: false };
|
|
57
|
+
case 5: _.label++; y = op[1]; op = [0]; continue;
|
|
58
|
+
case 7: op = _.ops.pop(); _.trys.pop(); continue;
|
|
59
|
+
default:
|
|
60
|
+
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
|
|
61
|
+
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
|
|
62
|
+
if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
|
|
63
|
+
if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
|
|
64
|
+
if (t[2]) _.ops.pop();
|
|
65
|
+
_.trys.pop(); continue;
|
|
66
|
+
}
|
|
67
|
+
op = body.call(thisArg, _);
|
|
68
|
+
} catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
|
|
69
|
+
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
|
|
70
|
+
}
|
|
71
|
+
};
|
|
72
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
73
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
74
|
+
};
|
|
75
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
76
|
+
exports.OS1HttpClient = exports.OS1Modal = exports.OS1Toast = exports.OS1Provider = exports.ConsoleUIContext = exports.AuthContext = void 0;
|
|
77
|
+
var jsx_runtime_1 = require("react/jsx-runtime");
|
|
78
|
+
var console_ui_js_1 = require("@os1-platform/console-ui-js");
|
|
79
|
+
Object.defineProperty(exports, "OS1HttpClient", { enumerable: true, get: function () { return console_ui_js_1.HttpClient; } });
|
|
80
|
+
var react_1 = __importStar(require("react"));
|
|
81
|
+
var axios_1 = __importDefault(require("axios"));
|
|
82
|
+
exports.AuthContext = react_1.default.createContext(undefined);
|
|
83
|
+
exports.ConsoleUIContext = react_1.default.createContext(undefined);
|
|
84
|
+
var HeaderAndSideBar = function (props) {
|
|
85
|
+
var _a = (0, react_1.useState)(null), consoleInstance = _a[0], setConsoleInstance = _a[1];
|
|
86
|
+
(0, react_1.useEffect)(function () {
|
|
87
|
+
if (!props.isLoading) {
|
|
88
|
+
var console_1 = console_ui_js_1.ConsoleUiInit.getInstance(props.clientId, props.loginRedirectPath, props.logoutRedirectPath, props.devOrgName, props.authurl, props.appId, props.userManager);
|
|
89
|
+
setConsoleInstance(console_1);
|
|
90
|
+
console_1.renderHeaderAndSidebar('headerAndSidebar', props.controls);
|
|
91
|
+
}
|
|
92
|
+
}, [props.isLoading]);
|
|
93
|
+
if (props.isLoading) {
|
|
94
|
+
if (props.loader) {
|
|
95
|
+
return props.loader;
|
|
96
|
+
}
|
|
97
|
+
else {
|
|
98
|
+
var keyframes = "\n @-webkit-keyframes spin {\n 0% {\n -webkit-transform: rotate(0deg);\n }\n 100% {\n -webkit-transform: rotate(360deg);\n }\n }\n ";
|
|
99
|
+
var styleSheets = Array.from(document.styleSheets).filter(function (styleSheet) {
|
|
100
|
+
return !styleSheet.href || styleSheet.href.startsWith(window.location.origin);
|
|
101
|
+
});
|
|
102
|
+
for (var _i = 0, styleSheets_1 = styleSheets; _i < styleSheets_1.length; _i++) {
|
|
103
|
+
var style = styleSheets_1[_i];
|
|
104
|
+
if (style instanceof CSSStyleSheet && style.cssRules) {
|
|
105
|
+
style.insertRule(keyframes, style.cssRules.length);
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
var loaderStyle = function () { return ({
|
|
109
|
+
marginTop: '50vh',
|
|
110
|
+
marginLeft: '50vw',
|
|
111
|
+
border: '12px solid #F3F3F3',
|
|
112
|
+
borderRadius: '50%',
|
|
113
|
+
borderTop: '12px solid grey',
|
|
114
|
+
width: '40px',
|
|
115
|
+
height: '40px',
|
|
116
|
+
animationName: 'spin',
|
|
117
|
+
animationDuration: '2s',
|
|
118
|
+
animationTimingFunction: 'linear',
|
|
119
|
+
animationIterationCount: 'infinite',
|
|
120
|
+
}); };
|
|
121
|
+
return (0, jsx_runtime_1.jsx)("div", { style: loaderStyle() });
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
//console.log(consoleInstance, props);
|
|
125
|
+
return ((0, jsx_runtime_1.jsx)(exports.ConsoleUIContext.Provider, __assign({ value: consoleInstance }, { children: (0, jsx_runtime_1.jsx)("div", __assign({ id: "headerAndSidebar" }, { children: props.children })) })));
|
|
126
|
+
};
|
|
127
|
+
var getCleanedDomain = function (domain) {
|
|
128
|
+
var cleanedDomain = String(domain);
|
|
129
|
+
var splitHost = cleanedDomain.split('.');
|
|
130
|
+
var org = splitHost[0] || '';
|
|
131
|
+
var cleanedOrg = org.replace('-cdev', '');
|
|
132
|
+
var base = splitHost.join('.');
|
|
133
|
+
return { orgShortName: cleanedOrg, baseDomain: base };
|
|
134
|
+
};
|
|
135
|
+
var getTenantFromDevPortal = function (orgShortName) { return __awaiter(void 0, void 0, void 0, function () {
|
|
136
|
+
var url, response;
|
|
137
|
+
return __generator(this, function (_a) {
|
|
138
|
+
switch (_a.label) {
|
|
139
|
+
case 0:
|
|
140
|
+
url = "https://api.getos1.com/app/core-api/tenant?orgShortName=".concat(orgShortName);
|
|
141
|
+
return [4 /*yield*/, axios_1.default.get(url)];
|
|
142
|
+
case 1:
|
|
143
|
+
response = _a.sent();
|
|
144
|
+
return [2 /*return*/, response.data.data];
|
|
145
|
+
}
|
|
146
|
+
});
|
|
147
|
+
}); };
|
|
148
|
+
var getTenantId = function (devOrgNameArg) {
|
|
149
|
+
if (devOrgNameArg === void 0) { devOrgNameArg = null; }
|
|
150
|
+
var devOrgName = devOrgNameArg;
|
|
151
|
+
//if (!devOrgNameArg) devOrgName = getAuthConfig().devOrgName;
|
|
152
|
+
var hostname = window.location.hostname || null;
|
|
153
|
+
return hostname
|
|
154
|
+
? (hostname.split('.')[0] == 'developer' ||
|
|
155
|
+
hostname.split('.')[0] == 'developer2' ||
|
|
156
|
+
hostname.split('.')[0].includes('-cdev')) &&
|
|
157
|
+
devOrgName
|
|
158
|
+
? devOrgName
|
|
159
|
+
: hostname.split('.')[0]
|
|
160
|
+
: '';
|
|
161
|
+
};
|
|
162
|
+
var getKeyCloakAuthority = function (domain, devOrgName) { return __awaiter(void 0, void 0, void 0, function () {
|
|
163
|
+
var orgName, baseDomainName, _a, orgShortName, baseDomain, tenant, tenantId;
|
|
164
|
+
return __generator(this, function (_b) {
|
|
165
|
+
switch (_b.label) {
|
|
166
|
+
case 0:
|
|
167
|
+
orgName = '';
|
|
168
|
+
baseDomainName = '';
|
|
169
|
+
if (devOrgName != undefined) {
|
|
170
|
+
orgName = devOrgName;
|
|
171
|
+
baseDomainName = domain.substring(domain.indexOf('.'));
|
|
172
|
+
}
|
|
173
|
+
else {
|
|
174
|
+
_a = getCleanedDomain(domain), orgShortName = _a.orgShortName, baseDomain = _a.baseDomain;
|
|
175
|
+
orgName = orgShortName;
|
|
176
|
+
baseDomainName = baseDomain;
|
|
177
|
+
}
|
|
178
|
+
if (!baseDomainName.includes('os1')) return [3 /*break*/, 2];
|
|
179
|
+
return [4 /*yield*/, getTenantFromDevPortal(orgName)];
|
|
180
|
+
case 1:
|
|
181
|
+
tenant = _b.sent();
|
|
182
|
+
return [2 /*return*/, "".concat(tenant.stackAuthUrl, "/auth/realms/").concat(tenant.tenantId)];
|
|
183
|
+
case 2:
|
|
184
|
+
tenantId = getTenantId(orgName);
|
|
185
|
+
//console.log(tenantId);
|
|
186
|
+
return [2 /*return*/, "https://keycloak".concat(baseDomainName, "/auth/realms/").concat(tenantId)];
|
|
187
|
+
}
|
|
188
|
+
});
|
|
189
|
+
}); };
|
|
190
|
+
var OS1Provider = function (props) {
|
|
191
|
+
var _a = (0, react_1.useState)(''), authUrl = _a[0], setAuthUrl = _a[1];
|
|
192
|
+
// const [tenantDns, setTenantDns] = useState('');
|
|
193
|
+
// let isMountedRef = useRef<boolean>(false);
|
|
194
|
+
var authUrls = '';
|
|
195
|
+
(0, react_1.useEffect)(function () {
|
|
196
|
+
(function () {
|
|
197
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
198
|
+
return __generator(this, function (_a) {
|
|
199
|
+
switch (_a.label) {
|
|
200
|
+
case 0: return [4 /*yield*/, getKeyCloakAuthority(window.location.hostname, props.devOrgName)];
|
|
201
|
+
case 1:
|
|
202
|
+
authUrls = _a.sent();
|
|
203
|
+
setAuthUrl(authUrls);
|
|
204
|
+
return [2 /*return*/];
|
|
205
|
+
}
|
|
206
|
+
});
|
|
207
|
+
});
|
|
208
|
+
})();
|
|
209
|
+
}, []);
|
|
210
|
+
return ((0, jsx_runtime_1.jsx)(OS1Provider2, { clientId: props.clientId, loginRedirectPath: props.loginRedirectPath, logoutRedirectPath: props.logoutRedirectPath, devOrgName: props.devOrgName, appId: props.appId, controls: props.controls, authUrl: authUrl, props: props }));
|
|
211
|
+
};
|
|
212
|
+
exports.OS1Provider = OS1Provider;
|
|
213
|
+
var OS1Provider2 = function (props) {
|
|
214
|
+
//console.log(props);
|
|
215
|
+
var userManager = new console_ui_js_1.AAA(props.clientId, props.loginRedirectPath, props.logoutRedirectPath, props.devOrgName, props.authUrl);
|
|
216
|
+
var value = '';
|
|
217
|
+
//console.log('userManager', userManager);
|
|
218
|
+
var _a = (0, react_1.useState)(true), isLoading = _a[0], setIsLoading = _a[1];
|
|
219
|
+
var isMountedRef = (0, react_1.useRef)(false);
|
|
220
|
+
(0, react_1.useEffect)(function () {
|
|
221
|
+
// Store current isMounted since this could change while awaiting async operations below
|
|
222
|
+
isMountedRef.current = true;
|
|
223
|
+
(function () { return __awaiter(void 0, void 0, void 0, function () {
|
|
224
|
+
var user, error_1;
|
|
225
|
+
return __generator(this, function (_a) {
|
|
226
|
+
switch (_a.label) {
|
|
227
|
+
case 0:
|
|
228
|
+
user = undefined;
|
|
229
|
+
_a.label = 1;
|
|
230
|
+
case 1:
|
|
231
|
+
_a.trys.push([1, 3, , 4]);
|
|
232
|
+
return [4 /*yield*/, userManager.getUserInfo()];
|
|
233
|
+
case 2:
|
|
234
|
+
user = _a.sent();
|
|
235
|
+
return [3 /*break*/, 4];
|
|
236
|
+
case 3:
|
|
237
|
+
error_1 = _a.sent();
|
|
238
|
+
window.console.log('Error: ', error_1);
|
|
239
|
+
return [3 /*break*/, 4];
|
|
240
|
+
case 4:
|
|
241
|
+
if (!hasCodeInUrl(window.location)) return [3 /*break*/, 6];
|
|
242
|
+
return [4 /*yield*/, (userManager === null || userManager === void 0 ? void 0 : userManager.logincallback())];
|
|
243
|
+
case 5:
|
|
244
|
+
_a.sent();
|
|
245
|
+
cleanBrowserUrl();
|
|
246
|
+
setIsLoading(false);
|
|
247
|
+
return [2 /*return*/];
|
|
248
|
+
case 6: return [4 /*yield*/, (userManager === null || userManager === void 0 ? void 0 : userManager.isAuthenticated())];
|
|
249
|
+
case 7:
|
|
250
|
+
if (!(_a.sent())) {
|
|
251
|
+
userManager === null || userManager === void 0 ? void 0 : userManager.login();
|
|
252
|
+
}
|
|
253
|
+
else if (isMountedRef.current) {
|
|
254
|
+
setIsLoading(false);
|
|
255
|
+
}
|
|
256
|
+
return [2 /*return*/];
|
|
257
|
+
}
|
|
258
|
+
});
|
|
259
|
+
}); })();
|
|
260
|
+
return function () {
|
|
261
|
+
isMountedRef.current = false;
|
|
262
|
+
};
|
|
263
|
+
}, [window.location, userManager]);
|
|
264
|
+
return ((0, jsx_runtime_1.jsx)(exports.AuthContext.Provider, __assign({ value: value }, { children: (0, jsx_runtime_1.jsx)(HeaderAndSideBar, __assign({ userManager: userManager, isLoading: isLoading, loader: props.loader, devOrgName: props.devOrgName, controls: props.controls, appId: props.appId, authUrl: props.authUrl }, { children: props.props.children })) })));
|
|
265
|
+
};
|
|
266
|
+
var hasCodeInUrl = function (location) {
|
|
267
|
+
var searchParams = new URLSearchParams(location.search);
|
|
268
|
+
var hashParams = new URLSearchParams(location.hash.replace('#', '?'));
|
|
269
|
+
return Boolean(searchParams.get('code') ||
|
|
270
|
+
searchParams.get('id_token') ||
|
|
271
|
+
searchParams.get('session_state') ||
|
|
272
|
+
searchParams.get('state') ||
|
|
273
|
+
hashParams.get('code') ||
|
|
274
|
+
hashParams.get('id_token') ||
|
|
275
|
+
hashParams.get('session_state') ||
|
|
276
|
+
hashParams.get('state'));
|
|
277
|
+
};
|
|
278
|
+
var cleanBrowserUrl = function () {
|
|
279
|
+
var search = window.location.search;
|
|
280
|
+
if (search &&
|
|
281
|
+
(search.includes('session_state=') ||
|
|
282
|
+
search.includes('state=') ||
|
|
283
|
+
search.includes('code='))) {
|
|
284
|
+
/*
|
|
285
|
+
* Use replaceState to redirect the user away and remove the querystring parameters
|
|
286
|
+
*/
|
|
287
|
+
window.history.replaceState({}, document.title, window.location.href.split('?')[0]);
|
|
288
|
+
}
|
|
289
|
+
};
|
|
290
|
+
// export { Toast, Modal };
|
|
291
|
+
var OS1Toast = function (props) {
|
|
292
|
+
var consoleInstance = react_1.default.useContext(exports.ConsoleUIContext);
|
|
293
|
+
var _a = (0, react_1.useState)(''), authUrl = _a[0], setAuthUrl = _a[1];
|
|
294
|
+
(0, react_1.useEffect)(function () {
|
|
295
|
+
var _a, _b;
|
|
296
|
+
if (consoleInstance) {
|
|
297
|
+
setAuthUrl((_b = (_a = consoleInstance.authInitializer) === null || _a === void 0 ? void 0 : _a.client) === null || _b === void 0 ? void 0 : _b._settings._authority);
|
|
298
|
+
}
|
|
299
|
+
var console = console_ui_js_1.ConsoleUiInit.getInstance(props.clientId, props.loginRedirectPath, props.logoutRedirectPath, props.devOrgName, authUrl, props.appId);
|
|
300
|
+
console.renderToast(props.elementId, props.toastConfig);
|
|
301
|
+
}, []);
|
|
302
|
+
return (0, jsx_runtime_1.jsx)("div", { id: props.elementId });
|
|
303
|
+
};
|
|
304
|
+
exports.OS1Toast = OS1Toast;
|
|
305
|
+
var OS1Modal = function (props) {
|
|
306
|
+
var consoleInstance = react_1.default.useContext(exports.ConsoleUIContext);
|
|
307
|
+
var _a = (0, react_1.useState)(''), authUrl = _a[0], setAuthUrl = _a[1];
|
|
308
|
+
(0, react_1.useEffect)(function () {
|
|
309
|
+
var _a, _b;
|
|
310
|
+
if (consoleInstance) {
|
|
311
|
+
setAuthUrl((_b = (_a = consoleInstance.authInitializer) === null || _a === void 0 ? void 0 : _a.client) === null || _b === void 0 ? void 0 : _b._settings._authority);
|
|
312
|
+
}
|
|
313
|
+
var console = console_ui_js_1.ConsoleUiInit.getInstance(props.clientId, props.loginRedirectPath, props.logoutRedirectPath, props.devOrgName, authUrl, props.appId);
|
|
314
|
+
console.renderModal('modal-ele', props.modalConfig);
|
|
315
|
+
}, []);
|
|
316
|
+
return (0, jsx_runtime_1.jsx)("div", { id: "modal-ele" });
|
|
317
|
+
};
|
|
318
|
+
exports.OS1Modal = OS1Modal;
|
|
319
|
+
//# sourceMappingURL=index.js.map
|
package/package.json
ADDED
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@os1-platform/console-ui-react",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "React wrapper for console-ui library",
|
|
5
|
+
"main": "dist/commonjs/aaa/index.js",
|
|
6
|
+
"types": "dist/commonjs/types/aaa/index.d.ts",
|
|
7
|
+
"type": "commonjs",
|
|
8
|
+
"files": [
|
|
9
|
+
"tsconfig.json",
|
|
10
|
+
"/src/*"
|
|
11
|
+
],
|
|
12
|
+
"scripts": {
|
|
13
|
+
"test": "echo \"Error: no test specified\" && exit 1",
|
|
14
|
+
"build:css": "postcss src/css/tailwind.css -o public/build/main.css",
|
|
15
|
+
"build": "rm -rf dist && tsc -p .",
|
|
16
|
+
"start": "postcss src/assets/tailwind.css -o src/assets/main.css --watch",
|
|
17
|
+
"watch:css": "postcss src/css/tailwind.css -o public/build/main.css -w",
|
|
18
|
+
"dev": "npx tailwindcss -i ./styles/tailwind.css -o ./styles/output.css --watch"
|
|
19
|
+
},
|
|
20
|
+
"author": "kshitij.sharma@delhivery.com",
|
|
21
|
+
"license": "MIT",
|
|
22
|
+
"devDependencies": {
|
|
23
|
+
"@types/axios": "^0.14.0",
|
|
24
|
+
"@types/react-router-dom": "^5.3.3",
|
|
25
|
+
"autoprefixer": "^10.4.13",
|
|
26
|
+
"tailwindcss": "^1.2.0"
|
|
27
|
+
},
|
|
28
|
+
"dependencies": {
|
|
29
|
+
"@fullhuman/postcss-purgecss": "^5.0.0",
|
|
30
|
+
"@os1-platform/console-ui-js": "^0.1.0",
|
|
31
|
+
"@react-native-community/eslint-config": "^2.0.0",
|
|
32
|
+
"@types/react": "^17.0.37",
|
|
33
|
+
"axios": "^0.21.4",
|
|
34
|
+
"cssnano": "^5.1.15",
|
|
35
|
+
"react": "^18.2.0",
|
|
36
|
+
"react-router-dom": "^6.10.0"
|
|
37
|
+
},
|
|
38
|
+
"eslintConfig": {
|
|
39
|
+
"root": true,
|
|
40
|
+
"extends": [
|
|
41
|
+
"@react-native-community",
|
|
42
|
+
"prettier"
|
|
43
|
+
],
|
|
44
|
+
"rules": {
|
|
45
|
+
"prettier/prettier": [
|
|
46
|
+
"error",
|
|
47
|
+
{
|
|
48
|
+
"quoteProps": "consistent",
|
|
49
|
+
"singleQuote": true,
|
|
50
|
+
"tabWidth": 2,
|
|
51
|
+
"trailingComma": "es5",
|
|
52
|
+
"useTabs": false
|
|
53
|
+
}
|
|
54
|
+
]
|
|
55
|
+
}
|
|
56
|
+
},
|
|
57
|
+
"eslintIgnore": [
|
|
58
|
+
"node_modules/",
|
|
59
|
+
"lib/"
|
|
60
|
+
],
|
|
61
|
+
"prettier": {
|
|
62
|
+
"quoteProps": "consistent",
|
|
63
|
+
"singleQuote": true,
|
|
64
|
+
"tabWidth": 2,
|
|
65
|
+
"trailingComma": "es5",
|
|
66
|
+
"useTabs": false
|
|
67
|
+
}
|
|
68
|
+
}
|
package/readme.md
ADDED
|
@@ -0,0 +1,294 @@
|
|
|
1
|
+
# @os1-platform/console-ui-react
|
|
2
|
+
|
|
3
|
+
## Installation and Usage
|
|
4
|
+
|
|
5
|
+
## How to use?
|
|
6
|
+
|
|
7
|
+
1. Install **console-ui-react** into your project.
|
|
8
|
+
|
|
9
|
+
#### `npm install @os1-platform/console-ui-react`
|
|
10
|
+
|
|
11
|
+
2. Use `OS1Provider` function of the library to use aunthentication and render header and sidebar. Pass function as a prop to your application that has setState method which sets the state of console Ui Instance.
|
|
12
|
+
|
|
13
|
+
```javascript
|
|
14
|
+
import { OS1Provider } from '@os1-platform/console-ui-react';
|
|
15
|
+
|
|
16
|
+
<OS1Provider
|
|
17
|
+
clientId={`sampleClientId`} // This is the clientId that you get after creating an app.
|
|
18
|
+
loginRedirectPath={'/abc'} // path that will be given when someone logins into console ui for the first time
|
|
19
|
+
logoutRedirectPath={'/'} //path that needs to be redirected when someone logouts from your application.
|
|
20
|
+
devOrgName={'orgName'} // this is an optional parameter, need only to be passed when using in development mode.
|
|
21
|
+
appId={'SolutionName-appId'} //initial appId on which you want to land when loading console ui for the first time.
|
|
22
|
+
>
|
|
23
|
+
<Initiate setConsole={handleConsoleInstanceChange} /> //This is your
|
|
24
|
+
component, which is needed to set Instance of Console ui.
|
|
25
|
+
</OS1Provider>;
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
3. Create Any Component that uses `ConsoleUiContext` and sets that as a state to be used by client application.
|
|
29
|
+
|
|
30
|
+
```javascript
|
|
31
|
+
import React from 'react';
|
|
32
|
+
import { ConsoleUIContext } from '@os1-platform/console-ui-react';
|
|
33
|
+
|
|
34
|
+
function Initiate(props) {
|
|
35
|
+
const consoleInstance = React.useContext(ConsoleUIContext);
|
|
36
|
+
if (consoleInstance) {
|
|
37
|
+
props.setConsole(consoleInstance);
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
export default Initiate;
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
4. We can also provide injectable controls to our header and sidebar by passing them as props to OS1Provider.
|
|
45
|
+
|
|
46
|
+
```javascript
|
|
47
|
+
import { OS1Provider } from "@os1-platform/console-ui-react";
|
|
48
|
+
|
|
49
|
+
const controls = [{
|
|
50
|
+
type: "AutoComplete", //Type can be TextBox,TextBoxButton,DropDown, SearchBox, AutoComplete
|
|
51
|
+
width: 100, // width as percentage of maximum width that is assigned to injectable component
|
|
52
|
+
placeholder: "Search Items", // placeHolder text
|
|
53
|
+
id: "AutoComplete1", //Unique Id which distinguish it with other injectable controls.
|
|
54
|
+
float: "left", // Option to align items left or right
|
|
55
|
+
functionBoundOption: autoComplete(), // Function that return value as an array of object in the form of [{ value: string, text: string }]
|
|
56
|
+
}]
|
|
57
|
+
<OS1Provider clientId={`sampleClientId`} loginRedirectPath={"/abc"} logoutRedirectPath={"/"} devOrgName={"orgName"} controls ={controls} appId={'SolutionName-appId'}>
|
|
58
|
+
<Initiate setConsole={handleConsoleInstanceChange} />
|
|
59
|
+
</OS1Provider>
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
NOTE: There can not be more than 3 injectable controls and each injectable control should be given a unique id.
|
|
63
|
+
|
|
64
|
+
5. Use the Toast function to render toast component in your webpage.
|
|
65
|
+
For example:
|
|
66
|
+
|
|
67
|
+
```javascript
|
|
68
|
+
const toastConfig = {
|
|
69
|
+
bgColor: "yellow", // background color of the toast [green,red,yellow,black,white]
|
|
70
|
+
message: "Operation Successful", // message that will be shown inside the toast [128 character limit]
|
|
71
|
+
timeout: 10, // time in seconds after which toast will disappear
|
|
72
|
+
icon: "error", // icon that will be appearing before the message [info,error,warning,success,failure,none]
|
|
73
|
+
closeButton: true, // denotes whether the close button will be present on the right of the toast
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
<OS1Toast clientId={"sampleClientId"} loginRedirectPath={"/xyz"} logoutRedirectPath={"/"} devOrgName={"orgName"} appId={'sampleAppId'} elementId={"toastElement"} toastConfig={toastConfig} />
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
NOTE: Each toast element that is to be rendered on the page should be given a unique elementId.
|
|
80
|
+
|
|
81
|
+
6. Use the Modal function to render a modal component in your webpage.
|
|
82
|
+
For example:
|
|
83
|
+
|
|
84
|
+
```javascript
|
|
85
|
+
const modalConfig = {
|
|
86
|
+
title: 'Deactivate', // Title of the modal [96 characters limit]
|
|
87
|
+
message: 'Do you want to continue?', // message that will be appearing on the modal
|
|
88
|
+
icon: 'info', // icon that will be appearing along with the message [info,error,warning,success,failure,none]
|
|
89
|
+
buttons: [
|
|
90
|
+
// maximum two buttons allowed
|
|
91
|
+
{
|
|
92
|
+
id: 'button-element-1', // unique id of the button
|
|
93
|
+
backgroundColor: 'green', // background color of the button
|
|
94
|
+
text: 'Cancel', // text appearing on the button
|
|
95
|
+
event: 'upEvent', // unique name of the custom event that will be triggered on click
|
|
96
|
+
},
|
|
97
|
+
],
|
|
98
|
+
};
|
|
99
|
+
<OS1Modal
|
|
100
|
+
clientId={'sampleClientId'}
|
|
101
|
+
loginRedirectPath={'/abc'}
|
|
102
|
+
logoutRedirectPath={'/'}
|
|
103
|
+
devOrgName={'orgNme'}
|
|
104
|
+
appId={'sampleAppId'}
|
|
105
|
+
elementId={'modalElement'}
|
|
106
|
+
modalConfig={modalConfig}
|
|
107
|
+
/>;
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
Note:- Listen to event when button is clicked, `event.details` will contain the modal element Id.
|
|
111
|
+
|
|
112
|
+
7. Use state variable of `ConsoleUIContext` context to listen to events emitted by injectable controls. This instance is usually passed as a prop to apps.
|
|
113
|
+
For example:
|
|
114
|
+
|
|
115
|
+
```javascript
|
|
116
|
+
const { consoleInstance } = props;
|
|
117
|
+
if (consoleInstance) {
|
|
118
|
+
consoleInstance
|
|
119
|
+
.eventBus()
|
|
120
|
+
.on(consoleInstance.events().OnChangeEvent, (e) =>
|
|
121
|
+
window.console.log(e)
|
|
122
|
+
);
|
|
123
|
+
}
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
Note:- We are exposing OnChangeEvent, OnBlurEvent, OnScrollEvent, OnClickEvent, OnFocusEvent for injectableId's.
|
|
127
|
+
|
|
128
|
+
8. Use `OS1HttpClient` API to create a client for network requests and pass `authInitializer` property of ConsoleUiContext as a constructor parameter.
|
|
129
|
+
|
|
130
|
+
```javascript
|
|
131
|
+
import { OS1HttpClient } from '@os1-platform/console-ui-react';
|
|
132
|
+
|
|
133
|
+
class NetworkClient {
|
|
134
|
+
public readonly instance: any;
|
|
135
|
+
|
|
136
|
+
constructor(`instanceName`) {
|
|
137
|
+
this.instance = OS1HttpClient.createClient({
|
|
138
|
+
baseURL: `https://abc.domain.com`,
|
|
139
|
+
},`instanceName`);
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
```
|
|
143
|
+
|
|
144
|
+
9. Following headers are automatically configured to requests originating from the `NetworkClient` adding Access token(`x-coreos-access`) or Tenant id(`x-coreos-tid`) or User info(`x-coreos-userinfo`) or Auth token(`x-coreos-auth`) headers to the actual request.
|
|
145
|
+
|
|
146
|
+
- `withAccess`
|
|
147
|
+
- `withTid`
|
|
148
|
+
- `withUserInfo`
|
|
149
|
+
- `withAuth`
|
|
150
|
+
|
|
151
|
+
Note:
|
|
152
|
+
|
|
153
|
+
1. By default all these headers are true, pass value against these headers as `false` to remove from request.
|
|
154
|
+
2. Access token is verified and regenerated (if expired), every time an api request is made.
|
|
155
|
+
3. `x-coreos-userinfo` contains the userId.
|
|
156
|
+
4. `x-coreos-auth` contains the id_token.
|
|
157
|
+
|
|
158
|
+
```javascript
|
|
159
|
+
import NetworkClient from "./networkClient";
|
|
160
|
+
|
|
161
|
+
const handleClick = () => {
|
|
162
|
+
//here consoleInstance is the state variable of ConsoleUIContext;
|
|
163
|
+
if (consoleInstance) {
|
|
164
|
+
const client1 = new NetworkClient(consoleInstance.authInitializer); //consoleInstance.authInitializer is an instance of AAA class that we get from ConsoleUi Context
|
|
165
|
+
const reqHeaders: any = {
|
|
166
|
+
withAccess: false,
|
|
167
|
+
withTid: false,
|
|
168
|
+
withUserInfo: false,
|
|
169
|
+
withAuth: false,
|
|
170
|
+
};
|
|
171
|
+
client1.users.('45', reqHeaders).catch(function (err) {
|
|
172
|
+
console.log('errr', err);
|
|
173
|
+
console.log('error', JSON.stringify(err));
|
|
174
|
+
});
|
|
175
|
+
};
|
|
176
|
+
};
|
|
177
|
+
```
|
|
178
|
+
|
|
179
|
+
10. Use Contact Us page, if you want to query about any application.
|
|
180
|
+
|
|
181
|
+
- We provide text area to describe the issue in details.
|
|
182
|
+
- We provide option to upload screenshots if any, that may help to understand the issue.
|
|
183
|
+
`We will get the query along with your details and we can contact you.`
|
|
184
|
+
|
|
185
|
+
11. Option to change the timezone of the application. At initital load, time zone will be tenant specific but user can change the time zone according to his choice and it will be stored in his browser's local Storage.
|
|
186
|
+
|
|
187
|
+
12. Exposed `convertTime` function that converts time of the user's application in their desired format and `currentTimeZone` function that gives user current timezone that is stored in the browser.
|
|
188
|
+
|
|
189
|
+
```javascript
|
|
190
|
+
const { consoleInstance } = props;
|
|
191
|
+
if (consoleInstance) {
|
|
192
|
+
console.log(
|
|
193
|
+
consoleInstance.convertTime('2014-06-01 12:00', 'MM-DD-YYYY HH:mm:ss')
|
|
194
|
+
); // In this 2nd parameter i.e. format in which we want to convert time is optional.
|
|
195
|
+
console.log(consoleInstance.currentTimeZone());
|
|
196
|
+
}
|
|
197
|
+
```
|
|
198
|
+
|
|
199
|
+
13. We have provided that defines how user navigates on Routing of tabs. Users can choose, how they want to navigate for particular app i.e. they want to open the app on new tab or the current tab. This is done by going into user preference in profile dropdown and select the choice in Set App Redirect Behaviour.
|
|
200
|
+
|
|
201
|
+
14. When user clicks on subroutes, then event naming `changeRoutes` is emitted, which contains the details of subMenu apps and their parent app details like appId, appUrl and appName.
|
|
202
|
+
|
|
203
|
+
15. If nothing is selected then, when user clicks on app for the first time, it asks how we want to redirect the app.
|
|
204
|
+
|
|
205
|
+
16. Link to acceess [example app](https://github.com/FoxtrotPlatform/console-ui-sdk/tree/development/example)
|
|
206
|
+
|
|
207
|
+
## Configuration for Injectable Controls offered by the Library
|
|
208
|
+
|
|
209
|
+
##### TextBox:-
|
|
210
|
+
|
|
211
|
+
- To use textbox in console ui, we provide following configuration:-
|
|
212
|
+
|
|
213
|
+
```javascript
|
|
214
|
+
{
|
|
215
|
+
type: "TextBox", // type of injectable control
|
|
216
|
+
width: 100, // maximum width in percentage that can be given
|
|
217
|
+
placeholder: "Search Package", // placeholder text
|
|
218
|
+
float: "left", // aligning the injectable control in left or right direction
|
|
219
|
+
id: "TextBox1" // unique id that can be given to injectable control
|
|
220
|
+
attributes: {
|
|
221
|
+
maxlength: “50”;
|
|
222
|
+
|
|
223
|
+
} // this is optional attributes parameter that contains object which defines if any attribute needs to be set to injectable controls
|
|
224
|
+
}
|
|
225
|
+
```
|
|
226
|
+
|
|
227
|
+
##### TextBoxButton:-
|
|
228
|
+
|
|
229
|
+
- To use textbox with button in console ui, we provide following configuration:-
|
|
230
|
+
|
|
231
|
+
```javascript
|
|
232
|
+
{
|
|
233
|
+
type: "TextBoxButton", // type of injectable control
|
|
234
|
+
width: 100, // maximum width in percentage that can be given
|
|
235
|
+
placeholder: "Search Package", // placeholder text
|
|
236
|
+
float: "left", // aligning the injectable control in left or right direction
|
|
237
|
+
id: "TextBoxButton1" // unique id that can be given to injectable control
|
|
238
|
+
attributes: {
|
|
239
|
+
maxlength: “50”;
|
|
240
|
+
} // this is optional attributes parameter that contains object which defines if any attribute needs to be set to injectable controls
|
|
241
|
+
button: true, // this by default set to false,
|
|
242
|
+
buttonText: “Search”, // this field needs to be present when button is true.
|
|
243
|
+
buttonColor: “red”, // this field needs to be present when button is true.
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
```
|
|
247
|
+
|
|
248
|
+
##### Search Box:-
|
|
249
|
+
|
|
250
|
+
- To use SearchBox with Lens Icon in console ui, we provide following configuration:-
|
|
251
|
+
|
|
252
|
+
```javascript
|
|
253
|
+
{
|
|
254
|
+
type: "SearchBox", // type of injectable control
|
|
255
|
+
width: 100, // maximum width in percentage that can be given
|
|
256
|
+
placeholder: "Search Package", // placeholder text
|
|
257
|
+
float: "right", // aligning the injectable control in left or right direction
|
|
258
|
+
id: "SearchBox1" // unique id that can be given to injectable control
|
|
259
|
+
attributes: { maxlength: “50”; } // this is optional attributes parameter that contains object which defines if any attribute needs to be set to injectable controls
|
|
260
|
+
lensIcon: true // this field is optional, if set to true then lensIcon will be shown.
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
```
|
|
264
|
+
|
|
265
|
+
##### AutoComplete:-
|
|
266
|
+
|
|
267
|
+
- To use AutoComplete in console ui, we provide following configuration:-
|
|
268
|
+
|
|
269
|
+
```javascript
|
|
270
|
+
{
|
|
271
|
+
type: "AutoComplete", // type of injectable control
|
|
272
|
+
width: 100, // maximum width in percentage that can be given
|
|
273
|
+
placeholder: "Search Package", // placeholder text
|
|
274
|
+
float: "right", // aligning the injectable control in left or right direction
|
|
275
|
+
id: "AutcoComplete1" // unique id that can be given to injectable control
|
|
276
|
+
functionBoundOption: autoComplete(), // This field can be a function which return array of Objects or normal array of objects in the form of [{ value: string, text: string }],
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
```
|
|
280
|
+
|
|
281
|
+
##### DropDown:-
|
|
282
|
+
|
|
283
|
+
- To use DropDown in console ui , we provide following configuration:-
|
|
284
|
+
|
|
285
|
+
```javascript
|
|
286
|
+
{
|
|
287
|
+
type: "DropDown", // type of injectable control
|
|
288
|
+
width: 100, // maximum width in percentage that can be given
|
|
289
|
+
placeholder: "Search Package", // placeholder text
|
|
290
|
+
float: "right", // aligning the injectable control in left or right direction
|
|
291
|
+
id: "DropDown1" // unique id that can be given to injectable control
|
|
292
|
+
functionBoundOption: [{ value: "1", text: "Mobiles" },{ value:"2", text: "Laptops" }], // This field can be a function which return array of Objects or normal array of objects in the form of [{ value: string, text: string }],
|
|
293
|
+
}
|
|
294
|
+
```
|
|
@@ -0,0 +1,318 @@
|
|
|
1
|
+
import { AAA, ConsoleUiInit, HttpClient } from '@os1-platform/console-ui-js';
|
|
2
|
+
import React, { useEffect, useRef, useState } from 'react';
|
|
3
|
+
import { ModalProps } from '../components/modal/interface';
|
|
4
|
+
import { ToastProps } from '../components/toast/interface';
|
|
5
|
+
import axios from 'axios';
|
|
6
|
+
|
|
7
|
+
export const AuthContext = React.createContext<any | undefined>(undefined);
|
|
8
|
+
export const ConsoleUIContext = React.createContext<any>(undefined);
|
|
9
|
+
|
|
10
|
+
const HeaderAndSideBar = (props: any) => {
|
|
11
|
+
const [consoleInstance, setConsoleInstance] = useState<any>(null);
|
|
12
|
+
|
|
13
|
+
useEffect(() => {
|
|
14
|
+
if (!props.isLoading) {
|
|
15
|
+
const console = ConsoleUiInit.getInstance(
|
|
16
|
+
props.clientId,
|
|
17
|
+
props.loginRedirectPath,
|
|
18
|
+
props.logoutRedirectPath,
|
|
19
|
+
props.devOrgName,
|
|
20
|
+
props.authurl,
|
|
21
|
+
props.appId,
|
|
22
|
+
props.userManager
|
|
23
|
+
);
|
|
24
|
+
|
|
25
|
+
setConsoleInstance(console);
|
|
26
|
+
console.renderHeaderAndSidebar('headerAndSidebar', props.controls);
|
|
27
|
+
}
|
|
28
|
+
}, [props.isLoading]);
|
|
29
|
+
|
|
30
|
+
if (props.isLoading) {
|
|
31
|
+
if (props.loader) {
|
|
32
|
+
return props.loader;
|
|
33
|
+
} else {
|
|
34
|
+
const keyframes = `
|
|
35
|
+
@-webkit-keyframes spin {
|
|
36
|
+
0% {
|
|
37
|
+
-webkit-transform: rotate(0deg);
|
|
38
|
+
}
|
|
39
|
+
100% {
|
|
40
|
+
-webkit-transform: rotate(360deg);
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
`;
|
|
44
|
+
const styleSheets = Array.from(document.styleSheets).filter(
|
|
45
|
+
(styleSheet) =>
|
|
46
|
+
!styleSheet.href || styleSheet.href.startsWith(window.location.origin)
|
|
47
|
+
);
|
|
48
|
+
for (let style of styleSheets) {
|
|
49
|
+
if (style instanceof CSSStyleSheet && style.cssRules) {
|
|
50
|
+
style.insertRule(keyframes, style.cssRules.length);
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
const loaderStyle = () => ({
|
|
54
|
+
marginTop: '50vh',
|
|
55
|
+
marginLeft: '50vw',
|
|
56
|
+
border: '12px solid #F3F3F3',
|
|
57
|
+
borderRadius: '50%',
|
|
58
|
+
borderTop: '12px solid grey',
|
|
59
|
+
width: '40px',
|
|
60
|
+
height: '40px',
|
|
61
|
+
animationName: 'spin',
|
|
62
|
+
animationDuration: '2s',
|
|
63
|
+
animationTimingFunction: 'linear',
|
|
64
|
+
animationIterationCount: 'infinite',
|
|
65
|
+
});
|
|
66
|
+
return <div style={loaderStyle()}></div>;
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
//console.log(consoleInstance, props);
|
|
70
|
+
return (
|
|
71
|
+
<ConsoleUIContext.Provider value={consoleInstance}>
|
|
72
|
+
<div id="headerAndSidebar">{props.children}</div>
|
|
73
|
+
</ConsoleUIContext.Provider>
|
|
74
|
+
);
|
|
75
|
+
};
|
|
76
|
+
|
|
77
|
+
interface TenantDTO {
|
|
78
|
+
tenantId: string;
|
|
79
|
+
tenantStatus: string;
|
|
80
|
+
tenantDns: string;
|
|
81
|
+
stackId: string;
|
|
82
|
+
stackName: string;
|
|
83
|
+
organizationShortName: string;
|
|
84
|
+
organizationBaseDomain: string;
|
|
85
|
+
stackAuthUrl: string;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
const getCleanedDomain = (domain: string) => {
|
|
89
|
+
const cleanedDomain = String(domain);
|
|
90
|
+
const splitHost = cleanedDomain.split('.');
|
|
91
|
+
const org = splitHost[0] || '';
|
|
92
|
+
const cleanedOrg = org.replace('-cdev', '');
|
|
93
|
+
const base = splitHost.join('.');
|
|
94
|
+
return { orgShortName: cleanedOrg, baseDomain: base };
|
|
95
|
+
};
|
|
96
|
+
|
|
97
|
+
const getTenantFromDevPortal = async (
|
|
98
|
+
orgShortName: any
|
|
99
|
+
): Promise<TenantDTO> => {
|
|
100
|
+
const url = `https://api.getos1.com/app/core-api/tenant?orgShortName=${orgShortName}`;
|
|
101
|
+
const response = await axios.get(url);
|
|
102
|
+
return response.data.data;
|
|
103
|
+
};
|
|
104
|
+
|
|
105
|
+
const getTenantId = (devOrgNameArg: string | null = null): string => {
|
|
106
|
+
let devOrgName = devOrgNameArg;
|
|
107
|
+
//if (!devOrgNameArg) devOrgName = getAuthConfig().devOrgName;
|
|
108
|
+
|
|
109
|
+
const hostname = window.location.hostname || null;
|
|
110
|
+
|
|
111
|
+
return hostname
|
|
112
|
+
? (hostname.split('.')[0] == 'developer' ||
|
|
113
|
+
hostname.split('.')[0] == 'developer2' ||
|
|
114
|
+
hostname.split('.')[0].includes('-cdev')) &&
|
|
115
|
+
devOrgName
|
|
116
|
+
? devOrgName
|
|
117
|
+
: hostname.split('.')[0]
|
|
118
|
+
: '';
|
|
119
|
+
};
|
|
120
|
+
|
|
121
|
+
const getKeyCloakAuthority = async (domain: string, devOrgName: string) => {
|
|
122
|
+
let orgName: string = '';
|
|
123
|
+
let baseDomainName: string = '';
|
|
124
|
+
|
|
125
|
+
if (devOrgName != undefined) {
|
|
126
|
+
orgName = devOrgName;
|
|
127
|
+
baseDomainName = domain.substring(domain.indexOf('.'));
|
|
128
|
+
} else {
|
|
129
|
+
const { orgShortName, baseDomain } = getCleanedDomain(domain);
|
|
130
|
+
|
|
131
|
+
orgName = orgShortName;
|
|
132
|
+
baseDomainName = baseDomain;
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
if (baseDomainName.includes('os1')) {
|
|
136
|
+
const tenant = await getTenantFromDevPortal(orgName);
|
|
137
|
+
|
|
138
|
+
return `${tenant.stackAuthUrl}/auth/realms/${tenant.tenantId}`;
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
const tenantId = getTenantId(orgName);
|
|
142
|
+
//console.log(tenantId);
|
|
143
|
+
return `https://keycloak${baseDomainName}/auth/realms/${tenantId}`;
|
|
144
|
+
};
|
|
145
|
+
|
|
146
|
+
const OS1Provider = (props: any) => {
|
|
147
|
+
const [authUrl, setAuthUrl] = useState('');
|
|
148
|
+
// const [tenantDns, setTenantDns] = useState('');
|
|
149
|
+
// let isMountedRef = useRef<boolean>(false);
|
|
150
|
+
|
|
151
|
+
let authUrls = '';
|
|
152
|
+
useEffect(() => {
|
|
153
|
+
(async function () {
|
|
154
|
+
authUrls = await getKeyCloakAuthority(
|
|
155
|
+
window.location.hostname,
|
|
156
|
+
props.devOrgName
|
|
157
|
+
);
|
|
158
|
+
setAuthUrl(authUrls);
|
|
159
|
+
})();
|
|
160
|
+
}, []);
|
|
161
|
+
|
|
162
|
+
return (
|
|
163
|
+
<OS1Provider2
|
|
164
|
+
clientId={props.clientId}
|
|
165
|
+
loginRedirectPath={props.loginRedirectPath}
|
|
166
|
+
logoutRedirectPath={props.logoutRedirectPath}
|
|
167
|
+
devOrgName={props.devOrgName}
|
|
168
|
+
appId={props.appId}
|
|
169
|
+
controls={props.controls}
|
|
170
|
+
authUrl={authUrl}
|
|
171
|
+
props={...props}
|
|
172
|
+
/>
|
|
173
|
+
);
|
|
174
|
+
};
|
|
175
|
+
const OS1Provider2 = (props: any) => {
|
|
176
|
+
//console.log(props);
|
|
177
|
+
const userManager = new AAA(
|
|
178
|
+
props.clientId,
|
|
179
|
+
props.loginRedirectPath,
|
|
180
|
+
props.logoutRedirectPath,
|
|
181
|
+
props.devOrgName,
|
|
182
|
+
props.authUrl
|
|
183
|
+
);
|
|
184
|
+
const value = '';
|
|
185
|
+
//console.log('userManager', userManager);
|
|
186
|
+
const [isLoading, setIsLoading] = useState(true);
|
|
187
|
+
let isMountedRef = useRef<boolean>(false);
|
|
188
|
+
|
|
189
|
+
useEffect(() => {
|
|
190
|
+
// Store current isMounted since this could change while awaiting async operations below
|
|
191
|
+
isMountedRef.current = true;
|
|
192
|
+
(async () => {
|
|
193
|
+
let user = undefined;
|
|
194
|
+
try {
|
|
195
|
+
user = await userManager!.getUserInfo();
|
|
196
|
+
} catch (error: any) {
|
|
197
|
+
window.console.log('Error: ', error);
|
|
198
|
+
}
|
|
199
|
+
/**
|
|
200
|
+
* Check if the user is returning back from OIDC.
|
|
201
|
+
*/
|
|
202
|
+
if (hasCodeInUrl(window.location)) {
|
|
203
|
+
await userManager?.logincallback();
|
|
204
|
+
cleanBrowserUrl();
|
|
205
|
+
setIsLoading(false);
|
|
206
|
+
return;
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
if (!(await userManager?.isAuthenticated())) {
|
|
210
|
+
userManager?.login();
|
|
211
|
+
} else if (isMountedRef.current) {
|
|
212
|
+
setIsLoading(false);
|
|
213
|
+
}
|
|
214
|
+
})();
|
|
215
|
+
|
|
216
|
+
return () => {
|
|
217
|
+
isMountedRef.current = false;
|
|
218
|
+
};
|
|
219
|
+
}, [window.location, userManager]);
|
|
220
|
+
|
|
221
|
+
return (
|
|
222
|
+
<AuthContext.Provider value={value}>
|
|
223
|
+
<HeaderAndSideBar
|
|
224
|
+
userManager={userManager}
|
|
225
|
+
isLoading={isLoading}
|
|
226
|
+
loader={props.loader}
|
|
227
|
+
devOrgName={props.devOrgName}
|
|
228
|
+
controls={props.controls}
|
|
229
|
+
appId={props.appId}
|
|
230
|
+
authUrl={props.authUrl}
|
|
231
|
+
>
|
|
232
|
+
{props.props.children}
|
|
233
|
+
</HeaderAndSideBar>
|
|
234
|
+
</AuthContext.Provider>
|
|
235
|
+
);
|
|
236
|
+
};
|
|
237
|
+
const hasCodeInUrl = (location: Location): boolean => {
|
|
238
|
+
const searchParams = new URLSearchParams(location.search);
|
|
239
|
+
const hashParams = new URLSearchParams(location.hash.replace('#', '?'));
|
|
240
|
+
return Boolean(
|
|
241
|
+
searchParams.get('code') ||
|
|
242
|
+
searchParams.get('id_token') ||
|
|
243
|
+
searchParams.get('session_state') ||
|
|
244
|
+
searchParams.get('state') ||
|
|
245
|
+
hashParams.get('code') ||
|
|
246
|
+
hashParams.get('id_token') ||
|
|
247
|
+
hashParams.get('session_state') ||
|
|
248
|
+
hashParams.get('state')
|
|
249
|
+
);
|
|
250
|
+
};
|
|
251
|
+
|
|
252
|
+
const cleanBrowserUrl = () => {
|
|
253
|
+
const search = window.location.search;
|
|
254
|
+
|
|
255
|
+
if (
|
|
256
|
+
search &&
|
|
257
|
+
(search.includes('session_state=') ||
|
|
258
|
+
search.includes('state=') ||
|
|
259
|
+
search.includes('code='))
|
|
260
|
+
) {
|
|
261
|
+
/*
|
|
262
|
+
* Use replaceState to redirect the user away and remove the querystring parameters
|
|
263
|
+
*/
|
|
264
|
+
window.history.replaceState(
|
|
265
|
+
{},
|
|
266
|
+
document.title,
|
|
267
|
+
window.location.href.split('?')[0]
|
|
268
|
+
);
|
|
269
|
+
}
|
|
270
|
+
};
|
|
271
|
+
|
|
272
|
+
// export { Toast, Modal };
|
|
273
|
+
|
|
274
|
+
const OS1Toast = (props: ToastProps) => {
|
|
275
|
+
const consoleInstance = React.useContext(ConsoleUIContext);
|
|
276
|
+
const [authUrl, setAuthUrl] = useState('');
|
|
277
|
+
|
|
278
|
+
useEffect(() => {
|
|
279
|
+
if (consoleInstance) {
|
|
280
|
+
setAuthUrl(consoleInstance.authInitializer?.client?._settings._authority);
|
|
281
|
+
}
|
|
282
|
+
const console = ConsoleUiInit.getInstance(
|
|
283
|
+
props.clientId,
|
|
284
|
+
props.loginRedirectPath,
|
|
285
|
+
props.logoutRedirectPath,
|
|
286
|
+
props.devOrgName,
|
|
287
|
+
authUrl,
|
|
288
|
+
props.appId
|
|
289
|
+
);
|
|
290
|
+
console.renderToast(props.elementId, props.toastConfig);
|
|
291
|
+
}, []);
|
|
292
|
+
|
|
293
|
+
return <div id={props.elementId}></div>;
|
|
294
|
+
};
|
|
295
|
+
|
|
296
|
+
const OS1Modal = (props: ModalProps) => {
|
|
297
|
+
const consoleInstance = React.useContext(ConsoleUIContext);
|
|
298
|
+
const [authUrl, setAuthUrl] = useState('');
|
|
299
|
+
|
|
300
|
+
useEffect(() => {
|
|
301
|
+
if (consoleInstance) {
|
|
302
|
+
setAuthUrl(consoleInstance.authInitializer?.client?._settings._authority);
|
|
303
|
+
}
|
|
304
|
+
const console = ConsoleUiInit.getInstance(
|
|
305
|
+
props.clientId,
|
|
306
|
+
props.loginRedirectPath,
|
|
307
|
+
props.logoutRedirectPath,
|
|
308
|
+
props.devOrgName,
|
|
309
|
+
authUrl,
|
|
310
|
+
props.appId
|
|
311
|
+
);
|
|
312
|
+
console.renderModal('modal-ele', props.modalConfig);
|
|
313
|
+
}, []);
|
|
314
|
+
|
|
315
|
+
return <div id="modal-ele"></div>;
|
|
316
|
+
};
|
|
317
|
+
|
|
318
|
+
export { OS1Provider, OS1Toast, OS1Modal, HttpClient as OS1HttpClient };
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
// import { ConsoleUiInit } from '@foxtrotplatform/console-ui-sdk';
|
|
2
|
+
// import { useEffect } from 'react';
|
|
3
|
+
// import { ModalProps } from './interface';
|
|
4
|
+
|
|
5
|
+
// export const OS1Modal = (props: ModalProps) => {
|
|
6
|
+
// // const console = ConsoleUiInit.getInstance(
|
|
7
|
+
// // props.clientId,
|
|
8
|
+
// // props.loginRedirectPath,
|
|
9
|
+
// // props.logoutRedirectPath,
|
|
10
|
+
// // props.devOrgName
|
|
11
|
+
// // );
|
|
12
|
+
|
|
13
|
+
// // useEffect(() => {
|
|
14
|
+
// // console.renderModal('modal-ele', props.modalConfig);
|
|
15
|
+
// // }, []);
|
|
16
|
+
|
|
17
|
+
// return <div id="modal-ele"></div>;
|
|
18
|
+
// };
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
export interface ModalConfig {
|
|
2
|
+
bgColor: string,
|
|
3
|
+
title: string,
|
|
4
|
+
message: string,
|
|
5
|
+
icon: string,
|
|
6
|
+
buttons: Button[]
|
|
7
|
+
id?: string,
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
export interface Button {
|
|
11
|
+
id: string,
|
|
12
|
+
backgroundColor: string,
|
|
13
|
+
text: string,
|
|
14
|
+
event: string,
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export interface ModalProps {
|
|
18
|
+
clientId: string,
|
|
19
|
+
loginRedirectPath: string,
|
|
20
|
+
logoutRedirectPath: string,
|
|
21
|
+
devOrgName: string,
|
|
22
|
+
appId: string,
|
|
23
|
+
elementId: string,
|
|
24
|
+
modalConfig: ModalConfig;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
export interface RouterProps {
|
|
28
|
+
component: string,
|
|
29
|
+
path: string,
|
|
30
|
+
exact: boolean,
|
|
31
|
+
props?: {} | undefined
|
|
32
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
// import { ConsoleUiInit } from '@foxtrotplatform/console-ui-sdk';
|
|
2
|
+
// import { useEffect } from 'react';
|
|
3
|
+
// import { ToastProps, ToastConfig } from './interface';
|
|
4
|
+
|
|
5
|
+
// export const OS1Toast = (props: ToastProps) => {
|
|
6
|
+
// // const console = ConsoleUiInit.getInstance(
|
|
7
|
+
// // props.clientId,
|
|
8
|
+
// // props.loginRedirectPath,
|
|
9
|
+
// // props.logoutRedirectPath,
|
|
10
|
+
// // props.devOrgName
|
|
11
|
+
// // );
|
|
12
|
+
|
|
13
|
+
// // useEffect(() => {
|
|
14
|
+
// // console.renderToast(props.elementId, props.toastConfig);
|
|
15
|
+
// // // console.renderHeaderAndSidebar(document.getElementById('headerAndSidebar'));
|
|
16
|
+
// // }, []);
|
|
17
|
+
|
|
18
|
+
// return <div id={props.elementId}></div>;
|
|
19
|
+
// };
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
export interface ToastConfig {
|
|
2
|
+
bgColor: string,
|
|
3
|
+
message: string,
|
|
4
|
+
timeout?: number,
|
|
5
|
+
icon: string,
|
|
6
|
+
closeButton: boolean,
|
|
7
|
+
id?: string,
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
export interface ToastProps {
|
|
11
|
+
clientId: string,
|
|
12
|
+
loginRedirectPath: string,
|
|
13
|
+
logoutRedirectPath: string,
|
|
14
|
+
devOrgName: string,
|
|
15
|
+
authurl: string,
|
|
16
|
+
appId: string,
|
|
17
|
+
userManager: string,
|
|
18
|
+
elementId: string,
|
|
19
|
+
toastConfig: ToastConfig;
|
|
20
|
+
}
|
package/src/index.ts
ADDED
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
// import {
|
|
2
|
+
// AAA,
|
|
3
|
+
// ConsoleUiInit,
|
|
4
|
+
// HttpClient as client,
|
|
5
|
+
// } from '@foxtrotplatform/console-ui-sdk';
|
|
6
|
+
// // import { SideNav } from '../components/side-nav';
|
|
7
|
+
// import * as React from 'react';
|
|
8
|
+
// import { useEffect, useLayoutEffect, useState } from 'react';
|
|
9
|
+
// import { AAAElements } from './interface';
|
|
10
|
+
|
|
11
|
+
// // export class ReactConsoleUiInit {
|
|
12
|
+
// // public authInitializer: any;
|
|
13
|
+
// // public console: any;
|
|
14
|
+
// // public tenantId: string;
|
|
15
|
+
// // constructor(clientId: string,
|
|
16
|
+
// // loginRedirectPath: string,
|
|
17
|
+
// // logoutRedirectPath: string,
|
|
18
|
+
// // devOrgName: string = '') {
|
|
19
|
+
|
|
20
|
+
// // this.console = new ConsoleUiInit(
|
|
21
|
+
// // clientId,
|
|
22
|
+
// // loginRedirectPath,
|
|
23
|
+
// // logoutRedirectPath,
|
|
24
|
+
// // devOrgName,
|
|
25
|
+
|
|
26
|
+
// // );
|
|
27
|
+
|
|
28
|
+
// // this.tenantId = devOrgName;
|
|
29
|
+
// // }
|
|
30
|
+
|
|
31
|
+
// // HeaderAndSideBar = () => {
|
|
32
|
+
|
|
33
|
+
// // return (
|
|
34
|
+
// // <div id='app'>
|
|
35
|
+
// // Hello
|
|
36
|
+
// // </div>
|
|
37
|
+
// // )
|
|
38
|
+
// // }
|
|
39
|
+
|
|
40
|
+
// // // headerAndSideBar() {
|
|
41
|
+
// // // const headerAndSideBar = new SideNav(this.tenantId, this.authInitializer);
|
|
42
|
+
// // // return headerAndSideBar.render();
|
|
43
|
+
// // // }
|
|
44
|
+
// // }
|
|
45
|
+
// let count: number = 0;
|
|
46
|
+
|
|
47
|
+
// export const AAAInstantiate = (aaaElements: AAAElements) => {
|
|
48
|
+
// const aaa: any = new AAA(
|
|
49
|
+
// aaaElements.clientId,
|
|
50
|
+
// aaaElements.loginRedirectPath,
|
|
51
|
+
// aaaElements.logoutRedirectPath,
|
|
52
|
+
// aaaElements.devOrgName
|
|
53
|
+
// );
|
|
54
|
+
// return aaa;
|
|
55
|
+
// };
|
|
56
|
+
|
|
57
|
+
// export const HeaderAndSideBar = (props: any) => {
|
|
58
|
+
// count++;
|
|
59
|
+
// window.console.log('Count: ', count);
|
|
60
|
+
|
|
61
|
+
// // const [aaaInstance, setAaaInstance] = useState<any>(null);
|
|
62
|
+
// const [consoleInstance, setConsoleInstance] = useState<any>(null);
|
|
63
|
+
// // const [userSignedIn, setUserSignedInstance] = useState<boolean>(true);
|
|
64
|
+
// // const aaa: any = new AAA(
|
|
65
|
+
// // props.clientId,
|
|
66
|
+
// // props.loginRedirectPath,
|
|
67
|
+
// // props.logoutRedirectPath,
|
|
68
|
+
// // props.devOrgName,
|
|
69
|
+
// // );
|
|
70
|
+
// // setAaaInstance(aaa);
|
|
71
|
+
// useEffect(() => {
|
|
72
|
+
// window.console.log('aaaInstance.client: ', props.aaaInstance.client);
|
|
73
|
+
// if (hasCodeInUrl(window.location)) {
|
|
74
|
+
// return;
|
|
75
|
+
// }
|
|
76
|
+
// if (props.aaaInstance.client) {
|
|
77
|
+
// // const aaa: any = new AAA(
|
|
78
|
+
// // props.clientId,
|
|
79
|
+
// // props.loginRedirectPath,
|
|
80
|
+
// // props.logoutRedirectPath,
|
|
81
|
+
// // props.devOrgName,
|
|
82
|
+
// // );
|
|
83
|
+
|
|
84
|
+
// (async () => {
|
|
85
|
+
// await props.aaaInstance.login();
|
|
86
|
+
// // setAaaInstance(aaa);
|
|
87
|
+
// // setUserSignedInstance(false);
|
|
88
|
+
// })();
|
|
89
|
+
// }
|
|
90
|
+
// }, []);
|
|
91
|
+
|
|
92
|
+
// // useEffect(() => {
|
|
93
|
+
// // window.console.log("AAAINSTANCE: ", props.aaaInstance);
|
|
94
|
+
// // const console: any = new ConsoleUiInit(
|
|
95
|
+
// // props.clientId,
|
|
96
|
+
// // props.loginRedirectPath,
|
|
97
|
+
// // props.logoutRedirectPath,
|
|
98
|
+
// // props.devOrgName,
|
|
99
|
+
// // props.aaaInstance,
|
|
100
|
+
// // );
|
|
101
|
+
// // setConsoleInstance(console);
|
|
102
|
+
|
|
103
|
+
// // }, [props.aaaInstance]);
|
|
104
|
+
|
|
105
|
+
// // useEffect(() => {
|
|
106
|
+
// // window.console.log("Initialization called: ", consoleInstance);
|
|
107
|
+
// // if (consoleInstance && props.aaaInstance) {
|
|
108
|
+
// // window.console.log("ConsoleInstance");
|
|
109
|
+
// // (async () => {
|
|
110
|
+
// // // window.console.log("Get TOken: ", await aaaInstance.getToken());
|
|
111
|
+
// // // if (await aaaInstance.isAuthenticated()) {
|
|
112
|
+
// // // window.console.log("IsUserLoaded[authenticated]: ", aaaInstance.isUserLoaded);
|
|
113
|
+
// // // window.console.log("Is Authenticated true");
|
|
114
|
+
// // // consoleInstance.renderHeaderAndSidebar(document.getElementById('headerAndSidebar') as HTMLDivElement);
|
|
115
|
+
// // // } else {
|
|
116
|
+
// // // window.console.log("IsUserLoaded: ", aaaInstance.isUserLoaded);
|
|
117
|
+
// // // if (!aaaInstance.isUserLoaded) {
|
|
118
|
+
// // // window.console.log("Login fn called");
|
|
119
|
+
// // // await aaaInstance.login();
|
|
120
|
+
// // // }
|
|
121
|
+
// // // }
|
|
122
|
+
// // // aaaInstance.loginOnload();
|
|
123
|
+
// // })()
|
|
124
|
+
|
|
125
|
+
// // }
|
|
126
|
+
// // }, [consoleInstance]);
|
|
127
|
+
|
|
128
|
+
// // (async () => {
|
|
129
|
+
// // const token = await aaaInstance.getToken();
|
|
130
|
+
// // window.console.log("Token: ", token);
|
|
131
|
+
// // })()
|
|
132
|
+
|
|
133
|
+
// return <div id="headerAndSidebar"></div>;
|
|
134
|
+
// };
|
|
135
|
+
|
|
136
|
+
// const hasCodeInUrl = (location: Location): boolean => {
|
|
137
|
+
// const searchParams = new URLSearchParams(location.search);
|
|
138
|
+
// const hashParams = new URLSearchParams(location.hash.replace('#', '?'));
|
|
139
|
+
// return Boolean(
|
|
140
|
+
// searchParams.get('code') ||
|
|
141
|
+
// searchParams.get('id_token') ||
|
|
142
|
+
// searchParams.get('session_state') ||
|
|
143
|
+
// searchParams.get('state') ||
|
|
144
|
+
// hashParams.get('code') ||
|
|
145
|
+
// hashParams.get('id_token') ||
|
|
146
|
+
// hashParams.get('session_state') ||
|
|
147
|
+
// hashParams.get('state')
|
|
148
|
+
// );
|
|
149
|
+
// };
|
package/tsconfig.json
ADDED
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
{
|
|
2
|
+
"compilerOptions": {
|
|
3
|
+
"moduleResolution": "node",
|
|
4
|
+
"target": "es5",
|
|
5
|
+
"module": "commonjs",
|
|
6
|
+
"declaration": true,
|
|
7
|
+
"strict": true,
|
|
8
|
+
"sourceMap": true,
|
|
9
|
+
"noImplicitAny": true,
|
|
10
|
+
"strictNullChecks": true,
|
|
11
|
+
"noImplicitThis": true,
|
|
12
|
+
"alwaysStrict": true,
|
|
13
|
+
"noImplicitReturns": true,
|
|
14
|
+
"inlineSources": true,
|
|
15
|
+
"skipLibCheck": true,
|
|
16
|
+
"esModuleInterop": true,
|
|
17
|
+
"jsx": "react-jsx",
|
|
18
|
+
"experimentalDecorators": true,
|
|
19
|
+
"typeRoots": ["./node_modules/@types"],
|
|
20
|
+
"declarationDir": "./dist/commonjs/types",
|
|
21
|
+
"outDir": "./dist/commonjs",
|
|
22
|
+
"lib": ["ES2015", "dom", "DOM.Iterable", "ESNext"]
|
|
23
|
+
},
|
|
24
|
+
"include": ["src"],
|
|
25
|
+
"exclude": ["node_modules", "test"]
|
|
26
|
+
}
|