diff --git a/public/build/manifest.json b/public/build/manifest.json index 0a1c654f..d692ffcd 100644 --- a/public/build/manifest.json +++ b/public/build/manifest.json @@ -1,18 +1,17 @@ { - "resources/css/cachet.css": { - "file": "assets/cachet-D-feVIY7.css", - "src": "resources/css/cachet.css", + "resources/js/cachet.js": { + "file": "assets/cachet.6122e927.js", + "src": "resources/js/cachet.js", "isEntry": true }, "resources/css/dashboard/theme.css": { - "file": "assets/theme-C6ZKRDAs.css", + "file": "assets/theme.8251fad4.css", "src": "resources/css/dashboard/theme.css", "isEntry": true }, - "resources/js/cachet.js": { - "file": "assets/cachet-DCZQ8JcZ.js", - "name": "cachet", - "src": "resources/js/cachet.js", + "resources/css/cachet.css": { + "file": "assets/cachet.30cb9e62.css", + "src": "resources/css/cachet.css", "isEntry": true } } \ No newline at end of file diff --git a/resources/views/components/incident.blade.php b/resources/views/components/incident.blade.php index 5548b27e..d8d9d9db 100644 --- a/resources/views/components/incident.blade.php +++ b/resources/views/components/incident.blade.php @@ -4,9 +4,7 @@ 'incidents', ]) -
-

- @forelse($incidents as $incident) + @foreach($incidents as $incident)
- @empty -
-
-
- {{ __('No incidents reported.') }} -
-
-
- @endforelse -
+ @endforeach 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 1ec66c48..1abb3c1b 100644 --- a/resources/views/components/schedule.blade.php +++ b/resources/views/components/schedule.blade.php @@ -13,6 +13,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 66% rename from resources/views/components/incident-timeline.blade.php rename to resources/views/components/timeline.blade.php index cda4b2d0..55a4107b 100644 --- a/resources/views/components/incident-timeline.blade.php +++ b/resources/views/components/timeline.blade.php @@ -29,13 +29,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/Models/Schedule.php b/src/Models/Schedule.php index bbbb5b2f..492e67f1 100644 --- a/src/Models/Schedule.php +++ b/src/Models/Schedule.php @@ -4,6 +4,7 @@ use Cachet\Database\Factories\ScheduleFactory; 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\Factory; @@ -113,6 +114,19 @@ public function scopeInThePast(Builder $query): Builder return $query->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); + } + /** * Create a new factory instance for the model. */ diff --git a/src/View/Components/IncidentTimeline.php b/src/View/Components/Timeline.php similarity index 65% rename from src/View/Components/IncidentTimeline.php rename to src/View/Components/Timeline.php index c9cfeab6..6921a4d0 100644 --- a/src/View/Components/IncidentTimeline.php +++ b/src/View/Components/Timeline.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; @@ -10,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) { @@ -23,12 +24,17 @@ 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, $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(), @@ -72,4 +78,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(); + } }