From c516deb488c0a11bfea4923c9533464695563304 Mon Sep 17 00:00:00 2001 From: steffjenl Date: Sun, 13 Oct 2024 12:58:31 +0200 Subject: [PATCH 1/3] Add schedule with status completed to incident timeline #93 --- .../components/incident-timeline.blade.php | 2 +- resources/views/components/incident.blade.php | 58 ++++++++++++++++++- src/Models/Schedule.php | 15 +++++ src/View/Components/IncidentTimeline.php | 35 +++++++++++ 4 files changed, 106 insertions(+), 4 deletions(-) diff --git a/resources/views/components/incident-timeline.blade.php b/resources/views/components/incident-timeline.blade.php index 83b22954..f4141a41 100644 --- a/resources/views/components/incident-timeline.blade.php +++ b/resources/views/components/incident-timeline.blade.php @@ -11,7 +11,7 @@
@forelse ($incidents as $date => $incident) - + @empty
{{ __('No incidents reported between :from and :to.', ['from' => $from, 'to' => $to]) }} diff --git a/resources/views/components/incident.blade.php b/resources/views/components/incident.blade.php index 33f731db..1166576f 100644 --- a/resources/views/components/incident.blade.php +++ b/resources/views/components/incident.blade.php @@ -2,11 +2,15 @@ @props([ 'date', 'incidents', + 'schedules', ]) +@php($empty = true) +

- @forelse($incidents as $incident) + @foreach($incidents as $incident) + @php($empty = false)
- @empty + @endforeach + @foreach($schedules[$date] as $schedule) + @php($empty = false) +
+
+ @if ($schedule->components()->exists()) +
+ {{ $schedule->components()->pluck('name')->join(', ', ' and ') }} +
+ @endif +
+
+
+

+ {{ $schedule->name}} +

+ @auth + + + + @endauth +
+ + {{ $schedule->completed_at->diffForHumans() }} — + +
+
+ +
+
+
+
+
+
+
+
+
+
+
+
{!! $schedule->formattedMessage() !!}
+
+
+
+
+ @endforeach + @if($empty)
{{ __('No incidents reported.') }}
- @endforelse + @endif
diff --git a/src/Models/Schedule.php b/src/Models/Schedule.php index 900c8dba..1262ef23 100644 --- a/src/Models/Schedule.php +++ b/src/Models/Schedule.php @@ -3,7 +3,9 @@ namespace Cachet\Models; use Cachet\Enums\ScheduleStatusEnum; +use Cachet\Filament\Resources\ScheduleResource; use Illuminate\Database\Eloquent\Builder; +use Illuminate\Database\Eloquent\Casts\Attribute; use Illuminate\Database\Eloquent\Factories\HasFactory; use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\Relations\BelongsToMany; @@ -93,4 +95,17 @@ public function scopeCompletedPreviously(Builder $query): Builder return $query->where('status', '=', ScheduleStatusEnum::complete) ->where('completed_at', '<=', Carbon::now()); } + + /** + * Get the URL to the schedule page within the dashboard. + */ + public function filamentDashboardEditUrl(): string + { + return ScheduleResource::getUrl(name: 'edit', parameters: ['record' => $this->id]); + } + + public function timestamp(): Attribute + { + return Attribute::get(fn () => $this->completed_at ?: $this->scheduled_at); + } } diff --git a/src/View/Components/IncidentTimeline.php b/src/View/Components/IncidentTimeline.php index 4e86df11..521b39eb 100644 --- a/src/View/Components/IncidentTimeline.php +++ b/src/View/Components/IncidentTimeline.php @@ -3,6 +3,7 @@ namespace Cachet\View\Components; use Cachet\Models\Incident; +use Cachet\Models\Schedule; use Cachet\Settings\AppSettings; use Illuminate\Contracts\View\View; use Illuminate\Database\Eloquent\Builder; @@ -29,6 +30,11 @@ public function render(): View $endDate, $this->appSettings->only_disrupted_days ), + 'schedules' => $this->schedules( + $startDate, + $endDate, + $this->appSettings->only_disrupted_days + ), 'from' => $startDate->toDateString(), 'to' => $endDate->toDateString(), 'nextPeriodFrom' => $startDate->clone()->subDays($incidentDays + 1)->toDateString(), @@ -73,4 +79,33 @@ private function incidents(Carbon $startDate, Carbon $endDate, bool $onlyDisrupt ->when($onlyDisruptedDays, fn ($collection) => $collection->filter(fn ($incidents) => $incidents->isNotEmpty())) ->sortKeysDesc(); } + + /** + * Fetch the schedules that occurred between the given start and end date. + * Schedules will be grouped by days. + */ + private function schedules(Carbon $startDate, Carbon $endDate, bool $onlyDisruptedDays = false): Collection + { + return Schedule::query() + ->with([ + 'components', + ]) + ->where(function (Builder $query) use ($endDate, $startDate) { + $query->whereBetween('completed_at', [ + $endDate->startOfDay()->toDateTimeString(), + $startDate->endofDay()->toDateTimeString(), + ]); + }) + ->orderBy('completed_at', 'desc') + ->get() + ->groupBy(fn (Schedule $schedule) => $schedule->completed_at->toDateString()) + ->union( + // Back-fill any missing dates... + collect($endDate->toPeriod($startDate)) + ->keyBy(fn ($period) => $period->toDateString()) + ->map(fn ($period) => collect()) + ) + ->when($onlyDisruptedDays, fn ($collection) => $collection->filter(fn ($schedules) => $schedules->isNotEmpty())) + ->sortKeysDesc(); + } } From bd44346d3725575e2c87a28c14baf52e7eb4e8b4 Mon Sep 17 00:00:00 2001 From: steffjenl Date: Sun, 13 Oct 2024 19:15:38 +0000 Subject: [PATCH 2/3] Compile Assets --- public/build/manifest.json | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/public/build/manifest.json b/public/build/manifest.json index eb93cbf8..d692ffcd 100644 --- a/public/build/manifest.json +++ b/public/build/manifest.json @@ -4,14 +4,14 @@ "src": "resources/js/cachet.js", "isEntry": true }, - "resources/css/cachet.css": { - "file": "assets/cachet.30cb9e62.css", - "src": "resources/css/cachet.css", - "isEntry": true - }, "resources/css/dashboard/theme.css": { "file": "assets/theme.8251fad4.css", "src": "resources/css/dashboard/theme.css", "isEntry": true + }, + "resources/css/cachet.css": { + "file": "assets/cachet.30cb9e62.css", + "src": "resources/css/cachet.css", + "isEntry": true } } \ No newline at end of file From 0e44bfc01ab02c62dcf495bd345893bd8f3ba558 Mon Sep 17 00:00:00 2001 From: steffjenl Date: Sun, 13 Oct 2024 22:28:33 +0200 Subject: [PATCH 3/3] Split incidents and schedules and rename to timeline and add edit button for schedules --- resources/views/components/incident.blade.php | 63 ------------------- .../components/schedule-timeline.blade.php | 43 +++++++++++++ resources/views/components/schedule.blade.php | 5 ++ ...-timeline.blade.php => timeline.blade.php} | 21 +++++-- resources/views/status-page/index.blade.php | 2 +- .../{IncidentTimeline.php => Timeline.php} | 4 +- 6 files changed, 66 insertions(+), 72 deletions(-) create mode 100644 resources/views/components/schedule-timeline.blade.php rename resources/views/components/{incident-timeline.blade.php => timeline.blade.php} (60%) rename src/View/Components/{IncidentTimeline.php => Timeline.php} (97%) diff --git a/resources/views/components/incident.blade.php b/resources/views/components/incident.blade.php index 5bbc5dac..4da7deac 100644 --- a/resources/views/components/incident.blade.php +++ b/resources/views/components/incident.blade.php @@ -2,15 +2,9 @@ @props([ 'date', 'incidents', - 'schedules', ]) -@php($empty = true) - -
-

@foreach($incidents as $incident) - @php($empty = false)
@endforeach - @foreach($schedules[$date] as $schedule) - @php($empty = false) -
-
- @if ($schedule->components()->exists()) -
- {{ $schedule->components()->pluck('name')->join(', ', ' and ') }} -
- @endif -
-
-
-

- {{ $schedule->name}} -

- @auth - - - - @endauth -
- - {{ $schedule->completed_at->diffForHumans() }} — - -
-
- -
-
-
-
-
-
-
-
-
-
-
-
{!! $schedule->formattedMessage() !!}
-
-
-
-
- @endforeach - @if($empty) -
-
-
- {{ __('No incidents reported.') }} -
-
-
- @endif -
diff --git a/resources/views/components/schedule-timeline.blade.php b/resources/views/components/schedule-timeline.blade.php new file mode 100644 index 00000000..7225c677 --- /dev/null +++ b/resources/views/components/schedule-timeline.blade.php @@ -0,0 +1,43 @@ +@use('Cachet\Enums\ScheduleStatusEnum') +@props([ + 'date', + 'schedules', +]) + + @foreach($schedules as $schedule) +
+
+
+
+
+

+ {{ $schedule->name}} +

+ @auth + + + + @endauth +
+ + {{ $schedule->completed_at->diffForHumans() }} — + +
+
+ +
+
+
+ +
+
+
+
{!! $schedule->formattedMessage() !!}
+
+
+
+
+ @endforeach diff --git a/resources/views/components/schedule.blade.php b/resources/views/components/schedule.blade.php index f06218d9..09e5766f 100644 --- a/resources/views/components/schedule.blade.php +++ b/resources/views/components/schedule.blade.php @@ -12,6 +12,11 @@ {{ $schedule->scheduled_at->diffForHumans() }} —
+ @auth + + + + @endauth
diff --git a/resources/views/components/incident-timeline.blade.php b/resources/views/components/timeline.blade.php similarity index 60% rename from resources/views/components/incident-timeline.blade.php rename to resources/views/components/timeline.blade.php index f4141a41..61e87c33 100644 --- a/resources/views/components/incident-timeline.blade.php +++ b/resources/views/components/timeline.blade.php @@ -10,13 +10,22 @@
- @forelse ($incidents as $date => $incident) - - @empty -
- {{ __('No incidents reported between :from and :to.', ['from' => $from, 'to' => $to]) }} + @foreach ($incidents as $date => $incident) +
+

+ + + @if(count($incident) === 0 && count($schedules[$date]) === 0) +
+
+
+ {{ __('No incidents reported.') }} +
+
+
+ @endif + @endforeach
- @endforelse
diff --git a/resources/views/status-page/index.blade.php b/resources/views/status-page/index.blade.php index 5fef4e98..6d076988 100644 --- a/resources/views/status-page/index.blade.php +++ b/resources/views/status-page/index.blade.php @@ -18,7 +18,7 @@ @endif - +
diff --git a/src/View/Components/IncidentTimeline.php b/src/View/Components/Timeline.php similarity index 97% rename from src/View/Components/IncidentTimeline.php rename to src/View/Components/Timeline.php index 521b39eb..a7a6e729 100644 --- a/src/View/Components/IncidentTimeline.php +++ b/src/View/Components/Timeline.php @@ -11,7 +11,7 @@ use Illuminate\Support\Collection; use Illuminate\View\Component; -class IncidentTimeline extends Component +class Timeline extends Component { public function __construct(private AppSettings $appSettings) { @@ -24,7 +24,7 @@ public function render(): View $startDate = Carbon::createFromFormat('Y-m-d', request('from', now()->toDateString())); $endDate = $startDate->clone()->subDays($incidentDays); - return view('cachet::components.incident-timeline', [ + return view('cachet::components.timeline', [ 'incidents' => $this->incidents( $startDate, $endDate,