@gen3/workspaces 0.12.45 → 0.12.46
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +201 -0
- package/dist/dts/providers/useJEGWorkspaceResourceMonitor.d.ts.map +1 -1
- package/dist/dts/providers/useJEGWorkspaceResourceMonitor.js +3 -1
- package/dist/dts/providers/useJEGWorkspaceResourceMonitor.js.map +1 -1
- package/dist/dts/server/workspaceAssetsHandler.d.ts.map +1 -1
- package/dist/dts/server/workspaceAssetsHandler.js +9 -2
- package/dist/dts/server/workspaceAssetsHandler.js.map +1 -1
- package/dist/dts/workspace/tiers/FreeWorkspace.d.ts.map +1 -1
- package/dist/dts/workspace/tiers/FreeWorkspace.js +65 -1
- package/dist/dts/workspace/tiers/FreeWorkspace.js.map +1 -1
- package/dist/dts/workspace/tiers/RemoteComputeWorkspace.d.ts.map +1 -1
- package/dist/dts/workspace/tiers/RemoteComputeWorkspace.js +69 -7
- package/dist/dts/workspace/tiers/RemoteComputeWorkspace.js.map +1 -1
- package/dist/index/cjs/index.js +132 -7
- package/dist/index/cjs/index.js.map +1 -1
- package/dist/index/esm/index.js +133 -8
- package/dist/index/esm/index.js.map +1 -1
- package/dist/jupyterlite-builds/free-private/requirements.txt +0 -1
- package/dist/server/cjs/server.js +9 -3
- package/dist/server/cjs/server.js.map +1 -1
- package/dist/server/esm/server.js +9 -3
- package/dist/server/esm/server.js.map +1 -1
- package/jupyterlite-builds/free-private/requirements.txt +0 -1
- package/package.json +5 -5
package/dist/index/esm/index.js
CHANGED
|
@@ -1,9 +1,8 @@
|
|
|
1
1
|
import { jsxs, jsx, Fragment } from 'react/jsx-runtime';
|
|
2
2
|
import React, { useCallback, useMemo, useState, useRef, useEffect, createContext, useImperativeHandle } from 'react';
|
|
3
|
-
import { mergeDefaultTailwindClassnames, convertSecondsToMilliseconds, InfoRolloverButton, OverflowTooltippedLabel, PanelErrorBoundary, ProtectedContent, NavPageLayout, ContentSource, getNavPageLayoutPropsFromConfig } from '@gen3/frontend';
|
|
3
|
+
import { mergeDefaultTailwindClassnames, ACTIVITY_CHANNEL, convertSecondsToMilliseconds, InfoRolloverButton, OverflowTooltippedLabel, PanelErrorBoundary, ProtectedContent, NavPageLayout, ContentSource, getNavPageLayoutPropsFromConfig } from '@gen3/frontend';
|
|
4
4
|
import { Card, Stack, Badge, Text, List, Group, Tooltip, Button, LoadingOverlay, Alert, Loader, Divider, Select, ActionIcon, TextInput, Textarea, Table, Scroller, Tabs, Center } from '@mantine/core';
|
|
5
5
|
import { Icon } from '@iconify-icon/react';
|
|
6
|
-
import { getCookie } from 'cookies-next';
|
|
7
6
|
import { GEN3_API, GEN3_WORKSPACE_API, gen3Api, useCoreSelector, selectJEGActiveWorkspaceStatus, useCoreDispatch, setJEGActiveWorkspaceStatus, WorkspaceStatus, setJEGRequestedWorkspaceStatus, RequestedWorkspaceStatus, setJEGActiveWorkspaceId, isFetchBaseQueryError, selectJEGRequestedWorkspaceStatus, selectJEGRequestedWorkspaceStatusTimestamp, isTimeGreaterThan, formatUptimeInMinutes, selectJEGKernelIds, removeManyJEGActiveKernels, upsertManyJEGActiveKernels, normalizeRtkError, selectAllJEGKernels, addJEGActiveKernel, selectWorkspaceTier, setWorkspaceTier, selectWorkspaceFullscreen, setWorkspaceFullscreen, useGetDictionaryFromUrlQuery, useUserAuth, GEN3_COMMONS_NAME } from '@gen3/core';
|
|
8
7
|
import { useDeepCompareEffect } from 'use-deep-compare';
|
|
9
8
|
import { notifications } from '@mantine/notifications';
|
|
@@ -175,13 +174,74 @@ const FreeWorkspace = ({ assetBaseUrl = '/api/workspace-assets/free', onReady, o
|
|
|
175
174
|
const [loading, setLoading] = useState(true);
|
|
176
175
|
const [loadError, setLoadError] = useState(false);
|
|
177
176
|
const [retryCount, setRetryCount] = useState(0);
|
|
177
|
+
const [jupyterReady, setJupyterReady] = useState(false);
|
|
178
178
|
const iframeRef = useRef(null);
|
|
179
|
+
const broadcastChannelRef = useRef(null);
|
|
179
180
|
const url = `${assetBaseUrl}/lab/index.html`;
|
|
180
181
|
const handleRetry = useCallback(()=>{
|
|
181
182
|
setLoadError(false);
|
|
182
183
|
setLoading(true);
|
|
183
184
|
setRetryCount((n)=>n + 1);
|
|
184
185
|
}, []);
|
|
186
|
+
// set up BroadcastChannel
|
|
187
|
+
useEffect(()=>{
|
|
188
|
+
if (!broadcastChannelRef?.current) {
|
|
189
|
+
broadcastChannelRef.current = new BroadcastChannel(ACTIVITY_CHANNEL);
|
|
190
|
+
}
|
|
191
|
+
return ()=>{
|
|
192
|
+
if (broadcastChannelRef.current) {
|
|
193
|
+
broadcastChannelRef.current.close();
|
|
194
|
+
broadcastChannelRef.current = null;
|
|
195
|
+
}
|
|
196
|
+
};
|
|
197
|
+
}, []);
|
|
198
|
+
// Handle setting up iframe event listeners
|
|
199
|
+
useEffect(()=>{
|
|
200
|
+
if (!jupyterReady) return;
|
|
201
|
+
const updateUserActivity = ()=>{
|
|
202
|
+
const timestamp = Date.now();
|
|
203
|
+
if (broadcastChannelRef.current) {
|
|
204
|
+
broadcastChannelRef.current.postMessage({
|
|
205
|
+
type: 'activity-update',
|
|
206
|
+
timestamp
|
|
207
|
+
});
|
|
208
|
+
}
|
|
209
|
+
};
|
|
210
|
+
const iframe = iframeRef.current;
|
|
211
|
+
if (!iframe?.contentWindow) {
|
|
212
|
+
return;
|
|
213
|
+
}
|
|
214
|
+
try {
|
|
215
|
+
const iframeDoc = iframe.contentDocument || iframe.contentWindow.document;
|
|
216
|
+
if (iframeDoc) {
|
|
217
|
+
iframeDoc.addEventListener('mousedown', updateUserActivity);
|
|
218
|
+
iframeDoc.addEventListener('keypress', updateUserActivity);
|
|
219
|
+
iframeDoc.addEventListener('scroll', updateUserActivity);
|
|
220
|
+
iframeDoc.addEventListener('click', updateUserActivity);
|
|
221
|
+
iframeDoc.addEventListener('touchstart', updateUserActivity);
|
|
222
|
+
}
|
|
223
|
+
} catch (error) {
|
|
224
|
+
console.warn('Cannot access iframe content - cross-origin restriction', error);
|
|
225
|
+
}
|
|
226
|
+
return ()=>{
|
|
227
|
+
if (iframe?.contentWindow) {
|
|
228
|
+
try {
|
|
229
|
+
const iframeDoc = iframe.contentDocument || iframe.contentWindow.document;
|
|
230
|
+
if (iframeDoc) {
|
|
231
|
+
iframeDoc.removeEventListener('mousedown', updateUserActivity);
|
|
232
|
+
iframeDoc.removeEventListener('keypress', updateUserActivity);
|
|
233
|
+
iframeDoc.removeEventListener('scroll', updateUserActivity);
|
|
234
|
+
iframeDoc.removeEventListener('click', updateUserActivity);
|
|
235
|
+
iframeDoc.removeEventListener('touchstart', updateUserActivity);
|
|
236
|
+
}
|
|
237
|
+
} catch {
|
|
238
|
+
// Ignore cleanup errors
|
|
239
|
+
}
|
|
240
|
+
}
|
|
241
|
+
};
|
|
242
|
+
}, [
|
|
243
|
+
jupyterReady
|
|
244
|
+
]);
|
|
185
245
|
if (loadError) {
|
|
186
246
|
return /*#__PURE__*/ jsx("div", {
|
|
187
247
|
children: /*#__PURE__*/ jsxs(Card, {
|
|
@@ -233,6 +293,7 @@ const FreeWorkspace = ({ assetBaseUrl = '/api/workspace-assets/free', onReady, o
|
|
|
233
293
|
className: "min-h-0 flex-1 border-0",
|
|
234
294
|
onLoad: ()=>{
|
|
235
295
|
setLoading(false);
|
|
296
|
+
setJupyterReady(true);
|
|
236
297
|
onReady?.();
|
|
237
298
|
},
|
|
238
299
|
onError: ()=>{
|
|
@@ -632,7 +693,9 @@ const workspaceShutdownAlertLimit = 30000; // 5 minutes: 5 * 60 * 1000 TODO Figu
|
|
|
632
693
|
]);
|
|
633
694
|
useDeepCompareEffect(()=>{
|
|
634
695
|
// TODO: add better error logging
|
|
635
|
-
|
|
696
|
+
if (error) {
|
|
697
|
+
console.log('useJEGWorkspaceResourceMonitor', error);
|
|
698
|
+
}
|
|
636
699
|
}, [
|
|
637
700
|
error
|
|
638
701
|
]);
|
|
@@ -994,6 +1057,7 @@ const MicroContainerReduxPanel = ({ compact = false })=>{
|
|
|
994
1057
|
const [retryCount, setRetryCount] = useState(0);
|
|
995
1058
|
const [jupyterReady, setJupyterReady] = useState(false);
|
|
996
1059
|
const iframeRef = useRef(null);
|
|
1060
|
+
const broadcastChannelRef = useRef(null);
|
|
997
1061
|
const { status } = useMicroContainerReduxContext();
|
|
998
1062
|
const normalizedBase = assetBaseUrl.replace(/\/$/, '');
|
|
999
1063
|
// Scoped notebook path for session isolation
|
|
@@ -1013,11 +1077,71 @@ const MicroContainerReduxPanel = ({ compact = false })=>{
|
|
|
1013
1077
|
const userHash = btoa(userId || 'anonymous').substring(0, 8);
|
|
1014
1078
|
scopedNotebookPath = `/workspace/${userHash}/${notebookName}.ipynb`;
|
|
1015
1079
|
}
|
|
1016
|
-
|
|
1017
|
-
|
|
1018
|
-
|
|
1019
|
-
|
|
1020
|
-
|
|
1080
|
+
// let accessToken = undefined;
|
|
1081
|
+
// if (process.env.NODE_ENV === 'development') {
|
|
1082
|
+
// // NOTE: This cookie can only be accessed from the client side
|
|
1083
|
+
// // in development mode. Otherwise, the cookie is set as httpOnly
|
|
1084
|
+
// accessToken = getCookie('credentials_token');
|
|
1085
|
+
// }
|
|
1086
|
+
// set up BroadcastChannel
|
|
1087
|
+
useEffect(()=>{
|
|
1088
|
+
if (!broadcastChannelRef?.current) {
|
|
1089
|
+
broadcastChannelRef.current = new BroadcastChannel(ACTIVITY_CHANNEL);
|
|
1090
|
+
}
|
|
1091
|
+
return ()=>{
|
|
1092
|
+
if (broadcastChannelRef.current) {
|
|
1093
|
+
broadcastChannelRef.current.close();
|
|
1094
|
+
broadcastChannelRef.current = null;
|
|
1095
|
+
}
|
|
1096
|
+
};
|
|
1097
|
+
}, []);
|
|
1098
|
+
// Handle setting up iframe event listeners
|
|
1099
|
+
useEffect(()=>{
|
|
1100
|
+
if (!jupyterReady) return;
|
|
1101
|
+
const updateUserActivity = ()=>{
|
|
1102
|
+
const timestamp = Date.now();
|
|
1103
|
+
if (broadcastChannelRef.current) {
|
|
1104
|
+
broadcastChannelRef.current.postMessage({
|
|
1105
|
+
type: 'activity-update',
|
|
1106
|
+
timestamp
|
|
1107
|
+
});
|
|
1108
|
+
}
|
|
1109
|
+
};
|
|
1110
|
+
const iframe = iframeRef.current;
|
|
1111
|
+
if (!iframe?.contentWindow) {
|
|
1112
|
+
return;
|
|
1113
|
+
}
|
|
1114
|
+
try {
|
|
1115
|
+
const iframeDoc = iframe.contentDocument || iframe.contentWindow.document;
|
|
1116
|
+
if (iframeDoc) {
|
|
1117
|
+
iframeDoc.addEventListener('mousedown', updateUserActivity);
|
|
1118
|
+
iframeDoc.addEventListener('keypress', updateUserActivity);
|
|
1119
|
+
iframeDoc.addEventListener('scroll', updateUserActivity);
|
|
1120
|
+
iframeDoc.addEventListener('click', updateUserActivity);
|
|
1121
|
+
iframeDoc.addEventListener('touchstart', updateUserActivity);
|
|
1122
|
+
}
|
|
1123
|
+
} catch (error) {
|
|
1124
|
+
console.warn('Cannot access iframe content - cross-origin restriction', error);
|
|
1125
|
+
}
|
|
1126
|
+
return ()=>{
|
|
1127
|
+
if (iframe?.contentWindow) {
|
|
1128
|
+
try {
|
|
1129
|
+
const iframeDoc = iframe.contentDocument || iframe.contentWindow.document;
|
|
1130
|
+
if (iframeDoc) {
|
|
1131
|
+
iframeDoc.removeEventListener('mousedown', updateUserActivity);
|
|
1132
|
+
iframeDoc.removeEventListener('keypress', updateUserActivity);
|
|
1133
|
+
iframeDoc.removeEventListener('scroll', updateUserActivity);
|
|
1134
|
+
iframeDoc.removeEventListener('click', updateUserActivity);
|
|
1135
|
+
iframeDoc.removeEventListener('touchstart', updateUserActivity);
|
|
1136
|
+
}
|
|
1137
|
+
} catch {
|
|
1138
|
+
// Ignore cleanup errors
|
|
1139
|
+
}
|
|
1140
|
+
}
|
|
1141
|
+
};
|
|
1142
|
+
}, [
|
|
1143
|
+
jupyterReady
|
|
1144
|
+
]);
|
|
1021
1145
|
/* ---- Wait for JupyterLite app inside the iframe --------------- */ useEffect(()=>{
|
|
1022
1146
|
if (!iframeRef.current || loadError) return;
|
|
1023
1147
|
if (jupyterReady) return;
|
|
@@ -1209,6 +1333,7 @@ const MicroContainerReduxPanel = ({ compact = false })=>{
|
|
|
1209
1333
|
className: "min-h-0 flex-1 border-0",
|
|
1210
1334
|
onLoad: ()=>{
|
|
1211
1335
|
setLoading(false);
|
|
1336
|
+
setJupyterReady(true);
|
|
1212
1337
|
},
|
|
1213
1338
|
onError: ()=>{
|
|
1214
1339
|
setLoadError(true);
|