projects: add /all endpoint for unlimited project list
Solve pagination issue where configs reference projects not in the
paginated list (default 10 items, but there could be 50+ projects).
Changes:
- Add GET /api/projects/all endpoint that returns ALL projects without
pagination as simple {uuid, name} objects
- Update frontend loadProjectsForConfigUI() to use /api/projects/all
instead of /api/projects?status=all
- Ensures all projects are available in projectNameByUUID for config
display, regardless of total project count
This fixes cases where project names don't display in /configs page
for configs that reference projects outside the paginated range.
Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -1166,7 +1166,8 @@ func setupRouter(cfg *config.Config, local *localdb.LocalDB, connMgr *db.Connect
|
|||||||
search := strings.ToLower(strings.TrimSpace(c.Query("search")))
|
search := strings.ToLower(strings.TrimSpace(c.Query("search")))
|
||||||
author := strings.ToLower(strings.TrimSpace(c.Query("author")))
|
author := strings.ToLower(strings.TrimSpace(c.Query("author")))
|
||||||
page, _ := strconv.Atoi(c.DefaultQuery("page", "1"))
|
page, _ := strconv.Atoi(c.DefaultQuery("page", "1"))
|
||||||
perPage, _ := strconv.Atoi(c.DefaultQuery("per_page", "10"))
|
// Return all projects by default (set high limit for configs to reference)
|
||||||
|
perPage, _ := strconv.Atoi(c.DefaultQuery("per_page", "1000"))
|
||||||
sortField := strings.ToLower(strings.TrimSpace(c.DefaultQuery("sort", "created_at")))
|
sortField := strings.ToLower(strings.TrimSpace(c.DefaultQuery("sort", "created_at")))
|
||||||
sortDir := strings.ToLower(strings.TrimSpace(c.DefaultQuery("dir", "desc")))
|
sortDir := strings.ToLower(strings.TrimSpace(c.DefaultQuery("dir", "desc")))
|
||||||
if status != "active" && status != "archived" && status != "all" {
|
if status != "active" && status != "archived" && status != "all" {
|
||||||
@@ -1318,6 +1319,32 @@ func setupRouter(cfg *config.Config, local *localdb.LocalDB, connMgr *db.Connect
|
|||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
||||||
|
// GET /api/projects/all - Returns all projects without pagination for UI dropdowns
|
||||||
|
projects.GET("/all", func(c *gin.Context) {
|
||||||
|
allProjects, err := projectService.ListByUser(dbUsername, true)
|
||||||
|
if err != nil {
|
||||||
|
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Return simplified list of all projects (UUID + Name only)
|
||||||
|
type ProjectSimple struct {
|
||||||
|
UUID string `json:"uuid"`
|
||||||
|
Name string `json:"name"`
|
||||||
|
}
|
||||||
|
|
||||||
|
simplified := make([]ProjectSimple, 0, len(allProjects))
|
||||||
|
for _, p := range allProjects {
|
||||||
|
simplified = append(simplified, ProjectSimple{
|
||||||
|
UUID: p.UUID,
|
||||||
|
Name: p.Name,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
c.JSON(http.StatusOK, simplified)
|
||||||
|
})
|
||||||
|
|
||||||
projects.POST("", func(c *gin.Context) {
|
projects.POST("", func(c *gin.Context) {
|
||||||
var req services.CreateProjectRequest
|
var req services.CreateProjectRequest
|
||||||
if err := c.ShouldBindJSON(&req); err != nil {
|
if err := c.ShouldBindJSON(&req); err != nil {
|
||||||
|
|||||||
@@ -835,12 +835,17 @@ async function loadProjectsForConfigUI() {
|
|||||||
projectsCache = [];
|
projectsCache = [];
|
||||||
projectNameByUUID = {};
|
projectNameByUUID = {};
|
||||||
try {
|
try {
|
||||||
const resp = await fetch('/api/projects?status=all');
|
// Use /api/projects/all to get all projects without pagination
|
||||||
|
const resp = await fetch('/api/projects/all');
|
||||||
if (!resp.ok) return;
|
if (!resp.ok) return;
|
||||||
const data = await resp.json();
|
const data = await resp.json();
|
||||||
projectsCache = (data.projects || []);
|
// data is now a simple array of {uuid, name} objects
|
||||||
|
const allProjects = Array.isArray(data) ? data : (data.projects || []);
|
||||||
|
|
||||||
projectsCache.forEach(project => {
|
// For compatibility with rest of code, populate projectsCache but mainly use projectNameByUUID
|
||||||
|
projectsCache = allProjects;
|
||||||
|
|
||||||
|
allProjects.forEach(project => {
|
||||||
projectNameByUUID[project.uuid] = project.name;
|
projectNameByUUID[project.uuid] = project.name;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user