From 268a710bf2c4ac498cbbb5428124c60788ecac2e Mon Sep 17 00:00:00 2001 From: 4gray Date: Sun, 8 Mar 2026 11:23:34 +0100 Subject: [PATCH] refactor(dashboard): improvements for dashboard widgets - Updated dashboard activity items styles for improved layout and media representation. - Introduced new styles for movie and series media types. - Enhanced placeholder styles for live, movie, and series items using oklch color model. - Added hover effects for activity items and action buttons in grid mode. - Refactored dashboard widget shell styles for better alignment and padding. - Created new on-air widget component with category filtering and loading skeletons. - Implemented responsive design for on-air widget and improved empty state handling. - Removed deprecated recent sources widget and integrated recent sources functionality into existing components. - Updated recently watched widget to include action links for adding sources. - Enhanced source stats widget with new styling for different source types (Xtream, Stalker, M3U). --- .../src/lib/dashboard-data.service.ts | 23 +- .../src/lib/dashboard-widget.model.ts | 30 +- .../lib/workspace-dashboard.component.html | 180 ++++++----- .../lib/workspace-dashboard.component.scss | 196 ++++++------ .../src/lib/workspace-dashboard.component.ts | 91 ++++-- .../lib/dashboard-widget-host.component.html | 6 +- .../lib/dashboard-widget-host.component.ts | 4 +- .../continue-watching-widget.component.html | 86 +++--- .../continue-watching-widget.component.scss | 259 +++++++++++++--- .../continue-watching-widget.component.ts | 42 ++- .../dashboard-activity-items.component.html | 16 +- .../dashboard-activity-items.component.scss | 113 +++++-- .../dashboard-activity-items.component.ts | 5 +- .../dashboard-widget-shell.component.scss | 9 +- .../global-favorites-widget.component.scss | 6 + .../global-favorites-widget.component.ts | 19 +- .../lib/widgets/on-air-widget.component.html | 130 ++++++++ .../lib/widgets/on-air-widget.component.scss | 279 ++++++++++++++++++ .../lib/widgets/on-air-widget.component.ts | 196 ++++++++++++ .../recent-sources-widget.component.html | 20 +- .../recent-sources-widget.component.scss | 67 ++++- .../recent-sources-widget.component.ts | 2 + .../recently-watched-widget.component.html | 2 + .../recently-watched-widget.component.scss | 6 + .../recently-watched-widget.component.ts | 19 +- .../source-stats-widget.component.html | 6 +- .../source-stats-widget.component.scss | 27 ++ 27 files changed, 1487 insertions(+), 352 deletions(-) create mode 100644 libs/workspace/dashboard/ui/src/lib/widgets/on-air-widget.component.html create mode 100644 libs/workspace/dashboard/ui/src/lib/widgets/on-air-widget.component.scss create mode 100644 libs/workspace/dashboard/ui/src/lib/widgets/on-air-widget.component.ts diff --git a/libs/workspace/dashboard/data-access/src/lib/dashboard-data.service.ts b/libs/workspace/dashboard/data-access/src/lib/dashboard-data.service.ts index 33db2fbf8..7754ff143 100644 --- a/libs/workspace/dashboard/data-access/src/lib/dashboard-data.service.ts +++ b/libs/workspace/dashboard/data-access/src/lib/dashboard-data.service.ts @@ -1,4 +1,4 @@ -import { Injectable, computed, inject, signal } from '@angular/core'; +import { Injectable, NgZone, computed, inject, signal } from '@angular/core'; import { Store } from '@ngrx/store'; import { PlaylistActions, @@ -58,6 +58,7 @@ interface DashboardNavigationTarget { export class DashboardDataService { private readonly store = inject(Store); private readonly dbService = inject(DatabaseService); + private readonly ngZone = inject(NgZone); private readonly xtreamGlobalRecentItems = signal([]); private readonly xtreamGlobalFavorites = signal( @@ -133,9 +134,13 @@ export class DashboardDataService { const normalized = recentItems.map((item) => this.mapGlobalRecent(item) ); - this.xtreamGlobalRecentItems.set(normalized); - } catch { - this.xtreamGlobalRecentItems.set([]); + this.ngZone.run(() => this.xtreamGlobalRecentItems.set(normalized)); + } catch (err) { + console.warn( + '[DashboardData] Failed to reload global recent items', + err + ); + this.ngZone.run(() => this.xtreamGlobalRecentItems.set([])); } } @@ -150,9 +155,13 @@ export class DashboardDataService { const normalized = favorites.map((item) => this.mapGlobalFavorite(item) ); - this.xtreamGlobalFavorites.set(normalized); - } catch { - this.xtreamGlobalFavorites.set([]); + this.ngZone.run(() => this.xtreamGlobalFavorites.set(normalized)); + } catch (err) { + console.warn( + '[DashboardData] Failed to reload global favorites', + err + ); + this.ngZone.run(() => this.xtreamGlobalFavorites.set([])); } } diff --git a/libs/workspace/dashboard/data-access/src/lib/dashboard-widget.model.ts b/libs/workspace/dashboard/data-access/src/lib/dashboard-widget.model.ts index 4f1dba321..6f2a0cc12 100644 --- a/libs/workspace/dashboard/data-access/src/lib/dashboard-widget.model.ts +++ b/libs/workspace/dashboard/data-access/src/lib/dashboard-widget.model.ts @@ -1,7 +1,7 @@ export type DashboardWidgetType = - | 'recent-sources' | 'source-stats' | 'continue-watching' + | 'on-air' | 'recently-watched' | 'global-favorites'; @@ -33,7 +33,7 @@ export interface DashboardLayoutState { widgets: DashboardWidgetConfig[]; } -export const DASHBOARD_LAYOUT_VERSION = 6; +export const DASHBOARD_LAYOUT_VERSION = 12; export const DASHBOARD_WIDGET_SIZE_OPTIONS: DashboardWidgetSize[] = [ 'one-third', 'half', @@ -58,22 +58,13 @@ export function createDefaultWidgetScope(): DashboardWidgetScopeSettings { } export const DEFAULT_DASHBOARD_WIDGETS: DashboardWidgetConfig[] = [ - { - id: 'recent-sources', - type: 'recent-sources', - title: 'Recent Sources', - description: 'Latest added or refreshed playlists across providers.', - size: 'half', - enabled: true, - order: 0, - }, { id: 'source-stats', type: 'source-stats', title: 'Source Statistics', description: 'Current source mix and total connected libraries.', size: 'one-third', - enabled: true, + enabled: false, order: 1, }, { @@ -81,10 +72,19 @@ export const DEFAULT_DASHBOARD_WIDGETS: DashboardWidgetConfig[] = [ type: 'continue-watching', title: 'Continue Watching', description: 'Jump back into the last active source.', - size: 'half', + size: 'full', enabled: true, order: 2, }, + { + id: 'on-air', + type: 'on-air', + title: 'On Air Now', + description: 'Live programs currently airing across your EPG channels.', + size: 'full', + enabled: true, + order: 3, + }, { id: 'recently-watched', type: 'recently-watched', @@ -92,7 +92,7 @@ export const DEFAULT_DASHBOARD_WIDGETS: DashboardWidgetConfig[] = [ description: 'Global watch history across channels, VOD and series.', size: 'two-thirds', enabled: true, - order: 3, + order: 4, settings: { scope: createDefaultWidgetScope(), }, @@ -104,7 +104,7 @@ export const DEFAULT_DASHBOARD_WIDGETS: DashboardWidgetConfig[] = [ description: 'Pinned items across all connected providers.', size: 'one-third', enabled: true, - order: 4, + order: 5, settings: { scope: createDefaultWidgetScope(), }, diff --git a/libs/workspace/dashboard/feature/src/lib/workspace-dashboard.component.html b/libs/workspace/dashboard/feature/src/lib/workspace-dashboard.component.html index 809fcaed3..91c1cda63 100644 --- a/libs/workspace/dashboard/feature/src/lib/workspace-dashboard.component.html +++ b/libs/workspace/dashboard/feature/src/lib/workspace-dashboard.component.html @@ -1,43 +1,45 @@
-
-
-

Workspace Dashboard

-

Control Center

-

- Keep your daily sources in one place. In customize mode, edit - directly on the canvas, then use the sidebar for visibility and - scope. -

-
-
-
-

- @if (editMode()) { - Drag cards by the handle. Resize inline. Use the sidebar for - visibility and scope. - } @else { - Start customize mode to rearrange and resize widgets in place. - } -

-
- @if (editMode()) { + @if (editMode()) { +

+ {{ 'WORKSPACE.DASHBOARD.TOOLBAR_HINT_EDITING' | translate }} +

+
- } - +
+ } @else { +

+ {{ 'WORKSPACE.DASHBOARD.TOPBAR_LABEL' | translate }} +

+ -
+ }
drag_indicator -

- {{ widget.title }} -

- - @for ( - size of sizeOptions; - track size.value - ) { - - {{ size.label }} - - } - +
+ + {{ + getSizeLabel(widget.size) + }} + +
@@ -125,10 +141,17 @@ @if (editMode()) {