dce-reactkit 3.9.2 → 3.9.4-beta-prompt.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cjs/index.js +184 -4
- package/dist/cjs/index.js.map +1 -1
- package/dist/cjs/types/components/AppWrapper.d.ts +24 -0
- package/dist/cjs/types/helpers/genRouteHandler.d.ts +8 -0
- package/dist/cjs/types/index.d.ts +2 -2
- package/dist/cjs/types/types/ModalType.d.ts +1 -0
- package/dist/cjs/types/types/ReactKitErrorCode.d.ts +2 -0
- package/dist/esm/index.js +184 -5
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/types/components/AppWrapper.d.ts +24 -0
- package/dist/esm/types/helpers/genRouteHandler.d.ts +8 -0
- package/dist/esm/types/index.d.ts +2 -2
- package/dist/esm/types/types/ModalType.d.ts +1 -0
- package/dist/esm/types/types/ReactKitErrorCode.d.ts +2 -0
- package/dist/index.d.ts +36 -1
- package/package.json +1 -1
- package/src/components/AppWrapper.tsx +216 -0
- package/src/components/Modal/index.tsx +3 -0
- package/src/helpers/genRouteHandler.ts +99 -0
- package/src/index.ts +2 -0
- package/src/types/ModalType.tsx +1 -0
- package/src/types/ReactKitErrorCode.tsx +3 -1
package/dist/cjs/index.js
CHANGED
|
@@ -59,7 +59,7 @@ function __awaiter(thisArg, _arguments, P, generator) {
|
|
|
59
59
|
});
|
|
60
60
|
}
|
|
61
61
|
|
|
62
|
-
// Highest error code =
|
|
62
|
+
// Highest error code = DRK18
|
|
63
63
|
/**
|
|
64
64
|
* List of error codes built into the react kit
|
|
65
65
|
* @author Gabe Abrams
|
|
@@ -71,6 +71,8 @@ var ReactKitErrorCode;
|
|
|
71
71
|
ReactKitErrorCode["SessionExpired"] = "DRK3";
|
|
72
72
|
ReactKitErrorCode["MissingParameter"] = "DRK4";
|
|
73
73
|
ReactKitErrorCode["InvalidParameter"] = "DRK5";
|
|
74
|
+
ReactKitErrorCode["HostNotAllowed"] = "DRK17";
|
|
75
|
+
ReactKitErrorCode["HostBanned"] = "DRK18";
|
|
74
76
|
ReactKitErrorCode["WrongCourse"] = "DRK6";
|
|
75
77
|
ReactKitErrorCode["NoCACCLSendRequestFunction"] = "DRK7";
|
|
76
78
|
ReactKitErrorCode["NoCACCLGetLaunchInfoFunction"] = "DRK8";
|
|
@@ -184,6 +186,7 @@ var ModalButtonType$1 = ModalButtonType;
|
|
|
184
186
|
var ModalType;
|
|
185
187
|
(function (ModalType) {
|
|
186
188
|
ModalType["Okay"] = "okay";
|
|
189
|
+
ModalType["Cancel"] = "cancel";
|
|
187
190
|
ModalType["OkayCancel"] = "okay-cancel";
|
|
188
191
|
ModalType["YesNo"] = "yes-no";
|
|
189
192
|
ModalType["YesNoCancel"] = "yes-no-cancel";
|
|
@@ -338,6 +341,9 @@ const modalTypeToModalButtonTypes = {
|
|
|
338
341
|
[ModalType$1.Okay]: [
|
|
339
342
|
ModalButtonType$1.Okay,
|
|
340
343
|
],
|
|
344
|
+
[ModalType$1.Cancel]: [
|
|
345
|
+
ModalButtonType$1.Cancel,
|
|
346
|
+
],
|
|
341
347
|
[ModalType$1.OkayCancel]: [
|
|
342
348
|
ModalButtonType$1.Okay,
|
|
343
349
|
ModalButtonType$1.Cancel,
|
|
@@ -1078,6 +1084,73 @@ const confirm = (title, text, opts) => __awaiter(void 0, void 0, void 0, functio
|
|
|
1078
1084
|
});
|
|
1079
1085
|
});
|
|
1080
1086
|
/*----------------------------------------*/
|
|
1087
|
+
/* --------------- Prompt -------------- */
|
|
1088
|
+
/*----------------------------------------*/
|
|
1089
|
+
// Stored copies of setters
|
|
1090
|
+
let setPromptInfo;
|
|
1091
|
+
// Function to call when prompt is closed
|
|
1092
|
+
let onPromptClosed;
|
|
1093
|
+
/**
|
|
1094
|
+
* Show a prompt modal asking the user for input
|
|
1095
|
+
* @author Yuen Ler Chow
|
|
1096
|
+
* @param title the title text to display at the top of the prompt
|
|
1097
|
+
* @param text the text to display in the prompt
|
|
1098
|
+
* @param [opts={}] additional options for the prompt dialog
|
|
1099
|
+
* @param [opts.placeholder] the placeholder text for the input field
|
|
1100
|
+
* @param [opts.defaultText] the default text for the input field
|
|
1101
|
+
* @param [opts.confirmButtonText=Okay] the text of the confirm button
|
|
1102
|
+
* @param [opts.confirmButtonVariant=Variant.Dark] the variant of the confirm button
|
|
1103
|
+
* @param [opts.cancelButtonText=Cancel] the text of the cancel button
|
|
1104
|
+
* @param [opts.cancelButtonVariant=Variant.Secondary] the variant of the cancel button
|
|
1105
|
+
* @returns Promise that resolves with the input string or null if canceled
|
|
1106
|
+
*/
|
|
1107
|
+
const prompt = (title, text, currentInputFieldText, opts) => __awaiter(void 0, void 0, void 0, function* () {
|
|
1108
|
+
var _a;
|
|
1109
|
+
// Wait for helper to exist
|
|
1110
|
+
yield waitForHelper(() => {
|
|
1111
|
+
return !!setPromptInfo;
|
|
1112
|
+
});
|
|
1113
|
+
// Fallback if prompt is not available
|
|
1114
|
+
if (!setPromptInfo) {
|
|
1115
|
+
const resultPassesValidation = false;
|
|
1116
|
+
while (!resultPassesValidation) {
|
|
1117
|
+
// eslint-disable-next-line no-alert
|
|
1118
|
+
const result = window.prompt(`${title}\n\n${text}`, (_a = opts === null || opts === void 0 ? void 0 : opts.defaultText) !== null && _a !== void 0 ? _a : '');
|
|
1119
|
+
if (result === null) {
|
|
1120
|
+
return null;
|
|
1121
|
+
}
|
|
1122
|
+
// Validate min num chars
|
|
1123
|
+
const minNumCharsValidationError = (((opts === null || opts === void 0 ? void 0 : opts.minNumChars) && result.length < opts.minNumChars)
|
|
1124
|
+
? `Please enter at least ${opts.minNumChars} characters.`
|
|
1125
|
+
: undefined);
|
|
1126
|
+
// Run custom validation
|
|
1127
|
+
const customValidationError = ((opts === null || opts === void 0 ? void 0 : opts.findValidationError)
|
|
1128
|
+
&& opts.findValidationError(result));
|
|
1129
|
+
// Show validation issue
|
|
1130
|
+
if (minNumCharsValidationError || customValidationError) {
|
|
1131
|
+
alert('Invalid Input', `${minNumCharsValidationError !== null && minNumCharsValidationError !== void 0 ? minNumCharsValidationError : ''} ${customValidationError !== null && customValidationError !== void 0 ? customValidationError : ''}`);
|
|
1132
|
+
}
|
|
1133
|
+
else {
|
|
1134
|
+
return result;
|
|
1135
|
+
}
|
|
1136
|
+
}
|
|
1137
|
+
}
|
|
1138
|
+
// Return promise that resolves with result of prompt
|
|
1139
|
+
return new Promise((resolve) => {
|
|
1140
|
+
// Setup handler
|
|
1141
|
+
onPromptClosed = (result) => {
|
|
1142
|
+
resolve(result);
|
|
1143
|
+
};
|
|
1144
|
+
// Show the prompt
|
|
1145
|
+
setPromptInfo({
|
|
1146
|
+
title,
|
|
1147
|
+
text,
|
|
1148
|
+
currentInputFieldText,
|
|
1149
|
+
opts: (opts !== null && opts !== void 0 ? opts : {}),
|
|
1150
|
+
});
|
|
1151
|
+
});
|
|
1152
|
+
});
|
|
1153
|
+
/*----------------------------------------*/
|
|
1081
1154
|
/* ------------- Fatal Error ------------ */
|
|
1082
1155
|
/*----------------------------------------*/
|
|
1083
1156
|
// Stored copies of setters
|
|
@@ -1093,14 +1166,14 @@ const fatalErrorHandlers = [];
|
|
|
1093
1166
|
* @param [errorTitle] title of the error box
|
|
1094
1167
|
*/
|
|
1095
1168
|
const showFatalError = (error, errorTitle = 'An Error Occurred') => __awaiter(void 0, void 0, void 0, function* () {
|
|
1096
|
-
var
|
|
1169
|
+
var _b, _c;
|
|
1097
1170
|
// Determine message and code
|
|
1098
1171
|
const message = (typeof error === 'string'
|
|
1099
1172
|
? error.trim()
|
|
1100
|
-
: String((
|
|
1173
|
+
: String((_b = error.message) !== null && _b !== void 0 ? _b : 'An unknown error occurred.'));
|
|
1101
1174
|
const code = (typeof error === 'string'
|
|
1102
1175
|
? ReactKitErrorCode$1.NoCode
|
|
1103
|
-
: String((
|
|
1176
|
+
: String((_c = error.code) !== null && _c !== void 0 ? _c : ReactKitErrorCode$1.NoCode));
|
|
1104
1177
|
// Call all fatal error listeners
|
|
1105
1178
|
try {
|
|
1106
1179
|
fatalErrorHandlers.forEach((handler) => {
|
|
@@ -1227,6 +1300,9 @@ const AppWrapper = (props) => {
|
|
|
1227
1300
|
// Confirm
|
|
1228
1301
|
const [confirmInfo, setConfirmInfoInner,] = React.useState(undefined);
|
|
1229
1302
|
setConfirmInfo = setConfirmInfoInner;
|
|
1303
|
+
// Prompt
|
|
1304
|
+
const [promptInfo, setPromptInfoInner] = React.useState(undefined);
|
|
1305
|
+
setPromptInfo = setPromptInfoInner;
|
|
1230
1306
|
// Session expired
|
|
1231
1307
|
const [sessionHasExpired, setSessionHasExpiredInner,] = React.useState(false);
|
|
1232
1308
|
setSessionHasExpired = setSessionHasExpiredInner;
|
|
@@ -1257,6 +1333,37 @@ const AppWrapper = (props) => {
|
|
|
1257
1333
|
}
|
|
1258
1334
|
}, onTopOfOtherModals: true, dontAllowBackdropExit: true }, confirmInfo.text));
|
|
1259
1335
|
}
|
|
1336
|
+
/* ------------- Prompt ------------ */
|
|
1337
|
+
if (promptInfo) {
|
|
1338
|
+
// Run min char validation
|
|
1339
|
+
const minNumCharsValidationError = ((promptInfo.opts.minNumChars
|
|
1340
|
+
&& promptInfo.currentInputFieldText.length < promptInfo.opts.minNumChars)
|
|
1341
|
+
? `Please enter at least ${promptInfo.opts.minNumChars} characters.`
|
|
1342
|
+
: undefined);
|
|
1343
|
+
// Run custom validation
|
|
1344
|
+
const customValidationError = (promptInfo.opts.findValidationError
|
|
1345
|
+
&& promptInfo.opts.findValidationError(promptInfo.currentInputFieldText));
|
|
1346
|
+
modal = (React__default["default"].createElement(Modal, { key: `prompt-${promptInfo.title}-${promptInfo.text}`, title: promptInfo.title,
|
|
1347
|
+
// Don't show ok button if there is a validation error
|
|
1348
|
+
type: ((customValidationError || minNumCharsValidationError)
|
|
1349
|
+
? ModalType$1.Cancel
|
|
1350
|
+
: ModalType$1.OkayCancel), okayLabel: promptInfo.opts.confirmButtonText, okayVariant: promptInfo.opts.confirmButtonVariant, cancelLabel: promptInfo.opts.cancelButtonText, cancelVariant: promptInfo.opts.cancelButtonVariant, onClose: (buttonType) => {
|
|
1351
|
+
const result = (buttonType === ModalButtonType$1.Okay
|
|
1352
|
+
? promptInfo.currentInputFieldText
|
|
1353
|
+
: null);
|
|
1354
|
+
setPromptInfo(undefined);
|
|
1355
|
+
if (onPromptClosed) {
|
|
1356
|
+
onPromptClosed(result);
|
|
1357
|
+
}
|
|
1358
|
+
}, onTopOfOtherModals: true, dontAllowBackdropExit: true },
|
|
1359
|
+
React__default["default"].createElement("div", { className: "d-flex flex-column align-items-center" },
|
|
1360
|
+
React__default["default"].createElement("p", null, promptInfo.text),
|
|
1361
|
+
React__default["default"].createElement("input", { type: "text", placeholder: promptInfo.opts.placeholder, value: promptInfo.currentInputFieldText, onChange: (e) => {
|
|
1362
|
+
return setPromptInfo(Object.assign(Object.assign({}, promptInfo), { currentInputFieldText: e.target.value }));
|
|
1363
|
+
} }),
|
|
1364
|
+
minNumCharsValidationError && (React__default["default"].createElement("div", { className: "text-danger bg-danger bg-opacity-25 p-2 m-1 rounded" }, minNumCharsValidationError)),
|
|
1365
|
+
customValidationError && (React__default["default"].createElement("div", { className: "text-danger bg-danger bg-opacity-25 p-2 m-1 rounded" }, customValidationError)))));
|
|
1366
|
+
}
|
|
1260
1367
|
/* ------ Custom Modal Portals ------ */
|
|
1261
1368
|
// Custom modal portals
|
|
1262
1369
|
const customModalPortals = [];
|
|
@@ -14469,6 +14576,12 @@ const parseUserAgent = (userAgent) => {
|
|
|
14469
14576
|
* @param opts.handler function that processes the request
|
|
14470
14577
|
* @param [opts.skipSessionCheck] if true, skip the session check (allow users
|
|
14471
14578
|
* to not be logged in and launched via LTI)
|
|
14579
|
+
* @param [opts.allowedHosts] if included, only allow requests from these hosts
|
|
14580
|
+
* (start a hostname with a "*" to only check the end of the hostname)
|
|
14581
|
+
* you can include just one string instead of an array
|
|
14582
|
+
* @param [opts.bannedHosts] if included, do not allow requests from these hosts
|
|
14583
|
+
* (start a hostname with a "*" to only check the end of the hostname)
|
|
14584
|
+
* you can include just one string instead of an array
|
|
14472
14585
|
* @param [opts.unhandledErrorMessagePrefix] if included, when an error that
|
|
14473
14586
|
* is not of type ErrorWithCode is thrown, the client will receive an error
|
|
14474
14587
|
* where the error message is prefixed with this string. For example,
|
|
@@ -14500,6 +14613,72 @@ const genRouteHandler = (opts) => {
|
|
|
14500
14613
|
// Output params
|
|
14501
14614
|
const output = {};
|
|
14502
14615
|
/*----------------------------------------*/
|
|
14616
|
+
/* ----------- Hostname Check ----------- */
|
|
14617
|
+
/*----------------------------------------*/
|
|
14618
|
+
// Get hostnames
|
|
14619
|
+
const originURL = String(req.get('origin')
|
|
14620
|
+
|| req.headers.origin
|
|
14621
|
+
|| req.headers.referer);
|
|
14622
|
+
const originHostname = (originURL
|
|
14623
|
+
// Remove protocol
|
|
14624
|
+
.replace(/(^\w+:|^)\/\//, '')
|
|
14625
|
+
// Remove port
|
|
14626
|
+
.replace(/:\d+$/, ''));
|
|
14627
|
+
const serverHostname = String(req.hostname);
|
|
14628
|
+
// Check allowed
|
|
14629
|
+
if (opts.allowedHosts) {
|
|
14630
|
+
// Only accept requests from allowed hosts
|
|
14631
|
+
const allowedArray = (Array.isArray(opts.allowedHosts)
|
|
14632
|
+
? opts.allowedHosts
|
|
14633
|
+
: [opts.allowedHosts]);
|
|
14634
|
+
// Check if server is localhost
|
|
14635
|
+
if (serverHostname === 'localhost') {
|
|
14636
|
+
// Allow localhost
|
|
14637
|
+
allowedArray.push('localhost');
|
|
14638
|
+
}
|
|
14639
|
+
// Check if current host is allowed
|
|
14640
|
+
const allowed = allowedArray.some((allowedHost) => {
|
|
14641
|
+
if (allowedHost.startsWith('*')) {
|
|
14642
|
+
// Check end of hostname
|
|
14643
|
+
return originHostname.endsWith(allowedHost.substring(1));
|
|
14644
|
+
}
|
|
14645
|
+
// Check full hostname
|
|
14646
|
+
return originHostname.toLowerCase() === allowedHost.toLowerCase();
|
|
14647
|
+
});
|
|
14648
|
+
// If not allowed, return error
|
|
14649
|
+
if (!allowed) {
|
|
14650
|
+
return handleError(res, {
|
|
14651
|
+
message: 'You are not allowed to access this endpoint.',
|
|
14652
|
+
code: ReactKitErrorCode$1.HostNotAllowed,
|
|
14653
|
+
status: 403,
|
|
14654
|
+
});
|
|
14655
|
+
}
|
|
14656
|
+
}
|
|
14657
|
+
// Check banned
|
|
14658
|
+
if (opts.bannedHosts) {
|
|
14659
|
+
// Do not allow requests from banned hosts
|
|
14660
|
+
const bannedArray = (Array.isArray(opts.bannedHosts)
|
|
14661
|
+
? opts.bannedHosts
|
|
14662
|
+
: [opts.bannedHosts]);
|
|
14663
|
+
// Check if current host is banned
|
|
14664
|
+
const banned = bannedArray.some((bannedHost) => {
|
|
14665
|
+
if (bannedHost.startsWith('*')) {
|
|
14666
|
+
// Check end of hostname
|
|
14667
|
+
return originHostname.endsWith(bannedHost.substring(1));
|
|
14668
|
+
}
|
|
14669
|
+
// Check full hostname
|
|
14670
|
+
return originHostname.toLowerCase() === bannedHost.toLowerCase();
|
|
14671
|
+
});
|
|
14672
|
+
// If banned, return error
|
|
14673
|
+
if (banned) {
|
|
14674
|
+
return handleError(res, {
|
|
14675
|
+
message: 'You are not allowed to access this endpoint.',
|
|
14676
|
+
code: ReactKitErrorCode$1.HostBanned,
|
|
14677
|
+
status: 403,
|
|
14678
|
+
});
|
|
14679
|
+
}
|
|
14680
|
+
}
|
|
14681
|
+
/*----------------------------------------*/
|
|
14503
14682
|
/* ------------ Parse Params ------------ */
|
|
14504
14683
|
/*----------------------------------------*/
|
|
14505
14684
|
// Process items one by one
|
|
@@ -16247,6 +16426,7 @@ exports.padDecimalZeros = padDecimalZeros;
|
|
|
16247
16426
|
exports.padZerosLeft = padZerosLeft;
|
|
16248
16427
|
exports.parallelLimit = parallelLimit;
|
|
16249
16428
|
exports.prefixWithAOrAn = prefixWithAOrAn;
|
|
16429
|
+
exports.prompt = prompt;
|
|
16250
16430
|
exports.roundToNumDecimals = roundToNumDecimals;
|
|
16251
16431
|
exports.setClientEventMetadataPopulator = setClientEventMetadataPopulator;
|
|
16252
16432
|
exports.showFatalError = showFatalError;
|