@datalayer/core 1.1.50 → 1.1.57
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +19 -42
- package/lib/client/auth/AuthenticationManager.js +6 -4
- package/lib/client/auth/strategies.js +2 -0
- package/lib/components/animation/AnimatedText.d.ts +98 -0
- package/lib/components/animation/AnimatedText.js +220 -0
- package/lib/components/animation/index.d.ts +1 -0
- package/lib/components/animation/index.js +5 -0
- package/lib/components/auth/{LoginToken.d.ts → SigInAPIKey.d.ts} +3 -3
- package/lib/components/auth/{LoginToken.js → SigInAPIKey.js} +5 -5
- package/lib/components/auth/{Login.d.ts → SignIn.d.ts} +3 -3
- package/lib/components/auth/{Login.js → SignIn.js} +12 -12
- package/lib/components/auth/{Login.stories.d.ts → SignIn.stories.d.ts} +2 -2
- package/lib/components/auth/{Login.stories.js → SignIn.stories.js} +4 -4
- package/lib/components/auth/index.d.ts +2 -2
- package/lib/components/auth/index.js +2 -2
- package/lib/components/avatars/UserAvatar.d.ts +3 -1
- package/lib/components/avatars/UserAvatar.js +16 -3
- package/lib/components/avatars/UserProfileAvatar.js +2 -6
- package/lib/components/collaboration/LiveEditorCollaborators.d.ts +31 -0
- package/lib/components/collaboration/LiveEditorCollaborators.js +107 -0
- package/lib/components/collaboration/index.d.ts +1 -0
- package/lib/components/collaboration/index.js +9 -0
- package/lib/components/display/DatalayerBox.d.ts +3 -1
- package/lib/components/display/DatalayerBox.js +7 -7
- package/lib/components/display/JupyterDialog.d.ts +2 -0
- package/lib/components/display/JupyterDialog.js +10 -4
- package/lib/components/iam/ExternalTokenSilentLogin.js +2 -2
- package/lib/components/index.d.ts +2 -0
- package/lib/components/index.js +2 -0
- package/lib/components/labels/StatusLabels.d.ts +42 -0
- package/lib/components/labels/StatusLabels.js +61 -0
- package/lib/components/labels/index.d.ts +1 -0
- package/lib/components/labels/index.js +1 -0
- package/lib/components/principal/Principal.d.ts +2 -0
- package/lib/components/principal/Principal.js +11 -1
- package/lib/components/principal/PrincipalAppearance.d.ts +136 -0
- package/lib/components/principal/PrincipalAppearance.js +203 -0
- package/lib/components/principal/PrincipalAvatar.d.ts +5 -2
- package/lib/components/principal/PrincipalAvatar.js +16 -3
- package/lib/components/principal/PrincipalBadge.js +7 -0
- package/lib/components/principal/PrincipalDetailsOverlay.d.ts +2 -1
- package/lib/components/principal/PrincipalDetailsOverlay.js +2 -2
- package/lib/components/principal/index.d.ts +1 -0
- package/lib/components/principal/index.js +1 -0
- package/lib/components/progress/ConsumptionBar.d.ts +9 -0
- package/lib/components/progress/ConsumptionBar.js +10 -2
- package/lib/components/sharing/ShareAccessComponent.js +6 -1
- package/lib/components/students/StudentItemStatus.d.ts +33 -0
- package/lib/components/students/StudentItemStatus.js +68 -0
- package/lib/components/students/index.d.ts +1 -0
- package/lib/components/students/index.js +1 -0
- package/lib/config/Configuration.d.ts +17 -8
- package/lib/config/Configuration.js +12 -5
- package/lib/hooks/useCache.d.ts +2 -0
- package/lib/hooks/useCache.js +35 -11
- package/lib/hooks/usePrincipalCacheStore.d.ts +2 -0
- package/lib/hooks/usePrincipalCacheStore.js +2 -0
- package/lib/models/IAM.d.ts +10 -0
- package/lib/models/Organization.d.ts +2 -0
- package/lib/models/Organization.js +2 -0
- package/lib/models/Profile.d.ts +2 -0
- package/lib/models/Team.d.ts +2 -0
- package/lib/models/Team.js +2 -0
- package/lib/models/User.d.ts +4 -0
- package/lib/models/User.js +4 -0
- package/lib/models/UserDTO.d.ts +6 -0
- package/lib/models/UserDTO.js +8 -0
- package/lib/state/substates/CoreState.js +3 -2
- package/lib/state/substates/IAMState.js +6 -0
- package/lib/state/substates/LayoutState.js +62 -7
- package/lib/state/substates/OrganizationState.d.ts +6 -0
- package/lib/state/substates/OrganizationState.js +5 -0
- package/lib/state/substates/ProfileState.d.ts +34 -0
- package/lib/state/substates/ProfileState.js +68 -0
- package/lib/state/substates/TeamState.d.ts +6 -0
- package/lib/state/substates/TeamState.js +3 -0
- package/lib/state/substates/index.d.ts +1 -0
- package/lib/state/substates/index.js +1 -0
- package/lib/views/iam/SignInSimple.d.ts +1 -1
- package/lib/views/iam/SignInSimple.js +3 -4
- package/package.json +2 -2
|
@@ -9,6 +9,11 @@ export const organizationStore = createStore((set, get) => ({
|
|
|
9
9
|
updateOrganizations: (organizations) => set((state) => ({
|
|
10
10
|
organizations,
|
|
11
11
|
})),
|
|
12
|
+
updateOrganization: organization => set((state) => ({
|
|
13
|
+
organizations: state.organizations.map(known => known.id === organization.id
|
|
14
|
+
? { ...known, ...organization }
|
|
15
|
+
: known),
|
|
16
|
+
})),
|
|
12
17
|
}));
|
|
13
18
|
export function useOrganizationStore(selector) {
|
|
14
19
|
return useStore(organizationStore, selector);
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import type { IUser } from '../../models';
|
|
2
|
+
/** The profile of the authenticated user, as the surfaces show it. */
|
|
3
|
+
export type IProfile = {
|
|
4
|
+
id?: string;
|
|
5
|
+
uid?: string;
|
|
6
|
+
handle?: string;
|
|
7
|
+
email?: string;
|
|
8
|
+
firstName?: string;
|
|
9
|
+
lastName?: string;
|
|
10
|
+
displayName?: string;
|
|
11
|
+
initials?: string;
|
|
12
|
+
avatarUrl?: string;
|
|
13
|
+
avatarIcon?: string;
|
|
14
|
+
banner?: string;
|
|
15
|
+
origin?: string;
|
|
16
|
+
roles?: string[];
|
|
17
|
+
};
|
|
18
|
+
export type ProfileState = {
|
|
19
|
+
profile?: IProfile;
|
|
20
|
+
/** Replace the profile wholesale. */
|
|
21
|
+
setProfile: (profile?: IProfile) => void;
|
|
22
|
+
/** Merge what a flow just learned into the profile. */
|
|
23
|
+
updateProfile: (partial: Partial<IProfile>) => void;
|
|
24
|
+
/** The IAM user as the profile — login and refresh feed through this. */
|
|
25
|
+
setProfileFromUser: (user?: IUser) => void;
|
|
26
|
+
/** Logout. */
|
|
27
|
+
clearProfile: () => void;
|
|
28
|
+
};
|
|
29
|
+
export declare const profileStore: import("zustand").StoreApi<ProfileState>;
|
|
30
|
+
export declare function useProfileStore(): ProfileState;
|
|
31
|
+
export declare function useProfileStore<T>(selector: (state: ProfileState) => T): T;
|
|
32
|
+
/** The profile, for surfaces that show it. */
|
|
33
|
+
export declare const useProfile: () => IProfile | undefined;
|
|
34
|
+
export default useProfileStore;
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright (c) 2023-2026 Datalayer, Inc.
|
|
3
|
+
* Distributed under the terms of the Modified BSD License.
|
|
4
|
+
*/
|
|
5
|
+
/**
|
|
6
|
+
* ProfileState — the one place the authenticated user's profile lives.
|
|
7
|
+
*
|
|
8
|
+
* The avatar and the banner used to be read from whatever carried them at
|
|
9
|
+
* each call site — the IAM user, a whoami response, a form snapshot — and
|
|
10
|
+
* the surfaces drifted: a banner updated on the profile page did not reach
|
|
11
|
+
* the user menu until the page reloaded. Every surface showing the profile
|
|
12
|
+
* (user menu, sidebars, profile views) reads this store instead, and every
|
|
13
|
+
* flow that learns something about the profile (login, `GET /me`, a profile
|
|
14
|
+
* update) writes it here.
|
|
15
|
+
*
|
|
16
|
+
* The store is fed automatically by {@link IAMState} on login, profile
|
|
17
|
+
* update and logout, and by the `useMe` query with the full profile — the
|
|
18
|
+
* consumers only ever read.
|
|
19
|
+
*
|
|
20
|
+
* @module state/substates/ProfileState
|
|
21
|
+
*/
|
|
22
|
+
import { useStore } from 'zustand';
|
|
23
|
+
import { createStore } from 'zustand/vanilla';
|
|
24
|
+
const userToProfile = (user) => user
|
|
25
|
+
? {
|
|
26
|
+
id: user.id,
|
|
27
|
+
uid: user.uid,
|
|
28
|
+
handle: user.handle,
|
|
29
|
+
email: user.email,
|
|
30
|
+
firstName: user.firstName,
|
|
31
|
+
lastName: user.lastName,
|
|
32
|
+
displayName: user.displayName,
|
|
33
|
+
initials: user.initials,
|
|
34
|
+
avatarUrl: user.avatarUrl,
|
|
35
|
+
avatarIcon: user.avatarIcon,
|
|
36
|
+
banner: user.banner,
|
|
37
|
+
origin: user.origin,
|
|
38
|
+
roles: user.roles,
|
|
39
|
+
}
|
|
40
|
+
: undefined;
|
|
41
|
+
export const profileStore = createStore(set => ({
|
|
42
|
+
profile: undefined,
|
|
43
|
+
setProfile: profile => set({ profile }),
|
|
44
|
+
updateProfile: partial => set(state => ({ profile: { ...state.profile, ...partial } })),
|
|
45
|
+
setProfileFromUser: user => set(state => {
|
|
46
|
+
const profile = userToProfile(user);
|
|
47
|
+
if (!profile) {
|
|
48
|
+
return state;
|
|
49
|
+
}
|
|
50
|
+
// A login refresh may know less than a profile update that already
|
|
51
|
+
// landed (the anonymous whoami has no banner): merge, newest wins,
|
|
52
|
+
// but never erase a field with undefined.
|
|
53
|
+
const merged = { ...state.profile };
|
|
54
|
+
for (const [key, value] of Object.entries(profile)) {
|
|
55
|
+
if (value !== undefined) {
|
|
56
|
+
merged[key] = value;
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
return { profile: merged };
|
|
60
|
+
}),
|
|
61
|
+
clearProfile: () => set({ profile: undefined }),
|
|
62
|
+
}));
|
|
63
|
+
export function useProfileStore(selector) {
|
|
64
|
+
return useStore(profileStore, selector);
|
|
65
|
+
}
|
|
66
|
+
/** The profile, for surfaces that show it. */
|
|
67
|
+
export const useProfile = () => useProfileStore(state => state.profile);
|
|
68
|
+
export default useProfileStore;
|
|
@@ -4,6 +4,12 @@ export type ITeamState = {
|
|
|
4
4
|
};
|
|
5
5
|
export type TeamState = ITeamState & {
|
|
6
6
|
update: (teams: IBaseTeam[]) => void;
|
|
7
|
+
/**
|
|
8
|
+
* Merge what just changed into the team of the list — the way a settings
|
|
9
|
+
* save keeps every surface reading this store current (avatar, banner,
|
|
10
|
+
* name…) without refetching the list.
|
|
11
|
+
*/
|
|
12
|
+
updateTeam: (team: Partial<IBaseTeam> & Pick<IBaseTeam, 'id'>) => void;
|
|
7
13
|
};
|
|
8
14
|
export declare const teamStore: import("zustand").StoreApi<TeamState>;
|
|
9
15
|
export declare function useTeamStore(): TeamState;
|
|
@@ -10,6 +10,9 @@ export const teamStore = createStore((set, get) => ({
|
|
|
10
10
|
update: (teams) => set((state) => ({
|
|
11
11
|
teams,
|
|
12
12
|
})),
|
|
13
|
+
updateTeam: team => set((state) => ({
|
|
14
|
+
teams: state.teams.map(known => known.id === team.id ? { ...known, ...team } : known),
|
|
15
|
+
})),
|
|
13
16
|
}));
|
|
14
17
|
export function useTeamStore(selector) {
|
|
15
18
|
return useStore(teamStore, selector);
|
|
@@ -6,6 +6,7 @@ export * from './CoreState.js';
|
|
|
6
6
|
export * from './DatasourceState.js';
|
|
7
7
|
export * from './IAMState.js';
|
|
8
8
|
export * from './LayoutState.js';
|
|
9
|
+
export * from './ProfileState.js';
|
|
9
10
|
export * from './OrganizationState.js';
|
|
10
11
|
export * from './SurveysState.js';
|
|
11
12
|
export * from './TeamState.js';
|
|
@@ -16,7 +16,7 @@ export interface SignInSimpleProps {
|
|
|
16
16
|
onSignIn?: (token: string, handle: string) => void;
|
|
17
17
|
/**
|
|
18
18
|
* Called when the user authenticates with an API key.
|
|
19
|
-
* If not provided the "Sign
|
|
19
|
+
* If not provided the "Sign in with an API Key" button is hidden.
|
|
20
20
|
*/
|
|
21
21
|
onApiKeySignIn?: (apiKey: string) => void;
|
|
22
22
|
/**
|
|
@@ -103,8 +103,7 @@ const SignInInputGlobalStyle = createGlobalStyle `
|
|
|
103
103
|
// ── Component ────────────────────────────────────────────────────────
|
|
104
104
|
export const SignInSimple = ({ onSignIn, onApiKeySignIn, loginUrl: loginUrlProp, name, title = 'Datalayer OTEL', description = 'Sign in to access the observability dashboard.', icon, leadingIcon = _jsx(TelescopeIcon, { size: 24 }), github = false, google = false, linkedin = false, apiKey = false, signUp = true, socialSignInNavigationTarget, asDoc = false, hideHero = false, calloutTitle, calloutDescription, passwordToggleLabel = 'Sign in with a password', signUpTitle = "Don't have an account?", signUpDescription = 'Create a free Datalayer account with your email address.', signUpLabel = 'Sign up with email', signUpHref = 'https://datalayer.ai/signup', forgotPasswordHref = '/password', forgotPasswordLabel = 'Forgot password?', showForgotPassword = true, socialButtonMarginTop = 3, actionButtonMaxWidth = 320, }) => {
|
|
105
105
|
const compactDocMode = asDoc && !hideHero;
|
|
106
|
-
const headingText = name ??
|
|
107
|
-
(asDoc && title === 'Datalayer OTEL' ? 'Datalayer Sign In' : title);
|
|
106
|
+
const headingText = name ?? (asDoc && title === 'Datalayer OTEL' ? 'Datalayer Sign In' : title);
|
|
108
107
|
const headingIcon = icon ?? (asDoc ? _jsx(SignInIcon, { size: 24 }) : leadingIcon);
|
|
109
108
|
const loginUrl = useMemo(() => {
|
|
110
109
|
if (loginUrlProp)
|
|
@@ -361,7 +360,7 @@ export const SignInSimple = ({ onSignIn, onApiKeySignIn, loginUrl: loginUrlProp,
|
|
|
361
360
|
alignItems: 'center',
|
|
362
361
|
justifyContent: 'space-between',
|
|
363
362
|
mt: 3,
|
|
364
|
-
}, children: [_jsx(Button, { variant: "primary", disabled: loading || asDoc || !handle || !password, onClick: submit, children: loading ? 'Signing in…' : 'Sign
|
|
363
|
+
}, children: [_jsx(Button, { variant: "primary", disabled: loading || asDoc || !handle || !password, onClick: submit, children: loading ? 'Signing in…' : 'Sign In' }), showForgotPassword && (_jsx(Link, { as: "button", sx: {
|
|
365
364
|
fontSize: 1,
|
|
366
365
|
cursor: asDoc ? 'not-allowed' : 'pointer',
|
|
367
366
|
background: 'none',
|
|
@@ -383,7 +382,7 @@ export const SignInSimple = ({ onSignIn, onApiKeySignIn, loginUrl: loginUrlProp,
|
|
|
383
382
|
alignItems: 'center',
|
|
384
383
|
gap: 2,
|
|
385
384
|
my: 3,
|
|
386
|
-
}, children: [_jsx(Box, { sx: { flex: 1, height: '1px', bg: 'border.default' } }), _jsx(Text, { sx: { fontSize: 0, color: 'fg.muted' }, children: "or" }), _jsx(Box, { sx: { flex: 1, height: '1px', bg: 'border.default' } })] }), _jsx(Button, { block: true, leadingVisual: KeyIcon, disabled: asDoc || loading || socialLoading, onClick: () => setShowApiKeyDialog(true), sx: { maxWidth: actionButtonMaxWidth, mx: 'auto' }, children: "Sign
|
|
385
|
+
}, children: [_jsx(Box, { sx: { flex: 1, height: '1px', bg: 'border.default' } }), _jsx(Text, { sx: { fontSize: 0, color: 'fg.muted' }, children: "or" }), _jsx(Box, { sx: { flex: 1, height: '1px', bg: 'border.default' } })] }), _jsx(Button, { block: true, leadingVisual: KeyIcon, disabled: asDoc || loading || socialLoading, onClick: () => setShowApiKeyDialog(true), sx: { maxWidth: actionButtonMaxWidth, mx: 'auto' }, children: "Sign in with an API Key" }), showApiKeyDialog && (_jsx(Box, { role: "dialog", "aria-modal": "true", "aria-labelledby": "signin-api-key-title", onKeyDown: event => {
|
|
387
386
|
if (event.key === 'Escape') {
|
|
388
387
|
closeApiKeyDialog();
|
|
389
388
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@datalayer/core",
|
|
3
|
-
"version": "1.1.
|
|
3
|
+
"version": "1.1.57",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"workspaces": [
|
|
6
6
|
".",
|
|
@@ -90,7 +90,7 @@
|
|
|
90
90
|
"watch:lib:src": "tsc -b -w",
|
|
91
91
|
"type-check:watch": "tsc -b -w --noEmit",
|
|
92
92
|
"examples": "run-p jupyter:start examples:vite",
|
|
93
|
-
"examples:vite": "
|
|
93
|
+
"examples:vite": "VITE_DATALAYER_IAM_URL=http://localhost:8888 vite --config vite.examples.config.ts",
|
|
94
94
|
"examples:nextjs": "npm run dev --workspace=nextjj-example",
|
|
95
95
|
"jupyter:start": "./dev/sh/start-jupyter-server.sh",
|
|
96
96
|
"prepare": "husky || true",
|