Skip to content

Commit 53964c5

Browse files
swogajbrooksuk
andauthored
feat: Time-controlled status for Planned Maintenances / Schedules (#119)
Co-authored-by: swoga <[email protected]> Co-authored-by: James Brooks <[email protected]>
1 parent 9b9a186 commit 53964c5

File tree

11 files changed

+107
-130
lines changed

11 files changed

+107
-130
lines changed

database/factories/ScheduleFactory.php

Lines changed: 2 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@
22

33
namespace Cachet\Database\Factories;
44

5-
use Cachet\Enums\ScheduleStatusEnum;
65
use Cachet\Models\Schedule;
76
use Illuminate\Database\Eloquent\Factories\Factory;
87

@@ -22,24 +21,22 @@ public function definition(): array
2221
{
2322
return [
2423
'name' => 'Incident Schedule',
25-
'status' => ScheduleStatusEnum::upcoming,
2624
'scheduled_at' => now()->addDays(7),
27-
'completed_at' => null,
25+
'completed_at' => now()->addDays(14),
2826
];
2927
}
3028

3129
public function completed(): self
3230
{
3331
return $this->state([
34-
'status' => ScheduleStatusEnum::complete,
32+
'scheduled_at' => now()->subMinutes(45),
3533
'completed_at' => now()->subMinutes(30),
3634
]);
3735
}
3836

3937
public function inProgress(): self
4038
{
4139
return $this->state([
42-
'status' => ScheduleStatusEnum::in_progress,
4340
'scheduled_at' => now()->subMinutes(30),
4441
'completed_at' => null,
4542
]);
@@ -48,7 +45,6 @@ public function inProgress(): self
4845
public function inTheFuture(): self
4946
{
5047
return $this->state([
51-
'status' => ScheduleStatusEnum::upcoming->value,
5248
'scheduled_at' => now()->addDays(30),
5349
'completed_at' => null,
5450
]);
@@ -57,17 +53,7 @@ public function inTheFuture(): self
5753
public function inThePast(): self
5854
{
5955
return $this->state([
60-
'status' => ScheduleStatusEnum::upcoming,
6156
'scheduled_at' => now()->subDays(30)->subHours(2),
62-
'completed_at' => null,
63-
]);
64-
}
65-
66-
public function completedInThePast(): self
67-
{
68-
return $this->state([
69-
'status' => ScheduleStatusEnum::complete,
70-
'scheduled_at' => now()->addDays(30)->subHours(2),
7157
'completed_at' => now()->subDays(30),
7258
]);
7359
}
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
<?php
2+
3+
use Illuminate\Database\Migrations\Migration;
4+
use Illuminate\Database\Schema\Blueprint;
5+
use Illuminate\Support\Facades\Schema;
6+
7+
return new class extends Migration
8+
{
9+
/**
10+
* Run the migrations.
11+
*
12+
* @return void
13+
*/
14+
public function up()
15+
{
16+
Schema::table('schedules', function (Blueprint $table) {
17+
$table->dropColumn('status');
18+
});
19+
}
20+
21+
/**
22+
* Reverse the migrations.
23+
*
24+
* @return void
25+
*/
26+
public function down()
27+
{
28+
Schema::table('incidents', function (Blueprint $table) {
29+
$table->tinyInteger('status')->unsigned()->default(0);
30+
});
31+
}
32+
};

database/seeders/DatabaseSeeder.php

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -50,11 +50,18 @@ public function run(): void
5050
'email_verified_at' => now(),
5151
]);
5252

53+
Schedule::create([
54+
'name' => 'Documentation Maintenance',
55+
'message' => 'We will be conducting maintenance on our documentation servers. Documentation may not be available during this time.',
56+
'scheduled_at' => now()->subHours(12)->subMinutes(45),
57+
'completed_at' => now()->subHours(12),
58+
]);
59+
5360
Schedule::create([
5461
'name' => 'Database Maintenance',
5562
'message' => 'We will be conducting maintenance on our database servers. You may experience degraded performance during this time.',
56-
'scheduled_at' => now()->addHours(6),
57-
'status' => ScheduleStatusEnum::upcoming,
63+
'scheduled_at' => now()->addHours(24),
64+
'completed_at' => null,
5865
]);
5966

6067
$componentGroup = ComponentGroup::create([

src/Filament/Resources/ScheduleResource.php

Lines changed: 2 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -25,17 +25,6 @@ public static function form(Form $form): Form
2525
Forms\Components\TextInput::make('name')
2626
->label(__('Name'))
2727
->required(),
28-
Forms\Components\Select::make('status')
29-
->label(__('Status'))
30-
->required()
31-
->options(ScheduleStatusEnum::class)
32-
->default(ScheduleStatusEnum::upcoming)
33-
->afterStateUpdated(function (Forms\Set $set, int|ScheduleStatusEnum $state): void {
34-
if (ScheduleStatusEnum::parse($state) !== ScheduleStatusEnum::complete) {
35-
$set('completed_at', null);
36-
}
37-
})
38-
->live(),
3928
Forms\Components\MarkdownEditor::make('message')
4029
->label(__('Message'))
4130
->columnSpanFull(),
@@ -45,9 +34,7 @@ public static function form(Form $form): Form
4534
->label(__('Scheduled at'))
4635
->required(),
4736
Forms\Components\DateTimePicker::make('completed_at')
48-
->label(__('Completed at'))
49-
->visible(fn (Forms\Get $get): bool => ScheduleStatusEnum::parse($get('status')) === ScheduleStatusEnum::complete)
50-
->required(fn (Forms\Get $get): bool => ScheduleStatusEnum::parse($get('status')) === ScheduleStatusEnum::complete),
37+
->label(__('Completed at')),
5138
])->columnSpan(1),
5239
])->columns(4);
5340
}
@@ -99,7 +86,7 @@ public static function table(Table $table): Table
9986
->required(),
10087
])
10188
->color('success')
102-
->action(fn (Schedule $record, array $data) => $record->update(['completed_at' => $data['completed_at'], 'status' => ScheduleStatusEnum::complete])),
89+
->action(fn (Schedule $record, array $data) => $record->update(['completed_at' => $data['completed_at']])),
10390
Tables\Actions\EditAction::make(),
10491
])
10592
->bulkActions([

src/Http/Controllers/Api/ScheduleController.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,8 +22,8 @@ public function index()
2222
{
2323
$schedules = QueryBuilder::for(Schedule::class)
2424
->allowedIncludes(['components'])
25-
->allowedFilters(['name', 'status'])
26-
->allowedSorts(['name', 'status', 'id', 'scheduled_at', 'completed_at'])
25+
->allowedFilters(['name'])
26+
->allowedSorts(['name', 'id', 'scheduled_at', 'completed_at'])
2727
->simplePaginate(request('per_page', 15));
2828

2929
return ScheduleResource::collection($schedules);

src/Http/Controllers/StatusPage/StatusPageController.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ public function index(): View
3030
->withCount('incidents')
3131
->get(),
3232

33-
'schedules' => Schedule::query()->inTheFuture()->orderBy('scheduled_at')->get(),
33+
'schedules' => Schedule::query()->incomplete()->orderBy('scheduled_at')->get(),
3434
]);
3535
}
3636

src/Http/Resources/Schedule.php

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,10 @@ public function toAttributes(Request $request): array
2121
'human' => optional($this->scheduled_at)->diffForHumans(),
2222
'string' => optional($this->scheduled_at)->toDateTimeString(),
2323
],
24+
'completed' => [
25+
'human' => optional($this->completed_at)->diffForHumans(),
26+
'string' => optional($this->completed_at)->toDateTimeString(),
27+
],
2428
'created' => [
2529
'human' => optional($this->created_at)->diffForHumans(),
2630
'string' => optional($this->created_at)->toDateTimeString(),

src/Models/Schedule.php

Lines changed: 25 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
use Cachet\Enums\ScheduleStatusEnum;
66
use Illuminate\Database\Eloquent\Builder;
7+
use Illuminate\Database\Eloquent\Casts\Attribute;
78
use Illuminate\Database\Eloquent\Factories\HasFactory;
89
use Illuminate\Database\Eloquent\Model;
910
use Illuminate\Database\Eloquent\Relations\BelongsToMany;
@@ -16,19 +17,33 @@ class Schedule extends Model
1617
use HasFactory, SoftDeletes;
1718

1819
protected $casts = [
19-
'status' => ScheduleStatusEnum::class,
2020
'scheduled_at' => 'datetime',
2121
'completed_at' => 'datetime',
2222
];
2323

2424
protected $fillable = [
2525
'name',
2626
'message',
27-
'status',
2827
'scheduled_at',
2928
'completed_at',
3029
];
3130

31+
/**
32+
* Get the status of the schedule.
33+
*/
34+
public function status(): Attribute
35+
{
36+
return Attribute::get(function () {
37+
$now = Carbon::now();
38+
39+
return match (true) {
40+
$this->scheduled_at->gte($now) => ScheduleStatusEnum::upcoming,
41+
$this->completed_at === null => ScheduleStatusEnum::in_progress,
42+
default => ScheduleStatusEnum::complete,
43+
};
44+
});
45+
}
46+
3247
/**
3348
* Get the components affected by this schedule.
3449
*/
@@ -53,7 +68,7 @@ public function formattedMessage(): string
5368
*/
5469
public function scopeIncomplete(Builder $query): Builder
5570
{
56-
return $query->whereIn('status', ScheduleStatusEnum::incomplete())
71+
return $query->whereDate('scheduled_at', '>=', Carbon::now())
5772
->whereNull('completed_at');
5873
}
5974

@@ -62,35 +77,26 @@ public function scopeIncomplete(Builder $query): Builder
6277
*/
6378
public function scopeInProgress(Builder $query): Builder
6479
{
65-
return $query->where('scheduled_at', '<=', Carbon::now())
66-
->where('status', '=', ScheduleStatusEnum::in_progress)
67-
->whereNull('completed_at');
80+
return $query->whereDate('scheduled_at', '<=', Carbon::now())
81+
->where(function (Builder $query) {
82+
$query->whereDate('completed_at', '>=', Carbon::now())
83+
->orWhereNull('completed_at');
84+
});
6885
}
6986

7087
/**
7188
* Scopes schedules to those in the future.
7289
*/
7390
public function scopeInTheFuture(Builder $query): Builder
7491
{
75-
return $query->whereIn('status', ScheduleStatusEnum::upcoming())
76-
->whereDate('scheduled_at', '>=', Carbon::now());
92+
return $query->whereDate('scheduled_at', '>=', Carbon::now());
7793
}
7894

7995
/**
8096
* Scopes schedules to those scheduled in the past.
8197
*/
8298
public function scopeInThePast(Builder $query): Builder
8399
{
84-
return $query->whereIn('status', ScheduleStatusEnum::upcoming())
85-
->where('scheduled_at', '<=', Carbon::now());
86-
}
87-
88-
/**
89-
* Scopes schedules to those completed in the past.
90-
*/
91-
public function scopeCompletedPreviously(Builder $query): Builder
92-
{
93-
return $query->where('status', '=', ScheduleStatusEnum::complete)
94-
->where('completed_at', '<=', Carbon::now());
100+
return $query->where('completed_at', '<=', Carbon::now());
95101
}
96102
}

0 commit comments

Comments
 (0)