diff --git a/platform/publicreport.go b/platform/publicreport.go index 643e1fbd..b5654bb1 100644 --- a/platform/publicreport.go +++ b/platform/publicreport.go @@ -18,20 +18,15 @@ import ( "github.com/Gleipnir-Technology/nidus-sync/platform/email" "github.com/Gleipnir-Technology/nidus-sync/platform/event" "github.com/Gleipnir-Technology/nidus-sync/platform/geocode" + "github.com/Gleipnir-Technology/nidus-sync/platform/publicreport" "github.com/Gleipnir-Technology/nidus-sync/platform/report" "github.com/Gleipnir-Technology/nidus-sync/platform/text" "github.com/Gleipnir-Technology/nidus-sync/platform/types" "github.com/rs/zerolog/log" ) -func PublicreportByID(ctx context.Context, report_id string) (*models.PublicreportReport, error) { - report, err := models.PublicreportReports.Query( - models.SelectWhere.PublicreportReports.PublicID.EQ(report_id), - ).One(ctx, db.PGInstance.BobDB) - if err != nil { - return nil, err - } - return report, nil +func PublicreportByID(ctx context.Context, report_id string) (*types.Report, error) { + return publicreport.Report(ctx, report_id) } func PublicreportInvalid(ctx context.Context, user User, report_id string) error { report, err := reportFromID(ctx, user, report_id) diff --git a/platform/publicreport/image.go b/platform/publicreport/image.go index 3dc78b03..a0a5e912 100644 --- a/platform/publicreport/image.go +++ b/platform/publicreport/image.go @@ -29,7 +29,7 @@ WHERE i.id IN (1, 2, 3, 4) GROUP BY i.id; */ // Get all the images that belong to the list of report IDs -func loadImagesForReport(ctx context.Context, org_id int32, report_ids []int32) (results map[int32][]types.Image, err error) { +func loadImagesForReport(ctx context.Context, 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", diff --git a/platform/publicreport/report.go b/platform/publicreport/report.go index e634fe45..813ff67e 100644 --- a/platform/publicreport/report.go +++ b/platform/publicreport/report.go @@ -18,13 +18,14 @@ import ( ) func ReportsForOrganization(ctx context.Context, org_id int32) ([]*types.Report, error) { - query := reportQuery(org_id) + query := reportQuery() query.Apply( + sm.Where(psql.Quote("publicreport", "report", "organization_id").EQ(psql.Arg(org_id))), sm.Where(psql.Quote("publicreport", "report", "reviewed").IsNull()), ) - return reportQueryToRows(ctx, org_id, query) + return reportQueryToRows(ctx, query) } -func reportQueryToRows(ctx context.Context, org_id int32, query bob.BaseQuery[*dialect.SelectQuery]) ([]*types.Report, error) { +func reportQueryToRows(ctx context.Context, query bob.BaseQuery[*dialect.SelectQuery]) ([]*types.Report, error) { rows, err := bob.All(ctx, db.PGInstance.BobDB, query, scan.StructMapper[types.Report]()) if err != nil { @@ -34,7 +35,7 @@ func reportQueryToRows(ctx context.Context, org_id int32, query bob.BaseQuery[*d for i, row := range rows { report_ids[i] = row.ID } - images_by_id, err := loadImagesForReport(ctx, org_id, report_ids) + images_by_id, err := loadImagesForReport(ctx, report_ids) if err != nil { return nil, fmt.Errorf("images for report: %w", err) } @@ -69,12 +70,27 @@ func reportQueryToRows(ctx context.Context, org_id int32, query bob.BaseQuery[*d } return results, nil } -func Reports(ctx context.Context, org_id int32, ids []int32) ([]*types.Report, error) { - query := reportQuery(org_id) +func Report(ctx context.Context, public_id string) (*types.Report, error) { + query := reportQuery() query.Apply( + sm.Where(psql.Quote("publicreport", "report", "public_id").EQ(psql.Arg(public_id))), + ) + reports, err := reportQueryToRows(ctx, query) + if err != nil { + return nil, fmt.Errorf("query to rows: %w", err) + } + if len(reports) != 1 { + return nil, fmt.Errorf("reports returned: %d", len(reports)) + } + return reports[0], nil +} +func Reports(ctx context.Context, org_id int32, ids []int32) ([]*types.Report, error) { + query := reportQuery() + query.Apply( + sm.Where(psql.Quote("publicreport", "report", "organization_id").EQ(psql.Arg(org_id))), sm.Where(psql.Quote("publicreport", "report", "id").EQ(psql.Any(ids))), ) - return reportQueryToRows(ctx, org_id, query) + return reportQueryToRows(ctx, query) } func ReportsForOrganizationCount(ctx context.Context, org_id int32) (uint, error) { type _Row struct { @@ -92,10 +108,11 @@ func ReportsForOrganizationCount(ctx context.Context, org_id int32) (uint, error } return row.Count, nil } -func reportQuery(org_id int32) bob.BaseQuery[*dialect.SelectQuery] { +func reportQuery() bob.BaseQuery[*dialect.SelectQuery] { return psql.Select( sm.Columns( "address_country AS \"address.country\"", + "address_gid AS \"address.gid\"", "address_locality AS \"address.locality\"", "address_number AS \"address.number\"", "address_postal_code AS \"address.postal_code\"", @@ -106,6 +123,7 @@ func reportQuery(org_id int32) bob.BaseQuery[*dialect.SelectQuery] { "id", "COALESCE(ST_Y(location::geometry::geometry(point, 4326)), 0.0) AS \"location.latitude\"", "COALESCE(ST_X(location::geometry::geometry(point, 4326)), 0.0) AS \"location.longitude\"", + "organization_id", "public_id", "report_type", "reporter_email AS \"reporter.email\"", @@ -114,6 +132,5 @@ func reportQuery(org_id int32) bob.BaseQuery[*dialect.SelectQuery] { "status", ), sm.From("publicreport.report"), - sm.Where(psql.Quote("publicreport", "report", "organization_id").EQ(psql.Arg(org_id))), ) } diff --git a/platform/types/report.go b/platform/types/report.go index 968660e9..ed8b2fd9 100644 --- a/platform/types/report.go +++ b/platform/types/report.go @@ -13,9 +13,12 @@ type Report struct { Location *Location `db:"location" json:"location"` Log []LogEntry `db:"-" json:"log"` Nuisance *Nuisance `db:"nuisance" json:"nuisance"` + DistrictID *int32 `db:"organization_id" json:"-"` + District *string `db:"-" json:"district"` PublicID string `db:"public_id" json:"public_id"` Reporter Contact `db:"reporter" json:"reporter"` Status string `db:"status" json:"status"` Type string `db:"report_type" json:"type"` + URI string `db:"-" json:"uri"` Water *Water `db:"water" json:"water"` } diff --git a/resource/district.go b/resource/district.go index 0d438d23..be9b86a5 100644 --- a/resource/district.go +++ b/resource/district.go @@ -20,6 +20,7 @@ type district struct { Name string `json:"name"` PhoneOffice string `json:"phone_office"` Slug string `json:"slug"` + URI string `json:"uri"` URLLogo string `json:"url_logo"` URLWebsite string `json:"url_website"` } @@ -75,10 +76,15 @@ func newDistrict(r *router, org *platform.Organization) (*district, error) { if err != nil { return nil, fmt.Errorf("logo url: %w", err) } + uri, err := r.IDToURI("district.ByIDGet", int(org.ID)) + if err != nil { + return nil, nhttp.NewError("district uri: %w", err) + } return &district{ Name: org.Name(), PhoneOffice: org.PhoneOffice(), Slug: slug, + URI: uri, URLLogo: logo, URLWebsite: org.Website(), }, nil diff --git a/resource/publicreport.go b/resource/publicreport.go index af069928..4e5e5183 100644 --- a/resource/publicreport.go +++ b/resource/publicreport.go @@ -2,7 +2,6 @@ package resource import ( "context" - "time" nhttp "github.com/Gleipnir-Technology/nidus-sync/http" "github.com/Gleipnir-Technology/nidus-sync/platform" @@ -16,25 +15,13 @@ type publicreportR struct { router *router } -type publicreport struct { - Address string `json:"address"` - Created time.Time `json:"created"` - District string `json:"district"` - ID string `json:"id"` - ImageCount int `json:"image_count"` - Location types.Location `json:"location"` - Status string `json:"status"` - Type string `json:"type"` - URI string `json:"uri"` -} - func Publicreport(r *router) *publicreportR { return &publicreportR{ router: r, } } -func (res *publicreportR) ByID(ctx context.Context, r *http.Request, query QueryParams) (*publicreport, *nhttp.ErrorWithStatus) { +func (res *publicreportR) ByID(ctx context.Context, r *http.Request, query QueryParams) (*types.Report, *nhttp.ErrorWithStatus) { vars := mux.Vars(r) public_id := vars["id"] if public_id == "" { @@ -44,27 +31,18 @@ func (res *publicreportR) ByID(ctx context.Context, r *http.Request, query Query if err != nil { return nil, nhttp.NewError("get report: %w", err) } - district_uri, err := res.router.IDToURI("district.ByIDGet", int(report.OrganizationID)) - if err != nil { - return nil, nhttp.NewError("district uri: %w", err) + var district_uri string + if report.DistrictID != nil { + district_uri, err = res.router.IDToURI("district.ByIDGet", int(*report.DistrictID)) + if err != nil { + return nil, nhttp.NewError("district uri: %w", err) + } } uri, err := res.router.IDStrToURI("publicreport.ByIDGet", report.PublicID) if err != nil { return nil, nhttp.NewError("uri: %w", err) } - location := types.Location{ - Latitude: report.LocationLatitude.GetOr(0.0), - Longitude: report.LocationLongitude.GetOr(0.0), - } - return &publicreport{ - District: district_uri, - ID: report.PublicID, - Address: report.AddressRaw, - Created: report.Created, - ImageCount: len(report.R.Images), - Location: location, - Status: report.Status.String(), - Type: report.ReportType.String(), - URI: uri, - }, nil + report.District = &district_uri + report.URI = uri + return report, nil } diff --git a/ts/components/MapLocatorDisplay.vue b/ts/components/MapLocatorDisplay.vue index 41707f48..dfa90be8 100644 --- a/ts/components/MapLocatorDisplay.vue +++ b/ts/components/MapLocatorDisplay.vue @@ -103,10 +103,10 @@ const updateMarkers = () => { markerData.location.longitude, markerData.location.latitude, ]); - marker.setDraggable(markerData.draggable ?? false); + marker.setDraggable(false); } else { marker = new maplibregl.Marker({ - draggable: markerData.draggable ?? false, + draggable: false, }) .setLngLat([ markerData.location.longitude, @@ -117,6 +117,7 @@ const updateMarkers = () => { mapMarkers.value.set(markerData.id, marker); } }); + frameMarkers(); }; // Frame all markers in view @@ -130,7 +131,7 @@ const frameMarkers = () => { lat: props.markers[0].location.latitude, lng: props.markers[0].location.longitude, }, - { duration: 1000 }, + { duration: 1000, zoom: 15 }, { isInternalUpdate: true }, ); } else { diff --git a/ts/rmo/content/Nuisance.vue b/ts/rmo/content/Nuisance.vue index 49496622..9ec1521c 100644 --- a/ts/rmo/content/Nuisance.vue +++ b/ts/rmo/content/Nuisance.vue @@ -13,19 +13,6 @@ margin-bottom: 1rem; padding-bottom: 0; } -.map-container { - border-radius: 10px; - box-shadow: 0 4px 6px rgba(0, 0, 0, 0.05); - height: 500px; - align-items: center; - justify-content: center; - margin-bottom: 20px; - margin-top: 20px; -} -#map { - width: 100%; - height: 100%; -} .section-heading { margin-bottom: 1.5rem; display: flex; @@ -111,9 +98,15 @@ select.tall { height: 500px; margin-bottom: 20px; margin-top: 20px; + align-items: center; + justify-content: center; /* Prevent touch scrolling issues */ touch-action: pan-y pinch-zoom; } +#map { + width: 100%; + height: 100%; +} /* Mobile-specific adjustments */ @media (max-width: 768px) { @@ -131,11 +124,6 @@ select.tall { border-radius: 5px; } } - -#map { - width: 100%; - height: 100%; -}