Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 1 addition & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,7 @@ Cachet 3.x is currently in development and is not yet completely ready for produ
- [x] Incident Management
- [x] Incident Updates
- [x] Scheduled Maintenance
- [ ] Scheduled Maintenance Updates
- WIP - https://github.com/cachethq/core/pull/109
- [x] Scheduled Maintenance Updates
- [x] Components
- [ ] Metrics
- API and dashboard are working.
Expand Down
33 changes: 0 additions & 33 deletions database/factories/IncidentUpdateFactory.php

This file was deleted.

61 changes: 61 additions & 0 deletions database/factories/UpdateFactory.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
<?php

namespace Cachet\Database\Factories;

use Cachet\Enums\ComponentStatusEnum;
use Cachet\Enums\IncidentStatusEnum;
use Cachet\Models\Component;
use Cachet\Models\Incident;
use Cachet\Models\Schedule;
use Cachet\Models\Update;
use Illuminate\Database\Eloquent\Factories\Factory;
use Illuminate\Database\Eloquent\Relations\Relation;

/**
* @extends Factory<Update>
*/
class UpdateFactory extends Factory
{
protected $model = Update::class;

/**
* Define the model's default state.
*
* @return array<string, mixed>
*/
public function definition(): array
{
return [
'updateable_id' => Incident::factory(),
'updateable_type' => Relation::getMorphAlias(Incident::class),
'status' => IncidentStatusEnum::identified->value,
'message' => fake()->paragraph,
'user_id' => 1,
];
}

/**
* Create an update for an incident.
*/
public function forIncident(?Incident $incident = null): self
{
return $this->state([
'updateable_id' => $component->id ?? Incident::factory(),
'updateable_type' => Relation::getMorphAlias(Incident::class),
'status' => IncidentStatusEnum::identified->value,
]);
}

/**
* Create an update for a schedule.
*/
public function forSchedule(?Schedule $schedule = null): self
{
return $this->state([
'updateable_id' => $schedule->id ?? Schedule::factory(),
'updateable_type' => Relation::getMorphAlias(Schedule::class),
'status' => null,
'user_id' => null,
]);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
<?php

use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;

return new class extends Migration
{
/**
* Run the migrations.
*/
public function up(): void
{
Schema::table('incident_updates', function (Blueprint $table) {
$table->morphs('updateable');
$table->unsignedTinyInteger('status')->nullable()->change();
});
}
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
<?php

use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;

return new class extends Migration
{
/**
* Run the migrations.
*/
public function up(): void
{
DB::table('incident_updates')
->update([
'updateable_type' => 'incident',
'updateable_id' => DB::raw('incident_id')
]);
}
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
<?php

use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;

return new class extends Migration
{
/**
* Run the migrations.
*/
public function up(): void
{
Schema::table('incident_updates', function (Blueprint $table) {
$table->dropIndex('incident_updates_incident_id_index');
$table->dropColumn('incident_id');
});
}
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
<?php

use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;

return new class extends Migration
{
/**
* Run the migrations.
*/
public function up(): void
{
Schema::rename('incident_updates', 'updates');
}
};
33 changes: 26 additions & 7 deletions database/seeders/DatabaseSeeder.php
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
use Cachet\Models\IncidentTemplate;
use Cachet\Models\Metric;
use Cachet\Models\Schedule;
use Cachet\Models\Update;
use Cachet\Settings\AppSettings;
use Cachet\Settings\CustomizationSettings;
use Cachet\Settings\ThemeSettings;
Expand All @@ -32,12 +33,12 @@ public function run(): void
{
DB::table('users')->truncate();
DB::table('incidents')->truncate();
DB::table('incident_updates')->truncate();
DB::table('components')->truncate();
DB::table('component_groups')->truncate();
DB::table('schedules')->truncate();
DB::table('metrics')->truncate();
DB::table('metric_points')->truncate();
DB::table('updates')->truncate();

/** @var \Illuminate\Foundation\Auth\User $userModel */
$userModel = config('cachet.user_model');
Expand All @@ -56,12 +57,24 @@ public function run(): void
'completed_at' => now()->subHours(12),
]);

Schedule::create([
tap(Schedule::create([
'name' => 'Documentation Maintenance',
'message' => 'We will be conducting maintenance on our documentation servers. You may experience degraded performance during this time.',
'scheduled_at' => now()->addHours(24),
'completed_at' => null,
]);
]), function (Schedule $schedule) use ($user) {
$update = new Update([
'message' => <<<'EOF'
This scheduled maintenance period has been pushed back by one hour.
EOF
,
'user_id' => $user->id,
'created_at' => $timestamp = $schedule->created_at->addMinutes(45),
'updated_at' => $timestamp,
]);

$schedule->updates()->save($update);
});

$componentGroup = ComponentGroup::create([
'name' => 'Cachet',
Expand Down Expand Up @@ -122,15 +135,17 @@ public function run(): void
'updated_at' => $timestamp,
'occurred_at' => $timestamp,
]), function (Incident $incident) use ($user) {
$incident->incidentUpdates()->create([
$update = new Update([
'status' => IncidentStatusEnum::identified,
'message' => 'We\'ve confirmed the issue is with our DNS provider. We\'re waiting on them to provide an ETA.',
'user_id' => $user->id,
'created_at' => $timestamp = $incident->created_at->addMinutes(30),
'updated_at' => $timestamp,
]);

$incident->incidentUpdates()->create([
$incident->updates()->save($update);

$update = new Update([
'status' => IncidentStatusEnum::fixed,
'message' => <<<'EOF'
Our DNS provider has fixed the issue. We will continue to monitor the situation.
Expand All @@ -142,6 +157,8 @@ public function run(): void
'created_at' => $timestamp = $incident->created_at->addMinutes(45),
'updated_at' => $timestamp,
]);

$incident->updates()->save($update);
});

$incident = Incident::create([
Expand All @@ -155,20 +172,22 @@ public function run(): void
'occurred_at' => $timestamp,
]);

$incident->incidentUpdates()->create([
$update = new Update([
'status' => IncidentStatusEnum::identified,
'message' => 'We\'ve identified the issue and are working on a fix.',
'created_at' => $timestamp = $incident->created_at->addMinutes(15),
'updated_at' => $timestamp,
]);

$incident->incidentUpdates()->create([
$incident->updates()->create([
'status' => IncidentStatusEnum::fixed,
'message' => 'The documentation is now back online. Happy reading!',
'created_at' => $timestamp = $incident->created_at->addMinutes(25),
'updated_at' => $timestamp,
]);

$incident->updates()->save($update);

IncidentTemplate::create([
'name' => 'Third-Party Service Outage',
'slug' => 'third-party-service-outage',
Expand Down
18 changes: 0 additions & 18 deletions public/build/assets/cachet-DCZQ8JcZ.js

This file was deleted.

1 change: 1 addition & 0 deletions public/build/assets/cachet.574fadd6.css

Large diffs are not rendered by default.

18 changes: 18 additions & 0 deletions public/build/assets/cachet.6122e927.js

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions public/build/assets/theme.8251fad4.css

Large diffs are not rendered by default.

15 changes: 7 additions & 8 deletions public/build/manifest.json
Original file line number Diff line number Diff line change
@@ -1,18 +1,17 @@
{
"resources/css/cachet.css": {
"file": "assets/cachet-BYgZ_nP6.css",
"src": "resources/css/cachet.css",
"resources/js/cachet.js": {
"file": "assets/cachet.6122e927.js",
"src": "resources/js/cachet.js",
"isEntry": true
},
"resources/css/dashboard/theme.css": {
"file": "assets/theme-C6ZKRDAs.css",
"file": "assets/theme.8251fad4.css",
"src": "resources/css/dashboard/theme.css",
"isEntry": true
},
"resources/js/cachet.js": {
"file": "assets/cachet-DCZQ8JcZ.js",
"name": "cachet",
"src": "resources/js/cachet.js",
"resources/css/cachet.css": {
"file": "assets/cachet.574fadd6.css",
"src": "resources/css/cachet.css",
"isEntry": true
}
}
1 change: 1 addition & 0 deletions resources/lang/en.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
{
":count Incident": ":count Incident|:count Incidents",
"+:count Update": "+:count Update|+:count Updates",
":name RSS Feed": ":name RSS Feed",
"Admin": "Admin",
"Always Hidden": "Always Hidden",
Expand Down
8 changes: 4 additions & 4 deletions resources/views/components/incident.blade.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,8 @@
<div x-data="{ timestamp: new Date(@js($incident->timestamp)) }" class="bg-white border divide-y rounded-lg ml-9 dark:divide-zinc-700 dark:border-zinc-700 dark:bg-zinc-800">
<div @class([
'flex flex-col bg-zinc-50 p-4 dark:bg-zinc-900 gap-2',
'rounded-t-lg' => $incident->incidentUpdates->isNotEmpty(),
'rounded-lg' => $incident->incidentUpdates->isEmpty(),
'rounded-t-lg' => $incident->updates->isNotEmpty(),
'rounded-lg' => $incident->updates->isEmpty(),
])>
@if ($incident->components()->exists())
<div class="text-xs font-medium">
Expand All @@ -35,7 +35,7 @@
</span>
</div>
<div class="flex justify-start sm:justify-end">
<x-cachet::badge :status="$incident->status" />
<x-cachet::badge :status="$incident->latestStatus" />
</div>
</div>
</div>
Expand All @@ -47,7 +47,7 @@
<div class="absolute inset-x-0 bottom-0 w-full h-24 bg-gradient-to-b from-transparent to-zinc-50 dark:from-transparent dark:to-zinc-900"></div>
</div>
<div class="flex flex-col px-4 divide-y dark:divide-zinc-700">
@foreach ($incident->incidentUpdates as $update)
@foreach ($incident->updates as $update)
<div class="relative py-4" x-data="{ timestamp: new Date(@js($update->created_at)) }">
<x-cachet::incident-update-status :status="$update->status" />
<h3 class="text-lg font-semibold">{{ $update->status->getLabel() }}</h3>
Expand Down
28 changes: 22 additions & 6 deletions resources/views/components/schedule.blade.php
Original file line number Diff line number Diff line change
@@ -1,23 +1,39 @@
<li class="p-4" x-data="{ timestamp: new Date(@js($schedule->scheduled_at)) }">
<div class="flex flex-col-reverse items-start justify-between gap-4 md:flex-row md:items-center">
<div class="flex items-start gap-2.5 w-full">
<span class="mt-1.5 h-3 w-3 shrink-0 rounded-full bg-orange-200 animate-pulse"></span>
<div class="flex-1">
<div class="flex flex-col sm:flex-row justify-between gap-2 flex-col-reverse items-start sm:items-center">
<div class="flex flex-col flex-1">
<h3 class="max-w-full text-base font-semibold break-words sm:text-xl">
{{ $schedule->name}}
</h3>
<div class="flex items-center gap-x-1">
<h3 class="max-w-full text-base font-semibold break-words sm:text-xl">
{{ $schedule->name }}
</h3>
</div>
<span class="text-xs text-zinc-500 dark:text-zinc-400">
{{ $schedule->scheduled_at->diffForHumans() }} — <time datetime="{{ $schedule->scheduled_at->toW3cString() }}" x-text="timestamp.toLocaleString()"></time>
</span>
{{ $schedule->scheduled_at->diffForHumans() }} — <time datetime="{{ $schedule->scheduled_at->toW3cString() }}" x-text="timestamp.toLocaleString()"></time>
</span>
</div>

<div class="flex justify-start sm:justify-end">
<x-cachet::badge :status="$schedule->status" />
</div>
</div>

<div class="prose-sm md:prose prose-zinc dark:prose-invert prose-a:text-primary-500 prose-a:underline prose-p:leading-normal">{!! $schedule->formattedMessage() !!}</div>
</div>
</div>
</div>

<div class="relative">
<div class="flex flex-col divide-y dark:divide-zinc-700">
@foreach ($schedule->updates as $update)
<div class="relative py-4" x-data="{ timestamp: new Date(@js($update->created_at)) }">
<span class="text-xs text-zinc-500 dark:text-zinc-400">
{{ $update->created_at->diffForHumans() }} — <time datetime="{{ $update->created_at->toW3cString() }}" x-text="timestamp.toLocaleString()"></time>
</span>
<div class="prose-sm md:prose prose-zinc dark:prose-invert prose-a:text-primary-500 prose-a:underline prose-p:leading-normal">{!! $update->formattedMessage() !!}</div>
</div>
@endforeach
</div>
</div>
</li>
Loading