mirror of
https://github.com/4gray/iptvnator.git
synced 2026-10-08 17:06:15 -08:00
feat(epg): restructure progress panel template and actions
Refactor the EPG progress panel template to improve DOM structure and action handling. Move the top-level panel wrapper and header markup so the "dismiss all" button is rendered consistently when multiple imports exist. Reorder imports list and per-item blocks so each import item contains its own header, icon, url and dismiss button. Restore the per-item dismiss button and adjust classes to distinguish between the global dismiss-all and item-level dismiss actions. These changes simplify markup nesting, fix button placement bugs, and prepare the template for clearer styling and behavior of active and queued import items.
This commit is contained in:
1 parent
397f57186e
commit
520f00a133
4 files changed
+119
-105
No files matched your search
@@ -1 +1,3 @@
|
||||
<router-outlet />
|
||||
|
||||
<app-epg-progress-panel />
|
||||
@@ -1,95 +1,117 @@
|
||||
@if (isVisible()) {
|
||||
<div class="epg-progress-panel">
|
||||
<div class="panel-header">
|
||||
<span class="header-title">
|
||||
<mat-icon>live_tv</mat-icon>
|
||||
{{ 'EPG.IMPORT_PROGRESS' | translate }}
|
||||
</span>
|
||||
@if (imports().length > 1) {
|
||||
<button
|
||||
mat-icon-button
|
||||
class="dismiss-all-btn"
|
||||
(click)="dismissAll()"
|
||||
[attr.aria-label]="'BUTTONS.CLOSE' | translate"
|
||||
>
|
||||
<mat-icon>close</mat-icon>
|
||||
</button>
|
||||
}
|
||||
</div>
|
||||
|
||||
<div class="imports-list">
|
||||
<!-- Active/Completed imports -->
|
||||
@for (item of activeImports; track item.url) {
|
||||
<div class="import-item" [class]="getStatusClass(item.status)">
|
||||
<div class="item-header">
|
||||
<div class="status-icon-wrapper">
|
||||
<mat-icon [class.spinning]="item.status === 'loading'">
|
||||
{{ getStatusIcon(item.status) }}
|
||||
</mat-icon>
|
||||
</div>
|
||||
<span class="item-url" [title]="item.url">
|
||||
{{ getDisplayUrl(item.url) }}
|
||||
</span>
|
||||
<div class="epg-progress-panel">
|
||||
<div class="panel-header">
|
||||
<span class="header-title">
|
||||
<mat-icon>live_tv</mat-icon>
|
||||
{{ 'EPG.IMPORT_PROGRESS' | translate }}
|
||||
</span>
|
||||
@if (imports().length > 1) {
|
||||
<button
|
||||
mat-icon-button
|
||||
class="dismiss-btn"
|
||||
(click)="dismiss(item.url)"
|
||||
class="dismiss-all-btn"
|
||||
(click)="dismissAll()"
|
||||
[attr.aria-label]="'BUTTONS.CLOSE' | translate"
|
||||
>
|
||||
<mat-icon>close</mat-icon>
|
||||
</button>
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
|
||||
@if (item.status === 'loading') {
|
||||
<mat-progress-bar mode="indeterminate"></mat-progress-bar>
|
||||
<div class="imports-list">
|
||||
<!-- Active/Completed imports -->
|
||||
@for (item of activeImports; track item.url) {
|
||||
<div class="import-item" [class]="getStatusClass(item.status)">
|
||||
<div class="item-header">
|
||||
<div class="status-icon-wrapper">
|
||||
<mat-icon
|
||||
[class.spinning]="item.status === 'loading'"
|
||||
>
|
||||
{{ getStatusIcon(item.status) }}
|
||||
</mat-icon>
|
||||
</div>
|
||||
<span class="item-url" [title]="item.url">
|
||||
{{ getDisplayUrl(item.url) }}
|
||||
</span>
|
||||
<button
|
||||
mat-icon-button
|
||||
class="dismiss-btn"
|
||||
(click)="dismiss(item.url)"
|
||||
[attr.aria-label]="'BUTTONS.CLOSE' | translate"
|
||||
>
|
||||
<mat-icon>close</mat-icon>
|
||||
</button>
|
||||
</div>
|
||||
|
||||
@if (item.status === 'loading') {
|
||||
<mat-progress-bar mode="indeterminate" />
|
||||
}
|
||||
|
||||
<div class="item-stats">
|
||||
@if (item.stats) {
|
||||
<span
|
||||
class="stat-badge"
|
||||
matTooltip="{{
|
||||
'EPG.TOTAL_CHANNELS' | translate
|
||||
}}"
|
||||
>
|
||||
<mat-icon>tv</mat-icon>
|
||||
{{ item.stats.totalChannels }}
|
||||
</span>
|
||||
<span
|
||||
class="stat-badge"
|
||||
matTooltip="{{
|
||||
'EPG.TOTAL_PROGRAMS' | translate
|
||||
}}"
|
||||
>
|
||||
<mat-icon>event</mat-icon>
|
||||
{{ item.stats.totalPrograms }}
|
||||
</span>
|
||||
} @else if (item.error) {
|
||||
<span class="error-text">{{ item.error }}</span>
|
||||
} @else if (item.status === 'loading') {
|
||||
<span>{{ 'EPG.LOADING' | translate }}...</span>
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
|
||||
<div class="item-stats">
|
||||
@if (item.stats) {
|
||||
<span class="stat-badge">
|
||||
<mat-icon>tv</mat-icon>
|
||||
{{ item.stats.totalChannels }}
|
||||
</span>
|
||||
<span class="stat-badge">
|
||||
<mat-icon>event</mat-icon>
|
||||
{{ item.stats.totalPrograms }}
|
||||
</span>
|
||||
} @else if (item.error) {
|
||||
<span class="error-text">{{ item.error }}</span>
|
||||
} @else if (item.status === 'loading') {
|
||||
<span>{{ 'EPG.LOADING' | translate }}...</span>
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
|
||||
<!-- Queued imports section -->
|
||||
@if (queuedImports.length > 0) {
|
||||
<div class="queue-section">
|
||||
<div class="queue-header">
|
||||
<mat-icon>queue</mat-icon>
|
||||
<span>{{ 'EPG.QUEUED' | translate }} ({{ queuedImports.length }})</span>
|
||||
</div>
|
||||
<div class="queue-list">
|
||||
@for (item of queuedImports; track item.url; let i = $index) {
|
||||
<div class="queue-item">
|
||||
<span class="queue-position">{{ i + 1 }}</span>
|
||||
<span class="queue-url" [title]="item.url">
|
||||
{{ getDisplayUrl(item.url) }}
|
||||
</span>
|
||||
<button
|
||||
mat-icon-button
|
||||
class="dismiss-btn"
|
||||
(click)="dismiss(item.url)"
|
||||
[attr.aria-label]="'BUTTONS.CLOSE' | translate"
|
||||
>
|
||||
<mat-icon>close</mat-icon>
|
||||
</button>
|
||||
<!-- Queued imports section -->
|
||||
@if (queuedImports.length > 0) {
|
||||
<div class="queue-section">
|
||||
<div class="queue-header">
|
||||
<mat-icon>queue</mat-icon>
|
||||
<span
|
||||
>{{ 'EPG.QUEUED' | translate }} ({{
|
||||
queuedImports.length
|
||||
}})</span
|
||||
>
|
||||
</div>
|
||||
<div class="queue-list">
|
||||
@for (
|
||||
item of queuedImports;
|
||||
track item.url;
|
||||
let i = $index
|
||||
) {
|
||||
<div class="queue-item">
|
||||
<span class="queue-position">{{ i + 1 }}</span>
|
||||
<span class="queue-url" [title]="item.url">
|
||||
{{ getDisplayUrl(item.url) }}
|
||||
</span>
|
||||
<button
|
||||
mat-icon-button
|
||||
class="dismiss-btn"
|
||||
(click)="dismiss(item.url)"
|
||||
[attr.aria-label]="
|
||||
'BUTTONS.CLOSE' | translate
|
||||
"
|
||||
>
|
||||
<mat-icon>close</mat-icon>
|
||||
</button>
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
@@ -144,16 +144,12 @@
|
||||
.dismiss-all-btn {
|
||||
width: 28px;
|
||||
height: 28px;
|
||||
padding: 2px;
|
||||
line-height: 28px;
|
||||
border-radius: 8px;
|
||||
transition: all 0.2s ease;
|
||||
color: var(--epg-text-tertiary);
|
||||
|
||||
&:hover {
|
||||
background: var(--epg-item-hover);
|
||||
color: var(--epg-text-primary);
|
||||
}
|
||||
|
||||
mat-icon {
|
||||
font-size: 18px;
|
||||
width: 18px;
|
||||
@@ -199,11 +195,11 @@
|
||||
}
|
||||
|
||||
.import-item {
|
||||
padding: 14px 16px;
|
||||
margin: 0 8px;
|
||||
padding: 6px 12px;
|
||||
border-radius: 10px;
|
||||
transition: all 0.2s ease;
|
||||
position: relative;
|
||||
margin: 0 6px;
|
||||
|
||||
&:not(:last-child) {
|
||||
margin-bottom: 2px;
|
||||
@@ -252,17 +248,13 @@
|
||||
.dismiss-btn {
|
||||
width: 26px;
|
||||
height: 26px;
|
||||
padding: 2px;
|
||||
line-height: 26px;
|
||||
border-radius: 6px;
|
||||
opacity: 0;
|
||||
transition: all 0.2s ease;
|
||||
color: var(--epg-text-tertiary);
|
||||
|
||||
&:hover {
|
||||
background: var(--epg-error-glow);
|
||||
color: var(--epg-error);
|
||||
}
|
||||
|
||||
mat-icon {
|
||||
font-size: 16px;
|
||||
width: 16px;
|
||||
@@ -378,7 +370,7 @@
|
||||
|
||||
// Queue section styles
|
||||
.queue-section {
|
||||
margin: 8px;
|
||||
//margin: 8px;
|
||||
padding: 12px;
|
||||
border-radius: 10px;
|
||||
animation: fadeIn 0.3s ease;
|
||||
@@ -455,6 +447,7 @@
|
||||
.dismiss-btn {
|
||||
width: 22px;
|
||||
height: 22px;
|
||||
padding: 0;
|
||||
line-height: 22px;
|
||||
border-radius: 4px;
|
||||
opacity: 0;
|
||||
@@ -462,11 +455,6 @@
|
||||
color: var(--epg-text-tertiary);
|
||||
flex-shrink: 0;
|
||||
|
||||
&:hover {
|
||||
background: var(--epg-error-glow);
|
||||
color: var(--epg-error);
|
||||
}
|
||||
|
||||
mat-icon {
|
||||
font-size: 14px;
|
||||
width: 14px;
|
||||
|
||||
@@ -1,12 +1,13 @@
|
||||
import { Component, inject } from '@angular/core';
|
||||
import { CommonModule } from '@angular/common';
|
||||
import { MatProgressBarModule } from '@angular/material/progress-bar';
|
||||
import { MatIconModule } from '@angular/material/icon';
|
||||
import { Component, inject } from '@angular/core';
|
||||
import { MatButtonModule } from '@angular/material/button';
|
||||
import { MatIconModule } from '@angular/material/icon';
|
||||
import { MatProgressBar } from '@angular/material/progress-bar';
|
||||
import { MatTooltip } from '@angular/material/tooltip';
|
||||
import { TranslateModule } from '@ngx-translate/core';
|
||||
import {
|
||||
EpgProgressService,
|
||||
EpgImportProgress,
|
||||
EpgProgressService,
|
||||
} from '../../services/epg-progress.service';
|
||||
|
||||
@Component({
|
||||
@@ -14,9 +15,10 @@ import {
|
||||
standalone: true,
|
||||
imports: [
|
||||
CommonModule,
|
||||
MatProgressBarModule,
|
||||
MatIconModule,
|
||||
MatButtonModule,
|
||||
MatIconModule,
|
||||
MatTooltip,
|
||||
MatProgressBar,
|
||||
TranslateModule,
|
||||
],
|
||||
templateUrl: './epg-progress-panel.component.html',
|
||||
|
||||
Reference in new issue
Block a user