working switch
This commit is contained in:
parent
24f0ae3219
commit
e8d25a8f11
7 changed files with 69 additions and 17 deletions
|
|
@ -17,9 +17,10 @@ export default defineSchema({
|
|||
provider: providerValidator,
|
||||
/** Different providers may use different ids for the same model */
|
||||
model_id: v.string(),
|
||||
pinned: v.union(v.number(), v.null())
|
||||
pinned: v.union(v.number(), v.null()),
|
||||
})
|
||||
.index('by_user', ['user_id'])
|
||||
.index('by_model_provider', ['model_id', 'provider'])
|
||||
.index('by_provider_user', ['provider', 'user_id']),
|
||||
.index('by_provider_user', ['provider', 'user_id'])
|
||||
.index('by_model_provider_user', ['model_id', 'provider', 'user_id']),
|
||||
});
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@ import { query, mutation } from './_generated/server';
|
|||
import { v } from 'convex/values';
|
||||
import { providerValidator } from './schema';
|
||||
import * as array from '../../utils/array';
|
||||
import * as object from '../../utils/object';
|
||||
|
||||
export const get_enabled = query({
|
||||
args: {
|
||||
|
|
@ -17,6 +18,24 @@ export const get_enabled = query({
|
|||
},
|
||||
});
|
||||
|
||||
export const is_enabled = query({
|
||||
args: {
|
||||
user_id: v.string(),
|
||||
provider: providerValidator,
|
||||
model_id: v.string(),
|
||||
},
|
||||
handler: async (ctx, args) => {
|
||||
const model = await ctx.db
|
||||
.query('user_enabled_models')
|
||||
.withIndex('by_model_provider_user', (q) =>
|
||||
q.eq('model_id', args.model_id).eq('provider', args.provider).eq('user_id', args.user_id)
|
||||
)
|
||||
.first();
|
||||
|
||||
return !!model;
|
||||
},
|
||||
});
|
||||
|
||||
export const set = mutation({
|
||||
args: {
|
||||
provider: providerValidator,
|
||||
|
|
@ -38,7 +57,7 @@ export const set = mutation({
|
|||
await ctx.db.delete(existing._id);
|
||||
} else {
|
||||
await ctx.db.insert('user_enabled_models', {
|
||||
...{ ...args, enabled: undefined },
|
||||
...object.pick(args, ['provider', 'model_id', 'user_id']),
|
||||
pinned: null,
|
||||
});
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,10 +1,19 @@
|
|||
<script lang="ts">
|
||||
import { cn } from '$lib/utils/utils';
|
||||
import { Toggle, type ToggleProps } from 'melt/builders';
|
||||
import { type ComponentProps } from 'melt';
|
||||
|
||||
let { class: className, ...rest }: ToggleProps & { class?: string } = $props();
|
||||
let {
|
||||
class: className,
|
||||
value = $bindable(false),
|
||||
...rest
|
||||
}: ComponentProps<ToggleProps> & { class?: string } = $props();
|
||||
|
||||
const toggle = new Toggle(rest);
|
||||
const toggle = new Toggle({
|
||||
value: () => value ?? false,
|
||||
onValueChange: (v) => (value = v),
|
||||
...rest,
|
||||
});
|
||||
</script>
|
||||
|
||||
<button
|
||||
|
|
|
|||
|
|
@ -2,3 +2,16 @@
|
|||
export function keys<T extends object>(obj: T): Array<keyof T> {
|
||||
return Object.keys(obj) as Array<keyof T>;
|
||||
}
|
||||
|
||||
export function omit<T extends object, K extends keyof T>(obj: T, keys: K[]): Omit<T, K> {
|
||||
return Object.fromEntries(
|
||||
Object.entries(obj).filter(([key]) => !keys.includes(key as K))
|
||||
) as Omit<T, K>;
|
||||
}
|
||||
|
||||
export function pick<T extends object, K extends keyof T>(obj: T, keys: K[]): Pick<T, K> {
|
||||
return Object.fromEntries(Object.entries(obj).filter(([key]) => keys.includes(key as K))) as Pick<
|
||||
T,
|
||||
K
|
||||
>;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -28,7 +28,6 @@
|
|||
|
||||
let loading = $state(false);
|
||||
const toasts = new LocalToasts({ id });
|
||||
$inspect(toasts.toasts);
|
||||
|
||||
async function submit(e: SubmitEvent) {
|
||||
loading = true;
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
<script lang="ts">
|
||||
import { Provider } from '$lib/types.js';
|
||||
import { useQuery } from 'convex-svelte';
|
||||
import Model from './model.svelte';
|
||||
import ModelCard from './model-card.svelte';
|
||||
import { session } from '$lib/state/session.svelte';
|
||||
import { api } from '$lib/backend/convex/_generated/api';
|
||||
|
||||
|
|
@ -10,6 +10,11 @@
|
|||
const enabledModels = useQuery(api.user_enabled_models.get_enabled, {
|
||||
user_id: session.current?.user.id ?? '',
|
||||
});
|
||||
|
||||
$inspect(
|
||||
enabledModels.data,
|
||||
!!enabledModels.data?.[`${Provider.OpenRouter}:${data.openRouterModels[0].id}`]
|
||||
);
|
||||
</script>
|
||||
|
||||
<svelte:head>
|
||||
|
|
@ -24,6 +29,6 @@
|
|||
<div class="mt-8 flex flex-col gap-4">
|
||||
{#each data.openRouterModels as model (model.id)}
|
||||
{@const enabled = enabledModels.data?.[`${Provider.OpenRouter}:${model.id}`] !== undefined}
|
||||
<Model provider={Provider.OpenRouter} {model} {enabled} />
|
||||
<ModelCard provider={Provider.OpenRouter} {model} {enabled} />
|
||||
{/each}
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@
|
|||
import { useConvexClient } from 'convex-svelte';
|
||||
import { api } from '$lib/backend/convex/_generated/api';
|
||||
import { session } from '$lib/state/session.svelte.js';
|
||||
import { ResultAsync } from 'neverthrow';
|
||||
|
||||
type Model = {
|
||||
id: string;
|
||||
|
|
@ -35,15 +36,21 @@
|
|||
|
||||
let showMore = $state(false);
|
||||
|
||||
async function toggleEnabled(enabled: boolean) {
|
||||
async function toggleEnabled(v: boolean) {
|
||||
enabled = v; // Optimistic!
|
||||
if (!session.current?.user.id) return;
|
||||
|
||||
await client.mutation(api.user_enabled_models.set, {
|
||||
provider,
|
||||
user_id: session.current.user.id,
|
||||
model_id: model.id,
|
||||
enabled,
|
||||
});
|
||||
const res = await ResultAsync.fromPromise(
|
||||
client.mutation(api.user_enabled_models.set, {
|
||||
provider,
|
||||
user_id: session.current.user.id,
|
||||
model_id: model.id,
|
||||
enabled: v,
|
||||
}),
|
||||
(e) => e
|
||||
);
|
||||
|
||||
if (res.isErr()) enabled = !v; // Should have been a realist :(
|
||||
}
|
||||
</script>
|
||||
|
||||
|
|
@ -52,7 +59,7 @@
|
|||
<div class="flex items-center justify-between">
|
||||
<Card.Title>{model.name}</Card.Title>
|
||||
<!-- TODO: make this actually work -->
|
||||
<Switch value={enabled} onValueChange={toggleEnabled} />
|
||||
<Switch bind:value={() => enabled, toggleEnabled} />
|
||||
</div>
|
||||
<Card.Description
|
||||
>{showMore ? fullDescription : (shortDescription ?? fullDescription)}</Card.Description
|
||||
|
|
@ -67,5 +74,4 @@
|
|||
</button>
|
||||
{/if}
|
||||
</Card.Header>
|
||||
<Card.Content></Card.Content>
|
||||
</Card.Root>
|
||||
Loading…
Add table
Reference in a new issue