Initial render of standing water reports from the public
This commit is contained in:
parent
cd47aaba94
commit
ce6c6c1cc1
6 changed files with 246 additions and 176 deletions
|
|
@ -9,6 +9,7 @@ import (
|
|||
"github.com/Gleipnir-Technology/nidus-sync/db/models"
|
||||
nhttp "github.com/Gleipnir-Technology/nidus-sync/http"
|
||||
"github.com/Gleipnir-Technology/nidus-sync/platform/publicreport"
|
||||
"github.com/Gleipnir-Technology/nidus-sync/platform/types"
|
||||
"github.com/google/uuid"
|
||||
//"github.com/rs/zerolog/log"
|
||||
)
|
||||
|
|
@ -19,22 +20,26 @@ type reporter struct {
|
|||
Name string `json:"name"`
|
||||
}
|
||||
type communication struct {
|
||||
Created time.Time `json:"created"`
|
||||
ID string `json:"id"`
|
||||
PublicReport publicreport.Nuisance `json:"public_report"`
|
||||
Type string `json:"type"`
|
||||
Created time.Time `json:"created"`
|
||||
ID string `json:"id"`
|
||||
PublicReport types.PublicReport `json:"public_report"`
|
||||
Type string `json:"type"`
|
||||
}
|
||||
type contentListCommunication struct {
|
||||
Communications []communication `json:"communications"`
|
||||
}
|
||||
|
||||
func listCommunication(ctx context.Context, r *http.Request, org *models.Organization, user *models.User, query queryParams) (*contentListCommunication, *nhttp.ErrorWithStatus) {
|
||||
reports, err := publicreport.NuisanceReportForOrganization(ctx, org.ID)
|
||||
nreports, err := publicreport.NuisanceReportForOrganization(ctx, org.ID)
|
||||
if err != nil {
|
||||
return nil, nhttp.NewError("query report: %w", err)
|
||||
return nil, nhttp.NewError("nuisance report query: %w", err)
|
||||
}
|
||||
comms := make([]communication, len(reports))
|
||||
for i, report := range reports {
|
||||
wreports, err := publicreport.WaterReportForOrganization(ctx, org.ID)
|
||||
if err != nil {
|
||||
return nil, nhttp.NewError("water report query: %w", err)
|
||||
}
|
||||
comms := make([]communication, len(nreports)+len(wreports))
|
||||
for i, report := range nreports {
|
||||
comms[i] = communication{
|
||||
Created: report.Created,
|
||||
ID: report.PublicID,
|
||||
|
|
@ -42,6 +47,14 @@ func listCommunication(ctx context.Context, r *http.Request, org *models.Organiz
|
|||
Type: "nuisance",
|
||||
}
|
||||
}
|
||||
for i, report := range wreports {
|
||||
comms[i+len(nreports)] = communication{
|
||||
Created: report.Created,
|
||||
ID: report.PublicID,
|
||||
PublicReport: report,
|
||||
Type: "water",
|
||||
}
|
||||
}
|
||||
return &contentListCommunication{
|
||||
Communications: comms,
|
||||
}, nil
|
||||
|
|
|
|||
|
|
@ -27,143 +27,152 @@
|
|||
<script src="/static/js/location.js"></script>
|
||||
<script src="/static/js/map-locator.js"></script>
|
||||
<script src="/static/js/photo-upload.js"></script>
|
||||
<script>
|
||||
const MAPBOX_ACCESS_TOKEN = '{{.MapboxToken}}';
|
||||
async function handleMapClick(mapLocator, lngLat) {
|
||||
mapLocator.SetMarker(lngLat);
|
||||
mapLocator.PanTo(lngLat, {duration: 2000});
|
||||
const response = await geocodeReverse(MAPBOX_ACCESS_TOKEN, {
|
||||
lat: lngLat.lat,
|
||||
lng: lngLat.lng,
|
||||
});
|
||||
console.log("click reverse geocode", response);
|
||||
if (response !== undefined && response.features.length > 0) {
|
||||
const addressInput = document.querySelector("address-input");
|
||||
addressInput.SetValue(response.features[0]);
|
||||
setLocationInputs(response.features[0]);
|
||||
}
|
||||
}
|
||||
async function handleMarkerDrag(lngLat) {
|
||||
const response = await geocodeReverse(MAPBOX_ACCESS_TOKEN, {
|
||||
lat: lngLat.lat,
|
||||
lng: lngLat.lng,
|
||||
})
|
||||
console.log("marker drag reverse geocode", response);
|
||||
if (response !== undefined && response.features.length > 0) {
|
||||
const addressInput = document.querySelector("address-input");
|
||||
addressInput.SetValue(response.features[0]);
|
||||
}
|
||||
}
|
||||
function setLocationInputs(location) {
|
||||
let country = document.getElementById('address-country');
|
||||
let latitude = document.getElementById('latitude');
|
||||
let longitude = document.getElementById('longitude');
|
||||
let latlngAccuracyType = document.getElementById('latlng-accuracy-type');
|
||||
let latlngAccuracyValue = document.getElementById('latlng-accuracy-value');
|
||||
let number = document.getElementById('address-number');
|
||||
let postalcode = document.getElementById('address-postalcode');
|
||||
let place = document.getElementById('address-place');
|
||||
let region = document.getElementById('address-region');
|
||||
let street = document.getElementById('address-street');
|
||||
|
||||
// Extract context data from properties
|
||||
const props = location.properties;
|
||||
const context = props.context || {};
|
||||
|
||||
// Populate structured fields
|
||||
country.value = context.iso_3166_a3;
|
||||
latitude.value = location.geometry.coordinates[1];
|
||||
longitude.value = location.geometry.coordinates[0];
|
||||
latlngAccuracyType.value = props.precision;
|
||||
latlngAccuracyValue.value = props.distance;
|
||||
number.value = props.address_components.number;
|
||||
postalcode.value = props.address_components.postal_code;
|
||||
locality.value = context.whosonfirst.locality.name;
|
||||
region.value = props.context.whosonfirst.region.abbreviation;
|
||||
street.value = props.address_components.street;
|
||||
}
|
||||
function toggleCollapse(something) {
|
||||
el = document.getElementById(something)
|
||||
if (el.classList.contains('collapse')) {
|
||||
el.classList.remove('collapse');
|
||||
} else {
|
||||
el.classList.add('collapse');
|
||||
}
|
||||
document.getElementById("toggle-additional").classList.add("visually-hidden");
|
||||
}
|
||||
|
||||
document.addEventListener('DOMContentLoaded', function() {
|
||||
// Elements
|
||||
const addressInput = document.querySelector("address-input");
|
||||
const latitudeInput = document.getElementById('latitude');
|
||||
const longitudeInput = document.getElementById('longitude');
|
||||
const latlngAccuracyType = document.getElementById('latlng-accuracy-type');
|
||||
const latlngAccuracyValue = document.getElementById('latlng-accuracy-value');
|
||||
|
||||
const mapLocator = document.querySelector("map-locator");
|
||||
mapLocator.addEventListener("load", (event) => {
|
||||
getGeolocation({
|
||||
enableHighAccuracy: true,
|
||||
timeout: 10000,
|
||||
maximumAge: 0
|
||||
}).then(position => {
|
||||
console.log("Got location", position);
|
||||
latitudeInput.value = position.coords.latitude;
|
||||
longitudeInput.value = position.coords.longitude;
|
||||
latlngAccuracyType.value = 'browser';
|
||||
latlngAccuracyValue.value = position.coords.accuracy;
|
||||
mapLocator.JumpTo({
|
||||
center: {
|
||||
lng: position.coords.longitude,
|
||||
lat: position.coords.latitude,
|
||||
},
|
||||
zoom: 14,
|
||||
<script>
|
||||
async function handleMapClick(mapLocator, lngLat) {
|
||||
mapLocator.SetMarker(lngLat);
|
||||
mapLocator.PanTo(lngLat, { duration: 2000 });
|
||||
const response = await geocodeReverse({
|
||||
lat: lngLat.lat,
|
||||
lng: lngLat.lng,
|
||||
});
|
||||
const coords = [
|
||||
position.coords.longitude,
|
||||
position.coords.latitude,
|
||||
];
|
||||
mapLocator.SetMarker(coords);
|
||||
mapLocator.JumpTo({center: coords, zoom: 14});
|
||||
handleMarkerDrag({
|
||||
lat: position.coords.latitude,
|
||||
lng: position.coords.longitude,
|
||||
});
|
||||
}).catch(error => {
|
||||
console.log("location error", error);
|
||||
})
|
||||
})
|
||||
let mapZoom = document.getElementById('map-zoom');
|
||||
mapLocator.addEventListener("zoomend", function(e) {
|
||||
mapZoom.value = e.target.GetZoom();
|
||||
});
|
||||
mapLocator.addEventListener("click", (e) => {
|
||||
// We get some events without the lngLat
|
||||
if (e.detail !== undefined && e.detail.lngLat !== undefined) {
|
||||
handleMapClick(mapLocator, e.detail.lngLat);
|
||||
console.log("click reverse geocode", response);
|
||||
if (response !== undefined && response.features.length > 0) {
|
||||
const addressInput = document.querySelector("address-input");
|
||||
addressInput.SetValue(response.features[0]);
|
||||
setLocationInputs(response.features[0]);
|
||||
}
|
||||
}
|
||||
});
|
||||
mapLocator.addEventListener("markerdragend", (e) => {
|
||||
const marker = event.detail.marker;
|
||||
const lngLat = marker.getLngLat();
|
||||
handleMarkerDrag(lngLat);
|
||||
});
|
||||
async function handleMarkerDrag(lngLat) {
|
||||
const response = await geocodeReverse({
|
||||
lat: lngLat.lat,
|
||||
lng: lngLat.lng,
|
||||
});
|
||||
console.log("marker drag reverse geocode", response);
|
||||
if (response !== undefined && response.features.length > 0) {
|
||||
const addressInput = document.querySelector("address-input");
|
||||
addressInput.SetValue(response.features[0]);
|
||||
}
|
||||
}
|
||||
function setLocationInputs(location) {
|
||||
let country = document.getElementById("address-country");
|
||||
let latitude = document.getElementById("latitude");
|
||||
let longitude = document.getElementById("longitude");
|
||||
let latlngAccuracyType = document.getElementById("latlng-accuracy-type");
|
||||
let latlngAccuracyValue = document.getElementById(
|
||||
"latlng-accuracy-value",
|
||||
);
|
||||
let number = document.getElementById("address-number");
|
||||
let postalcode = document.getElementById("address-postalcode");
|
||||
let place = document.getElementById("address-place");
|
||||
let region = document.getElementById("address-region");
|
||||
let street = document.getElementById("address-street");
|
||||
|
||||
const addressDisplay = document.querySelector("address-display");
|
||||
addressInput.addEventListener("address-selected", (event) => {
|
||||
const l = event.detail.location;
|
||||
console.log("Address selected", l);
|
||||
// Center map on selected address
|
||||
mapLocator.SetMarker(l.geometry.coordinates);
|
||||
mapLocator.JumpTo({
|
||||
center: l.geometry.coordinates,
|
||||
zoom: 14,
|
||||
// Extract context data from properties
|
||||
const props = location.properties;
|
||||
const context = props.context || {};
|
||||
|
||||
// Populate structured fields
|
||||
country.value = context.iso_3166_a3;
|
||||
latitude.value = location.geometry.coordinates[1];
|
||||
longitude.value = location.geometry.coordinates[0];
|
||||
latlngAccuracyType.value = props.precision;
|
||||
latlngAccuracyValue.value = props.distance;
|
||||
number.value = props.address_components.number;
|
||||
postalcode.value = props.address_components.postal_code;
|
||||
locality.value = context.whosonfirst.locality.name;
|
||||
region.value = props.context.whosonfirst.region.abbreviation;
|
||||
street.value = props.address_components.street;
|
||||
}
|
||||
function toggleCollapse(something) {
|
||||
el = document.getElementById(something);
|
||||
if (el.classList.contains("collapse")) {
|
||||
el.classList.remove("collapse");
|
||||
} else {
|
||||
el.classList.add("collapse");
|
||||
}
|
||||
document
|
||||
.getElementById("toggle-additional")
|
||||
.classList.add("visually-hidden");
|
||||
}
|
||||
|
||||
document.addEventListener("DOMContentLoaded", function () {
|
||||
// Elements
|
||||
const addressInput = document.querySelector("address-input");
|
||||
const latitudeInput = document.getElementById("latitude");
|
||||
const longitudeInput = document.getElementById("longitude");
|
||||
const latlngAccuracyType = document.getElementById(
|
||||
"latlng-accuracy-type",
|
||||
);
|
||||
const latlngAccuracyValue = document.getElementById(
|
||||
"latlng-accuracy-value",
|
||||
);
|
||||
|
||||
const mapLocator = document.querySelector("map-locator");
|
||||
mapLocator.addEventListener("load", (event) => {
|
||||
getGeolocation({
|
||||
enableHighAccuracy: true,
|
||||
timeout: 10000,
|
||||
maximumAge: 0,
|
||||
})
|
||||
.then((position) => {
|
||||
console.log("Got location", position);
|
||||
latitudeInput.value = position.coords.latitude;
|
||||
longitudeInput.value = position.coords.longitude;
|
||||
latlngAccuracyType.value = "browser";
|
||||
latlngAccuracyValue.value = position.coords.accuracy;
|
||||
mapLocator.JumpTo({
|
||||
center: {
|
||||
lng: position.coords.longitude,
|
||||
lat: position.coords.latitude,
|
||||
},
|
||||
zoom: 14,
|
||||
});
|
||||
const coords = [
|
||||
position.coords.longitude,
|
||||
position.coords.latitude,
|
||||
];
|
||||
mapLocator.SetMarker(coords);
|
||||
mapLocator.JumpTo({ center: coords, zoom: 14 });
|
||||
handleMarkerDrag({
|
||||
lat: position.coords.latitude,
|
||||
lng: position.coords.longitude,
|
||||
});
|
||||
})
|
||||
.catch((error) => {
|
||||
console.log("location error", error);
|
||||
});
|
||||
});
|
||||
let mapZoom = document.getElementById("map-zoom");
|
||||
mapLocator.addEventListener("zoomend", function (e) {
|
||||
mapZoom.value = e.target.GetZoom();
|
||||
});
|
||||
mapLocator.addEventListener("click", (e) => {
|
||||
// We get some events without the lngLat
|
||||
if (e.detail !== undefined && e.detail.lngLat !== undefined) {
|
||||
handleMapClick(mapLocator, e.detail.lngLat);
|
||||
}
|
||||
});
|
||||
mapLocator.addEventListener("markerdragend", (e) => {
|
||||
const marker = event.detail.marker;
|
||||
const lngLat = marker.getLngLat();
|
||||
handleMarkerDrag(lngLat);
|
||||
});
|
||||
|
||||
const addressDisplay = document.querySelector("address-display");
|
||||
addressInput.addEventListener("address-selected", (event) => {
|
||||
const l = event.detail.location;
|
||||
console.log("Address selected", l);
|
||||
// Center map on selected address
|
||||
mapLocator.SetMarker(l.geometry.coordinates);
|
||||
mapLocator.JumpTo({
|
||||
center: l.geometry.coordinates,
|
||||
zoom: 14,
|
||||
});
|
||||
|
||||
setLocationInputs(l);
|
||||
});
|
||||
});
|
||||
|
||||
setLocationInputs(l);
|
||||
});
|
||||
});
|
||||
</script>
|
||||
</script>
|
||||
{{ end }}
|
||||
{{ define "content" }}
|
||||
{{ if (eq .District nil) }}
|
||||
|
|
@ -283,7 +292,6 @@ document.addEventListener('DOMContentLoaded', function() {
|
|||
<div class="mb-3 position-relative">
|
||||
<address-input
|
||||
placeholder="Start typing an address (min 3 characters)"
|
||||
api-key="{{ .MapboxToken }}"
|
||||
>
|
||||
</address-input>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -28,7 +28,7 @@ LEFT JOIN publicreport.image_exif e ON i.id = e.image_id
|
|||
WHERE i.id IN (1, 2, 3, 4)
|
||||
GROUP BY i.id;
|
||||
*/
|
||||
// Get all the images that belong to the list of report IDs
|
||||
// Get all the images that belong to the list of nuisance report IDs
|
||||
func loadImagesForReportNuisance(ctx context.Context, org_id int32, report_ids []int32) (results map[int32][]types.Image, err error) {
|
||||
rows, err := bob.All(ctx, db.PGInstance.BobDB, psql.Select(
|
||||
sm.Columns(
|
||||
|
|
@ -39,7 +39,7 @@ func loadImagesForReportNuisance(ctx context.Context, org_id int32, report_ids [
|
|||
"COALESCE(MAX(e.value) FILTER (WHERE e.name = 'Make'), '') AS exif_make",
|
||||
"COALESCE(MAX(e.value) FILTER (WHERE e.name = 'Model'), '') AS exif_model",
|
||||
"COALESCE(MAX(e.value) FILTER (WHERE e.name = 'DateTime'), '') AS exif_datetime",
|
||||
"ni.nuisance_id AS nuisance_id",
|
||||
"ni.nuisance_id AS report_id",
|
||||
),
|
||||
sm.From("publicreport.image").As("i"),
|
||||
sm.LeftJoin("publicreport.image_exif").As("e").OnEQ(
|
||||
|
|
@ -66,12 +66,60 @@ func loadImagesForReportNuisance(ctx context.Context, org_id int32, report_ids [
|
|||
}
|
||||
results = make(map[int32][]types.Image, len(report_ids))
|
||||
for _, row := range rows {
|
||||
r, ok := results[row.NuisanceID]
|
||||
r, ok := results[row.ReportID]
|
||||
if !ok {
|
||||
r = make([]types.Image, 0)
|
||||
}
|
||||
r = append(r, row)
|
||||
results[row.NuisanceID] = r
|
||||
results[row.ReportID] = r
|
||||
}
|
||||
return results, nil
|
||||
}
|
||||
|
||||
// Get all the images that belong to the list of water report IDs
|
||||
func loadImagesForReportWater(ctx context.Context, org_id int32, report_ids []int32) (results map[int32][]types.Image, err error) {
|
||||
rows, err := bob.All(ctx, db.PGInstance.BobDB, psql.Select(
|
||||
sm.Columns(
|
||||
"i.storage_uuid AS uuid",
|
||||
"COALESCE(ST_X(i.location), 0) AS \"location.longitude\"",
|
||||
"COALESCE(ST_Y(i.location), 0) AS \"location.latitude\"",
|
||||
"ST_Distance(i.location::geography, w.location::geography) AS \"distance_from_reporter_meters\"",
|
||||
"COALESCE(MAX(e.value) FILTER (WHERE e.name = 'Make'), '') AS exif_make",
|
||||
"COALESCE(MAX(e.value) FILTER (WHERE e.name = 'Model'), '') AS exif_model",
|
||||
"COALESCE(MAX(e.value) FILTER (WHERE e.name = 'DateTime'), '') AS exif_datetime",
|
||||
"wi.water_id AS report_id",
|
||||
),
|
||||
sm.From("publicreport.image").As("i"),
|
||||
sm.LeftJoin("publicreport.image_exif").As("e").OnEQ(
|
||||
psql.Quote("i", "id"),
|
||||
psql.Quote("e", "image_id"),
|
||||
),
|
||||
sm.InnerJoin("publicreport.water_image").As("wi").OnEQ(
|
||||
psql.Quote("wi", "image_id"),
|
||||
psql.Quote("i", "id"),
|
||||
),
|
||||
sm.InnerJoin("publicreport.water").As("w").OnEQ(
|
||||
psql.Quote("wi", "water_id"),
|
||||
psql.Quote("w", "id"),
|
||||
),
|
||||
sm.Where(psql.Quote("wi", "water_id").EQ(psql.Any(report_ids))),
|
||||
sm.GroupBy(
|
||||
//psql.Quote("i", "id"),
|
||||
//psql.Quote("ni", "nuisance_id"),
|
||||
psql.Raw("i.id, wi.water_id, w.location"),
|
||||
),
|
||||
), scan.StructMapper[types.Image]())
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("get images: %w", err)
|
||||
}
|
||||
results = make(map[int32][]types.Image, len(report_ids))
|
||||
for _, row := range rows {
|
||||
r, ok := results[row.ReportID]
|
||||
if !ok {
|
||||
r = make([]types.Image, 0)
|
||||
}
|
||||
r = append(r, row)
|
||||
results[row.ReportID] = r
|
||||
}
|
||||
return results, nil
|
||||
}
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@ import (
|
|||
|
||||
"github.com/Gleipnir-Technology/nidus-sync/config"
|
||||
"github.com/google/uuid"
|
||||
//"github.com/rs/zerolog/log"
|
||||
)
|
||||
|
||||
type Exif struct {
|
||||
|
|
@ -35,13 +36,13 @@ func (e Exif) MarshalJSON() ([]byte, error) {
|
|||
}
|
||||
|
||||
type Image struct {
|
||||
DistanceToReporterMeters float64 `db:"distance_from_reporter_meters"`
|
||||
DistanceToReporterMeters *float64 `db:"distance_from_reporter_meters"`
|
||||
Exif Exif `db:"-" json:"exif"`
|
||||
ExifMake string `db:"exif_make" json:"-"`
|
||||
ExifModel string `db:"exif_model" json:"-"`
|
||||
ExifDateTime string `db:"exif_datetime" json:"-"`
|
||||
Location Location `db:"location"`
|
||||
NuisanceID int32 `db:"nuisance_id"`
|
||||
ReportID int32 `db:"report_id" json:"-"`
|
||||
URLContent string `db:"-" json:"url_content"`
|
||||
UUID uuid.UUID `db:"uuid"`
|
||||
}
|
||||
|
|
@ -55,7 +56,7 @@ func (i *Image) MarshalJSON() ([]byte, error) {
|
|||
Model: i.ExifModel,
|
||||
}
|
||||
to_marshal["location"] = i.Location
|
||||
to_marshal["nuisance_id"] = i.NuisanceID
|
||||
//to_marshal["report_id"] = i.ReportID
|
||||
to_marshal["url_content"] = config.MakeURLNidus("/api/image/%s/content", i.UUID.String())
|
||||
to_marshal["uuid"] = i.UUID
|
||||
|
||||
|
|
|
|||
|
|
@ -202,20 +202,20 @@ func contentFromNuisance(ctx context.Context, report_id string) (result ContentS
|
|||
return result, err
|
||||
}
|
||||
func contentFromWater(ctx context.Context, report_id string) (result ContentStatusByID, err error) {
|
||||
pool, err := models.PublicreportWaters.Query(
|
||||
water, err := models.PublicreportWaters.Query(
|
||||
models.SelectWhere.PublicreportWaters.PublicID.EQ(report_id),
|
||||
).One(ctx, db.PGInstance.BobDB)
|
||||
if err != nil {
|
||||
return result, fmt.Errorf("Failed to query pool %s: %w", report_id, err)
|
||||
return result, fmt.Errorf("Failed to query water %s: %w", report_id, err)
|
||||
}
|
||||
|
||||
images, err := sql.PublicreportImageWithJSONByWaterID(pool.ID).All(ctx, db.PGInstance.BobDB)
|
||||
images, err := sql.PublicreportImageWithJSONByWaterID(water.ID).All(ctx, db.PGInstance.BobDB)
|
||||
if err != nil {
|
||||
return result, fmt.Errorf("Failed to get images %s: %w", report_id, err)
|
||||
}
|
||||
|
||||
if !pool.OrganizationID.IsNull() {
|
||||
org_id := pool.OrganizationID.MustGet()
|
||||
if !water.OrganizationID.IsNull() {
|
||||
org_id := water.OrganizationID.MustGet()
|
||||
org, err := models.FindOrganization(ctx, db.PGInstance.BobDB, org_id)
|
||||
if err != nil {
|
||||
return result, fmt.Errorf("Failed to get district %d information: %w", org_id, err)
|
||||
|
|
@ -224,44 +224,44 @@ func contentFromWater(ctx context.Context, report_id string) (result ContentStat
|
|||
}
|
||||
|
||||
result.Report.ID = report_id
|
||||
result.Report.Address = pool.AddressRaw
|
||||
result.Report.Created = pool.Created
|
||||
result.Report.Address = water.AddressRaw
|
||||
result.Report.Created = water.Created
|
||||
result.Report.ImageCount = len(images)
|
||||
result.Report.Status = strings.Title(pool.Status.String())
|
||||
result.Report.Status = strings.Title(water.Status.String())
|
||||
result.Report.Type = "Mosquito Nuisance"
|
||||
result.Report.Details = []DetailEntry{
|
||||
DetailEntry{
|
||||
Name: "Has a gate that affects access?",
|
||||
Value: strconv.FormatBool(pool.AccessGate),
|
||||
Value: strconv.FormatBool(water.AccessGate),
|
||||
},
|
||||
DetailEntry{
|
||||
Name: "Has dog that affects access?",
|
||||
Value: strconv.FormatBool(pool.AccessDog),
|
||||
Value: strconv.FormatBool(water.AccessDog),
|
||||
},
|
||||
DetailEntry{
|
||||
Name: "Has a fence that affects access?",
|
||||
Value: strconv.FormatBool(pool.AccessFence),
|
||||
Value: strconv.FormatBool(water.AccessFence),
|
||||
},
|
||||
DetailEntry{
|
||||
Name: "Has a locked entrace that affects access?",
|
||||
Value: strconv.FormatBool(pool.AccessLocked),
|
||||
Value: strconv.FormatBool(water.AccessLocked),
|
||||
},
|
||||
DetailEntry{
|
||||
Name: "Reporter observed larvae (wigglers)?",
|
||||
Value: strconv.FormatBool(pool.HasLarvae),
|
||||
Value: strconv.FormatBool(water.HasLarvae),
|
||||
},
|
||||
DetailEntry{
|
||||
Name: "Reporter observed pupae (tumblers)?",
|
||||
Value: strconv.FormatBool(pool.HasPupae),
|
||||
Value: strconv.FormatBool(water.HasPupae),
|
||||
},
|
||||
DetailEntry{
|
||||
Name: "Reporter observed adult mosquitoes?",
|
||||
Value: strconv.FormatBool(pool.HasAdult),
|
||||
Value: strconv.FormatBool(water.HasAdult),
|
||||
},
|
||||
}
|
||||
result.Timeline = []TimelineEntry{
|
||||
TimelineEntry{
|
||||
At: pool.Created,
|
||||
At: water.Created,
|
||||
Detail: "Initial report was submitted",
|
||||
Title: "Created",
|
||||
},
|
||||
|
|
@ -273,11 +273,11 @@ func contentFromWater(ctx context.Context, report_id string) (result ContentStat
|
|||
sm.Columns(
|
||||
psql.F("ST_AsGeoJSON", "location"),
|
||||
),
|
||||
sm.From("publicreport.pool"),
|
||||
sm.From("publicreport.water"),
|
||||
sm.Where(psql.Quote("public_id").EQ(psql.Arg(report_id))),
|
||||
), scan.SingleColumnMapper[string])
|
||||
if err != nil {
|
||||
return result, fmt.Errorf("Failed to query pool %s: %w", report_id, err)
|
||||
return result, fmt.Errorf("Failed to query water %s: %w", report_id, err)
|
||||
}
|
||||
result.Report.Location = location
|
||||
|
||||
|
|
@ -299,7 +299,7 @@ func getStatusByID(w http.ResponseWriter, r *http.Request) {
|
|||
switch location.TableName.MustGet() {
|
||||
case "nuisance":
|
||||
content, err = contentFromNuisance(ctx, report_id)
|
||||
case "pool":
|
||||
case "water":
|
||||
content, err = contentFromWater(ctx, report_id)
|
||||
}
|
||||
if err != nil {
|
||||
|
|
|
|||
16
rmo/water.go
16
rmo/water.go
|
|
@ -81,7 +81,7 @@ func postWater(w http.ResponseWriter, r *http.Request) {
|
|||
|
||||
latlng, err := parseLatLng(r)
|
||||
if err != nil {
|
||||
respondError(w, "Failed to parse lat lng for pool report", err, http.StatusInternalServerError)
|
||||
respondError(w, "Failed to parse lat lng for water report", err, http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
|
||||
|
|
@ -92,7 +92,7 @@ func postWater(w http.ResponseWriter, r *http.Request) {
|
|||
}
|
||||
public_id, err := report.GenerateReportID()
|
||||
if err != nil {
|
||||
respondError(w, "Failed to create pool report public ID", err, http.StatusInternalServerError)
|
||||
respondError(w, "Failed to create water report public ID", err, http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
|
||||
|
|
@ -156,7 +156,7 @@ func postWater(w http.ResponseWriter, r *http.Request) {
|
|||
ReporterPhone: omit.From(""),
|
||||
Status: omit.From(enums.PublicreportReportstatustypeReported),
|
||||
}
|
||||
pool, err := models.PublicreportWaters.Insert(&setter).One(ctx, tx)
|
||||
water, err := models.PublicreportWaters.Insert(&setter).One(ctx, tx)
|
||||
if err != nil {
|
||||
respondError(w, "Failed to create database record", err, http.StatusInternalServerError)
|
||||
return
|
||||
|
|
@ -164,22 +164,22 @@ func postWater(w http.ResponseWriter, r *http.Request) {
|
|||
|
||||
if geospatial.Populated {
|
||||
_, err = psql.Update(
|
||||
um.Table("publicreport.pool"),
|
||||
um.Table("publicreport.water"),
|
||||
um.SetCol("h3cell").ToArg(geospatial.Cell),
|
||||
um.SetCol("location").To(geospatial.GeometryQuery),
|
||||
um.Where(psql.Quote("id").EQ(psql.Arg(pool.ID))),
|
||||
um.Where(psql.Quote("id").EQ(psql.Arg(water.ID))),
|
||||
).Exec(ctx, tx)
|
||||
if err != nil {
|
||||
respondError(w, "Failed to update publicreport.pool geospatial", err, http.StatusInternalServerError)
|
||||
respondError(w, "Failed to update publicreport.water geospatial", err, http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
}
|
||||
log.Info().Int32("id", pool.ID).Str("public_id", pool.PublicID).Msg("Created pool report")
|
||||
log.Info().Int32("id", water.ID).Str("public_id", water.PublicID).Msg("Created water report")
|
||||
setters := make([]*models.PublicreportWaterImageSetter, 0)
|
||||
for _, image := range images {
|
||||
setters = append(setters, &models.PublicreportWaterImageSetter{
|
||||
ImageID: omit.From(int32(image.ID)),
|
||||
WaterID: omit.From(int32(pool.ID)),
|
||||
WaterID: omit.From(int32(water.ID)),
|
||||
})
|
||||
}
|
||||
if len(setters) > 0 {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue