Appearance
Kiến trúc Boxme AI Insight
Quick Reference
- Type: Embedded Angular SPA (standalone components)
- Stack: Angular 19, TypeScript 5.9, TailwindCSS 4, ECharts
- State: Signal-based (không dùng NgRx)
- Pattern: Container/Presenter, Lazy-loaded features
- Deployment: Docker (Node 20 + Nginx)
Tổng quan Kiến trúc
Boxme Insight là module "nhúng" (embedded), nhận JWT token từ parent app (oms.boxme.asia) qua localStorage/cookie/URL param, rồi giao tiếp với backend insights.omisell.com qua REST API.
mermaid
graph TB
subgraph Shell ["Parent App (oms.boxme.asia)"]
ParentUI["OMS Dashboard"]
Token["JWT Token"]
end
subgraph Frontend ["Boxme AI Insight — Angular 19"]
Auth["Auth Service"]
Chat["AI Chat"]
Insights["Insight Catalog"]
Dashboards["Dashboard Builder"]
Settings["Settings & Config"]
Shared["Shared: Charts + Tables"]
end
subgraph Backend ["Omisell Insights API"]
Gateway["API Gateway"]
AI["LLM Engine"]
DB["PostgreSQL"]
Scheduler["Cron Scheduler"]
end
subgraph Channels ["Notification"]
TG["Telegram"]
Email["Email"]
Lark["Lark"]
end
ParentUI -- "iframe / postMessage" --> Auth
Token -- "localStorage / cookie" --> Auth
Auth --> Chat
Auth --> Insights
Auth --> Dashboards
Auth --> Settings
Chat --> Shared
Dashboards --> Shared
Insights --> Shared
Chat -- "POST /ai/chat" --> Gateway
Insights -- "POST /insights/execute" --> Gateway
Dashboards -- "CRUD /dashboards" --> Gateway
Settings -- "CRUD /connectors, /channels" --> Gateway
Gateway --> AI
Gateway --> DB
Scheduler -- "Scheduled reports" --> Gateway
Scheduler --> ChannelsMô tả: Frontend Angular 19 hoạt động trong ngữ cảnh nhúng. Token JWT chứa thông tin user (id, email, role, tenant_id, seller_type). Backend xử lý AI inference, truy vấn DB, và gửi scheduled reports qua notification channels.
Các thành phần chính
| Component | Mô tả | Key Files |
|---|---|---|
| Auth Layer | JWT management, route guards, token resolution | auth.service.ts, auth.guard.ts, auth.interceptor.ts |
| AI Chat | NLP chat interface, artifact rendering | chat.component.ts, chat.service.ts, artifact-renderer.component.ts |
| Insight Catalog | Browse/search/execute pre-built insights | insight-catalog.component.ts, insight-detail.component.ts |
| Dashboard Builder | Custom dashboards, widgets, filters, sharing | dashboard-view.component.ts, dashboard.service.ts, widget-card.component.ts |
| Settings | AI connectors, notification channels, subscriptions | settings.component.ts, ai-config-wizard.component.ts |
| Chart Renderer | ECharts wrapper — 7 chart types | chart-renderer.component.ts |
| Data Table | Paginated table with sort/export | data-table.component.ts |
| Permission | RBAC checks (owner/admin/member) | permission.service.ts |
Angular 19 Patterns
Toàn bộ components cấu hình standalone: true, sử dụng @if, @for control flow mới. State quản lý bằng Angular Signals (computed, effect) thay vì NgRx store.
Main Processing Flow
mermaid
sequenceDiagram
participant User
participant Angular UI
participant Signal State
participant Interceptor Pipeline
participant Backend
User->>Angular UI: Nhập câu hỏi / Execute insight
Angular UI->>Signal State: set loading = true
Angular UI->>Interceptor Pipeline: HTTP Request
Note over Interceptor Pipeline: 1. Demo check<br/>2. Auth header<br/>3. Error handler
Interceptor Pipeline->>Backend: Request + JWT
Backend-->>Interceptor Pipeline: { data, chart_hint, alerts }
Interceptor Pipeline-->>Angular UI: Response
Angular UI->>Signal State: Update data signals
Angular UI-->>User: Render ECharts / Data Table / MarkdownPermission Model (RBAC)
mermaid
graph LR
subgraph Roles ["OrgRole"]
Owner["Owner"]
Admin["Admin"]
Member["Member"]
end
subgraph Actions ["Permissions"]
ChatAll["AI Chat: Full"]
InsightAll["Insights: Full"]
DashCreate["Dashboard: Create/Edit/Delete"]
DashView["Dashboard: View Shared"]
SettingsFull["Settings: Full"]
end
Owner --> ChatAll
Owner --> InsightAll
Owner --> DashCreate
Owner --> SettingsFull
Admin --> ChatAll
Admin --> InsightAll
Admin --> DashCreate
Admin --> SettingsFull
Member --> ChatAll
Member --> InsightAll
Member --> DashViewSource: (src/app/core/services/permission.service.ts:1-42)
Member có thể xem Dashboard nếu is_shared=true hoặc shared_with_emails chứa email của họ. Owner/Admin có quyền tạo, sửa, xoá mọi dashboard.
Demo Mode Architecture
mermaid
flowchart LR
A["HTTP Request"] --> B{"environment.demoMode?"}
B -- "true" --> C["DemoInterceptor"]
C --> D["Return mock JSON + simulated delay"]
B -- "false" --> E["AuthInterceptor → Backend"]Frontend hỗ trợ chế độ offline với DemoInterceptor (demo.interceptor.ts:1-256):
- Intercept tất cả
/api/v1/*requests khidemoMode=true - Trả mock data với simulated delay (200ms-3000ms tùy loại request)
- Mock data: 12 insights, 2 dashboards, 3 channels, 3 subscriptions, 8 chat patterns
- Cho phép develop/test UI mà không cần backend
Architecture Decision Records (ADR)
| # | Quyết định | Lý do | Trạng thái |
|---|---|---|---|
| 1 | Angular Signals thay vì NgRx | App size trung bình, signals đủ cho state management, giảm boilerplate | Accepted |
| 2 | Standalone Components | Angular 19 best practice, tree-shakeable, lazy-load dễ hơn | Accepted |
| 3 | Demo Mode via Interceptor | Cho phép UI development song song backend, giảm dependency | Accepted |
| 4 | Embedded Architecture | Tận dụng auth flow của parent app (oms.boxme.asia), SSO tự nhiên | Accepted |
| 5 | ECharts thay vì Chart.js | Hỗ trợ nhiều chart type hơn (heatmap, stacked), đẹp hơn out-of-box | Accepted |
| 6 | TailwindCSS 4 | Utility-first, custom theme dễ, dark mode tự nhiên | Accepted |
ADR-001: Angular Signals thay vì NgRx
Context: Cần state management cho chat messages, dashboard widgets, loading states.
Decision: Dùng Angular Signals (signal, computed, effect) thay vì NgRx store.
Consequences:
- Ít boilerplate hơn (không cần actions, reducers, effects)
- Performance tốt hơn nhờ fine-grained reactivity
- Trade-off: không có Redux DevTools, time-travel debugging
ADR-003: Demo Mode via HttpInterceptor
Context: Frontend team cần develop UI song song với backend team. Backend API chưa stable.
Decision: Tạo DemoInterceptor intercept tất cả API calls khi demoMode=true, trả mock data.
Consequences:
- UI development không bị block bởi backend
- Mock data phản ánh real API contract (dùng chung interfaces)
- Trade-off: cần maintain mock data song song với real API
Security
| Layer | Mechanism | Source |
|---|---|---|
| Authentication | JWT token (4 nguồn: URL, localStorage, cookie, demo) | auth.service.ts:50-100 |
| Authorization | Header Authorization: Omi <token> | auth.interceptor.ts:10-20 |
| Route Protection | authGuard functional guard trên mọi route | auth.guard.ts:1-32 |
| RBAC | PermissionService check role cho dashboard operations | permission.service.ts |
| Error Handling | Global interceptor: 401→logout, 403→log, 500→log | error.interceptor.ts |
| Token Storage | localStorage key boxme_insight_token | environment.ts:6 |
Liên kết
- Phân tích Mã nguồn — Chi tiết code analysis
- Data Flow — Luồng dữ liệu chi tiết
- Deployment — Hướng dẫn triển khai
- Process Flows — Luồng quy trình nghiệp vụ