@kb-labs/studio-app 0.7.0 → 2.9.0
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/dist/index.html +1 -0
- package/dist/main.80b70197.css +2 -0
- package/dist/main.80b70197.css.map +1 -0
- package/dist/main.ad42ef4a.js +522 -0
- package/dist/main.ad42ef4a.js.map +1 -0
- package/dist/mf-manifest.json +241 -0
- package/dist/mf-stats.json +271 -0
- package/package.json +56 -39
- package/server.js +68 -0
- package/.env.example +0 -10
- package/UI-KIT-COMPONENTS.md +0 -783
- package/UI-KIT-PLAN.md +0 -326
- package/eslint-rules/no-direct-antd-import.js +0 -151
- package/eslint.config.ts +0 -27
- package/index.html +0 -17
- package/postcss.config.js +0 -7
- package/public/favicon.ico +0 -0
- package/rspack.config.mjs +0 -118
- package/src/App.tsx +0 -46
- package/src/components/devtools/devtools-log-feed.module.css +0 -165
- package/src/components/devtools/devtools-log-feed.tsx +0 -300
- package/src/components/devtools/devtools-panel.module.css +0 -121
- package/src/components/devtools/devtools-panel.tsx +0 -115
- package/src/components/empty-state.tsx +0 -28
- package/src/components/error-boundary.tsx +0 -210
- package/src/components/health-banner.module.css +0 -103
- package/src/components/health-banner.tsx +0 -134
- package/src/components/health-indicator.tsx +0 -12
- package/src/components/page-header.tsx +0 -49
- package/src/components/page-transition.tsx +0 -24
- package/src/components/role-switcher.tsx +0 -148
- package/src/components/run-badge.tsx +0 -13
- package/src/components/ui/icons.tsx +0 -509
- package/src/components/ui/index.ts +0 -25
- package/src/components/ui/kb-config-provider.tsx +0 -130
- package/src/components/ui/kb-header.module.css +0 -51
- package/src/components/ui/kb-header.tsx +0 -112
- package/src/components/ui/kb-notification-bell.module.css +0 -103
- package/src/components/ui/kb-notification-bell.tsx +0 -199
- package/src/components/ui/kb-page-layout.tsx +0 -66
- package/src/components/ui/kb-quick-search.module.css +0 -86
- package/src/components/ui/kb-quick-search.tsx +0 -196
- package/src/components/ui/kb-sidebar.module.css +0 -47
- package/src/components/ui/kb-sidebar.tsx +0 -196
- package/src/components/ui/kb-stat-card.module.css +0 -21
- package/src/components/ui/kb-stat-card.tsx +0 -22
- package/src/components/ui/kb-stat-grid.tsx +0 -22
- package/src/components/ui/kb-status-bar.module.css +0 -49
- package/src/components/ui/kb-status-bar.tsx +0 -145
- package/src/components/ui/kb-system-health-indicator.tsx +0 -229
- package/src/components/ui/kb-theme-toggle.tsx +0 -42
- package/src/components/ui/theme-adapter.ts +0 -812
- package/src/components/ui/theme-transition-overlay.tsx +0 -70
- package/src/components/ui/utils.ts +0 -6
- package/src/components/widget-error-boundary.tsx +0 -172
- package/src/config/env.ts +0 -5
- package/src/config/feature-flags.ts +0 -482
- package/src/config/studio.config.schema.ts +0 -88
- package/src/config/studio.config.ts +0 -84
- package/src/env.d.ts +0 -23
- package/src/hooks/use-command-palette.ts +0 -6
- package/src/hooks/use-devtools-store.ts +0 -25
- package/src/hooks/use-feature-flags.ts +0 -101
- package/src/index.css +0 -10
- package/src/layouts/dashboard-grid.tsx +0 -122
- package/src/layouts/index.ts +0 -12
- package/src/layouts/two-pane.tsx +0 -134
- package/src/main.tsx +0 -15
- package/src/modules/analytics/components/analytics-daily-stats-chart.tsx +0 -257
- package/src/modules/analytics/components/analytics-date-range-picker.tsx +0 -121
- package/src/modules/analytics/pages/analytics-cache-page.tsx +0 -285
- package/src/modules/analytics/pages/analytics-embeddings-page.tsx +0 -274
- package/src/modules/analytics/pages/analytics-events-page.tsx +0 -425
- package/src/modules/analytics/pages/analytics-llm-page.tsx +0 -434
- package/src/modules/analytics/pages/analytics-overview-page.tsx +0 -336
- package/src/modules/analytics/pages/analytics-page.tsx +0 -20
- package/src/modules/analytics/pages/analytics-storage-page.tsx +0 -344
- package/src/modules/analytics/pages/analytics-vectorstore-page.tsx +0 -279
- package/src/modules/analytics/routes/index.tsx +0 -133
- package/src/modules/analytics/utils/formatters.test.ts +0 -148
- package/src/modules/analytics/utils/formatters.ts +0 -100
- package/src/modules/auth/pages/login-page.module.css +0 -113
- package/src/modules/auth/pages/login-page.tsx +0 -80
- package/src/modules/auth/routes/index.tsx +0 -24
- package/src/modules/dashboard/components/ActivityTimelineWidget.tsx +0 -199
- package/src/modules/dashboard/components/AiInsightsWidget.tsx +0 -358
- package/src/modules/dashboard/components/AnimatedMetricCard.css +0 -88
- package/src/modules/dashboard/components/AnimatedMetricCard.tsx +0 -125
- package/src/modules/dashboard/components/HeroMetricCard.css +0 -114
- package/src/modules/dashboard/components/HeroMetricCard.tsx +0 -152
- package/src/modules/dashboard/components/HeroMetricsWidget.tsx +0 -146
- package/src/modules/dashboard/components/SystemResourcesWidget.tsx +0 -197
- package/src/modules/dashboard/components/dashboard-empty.tsx +0 -22
- package/src/modules/dashboard/components/dashboard-kpis-widget.tsx +0 -59
- package/src/modules/dashboard/components/dashboard-kpis.tsx +0 -13
- package/src/modules/dashboard/components/dashboard-latency-percentiles-widget.tsx +0 -85
- package/src/modules/dashboard/components/dashboard-metrics-widget.tsx +0 -78
- package/src/modules/dashboard/components/dashboard-plugins-widget.tsx +0 -67
- package/src/modules/dashboard/components/dashboard-requests-widget.tsx +0 -62
- package/src/modules/dashboard/layouts/dashboard-layout.tsx +0 -16
- package/src/modules/dashboard/pages/ai-insights-page.tsx +0 -563
- package/src/modules/dashboard/pages/dashboard-animations.css +0 -317
- package/src/modules/dashboard/pages/dashboard-page.tsx +0 -13
- package/src/modules/dashboard/routes/index.tsx +0 -70
- package/src/modules/observability/pages/devkit-page.tsx +0 -263
- package/src/modules/observability/pages/incident-detail-page.tsx +0 -571
- package/src/modules/observability/pages/incidents-page.tsx +0 -370
- package/src/modules/observability/pages/log-detail-page.tsx +0 -508
- package/src/modules/observability/pages/logs-page.tsx +0 -1129
- package/src/modules/observability/pages/prometheus-metrics-page.tsx +0 -486
- package/src/modules/observability/pages/state-broker-page.tsx +0 -229
- package/src/modules/observability/pages/system-events-page.tsx +0 -255
- package/src/modules/observability/routes/index.tsx +0 -133
- package/src/modules/plugins/components/marketplace-card.tsx +0 -153
- package/src/modules/plugins/components/plugin-ai-assistant-modal.tsx +0 -374
- package/src/modules/plugins/components/plugin-card.tsx +0 -136
- package/src/modules/plugins/components/plugin-detail/capabilities-summary.tsx +0 -101
- package/src/modules/plugins/components/plugin-detail/cli-commands-table.tsx +0 -101
- package/src/modules/plugins/components/plugin-detail/index.ts +0 -7
- package/src/modules/plugins/components/plugin-detail/jobs-table.tsx +0 -64
- package/src/modules/plugins/components/plugin-detail/permissions/env-permissions.tsx +0 -30
- package/src/modules/plugins/components/plugin-detail/permissions/filesystem-permissions.tsx +0 -68
- package/src/modules/plugins/components/plugin-detail/permissions/index.ts +0 -6
- package/src/modules/plugins/components/plugin-detail/permissions/network-permissions.tsx +0 -43
- package/src/modules/plugins/components/plugin-detail/permissions/platform-services.tsx +0 -242
- package/src/modules/plugins/components/plugin-detail/permissions/resource-quotas.tsx +0 -96
- package/src/modules/plugins/components/plugin-detail/permissions/shell-permissions.tsx +0 -55
- package/src/modules/plugins/components/plugin-detail/permissions-view.tsx +0 -47
- package/src/modules/plugins/components/plugin-detail/plugin-header.tsx +0 -169
- package/src/modules/plugins/components/plugin-detail/rest-routes-table.tsx +0 -159
- package/src/modules/plugins/components/plugin-detail/workflows-table.tsx +0 -40
- package/src/modules/plugins/components/plugin-grid.tsx +0 -20
- package/src/modules/plugins/components/plugin-table.tsx +0 -178
- package/src/modules/plugins/pages/marketplace-page.tsx +0 -200
- package/src/modules/plugins/pages/plugin-detail-page.tsx +0 -1145
- package/src/modules/plugins/routes/index.tsx +0 -48
- package/src/modules/plugins/utils/index.ts +0 -1
- package/src/modules/plugins/utils/schema-helpers.ts +0 -21
- package/src/modules/settings/components/api-routes-viewer.tsx +0 -415
- package/src/modules/settings/components/appearance-settings.tsx +0 -200
- package/src/modules/settings/components/configuration-settings.tsx +0 -321
- package/src/modules/settings/components/data-privacy-settings.tsx +0 -111
- package/src/modules/settings/components/experimental-settings.tsx +0 -243
- package/src/modules/settings/components/navigation-settings.tsx +0 -198
- package/src/modules/settings/components/notifications-settings.tsx +0 -40
- package/src/modules/settings/pages/settings-page.tsx +0 -298
- package/src/modules/settings/routes/index.tsx +0 -47
- package/src/pages/README-assistant.md +0 -91
- package/src/pages/login-page.tsx +0 -177
- package/src/pages/not-found-page.tsx +0 -85
- package/src/providers/auth-provider.tsx +0 -40
- package/src/providers/command-palette-provider.tsx +0 -193
- package/src/providers/data-sources-provider.tsx +0 -27
- package/src/providers/devtools-provider.tsx +0 -72
- package/src/providers/navigation-items-provider.tsx +0 -38
- package/src/providers/registry-v2-provider.tsx +0 -93
- package/src/providers/settings-provider.tsx +0 -158
- package/src/router.tsx +0 -302
- package/src/routes/helpers.tsx +0 -25
- package/src/routes/plugin-page-v2.tsx +0 -52
- package/src/routes/types.ts +0 -18
- package/src/styles/antd-overrides.css +0 -211
- package/src/styles/base.css +0 -190
- package/src/styles/settings.css +0 -75
- package/src/styles/variables.css +0 -94
- package/src/utils/analytics.ts +0 -183
- package/src/utils/apply-navigation-categories.ts +0 -83
- package/src/utils/commands.ts +0 -252
- package/src/utils/export.ts +0 -174
- package/src/utils/format-date.ts +0 -166
- package/src/utils/logger.ts +0 -110
- package/tailwind.config.ts +0 -13
- package/tsconfig.json +0 -13
- package/vitest-setup.ts +0 -1
- /package/{public → dist}/favicon.svg +0 -0
package/src/pages/login-page.tsx
DELETED
|
@@ -1,177 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* @module @kb-labs/studio-app/pages/login-page
|
|
3
|
-
* Login page placeholder - mock authentication
|
|
4
|
-
*/
|
|
5
|
-
|
|
6
|
-
import * as React from 'react';
|
|
7
|
-
import { useNavigate } from 'react-router-dom';
|
|
8
|
-
import {
|
|
9
|
-
UICard, UIButton, UISpace, UITitle, UITypographyText, UITypographyParagraph,
|
|
10
|
-
UISelect, UIDivider, UIMessage, UIIcon,
|
|
11
|
-
} from '@kb-labs/studio-ui-kit';
|
|
12
|
-
import { useAuth, type UserRole } from '@/providers/auth-provider';
|
|
13
|
-
|
|
14
|
-
export function LoginPage() {
|
|
15
|
-
const navigate = useNavigate();
|
|
16
|
-
const { setRole } = useAuth();
|
|
17
|
-
const [selectedRole, setSelectedRole] = React.useState<UserRole>('operator');
|
|
18
|
-
|
|
19
|
-
const handleLogin = () => {
|
|
20
|
-
setRole(selectedRole);
|
|
21
|
-
navigate('/');
|
|
22
|
-
};
|
|
23
|
-
|
|
24
|
-
const handleSSOLogin = () => {
|
|
25
|
-
UIMessage.info('SSO аутентификация будет реализована позже');
|
|
26
|
-
// TODO: Implement SSO authentication
|
|
27
|
-
};
|
|
28
|
-
|
|
29
|
-
return (
|
|
30
|
-
<div
|
|
31
|
-
style={{
|
|
32
|
-
display: 'flex',
|
|
33
|
-
alignItems: 'center',
|
|
34
|
-
justifyContent: 'center',
|
|
35
|
-
minHeight: '100vh',
|
|
36
|
-
backgroundColor: 'var(--bg-tertiary)',
|
|
37
|
-
padding: '2rem',
|
|
38
|
-
}}
|
|
39
|
-
>
|
|
40
|
-
<UICard
|
|
41
|
-
style={{
|
|
42
|
-
maxWidth: '480px',
|
|
43
|
-
width: '100%',
|
|
44
|
-
borderRadius: '16px',
|
|
45
|
-
boxShadow: '0 20px 60px rgba(0,0,0,0.3)',
|
|
46
|
-
}}
|
|
47
|
-
styles={{ body: { padding: '3rem' } }}
|
|
48
|
-
>
|
|
49
|
-
<UISpace direction="vertical" size="large" style={{ width: '100%', textAlign: 'center' }}>
|
|
50
|
-
{/* Logo */}
|
|
51
|
-
<div
|
|
52
|
-
style={{
|
|
53
|
-
width: '80px',
|
|
54
|
-
height: '80px',
|
|
55
|
-
margin: '0 auto',
|
|
56
|
-
background: 'linear-gradient(135deg, #667eea 0%, #764ba2 100%)',
|
|
57
|
-
borderRadius: '20px',
|
|
58
|
-
display: 'flex',
|
|
59
|
-
alignItems: 'center',
|
|
60
|
-
justifyContent: 'center',
|
|
61
|
-
fontSize: '40px',
|
|
62
|
-
}}
|
|
63
|
-
>
|
|
64
|
-
<UIIcon name="RocketOutlined" style={{ color: 'white' }} />
|
|
65
|
-
</div>
|
|
66
|
-
|
|
67
|
-
{/* Title */}
|
|
68
|
-
<div>
|
|
69
|
-
<UITitle level={2} style={{ marginBottom: 8 }}>
|
|
70
|
-
KB Labs Studio
|
|
71
|
-
</UITitle>
|
|
72
|
-
<UITypographyText type="secondary">Добро пожаловать в платформу</UITypographyText>
|
|
73
|
-
</div>
|
|
74
|
-
|
|
75
|
-
<UIDivider style={{ margin: '8px 0' }} />
|
|
76
|
-
|
|
77
|
-
{/* Mock Auth Notice */}
|
|
78
|
-
<div
|
|
79
|
-
style={{
|
|
80
|
-
padding: '16px',
|
|
81
|
-
backgroundColor: 'var(--bg-tertiary)',
|
|
82
|
-
borderRadius: '8px',
|
|
83
|
-
border: '1px solid var(--border-primary)',
|
|
84
|
-
}}
|
|
85
|
-
>
|
|
86
|
-
<UISpace direction="vertical" size="small" style={{ width: '100%' }}>
|
|
87
|
-
<div style={{ display: 'flex', alignItems: 'center', gap: 8 }}>
|
|
88
|
-
<UIIcon name="LockOutlined" style={{ color: '#667eea' }} />
|
|
89
|
-
<UITypographyText strong style={{ color: '#667eea' }}>
|
|
90
|
-
Режим разработки
|
|
91
|
-
</UITypographyText>
|
|
92
|
-
</div>
|
|
93
|
-
<UITypographyParagraph
|
|
94
|
-
type="secondary"
|
|
95
|
-
style={{ margin: 0, fontSize: '0.875rem', textAlign: 'left' }}
|
|
96
|
-
>
|
|
97
|
-
Это заглушка для входа. Выберите роль и войдите без пароля.
|
|
98
|
-
</UITypographyParagraph>
|
|
99
|
-
</UISpace>
|
|
100
|
-
</div>
|
|
101
|
-
|
|
102
|
-
{/* Role Selector */}
|
|
103
|
-
<div style={{ width: '100%', textAlign: 'left' }}>
|
|
104
|
-
<UITypographyText strong style={{ display: 'block', marginBottom: 8 }}>
|
|
105
|
-
Выберите роль:
|
|
106
|
-
</UITypographyText>
|
|
107
|
-
<UISelect
|
|
108
|
-
value={selectedRole}
|
|
109
|
-
onChange={(v) => setSelectedRole(v as UserRole)}
|
|
110
|
-
style={{ width: '100%' }}
|
|
111
|
-
size="large"
|
|
112
|
-
options={[
|
|
113
|
-
{
|
|
114
|
-
label: 'Viewer — Просмотр данных',
|
|
115
|
-
value: 'viewer',
|
|
116
|
-
},
|
|
117
|
-
{
|
|
118
|
-
label: 'Operator — Управление системой',
|
|
119
|
-
value: 'operator',
|
|
120
|
-
},
|
|
121
|
-
{
|
|
122
|
-
label: 'Admin — Полный доступ',
|
|
123
|
-
value: 'admin',
|
|
124
|
-
},
|
|
125
|
-
]}
|
|
126
|
-
/>
|
|
127
|
-
</div>
|
|
128
|
-
|
|
129
|
-
{/* Login Buttons */}
|
|
130
|
-
<UISpace direction="vertical" size="middle" style={{ width: '100%' }}>
|
|
131
|
-
<UIButton
|
|
132
|
-
variant="primary"
|
|
133
|
-
size="large"
|
|
134
|
-
block
|
|
135
|
-
icon={<UIIcon name="RocketOutlined" />}
|
|
136
|
-
onClick={handleLogin}
|
|
137
|
-
style={{
|
|
138
|
-
height: '48px',
|
|
139
|
-
fontSize: '16px',
|
|
140
|
-
fontWeight: 500,
|
|
141
|
-
}}
|
|
142
|
-
>
|
|
143
|
-
Войти в систему
|
|
144
|
-
</UIButton>
|
|
145
|
-
|
|
146
|
-
<UIDivider style={{ margin: '8px 0' }}>
|
|
147
|
-
<UITypographyText type="secondary" style={{ fontSize: '0.75rem' }}>
|
|
148
|
-
или
|
|
149
|
-
</UITypographyText>
|
|
150
|
-
</UIDivider>
|
|
151
|
-
|
|
152
|
-
<UIButton
|
|
153
|
-
size="large"
|
|
154
|
-
block
|
|
155
|
-
icon={<UIIcon name="SafetyOutlined" />}
|
|
156
|
-
onClick={handleSSOLogin}
|
|
157
|
-
style={{
|
|
158
|
-
height: '48px',
|
|
159
|
-
fontSize: '16px',
|
|
160
|
-
fontWeight: 500,
|
|
161
|
-
}}
|
|
162
|
-
>
|
|
163
|
-
Войти через SSO
|
|
164
|
-
</UIButton>
|
|
165
|
-
</UISpace>
|
|
166
|
-
|
|
167
|
-
{/* Footer */}
|
|
168
|
-
<div style={{ marginTop: '16px' }}>
|
|
169
|
-
<UITypographyText type="secondary" style={{ fontSize: '0.75rem' }}>
|
|
170
|
-
© 2025 KB Labs Studio. Development Preview.
|
|
171
|
-
</UITypographyText>
|
|
172
|
-
</div>
|
|
173
|
-
</UISpace>
|
|
174
|
-
</UICard>
|
|
175
|
-
</div>
|
|
176
|
-
);
|
|
177
|
-
}
|
|
@@ -1,85 +0,0 @@
|
|
|
1
|
-
import { useNavigate, useLocation } from 'react-router-dom';
|
|
2
|
-
import { UIButton } from '@kb-labs/studio-ui-kit';
|
|
3
|
-
import { ArrowLeft, Home } from 'lucide-react';
|
|
4
|
-
|
|
5
|
-
export function NotFoundPage() {
|
|
6
|
-
const navigate = useNavigate();
|
|
7
|
-
const location = useLocation();
|
|
8
|
-
|
|
9
|
-
return (
|
|
10
|
-
<div style={{
|
|
11
|
-
display: 'flex',
|
|
12
|
-
alignItems: 'center',
|
|
13
|
-
justifyContent: 'center',
|
|
14
|
-
minHeight: '100vh',
|
|
15
|
-
backgroundColor: 'var(--bg-primary)',
|
|
16
|
-
padding: 24,
|
|
17
|
-
}}>
|
|
18
|
-
<div style={{ textAlign: 'center', maxWidth: 400 }}>
|
|
19
|
-
<div style={{
|
|
20
|
-
fontSize: 96,
|
|
21
|
-
fontWeight: 700,
|
|
22
|
-
lineHeight: 1,
|
|
23
|
-
letterSpacing: '-4px',
|
|
24
|
-
color: 'var(--border-secondary)',
|
|
25
|
-
fontFamily: 'var(--font-heading)',
|
|
26
|
-
marginBottom: 24,
|
|
27
|
-
userSelect: 'none',
|
|
28
|
-
}}>
|
|
29
|
-
404
|
|
30
|
-
</div>
|
|
31
|
-
|
|
32
|
-
<div style={{
|
|
33
|
-
fontSize: 18,
|
|
34
|
-
fontWeight: 600,
|
|
35
|
-
color: 'var(--text-primary)',
|
|
36
|
-
marginBottom: 8,
|
|
37
|
-
}}>
|
|
38
|
-
Page not found
|
|
39
|
-
</div>
|
|
40
|
-
|
|
41
|
-
<div style={{
|
|
42
|
-
fontSize: 13,
|
|
43
|
-
color: 'var(--text-secondary)',
|
|
44
|
-
marginBottom: 4,
|
|
45
|
-
lineHeight: 1.5,
|
|
46
|
-
}}>
|
|
47
|
-
The page you're looking for doesn't exist or has been moved.
|
|
48
|
-
</div>
|
|
49
|
-
|
|
50
|
-
{location.pathname !== '/' && (
|
|
51
|
-
<div style={{
|
|
52
|
-
fontSize: 11,
|
|
53
|
-
color: 'var(--text-tertiary)',
|
|
54
|
-
marginBottom: 32,
|
|
55
|
-
fontFamily: 'var(--font-mono, monospace)',
|
|
56
|
-
background: 'var(--bg-tertiary)',
|
|
57
|
-
border: '1px solid var(--border-primary)',
|
|
58
|
-
borderRadius: 6,
|
|
59
|
-
padding: '4px 10px',
|
|
60
|
-
display: 'inline-block',
|
|
61
|
-
marginTop: 12,
|
|
62
|
-
}}>
|
|
63
|
-
{location.pathname}
|
|
64
|
-
</div>
|
|
65
|
-
)}
|
|
66
|
-
|
|
67
|
-
<div style={{ display: 'flex', gap: 8, justifyContent: 'center', marginTop: 24 }}>
|
|
68
|
-
<UIButton
|
|
69
|
-
variant="primary"
|
|
70
|
-
icon={<Home size={14} />}
|
|
71
|
-
onClick={() => navigate('/')}
|
|
72
|
-
>
|
|
73
|
-
Go home
|
|
74
|
-
</UIButton>
|
|
75
|
-
<UIButton
|
|
76
|
-
icon={<ArrowLeft size={14} />}
|
|
77
|
-
onClick={() => navigate(-1)}
|
|
78
|
-
>
|
|
79
|
-
Go back
|
|
80
|
-
</UIButton>
|
|
81
|
-
</div>
|
|
82
|
-
</div>
|
|
83
|
-
</div>
|
|
84
|
-
);
|
|
85
|
-
}
|
|
@@ -1,40 +0,0 @@
|
|
|
1
|
-
import { createContext, useContext, useState, useEffect, type ReactNode } from 'react';
|
|
2
|
-
|
|
3
|
-
export type UserRole = 'viewer' | 'operator' | 'admin';
|
|
4
|
-
|
|
5
|
-
interface AuthState {
|
|
6
|
-
role: UserRole;
|
|
7
|
-
setRole: (role: UserRole) => void;
|
|
8
|
-
}
|
|
9
|
-
|
|
10
|
-
const AuthContext = createContext<AuthState | null>(null);
|
|
11
|
-
|
|
12
|
-
export function AuthProvider({ children }: { children: ReactNode }) {
|
|
13
|
-
const [role, setRoleState] = useState<UserRole>(
|
|
14
|
-
() => (localStorage.getItem('studio-user-role') as UserRole) || 'operator'
|
|
15
|
-
);
|
|
16
|
-
|
|
17
|
-
useEffect(() => {
|
|
18
|
-
localStorage.setItem('studio-user-role', role);
|
|
19
|
-
}, [role]);
|
|
20
|
-
|
|
21
|
-
const setRole = (newRole: UserRole) => {
|
|
22
|
-
setRoleState(newRole);
|
|
23
|
-
};
|
|
24
|
-
|
|
25
|
-
return <AuthContext.Provider value={{ role, setRole }}>{children}</AuthContext.Provider>;
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
export function useAuth() {
|
|
29
|
-
const context = useContext(AuthContext);
|
|
30
|
-
if (!context) {
|
|
31
|
-
throw new Error('useAuth must be used within AuthProvider');
|
|
32
|
-
}
|
|
33
|
-
return context;
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
export function useRole() {
|
|
37
|
-
const { role } = useAuth();
|
|
38
|
-
return role;
|
|
39
|
-
}
|
|
40
|
-
|
|
@@ -1,193 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* @module @kb-labs/studio-app/providers/command-palette-provider
|
|
3
|
-
* Command Palette provider - manages commands and quick search
|
|
4
|
-
*/
|
|
5
|
-
|
|
6
|
-
import * as React from 'react';
|
|
7
|
-
import { useNavigate } from 'react-router-dom';
|
|
8
|
-
import { UIMessage } from '@kb-labs/studio-ui-kit';
|
|
9
|
-
import { useQueryClient } from '@tanstack/react-query';
|
|
10
|
-
import { useDataSources } from './data-sources-provider';
|
|
11
|
-
import { useSettings } from './settings-provider';
|
|
12
|
-
import { getCommands, saveRecentCommand, getRecentCommands } from '@/utils/commands';
|
|
13
|
-
import { KBQuickSearch, type SearchableItem } from '@/components/ui';
|
|
14
|
-
|
|
15
|
-
interface CommandPaletteContextValue {
|
|
16
|
-
/** Open command palette */
|
|
17
|
-
open: () => void;
|
|
18
|
-
/** Close command palette */
|
|
19
|
-
close: () => void;
|
|
20
|
-
/** Toggle command palette */
|
|
21
|
-
toggle: () => void;
|
|
22
|
-
/** Check if palette is open */
|
|
23
|
-
isOpen: boolean;
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
const CommandPaletteContext = React.createContext<CommandPaletteContextValue | undefined>(
|
|
27
|
-
undefined
|
|
28
|
-
);
|
|
29
|
-
|
|
30
|
-
export function CommandPaletteProvider({ children }: { children: React.ReactNode }) {
|
|
31
|
-
const [isOpen, setIsOpen] = React.useState(false);
|
|
32
|
-
const navigate = useNavigate();
|
|
33
|
-
const { settings, updateSettings } = useSettings();
|
|
34
|
-
const queryClient = useQueryClient();
|
|
35
|
-
const refresh = React.useCallback(
|
|
36
|
-
() => queryClient.invalidateQueries({ queryKey: ['studio-registry-v2'] }),
|
|
37
|
-
[queryClient],
|
|
38
|
-
);
|
|
39
|
-
const sources = useDataSources();
|
|
40
|
-
|
|
41
|
-
// Commands configuration
|
|
42
|
-
const allCommands = React.useMemo(
|
|
43
|
-
() =>
|
|
44
|
-
getCommands({
|
|
45
|
-
navigate,
|
|
46
|
-
toggleTheme: () => {
|
|
47
|
-
const currentTheme = settings.appearance.theme;
|
|
48
|
-
const newTheme = currentTheme === 'dark' ? 'light' : 'dark';
|
|
49
|
-
updateSettings({ appearance: { ...settings.appearance, theme: newTheme } });
|
|
50
|
-
UIMessage.success(`Switched to ${newTheme} mode`);
|
|
51
|
-
},
|
|
52
|
-
refreshRegistry: async () => {
|
|
53
|
-
try {
|
|
54
|
-
await refresh();
|
|
55
|
-
UIMessage.success('Registry refreshed successfully');
|
|
56
|
-
} catch (error) {
|
|
57
|
-
UIMessage.error(
|
|
58
|
-
`Failed to refresh registry: ${error instanceof Error ? error.message : String(error)}`
|
|
59
|
-
);
|
|
60
|
-
}
|
|
61
|
-
},
|
|
62
|
-
invalidateCache: async () => {
|
|
63
|
-
try {
|
|
64
|
-
const result = await sources.cache.invalidateCache();
|
|
65
|
-
UIMessage.success(
|
|
66
|
-
`Cache invalidated! Rev: ${result.previousRev ?? 'N/A'} → ${result.newRev}`
|
|
67
|
-
);
|
|
68
|
-
await refresh();
|
|
69
|
-
} catch (error) {
|
|
70
|
-
UIMessage.error(
|
|
71
|
-
`Failed to invalidate cache: ${error instanceof Error ? error.message : String(error)}`
|
|
72
|
-
);
|
|
73
|
-
}
|
|
74
|
-
},
|
|
75
|
-
openQuickSearch: () => {
|
|
76
|
-
setIsOpen(true);
|
|
77
|
-
},
|
|
78
|
-
}),
|
|
79
|
-
[navigate, settings, updateSettings, refresh, sources]
|
|
80
|
-
);
|
|
81
|
-
|
|
82
|
-
// Get recent commands and merge with all commands
|
|
83
|
-
const items = React.useMemo(() => {
|
|
84
|
-
const recentIds = getRecentCommands();
|
|
85
|
-
const recentCommands: SearchableItem[] = [];
|
|
86
|
-
const otherCommands: SearchableItem[] = [];
|
|
87
|
-
|
|
88
|
-
allCommands.forEach((cmd) => {
|
|
89
|
-
const item: SearchableItem = {
|
|
90
|
-
id: cmd.id,
|
|
91
|
-
title: cmd.title,
|
|
92
|
-
description: cmd.description,
|
|
93
|
-
category: cmd.category as SearchableItem['category'],
|
|
94
|
-
path: cmd.path,
|
|
95
|
-
icon: undefined, // Explicitly set to undefined - icons will be rendered based on category
|
|
96
|
-
badge: cmd.shortcut,
|
|
97
|
-
};
|
|
98
|
-
|
|
99
|
-
if (recentIds.includes(cmd.id)) {
|
|
100
|
-
recentCommands.push(item);
|
|
101
|
-
} else {
|
|
102
|
-
otherCommands.push(item);
|
|
103
|
-
}
|
|
104
|
-
});
|
|
105
|
-
|
|
106
|
-
// Sort recent by recency, others by priority
|
|
107
|
-
const sortedRecent = recentCommands.sort(
|
|
108
|
-
(a, b) => recentIds.indexOf(a.id) - recentIds.indexOf(b.id)
|
|
109
|
-
);
|
|
110
|
-
|
|
111
|
-
const sortedOthers = otherCommands.sort((a, b) => {
|
|
112
|
-
const cmdA = allCommands.find((c) => c.id === a.id);
|
|
113
|
-
const cmdB = allCommands.find((c) => c.id === b.id);
|
|
114
|
-
return (cmdB?.priority ?? 0) - (cmdA?.priority ?? 0);
|
|
115
|
-
});
|
|
116
|
-
|
|
117
|
-
return [...sortedRecent, ...sortedOthers];
|
|
118
|
-
}, [allCommands]);
|
|
119
|
-
|
|
120
|
-
// Handle command execution
|
|
121
|
-
const handleNavigate = React.useCallback(
|
|
122
|
-
(path: string) => {
|
|
123
|
-
const command = allCommands.find((cmd) => cmd.path === path);
|
|
124
|
-
if (!command) {return;}
|
|
125
|
-
|
|
126
|
-
// Save to recent
|
|
127
|
-
saveRecentCommand(command.id);
|
|
128
|
-
|
|
129
|
-
// Execute action or navigate
|
|
130
|
-
if (command.action) {
|
|
131
|
-
command.action();
|
|
132
|
-
} else if (command.path) {
|
|
133
|
-
// Handle URL params (e.g., /settings?tab=appearance)
|
|
134
|
-
if (command.path.includes('?')) {
|
|
135
|
-
const [basePath, search] = command.path.split('?');
|
|
136
|
-
navigate({ pathname: basePath, search: `?${search}` });
|
|
137
|
-
} else {
|
|
138
|
-
navigate(command.path);
|
|
139
|
-
}
|
|
140
|
-
}
|
|
141
|
-
|
|
142
|
-
setIsOpen(false);
|
|
143
|
-
},
|
|
144
|
-
[allCommands, navigate]
|
|
145
|
-
);
|
|
146
|
-
|
|
147
|
-
// Keyboard shortcut: Cmd+K / Ctrl+K
|
|
148
|
-
React.useEffect(() => {
|
|
149
|
-
const handleKeyDown = (e: KeyboardEvent) => {
|
|
150
|
-
if ((e.metaKey || e.ctrlKey) && e.key === 'k') {
|
|
151
|
-
e.preventDefault();
|
|
152
|
-
setIsOpen((prev) => !prev);
|
|
153
|
-
}
|
|
154
|
-
};
|
|
155
|
-
|
|
156
|
-
window.addEventListener('keydown', handleKeyDown);
|
|
157
|
-
return () => window.removeEventListener('keydown', handleKeyDown);
|
|
158
|
-
}, []);
|
|
159
|
-
|
|
160
|
-
const value = React.useMemo(
|
|
161
|
-
() => ({
|
|
162
|
-
open: () => setIsOpen(true),
|
|
163
|
-
close: () => setIsOpen(false),
|
|
164
|
-
toggle: () => setIsOpen((prev) => !prev),
|
|
165
|
-
isOpen,
|
|
166
|
-
}),
|
|
167
|
-
[isOpen]
|
|
168
|
-
);
|
|
169
|
-
|
|
170
|
-
return (
|
|
171
|
-
<CommandPaletteContext.Provider value={value}>
|
|
172
|
-
{children}
|
|
173
|
-
<KBQuickSearch
|
|
174
|
-
open={isOpen}
|
|
175
|
-
onClose={() => setIsOpen(false)}
|
|
176
|
-
items={items}
|
|
177
|
-
onNavigate={handleNavigate}
|
|
178
|
-
placeholder="Search pages, run commands..."
|
|
179
|
-
/>
|
|
180
|
-
</CommandPaletteContext.Provider>
|
|
181
|
-
);
|
|
182
|
-
}
|
|
183
|
-
|
|
184
|
-
/**
|
|
185
|
-
* Hook to use command palette
|
|
186
|
-
*/
|
|
187
|
-
export function useCommandPalette() {
|
|
188
|
-
const context = React.useContext(CommandPaletteContext);
|
|
189
|
-
if (!context) {
|
|
190
|
-
throw new Error('useCommandPalette must be used within CommandPaletteProvider');
|
|
191
|
-
}
|
|
192
|
-
return context;
|
|
193
|
-
}
|
|
@@ -1,27 +0,0 @@
|
|
|
1
|
-
import { createContext, useContext, useMemo, type ReactNode } from 'react';
|
|
2
|
-
import { createDataSources, type DataSources } from '@kb-labs/studio-data-client';
|
|
3
|
-
import { studioConfig } from '@/config/studio.config';
|
|
4
|
-
|
|
5
|
-
const DataSourcesContext = createContext<DataSources | null>(null);
|
|
6
|
-
|
|
7
|
-
export function DataSourcesProvider({ children }: { children: ReactNode }) {
|
|
8
|
-
const sources = useMemo(
|
|
9
|
-
() => createDataSources({
|
|
10
|
-
mode: studioConfig.dataSourceMode,
|
|
11
|
-
baseUrl: studioConfig.apiBaseUrl,
|
|
12
|
-
token: studioConfig.gatewayToken,
|
|
13
|
-
}),
|
|
14
|
-
[],
|
|
15
|
-
);
|
|
16
|
-
|
|
17
|
-
return <DataSourcesContext.Provider value={sources}>{children}</DataSourcesContext.Provider>;
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
export function useDataSources() {
|
|
21
|
-
const context = useContext(DataSourcesContext);
|
|
22
|
-
if (!context) {
|
|
23
|
-
throw new Error('useDataSources must be used within DataSourcesProvider');
|
|
24
|
-
}
|
|
25
|
-
return context;
|
|
26
|
-
}
|
|
27
|
-
|
|
@@ -1,72 +0,0 @@
|
|
|
1
|
-
import { useEffect, useRef, type ReactNode } from 'react';
|
|
2
|
-
import { devToolsStore, GenericChannel } from '@kb-labs/studio-devtools';
|
|
3
|
-
import type { DevToolsPlugin, EventBusEvent } from '@kb-labs/studio-devtools';
|
|
4
|
-
import { eventBus } from '@kb-labs/studio-event-bus';
|
|
5
|
-
import { useFeatureFlags } from '@/hooks/use-feature-flags';
|
|
6
|
-
|
|
7
|
-
interface DevToolsProviderProps {
|
|
8
|
-
children: ReactNode;
|
|
9
|
-
/** External plugins to register alongside built-in channels */
|
|
10
|
-
plugins?: DevToolsPlugin[];
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
/**
|
|
14
|
-
* Mounts all DevTools instrumentation when the 'devtools-panel' feature flag is enabled.
|
|
15
|
-
* Must be placed inside SettingsProvider (for feature flags) and outside RegistryV2Provider
|
|
16
|
-
* (so MF events from registry load are captured).
|
|
17
|
-
*/
|
|
18
|
-
export function DevToolsProvider({ children, plugins = [] }: DevToolsProviderProps) {
|
|
19
|
-
const { isEnabled } = useFeatureFlags();
|
|
20
|
-
const enabled = isEnabled('devtools-panel');
|
|
21
|
-
const pluginsRef = useRef(plugins);
|
|
22
|
-
pluginsRef.current = plugins;
|
|
23
|
-
|
|
24
|
-
useEffect(() => {
|
|
25
|
-
if (!enabled) { return; }
|
|
26
|
-
|
|
27
|
-
// --- EventBus channel ---
|
|
28
|
-
const eventBusChannel = new GenericChannel<EventBusEvent>(
|
|
29
|
-
'eventbus',
|
|
30
|
-
'EventBus',
|
|
31
|
-
'NodeIndexOutlined',
|
|
32
|
-
);
|
|
33
|
-
devToolsStore.registerChannel(eventBusChannel);
|
|
34
|
-
|
|
35
|
-
// Backfill existing history
|
|
36
|
-
eventBus.getHistory().forEach((record) => {
|
|
37
|
-
eventBusChannel.push({
|
|
38
|
-
id: `eb-${record.meta.timestamp}-${Math.random().toString(36).slice(2)}`,
|
|
39
|
-
event: record.event,
|
|
40
|
-
payload: record.payload,
|
|
41
|
-
sourcePluginId: record.meta.sourcePluginId,
|
|
42
|
-
sourcePageId: record.meta.sourcePageId,
|
|
43
|
-
timestamp: record.meta.timestamp,
|
|
44
|
-
});
|
|
45
|
-
});
|
|
46
|
-
|
|
47
|
-
// Live stream
|
|
48
|
-
eventBus.setDevToolsObserver((record) => {
|
|
49
|
-
eventBusChannel.push({
|
|
50
|
-
id: `eb-${record.meta.timestamp}-${Math.random().toString(36).slice(2)}`,
|
|
51
|
-
event: record.event,
|
|
52
|
-
payload: record.payload,
|
|
53
|
-
sourcePluginId: record.meta.sourcePluginId,
|
|
54
|
-
sourcePageId: record.meta.sourcePageId,
|
|
55
|
-
timestamp: record.meta.timestamp,
|
|
56
|
-
});
|
|
57
|
-
});
|
|
58
|
-
|
|
59
|
-
// --- External plugins ---
|
|
60
|
-
pluginsRef.current.forEach((p) => { devToolsStore.registerPlugin(p); });
|
|
61
|
-
|
|
62
|
-
return () => {
|
|
63
|
-
eventBus.clearDevToolsObserver();
|
|
64
|
-
devToolsStore.unregisterChannel('eventbus');
|
|
65
|
-
pluginsRef.current.forEach((p) => {
|
|
66
|
-
devToolsStore.unregisterChannel(p.channel.id);
|
|
67
|
-
});
|
|
68
|
-
};
|
|
69
|
-
}, [enabled]);
|
|
70
|
-
|
|
71
|
-
return <>{children}</>;
|
|
72
|
-
}
|
|
@@ -1,38 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* @module @kb-labs/studio-app/providers/navigation-items-provider
|
|
3
|
-
* Provides the list of available sidebar navigation items to settings UI.
|
|
4
|
-
* Single source of truth — no hardcoded item lists.
|
|
5
|
-
*/
|
|
6
|
-
|
|
7
|
-
import * as React from 'react';
|
|
8
|
-
|
|
9
|
-
export interface NavigationItemDescriptor {
|
|
10
|
-
key: string;
|
|
11
|
-
label: string;
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
interface NavigationItemsContextValue {
|
|
15
|
-
availableItems: NavigationItemDescriptor[];
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
const NavigationItemsContext = React.createContext<NavigationItemsContextValue>({
|
|
19
|
-
availableItems: [],
|
|
20
|
-
});
|
|
21
|
-
|
|
22
|
-
export interface NavigationItemsProviderProps {
|
|
23
|
-
items: NavigationItemDescriptor[];
|
|
24
|
-
children: React.ReactNode;
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
export function NavigationItemsProvider({ items, children }: NavigationItemsProviderProps) {
|
|
28
|
-
const value = React.useMemo(() => ({ availableItems: items }), [items]);
|
|
29
|
-
return (
|
|
30
|
-
<NavigationItemsContext.Provider value={value}>
|
|
31
|
-
{children}
|
|
32
|
-
</NavigationItemsContext.Provider>
|
|
33
|
-
);
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
export function useNavigationItems(): NavigationItemDescriptor[] {
|
|
37
|
-
return React.useContext(NavigationItemsContext).availableItems;
|
|
38
|
-
}
|