dce-reactkit 3.2.8 → 3.3.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 CHANGED
@@ -36,7 +36,7 @@ function __awaiter(thisArg, _arguments, P, generator) {
36
36
  });
37
37
  }
38
38
 
39
- // Highest error code = DRK11
39
+ // Highest error code = DRK13
40
40
  /**
41
41
  * List of error codes built into the react kit
42
42
  * @author Gabe Abrams
@@ -54,6 +54,8 @@ var ReactKitErrorCode;
54
54
  ReactKitErrorCode["NotTTM"] = "DRK9";
55
55
  ReactKitErrorCode["NotAdmin"] = "DRK10";
56
56
  ReactKitErrorCode["NotAllowedToReviewLogs"] = "DRK11";
57
+ ReactKitErrorCode["ThemeCheckedBeforeReactKitReady"] = "DRK12";
58
+ ReactKitErrorCode["SessionExpiredMessageGottenBeforeReactKitReady"] = "DRK13";
57
59
  })(ReactKitErrorCode || (ReactKitErrorCode = {}));
58
60
  var ReactKitErrorCode$1 = ReactKitErrorCode;
59
61
 
@@ -149,6 +151,24 @@ var ModalType;
149
151
  })(ModalType || (ModalType = {}));
150
152
  var ModalType$1 = ModalType;
151
153
 
154
+ /**
155
+ * Built-in metadata for logs
156
+ * @author Gabe Abrams
157
+ */
158
+ const LogBuiltInMetadata = {
159
+ // Contexts
160
+ Context: {
161
+ Uncategorized: 'Uncategorized',
162
+ ServerRenderedErrorPage: 'ServerRenderedErrorPage',
163
+ ServerEndpointError: 'ServerEndpointError',
164
+ ClientFatalError: 'ClientFatalError',
165
+ },
166
+ // Targets
167
+ Target: {
168
+ NoTarget: 'NoTarget',
169
+ },
170
+ };
171
+
152
172
  /**
153
173
  * Wait for a certain number of ms
154
174
  * @author Gabe Abrams
@@ -512,24 +532,6 @@ const ROUTE_PATH_PREFIX = '/dce-reactkit';
512
532
  */
513
533
  const LOG_ROUTE_PATH = `${ROUTE_PATH_PREFIX}/log`;
514
534
 
515
- /**
516
- * Built-in metadata for logs
517
- * @author Gabe Abrams
518
- */
519
- const LogBuiltInMetadata = {
520
- // Contexts
521
- Context: {
522
- Uncategorized: 'Uncategorized',
523
- ServerRenderedErrorPage: 'ServerRenderedErrorPage',
524
- ServerEndpointError: 'ServerEndpointError',
525
- ClientFatalError: 'ClientFatalError',
526
- },
527
- // Targets
528
- Target: {
529
- NoTarget: 'NoTarget',
530
- },
531
- };
532
-
533
535
  /**
534
536
  * Allowed log levels
535
537
  * @author Gabe Abrams
@@ -542,6 +544,83 @@ var LogLevel;
542
544
  })(LogLevel || (LogLevel = {}));
543
545
  var LogLevel$1 = LogLevel;
544
546
 
547
+ // Import other components
548
+ /*----------------------------------------*/
549
+ /* ---- Static Variables and Getters ---- */
550
+ /*----------------------------------------*/
551
+ /* ----------- Initialized ---------- */
552
+ let initialized = false;
553
+ /* ---------- Send Request ---------- */
554
+ let storedSendRequest;
555
+ /**
556
+ * Get the send request function
557
+ * @author Gabe Abrams
558
+ * @returns sendRequest function
559
+ */
560
+ const getSendRequest = () => {
561
+ // Error if no send request function
562
+ if (!initialized) {
563
+ showFatalError(new ErrorWithCode('Could not send a request because the request needed to be sent before dce-reactkit was properly initialized. Perhaps dce-reactkit was not initialized with initClient.', ReactKitErrorCode$1.NoCACCLSendRequestFunction));
564
+ // Return dummy function that never resolves
565
+ return (() => {
566
+ return new Promise(() => { });
567
+ });
568
+ }
569
+ // Return
570
+ return storedSendRequest;
571
+ };
572
+ /* ------------ Dark Mode ----------- */
573
+ let dark;
574
+ /**
575
+ * Get the current dark/light theme
576
+ * @author Gabe Abrams
577
+ * @returns true if the app has a dark theme
578
+ */
579
+ const darkModeIsOn = () => {
580
+ // Error if not set up yet
581
+ if (!initialized) {
582
+ showFatalError(new ErrorWithCode('Could not check theme color because dce-reactkit was properly initialized. Perhaps dce-reactkit was not initialized with initClient.', ReactKitErrorCode$1.ThemeCheckedBeforeReactKitReady));
583
+ return false;
584
+ }
585
+ // Return
586
+ return !!dark;
587
+ };
588
+ /* ----- Session Expired Message ---- */
589
+ let sessionExpiredMessage;
590
+ /**
591
+ * Get the custom session expired message
592
+ * @author Gabe Abrams
593
+ * @returns session expired message
594
+ */
595
+ const getSessionExpiredMessage = () => {
596
+ // Error if not set up yet
597
+ if (!initialized) {
598
+ showFatalError(new ErrorWithCode('Could not get the session expired message because dce-reactkit was properly initialized. Perhaps dce-reactkit was not initialized with initClient.', ReactKitErrorCode$1.SessionExpiredMessageGottenBeforeReactKitReady));
599
+ return '';
600
+ }
601
+ // Return
602
+ return (sessionExpiredMessage !== null && sessionExpiredMessage !== void 0 ? sessionExpiredMessage : 'Your session has expired. Please go back to Canvas and start over.');
603
+ };
604
+ /*----------------------------------------*/
605
+ /* ---------------- Init ---------------- */
606
+ /*----------------------------------------*/
607
+ /**
608
+ * Initialize the client-side version of reactkit
609
+ * @author Gabe Abrams
610
+ * @param opts object containing all arguments
611
+ * @param opts.sendRequest caccl send request functions
612
+ * @param [opts.dark] if true, the app is a dark-themed app
613
+ * @param [opts.sessionExpiredMessage] a custom session expired message
614
+ */
615
+ const initClient = (opts) => {
616
+ // Store values
617
+ storedSendRequest = opts.sendRequest;
618
+ dark = !!opts.dark;
619
+ sessionExpiredMessage = opts.sessionExpiredMessage;
620
+ // Mark as initialized
621
+ initialized = true;
622
+ };
623
+
545
624
  // Keep track of whether or not session expiry has already been handled
546
625
  let sessionAlreadyExpired = false;
547
626
  /*------------------------------------------------------------------------*/
@@ -613,7 +692,8 @@ const visitServerEndpoint = (opts) => __awaiter(void 0, void 0, void 0, function
613
692
  throw new ErrorWithCode(stubResponse.errorMessage, stubResponse.errorCode);
614
693
  }
615
694
  // Send the request
616
- const response = yield cacclSendRequest({
695
+ const sendRequest = getSendRequest();
696
+ const response = yield sendRequest({
617
697
  path: opts.path,
618
698
  method: (_c = opts.method) !== null && _c !== void 0 ? _c : 'GET',
619
699
  params: opts.params,
@@ -700,24 +780,6 @@ const logClientEvent = (opts) => __awaiter(void 0, void 0, void 0, function* ()
700
780
  /* Static Helpers */
701
781
  /*------------------------------------------------------------------------*/
702
782
  /*----------------------------------------*/
703
- /* Send Request */
704
- /*----------------------------------------*/
705
- // Store copy of caccl send request
706
- let _cacclSendRequest;
707
- /**
708
- * Send a request using caccl's send request feature
709
- * @author Gabe Abrams
710
- * @param opts send request options
711
- * @returns send request response
712
- */
713
- const cacclSendRequest = (opts) => __awaiter(void 0, void 0, void 0, function* () {
714
- // Make sure send request has been passed in
715
- if (!_cacclSendRequest) {
716
- throw new ErrorWithCode(`\nThe request could not be sent because the AppWrapper component does not have a copy of sendRequest from CACCL.\nIf you are currently writing tests for your app, this means you did not properly stub the server response.\nMethod: ${opts.method}\nPath: ${opts.path}\n\n`, ReactKitErrorCode$1.NoCACCLSendRequestFunction);
717
- }
718
- return _cacclSendRequest(opts);
719
- });
720
- /*----------------------------------------*/
721
783
  /* Alert */
722
784
  /*----------------------------------------*/
723
785
  // Stored copies of setters
@@ -841,9 +903,7 @@ const AppWrapper = (props) => {
841
903
  /* Setup */
842
904
  /*------------------------------------------------------------------------*/
843
905
  /* -------------- Props ------------- */
844
- const { children, sendRequest, dark, sessionExpiredMessage = 'Your session has expired. Please go back to Canvas and start over.', } = props;
845
- // Store copy of send request
846
- _cacclSendRequest = sendRequest;
906
+ const { children, } = props;
847
907
  /* -------------- State ------------- */
848
908
  // Fatal error
849
909
  const [fatalErrorMessage, setFatalErrorMessageInner,] = React.useState();
@@ -896,7 +956,7 @@ const AppWrapper = (props) => {
896
956
  if (fatalErrorMessage || fatalErrorCode || sessionHasExpired) {
897
957
  // Re-encapsulate in an error
898
958
  const error = (sessionHasExpired
899
- ? new ErrorWithCode(sessionExpiredMessage, ReactKitErrorCode$1.SessionExpired)
959
+ ? new ErrorWithCode(getSessionExpiredMessage(), ReactKitErrorCode$1.SessionExpired)
900
960
  : new ErrorWithCode((fatalErrorMessage !== null && fatalErrorMessage !== void 0 ? fatalErrorMessage : 'An unknown error has occurred. Please contact support.'), (fatalErrorCode !== null && fatalErrorCode !== void 0 ? fatalErrorCode : ReactKitErrorCode$1.NoCode)));
901
961
  // Build error screen
902
962
  body = (React__default["default"].createElement("div", { style: {
@@ -904,7 +964,7 @@ const AppWrapper = (props) => {
904
964
  width: '100vw',
905
965
  minHeight: '100vh',
906
966
  paddingTop: '2rem',
907
- backgroundColor: (dark
967
+ backgroundColor: (darkModeIsOn()
908
968
  ? '#222'
909
969
  : '#fff'),
910
970
  } },
@@ -5533,6 +5593,54 @@ const canReviewLogs = () => __awaiter(void 0, void 0, void 0, function* () {
5533
5593
  return canReview;
5534
5594
  });
5535
5595
 
5596
+ /**
5597
+ * For every element in an array, extract the value of a prop
5598
+ * (e.g. for all user objects, extract their ages and put that into a new
5599
+ * ages array)
5600
+ * @author Gabe Abrams
5601
+ * @param arr the array of objects to operate on
5602
+ * @param prop the property to extract from each object
5603
+ * @returns new array containing the corresponding values, in order, of each
5604
+ * object in the original array
5605
+ */
5606
+ const extractProp = (arr, prop) => {
5607
+ return arr.map((item) => {
5608
+ return item[prop];
5609
+ });
5610
+ };
5611
+
5612
+ // Import shared helpers
5613
+ /**
5614
+ * Compare two arrays of objects by only comparing the values in a specific
5615
+ * property (e.g. compare user arrays by comparing their user.id values)
5616
+ * @author Gabe Abrams
5617
+ * @param a the first array
5618
+ * @param b the second array
5619
+ * @param prop the property to compare with
5620
+ * @returns true if the arrays contain the same objects as determined by
5621
+ * the values associated with each object's prop
5622
+ */
5623
+ const compareArraysByProp = (a, b, prop) => {
5624
+ // Extract values for comparison
5625
+ const aVals = new Set(extractProp(a, prop));
5626
+ const bVals = new Set(extractProp(b, prop));
5627
+ // Compare sizes first
5628
+ if (aVals.size !== bVals.size) {
5629
+ return false;
5630
+ }
5631
+ // Same number of items. Make sure every object in aVals appears in bVals
5632
+ // (if so, they should be equivalent since the sizes are the same)
5633
+ // > Create map of items in bVals
5634
+ const inBVals = {}; // item => true if in bVals
5635
+ Array.from(bVals.values()).forEach((item) => {
5636
+ inBVals[item] = true;
5637
+ });
5638
+ // > Loop through aVals and make sure every item is in bVals
5639
+ return Array.from(aVals.values()).every((item) => {
5640
+ return inBVals[item];
5641
+ });
5642
+ };
5643
+
5536
5644
  /**
5537
5645
  * Days of the week
5538
5646
  * @author Gabe Abrams
@@ -5588,7 +5696,9 @@ exports.alert = alert$1;
5588
5696
  exports.avg = avg;
5589
5697
  exports.canReviewLogs = canReviewLogs;
5590
5698
  exports.ceilToNumDecimals = ceilToNumDecimals;
5699
+ exports.compareArraysByProp = compareArraysByProp;
5591
5700
  exports.confirm = confirm;
5701
+ exports.extractProp = extractProp;
5592
5702
  exports.floorToNumDecimals = floorToNumDecimals;
5593
5703
  exports.forceNumIntoBounds = forceNumIntoBounds;
5594
5704
  exports.genCSV = genCSV;
@@ -5600,6 +5710,7 @@ exports.getPartOfDay = getPartOfDay;
5600
5710
  exports.getTimeInfoInET = getTimeInfoInET;
5601
5711
  exports.handleError = handleError;
5602
5712
  exports.handleSuccess = handleSuccess;
5713
+ exports.initClient = initClient;
5603
5714
  exports.initLogCollection = initLogCollection;
5604
5715
  exports.initServer = initServer;
5605
5716
  exports.isMobileOrTablet = isMobileOrTablet;