@datalayer/core 1.2.18 → 1.2.20
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/lib/cli-login.js +5 -51
- package/lib/components/anonymous/AnonymousKeyExpired.js +1 -15
- package/lib/components/anonymous/AnonymousKeyTimer.js +5 -15
- package/lib/components/auth/SignIn.js +2 -2
- package/lib/components/avatars/UserAvatar.d.ts +10 -11
- package/lib/components/avatars/UserAvatar.js +23 -52
- package/lib/components/avatars/UserProfileAvatar.js +1 -1
- package/lib/components/avatars/avatarChoice.d.ts +42 -0
- package/lib/components/avatars/avatarChoice.js +65 -0
- package/lib/components/avatars/index.d.ts +1 -0
- package/lib/components/avatars/index.js +1 -0
- package/lib/components/billing/BillingEntitySelect.js +6 -48
- package/lib/components/checkout/StripeCheckout.js +33 -217
- package/lib/components/collaboration/LiveEditorCollaborators.d.ts +3 -4
- package/lib/components/collaboration/LiveEditorCollaborators.js +7 -5
- package/lib/components/contents/ContentSourceCard.js +2 -11
- package/lib/components/contents/HomeFolderObjectsBrowser.d.ts +1 -1
- package/lib/components/contents/HomeFolderObjectsBrowser.js +11 -35
- package/lib/components/display/CenteredSpinner.js +1 -6
- package/lib/components/display/DatalayerBox.js +2 -14
- package/lib/components/emoji/faceEmojis.js +48 -0
- package/lib/components/emoji/fluent/loaders.js +46 -0
- package/lib/components/emoji/fluent/svg/1f30a.d.ts +2 -0
- package/lib/components/emoji/fluent/svg/1f30a.js +5 -0
- package/lib/components/emoji/fluent/svg/1f310.d.ts +2 -0
- package/lib/components/emoji/fluent/svg/1f310.js +5 -0
- package/lib/components/emoji/fluent/svg/1f324.d.ts +2 -0
- package/lib/components/emoji/fluent/svg/1f324.js +5 -0
- package/lib/components/emoji/fluent/svg/1f326.d.ts +2 -0
- package/lib/components/emoji/fluent/svg/1f326.js +5 -0
- package/lib/components/emoji/fluent/svg/1f327.d.ts +2 -0
- package/lib/components/emoji/fluent/svg/1f327.js +5 -0
- package/lib/components/emoji/fluent/svg/1f33e.d.ts +2 -0
- package/lib/components/emoji/fluent/svg/1f33e.js +5 -0
- package/lib/components/emoji/fluent/svg/1f372.d.ts +2 -0
- package/lib/components/emoji/fluent/svg/1f372.js +5 -0
- package/lib/components/emoji/fluent/svg/1f373.d.ts +2 -0
- package/lib/components/emoji/fluent/svg/1f373.js +5 -0
- package/lib/components/emoji/fluent/svg/1f39b.d.ts +2 -0
- package/lib/components/emoji/fluent/svg/1f39b.js +5 -0
- package/lib/components/emoji/fluent/svg/1f3ab.d.ts +2 -0
- package/lib/components/emoji/fluent/svg/1f3ab.js +5 -0
- package/lib/components/emoji/fluent/svg/1f41b.d.ts +2 -0
- package/lib/components/emoji/fluent/svg/1f41b.js +5 -0
- package/lib/components/emoji/fluent/svg/1f441.d.ts +2 -0
- package/lib/components/emoji/fluent/svg/1f441.js +5 -0
- package/lib/components/emoji/fluent/svg/1f465.d.ts +2 -0
- package/lib/components/emoji/fluent/svg/1f465.js +5 -0
- package/lib/components/emoji/fluent/svg/1f4b9.d.ts +2 -0
- package/lib/components/emoji/fluent/svg/1f4b9.js +5 -0
- package/lib/components/emoji/fluent/svg/1f4be.d.ts +2 -0
- package/lib/components/emoji/fluent/svg/1f4be.js +5 -0
- package/lib/components/emoji/fluent/svg/1f4c1.d.ts +2 -0
- package/lib/components/emoji/fluent/svg/1f4c1.js +5 -0
- package/lib/components/emoji/fluent/svg/1f4c2.d.ts +2 -0
- package/lib/components/emoji/fluent/svg/1f4c2.js +5 -0
- package/lib/components/emoji/fluent/svg/1f4c4.d.ts +2 -0
- package/lib/components/emoji/fluent/svg/1f4c4.js +5 -0
- package/lib/components/emoji/fluent/svg/1f4d3.d.ts +2 -0
- package/lib/components/emoji/fluent/svg/1f4d3.js +5 -0
- package/lib/components/emoji/fluent/svg/1f4d6.d.ts +2 -0
- package/lib/components/emoji/fluent/svg/1f4d6.js +5 -0
- package/lib/components/emoji/fluent/svg/1f4dc.d.ts +2 -0
- package/lib/components/emoji/fluent/svg/1f4dc.js +5 -0
- package/lib/components/emoji/fluent/svg/1f4e1.d.ts +2 -0
- package/lib/components/emoji/fluent/svg/1f4e1.js +5 -0
- package/lib/components/emoji/fluent/svg/1f4e2.d.ts +2 -0
- package/lib/components/emoji/fluent/svg/1f4e2.js +5 -0
- package/lib/components/emoji/fluent/svg/1f4e7.d.ts +2 -0
- package/lib/components/emoji/fluent/svg/1f4e7.js +5 -0
- package/lib/components/emoji/fluent/svg/1f500.d.ts +2 -0
- package/lib/components/emoji/fluent/svg/1f500.js +5 -0
- package/lib/components/emoji/fluent/svg/1f501.d.ts +2 -0
- package/lib/components/emoji/fluent/svg/1f501.js +5 -0
- package/lib/components/emoji/fluent/svg/1f504.d.ts +2 -0
- package/lib/components/emoji/fluent/svg/1f504.js +5 -0
- package/lib/components/emoji/fluent/svg/1f52d.d.ts +2 -0
- package/lib/components/emoji/fluent/svg/1f52d.js +5 -0
- package/lib/components/emoji/fluent/svg/1f552.d.ts +2 -0
- package/lib/components/emoji/fluent/svg/1f552.js +5 -0
- package/lib/components/emoji/fluent/svg/1f58b.d.ts +2 -0
- package/lib/components/emoji/fluent/svg/1f58b.js +5 -0
- package/lib/components/emoji/fluent/svg/1f5b2.d.ts +2 -0
- package/lib/components/emoji/fluent/svg/1f5b2.js +5 -0
- package/lib/components/emoji/fluent/svg/1f5c3.d.ts +2 -0
- package/lib/components/emoji/fluent/svg/1f5c3.js +5 -0
- package/lib/components/emoji/fluent/svg/1f5d1.d.ts +2 -0
- package/lib/components/emoji/fluent/svg/1f5d1.js +5 -0
- package/lib/components/emoji/fluent/svg/1f5dc.d.ts +2 -0
- package/lib/components/emoji/fluent/svg/1f5dc.js +5 -0
- package/lib/components/emoji/fluent/svg/1f604.d.ts +2 -0
- package/lib/components/emoji/fluent/svg/1f604.js +5 -0
- package/lib/components/emoji/fluent/svg/1f917.d.ts +2 -0
- package/lib/components/emoji/fluent/svg/1f917.js +5 -0
- package/lib/components/emoji/fluent/svg/1f9d1-200d-2696.d.ts +2 -0
- package/lib/components/emoji/fluent/svg/1f9d1-200d-2696.js +5 -0
- package/lib/components/emoji/fluent/svg/1fa79.d.ts +2 -0
- package/lib/components/emoji/fluent/svg/1fa79.js +5 -0
- package/lib/components/emoji/fluent/svg/1fa9d.d.ts +2 -0
- package/lib/components/emoji/fluent/svg/1fa9d.js +5 -0
- package/lib/components/emoji/fluent/svg/1fa9f.d.ts +2 -0
- package/lib/components/emoji/fluent/svg/1fa9f.js +5 -0
- package/lib/components/emoji/fluent/svg/23f3.d.ts +2 -0
- package/lib/components/emoji/fluent/svg/23f3.js +5 -0
- package/lib/components/emoji/fluent/svg/2611.d.ts +2 -0
- package/lib/components/emoji/fluent/svg/2611.js +5 -0
- package/lib/components/emoji/fluent/svg/2702.d.ts +2 -0
- package/lib/components/emoji/fluent/svg/2702.js +5 -0
- package/lib/components/emoji/fluent/svg/270f.d.ts +2 -0
- package/lib/components/emoji/fluent/svg/270f.js +5 -0
- package/lib/components/emoji/fluent/svg/2728.d.ts +2 -0
- package/lib/components/emoji/fluent/svg/2728.js +5 -0
- package/lib/components/emoji/fluent/svg/2b1c.d.ts +2 -0
- package/lib/components/emoji/fluent/svg/2b1c.js +5 -0
- package/lib/components/flashes/FlashClosable.js +2 -17
- package/lib/components/mcp/ClientBadge.js +1 -1
- package/lib/components/mcp/McpErrorBlankslate.js +1 -1
- package/lib/components/mcp/ScopeList.js +1 -1
- package/lib/components/notebooks/JupyterNotebook.js +1 -2
- package/lib/components/principal/Principal.js +2 -10
- package/lib/components/principal/PrincipalAppearance.d.ts +24 -1
- package/lib/components/principal/PrincipalAppearance.js +107 -80
- package/lib/components/principal/PrincipalAvatar.d.ts +5 -7
- package/lib/components/principal/PrincipalAvatar.js +12 -38
- package/lib/components/principal/PrincipalBadge.js +3 -13
- package/lib/components/principal/PrincipalBanner.js +4 -32
- package/lib/components/principal/PrincipalDetailsOverlay.d.ts +4 -7
- package/lib/components/principal/PrincipalDetailsOverlay.js +8 -24
- package/lib/components/principal/PrincipalHoverCard.js +15 -18
- package/lib/components/principal/PrincipalSwitcherMenu.js +15 -83
- package/lib/components/progress/ConsumptionBar.js +1 -1
- package/lib/components/sharing/ShareAccessComponent.js +21 -229
- package/lib/components/sharing/SharingEditor.js +1 -1
- package/lib/components/spaces/SpaceDetailsOverlay.js +4 -35
- package/lib/components/spaces/SpaceDisplay.js +1 -8
- package/lib/components/storage/ContentsBrowser.js +3 -26
- package/lib/components/storage/ContentsTable.js +4 -23
- package/lib/components/students/StudentResultCircle.js +7 -29
- package/lib/components/timeline/Timeline.js +4 -36
- package/lib/hooks/layouts/LayoutBackdrop.js +2 -1
- package/lib/hooks/layouts/LayoutScreencapture.js +1 -1
- package/lib/hooks/libraryApp.d.ts +6 -1
- package/lib/hooks/libraryApp.js +10 -1
- package/lib/hooks/unlinkIAMProvider.d.ts +22 -0
- package/lib/hooks/unlinkIAMProvider.js +24 -0
- package/lib/hooks/useAuthorization.js +6 -1
- package/lib/hooks/useCache.d.ts +8 -1
- package/lib/hooks/useCache.js +35 -4
- package/lib/hooks/useNavigate.js +8 -2
- package/lib/mocks/components/FlashMock.js +3 -8
- package/lib/mocks/views/DashboardMock.js +6 -72
- package/lib/mocks/views/FormMock.js +3 -2
- package/lib/mocks/views/TableMock.js +3 -2
- package/lib/mocks/views/WipMock.js +2 -1
- package/lib/models/IAMProviderLinked.d.ts +9 -0
- package/lib/models/IAMProviderLinked.js +34 -5
- package/lib/models/McpTask.d.ts +18 -1
- package/lib/models/McpTask.js +15 -0
- package/lib/models/Person.d.ts +9 -0
- package/lib/models/Person.js +23 -0
- package/lib/models/Profile.d.ts +2 -2
- package/lib/models/User.js +5 -12
- package/lib/models/UserOnboarding.d.ts +9 -0
- package/lib/models/UserOnboarding.js +33 -0
- package/lib/otel/views/OtelLive.js +4 -62
- package/lib/otel/views/OtelLiveSpans.js +4 -29
- package/lib/otel/views/OtelLogsList.js +13 -64
- package/lib/otel/views/OtelMetricsChart.js +4 -19
- package/lib/otel/views/OtelMetricsList.js +8 -77
- package/lib/otel/views/OtelSearchBar.js +3 -12
- package/lib/otel/views/OtelSpanDetail.js +9 -79
- package/lib/otel/views/OtelSpanTree.js +7 -57
- package/lib/otel/views/OtelSqlView.js +5 -99
- package/lib/otel/views/OtelSystemView.js +4 -34
- package/lib/otel/views/OtelTimeline.js +7 -37
- package/lib/otel/views/OtelTimelineRangeSlider.js +7 -140
- package/lib/otel/views/OtelTracesList.js +12 -76
- package/lib/portable/index.d.ts +9 -0
- package/lib/portable/index.js +14 -0
- package/lib/portable/states.d.ts +39 -0
- package/lib/portable/states.js +71 -0
- package/lib/state/substates/NavigationState.d.ts +10 -6
- package/lib/state/substates/NavigationState.js +18 -8
- package/lib/views/api-keys/APIKeyEdit.js +2 -11
- package/lib/views/api-keys/APIKeyNew.js +3 -19
- package/lib/views/api-keys/APIKeys.js +6 -11
- package/lib/views/api-keys/APIKeysStandalone.js +1 -1
- package/lib/views/datasources/DatasourceDetail.d.ts +1 -1
- package/lib/views/datasources/DatasourceDetail.js +24 -17
- package/lib/views/datasources/DatasourceNew.js +2 -6
- package/lib/views/datasources/Datasources.js +2 -14
- package/lib/views/iam/SignInSimple.js +8 -64
- package/lib/views/mcp/AdmittedClients.js +3 -16
- package/lib/views/mcp/AlertDestinations.js +3 -11
- package/lib/views/mcp/AlertRules.js +4 -9
- package/lib/views/mcp/ApprovalQueue.js +5 -22
- package/lib/views/mcp/AuditLog.js +7 -44
- package/lib/views/mcp/ConnectedAgents.js +1 -6
- package/lib/views/mcp/EnterpriseConsole.js +11 -24
- package/lib/views/mcp/IdentityProviders.js +7 -31
- package/lib/views/mcp/McpDashboard.js +15 -31
- package/lib/views/mcp/McpHome.js +8 -55
- package/lib/views/mcp/McpObservability.js +14 -86
- package/lib/views/mcp/NotebookRuns.js +6 -13
- package/lib/views/mcp/OrganizationPolicy.js +3 -9
- package/lib/views/mcp/OrganizationUsage.js +5 -12
- package/lib/views/mcp/PersonalPolicy.js +3 -3
- package/lib/views/mcp/Policies.js +6 -47
- package/lib/views/mcp/PolicyForm.js +1 -9
- package/lib/views/mcp/PolicyHistory.js +2 -8
- package/lib/views/mcp/RunDetail.d.ts +1 -1
- package/lib/views/mcp/RunDetail.js +7 -26
- package/lib/views/mcp/ScimProvisioning.js +4 -16
- package/lib/views/mcp/ServiceAgents.js +4 -17
- package/lib/views/mcp/TeamPolicies.js +7 -19
- package/lib/views/mcp/ToolAccess.js +16 -23
- package/lib/views/mcp/TraceTimeline.js +8 -23
- package/lib/views/otel/DashboardView.js +2 -2
- package/lib/views/otel/LogsView.js +2 -2
- package/lib/views/otel/MetricsView.js +2 -2
- package/lib/views/otel/OtelHeader.js +6 -40
- package/lib/views/otel/SqlView.js +2 -2
- package/lib/views/otel/SystemView.js +2 -2
- package/lib/views/otel/TracesView.js +2 -2
- package/lib/views/profile/UserBadge.js +6 -98
- package/lib/views/secrets/SecretEdit.js +2 -11
- package/lib/views/secrets/SecretNew.js +1 -1
- package/package.json +1 -1
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
2
|
-
import {
|
|
2
|
+
import { Box } from '@datalayer/primer-addons';
|
|
3
|
+
import { ActionMenu, Button, Label, Text, ThemeProvider } from '@primer/react';
|
|
3
4
|
import { SpaceIcon } from '@primer/octicons-react';
|
|
4
5
|
import { useNavigate } from '../../hooks/index.js';
|
|
5
6
|
import { buildSpaceDetailsPath } from './spaceDisplayModel.js';
|
|
@@ -31,22 +32,7 @@ export function SpaceDetailsCard({ uid, displayName, handle, accountHandle, desc
|
|
|
31
32
|
const address = normalizedAccount && normalizedHandle
|
|
32
33
|
? `@${normalizedAccount}/${normalizedHandle}`
|
|
33
34
|
: normalizedHandle;
|
|
34
|
-
return (_jsxs(Box, {
|
|
35
|
-
display: 'inline-flex',
|
|
36
|
-
alignItems: 'center',
|
|
37
|
-
justifyContent: 'center',
|
|
38
|
-
width: 40,
|
|
39
|
-
height: 40,
|
|
40
|
-
flexShrink: 0,
|
|
41
|
-
borderRadius: 2,
|
|
42
|
-
bg: 'accent.subtle',
|
|
43
|
-
color: 'accent.fg',
|
|
44
|
-
}, children: _jsx(SpaceIcon, { size: 20 }) }), _jsxs(Box, { sx: { display: 'grid', gap: 0.5, minWidth: 0 }, children: [_jsx(Text, { sx: { fontWeight: 'semibold' }, children: normalizedDisplayName }), address ? (_jsx(Text, { sx: { fontSize: 0, color: 'fg.muted' }, children: address })) : null] })] }), _jsxs(Box, { sx: {
|
|
45
|
-
display: 'grid',
|
|
46
|
-
gridTemplateColumns: '110px 1fr',
|
|
47
|
-
gap: 1,
|
|
48
|
-
alignItems: 'baseline',
|
|
49
|
-
}, children: [_jsx(Text, { sx: { fontSize: 0, color: 'fg.muted' }, children: "Kind" }), _jsx(Text, { sx: { fontSize: 1 }, children: "space" }), normalizedHandle ? (_jsxs(_Fragment, { children: [_jsx(Text, { sx: { fontSize: 0, color: 'fg.muted' }, children: "Handle" }), _jsx(Text, { sx: { fontSize: 1 }, children: normalizedHandle })] })) : null, normalizedAccount ? (_jsxs(_Fragment, { children: [_jsx(Text, { sx: { fontSize: 0, color: 'fg.muted' }, children: "Account" }), _jsxs(Text, { sx: { fontSize: 1 }, children: ["@", normalizedAccount] })] })) : null, normalize(variant) ? (_jsxs(_Fragment, { children: [_jsx(Text, { sx: { fontSize: 0, color: 'fg.muted' }, children: "Variant" }), _jsx(Text, { sx: { fontSize: 1 }, children: normalize(variant) })] })) : null, typeof isPublic === 'boolean' ? (_jsxs(_Fragment, { children: [_jsx(Text, { sx: { fontSize: 0, color: 'fg.muted' }, children: "Visibility" }), _jsx(Label, { size: "small", variant: isPublic ? 'success' : 'secondary', sx: { justifySelf: 'start', width: 'fit-content' }, children: isPublic ? 'Public' : 'Private' })] })) : null, _jsx(Text, { sx: { fontSize: 0, color: 'fg.muted' }, children: "Description" }), _jsx(Text, { sx: { fontSize: 1 }, children: normalize(description) || 'N/A' }), normalizedUid ? (_jsxs(_Fragment, { children: [_jsx(Text, { sx: { fontSize: 0, color: 'fg.muted' }, children: "UID" }), _jsx(Text, { sx: { fontSize: 1 }, children: normalizedUid })] })) : null] }), _jsx(Box, { sx: { display: 'flex', justifyContent: 'flex-end', gap: 2 }, children: _jsx(Button, { size: "small", onClick: go, disabled: !targetPath, children: "View Space" }) })] }));
|
|
35
|
+
return (_jsxs(Box, { display: "grid", gap: 3, p: 4, minWidth: 360, children: [_jsxs(Box, { display: "flex", alignItems: "center", gap: 2, children: [_jsx(Box, { "aria-hidden": "true", display: "inline-flex", alignItems: "center", justifyContent: "center", width: 40, height: 40, flexShrink: 0, borderRadius: 2, bg: "accent.subtle", color: "accent.fg", children: _jsx(SpaceIcon, { size: 20 }) }), _jsxs(Box, { display: "grid", gap: 0.5, minWidth: 0, children: [_jsx(Text, { sx: { fontWeight: 'semibold' }, children: normalizedDisplayName }), address ? (_jsx(Text, { sx: { fontSize: 0, color: 'fg.muted' }, children: address })) : null] })] }), _jsxs(Box, { display: "grid", gridTemplateColumns: "110px 1fr", gap: 1, alignItems: "baseline", children: [_jsx(Text, { sx: { fontSize: 0, color: 'fg.muted' }, children: "Kind" }), _jsx(Text, { sx: { fontSize: 1 }, children: "space" }), normalizedHandle ? (_jsxs(_Fragment, { children: [_jsx(Text, { sx: { fontSize: 0, color: 'fg.muted' }, children: "Handle" }), _jsx(Text, { sx: { fontSize: 1 }, children: normalizedHandle })] })) : null, normalizedAccount ? (_jsxs(_Fragment, { children: [_jsx(Text, { sx: { fontSize: 0, color: 'fg.muted' }, children: "Account" }), _jsxs(Text, { sx: { fontSize: 1 }, children: ["@", normalizedAccount] })] })) : null, normalize(variant) ? (_jsxs(_Fragment, { children: [_jsx(Text, { sx: { fontSize: 0, color: 'fg.muted' }, children: "Variant" }), _jsx(Text, { sx: { fontSize: 1 }, children: normalize(variant) })] })) : null, typeof isPublic === 'boolean' ? (_jsxs(_Fragment, { children: [_jsx(Text, { sx: { fontSize: 0, color: 'fg.muted' }, children: "Visibility" }), _jsx(Label, { size: "small", variant: isPublic ? 'success' : 'secondary', sx: { justifySelf: 'start', width: 'fit-content' }, children: isPublic ? 'Public' : 'Private' })] })) : null, _jsx(Text, { sx: { fontSize: 0, color: 'fg.muted' }, children: "Description" }), _jsx(Text, { sx: { fontSize: 1 }, children: normalize(description) || 'N/A' }), normalizedUid ? (_jsxs(_Fragment, { children: [_jsx(Text, { sx: { fontSize: 0, color: 'fg.muted' }, children: "UID" }), _jsx(Text, { sx: { fontSize: 1 }, children: normalizedUid })] })) : null] }), _jsx(Box, { display: "flex", justifyContent: "flex-end", gap: 2, children: _jsx(Button, { size: "small", onClick: go, disabled: !targetPath, children: "View Space" }) })] }));
|
|
50
36
|
}
|
|
51
37
|
/**
|
|
52
38
|
* A space's details, shown from a click on its name.
|
|
@@ -58,23 +44,6 @@ export function SpaceDetailsOverlay(props) {
|
|
|
58
44
|
normalize(props.handle) ||
|
|
59
45
|
normalize(props.uid) ||
|
|
60
46
|
'Space';
|
|
61
|
-
return (_jsx(ThemeProvider, { children: _jsxs(ActionMenu, { children: [_jsx(ActionMenu.Anchor, { children: _jsx(Box, { as: "button", type: "button", title: normalizedDisplayName,
|
|
62
|
-
fontWeight: 'semibold',
|
|
63
|
-
color: 'accent.fg',
|
|
64
|
-
textDecoration: 'underline',
|
|
65
|
-
background: 'transparent',
|
|
66
|
-
border: 0,
|
|
67
|
-
padding: 0,
|
|
68
|
-
margin: 0,
|
|
69
|
-
cursor: 'pointer',
|
|
70
|
-
maxWidth: '100%',
|
|
71
|
-
overflow: 'hidden',
|
|
72
|
-
textOverflow: 'ellipsis',
|
|
73
|
-
whiteSpace: 'nowrap',
|
|
74
|
-
textAlign: 'left',
|
|
75
|
-
':hover': {
|
|
76
|
-
textDecoration: 'underline',
|
|
77
|
-
},
|
|
78
|
-
}, children: normalizedDisplayName }) }), _jsx(ActionMenu.Overlay, { width: "large", children: _jsx(SpaceDetailsCard, { ...props }) })] }) }));
|
|
47
|
+
return (_jsx(ThemeProvider, { children: _jsxs(ActionMenu, { children: [_jsx(ActionMenu.Anchor, { children: _jsx(Box, { as: "button", type: "button", title: normalizedDisplayName, fontWeight: "semibold", color: "accent.fg", textDecoration: "underline", background: "transparent", border: 0, padding: 0, margin: 0, cursor: "pointer", maxWidth: "100%", overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap", textAlign: "left", hover: { textDecoration: 'underline' }, children: normalizedDisplayName }) }), _jsx(ActionMenu.Overlay, { width: "large", children: _jsx(SpaceDetailsCard, { ...props }) })] }) }));
|
|
79
48
|
}
|
|
80
49
|
export default SpaceDetailsOverlay;
|
|
@@ -80,13 +80,6 @@ export const SpaceDisplay = ({ space, showIcon = true, iconSize = 16, gap = 1, p
|
|
|
80
80
|
Boolean(givenRootId || String(itemUid || '').trim());
|
|
81
81
|
return (_jsx(Text, { sx: { color: 'fg.muted', ...sx }, children: waiting ? '…' : emptyText }));
|
|
82
82
|
}
|
|
83
|
-
return (_jsxs(Box, { sx: {
|
|
84
|
-
display: 'inline-flex',
|
|
85
|
-
alignItems: 'center',
|
|
86
|
-
gap,
|
|
87
|
-
minWidth: 0,
|
|
88
|
-
maxWidth: '100%',
|
|
89
|
-
...sx,
|
|
90
|
-
}, children: [showIcon ? (_jsx(Box, { as: "span", "aria-hidden": "true", sx: { display: 'inline-flex', color: 'fg.muted', flexShrink: 0 }, children: _jsx(SpaceIcon, { size: iconSize }) })) : null, _jsx(SpaceDetailsOverlay, { uid: resolved.uid, displayName: resolved.displayName, handle: resolved.handle, accountHandle: resolved.accountHandle, description: resolved.description, variant: resolved.variant, isPublic: resolved.isPublic, onNavigate: onNavigate })] }));
|
|
83
|
+
return (_jsxs(Box, { display: "inline-flex", alignItems: "center", gap: gap, minWidth: 0, maxWidth: "100%", sx: sx, children: [showIcon ? (_jsx(Box, { as: "span", "aria-hidden": "true", display: "inline-flex", color: "fg.muted", flexShrink: 0, children: _jsx(SpaceIcon, { size: iconSize }) })) : null, _jsx(SpaceDetailsOverlay, { uid: resolved.uid, displayName: resolved.displayName, handle: resolved.handle, accountHandle: resolved.accountHandle, description: resolved.description, variant: resolved.variant, isPublic: resolved.isPublic, onNavigate: onNavigate })] }));
|
|
91
84
|
};
|
|
92
85
|
export default SpaceDisplay;
|
|
@@ -41,7 +41,7 @@ export function ContentsBrowser(props) {
|
|
|
41
41
|
// caller that has not resolved its sandbox yet must not appear to have.
|
|
42
42
|
const contents = props.contents ?? (mock ? CONTENTS_BROWSER_MOCK_MANAGER : undefined);
|
|
43
43
|
if (!contents) {
|
|
44
|
-
return (_jsxs(Box, {
|
|
44
|
+
return (_jsxs(Box, { p: 3, children: [title, _jsx(Text, { sx: { display: 'block', color: 'fg.muted', fontSize: 1, mt: 2 }, children: "No filesystem is connected." })] }));
|
|
45
45
|
}
|
|
46
46
|
return (_jsx(ConnectedContentsBrowser, { ...props, contents: contents, mock: mock, title: title }));
|
|
47
47
|
}
|
|
@@ -292,32 +292,9 @@ const ConnectedContentsBrowser = (props) => {
|
|
|
292
292
|
const onSelect = useCallback((item, refresh) => {
|
|
293
293
|
setSelectedItem(item.path === selectedItem?.path ? null : { ...item, refresh });
|
|
294
294
|
}, [selectedItem]);
|
|
295
|
-
return (_jsxs(Box, {
|
|
296
|
-
display: 'grid',
|
|
297
|
-
gridTemplateAreas: `"header" "content"`,
|
|
298
|
-
overflow: 'hidden',
|
|
299
|
-
}, children: [_jsxs(Box, { sx: {
|
|
300
|
-
gridArea: 'header',
|
|
301
|
-
display: 'flex',
|
|
302
|
-
alignItems: 'center',
|
|
303
|
-
minWidth: 0,
|
|
304
|
-
overflow: 'hidden',
|
|
305
|
-
}, children: [_jsx(Box, { sx: { flex: '1 1 auto', minWidth: 0, overflow: 'hidden' }, children: title }), _jsxs(Box, { sx: {
|
|
306
|
-
display: 'flex',
|
|
307
|
-
flexDirection: 'row',
|
|
308
|
-
alignItems: 'center',
|
|
309
|
-
flexWrap: 'nowrap',
|
|
310
|
-
flexShrink: 0,
|
|
311
|
-
}, children: [_jsx(SegmentedControl, { "aria-label": "Contents view", size: "small", onChange: index => {
|
|
295
|
+
return (_jsxs(Box, { display: "grid", gridTemplateAreas: '"header" "content"', overflow: "hidden", children: [_jsxs(Box, { gridArea: "header", display: "flex", alignItems: "center", minWidth: 0, overflow: "hidden", children: [_jsx(Box, { flex: "1 1 auto", minWidth: 0, overflow: "hidden", children: title }), _jsxs(Box, { display: "flex", flexDirection: "row", alignItems: "center", flexWrap: "nowrap", flexShrink: 0, children: [_jsx(SegmentedControl, { "aria-label": "Contents view", size: "small", onChange: index => {
|
|
312
296
|
changeView(CONTENTS_BROWSER_VIEWS[index].value);
|
|
313
|
-
}, children: CONTENTS_BROWSER_VIEWS.map(candidate => (_jsx(SegmentedControl.IconButton, { icon: candidate.icon, "aria-label": candidate.label, selected: candidate.value === view }, candidate.value))) }), _jsx(IconButton, { variant: "invisible", "aria-label": 'Refresh contents browser.', title: 'Refresh contents browser.', icon: SyncIcon, onClick: refreshView, disabled: mock }), !mock && (_jsx(UploadIconButton, { label: 'Upload a file', multiple: true, upload: upload }))] })] }), isLoading ? (_jsx(Box, {
|
|
314
|
-
gridArea: 'content',
|
|
315
|
-
display: 'flex',
|
|
316
|
-
alignItems: 'center',
|
|
317
|
-
justifyContent: 'center',
|
|
318
|
-
minHeight: '40px',
|
|
319
|
-
height: '100vh',
|
|
320
|
-
}, children: _jsx(Spinner, {}) })) : (_jsxs(Box, { sx: { gridArea: 'content' }, children: [view === 'table' ? (folderItems === null && !isFolderLoading ? (_jsx(Blankslate, { children: _jsx(Blankslate.Heading, { children: "No contents" }) })) : (_jsx(ContentsTable, { path: folderPath, items: folderItems ?? [], current: selectedItem, loading: isFolderLoading, onNavigate: navigateTo, onSelect: item => {
|
|
297
|
+
}, children: CONTENTS_BROWSER_VIEWS.map(candidate => (_jsx(SegmentedControl.IconButton, { icon: candidate.icon, "aria-label": candidate.label, selected: candidate.value === view }, candidate.value))) }), _jsx(IconButton, { variant: "invisible", "aria-label": 'Refresh contents browser.', title: 'Refresh contents browser.', icon: SyncIcon, onClick: refreshView, disabled: mock }), !mock && (_jsx(UploadIconButton, { label: 'Upload a file', multiple: true, upload: upload }))] })] }), isLoading ? (_jsx(Box, { gridArea: "content", display: "flex", alignItems: "center", justifyContent: "center", minHeight: "40px", height: "100vh", children: _jsx(Spinner, {}) })) : (_jsxs(Box, { gridArea: "content", children: [view === 'table' ? (folderItems === null && !isFolderLoading ? (_jsx(Blankslate, { children: _jsx(Blankslate.Heading, { children: "No contents" }) })) : (_jsx(ContentsTable, { path: folderPath, items: folderItems ?? [], current: selectedItem, loading: isFolderLoading, onNavigate: navigateTo, onSelect: item => {
|
|
321
298
|
onSelect(item, refreshFolder);
|
|
322
299
|
}, onContextMenu: onContextMenu }))) : children ? (_jsx(TreeView, { children: children?.map(child => {
|
|
323
300
|
return child.type === 'directory' ? (_jsx(DirectoryItem, { item: child, contents: contents, current: selectedItem, documentRegistry: documentRegistry, onContextMenu: onContextMenu, onSelect: onSelect }, child.name)) : (_jsx(TreeItem, { item: child, current: selectedItem?.path === child.path, onSelect: item => {
|
|
@@ -63,7 +63,7 @@ function ParentRow(props) {
|
|
|
63
63
|
event.preventDefault();
|
|
64
64
|
goUp();
|
|
65
65
|
}
|
|
66
|
-
}, children: [_jsx(Table.Cell, { scope: "row", children: _jsxs(Box, {
|
|
66
|
+
}, children: [_jsx(Table.Cell, { scope: "row", children: _jsxs(Box, { display: "flex", alignItems: "center", gap: 2, children: [_jsx(FileDirectoryIcon, {}), _jsx("span", { children: ".." })] }) }), _jsx(Table.Cell, {}), _jsx(Table.Cell, {})] }));
|
|
67
67
|
}
|
|
68
68
|
/**
|
|
69
69
|
* A folder or file row.
|
|
@@ -92,7 +92,7 @@ function ContentsRow(props) {
|
|
|
92
92
|
onSelect(item);
|
|
93
93
|
}
|
|
94
94
|
onContextMenu(ref);
|
|
95
|
-
}, children: [_jsx(Table.Cell, { scope: "row", children: _jsxs(Box, { ref: ref,
|
|
95
|
+
}, children: [_jsx(Table.Cell, { scope: "row", children: _jsxs(Box, { ref: ref, display: "flex", alignItems: "center", gap: 2, minWidth: 0, children: [isDirectory ? (_jsx(FileDirectoryFillIcon, {})) : icon ? (_jsx(icon.react, { tag: 'span' })) : (_jsx(FileIcon, {})), _jsx("span", { style: {
|
|
96
96
|
overflow: 'hidden',
|
|
97
97
|
textOverflow: 'ellipsis',
|
|
98
98
|
whiteSpace: 'nowrap',
|
|
@@ -108,27 +108,8 @@ export function ContentsTable(props) {
|
|
|
108
108
|
const { path, items, current, loading = false, onNavigate, onSelect, onContextMenu, } = props;
|
|
109
109
|
const segments = pathSegments(path);
|
|
110
110
|
const label = path ? `Contents of ${path}` : 'Contents of the root folder';
|
|
111
|
-
return (_jsxs(Box, {
|
|
112
|
-
display: 'flex',
|
|
113
|
-
alignItems: 'center',
|
|
114
|
-
gap: 2,
|
|
115
|
-
minWidth: 0,
|
|
116
|
-
overflow: 'hidden',
|
|
117
|
-
}, children: _jsxs(Box, { role: "navigation", "aria-label": "Folder path", sx: {
|
|
118
|
-
display: 'flex',
|
|
119
|
-
alignItems: 'center',
|
|
120
|
-
flexWrap: 'wrap',
|
|
121
|
-
gap: 1,
|
|
122
|
-
minWidth: 0,
|
|
123
|
-
fontSize: 1,
|
|
124
|
-
}, children: [_jsx(PathSegment, { name: "/", path: "", current: segments.length === 0, title: "Go to the root folder.", onNavigate: onNavigate }), segments.map((segment, index) => (_jsxs(Fragment, { children: [index > 0 && _jsx(Text, { sx: { color: 'fg.muted' }, children: "/" }), _jsx(PathSegment, { name: segment.name, path: segment.path, current: index === segments.length - 1, title: index === segments.length - 1
|
|
111
|
+
return (_jsxs(Box, { display: "flex", flexDirection: "column", gap: 2, children: [_jsx(Box, { display: "flex", alignItems: "center", gap: 2, minWidth: 0, overflow: "hidden", children: _jsxs(Box, { role: "navigation", "aria-label": "Folder path", display: "flex", alignItems: "center", flexWrap: "wrap", gap: 1, minWidth: 0, fontSize: 1, children: [_jsx(PathSegment, { name: "/", path: "", current: segments.length === 0, title: "Go to the root folder.", onNavigate: onNavigate }), segments.map((segment, index) => (_jsxs(Fragment, { children: [index > 0 && _jsx(Text, { sx: { color: 'fg.muted' }, children: "/" }), _jsx(PathSegment, { name: segment.name, path: segment.path, current: index === segments.length - 1, title: index === segments.length - 1
|
|
125
112
|
? `Reload ${segment.path}`
|
|
126
|
-
: `Go to ${segment.path}`, onNavigate: onNavigate })] }, segment.path)))] }) }), loading ? (_jsx(Box, {
|
|
127
|
-
display: 'flex',
|
|
128
|
-
alignItems: 'center',
|
|
129
|
-
justifyContent: 'center',
|
|
130
|
-
minHeight: '40px',
|
|
131
|
-
padding: 3,
|
|
132
|
-
}, children: _jsx(Spinner, { "aria-label": "Loading folder\u2026" }) })) : (_jsx(Table.Container, { children: _jsxs(Table, { "aria-label": label, cellPadding: "condensed", gridTemplateColumns: "minmax(0, 1fr) max-content max-content", children: [_jsx(Table.Head, { children: _jsxs(Table.Row, { children: [_jsx(Table.Header, { children: "Name" }), _jsx(Table.Header, { children: "Last modified" }), _jsx(Table.Header, { align: "end", children: "Size" })] }) }), _jsxs(Table.Body, { children: [path && (_jsx(ParentRow, { path: PathExt.dirname(path), onNavigate: onNavigate })), items.map(item => (_jsx(ContentsRow, { item: item, current: item.path === current?.path, onNavigate: onNavigate, onSelect: onSelect, onContextMenu: onContextMenu }, item.path)))] })] }) }))] }));
|
|
113
|
+
: `Go to ${segment.path}`, onNavigate: onNavigate })] }, segment.path)))] }) }), loading ? (_jsx(Box, { display: "flex", alignItems: "center", justifyContent: "center", minHeight: "40px", padding: 3, children: _jsx(Spinner, { "aria-label": "Loading folder\u2026" }) })) : (_jsx(Table.Container, { children: _jsxs(Table, { "aria-label": label, cellPadding: "condensed", gridTemplateColumns: "minmax(0, 1fr) max-content max-content", children: [_jsx(Table.Head, { children: _jsxs(Table.Row, { children: [_jsx(Table.Header, { children: "Name" }), _jsx(Table.Header, { children: "Last modified" }), _jsx(Table.Header, { align: "end", children: "Size" })] }) }), _jsxs(Table.Body, { children: [path && (_jsx(ParentRow, { path: PathExt.dirname(path), onNavigate: onNavigate })), items.map(item => (_jsx(ContentsRow, { item: item, current: item.path === current?.path, onNavigate: onNavigate, onSelect: onSelect, onContextMenu: onContextMenu }, item.path)))] })] }) }))] }));
|
|
133
114
|
}
|
|
134
115
|
export default ContentsTable;
|
|
@@ -26,34 +26,12 @@ export const StudentResultCircle = (props) => {
|
|
|
26
26
|
}, onMouseDown: event => {
|
|
27
27
|
event.preventDefault();
|
|
28
28
|
event.stopPropagation();
|
|
29
|
-
},
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
lineHeight: 0,
|
|
37
|
-
border: 'none',
|
|
38
|
-
outline: 'none',
|
|
39
|
-
}, children: _jsx(Box, { as: "span", role: "img", "aria-hidden": true, sx: {
|
|
40
|
-
display: 'inline-block',
|
|
41
|
-
flex: 'none',
|
|
42
|
-
width: '14px',
|
|
43
|
-
height: '14px',
|
|
44
|
-
borderRadius: 3,
|
|
45
|
-
ml: 1,
|
|
46
|
-
pointerEvents: 'auto',
|
|
47
|
-
boxSizing: 'border-box',
|
|
48
|
-
backgroundColor: isNone
|
|
49
|
-
? 'transparent'
|
|
50
|
-
: status === 'pass'
|
|
51
|
-
? okColor
|
|
52
|
-
: status === 'partial'
|
|
53
|
-
? partialColor
|
|
54
|
-
: nokColor,
|
|
55
|
-
border: isNone ? '1px solid' : 'none',
|
|
56
|
-
borderColor: isNone ? 'border.default' : 'transparent',
|
|
57
|
-
} }) }) }));
|
|
29
|
+
}, display: "inline-block", flex: "none", appearance: "none", p: 0, bg: "transparent", cursor: "default", lineHeight: 0, border: "none", outline: "none", children: _jsx(Box, { as: "span", role: "img", "aria-hidden": true, display: "inline-block", flex: "none", width: "14px", height: "14px", borderRadius: 3, ml: 1, pointerEvents: "auto", boxSizing: "border-box", backgroundColor: isNone
|
|
30
|
+
? 'transparent'
|
|
31
|
+
: status === 'pass'
|
|
32
|
+
? okColor
|
|
33
|
+
: status === 'partial'
|
|
34
|
+
? partialColor
|
|
35
|
+
: nokColor, border: isNone ? '1px solid' : 'none', borderColor: isNone ? 'border.default' : 'transparent' }) }) }));
|
|
58
36
|
};
|
|
59
37
|
export default StudentResultCircle;
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
-
import { Box
|
|
2
|
+
import { Box } from '@datalayer/primer-addons';
|
|
3
|
+
import { Text } from '@primer/react';
|
|
3
4
|
const statusStyles = {
|
|
4
5
|
done: {
|
|
5
6
|
dotBackground: 'success.emphasis',
|
|
@@ -42,44 +43,11 @@ export const Timeline = ({ items, renderTimestamp }) => {
|
|
|
42
43
|
if (!items.length) {
|
|
43
44
|
return null;
|
|
44
45
|
}
|
|
45
|
-
return (_jsx(Box, {
|
|
46
|
-
overflowX: 'auto',
|
|
47
|
-
pb: 1,
|
|
48
|
-
}, children: _jsx(Box, { sx: {
|
|
49
|
-
display: 'flex',
|
|
50
|
-
alignItems: 'stretch',
|
|
51
|
-
minWidth: 'max-content',
|
|
52
|
-
}, children: items.map((item, index) => {
|
|
46
|
+
return (_jsx(Box, { overflowX: "auto", pb: 1, children: _jsx(Box, { display: "flex", alignItems: "stretch", minWidth: "max-content", children: items.map((item, index) => {
|
|
53
47
|
const status = item.status || 'neutral';
|
|
54
48
|
const style = statusStyles[status];
|
|
55
49
|
const hasNext = index < items.length - 1;
|
|
56
|
-
return (_jsxs(Box, { sx: {
|
|
57
|
-
display: 'flex',
|
|
58
|
-
flexDirection: 'column',
|
|
59
|
-
minWidth: 220,
|
|
60
|
-
flex: hasNext ? '0 0 220px' : '0 0 auto',
|
|
61
|
-
pr: hasNext ? 0 : 1,
|
|
62
|
-
}, children: [_jsxs(Box, { sx: {
|
|
63
|
-
display: 'flex',
|
|
64
|
-
alignItems: 'center',
|
|
65
|
-
minHeight: 28,
|
|
66
|
-
mb: 2,
|
|
67
|
-
}, children: [_jsx(Box, { sx: {
|
|
68
|
-
width: 16,
|
|
69
|
-
height: 16,
|
|
70
|
-
borderRadius: '50%',
|
|
71
|
-
border: '2px solid',
|
|
72
|
-
borderColor: style.dotBorder,
|
|
73
|
-
bg: style.dotBackground,
|
|
74
|
-
boxShadow: 'inset 0 0 0 1px rgba(255,255,255,0.2)',
|
|
75
|
-
} }), hasNext ? (_jsx(Box, { sx: {
|
|
76
|
-
flex: 1,
|
|
77
|
-
height: 4,
|
|
78
|
-
ml: 2,
|
|
79
|
-
mr: 2,
|
|
80
|
-
borderRadius: 999,
|
|
81
|
-
bg: style.lineColor,
|
|
82
|
-
} })) : null] }), _jsx(Text, { as: "p", sx: { fontWeight: 600, color: style.titleColor, mb: 1 }, children: item.title }), _jsx(Text, { as: "p", sx: {
|
|
50
|
+
return (_jsxs(Box, { display: "flex", flexDirection: "column", minWidth: 220, flex: hasNext ? '0 0 220px' : '0 0 auto', pr: hasNext ? 0 : 1, children: [_jsxs(Box, { display: "flex", alignItems: "center", minHeight: 28, mb: 2, children: [_jsx(Box, { width: 16, height: 16, borderRadius: "50%", border: "2px solid", borderColor: style.dotBorder, bg: style.dotBackground, boxShadow: "inset 0 0 0 1px rgba(255,255,255,0.2)" }), hasNext ? (_jsx(Box, { flex: 1, height: 4, ml: 2, mr: 2, borderRadius: 999, bg: style.lineColor })) : null] }), _jsx(Text, { as: "p", sx: { fontWeight: 600, color: style.titleColor, mb: 1 }, children: item.title }), _jsx(Text, { as: "p", sx: {
|
|
83
51
|
fontSize: 0,
|
|
84
52
|
color: 'fg.muted',
|
|
85
53
|
mb: item.subtitle ? 1 : 0,
|
|
@@ -4,7 +4,8 @@ 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 { useEffect } from 'react';
|
|
7
|
-
import {
|
|
7
|
+
import { Box } from '@datalayer/primer-addons';
|
|
8
|
+
import { Heading, Spinner } from '@primer/react';
|
|
8
9
|
import { useBackdrop } from '../index.js';
|
|
9
10
|
import { useLayoutStore } from '../../state/index.js';
|
|
10
11
|
const BackdropContent = (props) => {
|
|
@@ -4,7 +4,7 @@ import { Fragment as _Fragment, jsx as _jsx } from "react/jsx-runtime";
|
|
|
4
4
|
* Distributed under the terms of the Modified BSD License.
|
|
5
5
|
*/
|
|
6
6
|
import { useEffect } from 'react';
|
|
7
|
-
import { Box } from '@primer
|
|
7
|
+
import { Box } from '@datalayer/primer-addons';
|
|
8
8
|
import { useScreencapture, useToast } from '../index.js';
|
|
9
9
|
import { lazyWithPreload, WithSuspense } from '../../utils/index.js';
|
|
10
10
|
import { useLayoutStore } from '../../state/index.js';
|
|
@@ -6,7 +6,10 @@
|
|
|
6
6
|
* projection carries them: `face_s` (the JSON of its `id`, `emoji`, `avatar`
|
|
7
7
|
* and `banner`, each only when set), `app_kind_s` and `runs_live_b` — an app
|
|
8
8
|
* that runs live can be tried before it is cloned: not a decision, and naming
|
|
9
|
-
* the agent it runs on.
|
|
9
|
+
* the agent it runs on. One of Datalayer's examples, published from the
|
|
10
|
+
* catalogue, also says which (`catalogue_example_s`), beside `publisher_s:
|
|
11
|
+
* datalayer` — the Library projects both only for an item of the `datalayer`
|
|
12
|
+
* organization's spaces whose metadata says `catalogueExample` (STUDIO E-10).
|
|
10
13
|
*
|
|
11
14
|
* @module hooks/libraryApp
|
|
12
15
|
*/
|
|
@@ -30,6 +33,8 @@ export type LibraryAppFields = {
|
|
|
30
33
|
appKind?: LibraryAppKind;
|
|
31
34
|
/** Whether it can be tried before it is cloned. */
|
|
32
35
|
runsLive: boolean;
|
|
36
|
+
/** The example of the catalogue it is, when it is one of Datalayer's. */
|
|
37
|
+
catalogueExample?: string;
|
|
33
38
|
};
|
|
34
39
|
/** The face `face_s` carries; a value that is not a face's JSON is refused. */
|
|
35
40
|
export declare function libraryAppFaceOf(value: unknown): LibraryAppFace | undefined;
|
package/lib/hooks/libraryApp.js
CHANGED
|
@@ -10,7 +10,10 @@
|
|
|
10
10
|
* projection carries them: `face_s` (the JSON of its `id`, `emoji`, `avatar`
|
|
11
11
|
* and `banner`, each only when set), `app_kind_s` and `runs_live_b` — an app
|
|
12
12
|
* that runs live can be tried before it is cloned: not a decision, and naming
|
|
13
|
-
* the agent it runs on.
|
|
13
|
+
* the agent it runs on. One of Datalayer's examples, published from the
|
|
14
|
+
* catalogue, also says which (`catalogue_example_s`), beside `publisher_s:
|
|
15
|
+
* datalayer` — the Library projects both only for an item of the `datalayer`
|
|
16
|
+
* organization's spaces whose metadata says `catalogueExample` (STUDIO E-10).
|
|
14
17
|
*
|
|
15
18
|
* @module hooks/libraryApp
|
|
16
19
|
*/
|
|
@@ -50,10 +53,16 @@ export function libraryAppFieldsOf(raw) {
|
|
|
50
53
|
!LIBRARY_APP_KINDS.includes(kind)) {
|
|
51
54
|
throw new Error(`An app's kind is not one of ${LIBRARY_APP_KINDS}: ${String(kind)}`);
|
|
52
55
|
}
|
|
56
|
+
const example = raw.catalogue_example_s;
|
|
57
|
+
if (example !== undefined &&
|
|
58
|
+
(typeof example !== 'string' || example.trim() === '')) {
|
|
59
|
+
throw new Error(`An app's example is not an example's id: ${String(example)}`);
|
|
60
|
+
}
|
|
53
61
|
const face = libraryAppFaceOf(raw.face_s);
|
|
54
62
|
return {
|
|
55
63
|
...(face ? { face } : {}),
|
|
56
64
|
...(kind ? { appKind: kind } : {}),
|
|
57
65
|
runsLive: raw.runs_live_b === true,
|
|
66
|
+
...(example ? { catalogueExample: example } : {}),
|
|
58
67
|
};
|
|
59
68
|
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import type { IIAMProviderName } from '../models/IAMProvidersSpecs';
|
|
2
|
+
/** What `requestDatalayer` resolves: on failure, `success: false` and IAM's sentence. */
|
|
3
|
+
type UnlinkResponse = {
|
|
4
|
+
success?: boolean;
|
|
5
|
+
message?: string;
|
|
6
|
+
};
|
|
7
|
+
type Request = (request: {
|
|
8
|
+
url: string;
|
|
9
|
+
method: 'DELETE';
|
|
10
|
+
notifyOnError: false;
|
|
11
|
+
}) => Promise<UnlinkResponse>;
|
|
12
|
+
/**
|
|
13
|
+
* Unlink a provider from the signed-in account
|
|
14
|
+
* (`DELETE /api/iam/v1/me/providers/{provider}`).
|
|
15
|
+
*
|
|
16
|
+
* IAM answers 409 when the provider is the account's only way to sign in and
|
|
17
|
+
* 404 when it is not linked; either way its sentence is thrown as the error's
|
|
18
|
+
* message for the page to show, and nothing is toasted. On success `refresh`
|
|
19
|
+
* reads the user again before this resolves.
|
|
20
|
+
*/
|
|
21
|
+
export declare function unlinkIAMProvider(request: Request, iamUrl: string, provider: IIAMProviderName, refresh: () => Promise<void>): Promise<void>;
|
|
22
|
+
export {};
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright (c) 2023-2025 Datalayer, Inc.
|
|
3
|
+
* Distributed under the terms of the Modified BSD License.
|
|
4
|
+
*/
|
|
5
|
+
/**
|
|
6
|
+
* Unlink a provider from the signed-in account
|
|
7
|
+
* (`DELETE /api/iam/v1/me/providers/{provider}`).
|
|
8
|
+
*
|
|
9
|
+
* IAM answers 409 when the provider is the account's only way to sign in and
|
|
10
|
+
* 404 when it is not linked; either way its sentence is thrown as the error's
|
|
11
|
+
* message for the page to show, and nothing is toasted. On success `refresh`
|
|
12
|
+
* reads the user again before this resolves.
|
|
13
|
+
*/
|
|
14
|
+
export async function unlinkIAMProvider(request, iamUrl, provider, refresh) {
|
|
15
|
+
const response = await request({
|
|
16
|
+
url: `${iamUrl}/api/iam/v1/me/providers/${encodeURIComponent(provider)}`,
|
|
17
|
+
method: 'DELETE',
|
|
18
|
+
notifyOnError: false,
|
|
19
|
+
});
|
|
20
|
+
if (!response?.success) {
|
|
21
|
+
throw new Error(response?.message || `The ${provider} account could not be unlinked.`);
|
|
22
|
+
}
|
|
23
|
+
await refresh();
|
|
24
|
+
}
|
|
@@ -35,8 +35,13 @@ export const useAuthorization = () => {
|
|
|
35
35
|
const checkIsPlatformMember = (user) => {
|
|
36
36
|
return user.roles.includes(PlatformRoles.Member.handle);
|
|
37
37
|
};
|
|
38
|
+
/**
|
|
39
|
+
* Whether the user sees the features that are not released yet: a Platform
|
|
40
|
+
* Features Previewer, or a Platform Admin — an admin previews everything.
|
|
41
|
+
*/
|
|
38
42
|
const checkIsPlatformFeaturesPreviewer = (user) => {
|
|
39
|
-
return user.roles.includes(PlatformRoles.FeaturesPreviewer.handle)
|
|
43
|
+
return (user.roles.includes(PlatformRoles.FeaturesPreviewer.handle) ||
|
|
44
|
+
checkIsPlatformAdmin(user));
|
|
40
45
|
};
|
|
41
46
|
const checkIsPlatformUsageReviewer = (user) => {
|
|
42
47
|
return user.roles.includes(PlatformRoles.UsageReviewer.handle);
|
package/lib/hooks/useCache.d.ts
CHANGED
|
@@ -33,7 +33,7 @@
|
|
|
33
33
|
* ```
|
|
34
34
|
*/
|
|
35
35
|
import { QueryClient, UseQueryOptions, UseMutationOptions } from '@tanstack/react-query';
|
|
36
|
-
import { IAnyOrganization, IContact, IIAMToken, IOrganization, ISchool, ISecret, IStudent, ITeam, IUser, IUserOnboarding, IUserSettings } from '../models';
|
|
36
|
+
import { IAnyOrganization, IContact, IIAMProviderName, IIAMToken, IOrganization, ISchool, ISecret, IStudent, ITeam, IUser, IUserOnboarding, IUserSettings } from '../models';
|
|
37
37
|
type IAnySpace = any;
|
|
38
38
|
export type CacheProps = {
|
|
39
39
|
loginRoute?: string;
|
|
@@ -486,6 +486,7 @@ export declare const useCache: ({ loginRoute }?: CacheProps) => {
|
|
|
486
486
|
useGetGitHubProfile: () => import("@tanstack/react-query").UseMutationResult<any, Error, string, unknown>;
|
|
487
487
|
useGetGoogleProfile: () => import("@tanstack/react-query").UseMutationResult<any, Error, string, unknown>;
|
|
488
488
|
useGetLinkedinProfile: () => import("@tanstack/react-query").UseMutationResult<any, Error, void, unknown>;
|
|
489
|
+
useUnlinkIAMProvider: () => import("@tanstack/react-query").UseMutationResult<void, Error, IIAMProviderName, unknown>;
|
|
489
490
|
usePostLinkedinShare: () => import("@tanstack/react-query").UseMutationResult<any, Error, {
|
|
490
491
|
postText: string;
|
|
491
492
|
}, unknown>;
|
|
@@ -1015,6 +1016,12 @@ export declare const useCache: ({ loginRoute }?: CacheProps) => {
|
|
|
1015
1016
|
useSecrets: (options?: {
|
|
1016
1017
|
principalUid?: string;
|
|
1017
1018
|
principalKind?: "personal" | "organization" | "team";
|
|
1019
|
+
} & {
|
|
1020
|
+
/**
|
|
1021
|
+
* `false` reads nothing: a page a visitor opens signed out, whose 401
|
|
1022
|
+
* would otherwise send them to the sign-in.
|
|
1023
|
+
*/
|
|
1024
|
+
enabled?: boolean;
|
|
1018
1025
|
}) => import("@tanstack/react-query").UseQueryResult<any, Error>;
|
|
1019
1026
|
useCreateSecret: (options?: {
|
|
1020
1027
|
principalUid?: string;
|
package/lib/hooks/useCache.js
CHANGED
|
@@ -40,6 +40,7 @@ import { useQuery, useQueries, useMutation, useQueryClient, } from '@tanstack/re
|
|
|
40
40
|
import { BOOTSTRAP_USER_ONBOARDING, asContact, asInvite, asOrganization, asSecret, asTeam, asToken, asUser, } from '../models/index.js';
|
|
41
41
|
import { asSpace } from './cacheConverters.js';
|
|
42
42
|
import { libraryAppFieldsOf } from './libraryApp.js';
|
|
43
|
+
import { unlinkIAMProvider } from './unlinkIAMProvider.js';
|
|
43
44
|
import { useCoreStore, useIAMStore, profileStore } from '../state/index.js';
|
|
44
45
|
import { asDisplayName, namesAsInitials, asArray } from '../utils/index.js';
|
|
45
46
|
import { useDatalayer } from './useDatalayer.js';
|
|
@@ -2853,6 +2854,7 @@ export const useCache = ({ loginRoute = '/login' } = {}) => {
|
|
|
2853
2854
|
},
|
|
2854
2855
|
...DEFAULT_QUERY_OPTIONS,
|
|
2855
2856
|
refetchOnMount: true, // Override to refetch when stale after invalidation
|
|
2857
|
+
enabled: options?.enabled ?? true,
|
|
2856
2858
|
});
|
|
2857
2859
|
};
|
|
2858
2860
|
/**
|
|
@@ -5740,14 +5742,17 @@ export const useCache = ({ loginRoute = '/login' } = {}) => {
|
|
|
5740
5742
|
});
|
|
5741
5743
|
};
|
|
5742
5744
|
/**
|
|
5743
|
-
* Confirm password change with token
|
|
5745
|
+
* Confirm password change with the token the reset email carried. The
|
|
5746
|
+
* handle and token travel in the body, never in the URL: paths are written
|
|
5747
|
+
* to access logs.
|
|
5744
5748
|
*/
|
|
5745
5749
|
const useConfirmPasswordWithToken = () => {
|
|
5746
5750
|
return useMutation({
|
|
5747
5751
|
mutationFn: async ({ userHandle, token, }) => {
|
|
5748
5752
|
return requestDatalayer({
|
|
5749
|
-
url: `${configuration.iamUrl}/api/iam/v1/password/confirm
|
|
5750
|
-
method: '
|
|
5753
|
+
url: `${configuration.iamUrl}/api/iam/v1/password-reset/confirm`,
|
|
5754
|
+
method: 'POST',
|
|
5755
|
+
body: { handle: userHandle, token },
|
|
5751
5756
|
});
|
|
5752
5757
|
},
|
|
5753
5758
|
});
|
|
@@ -7273,13 +7278,38 @@ export const useCache = ({ loginRoute = '/login' } = {}) => {
|
|
|
7273
7278
|
},
|
|
7274
7279
|
});
|
|
7275
7280
|
};
|
|
7276
|
-
/**
|
|
7281
|
+
/**
|
|
7282
|
+
* Unlink a provider (github, google, linkedin, x) from the signed-in
|
|
7283
|
+
* account; IAM deletes the link and the tokens it holds for it.
|
|
7284
|
+
*
|
|
7285
|
+
* IAM's refusal (409: the provider is the account's only way to sign in)
|
|
7286
|
+
* is the error's message, for the page to show: nothing is toasted. On
|
|
7287
|
+
* success the signed-in user is read again, so the settings pages and the
|
|
7288
|
+
* header's provider icons follow its linked providers.
|
|
7289
|
+
*/
|
|
7290
|
+
const useUnlinkIAMProvider = () => {
|
|
7291
|
+
const iamStore = useIAMStore();
|
|
7292
|
+
return useMutation({
|
|
7293
|
+
mutationFn: async (provider) => unlinkIAMProvider(requestDatalayer, configuration.iamUrl, provider, async () => {
|
|
7294
|
+
queryClient.invalidateQueries({ queryKey: queryKeys.auth.me() });
|
|
7295
|
+
await iamStore.refreshUser();
|
|
7296
|
+
}),
|
|
7297
|
+
});
|
|
7298
|
+
};
|
|
7299
|
+
/**
|
|
7300
|
+
* Get the server-connected LinkedIn profile.
|
|
7301
|
+
*
|
|
7302
|
+
* IAM answers 404 when no LinkedIn posting account is connected: a state
|
|
7303
|
+
* the caller shows (a link button), never an error toast. The resolved
|
|
7304
|
+
* response then carries `success: false`, `status` and `message`.
|
|
7305
|
+
*/
|
|
7277
7306
|
const useGetLinkedinProfile = () => {
|
|
7278
7307
|
return useMutation({
|
|
7279
7308
|
mutationFn: async () => {
|
|
7280
7309
|
return requestDatalayer({
|
|
7281
7310
|
url: `${configuration.iamUrl}/api/iam/v1/social/linkedin/profile`,
|
|
7282
7311
|
method: 'GET',
|
|
7312
|
+
notifyOnError: false,
|
|
7283
7313
|
});
|
|
7284
7314
|
},
|
|
7285
7315
|
});
|
|
@@ -8426,6 +8456,7 @@ export const useCache = ({ loginRoute = '/login' } = {}) => {
|
|
|
8426
8456
|
useGetGitHubProfile,
|
|
8427
8457
|
useGetGoogleProfile,
|
|
8428
8458
|
useGetLinkedinProfile,
|
|
8459
|
+
useUnlinkIAMProvider,
|
|
8429
8460
|
usePostLinkedinShare,
|
|
8430
8461
|
usePostLinkedinShareWithUpload,
|
|
8431
8462
|
useGetBlueskyConnection,
|
package/lib/hooks/useNavigate.js
CHANGED
|
@@ -25,6 +25,7 @@
|
|
|
25
25
|
import { useCallback, useMemo } from 'react';
|
|
26
26
|
import { useLayoutStore } from '../state/index.js';
|
|
27
27
|
import { navigationStore } from '../state/substates/NavigationState.js';
|
|
28
|
+
import { iamStore } from '../state/substates/IAMState.js';
|
|
28
29
|
import { createNativeNavigate } from '../navigation/adapters/native.js';
|
|
29
30
|
// Import React Router hooks from our wrapper
|
|
30
31
|
import { useNavigateRR } from '../navigation/adapters/react-router.js';
|
|
@@ -133,8 +134,13 @@ export const useNavigate = () => {
|
|
|
133
134
|
document.body.scrollTop = 0;
|
|
134
135
|
}
|
|
135
136
|
// Where the reader is now, for the shell they are in. A new tab and a
|
|
136
|
-
// step back through history are both already past by here.
|
|
137
|
-
|
|
137
|
+
// step back through history are both already past by here. Only for
|
|
138
|
+
// somebody signed in: the shells are theirs, and a page a visitor read
|
|
139
|
+
// signed out (`/features`) would otherwise come back as the Platform's
|
|
140
|
+
// last page after they sign in.
|
|
141
|
+
if (iamStore.getState().user) {
|
|
142
|
+
navigationStore.getState().rememberRoute(to);
|
|
143
|
+
}
|
|
138
144
|
if (rrNavigate) {
|
|
139
145
|
rrNavigate(to, { replace: options.replace, state: options.state });
|
|
140
146
|
return;
|
|
@@ -4,16 +4,11 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
|
4
4
|
* Distributed under the terms of the Modified BSD License.
|
|
5
5
|
*/
|
|
6
6
|
import { AlertIcon } from '@primer/octicons-react';
|
|
7
|
-
import { Box
|
|
7
|
+
import { Box } from '@datalayer/primer-addons';
|
|
8
|
+
import { Button, Flash } from '@primer/react';
|
|
8
9
|
import { useNavigate } from '../../hooks/index.js';
|
|
9
10
|
export const FlashMock = () => {
|
|
10
11
|
const navigate = useNavigate();
|
|
11
|
-
return (_jsx(Flash, { variant: "warning", style: { marginBottom: 10 }, children: _jsxs(Box, {
|
|
12
|
-
display: 'flex',
|
|
13
|
-
alignItems: 'center',
|
|
14
|
-
justifyContent: 'space-between',
|
|
15
|
-
gap: 3,
|
|
16
|
-
width: '100%',
|
|
17
|
-
}, children: [_jsxs(Box, { sx: { display: 'flex', alignItems: 'center', gap: 2 }, children: [_jsx(AlertIcon, {}), _jsx("span", { children: "This is placeholder content. Contact us to learn more about this feature." })] }), _jsx(Button, { size: "small", onClick: () => navigate('/contact'), children: "Contact Us" })] }) }));
|
|
12
|
+
return (_jsx(Flash, { variant: "warning", style: { marginBottom: 10 }, children: _jsxs(Box, { display: "flex", alignItems: "center", justifyContent: "space-between", gap: 3, width: "100%", children: [_jsxs(Box, { display: "flex", alignItems: "center", gap: 2, children: [_jsx(AlertIcon, {}), _jsx("span", { children: "This is placeholder content. Contact us to learn more about this feature." })] }), _jsx(Button, { size: "small", onClick: () => navigate('/contact'), children: "Contact Us" })] }) }));
|
|
18
13
|
};
|
|
19
14
|
export default FlashMock;
|