summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPeter Stone <thepeterstone@gmail.com>2026-01-19 09:54:42 -1000
committerPeter Stone <thepeterstone@gmail.com>2026-01-19 09:54:42 -1000
commita38abc90ee4fe00bf0fbdf897c5ef93e80e0c256 (patch)
tree0936c38580482f9de52e8b1e8c207e8d11f3457b
parent2215aaa458b318edb16337ab56cf658117023eb4 (diff)
Refactor: Add cache key constants and configurable template path
Code quality improvements: - Define CacheKey* constants in store package for type safety - Add TemplateDir to config (default: web/templates, env: TEMPLATE_DIR) - Update handlers to use store.CacheKey* instead of hardcoded strings - Update NewTabsHandler to accept templateDir parameter - Use filepath.Join for cross-platform template path construction Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
-rw-r--r--cmd/dashboard/main.go2
-rw-r--r--internal/config/config.go2
-rw-r--r--internal/handlers/handlers.go21
-rw-r--r--internal/handlers/heuristic_test.go2
-rw-r--r--internal/handlers/tabs.go7
-rw-r--r--internal/store/sqlite.go8
6 files changed, 27 insertions, 15 deletions
diff --git a/cmd/dashboard/main.go b/cmd/dashboard/main.go
index 30b90ab..e52aeb0 100644
--- a/cmd/dashboard/main.go
+++ b/cmd/dashboard/main.go
@@ -52,7 +52,7 @@ func main() {
// Initialize handlers
h := handlers.New(db, todoistClient, trelloClient, obsidianClient, planToEatClient, cfg)
- tabsHandler := handlers.NewTabsHandler(db)
+ tabsHandler := handlers.NewTabsHandler(db, cfg.TemplateDir)
// Set up router
r := chi.NewRouter()
diff --git a/internal/config/config.go b/internal/config/config.go
index dc7d1c3..93f57cc 100644
--- a/internal/config/config.go
+++ b/internal/config/config.go
@@ -17,6 +17,7 @@ type Config struct {
// Paths
ObsidianVaultPath string
DatabasePath string
+ TemplateDir string
// Server
Port string
@@ -36,6 +37,7 @@ func Load() (*Config, error) {
// Paths
ObsidianVaultPath: os.Getenv("OBSIDIAN_VAULT_PATH"),
DatabasePath: getEnvWithDefault("DATABASE_PATH", "./dashboard.db"),
+ TemplateDir: getEnvWithDefault("TEMPLATE_DIR", "web/templates"),
// Server
Port: getEnvWithDefault("PORT", "8080"),
diff --git a/internal/handlers/handlers.go b/internal/handlers/handlers.go
index 20095fe..0af2bba 100644
--- a/internal/handlers/handlers.go
+++ b/internal/handlers/handlers.go
@@ -7,6 +7,7 @@ import (
"html/template"
"log"
"net/http"
+ "path/filepath"
"sort"
"strings"
"sync"
@@ -30,21 +31,21 @@ type Handler struct {
}
// New creates a new Handler instance
-func New(store *store.Store, todoist api.TodoistAPI, trello api.TrelloAPI, obsidian api.ObsidianAPI, planToEat api.PlanToEatAPI, cfg *config.Config) *Handler {
+func New(s *store.Store, todoist api.TodoistAPI, trello api.TrelloAPI, obsidian api.ObsidianAPI, planToEat api.PlanToEatAPI, cfg *config.Config) *Handler {
// Parse templates including partials
- tmpl, err := template.ParseGlob("web/templates/*.html")
+ tmpl, err := template.ParseGlob(filepath.Join(cfg.TemplateDir, "*.html"))
if err != nil {
log.Printf("Warning: failed to parse templates: %v", err)
}
// Also parse partials
- tmpl, err = tmpl.ParseGlob("web/templates/partials/*.html")
+ tmpl, err = tmpl.ParseGlob(filepath.Join(cfg.TemplateDir, "partials", "*.html"))
if err != nil {
log.Printf("Warning: failed to parse partial templates: %v", err)
}
return &Handler{
- store: store,
+ store: s,
todoistClient: todoist,
trelloClient: trello,
obsidianClient: obsidian,
@@ -351,7 +352,7 @@ func (h *Handler) aggregateData(ctx context.Context, forceRefresh bool) (*models
// fetchTasks fetches tasks from cache or API
func (h *Handler) fetchTasks(ctx context.Context, forceRefresh bool) ([]models.Task, error) {
- cacheKey := "todoist_tasks"
+ cacheKey := store.CacheKeyTodoistTasks
// Check cache validity
if !forceRefresh {
@@ -387,7 +388,7 @@ func (h *Handler) fetchTasks(ctx context.Context, forceRefresh bool) ([]models.T
// fetchNotes fetches notes from cache or filesystem
func (h *Handler) fetchNotes(ctx context.Context, forceRefresh bool) ([]models.Note, error) {
- cacheKey := "obsidian_notes"
+ cacheKey := store.CacheKeyObsidianNotes
// Check cache validity
if !forceRefresh {
@@ -423,7 +424,7 @@ func (h *Handler) fetchNotes(ctx context.Context, forceRefresh bool) ([]models.N
// fetchMeals fetches meals from cache or API
func (h *Handler) fetchMeals(ctx context.Context, forceRefresh bool) ([]models.Meal, error) {
- cacheKey := "plantoeat_meals"
+ cacheKey := store.CacheKeyPlanToEatMeals
// Check cache validity
if !forceRefresh {
@@ -463,7 +464,7 @@ func (h *Handler) fetchMeals(ctx context.Context, forceRefresh bool) ([]models.M
// fetchBoards fetches Trello boards from cache or API
func (h *Handler) fetchBoards(ctx context.Context, forceRefresh bool) ([]models.Board, error) {
- cacheKey := "trello_boards"
+ cacheKey := store.CacheKeyTrelloBoards
// Check cache validity
if !forceRefresh {
@@ -765,7 +766,7 @@ func (h *Handler) HandleUnifiedAdd(w http.ResponseWriter, r *http.Request) {
return
}
// Invalidate cache so fresh data is fetched
- h.store.InvalidateCache("todoist_tasks")
+ h.store.InvalidateCache(store.CacheKeyTodoistTasks)
case "trello":
listID := r.FormValue("list_id")
@@ -780,7 +781,7 @@ func (h *Handler) HandleUnifiedAdd(w http.ResponseWriter, r *http.Request) {
return
}
// Invalidate cache so fresh data is fetched
- h.store.InvalidateCache("trello_boards")
+ h.store.InvalidateCache(store.CacheKeyTrelloBoards)
default:
http.Error(w, "Invalid source", http.StatusBadRequest)
diff --git a/internal/handlers/heuristic_test.go b/internal/handlers/heuristic_test.go
index f76fdc0..dc8620a 100644
--- a/internal/handlers/heuristic_test.go
+++ b/internal/handlers/heuristic_test.go
@@ -63,7 +63,7 @@ func TestHandleTasks_Heuristic(t *testing.T) {
}
// Create Handler
- h := NewTabsHandler(db)
+ h := NewTabsHandler(db, "../../web/templates")
// Skip if templates are not loaded
if h.templates == nil {
diff --git a/internal/handlers/tabs.go b/internal/handlers/tabs.go
index 74dfbe8..ffdabb0 100644
--- a/internal/handlers/tabs.go
+++ b/internal/handlers/tabs.go
@@ -4,6 +4,7 @@ import (
"html/template"
"log"
"net/http"
+ "path/filepath"
"sort"
"strings"
"time"
@@ -31,15 +32,15 @@ type TabsHandler struct {
}
// NewTabsHandler creates a new TabsHandler instance
-func NewTabsHandler(store *store.Store) *TabsHandler {
+func NewTabsHandler(store *store.Store, templateDir string) *TabsHandler {
// Parse templates including partials
- tmpl, err := template.ParseGlob("web/templates/*.html")
+ tmpl, err := template.ParseGlob(filepath.Join(templateDir, "*.html"))
if err != nil {
log.Printf("Warning: failed to parse templates: %v", err)
}
// Also parse partials
- tmpl, err = tmpl.ParseGlob("web/templates/partials/*.html")
+ tmpl, err = tmpl.ParseGlob(filepath.Join(templateDir, "partials", "*.html"))
if err != nil {
log.Printf("Warning: failed to parse partial templates: %v", err)
}
diff --git a/internal/store/sqlite.go b/internal/store/sqlite.go
index 259bd0f..5f58fd4 100644
--- a/internal/store/sqlite.go
+++ b/internal/store/sqlite.go
@@ -13,6 +13,14 @@ import (
"task-dashboard/internal/models"
)
+// Cache key constants
+const (
+ CacheKeyTodoistTasks = "todoist_tasks"
+ CacheKeyTrelloBoards = "trello_boards"
+ CacheKeyObsidianNotes = "obsidian_notes"
+ CacheKeyPlanToEatMeals = "plantoeat_meals"
+)
+
type Store struct {
db *sql.DB
}