mirror of
https://github.com/runebookai/tome.git
synced 2025-07-21 00:27:30 +03:00
Support autosaving existing Tasks and explicit saving new ones
This commit is contained in:
@@ -28,13 +28,14 @@
|
||||
filterProp,
|
||||
}: Props = $props();
|
||||
|
||||
let filteredItems = $state(items);
|
||||
let filterTerm = $state('');
|
||||
let css = borderless ? '' : 'border-b-light border-b';
|
||||
|
||||
function filter() {
|
||||
if (filterable && filterProp) {
|
||||
filteredItems = items.filter(item => (item[filterProp] as string).includes(filterTerm));
|
||||
return items.filter(item => (item[filterProp] as string).includes(filterTerm));
|
||||
} else {
|
||||
return items;
|
||||
}
|
||||
}
|
||||
</script>
|
||||
@@ -60,7 +61,7 @@
|
||||
</Flex>
|
||||
{/if}
|
||||
|
||||
{#each filteredItems as item, i (i)}
|
||||
{#each filter() as item, i (i)}
|
||||
<div class={twMerge('w-full', css)}>
|
||||
{@render itemView(item)}
|
||||
</div>
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
<script lang="ts">
|
||||
import { goto } from '$app/navigation';
|
||||
|
||||
import Button from './Button.svelte';
|
||||
|
||||
import Flex from '$components/Flex.svelte';
|
||||
@@ -11,11 +13,12 @@
|
||||
|
||||
interface Props {
|
||||
task: Task;
|
||||
onsave?: () => void | Promise<void>;
|
||||
onsave?: () => Task | Promise<Task>;
|
||||
}
|
||||
|
||||
const { task, onsave }: Props = $props();
|
||||
const isEdit = task.id !== undefined;
|
||||
const isEdit = $derived(task.id !== undefined);
|
||||
|
||||
let mcpServers: McpServer[] = $state([]);
|
||||
|
||||
async function addMcpServer(mcpServer: McpServer) {
|
||||
@@ -47,6 +50,15 @@
|
||||
await onsave?.();
|
||||
}
|
||||
}
|
||||
|
||||
async function save() {
|
||||
const task = await onsave?.();
|
||||
|
||||
if (task) {
|
||||
mcpServers.forEach(server => task.addMcpServer(server));
|
||||
goto(`/tasks/${task.id}`);
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
{#snippet McpServerView(mcpServer: McpServer)}
|
||||
@@ -101,6 +113,6 @@
|
||||
/>
|
||||
|
||||
{#if !isEdit}
|
||||
<Button onclick={onsave} class="border-purple text-purple mt-8">Save</Button>
|
||||
<Button onclick={save} class="border-purple text-purple mt-8">Save</Button>
|
||||
{/if}
|
||||
</Flex>
|
||||
|
||||
@@ -44,6 +44,10 @@ export default class Task extends Base<Row>('tasks') {
|
||||
return TaskMcpServer.exists({ taskId: this.id, mcpServerId: mcpServer.id });
|
||||
}
|
||||
|
||||
should_run(): boolean {
|
||||
return this.next_run <= new Date();
|
||||
}
|
||||
|
||||
async start(force: boolean = false): Promise<void> {
|
||||
if (this.should_run() || force) {
|
||||
this.next_run = await this.calculate_next_run();
|
||||
@@ -52,13 +56,9 @@ export default class Task extends Base<Row>('tasks') {
|
||||
}
|
||||
}
|
||||
|
||||
should_run(): boolean {
|
||||
return this.next_run <= new Date();
|
||||
}
|
||||
|
||||
async calculate_next_run(): Promise<Date> {
|
||||
const interval = CronExpressionParser.parse(this.period);
|
||||
return new Date(interval.next().toString());
|
||||
async delete() {
|
||||
TaskMcpServer.where({ taskId: this.id }).forEach(r => r.delete());
|
||||
return super.delete();
|
||||
}
|
||||
|
||||
protected async beforeSave(row: ToSqlRow<Row>): Promise<ToSqlRow<Row>> {
|
||||
@@ -68,6 +68,11 @@ export default class Task extends Base<Row>('tasks') {
|
||||
};
|
||||
}
|
||||
|
||||
async calculate_next_run(): Promise<Date> {
|
||||
const interval = CronExpressionParser.parse(this.period);
|
||||
return new Date(interval.next().toString());
|
||||
}
|
||||
|
||||
protected static async fromSql(row: Row): Promise<Task> {
|
||||
return Task.new({
|
||||
id: row.id,
|
||||
|
||||
@@ -11,9 +11,8 @@
|
||||
import Titlebar from '$components/Titlebar.svelte';
|
||||
import Task from '$lib/models/task.svelte';
|
||||
|
||||
let allTasks: Task[] = $derived(Task.all());
|
||||
|
||||
const { children } = $props();
|
||||
const tasks: Task[] = $derived(Task.all());
|
||||
|
||||
function items(task: Task): MenuItem[] {
|
||||
return [
|
||||
@@ -35,7 +34,7 @@
|
||||
|
||||
async function destroy(task: Task) {
|
||||
await task.delete();
|
||||
goto(`/tasks`);
|
||||
await goto(`/tasks`);
|
||||
}
|
||||
|
||||
async function edit(task: Task) {
|
||||
@@ -80,7 +79,7 @@
|
||||
<Layout {titlebar}>
|
||||
<Flex class="h-full items-start">
|
||||
<Flex class="border-r-light h-full w-[300px] flex-col items-start border-r">
|
||||
<List items={allTasks} itemView={TaskView} />
|
||||
<List items={tasks} itemView={TaskView} />
|
||||
</Flex>
|
||||
|
||||
<Flex class="h-full w-[calc(100%-300px)] items-start">
|
||||
|
||||
@@ -7,8 +7,8 @@
|
||||
const taskId = Number(page.params.task_id);
|
||||
const task: Task = $derived(Task.find(taskId));
|
||||
|
||||
async function save(): Promise<void> {
|
||||
await task.save();
|
||||
async function save(): Promise<Task> {
|
||||
return await task.save();
|
||||
}
|
||||
</script>
|
||||
|
||||
|
||||
@@ -41,7 +41,7 @@
|
||||
|
||||
<Flex class="border-t-light h-2/5 w-full flex-col items-start border-t py-4">
|
||||
<h3 class="mb-4 ml-8 uppercase">History</h3>
|
||||
<List items={task.runs} itemView={RunView} class="border-t-light border-t" />
|
||||
<List items={task?.runs} itemView={RunView} class="border-t-light border-t" />
|
||||
</Flex>
|
||||
</Flex>
|
||||
{/key}
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
const task: Task = $state(Task.new());
|
||||
|
||||
async function save() {
|
||||
await task.save();
|
||||
return await task.save();
|
||||
}
|
||||
</script>
|
||||
|
||||
|
||||
Reference in New Issue
Block a user