Editor Web Library

Documentation for the editor-web-lib Angular library with Flash-persistence and AI integration

Editor Web Library

The editor-web-lib library provides the core editor functionality for the GoGrab Space platform, featuring AI-powered editing, automatic state persistence, and intelligent user workflows.

Overview

Location: libs/editor-web-lib/
Dependencies: Angular 20+, @storage-system, @gograb-ai
Type: Feature Library
Purpose: Visual page editor with AI assistance

Features

Quick Start

Installation

The library is part of the monorepo. Import it in your application:

```typescript import { EditorRoutes } from '@editor-web-lib';

// Add to app routes export const routes: Routes = [ { path: 'editor', children: EditorRoutes } ]; ```

Basic Usage

```typescript import { Component } from '@angular/core'; import { Router } from '@angular/router';

@Component({ selector: 'app-root', template: ` <button (click)="openEditor()">Open Editor ` }) export class AppComponent { constructor(private router: Router) {}

openEditor() { this.router.navigate(['/editor']); } } ```

Architecture

Component Hierarchy

``` editor-web-lib/ ├── components/ │ ├── landing-editor/ # Welcome page with skip logic │ ├── editor-workspace/ # Main editor interface │ ├── execution-logs/ # Execution history │ ├── live-activity/ # Real-time updates │ └── widgets/ # Widget management ├── services/ │ ├── unified-events.service # Event communication │ └── project-detection.service # Project existence detection └── guards/ └── landing.guard # Landing skip logic ```

Data Flow

``` User → Landing Guard → Landing/Workspace ↓ Flash-Persistence ← Auto-save ↓ Storage System (IndexedDB/localStorage) ```

Key Concepts

Flash-Persistence

Automatic state persistence without manual localStorage management:

```typescript import { autoFlashState } from '@storage-system';

// Preferences auto-persist const prefs = autoFlashState('editor-preferences/landing', { showLandingByDefault: true, rememberLastProject: false });

// Update automatically saves prefs.update(p => ({ ...p, showLandingByDefault: false })); ```

Project Detection

Detect existing projects for skip logic:

```typescript import { ProjectDetectionService } from '@editor-web-lib/services';

constructor(private detection: ProjectDetectionService) {}

async checkProjects() { const hasProjects = await this.detection.hasExistingProjects(); const count = await this.detection.getProjectCount(); const recent = await this.detection.getRecentProjects(5); } ```

Landing Guard

Automatic navigation based on user preferences:

```typescript // In routes { path: 'landing', component: LandingComponent, canActivate: [landingGuard] }

// Guard logic: // - First-time users → Show landing // - Returning with skip → Go to workspace // - Remember last project → Open last project ```

Routes

Route Component Description
/editor Redirect Redirects to landing
/editor/landing LandingComponent Welcome page
/editor/workspace EditorWorkspaceComponent Main editor
/editor/execution-logs ExecutionLogsComponent Execution history
/editor/widgets WidgetsPanelComponent Widget browser

Components

Landing Component

Welcoming introduction with:

Learn more about Landing Page

Editor Workspace

Main editing interface with:

Execution Logs

View execution history:

Live Activity

Real-time updates via SSE:

Services

UnifiedEventsService

Cross-system event communication:

```typescript import { UnifiedEventsService } from '@editor-web-lib/services';

constructor(private events: UnifiedEventsService) {}

ngOnInit() { this.events.connect().subscribe(event => { console.log('Event:', event.type, event.data); }); } ```

ProjectDetectionService

Detect and manage projects:

```typescript // Check if user has projects const hasProjects = await this.detection.hasExistingProjects();

// Get project count const count = await this.detection.getProjectCount();

// Get recent projects const recent = await this.detection.getRecentProjects(10);

// Check specific project const exists = await this.detection.projectExists('project-123'); ```

Guards

Landing Guard

Controls landing page access with automatic skip logic:

```typescript // Configuration via Flash-persistence const prefs = { showLandingByDefault: false, // Skip landing rememberLastProject: true // Go to last project };

// Guard automatically: // 1. Checks preferences // 2. Detects existing projects // 3. Routes accordingly ```

Storage Keys

All editor data uses consistent key patterns:

Key Pattern Purpose Example
flash:editor-preferences/* User preferences flash:editor-preferences/landing
flash:editor-web/pages Page data All pages storage
flash:editor-preferences/recent-projects Recent projects Project history
gg_editor_user_id User identification localStorage only

Best Practices

1. Use Flash-Persistence

```typescript // ❌ Manual localStorage (old way) localStorage.setItem('prefs', JSON.stringify(prefs));

// ✅ Flash-persistence (new way) const prefs = autoFlashState('editor-preferences/workspace', defaultPrefs); ```

2. Check Project Existence

```typescript // Before navigation const hasProjects = await this.detection.hasExistingProjects(); if (!hasProjects) { // Show onboarding } ```

3. Use Landing Guard

```typescript // Always use guard for landing route { path: 'landing', component: LandingComponent, canActivate: [landingGuard] // ← Critical for UX } ```

4. Handle Async ngOnInit

```typescript // Use async for auto-skip logic async ngOnInit() { await this.checkShouldSkip(); // Continue initialization } ```

Advanced Topics

Troubleshooting

Landing page doesn't skip

Problem: Landing shows even when skip is enabled

Solution: Check preferences in storage: ```typescript // Debug preferences const prefs = await storage.get('flash:editor-preferences/landing'); console.log('Preferences:', prefs);

// Verify projects exist const hasProjects = await detection.hasExistingProjects(); console.log('Has projects:', hasProjects); ```

Flash-persistence not saving

Problem: Preferences reset on page refresh

Solution: Ensure storage is properly initialized: ```typescript // Check storage initialization import { provideGgStorage } from '@storage-system';

export const appConfig = { providers: [ provideGgStorage() // Required for Flash-persistence ] }; ```

Projects not detected

Problem: Guard always shows landing

Solution: Verify storage keys: ```typescript // Check storage keys const pages = await storage.get('flash:editor-web/pages'); const recent = await storage.get('flash:editor-preferences/recent-projects'); console.log('Pages:', pages, 'Recent:', recent); ```

See Also

API Reference

EditorRoutes

```typescript export const EditorRoutes: Routes = [ { path: '', redirectTo: 'landing', pathMatch: 'full' }, { path: 'landing', component: LandingComponent, canActivate: [landingGuard] }, { path: 'workspace', component: EditorWorkspaceComponent }, { path: 'execution-logs', component: ExecutionLogsComponent }, { path: 'widgets', component: WidgetsPanelComponent } ]; ```

Exports

```typescript // Routes export { EditorRoutes } from './lib/editor.routes';

// Components export { LandingComponent } from './lib/components/landing-editor'; export { EditorWorkspaceComponent } from './lib/components/editor-workspace';

// Services export { UnifiedEventsService } from './lib/services/unified-events.service'; export { ProjectDetectionService } from './lib/services/project-detection.service';

// Guards export { landingGuard } from './lib/guards/landing.guard'; ```

Contributing

When adding features to editor-web-lib:

  1. Use Flash-persistence for all state
  2. Follow Angular 20 standalone patterns
  3. Implement OnPush change detection
  4. Add comprehensive tests
  5. Document in this section
  6. Update routes if needed

License

Part of the GoGrab Space platform.