@datalayer/core 1.0.20 → 1.0.22
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/README.md +27 -0
- package/lib/api/DatalayerApi.d.ts +5 -1
- package/lib/api/DatalayerApi.js +55 -8
- package/lib/api/iam/oauth2.d.ts +3 -3
- package/lib/api/iam/oauth2.js +2 -2
- package/lib/api/iam/profile.d.ts +9 -1
- package/lib/api/iam/profile.js +15 -0
- package/lib/api/runtimes/checkpoints.js +1 -1
- package/lib/api/runtimes/snapshots.d.ts +7 -7
- package/lib/api/runtimes/snapshots.js +9 -9
- package/lib/client/auth/storage.js +103 -12
- package/lib/client/index.d.ts +7 -7
- package/lib/client/index.js +1 -1
- package/lib/client/mixins/RuntimesMixin.d.ts +6 -6
- package/lib/client/mixins/RuntimesMixin.js +5 -5
- package/lib/client/mixins/SpacerMixin.js +22 -1
- package/lib/collaboration/DatalayerCollaborationProvider.d.ts +4 -3
- package/lib/components/avatars/DLAvatar.d.ts +24 -0
- package/lib/components/avatars/DLAvatar.js +26 -0
- package/lib/components/avatars/UserProfileAvatar.js +4 -4
- package/lib/components/avatars/index.d.ts +1 -0
- package/lib/components/avatars/index.js +1 -0
- package/lib/components/billing/BillableAccountSelect.d.ts +35 -0
- package/lib/components/billing/BillableAccountSelect.js +340 -0
- package/lib/components/billing/index.d.ts +1 -0
- package/lib/components/billing/index.js +5 -0
- package/lib/components/checkout/StripeCheckout.d.ts +24 -3
- package/lib/components/checkout/StripeCheckout.js +1116 -55
- package/lib/components/display/DatalayerBox.js +6 -1
- package/lib/components/index.d.ts +2 -0
- package/lib/components/index.js +2 -0
- package/lib/components/principal/Principal.d.ts +37 -0
- package/lib/components/principal/Principal.js +54 -0
- package/lib/components/principal/PrincipalAvatar.d.ts +10 -0
- package/lib/components/principal/PrincipalAvatar.js +55 -0
- package/lib/components/principal/PrincipalBadge.d.ts +20 -0
- package/lib/components/principal/PrincipalBadge.js +208 -0
- package/lib/components/principal/PrincipalBanner.d.ts +7 -0
- package/lib/components/principal/PrincipalBanner.js +84 -0
- package/lib/components/principal/PrincipalDetailsOverlay.d.ts +23 -0
- package/lib/components/principal/PrincipalDetailsOverlay.js +86 -0
- package/lib/components/principal/PrincipalSwitcherMenu.d.ts +14 -0
- package/lib/components/principal/PrincipalSwitcherMenu.js +287 -0
- package/lib/components/principal/index.d.ts +7 -0
- package/lib/components/principal/index.js +10 -0
- package/lib/components/runtimes/RuntimeLauncherDialog.d.ts +2 -2
- package/lib/components/sharing/ShareAccessComponent.d.ts +18 -0
- package/lib/components/sharing/ShareAccessComponent.js +1368 -0
- package/lib/components/sharing/SharingEditor.d.ts +20 -0
- package/lib/components/sharing/SharingEditor.js +65 -0
- package/lib/components/sharing/index.d.ts +9 -0
- package/lib/components/sharing/index.js +12 -0
- package/lib/components/snapshots/{RuntimeSnapshotMenu.d.ts → SandboxSnapshotMenu.d.ts} +4 -4
- package/lib/components/snapshots/{RuntimeSnapshotMenu.js → SandboxSnapshotMenu.js} +33 -33
- package/lib/components/snapshots/index.d.ts +1 -1
- package/lib/components/snapshots/index.js +1 -1
- package/lib/components/storage/ContentsBrowser.js +2 -2
- package/lib/components/tokens/SpaceVariantToken.d.ts +1 -1
- package/lib/components/tokens/SpaceVariantToken.js +7 -4
- package/lib/components/users/PeerIndicator.js +5 -4
- package/lib/hooks/index.d.ts +5 -0
- package/lib/hooks/index.js +5 -0
- package/lib/hooks/useBillableAccountStore.d.ts +31 -0
- package/lib/hooks/useBillableAccountStore.js +53 -0
- package/lib/hooks/useCache.d.ts +125 -18
- package/lib/hooks/useCache.js +893 -120
- package/lib/hooks/useDatalayer.js +31 -3
- package/lib/hooks/useIAM.js +1 -8
- package/lib/hooks/usePrincipalStore.d.ts +41 -0
- package/lib/hooks/usePrincipalStore.js +101 -0
- package/lib/hooks/useProjects.d.ts +44 -0
- package/lib/hooks/useProjects.js +26 -2
- package/lib/hooks/useSelectedBillableAccount.d.ts +14 -0
- package/lib/hooks/useSelectedBillableAccount.js +36 -0
- package/lib/hooks/useSelectedPrincipal.d.ts +17 -0
- package/lib/hooks/useSelectedPrincipal.js +29 -0
- package/lib/hooks/useUsageRefreshStore.d.ts +8 -0
- package/lib/hooks/useUsageRefreshStore.js +16 -0
- package/lib/index.d.ts +2 -2
- package/lib/index.js +1 -1
- package/lib/mocks/components/FlashMock.js +8 -2
- package/lib/models/{RuntimeSnapshot.d.ts → CodeSandboxSnapshot.d.ts} +5 -5
- package/lib/models/{RuntimeSnapshot.js → CodeSandboxSnapshot.js} +1 -1
- package/lib/models/{RuntimeSnapshotDTO.d.ts → CodeSandboxSnapshotDTO.d.ts} +30 -30
- package/lib/models/{RuntimeSnapshotDTO.js → CodeSandboxSnapshotDTO.js} +6 -6
- package/lib/models/Environment.d.ts +4 -0
- package/lib/models/IAM.d.ts +66 -0
- package/lib/models/Organization.d.ts +1 -0
- package/lib/models/Organization.js +1 -0
- package/lib/models/Page.d.ts +2 -2
- package/lib/models/Page.js +2 -2
- package/lib/models/Profile.d.ts +1 -1
- package/lib/models/RuntimeDTO.d.ts +2 -2
- package/lib/models/Space.d.ts +1 -0
- package/lib/models/Space.js +29 -5
- package/lib/models/SpaceDTO.d.ts +4 -0
- package/lib/models/SpaceDTO.js +5 -0
- package/lib/models/Usage.d.ts +15 -0
- package/lib/models/Usage.js +9 -0
- package/lib/models/User.d.ts +21 -0
- package/lib/models/User.js +6 -2
- package/lib/models/index.d.ts +2 -2
- package/lib/models/index.js +2 -2
- package/lib/otel/auth.js +0 -4
- package/lib/services/index.d.ts +1 -1
- package/lib/services/index.js +1 -1
- package/lib/state/substates/IAMState.js +0 -7
- package/lib/state/substates/RuntimesState.d.ts +9 -9
- package/lib/state/substates/RuntimesState.js +3 -3
- package/lib/stateful/runtimes/actions.d.ts +17 -17
- package/lib/stateful/runtimes/actions.js +35 -55
- package/lib/stateful/runtimes/apis.d.ts +3 -3
- package/lib/stateful/runtimes/snapshots.d.ts +2 -2
- package/lib/stateful/runtimes/snapshots.js +7 -7
- package/lib/utils/Format.d.ts +6 -0
- package/lib/utils/Format.js +17 -0
- package/lib/utils/Handles.d.ts +3 -0
- package/lib/utils/Handles.js +53 -0
- package/lib/utils/Snapshot.d.ts +1 -1
- package/lib/utils/Snapshot.js +1 -1
- package/lib/utils/index.d.ts +1 -0
- package/lib/utils/index.js +1 -0
- package/lib/views/datasources/DatasourceDetail.d.ts +7 -1
- package/lib/views/datasources/DatasourceDetail.js +61 -23
- package/lib/views/datasources/DatasourceNew.d.ts +8 -1
- package/lib/views/datasources/DatasourceNew.js +23 -10
- package/lib/views/datasources/Datasources.d.ts +5 -1
- package/lib/views/datasources/Datasources.js +38 -30
- package/lib/views/iam-tokens/IAMTokenNew.d.ts +3 -1
- package/lib/views/iam-tokens/IAMTokenNew.js +2 -2
- package/lib/views/iam-tokens/IAMTokens.d.ts +3 -1
- package/lib/views/iam-tokens/IAMTokens.js +2 -2
- package/lib/views/otel/OtelHeader.d.ts +5 -0
- package/lib/views/otel/OtelHeader.js +3 -3
- package/lib/views/profile/UserBadge.d.ts +7 -2
- package/lib/views/profile/UserBadge.js +11 -2
- package/lib/views/secrets/Secrets.js +21 -21
- package/package.json +7 -8
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
export type SharingAccessLevel = 'view' | 'update' | 'execute';
|
|
2
|
+
export type SharingLevelPayload = {
|
|
3
|
+
userUids?: string[];
|
|
4
|
+
teamUids?: string[];
|
|
5
|
+
organizationUids?: string[];
|
|
6
|
+
};
|
|
7
|
+
export type SharingPayload = {
|
|
8
|
+
access?: Partial<Record<SharingAccessLevel, SharingLevelPayload>>;
|
|
9
|
+
};
|
|
10
|
+
export declare const EMPTY_SHARING_PAYLOAD: SharingPayload;
|
|
11
|
+
export type SharingEditorProps = {
|
|
12
|
+
value: SharingPayload;
|
|
13
|
+
onChange: (next: SharingPayload) => void;
|
|
14
|
+
label?: string;
|
|
15
|
+
caption?: string;
|
|
16
|
+
rows?: number;
|
|
17
|
+
disabled?: boolean;
|
|
18
|
+
};
|
|
19
|
+
export declare function SharingEditor({ value, onChange, label, caption, rows, disabled, }: SharingEditorProps): JSX.Element;
|
|
20
|
+
export default SharingEditor;
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
/*
|
|
3
|
+
* Copyright (c) 2023-2026 Datalayer, Inc.
|
|
4
|
+
* Distributed under the terms of the Modified BSD License.
|
|
5
|
+
*/
|
|
6
|
+
/**
|
|
7
|
+
* SharingEditor — inline editor for the sharing payload shape used by
|
|
8
|
+
* `ShareAccessComponent` ACL endpoints.
|
|
9
|
+
*
|
|
10
|
+
* Unlike `ShareAccessComponent` (which is bound to a server-side resource
|
|
11
|
+
* via `requestUrl`), this component edits a free-form
|
|
12
|
+
* `{ access: { view/update/execute: { userUids, teamUids, organizationUids } } }`
|
|
13
|
+
* blob in memory. It is intended for "create" flows where the resource does
|
|
14
|
+
* not yet exist and the sharing payload must be POSTed alongside the rest of
|
|
15
|
+
* the configuration.
|
|
16
|
+
*
|
|
17
|
+
* This is a scaffold: it currently exposes a structured JSON editor with
|
|
18
|
+
* validation and the canonical default shape. Future iterations can replace
|
|
19
|
+
* the textarea with the same principal-picker UI used by
|
|
20
|
+
* `ShareAccessComponent`.
|
|
21
|
+
*/
|
|
22
|
+
import { useEffect, useMemo, useState } from 'react';
|
|
23
|
+
import { Box } from '@datalayer/primer-addons';
|
|
24
|
+
import { FormControl, Text, Textarea } from '@primer/react';
|
|
25
|
+
export const EMPTY_SHARING_PAYLOAD = {
|
|
26
|
+
access: {
|
|
27
|
+
view: { userUids: [], teamUids: [], organizationUids: [] },
|
|
28
|
+
update: { userUids: [], teamUids: [], organizationUids: [] },
|
|
29
|
+
execute: { userUids: [], teamUids: [], organizationUids: [] },
|
|
30
|
+
},
|
|
31
|
+
};
|
|
32
|
+
const stringify = (value) => {
|
|
33
|
+
try {
|
|
34
|
+
return JSON.stringify(value ?? {}, null, 2);
|
|
35
|
+
}
|
|
36
|
+
catch {
|
|
37
|
+
return '{}';
|
|
38
|
+
}
|
|
39
|
+
};
|
|
40
|
+
export function SharingEditor({ value, onChange, label = 'Sharing', caption = 'Edit the sharing payload. Each access level (view/update/execute) can grant access to user, team, and organization UIDs.', rows = 10, disabled = false, }) {
|
|
41
|
+
const initial = useMemo(() => stringify(value), [value]);
|
|
42
|
+
const [raw, setRaw] = useState(initial);
|
|
43
|
+
const [error, setError] = useState(null);
|
|
44
|
+
useEffect(() => {
|
|
45
|
+
setRaw(stringify(value));
|
|
46
|
+
}, [value]);
|
|
47
|
+
return (_jsxs(FormControl, { disabled: disabled, children: [_jsx(FormControl.Label, { children: label }), _jsx(Textarea, { rows: rows, value: raw, onChange: event => {
|
|
48
|
+
const next = event.target.value;
|
|
49
|
+
setRaw(next);
|
|
50
|
+
if (!next.trim()) {
|
|
51
|
+
setError(null);
|
|
52
|
+
onChange({});
|
|
53
|
+
return;
|
|
54
|
+
}
|
|
55
|
+
try {
|
|
56
|
+
const parsed = JSON.parse(next);
|
|
57
|
+
setError(null);
|
|
58
|
+
onChange(parsed);
|
|
59
|
+
}
|
|
60
|
+
catch (reason) {
|
|
61
|
+
setError(reason?.message || 'Invalid JSON');
|
|
62
|
+
}
|
|
63
|
+
}, sx: { width: '100%', fontFamily: 'mono' } }), _jsx(FormControl.Caption, { children: caption }), error && (_jsx(Box, { sx: { mt: 1 }, children: _jsx(Text, { sx: { color: 'danger.fg', fontSize: 1 }, children: error }) }))] }));
|
|
64
|
+
}
|
|
65
|
+
export default SharingEditor;
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
export * from '../principal/Principal';
|
|
2
|
+
export * from '../principal/PrincipalAvatar';
|
|
3
|
+
export * from '../principal/PrincipalBadge';
|
|
4
|
+
export * from '../principal/PrincipalBanner';
|
|
5
|
+
export { buildPrincipalProfilePath, PrincipalDetailsOverlay, } from '../principal/PrincipalDetailsOverlay';
|
|
6
|
+
export type { PrincipalDetailsOverlayProps } from '../principal/PrincipalDetailsOverlay';
|
|
7
|
+
export * from '../principal/PrincipalSwitcherMenu';
|
|
8
|
+
export * from './ShareAccessComponent';
|
|
9
|
+
export * from './SharingEditor';
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright (c) 2023-2025 Datalayer, Inc.
|
|
3
|
+
* Distributed under the terms of the Modified BSD License.
|
|
4
|
+
*/
|
|
5
|
+
export * from '../principal/Principal.js';
|
|
6
|
+
export * from '../principal/PrincipalAvatar.js';
|
|
7
|
+
export * from '../principal/PrincipalBadge.js';
|
|
8
|
+
export * from '../principal/PrincipalBanner.js';
|
|
9
|
+
export { buildPrincipalProfilePath, PrincipalDetailsOverlay, } from '../principal/PrincipalDetailsOverlay.js';
|
|
10
|
+
export * from '../principal/PrincipalSwitcherMenu.js';
|
|
11
|
+
export * from './ShareAccessComponent.js';
|
|
12
|
+
export * from './SharingEditor.js';
|
|
@@ -2,9 +2,9 @@ import { type PropsWithChildren } from 'react';
|
|
|
2
2
|
import { Kernel } from '@jupyterlab/services';
|
|
3
3
|
import { IMultiServiceManager } from '../../stateful/runtimes';
|
|
4
4
|
/**
|
|
5
|
-
*
|
|
5
|
+
* Code Sandbox snapshot menu component properties
|
|
6
6
|
*/
|
|
7
|
-
type
|
|
7
|
+
type ICodeSandboxSnapshotMenu = {
|
|
8
8
|
/**
|
|
9
9
|
* Application multi service manager.
|
|
10
10
|
*/
|
|
@@ -27,7 +27,7 @@ type IRuntimeSnapshotMenu = {
|
|
|
27
27
|
disabled: boolean;
|
|
28
28
|
};
|
|
29
29
|
/**
|
|
30
|
-
*
|
|
30
|
+
* Code Sandbox Snapshot menu component.
|
|
31
31
|
*/
|
|
32
|
-
export declare function
|
|
32
|
+
export declare function SandboxSnapshotMenu({ children, connection, podName, multiServiceManager, disabled, }: PropsWithChildren<ICodeSandboxSnapshotMenu>): JSX.Element;
|
|
33
33
|
export {};
|
|
@@ -4,29 +4,29 @@ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-run
|
|
|
4
4
|
* Distributed under the terms of the Modified BSD License.
|
|
5
5
|
*/
|
|
6
6
|
import { useCallback, useEffect, useState, } from 'react';
|
|
7
|
-
import {
|
|
7
|
+
import { DeviceCameraIcon } from '@primer/octicons-react';
|
|
8
8
|
import { ActionList, ActionMenu, Flash, FormControl, Select, Spinner, } from '@primer/react';
|
|
9
9
|
import { Dialog } from '@primer/react/experimental';
|
|
10
10
|
import { Box } from '@datalayer/primer-addons';
|
|
11
11
|
import { useToast } from '../../hooks/index.js';
|
|
12
|
-
import {
|
|
12
|
+
import { createSandboxSnapshot, getSandboxSnapshots, loadBrowserSandboxSnapshot, loadSandboxSnapshot, } from '../../stateful/runtimes/index.js';
|
|
13
13
|
import { useRuntimesStore } from '../../state/index.js';
|
|
14
|
-
import {
|
|
14
|
+
import { createSandboxSnapshotName } from '../../utils/index.js';
|
|
15
15
|
/**
|
|
16
|
-
*
|
|
16
|
+
* Code Sandbox Snapshot menu component.
|
|
17
17
|
*/
|
|
18
|
-
export function
|
|
19
|
-
const {
|
|
18
|
+
export function SandboxSnapshotMenu({ children, connection, podName, multiServiceManager, disabled = false, }) {
|
|
19
|
+
const { addSandboxSnapshot, runtimesRunUrl, runtimeSnapshots, setSandboxSnapshots, } = useRuntimesStore();
|
|
20
20
|
const { enqueueToast, trackAsyncTask } = useToast();
|
|
21
21
|
const [openLoadDialog, setOpenLoadDialog] = useState(false);
|
|
22
|
-
const [
|
|
23
|
-
const [
|
|
22
|
+
const [loadingSandboxSnapshot, setLoadingSandboxSnapshot] = useState(false);
|
|
23
|
+
const [takingSandboxSnapshot, setTakingSandboxSnapshot] = useState(false);
|
|
24
24
|
const [selection, setSelection] = useState(runtimeSnapshots[0]?.id ?? '');
|
|
25
25
|
const [error, setError] = useState();
|
|
26
26
|
useEffect(() => {
|
|
27
|
-
|
|
27
|
+
getSandboxSnapshots()
|
|
28
28
|
.then(snapshots => {
|
|
29
|
-
|
|
29
|
+
setSandboxSnapshots(snapshots);
|
|
30
30
|
if (!selection && snapshots.length > 0) {
|
|
31
31
|
setSelection(snapshots[0].id);
|
|
32
32
|
}
|
|
@@ -35,36 +35,36 @@ export function RuntimeSnapshotMenu({ children, connection, podName, multiServic
|
|
|
35
35
|
console.error(`Failed to fetch remote kernel snapshots; ${reason}`);
|
|
36
36
|
});
|
|
37
37
|
}, [runtimesRunUrl]);
|
|
38
|
-
const
|
|
38
|
+
const onLoadSandboxSnapshot = useCallback(() => {
|
|
39
39
|
setError(undefined);
|
|
40
40
|
setOpenLoadDialog(true);
|
|
41
41
|
}, []);
|
|
42
|
-
const
|
|
42
|
+
const onSandboxSnapshotChanged = useCallback(event => {
|
|
43
43
|
setSelection(event.target.value);
|
|
44
44
|
}, []);
|
|
45
|
-
const
|
|
45
|
+
const onLoadSandboxSnapshotSubmit = useCallback(async ({ id, connection, podName, }) => {
|
|
46
46
|
if (podName) {
|
|
47
|
-
await
|
|
48
|
-
enqueueToast(`
|
|
47
|
+
await loadSandboxSnapshot({ id: podName, from: id });
|
|
48
|
+
enqueueToast(`Code Sandbox snapshot ${podName} is loaded.`, {
|
|
49
49
|
variant: 'success',
|
|
50
50
|
});
|
|
51
51
|
}
|
|
52
52
|
else if (connection) {
|
|
53
|
-
await
|
|
54
|
-
enqueueToast(`
|
|
53
|
+
await loadBrowserSandboxSnapshot({ connection, id });
|
|
54
|
+
enqueueToast(`Code Sandbox snapshot ${id} is loaded.`, {
|
|
55
55
|
variant: 'success',
|
|
56
56
|
});
|
|
57
57
|
}
|
|
58
58
|
}, []);
|
|
59
|
-
const
|
|
59
|
+
const onTakeSandboxSnapshot = useCallback(async () => {
|
|
60
60
|
try {
|
|
61
|
-
|
|
61
|
+
setTakingSandboxSnapshot(true);
|
|
62
62
|
let snapshot;
|
|
63
63
|
let task;
|
|
64
64
|
let ref = '';
|
|
65
65
|
let snapshotName = '';
|
|
66
66
|
if (podName && multiServiceManager?.remote) {
|
|
67
|
-
snapshotName =
|
|
67
|
+
snapshotName = createSandboxSnapshotName('cloud');
|
|
68
68
|
task = multiServiceManager.remote.runtimesManager.snapshotRuntime({
|
|
69
69
|
podName,
|
|
70
70
|
name: snapshotName,
|
|
@@ -79,9 +79,9 @@ export function RuntimeSnapshotMenu({ children, connection, podName, multiServic
|
|
|
79
79
|
else if (connection && multiServiceManager?.browser) {
|
|
80
80
|
const model = connection.model;
|
|
81
81
|
ref = model.id;
|
|
82
|
-
snapshotName =
|
|
82
|
+
snapshotName = createSandboxSnapshotName('browser');
|
|
83
83
|
let isPending = true;
|
|
84
|
-
task =
|
|
84
|
+
task = createSandboxSnapshot({
|
|
85
85
|
connection: multiServiceManager.browser.kernels.connectTo({
|
|
86
86
|
model,
|
|
87
87
|
}),
|
|
@@ -90,7 +90,7 @@ export function RuntimeSnapshotMenu({ children, connection, podName, multiServic
|
|
|
90
90
|
if (isPending) {
|
|
91
91
|
isPending = false;
|
|
92
92
|
// Get the kernel snapshot uid.
|
|
93
|
-
|
|
93
|
+
getSandboxSnapshots().then(snapshots => {
|
|
94
94
|
snapshot = snapshots.find(s => s.name === snapshotName);
|
|
95
95
|
});
|
|
96
96
|
}
|
|
@@ -114,15 +114,15 @@ export function RuntimeSnapshotMenu({ children, connection, podName, multiServic
|
|
|
114
114
|
});
|
|
115
115
|
await task;
|
|
116
116
|
if (snapshot) {
|
|
117
|
-
|
|
117
|
+
addSandboxSnapshot(snapshot);
|
|
118
118
|
}
|
|
119
119
|
}
|
|
120
120
|
}
|
|
121
121
|
finally {
|
|
122
|
-
|
|
122
|
+
setTakingSandboxSnapshot(false);
|
|
123
123
|
}
|
|
124
124
|
}, [connection, podName, multiServiceManager]);
|
|
125
|
-
return (_jsxs(_Fragment, { children: [_jsxs(ActionMenu, { children: [_jsx(ActionMenu.Button, { leadingVisual:
|
|
125
|
+
return (_jsxs(_Fragment, { children: [_jsxs(ActionMenu, { children: [_jsx(ActionMenu.Button, { leadingVisual: DeviceCameraIcon, variant: "invisible", size: "small", disabled: loadingSandboxSnapshot || takingSandboxSnapshot || disabled, children: children }), _jsx(ActionMenu.Overlay, { children: _jsxs(ActionList, { children: [_jsx(ActionList.Item, { onSelect: onLoadSandboxSnapshot, disabled: loadingSandboxSnapshot || runtimeSnapshots.length === 0, children: "Load a code sandbox snapshot\u2026" }), _jsx(ActionList.Item, { onSelect: onTakeSandboxSnapshot, disabled: takingSandboxSnapshot, children: "Take a code sandbox snapshot" })] }) })] }), openLoadDialog && (_jsx(Dialog, { title: _jsx("span", { style: { color: 'var(--fgColor-default)' }, children: "Choose a code sandbox snapshot to load" }), onClose: () => {
|
|
126
126
|
setOpenLoadDialog(false);
|
|
127
127
|
}, footerButtons: [
|
|
128
128
|
{
|
|
@@ -137,33 +137,33 @@ export function RuntimeSnapshotMenu({ children, connection, podName, multiServic
|
|
|
137
137
|
},
|
|
138
138
|
{
|
|
139
139
|
buttonType: 'primary',
|
|
140
|
-
content:
|
|
141
|
-
disabled:
|
|
140
|
+
content: loadingSandboxSnapshot ? (_jsx(Spinner, { size: "small" })) : ('Load'),
|
|
141
|
+
disabled: loadingSandboxSnapshot,
|
|
142
142
|
onClick: async (event) => {
|
|
143
143
|
if (!event.defaultPrevented) {
|
|
144
144
|
event.preventDefault();
|
|
145
|
-
|
|
145
|
+
setLoadingSandboxSnapshot(true);
|
|
146
146
|
try {
|
|
147
147
|
setError(undefined);
|
|
148
148
|
const snapshot = runtimeSnapshots.find(s => s.id === selection);
|
|
149
149
|
if (snapshot && (connection || podName)) {
|
|
150
|
-
await
|
|
150
|
+
await onLoadSandboxSnapshotSubmit({
|
|
151
151
|
connection,
|
|
152
152
|
id: snapshot.id,
|
|
153
153
|
podName,
|
|
154
154
|
});
|
|
155
155
|
}
|
|
156
156
|
else {
|
|
157
|
-
setError('No
|
|
157
|
+
setError('No code sandbox snapshot found.');
|
|
158
158
|
}
|
|
159
159
|
}
|
|
160
160
|
finally {
|
|
161
|
-
|
|
161
|
+
setLoadingSandboxSnapshot(false);
|
|
162
162
|
setOpenLoadDialog(false);
|
|
163
163
|
}
|
|
164
164
|
}
|
|
165
165
|
},
|
|
166
166
|
autoFocus: true,
|
|
167
167
|
},
|
|
168
|
-
], children: _jsxs(Box, { as: "form", children: [_jsxs(FormControl, { children: [_jsx(FormControl.Label, { children: "Snapshot" }), _jsx(Select, { name: "snapshot", value: selection, onChange:
|
|
168
|
+
], children: _jsxs(Box, { as: "form", children: [_jsxs(FormControl, { children: [_jsx(FormControl.Label, { children: "Snapshot" }), _jsx(Select, { name: "snapshot", value: selection, onChange: onSandboxSnapshotChanged, block: true, children: runtimeSnapshots.map(s => (_jsx(Select.Option, { value: s.id, children: s.name ? `${s.name} (${s.id})` : s.id }, s.id))) })] }), error && _jsx(Flash, { variant: "danger", children: error })] }) }))] }));
|
|
169
169
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
export * from './
|
|
1
|
+
export * from './SandboxSnapshotMenu';
|
|
@@ -9,7 +9,7 @@ import { PromiseDelegate } from '@lumino/coreutils';
|
|
|
9
9
|
import { ActionList, ActionMenu, Heading, IconButton, Spinner, TreeView, } from '@primer/react';
|
|
10
10
|
import { Box } from '@datalayer/primer-addons';
|
|
11
11
|
import { Blankslate, Dialog } from '@primer/react/experimental';
|
|
12
|
-
import {
|
|
12
|
+
import { SyncIcon } from '@primer/octicons-react';
|
|
13
13
|
import { useIsMounted } from 'usehooks-ts';
|
|
14
14
|
import { useToast } from '../../hooks/index.js';
|
|
15
15
|
import { UploadIconButton } from '../buttons/index.js';
|
|
@@ -225,7 +225,7 @@ export function ContentsBrowser(props) {
|
|
|
225
225
|
alignItems: 'center',
|
|
226
226
|
flexWrap: 'nowrap',
|
|
227
227
|
flexShrink: 0,
|
|
228
|
-
}, children: [_jsx(IconButton, { variant: "invisible", "aria-label": 'Refresh contents browser.', title: 'Refresh contents browser.', icon:
|
|
228
|
+
}, children: [_jsx(IconButton, { variant: "invisible", "aria-label": 'Refresh contents browser.', title: 'Refresh contents browser.', icon: SyncIcon, onClick: refresh }), _jsx(UploadIconButton, { label: 'Upload a file', multiple: true, upload: upload })] })] }), isLoading ? (_jsx(Box, { sx: {
|
|
229
229
|
gridArea: 'content',
|
|
230
230
|
display: 'flex',
|
|
231
231
|
alignItems: 'center',
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { jsx as _jsx
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
2
|
/*
|
|
3
3
|
* Copyright (c) 2023-2025 Datalayer, Inc.
|
|
4
4
|
* Distributed under the terms of the Modified BSD License.
|
|
@@ -7,14 +7,17 @@ import { Token } from '@primer/react';
|
|
|
7
7
|
import { ProjectIcon } from '@primer/octicons-react';
|
|
8
8
|
import { StudentIcon } from '@datalayer/icons-react';
|
|
9
9
|
export const SpaceVariantToken = (props) => {
|
|
10
|
-
const
|
|
10
|
+
const variant = String(props.variant || 'default').toLowerCase();
|
|
11
|
+
if (variant.includes('project')) {
|
|
12
|
+
return _jsx(Token, { text: "project", leadingVisual: ProjectIcon });
|
|
13
|
+
}
|
|
11
14
|
switch (variant) {
|
|
12
15
|
case 'default':
|
|
13
|
-
return _jsx(Token, { text: "default"
|
|
16
|
+
return _jsx(Token, { text: "default" });
|
|
14
17
|
case 'course':
|
|
15
18
|
return _jsx(Token, { text: "course", leadingVisual: StudentIcon });
|
|
16
19
|
default:
|
|
17
|
-
return _jsx(
|
|
20
|
+
return _jsx(Token, { text: String(variant || 'default') });
|
|
18
21
|
}
|
|
19
22
|
};
|
|
20
23
|
export default SpaceVariantToken;
|
|
@@ -4,8 +4,9 @@ import { jsx as _jsx } from "react/jsx-runtime";
|
|
|
4
4
|
* Distributed under the terms of the Modified BSD License.
|
|
5
5
|
*/
|
|
6
6
|
import { useEffect, useState } from 'react';
|
|
7
|
-
import {
|
|
8
|
-
import {
|
|
7
|
+
import { AvatarStack } from '@primer/react';
|
|
8
|
+
import { getRelativeTime } from '../../utils/index.js';
|
|
9
|
+
import { DLAvatar } from '../avatars/index.js';
|
|
9
10
|
const AVATAR_SIZE = 28;
|
|
10
11
|
const SPACER_USER_AGENT = 'DatalayerSpacer';
|
|
11
12
|
const AWARENESS_NOTIFICATION_TIMEOUT_MS = 30_000;
|
|
@@ -89,12 +90,12 @@ export function PeersIndicator({ awareness, currentUserHandle, }) {
|
|
|
89
90
|
if (peer.notification) {
|
|
90
91
|
title += `\n${peer.notification}`;
|
|
91
92
|
}
|
|
92
|
-
return (_jsx(
|
|
93
|
+
return (_jsx(DLAvatar, { sx: {
|
|
93
94
|
border: peer.notificationType
|
|
94
95
|
? `var(--borderWidth-thick) solid ${peer.notificationType}`
|
|
95
96
|
: 'none',
|
|
96
97
|
}, title: title, src: peer.avatarUrl
|
|
97
|
-
?
|
|
98
|
+
? peer.avatarUrl
|
|
98
99
|
: defaultAvatarSrc(peer.color, peer.initials), size: AVATAR_SIZE }, peer.displayName));
|
|
99
100
|
}) }));
|
|
100
101
|
}
|
package/lib/hooks/index.d.ts
CHANGED
|
@@ -28,5 +28,10 @@ export * from './useUser';
|
|
|
28
28
|
export * from './useProjects';
|
|
29
29
|
export * from './useProjectStore';
|
|
30
30
|
export * from './useMobile';
|
|
31
|
+
export * from './useUsageRefreshStore';
|
|
32
|
+
export * from './usePrincipalStore';
|
|
33
|
+
export * from './useBillableAccountStore';
|
|
34
|
+
export * from './useSelectedPrincipal';
|
|
35
|
+
export * from './useSelectedBillableAccount';
|
|
31
36
|
export * from './useVisibilityObserver';
|
|
32
37
|
export * from './useWindowSize';
|
package/lib/hooks/index.js
CHANGED
|
@@ -33,5 +33,10 @@ export * from './useUser.js';
|
|
|
33
33
|
export * from './useProjects.js';
|
|
34
34
|
export * from './useProjectStore.js';
|
|
35
35
|
export * from './useMobile.js';
|
|
36
|
+
export * from './useUsageRefreshStore.js';
|
|
37
|
+
export * from './usePrincipalStore.js';
|
|
38
|
+
export * from './useBillableAccountStore.js';
|
|
39
|
+
export * from './useSelectedPrincipal.js';
|
|
40
|
+
export * from './useSelectedBillableAccount.js';
|
|
36
41
|
export * from './useVisibilityObserver.js';
|
|
37
42
|
export * from './useWindowSize.js';
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The kind of billable account currently in scope.
|
|
3
|
+
*
|
|
4
|
+
* An account is the *billable* principal — only users and organizations
|
|
5
|
+
* are accounts. Teams are NOT accounts; when a team is the selected
|
|
6
|
+
* principal, the billable account is the team's parent organization.
|
|
7
|
+
*/
|
|
8
|
+
export type BillableAccountKind = 'user' | 'organization';
|
|
9
|
+
export type BillableAccountState = {
|
|
10
|
+
billableAccountKind: BillableAccountKind;
|
|
11
|
+
billableAccountUid?: string;
|
|
12
|
+
billableAccountHandle?: string;
|
|
13
|
+
setBillableAccount: (args: {
|
|
14
|
+
kind: BillableAccountKind;
|
|
15
|
+
uid: string;
|
|
16
|
+
handle: string;
|
|
17
|
+
}) => void;
|
|
18
|
+
resetBillableAccount: () => void;
|
|
19
|
+
};
|
|
20
|
+
export declare const useBillableAccountStore: import("zustand").UseBoundStore<Omit<import("zustand").StoreApi<BillableAccountState>, "persist"> & {
|
|
21
|
+
persist: {
|
|
22
|
+
setOptions: (options: Partial<import("zustand/middleware").PersistOptions<BillableAccountState, unknown>>) => void;
|
|
23
|
+
clearStorage: () => void;
|
|
24
|
+
rehydrate: () => Promise<void> | void;
|
|
25
|
+
hasHydrated: () => boolean;
|
|
26
|
+
onHydrate: (fn: (state: BillableAccountState) => void) => () => void;
|
|
27
|
+
onFinishHydration: (fn: (state: BillableAccountState) => void) => () => void;
|
|
28
|
+
getOptions: () => Partial<import("zustand/middleware").PersistOptions<BillableAccountState, unknown>>;
|
|
29
|
+
};
|
|
30
|
+
}>;
|
|
31
|
+
export default useBillableAccountStore;
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright (c) 2023-2025 Datalayer, Inc.
|
|
3
|
+
* Distributed under the terms of the Modified BSD License.
|
|
4
|
+
*/
|
|
5
|
+
import { create } from 'zustand';
|
|
6
|
+
import { createJSONStorage, persist } from 'zustand/middleware';
|
|
7
|
+
import { useUsageRefreshStore } from './useUsageRefreshStore.js';
|
|
8
|
+
export const useBillableAccountStore = create()(persist(set => ({
|
|
9
|
+
billableAccountKind: 'user',
|
|
10
|
+
billableAccountUid: undefined,
|
|
11
|
+
billableAccountHandle: undefined,
|
|
12
|
+
setBillableAccount: ({ kind, uid, handle }) => set(state => {
|
|
13
|
+
const unchanged = state.billableAccountKind === kind &&
|
|
14
|
+
state.billableAccountUid === uid &&
|
|
15
|
+
state.billableAccountHandle === handle;
|
|
16
|
+
if (unchanged) {
|
|
17
|
+
return state;
|
|
18
|
+
}
|
|
19
|
+
useUsageRefreshStore
|
|
20
|
+
.getState()
|
|
21
|
+
.requestUsageRefresh('billable-account-changed');
|
|
22
|
+
return {
|
|
23
|
+
billableAccountKind: kind,
|
|
24
|
+
billableAccountUid: uid,
|
|
25
|
+
billableAccountHandle: handle,
|
|
26
|
+
};
|
|
27
|
+
}),
|
|
28
|
+
resetBillableAccount: () => set(state => {
|
|
29
|
+
const unchanged = state.billableAccountKind === 'user' &&
|
|
30
|
+
state.billableAccountUid === undefined &&
|
|
31
|
+
state.billableAccountHandle === undefined;
|
|
32
|
+
if (unchanged) {
|
|
33
|
+
return state;
|
|
34
|
+
}
|
|
35
|
+
useUsageRefreshStore
|
|
36
|
+
.getState()
|
|
37
|
+
.requestUsageRefresh('billable-account-reset');
|
|
38
|
+
return {
|
|
39
|
+
billableAccountKind: 'user',
|
|
40
|
+
billableAccountUid: undefined,
|
|
41
|
+
billableAccountHandle: undefined,
|
|
42
|
+
};
|
|
43
|
+
}),
|
|
44
|
+
}), {
|
|
45
|
+
name: 'datalayer-billable-account',
|
|
46
|
+
storage: createJSONStorage(() => localStorage),
|
|
47
|
+
partialize: state => ({
|
|
48
|
+
billableAccountKind: state.billableAccountKind,
|
|
49
|
+
billableAccountUid: state.billableAccountUid,
|
|
50
|
+
billableAccountHandle: state.billableAccountHandle,
|
|
51
|
+
}),
|
|
52
|
+
}));
|
|
53
|
+
export default useBillableAccountStore;
|