From: Oliver Sluke <22557015+oliversluke@users.noreply.github.com> Date: Tue, 14 Jul 2026 19:31:19 +0000 (+0200) Subject: webui: label the home health line 'active subscriptions' X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=633b653fa090fc6fa1b6855de4d768f03524ade0;p=thirdparty%2Ftvheadend.git webui: label the home health line 'active subscriptions' The home health line summed each tuner's subscription count and linked to Status > Subscriptions, but labelled it 'N active streams'. The number and the link target are both subscriptions, so the label read as a mismatch. Rename it to 'N active subscription(s)' (and the backing identifiers) so the label matches what it counts and where it lands. Refs #2175 Signed-off-by: Oliver Sluke <22557015+oliversluke@users.noreply.github.com> --- diff --git a/src/webui/static-vue/src/views/home/HealthLine.vue b/src/webui/static-vue/src/views/home/HealthLine.vue index b4fd9c2d8..d7bb0e0fa 100644 --- a/src/webui/static-vue/src/views/home/HealthLine.vue +++ b/src/webui/static-vue/src/views/home/HealthLine.vue @@ -41,23 +41,26 @@ onMounted(() => { inputs.fetch().catch(() => { /* fetch errors surface via inputs.error */ }) }) -/* "Active streams" = total subscriptions across all tuner inputs - * (each tuner's `subs` count summed — one tuner serving several - * channels off the same transponder counts each). status/inputs - * also emits an idle "empty status" placeholder row per - * enabled-but-idle tuner (mpegts_input_get_streams); those carry - * subs:0, so summing `subs` excludes them naturally. */ -const activeStreams = computed(() => +/* Active subscriptions = total subscriptions across all tuner + * inputs (each tuner's `subs` count summed — one tuner serving + * several channels off the same transponder counts each). + * status/inputs also emits an idle "empty status" placeholder row + * per enabled-but-idle tuner (mpegts_input_get_streams); those + * carry subs:0, so summing `subs` excludes them naturally. The + * label counts subscriptions and links to Status → Subscriptions, + * so it reads "subscriptions" (not "streams") to match where it + * lands. */ +const activeSubscriptions = computed(() => inputs.entries.reduce((sum, row) => { const subs = row.subs return sum + (typeof subs === 'number' ? subs : 0) }, 0), ) -const streamsLabel = computed(() => { - const n = activeStreams.value +const subscriptionsLabel = computed(() => { + const n = activeSubscriptions.value if (n === 0) return t('Idle') - if (n === 1) return t('1 active stream') - return t('{0} active streams', n) + if (n === 1) return t('1 active subscription') + return t('{0} active subscriptions', n) }) /* The label is a router-link to Status → Subscriptions for @@ -68,8 +71,8 @@ const streamsLabel = computed(() => { * text instead of a link they'd land on a permission denial * from. Idle ("0 streams") also stays plain text — there's * nothing to drill into. */ -const streamsLinkable = computed( - () => activeStreams.value > 0 && access.has('admin'), +const subscriptionsLinkable = computed( + () => activeSubscriptions.value > 0 && access.has('admin'), ) /* Free space below this fraction of total → the low-disk warning. */ @@ -131,14 +134,14 @@ const totalText = computed(() => (total.value === null ? '—' : formatBytes(tot aria-hidden="true" /> - {{ streamsLabel }} + {{ subscriptionsLabel }} - {{ streamsLabel }} + {{ subscriptionsLabel }}

diff --git a/src/webui/static-vue/src/views/home/__tests__/HealthLine.test.ts b/src/webui/static-vue/src/views/home/__tests__/HealthLine.test.ts index 24d1cef20..92ab50401 100644 --- a/src/webui/static-vue/src/views/home/__tests__/HealthLine.test.ts +++ b/src/webui/static-vue/src/views/home/__tests__/HealthLine.test.ts @@ -106,15 +106,15 @@ describe('HealthLine', () => { { uuid: 'tuner-idle', subs: 0 } /* idle "empty status" placeholder */, ) const w = mount(HealthLine, globalMountOpts) - expect(w.find('.health-line__streams').text()).toBe('3 active streams') + expect(w.find('.health-line__streams').text()).toBe('3 active subscriptions') }) - it('uses the singular for a single active stream', () => { + it('uses the singular for a single active subscription', () => { accessData.totaldiskspace = 2 * TIB accessData.freediskspace = TIB statusEntries.push({ uuid: 'tuner-a', subs: 1 }) const w = mount(HealthLine, globalMountOpts) - expect(w.find('.health-line__streams').text()).toBe('1 active stream') + expect(w.find('.health-line__streams').text()).toBe('1 active subscription') }) it('reads "Idle" when only idle tuners are present', () => { @@ -125,8 +125,8 @@ describe('HealthLine', () => { expect(w.find('.health-line__streams').text()).toBe('Idle') }) - describe('active-streams link to status/subscriptions', () => { - it('wraps the streams count in a router-link to status-subscriptions for admins with active streams', () => { + describe('active-subscriptions link to status/subscriptions', () => { + it('wraps the subscriptions count in a router-link to status-subscriptions for admins with active subscriptions', () => { accessData.totaldiskspace = 2 * TIB accessData.freediskspace = TIB mockIsAdmin = true @@ -135,17 +135,17 @@ describe('HealthLine', () => { const link = w.find('.health-line__streams-link') expect(link.exists()).toBe(true) expect(link.attributes('data-to')).toContain('status-subscriptions') - expect(link.text()).toBe('3 active streams') + expect(link.text()).toBe('3 active subscriptions') }) - it('renders the streams count as plain text (no link) for non-admin users', () => { + it('renders the subscriptions count as plain text (no link) for non-admin users', () => { accessData.totaldiskspace = 2 * TIB accessData.freediskspace = TIB mockIsAdmin = false statusEntries.push({ uuid: 'tuner-a', subs: 3 }) const w = mount(HealthLine, globalMountOpts) expect(w.find('.health-line__streams-link').exists()).toBe(false) - expect(w.find('.health-line__streams').text()).toBe('3 active streams') + expect(w.find('.health-line__streams').text()).toBe('3 active subscriptions') }) it('renders Idle as plain text (no link) even for admins — nothing to drill into', () => {