@elice/material-exercise 1.250529.1 → 1.250602.0

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.
@@ -72,7 +72,7 @@ export declare const exerciseWebsocketQuery: (param: AtomWebSocketStateKey) => i
72
72
  /**
73
73
  * Check all necessary websockets and return the status.
74
74
  */
75
- export declare const exerciseWebSocketTotalStatusQuery: import("recoil").RecoilValueReadOnly<number>;
75
+ export declare const exerciseWebSocketTotalStatusQuery: (param: AtomWebSocketStateKey[]) => import("recoil").RecoilValueReadOnly<number>;
76
76
  /**
77
77
  *
78
78
  */
@@ -491,27 +491,31 @@ var exerciseWebsocketQuery = recoil.selectorFamily({
491
491
  /**
492
492
  * Check all necessary websockets and return the status.
493
493
  */
494
- var exerciseWebSocketTotalStatusQuery = recoil.selector({
494
+ var exerciseWebSocketTotalStatusQuery = recoil.selectorFamily({
495
495
  key: "".concat(KEY_PREFIX, "/Websocket/TotalStatus"),
496
- get: function get(_ref21) {
497
- var _get = _ref21.get;
498
- var states = Object.freeze([_get(exerciseWebsocketStates).usercodeEdit, _get(exerciseWebsocketStates).runnerRoom, _get(exerciseWebsocketStates).stdio]);
499
- switch (true) {
500
- case states.every(function (state) {
501
- return state === websocket.EliceWebSocket.OPEN;
502
- }):
503
- return websocket.EliceWebSocket.OPEN;
504
- case states.every(function (state) {
505
- return state === websocket.EliceWebSocket.CLOSED;
506
- }):
507
- return websocket.EliceWebSocket.CLOSED;
508
- case states.every(function (state) {
509
- return state === websocket.EliceWebSocket.CLOSING;
510
- }):
511
- return websocket.EliceWebSocket.CLOSING;
512
- default:
513
- return websocket.EliceWebSocket.CONNECTING;
514
- }
496
+ get: function get(keys) {
497
+ return function (_ref21) {
498
+ var get = _ref21.get;
499
+ var states = Object.freeze(keys.map(function (key) {
500
+ return get(exerciseWebsocketStates)[key];
501
+ }));
502
+ switch (true) {
503
+ case states.every(function (state) {
504
+ return state === websocket.EliceWebSocket.OPEN;
505
+ }):
506
+ return websocket.EliceWebSocket.OPEN;
507
+ case states.every(function (state) {
508
+ return state === websocket.EliceWebSocket.CLOSED;
509
+ }):
510
+ return websocket.EliceWebSocket.CLOSED;
511
+ case states.every(function (state) {
512
+ return state === websocket.EliceWebSocket.CLOSING;
513
+ }):
514
+ return websocket.EliceWebSocket.CLOSING;
515
+ default:
516
+ return websocket.EliceWebSocket.CONNECTING;
517
+ }
518
+ };
515
519
  }
516
520
  });
517
521
  //
@@ -374,9 +374,11 @@ var ExerciseFileEditor = function ExerciseFileEditor() {
374
374
  return;
375
375
  }
376
376
  var content = model.getValue();
377
- var _wsUsercode$sendOTs = wsUsercode.sendOTs([{
377
+ var _wsUsercode$sendOTs = wsUsercode.sendOTs(
378
+ // ot-text-unicode doesn't accept empty deletion. So we fallback to no-op when content = "".
379
+ content.length > 0 ? [{
378
380
  d: content
379
- }, content]),
381
+ }, content] : []),
380
382
  requestId = _wsUsercode$sendOTs.requestId;
381
383
  usercodeSyncRequestsRef.current.set(requestId, request);
382
384
  });
@@ -9,11 +9,23 @@ var types = require('@elice/types');
9
9
  var recoil = require('recoil');
10
10
  var styled = require('styled-components');
11
11
  var stylesheets = require('../../../constants/stylesheets.js');
12
+ require('react-use');
13
+ require('socket.io-client');
12
14
  var recoil$1 = require('../context/recoil.js');
13
15
  var context = require('../context/context.js');
14
16
  require('../context/recoilTypes.js');
15
17
  require('../context/subjects.js');
16
18
  require('../context/ExerciseProvider.js');
19
+ require('../../../constants/arduino.js');
20
+ var useExerciseFile = require('../../../hooks/useExerciseFile.js');
21
+ require('@elice/api-client');
22
+ require('@elice/material-shared-utils');
23
+ require('@elice/websocket');
24
+ require('humps');
25
+ require('ot-text-unicode');
26
+ require('lodash/debounce');
27
+ require('random-words');
28
+ require('unicount');
17
29
  var ExerciseRunnerControllerArduinoAgentModal = require('./ExerciseRunnerControllerArduinoAgentModal.js');
18
30
  var ExerciseRunnerControllerArduinoStatusMessage = require('./ExerciseRunnerControllerArduinoStatusMessage.js');
19
31
  var ExerciseRunnerControllerButtonGroup = require('./ExerciseRunnerControllerButtonGroup.js');
@@ -35,17 +47,19 @@ var ExerciseRunnerController = function ExerciseRunnerController() {
35
47
  materialExerciseId = _React$useContext.materialExerciseId;
36
48
  var exercise = recoil.useRecoilValue(recoil$1.exerciseState(materialExerciseId));
37
49
  var isArduinoExercise = (exercise === null || exercise === void 0 ? void 0 : exercise.envType) === types.enums.ExerciseEnvType.Arduino;
50
+ var activeFilename = recoil.useRecoilValue(recoil$1.exerciseActiveFilenameState);
51
+ var isFileEditable = useExerciseFile.useExerciseFileEditable(activeFilename);
38
52
  return jsxRuntime.jsxs(StyledController, {
39
53
  children: [jsxRuntime.jsxs(blocks.Flex, {
40
54
  align: "center",
41
55
  children: [jsxRuntime.jsx(ExerciseRunnerControllerButtonGroup.default, {}), jsxRuntime.jsx(blocks.Hspace, {
42
56
  width: 1
43
57
  }), jsxRuntime.jsx(ExerciseRunnerControllerRunningInfo.default, {}), jsxRuntime.jsx(ExerciseRunnerControllerTimer.default, {})]
44
- }), jsxRuntime.jsxs(blocks.Flex, {
58
+ }), isFileEditable ? jsxRuntime.jsxs(blocks.Flex, {
45
59
  column: true,
46
60
  align: "flex-end",
47
61
  children: [jsxRuntime.jsx(ExerciseRunnerControllerStatusMessage.default, {}), isArduinoExercise ? jsxRuntime.jsx(ExerciseRunnerControllerArduinoStatusMessage.default, {}) : null]
48
- }), isArduinoExercise ? jsxRuntime.jsx(ExerciseRunnerControllerArduinoAgentModal.default, {}) : null]
62
+ }) : null, isArduinoExercise ? jsxRuntime.jsx(ExerciseRunnerControllerArduinoAgentModal.default, {}) : null]
49
63
  });
50
64
  };
51
65
 
@@ -2,6 +2,7 @@
2
2
 
3
3
  Object.defineProperty(exports, '__esModule', { value: true });
4
4
 
5
+ var _rollupPluginBabelHelpers = require('../../../_virtual/_rollupPluginBabelHelpers.js');
5
6
  var jsxRuntime = require('react/jsx-runtime');
6
7
  var React = require('react');
7
8
  var blocks = require('@elice/blocks');
@@ -19,6 +20,7 @@ require('../context/recoilTypes.js');
19
20
  var subjects = require('../context/subjects.js');
20
21
  require('../context/ExerciseProvider.js');
21
22
  require('../../../constants/arduino.js');
23
+ var useExerciseFile = require('../../../hooks/useExerciseFile.js');
22
24
  var useExericseShortcut = require('../../../hooks/useExericseShortcut.js');
23
25
  require('@elice/api-client');
24
26
  require('@elice/material-shared-utils');
@@ -52,7 +54,9 @@ var ExerciseRunnerControllerButtonGroup = function ExerciseRunnerControllerButto
52
54
  onSubmit = _React$useContext2.onSubmit,
53
55
  onSyncRequest = _React$useContext2.onSyncRequest,
54
56
  onCancel = _React$useContext2.onCancel;
55
- var runnerWebsocketStatus = recoil.useRecoilValue(recoil$1.exerciseWebSocketTotalStatusQuery);
57
+ var activeFilename = recoil.useRecoilValue(recoil$1.exerciseActiveFilenameState);
58
+ var isFileEditable = useExerciseFile.useExerciseFileEditable(activeFilename);
59
+ var runnerWebsocketStatus = recoil.useRecoilValue(recoil$1.exerciseWebSocketTotalStatusQuery([].concat(_rollupPluginBabelHelpers.toConsumableArray(isFileEditable ? ['usercodeEdit'] : []), ['runnerRoom', 'stdio'])));
56
60
  var exercise = recoil.useRecoilValue(recoil$1.exerciseState(materialExerciseId));
57
61
  var exerciseRunType = recoil.useRecoilValue(recoil$1.exerciseRunnerRunTypeState);
58
62
  var exerciseWithNoGrade = Boolean(exercise === null || exercise === void 0 ? void 0 : exercise.isNoSubmitGrade);
@@ -26,7 +26,7 @@ var StyledMessageWrapper = styled__default.default(blocks.Flex).withConfig({
26
26
  })(["height:1rem;"]);
27
27
  var ExerciseRunnerControllerStatusMessage = function ExerciseRunnerControllerStatusMessage() {
28
28
  var intl$1 = intl.useRawEliceIntl();
29
- var websocketStatus = recoil.useRecoilValue(recoil$1.exerciseWebSocketTotalStatusQuery);
29
+ var websocketStatus = recoil.useRecoilValue(recoil$1.exerciseWebSocketTotalStatusQuery(['usercodeEdit', 'runnerRoom', 'stdio']));
30
30
  var _useState = React.useState(false),
31
31
  _useState2 = _rollupPluginBabelHelpers.slicedToArray(_useState, 2),
32
32
  isOpenedOnce = _useState2[0],
@@ -72,7 +72,7 @@ export declare const exerciseWebsocketQuery: (param: AtomWebSocketStateKey) => i
72
72
  /**
73
73
  * Check all necessary websockets and return the status.
74
74
  */
75
- export declare const exerciseWebSocketTotalStatusQuery: import("recoil").RecoilValueReadOnly<number>;
75
+ export declare const exerciseWebSocketTotalStatusQuery: (param: AtomWebSocketStateKey[]) => import("recoil").RecoilValueReadOnly<number>;
76
76
  /**
77
77
  *
78
78
  */
@@ -4,7 +4,7 @@ import { enums } from '@elice/types';
4
4
  import { EliceWebSocket } from '@elice/websocket';
5
5
  import { camelizeKeys } from 'humps';
6
6
  import isEqual from 'lodash/isEqual';
7
- import { atomFamily, atom, selectorFamily, selector } from 'recoil';
7
+ import { atomFamily, atom, selectorFamily } from 'recoil';
8
8
  import '../../shared/monaco-editor/MonacoEditorLazy.js';
9
9
  import '../../shared/monaco-editor/MonacoEditorPerferenceForm.js';
10
10
  import 'monaco-editor/esm/vs/editor/editor.api';
@@ -485,27 +485,31 @@ var exerciseWebsocketQuery = selectorFamily({
485
485
  /**
486
486
  * Check all necessary websockets and return the status.
487
487
  */
488
- var exerciseWebSocketTotalStatusQuery = selector({
488
+ var exerciseWebSocketTotalStatusQuery = selectorFamily({
489
489
  key: "".concat(KEY_PREFIX, "/Websocket/TotalStatus"),
490
- get: function get(_ref21) {
491
- var _get = _ref21.get;
492
- var states = Object.freeze([_get(exerciseWebsocketStates).usercodeEdit, _get(exerciseWebsocketStates).runnerRoom, _get(exerciseWebsocketStates).stdio]);
493
- switch (true) {
494
- case states.every(function (state) {
495
- return state === EliceWebSocket.OPEN;
496
- }):
497
- return EliceWebSocket.OPEN;
498
- case states.every(function (state) {
499
- return state === EliceWebSocket.CLOSED;
500
- }):
501
- return EliceWebSocket.CLOSED;
502
- case states.every(function (state) {
503
- return state === EliceWebSocket.CLOSING;
504
- }):
505
- return EliceWebSocket.CLOSING;
506
- default:
507
- return EliceWebSocket.CONNECTING;
508
- }
490
+ get: function get(keys) {
491
+ return function (_ref21) {
492
+ var get = _ref21.get;
493
+ var states = Object.freeze(keys.map(function (key) {
494
+ return get(exerciseWebsocketStates)[key];
495
+ }));
496
+ switch (true) {
497
+ case states.every(function (state) {
498
+ return state === EliceWebSocket.OPEN;
499
+ }):
500
+ return EliceWebSocket.OPEN;
501
+ case states.every(function (state) {
502
+ return state === EliceWebSocket.CLOSED;
503
+ }):
504
+ return EliceWebSocket.CLOSED;
505
+ case states.every(function (state) {
506
+ return state === EliceWebSocket.CLOSING;
507
+ }):
508
+ return EliceWebSocket.CLOSING;
509
+ default:
510
+ return EliceWebSocket.CONNECTING;
511
+ }
512
+ };
509
513
  }
510
514
  });
511
515
  //
@@ -366,9 +366,11 @@ var ExerciseFileEditor = function ExerciseFileEditor() {
366
366
  return;
367
367
  }
368
368
  var content = model.getValue();
369
- var _wsUsercode$sendOTs = wsUsercode.sendOTs([{
369
+ var _wsUsercode$sendOTs = wsUsercode.sendOTs(
370
+ // ot-text-unicode doesn't accept empty deletion. So we fallback to no-op when content = "".
371
+ content.length > 0 ? [{
370
372
  d: content
371
- }, content]),
373
+ }, content] : []),
372
374
  requestId = _wsUsercode$sendOTs.requestId;
373
375
  usercodeSyncRequestsRef.current.set(requestId, request);
374
376
  });
@@ -5,11 +5,23 @@ import { enums } from '@elice/types';
5
5
  import { useRecoilValue } from 'recoil';
6
6
  import styled from 'styled-components';
7
7
  import { MATERIAL_DIVIDER_BORDER_VALUE } from '../../../constants/stylesheets.js';
8
- import { exerciseState } from '../context/recoil.js';
8
+ import 'react-use';
9
+ import 'socket.io-client';
10
+ import { exerciseState, exerciseActiveFilenameState } from '../context/recoil.js';
9
11
  import { ExerciseContext } from '../context/context.js';
10
12
  import '../context/recoilTypes.js';
11
13
  import '../context/subjects.js';
12
14
  import '../context/ExerciseProvider.js';
15
+ import '../../../constants/arduino.js';
16
+ import { useExerciseFileEditable } from '../../../hooks/useExerciseFile.js';
17
+ import '@elice/api-client';
18
+ import '@elice/material-shared-utils';
19
+ import '@elice/websocket';
20
+ import 'humps';
21
+ import 'ot-text-unicode';
22
+ import 'lodash/debounce';
23
+ import 'random-words';
24
+ import 'unicount';
13
25
  import ExerciseRunnerControllerArduinoAgentModal from './ExerciseRunnerControllerArduinoAgentModal.js';
14
26
  import ExerciseRunnerControllerArduinoStatusMessage from './ExerciseRunnerControllerArduinoStatusMessage.js';
15
27
  import ExerciseRunnerControllerButtonGroup from './ExerciseRunnerControllerButtonGroup.js';
@@ -26,17 +38,19 @@ var ExerciseRunnerController = function ExerciseRunnerController() {
26
38
  materialExerciseId = _React$useContext.materialExerciseId;
27
39
  var exercise = useRecoilValue(exerciseState(materialExerciseId));
28
40
  var isArduinoExercise = (exercise === null || exercise === void 0 ? void 0 : exercise.envType) === enums.ExerciseEnvType.Arduino;
41
+ var activeFilename = useRecoilValue(exerciseActiveFilenameState);
42
+ var isFileEditable = useExerciseFileEditable(activeFilename);
29
43
  return jsxs(StyledController, {
30
44
  children: [jsxs(Flex, {
31
45
  align: "center",
32
46
  children: [jsx(ExerciseRunnerControllerButtonGroup, {}), jsx(Hspace, {
33
47
  width: 1
34
48
  }), jsx(ExerciseRunnerControllerRunningInfo, {}), jsx(ExerciseRunnerControllerTimer, {})]
35
- }), jsxs(Flex, {
49
+ }), isFileEditable ? jsxs(Flex, {
36
50
  column: true,
37
51
  align: "flex-end",
38
52
  children: [jsx(ExerciseRunnerControllerStatusMessage, {}), isArduinoExercise ? jsx(ExerciseRunnerControllerArduinoStatusMessage, {}) : null]
39
- }), isArduinoExercise ? jsx(ExerciseRunnerControllerArduinoAgentModal, {}) : null]
53
+ }) : null, isArduinoExercise ? jsx(ExerciseRunnerControllerArduinoAgentModal, {}) : null]
40
54
  });
41
55
  };
42
56
 
@@ -1,3 +1,4 @@
1
+ import { toConsumableArray as _toConsumableArray } from '../../../_virtual/_rollupPluginBabelHelpers.js';
1
2
  import { jsxs, jsx } from 'react/jsx-runtime';
2
3
  import React from 'react';
3
4
  import { Button, Tooltip } from '@elice/blocks';
@@ -9,12 +10,13 @@ import { useRecoilValue } from 'recoil';
9
10
  import styled from 'styled-components';
10
11
  import 'react-use';
11
12
  import 'socket.io-client';
12
- import { exerciseWebSocketTotalStatusQuery, exerciseState, exerciseRunnerRunTypeState, exerciseLectureState, exerciseRunnerSubmittingState, exerciseRunnerRunningState, exerciseArduinoUploadProgressState, exerciseArduinoOpenedPortNameState } from '../context/recoil.js';
13
+ import { exerciseActiveFilenameState, exerciseWebSocketTotalStatusQuery, exerciseState, exerciseRunnerRunTypeState, exerciseLectureState, exerciseRunnerSubmittingState, exerciseRunnerRunningState, exerciseArduinoUploadProgressState, exerciseArduinoOpenedPortNameState } from '../context/recoil.js';
13
14
  import { ExerciseContext } from '../context/context.js';
14
15
  import '../context/recoilTypes.js';
15
16
  import { exerciseFileEditorSaveAction$ } from '../context/subjects.js';
16
17
  import '../context/ExerciseProvider.js';
17
18
  import '../../../constants/arduino.js';
19
+ import { useExerciseFileEditable } from '../../../hooks/useExerciseFile.js';
18
20
  import { useExericseShortcut } from '../../../hooks/useExericseShortcut.js';
19
21
  import '@elice/api-client';
20
22
  import '@elice/material-shared-utils';
@@ -43,7 +45,9 @@ var ExerciseRunnerControllerButtonGroup = function ExerciseRunnerControllerButto
43
45
  onSubmit = _React$useContext2.onSubmit,
44
46
  onSyncRequest = _React$useContext2.onSyncRequest,
45
47
  onCancel = _React$useContext2.onCancel;
46
- var runnerWebsocketStatus = useRecoilValue(exerciseWebSocketTotalStatusQuery);
48
+ var activeFilename = useRecoilValue(exerciseActiveFilenameState);
49
+ var isFileEditable = useExerciseFileEditable(activeFilename);
50
+ var runnerWebsocketStatus = useRecoilValue(exerciseWebSocketTotalStatusQuery([].concat(_toConsumableArray(isFileEditable ? ['usercodeEdit'] : []), ['runnerRoom', 'stdio'])));
47
51
  var exercise = useRecoilValue(exerciseState(materialExerciseId));
48
52
  var exerciseRunType = useRecoilValue(exerciseRunnerRunTypeState);
49
53
  var exerciseWithNoGrade = Boolean(exercise === null || exercise === void 0 ? void 0 : exercise.isNoSubmitGrade);
@@ -18,7 +18,7 @@ var StyledMessageWrapper = styled(Flex).withConfig({
18
18
  })(["height:1rem;"]);
19
19
  var ExerciseRunnerControllerStatusMessage = function ExerciseRunnerControllerStatusMessage() {
20
20
  var intl = useRawEliceIntl();
21
- var websocketStatus = useRecoilValue(exerciseWebSocketTotalStatusQuery);
21
+ var websocketStatus = useRecoilValue(exerciseWebSocketTotalStatusQuery(['usercodeEdit', 'runnerRoom', 'stdio']));
22
22
  var _useState = useState(false),
23
23
  _useState2 = _slicedToArray(_useState, 2),
24
24
  isOpenedOnce = _useState2[0],
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@elice/material-exercise",
3
- "version": "1.250529.1",
3
+ "version": "1.250602.0",
4
4
  "description": "User view and editing components of Elice material exercise",
5
5
  "repository": "https://git.elicer.io/elice/frontend/library/elice-material",
6
6
  "license": "UNLICENSED",
@@ -83,8 +83,8 @@
83
83
  "@elice/icons": "^1.230814.0",
84
84
  "@elice/intl": "0.241127.0",
85
85
  "@elice/markdown": "1.241015.0",
86
- "@elice/material-shared-types": "1.250529.1",
87
- "@elice/material-shared-utils": "1.250529.1",
86
+ "@elice/material-shared-types": "1.250602.0",
87
+ "@elice/material-shared-utils": "1.250602.0",
88
88
  "@elice/mui-elements": "^5.250108.0-controllabel.0",
89
89
  "@elice/mui-system": "^5.250108.0-controllabel.0",
90
90
  "@elice/types": "1.241220.0",