Skip to content

Commit

Permalink
Merge pull request #181 from calvinmclean/feature/garden-notification…
Browse files Browse the repository at this point in the history
…-settings

Add NotificationSettings to the Garden
  • Loading branch information
calvinmclean authored Dec 29, 2024
2 parents 5d7e320 + 9e91f1a commit 1544831
Show file tree
Hide file tree
Showing 14 changed files with 206 additions and 4,122 deletions.
3 changes: 3 additions & 0 deletions garden-app/integration_tests/main_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -497,6 +497,9 @@ func ControllerStartupNotificationTest(t *testing.T) {
t.Run("EnableNotificationsForGarden", func(t *testing.T) {
status, err := makeRequest(http.MethodPatch, "/gardens/"+g.GetID(), pkg.Garden{
NotificationClientID: pointer(nc.GetID()),
NotificationSettings: &pkg.NotificationSettings{
ControllerStartup: true,
},
}, &g)
assert.NoError(t, err)
assert.Equal(t, http.StatusOK, status)
Expand Down
47 changes: 35 additions & 12 deletions garden-app/pkg/garden.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,22 +20,28 @@ const (
HealthStatusUp HealthStatus = "UP"
HealthStatusUnknown HealthStatus = "N/A"

currentGardenVersion = uint(1)
currentGardenVersion = uint(2)
)

// Garden is the representation of a single garden-controller device
type Garden struct {
Name string `json:"name" yaml:"name,omitempty"`
TopicPrefix string `json:"topic_prefix,omitempty" yaml:"topic_prefix,omitempty"`
ID babyapi.ID `json:"id" yaml:"id,omitempty"`
MaxZones *uint `json:"max_zones" yaml:"max_zones"`
CreatedAt *time.Time `json:"created_at" yaml:"created_at,omitempty"`
EndDate *time.Time `json:"end_date,omitempty" yaml:"end_date,omitempty"`
LightSchedule *LightSchedule `json:"light_schedule,omitempty" yaml:"light_schedule,omitempty"`
TemperatureHumiditySensor *bool `json:"temperature_humidity_sensor,omitempty" yaml:"temperature_humidity_sensor,omitempty"`
NotificationClientID *string `json:"notification_client_id,omitempty" yaml:"notification_client_id,omitempty"`
ControllerConfig *ControllerConfig `json:"controller_config,omitempty" yaml:"controller_config,omitempty"`
Version uint `json:"version,omitempty" yaml:"version"`
Name string `json:"name" yaml:"name,omitempty"`
TopicPrefix string `json:"topic_prefix,omitempty" yaml:"topic_prefix,omitempty"`
ID babyapi.ID `json:"id" yaml:"id,omitempty"`
MaxZones *uint `json:"max_zones" yaml:"max_zones"`
CreatedAt *time.Time `json:"created_at" yaml:"created_at,omitempty"`
EndDate *time.Time `json:"end_date,omitempty" yaml:"end_date,omitempty"`
LightSchedule *LightSchedule `json:"light_schedule,omitempty" yaml:"light_schedule,omitempty"`
TemperatureHumiditySensor *bool `json:"temperature_humidity_sensor,omitempty" yaml:"temperature_humidity_sensor,omitempty"`
NotificationClientID *string `json:"notification_client_id,omitempty" yaml:"notification_client_id,omitempty"`
NotificationSettings *NotificationSettings `json:"notification_settings,omitempty" yaml:"notification_settings,omitempty"`
ControllerConfig *ControllerConfig `json:"controller_config,omitempty" yaml:"controller_config,omitempty"`
Version uint `json:"version,omitempty" yaml:"version"`
}

type NotificationSettings struct {
ControllerStartup bool `json:"controller_startup" yaml:"controller_startup"`
LightSchedule bool `json:"light_schedule" yaml:"light_schedule"`
}

func (g *Garden) GetVersion() uint {
Expand Down Expand Up @@ -63,6 +69,14 @@ func (g *Garden) GetNotificationClientID() string {
return *g.NotificationClientID
}

func (g *Garden) GetNotificationSettings() NotificationSettings {
if g.NotificationSettings == nil {
return NotificationSettings{}
}

return *g.NotificationSettings
}

// GardenHealth holds information about the Garden controller's health status
type GardenHealth struct {
Status HealthStatus `json:"status,omitempty"`
Expand Down Expand Up @@ -149,6 +163,7 @@ func (g *Garden) Patch(newGarden *Garden) *babyapi.ErrResponse {
if newGarden.NotificationClientID != nil {
g.NotificationClientID = newGarden.NotificationClientID
}

if newGarden.ControllerConfig != nil {
if g.ControllerConfig == nil {
g.ControllerConfig = &ControllerConfig{}
Expand All @@ -159,6 +174,14 @@ func (g *Garden) Patch(newGarden *Garden) *babyapi.ErrResponse {
}
}

if newGarden.NotificationSettings != nil {
if g.NotificationSettings == nil {
g.NotificationSettings = &NotificationSettings{}
}
g.NotificationSettings.ControllerStartup = newGarden.NotificationSettings.ControllerStartup
g.NotificationSettings.LightSchedule = newGarden.NotificationSettings.LightSchedule
}

return nil
}

Expand Down
7 changes: 7 additions & 0 deletions garden-app/pkg/garden_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -145,6 +145,13 @@ func TestGardenPatch(t *testing.T) {
TemperatureHumidityPin: pointer(uint(1)),
}},
},
{
"PatchNotificationSettings",
&Garden{NotificationSettings: &NotificationSettings{
ControllerStartup: true,
LightSchedule: true,
}},
},
}

for _, tt := range tests {
Expand Down
4 changes: 4 additions & 0 deletions garden-app/pkg/storage/migrate/migrate.go
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,10 @@ func migrateToFinalVersion[From, To Versioned](migrations []Migration, from From
return *new(To), err
}

if next.GetVersion() < uint(len(migrations)) {
continue
}

result, ok := next.(To)
if ok {
return result, nil
Expand Down
9 changes: 9 additions & 0 deletions garden-app/pkg/storage/migrations.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,15 @@ var (
migrate.NewMigration("InitializeVersion1", func(g *pkg.Garden) (*pkg.Garden, error) {
return g, nil
}),
migrate.NewMigration("EnableNotificationsIfClientIsSet", func(g *pkg.Garden) (*pkg.Garden, error) {
if g.NotificationClientID != nil {
g.NotificationSettings = &pkg.NotificationSettings{
ControllerStartup: true,
LightSchedule: true,
}
}
return g, nil
}),
}

waterScheduleMigrations = []migrate.Migration{
Expand Down
18 changes: 15 additions & 3 deletions garden-app/pkg/storage/migrations_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -56,8 +56,9 @@ func TestMigrations(t *testing.T) {
Name: "Garden3",
},
{
ID: babyapi.NewID(),
Name: "Garden4",
ID: babyapi.NewID(),
Name: "GardenWithNotificationClient",
NotificationClientID: pointer("client_id"),
},
}

Expand Down Expand Up @@ -110,7 +111,14 @@ func TestMigrations(t *testing.T) {
allGardens, err := client.Gardens.GetAll(context.Background(), nil)
require.NoError(t, err)
for _, g := range allGardens {
require.Equal(t, uint(1), g.GetVersion())
require.Equal(t, uint(2), g.GetVersion())

if g.Name == "GardenWithNotificationClient" {
t.Run("GardenWithNotificationClientHasSettingsTrue_Migration2", func(t *testing.T) {
require.True(t, g.GetNotificationSettings().ControllerStartup)
require.True(t, g.GetNotificationSettings().LightSchedule)
})
}
}
})

Expand All @@ -122,3 +130,7 @@ func TestMigrations(t *testing.T) {
}
})
}

func pointer[T any](v T) *T {
return &v
}
29 changes: 29 additions & 0 deletions garden-app/server/templates/garden_modal.html
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,35 @@ <h3 class="uk-modal-title">{{ if .Name }}{{ .Name }}{{ else }}Create Garden{{ en
<option value="{{ $nc.GetID }}" {{ if $selected }}selected{{ end }}>{{ $nc.Name }}</option>
{{ end }}
</select>

<div id="zone-water-schedules" class="uk-margin uk-child-width-auto uk-grid">
<div class="uk-width-1-2@m">
<label>
<div class="uk-inline">
<input class="uk-checkbox" type="checkbox" name="NotificationSettings.ControllerStartup"
value="true" {{ if and .NotificationSettings .NotificationSettings.ControllerStartup }}checked{{ end }}>
Controller startup
<span class="uk-margin-small-right" uk-icon="icon: info; ratio: 0.75"></span>
<div uk-dropdown="pos: right-center">
Enable notifications when the controller starts up and connects
</div>
</div>
</label>
</div>
<div class="uk-width-1-2@m">
<label>
<div class="uk-inline">
<input class="uk-checkbox" type="checkbox" name="NotificationSettings.LightSchedule"
value="true" {{ if and .NotificationSettings .NotificationSettings.LightSchedule }}checked{{ end }}>
Light schedule
<span class="uk-margin-small-right" uk-icon="icon: info; ratio: 0.75"></span>
<div uk-dropdown="pos: right-center">
Enable notifications when the Garden's light is turned on or off by the schedule
</div>
</div>
</label>
</div>
</div>
</div>

{{ if .MaxZones }}
Expand Down
Loading

0 comments on commit 1544831

Please sign in to comment.