# Birleşik Tasarım Ortamı — Tasarım Dokümanı

**Tarih:** 2026-03-21
**Durum:** Onaylandı

## Özet

Sablon editörü ve widget editörü tek birleşik editör component'ine dönüştürülüyor. IWidget interface'i kaldırılıp ISablon genişletiliyor. Sürükle-bırak + Monaco kod + HTML modu birleşik çalışıyor. Canlı önizleme her düzenlemede gerçek zamanlı. Mobil uyumlu.

## Kararlar

1. **Kullanım:** Widget ve kart şablonları eşit ağırlıkta — aynı editör, fark sadece `tur` alanında
2. **Layout:** Hibrit — görsel canvas + alt Monaco kod paneli aynı anda görünür, mobilde paneller modal
3. **Palet:** Birleşik tek palet — 50+ element kategorize, context farkı yok
4. **Veri:** Birleşik veri katmanı — her şablon parametre + aggregate + socket + hesaplama kullanabilir
5. **Interface:** ISablon genişletilir, IWidget tamamen kaldırılır
6. **Mimari:** Yeni birleşik component (fiko-tasarim-editoru), eski editörler kaldırılır

## ISablon Genişletme

```typescript
ISablon {
  // Mevcut (korunur)
  mod: SablonMod                        // 'blok' | 'serbest' | 'hibrit'
  arkaPlan: ISablonArkaPlan
  bolgeler: ISablonBolge[]
  elementler: ISablonElement[]
  genislik?: number
  yukseklik?: number
  htmlModu?: boolean
  htmlIcerik?: string
  cssIcerik?: string
  jsIcerik?: string

  // Yeni — kimlik & meta (IWidget'tan)
  id?: string                           // widget/şablon kimlik
  tur?: 'widget' | 'kart' | 'serbest'  // varsayılan: 'kart'
  baslik?: string
  simge?: string
  aciklama?: string
  gorunur?: boolean                     // varsayılan: true
  silindi?: boolean
  yetki?: string[]
  sira?: number
  kaynak?: 'kod' | 'db'

  // Yeni — görünüm & konum
  pozisyon?: ISablonPozisyon            // { genislik, yukseklik, x?, y?, sira? }
  stil?: ISablonGorunumStil             // { arkaPlan?, gradyan?, renkYazi?, borderRadius?, golge? }

  // Yeni — veri & olaylar
  veriKaynagi?: ISablonVeriKaynagi
  olaylar?: ISablonOlaylar
  itemler?: ISablonItem[]
}
```

**Not:** Eski `IWidget.sablon?: ISablon` alt alanı elimine edilir. Widget'ın şablon içeriği (elementler, htmlModu, arkaPlan vb.) doğrudan ISablon kök seviyesinde bulunur.

### ISablonVeriKaynagi

Mevcut IWidgetVeriKaynagi alan adları **korunur** (DB geriye uyumluluk):

```typescript
ISablonVeriKaynagi {
  mod: 'aggregate' | 'sabit' | 'soket' | 'hesaplama'
  vt?: string                          // aggregate: hareketler vt değeri
  pipeline?: any[]                     // aggregate: MongoDB pipeline
  donusumFunc?: string                 // aggregate: JS transform fonksiyonu
  sabitVeri?: any                      // sabit: JSON veri
  soketOlay?: string                   // soket: Socket.IO event adı
  soketFiltre?: Record<string, any>    // soket: payload filtresi
  piFunc?: string                      // hesaplama: JS fonksiyon kodu
  yenilemeAraligi?: number             // polling saniye (0 = yok)
  soketTetik?: string                  // aggregate + socket tetik
}
```

### ISablonOlaylar

```typescript
ISablonOlaylar {
  tiklanma?: string
  yenilendi?: string
  esikAsimi?: string
  ciftTiklama?: string
  [key: string]: string | undefined    // custom olaylar
}
```

### ISablonItem

```typescript
ISablonItem {
  id: string
  sablon?: ISablon                     // nested alt şablon
  veriKaynagi?: ISablonVeriKaynagi
  olaylar?: ISablonOlaylar
  [key: string]: any                   // dinamik özellikler (simge, baslik, renk vb.)
}
```

### ISablonPozisyon

```typescript
ISablonPozisyon {
  genislik: number    // 1-4 grid sütun
  yukseklik: number   // 1-4 grid satır
  x?: number
  y?: number
  sira?: number
}
```

### ISablonGorunumStil

```typescript
ISablonGorunumStil {
  arkaPlan?: string
  gradyan?: string
  renkYazi?: string
  borderRadius?: number
  animasyon?: string            // CSS animasyon string (container seviyesi)
  golge?: string
}
```

### IDashboardAyarlar (güncellenir)

```typescript
IDashboardAyarlar {
  layout: 'grid' | 'serbest'
  kolonSayisi?: number
  aralik?: number
  widgetler: ISablon[]          // IWidget[] → ISablon[]
}
```

### ElementTur (birleşik, 45+ tür)

```typescript
type ElementTur =
  // Metin
  | 'sabit-metin' | 'parametre-metin' | 'parametre-render' | 'markdown'
  // Şekil
  | 'sekil' | 'resim'
  // Veri
  | 'sayac' | 'ilerleme-cubugu' | 'ilerleme-halka' | 'gauge'
  | 'sparkline' | 'bar-grafik' | 'pasta-grafik' | 'alan-grafik'
  | 'radar-grafik' | 'isi-haritasi' | 'seviye-cubugu'
  // Zaman
  | 'dijital-saat' | 'analog-saat' | 'countdown' | 'kronometr' | 'zaman-cizelgesi'
  // Durum
  | 'durum-dot' | 'durum-kart' | 'led-gosterge' | 'trafik-isigi' | 'sinyal-cubugu'
  // Liste
  | 'liste-tekrar' | 'siralama-listesi' | 'mini-tablo' | 'kanban-sutun'
  // Medya
  | 'avatar' | 'badge' | 'ticker' | 'qr-kod' | 'hava-durumu' | 'lottie' | 'iframe'
  // Kontrol
  | 'buton' | 'toggle' | 'slider' | 'tab-grup';
```

### Element Palet Kategorileri

| Kategori | Elementler |
|----------|-----------|
| Metin | sabit-metin, parametre-metin, parametre-render, markdown |
| Şekil & Medya | sekil, resim, avatar, badge, qr-kod, iframe, lottie |
| Veri & Grafik | sayac, gauge, sparkline, bar-grafik, pasta-grafik, alan-grafik, radar-grafik, isi-haritasi, ilerleme-cubugu, ilerleme-halka, seviye-cubugu |
| Zaman | dijital-saat, analog-saat, countdown, kronometr, zaman-cizelgesi |
| Durum | durum-dot, durum-kart, led-gosterge, trafik-isigi, sinyal-cubugu |
| Liste & Tablo | liste-tekrar, siralama-listesi, mini-tablo, kanban-sutun, ticker |
| Kontrol | buton, toggle, slider, tab-grup |

## Component Yapısı

Konum: `src/service/fikoyt-ui/src/lib/paylasim-sistemi/fiko-tasarim-editoru/`

| Component | Dosya | Sorumluluk |
|-----------|-------|------------|
| FikoTasarimEditoruComponent | `fiko-tasarim-editoru.component.ts` | Ana orchestrator, layout, state |
| TePaletComponent | `te-palet.component.ts` | 50+ element kategorize palet, sürükle-bırak ekleme |
| TeCanvasComponent | `te-canvas.component.ts` | Görsel düzenleme, seçim, resize, sürükle |
| TeKodPaneliComponent | `te-kod-paneli.component.ts` | Monaco (NzCodeEditorModule) HTML/CSS/JS/Olaylar tab'ları |
| TeStilPaneliComponent | `te-stil-paneli.component.ts` | Seçili element stil düzenleme |
| TeVeriPaneliComponent | `te-veri-paneli.component.ts` | Veri kaynağı + itemler |

## Responsive Layout

### Masaüstü (1200px+)
- Sol: Palet sidebar (56px, icon-only)
- Orta üst: Canvas (flex, sürükle-bırak + resize tutamaçları)
- Orta alt: Monaco kod paneli (resize edilebilir, HTML/CSS/JS/Olaylar tab)
- Sağ: Özellikler paneli (220px, Stil/Veri/Genel tab)

### Tablet (768–1199px)
- Sol: Palet toggle panel (180px, ✕ ile kapatılır)
- Orta: Canvas + kod paneli
- Stil/Veri: Araç çubuğundan NzDrawer olarak açılır

### Mobil (<768px)
- Canvas tam ekran
- Alt bar: 5 FAB butonu (Palet, Stil, Kod, Veri, Olaylar)
- Her panel bottom sheet modal (yarım/tam ekran sürüklenebilir)

## Performans

### State
- Tek `sablon = signal<ISablon>()` — immutable update
- Alt component'ler `computed()` ile sadece ilgili dilimi izler
- Önizleme: `effect()` ile 300ms debounce

### Rendering
- Tüm component'ler `OnPush`
- Canvas: `trackBy: element.id`
- Palet: statik, tek render
- Monaco: lazy load (NzCodeEditorModule), tab değişince init
- Resize/drag: `ngZone.runOutsideAngular()`, `requestAnimationFrame` throttle
- Pozisyon commit sadece mouseup'ta

### Lazy Loading
- Monaco: kod paneli açıkken yüklenir
- Veri paneli: `@defer`
- Mobil bottom sheet: `@defer (when panelAcik())`
- Touch event'ler passive, canvas `will-change: transform`

## Renderer Birleştirme

Mevcut sablon-renderer genişletilir, widget-renderer kaldırılır.

Eklenen mantık:
- `veriYukle()` — aggregate/sabit/hesaplama kaynaklarından veri çekme
- `soketBagla()` — Socket.IO event dinleme + `soketFiltre` ile payload filtreleme
- `pollingKur()` — yenileme aralığı interval
- `veriParametreleri = computed()` — veriyi parametreDegerleri'ne dönüştür
- Olay yürütme: `new Function('veri','sablon','router','bildirim','guncelle', kod)`

### Güvenlik

Olay yürütme (`new Function()`) ve JS kodu çalıştırma yalnızca `olaylarAktif` flag'i `true` olduğunda aktif olur. Varsayılan `false`. Consumer'lar açıkça opt-in eder:
- Dashboard: `olaylarAktif = true` (HMI context)
- icerikler / paylas-kutusu: `olaylarAktif = false` (güvenli render)

### Sablon-renderer ElementTur genişletme

Mevcut 15 element türüne ek olarak, `widget-elementler/` altındaki 30 component sablon-renderer'a import edilir. Her element türü `@switch` case'i ile render edilir.

## Migration

### Kaldırılacak
- `hmi-pano/dashboard/widget-editor/` (3 dosya)
- `hmi-pano/dashboard/widget-renderer/` (3 dosya)
- `hmi-pano/dashboard/interfaces/widget.interface.ts`
- `paylasim-sistemi/sablon-editoru/` (3 dosya)

### Güncellenecek Consumer'lar

| Consumer | Dosya | Değişiklik |
|----------|-------|-----------|
| Dashboard component | `hmi-pano/dashboard/dashboard.component.ts` | `IWidget[]` → `ISablon[]`, widget-renderer → sablon-renderer |
| DashboardService | `hmi-pano/dashboard/dashboard.service.ts` | Tüm metod imzaları `IWidget` → `ISablon`. Alan adları korunduğu için iç mantık aynı kalır |
| hazir-widgetler.ts | `hmi-pano/dashboard/hazir-widgetler.ts` | `IWidget` → `ISablon` tip, `tur: 'widget'` eklenir, `sablon` alt alanı kök seviyeye taşınır |
| IDashboardAyarlar | `hmi-pano/dashboard/interfaces/` | `widgetler: IWidget[]` → `widgetler: ISablon[]` (sablon.interface.ts'e taşınır) |
| paylas-icerik-editor | `paylas-kutusu/IKart/paylas-icerik-editor/` | SablonEditoruComponent → FikoTasarimEditoruComponent |
| icerikler.component | `fikoyt-kart-kok/icerikler/` | Değişiklik yok — sablon-renderer kullanmaya devam, veri/olay mantığı opt-in |
| HMI routes | `hmi-pano/hmi-pano.routes.ts` | `widget-editor/:widgetId` route → fiko-tasarim-editoru'na yönlendirilir |
| paylas-kutusu / ikart-kutusu | — | Zaten ISablon — değişiklik yok |

### DashboardService Metod Eşlemesi

| Mevcut Metod | Değişiklik |
|-------------|-----------|
| `widgetVerisiCek(widget: IWidget)` | `sablonVerisiCek(sablon: ISablon)` — iç alan adları aynı (vt, piFunc, donusumFunc) |
| `widgetGuncelle(id, degisiklikler: Partial<IWidget>)` | `sablonGuncelle(id, degisiklikler: Partial<ISablon>)` |
| `widgetEkle(widget: IWidget)` | `sablonEkle(sablon: ISablon)` |
| `widgetSil(id)` | `sablonSil(id)` |
| `soketDinle(widget: IWidget, cb)` | `soketDinle(sablon: ISablon, cb)` — soketFiltre mantığı korunur |
| `birlestir(ts, db)` | Aynı — `gorunur`, `silindi` filtreleri korunur |

### Geriye Uyumluluk
- DB'deki mevcut widget kayıtları `tur: 'widget'` olarak okunur
- `kaynak: 'kod'` hazır widget'lar TS'de kalır
- `kaynak: 'db'` olanlar DB'den yüklenir
- VeriKaynagi alan adları (`vt`, `piFunc`, `donusumFunc`, `soketFiltre`) korunur — DB migration gerekmez
- `tur` belirtilmemiş ISablon'lar varsayılan `'kart'` olarak kabul edilir
