commit 8a780bef866d683ef1845cbdb7140165aedf587e
parent c10d1b070d4990184385e41ec6e6d89b32bec8da
Author: Jacob R. Edwards <jacob@jacobedwards.org>
Date: Tue, 20 Aug 2024 17:46:38 -0700
Add floorplan data PUT endpoint
I just made use of the patch functionality for now. It may stay
that way because it's not too awful.
Diffstat:
3 files changed, 91 insertions(+), 8 deletions(-)
diff --git a/cmd/api/floorplans.go b/cmd/api/floorplans.go
@@ -152,6 +152,24 @@ func (e *Env) PatchFloorplanData(c *gin.Context) {
}
}
+func (e *Env) ReplaceFloorplanData(c *gin.Context) {
+ var data *backend.FloorplanData
+
+ user := c.Param("user")
+ floorplan := c.Param("floorplan")
+ if err := c.ShouldBind(&data); err != nil {
+ RespondError(c, 400, "%s: Couldn't get floorplan data", err.Error())
+ return
+ }
+
+ newdata, err := e.backend.ReplaceFloorplanData(nil, user, floorplan, data)
+ if err != nil {
+ RespondError(c, 500, "%s: Unable to update floorplan data", err.Error())
+ return
+ }
+ Respond(c, 200, newdata)
+}
+
func patchableToSettable(data map[string]interface{}) (*SettableFloorplan, error) {
// Seems stupidly inefficient, but I can't find a better way at the moment
jsondata, err := json.Marshal(data)
diff --git a/cmd/api/main.go b/cmd/api/main.go
@@ -98,6 +98,7 @@ func setAuthenticatedRoutes(env *Env, r *gin.RouterGroup) {
fpdata := fp.Group("/data")
fpdata.GET("", env.GetFloorplanData)
+ fpdata.PUT("", env.ReplaceFloorplanData)
fpdata.PATCH("", env.PatchFloorplanData)
}
diff --git a/internal/backend/floorplan_data.go b/internal/backend/floorplan_data.go
@@ -36,8 +36,8 @@ type rowReference struct {
type PatchError struct {
ref *rowReference
- rawref *string
- msg *string
+ rawref string
+ msg string
extra error
}
@@ -99,6 +99,63 @@ func (e *Env) getFloorplanPointMaps(tx *sql.Tx, user string, floorplan string) (
return mapArray(pointmaps, mapPointMap)
}
+func (e *Env) ReplaceFloorplanData(tx *sql.Tx, user string, floorplan string, data *FloorplanData) (FloorplanData, error) {
+ mytx := false
+ if (tx == nil) {
+ mytx = true
+ var err error
+ tx, err = e.DB.Begin()
+ if err != nil {
+ return FloorplanData{}, err
+ }
+ defer tx.Rollback()
+ }
+
+ if err := e.DeleteFloorplanData(tx, user, floorplan); err != nil {
+ return FloorplanData{}, err
+ }
+
+ patches := make([]Patch, 0)
+ for id, point := range data.Points {
+ patch := Patch{
+ Op: "new",
+ Path: rowReference{table: "points", id: id}.String(),
+ Value: point,
+ }
+ patches = append(patches, patch)
+ }
+ for id, pointmap := range data.Pointmaps {
+ patch := Patch{
+ Op: "new",
+ Path: rowReference{table: "pointmaps", id: id}.String(),
+ Value: pointmap,
+ }
+ patches = append(patches, patch)
+ }
+ newdata, err := e.PatchFloorplanData(tx, user, floorplan, patches)
+ if err != nil {
+ return FloorplanData{}, err
+ }
+ if (mytx) {
+ if err := tx.Commit(); err != nil {
+ return FloorplanData{}, err
+ }
+ }
+ return newdata, nil
+}
+
+func (e *Env) DeleteFloorplanData(tx *sql.Tx, user string, floorplan string) error {
+ stmt, err := e.CacheTxStmt(tx, "del_floorplan_data",
+ `DELETE from spaceplanner.floorplan_points
+ WHERE floorplan = spaceplanner.floorplan_id($1, $2)`)
+ if err != nil {
+ return err
+ }
+
+ _, err = stmt.Exec(user, floorplan)
+ return err
+}
+
func (e *Env) PatchFloorplanData(tx *sql.Tx, user string, floorplan string, patches []Patch) (FloorplanData, error) {
var err error
mytx := false
@@ -377,16 +434,23 @@ func mapPointMap(p PointMap) (int64, error) {
return p.id, nil
}
+func (ref rowReference) String() string {
+ return fmt.Sprintf("/%s/%d", ref.table, ref.id)
+}
+
func (ref rowReference) Error(msg string, extra error) PatchError {
return PatchError{}.New(&ref, nil, msg, extra)
}
func (e PatchError) New(ref *rowReference, rawref *string, msg string, extra error) PatchError {
- e.ref = ref
- e.rawref = rawref
- if len(msg) > 0 {
- e.msg = &msg
+ if ref != nil {
+ copy := *ref
+ e.ref = ©
+ }
+ if rawref != nil {
+ e.rawref = *rawref
}
+ e.msg = msg
e.extra = extra
return e;
}
@@ -397,11 +461,11 @@ func (e PatchError) Error() string {
// Assume msg or extra will be defined (they should be)
if e.ref != nil {
err = fmt.Sprintf("/%s/%d: ", e.ref.table, e.ref.id)
- } else if e.rawref != nil {
+ } else if len(e.rawref) > 0 {
err = fmt.Sprintf("%s: ", e.rawref)
}
- if e.msg != nil{
+ if len(e.msg) > 0 {
err = fmt.Sprintf("%s: %s", err, e.msg)
}
if e.extra != nil {