@datalayer/core 1.0.23 → 1.0.25
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 +30 -7
- package/lib/api/constants.d.ts +3 -0
- package/lib/api/constants.js +3 -0
- package/lib/api/index.d.ts +1 -0
- package/lib/api/index.js +1 -0
- package/lib/api/runtimes/checkpoints.d.ts +4 -4
- package/lib/api/runtimes/runtimes.d.ts +3 -3
- package/lib/api/scheduler/index.d.ts +6 -0
- package/lib/api/scheduler/index.js +10 -0
- package/lib/api/scheduler/schedules.d.ts +85 -0
- package/lib/api/scheduler/schedules.js +78 -0
- package/lib/components/checkout/StripeCheckout.js +48 -2
- package/lib/components/display/LiveRelativeTime.d.ts +1 -10
- package/lib/components/display/LiveRelativeTime.js +3 -18
- package/lib/components/index.d.ts +3 -0
- package/lib/components/index.js +3 -0
- package/lib/components/runtimes/RuntimePickerBase.js +18 -16
- package/lib/components/runtimes/RuntimePickerCell.js +1 -1
- package/lib/components/scheduler/ScheduleMenu.d.ts +54 -0
- package/lib/components/scheduler/ScheduleMenu.js +154 -0
- package/lib/components/scheduler/index.d.ts +1 -0
- package/lib/{views/iam-tokens → components/scheduler}/index.js +1 -3
- package/lib/components/time/LiveRelativeTime.d.ts +14 -0
- package/lib/components/time/LiveRelativeTime.js +39 -0
- package/lib/components/time/index.d.ts +1 -0
- package/lib/components/time/index.js +5 -0
- package/lib/components/timeline/Timeline.d.ts +20 -0
- package/lib/components/timeline/Timeline.js +90 -0
- package/lib/components/timeline/index.d.ts +1 -0
- package/lib/components/timeline/index.js +5 -0
- package/lib/hooks/useCache.d.ts +31 -1
- package/lib/hooks/useCache.js +221 -17
- package/lib/hooks/useProjectStore.d.ts +1 -1
- package/lib/hooks/useProjects.d.ts +2 -2
- package/lib/models/IAMToken.d.ts +1 -1
- package/lib/models/Page.d.ts +3 -0
- package/lib/models/ProjectDTO.d.ts +1 -1
- package/lib/models/ProjectDTO.js +1 -1
- package/lib/state/substates/CoreState.js +2 -2
- package/lib/utils/Date.d.ts +7 -0
- package/lib/utils/Date.js +43 -10
- package/lib/utils/Name.d.ts +1 -0
- package/lib/utils/Name.js +8 -0
- package/lib/utils/Snapshot.js +2 -2
- package/lib/utils/index.d.ts +1 -0
- package/lib/utils/index.js +1 -0
- package/lib/views/api-keys/APIKeyEdit.d.ts +8 -0
- package/lib/views/{iam-tokens/IAMTokenEdit.js → api-keys/APIKeyEdit.js} +31 -31
- package/lib/views/api-keys/APIKeyNew.d.ts +8 -0
- package/lib/views/api-keys/APIKeyNew.js +143 -0
- package/lib/views/api-keys/APIKeys.d.ts +12 -0
- package/lib/views/api-keys/APIKeys.js +119 -0
- package/lib/views/api-keys/APIKeysStandalone.d.ts +2 -0
- package/lib/views/api-keys/APIKeysStandalone.js +117 -0
- package/lib/views/api-keys/index.d.ts +3 -0
- package/lib/views/api-keys/index.js +7 -0
- package/package.json +1 -1
- package/lib/views/iam-tokens/IAMTokenEdit.d.ts +0 -6
- package/lib/views/iam-tokens/IAMTokenNew.d.ts +0 -8
- package/lib/views/iam-tokens/IAMTokenNew.js +0 -118
- package/lib/views/iam-tokens/IAMTokens.d.ts +0 -12
- package/lib/views/iam-tokens/IAMTokens.js +0 -87
- package/lib/views/iam-tokens/Tokens.d.ts +0 -2
- package/lib/views/iam-tokens/Tokens.js +0 -85
- package/lib/views/iam-tokens/index.d.ts +0 -3
- /package/lib/utils/{logger.d.ts → Logger.d.ts} +0 -0
- /package/lib/utils/{logger.js → Logger.js} +0 -0
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
2
|
+
/*
|
|
3
|
+
* Copyright (c) 2023-2025 Datalayer, Inc.
|
|
4
|
+
* Distributed under the terms of the Modified BSD License.
|
|
5
|
+
*/
|
|
6
|
+
import { useEffect, useMemo, useState } from 'react';
|
|
7
|
+
import { ActionList, ActionMenu, Box, Button, Dialog, FormControl, IconButton, Spinner, Text, TextInput, } from '@primer/react';
|
|
8
|
+
import { ClockIcon, TrashIcon } from '@primer/octicons-react';
|
|
9
|
+
import { disableSchedule, updateSchedule, upsertSchedule, } from '../../api/scheduler/schedules.js';
|
|
10
|
+
import { DEFAULT_SERVICE_URLS } from '../../api/constants.js';
|
|
11
|
+
const SCHEDULE_PRESETS = [
|
|
12
|
+
{ id: 'every-minute', label: 'Every minute', cron: '* * * * *' },
|
|
13
|
+
{ id: 'hourly', label: 'Every hour', cron: '0 * * * *' },
|
|
14
|
+
{ id: 'daily', label: 'Every day', cron: '0 0 * * *' },
|
|
15
|
+
];
|
|
16
|
+
const DEFAULT_CRON_EXPRESSION = '* * * * *';
|
|
17
|
+
const presetFromCron = (cronExpression) => {
|
|
18
|
+
const normalized = cronExpression.trim();
|
|
19
|
+
const preset = SCHEDULE_PRESETS.find(item => item.cron === normalized);
|
|
20
|
+
return preset ? preset.id : 'custom';
|
|
21
|
+
};
|
|
22
|
+
/**
|
|
23
|
+
* Self-contained schedule menu that lets a user pick a cron schedule for a
|
|
24
|
+
* notebook and persists it to the scheduler service.
|
|
25
|
+
*
|
|
26
|
+
* The component owns its loading state and renders a spinner in place of the
|
|
27
|
+
* anchor icon while a save request is in flight. The scheduler service URL is
|
|
28
|
+
* configurable through the `baseUrl` prop.
|
|
29
|
+
*/
|
|
30
|
+
export const ScheduleMenu = ({ notebookUid, scheduleUid, token, baseUrl = DEFAULT_SERVICE_URLS.SCHEDULER, enabled, icon = ClockIcon, iconColor, ariaLabel = 'Schedule execution', initialPreset = 'every-minute', initialCronExpression, onSaved, onDeleted, onError, }) => {
|
|
31
|
+
const providedInitialCron = (initialCronExpression || '').trim();
|
|
32
|
+
const hasProvidedInitialCron = providedInitialCron.length > 0;
|
|
33
|
+
const initialCron = hasProvidedInitialCron
|
|
34
|
+
? providedInitialCron
|
|
35
|
+
: DEFAULT_CRON_EXPRESSION;
|
|
36
|
+
const [cronExpression, setCronExpression] = useState(initialCron);
|
|
37
|
+
const [hasExplicitCron, setHasExplicitCron] = useState(hasProvidedInitialCron);
|
|
38
|
+
const [isSaving, setIsSaving] = useState(false);
|
|
39
|
+
const [isDeleting, setIsDeleting] = useState(false);
|
|
40
|
+
const [isDeleteDialogOpen, setIsDeleteDialogOpen] = useState(false);
|
|
41
|
+
const [deleteConfirmUid, setDeleteConfirmUid] = useState('');
|
|
42
|
+
useEffect(() => {
|
|
43
|
+
const nextProvidedCron = (initialCronExpression || '').trim();
|
|
44
|
+
const nextHasExplicitCron = nextProvidedCron.length > 0;
|
|
45
|
+
setHasExplicitCron(nextHasExplicitCron);
|
|
46
|
+
setCronExpression(nextHasExplicitCron ? nextProvidedCron : DEFAULT_CRON_EXPRESSION);
|
|
47
|
+
}, [initialCronExpression, scheduleUid, notebookUid]);
|
|
48
|
+
const preset = useMemo(() => (hasExplicitCron ? presetFromCron(cronExpression) : 'custom'), [cronExpression, hasExplicitCron]);
|
|
49
|
+
const isEnabled = (enabled ?? true) &&
|
|
50
|
+
Boolean(token) &&
|
|
51
|
+
Boolean(notebookUid || scheduleUid) &&
|
|
52
|
+
!isSaving &&
|
|
53
|
+
!isDeleting;
|
|
54
|
+
const selectedPresetDescription = useMemo(() => {
|
|
55
|
+
if (!hasExplicitCron) {
|
|
56
|
+
return 'Not scheduled';
|
|
57
|
+
}
|
|
58
|
+
const selected = SCHEDULE_PRESETS.find(item => item.cron === cronExpression.trim());
|
|
59
|
+
if (selected) {
|
|
60
|
+
return `${selected.label} (${selected.cron})`;
|
|
61
|
+
}
|
|
62
|
+
return `Custom (${cronExpression || 'Cron expression not set'})`;
|
|
63
|
+
}, [cronExpression, hasExplicitCron]);
|
|
64
|
+
const saveSchedule = async (nextPreset, nextCron) => {
|
|
65
|
+
const cron = nextCron.trim();
|
|
66
|
+
if (!token || (!notebookUid && !scheduleUid) || !cron) {
|
|
67
|
+
return;
|
|
68
|
+
}
|
|
69
|
+
setIsSaving(true);
|
|
70
|
+
try {
|
|
71
|
+
let schedule;
|
|
72
|
+
if (scheduleUid) {
|
|
73
|
+
const response = await updateSchedule(token, scheduleUid, {
|
|
74
|
+
cronExpression: cron,
|
|
75
|
+
preset: nextPreset,
|
|
76
|
+
}, baseUrl);
|
|
77
|
+
schedule = response.schedule;
|
|
78
|
+
}
|
|
79
|
+
else {
|
|
80
|
+
const response = await upsertSchedule(token, {
|
|
81
|
+
notebookUid: notebookUid,
|
|
82
|
+
cronExpression: cron,
|
|
83
|
+
preset: nextPreset,
|
|
84
|
+
enabled: true,
|
|
85
|
+
}, baseUrl);
|
|
86
|
+
schedule = response.schedule;
|
|
87
|
+
}
|
|
88
|
+
onSaved?.(schedule);
|
|
89
|
+
}
|
|
90
|
+
catch (error) {
|
|
91
|
+
onError?.(error);
|
|
92
|
+
}
|
|
93
|
+
finally {
|
|
94
|
+
setIsSaving(false);
|
|
95
|
+
}
|
|
96
|
+
};
|
|
97
|
+
const selectPreset = (nextPreset) => {
|
|
98
|
+
const next = SCHEDULE_PRESETS.find(item => item.id === nextPreset);
|
|
99
|
+
if (!next) {
|
|
100
|
+
return;
|
|
101
|
+
}
|
|
102
|
+
setHasExplicitCron(true);
|
|
103
|
+
setCronExpression(next.cron);
|
|
104
|
+
void saveSchedule(nextPreset, next.cron);
|
|
105
|
+
};
|
|
106
|
+
const applyCustomCron = () => {
|
|
107
|
+
const value = cronExpression.trim();
|
|
108
|
+
const inferredPreset = presetFromCron(value);
|
|
109
|
+
void saveSchedule(inferredPreset, value);
|
|
110
|
+
};
|
|
111
|
+
const performDeleteSchedule = async () => {
|
|
112
|
+
if (!token || !scheduleUid) {
|
|
113
|
+
return;
|
|
114
|
+
}
|
|
115
|
+
setIsDeleting(true);
|
|
116
|
+
try {
|
|
117
|
+
const response = await disableSchedule(token, scheduleUid, baseUrl);
|
|
118
|
+
setIsDeleteDialogOpen(false);
|
|
119
|
+
setDeleteConfirmUid('');
|
|
120
|
+
onDeleted?.(response.schedule);
|
|
121
|
+
}
|
|
122
|
+
catch (error) {
|
|
123
|
+
onError?.(error);
|
|
124
|
+
}
|
|
125
|
+
finally {
|
|
126
|
+
setIsDeleting(false);
|
|
127
|
+
}
|
|
128
|
+
};
|
|
129
|
+
return (_jsxs(_Fragment, { children: [_jsxs(ActionMenu, { children: [_jsx(ActionMenu.Anchor, { children: _jsx(IconButton, { icon: isSaving ? () => _jsx(Spinner, { size: "small" }) : icon, variant: "invisible", sx: iconColor ? { color: iconColor } : undefined, "aria-label": ariaLabel, title: isSaving
|
|
130
|
+
? `${ariaLabel} (saving…)`
|
|
131
|
+
: isEnabled
|
|
132
|
+
? ariaLabel
|
|
133
|
+
: `${ariaLabel} (disabled)` }) }), _jsxs(ActionMenu.Overlay, { width: "medium", sx: { minWidth: 300 }, children: [_jsx(Box, { sx: {
|
|
134
|
+
px: 3,
|
|
135
|
+
pt: 3,
|
|
136
|
+
pb: 2,
|
|
137
|
+
borderBottom: '1px solid',
|
|
138
|
+
borderColor: 'border.default',
|
|
139
|
+
}, children: _jsx(Text, { as: "p", sx: { fontWeight: 600 }, children: "Schedule" }) }), _jsx(ActionList, { selectionVariant: "single", showDividers: true, children: SCHEDULE_PRESETS.map(option => (_jsxs(ActionList.Item, { selected: preset === option.id, disabled: !isEnabled, onSelect: () => selectPreset(option.id), children: [option.label, _jsx(ActionList.Description, { variant: "block", children: option.cron })] }, option.id))) }), _jsxs(Box, { sx: { p: 3, borderTop: '1px solid', borderColor: 'border.default' }, children: [_jsx(Text, { as: "p", sx: { fontSize: 0, color: 'fg.muted', mb: 2 }, children: "Cron Expression" }), _jsx(TextInput, { value: cronExpression, onChange: event => {
|
|
140
|
+
const value = event.currentTarget.value;
|
|
141
|
+
setHasExplicitCron(value.trim().length > 0);
|
|
142
|
+
setCronExpression(value);
|
|
143
|
+
}, placeholder: "* * * * *", "aria-label": "Cron expression", block: true, disabled: !isEnabled }), _jsxs(Box, { sx: { mt: 2, display: 'flex', gap: 2, flexWrap: 'wrap' }, children: [_jsx(Button, { size: "small", onClick: applyCustomCron, disabled: !isEnabled, children: "Apply Cron" }), scheduleUid ? (_jsx(Button, { size: "small", variant: "danger", leadingVisual: TrashIcon, onClick: () => setIsDeleteDialogOpen(true), disabled: !isEnabled, children: "Delete Schedule" })) : null] }), _jsxs(Text, { as: "p", sx: { mt: 2, fontSize: 0, color: 'fg.muted' }, children: ["Current: ", selectedPresetDescription] })] })] })] }), isDeleteDialogOpen && scheduleUid ? (_jsx(Dialog, { title: "Delete schedule", onClose: () => {
|
|
144
|
+
if (isDeleting) {
|
|
145
|
+
return;
|
|
146
|
+
}
|
|
147
|
+
setIsDeleteDialogOpen(false);
|
|
148
|
+
setDeleteConfirmUid('');
|
|
149
|
+
}, width: "medium", children: _jsxs(Box, { sx: { display: 'grid', gap: 3 }, children: [_jsxs(Text, { children: ["This action will disable the schedule and remove planned runs. Type", ' ', _jsx(Text, { as: "span", sx: { fontWeight: 700 }, children: scheduleUid }), ' ', "to confirm."] }), _jsxs(FormControl, { children: [_jsx(FormControl.Label, { children: "Schedule UID" }), _jsx(TextInput, { value: deleteConfirmUid, onChange: event => setDeleteConfirmUid(event.currentTarget.value), placeholder: scheduleUid, autoFocus: true })] }), _jsxs(Box, { sx: { display: 'flex', justifyContent: 'flex-end', gap: 2 }, children: [_jsx(Button, { variant: "default", onClick: () => {
|
|
150
|
+
setIsDeleteDialogOpen(false);
|
|
151
|
+
setDeleteConfirmUid('');
|
|
152
|
+
}, disabled: isDeleting, children: "Cancel" }), _jsx(Button, { variant: "danger", onClick: () => void performDeleteSchedule(), disabled: isDeleting || deleteConfirmUid !== scheduleUid, children: "Delete schedule" })] })] }) })) : null] }));
|
|
153
|
+
};
|
|
154
|
+
export default ScheduleMenu;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './ScheduleMenu';
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
type ILiveRelativeTimeProps = {
|
|
2
|
+
value?: Date | string | number;
|
|
3
|
+
refreshIntervalMs?: number;
|
|
4
|
+
fallback?: string;
|
|
5
|
+
showTooltip?: boolean;
|
|
6
|
+
};
|
|
7
|
+
/**
|
|
8
|
+
* Display a live-updating relative time label (e.g. "5m ago", "in 2m").
|
|
9
|
+
*
|
|
10
|
+
* When `showTooltip` is true, a Primer tooltip shows ISO + localized datetime
|
|
11
|
+
* details with timezone information.
|
|
12
|
+
*/
|
|
13
|
+
export declare function LiveRelativeTime({ value, refreshIntervalMs, fallback, showTooltip, }: ILiveRelativeTimeProps): JSX.Element;
|
|
14
|
+
export {};
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
/*
|
|
3
|
+
* Copyright (c) 2023-2026 Datalayer, Inc.
|
|
4
|
+
* Distributed under the terms of the Modified BSD License.
|
|
5
|
+
*/
|
|
6
|
+
import { useEffect, useMemo, useState } from 'react';
|
|
7
|
+
import { Tooltip } from '@primer/react';
|
|
8
|
+
import { formatDateTimeDetails, formatRelativeTime } from '../../utils/index.js';
|
|
9
|
+
/**
|
|
10
|
+
* Display a live-updating relative time label (e.g. "5m ago", "in 2m").
|
|
11
|
+
*
|
|
12
|
+
* When `showTooltip` is true, a Primer tooltip shows ISO + localized datetime
|
|
13
|
+
* details with timezone information.
|
|
14
|
+
*/
|
|
15
|
+
export function LiveRelativeTime({ value, refreshIntervalMs = 30_000, fallback = '—', showTooltip = true, }) {
|
|
16
|
+
const [now, setNow] = useState(() => new Date());
|
|
17
|
+
useEffect(() => {
|
|
18
|
+
const timer = window.setInterval(() => {
|
|
19
|
+
setNow(new Date());
|
|
20
|
+
}, refreshIntervalMs);
|
|
21
|
+
return () => window.clearInterval(timer);
|
|
22
|
+
}, [refreshIntervalMs]);
|
|
23
|
+
const label = useMemo(() => formatRelativeTime(value, now), [value, now]);
|
|
24
|
+
const tooltip = useMemo(() => formatDateTimeDetails(value), [value]);
|
|
25
|
+
const content = (_jsx("button", { type: "button", "aria-label": tooltip || 'Date and time details', style: {
|
|
26
|
+
border: 'none',
|
|
27
|
+
background: 'transparent',
|
|
28
|
+
padding: 0,
|
|
29
|
+
margin: 0,
|
|
30
|
+
font: 'inherit',
|
|
31
|
+
color: 'inherit',
|
|
32
|
+
cursor: 'inherit',
|
|
33
|
+
lineHeight: 'inherit',
|
|
34
|
+
}, children: label ?? fallback }));
|
|
35
|
+
if (!showTooltip || !tooltip) {
|
|
36
|
+
return content;
|
|
37
|
+
}
|
|
38
|
+
return _jsx(Tooltip, { text: tooltip, children: content });
|
|
39
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './LiveRelativeTime';
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { type ReactNode } from 'react';
|
|
2
|
+
export type TimelineStatus = 'done' | 'current' | 'pending' | 'failed' | 'neutral';
|
|
3
|
+
export type TimelineItem = {
|
|
4
|
+
id: string;
|
|
5
|
+
title: string;
|
|
6
|
+
timestamp?: string;
|
|
7
|
+
status?: TimelineStatus;
|
|
8
|
+
subtitle?: ReactNode;
|
|
9
|
+
};
|
|
10
|
+
export type TimelineProps = {
|
|
11
|
+
items: TimelineItem[];
|
|
12
|
+
renderTimestamp?: (value?: string) => ReactNode;
|
|
13
|
+
};
|
|
14
|
+
/**
|
|
15
|
+
* Horizontal metro-style timeline with connected markers and labels.
|
|
16
|
+
*
|
|
17
|
+
* The first item is rendered on the left. Pass items in the desired order
|
|
18
|
+
* (for example: newest to oldest).
|
|
19
|
+
*/
|
|
20
|
+
export declare const Timeline: ({ items, renderTimestamp }: TimelineProps) => import("react/jsx-runtime").JSX.Element | null;
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { Box, Text } from '@primer/react';
|
|
3
|
+
const statusStyles = {
|
|
4
|
+
done: {
|
|
5
|
+
dotBackground: 'success.emphasis',
|
|
6
|
+
dotBorder: 'success.emphasis',
|
|
7
|
+
lineColor: 'success.muted',
|
|
8
|
+
titleColor: 'fg.default',
|
|
9
|
+
},
|
|
10
|
+
current: {
|
|
11
|
+
dotBackground: 'attention.emphasis',
|
|
12
|
+
dotBorder: 'attention.emphasis',
|
|
13
|
+
lineColor: 'attention.muted',
|
|
14
|
+
titleColor: 'fg.default',
|
|
15
|
+
},
|
|
16
|
+
pending: {
|
|
17
|
+
dotBackground: 'canvas.default',
|
|
18
|
+
dotBorder: 'border.default',
|
|
19
|
+
lineColor: 'border.default',
|
|
20
|
+
titleColor: 'fg.muted',
|
|
21
|
+
},
|
|
22
|
+
failed: {
|
|
23
|
+
dotBackground: 'danger.emphasis',
|
|
24
|
+
dotBorder: 'danger.emphasis',
|
|
25
|
+
lineColor: 'danger.muted',
|
|
26
|
+
titleColor: 'danger.fg',
|
|
27
|
+
},
|
|
28
|
+
neutral: {
|
|
29
|
+
dotBackground: 'accent.emphasis',
|
|
30
|
+
dotBorder: 'accent.emphasis',
|
|
31
|
+
lineColor: 'accent.muted',
|
|
32
|
+
titleColor: 'fg.default',
|
|
33
|
+
},
|
|
34
|
+
};
|
|
35
|
+
/**
|
|
36
|
+
* Horizontal metro-style timeline with connected markers and labels.
|
|
37
|
+
*
|
|
38
|
+
* The first item is rendered on the left. Pass items in the desired order
|
|
39
|
+
* (for example: newest to oldest).
|
|
40
|
+
*/
|
|
41
|
+
export const Timeline = ({ items, renderTimestamp }) => {
|
|
42
|
+
if (!items.length) {
|
|
43
|
+
return null;
|
|
44
|
+
}
|
|
45
|
+
return (_jsx(Box, { sx: {
|
|
46
|
+
overflowX: 'auto',
|
|
47
|
+
pb: 1,
|
|
48
|
+
}, children: _jsx(Box, { sx: {
|
|
49
|
+
display: 'flex',
|
|
50
|
+
alignItems: 'stretch',
|
|
51
|
+
minWidth: 'max-content',
|
|
52
|
+
}, children: items.map((item, index) => {
|
|
53
|
+
const status = item.status || 'neutral';
|
|
54
|
+
const style = statusStyles[status];
|
|
55
|
+
const hasNext = index < items.length - 1;
|
|
56
|
+
return (_jsxs(Box, { sx: {
|
|
57
|
+
display: 'flex',
|
|
58
|
+
flexDirection: 'column',
|
|
59
|
+
minWidth: 220,
|
|
60
|
+
flex: hasNext ? '0 0 220px' : '0 0 auto',
|
|
61
|
+
pr: hasNext ? 0 : 1,
|
|
62
|
+
}, children: [_jsxs(Box, { sx: {
|
|
63
|
+
display: 'flex',
|
|
64
|
+
alignItems: 'center',
|
|
65
|
+
minHeight: 28,
|
|
66
|
+
mb: 2,
|
|
67
|
+
}, children: [_jsx(Box, { sx: {
|
|
68
|
+
width: 16,
|
|
69
|
+
height: 16,
|
|
70
|
+
borderRadius: '50%',
|
|
71
|
+
border: '2px solid',
|
|
72
|
+
borderColor: style.dotBorder,
|
|
73
|
+
bg: style.dotBackground,
|
|
74
|
+
boxShadow: 'inset 0 0 0 1px rgba(255,255,255,0.2)',
|
|
75
|
+
} }), hasNext ? (_jsx(Box, { sx: {
|
|
76
|
+
flex: 1,
|
|
77
|
+
height: 4,
|
|
78
|
+
ml: 2,
|
|
79
|
+
mr: 2,
|
|
80
|
+
borderRadius: 999,
|
|
81
|
+
bg: style.lineColor,
|
|
82
|
+
} })) : null] }), _jsx(Text, { as: "p", sx: { fontWeight: 600, color: style.titleColor, mb: 1 }, children: item.title }), _jsx(Text, { as: "p", sx: {
|
|
83
|
+
fontSize: 0,
|
|
84
|
+
color: 'fg.muted',
|
|
85
|
+
mb: item.subtitle ? 1 : 0,
|
|
86
|
+
}, children: renderTimestamp
|
|
87
|
+
? renderTimestamp(item.timestamp)
|
|
88
|
+
: item.timestamp || 'n/a' }), item.subtitle ? (_jsx(Text, { as: "p", sx: { fontSize: 0, color: 'fg.subtle' }, children: item.subtitle })) : null] }, item.id));
|
|
89
|
+
}) }) }));
|
|
90
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './Timeline';
|
package/lib/hooks/useCache.d.ts
CHANGED
|
@@ -233,6 +233,14 @@ export declare const queryKeys: {
|
|
|
233
233
|
readonly growth: {
|
|
234
234
|
readonly kpi: () => readonly ["growth", "kpi"];
|
|
235
235
|
};
|
|
236
|
+
readonly ray: {
|
|
237
|
+
readonly all: () => readonly ["ray"];
|
|
238
|
+
readonly clusters: () => readonly ["ray", "clusters"];
|
|
239
|
+
readonly cluster: (namespace: string, clusterName: string) => readonly ["ray", "cluster", string, string];
|
|
240
|
+
readonly jobs: (namespace: string, clusterName?: string) => readonly ["ray", "jobs", string, string];
|
|
241
|
+
readonly job: (namespace: string, jobName: string) => readonly ["ray", "job", string, string];
|
|
242
|
+
readonly logs: (namespace: string, jobName: string) => readonly ["ray", "job", string, string, "logs"];
|
|
243
|
+
};
|
|
236
244
|
readonly oauth2: {
|
|
237
245
|
readonly authorizationUrl: (queryArgs: Record<string, string>) => readonly ["oauth2", "authz", "url", Record<string, string>];
|
|
238
246
|
readonly authorizationLinkUrl: (queryArgs: Record<string, string>) => readonly ["oauth2", "authz", "url", "link", Record<string, string>];
|
|
@@ -750,7 +758,7 @@ export declare const useCache: ({ loginRoute }?: CacheProps) => {
|
|
|
750
758
|
principalKind?: "user" | "organization" | "team";
|
|
751
759
|
}) => import("@tanstack/react-query").UseMutationResult<any, Error, string, unknown>;
|
|
752
760
|
useToken: (tokenId: string) => import("@tanstack/react-query").UseQueryResult<IIAMToken | null | undefined, Error>;
|
|
753
|
-
useTokens: () => import("@tanstack/react-query").UseQueryResult<
|
|
761
|
+
useTokens: () => import("@tanstack/react-query").UseQueryResult<(IIAMToken | undefined)[], Error>;
|
|
754
762
|
useCreateToken: () => import("@tanstack/react-query").UseMutationResult<any, Error, Omit<IIAMToken, "id" | "value">, unknown>;
|
|
755
763
|
useUpdateToken: () => import("@tanstack/react-query").UseMutationResult<any, Error, IIAMToken, unknown>;
|
|
756
764
|
useDeleteToken: () => import("@tanstack/react-query").UseMutationResult<any, Error, string, unknown>;
|
|
@@ -899,6 +907,20 @@ export declare const useCache: ({ loginRoute }?: CacheProps) => {
|
|
|
899
907
|
useUserSurveys: (userId: string, options?: Omit<UseQueryOptions<unknown>, "queryKey" | "queryFn">) => import("@tanstack/react-query").UseQueryResult<unknown, Error>;
|
|
900
908
|
useGrowthKPI: (options?: Omit<UseQueryOptions<unknown>, "queryKey" | "queryFn">) => import("@tanstack/react-query").UseQueryResult<unknown, Error>;
|
|
901
909
|
useGrowthContactsKPI: (options?: Omit<UseQueryOptions<unknown>, "queryKey" | "queryFn">) => import("@tanstack/react-query").UseQueryResult<unknown, Error>;
|
|
910
|
+
useRayClusters: () => import("@tanstack/react-query").UseQueryResult<{
|
|
911
|
+
clusters: any[];
|
|
912
|
+
namespaces: string[];
|
|
913
|
+
}, Error>;
|
|
914
|
+
useRayCluster: (namespace?: string, clusterName?: string) => import("@tanstack/react-query").UseQueryResult<any, Error>;
|
|
915
|
+
useCreateRayCluster: () => import("@tanstack/react-query").UseMutationResult<any, Error, Record<string, unknown>, unknown>;
|
|
916
|
+
useDeleteRayCluster: (namespace?: string) => import("@tanstack/react-query").UseMutationResult<any, Error, string, unknown>;
|
|
917
|
+
useRayJobs: (namespace?: string, clusterName?: string) => import("@tanstack/react-query").UseQueryResult<any[], Error>;
|
|
918
|
+
useSubmitRayJob: (clusterName: string) => import("@tanstack/react-query").UseMutationResult<any, Error, Record<string, unknown>, unknown>;
|
|
919
|
+
useDeleteRayJob: (namespace?: string) => import("@tanstack/react-query").UseMutationResult<any, Error, string, unknown>;
|
|
920
|
+
useRayJobLogs: (jobName: string, namespace?: string, tailLines?: number, enabled?: boolean) => import("@tanstack/react-query").UseQueryResult<{
|
|
921
|
+
logs: string;
|
|
922
|
+
status: string;
|
|
923
|
+
}, Error>;
|
|
902
924
|
queryKeys: {
|
|
903
925
|
readonly auth: {
|
|
904
926
|
readonly me: () => readonly ["auth", "me"];
|
|
@@ -1084,6 +1106,14 @@ export declare const useCache: ({ loginRoute }?: CacheProps) => {
|
|
|
1084
1106
|
readonly growth: {
|
|
1085
1107
|
readonly kpi: () => readonly ["growth", "kpi"];
|
|
1086
1108
|
};
|
|
1109
|
+
readonly ray: {
|
|
1110
|
+
readonly all: () => readonly ["ray"];
|
|
1111
|
+
readonly clusters: () => readonly ["ray", "clusters"];
|
|
1112
|
+
readonly cluster: (namespace: string, clusterName: string) => readonly ["ray", "cluster", string, string];
|
|
1113
|
+
readonly jobs: (namespace: string, clusterName?: string) => readonly ["ray", "jobs", string, string];
|
|
1114
|
+
readonly job: (namespace: string, jobName: string) => readonly ["ray", "job", string, string];
|
|
1115
|
+
readonly logs: (namespace: string, jobName: string) => readonly ["ray", "job", string, string, "logs"];
|
|
1116
|
+
};
|
|
1087
1117
|
readonly oauth2: {
|
|
1088
1118
|
readonly authorizationUrl: (queryArgs: Record<string, string>) => readonly ["oauth2", "authz", "url", Record<string, string>];
|
|
1089
1119
|
readonly authorizationLinkUrl: (queryArgs: Record<string, string>) => readonly ["oauth2", "authz", "url", "link", Record<string, string>];
|