@datalayer/core 1.0.25 → 1.1.41

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 (339) hide show
  1. package/README.md +14 -26
  2. package/lib/api/index.d.ts +0 -9
  3. package/lib/api/index.js +0 -9
  4. package/lib/cli-login.js +167 -0
  5. package/lib/client/base.d.ts +0 -3
  6. package/lib/client/base.js +0 -2
  7. package/lib/client/index.d.ts +10 -98
  8. package/lib/client/index.js +12 -21
  9. package/lib/components/avatars/UserAvatar.d.ts +16 -0
  10. package/lib/components/avatars/UserAvatar.js +47 -0
  11. package/lib/components/avatars/index.d.ts +1 -0
  12. package/lib/components/avatars/index.js +1 -0
  13. package/lib/components/billing/BillableAccountSelect.js +4 -0
  14. package/lib/components/billing/index.js +4 -0
  15. package/lib/components/context/index.d.ts +0 -1
  16. package/lib/components/context/index.js +0 -1
  17. package/lib/components/display/DisplayHandle.d.ts +12 -0
  18. package/lib/components/display/DisplayHandle.js +11 -0
  19. package/lib/components/display/LiveRelativeTime.js +4 -0
  20. package/lib/components/display/index.d.ts +1 -0
  21. package/lib/components/display/index.js +1 -0
  22. package/lib/components/flashes/index.d.ts +0 -1
  23. package/lib/components/flashes/index.js +0 -1
  24. package/lib/components/index.d.ts +0 -1
  25. package/lib/components/index.js +0 -1
  26. package/lib/components/principal/Principal.d.ts +7 -0
  27. package/lib/components/principal/Principal.js +153 -16
  28. package/lib/components/principal/PrincipalAvatar.d.ts +1 -1
  29. package/lib/components/principal/PrincipalAvatar.js +4 -28
  30. package/lib/components/principal/PrincipalBadge.js +4 -4
  31. package/lib/components/principal/PrincipalDetailsOverlay.d.ts +4 -2
  32. package/lib/components/principal/PrincipalDetailsOverlay.js +27 -7
  33. package/lib/components/principal/PrincipalSwitcherMenu.js +76 -39
  34. package/lib/components/progress/index.d.ts +0 -1
  35. package/lib/components/progress/index.js +0 -1
  36. package/lib/components/sharing/ShareAccessComponent.d.ts +3 -2
  37. package/lib/components/sharing/ShareAccessComponent.js +180 -133
  38. package/lib/components/sharing/SharingEditor.js +4 -0
  39. package/lib/components/snippets/index.d.ts +1 -1
  40. package/lib/components/snippets/index.js +1 -1
  41. package/lib/components/students/StudentResultCircle.d.ts +21 -0
  42. package/lib/components/students/StudentResultCircle.js +59 -0
  43. package/lib/components/students/index.d.ts +1 -1
  44. package/lib/components/students/index.js +1 -1
  45. package/lib/components/time/LiveRelativeTime.js +4 -0
  46. package/lib/components/time/index.js +4 -0
  47. package/lib/components/timeline/index.js +4 -0
  48. package/lib/components/tokens/index.d.ts +1 -1
  49. package/lib/components/tokens/index.js +1 -1
  50. package/lib/components/toolbars/index.d.ts +1 -3
  51. package/lib/components/toolbars/index.js +1 -3
  52. package/lib/hooks/cacheConverters.d.ts +21 -0
  53. package/lib/hooks/cacheConverters.js +110 -0
  54. package/lib/hooks/index.d.ts +0 -2
  55. package/lib/hooks/index.js +0 -2
  56. package/lib/hooks/useCache.d.ts +64 -35
  57. package/lib/hooks/useCache.js +407 -52
  58. package/lib/hooks/useDatalayer.js +3 -1
  59. package/lib/hooks/useIAM.js +1 -3
  60. package/lib/hooks/useLocationHandles.d.ts +3 -1
  61. package/lib/hooks/useLocationHandles.js +2 -1
  62. package/lib/hooks/usePrincipalStore.d.ts +2 -2
  63. package/lib/hooks/usePrincipalStore.js +97 -14
  64. package/lib/hooks/useSelectedPrincipal.js +1 -1
  65. package/lib/hooks/useUser.js +19 -2
  66. package/lib/index.d.ts +1 -6
  67. package/lib/index.js +1 -13
  68. package/lib/main.js +3 -3
  69. package/lib/mocks/index.js +1 -1
  70. package/lib/mocks/models/index.d.ts +0 -1
  71. package/lib/mocks/models/index.js +0 -1
  72. package/lib/models/Datasource.d.ts +2 -2
  73. package/lib/models/IAM.d.ts +1 -1
  74. package/lib/models/School.d.ts +12 -3
  75. package/lib/models/Secret.d.ts +2 -2
  76. package/lib/models/Student.d.ts +13 -3
  77. package/lib/models/Usage.d.ts +11 -1
  78. package/lib/models/UserDTO.d.ts +2 -2
  79. package/lib/models/index.d.ts +0 -30
  80. package/lib/models/index.js +0 -30
  81. package/lib/routes/index.d.ts +1 -0
  82. package/lib/routes/index.js +1 -0
  83. package/lib/routes/publicPaths.d.ts +23 -0
  84. package/lib/routes/publicPaths.js +74 -0
  85. package/lib/state/State.d.ts +0 -12
  86. package/lib/state/State.js +0 -12
  87. package/lib/state/substates/LayoutState.d.ts +12 -1
  88. package/lib/state/substates/index.d.ts +0 -7
  89. package/lib/state/substates/index.js +0 -7
  90. package/lib/utils/Handles.js +3 -1
  91. package/lib/utils/index.d.ts +0 -1
  92. package/lib/utils/index.js +0 -1
  93. package/lib/views/api-keys/APIKeys.js +12 -3
  94. package/lib/views/datasources/DatasourceDetail.d.ts +1 -1
  95. package/lib/views/datasources/DatasourceNew.d.ts +1 -1
  96. package/lib/views/datasources/Datasources.d.ts +1 -1
  97. package/lib/views/datasources/Datasources.js +12 -3
  98. package/lib/views/iam/SignInSimple.d.ts +37 -1
  99. package/lib/views/iam/SignInSimple.js +110 -12
  100. package/package.json +5 -3
  101. package/lib/App.css +0 -47
  102. package/lib/App.d.ts +0 -3
  103. package/lib/App.js +0 -21
  104. package/lib/api/runtimes/checkpoints.d.ts +0 -122
  105. package/lib/api/runtimes/checkpoints.js +0 -118
  106. package/lib/api/runtimes/environments.d.ts +0 -9
  107. package/lib/api/runtimes/environments.js +0 -29
  108. package/lib/api/runtimes/healthz.d.ts +0 -15
  109. package/lib/api/runtimes/healthz.js +0 -44
  110. package/lib/api/runtimes/index.d.ts +0 -12
  111. package/lib/api/runtimes/index.js +0 -16
  112. package/lib/api/runtimes/runtimes.d.ts +0 -138
  113. package/lib/api/runtimes/runtimes.js +0 -230
  114. package/lib/api/runtimes/snapshots.d.ts +0 -38
  115. package/lib/api/runtimes/snapshots.js +0 -82
  116. package/lib/api/scheduler/index.d.ts +0 -6
  117. package/lib/api/scheduler/index.js +0 -10
  118. package/lib/api/scheduler/schedules.d.ts +0 -85
  119. package/lib/api/scheduler/schedules.js +0 -78
  120. package/lib/api/spacer/documents.d.ts +0 -12
  121. package/lib/api/spacer/documents.js +0 -43
  122. package/lib/api/spacer/healthz.d.ts +0 -15
  123. package/lib/api/spacer/healthz.js +0 -44
  124. package/lib/api/spacer/index.d.ts +0 -15
  125. package/lib/api/spacer/index.js +0 -19
  126. package/lib/api/spacer/items.d.ts +0 -25
  127. package/lib/api/spacer/items.js +0 -55
  128. package/lib/api/spacer/lexicals.d.ts +0 -34
  129. package/lib/api/spacer/lexicals.js +0 -89
  130. package/lib/api/spacer/notebooks.d.ts +0 -34
  131. package/lib/api/spacer/notebooks.js +0 -89
  132. package/lib/api/spacer/spaces.d.ts +0 -84
  133. package/lib/api/spacer/spaces.js +0 -170
  134. package/lib/api/spacer/users.d.ts +0 -9
  135. package/lib/api/spacer/users.js +0 -29
  136. package/lib/client/mixins/RuntimesMixin.d.ts +0 -93
  137. package/lib/client/mixins/RuntimesMixin.js +0 -229
  138. package/lib/client/mixins/SpacerMixin.d.ts +0 -210
  139. package/lib/client/mixins/SpacerMixin.js +0 -615
  140. package/lib/client/utils/spacerUtils.d.ts +0 -18
  141. package/lib/client/utils/spacerUtils.js +0 -32
  142. package/lib/collaboration/DatalayerCollaboration.d.ts +0 -13
  143. package/lib/collaboration/DatalayerCollaboration.js +0 -28
  144. package/lib/collaboration/DatalayerCollaborationProvider.d.ts +0 -60
  145. package/lib/collaboration/DatalayerCollaborationProvider.js +0 -163
  146. package/lib/collaboration/index.d.ts +0 -2
  147. package/lib/collaboration/index.js +0 -6
  148. package/lib/components/context/SpaceSelect.d.ts +0 -2
  149. package/lib/components/context/SpaceSelect.js +0 -42
  150. package/lib/components/flashes/FlashDisclaimer.d.ts +0 -2
  151. package/lib/components/flashes/FlashDisclaimer.js +0 -17
  152. package/lib/components/icons/ArtifactIcon.d.ts +0 -10
  153. package/lib/components/icons/ArtifactIcon.js +0 -58
  154. package/lib/components/icons/index.d.ts +0 -1
  155. package/lib/components/icons/index.js +0 -5
  156. package/lib/components/nbgrader/NbGradesDetails.d.ts +0 -5
  157. package/lib/components/nbgrader/NbGradesDetails.js +0 -14
  158. package/lib/components/nbgrader/index.d.ts +0 -1
  159. package/lib/components/nbgrader/index.js +0 -5
  160. package/lib/components/progress/CreditsIndicator.d.ts +0 -33
  161. package/lib/components/progress/CreditsIndicator.js +0 -23
  162. package/lib/components/runtimes/RuntimeCellVariables.d.ts +0 -39
  163. package/lib/components/runtimes/RuntimeCellVariables.js +0 -172
  164. package/lib/components/runtimes/RuntimeCellVariablesDialog.d.ts +0 -37
  165. package/lib/components/runtimes/RuntimeCellVariablesDialog.js +0 -101
  166. package/lib/components/runtimes/RuntimeLauncherDialog.d.ts +0 -57
  167. package/lib/components/runtimes/RuntimeLauncherDialog.js +0 -275
  168. package/lib/components/runtimes/RuntimePickerBase.d.ts +0 -69
  169. package/lib/components/runtimes/RuntimePickerBase.js +0 -122
  170. package/lib/components/runtimes/RuntimePickerCell.d.ts +0 -34
  171. package/lib/components/runtimes/RuntimePickerCell.js +0 -104
  172. package/lib/components/runtimes/RuntimePickerNotebook.d.ts +0 -42
  173. package/lib/components/runtimes/RuntimePickerNotebook.js +0 -232
  174. package/lib/components/runtimes/RuntimeReservationControl.d.ts +0 -47
  175. package/lib/components/runtimes/RuntimeReservationControl.js +0 -42
  176. package/lib/components/runtimes/RuntimeSimplePicker.d.ts +0 -38
  177. package/lib/components/runtimes/RuntimeSimplePicker.js +0 -155
  178. package/lib/components/runtimes/RuntimeTransfer.d.ts +0 -16
  179. package/lib/components/runtimes/RuntimeTransfer.js +0 -5
  180. package/lib/components/runtimes/RuntimeUtils.d.ts +0 -17
  181. package/lib/components/runtimes/RuntimeUtils.js +0 -178
  182. package/lib/components/runtimes/RuntimeVariables.d.ts +0 -38
  183. package/lib/components/runtimes/RuntimeVariables.js +0 -75
  184. package/lib/components/runtimes/index.d.ts +0 -11
  185. package/lib/components/runtimes/index.js +0 -15
  186. package/lib/components/scheduler/ScheduleMenu.d.ts +0 -54
  187. package/lib/components/scheduler/ScheduleMenu.js +0 -154
  188. package/lib/components/scheduler/index.d.ts +0 -1
  189. package/lib/components/scheduler/index.js +0 -5
  190. package/lib/components/snapshots/SandboxSnapshotMenu.d.ts +0 -33
  191. package/lib/components/snapshots/SandboxSnapshotMenu.js +0 -169
  192. package/lib/components/snapshots/index.d.ts +0 -1
  193. package/lib/components/snapshots/index.js +0 -5
  194. package/lib/components/snippets/SnippetDialog.d.ts +0 -42
  195. package/lib/components/snippets/SnippetDialog.js +0 -42
  196. package/lib/components/students/StudentItemStatus.d.ts +0 -7
  197. package/lib/components/students/StudentItemStatus.js +0 -66
  198. package/lib/components/tokens/SpaceVariantToken.d.ts +0 -5
  199. package/lib/components/tokens/SpaceVariantToken.js +0 -23
  200. package/lib/components/toolbars/AssignmentEditorToolbar.d.ts +0 -4
  201. package/lib/components/toolbars/AssignmentEditorToolbar.js +0 -18
  202. package/lib/components/toolbars/DocumentEditorToolbar.d.ts +0 -2
  203. package/lib/components/toolbars/DocumentEditorToolbar.js +0 -12
  204. package/lib/components/toolbars/NotebookEditorToolbar.d.ts +0 -29
  205. package/lib/components/toolbars/NotebookEditorToolbar.js +0 -30
  206. package/lib/examples/CellExample.d.ts +0 -6
  207. package/lib/examples/CellExample.js +0 -20
  208. package/lib/examples/NotebookExample.d.ts +0 -6
  209. package/lib/examples/NotebookExample.js +0 -19
  210. package/lib/examples/lexical-theme.css +0 -436
  211. package/lib/examples/notebooks/IPyWidgetsExample.ipynb.json +0 -101
  212. package/lib/examples/notebooks/IPyWidgetsExampleWithState.ipynb.json +0 -112
  213. package/lib/examples/notebooks/Lite.ipynb.json +0 -128
  214. package/lib/examples/notebooks/Matplotlib.ipynb.json +0 -137
  215. package/lib/examples/notebooks/NotebookExample1.ipynb.json +0 -126
  216. package/lib/examples/notebooks/NotebookExample2.ipynb.json +0 -48
  217. package/lib/examples/notebooks/NotebookOutputs.ipynb.json +0 -49
  218. package/lib/examples/notebooks/NotebookToCExample.ipynb.json +0 -102
  219. package/lib/examples/notebooks/PyGWalker.ipynb.json +0 -55
  220. package/lib/hooks/useCellOutputshot.d.ts +0 -4
  221. package/lib/hooks/useCellOutputshot.js +0 -25
  222. package/lib/hooks/useProjects.d.ts +0 -628
  223. package/lib/hooks/useProjects.js +0 -190
  224. package/lib/hooks/useRuntimes.d.ts +0 -5
  225. package/lib/hooks/useRuntimes.js +0 -34
  226. package/lib/mocks/jupyter/index.js +0 -5
  227. package/lib/mocks/models/CourseMock.d.ts +0 -6
  228. package/lib/mocks/models/CourseMock.js +0 -29
  229. package/lib/mocks/models/SpaceMock.d.ts +0 -6
  230. package/lib/mocks/models/SpaceMock.js +0 -25
  231. package/lib/models/Assignment.d.ts +0 -7
  232. package/lib/models/Assignment.js +0 -5
  233. package/lib/models/Cell.d.ts +0 -8
  234. package/lib/models/Cell.js +0 -5
  235. package/lib/models/CodeBlock.d.ts +0 -10
  236. package/lib/models/CodeBlock.js +0 -5
  237. package/lib/models/CodeSandboxSnapshot.d.ts +0 -92
  238. package/lib/models/CodeSandboxSnapshot.js +0 -13
  239. package/lib/models/CodeSandboxSnapshotDTO.d.ts +0 -173
  240. package/lib/models/CodeSandboxSnapshotDTO.js +0 -139
  241. package/lib/models/CodefeedBlocks.d.ts +0 -7
  242. package/lib/models/CodefeedBlocks.js +0 -5
  243. package/lib/models/Content.d.ts +0 -5
  244. package/lib/models/Content.js +0 -5
  245. package/lib/models/Course.d.ts +0 -17
  246. package/lib/models/Course.js +0 -5
  247. package/lib/models/Dataset.d.ts +0 -16
  248. package/lib/models/Dataset.js +0 -5
  249. package/lib/models/Document.d.ts +0 -8
  250. package/lib/models/Document.js +0 -5
  251. package/lib/models/Environment.d.ts +0 -86
  252. package/lib/models/Environment.js +0 -5
  253. package/lib/models/EnvironmentDTO.d.ts +0 -125
  254. package/lib/models/EnvironmentDTO.js +0 -88
  255. package/lib/models/Exercise.d.ts +0 -16
  256. package/lib/models/Exercise.js +0 -5
  257. package/lib/models/Item.d.ts +0 -20
  258. package/lib/models/Item.js +0 -5
  259. package/lib/models/ItemDTO.d.ts +0 -74
  260. package/lib/models/ItemDTO.js +0 -186
  261. package/lib/models/ItemType.d.ts +0 -2
  262. package/lib/models/ItemType.js +0 -5
  263. package/lib/models/Lesson.d.ts +0 -5
  264. package/lib/models/Lesson.js +0 -5
  265. package/lib/models/LexicalDTO.d.ts +0 -155
  266. package/lib/models/LexicalDTO.js +0 -157
  267. package/lib/models/Library.d.ts +0 -10
  268. package/lib/models/Library.js +0 -5
  269. package/lib/models/Notebook.d.ts +0 -11
  270. package/lib/models/Notebook.js +0 -5
  271. package/lib/models/NotebookDTO.d.ts +0 -96
  272. package/lib/models/NotebookDTO.js +0 -153
  273. package/lib/models/Page.d.ts +0 -41
  274. package/lib/models/Page.js +0 -25
  275. package/lib/models/PageTag.d.ts +0 -19
  276. package/lib/models/PageTag.js +0 -94
  277. package/lib/models/ProjectDTO.d.ts +0 -89
  278. package/lib/models/ProjectDTO.js +0 -131
  279. package/lib/models/Runtime.d.ts +0 -123
  280. package/lib/models/Runtime.js +0 -18
  281. package/lib/models/RuntimeDTO.d.ts +0 -191
  282. package/lib/models/RuntimeDTO.js +0 -204
  283. package/lib/models/Space.d.ts +0 -35
  284. package/lib/models/Space.js +0 -66
  285. package/lib/models/SpaceDTO.d.ts +0 -334
  286. package/lib/models/SpaceDTO.js +0 -244
  287. package/lib/models/SpaceItem.d.ts +0 -10
  288. package/lib/models/SpaceItem.js +0 -5
  289. package/lib/models/SpaceMember.d.ts +0 -6
  290. package/lib/models/SpaceMember.js +0 -5
  291. package/lib/models/StudentItem.d.ts +0 -21
  292. package/lib/models/StudentItem.js +0 -5
  293. package/lib/services/DatalayerServiceManager.d.ts +0 -22
  294. package/lib/services/DatalayerServiceManager.js +0 -69
  295. package/lib/services/index.d.ts +0 -4
  296. package/lib/services/index.js +0 -7
  297. package/lib/services/reconnectToRuntime.d.ts +0 -32
  298. package/lib/services/reconnectToRuntime.js +0 -59
  299. package/lib/state/substates/CellState.d.ts +0 -12
  300. package/lib/state/substates/CellState.js +0 -22
  301. package/lib/state/substates/DocumentState.d.ts +0 -10
  302. package/lib/state/substates/DocumentState.js +0 -14
  303. package/lib/state/substates/GradeState.d.ts +0 -10
  304. package/lib/state/substates/GradeState.js +0 -14
  305. package/lib/state/substates/JupyterLabState.d.ts +0 -16
  306. package/lib/state/substates/JupyterLabState.js +0 -17
  307. package/lib/state/substates/NbformatState.d.ts +0 -13
  308. package/lib/state/substates/NbformatState.js +0 -16
  309. package/lib/state/substates/RuntimesState.d.ts +0 -79
  310. package/lib/state/substates/RuntimesState.js +0 -180
  311. package/lib/state/substates/SpaceState.d.ts +0 -11
  312. package/lib/state/substates/SpaceState.js +0 -16
  313. package/lib/stateful/index.d.ts +0 -2
  314. package/lib/stateful/index.js +0 -6
  315. package/lib/stateful/jupyter/exec/Python.d.ts +0 -5
  316. package/lib/stateful/jupyter/exec/Python.js +0 -100
  317. package/lib/stateful/jupyter/exec/Snippets.d.ts +0 -105
  318. package/lib/stateful/jupyter/exec/Snippets.js +0 -101
  319. package/lib/stateful/jupyter/exec/index.d.ts +0 -2
  320. package/lib/stateful/jupyter/exec/index.js +0 -6
  321. package/lib/stateful/jupyter/index.d.ts +0 -2
  322. package/lib/stateful/jupyter/index.js +0 -6
  323. package/lib/stateful/jupyter/kernelsHandler.d.ts +0 -8
  324. package/lib/stateful/jupyter/kernelsHandler.js +0 -39
  325. package/lib/stateful/runtimes/actions.d.ts +0 -102
  326. package/lib/stateful/runtimes/actions.js +0 -249
  327. package/lib/stateful/runtimes/apis.d.ts +0 -273
  328. package/lib/stateful/runtimes/apis.js +0 -5
  329. package/lib/stateful/runtimes/index.d.ts +0 -5
  330. package/lib/stateful/runtimes/index.js +0 -9
  331. package/lib/stateful/runtimes/settings.d.ts +0 -15
  332. package/lib/stateful/runtimes/settings.js +0 -31
  333. package/lib/stateful/runtimes/snapshots.d.ts +0 -25
  334. package/lib/stateful/runtimes/snapshots.js +0 -150
  335. package/lib/stateful/runtimes/utils.d.ts +0 -7
  336. package/lib/stateful/runtimes/utils.js +0 -14
  337. package/lib/utils/Cells.d.ts +0 -2
  338. package/lib/utils/Cells.js +0 -28
  339. /package/lib/{mocks/jupyter/index.d.ts → cli-login.d.ts} +0 -0
@@ -36,8 +36,9 @@
36
36
  * }
37
37
  * ```
38
38
  */
39
- import { useQuery, useMutation, useQueryClient, } from '@tanstack/react-query';
40
- import { BOOTSTRAP_USER_ONBOARDING, asContact, asDatasource, asInvite, asOrganization, asPage, asSecret, asSpace, asTeam, asToken, asUser, } from '../models/index.js';
39
+ import { useQuery, useQueries, useMutation, useQueryClient, } from '@tanstack/react-query';
40
+ import { BOOTSTRAP_USER_ONBOARDING, asContact, asDatasource, asInvite, asOrganization, asSecret, asTeam, asToken, asUser, } from '../models/index.js';
41
+ import { asPage, asSpace } from './cacheConverters.js';
41
42
  import { useCoreStore, useIAMStore } from '../state/index.js';
42
43
  import { asDisplayName, namesAsInitials, asArray } from '../utils/index.js';
43
44
  import { useDatalayer } from './useDatalayer.js';
@@ -361,6 +362,85 @@ export const useCache = ({ loginRoute = '/login' } = {}) => {
361
362
  return asUser(u);
362
363
  }
363
364
  };
365
+ const toStudent = (rawStudent) => {
366
+ if (!rawStudent) {
367
+ return undefined;
368
+ }
369
+ const baseUser = asUser(rawStudent);
370
+ const studentItems = new Map();
371
+ const rawItemsSource = rawStudent.student_items ??
372
+ rawStudent.studentItems ??
373
+ rawStudent.items ??
374
+ rawStudent.course_items ??
375
+ rawStudent.student_items_by_uid ??
376
+ rawStudent.studentItemsByUid;
377
+ const rawItems = Array.isArray(rawItemsSource)
378
+ ? rawItemsSource
379
+ : rawItemsSource && typeof rawItemsSource === 'object'
380
+ ? Object.values(rawItemsSource)
381
+ : [];
382
+ rawItems.forEach((studentItem) => {
383
+ const itemId = String(studentItem.item_uid ??
384
+ studentItem.item_uid_s ??
385
+ studentItem.itemId ??
386
+ studentItem.item_id ??
387
+ studentItem.item_id_s ??
388
+ '').trim();
389
+ if (!itemId) {
390
+ return;
391
+ }
392
+ const completedRaw = studentItem.completed_b ??
393
+ studentItem.completed ??
394
+ studentItem.is_completed_b ??
395
+ studentItem.isCompleted ??
396
+ studentItem.done_b ??
397
+ studentItem.done;
398
+ const completed = typeof completedRaw === 'string'
399
+ ? ['true', '1', 'yes'].includes(completedRaw.toLowerCase())
400
+ : Boolean(completedRaw);
401
+ const passRaw = studentItem.pass_b ??
402
+ studentItem.pass ??
403
+ studentItem.passed_b ??
404
+ studentItem.passed;
405
+ const pass = typeof passRaw === 'string'
406
+ ? ['true', '1', 'yes'].includes(passRaw.toLowerCase())
407
+ : passRaw;
408
+ const mapped = {
409
+ id: studentItem.uid ?? studentItem.id,
410
+ type: 'student_item',
411
+ itemId,
412
+ itemType: studentItem.item_type_s ??
413
+ studentItem.itemType ??
414
+ studentItem.type_s ??
415
+ studentItem.type,
416
+ score: studentItem.score_i ??
417
+ studentItem.score_f ??
418
+ studentItem.score ??
419
+ studentItem.total_score_f,
420
+ codeStudent: studentItem.code_student_t ?? studentItem.codeStudent,
421
+ completed,
422
+ pass,
423
+ nbgrades: studentItem.nbgrades ??
424
+ studentItem.grades ??
425
+ [],
426
+ nbgradesTotalPoints: studentItem.nbgrades_total_points_f ??
427
+ studentItem.nbgradesTotalPoints ??
428
+ studentItem.total_points_f ??
429
+ ((studentItem.item_type_s ?? studentItem.itemType ?? studentItem.type_s ?? studentItem.type) === 'assignment'
430
+ ? 0
431
+ : undefined),
432
+ nbgradesTotalScore: studentItem.nbgrades_total_score_f ??
433
+ studentItem.nbgradesTotalScore ??
434
+ studentItem.total_score_f ??
435
+ ((studentItem.item_type_s ?? studentItem.itemType ?? studentItem.type_s ?? studentItem.type) === 'assignment'
436
+ ? 0
437
+ : undefined),
438
+ };
439
+ studentItems.set(itemId, mapped);
440
+ });
441
+ baseUser.studentItems = studentItems;
442
+ return baseUser;
443
+ };
364
444
  const toOrganization = (org) => {
365
445
  return asOrganization(org);
366
446
  };
@@ -447,7 +527,7 @@ export const useCache = ({ loginRoute = '/login' } = {}) => {
447
527
  path: raw_dataset.s3_path_s,
448
528
  cdnUrl: raw_dataset.cdn_url_s,
449
529
  creationDate: new Date(raw_dataset.creation_ts_dt),
450
- public: raw_dataset.public_b ?? false,
530
+ public: raw_dataset.is_public_b ?? false,
451
531
  lastPublicationDate: raw_dataset.creation_ts_dt
452
532
  ? new Date(raw_dataset.creation_ts_dt)
453
533
  : undefined,
@@ -470,7 +550,7 @@ export const useCache = ({ loginRoute = '/login' } = {}) => {
470
550
  description: cl.description_t,
471
551
  source: cl.source_t,
472
552
  creationDate: new Date(cl.creation_ts_dt),
473
- public: cl.public_b ?? false,
553
+ public: cl.is_public_b ?? false,
474
554
  lastPublicationDate: cl.last_publication_ts_dt
475
555
  ? new Date(cl.last_publication_ts_dt)
476
556
  : undefined,
@@ -496,7 +576,7 @@ export const useCache = ({ loginRoute = '/login' } = {}) => {
496
576
  nbformat: raw_notebook.model_s
497
577
  ? JSON.parse(raw_notebook.model_s)
498
578
  : undefined,
499
- public: raw_notebook.public_b ?? false,
579
+ public: raw_notebook.is_public_b ?? false,
500
580
  creationDate: new Date(raw_notebook.creation_ts_dt),
501
581
  lastUpdateDate: raw_notebook.last_update_ts_dt
502
582
  ? new Date(raw_notebook.last_update_ts_dt)
@@ -523,7 +603,7 @@ export const useCache = ({ loginRoute = '/login' } = {}) => {
523
603
  name: doc.name_t,
524
604
  description: doc.description_t,
525
605
  model: doc.model_s ? JSON.parse(doc.model_s) : undefined,
526
- public: doc.public_b ?? false,
606
+ public: doc.is_public_b ?? false,
527
607
  creationDate: new Date(doc.creation_ts_dt),
528
608
  lastUpdateDate: doc.last_update_ts_dt
529
609
  ? new Date(doc.last_update_ts_dt)
@@ -549,7 +629,7 @@ export const useCache = ({ loginRoute = '/login' } = {}) => {
549
629
  name: raw_lesson.name_t,
550
630
  description: raw_lesson.description_t,
551
631
  nbformat: raw_lesson.model_s ? JSON.parse(raw_lesson.model_s) : undefined,
552
- public: raw_lesson.public_b ?? false,
632
+ public: raw_lesson.is_public_b ?? false,
553
633
  creationDate: new Date(raw_lesson.creation_ts_dt),
554
634
  lastUpdateDate: raw_lesson.last_update_ts_dt
555
635
  ? new Date(raw_lesson.last_update_ts_dt)
@@ -580,7 +660,7 @@ export const useCache = ({ loginRoute = '/login' } = {}) => {
580
660
  codeQuestion: ex.code_question_t,
581
661
  codeSolution: ex.code_solution_t,
582
662
  codeTest: ex.code_test_t,
583
- public: ex.public_b ?? false,
663
+ public: ex.is_public_b ?? false,
584
664
  creationDate: new Date(ex.creation_ts_dt),
585
665
  lastUpdateDate: ex.last_update_ts_dt
586
666
  ? new Date(ex.last_update_ts_dt)
@@ -623,7 +703,7 @@ export const useCache = ({ loginRoute = '/login' } = {}) => {
623
703
  nbformat: raw_assignment.model_s
624
704
  ? JSON.parse(raw_assignment.model_s)
625
705
  : undefined,
626
- public: raw_assignment.public_b ?? false,
706
+ public: raw_assignment.is_public_b ?? false,
627
707
  creationDate: new Date(raw_assignment.creation_ts_dt),
628
708
  lastUpdateDate: raw_assignment.last_update_ts_dt
629
709
  ? new Date(raw_assignment.last_update_ts_dt)
@@ -665,6 +745,24 @@ export const useCache = ({ loginRoute = '/login' } = {}) => {
665
745
  },
666
746
  };
667
747
  };
748
+ const toEvalset = (raw_evalset) => {
749
+ const owner = toItemOwner(raw_evalset);
750
+ return {
751
+ id: raw_evalset.uid,
752
+ type: 'evalset',
753
+ name: raw_evalset.name_t,
754
+ description: raw_evalset.description_t,
755
+ public: raw_evalset.is_public_b ?? false,
756
+ creationDate: raw_evalset.creation_ts_dt
757
+ ? new Date(raw_evalset.creation_ts_dt)
758
+ : undefined,
759
+ lastUpdateDate: raw_evalset.last_update_ts_dt
760
+ ? new Date(raw_evalset.last_update_ts_dt)
761
+ : undefined,
762
+ tags: Array.isArray(raw_evalset.tags_ss) ? raw_evalset.tags_ss : [],
763
+ owner,
764
+ };
765
+ };
668
766
  const toItem = (item) => {
669
767
  if (!item.type_s) {
670
768
  console.error('No type_s found on item', item);
@@ -675,6 +773,45 @@ export const useCache = ({ loginRoute = '/login' } = {}) => {
675
773
  return toAssignment(item);
676
774
  case 'cell':
677
775
  return toCell(item);
776
+ case 'course':
777
+ return {
778
+ id: item.uid,
779
+ type: 'course',
780
+ name: item.name_t,
781
+ description: item.description_t,
782
+ tags: item.tags_ss ?? [],
783
+ handle: item.handle_s ?? item.handle,
784
+ handle_s: item.handle_s,
785
+ organization_handle_s: item.organization_handle_s,
786
+ owner_handle_s: item.owner_handle_s,
787
+ organization: {
788
+ handle: item.organization_handle_s,
789
+ },
790
+ owner: {
791
+ handle: item.owner_handle_s,
792
+ },
793
+ };
794
+ case 'space': {
795
+ const variant = (item.variant_s ?? item.variant ?? '').toLowerCase();
796
+ return {
797
+ id: item.uid,
798
+ type: variant === 'course' ? 'course' : 'space',
799
+ name: item.name_t,
800
+ description: item.description_t,
801
+ tags: item.tags_ss ?? [],
802
+ variant,
803
+ handle: item.handle_s ?? item.handle,
804
+ handle_s: item.handle_s,
805
+ organization_handle_s: item.organization_handle_s,
806
+ owner_handle_s: item.owner_handle_s,
807
+ organization: {
808
+ handle: item.organization_handle_s,
809
+ },
810
+ owner: {
811
+ handle: item.owner_handle_s,
812
+ },
813
+ };
814
+ }
678
815
  case 'dataset':
679
816
  return toDataset(item);
680
817
  case 'document':
@@ -687,6 +824,8 @@ export const useCache = ({ loginRoute = '/login' } = {}) => {
687
824
  return toNotebook(item);
688
825
  case 'page':
689
826
  return toPage(item);
827
+ case 'evalset':
828
+ return toEvalset(item);
690
829
  default:
691
830
  return {};
692
831
  }
@@ -721,17 +860,26 @@ export const useCache = ({ loginRoute = '/login' } = {}) => {
721
860
  if (raw_course.students) {
722
861
  students = new Map();
723
862
  raw_course.students.forEach((raw_stud) => {
724
- const student = toUser(raw_stud);
863
+ const student = toStudent(raw_stud);
725
864
  if (student && students) {
726
865
  students.set(student.id, student);
727
866
  }
728
867
  });
729
868
  }
730
869
  let itemIds = new Array();
731
- let raw_item_uids = raw_course.item_uids_s;
732
- if (raw_item_uids && raw_item_uids !== '()') {
733
- raw_item_uids = raw_item_uids.replace('(', '').replace(')', '');
734
- itemIds = raw_item_uids.split(' ');
870
+ const rawItemUids = raw_course.item_uids_s;
871
+ if (Array.isArray(rawItemUids)) {
872
+ itemIds = Array.from(new Set(rawItemUids
873
+ .map(uid => String(uid || '').trim())
874
+ .filter(Boolean)));
875
+ }
876
+ else if (typeof rawItemUids === 'string' && rawItemUids !== '()') {
877
+ itemIds = Array.from(new Set(rawItemUids
878
+ .replace('(', ' ')
879
+ .replace(')', ' ')
880
+ .split(/[\s,]+/g)
881
+ .map(uid => uid.trim())
882
+ .filter(Boolean)));
735
883
  }
736
884
  const items = new Array();
737
885
  if (raw_course.items) {
@@ -1550,7 +1698,12 @@ export const useCache = ({ loginRoute = '/login' } = {}) => {
1550
1698
  method: 'DELETE',
1551
1699
  });
1552
1700
  },
1553
- onSuccess: () => {
1701
+ onSuccess: (_resp, deletedSpaceUid) => {
1702
+ const deletedUid = String(deletedSpaceUid || '').trim();
1703
+ // Invalidate deleted space detail cache and all list queries.
1704
+ queryClient.removeQueries({
1705
+ queryKey: queryKeys.spaces.detail(deletedUid),
1706
+ });
1554
1707
  // Invalidate all space queries
1555
1708
  queryClient.invalidateQueries({
1556
1709
  queryKey: queryKeys.spaces.all(),
@@ -1616,6 +1769,8 @@ export const useCache = ({ loginRoute = '/login' } = {}) => {
1616
1769
  return useMutation({
1617
1770
  mutationFn: async ({ spaceId, name, description, notebookType = 'notebook', file, }) => {
1618
1771
  const formData = new FormData();
1772
+ formData.append('space_id', spaceId);
1773
+ // Backward compatibility for endpoints still expecting camelCase.
1619
1774
  formData.append('spaceId', spaceId);
1620
1775
  formData.append('notebookType', notebookType);
1621
1776
  formData.append('name', name);
@@ -3457,9 +3612,29 @@ export const useCache = ({ loginRoute = '/login' } = {}) => {
3457
3612
  method: 'POST',
3458
3613
  });
3459
3614
  },
3460
- onSuccess: (_, { courseId }) => {
3615
+ onSuccess: (_, { courseId, studentId }) => {
3616
+ // Optimistically add the student to the cached course so enrollment
3617
+ // dependent UI (e.g. the Progress tab) updates immediately. The Solr
3618
+ // read model is eventually consistent, so an immediate refetch would
3619
+ // return stale data; mark the detail query stale without refetching and
3620
+ // let it reconcile on the next natural fetch.
3621
+ const detailKey = ['courses', 'detail', courseId];
3622
+ const cached = queryClient.getQueryData(detailKey);
3623
+ if (cached) {
3624
+ const nextStudents = cached.students instanceof Map
3625
+ ? new Map(cached.students)
3626
+ : new Map();
3627
+ if (!nextStudents.has(studentId)) {
3628
+ nextStudents.set(studentId, { id: studentId });
3629
+ }
3630
+ queryClient.setQueryData(detailKey, {
3631
+ ...cached,
3632
+ students: nextStudents,
3633
+ });
3634
+ }
3461
3635
  queryClient.invalidateQueries({
3462
- queryKey: ['courses', 'detail', courseId],
3636
+ queryKey: detailKey,
3637
+ refetchType: 'none',
3463
3638
  });
3464
3639
  queryClient.invalidateQueries({
3465
3640
  queryKey: ['courses', 'enrollments'],
@@ -3478,9 +3653,25 @@ export const useCache = ({ loginRoute = '/login' } = {}) => {
3478
3653
  method: 'DELETE',
3479
3654
  });
3480
3655
  },
3481
- onSuccess: (_, { courseId }) => {
3656
+ onSuccess: (_, { courseId, studentId }) => {
3657
+ // Optimistically remove the student from the cached course so
3658
+ // enrollment dependent UI (e.g. the Progress tab) updates immediately.
3659
+ // The Solr read model is eventually consistent, so an immediate refetch
3660
+ // would return stale data; mark the detail query stale without
3661
+ // refetching and let it reconcile on the next natural fetch.
3662
+ const detailKey = ['courses', 'detail', courseId];
3663
+ const cached = queryClient.getQueryData(detailKey);
3664
+ if (cached && cached.students instanceof Map) {
3665
+ const nextStudents = new Map(cached.students);
3666
+ nextStudents.delete(studentId);
3667
+ queryClient.setQueryData(detailKey, {
3668
+ ...cached,
3669
+ students: nextStudents,
3670
+ });
3671
+ }
3482
3672
  queryClient.invalidateQueries({
3483
- queryKey: ['courses', 'detail', courseId],
3673
+ queryKey: detailKey,
3674
+ refetchType: 'none',
3484
3675
  });
3485
3676
  queryClient.invalidateQueries({
3486
3677
  queryKey: ['courses', 'enrollments'],
@@ -3541,7 +3732,8 @@ export const useCache = ({ loginRoute = '/login' } = {}) => {
3541
3732
  mutationFn: async (itemId) => {
3542
3733
  return requestDatalayer({
3543
3734
  url: `${configuration.libraryRunUrl}/api/library/v1/items/${itemId}/public`,
3544
- method: 'PUT',
3735
+ method: 'PATCH',
3736
+ body: { is_public: true },
3545
3737
  });
3546
3738
  },
3547
3739
  onSuccess: () => {
@@ -3556,8 +3748,9 @@ export const useCache = ({ loginRoute = '/login' } = {}) => {
3556
3748
  return useMutation({
3557
3749
  mutationFn: async (itemId) => {
3558
3750
  return requestDatalayer({
3559
- url: `${configuration.libraryRunUrl}/api/library/v1/items/${itemId}/private`,
3560
- method: 'PUT',
3751
+ url: `${configuration.libraryRunUrl}/api/library/v1/items/${itemId}/public`,
3752
+ method: 'PATCH',
3753
+ body: { is_public: false },
3561
3754
  });
3562
3755
  },
3563
3756
  onSuccess: () => {
@@ -3577,9 +3770,16 @@ export const useCache = ({ loginRoute = '/login' } = {}) => {
3577
3770
  */
3578
3771
  const useRefreshLayout = () => {
3579
3772
  return useMutation({
3580
- mutationFn: async ({ accountHandle, spaceHandle, }) => {
3773
+ mutationFn: async ({ accountHandle, teamHandle, spaceHandle, }) => {
3774
+ let path = `/api/spacer/v1/layouts/accounts/${accountHandle}`;
3775
+ if (teamHandle !== undefined && spaceHandle !== undefined) {
3776
+ path += `/teams/${teamHandle}/spaces/${spaceHandle}`;
3777
+ }
3778
+ else if (spaceHandle !== undefined) {
3779
+ path += `/spaces/${spaceHandle}`;
3780
+ }
3581
3781
  return requestDatalayer({
3582
- url: `${configuration.spacerRunUrl}/api/spacer/v1/layouts/accounts/${accountHandle}${spaceHandle !== undefined ? '/spaces/' + spaceHandle : ''}`,
3782
+ url: `${configuration.spacerRunUrl}${path}`,
3583
3783
  method: 'GET',
3584
3784
  });
3585
3785
  },
@@ -3590,6 +3790,9 @@ export const useCache = ({ loginRoute = '/login' } = {}) => {
3590
3790
  const transformedOrganization = resp.organization
3591
3791
  ? toOrganization(resp.organization)
3592
3792
  : undefined;
3793
+ const transformedTeam = resp.team && transformedOrganization
3794
+ ? toTeam(resp.team, transformedOrganization.id)
3795
+ : undefined;
3593
3796
  const transformedSpace = resp.space ? toSpace(resp.space) : undefined;
3594
3797
  // Set data directly into cache instead of just invalidating
3595
3798
  if (transformedUser) {
@@ -3602,6 +3805,15 @@ export const useCache = ({ loginRoute = '/login' } = {}) => {
3602
3805
  queryKey: queryKeys.organizations.all(),
3603
3806
  });
3604
3807
  }
3808
+ if (transformedTeam) {
3809
+ if (transformedTeam.id) {
3810
+ queryClient.setQueryData(queryKeys.teams.detail(transformedTeam.id), transformedTeam);
3811
+ }
3812
+ if (variables.teamHandle) {
3813
+ queryClient.setQueryData(queryKeys.teams.byHandle(variables.teamHandle), transformedTeam);
3814
+ }
3815
+ queryClient.invalidateQueries({ queryKey: queryKeys.teams.all() });
3816
+ }
3605
3817
  if (transformedSpace) {
3606
3818
  // Set both user and org space queries based on which type it is
3607
3819
  if (transformedUser && variables.spaceHandle) {
@@ -3729,12 +3941,24 @@ export const useCache = ({ loginRoute = '/login' } = {}) => {
3729
3941
  /**
3730
3942
  * Get dataset by ID
3731
3943
  */
3732
- const useDataset = (datasetId) => {
3944
+ const useDataset = (datasetId, scope) => {
3733
3945
  return useQuery({
3734
- queryKey: queryKeys.datasets.detail(datasetId),
3946
+ queryKey: [
3947
+ ...queryKeys.datasets.detail(datasetId),
3948
+ scope?.selectedPrincipalUid || '',
3949
+ scope?.selectedPrincipalKind || '',
3950
+ ],
3735
3951
  queryFn: async () => {
3952
+ const params = new URLSearchParams();
3953
+ if (scope?.selectedPrincipalUid) {
3954
+ params.set('selected_principal_uid', scope.selectedPrincipalUid);
3955
+ }
3956
+ if (scope?.selectedPrincipalKind) {
3957
+ params.set('selected_principal_kind', scope.selectedPrincipalKind);
3958
+ }
3959
+ const query = params.toString();
3736
3960
  const resp = await requestDatalayer({
3737
- url: `${configuration.spacerRunUrl}/api/spacer/v1/spaces/items/${datasetId}`,
3961
+ url: `${configuration.runtimesRunUrl}/api/runtimes/v1/spaces/items/${datasetId}${query ? `?${query}` : ''}`,
3738
3962
  method: 'GET',
3739
3963
  });
3740
3964
  if (resp.success && resp.item) {
@@ -3749,12 +3973,24 @@ export const useCache = ({ loginRoute = '/login' } = {}) => {
3749
3973
  /**
3750
3974
  * Get datasets by space
3751
3975
  */
3752
- const useDatasetsBySpace = (spaceId) => {
3976
+ const useDatasetsBySpace = (spaceId, scope) => {
3753
3977
  return useQuery({
3754
- queryKey: queryKeys.datasets.bySpace(spaceId),
3978
+ queryKey: [
3979
+ ...queryKeys.datasets.bySpace(spaceId),
3980
+ scope?.selectedPrincipalUid || '',
3981
+ scope?.selectedPrincipalKind || '',
3982
+ ],
3755
3983
  queryFn: async () => {
3984
+ const params = new URLSearchParams();
3985
+ if (scope?.selectedPrincipalUid) {
3986
+ params.set('selected_principal_uid', scope.selectedPrincipalUid);
3987
+ }
3988
+ if (scope?.selectedPrincipalKind) {
3989
+ params.set('selected_principal_kind', scope.selectedPrincipalKind);
3990
+ }
3991
+ const query = params.toString();
3756
3992
  const resp = await requestDatalayer({
3757
- url: `${configuration.spacerRunUrl}/api/spacer/v1/spaces/${spaceId}/items/types/dataset`,
3993
+ url: `${configuration.runtimesRunUrl}/api/runtimes/v1/spaces/${spaceId}/items/types/dataset${query ? `?${query}` : ''}`,
3758
3994
  method: 'GET',
3759
3995
  });
3760
3996
  if (resp.success && resp.items) {
@@ -3771,9 +4007,17 @@ export const useCache = ({ loginRoute = '/login' } = {}) => {
3771
4007
  */
3772
4008
  const useUpdateDataset = () => {
3773
4009
  return useMutation({
3774
- mutationFn: async ({ id, name, description, }) => {
4010
+ mutationFn: async ({ id, name, description, selectedPrincipalUid, selectedPrincipalKind, }) => {
4011
+ const params = new URLSearchParams();
4012
+ if (selectedPrincipalUid) {
4013
+ params.set('selected_principal_uid', selectedPrincipalUid);
4014
+ }
4015
+ if (selectedPrincipalKind) {
4016
+ params.set('selected_principal_kind', selectedPrincipalKind);
4017
+ }
4018
+ const query = params.toString();
3775
4019
  return requestDatalayer({
3776
- url: `${configuration.spacerRunUrl}/api/spacer/v1/datasets/${id}`,
4020
+ url: `${configuration.runtimesRunUrl}/api/runtimes/v1/datasets/${id}${query ? `?${query}` : ''}`,
3777
4021
  method: 'PUT',
3778
4022
  body: { name, description },
3779
4023
  });
@@ -4162,6 +4406,12 @@ export const useCache = ({ loginRoute = '/login' } = {}) => {
4162
4406
  queryClient.invalidateQueries({
4163
4407
  queryKey: ['assignments', assignmentId],
4164
4408
  });
4409
+ queryClient.invalidateQueries({
4410
+ queryKey: ['courses', 'detail', courseId],
4411
+ });
4412
+ queryClient.invalidateQueries({
4413
+ queryKey: ['courses', courseId, 'students'],
4414
+ });
4165
4415
  },
4166
4416
  });
4167
4417
  };
@@ -4185,6 +4435,12 @@ export const useCache = ({ loginRoute = '/login' } = {}) => {
4185
4435
  queryClient.invalidateQueries({
4186
4436
  queryKey: ['assignments', assignmentId],
4187
4437
  });
4438
+ queryClient.invalidateQueries({
4439
+ queryKey: ['courses', 'detail', courseId],
4440
+ });
4441
+ queryClient.invalidateQueries({
4442
+ queryKey: ['courses', courseId, 'students'],
4443
+ });
4188
4444
  },
4189
4445
  });
4190
4446
  };
@@ -4208,16 +4464,16 @@ export const useCache = ({ loginRoute = '/login' } = {}) => {
4208
4464
  // Exercise Grading
4209
4465
  // ============================================================================
4210
4466
  /**
4211
- * Grade an exercise by assigning points to student code
4467
+ * Grade an exercise by assigning a score to student code
4212
4468
  */
4213
- const useUpdateExercisePoints = () => {
4469
+ const useUpdateExerciseScore = () => {
4214
4470
  const queryClient = useQueryClient();
4215
4471
  return useMutation({
4216
- mutationFn: async ({ exerciseId, codeStudent, points, }) => {
4472
+ mutationFn: async ({ exerciseId, codeStudent, score, courseId, }) => {
4217
4473
  return requestDatalayer({
4218
- url: `${configuration.spacerRunUrl}/api/spacer/v1/exercises/${exerciseId}/points`,
4474
+ url: `${configuration.spacerRunUrl}/api/spacer/v1/exercises/${exerciseId}/score`,
4219
4475
  method: 'PUT',
4220
- body: { codeStudent, points },
4476
+ body: { codeStudent, score, courseId },
4221
4477
  });
4222
4478
  },
4223
4479
  onSuccess: (_, { exerciseId }) => {
@@ -4247,12 +4503,40 @@ export const useCache = ({ loginRoute = '/login' } = {}) => {
4247
4503
  if (!resp.success) {
4248
4504
  throw new Error(resp.message || 'Failed to fetch student');
4249
4505
  }
4250
- return resp.student;
4506
+ return toStudent(resp.student);
4251
4507
  },
4252
4508
  enabled: !!courseId && !!studentId,
4253
4509
  ...options,
4254
4510
  });
4255
4511
  };
4512
+ /**
4513
+ * Hydrate multiple students (with their student items) for a course.
4514
+ *
4515
+ * The course payload only carries the public member projection of each
4516
+ * student (uid/handle/name) and intentionally omits the nested
4517
+ * `student_items`. To compute per-item progress (e.g. in the course report)
4518
+ * each student must be fetched individually through the enrollment endpoint,
4519
+ * which returns the deep student document including its items.
4520
+ */
4521
+ const useStudents = (courseId, studentIds) => {
4522
+ const uniqueStudentIds = Array.from(new Set((studentIds || []).map(id => String(id || '').trim()).filter(Boolean)));
4523
+ return useQueries({
4524
+ queries: uniqueStudentIds.map(studentId => ({
4525
+ queryKey: ['courses', courseId, 'students', studentId],
4526
+ queryFn: async () => {
4527
+ const resp = await requestDatalayer({
4528
+ url: `${configuration.spacerRunUrl}/api/spacer/v1/courses/${courseId}/enrollments/students/${studentId}`,
4529
+ method: 'GET',
4530
+ });
4531
+ if (!resp.success) {
4532
+ throw new Error(resp.message || 'Failed to fetch student');
4533
+ }
4534
+ return toStudent(resp.student);
4535
+ },
4536
+ enabled: !!courseId && !!studentId,
4537
+ })),
4538
+ });
4539
+ };
4256
4540
  /**
4257
4541
  * Mark a course item as completed
4258
4542
  */
@@ -4273,6 +4557,9 @@ export const useCache = ({ loginRoute = '/login' } = {}) => {
4273
4557
  queryClient.invalidateQueries({
4274
4558
  queryKey: ['courses', courseId, 'items'],
4275
4559
  });
4560
+ queryClient.invalidateQueries({
4561
+ queryKey: ['courses', courseId, 'students'],
4562
+ });
4276
4563
  },
4277
4564
  });
4278
4565
  };
@@ -5631,12 +5918,19 @@ export const useCache = ({ loginRoute = '/login' } = {}) => {
5631
5918
  */
5632
5919
  const useSearchPublicItems = () => {
5633
5920
  return useMutation({
5634
- mutationFn: async ({ q, types = ['notebook', 'document', 'lesson'], max = 100, }) => {
5921
+ mutationFn: async ({ q, types = ['notebook', 'document', 'cell', 'lesson', 'evalset', 'course'], max = 100, }) => {
5922
+ const normalizedTypes = Array.from(new Set((types || [])
5923
+ .map(type => String(type || '')
5924
+ .trim()
5925
+ .toLowerCase())
5926
+ .filter(Boolean)
5927
+ .map(type => (type === 'eval' ? 'evalset' : type))));
5635
5928
  const queryString = Object.entries({
5636
5929
  q: q || '*',
5637
- types: types.join(' '),
5930
+ types: (normalizedTypes.length > 0
5931
+ ? normalizedTypes
5932
+ : ['notebook', 'document', 'cell', 'lesson', 'evalset', 'course']).join(' '),
5638
5933
  max: max.toString(),
5639
- public: 'true',
5640
5934
  })
5641
5935
  .map(([key, value]) => `${key}=${encodeURIComponent(value)}`)
5642
5936
  .join('&');
@@ -6244,14 +6538,26 @@ export const useCache = ({ loginRoute = '/login' } = {}) => {
6244
6538
  const useRefreshDataset = (options) => {
6245
6539
  const queryClient = useQueryClient();
6246
6540
  return useMutation({
6247
- mutationFn: async (datasetId) => {
6541
+ mutationFn: async (variables) => {
6542
+ const datasetId = typeof variables === 'string' ? variables : variables.datasetId;
6543
+ const selectedPrincipalUid = typeof variables === 'string' ? undefined : variables.selectedPrincipalUid;
6544
+ const selectedPrincipalKind = typeof variables === 'string' ? undefined : variables.selectedPrincipalKind;
6545
+ const params = new URLSearchParams();
6546
+ if (selectedPrincipalUid) {
6547
+ params.set('selected_principal_uid', selectedPrincipalUid);
6548
+ }
6549
+ if (selectedPrincipalKind) {
6550
+ params.set('selected_principal_kind', selectedPrincipalKind);
6551
+ }
6552
+ const query = params.toString();
6248
6553
  const resp = await requestDatalayer({
6249
- url: `${configuration.spacerRunUrl}/api/spacer/v1/spaces/items/${datasetId}`,
6554
+ url: `${configuration.runtimesRunUrl}/api/runtimes/v1/spaces/items/${datasetId}${query ? `?${query}` : ''}`,
6250
6555
  method: 'GET',
6251
6556
  });
6252
6557
  return resp;
6253
6558
  },
6254
- onSuccess: (data, datasetId) => {
6559
+ onSuccess: (data, variables) => {
6560
+ const datasetId = typeof variables === 'string' ? variables : variables.datasetId;
6255
6561
  queryClient.invalidateQueries({
6256
6562
  queryKey: queryKeys.datasets.detail(datasetId),
6257
6563
  });
@@ -6266,14 +6572,26 @@ export const useCache = ({ loginRoute = '/login' } = {}) => {
6266
6572
  const useRefreshSpaceDatasets = (options) => {
6267
6573
  const queryClient = useQueryClient();
6268
6574
  return useMutation({
6269
- mutationFn: async (spaceId) => {
6575
+ mutationFn: async (variables) => {
6576
+ const spaceId = typeof variables === 'string' ? variables : variables.spaceId;
6577
+ const selectedPrincipalUid = typeof variables === 'string' ? undefined : variables.selectedPrincipalUid;
6578
+ const selectedPrincipalKind = typeof variables === 'string' ? undefined : variables.selectedPrincipalKind;
6579
+ const params = new URLSearchParams();
6580
+ if (selectedPrincipalUid) {
6581
+ params.set('selected_principal_uid', selectedPrincipalUid);
6582
+ }
6583
+ if (selectedPrincipalKind) {
6584
+ params.set('selected_principal_kind', selectedPrincipalKind);
6585
+ }
6586
+ const query = params.toString();
6270
6587
  const resp = await requestDatalayer({
6271
- url: `${configuration.spacerRunUrl}/api/spacer/v1/spaces/${spaceId}/items/types/dataset`,
6588
+ url: `${configuration.runtimesRunUrl}/api/runtimes/v1/spaces/${spaceId}/items/types/dataset${query ? `?${query}` : ''}`,
6272
6589
  method: 'GET',
6273
6590
  });
6274
6591
  return resp;
6275
6592
  },
6276
- onSuccess: (data, spaceId) => {
6593
+ onSuccess: (data, variables) => {
6594
+ const spaceId = typeof variables === 'string' ? variables : variables.spaceId;
6277
6595
  queryClient.invalidateQueries({
6278
6596
  queryKey: queryKeys.datasets.bySpace(spaceId),
6279
6597
  });
@@ -6310,10 +6628,37 @@ export const useCache = ({ loginRoute = '/login' } = {}) => {
6310
6628
  queryKey: queryKeys.items.public(),
6311
6629
  queryFn: async () => {
6312
6630
  const resp = await requestDatalayer({
6313
- url: `${configuration.libraryRunUrl}/api/library/v1/items/public`,
6631
+ url: `${configuration.libraryRunUrl}/api/library/v1/search?q=*&max=-1`,
6314
6632
  method: 'GET',
6315
6633
  });
6316
- return resp;
6634
+ return {
6635
+ ...resp,
6636
+ items: (resp.items || [])
6637
+ .map((item) => toItem(item))
6638
+ .filter(Boolean),
6639
+ };
6640
+ },
6641
+ ...options,
6642
+ });
6643
+ };
6644
+ /**
6645
+ * Get the current user's own public items (publications).
6646
+ * @param options - Query options
6647
+ */
6648
+ const usePublications = (options) => {
6649
+ return useQuery({
6650
+ queryKey: [...queryKeys.items.all(), 'publications'],
6651
+ queryFn: async () => {
6652
+ const resp = await requestDatalayer({
6653
+ url: `${configuration.libraryRunUrl}/api/library/v1/publications`,
6654
+ method: 'GET',
6655
+ });
6656
+ return {
6657
+ ...resp,
6658
+ items: (resp.items || [])
6659
+ .map((item) => toItem(item))
6660
+ .filter(Boolean),
6661
+ };
6317
6662
  },
6318
6663
  ...options,
6319
6664
  });
@@ -6327,10 +6672,15 @@ export const useCache = ({ loginRoute = '/login' } = {}) => {
6327
6672
  return useMutation({
6328
6673
  mutationFn: async () => {
6329
6674
  const resp = await requestDatalayer({
6330
- url: `${configuration.libraryRunUrl}/api/library/v1/items/public`,
6675
+ url: `${configuration.libraryRunUrl}/api/library/v1/search?q=*&max=-1`,
6331
6676
  method: 'GET',
6332
6677
  });
6333
- return resp;
6678
+ return {
6679
+ ...resp,
6680
+ items: (resp.items || [])
6681
+ .map((item) => toItem(item))
6682
+ .filter(Boolean),
6683
+ };
6334
6684
  },
6335
6685
  onSuccess: () => {
6336
6686
  queryClient.invalidateQueries({ queryKey: queryKeys.items.public() });
@@ -6625,6 +6975,9 @@ export const useCache = ({ loginRoute = '/login' } = {}) => {
6625
6975
  },
6626
6976
  onSuccess: () => {
6627
6977
  queryClient.invalidateQueries({ queryKey: queryKeys.items.public() });
6978
+ queryClient.invalidateQueries({
6979
+ queryKey: [...queryKeys.items.all(), 'publications'],
6980
+ });
6628
6981
  },
6629
6982
  ...options,
6630
6983
  });
@@ -7118,6 +7471,7 @@ export const useCache = ({ loginRoute = '/login' } = {}) => {
7118
7471
  useEnrollStudentToCourse,
7119
7472
  useRemoveStudentFromCourse,
7120
7473
  useStudent,
7474
+ useStudents,
7121
7475
  useConfirmCourseItemCompletion,
7122
7476
  useSetCourseItems,
7123
7477
  useRefreshCourse,
@@ -7172,7 +7526,7 @@ export const useCache = ({ loginRoute = '/login' } = {}) => {
7172
7526
  useExercisesBySpace,
7173
7527
  useUpdateExercise,
7174
7528
  useCloneExercise,
7175
- useUpdateExercisePoints,
7529
+ useUpdateExerciseScore,
7176
7530
  useRefreshExercise,
7177
7531
  useRefreshSpaceExercises,
7178
7532
  // Assignments
@@ -7194,6 +7548,7 @@ export const useCache = ({ loginRoute = '/login' } = {}) => {
7194
7548
  useMakeItemPrivate,
7195
7549
  useSearchPublicItems,
7196
7550
  usePublicItems,
7551
+ usePublications,
7197
7552
  useRefreshPublicItems,
7198
7553
  useRefreshSpaceItems,
7199
7554
  useClearCachedPublicItems,