Skip to content

Commit b0f454b

Browse files
committed
Update @vueuse/core to version 14.1.0, enhance pipeline selection functionality, and improve worker initialization with timeout
1 parent 6bceda9 commit b0f454b

File tree

16 files changed

+434
-118
lines changed

16 files changed

+434
-118
lines changed

.claude/settings.local.json

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,18 @@
1717
"Bash(./emsdk activate:*)",
1818
"Bash(source:*)",
1919
"mcp__playwright__browser_navigate",
20-
"mcp__playwright__browser_console_messages"
20+
"mcp__playwright__browser_console_messages",
21+
"mcp__playwright__browser_click",
22+
"mcp__playwright__browser_take_screenshot",
23+
"mcp__playwright__browser_evaluate",
24+
"mcp__shadcnVue__search_items_in_registries",
25+
"mcp__shadcnVue__view_items_in_registries",
26+
"mcp__shadcnVue__get_item_examples_from_registries",
27+
"mcp__playwright__browser_snapshot",
28+
"mcp__playwright__browser_press_key",
29+
"mcp__playwright__browser_run_code",
30+
"mcp__playwright__browser_network_requests",
31+
"mcp__playwright__browser_wait_for"
2132
]
2233
},
2334
"enabledMcpjsonServers": [

bun.lock

Lines changed: 10 additions & 4 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@
2424
"@tanstack/vue-virtual": "^3.13.13",
2525
"@types/js-yaml": "^4.0.9",
2626
"@unhead/vue": "^2.0.19",
27-
"@vueuse/core": "^13.9.0",
27+
"@vueuse/core": "^14.1.0",
2828
"@vueuse/integrations": "^13.9.0",
2929
"change-case": "^5.4.4",
3030
"class-variance-authority": "^0.7.1",
Lines changed: 180 additions & 82 deletions
Original file line numberDiff line numberDiff line change
@@ -1,39 +1,84 @@
11
<script lang="ts" setup>
2-
import {computed, ref} from "vue";
2+
import {computed, watch, ref, onMounted} from "vue";
33
import {useWorkspaceStore} from "@/stores/WorkspaceStore";
4+
import {getAvailablePipelines} from "@/lib/sigma/worker/workerApi";
45
import {
5-
Select,
6-
SelectContent,
7-
SelectGroup,
8-
SelectItem,
9-
SelectLabel,
10-
SelectTrigger,
11-
SelectValue
12-
} from "@/components/ui/select";
13-
import {Badge} from "@/components/ui/badge";
14-
import {Plus, X} from "lucide-vue-next";
6+
DropdownMenu,
7+
DropdownMenuContent,
8+
DropdownMenuCheckboxItem,
9+
DropdownMenuLabel,
10+
DropdownMenuSeparator,
11+
DropdownMenuTrigger,
12+
} from "@/components/ui/dropdown-menu";
1513
import {Button} from "@/components/ui/button";
14+
import {ScrollArea} from "@/components/ui/scroll-area";
15+
import {Filter, Check} from "lucide-vue-next";
1616
import type {FileItem} from "@/types/types";
1717
18+
const isDropdownOpen = ref(false);
19+
1820
const workspace = useWorkspaceStore();
1921
const fs = computed(() => workspace.currentWorkspace?.fileStore());
2022
const sigma = computed(() => workspace.currentWorkspace?.sigmaStore());
2123
22-
// Default built-in pipelines
23-
const defaultPipelines = [
24-
'splunk_windows',
25-
'splunk_linux',
26-
'splunk_web',
27-
'splunk_network',
28-
'elasticsearch_windows',
29-
'elasticsearch_linux',
30-
'elasticsearch_web',
31-
'elasticsearch_network'
32-
];
33-
34-
// Get available pipelines from pipeline files
24+
// All available pipelines from plugins
25+
const allPipelines = ref<string[]>([]);
26+
27+
// Load available pipelines from worker on mount
28+
onMounted(async () => {
29+
try {
30+
console.log('Fetching available pipelines from worker...');
31+
const result = await getAvailablePipelines();
32+
console.log('Pipeline fetch result:', result);
33+
if (result.success && result.pipelines) {
34+
allPipelines.value = result.pipelines;
35+
console.log('Loaded pipelines:', allPipelines.value);
36+
} else {
37+
console.warn('Failed to get pipelines:', result.error);
38+
}
39+
} catch (error) {
40+
console.error('Failed to load available pipelines:', error);
41+
}
42+
});
43+
44+
// Filter pipelines by backend prefix
45+
function getPipelinesForBackend(backend: string): string[] {
46+
if (!backend || allPipelines.value.length === 0) {
47+
return allPipelines.value;
48+
}
49+
50+
// Map backend names to their pipeline prefixes
51+
const backendPrefixes: Record<string, string[]> = {
52+
'splunk': ['splunk'],
53+
'esql': ['ecs', 'elasticsearch'],
54+
'lucene': ['ecs', 'elasticsearch'],
55+
'eql': ['ecs', 'elasticsearch'],
56+
'loki': ['loki'],
57+
'kusto': ['azure', 'microsoft'],
58+
'qradar': ['qradar'],
59+
'carbonblack': ['carbonblack'],
60+
'crowdstrike': ['crowdstrike'],
61+
'sentinel': ['azure', 'microsoft'],
62+
};
63+
64+
const prefixes = backendPrefixes[backend] || [];
65+
66+
// Filter pipelines that start with any of the backend's prefixes
67+
return allPipelines.value.filter(pipeline =>
68+
prefixes.some(prefix => pipeline.startsWith(prefix))
69+
);
70+
}
71+
72+
// Get available pipelines filtered by selected backend
3573
const availablePipelines = computed(() => {
36-
const pipelines: string[] = [...defaultPipelines];
74+
const selectedBackend = sigma.value?.selected_siem;
75+
76+
// Start with backend-specific pipelines if available, otherwise all pipelines
77+
const basePipelines = selectedBackend
78+
? getPipelinesForBackend(selectedBackend)
79+
: allPipelines.value;
80+
81+
const pipelines: string[] = [...basePipelines];
3782
3883
// Add custom pipelines from files
3984
const pipelineFiles = fs.value?.files.filter((f: FileItem) => f.type === "pipeline") || [];
@@ -43,7 +88,6 @@ const availablePipelines = computed(() => {
4388
const content = file.content || '';
4489
4590
// Look for name patterns in YAML
46-
// This is a simple approach - the backend uses pipeline_resolver.py for proper parsing
4791
const pipelines_in_file = [
4892
// Look for name: value format
4993
...content.split('\n')
@@ -63,70 +107,124 @@ const availablePipelines = computed(() => {
63107
return [...new Set(pipelines)].sort(); // Remove duplicates and sort
64108
});
65109
66-
// Handle pipeline selection
67-
const selectedPipeline = ref('');
110+
const selectedPipelines = computed(() => sigma.value?.selected_pipelines || []);
68111
69-
function addPipeline() {
70-
if (!selectedPipeline.value ||
71-
sigma.value.selected_pipelines.includes(selectedPipeline.value)) {
72-
return;
112+
// Toggle pipeline selection
113+
function togglePipeline(pipeline: string, checked: boolean) {
114+
if (!sigma.value) return;
115+
116+
const currentPipelines = sigma.value.selected_pipelines || [];
117+
118+
if (checked) {
119+
// Add pipeline if not already selected
120+
if (!currentPipelines.includes(pipeline)) {
121+
const newPipelines = [...currentPipelines, pipeline];
122+
sigma.value.updateSelectedPipelines(newPipelines);
123+
}
124+
} else {
125+
// Remove pipeline
126+
const newPipelines = currentPipelines.filter(p => p !== pipeline);
127+
sigma.value.updateSelectedPipelines(newPipelines);
73128
}
74-
75-
const newPipelines = [...sigma.value.selected_pipelines, selectedPipeline.value];
76-
sigma.value.updateSelectedPipelines(newPipelines);
77-
selectedPipeline.value = '';
78129
}
79130
80-
function removePipeline(pipeline: string) {
81-
const newPipelines = sigma.value.selected_pipelines.filter(p => p !== pipeline);
82-
sigma.value.updateSelectedPipelines(newPipelines);
83-
}
131+
// Watch for backend changes and clear incompatible pipelines
132+
watch(() => sigma.value?.selected_siem, (newBackend) => {
133+
if (!newBackend || !sigma.value) return;
84134
85-
const selectedPipelines = computed(() => sigma.value?.selected_pipelines || []);
135+
const compatiblePipelines = getPipelinesForBackend(newBackend);
136+
const currentPipelines = sigma.value.selected_pipelines || [];
137+
138+
// Remove pipelines that are not compatible with the new backend
139+
const filteredPipelines = currentPipelines.filter(pipeline => {
140+
// Keep pipelines that are compatible with the backend
141+
return compatiblePipelines.includes(pipeline);
142+
});
143+
144+
// Update if pipelines were filtered out
145+
if (filteredPipelines.length !== currentPipelines.length) {
146+
sigma.value.updateSelectedPipelines(filteredPipelines);
147+
}
148+
});
149+
150+
// Computed label for the button
151+
const buttonLabel = computed(() => {
152+
const count = selectedPipelines.value.length;
153+
if (count === 0) return 'Pipelines';
154+
if (count === 1) return '1 Pipeline';
155+
return `${count} Pipelines`;
156+
});
157+
158+
// Convert to Title Case, minus the underscores
159+
function toTitleCase(str: string): string {
160+
return str
161+
.toLowerCase()
162+
.split(/[_\s]+/)
163+
.map(word => {
164+
if (word === 'ecs') return 'ECS';
165+
return word.charAt(0).toUpperCase() + word.slice(1);
166+
})
167+
.join(' ');
168+
}
86169
</script>
87170

88171
<template>
89-
<div class="flex flex-col gap-2">
90-
<div class="flex gap-2 items-center">
91-
<Select v-model="selectedPipeline">
92-
<SelectTrigger class="h-8 w-[200px]">
93-
<SelectValue placeholder="Select pipeline"/>
94-
</SelectTrigger>
95-
<SelectContent>
96-
<SelectLabel class="m-0 pt-2 pb-0 px-3">Pipelines</SelectLabel>
97-
<SelectGroup>
98-
<div class="grid grid-cols-1 gap-1 p-2">
99-
<template v-for="pipeline in availablePipelines" :key="pipeline">
100-
<SelectItem :value="pipeline">
101-
{{ pipeline }}
102-
</SelectItem>
103-
</template>
104-
</div>
105-
</SelectGroup>
106-
</SelectContent>
107-
</Select>
108-
172+
<DropdownMenu v-model:open="isDropdownOpen">
173+
<DropdownMenuTrigger as-child>
109174
<Button
110-
class="h-8 w-8"
111-
size="icon"
112175
variant="outline"
113-
@click="addPipeline">
114-
<Plus class="h-4 w-4"/>
115-
</Button>
116-
</div>
117-
118-
<div class="flex flex-wrap gap-2 mt-1">
119-
<Badge
120-
v-for="pipeline in selectedPipelines"
121-
:key="pipeline"
122-
class="flex items-center gap-1"
123-
variant="secondary"
176+
size="sm"
177+
class="h-8 gap-2"
178+
:class="selectedPipelines.length > 0 ? 'border-primary' : ''"
124179
>
125-
{{ pipeline }}
126-
<button class="ml-1 p-0" @click="removePipeline(pipeline)">
127-
<X class="h-3 w-3"/>
128-
</button>
129-
</Badge>
130-
</div>
131-
</div>
132-
</template>
180+
<Filter class="h-3.5 w-3.5"/>
181+
<span>{{ toTitleCase(buttonLabel) }}</span>
182+
<Check v-if="selectedPipelines.length > 0" class="h-3.5 w-3.5 text-primary"/>
183+
</Button>
184+
</DropdownMenuTrigger>
185+
<DropdownMenuContent class="w-[280px]" align="start">
186+
<DropdownMenuLabel>
187+
<div class="flex flex-col gap-1">
188+
<span>Pipelines</span>
189+
<span class="text-xs font-normal text-muted-foreground">
190+
Compatible with {{ sigma?.selected_siem || 'current backend' }}
191+
</span>
192+
</div>
193+
</DropdownMenuLabel>
194+
<DropdownMenuSeparator/>
195+
196+
<ScrollArea class="h-[280px]">
197+
<div class="px-1">
198+
<DropdownMenuCheckboxItem
199+
v-for="pipeline in availablePipelines"
200+
:key="pipeline"
201+
:checked="selectedPipelines.includes(pipeline)"
202+
@select.prevent
203+
@update:checked="(checked) => togglePipeline(pipeline, checked)"
204+
>
205+
{{ toTitleCase(pipeline) }}
206+
</DropdownMenuCheckboxItem>
207+
208+
<div v-if="availablePipelines.length === 0" class="px-2 py-6 text-center text-sm text-muted-foreground">
209+
No pipelines available for this backend
210+
</div>
211+
</div>
212+
</ScrollArea>
213+
214+
<template v-if="selectedPipelines.length > 0">
215+
<DropdownMenuSeparator/>
216+
<div class="px-2 py-2 flex items-center justify-between">
217+
<span class="text-xs text-muted-foreground">{{ selectedPipelines.length }} selected</span>
218+
<Button
219+
variant="ghost"
220+
size="sm"
221+
class="h-6 px-2 text-xs"
222+
@click="sigma?.updateSelectedPipelines([]); isDropdownOpen = false"
223+
>
224+
Clear all
225+
</Button>
226+
</div>
227+
</template>
228+
</DropdownMenuContent>
229+
</DropdownMenu>
230+
</template>

src/components/PrismEditor.vue

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@ import {cursorPosition} from "prism-code-editor/cursor"
77
import {copyButton} from "prism-code-editor/copy-button"
88
import {matchTags} from "prism-code-editor/match-tags"
99
import {highlightBracketPairs} from "prism-code-editor/highlight-brackets"
10-
import {indentGuides} from "prism-code-editor/guides";
1110
import {createEditor} from "prism-code-editor";
1211
import {autoComplete, fuzzyFilter} from "prism-code-editor/autocomplete";
1312
@@ -79,7 +78,6 @@ onMounted(() => {
7978
matchTags(),
8079
highlightBracketPairs(),
8180
cursorPosition(),
82-
indentGuides(),
8381
];
8482
8583
// Add autocomplete extension if enabled

0 commit comments

Comments
 (0)