fix(icons): migrate admin dashboard to Lucide
Replace every PrimeIcons pi-* class (static and data-driven) in the admin dashboard area with app-icon: dashboard-card, dashboard-shortcut- card, dashboard-status-row, dashboard-timeline, and the icon data in admin-dashboard.facade.ts / admin-dashboard-page.component.ts. Icon fields on AdminDashboardQuickAction/Shortcut/DashboardTimelineEntry are now typed AppIconName instead of string, so a typo or unmapped icon name is a compile error instead of a silently blank icon. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
@@ -1,8 +1,8 @@
|
|||||||
<app-card class="dashboard-card" padding="lg">
|
<app-card class="dashboard-card" padding="lg">
|
||||||
@if (titleKey(); as title) {
|
@if (titleKey(); as title) {
|
||||||
<header class="dashboard-card__header">
|
<header class="dashboard-card__header">
|
||||||
@if (icon(); as iconClass) {
|
@if (icon(); as iconName) {
|
||||||
<span class="pi {{ iconClass }} dashboard-card__icon" aria-hidden="true"></span>
|
<app-icon [name]="iconName" [size]="18" class="dashboard-card__icon" />
|
||||||
}
|
}
|
||||||
<h3 class="dashboard-card__title">{{ title | translate }}</h3>
|
<h3 class="dashboard-card__title">{{ title | translate }}</h3>
|
||||||
<div class="dashboard-card__header-actions">
|
<div class="dashboard-card__header-actions">
|
||||||
|
|||||||
@@ -1,11 +1,13 @@
|
|||||||
import { ChangeDetectionStrategy, Component, input } from '@angular/core';
|
import { ChangeDetectionStrategy, Component, input } from '@angular/core';
|
||||||
import { TranslatePipe } from '../../../../i18n/translate.pipe';
|
import { TranslatePipe } from '../../../../i18n/translate.pipe';
|
||||||
import { CardComponent } from '../../../../shared/ui/card/card.component';
|
import { CardComponent } from '../../../../shared/ui/card/card.component';
|
||||||
|
import { IconComponent } from '../../../../shared/ui/icon/icon.component';
|
||||||
|
import { AppIconName } from '../../../../shared/ui/icon/icon-registry';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-dashboard-card',
|
selector: 'app-dashboard-card',
|
||||||
standalone: true,
|
standalone: true,
|
||||||
imports: [TranslatePipe, CardComponent],
|
imports: [TranslatePipe, CardComponent, IconComponent],
|
||||||
templateUrl: './dashboard-card.component.html',
|
templateUrl: './dashboard-card.component.html',
|
||||||
styleUrl: './dashboard-card.component.scss',
|
styleUrl: './dashboard-card.component.scss',
|
||||||
changeDetection: ChangeDetectionStrategy.OnPush,
|
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||||
@@ -15,7 +17,7 @@ import { CardComponent } from '../../../../shared/ui/card/card.component';
|
|||||||
})
|
})
|
||||||
export class DashboardCardComponent {
|
export class DashboardCardComponent {
|
||||||
readonly titleKey = input<string | null>(null);
|
readonly titleKey = input<string | null>(null);
|
||||||
readonly icon = input<string | null>(null);
|
readonly icon = input<AppIconName | null>(null);
|
||||||
/** 12-column grid span at desktop width, e.g. 'span 12' or 'span 4'. */
|
/** 12-column grid span at desktop width, e.g. 'span 12' or 'span 4'. */
|
||||||
readonly span = input<string>('span 4');
|
readonly span = input<string>('span 4');
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
@if (comingSoon()) {
|
@if (comingSoon()) {
|
||||||
<button type="button" class="dashboard-shortcut-card dashboard-shortcut-card--disabled" disabled>
|
<button type="button" class="dashboard-shortcut-card dashboard-shortcut-card--disabled" disabled>
|
||||||
<span class="pi {{ icon() }} dashboard-shortcut-card__icon" aria-hidden="true"></span>
|
<app-icon [name]="icon()" [size]="22" class="dashboard-shortcut-card__icon" />
|
||||||
<span class="dashboard-shortcut-card__title">{{ labelKey() | translate }}</span>
|
<span class="dashboard-shortcut-card__title">{{ labelKey() | translate }}</span>
|
||||||
@if (descriptionKey(); as description) {
|
@if (descriptionKey(); as description) {
|
||||||
<span class="dashboard-shortcut-card__description">{{ description | translate }}</span>
|
<span class="dashboard-shortcut-card__description">{{ description | translate }}</span>
|
||||||
@@ -9,7 +9,7 @@
|
|||||||
</button>
|
</button>
|
||||||
} @else {
|
} @else {
|
||||||
<a class="dashboard-shortcut-card" [routerLink]="route()">
|
<a class="dashboard-shortcut-card" [routerLink]="route()">
|
||||||
<span class="pi {{ icon() }} dashboard-shortcut-card__icon" aria-hidden="true"></span>
|
<app-icon [name]="icon()" [size]="22" class="dashboard-shortcut-card__icon" />
|
||||||
<span class="dashboard-shortcut-card__title">{{ labelKey() | translate }}</span>
|
<span class="dashboard-shortcut-card__title">{{ labelKey() | translate }}</span>
|
||||||
@if (descriptionKey(); as description) {
|
@if (descriptionKey(); as description) {
|
||||||
<span class="dashboard-shortcut-card__description">{{ description | translate }}</span>
|
<span class="dashboard-shortcut-card__description">{{ description | translate }}</span>
|
||||||
|
|||||||
@@ -1,17 +1,19 @@
|
|||||||
import { ChangeDetectionStrategy, Component, input } from '@angular/core';
|
import { ChangeDetectionStrategy, Component, input } from '@angular/core';
|
||||||
import { RouterLink } from '@angular/router';
|
import { RouterLink } from '@angular/router';
|
||||||
import { TranslatePipe } from '../../../../i18n/translate.pipe';
|
import { TranslatePipe } from '../../../../i18n/translate.pipe';
|
||||||
|
import { IconComponent } from '../../../../shared/ui/icon/icon.component';
|
||||||
|
import { AppIconName } from '../../../../shared/ui/icon/icon-registry';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-dashboard-shortcut-card',
|
selector: 'app-dashboard-shortcut-card',
|
||||||
standalone: true,
|
standalone: true,
|
||||||
imports: [RouterLink, TranslatePipe],
|
imports: [RouterLink, TranslatePipe, IconComponent],
|
||||||
templateUrl: './dashboard-shortcut-card.component.html',
|
templateUrl: './dashboard-shortcut-card.component.html',
|
||||||
styleUrl: './dashboard-shortcut-card.component.scss',
|
styleUrl: './dashboard-shortcut-card.component.scss',
|
||||||
changeDetection: ChangeDetectionStrategy.OnPush,
|
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||||
})
|
})
|
||||||
export class DashboardShortcutCardComponent {
|
export class DashboardShortcutCardComponent {
|
||||||
readonly icon = input.required<string>();
|
readonly icon = input.required<AppIconName>();
|
||||||
readonly labelKey = input.required<string>();
|
readonly labelKey = input.required<string>();
|
||||||
readonly descriptionKey = input<string | null>(null);
|
readonly descriptionKey = input<string | null>(null);
|
||||||
readonly route = input<string[] | null>(null);
|
readonly route = input<string[] | null>(null);
|
||||||
|
|||||||
@@ -5,7 +5,7 @@
|
|||||||
</div>
|
</div>
|
||||||
} @else {
|
} @else {
|
||||||
<div class="dashboard-status-row dashboard-status-row--{{ status() }}">
|
<div class="dashboard-status-row dashboard-status-row--{{ status() }}">
|
||||||
<span class="pi {{ icon() }} dashboard-status-row__icon" aria-hidden="true"></span>
|
<app-icon [name]="icon()" [size]="16" class="dashboard-status-row__icon" />
|
||||||
<span class="dashboard-status-row__label">{{ labelKey() | translate }}</span>
|
<span class="dashboard-status-row__label">{{ labelKey() | translate }}</span>
|
||||||
@if (displayValue() !== null) {
|
@if (displayValue() !== null) {
|
||||||
<span class="dashboard-status-row__value">{{ displayValue() }}</span>
|
<span class="dashboard-status-row__value">{{ displayValue() }}</span>
|
||||||
|
|||||||
@@ -1,14 +1,16 @@
|
|||||||
import { ChangeDetectionStrategy, Component, computed, input } from '@angular/core';
|
import { ChangeDetectionStrategy, Component, computed, input } from '@angular/core';
|
||||||
import { TranslatePipe } from '../../../../i18n/translate.pipe';
|
import { TranslatePipe } from '../../../../i18n/translate.pipe';
|
||||||
import { SkeletonComponent } from '../../../../shared/ui/skeleton/skeleton.component';
|
import { SkeletonComponent } from '../../../../shared/ui/skeleton/skeleton.component';
|
||||||
|
import { IconComponent } from '../../../../shared/ui/icon/icon.component';
|
||||||
|
import { AppIconName } from '../../../../shared/ui/icon/icon-registry';
|
||||||
import { AdminDashboardHealthStatus } from '../models/admin-dashboard.model';
|
import { AdminDashboardHealthStatus } from '../models/admin-dashboard.model';
|
||||||
|
|
||||||
const STATUS_ICON: Record<AdminDashboardHealthStatus, string> = {
|
const STATUS_ICON: Record<AdminDashboardHealthStatus, AppIconName> = {
|
||||||
healthy: 'pi-check-circle',
|
healthy: 'checkCircle',
|
||||||
attention: 'pi-exclamation-triangle',
|
attention: 'warning',
|
||||||
unhealthy: 'pi-times-circle',
|
unhealthy: 'xCircle',
|
||||||
unknown: 'pi-question-circle',
|
unknown: 'help',
|
||||||
loading: 'pi-spin pi-spinner',
|
loading: 'spinner',
|
||||||
};
|
};
|
||||||
|
|
||||||
const STATUS_TEXT_KEY: Record<AdminDashboardHealthStatus, string> = {
|
const STATUS_TEXT_KEY: Record<AdminDashboardHealthStatus, string> = {
|
||||||
@@ -22,7 +24,7 @@ const STATUS_TEXT_KEY: Record<AdminDashboardHealthStatus, string> = {
|
|||||||
@Component({
|
@Component({
|
||||||
selector: 'app-dashboard-status-row',
|
selector: 'app-dashboard-status-row',
|
||||||
standalone: true,
|
standalone: true,
|
||||||
imports: [TranslatePipe, SkeletonComponent],
|
imports: [TranslatePipe, SkeletonComponent, IconComponent],
|
||||||
templateUrl: './dashboard-status-row.component.html',
|
templateUrl: './dashboard-status-row.component.html',
|
||||||
styleUrl: './dashboard-status-row.component.scss',
|
styleUrl: './dashboard-status-row.component.scss',
|
||||||
changeDetection: ChangeDetectionStrategy.OnPush,
|
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||||
|
|||||||
@@ -31,7 +31,7 @@
|
|||||||
<ol class="dashboard-timeline">
|
<ol class="dashboard-timeline">
|
||||||
@for (entry of entries(); track entry.id) {
|
@for (entry of entries(); track entry.id) {
|
||||||
<li class="dashboard-timeline__item">
|
<li class="dashboard-timeline__item">
|
||||||
<span class="pi {{ entry.icon }} dashboard-timeline__icon" aria-hidden="true"></span>
|
<app-icon [name]="entry.icon" [size]="18" class="dashboard-timeline__icon" />
|
||||||
<span class="dashboard-timeline__label">{{ entry.labelKey | translate }}</span>
|
<span class="dashboard-timeline__label">{{ entry.labelKey | translate }}</span>
|
||||||
<time class="dashboard-timeline__time">{{ entry.timeText }}</time>
|
<time class="dashboard-timeline__time">{{ entry.timeText }}</time>
|
||||||
</li>
|
</li>
|
||||||
|
|||||||
@@ -2,12 +2,14 @@ import { ChangeDetectionStrategy, Component, input } from '@angular/core';
|
|||||||
import { TranslatePipe } from '../../../../i18n/translate.pipe';
|
import { TranslatePipe } from '../../../../i18n/translate.pipe';
|
||||||
import { SkeletonComponent } from '../../../../shared/ui/skeleton/skeleton.component';
|
import { SkeletonComponent } from '../../../../shared/ui/skeleton/skeleton.component';
|
||||||
import { EmptyStateComponent } from '../../../../shared/ui/empty-state/empty-state.component';
|
import { EmptyStateComponent } from '../../../../shared/ui/empty-state/empty-state.component';
|
||||||
|
import { IconComponent } from '../../../../shared/ui/icon/icon.component';
|
||||||
|
import { AppIconName } from '../../../../shared/ui/icon/icon-registry';
|
||||||
|
|
||||||
export interface DashboardTimelineEntry {
|
export interface DashboardTimelineEntry {
|
||||||
id: string;
|
id: string;
|
||||||
labelKey: string;
|
labelKey: string;
|
||||||
timeText: string;
|
timeText: string;
|
||||||
icon: string;
|
icon: AppIconName;
|
||||||
}
|
}
|
||||||
|
|
||||||
export type DashboardTimelineStatus = 'loading' | 'ready' | 'unavailable' | 'error';
|
export type DashboardTimelineStatus = 'loading' | 'ready' | 'unavailable' | 'error';
|
||||||
@@ -15,7 +17,7 @@ export type DashboardTimelineStatus = 'loading' | 'ready' | 'unavailable' | 'err
|
|||||||
@Component({
|
@Component({
|
||||||
selector: 'app-dashboard-timeline',
|
selector: 'app-dashboard-timeline',
|
||||||
standalone: true,
|
standalone: true,
|
||||||
imports: [TranslatePipe, SkeletonComponent, EmptyStateComponent],
|
imports: [TranslatePipe, SkeletonComponent, EmptyStateComponent, IconComponent],
|
||||||
templateUrl: './dashboard-timeline.component.html',
|
templateUrl: './dashboard-timeline.component.html',
|
||||||
styleUrl: './dashboard-timeline.component.scss',
|
styleUrl: './dashboard-timeline.component.scss',
|
||||||
changeDetection: ChangeDetectionStrategy.OnPush,
|
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||||
|
|||||||
@@ -16,24 +16,24 @@ import {
|
|||||||
} from '../models/admin-dashboard.model';
|
} from '../models/admin-dashboard.model';
|
||||||
|
|
||||||
const QUICK_ACTIONS: AdminDashboardQuickAction[] = [
|
const QUICK_ACTIONS: AdminDashboardQuickAction[] = [
|
||||||
{ id: 'add-product', icon: 'pi-plus-circle', labelKey: 'dashboard.actionAddProduct', descriptionKey: 'dashboard.actionAddProductDescription', route: ['backoffice', 'products', 'create'] },
|
{ id: 'add-product', icon: 'plusCircle', labelKey: 'dashboard.actionAddProduct', descriptionKey: 'dashboard.actionAddProductDescription', route: ['backoffice', 'products', 'create'] },
|
||||||
{ id: 'create-category', icon: 'pi-sitemap', labelKey: 'dashboard.actionCreateCategory', descriptionKey: 'dashboard.actionCreateCategoryDescription', route: ['backoffice', 'categories', 'create'] },
|
{ id: 'create-category', icon: 'network', labelKey: 'dashboard.actionCreateCategory', descriptionKey: 'dashboard.actionCreateCategoryDescription', route: ['backoffice', 'categories', 'create'] },
|
||||||
{ id: 'edit-project', icon: 'pi-th-large', labelKey: 'dashboard.actionEditProject', descriptionKey: 'dashboard.actionEditProjectDescription', route: ['edit'] },
|
{ id: 'edit-project', icon: 'layoutGrid', labelKey: 'dashboard.actionEditProject', descriptionKey: 'dashboard.actionEditProjectDescription', route: ['edit'] },
|
||||||
{ id: 'edit-homepage', icon: 'pi-home', labelKey: 'dashboard.actionEditHomepage', descriptionKey: 'dashboard.actionEditHomepageDescription', route: ['edit', 'homepage'] },
|
{ id: 'edit-homepage', icon: 'home', labelKey: 'dashboard.actionEditHomepage', descriptionKey: 'dashboard.actionEditHomepageDescription', route: ['edit', 'homepage'] },
|
||||||
{ id: 'media-library', icon: 'pi-images', labelKey: 'dashboard.actionMediaLibrary', descriptionKey: 'dashboard.actionMediaLibraryDescription', route: ['backoffice', 'media'] },
|
{ id: 'media-library', icon: 'images', labelKey: 'dashboard.actionMediaLibrary', descriptionKey: 'dashboard.actionMediaLibraryDescription', route: ['backoffice', 'media'] },
|
||||||
{ id: 'orders', icon: 'pi-shopping-cart', labelKey: 'dashboard.actionOrders', descriptionKey: 'dashboard.actionOrdersDescription', route: ['backoffice', 'orders'] },
|
{ id: 'orders', icon: 'cart', labelKey: 'dashboard.actionOrders', descriptionKey: 'dashboard.actionOrdersDescription', route: ['backoffice', 'orders'] },
|
||||||
];
|
];
|
||||||
|
|
||||||
const SHORTCUTS: AdminDashboardShortcut[] = [
|
const SHORTCUTS: AdminDashboardShortcut[] = [
|
||||||
{ id: 'products', icon: 'pi-box', labelKey: 'dashboard.actionProducts', route: ['backoffice', 'products'] },
|
{ id: 'products', icon: 'package', labelKey: 'dashboard.actionProducts', route: ['backoffice', 'products'] },
|
||||||
{ id: 'categories', icon: 'pi-tags', labelKey: 'dashboard.actionCategories', route: ['backoffice', 'categories'] },
|
{ id: 'categories', icon: 'tags', labelKey: 'dashboard.actionCategories', route: ['backoffice', 'categories'] },
|
||||||
{ id: 'marketplace-builder', icon: 'pi-sitemap', labelKey: 'dashboard.shortcutMarketplaceBuilder', route: ['edit'] },
|
{ id: 'marketplace-builder', icon: 'network', labelKey: 'dashboard.shortcutMarketplaceBuilder', route: ['edit'] },
|
||||||
{ id: 'static-pages', icon: 'pi-file-edit', labelKey: 'dashboard.actionStaticPages', route: ['backoffice', 'static-pages'] },
|
{ id: 'static-pages', icon: 'edit', labelKey: 'dashboard.actionStaticPages', route: ['backoffice', 'static-pages'] },
|
||||||
{ id: 'orders', icon: 'pi-shopping-cart', labelKey: 'dashboard.actionOrders', route: ['backoffice', 'orders'] },
|
{ id: 'orders', icon: 'cart', labelKey: 'dashboard.actionOrders', route: ['backoffice', 'orders'] },
|
||||||
{ id: 'users', icon: 'pi-users', labelKey: 'dashboard.actionUsers', route: ['backoffice', 'users'] },
|
{ id: 'users', icon: 'users', labelKey: 'dashboard.actionUsers', route: ['backoffice', 'users'] },
|
||||||
{ id: 'settings', icon: 'pi-cog', labelKey: 'dashboard.shortcutSettings', route: [], comingSoon: true },
|
{ id: 'settings', icon: 'settings', labelKey: 'dashboard.shortcutSettings', route: [], comingSoon: true },
|
||||||
{ id: 'media-library', icon: 'pi-images', labelKey: 'dashboard.actionMediaLibrary', route: ['backoffice', 'media'] },
|
{ id: 'media-library', icon: 'images', labelKey: 'dashboard.actionMediaLibrary', route: ['backoffice', 'media'] },
|
||||||
{ id: 'content', icon: 'pi-align-left', labelKey: 'dashboard.shortcutContent', route: ['edit', 'static-pages'] },
|
{ id: 'content', icon: 'alignLeft', labelKey: 'dashboard.shortcutContent', route: ['edit', 'static-pages'] },
|
||||||
];
|
];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
import { AppIconName } from '../../../../shared/ui/icon/icon-registry';
|
||||||
|
|
||||||
export type AdminDashboardCardStatus = 'loading' | 'ready' | 'empty' | 'error' | 'pending-backend';
|
export type AdminDashboardCardStatus = 'loading' | 'ready' | 'empty' | 'error' | 'pending-backend';
|
||||||
|
|
||||||
export interface AdminDashboardCardState<T> {
|
export interface AdminDashboardCardState<T> {
|
||||||
@@ -28,7 +30,7 @@ export type AdminDashboardQuickActionId =
|
|||||||
|
|
||||||
export interface AdminDashboardQuickAction {
|
export interface AdminDashboardQuickAction {
|
||||||
id: AdminDashboardQuickActionId;
|
id: AdminDashboardQuickActionId;
|
||||||
icon: string;
|
icon: AppIconName;
|
||||||
labelKey: string;
|
labelKey: string;
|
||||||
descriptionKey: string;
|
descriptionKey: string;
|
||||||
route: string[];
|
route: string[];
|
||||||
@@ -73,7 +75,7 @@ export interface AdminDashboardDraftField {
|
|||||||
|
|
||||||
export interface AdminDashboardShortcut {
|
export interface AdminDashboardShortcut {
|
||||||
id: string;
|
id: string;
|
||||||
icon: string;
|
icon: AppIconName;
|
||||||
labelKey: string;
|
labelKey: string;
|
||||||
route: string[];
|
route: string[];
|
||||||
comingSoon?: boolean;
|
comingSoon?: boolean;
|
||||||
|
|||||||
@@ -41,7 +41,7 @@
|
|||||||
</app-dashboard-section>
|
</app-dashboard-section>
|
||||||
|
|
||||||
<!-- Draft Status -->
|
<!-- Draft Status -->
|
||||||
<app-dashboard-card [titleKey]="'dashboard.draftStatusTitle'" [icon]="'pi-file-edit'" [span]="'span 4'">
|
<app-dashboard-card [titleKey]="'dashboard.draftStatusTitle'" [icon]="'edit'" [span]="'span 4'">
|
||||||
@if (facade.dirty()) {
|
@if (facade.dirty()) {
|
||||||
<p class="dashboard-draft__lead">{{ 'dashboard.draftStatusHasChanges' | translate }}</p>
|
<p class="dashboard-draft__lead">{{ 'dashboard.draftStatusHasChanges' | translate }}</p>
|
||||||
@if (facade.modifiedFieldLabelKeys().length > 0) {
|
@if (facade.modifiedFieldLabelKeys().length > 0) {
|
||||||
@@ -66,21 +66,21 @@
|
|||||||
</div>
|
</div>
|
||||||
} @else {
|
} @else {
|
||||||
<p class="dashboard-draft__all-clear">
|
<p class="dashboard-draft__all-clear">
|
||||||
<span class="pi pi-check-circle" aria-hidden="true"></span>
|
<app-icon name="checkCircle" [size]="18" />
|
||||||
{{ 'dashboard.draftStatusAllPublished' | translate }}
|
{{ 'dashboard.draftStatusAllPublished' | translate }}
|
||||||
</p>
|
</p>
|
||||||
}
|
}
|
||||||
</app-dashboard-card>
|
</app-dashboard-card>
|
||||||
|
|
||||||
<!-- Marketplace Health -->
|
<!-- Marketplace Health -->
|
||||||
<app-dashboard-card [titleKey]="'dashboard.healthTitle'" [icon]="'pi-heart'" [span]="'span 4'">
|
<app-dashboard-card [titleKey]="'dashboard.healthTitle'" [icon]="'heart'" [span]="'span 4'">
|
||||||
@for (check of facade.homeHealthChecks(); track check.code) {
|
@for (check of facade.homeHealthChecks(); track check.code) {
|
||||||
<app-dashboard-status-row [labelKey]="check.labelKey" [status]="check.status" [displayValue]="check.displayValue ?? null" />
|
<app-dashboard-status-row [labelKey]="check.labelKey" [status]="check.status" [displayValue]="check.displayValue ?? null" />
|
||||||
}
|
}
|
||||||
</app-dashboard-card>
|
</app-dashboard-card>
|
||||||
|
|
||||||
<!-- Recent Activity -->
|
<!-- Recent Activity -->
|
||||||
<app-dashboard-card [titleKey]="'dashboard.activityTitle'" [icon]="'pi-clock'" [span]="'span 4'">
|
<app-dashboard-card [titleKey]="'dashboard.activityTitle'" [icon]="'clock'" [span]="'span 4'">
|
||||||
<app-dashboard-timeline [status]="activityStatus()" [entries]="activityTimelineEntries()" />
|
<app-dashboard-timeline [status]="activityStatus()" [entries]="activityTimelineEntries()" />
|
||||||
</app-dashboard-card>
|
</app-dashboard-card>
|
||||||
|
|
||||||
@@ -99,12 +99,12 @@
|
|||||||
</app-dashboard-section>
|
</app-dashboard-section>
|
||||||
|
|
||||||
<!-- Documentation -->
|
<!-- Documentation -->
|
||||||
<app-dashboard-card [titleKey]="'dashboard.docTitle'" [icon]="'pi-question-circle'" [span]="'span 4'">
|
<app-dashboard-card [titleKey]="'dashboard.docTitle'" [icon]="'help'" [span]="'span 4'">
|
||||||
<ul class="dashboard-doc-list">
|
<ul class="dashboard-doc-list">
|
||||||
@for (link of documentationLinks; track link.id) {
|
@for (link of documentationLinks; track link.id) {
|
||||||
<li>
|
<li>
|
||||||
<button type="button" class="dashboard-doc-list__item" disabled>
|
<button type="button" class="dashboard-doc-list__item" disabled>
|
||||||
<span class="pi {{ link.icon }}" aria-hidden="true"></span>
|
<app-icon [name]="link.icon" [size]="18" />
|
||||||
<span>{{ link.labelKey | translate }}</span>
|
<span>{{ link.labelKey | translate }}</span>
|
||||||
<span class="dashboard-doc-list__badge">{{ 'adminShell.nav.comingSoonBadge' | translate }}</span>
|
<span class="dashboard-doc-list__badge">{{ 'adminShell.nav.comingSoonBadge' | translate }}</span>
|
||||||
</button>
|
</button>
|
||||||
|
|||||||
@@ -11,19 +11,21 @@ import { DashboardStatusRowComponent } from '../components/dashboard-status-row.
|
|||||||
import { DashboardShortcutCardComponent } from '../components/dashboard-shortcut-card.component';
|
import { DashboardShortcutCardComponent } from '../components/dashboard-shortcut-card.component';
|
||||||
import { DashboardTimelineComponent, DashboardTimelineEntry, DashboardTimelineStatus } from '../components/dashboard-timeline.component';
|
import { DashboardTimelineComponent, DashboardTimelineEntry, DashboardTimelineStatus } from '../components/dashboard-timeline.component';
|
||||||
import { ButtonComponent } from '../../../../shared/ui/button/button.component';
|
import { ButtonComponent } from '../../../../shared/ui/button/button.component';
|
||||||
|
import { IconComponent } from '../../../../shared/ui/icon/icon.component';
|
||||||
import { AdminDashboardQuickAction, AdminDashboardShortcut } from '../models/admin-dashboard.model';
|
import { AdminDashboardQuickAction, AdminDashboardShortcut } from '../models/admin-dashboard.model';
|
||||||
|
import { AppIconName } from '../../../../shared/ui/icon/icon-registry';
|
||||||
|
|
||||||
interface LinkedAction {
|
interface LinkedAction {
|
||||||
icon: string;
|
icon: AppIconName;
|
||||||
labelKey: string;
|
labelKey: string;
|
||||||
descriptionKey?: string;
|
descriptionKey?: string;
|
||||||
route: string[];
|
route: string[];
|
||||||
comingSoon: boolean;
|
comingSoon: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
const ACTIVITY_ICON: Record<string, string> = {
|
const ACTIVITY_ICON: Record<string, AppIconName> = {
|
||||||
'draft-saved': 'pi-save',
|
'draft-saved': 'save',
|
||||||
published: 'pi-upload',
|
published: 'upload',
|
||||||
};
|
};
|
||||||
|
|
||||||
const ACTIVITY_LABEL_KEY: Record<string, string> = {
|
const ACTIVITY_LABEL_KEY: Record<string, string> = {
|
||||||
@@ -31,11 +33,11 @@ const ACTIVITY_LABEL_KEY: Record<string, string> = {
|
|||||||
published: 'dashboard.activityPublished',
|
published: 'dashboard.activityPublished',
|
||||||
};
|
};
|
||||||
|
|
||||||
const DOCUMENTATION_LINKS = [
|
const DOCUMENTATION_LINKS: Array<{ id: string; icon: AppIconName; labelKey: string }> = [
|
||||||
{ id: 'documentation', icon: 'pi-book', labelKey: 'dashboard.docDocumentation' },
|
{ id: 'documentation', icon: 'book', labelKey: 'dashboard.docDocumentation' },
|
||||||
{ id: 'shortcuts', icon: 'pi-bolt', labelKey: 'dashboard.docKeyboardShortcuts' },
|
{ id: 'shortcuts', icon: 'zap', labelKey: 'dashboard.docKeyboardShortcuts' },
|
||||||
{ id: 'report-issue', icon: 'pi-flag', labelKey: 'dashboard.docReportIssue' },
|
{ id: 'report-issue', icon: 'flag', labelKey: 'dashboard.docReportIssue' },
|
||||||
{ id: 'release-notes', icon: 'pi-megaphone', labelKey: 'dashboard.docReleaseNotes' },
|
{ id: 'release-notes', icon: 'megaphone', labelKey: 'dashboard.docReleaseNotes' },
|
||||||
];
|
];
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
@@ -51,6 +53,7 @@ const DOCUMENTATION_LINKS = [
|
|||||||
DashboardShortcutCardComponent,
|
DashboardShortcutCardComponent,
|
||||||
DashboardTimelineComponent,
|
DashboardTimelineComponent,
|
||||||
ButtonComponent,
|
ButtonComponent,
|
||||||
|
IconComponent,
|
||||||
],
|
],
|
||||||
templateUrl: './admin-dashboard-page.component.html',
|
templateUrl: './admin-dashboard-page.component.html',
|
||||||
styleUrls: ['./admin-dashboard-page.component.scss'],
|
styleUrls: ['./admin-dashboard-page.component.scss'],
|
||||||
@@ -98,7 +101,7 @@ export class AdminDashboardPageComponent {
|
|||||||
id: entry.id,
|
id: entry.id,
|
||||||
labelKey: ACTIVITY_LABEL_KEY[entry.type] ?? entry.type,
|
labelKey: ACTIVITY_LABEL_KEY[entry.type] ?? entry.type,
|
||||||
timeText: new Date(entry.timestamp).toLocaleString(this.languageService.currentLanguage()),
|
timeText: new Date(entry.timestamp).toLocaleString(this.languageService.currentLanguage()),
|
||||||
icon: ACTIVITY_ICON[entry.type] ?? 'pi-circle',
|
icon: ACTIVITY_ICON[entry.type] ?? 'circle',
|
||||||
})),
|
})),
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|||||||
@@ -73,7 +73,8 @@ import {
|
|||||||
LucideUsers as Users,
|
LucideUsers as Users,
|
||||||
LucideVideo as Video,
|
LucideVideo as Video,
|
||||||
LucideX as X,
|
LucideX as X,
|
||||||
LucideXCircle as XCircle
|
LucideXCircle as XCircle,
|
||||||
|
LucideZap as Zap
|
||||||
} from '@lucide/angular';
|
} from '@lucide/angular';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -113,6 +114,7 @@ export const APP_ICONS = {
|
|||||||
edit: Pencil,
|
edit: Pencil,
|
||||||
trash: Trash2,
|
trash: Trash2,
|
||||||
copy: Copy,
|
copy: Copy,
|
||||||
|
save: Save,
|
||||||
plus: Plus,
|
plus: Plus,
|
||||||
plusCircle: PlusCircle,
|
plusCircle: PlusCircle,
|
||||||
minus: Minus,
|
minus: Minus,
|
||||||
@@ -156,7 +158,8 @@ export const APP_ICONS = {
|
|||||||
layoutGrid: LayoutGrid,
|
layoutGrid: LayoutGrid,
|
||||||
verified: BadgeCheck,
|
verified: BadgeCheck,
|
||||||
video: Video,
|
video: Video,
|
||||||
circle: Circle
|
circle: Circle,
|
||||||
|
zap: Zap
|
||||||
} as const;
|
} as const;
|
||||||
|
|
||||||
export type AppIconName = keyof typeof APP_ICONS;
|
export type AppIconName = keyof typeof APP_ICONS;
|
||||||
|
|||||||
Reference in New Issue
Block a user