Set up initial implementation of completing review tasks
Insufficiently tested at this point.
This commit is contained in:
parent
10b4bf929f
commit
ce3650bc21
3 changed files with 158 additions and 13 deletions
146
api/review.go
Normal file
146
api/review.go
Normal file
|
|
@ -0,0 +1,146 @@
|
|||
package api
|
||||
|
||||
import (
|
||||
"context"
|
||||
"net/http"
|
||||
"time"
|
||||
|
||||
"github.com/Gleipnir-Technology/bob"
|
||||
"github.com/Gleipnir-Technology/bob/dialect/psql"
|
||||
"github.com/Gleipnir-Technology/bob/dialect/psql/um"
|
||||
"github.com/Gleipnir-Technology/nidus-sync/db"
|
||||
"github.com/Gleipnir-Technology/nidus-sync/db/enums"
|
||||
"github.com/Gleipnir-Technology/nidus-sync/db/models"
|
||||
nhttp "github.com/Gleipnir-Technology/nidus-sync/http"
|
||||
"github.com/aarondl/opt/omit"
|
||||
"github.com/aarondl/opt/omitnull"
|
||||
/*
|
||||
"github.com/Gleipnir-Technology/bob/dialect/psql/sm"
|
||||
"github.com/Gleipnir-Technology/nidus-sync/platform/geom"
|
||||
"github.com/aarondl/opt/omit"
|
||||
"github.com/aarondl/opt/omitnull"
|
||||
"github.com/rs/zerolog/log"
|
||||
"github.com/stephenafamo/scan"
|
||||
*/)
|
||||
|
||||
type reviewPoolUpdate struct {
|
||||
Condition *string `json:"condition"`
|
||||
Latitude *float32 `json:"latitude"`
|
||||
Longitude *float32 `json:"longitude"`
|
||||
}
|
||||
type createReviewPool struct {
|
||||
Status string `json:"status"`
|
||||
TaskID int32 `json:"task_id"`
|
||||
Updates *reviewPoolUpdate `json:"updates"`
|
||||
}
|
||||
type createdReviewPool struct{}
|
||||
|
||||
func postReviewPool(ctx context.Context, r *http.Request, org *models.Organization, user *models.User, req createReviewPool) (*createdReviewPool, *nhttp.ErrorWithStatus) {
|
||||
txn, err := db.PGInstance.BobDB.BeginTx(ctx, nil)
|
||||
if err != nil {
|
||||
return nil, nhttp.NewError("start txn: %w", err)
|
||||
}
|
||||
defer txn.Rollback(ctx)
|
||||
review_task, err := models.ReviewTasks.Query(
|
||||
models.SelectWhere.ReviewTasks.ID.EQ(req.TaskID),
|
||||
models.SelectWhere.ReviewTasks.OrganizationID.EQ(org.ID),
|
||||
).One(ctx, txn)
|
||||
if err != nil {
|
||||
return nil, nhttp.NewErrorStatus(http.StatusNotFound, "review task %d not found", req.TaskID)
|
||||
}
|
||||
var resolution enums.Reviewtaskresolutiontype
|
||||
err = resolution.Scan(req.Status)
|
||||
if err != nil {
|
||||
return nil, nhttp.NewErrorStatus(http.StatusNotFound, "status '%s' is not recognized", req.Status)
|
||||
}
|
||||
review_task.Update(ctx, txn, &models.ReviewTaskSetter{
|
||||
Resolution: omitnull.From(resolution),
|
||||
Reviewed: omitnull.From(time.Now()),
|
||||
ReviewerID: omitnull.From(user.ID),
|
||||
})
|
||||
review_task_pool, err := models.ReviewTaskPools.Query(
|
||||
models.SelectWhere.ReviewTaskPools.ReviewTaskID.EQ(review_task.ID),
|
||||
).One(ctx, txn)
|
||||
var e *nhttp.ErrorWithStatus
|
||||
switch req.Status {
|
||||
case "discarded":
|
||||
e = discardReviewPool(ctx, txn, user, req, review_task_pool)
|
||||
case "committed":
|
||||
e = commitReviewPool(ctx, txn, user, req, review_task_pool)
|
||||
default:
|
||||
return nil, nhttp.NewErrorStatus(http.StatusBadRequest, "unrecognized status %s", req.Status)
|
||||
}
|
||||
if e != nil {
|
||||
return nil, e
|
||||
}
|
||||
txn.Commit(ctx)
|
||||
return &createdReviewPool{}, e
|
||||
}
|
||||
func discardReviewPool(ctx context.Context, txn bob.Tx, user *models.User, req createReviewPool, review_task_pool *models.ReviewTaskPool) *nhttp.ErrorWithStatus {
|
||||
return nil
|
||||
}
|
||||
func commitReviewPool(ctx context.Context, txn bob.Tx, user *models.User, req createReviewPool, review_task_pool *models.ReviewTaskPool) *nhttp.ErrorWithStatus {
|
||||
if req.Updates == nil {
|
||||
return nil
|
||||
}
|
||||
up := *req.Updates
|
||||
feature_pool, err := models.FindFeaturePool(ctx, txn, review_task_pool.FeaturePoolID)
|
||||
if err != nil {
|
||||
return nhttp.NewError("find feature pool: %w", err)
|
||||
}
|
||||
if up.Condition != nil {
|
||||
var condition enums.Poolconditiontype
|
||||
err := condition.Scan(up.Condition)
|
||||
if err != nil {
|
||||
return nhttp.NewErrorStatus(http.StatusBadRequest, "unrecognized condition %s", up.Condition)
|
||||
}
|
||||
err = review_task_pool.Update(ctx, txn, &models.ReviewTaskPoolSetter{
|
||||
Condition: omitnull.From(condition),
|
||||
})
|
||||
if err != nil {
|
||||
return nhttp.NewError("update rewiew task: %w", err)
|
||||
}
|
||||
err = feature_pool.Update(ctx, txn, &models.FeaturePoolSetter{
|
||||
Condition: omit.From(condition),
|
||||
})
|
||||
if err != nil {
|
||||
return nhttp.NewError("update feature_pool: %w", err)
|
||||
}
|
||||
}
|
||||
if up.Latitude != nil || up.Longitude != nil {
|
||||
if up.Latitude == nil || up.Longitude == nil {
|
||||
return nhttp.NewErrorStatus(http.StatusBadRequest, "you have to specify lat and lng together")
|
||||
}
|
||||
_, err = psql.Update(
|
||||
um.Table("review_task_pool"),
|
||||
um.SetCol("location").To(
|
||||
psql.F("ST_SetSRID",
|
||||
psql.F("ST_MakePoint",
|
||||
psql.Arg(*up.Longitude),
|
||||
psql.Arg(*up.Latitude),
|
||||
), psql.Arg(4326),
|
||||
),
|
||||
),
|
||||
um.Where(psql.Quote("review_task_pool", "id").EQ(psql.Arg(review_task_pool.ReviewTaskID))),
|
||||
).Exec(ctx, txn)
|
||||
if err != nil {
|
||||
return nhttp.NewError("save task: %w", err)
|
||||
}
|
||||
_, err = psql.Update(
|
||||
um.Table("feature"),
|
||||
um.SetCol("location").To(
|
||||
psql.F("ST_SetSRID",
|
||||
psql.F("ST_MakePoint",
|
||||
psql.Arg(*up.Longitude),
|
||||
psql.Arg(*up.Latitude),
|
||||
), psql.Arg(4326),
|
||||
),
|
||||
),
|
||||
um.Where(psql.Quote("feature", "id").EQ(psql.Arg(review_task_pool.FeaturePoolID))),
|
||||
).Exec(ctx, txn)
|
||||
if err != nil {
|
||||
return nhttp.NewError("save feature: %w", err)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
|
@ -10,20 +10,21 @@ import (
|
|||
func AddRoutes(r chi.Router) {
|
||||
// Authenticated endpoints
|
||||
r.Use(render.SetContentType(render.ContentTypeJSON))
|
||||
r.Method("GET", "/communication", authenticatedHandlerJSON(listCommunication))
|
||||
r.Method("GET", "/mosquito-source", auth.NewEnsureAuth(apiMosquitoSource))
|
||||
r.Method("GET", "/review-task/pool", authenticatedHandlerJSON(listReviewTaskPool))
|
||||
r.Method("GET", "/service-request", auth.NewEnsureAuth(apiServiceRequest))
|
||||
r.Method("GET", "/signal", authenticatedHandlerJSON(listSignal))
|
||||
r.Method("GET", "/trap-data", auth.NewEnsureAuth(apiTrapData))
|
||||
r.Method("GET", "/client/ios", auth.NewEnsureAuth(handleClientIos))
|
||||
r.Method("POST", "/audio/{uuid}", auth.NewEnsureAuth(apiAudioPost))
|
||||
r.Method("POST", "/audio/{uuid}/content", auth.NewEnsureAuth(apiAudioContentPost))
|
||||
r.Method("GET", "/client/ios", auth.NewEnsureAuth(handleClientIos))
|
||||
r.Method("GET", "/communication", authenticatedHandlerJSON(listCommunication))
|
||||
r.Method("POST", "/image/{uuid}", auth.NewEnsureAuth(apiImagePost))
|
||||
r.Method("GET", "/image/{uuid}/content", auth.NewEnsureAuth(apiImageContentGet))
|
||||
r.Method("POST", "/image/{uuid}/content", auth.NewEnsureAuth(apiImageContentPost))
|
||||
r.Method("GET", "/leads", authenticatedHandlerJSON(listLead))
|
||||
r.Method("POST", "/leads", authenticatedHandlerJSONPost(postLeads))
|
||||
r.Method("GET", "/mosquito-source", auth.NewEnsureAuth(apiMosquitoSource))
|
||||
r.Method("POST", "/review/pool", authenticatedHandlerJSONPost(postReviewPool))
|
||||
r.Method("GET", "/review-task/pool", authenticatedHandlerJSON(listReviewTaskPool))
|
||||
r.Method("GET", "/service-request", auth.NewEnsureAuth(apiServiceRequest))
|
||||
r.Method("GET", "/signal", authenticatedHandlerJSON(listSignal))
|
||||
r.Method("GET", "/trap-data", auth.NewEnsureAuth(apiTrapData))
|
||||
r.Method("GET", "/tile/{z}/{y}/{x}", auth.NewEnsureAuth(getTile))
|
||||
|
||||
// Unauthenticated endpoints
|
||||
|
|
|
|||
|
|
@ -219,7 +219,7 @@
|
|||
});
|
||||
}
|
||||
|
||||
const response = await fetch(`/api/review/`, {
|
||||
const response = await fetch(`/api/review/pool`, {
|
||||
method: "POST",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
|
|
@ -262,16 +262,14 @@
|
|||
}
|
||||
},
|
||||
|
||||
// Mark as reviewed
|
||||
// Mark as committed
|
||||
markReviewed() {
|
||||
this.submitReview("reviewed");
|
||||
this.submitReview("committed");
|
||||
},
|
||||
|
||||
// Discard entry
|
||||
discardEntry() {
|
||||
if (confirm("Are you sure you want to discard this entry?")) {
|
||||
this.submitReview("discarded");
|
||||
}
|
||||
this.submitReview("discarded");
|
||||
},
|
||||
updatePoolLocation(e, pool_id) {
|
||||
console.log("map click", pool_id, e.detail);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue