# Orchestration Triggers — Usage Guide

The `OrchestrationService` now supports triggering actions from multiple sources in your app flow. Use `triggerActions()` to fire orchestration workflows from anywhere.

---

## Trigger Sources

```typescript
enum OrchestrationTriggerSource {
  Login = 'Login',           // 1️⃣ After user login
  ModuleClick = 'ModuleNavigation',  // 2️⃣ When module is clicked
  MenuClick = 'MenuNavigation',      // 3️⃣ When menu is clicked (existing)
  Custom = 'Custom'          // Any other custom trigger
}
```

---

## Usage Pattern

```typescript
import { OrchestrationService, OrchestrationTriggerSource } from 'features/gborchestration/service/orchestration.service';

// Inject the service
private orchestrationService = inject(OrchestrationService);

// Call triggerActions() with appropriate trigger source
this.orchestrationService.triggerActions({
  triggerSource: OrchestrationTriggerSource.Login,  // ← Source
  loginDTO: this.loginDTO,                          // ← User context
  menuData?: this.menuData,                         // ← Optional: Menu context
  customContext?: { moduleId: 123 }                 // ← Optional: Custom data
});
```

---

## 1️⃣ Trigger During Login

Call this in **login service** after successful authentication:

```typescript
// features/login/service/login.service.ts

import { OrchestrationService, OrchestrationTriggerSource } from 'features/gborchestration/service/orchestration.service';

export class Loginservice {
  private orchestrationService = inject(OrchestrationService);

  public async loginComplete(loginDTO: any) {
    // ✅ User logged in successfully
    console.log('Login complete, triggering orchestration actions...');
    
    this.orchestrationService.triggerActions({
      triggerSource: OrchestrationTriggerSource.Login,
      loginDTO: loginDTO
    });
  }
}
```

**Location:** Call after setting `sessionStorage['LoginDTO']` and redirecting to main app.

---

## 2️⃣ Trigger On Module Click

Call this in **GbMainComponent** or **MenuService** when a module is selected:

```typescript
// features/gbmain/gbmain/gbmain.component.ts

import { OrchestrationService, OrchestrationTriggerSource } from 'features/gborchestration/service/orchestration.service';

export class GbMainComponent implements OnInit {
  private orchestrationService = inject(OrchestrationService);
  
  // In your module selection handler:
  onModuleSelected(moduleId: number, moduleName: string) {
    const loginDTO = JSON.parse(sessionStorage.getItem('LoginDTO') as string);
    
    // ✅ Trigger actions when module is clicked
    this.orchestrationService.triggerActions({
      triggerSource: OrchestrationTriggerSource.ModuleClick,
      loginDTO: loginDTO,
      customContext: {
        moduleId: moduleId,
        moduleName: moduleName
      }
    });
  }

  // Or integrate into your existing module navigation:
  onQueryParamsChange(params: any) {
    let moduleId = params['moduleid'];
    // ... decrypt if needed ...
    
    if (moduleId !== this.ModuleId && moduleId !== -1) {
      this.ModuleId = Number(moduleId);
      const loginDTO = JSON.parse(sessionStorage.getItem('LoginDTO') as string);
      
      // ✅ Trigger orchestration on module change
      this.orchestrationService.triggerActions({
        triggerSource: OrchestrationTriggerSource.ModuleClick,
        loginDTO: loginDTO,
        customContext: {
          moduleId: this.ModuleId,
          moduleName: 'Shipping'  // or derive from MenuList
        }
      });
    }
  }
}
```

**Location:** In module click handler or module route change logic.

---

## 3️⃣ Trigger On Menu Click

This already works via `@Input` changes, but you can also trigger explicitly:

```typescript
// features/gbmain/gbmain/gbmain.component.ts (or any menu handler)

onMenuSelected(menuData: any) {
  const loginDTO = JSON.parse(sessionStorage.getItem('LoginDTO') as string);
  
  // ✅ Trigger actions when menu is clicked (optional explicit call)
  this.orchestrationService.triggerActions({
    triggerSource: OrchestrationTriggerSource.MenuClick,
    loginDTO: loginDTO,
    menuData: {
      MenuDetails: {
        ModuleName: 'Shipping',
        DisplayName: 'Port Management',
        Id: 123,
        ListMenuId: 456,
        WebFormSecondURL: 'PortComponent',
        MenuType: 1
        // ... other menu fields
      }
    }
  });
}

// Or rely on the existing @Input binding in OrchestrationComponent:
// <gb-orchestration [MenuData]="currentMenuData"></gb-orchestration>
```

**Location:** Menu click handler or existing OrchestrationComponent @Input flow.

---

## 4️⃣ Trigger Custom Actions

For any other trigger source:

```typescript
this.orchestrationService.triggerActions({
  triggerSource: OrchestrationTriggerSource.Custom,
  loginDTO: loginDTO,
  customContext: {
    eventType: 'InventoryLow',
    entityId: 789,
    details: { quantity: 50, threshold: 100 }
  }
});
```

---

## Data Passed to Backend

The payload sent to `Framework.Enablement.show` API includes:

```json
{
  "requestId": "req-2026-05-06-123456",
  "clientTimestamp": "2026-05-06T12:34:56.789Z",
  "context": {
    "database": { "dbName": "goodbooksdb" },
    "user": { "userId": 123, "userCode": "VV", "userName": "Venkat" },
    "ui": { "product": "GoodBooks", "module": "Shipping", "menu": "Port", "menuId": 123 },
    "entity": { "entityType": "Menu", "entityId": 123 },
    "trigger": {
      "type": "Login|ModuleNavigation|MenuNavigation|Custom",
      "source": "Login|ModuleNavigation|MenuNavigation|Custom",
      "key": "Login.Complete|Module.Shipping.Open|Port.Open"
    },
    "temporal": { "businessDate": "2026-05-06", "workPeriodId": -1 },
    "custom": { "criteria": "NONE", "expandable": false },
    "stateHints": { "alreadySeen": [], "completed": [] }
  }
}
```

---

## Component Side

The `OrchestrationComponent` listens to both:
1. **Signal-based events** from `this.orchestrationService.getTriggerStream()`
2. **@Input changes** from `MenuData` (existing flow)

Both trigger the same `handleOrchestrationTrigger()` method, which builds the payload and calls the API.

---

## Complete Example: Module Navigation Flow

```typescript
// gbmain.component.ts
export class GbMainComponent {
  private orchestrationService = inject(OrchestrationService);
  private menuService = inject(MenuService);

  constructor(private route: ActivatedRoute) {
    this.route.queryParams.subscribe(params => {
      let moduleId = params['moduleid'];
      const loginDTO = JSON.parse(sessionStorage.getItem('LoginDTO') as string);

      if (moduleId && moduleId !== this.ModuleId) {
        this.ModuleId = Number(moduleId);

        // ✅ Load module menu list
        this.menuService.getmenulistservice(this.ModuleId).subscribe((res) => {
          this.MenuList = res.responseValue;

          // ✅ Trigger orchestration on module change
          this.orchestrationService.triggerActions({
            triggerSource: OrchestrationTriggerSource.ModuleClick,
            loginDTO: loginDTO,
            customContext: {
              moduleId: this.ModuleId,
              moduleName: this.getModuleName(this.ModuleId)
            }
          });
        });
      }
    });
  }

  getRoutingMenuDetails(MenuId: number) {
    // Menu click → passes MenuData to orchestration component via @Input
    // Component automatically triggers via ngOnChanges
  }
}
```

---

## Error Handling

```typescript
this.orchestrationService.triggerActions({
  triggerSource: OrchestrationTriggerSource.Login,
  loginDTO: loginDTO
});

// Component handles errors internally and logs to console
// Check console for: "API response:", "Error fetching actions:", etc.
```

---

## Notes

- **loginDTO** is required for all triggers (user context)
- **menuData** is optional (used for menu/menu-specific context)
- **customContext** is flexible (module ID, event type, etc.)
- The component uses `takeUntilDestroyed()` to clean up subscriptions automatically
- Actions are displayed sequentially with 300ms delay between each
- Use `OverlayLauncherService` or `MatDialog` for different action types
