Rewrite the entire scheduled maintenance implementation

This commit is contained in:
James Brooks
2016-10-30 20:54:12 +00:00
parent a2cded299d
commit ebed68a7d8
57 changed files with 1989 additions and 512 deletions
@@ -1,73 +0,0 @@
<?php
/*
* This file is part of Cachet.
*
* (c) Alt Three Services Limited
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace CachetHQ\Cachet\Bus\Commands\Incident;
final class ReportMaintenanceCommand
{
/**
* The maintenance name.
*
* @var string
*/
public $name;
/**
* The maintenance message.
*
* @var string
*/
public $message;
/**
* Whether to notify about the maintenance or not.
*
* @var bool
*/
public $notify;
/**
* Timestamp of when the maintenance is due to start.
*
* @var string
*/
public $timestamp;
/**
* The validation rules.
*
* @var string[]
*/
public $rules = [
'name' => 'required|string',
'message' => 'required|string',
'notify' => 'nullable|bool',
'timestamp' => 'required|string',
];
/**
* Create a new report maintenance command instance.
*
* @param string $name
* @param string $message
* @param bool $notify
* @param string $timestamp
*
* @return void
*/
public function __construct($name, $message, $notify, $timestamp)
{
$this->name = $name;
$this->message = $message;
$this->notify = $notify;
$this->timestamp = $timestamp;
}
}
@@ -0,0 +1,98 @@
<?php
/*
* This file is part of Cachet.
*
* (c) Alt Three Services Limited
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace CachetHQ\Cachet\Bus\Commands\Schedule;
/**
* This is the create schedule command.
*
* @author James Brooks <james@alt-three.com>
*/
final class CreateScheduleCommand
{
/**
* The schedule name.
*
* @var string
*/
public $name;
/**
* The schedule message.
*
* @var string
*/
public $message;
/**
* The schedule status.
*
* @var int
*/
public $status;
/**
* The schedule date.
*
* @var string
*/
public $scheduled_at;
/**
* The completed at date.
*
* @var string
*/
public $completed_at;
/**
* The components affected by the schedule.
*
* @var array
*/
public $components;
/**
* The validation rules.
*
* @var string[]
*/
public $rules = [
'name' => 'required|string',
'message' => 'nullable|string',
'status' => 'required|int|min:0|max:2',
'scheduled_at' => 'required|string',
'completed_at' => 'nullable|string',
'components' => 'required|array',
];
/**
* Create a new create schedule command instance.
*
* @param string $name
* @param string $message
* @param int $status
* @param string $scheduled_at
* @param string $completed_at
* @param array $components
*
* @return void
*/
public function __construct($name, $message, $status, $scheduled_at, $completed_at, array $components)
{
$this->name = $name;
$this->message = $message;
$this->status = $status;
$this->scheduled_at = $scheduled_at;
$this->completed_at = $completed_at;
$this->components = $components;
}
}
@@ -0,0 +1,50 @@
<?php
/*
* This file is part of Cachet.
*
* (c) Alt Three Services Limited
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace CachetHQ\Cachet\Bus\Commands\Schedule;
use CachetHQ\Cachet\Models\Schedule;
/**
* This is the delete schedule command.
*
* @author James Brooks <james@alt-three.com>
*/
final class DeleteScheduleCommand
{
/**
* The schedule to delete.
*
* @var \CachetHQ\Cachet\Models\Schedule
*/
public $schedule;
/**
* The validation rules.
*
* @var string[]
*/
public $rules = [
'schedule' => 'required',
];
/**
* Create a new delete schedule command instance.
*
* @param \CachetHQ\Cachet\Models\Schedule $schedule
*
* @return void
*/
public function __construct(Schedule $schedule)
{
$this->schedule = $schedule;
}
}
@@ -0,0 +1,110 @@
<?php
/*
* This file is part of Cachet.
*
* (c) Alt Three Services Limited
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace CachetHQ\Cachet\Bus\Commands\Schedule;
use CachetHQ\Cachet\Models\Schedule;
/**
* This is the update schedule command.
*
* @author James Brooks <james@alt-three.com>
*/
final class UpdateScheduleCommand
{
/**
* The schedule to update.
*
* @param \CachetHQ\Cachet\Models\Schedule
*/
public $schedule;
/**
* The schedule name.
*
* @var string
*/
public $name;
/**
* The schedule message.
*
* @var string
*/
public $message;
/**
* The schedule status.
*
* @var int
*/
public $status;
/**
* The schedule date.
*
* @var string
*/
public $scheduled_at;
/**
* The completed at date.
*
* @var string
*/
public $completed_at;
/**
* The components affected by the schedule.
*
* @var array
*/
public $components;
/**
* The validation rules.
*
* @var string[]
*/
public $rules = [
'schedule' => 'required',
'name' => 'nullable|string',
'message' => 'nullable|string',
'status' => 'nullable|int|min:0|max:2',
'scheduled_at' => 'nullable|string',
'completed_at' => 'nullable|string',
'components' => 'nullable|array',
];
/**
* Create a new update schedule command instance.
*
* @param \CachetHQ\Cachet\Models\Schedule $schedule
* @param string $name
* @param string $message
* @param int $status
* @param string $scheduled_at
* @param string $completed_at
* @param array $components
*
* @return void
*/
public function __construct(Schedule $schedule, $name, $message, $status, $scheduled_at, $completed_at, array $components = [])
{
$this->schedule = $schedule;
$this->name = $name;
$this->message = $message;
$this->status = $status;
$this->scheduled_at = $scheduled_at;
$this->completed_at = $completed_at;
$this->components = $components;
}
}
@@ -1,36 +0,0 @@
<?php
/*
* This file is part of Cachet.
*
* (c) Alt Three Services Limited
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace CachetHQ\Cachet\Bus\Events\Incident;
use CachetHQ\Cachet\Models\Incident;
final class MaintenanceWasScheduledEvent implements IncidentEventInterface
{
/**
* The incident that has been reported.
*
* @var \CachetHQ\Cachet\Models\Incident
*/
public $incident;
/**
* Create a new maintenance has scheduled event instance.
*
* @param \CachetHQ\Cachet\Models\Incident $incident
*
* @return void
*/
public function __construct(Incident $incident)
{
$this->incident = $incident;
}
}
@@ -0,0 +1,24 @@
<?php
/*
* This file is part of Cachet.
*
* (c) Alt Three Services Limited
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace CachetHQ\Cachet\Bus\Events\Schedule;
use CachetHQ\Cachet\Bus\Events\EventInterface;
/**
* This is the schedule event interface.
*
* @author James Brooks <james@alt-three.com>
*/
interface ScheduleEventInterface extends EventInterface
{
//
}
@@ -0,0 +1,41 @@
<?php
/*
* This file is part of Cachet.
*
* (c) Alt Three Services Limited
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace CachetHQ\Cachet\Bus\Events\Schedule;
use CachetHQ\Cachet\Models\Schedule;
/**
* This is the schedule was created event class.
*
* @author James Brooks <james@alt-three.com>
*/
final class ScheduleWasCreatedEvent implements ScheduleEventInterface
{
/**
* The schedule that has been created.
*
* @var \CachetHQ\Cachet\Models\Schedule
*/
public $schedule;
/**
* Create a new schedule was created event instance.
*
* @param \CachetHQ\Cachet\Models\Schedule $schedule
*
* @return void
*/
public function __construct(Schedule $schedule)
{
$this->schedule = $schedule;
}
}
@@ -0,0 +1,41 @@
<?php
/*
* This file is part of Cachet.
*
* (c) Alt Three Services Limited
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace CachetHQ\Cachet\Bus\Events\Schedule;
use CachetHQ\Cachet\Models\Schedule;
/**
* This is the schedule was removed event class.
*
* @author James Brooks <james@alt-three.com>
*/
final class ScheduleWasRemovedEvent implements ScheduleEventInterface
{
/**
* The schedule that has been removed.
*
* @var \CachetHQ\Cachet\Models\Schedule
*/
public $schedule;
/**
* Create a new schedule was removed event instance.
*
* @param \CachetHQ\Cachet\Models\Schedule $schedule
*
* @return void
*/
public function __construct(Schedule $schedule)
{
$this->schedule = $schedule;
}
}
@@ -0,0 +1,41 @@
<?php
/*
* This file is part of Cachet.
*
* (c) Alt Three Services Limited
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace CachetHQ\Cachet\Bus\Events\Schedule;
use CachetHQ\Cachet\Models\Schedule;
/**
* This is the schedule was updated event class.
*
* @author James Brooks <james@alt-three.com>
*/
final class ScheduleWasUpdatedEvent implements ScheduleEventInterface
{
/**
* The schedule that has been updated.
*
* @var \CachetHQ\Cachet\Models\Schedule
*/
public $schedule;
/**
* Create a new schedule was updated event instance.
*
* @param \CachetHQ\Cachet\Models\Schedule $schedule
*
* @return void
*/
public function __construct(Schedule $schedule)
{
$this->schedule = $schedule;
}
}
@@ -1,66 +0,0 @@
<?php
/*
* This file is part of Cachet.
*
* (c) Alt Three Services Limited
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace CachetHQ\Cachet\Bus\Handlers\Commands\Incident;
use CachetHQ\Cachet\Bus\Commands\Incident\ReportMaintenanceCommand;
use CachetHQ\Cachet\Bus\Events\Incident\MaintenanceWasScheduledEvent;
use CachetHQ\Cachet\Dates\DateFactory;
use CachetHQ\Cachet\Models\Incident;
class ReportMaintenanceCommandHandler
{
/**
* The date factory instance.
*
* @var \CachetHQ\Cachet\Dates\DateFactory
*/
protected $dates;
/**
* Create a new report maintenance command handler instance.
*
* @param \CachetHQ\Cachet\Dates\DateFactory $dates
*
* @return void
*/
public function __construct(DateFactory $dates)
{
$this->dates = $dates;
}
/**
* Handle the report maintenance command.
*
* @param \CachetHQ\Cachet\Bus\Commands\Incident\ReportMaintenanceCommand $command
*
* @return \CachetHQ\Cachet\Models\Incident
*/
public function handle(ReportMaintenanceCommand $command)
{
$scheduledAt = $this->dates->create('d/m/Y H:i', $command->timestamp);
$maintenanceEvent = Incident::create([
'name' => $command->name,
'message' => $command->message,
'scheduled_at' => $scheduledAt,
'status' => 0,
'visible' => 1,
'stickied' => false,
]);
$maintenanceEvent->notify = (bool) $command->notify;
event(new MaintenanceWasScheduledEvent($maintenanceEvent));
return $maintenanceEvent;
}
}
@@ -0,0 +1,90 @@
<?php
/*
* This file is part of Cachet.
*
* (c) Alt Three Services Limited
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace CachetHQ\Cachet\Bus\Handlers\Commands\Schedule;
use CachetHQ\Cachet\Bus\Commands\Schedule\CreateScheduleCommand;
use CachetHQ\Cachet\Bus\Events\Schedule\ScheduleWasCreatedEvent;
use CachetHQ\Cachet\Dates\DateFactory;
use CachetHQ\Cachet\Models\Schedule;
/**
* This is the create schedule command handler.
*
* @author James Brooks <james@alt-three.com>
*/
class CreateScheduleCommandHandler
{
/**
* The date factory instance.
*
* @var \CachetHQ\Cachet\Dates\DateFactory
*/
protected $dates;
/**
* Create a new update schedule command handler instance.
*
* @param \CachetHQ\Cachet\Dates\DateFactory $dates
*
* @return void
*/
public function __construct(DateFactory $dates)
{
$this->dates = $dates;
}
/**
* Handle the create schedule command.
*
* @param \CachetHQ\Cachet\Bus\Commands\Schedule\CreateScheduleCommand $command
*
* @return \CachetHQ\Cachet\Models\Schedule
*/
public function handle(CreateScheduleCommand $command)
{
$schedule = Schedule::create($this->filter($command));
event(new ScheduleWasCreatedEvent($schedule));
return $schedule;
}
/**
* Filter the command data.
*
* @param \CachetHQ\Cachet\Bus\Commands\Schedule\CreateScheduleCommand $command
*
* @return array
*/
protected function filter(CreateScheduleCommand $command)
{
$scheduledAt = $this->dates->create('Y-m-d H:i', $command->scheduled_at);
if ($completedAt = $command->completed_at) {
$completedAt = $this->dates->create('Y-m-d H:i', $command->completed_at);
}
$params = [
'name' => $command->name,
'message' => $command->message,
'status' => $command->status,
'scheduled_at' => $scheduledAt,
'completed_at' => $completedAt,
];
$availableParams = array_filter($params, function ($val) {
return $val !== null;
});
return $availableParams;
}
}
@@ -0,0 +1,39 @@
<?php
/*
* This file is part of Cachet.
*
* (c) Alt Three Services Limited
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace CachetHQ\Cachet\Bus\Handlers\Commands\Schedule;
use CachetHQ\Cachet\Bus\Commands\Schedule\DeleteScheduleCommand;
use CachetHQ\Cachet\Bus\Events\Schedule\ScheduleWasRemovedEvent;
/**
* This is the delete schedule command handler.
*
* @author James Brooks <james@alt-three.com>
*/
class DeleteScheduleCommandHandler
{
/**
* Handle the delete schedule command.
*
* @param \CachetHQ\Cachet\Bus\Commands\Schedule\DeleteScheduleCommand $command
*
* @return void
*/
public function handle(DeleteScheduleCommand $command)
{
$schedule = $command->schedule;
event(new ScheduleWasRemovedEvent($schedule));
$schedule->delete();
}
}
@@ -0,0 +1,92 @@
<?php
/*
* This file is part of Cachet.
*
* (c) Alt Three Services Limited
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace CachetHQ\Cachet\Bus\Handlers\Commands\Schedule;
use CachetHQ\Cachet\Bus\Commands\Schedule\UpdateScheduleCommand;
use CachetHQ\Cachet\Bus\Events\Schedule\ScheduleWasUpdatedEvent;
use CachetHQ\Cachet\Dates\DateFactory;
use CachetHQ\Cachet\Models\Schedule;
/**
* This is the update schedule command handler.
*
* @author James Brooks <james@alt-three.com>
*/
class UpdateScheduleCommandHandler
{
/**
* The date factory instance.
*
* @var \CachetHQ\Cachet\Dates\DateFactory
*/
protected $dates;
/**
* Create a new update schedule command handler instance.
*
* @param \CachetHQ\Cachet\Dates\DateFactory $dates
*
* @return void
*/
public function __construct(DateFactory $dates)
{
$this->dates = $dates;
}
/**
* Handle the update schedule command.
*
* @param \CachetHQ\Cachet\Bus\Commands\Schedule\UpdateScheduleCommand $command
*
* @return \CachetHQ\Cachet\Models\Schedule
*/
public function handle(UpdateScheduleCommand $command)
{
$schedule = $command->schedule;
$schedule->update($this->filter($command));
event(new ScheduleWasUpdatedEvent($schedule));
return $schedule;
}
/**
* Filter the command data.
*
* @param \CachetHQ\Cachet\Bus\Commands\Schedule\UpdateScheduleCommand $command
*
* @return array
*/
protected function filter(UpdateScheduleCommand $command)
{
$params = [
'name' => $command->name,
'message' => $command->message,
'status' => $command->status,
];
if ($scheduleddAt = $command->scheduled_at) {
$params['scheduled_at'] = $this->dates->create('Y-m-d H:i', $scheduledAt);
}
if ($completedAt = $command->completed_at) {
$params['completed_at'] = $this->dates->create('Y-m-d H:i', $completedAt);
}
$availableParams = array_filter($params, function ($val) {
return $val !== null;
});
return $availableParams;
}
}
@@ -9,15 +9,20 @@
* file that was distributed with this source code.
*/
namespace CachetHQ\Cachet\Bus\Handlers\Events\Incident;
namespace CachetHQ\Cachet\Bus\Handlers\Events\Schedule;
use CachetHQ\Cachet\Bus\Events\Incident\MaintenanceWasScheduledEvent;
use CachetHQ\Cachet\Bus\Events\Schedule\ScheduleEventInterface;
use CachetHQ\Cachet\Models\Subscriber;
use Illuminate\Contracts\Mail\MailQueue;
use Illuminate\Mail\Message;
use McCool\LaravelAutoPresenter\Facades\AutoPresenter;
class SendMaintenanceEmailNotificationHandler
/**
* This is the send schedule event notification handler.
*
* @author James Brooks <james@alt-three.com>
*/
class SendScheduleEmailNotificationHandler
{
/**
* The mailer instance.
@@ -50,21 +55,12 @@ class SendMaintenanceEmailNotificationHandler
/**
* Handle the event.
*
* @param \CachetHQ\Cachet\Bus\Events\MaintenanceWasScheduledEvent $event
* @param \CachetHQ\Cachet\Bus\Events\Schedule\ScheduleEventInterface $event
*
* @return void
*/
public function handle(MaintenanceWasScheduledEvent $event)
public function handle(ScheduleEventInterface $event)
{
if (!$event->incident->notify) {
return false;
}
// Only send emails for public incidents.
if ($event->incident->visible === 0) {
return;
}
// First notify all global subscribers.
$globalSubscribers = $this->subscriber->isVerified()->isGlobal()->get();
@@ -72,10 +68,6 @@ class SendMaintenanceEmailNotificationHandler
$this->notify($event, $subscriber);
}
if (!$event->incident->component) {
return;
}
$notified = $globalSubscribers->pluck('id')->all();
// Notify the remaining component specific subscribers.
@@ -95,12 +87,12 @@ class SendMaintenanceEmailNotificationHandler
/**
* Send notification to subscriber.
*
* @param \CachetHQ\Cachet\Bus\Events\MaintenanceWasScheduledEvent $event
* @param \CachetHQ\Cachet\Models\Subscriber $subscriber
* @param \CachetHQ\Cachet\Bus\Events\Schedule\ScheduleEventInterface $event
* @param \CachetHQ\Cachet\Models\Subscriber $subscriber
*
* @return \Illuminate\Database\Eloquent\Collection
*/
public function notify(MaintenanceWasScheduledEvent $event, $subscriber)
public function notify(ScheduleEventInterface $event, $subscriber)
{
$incident = AutoPresenter::decorate($event->incident);
$component = AutoPresenter::decorate($event->incident->component);
+4 -2
View File
@@ -14,6 +14,7 @@ namespace CachetHQ\Cachet\Composers;
use CachetHQ\Cachet\Models\Component;
use CachetHQ\Cachet\Models\Incident;
use CachetHQ\Cachet\Models\IncidentTemplate;
use CachetHQ\Cachet\Models\Schedule;
use CachetHQ\Cachet\Models\Subscriber;
use Illuminate\Contracts\View\View;
@@ -34,9 +35,10 @@ class DashboardComposer
*/
public function compose(View $view)
{
$view->withIncidentCount(Incident::notScheduled()->count());
$view->withComponentCount(Component::count());
$view->withIncidentCount(Incident::count());
$view->withIncidentTemplateCount(IncidentTemplate::count());
$view->withComponentCount(Component::all()->count());
$view->withScheduleCount(Schedule::count());
$view->withSubscriberCount(Subscriber::isVerified()->count());
}
}
+2 -2
View File
@@ -11,7 +11,7 @@
namespace CachetHQ\Cachet\Composers\Modules;
use CachetHQ\Cachet\Models\Incident;
use CachetHQ\Cachet\Models\Schedule;
use Illuminate\Contracts\View\View;
/**
@@ -31,7 +31,7 @@ class ScheduledComposer
*/
public function compose(View $view)
{
$scheduledMaintenance = Incident::scheduled()->orderBy('scheduled_at')->get();
$scheduledMaintenance = Schedule::futureSchedules()->orderBy('scheduled_at')->get();
$view->withScheduledMaintenance($scheduledMaintenance);
}
+2 -1
View File
@@ -33,9 +33,10 @@ class StickiedComposer
*/
public function compose(View $view)
{
$stickiedIncidents = Incident::stickied()->orderBy('scheduled_at', 'desc')->orderBy('occurred_at', 'desc')->get()->groupBy(function (Incident $incident) {
$stickiedIncidents = Incident::stickied()->orderBy('occurred_at', 'desc')->get()->groupBy(function (Incident $incident) {
return app(DateFactory::class)->make($incident->is_scheduled ? $incident->scheduled_at : $incident->occurred_at)->toDateString();
});
$view->withStickiedIncidents($stickiedIncidents);
}
}
+23 -2
View File
@@ -18,6 +18,7 @@ use CachetHQ\Cachet\Models\IncidentTemplate;
use CachetHQ\Cachet\Models\IncidentUpdate;
use CachetHQ\Cachet\Models\Metric;
use CachetHQ\Cachet\Models\MetricPoint;
use CachetHQ\Cachet\Models\Schedule;
use CachetHQ\Cachet\Models\Subscriber;
use CachetHQ\Cachet\Models\User;
use CachetHQ\Cachet\Settings\Repository;
@@ -89,6 +90,7 @@ class DemoSeederCommand extends Command
$this->seedIncidentTemplates();
$this->seedMetricPoints();
$this->seedMetrics();
$this->seedSchedules();
$this->seedSettings();
$this->seedSubscribers();
$this->seedUsers();
@@ -207,7 +209,6 @@ EINCIDENT;
'message' => 'We\'re investigating an issue with our monkeys not performing as they should be.',
'status' => Incident::INVESTIGATING,
'component_id' => 0,
'scheduled_at' => null,
'visible' => 1,
'stickied' => false,
'occurred_at' => Carbon::now(),
@@ -217,7 +218,6 @@ EINCIDENT;
'message' => 'Unresolved incidents are left without a **Fixed** update.',
'status' => Incident::INVESTIGATING,
'component_id' => 0,
'scheduled_at' => null,
'visible' => 1,
'stickied' => false,
'occurred_at' => Carbon::now(),
@@ -332,6 +332,27 @@ EINCIDENT;
}
}
/**
* Seed the schedules table.
*
* @return void
*/
protected function seedSchedules()
{
$defaultSchedules = [
[
'name' => 'Demo resets every half hour!',
'message' => 'You can schedule downtime for _your_ service!',
'status' => Schedule::UPCOMING,
'scheduled_at' => (new DateTime())->add(new DateInterval('PT2H')),
],
];
foreach ($defaultSchedules as $schedule) {
Schedule::create($schedule);
}
}
/**
* Seed the settings table.
*
@@ -69,9 +69,6 @@ class EventServiceProvider extends ServiceProvider
'CachetHQ\Cachet\Bus\Events\Incident\IncidentWasRemovedEvent' => [
//
],
'CachetHQ\Cachet\Bus\Events\Incident\MaintenanceWasScheduledEvent' => [
'CachetHQ\Cachet\Bus\Handlers\Events\Incident\SendMaintenanceEmailNotificationHandler',
],
'CachetHQ\Cachet\Bus\Events\Invite\InviteWasClaimedEvent' => [
//
],
@@ -93,6 +90,15 @@ class EventServiceProvider extends ServiceProvider
'CachetHQ\Cachet\Bus\Events\Metric\MetricWasUpdatedEvent' => [
//
],
'CachetHQ\Cachet\Bus\Events\Schedule\ScheduleWasCreatedEvent' => [
// 'CachetHQ\Cachet\Bus\Handlers\Events\Schedule\SendScheduleEmailNotificationHandler',
],
'CachetHQ\Cachet\Bus\Events\Schedule\ScheduleWasRemovedEvent' => [
//
],
'CachetHQ\Cachet\Bus\Events\Schedule\ScheduleWasUpdatedEvent' => [
//
],
'CachetHQ\Cachet\Bus\Events\Subscriber\SubscriberHasSubscribedEvent' => [
'CachetHQ\Cachet\Bus\Handlers\Events\Subscriber\SendSubscriberVerificationEmailHandler',
],
@@ -69,6 +69,7 @@ class RouteServiceProvider extends ServiceProvider
$router->model('incident_update', 'CachetHQ\Cachet\Models\IncidentUpdate');
$router->model('metric', 'CachetHQ\Cachet\Models\Metric');
$router->model('metric_point', 'CachetHQ\Cachet\Models\MetricPoint');
$router->model('schedule', 'CachetHQ\Cachet\Models\Schedule');
$router->model('setting', 'CachetHQ\Cachet\Models\Setting');
$router->model('subscriber', 'CachetHQ\Cachet\Models\Subscriber');
$router->model('subscription', 'CachetHQ\Cachet\Models\Subscription');
@@ -0,0 +1,128 @@
<?php
/*
* This file is part of Cachet.
*
* (c) Alt Three Services Limited
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace CachetHQ\Cachet\Http\Controllers\Api;
use CachetHQ\Cachet\Bus\Commands\Schedule\CreateScheduleCommand;
use CachetHQ\Cachet\Bus\Commands\Schedule\DeleteScheduleCommand;
use CachetHQ\Cachet\Bus\Commands\Schedule\UpdateScheduleCommand;
use CachetHQ\Cachet\Models\Schedule;
use GrahamCampbell\Binput\Facades\Binput;
use Illuminate\Database\QueryException;
use Illuminate\Support\Facades\Request;
use Symfony\Component\HttpKernel\Exception\BadRequestHttpException;
/**
* This is the schedule controller.
*
* @author James Brooks <james@alt-three.com>
*/
class ScheduleController extends AbstractApiController
{
/**
* Return all schedules.
*
* @return \Illuminate\Http\JsonResponse
*/
public function getSchedules()
{
$schedule = Schedule::whereRaw('1 = 1');
if ($sortBy = Binput::get('sort')) {
$direction = Binput::has('order') && Binput::get('order') == 'desc';
$schedule->sort($sortBy, $direction);
}
$schedule = $schedule->paginate(Binput::get('per_page', 20));
return $this->paginator($schedule, Request::instance());
}
/**
* Return a single schedule.
*
* @param \CachetHQ\Cachet\Models\Schedule $schedule
*
* @return \Illuminate\Http\JsonResponse
*/
public function getSchedule(Schedule $schedule)
{
return $this->item($schedule);
}
/**
* Create a new schedule.
*
* @return \Illuminate\Http\JsonResponse
*/
public function postSchedule()
{
try {
$schedule = dispatch(new CreateScheduleCommand(
Binput::get('name'),
Binput::get('message'),
Binput::get('status'),
Binput::get('scheduled_at'),
Binput::get('completed_at'),
Binput::get('components', [])
));
} catch (QueryException $e) {
throw new BadRequestHttpException();
}
return $this->item($schedule);
}
/**
* Update a schedule.
*
* @param \CachetHQ\Cachet\Models\Schedule $schedule
*
* @return \Illuminate\Http\JsonResponse
*/
public function putSchedule(Schedule $schedule)
{
try {
$schedule = dispatch(new UpdateScheduleCommand(
$schedule,
Binput::get('name'),
Binput::get('message'),
Binput::get('status'),
Binput::get('scheduled_at'),
Binput::get('completed_at'),
Binput::get('components', [])
));
} catch (QueryException $e) {
throw new BadRequestHttpException();
}
return $this->item($schedule);
}
/**
* Delete a schedule.
*
* @param \CachetHQ\Cachet\Models\Schedule $schedule
*
* @return \Illuminate\Http\JsonResponse
*/
public function deleteSchedule(Schedule $schedule)
{
try {
dispatch(new DeleteScheduleCommand($schedule));
} catch (QueryException $e) {
throw new BadRequestHttpException();
}
return $this->noContent();
}
}
@@ -127,7 +127,7 @@ class DashboardController extends Controller
*/
protected function getIncidents()
{
$allIncidents = Incident::notScheduled()->whereBetween('occurred_at', [
$allIncidents = Incident::whereBetween('occurred_at', [
$this->startDate->copy()->subDays(30)->format('Y-m-d').' 00:00:00',
$this->startDate->format('Y-m-d').' 23:59:59',
])->orderBy('occurred_at', 'desc')->get()->groupBy(function (Incident $incident) {
@@ -57,22 +57,6 @@ class IncidentController extends Controller
{
$this->auth = $auth;
$this->subMenu = [
'incidents' => [
'title' => trans('dashboard.incidents.incidents'),
'url' => cachet_route('dashboard.incidents'),
'icon' => 'ion-android-checkmark-circle',
'active' => true,
],
'schedule' => [
'title' => trans('dashboard.schedule.schedule'),
'url' => cachet_route('dashboard.schedule'),
'icon' => 'ion-android-calendar',
'active' => false,
],
];
View::share('sub_menu', $this->subMenu);
View::share('sub_title', trans('dashboard.incidents.title'));
}
@@ -83,7 +67,7 @@ class IncidentController extends Controller
*/
public function showIncidents()
{
$incidents = Incident::notScheduled()->orderBy('created_at', 'desc')->get();
$incidents = Incident::orderBy('created_at', 'desc')->get();
return View::make('dashboard.incidents.index')
->withPageTitle(trans('dashboard.incidents.incidents').' - '.trans('dashboard.dashboard'))
@@ -12,16 +12,20 @@
namespace CachetHQ\Cachet\Http\Controllers\Dashboard;
use AltThree\Validator\ValidationException;
use CachetHQ\Cachet\Bus\Commands\Incident\ReportMaintenanceCommand;
use CachetHQ\Cachet\Dates\DateFactory;
use CachetHQ\Cachet\Models\Incident;
use CachetHQ\Cachet\Bus\Commands\Schedule\CreateScheduleCommand;
use CachetHQ\Cachet\Bus\Commands\Schedule\DeleteScheduleCommand;
use CachetHQ\Cachet\Bus\Commands\Schedule\UpdateScheduleCommand;
use CachetHQ\Cachet\Models\IncidentTemplate;
use CachetHQ\Cachet\Models\Schedule;
use GrahamCampbell\Binput\Facades\Binput;
use Illuminate\Routing\Controller;
use Illuminate\Support\Facades\View;
use Illuminate\Support\MessageBag;
use Jenssegers\Date\Date;
/**
* This is the schedule controller class.
*
* @author James Brooks <james@alt-three.com>
*/
class ScheduleController extends Controller
{
/**
@@ -38,23 +42,7 @@ class ScheduleController extends Controller
*/
public function __construct()
{
$this->subMenu = [
'incidents' => [
'title' => trans('dashboard.incidents.incidents'),
'url' => cachet_route('dashboard.incidents'),
'icon' => 'ion-android-checkmark-circle',
'active' => false,
],
'schedule' => [
'title' => trans('dashboard.schedule.schedule'),
'url' => cachet_route('dashboard.schedule'),
'icon' => 'ion-android-calendar',
'active' => true,
],
];
View::share('sub_menu', $this->subMenu);
View::share('sub_title', trans('dashboard.incidents.title'));
View::share('sub_title', trans('dashboard.schedule.title'));
}
/**
@@ -64,7 +52,7 @@ class ScheduleController extends Controller
*/
public function showIndex()
{
$schedule = Incident::scheduled()->orderBy('created_at')->get();
$schedule = Schedule::orderBy('created_at')->get();
return View::make('dashboard.schedule.index')
->withPageTitle(trans('dashboard.schedule.schedule').' - '.trans('dashboard.dashboard'))
@@ -86,18 +74,20 @@ class ScheduleController extends Controller
}
/**
* Creates a new scheduled maintenance "incident".
* Creates a new scheduled maintenance.
*
* @return \Illuminate\Http\RedirectResponse
*/
public function addScheduleAction()
{
try {
$incident = dispatch(new ReportMaintenanceCommand(
dispatch(new CreateScheduleCommand(
Binput::get('name'),
Binput::get('message'),
Binput::get('notify'),
Binput::get('scheduled_at')
Binput::get('status', Schedule::UPCOMING),
Binput::get('scheduled_at'),
Binput::get('completed_at'),
Binput::get('components', [])
));
} catch (ValidationException $e) {
return cachet_redirect('dashboard.schedule.create')
@@ -113,11 +103,11 @@ class ScheduleController extends Controller
/**
* Shows the edit schedule maintenance form.
*
* @param \CachetHQ\Cachet\Models\Incident $schedule
* @param \CachetHQ\Cachet\Models\Schedule $schedule
*
* @return \Illuminate\View\View
*/
public function showEditSchedule(Incident $schedule)
public function showEditSchedule(Schedule $schedule)
{
$incidentTemplates = IncidentTemplate::all();
@@ -130,30 +120,22 @@ class ScheduleController extends Controller
/**
* Updates the given incident.
*
* @param \CachetHQ\Cachet\Models\Incident $schedule
* @param \CachetHQ\Cachet\Models\Schedule $schedule
*
* @return \Illuminate\Http\RedirectResponse
*/
public function editScheduleAction(Incident $schedule)
public function editScheduleAction(Schedule $schedule)
{
$scheduleData = Binput::get('incident');
// Parse the schedule date.
$scheduledAt = app(DateFactory::class)->create('d/m/Y H:i', $scheduleData['scheduled_at']);
if ($scheduledAt->isPast()) {
$messageBag = new MessageBag();
$messageBag->add('scheduled_at', trans('validation.date', ['attribute' => 'scheduled time you supplied']));
return cachet_redirect('dashboard.schedule.edit', [$schedule->id])->withErrors($messageBag);
}
$scheduleData['scheduled_at'] = $scheduledAt;
// Bypass the incident.status field.
$scheduleData['status'] = 0;
try {
$schedule->update($scheduleData);
$schedule = dispatch(new UpdateScheduleCommand(
$schedule,
Binput::get('name', null),
Binput::get('message', null),
Binput::get('status', null),
Binput::get('scheduled_at', null),
Binput::get('completed_at', null),
Binput::get('components', [])
));
} catch (ValidationException $e) {
return cachet_redirect('dashboard.schedule.edit', [$schedule->id])
->withInput(Binput::all())
@@ -168,13 +150,13 @@ class ScheduleController extends Controller
/**
* Deletes a given schedule.
*
* @param \CachetHQ\Cachet\Models\Incident $schedule
* @param \CachetHQ\Cachet\Models\Schedule $schedule
*
* @return \Illuminate\Http\RedirectResponse
*/
public function deleteScheduleAction(Incident $schedule)
public function deleteScheduleAction(Schedule $schedule)
{
$schedule->delete();
dispatch(new DeleteScheduleCommand($schedule));
return cachet_redirect('dashboard.schedule')
->withSuccess(sprintf('%s %s', trans('dashboard.notifications.awesome'), trans('dashboard.schedule.delete.success')));
+18 -6
View File
@@ -17,6 +17,7 @@ use CachetHQ\Cachet\Http\Controllers\Api\AbstractApiController;
use CachetHQ\Cachet\Models\Component;
use CachetHQ\Cachet\Models\Incident;
use CachetHQ\Cachet\Models\Metric;
use CachetHQ\Cachet\Models\Schedule;
use CachetHQ\Cachet\Repositories\Metric\MetricRepository;
use Exception;
use GrahamCampbell\Binput\Facades\Binput;
@@ -84,11 +85,11 @@ class StatusPageController extends AbstractApiController
$incidentVisibility = Auth::check() ? 0 : 1;
$allIncidents = Incident::notScheduled()->where('visible', '>=', $incidentVisibility)->whereBetween('occurred_at', [
$allIncidents = Incident::where('visible', '>=', $incidentVisibility)->whereBetween('occurred_at', [
$startDate->copy()->subDays($daysToShow)->format('Y-m-d').' 00:00:00',
$startDate->format('Y-m-d').' 23:59:59',
])->orderBy('scheduled_at', 'desc')->orderBy('occurred_at', 'desc')->get()->groupBy(function (Incident $incident) {
return app(DateFactory::class)->make($incident->is_scheduled ? $incident->scheduled_at : $incident->occurred_at)->toDateString();
])->orderBy('occurred_at', 'desc')->get()->groupBy(function (Incident $incident) {
return app(DateFactory::class)->make($incident->occurred_at)->toDateString();
});
// Add in days that have no incidents
@@ -111,7 +112,7 @@ class StatusPageController extends AbstractApiController
->withDaysToShow($daysToShow)
->withAllIncidents($allIncidents)
->withCanPageForward((bool) $today->gt($startDate))
->withCanPageBackward(Incident::notScheduled()->where('occurred_at', '<', $startDate->format('Y-m-d'))->count() > 0)
->withCanPageBackward(Incident::where('occurred_at', '<', $startDate->format('Y-m-d'))->count() > 0)
->withPreviousDate($startDate->copy()->subDays($daysToShow)->toDateString())
->withNextDate($startDate->copy()->addDays($daysToShow)->toDateString());
}
@@ -125,8 +126,19 @@ class StatusPageController extends AbstractApiController
*/
public function showIncident(Incident $incident)
{
return View::make('single-incident')
->withIncident($incident);
return View::make('single-incident')->withIncident($incident);
}
/**
* Show a single schedule.
*
* @param \CachetHQ\Cachet\Models\Schedule $schedule
*
* @return \Illuminate\View\View
*/
public function showSchedule(Schedule $schedule)
{
return View::make('single-schedule')->withSchedule($schedule);
}
/**
+6
View File
@@ -59,6 +59,9 @@ class ApiRoutes
$router->get('metrics', 'MetricController@getMetrics');
$router->get('metrics/{metric}', 'MetricController@getMetric');
$router->get('metrics/{metric}/points', 'MetricController@getMetricPoints');
$router->get('schedules', 'ScheduleController@getSchedules');
$router->get('schedules/{schedule}', 'ScheduleController@getSchedule');
});
$router->group(['middleware' => ['auth.api:true']], function (Registrar $router) {
@@ -70,6 +73,7 @@ class ApiRoutes
$router->post('incidents/{incident}/updates', 'IncidentUpdateController@postIncidentUpdate');
$router->post('metrics', 'MetricController@postMetrics');
$router->post('metrics/{metric}/points', 'MetricPointController@postMetricPoints');
$router->post('schedules', 'ScheduleController@postSchedule');
$router->post('subscribers', 'SubscriberController@postSubscribers');
$router->put('components/groups/{component_group}', 'ComponentGroupController@putGroup');
@@ -78,6 +82,7 @@ class ApiRoutes
$router->put('incidents/{incident}/updates/{update}', 'IncidentUpdateController@putIncidentUpdate');
$router->put('metrics/{metric}', 'MetricController@putMetric');
$router->put('metrics/{metric}/points/{metric_point}', 'MetricPointController@putMetricPoint');
$router->put('schedules/{schedule}', 'ScheduleController@putSchedule');
$router->delete('components/groups/{component_group}', 'ComponentGroupController@deleteGroup');
$router->delete('components/{component}', 'ComponentController@deleteComponent');
@@ -85,6 +90,7 @@ class ApiRoutes
$router->delete('incidents/{incident}/updates/{update}', 'IncidentUpdateController@deleteIncidentUpdate');
$router->delete('metrics/{metric}', 'MetricController@deleteMetric');
$router->delete('metrics/{metric}/points/{metric_point}', 'MetricPointController@deleteMetricPoint');
$router->delete('schedules/{schedule}', 'ScheduleController@deleteSchedule');
$router->delete('subscribers/{subscriber}', 'SubscriberController@deleteSubscriber');
$router->delete('subscriptions/{subscription}', 'SubscriberController@deleteSubscription');
});
+3 -3
View File
@@ -56,15 +56,15 @@ class ScheduleRoutes
'uses' => 'ScheduleController@addScheduleAction',
]);
$router->get('{incident}', [
$router->get('{schedule}', [
'as' => 'get:dashboard.schedule.edit',
'uses' => 'ScheduleController@showEditSchedule',
]);
$router->post('{incident}', [
$router->post('{schedule}', [
'as' => 'post:dashboard.schedule.edit',
'uses' => 'ScheduleController@editScheduleAction',
]);
$router->delete('{incident}', [
$router->delete('{schedule}', [
'as' => 'delete:dashboard.schedule.delete',
'uses' => 'ScheduleController@deleteScheduleAction',
]);
+5
View File
@@ -49,6 +49,11 @@ class StatusPageRoutes
'uses' => 'StatusPageController@showIncident',
]);
$router->get('schedules/{schedule}', [
'as' => 'get:schedule',
'uses' => 'StatusPageController@showSchedule',
]);
$router->get('metrics/{metric}', [
'as' => 'get:metric',
'uses' => 'StatusPageController@getMetrics',
+1 -1
View File
@@ -49,7 +49,7 @@ class System implements SystemContract
];
} elseif ($enabledScope->notStatus(1)->count() === 0) {
// If all our components are ok, do we have any non-fixed incidents?
$incidents = Incident::notScheduled()->orderBy('occurred_at', 'desc')->get()->filter(function ($incident) {
$incidents = Incident::orderBy('occurred_at', 'desc')->get()->filter(function ($incident) {
return $incident->status > 0;
});
$incidentCount = $incidents->count();
+4 -45
View File
@@ -15,7 +15,6 @@ use AltThree\Validator\ValidatingTrait;
use CachetHQ\Cachet\Models\Traits\SearchableTrait;
use CachetHQ\Cachet\Models\Traits\SortableTrait;
use CachetHQ\Cachet\Presenters\IncidentPresenter;
use Carbon\Carbon;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\SoftDeletes;
@@ -75,11 +74,10 @@ class Incident extends Model implements HasPresenter
* @var string[]
*/
protected $casts = [
'visible' => 'int',
'stickied' => 'bool',
'scheduled_at' => 'date',
'occurred_at' => 'date',
'deleted_at' => 'date',
'visible' => 'int',
'stickied' => 'bool',
'occurred_at' => 'date',
'deleted_at' => 'date',
];
/**
@@ -94,7 +92,6 @@ class Incident extends Model implements HasPresenter
'visible',
'stickied',
'message',
'scheduled_at',
'occurred_at',
'created_at',
'updated_at',
@@ -194,44 +191,6 @@ class Incident extends Model implements HasPresenter
return $query->where('stickied', '=', true);
}
/**
* Finds all scheduled incidents (maintenance).
*
* @param \Illuminate\Database\Eloquent\Builder $query
*
* @return \Illuminate\Database\Eloquent\Builder
*/
public function scopeScheduled(Builder $query)
{
return $query->where('status', '=', 0)->where('scheduled_at', '>=', Carbon::now());
}
/**
* Finds all non-scheduled incidents.
*
* @param \Illuminate\Database\Eloquent\Builder $query
*
* @return \Illuminate\Database\Eloquent\Builder
*/
public function scopeNotScheduled(Builder $query)
{
return $query->where('status', '>', 0)->orWhere(function ($query) {
$query->where('status', '=', 0)->where(function ($query) {
$query->whereNull('scheduled_at')->orWhere('scheduled_at', '<=', Carbon::now());
});
});
}
/**
* Returns whether the "incident" is scheduled or not.
*
* @return bool
*/
public function getIsScheduledAttribute()
{
return $this->getOriginal('scheduled_at') !== null;
}
/**
* Is the incident resolved?
*
+162
View File
@@ -0,0 +1,162 @@
<?php
/*
* This file is part of Cachet.
*
* (c) Alt Three Services Limited
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace CachetHQ\Cachet\Models;
use AltThree\Validator\ValidatingTrait;
use CachetHQ\Cachet\Models\Traits\SearchableTrait;
use CachetHQ\Cachet\Models\Traits\SortableTrait;
use CachetHQ\Cachet\Presenters\SchedulePresenter;
use Carbon\Carbon;
use Illuminate\Database\Eloquent\Model;
use McCool\LaravelAutoPresenter\HasPresenter;
class Schedule extends Model implements HasPresenter
{
use SearchableTrait, SortableTrait, ValidatingTrait;
/**
* The upcoming status.
*
* @var int
*/
const UPCOMING = 0;
/**
* The in progress status.
*
* @var int
*/
const IN_PROGRESS = 1;
/**
* The complete status.
*
* @var int
*/
const COMPLETE = 2;
/**
* The attributes that should be casted to native types.
*
* @var string[]
*/
protected $casts = [
'name' => 'string',
'message' => 'string',
'status' => 'int',
'scheduled_at' => 'date',
'completed_at' => 'date',
];
/**
* The fillable properties.
*
* @var string[]
*/
protected $fillable = [
'name',
'message',
'status',
'scheduled_at',
'completed_at',
'created_at',
'updated_at',
];
/**
* The validation rules.
*
* @var string[]
*/
public $rules = [
'name' => 'required|string',
'message' => 'nullable|string',
'status' => 'required|int|between:0,2',
];
/**
* The searchable fields.
*
* @var string[]
*/
protected $searchable = [
'id',
'name',
'status',
];
/**
* The sortable fields.
*
* @var string[]
*/
protected $sortable = [
'id',
'name',
'status',
'scheduled_at',
'completed_at',
'created_at',
'updated_at',
];
/**
* The relations to eager load on every query.
*
* @var string[]
*/
protected $with = ['components'];
/**
* Scopes schedules to those in the future.
*
* @param \Illuminate\Database\Eloquent\Builder $query
*
* @return \Illuminate\Database\Eloquent\Builder
*/
public function scopeFutureSchedules($query)
{
return $query->whereIn('status', [self::UPCOMING, self::IN_PROGRESS])->where('scheduled_at', '>=', Carbon::now());
}
/**
* Scopes schedules to those in the past.
*
* @param \Illuminate\Database\Eloquent\Builder $query
*
* @return \Illuminate\Database\Eloquent\Builder
*/
public function scopePastSchedules($query)
{
return $query->where('status', '<', self::COMPLETE)->where('scheduled_at', '<=', Carbon::now());
}
/**
* Get the components relation.
*
* @return \Illuminate\Database\Eloquent\Relations\HasMany
*/
public function components()
{
return $this->hasMany(ScheduleComponent::class);
}
/**
* Get the presenter class.
*
* @return string
*/
public function getPresenterClass()
{
return SchedulePresenter::class;
}
}
+73
View File
@@ -0,0 +1,73 @@
<?php
/*
* This file is part of Cachet.
*
* (c) Alt Three Services Limited
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace CachetHQ\Cachet\Models;
use AltThree\Validator\ValidatingTrait;
use Illuminate\Database\Eloquent\Model;
class ScheduleComponent extends Model
{
use ValidatingTrait;
/**
* The attributes that should be casted to native types.
*
* @var string[]
*/
protected $casts = [
'schedule_id' => 'int',
'component_id' => 'int',
'component_status' => 'int',
];
/**
* The fillable properties.
*
* @var string[]
*/
protected $fillable = [
'schedule_id',
'component_id',
'component_status',
];
/**
* The validation rules.
*
* @var string[]
*/
public $rules = [
'schedule_id' => 'required|int',
'component_id' => 'required|int',
'component_status' => 'required|int',
];
/**
* Get the schedule relation.
*
* @return \Illuminate\Database\Eloquent\Relations\BelongsTo
*/
public function schedule()
{
return $this->belongsTo(Schedule::class);
}
/**
* Get the component relation.
*
* @return \Illuminate\Database\Eloquent\Relations\HasOne
*/
public function component()
{
return $this->hasOne(Component::class);
}
}
-59
View File
@@ -157,56 +157,6 @@ class IncidentPresenter extends BasePresenter implements Arrayable
return $this->dates->make($this->wrappedObject->created_at)->toISO8601String();
}
/**
* Present formatted date time.
*
* @return string
*/
public function scheduled_at()
{
return $this->dates->make($this->wrappedObject->scheduled_at)->toDateTimeString();
}
/**
* Present diff for humans date time.
*
* @return string
*/
public function scheduled_at_diff()
{
return $this->dates->make($this->wrappedObject->scheduled_at)->diffForHumans();
}
/**
* Present formatted date time.
*
* @return string
*/
public function scheduled_at_formatted()
{
return ucfirst($this->dates->make($this->wrappedObject->scheduled_at)->format($this->incidentDateFormat()));
}
/**
* Present formatted date time.
*
* @return string
*/
public function scheduled_at_iso()
{
return $this->dates->make($this->wrappedObject->scheduled_at)->toISO8601String();
}
/**
* Formats the scheduled_at time ready to be used by bootstrap-datetimepicker.
*
* @return string
*/
public function scheduled_at_datetimepicker()
{
return $this->dates->make($this->wrappedObject->scheduled_at)->format('d/m/Y H:i');
}
/**
* Returns a formatted timestamp for use within the timeline.
*
@@ -214,10 +164,6 @@ class IncidentPresenter extends BasePresenter implements Arrayable
*/
public function timestamp_formatted()
{
if ($this->wrappedObject->is_scheduled) {
return $this->scheduled_at_formatted;
}
return $this->occurred_at_formatted;
}
@@ -228,10 +174,6 @@ class IncidentPresenter extends BasePresenter implements Arrayable
*/
public function timestamp_iso()
{
if ($this->wrappedObject->is_scheduled) {
return $this->scheduled_at_iso;
}
return $this->occurred_at_iso;
}
@@ -352,7 +294,6 @@ class IncidentPresenter extends BasePresenter implements Arrayable
'latest_icon' => $this->latest_icon(),
'permalink' => $this->permalink(),
'duration' => $this->duration(),
'scheduled_at' => $this->scheduled_at(),
'occurred_at' => $this->occurred_at(),
'created_at' => $this->created_at(),
'updated_at' => $this->updated_at(),
+261
View File
@@ -0,0 +1,261 @@
<?php
/*
* This file is part of Cachet.
*
* (c) Alt Three Services Limited
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace CachetHQ\Cachet\Presenters;
use CachetHQ\Cachet\Dates\DateFactory;
use CachetHQ\Cachet\Models\Schedule;
use CachetHQ\Cachet\Presenters\Traits\TimestampsTrait;
use GrahamCampbell\Markdown\Facades\Markdown;
use Illuminate\Contracts\Support\Arrayable;
use McCool\LaravelAutoPresenter\BasePresenter;
/**
* This is the schedule presenter class.
*
* @author James Brooks <james@alt-three.com>
*/
class SchedulePresenter extends BasePresenter implements Arrayable
{
use TimestampsTrait;
/**
* The date factory instance.
*
* @var \CachetHQ\Cachet\Dates\DateFactory
*/
protected $dates;
/**
* Create a new presenter.
*
* @param \CachetHQ\Cachet\Dates\DateFactory $dates
* @param \CachetHQ\Cachet\Models\Schedule $resource
*
* @return void
*/
public function __construct(DateFactory $dates, Schedule $resource)
{
$this->dates = $dates;
parent::__construct($resource);
}
/**
* Renders the message from Markdown into HTML.
*
* @return string
*/
public function formattedMessage()
{
return Markdown::convertToHtml($this->wrappedObject->message);
}
/**
* Present diff for humans date time.
*
* @return string
*/
public function created_at_diff()
{
return $this->dates->make($this->wrappedObject->created_at)->diffForHumans();
}
/**
* Present formatted date time.
*
* @return string
*/
public function created_at_formatted()
{
return ucfirst($this->dates->make($this->wrappedObject->created_at)->format($this->incidentDateFormat()));
}
/**
* Formats the created_at time ready to be used by bootstrap-datetimepicker.
*
* @return string
*/
public function created_at_datetimepicker()
{
return $this->dates->make($this->wrappedObject->created_at)->format('Y-m-d H:i');
}
/**
* Present formatted date time.
*
* @return string
*/
public function created_at_iso()
{
return $this->dates->make($this->wrappedObject->created_at)->toISO8601String();
}
/**
* Present formatted date time.
*
* @return string
*/
public function scheduled_at()
{
return $this->dates->make($this->wrappedObject->scheduled_at)->toDateTimeString();
}
/**
* Present diff for humans date time.
*
* @return string
*/
public function scheduled_at_diff()
{
return $this->dates->make($this->wrappedObject->scheduled_at)->diffForHumans();
}
/**
* Present formatted date time.
*
* @return string
*/
public function scheduled_at_formatted()
{
return ucfirst($this->dates->make($this->wrappedObject->scheduled_at)->format($this->incidentDateFormat()));
}
/**
* Present formatted date time.
*
* @return string
*/
public function scheduled_at_iso()
{
return $this->dates->make($this->wrappedObject->scheduled_at)->toISO8601String();
}
/**
* Formats the scheduled_at time ready to be used by bootstrap-datetimepicker.
*
* @return string
*/
public function scheduled_at_datetimepicker()
{
return $this->dates->make($this->wrappedObject->scheduled_at)->format('Y-m-d H:i');
}
/**
* Returns a formatted timestamp for use within the timeline.
*
* @return string
*/
public function timestamp_formatted()
{
if ($this->wrappedObject->is_scheduled) {
return $this->scheduled_at_formatted;
}
return $this->created_at_formatted;
}
/**
* Present formatted date time.
*
* @return string
*/
public function completed_at()
{
return $this->dates->make($this->wrappedObject->completed_at)->toDateTimeString();
}
/**
* Present diff for humans date time.
*
* @return string
*/
public function completed_at_diff()
{
return $this->dates->make($this->wrappedObject->completed_at)->diffForHumans();
}
/**
* Present formatted date time.
*
* @return string
*/
public function completed_at_formatted()
{
return ucfirst($this->dates->make($this->wrappedObject->completed_at)->format($this->incidentDateFormat()));
}
/**
* Present formatted date time.
*
* @return string
*/
public function completed_at_iso()
{
return $this->dates->make($this->wrappedObject->completed_at)->toISO8601String();
}
/**
* Formats the completed_at time ready to be used by bootstrap-datetimepicker.
*
* @return string
*/
public function completed_at_datetimepicker()
{
return $this->dates->make($this->wrappedObject->completed_at)->format('Y-m-d H:i');
}
/**
* Return the iso timestamp for use within the timeline.
*
* @return string
*/
public function timestamp_iso()
{
if ($this->wrappedObject->is_scheduled) {
return $this->scheduled_at_iso;
}
return $this->completed_at_iso;
}
/**
* Returns a human readable version of the status.
*
* @return string
*/
public function human_status()
{
// return trans('cachet.incidents.status.'.$this->wrappedObject->status);
// TODO: Refactor into translations.
switch ($this->wrappedObject->status) {
case 0: return 'Upcoming';
case 1: return 'In Progress';
case 2: return 'Complete';
}
}
/**
* Convert the presenter instance to an array.
*
* @return string[]
*/
public function toArray()
{
return array_merge($this->wrappedObject->toArray(), [
'human_status' => $this->human_status(),
'scheduled_at' => $this->scheduled_at(),
'completed_at' => $this->completed_at(),
'created_at' => $this->created_at(),
'updated_at' => $this->updated_at(),
]);
}
}