Add example programs
- examples/basic: Client setup, projects, tasks, and create operations - examples/fluent: Fluent API with TaskParams, TaskUpdateParams, tags - examples/search: Project-specific and global search functionality
This commit is contained in:
parent
ff06643bc8
commit
a2913c6b8d
4 changed files with 317 additions and 2 deletions
83
examples/basic/main.go
Normal file
83
examples/basic/main.go
Normal file
|
|
@ -0,0 +1,83 @@
|
|||
// Example: basic demonstrates basic client setup and simple operations.
|
||||
package main
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"log"
|
||||
"os"
|
||||
"time"
|
||||
|
||||
kanboard "code.beautifulmachines.dev/jakoubek/kanboard-api"
|
||||
)
|
||||
|
||||
func main() {
|
||||
// Read configuration from environment
|
||||
baseURL := os.Getenv("KANBOARD_URL")
|
||||
token := os.Getenv("KANBOARD_TOKEN")
|
||||
|
||||
if baseURL == "" || token == "" {
|
||||
log.Fatal("Set KANBOARD_URL and KANBOARD_TOKEN environment variables")
|
||||
}
|
||||
|
||||
// Create a client with API token authentication
|
||||
client := kanboard.NewClient(baseURL).
|
||||
WithAPIToken(token).
|
||||
WithTimeout(30 * time.Second)
|
||||
|
||||
ctx := context.Background()
|
||||
|
||||
// Get all projects
|
||||
projects, err := client.GetAllProjects(ctx)
|
||||
if err != nil {
|
||||
log.Fatalf("Failed to get projects: %v", err)
|
||||
}
|
||||
|
||||
fmt.Printf("Found %d projects:\n", len(projects))
|
||||
for _, p := range projects {
|
||||
fmt.Printf(" - [%d] %s\n", p.ID, p.Name)
|
||||
}
|
||||
|
||||
if len(projects) == 0 {
|
||||
fmt.Println("No projects found. Create one in Kanboard first.")
|
||||
return
|
||||
}
|
||||
|
||||
// Use the first project
|
||||
projectID := int(projects[0].ID)
|
||||
|
||||
// Get all active tasks for the project
|
||||
tasks, err := client.GetAllTasks(ctx, projectID, kanboard.StatusActive)
|
||||
if err != nil {
|
||||
log.Fatalf("Failed to get tasks: %v", err)
|
||||
}
|
||||
|
||||
fmt.Printf("\nActive tasks in project %d:\n", projectID)
|
||||
for _, t := range tasks {
|
||||
fmt.Printf(" - [%d] %s\n", t.ID, t.Title)
|
||||
}
|
||||
|
||||
// Create a simple task using the direct API
|
||||
newTask, err := client.CreateTask(ctx, kanboard.CreateTaskRequest{
|
||||
Title: "Task created via API",
|
||||
ProjectID: projectID,
|
||||
Description: "This task was created using the kanboard-api library.",
|
||||
})
|
||||
if err != nil {
|
||||
log.Fatalf("Failed to create task: %v", err)
|
||||
}
|
||||
|
||||
fmt.Printf("\nCreated task: [%d] %s\n", newTask.ID, newTask.Title)
|
||||
|
||||
// Get task details
|
||||
task, err := client.GetTask(ctx, int(newTask.ID))
|
||||
if err != nil {
|
||||
log.Fatalf("Failed to get task: %v", err)
|
||||
}
|
||||
|
||||
fmt.Printf("Task details:\n")
|
||||
fmt.Printf(" Title: %s\n", task.Title)
|
||||
fmt.Printf(" Description: %s\n", task.Description)
|
||||
fmt.Printf(" Column ID: %d\n", task.ColumnID)
|
||||
fmt.Printf(" Created: %s\n", task.DateCreation.Time.Format(time.RFC3339))
|
||||
}
|
||||
116
examples/fluent/main.go
Normal file
116
examples/fluent/main.go
Normal file
|
|
@ -0,0 +1,116 @@
|
|||
// Example: fluent demonstrates the fluent API for task management.
|
||||
package main
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"log"
|
||||
"log/slog"
|
||||
"os"
|
||||
"time"
|
||||
|
||||
kanboard "code.beautifulmachines.dev/jakoubek/kanboard-api"
|
||||
)
|
||||
|
||||
func main() {
|
||||
// Read configuration from environment
|
||||
baseURL := os.Getenv("KANBOARD_URL")
|
||||
token := os.Getenv("KANBOARD_TOKEN")
|
||||
|
||||
if baseURL == "" || token == "" {
|
||||
log.Fatal("Set KANBOARD_URL and KANBOARD_TOKEN environment variables")
|
||||
}
|
||||
|
||||
// Create a fully configured client
|
||||
client := kanboard.NewClient(baseURL).
|
||||
WithAPIToken(token).
|
||||
WithTimeout(60 * time.Second).
|
||||
WithLogger(slog.Default()) // Enable debug logging
|
||||
|
||||
ctx := context.Background()
|
||||
|
||||
// Get the first project
|
||||
projects, err := client.GetAllProjects(ctx)
|
||||
if err != nil {
|
||||
log.Fatalf("Failed to get projects: %v", err)
|
||||
}
|
||||
if len(projects) == 0 {
|
||||
log.Fatal("No projects found")
|
||||
}
|
||||
projectID := int(projects[0].ID)
|
||||
|
||||
// Use BoardScope for project-scoped operations
|
||||
board := client.Board(projectID)
|
||||
|
||||
// Get columns to understand the workflow
|
||||
columns, err := board.GetColumns(ctx)
|
||||
if err != nil {
|
||||
log.Fatalf("Failed to get columns: %v", err)
|
||||
}
|
||||
fmt.Println("Columns in project:")
|
||||
for _, c := range columns {
|
||||
fmt.Printf(" - [%d] %s (position: %d)\n", c.ID, c.Title, c.Position)
|
||||
}
|
||||
|
||||
// Create a task using TaskParams (fluent builder)
|
||||
params := kanboard.NewTask("Feature: User Dashboard").
|
||||
WithDescription("Implement the user dashboard with activity feed").
|
||||
WithPriority(2).
|
||||
WithScore(5).
|
||||
WithTags("feature", "frontend", "v2.0").
|
||||
WithDueDate(time.Now().Add(14 * 24 * time.Hour))
|
||||
|
||||
task, err := board.CreateTaskFromParams(ctx, params)
|
||||
if err != nil {
|
||||
log.Fatalf("Failed to create task: %v", err)
|
||||
}
|
||||
fmt.Printf("\nCreated task: [%d] %s\n", task.ID, task.Title)
|
||||
|
||||
// Use TaskScope for task-scoped operations
|
||||
taskScope := client.Task(int(task.ID))
|
||||
|
||||
// Add more tags
|
||||
if err := taskScope.AddTag(ctx, "priority"); err != nil {
|
||||
log.Fatalf("Failed to add tag: %v", err)
|
||||
}
|
||||
fmt.Println("Added 'priority' tag")
|
||||
|
||||
// Get current tags
|
||||
tags, err := taskScope.GetTags(ctx)
|
||||
if err != nil {
|
||||
log.Fatalf("Failed to get tags: %v", err)
|
||||
}
|
||||
fmt.Printf("Current tags: %v\n", tags)
|
||||
|
||||
// Update the task using TaskUpdateParams
|
||||
updates := kanboard.NewTaskUpdate().
|
||||
SetTitle("Feature: Enhanced User Dashboard").
|
||||
SetDescription("Implement user dashboard with activity feed and notifications").
|
||||
SetPriority(1)
|
||||
|
||||
if err := taskScope.Update(ctx, updates); err != nil {
|
||||
log.Fatalf("Failed to update task: %v", err)
|
||||
}
|
||||
fmt.Println("Updated task title and priority")
|
||||
|
||||
// Move task to next column
|
||||
if err := taskScope.MoveToNextColumn(ctx); err != nil {
|
||||
if err == kanboard.ErrAlreadyInLastColumn {
|
||||
fmt.Println("Task is already in the last column")
|
||||
} else {
|
||||
log.Fatalf("Failed to move task: %v", err)
|
||||
}
|
||||
} else {
|
||||
fmt.Println("Moved task to next column")
|
||||
}
|
||||
|
||||
// Get updated task details
|
||||
updated, err := taskScope.Get(ctx)
|
||||
if err != nil {
|
||||
log.Fatalf("Failed to get task: %v", err)
|
||||
}
|
||||
fmt.Printf("\nUpdated task:\n")
|
||||
fmt.Printf(" Title: %s\n", updated.Title)
|
||||
fmt.Printf(" Column: %d\n", updated.ColumnID)
|
||||
fmt.Printf(" Priority: %d\n", updated.Priority)
|
||||
}
|
||||
116
examples/search/main.go
Normal file
116
examples/search/main.go
Normal file
|
|
@ -0,0 +1,116 @@
|
|||
// Example: search demonstrates search functionality.
|
||||
package main
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"log"
|
||||
"os"
|
||||
"time"
|
||||
|
||||
kanboard "code.beautifulmachines.dev/jakoubek/kanboard-api"
|
||||
)
|
||||
|
||||
func main() {
|
||||
// Read configuration from environment
|
||||
baseURL := os.Getenv("KANBOARD_URL")
|
||||
token := os.Getenv("KANBOARD_TOKEN")
|
||||
|
||||
if baseURL == "" || token == "" {
|
||||
log.Fatal("Set KANBOARD_URL and KANBOARD_TOKEN environment variables")
|
||||
}
|
||||
|
||||
client := kanboard.NewClient(baseURL).
|
||||
WithAPIToken(token).
|
||||
WithTimeout(30 * time.Second)
|
||||
|
||||
ctx := context.Background()
|
||||
|
||||
// Get the first project for project-specific search
|
||||
projects, err := client.GetAllProjects(ctx)
|
||||
if err != nil {
|
||||
log.Fatalf("Failed to get projects: %v", err)
|
||||
}
|
||||
if len(projects) == 0 {
|
||||
log.Fatal("No projects found")
|
||||
}
|
||||
projectID := int(projects[0].ID)
|
||||
fmt.Printf("Using project: %s (ID: %d)\n\n", projects[0].Name, projectID)
|
||||
|
||||
// Project-specific search using Kanboard query syntax
|
||||
// See: https://docs.kanboard.org/v1/user/search/
|
||||
fmt.Println("=== Project-Specific Search ===")
|
||||
|
||||
// Search for open tasks
|
||||
tasks, err := client.SearchTasks(ctx, projectID, "status:open")
|
||||
if err != nil {
|
||||
log.Fatalf("Failed to search: %v", err)
|
||||
}
|
||||
fmt.Printf("Open tasks: %d\n", len(tasks))
|
||||
for _, t := range tasks {
|
||||
fmt.Printf(" - [%d] %s\n", t.ID, t.Title)
|
||||
}
|
||||
|
||||
// Search by title keyword
|
||||
tasks, err = client.Board(projectID).SearchTasks(ctx, "title:feature")
|
||||
if err != nil {
|
||||
log.Fatalf("Failed to search: %v", err)
|
||||
}
|
||||
fmt.Printf("\nTasks with 'feature' in title: %d\n", len(tasks))
|
||||
for _, t := range tasks {
|
||||
fmt.Printf(" - [%d] %s\n", t.ID, t.Title)
|
||||
}
|
||||
|
||||
// Search overdue tasks
|
||||
tasks, err = client.SearchTasks(ctx, projectID, "due:<today")
|
||||
if err != nil {
|
||||
log.Fatalf("Failed to search: %v", err)
|
||||
}
|
||||
fmt.Printf("\nOverdue tasks: %d\n", len(tasks))
|
||||
for _, t := range tasks {
|
||||
fmt.Printf(" - [%d] %s (due: %s)\n", t.ID, t.Title, t.DateDue.Time.Format("2006-01-02"))
|
||||
}
|
||||
|
||||
// Global search across ALL projects
|
||||
fmt.Println("\n=== Global Search (All Projects) ===")
|
||||
|
||||
// This searches in parallel across all accessible projects
|
||||
allTasks, err := client.SearchTasksGlobally(ctx, "status:open")
|
||||
if err != nil {
|
||||
log.Fatalf("Failed to global search: %v", err)
|
||||
}
|
||||
fmt.Printf("Open tasks across all projects: %d\n", len(allTasks))
|
||||
|
||||
// Group results by project
|
||||
byProject := make(map[int][]kanboard.Task)
|
||||
for _, t := range allTasks {
|
||||
pid := int(t.ProjectID)
|
||||
byProject[pid] = append(byProject[pid], t)
|
||||
}
|
||||
|
||||
for pid, tasks := range byProject {
|
||||
fmt.Printf("\n Project %d: %d tasks\n", pid, len(tasks))
|
||||
for _, t := range tasks {
|
||||
fmt.Printf(" - [%d] %s\n", t.ID, t.Title)
|
||||
}
|
||||
}
|
||||
|
||||
// Search examples with Kanboard query syntax
|
||||
fmt.Println("\n=== Query Syntax Examples ===")
|
||||
fmt.Println("Kanboard supports rich query syntax:")
|
||||
fmt.Println(" status:open - Open tasks")
|
||||
fmt.Println(" status:closed - Closed tasks")
|
||||
fmt.Println(" assignee:me - Tasks assigned to current user")
|
||||
fmt.Println(" due:today - Tasks due today")
|
||||
fmt.Println(" due:<tomorrow - Tasks due before tomorrow")
|
||||
fmt.Println(" due:>2024-01-01 - Tasks due after date")
|
||||
fmt.Println(" title:\"bug fix\" - Tasks with exact title match")
|
||||
fmt.Println(" color:red - Tasks with red color")
|
||||
fmt.Println(" category:\"Bug\" - Tasks in category")
|
||||
fmt.Println(" tag:urgent - Tasks with tag")
|
||||
fmt.Println(" priority:3 - Tasks with priority")
|
||||
fmt.Println()
|
||||
fmt.Println("Combine queries with spaces (AND) or | (OR):")
|
||||
fmt.Println(" status:open assignee:me - Open tasks assigned to me")
|
||||
fmt.Println(" status:open | status:closed - All tasks")
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue