From ffc6cda97f3d1265646ebb44b55c314fbbd02735 Mon Sep 17 00:00:00 2001 From: centdix Date: Thu, 29 May 2025 11:58:03 +0200 Subject: [PATCH] add ask in search bar + right top icon on homepage + suggestions --- .../src/lib/components/AskAiButton.svelte | 29 ++++++++++ .../src/lib/components/chat/GlobalChat.svelte | 43 +++++++++++++++ .../search/GlobalSearchModal.svelte | 54 +++++++++++-------- frontend/src/lib/stores.ts | 1 + .../src/routes/(root)/(logged)/+layout.svelte | 6 +-- .../src/routes/(root)/(logged)/+page.svelte | 10 +++- 6 files changed, 115 insertions(+), 28 deletions(-) create mode 100644 frontend/src/lib/components/AskAiButton.svelte diff --git a/frontend/src/lib/components/AskAiButton.svelte b/frontend/src/lib/components/AskAiButton.svelte new file mode 100644 index 0000000000..0ad318e889 --- /dev/null +++ b/frontend/src/lib/components/AskAiButton.svelte @@ -0,0 +1,29 @@ + + + diff --git a/frontend/src/lib/components/chat/GlobalChat.svelte b/frontend/src/lib/components/chat/GlobalChat.svelte index f7169825cf..d81317664b 100644 --- a/frontend/src/lib/components/chat/GlobalChat.svelte +++ b/frontend/src/lib/components/chat/GlobalChat.svelte @@ -4,6 +4,7 @@ import { Send, Loader2 } from 'lucide-svelte' import { chatRequest, prepareSystemMessage } from './core' import type { ChatCompletionMessageParam } from 'openai/resources/index.mjs' + import { globalChatInitialInput } from '$lib/stores' let chatHistory = [ { @@ -17,6 +18,17 @@ let currentReply = $state('') let messages = $state(chatHistory) + // Suggested questions for the user + const suggestions = $state([ + 'How do I create a new workflow?', + "What's the difference between scripts and flows?", + 'How can I connect to a database?', + 'How do I schedule a recurring job?' + ]) + + // Check if there are any user messages + const hasUserMessages = $derived(messages.some((msg) => msg.role === 'user')) + let abortController = new AbortController() async function handleSubmit() { @@ -45,6 +57,19 @@ inputValue = '' isSubmitting = false } + + function submitSuggestion(suggestion: string) { + inputValue = suggestion + handleSubmit() + } + + $effect(() => { + if (globalChatInitialInput) { + inputValue = $globalChatInitialInput + globalChatInitialInput.set('') + handleSubmit() + } + })
@@ -75,6 +100,24 @@
{/if} + + + {#if !hasUserMessages && !isSubmitting} +
+
+ {#each suggestions as suggestion} + + {/each} +
+
+ {/if} diff --git a/frontend/src/lib/components/search/GlobalSearchModal.svelte b/frontend/src/lib/components/search/GlobalSearchModal.svelte index 8edf4e8dae..355a5fa385 100644 --- a/frontend/src/lib/components/search/GlobalSearchModal.svelte +++ b/frontend/src/lib/components/search/GlobalSearchModal.svelte @@ -9,9 +9,7 @@ type ListableApp, type ListableRawApp, type Script, - type SearchJobsIndexResponse - } from '$lib/gen' import { clickOutside, isMac } from '$lib/utils' import { @@ -44,6 +42,7 @@ import Logs from 'lucide-svelte/icons/logs' import { AwsIcon, GoogleCloudIcon, KafkaIcon, MqttIcon, NatsIcon } from '../icons' import RunsSearch from './RunsSearch.svelte' + import AskAiButton from '../AskAiButton.svelte' let open: boolean = false @@ -264,7 +263,6 @@ return r } - let queryParseErrors: string[] = [] async function handleSearch() { @@ -320,8 +318,8 @@ ) } if (tab === 'runs') { - await tick() - runsSearch?.handleRunSearch(removePrefix(searchTerm, RUNS_PREFIX)) + await tick() + runsSearch?.handleRunSearch(removePrefix(searchTerm, RUNS_PREFIX)) } selectedItem = selectItem(0) } @@ -413,7 +411,7 @@ open = false goto(path) } else { - window.open(path, "_blank") + window.open(path, '_blank') } } @@ -581,8 +579,7 @@ let runsSearch: RunsSearch let runSearchRemainingCount: number | undefined = undefined let runSearchTotalCount: number | undefined = undefined - let indexMetadata: SearchJobsIndexResponse["index_metadata"] = undefined - + let indexMetadata: SearchJobsIndexResponse['index_metadata'] = undefined {#if open} @@ -618,6 +615,15 @@ >{placeholderFromPrefix(searchTerm)} + {#if (itemMap[tab] ?? []).length === 0 && searchTerm.length > 0} + { + closeModal() + }} + /> + {/if} {#if queryParseErrors.length > 0} @@ -682,7 +688,9 @@ {#if (itemMap[tab] ?? []).length === 0}
-
Nothing found
+
Nothing found, ask the AI to find what you need !
Tip: press `esc` to quickly clear the search bar
@@ -718,20 +726,20 @@ {/if} {:else if tab === 'runs'} - + {/if} diff --git a/frontend/src/lib/stores.ts b/frontend/src/lib/stores.ts index 5e0d18e062..8a7ff3d8ab 100644 --- a/frontend/src/lib/stores.ts +++ b/frontend/src/lib/stores.ts @@ -174,6 +174,7 @@ export const triggerablesByAI = writable< Record void) | undefined }> >({}) export const globalChatOpen = writable(false) +export const globalChatInitialInput = writable('') type SQLBaseSchema = { [schemaKey: string]: { diff --git a/frontend/src/routes/(root)/(logged)/+layout.svelte b/frontend/src/routes/(root)/(logged)/+layout.svelte index 52ffcdf8bf..6e681127a3 100644 --- a/frontend/src/routes/(root)/(logged)/+layout.svelte +++ b/frontend/src/routes/(root)/(logged)/+layout.svelte @@ -460,7 +460,7 @@ on:click={() => openGlobalChat()} isCollapsed={false} icon={MessageCircle} - label="Global Chat" + label="Ask AI" class="!text-xs" /> @@ -527,7 +527,7 @@ on:click={() => openGlobalChat()} {isCollapsed} icon={MessageCircle} - label="Global Chat" + label="Ask AI" class="!text-xs" /> @@ -634,7 +634,7 @@ on:click={() => openGlobalChat()} {isCollapsed} icon={MessageCircle} - label="Global Chat" + label="Ask AI" class="!text-xs" /> diff --git a/frontend/src/routes/(root)/(logged)/+page.svelte b/frontend/src/routes/(root)/(logged)/+page.svelte index 8d8d73a489..f6af3d8551 100644 --- a/frontend/src/routes/(root)/(logged)/+page.svelte +++ b/frontend/src/routes/(root)/(logged)/+page.svelte @@ -1,6 +1,6 @@