Fix bug in create and start
This commit is contained in:
@@ -25,6 +25,7 @@ fn main() {
|
||||
vibe_kanban::models::project::SearchResult::decl(),
|
||||
vibe_kanban::models::project::SearchMatchType::decl(),
|
||||
vibe_kanban::models::task::CreateTask::decl(),
|
||||
vibe_kanban::models::task::CreateTaskAndStart::decl(),
|
||||
vibe_kanban::models::task::TaskStatus::decl(),
|
||||
vibe_kanban::models::task::Task::decl(),
|
||||
vibe_kanban::models::task::TaskWithAttemptStatus::decl(),
|
||||
|
||||
@@ -50,6 +50,15 @@ pub struct CreateTask {
|
||||
pub description: Option<String>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Deserialize, TS)]
|
||||
#[ts(export)]
|
||||
pub struct CreateTaskAndStart {
|
||||
pub project_id: Uuid,
|
||||
pub title: String,
|
||||
pub description: Option<String>,
|
||||
pub executor: Option<crate::executor::ExecutorConfig>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Deserialize, TS)]
|
||||
#[ts(export)]
|
||||
pub struct UpdateTask {
|
||||
|
||||
@@ -10,7 +10,7 @@ use uuid::Uuid;
|
||||
|
||||
use crate::models::{
|
||||
project::Project,
|
||||
task::{CreateTask, Task, TaskWithAttemptStatus, UpdateTask},
|
||||
task::{CreateTask, CreateTaskAndStart, Task, TaskWithAttemptStatus, UpdateTask},
|
||||
task_attempt::{CreateTaskAttempt, TaskAttempt},
|
||||
ApiResponse,
|
||||
};
|
||||
@@ -98,7 +98,7 @@ pub async fn create_task_and_start(
|
||||
Path(project_id): Path<Uuid>,
|
||||
Extension(pool): Extension<SqlitePool>,
|
||||
Extension(app_state): Extension<crate::app_state::AppState>,
|
||||
Json(mut payload): Json<CreateTask>,
|
||||
Json(mut payload): Json<CreateTaskAndStart>,
|
||||
) -> Result<ResponseJson<ApiResponse<Task>>, StatusCode> {
|
||||
let task_id = Uuid::new_v4();
|
||||
|
||||
@@ -122,7 +122,12 @@ pub async fn create_task_and_start(
|
||||
);
|
||||
|
||||
// Create the task first
|
||||
let task = match Task::create(&pool, &payload, task_id).await {
|
||||
let create_task_payload = CreateTask {
|
||||
project_id: payload.project_id,
|
||||
title: payload.title.clone(),
|
||||
description: payload.description.clone(),
|
||||
};
|
||||
let task = match Task::create(&pool, &create_task_payload, task_id).await {
|
||||
Ok(task) => task,
|
||||
Err(e) => {
|
||||
tracing::error!("Failed to create task: {}", e);
|
||||
@@ -132,8 +137,13 @@ pub async fn create_task_and_start(
|
||||
|
||||
// Create task attempt
|
||||
let attempt_id = Uuid::new_v4();
|
||||
let executor_string = payload.executor.as_ref().map(|exec| match exec {
|
||||
crate::executor::ExecutorConfig::Echo => "echo".to_string(),
|
||||
crate::executor::ExecutorConfig::Claude => "claude".to_string(),
|
||||
crate::executor::ExecutorConfig::Amp => "amp".to_string(),
|
||||
});
|
||||
let attempt_payload = CreateTaskAttempt {
|
||||
executor: Some("claude".to_string()), // Default executor
|
||||
executor: executor_string,
|
||||
};
|
||||
|
||||
match TaskAttempt::create(&pool, &attempt_payload, attempt_id, task_id).await {
|
||||
|
||||
@@ -1,11 +1,10 @@
|
||||
import { Link, useLocation } from "react-router-dom";
|
||||
import { Button } from "@/components/ui/button";
|
||||
import { ArrowLeft, FolderOpen, Settings } from "lucide-react";
|
||||
import { FolderOpen, Settings } from "lucide-react";
|
||||
import { Logo } from "@/components/logo";
|
||||
|
||||
export function Navbar() {
|
||||
const location = useLocation();
|
||||
const isHome = location.pathname === "/";
|
||||
|
||||
return (
|
||||
<div className="border-b">
|
||||
|
||||
@@ -16,7 +16,8 @@ import {
|
||||
SelectTrigger,
|
||||
SelectValue
|
||||
} from '@/components/ui/select'
|
||||
import type { TaskStatus } from 'shared/types'
|
||||
import { useConfig } from '@/components/config-provider'
|
||||
import type { TaskStatus, ExecutorConfig } from 'shared/types'
|
||||
|
||||
interface Task {
|
||||
id: string
|
||||
@@ -34,7 +35,7 @@ interface TaskFormDialogProps {
|
||||
task?: Task | null // Optional for create mode
|
||||
projectId?: string // For file search functionality
|
||||
onCreateTask?: (title: string, description: string) => Promise<void>
|
||||
onCreateAndStartTask?: (title: string, description: string) => Promise<void>
|
||||
onCreateAndStartTask?: (title: string, description: string, executor?: ExecutorConfig) => Promise<void>
|
||||
onUpdateTask?: (title: string, description: string, status: TaskStatus) => Promise<void>
|
||||
}
|
||||
|
||||
@@ -53,6 +54,7 @@ export function TaskFormDialog({
|
||||
const [isSubmitting, setIsSubmitting] = useState(false)
|
||||
const [isSubmittingAndStart, setIsSubmittingAndStart] = useState(false)
|
||||
|
||||
const { config } = useConfig()
|
||||
const isEditMode = Boolean(task)
|
||||
|
||||
useEffect(() => {
|
||||
@@ -99,7 +101,7 @@ export function TaskFormDialog({
|
||||
setIsSubmittingAndStart(true)
|
||||
try {
|
||||
if (!isEditMode && onCreateAndStartTask) {
|
||||
await onCreateAndStartTask(title, description)
|
||||
await onCreateAndStartTask(title, description, config?.executor)
|
||||
}
|
||||
|
||||
// Reset form on successful creation
|
||||
|
||||
@@ -14,7 +14,13 @@ import {
|
||||
|
||||
import { TaskKanbanBoard } from "@/components/tasks/TaskKanbanBoard";
|
||||
import { TaskDetailsPanel } from "@/components/tasks/TaskDetailsPanel";
|
||||
import type { TaskStatus, TaskWithAttemptStatus, Project } from "shared/types";
|
||||
import type {
|
||||
TaskStatus,
|
||||
TaskWithAttemptStatus,
|
||||
Project,
|
||||
ExecutorConfig,
|
||||
CreateTaskAndStart,
|
||||
} from "shared/types";
|
||||
import type { DragEndEvent } from "@/components/ui/shadcn-io/kanban";
|
||||
|
||||
type Task = TaskWithAttemptStatus;
|
||||
@@ -26,7 +32,10 @@ interface ApiResponse<T> {
|
||||
}
|
||||
|
||||
export function ProjectTasks() {
|
||||
const { projectId, taskId } = useParams<{ projectId: string; taskId?: string }>();
|
||||
const { projectId, taskId } = useParams<{
|
||||
projectId: string;
|
||||
taskId?: string;
|
||||
}>();
|
||||
const navigate = useNavigate();
|
||||
const [tasks, setTasks] = useState<Task[]>([]);
|
||||
const [project, setProject] = useState<Project | null>(null);
|
||||
@@ -73,7 +82,7 @@ export function ProjectTasks() {
|
||||
// Handle direct navigation to task URLs
|
||||
useEffect(() => {
|
||||
if (taskId && tasks.length > 0) {
|
||||
const task = tasks.find(t => t.id === taskId);
|
||||
const task = tasks.find((t) => t.id === taskId);
|
||||
if (task) {
|
||||
setSelectedTask(task);
|
||||
setIsPanelOpen(true);
|
||||
@@ -115,15 +124,21 @@ export function ProjectTasks() {
|
||||
if (JSON.stringify(prevTasks) === JSON.stringify(newTasks)) {
|
||||
return prevTasks; // Return same reference to prevent re-render
|
||||
}
|
||||
|
||||
|
||||
// Update selectedTask if it exists and has been modified
|
||||
if (selectedTask) {
|
||||
const updatedSelectedTask = newTasks.find(task => task.id === selectedTask.id);
|
||||
if (updatedSelectedTask && JSON.stringify(selectedTask) !== JSON.stringify(updatedSelectedTask)) {
|
||||
const updatedSelectedTask = newTasks.find(
|
||||
(task) => task.id === selectedTask.id
|
||||
);
|
||||
if (
|
||||
updatedSelectedTask &&
|
||||
JSON.stringify(selectedTask) !==
|
||||
JSON.stringify(updatedSelectedTask)
|
||||
) {
|
||||
setSelectedTask(updatedSelectedTask);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return newTasks;
|
||||
});
|
||||
}
|
||||
@@ -162,18 +177,22 @@ export function ProjectTasks() {
|
||||
|
||||
const handleCreateAndStartTask = async (
|
||||
title: string,
|
||||
description: string
|
||||
description: string,
|
||||
executor?: ExecutorConfig
|
||||
) => {
|
||||
try {
|
||||
const payload: CreateTaskAndStart = {
|
||||
project_id: projectId!,
|
||||
title,
|
||||
description: description || null,
|
||||
executor: executor || null,
|
||||
};
|
||||
|
||||
const response = await makeRequest(
|
||||
`/api/projects/${projectId}/tasks/create-and-start`,
|
||||
{
|
||||
method: "POST",
|
||||
body: JSON.stringify({
|
||||
project_id: projectId,
|
||||
title,
|
||||
description: description || null,
|
||||
}),
|
||||
body: JSON.stringify(payload),
|
||||
}
|
||||
);
|
||||
|
||||
|
||||
@@ -26,6 +26,8 @@ export type SearchMatchType = "FileName" | "DirectoryName" | "FullPath";
|
||||
|
||||
export type CreateTask = { project_id: string, title: string, description: string | null, };
|
||||
|
||||
export type CreateTaskAndStart = { project_id: string, title: string, description: string | null, executor: ExecutorConfig | null, };
|
||||
|
||||
export type TaskStatus = "todo" | "inprogress" | "inreview" | "done" | "cancelled";
|
||||
|
||||
export type Task = { id: string, project_id: string, title: string, description: string | null, status: TaskStatus, created_at: string, updated_at: string, };
|
||||
|
||||
Reference in New Issue
Block a user