mirror of
https://github.com/open-webui/open-webui.git
synced 2025-12-12 12:25:20 +00:00
refac: suggestion prompts
This commit is contained in:
parent
db0d2ae6d4
commit
198b89faa5
7 changed files with 32 additions and 64 deletions
|
|
@ -193,6 +193,15 @@
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const onSelect = async (e) => {
|
||||||
|
const { type, data } = e;
|
||||||
|
|
||||||
|
if (type === 'prompt') {
|
||||||
|
// Handle prompt selection
|
||||||
|
messageInput?.setText(data);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
$: if (selectedModels && chatIdProp !== '') {
|
$: if (selectedModels && chatIdProp !== '') {
|
||||||
saveSessionSelectedModels();
|
saveSessionSelectedModels();
|
||||||
}
|
}
|
||||||
|
|
@ -2117,6 +2126,7 @@
|
||||||
{chatActionHandler}
|
{chatActionHandler}
|
||||||
{addMessages}
|
{addMessages}
|
||||||
bottomPadding={files.length > 0}
|
bottomPadding={files.length > 0}
|
||||||
|
{onSelect}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -2202,6 +2212,7 @@
|
||||||
toolServers={$toolServers}
|
toolServers={$toolServers}
|
||||||
{stopResponse}
|
{stopResponse}
|
||||||
{createMessagePair}
|
{createMessagePair}
|
||||||
|
{onSelect}
|
||||||
on:upload={async (e) => {
|
on:upload={async (e) => {
|
||||||
const { type, data } = e.detail;
|
const { type, data } = e.detail;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -18,7 +18,7 @@
|
||||||
export let models = [];
|
export let models = [];
|
||||||
export let atSelectedModel;
|
export let atSelectedModel;
|
||||||
|
|
||||||
export let submitPrompt;
|
export let onSelect = (e) => {};
|
||||||
|
|
||||||
let mounted = false;
|
let mounted = false;
|
||||||
let selectedModelIdx = 0;
|
let selectedModelIdx = 0;
|
||||||
|
|
@ -135,9 +135,7 @@
|
||||||
models[selectedModelIdx]?.info?.meta?.suggestion_prompts ??
|
models[selectedModelIdx]?.info?.meta?.suggestion_prompts ??
|
||||||
$config?.default_prompt_suggestions ??
|
$config?.default_prompt_suggestions ??
|
||||||
[]}
|
[]}
|
||||||
on:select={(e) => {
|
{onSelect}
|
||||||
submitPrompt(e.detail);
|
|
||||||
}}
|
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -119,6 +119,7 @@
|
||||||
if (chatInput) {
|
if (chatInput) {
|
||||||
if ($settings?.richTextInput ?? true) {
|
if ($settings?.richTextInput ?? true) {
|
||||||
chatInputElement.setText(text);
|
chatInputElement.setText(text);
|
||||||
|
chatInputElement.focus();
|
||||||
} else {
|
} else {
|
||||||
chatInput.value = text;
|
chatInput.value = text;
|
||||||
prompt = text;
|
prompt = text;
|
||||||
|
|
|
||||||
|
|
@ -51,6 +51,8 @@
|
||||||
export let bottomPadding = false;
|
export let bottomPadding = false;
|
||||||
export let autoScroll;
|
export let autoScroll;
|
||||||
|
|
||||||
|
export let onSelect = (e) => {};
|
||||||
|
|
||||||
let messagesCount = 20;
|
let messagesCount = 20;
|
||||||
let messagesLoading = false;
|
let messagesLoading = false;
|
||||||
|
|
||||||
|
|
@ -395,25 +397,7 @@
|
||||||
|
|
||||||
<div class={className}>
|
<div class={className}>
|
||||||
{#if Object.keys(history?.messages ?? {}).length == 0}
|
{#if Object.keys(history?.messages ?? {}).length == 0}
|
||||||
<ChatPlaceholder
|
<ChatPlaceholder modelIds={selectedModels} {atSelectedModel} {onSelect} />
|
||||||
modelIds={selectedModels}
|
|
||||||
{atSelectedModel}
|
|
||||||
submitPrompt={async (p) => {
|
|
||||||
let text = p;
|
|
||||||
|
|
||||||
if (p.includes('{{CLIPBOARD}}')) {
|
|
||||||
const clipboardText = await navigator.clipboard.readText().catch((err) => {
|
|
||||||
toast.error($i18n.t('Failed to read clipboard contents'));
|
|
||||||
return '{{CLIPBOARD}}';
|
|
||||||
});
|
|
||||||
|
|
||||||
text = p.replaceAll('{{CLIPBOARD}}', clipboardText);
|
|
||||||
}
|
|
||||||
|
|
||||||
prompt = text;
|
|
||||||
await tick();
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
{:else}
|
{:else}
|
||||||
<div class="w-full pt-2">
|
<div class="w-full pt-2">
|
||||||
{#key chatId}
|
{#key chatId}
|
||||||
|
|
|
||||||
|
|
@ -43,45 +43,12 @@
|
||||||
export let codeInterpreterEnabled = false;
|
export let codeInterpreterEnabled = false;
|
||||||
export let webSearchEnabled = false;
|
export let webSearchEnabled = false;
|
||||||
|
|
||||||
|
export let onSelect = (e) => {};
|
||||||
|
|
||||||
export let toolServers = [];
|
export let toolServers = [];
|
||||||
|
|
||||||
let models = [];
|
let models = [];
|
||||||
|
|
||||||
const selectSuggestionPrompt = async (p) => {
|
|
||||||
let text = p;
|
|
||||||
|
|
||||||
if (p.includes('{{CLIPBOARD}}')) {
|
|
||||||
const clipboardText = await navigator.clipboard.readText().catch((err) => {
|
|
||||||
toast.error($i18n.t('Failed to read clipboard contents'));
|
|
||||||
return '{{CLIPBOARD}}';
|
|
||||||
});
|
|
||||||
|
|
||||||
text = p.replaceAll('{{CLIPBOARD}}', clipboardText);
|
|
||||||
|
|
||||||
console.log('Clipboard text:', clipboardText, text);
|
|
||||||
}
|
|
||||||
|
|
||||||
prompt = text;
|
|
||||||
|
|
||||||
console.log(prompt);
|
|
||||||
await tick();
|
|
||||||
|
|
||||||
const chatInputContainerElement = document.getElementById('chat-input-container');
|
|
||||||
const chatInputElement = document.getElementById('chat-input');
|
|
||||||
|
|
||||||
if (chatInputContainerElement) {
|
|
||||||
chatInputContainerElement.scrollTop = chatInputContainerElement.scrollHeight;
|
|
||||||
}
|
|
||||||
|
|
||||||
await tick();
|
|
||||||
if (chatInputElement) {
|
|
||||||
chatInputElement.focus();
|
|
||||||
chatInputElement.dispatchEvent(new Event('input'));
|
|
||||||
}
|
|
||||||
|
|
||||||
await tick();
|
|
||||||
};
|
|
||||||
|
|
||||||
let selectedModelIdx = 0;
|
let selectedModelIdx = 0;
|
||||||
|
|
||||||
$: if (selectedModels.length > 0) {
|
$: if (selectedModels.length > 0) {
|
||||||
|
|
@ -255,9 +222,7 @@
|
||||||
$config?.default_prompt_suggestions ??
|
$config?.default_prompt_suggestions ??
|
||||||
[]}
|
[]}
|
||||||
inputValue={prompt}
|
inputValue={prompt}
|
||||||
on:select={(e) => {
|
{onSelect}
|
||||||
selectSuggestionPrompt(e.detail);
|
|
||||||
}}
|
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -1,16 +1,16 @@
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import Fuse from 'fuse.js';
|
import Fuse from 'fuse.js';
|
||||||
import Bolt from '$lib/components/icons/Bolt.svelte';
|
import Bolt from '$lib/components/icons/Bolt.svelte';
|
||||||
import { onMount, getContext, createEventDispatcher } from 'svelte';
|
import { onMount, getContext } from 'svelte';
|
||||||
import { settings, WEBUI_NAME } from '$lib/stores';
|
import { settings, WEBUI_NAME } from '$lib/stores';
|
||||||
import { WEBUI_VERSION } from '$lib/constants';
|
import { WEBUI_VERSION } from '$lib/constants';
|
||||||
|
|
||||||
const i18n = getContext('i18n');
|
const i18n = getContext('i18n');
|
||||||
const dispatch = createEventDispatcher();
|
|
||||||
|
|
||||||
export let suggestionPrompts = [];
|
export let suggestionPrompts = [];
|
||||||
export let className = '';
|
export let className = '';
|
||||||
export let inputValue = '';
|
export let inputValue = '';
|
||||||
|
export let onSelect = (e) => {};
|
||||||
|
|
||||||
let sortedPrompts = [];
|
let sortedPrompts = [];
|
||||||
|
|
||||||
|
|
@ -85,13 +85,14 @@
|
||||||
{#if filteredPrompts.length > 0}
|
{#if filteredPrompts.length > 0}
|
||||||
<div role="list" class="max-h-40 overflow-auto scrollbar-none items-start {className}">
|
<div role="list" class="max-h-40 overflow-auto scrollbar-none items-start {className}">
|
||||||
{#each filteredPrompts as prompt, idx (prompt.id || prompt.content)}
|
{#each filteredPrompts as prompt, idx (prompt.id || prompt.content)}
|
||||||
|
<!-- svelte-ignore a11y-no-interactive-element-to-noninteractive-role -->
|
||||||
<button
|
<button
|
||||||
role="listitem"
|
role="listitem"
|
||||||
class="waterfall flex flex-col flex-1 shrink-0 w-full justify-between
|
class="waterfall flex flex-col flex-1 shrink-0 w-full justify-between
|
||||||
px-3 py-2 rounded-xl bg-transparent hover:bg-black/5
|
px-3 py-2 rounded-xl bg-transparent hover:bg-black/5
|
||||||
dark:hover:bg-white/5 transition group"
|
dark:hover:bg-white/5 transition group"
|
||||||
style="animation-delay: {idx * 60}ms"
|
style="animation-delay: {idx * 60}ms"
|
||||||
on:click={() => dispatch('select', prompt.content)}
|
on:click={() => onSelect({ type: 'prompt', data: prompt.content })}
|
||||||
>
|
>
|
||||||
<div class="flex flex-col text-left">
|
<div class="flex flex-col text-left">
|
||||||
{#if prompt.title && prompt.title[0] !== ''}
|
{#if prompt.title && prompt.title[0] !== ''}
|
||||||
|
|
|
||||||
|
|
@ -207,6 +207,14 @@
|
||||||
selectNextTemplate(editor.view.state, editor.view.dispatch);
|
selectNextTemplate(editor.view.state, editor.view.dispatch);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const focus = () => {
|
||||||
|
if (editor) {
|
||||||
|
editor.view.focus();
|
||||||
|
// Scroll to the top of the editor
|
||||||
|
editor.view.dispatch(editor.view.state.tr.scrollIntoView());
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
// Function to find the next template in the document
|
// Function to find the next template in the document
|
||||||
function findNextTemplate(doc, from = 0) {
|
function findNextTemplate(doc, from = 0) {
|
||||||
const patterns = [{ start: '{{', end: '}}' }];
|
const patterns = [{ start: '{{', end: '}}' }];
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue