@kb-labs/studio-app 0.6.0 → 2.8.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.1d68e922.js +522 -0
- package/dist/main.1d68e922.js.map +1 -0
- package/dist/main.80b70197.css +2 -0
- package/dist/main.80b70197.css.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/utils/analytics.ts
DELETED
|
@@ -1,183 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* @module @kb-labs/studio-app/utils/analytics
|
|
3
|
-
* Analytics helpers for widget events, page views, and performance tracking
|
|
4
|
-
*/
|
|
5
|
-
|
|
6
|
-
import { createStudioLogger } from './logger';
|
|
7
|
-
|
|
8
|
-
const analyticsLogger = createStudioLogger('analytics');
|
|
9
|
-
|
|
10
|
-
/**
|
|
11
|
-
* Analytics configuration
|
|
12
|
-
*/
|
|
13
|
-
export interface AnalyticsConfig {
|
|
14
|
-
enabled: boolean;
|
|
15
|
-
trackPageViews: boolean;
|
|
16
|
-
trackWidgetEvents: boolean;
|
|
17
|
-
trackPerformance: boolean;
|
|
18
|
-
trackErrors: boolean;
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
let analyticsConfig: AnalyticsConfig = {
|
|
22
|
-
enabled: true,
|
|
23
|
-
trackPageViews: true,
|
|
24
|
-
trackWidgetEvents: true,
|
|
25
|
-
trackPerformance: true,
|
|
26
|
-
trackErrors: true,
|
|
27
|
-
};
|
|
28
|
-
|
|
29
|
-
/**
|
|
30
|
-
* Set analytics configuration
|
|
31
|
-
*/
|
|
32
|
-
export function setAnalyticsConfig(config: Partial<AnalyticsConfig>): void {
|
|
33
|
-
analyticsConfig = { ...analyticsConfig, ...config };
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
/**
|
|
37
|
-
* Get analytics configuration
|
|
38
|
-
*/
|
|
39
|
-
export function getAnalyticsConfig(): AnalyticsConfig {
|
|
40
|
-
return { ...analyticsConfig };
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
/**
|
|
44
|
-
* Widget event types
|
|
45
|
-
*/
|
|
46
|
-
export type WidgetEventType =
|
|
47
|
-
| 'mounted'
|
|
48
|
-
| 'error'
|
|
49
|
-
| 'interaction'
|
|
50
|
-
| 'data-loaded'
|
|
51
|
-
| 'data-error'
|
|
52
|
-
| 'export'
|
|
53
|
-
| 'refresh';
|
|
54
|
-
|
|
55
|
-
/**
|
|
56
|
-
* Track widget event
|
|
57
|
-
* Fire-and-forget, analytics failures should not break execution
|
|
58
|
-
*/
|
|
59
|
-
export function trackWidgetEvent(
|
|
60
|
-
event: WidgetEventType,
|
|
61
|
-
data: {
|
|
62
|
-
widgetId: string;
|
|
63
|
-
pluginId: string;
|
|
64
|
-
code?: string;
|
|
65
|
-
event?: string;
|
|
66
|
-
duration?: number;
|
|
67
|
-
exportFormat?: string;
|
|
68
|
-
}
|
|
69
|
-
): void {
|
|
70
|
-
if (!analyticsConfig.enabled || !analyticsConfig.trackWidgetEvents) {
|
|
71
|
-
return;
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
try {
|
|
75
|
-
// TODO: Integrate with @kb-labs/analytics-sdk-node
|
|
76
|
-
// For now, just log
|
|
77
|
-
analyticsLogger.info('Widget analytic event', {
|
|
78
|
-
event,
|
|
79
|
-
...data,
|
|
80
|
-
timestamp: new Date().toISOString(),
|
|
81
|
-
});
|
|
82
|
-
} catch (e) {
|
|
83
|
-
// Silently fail - analytics should not break execution
|
|
84
|
-
analyticsLogger.warn('Failed to track widget event', {
|
|
85
|
-
event,
|
|
86
|
-
data,
|
|
87
|
-
error: e instanceof Error ? e.message : String(e),
|
|
88
|
-
});
|
|
89
|
-
}
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
/**
|
|
93
|
-
* Track page view
|
|
94
|
-
*/
|
|
95
|
-
export function trackPageView(data: {
|
|
96
|
-
path: string;
|
|
97
|
-
title?: string;
|
|
98
|
-
layoutId?: string;
|
|
99
|
-
pluginId?: string;
|
|
100
|
-
}): void {
|
|
101
|
-
if (!analyticsConfig.enabled || !analyticsConfig.trackPageViews) {
|
|
102
|
-
return;
|
|
103
|
-
}
|
|
104
|
-
|
|
105
|
-
try {
|
|
106
|
-
analyticsLogger.info('Page view', {
|
|
107
|
-
...data,
|
|
108
|
-
timestamp: new Date().toISOString(),
|
|
109
|
-
});
|
|
110
|
-
} catch (e) {
|
|
111
|
-
// Silently fail
|
|
112
|
-
analyticsLogger.warn('Failed to track page view', {
|
|
113
|
-
data,
|
|
114
|
-
error: e instanceof Error ? e.message : String(e),
|
|
115
|
-
});
|
|
116
|
-
}
|
|
117
|
-
}
|
|
118
|
-
|
|
119
|
-
/**
|
|
120
|
-
* Track performance metric
|
|
121
|
-
*/
|
|
122
|
-
export function trackPerformance(data: {
|
|
123
|
-
metric: string;
|
|
124
|
-
value: number;
|
|
125
|
-
unit?: string;
|
|
126
|
-
widgetId?: string;
|
|
127
|
-
pluginId?: string;
|
|
128
|
-
}): void {
|
|
129
|
-
if (!analyticsConfig.enabled || !analyticsConfig.trackPerformance) {
|
|
130
|
-
return;
|
|
131
|
-
}
|
|
132
|
-
|
|
133
|
-
try {
|
|
134
|
-
analyticsLogger.info('Performance metric', {
|
|
135
|
-
...data,
|
|
136
|
-
timestamp: new Date().toISOString(),
|
|
137
|
-
});
|
|
138
|
-
} catch (e) {
|
|
139
|
-
// Silently fail
|
|
140
|
-
analyticsLogger.warn('Failed to track performance', {
|
|
141
|
-
data,
|
|
142
|
-
error: e instanceof Error ? e.message : String(e),
|
|
143
|
-
});
|
|
144
|
-
}
|
|
145
|
-
}
|
|
146
|
-
|
|
147
|
-
/**
|
|
148
|
-
* Track error
|
|
149
|
-
*/
|
|
150
|
-
export function trackError(data: {
|
|
151
|
-
error: Error | string;
|
|
152
|
-
context?: string;
|
|
153
|
-
widgetId?: string;
|
|
154
|
-
pluginId?: string;
|
|
155
|
-
metadata?: Record<string, unknown>;
|
|
156
|
-
}): void {
|
|
157
|
-
if (!analyticsConfig.enabled || !analyticsConfig.trackErrors) {
|
|
158
|
-
return;
|
|
159
|
-
}
|
|
160
|
-
|
|
161
|
-
try {
|
|
162
|
-
const errorMessage = data.error instanceof Error ? data.error.message : data.error;
|
|
163
|
-
const errorStack = data.error instanceof Error ? data.error.stack : undefined;
|
|
164
|
-
|
|
165
|
-
analyticsLogger.error('Error tracked', {
|
|
166
|
-
error: errorMessage,
|
|
167
|
-
stack: errorStack,
|
|
168
|
-
context: data.context,
|
|
169
|
-
widgetId: data.widgetId,
|
|
170
|
-
pluginId: data.pluginId,
|
|
171
|
-
metadata: data.metadata,
|
|
172
|
-
timestamp: new Date().toISOString(),
|
|
173
|
-
});
|
|
174
|
-
} catch (e) {
|
|
175
|
-
// Silently fail
|
|
176
|
-
analyticsLogger.warn('Failed to track error', {
|
|
177
|
-
data,
|
|
178
|
-
error: e instanceof Error ? e.message : String(e),
|
|
179
|
-
});
|
|
180
|
-
}
|
|
181
|
-
}
|
|
182
|
-
|
|
183
|
-
|
|
@@ -1,83 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* @module @kb-labs/studio-app/utils/apply-navigation-categories
|
|
3
|
-
* Pure transform: flat NavigationItem[] + user categories → grouped NavigationItem[]
|
|
4
|
-
*/
|
|
5
|
-
|
|
6
|
-
import type { NavigationCategory } from '../providers/settings-provider';
|
|
7
|
-
import type { NavigationItem } from '@/components/ui';
|
|
8
|
-
|
|
9
|
-
const PROTECTED_KEYS = new Set(['settings']);
|
|
10
|
-
|
|
11
|
-
/**
|
|
12
|
-
* Apply user's category configuration to the flat navigation items list.
|
|
13
|
-
*
|
|
14
|
-
* - Items assigned to a category are grouped under that category's header
|
|
15
|
-
* - Items not assigned to any category remain as top-level items (original order)
|
|
16
|
-
* - Categories sorted by `order` field
|
|
17
|
-
* - "settings" is protected — always last, never categorized
|
|
18
|
-
* - Missing keys (removed plugin/module) are silently skipped
|
|
19
|
-
* - Empty categories (all items removed) are omitted
|
|
20
|
-
*/
|
|
21
|
-
export function applyNavigationCategories(
|
|
22
|
-
items: NavigationItem[],
|
|
23
|
-
categories: NavigationCategory[],
|
|
24
|
-
): NavigationItem[] {
|
|
25
|
-
if (categories.length === 0) {
|
|
26
|
-
return items;
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
// Collect all keys assigned to any category
|
|
30
|
-
const assignedKeys = new Set<string>();
|
|
31
|
-
for (const cat of categories) {
|
|
32
|
-
for (const key of cat.itemKeys) {
|
|
33
|
-
assignedKeys.add(key);
|
|
34
|
-
}
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
// Map key → item for quick lookup
|
|
38
|
-
const itemsByKey = new Map<string, NavigationItem>();
|
|
39
|
-
for (const item of items) {
|
|
40
|
-
itemsByKey.set(item.key, item);
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
const result: NavigationItem[] = [];
|
|
44
|
-
|
|
45
|
-
// 1. Uncategorized items in original order (except protected)
|
|
46
|
-
for (const item of items) {
|
|
47
|
-
if (!assignedKeys.has(item.key) && !PROTECTED_KEYS.has(item.key)) {
|
|
48
|
-
result.push(item);
|
|
49
|
-
}
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
// 2. Categories sorted by order
|
|
53
|
-
const sortedCategories = [...categories].sort((a, b) => a.order - b.order);
|
|
54
|
-
for (const cat of sortedCategories) {
|
|
55
|
-
const groupChildren: NavigationItem[] = [];
|
|
56
|
-
for (const key of cat.itemKeys) {
|
|
57
|
-
const item = itemsByKey.get(key);
|
|
58
|
-
if (item && !PROTECTED_KEYS.has(key)) {
|
|
59
|
-
groupChildren.push(item);
|
|
60
|
-
}
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
if (groupChildren.length > 0) {
|
|
64
|
-
result.push({
|
|
65
|
-
key: `category-${cat.id}`,
|
|
66
|
-
label: cat.label,
|
|
67
|
-
type: 'group',
|
|
68
|
-
children: groupChildren,
|
|
69
|
-
});
|
|
70
|
-
}
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
// 3. Divider + protected items last (settings)
|
|
74
|
-
const protectedItems = items.filter(item => PROTECTED_KEYS.has(item.key));
|
|
75
|
-
if (protectedItems.length > 0) {
|
|
76
|
-
result.push({ key: '__settings-divider', label: '', type: 'divider' });
|
|
77
|
-
for (const item of protectedItems) {
|
|
78
|
-
result.push(item);
|
|
79
|
-
}
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
return result;
|
|
83
|
-
}
|
package/src/utils/commands.ts
DELETED
|
@@ -1,252 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* @module @kb-labs/studio-app/utils/commands
|
|
3
|
-
* Centralized command registry for Command Palette
|
|
4
|
-
*/
|
|
5
|
-
|
|
6
|
-
export type CommandCategory = 'recent' | 'navigation' | 'action' | 'plugin' | 'widget' | 'setting';
|
|
7
|
-
|
|
8
|
-
export interface Command {
|
|
9
|
-
id: string;
|
|
10
|
-
title: string;
|
|
11
|
-
description?: string;
|
|
12
|
-
category: CommandCategory;
|
|
13
|
-
path: string;
|
|
14
|
-
/** Action to execute (alternative to path for navigation) */
|
|
15
|
-
action?: () => void | Promise<void>;
|
|
16
|
-
/** Keyboard shortcut */
|
|
17
|
-
shortcut?: string;
|
|
18
|
-
/** Tags for better search */
|
|
19
|
-
tags?: string[];
|
|
20
|
-
/** Priority for sorting (higher = shown first) */
|
|
21
|
-
priority?: number;
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
export interface CommandsConfig {
|
|
25
|
-
navigate: (path: string) => void;
|
|
26
|
-
toggleTheme: () => void;
|
|
27
|
-
refreshRegistry: () => Promise<void>;
|
|
28
|
-
invalidateCache: () => Promise<void>;
|
|
29
|
-
openQuickSearch: () => void;
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
/**
|
|
33
|
-
* Get all available commands for Command Palette
|
|
34
|
-
*/
|
|
35
|
-
export function getCommands(config: CommandsConfig): Command[] {
|
|
36
|
-
const { toggleTheme, refreshRegistry, invalidateCache, openQuickSearch } = config;
|
|
37
|
-
|
|
38
|
-
return [
|
|
39
|
-
// ============================================
|
|
40
|
-
// NAVIGATION COMMANDS
|
|
41
|
-
// ============================================
|
|
42
|
-
{
|
|
43
|
-
id: 'nav-dashboard',
|
|
44
|
-
title: 'Go to Dashboard',
|
|
45
|
-
description: 'View main dashboard',
|
|
46
|
-
category: 'navigation' as const,
|
|
47
|
-
path: '/',
|
|
48
|
-
tags: ['home', 'main', 'overview'],
|
|
49
|
-
priority: 100,
|
|
50
|
-
},
|
|
51
|
-
{
|
|
52
|
-
id: 'nav-observability',
|
|
53
|
-
title: 'Go to Observability',
|
|
54
|
-
description: 'View system observability',
|
|
55
|
-
category: 'navigation' as const,
|
|
56
|
-
path: '/observability',
|
|
57
|
-
tags: ['monitoring', 'metrics', 'logs'],
|
|
58
|
-
priority: 90,
|
|
59
|
-
},
|
|
60
|
-
{
|
|
61
|
-
id: 'nav-observability-events',
|
|
62
|
-
title: 'Go to System Events',
|
|
63
|
-
description: 'View system event log',
|
|
64
|
-
category: 'navigation' as const,
|
|
65
|
-
path: '/observability/system-events',
|
|
66
|
-
tags: ['events', 'logs', 'history'],
|
|
67
|
-
priority: 85,
|
|
68
|
-
},
|
|
69
|
-
{
|
|
70
|
-
id: 'nav-observability-registry',
|
|
71
|
-
title: 'Go to Registry Browser',
|
|
72
|
-
description: 'Browse plugin registry',
|
|
73
|
-
category: 'navigation' as const,
|
|
74
|
-
path: '/observability/registry',
|
|
75
|
-
tags: ['plugins', 'registry', 'browse'],
|
|
76
|
-
priority: 80,
|
|
77
|
-
},
|
|
78
|
-
{
|
|
79
|
-
id: 'nav-settings',
|
|
80
|
-
title: 'Go to Settings',
|
|
81
|
-
description: 'Configure application settings',
|
|
82
|
-
category: 'navigation' as const,
|
|
83
|
-
path: '/settings',
|
|
84
|
-
tags: ['preferences', 'config', 'configuration'],
|
|
85
|
-
shortcut: 'Cmd+,',
|
|
86
|
-
priority: 95,
|
|
87
|
-
},
|
|
88
|
-
{
|
|
89
|
-
id: 'nav-settings-appearance',
|
|
90
|
-
title: 'Go to Appearance Settings',
|
|
91
|
-
description: 'Change theme and appearance',
|
|
92
|
-
category: 'navigation' as const,
|
|
93
|
-
path: '/settings?tab=appearance',
|
|
94
|
-
tags: ['theme', 'dark mode', 'colors'],
|
|
95
|
-
priority: 70,
|
|
96
|
-
},
|
|
97
|
-
{
|
|
98
|
-
id: 'nav-settings-experimental',
|
|
99
|
-
title: 'Go to Experimental Features',
|
|
100
|
-
description: 'Enable experimental features',
|
|
101
|
-
category: 'navigation' as const,
|
|
102
|
-
path: '/settings?tab=experimental',
|
|
103
|
-
tags: ['features', 'flags', 'beta'],
|
|
104
|
-
priority: 65,
|
|
105
|
-
},
|
|
106
|
-
{
|
|
107
|
-
id: 'nav-settings-developer',
|
|
108
|
-
title: 'Go to Developer Tools',
|
|
109
|
-
description: 'Developer settings and tools',
|
|
110
|
-
category: 'navigation' as const,
|
|
111
|
-
path: '/settings?tab=developer',
|
|
112
|
-
tags: ['dev', 'debug', 'tools'],
|
|
113
|
-
priority: 60,
|
|
114
|
-
},
|
|
115
|
-
|
|
116
|
-
// ============================================
|
|
117
|
-
// ACTION COMMANDS
|
|
118
|
-
// ============================================
|
|
119
|
-
{
|
|
120
|
-
id: 'action-toggle-theme',
|
|
121
|
-
title: 'Toggle Dark Mode',
|
|
122
|
-
description: 'Switch between light and dark theme',
|
|
123
|
-
category: 'action' as const,
|
|
124
|
-
path: '',
|
|
125
|
-
action: toggleTheme,
|
|
126
|
-
tags: ['theme', 'dark', 'light', 'appearance'],
|
|
127
|
-
shortcut: 'Cmd+Shift+T',
|
|
128
|
-
priority: 90,
|
|
129
|
-
},
|
|
130
|
-
{
|
|
131
|
-
id: 'action-refresh-registry',
|
|
132
|
-
title: 'Refresh Registry',
|
|
133
|
-
description: 'Fetch latest registry data',
|
|
134
|
-
category: 'action' as const,
|
|
135
|
-
path: '',
|
|
136
|
-
action: refreshRegistry,
|
|
137
|
-
tags: ['refresh', 'reload', 'update'],
|
|
138
|
-
shortcut: 'Cmd+R',
|
|
139
|
-
priority: 85,
|
|
140
|
-
},
|
|
141
|
-
{
|
|
142
|
-
id: 'action-invalidate-cache',
|
|
143
|
-
title: 'Invalidate Cache & Re-discover',
|
|
144
|
-
description: 'Force full plugin re-discovery',
|
|
145
|
-
category: 'action' as const,
|
|
146
|
-
path: '',
|
|
147
|
-
action: invalidateCache,
|
|
148
|
-
tags: ['cache', 'clear', 'discover', 'plugins'],
|
|
149
|
-
priority: 80,
|
|
150
|
-
},
|
|
151
|
-
{
|
|
152
|
-
id: 'action-quick-search',
|
|
153
|
-
title: 'Open Quick Search',
|
|
154
|
-
description: 'Search pages and plugins',
|
|
155
|
-
category: 'action' as const,
|
|
156
|
-
path: '',
|
|
157
|
-
action: openQuickSearch,
|
|
158
|
-
tags: ['search', 'find'],
|
|
159
|
-
shortcut: 'Cmd+K',
|
|
160
|
-
priority: 100,
|
|
161
|
-
},
|
|
162
|
-
{
|
|
163
|
-
id: 'action-copy-registry-url',
|
|
164
|
-
title: 'Copy Registry URL',
|
|
165
|
-
description: 'Copy REST API registry endpoint',
|
|
166
|
-
category: 'action' as const,
|
|
167
|
-
path: '',
|
|
168
|
-
action: () => {
|
|
169
|
-
const url = `${window.location.origin}/api/v1/registry`;
|
|
170
|
-
navigator.clipboard.writeText(url);
|
|
171
|
-
},
|
|
172
|
-
tags: ['copy', 'url', 'api'],
|
|
173
|
-
priority: 50,
|
|
174
|
-
},
|
|
175
|
-
|
|
176
|
-
// ============================================
|
|
177
|
-
// SETTING COMMANDS
|
|
178
|
-
// ============================================
|
|
179
|
-
{
|
|
180
|
-
id: 'setting-appearance',
|
|
181
|
-
title: 'Appearance Settings',
|
|
182
|
-
description: 'Theme, colors, and visual preferences',
|
|
183
|
-
category: 'setting' as const,
|
|
184
|
-
path: '/settings?tab=appearance',
|
|
185
|
-
tags: ['theme', 'dark mode', 'colors', 'visual'],
|
|
186
|
-
priority: 70,
|
|
187
|
-
},
|
|
188
|
-
{
|
|
189
|
-
id: 'setting-privacy',
|
|
190
|
-
title: 'Data & Privacy Settings',
|
|
191
|
-
description: 'Privacy and data management',
|
|
192
|
-
category: 'setting' as const,
|
|
193
|
-
path: '/settings?tab=privacy',
|
|
194
|
-
tags: ['privacy', 'data', 'security'],
|
|
195
|
-
priority: 65,
|
|
196
|
-
},
|
|
197
|
-
{
|
|
198
|
-
id: 'setting-system',
|
|
199
|
-
title: 'System Information',
|
|
200
|
-
description: 'View system health and status',
|
|
201
|
-
category: 'setting' as const,
|
|
202
|
-
path: '/settings?tab=system',
|
|
203
|
-
tags: ['health', 'status', 'info'],
|
|
204
|
-
priority: 60,
|
|
205
|
-
},
|
|
206
|
-
{
|
|
207
|
-
id: 'setting-developer',
|
|
208
|
-
title: 'Developer Settings',
|
|
209
|
-
description: 'Development tools and debugging',
|
|
210
|
-
category: 'setting' as const,
|
|
211
|
-
path: '/settings?tab=developer',
|
|
212
|
-
tags: ['dev', 'debug', 'tools'],
|
|
213
|
-
priority: 55,
|
|
214
|
-
},
|
|
215
|
-
];
|
|
216
|
-
}
|
|
217
|
-
|
|
218
|
-
/**
|
|
219
|
-
* Get recent commands from localStorage
|
|
220
|
-
*/
|
|
221
|
-
export function getRecentCommands(): string[] {
|
|
222
|
-
try {
|
|
223
|
-
const stored = localStorage.getItem('kb-recent-commands');
|
|
224
|
-
return stored ? JSON.parse(stored) : [];
|
|
225
|
-
} catch {
|
|
226
|
-
return [];
|
|
227
|
-
}
|
|
228
|
-
}
|
|
229
|
-
|
|
230
|
-
/**
|
|
231
|
-
* Save command to recent history
|
|
232
|
-
*/
|
|
233
|
-
export function saveRecentCommand(commandId: string): void {
|
|
234
|
-
try {
|
|
235
|
-
const recent = getRecentCommands();
|
|
236
|
-
const updated = [commandId, ...recent.filter((id) => id !== commandId)].slice(0, 5);
|
|
237
|
-
localStorage.setItem('kb-recent-commands', JSON.stringify(updated));
|
|
238
|
-
} catch (error) {
|
|
239
|
-
console.error('Failed to save recent command:', error);
|
|
240
|
-
}
|
|
241
|
-
}
|
|
242
|
-
|
|
243
|
-
/**
|
|
244
|
-
* Clear recent commands history
|
|
245
|
-
*/
|
|
246
|
-
export function clearRecentCommands(): void {
|
|
247
|
-
try {
|
|
248
|
-
localStorage.removeItem('kb-recent-commands');
|
|
249
|
-
} catch (error) {
|
|
250
|
-
console.error('Failed to clear recent commands:', error);
|
|
251
|
-
}
|
|
252
|
-
}
|
package/src/utils/export.ts
DELETED
|
@@ -1,174 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* @module @kb-labs/studio-app/utils/export
|
|
3
|
-
* Export utilities for widget data (CSV, JSON, PNG)
|
|
4
|
-
*/
|
|
5
|
-
|
|
6
|
-
/**
|
|
7
|
-
* Export data to CSV format
|
|
8
|
-
*/
|
|
9
|
-
export function exportToCSV(
|
|
10
|
-
data: unknown[],
|
|
11
|
-
filename: string = 'export.csv',
|
|
12
|
-
options?: {
|
|
13
|
-
headers?: string[];
|
|
14
|
-
delimiter?: string;
|
|
15
|
-
}
|
|
16
|
-
): void {
|
|
17
|
-
if (!data || data.length === 0) {
|
|
18
|
-
console.warn('No data to export');
|
|
19
|
-
return;
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
const delimiter = options?.delimiter || ',';
|
|
23
|
-
const rows: string[] = [];
|
|
24
|
-
|
|
25
|
-
// Get headers
|
|
26
|
-
let headers: string[] = [];
|
|
27
|
-
if (options?.headers && options.headers.length > 0) {
|
|
28
|
-
headers = options.headers;
|
|
29
|
-
} else if (data.length > 0) {
|
|
30
|
-
// Auto-detect headers from first object
|
|
31
|
-
const firstItem = data[0];
|
|
32
|
-
if (typeof firstItem === 'object' && firstItem !== null) {
|
|
33
|
-
headers = Object.keys(firstItem as Record<string, unknown>);
|
|
34
|
-
}
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
// Add header row
|
|
38
|
-
if (headers.length > 0) {
|
|
39
|
-
rows.push(headers.map((h) => escapeCSVValue(h)).join(delimiter));
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
// Add data rows
|
|
43
|
-
for (const item of data) {
|
|
44
|
-
if (typeof item === 'object' && item !== null) {
|
|
45
|
-
const values = headers.map((header) => {
|
|
46
|
-
const value = (item as Record<string, unknown>)[header];
|
|
47
|
-
return escapeCSVValue(value);
|
|
48
|
-
});
|
|
49
|
-
rows.push(values.join(delimiter));
|
|
50
|
-
} else {
|
|
51
|
-
rows.push(escapeCSVValue(item));
|
|
52
|
-
}
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
// Create blob and download
|
|
56
|
-
const csvContent = rows.join('\n');
|
|
57
|
-
const blob = new Blob([csvContent], { type: 'text/csv;charset=utf-8;' });
|
|
58
|
-
downloadBlob(blob, filename);
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
/**
|
|
62
|
-
* Export data to JSON format
|
|
63
|
-
*/
|
|
64
|
-
export function exportToJSON(
|
|
65
|
-
data: unknown,
|
|
66
|
-
filename: string = 'export.json',
|
|
67
|
-
options?: {
|
|
68
|
-
pretty?: boolean;
|
|
69
|
-
}
|
|
70
|
-
): void {
|
|
71
|
-
const jsonContent = options?.pretty
|
|
72
|
-
? JSON.stringify(data, null, 2)
|
|
73
|
-
: JSON.stringify(data);
|
|
74
|
-
|
|
75
|
-
const blob = new Blob([jsonContent], { type: 'application/json;charset=utf-8;' });
|
|
76
|
-
downloadBlob(blob, filename);
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
/**
|
|
80
|
-
* Export chart/canvas to PNG
|
|
81
|
-
*/
|
|
82
|
-
export function exportToPNG(
|
|
83
|
-
element: HTMLElement | HTMLCanvasElement,
|
|
84
|
-
filename: string = 'export.png',
|
|
85
|
-
options?: {
|
|
86
|
-
backgroundColor?: string;
|
|
87
|
-
scale?: number;
|
|
88
|
-
}
|
|
89
|
-
): void {
|
|
90
|
-
let canvas: HTMLCanvasElement;
|
|
91
|
-
|
|
92
|
-
if (element instanceof HTMLCanvasElement) {
|
|
93
|
-
canvas = element;
|
|
94
|
-
} else {
|
|
95
|
-
// Try to find canvas inside element
|
|
96
|
-
const canvasElement = element.querySelector('canvas');
|
|
97
|
-
if (!canvasElement) {
|
|
98
|
-
console.error('No canvas element found for PNG export');
|
|
99
|
-
return;
|
|
100
|
-
}
|
|
101
|
-
canvas = canvasElement;
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
// Create a new canvas for export
|
|
105
|
-
const exportCanvas = document.createElement('canvas');
|
|
106
|
-
const scale = options?.scale || 2; // Higher scale for better quality
|
|
107
|
-
exportCanvas.width = canvas.width * scale;
|
|
108
|
-
exportCanvas.height = canvas.height * scale;
|
|
109
|
-
|
|
110
|
-
const ctx = exportCanvas.getContext('2d');
|
|
111
|
-
if (!ctx) {
|
|
112
|
-
console.error('Failed to get canvas context');
|
|
113
|
-
return;
|
|
114
|
-
}
|
|
115
|
-
|
|
116
|
-
// Fill background if specified
|
|
117
|
-
if (options?.backgroundColor) {
|
|
118
|
-
ctx.fillStyle = options.backgroundColor;
|
|
119
|
-
ctx.fillRect(0, 0, exportCanvas.width, exportCanvas.height);
|
|
120
|
-
}
|
|
121
|
-
|
|
122
|
-
// Draw original canvas scaled up
|
|
123
|
-
ctx.drawImage(canvas, 0, 0, exportCanvas.width, exportCanvas.height);
|
|
124
|
-
|
|
125
|
-
// Convert to blob and download
|
|
126
|
-
exportCanvas.toBlob((blob) => {
|
|
127
|
-
if (blob) {
|
|
128
|
-
downloadBlob(blob, filename);
|
|
129
|
-
} else {
|
|
130
|
-
console.error('Failed to create PNG blob');
|
|
131
|
-
}
|
|
132
|
-
}, 'image/png');
|
|
133
|
-
}
|
|
134
|
-
|
|
135
|
-
/**
|
|
136
|
-
* Escape CSV value (handle commas, quotes, newlines)
|
|
137
|
-
*/
|
|
138
|
-
function escapeCSVValue(value: unknown): string {
|
|
139
|
-
if (value === null || value === undefined) {
|
|
140
|
-
return '';
|
|
141
|
-
}
|
|
142
|
-
|
|
143
|
-
const str = String(value);
|
|
144
|
-
|
|
145
|
-
// If value contains delimiter, quote, or newline, wrap in quotes and escape quotes
|
|
146
|
-
if (str.includes(',') || str.includes('"') || str.includes('\n') || str.includes('\r')) {
|
|
147
|
-
return `"${str.replace(/"/g, '""')}"`;
|
|
148
|
-
}
|
|
149
|
-
|
|
150
|
-
return str;
|
|
151
|
-
}
|
|
152
|
-
|
|
153
|
-
/**
|
|
154
|
-
* Download blob as file
|
|
155
|
-
*/
|
|
156
|
-
function downloadBlob(blob: Blob, filename: string): void {
|
|
157
|
-
const url = URL.createObjectURL(blob);
|
|
158
|
-
const link = document.createElement('a');
|
|
159
|
-
link.href = url;
|
|
160
|
-
link.download = filename;
|
|
161
|
-
document.body.appendChild(link);
|
|
162
|
-
link.click();
|
|
163
|
-
document.body.removeChild(link);
|
|
164
|
-
URL.revokeObjectURL(url);
|
|
165
|
-
}
|
|
166
|
-
|
|
167
|
-
/**
|
|
168
|
-
* Generate filename with timestamp
|
|
169
|
-
*/
|
|
170
|
-
export function generateFilename(prefix: string, extension: string): string {
|
|
171
|
-
const timestamp = new Date().toISOString().replace(/[:.]/g, '-').slice(0, -5);
|
|
172
|
-
return `${prefix}-${timestamp}.${extension}`;
|
|
173
|
-
}
|
|
174
|
-
|