feat(sprint18): editor autosave/reset, admin auth, QR reuse, Ed25519 prep
Some checks failed
Architecture Governance / architecture (push) Has been cancelled

- Project editor: persist draft to localStorage, restore on reload,
  last-saved/draft-restored status indicators, section/whole-draft reset
  with confirmation.
- Extract shared QR/polling/expiry engine from TelegramLoginComponent
  (shared/qr-login) and reuse it for a new admin login flow.
- Admin authentication kept fully separate from customer session:
  own cookie/localStorage keys, signals, guard, and header interceptor
  (core/admin-auth).
- ?login=true / ?adminLogin=true open the respective login dialog for
  manual testing.
- Ed25519 challenge/verify interfaces (fail-closed no-op binding) ready
  for backend delivery.
- Document autosave/reset/admin-auth/QR-reuse/Ed25519 model and the
  remaining full-field-coverage gap in docs/Project-Editor.md.
This commit is contained in:
sdarbinyan
2026-07-14 09:50:03 +04:00
parent c6482f0037
commit 3877b70fdf
33 changed files with 1423 additions and 171 deletions

View File

@@ -15,10 +15,13 @@ import { PlatformRuntimeService } from './core/runtime/platform-runtime.service'
import { UiRuntimeFacade } from './facades/runtime/ui-runtime.facade';
import { ApiHealthService } from './services/api-health.service';
import { FloatingNotificationsComponent } from './features/website/user-experience/components/floating-notifications/floating-notifications.component';
import { AdminLoginComponent } from './core/admin-auth/admin-login.component';
import { AdminAuthService } from './core/admin-auth/admin-auth.service';
import { AuthService } from './services/auth.service';
@Component({
selector: 'app-root',
imports: [RouterOutlet, HeaderComponent, FooterComponent, BackButtonComponent, TranslatePipe, FloatingNotificationsComponent],
imports: [RouterOutlet, HeaderComponent, FooterComponent, BackButtonComponent, TranslatePipe, FloatingNotificationsComponent, AdminLoginComponent],
templateUrl: './app.html',
styleUrl: './app.scss'
})
@@ -37,6 +40,8 @@ export class App implements OnInit {
private platformRuntime = inject(PlatformRuntimeService);
private uiRuntime = inject(UiRuntimeFacade);
private apiHealth = inject(ApiHealthService);
private authService = inject(AuthService);
private adminAuthService = inject(AdminAuthService);
ngOnInit(): void {
this.platformRuntime.initialize();
@@ -44,6 +49,7 @@ export class App implements OnInit {
this.titleService.setTitle(`${this.uiRuntime.marketplaceDisplayName()} - ${this.i18n.t('app.pageTitle')}`);
this.checkServerHealth();
this.setupAutoUpdates();
this.openLoginDialogsFromTestModeQueryParams();
// Track route changes to show/hide back button
this.router.events
@@ -79,6 +85,20 @@ export class App implements OnInit {
this.checkServerHealth();
}
/** ?login=true / ?adminLogin=true open the respective login dialog for manual testing. No effect when absent. */
private openLoginDialogsFromTestModeQueryParams(): void {
if (typeof window === 'undefined') {
return;
}
const params = new URLSearchParams(window.location.search);
if (params.get('login') === 'true') {
this.authService.requestLogin();
}
if (params.get('adminLogin') === 'true') {
this.adminAuthService.requestLogin();
}
}
private setupAutoUpdates(): void {
if (!this.swUpdate.isEnabled) {
return;