aboutsummaryrefslogtreecommitdiff
path: root/internal/admin/api_items.go
diff options
context:
space:
mode:
authorhistoria <[not public]>2026-06-29 22:31:11 -0400
committerhistoria <[not public]>2026-06-29 22:31:11 -0400
commit069d3c1c81d71042706372df153254487a765dfc (patch)
treed83a4a3954d2b8304f49d83e365f4c2b075b91eb /internal/admin/api_items.go
parent6c5271fb085b4571a10f106391974c249cd84317 (diff)
downloadthehouseoficarus-069d3c1c81d71042706372df153254487a765dfc.tar.gz
feat: wip web admin for mapping and crud
Diffstat (limited to 'internal/admin/api_items.go')
-rw-r--r--internal/admin/api_items.go166
1 files changed, 166 insertions, 0 deletions
diff --git a/internal/admin/api_items.go b/internal/admin/api_items.go
new file mode 100644
index 0000000..3ab20ae
--- /dev/null
+++ b/internal/admin/api_items.go
@@ -0,0 +1,166 @@
+package admin
+
+import (
+ "fmt"
+ "net/http"
+ "os"
+ "path/filepath"
+ "strings"
+)
+
+func (s *AdminServer) handleItems(w http.ResponseWriter, r *http.Request) {
+ switch r.Method {
+ case http.MethodGet:
+ ids, err := listYAMLFiles(s.dataDir, "items")
+ if err != nil {
+ http.Error(w, `{"error":"failed to list items"}`, http.StatusInternalServerError)
+ return
+ }
+ if ids == nil {
+ ids = []string{}
+ }
+ writeJSON(w, ids)
+ case http.MethodPost:
+ s.createItem(w, r)
+ default:
+ http.Error(w, `{"error":"method not allowed"}`, http.StatusMethodNotAllowed)
+ }
+}
+
+func (s *AdminServer) handleItemByID(w http.ResponseWriter, r *http.Request) {
+ id := strings.TrimPrefix(r.URL.Path, "/api/items/")
+ if id == "" {
+ http.Error(w, `{"error":"missing item id"}`, http.StatusBadRequest)
+ return
+ }
+
+ switch r.Method {
+ case http.MethodGet:
+ s.getItem(w, r, id)
+ case http.MethodPut:
+ s.updateItem(w, r, id)
+ case http.MethodDelete:
+ s.deleteItem(w, r, id)
+ default:
+ http.Error(w, `{"error":"method not allowed"}`, http.StatusMethodNotAllowed)
+ }
+}
+
+func (s *AdminServer) findItemFile(id string) ([]byte, string, error) {
+ data, path, err := readYAMLFile(s.dataDir, "items", id)
+ if err == nil {
+ return data, path, nil
+ }
+ return findYAMLFileInSubdirs(s.dataDir, "items", id)
+}
+
+func (s *AdminServer) getItem(w http.ResponseWriter, r *http.Request, id string) {
+ data, path, err := s.findItemFile(id)
+ if err != nil {
+ http.Error(w, `{"error":"item not found"}`, http.StatusNotFound)
+ return
+ }
+ m, err := yamlToMap(data)
+ if err != nil {
+ http.Error(w, `{"error":"failed to parse item yaml"}`, http.StatusInternalServerError)
+ return
+ }
+ m["_path"] = path
+ m["_raw"] = string(data)
+ writeJSON(w, m)
+}
+
+func (s *AdminServer) updateItem(w http.ResponseWriter, r *http.Request, id string) {
+ _, path, err := s.findItemFile(id)
+ if err != nil {
+ http.Error(w, `{"error":"item not found"}`, http.StatusNotFound)
+ return
+ }
+
+ var m map[string]any
+ if err := readJSON(r, &m); err != nil {
+ http.Error(w, `{"error":"invalid json body"}`, http.StatusBadRequest)
+ return
+ }
+ m["id"] = id
+
+ oldContent, err := snapshotFile(path)
+ if err != nil {
+ http.Error(w, `{"error":"failed to read existing item"}`, http.StatusInternalServerError)
+ return
+ }
+
+ newContent, err := writeMapAsYAML(path, m)
+ if err != nil {
+ http.Error(w, `{"error":"failed to write item"}`, http.StatusInternalServerError)
+ return
+ }
+
+ s.undoStack.Push(ChangeDesc{
+ Description: fmt.Sprintf("Update item %s", id),
+ FilePath: path,
+ OldContent: oldContent,
+ NewContent: newContent,
+ })
+
+ writeJSON(w, m)
+}
+
+func (s *AdminServer) deleteItem(w http.ResponseWriter, r *http.Request, id string) {
+ _, path, err := s.findItemFile(id)
+ if err != nil {
+ http.Error(w, `{"error":"item not found"}`, http.StatusNotFound)
+ return
+ }
+
+ oldContent := backupFile(path)
+
+ if err := os.Remove(path); err != nil {
+ http.Error(w, `{"error":"failed to delete item"}`, http.StatusInternalServerError)
+ return
+ }
+
+ s.undoStack.Push(ChangeDesc{
+ Description: fmt.Sprintf("Delete item %s", id),
+ FilePath: path,
+ OldContent: oldContent,
+ IsDelete: true,
+ })
+
+ writeJSON(w, map[string]any{"deleted": id})
+}
+
+func (s *AdminServer) createItem(w http.ResponseWriter, r *http.Request) {
+ var m map[string]any
+ if err := readJSON(r, &m); err != nil {
+ http.Error(w, `{"error":"invalid json body"}`, http.StatusBadRequest)
+ return
+ }
+ id, _ := m["id"].(string)
+ if strings.TrimSpace(id) == "" {
+ http.Error(w, `{"error":"missing item id"}`, http.StatusBadRequest)
+ return
+ }
+
+ if _, _, err := s.findItemFile(id); err == nil {
+ http.Error(w, `{"error":"item already exists"}`, http.StatusConflict)
+ return
+ }
+
+ path := filepath.Join(s.dataDir, "items", id+".yaml")
+
+ newContent, err := writeMapAsYAML(path, m)
+ if err != nil {
+ http.Error(w, `{"error":"failed to write item"}`, http.StatusInternalServerError)
+ return
+ }
+
+ s.undoStack.Push(ChangeDesc{
+ Description: fmt.Sprintf("Create item %s", id),
+ FilePath: path,
+ NewContent: newContent,
+ IsCreate: true,
+ })
+
+ writeJSON(w, m)
+}