feat: initial release v0.3.0
- Support 9 chart types: line, bar, pie, scatter, bubble, donut, mixed, polar, radar - Multi-format output: ANSI, SVG, PNG, Markdown - Go + Fiber + gonum/plot - Docker support - Morandi color palette
This commit is contained in:
96
internal/handler/chart.go
Normal file
96
internal/handler/chart.go
Normal file
@@ -0,0 +1,96 @@
|
||||
package handler
|
||||
|
||||
import (
|
||||
"github.com/gofiber/fiber/v2"
|
||||
"github.com/picoclaw/chart/internal/service"
|
||||
"github.com/picoclaw/chart/internal/types"
|
||||
)
|
||||
|
||||
type ChartHandler struct {
|
||||
chartService *service.ChartService
|
||||
}
|
||||
|
||||
func NewChartHandler(chartService *service.ChartService) *ChartHandler {
|
||||
return &ChartHandler{
|
||||
chartService: chartService,
|
||||
}
|
||||
}
|
||||
|
||||
func (h *ChartHandler) CreateChart(c *fiber.Ctx) error {
|
||||
var req types.ChartRequest
|
||||
if err := c.BodyParser(&req); err != nil {
|
||||
return c.Status(fiber.StatusBadRequest).JSON(types.ErrorResponse{
|
||||
Error: "invalid request body: " + err.Error(),
|
||||
})
|
||||
}
|
||||
|
||||
if req.Type == "" {
|
||||
req.Type = types.ChartTypeLine
|
||||
}
|
||||
|
||||
if len(req.Data.Datasets) == 0 {
|
||||
return c.Status(fiber.StatusBadRequest).JSON(types.ErrorResponse{
|
||||
Error: "datasets are required",
|
||||
})
|
||||
}
|
||||
|
||||
for _, dataset := range req.Data.Datasets {
|
||||
if len(dataset.Values) == 0 {
|
||||
return c.Status(fiber.StatusBadRequest).JSON(types.ErrorResponse{
|
||||
Error: "dataset values cannot be empty",
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
resp, err := h.chartService.CreateChart(&req)
|
||||
if err != nil {
|
||||
return c.Status(fiber.StatusInternalServerError).JSON(types.ErrorResponse{
|
||||
Error: err.Error(),
|
||||
})
|
||||
}
|
||||
|
||||
return c.Status(fiber.StatusCreated).JSON(resp)
|
||||
}
|
||||
|
||||
func (h *ChartHandler) GetChart(c *fiber.Ctx) error {
|
||||
id := c.Params("id")
|
||||
if id == "" {
|
||||
return c.Status(fiber.StatusBadRequest).JSON(types.ErrorResponse{
|
||||
Error: "chart id is required",
|
||||
})
|
||||
}
|
||||
|
||||
chart, err := h.chartService.GetChart(id)
|
||||
if err != nil {
|
||||
return c.Status(fiber.StatusNotFound).JSON(types.ErrorResponse{
|
||||
Error: err.Error(),
|
||||
})
|
||||
}
|
||||
|
||||
return c.Send(chart.SVG)
|
||||
}
|
||||
|
||||
func (h *ChartHandler) GetChartPNG(c *fiber.Ctx) error {
|
||||
id := c.Params("id")
|
||||
if id == "" {
|
||||
return c.Status(fiber.StatusBadRequest).JSON(types.ErrorResponse{
|
||||
Error: "chart id is required",
|
||||
})
|
||||
}
|
||||
|
||||
pngData, err := h.chartService.GetChartPNG(id)
|
||||
if err != nil {
|
||||
return c.Status(fiber.StatusNotFound).JSON(types.ErrorResponse{
|
||||
Error: err.Error(),
|
||||
})
|
||||
}
|
||||
|
||||
c.Set("Content-Type", "image/png")
|
||||
return c.Send(pngData)
|
||||
}
|
||||
|
||||
func (h *ChartHandler) Health(c *fiber.Ctx) error {
|
||||
return c.JSON(fiber.Map{
|
||||
"status": "ok",
|
||||
})
|
||||
}
|
||||
Reference in New Issue
Block a user