Skip to content

Commit

Permalink
✨ Add missing handlers
Browse files Browse the repository at this point in the history
  • Loading branch information
wesen committed Dec 31, 2024
1 parent 4965f2c commit 09dda72
Show file tree
Hide file tree
Showing 11 changed files with 161 additions and 38 deletions.
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
module github.com/go-go-golems/prompto

go 1.21
go 1.22

toolchain go1.23.3

Expand Down
104 changes: 104 additions & 0 deletions pkg/server/handlers/prompt.go
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
package handlers

import (
"fmt"
"net/http"
"strings"

"github.com/go-go-golems/prompto/pkg"
"github.com/go-go-golems/prompto/pkg/server/templates/components"
"github.com/rs/zerolog/log"
)

func (h *Handlers) PromptList() http.HandlerFunc {
Expand All @@ -31,6 +33,108 @@ func (h *Handlers) PromptList() http.HandlerFunc {
}
}

func (h *Handlers) PromptContent() http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
logger := log.With().Str("handler", "PromptContent").Logger()

name := r.PathValue("name")
logger.Debug().Str("path", name).Msg("handling prompt request")

if name == "" {
logger.Debug().Msg("invalid path: empty name")
http.Error(w, "Invalid path", http.StatusBadRequest)
return
}

// Handle root directory listing
if name == "" {
logger.Debug().Msg("rendering root directory listing")
var allPrompts []pkg.Prompto
for _, repo := range h.state.Repos {
allPrompts = append(allPrompts, repo.GetPromptos()...)
}
component := components.PromptList(allPrompts)
component.Render(r.Context(), w)
return
}

// Split the path into group and prompt path
parts := strings.SplitN(name, "/", 2)

// Handle group listing
if len(parts) == 1 {
group := parts[0]
logger = logger.With().Str("group", group).Logger()
logger.Debug().Msg("rendering group listing")

// Get all prompts from this group across all repositories
var prompts []pkg.Prompto
for _, repo := range h.state.Repos {
prompts = append(prompts, repo.GetPromptosByGroup(group)...)
}

component := components.PromptList(prompts)
component.Render(r.Context(), w)
return
}

group := parts[0]
promptPath := name
logger = logger.With().
Str("group", group).
Str("promptPath", promptPath).
Logger()

logger.Debug().Msg("looking up prompt")

// Get all prompts for this group and find the matching one
files := h.state.GetPromptosByGroup(group)
var foundFile pkg.Prompto
for _, file := range files {
if file.Name == promptPath {
foundFile = file
break
}
}

if foundFile.Name == "" {
logger.Debug().Msg("prompt not found")
http.Error(w, "Prompt not found", http.StatusNotFound)
return
}

logger = logger.With().
Str("repository", foundFile.Repository).
Str("prompt", foundFile.Name).
Logger()
logger.Debug().Msg("found prompt, rendering with args")

// Extract URL parameters
queryParams := r.URL.Query()
var restArgs []string
for key, values := range queryParams {
for _, value := range values {
if value == "" {
// pass non-keyword arguments as a straight string
restArgs = append(restArgs, key)
} else {
restArgs = append(restArgs, fmt.Sprintf("--%s", key), value)
}
}
}

content, err := foundFile.Render(foundFile.Repository, restArgs)
if err != nil {
logger.Debug().Err(err).Msg("error rendering prompt")
http.Error(w, "Error rendering prompt", http.StatusInternalServerError)
return
}

w.Header().Set("Content-Type", "text/markdown")
_, _ = w.Write([]byte(content))
}
}

func (h *Handlers) Search() http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
query := r.URL.Query().Get("q")
Expand Down
22 changes: 22 additions & 0 deletions pkg/server/handlers/refresh.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
package handlers

import (
"net/http"
)

func (h *Handlers) Refresh() http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
if r.Method != http.MethodPost {
http.Error(w, "Method not allowed", http.StatusMethodNotAllowed)
return
}

if err := h.state.LoadRepositories(); err != nil {
http.Error(w, "Error refreshing repositories", http.StatusInternalServerError)
return
}

w.WriteHeader(http.StatusOK)
_, _ = w.Write([]byte("Repositories refreshed successfully"))
}
}
19 changes: 19 additions & 0 deletions pkg/server/handlers/repositories.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package handlers

import (
"encoding/json"
"net/http"
)

func (h *Handlers) Repositories() http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
repos := h.state.GetAllRepositories()

w.Header().Set("Content-Type", "application/json")
err := json.NewEncoder(w).Encode(repos)
if err != nil {
http.Error(w, "Error encoding response", http.StatusInternalServerError)
return
}
}
}
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
4 changes: 3 additions & 1 deletion pkg/server/serve.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,10 @@ func Serve(port int, watching bool, repositories []string) error {
// Set up routes
mux := http.NewServeMux()
mux.Handle("/", h.Index())
mux.Handle("/prompts/", h.PromptList())
mux.Handle("/prompts/{name...}", h.PromptContent())
mux.Handle("/search", h.Search())
mux.Handle("/refresh", h.Refresh())
mux.Handle("/repositories", h.Repositories())

// Serve static files
fs := http.FileServer(http.Dir("pkg/server/static"))
Expand Down
11 changes: 0 additions & 11 deletions pkg/server/templates/pages/index.templ
Original file line number Diff line number Diff line change
Expand Up @@ -79,16 +79,5 @@ templ Index(repositories []string, repos map[string]*pkg.Repository) {
</div>
</div>
</div>
<script>
function copyToClipboard(text) {
navigator.clipboard.writeText(text).then(() => {
// Could add a toast notification here
});
}

function addToFavorites(name) {
// TODO: Implement favorites functionality
}
</script>
}
}
37 changes: 12 additions & 25 deletions pkg/server/templates/pages/index_templ.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

0 comments on commit 09dda72

Please sign in to comment.