Sans catchError, la premiere reponse en erreur terminait le flux du timer : le rafraichissement ne repartait jamais et l'ecran restait fige sur des chiffres perimes, sans rien signaler. Le catchError porte sur l'observable interne du switchMap. Place sur le flux externe il terminerait le timer tout autant. Un signal error alimente un bandeau, efface des qu'une reponse valide revient.
141 lines
2.5 KiB
SCSS
141 lines
2.5 KiB
SCSS
:host {
|
|
--color-good: #2e7d32;
|
|
--color-partial: #f9a825;
|
|
--color-degraded: #ef6c00;
|
|
--color-critical: #c62828;
|
|
--color-bg-card: #ffffff;
|
|
--color-border: #e5e7eb;
|
|
--color-text-muted: #6b7280;
|
|
--radius: 10px;
|
|
|
|
display: block;
|
|
font-family: 'Segoe UI', system-ui, sans-serif;
|
|
color: #1f2937;
|
|
padding: 2rem;
|
|
max-width: 1100px;
|
|
margin: 0 auto;
|
|
}
|
|
|
|
.dashboard__header {
|
|
margin-bottom: 2rem;
|
|
|
|
h1 {
|
|
margin: 0;
|
|
font-size: 1.75rem;
|
|
font-weight: 700;
|
|
}
|
|
}
|
|
|
|
.dashboard__subtitle {
|
|
margin: 0.25rem 0 0;
|
|
color: var(--color-text-muted);
|
|
}
|
|
|
|
h2 {
|
|
font-size: 1.1rem;
|
|
font-weight: 600;
|
|
margin: 0 0 1rem;
|
|
}
|
|
|
|
.banner-error {
|
|
margin: 0 0 1.5rem;
|
|
padding: 0.75rem 1rem;
|
|
border: 1px solid var(--color-critical);
|
|
border-left-width: 4px;
|
|
border-radius: var(--radius);
|
|
background: #fdecea;
|
|
color: var(--color-critical);
|
|
}
|
|
|
|
.overview {
|
|
display: grid;
|
|
grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
|
|
gap: 1rem;
|
|
margin-bottom: 2.5rem;
|
|
}
|
|
|
|
.card {
|
|
background: var(--color-bg-card);
|
|
border: 1px solid var(--color-border);
|
|
border-radius: var(--radius);
|
|
padding: 1.25rem;
|
|
display: flex;
|
|
flex-direction: column;
|
|
gap: 0.35rem;
|
|
box-shadow: 0 1px 2px rgba(0, 0, 0, 0.04);
|
|
}
|
|
|
|
.card--gauge {
|
|
align-items: center;
|
|
text-align: center;
|
|
}
|
|
|
|
.card__label {
|
|
font-size: 0.8rem;
|
|
color: var(--color-text-muted);
|
|
text-transform: uppercase;
|
|
letter-spacing: 0.02em;
|
|
}
|
|
|
|
.card__value {
|
|
font-size: 1.6rem;
|
|
font-weight: 700;
|
|
}
|
|
|
|
.progress-bar {
|
|
height: 6px;
|
|
background: #e5e7eb;
|
|
border-radius: 999px;
|
|
overflow: hidden;
|
|
margin-top: 0.25rem;
|
|
}
|
|
|
|
.progress-bar__fill {
|
|
height: 100%;
|
|
background: #3b82f6;
|
|
border-radius: 999px;
|
|
transition: width 0.3s ease;
|
|
}
|
|
|
|
.chart-section {
|
|
margin-bottom: 2.5rem;
|
|
}
|
|
|
|
.alerts-list {
|
|
list-style: none;
|
|
margin: 0;
|
|
padding: 0;
|
|
display: flex;
|
|
flex-direction: column;
|
|
gap: 0.5rem;
|
|
}
|
|
|
|
.alert-item {
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 0.75rem;
|
|
padding: 0.7rem 1rem;
|
|
border-radius: var(--radius);
|
|
background: #fef2f2;
|
|
border: 1px solid #fecaca;
|
|
}
|
|
|
|
.alert-item__badge {
|
|
font-size: 0.7rem;
|
|
font-weight: 700;
|
|
text-transform: uppercase;
|
|
padding: 0.2rem 0.55rem;
|
|
border-radius: 999px;
|
|
color: #fff;
|
|
background: var(--color-critical);
|
|
flex-shrink: 0;
|
|
}
|
|
|
|
.alert-item--high .alert-item__badge { background: var(--color-degraded); }
|
|
.alert-item--medium .alert-item__badge { background: var(--color-partial); }
|
|
.alert-item--low .alert-item__badge { background: var(--color-good); }
|
|
|
|
.alert-item__message {
|
|
font-size: 0.9rem;
|
|
}
|