@elice/material-runbox 1.260820.1 → 1.260825.0-runboxusability.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.
Files changed (81) hide show
  1. package/cjs/components/material-runbox/MaterialRunboxContent.js +1 -2
  2. package/cjs/components/material-runbox/MaterialRunboxHeader.js +12 -29
  3. package/cjs/components/material-runbox/actions/MaterialRunboxActionMenu.d.ts +3 -1
  4. package/cjs/components/material-runbox/actions/MaterialRunboxActionMenu.js +17 -1
  5. package/cjs/components/material-runbox/hooks/index.d.ts +2 -0
  6. package/cjs/components/material-runbox/hooks/index.js +6 -0
  7. package/cjs/components/material-runbox/hooks/useOnlineState.d.ts +12 -0
  8. package/cjs/components/material-runbox/hooks/useOnlineState.js +50 -0
  9. package/cjs/components/material-runbox/hooks/useRunboxSessionEndWarning.d.ts +18 -0
  10. package/cjs/components/material-runbox/hooks/useRunboxSessionEndWarning.js +67 -0
  11. package/cjs/components/material-runbox/locales/en.json.js +1 -1
  12. package/cjs/components/material-runbox/locales/ja.json.js +1 -1
  13. package/cjs/components/material-runbox/locales/ko.json.js +1 -1
  14. package/cjs/components/material-runbox/locales/th.json.js +1 -1
  15. package/cjs/components/material-runbox/status/MaterialRunboxStatusButton.d.ts +18 -0
  16. package/cjs/components/material-runbox/status/MaterialRunboxStatusButton.js +88 -0
  17. package/cjs/components/material-runbox/status/MaterialRunboxStatusConnectionItem.d.ts +11 -0
  18. package/cjs/components/material-runbox/status/MaterialRunboxStatusConnectionItem.js +32 -0
  19. package/cjs/components/material-runbox/status/MaterialRunboxStatusPopover.d.ts +17 -0
  20. package/cjs/components/material-runbox/status/MaterialRunboxStatusPopover.js +133 -0
  21. package/cjs/components/material-runbox/status/MaterialRunboxStatusResourceItem.d.ts +11 -0
  22. package/cjs/components/material-runbox/status/MaterialRunboxStatusResourceItem.js +42 -0
  23. package/cjs/components/material-runbox/status/index.d.ts +4 -0
  24. package/cjs/components/material-runbox/status/index.js +9 -0
  25. package/cjs/components/material-runbox/timer/MaterialRunboxQuotaAlmostEndDialog.d.ts +11 -0
  26. package/cjs/components/material-runbox/timer/MaterialRunboxQuotaAlmostEndDialog.js +116 -0
  27. package/cjs/components/material-runbox/timer/MaterialRunboxQuotaAmount.d.ts +13 -0
  28. package/cjs/components/material-runbox/timer/MaterialRunboxQuotaAmount.js +56 -0
  29. package/cjs/components/material-runbox/timer/MaterialRunboxQuotaPerSessionAlmostEndDialog.d.ts +12 -0
  30. package/cjs/components/material-runbox/timer/MaterialRunboxQuotaPerSessionAlmostEndDialog.js +117 -0
  31. package/cjs/components/material-runbox/timer/MaterialRunboxQuotaTimePart.d.ts +15 -0
  32. package/cjs/components/material-runbox/timer/MaterialRunboxQuotaTimePart.js +50 -0
  33. package/cjs/components/material-runbox/timer/MaterialRunboxTimer.d.ts +6 -0
  34. package/cjs/components/material-runbox/timer/MaterialRunboxTimer.js +20 -16
  35. package/cjs/components/material-runbox/timer/MaterialRunboxTimerDetailPopover.js +19 -81
  36. package/es/components/material-runbox/MaterialRunboxContent.js +1 -2
  37. package/es/components/material-runbox/MaterialRunboxHeader.js +13 -30
  38. package/es/components/material-runbox/actions/MaterialRunboxActionMenu.d.ts +3 -1
  39. package/es/components/material-runbox/actions/MaterialRunboxActionMenu.js +19 -3
  40. package/es/components/material-runbox/hooks/index.d.ts +2 -0
  41. package/es/components/material-runbox/hooks/index.js +2 -0
  42. package/es/components/material-runbox/hooks/useOnlineState.d.ts +12 -0
  43. package/es/components/material-runbox/hooks/useOnlineState.js +44 -0
  44. package/es/components/material-runbox/hooks/useRunboxSessionEndWarning.d.ts +18 -0
  45. package/es/components/material-runbox/hooks/useRunboxSessionEndWarning.js +63 -0
  46. package/es/components/material-runbox/locales/en.json.js +1 -1
  47. package/es/components/material-runbox/locales/ja.json.js +1 -1
  48. package/es/components/material-runbox/locales/ko.json.js +1 -1
  49. package/es/components/material-runbox/locales/th.json.js +1 -1
  50. package/es/components/material-runbox/status/MaterialRunboxStatusButton.d.ts +18 -0
  51. package/es/components/material-runbox/status/MaterialRunboxStatusButton.js +80 -0
  52. package/es/components/material-runbox/status/MaterialRunboxStatusConnectionItem.d.ts +11 -0
  53. package/es/components/material-runbox/status/MaterialRunboxStatusConnectionItem.js +28 -0
  54. package/es/components/material-runbox/status/MaterialRunboxStatusPopover.d.ts +17 -0
  55. package/es/components/material-runbox/status/MaterialRunboxStatusPopover.js +129 -0
  56. package/es/components/material-runbox/status/MaterialRunboxStatusResourceItem.d.ts +11 -0
  57. package/es/components/material-runbox/status/MaterialRunboxStatusResourceItem.js +38 -0
  58. package/es/components/material-runbox/status/index.d.ts +4 -0
  59. package/es/components/material-runbox/status/index.js +2 -0
  60. package/es/components/material-runbox/timer/MaterialRunboxQuotaAlmostEndDialog.d.ts +11 -0
  61. package/es/components/material-runbox/timer/MaterialRunboxQuotaAlmostEndDialog.js +112 -0
  62. package/es/components/material-runbox/timer/MaterialRunboxQuotaAmount.d.ts +13 -0
  63. package/es/components/material-runbox/timer/MaterialRunboxQuotaAmount.js +52 -0
  64. package/es/components/material-runbox/timer/MaterialRunboxQuotaPerSessionAlmostEndDialog.d.ts +12 -0
  65. package/es/components/material-runbox/timer/MaterialRunboxQuotaPerSessionAlmostEndDialog.js +113 -0
  66. package/es/components/material-runbox/timer/MaterialRunboxQuotaTimePart.d.ts +15 -0
  67. package/es/components/material-runbox/timer/MaterialRunboxQuotaTimePart.js +46 -0
  68. package/es/components/material-runbox/timer/MaterialRunboxTimer.d.ts +6 -0
  69. package/es/components/material-runbox/timer/MaterialRunboxTimer.js +19 -15
  70. package/es/components/material-runbox/timer/MaterialRunboxTimerDetailPopover.js +15 -77
  71. package/package.json +8 -8
  72. package/cjs/assets/runbox_logo.png.js +0 -7
  73. package/cjs/components/material-runbox/MaterialRunboxFooter.d.ts +0 -4
  74. package/cjs/components/material-runbox/MaterialRunboxFooter.js +0 -64
  75. package/cjs/components/material-runbox/timer/MaterialRunboxAlmostEndSnackbars.d.ts +0 -6
  76. package/cjs/components/material-runbox/timer/MaterialRunboxAlmostEndSnackbars.js +0 -90
  77. package/es/assets/runbox_logo.png.js +0 -3
  78. package/es/components/material-runbox/MaterialRunboxFooter.d.ts +0 -4
  79. package/es/components/material-runbox/MaterialRunboxFooter.js +0 -56
  80. package/es/components/material-runbox/timer/MaterialRunboxAlmostEndSnackbars.d.ts +0 -6
  81. package/es/components/material-runbox/timer/MaterialRunboxAlmostEndSnackbars.js +0 -86
@@ -0,0 +1,117 @@
1
+ 'use strict';
2
+
3
+ Object.defineProperty(exports, '__esModule', { value: true });
4
+
5
+ var jsxRuntime = require('react/jsx-runtime');
6
+ var intl = require('@elice/intl');
7
+ var runboxClient = require('@elice/runbox-client');
8
+ var material = require('@mui/material');
9
+ var useRunboxSessionEndWarning = require('../hooks/useRunboxSessionEndWarning.js');
10
+ var MaterialRunboxQuotaAmount = require('./MaterialRunboxQuotaAmount.js');
11
+
12
+ //
13
+ //
14
+ //
15
+ /**
16
+ * Warns the learner that the time granted to *this connection* is about to run out.
17
+ *
18
+ * Unlike the total quota, the learner can reconnect and keep going as long as total
19
+ * time is left — so this dialog is about saving work, not about the practice ending.
20
+ */
21
+ var MaterialRunboxQuotaPerSessionAlmostEndDialog = function MaterialRunboxQuotaPerSessionAlmostEndDialog(_ref) {
22
+ var open = _ref.open,
23
+ onClose = _ref.onClose;
24
+ var intl$1 = intl.useRawEliceIntl();
25
+ var _useEliceRunboxQuota = runboxClient.useEliceRunboxQuota(),
26
+ quotaInfo = _useEliceRunboxQuota.quotaInfo,
27
+ quotaPerSessionInfo = _useEliceRunboxQuota.quotaPerSessionInfo;
28
+ if (quotaPerSessionInfo.isUnlimited) {
29
+ return null;
30
+ }
31
+ var isQuotaAlmostEnd = !quotaInfo.isUnlimited && quotaInfo.remainingQuota <= useRunboxSessionEndWarning.QUOTA_ALMOST_END_MINUTES;
32
+ var isQuotaPerSessionAlmostEnd = quotaPerSessionInfo.remainingQuota <= useRunboxSessionEndWarning.QUOTA_PER_SESSION_ALMOST_END_MINUTES;
33
+ return jsxRuntime.jsxs(material.Dialog, {
34
+ fullWidth: true,
35
+ maxWidth: "xs",
36
+ open: open,
37
+ onClose: onClose,
38
+ children: [jsxRuntime.jsx(material.DialogTitle, {
39
+ children: intl$1.formatMessage({
40
+ id: 'runbox.timer.almost_end.dialog.quota_per_session.title'
41
+ }, {
42
+ time: intl$1.formatNumber(useRunboxSessionEndWarning.QUOTA_PER_SESSION_ALMOST_END_MINUTES, {
43
+ style: 'unit',
44
+ unit: 'minute',
45
+ unitDisplay: 'short'
46
+ })
47
+ })
48
+ }), jsxRuntime.jsx(material.DialogContent, {
49
+ children: jsxRuntime.jsxs(material.Stack, {
50
+ direction: "column",
51
+ gap: "1.5rem",
52
+ children: [jsxRuntime.jsxs(material.Card, {
53
+ sx: {
54
+ bgcolor: 'background.neutral'
55
+ },
56
+ children: [jsxRuntime.jsxs(material.Stack, {
57
+ direction: "column",
58
+ gap: "0.5rem",
59
+ padding: "1rem",
60
+ bgcolor: isQuotaAlmostEnd ? 'warning.opacity03' : undefined,
61
+ children: [jsxRuntime.jsx(material.Typography, {
62
+ variant: "body2",
63
+ fontWeight: "bold",
64
+ children: intl$1.formatMessage({
65
+ id: 'runbox.timer.popover.quota.title'
66
+ })
67
+ }), quotaInfo.isUnlimited ? jsxRuntime.jsx(material.Typography, {
68
+ component: "span",
69
+ variant: "h5",
70
+ fontWeight: "extraBold",
71
+ children: intl$1.formatMessage({
72
+ id: 'runbox.timer.unlimited'
73
+ })
74
+ }) : jsxRuntime.jsx(MaterialRunboxQuotaAmount.default, {
75
+ remainingQuota: quotaInfo.remainingQuota,
76
+ quota: quotaInfo.quota,
77
+ color: isQuotaAlmostEnd ? 'warning.main' : 'success.main'
78
+ })]
79
+ }), jsxRuntime.jsx(material.Divider, {}), jsxRuntime.jsxs(material.Stack, {
80
+ direction: "column",
81
+ gap: "0.5rem",
82
+ padding: "1rem",
83
+ bgcolor: isQuotaPerSessionAlmostEnd ? 'warning.opacity03' : undefined,
84
+ children: [jsxRuntime.jsx(material.Typography, {
85
+ variant: "body2",
86
+ fontWeight: "bold",
87
+ children: intl$1.formatMessage({
88
+ id: 'runbox.timer.popover.quota_per_session.title'
89
+ })
90
+ }), jsxRuntime.jsx(MaterialRunboxQuotaAmount.default, {
91
+ remainingQuota: quotaPerSessionInfo.remainingQuota,
92
+ quota: quotaPerSessionInfo.quota,
93
+ color: isQuotaPerSessionAlmostEnd ? 'warning.main' : 'success.main'
94
+ })]
95
+ })]
96
+ }), jsxRuntime.jsx(material.Typography, {
97
+ variant: "body2",
98
+ whiteSpace: "pre-line",
99
+ children: intl$1.formatMessage({
100
+ id: 'runbox.timer.almost_end.dialog.quota_per_session.description'
101
+ })
102
+ })]
103
+ })
104
+ }), jsxRuntime.jsx(material.DialogActions, {
105
+ children: jsxRuntime.jsx(material.Button, {
106
+ variant: "contained",
107
+ color: "inherit",
108
+ onClick: onClose,
109
+ children: intl$1.formatMessage({
110
+ id: 'runbox.timer.almost_end.dialog.confirm'
111
+ })
112
+ })
113
+ })]
114
+ });
115
+ };
116
+
117
+ exports.default = MaterialRunboxQuotaPerSessionAlmostEndDialog;
@@ -0,0 +1,15 @@
1
+ export interface MaterialRunboxQuotaTimePartProps {
2
+ value: number;
3
+ unit: 'hour' | 'minute';
4
+ color?: string;
5
+ }
6
+ /**
7
+ * A single `4시간` / `11분` part, with the unit rendered smaller than the number.
8
+ *
9
+ * The number and its unit are split with `formatNumberToParts` rather than by hand,
10
+ * because where the unit sits and how it is written differs per locale.
11
+ *
12
+ * Renders nothing when `value` is 0, so `29분` does not come out as `0시간 29분`.
13
+ */
14
+ declare const MaterialRunboxQuotaTimePart: React.FC<MaterialRunboxQuotaTimePartProps>;
15
+ export default MaterialRunboxQuotaTimePart;
@@ -0,0 +1,50 @@
1
+ 'use strict';
2
+
3
+ Object.defineProperty(exports, '__esModule', { value: true });
4
+
5
+ var jsxRuntime = require('react/jsx-runtime');
6
+ var intl = require('@elice/intl');
7
+ var material = require('@mui/material');
8
+
9
+ //
10
+ //
11
+ //
12
+ /**
13
+ * A single `4시간` / `11분` part, with the unit rendered smaller than the number.
14
+ *
15
+ * The number and its unit are split with `formatNumberToParts` rather than by hand,
16
+ * because where the unit sits and how it is written differs per locale.
17
+ *
18
+ * Renders nothing when `value` is 0, so `29분` does not come out as `0시간 29분`.
19
+ */
20
+ var MaterialRunboxQuotaTimePart = function MaterialRunboxQuotaTimePart(_ref) {
21
+ var value = _ref.value,
22
+ unit = _ref.unit,
23
+ color = _ref.color;
24
+ var intl$1 = intl.useRawEliceIntl();
25
+ if (value === 0) {
26
+ return null;
27
+ }
28
+ return jsxRuntime.jsx(material.Typography, {
29
+ component: "span",
30
+ variant: "h5",
31
+ fontWeight: "extraBold",
32
+ color: color,
33
+ children: intl$1.formatNumberToParts(value, {
34
+ style: 'unit',
35
+ unit: unit,
36
+ unitDisplay: 'short'
37
+ }).map(function (part, index) {
38
+ return part.type === 'unit' ? jsxRuntime.jsx(material.Typography, {
39
+ component: "span",
40
+ variant: "body2",
41
+ fontWeight: "regular",
42
+ children: part.value
43
+ }, index) : jsxRuntime.jsx("span", {
44
+ children: part.value
45
+ }, index);
46
+ })
47
+ });
48
+ };
49
+
50
+ exports.default = MaterialRunboxQuotaTimePart;
@@ -9,6 +9,12 @@ export interface MaterialRunboxTimerProps {
9
9
  * @default false
10
10
  */
11
11
  hideTimerPopover?: boolean;
12
+ /**
13
+ * Tutoring mode? Session-end warnings are for the learner, not for the tutor
14
+ * looking at their runbox.
15
+ * @default false
16
+ */
17
+ isTutoring?: boolean;
12
18
  }
13
19
  declare const MaterialRunboxTimer: React.FC<MaterialRunboxTimerProps>;
14
20
  export default MaterialRunboxTimer;
@@ -12,7 +12,9 @@ var muiElements = require('@elice/mui-elements');
12
12
  var runboxClient = require('@elice/runbox-client');
13
13
  var proSolidSvgIcons = require('@fortawesome/pro-solid-svg-icons');
14
14
  var material = require('@mui/material');
15
- var MaterialRunboxAlmostEndSnackbars = require('./MaterialRunboxAlmostEndSnackbars.js');
15
+ var useRunboxSessionEndWarning = require('../hooks/useRunboxSessionEndWarning.js');
16
+ var MaterialRunboxQuotaAlmostEndDialog = require('./MaterialRunboxQuotaAlmostEndDialog.js');
17
+ var MaterialRunboxQuotaPerSessionAlmostEndDialog = require('./MaterialRunboxQuotaPerSessionAlmostEndDialog.js');
16
18
  var MaterialRunboxTimerDetailPopover = require('./MaterialRunboxTimerDetailPopover.js');
17
19
  var time = require('../../../utils/time.js');
18
20
 
@@ -21,10 +23,6 @@ function _interopDefaultCompat (e) { return e && typeof e === 'object' && 'defau
21
23
  var _styled__default = /*#__PURE__*/_interopDefaultCompat(_styled);
22
24
  var React__default = /*#__PURE__*/_interopDefaultCompat(React);
23
25
 
24
- //
25
- //
26
- //
27
- var QUOTA_ALMOST_END_MINUTES = 30;
28
26
  //
29
27
  //
30
28
  //
@@ -46,13 +44,21 @@ var MaterialRunboxTimer = function MaterialRunboxTimer(_ref3) {
46
44
  headerElement = _ref3.headerElement,
47
45
  stopRuntime = _ref3.stopRuntime,
48
46
  _ref3$hideTimerPopove = _ref3.hideTimerPopover,
49
- hideTimerPopover = _ref3$hideTimerPopove === void 0 ? false : _ref3$hideTimerPopove;
47
+ hideTimerPopover = _ref3$hideTimerPopove === void 0 ? false : _ref3$hideTimerPopove,
48
+ _ref3$isTutoring = _ref3.isTutoring,
49
+ isTutoring = _ref3$isTutoring === void 0 ? false : _ref3$isTutoring;
50
50
  var intl$1 = intl.useRawEliceIntl();
51
51
  var _useEliceRunboxRunnin = runboxClient.useEliceRunboxRunning(),
52
52
  status = _useEliceRunboxRunnin.status;
53
53
  var isRunboxRunning = status === 'running';
54
54
  var _useEliceRunboxQuota = runboxClient.useEliceRunboxQuota(),
55
55
  quotaInfo = _useEliceRunboxQuota.quotaInfo;
56
+ var _useRunboxSessionEndW = useRunboxSessionEndWarning.useRunboxSessionEndWarning({
57
+ runboxId: runboxId,
58
+ disabled: isTutoring || !isRunboxRunning
59
+ }),
60
+ warning = _useRunboxSessionEndW.warning,
61
+ dismiss = _useRunboxSessionEndW.dismiss;
56
62
  var _React$useState = React__default.default.useState(false),
57
63
  _React$useState2 = _rollupPluginBabelHelpers.slicedToArray(_React$useState, 2),
58
64
  isTimerDetailPopoverOpen = _React$useState2[0],
@@ -82,7 +88,7 @@ var MaterialRunboxTimer = function MaterialRunboxTimer(_ref3) {
82
88
  var hoursString = hours.toString().padStart(2, '0');
83
89
  var minutesString = minutes.toString().padStart(2, '0');
84
90
  var timeString = "".concat(hoursString, " : ").concat(minutesString);
85
- var isAlmostEnd = !quotaInfo.isUnlimited && quotaInfo.remainingQuota <= QUOTA_ALMOST_END_MINUTES;
91
+ var isAlmostEnd = !quotaInfo.isUnlimited && quotaInfo.remainingQuota <= useRunboxSessionEndWarning.QUOTA_ALMOST_END_MINUTES;
86
92
  return jsxRuntime.jsx(material.Tooltip, {
87
93
  arrow: true,
88
94
  placement: "bottom",
@@ -160,19 +166,17 @@ var MaterialRunboxTimer = function MaterialRunboxTimer(_ref3) {
160
166
  }
161
167
  });
162
168
  };
163
- var renderAlmostEndSnackbars = function renderAlmostEndSnackbars() {
164
- return jsxRuntime.jsx(MaterialRunboxAlmostEndSnackbars.default, {
165
- runboxId: runboxId,
166
- onClickDetail: function onClickDetail() {
167
- return setTimerDetailPopoverOpen(true);
168
- }
169
- });
170
- };
171
169
  if (!isRunboxRunning) {
172
170
  return null;
173
171
  }
174
172
  return jsxRuntime.jsxs(jsxRuntime.Fragment, {
175
- children: [renderTimer(), renderTimerDetailPopover(), renderAlmostEndSnackbars()]
173
+ children: [renderTimer(), renderTimerDetailPopover(), jsxRuntime.jsx(MaterialRunboxQuotaAlmostEndDialog.default, {
174
+ open: warning === 'quota',
175
+ onClose: dismiss
176
+ }), jsxRuntime.jsx(MaterialRunboxQuotaPerSessionAlmostEndDialog.default, {
177
+ open: warning === 'quotaPerSession',
178
+ onClose: dismiss
179
+ })]
176
180
  });
177
181
  };
178
182
 
@@ -13,13 +13,12 @@ var runboxClient = require('@elice/runbox-client');
13
13
  var proRegularSvgIcons = require('@fortawesome/pro-regular-svg-icons');
14
14
  var material = require('@mui/material');
15
15
  var reactQuery = require('@tanstack/react-query');
16
- var time = require('../../../utils/time.js');
16
+ var useRunboxSessionEndWarning = require('../hooks/useRunboxSessionEndWarning.js');
17
+ var MaterialRunboxQuotaAmount = require('./MaterialRunboxQuotaAmount.js');
17
18
 
18
19
  //
19
20
  //
20
21
  //
21
- var QUOTA_ALMOST_END_MINUTES = 30;
22
- var QUOTA_PER_SESSION_ALMOST_END_MINUTES = 10;
23
22
  var QUOTA_POPOVER_NOT_SHOW_ON_START = 'MaterialRunboxTimer.timerDetailPopover.notShowOnStart';
24
23
  //
25
24
  //
@@ -118,48 +117,6 @@ var MaterialRunboxTimerDetailPopover = function MaterialRunboxTimerDetailPopover
118
117
  })]
119
118
  });
120
119
  };
121
- /**
122
- *
123
- */
124
- var formatTimePart = function formatTimePart(value, unit) {
125
- return intl$1.formatNumber(value, {
126
- style: 'unit',
127
- unit: unit,
128
- unitDisplay: 'short'
129
- });
130
- };
131
- /**
132
- *
133
- */
134
- var renderQuotaTimePart = function renderQuotaTimePart(value, unit, color) {
135
- if (value === 0) {
136
- return null;
137
- }
138
- var parts = intl$1.formatNumberToParts(value, {
139
- style: 'unit',
140
- unit: unit,
141
- unitDisplay: 'short'
142
- });
143
- return jsxRuntime.jsx(material.Typography, {
144
- component: "span",
145
- variant: "h5",
146
- fontWeight: "extraBold",
147
- color: color,
148
- children: parts.map(function (part, index) {
149
- if (part.type === 'unit') {
150
- return jsxRuntime.jsx(material.Typography, {
151
- component: "span",
152
- variant: "body2",
153
- fontWeight: "regular",
154
- children: part.value
155
- }, index);
156
- }
157
- return jsxRuntime.jsx("span", {
158
- children: part.value
159
- }, index);
160
- })
161
- });
162
- };
163
120
  /**
164
121
  *
165
122
  */
@@ -185,15 +142,8 @@ var MaterialRunboxTimerDetailPopover = function MaterialRunboxTimerDetailPopover
185
142
  })]
186
143
  });
187
144
  }
188
- // Sync UI with the timer.
189
- var _getTimeParts = time.getTimeParts(quotaInfo.remainingQuota * 60),
190
- remainingHours = _getTimeParts.hours,
191
- remainingMinutes = _getTimeParts.minutes;
192
- var _getTimeParts2 = time.getTimeParts(quotaInfo.quota * 60),
193
- totalHours = _getTimeParts2.hours,
194
- totalMinutes = _getTimeParts2.minutes;
195
- var quotaColor = quotaInfo.remainingQuota > QUOTA_ALMOST_END_MINUTES ? 'success.main' : 'warning.main';
196
- var quotaBgColor = quotaInfo.remainingQuota > QUOTA_ALMOST_END_MINUTES ? undefined : 'warning.opacity03';
145
+ var quotaColor = quotaInfo.remainingQuota > useRunboxSessionEndWarning.QUOTA_ALMOST_END_MINUTES ? 'success.main' : 'warning.main';
146
+ var quotaBgColor = quotaInfo.remainingQuota > useRunboxSessionEndWarning.QUOTA_ALMOST_END_MINUTES ? undefined : 'warning.opacity03';
197
147
  return jsxRuntime.jsxs(material.Stack, {
198
148
  direction: "column",
199
149
  gap: "0.5rem",
@@ -205,15 +155,10 @@ var MaterialRunboxTimerDetailPopover = function MaterialRunboxTimerDetailPopover
205
155
  children: intl$1.formatMessage({
206
156
  id: 'runbox.timer.popover.quota.title'
207
157
  })
208
- }), jsxRuntime.jsxs(material.Typography, {
209
- variant: "body2",
210
- children: [jsxRuntime.jsxs(material.Stack, {
211
- component: "span",
212
- display: "inline-flex",
213
- direction: "row",
214
- gap: "0.25rem",
215
- children: [renderQuotaTimePart(remainingHours, 'hour', quotaColor), renderQuotaTimePart(remainingMinutes, 'minute', quotaColor)]
216
- }), [" / ", totalHours > 0 ? formatTimePart(totalHours, 'hour') : null, totalMinutes > 0 ? formatTimePart(totalMinutes, 'minute') : null].filter(Boolean).join(' ')]
158
+ }), jsxRuntime.jsx(MaterialRunboxQuotaAmount.default, {
159
+ remainingQuota: quotaInfo.remainingQuota,
160
+ quota: quotaInfo.quota,
161
+ color: quotaColor
217
162
  })]
218
163
  });
219
164
  };
@@ -232,14 +177,8 @@ var MaterialRunboxTimerDetailPopover = function MaterialRunboxTimerDetailPopover
232
177
  })]
233
178
  });
234
179
  }
235
- var _getTimeParts3 = time.getTimeParts(quotaPerSessionInfo.remainingQuota * 60),
236
- remainingHours = _getTimeParts3.hours,
237
- remainingMinutes = _getTimeParts3.minutes;
238
- var _getTimeParts4 = time.getTimeParts(quotaPerSessionInfo.quota * 60),
239
- totalHours = _getTimeParts4.hours,
240
- totalMinutes = _getTimeParts4.minutes;
241
- var perSessionColor = quotaPerSessionInfo.remainingQuota > QUOTA_PER_SESSION_ALMOST_END_MINUTES ? 'success.main' : 'warning.main';
242
- var perSessionBgColor = quotaPerSessionInfo.remainingQuota > QUOTA_PER_SESSION_ALMOST_END_MINUTES ? undefined : 'warning.opacity03';
180
+ var perSessionColor = quotaPerSessionInfo.remainingQuota > useRunboxSessionEndWarning.QUOTA_PER_SESSION_ALMOST_END_MINUTES ? 'success.main' : 'warning.main';
181
+ var perSessionBgColor = quotaPerSessionInfo.remainingQuota > useRunboxSessionEndWarning.QUOTA_PER_SESSION_ALMOST_END_MINUTES ? undefined : 'warning.opacity03';
243
182
  return jsxRuntime.jsxs(material.Stack, {
244
183
  direction: "column",
245
184
  gap: "0.5rem",
@@ -251,22 +190,21 @@ var MaterialRunboxTimerDetailPopover = function MaterialRunboxTimerDetailPopover
251
190
  children: intl$1.formatMessage({
252
191
  id: 'runbox.timer.popover.quota_per_session.title'
253
192
  })
254
- }), jsxRuntime.jsxs(material.Typography, {
255
- variant: "body2",
256
- children: [jsxRuntime.jsxs(material.Stack, {
257
- component: "span",
258
- display: "inline-flex",
259
- direction: "row",
260
- gap: "0.25rem",
261
- children: [renderQuotaTimePart(remainingHours, 'hour', perSessionColor), renderQuotaTimePart(remainingMinutes, 'minute', perSessionColor)]
262
- }), [" / ", totalHours > 0 ? formatTimePart(totalHours, 'hour') : null, totalMinutes > 0 ? formatTimePart(totalMinutes, 'minute') : null].filter(Boolean).join(' ')]
193
+ }), jsxRuntime.jsx(MaterialRunboxQuotaAmount.default, {
194
+ remainingQuota: quotaPerSessionInfo.remainingQuota,
195
+ quota: quotaPerSessionInfo.quota,
196
+ color: perSessionColor
263
197
  }), jsxRuntime.jsx(material.Typography, {
264
198
  variant: "body2",
265
199
  color: "text.tertiary",
266
200
  children: intl$1.formatMessage({
267
201
  id: 'runbox.timer.popover.quota_per_session.description'
268
202
  }, {
269
- time: formatTimePart(quotaPerSessionInfo.quota, 'minute')
203
+ time: intl$1.formatNumber(quotaPerSessionInfo.quota, {
204
+ style: 'unit',
205
+ unit: 'minute',
206
+ unitDisplay: 'short'
207
+ })
270
208
  })
271
209
  })]
272
210
  });
@@ -11,7 +11,6 @@ import { useQuery } from '@tanstack/react-query';
11
11
  import MaterialAdminRunboxConfirmDialog from './MaterialAdminRunboxConfirmDialog.js';
12
12
  import MaterialRunboxAlert from './MaterialRunboxAlert.js';
13
13
  import MaterialRunboxBody from './MaterialRunboxBody.js';
14
- import MaterialRunboxFooter from './MaterialRunboxFooter.js';
15
14
  import MaterialRunboxHeader from './MaterialRunboxHeader.js';
16
15
  import { useMaterialRunboxContext } from './contexts/MaterialRunboxContext.js';
17
16
  import { useMaterialRunboxApiContext } from './contexts/MaterialRunboxApiContext.js';
@@ -283,7 +282,7 @@ var MaterialRunboxContent = function MaterialRunboxContent(_ref) {
283
282
  isTutoring: isTutoring
284
283
  }), jsx(MaterialRunboxBody, Object.assign({
285
284
  setSnackbarRoot: setSnackbarRoot
286
- }, props)), jsx(MaterialRunboxFooter, Object.assign({}, props))]
285
+ }, props))]
287
286
  })
288
287
  })
289
288
  })
@@ -9,16 +9,15 @@ import { Tag, EliceIcon } from '@elice/mui-elements';
9
9
  import { useEliceRunboxRunning } from '@elice/runbox-client';
10
10
  import { enums } from '@elice/types';
11
11
  import { faEllipsisVertical } from '@fortawesome/pro-solid-svg-icons';
12
- import { Box, Stack, Button } from '@mui/material';
12
+ import { Stack, Button } from '@mui/material';
13
13
  import { useQuery } from '@tanstack/react-query';
14
- import MaterialRunboxActionAutoShutdown from './actions/MaterialRunboxActionAutoShutdown.js';
15
14
  import MaterialRunboxActionDisconnect from './actions/MaterialRunboxActionDisconnect.js';
16
15
  import MaterialRunboxActionGrade from './actions/MaterialRunboxActionGrade.js';
17
16
  import MaterialRunboxActionMenu from './actions/MaterialRunboxActionMenu.js';
18
- import img from '../../assets/runbox_logo.png.js';
19
17
  import { useMaterialRunboxContext } from './contexts/MaterialRunboxContext.js';
20
18
  import { useMaterialRunboxApiContext } from './contexts/MaterialRunboxApiContext.js';
21
19
  import MaterialRunboxTimer from './timer/MaterialRunboxTimer.js';
20
+ import MaterialRunboxStatusButton from './status/MaterialRunboxStatusButton.js';
22
21
  import MaterialRunboxDiskAlmostFullSnackbar from './disk/MaterialRunboxDiskAlmostFullSnackbar.js';
23
22
  import { useRunboxControl } from './hooks/useRunboxControl.js';
24
23
 
@@ -138,20 +137,11 @@ var MaterialRunboxHeader = function MaterialRunboxHeader(_ref3) {
138
137
  });
139
138
  };
140
139
  /**
141
- *
140
+ * Whether the auto-shutdown toggle is available.
141
+ * The toggle itself lives in the option menu. (PLAT-4181)
142
142
  */
143
- var renderHeaderActionAutoShutdown = function renderHeaderActionAutoShutdown() {
144
- var isAidtOrg = (organization === null || organization === void 0 ? void 0 : organization.organizationType) === enums.OrganizationType.Aidt;
145
- if (!enableAutoShutdownToggle || isTutoring || isAidtOrg) {
146
- return null;
147
- }
148
- return jsx(MaterialRunboxActionAutoShutdown, {
149
- runtime: runtime,
150
- runtimeTemplate: runtimeTemplate,
151
- courseId: courseId,
152
- refetch: refetch
153
- });
154
- };
143
+ var isAidtOrg = (organization === null || organization === void 0 ? void 0 : organization.organizationType) === enums.OrganizationType.Aidt;
144
+ var enableAutoShutdown = Boolean(enableAutoShutdownToggle) && !isTutoring && !isAidtOrg;
155
145
  /**
156
146
  *
157
147
  */
@@ -192,9 +182,11 @@ var MaterialRunboxHeader = function MaterialRunboxHeader(_ref3) {
192
182
  }), jsx(MaterialRunboxActionMenu, {
193
183
  runbox: runbox,
194
184
  runtime: runtime,
185
+ runtimeTemplate: runtimeTemplate,
195
186
  courseId: courseId,
196
187
  studentUserId: studentUserId,
197
188
  isTutoring: isTutoring,
189
+ enableAutoShutdown: enableAutoShutdown,
198
190
  menuAnchorEl: menuAnchorEl,
199
191
  refetch: refetch,
200
192
  handleMenuClose: handleMenuClose,
@@ -218,30 +210,21 @@ var MaterialRunboxHeader = function MaterialRunboxHeader(_ref3) {
218
210
  //
219
211
  return jsxs(StyledHeader, {
220
212
  ref: headerRef,
221
- children: [jsx(Box, {
222
- component: "img",
223
- src: img,
224
- alt: "elice runbox",
225
- sx: {
226
- width: 'auto',
227
- height: '100%',
228
- imageRendering: 'auto',
229
- padding: '0.465rem 0'
230
- }
231
- }), runtime ? jsx(MaterialRunboxTimer, {
213
+ children: [runtime ? jsx(MaterialRunboxTimer, {
232
214
  runboxId: runbox.id,
233
215
  userId: userId,
234
216
  headerElement: headerRef.current,
235
217
  stopRuntime: stopRuntime,
236
- hideTimerPopover: hideTimerPopover
237
- }) : null, jsx(MaterialRunboxDiskAlmostFullSnackbar, {
218
+ hideTimerPopover: hideTimerPopover,
219
+ isTutoring: isTutoring
220
+ }) : null, jsx(MaterialRunboxStatusButton, {}), jsx(MaterialRunboxDiskAlmostFullSnackbar, {
238
221
  runboxId: runbox.id
239
222
  }), jsxs(Stack, {
240
223
  direction: "row",
241
224
  alignItems: "center",
242
225
  gap: "0.5rem",
243
226
  marginLeft: "auto",
244
- children: [renderHeaderSubmitInfo(), renderHeaderActionAutoShutdown(), renderOptionMenu(), renderHeaderActionDisconnect(), renderHeaderActionGrade()]
227
+ children: [renderHeaderSubmitInfo(), renderOptionMenu(), renderHeaderActionDisconnect(), renderHeaderActionGrade()]
245
228
  })]
246
229
  });
247
230
  };
@@ -1,7 +1,9 @@
1
1
  import React from 'react';
2
2
  import type { RuntimeProps } from '../runtime/Runtime';
3
- type MaterialRunboxActionMenuProps = Pick<RuntimeProps, 'runbox' | 'runtime' | 'courseId' | 'refetch' | 'studentUserId' | 'isTutoring' | 'getAchievementColor'> & {
3
+ type MaterialRunboxActionMenuProps = Pick<RuntimeProps, 'runbox' | 'runtime' | 'runtimeTemplate' | 'courseId' | 'refetch' | 'studentUserId' | 'isTutoring' | 'getAchievementColor'> & {
4
4
  menuAnchorEl: null | HTMLButtonElement;
5
+ /** Whether the auto-shutdown toggle is available. Decided by the header. */
6
+ enableAutoShutdown?: boolean;
5
7
  handleMenuClose: () => void;
6
8
  };
7
9
  declare const MaterialRunboxActionMenu: React.FC<MaterialRunboxActionMenuProps>;
@@ -1,11 +1,12 @@
1
1
  import { asyncToGenerator as _asyncToGenerator, regenerator as _regenerator } from '../../../_virtual/_rollupPluginBabelHelpers.js';
2
- import { jsxs, jsx } from 'react/jsx-runtime';
2
+ import { jsxs, Fragment, jsx } from 'react/jsx-runtime';
3
3
  import React from 'react';
4
4
  import { getOrgCourseGet } from '@elice/api-client';
5
5
  import { useEliceRunboxRunning } from '@elice/runbox-client';
6
6
  import { enums } from '@elice/types';
7
- import { Menu } from '@mui/material';
7
+ import { Menu, Stack, Divider } from '@mui/material';
8
8
  import { useQuery } from '@tanstack/react-query';
9
+ import MaterialRunboxActionAutoShutdown from './MaterialRunboxActionAutoShutdown.js';
9
10
  import MaterialRunboxActionReset from './MaterialRunboxActionReset.js';
10
11
  import MaterialRunboxActionRestart from './MaterialRunboxActionRestart.js';
11
12
  import MaterialRunboxActionShare from './MaterialRunboxActionShare.js';
@@ -17,9 +18,12 @@ import MaterialRunboxActionSubmitLog from './MaterialRunboxActionSubmitLog.js';
17
18
  var MaterialRunboxActionMenu = function MaterialRunboxActionMenu(_ref) {
18
19
  var runbox = _ref.runbox,
19
20
  runtime = _ref.runtime,
21
+ runtimeTemplate = _ref.runtimeTemplate,
20
22
  courseId = _ref.courseId,
21
23
  studentUserId = _ref.studentUserId,
22
24
  isTutoring = _ref.isTutoring,
25
+ _ref$enableAutoShutdo = _ref.enableAutoShutdown,
26
+ enableAutoShutdown = _ref$enableAutoShutdo === void 0 ? false : _ref$enableAutoShutdo,
23
27
  menuAnchorEl = _ref.menuAnchorEl,
24
28
  refetch = _ref.refetch,
25
29
  getAchievementColor = _ref.getAchievementColor,
@@ -80,7 +84,19 @@ var MaterialRunboxActionMenu = function MaterialRunboxActionMenu(_ref) {
80
84
  horizontal: 'right'
81
85
  },
82
86
  onClose: handleMenuClose,
83
- children: [jsx(MaterialRunboxActionShare, {
87
+ children: [enableAutoShutdown ? jsxs(Fragment, {
88
+ children: [jsx(Stack, {
89
+ direction: "row",
90
+ alignItems: "center",
91
+ padding: "0.25rem 1rem",
92
+ children: jsx(MaterialRunboxActionAutoShutdown, {
93
+ runtime: runtime,
94
+ runtimeTemplate: runtimeTemplate,
95
+ courseId: courseId,
96
+ refetch: refetch
97
+ })
98
+ }), jsx(Divider, {})]
99
+ }) : null, jsx(MaterialRunboxActionShare, {
84
100
  handleMenuClose: handleMenuClose
85
101
  }), jsx(MaterialRunboxActionRestart, {
86
102
  runbox: runbox,
@@ -1,4 +1,6 @@
1
1
  export * from './useRunboxControl';
2
+ export * from './useRunboxSessionEndWarning';
2
3
  export * from './useRunboxTimer';
3
4
  export * from './useInfiniteRunboxRunboxIdGrade';
4
5
  export * from './useMaterialRunboxRunboxIdStarterGet';
6
+ export * from './useOnlineState';
@@ -1,4 +1,6 @@
1
1
  export { RunboxPreCheckResultType, useRunboxControl } from './useRunboxControl.js';
2
+ export { QUOTA_ALMOST_END_MINUTES, QUOTA_PER_SESSION_ALMOST_END_MINUTES, useRunboxSessionEndWarning } from './useRunboxSessionEndWarning.js';
2
3
  export { useRunboxTimer } from './useRunboxTimer.js';
3
4
  export { useInfiniteRunboxRunboxIdGrade } from './useInfiniteRunboxRunboxIdGrade.js';
4
5
  export { useMaterialRunboxRunboxIdStarterGet } from './useMaterialRunboxRunboxIdStarterGet.js';
6
+ export { useOnlineState } from './useOnlineState.js';
@@ -0,0 +1,12 @@
1
+ /**
2
+ * Whether the browser currently has a network connection.
3
+ *
4
+ * NOTICE: this deliberately does not use `react-use`'s `useNetworkState`.
5
+ * That hook only exists in react-use v17, and consumers of this package do not
6
+ * agree on the major — elice-web still resolves v13, which breaks the build at
7
+ * link time. Reading `navigator.onLine` keeps this working on both.
8
+ *
9
+ * `undefined` means "not known yet" (server render, or no `navigator`), which
10
+ * callers should treat as online rather than as offline.
11
+ */
12
+ export declare const useOnlineState: () => boolean | undefined;