Spaces:
Runtime error
Runtime error
File size: 3,923 Bytes
05e5873 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 |
<script lang="ts" module>
let open = $state(false);
export function openExtraParamsModal() {
open = true;
}
</script>
<script lang="ts">
import type { ConversationClass } from "$lib/state/conversations.svelte.js";
import { createFieldValidation } from "$lib/utils/form.svelte";
import { deleteKey, entries, renameKey } from "$lib/utils/object.svelte";
import { onchange } from "$lib/utils/template.js";
import IconX from "~icons/carbon/close";
import Dialog from "../dialog.svelte";
import InfoPopover from "../info-popover.svelte";
import { watch } from "runed";
interface Props {
conversation: ConversationClass;
}
let { conversation }: Props = $props();
type Field = {
value: string;
} & ReturnType<typeof createFieldValidation>;
let fields = $state<Record<string, Field>>({});
watch(
() => open,
() => {
if (!open) return;
// Sync with conversation.extraParams
fields = Object.fromEntries(
entries(conversation.data.extraParams ?? {}).map(([key, value]) => [
key,
Object.assign(createFieldValidation({ validate: validateParamValue }), { value }),
]),
);
},
);
function validateParamValue(v: string) {
if (!v) return "Value cannot be empty";
try {
JSON.parse(v);
} catch {
return "Value is not valid JSON";
}
}
async function close() {
fields = {};
open = false;
}
async function save() {
Object.values(fields).forEach(f => f.validate());
if (!Object.values(fields).every(f => f.valid)) return;
open = false;
// Set conversation.extraParams
conversation.update({
extraParams: Object.fromEntries(entries(fields).map(([key, field]) => [key, field.value])),
});
}
</script>
<Dialog
class="!w-2xl max-w-[90vw]"
title="Edit Extra Parameters"
{open}
onClose={() => {
close();
}}
onSubmit={e => {
e.preventDefault();
}}
>
<div class="flex items-center gap-2">
<h2 class="font-semibold">Parameters</h2>
<InfoPopover content="These parameters are passed as JSON parameters, as is." />
<button
type="button"
class="btn-sm ml-auto flex items-center justify-center rounded-md"
onclick={() => {
const prevLength = Object.keys(fields).length ?? 0;
const key = `newParam${prevLength + 1}`;
fields[key] = Object.assign(createFieldValidation({ validate: validateParamValue }), { value: "" });
}}
>
Add parameter
</button>
</div>
<div class="mt-4 flex flex-col gap-4">
{#each entries(fields) as [key, field]}
<div class="flex items-start gap-2">
<label class="flex grow flex-col gap-1">
<p class="text-xs font-medium text-gray-500 dark:text-gray-400">Key</p>
<input
type="text"
class="w-full rounded-md border border-gray-300 bg-white px-2 py-1 text-sm text-gray-900 shadow-sm focus:border-blue-500 focus:ring-blue-500 dark:border-gray-700 dark:bg-gray-800 dark:text-white"
value={key}
{...onchange(k => (fields = renameKey(fields, key, k)))}
/>
</label>
<label class="flex grow flex-col gap-1">
<p class="text-xs font-medium text-gray-500 dark:text-gray-400">Value</p>
<input
type="text"
class="w-full rounded-md border border-gray-300 bg-white px-2 py-1 font-mono text-sm text-gray-900 shadow-sm focus:border-blue-500 focus:ring-blue-500 dark:border-gray-700 dark:bg-gray-800 dark:text-white"
{...field.attrs}
bind:value={field.value}
/>
{#if field.msg}
<p class="text-xs text-red-500">{field.msg}</p>
{/if}
</label>
<button
type="button"
class="btn-xs mt-5 rounded-md text-red-500 hover:text-red-600 dark:text-red-400 dark:hover:text-red-500"
onclick={() => (fields = deleteKey(fields, key))}
>
<IconX />
</button>
</div>
{:else}
<p class="text-sm text-gray-500">No parameters defined yet.</p>
{/each}
</div>
{#snippet footer()}
<button class="btn ml-auto" onclick={save}> Save </button>
{/snippet}
</Dialog>
|