diff --git a/api/address.go b/api/address.go
new file mode 100644
index 00000000..3cfa61bc
--- /dev/null
+++ b/api/address.go
@@ -0,0 +1,11 @@
+package api
+
+type Address struct {
+ Country string `db:"country" json:"country"`
+ Locality string `db:"locality" json:"locality"`
+ Number string `db:"number" json:"number"`
+ PostalCode string `db:"postal_code" json:"postal_code"`
+ Region string `db:"region" json:"region"`
+ Street string `db:"street" json:"street"`
+ Unit string `db:"unit" json:"unit"`
+}
diff --git a/api/communication.go b/api/communication.go
new file mode 100644
index 00000000..e6cf9b1b
--- /dev/null
+++ b/api/communication.go
@@ -0,0 +1,118 @@
+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/sm"
+ "github.com/Gleipnir-Technology/nidus-sync/config"
+ "github.com/Gleipnir-Technology/nidus-sync/db"
+ "github.com/Gleipnir-Technology/nidus-sync/db/models"
+ nhttp "github.com/Gleipnir-Technology/nidus-sync/http"
+ "github.com/google/uuid"
+ //"github.com/Gleipnir-Technology/nidus-sync/platform"
+ //"github.com/aarondl/opt/null"
+ "github.com/stephenafamo/scan"
+)
+
+type reporter struct {
+ HasEmail bool `json:"has_email"`
+ HasPhone bool `json:"has_phone"`
+ Name string `json:"name"`
+}
+type publicReport struct {
+ Address Address `json:"address"`
+ Images []string `json:"images"`
+ Reporter reporter `json:"reporter"`
+}
+type communication struct {
+ Created time.Time `json:"created"`
+ ID string `json:"id"`
+ PublicReport 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 := models.PublicreportNuisances.Query(
+ models.SelectWhere.PublicreportNuisances.OrganizationID.EQ(org.ID),
+ ).All(ctx, db.PGInstance.BobDB)
+ if err != nil {
+ return nil, nhttp.NewError("get reports: %w")
+ }
+ type _Row struct {
+ PublicID string `db:"nuisance_public_id"`
+ StorageUUID uuid.UUID `db:"storage_uuid"`
+ }
+ rows, err := bob.All(ctx, db.PGInstance.BobDB, psql.Select(
+ sm.Columns(
+ "n.public_id AS nuisance_public_id",
+ "i.storage_uuid AS storage_uuid",
+ ),
+ sm.From("publicreport.nuisance").As("n"),
+ sm.InnerJoin("publicreport.nuisance_image").As("ni").OnEQ(
+ psql.Quote("n", "id"),
+ psql.Quote("ni", "nuisance_id"),
+ ),
+ sm.InnerJoin("publicreport.image").As("i").OnEQ(
+ psql.Quote("ni", "image_id"),
+ psql.Quote("i", "id"),
+ ),
+ sm.Where(psql.Quote("n", "organization_id").EQ(psql.Arg(org.ID))),
+ ), scan.StructMapper[_Row]())
+ if err != nil {
+ return nil, nhttp.NewError("get images: %w")
+ }
+ id_to_images := make(map[string][]uuid.UUID, len(reports))
+ for _, row := range rows {
+ r, ok := id_to_images[row.PublicID]
+ if !ok {
+ r = make([]uuid.UUID, 0)
+ }
+ r = append(r, row.StorageUUID)
+ id_to_images[row.PublicID] = r
+ }
+ comms := make([]communication, len(reports))
+ for i, report := range reports {
+ comms[i] = communication{
+ PublicReport: publicReport{
+ Address: Address{
+ Country: report.AddressCountry,
+ Locality: report.AddressPlace,
+ //Number: report.Address
+ PostalCode: report.AddressPostcode,
+ Region: report.AddressRegion,
+ Street: report.AddressStreet,
+ },
+ Images: toImageURLs(id_to_images, report.PublicID),
+ Reporter: reporter{
+ Name: report.ReporterName.GetOr(""),
+ HasEmail: report.ReporterEmail.IsValue(),
+ HasPhone: report.ReporterPhone.IsValue(),
+ },
+ },
+ Created: report.Created,
+ ID: report.PublicID,
+ }
+ }
+ return &contentListCommunication{
+ Communications: comms,
+ }, nil
+}
+
+func toImageURLs(m map[string][]uuid.UUID, id string) []string {
+ uuids, ok := m[id]
+ if !ok {
+ return []string{}
+ }
+ urls := make([]string, len(uuids))
+ for _, u := range uuids {
+ urls = append(urls, config.MakeURLNidus("/api/image/%s", u.String()))
+ }
+ return urls
+}
diff --git a/api/handler.go b/api/handler.go
index d3e933e5..451d60af 100644
--- a/api/handler.go
+++ b/api/handler.go
@@ -22,6 +22,7 @@ var decoder = schema.NewDecoder()
type queryParams struct {
Limit *int `schema:"limit"`
Sort *string `schema:"sort"`
+ Type *string `schema:"type"`
}
type handlerFunctionGet[T any] func(context.Context, *http.Request, *models.Organization, *models.User, queryParams) (*T, *nhttp.ErrorWithStatus)
diff --git a/api/routes.go b/api/routes.go
index 6740b389..b0ed5c18 100644
--- a/api/routes.go
+++ b/api/routes.go
@@ -10,6 +10,7 @@ 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))
diff --git a/api/signal.go b/api/signal.go
index 7a665803..343a81a0 100644
--- a/api/signal.go
+++ b/api/signal.go
@@ -16,15 +16,6 @@ import (
"github.com/stephenafamo/scan"
)
-type Address struct {
- Country string `db:"country" json:"country"`
- Locality string `db:"locality" json:"locality"`
- Number string `db:"number" json:"number"`
- PostalCode string `db:"postal_code" json:"postal_code"`
- Region string `db:"region" json:"region"`
- Street string `db:"street" json:"street"`
- Unit string `db:"unit" json:"unit"`
-}
type signal struct {
Address Address `json:"address"`
Addressed *time.Time `json:"addressed"`
diff --git a/html/template/sync/communication-root.html b/html/template/sync/communication-root.html
index a7163305..faa3e3da 100644
--- a/html/template/sync/communication-root.html
+++ b/html/template/sync/communication-root.html
@@ -14,72 +14,18 @@
function onLoad() {}
window.addEventListener("load", onLoad);
-