diff --git a/htmlpage/static/js/map-aggregate.js b/htmlpage/static/js/map-aggregate.js index 6c912eb0..11175360 100644 --- a/htmlpage/static/js/map-aggregate.js +++ b/htmlpage/static/js/map-aggregate.js @@ -132,14 +132,13 @@ class MapAggregate extends HTMLElement { 'fill-color': '#0dcaf0' } }); - var self = this; map.addInteraction("tegola-click-interaction", { type: "click", target: { layerId: "mosquito_source" }, handler: (e) => { const coordinates = e.feature.geometry.coordinates.slice(); const properties = e.feature.properties; - self.dispatchEvent(new CustomEvent("cell-click", { + this.dispatchEvent(new CustomEvent("cell-click", { bubbles: true, composed: true, // Allows event to cross shadow DOM boundary detail: { diff --git a/sync/dash.go b/sync/dash.go index 66e1f1f6..04b464ac 100644 --- a/sync/dash.go +++ b/sync/dash.go @@ -33,6 +33,15 @@ type Config struct { URLTegola string } +type ContextCell struct { + BreedingSources []BreedingSourceSummary + CellBoundary h3.CellBoundary + Inspections []Inspection + MapData ComponentMap + Traps []Trap + Treatments []Treatment + User User +} type ContextDashboard struct { Config Config CountTraps int @@ -161,12 +170,18 @@ func cell(ctx context.Context, w http.ResponseWriter, user *models.User, c int64 respondError(w, "Failed to get sources", err, http.StatusInternalServerError) return } + traps, err := trapsByCell(ctx, org, h3.Cell(c)) + if err != nil { + respondError(w, "Failed to get traps", err, http.StatusInternalServerError) + return + } + treatments, err := treatmentsByCell(ctx, org, h3.Cell(c)) if err != nil { respondError(w, "Failed to get treatments", err, http.StatusInternalServerError) return } - data := ContentCell{ + data := ContextCell{ BreedingSources: sources, CellBoundary: boundary, Inspections: inspections, @@ -179,6 +194,7 @@ func cell(ctx context.Context, w http.ResponseWriter, user *models.User, c int64 MapboxToken: config.MapboxToken, Zoom: resolution + 5, }, + Traps: traps, Treatments: treatments, User: userContent, } diff --git a/sync/model_conversion.go b/sync/model_conversion.go index 6f07ec8a..31156274 100644 --- a/sync/model_conversion.go +++ b/sync/model_conversion.go @@ -154,6 +154,13 @@ type TrapData struct { Comments string `json:"comments"` } +type Trap struct { + Active bool + Comments string + Description string + GlobalID uuid.UUID +} + type Treatment struct { CadenceDelta time.Duration Date *time.Time @@ -162,7 +169,18 @@ type Treatment struct { Product string } -func toTemplateTraps(locations []sql.TrapLocationBySourceIDRow, trap_data []sql.TrapDataByLocationIDRecentRow, counts []sql.TrapCountByLocationIDRow) ([]TrapNearby, error) { +func toTemplateTrap(traps models.FieldseekerTraplocationSlice) (results []Trap, err error) { + for _, t := range traps { + results = append(results, Trap{ + Active: toBool16Or(t.Active, false), + Comments: t.Comments.GetOr(""), + Description: t.Description.GetOr(""), + GlobalID: t.Globalid, + }) + } + return results, err +} +func toTemplateTrapsNearby(locations []sql.TrapLocationBySourceIDRow, trap_data []sql.TrapDataByLocationIDRecentRow, counts []sql.TrapCountByLocationIDRow) ([]TrapNearby, error) { results := make([]TrapNearby, 0) count_by_trap_data_id := make(map[uuid.UUID]*sql.TrapCountByLocationIDRow) for _, c := range counts { @@ -409,3 +427,17 @@ func getTimeOrNull(v null.Val[time.Time]) *time.Time { val := v.MustGet() return &val } + +func toBool16Or(t null.Val[int16], def bool) bool { + if t.IsNull() { + return def + } + val := t.MustGet() + var b bool + if val == 0 { + b = false + } else { + b = true + } + return b +} diff --git a/sync/template/cell.html b/sync/template/cell.html index 96d716fb..82a9162a 100644 --- a/sync/template/cell.html +++ b/sync/template/cell.html @@ -160,6 +160,36 @@
+

Traps

+ {{ if gt (len .Traps) 0}} +
+
+
+ + + + + + + + + + {{ range .Traps }} + + + + + + {{ end }} + +
IDActiveComments
{{.GlobalID|uuidShort}}{{.Active}}{{.Comments}}
+
+
+
+ {{ else }} +

No traps

+ {{ end }} +

Treatment History

diff --git a/sync/types.go b/sync/types.go index b8435495..a31b3712 100644 --- a/sync/types.go +++ b/sync/types.go @@ -28,14 +28,6 @@ type ComponentMap struct { type ContentAuthenticatedPlaceholder struct { User User } -type ContentCell struct { - BreedingSources []BreedingSourceSummary - CellBoundary h3.CellBoundary - Inspections []Inspection - MapData ComponentMap - Treatments []Treatment - User User -} type ContentMockURLs struct { Dispatch string DispatchResults string @@ -95,7 +87,7 @@ type Link struct { Title string } type Organization struct { - ID int + ID int Name string } type ServiceRequestSummary struct { @@ -104,9 +96,9 @@ type ServiceRequestSummary struct { Status string } type User struct { - DisplayName string - Initials string - Notifications []notification.Notification - Organization Organization - Username string + DisplayName string + Initials string + Notifications []notification.Notification + Organization Organization + Username string } diff --git a/sync/utils.go b/sync/utils.go index 45c0d23b..7cba5560 100644 --- a/sync/utils.go +++ b/sync/utils.go @@ -100,11 +100,11 @@ func contentForUser(ctx context.Context, user *models.User) (User, error) { DisplayName: user.DisplayName, Initials: extractInitials(user.DisplayName), Notifications: notifications, - Organization: Organization { - ID: int(org.ID), + Organization: Organization{ + ID: int(org.ID), Name: org.Name, }, - Username: user.Username, + Username: user.Username, }, nil } @@ -181,7 +181,7 @@ func trapsBySource(ctx context.Context, org *models.Organization, sourceID uuid. return nil, fmt.Errorf("Failed to query trap counts: %w", err) } - traps, err := toTemplateTraps(locations, trap_data, counts) + traps, err := toTemplateTrapsNearby(locations, trap_data, counts) if err != nil { return nil, fmt.Errorf("Failed to convert trap data: %w", err) } @@ -203,6 +203,24 @@ func treatmentsBySource(ctx context.Context, org *models.Organization, sourceID return toTemplateTreatment(rows) } +func trapsByCell(ctx context.Context, org *models.Organization, c h3.Cell) (results []Trap, err error) { + boundary, err := c.Boundary() + if err != nil { + return results, fmt.Errorf("Failed to get cell boundary: %w", err) + } + geom_query := gisStatement(boundary) + rows, err := org.Traplocations( + sm.Where( + psql.F("ST_Within", "geospatial", geom_query), + ), + sm.OrderBy("objectid"), + ).All(ctx, db.PGInstance.BobDB) + if err != nil { + return results, fmt.Errorf("Failed to query rows: %w", err) + } + return toTemplateTrap(rows) +} + func treatmentsByCell(ctx context.Context, org *models.Organization, c h3.Cell) ([]Treatment, error) { var results []Treatment boundary, err := c.Boundary()