Skip to content

Commit

Permalink
feat: add hourly results for daily summary table
Browse files Browse the repository at this point in the history
by clicking hour column you now see all results of that specific hour
  • Loading branch information
tphakala committed Jun 22, 2024
1 parent 1219025 commit fc3c6f3
Show file tree
Hide file tree
Showing 5 changed files with 149 additions and 2 deletions.
17 changes: 16 additions & 1 deletion internal/datastore/interfaces.go
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// interfaces.go this code defines the interface for the database operations
// interfaces.go: this code defines the interface for the database operations
package datastore

import (
Expand Down Expand Up @@ -36,6 +36,7 @@ type Interface interface {
SaveHourlyWeather(hourlyWeather *HourlyWeather) error
GetHourlyWeather(date string) ([]HourlyWeather, error)
LatestHourlyWeather() (*HourlyWeather, error)
GetHourlyDetections(date, hour string) ([]Note, error)
}

// DataStore implements StoreInterface using a GORM database.
Expand Down Expand Up @@ -442,3 +443,17 @@ func createGormLogger() logger.Interface {
},
)
}

// GetHourlyDetections retrieves bird detections for a specific date and hour.
func (ds *DataStore) GetHourlyDetections(date, hour string) ([]Note, error) {
var detections []Note

startTime := hour + ":00:00"
endTime := hour + ":59:59"

err := ds.DB.Where("date = ? AND time >= ? AND time <= ?", date, startTime, endTime).
Order("time ASC").
Find(&detections).Error

return detections, err
}
32 changes: 32 additions & 0 deletions internal/httpcontroller/handlers.go
Original file line number Diff line number Diff line change
Expand Up @@ -399,3 +399,35 @@ func (s *Server) serveSpectrogramHandler(c echo.Context) error {
// Serve the spectrogram image file
return c.File(spectrogramPath)
}

// hourlyDetectionsHandler handles requests for hourly detections
func (s *Server) hourlyDetectionsHandler(c echo.Context) error {
date := c.QueryParam("date")
hour := c.QueryParam("hour")

if date == "" || hour == "" {
return echo.NewHTTPError(http.StatusBadRequest, "Date and hour are required.")
}

// Fetch all detections for the specified date and hour
detections, err := s.ds.GetHourlyDetections(date, hour)
if err != nil {
return echo.NewHTTPError(http.StatusInternalServerError, err.Error())
}

// Prepare data for rendering in the template
data := struct {
Date string
Hour string
Detections []datastore.Note
DashboardSettings *conf.Dashboard
}{
Date: date,
Hour: hour,
Detections: detections,
DashboardSettings: s.DashboardSettings,
}

// Render the hourlyDetections template with the data
return c.Render(http.StatusOK, "hourlyDetections", data)
}
2 changes: 2 additions & 0 deletions internal/httpcontroller/routes.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ var routes = []routeConfig{
{Path: "/logs", TemplateName: "logs", Title: "Logs"},
{Path: "/stats", TemplateName: "stats", Title: "Statistics"},
{Path: "/settings", TemplateName: "settings", Title: "General Settings"},
{Path: "/hourly-detections", TemplateName: "hourlyDetections", Title: "Hourly Detections"},
}

// initRoutes initializes the routes for the server.
Expand Down Expand Up @@ -76,6 +77,7 @@ func (s *Server) initRoutes() {
s.Echo.GET("/species-detections", s.speciesDetectionsHandler)
s.Echo.GET("/search", s.searchHandler)
s.Echo.GET("/spectrogram", s.serveSpectrogramHandler)
s.Echo.GET("/hourly-detections", s.hourlyDetectionsHandler)

// Handle both GET and DELETE requests for the /note route
s.Echo.Add("GET", "/note", s.getNoteHandler)
Expand Down
10 changes: 9 additions & 1 deletion views/fragments/birdsTableHTML.html
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,15 @@
{{end}}
<th scope="col" class="py-2 px-4 w-100 hidden md:table-cell">Detections</th>
{{range .Hours}}
<th scope="col" class="text-center py-2 px-0">{{printf "%02d" .}}</th>
<th scope="col" class="text-center py-2 px-0">
<a href="#"
hx-get="/hourly-detections?date={{urlquery $.SelectedDate}}&hour={{printf "%02d" .}}"
hx-target="#mainContent"
hx-trigger="click"
hx-push-url="true">
{{printf "%02d" .}}
</a>
</th>
{{end}}
<th scope="col" class="py-2 px-0"></th>
</tr>
Expand Down
90 changes: 90 additions & 0 deletions views/fragments/hourlyDetections.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
{{define "hourlyDetections"}}
<section class="card col-span-12 overflow-hidden bg-base-100 shadow-sm xl:col-span-12">
<div class="card-body grow-0 p-4 ml-2">
<div class="flex justify-between">
<span class="card-title grow"><a class="link-hover link">Hourly Results for {{.Hour}}:00 on {{.Date}}</a></span>
</div>
</div>

<table class="table w-full text-sm text-left text-gray-600 dark:text-gray-300">
<thead class="text-xs">
<tr>
<!-- Date Column -->
<th scope="col" class="py-2 px-6" style="width: 15%">Date</th>

<!-- Time Column -->
<th scope="col" class="py-2 px-2" style="width: 15%">Time</th>

<!-- Common Name Column -->
<th scope="col" class="py-2 px-4" style="width: auto">Common Name</th>

<!-- Thumbnail Column -->
{{if .DashboardSettings.Thumbnails.Summary}}
<th scope="col" class="py-2 px-4" style="width: 20%">Thumbnail</th>
{{end}}

<!-- Confidence Column -->
<th scope="col" class="py-2 px-4" style="width: auto">Confidence</th>

<!-- Recording Column -->
<th scope="col" class="py-2 px-4" style="width: 30%">Recording</th>
</tr>
</thead>
<tbody>
{{range .Detections}}
<tr class="">
<!-- Date Column -->
<td class="py-1 px-6">{{.Date}}</td>

<!-- Time Column -->
<td class="py-1 px-2">{{.Time}}</td>

<!-- Common Name Column -->
<td class="py-1 px-4">
<a href="#" hx-get="/note?id={{.ID}}" hx-target="#mainContent" hx-swap="innerHTML" hx-trigger="click" hx-push-url="true">
{{.CommonName}}
</a>
</td>

<!-- Thumbnail Column -->
{{if $.DashboardSettings.Thumbnails.Summary}}
<td class="py-1 px-4">
<div class="thumbnail-container">
<img loading="lazy" width="150" src="{{thumbnail .ScientificName}}" class="h-auto rounded-md">
<div class="thumbnail-tooltip hidden">
{{thumbnailAttribution .ScientificName}}
</div>
</div>
</td>
{{end}}

<!-- Confidence Column -->
<td class="py-1 px-4">
<div class="confidence-ball {{confidenceColor .Confidence}} text-white font-medium">
<a href="#" hx-get="/note?id={{.ID}}" hx-target="#mainContent" hx-swap="innerHTML" hx-trigger="click" hx-push-url="true">
{{confidence .Confidence}}
</a>
</div>
</td>

<!-- Recording Column -->
<td class="py-1 px-6 flex justify-center">
<div class="w-full">
<!-- Spectrogram Image -->
<a href="#" hx-get="/note?id={{.ID}}" hx-target="#mainContent" hx-swap="innerHTML" hx-trigger="click" hx-push-url="true">
<img loading="lazy" width="400" src="/spectrogram?clip={{urlquery .ClipName}}" alt="Spectrogram Image" class="max-w-full h-auto rounded-md">
</a>

<!-- Audio player -->
<audio controls class="audio-control" preload="metadata">
<source src="{{.ClipName}}" type="audio/wav">
Your browser does not support the audio element.
</audio>
</div>
</td>
</tr>
{{end}}
</tbody>
</table>
</section>
{{end}}

0 comments on commit fc3c6f3

Please sign in to comment.