Skip to content

Commit 00cf9bc

Browse files
authored
[6.x] Critical updates visibility (#14202)
1 parent ae9f388 commit 00cf9bc

12 files changed

Lines changed: 382 additions & 28 deletions

File tree

resources/js/components/UpdatesBadge.vue

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,13 @@
11
<template>
2-
<Badge v-if="count" :text="String(count)" color="amber" size="sm" pill />
2+
<Badge v-if="count" :text="String(count)" :color="critical ? 'red' : 'amber'" size="sm" pill />
33
</template>
44

55
<script>
66
import { ref } from 'vue';
77
import { Badge } from '@/components/ui';
88
9-
const count = ref(null);
9+
const countRef = ref(null);
10+
const criticalRef = ref(false);
1011
const requested = ref(false);
1112
1213
export default {
@@ -16,7 +17,10 @@ export default {
1617
1718
computed: {
1819
count() {
19-
return count.value;
20+
return countRef.value;
21+
},
22+
critical() {
23+
return criticalRef.value;
2024
},
2125
},
2226
@@ -30,7 +34,10 @@ export default {
3034
3135
this.$axios
3236
.get(cp_url('updater/count'))
33-
.then((response) => (count.value = !isNaN(response.data) ? response.data : 0));
37+
.then((response) => {
38+
countRef.value = response.data?.count ?? 0;
39+
criticalRef.value = response.data?.critical ?? false;
40+
});
3441
3542
requested.value = true;
3643
},

resources/js/components/updater/Release.vue

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,10 @@
22
<ui-panel>
33
<ui-panel-header class="flex items-center justify-between">
44
<div>
5-
<ui-heading :text="release.version" />
5+
<div class="flex items-center gap-2">
6+
<ui-heading :text="release.version" />
7+
<ui-badge v-if="release.critical" :text="__('Critical')" color="red" size="sm" />
8+
</div>
69
<ui-subheading :text="`${__('Released on :date', { date })}`" />
710
</div>
811
<ui-modal :title="__('Update to :version', { version: release.version })" blur>

resources/js/components/updater/Updater.vue

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,10 @@
22
<div class="max-w-page mx-auto">
33
<ui-header :title="name" icon="updates">
44
<template v-if="!gettingChangelog" #actions>
5-
<ui-badge :prepend="__('Version')" :text="currentVersion" :color="onLatestVersion ? 'green' : 'amber'" size="lg" />
6-
<div v-if="onLatestVersion" v-text="__('Up to date')" />
5+
{{ currentVersion }}
6+
<ui-badge v-if="onLatestVersion" :text="__('Up to date')" color="green" size="lg" icon="checkmark" />
7+
<ui-badge v-else-if="criticalUpdateAvailable" :text="__('Critical update available')" color="red" size="lg" icon="alert-warning-exclamation-mark" />
8+
<ui-badge v-else :text="__('Update available')" color="amber" size="lg" icon="alert-warning-exclamation-mark" />
79
</template>
810
</ui-header>
911

@@ -93,6 +95,12 @@ export default {
9395
return this.currentVersion && this.currentVersion == this.latestVersion;
9496
},
9597
98+
criticalUpdateAvailable() {
99+
return this.currentVersion && this.changelog
100+
.filter((release) => release.type === 'upgrade')
101+
.some((release) => release.critical);
102+
},
103+
96104
licensedReleases() {
97105
return this.changelog.filter((release) => release.licensed);
98106
},

resources/js/components/updater/UpdaterWidget.vue

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -18,10 +18,12 @@ defineProps({
1818
<Link :href="update.url" class="flex items-center gap-2" v-text="update.name" />
1919
</td>
2020
<td>
21-
<Badge pill :color="update.critical ? 'red' : 'amber'" :text="update.count" />
22-
<div class="inline-flex" v-tooltip="__('Critical')">
23-
<Icon v-if="update.critical" name="warning-diamond" color="red" />
24-
</div>
21+
<Badge
22+
pill
23+
:text="update.count"
24+
:color="update.critical ? 'red' : 'amber'"
25+
v-tooltip="update.critical ? __('Critical update available') : null"
26+
/>
2527
</td>
2628
</tr>
2729
</table>

resources/js/pages/updater/Index.vue

Lines changed: 19 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,15 +2,22 @@
22
import { Link } from '@inertiajs/vue3';
33
import Head from '@/pages/layout/Head.vue';
44
import { Header, Card, Panel, Table, TableRow, TableCell, Badge, Heading, Button, DocsCallout, CommandPaletteItem } from '@ui';
5+
import { computed } from 'vue';
56
6-
defineProps(['requestError', 'statamic', 'addons']);
7+
const props = defineProps(['requestError', 'statamic', 'addons']);
8+
9+
const criticalUpdateAvailable = computed(() => props.statamic.critical || props.addons.some(addon => addon.critical));
710
</script>
811

912
<template>
1013
<Head :title="__('Updates')" />
1114

1215
<div class="max-w-page mx-auto">
13-
<Header :title="__('Updates')" icon="updates" />
16+
<Header :title="__('Updates')" icon="updates">
17+
<template #actions>
18+
<Badge v-if="criticalUpdateAvailable" :text="__('Critical update available')" color="red" size="lg" icon="alert-warning-exclamation-mark" />
19+
</template>
20+
</Header>
1421

1522
<Card v-if="requestError" class="w-full space-y-4 flex items-center justify-between">
1623
<Heading size="lg" class="mb-0!" :text="__('statamic::messages.outpost_issue_try_later')" icon="warning-diamond" />
@@ -38,7 +45,11 @@ defineProps(['requestError', 'statamic', 'addons']);
3845
</TableCell>
3946
<TableCell>{{ statamic.currentVersion }}</TableCell>
4047
<TableCell v-if="statamic.availableUpdatesCount" class="text-right">
41-
<Badge size="sm" color="amber">{{ __n('1 update|:count updates', statamic.availableUpdatesCount) }}</Badge>
48+
<Badge
49+
size="sm"
50+
:text="__n('1 update|:count updates', statamic.availableUpdatesCount)"
51+
:color="statamic.critical ? 'red' : 'amber'"
52+
/>
4253
</TableCell>
4354
<TableCell v-else class="text-right">{{ __('Up to date') }}</TableCell>
4455
</TableRow>
@@ -63,7 +74,11 @@ defineProps(['requestError', 'statamic', 'addons']);
6374
</TableCell>
6475
<TableCell>{{ addon.version }}</TableCell>
6576
<TableCell v-if="addon.availableUpdatesCount" class="text-right">
66-
<Badge size="sm" color="amber">{{ __n('1 update|:count updates', addon.availableUpdatesCount) }}</Badge>
77+
<Badge
78+
size="sm"
79+
:text="__n('1 update|:count updates', addon.availableUpdatesCount)"
80+
:color="addon.critical ? 'red' : 'amber'"
81+
/>
6782
</TableCell>
6883
<TableCell v-else class="text-right">{{ __('Up to date') }}</TableCell>
6984
</TableRow>

resources/views/nav/updates.blade.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
<li>
2-
<inertia-link href="{{ $item->url() }}" class="flex items-centerb gap-2 sm:gap-3 {{ $item->isActive() ? 'active' : '' }}">
2+
<inertia-link href="{{ $item->url() }}" class="flex items-center gap-2 sm:gap-3 {{ $item->isActive() ? 'active' : '' }}">
33
@cp_svg('icons/updates', 'size-4 shrink-0')
44
<span v-pre>{{ __($item->name()) }}</span>
55
<updates-badge class="-ml-1.5"></updates-badge>

src/Http/Controllers/CP/Updater/UpdaterController.php

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,12 +33,14 @@ public function index(Licenses $licenses)
3333
'statamic' => [
3434
'currentVersion' => $changelog->currentVersion(),
3535
'availableUpdatesCount' => $changelog->availableUpdatesCount(),
36+
'critical' => $changelog->hasCriticalUpdate(),
3637
],
3738
'addons' => $addons->filter->existsOnMarketplace()->map(fn ($addon) => [
3839
'name' => $addon->name(),
3940
'slug' => $addon->slug(),
4041
'version' => $addon->version(),
4142
'availableUpdatesCount' => $addon->changelog()->availableUpdatesCount(),
43+
'critical' => $addon->changelog()->hasCriticalUpdate(),
4244
])->values()->all(),
4345
]);
4446
}
@@ -50,6 +52,6 @@ public function count(Request $request)
5052
{
5153
$this->authorize('view updates');
5254

53-
return UpdatesOverview::count();
55+
return UpdatesOverview::badge();
5456
}
5557
}

src/Updater/Changelog.php

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,7 @@ protected function transformReleases($releases, $page = 1)
7070
'licensed' => $this->isLicensed($release['version']),
7171
'date' => Carbon::parse($release['date'])->toIso8601String(),
7272
'body' => $release['changelog'],
73+
'critical' => $release['critical'] ?? false,
7374
];
7475
});
7576
}
@@ -86,6 +87,18 @@ public function availableUpdatesCount()
8687
})->count();
8788
}
8889

90+
/**
91+
* Check if any available upgrade is marked as critical.
92+
*
93+
* @return bool
94+
*/
95+
public function hasCriticalUpdate()
96+
{
97+
return $this->get()->contains(function ($release) {
98+
return $release->type === 'upgrade' && $release->critical;
99+
});
100+
}
101+
89102
/**
90103
* Get latest release.
91104
*

src/Updater/UpdatesOverview.php

Lines changed: 41 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ class UpdatesOverview
1515

1616
protected $count;
1717
protected $statamic;
18+
protected $critical;
1819
protected $addons;
1920

2021
/**
@@ -47,6 +48,29 @@ public function updatableAddons()
4748
return $this->getCached('updates-overview.addons');
4849
}
4950

51+
/**
52+
* Check if a critical update is available (Statamic or any addon).
53+
*
54+
* @return bool
55+
*/
56+
public function hasCriticalUpdate()
57+
{
58+
return $this->getCached('updates-overview.critical');
59+
}
60+
61+
/**
62+
* Get badge data (count and whether there is a critical update).
63+
*
64+
* @return array{count: int, critical: bool}
65+
*/
66+
public function badge()
67+
{
68+
return [
69+
'count' => $this->count(),
70+
'critical' => $this->hasCriticalUpdate(),
71+
];
72+
}
73+
5074
/**
5175
* Get value from cache.
5276
*
@@ -83,6 +107,7 @@ protected function resetState()
83107
{
84108
$this->count = 0;
85109
$this->statamic = false;
110+
$this->critical = false;
86111
$this->addons = [];
87112

88113
return $this;
@@ -106,6 +131,10 @@ protected function checkForStatamicUpdates()
106131
$this->count++;
107132
}
108133

134+
if ($this->statamic && Marketplace::statamic()->changelog()->hasCriticalUpdate()) {
135+
$this->critical = true;
136+
}
137+
109138
return $this;
110139
}
111140

@@ -116,11 +145,17 @@ protected function checkForStatamicUpdates()
116145
*/
117146
protected function checkForAddonUpdates()
118147
{
119-
$this->addons = Addon::all()
120-
->reject->isLatestVersion()
121-
->map->id()
122-
->values()
123-
->all();
148+
$updatableAddons = Addon::all()->reject->isLatestVersion();
149+
150+
foreach ($updatableAddons as $addon) {
151+
if ($addon->changelog()->hasCriticalUpdate()) {
152+
$this->critical = true;
153+
break;
154+
}
155+
}
156+
157+
$this->addons = $updatableAddons->map->id()->values()->all();
158+
$this->count += count($this->addons);
124159

125160
return $this;
126161
}
@@ -136,6 +171,7 @@ protected function cache()
136171

137172
Cache::put('updates-overview.count', $this->count, $expiry);
138173
Cache::put('updates-overview.statamic', $this->statamic, $expiry);
174+
Cache::put('updates-overview.critical', $this->critical, $expiry);
139175
Cache::put('updates-overview.addons', $this->addons, $expiry);
140176

141177
return $this;

src/Widgets/Updater.php

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -18,19 +18,22 @@ public function component()
1818
$items = collect(UpdatesOverview::updatableAddons())->map(function ($id) {
1919
$addon = Addon::get($id);
2020

21+
$changelog = $addon->changelog();
22+
2123
return [
2224
'name' => $addon->name(),
23-
'count' => $addon->changelog()->availableUpdatesCount(),
24-
'critical' => false,
25+
'count' => $changelog->availableUpdatesCount(),
26+
'critical' => $changelog->hasCriticalUpdate(),
2527
'url' => cp_route('updater.product', $addon->slug()),
2628
];
2729
});
2830

2931
if (UpdatesOverview::hasStatamicUpdate()) {
32+
$changelog = Marketplace::statamic()->changelog();
3033
$items->push([
3134
'name' => 'Statamic Core',
32-
'count' => Marketplace::statamic()->changelog()->availableUpdatesCount(),
33-
'critical' => false,
35+
'count' => $changelog->availableUpdatesCount(),
36+
'critical' => $changelog->hasCriticalUpdate(),
3437
'url' => cp_route('updater.product', 'statamic'),
3538
]);
3639
}

0 commit comments

Comments
 (0)