Skip to content

Commit e98851b

Browse files
authored
Incident templates (#36)
1 parent 117f921 commit e98851b

22 files changed

+532
-20
lines changed

database/factories/IncidentTemplateFactory.php

Lines changed: 31 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,10 @@
22

33
namespace Cachet\Database\Factories;
44

5+
use Cachet\Enums\IncidentTemplateEngineEnum;
56
use Cachet\Models\IncidentTemplate;
67
use Illuminate\Database\Eloquent\Factories\Factory;
8+
use Illuminate\Support\Str;
79

810
/**
911
* @extends \Illuminate\Database\Eloquent\Factories\Factory<\Cachet\Models\IncidentTemplate>
@@ -20,16 +22,40 @@ class IncidentTemplateFactory extends Factory
2022
public function definition(): array
2123
{
2224
return [
23-
'name' => fake()->sentence,
24-
'slug' => fake()->slug,
25+
'name' => $name = fake()->words(2, true),
26+
'slug' => Str::slug($name),
27+
'engine' => IncidentTemplateEngineEnum::twig,
28+
'template' => 'This is an incident template.',
29+
];
30+
}
31+
32+
public function blade(): self
33+
{
34+
return $this->state([
35+
'engine' => IncidentTemplateEngineEnum::blade,
2536
'template' => <<<'EOT'
2637
Hey,
2738
2839
A new incident has been reported:
2940
30-
Name: {{ incident_name }}
31-
{{ incident_description }}
41+
Name: {{ $incident['name'] }}
42+
{{ $incident['message'] }}
3243
EOT,
33-
];
44+
]);
45+
}
46+
47+
public function twig(): self
48+
{
49+
return $this->state([
50+
'engine' => IncidentTemplateEngineEnum::twig,
51+
'template' => <<<'EOT'
52+
Hey,
53+
54+
A new incident has been reported:
55+
56+
Name: {{ incident.name }}
57+
{{ incident.message }}
58+
EOT,
59+
]);
3460
}
3561
}
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
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+
public function up(): void
13+
{
14+
Schema::table('incident_templates', function (Blueprint $table) {
15+
$table->char('engine')->default('twig')->after('template');
16+
});
17+
}
18+
};

routes/api.php

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
use Cachet\Http\Controllers\Api\ComponentGroupController;
55
use Cachet\Http\Controllers\Api\GeneralController;
66
use Cachet\Http\Controllers\Api\IncidentController;
7+
use Cachet\Http\Controllers\Api\IncidentTemplateController;
78
use Cachet\Http\Controllers\Api\IncidentUpdateController;
89
use Cachet\Http\Controllers\Api\MetricController;
910
use Cachet\Http\Controllers\Api\MetricPointController;
@@ -14,6 +15,7 @@
1415
'components' => ComponentController::class,
1516
'component-groups' => ComponentGroupController::class,
1617
'incidents' => IncidentController::class,
18+
'incident-templates' => IncidentTemplateController::class,
1719
'metrics' => MetricController::class,
1820
'schedules' => ScheduleController::class,
1921
]);

src/Actions/Incident/CreateIncident.php

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,16 +2,46 @@
22

33
namespace Cachet\Actions\Incident;
44

5+
use Cachet\Models\Component;
56
use Cachet\Models\Incident;
7+
use Cachet\Models\IncidentTemplate;
8+
use Illuminate\Support\Carbon;
69
use Illuminate\Support\Str;
710

811
class CreateIncident
912
{
1013
public function handle(array $incident): Incident
1114
{
15+
if (isset($incident['template'])) {
16+
$template = IncidentTemplate::where('slug', $incident['template'])->first();
17+
$incident['message'] = $this->parseTemplate($template, $incident);
18+
}
19+
1220
return Incident::create(array_merge(
1321
['guid' => Str::uuid()],
1422
$incident
1523
));
1624
}
25+
26+
/**
27+
* Render the incident template with the given data.
28+
*/
29+
private function parseTemplate(IncidentTemplate $template, array $data): string
30+
{
31+
$vars = array_merge($data['template_vars'], [
32+
'incident' => [
33+
'name' => $data['name'],
34+
'status' => $data['status'],
35+
'message' => $data['message'] ?? null,
36+
'visible' => $data['visible'] ?? false,
37+
'notify' => $data['notifications'] ?? false,
38+
'stickied' => $data['stickied'] ?? false,
39+
'occurred_at' => $data['occurred_at'] ?? Carbon::now(),
40+
'component' => isset($data['component_id']) ? Component::find($data['component_id']) : null,
41+
'component_status' => $data['component_status'] ?? null,
42+
],
43+
]);
44+
45+
return $template->render($vars);
46+
}
1747
}

src/Actions/IncidentTemplate/CreateIncidentTemplate.php

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,16 @@
33
namespace Cachet\Actions\IncidentTemplate;
44

55
use Cachet\Models\IncidentTemplate;
6+
use Illuminate\Support\Str;
67

78
class CreateIncidentTemplate
89
{
9-
public function handle(): IncidentTemplate
10+
public function handle(array $template): IncidentTemplate
1011
{
11-
//
12+
$data = array_merge([
13+
'slug' => Str::slug($template['name']),
14+
], $template);
15+
16+
return IncidentTemplate::create($data);
1217
}
1318
}

src/Actions/IncidentTemplate/UpdateIncidentTemplate.php

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,10 @@
66

77
class UpdateIncidentTemplate
88
{
9-
public function handle(IncidentTemplate $incidentTemplate): IncidentTemplate
9+
public function handle(IncidentTemplate $incidentTemplate, array $data): IncidentTemplate
1010
{
11-
//
11+
$incidentTemplate->update($data);
12+
13+
return $incidentTemplate->fresh();
1214
}
1315
}
Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
<?php
2+
3+
namespace Cachet\Http\Controllers\Api;
4+
5+
use Cachet\Actions\IncidentTemplate\CreateIncidentTemplate;
6+
use Cachet\Actions\IncidentTemplate\DeleteIncidentTemplate;
7+
use Cachet\Actions\IncidentTemplate\UpdateIncidentTemplate;
8+
use Cachet\Http\Requests\CreateIncidentTemplateRequest;
9+
use Cachet\Http\Requests\UpdateIncidentTemplateRequest;
10+
use Cachet\Http\Resources\IncidentTemplate as IncidentTemplateResource;
11+
use Cachet\Models\IncidentTemplate;
12+
use Illuminate\Http\Response;
13+
use Illuminate\Routing\Controller;
14+
use Spatie\QueryBuilder\QueryBuilder;
15+
16+
class IncidentTemplateController extends Controller
17+
{
18+
/**
19+
* List Incident Templates.
20+
*/
21+
public function index()
22+
{
23+
$templates = QueryBuilder::for(IncidentTemplate::class)
24+
->allowedFilters(['name', 'slug'])
25+
->allowedSorts(['name', 'slug', 'id'])
26+
->simplePaginate(request('per_page', 15));
27+
28+
return IncidentTemplateResource::collection($templates);
29+
}
30+
31+
/**
32+
* Create Incident Template.
33+
*/
34+
public function store(CreateIncidentTemplateRequest $request)
35+
{
36+
$template = app(CreateIncidentTemplate::class)->handle($request->validated());
37+
38+
return IncidentTemplateResource::make($template);
39+
}
40+
41+
/**
42+
* Get Incident Template.
43+
*/
44+
public function show(IncidentTemplate $incidentTemplate)
45+
{
46+
return IncidentTemplateResource::make($incidentTemplate)
47+
->response()
48+
->setStatusCode(Response::HTTP_OK);
49+
}
50+
51+
/**
52+
* Update Incident Template.
53+
*/
54+
public function update(UpdateIncidentTemplateRequest $request, IncidentTemplate $incidentTemplate)
55+
{
56+
app(UpdateIncidentTemplate::class)->handle($incidentTemplate, $request->validated());
57+
58+
return IncidentTemplateResource::make($incidentTemplate->fresh());
59+
}
60+
61+
/**
62+
* Delete Incident Template.
63+
*/
64+
public function destroy(IncidentTemplate $incidentTemplate)
65+
{
66+
app(DeleteIncidentTemplate::class)->handle($incidentTemplate);
67+
68+
return response()->noContent();
69+
}
70+
}

src/Http/Requests/CreateIncidentRequest.php

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
namespace Cachet\Http\Requests;
44

5+
use Cachet\Enums\ComponentStatusEnum;
56
use Cachet\Enums\IncidentStatusEnum;
67
use Illuminate\Foundation\Http\FormRequest;
78
use Illuminate\Validation\Rule;
@@ -25,12 +26,30 @@ public function rules(): array
2526
{
2627
return [
2728
'name' => ['required', 'string', 'max:255'],
28-
'message' => ['required', 'string'],
29+
'message' => ['required_without:template', 'string'],
30+
'template' => ['required_without:message', 'string'],
2931
'status' => ['required', Rule::enum(IncidentStatusEnum::class)],
3032
'visible' => ['boolean'],
3133
'stickied' => ['boolean'],
3234
'notifications' => ['boolean'],
3335
'occurred_at' => ['nullable', 'string'],
36+
'template_vars' => ['array'],
37+
'component_id' => [Rule::exists('components', 'id')],
38+
'component_status' => ['nullable', Rule::enum(ComponentStatusEnum::class), 'required_with:component_id'],
3439
];
3540
}
41+
42+
/**
43+
* Get data to be validated from the request.
44+
*/
45+
public function validationData(): array
46+
{
47+
return array_merge(parent::validationData(), [
48+
'template_vars' => $this->input('template_vars', []),
49+
'visible' => $this->boolean('visible'),
50+
'notifications' => $this->boolean('notifications'),
51+
'stickied' => $this->boolean('stickied'),
52+
'component_status' => $this->enum('component_status', ComponentStatusEnum::class),
53+
]);
54+
}
3655
}

src/Http/Requests/CreateIncidentTemplateRequest.php

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

33
namespace Cachet\Http\Requests;
44

5+
use Cachet\Enums\IncidentTemplateEngineEnum;
56
use Illuminate\Foundation\Http\FormRequest;
7+
use Illuminate\Validation\Rule;
68

79
class CreateIncidentTemplateRequest extends FormRequest
810
{
@@ -11,7 +13,7 @@ class CreateIncidentTemplateRequest extends FormRequest
1113
*/
1214
public function authorize(): bool
1315
{
14-
return false;
16+
return true;
1517
}
1618

1719
/**
@@ -22,7 +24,10 @@ public function authorize(): bool
2224
public function rules(): array
2325
{
2426
return [
25-
//
27+
'name' => ['required', 'string', 'max:255'],
28+
'slug' => ['string'],
29+
'template' => ['required', 'string'],
30+
'engine' => [Rule::enum(IncidentTemplateEngineEnum::class)],
2631
];
2732
}
2833
}

src/Http/Requests/UpdateIncidentTemplateRequest.php

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

33
namespace Cachet\Http\Requests;
44

5+
use Cachet\Enums\IncidentTemplateEngineEnum;
56
use Illuminate\Foundation\Http\FormRequest;
7+
use Illuminate\Validation\Rule;
68

79
class UpdateIncidentTemplateRequest extends FormRequest
810
{
@@ -11,7 +13,7 @@ class UpdateIncidentTemplateRequest extends FormRequest
1113
*/
1214
public function authorize(): bool
1315
{
14-
return false;
16+
return true;
1517
}
1618

1719
/**
@@ -22,7 +24,10 @@ public function authorize(): bool
2224
public function rules(): array
2325
{
2426
return [
25-
//
27+
'name' => ['string', 'max:255'],
28+
'slug' => ['string'],
29+
'template' => ['string'],
30+
'engine' => [Rule::enum(IncidentTemplateEngineEnum::class)],
2631
];
2732
}
2833
}

0 commit comments

Comments
 (0)