From 1954cf26f34aa2472d4e1c1b87b180707aac0764 Mon Sep 17 00:00:00 2001 From: Antoine GIRARD Date: Wed, 17 Aug 2016 01:12:21 +0200 Subject: [PATCH] Add stickied incident --- .../Incident/ReportIncidentCommand.php | 12 +++++- .../Incident/UpdateIncidentCommand.php | 12 +++++- .../Incident/ReportIncidentCommandHandler.php | 7 ++-- .../ReportMaintenanceCommandHandler.php | 1 + .../Incident/UpdateIncidentCommandHandler.php | 1 + app/Composers/Modules/StickiedComposer.php | 41 +++++++++++++++++++ app/Console/Commands/DemoSeederCommand.php | 15 +++++++ .../Providers/ComposerServiceProvider.php | 2 + .../Providers/ModuleServiceProvider.php | 4 +- .../Controllers/Api/IncidentController.php | 2 + .../Dashboard/IncidentController.php | 2 + app/Models/Incident.php | 17 ++++++++ database/factories/ModelFactory.php | 9 ++-- ...0_AlterTableIncidentsAddStickiedColumn.php | 39 ++++++++++++++++++ resources/lang/en/cachet.php | 1 + resources/lang/en/forms.php | 3 ++ .../views/dashboard/incidents/add.blade.php | 7 ++++ .../views/dashboard/incidents/edit.blade.php | 7 ++++ .../views/partials/modules/stickied.blade.php | 8 ++++ tests/Api/IncidentTest.php | 11 +++-- .../Incident/ReportIncidentCommandTest.php | 2 + .../Incident/UpdateIncidentCommandTest.php | 2 + 22 files changed, 191 insertions(+), 14 deletions(-) create mode 100644 app/Composers/Modules/StickiedComposer.php create mode 100644 database/migrations/2016_09_04_100000_AlterTableIncidentsAddStickiedColumn.php create mode 100644 resources/views/partials/modules/stickied.blade.php diff --git a/app/Bus/Commands/Incident/ReportIncidentCommand.php b/app/Bus/Commands/Incident/ReportIncidentCommand.php index 4e1e972f94dc..67158bfc9aa1 100644 --- a/app/Bus/Commands/Incident/ReportIncidentCommand.php +++ b/app/Bus/Commands/Incident/ReportIncidentCommand.php @@ -62,6 +62,13 @@ final class ReportIncidentCommand */ public $notify; + /** + * Whether to stick the incident on top. + * + * @var bool + */ + public $stickied; + /** * The date at which the incident occurred. * @@ -96,6 +103,7 @@ final class ReportIncidentCommand 'component_id' => 'int|required_with:component_status', 'component_status' => 'int|min:1|max:4|required_with:component_id', 'notify' => 'bool', + 'stickied' => 'bool', 'incident_date' => 'string', 'template' => 'string', ]; @@ -110,13 +118,14 @@ final class ReportIncidentCommand * @param int $component_id * @param int $component_status * @param bool $notify + * @param bool $stickied * @param string|null $incident_date * @param string|null $template * @param array|null $template_vars * * @return void */ - public function __construct($name, $status, $message, $visible, $component_id, $component_status, $notify, $incident_date, $template, array $template_vars = null) + public function __construct($name, $status, $message, $visible, $component_id, $component_status, $notify, $stickied, $incident_date, $template, array $template_vars = null) { $this->name = $name; $this->status = $status; @@ -125,6 +134,7 @@ public function __construct($name, $status, $message, $visible, $component_id, $ $this->component_id = $component_id; $this->component_status = $component_status; $this->notify = $notify; + $this->stickied = $stickied; $this->incident_date = $incident_date; $this->template = $template; $this->template_vars = $template_vars; diff --git a/app/Bus/Commands/Incident/UpdateIncidentCommand.php b/app/Bus/Commands/Incident/UpdateIncidentCommand.php index 2d5f2c731919..928e037a1e44 100644 --- a/app/Bus/Commands/Incident/UpdateIncidentCommand.php +++ b/app/Bus/Commands/Incident/UpdateIncidentCommand.php @@ -71,6 +71,13 @@ final class UpdateIncidentCommand */ public $notify; + /** + * Whether to stick the incident on top. + * + * @var bool + */ + public $stickied; + /** * The date that the incident occurred on. * @@ -105,6 +112,7 @@ final class UpdateIncidentCommand 'component_id' => 'int', 'component_status' => 'int|min:1|max:4|required_with:component_id', 'notify' => 'bool', + 'stickied' => 'bool', 'template' => 'string', ]; @@ -119,13 +127,14 @@ final class UpdateIncidentCommand * @param int $component_id * @param int $component_status * @param bool $notify + * @param bool $stickied * @param string|null $incident_date * @param string|null $template * @param array|null $template_vars * * @return void */ - public function __construct(Incident $incident, $name, $status, $message, $visible, $component_id, $component_status, $notify, $incident_date, $template, array $template_vars = null) + public function __construct(Incident $incident, $name, $status, $message, $visible, $component_id, $component_status, $notify, $stickied, $incident_date, $template, array $template_vars = null) { $this->incident = $incident; $this->name = $name; @@ -135,6 +144,7 @@ public function __construct(Incident $incident, $name, $status, $message, $visib $this->component_id = $component_id; $this->component_status = $component_status; $this->notify = $notify; + $this->stickied = $stickied; $this->incident_date = $incident_date; $this->template = $template; $this->template_vars = $template_vars; diff --git a/app/Bus/Handlers/Commands/Incident/ReportIncidentCommandHandler.php b/app/Bus/Handlers/Commands/Incident/ReportIncidentCommandHandler.php index 6117074891e0..cae916339456 100644 --- a/app/Bus/Handlers/Commands/Incident/ReportIncidentCommandHandler.php +++ b/app/Bus/Handlers/Commands/Incident/ReportIncidentCommandHandler.php @@ -65,9 +65,10 @@ public function __construct(DateFactory $dates, Bridge $twig) public function handle(ReportIncidentCommand $command) { $data = [ - 'name' => $command->name, - 'status' => $command->status, - 'visible' => $command->visible, + 'name' => $command->name, + 'status' => $command->status, + 'visible' => $command->visible, + 'stickied' => $command->stickied, ]; if ($command->template) { diff --git a/app/Bus/Handlers/Commands/Incident/ReportMaintenanceCommandHandler.php b/app/Bus/Handlers/Commands/Incident/ReportMaintenanceCommandHandler.php index 4126909d0d3d..b63b767ac4f8 100644 --- a/app/Bus/Handlers/Commands/Incident/ReportMaintenanceCommandHandler.php +++ b/app/Bus/Handlers/Commands/Incident/ReportMaintenanceCommandHandler.php @@ -54,6 +54,7 @@ public function handle(ReportMaintenanceCommand $command) 'scheduled_at' => $scheduledAt, 'status' => 0, 'visible' => 1, + 'stickied' => false, ]); $maintenanceEvent->notify = (bool) $command->notify; diff --git a/app/Bus/Handlers/Commands/Incident/UpdateIncidentCommandHandler.php b/app/Bus/Handlers/Commands/Incident/UpdateIncidentCommandHandler.php index 53bc3f7f9a8e..8001cf6ae14d 100644 --- a/app/Bus/Handlers/Commands/Incident/UpdateIncidentCommandHandler.php +++ b/app/Bus/Handlers/Commands/Incident/UpdateIncidentCommandHandler.php @@ -107,6 +107,7 @@ protected function filter(UpdateIncidentCommand $command) 'status' => $command->status, 'message' => $command->message, 'visible' => $command->visible, + 'stickied' => $command->stickied, 'component_id' => $command->component_id, 'component_status' => $command->component_status, 'notify' => $command->notify, diff --git a/app/Composers/Modules/StickiedComposer.php b/app/Composers/Modules/StickiedComposer.php new file mode 100644 index 000000000000..dfb186599936 --- /dev/null +++ b/app/Composers/Modules/StickiedComposer.php @@ -0,0 +1,41 @@ + + * @author Connor S. Parks + * @author Antoine Girard + */ +class StickiedComposer +{ + /** + * Index page view composer. + * + * @param \Illuminate\Contracts\View\View $view + * + * @return void + */ + public function compose(View $view) + { + $stickiedIncidents = Incident::stickied()->orderBy('scheduled_at', 'desc')->orderBy('created_at', 'desc')->get()->groupBy(function (Incident $incident) { + return app(DateFactory::class)->make($incident->is_scheduled ? $incident->scheduled_at : $incident->created_at)->toDateString(); + }); + $view->withStickiedIncidents($stickiedIncidents); + } +} diff --git a/app/Console/Commands/DemoSeederCommand.php b/app/Console/Commands/DemoSeederCommand.php index 8048891ca62d..2eb88353b126 100644 --- a/app/Console/Commands/DemoSeederCommand.php +++ b/app/Console/Commands/DemoSeederCommand.php @@ -205,6 +205,7 @@ protected function seedIncidents() 'component_id' => 0, 'scheduled_at' => null, 'visible' => 1, + 'stickied' => false, ], [ 'name' => 'Awesome', @@ -213,6 +214,7 @@ protected function seedIncidents() 'component_id' => 0, 'scheduled_at' => null, 'visible' => 1, + 'stickied' => false, ], [ 'name' => 'Monitoring the fix', @@ -221,6 +223,7 @@ protected function seedIncidents() 'component_id' => 0, 'scheduled_at' => null, 'visible' => 1, + 'stickied' => false, ], [ 'name' => 'Update', @@ -229,6 +232,7 @@ protected function seedIncidents() 'component_id' => 0, 'scheduled_at' => null, 'visible' => 1, + 'stickied' => false, ], [ 'name' => 'Test Incident', @@ -237,6 +241,7 @@ protected function seedIncidents() 'component_id' => 0, 'scheduled_at' => null, 'visible' => 1, + 'stickied' => false, ], [ 'name' => 'Investigating the API', @@ -245,6 +250,16 @@ protected function seedIncidents() 'component_id' => 1, 'scheduled_at' => null, 'visible' => 1, + 'stickied' => false, + ], + [ + 'name' => 'Stickied to the top', + 'message' => 'Will be forever hanged here.', + 'status' => 1, + 'component_id' => 1, + 'scheduled_at' => null, + 'visible' => 1, + 'stickied' => true, ], ]; diff --git a/app/Foundation/Providers/ComposerServiceProvider.php b/app/Foundation/Providers/ComposerServiceProvider.php index 876903d31bff..445d2e08a787 100644 --- a/app/Foundation/Providers/ComposerServiceProvider.php +++ b/app/Foundation/Providers/ComposerServiceProvider.php @@ -19,6 +19,7 @@ use CachetHQ\Cachet\Composers\Modules\MetricsComposer as MetricsModuleComposer; use CachetHQ\Cachet\Composers\Modules\ScheduledComposer as ScheduledModuleComposer; use CachetHQ\Cachet\Composers\Modules\StatusComposer as StatusModuleComposer; +use CachetHQ\Cachet\Composers\Modules\StickiedComposer as StickiedModuleComposer; use CachetHQ\Cachet\Composers\Modules\TimelineComposer as TimelineModuleComposer; use CachetHQ\Cachet\Composers\ThemeComposer; use CachetHQ\Cachet\Composers\TimezoneLocaleComposer; @@ -43,6 +44,7 @@ public function boot(Factory $factory) $factory->composer('*', ModuleComposer::class); $factory->composer('partials.modules.components', ComponentsModuleComposer::class); $factory->composer('partials.modules.metrics', MetricsModuleComposer::class); + $factory->composer('partials.modules.stickied', StickiedModuleComposer::class); $factory->composer('partials.modules.scheduled', ScheduledModuleComposer::class); $factory->composer('partials.modules.status', StatusModuleComposer::class); $factory->composer('partials.modules.timeline', TimelineModuleComposer::class); diff --git a/app/Foundation/Providers/ModuleServiceProvider.php b/app/Foundation/Providers/ModuleServiceProvider.php index c997d1e70204..895f3d58f175 100644 --- a/app/Foundation/Providers/ModuleServiceProvider.php +++ b/app/Foundation/Providers/ModuleServiceProvider.php @@ -28,6 +28,7 @@ class ModuleServiceProvider extends ServiceProvider ['group' => 'status', 'partial' => 'partials.modules.status'], ['group' => 'components', 'partial' => 'partials.modules.components'], ['group' => 'metrics', 'partial' => 'partials.modules.metrics'], + ['group' => 'stickied', 'partial' => 'partials.modules.stickied'], ['group' => 'scheduled', 'partial' => 'partials.modules.scheduled'], ['group' => 'timeline', 'partial' => 'partials.modules.timeline'], ], @@ -45,7 +46,8 @@ class ModuleServiceProvider extends ServiceProvider 'components' => 30000, 'metrics' => 40000, 'scheduled' => 50000, - 'timeline' => 60000, + 'stickied' => 60000, + 'timeline' => 70000, ], ]; diff --git a/app/Http/Controllers/Api/IncidentController.php b/app/Http/Controllers/Api/IncidentController.php index 3a3066e695f4..0d7c8993c682 100644 --- a/app/Http/Controllers/Api/IncidentController.php +++ b/app/Http/Controllers/Api/IncidentController.php @@ -75,6 +75,7 @@ public function postIncidents() Binput::get('component_id'), Binput::get('component_status'), Binput::get('notify', true), + Binput::get('stickied', false), Binput::get('created_at'), Binput::get('template'), Binput::get('vars') @@ -105,6 +106,7 @@ public function putIncident(Incident $incident) Binput::get('component_id'), Binput::get('component_status'), Binput::get('notify', true), + Binput::get('stickied', false), Binput::get('created_at'), Binput::get('template'), Binput::get('vars') diff --git a/app/Http/Controllers/Dashboard/IncidentController.php b/app/Http/Controllers/Dashboard/IncidentController.php index 80b5bd507c1c..5a1284c86296 100644 --- a/app/Http/Controllers/Dashboard/IncidentController.php +++ b/app/Http/Controllers/Dashboard/IncidentController.php @@ -115,6 +115,7 @@ public function createIncidentAction() Binput::get('component_id'), Binput::get('component_status'), Binput::get('notify', false), + Binput::get('stickied', false), Binput::get('created_at'), null, null @@ -240,6 +241,7 @@ public function editIncidentAction(Incident $incident) Binput::get('component_id'), Binput::get('component_status'), Binput::get('notify', true), + Binput::get('stickied', false), Binput::get('created_at'), null, null diff --git a/app/Models/Incident.php b/app/Models/Incident.php index 19fe678f4900..e89364c29f5f 100644 --- a/app/Models/Incident.php +++ b/app/Models/Incident.php @@ -32,6 +32,7 @@ class Incident extends Model implements HasPresenter */ protected $casts = [ 'visible' => 'int', + 'stickied' => 'int', 'scheduled_at' => 'date', 'deleted_at' => 'date', ]; @@ -46,6 +47,7 @@ class Incident extends Model implements HasPresenter 'name', 'status', 'visible', + 'stickied', 'message', 'scheduled_at', 'created_at', @@ -62,6 +64,7 @@ class Incident extends Model implements HasPresenter 'name' => 'required', 'status' => 'required|int', 'visible' => 'required|bool', + 'stickied' => 'bool', 'message' => 'required', ]; @@ -76,6 +79,7 @@ class Incident extends Model implements HasPresenter 'name', 'status', 'visible', + 'stickied', ]; /** @@ -88,6 +92,7 @@ class Incident extends Model implements HasPresenter 'name', 'status', 'visible', + 'stickied', 'message', ]; @@ -113,6 +118,18 @@ public function scopeVisible(Builder $query) return $query->where('visible', 1); } + /** + * Finds all stickied incidents. + * + * @param \Illuminate\Database\Eloquent\Builder $query + * + * @return \Illuminate\Database\Eloquent\Builder + */ + public function scopeStickied(Builder $query) + { + return $query->where('stickied', true); + } + /** * Finds all scheduled incidents (maintenance). * diff --git a/database/factories/ModelFactory.php b/database/factories/ModelFactory.php index 15862fa3fef7..3c70bdbeb169 100644 --- a/database/factories/ModelFactory.php +++ b/database/factories/ModelFactory.php @@ -40,10 +40,11 @@ $factory->define(Incident::class, function ($faker) { return [ - 'name' => $faker->sentence(), - 'message' => $faker->paragraph(), - 'status' => random_int(1, 4), - 'visible' => 1, + 'name' => $faker->sentence(), + 'message' => $faker->paragraph(), + 'status' => random_int(1, 4), + 'visible' => 1, + 'stickied' => false, ]; }); diff --git a/database/migrations/2016_09_04_100000_AlterTableIncidentsAddStickiedColumn.php b/database/migrations/2016_09_04_100000_AlterTableIncidentsAddStickiedColumn.php new file mode 100644 index 000000000000..056c21e1148f --- /dev/null +++ b/database/migrations/2016_09_04_100000_AlterTableIncidentsAddStickiedColumn.php @@ -0,0 +1,39 @@ +boolean('stickied')->after('visible')->default(false); + + $table->index('stickied'); + }); + } + + /** + * Reverse the migrations. + */ + public function down() + { + Schema::table('incidents', function (Blueprint $table) { + $table->dropColumn('stickied'); + }); + } +} diff --git a/resources/lang/en/cachet.php b/resources/lang/en/cachet.php index fef9dc9ccde3..945afaff8aec 100644 --- a/resources/lang/en/cachet.php +++ b/resources/lang/en/cachet.php @@ -30,6 +30,7 @@ 'past' => 'Past Incidents', 'previous_week' => 'Previous week', 'next_week' => 'Next week', + 'stickied' => 'Stickied Incidents', 'scheduled' => 'Scheduled Maintenance', 'scheduled_at' => ', scheduled :timestamp', 'status' => [ diff --git a/resources/lang/en/forms.php b/resources/lang/en/forms.php index 1eb9246e1608..fac80593fe56 100644 --- a/resources/lang/en/forms.php +++ b/resources/lang/en/forms.php @@ -53,6 +53,9 @@ 'incident_time' => 'When did this incident occur?', 'notify_subscribers' => 'Notify subscribers?', 'visibility' => 'Incident Visibility', + 'stick_status' => 'Stick Incident', + 'stickied' => 'Stickied', + 'not_stickied' => 'Not Stickied', 'public' => 'Viewable by public', 'logged_in_only' => 'Only visible to logged in users', 'templates' => [ diff --git a/resources/views/dashboard/incidents/add.blade.php b/resources/views/dashboard/incidents/add.blade.php index f799042f7e65..09c8c47eb813 100644 --- a/resources/views/dashboard/incidents/add.blade.php +++ b/resources/views/dashboard/incidents/add.blade.php @@ -62,6 +62,13 @@ +
+ + +
@if(!$components_in_groups->isEmpty() || !$components_out_groups->isEmpty())
diff --git a/resources/views/dashboard/incidents/edit.blade.php b/resources/views/dashboard/incidents/edit.blade.php index d42d6520722e..f8beec8d6bb8 100644 --- a/resources/views/dashboard/incidents/edit.blade.php +++ b/resources/views/dashboard/incidents/edit.blade.php @@ -51,6 +51,13 @@
+
+ + +
@if($incident->component)
diff --git a/resources/views/partials/modules/stickied.blade.php b/resources/views/partials/modules/stickied.blade.php new file mode 100644 index 000000000000..1b36cb3b0ebf --- /dev/null +++ b/resources/views/partials/modules/stickied.blade.php @@ -0,0 +1,8 @@ +@if(!$stickied_incidents->isEmpty()) +
+

{{ trans('cachet.incidents.stickied') }}

+ @foreach($stickied_incidents as $date => $incidents) + @include('partials.incidents', [compact($date), compact($incidents)]) + @endforeach +
+@endif diff --git a/tests/Api/IncidentTest.php b/tests/Api/IncidentTest.php index f0ebafc32232..dfd260a89e70 100644 --- a/tests/Api/IncidentTest.php +++ b/tests/Api/IncidentTest.php @@ -55,10 +55,11 @@ public function testPostIncident() $this->beUser(); $this->post('/api/v1/incidents', [ - 'name' => 'Foo', - 'message' => 'Lorem ipsum dolor sit amet', - 'status' => 1, - 'visible' => 1, + 'name' => 'Foo', + 'message' => 'Lorem ipsum dolor sit amet', + 'status' => 1, + 'visible' => 1, + 'stickied' => false, ]); $this->seeJson(['name' => 'Foo']); $this->assertResponseOk(); @@ -77,6 +78,7 @@ public function testPostIncidentWithComponentStatus() 'component_id' => $component->id, 'component_status' => 1, 'visible' => 1, + 'stickied' => false, ]); $this->seeJson(['name' => 'Foo']); $this->assertResponseOk(); @@ -91,6 +93,7 @@ public function testCreateIncidentWithTemplate() 'name' => 'Foo', 'status' => 1, 'visible' => 1, + 'stickied' => false, 'template' => $template->slug, 'vars' => [ 'name' => 'Foo', diff --git a/tests/Bus/Commands/Incident/ReportIncidentCommandTest.php b/tests/Bus/Commands/Incident/ReportIncidentCommandTest.php index 0b66aa72df52..09ac5c4c114b 100644 --- a/tests/Bus/Commands/Incident/ReportIncidentCommandTest.php +++ b/tests/Bus/Commands/Incident/ReportIncidentCommandTest.php @@ -36,6 +36,7 @@ protected function getObjectAndParams() 'component_id' => 1, 'component_status' => 1, 'notify' => false, + 'stickied' => false, 'incident_date' => null, 'template' => null, 'template_vars' => null, @@ -49,6 +50,7 @@ protected function getObjectAndParams() $params['component_id'], $params['component_status'], $params['notify'], + $params['stickied'], $params['incident_date'], $params['template'], $params['template_vars'] diff --git a/tests/Bus/Commands/Incident/UpdateIncidentCommandTest.php b/tests/Bus/Commands/Incident/UpdateIncidentCommandTest.php index 6a4926e5c4fa..1957dea2158b 100644 --- a/tests/Bus/Commands/Incident/UpdateIncidentCommandTest.php +++ b/tests/Bus/Commands/Incident/UpdateIncidentCommandTest.php @@ -38,6 +38,7 @@ protected function getObjectAndParams() 'component_id' => 1, 'component_status' => 1, 'notify' => false, + 'stickied' => false, 'incident_date' => null, 'template' => null, 'template_vars' => null, @@ -52,6 +53,7 @@ protected function getObjectAndParams() $params['component_id'], $params['component_status'], $params['notify'], + $params['stickied'], $params['incident_date'], $params['template'], $params['template_vars']