@datalayer/core 1.2.18 → 1.2.19
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.js +3 -27
- package/lib/components/billing/BillingEntitySelect.js +6 -48
- package/lib/components/checkout/StripeCheckout.js +33 -217
- 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/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.js +19 -63
- package/lib/components/principal/PrincipalAvatar.js +5 -25
- package/lib/components/principal/PrincipalBadge.js +3 -13
- package/lib/components/principal/PrincipalBanner.js +4 -32
- package/lib/components/principal/PrincipalDetailsOverlay.js +7 -23
- 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/useAuthorization.js +6 -1
- 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/Person.d.ts +9 -0
- package/lib/models/Person.js +23 -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 +8 -0
- package/lib/portable/index.js +12 -0
- package/lib/state/substates/NavigationState.d.ts +6 -4
- package/lib/state/substates/NavigationState.js +6 -5
- 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 +2 -10
- package/lib/views/mcp/AlertRules.js +4 -9
- package/lib/views/mcp/ApprovalQueue.js +4 -21
- package/lib/views/mcp/AuditLog.js +7 -44
- package/lib/views/mcp/ConnectedAgents.js +1 -6
- package/lib/views/mcp/EnterpriseConsole.js +10 -23
- package/lib/views/mcp/IdentityProviders.js +7 -31
- package/lib/views/mcp/McpDashboard.js +14 -30
- package/lib/views/mcp/McpHome.js +7 -54
- package/lib/views/mcp/McpObservability.js +13 -85
- package/lib/views/mcp/NotebookRuns.js +5 -12
- package/lib/views/mcp/OrganizationPolicy.js +3 -9
- package/lib/views/mcp/OrganizationUsage.js +4 -11
- package/lib/views/mcp/PersonalPolicy.js +3 -3
- package/lib/views/mcp/Policies.js +5 -46
- package/lib/views/mcp/PolicyForm.js +1 -9
- package/lib/views/mcp/PolicyHistory.js +2 -8
- package/lib/views/mcp/RunDetail.js +3 -25
- package/lib/views/mcp/ScimProvisioning.js +3 -15
- package/lib/views/mcp/ServiceAgents.js +4 -17
- package/lib/views/mcp/TeamPolicies.js +7 -19
- package/lib/views/mcp/ToolAccess.js +15 -22
- 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
|
@@ -66,5 +66,5 @@ export function ConsumptionBar(props) {
|
|
|
66
66
|
...(paddingRight !== undefined ? { paddingRight } : {}),
|
|
67
67
|
...(paddingTop !== undefined ? { paddingTop } : {}),
|
|
68
68
|
...(paddingBottom !== undefined ? { paddingBottom } : {}),
|
|
69
|
-
}, children: _jsx(Box, {
|
|
69
|
+
}, children: _jsx(Box, { width: "70px", children: _jsx(ProgressBar, { style: style, animated: expiredAt ? false : true, bg: bg, progress: progress }) }) }) }) }));
|
|
70
70
|
}
|
|
@@ -314,13 +314,7 @@ export function hydrateAccessFromSharing(sharing, levels) {
|
|
|
314
314
|
// Avatar shimmer (used while a user row is being hydrated).
|
|
315
315
|
// ---------------------------------------------------------------------------
|
|
316
316
|
function AvatarShimmer({ size = 20 }) {
|
|
317
|
-
return (_jsx(Box, { sx: {
|
|
318
|
-
width: size,
|
|
319
|
-
height: size,
|
|
320
|
-
borderRadius: '50%',
|
|
321
|
-
backgroundImage: 'linear-gradient(90deg, var(--bgColor-muted, #d0d7de) 25%, var(--bgColor-default, #ffffff) 50%, var(--bgColor-muted, #d0d7de) 75%)',
|
|
322
|
-
backgroundSize: '220% 100%',
|
|
323
|
-
animation: 'avatarShimmerAcl 1.2s ease-in-out infinite',
|
|
317
|
+
return (_jsx(Box, { width: size, height: size, borderRadius: "50%", backgroundImage: "linear-gradient(90deg, var(--bgColor-muted, #d0d7de) 25%, var(--bgColor-default, #ffffff) 50%, var(--bgColor-muted, #d0d7de) 75%)", backgroundSize: "220% 100%", animation: "avatarShimmerAcl 1.2s ease-in-out infinite", sx: {
|
|
324
318
|
'@keyframes avatarShimmerAcl': {
|
|
325
319
|
'0%': { backgroundPosition: '100% 0' },
|
|
326
320
|
'100%': { backgroundPosition: '-100% 0' },
|
|
@@ -336,28 +330,12 @@ function AvatarShimmer({ size = 20 }) {
|
|
|
336
330
|
* pushed through the personal/team/organization avatar system.
|
|
337
331
|
*/
|
|
338
332
|
function AgentAvatar({ size = 20 }) {
|
|
339
|
-
return (_jsx(Box, {
|
|
340
|
-
display: 'inline-flex',
|
|
341
|
-
alignItems: 'center',
|
|
342
|
-
justifyContent: 'center',
|
|
343
|
-
width: size,
|
|
344
|
-
height: size,
|
|
345
|
-
borderRadius: 2,
|
|
346
|
-
bg: 'canvas.subtle',
|
|
347
|
-
color: 'fg.muted',
|
|
348
|
-
flexShrink: 0,
|
|
349
|
-
}, "aria-label": "Agent", children: _jsx(KeyIcon, { size: Math.max(12, Math.round(size * 0.6)) }) }));
|
|
333
|
+
return (_jsx(Box, { display: "inline-flex", alignItems: "center", justifyContent: "center", width: size, height: size, borderRadius: 2, bg: "canvas.subtle", color: "fg.muted", flexShrink: 0, "aria-label": "Agent", children: _jsx(KeyIcon, { size: Math.max(12, Math.round(size * 0.6)) }) }));
|
|
350
334
|
}
|
|
351
335
|
/** An agent as it appears in a row of principals: key, name, and the label
|
|
352
336
|
* that says what it is, so an agent is never mistaken for a person. */
|
|
353
337
|
function AgentPrincipalChip({ displayName, size = 20, }) {
|
|
354
|
-
return (_jsxs(Box, { sx: {
|
|
355
|
-
display: 'inline-flex',
|
|
356
|
-
alignItems: 'center',
|
|
357
|
-
gap: 1,
|
|
358
|
-
minWidth: 0,
|
|
359
|
-
flexWrap: 'wrap',
|
|
360
|
-
}, children: [_jsx(AgentAvatar, { size: size }), _jsx(Text, { sx: { minWidth: 0 }, children: displayName }), _jsx(Label, { size: "small", children: "Agent" })] }));
|
|
338
|
+
return (_jsxs(Box, { display: "inline-flex", alignItems: "center", gap: 1, minWidth: 0, flexWrap: "wrap", children: [_jsx(AgentAvatar, { size: size }), _jsx(Text, { sx: { minWidth: 0 }, children: displayName }), _jsx(Label, { size: "small", children: "Agent" })] }));
|
|
361
339
|
}
|
|
362
340
|
function OwnerPrincipalRow({ ownerPrincipal, cache, showAvatarSkeleton = false, isPlatformAdmin, }) {
|
|
363
341
|
const entry = cache[principalKey(ownerPrincipal.kind, ownerPrincipal.uid)] || {};
|
|
@@ -373,12 +351,7 @@ function OwnerPrincipalRow({ ownerPrincipal, cache, showAvatarSkeleton = false,
|
|
|
373
351
|
const resolvedOrigin = ownerPrincipal.origin ||
|
|
374
352
|
entry.origin ||
|
|
375
353
|
(ownerPrincipal.kind === 'personal' ? 'Datalayer' : undefined);
|
|
376
|
-
return (_jsx(Box, { sx: {
|
|
377
|
-
display: 'inline-flex',
|
|
378
|
-
alignItems: 'center',
|
|
379
|
-
gap: 1,
|
|
380
|
-
flexWrap: 'wrap',
|
|
381
|
-
}, children: showAvatarSkeleton ? (_jsxs(_Fragment, { children: [_jsx(AvatarShimmer, { size: 20 }), _jsx(Text, { sx: { fontWeight: 'semibold' }, children: resolvedDisplayName })] })) : (_jsx(PrincipalBadge, { principal: {
|
|
354
|
+
return (_jsx(Box, { display: "inline-flex", alignItems: "center", gap: 1, flexWrap: "wrap", children: showAvatarSkeleton ? (_jsxs(_Fragment, { children: [_jsx(AvatarShimmer, { size: 20 }), _jsx(Text, { sx: { fontWeight: 'semibold' }, children: resolvedDisplayName })] })) : (_jsx(PrincipalBadge, { principal: {
|
|
382
355
|
kind: ownerPrincipal.kind,
|
|
383
356
|
uid: ownerPrincipal.uid,
|
|
384
357
|
displayName: resolvedDisplayName,
|
|
@@ -394,12 +367,7 @@ function AccessPrincipalRow({ entry, cache, showAvatarSkeleton = false, isPlatfo
|
|
|
394
367
|
const safeCachedHandle = cachedHandle && cachedHandle !== entry.uid ? cachedHandle : '';
|
|
395
368
|
const resolvedHandle = safeCachedHandle || cached.accountHandle;
|
|
396
369
|
const resolvedDisplayName = ensurePrincipalDisplayName(entry.kind, cached.displayName, formatPrincipalHandle(entry.kind, resolvedHandle, cached.accountHandle), resolvedHandle, entry.uid);
|
|
397
|
-
return (_jsx(Box, {
|
|
398
|
-
display: 'inline-flex',
|
|
399
|
-
alignItems: 'center',
|
|
400
|
-
gap: 1,
|
|
401
|
-
flexWrap: 'wrap',
|
|
402
|
-
}, children: showAvatarSkeleton ? (_jsxs(_Fragment, { children: [_jsx(AvatarShimmer, { size: 20 }), _jsx(Text, { children: resolvedDisplayName })] })) : entry.kind === 'agent' ? (_jsx(AgentPrincipalChip, { displayName: resolvedDisplayName })) : (_jsx(PrincipalBadge, { principal: {
|
|
370
|
+
return (_jsx(Box, { display: "inline-flex", alignItems: "center", gap: 1, flexWrap: "wrap", children: showAvatarSkeleton ? (_jsxs(_Fragment, { children: [_jsx(AvatarShimmer, { size: 20 }), _jsx(Text, { children: resolvedDisplayName })] })) : entry.kind === 'agent' ? (_jsx(AgentPrincipalChip, { displayName: resolvedDisplayName })) : (_jsx(PrincipalBadge, { principal: {
|
|
403
371
|
kind: entry.kind,
|
|
404
372
|
uid: entry.uid,
|
|
405
373
|
displayName: resolvedDisplayName,
|
|
@@ -1228,142 +1196,34 @@ export function ShareAccessComponent({ isOpen, requestUrl, transport, resourceLa
|
|
|
1228
1196
|
if (!alreadyAdded) {
|
|
1229
1197
|
addPrincipal(principal.kind, principal.uid);
|
|
1230
1198
|
}
|
|
1231
|
-
}, disabled: alreadyAdded || isSaving || isReadOnly,
|
|
1232
|
-
|
|
1233
|
-
|
|
1234
|
-
|
|
1235
|
-
|
|
1236
|
-
gap: 2,
|
|
1237
|
-
px: 2,
|
|
1238
|
-
py: 2,
|
|
1239
|
-
cursor: alreadyAdded || isSaving || isReadOnly ? 'not-allowed' : 'pointer',
|
|
1240
|
-
opacity: alreadyAdded ? 0.55 : 1,
|
|
1241
|
-
borderRadius: 2,
|
|
1242
|
-
borderWidth: 1,
|
|
1243
|
-
borderStyle: 'solid',
|
|
1244
|
-
borderColor: 'border.default',
|
|
1245
|
-
bg: 'canvas.default',
|
|
1246
|
-
':hover': {
|
|
1247
|
-
bg: alreadyAdded || isSaving || isReadOnly
|
|
1248
|
-
? 'canvas.default'
|
|
1249
|
-
: 'canvas.subtle',
|
|
1250
|
-
},
|
|
1251
|
-
}, children: [_jsxs(Box, { sx: {
|
|
1252
|
-
display: 'inline-flex',
|
|
1253
|
-
alignItems: 'center',
|
|
1254
|
-
gap: 2,
|
|
1255
|
-
minWidth: 0,
|
|
1256
|
-
}, children: [principal.kind === 'agent' ? (_jsx(AgentAvatar, { size: 22 })) : (_jsx(PrincipalAvatar, { kind: principal.kind, avatarUrl: principal.avatarUrl || undefined, alt: displayName, size: 22 })), _jsxs(Box, { sx: { display: 'grid', minWidth: 0 }, children: [_jsxs(Box, { sx: {
|
|
1257
|
-
display: 'inline-flex',
|
|
1258
|
-
alignItems: 'center',
|
|
1259
|
-
gap: 1,
|
|
1260
|
-
flexWrap: 'wrap',
|
|
1261
|
-
}, children: [_jsx(Text, { sx: { fontWeight: 'semibold' }, children: displayName }), principal.kind === 'personal' &&
|
|
1199
|
+
}, disabled: alreadyAdded || isSaving || isReadOnly, display: "flex", alignItems: "center", justifyContent: "space-between", gap: 2, px: 2, py: 2, cursor: alreadyAdded || isSaving || isReadOnly ? 'not-allowed' : 'pointer', opacity: alreadyAdded ? 0.55 : 1, borderRadius: 2, borderWidth: 1, borderStyle: "solid", borderColor: "border.default", bg: "canvas.default", hover: {
|
|
1200
|
+
bg: alreadyAdded || isSaving || isReadOnly
|
|
1201
|
+
? 'canvas.default'
|
|
1202
|
+
: 'canvas.subtle',
|
|
1203
|
+
}, all: "unset", children: [_jsxs(Box, { display: "inline-flex", alignItems: "center", gap: 2, minWidth: 0, children: [principal.kind === 'agent' ? (_jsx(AgentAvatar, { size: 22 })) : (_jsx(PrincipalAvatar, { kind: principal.kind, avatarUrl: principal.avatarUrl || undefined, alt: displayName, size: 22 })), _jsxs(Box, { display: "grid", minWidth: 0, children: [_jsxs(Box, { display: "inline-flex", alignItems: "center", gap: 1, flexWrap: "wrap", children: [_jsx(Text, { sx: { fontWeight: 'semibold' }, children: displayName }), principal.kind === 'personal' &&
|
|
1262
1204
|
user?.uid &&
|
|
1263
|
-
principal.uid === user.uid && (_jsx(Label, { size: "small", variant: "accent", children: "You" }))] }), _jsxs(Text, { sx: { fontSize: 0, color: 'fg.muted' }, children: ["@", principal.handle, principal.kind === 'team' && principal.organizationHandle && (_jsxs(Text, { as: "span", sx: { color: 'fg.muted' }, children: [' · ', "org @", principal.organizationHandle] }))] })] })] }), _jsxs(Box, {
|
|
1205
|
+
principal.uid === user.uid && (_jsx(Label, { size: "small", variant: "accent", children: "You" }))] }), _jsxs(Text, { sx: { fontSize: 0, color: 'fg.muted' }, children: ["@", principal.handle, principal.kind === 'team' && principal.organizationHandle && (_jsxs(Text, { as: "span", sx: { color: 'fg.muted' }, children: [' · ', "org @", principal.organizationHandle] }))] })] })] }), _jsxs(Box, { display: "inline-flex", alignItems: "center", gap: 1, children: [_jsx(Icon, { size: 14 }), alreadyAdded ? (_jsx(Label, { size: "small", variant: "success", children: "Added" })) : (_jsx(Text, { sx: { fontSize: 0, color: 'fg.muted' }, children: "Add" }))] })] }, principalKey(principal.kind, principal.uid)));
|
|
1264
1206
|
};
|
|
1265
1207
|
const renderShareableGroup = (label, items) => {
|
|
1266
1208
|
if (items.length === 0) {
|
|
1267
1209
|
return null;
|
|
1268
1210
|
}
|
|
1269
|
-
return (_jsxs(Box, {
|
|
1211
|
+
return (_jsxs(Box, { display: "grid", gap: 1, children: [_jsx(Text, { sx: {
|
|
1270
1212
|
fontSize: 0,
|
|
1271
1213
|
color: 'fg.muted',
|
|
1272
1214
|
textTransform: 'uppercase',
|
|
1273
1215
|
letterSpacing: 0.4,
|
|
1274
|
-
}, children: label }), _jsx(Box, {
|
|
1216
|
+
}, children: label }), _jsx(Box, { display: "grid", gap: 1, children: items.map(renderShareablePrincipalRow) })] }));
|
|
1275
1217
|
};
|
|
1276
|
-
const content = (_jsxs(Box, {
|
|
1277
|
-
px: 3,
|
|
1278
|
-
py: 3,
|
|
1279
|
-
borderRadius: 2,
|
|
1280
|
-
borderWidth: 1,
|
|
1281
|
-
borderStyle: 'solid',
|
|
1282
|
-
borderColor: 'attention.muted',
|
|
1283
|
-
bg: 'attention.subtle',
|
|
1284
|
-
display: 'grid',
|
|
1285
|
-
gap: 1,
|
|
1286
|
-
}, children: [_jsx(Text, { sx: { fontWeight: 600 }, children: "Sharing access is restricted" }), _jsx(Text, { sx: { color: 'fg.muted' }, children: sharingAccessMessage })] })), _jsxs(Box, { sx: {
|
|
1287
|
-
opacity: isReadOnly ? 0.6 : 1,
|
|
1288
|
-
pointerEvents: isReadOnly ? 'none' : 'auto',
|
|
1289
|
-
display: 'flex',
|
|
1290
|
-
flexDirection: 'column',
|
|
1291
|
-
gap: 3,
|
|
1292
|
-
}, "aria-disabled": isReadOnly, children: [_jsxs(Box, { sx: {
|
|
1293
|
-
px: 3,
|
|
1294
|
-
py: 2,
|
|
1295
|
-
borderRadius: 2,
|
|
1296
|
-
borderWidth: 1,
|
|
1297
|
-
borderStyle: 'solid',
|
|
1298
|
-
borderColor: 'border.default',
|
|
1299
|
-
bg: 'canvas.subtle',
|
|
1300
|
-
display: 'flex',
|
|
1301
|
-
alignItems: 'flex-start',
|
|
1302
|
-
justifyContent: 'space-between',
|
|
1303
|
-
gap: 2,
|
|
1304
|
-
}, children: [_jsx(Box, { sx: { display: 'grid', gap: 1 }, children: _jsxs(Text, { sx: { fontSize: 1, color: 'fg.muted' }, children: ["Share ", resourceName || `this ${resourceLabel.toLowerCase()}`, ". Pick a principal below \u2014 they will be granted the selected access level."] }) }), _jsxs(ActionMenu, { children: [_jsxs(Box, { sx: { display: 'inline-flex', alignItems: 'center', gap: 1 }, children: [_jsx(ActionMenu.Anchor, { children: _jsxs(Button, { variant: "default", size: "small", leadingVisual: KeyIcon, disabled: isSaving || isReadOnly, children: ["Access:", ' ', levelLabels[selectedAccessLevel] || selectedAccessLevel] }) }), _jsx(Button, { variant: "invisible", size: "small", leadingVisual: isExpanded ? ChevronUpIcon : ChevronDownIcon, onClick: () => setIsExpanded(previous => !previous), "aria-label": isExpanded
|
|
1218
|
+
const content = (_jsxs(Box, { p: 3, display: "flex", flexDirection: "column", gap: 3, children: [sharingAccessMessage && (_jsxs(Box, { px: 3, py: 3, borderRadius: 2, borderWidth: 1, borderStyle: "solid", borderColor: "attention.muted", bg: "attention.subtle", display: "grid", gap: 1, children: [_jsx(Text, { sx: { fontWeight: 600 }, children: "Sharing access is restricted" }), _jsx(Text, { sx: { color: 'fg.muted' }, children: sharingAccessMessage })] })), _jsxs(Box, { opacity: isReadOnly ? 0.6 : 1, pointerEvents: isReadOnly ? 'none' : 'auto', display: "flex", flexDirection: "column", gap: 3, "aria-disabled": isReadOnly, children: [_jsxs(Box, { px: 3, py: 2, borderRadius: 2, borderWidth: 1, borderStyle: "solid", borderColor: "border.default", bg: "canvas.subtle", display: "flex", alignItems: "flex-start", justifyContent: "space-between", gap: 2, children: [_jsx(Box, { display: "grid", gap: 1, children: _jsxs(Text, { sx: { fontSize: 1, color: 'fg.muted' }, children: ["Share ", resourceName || `this ${resourceLabel.toLowerCase()}`, ". Pick a principal below \u2014 they will be granted the selected access level."] }) }), _jsxs(ActionMenu, { children: [_jsxs(Box, { display: "inline-flex", alignItems: "center", gap: 1, children: [_jsx(ActionMenu.Anchor, { children: _jsxs(Button, { variant: "default", size: "small", leadingVisual: KeyIcon, disabled: isSaving || isReadOnly, children: ["Access:", ' ', levelLabels[selectedAccessLevel] || selectedAccessLevel] }) }), _jsx(Button, { variant: "invisible", size: "small", leadingVisual: isExpanded ? ChevronUpIcon : ChevronDownIcon, onClick: () => setIsExpanded(previous => !previous), "aria-label": isExpanded
|
|
1305
1219
|
? 'Shrink sharing details'
|
|
1306
|
-
: 'Expand sharing details', children: isExpanded ? 'Shrink details' : 'Expand details' })] }), _jsx(ActionMenu.Overlay, { width: "small", children: _jsx(ActionList, { selectionVariant: "single", children: levels.map(({ level, label }) => (_jsx(ActionList.Item, { selected: selectedAccessLevel === level, onSelect: () => setSelectedAccessLevel(level), children: label }, level))) }) })] })] }), !isExpanded && (_jsxs(Box, { sx: {
|
|
1307
|
-
|
|
1308
|
-
py: 2,
|
|
1309
|
-
borderRadius: 2,
|
|
1310
|
-
borderWidth: 1,
|
|
1311
|
-
borderStyle: 'solid',
|
|
1312
|
-
borderColor: 'border.default',
|
|
1313
|
-
bg: 'canvas.default',
|
|
1314
|
-
display: 'grid',
|
|
1315
|
-
gap: 1,
|
|
1316
|
-
}, children: [_jsx(Text, { sx: { fontSize: 1, color: 'fg.muted' }, children: "Sharing details are collapsed." }), _jsxs(Text, { sx: { fontSize: 0, color: 'fg.muted' }, children: [aclEntries.length, " principal", aclEntries.length === 1 ? '' : 's', ' ', "currently granted access."] })] })), isExpanded && (_jsxs(_Fragment, { children: [_jsxs(Box, { sx: {
|
|
1317
|
-
px: 3,
|
|
1318
|
-
py: 2,
|
|
1319
|
-
borderRadius: 2,
|
|
1320
|
-
borderWidth: 1,
|
|
1321
|
-
borderStyle: 'solid',
|
|
1322
|
-
borderColor: 'border.default',
|
|
1323
|
-
bg: 'canvas.default',
|
|
1324
|
-
display: 'grid',
|
|
1325
|
-
gap: 1,
|
|
1326
|
-
}, children: [_jsx(Text, { sx: { fontSize: 1, color: 'fg.muted' }, children: "Owner" }), ownerPrincipals.length > 0 ? (_jsx(Box, { sx: { display: 'grid' }, children: ownerPrincipals.map((ownerPrincipal, index) => (_jsx(Box, { sx: {
|
|
1327
|
-
py: 1,
|
|
1328
|
-
borderTopWidth: index === 0 ? 0 : 1,
|
|
1329
|
-
borderTopStyle: 'solid',
|
|
1330
|
-
borderColor: 'border.subtle',
|
|
1331
|
-
}, children: _jsx(OwnerPrincipalRow, { ownerPrincipal: ownerPrincipal, cache: principalCache, showAvatarSkeleton: ownerPrincipal.kind === 'personal' &&
|
|
1332
|
-
Boolean(hydratingUserUids[ownerPrincipal.uid]), isPlatformAdmin: isPlatformAdmin }) }, principalKey(ownerPrincipal.kind, ownerPrincipal.uid)))) })) : (_jsx(Text, { sx: { fontSize: 1, color: 'fg.muted' }, children: "Owner information is not available." }))] }), _jsxs(Box, { sx: {
|
|
1333
|
-
px: 3,
|
|
1334
|
-
py: 2,
|
|
1335
|
-
borderRadius: 2,
|
|
1336
|
-
borderWidth: 1,
|
|
1337
|
-
borderStyle: 'solid',
|
|
1338
|
-
borderColor: 'border.default',
|
|
1339
|
-
bg: 'canvas.default',
|
|
1340
|
-
display: 'grid',
|
|
1341
|
-
gap: 2,
|
|
1342
|
-
}, children: [_jsxs(Box, { sx: {
|
|
1343
|
-
display: 'flex',
|
|
1344
|
-
alignItems: 'center',
|
|
1345
|
-
justifyContent: 'space-between',
|
|
1346
|
-
gap: 2,
|
|
1347
|
-
}, children: [_jsx(Text, { sx: { fontSize: 1, fontWeight: 600 }, children: "Share with\u2026" }), isLoadingShareable && (_jsxs(Box, { sx: {
|
|
1348
|
-
display: 'inline-flex',
|
|
1349
|
-
alignItems: 'center',
|
|
1350
|
-
gap: 1,
|
|
1351
|
-
}, children: [_jsx(Spinner, { size: "small" }), _jsx(Text, { sx: { fontSize: 0, color: 'fg.muted' }, children: "Loading\u2026" })] }))] }), !isLoadingShareable &&
|
|
1220
|
+
: 'Expand sharing details', children: isExpanded ? 'Shrink details' : 'Expand details' })] }), _jsx(ActionMenu.Overlay, { width: "small", children: _jsx(ActionList, { selectionVariant: "single", children: levels.map(({ level, label }) => (_jsx(ActionList.Item, { selected: selectedAccessLevel === level, onSelect: () => setSelectedAccessLevel(level), children: label }, level))) }) })] })] }), !isExpanded && (_jsxs(Box, { px: 3, py: 2, borderRadius: 2, borderWidth: 1, borderStyle: "solid", borderColor: "border.default", bg: "canvas.default", display: "grid", gap: 1, children: [_jsx(Text, { sx: { fontSize: 1, color: 'fg.muted' }, children: "Sharing details are collapsed." }), _jsxs(Text, { sx: { fontSize: 0, color: 'fg.muted' }, children: [aclEntries.length, " principal", aclEntries.length === 1 ? '' : 's', ' ', "currently granted access."] })] })), isExpanded && (_jsxs(_Fragment, { children: [_jsxs(Box, { px: 3, py: 2, borderRadius: 2, borderWidth: 1, borderStyle: "solid", borderColor: "border.default", bg: "canvas.default", display: "grid", gap: 1, children: [_jsx(Text, { sx: { fontSize: 1, color: 'fg.muted' }, children: "Owner" }), ownerPrincipals.length > 0 ? (_jsx(Box, { display: "grid", children: ownerPrincipals.map((ownerPrincipal, index) => (_jsx(Box, { py: 1, borderTopWidth: index === 0 ? 0 : 1, borderTopStyle: "solid", borderColor: "border.subtle", children: _jsx(OwnerPrincipalRow, { ownerPrincipal: ownerPrincipal, cache: principalCache, showAvatarSkeleton: ownerPrincipal.kind === 'personal' &&
|
|
1221
|
+
Boolean(hydratingUserUids[ownerPrincipal.uid]), isPlatformAdmin: isPlatformAdmin }) }, principalKey(ownerPrincipal.kind, ownerPrincipal.uid)))) })) : (_jsx(Text, { sx: { fontSize: 1, color: 'fg.muted' }, children: "Owner information is not available." }))] }), _jsxs(Box, { px: 3, py: 2, borderRadius: 2, borderWidth: 1, borderStyle: "solid", borderColor: "border.default", bg: "canvas.default", display: "grid", gap: 2, children: [_jsxs(Box, { display: "flex", alignItems: "center", justifyContent: "space-between", gap: 2, children: [_jsx(Text, { sx: { fontSize: 1, fontWeight: 600 }, children: "Share with\u2026" }), isLoadingShareable && (_jsxs(Box, { display: "inline-flex", alignItems: "center", gap: 1, children: [_jsx(Spinner, { size: "small" }), _jsx(Text, { sx: { fontSize: 0, color: 'fg.muted' }, children: "Loading\u2026" })] }))] }), !isLoadingShareable &&
|
|
1352
1222
|
groupedShareable.self.length === 0 &&
|
|
1353
1223
|
groupedShareable.otherUsers.length === 0 &&
|
|
1354
1224
|
groupedShareable.orgs.length === 0 &&
|
|
1355
1225
|
groupedShareable.teams.length === 0 &&
|
|
1356
|
-
groupedShareable.agents.length === 0 ? (_jsx(Text, { sx: { fontSize: 1, color: 'fg.muted' }, children: "No principals available to share with." })) : (_jsxs(Box, {
|
|
1357
|
-
px: 3,
|
|
1358
|
-
py: 2,
|
|
1359
|
-
borderRadius: 2,
|
|
1360
|
-
borderWidth: 1,
|
|
1361
|
-
borderStyle: 'solid',
|
|
1362
|
-
borderColor: 'border.subtle',
|
|
1363
|
-
bg: 'canvas.subtle',
|
|
1364
|
-
display: 'grid',
|
|
1365
|
-
gap: 1,
|
|
1366
|
-
}, children: [_jsx(Text, { sx: { fontSize: 0, color: 'fg.muted' }, children: "Or search for any user, team, or organization" }), _jsxs(Box, { sx: { position: 'relative' }, ref: searchContainerRef, children: [_jsx(TextInput, { ref: searchInputRef, block: true, value: searchQuery, onChange: e => {
|
|
1226
|
+
groupedShareable.agents.length === 0 ? (_jsx(Text, { sx: { fontSize: 1, color: 'fg.muted' }, children: "No principals available to share with." })) : (_jsxs(Box, { display: "grid", gap: 2, children: [renderShareableGroup('You', groupedShareable.self), renderShareableGroup('Other users', groupedShareable.otherUsers), renderShareableGroup('Your organizations', groupedShareable.orgs), renderShareableGroup('Your teams', groupedShareable.teams), renderShareableGroup('Agents', groupedShareable.agents)] }))] }), _jsxs(Box, { px: 3, py: 2, borderRadius: 2, borderWidth: 1, borderStyle: "solid", borderColor: "border.subtle", bg: "canvas.subtle", display: "grid", gap: 1, children: [_jsx(Text, { sx: { fontSize: 0, color: 'fg.muted' }, children: "Or search for any user, team, or organization" }), _jsxs(Box, { position: "relative", ref: searchContainerRef, children: [_jsx(TextInput, { ref: searchInputRef, block: true, value: searchQuery, onChange: e => {
|
|
1367
1227
|
const next = e.target.value;
|
|
1368
1228
|
setSearchQuery(next);
|
|
1369
1229
|
setIsSearchOverlayOpen(next.trim().length > 0);
|
|
@@ -1376,82 +1236,14 @@ export function ShareAccessComponent({ isOpen, requestUrl, transport, resourceLa
|
|
|
1376
1236
|
e.preventDefault();
|
|
1377
1237
|
setIsSearchOverlayOpen(false);
|
|
1378
1238
|
}
|
|
1379
|
-
}, placeholder: "Search by handle, name, or email", "aria-label": "Search principals", disabled: isSaving }), canShowSearchResults && (_jsx(Box, { sx: {
|
|
1380
|
-
position: 'absolute',
|
|
1381
|
-
top: 'calc(100% + 8px)',
|
|
1382
|
-
left: 0,
|
|
1383
|
-
right: 0,
|
|
1384
|
-
zIndex: 100,
|
|
1385
|
-
borderWidth: 1,
|
|
1386
|
-
borderStyle: 'solid',
|
|
1387
|
-
borderColor: 'border.default',
|
|
1388
|
-
borderRadius: 2,
|
|
1389
|
-
maxHeight: '220px',
|
|
1390
|
-
overflowY: 'auto',
|
|
1391
|
-
bg: 'canvas.overlay',
|
|
1392
|
-
boxShadow: 'shadow.medium',
|
|
1393
|
-
}, children: isSearching ? (_jsxs(Box, { sx: {
|
|
1394
|
-
px: 3,
|
|
1395
|
-
py: 2,
|
|
1396
|
-
display: 'inline-flex',
|
|
1397
|
-
alignItems: 'center',
|
|
1398
|
-
gap: 2,
|
|
1399
|
-
}, children: [_jsx(Spinner, { size: "small" }), _jsx(Text, { sx: { fontSize: 1, color: 'fg.muted' }, children: "Searching\u2026" })] })) : searchResults.length === 0 ? (_jsx(Box, { sx: { px: 3, py: 2 }, children: _jsx(Text, { sx: { fontSize: 1, color: 'fg.muted' }, children: "No principals found." }) })) : (_jsx(ActionList, { children: searchResults.map(result => (_jsxs(ActionList.Item, { onSelect: () => handleSearchResultSelect(result), children: [_jsx(ActionList.LeadingVisual, { children: result.kind === 'agent' ? (_jsx(AgentAvatar, { size: 18 })) : (_jsx(PrincipalAvatar, { kind: result.kind, avatarUrl: result.avatarUrl, alt: result.displayName, size: 18 })) }), _jsxs(Box, { sx: {
|
|
1400
|
-
display: 'inline-flex',
|
|
1401
|
-
alignItems: 'center',
|
|
1402
|
-
gap: 1,
|
|
1403
|
-
flexWrap: 'wrap',
|
|
1404
|
-
}, children: [_jsx(Text, { children: result.displayName }), result.kind === 'personal' && (_jsx(Label, { size: "small", variant: "secondary", children: result.origin ||
|
|
1239
|
+
}, placeholder: "Search by handle, name, or email", "aria-label": "Search principals", disabled: isSaving }), canShowSearchResults && (_jsx(Box, { position: "absolute", top: "calc(100% + 8px)", left: 0, right: 0, zIndex: 100, borderWidth: 1, borderStyle: "solid", borderColor: "border.default", borderRadius: 2, maxHeight: "220px", overflowY: "auto", bg: "canvas.overlay", boxShadow: "shadow.medium", children: isSearching ? (_jsxs(Box, { px: 3, py: 2, display: "inline-flex", alignItems: "center", gap: 2, children: [_jsx(Spinner, { size: "small" }), _jsx(Text, { sx: { fontSize: 1, color: 'fg.muted' }, children: "Searching\u2026" })] })) : searchResults.length === 0 ? (_jsx(Box, { px: 3, py: 2, children: _jsx(Text, { sx: { fontSize: 1, color: 'fg.muted' }, children: "No principals found." }) })) : (_jsx(ActionList, { children: searchResults.map(result => (_jsxs(ActionList.Item, { onSelect: () => handleSearchResultSelect(result), children: [_jsx(ActionList.LeadingVisual, { children: result.kind === 'agent' ? (_jsx(AgentAvatar, { size: 18 })) : (_jsx(PrincipalAvatar, { kind: result.kind, avatarUrl: result.avatarUrl, alt: result.displayName, size: 18 })) }), _jsxs(Box, { display: "inline-flex", alignItems: "center", gap: 1, flexWrap: "wrap", children: [_jsx(Text, { children: result.displayName }), result.kind === 'personal' && (_jsx(Label, { size: "small", variant: "secondary", children: result.origin ||
|
|
1405
1240
|
principalCache[principalKey('personal', result.uid)]?.origin ||
|
|
1406
|
-
'Datalayer' }))] }), _jsxs(ActionList.Description, { variant: "block", children: ["@", result.handle] })] }, principalKey(result.kind, result.uid)))) })) }))] })] }), _jsxs(Box, { sx: {
|
|
1407
|
-
px: 3,
|
|
1408
|
-
py: 2,
|
|
1409
|
-
borderRadius: 2,
|
|
1410
|
-
borderWidth: 1,
|
|
1411
|
-
borderStyle: 'solid',
|
|
1412
|
-
borderColor: 'border.default',
|
|
1413
|
-
bg: 'canvas.default',
|
|
1414
|
-
display: 'grid',
|
|
1415
|
-
gap: 1,
|
|
1416
|
-
}, children: [_jsx(Text, { sx: { fontSize: 1, color: 'fg.muted' }, children: "Access Control List (ACL)" }), _jsx(Box, { sx: {
|
|
1417
|
-
borderWidth: 1,
|
|
1418
|
-
borderStyle: 'solid',
|
|
1419
|
-
borderColor: 'border.default',
|
|
1420
|
-
borderRadius: 2,
|
|
1421
|
-
maxHeight: '220px',
|
|
1422
|
-
overflowY: 'auto',
|
|
1423
|
-
bg: 'canvas.subtle',
|
|
1424
|
-
}, children: aclEntries.length === 0 ? (_jsx(Box, { sx: { px: 3, py: 2 }, children: _jsx(Text, { sx: { fontSize: 1, color: 'fg.muted' }, children: "No principals shared yet." }) })) : (_jsx(Box, { sx: { display: 'grid' }, children: aclEntries.map(entry => (_jsxs(Box, { sx: {
|
|
1425
|
-
px: 3,
|
|
1426
|
-
py: 2,
|
|
1427
|
-
display: 'flex',
|
|
1428
|
-
alignItems: 'center',
|
|
1429
|
-
justifyContent: 'space-between',
|
|
1430
|
-
gap: 2,
|
|
1431
|
-
borderTopWidth: 1,
|
|
1432
|
-
borderTopStyle: 'solid',
|
|
1433
|
-
borderColor: 'border.subtle',
|
|
1241
|
+
'Datalayer' }))] }), _jsxs(ActionList.Description, { variant: "block", children: ["@", result.handle] })] }, principalKey(result.kind, result.uid)))) })) }))] })] }), _jsxs(Box, { px: 3, py: 2, borderRadius: 2, borderWidth: 1, borderStyle: "solid", borderColor: "border.default", bg: "canvas.default", display: "grid", gap: 1, children: [_jsx(Text, { sx: { fontSize: 1, color: 'fg.muted' }, children: "Access Control List (ACL)" }), _jsx(Box, { borderWidth: 1, borderStyle: "solid", borderColor: "border.default", borderRadius: 2, maxHeight: "220px", overflowY: "auto", bg: "canvas.subtle", children: aclEntries.length === 0 ? (_jsx(Box, { px: 3, py: 2, children: _jsx(Text, { sx: { fontSize: 1, color: 'fg.muted' }, children: "No principals shared yet." }) })) : (_jsx(Box, { display: "grid", children: aclEntries.map(entry => (_jsxs(Box, { px: 3, py: 2, display: "flex", alignItems: "center", justifyContent: "space-between", gap: 2, borderTopWidth: 1, borderTopStyle: "solid", borderColor: "border.subtle", sx: {
|
|
1434
1242
|
'&:first-of-type': { borderTop: 'none' },
|
|
1435
1243
|
}, children: [_jsx(AccessPrincipalRow, { entry: entry, cache: principalCache, showAvatarSkeleton: entry.kind === 'personal' &&
|
|
1436
|
-
Boolean(hydratingUserUids[entry.uid]), isPlatformAdmin: isPlatformAdmin }), _jsx(Box, { sx: {
|
|
1437
|
-
display: 'flex',
|
|
1438
|
-
flexWrap: 'wrap',
|
|
1439
|
-
gap: 1,
|
|
1440
|
-
justifyContent: 'flex-end',
|
|
1441
|
-
}, children: entry.levels.map(level => (_jsx(Label, { size: "small", variant: "secondary", children: levelLabels[level] || level }, level))) }), _jsx(Button, { size: "small", variant: "invisible", onClick: () => removePrincipal(entry.kind, entry.uid), disabled: isSaving, children: "Remove" })] }, principalKey(entry.kind, entry.uid)))) })) })] })] }))] }), _jsxs(Box, { sx: {
|
|
1442
|
-
display: 'flex',
|
|
1443
|
-
justifyContent: 'flex-end',
|
|
1444
|
-
alignItems: 'center',
|
|
1445
|
-
gap: 2,
|
|
1446
|
-
}, children: [isSaving && (_jsxs(Box, { sx: { display: 'flex', alignItems: 'center', gap: 1 }, children: [_jsx(Spinner, { size: "small" }), _jsx(Text, { sx: { fontSize: 0, color: 'fg.muted' }, children: "Saving\u2026" })] })), displayMode === 'dialog' && (_jsx(Button, { onClick: onClose, disabled: isSaving, children: "Close" }))] }), isLoading && (_jsx(Text, { sx: { fontSize: 0, color: 'fg.muted' }, children: "Loading current sharing settings\u2026" }))] }));
|
|
1244
|
+
Boolean(hydratingUserUids[entry.uid]), isPlatformAdmin: isPlatformAdmin }), _jsx(Box, { display: "flex", flexWrap: "wrap", gap: 1, justifyContent: "flex-end", children: entry.levels.map(level => (_jsx(Label, { size: "small", variant: "secondary", children: levelLabels[level] || level }, level))) }), _jsx(Button, { size: "small", variant: "invisible", onClick: () => removePrincipal(entry.kind, entry.uid), disabled: isSaving, children: "Remove" })] }, principalKey(entry.kind, entry.uid)))) })) })] })] }))] }), _jsxs(Box, { display: "flex", justifyContent: "flex-end", alignItems: "center", gap: 2, children: [isSaving && (_jsxs(Box, { display: "flex", alignItems: "center", gap: 1, children: [_jsx(Spinner, { size: "small" }), _jsx(Text, { sx: { fontSize: 0, color: 'fg.muted' }, children: "Saving\u2026" })] })), displayMode === 'dialog' && (_jsx(Button, { onClick: onClose, disabled: isSaving, children: "Close" }))] }), isLoading && (_jsx(Text, { sx: { fontSize: 0, color: 'fg.muted' }, children: "Loading current sharing settings\u2026" }))] }));
|
|
1447
1245
|
if (displayMode === 'inline') {
|
|
1448
|
-
return (_jsx(Box, {
|
|
1449
|
-
borderWidth: 1,
|
|
1450
|
-
borderStyle: 'solid',
|
|
1451
|
-
borderColor: 'border.default',
|
|
1452
|
-
borderRadius: 2,
|
|
1453
|
-
bg: 'canvas.default',
|
|
1454
|
-
}, children: content }));
|
|
1246
|
+
return (_jsx(Box, { borderWidth: 1, borderStyle: "solid", borderColor: "border.default", borderRadius: 2, bg: "canvas.default", children: content }));
|
|
1455
1247
|
}
|
|
1456
1248
|
return (_jsx(Dialog, { title: `Share ${resourceLabel.toLowerCase()}`, onClose: onClose,
|
|
1457
1249
|
// Wider than any preset — Primer's `xlarge` stops at 640px, and the
|
|
@@ -45,6 +45,6 @@ export function SharingEditor({ value, onChange, label = 'Sharing', caption = 'E
|
|
|
45
45
|
catch (reason) {
|
|
46
46
|
setError(reason?.message || 'Invalid JSON');
|
|
47
47
|
}
|
|
48
|
-
}, sx: { width: '100%', fontFamily: 'mono' } }), _jsx(FormControl.Caption, { children: caption }), error && (_jsx(Box, {
|
|
48
|
+
}, sx: { width: '100%', fontFamily: 'mono' } }), _jsx(FormControl.Caption, { children: caption }), error && (_jsx(Box, { mt: 1, children: _jsx(Text, { sx: { color: 'danger.fg', fontSize: 1 }, children: error }) }))] }));
|
|
49
49
|
}
|
|
50
50
|
export default SharingEditor;
|
|
@@ -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;
|