dce-reactkit 3.2.1 → 3.2.2-beta.2

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 (55) hide show
  1. package/.vscode/settings.json +3 -0
  2. package/dist/cjs/index.js +2106 -416
  3. package/dist/cjs/index.js.map +1 -1
  4. package/dist/cjs/types/components/CSVDownloadButton.d.ts +19 -0
  5. package/dist/cjs/types/components/IntelliTable.d.ts +17 -0
  6. package/dist/cjs/types/components/LogReviewer.d.ts +13 -0
  7. package/dist/cjs/types/components/SimpleDateChooser.d.ts +1 -0
  8. package/dist/cjs/types/constants/LOG_REVIEW_ROUTE_PATH_PREFIX.d.ts +6 -0
  9. package/dist/cjs/types/constants/LOG_REVIEW_STATUS_ROUTE.d.ts +7 -0
  10. package/dist/cjs/types/helpers/canReviewLogs.d.ts +7 -0
  11. package/dist/cjs/types/helpers/genCSV.d.ts +14 -0
  12. package/dist/cjs/types/helpers/getMonthName.d.ts +14 -0
  13. package/dist/cjs/types/index.d.ts +8 -1
  14. package/dist/cjs/types/server/initServer.d.ts +8 -0
  15. package/dist/cjs/types/types/IntelliTableColumn.d.ts +12 -0
  16. package/dist/cjs/types/types/LogBuiltInMetadata.d.ts +1 -0
  17. package/dist/cjs/types/types/LogMetadataType.d.ts +19 -0
  18. package/dist/cjs/types/types/ReactKitErrorCode.d.ts +2 -1
  19. package/dist/esm/index.js +2103 -418
  20. package/dist/esm/index.js.map +1 -1
  21. package/dist/esm/types/components/CSVDownloadButton.d.ts +19 -0
  22. package/dist/esm/types/components/IntelliTable.d.ts +17 -0
  23. package/dist/esm/types/components/LogReviewer.d.ts +13 -0
  24. package/dist/esm/types/components/SimpleDateChooser.d.ts +1 -0
  25. package/dist/esm/types/constants/LOG_REVIEW_ROUTE_PATH_PREFIX.d.ts +6 -0
  26. package/dist/esm/types/constants/LOG_REVIEW_STATUS_ROUTE.d.ts +7 -0
  27. package/dist/esm/types/helpers/canReviewLogs.d.ts +7 -0
  28. package/dist/esm/types/helpers/genCSV.d.ts +14 -0
  29. package/dist/esm/types/helpers/getMonthName.d.ts +14 -0
  30. package/dist/esm/types/index.d.ts +8 -1
  31. package/dist/esm/types/server/initServer.d.ts +8 -0
  32. package/dist/esm/types/types/IntelliTableColumn.d.ts +12 -0
  33. package/dist/esm/types/types/LogBuiltInMetadata.d.ts +1 -0
  34. package/dist/esm/types/types/LogMetadataType.d.ts +19 -0
  35. package/dist/esm/types/types/ReactKitErrorCode.d.ts +2 -1
  36. package/dist/index.d.ts +163 -47
  37. package/package.json +1 -1
  38. package/sandbox.js +78 -17
  39. package/src/components/AppWrapper.tsx +15 -0
  40. package/src/components/CSVDownloadButton.tsx +102 -0
  41. package/src/components/IntelliTable.tsx +610 -0
  42. package/src/components/LogReviewer.tsx +2038 -0
  43. package/src/components/SimpleDateChooser.tsx +26 -27
  44. package/src/constants/LOG_REVIEW_ROUTE_PATH_PREFIX.ts +9 -0
  45. package/src/constants/LOG_REVIEW_STATUS_ROUTE.ts +10 -0
  46. package/src/helpers/canReviewLogs.ts +33 -0
  47. package/src/helpers/genCSV.ts +59 -0
  48. package/src/helpers/getHumanReadableDate.ts +6 -17
  49. package/src/helpers/getMonthName.ts +29 -0
  50. package/src/index.ts +14 -0
  51. package/src/server/initServer.ts +105 -3
  52. package/src/types/IntelliTableColumn.ts +24 -0
  53. package/src/types/LogBuiltInMetadata.ts +1 -0
  54. package/src/types/LogMetadataType.ts +23 -0
  55. package/src/types/ReactKitErrorCode.tsx +2 -1
@@ -0,0 +1,7 @@
1
+ /**
2
+ * Route for checking the status of the current user's
3
+ * access to log review
4
+ * @author Gabe Abrams
5
+ */
6
+ declare const LOG_REVIEW_STATUS_ROUTE: string;
7
+ export default LOG_REVIEW_STATUS_ROUTE;
@@ -0,0 +1,7 @@
1
+ /**
2
+ * Check if the current user can review logs
3
+ * @author Gabe Abrams
4
+ * @returns true if current user can review logs
5
+ */
6
+ declare const canReviewLogs: () => Promise<boolean>;
7
+ export default canReviewLogs;
@@ -0,0 +1,14 @@
1
+ /**
2
+ * Generate a CSV file
3
+ * @author Gabe Abrams
4
+ * @param data list of row data in the form of json objects
5
+ * @param columns list of columns to include in the csv
6
+ * @returns multiline csv string
7
+ */
8
+ declare const genCSV: (data: {
9
+ [k: string]: any;
10
+ }[], columns: {
11
+ title: string;
12
+ param: string;
13
+ }[]) => string;
14
+ export default genCSV;
@@ -0,0 +1,14 @@
1
+ /**
2
+ * Get the name of a month given the month number (1 = January, etc.)
3
+ * If an invalid number is provided, we will treat it like January
4
+ * @author Gabe Abrams
5
+ * @param month the number of the month
6
+ * @returns object containing multiple month name formats:
7
+ * { short, full } where short will look like "Jan" and full will look like
8
+ * "January"
9
+ */
10
+ declare const getMonthName: (month: number) => {
11
+ short: string;
12
+ full: string;
13
+ };
14
+ export default getMonthName;
@@ -13,6 +13,9 @@ import PopFailureMark from './components/PopFailureMark';
13
13
  import PopPendingMark from './components/PopPendingMark';
14
14
  import CopiableBox from './components/CopiableBox';
15
15
  import ItemPicker from './components/ItemPicker';
16
+ import LogReviewer from './components/LogReviewer';
17
+ import IntelliTable from './components/IntelliTable';
18
+ import CSVDownloadButton from './components/CSVDownloadButton';
16
19
  import ErrorWithCode from './errors/ErrorWithCode';
17
20
  import MINUTE_IN_MS from './constants/MINUTE_IN_MS';
18
21
  import HOUR_IN_MS from './constants/HOUR_IN_MS';
@@ -43,6 +46,8 @@ import onlyKeepLetters from './helpers/onlyKeepLetters';
43
46
  import parallelLimit from './helpers/parallelLimit';
44
47
  import logClientEvent from './helpers/logClientEvent';
45
48
  import initLogCollection from './server/initLogCollection';
49
+ import getMonthName from './helpers/getMonthName';
50
+ import genCSV from './helpers/genCSV';
46
51
  import ModalButtonType from './types/ModalButtonType';
47
52
  import ModalSize from './types/ModalSize';
48
53
  import ModalType from './types/ModalType';
@@ -55,5 +60,7 @@ import LogType from './types/LogType';
55
60
  import LogSource from './types/LogSource';
56
61
  import LogAction from './types/LogAction';
57
62
  import LogBuiltInMetadata from './types/LogBuiltInMetadata';
63
+ import LogMetadataType from './types/LogMetadataType';
64
+ import IntelliTableColumn from './types/IntelliTableColumn';
58
65
  import PickableItem from './components/ItemPicker/types/PickableItem';
59
- export { AppWrapper, LoadingSpinner, ErrorBox, Modal, TabBox, RadioButton, CheckboxButton, ButtonInputGroup, SimpleDateChooser, Drawer, PopSuccessMark, PopFailureMark, PopPendingMark, CopiableBox, ItemPicker, alert, confirm, showFatalError, ErrorWithCode, MINUTE_IN_MS, HOUR_IN_MS, DAY_IN_MS, abbreviate, avg, ceilToNumDecimals, floorToNumDecimals, forceNumIntoBounds, padDecimalZeros, padZerosLeft, roundToNumDecimals, sum, waitMs, getOrdinal, getTimeInfoInET, stubServerEndpoint, startMinWait, getHumanReadableDate, getPartOfDay, stringsToHumanReadableList, onlyKeepLetters, parallelLimit, visitServerEndpoint, logClientEvent, initServer, genRouteHandler, handleError, handleSuccess, initLogCollection, ModalButtonType, ModalSize, ModalType, ReactKitErrorCode, Variant, DayOfWeek, Log, LogType, LogSource, LogAction, LogBuiltInMetadata, PickableItem, ParamType, };
66
+ export { AppWrapper, LoadingSpinner, ErrorBox, Modal, TabBox, RadioButton, CheckboxButton, ButtonInputGroup, SimpleDateChooser, Drawer, PopSuccessMark, PopFailureMark, PopPendingMark, CopiableBox, ItemPicker, LogReviewer, IntelliTable, CSVDownloadButton, alert, confirm, showFatalError, ErrorWithCode, MINUTE_IN_MS, HOUR_IN_MS, DAY_IN_MS, abbreviate, avg, ceilToNumDecimals, floorToNumDecimals, forceNumIntoBounds, padDecimalZeros, padZerosLeft, roundToNumDecimals, sum, waitMs, getOrdinal, getTimeInfoInET, stubServerEndpoint, startMinWait, getHumanReadableDate, getPartOfDay, stringsToHumanReadableList, onlyKeepLetters, parallelLimit, getMonthName, genCSV, visitServerEndpoint, logClientEvent, initServer, genRouteHandler, handleError, handleSuccess, initLogCollection, ModalButtonType, ModalSize, ModalType, ReactKitErrorCode, Variant, DayOfWeek, Log, LogType, LogSource, LogAction, LogBuiltInMetadata, LogMetadataType, IntelliTableColumn, PickableItem, ParamType, };
@@ -25,10 +25,18 @@ export declare const internalGetLogCollection: () => any;
25
25
  * @param opts.getLaunchInfo CACCL LTI's get launch info function
26
26
  * @param [opts.logCollection] mongo collection from dce-mango to use for
27
27
  * storing logs. If none is included, logs are written to the console
28
+ * @param [opts.logReviewAdmins=all admins] info on which admins can review
29
+ * logs from the client. If not included, all Canvas admins are allowed to
30
+ * review logs. If null, no Canvas admins are allowed to review logs.
31
+ * If an array of Canvas userIds (numbers), only Canvas admins with those
32
+ * userIds are allowed to review logs. If a dce-mango collection, only
33
+ * Canvas admins with entries in that collection ({ userId, ...}) are allowed
34
+ * to review logs
28
35
  */
29
36
  declare const initServer: (opts: {
30
37
  app: any;
31
38
  getLaunchInfo: GetLaunchInfoFunction;
32
39
  logCollection?: any;
40
+ logReviewAdmins?: (number[] | any);
33
41
  }) => void;
34
42
  export default initServer;
@@ -0,0 +1,12 @@
1
+ import ParamType from './ParamType';
2
+ /**
3
+ * Column description for a column in the IntelliTable
4
+ * @author Gabe Abrams
5
+ */
6
+ declare type IntelliTableColumn = {
7
+ title: string;
8
+ param: string;
9
+ type: (ParamType.Boolean | ParamType.Float | ParamType.Int | ParamType.String | ParamType.JSON);
10
+ startsHidden?: boolean;
11
+ };
12
+ export default IntelliTableColumn;
@@ -7,6 +7,7 @@ declare const LogBuiltInMetadata: {
7
7
  Uncategorized: string;
8
8
  ServerRenderedErrorPage: string;
9
9
  ServerEndpointError: string;
10
+ ClientFatalError: string;
10
11
  };
11
12
  Target: {
12
13
  NoSpecificTarget: string;
@@ -0,0 +1,19 @@
1
+ /**
2
+ * Type of a LogMetadata file
3
+ * @author Gabe Abrams
4
+ */
5
+ declare type LogMetadataType = {
6
+ Context?: {
7
+ [k: string]: (string | {
8
+ _: string;
9
+ [k: string]: string;
10
+ });
11
+ };
12
+ Tag?: {
13
+ [k: string]: string;
14
+ };
15
+ Target?: {
16
+ [k: string]: string;
17
+ };
18
+ };
19
+ export default LogMetadataType;
@@ -12,6 +12,7 @@ declare enum ReactKitErrorCode {
12
12
  NoCACCLSendRequestFunction = "DRK7",
13
13
  NoCACCLGetLaunchInfoFunction = "DRK8",
14
14
  NotTTM = "DRK9",
15
- NotAdmin = "DRK10"
15
+ NotAdmin = "DRK10",
16
+ NotAllowedToReviewLogs = "DRK11"
16
17
  }
17
18
  export default ReactKitErrorCode;
package/dist/index.d.ts CHANGED
@@ -22,7 +22,7 @@ declare enum Variant {
22
22
  * @author Gabe Abrams
23
23
  */
24
24
 
25
- declare type Props$d = {
25
+ declare type Props$g = {
26
26
  children: React.ReactNode;
27
27
  sendRequest: SendRequestFunction;
28
28
  dark?: boolean;
@@ -80,7 +80,7 @@ declare const confirm: (title: string, text: string, opts?: {
80
80
  * @param [errorTitle] title of the error box
81
81
  */
82
82
  declare const showFatalError: (error: any, errorTitle?: string) => undefined;
83
- declare const AppWrapper: React.FC<Props$d>;
83
+ declare const AppWrapper: React.FC<Props$g>;
84
84
 
85
85
  /**
86
86
  * Loading spinner/indicator
@@ -93,12 +93,12 @@ declare const LoadingSpinner: () => JSX.Element;
93
93
  * @author Gabe Abrams
94
94
  */
95
95
 
96
- declare type Props$c = {
96
+ declare type Props$f = {
97
97
  error: any;
98
98
  title?: string;
99
99
  onClose?: () => void;
100
100
  };
101
- declare const ErrorBox: React.FC<Props$c>;
101
+ declare const ErrorBox: React.FC<Props$f>;
102
102
 
103
103
  /**
104
104
  * Types of buttons in the modal
@@ -149,7 +149,7 @@ declare enum ModalType {
149
149
  * @author Gabe Abrams
150
150
  */
151
151
 
152
- declare type Props$b = {
152
+ declare type Props$e = {
153
153
  type?: ModalType;
154
154
  size?: ModalSize;
155
155
  title?: React.ReactNode;
@@ -178,27 +178,27 @@ declare type Props$b = {
178
178
  confirmVariant?: Variant;
179
179
  onTopOfOtherModals?: boolean;
180
180
  };
181
- declare const Modal: React.FC<Props$b>;
181
+ declare const Modal: React.FC<Props$e>;
182
182
 
183
183
  /**
184
184
  * A box with a tab on the top that holds buttons and other content
185
185
  * @author Gabe Abrams
186
186
  */
187
187
 
188
- declare type Props$a = {
188
+ declare type Props$d = {
189
189
  title: React.ReactNode;
190
190
  children: React.ReactNode;
191
191
  noBottomMargin?: boolean;
192
192
  noBottomPadding?: boolean;
193
193
  };
194
- declare const TabBox: React.FC<Props$a>;
194
+ declare const TabBox: React.FC<Props$d>;
195
195
 
196
196
  /**
197
197
  * A radio selection button
198
198
  * @author Gabe Abrams
199
199
  */
200
200
 
201
- declare type Props$9 = {
201
+ declare type Props$c = {
202
202
  text: string;
203
203
  onSelected: () => void;
204
204
  ariaLabel: string;
@@ -210,14 +210,14 @@ declare type Props$9 = {
210
210
  unselectedVariant?: Variant;
211
211
  small?: boolean;
212
212
  };
213
- declare const RadioButton: React.FC<Props$9>;
213
+ declare const RadioButton: React.FC<Props$c>;
214
214
 
215
215
  /**
216
216
  * A checkbox button
217
217
  * @author Gabe Abrams
218
218
  */
219
219
 
220
- declare type Props$8 = {
220
+ declare type Props$b = {
221
221
  text: string;
222
222
  onChanged: (checked: boolean) => void;
223
223
  ariaLabel: string;
@@ -231,26 +231,26 @@ declare type Props$8 = {
231
231
  small?: boolean;
232
232
  dashed?: boolean;
233
233
  };
234
- declare const CheckboxButton: React.FC<Props$8>;
234
+ declare const CheckboxButton: React.FC<Props$b>;
235
235
 
236
236
  /**
237
237
  * Input group with a title and space for buttons
238
238
  * @author Gabe Abrams
239
239
  */
240
240
 
241
- declare type Props$7 = {
241
+ declare type Props$a = {
242
242
  label: string;
243
243
  minLabelWidth?: string;
244
244
  children: React.ReactNode;
245
245
  };
246
- declare const ButtonInputGroup: React.FC<Props$7>;
246
+ declare const ButtonInputGroup: React.FC<Props$a>;
247
247
 
248
248
  /**
249
249
  * A very simple, lightweight date chooser
250
250
  * @author Gabe Abrams
251
251
  */
252
252
 
253
- declare type Props$6 = {
253
+ declare type Props$9 = {
254
254
  ariaLabel: string;
255
255
  name: string;
256
256
  month: number;
@@ -264,61 +264,62 @@ declare type Props$6 = {
264
264
  */
265
265
  onChange: (month: number, day: number, year: number) => void;
266
266
  numMonthsToShow?: number;
267
+ chooseFromPast?: boolean;
267
268
  };
268
- declare const SimpleDateChooser: React.FC<Props$6>;
269
+ declare const SimpleDateChooser: React.FC<Props$9>;
269
270
 
270
271
  /**
271
272
  * Drawer container
272
273
  * @author Gabe Abrams
273
274
  */
274
275
 
275
- declare type Props$5 = {
276
+ declare type Props$8 = {
276
277
  children: React.ReactNode;
277
278
  };
278
- declare const Drawer: React.FC<Props$5>;
279
+ declare const Drawer: React.FC<Props$8>;
279
280
 
280
281
  /**
281
282
  * Success checkmark that pops into view
282
283
  * @author Gabe Abrams
283
284
  */
284
285
 
285
- declare type Props$4 = {
286
+ declare type Props$7 = {
286
287
  sizeRem?: number;
287
288
  circleVariant?: string;
288
289
  checkVariant?: string;
289
290
  };
290
- declare const PopSuccessMark: React.FC<Props$4>;
291
+ declare const PopSuccessMark: React.FC<Props$7>;
291
292
 
292
293
  /**
293
294
  * Failure x mark that pops into view
294
295
  * @author Gabe Abrams
295
296
  */
296
297
 
297
- declare type Props$3 = {
298
+ declare type Props$6 = {
298
299
  sizeRem?: number;
299
300
  circleVariant?: string;
300
301
  xVariant?: string;
301
302
  };
302
- declare const PopFailureMark: React.FC<Props$3>;
303
+ declare const PopFailureMark: React.FC<Props$6>;
303
304
 
304
305
  /**
305
306
  * Failure pending that pops into view
306
307
  * @author Gabe Abrams
307
308
  */
308
309
 
309
- declare type Props$2 = {
310
+ declare type Props$5 = {
310
311
  sizeRem?: number;
311
312
  circleVariant?: string;
312
313
  hourglassVariant?: string;
313
314
  };
314
- declare const PopPendingMark: React.FC<Props$2>;
315
+ declare const PopPendingMark: React.FC<Props$5>;
315
316
 
316
317
  /**
317
318
  * Copiable text box
318
319
  * @author Gabe Abrams
319
320
  */
320
321
 
321
- declare type Props$1 = {
322
+ declare type Props$4 = {
322
323
  text: string;
323
324
  maxTextWidthRem?: number;
324
325
  label?: string;
@@ -330,7 +331,7 @@ declare type Props$1 = {
330
331
  textAreaId?: string;
331
332
  copyButtonId?: string;
332
333
  };
333
- declare const CopiableBox: React.FC<Props$1>;
334
+ declare const CopiableBox: React.FC<Props$4>;
334
335
 
335
336
  /**
336
337
  * An item that can be chosen (for use within ItemPicker)
@@ -353,7 +354,7 @@ declare type PickableItem = ({
353
354
  * @author Yuen Ler Chow
354
355
  */
355
356
 
356
- declare type Props = {
357
+ declare type Props$3 = {
357
358
  title: string;
358
359
  items: PickableItem[];
359
360
  /**
@@ -363,7 +364,101 @@ declare type Props = {
363
364
  */
364
365
  onChanged: (updatedItems: PickableItem[]) => void;
365
366
  };
366
- declare const ItemPicker: React.FC<Props>;
367
+ declare const ItemPicker: React.FC<Props$3>;
368
+
369
+ /**
370
+ * Type of a LogMetadata file
371
+ * @author Gabe Abrams
372
+ */
373
+ declare type LogMetadataType = {
374
+ Context?: {
375
+ [k: string]: (string | {
376
+ _: string;
377
+ [k: string]: string;
378
+ });
379
+ };
380
+ Tag?: {
381
+ [k: string]: string;
382
+ };
383
+ Target?: {
384
+ [k: string]: string;
385
+ };
386
+ };
387
+
388
+ /**
389
+ * Log reviewer panel that allows users (must be approved admins) to
390
+ * review logs written by dce-reactkit
391
+ * @author Gabe Abrams
392
+ */
393
+
394
+ declare type Props$2 = {
395
+ LogMetadata: LogMetadataType;
396
+ onClose: () => void;
397
+ };
398
+ declare const LogReviewer: React.FC<Props$2>;
399
+
400
+ /**
401
+ * Server-side API param types
402
+ * @author Gabe Abrams
403
+ */
404
+ declare enum ParamType {
405
+ Boolean = "boolean",
406
+ BooleanOptional = "boolean-optional",
407
+ Float = "float",
408
+ FloatOptional = "float-optional",
409
+ Int = "int",
410
+ IntOptional = "int-optional",
411
+ JSON = "json",
412
+ JSONOptional = "json-optional",
413
+ String = "string",
414
+ StringOptional = "string-optional"
415
+ }
416
+
417
+ /**
418
+ * Column description for a column in the IntelliTable
419
+ * @author Gabe Abrams
420
+ */
421
+ declare type IntelliTableColumn = {
422
+ title: string;
423
+ param: string;
424
+ type: (ParamType.Boolean | ParamType.Float | ParamType.Int | ParamType.String | ParamType.JSON);
425
+ startsHidden?: boolean;
426
+ };
427
+
428
+ /**
429
+ * Intelligent table
430
+ * @author Gabe Abrams
431
+ */
432
+
433
+ declare type Props$1 = {
434
+ title: string;
435
+ id: string;
436
+ data: {
437
+ id: string | number;
438
+ [k: string]: any;
439
+ }[];
440
+ columns: IntelliTableColumn[];
441
+ };
442
+ declare const IntelliTable: React.FC<Props$1>;
443
+
444
+ /**
445
+ * Button for downloading a csv file
446
+ * @author Gabe Abrams
447
+ */
448
+
449
+ declare type Props = {
450
+ filename: string;
451
+ csv: string;
452
+ id?: string;
453
+ className?: string;
454
+ ariaLabel?: string;
455
+ style?: {
456
+ [k: string]: any;
457
+ };
458
+ onClick?: () => void;
459
+ children?: React.ReactNode;
460
+ };
461
+ declare const CSVDownloadButton: React.FC<Props>;
367
462
 
368
463
  /**
369
464
  * An error with a code
@@ -498,23 +593,6 @@ declare const visitServerEndpoint: (opts: {
498
593
  } | undefined;
499
594
  }) => Promise<any>;
500
595
 
501
- /**
502
- * Server-side API param types
503
- * @author Gabe Abrams
504
- */
505
- declare enum ParamType {
506
- Boolean = "boolean",
507
- BooleanOptional = "boolean-optional",
508
- Float = "float",
509
- FloatOptional = "float-optional",
510
- Int = "int",
511
- IntOptional = "int-optional",
512
- JSON = "json",
513
- JSONOptional = "json-optional",
514
- String = "string",
515
- StringOptional = "string-optional"
516
- }
517
-
518
596
  /**
519
597
  * Allowed log levels
520
598
  * @author Gabe Abrams
@@ -744,11 +822,19 @@ declare type GetLaunchInfoFunction = (req: any) => {
744
822
  * @param opts.getLaunchInfo CACCL LTI's get launch info function
745
823
  * @param [opts.logCollection] mongo collection from dce-mango to use for
746
824
  * storing logs. If none is included, logs are written to the console
825
+ * @param [opts.logReviewAdmins=all admins] info on which admins can review
826
+ * logs from the client. If not included, all Canvas admins are allowed to
827
+ * review logs. If null, no Canvas admins are allowed to review logs.
828
+ * If an array of Canvas userIds (numbers), only Canvas admins with those
829
+ * userIds are allowed to review logs. If a dce-mango collection, only
830
+ * Canvas admins with entries in that collection ({ userId, ...}) are allowed
831
+ * to review logs
747
832
  */
748
833
  declare const initServer: (opts: {
749
834
  app: any;
750
835
  getLaunchInfo: GetLaunchInfoFunction;
751
836
  logCollection?: any;
837
+ logReviewAdmins?: (number[] | any);
752
838
  }) => void;
753
839
 
754
840
  /**
@@ -861,6 +947,34 @@ declare const logClientEvent: LogFunction;
861
947
  */
862
948
  declare const initLogCollection: (Collection: any) => any;
863
949
 
950
+ /**
951
+ * Get the name of a month given the month number (1 = January, etc.)
952
+ * If an invalid number is provided, we will treat it like January
953
+ * @author Gabe Abrams
954
+ * @param month the number of the month
955
+ * @returns object containing multiple month name formats:
956
+ * { short, full } where short will look like "Jan" and full will look like
957
+ * "January"
958
+ */
959
+ declare const getMonthName: (month: number) => {
960
+ short: string;
961
+ full: string;
962
+ };
963
+
964
+ /**
965
+ * Generate a CSV file
966
+ * @author Gabe Abrams
967
+ * @param data list of row data in the form of json objects
968
+ * @param columns list of columns to include in the csv
969
+ * @returns multiline csv string
970
+ */
971
+ declare const genCSV: (data: {
972
+ [k: string]: any;
973
+ }[], columns: {
974
+ title: string;
975
+ param: string;
976
+ }[]) => string;
977
+
864
978
  /**
865
979
  * List of error codes built into the react kit
866
980
  * @author Gabe Abrams
@@ -875,7 +989,8 @@ declare enum ReactKitErrorCode {
875
989
  NoCACCLSendRequestFunction = "DRK7",
876
990
  NoCACCLGetLaunchInfoFunction = "DRK8",
877
991
  NotTTM = "DRK9",
878
- NotAdmin = "DRK10"
992
+ NotAdmin = "DRK10",
993
+ NotAllowedToReviewLogs = "DRK11"
879
994
  }
880
995
 
881
996
  /**
@@ -901,10 +1016,11 @@ declare const LogBuiltInMetadata: {
901
1016
  Uncategorized: string;
902
1017
  ServerRenderedErrorPage: string;
903
1018
  ServerEndpointError: string;
1019
+ ClientFatalError: string;
904
1020
  };
905
1021
  Target: {
906
1022
  NoSpecificTarget: string;
907
1023
  };
908
1024
  };
909
1025
 
910
- export { AppWrapper, ButtonInputGroup, CheckboxButton, CopiableBox, DAY_IN_MS, DayOfWeek, Drawer, ErrorBox, ErrorWithCode, HOUR_IN_MS, ItemPicker, LoadingSpinner, Log, LogAction, LogBuiltInMetadata, LogSource, LogType, MINUTE_IN_MS, Modal, ModalButtonType, ModalSize, ModalType, ParamType, PickableItem, PopFailureMark, PopPendingMark, PopSuccessMark, RadioButton, ReactKitErrorCode, SimpleDateChooser, TabBox, Variant, abbreviate, alert, avg, ceilToNumDecimals, confirm, floorToNumDecimals, forceNumIntoBounds, genRouteHandler, getHumanReadableDate, getOrdinal, getPartOfDay, getTimeInfoInET, handleError, handleSuccess, initLogCollection, initServer, logClientEvent, onlyKeepLetters, padDecimalZeros, padZerosLeft, parallelLimit, roundToNumDecimals, showFatalError, startMinWait, stringsToHumanReadableList, stubServerEndpoint, sum, visitServerEndpoint, waitMs };
1026
+ export { AppWrapper, ButtonInputGroup, CSVDownloadButton, CheckboxButton, CopiableBox, DAY_IN_MS, DayOfWeek, Drawer, ErrorBox, ErrorWithCode, HOUR_IN_MS, IntelliTable, IntelliTableColumn, ItemPicker, LoadingSpinner, Log, LogAction, LogBuiltInMetadata, LogMetadataType, LogReviewer, LogSource, LogType, MINUTE_IN_MS, Modal, ModalButtonType, ModalSize, ModalType, ParamType, PickableItem, PopFailureMark, PopPendingMark, PopSuccessMark, RadioButton, ReactKitErrorCode, SimpleDateChooser, TabBox, Variant, abbreviate, alert, avg, ceilToNumDecimals, confirm, floorToNumDecimals, forceNumIntoBounds, genCSV, genRouteHandler, getHumanReadableDate, getMonthName, getOrdinal, getPartOfDay, getTimeInfoInET, handleError, handleSuccess, initLogCollection, initServer, logClientEvent, onlyKeepLetters, padDecimalZeros, padZerosLeft, parallelLimit, roundToNumDecimals, showFatalError, startMinWait, stringsToHumanReadableList, stubServerEndpoint, sum, visitServerEndpoint, waitMs };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "dce-reactkit",
3
- "version": "3.2.1",
3
+ "version": "3.2.2-beta.2",
4
4
  "description": "Shared components for Harvard DCE apps",
5
5
  "main": "dist/cjs/index.js",
6
6
  "module": "dist/esm/index.js",
package/sandbox.js CHANGED
@@ -1,20 +1,81 @@
1
- const { parallelLimit, waitMs } = require('.');
1
+ const monthNames = [
2
+ { short: 'Jan', full: 'January' },
3
+ { short: 'Feb', full: 'February' },
4
+ { short: 'Mar', full: 'March' },
5
+ { short: 'Apr', full: 'April' },
6
+ { short: 'May', full: 'May' },
7
+ { short: 'Jun', full: 'June' },
8
+ { short: 'Jul', full: 'July' },
9
+ { short: 'Aug', full: 'August' },
10
+ { short: 'Sep', full: 'September' },
11
+ { short: 'Oct', full: 'October' },
12
+ { short: 'Nov', full: 'November' },
13
+ { short: 'Dec', full: 'December' },
14
+ ];
2
15
 
3
- (async () => {
16
+ /**
17
+ * Get the name of a month given the month number (1 = January, etc.)
18
+ * If an invalid number is provided, we will treat it like January
19
+ * @author Gabe Abrams
20
+ * @param month the number of the month
21
+ * @returns object containing multiple month name formats:
22
+ * { short, full } where short will look like "Jan" and full will look like
23
+ * "January"
24
+ */
25
+ const getMonthName = (month) => {
26
+ return (monthNames[month - 1] ?? monthNames[0]);
27
+ };
4
28
 
5
- const tasks = [2, 4, 3, 5, 6, 20, 1, 1, 1, 1, 5, 4, 6].map((sec, i) => {
6
- return async () => {
7
- let prefix = '';
8
- for (let j = 0; j < i; j++) {
9
- prefix += '\t';
10
- }
11
- for (let j = 0; j < sec * 5; j++) {
12
- await waitMs(200);
13
- console.log(`${prefix}${j}/${sec * 5}`);
14
- }
15
- return i;
16
- };
17
- });
29
+ today = {
30
+ year: 2023,
31
+ month: 1,
32
+ day: 11,
33
+ };
34
+ numMonthsToShow = 6;
35
+ chooseFromPast = true;
36
+
37
+ const choices = [];
38
+ let startYear = today.year;
39
+ let startMonth = today.month;
40
+ if (chooseFromPast) {
41
+ startMonth -= Math.max(0, numMonthsToShow - 1);
42
+ if (startMonth <= 0) {
43
+ startMonth += 12;
44
+ startYear -= 1;
45
+ }
46
+ }
47
+ for (let i = 0; i < numMonthsToShow; i++) {
48
+ // Get month and year info
49
+ const unmoddedMonth = (startMonth + i);
50
+ const month = (
51
+ unmoddedMonth > 12
52
+ ? unmoddedMonth - 12
53
+ : unmoddedMonth
54
+ );
55
+ const monthName = getMonthName(month).full;
56
+ const year = (
57
+ unmoddedMonth > 12
58
+ ? startYear + 1
59
+ : startYear
60
+ );
18
61
 
19
- const results = await parallelLimit(tasks, 1000);
20
- })();
62
+ // Figure out which days are allowed
63
+ const days = [];
64
+ const numDaysInMonth = (new Date(year, month, 0)).getDate();
65
+ const firstDay = (
66
+ month === today.month
67
+ ? today.day // Current month: start at current date
68
+ : 1 // Future month: start at beginning of month
69
+ );
70
+ for (let day = firstDay; day <= numDaysInMonth; day++) {
71
+ days.push(day);
72
+ }
73
+
74
+ choices.push({
75
+ choiceName: `${monthName} ${year}`,
76
+ month,
77
+ year,
78
+ days,
79
+ });
80
+ }
81
+ console.log(choices);