1544 lines
121 KiB
Markdown
1544 lines
121 KiB
Markdown
# Low-Code Genişletilmiş Referans (JSON Kolon ve Modül Sözleşmeleri)
|
||
|
||
`lowcode.instructions.md` **nasıl üretileceğini** anlatır; bu dosya **neyin ayarlanabildiğini**
|
||
tek tek listeler. Orada "bunun bir JSON kolonu var" denen her şeyin alan alan karşılığı burada
|
||
durur: ListForm/ListFormField'ın tüm JSON kolonları, grafik sözleşmesi, Visual Designer envanteri
|
||
ve zamanlanmış e-posta modülü. Son bölüm (§12) Saas, Administration ve İK (Hr) menülerindeki **hazır
|
||
gelen bütün ekranları** ve bunların yeni bir komponentte nasıl kullanılacağını listeler.
|
||
|
||
**Kullanım sırası:** `ai.instructions.md` → `lowcode.instructions.md` → **bu dosya** → `README.md`.
|
||
Bir istek geldiğinde önce ana dosyadaki karar sırasını işlet; "hangi anahtarı yazacağım?"
|
||
sorusunda buraya bak.
|
||
|
||
**Kaynak:** Buradaki her tablo `api/src/Sozsoft.Platform.Application.Contracts/ListForms/**`
|
||
(DTO), `api/src/Sozsoft.Platform.Domain/Entities/Tenant/ListForm/ListForm{,Field}.cs` (entity),
|
||
`ui/src/views/{list,form}/**` (alanın gerçekten okunup okunmadığı) ve §12 için
|
||
`configs/seeds/host/data/App.Menus.*.json` + `ListFormSeeder_*.cs` dosyalarından çıkarılmıştır.
|
||
Çelişki hâlinde **kod esastır**; bu dosya güncellenir.
|
||
|
||
**Ortak kurallar**
|
||
|
||
- Bütün `*Json` kolonları veritabanında **tek satır JSON string** olarak durur. Wizard seed
|
||
dosyasının `ListForm`/`Fields` bölümleri ekranın DTO sözleşmesini taşıdığı için orada bu
|
||
kolonlar kaçışlanmış metin değil, tipli karşılıkları (`SchedulerOptionJson` →
|
||
`SchedulerOptionDto`) olarak yer alır; kaçışlama yalnızca `EditorOptions`, `EditorScript`,
|
||
`LookupQuery` gibi gerçekten metin olan alanlar içindir.
|
||
- Varsayılan değeri olan bir alanı tekrar yazmak zorunda değilsin; yalnızca farklı olanı yaz.
|
||
- `Accepted Values` yazan yerlerde değer birebir eşleşmelidir (büyük/küçük harf dahil).
|
||
- **Bilinmeyen anahtar sessizce düşer — tarayıcıya hiç ulaşmaz.** `GridOptionsDto` (ekran) ve
|
||
`ColumnFormatDto` (alan) `*Json` kolonlarının ham metnini `[JsonIgnore]` ile gizler ve istemciye
|
||
yalnızca tipli DTO'ya (`SchedulerOptionJson` → `SchedulerOptionDto`) çözülmüş hâlini yollar.
|
||
Dolayısıyla:
|
||
- DTO'da olmayan bir DevExtreme seçeneğini `*Json`'a yazmak **işe yaramaz**; kalıcı olarak
|
||
gerekiyorsa önce ilgili DTO'ya alan eklenir (ve bu dosya güncellenir).
|
||
- Çözme `JsonSerializer`'ın varsayılan ayarlarıyla yapılır: anahtarlar **PascalCase ve
|
||
büyük/küçük harfe duyarlıdır**. `"visible"` yazılan yerde `"Visible"` beklenir; küçük harfli
|
||
anahtar hata vermez, sessizce düşer. İstemcinin gördüğü camelCase hâl API çıktısıdır, seed'e
|
||
yazılmaz.
|
||
- Yanlış **tipte** yazılan değer (`"3"` yerine `3`, dizi yerine metin) `JsonSerializer`
|
||
tarafında `JsonException` fırlatır ve ekranın metadata isteği tamamen düşer — sessiz
|
||
değil, gürültülü bir hatadır. Tipleri tablodaki gibi yaz.
|
||
- Bu kural yalnızca alan seviyesindeki `ListFormField.EditorOptions` için geçmez: orası
|
||
ham metin olarak taşınır, tanımadığı anahtarı doğrudan editöre geçirir (§9.8).
|
||
|
||
---
|
||
|
||
## 0. Üretim yetenek envanteri — bir komponent üretirken tara
|
||
|
||
Bir ekran/komponent üretirken **her katmanı sırayla geç**. Cevabı "gerekmiyor" olan katmanı atla,
|
||
ama hiçbirini görmeden bırakma; kullanıcı "şunu da yapabilir miydik?" dediğinde cevap
|
||
"kod yazmamız gerekir" olmasın.
|
||
|
||
| # | Katman | Sorulacak soru | Nerede |
|
||
| --- | --- | --- | --- |
|
||
| 0 | **Hazır yetenek** | Bu talebin karşılığı Saas/Administration/İK menüsünde zaten var mı? | §12.6 |
|
||
| 1 | **Veri** | Tablo/view var mı, join gerekiyor mu, anahtar ve tipi ne? | `lowcode` §8 · §9.6 |
|
||
| 2 | **Ekran türü** | Liste mi, tek kayıt formu mu, serbest yerleşim mi? Kaç görünüm açılacak? | `lowcode` §0.6.1 · §9.8 · §5.4 |
|
||
| 3 | **Sütunlar** | Editör tipi, biçim, hizalama, genişlik, band, gizli/aktif | `lowcode` §4.3 · §9.7 |
|
||
| 4 | **Lookup** | Sabit liste mi, sorgu mu, servis mi? Cascade var mı? | `lowcode` §4.3.4 |
|
||
| 5 | **Varsayılanlar** | Kullanıcı/tarih/tenant/sequence/sorgu ile otomatik dolacak alanlar | `lowcode` §4.3.5 · §9.9 |
|
||
| 6 | **Alan davranışı** | Hesap, kopyalama, temizleme, koşullu kilit, uyarı, servis çağrısı | `lowcode` §5 |
|
||
| 7 | **Editör görünümü** | Maske, ondalık, tarih biçimi, arama, çoklu seçim, görsel yükleme, kamera/barkod/konum | `lowcode` §6 · §9.8 |
|
||
| 8 | **Doğrulama** | Zorunluluk, aralık, desen, karşılaştırma + sunucu tarafı kontrol | `lowcode` §4.3.6 · §4 |
|
||
| 9 | **Filtre/arama** | Filtre satırı, başlık filtresi, arama paneli, ek filtre çubuğu, grup paneli | §2.6 · `lowcode` §4.3.8 |
|
||
| 10 | **Özet** | Toplam/adet satırı, grup özetleri, pivot | §9.5 · §6 |
|
||
| 11 | **Biçimlendirme** | Koşullu satır/hücre rengi, CSS sınıfı | `lowcode` §4.3.7 |
|
||
| 12 | **Düzenleme deneyimi** | Popup/satır/hücre/batch, form grupları, kopyalama, toplu silme | §3 |
|
||
| 13 | **Aksiyonlar** | Toolbar ve satır butonları: adres, diyalog, script, yetki, koşullu görünürlük | `lowcode` §4.9 |
|
||
| 14 | **Yazma mantığı** | Özel SQL, before/after kancaları, farklı servis adresi | §4 |
|
||
| 15 | **Ana-detay** | Alt form sekmeleri ve ilişki alanları | §5.2 |
|
||
| 16 | **Gösterge** | Üstte KPI kartları, grafik | §5.3 · §8 |
|
||
| 17 | **Süreç** | Onay akışı, bilgilendirme, durum alanları | `lowcode` §4.7 |
|
||
| 18 | **Otomasyon** | Zamanlanmış iş, zamanlanmış e-posta, bildirim kuralı | `lowcode` §9.10–§9.11 · §11 |
|
||
| 19 | **Çıktı** | Hazır grid raporu ya da rapor şablonu | `lowcode` §9.12 |
|
||
| 20 | **Yetki** | Ekran, alan, komut ve buton yetkileri; menü görünürlüğü | §5.1 · `lowcode` §4.2 |
|
||
| 21 | **Tenant/şube/satır kısıtı** | `IsTenant`, `IsBranch`, `IsOrganizationUnit`, sorgularda kırılım, rol/kullanıcıya `ServerWhere` | `lowcode` §4.2 · §2.5 |
|
||
| 22 | **Dil** | Menü, başlık, alan, buton, mesaj metinleri EN + TR | `lowcode` §4.2 |
|
||
| 23 | **Kullanıcı tercihi** | Grid durumunun saklanması, kullanıcı/rol/dil varyantı | §2.5 · §5.7 |
|
||
| 24 | **Seed** | Üretilen her artefaktın dosyası + yalnızca DB'de yaşayan kayıtların geri getirici script'i | `lowcode` §0.2 · §9.14 |
|
||
|
||
Serbest yerleşimli bir komponent (Visual Designer) üretiyorsan 0–2 ve 13–24 aynen geçerlidir;
|
||
3–12 yerine tasarımcı envanteri (§10.1), `Form` sözleşmesi (§10.2), veri kaynağı/filtre
|
||
sözleşmesi (§10.4), bileşen prop sözleşmeleri (§10.5–§10.9), olay yükleri (§10.10) ve event
|
||
script'leri (`lowcode` §7.8) kullanılır. 20. katman (yetki) orada
|
||
iki yerdedir: düğüm başına `designerPermission` ve `Form`'un dört komut yetkisi.
|
||
|
||
Katmanların çoğunda cevap yeni bir artefakt değil, platformun **hazır bir ekranıdır**: numaratör,
|
||
bildirim, zamanlanmış iş, rapor, ayar, dil, yetki, şube, kısıt, dosya. Hepsinin envanteri §12'de —
|
||
"kod yazmamız gerekir" demeden önce §12.6'ya bak.
|
||
|
||
---
|
||
|
||
## 1. ListForm JSON kolon haritası
|
||
|
||
Bir List ekranının bütün davranışı bu kolonlardadır. "Şunu yapabilir miyiz?" sorusunun cevabı
|
||
önce bu tabloda aranır.
|
||
|
||
Aşağıdaki tablo `*Json` bloklarını listeler. Bunların **öncesinde** ekranın düz kolonları gelir
|
||
ve çoğu isteğin cevabı aslında oradadır:
|
||
|
||
| Kolon | Varsayılan | Ne yapar |
|
||
| --- | --- | --- |
|
||
| `ListFormCode` | — | Ekranın kimliği; route, metadata ve varyantlar bu koda bağlanır |
|
||
| `DataSourceCode` | `"Default"` | Hangi bağlantıdan okunacağı (`Sas_H_DataSource`) |
|
||
| `SelectCommandType` | `1` Table | `1` Table · `2` View · `3` TableValuedFunction · `4` Query · `5` StoredProcedure |
|
||
| `SelectCommand` | — | Tablo/view adı, fonksiyon çağrısı ya da sorgu metni |
|
||
| `TableName` | `SelectCommand` | Üretilen `SELECT`'te kolonların ve join'lerin önüne yazılan **alias**. Boşsa `SelectCommand` kullanılır. `4` Query'de **zorunludur**: sorgu `FROM (…) AS "{TableName}"` biçiminde türetilmiş tablo olarak sarılır ve boş bırakılırsa sorgu metni alias olur (SQL hatası). Wizard/MCP `deploy_wizard` Query ekranına `"Q"` (`WizardConsts.QuerySourceAlias`) yazar; fonksiyon çağrısında da kısa bir ad yaz |
|
||
| `KeyFieldName` · `KeyFieldDbSourceType` | — · `16` String | Anahtar kolon ve `System.Data.DbType` karşılığı. `4` Query'de ikisi de **zorunludur** (kolonlar katalogdan okunamaz); wizard/`deploy_wizard` anahtarsız Query ekranını reddeder, tip boşsa (`0`) seçilen alanlardaki karşılığından tamamlar. Ana tablo (en dıştaki `FROM`) `IsDeleted` taşıyorsa `DefaultFilter` yazılır ve sorgu `IsDeleted`'i seçmek zorundadır |
|
||
| `SelectFieldsDefaultValueJson` | — | **Okuma** sorgusuna parametre olarak katılan değerler (`FieldsDefaultValueDto[]`) — `@USERID`, `@TENANTID` gibi |
|
||
| `DefaultFilter` | — | Her sorgunun sonuna `AND` ile eklenen sabit `WHERE` koşulu. `DefaultValueHelper` üzerinden geçer, yani `@USERID`/`@TENANTID`/`@NOW` gibi token'lar çözülür. Soft delete'li tabloda (`IsDeletedField: true`) wizard buraya `"IsDeleted" = 'false'` yazar |
|
||
| `SortMode` | — | **Metin**: `"single"` \| `"multiple"` \| `"none"` (`PlatformConsts.GridOptions.SortMode*`; wizard `single` yazar) |
|
||
| `PageSize` | — | Sayfa başına kayıt; `0` = tümü |
|
||
| `Name` · `Title` · `Description` | — | Ekran adı, başlığı, açıklaması — **dil anahtarı** yazılır |
|
||
| `IsTenant` · `IsBranch` · `IsOrganizationUnit` | `IsMultiTenant` · `false` · `false` | Otomatik kırılım filtresi; `IsTenant` ayrıca bağlantı çözümünü belirler (`lowcode` §9.3.3) |
|
||
| `SeedFilePath` · `SeedSyncInsert` · `SeedSyncUpdate` · `SeedSyncDelete` | — · `false` | Ekranın verisini `data/` altındaki dosyaya aynalar; `.json` uzantılı değer tek dosya, uzantısız değer klasör (`lowcode` §9.15) |
|
||
|
||
| Kolon | Ne yapılandırır | Bölüm |
|
||
| --- | --- | --- |
|
||
| `ColumnOptionJson` | Grid genel görünümü (kenarlık, satır rengi, kolon seçici, sabitleme) | §2.1 |
|
||
| `CommandColumnJson` | Toolbar ve satır butonları | `lowcode` §4.9 |
|
||
| `RowJson` | Satır yüksekliği ve metin kaydırma | §2.2 |
|
||
| `PagerOptionJson` | Sayfalama şeridi | §2.3 |
|
||
| `SelectionJson` | Seçim modu ve checkbox davranışı | §2.4 |
|
||
| `StateStoringJson` | Kullanıcının grid tercihlerinin saklanması | §2.5 |
|
||
| `FilterRowJson` · `HeaderFilterJson` · `FilterPanelJson` · `SearchPanelJson` · `GroupPanelJson` | Filtre/arama/gruplama panelleri | §2.6 |
|
||
| `ExtraFilterJson` | Ekran üstü ek filtre çubuğu | `lowcode` §4.3.8 |
|
||
| `EditingOptionJson` | Düzenleme modu, izinler, popup ayarları | §3.1 |
|
||
| `EditingFormJson` | Düzenleme formunun grup/sekme yerleşimi | §3.2 |
|
||
| `InsertCommand` · `UpdateCommand` · `DeleteCommand` (+ `*Before`/`*After`) | Özel SQL komutları ve kancalar | §4 |
|
||
| `*FieldsDefaultValueJson` | Otomatik doldurulan alanlar | `lowcode` §4.3.5 |
|
||
| `*ServiceAddress` | Yazma işlemini karşılayan uç | §4.3 |
|
||
| `PermissionJson` | Ekran yetkileri | §5.1 |
|
||
| `SubFormsJson` | Alt form sekmeleri | §5.2 |
|
||
| `WidgetsJson` | KPI kartları | §5.3 |
|
||
| `WorkflowJson` | Onay akışı | `lowcode` §4.7 |
|
||
| `LayoutJson` | Açık görünümler ve varsayılan | §5.4 |
|
||
| `PivotOptionJson` | Pivot görünümü | §6 |
|
||
| `TreeOptionJson` · `GanttOptionJson` · `SchedulerOptionJson` · `TodoOptionJson` | Ağaç/Gantt/Takvim/Kanban eşlemeleri | §7 |
|
||
| `SeriesJson`, `CommonJson` ve diğer 19 grafik kolonu | Chart görünümü (21 kolon; `DataSourceJson` okunmaz) | §8 |
|
||
| `CustomJsSourcesJson` · `CustomStyleSourcesJson` | Sayfaya enjekte edilen JS/CSS | §5.5 |
|
||
| `Width` · `Height` · `FullHeight` | Ekran boyutu. `Height > 0` sabit piksel yüksekliği verir. Grid/Tree/Gantt/Scheduler'da `FullHeight` bayrağı görünümü `calc(100vh - …)` ile sayfaya yayar; **TodoBoard** bayrağa bakmaz, `Height` verilmediyse panoyu her zaman sayfanın kalan yüksekliğine yayar (kolonlar kendi içinde kayar), alt form olarak açıldığında ise içeriği kadar yer kaplar. | — |
|
||
| `ListFormType` · `IsSubForm` · `SubFormsListFormType` · `ShowNote` | Ekranın türü ve alt form davranışı | §5.6 |
|
||
| `CultureName` · `UserId` · `RoleId` | Aynı ekranın dil/kullanıcı/rol varyantı | §5.7 |
|
||
|
||
---
|
||
|
||
## 2. Grid görünümü
|
||
|
||
### 2.1 `ColumnOptionJson` (`GridColumnOptionDto`)
|
||
|
||
| Anahtar | Varsayılan | Anlam |
|
||
| --- | --- | --- |
|
||
| `ShowBorders` | `true` | Dış kenarlık |
|
||
| `ShowRowLines` | `true` | Satır çizgileri |
|
||
| `ShowColumnLines` | `false` | Kolon çizgileri |
|
||
| `RowAlternationEnabled` | `true` | Tek/çift satır renklendirme |
|
||
| `AllowColumnReordering` | `true` | Kullanıcı kolon sırasını değiştirebilir |
|
||
| `AllowColumnResizing` | `true` | Kolon genişliği değiştirilebilir |
|
||
| `ColumnResizingMode` | `"widget"` | `nextColumn` \| `widget` |
|
||
| `ColumnAutoWidth` | `false` | İçeriğe göre genişlik |
|
||
| `ColumnFixingEnabled` | `false` | Kolon sabitleme menüsü |
|
||
| `ColumnChooserEnabled` | `false` | Kolon seçici düğmesi |
|
||
| `ColumnChooserMode` | `"dragAndDrop"` | `dragAndDrop` \| `select` |
|
||
| `ColumnHidingEnabled` | `true` | Dar ekranda kolon gizleme |
|
||
| `HoverStateEnabled` | `false` | Satır üzerine gelince vurgulama |
|
||
| `FocusedRowEnabled` | `true` | Odaklı satır |
|
||
| `ShowColumnHeaders` | `true` | Başlık satırı |
|
||
| `RtlEnabled` | `false` | Sağdan sola |
|
||
|
||
### 2.2 `RowJson` (`GridRowDto`)
|
||
|
||
| Anahtar | Varsayılan | Anlam |
|
||
| --- | --- | --- |
|
||
| `RowHeight` | `"auto"` | Satır yüksekliği (CSS) |
|
||
| `WhiteSpace` | `"normal"` | Uzun metnin kaydırılması |
|
||
| `OverflowWrap` | `"break-word"` | Kelime kırma |
|
||
|
||
### 2.3 `PagerOptionJson` (`GridPagerOptionDto`)
|
||
|
||
Adı yalnızca sayfalamayı çağrıştırsa da bu blok **kaydırma ve yükleniyor panelini** de taşır.
|
||
|
||
| Anahtar | Varsayılan | Anlam |
|
||
| --- | --- | --- |
|
||
| `Visible` | `true` | Sayfalama şeridi |
|
||
| `ShowPageSizeSelector` | `false` | Sayfa boyu seçici |
|
||
| `ShowInfo` | `false` | "Page 1 of 4 (37 items)" bilgisi |
|
||
| `ShowNavigationButtons` | `true` | İleri/geri düğmeleri |
|
||
| `AllowedPageSizes` | `"10,20,50,100"` | **Virgüllü metin**, dizi değil |
|
||
| `InfoText` | `"Page {0} of {1} ({2} items)"` | `{0}` sayfa · `{1}` toplam sayfa · `{2}` kayıt |
|
||
| `DisplayMode` | `"adaptive"` | `adaptive` \| `compact` \| `full` |
|
||
| `ScrollingMode` | `"standard"` | `standard` \| `virtual` \| `infinite` — uzun listelerde `virtual` |
|
||
| `LoadPanelEnabled` | `"auto"` | **Metin** alanıdır: `"auto"` \| `"true"` \| `"false"` |
|
||
| `LoadPanelText` | `"Loading..."` | Yükleniyor metni |
|
||
|
||
Sayfa başına kayıt sayısı ekranın `PageSize` alanındadır; `0` = tümü. `ScrollingMode` ile
|
||
`PageSize` birlikte düşünülür: `virtual`/`infinite` seçilip `PageSize: 0` yazılırsa sayfalama
|
||
devre dışı kalır ve tüm küme tek istekte çekilir.
|
||
|
||
### 2.4 `SelectionJson` (`SelectionDto`)
|
||
|
||
| Anahtar | Varsayılan | Değerler |
|
||
| --- | --- | --- |
|
||
| `Mode` | `"none"` | `single` \| `multiple` \| `none` |
|
||
| `AllowSelectAll` | `false` | |
|
||
| `SelectAllMode` | `"allPages"` | `allPages` \| `page` |
|
||
| `ShowCheckBoxesMode` | `"always"` | `always` \| `none` \| `onClick` \| `onLongTap` |
|
||
|
||
Toolbar butonları seçili satırlarla çalışır (`lowcode` §4.9); onay akışı varsa wizard `single` yazar.
|
||
|
||
### 2.5 `StateStoringJson` (`StateStoringDto`)
|
||
|
||
| Anahtar | Varsayılan | Anlam |
|
||
| --- | --- | --- |
|
||
| `Enabled` | `true` | Kullanıcının kolon/filtre/sıralama tercihleri saklansın mı |
|
||
| `Type` | `"custom"` | `custom` (sunucuda kullanıcı bazlı) \| `localStorage` \| `sessionStorage` |
|
||
| `StorageKey` | — | Anahtar; boşsa sunucu `listFormGridStorage-{ListFormCode}` üretir |
|
||
| `SavingTimeout` | `5000` | Değişiklikten kaç ms sonra yazılacağı — **`[Range(1500, 5000)]`**, dışına çıkan değer doğrulamada reddedilir |
|
||
|
||
`Type: "custom"` tercih edilir: tercih sunucuda `ListFormCustomization` kaydı olarak
|
||
(`ListFormCustomizationTypeEnum.GridState = 2`) kullanıcı bazlı saklanır, bu yüzden başka
|
||
tarayıcıdan girildiğinde de korunur. `localStorage`/`sessionStorage` yalnızca o tarayıcıdadır.
|
||
Aynı tablonun diğer türleri: `UserUiFilter = 1` (kaydedilmiş filtre, §2.6), `ServerJoin = 3` ve
|
||
`ServerWhere = 4` — `UserId`/`RoleId` boşsa herkese, doluysa o rol/kullanıcıya sunucu tarafında
|
||
eklenen join ve `WHERE` parçası (`SelectQueryManager`; `ServerWhere` token'ları `DefaultValueHelper`
|
||
ile çözülür). **Satır bazlı veri kısıtının** kod yazmadan kurulduğu yer burasıdır; ListForm
|
||
editörünün **Kişiselleştirme** sekmesinden yazılır.
|
||
|
||
### 2.6 Filtre, arama ve gruplama panelleri
|
||
|
||
**`FilterRowJson`** (`GridFilterRowDto`): `Visible` (`false`), `ApplyFilter` (`auto` \| `onClick`),
|
||
`AllowUserUiFilterSave` (varsayılan `true` — kullanıcı kendi filtresini kaydedebilir;
|
||
kayıt `ListFormCustomizationTypeEnum.UserUiFilter = 1` olarak tutulur).
|
||
|
||
**`HeaderFilterJson`** (`GridHeaderFilterDto`): `Visible` (`false`), `AllowSearch` (`false`),
|
||
`Height` (`325`), `Width` (`252`), `SearchTimeout` (`500`).
|
||
|
||
**`FilterPanelJson`** (`FilterPanelDto`): `Visible` (`false`), `FilterEnabled` (`false`),
|
||
`Texts.ClearFilter` (`"Clear"`) / `Texts.CreateFilter` (`"Create Filter"`) /
|
||
`Texts.FilterEnabledHint` (`"Enable the filter"`), `CustomizeText` (serbest JSON; filtre
|
||
metnini biçimlendirmek için — sözlükte tipi yoktur, olduğu gibi bileşene geçer).
|
||
|
||
**`SearchPanelJson`** (`SearchPanelDto`): `Visible` (`false`), `Width` (`160`).
|
||
|
||
**`GroupPanelJson`** (`GroupPanelDto`): `Visible` (`false`), `AutoExpandAll` (`false`).
|
||
`AutoExpandAll: true` **fazladan bir sorgu daha** çalıştırır.
|
||
|
||
---
|
||
|
||
## 3. Düzenleme
|
||
|
||
### 3.1 `EditingOptionJson` (`GridEditingDto`)
|
||
|
||
| Anahtar | Varsayılan | Anlam |
|
||
| --- | --- | --- |
|
||
| `Mode` | `"popup"` | `batch` \| `cell` \| `row` \| `form` \| `popup` |
|
||
| `RefreshMode` | `"full"` | `full` \| `reshape` \| `repaint` |
|
||
| `AllowAdding` / `AllowUpdating` / `AllowDeleting` | `false` | Aksiyon izinleri (yetki ayrıca `PermissionJson`) |
|
||
| `AllowAllDeleting` | `false` | Toplu silme düğmesi |
|
||
| `AllowDuplicate` | `false` | Kaydı kopyalayarak yeni kayıt |
|
||
| `AllowDetail` | `false` | Satırda Detay düğmesi |
|
||
| `ConfirmDelete` | `true` | Silme onayı |
|
||
| `UseIcons` | `false` | Aksiyonlar ikon olarak |
|
||
| `NewRowPosition` | `"viewportTop"` | `first` \| `last` \| `pageTop` \| `pageBottom` \| `viewportTop` \| `viewportBottom` |
|
||
| `StartEditAction` | `"click"` | `click` \| `dblClick` |
|
||
| `SelectTextOnEditStart` | `false` | Düzenlemeye girince metni seç |
|
||
| `EditColumnName` | — | Aksiyon sütununun başlığı |
|
||
| `SendOnlyChangedFormValuesUpdate` | `false` | Update'te yalnızca değişen alanları gönder |
|
||
| `AddPageUrl` | — | Yeni kayıt popup yerine bu adreste açılır (`window.open`; PWA'da aynı sekme) |
|
||
| `AddDialogName` | — | Yeni kayıt kayıtlı bir diyalogda açılır (`CommandColumnDto.DialogName` ile aynı liste). `AddPageUrl` ile birlikte verilirse **diyalog önceliklidir**; diyalog kapanınca liste yenilenir |
|
||
| `AddDialogParameters` | — | `AddDialogName` diyaloguna geçilen sabit parametreler. Tipi **string**'dir: nesne değil, JSON metni yazılır (`"{\"id\":\"\"}"`); istemci `safeJsonParse` ile açar, bozuksa `{}` geçer. Toolbar'da satır bağlamı olmadığı için `@Kolon` token'i kullanılmaz |
|
||
| `Popup` | — | Aşağıdaki alt nesne |
|
||
|
||
`Popup` (`GridEditingPopupDto`): `Title`, `ShowTitle` (`true`), `Width` (`700`), `Height` (`500`),
|
||
`FullScreen` (`false`), `HideOnOutsideClick` (`true`), `ResizeEnabled` (`true`),
|
||
`DragEnabled` (`true`), `RestorePosition` (`true`),
|
||
`Position` (`center` \| `top` \| `bottom` \| `left` \| `right`).
|
||
|
||
### 3.2 `EditingFormJson` (`EditingFormDto[]`)
|
||
|
||
Düzenleme formundaki grupların listesi. Alanların hangi gruba düştüğü `ListFormField` üzerindeki
|
||
`EditGroupOrderNo` / `EditOrderNo` ile belirlenir.
|
||
|
||
| Anahtar | Varsayılan | Anlam |
|
||
| --- | --- | --- |
|
||
| `Order` | `1` | Grubun sırası (`EditGroupOrderNo` ile eşleşir) |
|
||
| `ItemType` | `"group"` | `group` (kullanılan) \| `tabbed` \| `simple` \| `empty` \| `button` |
|
||
| `Caption` | — | Grup başlığı (dil anahtarı) |
|
||
| `ColCount` | `2` | Grup içi kolon sayısı |
|
||
| `ColSpan` | `2` | Grubun formda kapladığı kolon |
|
||
|
||
Wizard bu listeyi `Groups` bloğundan üretir; anahtar alan ve `IncludeInEditingForm: false`
|
||
olanlar dışarıda kalır.
|
||
|
||
---
|
||
|
||
## 4. Yazma komutları ve kancalar
|
||
|
||
### 4.1 Komutlar
|
||
|
||
| Kolon | Ne zaman |
|
||
| --- | --- |
|
||
| `InsertCommand` / `UpdateCommand` / `DeleteCommand` | Boşsa platform komutu kendi üretir; doluysa **bu SQL** çalışır |
|
||
| `InsertBeforeCommand` / `InsertAfterCommand` | Insert'ten önce/sonra |
|
||
| `UpdateBeforeCommand` / `UpdateAfterCommand` | Update'ten önce/sonra |
|
||
| `DeleteBeforeCommand` / `DeleteAfterCommand` | Delete'ten önce/sonra |
|
||
|
||
**Kancalar, kod yazmadan iş mantığı çalıştırmanın yeridir**: stok düşme, hareket kaydı, durum
|
||
güncelleme, log, bildirim kuyruğuna satır ekleme. Karmaşıklaşınca gövdeyi bir stored procedure'e
|
||
taşı ve kancadan onu çağır (`EXEC Wms_S_AfterOrderInsert @Id, @USERID`).
|
||
|
||
### 4.2 Komut içinde kullanılabilen anahtarlar
|
||
|
||
| Token | Değer |
|
||
| --- | --- |
|
||
| `@ID` | Kaydın anahtarı (Delete'te seçili anahtar kümesi) |
|
||
| `@USERID` · `@USERNAME` · `@ROLES` | Oturumdaki kullanıcı |
|
||
| `@FieldName` | Ekrandan gelen o alanın değeri — tablodaki her kolon için geçerlidir (`@OrderNo`, `@Amount`) |
|
||
|
||
`*FieldsDefaultValueJson` ile üretilen değerler (`@NOW`, `@NEWID`, `@TENANTID`, Sequence…)
|
||
komuta parametre olarak katılır (`lowcode` §4.3.5). **String birleştirme ile sorgu kurma.**
|
||
|
||
### 4.3 `*ServiceAddress`
|
||
|
||
`InsertServiceAddress` / `UpdateServiceAddress` / `DeleteServiceAddress` varsayılan olarak
|
||
`list-form-data/insert|update|delete` uçlarıdır. Yazma işini bir Custom Endpoint ya da Dynamic
|
||
Service'e devretmek istiyorsan bu alanı o ucun adresiyle değiştirirsin — ekranın geri kalanı
|
||
(form, doğrulama, yetki) aynı kalır.
|
||
|
||
**Çok değerli alanlar bu iki yolda farklı davranır.** Varsayılan uçta payload bir sözlüktür
|
||
(`data: {...}`) ve `dxTagBox` dizisini `QueryHelper.GetFormattedValue` `|` ile birleştirir.
|
||
Tipli bir DTO alan uçta (`list-form-dynamic-api/...` gibi) böyle bir adım yoktur: dizi `string`
|
||
property'ye bağlanamaz ve istek `400` ile düşer. Çözüm, DTO alanına
|
||
`[JsonConverter(typeof(MultiValueStringJsonConverter))]` eklemektir — `Modules` alanında
|
||
uygulanmış örneği `CreateUpdateTenantInput` / `CreateTenantFromOrderInput` taşır. Yalnızca
|
||
**girdi** DTO'larına eklenir; okuma DTO'larında (`SettingDefinitionDto.Providers`,
|
||
`PlatformPermissionGrantInfoDto.Modules`) karşılığı yoktur çünkü o ekranlar varsayılan SQL
|
||
yolundan kaydeder.
|
||
|
||
---
|
||
|
||
## 5. Ekran seviyesindeki diğer bloklar
|
||
|
||
### 5.1 `PermissionJson` (`PermissionCrudDto`)
|
||
|
||
Tek harfli anahtarlar: `R` (read), `C` (create), `U` (update), `D` (delete), `E` (export),
|
||
`I` (import), `N` (note). Değerler **yetki adıdır**, boolean değil:
|
||
|
||
```json
|
||
{ "R": "App.Mrp.Orders", "C": "App.Mrp.Orders.Create", "U": "App.Mrp.Orders.Update",
|
||
"D": "App.Mrp.Orders.Delete", "E": "App.Mrp.Orders.Export", "I": "App.Mrp.Orders.Import",
|
||
"N": "App.Mrp.Orders.Note" }
|
||
```
|
||
|
||
Alan seviyesindeki karşılığı `ListFormField.PermissionJson`'dır ve **şeması farklıdır**
|
||
(`ListFormFieldPermissionDto`) — ekran seviyesindeki yedi harfli sözleşmeyi buraya kopyalama:
|
||
|
||
| Anahtar | Tip | Anlam |
|
||
| --- | --- | --- |
|
||
| `Deny` | bool | `true` ise alan **hiç dönmez**; diğer anahtarlara bakılmaz |
|
||
| `C` · `R` · `U` | string | Yaratma / okuma / güncelleme yetkisinin **adı**. Boşsa ekranın kendi Create/Read/Update yetkisi kullanılır |
|
||
| `E` | bool | Alan dışa aktarımda yer alsın mı |
|
||
| `I` | bool | Alan içe aktarımda kabul edilsin mi |
|
||
|
||
```json
|
||
{ "C": "App.Mrp.Orders.Create", "R": "App.Mrp.Orders", "U": "App.Mrp.Orders.Update",
|
||
"E": true, "I": true, "Deny": false }
|
||
```
|
||
|
||
`ListFormField` üzerindeki `CanRead` / `CanCreate` / `CanUpdate` / `CanExport` kolonları
|
||
**veritabanında yoktur** (`[NotMapped]`); `ListFormFieldManager.SetPermissionsAsync` bu
|
||
JSON'u oturumdaki yetkilerle karşılaştırarak istek başına hesaplar. Üçü de `false` çıkan alan
|
||
metadata'dan tamamen düşer — yani okuma yetkisi olmayan bir kolon sorguya bile girmez.
|
||
Wizard varsayılan olarak `DefaultFieldPermissionJson(permissionName)` üretir.
|
||
|
||
### 5.2 `SubFormsJson` (`SubFormDto[]`)
|
||
|
||
| Anahtar | Anlam |
|
||
| --- | --- |
|
||
| `TabType` | Sekmenin görünümü — `ListFormTabTypeEnum`: `List` \| `Card` \| `Tree` \| `Gantt` \| `Scheduler` \| `Todo` \| `Form` \| `Chart` \| `Pivot`. `Form` ana kayda bağlı **tek** kaydı gösterir: kayıt yokken "Yeni" düğmesi (hedef ekranda `AllowAdding` açıksa), kayıt varken yalnızca düzenleme; ikinci kayıt açılmaz |
|
||
| `TabTitle` | Dil anahtarı |
|
||
| `Code` | Hedef `ListFormCode` |
|
||
| `IsRefresh` | Ana kayıt değişince yenilensin |
|
||
| `Relation[]` | `ParentFieldName` → `ChildFieldName` + `DbType` (`System.Data.DbType`, **sayı**; bileşik anahtarda birden çok satır) |
|
||
|
||
Alt formun kendisi de bir ListForm'dur: `IsSubForm = true` olmalı ve genellikle `CreateMenu:
|
||
false` ile menüsüz üretilir (`lowcode` §4.2). `TabType`, hedef ekranın `LayoutJson`'ında açık
|
||
olan bir görünüm olmalıdır; kapalı bir görünüm sekmede boş çizilir.
|
||
|
||
### 5.3 `WidgetsJson` (`WidgetEditDto[]`)
|
||
|
||
Ekranın üstündeki KPI şeridi. **Sözleşmesi sezgisel değildir, dikkatle oku:**
|
||
|
||
| Anahtar | Ne yazılır |
|
||
| --- | --- |
|
||
| `SqlQuery` | Kartları besleyen sorgu. **Zorunludur** — boş olan widget hiç çizilmez |
|
||
| `Title` · `SubTitle` · `Value` · `Color` · `Icon` · `OnClick` | **Sorgu sonucundaki kolon adları** — sabit metin değil. Sunucu her satırda bu adlı kolonu okur; kolon yoksa boş string döner. `Title`/`SubTitle` kolonunun **değeri** ekranda dil anahtarı olarak çözülür (`WidgetGroup`, `::` öneki eklenerek); karşılığı olmayan metin aynen basılır, bu yüzden sorguya dil anahtarı yazılır |
|
||
| `ColSpan` · `ColGap` · `ClassName` | Şeritteki yerleşim (widget başına, karta değil) |
|
||
| `ValueClassName` | Değerin CSS sınıfı, varsayılan `text-3xl` |
|
||
| `IsActive` | **Varsayılanı `false`'tur** — yazılmazsa sorgu hiç çalışmaz ve şerit boş kalır; her widget'a `true` yaz |
|
||
|
||
**Bir widget, sorgunun döndürdüğü her satır için bir kart çizer.** Yani tek bir widget kaydıyla
|
||
"Bekleyen / Onaylı / Reddedilen" üçlüsü tek sorgudan üretilebilir:
|
||
|
||
```sql
|
||
SELECT 'Bekleyen' AS Baslik, COUNT(*) AS Deger, 'amber' AS Renk, 'FaClock' AS Ikon
|
||
FROM Mrp_T_Order WHERE Status = 1
|
||
UNION ALL
|
||
SELECT 'Onaylı', COUNT(*), 'green', 'FaCheck' FROM Mrp_T_Order WHERE Status = 2
|
||
```
|
||
|
||
```json
|
||
{ "Title": "Baslik", "Value": "Deger", "Color": "Renk", "Icon": "Ikon", "ColSpan": 4, "IsActive": true }
|
||
```
|
||
|
||
Sorgu ekranın bağlantısında (`IsTenant` + `DataSourceCode` ile çözülen, `lowcode` §9.3.3),
|
||
**olduğu gibi** çalıştırılır:
|
||
|
||
- Ekranın otomatik tenant/şube/OU filtresi **uygulanmaz**; kırılım sorguya yazılır.
|
||
- Sorgu `DefaultFilter` ile aynı token çözümünden geçer (`DefaultValueHelper.GetDefaultValue`):
|
||
`@USERID`, `@USERNAME`, `@DATE`, `@NOW` ve `@TENANTID` metin olarak yerine konur.
|
||
Kiracı tablosunda (`IsTenant: true`) her karta `"TenantId" = '@TENANTID'` yaz; host'ta bu
|
||
`"TenantId" IS NULL`'a döner, yani kartlar liste ekranıyla aynı kümeyi sayar. Yazılmazsa ortak
|
||
veritabanında kartlar bütün kiracıların toplamını gösterir.
|
||
- `IsDeleted` koşulu widget sorgusuna yazılmaz (platform varsayılanı).
|
||
- Wizard / MCP ile üretilen List ekranı sorulmadan en az 3 kartla gelir; kart seçimi, istisnalar
|
||
ve metin/renk kuralı: `lowcode` §4.6.1.
|
||
- Seeder'da şerit `DefaultWidgetsJson(tablo, listFormName, tenant, params WidgetCard[])` ile
|
||
kurulur (`ListFormSeeder_DefaultJsons`): kart başına `Title` (dil anahtarı), renk, ikon, ek koşul
|
||
ve isteğe bağlı `Value` ifadesi; alt başlık ekranın adıdır, değer tip çakışmasın diye metne
|
||
çevrilir. Gruplamalı sorgu için `DefaultWidgetsJson(sql, kartSayısı)`. Genel kart başlıkları
|
||
`App.Widget.*` dil anahtarlarındadır.
|
||
- Kartlar GridDto ile gelir; Grid, Tree, Card, Gantt ve Scheduler görünümünde Yenile düğmesi ve
|
||
satır ekleme/güncelleme/silme kartları yeniden çeker (`useListFormWidgets`). Yalnızca widget
|
||
listesi değişir, GridDto değiştirilmez — görünüm durumu (sayfa, seçim) korunur. Kart sorgusu
|
||
ekranın filtresine bağlı olmadığı için filtre değişikliği kartları yenilemez.
|
||
- Kart sorgusu alt form sekmesinde `Relation` ile süzülmez; bu yüzden alt form olarak üretilen
|
||
ekrana widget yazılmaz (menüsüz ya da menülü). Menüsüz (`CreateMenu: false`) wizard'ın `Widgets`'ı
|
||
deploy'da ayrıca düşürülür; ekran alt form olarak (`SubForms` sekmesi, `isSubForm`) açıldığında
|
||
şerit çizilmez ve yenilenmez.
|
||
|
||
### 5.4 `LayoutJson` (`LayoutDto`)
|
||
|
||
| Anahtar | Varsayılan |
|
||
| --- | --- |
|
||
| `Grid` · `Card` · `Pivot` · `Chart` | `true` |
|
||
| `Tree` · `Gantt` · `Scheduler` · `Todo` | `false` |
|
||
| `DefaultLayout` | `"grid"` |
|
||
|
||
Wizard'daki görünüm bayraklarının karşılığıdır. Varsayılan **dörtlüdür**: `Grid`, `Card`, `Pivot`,
|
||
`Chart` her liste ekranında açık gelir; üretilen ekranda bunlardan biri yalnızca istek onu açıkça
|
||
dışarıda bıraktığında kapatılır (`lowcode` §9.8). Aynı varsayılan üç yerde tutulur ve birlikte
|
||
değişir: UI wizard başlangıç değerleri (`Wizard.tsx`), `ListFormWizardDto` ve `LayoutDto`
|
||
(+ `WizardConsts.DefaultLayoutJson`). Tree/Gantt/Scheduler/Todo zorunlu `*Expr` alanı ister
|
||
(§7); bayrak açık olsa bile alanlar boşsa istemci görünümü göstermez (`List.tsx` `isLayoutValid`)
|
||
ve seeder o görünümün JSON'unu yazmaz. `DefaultLayout`, `true` olan bir görünümü göstermelidir.
|
||
|
||
### 5.5 `CustomJsSourcesJson` / `CustomStyleSourcesJson`
|
||
|
||
Her ikisi de **string dizisidir**. Bir eleman `http` ya da `/` ile başlıyorsa dosya olarak
|
||
sayfaya eklenir (`<script src>` / `<link rel=stylesheet>`); aksi hâlde içerik olarak çalıştırılır
|
||
(JS'te `eval`, CSS'te inline `<style>`).
|
||
|
||
```json
|
||
["/assets/custom/orders.js", "console.log('orders ekranı yüklendi')"]
|
||
```
|
||
|
||
**Son çaredir.** Önce `EditorScript`, `EditorOptions`, `ColumnStylingJson` ve `CommandColumnJson`
|
||
denenir. Buraya yazılan kod ekran her açıldığında çalışır ve hiçbir yerde denetlenmez.
|
||
|
||
### 5.6 Ekranın türü
|
||
|
||
| Kolon | Varsayılan | Anlam |
|
||
| --- | --- | --- |
|
||
| `ListFormType` | `"List"` | `ListFormTypeEnum`: `List` (ızgara) \| `Form` (tek kayıt) \| `Chart` (yalnız grafik). Route karşılıkları: `/admin/list/{kod}` · `/admin/form/{kod}[/{id}[/edit]]` · `/admin/chart/{kod}` |
|
||
| `IsSubForm` | `false` | Ekran alt form olarak da kullanılıyor mu |
|
||
| `SubFormsListFormType` | `"Form"` | Alt form olarak açıldığında hangi görünümle geleceği |
|
||
| `ShowNote` | `true` | Not paneli (alt form ya da iş akışı varsa wizard açar) |
|
||
|
||
`ListFormType = "Form"` listesiz, tek kayıtlık kart ekrandır; canlı örneği Administration ›
|
||
Licence'tır (§12.7). `Pivot` bir `ListFormType` **değildir** — pivot, `LayoutJson.Pivot`
|
||
bayrağıyla açılan bir görünümdür ve `/admin/pivot/...` diye bir route yoktur.
|
||
|
||
### 5.7 Varyantlar
|
||
|
||
Aynı `ListFormCode` ile ikinci bir `ListForm` kaydı açılıp `CultureName`, `UserId` ya da `RoleId`
|
||
doldurulursa o dil/kullanıcı/rol için **farklı sütun düzeni ve ayarlar** verilebilir. Aynı şey
|
||
`ListFormField` ve `Menu` kayıtları için de geçerlidir. Wizard bunu üretmez; ihtiyaç varsa
|
||
ListForm editöründen açılır ve seed karşılığı elle yazılır.
|
||
|
||
---
|
||
|
||
## 6. Pivot
|
||
|
||
### 6.1 `PivotOptionJson` (`GridPivotOptionDto`)
|
||
|
||
| Anahtar | Varsayılan |
|
||
| --- | --- |
|
||
| `ShowFieldPanel` | `true` |
|
||
| `AllowFieldDragging` | `true` |
|
||
| `ShowDataFields` / `ShowColumnFields` / `ShowRowFields` / `ShowFilterFields` | `true` |
|
||
| `ColumnChooserEnabled` | `false` |
|
||
| `ShowChart` | `false` |
|
||
| `ChartHeight` | `320` |
|
||
| `ChartCommonSeriesType` | `"bar"` |
|
||
|
||
### 6.2 Alan başına `PivotSettingsJson` (`ListFormFieldPivotSettingsDto`)
|
||
|
||
| Anahtar | Varsayılan | Değerler |
|
||
| --- | --- | --- |
|
||
| `IsPivot` | `true` | Alan pivotta kullanılsın mı |
|
||
| `Area` | `filter` | `row` \| `column` \| `data` \| `filter` |
|
||
| `SummaryType` | — | `sum` \| `avg` \| `count` \| `min` \| `max` |
|
||
| `GroupInterval` | `none` | `day` \| `dayOfWeek` \| `month` \| `quarter` \| `year` |
|
||
| `SortOrder` | `asc` | `asc` \| `desc` |
|
||
| `Format` | — | DevExtreme format adı |
|
||
| `Expanded` | `false` | Başlangıçta açık |
|
||
| `WordWrapEnabled` | `false` | |
|
||
|
||
Pivot ekranı ayrı bir sorgu istemez; ızgarayla aynı `SelectCommand` üzerinden çalışır.
|
||
|
||
---
|
||
|
||
## 7. Ağaç, Gantt, Takvim, Kanban
|
||
|
||
### 7.1 `TreeOptionJson` (`TreeOptionDto`)
|
||
|
||
`KeyExpr`*, `ParentIdExpr`*, `HasItemsExpr`, `RootValue` (varsayılan `null`; `""` de `null`
|
||
sayılır), `ExpandedRowKeys[]`, `AutoExpandAll` (`false`; seeder yardımcısı
|
||
`DefaultTreeOptionJson` `true` yazar), `RecursiveSelection` (`false`).
|
||
DTO'daki `TitleExpr`/`StartExpr`/`EndExpr`/`ProgressExpr` ağaçta okunmaz — Gantt alanlarıdır.
|
||
|
||
### 7.2 `GanttOptionJson` (`GanttOptionDto`)
|
||
|
||
Ağaç alanlarının tamamı + `TitleExpr`*, `StartExpr`*, `EndExpr`*, `ProgressExpr`*
|
||
(istemci dördü olmadan görünümü açmaz — `List.tsx` `isLayoutValid`), `ScaleType` (varsayılan
|
||
`weeks`; DevExtreme `GanttScaleType`: `auto` \| `minutes` \| `hours` \| `sixHours` \| `days` \|
|
||
`weeks` \| `months` \| `quarters` \| `years`; kullanıcının seçtiği ölçek grid durumuyla saklanır)
|
||
ve düzenleme bayrakları: **`EditingEnabled`** (ana anahtar — `AllowEditing` diye bir alan yoktur,
|
||
yazılırsa düşer), `AllowTaskAdding`, `AllowTaskUpdating`, `AllowTaskResourceUpdating`,
|
||
`AllowTaskDeleting`, `AllowDependencyAdding`, `AllowDependencyDeleting`, `AllowResourceAdding`,
|
||
`AllowResourceUpdating`, `AllowResourceDeleting` (hepsi `false`).
|
||
|
||
### 7.3 `SchedulerOptionJson` (`SchedulerOptionDto`)
|
||
|
||
| Anahtar | Varsayılan | Anlam |
|
||
| --- | --- | --- |
|
||
| `TextExpr`* · `StartDateExpr`* · `EndDateExpr`* | — | Başlık ve zaman kolonları |
|
||
| `UserNameExpr` · `DescriptionExpr` | — | Randevu sahibinin kullanıcı adı (kartta avatarı çizilir) ve açıklama |
|
||
| `AllDayExpr` | — | Tüm gün bayrağı kolonu |
|
||
| `RecurrenceRuleExpr` · `RecurrenceExceptionExpr` | — | Tekrar kuralı kolonları |
|
||
| `StartDayHour` / `EndDayHour` | `8` / `20` | Görünen saat aralığı |
|
||
| `DefaultView` | `"week"` | Ekranın çizdiği sekiz görünüm: `day` \| `week` \| `workWeek` \| `month` \| `timelineDay` \| `timelineWeek` \| `timelineMonth` \| `agenda` |
|
||
| `ShowAllDayPanel` | `true` | |
|
||
| `CellDuration` | `30` | Hücre dakikası |
|
||
| `FirstDayOfWeek` | `1` | 0 = Pazar |
|
||
| `CrossScrollingEnabled` | `false` | Kaynak (resource) görünümünde yatay+dikey kaydırma |
|
||
| `AllowAdding` / `AllowEditing` / `AllowDeleting` / `AllowDragging` / `AllowResizing` | `false` | |
|
||
|
||
> **`Resources[]` bugün çalışmaz.** UI modeli (`proxy/form/models.ts`) ve `SchedulerView`
|
||
> randevuları renklendiren kaynak eşlemesini (`FieldExpr`, `DataSource[]`, `Label`,
|
||
> `UseColorAsDefault`) okur, ama C# `SchedulerOptionDto`'da alan yoktur — girişteki kural gereği
|
||
> sunucu anahtarı düşürür, seed'e yazılan değer istemciye hiç ulaşmaz. Gerekirse önce DTO'ya
|
||
> geriye dönük uyumlu alan eklenir.
|
||
|
||
### 7.4 `TodoOptionJson` (`TodoOptionDto`) — Kanban
|
||
|
||
`TitleExpr`*, `StatusExpr`*, `DescriptionExpr`, `AnalysisExpr` (detayda Açıklama yanında HTML sekmesi), `DueDateExpr`, `TagExpr`, `AssigneeExpr`,
|
||
`PriorityExpr`, `CompletedExpr`, `OrderExpr`, `TimesheetExpr`, `SubTaskExpr`,
|
||
`StatusOrder` (kolon sırası, virgüllü), `AllowDragging` (varsayılan `true`).
|
||
|
||
Panonun yüksekliği `TodoOptionJson` ile değil ekranın `Height` kolonuyla belirlenir; boş
|
||
bırakıldığında pano sayfanın kalan yüksekliğini kaplar ve her kolon kendi içinde kayar.
|
||
|
||
> `*` işaretli alan boşsa seeder o görünümün JSON'unu **yazmaz**; bayrağı açmak yetmez.
|
||
|
||
---
|
||
|
||
## 8. Chart (grafik) sözleşmesi
|
||
|
||
Grafik, ListForm üzerindeki **21 JSON kolonuyla** yapılandırılır. Hepsi DevExtreme
|
||
`dxChart` yapılandırmasının karşılık gelen bölümüne geçer — ama tipli DTO'dan süzülerek
|
||
(girişteki "bilinmeyen anahtar düşer" kuralı grafik kolonları için de geçerlidir). Entity'deki
|
||
22. kolon `DataSourceJson` hiçbir yerde okunmaz (§8.2).
|
||
|
||
Grafik iki yoldan açılır: ekranın `LayoutJson.Chart` bayrağıyla bir görünüm olarak, ya da
|
||
`ListFormType = "Chart"` ile yalnız grafikten oluşan bir ekran (`/admin/chart/{kod}`) olarak.
|
||
|
||
| Kolon | Karşılığı |
|
||
| --- | --- |
|
||
| `SeriesJson` | `series[]` — **zorunlu**, §8.1 |
|
||
| `CommonJson` | Grafik geneli (palet, zemin), §8.3 |
|
||
| `CommonSeriesSettingsJson` | Tüm serilere ortak ayarlar — `ChartSeriesDto`'nun `Name`/`SummaryType`/`UserId` dışındaki alanları |
|
||
| `ArgumentAxisJson` · `ValueAxisJson` (**dizi**) · `CommonAxisSettingsJson` | Eksenler, §8.5 |
|
||
| `LegendJson` | Açıklama kutusu, §8.6 |
|
||
| `TooltipJson` | İpucu balonu, §8.7 |
|
||
| `PanesJson` · `CommonPaneSettingsJson` | Bölmeler (çok panelli grafik) |
|
||
| `AnnotationsJson` · `CommonAnnotationsSettingsJson` | Ek açıklamalar |
|
||
| `CrosshairJson` | Artı imleç çizgileri |
|
||
| `ScrollBarJson` | Kaydırma çubuğu |
|
||
| `ZoomAndPanJson` | Yakınlaştırma/kaydırma |
|
||
| `SizeJson` · `MarginJson` · `AdaptiveLayoutJson` | Boyut, kenar boşluğu, dar ekran davranışı |
|
||
| `TitleJson` | Başlık/alt başlık |
|
||
| `AnimationJson` | Animasyon |
|
||
| `ExportJson` | Dışa aktarma/yazdırma |
|
||
|
||
Kullanıcı/rol bazlı farklı grafik, ekranın `UserId`/`RoleId` varyantıyla kurulur (§5.7); boşsa
|
||
grafik herkese aynıdır.
|
||
|
||
### 8.1 `SeriesJson` (`ChartSeriesDto[]`)
|
||
|
||
| Anahtar | Varsayılan | Anlam |
|
||
| --- | --- | --- |
|
||
| `Name` | — | Açıklamada görünen seri adı |
|
||
| `Type` | — (DevExtreme: `line`) | `line` \| `stepline` \| `spline` \| `bar` \| `area` \| `splinearea` \| `steparea` \| `scatter` \| `bubble` \| `rangebar` \| `rangearea` \| `candlestick` \| `stock` \| `stackedbar` \| `stackedarea` \| `stackedline` \| `stackedspline` \| `stackedsplinearea` \| `fullstackedbar` \| `fullstackedarea` \| `fullstackedline` \| `fullstackedspline` \| `fullstackedsplinearea` (ListForm editörünün listesi: `chartSeriesTypeOptions`) |
|
||
| `ArgumentField` | `"arg"` | X ekseni kolonu — ekranın sorgusundaki bir **alan adı** |
|
||
| `ValueField` | — | Y ekseni kolonu |
|
||
| `SummaryType` | `"sum"` | `sum` \| `avg` \| `count` \| `min` \| `max` — sunucuda `ArgumentField` kırılımıyla toplanır (§8.2) |
|
||
| `Color` | — | Seri rengi |
|
||
| `Axis` · `Pane` | — | Hangi eksen/bölme |
|
||
| `Visible` | `true` | |
|
||
| `ShowInLegend` | `true` | |
|
||
| `Width` | `2` | Çizgi kalınlığı |
|
||
| `DashStyle` | `"solid"` | `solid` \| `dash` \| `dot` \| `longDash` |
|
||
| `BarWidth` · `BarPadding` · `BarOverlapGroup` · `CornerRadius` | — | Çubuk serileri |
|
||
| `IgnoreEmptyPoints` | `false` | |
|
||
| `SelectionMode` | `"none"` | `onlyPoint` \| `allSeriesPoints` \| `allArgumentPoints` \| `includePoints` \| `excludePoints` \| `none` |
|
||
| `RangeValue1Field` / `RangeValue2Field` | `val1` / `val2` | Aralık serileri |
|
||
| `Label` | — | `ChartLabelDto`: `Visible`, `Format`, `Font`, `BackgroundColor`, `CustomizeText` |
|
||
| `UserId` | — | Kullanıcı adı (`UserName`, kimlik değil). O kullanıcının kendi serisi varsa **yalnızca** onun serileri çizilir, yoksa `UserId`'si ne olursa olsun bütün seriler. Kullanıcı grafik çekmecesinden kendi serisini kaydettiğinde bu alan dolar |
|
||
|
||
### 8.2 Veri — grafik ekranın kendi sorgusundan beslenir
|
||
|
||
Grafik ayrı bir sorgu çalıştırmaz: ekranın `SelectCommand`'ı (ve `DefaultFilter`, kırılım
|
||
filtreleri, kullanıcının o anki filtresi) üzerinde, serilerin `ArgumentField` değerleriyle
|
||
**gruplanmış** ve her serinin `ValueField` + `SummaryType` çiftiyle **özetlenmiş** bir istek atılır
|
||
(`useListFormCustomDataSource`, `layoutTypes.chart`). Yani `SELECT … GROUP BY` yazmaya gerek yoktur;
|
||
özetlenecek ham satırları döndüren sorgu yeter. Farklı kırılımda ikinci bir grafik gerekiyorsa
|
||
ikinci bir ListForm (ya da view) açılır.
|
||
|
||
`DataSourceJson` kolonu ve `ChartDataSourceDto { Query }` / `ChartDataRequestDto` tipleri kodda
|
||
durur ama **okunmaz** — oraya sorgu yazmak grafiği değiştirmez.
|
||
|
||
### 8.3 `CommonJson` (`ChartCommonDto`)
|
||
|
||
| Anahtar | Varsayılan | Anlam |
|
||
| --- | --- | --- |
|
||
| `Palette` | `"Material"` | `Bright` \| `Harmony Light` \| `Ocean` \| `Pastel` \| `Soft` \| `Soft Pastel` \| `Vintage` \| `Violet` \| `Carmine` \| `Dark Moon` \| `Dark Violet` \| `Green Mist` \| `Soft Blue` \| `Material` \| `Office` |
|
||
| `PaletteExtensionMode` | `"blend"` | `alternate` \| `blend` \| `extrapolate` |
|
||
| `Theme` | `"generic.light"` | DTO'da durur ama `Chart.tsx` grafiğe geçirmez — tema uygulamanın temasından gelir |
|
||
| `ContainerBackgroundColor` | `"#FFFFFF"` | |
|
||
| `AdjustOnZoom` | `true` | |
|
||
| `DefaultPane` | — | |
|
||
| `Disabled` | `false` | |
|
||
|
||
### 8.4 Boyut ve yerleşim
|
||
|
||
- `SizeJson` (`ChartSizeDto`): `UseSize` (`false`), `Width` (`400`), `Height` (`200`).
|
||
`UseSize: false` iken grafik pencereye yayılır (`Width`/`Height` yok sayılır).
|
||
- `MarginJson` (`ChartMarginDto`): `Top`, `Bottom`, `Left`, `Right`.
|
||
- `AdaptiveLayoutJson` (`ChartAdaptivelayoutDto`): `Width`/`Height` eşiği (`80`/`80`),
|
||
`KeepLabels` (`true`).
|
||
- `TitleJson` (`ChartTitleDto`): `Text`, `Subtitle`, `HorizontalAlignment` (`center`),
|
||
`VerticalAlignment` (`top`), `TextOverflow` (`ellipsis`), `WordWrap`.
|
||
- `AnimationJson` (`ChartAnimationDto`): `Enabled` (`true`), `Duration` (`1000`),
|
||
`Easing` (`easeOutCubic` \| `linear`), `MaxPointCountSupported` (`300`).
|
||
- `ExportJson` (`ChartExportDto`): `Enabled`, `PrintingEnabled` (`true`),
|
||
`AllowExportSelectedData`, `BackgroundColor` (`#ffffff`), `Margin` (`10`).
|
||
|
||
### 8.5 Eksenler
|
||
|
||
`ArgumentAxisJson` (`ChartArgumentAxisDto`): `Title`, `Visible` (`true`), `Width` (`1`),
|
||
`ArgumentType` (— \| `datetime` \| `numeric` \| `string`),
|
||
`AggregationInterval` (`millisecond` \| `second` \| `minute` \| `hour` \| `day` \| `week` \| `month` \| `quarter` \| `year`),
|
||
`WorkdaysOnly` (`false`), `Position` (`bottom` \| `left` \| `right` \| `top`),
|
||
`HoverMode` (`none` \| `allArgumentPoints`), `Grid` (`ChartAxisGridDto`: `Visible`, `Color`
|
||
`#d3d3d3`, `Width` `1`), `Label` → `DisplayMode` (`standard` \| `rotate` \| `stagger`),
|
||
`RotationAngle` (`90`), `OverlappingBehavior` (`hide` \| `stagger` \| `none`). Argüman alanında
|
||
lookup varsa etiket metni lookup'ın görünen değerine otomatik çevrilir.
|
||
|
||
`ValueAxisJson` bir **dizidir** (`ChartValueAxisDto[]`; çok eksenli grafik — seri `Axis` alanıyla
|
||
`Name`'e bağlanır): `Name`, `Title`, `ValueType` (`numeric`), `Position` (`left`),
|
||
`Type` (`continuous` \| `discrete` \| `logarithmic`), `Visible` (`true`), `Width` (`1`), `Grid`,
|
||
`Breaks[]` (`StartValue`/`EndValue`), `BreakStyle` (`Color` `#ababab`, `Line` `waved`, `Width` `5`),
|
||
`AutoBreaksEnabled` (`true`), `MaxAutoBreakCount` (`2`). Tek nesne yazmak `JsonException` verir.
|
||
|
||
`CommonAxisSettingsJson` (`ChartCommonAxisDto`: `Title`, `Visible`, `Width`, `Grid`) iki eksene
|
||
birden uygulanır; **eksene özel ayar varsa yok sayılır.**
|
||
|
||
### 8.6 `LegendJson` (`ChartLegendDto`)
|
||
|
||
`Visible` (`true`), `Position` (`outside` \| `inside`), `Orientation` (`vertical` \| `horizontal`),
|
||
`ColumnCount`, `RowCount`, `Title`, `BackgroundColor`, `Border`.
|
||
|
||
### 8.7 `TooltipJson` (`ChartTooltipDto`)
|
||
|
||
`Enabled`, `Shared`, `Format` / `ArgumentFormat` (DevExtreme format adları),
|
||
`Color` (`#ffffff`), `ArrowLength` (`10`), `Location` (`center` \| `edge`),
|
||
`PaddingLeftRight` (`18`), `PaddingTopBottom` (`15`), `Border`, `Font`.
|
||
|
||
### 8.8 Diğerleri
|
||
|
||
- `PanesJson` (`ChartPanesDto[]`): `Name`, `Height` (`250`), `BackgroundColor`.
|
||
Seriler `Pane` alanıyla bir bölmeye bağlanır.
|
||
- `CrosshairJson` (`ChartCrosshairDto`): `Enabled`, `Color` (`#f05b41`), `Width` (`1`),
|
||
`DashStyle` (`dot`), `HorizontalLine`, `VerticalLine`, `Label`.
|
||
- `ScrollBarJson` (`ChartScrollBarDto`): `Visible`, `Position` (`top`), `Color` (`gray`),
|
||
`Width` (`10`), `Offset` (`5`).
|
||
- `ZoomAndPanJson` (`ChartZoomAndPanDto`): `ArgumentAxis` / `ValueAxis`
|
||
(`none` \| `pan` \| `zoom` \| `both`), `AllowMouseWheel` (`true`), `AllowTouchGestures` (`true`),
|
||
`DragToZoom` (`false`), `PanKey` (`shift`), `DragBoxStyle`.
|
||
- `AnnotationsJson` (`ChartAnnotationDto[]`): `Name`, `Type` (`text` \| `image`), `Text`, `Image`,
|
||
konum için `Series` + `Argument`/`Value` ya da piksel `X`/`Y`, `OffsetX`/`OffsetY` (`-1`),
|
||
`Width`/`Height`, `PaddingLeftRight`/`PaddingTopBottom` (`10`), `WordWrap` (`normal`),
|
||
`Color` (`#ffffff`), `Font`, `Border`, `TooltipEnabled` (`true`), `Description`.
|
||
`CommonAnnotationsSettingsJson` (`ChartCommonAnnotationDto`) aynı alanları `Name` olmadan taşır.
|
||
- `CommonPaneSettingsJson` (`ChartCommonPaneDto`): yalnızca `BackgroundColor`.
|
||
- Ortak alt nesneler: `Font` (`Color` `#FFFFFF`, `Family`, `Size` `12`, `Weight` `400`),
|
||
`Border` (`Visible`, `Color` `#d3d3d3`, `Width` `1`, `CornerRadius` `0`, `DashStyle` `solid`).
|
||
|
||
---
|
||
|
||
## 9. Alan (`ListFormField`) JSON kolonları
|
||
|
||
`lowcode` §4.3.4–4.3.7'de anlatılan `LookupJson`, `ValidationRuleJson`, `ColumnStylingJson`
|
||
dışında kalanlar:
|
||
|
||
### 9.1 `ColumnFilterJson` (`ColumnFilterDto`)
|
||
|
||
| Anahtar | Anlam |
|
||
| --- | --- |
|
||
| `AllowFiltering` | Bu sütun filtrelenebilsin mi (`true`) |
|
||
| `FilterOperations[]` | İzin verilen operatörler; boş bırakılırsa tipe göre otomatik. Değerler: `=`, `<>`, `<`, `<=`, `>`, `>=`, `contains`, `notcontains`, `startswith`, `endswith`, `isblank`, `isnotblank`, `between`, `anyof`, `noneof` |
|
||
| `SelectedFilterOperation` | Varsayılan seçili operatör |
|
||
| `FilterValue` | Ekran açılırken uygulanan filtre değeri |
|
||
|
||
### 9.2 `ColumnHeaderJson` (`ColumnHeaderDto`)
|
||
|
||
`AllowHeaderFiltering` (`true`), `AllowSearch` (`false`) ve **özel başlık filtresi listesi**
|
||
(`ColumnsHeaderDataSourceDto`: `Text` + `Value` — DevExtreme filtre ifadesi dizisi):
|
||
|
||
```json
|
||
{ "AllowHeaderFiltering": true,
|
||
"DataSource": [ { "Text": "3000 altı", "Value": ["Amount", "<", 3000] },
|
||
{ "Text": "3000 üstü", "Value": ["Amount", ">=", 3000] } ] }
|
||
```
|
||
|
||
Anahtarlar PascalCase yazılır; `text`/`value` küçük harfle yazılırsa liste boş gelir (giriş, ortak
|
||
kurallar). Ekranın `HeaderFilterJson.Visible` bayrağı kapalıysa bu liste de görünmez.
|
||
|
||
### 9.3 `GroupingJson` (`ColumnGroupingDto`)
|
||
|
||
`AllowGrouping` (`true`), `GroupIndex` (kaçıncı seviyeden gruplanacağı), `AutoExpandGroup` (`false`).
|
||
`GroupIndex` verilen sütun ekran açılışında gruplanmış gelir.
|
||
|
||
### 9.4 `ColumnCustomizationJson` (`ColumnCustomizationDto`)
|
||
|
||
`Fixed` (`false`), `FixedPosition` (`left` \| `right`), `AllowReordering` (`false`).
|
||
Sol/sağa sabitlenmiş kolon yatay kaydırmada sabit kalır.
|
||
|
||
### 9.5 `TotalSummaryJson` / `GroupSummaryJson` (`ColumnTotalSummaryDto`)
|
||
|
||
| Anahtar | Anlam |
|
||
| --- | --- |
|
||
| `SummaryType` | `sum` \| `avg` \| `count` \| `min` \| `max` (`SummaryTypeEnum`; `custom` hesaplayıcısı bağlanmadığı için kullanılmaz) |
|
||
| `ValueFormat` | DevExtreme format adı (`fixedPoint`, `currency`, `percent`, `shortDate`…) |
|
||
| `DisplayFormat` | Metin şablonu: `{0}` biçimlenmiş değer, `{1}` `ShowInColumn`'daki sütunun başlığı |
|
||
| `ShowInColumn` | Özetin hangi sütunun altında görüneceği (kolon adı). `DisplayFormat`'taki `{1}` bunun başlığıdır |
|
||
| `ShowInGroupFooter` | `false` — grup alt bilgisinde göster (yalnızca `GroupSummaryJson`) |
|
||
| `AlignByColumn` | `false` — grup satırında ilgili sütunun altına hizala; `false` iken özet grup başlığının yanında parantez içinde çıkar |
|
||
|
||
`TotalSummaryJson` listenin altındaki toplam satırını, `GroupSummaryJson` grup kırılımındaki
|
||
özeti üretir; ikisi de **aynı DTO'yu** kullanır, fark yazıldıkları kolondur.
|
||
|
||
"Listenin altında toplam görünsün" isteği budur; ayrı sorgu ya da widget gerekmez.
|
||
|
||
### 9.6 `JoinTableJson` (`JoinTableDto`)
|
||
|
||
Bir kolonu **başka bir tablodan** çekmek için; view yazmadan tek alanlık join kurar.
|
||
|
||
| Anahtar | Anlam |
|
||
| --- | --- |
|
||
| `JoinType` | `INNER JOIN` \| `LEFT JOIN` \| `RIGHT JOIN` |
|
||
| `TableName` | Join kurulacak tablo |
|
||
| `BaseTableJoinFieldName` | Ana tablonun join alanı |
|
||
| `JoinFieldName` | Join kurulan tablonun ilişkili alanı |
|
||
| `SelectFieldName` | Ekranda gösterilecek alan |
|
||
| `FieldNameAlias` | Alanın takma adı |
|
||
| `JoinCondition2` | İkinci koşulun bağlacı (`AND` varsayılan \| `OR`) |
|
||
| `JoinFieldName2` | İkinci koşulun alanı — **tablo adıyla birlikte** (`Def_T_City.CultureName`) |
|
||
| `BaseTableJoinFieldName2_OrValue` | İkinci koşulun karşı tarafı: tablo adlı bir alan ya da `'en'` gibi sabit |
|
||
|
||
Üç-dört join'i geçen ihtiyaçta view tasarımcısı tercih edilir (`lowcode` §8.2).
|
||
|
||
### 9.7 Diğer alan kolonları
|
||
|
||
| Kolon | Varsayılan | Anlam |
|
||
| --- | --- | --- |
|
||
| `FieldName` | — | Kaynaktaki sütun adı; SQL'deki adıyla birebir |
|
||
| `CaptionName` | — | Sütun başlığı — **dil anahtarı** |
|
||
| `PlaceHolder` | — | Editörün placeholder metni |
|
||
| `Alignment` | `"left"` | `left` \| `center` \| `right` |
|
||
| `Format` | — | Hücre biçimi (DevExtreme format adı ya da desen) |
|
||
| `BandName` | — | Sütunu bir başlık bandının altına toplar |
|
||
| `Width` · `ListOrderNo` | — | Genişlik ve grid'deki sıra |
|
||
| `Visible` | — | Sütun grid'de görünür mü; `false` ise kolon seçicide durur ama **sorguya girer** |
|
||
| `IsActive` | `true` | `false` olan alan **sorguya bile girmez** |
|
||
| `SortIndex` · `SortDirection` | — | Açılıştaki sıralama (`asc` \| `desc`); çok sütunlu sıralamada `SortIndex` sırası belirler |
|
||
| `AllowSearch` · `AllowEditing` · `AllowAdding` | `true` | Arama paneline dâhil olma, güncellemede ve yeni kayıtta düzenlenebilirlik |
|
||
| `ColumnCssClass` · `ColumnCssValue` | — | Koşulsuz stil (sınıf adı + sınıfın içeriği); koşullu olan `ColumnStylingJson` |
|
||
| `SourceDbType` | `16` String | Kolonun `System.Data.DbType` karşılığı |
|
||
| `EditorType2` · `EditorOptions` · `EditorScript` | — | Editör tipi ve davranışı (`lowcode` §5, §6) |
|
||
| `ColSpan` · `EditOrderNo` · `EditGroupOrderNo` | — | Düzenleme formundaki yeri; `EditGroupOrderNo` `EditingFormJson`'daki `Order` ile eşleşir |
|
||
| `PermissionJson` | — | Alan yetkileri (§5.1) |
|
||
| `CultureName` · `UserId` · `RoleId` | — | Alan varyantı (§5.7) |
|
||
|
||
> **`DefaultValue` / `DefaultValueType` / `ReadOnly` diye bir alan kolonu yoktur.** İstemciye
|
||
> giden `ColumnFormatDto`'da bu adlar görünür ama çıktı alanlarıdır; seed'e yazılan değer düşer.
|
||
> Varsayılan değerler ekran seviyesindeki `Insert/Update/Delete/Form/SelectFieldsDefaultValueJson`
|
||
> bloklarında, alan adıyla eşleşen `FieldsDefaultValueDto` satırları olarak durur
|
||
> (`lowcode` §4.3.5); salt okunurluk ise `EditorOptions.readOnly` ya da `EditorScript`'in
|
||
> `readOnly` tarifidir (`lowcode` §6.6).
|
||
|
||
### 9.8 Tipli editör seçenekleri
|
||
|
||
`EditorOptions` JSON'unun bazı anahtarları backend'de **tipli DTO'ya** çözülür; yanlış tip
|
||
sessizce yok sayılır. Bu çözme, ekran kolonlarının aksine **büyük/küçük harfe duyarsızdır**
|
||
(`columns` ile `Columns` aynıdır):
|
||
|
||
| DTO | Hangi `EditorType2` | Anahtarlar (varsayılan) |
|
||
| --- | --- | --- |
|
||
| `GridBoxOptionsDto` | `dxGridBox` | `Columns[]` (ilk kolon `Key` ile aynı adda olmalı), `SelectionMode` (`"single"`), `FilterRowVisible` (`false`), `AcceptCustomValue` (`false`), `ShowClearButton` (`true`), `Height` (`250`), `Width` (`500`) |
|
||
| `TagBoxOptionsDto` | `dxTagBox` | `ShowSelectionControls` (`true`), `MaxDisplayedTags` (`3`), `ShowMultiTagOnly` (`false`), `ApplyValueMode` (`"useButtons"`), `SearchEnabled` (`true`), `AcceptCustomValue` (`false`), `ShowClearButton` (`true`) — değer tek kolonda `\|` ile saklanır, bkz. §4.3 |
|
||
| `ImageUploadOptionsDto` | `dxImageUpload` · `dxImageViewer` | `UploadUrl`, `Accept`, `Multiple`, `MaxFileSize` (bayt), `Width`, `Height`, `Capture` (`environment`/`user` — mobilde dosya seçici yerine **yalnızca** kamerayı açar; boş bırakılırsa dokunmatik cihazda dosya seçicinin yanına ayrı bir kamera butonu gelir) — hepsi nullable, varsayılanı yok |
|
||
|
||
Çözüm **yalnızca alanın `EditorType2` değeri eşleşiyorsa** yapılır: `dxTextBox` bir alana
|
||
`columns` yazmak `GridBoxOptions`'ı doldurmaz. Ayrıca `ListFormField.EditorOptions`'ın ham
|
||
metni istemciye **her hâlükârda** gider; tipli DTO'lar onun yanında ek bir kolaylıktır ve
|
||
`JsonException` durumunda sessizce `null` döner — yani bozuk JSON burada ekranı düşürmez, ama
|
||
tipli okumaya bağlı davranış (GridBox kolonları, TagBox etiket sayısı) çalışmaz.
|
||
|
||
**Cihaz yetenekleri yeni editör tipi istemez** (üçü de HTTPS ister):
|
||
|
||
| İhtiyaç | Nerede |
|
||
| --- | --- |
|
||
| Fotoğraf çekme | `dxImageUpload` · `Capture` (yukarıda) |
|
||
| Görsel tutan kolon | Editör `dxImageUpload`, kolon `nvarchar(MAX)` (base64); `dxImageViewer` kolona bağlanmaz (`lowcode.instructions.md` §0.12 madde 5) |
|
||
| Alana barkod/QR okutma | `dxTextBox` `EditorOptions.buttons[]` içinde `onClick: "@SCAN_BARCODE"` (`lowcode` §6.4) |
|
||
| Sürekli okutup her kodu yeni satır yapma | Toolbar butonu `DialogName: "BarcodeScanDialog"` + `DialogParameters` `{"field": "…", …sabit alanlar}` — ekranın insert ucundan geçer (`lowcode` §4.9) |
|
||
| Cihaz konumu | `EditorScript` `location` tarifi → `geoTo('Enlem', 'Boylam')` (`lowcode` §5.3) |
|
||
| Tasarımcıda okutma / kod basma | `BarcodeScanField` · `BarcodeViewer` (§10.9) |
|
||
|
||
---
|
||
|
||
## 10. Visual Designer envanteri
|
||
|
||
`lowcode` §7 tasarımcı dokümanının şemasını anlatır; burada **kutuda ne olduğu** listelenir.
|
||
|
||
### 10.1 Toolbox aileleri
|
||
|
||
Kutunun içeriği tek bir yerden, `getDesignerCatalog()` (`components/visualDesigner/catalog.ts`)
|
||
tarafından üretilir: elle yazılmış tanımlar + `components/ui` altındaki bileşenlerden
|
||
otomatik çıkarılan metadata (`generated/componentProps.json`).
|
||
|
||
| Aile | Bileşenler |
|
||
| --- | --- |
|
||
| `layout` | `PageContainer` (maxWidth, padding, gap, className), `FlexRow` (columns, firstColumnWidth, gap, wrap, align, className), `Table` |
|
||
| `data` | `Form` (§10.2) ve veri bağlanabilen UI bileşenleri: `Select`, `AutoComplete`, `Dropdown`, `Menu`, `Pagination`, `Radio.Group`, `Tabs`, `Grid` |
|
||
| `platform` | Gömülü ListForm görünümleri: `ListView`, `DataGridView`, `TreeView`, `GanttView`, `TodoBoard`, `CardView`, `SchedulerView`, `PivotView`, `ChartView` (§10.7). Public site düğümleri: `PublicHeaderBar`, `PublicNav`, `PublicMobileMenu`, `PublicLogo`, `PublicThemeToggle`, `PublicLanguageSelector`, `PublicDemoButton` (`PUBLIC_SITE_COMPONENTS`, §10.7) |
|
||
| `html` | `a`, `div`, `p`, `span`, `h1`, `h2`, `h3`, `h4`, `h5`, `img` — **yalnız bu on etiket** |
|
||
| `ui` | `Avatar`, `Badge`, `BarcodeScanField`, `BarcodeViewer`, `Button`, `Calendar`, `Card`, `Checkbox`, `Chips`, `ColorPicker`, `DatePicker`, `ImageViewer`, `Input`, `Knob`, `Marquee`, `Notification`, `PlatformIcon`, `Progress`, `Radio`, `RangeCalendar`, `Rate`, `ScrollBar`, `Skeleton`, `Slider`, `Spacer`, `Spinner`, `Switcher`, `Tag`, `TimeInput`, `Tooltip`, `Upload` |
|
||
| `custom` | Kayıtlı diğer custom component'ler (`Dependencies`'e eklenir) |
|
||
|
||
**`input`, `button`, `textarea`, `select`, `checkbox` HTML etiketleri kutuda yoktur**
|
||
(`HTML_UI_DUPLICATES`): karşılıkları `ui` ailesindeki `Input`, `Button`, `Select`, `Checkbox`
|
||
bileşenleridir; ham etiket bırakmaya çalışma, tema ve doğrulama onlardan gelir.
|
||
|
||
Kutu dışında tutulanlar (`EXCLUDED_COMPONENTS`): `Alert`, `Breadcrumb`, `Dialog`, `Drawer`,
|
||
`FormContainer`, `FormItem`, `InputGroup`, `MenuItem`, `Segment`, `Steps`. Bunlara ihtiyaç
|
||
duyan bir yerleşim, tasarımcı yerine **Code modunda** yazılır (`lowcode` §7.1.1) — orada
|
||
`components/ui`'nin tamamı kapsamdadır.
|
||
|
||
Çocuk düğüm kabul edenler: `PageContainer`, `FlexRow`, `Form`, `div`, `a`, `Card`, `Table`, `Tabs`,
|
||
`PublicHeaderBar`, `PublicMobileMenu` ve **her custom component**. Diğer düğümlerin içine bırakma; kanvas kabul etse de üretilen kod
|
||
çocukları çizmez.
|
||
|
||
Düğüm başına iki ortak prop, hangi ailede olursa olsun geçerlidir:
|
||
|
||
| Prop | Anlam |
|
||
| --- | --- |
|
||
| `designerPermission` | Boş değilse düğüm yalnızca bu yetki verilmişse **çizilir**; verisini göremeyeceği bir grid hiç oluşturulmaz |
|
||
| `className` | Tailwind sınıfları |
|
||
|
||
> **Önce yeniden kullan:** İstenen şey bir ListForm ekranının verdiği liste/ağaç/pano/grafikse
|
||
> primitiflerden kurma; `platform` düğümünü `listFormCode` ile bırak.
|
||
>
|
||
> **Eksik olan = var olan bileşene ekle, yeni bileşen yazma:** İstenen komponent bu
|
||
> envanterle büyük ölçüde kuruluyor ama bir bileşende **olay, prop ya da küçük bir yetenek**
|
||
> eksikse komponent yine üretilir: eksik parça `components/ui/{Name}`'e geriye dönük uyumlu
|
||
> eklenir, `componentProps.json` elle güncellenir, olaysa `catalog.ts` `DESIGNER_PRIMARY_EVENTS`,
|
||
> değer kümesiyse `NAMED_UNION_OPTIONS`/`PROPERTY_OVERRIDES`, sonra §10.9/§10.10 tabloları
|
||
> tamamlanır (`lowcode` §7.3 notu). Yeni `ui` bileşeni, yeni toolbox ailesi, Developer Kit
|
||
> menüsüne yeni komponent ya da var olan bileşenin davranışını değiştiren ekleme **yapılmaz** —
|
||
> bunlar çerçeve dışıdır ve onay ister (`lowcode` §0.8).
|
||
|
||
### 10.2 `Form` düğümü
|
||
|
||
Dört CRUD ucunu sahiplenen kapsayıcı. İçine bırakılan her bileşen kaydın bir kolonuna bağlanır.
|
||
|
||
| Prop | Varsayılan | Anlam |
|
||
| --- | --- | --- |
|
||
| `title` | `""` | Kart başlığı; boşsa Card başlığı hiç çizilmez (`::` önekli değer dil anahtarıdır) |
|
||
| `selectEndpoint` / `insertEndpoint` / `updateEndpoint` / `deleteEndpoint` | — | GET / POST / PUT / DELETE uçları |
|
||
| `selectPermission` / `insertPermission` / `updatePermission` / `deletePermission` | — | Komut yetkileri; boşsa dokümanın `permissionCode` değeri + `""`/`.Create`/`.Update`/`.Delete` **otomatik** çözülür (`FORM_AUTO_SUFFIXES`), o da yoksa komut açıktır |
|
||
| `keyFieldName` | `"id"` | Anahtar kolon |
|
||
| `collectionPath` | `""` | Select yanıtındaki liste yolu; boşsa yanıtın kendisi |
|
||
| `keySource` | `"query"` | `query` \| `route` — anahtarın URL'de nereden okunacağı |
|
||
| `keyParamName` | `""` | Parametre/segment adı; boşsa `route`'ta son segment kullanılır |
|
||
| `previewKeyValue` | `""` | Yalnızca tasarımcı önizlemesi; üretilen koda girmez |
|
||
| `autoLoad` | `true` | Açılışta veriyi çek |
|
||
| `showToolbar` | `true` | Kaydet/Sil/Gezinme çubuğu |
|
||
| `columnCount` | `1` | Form içindeki alanların kaç kolona diziliceği |
|
||
| `gap` | `16` | Alanlar arası boşluk (px) |
|
||
| `className` | `""` | Ek sınıflar |
|
||
|
||
Olayları ve script API'si `lowcode` §7.8'dedir. Bir sayfada birden fazla `Form` olabilir;
|
||
ana-detay için detay tarafının veri kaynağına `source: "record"` filtresi verilir ve değeri
|
||
`<anaFormRef>.<kolon>` biçiminde yazılır (§10.4).
|
||
|
||
### 10.3 Veri bileşenleri
|
||
|
||
`DESIGNER_DATA_COMPONENTS` iki tür tanır:
|
||
|
||
| Tür | Bileşenler | Koleksiyon prop'u |
|
||
| --- | --- | --- |
|
||
| `option` (etiket/değer) | `Select`, `AutoComplete`, `Dropdown`, `Menu`, `Pagination`, `Radio.Group`, `Tabs` | `options` (Select/AutoComplete) ya da `items` |
|
||
| `tabular` (satır) | `Grid` | `items` |
|
||
|
||
`option` bileşenlerinde binding'e `columns` eklenirse, ekranda görünmeyen kolonlar script'ten
|
||
`refs.<ad>.getColumn('kolon')` ile okunabilir. Bu, "müşteri seçilince vergi numarası da gelsin"
|
||
isteğinin tasarımcı tarafındaki karşılığıdır — ikinci bir istek atılmaz.
|
||
|
||
### 10.4 Veri kaynakları ve filtreler
|
||
|
||
Doküman seviyesindeki `dataSources` listesi, düğümlerin `bindings.sourceId` ile bağlandığı
|
||
uçlardır. Şeması `lowcode` §7.2'de; burada **filtre sözleşmesi** açılır.
|
||
|
||
| `source` | `value` ne demek | Ne zaman |
|
||
| --- | --- | --- |
|
||
| `static` | Değerin kendisi | Sabit kırılım (`IsActive = true`) |
|
||
| `query` | Sayfa adresindeki query parametresinin **adı** (`?id=…`) | Adresle taşınan bağlam |
|
||
| `route` | Yol segmentinin adı; boşsa **son segment** | `/admin/order/123` gibi rotalar |
|
||
| `record` | `<formRef>.<kolon>` — başka bir `Form` düğümünün aktif kaydının kolonu | Ana-detay; tek satır kod yazmadan |
|
||
|
||
| `operator` | Query string'e nasıl çıkar |
|
||
| --- | --- |
|
||
| `eq` | Çıplak parametre: `?RoleId=5` |
|
||
| `ne` `contains` `startswith` `endswith` `gt` `gte` `lt` `lte` `in` `isnull` `notnull` | Adını son ek olarak taşır: `?Name.contains=abc` |
|
||
|
||
`isnull` / `notnull` değer almaz (`DESIGNER_VALUELESS_FILTER_OPERATORS`); değer kutuları gizlenir.
|
||
|
||
`required` **varsayılan olarak `true`'dur ve bilinçlidir**: değeri henüz gelmemiş bir filtre
|
||
isteği tutar. Aksi hâlde filtresiz koleksiyon yüklenir ve bu, kullanıcıya "filtre çalışmıyor"
|
||
diye görünür. `previewValue` yalnızca tasarımcı kanvasında kullanılır, üretilen koda girmez.
|
||
|
||
Bu sözleşme CRUD Endpoint `GetList` ucunun okuduğu sözleşmenin aynısıdır (`lowcode` §9.1) —
|
||
yani tasarımcıdan kurulan filtre, sunucu tarafında ek bir şey yazmadan çalışır.
|
||
|
||
### 10.5 Property Panel — nasıl çalışır
|
||
|
||
Kanvasta seçili düğümün sağ paneli üç sekmedir ve her prop bir **kategoriye** aittir:
|
||
|
||
| Kategori | Nerede görünür | Ne taşır |
|
||
| --- | --- | --- |
|
||
| `properties` | Properties sekmesi | Davranış ve içerik prop'ları |
|
||
| `styling` | Properties sekmesi (stil grubu) | `className`, boyut, boşluk, hizalama |
|
||
| `events` | **JavaScript sekmesi** | `function` tipli prop'lar — değer değil **script** olarak düzenlenir (§7.8 · `lowcode`) |
|
||
|
||
Panelin kuralları:
|
||
|
||
- **Değer kümesi bilinen prop yazılmaz, seçilir.** `options` taşıyan (ya da tsType'ı bilinen bir
|
||
union olan) her string prop panelde açılır listeye döner (`withPickableOptions`); listede
|
||
olmayan mevcut değer korunur.
|
||
- **Olay listesi süzülür:** `DESIGNER_PRIMARY_EVENTS`'te kaydı olan bileşende yalnızca o olaylar
|
||
JavaScript sekmesinde görünür (aşağıda §10.10); kaydı olmayan bileşende bütün `function`
|
||
prop'ları listelenir.
|
||
- `field` ve `form` prop'ları panelde **hiç görünmez** (Formik'in runtime nesneleridir).
|
||
- Her düğümün panel-üstü iki ortak alanı vardır: **`ref`** (script adresi — `refs.<ad>`) ve
|
||
**`designerPermission`** (boş değilse düğüm yalnızca o yetkiyle çizilir).
|
||
- Seed dosyasına yalnızca **varsayılandan farklı** prop'ları yaz; panel dokunulmayan prop'u
|
||
dokümana koymaz.
|
||
|
||
### 10.6 `layout` bileşenleri — prop sözleşmesi
|
||
|
||
**`PageContainer`** — sayfanın dış kabı; çocuk kabul eder:
|
||
|
||
| Prop | Varsayılan | Anlam |
|
||
| --- | --- | --- |
|
||
| `maxWidth` | `"1280px"` | İçerik genişliği (CSS değeri) |
|
||
| `padding` | `24` | İç boşluk (px) |
|
||
| `gap` | `16` | Çocuklar arası dikey boşluk (px) |
|
||
| `className` | `""` | |
|
||
|
||
**`FlexRow`** — yatay bölme; çocuk kabul eder:
|
||
|
||
| Prop | Varsayılan | Anlam |
|
||
| --- | --- | --- |
|
||
| `columns` | `1` | `1` = serbest akan flex satırı; `2+` = o kadar **eşit grid kolonu** |
|
||
| `firstColumnWidth` | `""` | Yalnız kolon modunda: ilk kolonu sabitler → kenar çubuğu düzeni (`"320px"`) |
|
||
| `gap` | `16` | Kolonlar arası boşluk |
|
||
| `wrap` | `true` | Taşan çocuk alta insin mi (yalnız flex modunda) |
|
||
| `align` | `"stretch"` | `stretch` \| `start` \| `center` \| `end` |
|
||
| `className` | `""` | |
|
||
|
||
**`Table`** (`ui` kitinden, `layout` grubunda; çocuk kabul eder) — statik tablo:
|
||
`borderlessRow` (—), `compact` (`false`), `hoverable` (`true`), `overflow` (`true`),
|
||
`rowCount` (`2`), `columnCount` (`3`), `className`. `columns`/`data` prop'ları panelden
|
||
kaldırılmıştır — hücreler kanvasta çocuk düğüm olarak doldurulur. Veri bağlanabilir tablo
|
||
istiyorsan `Grid` (data) ya da `DataGridView` (platform) kullan.
|
||
|
||
**`Spacer`** (`ui` grubunda listelenir) — dikey boşluk: `height` (`24`).
|
||
|
||
### 10.7 `platform` bileşenleri — prop sözleşmesi
|
||
|
||
Dokuz görünüm düğümü de aynı üç prop'u alır; başka prop'ları **yoktur** (görünümün tüm davranışı gömülen
|
||
ListForm ekranının kendi tanımından gelir):
|
||
|
||
| Prop | Varsayılan | Anlam |
|
||
| --- | --- | --- |
|
||
| `listFormCode` | `""` | **Zorunlu.** Gömülecek ekranın kodu |
|
||
| `height` | `"520px"` (`ChartView`: `"420px"`) | Kapsayıcı yüksekliği |
|
||
| `className` | `""` | |
|
||
|
||
`ListView` · `DataGridView` · `TreeView` · `GanttView` · `TodoBoard` · `CardView` ·
|
||
`SchedulerView` · `PivotView` · `ChartView`. Bileşen, kullanıcının o ekranda yetkisi yoksa
|
||
ekranın kendi yetki hatasını gösterir; ayrıca gizlemek istiyorsan `designerPermission` yaz.
|
||
Gömülen görünüm, hedef ekranın `LayoutJson`'ında açık olmalıdır.
|
||
|
||
**Public site düğümleri** yalnızca public bileşenlerde (`PublicHeader`, `PublicFooter`, public
|
||
sayfalar) anlamlıdır; veriyi uygulama konfigürasyonundan (`publicMenus`, tema, dil) okur:
|
||
|
||
| Düğüm | Prop'lar (varsayılan) |
|
||
| --- | --- |
|
||
| `PublicHeaderBar` (çocuk kabul eder) | `scrolledClassName`, `scrollThreshold` (`10`) — sayfa kaydırılınca ek sınıf |
|
||
| `PublicNav` | `source` (`navigation` gezinme bağlantıları \| `actions` vurgulu/CTA kayıtlar \| `all`; kaynak `Pub` menüsündeki `App.Public.Header` düğümleri), `variant` (`horizontal` \| `vertical`), `showIcons` (`true`), `iconSize`, `itemClassName`, `activeItemClassName` |
|
||
| `PublicMobileMenu` (çocuk kabul eder) | `buttonClassName`, `panelClassName` |
|
||
| `PublicLogo` · `PublicThemeToggle` · `PublicLanguageSelector` · `PublicDemoButton` | Yalnız sınıf prop'ları (`imgClassName`, `buttonClassName`, `activeClassName`, `iconSize` `15`) |
|
||
|
||
Runtime kapsamında `react-icons`/`react-router` yoktur: ikon `PlatformIcon` (`name` `FaUser`,
|
||
`size` `24`), gezinme `a` düğümüdür. Kanvasın doğrudan çizdiği düğümler
|
||
`componentEditor/runtimeNodes.ts` sözlüğündedir; yeni düğüm = bileşen + bu sözlük + `catalog.ts` +
|
||
dil anahtarı.
|
||
|
||
### 10.8 `html` elemanları — prop sözleşmesi
|
||
|
||
| Eleman | Prop'lar | Olaylar |
|
||
| --- | --- | --- |
|
||
| `a` (çocuk kabul eder) | `children`, `href`, `target`, `aria-label`, `className`, `style` — public sayfalarda gezinmenin tek yolu | `onClick` |
|
||
| `div` (çocuk kabul eder) | `children`, `className`, `style` | `onClick`, `onMouseEnter`, `onMouseLeave` |
|
||
| `p` · `span` | `children`, `className` | `onClick` |
|
||
| `h1`–`h5` | `children`, `className` — başlıklar hazır Tailwind sınıfıyla düşer (`h1`: `text-4xl font-bold` … `h5`: `text-lg font-semibold`); Tailwind reset'i yüzünden sınıfı silersen başlık paragraf boyutuna iner | `onClick` |
|
||
| `img` | `src` (yeni düşen eleman gömülü SVG yer tutucusuyla gelir; herhangi bir URL/data-URI yazılabilir), `alt`, `width`, `height`, `loading`, `decoding`, `className` (`max-w-full rounded-md`) | `onClick`, `onLoad` |
|
||
|
||
`input`/`button`/`textarea`/`select`/`checkbox` etiketleri kutuda yoktur — `ui` karşılıklarını
|
||
kullan (§10.1).
|
||
|
||
### 10.9 `data` ve `ui` bileşenleri — Property Panel sözleşmeleri
|
||
|
||
Kaynak: `generated/componentProps.json` + `catalog.ts` düzeltmeleri. Her tabloda yalnızca
|
||
karar gerektiren prop'lar listelenir; `className`, `children`, `style` her bileşende vardır ve
|
||
tekrarlanmaz. `(z)` = zorunlu.
|
||
|
||
**Veri bileşenleri** (koleksiyon prop'u §10.3'e göre statik değer ya da data source binding'i
|
||
alır):
|
||
|
||
| Bileşen | Koleksiyon | Diğer prop'lar (varsayılan) |
|
||
| --- | --- | --- |
|
||
| `Select` | `options[]` (`{label, value}`) | `size` (`sm/md/lg`), `componentAs` (`''` \| `ReactSelect` \| `CreatableSelect` \| `AsyncSelect`), `value`, `isDisabled` (`false`), `isMulti` (`false`), `isClearable` (`false`), `isSearchable` (`true`) — tasarımcı `disabled/multiple/clearable/searchable` adlarını react-select karşılıklarına çevirir |
|
||
| `AutoComplete` | `options[]` | `value`, `defaultValue`, `placeholder`, `disabled` (`false`), `invalid` (`false`), `size`, `debounce`, `minChars` (`1`), `clearable` (`true`), `noOptionsText`, `loadingText`, `name` |
|
||
| `Dropdown` | `items[]` (`{eventKey, children, to}`) | `title` (`'Dropdown'`), `trigger` (`click` \| `hover` \| `context`), `placement` (`bottom-start`; 10 değerli liste), `disabled`, `activeKey`, `menuClass`, `menuStyle` |
|
||
| `Menu` | `items[]` (`{eventKey, icon, children/label}`) | `menuItemHeight` (`30`), `sideCollapsed` (`false`), `variant` (`light` \| `dark` \| `themed` \| `transparent`), `defaultActiveKeys[]`, `defaultExpandedKeys[]` |
|
||
| `Pagination` | `items[]` | `currentPage` (`1`), `pageSize` (`1`), `total` (`5`), `displayTotal` (`false`) |
|
||
| `Radio.Group` | `items[]` (`{value, label, disabled}`) | `name` (`'radioGroup'`), `value`, `vertical` (`false`), `disabled`, `readOnly`, `color` |
|
||
| `Tabs` | `items[]` (`{label, value}`) — **her sekme değeri bir çocuk yuvasıdır** (`slot: "tab:<value>"`), içine bileşen bırakılır | `defaultValue`, `value`, `variant` (`underline` \| `pill`) |
|
||
| `Grid` | `items[]` (satır nesneleri; kolonlar binding'den seçilir) | `cols` (`3`), `rows` (`2`), `gap`/`colGap`/`rowGap` (`4`), `responsive` (`true`), `smCols`/`mdCols`/`lgCols`/`xlCols` (`1/2/3/4`), `autoFit` (`false`), `minColWidth` (`'200px'`), `height` (`'auto'`) |
|
||
|
||
**Form/giriş bileşenleri:**
|
||
|
||
| Bileşen | Prop'lar (varsayılan) |
|
||
| --- | --- |
|
||
| `Input` | `type` (`text`; `HTMLInputTypeAttribute` listesi: `text/password/email/number/tel/url/search/date/time/…`), `value`, `placeholder` (`'Metin girin...'`), `textArea` (`false`) + `rows` (`3`), `prefix`/`suffix`, `size`, `disabled`, `invalid`, `readOnly`, `required`, `maxLength`/`minLength`, `pattern`, `autoComplete` (`off`), `autoFocus`, `name`, `unstyle` |
|
||
| `Checkbox` | `checked`, `defaultChecked`, `value`, `name`, `color`, `disabled`, `readOnly` |
|
||
| `Switcher` | `checked`, `defaultChecked`, `checkedContent`/`unCheckedContent`, `color`, `disabled`, `readOnly`, `isLoading` (`false`), `name` |
|
||
| `Radio` | `checked`, `defaultChecked`, `value`, `name`, `color`, `vertical`, `disabled`, `readOnly` — tekil düğme; seçenek grubu için `Radio.Group` |
|
||
| `DatePicker` | `value`/`defaultValue` (ISO string olarak saklanır, render'da `Date`'e çevrilir), `inputFormat`, `closePickerOnChange` (`true`), `defaultOpen` (`false`), `openPickerOnClear` (`false`), `inputtableBlurClose` |
|
||
| `TimeInput` | `value`/`defaultValue`, `format` (`24` \| `12`), `showSeconds` (`false`), `clearable` (`true`), `amLabel`/`pmLabel`, `timeFieldPlaceholder` (`'--'`), `prefix`/`suffix`, `size` (`md`), `disabled`, `invalid`, `name` |
|
||
| `Calendar` · `RangeCalendar` | `value` (`Date` \| `Date[]`), `multipleSelection` · `value` (`[Date, Date]`), `singleDate` (`false`) |
|
||
| `ColorPicker` | `value`/`defaultValue` (`'#6366f1'`), `presets[]`, `showAlpha`, `showInput` (`true`), `showRgb` (`false`), `size` (`md`), `disabled`, `name` |
|
||
| `Chips` | `value`/`defaultValue` (string dizisi; örnek `['Deneme','Deneme2']`), `max` (`0` = sınırsız), `allowDuplicate` (`false`), `separator`, `placeholder`, `size`, `disabled`, `invalid`, `name` |
|
||
| `Slider` | `value`/`defaultValue`, `min` (`0`), `max` (`100`), `step` (`1`), `range` (`false`), `orientation` (`horizontal` \| `vertical`), `marks`, `tooltip` (`false`), `trackSize` (`4`), `handleSize` (`18`), `disabled`, `readOnly`, `name` |
|
||
| `Knob` | `value`/`defaultValue` (`0`), `min`/`max` (`0/100`), `step` (`1`), `size` (`100`), `strokeWidth` (`14`), `valueColor`/`rangeColor`/`textColor`, `valueTemplate` (`'{value}'`), `showValue` (`true`), `readOnly`, `disabled`, `name` |
|
||
| `Rate` | `count` (`5`), `value`/`defaultValue`, `allowHalf` (`false`), `allowClear` (`true`), `color` (`amber`), `size` (`20`), `gap` (`4`), `tooltips[]`, `disabled`, `readOnly` |
|
||
| `Upload` | `accept`, `multiple`, `draggable` (`false`), `uploadLimit`, `showList` (`true`), `tip`, `fileList[]`, `disabled` — dosyanın **gerçek** yüklenmesi `beforeUpload`/`onChange` script'inde `api.post` ile yapılır |
|
||
| `BarcodeScanField` | `label`, `name` (`'barcode'`), `placeholder`, `buttonText`, `continuous` (`false` — açıkken diyalog okumadan sonra kapanmaz), `readOnly` (`true`), `className`; **olay**: `onScan(event)` — `event` okunan kodun metin hâli (Event workspace'te Input'un `onChange`'i gibi düzenlenir). Kamerayı `BarcodeDetector` (Android/Chromium) ya da lazy `zxing-wasm` (iOS/Firefox) ile okur — 1D + QR. **HTTPS şart**; iOS'ta yüklü PWA içinde yalnız 16.4+ çalışır, bileşen aksini kullanıcıya söyler |
|
||
| `BarcodeViewer` | `value` (barkoda çevrilecek veri), `format` (`QRCode` \| `Code128` \| `Code39` \| `Code93` \| `Codabar` \| `EAN13` \| `EAN8` \| `UPCA` \| `UPCE` \| `ITF` \| `DataMatrix` \| `PDF417` \| `Aztec`), `label`, `showText` (`false` — kodun altına okunabilir metni de basar), `scale` (`4`, modül kalınlığı), `fitWidth` (`false` — açıkken kapsayıcının genişliğine yayılır), `className`. Veriyi **SVG** olarak çizer (lazy `zxing-wasm/writer`); karanlık temada da okunabilsin diye beyaz zemin üstünde. `Form` düğümünün içinde `value` bir kolona bağlanırsa kayıt değiştikçe kod yeniden çizilir — tıpkı bir `Input` gibi. Veri formata uymuyorsa (EAN13'e harf gibi) kod yerine zxing'in hata metni görünür |
|
||
|
||
**Gösterim/geri bildirim bileşenleri:**
|
||
|
||
| Bileşen | Prop'lar (varsayılan) |
|
||
| --- | --- |
|
||
| `Button` | `variant` (`default` \| `solid` \| `twoTone` \| `plain`), `color`, `size` (`sm`), `shape` (`round` \| `circle` \| `none`), `icon`, `block` (`false`), `active` (`false`), `loading` (`false`), `disabled` |
|
||
| `Card` (çocuk kabul eder) | `header`/`headerExtra`/`footer`, `headerBorder`/`footerBorder` (`true`), `bordered`, `clickable` (`false`), `bodyClass`/`headerClass`/`footerClass` |
|
||
| `Avatar` | `src`/`srcSet`, `icon`, `alt`, `size` (`md`), `shape` (`circle`; `round` \| `circle` \| `square`) |
|
||
| `Badge` | `content`, `maxCount` (`99`), `innerClass`, `badgeStyle` |
|
||
| `Tag` | `children`, `prefix`/`suffix` (+ `prefixClass`/`suffixClass`), `title` |
|
||
| `Progress` | `variant` (`line` \| `circle`), `percent` (`0`), `color`, `showInfo` (`true`), `customInfo`, `strokeWidth` (`6`), `strokeLinecap` (`round` \| `square`), `width` (`120`; circle), `gapDegree`/`gapPosition` (circle) |
|
||
| `Skeleton` | `variant` (`block` \| `circle`), `animation` (`true`), `width`/`height`, `asElement` |
|
||
| `Spinner` | `size` (`20`), `color`, `isSpining` (`true`), `enableTheme` (`true`), `indicator` |
|
||
| `Notification` | `title`, `type` (`success` \| `warning` \| `danger` \| `info`), `closable` (`false`), `duration` (`3000`), `customIcon`, `width` (`350`) — sayfada sabit kutu olarak durur; olaya bağlı geçici bildirim için script'te `notify()` kullan |
|
||
| `Tooltip` | `title`, `placement` (`top`; 12 değerli `ArrowPlacement` listesi), `isOpen`, `wrapperClass` |
|
||
| `ImageViewer` | `images[]` (`{src, alt, caption}` — yeni düşen bileşen iki örnek görselle gelir), `children` (`'Galeri'` tetikleyici), `defaultIndex` (`0`), `loop` (`true`), `showToolbar`/`showThumbnails` (`true`), `zoomStep` (`0.25`), `minZoom`/`maxZoom` (`0.5/4`), `keyboard` |
|
||
| `Marquee` | `speed` (`100`), `direction` (`left` \| `right` \| `up` \| `down`), `pauseOnHover`/`pauseOnClick` (`false`), `loop` (`0` = sonsuz), `gradient` (`false`), `gradientColor`/`gradientWidth`, `delay` (`0`), `play` (`true`), `autoFill` (`false`) |
|
||
| `ScrollBar` | `direction` (`ltr` \| `rtl`) |
|
||
|
||
### 10.10 Olaylar — bileşen başına `event` yükü
|
||
|
||
JavaScript sekmesinde görünen olaylar ve handler'a gelen tek argümanın (`event`) içeriği.
|
||
Script kapsamındaki her şey (`refs`, `api`, `notify`, `translate`, `checkPermission`) ve
|
||
`Form` yaşam döngüsü olayları `lowcode` §7.8'dedir; buradaki tablo bileşen olaylarının yüküdür.
|
||
|
||
| Bileşen | Olay(lar) | `event` |
|
||
| --- | --- | --- |
|
||
| `Button` | `onClick` | DOM tıklama olayı |
|
||
| `Input` | `onChange` | DOM olayı → değer `event.target.value` |
|
||
| `Checkbox` | `onChange` | `event.checked` |
|
||
| `Select` | `onChange` | Seçilen `{label, value}` nesnesi; temizlenince `null` → `event?.value ?? null` |
|
||
| `AutoComplete` | `onInputChange` · `onSelect` | Yazılan metin · seçilen option nesnesi |
|
||
| `Dropdown` | `onSelect` | Seçilen öğenin `eventKey` değeri |
|
||
| `Menu` | `onSelect` | Seçilen öğenin `eventKey` değeri |
|
||
| `Pagination` | `onChange` | Seçilen sayfa numarası |
|
||
| `Radio.Group` | `onChange` | Seçilen öğenin `value` değeri |
|
||
| `Tabs` | `onChange` | Aktif sekmenin `value` değeri |
|
||
| `BarcodeScanField` | `onScan` | Okunan kodun metni |
|
||
|
||
Bu on bir bileşen `DESIGNER_PRIMARY_EVENTS` kaydıdır — panel yalnızca bu olayları gösterir.
|
||
Kayıtta olmayan bileşenlerde bütün `function` prop'ları listelenir; işe yarayanlar:
|
||
|
||
| Bileşen | Olaylar |
|
||
| --- | --- |
|
||
| `Switcher` · `ColorPicker` · `Knob` · `Slider` (+`onAfterChange`) · `Rate` (+`onHoverChange`) · `TimeInput` · `DatePicker` · `RangeCalendar` | `onChange` — yeni değer |
|
||
| `Chips` | `onChange`, `onAdd`, `onRemove` |
|
||
| `Upload` | `beforeUpload` (false → dosya reddedilir), `onChange` (dosya listesi), `onFileRemove` |
|
||
| `Card` · `Avatar` · `p` · `span` · `h1`–`h5` | `onClick` |
|
||
| `div` | `onClick`, `onMouseEnter`, `onMouseLeave` |
|
||
| `a` | `onClick` |
|
||
| `img` | `onClick`, `onLoad` |
|
||
| `Notification` · `ImageViewer` | `onClose` (`ImageViewer` ayrıca `onIndexChange`) |
|
||
| `Marquee` | `onFinish`, `onCycleComplete` |
|
||
|
||
Sayfa düzeyinde tek yaşam döngüsü kancası vardır: **`lifecycle.onMount`** — sayfa açıldığında
|
||
bir kez çalışır; açılış verisi çekme ve `refs` üzerinden ilk durumu kurma buraya yazılır.
|
||
|
||
> Olay davranışı kurarken önce Script Builder tarifleri (`lowcode` §7.8 tablosu) denenir;
|
||
> serbest kod `custom` tarifiyle eklenir ki sihirbaz açık kalsın.
|
||
|
||
---
|
||
|
||
## 11. Zamanlanmış e-posta (MailQueue modülü)
|
||
|
||
`BackgroundWorker` kaydı (`Sas_H_BackgroundWorker`, ekran Saas › Background Workers ›
|
||
Recurring Jobs) `WorkerType: 1` (MailQueueWorker) ise gövde bu modüldür
|
||
(`api/modules/Sozsoft.MailQueue`). Diğer tipler: `2` SqlWorker (`BeforeSp`/`AfterSp`) · `3`
|
||
NotificationWorker · `4` SessionCleanupWorker · `5` BackupWorker. `Scope`: `1` Host · `2` Tenant ·
|
||
`3` All (host + her kiracı) — kiracı tablosuna dokunan iş `Host` olamaz (`README.md` §14). Hazır
|
||
işler `data/App.BackgroundWorkers.RecurringJobs.json` ile gelir.
|
||
|
||
### 11.1 Worker `Options` (`MailQueueWorkerOptions`)
|
||
|
||
| Anahtar | Anlam |
|
||
| --- | --- |
|
||
| `MailType` | Şablon tipi etiketi |
|
||
| `MailSubject` | Mail konusu |
|
||
| `MailTemplate` | Razor ile render edilen HTML gövde (`EmailLayout` düzeni içinde) |
|
||
| `TableName` | Maildeki tabloların tarifi (§11.2) |
|
||
|
||
### 11.2 `TableName` biçimi
|
||
|
||
Her tablo `{index:TabloAdi:DosyaTipi:MailEkAdi:Korumalimi:DosyaAciklama}` altılısıdır;
|
||
birden fazlası `};{` ile birleştirilir:
|
||
|
||
```
|
||
{0:MT3_GECIKEN_SIPARIS:IN:Order Delay Notification:0:};{1:MT7_SIPARIS_DURUM:PDF:Durum.pdf:0:BRU,3,1}
|
||
```
|
||
|
||
- `TabloAdi` bir **tablo/view adıdır**; `SELECT * FROM {TabloAdi} WHERE ...` olarak parametreli
|
||
çalıştırılır (parametreler kuyruk satırındaki `TableParameter` alanından gelir).
|
||
- `DosyaTipi` = `IN` ise tablo mail gövdesine gömülür; `PDF` / `XLS` / `TXT` ise ek dosya olur.
|
||
- Sütun başlıkları, sırası, CSS'i ve alt toplamları `Sas_H_BackgroundWorker_MailQueueTableFormat`
|
||
kayıtlarından okunur: `TableName`, `Order`, `ColumnName`, `Caption`, `HeaderCss`, `Css`,
|
||
`FooterCss`, `DataType`, `DataFormat`, `IsHidden`, `IsProtected`, `SubTotal`, `Width`.
|
||
|
||
### 11.3 Kuyruk satırı (`Sas_H_BackgroundWorker_MailQueue`)
|
||
|
||
`TemplateId` (worker), `From`, `To`, `MailParameter`, `TableName`, `TableParameter`,
|
||
`Attachment`, `AttachmentParameter`, `RelatedRecordId`, `SendStatus`, `SendTime`, `AwsMessageId`.
|
||
Gönderim sonuçları `Sas_H_BackgroundWorker_MailQueueEvents` tablosunda izlenir. Tabloların
|
||
ekranı yoktur; satırı kanca/prosedür yazar.
|
||
|
||
Kuyruğa satır yazma işi genellikle worker'ın `BeforeSp` prosedüründe ya da ekranın
|
||
`InsertAfterCommand` kancasında yapılır — yani "kayıt onaylanınca mail çıksın" isteği kod
|
||
gerektirmez.
|
||
|
||
---
|
||
|
||
## 12. Saas, Administration ve İK menüleri — platform yetenek kataloğu
|
||
|
||
Bu üç menü, platformun **hazır gelen tüm yeteneklerinin** girişidir. Bir komponent üretirken
|
||
buradaki her ekran üç rolden birindedir:
|
||
|
||
- **Yeniden kullanılacak yetenek** — numaratör, bildirim, zamanlanmış iş, rapor, dosya, yetki,
|
||
dil, ayar. Talebin bu kısmı için yeni artefakt üretilmez; ilgili ekrana kayıt girilir.
|
||
- **Veri kaynağı** — ülke/il/ilçe, para birimi, ölçü birimi, departman, ünvan, şube, kullanıcı,
|
||
rol. Yeni ekranın lookup'ı bu tablolara bağlanır; aynı listeyi tekrar tanımlama.
|
||
- **Referans uygulama** — istenen davranışın bu uygulamada zaten çalışan bir örneği. Aynı JSON'u
|
||
oradan alıp uyarlamak, sıfırdan yazmaktan hem hızlı hem güvenlidir (§12.7).
|
||
|
||
### 12.1 Tablo adlandırma sözleşmesi
|
||
|
||
Platform tablolarının adı `TableNameResolver` tarafından üretilir:
|
||
|
||
```
|
||
{ModülÖnEki}_{H|T|B}_{TableNameEnum} view'ler: V_{aynı ad}
|
||
```
|
||
|
||
| Parça | Değerler |
|
||
| --- | --- |
|
||
| Modül ön eki (`MenuPrefix`) | Yalnızca `Sas` (Saas) · `Adm` (Administration) · `Hr` (İK — `ListFormSeeder_Hr`, menü/yetki grubu `App.Hr`, modül `Hr`). Modüller (`api/modules/*`) kendi `*DbProperties.MenuPrefix` değerini taşır (MailQueue/Settings/Languages `Sas`, Notifications `Adm`) |
|
||
| Kapsam | `H` host (tüm tenant'lar için ortak) · `T` tenant · `B` şube (`TablePrefix.BranchByName`; şu an eşlemesi olan tablo yok) |
|
||
| Ad | `TableNameEnum` üyesi |
|
||
|
||
Örnek: `Sas_H_Currency` (host — tüm kiracılar aynı para birimlerini görür), `Hr_T_Department`
|
||
(kiracı başına), `V_Sas_H_Order` (view). Menü ile tablo öneki her zaman örtüşmez:
|
||
`Sas_T_GlobalSearch`, `Sas_T_Branch`, `Sas_T_Forum*`, `Sas_T_IntranetWidget` kiracı tablosudur. Özel view'ler
|
||
`TableNameResolver.GetFullSpecialViewName` ile `V_{Önek}_{Prefix}_{Ad}` biçiminde üretilir.
|
||
|
||
> Yeni bir platform tablosu eklenecekse `TableNameEnum` + `TableNameResolver._map` birlikte
|
||
> güncellenir; eşlemesi olmayan ad `KeyNotFoundException` fırlatır. Proje tabloları için
|
||
> `lowcode.instructions.md` §2'deki `{Modul}_T_{Entity}` kuralı geçerlidir.
|
||
|
||
### 12.2 Saas menüsü
|
||
|
||
Kök menü `App.Saas`. Yetki adı her satırda menünün `RequiredPermissionName` değeridir; ListForm
|
||
ekranlarında alt yetkiler `.Create`, `.Update`, `.Delete`, `.Export`, `.Import`, `.Note`
|
||
soneklerini alır.
|
||
|
||
| Ekran | Kod / route | Tablo | Kapsam | Komponent üretirken ne işe yarar |
|
||
| --- | --- | --- | --- | --- |
|
||
| **Definitions › AiBot** | `App.Definitions.AiBot` | `Sas_H_AiBot` | host | Yapay zekâ asistanı tanımı (`Name`, `ApiUrl`, `Tenants`); `/admin/ai` bu kayıtları kullanır. |
|
||
| **Definitions › Global Search** | `App.Definitions.GlobalSearch` | `Sas_T_GlobalSearch` | tenant | Üretilen ekranın üst aramada çıkması için kayıt: `System`, `Group`, `Term`, `Weight`, `Url`. |
|
||
| **Definitions › Contact Title** | `App.Definitions.ContactTitle` | `Sas_H_ContactTitle` | host | Ünvan/hitap lookup'ı (`Title`, `Abbreviation`). |
|
||
| **Definitions › Currency** | `App.Definitions.Currency` | `Sas_H_Currency` | host | Para birimi + `Rate`. Tutar alanı olan ekranın kur lookup'ı ve `DbQuery` varsayılanı buradan beslenir. |
|
||
| **Definitions › Country Group / Country / City / District** | `App.Definitions.CountryGroup` · `.Country` · `.City` · `.District` | `Sas_H_CountryGroup` · `Sas_H_Country` · `Sas_H_City` · `Sas_H_District` | host | Adres alanlarının hazır cascade zinciri (dört ayrı menü ve seed dosyası; `Order` sırası grup → ülke → il → ilçe). `Country` ayrıca `PhoneCode`, `PhoneNumberFormat`, `ZipRequired`, `StateRequired`, `TaxLabel` taşır — adres doğrulaması için kullan. |
|
||
| **Public › Products / Payment Methods / Installment Options** | `App.Orders.Products` · `.PaymentMethods` · `.InstallmentOptions` | `Sas_H_Product` · `Sas_H_PaymentMethod` · `Sas_H_InstallmentOption` | host | Ürün, ödeme yöntemi (`Commission`), taksit — satış/abonelik ekranlarının ve public `/products` sayfasının kaynağı. |
|
||
| **Public › Sales Orders** | `App.Orders.SalesOrders` (alt form Sales Order Item) | `Sas_H_Order` + `Sas_H_OrderItem` | host | **Onay akışı + alt kalem + toplam + diyalog** birlikte kullanılan tam örnek (§12.7). |
|
||
| **Public › Blog Category / Posts** | `App.BlogManagement.Category` · `.Posts` | `Sas_H_BlogCategory` · `Sas_H_BlogPost` | host | Çok dilli içerik (`ContentTr`/`ContentEn`), slug, yayın durumu, sayaç alanları; public `/blog` bu tablolardan okur, yayınlanmış yazılar sitemap'e girer. |
|
||
| **Public › Demos** | `App.Demos` | `Sas_H_Demo` | host | Public `/demo` formundan gelen talepler — public form → tablo akışının örneği. |
|
||
| **Dev Requests** | `App.DevRequests` | `Sas_H_DevRequest` | host | **Kanban/Todo düzeninin** referansı (`DefaultLayout: todo`): `Status`, `Priority`, `SortOrder`, `Tags`, `Assignees`, `SubTasks`, `Timesheets`; detayda `Description` yanında `Analysis` sekmesi (`AnalysisExpr`). MCP geliştirme döngüsünün kuyruğudur (`Backlog` → `Analysis` MCP analiz eder, `Ready to Start`'a kullanıcı alır; `Ready to Start` → `Testing`, `Staging`'e kullanıcı alır; araç çubuğunda DB Migrate butonu vardır — `UiEvalService.ApiDbMigrate()`, `App.Setup.Migrate`; yalnızca `start_dev_request` başlatır; açıklamadaki base64 görseller MCP'ye resim içeriği olarak gider, analiz `save_dev_request_analysis` ile yazılır, üretim notu `append_dev_request_note` ile `Analysis`'e eklenir — `Description` talebin yazıldığı hâliyle kalır; `lowcode.instructions.md` §0.11–§0.12). |
|
||
| **Tenants** | `AbpTenantManagement.Tenants` | `AbpTenants` | host | Kiracı kaydı, bağlantı dizesi diyaloğu (`TenantsConnectionString`), alt form olarak şubeler; yazma `list-form-dynamic-api/tenant-*`. Ekranların `IsTenant` davranışının kaynağı. |
|
||
| **Branches** | `App.Branches` | `Sas_T_Branch` | tenant | Şube listesi. Ekranı `IsBranch = true` yaparsan filtre bu tablodan gelir; `BranchSeed` diyaloğu şube verisini kurar. |
|
||
| **Setting Definitions** | `App.SettingDefinitions` | `Sas_H_SettingDefinition` | host | Yeni uygulama ayarı: `Code`, `MainGroupKey`/`SubGroupKey`, `DataType`, `SelectOptions`, `DefaultValue`, `Providers`, `RequiredPermissionName`, `IsEncrypted`, `IsVisibleToClients`. Hazır tanımlar `data/App.SettingDefinitions.json`'dan gelir. Ayarlanabilir olması gereken değeri koda gömme. |
|
||
| **Languages › Language / Language Text** | `App.Languages.Language` · `.LanguageText` | `Sas_H_Language` · `Sas_H_LanguageKey` · `Sas_H_LanguageText` | host | Dil anahtarları. Üretilen her ekranın EN+TR metinleri buraya yazılır; ekran `data/App.Languages.{Language,LanguageText}.json` dosyalarına senkronlanır. Metin insert'i eksik `LanguageKey`'i de üretir, aynı kültür+kaynak+anahtar varsa eklemez. |
|
||
| **Data Source** | `App.DataSource` | `Sas_H_DataSource` | host | `Code`, `DataSourceType`, `ConnectionString`. **İki tür kayıt bir arada:** elle tanımlanan host/harici bağlantılar ve `Code = tenant adı` olan otomatik tenant bağlantıları (Tenants ekranındaki bağlantı diyaloğu yönetir, elle dokunma). Varsayılan kaydı `HostDataSeeder` appsettings'teki bağlantı cümlesinden kurar. Çözüm kuralı `lowcode` §9.3.3. Bağlantı dizesi koda/JSON'a yazılmaz. |
|
||
| **Background Workers › Recurring Jobs / Jobs** | `App.BackgroundWorkers.RecurringJobs` · `.Jobs` | `Sas_H_BackgroundWorker` · `Sas_H_BackgroundWorker_JobFlow` | host | Cron'lu işler ve çalıştırma geçmişi (`Tenant`, `ExecutionDate`, `Duration`, `Status`, `FailureReason`, `ExceptionDetails`). `WorkerType`/`Scope` değerleri §11'de; her kapsam ayrı bir Hangfire işidir, `Tenant` kolonu hangi kiracıda çalıştığını gösterir. Hazır işler (oturum temizliği, bildirim, yedek, şema sözlüğü) `data/App.BackgroundWorkers.RecurringJobs.json`'dan gelir. Ayrıntı: `lowcode` §9.10, `README.md` §14. |
|
||
| **Menus › Module / Routes / Menu / Manager** | `App.Menus.Module` · `.Routes` · `.Menu` · `.Manager` (`/admin/menuManager`) | `Sas_H_Module` · `Sas_H_Route` · `Sas_H_Menu` | host | Menü ve route veritabanından gelir; üretilen ekranın menü kaydı buradan açılır. `Menu` ekranı ağaç düzeninin referansıdır. Seed: `data/App.Menus.{Routes,Module,Menu}.json` — `Routes` dosyasına yalnızca var olan satırın `Seo*` alanları için dokunulur. |
|
||
| **Developer Kit › SQL Query Manager** | `App.SqlQueryManager` · `/admin/sqlQueryManager` | `Sas_H_CrudEndpoint` (üretilen CRUD uçları) | — | View/procedure/function/tablo tasarımı ve çalıştırma, tablodan CRUD endpoint üretimi (`.CrudEndpoints` yetkisi); karar sırasının 2. adımı buradan başlar. |
|
||
| **Developer Kit › Files** | `App.Files` · `/admin/files` | Blob depolama | tenant | Dosya yöneticisi. Ekranın dosya alanı için ayrı depolama kurma; dosya/görsel editörleri ve Intranet Documents bu altyapıyı kullanır. |
|
||
| **Developer Kit › Custom Endpoints** | `App.DeveloperKit.CustomEndpoints` | `Sas_H_CustomEndpoint` | host | `Name`, `Url`, `Method`, `DataSourceCode`, `Sql`, `ParametersJson` (`Static`/`Query`/`Path`/`Body`), `PermissionsJson` (`Global`/`Role`/`User`) — parametreli SQL'i yetkili bir HTTP ucuna çevirir. |
|
||
| **Developer Kit › Dynamic Services** | `App.DeveloperKit.DynamicServices` | `Sas_H_DynamicService` | host | Liste ListForm ekranıdır; kod, toolbar/satır butonlarından açılan `DynamicServiceEditor` diyalogunda (Monaco) yazılıp derlenir ve yayınlanır (`.TestCompile`, `.Publish`, `.ViewCode`). SQL'in yetmediği iş kuralı için 3. adım. |
|
||
| **Developer Kit › Components** | `App.DeveloperKit.CustomComponents` | `Sas_H_CustomComponent` | host | Custom component listesi ve satırdaki **Design** butonuyla **Visual Designer** girişi (§10; `/admin/developerkit/components/design/:id`). Kayıtlar `data/App.DeveloperKit.CustomComponents/{Id}.json` klasörüne satır başına senkronlanır; public sayfalar ile üst/alt bilgi de buradadır. |
|
||
| **Developer Kit › ListForm** | `App.Listforms.Listform` | `Sas_H_ListForm` · `Sas_H_ListFormField` · `Sas_H_ListFormWorkflow` · `Sas_H_ListFormCustomization` · `Sas_H_ListFormImport` | host | Ekran tanımlarının kendisi. Bu dosyada anlatılan bütün JSON kolonlarının canlı hâli; düzenleyicisi `/admin/listform/edit/{kod}`. |
|
||
| **Developer Kit › Intranet Widgets** | `App.DeveloperKit.IntranetWidgets` | `Sas_T_IntranetWidget` | tenant | Intranet panosunda hangi widget'ın hangi kolonda (`Column`), hangi sırada (`Order`) ve hangi yetkiyle (`PermissionName`) çizileceği; `SourceType` `Builtin` (koddaki `Code`) ya da `Custom` (`ComponentName` ile bir custom component). Seed: `data/App.DeveloperKit.IntranetWidgets.json`. |
|
||
| **Developer Kit › MCP Servers** | `App.DeveloperKit.McpServers` | `Sas_H_McpServer` | host | `/mcp` ucunun kiracı bazlı sözleşmesi: `Name`, `Url`, `Tenants`, `AllowedTools` (boşsa tüm araçlar, doluysa yalnızca seçilenler), `MaxRows`. Yetkiler: ekran `App.DeveloperKit.McpServers`, erişim ve okuma `.Invoke`, her değişiklik `.Write` (kiracıda satır yazma, host'ta ayrıca tablo/ekran/bileşen geliştirme) — arkasındaki ekran C/U/D, Wizard ve Custom Components yetkileri ayrıca istenir. Kiracı veri okur ve yazar, geliştirme yapamaz (`TenantTools`: şema araçları, `query_list`, `run_select`, `insert_row`/`update_row`/`delete_row`); ham SQL `App.SqlQueryManager` ister; MCP yetki vermez. Kayıtlar `data/App.DeveloperKit.McpServers.json`'a senkronlanır. Ayrıntı: `README.md` §13.9. |
|
||
| **Developer Kit › Wizard Manager** | menü kodu `App.Listforms.WizardManager` · yetki `App.Listforms.Wizard` · `/admin/listform/wizardManager` | `configs/seeds/{kapsam}/wizard/*.json` | host | Wizard seed dosyalarının kart/liste görünümü: menü üst düğümü ve URL, **bağımlılıklar**, düzenleme, export (bağımlılık kapanışı) / import ve **silme** (`WizardRecordCleaner`: ekran, veri aynası ve izlenen kayıtları kaldırılır, başka ekran kullanıyorsa engellenir, sonuç raporlanır; onay diyaloğu ekranın tablosunu sorar, seçilirse `WizardTableCleaner` tabloyu scripti ve crud dosyasıyla düşürür — `lowcode` §4.5). Sihirbazın kendisi `/admin/listform/wizard`. |
|
||
| **Forum Management › Categories / Topics / Posts** | `App.ForumManagement.Categories` · `.Topics` · `.Posts` | `Sas_T_ForumCategory` · `Sas_T_ForumTopic` · `Sas_T_ForumPost` | tenant | Forumun yönetim tarafı: kategori (seed `data/App.ForumManagement.Categories.json`), konu (kategori lookup'ı, sayaçlar, sabitle/kilitle/çözüldü bayrakları), gönderi (konu lookup'ı, kabul edilen yanıt). Kullanıcı tarafı Administration'daki `/admin/forum`. |
|
||
|
||
> Menü kodu ile yetki adı **her zaman aynı değildir**: Wizard Manager'da kod
|
||
> `App.Listforms.WizardManager`, yetki `App.Listforms.Wizard`'dır; Administration'daki Forum
|
||
> ekranında kod `App.Forum`, yetki `App.ForumManagement.Publish`'tir. Org Chart'ta menü ve
|
||
> `/admin/organization` rotası aynı yetkiyi (`App.Hr.OrgChart`) ister. Yeni ürettiğin ekranlarda
|
||
> ikisini ayırma — wizard zaten aynı kökü kullanır (`lowcode` §2).
|
||
|
||
### 12.3 Administration menüsü
|
||
|
||
Kök menü `App.Administration`. Tabloların çoğu `Adm_T_*` — yani **kiracı başına** ayrışır; Identity
|
||
ekranları ABP tablolarıdır, Licence/Dev Request host tablolarını okur.
|
||
|
||
| Ekran | Kod / route | Tablo | Komponent üretirken ne işe yarar |
|
||
| --- | --- | --- | --- |
|
||
| **Definitions › Sector** | `App.Definitions.Sector` | `Adm_T_Sector` | Sektör lookup’ı. Veri `data/App.Definitions.Sector.json`'dan seed edilir. |
|
||
| **Definitions › Sequence** | `App.Definitions.Sequence` | `Adm_T_Sequence` | Belge numarası üretimi (`lowcode` §9.9); alan varsayılanında `CustomValueType: 5` ile bağlanır. Entity `IMultiTenant`'tır; ekran `IsTenant = true`, yetkiler `MultiTenancySide = Both` — her kiracı kendi numaratörlerini tutar. Seed `data/App.Definitions.Sequence.json`. |
|
||
| **Definitions › UoM Category** | `App.Definitions.UomCategory` (alt form `.Uom`) | `Adm_T_UomCategory` · `Adm_T_Uom` | Ölçü birimi, `Ratio`/`Rounding` — miktar alanı olan ekranlarda birim lookup'ı ve çevrim. Entity'ler `IMultiTenant`'tır; ekranlar `IsTenant = true`, yetkiler `MultiTenancySide = Both`. Seed `data/App.Definitions.{UomCategory,Uom}.json`. |
|
||
| **Licence** | `App.Licence` · `/admin/form/App.Licence` | `AbpTenants` + `V_Sas_H_OrderItem_ByTenantId` | **`ListFormType = Form`** (listesiz, tek kayıtlık ekran) + alt kalem listesi. "Tek kayıtlık kart ekran" isteğinin karşılığı budur. |
|
||
| **Dev Request** | `App.DevRequest` | `Sas_H_DevRequest` | Kiracı tarafındaki talep ekranı (Saas'taki listenin kullanıcı yüzü; `UserName` varsayılanı `@USERNAME`). |
|
||
| **Bildirimler › Bildirim Şablonları** | `App.Notifications.NotificationTemplates` | `Adm_T_NotificationTemplate` | Elle gönderimde seçilen mesaj metinleri: `Code`, `Name`, `Channel` (boş = tüm kanallar), `Subject`, `Body` (`{AdSoyad}`, `{KullaniciAdi}`, `{Eposta}`, `{Tarih}`, `{Saat}`, `{Kiraci}` yer tutucuları), `IsActive`. Boş bırakılan konu/gövde şablondan tamamlanır. Seed: `data/App.Notifications.NotificationTemplates.json`. |
|
||
| **Bildirimler › Bildirim Türleri / Kuralları** | `App.Notifications.NotificationTypes` · `.NotificationRules` | `Adm_T_NotificationType` · `Adm_T_NotificationRule` | Olay bazlı bildirim: tür + kanal + alıcı (`All`/`User`/`Role`/`OrganizationUnit`/`Custom`), `IsFixed` zorunlu kural. 8 kanal (`Sms`, `Mail`, `Rocket`, `Desktop`, `UiActivity`, `UiToast`, `WhatsApp`, `Telegram`); etiketleri `App.NotificationChannel.{Kanal}` dil anahtarlarıdır. Tür ve kural kiracıya aittir, yeni kiracıya varsayılan küme kopyalanır (`NotificationTenantDefaultsSeedContributor`). Kurallar ekranında `CreateNotification` diyaloğu da vardır. Ayrıntı: `lowcode` §9.11, `README.md` §13. |
|
||
| **Bildirimler › Bildirimler** | `App.Notifications.Notification` | `Adm_T_Notification` | Hem kuyruk günlüğü hem elle gönderim ekranı: liste kural motorunun ürettiklerini de gösterir, ekleme formu alıcı × kanal açılımını kuyruğa yazar (`InsertServiceAddress = list-form-dynamic-api/notification-insert`; `dxTagBox` çoklu alıcı/kanal). Tip her zaman `Manuel`, güncelleme kapalı. Ayrı bir manuel gönderim tablosu yoktur. Ayrıntı: `README.md` §13.5.1. |
|
||
| **Agenda** | `App.Agenda` | `Adm_T_Agenda` | **Takvim (Scheduler) düzeninin** referansı (`DefaultLayout: scheduler`): `StartDate`, `EndDate`, `AllDay`, `RecurrenceRule`, `RecurrenceException`. Tekrarlayan randevu isteği kod gerektirmez. |
|
||
| **Settings** | `App.Setting` · `/admin/settings` | — | `SettingDefinition` kayıtlarından üretilen ayar ekranı; değerler burada girilir. |
|
||
| **Intranet › Announcement** | `App.Intranet.Announcement` (alt formlar Like/Comment) | `Adm_T_Announcement` · `Adm_T_AnnouncementLike` · `Adm_T_AnnouncementComment` | Duyuru + beğeni + yorum: **ana kayıt / alt etkileşim** kalıbının hazır örneği. |
|
||
| **Intranet › Survey** | `App.Intranet.Survey` (alt form Question → Option; Response → Answer) | `Adm_T_Survey` · `Adm_T_SurveyQuestion` · `Adm_T_SurveyQuestionOption` · `Adm_T_SurveyResponse` · `Adm_T_SurveyAnswer` | Anket motoru; soru–seçenek–yanıt zinciri **iki seviyeli alt form** ihtiyacının referansıdır. |
|
||
| **Intranet › Social Post** | `App.Intranet.SocialPost` | `Adm_T_SocialPost` · `Adm_T_SocialComment` · `Adm_T_SocialLike` (+ `SocialPollOption`, `SocialMedia`, `SocialLocation`) | Kurum içi akış; `IsLiked`, `IsOwnPost` gibi hesaplanmış kolonların view içinde üretilmesine örnek. Alt formlar: `App.Intranet.SocialMedia`, `SocialComment`, `SocialLike` (`Id` → `SocialPostId`); anket seçenekleri (`App.Intranet.SocialPollOption`) medyaya bağlı olduğu için `SocialMedia` ekranının alt formudur (`Id` → `SocialMediaId`). |
|
||
| **Intranet › Event Type / Category / Event** | `App.Intranet.Events.EventType` · `.EventCategory` · `.Event` | `Adm_T_EventType` · `Adm_T_EventCategory` · `Adm_T_Event` · `Adm_T_EventPhoto` · `Adm_T_EventLike` · `Adm_T_EventComment` | Etkinlik yönetimi; foto ve katılımcı sayacı olan kayıt kalıbı. `EventLike`/`EventComment` alt formdur, `EventPhoto` menüde yer almaz; yetkileri `App.Intranet.Events.Event` altındadır. `Adm_T_EventPhoto` tablosu `sql/object/Adm_T_EventPhoto.sql` ile oluşturulur. |
|
||
| **Intranet › Documents** | `App.Intranet.Document` · `/admin/intranet-documents` | Dosya yöneticisi (`intranet` / `intranet\|_passive` klasörleri) | Kurum içi doküman paylaşımı — aktif/pasif klasör, yükleme, taşıma, toplu silme. Doküman listesi isteği yeni tablo gerektirmez. |
|
||
| **Restrictions › Work Hour** | `App.Restrictions.WorkHour` | `Adm_T_WorkHour` | Gün bazlı çalışma saati (`Monday`…`Sunday`, `StartTime`, `EndTime`); kullanıcıya `AbpUsers.WorkHour` ile bağlanır. "Sadece mesai saatinde girilebilsin" burada çözülür. |
|
||
| **Restrictions › IP Restrictions** | `App.Restrictions.IpRestrictions` | `Adm_T_IpRestriction` | `ResourceType` + `ResourceId` + `IP` — kullanıcı/rol bazlı IP kısıtı. |
|
||
| **Identity › Permission Groups / Permissions** | `Abp.Identity.PermissionGroups` · `Abp.Identity.Permissions` | `AbpPermissionGroups` · `AbpPermissions` | Yetki ağacı (tree düzeni). Yeni ekranın yetkileri burada görünür; `Modules` kolonu yetkiyi modüllere bağlar (pipe ile çoklu), `Order` kardeşler arası sıradır. Seed: `data/Abp.Identity.Permission{Groups,s}.json`. |
|
||
| **Identity › Claim Type** | `App.IdentityManagement.ClaimType` | `AbpClaimTypes` | Kullanıcıya ek alan (claim) tanımı: `ValueType`, `Regex`, `Required`, `IsStatic`. |
|
||
| **Identity › Roles** | `AbpIdentity.Roles` | `AbpRoles` | Rol yönetimi + `RolesPermission` diyaloğu; yeni ekranın yetkisi role buradan verilir. Yazma `list-form-dynamic-api/role-*`. |
|
||
| **Identity › Users** | `AbpIdentity.Users` · detay `/admin/users/detail/:userId` | `AbpUsers` | Kullanıcı yönetimi + `UsersPermission` diyaloğu, **KPI widget'ları** ve `list-form-dynamic-api/user-*` ile devredilen yazma. Kullanıcı `WorkHour`, `DepartmentId`, `JobPositionId`, `Gender` (`Male`/`Female`, `App.StaticLookup.*`) ve `HomeAddress` alanlarını liste ve formda taşır; kişisel ve kimlik bilgileri (`IdentityNumber`, `BirthDate`, `EducationLevel`, `Nationality`, `SskNo`…) detay ekranındadır. Detaydaki **Sağlık Kartı** sekmesi `BloodType` ile soy geçmişini (`{Mother,Father,Sibling,Child}HealthStatus` — `Alive`/`Deceased`, `App.StaticLookup.*` — ve `…HealthNote`) ve öz geçmişini (`ChronicDisease`, `TetanusVaccination`, `HepatitisVaccination`, `OtherVaccination`) taşır; sekme dört gruptur (Soy/Öz Geçmişi, Laboratuvar - Fizik Muayene `Lab*`/`Exam*`, Anamnez `Complaint*`/`Diagnosis*` + 3-10. sorular, Sonuç `FitForWork*`/`ShiftWorkFit`/`NightWorkFit`). Sonuçtaki hekim (`FitnessDoctorId`, `ShiftNightDoctorId`) wizard tablosu `Hr_T_Doctor`'dan `LookupQueryValues.TenantDoctorValues` ile seçilir; diploma ve işyeri hekimliği belgesi hekimden gösterilir, kullanıcıya yazılmaz. Bu alanların hepsi listede gizli alandır; arayüz `user-management/HealthCardTab.tsx`. Kullanıcı seçen her lookup bu bilgileri `AbpUsers`'tan okur ve kopya kolon aynı ad/tip/değer kümesiyle açılır (`lowcode.instructions.md` §0.12 madde 5). Yeni bir kullanıcı alanı = `PlatformConsts.AbpIdentity.User` + `AbpIdentityUserExtensions` + EF eşlemesi ve migration + `UserInfoViewModel` (detay/profil) + `CreateUpdateUserInput` ve `user-insert`/`user-update` (liste) + `ListFormSeeder_Administration` alanı. |
|
||
| **Identity › Users › Work Experience** | `App.IdentityManagement.UserWorkExperience` (menüsüz alt liste) | `Adm_T_UserWorkExperience` | Kullanıcının daha önce çalıştığı yerler: `CompanyName`, `SectorId` (Sektörler lookup'ı, `LookupQueryValues.TenantSectorValues`), `StartDate`, `EndDate`, `JobDescription` (HtmlEditor). Entity `IMultiTenant`; kullanıcı detayının Work sekmesinde `PlatformViewHost` ile `UserId` filtresiyle gömülüdür, yeni satır `UserId`'yi filtreden alır. Kendi yetkisi yoktur: okuma `AbpIdentity.Users`, ekleme/güncelleme/silme detay sayfasının yetkisi `AbpIdentity.Users.Update`. |
|
||
| **Identity › Users › Health Card lists** | `App.IdentityManagement.UserPeriodicExamination` · `.UserPatientProtocol` · `.UserSickLeave` (menüsüz alt listeler) | `Adm_T_UserPeriodicExamination` · `Adm_T_UserPatientProtocol` · `Adm_T_UserSickLeave` | Periyodik muayene (hekim `Hr_T_Doctor`'dan, diploma no seçimde `EditorScript.Copy` ile kopyalanır), hasta protokol defteri (`ProtocolType`/`ProtocolResult` statik lookup) ve istirahat listesi (`Days` tarihlerden `EditorScript.Days` ile hesaplanır). Entity'ler `IMultiTenant`; Sağlık Kartı sekmesinde (`HealthCardTab.tsx`) `UserId` filtresiyle gömülüdür. Yetki Work Experience ile aynıdır: okuma `AbpIdentity.Users`, ekleme/güncelleme/silme `AbpIdentity.Users.Update`. |
|
||
| **Identity › Organization Units** | `Abp.Identity.OrganizationUnits` · `/admin/ous` | ABP OU tabloları | Birim ağacı. Ekranı `IsOrganizationUnit = true` yaparsan veri bu ağaca göre süzülür; bildirim alıcısı da OU olabilir. |
|
||
| **Identity › Audit Logs** | `App.IdentityManagement.AuditLogs` | `AbpAuditLogs` | İstek denetim kaydı + `AuditLogDetail` diyaloğu. "Kim ne zaman ne yaptı" isteği yeni tablo gerektirmez. |
|
||
| **Identity › Sessions** | `App.IdentityManagement.Sessions` | `AbpSessions` | Açık oturumlar; `UiEvalService.ApiKickUser` ile oturum düşürme (`lowcode` §9.13). |
|
||
| **Reports › Categories / Templates** | `App.Reports.Categories` · `App.Reports.ReportTemplates` | `Adm_T_ReportCategory` · `Adm_T_ReportTemplate` | Kendi düzeni olan çıktılar (fatura, teklif); ekrana `CommandColumnJson` butonuyla bağlanır (`lowcode` §9.12). |
|
||
| **Videoroom** | `App.Videoroom` · `/admin/videoroom/dashboard` | `Adm_T_Videoroom` · `Adm_T_VideoroomParticipant` · `Adm_T_VideoroomAttandance` · `Adm_T_VideoroomChat` | Görüntülü oda, katılım ve sohbet kaydı. |
|
||
| **Forum** | menü kodu `App.Forum` · yetki `App.ForumManagement.Publish` · `/admin/forum` | `Sas_T_Forum*` | Forumun kullanıcı tarafı. |
|
||
|
||
Menüde görünmeyen ama route'u olan ekranlar: `/admin/dashboard`, `/admin/ai`,
|
||
`/admin/activityLog`, `/admin/changeLog`, `/admin/profile/{general,password,notification-settings}`,
|
||
`/admin/users/detail/:userId` (yetki `AbpIdentity.Users.Update`), `/admin/videoroom/list` ve
|
||
`/admin/videoroom/room/:id`, `/admin/reports/*`, `/admin/listform/{wizard,wizardManager}`,
|
||
`/admin/listform/edit/:listFormCode`, `/admin/developerkit/components/design/:id` ve dinamik ekran
|
||
rotaları. Custom component'lerin kendi `RoutePath`'leri (`/admin/roles`, `/admin/roles-list` gibi)
|
||
route tablosunda değil bileşen kaydındadır.
|
||
|
||
**Dinamik ekran rotaları** — üretilen her ListForm ekranı bunları kullanır, ayrıca route kaydı
|
||
açılmaz:
|
||
|
||
| Route | Bileşen | Ne açar |
|
||
| --- | --- | --- |
|
||
| `/admin/list/:listFormCode` | `views/list/List` | Liste (grid/card/pivot/tree/gantt/scheduler/todo — `LayoutJson`'a göre) |
|
||
| `/admin/form/:listFormCode` | `views/form/FormNew` | Yeni kayıt formu |
|
||
| `/admin/form/:listFormCode/:id` | `views/form/FormView` | Tek kayıt görüntüleme (`AllowDetail` bunu açar) |
|
||
| `/admin/form/:listFormCode/:id/edit` | `views/form/FormEdit` | Tek kayıt düzenleme |
|
||
| `/admin/chart/:listFormCode` | `views/list/Chart` | Yalnız grafik ekranı |
|
||
|
||
`/admin/pivot/...` diye bir route **yoktur**; pivot, liste ekranındaki bir görünümdür.
|
||
|
||
### 12.4 İK (Hr) menüsü
|
||
|
||
Kök menü `App.Hr` (`ModuleId = Hr`, `Order = 0`; Saas `-2` ve Administration `-1`'in yanında),
|
||
yetki grubu `App.Hr`. İK'ya ait her şey `Hr` ile başlar: tablo `Hr_{H|T}_*` (`MenuPrefix.Hr`),
|
||
ListForm kodu / menü kodu / yetki adı / dil anahtarı `App.Hr.*`, seed dosyası `data/App.Hr.*.json`,
|
||
seeder `ListFormSeeder_Hr.cs` (`SeedConsts.AppCodes.Hr`, `PlatformConsts.AppCodes.Hr`), entity
|
||
klasörü `Entities/Tenant/Hr/Definitions`. Tanımlar alt menüsü `App.Hr.Definitions`'tır
|
||
(`App.Platform.Definitions` başlığı); Organizasyon Şeması doğrudan `App.Hr` altındadır.
|
||
|
||
İK yetkilerinin `Modules` değeri `Sas|Hr`'dir: host (`Sas`) her zaman görür, kiracı yalnızca modül
|
||
listesinde `Hr` varsa görür (modül listesi boş kiracıda süzme yoktur — `MenuAppService`,
|
||
`RolesPermission.tsx`). Yetki ağacı: `App.Hr.Definitions` → `App.Hr.SkillType` (1),
|
||
`App.Hr.SkillLevel` (2), `App.Hr.Skill` (3), `App.Hr.Department` (4), `App.Hr.JobPosition` (5);
|
||
`App.Hr.OrgChart` grubun kökünde (2). ListForm ekranlarının alt yetkileri `.Create`, `.Update`,
|
||
`.Delete`, `.Export`, `.Import` (Skill Type'ta ayrıca `.Note`).
|
||
|
||
| Ekran | Kod / route | Tablo | Kapsam | Komponent üretirken ne işe yarar |
|
||
| --- | --- | --- | --- | --- |
|
||
| **Definitions › Skill Type** | `App.Hr.SkillType` (alt formlar `App.Hr.SkillLevel`, `App.Hr.Skill`) | `Hr_T_SkillType` · `Hr_T_SkillLevel` · `Hr_T_Skill` | tenant | Yetkinlik tanımı; bir ana ekrandan iki alt forma açılan **çoklu alt form** örneği. Seed `data/App.Hr.{SkillType,SkillLevel,Skill}.json`. |
|
||
| **Definitions › Department** | `App.Hr.Department` | `Hr_T_Department` | tenant | **Şube bazlı** departman ağacı: ilk sütun `BranchId` (Şube Adı; `LookupQueryValues.TenantBranchValues`, zorunlu), `ParentId` lookup'ı seçili şubenin departmanlarına süzülür (`BranchDepartmentValues`, cascade `BranchId`). `ParentId` ile **ağaç (TreeList) düzeninin** referansı; personel/onay ekranlarının departman lookup'ı. Tekil indeks `TenantId + BranchId + Name`. Seed `data/App.Hr.Department.json`. |
|
||
| **Definitions › Job Position** | `App.Hr.JobPosition` | `Hr_T_JobPosition` | tenant | Ünvan ağacı. Form sırası `BranchId` → `DepartmentId` (şubeye göre süzülür) → `Name` → `ParentId` (departmana göre süzülür); şube değişince departman ve üst görev temizlenir (`CascadeEmptyFields`). **İki kademeli cascade** örneği. Seed `data/App.Hr.JobPosition.json`. |
|
||
| **Org Chart** | `App.Hr.OrgChart` · `/admin/organization` | `Hr_T_Department` · `Hr_T_JobPosition` | tenant | Departman/ünvan verisinin organizasyon şeması görünümü (özel React sayfası `hr/OrgChart`, veri `api/app/org-chart`). Menü ve route aynı yetkiyi ister. |
|
||
|
||
**Şube bilgisi:** `Department.BranchId` ve `JobPosition.BranchId` (`Guid`, **zorunlu** — kolon `NOT NULL`, formda
|
||
zorunlu alan; değer `Sas_T_Branch.Id`) şubeyi taşır; ekranlar `IsBranch = false`'tur (satırlar kullanıcının şube atamasına göre süzülmez, şube
|
||
sütunu veridir). Host varsayılan şubesinin kimliği sabittir
|
||
(`PlatformConsts.Branches.BranchIdDefaultValue`; `PlatformIdentityDataSeeder` /
|
||
`TenantIdentityDataSeeder` host şubesi için bu kimliği kullanır, kiracı şubeleri yeni GUID alır);
|
||
seed edilen departman ve pozisyon satırları `BranchId` ile bu şubeye bağlanır. Yeni seed satırı
|
||
eklerken `BranchId` de yazılır.
|
||
|
||
### 12.5 ListForm olmayan (özel React) ekranlar
|
||
|
||
Bu ekranlar `Sas_H_Route` kayıtlarıyla yönetilir (seed:
|
||
`configs/seeds/host/data/App.Menus.Routes.json`). Yenisini eklemek **kod yazmak demektir** — karar
|
||
sırasının son adımıdır ve çerçeve dışıdır (onay ister, `lowcode` §0.8). Rotalı bir sayfa ihtiyacının
|
||
çerçeve içi karşılığı `RoutePath` taşıyan bir custom component'tir.
|
||
|
||
Bir route kaydının alanları: `Id`, `Key`, `Path`, `ComponentType`, `ComponentPath` (`@/views/...`),
|
||
`RouteType`, `Authority` (virgülle ayrılmış yetki listesi) ve SEO alanları `SeoTitle`,
|
||
`SeoDescription`, `SeoKeywords`, `SeoOgImage`, `SeoCanonicalUrl`, `SeoNoIndex`,
|
||
`SeoIncludeInSitemap`, `SeoChangeFrequency`, `SeoPriority`, `SeoStructuredData` (Custom Component
|
||
kaydı aynı `Seo*` kümesini taşır).
|
||
|
||
| `routeType` | Anlam |
|
||
| --- | --- |
|
||
| `public` | Oturum gerekmez — genel siteye açık sayfalar |
|
||
| `authenticated` | Kimlik akışı sayfaları (giriş, kayıt, parola, doğrulama) |
|
||
| `protected` | Oturum zorunlu; `authority` doluysa ayrıca yetki kontrolü yapılır |
|
||
|
||
`authority: []` **yetki kontrolü yok** demektir; ekranın kendi yetkisi varsa kontrol
|
||
bileşenin/ListForm'un içindedir. Custom component route'ları da böyle üretilir — bu yüzden
|
||
görünürlük `checkPermission` ile bileşen içinde kurulur (`lowcode` §7.5).
|
||
|
||
| Route | Bileşen | Yetki |
|
||
| --- | --- | --- |
|
||
| `/admin/menuManager` | `views/menu/MenuManager` | `App.Menus.Manager` |
|
||
| `/admin/listform/wizard` | `listForm/wizard/Wizard` | `App.Listforms.Wizard` |
|
||
| `/admin/listform/wizardManager` | `listForm/wizard/WizardFileManager` | `App.Listforms.Wizard` |
|
||
| `/admin/listform/edit/:listFormCode` | `listForm/edit/FormEdit` | `[]` — yetki ListForm tarafında |
|
||
| `/admin/sqlQueryManager` | `developerKit/SqlQueryManager` | `App.SqlQueryManager` |
|
||
| `/admin/developerkit/components/design/:id` | `ComponentCodeLayout` (liste tarafı ListForm ekranıdır) | `App.DeveloperKit.CustomComponents` |
|
||
| `/admin/reports/:report/{view,design}/:id?/:listFormCode?` | `DevexpressReportViewer` · `DevexpressReportDesigner` | — |
|
||
| `/admin/settings` | `settings/Settings` | `App.Setting` |
|
||
| `/admin/files` | `admin/files/FileManager` | `App.Files` |
|
||
| `/admin/intranet-documents` | `intranet/documents/IntranetDocuments` | `App.Intranet.Document` |
|
||
| `/admin/ous` · `/admin/organization` | `organization-unit/OrganizationUnits` · `hr/OrgChart` | `Abp.Identity.OrganizationUnits` · `App.Hr.OrgChart` (menü ile aynı — §12.4) |
|
||
| `/admin/forum` | `forum/Forum` | `App.ForumManagement.Publish` |
|
||
| `/admin/videoroom/{dashboard,list,room/:id}` | `admin/videoroom/{Dashboard,RoomList,RoomDetail}` | `App.Videoroom{,.List,.Detail}` |
|
||
| `/admin/ai` | `ai/Assistant` | `App.Definitions.AiBot.Asistant` |
|
||
| `/admin/dashboard` · `/admin/activityLog` · `/admin/changeLog` · `/admin/profile/*` | `Dashboard` · `admin/activityLog/ActivityLog` · `version/ChangeLog` · `admin/profile/Profile` | `[]` |
|
||
| `/admin/users/detail/:userId` | `admin/user-management/Details` | `AbpIdentity.Users.Update` |
|
||
|
||
**Oturum gerektirmeyen sayfalar** — genel site. `/home` · `/about` · `/contact` route tablosunda
|
||
**yoktur**: `/admin/` ile başlamayan `RoutePath`'li Custom Component otomatik public rota olur
|
||
(aynı yolu paylaşan fiziksel rotayı gölgeler). Bir "tanıtım sayfası" isteğinde yeni React sayfası
|
||
yazma; tasarımcıda yeni bir Custom Component + `Pub` menü kaydı (`App.Public.Header` altı) üret
|
||
(`README.md` §10.4). Üst ve alt bilgi rotasız bileşenlerdir (`PublicHeader`, `PublicFooter`,
|
||
`RoutePath = NULL`); public bileşenlerin hepsi tasarımcı belgesidir (`sourceMode: visual`).
|
||
|
||
| Route | Bileşen | Veri |
|
||
| --- | --- | --- |
|
||
| `/home` · `/about` · `/contact` | Custom Component (`PublicHomePage` · `PublicAboutPage` · `PublicContactPage`) | `data/App.DeveloperKit.CustomComponents/{Id}.json` · SEO bileşen kaydında |
|
||
| (rotasız) | Custom Component (`PublicHeader` · `PublicFooter`) | Üst menü + alt bilgi hızlı bağlantıları: `Pub` menüsü `App.Public.Header` (uygulama konfigürasyonunun `publicMenus` alanı) |
|
||
| `/products` · `/checkout` · `/payment` · `/success` | `views/public/{Products,Checkout,Payment,Success}` | `Sas_H_Product` · `Sas_H_PaymentMethod` · `Sas_H_InstallmentOption` · `Sas_H_Order` |
|
||
| `/blog` · `/blog/:id` | `views/public/{Blog,BlogDetail}` | `Sas_H_BlogPost` · `Sas_H_BlogCategory` |
|
||
| `/demo` | `views/public/Demo` | `Sas_H_Demo` |
|
||
| `/access-denied` | `views/AccessDenied` | — |
|
||
|
||
Ziyaretçiye açık her yolun SEO alanları ayrı bir tabloda değil, yolu tanımlayan kaydın
|
||
üzerindedir: `Route` satırının ya da Custom Component'in `Seo*` kolonları; genel varsayılanlar
|
||
`App.SiteManagement.Seo.*` ayarlarındadır. `sitemap.xml` `Pub` menülerini, aktif custom component
|
||
rotalarını ve yayınlanmış blog yazılarını toplar (`SeoAppService`). Yeni bir public yol üreten iş bu
|
||
alanları da doldurur (`lowcode` §0.9).
|
||
|
||
**Kimlik akışı** (`routeType: authenticated`): `/login`, `/register`, `/forgot-password`,
|
||
`/reset-password`, `/confirm`, `/confirm/:userId/:token`, `/extend-login` →
|
||
`views/auth/*`. Bunlara dokunma; parola ve doğrulama akışları ABP tarafındadır.
|
||
|
||
### 12.6 Talep → hangi menü
|
||
|
||
§0'daki katman taraması bu tabloyla eşleşir; "kod yazmamız gerekir" demeden önce buraya bak.
|
||
|
||
| Talepte geçen | Menü / ekran | Ne yapılır |
|
||
| --- | --- | --- |
|
||
| "numara otomatik gelsin" | Administration › Definitions › Sequence | Kayıt aç, alan varsayılanına `CustomValueType: 5` |
|
||
| "her gece / saat başı çalışsın" | Saas › Background Workers | `WorkerType: 2` + `BeforeSp`; prosedür `sql/object/` altına |
|
||
| "bilgilendirme gitsin" | Administration › Bildirimler (+ MailQueue §11) | Tür + kural (8 kanal); tablolu/ekli e-posta ise MailQueue |
|
||
| "elden bildirim/duyuru gönderelim" | Administration › Bildirimler › Bildirimler (+ Şablonlar) | Ekleme formu = elle gönderim; hazır metin için şablon kaydı |
|
||
| "onaya düşsün" | `WorkflowJson` + `ListFormWorkflow` (örnek: Sales Orders) | Onay düğümleri; `Inform` düğümü e-posta gönderir |
|
||
| "çıktısı alınsın / fatura basılsın" | Administration › Reports | Hazır `DynamicGrid` ya da `ReportTemplate` |
|
||
| "dosya eklensin" | Saas › Developer Kit › Files | Dosya/görsel editörü; ayrı depolama kurma |
|
||
| "fotoğraf çekilsin / barkod okutulsun / konum alınsın" | Alan editörü (§9.8 tablosu) · tasarımcıda `BarcodeScanField` | `Capture`, `@SCAN_BARCODE`, `BarcodeScanDialog`, `geoTo`; yeni editör yazma |
|
||
| "barkod/QR basılsın" | Visual Designer › `BarcodeViewer` | `value`'yu `Form` kolonuna bağla |
|
||
| "başka veritabanından gelsin" | Saas › Data Source | Yeni DataSource + ekranın `DataSourceCode` alanı |
|
||
| "ayarlanabilir olsun" | Saas › Setting Definitions | Tanım aç, değeri `/admin/settings`'ten yönet |
|
||
| "İngilizcesi de olsun" | Saas › Languages | Dil anahtarı + `data/App.Languages.LanguageText.json` |
|
||
| "aramada çıksın" | Saas › Definitions › Global Search | `System`/`Group`/`Term`/`Weight`/`Url` kaydı |
|
||
| "sadece şu rol görsün" | Administration › Identity › Roles / Permissions | Yetki kodu + ekranın `PermissionJson`'ı |
|
||
| "herkes yalnızca kendi kayıtlarını görsün" / "şu rol şu bölgeyi görsün" | ListForm editörü › Kişiselleştirme | `ServerWhere` kaydı (herkes/rol/kullanıcı; §2.5) ya da `DefaultFilter` |
|
||
| "intranet ana sayfasına kutu eklensin" | Saas › Developer Kit › Intranet Widgets | `Custom` kaynaklı widget + custom component |
|
||
| "şube bazlı olsun" | Saas › Branches | `IsBranch = true` |
|
||
| "birim ağacına göre süzülsün" | Administration › Identity › Organization Units | `IsOrganizationUnit = true` |
|
||
| "mesai dışında girilemesin" / "sadece ofis IP'si" | Administration › Restrictions | Work Hour · IP Restriction kaydı |
|
||
| "kim değiştirmiş görelim" | Administration › Identity › Audit Logs | Hazır ekran; kayıt notu için `ShowNote` |
|
||
| "menüye eklensin" | Saas › Menus › Manager | Menü kaydı + yetki + route eşlemesi |
|
||
| "yapay zekâ ajanı sorgulasın / veri çeksin" | Saas › DeveloperKit › MCP Servers | Kayıt aç, `AllowedTools`/tenant kapsamını ayarla; yeni endpoint/kod yok |
|
||
| "yapay zekâ ajanı ekran/bileşen geliştirsin" | Saas › DeveloperKit › MCP Servers | Yalnızca host kullanıcısı: `App.DeveloperKit.McpServers.Invoke` + `.Write` + Wizard / Custom Components yetkilerini ver; geliştirme araçları `AllowedTools` ile açılıp kapatılır. Kiracı MCP'de veri okur ve yazar, geliştirme yapamaz |
|
||
| "ülke/il/ilçe, para birimi, birim, sektör" | Saas / Administration › Definitions | Var olan tabloya lookup bağla, yenisini üretme |
|
||
| "departman, pozisyon/ünvan, yetkinlik, organizasyon şeması" | İK › Definitions · İK › Org Chart | Var olan `Hr_*` tablosuna lookup bağla (departman lookup'ı şubeye göre süzülebilir — `BranchDepartmentValues`); yenisini üretme |
|
||
| "yapay zekâ cevaplasın" | Saas › Definitions › AiBot | Bot tanımı; `/admin/ai` bu tanımı kullanır |
|
||
|
||
### 12.7 Canlı referans uygulamalar
|
||
|
||
İstenen davranışın bu uygulamada çalışan örneği. Tanımlar
|
||
`api/src/Sozsoft.Platform.DbMigrator/Migrations/ListFormSeeder_{Saas,Administration,Hr}.cs`
|
||
içinde ilgili `#region` altındadır.
|
||
|
||
| İhtiyaç | Bak |
|
||
| --- | --- |
|
||
| Ağaç (TreeList) | `Menu`, `Permission`, `Department`, `JobPosition` |
|
||
| Kanban / Todo | `DevRequests` (`TodoOptionJson` + `SortOrder`, `Priority`, `Tags`) |
|
||
| Takvim (Scheduler) | `Agenda` (`SchedulerOptionJson` + `RecurrenceRule`) |
|
||
| Tek kayıtlık form ekranı | `Licence` (`ListFormType = Form` + alt kalem listesi) |
|
||
| Onay akışı | `Sales Orders` — `WorkflowJson` (`ApprovalUserFieldName`, `ApprovalStatusFieldName`, `ApprovalDateFieldName`, `ApprovalDescriptionFieldName`) + `ListFormWorkflow` düğümleri (Start → Approval → End/End) |
|
||
| Alt form (master-detail) | `Tenant → Branches`, `Sales Orders → Sales Order Item`, `Survey → Question → Option` |
|
||
| KPI widget | Saas, Administration ve İK'daki yönetim ekranlarının çoğu (Users, Tenants, Dynamic Services, Custom Components, Audit Logs, Bildirimler, Duyuru/Anket/Etkinlik, Forum…; basit tanım listeleri hariç) — `WidgetsJson`; tek sorgu `UNION ALL` ile birden çok kart döndürür (`Title`, `Value`, `Color`, `SubTitle`, `Icon`) |
|
||
| Toolbar'dan diyalog açma | `Tenant` (`TenantsConnectionString`), `Role` (`RolesPermission`), `User` (`UsersPermission`), `Audit Logs` (`AuditLogDetail`), `Notification Rule` (`CreateNotification`), `Branches` (`BranchSeed`), `Sales Orders` (`CreateTenantFromOrderDialog`), `Dynamic Services` (`DynamicServiceEditor` — hem toolbar hem satır) |
|
||
| Yazmayı servise devretme | `Tenant`, `Role`, `User` — `*ServiceAddress = "list-form-dynamic-api/{tenant\|role\|user}-{insert\|update}"`; `Notification` — `notification-insert` (çoklu değer `MultiValueStringJsonConverter`) |
|
||
| Ekle düğmesini diyaloğa bağlama | `Dynamic Services` — `EditingOptionJson.AddDialogName = "DynamicServiceEditor"` |
|
||
| Satır butonundan servis silme | `Dynamic Services` — `UiEvalService.ApiDeleteDynamicService` |
|
||
| Toplam satırı | `Sales Order Item`, `Licence Item` (`TotalSummaryJson`) |
|
||
| View üzerinden okuma | `Background Worker Jobs`, `Licence Item` (`SelectCommandType = View`) |
|
||
| Cascade lookup | `City` → `District` (ülke/il/ilçe zinciri); `Job Position` (şube → departman → üst görev) |
|
||
| Alan varsayılanı ve soft delete | `Tenant` (`FormFieldsDefaultValueJson`, `DeleteFieldsDefaultValueJson`) |
|
||
|
||
### 12.8 Uyarılar
|
||
|
||
- **Bu ekranların seeder'ı idempotenttir:** `ListFormCode` zaten varsa kayıt **güncellenmez**.
|
||
Hazır bir ekranın davranışını değiştirmek gerekiyorsa seeder'ı düzenlemek yetmez; değişikliği
|
||
`sql/execute/{Ad}.sql` altında var olan kaydı güncelleyen bir prosedürle taşı.
|
||
- **Host tablosuna kiracı verisi yazma.** `Sas_H_*` tabloları bütün kiracılar için ortaktır;
|
||
kiracıya özel veri `*_T_*` tablosuna gider. Ekranın `IsTenant`/`IsBranch` bayrakları ile
|
||
tablonun kapsam harfi tutarlı olmalıdır.
|
||
- **Yetki adı menüden gelir.** Ekranın `PermissionJson`'ındaki adlarla menünün
|
||
`RequiredPermissionName` değeri aynı sözleşmeyi göstermelidir; farklıysa kullanıcı menüyü görür,
|
||
ekranı göremez.
|
||
- **Platformun hazır tablolarına doğrudan yazan ekran üretme.** `AbpUsers`, `AbpRoles`,
|
||
`AbpTenants` yazma işi `list-form-dynamic-api` uçlarındadır; ham SQL ile yazmak parola
|
||
hash'ini, yetki önbelleğini ve kiracı kurulumunu atlar.
|
||
|
||
---
|
||
|
||
## 13. Bu dosyanın kapsamadıkları
|
||
|
||
| Konu | Nerede |
|
||
| --- | --- |
|
||
| Karar sırası, üretim protokolü, seed sözleşmesi | `lowcode.instructions.md` §0–§2 |
|
||
| Wizard seed dosyasının alanları | `lowcode.instructions.md` §4 |
|
||
| `EditorScript` tarifleri ve runtime API | `lowcode.instructions.md` §5 |
|
||
| `EditorOptions` sözlüğü ve preset'ler | `lowcode.instructions.md` §6 |
|
||
| Visual Designer doküman şeması ve event script'leri | `lowcode.instructions.md` §7 |
|
||
| SQL nesneleri, CRUD/Custom Endpoint, Dynamic Service | `lowcode.instructions.md` §8–§9 |
|
||
| Sequence, zamanlanmış iş, bildirim, rapor ekranları | `lowcode.instructions.md` §9.9–§9.14 |
|
||
| `api/` kod standardı | `dotnet.instructions.md` |
|
||
|
||
DevExtreme'in burada listelenmeyen bir seçeneğini kullanman gerekiyorsa, **nereye yazdığın
|
||
belirleyicidir**:
|
||
|
||
| Nereye | Bilinmeyen anahtara ne olur |
|
||
| --- | --- |
|
||
| Ekran seviyesindeki `*Json` kolonları (§2–§8) | **Düşer.** `GridOptionsDto` ham metni `[JsonIgnore]` ile gizler, istemciye yalnızca tipli DTO gider. Kalıcı olarak gerekiyorsa önce ilgili DTO'ya alan eklenir, sonra bu dosya güncellenir |
|
||
| Alan seviyesindeki `ListFormField.EditorOptions` (§9.8) | **Geçer.** Ham metin olarak istemciye iner ve editöre olduğu gibi verilir; sözlükte olmayan anahtar Options Builder'ın "Sözlük dışı ayarlar" bölümünden de yazılabilir (`lowcode` §6.1) |
|
||
| `CustomJsSourcesJson` / `CustomStyleSourcesJson` (§5.5) | Geçer — ama son çaredir, denetlenmez |
|
||
|
||
Yani "DevExtreme'de var, platformda yok" durumunda önce §9.8'e (editör seçeneği mi?) bak; ekran
|
||
seviyesindeki bir seçenekse DTO'ya eklenmeden çalışmayacağını bilerek planla.
|