- Add type-to-trigger Spotlight with keyboard (any character) - Add canvas click to open Spotlight - Implement keyboard navigation (↑↓ Enter Esc) - Add keyboard shortcut handlers and spotlight store - Create useSpotlight hook with fuzzy search - Create mock Kubernetes resources for initial testing - Implement krate creation with collision detection - Add Quick Actions (all pods, services, deployments, namespaces) - Create Spotlight with filter chips and result rendering - Add Spotlight state management with setQuery, setFilter, setSel - Include design specs (Krates.dc.html, server.js, support.js)
136 lines
3.5 KiB
TypeScript
136 lines
3.5 KiB
TypeScript
import { useMemo } from 'react'
|
|
import { fuzzySearch } from '../utils/fuzzy'
|
|
import { MOCK_NAMESPACES, MOCK_PODS, MOCK_DEPLOYMENTS, MOCK_SERVICES } from '../data/mockResources'
|
|
|
|
export interface SpotlightResource {
|
|
id: string
|
|
type: string
|
|
name: string
|
|
namespace?: string
|
|
status?: string
|
|
color: string
|
|
}
|
|
|
|
export const useSpotlight = () => {
|
|
const executeSearch = (query: string, filterType: string | null): SpotlightResource[] => {
|
|
if (!query || query.trim() === '') {
|
|
return []
|
|
}
|
|
|
|
const resources: SpotlightResource[] = []
|
|
|
|
const addIfExists = (items: any[], type: string) => {
|
|
items.forEach((item, index) => {
|
|
const name = item.name || item.metadata?.name
|
|
const ns = item.namespace || item.metadata?.namespace || 'default'
|
|
const color = getNamespaceColor(ns)
|
|
|
|
const score = fuzzySearch(query, name)
|
|
if (score > 0.3) {
|
|
if (!filterType || filterType === 'all' || filterType === type) {
|
|
resources.push({
|
|
id: `${type}-${index}-${name}`,
|
|
type,
|
|
name,
|
|
namespace: ns,
|
|
color: color,
|
|
})
|
|
}
|
|
}
|
|
})
|
|
}
|
|
|
|
if (!filterType || filterType === 'all' || filterType === 'namespace') {
|
|
MOCK_NAMESPACES.forEach((ns, index) => {
|
|
if (fuzzySearch(query, ns.name) > 0.3) {
|
|
resources.push({
|
|
id: `namespace-${index}-${ns.name}`,
|
|
type: 'namespace',
|
|
name: ns.name,
|
|
color: getNamespaceColor(ns.name),
|
|
})
|
|
}
|
|
})
|
|
}
|
|
|
|
if (!filterType || filterType === 'all' || filterType === 'pod') {
|
|
addIfExists(MOCK_PODS, 'pod')
|
|
}
|
|
|
|
if (!filterType || filterType === 'all' || filterType === 'deployment') {
|
|
addIfExists(MOCK_DEPLOYMENTS, 'deployment')
|
|
}
|
|
|
|
if (!filterType || filterType === 'all' || filterType === 'service') {
|
|
addIfExists(MOCK_SERVICES, 'service')
|
|
}
|
|
|
|
return resources.sort((a, b) => fuzzySearch(query, b.name) - fuzzySearch(query, a.name))
|
|
}
|
|
|
|
const getQuickActions = (query: string): SpotlightResource[] => {
|
|
const actions: SpotlightResource[] = []
|
|
const namespaces = Array.from(new Set([...MOCK_NAMESPACES.map((ns) => ns.name)]))
|
|
|
|
namespaces.forEach((ns, index) => {
|
|
actions.push({
|
|
id: `quick-${index}-${ns}`,
|
|
type: 'quick_create',
|
|
name: `Create krate for ns/${ns}`,
|
|
namespace: ns,
|
|
color: getNamespaceColor(ns),
|
|
})
|
|
})
|
|
|
|
actions.push({
|
|
id: 'quick-pods',
|
|
type: 'quick_create',
|
|
name: 'All pods',
|
|
color: '#6fb1ff',
|
|
})
|
|
|
|
actions.push({
|
|
id: 'quick-svcs',
|
|
type: 'quick_create',
|
|
name: 'All services',
|
|
color: '#6fb1ff',
|
|
})
|
|
|
|
actions.push({
|
|
id: 'quick-deployments',
|
|
type: 'quick_create',
|
|
name: 'All deployments',
|
|
color: '#6fb1ff',
|
|
})
|
|
|
|
if (query.trim()) {
|
|
actions.push({
|
|
id: 'quick-search',
|
|
type: 'quick_create',
|
|
name: `Search again for "${query}"`,
|
|
color: '#4dd6e8',
|
|
})
|
|
}
|
|
|
|
return actions
|
|
}
|
|
|
|
const getNamespaceColor = (namespace: string): string => {
|
|
if (namespace === 'default') return '#6fb1ff'
|
|
if (namespace === 'kube-system') return '#9c88ff'
|
|
if (namespace === 'kube-public') return '#4dd6e8'
|
|
if (namespace === 'production') return '#6fb1ff'
|
|
if (namespace === 'staging') return '#4dd6e8'
|
|
return '#6fb1ff'
|
|
}
|
|
|
|
return useMemo(
|
|
() => ({
|
|
executeSearch,
|
|
getQuickActions,
|
|
getNamespaceColor,
|
|
}),
|
|
[]
|
|
)
|
|
}
|