@datalayer/core 1.2.19 → 1.2.21
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/api/evals/client.d.ts +6 -6
- package/lib/api/evals/client.js +5 -5
- package/lib/api/evals/status.d.ts +3 -3
- package/lib/api/evals/status.js +3 -3
- package/lib/api/evals/types.d.ts +9 -9
- package/lib/api/iam/secrets.js +2 -2
- package/lib/api/iam/servicePrincipals.js +1 -1
- package/lib/api/iam/trials.js +1 -1
- package/lib/api/orchestration/generated.d.ts +12 -12
- package/lib/api/orchestration/generated.js +1 -1
- package/lib/api/orchestration/index.d.ts +2 -2
- package/lib/api/orchestration/index.js +2 -2
- package/lib/api/orchestration/lifecycle.d.ts +1 -1
- package/lib/api/orchestration/lifecycle.js +1 -1
- package/lib/api/scheduler/client.d.ts +1 -1
- package/lib/api/scheduler/client.js +1 -1
- package/lib/api/scheduler/types.d.ts +1 -1
- package/lib/api/spacer/comments.d.ts +1 -1
- package/lib/api/spacer/comments.js +1 -1
- package/lib/api/spacer/spaces.d.ts +1 -1
- package/lib/api/spacer/spaces.js +1 -1
- package/lib/components/avatars/UserAvatar.d.ts +10 -11
- package/lib/components/avatars/UserAvatar.js +23 -28
- 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/collaboration/LiveEditorCollaborators.d.ts +3 -4
- package/lib/components/collaboration/LiveEditorCollaborators.js +7 -5
- 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/principal/Principal.js +1 -1
- package/lib/components/principal/PrincipalAppearance.d.ts +24 -1
- package/lib/components/principal/PrincipalAppearance.js +105 -34
- package/lib/components/principal/PrincipalAvatar.d.ts +5 -7
- package/lib/components/principal/PrincipalAvatar.js +12 -18
- package/lib/components/principal/PrincipalDetailsOverlay.d.ts +4 -7
- package/lib/components/principal/PrincipalDetailsOverlay.js +2 -2
- package/lib/components/principal/PrincipalSwitcherMenu.js +1 -1
- package/lib/hooks/unlinkIAMProvider.d.ts +22 -0
- package/lib/hooks/unlinkIAMProvider.js +24 -0
- package/lib/hooks/useCache.d.ts +8 -1
- package/lib/hooks/useCache.js +37 -6
- package/lib/hooks/useNavigate.js +8 -2
- 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/Profile.d.ts +2 -2
- package/lib/models/Secret.d.ts +1 -1
- package/lib/models/Secret.js +1 -1
- package/lib/models/StartedBy.d.ts +1 -1
- package/lib/models/StartedBy.js +1 -1
- package/lib/models/User.js +5 -12
- package/lib/models/UserOnboarding.d.ts +9 -0
- package/lib/models/UserOnboarding.js +33 -0
- package/lib/portable/index.d.ts +3 -2
- package/lib/portable/index.js +4 -2
- package/lib/portable/states.d.ts +39 -0
- package/lib/portable/states.js +71 -0
- package/lib/state/substates/NavigationState.d.ts +5 -3
- package/lib/state/substates/NavigationState.js +12 -3
- package/lib/views/mcp/AlertDestinations.js +2 -2
- package/lib/views/mcp/ApprovalQueue.js +2 -2
- package/lib/views/mcp/EnterpriseConsole.js +2 -2
- package/lib/views/mcp/McpDashboard.js +2 -2
- package/lib/views/mcp/McpHome.js +4 -4
- package/lib/views/mcp/McpObservability.js +5 -5
- package/lib/views/mcp/NotebookRuns.js +2 -2
- package/lib/views/mcp/OrganizationUsage.js +2 -2
- package/lib/views/mcp/Policies.js +2 -2
- package/lib/views/mcp/RunDetail.d.ts +1 -1
- package/lib/views/mcp/RunDetail.js +4 -1
- package/lib/views/mcp/ScimProvisioning.js +2 -2
- package/lib/views/mcp/ToolAccess.js +2 -2
- package/lib/views/secrets/SecretNew.js +1 -1
- package/package.json +1 -1
- package/scripts/generate-orchestration-types.py +12 -12
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* ✨ sparkles — Fluent Emoji, Flat, by Microsoft (MIT,
|
|
3
|
+
* see ../LICENSE). Written by scripts/generate-fluent-emoji.py: do not edit.
|
|
4
|
+
*/
|
|
5
|
+
export default '<svg width="32" height="32" viewBox="0 0 32 32" fill="none" xmlns="http://www.w3.org/2000/svg"> <path d="M10.5194 7.0517C10.2265 6.93064 9.99626 6.69861 9.88117 6.41614L8.929 4.25725C8.75112 3.91425 8.23842 3.91425 8.071 4.25725L7.11883 6.41614C6.99327 6.69861 6.76308 6.92055 6.48057 7.0517L5.26682 7.57629C4.91106 7.74779 4.91106 8.24212 5.26682 8.41362L6.48057 8.93821C6.77354 9.05927 7.00374 9.2913 7.11883 9.57377L8.071 11.7427C8.24888 12.0858 8.76158 12.0858 8.929 11.7427L9.88117 9.57377C10.0067 9.2913 10.2369 9.06936 10.5194 8.93821L11.7332 8.41362C12.0889 8.24212 12.0889 7.74779 11.7332 7.57629L10.5194 7.0517Z" fill="#F9C23C"/> <path d="M25.5744 13.5546C24.7045 13.1673 24.0166 12.4539 23.6525 11.5775L20.7897 4.81023C20.2637 3.72992 18.7363 3.72992 18.2103 4.81023L15.3475 11.5775C14.9733 12.4539 14.2854 13.1673 13.4256 13.5546L9.80419 15.1955C8.73194 15.7254 8.73194 17.2746 9.80419 17.8045L13.4256 19.4454C14.2955 19.8327 14.9834 20.5461 15.3475 21.4225L18.2103 28.1898C18.7363 29.2701 20.2637 29.2701 20.7897 28.1898L23.6525 21.4225C24.0267 20.5461 24.7146 19.8327 25.5744 19.4454L29.1958 17.8045C30.2681 17.2746 30.2681 15.7254 29.1958 15.1955L25.5744 13.5546Z" fill="#F9C23C"/> <path d="M8.2811 20.3304C8.44173 20.7222 8.73465 21.0258 9.10315 21.2021L10.6528 21.927C11.1157 22.1621 11.1157 22.8379 10.6528 23.073L9.10315 23.7979C8.73465 23.9742 8.44173 24.2876 8.2811 24.6696L7.05276 27.6474C6.82598 28.1175 6.17402 28.1175 5.94724 27.6474L4.7189 24.6696C4.55827 24.2778 4.26535 23.9742 3.89685 23.7979L2.34724 23.073C1.88425 22.8379 1.88425 22.1621 2.34724 21.927L3.89685 21.2021C4.26535 21.0258 4.55827 20.7124 4.7189 20.3304L5.94724 17.3526C6.17402 16.8825 6.82598 16.8825 7.05276 17.3526L8.2811 20.3304Z" fill="#F9C23C"/> </svg>';
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
declare const _default: "<svg width=\"32\" height=\"32\" viewBox=\"0 0 32 32\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\"> <path d=\"M4.02783 1.5C2.64712 1.5 1.52783 2.61929 1.52783 4V28C1.52783 29.3807 2.64712 30.5 4.02783 30.5H28.0278C29.4085 30.5 30.5278 29.3807 30.5278 28V4C30.5278 2.61929 29.4085 1.5 28.0278 1.5H4.02783Z\" fill=\"#9B9B9B\"/> <path d=\"M2.52783 4C2.52783 3.17157 3.19941 2.5 4.02783 2.5H28.0278C28.8563 2.5 29.5278 3.17157 29.5278 4V28C29.5278 28.8284 28.8563 29.5 28.0278 29.5H4.02783C3.19941 29.5 2.52783 28.8284 2.52783 28V4Z\" fill=\"white\"/> </svg>";
|
|
2
|
+
export default _default;
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* ⬜ white large square — Fluent Emoji, Flat, by Microsoft (MIT,
|
|
3
|
+
* see ../LICENSE). Written by scripts/generate-fluent-emoji.py: do not edit.
|
|
4
|
+
*/
|
|
5
|
+
export default '<svg width="32" height="32" viewBox="0 0 32 32" fill="none" xmlns="http://www.w3.org/2000/svg"> <path d="M4.02783 1.5C2.64712 1.5 1.52783 2.61929 1.52783 4V28C1.52783 29.3807 2.64712 30.5 4.02783 30.5H28.0278C29.4085 30.5 30.5278 29.3807 30.5278 28V4C30.5278 2.61929 29.4085 1.5 28.0278 1.5H4.02783Z" fill="#9B9B9B"/> <path d="M2.52783 4C2.52783 3.17157 3.19941 2.5 4.02783 2.5H28.0278C28.8563 2.5 29.5278 3.17157 29.5278 4V28C29.5278 28.8284 28.8563 29.5 28.0278 29.5H4.02783C3.19941 29.5 2.52783 28.8284 2.52783 28V4Z" fill="white"/> </svg>';
|
|
@@ -288,6 +288,6 @@ export const Principal = ({ principal, isAdmin = false, avatarSize = 20, gap = 2
|
|
|
288
288
|
resolvedIsPublic,
|
|
289
289
|
upsertCachedPrincipal,
|
|
290
290
|
]);
|
|
291
|
-
return (_jsxs(Box, { display: "inline-flex", alignItems: "center", gap: gap, minWidth: 0, sx: sx, children: [_jsx(PrincipalAvatar, { kind: resolvedPrincipal.kind, avatarUrl: resolvedPrincipal.avatarUrl,
|
|
291
|
+
return (_jsxs(Box, { display: "inline-flex", alignItems: "center", gap: gap, minWidth: 0, sx: sx, children: [_jsx(PrincipalAvatar, { kind: resolvedPrincipal.kind, avatarUrl: resolvedPrincipal.avatarUrl, avatar: resolvedPrincipal.avatarIcon, alt: resolvedPrincipal.displayName, size: avatarSize, square: square }), _jsx(PrincipalDetailsOverlay, { kind: resolvedPrincipal.kind, uid: resolvedPrincipal.uid, displayName: resolvedPrincipal.displayName, name: resolvedPrincipal.name, description: resolvedPrincipal.description, handle: resolvedPrincipal.handle, accountHandle: resolvedPrincipal.accountHandle, firstName: resolvedPrincipal.firstName, lastName: resolvedPrincipal.lastName, email: resolvedPrincipal.email, origin: resolvedPrincipal.origin, avatarUrl: resolvedPrincipal.avatarUrl, avatar: resolvedPrincipal.avatarIcon, organizationName: teamOrganizationNameResolved, memberCount: teamMemberCount, isPublic: resolvedIsPublic, isAdmin: isAdmin })] }));
|
|
292
292
|
};
|
|
293
293
|
export default Principal;
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import type { JSX } from 'react';
|
|
2
2
|
import { type ComponentType, type SVGProps } from 'react';
|
|
3
|
+
import { type AvatarChoice } from '../avatars/avatarChoice';
|
|
3
4
|
/**
|
|
4
5
|
* Who a principal is: a person, an organization, a team — or a service
|
|
5
6
|
* principal, the one a deployed LOOP application acts in its own name through
|
|
@@ -114,7 +115,29 @@ export declare const PRINCIPAL_BANNERS: readonly [{
|
|
|
114
115
|
readonly Component: ComponentType<any>;
|
|
115
116
|
}];
|
|
116
117
|
export declare function getPrincipalBannerForSeed(seed: string): string;
|
|
117
|
-
|
|
118
|
+
/** The names of the avatar set: the icons an avatar may be. */
|
|
119
|
+
export declare const PRINCIPAL_AVATAR_ICON_NAMES: ReadonlySet<string>;
|
|
120
|
+
/** The avatar a kept value names; throws `AvatarRefused` for anything else. */
|
|
121
|
+
export declare function parsePrincipalAvatar(value: string): AvatarChoice;
|
|
122
|
+
/**
|
|
123
|
+
* The avatar a kept value names, or `undefined` when there is none or it is
|
|
124
|
+
* refused — said once on the console, in its sentence: a picture that cannot
|
|
125
|
+
* be drawn is drawn as no choice, never as a broken page.
|
|
126
|
+
*/
|
|
127
|
+
export declare function principalAvatarOf(value: string | undefined): AvatarChoice | undefined;
|
|
128
|
+
/**
|
|
129
|
+
* The drawing of a chosen avatar — an emoji or an icon of the set, by its
|
|
130
|
+
* kept value — on nothing: whatever holds it gives it its disc
|
|
131
|
+
* (`UserAvatar`, `PrincipalAvatar`, an application's face). `null` for no
|
|
132
|
+
* choice, or a refused one.
|
|
133
|
+
*/
|
|
134
|
+
export declare function ChosenAvatar({ avatar, size, label, }: {
|
|
135
|
+
avatar: string | undefined;
|
|
136
|
+
/** Its edge, in pixels. */
|
|
137
|
+
size: number;
|
|
138
|
+
/** What it is called for a screen reader; empty, it is decoration. */
|
|
139
|
+
label?: string;
|
|
140
|
+
}): JSX.Element | null;
|
|
118
141
|
export declare function PrincipalBannerImage({ banner, height, }: {
|
|
119
142
|
banner?: string;
|
|
120
143
|
height?: number;
|
|
@@ -1,8 +1,11 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
2
2
|
import { Suspense, lazy, useEffect, useState, } from 'react';
|
|
3
|
-
import { Box } from '@datalayer/primer-addons';
|
|
4
|
-
import { Button, Text, Tooltip } from '@primer/react';
|
|
3
|
+
import { Box, useColorPalette } from '@datalayer/primer-addons';
|
|
4
|
+
import { Button, SegmentedControl, Text, Tooltip } from '@primer/react';
|
|
5
5
|
import { Dialog } from '@primer/react/experimental';
|
|
6
|
+
import { AvatarRefused, emojiAvatar, iconAvatar, parseAvatar, } from '../avatars/avatarChoice.js';
|
|
7
|
+
import { FACE_EMOJIS } from '../emoji/faceEmojis.js';
|
|
8
|
+
import { FluentEmoji } from '../emoji/FluentEmoji.js';
|
|
6
9
|
/**
|
|
7
10
|
* An avatar icon, fetched the first time it is drawn.
|
|
8
11
|
*
|
|
@@ -577,8 +580,50 @@ export function getPrincipalBannerForSeed(seed) {
|
|
|
577
580
|
}
|
|
578
581
|
return PRINCIPAL_BANNERS[Math.abs(hash) % PRINCIPAL_BANNERS.length].name;
|
|
579
582
|
}
|
|
580
|
-
|
|
581
|
-
|
|
583
|
+
/** The names of the avatar set: the icons an avatar may be. */
|
|
584
|
+
export const PRINCIPAL_AVATAR_ICON_NAMES = new Set(PRINCIPAL_AVATAR_ICONS.map(option => option.name));
|
|
585
|
+
/** The avatar a kept value names; throws `AvatarRefused` for anything else. */
|
|
586
|
+
export function parsePrincipalAvatar(value) {
|
|
587
|
+
return parseAvatar(value, PRINCIPAL_AVATAR_ICON_NAMES);
|
|
588
|
+
}
|
|
589
|
+
/**
|
|
590
|
+
* The avatar a kept value names, or `undefined` when there is none or it is
|
|
591
|
+
* refused — said once on the console, in its sentence: a picture that cannot
|
|
592
|
+
* be drawn is drawn as no choice, never as a broken page.
|
|
593
|
+
*/
|
|
594
|
+
export function principalAvatarOf(value) {
|
|
595
|
+
if (!value) {
|
|
596
|
+
return undefined;
|
|
597
|
+
}
|
|
598
|
+
try {
|
|
599
|
+
return parsePrincipalAvatar(value);
|
|
600
|
+
}
|
|
601
|
+
catch (error) {
|
|
602
|
+
if (error instanceof AvatarRefused) {
|
|
603
|
+
console.error(`Avatar refused: ${error.message}`);
|
|
604
|
+
return undefined;
|
|
605
|
+
}
|
|
606
|
+
throw error;
|
|
607
|
+
}
|
|
608
|
+
}
|
|
609
|
+
/**
|
|
610
|
+
* The drawing of a chosen avatar — an emoji or an icon of the set, by its
|
|
611
|
+
* kept value — on nothing: whatever holds it gives it its disc
|
|
612
|
+
* (`UserAvatar`, `PrincipalAvatar`, an application's face). `null` for no
|
|
613
|
+
* choice, or a refused one.
|
|
614
|
+
*/
|
|
615
|
+
export function ChosenAvatar({ avatar, size, label = '', }) {
|
|
616
|
+
const choice = principalAvatarOf(avatar);
|
|
617
|
+
if (!choice) {
|
|
618
|
+
return null;
|
|
619
|
+
}
|
|
620
|
+
if (choice.kind === 'emoji') {
|
|
621
|
+
return _jsx(FluentEmoji, { emoji: choice.emoji, size: size, label: label });
|
|
622
|
+
}
|
|
623
|
+
const Icon = PRINCIPAL_AVATAR_ICONS.find(option => option.name === choice.name).Icon;
|
|
624
|
+
// The plain icon, coloured by the theme — never the `colored` variant,
|
|
625
|
+
// whose fixed palette belongs to the emoji it is drawn from.
|
|
626
|
+
return (_jsx(Icon, { size: size, themed: true, colormode: true, "aria-label": label || undefined, "aria-hidden": label ? undefined : true }));
|
|
582
627
|
}
|
|
583
628
|
export function PrincipalBannerImage({ banner, height = 180, }) {
|
|
584
629
|
const Banner = PRINCIPAL_BANNERS.find(option => option.name === banner)?.Component;
|
|
@@ -601,8 +646,26 @@ export function PrincipalBannerImage({ banner, height = 180, }) {
|
|
|
601
646
|
}
|
|
602
647
|
export function PrincipalAvatarPicker({ value, onChange, disabled = false, }) {
|
|
603
648
|
const [open, setOpen] = useState(false);
|
|
604
|
-
const
|
|
605
|
-
|
|
649
|
+
const chosen = principalAvatarOf(value);
|
|
650
|
+
// The colour a chosen avatar is drawn in (`UserAvatar`'s `--datalayer-icon-fg`):
|
|
651
|
+
// the icons are offered as they will look.
|
|
652
|
+
const palette = useColorPalette();
|
|
653
|
+
// The tab the dialog opens on: what is chosen, the icons when nothing is.
|
|
654
|
+
const [tab, setTab] = useState(chosen?.kind === 'emoji' ? 'emoji' : 'icons');
|
|
655
|
+
const choose = (next) => {
|
|
656
|
+
onChange(next);
|
|
657
|
+
setOpen(false);
|
|
658
|
+
};
|
|
659
|
+
const selectedLabel = chosen?.kind === 'emoji'
|
|
660
|
+
? chosen.emoji
|
|
661
|
+
: chosen
|
|
662
|
+
? PRINCIPAL_AVATAR_ICONS.find(option => option.name === chosen.name)
|
|
663
|
+
?.label
|
|
664
|
+
: undefined;
|
|
665
|
+
return (_jsxs(_Fragment, { children: [_jsx(Button, { type: "button", disabled: disabled, onClick: () => {
|
|
666
|
+
setTab(chosen?.kind === 'emoji' ? 'emoji' : 'icons');
|
|
667
|
+
setOpen(true);
|
|
668
|
+
}, leadingVisual: chosen ? () => _jsx(ChosenAvatar, { avatar: value, size: 16 }) : undefined, children: selectedLabel ? `Change Avatar (${selectedLabel})` : 'Choose Avatar' }), open ? (_jsxs(Dialog, { title: "Choose an Avatar", onClose: () => setOpen(false),
|
|
606
669
|
// The widest the dialog names — 640px — which is what it falls
|
|
607
670
|
// back to should the width below ever stop applying.
|
|
608
671
|
width: "xlarge",
|
|
@@ -622,34 +685,42 @@ export function PrincipalAvatarPicker({ value, onChange, disabled = false, }) {
|
|
|
622
685
|
width: 'min(1080px, calc(100vw - 32px))',
|
|
623
686
|
maxWidth: 'none',
|
|
624
687
|
},
|
|
625
|
-
}, children: _jsx(Box, { display: "grid",
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
688
|
+
}, children: [_jsxs(SegmentedControl, { "aria-label": "Avatar kind", sx: { mb: 3 }, onChange: index => setTab(index === 0 ? 'emoji' : 'icons'), children: [_jsx(SegmentedControl.Button, { selected: tab === 'emoji', children: "Emoji" }), _jsx(SegmentedControl.Button, { selected: tab === 'icons', children: "Icons" })] }), tab === 'emoji' ? (_jsx(Box, { display: "grid", gridTemplateColumns: [
|
|
689
|
+
'repeat(6, minmax(0, 1fr))',
|
|
690
|
+
'repeat(12, minmax(0, 1fr))',
|
|
691
|
+
], gap: 2, children: FACE_EMOJIS.map(emoji => {
|
|
692
|
+
const next = emojiAvatar(emoji);
|
|
693
|
+
const pressed = value === next;
|
|
694
|
+
return (_jsx(Box, { as: "button", type: "button", "aria-label": emoji, "aria-pressed": pressed, onClick: () => choose(next), display: "flex", alignItems: "center", justifyContent: "center", height: 72, width: "100%", p: 0, appearance: "none", cursor: "pointer", border: "1px solid", borderRadius: 2, borderColor: pressed ? 'accent.emphasis' : 'border.default', bg: pressed ? 'accent.subtle' : 'canvas.default', hover: { borderColor: 'accent.emphasis' }, children: _jsx(FluentEmoji, { emoji: emoji, size: 44, label: "" }) }, emoji));
|
|
695
|
+
}) })) : null, tab === 'icons' ? (_jsx(Box, { style: { '--datalayer-icon-fg': palette.primary }, display: "grid",
|
|
696
|
+
// Twelve to a line, whatever the dialog is wide: the columns
|
|
697
|
+
// share it evenly and `minmax(0, …)` lets them shrink under
|
|
698
|
+
// their content, which a long name would otherwise widen.
|
|
699
|
+
gridTemplateColumns: [
|
|
700
|
+
'repeat(6, minmax(0, 1fr))',
|
|
701
|
+
'repeat(12, minmax(0, 1fr))',
|
|
702
|
+
], gap: 2, children: PRINCIPAL_AVATAR_ICONS.map(({ name, label, description, Icon }) => (
|
|
703
|
+
// A button drawn as a card rather than a Primer `Button`: the
|
|
704
|
+
// avatar is named under it, as the banners are under theirs.
|
|
705
|
+
// The name under a card is clipped when it is long, and a
|
|
706
|
+
// picture says only so much: the tooltip gives the whole name
|
|
707
|
+
// and what the picture is of.
|
|
708
|
+
_jsx(Tooltip, { text: description ? `${label} — ${description}` : label, direction: "n", children: _jsxs(Box, { as: "button", type: "button", "aria-label": description ? `${label} — ${description}` : label, "aria-pressed": value === iconAvatar(name), onClick: () => choose(iconAvatar(name)), display: "block", width: "100%", p: 0, overflow: "hidden", appearance: "none", color: "fg.default", cursor: "pointer", border: "1px solid", borderRadius: 2, borderColor: value === iconAvatar(name)
|
|
709
|
+
? 'accent.emphasis'
|
|
710
|
+
: 'border.default', bg: value === iconAvatar(name)
|
|
711
|
+
? 'accent.subtle'
|
|
712
|
+
: 'canvas.default', hover: { borderColor: 'accent.emphasis' }, children: [_jsx(Box, { height: 72, display: "flex", alignItems: "center", justifyContent: "center", children: _jsx(Icon, { size: 52, themed: true, colormode: true }) }), _jsx(Text, { sx: {
|
|
713
|
+
display: 'block',
|
|
714
|
+
px: 2,
|
|
715
|
+
py: 1,
|
|
716
|
+
fontSize: 0,
|
|
717
|
+
textAlign: 'center',
|
|
718
|
+
// A name too long for the card is cut rather than
|
|
719
|
+
// stretching the grid it sits in.
|
|
720
|
+
overflow: 'hidden',
|
|
721
|
+
textOverflow: 'ellipsis',
|
|
722
|
+
whiteSpace: 'nowrap',
|
|
723
|
+
}, children: label })] }) }, name))) })) : null] })) : null] }));
|
|
653
724
|
}
|
|
654
725
|
export function PrincipalBannerPicker({ value, onChange, disabled = false, showPreview = true, }) {
|
|
655
726
|
const [open, setOpen] = useState(false);
|
|
@@ -4,14 +4,12 @@ export type PrincipalAvatarKind = PrincipalType;
|
|
|
4
4
|
export type PrincipalAvatarProps = {
|
|
5
5
|
kind: PrincipalAvatarKind;
|
|
6
6
|
avatarUrl?: string;
|
|
7
|
-
avatarIcon?: string;
|
|
8
7
|
/**
|
|
9
|
-
*
|
|
10
|
-
*
|
|
11
|
-
*
|
|
12
|
-
* personal-shaped seat in every roster it appears in today.
|
|
8
|
+
* The chosen avatar, as it is kept: `emoji:…` or
|
|
9
|
+
* `@datalayer/icons-react:…` (`components/avatars/avatarChoice`). An
|
|
10
|
+
* agent's face is its emoji, as `emoji:…`.
|
|
13
11
|
*/
|
|
14
|
-
|
|
12
|
+
avatar?: string;
|
|
15
13
|
alt?: string;
|
|
16
14
|
size?: number;
|
|
17
15
|
square?: boolean;
|
|
@@ -24,5 +22,5 @@ export type PrincipalAvatarProps = {
|
|
|
24
22
|
ring?: boolean;
|
|
25
23
|
className?: string;
|
|
26
24
|
};
|
|
27
|
-
export declare function PrincipalAvatar({ kind, avatarUrl,
|
|
25
|
+
export declare function PrincipalAvatar({ kind, avatarUrl, avatar, alt, size, square, ring, className, }: PrincipalAvatarProps): JSX.Element;
|
|
28
26
|
export default PrincipalAvatar;
|
|
@@ -1,18 +1,14 @@
|
|
|
1
1
|
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
-
import {
|
|
2
|
+
import { EntityAvatar } from '@datalayer/primer-addons';
|
|
3
3
|
import { OrganizationIcon, PeopleIcon } from '@primer/octicons-react';
|
|
4
4
|
import { UserAvatar } from '../avatars/index.js';
|
|
5
|
-
import {
|
|
5
|
+
import { ChosenAvatar, principalAvatarOf, } from './PrincipalAppearance.js';
|
|
6
6
|
function getFallbackIconSize(size) {
|
|
7
7
|
return Math.max(12, Math.round(size * 0.62));
|
|
8
8
|
}
|
|
9
|
-
export function PrincipalAvatar({ kind, avatarUrl,
|
|
10
|
-
const
|
|
11
|
-
|
|
12
|
-
// was asked for — see `UserAvatar`, which draws its ring the same way.
|
|
13
|
-
const ringSx = ring
|
|
14
|
-
? { boxShadow: '0 0 0 1px var(--borderColor-default, currentColor)' }
|
|
15
|
-
: undefined;
|
|
9
|
+
export function PrincipalAvatar({ kind, avatarUrl, avatar, alt, size = 20, square = false, ring = false, className, }) {
|
|
10
|
+
const chosen = principalAvatarOf(avatar);
|
|
11
|
+
const shape = square ? 'rounded' : 'circle';
|
|
16
12
|
/*
|
|
17
13
|
* A person is drawn by `UserAvatar`, whatever they wear.
|
|
18
14
|
*
|
|
@@ -25,17 +21,15 @@ export function PrincipalAvatar({ kind, avatarUrl, avatarIcon, avatarEmoji, alt,
|
|
|
25
21
|
// A service principal — an application's — is drawn as a person is: its
|
|
26
22
|
// chosen avatar, or its emoji, on the same disc (LOOP I-07).
|
|
27
23
|
if (kind === 'personal' || kind === 'service') {
|
|
28
|
-
return (_jsx(UserAvatar, { avatarUrl: avatarUrl,
|
|
24
|
+
return (_jsx(UserAvatar, { avatarUrl: avatarUrl, avatar: avatar, size: size, square: square, iconSize: getFallbackIconSize(size), ring: ring, className: className }));
|
|
29
25
|
}
|
|
30
|
-
if (
|
|
31
|
-
return (
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
26
|
+
if (chosen) {
|
|
27
|
+
return (
|
|
28
|
+
// The disc of `UserAvatar`, for the same reason: the shape is what says
|
|
29
|
+
// "avatar", and an icon drawn on nothing shows none of it.
|
|
30
|
+
_jsx(EntityAvatar, { className: className, size: size, shape: shape, ring: ring, alt: alt || `${kind} avatar`, children: _jsx(ChosenAvatar, { avatar: avatar, size: getFallbackIconSize(size) }) }));
|
|
35
31
|
}
|
|
36
|
-
const iconSize = getFallbackIconSize(size);
|
|
37
|
-
const borderRadius = square ? 2 : '50%';
|
|
38
32
|
const Icon = kind === 'team' ? PeopleIcon : OrganizationIcon;
|
|
39
|
-
return (_jsx(
|
|
33
|
+
return (_jsx(EntityAvatar, { className: className, size: size, shape: shape, ring: ring, ground: "canvas", alt: alt || (kind === 'team' ? 'Team' : 'Organization'), children: _jsx(Icon, { size: getFallbackIconSize(size) }) }));
|
|
40
34
|
}
|
|
41
35
|
export default PrincipalAvatar;
|
|
@@ -14,14 +14,11 @@ export type PrincipalDetailsOverlayProps = {
|
|
|
14
14
|
email?: string;
|
|
15
15
|
origin?: string;
|
|
16
16
|
avatarUrl?: string;
|
|
17
|
-
avatarIcon?: string;
|
|
18
17
|
/**
|
|
19
|
-
*
|
|
20
|
-
*
|
|
21
|
-
* `avatarIcon` since the emoji is its real identity here, not a
|
|
22
|
-
* placeholder standing in for one.
|
|
18
|
+
* The chosen avatar, as it is kept: `emoji:…` (an agent's face is its
|
|
19
|
+
* emoji) or `@datalayer/icons-react:…`.
|
|
23
20
|
*/
|
|
24
|
-
|
|
21
|
+
avatar?: string;
|
|
25
22
|
/** Team-specific: parent organization display name. */
|
|
26
23
|
organizationName?: string;
|
|
27
24
|
/** Team-specific: number of members. */
|
|
@@ -59,7 +56,7 @@ export declare function buildPrincipalProfilePath({ kind, uid, handle, accountHa
|
|
|
59
56
|
* anchored on an avatar ({@link PrincipalHoverCard}) both render this, so
|
|
60
57
|
* the two never drift.
|
|
61
58
|
*/
|
|
62
|
-
export declare function PrincipalDetailsCard({ kind, uid, displayName, name, description, handle, accountHandle, firstName, lastName, email, origin, avatarUrl,
|
|
59
|
+
export declare function PrincipalDetailsCard({ kind, uid, displayName, name, description, handle, accountHandle, firstName, lastName, email, origin, avatarUrl, avatar, organizationName, memberCount, isPublic, isAdmin, onNavigate, }: PrincipalDetailsOverlayProps): JSX.Element;
|
|
63
60
|
/**
|
|
64
61
|
* A principal's details, shown from a click on their name.
|
|
65
62
|
*
|
|
@@ -89,7 +89,7 @@ export function buildPrincipalProfilePath({ kind, uid, handle, accountHandle, is
|
|
|
89
89
|
* anchored on an avatar ({@link PrincipalHoverCard}) both render this, so
|
|
90
90
|
* the two never drift.
|
|
91
91
|
*/
|
|
92
|
-
export function PrincipalDetailsCard({ kind, uid, displayName, name, description, handle, accountHandle, firstName, lastName, email, origin, avatarUrl,
|
|
92
|
+
export function PrincipalDetailsCard({ kind, uid, displayName, name, description, handle, accountHandle, firstName, lastName, email, origin, avatarUrl, avatar, organizationName, memberCount, isPublic, isAdmin = false, onNavigate, }) {
|
|
93
93
|
const navigate = useNavigate();
|
|
94
94
|
// Where a profile or organization link goes: the router of this subtree,
|
|
95
95
|
// unless the caller knows of one that can actually serve it — see
|
|
@@ -140,7 +140,7 @@ export function PrincipalDetailsCard({ kind, uid, displayName, name, description
|
|
|
140
140
|
const organizationPath = teamOrganizationHandle
|
|
141
141
|
? `/${teamOrganizationHandle.replace(/^@+/, '')}`
|
|
142
142
|
: '';
|
|
143
|
-
return (_jsxs(Box, { display: "grid", gap: 3, p: 4, minWidth: 420, children: [_jsxs(Box, { display: "flex", alignItems: "center", gap: 2, children: [_jsx(PrincipalAvatar, { kind: kind, avatarUrl: avatarUrl,
|
|
143
|
+
return (_jsxs(Box, { display: "grid", gap: 3, p: 4, minWidth: 420, children: [_jsxs(Box, { display: "flex", alignItems: "center", gap: 2, children: [_jsx(PrincipalAvatar, { kind: kind, avatarUrl: avatarUrl, avatar: avatar, alt: normalizedDisplayName, size: 40,
|
|
144
144
|
// The card sets the avatar on its own ground, the same colour
|
|
145
145
|
// the avatar itself is on: without an edge of its own it has
|
|
146
146
|
// no visible shape at all. Round, and ringed.
|
|
@@ -226,7 +226,7 @@ export function PrincipalSwitcherMenu({ maxLabelChars = 48, fullWidth = true, sh
|
|
|
226
226
|
if (personalUid && personalHandle) {
|
|
227
227
|
selectUser(personalUid, personalHandle);
|
|
228
228
|
}
|
|
229
|
-
}, children: [_jsx(ActionList.LeadingVisual, { children: _jsx(UserAvatar, { avatarUrl: user?.avatarUrl,
|
|
229
|
+
}, children: [_jsx(ActionList.LeadingVisual, { children: _jsx(UserAvatar, { avatarUrl: user?.avatarUrl, avatar: user?.avatarIcon, size: 16, square: false, ring: true }) }), _jsxs(Box, { as: "span", display: "block", minWidth: 0, overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap", children: [String(user?.friendlyName ||
|
|
230
230
|
user?.displayName ||
|
|
231
231
|
personalHandle ||
|
|
232
232
|
'Me').trim(), _jsxs(Box, { as: "span", color: "fg.muted", children: [' ', "\u00B7 ", _jsx(DisplayHandle, { handle: personalHandle || 'me' })] })] }), isPlatformAdmin ? (_jsx(ActionList.TrailingVisual, { children: _jsx(AdminLabel, {}) })) : null] })] }), _jsxs(ActionList.Group, { children: [_jsx(ActionList.GroupHeading, { children: "Organizations" }), organizations.length === 0 ? (_jsx(ActionList.Item, { disabled: true, children: "No organizations" })) : (organizations.map((organization) => {
|
|
@@ -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
|
+
}
|
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';
|
|
@@ -1270,7 +1271,7 @@ export const useCache = ({ loginRoute = '/login' } = {}) => {
|
|
|
1270
1271
|
tags: Array.isArray(raw_evalset.tags_ss) ? raw_evalset.tags_ss : [],
|
|
1271
1272
|
/*
|
|
1272
1273
|
* What the runs of a benchmark say about it, projected onto its
|
|
1273
|
-
* library card whenever a run moves (
|
|
1274
|
+
* library card whenever a run moves (B2-10 and B1-09).
|
|
1274
1275
|
*
|
|
1275
1276
|
* These were dropped here, so a card in the Library or on the home
|
|
1276
1277
|
* page could show a name and a description and nothing that would
|
|
@@ -1296,7 +1297,7 @@ export const useCache = ({ loginRoute = '/login' } = {}) => {
|
|
|
1296
1297
|
};
|
|
1297
1298
|
};
|
|
1298
1299
|
/**
|
|
1299
|
-
* A published environment version as a library artifact (
|
|
1300
|
+
* A published environment version as a library artifact (E2-16).
|
|
1300
1301
|
*
|
|
1301
1302
|
* Keyed on the version uid, so one published version is one card, and read
|
|
1302
1303
|
* from the publication's immutable snapshot: its name, title, README (the
|
|
@@ -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;
|
|
@@ -1,6 +1,15 @@
|
|
|
1
1
|
import { JSONObject } from '@lumino/coreutils';
|
|
2
2
|
import { IIAMProviderName } from './IAMProvidersSpecs';
|
|
3
|
+
/**
|
|
4
|
+
* One `iam_providers` child of the user IAM returns (whoami, login): its
|
|
5
|
+
* Solr fields `iam_provider_name_s`, `linked_account_s`,
|
|
6
|
+
* `linked_account_url_s`, `linked_account_id_s`.
|
|
7
|
+
*/
|
|
3
8
|
export declare function asIAMProviderLinked(iamProvider: any): IIAMProviderLinked;
|
|
9
|
+
/** Whether the user has linked this provider in IAM. */
|
|
10
|
+
export declare function hasLinkedIAMProvider(user: {
|
|
11
|
+
iamProviders?: Array<IIAMProviderLinked>;
|
|
12
|
+
} | null | undefined, name: IIAMProviderName): boolean;
|
|
4
13
|
export type IIAMProviderLinked = {
|
|
5
14
|
iamProviderName: IIAMProviderName;
|
|
6
15
|
linkedAccount: JSONObject;
|