api.spaceplanner.app

Spaceplanner API
git clone git://jacobedwards.org/api.spaceplanner.app
Log | Files | Refs

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:
Mcmd/api/floorplans.go | 18++++++++++++++++++
Mcmd/api/main.go | 1+
Minternal/backend/floorplan_data.go | 80+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++--------
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 = &copy + } + 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 {