feat: Authenticated Shell, Quick Tabs and Change Password 1.04

This commit is contained in:
OpenVelo Agent
2026-07-22 09:37:08 +00:00
parent 4e463de65c
commit 5399238d9f
7 changed files with 112 additions and 228 deletions
@@ -36,3 +36,14 @@ export function deriveCountdownText(
}
return secondsToEnd == null ? '00:00:00' : formatDdHhMm(secondsToEnd);
}
export const LED_COLOR_BY_STATE: Readonly<Record<EventState, string>> = {
running: 'var(--color-success)',
countdown: 'var(--color-warning)',
stopped: 'var(--color-danger)',
unconfigured: 'var(--color-secondary)',
};
export function ledBackgroundColor(state: EventState): string {
return LED_COLOR_BY_STATE[state];
}
@@ -4,9 +4,19 @@ import {
EventSourceLike,
EventState,
EventStatePayload,
LED_COLOR_BY_STATE,
ledBackgroundColor,
} from './event-status.pure';
export { EventState, EventStatePayload, EventSourceLike, deriveCountdownText, formatDdHhMm } from './event-status.pure';
export {
EventState,
EventStatePayload,
EventSourceLike,
deriveCountdownText,
formatDdHhMm,
LED_COLOR_BY_STATE,
ledBackgroundColor,
} from './event-status.pure';
@Injectable({ providedIn: 'root' })
export class EventStatusStore {
@@ -1,6 +1,6 @@
import { ChangeDetectionStrategy, Component, computed, input, output } from '@angular/core';
import { CommonModule } from '@angular/common';
import { EventState } from '../../../core/services/event-status.store';
import { EventState, ledBackgroundColor } from '../../../core/services/event-status.store';
@Component({
selector: 'app-shell-header',
@@ -8,20 +8,14 @@ import { EventState } from '../../../core/services/event-status.store';
changeDetection: ChangeDetectionStrategy.OnPush,
imports: [CommonModule],
styles: [`
:host .led,
.led {
display: inline-block;
width: 10px;
height: 10px;
border-radius: 50%;
border: 0;
background-color: transparent;
vertical-align: middle;
}
.led-running { background-color: var(--color-success); }
.led-countdown { background-color: var(--color-warning); }
.led-stopped { background-color: var(--color-danger); }
.led-unconfigured { background-color: var(--color-secondary); }
`],
template: `
<header class="shell-header" data-testid="shell-header">
@@ -45,6 +39,7 @@ import { EventState } from '../../../core/services/event-status.store';
[class.led-countdown]="eventState() === 'countdown'"
[class.led-stopped]="eventState() === 'stopped'"
[class.led-unconfigured]="eventState() === 'unconfigured'"
[style.background-color]="ledColor()"
data-testid="shell-led"
[attr.aria-label]="'Event status: ' + eventState()"
></span>
@@ -120,5 +115,5 @@ export class ShellHeaderComponent {
readonly adminClick = output<void>();
readonly logoutClick = output<void>();
readonly ledClass = computed(() => `led led-${this.eventState()}`);
}
readonly ledColor = computed(() => ledBackgroundColor(this.eventState()));
}
+1 -5
View File
@@ -20,8 +20,4 @@ button[disabled] { opacity: .5; cursor: not-allowed; }
input { font: inherit; padding: 8px 12px; border: 1px solid var(--color-secondary); border-radius: var(--radius-sm); width: 100%; }
.container { max-width: 960px; margin: 0 auto; padding: 24px; }
.card { padding: 24px; border-radius: var(--radius-lg); box-shadow: 0 1px 4px rgba(0,0,0,.1); }
.led { display: inline-block; width: 10px; height: 10px; border-radius: 50%; border: 0; background-color: transparent; vertical-align: middle; }
.led-running { background-color: var(--color-success); }
.led-countdown { background-color: var(--color-warning); }
.led-stopped { background-color: var(--color-danger); }
.led-unconfigured { background-color: var(--color-secondary); }
.led { display: inline-block; width: 10px; height: 10px; border-radius: 50%; border: 0; background-color: transparent; vertical-align: middle; }