Upload images on compliance report

This commit is contained in:
Eli Ribble 2026-04-10 22:34:14 +00:00
parent 730f40956f
commit 4060e7ddcd
No known key found for this signature in database
5 changed files with 89 additions and 9 deletions

View file

@ -83,6 +83,7 @@ func AddRoutes(r *mux.Router) {
publicreport := resource.Publicreport(router) publicreport := resource.Publicreport(router)
r.Handle("/publicreport/{id}", handlerJSON(publicreport.ByID)).Methods("GET").Name("publicreport.ByIDGet") r.Handle("/publicreport/{id}", handlerJSON(publicreport.ByID)).Methods("GET").Name("publicreport.ByIDGet")
r.Handle("/publicreport/{id}", handlerJSONPut(publicreport.Update)).Methods("PUT") r.Handle("/publicreport/{id}", handlerJSONPut(publicreport.Update)).Methods("PUT")
r.Handle("/publicreport/{id}/image", handlerFormPost(publicreport.ImageCreate)).Methods("POST")
publicreport_notification := resource.PublicreportNotification(router) publicreport_notification := resource.PublicreportNotification(router)
r.Handle("/publicreport-notification", handlerJSONPost(publicreport_notification.Create)).Methods("POST") r.Handle("/publicreport-notification", handlerJSONPost(publicreport_notification.Create)).Methods("POST")

View file

@ -129,6 +129,38 @@ func ReportComplianceCreate(ctx context.Context, setter_report models.Publicrepo
return nil return nil
}) })
} }
func ReportImageCreate(ctx context.Context, report_id string, images []ImageUpload) error {
txn, err := db.PGInstance.BobDB.BeginTx(ctx, nil)
if err != nil {
return fmt.Errorf("create txn: %w", err)
}
defer txn.Rollback(ctx)
report, err := reportFromID(ctx, report_id)
if err != nil {
return fmt.Errorf("report from ID: %w", err)
}
saved_images, err := saveImageUploads(ctx, txn, images)
if err != nil {
return fmt.Errorf("Failed to save image uploads: %w", err)
}
if len(saved_images) > 0 {
setters := make([]*models.PublicreportReportImageSetter, 0)
for _, image := range saved_images {
setters = append(setters, &models.PublicreportReportImageSetter{
ImageID: omit.From(int32(image.ID)),
ReportID: omit.From(int32(report.ID)),
})
}
_, err = models.PublicreportReportImages.Insert(bob.ToMods(setters...)).Exec(ctx, txn)
if err != nil {
return fmt.Errorf("Failed to save reference to images: %w", err)
}
log.Info().Int("len", len(images)).Msg("saved uploaded images")
}
txn.Commit(ctx)
return nil
}
func ReportNuisanceCreate(ctx context.Context, setter_report models.PublicreportReportSetter, setter_nuisance models.PublicreportNuisanceSetter, location types.Location, address Address, images []ImageUpload) (*models.PublicreportReport, error) { func ReportNuisanceCreate(ctx context.Context, setter_report models.PublicreportReportSetter, setter_nuisance models.PublicreportNuisanceSetter, location types.Location, address Address, images []ImageUpload) (*models.PublicreportReport, error) {
return reportCreate(ctx, setter_report, &location, &address, images, func(ctx context.Context, txn bob.Executor, report_id int32) error { return reportCreate(ctx, setter_report, &location, &address, images, func(ctx context.Context, txn bob.Executor, report_id int32) error {
setter_nuisance.ReportID = omit.From(report_id) setter_nuisance.ReportID = omit.From(report_id)

View file

@ -29,14 +29,8 @@ type compliance struct {
ID string `json:"id"` ID string `json:"id"`
URI string `json:"uri"` URI string `json:"uri"`
} }
type complianceForm struct {
ClientID string `schema:"client_id"`
DistrictID string `schema:"district"`
Location *types.Location `schema:"location"`
Locator *Locator `schema:"locator"`
}
func (res *complianceR) Create(ctx context.Context, r *http.Request, n complianceForm) (*compliance, *nhttp.ErrorWithStatus) { func (res *complianceR) Create(ctx context.Context, r *http.Request, n publicreportForm) (*compliance, *nhttp.ErrorWithStatus) {
setter_report := models.PublicreportReportSetter{ setter_report := models.PublicreportReportSetter{
//AddressID: omitnull.From(latlng.Cell.String()), //AddressID: omitnull.From(latlng.Cell.String()),
AddressCountry: omit.From(""), AddressCountry: omit.From(""),

View file

@ -7,11 +7,12 @@ import (
"github.com/aarondl/opt/omit" "github.com/aarondl/opt/omit"
//"github.com/aarondl/opt/omitnull" //"github.com/aarondl/opt/omitnull"
"github.com/Gleipnir-Technology/nidus-sync/db/models" "github.com/Gleipnir-Technology/nidus-sync/db/models"
"github.com/Gleipnir-Technology/nidus-sync/html"
nhttp "github.com/Gleipnir-Technology/nidus-sync/http" nhttp "github.com/Gleipnir-Technology/nidus-sync/http"
"github.com/Gleipnir-Technology/nidus-sync/platform" "github.com/Gleipnir-Technology/nidus-sync/platform"
"github.com/Gleipnir-Technology/nidus-sync/platform/types" "github.com/Gleipnir-Technology/nidus-sync/platform/types"
//"github.com/rs/zerolog/log"
"github.com/gorilla/mux" "github.com/gorilla/mux"
"github.com/rs/zerolog/log"
) )
type publicreportR struct { type publicreportR struct {
@ -50,9 +51,35 @@ func (res *publicreportR) ByID(ctx context.Context, r *http.Request, query Query
return report, nil return report, nil
} }
type image struct {
Status string `json:"status"`
}
func (res *publicreportR) ImageCreate(ctx context.Context, r *http.Request, n nuisanceForm) (*image, *nhttp.ErrorWithStatus) {
vars := mux.Vars(r)
public_id := vars["id"]
if public_id == "" {
return nil, nhttp.NewBadRequest("You must provide an ID")
}
uploads, err := html.ExtractImageUploads(r)
log.Info().Int("len", len(uploads)).Msg("report image uploads")
if err != nil {
return nil, nhttp.NewError("Failed to extract image uploads: %w", err)
}
platform.ReportImageCreate(ctx, public_id, uploads)
return &image{Status: "ok"}, nil
}
type complianceForm struct {
Comments *string `schema:"comments"`
}
type publicreportForm struct { type publicreportForm struct {
Address *types.Address `schema:"address"` Address *types.Address `schema:"address"`
ClientID string `schema:"client_id"` ClientID string `schema:"client_id"`
Compliance *complianceForm `schema:"compliance"`
DistrictID string `schema:"district"` DistrictID string `schema:"district"`
Location *types.Location `schema:"location"` Location *types.Location `schema:"location"`
Locator *Locator `schema:"locator"` Locator *Locator `schema:"locator"`

View file

@ -106,6 +106,7 @@ const compliance = ref<Compliance>({
uri: "", uri: "",
}); });
const isLoading = ref<boolean>(true); const isLoading = ref<boolean>(true);
const isUploading = ref<boolean>(false);
const props = defineProps<Props>(); const props = defineProps<Props>();
const report = ref<PublicReport | null>(); const report = ref<PublicReport | null>();
const district = computedAsync(async (): Promise<District | undefined> => { const district = computedAsync(async (): Promise<District | undefined> => {
@ -147,7 +148,7 @@ function doAddress() {
}); });
} }
function doEvidence() { function doEvidence() {
console.log("evidence", compliance.value); uploadImages(compliance.value.images);
} }
function doContact() { function doContact() {
console.log("contact", compliance.value.contact); console.log("contact", compliance.value.contact);
@ -193,6 +194,31 @@ async function updateReport(updates: ComplianceUpdate) {
return; return;
} }
} }
async function uploadImages(images: Image[]) {
isUploading.value = true;
const formData = new FormData();
images.map(async (image, index) => {
formData.append(`image[${index}]`, image.file, image.name);
});
const url = `${compliance.value.uri}/image`;
const response = await fetch(url, {
body: formData,
method: "POST",
});
if (!response.ok) {
const content = await response.text();
console.error(
"Failed to POST images",
url,
response.status,
response.statusText,
content,
);
isUploading.value = false;
return;
}
isUploading.value = false;
}
onMounted(() => { onMounted(() => {
const client_id = storeLocal.getClientID(); const client_id = storeLocal.getClientID();
const report_uri = storeLocal.getExistingComplianceReportURI(); const report_uri = storeLocal.getExistingComplianceReportURI();