dce-reactkit 3.12.1-beta-cross-server.2 → 3.12.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (51) hide show
  1. package/.vscode/settings.json +3 -1
  2. package/README.md +0 -20
  3. package/dist/cjs/index.js +356 -406
  4. package/dist/cjs/index.js.map +1 -1
  5. package/dist/cjs/types/components/ItemPicker/index.d.ts +1 -0
  6. package/dist/cjs/types/components/Modal/ModalProps.d.ts +2 -0
  7. package/dist/cjs/types/components/TabBox.d.ts +1 -0
  8. package/dist/cjs/types/helpers/genRouteHandler.d.ts +10 -10
  9. package/dist/cjs/types/helpers/getWordCount.d.ts +10 -0
  10. package/dist/cjs/types/helpers/visitEndpointOnAnotherServer/index.d.ts +13 -15
  11. package/dist/cjs/types/helpers/visitEndpointOnAnotherServer/sendServerToServerRequest.d.ts +6 -0
  12. package/dist/cjs/types/index.d.ts +2 -3
  13. package/dist/cjs/types/server/initServer.d.ts +0 -11
  14. package/dist/cjs/types/types/ReactKitErrorCode.d.ts +1 -13
  15. package/dist/esm/index.js +357 -406
  16. package/dist/esm/index.js.map +1 -1
  17. package/dist/esm/types/components/ItemPicker/index.d.ts +1 -0
  18. package/dist/esm/types/components/Modal/ModalProps.d.ts +2 -0
  19. package/dist/esm/types/components/TabBox.d.ts +1 -0
  20. package/dist/esm/types/helpers/genRouteHandler.d.ts +10 -10
  21. package/dist/esm/types/helpers/getWordCount.d.ts +10 -0
  22. package/dist/esm/types/helpers/visitEndpointOnAnotherServer/index.d.ts +13 -15
  23. package/dist/esm/types/helpers/visitEndpointOnAnotherServer/sendServerToServerRequest.d.ts +6 -0
  24. package/dist/esm/types/index.d.ts +2 -3
  25. package/dist/esm/types/server/initServer.d.ts +0 -11
  26. package/dist/esm/types/types/ReactKitErrorCode.d.ts +1 -13
  27. package/dist/index.d.ts +39 -62
  28. package/package.json +2 -5
  29. package/src/components/IntelliTable.tsx +1 -1
  30. package/src/components/ItemPicker/NestableItemList.tsx +1 -0
  31. package/src/components/ItemPicker/index.tsx +96 -0
  32. package/src/components/Modal/ModalProps.ts +4 -0
  33. package/src/components/Modal/index.tsx +59 -20
  34. package/src/components/TabBox.tsx +27 -9
  35. package/src/helpers/genRouteHandler.ts +95 -55
  36. package/src/helpers/getWordCount.ts +26 -0
  37. package/src/helpers/visitEndpointOnAnotherServer/index.ts +41 -42
  38. package/src/helpers/visitEndpointOnAnotherServer/sendServerToServerRequest.ts +5 -3
  39. package/src/index.ts +2 -4
  40. package/src/server/initServer.ts +0 -18
  41. package/src/types/ReactKitErrorCode.tsx +1 -13
  42. package/dist/cjs/types/helpers/dataSigner.d.ts +0 -38
  43. package/dist/cjs/types/server/initCrossServerCredentialCollection.d.ts +0 -8
  44. package/dist/cjs/types/types/CrossServerCredential.d.ts +0 -11
  45. package/dist/esm/types/helpers/dataSigner.d.ts +0 -38
  46. package/dist/esm/types/server/initCrossServerCredentialCollection.d.ts +0 -8
  47. package/dist/esm/types/types/CrossServerCredential.d.ts +0 -11
  48. package/genEncodedSecret.ts +0 -28
  49. package/src/helpers/dataSigner.ts +0 -232
  50. package/src/server/initCrossServerCredentialCollection.ts +0 -16
  51. package/src/types/CrossServerCredential.ts +0 -16
@@ -14,6 +14,7 @@ type Props = {
14
14
  */
15
15
  onChanged: (updatedItems: PickableItem[]) => void;
16
16
  noBottomMargin?: boolean;
17
+ hideSelectAllOrNoneButtons?: boolean;
17
18
  };
18
19
  declare const ItemPicker: React.FC<Props>;
19
20
  export default ItemPicker;
@@ -38,5 +38,7 @@ type ModalProps = {
38
38
  confirmLabel?: string;
39
39
  confirmVariant?: Variant;
40
40
  onTopOfOtherModals?: boolean;
41
+ isLoading?: boolean;
42
+ isLoadingCancelable?: boolean;
41
43
  };
42
44
  export default ModalProps;
@@ -6,6 +6,7 @@ import React from 'react';
6
6
  type Props = {
7
7
  title: React.ReactNode;
8
8
  children: React.ReactNode;
9
+ topRightChildren?: React.ReactNode;
9
10
  noBottomMargin?: boolean;
10
11
  noBottomPadding?: boolean;
11
12
  };
@@ -7,15 +7,14 @@ import LogFunction from '../types/LogFunction';
7
7
  * @param opts.paramTypes map containing the types for each parameter that is
8
8
  * included in the request (map: param name => type)
9
9
  * @param opts.handler function that processes the request
10
- * @param [opts.crossServerScope] the scope associated with this endpoint.
11
- * If defined, this is a cross-server endpoint, which will never
12
- * have any launch data, will never check Canvas roles or launch status, and will
13
- * instead use scopes and reactkit credentials to sign and validate requests.
14
- * Never start the path with /api/ttm or /api/admin if the endpoint is a cross-server
15
- * endpoint because those roles will not be validated
16
- * @param [opts.skipSessionCheck=true if crossServerScope defined] if true, skip
17
- * the session check (allow users to not be logged in and launched via LTI).
18
- * If crossServerScope is defined, this is always true
10
+ * @param [opts.skipSessionCheck] if true, skip the session check (allow users
11
+ * to not be logged in and launched via LTI)
12
+ * @param [opts.allowedHosts] if included, only allow requests from these hosts
13
+ * (start a hostname with a "*" to only check the end of the hostname)
14
+ * you can include just one string instead of an array
15
+ * @param [opts.bannedHosts] if included, do not allow requests from these hosts
16
+ * (start a hostname with a "*" to only check the end of the hostname)
17
+ * you can include just one string instead of an array
19
18
  * @param [opts.unhandledErrorMessagePrefix] if included, when an error that
20
19
  * is not of type ErrorWithCode is thrown, the client will receive an error
21
20
  * where the error message is prefixed with this string. For example,
@@ -69,8 +68,9 @@ declare const genRouteHandler: (opts: {
69
68
  }) => void;
70
69
  logServerEvent: LogFunction;
71
70
  }) => any;
72
- crossServerScope?: string | undefined;
73
71
  skipSessionCheck?: boolean | undefined;
72
+ allowedHosts?: string | string[] | undefined;
73
+ bannedHosts?: string | string[] | undefined;
74
74
  unhandledErrorMessagePrefix?: string | undefined;
75
75
  }) => (req: any, res: any, next: () => void) => Promise<undefined>;
76
76
  export default genRouteHandler;
@@ -0,0 +1,10 @@
1
+ /**
2
+ * Get number of words in string
3
+ * @author Gardenia Liu
4
+ * @author Allison Zhang
5
+ * @author Gabe Abrams
6
+ * @param text the string to check
7
+ * @returns number of words in the string
8
+ */
9
+ declare const getWordCount: (text: string) => number;
10
+ export default getWordCount;
@@ -1,26 +1,24 @@
1
1
  /**
2
- * Visit an endpoint on another server
2
+ * Send a server-to-server request from this sever to another server that uses
3
+ * dce-reactkit [for server only]
3
4
  * @author Gabe Abrams
4
5
  * @param opts object containing all arguments
5
- * @param opts.method the method of the endpoint
6
- * @param opts.path the path of the other server's endpoint
7
- * @param opts.host the host of the other server
8
- * @param [opts.key=process.env.REACTKIT_CROSS_SERVER_CREDENTIAL_KEY] reactkit cross-server
9
- * credential key
10
- * @param [opts.secret=process.env.REACTKIT_CROSS_SERVER_CREDENTIAL_SECRET reactkit cross-server
11
- * credential secret
12
- * @param [opts.params={}] query/body parameters to include
13
- * @param [opts.responseType=JSON] the response type from the other server
6
+ * @param opts.host - the host of the other server
7
+ * @param opts.path - the path of the other server's endpoint
8
+ * @param [opts.method=GET] - the method of the endpoint
9
+ * @param [opts.params] - query/body parameters to include
10
+ * @param [opts.headers] - headers to include
11
+ * @returns response from server
14
12
  */
15
13
  declare const visitEndpointOnAnotherServer: (opts: {
16
- method: 'GET' | 'POST' | 'DELETE' | 'PUT';
17
- path: string;
18
14
  host: string;
19
- key?: string | undefined;
20
- secret?: string | undefined;
15
+ path: string;
16
+ method?: "GET" | "POST" | "DELETE" | "PUT" | undefined;
21
17
  params?: {
22
18
  [x: string]: any;
23
19
  } | undefined;
24
- responseType?: "Text" | "JSON" | undefined;
20
+ headers?: {
21
+ [x: string]: any;
22
+ } | undefined;
25
23
  }) => Promise<any>;
26
24
  export default visitEndpointOnAnotherServer;
@@ -6,6 +6,9 @@
6
6
  * @param [opts.host] host to send request to
7
7
  * @param [opts.method=GET] http method to use
8
8
  * @param [opts.params] body/data to include in the request
9
+ * @param [opts.headers] headers to include in the request
10
+ * @param [opts.sendCrossDomainCredentials=true if in development mode] if true,
11
+ * send cross-domain credentials even if not in dev mode
9
12
  * @param [opts.responseType=JSON] expected response type
10
13
  * @returns { body, status, headers } on success
11
14
  */
@@ -16,6 +19,9 @@ declare const sendServerToServerRequest: (opts: {
16
19
  params?: {
17
20
  [x: string]: any;
18
21
  } | undefined;
22
+ headers?: {
23
+ [x: string]: any;
24
+ } | undefined;
19
25
  responseType?: "Text" | "JSON" | undefined;
20
26
  }) => Promise<{
21
27
  body: any;
@@ -54,7 +54,6 @@ import onlyKeepLetters from './helpers/onlyKeepLetters';
54
54
  import parallelLimit from './helpers/parallelLimit';
55
55
  import logClientEvent, { setClientEventMetadataPopulator } from './helpers/logClientEvent';
56
56
  import initLogCollection from './server/initLogCollection';
57
- import initCrossServerCredentialCollection from './server/initCrossServerCredentialCollection';
58
57
  import getMonthName from './helpers/getMonthName';
59
58
  import genCSV from './helpers/genCSV';
60
59
  import canReviewLogs from './helpers/canReviewLogs';
@@ -80,6 +79,7 @@ import someAsync from './helpers/asyncArrayFunctions/someAsync';
80
79
  import capitalize from './helpers/capitalize';
81
80
  import shuffleArray from './helpers/shuffleArray';
82
81
  import visitEndpointOnAnotherServer from './helpers/visitEndpointOnAnotherServer';
82
+ import getWordCount from './helpers/getWordCount';
83
83
  import ModalButtonType from './types/ModalButtonType';
84
84
  import ModalSize from './types/ModalSize';
85
85
  import ModalType from './types/ModalType';
@@ -96,9 +96,8 @@ import LogMetadataType from './types/LogMetadataType';
96
96
  import LogFunction from './types/LogFunction';
97
97
  import IntelliTableColumn from './types/IntelliTableColumn';
98
98
  import DropdownItemType from './types/DropdownItemType';
99
- import CrossServerCredential from './types/CrossServerCredential';
100
99
  import PickableItem from './components/ItemPicker/types/PickableItem';
101
100
  import DBEntry from './components/DBEntryManagerPanel/types/DBEntry';
102
101
  import DBEntryField from './components/DBEntryManagerPanel/types/DBEntryField';
103
102
  import DBEntryFieldType from './components/DBEntryManagerPanel/types/DBEntryFieldType';
104
- export { AppWrapper, LoadingSpinner, ErrorBox, Modal, TabBox, RadioButton, CheckboxButton, ButtonInputGroup, SimpleDateChooser, Drawer, PopSuccessMark, PopFailureMark, PopPendingMark, CopiableBox, ItemPicker, LogReviewer, IntelliTable, CSVDownloadButton, DBEntryManagerPanel, Tooltip, ToggleSwitch, AutoscrollToBottomContainer, MultiSwitch, Dropdown, alert, prompt, confirm, showFatalError, ErrorWithCode, MINUTE_IN_MS, HOUR_IN_MS, DAY_IN_MS, DynamicWord, abbreviate, avg, ceilToNumDecimals, floorToNumDecimals, forceNumIntoBounds, padDecimalZeros, padZerosLeft, roundToNumDecimals, sum, waitMs, getOrdinal, getTimeInfoInET, stubServerEndpoint, startMinWait, getHumanReadableDate, getPartOfDay, stringsToHumanReadableList, onlyKeepLetters, parallelLimit, getMonthName, genCSV, canReviewLogs, isMobileOrTablet, extractProp, compareArraysByProp, genCommaList, validateEmail, validatePhoneNumber, validateString, getLocalTimeInfo, idify, makeLinksClickable, prefixWithAOrAn, everyAsync, filterAsync, forEachAsync, mapAsync, someAsync, capitalize, shuffleArray, initClient, visitServerEndpoint, logClientEvent, addFatalErrorHandler, leaveToURL, combineClassNames, useForceRender, setClientEventMetadataPopulator, initServer, genRouteHandler, handleError, handleSuccess, initLogCollection, initCrossServerCredentialCollection, addDBEditorEndpoints, visitEndpointOnAnotherServer, ModalButtonType, ModalSize, ModalType, ReactKitErrorCode, Variant, DayOfWeek, Log, LogType, LogSource, LogAction, LogBuiltInMetadata, LogMetadataType, LogFunction, IntelliTableColumn, DropdownItemType, CrossServerCredential, PickableItem, DBEntry, DBEntryField, DBEntryFieldType, ParamType, };
103
+ export { AppWrapper, LoadingSpinner, ErrorBox, Modal, TabBox, RadioButton, CheckboxButton, ButtonInputGroup, SimpleDateChooser, Drawer, PopSuccessMark, PopFailureMark, PopPendingMark, CopiableBox, ItemPicker, LogReviewer, IntelliTable, CSVDownloadButton, DBEntryManagerPanel, Tooltip, ToggleSwitch, AutoscrollToBottomContainer, MultiSwitch, Dropdown, alert, prompt, confirm, showFatalError, ErrorWithCode, MINUTE_IN_MS, HOUR_IN_MS, DAY_IN_MS, DynamicWord, abbreviate, avg, ceilToNumDecimals, floorToNumDecimals, forceNumIntoBounds, padDecimalZeros, padZerosLeft, roundToNumDecimals, sum, waitMs, getOrdinal, getTimeInfoInET, stubServerEndpoint, startMinWait, getHumanReadableDate, getPartOfDay, stringsToHumanReadableList, onlyKeepLetters, parallelLimit, getMonthName, genCSV, canReviewLogs, isMobileOrTablet, extractProp, compareArraysByProp, genCommaList, validateEmail, validatePhoneNumber, validateString, getLocalTimeInfo, idify, makeLinksClickable, prefixWithAOrAn, everyAsync, filterAsync, forEachAsync, mapAsync, someAsync, capitalize, shuffleArray, getWordCount, initClient, visitServerEndpoint, logClientEvent, addFatalErrorHandler, leaveToURL, combineClassNames, useForceRender, setClientEventMetadataPopulator, initServer, genRouteHandler, handleError, handleSuccess, initLogCollection, addDBEditorEndpoints, visitEndpointOnAnotherServer, ModalButtonType, ModalSize, ModalType, ReactKitErrorCode, Variant, DayOfWeek, Log, LogType, LogSource, LogAction, LogBuiltInMetadata, LogMetadataType, LogFunction, IntelliTableColumn, DropdownItemType, PickableItem, DBEntry, DBEntryField, DBEntryFieldType, ParamType, };
@@ -16,13 +16,6 @@ export declare const cacclGetLaunchInfo: GetLaunchInfoFunction;
16
16
  * have a log collection (yet)
17
17
  */
18
18
  export declare const internalGetLogCollection: () => any;
19
- /**
20
- * Get cross-server credential collection
21
- * @author Gabe Abrams
22
- * @return cross-server credential collection if one was included during launch or null
23
- * if we don't have a cross-server credential collection (yet)
24
- */
25
- export declare const internalGetCrossServerCredentialCollection: () => any;
26
19
  /**
27
20
  * Prepare dce-reactkit to run on the server
28
21
  * @author Gabe Abrams
@@ -39,15 +32,11 @@ export declare const internalGetCrossServerCredentialCollection: () => any;
39
32
  * userIds are allowed to review logs. If a dce-mango collection, only
40
33
  * Canvas admins with entries in that collection ({ userId, ...}) are allowed
41
34
  * to review logs
42
- * @param [opts.crossServerCredentialCollection] mongo collection from dce-mango to use for
43
- * storing cross-server credentials. If none is included, cross-server credentials
44
- * are not supported
45
35
  */
46
36
  declare const initServer: (opts: {
47
37
  app: any;
48
38
  getLaunchInfo: GetLaunchInfoFunction;
49
39
  logCollection?: any;
50
40
  logReviewAdmins?: (number[] | any);
51
- crossServerCredentialCollection?: any;
52
41
  }) => void;
53
42
  export default initServer;
@@ -20,18 +20,6 @@ declare enum ReactKitErrorCode {
20
20
  SessionExpiredMessageGottenBeforeReactKitReady = "DRK13",
21
21
  NotConnected = "DRK14",
22
22
  SelfSigned = "DRK15",
23
- ResponseParseError = "DRK16",
24
- PackUnparseable = "DRK28",
25
- PackInvalidMethod = "DRK19",
26
- PackInvalidPath = "DRK20",
27
- PackInvalidCollection = "DRK21",
28
- PackInvalidCredential = "DRK23",
29
- PackInvalidScope = "DRK22",
30
- PackInvalidTimestamp = "DRK24",
31
- PackInvalidSignature = "DRK25",
32
- PackInvalidBody = "DRK26",
33
- CrossServerNoCredentialsToSignWith = "DRK27",
34
- CrossServerNoPack = "DRK29",
35
- CrossServerNoCredentialEncodingSalt = "DRK30"
23
+ ResponseParseError = "DRK16"
36
24
  }
37
25
  export default ReactKitErrorCode;
package/dist/index.d.ts CHANGED
@@ -209,6 +209,8 @@ type ModalProps = {
209
209
  confirmLabel?: string;
210
210
  confirmVariant?: Variant;
211
211
  onTopOfOtherModals?: boolean;
212
+ isLoading?: boolean;
213
+ isLoadingCancelable?: boolean;
212
214
  };
213
215
 
214
216
  /**
@@ -227,6 +229,7 @@ declare const Modal: React$1.FC<ModalProps>;
227
229
  type Props$j = {
228
230
  title: React$1.ReactNode;
229
231
  children: React$1.ReactNode;
232
+ topRightChildren?: React$1.ReactNode;
230
233
  noBottomMargin?: boolean;
231
234
  noBottomPadding?: boolean;
232
235
  };
@@ -412,6 +415,7 @@ type Props$9 = {
412
415
  */
413
416
  onChanged: (updatedItems: PickableItem[]) => void;
414
417
  noBottomMargin?: boolean;
418
+ hideSelectAllOrNoneButtons?: boolean;
415
419
  };
416
420
  declare const ItemPicker: React$1.FC<Props$9>;
417
421
 
@@ -1086,15 +1090,14 @@ type LogFunction = (opts: ({
1086
1090
  * @param opts.paramTypes map containing the types for each parameter that is
1087
1091
  * included in the request (map: param name => type)
1088
1092
  * @param opts.handler function that processes the request
1089
- * @param [opts.crossServerScope] the scope associated with this endpoint.
1090
- * If defined, this is a cross-server endpoint, which will never
1091
- * have any launch data, will never check Canvas roles or launch status, and will
1092
- * instead use scopes and reactkit credentials to sign and validate requests.
1093
- * Never start the path with /api/ttm or /api/admin if the endpoint is a cross-server
1094
- * endpoint because those roles will not be validated
1095
- * @param [opts.skipSessionCheck=true if crossServerScope defined] if true, skip
1096
- * the session check (allow users to not be logged in and launched via LTI).
1097
- * If crossServerScope is defined, this is always true
1093
+ * @param [opts.skipSessionCheck] if true, skip the session check (allow users
1094
+ * to not be logged in and launched via LTI)
1095
+ * @param [opts.allowedHosts] if included, only allow requests from these hosts
1096
+ * (start a hostname with a "*" to only check the end of the hostname)
1097
+ * you can include just one string instead of an array
1098
+ * @param [opts.bannedHosts] if included, do not allow requests from these hosts
1099
+ * (start a hostname with a "*" to only check the end of the hostname)
1100
+ * you can include just one string instead of an array
1098
1101
  * @param [opts.unhandledErrorMessagePrefix] if included, when an error that
1099
1102
  * is not of type ErrorWithCode is thrown, the client will receive an error
1100
1103
  * where the error message is prefixed with this string. For example,
@@ -1148,8 +1151,9 @@ declare const genRouteHandler: (opts: {
1148
1151
  }) => void;
1149
1152
  logServerEvent: LogFunction;
1150
1153
  }) => any;
1151
- crossServerScope?: string | undefined;
1152
1154
  skipSessionCheck?: boolean | undefined;
1155
+ allowedHosts?: string | string[] | undefined;
1156
+ bannedHosts?: string | string[] | undefined;
1153
1157
  unhandledErrorMessagePrefix?: string | undefined;
1154
1158
  }) => (req: any, res: any, next: () => void) => Promise<undefined>;
1155
1159
 
@@ -1199,16 +1203,12 @@ type GetLaunchInfoFunction = (req: any) => {
1199
1203
  * userIds are allowed to review logs. If a dce-mango collection, only
1200
1204
  * Canvas admins with entries in that collection ({ userId, ...}) are allowed
1201
1205
  * to review logs
1202
- * @param [opts.crossServerCredentialCollection] mongo collection from dce-mango to use for
1203
- * storing cross-server credentials. If none is included, cross-server credentials
1204
- * are not supported
1205
1206
  */
1206
1207
  declare const initServer: (opts: {
1207
1208
  app: any;
1208
1209
  getLaunchInfo: GetLaunchInfoFunction;
1209
1210
  logCollection?: any;
1210
1211
  logReviewAdmins?: (number[] | any);
1211
- crossServerCredentialCollection?: any;
1212
1212
  }) => void;
1213
1213
 
1214
1214
  /**
@@ -1339,14 +1339,6 @@ declare const logClientEvent: LogFunction;
1339
1339
  */
1340
1340
  declare const initLogCollection: (Collection: any) => any;
1341
1341
 
1342
- /**
1343
- * Initialize a cross-server credential collection given the dce-mango Collection class
1344
- * @author Gabe Abrams
1345
- * @param Collection the Collection class from dce-mango
1346
- * @returns initialized logCollection
1347
- */
1348
- declare const initCrossServerCredentialCollection: (Collection: any) => any;
1349
-
1350
1342
  /**
1351
1343
  * Get the name of a month given the month number (1 = January, etc.)
1352
1344
  * If an invalid number is provided, we will treat it like January
@@ -1668,31 +1660,39 @@ declare const capitalize: (str: string) => string;
1668
1660
  declare const shuffleArray: <T>(arr: T[]) => T[];
1669
1661
 
1670
1662
  /**
1671
- * Visit an endpoint on another server
1663
+ * Send a server-to-server request from this sever to another server that uses
1664
+ * dce-reactkit [for server only]
1672
1665
  * @author Gabe Abrams
1673
1666
  * @param opts object containing all arguments
1674
- * @param opts.method the method of the endpoint
1675
- * @param opts.path the path of the other server's endpoint
1676
- * @param opts.host the host of the other server
1677
- * @param [opts.key=process.env.REACTKIT_CROSS_SERVER_CREDENTIAL_KEY] reactkit cross-server
1678
- * credential key
1679
- * @param [opts.secret=process.env.REACTKIT_CROSS_SERVER_CREDENTIAL_SECRET reactkit cross-server
1680
- * credential secret
1681
- * @param [opts.params={}] query/body parameters to include
1682
- * @param [opts.responseType=JSON] the response type from the other server
1667
+ * @param opts.host - the host of the other server
1668
+ * @param opts.path - the path of the other server's endpoint
1669
+ * @param [opts.method=GET] - the method of the endpoint
1670
+ * @param [opts.params] - query/body parameters to include
1671
+ * @param [opts.headers] - headers to include
1672
+ * @returns response from server
1683
1673
  */
1684
1674
  declare const visitEndpointOnAnotherServer: (opts: {
1685
- method: 'GET' | 'POST' | 'DELETE' | 'PUT';
1686
- path: string;
1687
1675
  host: string;
1688
- key?: string | undefined;
1689
- secret?: string | undefined;
1676
+ path: string;
1677
+ method?: "GET" | "POST" | "DELETE" | "PUT" | undefined;
1690
1678
  params?: {
1691
1679
  [x: string]: any;
1692
1680
  } | undefined;
1693
- responseType?: "Text" | "JSON" | undefined;
1681
+ headers?: {
1682
+ [x: string]: any;
1683
+ } | undefined;
1694
1684
  }) => Promise<any>;
1695
1685
 
1686
+ /**
1687
+ * Get number of words in string
1688
+ * @author Gardenia Liu
1689
+ * @author Allison Zhang
1690
+ * @author Gabe Abrams
1691
+ * @param text the string to check
1692
+ * @returns number of words in the string
1693
+ */
1694
+ declare const getWordCount: (text: string) => number;
1695
+
1696
1696
  /**
1697
1697
  * List of error codes built into the react kit
1698
1698
  * @author Gabe Abrams
@@ -1715,19 +1715,7 @@ declare enum ReactKitErrorCode {
1715
1715
  SessionExpiredMessageGottenBeforeReactKitReady = "DRK13",
1716
1716
  NotConnected = "DRK14",
1717
1717
  SelfSigned = "DRK15",
1718
- ResponseParseError = "DRK16",
1719
- PackUnparseable = "DRK28",
1720
- PackInvalidMethod = "DRK19",
1721
- PackInvalidPath = "DRK20",
1722
- PackInvalidCollection = "DRK21",
1723
- PackInvalidCredential = "DRK23",
1724
- PackInvalidScope = "DRK22",
1725
- PackInvalidTimestamp = "DRK24",
1726
- PackInvalidSignature = "DRK25",
1727
- PackInvalidBody = "DRK26",
1728
- CrossServerNoCredentialsToSignWith = "DRK27",
1729
- CrossServerNoPack = "DRK29",
1730
- CrossServerNoCredentialEncodingSalt = "DRK30"
1718
+ ResponseParseError = "DRK16"
1731
1719
  }
1732
1720
 
1733
1721
  /**
@@ -1760,15 +1748,4 @@ declare const LogBuiltInMetadata: {
1760
1748
  };
1761
1749
  };
1762
1750
 
1763
- /**
1764
- * Single cross-server credential
1765
- * @author Gabe Abrams
1766
- */
1767
- type CrossServerCredential = {
1768
- description: string;
1769
- key: string;
1770
- encodedeSecret: string;
1771
- scopes: string[];
1772
- };
1773
-
1774
- export { AppWrapper, AutoscrollToBottomContainer, ButtonInputGroup, CSVDownloadButton, CheckboxButton, CopiableBox, CrossServerCredential, DAY_IN_MS, DBEntry, DBEntryField, DBEntryFieldType, DBEntryManagerPanel, DayOfWeek, Drawer, Dropdown, DropdownItemType, DynamicWord, ErrorBox, ErrorWithCode, HOUR_IN_MS, IntelliTable, IntelliTableColumn, ItemPicker, LoadingSpinner, Log, LogAction, LogBuiltInMetadata, LogFunction, LogMetadataType, LogReviewer, LogSource, LogType, MINUTE_IN_MS, Modal, ModalButtonType, ModalSize, ModalType, MultiSwitch, ParamType, PickableItem, PopFailureMark, PopPendingMark, PopSuccessMark, RadioButton, ReactKitErrorCode, SimpleDateChooser, TabBox, ToggleSwitch, Tooltip, Variant, abbreviate, addDBEditorEndpoints, addFatalErrorHandler, alert, avg, canReviewLogs, capitalize, ceilToNumDecimals, combineClassNames, compareArraysByProp, confirm, everyAsync, extractProp, filterAsync, floorToNumDecimals, forEachAsync, forceNumIntoBounds, genCSV, genCommaList, genRouteHandler, getHumanReadableDate, getLocalTimeInfo, getMonthName, getOrdinal, getPartOfDay, getTimeInfoInET, handleError, handleSuccess, idify, initClient, initCrossServerCredentialCollection, initLogCollection, initServer, isMobileOrTablet, leaveToURL, logClientEvent, makeLinksClickable, mapAsync, onlyKeepLetters, padDecimalZeros, padZerosLeft, parallelLimit, prefixWithAOrAn, prompt, roundToNumDecimals, setClientEventMetadataPopulator, showFatalError, shuffleArray, someAsync, startMinWait, stringsToHumanReadableList, stubServerEndpoint, sum, useForceRender, validateEmail, validatePhoneNumber, validateString, visitEndpointOnAnotherServer, visitServerEndpoint, waitMs };
1751
+ export { AppWrapper, AutoscrollToBottomContainer, ButtonInputGroup, CSVDownloadButton, CheckboxButton, CopiableBox, DAY_IN_MS, DBEntry, DBEntryField, DBEntryFieldType, DBEntryManagerPanel, DayOfWeek, Drawer, Dropdown, DropdownItemType, DynamicWord, ErrorBox, ErrorWithCode, HOUR_IN_MS, IntelliTable, IntelliTableColumn, ItemPicker, LoadingSpinner, Log, LogAction, LogBuiltInMetadata, LogFunction, LogMetadataType, LogReviewer, LogSource, LogType, MINUTE_IN_MS, Modal, ModalButtonType, ModalSize, ModalType, MultiSwitch, ParamType, PickableItem, PopFailureMark, PopPendingMark, PopSuccessMark, RadioButton, ReactKitErrorCode, SimpleDateChooser, TabBox, ToggleSwitch, Tooltip, Variant, abbreviate, addDBEditorEndpoints, addFatalErrorHandler, alert, avg, canReviewLogs, capitalize, ceilToNumDecimals, combineClassNames, compareArraysByProp, confirm, everyAsync, extractProp, filterAsync, floorToNumDecimals, forEachAsync, forceNumIntoBounds, genCSV, genCommaList, genRouteHandler, getHumanReadableDate, getLocalTimeInfo, getMonthName, getOrdinal, getPartOfDay, getTimeInfoInET, getWordCount, handleError, handleSuccess, idify, initClient, initLogCollection, initServer, isMobileOrTablet, leaveToURL, logClientEvent, makeLinksClickable, mapAsync, onlyKeepLetters, padDecimalZeros, padZerosLeft, parallelLimit, prefixWithAOrAn, prompt, roundToNumDecimals, setClientEventMetadataPopulator, showFatalError, shuffleArray, someAsync, startMinWait, stringsToHumanReadableList, stubServerEndpoint, sum, useForceRender, validateEmail, validatePhoneNumber, validateString, visitEndpointOnAnotherServer, visitServerEndpoint, waitMs };
package/package.json CHANGED
@@ -1,14 +1,13 @@
1
1
  {
2
2
  "name": "dce-reactkit",
3
- "version": "3.12.1-beta-cross-server.2",
3
+ "version": "3.12.3",
4
4
  "description": "Shared components for Harvard DCE apps",
5
5
  "main": "dist/cjs/index.js",
6
6
  "module": "dist/esm/index.js",
7
7
  "types": "dist/index.d.ts",
8
8
  "scripts": {
9
9
  "build": "rm -rf dist && rollup -c",
10
- "test": "jest --runInBand",
11
- "gen-reactkit-cross-server-secret": "npx tsx genEncodedSecret.ts"
10
+ "test": "jest --runInBand"
12
11
  },
13
12
  "jest": {
14
13
  "preset": "ts-jest",
@@ -25,7 +24,6 @@
25
24
  },
26
25
  "homepage": "https://github.com/harvard-edtech/dce-reactkit#readme",
27
26
  "dependencies": {
28
- "jwt-simple": "^0.5.6",
29
27
  "qs": "^6.x.x",
30
28
  "react-select": "^5.7.3"
31
29
  },
@@ -47,7 +45,6 @@
47
45
  "@types/bootstrap": "^5.2.8",
48
46
  "@types/express": "^4.17.17",
49
47
  "@types/jest": "^28.1.7",
50
- "@types/jwt-simple": "^0.5.36",
51
48
  "@types/node": "^20.2.5",
52
49
  "@types/react": "^17.0.7",
53
50
  "@typescript-eslint/eslint-plugin": "^5.59.9",
@@ -315,7 +315,7 @@ const IntelliTable: React.FC<Props> = (props) => {
315
315
  checked={columnVisibilityMap[column.param]}
316
316
  ariaLabel={`show "${column.title}" column in the ${title} table`}
317
317
  checkedVariant={Variant.Light}
318
- uncheckedVariant={Variant.Secondary}
318
+ uncheckedVariant={Variant.Light}
319
319
  />
320
320
  );
321
321
  })
@@ -272,6 +272,7 @@ const NestableItemList: React.FC<Props> = (props) => {
272
272
  }}
273
273
  ariaLabel={`Select ${item.name}`}
274
274
  checkedVariant={Variant.Light}
275
+ uncheckedVariant={Variant.Light}
275
276
  />
276
277
 
277
278
  {/* Children */}
@@ -33,6 +33,8 @@ type Props = {
33
33
  onChanged: (updatedItems: PickableItem[]) => void,
34
34
  // If true, don't add margin to bottom of item picker
35
35
  noBottomMargin?: boolean,
36
+ // If true, hide select all or none buttons
37
+ hideSelectAllOrNoneButtons?: boolean,
36
38
  };
37
39
 
38
40
  /*------------------------------------------------------------------------*/
@@ -52,12 +54,61 @@ const ItemPicker: React.FC<Props> = (props) => {
52
54
  items,
53
55
  onChanged,
54
56
  noBottomMargin,
57
+ hideSelectAllOrNoneButtons,
55
58
  } = props;
56
59
 
57
60
  /*------------------------------------------------------------------------*/
58
61
  /* ------------------------- Component Functions ------------------------ */
59
62
  /*------------------------------------------------------------------------*/
60
63
 
64
+ /**
65
+ * Updates the checked state of an item (including all children)
66
+ * @author Yuen Ler Chow
67
+ * @param item the item to update
68
+ * @param checked the new checked state
69
+ * @returns the updated item
70
+ */
71
+ const updateItemChecked = (
72
+ item: PickableItem,
73
+ checked: boolean,
74
+ ): PickableItem => {
75
+ if (item.isGroup) {
76
+ return {
77
+ ...item,
78
+ children: item.children.map((child) => {
79
+ return updateItemChecked(child, checked);
80
+ }),
81
+ };
82
+ }
83
+ return { ...item, checked };
84
+ };
85
+
86
+ /**
87
+ * Selects all items in the list
88
+ * @author Yuen Ler Chow
89
+ */
90
+ const handleSelectAll = () => {
91
+ const updatedItems = items.map(
92
+ (item) => {
93
+ return updateItemChecked(item, true);
94
+ },
95
+ );
96
+ onChanged(updatedItems);
97
+ };
98
+
99
+ /**
100
+ * Deselects all items in the list
101
+ * @author Yuen Ler Chow
102
+ */
103
+ const handleDeselectAll = () => {
104
+ const updatedItems = items.map(
105
+ (item) => {
106
+ return updateItemChecked(item, false);
107
+ },
108
+ );
109
+ onChanged(updatedItems);
110
+ };
111
+
61
112
  /*------------------------------------------------------------------------*/
62
113
  /* ------------------------------- Render ------------------------------- */
63
114
  /*------------------------------------------------------------------------*/
@@ -66,10 +117,55 @@ const ItemPicker: React.FC<Props> = (props) => {
66
117
  /* --------------- Main UI -------------- */
67
118
  /*----------------------------------------*/
68
119
 
120
+ // Select all/none
121
+ const selectAllOrNone = (
122
+ !hideSelectAllOrNoneButtons
123
+ ? (
124
+ <div
125
+ className="d-flex h-100 align-items-end flex-row"
126
+ >
127
+ <div className="d-flex justify-content-end">
128
+ {/* Label */}
129
+ <div
130
+ className="me-2"
131
+ style={{ fontSize: '1.2rem' }}
132
+ >
133
+ Select
134
+ </div>
135
+ {/* Buttons */}
136
+ <div className="btn-group" role="group">
137
+ {/* All */}
138
+ <button
139
+ type="button"
140
+ style={{ borderRight: '0.1rem solid white' }}
141
+ aria-label="Select all contexts"
142
+ className="btn btn-secondary py-0"
143
+ onClick={handleSelectAll}
144
+ >
145
+ All
146
+ </button>
147
+ {/* None */}
148
+ <button
149
+ type="button"
150
+ aria-label="Deselect all contexts"
151
+ className="btn btn-secondary py-0"
152
+ onClick={handleDeselectAll}
153
+ >
154
+ None
155
+ </button>
156
+ </div>
157
+ </div>
158
+ </div>
159
+ )
160
+ : undefined
161
+ );
162
+
163
+ // Main UI
69
164
  return (
70
165
  <TabBox
71
166
  title={title}
72
167
  noBottomMargin={noBottomMargin}
168
+ topRightChildren={selectAllOrNone}
73
169
  >
74
170
  <div style={{ overflowX: 'auto' }}>
75
171
  <NestableItemList
@@ -69,6 +69,10 @@ type ModalProps = {
69
69
  confirmVariant?: Variant,
70
70
  // True if modal should be on top of other modals
71
71
  onTopOfOtherModals?: boolean,
72
+ // If true, the modal is loading
73
+ isLoading?: boolean,
74
+ // If true, the loading is cancelable
75
+ isLoadingCancelable?: boolean,
72
76
  };
73
77
 
74
78
  export default ModalProps;