feature/backoffice #6
@@ -41,13 +41,18 @@ func listCartFiles(dir string) ([]CartFileInfo, error) {
|
|||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
name := e.Name()
|
name := e.Name()
|
||||||
m := cartFileRe.FindStringSubmatch(name)
|
var id uint64
|
||||||
if m == nil {
|
var parseErr error
|
||||||
|
if strings.HasPrefix(name, "{") && strings.HasSuffix(name, "}.events.log") {
|
||||||
|
idStr := strings.TrimSuffix(strings.TrimPrefix(name, "{"), "}.events.log")
|
||||||
|
id, parseErr = strconv.ParseUint(idStr, 10, 64)
|
||||||
|
} else if strings.HasSuffix(name, ".events.log") {
|
||||||
|
base := strings.TrimSuffix(name, ".events.log")
|
||||||
|
id, parseErr = strconv.ParseUint(base, 10, 64)
|
||||||
|
} else {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
idStr := m[1]
|
if parseErr != nil {
|
||||||
id, err := strconv.ParseUint(idStr, 10, 64)
|
|
||||||
if err != nil {
|
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
p := filepath.Join(dir, name)
|
p := filepath.Join(dir, name)
|
||||||
@@ -57,6 +62,7 @@ func listCartFiles(dir string) ([]CartFileInfo, error) {
|
|||||||
}
|
}
|
||||||
out = append(out, CartFileInfo{
|
out = append(out, CartFileInfo{
|
||||||
ID: id,
|
ID: id,
|
||||||
|
CartId: cart.CartId(id),
|
||||||
Path: p,
|
Path: p,
|
||||||
Size: info.Size(),
|
Size: info.Size(),
|
||||||
Modified: info.ModTime(),
|
Modified: info.ModTime(),
|
||||||
@@ -104,9 +110,20 @@ func (fs *FileServer) CartsHandler(w http.ResponseWriter, r *http.Request) {
|
|||||||
}
|
}
|
||||||
// sort by modified desc
|
// sort by modified desc
|
||||||
sort.Slice(list, func(i, j int) bool { return list[i].Modified.After(list[j].Modified) })
|
sort.Slice(list, func(i, j int) bool { return list[i].Modified.After(list[j].Modified) })
|
||||||
|
carts := make([]map[string]any, 0, len(list))
|
||||||
|
for _, it := range list {
|
||||||
|
carts = append(carts, map[string]any{
|
||||||
|
"id": it.ID,
|
||||||
|
"cartId": cart.CartId(it.ID).String(),
|
||||||
|
"filename": filepath.Base(it.Path),
|
||||||
|
"path": it.Path,
|
||||||
|
"size": it.Size,
|
||||||
|
"modified": it.Modified,
|
||||||
|
})
|
||||||
|
}
|
||||||
writeJSON(w, http.StatusOK, map[string]any{
|
writeJSON(w, http.StatusOK, map[string]any{
|
||||||
"count": len(list),
|
"count": len(carts),
|
||||||
"carts": list,
|
"carts": carts,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -116,8 +133,12 @@ func (fs *FileServer) CartHandler(w http.ResponseWriter, r *http.Request) {
|
|||||||
writeJSON(w, http.StatusBadRequest, map[string]string{"error": "missing id"})
|
writeJSON(w, http.StatusBadRequest, map[string]string{"error": "missing id"})
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
// allow both decimal id and filename-like with suffix
|
// normalize idStr: support "{123}.events.log", "{123}", "123.events.log", "123"
|
||||||
if strings.HasSuffix(idStr, ".events.log") {
|
if strings.HasPrefix(idStr, "{") && strings.HasSuffix(idStr, "}.events.log") {
|
||||||
|
idStr = strings.TrimSuffix(strings.TrimPrefix(idStr, "{"), "}.events.log")
|
||||||
|
} else if strings.HasPrefix(idStr, "{") && strings.HasSuffix(idStr, "}") {
|
||||||
|
idStr = strings.TrimSuffix(strings.TrimPrefix(idStr, "{"), "}")
|
||||||
|
} else if strings.HasSuffix(idStr, ".events.log") {
|
||||||
idStr = strings.TrimSuffix(idStr, ".events.log")
|
idStr = strings.TrimSuffix(idStr, ".events.log")
|
||||||
}
|
}
|
||||||
id, err := strconv.ParseUint(idStr, 10, 64)
|
id, err := strconv.ParseUint(idStr, 10, 64)
|
||||||
@@ -133,11 +154,21 @@ func (fs *FileServer) CartHandler(w http.ResponseWriter, r *http.Request) {
|
|||||||
|
|
||||||
path := filepath.Join(fs.dataDir, fmt.Sprintf("%d.events.log", id))
|
path := filepath.Join(fs.dataDir, fmt.Sprintf("%d.events.log", id))
|
||||||
info, err := os.Stat(path)
|
info, err := os.Stat(path)
|
||||||
if err != nil {
|
if err != nil && errors.Is(err, os.ErrNotExist) {
|
||||||
if errors.Is(err, os.ErrNotExist) {
|
// try brace-wrapped filename as fallback
|
||||||
writeJSON(w, http.StatusNotFound, map[string]string{"error": "cart not found"})
|
alt := filepath.Join(fs.dataDir, fmt.Sprintf("{%d}.events.log", id))
|
||||||
|
if fi, err2 := os.Stat(alt); err2 == nil {
|
||||||
|
path = alt
|
||||||
|
info = fi
|
||||||
|
} else {
|
||||||
|
if errors.Is(err2, os.ErrNotExist) {
|
||||||
|
writeJSON(w, http.StatusNotFound, map[string]string{"error": "cart not found"})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
writeJSON(w, http.StatusInternalServerError, map[string]string{"error": err2.Error()})
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
} else if err != nil {
|
||||||
writeJSON(w, http.StatusInternalServerError, map[string]string{"error": err.Error()})
|
writeJSON(w, http.StatusInternalServerError, map[string]string{"error": err.Error()})
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@@ -148,6 +179,7 @@ func (fs *FileServer) CartHandler(w http.ResponseWriter, r *http.Request) {
|
|||||||
}
|
}
|
||||||
writeJSON(w, http.StatusOK, map[string]any{
|
writeJSON(w, http.StatusOK, map[string]any{
|
||||||
"id": id,
|
"id": id,
|
||||||
|
"cartId": cart.CartId(id).String(),
|
||||||
"state": grain,
|
"state": grain,
|
||||||
"rawLog": lines,
|
"rawLog": lines,
|
||||||
"meta": map[string]any{
|
"meta": map[string]any{
|
||||||
|
|||||||
@@ -16,10 +16,11 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
type CartFileInfo struct {
|
type CartFileInfo struct {
|
||||||
ID uint64 `json:"id"`
|
ID uint64 `json:"id"`
|
||||||
Path string `json:"path"`
|
CartId cart.CartId `json:"cart_id"`
|
||||||
Size int64 `json:"size"`
|
Path string `json:"path"`
|
||||||
Modified time.Time `json:"modified"`
|
Size int64 `json:"size"`
|
||||||
|
Modified time.Time `json:"modified"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func envOrDefault(key, def string) string {
|
func envOrDefault(key, def string) string {
|
||||||
|
|||||||
Reference in New Issue
Block a user